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 librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
24 #ifdef VERBOSE_REV_INFO
25 static char rcs_id[] = "$XConsortium: TermPrimBuffer.c /main/1 1996/04/21 19:16:49 drk $";
26 #endif /* VERBOSE_REV_INFO */
30 * (c) Copyright 1993, 1994, 1996 Hewlett-Packard Company *
31 * (c) Copyright 1993, 1994, 1996 International Business Machines Corp. *
32 * (c) Copyright 1993, 1994, 1996 Sun Microsystems, Inc. *
33 * (c) Copyright 1993, 1994, 1996 Novell, Inc. *
34 * (c) Copyright 1996 Digital Equipment Corporation. *
35 * (c) Copyright 1996 FUJITSU LIMITED. *
36 * (c) Copyright 1996 Hitachi. *
39 #define USE_MEMCPY /* use memcpy for line movement... */
43 #include "TermHeader.h" /* for MIN/MAX */
45 #include "TermPrimBuffer.h"
46 #include "TermPrimBufferP.h"
47 #include "TermPrimSelect.h"
48 #include "TermPrimDebug.h"
51 ** Allocate and initialize a new terminal buffer.
54 _DtTermPrimBufferCreateBuffer
59 const short sizeOfBuffer,
60 const short sizeOfLine,
71 ** malloc new a TermBuffer and an array of TermLine pointers
73 newTB = (TermBuffer) malloc(sizeOfBuffer);
74 /* the following MIN ensures that on systems where malloc of 0 returns
75 * NULL, we won't confuse a 0 size buffer with a malloc failure and an
78 newTL = (TermLine *) malloc((unsigned) MAX(rows, 1) * sizeof(TermLine));
83 ** clean up and leave if either of the previous malloc's failed.
93 return((TermBuffer)NULL);
97 ** malloc a tabs array...
99 tabs = (Boolean *) malloc((unsigned) cols * sizeof(Boolean));
105 ** clean up and leave if either of the previous malloc's failed.
107 return((TermBuffer)NULL);
110 ** initialize the tabs...
112 for (i = 0; i < cols; i++) {
113 tabs[i] = 0 == i % 8;
117 ** decide how many bytes to allocate per character...
119 BYTES_PER_CHAR(newTB) = MB_CUR_MAX == 1 ? 1 : sizeof(wchar_t);
122 ** setting debug flag m:1 forces us into wide char mode...
124 DebugF('m', 1, BYTES_PER_CHAR(newTB) = sizeof(wchar_t));
127 ** now malloc the individual lines...
129 for (i = 0; i < rows; i++)
131 newTL[i] = (TermLine) malloc(sizeOfLine);
134 BUFFER(newTL[i]) = (termChar *)
136 cols * BYTES_PER_CHAR(newTB));
138 if (BUFFER(newTL[i]) == NULL)
141 ** we couldn't malloc a line buffer
145 LENGTH(newTL[i]) = 0;
147 WRAPPED(newTL[i]) = False;
148 START_SELECTION(newTL[i]) = NON_SELECTION_COL;
149 END_SELECTION(newTL[i]) = NON_SELECTION_COL;
154 ** we couldn't malloc a line
161 ** If we were unable to malloc a full set of lines (i != rows),
162 ** then cleanup and leave.
168 for (j = 0; j < i; j++)
170 free(BUFFER(newTL[j]));
176 return((TermBuffer)NULL);
180 ** Initialize the new TermBuffer.
182 LINES(newTB) = newTL;
186 MAX_ROWS(newTB) = rows;
187 MAX_COLS(newTB) = cols;
188 SIZE_OF_BUFFER(newTB) = sizeOfBuffer;
189 SIZE_OF_LINE(newTB) = sizeOfLine;
190 SIZE_OF_ENH(newTB) = sizeOfEnh;
191 BUFFER_CREATE(newTB) = _DtTermPrimBufferCreateBuffer;
192 BUFFER_FREE(newTB) = NULL;
193 BUFFER_RESIZE(newTB) = NULL;
194 ENH_PROC(newTB) = NULL;
195 CLEAR_ENH(newTB) = NULL;
196 INSERT_ENH(newTB) = NULL;
197 DELETE_ENH(newTB) = NULL;
198 SET_ENH(newTB) = NULL;
199 GET_ENH(newTB) = NULL;
200 SET_LINE_WIDTH(newTB) = NULL;
201 CLEAR_LINE(newTB) = NULL;
202 NEXT_BUFFER(newTB) = NULL;
203 PREV_BUFFER(newTB) = NULL;
204 BUFFER_SELECT_INFO(newTB) = NULL;
210 _DtTermPrimBufferFreeBuffer
217 /* check for null buffer... */
223 ** Free any buffer-specific info first...
227 (*BUFFER_FREE(tb))(tb);
231 ** free the old buffer...
233 for (i = 0; i < MAX_ROWS(tb); i++)
235 (void) free(BUFFER(LINES(tb)[i]));
236 (void) free(LINES(tb)[i]);
238 (void) free(TABS(tb));
239 (void) free(LINES(tb));
244 ** Resize the terminal buffer, and try to be smart about it. If the buffer
245 ** shrinks, then simply adjust the size, no reallocs necessary (that way if
246 ** the user returns to the previous size, no data is lost).
249 ** Given this implementation, the memory allocated to the buffer will
250 ** never decrease it simply increases to accomodate the largest size
251 ** that has ever been requested.
254 _DtTermPrimBufferResizeBuffer
268 ** enforce some minimum size constraints...
270 *newRows = MAX(*newRows, 1);
271 *newCols = MAX(*newCols, 1);
274 ** the number of cols is increasing, start small and adjust the tab
277 if (*newCols > MAX_COLS(*oldTB))
279 tabs = (Boolean *) malloc((unsigned) *newCols * sizeof(Boolean));
282 /* copy over the tab stops... */
283 (void) memcpy(tabs, TABS(*oldTB), COLS(*oldTB) * sizeof(Boolean));
288 ** we need to extend the tab stops...
290 ** when tabWidth == 0, it has not been initialized. When
291 ** it is < 0, we have encountered unequal tab stops...
294 for (i = 0, thisTabWidth = 0; i < COLS(*oldTB); i++, thisTabWidth++)
300 /* first tab stop, set tabWidth... */
301 tabWidth = thisTabWidth;
303 else if (tabWidth != thisTabWidth)
305 /* tab stops differ, set tabWidth to -1... */
308 /* reset for next tab stop... */
316 ** we have consistent tab stops. Extend the buffer...
318 for (i = COLS(*oldTB); i < *newCols; i++)
320 TABS(*oldTB)[i] = (0 == (i % tabWidth));
326 ** we don't have consistent tab stops, so clear the rest...
328 (void) memset(&(TABS(*oldTB)[COLS(*oldTB)]), '\0',
329 (*newCols - COLS(*oldTB)) * sizeof(Boolean));
335 ** the malloc failed, adjust newCols and newRows and leave...
337 *newCols = MAX_COLS(*oldTB);
338 *newRows = MIN(*newRows, MAX_ROWS(*oldTB));
339 COLS(*oldTB) = *newCols;
340 ROWS(*oldTB) = *newRows;
347 ** take care of any shrinkage...
349 COLS(*oldTB) = *newCols;
353 ** Now give the resize helper a shot at resizing the buffer
355 if (BUFFER_RESIZE(*oldTB))
358 ** Call the resize helper function if it exists...
360 (*BUFFER_RESIZE(*oldTB))(*oldTB, newRows, newCols);
365 ** There is no helper function, do it ourselves...
367 ** This might cause some duplication of code, but due
368 ** to time constraints, it is the most expeditious route.
371 ** make any necessary width adjustments first...
374 ** We do not take any action if the new column width is less
375 ** than the current column width. It is the responsibility of
376 ** the rendering code to make sure that two column characters
377 ** are handled properly if the second column falls past the last
378 ** column in the window.
380 if (*newCols > MAX_COLS(*oldTB))
382 termChar *newLineBuffer;
385 ** now extend the line buffers for all lines, (even lines that
386 ** are not being used at the moment (ROWS < MAX_ROWS))...
388 newTL = LINES(*oldTB);
389 for (i = 0; i < MAX_ROWS(*oldTB); i++)
391 newLineBuffer = (termChar *) malloc((unsigned)
392 *newCols * BYTES_PER_CHAR(*oldTB));
394 if (newLineBuffer == NULL)
397 ** line buffer malloc failed, we can only increase the
398 ** width to the current maximum...
400 *newCols = MAX_COLS(*oldTB);
401 *newRows = MIN(*newRows, MAX_ROWS(*oldTB));
404 memcpy(newLineBuffer, BUFFER(newTL[i]), LENGTH(newTL[i]));
405 free(BUFFER(newTL[i]));
406 BUFFER(newTL[i]) = newLineBuffer;
407 WRAPPED(newTL[i]) = False;
409 MAX_COLS(*oldTB) = *newCols;
411 COLS(*oldTB) = *newCols;
414 ** now adjust the length of the buffer as necessary...
416 if (*newRows > MAX_ROWS(*oldTB))
419 ** the number of rows is increasing
421 newTL = (TermLine *) malloc((unsigned) *newRows *
426 ** the malloc succeeded, copy the old information, and
429 memcpy(newTL, LINES(*oldTB), sizeof(TermLine) *
432 LINES(*oldTB) = newTL;
435 ** now initialize the new lines...
437 for (i = ROWS(*oldTB); i < *newRows; i++)
439 newTL[i] = (TermLine) malloc(SIZE_OF_LINE(*oldTB));
442 BUFFER(newTL[i]) = (termChar *)
443 malloc((unsigned) COLS(*oldTB) *
444 BYTES_PER_CHAR(*oldTB));
445 if (BUFFER(newTL[i]) == NULL)
448 ** line buffer malloc failed...
453 LENGTH(newTL[i]) = 0;
455 WRAPPED(newTL[i]) = False;
456 START_SELECTION(newTL[i]) = NON_SELECTION_COL;
457 END_SELECTION(newTL[i]) = NON_SELECTION_COL;
462 ** line malloc failed, lets limit the
470 ** its conceivable that MAX_ROWS could actually decrease if
471 ** we are low on memory...
473 MAX_ROWS(*oldTB) = MIN(MAX_ROWS(*oldTB), *newRows);
478 ** the row buffer malloc failed, revert back to MAX_ROWS
480 *newRows = MAX_ROWS(*oldTB);
483 ROWS(*oldTB) = *newRows;
490 ** Create an enhancement block at the specified row and column.
492 ** NOTE: For the time being, we simply allocate an entire row's worth
493 ** of enhancement blocks if it doesn't exist already. We may
494 ** get smarter later on.
498 _DtTermPrimBufferCreateEnhancement
509 ** Clear the enhancement block at the specified row and column.
525 ** Call the emulations specific function to insert the desired number of
526 ** enhancements at the specified position...
529 ** - insertCount has been properly clipped to insure that we don't go
533 ** - results are undefined if this function is called when the specified
534 ** column is at the end of the line.
542 const short insertCount,
543 const Boolean insertFlag
547 ** call the insert function only when it exists and we're in
552 (*INSERT_ENH(tb))(tb, row, col, insertCount, insertFlag);
557 ** Free the enhancement block at the specified row and column.
559 ** NOTE: We may get smarter later on.
562 _DtTermPrimBufferFreeEnhancement
579 TermLine **referenceLines,
580 int *referenceLineCount
586 *referenceLineCount = ROWS(tb);
587 *referenceLines = (TermLine *) XtMalloc(ROWS(tb) * sizeof(TermLine));
589 /* copy over the lines...
591 for (i1 = 0; i1 < ROWS(tb); i1++) {
592 (*referenceLines)[i1] = LINE_OF_TBUF(tb, i1);
595 /* verify that they are all unique...
598 /* do a brute force check... */
599 for (i1 = 0; i1 < ROWS(tb) - 1; i1++) {
600 for (i2 = i1 + 1; i2 < ROWS(tb); i2++) {
601 if ((*referenceLines)[i1] == (*referenceLines)[i2]) {
602 (void) fprintf(stderr,
603 ">>RememberTermBuffer: dup ptrs lines %d and %d\n",
617 TermLine *referenceLines,
618 int referenceLineCount
625 if (referenceLineCount != ROWS(tb)) {
626 for (i1 = 0; i1 < ROWS(tb); i1++) {
628 for (i2 = 0; i2 < ROWS(tb); i2++) {
629 if (referenceLines[i1] == LINE_OF_TBUF(tb, i2)) {
630 if (matchedLine == -1) {
633 /* duplicate pointer... */
635 ">>CheckTermBuffer: duplicate pointer src=%d, dest=%d and %d\n",
636 i1, matchedLine, i2);
640 if (matchedLine == -1) {
642 ">>CheckTermBuffer: dropped pointer src=%d\n", i1);
647 if (referenceLines) {
648 XtFree((char *) referenceLines);
653 _DtTermPrimBufferGetText
660 const Boolean needWideChar
668 TermCharInfoRec charInfoFirst;
669 TermCharInfoRec charInfoLast;
671 if (!VALID_ROW(tb, row) || !VALID_COL(tb, col))
676 colWidth = MIN(width, WIDTH(LINE_OF_TBUF(tb, row)) - col);
679 _DtTermPrimGetCharacterInfo(tb, row, col, &charInfoFirst);
680 _DtTermPrimGetCharacterInfo(tb, row, col + colWidth - 1, &charInfoLast);
682 if ((BYTES_PER_CHAR(tb) > 1) && !needWideChar)
685 ** our caller wants multi-byte characters...
690 for (pwc = charInfoFirst.u.pwc; pwc <= charInfoLast.u.pwc; pwc++)
692 mbLen = wctomb(pChar, *pwc);
700 fprintf(stderr, "_DtTermPrimBufferGetText: invalid wide char.\n");
706 retLen = charInfoLast.idx - charInfoFirst.idx + 1;
707 memcpy(buffer, charInfoFirst.u.pc, retLen);
713 ** colWidth == 0, there is nothing to return
722 _DtTermPrimBufferGetRows
731 _DtTermPrimBufferGetCols
740 _DtTermPrimBufferSetLinks
743 const TermBuffer prev,
744 const TermBuffer next
747 PREV_BUFFER(tb) = prev;
748 NEXT_BUFFER(tb) = next;
752 _DtTermPrimBufferSetSelectInfo
755 const TermSelectInfo si
758 BUFFER_SELECT_INFO(tb) = si;
762 ** Set the desired enhancement; simply call the emulator specific
766 _DtTermPrimBufferSetEnhancement
771 const unsigned char id,
777 return((*SET_ENH(tb))(tb, row, col, id, value));
786 ** Get the enhancements for the desired row and column by calling the
787 ** emulator specific routine.
790 _DtTermPrimBufferGetEnhancement
797 const countSpec countWhich
802 return((*GET_ENH(tb))(tb, row, col, values, count, countWhich));
806 *count = WIDTH(LINE_OF_TBUF(tb, row));
812 ** Return a pointer to the character at the specified row,col.
815 _DtTermPrimBufferGetCharacterPointer
822 TermCharInfoRec charInfo;
824 if (VALID_ROW(tb, row) && VALID_COL(tb, col))
826 _DtTermPrimGetCharacterInfo(tb, row, col, &charInfo);
827 return((termChar *)charInfo.u.pc);
836 ** Get the character info for the specified character. If the
837 ** specified column exceeds the width of the line, then make up
838 ** some reasonable information, allowing the calling routine to
839 ** continue in a reasonable fashion.
841 ** XXX: this doesn't get the emulator specific information yet (like
845 _DtTermPrimGetCharacterInfo
850 TermCharInfo charInfo
858 if (!VALID_ROW(tb, row))
863 line = LINE_OF_TBUF(tb, row);
866 ** handle the easy cases first...
868 if (col >= WIDTH(line))
871 ** make up some reasonable values when col equals or
872 ** exceeds the width of the line
874 charInfo->u.ptc = NULL;
875 charInfo->idx = LENGTH(line);
876 charInfo->len = BYTES_PER_CHAR(tb);
877 charInfo->startCol = col;
880 charInfo->enhLen = 0;
882 else if (BYTES_PER_CHAR(tb) == 1)
885 ** this is easy in a 1 byte locale...
887 charInfo->u.ptc = BUFFER(line) + col;
889 charInfo->len = BYTES_PER_CHAR(tb);
890 charInfo->startCol = col;
893 charInfo->enhLen = 0;
897 charInfo->u.pwc = (wchar_t *)BUFFER(line);
899 charInfo->len = BYTES_PER_CHAR(tb);
900 charInfo->startCol = 0;
901 charInfo->width = MAX(1, wcwidth(*((wchar_t *)BUFFER(line))));
903 charInfo->enhLen = 0;
908 ** not so easy when we're dealing with wchars...
910 if (col <= WIDTH(line) / 2)
913 ** work from left to right
916 for (pwc = (wchar_t *)BUFFER(line);
917 pwc < (wchar_t *)BUFFER(line) + LENGTH(line);
920 charWidth = MAX(1, wcwidth(*pwc));
921 totalWidth += charWidth;
922 if (col < totalWidth)
925 ** we've found the character, now fill in the info...
927 charInfo->u.pwc = pwc;
928 charInfo->idx = pwc - (wchar_t *)BUFFER(line);
929 charInfo->startCol = totalWidth - charWidth;
930 charInfo->width = charWidth;
938 ** work from right to left
940 totalWidth = WIDTH(line);
941 for (pwc = (wchar_t *)BUFFER(line) + (LENGTH(line) - 1);
942 pwc >= (wchar_t *)BUFFER(line);
945 charWidth = MAX(1, wcwidth(*pwc));
946 totalWidth -= charWidth;
947 if (totalWidth <= col)
950 ** we've found the character, now fill in the info...
952 charInfo->u.pwc = pwc;
953 charInfo->idx = pwc - (wchar_t *)BUFFER(line);
954 if (totalWidth == col)
956 charInfo->startCol = col;
960 charInfo->startCol = col - 1;
962 charInfo->width = charWidth;
967 charInfo->len = BYTES_PER_CHAR(tb);
969 charInfo->enhLen = 0;
975 ** Insert as many characters as possible at the specified row,col
976 ** return a count of the number of characters bumped off the end of the line
977 ** in 'returnCount' and a pointer to a buffer containing those characters
980 ** The the new width of the line is returned as the value of the function.
983 _DtTermPrimBufferInsert
988 const termChar *newChars,
990 Boolean insertFlag, /* if TRUE, insert, else overwrite */
991 termChar **returnChars, /* pointer to overflow buffer */
992 short *returnCount /* count of characters in overflow buffer */
997 short insertOverflow; /* # of newChars that would overflow */
1000 short copyCount; /* number of bytes to copy */
1002 if (!VALID_ROW(tb, row) || !VALID_COL(tb, col))
1008 line = LINE_OF_TBUF(tb, row);
1011 /* before we modify the buffer, disown the selection... */
1012 (void) _DtTermPrimSelectDisownIfNecessary(WIDGET(tb));
1013 #endif /* OLD_CODE */
1015 /* if this line is part of the selection, disown the selection... */
1016 if (IS_IN_SELECTION(line, col, MAX_SELECTION_COL)) {
1017 (void) _DtTermPrimSelectDisown(WIDGET(tb));
1020 if (BYTES_PER_CHAR(tb) > 1)
1023 ** we do not handle multibyte characters here...
1025 _DtTermPrimBufferInsertWc(tb, row, col, (wchar_t *)newChars,
1026 numChars, insertFlag,
1027 returnChars, returnCount);
1031 if (WIDTH(line) < col)
1034 ** We're adding characters past the current end of line,
1037 _DtTermPrimBufferPadLine(tb, row, col);
1040 insertCount = MIN(numChars, COLS(tb) - col);
1041 copyCount = insertCount * BYTES_PER_CHAR(tb);
1042 start = BUFFER(line) + col;
1045 ** It doesn't matter if we're overwriting, or inserting at the end
1046 ** of the line, the result is the same...
1048 if (col == WIDTH(line))
1053 if (insertFlag == False)
1056 ** We're overwriting:
1057 ** - determine the new line width
1058 ** - put any extra new characters into the overflow buffer
1060 ** The following will be done later:
1061 ** - copy the newChars into the line buffer
1062 ** - adjust line width (_DtTermPrimBufferSetLineWidth won't
1063 ** let the line get shorter)...
1065 newWidth = MAX(WIDTH(line), col + insertCount);
1066 *returnCount = numChars - insertCount;
1067 if (*returnCount > 0)
1069 memcpy(*returnChars, newChars + insertCount,
1070 *returnCount * BYTES_PER_CHAR(tb));
1076 ** we're inserting text in the middle of the line...
1078 *returnCount = MAX(0, (WIDTH(line) + numChars) - COLS(tb));
1079 if (*returnCount > 0)
1082 ** we'll have some overflow, figure out how many (if any)
1083 ** of the new characters will overflow and put them into
1084 ** the overflow buffer...
1086 insertOverflow = numChars - insertCount;
1087 memcpy(*returnChars, newChars + insertCount,
1088 insertOverflow * BYTES_PER_CHAR(tb));
1091 ** copy the displaced characters from the line to the
1092 ** overflow buffer as well...
1094 memcpy(*returnChars + insertOverflow, BUFFER(line) +
1095 (WIDTH(line) - MAX(0, *returnCount - insertOverflow)),
1096 MAX(0, *returnCount - insertOverflow)
1097 * BYTES_PER_CHAR(tb));
1100 ** Any overflow has been taken care of, now it's time to make
1101 ** room for the new characters...
1103 memmove(start + insertCount, start,
1104 MAX(0, WIDTH(line) - col - *returnCount));
1107 ** Compute the new line width...
1109 newWidth = WIDTH(line) + insertCount;
1113 ** Everything's ready:
1114 ** - put the characters into the line
1115 ** - adjust the line width (_DtTermPrimBufferSetLineWidth won't
1116 ** let the line get shorter)...
1117 ** - update the enhancements
1119 memcpy(start, newChars, copyCount);
1120 _DtTermPrimBufferSetLineWidth(tb, row, newWidth);
1121 insertEnhancements(tb, row, col, insertCount, insertFlag);
1122 return(WIDTH(line));
1126 ** Delete enough characters from the buffer to exceed width.
1128 ** If returnChars != NULL then the deleted characters are returned
1129 ** in a buffer pointed to by returnChars. It is the responsibility
1130 ** of the calling function to XtFree the buffer containing returned
1131 ** characters when they are no longer needed.
1134 _DtTermPrimBufferDelete
1140 termChar **returnChars, /* pointer to delete buffer */
1141 short *returnCount /* count of bytes in delete buffer */
1148 TermCharInfoRec charInfo;
1151 if (!VALID_ROW(tb, *row) || !VALID_COL(tb, *col))
1155 *returnChars = NULL;
1161 line = LINE_OF_TBUF(tb, *row);
1164 /* before we modify the buffer, disown the selection... */
1165 (void) _DtTermPrimSelectDisownIfNecessary(WIDGET(tb));
1166 #endif /* OLD_CODE */
1168 /* if this line is part of the selection, disown the selection... */
1169 if (IS_IN_SELECTION(line, *col, MAX_SELECTION_COL)) {
1170 (void) _DtTermPrimSelectDisown(WIDGET(tb));
1173 if (BYTES_PER_CHAR(tb) > 1)
1176 ** we do not handle multibyte characters here...
1178 _DtTermPrimBufferDeleteWc(tb, row, col, width, returnChars,
1184 *width = MAX(0, MIN(WIDTH(line) - localCol, *width));
1187 ** there are 4 cases of deleting a character from a line:
1189 ** the cursor is past the end of the line (col >= WIDTH(line))
1192 ** the cursor is in the middle of the line (copyCount > 0)
1193 ** - move the remaining characters to the left
1194 ** - deleteEnhancement
1197 ** the cursor is at the end of the line (copyCount == 0 and
1198 ** col == WIDTH(line) - 1)
1199 ** - deleteEnhancement
1200 ** - adjust WIDTH and LENGTH
1202 if (localCol >= WIDTH(line) || *width == 0)
1209 *returnChars = NULL;
1215 _DtTermPrimGetCharacterInfo(tb, localRow, localCol, &charInfo);
1218 ** Save the current characters before we overwrite them...
1220 if (returnChars != NULL)
1222 *returnCount = (*width * BYTES_PER_CHAR(tb));
1223 *returnChars = (termChar *)XtMalloc(*returnCount);
1224 memcpy(*returnChars, charInfo.u.pc, *returnCount);
1228 ** Cases 2 and 3 require that we delete the enhancement...
1232 (*DELETE_ENH(tb))(tb, localRow, localCol, *width);
1235 copyCount = MAX(0, WIDTH(line) - *width - localCol);
1241 memmove(charInfo.u.pc, charInfo.u.pc + *width,
1242 copyCount * BYTES_PER_CHAR(tb));
1246 ** Case 2 and 3 require that we adjust the line width
1248 WIDTH(line) -= *width;
1249 LENGTH(line) -= *width;
1253 ** replace all characters between startCol, and stopCol with spaces,
1254 ** if startCol > stopCol, then simply return
1257 _DtTermPrimBufferErase
1265 TermCharInfoRec charInfo;
1269 ** Make sure we have a valid row, and if we have a valid
1270 ** row, make sure that startCol is <= stopCol
1272 if (!(VALID_ROW(tb, row)) || (startCol > stopCol))
1278 /* before we modify the buffer, disown the selection... */
1279 (void) _DtTermPrimSelectDisownIfNecessary(WIDGET(tb));
1280 #endif /* OLD_CODE */
1282 /* if this line is part of the selection, disown the selection... */
1283 if (IS_IN_SELECTION(LINE_OF_TBUF(tb, row), startCol, stopCol)) {
1284 (void) _DtTermPrimSelectDisown(WIDGET(tb));
1287 if (BYTES_PER_CHAR(tb) > 1)
1289 _DtTermPrimBufferEraseWc(tb, row, startCol, stopCol);
1293 _DtTermPrimGetCharacterInfo(tb, row, startCol, &charInfo);
1294 pchar = charInfo.u.pc;
1296 _DtTermPrimGetCharacterInfo(tb, row, stopCol, &charInfo);
1299 ** replace the characters with spaces...
1301 while(pchar <= charInfo.u.pc)
1311 ** Adjust the line width, (the line can never be shortened)
1314 _DtTermPrimBufferSetLineWidth
1316 const TermBuffer tb,
1324 ** Make sure we have a valid row.
1326 if (!VALID_ROW(tb, row))
1331 line = LINE_OF_TBUF(tb, row);
1334 /* before we modify the buffer, disown the selection... */
1335 (void) _DtTermPrimSelectDisownIfNecessary(WIDGET(tb));
1336 #endif /* OLD_CODE */
1338 /* if this line is part of the selection, disown the selection... */
1339 if (IS_IN_SELECTION(line, newWidth, MAX_SELECTION_COL)) {
1340 (void) _DtTermPrimSelectDisown(WIDGET(tb));
1344 ** Clip the new width to the buffer width.
1346 newWidth = MIN(newWidth, COLS(tb));
1349 ** Make sure we actually have something to do.
1351 if (WIDTH(line) >= newWidth)
1356 WIDTH(line) = newWidth;
1357 if (BYTES_PER_CHAR(tb) == 1)
1360 ** in single byte locales, we go ahead and set the line length too,
1361 ** it is the responsibility of wide-character routines to set the
1362 ** line length themselves...
1364 LENGTH(line) = newWidth; /* works in single byte locales */
1371 ** the line length is the lesser of the actual length, or the length
1372 ** necessary to get to the buffer width
1373 ** (in the case that the buffer shrank after the line was full)
1376 _DtTermPrimBufferGetLineLength
1378 const TermBuffer tb,
1384 TermCharInfoRec charInfo;
1386 if (VALID_ROW(tb, row))
1388 width = MIN(WIDTH(LINE_OF_TBUF(tb, row)), COLS(tb));
1392 (void)_DtTermPrimGetCharacterInfo(tb, row, width - 1, &charInfo);
1395 ** a line can not end on column 1 of 2. Note that we must
1396 ** add 1 to the column index to make it the line length...
1398 if ((charInfo.width == 2) && (charInfo.startCol != width - 2)) {
1399 /* only half of charInfo.idx fits in the line, so drop
1402 retLen = charInfo.idx;
1404 /* single column character or double column character that
1405 * fits on the line...
1407 retLen = charInfo.idx + 1;
1425 ** the line width is the lesser of the actual width, or the buffer width
1426 ** (in the case that the buffer shrank after the line was full)
1429 _DtTermPrimBufferGetLineWidth
1431 const TermBuffer tb,
1436 TermCharInfoRec charInfo;
1438 if (VALID_ROW(tb, row))
1440 width = MIN(WIDTH(LINE_OF_TBUF(tb, row)), COLS(tb));
1444 (void)_DtTermPrimGetCharacterInfo(tb, row, width - 1, &charInfo);
1447 ** a line can not end on column 1 of 2...
1449 if ((charInfo.width == 2) && (charInfo.startCol != width - 2)) {
1450 /* only half of charInfo.idx fits in the line, so drop
1455 /* single column character or double column character that
1456 * fits on the line...
1466 /**************************************************************************
1468 * _DtTermPrimBufferMoveLockArea():
1469 * move locked screen memory up or down in the screen buffer.
1472 * TermBuffer tb: term buffer to use
1473 * short dest: point to move the locked region to
1474 * short src: point to move the locked region from
1475 * short length: size of the locked region
1483 _DtTermPrimBufferMoveLockArea
1485 const TermBuffer tb,
1491 TermLine lineCache[10];
1492 TermLine *holdLines = lineCache;
1501 DebugF('B', 1, RememberTermBuffer(tb,&refLines,&refLineCount));
1503 /* don't bother if there is we are being asked to do nothing...
1505 if ((length <= 0) || (dest == src))
1509 /* before we modify the buffer, disown the selection... */
1510 (void) _DtTermPrimSelectDisownIfNecessary(WIDGET(tb));
1511 #endif /* OLD_CODE */
1513 /* before we modify the buffer, check and see if the leading or
1514 * trailing edge of the buffer crosses the selection and if the
1515 * destination line crosses the selection. If it does, we need
1518 /* leading edge of src... */
1520 IS_IN_SELECTION(LINE_OF_TBUF(tb, src - 1), MIN_SELECTION_COL,
1521 MAX_SELECTION_COL) &&
1522 IS_IN_SELECTION(LINE_OF_TBUF(tb, src), MIN_SELECTION_COL,
1523 MAX_SELECTION_COL)) {
1524 (void) _DtTermPrimSelectDisown(WIDGET(tb));
1527 /* trailing edge of src... */
1528 if (((src + length) < ROWS(tb)) &&
1529 IS_IN_SELECTION(LINE_OF_TBUF(tb, src + length - 1),
1530 MIN_SELECTION_COL, MAX_SELECTION_COL) &&
1531 IS_IN_SELECTION(LINE_OF_TBUF(tb, src + length), MIN_SELECTION_COL,
1532 MAX_SELECTION_COL)) {
1533 (void) _DtTermPrimSelectDisown(WIDGET(tb));
1536 /* destination... */
1537 if ((dest > 0) && IS_IN_SELECTION(LINE_OF_TBUF(tb, dest - 1),
1538 MIN_SELECTION_COL, MAX_SELECTION_COL) &&
1539 IS_IN_SELECTION(LINE_OF_TBUF(tb, dest),
1540 MIN_SELECTION_COL, MAX_SELECTION_COL)) {
1541 (void) _DtTermPrimSelectDisown(WIDGET(tb));
1544 /* we need to save the line positions of the smaller of the length
1545 * of the chunk to move, or the distance to move the chunk.
1547 distance = (dest > src) ? (dest - src) : (src - dest);
1548 cacheSize = MIN(length, distance);
1550 /* if we are moving more lines than will fit in the lineCache, we need
1551 * to malloc (and free) storage for the termLineRecs...
1553 if (cacheSize > (sizeof(lineCache) / sizeof(lineCache[0]))) {
1554 holdLines = (TermLine *) XtMalloc(cacheSize * sizeof(TermLine));
1558 ** clear the wrap flag for the line preceding the block to be
1559 ** moved, and the last line of the block to be moved
1561 _DtTermPrimBufferSetLineWrapFlag(tb, src - 1, FALSE);
1562 _DtTermPrimBufferSetLineWrapFlag(tb, src + length, FALSE);
1564 /* cache them away... */
1565 if (distance > length) {
1566 /* save away the locked area... */
1567 destPtr = holdLines;
1568 srcPtr = &(LINE_OF_TBUF(tb, src));
1570 for (i = 0; i < length; i++) {
1571 *destPtr++ = *srcPtr++;
1573 /* move the area above/below the locked area... */
1575 /* we are moving the locked area down, so we must move
1576 * the scroll area up...
1578 destPtr = &(LINE_OF_TBUF(tb, src));
1579 srcPtr = &(LINE_OF_TBUF(tb, src + length));
1580 for (i = 0; i < distance; i++) {
1581 *destPtr++ = *srcPtr++;
1584 /* we are moving the locked area up, so we must move
1585 * the scroll area down...
1587 destPtr = &(LINE_OF_TBUF(tb, src + length - 1));
1588 srcPtr = &(LINE_OF_TBUF(tb, src - 1));
1589 for (i = 0; i < distance; i++) {
1590 *destPtr-- = *srcPtr--;
1593 /* restore the cached lock area... */
1594 destPtr = &(LINE_OF_TBUF(tb, dest));
1596 for (i = 0; i < length; i++) {
1597 *destPtr++ = *srcPtr++;
1600 /* save away the area we will move the lock area over...
1603 /* moving it down. Save the area under the lock area...
1605 destPtr = holdLines;
1606 srcPtr = &(LINE_OF_TBUF(tb, src + length));
1607 for (i = 0; i < distance; i++) {
1608 *destPtr++ = *srcPtr++;
1610 /* move the lock area down... */
1611 destPtr = &(LINE_OF_TBUF(tb, dest + length - 1));
1612 srcPtr = &(LINE_OF_TBUF(tb, src + length - 1));
1613 for (i = 0; i < length; i++) {
1614 *destPtr-- = *srcPtr--;
1616 /* restore the area under (that is now over) the lock area... */
1617 destPtr = &(LINE_OF_TBUF(tb, src));
1619 for (i = 0; i < distance; i++) {
1620 *destPtr++ = *srcPtr++;
1623 /* moving it up. Save the area over the lock area...
1625 destPtr = holdLines;
1626 srcPtr = &(LINE_OF_TBUF(tb, dest));
1627 for (i = 0; i < distance; i++) {
1628 *destPtr++ = *srcPtr++;
1630 /* move the lock area up... */
1631 destPtr = &(LINE_OF_TBUF(tb, dest));
1632 srcPtr = &(LINE_OF_TBUF(tb, src));
1633 for (i = 0; i < length; i++) {
1634 *destPtr++ = *srcPtr++;
1636 /* restore the area over (that is now under) the lock area... */
1637 destPtr = &(LINE_OF_TBUF(tb, dest + length));
1639 for (i = 0; i < distance; i++) {
1640 *destPtr++ = *srcPtr++;
1645 /* free up the holdLines (if we malloc'ed it)... */
1646 if (holdLines != lineCache) {
1647 (void) XtFree((char *) holdLines);
1650 DebugF('B', 1, CheckTermBuffer(tb,refLines,refLineCount));
1654 /**************************************************************************
1656 * _DtTermPrimBufferInsertLine(): insert one or more lines of text from
1657 * the end of the buffer below the insertion point, or from
1658 * the beginning of the buffer above the insertion point.
1661 * TermBuffer tb: term buffer to insert end/begining into
1662 * short dest: point to insert below/above
1663 * short length: number of lines to insert
1664 * short src: source point of insertion
1672 _DtTermPrimBufferInsertLine
1674 const TermBuffer tb,
1680 TermLine lineCache[10];
1681 TermLine *holdLines = lineCache;
1689 DebugF('B', 1, RememberTermBuffer(tb,&refLines,&refLineCount));
1691 /* don't bother if there is we are being asked to do nothing...
1697 /* before we modify the buffer, disown the selection... */
1698 (void) _DtTermPrimSelectDisownIfNecessary(WIDGET(tb));
1699 #endif /* OLD_CODE */
1701 /* before we modify the buffer, check and see if the
1702 * destination line crosses the selection. If it does, we need
1705 /* destination... */
1707 if (((dest + length) < ROWS(tb)) &&
1708 IS_IN_SELECTION(LINE_OF_TBUF(tb, dest + length),
1709 MIN_SELECTION_COL, MAX_SELECTION_COL) &&
1710 IS_IN_SELECTION(LINE_OF_TBUF(tb, dest + length + 1),
1711 MIN_SELECTION_COL, MAX_SELECTION_COL)) {
1712 (void) _DtTermPrimSelectDisown(WIDGET(tb));
1716 if (IS_IN_SELECTION(LINE_OF_TBUF(tb, dest),
1717 MIN_SELECTION_COL, MAX_SELECTION_COL) &&
1718 IS_IN_SELECTION(LINE_OF_TBUF(tb, dest - 1),
1719 MIN_SELECTION_COL, MAX_SELECTION_COL)) {
1720 (void) _DtTermPrimSelectDisown(WIDGET(tb));
1725 /* if we are being asked to move all (or more) the lines in the
1726 * buffer, then we can just clear them all out and return...
1728 if (length >= ROWS(tb)) {
1729 for (i = 0; i < ROWS(tb); i++) {
1730 _DtTermPrimBufferClearLine(tb, i, 0);
1735 /* if dest and src match, we can just clear them out and return...
1738 for (i = 0; (i < length) && ((i + dest) < ROWS(tb)); i++) {
1739 _DtTermPrimBufferClearLine(tb, src + i, 0);
1744 /* if we are moving more lines than will fit in the lineCache, we need
1745 * to malloc (and free) storage for the termLineRecs...
1747 if (length > (sizeof(lineCache) / sizeof(lineCache[0]))) {
1748 holdLines = (TermLine *) XtMalloc(length * sizeof(TermLine));
1752 /* our src is above the destination. Copy the lines to insert,
1753 * move the lines above the insertion pointer up, and insert
1754 * the saved lines...
1757 /* save away the top length lines... */
1758 destPtr = holdLines;
1759 srcPtr = &(LINE_OF_TBUF(tb, src));
1760 for (i = 0; i < length; i++) {
1761 /* these lines will be cleared, so we don't need to track
1762 * movement of them...
1764 *destPtr++ = *srcPtr++;
1766 /* copy the lines above the insertion point up... */
1767 destPtr = &(LINE_OF_TBUF(tb, src));
1768 srcPtr = &(LINE_OF_TBUF(tb, src + length));
1769 for (i = src; i < dest - length + 1; i++) {
1770 *destPtr++ = *srcPtr++;
1772 /* restore the saved lines above the insertion point... */
1773 destPtr = &(LINE_OF_TBUF(tb, dest - length + 1));
1775 for (i = 0; i < length; i++) {
1777 /* clear the line... */
1778 _DtTermPrimBufferClearLine(tb, dest - length + 1 + i, 0);
1783 #ifdef DONT_DO_THIS_ANY_MORE
1784 /* Adjust or disown selection */
1785 _DtTermPrimSelectDeleteLine(tb,length) ;
1786 #endif /* DONT_DO_THIS_ANY_MORE */
1788 /* our src is below the destination. Copy the lines to insert,
1789 * move the lines below the insertion pointer down, and insert
1790 * the saved lines...
1792 /* save away the bottom length lines... */
1793 destPtr = holdLines;
1794 srcPtr = &(LINE_OF_TBUF(tb, src));
1795 for (i = 0; i < length; i++) {
1796 *destPtr++ = *srcPtr++;
1798 /* copy the lines below the insertion point down... */
1799 destPtr = &(LINE_OF_TBUF(tb, src + length - 1));
1800 srcPtr = &(LINE_OF_TBUF(tb, src - 1));
1801 for (i = 0; i < src - dest; i++) {
1802 *destPtr-- = *srcPtr--;
1804 /* restore the saved lines below the insertion point... */
1805 destPtr = &(LINE_OF_TBUF(tb, dest));
1807 for (i = 0; i < length; i++) {
1809 /* clear the line... */
1810 _DtTermPrimBufferClearLine(tb, dest + i, 0);
1816 /* free up the holdLines (if we malloc'ed it)... */
1817 if (holdLines != lineCache) {
1818 (void) XtFree((char *) holdLines);
1821 DebugF('B', 1, CheckTermBuffer(tb,refLines,refLineCount));
1825 /**************************************************************************
1827 * _DtTermPrimBufferInsertLineFromTB(): insert one or more lines
1828 * of text from the end of the buffer below the insertion
1829 * point, or from the beginning of the buffer above the
1833 * TermBuffer tb: term buffer to insert end/begining into
1834 * short dest: point to insert below/above
1835 * short length: number of lines to insert
1836 * InsertSource: source of insertion (end or beginning)
1844 _DtTermPrimBufferInsertLineFromTB
1846 const TermBuffer tb,
1849 const InsertSource insertSource
1852 if (insertSource == insertFromTop) {
1853 (void) _DtTermPrimBufferInsertLine(tb, dest, length, 0);
1855 (void) _DtTermPrimBufferInsertLine(tb, dest, length,
1862 /**************************************************************************
1864 * _DtTermPrimBufferScrollToHistory(): scroll one or more lines
1865 * of text from the beginning of the active buffer into
1866 * the history buffer.
1869 * TermBuffer tb: term buffer to scroll out of
1870 * short length: number of lines to scroll
1873 * the number of lines scrolled (removed from active buffer)
1878 _DtTermPrimBufferScrollToHistory()
1880 const TermBuffer tb,
1884 if (PREV_BUFFER(tb)) {
1887 #endif /* NOTDONE */
1890 /**************************************************************************
1892 * _DtTermPrimBufferDeleteLine(): deletes one or more lines of text from
1893 * the deletion poing and sticks them at the end of the
1894 * line buffer. It does not clear the line. That is
1895 * normally done when the line is inserted.
1898 * TermBuffer tb: term buffer to insert end/begining into
1899 * short source: point to insert below/above
1900 * short length: number of lines to insert
1901 * short lastUsedLine: number of last line in the buffer we need
1910 _DtTermPrimBufferDeleteLine
1912 const TermBuffer tb,
1915 const short lastUsedRow
1918 TermLine lineCache[10];
1919 TermLine *holdLines = lineCache;
1927 DebugF('B', 1, RememberTermBuffer(tb,&refLines,&refLineCount));
1929 /* don't bother if there is we are being asked to do nothing...
1933 /* if we are being asked to move the last usedLines, we don't have
1934 * to do anything either...
1936 if (source + length >= lastUsedRow)
1940 /* before we modify the buffer, disown the selection... */
1941 (void) _DtTermPrimSelectDisownIfNecessary(WIDGET(tb));
1942 #endif /* OLD_CODE */
1944 /* if we are moving more lines than will fit in the lineCache, we need
1945 * to malloc (and free) storage for the termLineRecs...
1947 if (length > (sizeof(lineCache) / sizeof(lineCache[0]))) {
1948 holdLines = (TermLine *) XtMalloc(length * sizeof(TermLine));
1951 /* clear the deleted lines... */
1952 for (i = 0; i < length; i++) {
1953 (void) _DtTermPrimBufferClearLine(tb, source + i, 0);
1957 (void) memcpy(holdLines, &(LINE_OF_TBUF(tb, source)), length *
1959 #else /* USE_MEMCPY */
1960 destPtr = holdLines;
1961 srcPtr = &(LINE_OF_TBUF(tb, source));
1962 for (i = 0; i < length; i++) {
1963 *destPtr++ = *srcPtr++;
1965 #endif /* USE_MEMCPY */
1967 /* ripple up the lines... */
1968 copyLength = MAX(0, MIN(ROWS(tb), lastUsedRow) - source - length);
1969 if (copyLength > 0) {
1971 (void) memcpy(&(LINE_OF_TBUF(tb, source)),
1972 &(LINE_OF_TBUF(tb, source + length)),
1973 copyLength * sizeof(TermLine));
1974 #else /* USE_MEMCPY */
1975 destPtr = &(LINE_OF_TBUF(tb, source));
1976 srcPtr = &(LINE_OF_TBUF(tb, source + length));
1977 for (i = 0; i < copyLength; i++) {
1978 *destPtr++ = *srcPtr++;
1980 #endif /* USE_MEMCPY */
1983 /* copy back the deleted (cached) lines... */
1985 (void) memcpy(&(LINE_OF_TBUF(tb, source + copyLength)), holdLines,
1986 length * sizeof(TermLine));
1987 #else /* USE_MEMCPY */
1988 destPtr = &(LINE_OF_TBUF(tb, source + copyLength));
1990 for (i = 0; i < length; i++) {
1991 *destPtr++ = *srcPtr++;
1993 #endif /* USE_MEMCPY */
1995 /* free up the holdLines (if we malloc'ed it)... */
1996 if (holdLines != lineCache) {
1997 (void) XtFree((char *) holdLines);
2000 DebugF('B', 1, CheckTermBuffer(tb,refLines,refLineCount));
2004 ** Pad the requested row from the current width to 'newWidth' with spaces...
2007 _DtTermPrimBufferPadLine
2009 const TermBuffer tb,
2011 const short newWidth
2017 /* before we modify the buffer, disown the selection... */
2018 (void) _DtTermPrimSelectDisownIfNecessary(WIDGET(tb));
2019 #endif /* OLD_CODE */
2021 line = LINE_OF_TBUF(tb, row);
2023 /* if this line is part of the selection, disown the selection... */
2024 if (IS_IN_SELECTION(line, MIN(newWidth, WIDTH(line)),
2025 MAX(newWidth, WIDTH(line)))) {
2026 (void) _DtTermPrimSelectDisown(WIDGET(tb));
2029 (void)memset(BUFFER(line) + WIDTH(line),
2030 0x20, (newWidth - WIDTH(line)) * BYTES_PER_CHAR(tb));
2033 (*CLEAR_ENH(tb))(tb, row, WIDTH(line), newWidth - WIDTH(line));
2035 _DtTermPrimBufferSetLineWidth(tb, row, newWidth);
2039 ** Clear the line to the new width (just reset the line width).
2041 ** We also clear the wrapped flag as well.
2044 _DtTermPrimBufferClearLine
2046 const TermBuffer tb,
2054 /* before we modify the buffer, disown the selection... */
2055 (void) _DtTermPrimSelectDisownIfNecessary(WIDGET(tb));
2056 #endif /* OLD_CODE */
2059 ** handle multi-byte locales...
2061 if (BYTES_PER_CHAR(tb) > 1)
2063 return(_DtTermPrimBufferClearLineWc(tb, row, newWidth));
2067 ** Some simple bounds checking.
2069 if (!VALID_ROW(tb, row))
2074 line = LINE_OF_TBUF(tb, row);
2076 /* if this line is part of the selection, disown the selection... */
2077 if (IS_IN_SELECTION(line, MIN(newWidth, WIDTH(line)),
2078 MAX(newWidth, WIDTH(line)))) {
2079 (void) _DtTermPrimSelectDisown(WIDGET(tb));
2083 ** Clip the new width to the buffer width.
2085 newWidth = MIN(newWidth, COLS(tb));
2088 ** force width to the desired value
2090 ** (We take the direct approach because _DtTermPrimBufferSetLineWidth
2091 ** doesn't allow the line width to decrease.)
2093 if (newWidth < WIDTH(line))
2096 ** Call the helper function if it exists
2100 (*CLEAR_LINE(tb))(tb, row, newWidth);
2102 WRAPPED(line) = False;
2103 WIDTH(line) = newWidth;
2104 LENGTH(line) = newWidth; /* this works in single-byte locales */
2110 _DtTermPrimBufferGetNextTab
2112 const TermBuffer tb,
2116 if (!VALID_COL(tb, col))
2121 /* find the next set tab stop... */
2122 for (col++; (col < COLS(tb)) && (!TABS(tb)[col]); col++)
2125 /* did we go to the end of the line w/out hitting one?... */
2126 if (col >= COLS(tb)) {
2135 _DtTermPrimBufferGetPreviousTab
2137 const TermBuffer tb,
2141 if (!VALID_COL(tb, col - 1))
2146 /* find the next set tab stop... */
2147 for (col--; (col > 0) && (!TABS(tb)[col]); col--)
2150 /* we can just return col. If ther was not another tab stop, it will
2158 _DtTermPrimBufferSetTab
2160 const TermBuffer tb,
2164 if (VALID_COL(tb, col))
2166 TABS(tb)[col] = True;
2174 _DtTermPrimBufferClearTab
2176 const TermBuffer tb,
2180 if (VALID_COL(tb, col))
2182 TABS(tb)[col] = False;
2190 _DtTermPrimBufferClearAllTabs
2195 (void) memset(TABS(tb), '\0', COLS(tb) * sizeof(Boolean));
2200 ** Set the line wrap flag to the desired state.
2203 _DtTermPrimBufferSetLineWrapFlag
2210 if (VALID_ROW(tb, row))
2212 WRAPPED(LINE_OF_TBUF(tb, row)) = state;
2218 ** Return the state of the line wrap flag.
2221 _DtTermPrimBufferTestLineWrapFlag
2227 if (VALID_ROW(tb, row))
2229 return(WRAPPED(LINE_OF_TBUF(tb, row)));
2238 ** Set the in selection flag to the desired state.
2241 _DtTermPrimBufferSetInSelectionFlag
2245 TermLineSelection state
2248 if (VALID_ROW(tb, row))
2251 START_SELECTION(LINE_OF_TBUF(tb, row)) = state->selectionStart;
2252 END_SELECTION(LINE_OF_TBUF(tb, row)) = state->selectionEnd;
2254 START_SELECTION(LINE_OF_TBUF(tb, row)) = NON_SELECTION_COL;
2255 END_SELECTION(LINE_OF_TBUF(tb, row)) = NON_SELECTION_COL;
2262 ** Return the state of the in selection flag.
2265 _DtTermPrimBufferGetInSelectionFlag
2271 if (VALID_ROW(tb, row))
2273 if ((START_SELECTION(LINE_OF_TBUF(tb, row)) != NON_SELECTION_COL) &&
2274 (END_SELECTION(LINE_OF_TBUF(tb, row)) != NON_SELECTION_COL)) {
2275 return(&IN_SELECTION(LINE_OF_TBUF(tb, row)));
2278 return((TermLineSelection) 0);
2282 _DtTermPrimBufferSetSelectLines
2293 for (i1 = 0; i1 < ROWS(tb); i1++) {
2294 if ((i1 >= beginRow) && (i1 <= endRow)) {
2295 if (i1 == beginRow) {
2296 START_SELECTION(LINE_OF_TBUF(tb, i1)) = beginCol;
2298 START_SELECTION(LINE_OF_TBUF(tb, i1)) = MIN_SELECTION_COL;
2301 END_SELECTION(LINE_OF_TBUF(tb, i1)) = endCol;
2303 END_SELECTION(LINE_OF_TBUF(tb, i1)) = MAX_SELECTION_COL;
2306 START_SELECTION(LINE_OF_TBUF(tb, i1)) = NON_SELECTION_COL;
2307 END_SELECTION(LINE_OF_TBUF(tb, i1)) = NON_SELECTION_COL;
2312 #if (defined(TEST) || defined(__CODECENTER__) || defined(DEBUG))
2314 _termBufferPrintLine
2316 const TermBuffer tb,
2324 printf("Line: %d\n", row);
2326 line = LINE_OF_TBUF(tb, row];
2327 printf(" width: %3d\n", WIDTH(line));
2328 printf(" length: %3d\n", LENGTH(line));
2329 if (LENGTH(line) > 0)
2331 printf(" buffer: <");
2332 pChar = BUFFER(line);
2333 for (j = 0; j < LENGTH(line); j++)
2335 printf("%X", *pChar++);
2342 ** Print the contents of the TermBuffer.
2345 _termBufferPrintBuffer
2355 printf("TermBuffer has been freed.\n");
2359 printf("TermBuffer dimensions:\n");
2360 printf(" rows: %d\n", ROWS(tb));
2361 printf(" cols: %d\n", COLS(tb));
2363 for (i = 0; i < ROWS(tb); i++)
2365 _termBufferPrintLine(tb, i);
2368 #endif /* (defined(TEST) || defined(__CODECENTER__)) */
2372 ** Some simple tests of the termBuffer.
2374 /* the following is to allow for a single main function in the code... */
2375 #define termBufMain main
2378 const TermBuffer myTB;
2380 printf("Sizeof termEnhRec : %d\n", sizeof(struct _termEnhRec));
2381 printf("Sizeof termBufferRec : %d\n", sizeof(struct _TermBufferRec));
2383 myTB = _DtTermPrimBufferCreateBuffer(12, 80);
2384 _termBufferPrintBuffer(myTB);
2386 printf("[0,0] %d\n", _DtTermPrimBufferSetEnhancement(myTB, 0, 0, enhVideo, BLINK));
2387 _termBufferPrintEnhancement(myTB, 0, 0);
2388 printf("[0,1] %d\n", _DtTermPrimBufferSetEnhancement(myTB, 0, 1, enhVideo, INVERSE));
2389 _termBufferPrintEnhancement(myTB, 0, 0);
2390 _termBufferPrintEnhancement(myTB, 0, 1);
2391 printf("[0,9] %d\n", _DtTermPrimBufferSetEnhancement(myTB, 0, 9, enhVideo, UNDERLINE));
2392 _termBufferPrintEnhancement(myTB, 0, 0);
2393 _termBufferPrintEnhancement(myTB, 0, 1);
2394 _termBufferPrintEnhancement(myTB, 0, 9);
2395 printf("[0,6] %d\n", _DtTermPrimBufferSetEnhancement(myTB, 0, 6, enhVideo, HALF_BRIGHT));
2396 _termBufferPrintEnhancement(myTB, 0, 0);
2397 _termBufferPrintEnhancement(myTB, 0, 1);
2398 _termBufferPrintEnhancement(myTB, 0, 6);
2399 _termBufferPrintEnhancement(myTB, 0, 9);
2400 _termBufferPrintBuffer(myTB);
2402 _DtTermPrimBufferSetEnhancement(myTB, 10, 10, enhVideo, BLINK);
2403 _DtTermPrimBufferSetEnhancement(myTB, 10, 20, enhColor, 3);
2404 _termBufferPrintBuffer(myTB);
2406 _DtTermPrimBufferResizeBuffer(&myTB, 6, 40);
2407 _termBufferPrintBuffer(myTB);
2409 _DtTermPrimBufferSetEnhancement(myTB, 10, 10, enhVideo, BLINK);
2410 _DtTermPrimBufferResizeBuffer(&myTB, 12, 80);
2411 _termBufferPrintBuffer(myTB);
2413 _DtTermPrimBufferFreeBuffer(myTB);