fl_text_buffer.cxx
来自「SRI international 发布的OAA框架软件」· CXX 代码 · 共 1,884 行 · 第 1/5 页
CXX
1,884 行
** routines which need to position the cursor after a delete operation)
*/
void Fl_Text_Buffer::remove_rectangular_( int start, int end, int rectStart,
int rectEnd, int *replaceLen, int *endPos ) {
int nLines, lineStart, lineEnd, len, endOffset;
char *outStr, *outPtr, *expText;
const char *s, *line;
/* allocate a buffer for the replacement string large enough to hold
possibly expanded tabs as well as an additional FL_TEXT_MAX_EXP_CHAR_LEN * 2
characters per line for padding where tabs and control characters cross
the edges of the selection */
start = line_start( start );
end = line_end( end );
nLines = count_lines( start, end ) + 1;
s = text_range( start, end );
expText = expandTabs( s, 0, mTabDist, mNullSubsChar, &len );
free( (void *) s );
free( (void *) expText );
outStr = (char *)malloc( len + nLines * FL_TEXT_MAX_EXP_CHAR_LEN * 2 + 1 );
/* loop over all lines in the buffer between start and end removing
the text between rectStart and rectEnd and padding appropriately */
lineStart = start;
outPtr = outStr;
while ( lineStart <= mLength && lineStart <= end ) {
lineEnd = line_end( lineStart );
line = text_range( lineStart, lineEnd );
deleteRectFromLine( line, rectStart, rectEnd, mTabDist,
mUseTabs, mNullSubsChar, outPtr, &len, &endOffset );
free( (void *) line );
outPtr += len;
*outPtr++ = '\n';
lineStart = lineEnd + 1;
}
if ( outPtr != outStr )
outPtr--; /* trim back off extra newline */
*outPtr = '\0';
/* replace the text between start and end with the newly created string */
remove_( start, end );
insert_( start, outStr );
*replaceLen = outPtr - outStr;
*endPos = start + ( outPtr - outStr ) - len + endOffset;
free( (void *) outStr );
}
/*
** Overlay a rectangular area of text without calling the modify callbacks.
** "nDeleted" and "nInserted" return the number of characters deleted and
** inserted beginning at the start of the line containing "startPos".
** "endPos" returns buffer position of the lower left edge of the inserted
** column (as a hint for routines which need to set a cursor position).
*/
void Fl_Text_Buffer::overlay_rectangular_(int startPos, int rectStart,
int rectEnd, const char *insText,
int *nDeleted, int *nInserted,
int *endPos ) {
int nLines, start, end, lineStart, lineEnd;
int expInsLen, len, endOffset;
char *c, *outStr, *outPtr, *expText, *insLine;
const char *line;
const char *insPtr;
/* Allocate a buffer for the replacement string large enough to hold
possibly expanded tabs in the inserted text, as well as per line: 1)
an additional 2*FL_TEXT_MAX_EXP_CHAR_LEN characters for padding where tabs
and control characters cross the column of the selection, 2) up to
"column" additional spaces per line for padding out to the position
of "column", 3) padding up to the width of the inserted text if that
must be padded to align the text beyond the inserted column. (Space
for additional newlines if the inserted text extends beyond the end
of the buffer is counted with the length of insText) */
start = line_start( startPos );
nLines = countLines( insText ) + 1;
end = line_end( skip_lines( start, nLines - 1 ) );
expText = expandTabs( insText, 0, mTabDist, mNullSubsChar,
&expInsLen );
free( (void *) expText );
outStr = (char *)malloc( end - start + expInsLen +
nLines * ( rectEnd + FL_TEXT_MAX_EXP_CHAR_LEN ) + 1 );
/* Loop over all lines in the buffer between start and end overlaying the
text between rectStart and rectEnd and padding appropriately. Trim
trailing space from line (whitespace at the ends of lines otherwise
tends to multiply, since additional padding is added to maintain it */
outPtr = outStr;
lineStart = start;
insPtr = insText;
for (;;) {
lineEnd = line_end( lineStart );
line = text_range( lineStart, lineEnd );
insLine = copyLine( insPtr, &len );
insPtr += len;
overlayRectInLine( line, insLine, rectStart, rectEnd, mTabDist,
mUseTabs, mNullSubsChar, outPtr, &len, &endOffset );
free( (void *) line );
free( (void *) insLine );
for ( c = outPtr + len - 1; c > outPtr && isspace( *c ); c-- )
len--;
outPtr += len;
*outPtr++ = '\n';
lineStart = lineEnd < mLength ? lineEnd + 1 : mLength;
if ( *insPtr == '\0' )
break;
insPtr++;
}
if ( outPtr != outStr )
outPtr--; /* trim back off extra newline */
*outPtr = '\0';
/* replace the text between start and end with the new stuff */
remove_( start, end );
insert_( start, outStr );
*nInserted = outPtr - outStr;
*nDeleted = end - start;
*endPos = start + ( outPtr - outStr ) - len + endOffset;
free( (void *) outStr );
}
/*
** Insert characters from single-line string "insLine" in single-line string
** "line" at "column", leaving "insWidth" space before continuing line.
** "outLen" returns the number of characters written to "outStr", "endOffset"
** returns the number of characters from the beginning of the string to
** the right edge of the inserted text (as a hint for routines which need
** to position the cursor).
*/
static void insertColInLine( const char *line, char *insLine, int column, int insWidth,
int tabDist, int useTabs, char nullSubsChar, char *outStr, int *outLen,
int *endOffset ) {
char * c, *outPtr, *retabbedStr;
const char *linePtr;
int indent, toIndent, len, postColIndent;
/* copy the line up to "column" */
outPtr = outStr;
indent = 0;
for ( linePtr = line; *linePtr != '\0'; linePtr++ ) {
len = Fl_Text_Buffer::character_width( *linePtr, indent, tabDist, nullSubsChar );
if ( indent + len > column )
break;
indent += len;
*outPtr++ = *linePtr;
}
/* If "column" falls in the middle of a character, and the character is a
tab, leave it off and leave the indent short and it will get padded
later. If it's a control character, insert it and adjust indent
accordingly. */
if ( indent < column && *linePtr != '\0' ) {
postColIndent = indent + len;
if ( *linePtr == '\t' )
linePtr++;
else {
*outPtr++ = *linePtr++;
indent += len;
}
} else
postColIndent = indent;
/* If there's no text after the column and no text to insert, that's all */
if ( *insLine == '\0' && *linePtr == '\0' ) {
*outLen = *endOffset = outPtr - outStr;
return;
}
/* pad out to column if text is too short */
if ( indent < column ) {
addPadding( outPtr, indent, column, tabDist, useTabs, nullSubsChar, &len );
outPtr += len;
indent = column;
}
/* Copy the text from "insLine" (if any), recalculating the tabs as if
the inserted string began at column 0 to its new column destination */
if ( *insLine != '\0' ) {
retabbedStr = realignTabs( insLine, 0, indent, tabDist, useTabs,
nullSubsChar, &len );
for ( c = retabbedStr; *c != '\0'; c++ ) {
*outPtr++ = *c;
len = Fl_Text_Buffer::character_width( *c, indent, tabDist, nullSubsChar );
indent += len;
}
free( (void *) retabbedStr );
}
/* If the original line did not extend past "column", that's all */
if ( *linePtr == '\0' ) {
*outLen = *endOffset = outPtr - outStr;
return;
}
/* Pad out to column + width of inserted text + (additional original
offset due to non-breaking character at column) */
toIndent = column + insWidth + postColIndent - column;
addPadding( outPtr, indent, toIndent, tabDist, useTabs, nullSubsChar, &len );
outPtr += len;
indent = toIndent;
/* realign tabs for text beyond "column" and write it out */
retabbedStr = realignTabs( linePtr, postColIndent, indent, tabDist,
useTabs, nullSubsChar, &len );
strcpy( outPtr, retabbedStr );
free( (void *) retabbedStr );
*endOffset = outPtr - outStr;
*outLen = ( outPtr - outStr ) + len;
}
/*
** Remove characters in single-line string "line" between displayed positions
** "rectStart" and "rectEnd", and write the result to "outStr", which is
** assumed to be large enough to hold the returned string. Note that in
** certain cases, it is possible for the string to get longer due to
** expansion of tabs. "endOffset" returns the number of characters from
** the beginning of the string to the point where the characters were
** deleted (as a hint for routines which need to position the cursor).
*/
static void deleteRectFromLine( const char *line, int rectStart, int rectEnd,
int tabDist, int useTabs, char nullSubsChar, char *outStr, int *outLen,
int *endOffset ) {
int indent, preRectIndent, postRectIndent, len;
const char *c;
char *retabbedStr, *outPtr;
/* copy the line up to rectStart */
outPtr = outStr;
indent = 0;
for ( c = line; *c != '\0'; c++ ) {
if ( indent > rectStart )
break;
len = Fl_Text_Buffer::character_width( *c, indent, tabDist, nullSubsChar );
if ( indent + len > rectStart && ( indent == rectStart || *c == '\t' ) )
break;
indent += len;
*outPtr++ = *c;
}
preRectIndent = indent;
/* skip the characters between rectStart and rectEnd */
for ( ; *c != '\0' && indent < rectEnd; c++ )
indent += Fl_Text_Buffer::character_width( *c, indent, tabDist, nullSubsChar );
postRectIndent = indent;
/* If the line ended before rectEnd, there's nothing more to do */
if ( *c == '\0' ) {
*outPtr = '\0';
*outLen = *endOffset = outPtr - outStr;
return;
}
/* fill in any space left by removed tabs or control characters
which straddled the boundaries */
indent = max( rectStart + postRectIndent - rectEnd, preRectIndent );
addPadding( outPtr, preRectIndent, indent, tabDist, useTabs, nullSubsChar,
&len );
outPtr += len;
/* Copy the rest of the line. If the indentation has changed, preserve
the position of non-whitespace characters by converting tabs to
spaces, then back to tabs with the correct offset */
retabbedStr = realignTabs( c, postRectIndent, indent, tabDist, useTabs,
nullSubsChar, &len );
strcpy( outPtr, retabbedStr );
free( (void *) retabbedStr );
*endOffset = outPtr - outStr;
*outLen = ( outPtr - outStr ) + len;
}
/*
** Overlay characters from single-line string "insLine" on single-line string
** "line" between displayed character offsets "rectStart" and "rectEnd".
** "outLen" returns the number of characters written to "outStr", "endOffset"
** returns the number of characters from the beginning of the string to
** the right edge of the inserted text (as a hint for routines which need
** to position the cursor).
*/
static void overlayRectInLine( const char *line, char *insLine, int rectStart,
int rectEnd, int tabDist, int useTabs, char nullSubsChar, char *outStr,
int *outLen, int *endOffset ) {
char * c, *outPtr, *retabbedStr;
int inIndent, outIndent, len, postRectIndent;
const char *linePtr;
/* copy the line up to "rectStart" */
outPtr = outStr;
inIndent = outIndent = 0;
for ( linePtr = line; *linePtr != '\0'; linePtr++ ) {
len = Fl_Text_Buffer::character_width( *linePtr, inIndent, tabDist, nullSubsChar );
if ( inIndent + len > rectStart )
break;
inIndent += len;
outIndent += len;
*outPtr++ = *linePtr;
}
/* If "rectStart" falls in the middle of a character, and the character
is a tab, leave it off and leave the outIndent short and it will get
padded later. If it's a control character, insert it and adjust
outIndent accordingly. */
if ( inIndent < rectStart && *linePtr != '\0' ) {
if ( *linePtr == '\t' ) {
linePtr++;
inIndent += len;
} else {
*outPtr++ = *linePtr++;
outIndent += len;
inIndent += len;
}
}
/* skip the characters between rectStart and rectEnd */
postRectIndent = rectEnd;
for ( ; *linePtr != '\0'; linePtr++ ) {
inIndent += Fl_Text_Buffer::character_width( *linePtr, inIndent, tabDist, nullSubsChar );
if ( inIndent >= rectEnd ) {
linePtr++;
postRectIndent = inIndent;
break;
}
}
/* If there's no text after rectStart and no text to insert, that's all */
if ( *insLine == '\0' && *linePtr == '\0' ) {
*outLen = *endOffset = outPtr - outStr;
return;
}
/* pad out to rectStart if text is too short */
if ( outIndent < rectStart ) {
addPadding( outPtr, outIndent, rectStart, tabDist, useTabs, nullSubsChar,
&len );
outPtr += len;
}
outIndent = rectStart;
/* Copy the text from "insLine" (if any), recalculating the tabs as if
the inserted string began at column 0 to its new column destination */
if ( *insLine != '\0' ) {
retabbedStr = realignTabs( insLine, 0, rectStart, tabDist, useTabs,
nullSubsChar, &len );
for ( c = retabbedStr; *c != '\0'; c++ ) {
*outPtr++ = *c;
len = Fl_Text_Buffer::character_width( *c, outIndent, tabDist, nullSubsChar );
outIndent += len;
}
free( (void *) retabbedStr );
}
/* If the original line did not extend past "rectStart", that's all */
if ( *linePtr == '\0' ) {
*outLen = *endOffset = outPtr - outStr;
return;
}
/* Pad out to rectEnd + (additional original offset
due to non-breaking character at right boundary) */
addPadding( outPtr, outIndent, postRectIndent, tabDist, useTabs,
nullSubsChar, &len );
outPtr += len;
outIndent = postRectIndent;
/* copy the text beyond "rectEnd" */
strcpy( outPtr, linePtr );
*endOffset = outPtr - outStr;
*outLen = ( outPtr - outStr ) + strlen( linePtr );
}
void Fl_Text_Selection::set( int startpos, int endpos ) {
mSelected = startpos != endpos;
mRectangular = 0;
mStart = min( startpos, endpos );
mEnd = max( startpos, endpos );
}
void Fl_Text_Selection::set_rectangul
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?