1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650 |
- /* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * Oct-2001 door32.sys/socket modifications by Rob Swindell (www.synchro.net)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- *
- * File: ODEdit.c
- *
- * Description: Implementation of the OpenDoors multi-line editor, which
- * allows the user to edit strings which may span many lines.
- * Provides standard text editor features, such as word wrap.
- *
- * Revisions: Date Ver Who Change
- * ---------------------------------------------------------------
- * Dec 07, 1995 6.00 BP Created.
- * Dec 12, 1995 6.00 BP Added entry, exit and kernel macros.
- * Dec 30, 1995 6.00 BP Added ODCALL for calling convention.
- * Jan 04, 1996 6.00 BP Use od_get_input().
- * Jan 12, 1996 6.00 BP Claim exclusive use of arrow keys.
- * Jan 31, 1996 6.00 BP Added timeout for od_get_input().
- * Feb 08, 1996 6.00 BP Finished implementation details.
- * Feb 13, 1996 6.00 BP Added od_get_input() flags parameter.
- * Feb 16, 1996 6.00 BP New trans. size estimation heuristics.
- * Feb 19, 1996 6.00 BP Changed version number to 6.00.
- * Feb 24, 1996 6.00 BP Fixed garbage on [Enter] after w-wrap.
- * Mar 03, 1996 6.10 BP Begin version 6.10.
- * Mar 13, 1996 6.10 BP Restore cursor position after menu.
- * Mar 19, 1996 6.10 BP MSVC15 source-level compatibility.
- * Jun 08, 1996 6.10 BP Added cast in call to alloc function.
- * Oct 19, 2001 6.20 RS Eliminated MSVC 6.0 warning.
- * Aug 10, 2003 6.23 SH *nix support
- */
- #define BUILDING_OPENDOORS
- #include <string.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include "OpenDoor.h"
- #include "ODTypes.h"
- #include "ODGen.h"
- #include "ODCore.h"
- #include "ODKrnl.h"
- #include "ODStat.h"
- #include "ODCom.h"
- #include "ODScrn.h"
- /* ========================================================================= */
- /* Misc. definitions. */
- /* ========================================================================= */
- /* Macros used by this module. */
- #define IS_EOL_CHAR(ch) ((ch) == '\n' || (ch) == '\r' || (ch) == '\0')
- /* Configurable constants. */
- #define LINE_ARRAY_GROW_SIZE 20
- #define BUFFER_GROW_SIZE 4096
- #define ANSI_SCROLL_DISTANCE 7
- #define PRE_DRAIN_TIME 10000
- #define MAX_TAB_STOP_SIZE 8
- #define DEFAULT_TAB_STOP_SIZE 8
- #define DEFAULT_LINE_BREAK "\n"
- /* Other manifest constants. */
- #define REDRAW_NO_BOUNDARY 0xffff
- /* Default editor options. */
- static tODEditOptions ODEditOptionsDefault =
- {
- 1, 1, 80, 23,
- FORMAT_PARAGRAPH_BREAKS,
- NULL,
- NULL,
- EFLAG_NORMAL,
- };
- /* ========================================================================= */
- /* Multiline editor instance structure. */
- /* ========================================================================= */
- typedef struct
- {
- char *pszEditBuffer;
- UINT unBufferSize;
- tODEditOptions *pUserOptions;
- UINT unCurrentLine;
- UINT unCurrentColumn;
- UINT unLineScrolledToTop;
- UINT unAreaWidth;
- UINT unAreaHeight;
- char **papchStartOfLine;
- UINT unLineArraySize;
- UINT unLinesInBuffer;
- BOOL bInsertMode;
- UINT unTabStopSize;
- UINT unScrollDistance;
- char *pszLineBreak;
- char *pszParagraphBreak;
- BOOL bWordWrapLongLines;
- void *pRememberBuffer;
- } tEditInstance;
- /* ========================================================================= */
- /* Editor function prototypes. */
- /* ========================================================================= */
- /* High level implementation. */
- static BOOL ODEditSetupInstance(tEditInstance *pEditInstance,
- char *pszBufferToEdit, UINT unBufferSize, tODEditOptions *pUserOptions);
- static void ODEditRedrawArea(tEditInstance *pEditInstance);
- static void ODEditDrawAreaLine(tEditInstance *pEditInstance,
- UINT unAreaLineToDraw);
- static INT ODEditMainLoop(tEditInstance *pEditInstance);
- static void ODEditGotoPreviousLine(tEditInstance *pEditInstance);
- static void ODEditGotoNextLine(tEditInstance *pEditInstance);
- static BOOL ODEditScrollArea(tEditInstance *pEditInstance, INT nDistance);
- static BOOL ODEditRecommendFullRedraw(tEditInstance *pEditInstance,
- UINT unEstPartialRedrawBytes, BOOL bDefault);
- static UINT ODEditEstDrawBytes(tEditInstance *pEditInstance,
- UINT unStartRedrawLine, UINT unStartRedrawColumn, UINT unFinishRedrawLine,
- UINT unFinishRedrawColumn);
- static UINT ODEditGetCurrentLineInArea(tEditInstance *pEditInstance);
- static void ODEditUpdateCursorPos(tEditInstance *pEditInstance);
- static void ODEditUpdateCursorIfMoved(tEditInstance *pEditInstance);
- static tODResult ODEditEnterText(tEditInstance *pEditInstance,
- char *pszEntered, BOOL bInsertMode);
- static void ODEditSetBreakSequence(tEditInstance *pEditInstance,
- char chFirstEOLChar, char chSecondEOLChar);
- static BOOL ODEditCursorLeft(tEditInstance *pEditInstance);
- static void ODEditDeleteCurrentChar(tEditInstance *pEditInstance);
- static void ODEditDeleteCurrentLine(tEditInstance *pEditInstance);
- static BOOL ODEditPastEndOfCurLine(tEditInstance *pEditInstance);
- static size_t ODEditRememberBufferSize(tEditInstance *pEditInstance);
- static void ODEditRememberArea(tEditInstance *pEditInstance,
- void *pRememberedArea);
- static void ODEditRedrawChanged(tEditInstance *pEditInstance,
- void *pRememberedArea, UINT unUpperBoundary, UINT unLowerBoundary);
- static BOOL ODEditDetermineChanged(tEditInstance *pEditInstance,
- void *pRememberedArea, UINT unUpperBoundary, UINT unLowerBoundary,
- UINT *punStartRedrawLine, UINT *punStartRedrawColumn,
- UINT *punFinishRedrawLine, UINT *punFinishRedrawColumn);
- static void ODEditRedrawSubArea(tEditInstance *pEditInstance,
- UINT unStartRedrawLine, UINT unStartRedrawColumn, UINT unFinishRedrawLine,
- UINT unFinishRedrawColumn);
- static void ODEditGetActualCurPos(tEditInstance *pEditInstance,
- UINT *punRow, UINT *punColumn);
- static BOOL ODEditIsEOLForMode(tEditInstance *pEditInstance, char chToTest);
- /* Low level buffer manipulation functions. */
- static BOOL ODEditBufferFormatAndIndex(tEditInstance *pEditInstance);
- static UINT ODEditBufferGetLineLength(tEditInstance *pEditInstance,
- UINT unBufferLine);
- static UINT ODEditBufferGetTotalLines(tEditInstance *pEditInstance);
- static char *ODEditBufferGetCharacter(tEditInstance *pEditInstance,
- UINT unBufferLine, UINT unBufferColumn);
- static tODResult ODEditBufferMakeSpace(tEditInstance *pEditInstance,
- UINT unLine, UINT unColumn, UINT unNumChars);
- static tODResult ODEditTryToGrow(tEditInstance *pEditInstance,
- UINT unSizeNeeded);
- /* ========================================================================= */
- /* High level editor implementation. */
- /* ========================================================================= */
- /* ----------------------------------------------------------------------------
- * od_multiline_edit()
- *
- * Multiline editor function, allows the user to enter or change text that
- * spans multiple lines.
- *
- * Parameters: pszBufferToEdit - Pointer to '\0'-terminated buffer of text
- * to edit.
- *
- * unBufferSize - Size of the buffer, in characters.
- *
- * pEditOptions - Pointer to a tODEditOptions structure, or
- * NULL to use default settings.
- *
- * Return: An od_multiline_edit()-specific result code.
- */
- ODAPIDEF INT ODCALL od_multiline_edit(char *pszBufferToEdit, UINT unBufferSize,
- tODEditOptions *pEditOptions)
- {
- tEditInstance EditInstance;
- INT nToReturn;
- /* Log function entry if running in trace mode */
- TRACE(TRACE_API, "od_node_open()");
- /* Initialize OpenDoors if not already done. */
- if(!bODInitialized) od_init();
- OD_API_ENTRY();
- /* Validate parameters. */
- if(pszBufferToEdit == NULL || unBufferSize == 0)
- {
- od_control.od_error = ERR_PARAMETER;
- OD_API_EXIT();
- return(OD_MULTIEDIT_ERROR);
- }
- /* Check the user's terminal supports the required capabilities. */
- if(!(od_control.user_ansi || od_control.user_avatar))
- {
- od_control.od_error = ERR_NOGRAPHICS;
- OD_API_EXIT();
- return(OD_MULTIEDIT_ERROR);
- }
- /* Initialize editor instance information structure. */
- if(!ODEditSetupInstance(&EditInstance, pszBufferToEdit, unBufferSize,
- pEditOptions))
- {
- OD_API_EXIT();
- return(OD_MULTIEDIT_ERROR);
- }
- /* Attempt to build the buffer line index and ensure that the buffer */
- /* conforms to the format specified by the client application. */
- if(!ODEditBufferFormatAndIndex(&EditInstance))
- {
- od_control.od_error = ERR_MEMORY;
- OD_API_EXIT();
- return(OD_MULTIEDIT_ERROR);
- }
- /* Claim exclusive use of arrow keys. */
- ODStatStartArrowUse();
- /* Ensure that all information in the outbound communications buffer */
- /* has been sent before starting. This way, we can safely purge the */
- /* outbound buffer at any time without loosing anything that was sent */
- /* before od_multiline_edit() was called. */
- ODWaitDrain(PRE_DRAIN_TIME);
- /* Draw the initial edit area. */
- ODEditRedrawArea(&EditInstance);
- /* Run the main editor loop. */
- nToReturn = ODEditMainLoop(&EditInstance);
- /* Release exclusive use of arrow keys. */
- ODStatEndArrowUse();
- /* Set final information which will be available in the user options */
- /* structure for the client application to access. */
- EditInstance.pUserOptions->pszFinalBuffer = EditInstance.pszEditBuffer;
- EditInstance.pUserOptions->unFinalBufferSize = unBufferSize;
- OD_API_EXIT();
- return(nToReturn);
- }
- /* ----------------------------------------------------------------------------
- * ODEditSetupInstance() *** PRIVATE FUNCTION ***
- *
- * Initializes editor instance information structure.
- *
- * Parameters: pEditInstance - Editor instance information structure.
- *
- * pszBufferToEdit - Buffer pointer provided by client.
- *
- * unBufferSize - Initial buffer size, as specified by the
- * client.
- *
- * pUserOptions - Editor options specified by the client.
- *
- * Return: TRUE on success, FALSE on failure. In the case of failure,
- * od_control.od_error is set appropriately.
- */
- static BOOL ODEditSetupInstance(tEditInstance *pEditInstance,
- char *pszBufferToEdit, UINT unBufferSize, tODEditOptions *pUserOptions)
- {
- ASSERT(pEditInstance != NULL);
- ASSERT(pszBufferToEdit != NULL);
- /* Setup editor instance structure. */
- pEditInstance->pszEditBuffer = pszBufferToEdit;
- pEditInstance->unBufferSize = unBufferSize;
- if(pUserOptions == NULL)
- {
- /* Edit options is just the defaults. */
- pEditInstance->pUserOptions = &ODEditOptionsDefault;
- }
- else
- {
- /* Edit options are supplied by the user. */
- pEditInstance->pUserOptions = pUserOptions;
- /* Initialize any edit options that the user did not setup. */
- /* Check that edit area has been initialized. */
- if(pUserOptions->nAreaLeft == 0)
- {
- pUserOptions->nAreaLeft = ODEditOptionsDefault.nAreaLeft;
- }
- if(pUserOptions->nAreaRight == 0)
- {
- pUserOptions->nAreaRight = ODEditOptionsDefault.nAreaRight;
- }
- if(pUserOptions->nAreaTop == 0)
- {
- pUserOptions->nAreaTop = ODEditOptionsDefault.nAreaTop;
- }
- if(pUserOptions->nAreaBottom == 0)
- {
- pUserOptions->nAreaBottom = ODEditOptionsDefault.nAreaBottom;
- }
- }
- pEditInstance->unCurrentLine = 0;
- pEditInstance->unCurrentColumn = 0;
- pEditInstance->unLineScrolledToTop = 0;
- pEditInstance->papchStartOfLine = NULL;
- pEditInstance->unLineArraySize = 0;
- pEditInstance->unLinesInBuffer = 0;
- pEditInstance->unAreaWidth = (UINT)pEditInstance->pUserOptions->
- nAreaRight - (UINT)pEditInstance->pUserOptions->nAreaLeft + 1;
- pEditInstance->unAreaHeight = (UINT)pEditInstance->pUserOptions->
- nAreaBottom - (UINT)pEditInstance->pUserOptions->nAreaTop + 1;
- pEditInstance->bInsertMode = TRUE;
- pEditInstance->unTabStopSize = DEFAULT_TAB_STOP_SIZE;
- /* Setup line break and paragraph break sequences, if they can be */
- /* determined at this point. If they can't be determined, set them */
- /* to NULL. */
- switch(pEditInstance->pUserOptions->TextFormat)
- {
- case FORMAT_FTSC_MESSAGE:
- /* FTSC compliant messages use \r as a paragraph break, and do */
- /* not have any line break characters. */
- pEditInstance->pszLineBreak = "";
- pEditInstance->pszParagraphBreak = "\r";
- break;
- case FORMAT_PARAGRAPH_BREAKS:
- /* Paragraph break mode only inserts CR/LF sequences at the end */
- /* of a paragrah, and word-wraps the text that forms a paragrah. */
- pEditInstance->pszLineBreak = "";
- pEditInstance->pszParagraphBreak = NULL;
- break;
- case FORMAT_LINE_BREAKS:
- case FORMAT_NO_WORDWRAP:
- /* Line break mode and no word wrap mode both terminate every */
- /* line of the file with a CR/LF sequence, and have no paragrah */
- /* terminator. In line break mode, word wrap is enabled, whereas */
- /* it is not in FORMAT_NO_WORDWRAP mode. */
- pEditInstance->pszLineBreak = NULL;
- pEditInstance->pszParagraphBreak = "";
- break;
- default:
- /* An invalid text format was specified. */
- od_control.od_error = ERR_PARAMETER;
- return(FALSE);
- }
- /* Determine whether long lines sould be word wrapped or character */
- /* wrapped. */
- pEditInstance->bWordWrapLongLines = (pEditInstance->pUserOptions->TextFormat
- != FORMAT_NO_WORDWRAP);
- /* Attempt to allocate abuffer for remembered data. */
- pEditInstance->pRememberBuffer =
- malloc(ODEditRememberBufferSize(pEditInstance));
-
- if(pEditInstance->pRememberBuffer == NULL)
- {
- od_control.od_error = ERR_MEMORY;
- return(FALSE);
- }
- /* If AVATAR mode or local mode is active, then scroll up or down one */
- /* line at a time. */
- if(od_control.user_avatar || od_control.baud == 0)
- {
- pEditInstance->unScrollDistance = 1;
- }
- /* In ANSI mode with a remote connection, scroll multiple lines at a */
- /* time. This is the minimum of the default scroll distance, and the */
- /* current height of the edit area - 1. */
- else
- {
- pEditInstance->unScrollDistance = MIN(ANSI_SCROLL_DISTANCE,
- pEditInstance->pUserOptions->nAreaBottom
- - pEditInstance->pUserOptions->nAreaTop);
- }
- /* Return with success. */
- return(TRUE);
- }
- /* ----------------------------------------------------------------------------
- * ODEditRedrawArea() *** PRIVATE FUNCTION ***
- *
- * Redraws the area of the screen used by the editor.
- *
- * Parameters: pEditInstance - Editor instance information structure.
- *
- * Return: void
- */
- static void ODEditRedrawArea(tEditInstance *pEditInstance)
- {
- UINT unAreaLine;
- ASSERT(pEditInstance != NULL);
- ODScrnEnableCaret(FALSE);
- /* First, remove anything that is still in the outbound communications */
- /* buffer, since whatever it was, it will no longer be visible after */
- /* the screen redraw anyhow. */
- if(od_control.baud != 0) ODComClearOutbound(hSerialPort);
- /* Loop, drawing every line in the edit area. */
- for(unAreaLine = 0; unAreaLine < pEditInstance->unAreaHeight; ++unAreaLine)
- {
- ODEditDrawAreaLine(pEditInstance, unAreaLine);
- }
- ODScrnEnableCaret(TRUE);
- }
- /* ----------------------------------------------------------------------------
- * ODEditDrawAreaLine() *** PRIVATE FUNCTION ***
- *
- * Redraws the specified line in the area of the screen used by the editor.
- *
- * Parameters: pEditInstance - Editor instance information structure.
- *
- * unAreaLineToDraw - 0-based line number in the edit area to be
- * redrawn.
- *
- * Return: void
- */
- static void ODEditDrawAreaLine(tEditInstance *pEditInstance,
- UINT unAreaLineToDraw)
- {
- UINT unBufferLine;
- UINT unLineLength;
- ASSERT(pEditInstance != NULL);
- ASSERT(unAreaLineToDraw >= 0);
- ASSERT(unAreaLineToDraw < pEditInstance->unAreaHeight);
- /* Determine the buffer line that is displayed on this screen line. */
- unBufferLine = unAreaLineToDraw + pEditInstance->unLineScrolledToTop;
- /* Position the cursor to the beginning of this line. */
- od_set_cursor((UINT)pEditInstance->pUserOptions->nAreaTop
- + unAreaLineToDraw, (UINT)pEditInstance->pUserOptions->nAreaLeft);
- /* If this line is not beyond the end of the buffer. */
- if(unBufferLine < pEditInstance->unLinesInBuffer)
- {
- /* Determine the length of this buffer line. */
- unLineLength = ODEditBufferGetLineLength(pEditInstance, unBufferLine);
- od_disp(ODEditBufferGetCharacter(pEditInstance, unBufferLine, 0),
- unLineLength, TRUE);
- }
- else
- {
- unLineLength = 0;
- }
- /* If right edge of edit area aligns with the right edge of the screen. */
- if(pEditInstance->pUserOptions->nAreaRight == OD_SCREEN_WIDTH)
- {
- /* Clear the remainder of this line on the screen. */
- od_clr_line();
- }
- else
- {
- /* Place spaces after the end of the current line, up to right edge of */
- /* the edit area. */
- od_repeat(' ', (BYTE)(pEditInstance->unAreaWidth - unLineLength));
- }
- }
- /* ----------------------------------------------------------------------------
- * ODEditMainLoop() *** PRIVATE FUNCTION ***
- *
- * Implements the main editor loop, which repeatedly waits for input from the
- * user, until the user chooses to exit.
- *
- * Parameters: pEditInstance - Editor instance information structure.
- *
- * Return: Value to be returned by od_multiline_edit.
- */
- static INT ODEditMainLoop(tEditInstance *pEditInstance)
- {
- tODInputEvent InputEvent;
- ASSERT(pEditInstance != NULL);
- /* Set initial cursor position. */
- ODEditUpdateCursorPos(pEditInstance);
- /* Loop, obtaining keystrokes until the user chooses to exit. */
- for(;;)
- {
- od_get_input(&InputEvent, OD_NO_TIMEOUT, GETIN_NORMAL);
- if(InputEvent.EventType == EVENT_EXTENDED_KEY)
- {
- switch(InputEvent.chKeyPress)
- {
- case OD_KEY_UP:
- /* If we aren't at the start of the file, then move to the */
- /* previous line. */
- if(pEditInstance->unCurrentLine > 0)
- {
- ODEditGotoPreviousLine(pEditInstance);
- ODEditUpdateCursorPos(pEditInstance);
- }
- break;
- case OD_KEY_DOWN:
- /* If we aren't at the end of the file, then move to the */
- /* next line. */
- if(pEditInstance->unCurrentLine
- < ODEditBufferGetTotalLines(pEditInstance) - 1)
- {
- ODEditGotoNextLine(pEditInstance);
- ODEditUpdateCursorPos(pEditInstance);
- }
- break;
- case OD_KEY_LEFT:
- /* Attempt to move the cursor left. */
- if(ODEditCursorLeft(pEditInstance))
- {
- /* If it was possible to move the cursor, then update the */
- /* cursor position on the screen. */
- ODEditUpdateCursorPos(pEditInstance);
- }
- break;
- case OD_KEY_RIGHT:
- /* In word wrap mode, we allow the cursor to move up to the */
- /* end of this line, and then wrap around to the next line. */
- if(pEditInstance->bWordWrapLongLines)
- {
- if(pEditInstance->unCurrentColumn < ODEditBufferGetLineLength
- (pEditInstance, pEditInstance->unCurrentLine))
- {
- ++pEditInstance->unCurrentColumn;
- ODEditUpdateCursorPos(pEditInstance);
- }
- else if(pEditInstance->unCurrentLine
- < ODEditBufferGetTotalLines(pEditInstance) - 1)
- {
- ODEditGotoNextLine(pEditInstance);
- pEditInstance->unCurrentColumn = 0;
- ODEditUpdateCursorPos(pEditInstance);
- }
- }
- /* In character wrap mode, we allow the cursor to move up to */
- /* the right edge of the edit area. */
- else
- {
- if(pEditInstance->unCurrentColumn
- < pEditInstance->unAreaWidth - 1)
- {
- ++pEditInstance->unCurrentColumn;
- ODEditUpdateCursorPos(pEditInstance);
- }
- }
- break;
- case OD_KEY_HOME:
- pEditInstance->unCurrentColumn = 0;
- ODEditUpdateCursorPos(pEditInstance);
- break;
- case OD_KEY_END:
- pEditInstance->unCurrentColumn = ODEditBufferGetLineLength(
- pEditInstance, pEditInstance->unCurrentLine);
- ODEditUpdateCursorPos(pEditInstance);
- break;
- case OD_KEY_PGUP:
- if(pEditInstance->unLineScrolledToTop > 0)
- {
- UINT unDistance = MIN(pEditInstance->unAreaHeight - 1,
- pEditInstance->unLineScrolledToTop);
- ODEditScrollArea(pEditInstance, -((INT)unDistance));
- pEditInstance->unCurrentLine -= unDistance;
- ODEditUpdateCursorPos(pEditInstance);
- }
- else if(pEditInstance->unCurrentLine != 0)
- {
- pEditInstance->unCurrentLine = 0;
- ODEditUpdateCursorPos(pEditInstance);
- }
- break;
- case OD_KEY_PGDN:
- if(pEditInstance->unLineScrolledToTop <
- pEditInstance->unLinesInBuffer - 1)
- {
- UINT unDistance = MIN(pEditInstance->unAreaHeight - 1,
- pEditInstance->unLinesInBuffer
- - pEditInstance->unLineScrolledToTop - 1);
- ODEditScrollArea(pEditInstance, (INT)unDistance);
- pEditInstance->unCurrentLine = MIN(
- pEditInstance->unCurrentLine + unDistance,
- pEditInstance->unLinesInBuffer - 1);
- ODEditUpdateCursorPos(pEditInstance);
- }
- break;
- case OD_KEY_INSERT:
- /* If the insert key is pressed, then toggle insert mode. */
- pEditInstance->bInsertMode = !pEditInstance->bInsertMode;
- break;
- case OD_KEY_DELETE:
- /* Delete the character at the current position. */
-
- /* If we are currently past the end of this line. */
- if(ODEditPastEndOfCurLine(pEditInstance))
- {
- /* Add spaces to this line to fill it up to the current */
- /* cursor position. */
- switch(ODEditBufferMakeSpace(pEditInstance,
- pEditInstance->unCurrentLine,
- pEditInstance->unCurrentColumn, 0))
- {
- case kODRCUnrecoverableFailure:
- /* If we encountered an unrecoverable failure, then */
- /* exit from the editor with a memory allocation */
- /* error. */
- od_control.od_error = ERR_MEMORY;
- return(OD_MULTIEDIT_ERROR);
- case kODRCSuccess:
- /* On success, delete the current character. */
- ODEditDeleteCurrentChar(pEditInstance);
- break;
- default:
- /* On any other failure, just beep and continue. */
- od_putch('\a');
- }
- }
- else
- {
- /* If we aren't pas the end of the line, then just do a */
- /* simple delete character operation. */
- ODEditDeleteCurrentChar(pEditInstance);
- }
- break;
- }
- }
- else if(InputEvent.EventType == EVENT_CHARACTER)
- {
- if(InputEvent.chKeyPress == 25)
- {
- /* Control-Y (delete line) has been pressed. */
- ODEditDeleteCurrentLine(pEditInstance);
- }
- else if(InputEvent.chKeyPress == 26
- || InputEvent.chKeyPress == 27)
- {
- /* Escape or control-Z has been pressed. */
- /* If a menu callback function has been provided by */
- /* the client, then call it. */
- if(pEditInstance->pUserOptions->pfMenuCallback != NULL)
- {
- /* Call the menu callback function. */
- switch((*pEditInstance->pUserOptions->pfMenuCallback)(NULL))
- {
- case EDIT_MENU_EXIT_EDITOR:
- return(OD_MULTIEDIT_SUCCESS);
- case EDIT_MENU_DO_NOTHING:
- /* Continue in the editor without doing anything. */
- break;
- default:
- ASSERT(FALSE);
- }
- /* If we are continuing, then restore initial cursor pos. */
- ODEditUpdateCursorPos(pEditInstance);
- }
- else
- {
- /* If a menu key callback function has not been provided, */
- /* then we exit the editor unconditionally. */
- return(OD_MULTIEDIT_SUCCESS);
- }
- }
- else if(InputEvent.chKeyPress == '\b')
- {
- /* Backspace key has been pressed. */
- /* If the cursor is past the end of the line, then we just move */
- /* the cursor left, without deleting any characters. */
- BOOL bDelete = !ODEditPastEndOfCurLine(pEditInstance);
- /* Backup the cursor one space. */
- if(ODEditCursorLeft(pEditInstance))
- {
- /* If there was space to move the cursor back to, then */
- /* proceed and remove the character at the current position. */
- if(bDelete)
- {
- ODEditDeleteCurrentChar(pEditInstance);
- }
- else
- {
- /* In this case, we must still show the new cursor */
- /* position. */
- ODEditUpdateCursorPos(pEditInstance);
- }
- }
- }
- else if(InputEvent.chKeyPress == '\t')
- {
- char szTextToAdd[MAX_TAB_STOP_SIZE + 1];
- UINT unTargetColumn;
- UINT unTargetDistance;
- /* A tab key has been entered. */
- /* Determine the column that this will move the cursor to. */
- ASSERT(pEditInstance->unTabStopSize <= MAX_TAB_STOP_SIZE);
- unTargetColumn = ((pEditInstance->unCurrentColumn / pEditInstance->
- unTabStopSize) + 1) * pEditInstance->unTabStopSize;
- /* In insert mode, then insert spaces into the buffer. */
- if(pEditInstance->bInsertMode)
- {
- /* Determine the number of columns that we need to advance in */
- /* order to reach this target column. */
- unTargetDistance = unTargetColumn -
- pEditInstance->unCurrentColumn;
- ASSERT(unTargetDistance <= MAX_TAB_STOP_SIZE);
- /* Translate this to a string with the appropriate number of */
- /* spaces. */
- memset(szTextToAdd, ' ', unTargetDistance);
- szTextToAdd[unTargetDistance] = '\0';
- /* Add this to the buffer. */
- if(ODEditEnterText(pEditInstance, szTextToAdd, TRUE) ==
- kODRCUnrecoverableFailure)
- {
- od_control.od_error = ERR_MEMORY;
- return(OD_MULTIEDIT_ERROR);
- }
- }
- /* In overwrite mode, then just advance the cursor position. */
- else
- {
- /* Determine the column where the cursor should be wrapped. */
- UINT unWrapColumn = pEditInstance->bWordWrapLongLines ?
- ODEditBufferGetLineLength(pEditInstance,
- pEditInstance->unCurrentLine)
- : pEditInstance->unAreaWidth;
- if(unTargetColumn < unWrapColumn)
- {
- pEditInstance->unCurrentColumn = unTargetColumn;
- ODEditUpdateCursorPos(pEditInstance);
- }
- else if(pEditInstance->unCurrentLine
- < ODEditBufferGetTotalLines(pEditInstance) - 1)
- {
- ODEditGotoNextLine(pEditInstance);
- pEditInstance->unCurrentColumn = 0;
- ODEditUpdateCursorPos(pEditInstance);
- }
- }
- }
- else if(InputEvent.chKeyPress == '\r')
- {
- char *pszTextToAdd;
- /* The enter key has been pressed. In insert mode, or at the end */
- /* of the buffer in overwrite mode, this adds a new line. */
- if(pEditInstance->bInsertMode || pEditInstance->unCurrentLine
- >= ODEditBufferGetTotalLines(pEditInstance) - 1)
- {
- if(!pEditInstance->bInsertMode)
- {
- /* If we are not in insert mode, begin by positioning the */
- /* cursor at the end of this line. */
- pEditInstance->unCurrentColumn = ODEditBufferGetLineLength(
- pEditInstance, pEditInstance->unCurrentLine);
- }
- /* Determine the line/paragraph break sequence to use. */
- if(pEditInstance->pszLineBreak != NULL
- && strlen(pEditInstance->pszLineBreak) > 0)
- {
- pszTextToAdd = pEditInstance->pszLineBreak;
- }
- else if(pEditInstance->pszParagraphBreak != NULL
- && strlen(pEditInstance->pszParagraphBreak) > 0)
- {
- pszTextToAdd = pEditInstance->pszParagraphBreak;
- }
- else
- {
- pszTextToAdd = DEFAULT_LINE_BREAK;
- }
- /* Insert the sequence into the buffer. */
- if(ODEditEnterText(pEditInstance, pszTextToAdd, TRUE) ==
- kODRCUnrecoverableFailure)
- {
- od_control.od_error = ERR_MEMORY;
- return(OD_MULTIEDIT_ERROR);
- }
- }
- else
- {
- /* Pressing the enter key in overwrite mode just moves the */
- /* cursor to the beginning of the next line. In other words, */
- /* it is equivalent to pressing Down arrow followed by home. */
- ODEditGotoNextLine(pEditInstance);
- pEditInstance->unCurrentColumn = 0;
- ODEditUpdateCursorPos(pEditInstance);
- }
- }
- else if(InputEvent.chKeyPress >= 32)
- {
- char szTextToAdd[2];
- szTextToAdd[0] = InputEvent.chKeyPress;
- szTextToAdd[1] = '\0';
- /* A valid buffer character has been entered. */
- if(ODEditEnterText(pEditInstance, szTextToAdd,
- (BOOL)(pEditInstance->bInsertMode
- || ODEditPastEndOfCurLine(pEditInstance)))
- == kODRCUnrecoverableFailure)
- {
- od_control.od_error = ERR_MEMORY;
- return(OD_MULTIEDIT_ERROR);
- }
- }
- }
- }
- }
- /* ----------------------------------------------------------------------------
- * ODEditGotoPreviousLine() *** PRIVATE FUNCTION ***
- *
- * Moves the current cursor position to the previous line, scrolling the screen
- * if necessary to keep the cursor visible.
- *
- * Parameters: pEditInstance - Editor instance information structure.
- *
- * Return: void
- */
- static void ODEditGotoPreviousLine(tEditInstance *pEditInstance)
- {
- ASSERT(pEditInstance != NULL);
- /* If we are already at the first line, then return without doing */
- /* anything. */
- if(pEditInstance->unCurrentLine == 0) return;
- /* If cursor is at top of edit area, then scroll area */
- /* first. */
- if(ODEditGetCurrentLineInArea(pEditInstance) == 0)
- {
- ODEditScrollArea(pEditInstance,
- -(INT)(MIN(pEditInstance->unScrollDistance,
- pEditInstance->unCurrentLine)));
- }
- /* Move cursor to previous line. */
- --pEditInstance->unCurrentLine;
- }
- /* ----------------------------------------------------------------------------
- * ODEditGotoNextLine() *** PRIVATE FUNCTION ***
- *
- * Advances the current cursor position to the next line, scrolling the screen
- * if necessary to keep the cursor visible.
- *
- * Parameters: pEditInstance - Editor instance information structure.
- *
- * Return: void
- */
- static void ODEditGotoNextLine(tEditInstance *pEditInstance)
- {
- ASSERT(pEditInstance != NULL);
- /* If we are already at the end of the file, then return without */
- /* doing anything. */
- if(pEditInstance->unCurrentLine
- >= ODEditBufferGetTotalLines(pEditInstance) - 1)
- {
- return;
- }
- /* If cursor is at the bottom of the edit area, then scroll area first. */
- if(ODEditGetCurrentLineInArea(pEditInstance)
- == pEditInstance->unAreaHeight - 1)
- {
- ODEditScrollArea(pEditInstance,
- (INT)MIN(pEditInstance->unScrollDistance,
- ODEditBufferGetTotalLines(pEditInstance)
- - pEditInstance->unCurrentLine));
- }
- /* Move cursor to next line. */
- ++pEditInstance->unCurrentLine;
- }
- /* ----------------------------------------------------------------------------
- * ODEditScrollArea() *** PRIVATE FUNCTION ***
- *
- * Scrolls the edit area up or down the specified distance, redrawing newly
- * "exposed" lines.
- *
- * Parameters: pEditInstance - Editor instance information structure.
- *
- * nDistance - Number of lines to scroll, where a positive
- * value moves the text upwards, and a negative
- * value moves the text down.
- *
- * Return: FALSE if a full redraw has been performed, TRUE if an efficient
- * scroll command has been used.
- */
- static BOOL ODEditScrollArea(tEditInstance *pEditInstance, INT nDistance)
- {
- BOOL bUseScrollCommand = FALSE;
- UINT unAreaLine;
- UINT unBufferLine;
- UINT unFirstAreaLineToDraw;
- UINT unLastAreaLineToDraw;
- UINT unPositiveDistance;
- ASSERT(pEditInstance);
- /* If scroll distance is zero, then we don't need to do anything at all. */
- if(nDistance == 0)
- {
- return(TRUE);
- }
- /* Otherwise, obtain the absolute value of the distance as an unsigned */
- /* integer. */
- else if(nDistance < 0)
- {
- unPositiveDistance = (UINT)-nDistance;
- }
- else
- {
- unPositiveDistance = (UINT)nDistance;
- }
- /* In AVATAR mode, if more than one of the currently visible lines will */
- /* still be visible after scrolling, then we will consider using the */
- /* scroll operation. */
- if(od_control.user_avatar
- && ((INT)pEditInstance->unAreaHeight) - ((INT)unPositiveDistance) > 1)
- {
- /* Even under this situation, we only want to use the scroll operation */
- /* if the amount of data still in the outbound buffer + our estimate */
- /* of the amount of data that will be sent to perform the scroll */
- /* operation is less than our estimate of the amount of data that */
- /* would be sent by a complete screen redraw. */
- UINT unEstimatedScrollData = ((pEditInstance->unAreaWidth + 4) *
- unPositiveDistance) + 7;
- if(!ODEditRecommendFullRedraw(pEditInstance, unEstimatedScrollData,
- TRUE))
- {
- bUseScrollCommand = TRUE;
- }
- }
- /* In local mode, we can also use the scroll command for efficiency. */
- if(od_control.baud == 0)
- {
- bUseScrollCommand = TRUE;
- }
- /* Area scroll is achieved by one of two means. We either use the scroll */
- /* command, and then draw just the newly visible lines, or we redraw the */
- /* entire edit area, after removing any data from the outbound */
- /* communications buffer. */
- if(bUseScrollCommand)
- {
- /* Use the od_scroll() function to scroll the screen contents. */
- od_scroll(pEditInstance->pUserOptions->nAreaLeft,
- pEditInstance->pUserOptions->nAreaTop,
- pEditInstance->pUserOptions->nAreaRight,
- pEditInstance->pUserOptions->nAreaBottom,
- nDistance, SCROLL_NO_CLEAR);
- /* Fill the newly visible lines. First, the portion of the area that */
- /* requires redrawing is determined, and then a loop redraws the lines */
- /* that must be drawn. */
- /* If we are moving text upwards, exposing new lines at the bottom of */
- /* the area: */
- if(nDistance > 0)
- {
- ASSERT(pEditInstance->unLineScrolledToTop + unPositiveDistance
- < pEditInstance->unLinesInBuffer);
- pEditInstance->unLineScrolledToTop += unPositiveDistance;
- unFirstAreaLineToDraw = pEditInstance->unAreaHeight
- - (UINT)unPositiveDistance;
- unLastAreaLineToDraw = pEditInstance->unAreaHeight - 1;
- }
- /* Otherwise, we have moved text downwards, exposing new lines at the */
- /* top of the edit area. */
- else
- {
- ASSERT(pEditInstance->unLineScrolledToTop >= unPositiveDistance);
- pEditInstance->unLineScrolledToTop -= unPositiveDistance;
- unFirstAreaLineToDraw = 0;
- unLastAreaLineToDraw = unPositiveDistance - 1;
- }
- ODScrnEnableCaret(FALSE);
- /* Now, redraw the new lines. */
- unBufferLine = unFirstAreaLineToDraw
- + pEditInstance->unLineScrolledToTop;
- for(unAreaLine = unFirstAreaLineToDraw; unAreaLine <=
- unLastAreaLineToDraw; ++unAreaLine, ++unBufferLine)
- {
- /* Draw the entire line. */
- ODEditDrawAreaLine(pEditInstance, unAreaLine);
- }
- ODScrnEnableCaret(TRUE);
- }
- /* Just redraw the entire edit area. */
- else
- {
- /* Adjust the line number that is scrolled to the top of the screen. */
- if(nDistance > 0)
- {
- pEditInstance->unLineScrolledToTop += unPositiveDistance;
- }
- else
- {
- pEditInstance->unLineScrolledToTop -= unPositiveDistance;
- }
- /* Perform redraw, first purging outbound buffer. */
- ODEditRedrawArea(pEditInstance);
- }
- return(bUseScrollCommand);
- }
- /* ----------------------------------------------------------------------------
- * ODEditRecommendFullRedraw() *** PRIVATE FUNCTION ***
- *
- * Determines whether it would be more efficient to add the specified number
- * of bytes to the outbound buffer as part of an incremental redraw, or if
- * it would be more efficient to just purge the outbound buffer and do a
- * complete redraw of the edit area.
- *
- * Parameters: pEditInstance - Editor instance information structure.
- *
- * unEstPartialRedrawBytes - Estimate of the number of bytes that
- * would be transmitted if an incremental
- * redraw is performed.
- *
- * bDefault - The default action (TRUE for full
- * redraw, FALSE for incremental) if the
- * number of bytes in the outbound buffer
- * cannot be determined.
- *
- * Return: TRUE if a full redraw is recommended, FALSE if an the
- * incremental redraw is recommended.
- */
- static BOOL ODEditRecommendFullRedraw(tEditInstance *pEditInstance,
- UINT unEstPartialRedrawBytes, BOOL bDefault)
- {
- int nOutboundBufferBytes;
- UINT unEstFullRedrawBytes;
- /* In local mode, just return the default action. */
- if(od_control.baud == 0)
- {
- return(bDefault);
- }
- /* Attempt to obtain the number of bytes in the communications outbound */
- /* buffer. Unfortunately, this information may not be available. For */
- /* example, FOSSIL drivers will only report whether or not there is */
- /* still data in the outbound buffer, but not a count of the number of */
- /* bytes in the buffer. Under such a situation, ODComOutbound() returns */
- /* SIZE_NON_ZERO if there is data in the buffer, and 0 if there is no */
- /* data in the buffer. This is not a problem under OpenDoor's internal */
- /* serial I/O code, nor is it a problem under Win32's communications */
- /* facilities. */
- ODComOutbound(hSerialPort, &nOutboundBufferBytes);
- if(nOutboundBufferBytes == SIZE_NON_ZERO)
- {
- /* We know that there is data in the outbound buffer, but we don't */
- /* know how much, and so we cannot make a recommendation. Instead, */
- /* the default course of action will be taken. */
- return(bDefault);
- }
- /* Estimate the # of bytes required for a full redraw of the edit area. */
- unEstFullRedrawBytes = ODEditEstDrawBytes(pEditInstance, 0,
- 0, pEditInstance->unAreaHeight - 1, pEditInstance->unAreaWidth);
- /* Recommend a full redraw if the number of bytes for an incremental */
- /* redraw plus the number of bytes already in the outbound buffer */
- /* exceed the number of bytes required for a full redraw. */
- if(unEstPartialRedrawBytes + (UINT)nOutboundBufferBytes
- > unEstFullRedrawBytes)
- {
- return(TRUE);
- }
- else
- {
- return(FALSE);
- }
- }
- /* ----------------------------------------------------------------------------
- * ODEditEstDrawBytes() *** PRIVATE FUNCTION ***
- *
- * Estimates the number of bytes which will be transmitted in order to redraw
- * the specified portion of the edit area.
- *
- * Parameters: pEditInstance - Editor instance information structure.
- *
- * unStartRedrawLine - Line of first character to draw.
- *
- * unStartRedrawColumn - Column of first character to draw.
- *
- * unFinishRedrawLine - Line of last character to draw.
- *
- * unFinishRedrawColumn - Column after last character to draw.
- *
- * Return: A rough estimate of the number of bytes required for the redraw.
- */
- static UINT ODEditEstDrawBytes(tEditInstance *pEditInstance,
- UINT unStartRedrawLine, UINT unStartRedrawColumn, UINT unFinishRedrawLine,
- UINT unFinishRedrawColumn)
- {
- UINT unAreaLine;
- UINT unBufferLine;
- UINT unLineLength;
- UINT unByteTally = 0;
- /* If we are only drawing text on a single line, then estimate is just */
- /* the distance between the start and finish redraw column. This number */
- /* is precise only if the cursor is already at the location where */
- /* output is to begin, and the final cursor position is the location */
- /* where output finishes. This is in fact the situation when the user */
- /* is entering new text in the middle of the line - the most common */
- /* situation that will be encountered. */
- if(unStartRedrawLine == unFinishRedrawLine)
- {
- return(unFinishRedrawColumn - unStartRedrawColumn);
- }
- /* If we are drawing text on multiple lines, then inspect the contents */
- /* of those lines to estimate the number of bytes to be transmitted. */
- for(unAreaLine = unStartRedrawLine,
- unBufferLine = pEditInstance->unLineScrolledToTop + unStartRedrawLine;
- unAreaLine <= unFinishRedrawLine;
- ++unAreaLine, ++unBufferLine)
- {
- /* Determine the length of this line. */
- if(unBufferLine < pEditInstance->unLinesInBuffer)
- {
- unLineLength = ODEditBufferGetLineLength(pEditInstance, unBufferLine);
- if(unAreaLine == unStartRedrawLine)
- {
- unLineLength -= unStartRedrawColumn;
- }
- }
- else
- {
- unLineLength = 0;
- }
- /* Add the number of characters on this line, along with the number of */
- /* bytes required to reposition the cursor and to clear the unused */
- /* portion of this line to the tally. This assumes that the edit area */
- /* spans the entire screen. */
- unByteTally += unLineLength + 7;
- }
- return(unByteTally);
- }
- /* ----------------------------------------------------------------------------
- * ODEditGetCurrentLineInArea() *** PRIVATE FUNCTION ***
- *
- * Determines which line of the edit area the cursor is currently located in.
- *
- * Parameters: pEditInstance - Editor instance information structure.
- *
- * Return: 0-based index of the distance from the top of the edit area
- * (as specified in the user options structure) where the
- * cursor is currently located.
- */
- static UINT ODEditGetCurrentLineInArea(tEditInstance *pEditInstance)
- {
- ASSERT(pEditInstance != NULL);
- return(pEditInstance->unCurrentLine - pEditInstance->unLineScrolledToTop);
- }
- /* ----------------------------------------------------------------------------
- * ODEditUpdateCursorPos() *** PRIVATE FUNCTION ***
- *
- * Unconditionally updates the position of the cursor on the screen to
- * reflect its actual position. Compare with ODEditUpdateCursorIfMoved().
- *
- * Parameters: pEditInstance - Editor instance information structure.
- *
- * Return: void
- */
- static void ODEditUpdateCursorPos(tEditInstance *pEditInstance)
- {
- ASSERT(pEditInstance != NULL);
- /* Reposition the cursor on the screen. */
- od_set_cursor(ODEditGetCurrentLineInArea(pEditInstance)
- + pEditInstance->pUserOptions->nAreaTop,
- pEditInstance->unCurrentColumn + pEditInstance->pUserOptions->nAreaLeft);
- }
- /* ----------------------------------------------------------------------------
- * ODEditUpdateCursorIfMoved() *** PRIVATE FUNCTION ***
- *
- * Updates the position of the cursor on the screen to reflec its actual
- * position only if we belive it isn't already there. Compare with
- * ODEditUpdateCursorPos().
- *
- * Parameters: pEditInstance - Editor instance information structure.
- *
- * Return: void
- */
- static void ODEditUpdateCursorIfMoved(tEditInstance *pEditInstance)
- {
- UINT unActualRow;
- UINT unActualColumn;
- ODEditGetActualCurPos(pEditInstance, &unActualRow, &unActualColumn);
- if(!(unActualRow == ODEditGetCurrentLineInArea(pEditInstance)
- + pEditInstance->pUserOptions->nAreaTop
- && unActualColumn == pEditInstance->unCurrentColumn
- + pEditInstance->pUserOptions->nAreaLeft))
- {
- ODEditUpdateCursorPos(pEditInstance);
- }
- }
- /* ----------------------------------------------------------------------------
- * ODEditEnterText() *** PRIVATE FUNCTION ***
- *
- * Inserts new text at the current cursor position, updating the cursor
- * position accordingly.
- *
- * Parameters: pEditInstance - Editor instance information structure.
- *
- * pszEntered - The character(s) to be inserted.
- *
- * Return: kODRCSuccess on success, kODRCSafeFailure if we were unable to
- * obtain enough buffer space before making any changes, or
- * kODRCUnrecoverableFailure if the buffer has been changed, but
- * there was insufficient memory to re-index the buffer.
- */
- static tODResult ODEditEnterText(tEditInstance *pEditInstance,
- char *pszEntered, BOOL bInsertMode)
- {
- UINT unNumCharsToAdd;
- char *pch;
- tODResult Result;
- ASSERT(pEditInstance != NULL);
- ASSERT(pszEntered != NULL);
- /* Remember initial edit area contents, to permit selective redraw. */
- ODEditRememberArea(pEditInstance, pEditInstance->pRememberBuffer);
- /* Determine the number of characters that are to be added to the buffer. */
- unNumCharsToAdd = strlen(pszEntered);
- /* Make room in the buffer for the new characters, if needed. */
- if(bInsertMode)
- {
- Result = ODEditBufferMakeSpace(pEditInstance,
- pEditInstance->unCurrentLine, pEditInstance->unCurrentColumn,
- unNumCharsToAdd);
- if(Result != kODRCSuccess)
- {
- /* Beep on failure. */
- od_putch('\a');
- return(Result);
- }
- }
- /* Copy the new characters to the buffer. */
- pch = ODEditBufferGetCharacter(pEditInstance,
- pEditInstance->unCurrentLine, pEditInstance->unCurrentColumn);
- memcpy(pch, pszEntered, unNumCharsToAdd);
- /* Move the cursor position to the end of the newly added text. The */
- /* cursor position may be temporarily assigned to a position that is */
- /* past the end of the edit area or past the end of the buffer. */
- for(pch = pszEntered; *pch != '\0'; ++pch)
- {
- if(IS_EOL_CHAR(*pch))
- {
- /* A carriage return character advances the cursor to the */
- /* leftmost column on the next line. */
- pEditInstance->unCurrentColumn = 0;
- pEditInstance->unCurrentLine++;
- /* If the next character is a different EOL character, and is */
- /* not the end of the string, then skip that character. */
- if(IS_EOL_CHAR(pch[1]) && pch[1] != '\0' && pch[1] != *pch)
- {
- ++pch;
- }
- }
- else
- {
- /* All other characters move the cursor ahead one column. */
- pEditInstance->unCurrentColumn++;
- }
- }
- /* Reindex and reformat the buffer based on its new contents. */
- if(!ODEditBufferFormatAndIndex(pEditInstance))
- {
- return(kODRCUnrecoverableFailure);
- }
- /* Check whether the cursor is now positioned past the end of the edit */
- /* area, requiring the edit area to be scrolled up. */
- if(ODEditGetCurrentLineInArea(pEditInstance)
- >= pEditInstance->unAreaHeight)
- {
- /* We need to scroll the area accordingly. */
- /* Distance to scroll is maximum of the current single-step scroll */
- /* distance, and the distance that the cursor is positioned below */
- /* the bottom of the current edit area. */
- UINT unScrollDistance = MAX(pEditInstance->unScrollDistance,
- ODEditGetCurrentLineInArea(pEditInstance) -
- pEditInstance->unAreaHeight + 1);
- /* Perform actual scroll operation. */
- if(ODEditScrollArea(pEditInstance, (INT)unScrollDistance))
- {
- /* Entire area wasn't redrawn by operation, so some redrawing */
- /* may still be required, within the area of text that was */
- /* visible before the scroll operation. */
- ODEditRedrawChanged(pEditInstance, pEditInstance->pRememberBuffer,
- 0, pEditInstance->unAreaHeight - unScrollDistance);
- }
- }
- /* Perform necessary redrawing and reposition the cursor if needed. */
- ODEditRedrawChanged(pEditInstance, pEditInstance->pRememberBuffer,
- REDRAW_NO_BOUNDARY, REDRAW_NO_BOUNDARY);
- /* Return with success. */
- return(kODRCSuccess);
- }
- /* ----------------------------------------------------------------------------
- * ODEditSetBreakSequence() *** PRIVATE FUNCTION ***
- *
- * If the default line or paragraph break sequence has not yet been set, then
- * this function sets it based on the break sequence that was encountered in
- * the buffer supplied by the client application.
- *
- * Parameters: pEditInstance - Editor instance information structure.
- *
- * chFirstEOLChar - First character in the encountered sequence.
- *
- * chSecondEOLChar - Second character in the encountered sequence.
- *
- * Return: void
- */
- static void ODEditSetBreakSequence(tEditInstance *pEditInstance,
- char chFirstEOLChar, char chSecondEOLChar)
- {
- char *pszSequence;
- ASSERT(pEditInstance != NULL);
- if(pEditInstance->pszParagraphBreak != NULL
- && pEditInstance->pszLineBreak != NULL)
- {
- /* In this situation, both the default line break sequence and default */
- /* paragraph break sequence have been set, so there is nothing for us */
- /* to do. */
- return;
- }
- /* Obtain a pointer to the encountered sequence. We want to use a static */
- /* string constant for this, so that the string will continue to exist, */
- /* in unchanged form. */
- if(chFirstEOLChar == '\r' && chSecondEOLChar == '\0')
- {
- pszSequence = "\r";
- }
- else if(chFirstEOLChar == '\n' && chSecondEOLChar == '\0')
- {
- pszSequence = "\n";
- }
- else if(chFirstEOLChar == '\n' && chSecondEOLChar == '\r')
- {
- pszSequence = "\n\r";
- }
- else if(chFirstEOLChar == '\r' && chSecondEOLChar == '\n')
- {
- pszSequence = "\r\n";
- }
- else
- {
- /* This should never happen: an invalid end of line sequence was */
- /* passed in. */
- pszSequence = NULL;
- ASSERT(FALSE);
- }
- /* Set the as yet undetermined line/paragraph terminators. */
- if(pEditInstance->pszParagraphBreak == NULL)
- {
- pEditInstance->pszParagraphBreak = pszSequence;
- }
- if(pEditInstance->pszLineBreak == NULL)
- {
- pEditInstance->pszLineBreak = pszSequence;
- }
- }
- /* ----------------------------------------------------------------------------
- * ODEditCursorLeft() *** PRIVATE FUNCTION ***
- *
- * Attempts to move the cursor left. Called when the user presses the left
- * arrow key, and is also called as part of the process of handling the
- * backspace key.
- *
- * Parameters: pEditInstance - Editor instance information structure.
- *
- * Return: TRUE on success, or FALSE if the cursor cannot be moved left any
- * further.
- */
- static BOOL ODEditCursorLeft(tEditInstance *pEditInstance)
- {
- ASSERT(pEditInstance != NULL);
- /* In word wrap mode, pressing the left key when the cursor */
- /* is past the end of the line jumps the cursor to the end */
- /* of the line. */
- if(pEditInstance->bWordWrapLongLines &&
- pEditInstance->unCurrentColumn > ODEditBufferGetLineLength
- (pEditInstance, pEditInstance->unCurrentLine))
- {
- pEditInstance->unCurrentColumn = ODEditBufferGetLineLength
- (pEditInstance, pEditInstance->unCurrentLine);
- return(TRUE);
- }
- /* If we are not already at the leftmost column. */
- else if(pEditInstance->unCurrentColumn > 0)
- {
- /* Move left one column. */
- --pEditInstance->unCurrentColumn;
- return(TRUE);
- }
- else if(pEditInstance->bWordWrapLongLines)
- {
- /* In word wrap mode, this will move us up to the end of */
- /* the previous line. */
- if(pEditInstance->unCurrentLine > 0)
- {
- ODEditGotoPreviousLine(pEditInstance);
- pEditInstance->unCurrentColumn = ODEditBufferGetLineLength(
- pEditInstance, pEditInstance->unCurrentLine);
- return(TRUE);
- }
- }
- /* It wasn't possible to move the cursor. */
- return(FALSE);
- }
- /* ----------------------------------------------------------------------------
- * ODEditDeleteCurrentChar() *** PRIVATE FUNCTION ***
- *
- * Deletes the character at the current cursor position, performing necessary
- * redraw. Pressing the delete key causes just this function to be called.
- * Pressing the backspace key causes ODEditCursorLeft() to be called to first
- * move the cursor left before calling ODEditDeleteCurrentChar().
- *
- * Parameters: pEditInstance - Editor instance information structure.
- *
- * Return: void
- */
- static void ODEditDeleteCurrentChar(tEditInstance *pEditInstance)
- {
- char *pch;
- ASSERT(pEditInstance != NULL);
- /* Remember initial edit area contents, to permit selective redraw. */
- ODEditRememberArea(pEditInstance, pEditInstance->pRememberBuffer);
- /* Backup the entire buffer contents by one character. */
- pch = ODEditBufferGetCharacter(pEditInstance,
- pEditInstance->unCurrentLine, pEditInstance->unCurrentColumn);
- memmove(pch, pch + 1, strlen(pch + 1) + 1);
- /* Reindex and reformat the buffer based on its new contents. */
- ODEditBufferFormatAndIndex(pEditInstance);
- /* Perform necessary redrawing and reposition the cursor if needed. */
- ODEditRedrawChanged(pEditInstance, pEditInstance->pRememberBuffer,
- REDRAW_NO_BOUNDARY, REDRAW_NO_BOUNDARY);
- }
- /* ----------------------------------------------------------------------------
- * ODEditDeleteCurrentLine() *** PRIVATE FUNCTION ***
- *
- * Removes the entire current line from the buffer.
- *
- * Parameters: pEditInstance - Editor instance information structure.
- *
- * Return: void
- */
- static void ODEditDeleteCurrentLine(tEditInstance *pEditInstance)
- {
- char *pszStartOfThisLine;
- char *pszStartOfNextLine;
- ASSERT(pEditInstance != NULL);
- /* Remember initial edit area contents, to permit selective redraw. */
- ODEditRememberArea(pEditInstance, pEditInstance->pRememberBuffer);
- /* Determine start of this line. */
- pszStartOfThisLine = ODEditBufferGetCharacter(pEditInstance,
- pEditInstance->unCurrentLine, 0);
- if(pEditInstance->unLinesInBuffer == pEditInstance->unCurrentLine + 1)
- {
- /* If this is the last line of the buffer, then we just remove */
- /* everything from this line, without actually removing the line. */
- *pszStartOfThisLine = '\0';
- }
- else
- {
- /* If this is not the last line of the buffer, then remove this */
- /* entire line, so that the next line will become the current */
- /* line. */
- pszStartOfNextLine = ODEditBufferGetCharacter(pEditInstance,
- pEditInstance->unCurrentLine + 1, 0);
- memmove(pszStartOfThisLine, pszStartOfNextLine,
- strlen(pszStartOfNextLine) + 1);
- }
- /* Reset the cursor position to the beginning of the current line. */
- pEditInstance->unCurrentColumn = 0;
- /* Reindex and reformat the buffer based on its new contents. */
- ODEditBufferFormatAndIndex(pEditInstance);
- /* Perform necessary redrawing and reposition the cursor if needed. */
- ODEditRedrawChanged(pEditInstance, pEditInstance->pRememberBuffer,
- REDRAW_NO_BOUNDARY, REDRAW_NO_BOUNDARY);
- }
- /* ----------------------------------------------------------------------------
- * ODEditPastEndOfCurLine() *** PRIVATE FUNCTION ***
- *
- * Determines whether the cursor is currently past the end of the current line.
- * The end of the line is considered to be the first column after the last
- * character on the line. So, on a blank line, a cursor is considered to be
- * past the end if it is in or past the second column (column 0).
- *
- * Parameters: pEditInstance - Editor instance information structure.
- *
- * Return: TRUE if the cursor is past the end of the current line,
- * FALSE if it is not.
- */
- static BOOL ODEditPastEndOfCurLine(tEditInstance *pEditInstance)
- {
- ASSERT(pEditInstance != NULL);
- return(pEditInstance->unCurrentColumn >
- ODEditBufferGetLineLength(pEditInstance, pEditInstance->unCurrentLine));
- }
- /* ----------------------------------------------------------------------------
- * ODEditRememberBufferSize() *** PRIVATE FUNCTION ***
- *
- * Determines the buffer size required by ODEditRememberArea().
- *
- * Parameters: pEditInstance - Editor instance information structure.
- *
- * Return: the required buffer size, in size_t units (bytes).
- */
- static size_t ODEditRememberBufferSize(tEditInstance *pEditInstance)
- {
- ASSERT(pEditInstance != NULL);
- return((pEditInstance->unAreaWidth + 1)
- * pEditInstance->unAreaHeight);
- }
- /* ----------------------------------------------------------------------------
- * ODEditRememberArea() *** PRIVATE FUNCTION ***
- *
- * Stores a copy of the text currently displayed in the edit area in the
- * provided buffer, so that it can later be reused to redraw only the portion
- * of the edit area which has been changed by an operation.
- *
- * Parameters: pEditInstance - Editor instance information structure.
- *
- * pRememberedArea - Pointer to a buffer, which is at least
- * the number of bytes specified by
- * ODEditRememberBufferSize() in size.
- *
- * Return: void
- */
- static void ODEditRememberArea(tEditInstance *pEditInstance,
- void *pRememberedArea)
- {
- UINT unDataLineOffset = 0;
- UINT unDataLineSize;
- UINT unAreaLine;
- UINT unBufferLine;
- UINT unLineLength;
- char *pchStartOfLine;
- char *pchDataLocation;
- ASSERT(pEditInstance != NULL);
- ASSERT(pRememberedArea != NULL);
- /* Determine the length of a single line in the remember buffer. */
- unDataLineSize = pEditInstance->unAreaWidth + 1;
- pchDataLocation = (char *)pRememberedArea + unDataLineOffset;
- for(unBufferLine = pEditInstance->unLineScrolledToTop, unAreaLine = 0;
- unAreaLine < pEditInstance->unAreaHeight;
- ++unAreaLine, ++unBufferLine)
- {
- /* If this line is not beyond the end of the buffer. */
- if(unBufferLine < pEditInstance->unLinesInBuffer)
- {
- /* Determine the length of this buffer line. */
- unLineLength = ODEditBufferGetLineLength(pEditInstance, unBufferLine);
- /* Determine the start location of this buffer line. */
- pchStartOfLine = ODEditBufferGetCharacter(pEditInstance, unBufferLine,
- 0);
- }
- else
- {
- /* If this line is beyond the end of the buffer, then it is empty. */
- unLineLength = 0;
- pchStartOfLine = "";
- }
- /* Copy the contents of this line to the data buffer. */
- memcpy(pchDataLocation, pchStartOfLine, unLineLength);
- pchDataLocation[unLineLength] = '\0';
- /* Update the location where data is being stored in the buffer. */
- pchDataLocation += unDataLineSize;
- }
- }
- /* ----------------------------------------------------------------------------
- * ODEditRedrawChanged() *** PRIVATE FUNCTION ***
- *
- * Redraws the portion of the edit area which has been changed by an operation,
- * based on the original edit area contents as stored in a buffer by the
- * ODEditRememberArea() function.
- *
- * Parameters: pEditInstance - Editor instance information structure.
- *
- * pRememberedArea - Pointer to a buffer that was filled by a
- * previous call to ODEditRememberArea().
- *
- * unUpperBoundary - The first line in the edit area to consider
- * redrawing, or REDRAW_NO_BOUNDARY to specify
- * the top of the edit area.
- *
- * unLowerBoundary - The last line in the edit area to consider
- * redrawing, or REDRAW_NO_BOUNDARY to specify
- * the bottom of the edit area.
- *
- * Return: void
- */
- static void ODEditRedrawChanged(tEditInstance *pEditInstance,
- void *pRememberedArea, UINT unUpperBoundary, UINT unLowerBoundary)
- {
- UINT unStartRedrawLine;
- UINT unStartRedrawColumn;
- UINT unFinishRedrawLine;
- UINT unFinishRedrawColumn;
- UINT unEstPartialRedrawBytes;
- ASSERT(pEditInstance != NULL);
- ASSERT(pRememberedArea != NULL);
- /* Determine what portion of the edit area, within the specified upper */
- /* and lower boundaries, has been changed. */
- if(!ODEditDetermineChanged(pEditInstance, pRememberedArea, unUpperBoundary,
- unLowerBoundary, &unStartRedrawLine, &unStartRedrawColumn,
- &unFinishRedrawLine, &unFinishRedrawColumn))
- {
- /* Nothing has changed in the edit area. */
- ODEditUpdateCursorIfMoved(pEditInstance);
- return;
- }
- /* Now that we have determined the portion of the edit area that would */
- /* be redraw by a partial (incremental) redraw, we compare the amount */
- /* of data involved + the amount of data still in the outbound buffer */
- /* with the amount of data involved in a full redraw. If the amount of */
- /* data in the outbound buffer cannot be determined, we default to */
- /* using an incremental redraw. */
- unEstPartialRedrawBytes = ODEditEstDrawBytes(pEditInstance,
- unStartRedrawLine, unStartRedrawColumn, unFinishRedrawLine,
- unFinishRedrawColumn);
- if(ODEditRecommendFullRedraw(pEditInstance, unEstPartialRedrawBytes,
- FALSE))
- {
- /* Purge the outbound buffer and do a full redraw. */
- ODEditRedrawArea(pEditInstance);
- /* Move the cursor back to its appropriate position. */
- ODEditUpdateCursorPos(pEditInstance);
- }
- else
- {
- /* Perform a partial (incremental) redraw. */
- /* Now, redraw the portion of the edit area that has been determined to */
- /* require redrawing. */
- ODEditRedrawSubArea(pEditInstance, unStartRedrawLine, unStartRedrawColumn,
- unFinishRedrawLine, unFinishRedrawColumn);
- /* Now, move the cursor back to its appropriate position, if it isn't */
- /* already there. */
- ODEditUpdateCursorIfMoved(pEditInstance);
- }
- }
- /* ----------------------------------------------------------------------------
- * ODEditDetermineChanged() *** PRIVATE FUNCTION ***
- *
- * Determines what portion of the edit area, within the specifiede upper and
- * lower boundary, has been changed. Area is specified as row and column
- * position of the first changed characer between boundaries, and the row
- * and column position past the last changed character between the boundaries.
- *
- * Parameters: pEditInstance - Editor instance information structure.
- *
- * pRememberedArea - Pointer to a buffer that was filled by a
- * previous call to ODEditRememberArea().
- *
- * unUpperBoundary - The first line in the edit area to
- * consider redrawing, or
- * REDRAW_NO_BOUNDARY to specify the top of
- * the edit area.
- *
- * unLowerBoundary - The last line in the edit area to
- * consider redrawing, or
- * REDRAW_NO_BOUNDARY to specify the bottom
- * of the edit area.
- *
- * punStartRedrawLine - Output: Line of first changed character.
- *
- * punStartRedrawColumn - Output: Column of first changed char.
- *
- * punFinishRedrawLine - Output: Line of last changed character.
- *
- * punFinishRedrawColumn - Output: Column after last changed char.
- *
- * Return: TRUE if some text in the edit area has been changed, FALSE
- * if there is no change.
- */
- static BOOL ODEditDetermineChanged(tEditInstance *pEditInstance,
- void *pRememberedArea, UINT unUpperBoundary, UINT unLowerBoundary,
- UINT *punStartRedrawLine, UINT *punStartRedrawColumn,
- UINT *punFinishRedrawLine, UINT *punFinishRedrawColumn)
- {
- BOOL bFoundStart = FALSE;
- BOOL bFoundFinish = FALSE;
- UINT unDataLineOffset = 0;
- UINT unDataLineSize;
- UINT unAreaLine;
- UINT unLineLength;
- UINT unColumn;
- UINT unBufferLine;
- char *pchCurrent;
- char *pchRemembered;
- /* Determine the length of a single line in the remember buffer. */
- unDataLineSize = pEditInstance->unAreaWidth + 1;
- /* If caller specified no upper boundary, then reset upper boundary */
- /* to 0. */
- if(unUpperBoundary == REDRAW_NO_BOUNDARY) unUpperBoundary = 0;
- /* Likewise, iff caller specified no lower boundary, then reset the */
- /* lower boundary to the bottom of the edit area. */
- if(unLowerBoundary == REDRAW_NO_BOUNDARY)
- {
- unLowerBoundary = pEditInstance->unAreaHeight;
- }
- /* Loop through the area within boundaries, determining which */
- /* portion of the edit area has changed. */
- for(unBufferLine = pEditInstance->unLineScrolledToTop + unUpperBoundary,
- unAreaLine = unUpperBoundary; unAreaLine < unLowerBoundary;
- ++unAreaLine, ++unBufferLine)
- {
- /* Determine location of corresponding line in remembered data. */
- pchRemembered = (char *)pRememberedArea + unDataLineOffset
- + unDataLineSize * unAreaLine;
- /* If this line is not beyond the end of the buffer. */
- if(unBufferLine < pEditInstance->unLinesInBuffer)
- {
- /* Determine the start location of this buffer line. */
- pchCurrent = ODEditBufferGetCharacter(pEditInstance, unBufferLine, 0);
- /* Determine the length of this buffer line. */
- unLineLength = ODEditBufferGetLineLength(pEditInstance, unBufferLine);
- }
- else
- {
- pchCurrent = "";
- unLineLength = 0;
- }
- /* Start at the first column on this line. */
- unColumn = 0;
- /* Look for any characters that differ. */
- for(;; ++unColumn, ++pchCurrent, ++pchRemembered)
- {
- /* Determine if we are at the end of the remembered line. */
- BOOL bEndOfRemembered = (*pchRemembered == '\0');
- /* Determine if we are at the end of the current buffer line. */
- BOOL bEndOfCurrent = (unColumn == unLineLength);
- /* If we are at the end of either of the buffers (but not both), */
- /* or if these two characters differ, then we have found the */
- /* start of the area that must be redrawn. */
- if(!(bEndOfRemembered && bEndOfCurrent))
- {
- if(bEndOfRemembered || bEndOfCurrent
- || *pchCurrent != *pchRemembered)
- {
- if(bFoundStart)
- {
- bFoundFinish = FALSE;
- }
- else
- {
- /* We have found a character that differs. */
- bFoundStart = TRUE;
- *punStartRedrawLine = unAreaLine;
- *punStartRedrawColumn = unColumn;
- }
- }
- }
- /* If we have found the first changed text in the buffer, then we */
- /* are now looking for the last changed text in the buffer. */
- if(bFoundStart && !bFoundFinish)
- {
- if(*pchCurrent == *pchRemembered)
- {
- bFoundFinish = TRUE;
- *punFinishRedrawLine = unAreaLine;
- *punFinishRedrawColumn = unColumn;
- }
- else if(bEndOfRemembered)
- {
- bFoundFinish = TRUE;
- *punFinishRedrawLine = unAreaLine;
- *punFinishRedrawColumn = unLineLength;
- }
- else if(bEndOfCurrent)
- {
- bFoundFinish = TRUE;
- *punFinishRedrawLine = unAreaLine;
- *punFinishRedrawColumn = unColumn + strlen(pchRemembered);
- }
- }
- /* If we are at the end of either buffers. */
- if(bEndOfRemembered || bEndOfCurrent)
- {
- /* Now, proceed to processing the next line in the edit area. */
- break;
- }
- }
- }
- /* If we haven't found any text in the edit area that has changed. */
- if(!bFoundStart)
- {
- /* Then return indicating no change. */
- return(FALSE);
- }
- /* If we haven't found an end to the portion of the area that has */
- /* changed, then we must redraw up to the end of the edit area. */
- if(!bFoundFinish)
- {
- *punFinishRedrawLine = unLowerBoundary;
- *punFinishRedrawColumn = unColumn;
- }
- /* Return indicating that ther has been some change. */
- return(TRUE);
- }
- /* ----------------------------------------------------------------------------
- * ODEditRedrawSubArea() *** PRIVATE FUNCTION ***
- *
- * Redraws the portion of the edit area within the specified range. Redrawing
- * is performed from the location of the start redraw row and column, up to
- * but not includin gthe finish redraw row and column.
- *
- * Parameters: pEditInstance - Editor instance information structure.
- *
- * unStartRedrawLine - Line of first character to draw.
- *
- * unStartRedrawColumn - Column of first character to draw.
- *
- * unFinishRedrawLine - Line of last character to draw.
- *
- * unFinishRedrawColumn - Column after last character to draw.
- *
- * Return: void
- */
- static void ODEditRedrawSubArea(tEditInstance *pEditInstance,
- UINT unStartRedrawLine, UINT unStartRedrawColumn, UINT unFinishRedrawLine,
- UINT unFinishRedrawColumn)
- {
- UINT unAreaLine;
- UINT unLineLength;
- UINT unBufferLine;
- char *pchCurrent;
- UINT unStartColumn;
- UINT unFinishColumn;
- UINT unScrnStartColumn;
- UINT unTextLength;
- /* Now, perform actual redraw in area that requires redrawing. */
- for(unBufferLine = pEditInstance->unLineScrolledToTop + unStartRedrawLine,
- unAreaLine = unStartRedrawLine; unAreaLine <= unFinishRedrawLine;
- ++unBufferLine, ++unAreaLine)
- {
- BOOL bFirstLine = (unAreaLine == unStartRedrawLine);
- BOOL bLastLine = (unAreaLine == unFinishRedrawLine);
- UINT unScrnRow = (UINT)pEditInstance->pUserOptions->nAreaTop
- + unAreaLine;
- /* If this line is not beyond the end of the buffer. */
- if(unBufferLine < pEditInstance->unLinesInBuffer)
- {
- pchCurrent = ODEditBufferGetCharacter(pEditInstance, unBufferLine, 0);
- unTextLength = unLineLength =
- ODEditBufferGetLineLength(pEditInstance, unBufferLine);
- }
- else
- {
- pchCurrent = "";
- unTextLength = unLineLength = 0;
- }
- /* Move to the position on the first line to begin redraw. */
- if(bFirstLine)
- {
- UINT unActualRow;
- UINT unActualColumn;
- ODEditGetActualCurPos(pEditInstance, &unActualRow, &unActualColumn);
- unStartColumn = unStartRedrawColumn;
- unScrnStartColumn = (UINT)pEditInstance->pUserOptions->nAreaLeft
- + unStartColumn;
- if(unScrnRow != unActualRow || unScrnStartColumn != unActualColumn)
- {
- od_set_cursor(unScrnRow, unScrnStartColumn);
- }
- pchCurrent += unStartRedrawColumn;
- unTextLength -= unStartRedrawColumn;
- }
- else
- {
- unStartColumn = 0;
- unScrnStartColumn = (UINT)pEditInstance->pUserOptions->nAreaLeft;
- od_set_cursor(unScrnRow, unScrnStartColumn);
- }
- /* If this is the last line to redraw, then adjust accordingly. */
- if(bLastLine)
- {
- if(unFinishRedrawColumn < unLineLength)
- {
- unTextLength -= unLineLength - unFinishRedrawColumn;
- }
- unFinishColumn = unFinishRedrawColumn;
- }
- else
- {
- unFinishColumn = pEditInstance->unAreaWidth;
- }
- /* Output changed text. */
- if(unStartColumn < unLineLength)
- {
- od_disp(pchCurrent, unTextLength, TRUE);
- unStartColumn += unTextLength;
- }
- /* If we need to clear the rest of the line. */
- if(unFinishColumn == pEditInstance->unAreaWidth)
- {
- /* If right edge of edit area aligns with the right edge of the */
- /* screen. */
- if(pEditInstance->pUserOptions->nAreaRight == OD_SCREEN_WIDTH)
- {
- /* Clear the remainder of this line on the screen. */
- od_clr_line();
- }
- else
- {
- /* Place spaces after the end of the current line, up to right */
- /* edge of the edit area. */
- od_repeat(' ', (BYTE)(pEditInstance->unAreaWidth - unLineLength));
- }
- }
- else if(unStartColumn < unFinishColumn)
- {
- od_repeat(' ', (BYTE)(unFinishColumn - unStartColumn));
- }
- }
- }
- /* ----------------------------------------------------------------------------
- * ODEditGetActualCurPos() *** PRIVATE FUNCTION ***
- *
- * Estimates the actual position of the cursor on the screen.
- *
- * Parameters: pEditInstance - Editor instance information structure.
- *
- * punRow - Pointer to location where cursor row number
- * should be stored.
- *
- * punColumn - Pointer to location where cursor column number
- * should be stored.
- *
- * Return: void
- */
- static void ODEditGetActualCurPos(tEditInstance *pEditInstance,
- UINT *punRow, UINT *punColumn)
- {
- tODScrnTextInfo TextInfo;
- ASSERT(pEditInstance != NULL);
- ASSERT(punRow != NULL);
- ASSERT(punColumn != NULL);
- UNUSED(pEditInstance);
- /* Obtain current cursor position information from the ODScrn module. */
- ODScrnGetTextInfo(&TextInfo);
- *punRow = (UINT)TextInfo.cury;
- *punColumn = (UINT)TextInfo.curx;
- }
- /* ----------------------------------------------------------------------------
- * ODEditIsEOLForMode() *** PRIVATE FUNCTION ***
- *
- * Determines whether the specified character should be treated as an EOL
- * character for the current mode.
- *
- * Parameters: pEditInstance - Editor instance information structure.
- *
- * Return: TRUE if this is an EOL character, FALSE otherwise.
- */
- static BOOL ODEditIsEOLForMode(tEditInstance *pEditInstance, char chToTest)
- {
- switch(pEditInstance->pUserOptions->TextFormat)
- {
- case FORMAT_FTSC_MESSAGE:
- return(chToTest == '\r' || chToTest == '\0');
- default:
- return(IS_EOL_CHAR(chToTest));
- }
- }
- /* ========================================================================= */
- /* Low level buffer manipulation functions. */
- /* ========================================================================= */
- /* ----------------------------------------------------------------------------
- * ODEditBufferFormatAndIndex() *** PRIVATE FUNCTION ***
- *
- * Regenerates the count of lines in the buffer, and the array of pointers to
- * the start of each line.
- *
- * Parameters: pEditInstance - Editor instance information structure.
- *
- * Return: TRUE on success, or FALSE if there is not enough memory
- * available to complete this operation.
- */
- static BOOL ODEditBufferFormatAndIndex(tEditInstance *pEditInstance)
- {
- char *pch;
- char *pchLastSpace;
- UINT unProcessingColumn;
- UINT unProcessingLine;
- BOOL bAtEndOfBuffer = FALSE;
- BOOL bLineEndedByBreak;
- BOOL bFTSCMode =
- (pEditInstance->pUserOptions->TextFormat == FORMAT_FTSC_MESSAGE);
- ASSERT(pEditInstance != NULL);
- /* Reset current line count. */
- unProcessingLine = 0;
- /* Begin at the beginning of the buffer to edit. */
- pch = pEditInstance->pszEditBuffer;
- ASSERT(pch != NULL);
- /* Loop for each line in the buffer. */
- while(!bAtEndOfBuffer)
- {
- /* In FTSC mode, skip a line if it begins with a ^A ("kludge lines"). */
- if(bFTSCMode)
- {
- /* Loop while the current line begins with a ^A. */
- while(*pch == 0x01)
- {
- /* Loop until the end of the line is found. */
- while(!ODEditIsEOLForMode(pEditInstance, *pch)) ++pch;
- if(*pch == '\0')
- {
- /* If the line was ended by a null character, then note that */
- /* the end of the buffer has been reached. */
- bAtEndOfBuffer = TRUE;
- }
- else
- {
- /* If the line was not ended by a null character, then skip */
- /* the end of line character. */
- ++pch;
- }
- }
- continue;
- }
- /* Add the address of the start of this line to the line array. */
-
- /* If the line array is full, then attempt to grow it. */
- ASSERT(unProcessingLine <= pEditInstance->unLineArraySize);
- if(unProcessingLine == pEditInstance->unLineArraySize)
- {
- /* Determine the size to grow the array to. */
- UINT unNewArraySize = pEditInstance->unLineArraySize
- + LINE_ARRAY_GROW_SIZE;
- /* Attempt to reallocate this memory block. */
- char **papchNewLineArray = (char **)realloc(
- pEditInstance->papchStartOfLine, unNewArraySize * sizeof(char *));
- /* If reallocation failed, then return with failure. */
- if(papchNewLineArray == NULL)
- {
- return(FALSE);
- }
- /* Otherwise, update the editor instance information with the new */
- /* array address and array size information. */
- pEditInstance->papchStartOfLine = papchNewLineArray;
- pEditInstance->unLineArraySize = unNewArraySize;
- }
- /* Add the address of the start of this line to the array. */
- pEditInstance->papchStartOfLine[unProcessingLine] = pch;
- /* Reset word wrap information. */
- pchLastSpace = NULL;
- /* Now, find the end of this line. */
- bLineEndedByBreak = TRUE;
- unProcessingColumn = 0;
- while(!ODEditIsEOLForMode(pEditInstance, *pch))
- {
- /* If this character is a space, then record the location of the */
- /* last space characters. */
- if(*pch == ' ') pchLastSpace = pch;
- /* Check for characters which must be filtered from the buffer */
- /* in FTSC message mode. */
- if(bFTSCMode)
- {
- if(*pch == 0x0a || ((unsigned char)*pch) == 0x8d)
- {
- /* If this character must be removed, then move rest of */
- /* buffer up by one character, and proceed to next loop */
- /* iteration. */
- memmove(pch, pch + 1, strlen(pch + 1) + 1);
- continue;
- }
- }
- /* Increment count of characters on this line. */
- ++unProcessingColumn;
- /* Check whether we have reached the maximum number of characters */
- /* that will fit on this line. */
- if(unProcessingColumn >= pEditInstance->unAreaWidth - 1)
- {
- if(pEditInstance->bWordWrapLongLines)
- {
- /* If we are to word wrap long lines, then back up to the */
- /* beginning of the last word, if we have encountered any */
- /* space characters. */
- if(pchLastSpace != NULL && pchLastSpace < pch)
- {
- /* Update current column number accordingly. */
- unProcessingColumn -= (UINT)(pch - pchLastSpace);
- /* Back up to position to perform word wrap at. */
- pch = pchLastSpace;
- }
- }
- /* If we are wrapping text where the cursor is located, then we */
- /* will have to reposition the cursor accordingly. */
- if(unProcessingLine == pEditInstance->unCurrentLine
- && unProcessingColumn < pEditInstance->unCurrentColumn)
- {
- /* Move the cursor to the next line. */
- pEditInstance->unCurrentLine++;
- /* Adjust the cursor column number to the position where the */
- /* corresponding wrapped text will appear. */
- pEditInstance->unCurrentColumn -= unProcessingColumn;
- }
- /* Note that line was not ended by en explicit line break. */
- bLineEndedByBreak = FALSE;
- break;
- }
- /* Move to the next character in the buffer. */
- ++pch;
- }
- /* If we the line was terminated by a '\0', then note that the end of */
- /* the buffer has been reached. */
- if(*pch == '\0')
- {
- bAtEndOfBuffer = TRUE;
- }
- /* If the line was not terminated by a '\0', then find the first */
- /* character of the next line. */
- else
- {
- char chFirstEOLChar = *pch;
- char chSecondEOLChar = '\0';
- /* Move to the next character in the buffer. */
- ++pch;
-
- /* If this character is a different EOL sequence character from the */
- /* already encountered EOL character, then skip past it too. */
- if(ODEditIsEOLForMode(pEditInstance, chFirstEOLChar) && *pch != '\0'
- && ODEditIsEOLForMode(pEditInstance, *pch)
- && *pch != chFirstEOLChar)
- {
- chSecondEOLChar = *pch;
- ++pch;
- }
-
- /* If we don't already know what form of line/paragraph break to */
- /* use (just a CR, just a LF, a CR/LF sequence or a LF/CR */
- /* sequence), then use this line termination as an example of */
- /* what should be used. */
- if(bLineEndedByBreak)
- {
- ODEditSetBreakSequence(pEditInstance, chFirstEOLChar,
- chSecondEOLChar);
- }
- }
- /* Increment the count of the current line number. */
- unProcessingLine++;
- }
- /* Update count of number of lines in the buffer, based on the number */
- /* that we have found. */
- pEditInstance->unLinesInBuffer = unProcessingLine;
- /* Return with success. */
- return(TRUE);
- }
- /* ----------------------------------------------------------------------------
- * ODEditBufferGetLineLength() *** PRIVATE FUNCTION ***
- *
- * Determines the length of the specified line in the buffer, not including
- * any line terminator characters.
- *
- * Parameters: pEditInstance - Editor instance information structure.
- *
- * unBufferLine - 0-based index of the line in question.
- *
- * Return: The number of characters on this line.
- */
- static UINT ODEditBufferGetLineLength(tEditInstance *pEditInstance,
- UINT unBufferLine)
- {
- char *pch;
- char *pchStartOfLine;
- UINT unCharsBeforeEOL;
- ASSERT(pEditInstance != NULL);
- ASSERT(unBufferLine < pEditInstance->unLinesInBuffer);
- ASSERT(pEditInstance->unLinesInBuffer <= pEditInstance->unLineArraySize);
- /* Get the address of the start of this line in the buffer. */
- pchStartOfLine
- = ODEditBufferGetCharacter(pEditInstance, unBufferLine, 0);
- /* Count the number of characters before the next end of line character. */
- for(pch = pchStartOfLine, unCharsBeforeEOL = 0;
- !ODEditIsEOLForMode(pEditInstance, *pch);
- ++unCharsBeforeEOL, ++pch);
- /* If this is the last line in the buffer, then the number of characers */
- /* before the next end of line character is the length of this line. */
- if(unBufferLine >= pEditInstance->unLinesInBuffer - 1)
- {
- return(unCharsBeforeEOL);
- }
- /* If this is not the last line in the buffer, then the length of this */
- /* line is the minimum of the number of characters before the next end */
- /* of line character and the number of characters before the next line, */
- /* according to the line index information. This is because all lines */
- /* do not necessarily end with an end-of-line character. */
- else
- {
- return(MIN(unCharsBeforeEOL, (UINT)(ODEditBufferGetCharacter(
- pEditInstance, unBufferLine + 1, 0) - pchStartOfLine)));
- }
- }
- /* ----------------------------------------------------------------------------
- * ODEditBufferGetTotalLines() *** PRIVATE FUNCTION ***
- *
- * Determines the number of lines in the current edit buffer.
- *
- * Parameters: pEditInstance - Editor instance information structure.
- *
- * Return: The total number of lines in the buffer.
- */
- static UINT ODEditBufferGetTotalLines(tEditInstance *pEditInstance)
- {
- ASSERT(pEditInstance != NULL);
- ASSERT(pEditInstance->unLinesInBuffer <= pEditInstance->unLineArraySize);
- /* Return the total number of lines in the buffer. */
- return(pEditInstance->unLinesInBuffer);
- }
- /* ----------------------------------------------------------------------------
- * ODEditBufferGetCharacter() *** PRIVATE FUNCTION ***
- *
- * Obtains the character at the specified position in the buffer.
- *
- * Parameters: pEditInstance - Editor instance information structure.
- *
- * unBufferLine - 0-based index of the line in question.
- *
- * unBufferColumn - The position in the line of the required
- * character.
- *
- * Return: A pointer to the character at the specified position in the
- * specified line. The caller can assume that any remaining
- * character(s) in the line follow this character, but should
- * not assume that the pointer can be used to access following
- * lines in the buffer.
- */
- static char *ODEditBufferGetCharacter(tEditInstance *pEditInstance,
- UINT unBufferLine, UINT unBufferColumn)
- {
- ASSERT(pEditInstance != NULL);
- ASSERT(unBufferLine < pEditInstance->unLinesInBuffer);
- ASSERT(pEditInstance->unLinesInBuffer <= pEditInstance->unLineArraySize);
- ASSERT(unBufferColumn <= ODEditBufferGetLineLength(pEditInstance, unBufferLine));
- /* The position of this character is the position of this line, plus */
- /* the number of characters into the line. */
- return(pEditInstance->papchStartOfLine[unBufferLine] + unBufferColumn);
- }
- /* ----------------------------------------------------------------------------
- * ODEditBufferMakeSpace() *** PRIVATE FUNCTION ***
- *
- * Moves the remaining buffer contents by the specified distance to make room
- * for new text. The new space is filled by space (' ') characters. Does not
- * necessarily reindex the buffer before returning, and so this should be done
- * by the caller after the new buffer space has been filled.
- *
- * Parameters: pEditInstance - Editor instance information structure.
- *
- * unLine - Line number to make more room on.
- *
- * unColumn - Column number to insert the space.
- *
- * unNumChars - Number of characters to make room for.
- *
- * Return: kODRCSuccess on success, kODRCSafeFailure if we were unable to
- * obtain enough buffer space before making any changes, or
- * kODRCUnrecoverableFailure if the buffer has been changed, but
- * there was insufficient memory to re-index the buffer.
- */
- static tODResult ODEditBufferMakeSpace(tEditInstance *pEditInstance,
- UINT unLine, UINT unColumn, UINT unNumChars)
- {
- UINT unLineLength;
- UINT unBufferUsed;
- UINT unBufferUnused;
- UINT unRemainingBufferBytes;
- UINT unCount;
- char *pchBufferPos;
- tODResult Result;
- ASSERT(pEditInstance != NULL);
- ASSERT(unLine < pEditInstance->unLinesInBuffer);
- /* Determine the current length of the specified line. */
- unLineLength = ODEditBufferGetLineLength(pEditInstance, unLine);
- /* If a column past the current end of this line was specified, then */
- /* adjust column and number of characters in order to extend the line */
- /* up to the specified column as well as adding space beginning at that */
- /* column. */
- if(unColumn > unLineLength)
- {
- UINT unExtendLineBy = unColumn - unLineLength;
- unColumn -= unExtendLineBy;
- unNumChars += unExtendLineBy;
- }
- /* Now, determine whether the buffer is large enough for the additional */
- /* space that will be added. */
- unBufferUsed = strlen(pEditInstance->pszEditBuffer) + 1;
- unBufferUnused = pEditInstance->unBufferSize - unBufferUsed;
- if(unBufferUnused < unNumChars)
- {
- /* There is not currently sufficient room in the buffer for the new */
- /* characters, then attempt to grow the buffer to make more room. */
- Result = ODEditTryToGrow(pEditInstance, unBufferUsed + unNumChars);
- if(Result != kODRCSuccess)
- {
- /* On failure, return the result code that indicates the nature */
- /* of the failure. */
- return(Result);
- }
- }
- /* Now, shift the buffer contents from this location forward by */
- /* unNumChars characters. */
- pchBufferPos = ODEditBufferGetCharacter(pEditInstance, unLine, unColumn);
- unRemainingBufferBytes = strlen(pchBufferPos) + 1;
- memmove(pchBufferPos + unNumChars, pchBufferPos, unRemainingBufferBytes);
- /* Next, we fill the new buffer area with space characters. */
- for(unCount = 0; unCount < unNumChars; ++unCount)
- {
- *pchBufferPos++ = ' ';
- }
- /* Return with success. */
- return(kODRCSuccess);
- }
- /* ----------------------------------------------------------------------------
- * ODEditTryToGrow() *** PRIVATE FUNCTION ***
- *
- * Attempts to reallocate the buffer to a larger size. This function is called
- * if it is found that the current buffer isn't large enough to complete some
- * operation. If the client application has setup the editor to permit buffer
- * reallocation, then this function will call the realloc callback function
- * supplied by the client application. If buffer growing is not possible, then
- * this function automatically fails.
- *
- * Parameters: pEditInstance - Editor instance information structure.
- *
- * unSizeNeeded - The minimum buffer size that is needed.
- *
- * Return: kODRCSuccess on success, kODRCSafeFailure if we were unable to
- * obtain enough buffer space before making any changes, or
- * kODRCUnrecoverableFailure if the buffer has been changed, but
- * there was insufficient memory to re-index the buffer.
- */
- static tODResult ODEditTryToGrow(tEditInstance *pEditInstance,
- UINT unSizeNeeded)
- {
- BOOL bFullReIndexRequired = FALSE;
- ASSERT(pEditInstance != NULL);
- ASSERT(unSizeNeeded > pEditInstance->unBufferSize);
- if(pEditInstance->pUserOptions->pfBufferRealloc != NULL)
- {
- /* If the buffer is growable, then attempt to grow it using the */
- /* realloc function provided by the client application. */
- UINT unNewBufferSize = MAX(pEditInstance->unBufferSize
- + BUFFER_GROW_SIZE, unSizeNeeded);
- char *pszNewBuffer = (char *)((*pEditInstance->pUserOptions->
- pfBufferRealloc)(pEditInstance->pszEditBuffer, unNewBufferSize));
- /* If we were unable to grow the buffer, then fail now. At this */
- /* point, nothing has changed, and so the buffer information */
- /* is still intact and valid. */
- if(pszNewBuffer == NULL)
- {
- return(kODRCSafeFailure);
- }
- /* Otherwise, determine whether the entire buffer will now have to */
- /* be reindexed. This is necessary if the reallocated buffer is at */
- /* a new location than the original was. */
- if(pszNewBuffer != pEditInstance->pszEditBuffer)
- {
- bFullReIndexRequired = TRUE;
- }
- /* Now, store the new buffer pointer and buffer size information. */
- pEditInstance->pszEditBuffer = pszNewBuffer;
- pEditInstance->unBufferSize = unNewBufferSize;
- }
- else
- {
- /* If the buffer is not growable, then fail right away. */
- return(kODRCSafeFailure);
- }
- /* If a full reindex is required due to buffer reallocation, then do so. */
- if(bFullReIndexRequired)
- {
- if(!ODEditBufferFormatAndIndex(pEditInstance))
- {
- /* If this fails, then return with failure. */
- return(kODRCUnrecoverableFailure);
- }
- bFullReIndexRequired = FALSE;
- }
- /* If we get to this point, we suceeded in growing the buffer to the */
- /* required size, so return with success. */
- return(kODRCSuccess);
- }
|