DRC | 2ff39b8 | 2011-07-28 08:38:59 +0000 | [diff] [blame] | 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 | */ |
| 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 | */ |
| 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 | */ |
| 118 | bool selected() const { return mSelected; } |
| 119 | |
| 120 | /** |
| 121 | \brief Modify the 'selected' flag. |
| 122 | \param b new flag |
| 123 | */ |
| 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 | */ |
| 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 | */ |
| 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 | */ |
| 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 | */ |
| 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 | */ |
| 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 | */ |
| 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 | */ |
| 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 | */ |
| 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 | */ |
| 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 | */ |
| 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 | */ |
| 624 | const Fl_Text_Selection* primary_selection() const { return &mPrimary; } |
| 625 | |
| 626 | /** |
| 627 | Returns the primary selection. |
| 628 | */ |
| 629 | Fl_Text_Selection* primary_selection() { return &mPrimary; } |
| 630 | |
| 631 | /** |
| 632 | Returns the secondary selection. |
| 633 | */ |
| 634 | const Fl_Text_Selection* secondary_selection() const { return &mSecondary; } |
| 635 | |
| 636 | /** |
| 637 | Returns the current highlight selection. |
| 638 | */ |
| 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 | // |