1 //
2 // "$Id: Fl_Text_Buffer.H 8148 2010-12-31 22:38:03Z matt $"
3 //
4 // Header file for Fl_Text_Buffer class.
5 //
6 // Copyright 2001-2010 by Bill Spitzak and others.
7 // Original code Copyright Mark Edel.  Permission to distribute under
8 // the LGPL for the FLTK library granted by Mark Edel.
9 //
10 // This library is free software; you can redistribute it and/or
11 // modify it under the terms of the GNU Library General Public
12 // License as published by the Free Software Foundation; either
13 // version 2 of the License, or (at your option) any later version.
14 //
15 // This library is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 // Library General Public License for more details.
19 //
20 // You should have received a copy of the GNU Library General Public
21 // License along with this library; if not, write to the Free Software
22 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
23 // USA.
24 //
25 // Please report all bugs and problems on the following page:
26 //
27 //     http://www.fltk.org/str.php
28 //
29 
30 /* \file
31  Fl_Text_Buffer, Fl_Text_Selection widget . */
32 
33 #ifndef FL_TEXT_BUFFER_H
34 #define FL_TEXT_BUFFER_H
35 
36 
37 #undef ASSERT_UTF8
38 
39 #ifdef ASSERT_UTF8
40 # include <assert.h>
41 # define IS_UTF8_ALIGNED(a) if (a && *a) assert(fl_utf8len(*(a))>0);
42 # define IS_UTF8_ALIGNED2(a, b) if (b>=0 && b<a->length()) assert(fl_utf8len(a->byte_at(b))>0);
43 #else
44 # define IS_UTF8_ALIGNED(a)
45 # define IS_UTF8_ALIGNED2(a, b)
46 #endif
47 
48 
49 /*
50  "character size" is the size of a UTF-8 character in bytes
51  "character width" is the width of a Unicode character in pixels
52  "column" was orginally defined as a character offset from the left margin.
53  It was identical to the byte offset. In UTF-8, we have neither a byte offset
54  nor truly fixed width fonts (*). Column could be a pixel value multiplied with
55  an average character width (which is a bearable approximation).
56 
57  * in Unicode, there are no fixed width fonts! Even if the ASCII characters may
58    happen to be all the same width in pixels, chinese charcaters surely are not.
59    There are plenty of exceptions, like ligatures, that make special handling of
60    "fixed" character widths a nightmare. I decided to remove all references to
61    fixed fonts and see "columns" as a multiple of the average width of a
62    character in the main font.
63      - Matthias
64  */
65 
66 
67 /* Maximum length in characters of a tab or control character expansion
68  of a single buffer character */
69 #define FL_TEXT_MAX_EXP_CHAR_LEN 20
70 
71 #include "Fl_Export.H"
72 
73 
74 /**
75  \class Fl_Text_Selection
76  \brief This is an internal class for Fl_Text_Buffer to manage text selections.
77  This class works correctly with utf-8 strings assuming that the parameters
78  for all calls are on character boundaries.
79  */
80 class FL_EXPORT Fl_Text_Selection {
81   friend class Fl_Text_Buffer;
82 
83 public:
84 
85   /**
86    \brief Set the selection range.
87    \param start byte offset to first selected character
88    \param end byte offset pointing after last selected character
89    */
90   void set(int start, int end);
91 
92   /**
93    \brief Updates a selection afer text was modified.
94    Updates an individual selection for changes in the corresponding text
95    \param pos byte offset into text buffer at which the change occured
96    \param nDeleted number of bytes deleted from the buffer
97    \param nInserted number of bytes inserted into the buffer
98    */
99   void update(int pos, int nDeleted, int nInserted);
100 
101   /**
102    \brief Return the byte offset to the first selected character.
103    \return byte offset
104    */
start()105   int start() const { return mStart; }
106 
107   /**
108    \brief Return the byte ofsset to the character after the last selected character.
109    \return byte offset
110    */
end()111   int end() const { return mEnd; }
112 
113   /**
114    \brief Returns true if any text is selected.
115    \return a non-zero number if any text has been selected, or 0
116    if no text is selected.
117    */
selected()118   bool selected() const { return mSelected; }
119 
120   /**
121    \brief Modify the 'selected' flag.
122    \param b new flag
123    */
selected(bool b)124   void selected(bool b) { mSelected = b; }
125 
126   /**
127    Return true if position \p pos with indentation \p dispIndex is in
128    the Fl_Text_Selection.
129    */
130   int includes(int pos) const;
131 
132   /**
133    \brief Return the positions of this selection.
134    \param start retrun byte offset to first selected character
135    \param end retrun byte offset pointing after last selected character
136    \return true if selected
137    */
138   int position(int* start, int* end) const;
139 
140 protected:
141 
142   int mStart;         ///< byte offset to the first selected character
143   int mEnd;           ///< byte offset to the character after the last selected character
144   bool mSelected;     ///< this flag is set if any text is selected
145 };
146 
147 
148 typedef void (*Fl_Text_Modify_Cb)(int pos, int nInserted, int nDeleted,
149                                   int nRestyled, const char* deletedText,
150                                   void* cbArg);
151 
152 
153 typedef void (*Fl_Text_Predelete_Cb)(int pos, int nDeleted, void* cbArg);
154 
155 
156 /**
157  \brief This class manages unicode displayed in one or more Fl_Text_Display widgets.
158 
159  All text in Fl_Text_Buffermust be encoded in UTF-8. All indices used in the
160  function calls must be aligned to the start of a UTF-8 sequence. All indices
161  and pointers returned will be aligned. All functions that return a single
162  character will return that in an unsiged int in UCS-4 encoding.
163 
164  The Fl_Text_Buffer class is used by the Fl_Text_Display
165  and Fl_Text_Editor to manage complex text data and is based upon the
166  excellent NEdit text editor engine - see http://www.nedit.org/.
167  */
168 class FL_EXPORT Fl_Text_Buffer {
169 public:
170 
171   /**
172    Create an empty text buffer of a pre-determined size.
173    \param requestedSize use this to avoid unnecessary re-allocation
174     if you know exactly how much the buffer will need to hold
175    \param preferredGapSize Initial size for the buffer gap (empty space
176     in the buffer where text might be inserted
177     if the user is typing sequential chars)
178    */
179   Fl_Text_Buffer(int requestedSize = 0, int preferredGapSize = 1024);
180 
181   /**
182    Frees a text buffer
183    */
184   ~Fl_Text_Buffer();
185 
186   /**
187    \brief Returns the number of bytes in the buffer.
188    \return size of text in bytes
189    */
length()190   int length() const { return mLength; }
191 
192   /**
193    \brief Get a copy of the entire contents of the text buffer.
194    Memory is allocated to contain the returned string, which the caller
195    must free.
196    \return newly allocated text buffer - must be free'd, text is utf8
197    */
198   char* text() const;
199 
200   /**
201    Replaces the entire contents of the text buffer.
202    \param text Text must be valid utf8.
203    */
204   void text(const char* text);
205 
206   /**
207    \brief Get a copy of a part of the text buffer.
208    Return a copy of the text between \p start and \p end character positions
209    from text buffer \p buf. Positions start at 0, and the range does not
210    include the character pointed to by \p end.
211    When you are done with the text, free it using the free() function.
212    \param start byte offset to first character
213    \param end byte offset after last character in range
214    \return newly allocated text buffer - must be free'd, text is utf8
215    */
216   char* text_range(int start, int end) const;
217 
218   /**
219    Returns the character at the specified position pos in the buffer.
220    Positions start at 0
221    \param pos byte offset into buffer, pos must be at acharacter boundary
222    \return Unicode UCS-4 encoded character
223    */
224   unsigned int char_at(int pos) const;
225 
226   /**
227    Returns the raw byte at the specified position pos in the buffer.
228    Positions start at 0
229    \param pos byte offset into buffer
230    \return unencoded raw byte
231    */
232   char byte_at(int pos) const;
233 
234   /**
235    Convert a byte offset in buffer into a memory address.
236    \param pos byte offset into buffer
237    \return byte offset converted to a memory address
238    */
address(int pos)239   const char *address(int pos) const
240   { return (pos < mGapStart) ? mBuf+pos : mBuf+pos+mGapEnd-mGapStart; }
241 
242   /**
243    Convert a byte offset in buffer into a memory address.
244    \param pos byte offset into buffer
245    \return byte offset converted to a memory address
246    */
address(int pos)247   char *address(int pos)
248   { return (pos < mGapStart) ? mBuf+pos : mBuf+pos+mGapEnd-mGapStart; }
249 
250   /**
251    Inserts null-terminated string \p text at position \p pos.
252    \param pos insertion position as byte offset (must be utf-8 character aligned)
253    \param text utf-8 encoded and nul terminated text
254    */
255   void insert(int pos, const char* text);
256 
257   /**
258    Appends the text string to the end of the buffer.
259    \param t utf-8 encoded and nul terminated text
260    */
append(const char * t)261   void append(const char* t) { insert(length(), t); }
262 
263   /**
264    Deletes a range of characters in the buffer.
265    \param start byte offset to first character to be removed
266    \param end byte offset to charcatre after last character to be removed
267    */
268   void remove(int start, int end);
269 
270   /**
271    Deletes the characters between \p start and \p end, and inserts the null-terminated string \p text in their place in the buffer.
272    \param start byte offset to first character to be removed and new insert position
273    \param end byte offset to charcatre after last character to be removed
274    \param text utf-8 encoded and nul terminated text
275    */
276   void replace(int start, int end, const char *text);
277 
278   /**
279    Copies text from one buffer to this one.
280    \param fromBuf source text buffer may be the same as this
281    \param fromStart byte offset into buffer
282    \param fromEnd byte offset into buffer
283    \param toPos destination byte offset into buffer
284    */
285   void copy(Fl_Text_Buffer* fromBuf, int fromStart, int fromEnd, int toPos);
286 
287   /**
288    Undo text modification according to the undo variables or insert text
289    from the undo buffer
290    */
291   int undo(int *cp=0);
292 
293   /**
294    Lets the undo system know if we can undo changes
295    */
296   void canUndo(char flag=1);
297 
298   /**
299    Inserts a file at the specified position. Returns 0 on success,
300    non-zero on error (strerror() contains reason).  1 indicates open
301    for read failed (no data loaded). 2 indicates error occurred
302    while reading data (data was partially loaded).
303    File can be UTF-8 or CP1252-encoded.
304    If the input file is not UTF-8-encoded, the Fl_Text_Buffer widget will contain
305    UTF-8-transcoded data. By default, the message Fl_Text_Buffer::file_encoding_warning_message
306    will warn the user about this.
307    \see input_file_was_transcoded and transcoding_warning_action.
308    */
309   int insertfile(const char *file, int pos, int buflen = 128*1024);
310 
311   /**
312    Appends the named file to the end of the buffer. See also insertfile().
313    */
314   int appendfile(const char *file, int buflen = 128*1024)
315   { return insertfile(file, length(), buflen); }
316 
317   /**
318    Loads a text file into the buffer. See also insertfile().
319    */
320   int loadfile(const char *file, int buflen = 128*1024)
321   { select(0, length()); remove_selection(); return appendfile(file, buflen); }
322 
323   /**
324    Writes the specified portions of the file to a file. Returns 0 on success, non-zero
325    on error (strerror() contains reason).  1 indicates open for write failed
326    (no data saved). 2 indicates error occurred while writing data
327    (data was partially saved).
328    */
329   int outputfile(const char *file, int start, int end, int buflen = 128*1024);
330 
331   /**
332    Saves a text file from the current buffer
333    */
334   int savefile(const char *file, int buflen = 128*1024)
335   { return outputfile(file, 0, length(), buflen); }
336 
337   /**
338    Gets the tab width.
339    */
tab_distance()340   int tab_distance() const { return mTabDist; }
341 
342   /**
343    Set the hardware tab distance (width) used by all displays for this buffer,
344    and used in computing offsets for rectangular selection operations.
345    */
346   void tab_distance(int tabDist);
347 
348   /**
349    Selects a range of characters in the buffer.
350    */
351   void select(int start, int end);
352 
353   /**
354    Returns a non 0 value if text has been selected, 0 otherwise
355    */
selected()356   int selected() const { return mPrimary.selected(); }
357 
358   /**
359    Cancels any previous selection on the primary text selection object
360    */
361   void unselect();
362 
363   /**
364    Gets the selection position
365    */
366   int selection_position(int* start, int* end);
367 
368   /**
369    Returns the currently selected text. When you are done with
370    the text, free it using the free() function.
371    */
372   char* selection_text();
373 
374   /**
375    Removes the text in the primary selection.
376    */
377   void remove_selection();
378 
379   /**
380    Replaces the text in the primary selection.
381    */
382   void replace_selection(const char* text);
383 
384   /**
385    Selects a range of characters in the secondary selection.
386    */
387   void secondary_select(int start, int end);
388 
389   /**
390    Returns a non 0 value if text has been selected in the secondary
391    text selection, 0 otherwise
392    */
secondary_selected()393   int secondary_selected() { return mSecondary.selected(); }
394 
395   /**
396    Clears any selection in the secondary text selection object.
397    */
398   void secondary_unselect();
399 
400   /**
401    Returns the current selection in the secondary text selection object.
402    */
403   int secondary_selection_position(int* start, int* end);
404 
405   /**
406    Returns the text in the secondary selection. When you are
407    done with the text, free it using the free() function.
408    */
409   char* secondary_selection_text();
410 
411   /**
412    Removes the text from the buffer corresponding to the secondary text selection object.
413    */
414   void remove_secondary_selection();
415 
416   /**
417    Replaces the text from the buffer corresponding to the secondary
418    text selection object with the new string \p text.
419    */
420   void replace_secondary_selection(const char* text);
421 
422   /**
423    Highlights the specified text within the buffer.
424    */
425   void highlight(int start, int end);
426 
427   /**
428    Returns the highlighted text. When you are done with the
429    text, free it using the free() function.
430    */
highlight()431   int highlight() { return mHighlight.selected(); }
432 
433   /**
434    Unhighlights text in the buffer.
435    */
436   void unhighlight();
437 
438   /**
439    Highlights the specified text between \p start and \p end within the buffer.
440    */
441   int highlight_position(int* start, int* end);
442 
443   /**
444    Returns the highlighted text. When you are done with the
445    text, free it using the free() function.
446    */
447   char* highlight_text();
448 
449   /**
450    Adds a callback function that is called whenever the text buffer is
451    modified. The callback function is declared as follows:
452 
453    \code
454    typedef void (*Fl_Text_Modify_Cb)(int pos, int nInserted, int nDeleted,
455       int nRestyled, const char* deletedText,
456       void* cbArg);
457    \endcode
458    */
459   void add_modify_callback(Fl_Text_Modify_Cb bufModifiedCB, void* cbArg);
460 
461   /**
462    Removes a modify callback.
463    */
464   void remove_modify_callback(Fl_Text_Modify_Cb bufModifiedCB, void* cbArg);
465 
466   /**
467    Calls all modify callbacks that have been registered using
468    the add_modify_callback()
469    method.
470    */
call_modify_callbacks()471   void call_modify_callbacks() { call_modify_callbacks(0, 0, 0, 0, 0); }
472 
473   /**
474    Adds a callback routine to be called before text is deleted from the buffer.
475    */
476   void add_predelete_callback(Fl_Text_Predelete_Cb bufPredelCB, void* cbArg);
477 
478   /**
479    Removes a callback routine \p bufPreDeleteCB associated with argument \p cbArg
480    to be called before text is deleted from the buffer.
481    */
482   void remove_predelete_callback(Fl_Text_Predelete_Cb predelCB, void* cbArg);
483 
484   /**
485    Calls the stored pre-delete callback procedure(s) for this buffer to update
486    the changed area(s) on the screen and any other listeners.
487    */
call_predelete_callbacks()488   void call_predelete_callbacks() { call_predelete_callbacks(0, 0); }
489 
490   /**
491    Returns the text from the entire line containing the specified
492    character position. When you are done with the text, free it
493    using the free() function.
494    \param pos byte index into buffer
495    \return copy of utf8 text, must be free'd
496    */
497   char* line_text(int pos) const;
498 
499   /**
500    Returns the position of the start of the line containing position \p pos.
501    \param pos byte index into buffer
502    \return byte offset to line start
503    */
504   int line_start(int pos) const;
505 
506   /**
507    Finds and returns the position of the end of the line containing position \p pos
508    (which is either a pointer to the newline character ending the line,
509    or a pointer to one character beyond the end of the buffer)
510    \param pos byte index into buffer
511    \return byte offset to line end
512    */
513   int line_end(int pos) const;
514 
515   /**
516    Returns the position corresponding to the start of the word
517    \param pos byte index into buffer
518    \return byte offset to word start
519    */
520   int word_start(int pos) const;
521 
522   /**
523    Returns the position corresponding to the end of the word.
524    \param pos byte index into buffer
525    \return byte offset to word end
526    */
527   int word_end(int pos) const;
528 
529   /**
530    Count the number of displayed characters between buffer position
531    \p lineStartPos and \p targetPos. (displayed characters are the characters
532    shown on the screen to represent characters in the buffer, where tabs and
533    control characters are expanded)
534    */
535   int count_displayed_characters(int lineStartPos, int targetPos) const;
536 
537   /**
538    Count forward from buffer position \p startPos in displayed characters
539    (displayed characters are the characters shown on the screen to represent
540    characters in the buffer, where tabs and control characters are expanded)
541    \param lineStartPos byte offset into buffer
542    \param nChars number of bytes that are sent to the display
543    \return byte offset in input after all output bytes are sent
544    */
545   int skip_displayed_characters(int lineStartPos, int nChars);
546 
547   /**
548    Counts the number of newlines between \p startPos and \p endPos in buffer.
549    The character at position \p endPos is not counted.
550    */
551   int count_lines(int startPos, int endPos) const;
552 
553   /**
554    Finds the first character of the line \p nLines forward from \p startPos
555    in the buffer and returns its position
556    */
557   int skip_lines(int startPos, int nLines);
558 
559   /**
560    Finds and returns the position of the first character of the line \p nLines backwards
561    from \p startPos (not counting the character pointed to by \p startpos if
562    that is a newline) in the buffer.  \p nLines == 0 means find the beginning of the line
563    */
564   int rewind_lines(int startPos, int nLines);
565 
566   /**
567    Finds the next occurrence of the specified character.
568    Search forwards in buffer for character \p searchChar, starting
569    with the character \p startPos, and returning the result in \p foundPos
570    returns 1 if found, 0 if not.  (The difference between this and
571    BufSearchForward is that it's optimized for single characters.  The
572    overall performance of the text widget is dependent on its ability to
573    count lines quickly, hence searching for a single character: newline)
574    \param startPos byte offset to start position
575    \param searchChar UCS-4 character that we want to find
576    \param foundPos byte offset where the character was found
577    \return 1 if found, 0 if not
578    */
579   int findchar_forward(int startPos, unsigned searchChar, int* foundPos) const;
580 
581   /**
582    Search backwards in buffer \p buf for character \p searchChar, starting
583    with the character BEFORE \p startPos, returning the result in \p foundPos
584    returns 1 if found, 0 if not.  (The difference between this and
585    BufSearchBackward is that it's optimized for single characters.  The
586    overall performance of the text widget is dependent on its ability to
587    count lines quickly, hence searching for a single character: newline)
588    \param startPos byte offset to start position
589    \param searchChar UCS-4 character that we want to find
590    \param foundPos byte offset where the character was found
591    \return 1 if found, 0 if not
592    */
593   int findchar_backward(int startPos, unsigned int searchChar, int* foundPos) const;
594 
595   /**
596    Search forwards in buffer for string \p searchString, starting with the
597    character \p startPos, and returning the result in \p foundPos
598    returns 1 if found, 0 if not.
599    \param startPos byte offset to start position
600    \param searchString utf8 string that we want to find
601    \param foundPos byte offset where the string was found
602    \param matchCase if set, match character case
603    \return 1 if found, 0 if not
604    */
605   int search_forward(int startPos, const char* searchString, int* foundPos,
606                      int matchCase = 0) const;
607 
608   /**
609    Search backwards in buffer for string <i>searchCharssearchString</i>, starting with the
610    character BEFORE \p startPos, returning the result in \p foundPos
611    returns 1 if found, 0 if not.
612    \param startPos byte offset to start position
613    \param searchString utf8 string that we want to find
614    \param foundPos byte offset where the string was found
615    \param matchCase if set, match character case
616    \return 1 if found, 0 if not
617    */
618   int search_backward(int startPos, const char* searchString, int* foundPos,
619                       int matchCase = 0) const;
620 
621   /**
622    Returns the primary selection.
623    */
primary_selection()624   const Fl_Text_Selection* primary_selection() const { return &mPrimary; }
625 
626   /**
627    Returns the primary selection.
628    */
primary_selection()629   Fl_Text_Selection* primary_selection() { return &mPrimary; }
630 
631   /**
632    Returns the secondary selection.
633    */
secondary_selection()634   const Fl_Text_Selection* secondary_selection() const { return &mSecondary; }
635 
636   /**
637    Returns the current highlight selection.
638    */
highlight_selection()639   const Fl_Text_Selection* highlight_selection() const { return &mHighlight; }
640 
641   /**
642    Returns the index of the previous character.
643    \param ix index to the current char
644    */
645   int prev_char(int ix) const;
646   int prev_char_clipped(int ix) const;
647 
648   /**
649    Returns the index of the next character.
650    \param ix index to the current char
651    */
652   int next_char(int ix) const;
653   int next_char_clipped(int ix) const;
654 
655   /**
656    Align an index into the buffer to the current or previous utf8 boundary.
657    */
658   int utf8_align(int) const;
659 
660   /**
661    \brief true iff the loaded file has been transcoded to UTF-8
662    */
663   int input_file_was_transcoded;
664 
665   /** This message may be displayed using the fl_alert() function when a file
666    which was not UTF-8 encoded is input.
667    */
668   static const char* file_encoding_warning_message;
669 
670   /**
671    \brief Pointer to a function called after reading a non UTF-8 encoded file.
672 
673    This function is called after reading a file if the file content
674    was transcoded to UTF-8. Its default implementation calls fl_alert()
675    with the text of \ref file_encoding_warning_message. No warning message is
676    displayed if this pointer is set to NULL. Use \ref input_file_was_transcoded
677    to be informed if file input required transcoding to UTF-8.
678    */
679   void (*transcoding_warning_action)(Fl_Text_Buffer*);
680 
681 protected:
682 
683   /**
684    Calls the stored modify callback procedure(s) for this buffer to update the
685    changed area(s) on the screen and any other listeners.
686    */
687   void call_modify_callbacks(int pos, int nDeleted, int nInserted,
688                              int nRestyled, const char* deletedText) const;
689 
690   /**
691    Calls the stored pre-delete callback procedure(s) for this buffer to update
692    the changed area(s) on the screen and any other listeners.
693    */
694   void call_predelete_callbacks(int pos, int nDeleted) const;
695 
696   /**
697    Internal (non-redisplaying) version of BufInsert. Returns the length of
698    text inserted (this is just strlen(\p text), however this calculation can be
699    expensive and the length will be required by any caller who will continue
700    on to call redisplay). \p pos must be contiguous with the existing text in
701    the buffer (i.e. not past the end).
702    \return the number of bytes inserted
703    */
704   int insert_(int pos, const char* text);
705 
706   /**
707    Internal (non-redisplaying) version of BufRemove.  Removes the contents
708    of the buffer between start and end (and moves the gap to the site of
709    the delete).
710    */
711   void remove_(int start, int end);
712 
713   /**
714    Calls the stored redisplay procedure(s) for this buffer to update the
715    screen for a change in a selection.
716    */
717   void redisplay_selection(Fl_Text_Selection* oldSelection,
718                            Fl_Text_Selection* newSelection) const;
719 
720   /**
721    Move the gap to start at a new position.
722    */
723   void move_gap(int pos);
724 
725   /**
726    Reallocates the text storage in the buffer to have a gap starting at \p newGapStart
727    and a gap size of \p newGapLen, preserving the buffer's current contents.
728    */
729   void reallocate_with_gap(int newGapStart, int newGapLen);
730 
731   char* selection_text_(Fl_Text_Selection* sel) const;
732 
733   /**
734    Removes the text from the buffer corresponding to \p sel.
735    */
736   void remove_selection_(Fl_Text_Selection* sel);
737 
738   /**
739    Replaces the \p text in selection \p sel.
740    */
741   void replace_selection_(Fl_Text_Selection* sel, const char* text);
742 
743   /**
744    Updates all of the selections in the buffer for changes in the buffer's text
745    */
746   void update_selections(int pos, int nDeleted, int nInserted);
747 
748   Fl_Text_Selection mPrimary;     /**< highlighted areas */
749   Fl_Text_Selection mSecondary;   /**< highlighted areas */
750   Fl_Text_Selection mHighlight;   /**< highlighted areas */
751   int mLength;                    /**< length of the text in the buffer (the length
752                                    of the buffer itself must be calculated:
753                                    gapEnd - gapStart + length) */
754   char* mBuf;                     /**< allocated memory where the text is stored */
755   int mGapStart;                  /**< points to the first character of the gap */
756   int mGapEnd;                    /**< points to the first char after the gap */
757   // The hardware tab distance used by all displays for this buffer,
758   // and used in computing offsets for rectangular selection operations.
759   int mTabDist;                   /**< equiv. number of characters in a tab */
760   int mNModifyProcs;              /**< number of modify-redisplay procs attached */
761   Fl_Text_Modify_Cb *mModifyProcs;/**< procedures to call when buffer is
762                                    modified to redisplay contents */
763   void** mCbArgs;                 /**< caller arguments for modifyProcs above */
764   int mNPredeleteProcs;           /**< number of pre-delete procs attached */
765   Fl_Text_Predelete_Cb *mPredeleteProcs; /**< procedure to call before text is deleted
766                                    from the buffer; at most one is supported. */
767   void **mPredeleteCbArgs;        /**< caller argument for pre-delete proc above */
768   int mCursorPosHint;             /**< hint for reasonable cursor position after
769                                    a buffer modification operation */
770   char mCanUndo;                  /**< if this buffer is used for attributes, it must
771                                    not do any undo calls */
772   int mPreferredGapSize;          /**< the default allocation for the text gap is 1024
773                                    bytes and should only be increased if frequent
774                                    and large changes in buffer size are expected */
775 };
776 
777 #endif
778 
779 //
780 // End of "$Id: Fl_Text_Buffer.H 8148 2010-12-31 22:38:03Z matt $".
781 //
782