Author: matt
Date: 2010-04-05 15:18:14 -0700 (Mon, 05 Apr 2010)
New Revision: 7449
Log:
Another update to Fl_Text_Buffer. This is by no means perfect, but at least it
currently does not crash (I am so easily satisfied :-P).
Modified:
branches/branch-1.3/FL/Fl_Text_Buffer.H
branches/branch-1.3/src/Fl_Text_Buffer.cxx
branches/branch-1.3/src/Fl_Text_Display.cxx
Modified: branches/branch-1.3/FL/Fl_Text_Buffer.H
===================================================================
--- branches/branch-1.3/FL/Fl_Text_Buffer.H 2010-04-05 21:56:59 UTC (rev
7448)
+++ branches/branch-1.3/FL/Fl_Text_Buffer.H 2010-04-05 22:18:14 UTC (rev
7449)
@@ -211,15 +211,16 @@
~Fl_Text_Buffer();
/**
- Returns the number of characters in the buffer.
- \todo unicode check
+ \brief Returns the number of bytes in the buffer.
+ \return size of text in bytes
*/
int length() const { return mLength; }
/**
- Get the entire contents of a text buffer. Memory is allocated to contain
- the returned string, which the caller must free.
- \todo unicode check
+ \brief Get a copy of the entire contents of the text buffer.
+ Memory is allocated to contain the returned string, which the caller
+ must free.
+ \return newly allocated text buffer - must be free'd
*/
char* text() const;
@@ -230,11 +231,14 @@
void text(const char* text);
/**
+ \brief Get a copy of a part of the text buffer.
Return a copy of the text between \p start and \p end character positions
from text buffer \p buf. Positions start at 0, and the range does not
include the character pointed to by \p end.
When you are done with the text, free it using the free() function.
- \todo unicode check
+ \param start byte offset to first character
+ \param end byte offset after last character in range
+ \return newly allocated text buffer - must be free'd
*/
char* text_range(int start, int end) const;
@@ -659,22 +663,25 @@
control code). Returns the number of characters added to \p outStr.
\p indent is the number of characters from the start of the line
for figuring tabs of length \p tabDist. Output string is guaranteed
- to be shorter or equal in length to FL_TEXT_MAX_EXP_CHAR_LEN
+ to be shorter or equal in length to FL_TEXT_MAX_EXP_CHAR_LEN
Tabs and other control characters are given special treatment.
- \p nulSubsChar represent the null character to be transformed in \<nul\>
- \todo unicode check
+ \param src address of utf-8 text
+ \param indent
+ \param[out] outStr write substitution here
+ \param tabDist
+ \return number of byte in substitution
*/
- static int expand_character(char c, int indent, char* outStr, int tabDist);
+ static int expand_character(const char *src, int indent, char* outStr, int
tabDist);
/**
Return the length in displayed characters of character \p c expanded
- for display (as discussed above in expand_character() ). If the
- buffer for which the character width is being measured is doing null
- substitution, nullSubsChar should be passed as that character (or nul
- to ignore).
- \todo unicode check
+ for display (as discussed above in expand_character() ).
+ \param src address of utf-8 text
+ \param indent
+ \param tabDist
+ \return number of byte in substitution
*/
- static int character_width(char c, int indent, int tabDist);
+ static int character_width(const char *src, int indent, int tabDist);
/**
Count the number of displayed characters between buffer position
@@ -689,6 +696,9 @@
Count forward from buffer position \p startPos in displayed characters
(displayed characters are the characters shown on the screen to represent
characters in the buffer, where tabs and control characters are expanded)
+ \param lineStartPos byte offset into buffer
+ \param nChars number of bytes that are sent to the display
+ \return byte offset in input after all output bytes are sent
\todo unicode check
*/
int skip_displayed_characters(int lineStartPos, int nChars);
@@ -929,6 +939,14 @@
*/
void update_selections(int pos, int nDeleted, int nInserted);
+ /**
+ Convert a byte offset in buffer into a memory address.
+ */
+ const char *address(int pos) const
+ { return (pos < mGapStart) ? mBuf+pos : mBuf+pos+mGapEnd-mGapStart; }
+ char *address(int pos)
+ { return (pos < mGapStart) ? mBuf+pos : mBuf+pos+mGapEnd-mGapStart; }
+
Fl_Text_Selection mPrimary; /**< highlighted areas */
Fl_Text_Selection mSecondary; /**< highlighted areas */
Fl_Text_Selection mHighlight; /**< highlighted areas */
Modified: branches/branch-1.3/src/Fl_Text_Buffer.cxx
===================================================================
--- branches/branch-1.3/src/Fl_Text_Buffer.cxx 2010-04-05 21:56:59 UTC (rev
7448)
+++ branches/branch-1.3/src/Fl_Text_Buffer.cxx 2010-04-05 22:18:14 UTC (rev
7449)
@@ -209,14 +209,19 @@
}
}
+
+// This function copies verbose whatever is in front and after the gap into a
+// single buffer.
+// - unicode ok
char *Fl_Text_Buffer::text() const {
- char *t = (char *) malloc(mLength + 1); //UTF8: we alloc from a string
len, but as (non-utf8 aware) strlen()
- // is used to affect mLength,
it is equal to buffer size - 1 and thus correct.
+ char *t = (char *) malloc(mLength + 1);
memcpy(t, mBuf, mGapStart);
memcpy(&t[mGapStart], &mBuf[mGapEnd], mLength - mGapStart);
t[mLength] = '\0';
return t;
-} void Fl_Text_Buffer::text(const char *t)
+}
+
+void Fl_Text_Buffer::text(const char *t)
{
call_predelete_callbacks(0, length());
@@ -249,6 +254,9 @@
free((void *) deletedText);
}
+
+// Creates a new buffer and copies verbose from around the gap.
+// - unicode ok
char *Fl_Text_Buffer::text_range(int start, int end) const {
char *s = NULL;
@@ -284,6 +292,8 @@
return s;
}
+
+// FIXME: a character must be UCS-4 encoded
char Fl_Text_Buffer::character(int pos) const {
if (pos < 0 || pos >= mLength)
return '\0';
@@ -291,7 +301,10 @@
return mBuf[pos];
else
return mBuf[pos + mGapEnd - mGapStart];
-} void Fl_Text_Buffer::insert(int pos, const char *text)
+}
+
+
+void Fl_Text_Buffer::insert(int pos, const char *text)
{
/* if pos is not contiguous to existing text, make it */
if (pos > mLength)
@@ -930,25 +943,23 @@
} return pos;
}
+
+// Expand from the byte representation into some readable text.
+// Under unicode, this is not really needed because all characters should
+// be prinatble one way or the other. But since we use this to (badly) simulate
+// tabs, we can leave this here anyway.
+// - unicode ok
int Fl_Text_Buffer::expand_character(int pos, int indent, char *outStr) const {
- char c = character(pos);
- int ret = expand_character(c, indent, outStr, mTabDist);
- if (ret > 1 && (c & 0x80))
- {
- int i;
- i = fl_utf8len(c);
- while (i > 1) {
- i--;
- pos++;
- outStr++;
- *outStr = character(pos);
- }}
-
- return ret;
+ const char *src = address(pos);
+ return expand_character(src, indent, outStr, mTabDist);
}
-int Fl_Text_Buffer::expand_character(char c, int indent, char *outStr, int
tabDist)
+
+// static function and counterpart to "character_width"
+// - unicode ok
+int Fl_Text_Buffer::expand_character(const char *src, int indent, char
*outStr, int tabDist)
{
+ char c = *src;
/* Convert tabs to spaces */
if (c == '\t') {
int nSpaces = tabDist - (indent % tabDist);
@@ -958,7 +969,6 @@
}
/* Convert control codes to readable character sequences */
- /*... is this safe with international character sets? */
if (((unsigned char) c) <= 31) {
sprintf(outStr, "<%s>", ControlCodeTable[(unsigned char) c]);
return strlen(outStr);
@@ -972,8 +982,9 @@
*outStr = c;
return 1;
} else if (c & 0x80) {
- *outStr = c;
- return fl_utf8len(c);
+ int i, n = fl_utf8len(c);
+ for (i=0; i<n; i++) *outStr++ = *src++;
+ return n;
}
/* Otherwise, just return the character */
@@ -981,9 +992,16 @@
return 1;
}
-int Fl_Text_Buffer::character_width(char c, int indent, int tabDist)
+
+// This function takes a character and optionally converts it into a little
+// string which will replace the character on screen. This function returns
+// the number of bytes in the replacement string, but *not* the number of
+// bytes in the original character!
+// - unicode ok
+int Fl_Text_Buffer::character_width(const char *src, int indent, int tabDist)
{
/* Note, this code must parallel that in Fl_Text_Buffer::ExpandCharacter */
+ char c = *src;
if (c == '\t') {
return tabDist - (indent % tabDist);
} else if (((unsigned char) c) <= 31) {
@@ -1011,18 +1029,22 @@
while (pos < targetPos)
charCount += expand_character(pos++, charCount, expandedChar);
return charCount;
-} int Fl_Text_Buffer::skip_displayed_characters(int lineStartPos,
- int nChars)
+}
+
+
+// All values are number of bytes.
+// - unicode ok
+int Fl_Text_Buffer::skip_displayed_characters(int lineStartPos, int nChars)
{
int pos = lineStartPos;
- char c;
for (int charCount = 0; charCount < nChars && pos < mLength;) {
- c = character(pos);
+ const char *src = address(pos);
+ char c = *src;
if (c == '\n')
return pos;
- charCount += character_width(c, charCount, mTabDist);
- pos++;
+ charCount += character_width(src, charCount, mTabDist);
+ pos += fl_utf8len(c);
}
return pos;
}
@@ -1488,7 +1510,7 @@
for (linePtr = line; *linePtr != '\0'; linePtr++) {
len =
- Fl_Text_Buffer::character_width(*linePtr, indent, tabDist);
+ Fl_Text_Buffer::character_width(linePtr, indent, tabDist);
if (indent + len > column)
break;
indent += len;
@@ -1532,7 +1554,7 @@
for (const char *c = retabbedStr; *c != '\0'; c++) {
*outPtr++ = *c;
len =
- Fl_Text_Buffer::character_width(*c, indent, tabDist);
+ Fl_Text_Buffer::character_width(c, indent, tabDist);
indent += len;
}
free((void *) retabbedStr);
@@ -1583,7 +1605,7 @@
if (indent > rectStart)
break;
len =
- Fl_Text_Buffer::character_width(*c, indent, tabDist);
+ Fl_Text_Buffer::character_width(c, indent, tabDist);
if (indent + len > rectStart && (indent == rectStart || *c == '\t'))
break;
indent += len;
@@ -1594,7 +1616,7 @@
/* skip the characters between rectStart and rectEnd */
for (; *c != '\0' && indent < rectEnd; c++)
indent +=
- Fl_Text_Buffer::character_width(*c, indent, tabDist);
+ Fl_Text_Buffer::character_width(c, indent, tabDist);
int postRectIndent = indent;
/* If the line ended before rectEnd, there's nothing more to do */
@@ -1641,7 +1663,7 @@
for (; *linePtr != '\0'; linePtr++) {
len =
- Fl_Text_Buffer::character_width(*linePtr, inIndent, tabDist);
+ Fl_Text_Buffer::character_width(linePtr, inIndent, tabDist);
if (inIndent + len > rectStart)
break;
inIndent += len;
@@ -1668,7 +1690,7 @@
int postRectIndent = rectEnd;
for (; *linePtr != '\0'; linePtr++) {
inIndent +=
- Fl_Text_Buffer::character_width(*linePtr, inIndent, tabDist);
+ Fl_Text_Buffer::character_width(linePtr, inIndent, tabDist);
if (inIndent >= rectEnd) {
linePtr++;
postRectIndent = inIndent;
@@ -1697,7 +1719,7 @@
for (const char *c = retabbedStr; *c != '\0'; c++) {
*outPtr++ = *c;
len =
- Fl_Text_Buffer::character_width(*c, outIndent, tabDist);
+ Fl_Text_Buffer::character_width(c, outIndent, tabDist);
outIndent += len;
}
free((void *) retabbedStr);
@@ -1852,8 +1874,8 @@
if (useTabs) {
while (indent < toIndent) {
- len =
- Fl_Text_Buffer::character_width('\t', indent, tabDist);
+ static char t = '\t';
+ len = Fl_Text_Buffer::character_width(&t, indent, tabDist);
if (len > 1 && indent + len <= toIndent) {
*outPtr++ = '\t';
indent += len;
@@ -2115,14 +2137,14 @@
{
int width = 0, maxWidth = 0;
- for (const char *c = text; *c != '\0'; c++) {
+ for (const char *c = text; *c != '\0'; c++) { // FIXME: increment is wrong!
if (*c == '\n') {
if (width > maxWidth)
maxWidth = width;
width = 0;
} else
width +=
- Fl_Text_Buffer::character_width(*c, width, tabDist);
+ Fl_Text_Buffer::character_width(c, width, tabDist);
}
if (width > maxWidth)
return width;
@@ -2145,7 +2167,7 @@
if (c == '\n')
break;
width =
- Fl_Text_Buffer::character_width(c, indent, mTabDist);
+ Fl_Text_Buffer::character_width(&c, indent, mTabDist); // FIXME: c si not
unicode
if (indent + width > rectStart) {
if (indent != rectStart && c != '\t') {
pos++;
@@ -2163,7 +2185,7 @@
if (c == '\n')
break;
width =
- Fl_Text_Buffer::character_width(c, indent, mTabDist);
+ Fl_Text_Buffer::character_width(&c, indent, mTabDist); // FIXME: c is not
unicode
indent += width;
if (indent > rectEnd) {
if (indent - width != rectEnd && c != '\t')
@@ -2220,7 +2242,7 @@
for (c = text; *c != '\0'; c++) {
if (*c == '\t') {
len =
- Fl_Text_Buffer::character_width(*c, indent, tabDist);
+ Fl_Text_Buffer::character_width(c, indent, tabDist);
outLen += len;
indent += len;
} else if (*c == '\n') {
@@ -2228,7 +2250,7 @@
outLen++;
} else {
indent +=
- Fl_Text_Buffer::character_width(*c, indent, tabDist);
+ Fl_Text_Buffer::character_width(c, indent, tabDist);
outLen++;
}
}
@@ -2240,7 +2262,7 @@
for (c = text; *c != '\0'; c++) {
if (*c == '\t') {
len =
- Fl_Text_Buffer::expand_character(*c, indent, outPtr, tabDist);
+ Fl_Text_Buffer::expand_character(c, indent, outPtr, tabDist);
outPtr += len;
indent += len;
} else if (*c == '\n') {
@@ -2248,7 +2270,7 @@
*outPtr++ = *c;
} else {
indent +=
- Fl_Text_Buffer::character_width(*c, indent, tabDist);
+ Fl_Text_Buffer::character_width(c, indent, tabDist);
*outPtr++ = *c;
}
}
@@ -2271,8 +2293,9 @@
for (const char *c = text; *c != '\0';) {
if (*c == ' ') {
+ static char tab = '\t';
len =
- Fl_Text_Buffer::expand_character('\t', indent, expandedChar, tabDist);
+ Fl_Text_Buffer::expand_character(&tab, indent, expandedChar, tabDist);
if (len >= 3 && !strncmp(c, expandedChar, len)) {
c += len;
*outPtr++ = '\t';
Modified: branches/branch-1.3/src/Fl_Text_Display.cxx
===================================================================
--- branches/branch-1.3/src/Fl_Text_Display.cxx 2010-04-05 21:56:59 UTC (rev
7448)
+++ branches/branch-1.3/src/Fl_Text_Display.cxx 2010-04-05 22:18:14 UTC (rev
7449)
@@ -629,7 +629,7 @@
startIndent = mBuffer->count_displayed_characters( lineStart, startPos );
indent = startIndent;
for ( c = text; *c != '\0'; c++ )
- indent += Fl_Text_Buffer::character_width( *c, indent, buf->tab_distance()
);
+ indent += Fl_Text_Buffer::character_width( c, indent, buf->tab_distance()
);
endIndent = indent;
/* find which characters to remove, and if necessary generate additional
@@ -641,7 +641,7 @@
ch = buf->character( p );
if ( ch == '\n' )
break;
- indent += Fl_Text_Buffer::character_width( ch, indent, buf->tab_distance()
);
+ indent += Fl_Text_Buffer::character_width( &ch, indent,
buf->tab_distance() ); // FIXME: not unicode
if ( indent == endIndent ) {
p++;
break;
@@ -722,18 +722,12 @@
to "pos" to calculate the X coordinate */
xStep = text_area.x - mHorizOffset;
outIndex = 0;
- for ( charIndex = 0; charIndex < lineLen && charIndex < pos - lineStartPos;
charIndex++ ) {
- charLen = Fl_Text_Buffer::expand_character( lineStr[ charIndex ],
outIndex, expandedChar,
+ for (charIndex = 0;
+ charIndex < lineLen && charIndex < pos - lineStartPos;
+ charIndex += fl_utf8len(lineStr[charIndex]) )
+ {
+ charLen = Fl_Text_Buffer::expand_character( lineStr+charIndex, outIndex,
expandedChar,
mBuffer->tab_distance());
- if (charLen > 1 && (lineStr[ charIndex ] & 0x80)) {
- int i, ii = 0;;
- i = fl_utf8len(lineStr[ charIndex ]);
- while (i > 1) {
- i--;
- ii++;
- expandedChar[ii] = lineStr[ charIndex + ii];
- }
- }
charStyle = position_style( lineStartPos, lineLen, charIndex,
outIndex );
xStep += string_width( expandedChar, charLen, charStyle );
@@ -1475,20 +1469,10 @@
that character */
X = text_area.x - mHorizOffset;
outIndex = 0;
- for ( charIndex = 0; ; charIndex++ ) {
+ for ( charIndex = 0; ; charIndex += lineStr ? fl_utf8len(lineStr[charIndex])
: 1 ) {
charLen = charIndex >= lineLen ? 1 :
- Fl_Text_Buffer::expand_character( lineStr[ charIndex ], outIndex,
+ Fl_Text_Buffer::expand_character( lineStr+charIndex, outIndex,
expandedChar,
buf->tab_distance());
- if (charIndex < lineLen && charLen > 1 && (lineStr[ charIndex ] & 0x80)) {
- int i, ii = 0;;
- i = fl_utf8len(lineStr[ charIndex ]);
- while (i > 1) {
- i--;
- ii++;
- expandedChar[ii] = lineStr[ charIndex + ii];
- }
- }
-
style = position_style( lineStartPos, lineLen, charIndex,
outIndex + dispIndexOffset );
charWidth = charIndex >= lineLen ? stdCharWidth :
@@ -1513,19 +1497,13 @@
outPtr = outStr;
outIndex = outStartIndex;
X = startX;
- for ( charIndex = startIndex; charIndex < rightCharIndex; charIndex++ ) {
+ for (charIndex = startIndex;
+ charIndex < rightCharIndex;
+ charIndex += lineStr ? fl_utf8len(lineStr[charIndex]) : 1 )
+ {
charLen = charIndex >= lineLen ? 1 :
- Fl_Text_Buffer::expand_character( lineStr[ charIndex ],
outIndex, expandedChar,
+ Fl_Text_Buffer::expand_character( lineStr+charIndex, outIndex,
expandedChar,
buf->tab_distance());
- if (charIndex < lineLen && charLen > 1 && (lineStr[ charIndex ] & 0x80)) {
- int i, ii = 0;;
- i = fl_utf8len(lineStr[ charIndex ]);
- while (i > 1) {
- i--;
- ii++;
- expandedChar[ii] = lineStr[ charIndex + ii];
- }
- }
charStyle = position_style( lineStartPos, lineLen, charIndex,
outIndex + dispIndexOffset );
for ( i = 0; i < charLen; i++ ) {
@@ -1561,19 +1539,13 @@
outPtr = outStr;
outIndex = outStartIndex;
X = startX;
- for ( charIndex = startIndex; charIndex < rightCharIndex; charIndex++ ) {
+ for (charIndex = startIndex;
+ charIndex < rightCharIndex;
+ charIndex += lineStr ? fl_utf8len(lineStr[charIndex]) : 0)
+ {
charLen = charIndex >= lineLen ? 1 :
- Fl_Text_Buffer::expand_character( lineStr[ charIndex ],
outIndex, expandedChar,
+ Fl_Text_Buffer::expand_character( lineStr+charIndex, outIndex,
expandedChar,
buf->tab_distance());
- if (charIndex < lineLen && charLen > 1 && (lineStr[ charIndex ] & 0x80)) {
- int i, ii = 0;;
- i = fl_utf8len(lineStr[ charIndex ]);
- while (i > 1) {
- i--;
- ii++;
- expandedChar[ii] = lineStr[ charIndex + ii];
- }
- }
charStyle = position_style( lineStartPos, lineLen, charIndex,
outIndex + dispIndexOffset );
for ( i = 0; i < charLen; i++ ) {
@@ -1923,18 +1895,12 @@
to find the character position corresponding to the X coordinate */
xStep = text_area.x - mHorizOffset;
outIndex = 0;
- for ( charIndex = 0; charIndex < lineLen; charIndex++ ) {
- charLen = Fl_Text_Buffer::expand_character( lineStr[ charIndex ],
outIndex, expandedChar,
+ for (charIndex = 0;
+ charIndex < lineLen;
+ charIndex += fl_utf8len(lineStr[charIndex]) )
+ {
+ charLen = Fl_Text_Buffer::expand_character( lineStr+charIndex, outIndex,
expandedChar,
mBuffer->tab_distance());
- if (charLen > 1 && (lineStr[ charIndex ] & 0x80)) {
- int i, ii = 0;;
- i = fl_utf8len(lineStr[ charIndex ]);
- while (i > 1) {
- i--;
- ii++;
- expandedChar[ii] = lineStr[ charIndex + ii];
- }
- }
charStyle = position_style( lineStart, lineLen, charIndex, outIndex );
charWidth = string_width( expandedChar, charLen, charStyle );
if ( X < xStep + ( posType == CURSOR_POS ? charWidth / 2 : charWidth ) ) {
@@ -2732,7 +2698,7 @@
colNum = 0;
width = 0;
} else {
- colNum += Fl_Text_Buffer::character_width(c, colNum, tabDist);
+ colNum += Fl_Text_Buffer::character_width((char*)&c, colNum,
tabDist); // FIXME: unicode
if (countPixels)
width += measure_proportional_character(c, colNum,
p+styleBufOffset);
}
@@ -2762,7 +2728,7 @@
}
if (!foundBreak) { /* no whitespace, just break at margin */
newLineStart = max(p, lineStart+1);
- colNum = Fl_Text_Buffer::character_width(c, colNum, tabDist);
+ colNum = Fl_Text_Buffer::character_width((char*)&c, colNum,
tabDist); // FIXME: unicode
if (countPixels)
width = measure_proportional_character(c, colNum,
p+styleBufOffset);
}
@@ -2814,7 +2780,7 @@
char expChar[ FL_TEXT_MAX_EXP_CHAR_LEN ];
Fl_Text_Buffer *styleBuf = mStyleBuffer;
- charLen = Fl_Text_Buffer::expand_character(c, colNum, expChar,
buffer()->tab_distance());
+ charLen = Fl_Text_Buffer::expand_character(&c, colNum, expChar,
buffer()->tab_distance()); // FIXME: unicode
if (styleBuf == 0) {
style = 0;
} else {
_______________________________________________
fltk-commit mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk-commit