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