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