2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these libraries and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
24 * (c) Copyright 1993, 1994, 1996 Hewlett-Packard Company *
25 * (c) Copyright 1993, 1994, 1996 International Business Machines Corp. *
26 * (c) Copyright 1993, 1994, 1996 Sun Microsystems, Inc. *
27 * (c) Copyright 1993, 1994, 1996 Novell, Inc. *
28 * (c) Copyright 1996 Digital Equipment Corporation. *
29 * (c) Copyright 1996 FUJITSU LIMITED. *
30 * (c) Copyright 1996 Hitachi. *
33 #define USE_MEMCPY /* use memcpy for line movement... */
38 #include "TermHeader.h" /* for MIN/MAX */
40 #include "TermPrimBuffer.h"
41 #include "TermPrimBufferP.h"
42 #include "TermPrimSelect.h"
43 #include "TermPrimDebug.h"
46 ** Allocate and initialize a new terminal buffer.
49 _DtTermPrimBufferCreateBuffer
54 const short sizeOfBuffer,
55 const short sizeOfLine,
66 ** malloc new a TermBuffer and an array of TermLine pointers
68 newTB = (TermBuffer) malloc(sizeOfBuffer);
69 /* the following MIN ensures that on systems where malloc of 0 returns
70 * NULL, we won't confuse a 0 size buffer with a malloc failure and an
73 newTL = (TermLine *) malloc((unsigned) MAX(rows, 1) * sizeof(TermLine));
78 ** clean up and leave if either of the previous malloc's failed.
88 return((TermBuffer)NULL);
92 ** malloc a tabs array...
94 tabs = (Boolean *) malloc((unsigned) cols * sizeof(Boolean));
100 ** clean up and leave if either of the previous malloc's failed.
102 return((TermBuffer)NULL);
105 ** initialize the tabs...
107 for (i = 0; i < cols; i++) {
108 tabs[i] = 0 == i % 8;
112 ** decide how many bytes to allocate per character...
114 BYTES_PER_CHAR(newTB) = MB_CUR_MAX == 1 ? 1 : sizeof(wchar_t);
117 ** setting debug flag m:1 forces us into wide char mode...
119 DebugF('m', 1, BYTES_PER_CHAR(newTB) = sizeof(wchar_t));
122 ** now malloc the individual lines...
124 for (i = 0; i < rows; i++)
126 newTL[i] = (TermLine) malloc(sizeOfLine);
129 BUFFER(newTL[i]) = (termChar *)
131 cols * BYTES_PER_CHAR(newTB));
133 if (BUFFER(newTL[i]) == NULL)
136 ** we couldn't malloc a line buffer
140 LENGTH(newTL[i]) = 0;
142 WRAPPED(newTL[i]) = False;
143 START_SELECTION(newTL[i]) = NON_SELECTION_COL;
144 END_SELECTION(newTL[i]) = NON_SELECTION_COL;
149 ** we couldn't malloc a line
156 ** If we were unable to malloc a full set of lines (i != rows),
157 ** then cleanup and leave.
163 for (j = 0; j < i; j++)
165 free(BUFFER(newTL[j]));
171 return((TermBuffer)NULL);
175 ** Initialize the new TermBuffer.
177 LINES(newTB) = newTL;
181 MAX_ROWS(newTB) = rows;
182 MAX_COLS(newTB) = cols;
183 SIZE_OF_BUFFER(newTB) = sizeOfBuffer;
184 SIZE_OF_LINE(newTB) = sizeOfLine;
185 SIZE_OF_ENH(newTB) = sizeOfEnh;
186 BUFFER_CREATE(newTB) = _DtTermPrimBufferCreateBuffer;
187 BUFFER_FREE(newTB) = NULL;
188 BUFFER_RESIZE(newTB) = NULL;
189 ENH_PROC(newTB) = NULL;
190 CLEAR_ENH(newTB) = NULL;
191 INSERT_ENH(newTB) = NULL;
192 DELETE_ENH(newTB) = NULL;
193 SET_ENH(newTB) = NULL;
194 GET_ENH(newTB) = NULL;
195 SET_LINE_WIDTH(newTB) = NULL;
196 CLEAR_LINE(newTB) = NULL;
197 NEXT_BUFFER(newTB) = NULL;
198 PREV_BUFFER(newTB) = NULL;
199 BUFFER_SELECT_INFO(newTB) = NULL;
205 _DtTermPrimBufferFreeBuffer
212 /* check for null buffer... */
218 ** Free any buffer-specific info first...
222 (*BUFFER_FREE(tb))(tb);
226 ** free the old buffer...
228 for (i = 0; i < MAX_ROWS(tb); i++)
230 (void) free(BUFFER(LINES(tb)[i]));
231 (void) free(LINES(tb)[i]);
233 (void) free(TABS(tb));
234 (void) free(LINES(tb));
239 ** Resize the terminal buffer, and try to be smart about it. If the buffer
240 ** shrinks, then simply adjust the size, no reallocs necessary (that way if
241 ** the user returns to the previous size, no data is lost).
244 ** Given this implementation, the memory allocated to the buffer will
245 ** never decrease it simply increases to accommodate the largest size
246 ** that has ever been requested.
249 _DtTermPrimBufferResizeBuffer
263 ** enforce some minimum size constraints...
265 *newRows = MAX(*newRows, 1);
266 *newCols = MAX(*newCols, 1);
269 ** the number of cols is increasing, start small and adjust the tab
272 if (*newCols > MAX_COLS(*oldTB))
274 tabs = (Boolean *) malloc((unsigned) *newCols * sizeof(Boolean));
277 /* copy over the tab stops... */
278 (void) memcpy(tabs, TABS(*oldTB), COLS(*oldTB) * sizeof(Boolean));
283 ** we need to extend the tab stops...
285 ** when tabWidth == 0, it has not been initialized. When
286 ** it is < 0, we have encountered unequal tab stops...
289 for (i = 0, thisTabWidth = 0; i < COLS(*oldTB); i++, thisTabWidth++)
295 /* first tab stop, set tabWidth... */
296 tabWidth = thisTabWidth;
298 else if (tabWidth != thisTabWidth)
300 /* tab stops differ, set tabWidth to -1... */
303 /* reset for next tab stop... */
311 ** we have consistent tab stops. Extend the buffer...
313 for (i = COLS(*oldTB); i < *newCols; i++)
315 TABS(*oldTB)[i] = (0 == (i % tabWidth));
321 ** we don't have consistent tab stops, so clear the rest...
323 (void) memset(&(TABS(*oldTB)[COLS(*oldTB)]), '\0',
324 (*newCols - COLS(*oldTB)) * sizeof(Boolean));
330 ** the malloc failed, adjust newCols and newRows and leave...
332 *newCols = MAX_COLS(*oldTB);
333 *newRows = MIN(*newRows, MAX_ROWS(*oldTB));
334 COLS(*oldTB) = *newCols;
335 ROWS(*oldTB) = *newRows;
342 ** take care of any shrinkage...
344 COLS(*oldTB) = *newCols;
348 ** Now give the resize helper a shot at resizing the buffer
350 if (BUFFER_RESIZE(*oldTB))
353 ** Call the resize helper function if it exists...
355 (*BUFFER_RESIZE(*oldTB))(*oldTB, newRows, newCols);
360 ** There is no helper function, do it ourselves...
362 ** This might cause some duplication of code, but due
363 ** to time constraints, it is the most expeditious route.
366 ** make any necessary width adjustments first...
369 ** We do not take any action if the new column width is less
370 ** than the current column width. It is the responsibility of
371 ** the rendering code to make sure that two column characters
372 ** are handled properly if the second column falls past the last
373 ** column in the window.
375 if (*newCols > MAX_COLS(*oldTB))
377 termChar *newLineBuffer;
380 ** now extend the line buffers for all lines, (even lines that
381 ** are not being used at the moment (ROWS < MAX_ROWS))...
383 newTL = LINES(*oldTB);
384 for (i = 0; i < MAX_ROWS(*oldTB); i++)
386 newLineBuffer = (termChar *) malloc((unsigned)
387 *newCols * BYTES_PER_CHAR(*oldTB));
389 if (newLineBuffer == NULL)
392 ** line buffer malloc failed, we can only increase the
393 ** width to the current maximum...
395 *newCols = MAX_COLS(*oldTB);
396 *newRows = MIN(*newRows, MAX_ROWS(*oldTB));
399 memcpy(newLineBuffer, BUFFER(newTL[i]), LENGTH(newTL[i]));
400 free(BUFFER(newTL[i]));
401 BUFFER(newTL[i]) = newLineBuffer;
402 WRAPPED(newTL[i]) = False;
404 MAX_COLS(*oldTB) = *newCols;
406 COLS(*oldTB) = *newCols;
409 ** now adjust the length of the buffer as necessary...
411 if (*newRows > MAX_ROWS(*oldTB))
414 ** the number of rows is increasing
416 newTL = (TermLine *) malloc((unsigned) *newRows *
421 ** the malloc succeeded, copy the old information, and
424 memcpy(newTL, LINES(*oldTB), sizeof(TermLine) *
427 LINES(*oldTB) = newTL;
430 ** now initialize the new lines...
432 for (i = ROWS(*oldTB); i < *newRows; i++)
434 newTL[i] = (TermLine) malloc(SIZE_OF_LINE(*oldTB));
437 BUFFER(newTL[i]) = (termChar *)
438 malloc((unsigned) COLS(*oldTB) *
439 BYTES_PER_CHAR(*oldTB));
440 if (BUFFER(newTL[i]) == NULL)
443 ** line buffer malloc failed...
448 LENGTH(newTL[i]) = 0;
450 WRAPPED(newTL[i]) = False;
451 START_SELECTION(newTL[i]) = NON_SELECTION_COL;
452 END_SELECTION(newTL[i]) = NON_SELECTION_COL;
457 ** line malloc failed, lets limit the
465 ** its conceivable that MAX_ROWS could actually decrease if
466 ** we are low on memory...
468 MAX_ROWS(*oldTB) = MIN(MAX_ROWS(*oldTB), *newRows);
473 ** the row buffer malloc failed, revert back to MAX_ROWS
475 *newRows = MAX_ROWS(*oldTB);
478 ROWS(*oldTB) = *newRows;
485 ** Create an enhancement block at the specified row and column.
487 ** NOTE: For the time being, we simply allocate an entire row's worth
488 ** of enhancement blocks if it doesn't exist already. We may
489 ** get smarter later on.
493 _DtTermPrimBufferCreateEnhancement
504 ** Clear the enhancement block at the specified row and column.
520 ** Call the emulations specific function to insert the desired number of
521 ** enhancements at the specified position...
524 ** - insertCount has been properly clipped to insure that we don't go
528 ** - results are undefined if this function is called when the specified
529 ** column is at the end of the line.
537 const short insertCount,
538 const Boolean insertFlag
542 ** call the insert function only when it exists and we're in
547 (*INSERT_ENH(tb))(tb, row, col, insertCount, insertFlag);
552 ** Free the enhancement block at the specified row and column.
554 ** NOTE: We may get smarter later on.
557 _DtTermPrimBufferFreeEnhancement
574 TermLine **referenceLines,
575 int *referenceLineCount
581 *referenceLineCount = ROWS(tb);
582 *referenceLines = (TermLine *) XtMalloc(ROWS(tb) * sizeof(TermLine));
584 /* copy over the lines...
586 for (i1 = 0; i1 < ROWS(tb); i1++) {
587 (*referenceLines)[i1] = LINE_OF_TBUF(tb, i1);
590 /* verify that they are all unique...
593 /* do a brute force check... */
594 for (i1 = 0; i1 < ROWS(tb) - 1; i1++) {
595 for (i2 = i1 + 1; i2 < ROWS(tb); i2++) {
596 if ((*referenceLines)[i1] == (*referenceLines)[i2]) {
597 (void) fprintf(stderr,
598 ">>RememberTermBuffer: dup ptrs lines %d and %d\n",
612 TermLine *referenceLines,
613 int referenceLineCount
620 if (referenceLineCount != ROWS(tb)) {
621 for (i1 = 0; i1 < ROWS(tb); i1++) {
623 for (i2 = 0; i2 < ROWS(tb); i2++) {
624 if (referenceLines[i1] == LINE_OF_TBUF(tb, i2)) {
625 if (matchedLine == -1) {
628 /* duplicate pointer... */
630 ">>CheckTermBuffer: duplicate pointer src=%d, dest=%d and %d\n",
631 i1, matchedLine, i2);
635 if (matchedLine == -1) {
637 ">>CheckTermBuffer: dropped pointer src=%d\n", i1);
642 if (referenceLines) {
643 XtFree((char *) referenceLines);
648 _DtTermPrimBufferGetText
655 const Boolean needWideChar
663 TermCharInfoRec charInfoFirst;
664 TermCharInfoRec charInfoLast;
666 if (!VALID_ROW(tb, row) || !VALID_COL(tb, col))
671 colWidth = MIN(width, WIDTH(LINE_OF_TBUF(tb, row)) - col);
674 _DtTermPrimGetCharacterInfo(tb, row, col, &charInfoFirst);
675 _DtTermPrimGetCharacterInfo(tb, row, col + colWidth - 1, &charInfoLast);
677 if ((BYTES_PER_CHAR(tb) > 1) && !needWideChar)
680 ** our caller wants multi-byte characters...
685 for (pwc = charInfoFirst.u.pwc; pwc <= charInfoLast.u.pwc; pwc++)
687 mbLen = wctomb(pChar, *pwc);
695 fprintf(stderr, "_DtTermPrimBufferGetText: invalid wide char.\n");
701 retLen = charInfoLast.idx - charInfoFirst.idx + 1;
702 memcpy(buffer, charInfoFirst.u.pc, retLen);
708 ** colWidth == 0, there is nothing to return
717 _DtTermPrimBufferGetRows
726 _DtTermPrimBufferGetCols
735 _DtTermPrimBufferSetLinks
738 const TermBuffer prev,
739 const TermBuffer next
742 PREV_BUFFER(tb) = prev;
743 NEXT_BUFFER(tb) = next;
747 _DtTermPrimBufferSetSelectInfo
750 const TermSelectInfo si
753 BUFFER_SELECT_INFO(tb) = si;
757 ** Set the desired enhancement; simply call the emulator specific
761 _DtTermPrimBufferSetEnhancement
766 const unsigned char id,
772 return((*SET_ENH(tb))(tb, row, col, id, value));
781 ** Get the enhancements for the desired row and column by calling the
782 ** emulator specific routine.
785 _DtTermPrimBufferGetEnhancement
792 const countSpec countWhich
797 return((*GET_ENH(tb))(tb, row, col, values, count, countWhich));
801 *count = WIDTH(LINE_OF_TBUF(tb, row));
807 ** Return a pointer to the character at the specified row,col.
810 _DtTermPrimBufferGetCharacterPointer
817 TermCharInfoRec charInfo;
819 if (VALID_ROW(tb, row) && VALID_COL(tb, col))
821 _DtTermPrimGetCharacterInfo(tb, row, col, &charInfo);
822 return((termChar *)charInfo.u.pc);
831 ** Get the character info for the specified character. If the
832 ** specified column exceeds the width of the line, then make up
833 ** some reasonable information, allowing the calling routine to
834 ** continue in a reasonable fashion.
836 ** XXX: this doesn't get the emulator specific information yet (like
840 _DtTermPrimGetCharacterInfo
845 TermCharInfo charInfo
853 if (!VALID_ROW(tb, row))
858 line = LINE_OF_TBUF(tb, row);
861 ** handle the easy cases first...
863 if (col >= WIDTH(line))
866 ** make up some reasonable values when col equals or
867 ** exceeds the width of the line
869 charInfo->u.ptc = NULL;
870 charInfo->idx = LENGTH(line);
871 charInfo->len = BYTES_PER_CHAR(tb);
872 charInfo->startCol = col;
875 charInfo->enhLen = 0;
877 else if (BYTES_PER_CHAR(tb) == 1)
880 ** this is easy in a 1 byte locale...
882 charInfo->u.ptc = BUFFER(line) + col;
884 charInfo->len = BYTES_PER_CHAR(tb);
885 charInfo->startCol = col;
888 charInfo->enhLen = 0;
892 charInfo->u.pwc = (wchar_t *)BUFFER(line);
894 charInfo->len = BYTES_PER_CHAR(tb);
895 charInfo->startCol = 0;
896 charInfo->width = MAX(1, wcwidth(*((wchar_t *)BUFFER(line))));
898 charInfo->enhLen = 0;
903 ** not so easy when we're dealing with wchars...
905 if (col <= WIDTH(line) / 2)
908 ** work from left to right
911 for (pwc = (wchar_t *)BUFFER(line);
912 pwc < (wchar_t *)BUFFER(line) + LENGTH(line);
915 charWidth = MAX(1, wcwidth(*pwc));
916 totalWidth += charWidth;
917 if (col < totalWidth)
920 ** we've found the character, now fill in the info...
922 charInfo->u.pwc = pwc;
923 charInfo->idx = pwc - (wchar_t *)BUFFER(line);
924 charInfo->startCol = totalWidth - charWidth;
925 charInfo->width = charWidth;
933 ** work from right to left
935 totalWidth = WIDTH(line);
936 for (pwc = (wchar_t *)BUFFER(line) + (LENGTH(line) - 1);
937 pwc >= (wchar_t *)BUFFER(line);
940 charWidth = MAX(1, wcwidth(*pwc));
941 totalWidth -= charWidth;
942 if (totalWidth <= col)
945 ** we've found the character, now fill in the info...
947 charInfo->u.pwc = pwc;
948 charInfo->idx = pwc - (wchar_t *)BUFFER(line);
949 if (totalWidth == col)
951 charInfo->startCol = col;
955 charInfo->startCol = col - 1;
957 charInfo->width = charWidth;
962 charInfo->len = BYTES_PER_CHAR(tb);
964 charInfo->enhLen = 0;
970 ** Insert as many characters as possible at the specified row,col
971 ** return a count of the number of characters bumped off the end of the line
972 ** in 'returnCount' and a pointer to a buffer containing those characters
975 ** The the new width of the line is returned as the value of the function.
978 _DtTermPrimBufferInsert
983 const termChar *newChars,
985 Boolean insertFlag, /* if TRUE, insert, else overwrite */
986 termChar **returnChars, /* pointer to overflow buffer */
987 short *returnCount /* count of characters in overflow buffer */
992 short insertOverflow; /* # of newChars that would overflow */
995 short copyCount; /* number of bytes to copy */
997 if (!VALID_ROW(tb, row) || !VALID_COL(tb, col))
1003 line = LINE_OF_TBUF(tb, row);
1006 /* before we modify the buffer, disown the selection... */
1007 (void) _DtTermPrimSelectDisownIfNecessary(WIDGET(tb));
1008 #endif /* OLD_CODE */
1010 /* if this line is part of the selection, disown the selection... */
1011 if (IS_IN_SELECTION(line, col, MAX_SELECTION_COL)) {
1012 (void) _DtTermPrimSelectDisown(WIDGET(tb));
1015 if (BYTES_PER_CHAR(tb) > 1)
1018 ** we do not handle multibyte characters here...
1020 _DtTermPrimBufferInsertWc(tb, row, col, (wchar_t *)newChars,
1021 numChars, insertFlag,
1022 returnChars, returnCount);
1026 if (WIDTH(line) < col)
1029 ** We're adding characters past the current end of line,
1032 _DtTermPrimBufferPadLine(tb, row, col);
1035 insertCount = MIN(numChars, COLS(tb) - col);
1036 copyCount = insertCount * BYTES_PER_CHAR(tb);
1037 start = BUFFER(line) + col;
1040 ** It doesn't matter if we're overwriting, or inserting at the end
1041 ** of the line, the result is the same...
1043 if (col == WIDTH(line))
1048 if (insertFlag == False)
1051 ** We're overwriting:
1052 ** - determine the new line width
1053 ** - put any extra new characters into the overflow buffer
1055 ** The following will be done later:
1056 ** - copy the newChars into the line buffer
1057 ** - adjust line width (_DtTermPrimBufferSetLineWidth won't
1058 ** let the line get shorter)...
1060 newWidth = MAX(WIDTH(line), col + insertCount);
1061 *returnCount = numChars - insertCount;
1062 if (*returnCount > 0)
1064 memcpy(*returnChars, newChars + insertCount,
1065 *returnCount * BYTES_PER_CHAR(tb));
1071 ** we're inserting text in the middle of the line...
1073 *returnCount = MAX(0, (WIDTH(line) + numChars) - COLS(tb));
1074 if (*returnCount > 0)
1077 ** we'll have some overflow, figure out how many (if any)
1078 ** of the new characters will overflow and put them into
1079 ** the overflow buffer...
1081 insertOverflow = numChars - insertCount;
1082 memcpy(*returnChars, newChars + insertCount,
1083 insertOverflow * BYTES_PER_CHAR(tb));
1086 ** copy the displaced characters from the line to the
1087 ** overflow buffer as well...
1089 memcpy(*returnChars + insertOverflow, BUFFER(line) +
1090 (WIDTH(line) - MAX(0, *returnCount - insertOverflow)),
1091 MAX(0, *returnCount - insertOverflow)
1092 * BYTES_PER_CHAR(tb));
1095 ** Any overflow has been taken care of, now it's time to make
1096 ** room for the new characters...
1098 memmove(start + insertCount, start,
1099 MAX(0, WIDTH(line) - col - *returnCount));
1102 ** Compute the new line width...
1104 newWidth = WIDTH(line) + insertCount;
1108 ** Everything's ready:
1109 ** - put the characters into the line
1110 ** - adjust the line width (_DtTermPrimBufferSetLineWidth won't
1111 ** let the line get shorter)...
1112 ** - update the enhancements
1114 memcpy(start, newChars, copyCount);
1115 _DtTermPrimBufferSetLineWidth(tb, row, newWidth);
1116 insertEnhancements(tb, row, col, insertCount, insertFlag);
1117 return(WIDTH(line));
1121 ** Delete enough characters from the buffer to exceed width.
1123 ** If returnChars != NULL then the deleted characters are returned
1124 ** in a buffer pointed to by returnChars. It is the responsibility
1125 ** of the calling function to XtFree the buffer containing returned
1126 ** characters when they are no longer needed.
1129 _DtTermPrimBufferDelete
1135 termChar **returnChars, /* pointer to delete buffer */
1136 short *returnCount /* count of bytes in delete buffer */
1143 TermCharInfoRec charInfo;
1146 if (!VALID_ROW(tb, *row) || !VALID_COL(tb, *col))
1150 *returnChars = NULL;
1156 line = LINE_OF_TBUF(tb, *row);
1159 /* before we modify the buffer, disown the selection... */
1160 (void) _DtTermPrimSelectDisownIfNecessary(WIDGET(tb));
1161 #endif /* OLD_CODE */
1163 /* if this line is part of the selection, disown the selection... */
1164 if (IS_IN_SELECTION(line, *col, MAX_SELECTION_COL)) {
1165 (void) _DtTermPrimSelectDisown(WIDGET(tb));
1168 if (BYTES_PER_CHAR(tb) > 1)
1171 ** we do not handle multibyte characters here...
1173 _DtTermPrimBufferDeleteWc(tb, row, col, width, returnChars,
1179 *width = MAX(0, MIN(WIDTH(line) - localCol, *width));
1182 ** there are 4 cases of deleting a character from a line:
1184 ** the cursor is past the end of the line (col >= WIDTH(line))
1187 ** the cursor is in the middle of the line (copyCount > 0)
1188 ** - move the remaining characters to the left
1189 ** - deleteEnhancement
1192 ** the cursor is at the end of the line (copyCount == 0 and
1193 ** col == WIDTH(line) - 1)
1194 ** - deleteEnhancement
1195 ** - adjust WIDTH and LENGTH
1197 if (localCol >= WIDTH(line) || *width == 0)
1204 *returnChars = NULL;
1210 _DtTermPrimGetCharacterInfo(tb, localRow, localCol, &charInfo);
1213 ** Save the current characters before we overwrite them...
1215 if (returnChars != NULL)
1217 *returnCount = (*width * BYTES_PER_CHAR(tb));
1218 *returnChars = (termChar *)XtMalloc(*returnCount);
1219 memcpy(*returnChars, charInfo.u.pc, *returnCount);
1223 ** Cases 2 and 3 require that we delete the enhancement...
1227 (*DELETE_ENH(tb))(tb, localRow, localCol, *width);
1230 copyCount = MAX(0, WIDTH(line) - *width - localCol);
1236 memmove(charInfo.u.pc, charInfo.u.pc + *width,
1237 copyCount * BYTES_PER_CHAR(tb));
1241 ** Case 2 and 3 require that we adjust the line width
1243 WIDTH(line) -= *width;
1244 LENGTH(line) -= *width;
1248 ** replace all characters between startCol, and stopCol with spaces,
1249 ** if startCol > stopCol, then simply return
1252 _DtTermPrimBufferErase
1260 TermCharInfoRec charInfo;
1264 ** Make sure we have a valid row, and if we have a valid
1265 ** row, make sure that startCol is <= stopCol
1267 if (!(VALID_ROW(tb, row)) || (startCol > stopCol))
1273 /* before we modify the buffer, disown the selection... */
1274 (void) _DtTermPrimSelectDisownIfNecessary(WIDGET(tb));
1275 #endif /* OLD_CODE */
1277 /* if this line is part of the selection, disown the selection... */
1278 if (IS_IN_SELECTION(LINE_OF_TBUF(tb, row), startCol, stopCol)) {
1279 (void) _DtTermPrimSelectDisown(WIDGET(tb));
1282 if (BYTES_PER_CHAR(tb) > 1)
1284 _DtTermPrimBufferEraseWc(tb, row, startCol, stopCol);
1288 _DtTermPrimGetCharacterInfo(tb, row, startCol, &charInfo);
1289 pchar = charInfo.u.pc;
1291 _DtTermPrimGetCharacterInfo(tb, row, stopCol, &charInfo);
1294 ** replace the characters with spaces...
1296 while(pchar <= charInfo.u.pc)
1306 ** Adjust the line width, (the line can never be shortened)
1309 _DtTermPrimBufferSetLineWidth
1311 const TermBuffer tb,
1319 ** Make sure we have a valid row.
1321 if (!VALID_ROW(tb, row))
1326 line = LINE_OF_TBUF(tb, row);
1329 /* before we modify the buffer, disown the selection... */
1330 (void) _DtTermPrimSelectDisownIfNecessary(WIDGET(tb));
1331 #endif /* OLD_CODE */
1333 /* if this line is part of the selection, disown the selection... */
1334 if (IS_IN_SELECTION(line, newWidth, MAX_SELECTION_COL)) {
1335 (void) _DtTermPrimSelectDisown(WIDGET(tb));
1339 ** Clip the new width to the buffer width.
1341 newWidth = MIN(newWidth, COLS(tb));
1344 ** Make sure we actually have something to do.
1346 if (WIDTH(line) >= newWidth)
1351 WIDTH(line) = newWidth;
1352 if (BYTES_PER_CHAR(tb) == 1)
1355 ** in single byte locales, we go ahead and set the line length too,
1356 ** it is the responsibility of wide-character routines to set the
1357 ** line length themselves...
1359 LENGTH(line) = newWidth; /* works in single byte locales */
1366 ** the line length is the lesser of the actual length, or the length
1367 ** necessary to get to the buffer width
1368 ** (in the case that the buffer shrank after the line was full)
1371 _DtTermPrimBufferGetLineLength
1373 const TermBuffer tb,
1379 TermCharInfoRec charInfo;
1381 if (VALID_ROW(tb, row))
1383 width = MIN(WIDTH(LINE_OF_TBUF(tb, row)), COLS(tb));
1387 (void)_DtTermPrimGetCharacterInfo(tb, row, width - 1, &charInfo);
1390 ** a line can not end on column 1 of 2. Note that we must
1391 ** add 1 to the column index to make it the line length...
1393 if ((charInfo.width == 2) && (charInfo.startCol != width - 2)) {
1394 /* only half of charInfo.idx fits in the line, so drop
1397 retLen = charInfo.idx;
1399 /* single column character or double column character that
1400 * fits on the line...
1402 retLen = charInfo.idx + 1;
1420 ** the line width is the lesser of the actual width, or the buffer width
1421 ** (in the case that the buffer shrank after the line was full)
1424 _DtTermPrimBufferGetLineWidth
1426 const TermBuffer tb,
1431 TermCharInfoRec charInfo;
1433 if (VALID_ROW(tb, row))
1435 width = MIN(WIDTH(LINE_OF_TBUF(tb, row)), COLS(tb));
1439 (void)_DtTermPrimGetCharacterInfo(tb, row, width - 1, &charInfo);
1442 ** a line can not end on column 1 of 2...
1444 if ((charInfo.width == 2) && (charInfo.startCol != width - 2)) {
1445 /* only half of charInfo.idx fits in the line, so drop
1450 /* single column character or double column character that
1451 * fits on the line...
1461 /**************************************************************************
1463 * _DtTermPrimBufferMoveLockArea():
1464 * move locked screen memory up or down in the screen buffer.
1467 * TermBuffer tb: term buffer to use
1468 * short dest: point to move the locked region to
1469 * short src: point to move the locked region from
1470 * short length: size of the locked region
1478 _DtTermPrimBufferMoveLockArea
1480 const TermBuffer tb,
1486 TermLine lineCache[10];
1487 TermLine *holdLines = lineCache;
1496 DebugF('B', 1, RememberTermBuffer(tb,&refLines,&refLineCount));
1498 /* don't bother if there is we are being asked to do nothing...
1500 if ((length <= 0) || (dest == src))
1504 /* before we modify the buffer, disown the selection... */
1505 (void) _DtTermPrimSelectDisownIfNecessary(WIDGET(tb));
1506 #endif /* OLD_CODE */
1508 /* before we modify the buffer, check and see if the leading or
1509 * trailing edge of the buffer crosses the selection and if the
1510 * destination line crosses the selection. If it does, we need
1513 /* leading edge of src... */
1515 IS_IN_SELECTION(LINE_OF_TBUF(tb, src - 1), MIN_SELECTION_COL,
1516 MAX_SELECTION_COL) &&
1517 IS_IN_SELECTION(LINE_OF_TBUF(tb, src), MIN_SELECTION_COL,
1518 MAX_SELECTION_COL)) {
1519 (void) _DtTermPrimSelectDisown(WIDGET(tb));
1522 /* trailing edge of src... */
1523 if (((src + length) < ROWS(tb)) &&
1524 IS_IN_SELECTION(LINE_OF_TBUF(tb, src + length - 1),
1525 MIN_SELECTION_COL, MAX_SELECTION_COL) &&
1526 IS_IN_SELECTION(LINE_OF_TBUF(tb, src + length), MIN_SELECTION_COL,
1527 MAX_SELECTION_COL)) {
1528 (void) _DtTermPrimSelectDisown(WIDGET(tb));
1531 /* destination... */
1532 if ((dest > 0) && IS_IN_SELECTION(LINE_OF_TBUF(tb, dest - 1),
1533 MIN_SELECTION_COL, MAX_SELECTION_COL) &&
1534 IS_IN_SELECTION(LINE_OF_TBUF(tb, dest),
1535 MIN_SELECTION_COL, MAX_SELECTION_COL)) {
1536 (void) _DtTermPrimSelectDisown(WIDGET(tb));
1539 /* we need to save the line positions of the smaller of the length
1540 * of the chunk to move, or the distance to move the chunk.
1542 distance = (dest > src) ? (dest - src) : (src - dest);
1543 cacheSize = MIN(length, distance);
1545 /* if we are moving more lines than will fit in the lineCache, we need
1546 * to malloc (and free) storage for the termLineRecs...
1548 if (cacheSize > (sizeof(lineCache) / sizeof(lineCache[0]))) {
1549 holdLines = (TermLine *) XtMalloc(cacheSize * sizeof(TermLine));
1553 ** clear the wrap flag for the line preceding the block to be
1554 ** moved, and the last line of the block to be moved
1556 _DtTermPrimBufferSetLineWrapFlag(tb, src - 1, FALSE);
1557 _DtTermPrimBufferSetLineWrapFlag(tb, src + length, FALSE);
1559 /* cache them away... */
1560 if (distance > length) {
1561 /* save away the locked area... */
1562 destPtr = holdLines;
1563 srcPtr = &(LINE_OF_TBUF(tb, src));
1565 for (i = 0; i < length; i++) {
1566 *destPtr++ = *srcPtr++;
1568 /* move the area above/below the locked area... */
1570 /* we are moving the locked area down, so we must move
1571 * the scroll area up...
1573 destPtr = &(LINE_OF_TBUF(tb, src));
1574 srcPtr = &(LINE_OF_TBUF(tb, src + length));
1575 for (i = 0; i < distance; i++) {
1576 *destPtr++ = *srcPtr++;
1579 /* we are moving the locked area up, so we must move
1580 * the scroll area down...
1582 destPtr = &(LINE_OF_TBUF(tb, src + length - 1));
1583 srcPtr = &(LINE_OF_TBUF(tb, src - 1));
1584 for (i = 0; i < distance; i++) {
1585 *destPtr-- = *srcPtr--;
1588 /* restore the cached lock area... */
1589 destPtr = &(LINE_OF_TBUF(tb, dest));
1591 for (i = 0; i < length; i++) {
1592 *destPtr++ = *srcPtr++;
1595 /* save away the area we will move the lock area over...
1598 /* moving it down. Save the area under the lock area...
1600 destPtr = holdLines;
1601 srcPtr = &(LINE_OF_TBUF(tb, src + length));
1602 for (i = 0; i < distance; i++) {
1603 *destPtr++ = *srcPtr++;
1605 /* move the lock area down... */
1606 destPtr = &(LINE_OF_TBUF(tb, dest + length - 1));
1607 srcPtr = &(LINE_OF_TBUF(tb, src + length - 1));
1608 for (i = 0; i < length; i++) {
1609 *destPtr-- = *srcPtr--;
1611 /* restore the area under (that is now over) the lock area... */
1612 destPtr = &(LINE_OF_TBUF(tb, src));
1614 for (i = 0; i < distance; i++) {
1615 *destPtr++ = *srcPtr++;
1618 /* moving it up. Save the area over the lock area...
1620 destPtr = holdLines;
1621 srcPtr = &(LINE_OF_TBUF(tb, dest));
1622 for (i = 0; i < distance; i++) {
1623 *destPtr++ = *srcPtr++;
1625 /* move the lock area up... */
1626 destPtr = &(LINE_OF_TBUF(tb, dest));
1627 srcPtr = &(LINE_OF_TBUF(tb, src));
1628 for (i = 0; i < length; i++) {
1629 *destPtr++ = *srcPtr++;
1631 /* restore the area over (that is now under) the lock area... */
1632 destPtr = &(LINE_OF_TBUF(tb, dest + length));
1634 for (i = 0; i < distance; i++) {
1635 *destPtr++ = *srcPtr++;
1640 /* free up the holdLines (if we malloc'ed it)... */
1641 if (holdLines != lineCache) {
1642 (void) XtFree((char *) holdLines);
1645 DebugF('B', 1, CheckTermBuffer(tb,refLines,refLineCount));
1649 /**************************************************************************
1651 * _DtTermPrimBufferInsertLine(): insert one or more lines of text from
1652 * the end of the buffer below the insertion point, or from
1653 * the beginning of the buffer above the insertion point.
1656 * TermBuffer tb: term buffer to insert end/begining into
1657 * short dest: point to insert below/above
1658 * short length: number of lines to insert
1659 * short src: source point of insertion
1667 _DtTermPrimBufferInsertLine
1669 const TermBuffer tb,
1675 TermLine lineCache[10];
1676 TermLine *holdLines = lineCache;
1684 DebugF('B', 1, RememberTermBuffer(tb,&refLines,&refLineCount));
1686 /* don't bother if there is we are being asked to do nothing...
1692 /* before we modify the buffer, disown the selection... */
1693 (void) _DtTermPrimSelectDisownIfNecessary(WIDGET(tb));
1694 #endif /* OLD_CODE */
1696 /* before we modify the buffer, check and see if the
1697 * destination line crosses the selection. If it does, we need
1700 /* destination... */
1702 if (((dest + length) < ROWS(tb)) &&
1703 IS_IN_SELECTION(LINE_OF_TBUF(tb, dest + length),
1704 MIN_SELECTION_COL, MAX_SELECTION_COL) &&
1705 IS_IN_SELECTION(LINE_OF_TBUF(tb, dest + length + 1),
1706 MIN_SELECTION_COL, MAX_SELECTION_COL)) {
1707 (void) _DtTermPrimSelectDisown(WIDGET(tb));
1711 if (IS_IN_SELECTION(LINE_OF_TBUF(tb, dest),
1712 MIN_SELECTION_COL, MAX_SELECTION_COL) &&
1713 IS_IN_SELECTION(LINE_OF_TBUF(tb, dest - 1),
1714 MIN_SELECTION_COL, MAX_SELECTION_COL)) {
1715 (void) _DtTermPrimSelectDisown(WIDGET(tb));
1720 /* if we are being asked to move all (or more) the lines in the
1721 * buffer, then we can just clear them all out and return...
1723 if (length >= ROWS(tb)) {
1724 for (i = 0; i < ROWS(tb); i++) {
1725 _DtTermPrimBufferClearLine(tb, i, 0);
1730 /* if dest and src match, we can just clear them out and return...
1733 for (i = 0; (i < length) && ((i + dest) < ROWS(tb)); i++) {
1734 _DtTermPrimBufferClearLine(tb, src + i, 0);
1739 /* if we are moving more lines than will fit in the lineCache, we need
1740 * to malloc (and free) storage for the termLineRecs...
1742 if (length > (sizeof(lineCache) / sizeof(lineCache[0]))) {
1743 holdLines = (TermLine *) XtMalloc(length * sizeof(TermLine));
1747 /* our src is above the destination. Copy the lines to insert,
1748 * move the lines above the insertion pointer up, and insert
1749 * the saved lines...
1752 /* save away the top length lines... */
1753 destPtr = holdLines;
1754 srcPtr = &(LINE_OF_TBUF(tb, src));
1755 for (i = 0; i < length; i++) {
1756 /* these lines will be cleared, so we don't need to track
1757 * movement of them...
1759 *destPtr++ = *srcPtr++;
1761 /* copy the lines above the insertion point up... */
1762 destPtr = &(LINE_OF_TBUF(tb, src));
1763 srcPtr = &(LINE_OF_TBUF(tb, src + length));
1764 for (i = src; i < dest - length + 1; i++) {
1765 *destPtr++ = *srcPtr++;
1767 /* restore the saved lines above the insertion point... */
1768 destPtr = &(LINE_OF_TBUF(tb, dest - length + 1));
1770 for (i = 0; i < length; i++) {
1772 /* clear the line... */
1773 _DtTermPrimBufferClearLine(tb, dest - length + 1 + i, 0);
1778 #ifdef DONT_DO_THIS_ANY_MORE
1779 /* Adjust or disown selection */
1780 _DtTermPrimSelectDeleteLine(tb,length) ;
1781 #endif /* DONT_DO_THIS_ANY_MORE */
1783 /* our src is below the destination. Copy the lines to insert,
1784 * move the lines below the insertion pointer down, and insert
1785 * the saved lines...
1787 /* save away the bottom length lines... */
1788 destPtr = holdLines;
1789 srcPtr = &(LINE_OF_TBUF(tb, src));
1790 for (i = 0; i < length; i++) {
1791 *destPtr++ = *srcPtr++;
1793 /* copy the lines below the insertion point down... */
1794 destPtr = &(LINE_OF_TBUF(tb, src + length - 1));
1795 srcPtr = &(LINE_OF_TBUF(tb, src - 1));
1796 for (i = 0; i < src - dest; i++) {
1797 *destPtr-- = *srcPtr--;
1799 /* restore the saved lines below the insertion point... */
1800 destPtr = &(LINE_OF_TBUF(tb, dest));
1802 for (i = 0; i < length; i++) {
1804 /* clear the line... */
1805 _DtTermPrimBufferClearLine(tb, dest + i, 0);
1811 /* free up the holdLines (if we malloc'ed it)... */
1812 if (holdLines != lineCache) {
1813 (void) XtFree((char *) holdLines);
1816 DebugF('B', 1, CheckTermBuffer(tb,refLines,refLineCount));
1820 /**************************************************************************
1822 * _DtTermPrimBufferInsertLineFromTB(): insert one or more lines
1823 * of text from the end of the buffer below the insertion
1824 * point, or from the beginning of the buffer above the
1828 * TermBuffer tb: term buffer to insert end/begining into
1829 * short dest: point to insert below/above
1830 * short length: number of lines to insert
1831 * InsertSource: source of insertion (end or beginning)
1839 _DtTermPrimBufferInsertLineFromTB
1841 const TermBuffer tb,
1844 const InsertSource insertSource
1847 if (insertSource == insertFromTop) {
1848 (void) _DtTermPrimBufferInsertLine(tb, dest, length, 0);
1850 (void) _DtTermPrimBufferInsertLine(tb, dest, length,
1855 /**************************************************************************
1857 * _DtTermPrimBufferDeleteLine(): deletes one or more lines of text from
1858 * the deletion poing and sticks them at the end of the
1859 * line buffer. It does not clear the line. That is
1860 * normally done when the line is inserted.
1863 * TermBuffer tb: term buffer to insert end/begining into
1864 * short source: point to insert below/above
1865 * short length: number of lines to insert
1866 * short lastUsedLine: number of last line in the buffer we need
1875 _DtTermPrimBufferDeleteLine
1877 const TermBuffer tb,
1880 const short lastUsedRow
1883 TermLine lineCache[10];
1884 TermLine *holdLines = lineCache;
1892 DebugF('B', 1, RememberTermBuffer(tb,&refLines,&refLineCount));
1894 /* don't bother if there is we are being asked to do nothing...
1898 /* if we are being asked to move the last usedLines, we don't have
1899 * to do anything either...
1901 if (source + length >= lastUsedRow)
1905 /* before we modify the buffer, disown the selection... */
1906 (void) _DtTermPrimSelectDisownIfNecessary(WIDGET(tb));
1907 #endif /* OLD_CODE */
1909 /* if we are moving more lines than will fit in the lineCache, we need
1910 * to malloc (and free) storage for the termLineRecs...
1912 if (length > (sizeof(lineCache) / sizeof(lineCache[0]))) {
1913 holdLines = (TermLine *) XtMalloc(length * sizeof(TermLine));
1916 /* clear the deleted lines... */
1917 for (i = 0; i < length; i++) {
1918 (void) _DtTermPrimBufferClearLine(tb, source + i, 0);
1922 (void) memcpy(holdLines, &(LINE_OF_TBUF(tb, source)), length *
1924 #else /* USE_MEMCPY */
1925 destPtr = holdLines;
1926 srcPtr = &(LINE_OF_TBUF(tb, source));
1927 for (i = 0; i < length; i++) {
1928 *destPtr++ = *srcPtr++;
1930 #endif /* USE_MEMCPY */
1932 /* ripple up the lines... */
1933 copyLength = MAX(0, MIN(ROWS(tb), lastUsedRow) - source - length);
1934 if (copyLength > 0) {
1936 (void) memmove(&(LINE_OF_TBUF(tb, source)),
1937 &(LINE_OF_TBUF(tb, source + length)),
1938 copyLength * sizeof(TermLine));
1939 #else /* USE_MEMCPY */
1940 destPtr = &(LINE_OF_TBUF(tb, source));
1941 srcPtr = &(LINE_OF_TBUF(tb, source + length));
1942 for (i = 0; i < copyLength; i++) {
1943 *destPtr++ = *srcPtr++;
1945 #endif /* USE_MEMCPY */
1948 /* copy back the deleted (cached) lines... */
1950 (void) memcpy(&(LINE_OF_TBUF(tb, source + copyLength)), holdLines,
1951 length * sizeof(TermLine));
1952 #else /* USE_MEMCPY */
1953 destPtr = &(LINE_OF_TBUF(tb, source + copyLength));
1955 for (i = 0; i < length; i++) {
1956 *destPtr++ = *srcPtr++;
1958 #endif /* USE_MEMCPY */
1960 /* free up the holdLines (if we malloc'ed it)... */
1961 if (holdLines != lineCache) {
1962 (void) XtFree((char *) holdLines);
1965 DebugF('B', 1, CheckTermBuffer(tb,refLines,refLineCount));
1969 ** Pad the requested row from the current width to 'newWidth' with spaces...
1972 _DtTermPrimBufferPadLine
1974 const TermBuffer tb,
1976 const short newWidth
1982 /* before we modify the buffer, disown the selection... */
1983 (void) _DtTermPrimSelectDisownIfNecessary(WIDGET(tb));
1984 #endif /* OLD_CODE */
1986 line = LINE_OF_TBUF(tb, row);
1988 /* if this line is part of the selection, disown the selection... */
1989 if (IS_IN_SELECTION(line, MIN(newWidth, WIDTH(line)),
1990 MAX(newWidth, WIDTH(line)))) {
1991 (void) _DtTermPrimSelectDisown(WIDGET(tb));
1994 (void)memset(BUFFER(line) + WIDTH(line),
1995 0x20, (newWidth - WIDTH(line)) * BYTES_PER_CHAR(tb));
1998 (*CLEAR_ENH(tb))(tb, row, WIDTH(line), newWidth - WIDTH(line));
2000 _DtTermPrimBufferSetLineWidth(tb, row, newWidth);
2004 ** Clear the line to the new width (just reset the line width).
2006 ** We also clear the wrapped flag as well.
2009 _DtTermPrimBufferClearLine
2011 const TermBuffer tb,
2019 /* before we modify the buffer, disown the selection... */
2020 (void) _DtTermPrimSelectDisownIfNecessary(WIDGET(tb));
2021 #endif /* OLD_CODE */
2024 ** handle multi-byte locales...
2026 if (BYTES_PER_CHAR(tb) > 1)
2028 return(_DtTermPrimBufferClearLineWc(tb, row, newWidth));
2032 ** Some simple bounds checking.
2034 if (!VALID_ROW(tb, row))
2039 line = LINE_OF_TBUF(tb, row);
2041 /* if this line is part of the selection, disown the selection... */
2042 if (IS_IN_SELECTION(line, MIN(newWidth, WIDTH(line)),
2043 MAX(newWidth, WIDTH(line)))) {
2044 (void) _DtTermPrimSelectDisown(WIDGET(tb));
2048 ** Clip the new width to the buffer width.
2050 newWidth = MIN(newWidth, COLS(tb));
2053 ** force width to the desired value
2055 ** (We take the direct approach because _DtTermPrimBufferSetLineWidth
2056 ** doesn't allow the line width to decrease.)
2058 if (newWidth < WIDTH(line))
2061 ** Call the helper function if it exists
2065 (*CLEAR_LINE(tb))(tb, row, newWidth);
2067 WRAPPED(line) = False;
2068 WIDTH(line) = newWidth;
2069 LENGTH(line) = newWidth; /* this works in single-byte locales */
2075 _DtTermPrimBufferGetNextTab
2077 const TermBuffer tb,
2081 if (!VALID_COL(tb, col))
2086 /* find the next set tab stop... */
2087 for (col++; (col < COLS(tb)) && (!TABS(tb)[col]); col++)
2090 /* did we go to the end of the line w/out hitting one?... */
2091 if (col >= COLS(tb)) {
2100 _DtTermPrimBufferGetPreviousTab
2102 const TermBuffer tb,
2106 if (!VALID_COL(tb, col - 1))
2111 /* find the next set tab stop... */
2112 for (col--; (col > 0) && (!TABS(tb)[col]); col--)
2115 /* we can just return col. If ther was not another tab stop, it will
2123 _DtTermPrimBufferSetTab
2125 const TermBuffer tb,
2129 if (VALID_COL(tb, col))
2131 TABS(tb)[col] = True;
2139 _DtTermPrimBufferClearTab
2141 const TermBuffer tb,
2145 if (VALID_COL(tb, col))
2147 TABS(tb)[col] = False;
2155 _DtTermPrimBufferClearAllTabs
2160 (void) memset(TABS(tb), '\0', COLS(tb) * sizeof(Boolean));
2165 ** Set the line wrap flag to the desired state.
2168 _DtTermPrimBufferSetLineWrapFlag
2175 if (VALID_ROW(tb, row))
2177 WRAPPED(LINE_OF_TBUF(tb, row)) = state;
2183 ** Return the state of the line wrap flag.
2186 _DtTermPrimBufferTestLineWrapFlag
2192 if (VALID_ROW(tb, row))
2194 return(WRAPPED(LINE_OF_TBUF(tb, row)));
2203 ** Set the in selection flag to the desired state.
2206 _DtTermPrimBufferSetInSelectionFlag
2210 TermLineSelection state
2213 if (VALID_ROW(tb, row))
2216 START_SELECTION(LINE_OF_TBUF(tb, row)) = state->selectionStart;
2217 END_SELECTION(LINE_OF_TBUF(tb, row)) = state->selectionEnd;
2219 START_SELECTION(LINE_OF_TBUF(tb, row)) = NON_SELECTION_COL;
2220 END_SELECTION(LINE_OF_TBUF(tb, row)) = NON_SELECTION_COL;
2227 ** Return the state of the in selection flag.
2230 _DtTermPrimBufferGetInSelectionFlag
2236 if (VALID_ROW(tb, row))
2238 if ((START_SELECTION(LINE_OF_TBUF(tb, row)) != NON_SELECTION_COL) &&
2239 (END_SELECTION(LINE_OF_TBUF(tb, row)) != NON_SELECTION_COL)) {
2240 return(&IN_SELECTION(LINE_OF_TBUF(tb, row)));
2243 return((TermLineSelection) 0);
2247 _DtTermPrimBufferSetSelectLines
2258 for (i1 = 0; i1 < ROWS(tb); i1++) {
2259 if ((i1 >= beginRow) && (i1 <= endRow)) {
2260 if (i1 == beginRow) {
2261 START_SELECTION(LINE_OF_TBUF(tb, i1)) = beginCol;
2263 START_SELECTION(LINE_OF_TBUF(tb, i1)) = MIN_SELECTION_COL;
2266 END_SELECTION(LINE_OF_TBUF(tb, i1)) = endCol;
2268 END_SELECTION(LINE_OF_TBUF(tb, i1)) = MAX_SELECTION_COL;
2271 START_SELECTION(LINE_OF_TBUF(tb, i1)) = NON_SELECTION_COL;
2272 END_SELECTION(LINE_OF_TBUF(tb, i1)) = NON_SELECTION_COL;
2277 #if (defined(TEST) || defined(__CODECENTER__) || defined(DEBUG))
2279 _termBufferPrintLine
2281 const TermBuffer tb,
2289 printf("Line: %d\n", row);
2291 line = LINE_OF_TBUF(tb, row];
2292 printf(" width: %3d\n", WIDTH(line));
2293 printf(" length: %3d\n", LENGTH(line));
2294 if (LENGTH(line) > 0)
2296 printf(" buffer: <");
2297 pChar = BUFFER(line);
2298 for (j = 0; j < LENGTH(line); j++)
2300 printf("%X", *pChar++);
2307 ** Print the contents of the TermBuffer.
2310 _termBufferPrintBuffer
2320 printf("TermBuffer has been freed.\n");
2324 printf("TermBuffer dimensions:\n");
2325 printf(" rows: %d\n", ROWS(tb));
2326 printf(" cols: %d\n", COLS(tb));
2328 for (i = 0; i < ROWS(tb); i++)
2330 _termBufferPrintLine(tb, i);
2333 #endif /* (defined(TEST) || defined(__CODECENTER__)) */
2337 ** Some simple tests of the termBuffer.
2339 /* the following is to allow for a single main function in the code... */
2340 #define termBufMain main
2343 const TermBuffer myTB;
2345 printf("Sizeof termEnhRec : %d\n", sizeof(struct _termEnhRec));
2346 printf("Sizeof termBufferRec : %d\n", sizeof(struct _TermBufferRec));
2348 myTB = _DtTermPrimBufferCreateBuffer(12, 80);
2349 _termBufferPrintBuffer(myTB);
2351 printf("[0,0] %d\n", _DtTermPrimBufferSetEnhancement(myTB, 0, 0, enhVideo, BLINK));
2352 _termBufferPrintEnhancement(myTB, 0, 0);
2353 printf("[0,1] %d\n", _DtTermPrimBufferSetEnhancement(myTB, 0, 1, enhVideo, INVERSE));
2354 _termBufferPrintEnhancement(myTB, 0, 0);
2355 _termBufferPrintEnhancement(myTB, 0, 1);
2356 printf("[0,9] %d\n", _DtTermPrimBufferSetEnhancement(myTB, 0, 9, enhVideo, UNDERLINE));
2357 _termBufferPrintEnhancement(myTB, 0, 0);
2358 _termBufferPrintEnhancement(myTB, 0, 1);
2359 _termBufferPrintEnhancement(myTB, 0, 9);
2360 printf("[0,6] %d\n", _DtTermPrimBufferSetEnhancement(myTB, 0, 6, enhVideo, HALF_BRIGHT));
2361 _termBufferPrintEnhancement(myTB, 0, 0);
2362 _termBufferPrintEnhancement(myTB, 0, 1);
2363 _termBufferPrintEnhancement(myTB, 0, 6);
2364 _termBufferPrintEnhancement(myTB, 0, 9);
2365 _termBufferPrintBuffer(myTB);
2367 _DtTermPrimBufferSetEnhancement(myTB, 10, 10, enhVideo, BLINK);
2368 _DtTermPrimBufferSetEnhancement(myTB, 10, 20, enhColor, 3);
2369 _termBufferPrintBuffer(myTB);
2371 _DtTermPrimBufferResizeBuffer(&myTB, 6, 40);
2372 _termBufferPrintBuffer(myTB);
2374 _DtTermPrimBufferSetEnhancement(myTB, 10, 10, enhVideo, BLINK);
2375 _DtTermPrimBufferResizeBuffer(&myTB, 12, 80);
2376 _termBufferPrintBuffer(myTB);
2378 _DtTermPrimBufferFreeBuffer(myTB);