2001-08-02 01:24:49 +04:00
|
|
|
//
|
2005-02-25 00:55:12 +03:00
|
|
|
// "$Id$"
|
2001-08-02 01:24:49 +04:00
|
|
|
//
|
|
|
|
// Header file for Fl_Text_Buffer class.
|
|
|
|
//
|
2009-01-01 19:11:32 +03:00
|
|
|
// Copyright 2001-2009 by Bill Spitzak and others.
|
2002-01-01 18:11:33 +03:00
|
|
|
// Original code Copyright Mark Edel. Permission to distribute under
|
|
|
|
// the LGPL for the FLTK library granted by Mark Edel.
|
2001-08-02 01:24:49 +04:00
|
|
|
//
|
|
|
|
// This library is free software; you can redistribute it and/or
|
|
|
|
// modify it under the terms of the GNU Library General Public
|
|
|
|
// License as published by the Free Software Foundation; either
|
|
|
|
// version 2 of the License, or (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This library is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
// Library General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU Library General Public
|
|
|
|
// License along with this library; if not, write to the Free Software
|
|
|
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
|
|
|
// USA.
|
|
|
|
//
|
2005-04-16 04:13:17 +04:00
|
|
|
// Please report all bugs and problems on the following page:
|
|
|
|
//
|
|
|
|
// http://www.fltk.org/str.php
|
2001-08-02 01:24:49 +04:00
|
|
|
//
|
|
|
|
|
2008-10-15 17:46:06 +04:00
|
|
|
/* \file
|
2008-09-16 11:26:22 +04:00
|
|
|
Fl_Text_Buffer, Fl_Text_Selection widget . */
|
|
|
|
|
2001-08-02 01:24:49 +04:00
|
|
|
#ifndef FL_TEXT_BUFFER_H
|
|
|
|
#define FL_TEXT_BUFFER_H
|
|
|
|
|
|
|
|
/* Maximum length in characters of a tab or control character expansion
|
|
|
|
of a single buffer character */
|
|
|
|
#define FL_TEXT_MAX_EXP_CHAR_LEN 20
|
|
|
|
|
2001-08-04 16:21:34 +04:00
|
|
|
#include "Fl_Export.H"
|
2001-08-02 01:24:49 +04:00
|
|
|
|
2008-09-21 05:46:27 +04:00
|
|
|
/** \class Fl_Text_Selection
|
|
|
|
This is an internal class for Fl_Text_Buffer to manage text selections.
|
|
|
|
|
|
|
|
\todo members must be documented
|
|
|
|
*/
|
2001-08-04 16:21:34 +04:00
|
|
|
class FL_EXPORT Fl_Text_Selection {
|
2001-08-02 01:24:49 +04:00
|
|
|
friend class Fl_Text_Buffer;
|
|
|
|
|
|
|
|
public:
|
|
|
|
void set(int start, int end);
|
|
|
|
void set_rectangular(int start, int end, int rectStart, int rectEnd);
|
|
|
|
void update(int pos, int nDeleted, int nInserted);
|
2009-07-04 03:54:34 +04:00
|
|
|
char rectangular() const { return mRectangular; }
|
|
|
|
int start() const { return mStart; }
|
|
|
|
int end() const { return mEnd; }
|
|
|
|
int rect_start() const { return mRectStart; }
|
|
|
|
int rect_end() const { return mRectEnd; }
|
2008-09-15 20:39:05 +04:00
|
|
|
/**
|
|
|
|
Returns a non-zero number if any text has been selected, or 0
|
|
|
|
if no text is selected.
|
|
|
|
*/
|
2009-07-04 03:54:34 +04:00
|
|
|
char selected() const { return mSelected; }
|
2001-08-02 01:24:49 +04:00
|
|
|
void selected(char b) { mSelected = b; }
|
2009-07-04 03:54:34 +04:00
|
|
|
int includes(int pos, int lineStartPos, int dispIndex) const;
|
|
|
|
int position(int* start, int* end) const;
|
|
|
|
int position(int* start, int* end, int* isRect, int* rectStart, int* rectEnd) const;
|
2001-08-02 01:24:49 +04:00
|
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
char mSelected;
|
|
|
|
char mRectangular;
|
|
|
|
int mStart;
|
|
|
|
int mEnd;
|
|
|
|
int mRectStart;
|
|
|
|
int mRectEnd;
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef void (*Fl_Text_Modify_Cb)(int pos, int nInserted, int nDeleted,
|
|
|
|
int nRestyled, const char* deletedText,
|
|
|
|
void* cbArg);
|
2002-09-20 23:59:45 +04:00
|
|
|
typedef void (*Fl_Text_Predelete_Cb)(int pos, int nDeleted, void* cbArg);
|
2001-08-02 01:24:49 +04:00
|
|
|
|
2008-09-15 20:39:05 +04:00
|
|
|
/**
|
|
|
|
The Fl_Text_Buffer class is used by the Fl_Text_Display
|
|
|
|
and Fl_Text_Editor to manage complex text data and is based upon the
|
|
|
|
excellent NEdit text editor engine - see http://www.nedit.org/.
|
|
|
|
*/
|
|
|
|
/**
|
|
|
|
The Fl_Text_Buffer class is used by the
|
|
|
|
Fl_Text_Display
|
|
|
|
and
|
|
|
|
Fl_Text_Editor
|
|
|
|
to manage complex text data and is based upon the
|
|
|
|
excellent NEdit text editor engine - see
|
|
|
|
http://www.nedit.org/.
|
|
|
|
*/
|
2001-08-04 16:21:34 +04:00
|
|
|
class FL_EXPORT Fl_Text_Buffer {
|
2001-08-02 01:24:49 +04:00
|
|
|
public:
|
2009-01-02 00:54:10 +03:00
|
|
|
Fl_Text_Buffer(int requestedSize = 0, int preferredGapSize = 1024);
|
2001-08-02 01:24:49 +04:00
|
|
|
~Fl_Text_Buffer();
|
|
|
|
|
2008-09-15 20:39:05 +04:00
|
|
|
/** Returns the number of characters in the buffer. */
|
2009-07-04 03:54:34 +04:00
|
|
|
int length() const { return mLength; }
|
2009-07-04 03:32:47 +04:00
|
|
|
char* text() const;
|
2001-08-02 01:24:49 +04:00
|
|
|
void text(const char* text);
|
2009-07-04 03:54:34 +04:00
|
|
|
char* text_range(int start, int end) const;
|
|
|
|
char character(int pos) const;
|
2009-07-04 04:06:32 +04:00
|
|
|
char* text_in_rectangle(int start, int end, int rectStart, int rectEnd) const;
|
2001-08-02 01:24:49 +04:00
|
|
|
void insert(int pos, const char* text);
|
2008-09-15 20:39:05 +04:00
|
|
|
/** Appends the text string to the end of the buffer. */
|
2002-08-09 07:17:30 +04:00
|
|
|
void append(const char* t) { insert(length(), t); }
|
2001-08-02 01:24:49 +04:00
|
|
|
void remove(int start, int end);
|
|
|
|
void replace(int start, int end, const char *text);
|
|
|
|
void copy(Fl_Text_Buffer* fromBuf, int fromStart, int fromEnd, int toPos);
|
2002-11-05 22:53:50 +03:00
|
|
|
int undo(int *cp=0);
|
2002-11-13 01:48:36 +03:00
|
|
|
void canUndo(char flag=1);
|
2001-08-02 01:24:49 +04:00
|
|
|
int insertfile(const char *file, int pos, int buflen = 128*1024);
|
2008-09-15 20:39:05 +04:00
|
|
|
/**
|
|
|
|
Appends the named file to the end of the buffer. Returns 0 on
|
|
|
|
success, non-zero on error (strerror() contains reason). 1 indicates
|
|
|
|
open for read failed (no data loaded). 2 indicates error occurred
|
|
|
|
while reading data (data was partially loaded).
|
|
|
|
*/
|
2001-08-02 01:24:49 +04:00
|
|
|
int appendfile(const char *file, int buflen = 128*1024)
|
|
|
|
{ return insertfile(file, length(), buflen); }
|
2008-09-15 20:39:05 +04:00
|
|
|
/** Loads a text file into the buffer */
|
2001-08-02 01:24:49 +04:00
|
|
|
int loadfile(const char *file, int buflen = 128*1024)
|
|
|
|
{ select(0, length()); remove_selection(); return appendfile(file, buflen); }
|
|
|
|
int outputfile(const char *file, int start, int end, int buflen = 128*1024);
|
2008-09-15 20:39:05 +04:00
|
|
|
/** Saves a text file from the current buffer */
|
2001-08-02 01:24:49 +04:00
|
|
|
int savefile(const char *file, int buflen = 128*1024)
|
|
|
|
{ return outputfile(file, 0, length(), buflen); }
|
|
|
|
|
|
|
|
void insert_column(int column, int startPos, const char* text,
|
|
|
|
int* charsInserted, int* charsDeleted);
|
|
|
|
|
|
|
|
void replace_rectangular(int start, int end, int rectStart, int rectEnd,
|
|
|
|
const char* text);
|
|
|
|
|
|
|
|
void overlay_rectangular(int startPos, int rectStart, int rectEnd,
|
|
|
|
const char* text, int* charsInserted,
|
|
|
|
int* charsDeleted);
|
|
|
|
|
|
|
|
void remove_rectangular(int start, int end, int rectStart, int rectEnd);
|
|
|
|
void clear_rectangular(int start, int end, int rectStart, int rectEnd);
|
2008-09-15 20:39:05 +04:00
|
|
|
/** Gets the tab width. */
|
2009-07-04 03:54:34 +04:00
|
|
|
int tab_distance() const { return mTabDist; }
|
2001-08-02 01:24:49 +04:00
|
|
|
void tab_distance(int tabDist);
|
|
|
|
void select(int start, int end);
|
2008-09-15 20:39:05 +04:00
|
|
|
/** Returns a non 0 value if text has been selected, 0 otherwise */
|
2009-07-04 03:54:34 +04:00
|
|
|
int selected() const { return mPrimary.selected(); }
|
2001-08-02 01:24:49 +04:00
|
|
|
void unselect();
|
|
|
|
void select_rectangular(int start, int end, int rectStart, int rectEnd);
|
|
|
|
int selection_position(int* start, int* end);
|
|
|
|
|
|
|
|
int selection_position(int* start, int* end, int* isRect, int* rectStart,
|
|
|
|
int* rectEnd);
|
|
|
|
|
2002-06-09 17:35:49 +04:00
|
|
|
char* selection_text();
|
2001-08-02 01:24:49 +04:00
|
|
|
void remove_selection();
|
|
|
|
void replace_selection(const char* text);
|
|
|
|
void secondary_select(int start, int end);
|
2008-09-15 20:39:05 +04:00
|
|
|
/** Returns a non 0 value if text has been selected in the secondary
|
|
|
|
text selection, 0 otherwise */
|
2008-01-04 23:31:52 +03:00
|
|
|
int secondary_selected() { return mSecondary.selected(); }
|
2008-09-15 20:39:05 +04:00
|
|
|
/** Clears any selection in the secondary text selection object. */
|
2001-08-02 01:24:49 +04:00
|
|
|
void secondary_unselect();
|
|
|
|
|
|
|
|
void secondary_select_rectangular(int start, int end, int rectStart,
|
|
|
|
int rectEnd);
|
|
|
|
|
2008-01-04 23:31:52 +03:00
|
|
|
int secondary_selection_position(int* start, int* end);
|
2001-08-02 01:24:49 +04:00
|
|
|
int secondary_selection_position(int* start, int* end, int* isRect,
|
|
|
|
int* rectStart, int* rectEnd);
|
|
|
|
|
2002-06-09 17:35:49 +04:00
|
|
|
char* secondary_selection_text();
|
2001-08-02 01:24:49 +04:00
|
|
|
void remove_secondary_selection();
|
|
|
|
void replace_secondary_selection(const char* text);
|
|
|
|
void highlight(int start, int end);
|
2008-09-15 20:39:05 +04:00
|
|
|
/**
|
|
|
|
Returns the highlighted text. When you are done with the
|
|
|
|
text, free it using the free() function.
|
|
|
|
*/
|
2008-01-04 23:31:52 +03:00
|
|
|
int highlight() { return mHighlight.selected(); }
|
2001-08-02 01:24:49 +04:00
|
|
|
void unhighlight();
|
|
|
|
void highlight_rectangular(int start, int end, int rectStart, int rectEnd);
|
|
|
|
|
2008-01-04 23:31:52 +03:00
|
|
|
int highlight_position(int* start, int* end);
|
2001-08-02 01:24:49 +04:00
|
|
|
int highlight_position(int* start, int* end, int* isRect, int* rectStart,
|
|
|
|
int* rectEnd);
|
|
|
|
|
2002-06-09 17:35:49 +04:00
|
|
|
char* highlight_text();
|
2001-08-02 01:24:49 +04:00
|
|
|
void add_modify_callback(Fl_Text_Modify_Cb bufModifiedCB, void* cbArg);
|
|
|
|
void remove_modify_callback(Fl_Text_Modify_Cb bufModifiedCB, void* cbArg);
|
|
|
|
|
2008-09-15 20:39:05 +04:00
|
|
|
/**
|
|
|
|
Calls all modify callbacks that have been registered using
|
|
|
|
the add_modify_callback()
|
|
|
|
method.
|
|
|
|
*/
|
2001-08-02 01:24:49 +04:00
|
|
|
void call_modify_callbacks() { call_modify_callbacks(0, 0, 0, 0, 0); }
|
|
|
|
|
2002-09-20 23:59:45 +04:00
|
|
|
void add_predelete_callback(Fl_Text_Predelete_Cb bufPredelCB, void* cbArg);
|
|
|
|
void remove_predelete_callback(Fl_Text_Predelete_Cb predelCB, void* cbArg);
|
|
|
|
|
2008-09-15 20:39:05 +04:00
|
|
|
/**
|
|
|
|
Calls the stored pre-delete callback procedure(s) for this buffer to update
|
|
|
|
the changed area(s) on the screen and any other listeners.
|
|
|
|
*/
|
|
|
|
void call_predelete_callbacks() { call_predelete_callbacks(0, 0); }
|
2002-09-20 23:59:45 +04:00
|
|
|
|
2009-07-04 04:06:32 +04:00
|
|
|
char* line_text(int pos) const;
|
|
|
|
int line_start(int pos) const;
|
|
|
|
int line_end(int pos) const;
|
|
|
|
int word_start(int pos) const;
|
|
|
|
int word_end(int pos) const;
|
|
|
|
int expand_character(int pos, int indent, char *outStr) const;
|
2001-08-02 01:24:49 +04:00
|
|
|
|
|
|
|
static int expand_character(char c, int indent, char* outStr, int tabDist,
|
|
|
|
char nullSubsChar);
|
|
|
|
|
|
|
|
static int character_width(char c, int indent, int tabDist, char nullSubsChar);
|
2009-07-04 04:06:32 +04:00
|
|
|
int count_displayed_characters(int lineStartPos, int targetPos) const;
|
2001-08-02 01:24:49 +04:00
|
|
|
int skip_displayed_characters(int lineStartPos, int nChars);
|
2009-07-04 04:06:32 +04:00
|
|
|
int count_lines(int startPos, int endPos) const;
|
2001-08-02 01:24:49 +04:00
|
|
|
int skip_lines(int startPos, int nLines);
|
|
|
|
int rewind_lines(int startPos, int nLines);
|
2009-07-04 03:54:34 +04:00
|
|
|
int findchar_forward(int startPos, char searchChar, int* foundPos) const;
|
|
|
|
int findchar_backward(int startPos, char searchChar, int* foundPos) const;
|
|
|
|
int findchars_forward(int startPos, const char* searchChars, int* foundPos) const;
|
|
|
|
int findchars_backward(int startPos, const char* searchChars, int* foundPos) const;
|
2001-08-02 01:24:49 +04:00
|
|
|
|
|
|
|
int search_forward(int startPos, const char* searchString, int* foundPos,
|
2009-07-04 03:54:34 +04:00
|
|
|
int matchCase = 0) const;
|
2001-08-02 01:24:49 +04:00
|
|
|
|
|
|
|
int search_backward(int startPos, const char* searchString, int* foundPos,
|
2009-07-04 03:54:34 +04:00
|
|
|
int matchCase = 0) const;
|
2001-08-02 01:24:49 +04:00
|
|
|
|
|
|
|
int substitute_null_characters(char* string, int length);
|
|
|
|
void unsubstitute_null_characters(char* string);
|
2008-09-15 20:39:05 +04:00
|
|
|
/** Returns the current nul substitution character. */
|
2009-07-04 04:06:32 +04:00
|
|
|
char null_substitution_character() const { return mNullSubsChar; }
|
2008-09-15 20:39:05 +04:00
|
|
|
/** Returns the primary selection. */
|
2009-07-04 04:24:26 +04:00
|
|
|
const Fl_Text_Selection* primary_selection() const { return &mPrimary; }
|
|
|
|
/** Returns the primary selection. */
|
2001-08-02 01:24:49 +04:00
|
|
|
Fl_Text_Selection* primary_selection() { return &mPrimary; }
|
2008-09-15 20:39:05 +04:00
|
|
|
/** Returns the secondary selection. */
|
2009-07-04 04:24:26 +04:00
|
|
|
const Fl_Text_Selection* secondary_selection() const { return &mSecondary; }
|
2008-09-15 20:39:05 +04:00
|
|
|
/** Returns the current highlight selection. */
|
2009-07-04 04:24:26 +04:00
|
|
|
const Fl_Text_Selection* highlight_selection() const { return &mHighlight; }
|
2001-08-02 01:24:49 +04:00
|
|
|
|
|
|
|
protected:
|
|
|
|
void call_modify_callbacks(int pos, int nDeleted, int nInserted,
|
2009-07-04 04:06:32 +04:00
|
|
|
int nRestyled, const char* deletedText) const;
|
|
|
|
void call_predelete_callbacks(int pos, int nDeleted) const;
|
2001-08-02 01:24:49 +04:00
|
|
|
|
|
|
|
int insert_(int pos, const char* text);
|
|
|
|
void remove_(int start, int end);
|
|
|
|
|
|
|
|
void remove_rectangular_(int start, int end, int rectStart, int rectEnd,
|
|
|
|
int* replaceLen, int* endPos);
|
|
|
|
|
|
|
|
void insert_column_(int column, int startPos, const char* insText,
|
|
|
|
int* nDeleted, int* nInserted, int* endPos);
|
|
|
|
|
|
|
|
void overlay_rectangular_(int startPos, int rectStart, int rectEnd,
|
|
|
|
const char* insText, int* nDeleted,
|
|
|
|
int* nInserted, int* endPos);
|
|
|
|
|
|
|
|
void redisplay_selection(Fl_Text_Selection* oldSelection,
|
2009-07-04 04:06:32 +04:00
|
|
|
Fl_Text_Selection* newSelection) const;
|
2001-08-02 01:24:49 +04:00
|
|
|
|
|
|
|
void move_gap(int pos);
|
|
|
|
void reallocate_with_gap(int newGapStart, int newGapLen);
|
2009-07-04 04:06:32 +04:00
|
|
|
char* selection_text_(Fl_Text_Selection* sel) const;
|
2001-08-02 01:24:49 +04:00
|
|
|
void remove_selection_(Fl_Text_Selection* sel);
|
|
|
|
void replace_selection_(Fl_Text_Selection* sel, const char* text);
|
|
|
|
|
|
|
|
void rectangular_selection_boundaries(int lineStartPos, int rectStart,
|
|
|
|
int rectEnd, int* selStart,
|
2009-07-04 04:06:32 +04:00
|
|
|
int* selEnd) const;
|
2001-08-02 01:24:49 +04:00
|
|
|
|
|
|
|
void update_selections(int pos, int nDeleted, int nInserted);
|
|
|
|
|
2008-09-18 23:09:34 +04:00
|
|
|
Fl_Text_Selection mPrimary; /**< highlighted areas */
|
|
|
|
Fl_Text_Selection mSecondary; /**< highlighted areas */
|
|
|
|
Fl_Text_Selection mHighlight; /**< highlighted areas */
|
|
|
|
int mLength; /**< length of the text in the buffer (the length
|
2001-08-02 01:24:49 +04:00
|
|
|
of the buffer itself must be calculated:
|
|
|
|
gapEnd - gapStart + length) */
|
2008-09-18 23:09:34 +04:00
|
|
|
char* mBuf; /**< allocated memory where the text is stored */
|
|
|
|
int mGapStart; /**< points to the first character of the gap */
|
|
|
|
int mGapEnd; /**< points to the first char after the gap */
|
2001-08-02 01:24:49 +04:00
|
|
|
// The hardware tab distance used by all displays for this buffer,
|
|
|
|
// and used in computing offsets for rectangular selection operations.
|
2008-09-18 23:09:34 +04:00
|
|
|
int mTabDist; /**< equiv. number of characters in a tab */
|
|
|
|
int mUseTabs; /**< True if buffer routines are allowed to use
|
2001-08-02 01:24:49 +04:00
|
|
|
tabs for padding in rectangular operations */
|
2008-09-18 23:09:34 +04:00
|
|
|
int mNModifyProcs; /**< number of modify-redisplay procs attached */
|
|
|
|
Fl_Text_Modify_Cb* /**< procedures to call when buffer is */
|
2009-07-04 03:32:47 +04:00
|
|
|
mModifyProcs; /**< modified to redisplay contents */
|
2008-09-18 23:09:34 +04:00
|
|
|
void** mCbArgs; /**< caller arguments for modifyProcs above */
|
|
|
|
int mNPredeleteProcs; /**< number of pre-delete procs attached */
|
|
|
|
Fl_Text_Predelete_Cb* /**< procedure to call before text is deleted */
|
|
|
|
mPredeleteProcs; /**< from the buffer; at most one is supported. */
|
|
|
|
void **mPredeleteCbArgs; /**< caller argument for pre-delete proc above */
|
|
|
|
int mCursorPosHint; /**< hint for reasonable cursor position after
|
2001-08-02 01:24:49 +04:00
|
|
|
a buffer modification operation */
|
2008-09-18 23:09:34 +04:00
|
|
|
char mNullSubsChar; /**< NEdit is based on C null-terminated strings,
|
2001-08-02 01:24:49 +04:00
|
|
|
so ascii-nul characters must be substituted
|
|
|
|
with something else. This is the else, but
|
|
|
|
of course, things get quite messy when you
|
|
|
|
use it */
|
2008-09-18 23:09:34 +04:00
|
|
|
char mCanUndo; /**< if this buffer is used for attributes, it must
|
2002-11-13 01:48:36 +03:00
|
|
|
not do any undo calls */
|
2009-01-02 00:54:10 +03:00
|
|
|
int mPreferredGapSize; /**< the default allocation for the text gap is 1024
|
|
|
|
bytes and should only be increased if frequent
|
|
|
|
and large changes in buffer size are expected */
|
2001-08-02 01:24:49 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
//
|
2005-02-25 00:55:12 +03:00
|
|
|
// End of "$Id$".
|
2001-08-02 01:24:49 +04:00
|
|
|
//
|