12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381 |
- /*
- * CDE - Common Desktop Environment
- *
- * Copyright (c) 1993-2012, The Open Group. All rights reserved.
- *
- * These libraries and programs are free software; you can
- * redistribute them and/or modify them 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.
- *
- * These libraries and programs are distributed in the hope that
- * they 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 these libraries and programs; if not, write
- * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
- * Floor, Boston, MA 02110-1301 USA
- */
- /* *
- * (c) Copyright 1993, 1994, 1996 Hewlett-Packard Company *
- * (c) Copyright 1993, 1994, 1996 International Business Machines Corp. *
- * (c) Copyright 1993, 1994, 1996 Sun Microsystems, Inc. *
- * (c) Copyright 1993, 1994, 1996 Novell, Inc. *
- * (c) Copyright 1996 Digital Equipment Corporation. *
- * (c) Copyright 1996 FUJITSU LIMITED. *
- * (c) Copyright 1996 Hitachi. *
- */
- #define USE_MEMCPY /* use memcpy for line movement... */
- #include <stdlib.h>
- #include <wchar.h>
- #include <Xm/Xm.h>
- #include "TermHeader.h" /* for MIN/MAX */
- #include "TermPrim.h"
- #include "TermPrimBuffer.h"
- #include "TermPrimBufferP.h"
- #include "TermPrimSelect.h"
- #include "TermPrimDebug.h"
- /*
- ** Allocate and initialize a new terminal buffer.
- */
- TermBuffer
- _DtTermPrimBufferCreateBuffer
- (
- const Widget w,
- const short rows,
- const short cols,
- const short sizeOfBuffer,
- const short sizeOfLine,
- const short sizeOfEnh
- )
- {
- int i;
- TermLine *newTL;
- TermBuffer newTB;
- Boolean *tabs;
- int sizeOfChar;
-
- /*
- ** malloc new a TermBuffer and an array of TermLine pointers
- */
- newTB = (TermBuffer) malloc(sizeOfBuffer);
- /* the following MIN ensures that on systems where malloc of 0 returns
- * NULL, we won't confuse a 0 size buffer with a malloc failure and an
- * invalid buffer...
- */
- newTL = (TermLine *) malloc((unsigned) MAX(rows, 1) * sizeof(TermLine));
- if (!newTB || !newTL)
- {
- /*
- ** clean up and leave if either of the previous malloc's failed.
- */
- if (newTB)
- {
- free(newTB);
- }
- if (newTL)
- {
- free(newTL);
- }
- return((TermBuffer)NULL);
- }
- /*
- ** malloc a tabs array...
- */
- tabs = (Boolean *) malloc((unsigned) cols * sizeof(Boolean));
- if (!tabs)
- {
- free(newTB);
- free(newTL);
- /*
- ** clean up and leave if either of the previous malloc's failed.
- */
- return((TermBuffer)NULL);
- }
- /*
- ** initialize the tabs...
- */
- for (i = 0; i < cols; i++) {
- tabs[i] = 0 == i % 8;
- }
- /*
- ** decide how many bytes to allocate per character...
- */
- BYTES_PER_CHAR(newTB) = MB_CUR_MAX == 1 ? 1 : sizeof(wchar_t);
- /*
- ** setting debug flag m:1 forces us into wide char mode...
- */
- DebugF('m', 1, BYTES_PER_CHAR(newTB) = sizeof(wchar_t));
- /*
- ** now malloc the individual lines...
- */
- for (i = 0; i < rows; i++)
- {
- newTL[i] = (TermLine) malloc(sizeOfLine);
- if (newTL[i])
- {
- BUFFER(newTL[i]) = (termChar *)
- malloc((unsigned)
- cols * BYTES_PER_CHAR(newTB));
- if (BUFFER(newTL[i]) == NULL)
- {
- /*
- ** we couldn't malloc a line buffer
- */
- break;
- }
- LENGTH(newTL[i]) = 0;
- WIDTH(newTL[i]) = 0;
- WRAPPED(newTL[i]) = False;
- START_SELECTION(newTL[i]) = NON_SELECTION_COL;
- END_SELECTION(newTL[i]) = NON_SELECTION_COL;
- }
- else
- {
- /*
- ** we couldn't malloc a line
- */
- break;
- }
- }
- /*
- ** If we were unable to malloc a full set of lines (i != rows),
- ** then cleanup and leave.
- */
- if (i != rows)
- {
- int j;
- for (j = 0; j < i; j++)
- {
- free(BUFFER(newTL[j]));
- free(newTL[j]);
- }
- free(newTL);
- free(newTB);
- free(tabs);
- return((TermBuffer)NULL);
- }
- /*
- ** Initialize the new TermBuffer.
- */
- LINES(newTB) = newTL;
- TABS(newTB) = tabs;
- ROWS(newTB) = rows;
- COLS(newTB) = cols;
- MAX_ROWS(newTB) = rows;
- MAX_COLS(newTB) = cols;
- SIZE_OF_BUFFER(newTB) = sizeOfBuffer;
- SIZE_OF_LINE(newTB) = sizeOfLine;
- SIZE_OF_ENH(newTB) = sizeOfEnh;
- BUFFER_CREATE(newTB) = _DtTermPrimBufferCreateBuffer;
- BUFFER_FREE(newTB) = NULL;
- BUFFER_RESIZE(newTB) = NULL;
- ENH_PROC(newTB) = NULL;
- CLEAR_ENH(newTB) = NULL;
- INSERT_ENH(newTB) = NULL;
- DELETE_ENH(newTB) = NULL;
- SET_ENH(newTB) = NULL;
- GET_ENH(newTB) = NULL;
- SET_LINE_WIDTH(newTB) = NULL;
- CLEAR_LINE(newTB) = NULL;
- NEXT_BUFFER(newTB) = NULL;
- PREV_BUFFER(newTB) = NULL;
- BUFFER_SELECT_INFO(newTB) = NULL;
- WIDGET(newTB) = w;
- return (newTB);
- }
- void
- _DtTermPrimBufferFreeBuffer
- (
- const TermBuffer tb
- )
- {
- int i;
- /* check for null buffer... */
- if (!tb) {
- return;
- }
- /*
- ** Free any buffer-specific info first...
- */
- if (BUFFER_FREE(tb))
- {
- (*BUFFER_FREE(tb))(tb);
- }
-
- /*
- ** free the old buffer...
- */
- for (i = 0; i < MAX_ROWS(tb); i++)
- {
- (void) free(BUFFER(LINES(tb)[i]));
- (void) free(LINES(tb)[i]);
- }
- (void) free(TABS(tb));
- (void) free(LINES(tb));
- (void) free(tb);
- }
- /*
- ** Resize the terminal buffer, and try to be smart about it. If the buffer
- ** shrinks, then simply adjust the size, no reallocs necessary (that way if
- ** the user returns to the previous size, no data is lost).
- **
- ** NOTE:
- ** Given this implementation, the memory allocated to the buffer will
- ** never decrease it simply increases to accommodate the largest size
- ** that has ever been requested.
- */
- void
- _DtTermPrimBufferResizeBuffer
- (
- TermBuffer *oldTB,
- short *newRows,
- short *newCols
- )
- {
- int i;
- short thisTabWidth;
- short tabWidth;
- TermLine *newTL;
- Boolean *tabs;
-
- /*
- ** enforce some minimum size constraints...
- */
- *newRows = MAX(*newRows, 1);
- *newCols = MAX(*newCols, 1);
- /*
- ** the number of cols is increasing, start small and adjust the tab
- ** stops first...
- */
- if (*newCols > MAX_COLS(*oldTB))
- {
- tabs = (Boolean *) malloc((unsigned) *newCols * sizeof(Boolean));
- if (tabs)
- {
- /* copy over the tab stops... */
- (void) memcpy(tabs, TABS(*oldTB), COLS(*oldTB) * sizeof(Boolean));
- free(TABS(*oldTB));
- TABS(*oldTB) = tabs;
-
- /*
- ** we need to extend the tab stops...
- **
- ** when tabWidth == 0, it has not been initialized. When
- ** it is < 0, we have encountered unequal tab stops...
- */
- tabWidth = 0;
- for (i = 0, thisTabWidth = 0; i < COLS(*oldTB); i++, thisTabWidth++)
- {
- if (TABS(*oldTB)[i])
- {
- if (tabWidth == 0)
- {
- /* first tab stop, set tabWidth... */
- tabWidth = thisTabWidth;
- }
- else if (tabWidth != thisTabWidth)
- {
- /* tab stops differ, set tabWidth to -1... */
- tabWidth = -1;
- }
- /* reset for next tab stop... */
- thisTabWidth = 0;
- }
- }
-
- if (tabWidth > 0)
- {
- /*
- ** we have consistent tab stops. Extend the buffer...
- */
- for (i = COLS(*oldTB); i < *newCols; i++)
- {
- TABS(*oldTB)[i] = (0 == (i % tabWidth));
- }
- }
- else
- {
- /*
- ** we don't have consistent tab stops, so clear the rest...
- */
- (void) memset(&(TABS(*oldTB)[COLS(*oldTB)]), '\0',
- (*newCols - COLS(*oldTB)) * sizeof(Boolean));
- }
- }
- else
- {
- /*
- ** the malloc failed, adjust newCols and newRows and leave...
- */
- *newCols = MAX_COLS(*oldTB);
- *newRows = MIN(*newRows, MAX_ROWS(*oldTB));
- COLS(*oldTB) = *newCols;
- ROWS(*oldTB) = *newRows;
- return;
- }
- }
- else
- {
- /*
- ** take care of any shrinkage...
- */
- COLS(*oldTB) = *newCols;
- }
- /*
- ** Now give the resize helper a shot at resizing the buffer
- */
- if (BUFFER_RESIZE(*oldTB))
- {
- /*
- ** Call the resize helper function if it exists...
- */
- (*BUFFER_RESIZE(*oldTB))(*oldTB, newRows, newCols);
- }
- else
- {
- /*
- ** There is no helper function, do it ourselves...
- ** NOTE:
- ** This might cause some duplication of code, but due
- ** to time constraints, it is the most expeditious route.
- */
- /*
- ** make any necessary width adjustments first...
- **
- ** NOTE:
- ** We do not take any action if the new column width is less
- ** than the current column width. It is the responsibility of
- ** the rendering code to make sure that two column characters
- ** are handled properly if the second column falls past the last
- ** column in the window.
- */
- if (*newCols > MAX_COLS(*oldTB))
- {
- termChar *newLineBuffer;
-
- /*
- ** now extend the line buffers for all lines, (even lines that
- ** are not being used at the moment (ROWS < MAX_ROWS))...
- */
- newTL = LINES(*oldTB);
- for (i = 0; i < MAX_ROWS(*oldTB); i++)
- {
- newLineBuffer = (termChar *) malloc((unsigned)
- *newCols * BYTES_PER_CHAR(*oldTB));
-
- if (newLineBuffer == NULL)
- {
- /*
- ** line buffer malloc failed, we can only increase the
- ** width to the current maximum...
- */
- *newCols = MAX_COLS(*oldTB);
- *newRows = MIN(*newRows, MAX_ROWS(*oldTB));
- break;
- }
- memcpy(newLineBuffer, BUFFER(newTL[i]), LENGTH(newTL[i]));
- free(BUFFER(newTL[i]));
- BUFFER(newTL[i]) = newLineBuffer;
- WRAPPED(newTL[i]) = False;
- }
- MAX_COLS(*oldTB) = *newCols;
- }
- COLS(*oldTB) = *newCols;
-
- /*
- ** now adjust the length of the buffer as necessary...
- */
- if (*newRows > MAX_ROWS(*oldTB))
- {
- /*
- ** the number of rows is increasing
- */
- newTL = (TermLine *) malloc((unsigned) *newRows *
- sizeof(TermLine));
- if (newTL != NULL)
- {
- /*
- ** the malloc succeeded, copy the old information, and
- ** then free it...
- */
- memcpy(newTL, LINES(*oldTB), sizeof(TermLine) *
- ROWS(*oldTB));
- free(LINES(*oldTB));
- LINES(*oldTB) = newTL;
-
- /*
- ** now initialize the new lines...
- */
- for (i = ROWS(*oldTB); i < *newRows; i++)
- {
- newTL[i] = (TermLine) malloc(SIZE_OF_LINE(*oldTB));
- if (newTL[i])
- {
- BUFFER(newTL[i]) = (termChar *)
- malloc((unsigned) COLS(*oldTB) *
- BYTES_PER_CHAR(*oldTB));
- if (BUFFER(newTL[i]) == NULL)
- {
- /*
- ** line buffer malloc failed...
- */
- *newRows = i;
- break;
- }
- LENGTH(newTL[i]) = 0;
- WIDTH(newTL[i]) = 0;
- WRAPPED(newTL[i]) = False;
- START_SELECTION(newTL[i]) = NON_SELECTION_COL;
- END_SELECTION(newTL[i]) = NON_SELECTION_COL;
- }
- else
- {
- /*
- ** line malloc failed, lets limit the
- ** number of rows
- */
- *newRows = i;
- break;
- }
- }
- /*
- ** its conceivable that MAX_ROWS could actually decrease if
- ** we are low on memory...
- */
- MAX_ROWS(*oldTB) = MIN(MAX_ROWS(*oldTB), *newRows);
- }
- else
- {
- /*
- ** the row buffer malloc failed, revert back to MAX_ROWS
- */
- *newRows = MAX_ROWS(*oldTB);
- }
- }
- ROWS(*oldTB) = *newRows;
- }
- }
- #ifdef NOCODE
- /*
- ** Create an enhancement block at the specified row and column.
- **
- ** NOTE: For the time being, we simply allocate an entire row's worth
- ** of enhancement blocks if it doesn't exist already. We may
- ** get smarter later on.
- */
- /*ARGSUSED*/
- Boolean
- _DtTermPrimBufferCreateEnhancement
- (
- const TermBuffer tb,
- const short row,
- const short col
- )
- {
- return(True);
- }
- /*
- ** Clear the enhancement block at the specified row and column.
- */
- static
- void
- clearEnhancement
- (
- const TermBuffer tb,
- const short row,
- const short col
- )
- {
- }
- #endif /* NOCODE */
- /*
- ** Call the emulations specific function to insert the desired number of
- ** enhancements at the specified position...
- **
- ** Assumptions:
- ** - insertCount has been properly clipped to insure that we don't go
- ** out of bounds
- **
- ** Notes:
- ** - results are undefined if this function is called when the specified
- ** column is at the end of the line.
- */
- static void
- insertEnhancements
- (
- const TermBuffer tb,
- const short row,
- const short col,
- const short insertCount,
- const Boolean insertFlag
- )
- {
- /*
- ** call the insert function only when it exists and we're in
- ** insert mode...
- */
- if (INSERT_ENH(tb))
- {
- (*INSERT_ENH(tb))(tb, row, col, insertCount, insertFlag);
- }
- }
- /*
- ** Free the enhancement block at the specified row and column.
- **
- ** NOTE: We may get smarter later on.
- */
- Boolean
- _DtTermPrimBufferFreeEnhancement
- (
- const TermBuffer tb,
- const short row,
- const short col
- )
- {
- return(True);
- }
- #ifdef BBA
- #pragma BBA_IGNORE
- #endif /*BBA*/
- static void
- RememberTermBuffer
- (
- const TermBuffer tb,
- TermLine **referenceLines,
- int *referenceLineCount
- )
- {
- int i1;
- int i2;
- *referenceLineCount = ROWS(tb);
- *referenceLines = (TermLine *) XtMalloc(ROWS(tb) * sizeof(TermLine));
- /* copy over the lines...
- */
- for (i1 = 0; i1 < ROWS(tb); i1++) {
- (*referenceLines)[i1] = LINE_OF_TBUF(tb, i1);
- }
- /* verify that they are all unique...
- */
- /* do a brute force check... */
- for (i1 = 0; i1 < ROWS(tb) - 1; i1++) {
- for (i2 = i1 + 1; i2 < ROWS(tb); i2++) {
- if ((*referenceLines)[i1] == (*referenceLines)[i2]) {
- (void) fprintf(stderr,
- ">>RememberTermBuffer: dup ptrs lines %d and %d\n",
- i1, i2);
- }
- }
- }
- }
- #ifdef BBA
- #pragma BBA_IGNORE
- #endif /*BBA*/
- static void
- CheckTermBuffer
- (
- const TermBuffer tb,
- TermLine *referenceLines,
- int referenceLineCount
- )
- {
- int i1;
- int i2;
- int matchedLine;
- if (referenceLineCount != ROWS(tb)) {
- for (i1 = 0; i1 < ROWS(tb); i1++) {
- matchedLine = -1;
- for (i2 = 0; i2 < ROWS(tb); i2++) {
- if (referenceLines[i1] == LINE_OF_TBUF(tb, i2)) {
- if (matchedLine == -1) {
- matchedLine = i2;
- } else {
- /* duplicate pointer... */
- fprintf(stderr,
- ">>CheckTermBuffer: duplicate pointer src=%d, dest=%d and %d\n",
- i1, matchedLine, i2);
- }
- }
- }
- if (matchedLine == -1) {
- fprintf(stderr,
- ">>CheckTermBuffer: dropped pointer src=%d\n", i1);
- }
- }
- }
-
- if (referenceLines) {
- XtFree((char *) referenceLines);
- }
- }
- short
- _DtTermPrimBufferGetText
- (
- const TermBuffer tb,
- const short row,
- const short col,
- const short width,
- char *buffer,
- const Boolean needWideChar
- )
- {
- short retLen;
- short colWidth;
- short mbLen;
- char *pChar;
- wchar_t *pwc;
- TermCharInfoRec charInfoFirst;
- TermCharInfoRec charInfoLast;
-
- if (!VALID_ROW(tb, row) || !VALID_COL(tb, col))
- {
- return(0);
- }
-
- colWidth = MIN(width, WIDTH(LINE_OF_TBUF(tb, row)) - col);
- if (colWidth > 0)
- {
- _DtTermPrimGetCharacterInfo(tb, row, col, &charInfoFirst);
- _DtTermPrimGetCharacterInfo(tb, row, col + colWidth - 1, &charInfoLast);
-
- if ((BYTES_PER_CHAR(tb) > 1) && !needWideChar)
- {
- /*
- ** our caller wants multi-byte characters...
- */
- retLen = 0;
- pChar = buffer;
-
- for (pwc = charInfoFirst.u.pwc; pwc <= charInfoLast.u.pwc; pwc++)
- {
- mbLen = wctomb(pChar, *pwc);
- if (mbLen > 0)
- {
- pChar += mbLen;
- retLen += mbLen;
- }
- else
- {
- fprintf(stderr, "_DtTermPrimBufferGetText: invalid wide char.\n");
- }
- }
- }
- else
- {
- retLen = charInfoLast.idx - charInfoFirst.idx + 1;
- memcpy(buffer, charInfoFirst.u.pc, retLen);
- }
- }
- else
- {
- /*
- ** colWidth == 0, there is nothing to return
- */
- retLen = 0;
- }
-
- return(retLen);
- }
- short
- _DtTermPrimBufferGetRows
- (
- const TermBuffer tb
- )
- {
- return(ROWS(tb));
- }
- short
- _DtTermPrimBufferGetCols
- (
- const TermBuffer tb
- )
- {
- return(COLS(tb));
- }
- void
- _DtTermPrimBufferSetLinks
- (
- const TermBuffer tb,
- const TermBuffer prev,
- const TermBuffer next
- )
- {
- PREV_BUFFER(tb) = prev;
- NEXT_BUFFER(tb) = next;
- }
- void
- _DtTermPrimBufferSetSelectInfo
- (
- const TermBuffer tb,
- const TermSelectInfo si
- )
- {
- BUFFER_SELECT_INFO(tb) = si;
- }
- /*
- ** Set the desired enhancement; simply call the emulator specific
- ** function.
- */
- int
- _DtTermPrimBufferSetEnhancement
- (
- const TermBuffer tb,
- const short row,
- const short col,
- const unsigned char id,
- const enhValue value
- )
- {
- if (SET_ENH(tb))
- {
- return((*SET_ENH(tb))(tb, row, col, id, value));
- }
- else
- {
- return(0);
- }
- }
- /*
- ** Get the enhancements for the desired row and column by calling the
- ** emulator specific routine.
- */
- Boolean
- _DtTermPrimBufferGetEnhancement
- (
- const TermBuffer tb,
- const short row,
- const short col,
- enhValue **values,
- short *count,
- const countSpec countWhich
- )
- {
- if (GET_ENH(tb))
- {
- return((*GET_ENH(tb))(tb, row, col, values, count, countWhich));
- }
- else
- {
- *count = WIDTH(LINE_OF_TBUF(tb, row));
- return(True);
- }
- }
- /*
- ** Return a pointer to the character at the specified row,col.
- */
- termChar *
- _DtTermPrimBufferGetCharacterPointer
- (
- const TermBuffer tb,
- const short row,
- const short col
- )
- {
- TermCharInfoRec charInfo;
-
- if (VALID_ROW(tb, row) && VALID_COL(tb, col))
- {
- _DtTermPrimGetCharacterInfo(tb, row, col, &charInfo);
- return((termChar *)charInfo.u.pc);
- }
- else
- {
- return(NULL);
- }
- }
- /*
- ** Get the character info for the specified character. If the
- ** specified column exceeds the width of the line, then make up
- ** some reasonable information, allowing the calling routine to
- ** continue in a reasonable fashion.
- **
- ** XXX: this doesn't get the emulator specific information yet (like
- ** enhancements
- */
- Boolean
- _DtTermPrimGetCharacterInfo
- (
- TermBuffer tb,
- short row,
- short col,
- TermCharInfo charInfo
- )
- {
- wchar_t *pwc;
- short charWidth;
- TermLine line;
- short totalWidth;
- if (!VALID_ROW(tb, row))
- {
- return(False);
- }
- line = LINE_OF_TBUF(tb, row);
- /*
- ** handle the easy cases first...
- */
- if (col >= WIDTH(line))
- {
- /*
- ** make up some reasonable values when col equals or
- ** exceeds the width of the line
- */
- charInfo->u.ptc = NULL;
- charInfo->idx = LENGTH(line);
- charInfo->len = BYTES_PER_CHAR(tb);
- charInfo->startCol = col;
- charInfo->width = 1;
- charInfo->enh = 0;
- charInfo->enhLen = 0;
- }
- else if (BYTES_PER_CHAR(tb) == 1)
- {
- /*
- ** this is easy in a 1 byte locale...
- */
- charInfo->u.ptc = BUFFER(line) + col;
- charInfo->idx = col;
- charInfo->len = BYTES_PER_CHAR(tb);
- charInfo->startCol = col;
- charInfo->width = 1;
- charInfo->enh = 0;
- charInfo->enhLen = 0;
- }
- else if (col == 0)
- {
- charInfo->u.pwc = (wchar_t *)BUFFER(line);
- charInfo->idx = 0;
- charInfo->len = BYTES_PER_CHAR(tb);
- charInfo->startCol = 0;
- charInfo->width = MAX(1, wcwidth(*((wchar_t *)BUFFER(line))));
- charInfo->enh = 0;
- charInfo->enhLen = 0;
- }
- else
- {
- /*
- ** not so easy when we're dealing with wchars...
- */
- if (col <= WIDTH(line) / 2)
- {
- /*
- ** work from left to right
- */
- totalWidth = 0;
- for (pwc = (wchar_t *)BUFFER(line);
- pwc < (wchar_t *)BUFFER(line) + LENGTH(line);
- pwc++)
- {
- charWidth = MAX(1, wcwidth(*pwc));
- totalWidth += charWidth;
- if (col < totalWidth)
- {
- /*
- ** we've found the character, now fill in the info...
- */
- charInfo->u.pwc = pwc;
- charInfo->idx = pwc - (wchar_t *)BUFFER(line);
- charInfo->startCol = totalWidth - charWidth;
- charInfo->width = charWidth;
- break;
- }
- }
- }
- else
- {
- /*
- ** work from right to left
- */
- totalWidth = WIDTH(line);
- for (pwc = (wchar_t *)BUFFER(line) + (LENGTH(line) - 1);
- pwc >= (wchar_t *)BUFFER(line);
- pwc--)
- {
- charWidth = MAX(1, wcwidth(*pwc));
- totalWidth -= charWidth;
- if (totalWidth <= col)
- {
- /*
- ** we've found the character, now fill in the info...
- */
- charInfo->u.pwc = pwc;
- charInfo->idx = pwc - (wchar_t *)BUFFER(line);
- if (totalWidth == col)
- {
- charInfo->startCol = col;
- }
- else
- {
- charInfo->startCol = col - 1;
- }
- charInfo->width = charWidth;
- break;
- }
- }
- }
- charInfo->len = BYTES_PER_CHAR(tb);
- charInfo->enh = 0;
- charInfo->enhLen = 0;
- }
- return(True);
- }
- /*
- ** Insert as many characters as possible at the specified row,col
- ** return a count of the number of characters bumped off the end of the line
- ** in 'returnCount' and a pointer to a buffer containing those characters
- ** 'returnChars'.
- **
- ** The the new width of the line is returned as the value of the function.
- */
- short
- _DtTermPrimBufferInsert
- (
- const TermBuffer tb,
- const short row,
- const short col,
- const termChar *newChars,
- short numChars,
- Boolean insertFlag, /* if TRUE, insert, else overwrite */
- termChar **returnChars, /* pointer to overflow buffer */
- short *returnCount /* count of characters in overflow buffer */
- )
- {
- short insertCount;
- short newWidth;
- short insertOverflow; /* # of newChars that would overflow */
- TermLine line;
- termChar *start;
- short copyCount; /* number of bytes to copy */
-
- if (!VALID_ROW(tb, row) || !VALID_COL(tb, col))
- {
- *returnCount = 0;
- return(0);
- }
-
- line = LINE_OF_TBUF(tb, row);
- #ifdef OLD_CODE
- /* before we modify the buffer, disown the selection... */
- (void) _DtTermPrimSelectDisownIfNecessary(WIDGET(tb));
- #endif /* OLD_CODE */
- /* if this line is part of the selection, disown the selection... */
- if (IS_IN_SELECTION(line, col, MAX_SELECTION_COL)) {
- (void) _DtTermPrimSelectDisown(WIDGET(tb));
- }
- if (BYTES_PER_CHAR(tb) > 1)
- {
- /*
- ** we do not handle multibyte characters here...
- */
- _DtTermPrimBufferInsertWc(tb, row, col, (wchar_t *)newChars,
- numChars, insertFlag,
- returnChars, returnCount);
- return 0;
- }
- if (WIDTH(line) < col)
- {
- /*
- ** We're adding characters past the current end of line,
- ** pad it out.
- */
- _DtTermPrimBufferPadLine(tb, row, col);
- }
-
- insertCount = MIN(numChars, COLS(tb) - col);
- copyCount = insertCount * BYTES_PER_CHAR(tb);
- start = BUFFER(line) + col;
-
- /*
- ** It doesn't matter if we're overwriting, or inserting at the end
- ** of the line, the result is the same...
- */
- if (col == WIDTH(line))
- {
- insertFlag = False;
- }
- if (insertFlag == False)
- {
- /*
- ** We're overwriting:
- ** - determine the new line width
- ** - put any extra new characters into the overflow buffer
- **
- ** The following will be done later:
- ** - copy the newChars into the line buffer
- ** - adjust line width (_DtTermPrimBufferSetLineWidth won't
- ** let the line get shorter)...
- */
- newWidth = MAX(WIDTH(line), col + insertCount);
- *returnCount = numChars - insertCount;
- if (*returnCount > 0)
- {
- memcpy(*returnChars, newChars + insertCount,
- *returnCount * BYTES_PER_CHAR(tb));
- }
- }
- else
- {
- /*
- ** we're inserting text in the middle of the line...
- */
- *returnCount = MAX(0, (WIDTH(line) + numChars) - COLS(tb));
- if (*returnCount > 0)
- {
- /*
- ** we'll have some overflow, figure out how many (if any)
- ** of the new characters will overflow and put them into
- ** the overflow buffer...
- */
- insertOverflow = numChars - insertCount;
- memcpy(*returnChars, newChars + insertCount,
- insertOverflow * BYTES_PER_CHAR(tb));
- /*
- ** copy the displaced characters from the line to the
- ** overflow buffer as well...
- */
- memcpy(*returnChars + insertOverflow, BUFFER(line) +
- (WIDTH(line) - MAX(0, *returnCount - insertOverflow)),
- MAX(0, *returnCount - insertOverflow)
- * BYTES_PER_CHAR(tb));
- }
- /*
- ** Any overflow has been taken care of, now it's time to make
- ** room for the new characters...
- */
- memmove(start + insertCount, start,
- MAX(0, WIDTH(line) - col - *returnCount));
- /*
- ** Compute the new line width...
- */
- newWidth = WIDTH(line) + insertCount;
- }
- /*
- ** Everything's ready:
- ** - put the characters into the line
- ** - adjust the line width (_DtTermPrimBufferSetLineWidth won't
- ** let the line get shorter)...
- ** - update the enhancements
- */
- memcpy(start, newChars, copyCount);
- _DtTermPrimBufferSetLineWidth(tb, row, newWidth);
- insertEnhancements(tb, row, col, insertCount, insertFlag);
- return(WIDTH(line));
- }
- /*
- ** Delete enough characters from the buffer to exceed width.
- **
- ** If returnChars != NULL then the deleted characters are returned
- ** in a buffer pointed to by returnChars. It is the responsibility
- ** of the calling function to XtFree the buffer containing returned
- ** characters when they are no longer needed.
- */
- void
- _DtTermPrimBufferDelete
- (
- TermBuffer tb,
- short *row,
- short *col,
- short *width,
- termChar **returnChars, /* pointer to delete buffer */
- short *returnCount /* count of bytes in delete buffer */
- )
- {
- int copyCount;
- TermLine line;
- short localRow;
- short localCol;
- TermCharInfoRec charInfo;
-
- if (!VALID_ROW(tb, *row) || !VALID_COL(tb, *col))
- {
- if (returnChars)
- {
- *returnChars = NULL;
- *returnCount = 0;
- }
- return;
- }
- line = LINE_OF_TBUF(tb, *row);
- #ifdef OLD_CODE
- /* before we modify the buffer, disown the selection... */
- (void) _DtTermPrimSelectDisownIfNecessary(WIDGET(tb));
- #endif /* OLD_CODE */
- /* if this line is part of the selection, disown the selection... */
- if (IS_IN_SELECTION(line, *col, MAX_SELECTION_COL)) {
- (void) _DtTermPrimSelectDisown(WIDGET(tb));
- }
- if (BYTES_PER_CHAR(tb) > 1)
- {
- /*
- ** we do not handle multibyte characters here...
- */
- _DtTermPrimBufferDeleteWc(tb, row, col, width, returnChars,
- returnCount);
- return;
- }
- localRow = *row;
- localCol = *col;
- *width = MAX(0, MIN(WIDTH(line) - localCol, *width));
- /*
- ** there are 4 cases of deleting a character from a line:
- ** Case 1:
- ** the cursor is past the end of the line (col >= WIDTH(line))
- **
- ** Case 2:
- ** the cursor is in the middle of the line (copyCount > 0)
- ** - move the remaining characters to the left
- ** - deleteEnhancement
- **
- ** Case 3:
- ** the cursor is at the end of the line (copyCount == 0 and
- ** col == WIDTH(line) - 1)
- ** - deleteEnhancement
- ** - adjust WIDTH and LENGTH
- */
- if (localCol >= WIDTH(line) || *width == 0)
- {
- /*
- ** Handle Case 1...
- */
- if (returnChars)
- {
- *returnChars = NULL;
- *returnCount = 0;
- }
- return;
- }
- _DtTermPrimGetCharacterInfo(tb, localRow, localCol, &charInfo);
-
- /*
- ** Save the current characters before we overwrite them...
- */
- if (returnChars != NULL)
- {
- *returnCount = (*width * BYTES_PER_CHAR(tb));
- *returnChars = (termChar *)XtMalloc(*returnCount);
- memcpy(*returnChars, charInfo.u.pc, *returnCount);
- }
- /*
- ** Cases 2 and 3 require that we delete the enhancement...
- */
- if (DELETE_ENH(tb))
- {
- (*DELETE_ENH(tb))(tb, localRow, localCol, *width);
- }
- copyCount = MAX(0, WIDTH(line) - *width - localCol);
- if (copyCount > 0)
- {
- /*
- ** handle case 2
- */
- memmove(charInfo.u.pc, charInfo.u.pc + *width,
- copyCount * BYTES_PER_CHAR(tb));
- }
- /*
- ** Case 2 and 3 require that we adjust the line width
- */
- WIDTH(line) -= *width;
- LENGTH(line) -= *width;
- }
- /*
- ** replace all characters between startCol, and stopCol with spaces,
- ** if startCol > stopCol, then simply return
- */
- void
- _DtTermPrimBufferErase
- (
- TermBuffer tb,
- short row,
- short startCol,
- short stopCol
- )
- {
- TermCharInfoRec charInfo;
- char *pchar;
- /*
- ** Make sure we have a valid row, and if we have a valid
- ** row, make sure that startCol is <= stopCol
- */
- if (!(VALID_ROW(tb, row)) || (startCol > stopCol))
- {
- return;
- }
- #ifdef OLD_CODE
- /* before we modify the buffer, disown the selection... */
- (void) _DtTermPrimSelectDisownIfNecessary(WIDGET(tb));
- #endif /* OLD_CODE */
- /* if this line is part of the selection, disown the selection... */
- if (IS_IN_SELECTION(LINE_OF_TBUF(tb, row), startCol, stopCol)) {
- (void) _DtTermPrimSelectDisown(WIDGET(tb));
- }
- if (BYTES_PER_CHAR(tb) > 1)
- {
- _DtTermPrimBufferEraseWc(tb, row, startCol, stopCol);
- }
- else
- {
- _DtTermPrimGetCharacterInfo(tb, row, startCol, &charInfo);
- pchar = charInfo.u.pc;
-
- _DtTermPrimGetCharacterInfo(tb, row, stopCol, &charInfo);
-
- /*
- ** replace the characters with spaces...
- */
- while(pchar <= charInfo.u.pc)
- {
- *pchar = ' ';
- pchar++;
- }
- }
- }
- /*
- ** Adjust the line width, (the line can never be shortened)
- */
- Boolean
- _DtTermPrimBufferSetLineWidth
- (
- const TermBuffer tb,
- const short row,
- short newWidth
- )
- {
- TermLine line;
-
- /*
- ** Make sure we have a valid row.
- */
- if (!VALID_ROW(tb, row))
- {
- return(False);
- }
- line = LINE_OF_TBUF(tb, row);
- #ifdef OLD_CODE
- /* before we modify the buffer, disown the selection... */
- (void) _DtTermPrimSelectDisownIfNecessary(WIDGET(tb));
- #endif /* OLD_CODE */
- /* if this line is part of the selection, disown the selection... */
- if (IS_IN_SELECTION(line, newWidth, MAX_SELECTION_COL)) {
- (void) _DtTermPrimSelectDisown(WIDGET(tb));
- }
- /*
- ** Clip the new width to the buffer width.
- */
- newWidth = MIN(newWidth, COLS(tb));
- /*
- ** Make sure we actually have something to do.
- */
- if (WIDTH(line) >= newWidth)
- {
- return(True);
- }
- WIDTH(line) = newWidth;
- if (BYTES_PER_CHAR(tb) == 1)
- {
- /*
- ** in single byte locales, we go ahead and set the line length too,
- ** it is the responsibility of wide-character routines to set the
- ** line length themselves...
- */
- LENGTH(line) = newWidth; /* works in single byte locales */
- }
-
- return(True);
- }
- /*
- ** the line length is the lesser of the actual length, or the length
- ** necessary to get to the buffer width
- ** (in the case that the buffer shrank after the line was full)
- */
- short
- _DtTermPrimBufferGetLineLength
- (
- const TermBuffer tb,
- const short row
- )
- {
- short retLen;
- short width;
- TermCharInfoRec charInfo;
-
- if (VALID_ROW(tb, row))
- {
- width = MIN(WIDTH(LINE_OF_TBUF(tb, row)), COLS(tb));
- if (width > 0)
- {
-
- (void)_DtTermPrimGetCharacterInfo(tb, row, width - 1, &charInfo);
-
- /*
- ** a line can not end on column 1 of 2. Note that we must
- ** add 1 to the column index to make it the line length...
- */
- if ((charInfo.width == 2) && (charInfo.startCol != width - 2)) {
- /* only half of charInfo.idx fits in the line, so drop
- * it...
- */
- retLen = charInfo.idx;
- } else {
- /* single column character or double column character that
- * fits on the line...
- */
- retLen = charInfo.idx + 1;
- }
- }
- else
- {
- retLen = 0;
- }
- }
- else
- {
- retLen = 0;
- }
-
- return(retLen);
- }
- /*
- ** the line width is the lesser of the actual width, or the buffer width
- ** (in the case that the buffer shrank after the line was full)
- */
- short
- _DtTermPrimBufferGetLineWidth
- (
- const TermBuffer tb,
- const short row
- )
- {
- short width = 0;
- TermCharInfoRec charInfo;
-
- if (VALID_ROW(tb, row))
- {
- width = MIN(WIDTH(LINE_OF_TBUF(tb, row)), COLS(tb));
- if (width > 0)
- {
-
- (void)_DtTermPrimGetCharacterInfo(tb, row, width - 1, &charInfo);
-
- /*
- ** a line can not end on column 1 of 2...
- */
- if ((charInfo.width == 2) && (charInfo.startCol != width - 2)) {
- /* only half of charInfo.idx fits in the line, so drop
- * it...
- */
- (void) width--;
- } else {
- /* single column character or double column character that
- * fits on the line...
- */
- }
- }
- }
-
- return(width);
- }
- /**************************************************************************
- * Function:
- * _DtTermPrimBufferMoveLockArea():
- * move locked screen memory up or down in the screen buffer.
- *
- * Parameters:
- * TermBuffer tb: term buffer to use
- * short dest: point to move the locked region to
- * short src: point to move the locked region from
- * short length: size of the locked region
- *
- * Returns:
- * <nothing>
- *
- * Notes:
- */
- void
- _DtTermPrimBufferMoveLockArea
- (
- const TermBuffer tb,
- const short dest,
- const short src,
- const short length
- )
- {
- TermLine lineCache[10];
- TermLine *holdLines = lineCache;
- TermLine *destPtr;
- TermLine *srcPtr;
- short cacheSize;
- short distance;
- int i;
- int refLineCount;
- TermLine *refLines;
- DebugF('B', 1, RememberTermBuffer(tb,&refLines,&refLineCount));
- /* don't bother if there is we are being asked to do nothing...
- */
- if ((length <= 0) || (dest == src))
- return;
- #ifdef OLD_CODE
- /* before we modify the buffer, disown the selection... */
- (void) _DtTermPrimSelectDisownIfNecessary(WIDGET(tb));
- #endif /* OLD_CODE */
- /* before we modify the buffer, check and see if the leading or
- * trailing edge of the buffer crosses the selection and if the
- * destination line crosses the selection. If it does, we need
- * to disown it...
- */
- /* leading edge of src... */
- if ((src > 0) &&
- IS_IN_SELECTION(LINE_OF_TBUF(tb, src - 1), MIN_SELECTION_COL,
- MAX_SELECTION_COL) &&
- IS_IN_SELECTION(LINE_OF_TBUF(tb, src), MIN_SELECTION_COL,
- MAX_SELECTION_COL)) {
- (void) _DtTermPrimSelectDisown(WIDGET(tb));
- }
- /* trailing edge of src... */
- if (((src + length) < ROWS(tb)) &&
- IS_IN_SELECTION(LINE_OF_TBUF(tb, src + length - 1),
- MIN_SELECTION_COL, MAX_SELECTION_COL) &&
- IS_IN_SELECTION(LINE_OF_TBUF(tb, src + length), MIN_SELECTION_COL,
- MAX_SELECTION_COL)) {
- (void) _DtTermPrimSelectDisown(WIDGET(tb));
- }
- /* destination... */
- if ((dest > 0) && IS_IN_SELECTION(LINE_OF_TBUF(tb, dest - 1),
- MIN_SELECTION_COL, MAX_SELECTION_COL) &&
- IS_IN_SELECTION(LINE_OF_TBUF(tb, dest),
- MIN_SELECTION_COL, MAX_SELECTION_COL)) {
- (void) _DtTermPrimSelectDisown(WIDGET(tb));
- }
-
- /* we need to save the line positions of the smaller of the length
- * of the chunk to move, or the distance to move the chunk.
- */
- distance = (dest > src) ? (dest - src) : (src - dest);
- cacheSize = MIN(length, distance);
- /* if we are moving more lines than will fit in the lineCache, we need
- * to malloc (and free) storage for the termLineRecs...
- */
- if (cacheSize > (sizeof(lineCache) / sizeof(lineCache[0]))) {
- holdLines = (TermLine *) XtMalloc(cacheSize * sizeof(TermLine));
- }
- /*
- ** clear the wrap flag for the line preceding the block to be
- ** moved, and the last line of the block to be moved
- */
- _DtTermPrimBufferSetLineWrapFlag(tb, src - 1, FALSE);
- _DtTermPrimBufferSetLineWrapFlag(tb, src + length, FALSE);
- /* cache them away... */
- if (distance > length) {
- /* save away the locked area... */
- destPtr = holdLines;
- srcPtr = &(LINE_OF_TBUF(tb, src));
- for (i = 0; i < length; i++) {
- *destPtr++ = *srcPtr++;
- }
- /* move the area above/below the locked area... */
- if (dest > src) {
- /* we are moving the locked area down, so we must move
- * the scroll area up...
- */
- destPtr = &(LINE_OF_TBUF(tb, src));
- srcPtr = &(LINE_OF_TBUF(tb, src + length));
- for (i = 0; i < distance; i++) {
- *destPtr++ = *srcPtr++;
- }
- } else {
- /* we are moving the locked area up, so we must move
- * the scroll area down...
- */
- destPtr = &(LINE_OF_TBUF(tb, src + length - 1));
- srcPtr = &(LINE_OF_TBUF(tb, src - 1));
- for (i = 0; i < distance; i++) {
- *destPtr-- = *srcPtr--;
- }
- }
- /* restore the cached lock area... */
- destPtr = &(LINE_OF_TBUF(tb, dest));
- srcPtr = holdLines;
- for (i = 0; i < length; i++) {
- *destPtr++ = *srcPtr++;
- }
- } else {
- /* save away the area we will move the lock area over...
- */
- if (dest > src) {
- /* moving it down. Save the area under the lock area...
- */
- destPtr = holdLines;
- srcPtr = &(LINE_OF_TBUF(tb, src + length));
- for (i = 0; i < distance; i++) {
- *destPtr++ = *srcPtr++;
- }
- /* move the lock area down... */
- destPtr = &(LINE_OF_TBUF(tb, dest + length - 1));
- srcPtr = &(LINE_OF_TBUF(tb, src + length - 1));
- for (i = 0; i < length; i++) {
- *destPtr-- = *srcPtr--;
- }
- /* restore the area under (that is now over) the lock area... */
- destPtr = &(LINE_OF_TBUF(tb, src));
- srcPtr = holdLines;
- for (i = 0; i < distance; i++) {
- *destPtr++ = *srcPtr++;
- }
- } else {
- /* moving it up. Save the area over the lock area...
- */
- destPtr = holdLines;
- srcPtr = &(LINE_OF_TBUF(tb, dest));
- for (i = 0; i < distance; i++) {
- *destPtr++ = *srcPtr++;
- }
- /* move the lock area up... */
- destPtr = &(LINE_OF_TBUF(tb, dest));
- srcPtr = &(LINE_OF_TBUF(tb, src));
- for (i = 0; i < length; i++) {
- *destPtr++ = *srcPtr++;
- }
- /* restore the area over (that is now under) the lock area... */
- destPtr = &(LINE_OF_TBUF(tb, dest + length));
- srcPtr = holdLines;
- for (i = 0; i < distance; i++) {
- *destPtr++ = *srcPtr++;
- }
- }
- }
- /* free up the holdLines (if we malloc'ed it)... */
- if (holdLines != lineCache) {
- (void) XtFree((char *) holdLines);
- }
- DebugF('B', 1, CheckTermBuffer(tb,refLines,refLineCount));
- }
- /**************************************************************************
- * Function:
- * _DtTermPrimBufferInsertLine(): insert one or more lines of text from
- * the end of the buffer below the insertion point, or from
- * the beginning of the buffer above the insertion point.
- *
- * Parameters:
- * TermBuffer tb: term buffer to insert end/begining into
- * short dest: point to insert below/above
- * short length: number of lines to insert
- * short src: source point of insertion
- *
- * Returns:
- * <nothing>
- *
- * Notes:
- */
- void
- _DtTermPrimBufferInsertLine
- (
- const TermBuffer tb,
- const short dest,
- const short length,
- const short src
- )
- {
- TermLine lineCache[10];
- TermLine *holdLines = lineCache;
- TermLine *destPtr;
- TermLine *srcPtr;
- short distance;
- int i;
- int refLineCount;
- TermLine *refLines;
- DebugF('B', 1, RememberTermBuffer(tb,&refLines,&refLineCount));
- /* don't bother if there is we are being asked to do nothing...
- */
- if (length <= 0)
- return;
- #ifdef OLD_CODE
- /* before we modify the buffer, disown the selection... */
- (void) _DtTermPrimSelectDisownIfNecessary(WIDGET(tb));
- #endif /* OLD_CODE */
- /* before we modify the buffer, check and see if the
- * destination line crosses the selection. If it does, we need
- * to disown it...
- */
- /* destination... */
- if (dest > src) {
- if (((dest + length) < ROWS(tb)) &&
- IS_IN_SELECTION(LINE_OF_TBUF(tb, dest + length),
- MIN_SELECTION_COL, MAX_SELECTION_COL) &&
- IS_IN_SELECTION(LINE_OF_TBUF(tb, dest + length + 1),
- MIN_SELECTION_COL, MAX_SELECTION_COL)) {
- (void) _DtTermPrimSelectDisown(WIDGET(tb));
- }
- } else {
- if (dest > 1) {
- if (IS_IN_SELECTION(LINE_OF_TBUF(tb, dest),
- MIN_SELECTION_COL, MAX_SELECTION_COL) &&
- IS_IN_SELECTION(LINE_OF_TBUF(tb, dest - 1),
- MIN_SELECTION_COL, MAX_SELECTION_COL)) {
- (void) _DtTermPrimSelectDisown(WIDGET(tb));
- }
- }
- }
- /* if we are being asked to move all (or more) the lines in the
- * buffer, then we can just clear them all out and return...
- */
- if (length >= ROWS(tb)) {
- for (i = 0; i < ROWS(tb); i++) {
- _DtTermPrimBufferClearLine(tb, i, 0);
- }
- return;
- }
- /* if dest and src match, we can just clear them out and return...
- */
- if (src == dest) {
- for (i = 0; (i < length) && ((i + dest) < ROWS(tb)); i++) {
- _DtTermPrimBufferClearLine(tb, src + i, 0);
- }
- return;
- }
- /* if we are moving more lines than will fit in the lineCache, we need
- * to malloc (and free) storage for the termLineRecs...
- */
- if (length > (sizeof(lineCache) / sizeof(lineCache[0]))) {
- holdLines = (TermLine *) XtMalloc(length * sizeof(TermLine));
- }
- if (dest > src) {
- /* our src is above the destination. Copy the lines to insert,
- * move the lines above the insertion pointer up, and insert
- * the saved lines...
- */
- /* save away the top length lines... */
- destPtr = holdLines;
- srcPtr = &(LINE_OF_TBUF(tb, src));
- for (i = 0; i < length; i++) {
- /* these lines will be cleared, so we don't need to track
- * movement of them...
- */
- *destPtr++ = *srcPtr++;
- }
- /* copy the lines above the insertion point up... */
- destPtr = &(LINE_OF_TBUF(tb, src));
- srcPtr = &(LINE_OF_TBUF(tb, src + length));
- for (i = src; i < dest - length + 1; i++) {
- *destPtr++ = *srcPtr++;
- }
- /* restore the saved lines above the insertion point... */
- destPtr = &(LINE_OF_TBUF(tb, dest - length + 1));
- srcPtr = holdLines;
- for (i = 0; i < length; i++) {
- *destPtr = *srcPtr;
- /* clear the line... */
- _DtTermPrimBufferClearLine(tb, dest - length + 1 + i, 0);
- *destPtr++;
- *srcPtr++;
- }
- #ifdef DONT_DO_THIS_ANY_MORE
- /* Adjust or disown selection */
- _DtTermPrimSelectDeleteLine(tb,length) ;
- #endif /* DONT_DO_THIS_ANY_MORE */
- } else {
- /* our src is below the destination. Copy the lines to insert,
- * move the lines below the insertion pointer down, and insert
- * the saved lines...
- */
- /* save away the bottom length lines... */
- destPtr = holdLines;
- srcPtr = &(LINE_OF_TBUF(tb, src));
- for (i = 0; i < length; i++) {
- *destPtr++ = *srcPtr++;
- }
- /* copy the lines below the insertion point down... */
- destPtr = &(LINE_OF_TBUF(tb, src + length - 1));
- srcPtr = &(LINE_OF_TBUF(tb, src - 1));
- for (i = 0; i < src - dest; i++) {
- *destPtr-- = *srcPtr--;
- }
- /* restore the saved lines below the insertion point... */
- destPtr = &(LINE_OF_TBUF(tb, dest));
- srcPtr = holdLines;
- for (i = 0; i < length; i++) {
- *destPtr = *srcPtr;
- /* clear the line... */
- _DtTermPrimBufferClearLine(tb, dest + i, 0);
- *destPtr++;
- *srcPtr++;
- }
- }
- /* free up the holdLines (if we malloc'ed it)... */
- if (holdLines != lineCache) {
- (void) XtFree((char *) holdLines);
- }
- DebugF('B', 1, CheckTermBuffer(tb,refLines,refLineCount));
- }
- /**************************************************************************
- * Function:
- * _DtTermPrimBufferInsertLineFromTB(): insert one or more lines
- * of text from the end of the buffer below the insertion
- * point, or from the beginning of the buffer above the
- * insertion point.
- *
- * Parameters:
- * TermBuffer tb: term buffer to insert end/begining into
- * short dest: point to insert below/above
- * short length: number of lines to insert
- * InsertSource: source of insertion (end or beginning)
- *
- * Returns:
- * <nothing>
- *
- * Notes:
- */
- void
- _DtTermPrimBufferInsertLineFromTB
- (
- const TermBuffer tb,
- const short dest,
- const short length,
- const InsertSource insertSource
- )
- {
- if (insertSource == insertFromTop) {
- (void) _DtTermPrimBufferInsertLine(tb, dest, length, 0);
- } else {
- (void) _DtTermPrimBufferInsertLine(tb, dest, length,
- ROWS(tb) - length);
- }
- }
- /**************************************************************************
- * Function:
- * _DtTermPrimBufferDeleteLine(): deletes one or more lines of text from
- * the deletion poing and sticks them at the end of the
- * line buffer. It does not clear the line. That is
- * normally done when the line is inserted.
- *
- * Parameters:
- * TermBuffer tb: term buffer to insert end/begining into
- * short source: point to insert below/above
- * short length: number of lines to insert
- * short lastUsedLine: number of last line in the buffer we need
- * to keep
- *
- * Returns:
- * <nothing>
- *
- * Notes:
- */
- void
- _DtTermPrimBufferDeleteLine
- (
- const TermBuffer tb,
- const short source,
- const short length,
- const short lastUsedRow
- )
- {
- TermLine lineCache[10];
- TermLine *holdLines = lineCache;
- TermLine *destPtr;
- TermLine *srcPtr;
- short copyLength;
- int i;
- int refLineCount;
- TermLine *refLines;
- DebugF('B', 1, RememberTermBuffer(tb,&refLines,&refLineCount));
- /* don't bother if there is we are being asked to do nothing...
- */
- if (length <= 0)
- return;
- /* if we are being asked to move the last usedLines, we don't have
- * to do anything either...
- */
- if (source + length >= lastUsedRow)
- return;
- #ifdef OLD_CODE
- /* before we modify the buffer, disown the selection... */
- (void) _DtTermPrimSelectDisownIfNecessary(WIDGET(tb));
- #endif /* OLD_CODE */
- /* if we are moving more lines than will fit in the lineCache, we need
- * to malloc (and free) storage for the termLineRecs...
- */
- if (length > (sizeof(lineCache) / sizeof(lineCache[0]))) {
- holdLines = (TermLine *) XtMalloc(length * sizeof(TermLine));
- }
- /* clear the deleted lines... */
- for (i = 0; i < length; i++) {
- (void) _DtTermPrimBufferClearLine(tb, source + i, 0);
- }
- #ifdef USE_MEMCPY
- (void) memcpy(holdLines, &(LINE_OF_TBUF(tb, source)), length *
- sizeof(TermLine));
- #else /* USE_MEMCPY */
- destPtr = holdLines;
- srcPtr = &(LINE_OF_TBUF(tb, source));
- for (i = 0; i < length; i++) {
- *destPtr++ = *srcPtr++;
- }
- #endif /* USE_MEMCPY */
- /* ripple up the lines... */
- copyLength = MAX(0, MIN(ROWS(tb), lastUsedRow) - source - length);
- if (copyLength > 0) {
- #ifdef USE_MEMCPY
- (void) memmove(&(LINE_OF_TBUF(tb, source)),
- &(LINE_OF_TBUF(tb, source + length)),
- copyLength * sizeof(TermLine));
- #else /* USE_MEMCPY */
- destPtr = &(LINE_OF_TBUF(tb, source));
- srcPtr = &(LINE_OF_TBUF(tb, source + length));
- for (i = 0; i < copyLength; i++) {
- *destPtr++ = *srcPtr++;
- }
- #endif /* USE_MEMCPY */
- }
- /* copy back the deleted (cached) lines... */
- #ifdef USE_MEMCPY
- (void) memcpy(&(LINE_OF_TBUF(tb, source + copyLength)), holdLines,
- length * sizeof(TermLine));
- #else /* USE_MEMCPY */
- destPtr = &(LINE_OF_TBUF(tb, source + copyLength));
- srcPtr = holdLines;
- for (i = 0; i < length; i++) {
- *destPtr++ = *srcPtr++;
- }
- #endif /* USE_MEMCPY */
- /* free up the holdLines (if we malloc'ed it)... */
- if (holdLines != lineCache) {
- (void) XtFree((char *) holdLines);
- }
- DebugF('B', 1, CheckTermBuffer(tb,refLines,refLineCount));
- }
- /*
- ** Pad the requested row from the current width to 'newWidth' with spaces...
- */
- void
- _DtTermPrimBufferPadLine
- (
- const TermBuffer tb,
- const short row,
- const short newWidth
- )
- {
- TermLine line;
-
- #ifdef OLD_CODE
- /* before we modify the buffer, disown the selection... */
- (void) _DtTermPrimSelectDisownIfNecessary(WIDGET(tb));
- #endif /* OLD_CODE */
- line = LINE_OF_TBUF(tb, row);
- /* if this line is part of the selection, disown the selection... */
- if (IS_IN_SELECTION(line, MIN(newWidth, WIDTH(line)),
- MAX(newWidth, WIDTH(line)))) {
- (void) _DtTermPrimSelectDisown(WIDGET(tb));
- }
- (void)memset(BUFFER(line) + WIDTH(line),
- 0x20, (newWidth - WIDTH(line)) * BYTES_PER_CHAR(tb));
- if (CLEAR_ENH(tb))
- {
- (*CLEAR_ENH(tb))(tb, row, WIDTH(line), newWidth - WIDTH(line));
- }
- _DtTermPrimBufferSetLineWidth(tb, row, newWidth);
- }
- /*
- ** Clear the line to the new width (just reset the line width).
- ** NOTES:
- ** We also clear the wrapped flag as well.
- */
- Boolean
- _DtTermPrimBufferClearLine
- (
- const TermBuffer tb,
- const short row,
- short newWidth
- )
- {
- TermLine line;
- #ifdef OLD_CODE
- /* before we modify the buffer, disown the selection... */
- (void) _DtTermPrimSelectDisownIfNecessary(WIDGET(tb));
- #endif /* OLD_CODE */
- /*
- ** handle multi-byte locales...
- */
- if (BYTES_PER_CHAR(tb) > 1)
- {
- return(_DtTermPrimBufferClearLineWc(tb, row, newWidth));
- }
-
- /*
- ** Some simple bounds checking.
- */
- if (!VALID_ROW(tb, row))
- {
- return(False);
- }
- line = LINE_OF_TBUF(tb, row);
- /* if this line is part of the selection, disown the selection... */
- if (IS_IN_SELECTION(line, MIN(newWidth, WIDTH(line)),
- MAX(newWidth, WIDTH(line)))) {
- (void) _DtTermPrimSelectDisown(WIDGET(tb));
- }
- /*
- ** Clip the new width to the buffer width.
- */
- newWidth = MIN(newWidth, COLS(tb));
- /*
- ** force width to the desired value
- **
- ** (We take the direct approach because _DtTermPrimBufferSetLineWidth
- ** doesn't allow the line width to decrease.)
- */
- if (newWidth < WIDTH(line))
- {
- /*
- ** Call the helper function if it exists
- */
- if (CLEAR_LINE(tb))
- {
- (*CLEAR_LINE(tb))(tb, row, newWidth);
- }
- WRAPPED(line) = False;
- WIDTH(line) = newWidth;
- LENGTH(line) = newWidth; /* this works in single-byte locales */
- }
- return(True);
- }
- short
- _DtTermPrimBufferGetNextTab
- (
- const TermBuffer tb,
- short col
- )
- {
- if (!VALID_COL(tb, col))
- {
- return(0);
- }
- /* find the next set tab stop... */
- for (col++; (col < COLS(tb)) && (!TABS(tb)[col]); col++)
- ;
- /* did we go to the end of the line w/out hitting one?... */
- if (col >= COLS(tb)) {
- return(0);
- } else {
- return(col);
- }
- }
- short
- _DtTermPrimBufferGetPreviousTab
- (
- const TermBuffer tb,
- short col
- )
- {
- if (!VALID_COL(tb, col - 1))
- {
- return(0);
- }
- /* find the next set tab stop... */
- for (col--; (col > 0) && (!TABS(tb)[col]); col--)
- ;
- /* we can just return col. If ther was not another tab stop, it will
- * be -1...
- */
- return(col);
- }
- Boolean
- _DtTermPrimBufferSetTab
- (
- const TermBuffer tb,
- const short col
- )
- {
- if (VALID_COL(tb, col))
- {
- TABS(tb)[col] = True;
- return(True);
- }
- return(False);
- }
- Boolean
- _DtTermPrimBufferClearTab
- (
- const TermBuffer tb,
- const short col
- )
- {
- if (VALID_COL(tb, col))
- {
- TABS(tb)[col] = False;
- return(True);
- }
- return(False);
- }
- Boolean
- _DtTermPrimBufferClearAllTabs
- (
- const TermBuffer tb
- )
- {
- (void) memset(TABS(tb), '\0', COLS(tb) * sizeof(Boolean));
- return(True);
- }
- /*
- ** Set the line wrap flag to the desired state.
- */
- void
- _DtTermPrimBufferSetLineWrapFlag
- (
- TermBuffer tb,
- short row,
- Boolean state
- )
- {
- if (VALID_ROW(tb, row))
- {
- WRAPPED(LINE_OF_TBUF(tb, row)) = state;
- }
- return;
- }
- /*
- ** Return the state of the line wrap flag.
- */
- Boolean
- _DtTermPrimBufferTestLineWrapFlag
- (
- TermBuffer tb,
- short row
- )
- {
- if (VALID_ROW(tb, row))
- {
- return(WRAPPED(LINE_OF_TBUF(tb, row)));
- }
- else
- {
- return(FALSE);
- }
- }
- /*
- ** Set the in selection flag to the desired state.
- */
- void
- _DtTermPrimBufferSetInSelectionFlag
- (
- TermBuffer tb,
- short row,
- TermLineSelection state
- )
- {
- if (VALID_ROW(tb, row))
- {
- if (state) {
- START_SELECTION(LINE_OF_TBUF(tb, row)) = state->selectionStart;
- END_SELECTION(LINE_OF_TBUF(tb, row)) = state->selectionEnd;
- } else {
- START_SELECTION(LINE_OF_TBUF(tb, row)) = NON_SELECTION_COL;
- END_SELECTION(LINE_OF_TBUF(tb, row)) = NON_SELECTION_COL;
- }
- }
- return;
- }
- /*
- ** Return the state of the in selection flag.
- */
- TermLineSelection
- _DtTermPrimBufferGetInSelectionFlag
- (
- TermBuffer tb,
- short row
- )
- {
- if (VALID_ROW(tb, row))
- {
- if ((START_SELECTION(LINE_OF_TBUF(tb, row)) != NON_SELECTION_COL) &&
- (END_SELECTION(LINE_OF_TBUF(tb, row)) != NON_SELECTION_COL)) {
- return(&IN_SELECTION(LINE_OF_TBUF(tb, row)));
- }
- }
- return((TermLineSelection) 0);
- }
- void
- _DtTermPrimBufferSetSelectLines
- (
- TermBuffer tb,
- short beginRow,
- short beginCol,
- short endRow,
- short endCol
- )
- {
- int i1;
- for (i1 = 0; i1 < ROWS(tb); i1++) {
- if ((i1 >= beginRow) && (i1 <= endRow)) {
- if (i1 == beginRow) {
- START_SELECTION(LINE_OF_TBUF(tb, i1)) = beginCol;
- } else {
- START_SELECTION(LINE_OF_TBUF(tb, i1)) = MIN_SELECTION_COL;
- }
- if (i1 == endRow) {
- END_SELECTION(LINE_OF_TBUF(tb, i1)) = endCol;
- } else {
- END_SELECTION(LINE_OF_TBUF(tb, i1)) = MAX_SELECTION_COL;
- }
- } else {
- START_SELECTION(LINE_OF_TBUF(tb, i1)) = NON_SELECTION_COL;
- END_SELECTION(LINE_OF_TBUF(tb, i1)) = NON_SELECTION_COL;
- }
- }
- }
- #if (defined(TEST) || defined(__CODECENTER__) || defined(DEBUG))
- static void
- _termBufferPrintLine
- (
- const TermBuffer tb,
- const short row
- )
- {
- TermLine line;
- termChar *pChar;
- short j;
- printf("Line: %d\n", row);
- line = LINE_OF_TBUF(tb, row];
- printf(" width: %3d\n", WIDTH(line));
- printf(" length: %3d\n", LENGTH(line));
- if (LENGTH(line) > 0)
- {
- printf(" buffer: <");
- pChar = BUFFER(line);
- for (j = 0; j < LENGTH(line); j++)
- {
- printf("%X", *pChar++);
- }
- printf(">\n");
- }
- }
- /*
- ** Print the contents of the TermBuffer.
- */
- static void
- _termBufferPrintBuffer
- (
- const TermBuffer tb
- )
- {
- short i;
- short j;
- short k;
- if (tb == NULL) {
- printf("TermBuffer has been freed.\n");
- return;
- }
- printf("TermBuffer dimensions:\n");
- printf(" rows: %d\n", ROWS(tb));
- printf(" cols: %d\n", COLS(tb));
- for (i = 0; i < ROWS(tb); i++)
- {
- _termBufferPrintLine(tb, i);
- }
- }
- #endif /* (defined(TEST) || defined(__CODECENTER__)) */
- #ifdef TEST
- /*
- ** Some simple tests of the termBuffer.
- */
- /* the following is to allow for a single main function in the code... */
- #define termBufMain main
- termBufMain()
- {
- const TermBuffer myTB;
- printf("Sizeof termEnhRec : %d\n", sizeof(struct _termEnhRec));
- printf("Sizeof termBufferRec : %d\n", sizeof(struct _TermBufferRec));
- myTB = _DtTermPrimBufferCreateBuffer(12, 80);
- _termBufferPrintBuffer(myTB);
- printf("[0,0] %d\n", _DtTermPrimBufferSetEnhancement(myTB, 0, 0, enhVideo, BLINK));
- _termBufferPrintEnhancement(myTB, 0, 0);
- printf("[0,1] %d\n", _DtTermPrimBufferSetEnhancement(myTB, 0, 1, enhVideo, INVERSE));
- _termBufferPrintEnhancement(myTB, 0, 0);
- _termBufferPrintEnhancement(myTB, 0, 1);
- printf("[0,9] %d\n", _DtTermPrimBufferSetEnhancement(myTB, 0, 9, enhVideo, UNDERLINE));
- _termBufferPrintEnhancement(myTB, 0, 0);
- _termBufferPrintEnhancement(myTB, 0, 1);
- _termBufferPrintEnhancement(myTB, 0, 9);
- printf("[0,6] %d\n", _DtTermPrimBufferSetEnhancement(myTB, 0, 6, enhVideo, HALF_BRIGHT));
- _termBufferPrintEnhancement(myTB, 0, 0);
- _termBufferPrintEnhancement(myTB, 0, 1);
- _termBufferPrintEnhancement(myTB, 0, 6);
- _termBufferPrintEnhancement(myTB, 0, 9);
- _termBufferPrintBuffer(myTB);
- _DtTermPrimBufferSetEnhancement(myTB, 10, 10, enhVideo, BLINK);
- _DtTermPrimBufferSetEnhancement(myTB, 10, 20, enhColor, 3);
- _termBufferPrintBuffer(myTB);
- _DtTermPrimBufferResizeBuffer(&myTB, 6, 40);
- _termBufferPrintBuffer(myTB);
- _DtTermPrimBufferSetEnhancement(myTB, 10, 10, enhVideo, BLINK);
- _DtTermPrimBufferResizeBuffer(&myTB, 12, 80);
- _termBufferPrintBuffer(myTB);
- _DtTermPrimBufferFreeBuffer(myTB);
- }
- #endif /* TEST */
|