cdesktopenv/cde/lib/DtTerm/TermPrim/TermPrimBufferWc.c

1155 lines
29 KiB
C

/*
* 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... */
#ifndef _XOPEN_SOURCE
#define _XOPEN_SOURCE 600
#endif
#include <stdlib.h>
#include <wchar.h>
#include <Xm/Xm.h>
#include "TermHeader.h" /* for MIN/MAX */
#include "TermPrim.h"
#include "TermPrimOSDepI.h"
#include "TermPrimBufferP.h"
#include "TermPrimDebug.h"
static void
_termBufferValidateLineWc
(
const TermBuffer tb,
const short row
);
static void
_patchUpChar
(
TermBuffer tb,
short row,
short *col,
TermCharInfo charInfo
);
static void
_countWidth
(
wchar_t *wcBuffer,
short length,
short maxWidth,
short *retCount,
short *retWidth
);
static void
_primBufferInsertWc
(
const TermBuffer tb,
const short row,
short *col,
wchar_t *newChars,
short numChars,
short *lengthInc,
short *widthInc,
short *widthInsert, /* width of inserted characters */
termChar *returnChars, /* pointer to overflow buffer */
short *returnCount /* count of characters in overflow buffer */
);
static void
_primBufferOverwriteWc
(
const TermBuffer tb,
const short row,
short *col,
wchar_t *newChars,
short numChars,
short *lengthInc,
short *widthInc,
short *widthInsert, /* width of inserted characters */
termChar *returnChars, /* pointer to overflow buffer */
short *returnCount /* count of characters in overflow buffer */
);
#ifdef USE_SUN_WCWIDTH_PATCH
#include <limits.h>
/*
** A small workaround for systems that don't have wcwidth...
*/
int
sun_wcwidth
(
const wchar_t wc
)
{
int status;
char mbstr[MB_LEN_MAX + 1];
status = wctomb(mbstr, wc);
if (status > 0)
return(euccol(mbstr));
else
return(status);
}
#endif /* USE_SUN_WCWIDTH_PATCH */
short
_DtTermPrimBufferGetTextWc
(
const TermBuffer tb,
const short row,
const short col,
const short length,
char *buffer,
const Boolean needWideChar
)
{
short len;
if (!VALID_ROW(tb, row) || !VALID_COL(tb, col))
{
return(0);
}
len = MIN(length, LENGTH(LINES(tb)[row]) - col);
if (length > 0)
{
memcpy(buffer, BUFFER(LINES(tb)[row]) + col, len);
}
return(len);
}
/*
** this is a helper function, that replaces a 2 column character with
** two spaces if "col" falls on column 2 of 2...
*/
static void
_patchUpChar
(
TermBuffer tb,
short row,
short *col,
TermCharInfo charInfo
)
{
TermLine line;
line = LINE_OF_TBUF(tb, row);
/*
** make sure we are not trying to overwrite the second column
** of a two column character.
*/
_DtTermPrimGetCharacterInfo(tb, row, *col, charInfo);
if ((charInfo->width == 2) &&
(charInfo->startCol == *col - 1))
{
/*
** we are on the second column of a two column character,
** replace the character with 2 spaces before we proceed
**
** first replace the character with a space, then slide the
** characters one to the right and bump the LENGTH
** (the width remains constant)
*/
*charInfo->u.pwc = L' ';
memmove(charInfo->u.pwc + 1, charInfo->u.pwc,
(LENGTH(line) - charInfo->idx) * sizeof(wchar_t));
LENGTH(line) += 1;
/*
** remember the old starting column for later...
*/
(*col)--;
/*
** now update the charInfo (since we replaced the 2 column
** character with 2 single column spaces)...
*/
charInfo->startCol++;
charInfo->u.pwc++;
charInfo->idx++;
charInfo->width = 1;
}
}
/*
** determine how many wide characters in the buffer we can have before the
** maxWidth is exceeded...
*/
static void
_countWidth
(
wchar_t *wcBuffer, /* buffer of wide characters */
short wcLen, /* number of wide chars in buffer */
short maxWidth, /* maximum width desired */
short *length, /* max num of chars with total width <= maxWidth */
short *width /* actual width of the retCount wide chars */
)
{
wchar_t *pwc;
short charWidth;
*width = 0;
for (pwc = wcBuffer; pwc < wcBuffer + wcLen; pwc++)
{
switch (charWidth = wcwidth(*pwc))
{
case -1:
/*
** invalid character, (but this should have been handled earlier)
*/
/* replace the character with a space... */
*pwc = L' ';
/* and set the width to 1... */
charWidth = 1;
break;
case 0:
/*
** its a null character, but is still has a width for our
** purposes...
*/
charWidth = 1;
break;
default:
break;
}
if (*width + charWidth > maxWidth)
{
break;
}
else
{
*width += charWidth;
}
}
*length = pwc - wcBuffer;
}
/*
** This is a helper function that inserts characters into the specified
** buffer in insert mode.
*/
static void
_primBufferInsertWc
(
const TermBuffer tb,
const short row,
short *col,
wchar_t *newChars,
short numChars,
short *lengthInc,
short *widthInc,
short *widthInsert, /* width of inserted characters */
termChar *returnChars, /* pointer to overflow buffer */
short *returnLength /* count of characters in overflow buffer */
)
{
short charWidth;
short lengthInsert;
short insertOverflow; /* # of newChars that would overflow */
short overflowLength;
short overflowWidth;
short localCol;
TermLine line;
wchar_t *pwc = NULL;
TermCharInfoRec charInfo;
/*
** make a copy of *col because it may be modified by
** _patchUpChar()
*/
localCol = *col;
/*
** first decide how many characters we can insert before
** running off the end of the line...
*/
_countWidth(newChars, numChars, COLS(tb) - localCol, &lengthInsert,
widthInsert);
/*
** return any extra characters...
*/
*returnLength = numChars - lengthInsert;
if (*returnLength > 0)
{
/*
** we have some overflow...
*/
memcpy(returnChars, newChars + lengthInsert,
*returnLength * sizeof(wchar_t));
}
/*
** make sure we are not trying to overwrite the second column
** of a two column character.
*/
_patchUpChar(tb, row, col, &charInfo);
/*
** Decide how many characters we can insert before running off the
** end of the buffer...
*/
line = LINE_OF_TBUF(tb, row);
if (WIDTH(line) + *widthInsert <= COLS(tb))
{
/*
** there is no overflow, we can insert all "lengthInsert" characters...
*/
*widthInc = *widthInsert;
*lengthInc = lengthInsert;
overflowLength = 0;
}
else
{
overflowWidth = WIDTH(line) + *widthInsert - COLS(tb);
/*
** inserting the new characters will overflow the line buffer,
** remove as many of the current characters on the line
** as necessary to prevent buffer overflow
*/
if (overflowWidth > 0)
{
*widthInc = *widthInsert - overflowWidth;
for (pwc = ((wchar_t *)BUFFER(line)) + LENGTH(line) - 1;
pwc >= charInfo.u.pwc; pwc--)
{
overflowWidth -= MAX(1, wcwidth(*pwc));
if (overflowWidth <= 0)
{
/*
** we've removed enough characters, pwc points to the
** first character to remove...
*/
break;
}
}
/*
** final adjustment to widthInc (at this point overflowWidth
** is either 0 (we removed exactly "overflowWidth" worth of
** characters) or -1 (we removed "overflowWidth + 1" worth of
** characters because we removed some 2 column characters)
*/
*widthInc += overflowWidth;
}
overflowLength = ((wchar_t *)BUFFER(line)) + LENGTH(line) - pwc;
if (overflowLength > 0)
{
*lengthInc = lengthInsert - overflowLength;
/*
** copy the displaced characters from the line to the
** overflow buffer...
*/
memcpy(returnChars + *returnLength, pwc,
overflowLength * sizeof(wchar_t));
*returnLength += overflowLength;
}
}
/*
** Any overflow has been taken care of, now it's time to make
** room for the new characters...
**
** at this point:
** charInfo.pchar points to the character at col
*/
memmove(charInfo.u.pwc + lengthInsert, charInfo.u.pwc,
(((LENGTH(line) - charInfo.idx) - overflowLength) *
sizeof(wchar_t)));
/*
** copy the new characters into the buffer
*/
memcpy(charInfo.u.pwc, newChars, lengthInsert * sizeof(wchar_t));
}
/*
** This is a helper function that inserts characters into the specified
** buffer in overwrite mode.
*/
static void
_primBufferOverwriteWc
(
const TermBuffer tb,
const short row,
short *col,
wchar_t *newChars,
short numChars,
short *lengthInc,
short *widthInc,
short *widthInsert, /* width of inserted characters */
termChar *returnChars, /* pointer to overflow buffer */
short *returnLength /* count of characters in overflow buffer */
)
{
short charWidth;
short insertOverflow; /* # of newChars that would overflow */
short lengthInsert;
short localCol;
TermLine line;
const char *pStart;
TermCharInfoRec charInfo;
TermCharInfoRec startCharInfo;
line = LINE_OF_TBUF(tb, row);
/*
** make a copy of *col because it may be modified by
** _patchUpChar()
*/
localCol = *col;
/*
** first decide how many characters we can overwrite before
** running off the end of the line.
*/
_countWidth(newChars, numChars, COLS(tb) - localCol, &lengthInsert,
widthInsert);
/*
** We are overwriting:
** - determine the length and width increments
** - put any extra new characters into the overflow buffer
*/
if (localCol == WIDTH(line))
{
/*
** we are appending to the end of the line, this is easy...
*/
*widthInc = *widthInsert;
*lengthInc = lengthInsert;
pStart = (char *)BUFFER(line) + (LENGTH(line) * sizeof(wchar_t));
}
else
{
/*
** we are overwriting characters in the middle of the line...
**
** make sure we are not trying to overwrite the second column
** of a two column character.
*/
_patchUpChar(tb, row, col, &startCharInfo);
/*
** see if we have to deal with the end of the line...
*/
if (localCol + *widthInsert < WIDTH(line))
{
/*
** the line width will remain constant, but the length may
** change...
*/
*widthInc = 0;
/*
** make sure we are not trying to overwrite the first column
** of a two column character.
*/
_DtTermPrimGetCharacterInfo(tb, row, localCol + *widthInsert,
&charInfo);
if ((charInfo.width == 2) &&
(charInfo.startCol == localCol + *widthInsert - 1))
{
/*
** We are about to overwrite column 1 of a 2 column
** character. Replace it with a space before we proceed
** (we make adjustments later to make it look like we
** replaced the second column with a space).
*/
*charInfo.u.pwc = L' ';
/*
** now update the charInfo (since we replaced the 2 column
** character with a single column space)...
*/
charInfo.width = 1;
}
/*
** at this point, startCharInfo points to the first
** character to replace, now we want charInfo.u.pwc
** to point to the character one past the last one
** we want to replace
*/
*lengthInc = lengthInsert - (charInfo.u.pwc - startCharInfo.u.pwc);
if (*lengthInc != 0)
{
memmove(charInfo.u.pwc + *lengthInc, charInfo.u.pwc,
(LENGTH(line) - charInfo.idx) * sizeof(wchar_t));
}
}
else
{
/*
** the line may get wider and longer...
*/
*widthInc = localCol + *widthInsert - WIDTH(line);
*lengthInc = startCharInfo.idx + lengthInsert - LENGTH(line);
}
pStart = startCharInfo.u.pc;
}
/*
** now insert the new characters...
*/
memcpy((void *)pStart, newChars, lengthInsert * sizeof(wchar_t));
/*
** put any overflow into the overflow buffer
*/
*returnLength = numChars - lengthInsert;
if (*returnLength > 0)
{
memcpy(returnChars, newChars + lengthInsert,
*returnLength * sizeof(wchar_t));
}
}
/*
** 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 'returnLength' and a pointer to a buffer containing those characters
** 'returnChars'.
**
** The the new column width of the line is returned as the value of the
** function.
**
** NOTES:
** We are trying to implement mechanism and not policy. This
** routine does a minimum of checking for boundary conditions.
*/
short
_DtTermPrimBufferInsertWc
(
const TermBuffer tb,
const short row,
const short col,
wchar_t *newChars,
short numChars,
Boolean insertFlag, /* if TRUE, insert, else overwrite */
termChar **returnChars, /* pointer to overflow buffer */
short *returnLength /* count of characters in overflow buffer */
)
{
short widthInc = 0; /* incremental change in line width */
short lengthInc = 0; /* incremental change in line length */
short widthInsert; /* column width of chars inserted */
short localCol;
TermLine line;
if (!VALID_ROW(tb, row) || !VALID_COL(tb, col))
{
*returnLength = 0;
return(0);
}
if (isDebugFSet('i', 1)) {
#ifdef BBA
#pragma BBA_IGNORE
#endif /*BBA*/
(void) _termBufferValidateLineWc(tb, row);
}
line = LINE_OF_TBUF(tb, row);
localCol = col;
if (WIDTH(line) < col)
{
/*
** We're adding characters past the current end of line,
** pad it out.
*/
_DtTermPrimBufferPadLineWc(tb, row, col);
}
/*
** It doesn't matter if we're overwriting, or inserting at the end
** of the line, the result is the same...
*/
if (insertFlag == False || col == WIDTH(line))
{
_primBufferOverwriteWc(tb, row, &localCol, newChars, numChars,
&lengthInc, &widthInc, &widthInsert,
*returnChars, returnLength);
}
else
{
_primBufferInsertWc(tb, row, &localCol, newChars, numChars,
&lengthInc, &widthInc, &widthInsert,
*returnChars, returnLength);
}
/*
** Everything's ready:
** - put the characters into the line
** - adjust the line width (_DtTermPrimBufferSetLineWidth won't
** let the line get shorter)...
** - adjust the line length
** - update the enhancements
*/
WIDTH(line) += widthInc;
LENGTH(line) += lengthInc;
/*
** fix up the enhancments...
*/
if (INSERT_ENH(tb))
{
(*INSERT_ENH(tb))(tb, row, col, widthInsert, insertFlag);
}
if (isDebugFSet('i', 1)) {
#ifdef BBA
#pragma BBA_IGNORE
#endif /*BBA*/
(void) _termBufferValidateLineWc(tb, row);
}
return(WIDTH(line));
}
void
_DtTermPrimBufferDeleteWc
(
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 startCharInfo;
TermCharInfoRec stopCharInfo;
if (!VALID_ROW(tb, *row) || !VALID_COL(tb, *col))
{
if (returnChars)
{
*returnChars = NULL;
*returnCount = 0;
}
return;
}
/*
** save some local copies, to originals may get modified
*/
localRow = *row;
localCol = *col;
line = LINE_OF_TBUF(tb, *row);
*width = MAX(0, MIN(WIDTH(line) - localCol, *width));
/*
** there are 3 cases of deleting a character from a line:
** Case 1:
** the cursor is at least 2 positions past the end of the
** line (col - WIDTH(line) > 0)
**
** Case 2:
** the cursor is in the middle of the line (copyCount > 0)
** - move the remaining characters to the left
** - deleteEnhancement
** - adjust WIDTH and LENGTH
**
** Case 3:
** the cursor is at the end of the line (copyCount == 0 and
** col == WIDTH(line))
** - deleteEnhancement
** - adjust WIDTH and LENGTH
*/
if (localCol >= WIDTH(line) || *width == 0)
{
/*
** Handle Case 1...
*/
if (returnChars)
{
*returnChars = NULL;
*returnCount = 0;
}
return;
}
/*
** make any necessary adjustments to 2 column characters...
*/
_patchUpChar(tb, *row, col, &startCharInfo);
(void) _DtTermPrimGetCharacterInfo(tb, localRow,
MIN(WIDTH(line), localCol + *width), &stopCharInfo);
if ((stopCharInfo.width == 2) &&
(stopCharInfo.startCol == localCol + *width - 1))
{
/*
** do not try to delete column 1 of 2...
**
** replace the 2 column character with two one column spaces...
*/
*stopCharInfo.u.pwc = L' ';
memmove(stopCharInfo.u.pwc + 1, stopCharInfo.u.pwc,
(LENGTH(line) - stopCharInfo.idx) * sizeof(wchar_t));
/*
** now make stopCharInfo point at the new space
*/
stopCharInfo.width = 1;
stopCharInfo.startCol++;
stopCharInfo.u.pwc++;
stopCharInfo.idx++;
LENGTH(line)++;
}
/*
** Save the current characters before we overwrite them
** (if returnChars is non-NULL 0)
*/
if (returnChars != NULL)
{
*returnCount = (stopCharInfo.idx - startCharInfo.idx) * sizeof(wchar_t);
*returnChars = (termChar *)XtMalloc(*returnCount);
memmove(*returnChars, startCharInfo.u.pwc, *returnCount);
}
/*
** Cases 2, 3, and 4 require that we delete the enhancement...
*/
if (DELETE_ENH(tb))
{
(*DELETE_ENH(tb))(tb, localRow, localCol, *width);
}
copyCount = MAX(0, LENGTH(line) - stopCharInfo.idx);
if (copyCount > 0)
{
/*
** handle case 2
*/
memmove(startCharInfo.u.pwc, stopCharInfo.u.pwc,
copyCount * sizeof(wchar_t));
}
/*
** Cases 2 and 3 require that we decrement the line length...
*/
WIDTH(line) -= *width;
LENGTH(line) -= (stopCharInfo.idx - startCharInfo.idx);
/*
** update info we need to return...
*/
*width = stopCharInfo.startCol - startCharInfo.startCol;
}
/*
** Pad the requested row from the current width to 'newWidth' with spaces...
*/
void
_DtTermPrimBufferPadLineWc
(
const TermBuffer tb,
const short row,
const short width
)
{
short i;
short widthInc;
TermLine line;
wchar_t *pwc;
line = LINE_OF_TBUF(tb, row);
if (isDebugFSet('i', 1)) {
#ifdef BBA
#pragma BBA_IGNORE
#endif /*BBA*/
(void) _termBufferValidateLineWc(tb, row);
}
/*
** if this line is part of the selection, disown the selection...
*/
if (IS_IN_SELECTION(line, MIN(width, WIDTH(line)),
MAX(width, WIDTH(line))))
{
(void) _DtTermPrimSelectDisown(WIDGET(tb));
}
widthInc = MIN(COLS(tb), width) - WIDTH(line);
for (i = 0, pwc = (wchar_t *)BUFFER(line) + MAX(0, LENGTH(line));
i < widthInc;
i++, pwc++)
{
*pwc = L' ';
LENGTH(line)++;
}
if (CLEAR_ENH(tb))
{
(*CLEAR_ENH(tb))(tb, row, WIDTH(line), widthInc);
}
_DtTermPrimBufferSetLineWidth(tb, row, WIDTH(line) + widthInc);
if (isDebugFSet('i', 1)) {
#ifdef BBA
#pragma BBA_IGNORE
#endif /*BBA*/
_termBufferValidateLineWc(tb, row);
}
}
/*
** Clear the line to the new width (just reset the line width).
*/
Boolean
_DtTermPrimBufferClearLineWc
(
const TermBuffer tb,
const short row,
short newWidth
)
{
TermLine line;
TermCharInfoRec charInfo;
short newLength;
/*
** Some simple bounds checking.
*/
if (!VALID_ROW(tb, row))
{
return(False);
}
/*
** force the width to the desired value
**
** (We take the direct approach because _DtTermPrimBufferSetLineWidth
** doesn't allow the line width to decrease.)
*/
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));
if (newWidth < WIDTH(line))
{
if (newWidth == 0)
{
newLength = 0;
}
else
{
/*
** handle the case of clearing the second column of a two column
** character...
*/
_DtTermPrimGetCharacterInfo(tb, row, MAX(0, newWidth - 1),
&charInfo);
if ((charInfo.width == 2 ) &&
(charInfo.startCol == MAX(0, newWidth - 1)))
{
/*
** we are clearing column 2 of 2, replace column 1 of 1 with
** a space...
*/
*charInfo.u.pwc = L' ';
}
newLength = charInfo.idx + 1;
}
/*
** 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) = newLength;
}
return(True);
}
/*
** replace all characters from startCol upto stopCol with spaces,
**
** NOTE:
** we are dealing with double width characters, the width needs
** to remain constant, but the length may have to change since we
** may replace a double width character with a single width
** character.
*/
void
_DtTermPrimBufferEraseWc
(
TermBuffer tb,
short row,
short startCol,
short stopCol
)
{
TermCharInfoRec startCharInfo;
TermCharInfoRec stopCharInfo;
short localCol;
TermLine line;
wchar_t *pwchar;
short lengthErase;
short lengthInc;
/*
** make sure we are not trying to erase the second column
** of a two column character.
*/
localCol = startCol;
_patchUpChar(tb, row, &localCol, &startCharInfo);
/*
** make sure we are not trying to erase the first column
** of a two column character.
*/
_DtTermPrimGetCharacterInfo(tb, row, stopCol, &stopCharInfo);
if ((stopCharInfo.width == 2) &&
(stopCharInfo.startCol == stopCol))
{
#ifdef NOTDEF
/*
** We are about to overwrite column 1 of a 2 column
** character. Replace it with a space before we proceed
** (we make adjustments later to make it look like we
** replaced the second column with a space).
*/
*stopCharInfo.u.pwc = L' ';
/*
** now update the charInfo (since we replaced the 2 column
** character with a single column space)...
*/
stopCharInfo.width = 1;
#endif /* NOTDEF */
(void) stopCol++;
}
/*
** at this point, startCharInfo points to the first character
** to erase, and stopCharInfo points to the last character
** we want to erase, make sure there is enough space between
** the two to accommodate the replacement spaces...
*/
lengthErase = stopCol - startCol + 1;
lengthInc = lengthErase - (stopCharInfo.u.pwc - startCharInfo.u.pwc + 1);
if (lengthInc != 0)
{
/*
** the length will have to change, make the necessary adjustments
*/
memmove(stopCharInfo.u.pwc + lengthInc, stopCharInfo.u.pwc,
(LENGTH(LINE_OF_TBUF(tb, row)) - stopCharInfo.idx) *
sizeof(wchar_t));
LENGTH(LINE_OF_TBUF(tb, row)) += lengthInc;
}
/*
** replace the characters with spaces...
*/
for (pwchar = startCharInfo.u.pwc;
pwchar < startCharInfo.u.pwc + lengthErase;
pwchar++)
{
*pwchar = L' ';
}
}
#ifdef BBA
#pragma BBA_IGNORE
#endif /*BBA*/
static void
_termBufferValidateLineWc
(
const TermBuffer tb,
const short row
)
{
wchar_t *pwc;
TermLine line;
line = LINE_OF_TBUF(tb, row);
for (pwc = (wchar_t *)BUFFER(line);
pwc < (wchar_t *)BUFFER(line) + LENGTH(line);
pwc++)
{
if (wcwidth(*pwc) == -1)
{
fprintf(stderr, "_termBufferValidateLineWc: invalid wide char\n");
/* replace the character with a space... */
*pwc = L' ';
break;
}
}
}
#if (defined(TEST) || defined(__CODECENTER__) || defined(DEBUG))
static void
_termBufferPrintLine
(
const TermBuffer tb,
const short row
)
{
TermLine line;
wchar_t *pChar;
short j;
printf("Line: %d\n", row);
line = LINE_OF_TBUF(tb, row);
printf(" length: %3d\n", WIDTH(line));
if (WIDTH(line) > 0)
{
printf(" buffer: <");
pChar = BUFFER(line);
for (j = 0; j < WIDTH(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 */