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