Author: matt
Date: 2010-05-09 13:55:07 -0700 (Sun, 09 May 2010)
New Revision: 7596
Log:
MOre cleaning up - sigh.

Modified:
   branches/branch-1.3-STR2158-matt/FL/Fl_Text_Buffer.H
   branches/branch-1.3-STR2158-matt/src/Fl_Text_Buffer.cxx
   branches/branch-1.3-STR2158-matt/src/Fl_Text_Display.cxx
   branches/branch-1.3-STR2158-matt/src/Fl_Text_Editor.cxx
   branches/branch-1.3-STR2158-matt/test/editor.cxx

Modified: branches/branch-1.3-STR2158-matt/FL/Fl_Text_Buffer.H
===================================================================
--- branches/branch-1.3-STR2158-matt/FL/Fl_Text_Buffer.H        2010-05-07 
20:23:07 UTC (rev 7595)
+++ branches/branch-1.3-STR2158-matt/FL/Fl_Text_Buffer.H        2010-05-09 
20:55:07 UTC (rev 7596)
@@ -205,12 +205,20 @@
   /**
    Returns the character at the specified position pos in the buffer.
    Positions start at 0 
-   \param pos byte offset into buffer
+   \param pos byte offset into buffer, pos must be at acharacter boundary
    \return Unicode UCS-4 encoded character
    */
-  unsigned int at(int pos) const;
+  unsigned int char_at(int pos) const;
   
   /**
+   Returns the raw byte at the specified position pos in the buffer.
+   Positions start at 0 
+   \param pos byte offset into buffer
+   \return unencoded raw byte
+   */
+  char byte_at(int pos) const;
+  
+  /**
    Convert a byte offset in buffer into a memory address.
    */
   const char *address(int pos) const
@@ -587,7 +595,7 @@
    overall performance of the text widget is dependent on its ability to
    count lines quickly, hence searching for a single character: newline)
    \param startPos byte offset to start position
-   \param searchChar UCS4 character that we want to find
+   \param searchChar UCS-4 character that we want to find
    \param foundPos byte offset where the character was found
    \return 1 if found, 0 if not
    \todo unicode check
@@ -602,7 +610,7 @@
    overall performance of the text widget is dependent on its ability to
    count lines quickly, hence searching for a single character: newline)
    \param startPos byte offset to start position
-   \param searchChar UCS4 character that we want to find
+   \param searchChar UCS-4 character that we want to find
    \param foundPos byte offset where the character was found
    \return 1 if found, 0 if not
    \todo unicode check
@@ -683,6 +691,32 @@
    */
   const Fl_Text_Selection* highlight_selection() const { return &mHighlight; }
   
+  /**
+   Returns the index of the previous character.
+   \param ix index to the current char
+   */
+  int prev_char(int ix) const;
+  
+  /**
+   Returns a pointer to the previous character.
+   \param c pointer to the current char
+   */
+  char *prev_char(char *c) const;
+  const char *prev_char(const char *c) const;
+  
+  /**
+   Returns the index of the next character.
+   \param ix index to the current char
+   */
+  int next_char(int ix) const;
+  
+  /**
+   Returns a pointer to the next character.
+   \param c pointer to the current char
+   */
+  char *next_char(char *c) const;
+  const char *next_char(const char *c) const;
+  
 protected:
 
   /**
@@ -770,8 +804,6 @@
   // The hardware tab distance used by all displays for this buffer,
   // and used in computing offsets for rectangular selection operations.
   int mTabDist;                   /**< equiv. number of characters in a tab */
-  int mUseTabs;                   /**< True if buffer routines are allowed to 
use
-                                   tabs for padding in rectangular operations 
*/
   int mNModifyProcs;              /**< number of modify-redisplay procs 
attached */
   Fl_Text_Modify_Cb *mModifyProcs;/**< procedures to call when buffer is 
                                    modified to redisplay contents */

Modified: branches/branch-1.3-STR2158-matt/src/Fl_Text_Buffer.cxx
===================================================================
--- branches/branch-1.3-STR2158-matt/src/Fl_Text_Buffer.cxx     2010-05-07 
20:23:07 UTC (rev 7595)
+++ branches/branch-1.3-STR2158-matt/src/Fl_Text_Buffer.cxx     2010-05-09 
20:55:07 UTC (rev 7596)
@@ -33,36 +33,47 @@
 #include <FL/Fl.H>
 #include <FL/Fl_Text_Buffer.H>
 
+
 /*
  This file is based on a port of NEdit to FLTK many years ago. NEdit at that
  point was already stretched beyond the task it was designed for which explains
- why the source code is sometimes pretty convoluted. It still is a nice widget
- for FLTK.
+ why the source code is sometimes pretty convoluted. It still is a very useful
+ widget for FLTK, and we are thankful that the nedit team allowed us to 
+ integrate their code.
 
  With the introduction of Unicode and UTF-8, Fl_Text_... has to go into a whole
  new generation of code. Originally designed for monspaced fonts only, many
  features make les sense in the multibyte and multiwdth world of UTF-8.
  
- Columns are a good example. There is simply no such thing.
+ Columns are a good example. There is simply no such thing. The new Fl_Text_...
+ widget converts columns to pixels by multiplying them with the average 
+ character width for a given font 
  
- Rectangular selections pose a real problem.
+ Rectangular selections were rearely used (if at all) and make little sense 
when
+ using variable width fonts. They have been removed.
  
- Using multiple spaces to emulate tab stops will no longer work.
+ Using multiple spaces to emulate tab stops has been replaced by pixel counting
+ routines. They are slower, but give the expected result for proportional 
fonts.
  
- And constantly recalculating character widths is just much too expensive.
- 
- But nevertheless, we will get ths widget rolling again ;-)
- 
+ And constantly recalculating character widths is just much too expensive. 
Lines
+ of text are now subdivided into blocks of text which are measured at once 
+ instead of individual characters. 
  */
 
 
 #ifndef min
 
+/*
+ Unicode safe.
+ */
 static int max(int i1, int i2)
 {
   return i1 >= i2 ? i1 : i2;
 }
 
+/*
+ Unicode safe.
+ */
 static int min(int i1, int i2)
 {
   return i1 <= i2 ? i1 : i2;
@@ -79,6 +90,10 @@
 static int undoinsert;         // number of characters inserted
 static int undoyankcut;                // length of valid contents of buffer, 
even if undocut=0
 
+/*
+ Resize the undo buffer to match at least the requested size.
+ Unicode safe.
+ */
 static void undobuffersize(int n)
 {
   if (n > undobufferlength) {
@@ -95,7 +110,10 @@
 }
 
 
-// unicode ok
+/*
+ Initialize all variables.
+ Unicode safe.
+ */
 Fl_Text_Buffer::Fl_Text_Buffer(int requestedSize, int preferredGapSize)
 {
   mLength = 0;
@@ -104,7 +122,6 @@
   mGapStart = 0;
   mGapEnd = mPreferredGapSize;
   mTabDist = 8;
-  mUseTabs = 1;
   mPrimary.mSelected = 0;
   mPrimary.mStart = mPrimary.mEnd = 0;
   mSecondary.mSelected = 0;
@@ -119,17 +136,13 @@
   mPredeleteCbArgs = NULL;
   mCursorPosHint = 0;
   mCanUndo = 1;
-#ifdef PURIFY
-  {
-    int i;
-    for (i = mGapStart; i < mGapEnd; i++)
-      mBuf[i] = '.';
-  }
-#endif
 }
 
 
-// unicode ok
+/*
+ Free all resources.
+ Unicode safe.
+ */
 Fl_Text_Buffer::~Fl_Text_Buffer()
 {
   free(mBuf);
@@ -144,19 +157,24 @@
 }
 
 
-// This function copies verbose whatever is in front and after the gap into a
-// single buffer.
-// - unicode ok
+/*
+ This function copies verbose whatever is in front and after the gap into a
+ single buffer.
+ Unicode safe.
+ */
 char *Fl_Text_Buffer::text() const {
   char *t = (char *) malloc(mLength + 1);
   memcpy(t, mBuf, mGapStart);
-  memcpy(&t[mGapStart], &mBuf[mGapEnd], mLength - mGapStart);
+  memcpy(t+mGapStart, mBuf+mGapEnd, mLength - mGapStart);
   t[mLength] = '\0';
   return t;
 } 
 
 
-// unicode ok, functions called have not been verified yet
+/*
+ Set the text buffer to a new string.
+ Unicode safe.
+ */
 void Fl_Text_Buffer::text(const char *t)
 {
   call_predelete_callbacks(0, length());
@@ -173,13 +191,6 @@
   mGapStart = insertedLength;
   mGapEnd = mGapStart + mPreferredGapSize;
   memcpy(mBuf, t, insertedLength);
-#ifdef PURIFY
-  {
-    int i;
-    for (i = mGapStart; i < mGapEnd; i++)
-      mBuf[i] = '.';
-  }
-#endif
   
   /* Zero all of the existing selections */
   update_selections(0, deletedLength, 0);
@@ -190,8 +201,10 @@
 }
 
 
-// Creates a new buffer and copies verbose from around the gap.
-// - unicode ok
+/*
+ Creates a range of text to a new buffer and copies verbose from around the 
gap.
+ Unicode safe.
+ */
 char *Fl_Text_Buffer::text_range(int start, int end) const {
   char *s = NULL;
   
@@ -215,22 +228,23 @@
   
   /* Copy the text from the buffer to the returned string */
   if (end <= mGapStart) {
-    memcpy(s, &mBuf[start], copiedLength);
+    memcpy(s, mBuf + start, copiedLength);
   } else if (start >= mGapStart) {
-    memcpy(s, &mBuf[start + (mGapEnd - mGapStart)], copiedLength);
+    memcpy(s, mBuf + start + (mGapEnd - mGapStart), copiedLength);
   } else {
     int part1Length = mGapStart - start;
-    memcpy(s, &mBuf[start], part1Length);
-    memcpy(&s[part1Length], &mBuf[mGapEnd], copiedLength - part1Length);
+    memcpy(s, mBuf + start, part1Length);
+    memcpy(s + part1Length, mBuf + mGapEnd, copiedLength - part1Length);
   }
   s[copiedLength] = '\0';
   return s;
 }
 
-
-// TODO: we will need the same signature function to get bytes (style buffer)
-// unicode ok
-unsigned int Fl_Text_Buffer::at(int pos) const {
+/*
+ Return a UCS-4 character at the given index.
+ Unicode safe. Pos must be at a character boundary.
+ */
+unsigned int Fl_Text_Buffer::char_at(int pos) const {
   if (pos < 0 || pos >= mLength)
     return '\0';
   const char *src = address(pos);
@@ -238,7 +252,22 @@
 } 
 
 
-// unicode ok, dependents not tested
+/*
+ Return the raw byte at the given index.
+ This function ignores all unicode encoding.
+ */
+char Fl_Text_Buffer::byte_at(int pos) const {
+  if (pos < 0 || pos >= mLength)
+    return '\0';
+  const char *src = address(pos);
+  return *src;
+} 
+
+
+/*
+ Insert some text at the given index.
+ Unicode safe. Pos must be at a character boundary.
+*/
 void Fl_Text_Buffer::insert(int pos, const char *text)
 {
   /* if pos is not contiguous to existing text, make it */
@@ -257,7 +286,10 @@
 }
 
 
-// unicode ok, dependents not tested
+/*
+ Replace a range of text with new text.
+ Unicode safe. Start and end must be at a character boundary.
+*/
 void Fl_Text_Buffer::replace(int start, int end, const char *text)
 {
   // Range check...
@@ -278,7 +310,10 @@
 }
 
 
-// unicode ok, dependents not tested
+/*
+ Remove a range of text.
+ Unicode safe. Start and End must be at a character boundary.
+*/
 void Fl_Text_Buffer::remove(int start, int end)
 {
   /* Make sure the arguments make sense */
@@ -308,6 +343,11 @@
   free((void *) deletedText);
 }
 
+
+/*
+ Copy a range of text from another text buffer.
+ Unicode safe. FromDtart, fromEnd, and toPos must be at a character boundary.
+ */
 void Fl_Text_Buffer::copy(Fl_Text_Buffer * fromBuf, int fromStart,
                          int fromEnd, int toPos)
 {
@@ -328,8 +368,7 @@
     memcpy(&mBuf[toPos], &fromBuf->mBuf[fromStart], copiedLength);
   } else if (fromStart >= fromBuf->mGapStart) {
     memcpy(&mBuf[toPos],
-          &fromBuf->mBuf[fromStart +
-                         (fromBuf->mGapEnd - fromBuf->mGapStart)],
+          &fromBuf->mBuf[fromStart + (fromBuf->mGapEnd - fromBuf->mGapStart)],
           copiedLength);
   } else {
     int part1Length = fromBuf->mGapStart - fromStart;
@@ -342,6 +381,12 @@
   update_selections(toPos, 0, copiedLength);
 }
 
+
+/*
+ Take the previous changes and undo them. Return the previous
+ cursor position in cursorPos. Returns 1 if the undo was applied.
+ Unicode safe. CursorPos will be at a character boundary.
+ */ 
 int Fl_Text_Buffer::undo(int *cursorPos)
 {
   if (undowidget != this || !undocut && !undoinsert && !mCanUndo)
@@ -380,12 +425,27 @@
 }
 
 
-// unicode ok
+/*
+ Set a flag is undo function will work.
+ Unicode safe.
+ */
 void Fl_Text_Buffer::canUndo(char flag)
 {
   mCanUndo = flag;
+  // disabeling undo also clears the last undo operation!
+  if (!mCanUndo && undowidget==this) 
+    undowidget = 0;
 }
 
+
+/*
+ Change the tab width. This will cause a couple of callbacks and a complete 
+ redisplay. 
+ Matt: I am not entirely sure why we need to trigger callbacks because
+ tabs are only a graphical hint, not changing any text at all, but I leave
+ this in here for back compatibility. 
+ Unicode safe.
+ */
 void Fl_Text_Buffer::tab_distance(int tabDist)
 {
   /* First call the pre-delete callbacks with the previous tab setting 
@@ -402,6 +462,11 @@
   free((void *) deletedText);
 }
 
+
+/*
+ Select a range of text.
+ Unicode safe. Start and End must be at a character boundary.
+ */
 void Fl_Text_Buffer::select(int start, int end)
 {
   Fl_Text_Selection oldSelection = mPrimary;
@@ -410,6 +475,11 @@
   redisplay_selection(&oldSelection, &mPrimary);
 }
 
+
+/*
+ Clear the primary selection.
+ Unicode safe.
+ */
 void Fl_Text_Buffer::unselect()
 {
   Fl_Text_Selection oldSelection = mPrimary;
@@ -418,26 +488,51 @@
   redisplay_selection(&oldSelection, &mPrimary);
 }
 
+
+/*
+ Return the primary selection range.
+ Unicode safe.
+ */
 int Fl_Text_Buffer::selection_position(int *start, int *end)
 {
   return mPrimary.position(start, end);
 }
 
+
+/*
+ Return a copy of the selected text.
+ Unicode safe.
+ */
 char *Fl_Text_Buffer::selection_text()
 {
   return selection_text_(&mPrimary);
 }
 
+
+/*
+ Remove the selected text.
+ Unicode safe.
+ */
 void Fl_Text_Buffer::remove_selection()
 {
   remove_selection_(&mPrimary);
 }
 
+
+/*
+ Replace the selected text.
+ Unicode safe.
+ */
 void Fl_Text_Buffer::replace_selection(const char *text)
 {
   replace_selection_(&mPrimary, text);
 }
 
+
+/*
+ Select text.
+ Unicode safe. Start and End must be at a character boundary.
+ */
 void Fl_Text_Buffer::secondary_select(int start, int end)
 {
   Fl_Text_Selection oldSelection = mSecondary;
@@ -446,6 +541,11 @@
   redisplay_selection(&oldSelection, &mSecondary);
 }
 
+
+/*
+ Deselect text.
+ Unicode safe.
+ */
 void Fl_Text_Buffer::secondary_unselect()
 {
   Fl_Text_Selection oldSelection = mSecondary;
@@ -454,26 +554,51 @@
   redisplay_selection(&oldSelection, &mSecondary);
 }
 
+
+/*
+ Return the selected range.
+ Unicode safe.
+ */
 int Fl_Text_Buffer::secondary_selection_position(int *start, int *end)
 {
   return mSecondary.position(start, end);
 }
 
+
+/*
+ Return a copy of the text in this selection.
+ Unicode safe.
+ */
 char *Fl_Text_Buffer::secondary_selection_text()
 {
   return selection_text_(&mSecondary);
 }
 
+
+/*
+ Remove the selected text.
+ Unicode safe.
+ */
 void Fl_Text_Buffer::remove_secondary_selection()
 {
   remove_selection_(&mSecondary);
 }
 
+
+/*
+ Replace selected text.
+ Unicode safe.
+ */
 void Fl_Text_Buffer::replace_secondary_selection(const char *text)
 {
   replace_selection_(&mSecondary, text);
 }
 
+
+/*
+ Highlight a range of text.
+ Unicode safe. Start and End must be at a character boundary.
+ */
 void Fl_Text_Buffer::highlight(int start, int end)
 {
   Fl_Text_Selection oldSelection = mHighlight;
@@ -482,6 +607,11 @@
   redisplay_selection(&oldSelection, &mHighlight);
 }
 
+
+/*
+ Remove text highlighting.
+ Unicode safe.
+ */
 void Fl_Text_Buffer::unhighlight()
 {
   Fl_Text_Selection oldSelection = mHighlight;
@@ -490,16 +620,31 @@
   redisplay_selection(&oldSelection, &mHighlight);
 }
 
+
+/*
+ Return position of highlight.
+ Unicode safe.
+ */
 int Fl_Text_Buffer::highlight_position(int *start, int *end)
 {
   return mHighlight.position(start, end);
 }
 
+
+/*
+ Return a copy of highlighted text.
+ Unicode safe.
+ */
 char *Fl_Text_Buffer::highlight_text()
 {
   return selection_text_(&mHighlight);
 }
 
+
+/*
+ Add a callback that is called whenever text is modified.
+ Unicode safe.
+ */
 void Fl_Text_Buffer::add_modify_callback(Fl_Text_Modify_Cb bufModifiedCB,
                                         void *cbArg)
 {
@@ -521,8 +666,13 @@
   mCbArgs = newCBArgs;
 }
 
-void Fl_Text_Buffer::
-remove_modify_callback(Fl_Text_Modify_Cb bufModifiedCB, void *cbArg)
+
+/*
+ Remove a callback.
+ Unicode safe.
+ */
+void Fl_Text_Buffer::remove_modify_callback(Fl_Text_Modify_Cb bufModifiedCB, 
+                                            void *cbArg)
 {
   int i, toRemove = -1;
   
@@ -568,8 +718,13 @@
   mCbArgs = newCBArgs;
 }
 
-void Fl_Text_Buffer::
-add_predelete_callback(Fl_Text_Predelete_Cb bufPreDeleteCB, void *cbArg)
+
+/*
+ Add a callback that is called before deleting text.
+ Unicode safe.
+ */
+void Fl_Text_Buffer::add_predelete_callback(Fl_Text_Predelete_Cb 
bufPreDeleteCB, 
+                                            void *cbArg)
 {
   Fl_Text_Predelete_Cb *newPreDeleteProcs =
   new Fl_Text_Predelete_Cb[mNPredeleteProcs + 1];
@@ -589,8 +744,12 @@
   mPredeleteCbArgs = newCBArgs;
 }
 
-void Fl_Text_Buffer::
-remove_predelete_callback(Fl_Text_Predelete_Cb bufPreDeleteCB, void *cbArg)
+
+/*
+ Remove a callback.
+ Unicode safe.
+ */
+void Fl_Text_Buffer::remove_predelete_callback(Fl_Text_Predelete_Cb 
bufPreDeleteCB, void *cbArg)
 {
   int i, toRemove = -1;
   /* find the matching callback to remove */
@@ -637,46 +796,78 @@
   mPredeleteCbArgs = newCBArgs;
 }
 
+
+/*
+ Return a copy of the line that contains a given index.
+ Unicode safe. Pos must be at a character boundary.
+ */
 char *Fl_Text_Buffer::line_text(int pos) const {
   return text_range(line_start(pos), line_end(pos));
 } 
 
-int Fl_Text_Buffer::line_start(int pos) const {
+
+/*
+ Find the beginning of the line.
+ NOT UNICODE SAFE.
+ */
+int Fl_Text_Buffer::line_start(int pos) const 
+{
+  // FIXME: this currently works for unicode, but will be very inefficent when 
findchar_backward is fixed.
   if (!findchar_backward(pos, '\n', &pos))
     return 0;
   return pos + 1;
 } 
 
+
+/*
+ Find the end of the line.
+ NOT UNICODE SAFE.
+ */
 int Fl_Text_Buffer::line_end(int pos) const {
+  // FIXME: this currently works for unicode, but will be very inefficent when 
findchar_forward is fixed.
   if (!findchar_forward(pos, '\n', &pos))
     pos = mLength;
   return pos;
 } 
 
+
+/*
+ Find the beginning of a word.
+ NOT UNICODE SAFE.
+ */
 int Fl_Text_Buffer::word_start(int pos) const {
   // FIXME: character is ucs-4
-  while (pos && (isalnum(at(pos)) || at(pos) == '_')) {
+  while (pos && (isalnum(char_at(pos)) || char_at(pos) == '_')) {
     pos--;
   } 
   // FIXME: character is ucs-4
-  if (!(isalnum(at(pos)) || at(pos) == '_'))
+  if (!(isalnum(char_at(pos)) || char_at(pos) == '_'))
     pos++;
   return pos;
 }
 
+
+/*
+ Find the end of a word.
+ NOT UNICODE SAFE.
+ */
 int Fl_Text_Buffer::word_end(int pos) const {
   // FIXME: character is ucs-4
-  while (pos < length() && (isalnum(at(pos)) || at(pos) == '_'))
+  while (pos < length() && (isalnum(char_at(pos)) || char_at(pos) == '_'))
   {
     pos++;
   } return pos;
 }
 
 
+/*
+ Matt: I am not sure why we need this function. Does it still make sense in
+ the world of proportional characters?
+ */
 int Fl_Text_Buffer::count_displayed_characters(int lineStartPos,
                                               int targetPos) const
 {
-  // FIXME: is this function still needed?
+  // TODO: is this function still needed? If it is, put this functionality in 
handle_vline?
   int charCount = 0;
   
   int pos = lineStartPos;
@@ -689,10 +880,15 @@
 } 
 
 
+/*
+ Matt: I am not sure why we need this function. Does it still make sense in
+ the world of proportional characters?
+ */
 // All values are number of bytes. 
-// - unicode ok
+// - unicode ok?
 int Fl_Text_Buffer::skip_displayed_characters(int lineStartPos, int nChars)
 {
+  // FIXME: is this function still needed?
   int pos = lineStartPos;
   
   for (int charCount = 0; charCount < nChars && pos < mLength;) {
@@ -706,6 +902,11 @@
   return pos;
 }
 
+
+/*
+ Count the number of newline characters between start and end.
+ Unicode safe. StartPos and endPos must be at a character boundary.
+ */
 int Fl_Text_Buffer::count_lines(int startPos, int endPos) const {
   int gapLen = mGapEnd - mGapStart;
   int lineCount = 0;
@@ -717,7 +918,8 @@
       return lineCount;
     if (mBuf[pos++] == '\n')
       lineCount++;
-  } while (pos < mLength) {
+  } 
+  while (pos < mLength) {
     if (pos == endPos)
       return lineCount;
     if (mBuf[pos++ + gapLen] == '\n')
@@ -726,6 +928,11 @@
   return lineCount;
 }
 
+
+/*
+ Skip to the first character, n lines ahead.
+ Unicode safe. StartPos must be at a character boundary.
+ */
 int Fl_Text_Buffer::skip_lines(int startPos, int nLines)
 {
   if (nLines == 0)
@@ -751,6 +958,11 @@
   return pos;
 }
 
+
+/*
+ Skip to the first character, n lines back.
+ Unicode safe. StartPos must be at a character boundary.
+ */
 int Fl_Text_Buffer::rewind_lines(int startPos, int nLines)
 {
   int pos = startPos - 1;
@@ -776,9 +988,15 @@
   return 0;
 }
 
+
+/*
+ Find a matching string in the buffer.
+ NOT TESTED FOR UNICODE.
+ */
 int Fl_Text_Buffer::search_forward(int startPos, const char *searchString,
                                   int *foundPos, int matchCase) const 
 {
+  // FIXME: Unicode?
   if (!searchString)
     return 0;
   int bp;
@@ -792,16 +1010,22 @@
         return 1;
       }
       // FIXME: character is ucs-4
-    } while ((matchCase ? at(bp++) == *sp++ :
-              toupper(at(bp++)) == toupper(*sp++))
+    } while ((matchCase ? char_at(bp++) == *sp++ :
+              toupper(char_at(bp++)) == toupper(*sp++))
              && bp < length());
     startPos++;
   }
   return 0;
 }
 
+
+/*
+ Find a matching string in the buffer.
+ NOT TESTED FOR UNICODE.
+ */
 int Fl_Text_Buffer::search_backward(int startPos, const char *searchString,
                                    int *foundPos, int matchCase) const {
+  // FIXME: Unicode?
   if (!searchString)
     return 0;
   int bp;
@@ -816,16 +1040,22 @@
         return 1;
       }
       // FIXME: character is ucs-4
-    } while ((matchCase ? at(bp--) == *sp-- :
-              toupper(at(bp--)) == toupper(*sp--))
+    } while ((matchCase ? char_at(bp--) == *sp-- :
+              toupper(char_at(bp--)) == toupper(*sp--))
              && bp >= 0);
     startPos--;
   }
   return 0;
 }
 
+
+/*
+ Find a matching string in the buffer.
+ NOT TESTED FOR UNICODE.
+ */
 int Fl_Text_Buffer::findchars_forward(int startPos, const char *searchChars,
                                      int *foundPos) const {
+  // FIXME: unicode?
   int gapLen = mGapEnd - mGapStart;
   const char *c;
   
@@ -852,8 +1082,14 @@
   return 0;
 }
 
+
+/*
+ Find a matching string in the buffer.
+ NOT TESTED FOR UNICODE.
+ */
 int Fl_Text_Buffer::findchars_backward(int startPos, const char *searchChars,
                                       int *foundPos) const {
+  // FIXME: Unicode
   int gapLen = mGapEnd - mGapStart;
   const char *c;
   
@@ -885,6 +1121,11 @@
   return 0;
 }
 
+
+/*
+ Insert a string into the buffer.
+ Unicode safe. Pos must be at a character boundary. Text must be a correct 
utf8 string.
+ */
 int Fl_Text_Buffer::insert_(int pos, const char *text)
 {
   int insertedLength = strlen(text);
@@ -920,6 +1161,11 @@
   return insertedLength;
 }
 
+
+/*
+ Remove a string from the buffer.
+ Unicode safe. Start and end must be at a character boundary.
+ */
 void Fl_Text_Buffer::remove_(int start, int end)
 {
   /* if the gap is not contiguous to the area to remove, move it there */
@@ -968,8 +1214,10 @@
 }
 
 
-// simple setter
-// Unicode safe
+/*
+ simple setter.
+ Unicode safe. Start and end must be at a character boundary.
+ */
 void Fl_Text_Selection::set(int startpos, int endpos)
 {
   mSelected = startpos != endpos;
@@ -978,8 +1226,10 @@
 }
 
 
-// simple getter
-// Unicode safe
+/*
+ simple getter.
+ Unicode safe. Start and end will be at a character boundary.
+ */
 int Fl_Text_Selection::position(int *startpos, int *endpos) const {
   if (!mSelected)
     return 0;
@@ -990,11 +1240,19 @@
 } 
 
 
-// unicode safe
+/*
+ Return if a position is inside the eselected area.
+ Unicode safe. Pos must be at a character boundary.
+ */
 int Fl_Text_Selection::includes(int pos) const {
   return (selected() && pos >= start() && pos < end() );
 } 
 
+
+/*
+ Return a duplicate of the selected text, or an empty string.
+ Unicode safe.
+ */
 char *Fl_Text_Buffer::selection_text_(Fl_Text_Selection * sel) const {
   int start, end;
   
@@ -1006,10 +1264,15 @@
     return s;
   }
   
-  /* If the selection is not rectangular, return the selected range */
+  /* Return the selected range */
   return text_range(start, end);
 }
 
+
+/*
+ Remove the selected text.
+ Unicode safe.
+ */
 void Fl_Text_Buffer::remove_selection_(Fl_Text_Selection * sel)
 {
   int start, end;
@@ -1021,6 +1284,10 @@
 }
 
 
+/*
+ Replace selection with text.
+ Unicode safe.
+ */
 void Fl_Text_Buffer::replace_selection_(Fl_Text_Selection * sel,
                                        const char *text)
 {
@@ -1041,6 +1308,10 @@
 }
 
 
+/*
+ Call all callbacks.
+ Unicode safe.
+ */
 void Fl_Text_Buffer::call_modify_callbacks(int pos, int nDeleted,
                                           int nInserted, int nRestyled,
                                           const char *deletedText) const {
@@ -1050,12 +1321,20 @@
 } 
 
 
+/*
+ Call all callbacks.
+ Unicode safe.
+ */
 void Fl_Text_Buffer::call_predelete_callbacks(int pos, int nDeleted) const {
   for (int i = 0; i < mNPredeleteProcs; i++)
     (*mPredeleteProcs[i]) (pos, nDeleted, mPredeleteCbArgs[i]);
 } 
 
 
+/*
+ Redisplay a new selected area.
+ Unicode safe.
+ */
 void Fl_Text_Buffer::redisplay_selection(Fl_Text_Selection *
                                           oldSelection,
                                           Fl_Text_Selection *
@@ -1107,6 +1386,11 @@
     call_modify_callbacks(ch2Start, 0, 0, ch2End - ch2Start, NULL);
 }
 
+
+/*
+ Move the gap around without changing buffer content.
+ Unicode safe. Pos must be at a character boundary.
+ */
 void Fl_Text_Buffer::move_gap(int pos)
 {
   int gapLen = mGapEnd - mGapStart;
@@ -1119,6 +1403,11 @@
   mGapStart += pos - mGapStart;
 }
 
+
+/*
+ Create a larger gap.
+ Unicode safe. Start must be at a character boundary.
+ */
 void Fl_Text_Buffer::reallocate_with_gap(int newGapStart, int newGapLen)
 {
   char *newBuf = (char *) malloc(mLength + newGapLen);
@@ -1141,15 +1430,13 @@
   mBuf = newBuf;
   mGapStart = newGapStart;
   mGapEnd = newGapEnd;
-#ifdef PURIFY
-  {
-    int i;
-    for (i = mGapStart; i < mGapEnd; i++)
-      mBuf[i] = '.';
-  }
-#endif
 }
 
+
+/*
+ Update selection range if characers were inserted.
+ Unicode safe. Pos must be at a character boundary.
+ */
 void Fl_Text_Buffer::update_selections(int pos, int nDeleted,
                                       int nInserted)
 {
@@ -1162,6 +1449,7 @@
 // unicode safe, assuming the arguments are on character boundaries
 void Fl_Text_Selection::update(int pos, int nDeleted, int nInserted)
 {
+  // FIXME: check if this is safe when seletion crosses selction boundaries
   if (!mSelected || pos > mEnd)
     return;
   if (pos + nDeleted <= mStart) {
@@ -1181,61 +1469,69 @@
   }
 }
 
+
+/*
+ Find a UCS-4 character.
+ Unicode safe. StartPos must be at a charcter boundary, searchChar is UCS-4 
encoded.
+ */
 int Fl_Text_Buffer::findchar_forward(int startPos, unsigned searchChar,
-                                    int *foundPos) const {
-  if (startPos < 0 || startPos >= mLength)
+                                    int *foundPos) const 
+{
+  if (startPos >= mLength)
   {
     *foundPos = mLength;
     return 0;
   }
   
-  int pos = startPos;
-  while (pos < mGapStart) {
-    if (mBuf[pos] == searchChar) {
-      *foundPos = pos;
+  if (startPos<0)
+    startPos = 0;
+  
+  // TODO: for performance reasons, we can re-insert the ASCII search here 
which is about three times as fast if searchChar is <128
+  
+  for ( ; startPos<mLength; startPos = next_char(startPos)) {
+    if (searchChar == char_at(startPos)) {
+      *foundPos = startPos;
       return 1;
     }
-    pos++;
   }
   
-  for (int gapLen = mGapEnd - mGapStart; pos < mLength; pos++) {
-    if (mBuf[pos + gapLen] == searchChar) {
-      *foundPos = pos;
-      return 1;
-    }
-  }
   *foundPos = mLength;
   return 0;
 }
 
+
+/*
+ Find a UCS-4 character.
+ Unicode safe. StartPos must be at a charcter boundary, searchChar is UCS-4 
encoded.
+ */
 int Fl_Text_Buffer::findchar_backward(int startPos, unsigned searchChar,
                                      int *foundPos) const {
-  
-  if (startPos <= 0 || startPos > mLength)
-  {
+  if (startPos <= 0) {
     *foundPos = 0;
     return 0;
   }
   
-  int pos = startPos - 1;
-  for (int gapLen = mGapEnd - mGapStart; pos >= mGapStart; pos--) {
-    if (mBuf[pos + gapLen] == searchChar) {
-      *foundPos = pos;
+  if (startPos > mLength)
+    startPos = mLength;
+  
+  // TODO: for performance reasons, we can re-insert the ASCII search here 
which is about three times as fast if searchChar is <128
+  
+  for (startPos = prev_char(startPos); startPos>=0; startPos = 
prev_char(startPos)) {
+    if (searchChar == char_at(startPos)) {
+      *foundPos = startPos;
       return 1;
     }
   }
   
-  for (; pos >= 0; pos--) {
-    if (mBuf[pos] == searchChar) {
-      *foundPos = pos;
-      return 1;
-    }
-  }
   *foundPos = 0;
   return 0;
 }
 
 
+/*
+ Insert text from a file.
+ Unicode safe. Inout must be correct utf8!
+ */
 int Fl_Text_Buffer::insertfile(const char *file, int pos, int buflen)
 {
   FILE *fp;
@@ -1253,6 +1549,11 @@
   return e;
 }
 
+
+/*
+ Write text to file,
+ Unicode safe.
+ */
 int Fl_Text_Buffer::outputfile(const char *file, int start, int end,
                               int buflen)
 {
@@ -1273,6 +1574,39 @@
 }
 
 
+/*
+ Return the previous character position.
+ Uncode safe.
+ */
+int Fl_Text_Buffer::prev_char(int pos) const
+{
+  if (pos<=0)
+    return 0;
+
+  char c;
+  do {
+    pos--;
+    if (pos==0)
+      return 0;
+    c = byte_at(pos);
+  } while ( (c&0xc0) == 0x80);
+  
+  return pos;
+}
+
+/*
+ Return the next character position.
+ Uncode safe.
+ */
+int Fl_Text_Buffer::next_char(int pos) const
+{
+  int n = fl_utf8len(byte_at(pos));
+  pos += n;
+  if (pos>=mLength)
+    return mLength;
+  return pos;
+}
+
 //
 // End of "$Id$".
 //

Modified: branches/branch-1.3-STR2158-matt/src/Fl_Text_Display.cxx
===================================================================
--- branches/branch-1.3-STR2158-matt/src/Fl_Text_Display.cxx    2010-05-07 
20:23:07 UTC (rev 7595)
+++ branches/branch-1.3-STR2158-matt/src/Fl_Text_Display.cxx    2010-05-09 
20:55:07 UTC (rev 7596)
@@ -209,6 +209,8 @@
    (see extendRangeForStyleMods for more information on this protocol).
 
    Style buffers, tables and their associated memory are managed by the caller.
+ 
+ Styles are ranged from 65 ('A') to 126.
 */
 void Fl_Text_Display::highlight_data(Fl_Text_Buffer *styleBuffer,
                                 const Style_Table_Entry *styleTable,
@@ -427,7 +429,7 @@
   int ok = 0;
   while (!ok && startpos > 0) {
     // FIXME: character is ucs-4
-    char c = buffer()->at( startpos );
+    char c = buffer()->char_at( startpos );
     if (!((c & 0x80) && !(c & 0x40))) {
       ok = 1;
     } else {
@@ -436,7 +438,7 @@
   }
   while (!ok && endpos < buffer()->length()) {
     // FIXME: character is ucs-4
-    char c = buffer()->at( endpos );
+    char c = buffer()->char_at( endpos );
     if (!((c & 0x80) && !(c & 0x40))) {
       ok = 1;
     } else {
@@ -574,6 +576,7 @@
   Word-wrapping does not change the text buffer itself, only the way that the 
text is displayed.
 */
 void Fl_Text_Display::wrap_mode(int wrap, int wrapMargin) {
+  // FIXME: fix the commentary
   mWrapMargin = wrapMargin;
   mContinuousWrap = wrap;
 
@@ -641,7 +644,7 @@
     if ( p == buf->length() )
       break;
     // FIXME: character is ucs-4
-    ch = buf->at( p );
+    ch = buf->char_at( p );
     if ( ch == '\n' )
       break;
     indent++;
@@ -851,11 +854,8 @@
   if ( mCursorPos >= mBuffer->length() )
     return 0;
   int p = insert_position();
-  const char *a = buffer()->address(p);
-  int o = fl_utf8len(*a);
-  if (o==-1)
-    return 0;
-  insert_position(p+o);
+  int q = buffer()->next_char(p);
+  insert_position(q);
   return 1;
 }
 
@@ -867,9 +867,8 @@
   if ( mCursorPos <= 0 )
     return 0;
   int p = insert_position();
-  const char *a = buffer()->address(p-1); // avoid falling into gap
-  const char *b = a; while (((*b) & 0xc0)==0x80) b--; // FIXME: fl_utf8_back( 
-  insert_position(p+(b-a)-1);
+  int q = buffer()->prev_char(p);
+  insert_position(q);
   return 1;
 }
 
@@ -908,7 +907,7 @@
   while (!ok) {
     int pos = insert_position();
     // FIXME: character is ucs-4
-    char c = buffer()->at( pos );
+    char c = buffer()->char_at( pos );
     if (!((c & 0x80) && !(c & 0x40))) {
       ok = 1;
     } else {
@@ -945,7 +944,7 @@
   while (!ok) {
     int pos = insert_position();
     // FIXME: character is ucs-4
-    char c = buffer()->at( pos );
+    char c = buffer()->char_at( pos );
     if (!((c & 0x80) && !(c & 0x40))) {
       ok = 1;
     } else {
@@ -1095,11 +1094,11 @@
 void Fl_Text_Display::next_word() {
   int pos = insert_position();
   // FIXME: character is ucs-4
-  while (pos < buffer()->length() && !fl_isseparator(buffer()->at(pos))) {
+  while (pos < buffer()->length() && !fl_isseparator(buffer()->char_at(pos))) {
     pos++;
   }
   // FIXME: character is ucs-4
-  while (pos < buffer()->length() && fl_isseparator(buffer()->at(pos))) {
+  while (pos < buffer()->length() && fl_isseparator(buffer()->char_at(pos))) {
     pos++;
   }
 
@@ -1112,15 +1111,15 @@
   if (pos==0) return;
   pos--;
   // FIXME: character is ucs-4
-  while (pos && fl_isseparator(buffer()->at(pos))) {
+  while (pos && fl_isseparator(buffer()->char_at(pos))) {
     pos--;
   }
   // FIXME: character is ucs-4
-  while (pos && !fl_isseparator(buffer()->at(pos))) {
+  while (pos && !fl_isseparator(buffer()->char_at(pos))) {
     pos--;
   }
   // FIXME: character is ucs-4
-  if (fl_isseparator(buffer()->at(pos))) pos++;
+  if (fl_isseparator(buffer()->char_at(pos))) pos++;
 
   insert_position( pos );
 }
@@ -1748,13 +1747,11 @@
   if ( lineIndex >= lineLen )
     style = FILL_MASK;
   else if ( styleBuf != NULL ) {
-    // FIXME: character is ucs-4
-    style = ( unsigned char ) styleBuf->at( pos );
+    style = ( unsigned char ) styleBuf->byte_at( pos );
     if (style == mUnfinishedStyle && mUnfinishedHighlightCB) {
         /* encountered "unfinished" style, trigger parsing */
         (mUnfinishedHighlightCB)( pos, mHighlightCBArg);
-        // FIXME: character is ucs-4
-        style = (unsigned char) styleBuf->at( pos);
+        style = (unsigned char) styleBuf->byte_at( pos);
     }
   }
   if (buf->primary_selection()->includes(pos))
@@ -2331,7 +2328,7 @@
        nLines++;
        if (lineStart > pos + nInserted &&
             // FIXME: character is ucs-4
-               buf->at(lineStart-1) == '\n') {
+               buf->char_at(lineStart-1) == '\n') {
            countTo = lineStart;
            *modRangeEnd = lineStart;
            break;
@@ -2477,7 +2474,7 @@
        nLines++;
        if (lineStart > pos + nDeleted &&
             // FIXME: character is ucs-4
-               buf->at(lineStart-1) == '\n') {
+               buf->char_at(lineStart-1) == '\n') {
            break;
        }
        
@@ -2548,14 +2545,14 @@
     
     /*
     ** Loop until position exceeds maxPos or line count exceeds maxLines.
-    ** (actually, contines beyond maxPos to end of line containing maxPos,
+    ** (actually, continues beyond maxPos to end of line containing maxPos,
     ** in case later characters cause a word wrap back before maxPos)
     */
     colNum = 0;
     width = 0;
     for (p=lineStart; p<buf->length(); p++) {
       // FIXME: character is ucs-4
-       c = (unsigned char)buf->at(p);
+       c = (unsigned char)buf->char_at(p);
 
        /* If the character was a newline, count the line and start over,
           otherwise, add it to the width and column counts */
@@ -2591,7 +2588,7 @@
            foundBreak = false;
            for (b=p; b>=lineStart; b--) {
               // FIXME: character is ucs-4
-               c = (unsigned char)buf->at(b);
+               c = (unsigned char)buf->char_at(b);
                if (c == '\t' || c == ' ') {
                    newLineStart = b + 1;
                    if (countPixels) {
@@ -2720,7 +2717,7 @@
        return 1;
     
   // FIXME: character is ucs-4
-    c = buffer()->at(lineEndPos);
+    c = buffer()->char_at(lineEndPos);
     return c == '\n' || ((c == '\t' || c == ' ') &&
            lineEndPos + 1 != buffer()->length());
 }
@@ -2990,7 +2987,7 @@
         int ok = 0;
         while (!ok) {
           // FIXME: character is ucs-4
-          char c = buffer()->at( pos );
+          char c = buffer()->char_at( pos );
           if (!((c & 0x80) && !(c & 0x40))) {
             ok = 1;
           } else {
@@ -3056,7 +3053,7 @@
          int ok = 0;
           while (!ok) {
             // FIXME: character is ucs-4
-            char c = buffer()->at( pos );
+            char c = buffer()->char_at( pos );
             if (!((c & 0x80) && !(c & 0x40))) {
               ok = 1;
             } else {

Modified: branches/branch-1.3-STR2158-matt/src/Fl_Text_Editor.cxx
===================================================================
--- branches/branch-1.3-STR2158-matt/src/Fl_Text_Editor.cxx     2010-05-07 
20:23:07 UTC (rev 7595)
+++ branches/branch-1.3-STR2158-matt/src/Fl_Text_Editor.cxx     2010-05-09 
20:55:07 UTC (rev 7596)
@@ -255,7 +255,7 @@
   if (!e->buffer()->selected() && e->move_left()) {
     int l = 1;
     // FIXME: character is ucs-4
-    char c = e->buffer()->at(e->insert_position());
+    char c = e->buffer()->char_at(e->insert_position());
     if (c & 0x80 && c & 0x40) {
       l = fl_utf8len(c);
     }
@@ -451,7 +451,7 @@
   if (!e->buffer()->selected()) {
     int l = 1;
     // FIXME: character is ucs-4
-    char c = e->buffer()->at(e->insert_position());
+    char c = e->buffer()->char_at(e->insert_position());
     if (c & 0x80 && c & 0x40) {
       l = fl_utf8len(c);
     }

Modified: branches/branch-1.3-STR2158-matt/test/editor.cxx
===================================================================
--- branches/branch-1.3-STR2158-matt/test/editor.cxx    2010-05-07 20:23:07 UTC 
(rev 7595)
+++ branches/branch-1.3-STR2158-matt/test/editor.cxx    2010-05-09 20:55:07 UTC 
(rev 7596)
@@ -789,6 +789,7 @@
                               sizeof(styletable) / sizeof(styletable[0]),
                              'A', style_unfinished_cb, 0);
     w->editor->textfont(FL_COURIER);
+  //w->editor->wrap_mode(1, 0); // FIXME: test wrap modes
   w->end();
   w->resizable(w->editor);
   w->callback((Fl_Callback *)close_cb, w);

_______________________________________________
fltk-commit mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk-commit

Reply via email to