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

Reply via email to