1 //
2 // "$Id: Fl_Text_Display.H 8306 2011-01-24 17:04:22Z matt $"
3 //
4 // Header file for Fl_Text_Display 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_Display widget . */
32 
33 #ifndef FL_TEXT_DISPLAY_H
34 #define FL_TEXT_DISPLAY_H
35 
36 #include "fl_draw.H"
37 #include "Fl_Group.H"
38 #include "Fl_Widget.H"
39 #include "Fl_Scrollbar.H"
40 #include "Fl_Text_Buffer.H"
41 
42 /**
43  \brief Rich text display widget.
44 
45  This is the FLTK text display widget. It allows the user to view multiple lines
46  of text and supports highlighting and scrolling. The buffer that is displayed
47  in the widget is managed by the Fl_Text_Buffer class. A single Text Buffer
48  can be displayed by multiple Text Displays.
49  */
50 class FL_EXPORT Fl_Text_Display: public Fl_Group {
51 
52 public:
53 
54   /**
55    text display cursor shapes enumeration
56    */
57   enum {
58     NORMAL_CURSOR,    /**< I-beam */
59     CARET_CURSOR,     /**< caret under the text */
60     DIM_CURSOR,       /**< dim I-beam */
61     BLOCK_CURSOR,     /**< unfille box under the current character */
62     HEAVY_CURSOR      /**< thick I-beam */
63   };
64 
65   /**
66    the character position is the left edge of a character, whereas
67    the cursor is thought to be between the centers of two consecutive
68    characters.
69    */
70   enum {
71     CURSOR_POS,
72     CHARACTER_POS
73   };
74 
75   /**
76    drag types - they match Fl::event_clicks() so that single clicking to
77    start a collection selects by character, double clicking selects by
78    word and triple clicking selects by line.
79    */
80   enum {
81     DRAG_NONE = -2,
82     DRAG_START_DND = -1,
83     DRAG_CHAR = 0,
84     DRAG_WORD = 1,
85     DRAG_LINE = 2
86   };
87 
88   /**
89    wrap types - used in wrap_mode()
90    */
91   enum {
92     WRAP_NONE,      /**< don't wrap text at all */
93     WRAP_AT_COLUMN, /**< wrap text at the given text column */
94     WRAP_AT_PIXEL,  /**< wrap text at a pixel position */
95     WRAP_AT_BOUNDS  /**< wrap text so that it fits into the widget width */
96   };
97 
98   friend void fl_text_drag_me(int pos, Fl_Text_Display* d);
99 
100   typedef void (*Unfinished_Style_Cb)(int, void *);
101 
102   /**
103    This structure associates the color, font, andsize of a string to draw
104    with an attribute mask matching attr
105    */
106   struct Style_Table_Entry {
107     Fl_Color    color;
108     Fl_Font     font;
109     Fl_Fontsize size;
110     unsigned    attr;
111   };
112 
113   Fl_Text_Display(int X, int Y, int W, int H, const char *l = 0);
114   ~Fl_Text_Display();
115 
116   virtual int handle(int e);
117 
118   void buffer(Fl_Text_Buffer* buf);
119 
120   /**
121    Sets the current text buffer associated with the text widget.
122    Multiple text widgets can be associated with the same text buffer.
123    \param buf new text buffer
124    */
buffer(Fl_Text_Buffer & buf)125   void buffer(Fl_Text_Buffer& buf) { buffer(&buf); }
126 
127   /**
128    Gets the current text buffer associated with the text widget.
129    Multiple text widgets can be associated with the same text buffer.
130    \return current text buffer
131    */
buffer()132   Fl_Text_Buffer* buffer() const { return mBuffer; }
133 
134   void redisplay_range(int start, int end);
135   void scroll(int topLineNum, int horizOffset);
136   void insert(const char* text);
137   void overstrike(const char* text);
138   void insert_position(int newPos);
139 
140   /**
141    Gets the position of the text insertion cursor for text display.
142    \return insert position index into text buffer
143    */
insert_position()144   int insert_position() const { return mCursorPos; }
145   int position_to_xy(int pos, int* x, int* y) const;
146 
147   int in_selection(int x, int y) const;
148   void show_insert_position();
149 
150   int move_right();
151   int move_left();
152   int move_up();
153   int move_down();
154   int count_lines(int start, int end, bool start_pos_is_line_start) const;
155   int line_start(int pos) const;
156   int line_end(int startPos, bool startPosIsLineStart) const;
157   int skip_lines(int startPos, int nLines, bool startPosIsLineStart);
158   int rewind_lines(int startPos, int nLines);
159   void next_word(void);
160   void previous_word(void);
161 
162   void show_cursor(int b = 1);
163 
164   /**
165    Hides the text cursor.
166    */
hide_cursor()167   void hide_cursor() { show_cursor(0); }
168 
169   void cursor_style(int style);
170 
171   /**
172    Gets the text cursor color.
173    \return cursor color
174    */
cursor_color()175   Fl_Color cursor_color() const {return mCursor_color;}
176 
177   /**
178    Sets the text cursor color.
179    \param n new cursor color
180    */
cursor_color(Fl_Color n)181   void cursor_color(Fl_Color n) {mCursor_color = n;}
182 
183   /**
184    Gets the width/height of the scrollbars.
185    /return width of scrollbars
186    */
scrollbar_width()187   int scrollbar_width() const { return scrollbar_width_; }
188 
189   /**
190    Sets the width/height of the scrollbars.
191    \param W width of scrollbars
192    */
scrollbar_width(int W)193   void scrollbar_width(int W) { scrollbar_width_ = W; }
194 
195   /**
196    Gets the scrollbar alignment type.
197    \return scrollbar alignment
198    */
scrollbar_align()199   Fl_Align scrollbar_align() const { return scrollbar_align_; }
200 
201   /**
202    Sets the scrollbar alignment type.
203    \param a new scrollbar alignment
204    */
scrollbar_align(Fl_Align a)205   void scrollbar_align(Fl_Align a) { scrollbar_align_ = a; }
206 
207   /**
208    Moves the insert position to the beginning of the current word.
209    \param pos start calculation at this index
210    \return beginning of the words
211    */
word_start(int pos)212   int word_start(int pos) const { return buffer()->word_start(pos); }
213 
214   /**
215    Moves the insert position to the end of the current word.
216    \param pos start calculation at this index
217    \return index of first character after the end of the word
218    */
word_end(int pos)219   int word_end(int pos) const { return buffer()->word_end(pos); }
220 
221 
222   void highlight_data(Fl_Text_Buffer *styleBuffer,
223                       const Style_Table_Entry *styleTable,
224                       int nStyles, char unfinishedStyle,
225                       Unfinished_Style_Cb unfinishedHighlightCB,
226                       void *cbArg);
227 
228   int position_style(int lineStartPos, int lineLen, int lineIndex) const;
229 
230   /**
231    \todo FIXME : get set methods pointing on shortcut_
232    have no effects as shortcut_ is unused in this class and derived!
233    \return the current shortcut key
234    */
shortcut()235   int shortcut() const {return shortcut_;}
236 
237   /**
238    \todo FIXME : get set methods pointing on shortcut_
239    have no effects as shortcut_ is unused in this class and derived!
240    \param s the new shortcut key
241    */
shortcut(int s)242   void shortcut(int s) {shortcut_ = s;}
243 
244   /**
245    Gets the default font used when drawing text in the widget.
246    \return current text font face unless overridden by a style
247    */
textfont()248   Fl_Font textfont() const {return textfont_;}
249 
250   /**
251    Sets the default font used when drawing text in the widget.
252    \param s default text font face
253    */
textfont(Fl_Font s)254   void textfont(Fl_Font s) {textfont_ = s; mColumnScale = 0;}
255 
256   /**
257    Gets the default size of text in the widget.
258    \return current text height unless overridden by a style
259    */
textsize()260   Fl_Fontsize textsize() const {return textsize_;}
261 
262   /**
263    Sets the default size of text in the widget.
264    \param s new text size
265    */
textsize(Fl_Fontsize s)266   void textsize(Fl_Fontsize s) {textsize_ = s; mColumnScale = 0;}
267 
268   /**
269    Gets the default color of text in the widget.
270    \return text color unless overridden by a style
271    */
textcolor()272   Fl_Color textcolor() const {return textcolor_;}
273 
274   /**
275    Sets the default color of text in the widget.
276    \param n new text color
277    */
textcolor(Fl_Color n)278   void textcolor(Fl_Color n) {textcolor_ = n;}
279 
280   int wrapped_column(int row, int column) const;
281   int wrapped_row(int row) const;
282   void wrap_mode(int wrap, int wrap_margin);
283 
284   virtual void resize(int X, int Y, int W, int H);
285 
286   /**
287    Convert an x pixel position into a column number.
288    \param x number of pixels from the left margin
289    \return an approximate column number based on the main font
290    */
291   double x_to_col(double x) const;
292 
293   /**
294    Convert a column number into an x pixel position.
295    \param col an approximate column number based on the main font
296    \return number of pixels from the left margin to the left of an
297 	   average sized character
298    */
299   double col_to_x(double col) const;
300 
301 protected:
302   // Most (all?) of this stuff should only be called from resize() or
303   // draw().
304   // Anything with "vline" indicates thats it deals with currently
305   // visible lines.
306 
307   virtual void draw();
308   void draw_text(int X, int Y, int W, int H);
309   void draw_range(int start, int end);
310   void draw_cursor(int, int);
311 
312   void draw_string(int style, int x, int y, int toX, const char *string,
313                    int nChars) const;
314 
315   void draw_vline(int visLineNum, int leftClip, int rightClip,
316                   int leftCharIndex, int rightCharIndex);
317 
318   int find_x(const char *s, int len, int style, int x) const;
319 
320   enum {
321     DRAW_LINE,
322     FIND_INDEX,
323     FIND_INDEX_FROM_ZERO,
324     GET_WIDTH
325   };
326 
327   int handle_vline(int mode,
328                    int lineStart, int lineLen, int leftChar, int rightChar,
329                    int topClip, int bottomClip,
330                    int leftClip, int rightClip) const;
331 
332   void draw_line_numbers(bool clearAll);
333 
334   void clear_rect(int style, int x, int y, int width, int height) const;
335   void display_insert();
336 
337   void offset_line_starts(int newTopLineNum);
338 
339   void calc_line_starts(int startLine, int endLine);
340 
341   void update_line_starts(int pos, int charsInserted, int charsDeleted,
342                           int linesInserted, int linesDeleted, int *scrolled);
343 
344   void calc_last_char();
345 
346   int position_to_line( int pos, int* lineNum ) const;
347   double string_width(const char* string, int length, int style) const;
348 
349   static void scroll_timer_cb(void*);
350 
351   static void buffer_predelete_cb(int pos, int nDeleted, void* cbArg);
352   static void buffer_modified_cb(int pos, int nInserted, int nDeleted,
353                                  int nRestyled, const char* deletedText,
354                                  void* cbArg);
355 
356   static void h_scrollbar_cb(Fl_Scrollbar* w, Fl_Text_Display* d);
357   static void v_scrollbar_cb( Fl_Scrollbar* w, Fl_Text_Display* d);
358   void update_v_scrollbar();
359   void update_h_scrollbar();
360   int measure_vline(int visLineNum) const;
361   int longest_vline() const;
362   int empty_vlines() const;
363   int vline_length(int visLineNum) const;
364   int xy_to_position(int x, int y, int PosType = CHARACTER_POS) const;
365 
366   void xy_to_rowcol(int x, int y, int* row, int* column,
367                     int PosType = CHARACTER_POS) const;
368   void maintain_absolute_top_line_number(int state);
369   int get_absolute_top_line_number() const;
370   void absolute_top_line_number(int oldFirstChar);
371   int maintaining_absolute_top_line_number() const;
372   void reset_absolute_top_line_number();
373   int position_to_linecol(int pos, int* lineNum, int* column) const;
374   int scroll_(int topLineNum, int horizOffset);
375 
376   void extend_range_for_styles(int* start, int* end);
377 
378   void find_wrap_range(const char *deletedText, int pos, int nInserted,
379                        int nDeleted, int *modRangeStart, int *modRangeEnd,
380                        int *linesInserted, int *linesDeleted);
381   void measure_deleted_lines(int pos, int nDeleted);
382   void wrapped_line_counter(Fl_Text_Buffer *buf, int startPos, int maxPos,
383                             int maxLines, bool startPosIsLineStart,
384                             int styleBufOffset, int *retPos, int *retLines,
385                             int *retLineStart, int *retLineEnd,
386                             bool countLastLineMissingNewLine = true) const;
387   void find_line_end(int pos, bool start_pos_is_line_start, int *lineEnd,
388                      int *nextLineStart) const;
389   double measure_proportional_character(const char *s, int colNum, int pos) const;
390   int wrap_uses_character(int lineEndPos) const;
391 
392   int damage_range1_start, damage_range1_end;
393   int damage_range2_start, damage_range2_end;
394   int mCursorPos;
395   int mCursorOn;
396   int mCursorOldY;              /* Y pos. of cursor for blanking */
397   int mCursorToHint;            /* Tells the buffer modified callback
398                                  where to move the cursor, to reduce
399                                  the number of redraw calls */
400   int mCursorStyle;             /* One of enum cursorStyles above */
401   int mCursorPreferredXPos;     /* Pixel position for vert. cursor movement */
402   int mNVisibleLines;           /* # of visible (displayed) lines */
403   int mNBufferLines;            /* # of newlines in the buffer */
404   Fl_Text_Buffer* mBuffer;      /* Contains text to be displayed */
405   Fl_Text_Buffer* mStyleBuffer; /* Optional parallel buffer containing
406                                  color and font information */
407   int mFirstChar, mLastChar;    /* Buffer positions of first and last
408                                  displayed character (lastChar points
409                                  either to a newline or one character
410                                  beyond the end of the buffer) */
411   int mContinuousWrap;          /* Wrap long lines when displaying */
412   int mWrapMarginPix; 	    	/* Margin in # of pixels for
413                                  wrapping in continuousWrap mode */
414   int* mLineStarts;
415   int mTopLineNum;              /* Line number of top displayed line
416                                  of file (first line of file is 1) */
417   int mAbsTopLineNum;           /* In continuous wrap mode, the line
418                                   number of the top line if the text
419                                   were not wrapped (note that this is
420                                   only maintained as needed). */
421   int mNeedAbsTopLineNum;       /* Externally settable flag to continue
422                                  maintaining absTopLineNum even if
423                                  it isn't needed for line # display */
424   int mHorizOffset;             /* Horizontal scroll pos. in pixels */
425   int mTopLineNumHint;          /* Line number of top displayed line
426                                  of file (first line of file is 1) */
427   int mHorizOffsetHint;         /* Horizontal scroll pos. in pixels */
428   int mNStyles;                 /* Number of entries in styleTable */
429   const Style_Table_Entry *mStyleTable; /* Table of fonts and colors for
430                                          coloring/syntax-highlighting */
431   char mUnfinishedStyle;        /* Style buffer entry which triggers
432                                  on-the-fly reparsing of region */
433   Unfinished_Style_Cb mUnfinishedHighlightCB; /* Callback to parse "unfinished" */
434   /* regions */
435   void* mHighlightCBArg;        /* Arg to unfinishedHighlightCB */
436 
437   int mMaxsize;
438 
439   int mSuppressResync;          /* Suppress resynchronization of line
440                                  starts during buffer updates */
441   int mNLinesDeleted;           /* Number of lines deleted during
442                                  buffer modification (only used
443                                  when resynchronization is suppressed) */
444   int mModifyingTabDistance;    /* Whether tab distance is being
445                                  modified */
446 
447   mutable double mColumnScale; /* Width in pixels of an average character. This
448                                  value is calculated as needed (lazy eval); it
449                                  needs to be mutable so that it can be calculated
450                                  within a method marked as "const" */
451 
452   Fl_Color mCursor_color;
453 
454   Fl_Scrollbar* mHScrollBar;
455   Fl_Scrollbar* mVScrollBar;
456   int scrollbar_width_;
457   Fl_Align scrollbar_align_;
458   int dragPos, dragType, dragging;
459   int display_insert_position_hint;
460   struct { int x, y, w, h; } text_area;
461 
462   int shortcut_;
463 
464   Fl_Font textfont_;
465   Fl_Fontsize textsize_;
466   Fl_Color textcolor_;
467 
468   // The following are not presently used from the original NEdit code,
469   // but are being put here so that future versions of Fl_Text_Display
470   // can implement line numbers without breaking binary compatibility.
471 
472   /* Line number margin and width */
473   int mLineNumLeft, mLineNumWidth;
474 };
475 
476 #endif
477 
478 //
479 // End of "$Id: Fl_Text_Display.H 8306 2011-01-24 17:04:22Z matt $".
480 //
481