fltk-1.4 mods

This commit is contained in:
dave-w1hkj 2023-05-18 23:52:34 -05:00
parent 49db4300dd
commit 3fc1ac5ae5
23 changed files with 7749 additions and 14770 deletions

View file

@ -338,22 +338,10 @@ EXTRA_DIST += \
include/wx_strings.h \
include/xml_io.h \
widgets/missing_strings.c \
widgets/Fl_Text_Buffer_mod_1_1.cxx \
widgets/Fl_Text_Buffer_mod_1_3.cxx \
widgets/Fl_Text_Display_mod_1_1.cxx \
widgets/Fl_Text_Display_mod_1_3.cxx \
widgets/Fl_Text_Editor_mod_1_1.cxx \
widgets/Fl_Text_Editor_mod_1_3.cxx \
include/Fl_Text_Buffer_mod.H \
include/Fl_Text_Buffer_mod_1_1.H \
include/Fl_Text_Buffer_mod_1_3.H \
include/Fl_Text_Display_mod.H \
include/Fl_Text_Display_mod_1_1.H \
include/Fl_Text_Display_mod_1_3.H \
include/Fl_Text_Editor_mod.H \
include/Fl_Text_Editor_mod_1_1.H \
include/Fl_Text_Editor_mod_1_3.H \
include/FTextView.h \
include/Fl_Text_Buffer_mod.H \
include/Fl_Text_Display_mod.H \
include/Fl_Text_Editor_mod.H \
include/blank.h \
include/csv.h \
include/missing_strings.h \

View file

@ -4,24 +4,21 @@
// Copyright (C) 2007-2009
// Stelios Bounanos, M0GLD
//
// ----------------------------------------------------------------------------
// Copyright (C) 2014
// David Freese, W1HKJ
// This file is part of FLAMP.
//
// This file is part of flmsg
//
// flrig is free software; you can redistribute it and/or modify
// This is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// flrig is distributed in the hope that it will be useful,
// This software 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
#ifndef FTextView_H_
@ -46,8 +43,8 @@ public:
// CLICK_START: same as first clickable style
// NATTR: number of styles (last style + 1)
enum TEXT_ATTR { RECV, XMIT, CTRL, SKIP, ALTR,
CLICK_START, QSY = CLICK_START, /* FOO, BAR, ..., */
NATTR };
CLICK_START, QSY = CLICK_START, /* FOO, BAR, ..., */
NATTR };
FTextBase(int x, int y, int w, int h, const char *l = 0);
virtual ~FTextBase() { delete tbuf; delete sbuf; }
@ -80,7 +77,7 @@ public:
protected:
void set_style(int attr, Fl_Font f, int s, Fl_Color c,
int set = SET_FONT | SET_SIZE | SET_COLOR);
int set = SET_FONT | SET_SIZE | SET_COLOR);
int readFile(const char* fn = 0);
void saveFile(void);
char* get_word(int x, int y, const char* nwchars = "", bool ontext = true);
@ -109,7 +106,7 @@ protected:
int max_lines;
bool scroll_hint;
bool restore_wrap;
// bool wrap_restore;
// bool wrap_restore;
private:
int oldw, oldh, olds;
@ -123,7 +120,7 @@ class FTextView : public FTextBase
{
public:
FTextView(int x, int y, int w, int h, const char *l = 0);
~FTextView() { }
~FTextView() { }
virtual int handle(int event);
@ -136,7 +133,7 @@ protected:
virtual void handle_context_menu(void);
virtual void menu_cb(size_t item);
static void changed_cb(int pos, int nins, int ndel, int nsty,
const char *dtext, void *arg);
const char *dtext, void *arg);
void change_keybindings(void);
private:
@ -171,7 +168,7 @@ protected:
virtual void handle_context_menu(void);
virtual void menu_cb(size_t item);
static void changed_cb(int pos, int nins, int ndel, int nsty,
const char *dtext, void *arg);
const char *dtext, void *arg);
private:
FTextEdit();

View file

@ -1,27 +1,788 @@
// ----------------------------------------------------------------------------
// Copyright (C) 2014
// David Freese, W1HKJ
//
// This file is part of flmsg
// "$Id: Fl_Text_Buffer_mod.H 8148 2010-12-31 22:38:03Z matt $"
//
// flrig is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
// Header file for Fl_Text_Buffer_mod class.
//
// flrig is distributed in the hope that it will be useful,
// Copyright 2001-2010 by Bill Spitzak and others.
// Original code Copyright Mark Edel. Permission to distribute under
// the LGPL for the FLTK library granted by Mark Edel.
//
// 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 General Public License for more details.
// 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 General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
// 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.
// 51 Franklin Street, Fifth Floor
// Boston, MA 02110-1301 USA.
//
// Please report all bugs and problems on the following page:
//
// http://www.fltk.org/str.php
//
/* \file
Fl_Text_Buffer_mod, Fl_Text_Selection_mod widget . */
#ifndef Fl_Text_Buffer_mod_H
#define Fl_Text_Buffer_mod_H
#include <config.h>
#if FLMSG_FLTK_API_MINOR < 3
# include "Fl_Text_Buffer_mod_1_1.H"
#undef ASSERT_UTF8
#ifdef ASSERT_UTF8
# include <assert.h>
# define IS_UTF8_ALIGNED(a) if (a && *a) assert(fl_utf8len(*(a))>0);
# define IS_UTF8_ALIGNED2(a, b) if (b>=0 && b<a->length()) assert(fl_utf8len(a->byte_at(b))>0);
#else
# include "Fl_Text_Buffer_mod_1_3.H"
# define IS_UTF8_ALIGNED(a)
# define IS_UTF8_ALIGNED2(a, b)
#endif
/*
"character size" is the size of a UTF-8 character in bytes
"character width" is the width of a Unicode character in pixels
"column" was orginally defined as a character offset from the left margin.
It was identical to the byte offset. In UTF-8, we have neither a byte offset
nor truly fixed width fonts (*). Column could be a pixel value multiplied with
an average character width (which is a bearable approximation).
* in Unicode, there are no fixed width fonts! Even if the ASCII characters may
happen to be all the same width in pixels, chinese charcaters surely are not.
There are plenty of exceptions, like ligatures, that make special handling of
"fixed" character widths a nightmare. I decided to remove all references to
fixed fonts and see "columns" as a multiple of the average width of a
character in the main font.
- Matthias
*/
/* Maximum length in characters of a tab or control character expansion
of a single buffer character */
#define FL_TEXT_MAX_EXP_CHAR_LEN 20
#include <FL/Fl_Export.H>
/**
\class Fl_Text_Selection_mod
\brief This is an internal class for Fl_Text_Buffer_mod to manage text selections.
This class works correctly with utf-8 strings assuming that the parameters
for all calls are on character boundaries.
*/
class FL_EXPORT Fl_Text_Selection_mod {
friend class Fl_Text_Buffer_mod;
public:
/**
\brief Set the selection range.
\param start byte offset to first selected character
\param end byte offset pointing after last selected character
*/
void set(int start, int end);
/**
\brief Updates a selection afer text was modified.
Updates an individual selection for changes in the corresponding text
\param pos byte offset into text buffer at which the change occured
\param nDeleted number of bytes deleted from the buffer
\param nInserted number of bytes inserted into the buffer
*/
void update(int pos, int nDeleted, int nInserted);
/**
\brief Return the byte offset to the first selected character.
\return byte offset
*/
int start() const { return mStart; }
/**
\brief Return the byte ofsset to the character after the last selected character.
\return byte offset
*/
int end() const { return mEnd; }
/**
\brief Returns true if any text is selected.
\return a non-zero number if any text has been selected, or 0
if no text is selected.
*/
bool selected() const { return mSelected; }
/**
\brief Modify the 'selected' flag.
\param b new flag
*/
void selected(bool b) { mSelected = b; }
/**
Return true if position \p pos with indentation \p dispIndex is in
the Fl_Text_Selection_mod.
*/
int includes(int pos) const;
/**
\brief Return the positions of this selection.
\param start retrun byte offset to first selected character
\param end retrun byte offset pointing after last selected character
\return true if selected
*/
int position(int* start, int* end) const;
protected:
int mStart; ///< byte offset to the first selected character
int mEnd; ///< byte offset to the character after the last selected character
bool mSelected; ///< this flag is set if any text is selected
};
typedef void (*Fl_Text_Modify_Cb)(int pos, int nInserted, int nDeleted,
int nRestyled, const char* deletedText,
void* cbArg);
typedef void (*Fl_Text_Predelete_Cb)(int pos, int nDeleted, void* cbArg);
/**
\brief This class manages unicode displayed in one or more Fl_Text_Display_mod widgets.
All text in Fl_Text_Buffer_modmust be encoded in UTF-8. All indices used in the
function calls must be aligned to the start of a UTF-8 sequence. All indices
and pointers returned will be aligned. All functions that return a single
character will return that in an unsiged int in UCS-4 encoding.
The Fl_Text_Buffer_mod class is used by the Fl_Text_Display_mod
and Fl_Text_Editor_mod to manage complex text data and is based upon the
excellent NEdit text editor engine - see http://www.nedit.org/.
*/
class FL_EXPORT Fl_Text_Buffer_mod {
public:
/**
Create an empty text buffer of a pre-determined size.
\param requestedSize use this to avoid unnecessary re-allocation
if you know exactly how much the buffer will need to hold
\param preferredGapSize Initial size for the buffer gap (empty space
in the buffer where text might be inserted
if the user is typing sequential chars)
*/
Fl_Text_Buffer_mod(int requestedSize = 0, int preferredGapSize = 1024);
/**
Frees a text buffer
*/
~Fl_Text_Buffer_mod();
/**
\brief Returns the number of bytes in the buffer.
\return size of text in bytes
*/
int length() const { return mLength; }
/**
\brief Get a copy of the entire contents of the text buffer.
Memory is allocated to contain the returned string, which the caller
must free.
\return newly allocated text buffer - must be free'd, text is utf8
*/
char* text() const;
/**
Replaces the entire contents of the text buffer.
\param text Text must be valid utf8.
*/
void text(const char* text);
/**
\brief Get a copy of a part of the text buffer.
Return a copy of the text between \p start and \p end character positions
from text buffer \p buf. Positions start at 0, and the range does not
include the character pointed to by \p end.
When you are done with the text, free it using the free() function.
\param start byte offset to first character
\param end byte offset after last character in range
\return newly allocated text buffer - must be free'd, text is utf8
*/
char* text_range(int start, int end) const;
/**
Returns the character at the specified position pos in the buffer.
Positions start at 0
\param pos byte offset into buffer, pos must be at acharacter boundary
\return Unicode UCS-4 encoded character
*/
unsigned int char_at(int pos) const;
/**
Returns the raw byte at the specified position pos in the buffer.
Positions start at 0
\param pos byte offset into buffer
\return unencoded raw byte
*/
char byte_at(int pos) const;
/**
Convert a byte offset in buffer into a memory address.
\param pos byte offset into buffer
\return byte offset converted to a memory address
*/
const char *address(int pos) const
{ return (pos < mGapStart) ? mBuf+pos : mBuf+pos+mGapEnd-mGapStart; }
/**
Convert a byte offset in buffer into a memory address.
\param pos byte offset into buffer
\return byte offset converted to a memory address
*/
char *address(int pos)
{ return (pos < mGapStart) ? mBuf+pos : mBuf+pos+mGapEnd-mGapStart; }
/**
Inserts null-terminated string \p text at position \p pos.
\param pos insertion position as byte offset (must be utf-8 character aligned)
\param text utf-8 encoded and nul terminated text
*/
void insert(int pos, const char* text);
/**
Appends the text string to the end of the buffer.
\param t utf-8 encoded and nul terminated text
*/
void append(const char* t) { insert(length(), t); }
/**
Deletes a range of characters in the buffer.
\param start byte offset to first character to be removed
\param end byte offset to charcatre after last character to be removed
*/
void remove(int start, int end);
/**
Deletes the characters between \p start and \p end, and inserts the null-terminated string \p text in their place in the buffer.
\param start byte offset to first character to be removed and new insert position
\param end byte offset to charcatre after last character to be removed
\param text utf-8 encoded and nul terminated text
*/
void replace(int start, int end, const char *text);
/**
Copies text from one buffer to this one.
\param fromBuf source text buffer may be the same as this
\param fromStart byte offset into buffer
\param fromEnd byte offset into buffer
\param toPos destination byte offset into buffer
*/
void copy(Fl_Text_Buffer_mod* fromBuf, int fromStart, int fromEnd, int toPos);
/**
Undo text modification according to the undo variables or insert text
from the undo buffer
*/
int undo(int *cp=0);
/**
Lets the undo system know if we can undo changes
*/
void canUndo(char flag=1);
/**
Inserts a file at the specified position. 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).
File can be UTF-8 or CP1252-encoded.
If the input file is not UTF-8-encoded, the Fl_Text_Buffer_mod widget will contain
UTF-8-transcoded data. By default, the message Fl_Text_Buffer_mod::file_encoding_warning_message
will warn the user about this.
\see input_file_was_transcoded and transcoding_warning_action.
*/
int insertfile(const char *file, int pos, int buflen = 128*1024);
/**
Appends the named file to the end of the buffer. See also insertfile().
*/
int appendfile(const char *file, int buflen = 128*1024)
{ return insertfile(file, length(), buflen); }
/**
Loads a text file into the buffer. See also insertfile().
*/
int loadfile(const char *file, int buflen = 128*1024)
{ select(0, length()); remove_selection(); return appendfile(file, buflen); }
/**
Writes the specified portions of the file to a file. Returns 0 on success, non-zero
on error (strerror() contains reason). 1 indicates open for write failed
(no data saved). 2 indicates error occurred while writing data
(data was partially saved).
*/
int outputfile(const char *file, int start, int end, int buflen = 128*1024);
/**
Saves a text file from the current buffer
*/
int savefile(const char *file, int buflen = 128*1024)
{ return outputfile(file, 0, length(), buflen); }
/**
Gets the tab width.
*/
int tab_distance() const { return mTabDist; }
/**
Set the hardware tab distance (width) used by all displays for this buffer,
and used in computing offsets for rectangular selection operations.
*/
void tab_distance(int tabDist);
/**
Selects a range of characters in the buffer.
*/
void select(int start, int end);
/**
Returns a non 0 value if text has been selected, 0 otherwise
*/
int selected() const { return mPrimary.selected(); }
/**
Cancels any previous selection on the primary text selection object
*/
void unselect();
/**
Gets the selection position
*/
int selection_position(int* start, int* end);
/**
Returns the currently selected text. When you are done with
the text, free it using the free() function.
*/
char* selection_text();
/**
Removes the text in the primary selection.
*/
void remove_selection();
/**
Replaces the text in the primary selection.
*/
void replace_selection(const char* text);
/**
Selects a range of characters in the secondary selection.
*/
void secondary_select(int start, int end);
/**
Returns a non 0 value if text has been selected in the secondary
text selection, 0 otherwise
*/
int secondary_selected() { return mSecondary.selected(); }
/**
Clears any selection in the secondary text selection object.
*/
void secondary_unselect();
/**
Returns the current selection in the secondary text selection object.
*/
int secondary_selection_position(int* start, int* end);
/**
Returns the text in the secondary selection. When you are
done with the text, free it using the free() function.
*/
char* secondary_selection_text();
/**
Removes the text from the buffer corresponding to the secondary text selection object.
*/
void remove_secondary_selection();
/**
Replaces the text from the buffer corresponding to the secondary
text selection object with the new string \p text.
*/
void replace_secondary_selection(const char* text);
/**
Highlights the specified text within the buffer.
*/
void highlight(int start, int end);
/**
Returns the highlighted text. When you are done with the
text, free it using the free() function.
*/
int highlight() { return mHighlight.selected(); }
/**
Unhighlights text in the buffer.
*/
void unhighlight();
/**
Highlights the specified text between \p start and \p end within the buffer.
*/
int highlight_position(int* start, int* end);
/**
Returns the highlighted text. When you are done with the
text, free it using the free() function.
*/
char* highlight_text();
/**
Adds a callback function that is called whenever the text buffer is
modified. The callback function is declared as follows:
\code
typedef void (*Fl_Text_Modify_Cb)(int pos, int nInserted, int nDeleted,
int nRestyled, const char* deletedText,
void* cbArg);
\endcode
*/
void add_modify_callback(Fl_Text_Modify_Cb bufModifiedCB, void* cbArg);
/**
Removes a modify callback.
*/
void remove_modify_callback(Fl_Text_Modify_Cb bufModifiedCB, void* cbArg);
/**
Calls all modify callbacks that have been registered using
the add_modify_callback()
method.
*/
void call_modify_callbacks() { call_modify_callbacks(0, 0, 0, 0, 0); }
/**
Adds a callback routine to be called before text is deleted from the buffer.
*/
void add_predelete_callback(Fl_Text_Predelete_Cb bufPredelCB, void* cbArg);
/**
Removes a callback routine \p bufPreDeleteCB associated with argument \p cbArg
to be called before text is deleted from the buffer.
*/
void remove_predelete_callback(Fl_Text_Predelete_Cb predelCB, void* cbArg);
/**
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); }
/**
Returns the text from the entire line containing the specified
character position. When you are done with the text, free it
using the free() function.
\param pos byte index into buffer
\return copy of utf8 text, must be free'd
*/
char* line_text(int pos) const;
/**
Returns the position of the start of the line containing position \p pos.
\param pos byte index into buffer
\return byte offset to line start
*/
int line_start(int pos) const;
/**
Finds and returns the position of the end of the line containing position \p pos
(which is either a pointer to the newline character ending the line,
or a pointer to one character beyond the end of the buffer)
\param pos byte index into buffer
\return byte offset to line end
*/
int line_end(int pos) const;
/**
Returns the position corresponding to the start of the word
\param pos byte index into buffer
\return byte offset to word start
*/
int word_start(int pos) const;
/**
Returns the position corresponding to the end of the word.
\param pos byte index into buffer
\return byte offset to word end
*/
int word_end(int pos) const;
/**
Count the number of displayed characters between buffer position
\p lineStartPos and \p targetPos. (displayed characters are the characters
shown on the screen to represent characters in the buffer, where tabs and
control characters are expanded)
*/
int count_displayed_characters(int lineStartPos, int targetPos) const;
/**
Count forward from buffer position \p startPos in displayed characters
(displayed characters are the characters shown on the screen to represent
characters in the buffer, where tabs and control characters are expanded)
\param lineStartPos byte offset into buffer
\param nChars number of bytes that are sent to the display
\return byte offset in input after all output bytes are sent
*/
int skip_displayed_characters(int lineStartPos, int nChars);
/**
Counts the number of newlines between \p startPos and \p endPos in buffer.
The character at position \p endPos is not counted.
*/
int count_lines(int startPos, int endPos) const;
/**
Finds the first character of the line \p nLines forward from \p startPos
in the buffer and returns its position
*/
int skip_lines(int startPos, int nLines);
/**
Finds and returns the position of the first character of the line \p nLines backwards
from \p startPos (not counting the character pointed to by \p startpos if
that is a newline) in the buffer. \p nLines == 0 means find the beginning of the line
*/
int rewind_lines(int startPos, int nLines);
/**
Finds the next occurrence of the specified character.
Search forwards in buffer for character \p searchChar, starting
with the character \p startPos, and returning the result in \p foundPos
returns 1 if found, 0 if not. (The difference between this and
BufSearchForward is that it's optimized for single characters. The
overall performance of the text widget is dependent on its ability to
count lines quickly, hence searching for a single character: newline)
\param startPos byte offset to start position
\param searchChar UCS-4 character that we want to find
\param foundPos byte offset where the character was found
\return 1 if found, 0 if not
*/
int findchar_forward(int startPos, unsigned searchChar, int* foundPos) const;
/**
Search backwards in buffer \p buf for character \p searchChar, starting
with the character BEFORE \p startPos, returning the result in \p foundPos
returns 1 if found, 0 if not. (The difference between this and
BufSearchBackward is that it's optimized for single characters. The
overall performance of the text widget is dependent on its ability to
count lines quickly, hence searching for a single character: newline)
\param startPos byte offset to start position
\param searchChar UCS-4 character that we want to find
\param foundPos byte offset where the character was found
\return 1 if found, 0 if not
*/
int findchar_backward(int startPos, unsigned int searchChar, int* foundPos) const;
/**
Search forwards in buffer for string \p searchString, starting with the
character \p startPos, and returning the result in \p foundPos
returns 1 if found, 0 if not.
\param startPos byte offset to start position
\param searchString utf8 string that we want to find
\param foundPos byte offset where the string was found
\param matchCase if set, match character case
\return 1 if found, 0 if not
*/
int search_forward(int startPos, const char* searchString, int* foundPos,
int matchCase = 0) const;
/**
Search backwards in buffer for string <i>searchCharssearchString</i>, starting with the
character BEFORE \p startPos, returning the result in \p foundPos
returns 1 if found, 0 if not.
\param startPos byte offset to start position
\param searchString utf8 string that we want to find
\param foundPos byte offset where the string was found
\param matchCase if set, match character case
\return 1 if found, 0 if not
*/
int search_backward(int startPos, const char* searchString, int* foundPos,
int matchCase = 0) const;
int findchars_forward(int startPos, const char* searchChars, int* foundPos);
int findchars_backward(int startPos, const char* searchChars, int* foundPos);
/**
Returns the primary selection.
*/
const Fl_Text_Selection_mod* primary_selection() const { return &mPrimary; }
/**
Returns the primary selection.
*/
Fl_Text_Selection_mod* primary_selection() { return &mPrimary; }
/**
Returns the secondary selection.
*/
const Fl_Text_Selection_mod* secondary_selection() const { return &mSecondary; }
/**
Returns the current highlight selection.
*/
const Fl_Text_Selection_mod* highlight_selection() const { return &mHighlight; }
/**
Returns the index of the previous character.
\param ix index to the current char
*/
int prev_char(int ix) const;
int prev_char_clipped(int ix) const;
/**
Returns the index of the next character.
\param ix index to the current char
*/
int next_char(int ix) const;
int next_char_clipped(int ix) const;
/**
Align an index into the buffer to the current or previous utf8 boundary.
*/
int utf8_align(int) const;
/**
\brief true iff the loaded file has been transcoded to UTF-8
*/
int input_file_was_transcoded;
/** This message may be displayed using the fl_alert() function when a file
which was not UTF-8 encoded is input.
*/
static const char* file_encoding_warning_message;
/**
\brief Pointer to a function called after reading a non UTF-8 encoded file.
This function is called after reading a file if the file content
was transcoded to UTF-8. Its default implementation calls fl_alert()
with the text of \ref file_encoding_warning_message. No warning message is
displayed if this pointer is set to NULL. Use \ref input_file_was_transcoded
to be informed if file input required transcoding to UTF-8.
*/
void (*transcoding_warning_action)(Fl_Text_Buffer_mod*);
protected:
/**
Calls the stored modify callback procedure(s) for this buffer to update the
changed area(s) on the screen and any other listeners.
*/
void call_modify_callbacks(int pos, int nDeleted, int nInserted,
int nRestyled, const char* deletedText) const;
/**
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(int pos, int nDeleted) const;
/**
Internal (non-redisplaying) version of BufInsert. Returns the length of
text inserted (this is just strlen(\p text), however this calculation can be
expensive and the length will be required by any caller who will continue
on to call redisplay). \p pos must be contiguous with the existing text in
the buffer (i.e. not past the end).
\return the number of bytes inserted
*/
int insert_(int pos, const char* text);
/**
Internal (non-redisplaying) version of BufRemove. Removes the contents
of the buffer between start and end (and moves the gap to the site of
the delete).
*/
void remove_(int start, int end);
/**
Calls the stored redisplay procedure(s) for this buffer to update the
screen for a change in a selection.
*/
void redisplay_selection(Fl_Text_Selection_mod* oldSelection,
Fl_Text_Selection_mod* newSelection) const;
/**
Move the gap to start at a new position.
*/
void move_gap(int pos);
/**
Reallocates the text storage in the buffer to have a gap starting at \p newGapStart
and a gap size of \p newGapLen, preserving the buffer's current contents.
*/
void reallocate_with_gap(int newGapStart, int newGapLen);
char* selection_text_(Fl_Text_Selection_mod* sel) const;
/**
Removes the text from the buffer corresponding to \p sel.
*/
void remove_selection_(Fl_Text_Selection_mod* sel);
/**
Replaces the \p text in selection \p sel.
*/
void replace_selection_(Fl_Text_Selection_mod* sel, const char* text);
/**
Updates all of the selections in the buffer for changes in the buffer's text
*/
void update_selections(int pos, int nDeleted, int nInserted);
Fl_Text_Selection_mod mPrimary; /**< highlighted areas */
Fl_Text_Selection_mod mSecondary; /**< highlighted areas */
Fl_Text_Selection_mod mHighlight; /**< highlighted areas */
int mLength; /**< length of the text in the buffer (the length
of the buffer itself must be calculated:
gapEnd - gapStart + length) */
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 */
// The hardware tab distance used by all displays for this buffer,
// and used in computing offsets for rectangular selection operations.
int mTabDist; /**< equiv. number of characters in a tab */
int mNModifyProcs; /**< number of modify-redisplay procs attached */
Fl_Text_Modify_Cb *mModifyProcs;/**< procedures to call when buffer is
modified to redisplay contents */
void** mCbArgs; /**< caller arguments for modifyProcs above */
int mNPredeleteProcs; /**< number of pre-delete procs attached */
Fl_Text_Predelete_Cb *mPredeleteProcs; /**< procedure to call before text is deleted
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
a buffer modification operation */
char mCanUndo; /**< if this buffer is used for attributes, it must
not do any undo calls */
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 */
};
#endif
//
// End of "$Id: Fl_Text_Buffer_mod.H 8148 2010-12-31 22:38:03Z matt $".
//

View file

@ -1,262 +0,0 @@
//
// "$Id: Fl_Text_Buffer.H 6010 2008-01-04 20:31:52Z matt $"
//
// Header file for Fl_Text_Buffer class.
//
// Copyright 2001-2005 by Bill Spitzak and others.
// Original code Copyright Mark Edel. Permission to distribute under
// the LGPL for the FLTK library granted by Mark Edel.
// ----------------------------------------------------------------------------
// Copyright (C) 2014
// David Freese, W1HKJ
//
// This file is part of flmsg
//
// flrig is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// flrig 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#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
#include <FL/Fl_Export.H>
class FL_EXPORT Fl_Text_Selection {
friend class Fl_Text_Buffer_mod;
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);
char rectangular() { return mRectangular; }
int start() { return mStart; }
int end() { return mEnd; }
int rect_start() { return mRectStart; }
int rect_end() { return mRectEnd; }
char selected() { return mSelected; }
void selected(char b) { mSelected = b; }
int includes(int pos, int lineStartPos, int dispIndex);
int position(int* start, int* end);
int position(int* start, int* end, int* isRect, int* rectStart, int* rectEnd);
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);
typedef void (*Fl_Text_Predelete_Cb)(int pos, int nDeleted, void* cbArg);
class FL_EXPORT Fl_Text_Buffer_mod {
public:
Fl_Text_Buffer_mod(int requestedSize = 0);
~Fl_Text_Buffer_mod();
int length() { return mLength; }
char* text();
void text(const char* text);
char* text_range(int start, int end);
char character(int pos);
char* text_in_rectangle(int start, int end, int rectStart, int rectEnd);
void insert(int pos, const char* text);
void append(const char* t) { insert(length(), t); }
void remove(int start, int end);
void replace(int start, int end, const char *text);
void copy(Fl_Text_Buffer_mod* fromBuf, int fromStart, int fromEnd, int toPos);
int undo(int *cp=0);
void canUndo(char flag=1);
int insertfile(const char *file, int pos, int buflen = 128*1024);
int appendfile(const char *file, int buflen = 128*1024)
{ return insertfile(file, length(), buflen); }
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);
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);
int tab_distance() { return mTabDist; }
void tab_distance(int tabDist);
void select(int start, int end);
int selected() { return mPrimary.selected(); }
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);
char* selection_text();
void remove_selection();
void replace_selection(const char* text);
void secondary_select(int start, int end);
int secondary_selected() { return mSecondary.selected(); }
void secondary_unselect();
void secondary_select_rectangular(int start, int end, int rectStart,
int rectEnd);
int secondary_selection_position(int* start, int* end);
int secondary_selection_position(int* start, int* end, int* isRect,
int* rectStart, int* rectEnd);
char* secondary_selection_text();
void remove_secondary_selection();
void replace_secondary_selection(const char* text);
void highlight(int start, int end);
int highlight() { return mHighlight.selected(); }
void unhighlight();
void highlight_rectangular(int start, int end, int rectStart, int rectEnd);
int highlight_position(int* start, int* end);
int highlight_position(int* start, int* end, int* isRect, int* rectStart,
int* rectEnd);
char* highlight_text();
void add_modify_callback(Fl_Text_Modify_Cb bufModifiedCB, void* cbArg);
void remove_modify_callback(Fl_Text_Modify_Cb bufModifiedCB, void* cbArg);
void call_modify_callbacks() { call_modify_callbacks(0, 0, 0, 0, 0); }
void add_predelete_callback(Fl_Text_Predelete_Cb bufPredelCB, void* cbArg);
void remove_predelete_callback(Fl_Text_Predelete_Cb predelCB, void* cbArg);
void call_predelete_callbacks() { call_predelete_callbacks(0, 0); }
char* line_text(int pos);
int line_start(int pos);
int line_end(int pos);
int word_start(int pos);
int word_end(int pos);
int expand_character(int pos, int indent, char *outStr);
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);
int count_displayed_characters(int lineStartPos, int targetPos);
int skip_displayed_characters(int lineStartPos, int nChars);
int count_lines(int startPos, int endPos);
int skip_lines(int startPos, int nLines);
int rewind_lines(int startPos, int nLines);
int findchar_forward(int startPos, char searchChar, int* foundPos);
int findchar_backward(int startPos, char searchChar, int* foundPos);
int findchars_forward(int startPos, const char* searchChars, int* foundPos);
int findchars_backward(int startPos, const char* searchChars, int* foundPos);
int search_forward(int startPos, const char* searchString, int* foundPos,
int matchCase = 0);
int search_backward(int startPos, const char* searchString, int* foundPos,
int matchCase = 0);
int substitute_null_characters(char* string, int length);
void unsubstitute_null_characters(char* string);
char null_substitution_character() { return mNullSubsChar; }
Fl_Text_Selection* primary_selection() { return &mPrimary; }
Fl_Text_Selection* secondary_selection() { return &mSecondary; }
Fl_Text_Selection* highlight_selection() { return &mHighlight; }
protected:
void call_modify_callbacks(int pos, int nDeleted, int nInserted,
int nRestyled, const char* deletedText);
void call_predelete_callbacks(int pos, int nDeleted);
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,
Fl_Text_Selection* newSelection);
void move_gap(int pos);
void reallocate_with_gap(int newGapStart, int newGapLen);
char* selection_text_(Fl_Text_Selection* sel);
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,
int* selEnd);
void update_selections(int pos, int nDeleted, int nInserted);
Fl_Text_Selection mPrimary; /* highlighted areas */
Fl_Text_Selection mSecondary;
Fl_Text_Selection mHighlight;
int mLength; /* length of the text in the buffer (the length
of the buffer itself must be calculated:
gapEnd - gapStart + length) */
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 */
// The hardware tab distance used by all displays for this buffer,
// and used in computing offsets for rectangular selection operations.
int mTabDist; /* equiv. number of characters in a tab */
int mUseTabs; /* True if buffer routines are allowed to use
tabs for padding in rectangular operations */
int mNModifyProcs; /* number of modify-redisplay procs attached */
Fl_Text_Modify_Cb* /* procedures to call when buffer is */
mNodifyProcs; /* modified to redisplay contents */
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
a buffer modification operation */
char mNullSubsChar; /* NEdit is based on C null-terminated strings,
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 */
char mCanUndo; /* if this buffer is used for attributes, it must
not do any undo calls */
};
#endif
//
// End of "$Id: Fl_Text_Buffer.H 6010 2008-01-04 20:31:52Z matt $".
//

View file

@ -1,783 +0,0 @@
//
// "$Id: Fl_Text_Buffer_mod.H 8148 2010-12-31 22:38:03Z matt $"
//
// Header file for Fl_Text_Buffer_mod class.
//
// Copyright 2001-2010 by Bill Spitzak and others.
// Original code Copyright Mark Edel. Permission to distribute under
// the LGPL for the FLTK library granted by Mark Edel.
// ----------------------------------------------------------------------------
// Copyright (C) 2014
// David Freese, W1HKJ
//
// This file is part of flmsg
//
// flrig is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// flrig 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
/* \file
Fl_Text_Buffer_mod, Fl_Text_Selection_mod widget . */
#ifndef Fl_Text_Buffer_mod_H
#define Fl_Text_Buffer_mod_H
#undef ASSERT_UTF8
#ifdef ASSERT_UTF8
# include <assert.h>
# define IS_UTF8_ALIGNED(a) if (a && *a) assert(fl_utf8len(*(a))>0);
# define IS_UTF8_ALIGNED2(a, b) if (b>=0 && b<a->length()) assert(fl_utf8len(a->byte_at(b))>0);
#else
# define IS_UTF8_ALIGNED(a)
# define IS_UTF8_ALIGNED2(a, b)
#endif
/*
"character size" is the size of a UTF-8 character in bytes
"character width" is the width of a Unicode character in pixels
"column" was orginally defined as a character offset from the left margin.
It was identical to the byte offset. In UTF-8, we have neither a byte offset
nor truly fixed width fonts (*). Column could be a pixel value multiplied with
an average character width (which is a bearable approximation).
* in Unicode, there are no fixed width fonts! Even if the ASCII characters may
happen to be all the same width in pixels, chinese charcaters surely are not.
There are plenty of exceptions, like ligatures, that make special handling of
"fixed" character widths a nightmare. I decided to remove all references to
fixed fonts and see "columns" as a multiple of the average width of a
character in the main font.
- Matthias
*/
/* Maximum length in characters of a tab or control character expansion
of a single buffer character */
#define FL_TEXT_MAX_EXP_CHAR_LEN 20
#include <FL/Fl_Export.H>
/**
\class Fl_Text_Selection_mod
\brief This is an internal class for Fl_Text_Buffer_mod to manage text selections.
This class works correctly with utf-8 strings assuming that the parameters
for all calls are on character boundaries.
*/
class FL_EXPORT Fl_Text_Selection_mod {
friend class Fl_Text_Buffer_mod;
public:
/**
\brief Set the selection range.
\param start byte offset to first selected character
\param end byte offset pointing after last selected character
*/
void set(int start, int end);
/**
\brief Updates a selection afer text was modified.
Updates an individual selection for changes in the corresponding text
\param pos byte offset into text buffer at which the change occured
\param nDeleted number of bytes deleted from the buffer
\param nInserted number of bytes inserted into the buffer
*/
void update(int pos, int nDeleted, int nInserted);
/**
\brief Return the byte offset to the first selected character.
\return byte offset
*/
int start() const { return mStart; }
/**
\brief Return the byte ofsset to the character after the last selected character.
\return byte offset
*/
int end() const { return mEnd; }
/**
\brief Returns true if any text is selected.
\return a non-zero number if any text has been selected, or 0
if no text is selected.
*/
bool selected() const { return mSelected; }
/**
\brief Modify the 'selected' flag.
\param b new flag
*/
void selected(bool b) { mSelected = b; }
/**
Return true if position \p pos with indentation \p dispIndex is in
the Fl_Text_Selection_mod.
*/
int includes(int pos) const;
/**
\brief Return the positions of this selection.
\param start retrun byte offset to first selected character
\param end retrun byte offset pointing after last selected character
\return true if selected
*/
int position(int* start, int* end) const;
protected:
int mStart; ///< byte offset to the first selected character
int mEnd; ///< byte offset to the character after the last selected character
bool mSelected; ///< this flag is set if any text is selected
};
typedef void (*Fl_Text_Modify_Cb)(int pos, int nInserted, int nDeleted,
int nRestyled, const char* deletedText,
void* cbArg);
typedef void (*Fl_Text_Predelete_Cb)(int pos, int nDeleted, void* cbArg);
/**
\brief This class manages unicode displayed in one or more Fl_Text_Display_mod widgets.
All text in Fl_Text_Buffer_modmust be encoded in UTF-8. All indices used in the
function calls must be aligned to the start of a UTF-8 sequence. All indices
and pointers returned will be aligned. All functions that return a single
character will return that in an unsiged int in UCS-4 encoding.
The Fl_Text_Buffer_mod class is used by the Fl_Text_Display_mod
and Fl_Text_Editor_mod to manage complex text data and is based upon the
excellent NEdit text editor engine - see http://www.nedit.org/.
*/
class FL_EXPORT Fl_Text_Buffer_mod {
public:
/**
Create an empty text buffer of a pre-determined size.
\param requestedSize use this to avoid unnecessary re-allocation
if you know exactly how much the buffer will need to hold
\param preferredGapSize Initial size for the buffer gap (empty space
in the buffer where text might be inserted
if the user is typing sequential chars)
*/
Fl_Text_Buffer_mod(int requestedSize = 0, int preferredGapSize = 1024);
/**
Frees a text buffer
*/
~Fl_Text_Buffer_mod();
/**
\brief Returns the number of bytes in the buffer.
\return size of text in bytes
*/
int length() const { return mLength; }
/**
\brief Get a copy of the entire contents of the text buffer.
Memory is allocated to contain the returned string, which the caller
must free.
\return newly allocated text buffer - must be free'd, text is utf8
*/
char* text() const;
/**
Replaces the entire contents of the text buffer.
\param text Text must be valid utf8.
*/
void text(const char* text);
/**
\brief Get a copy of a part of the text buffer.
Return a copy of the text between \p start and \p end character positions
from text buffer \p buf. Positions start at 0, and the range does not
include the character pointed to by \p end.
When you are done with the text, free it using the free() function.
\param start byte offset to first character
\param end byte offset after last character in range
\return newly allocated text buffer - must be free'd, text is utf8
*/
char* text_range(int start, int end) const;
/**
Returns the character at the specified position pos in the buffer.
Positions start at 0
\param pos byte offset into buffer, pos must be at acharacter boundary
\return Unicode UCS-4 encoded character
*/
unsigned int char_at(int pos) const;
/**
Returns the raw byte at the specified position pos in the buffer.
Positions start at 0
\param pos byte offset into buffer
\return unencoded raw byte
*/
char byte_at(int pos) const;
/**
Convert a byte offset in buffer into a memory address.
\param pos byte offset into buffer
\return byte offset converted to a memory address
*/
const char *address(int pos) const
{ return (pos < mGapStart) ? mBuf+pos : mBuf+pos+mGapEnd-mGapStart; }
/**
Convert a byte offset in buffer into a memory address.
\param pos byte offset into buffer
\return byte offset converted to a memory address
*/
char *address(int pos)
{ return (pos < mGapStart) ? mBuf+pos : mBuf+pos+mGapEnd-mGapStart; }
/**
Inserts null-terminated string \p text at position \p pos.
\param pos insertion position as byte offset (must be utf-8 character aligned)
\param text utf-8 encoded and nul terminated text
*/
void insert(int pos, const char* text);
/**
Appends the text string to the end of the buffer.
\param t utf-8 encoded and nul terminated text
*/
void append(const char* t) { insert(length(), t); }
/**
Deletes a range of characters in the buffer.
\param start byte offset to first character to be removed
\param end byte offset to charcatre after last character to be removed
*/
void remove(int start, int end);
/**
Deletes the characters between \p start and \p end, and inserts the null-terminated string \p text in their place in the buffer.
\param start byte offset to first character to be removed and new insert position
\param end byte offset to charcatre after last character to be removed
\param text utf-8 encoded and nul terminated text
*/
void replace(int start, int end, const char *text);
/**
Copies text from one buffer to this one.
\param fromBuf source text buffer may be the same as this
\param fromStart byte offset into buffer
\param fromEnd byte offset into buffer
\param toPos destination byte offset into buffer
*/
void copy(Fl_Text_Buffer_mod* fromBuf, int fromStart, int fromEnd, int toPos);
/**
Undo text modification according to the undo variables or insert text
from the undo buffer
*/
int undo(int *cp=0);
/**
Lets the undo system know if we can undo changes
*/
void canUndo(char flag=1);
/**
Inserts a file at the specified position. 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).
File can be UTF-8 or CP1252-encoded.
If the input file is not UTF-8-encoded, the Fl_Text_Buffer_mod widget will contain
UTF-8-transcoded data. By default, the message Fl_Text_Buffer_mod::file_encoding_warning_message
will warn the user about this.
\see input_file_was_transcoded and transcoding_warning_action.
*/
int insertfile(const char *file, int pos, int buflen = 128*1024);
/**
Appends the named file to the end of the buffer. See also insertfile().
*/
int appendfile(const char *file, int buflen = 128*1024)
{ return insertfile(file, length(), buflen); }
/**
Loads a text file into the buffer. See also insertfile().
*/
int loadfile(const char *file, int buflen = 128*1024)
{ select(0, length()); remove_selection(); return appendfile(file, buflen); }
/**
Writes the specified portions of the file to a file. Returns 0 on success, non-zero
on error (strerror() contains reason). 1 indicates open for write failed
(no data saved). 2 indicates error occurred while writing data
(data was partially saved).
*/
int outputfile(const char *file, int start, int end, int buflen = 128*1024);
/**
Saves a text file from the current buffer
*/
int savefile(const char *file, int buflen = 128*1024)
{ return outputfile(file, 0, length(), buflen); }
/**
Gets the tab width.
*/
int tab_distance() const { return mTabDist; }
/**
Set the hardware tab distance (width) used by all displays for this buffer,
and used in computing offsets for rectangular selection operations.
*/
void tab_distance(int tabDist);
/**
Selects a range of characters in the buffer.
*/
void select(int start, int end);
/**
Returns a non 0 value if text has been selected, 0 otherwise
*/
int selected() const { return mPrimary.selected(); }
/**
Cancels any previous selection on the primary text selection object
*/
void unselect();
/**
Gets the selection position
*/
int selection_position(int* start, int* end);
/**
Returns the currently selected text. When you are done with
the text, free it using the free() function.
*/
char* selection_text();
/**
Removes the text in the primary selection.
*/
void remove_selection();
/**
Replaces the text in the primary selection.
*/
void replace_selection(const char* text);
/**
Selects a range of characters in the secondary selection.
*/
void secondary_select(int start, int end);
/**
Returns a non 0 value if text has been selected in the secondary
text selection, 0 otherwise
*/
int secondary_selected() { return mSecondary.selected(); }
/**
Clears any selection in the secondary text selection object.
*/
void secondary_unselect();
/**
Returns the current selection in the secondary text selection object.
*/
int secondary_selection_position(int* start, int* end);
/**
Returns the text in the secondary selection. When you are
done with the text, free it using the free() function.
*/
char* secondary_selection_text();
/**
Removes the text from the buffer corresponding to the secondary text selection object.
*/
void remove_secondary_selection();
/**
Replaces the text from the buffer corresponding to the secondary
text selection object with the new string \p text.
*/
void replace_secondary_selection(const char* text);
/**
Highlights the specified text within the buffer.
*/
void highlight(int start, int end);
/**
Returns the highlighted text. When you are done with the
text, free it using the free() function.
*/
int highlight() { return mHighlight.selected(); }
/**
Unhighlights text in the buffer.
*/
void unhighlight();
/**
Highlights the specified text between \p start and \p end within the buffer.
*/
int highlight_position(int* start, int* end);
/**
Returns the highlighted text. When you are done with the
text, free it using the free() function.
*/
char* highlight_text();
/**
Adds a callback function that is called whenever the text buffer is
modified. The callback function is declared as follows:
\code
typedef void (*Fl_Text_Modify_Cb)(int pos, int nInserted, int nDeleted,
int nRestyled, const char* deletedText,
void* cbArg);
\endcode
*/
void add_modify_callback(Fl_Text_Modify_Cb bufModifiedCB, void* cbArg);
/**
Removes a modify callback.
*/
void remove_modify_callback(Fl_Text_Modify_Cb bufModifiedCB, void* cbArg);
/**
Calls all modify callbacks that have been registered using
the add_modify_callback()
method.
*/
void call_modify_callbacks() { call_modify_callbacks(0, 0, 0, 0, 0); }
/**
Adds a callback routine to be called before text is deleted from the buffer.
*/
void add_predelete_callback(Fl_Text_Predelete_Cb bufPredelCB, void* cbArg);
/**
Removes a callback routine \p bufPreDeleteCB associated with argument \p cbArg
to be called before text is deleted from the buffer.
*/
void remove_predelete_callback(Fl_Text_Predelete_Cb predelCB, void* cbArg);
/**
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); }
/**
Returns the text from the entire line containing the specified
character position. When you are done with the text, free it
using the free() function.
\param pos byte index into buffer
\return copy of utf8 text, must be free'd
*/
char* line_text(int pos) const;
/**
Returns the position of the start of the line containing position \p pos.
\param pos byte index into buffer
\return byte offset to line start
*/
int line_start(int pos) const;
/**
Finds and returns the position of the end of the line containing position \p pos
(which is either a pointer to the newline character ending the line,
or a pointer to one character beyond the end of the buffer)
\param pos byte index into buffer
\return byte offset to line end
*/
int line_end(int pos) const;
/**
Returns the position corresponding to the start of the word
\param pos byte index into buffer
\return byte offset to word start
*/
int word_start(int pos) const;
/**
Returns the position corresponding to the end of the word.
\param pos byte index into buffer
\return byte offset to word end
*/
int word_end(int pos) const;
/**
Count the number of displayed characters between buffer position
\p lineStartPos and \p targetPos. (displayed characters are the characters
shown on the screen to represent characters in the buffer, where tabs and
control characters are expanded)
*/
int count_displayed_characters(int lineStartPos, int targetPos) const;
/**
Count forward from buffer position \p startPos in displayed characters
(displayed characters are the characters shown on the screen to represent
characters in the buffer, where tabs and control characters are expanded)
\param lineStartPos byte offset into buffer
\param nChars number of bytes that are sent to the display
\return byte offset in input after all output bytes are sent
*/
int skip_displayed_characters(int lineStartPos, int nChars);
/**
Counts the number of newlines between \p startPos and \p endPos in buffer.
The character at position \p endPos is not counted.
*/
int count_lines(int startPos, int endPos) const;
/**
Finds the first character of the line \p nLines forward from \p startPos
in the buffer and returns its position
*/
int skip_lines(int startPos, int nLines);
/**
Finds and returns the position of the first character of the line \p nLines backwards
from \p startPos (not counting the character pointed to by \p startpos if
that is a newline) in the buffer. \p nLines == 0 means find the beginning of the line
*/
int rewind_lines(int startPos, int nLines);
/**
Finds the next occurrence of the specified character.
Search forwards in buffer for character \p searchChar, starting
with the character \p startPos, and returning the result in \p foundPos
returns 1 if found, 0 if not. (The difference between this and
BufSearchForward is that it's optimized for single characters. The
overall performance of the text widget is dependent on its ability to
count lines quickly, hence searching for a single character: newline)
\param startPos byte offset to start position
\param searchChar UCS-4 character that we want to find
\param foundPos byte offset where the character was found
\return 1 if found, 0 if not
*/
int findchar_forward(int startPos, unsigned searchChar, int* foundPos) const;
/**
Search backwards in buffer \p buf for character \p searchChar, starting
with the character BEFORE \p startPos, returning the result in \p foundPos
returns 1 if found, 0 if not. (The difference between this and
BufSearchBackward is that it's optimized for single characters. The
overall performance of the text widget is dependent on its ability to
count lines quickly, hence searching for a single character: newline)
\param startPos byte offset to start position
\param searchChar UCS-4 character that we want to find
\param foundPos byte offset where the character was found
\return 1 if found, 0 if not
*/
int findchar_backward(int startPos, unsigned int searchChar, int* foundPos) const;
/**
Search forwards in buffer for string \p searchString, starting with the
character \p startPos, and returning the result in \p foundPos
returns 1 if found, 0 if not.
\param startPos byte offset to start position
\param searchString utf8 string that we want to find
\param foundPos byte offset where the string was found
\param matchCase if set, match character case
\return 1 if found, 0 if not
*/
int search_forward(int startPos, const char* searchString, int* foundPos,
int matchCase = 0) const;
/**
Search backwards in buffer for string <i>searchCharssearchString</i>, starting with the
character BEFORE \p startPos, returning the result in \p foundPos
returns 1 if found, 0 if not.
\param startPos byte offset to start position
\param searchString utf8 string that we want to find
\param foundPos byte offset where the string was found
\param matchCase if set, match character case
\return 1 if found, 0 if not
*/
int search_backward(int startPos, const char* searchString, int* foundPos,
int matchCase = 0) const;
int findchars_forward(int startPos, const char* searchChars, int* foundPos);
int findchars_backward(int startPos, const char* searchChars, int* foundPos);
/**
Returns the primary selection.
*/
const Fl_Text_Selection_mod* primary_selection() const { return &mPrimary; }
/**
Returns the primary selection.
*/
Fl_Text_Selection_mod* primary_selection() { return &mPrimary; }
/**
Returns the secondary selection.
*/
const Fl_Text_Selection_mod* secondary_selection() const { return &mSecondary; }
/**
Returns the current highlight selection.
*/
const Fl_Text_Selection_mod* highlight_selection() const { return &mHighlight; }
/**
Returns the index of the previous character.
\param ix index to the current char
*/
int prev_char(int ix) const;
int prev_char_clipped(int ix) const;
/**
Returns the index of the next character.
\param ix index to the current char
*/
int next_char(int ix) const;
int next_char_clipped(int ix) const;
/**
Align an index into the buffer to the current or previous utf8 boundary.
*/
int utf8_align(int) const;
/**
\brief true iff the loaded file has been transcoded to UTF-8
*/
int input_file_was_transcoded;
/** This message may be displayed using the fl_alert() function when a file
which was not UTF-8 encoded is input.
*/
static const char* file_encoding_warning_message;
/**
\brief Pointer to a function called after reading a non UTF-8 encoded file.
This function is called after reading a file if the file content
was transcoded to UTF-8. Its default implementation calls fl_alert()
with the text of \ref file_encoding_warning_message. No warning message is
displayed if this pointer is set to NULL. Use \ref input_file_was_transcoded
to be informed if file input required transcoding to UTF-8.
*/
void (*transcoding_warning_action)(Fl_Text_Buffer_mod*);
protected:
/**
Calls the stored modify callback procedure(s) for this buffer to update the
changed area(s) on the screen and any other listeners.
*/
void call_modify_callbacks(int pos, int nDeleted, int nInserted,
int nRestyled, const char* deletedText) const;
/**
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(int pos, int nDeleted) const;
/**
Internal (non-redisplaying) version of BufInsert. Returns the length of
text inserted (this is just strlen(\p text), however this calculation can be
expensive and the length will be required by any caller who will continue
on to call redisplay). \p pos must be contiguous with the existing text in
the buffer (i.e. not past the end).
\return the number of bytes inserted
*/
int insert_(int pos, const char* text);
/**
Internal (non-redisplaying) version of BufRemove. Removes the contents
of the buffer between start and end (and moves the gap to the site of
the delete).
*/
void remove_(int start, int end);
/**
Calls the stored redisplay procedure(s) for this buffer to update the
screen for a change in a selection.
*/
void redisplay_selection(Fl_Text_Selection_mod* oldSelection,
Fl_Text_Selection_mod* newSelection) const;
/**
Move the gap to start at a new position.
*/
void move_gap(int pos);
/**
Reallocates the text storage in the buffer to have a gap starting at \p newGapStart
and a gap size of \p newGapLen, preserving the buffer's current contents.
*/
void reallocate_with_gap(int newGapStart, int newGapLen);
char* selection_text_(Fl_Text_Selection_mod* sel) const;
/**
Removes the text from the buffer corresponding to \p sel.
*/
void remove_selection_(Fl_Text_Selection_mod* sel);
/**
Replaces the \p text in selection \p sel.
*/
void replace_selection_(Fl_Text_Selection_mod* sel, const char* text);
/**
Updates all of the selections in the buffer for changes in the buffer's text
*/
void update_selections(int pos, int nDeleted, int nInserted);
Fl_Text_Selection_mod mPrimary; /**< highlighted areas */
Fl_Text_Selection_mod mSecondary; /**< highlighted areas */
Fl_Text_Selection_mod mHighlight; /**< highlighted areas */
int mLength; /**< length of the text in the buffer (the length
of the buffer itself must be calculated:
gapEnd - gapStart + length) */
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 */
// The hardware tab distance used by all displays for this buffer,
// and used in computing offsets for rectangular selection operations.
int mTabDist; /**< equiv. number of characters in a tab */
int mNModifyProcs; /**< number of modify-redisplay procs attached */
Fl_Text_Modify_Cb *mModifyProcs;/**< procedures to call when buffer is
modified to redisplay contents */
void** mCbArgs; /**< caller arguments for modifyProcs above */
int mNPredeleteProcs; /**< number of pre-delete procs attached */
Fl_Text_Predelete_Cb *mPredeleteProcs; /**< procedure to call before text is deleted
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
a buffer modification operation */
char mCanUndo; /**< if this buffer is used for attributes, it must
not do any undo calls */
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 */
};
#endif
//
// End of "$Id: Fl_Text_Buffer_mod.H 8148 2010-12-31 22:38:03Z matt $".
//

View file

@ -1,27 +1,496 @@
// ----------------------------------------------------------------------------
// Copyright (C) 2014
// David Freese, W1HKJ
//
// This file is part of flmsg
// "$Id: Fl_Text_Display_mod.H 8306 2011-01-24 17:04:22Z matt $"
//
// flrig is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
// Header file for Fl_Text_Display_mod class.
//
// flrig is distributed in the hope that it will be useful,
// Copyright 2001-2010 by Bill Spitzak and others.
// Original code Copyright Mark Edel. Permission to distribute under
// the LGPL for the FLTK library granted by Mark Edel.
//
// 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 General Public License for more details.
// 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 General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
// 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.
// 51 Franklin Street, Fifth Floor
// Boston, MA 02110-1301 USA.
//
// Please report all bugs and problems on the following page:
//
// http://www.fltk.org/str.php
//
/* \file
Fl_Text_Display_mod widget . */
#ifndef Fl_Text_Display_mod_H
#define Fl_Text_Display_mod_H
#include <string>
#include <FL/fl_draw.H>
#include <FL/Fl_Group.H>
#include <FL/Fl_Widget.H>
#include <FL/Fl_Scrollbar.H>
#include "Fl_Text_Buffer_mod.H"
#include <config.h>
#if FLMSG_FLTK_API_MINOR < 3
# include "Fl_Text_Display_mod_1_1.H"
#else
# include "Fl_Text_Display_mod_1_3.H"
/**
\brief Rich text display widget.
This is the FLTK text display widget. It allows the user to view multiple lines
of text and supports highlighting and scrolling. The buffer that is displayed
in the widget is managed by the Fl_Text_Buffer_mod class. A single Text Buffer
can be displayed by multiple Text Displays.
*/
class FL_EXPORT Fl_Text_Display_mod: public Fl_Group {
public:
/**
text display cursor shapes enumeration
*/
enum {
NORMAL_CURSOR, /**< I-beam */
CARET_CURSOR, /**< caret under the text */
DIM_CURSOR, /**< dim I-beam */
BLOCK_CURSOR, /**< unfille box under the current character */
HEAVY_CURSOR /**< thick I-beam */
};
/**
the character position is the left edge of a character, whereas
the cursor is thought to be between the centers of two consecutive
characters.
*/
enum {
CURSOR_POS,
CHARACTER_POS
};
/**
drag types - they match Fl::event_clicks() so that single clicking to
start a collection selects by character, double clicking selects by
word and triple clicking selects by line.
*/
enum {
DRAG_NONE = -2,
DRAG_START_DND = -1,
DRAG_CHAR = 0,
DRAG_WORD = 1,
DRAG_LINE = 2
};
/**
wrap types - used in wrap_mode()
*/
enum {
WRAP_NONE, /**< don't wrap text at all */
WRAP_AT_COLUMN, /**< wrap text at the given text column */
WRAP_AT_PIXEL, /**< wrap text at a pixel position */
WRAP_AT_BOUNDS /**< wrap text so that it fits into the widget width */
};
friend void fl_text_drag_me(int pos, Fl_Text_Display_mod* d);
typedef void (*Unfinished_Style_Cb)(int, void *);
/**
This structure associates the color, font, andsize of a string to draw
with an attribute mask matching attr
*/
struct Style_Table_Entry {
Fl_Color color;
Fl_Font font;
Fl_Fontsize size;
unsigned attr;
};
Fl_Text_Display_mod(int X, int Y, int W, int H, const char *l = 0);
~Fl_Text_Display_mod();
virtual int handle(int e);
void buffer(Fl_Text_Buffer_mod* buf);
/**
Sets the current text buffer associated with the text widget.
Multiple text widgets can be associated with the same text buffer.
\param buf new text buffer
*/
void buffer(Fl_Text_Buffer_mod& buf) { buffer(&buf); }
/**
Gets the current text buffer associated with the text widget.
Multiple text widgets can be associated with the same text buffer.
\return current text buffer
*/
Fl_Text_Buffer_mod* buffer() const { return mBuffer; }
void redisplay_range(int start, int end);
void scroll(int topLineNum, int horizOffset);
void insert(const char* text);
void overstrike(const char* text);
void insert_position(int newPos);
/**
Gets the position of the text insertion cursor for text display.
\return insert position index into text buffer
*/
int insert_position() const { return mCursorPos; }
int position_to_xy(int pos, int* x, int* y) const;
int in_selection(int x, int y) const;
void show_insert_position();
int move_right();
int move_left();
int move_up();
int move_down();
int count_lines(int start, int end, bool start_pos_is_line_start) const;
int line_start(int pos) const;
int line_end(int startPos, bool startPosIsLineStart) const;
int skip_lines(int startPos, int nLines, bool startPosIsLineStart);
int rewind_lines(int startPos, int nLines);
void next_word(void);
void previous_word(void);
void show_cursor(int b = 1);
/**
Hides the text cursor.
*/
void hide_cursor() { show_cursor(0); }
void cursor_style(int style);
/**
Gets the text cursor color.
\return cursor color
*/
Fl_Color cursor_color() const {return mCursor_color;}
/**
Sets the text cursor color.
\param n new cursor color
*/
void cursor_color(Fl_Color n) {mCursor_color = n;}
/**
Gets the width/height of the scrollbars.
/return width of scrollbars
*/
int scrollbar_width() const { return scrollbar_width_; }
/**
Sets the width/height of the scrollbars.
\param W width of scrollbars
*/
void scrollbar_width(int W) { scrollbar_width_ = W; }
/**
Gets the scrollbar alignment type.
\return scrollbar alignment
*/
Fl_Align scrollbar_align() const { return scrollbar_align_; }
/**
Sets the scrollbar alignment type.
\param a new scrollbar alignment
*/
void scrollbar_align(Fl_Align a) { scrollbar_align_ = a; }
/**
Moves the insert position to the beginning of the current word.
\param pos start calculation at this index
\return beginning of the words
*/
int word_start(int pos) const { return buffer()->word_start(pos); }
/**
Moves the insert position to the end of the current word.
\param pos start calculation at this index
\return index of first character after the end of the word
*/
int word_end(int pos) const { return buffer()->word_end(pos); }
void highlight_data(Fl_Text_Buffer_mod *styleBuffer,
const Style_Table_Entry *styleTable,
int nStyles, char unfinishedStyle,
Unfinished_Style_Cb unfinishedHighlightCB,
void *cbArg);
int position_style(int lineStartPos, int lineLen, int lineIndex) const;
/**
\todo FIXME : get set methods pointing on shortcut_
have no effects as shortcut_ is unused in this class and derived!
\return the current shortcut key
*/
int shortcut() const {return shortcut_;}
/**
\todo FIXME : get set methods pointing on shortcut_
have no effects as shortcut_ is unused in this class and derived!
\param s the new shortcut key
*/
void shortcut(int s) {shortcut_ = s;}
/**
Gets the default font used when drawing text in the widget.
\return current text font face unless overridden by a style
*/
Fl_Font textfont() const {return textfont_;}
/**
Sets the default font used when drawing text in the widget.
\param s default text font face
*/
void textfont(Fl_Font s) {textfont_ = s; mColumnScale = 0;}
/**
Gets the default size of text in the widget.
\return current text height unless overridden by a style
*/
Fl_Fontsize textsize() const {return textsize_;}
/**
Sets the default size of text in the widget.
\param s new text size
*/
void textsize(Fl_Fontsize s) {textsize_ = s; mColumnScale = 0;}
/**
Gets the default color of text in the widget.
\return text color unless overridden by a style
*/
Fl_Color textcolor() const {return textcolor_;}
/**
Sets the default color of text in the widget.
\param n new text color
*/
void textcolor(Fl_Color n) {textcolor_ = n;}
int wrapped_column(int row, int column) const;
int wrapped_row(int row) const;
void wrap_mode(int wrap, int wrap_margin);
virtual void resize(int X, int Y, int W, int H);
/**
Convert an x pixel position into a column number.
\param x number of pixels from the left margin
\return an approximate column number based on the main font
*/
double x_to_col(double x) const;
/**
Convert a column number into an x pixel position.
\param col an approximate column number based on the main font
\return number of pixels from the left margin to the left of an
average sized character
*/
double col_to_x(double col) const;
protected:
// Most (all?) of this stuff should only be called from resize() or
// draw().
// Anything with "vline" indicates thats it deals with currently
// visible lines.
virtual void draw();
void draw_text(int X, int Y, int W, int H);
void draw_range(int start, int end);
void draw_cursor(int, int);
void draw_string(int style, int x, int y, int toX, const char *string,
int nChars) const;
void draw_vline(int visLineNum, int leftClip, int rightClip,
int leftCharIndex, int rightCharIndex);
int find_x(const char *s, int len, int style, int x) const;
enum {
DRAW_LINE,
FIND_INDEX,
FIND_INDEX_FROM_ZERO,
GET_WIDTH
};
int handle_vline(int mode,
int lineStart, int lineLen, int leftChar, int rightChar,
int topClip, int bottomClip,
int leftClip, int rightClip) const;
void draw_line_numbers(bool clearAll);
void clear_rect(int style, int x, int y, int width, int height) const;
void display_insert();
void offset_line_starts(int newTopLineNum);
void calc_line_starts(int startLine, int endLine);
void update_line_starts(int pos, int charsInserted, int charsDeleted,
int linesInserted, int linesDeleted, int *scrolled);
void calc_last_char();
int position_to_line( int pos, int* lineNum ) const;
double string_width(const char* string, int length, int style) const;
static void scroll_timer_cb(void*);
static void buffer_predelete_cb(int pos, int nDeleted, void* cbArg);
static void buffer_modified_cb(int pos, int nInserted, int nDeleted,
int nRestyled, const char* deletedText,
void* cbArg);
static void h_scrollbar_cb(Fl_Scrollbar* w, Fl_Text_Display_mod* d);
static void v_scrollbar_cb( Fl_Scrollbar* w, Fl_Text_Display_mod* d);
void update_v_scrollbar();
void update_h_scrollbar();
int measure_vline(int visLineNum) const;
int longest_vline() const;
int empty_vlines() const;
int vline_length(int visLineNum) const;
int xy_to_position(int x, int y, int PosType = CHARACTER_POS) const;
void xy_to_rowcol(int x, int y, int* row, int* column,
int PosType = CHARACTER_POS) const;
void maintain_absolute_top_line_number(int state);
int get_absolute_top_line_number() const;
void absolute_top_line_number(int oldFirstChar);
int maintaining_absolute_top_line_number() const;
void reset_absolute_top_line_number();
int position_to_linecol(int pos, int* lineNum, int* column) const;
int scroll_(int topLineNum, int horizOffset);
void extend_range_for_styles(int* start, int* end);
void find_wrap_range(const char *deletedText, int pos, int nInserted,
int nDeleted, int *modRangeStart, int *modRangeEnd,
int *linesInserted, int *linesDeleted);
void measure_deleted_lines(int pos, int nDeleted);
void wrapped_line_counter(Fl_Text_Buffer_mod *buf, int startPos, int maxPos,
int maxLines, bool startPosIsLineStart,
int styleBufOffset, int *retPos, int *retLines,
int *retLineStart, int *retLineEnd,
bool countLastLineMissingNewLine = true) const;
void find_line_end(int pos, bool start_pos_is_text_start, int *lineEnd,
int *nextLineStart) const;
double measure_proportional_character(const char *s, int colNum, int pos) const;
int wrap_uses_character(int lineEndPos) const;
static const int DEFAULT_TOP_MARGIN;
static const int DEFAULT_BOTTOM_MARGIN;
static const int DEFAULT_LEFT_MARGIN;
static const int DEFAULT_RIGHT_MARGIN;
int TOP_MARGIN, BOTTOM_MARGIN, LEFT_MARGIN, RIGHT_MARGIN;
int damage_range1_start, damage_range1_end;
int damage_range2_start, damage_range2_end;
int mCursorPos;
int mCursorOn;
int mCursorOldY; /* Y pos. of cursor for blanking */
int mCursorToHint; /* Tells the buffer modified callback
where to move the cursor, to reduce
the number of redraw calls */
int mCursorStyle; /* One of enum cursorStyles above */
int mCursorPreferredXPos; /* Pixel position for vert. cursor movement */
int mNVisibleLines; /* # of visible (displayed) lines */
int mNBufferLines; /* # of newlines in the buffer */
Fl_Text_Buffer_mod* mBuffer; /* Contains text to be displayed */
Fl_Text_Buffer_mod* mStyleBuffer; /* Optional parallel buffer containing
color and font information */
int mFirstChar, mLastChar; /* Buffer positions of first and last
displayed character (lastChar points
either to a newline or one character
beyond the end of the buffer) */
int mContinuousWrap; /* Wrap long lines when displaying */
int mFastDisplay; /* force continuous wrap and insertion of eol characters
used in FTextRX */
std::string s_text; /* current contents of line text buffer */
std::string s_style; /* current contents of line stype buffer */
int mWrapMarginPix; /* Margin in # of pixels for
wrapping in continuousWrap mode */
int* mLineStarts;
int mTopLineNum; /* Line number of top displayed line
of file (first line of file is 1) */
int mAbsTopLineNum; /* In continuous wrap mode, the line
number of the top line if the text
were not wrapped (note that this is
only maintained as needed). */
int mNeedAbsTopLineNum; /* Externally settable flag to continue
maintaining absTopLineNum even if
it isn't needed for line # display */
int mHorizOffset; /* Horizontal scroll pos. in pixels */
int mTopLineNumHint; /* Line number of top displayed line
of file (first line of file is 1) */
int mHorizOffsetHint; /* Horizontal scroll pos. in pixels */
int mNStyles; /* Number of entries in styleTable */
const Style_Table_Entry *mStyleTable; /* Table of fonts and colors for
coloring/syntax-highlighting */
char mUnfinishedStyle; /* Style buffer entry which triggers
on-the-fly reparsing of region */
Unfinished_Style_Cb mUnfinishedHighlightCB; /* Callback to parse "unfinished" */
/* regions */
void* mHighlightCBArg; /* Arg to unfinishedHighlightCB */
int mMaxsize;
int mSuppressResync; /* Suppress resynchronization of line
starts during buffer updates */
int mNLinesDeleted; /* Number of lines deleted during
buffer modification (only used
when resynchronization is suppressed) */
int mModifyingTabDistance; /* Whether tab distance is being
modified */
mutable double mColumnScale; /* Width in pixels of an average character. This
value is calculated as needed (lazy eval); it
needs to be mutable so that it can be calculated
within a method marked as "const" */
Fl_Color mCursor_color;
Fl_Scrollbar* mHScrollBar;
Fl_Scrollbar* mVScrollBar;
int scrollbar_width_;
Fl_Align scrollbar_align_;
int dragPos, dragType, dragging;
int display_insert_position_hint;
struct { int x, y, w, h; } text_area;
int shortcut_;
Fl_Font textfont_;
Fl_Fontsize textsize_;
Fl_Color textcolor_;
// The following are not presently used from the original NEdit code,
// but are being put here so that future versions of Fl_Text_Display_mod
// can implement line numbers without breaking binary compatibility.
/* Line number margin and width */
int mLineNumLeft, mLineNumWidth;
};
#endif
//
// End of "$Id: Fl_Text_Display_mod.H 8306 2011-01-24 17:04:22Z matt $".
//

View file

@ -1,303 +0,0 @@
//
// "$Id: Fl_Text_Display.H 4502 2005-08-10 23:11:51Z matt $"
//
// Header file for Fl_Text_Display class.
//
// Copyright 2001-2005 by Bill Spitzak and others.
// Original code Copyright Mark Edel. Permission to distribute under
// the LGPL for the FLTK library granted by Mark Edel.
// ----------------------------------------------------------------------------
// Copyright (C) 2014
// David Freese, W1HKJ
//
// This file is part of flmsg
//
// flrig is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// flrig 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#ifndef FL_TEXT_DISPLAY_MOD_H
#define FL_TEXT_DISPLAY_MOD_H
#include <FL/fl_draw.H>
#include <FL/Fl_Group.H>
#include <FL/Fl_Widget.H>
#include <FL/Fl_Scrollbar.H>
#include "Fl_Text_Buffer_mod.H"
class Fl_Text_Display_mod: public Fl_Group {
public:
enum {
NORMAL_CURSOR, CARET_CURSOR, DIM_CURSOR,
BLOCK_CURSOR, HEAVY_CURSOR
};
enum {
CURSOR_POS, CHARACTER_POS
};
// drag types- they match Fl::event_clicks() so that single clicking to
// start a collection selects by character, double clicking selects by
// word and triple clicking selects by line.
enum {
DRAG_CHAR = 0, DRAG_WORD = 1, DRAG_LINE = 2
};
friend void fl_text_drag_me(int pos, Fl_Text_Display_mod* d);
typedef void (*Unfinished_Style_Cb)(int, void *);
// style attributes - currently not implemented!
enum {
ATTR_NONE = 0,
ATTR_UNDERLINE = 1,
ATTR_HIDDEN = 2
};
struct Style_Table_Entry {
Fl_Color color;
Fl_Font font;
int size;
unsigned attr;
};
Fl_Text_Display_mod(int X, int Y, int W, int H, const char *l = 0);
~Fl_Text_Display_mod();
virtual int handle(int e);
void buffer(Fl_Text_Buffer_mod* buf);
void buffer(Fl_Text_Buffer_mod& buf) { buffer(&buf); }
Fl_Text_Buffer_mod* buffer() { return mBuffer; }
void redisplay_range(int start, int end);
void scroll(int topLineNum, int horizOffset);
void insert(const char* text);
void overstrike(const char* text);
void insert_position(int newPos);
int insert_position() { return mCursorPos; }
int in_selection(int x, int y);
void show_insert_position();
int move_right();
int move_left();
int move_up();
int move_down();
int count_lines(int start, int end, bool start_pos_is_line_start);
int line_start(int pos);
int line_end(int pos, bool start_pos_is_line_start);
int skip_lines(int startPos, int nLines, bool startPosIsLineStart);
int rewind_lines(int startPos, int nLines);
void next_word(void);
void previous_word(void);
void show_cursor(int b = 1);
void hide_cursor() { show_cursor(0); }
void cursor_style(int style);
Fl_Color cursor_color() const {return mCursor_color;}
void cursor_color(Fl_Color n) {mCursor_color = n;}
int scrollbar_width() { return scrollbar_width_; }
Fl_Align scrollbar_align() { return scrollbar_align_; }
void scrollbar_width(int W) { scrollbar_width_ = W; }
void scrollbar_align(Fl_Align a) { scrollbar_align_ = a; }
int word_start(int pos) { return buffer()->word_start(pos); }
int word_end(int pos) { return buffer()->word_end(pos); }
void highlight_data(Fl_Text_Buffer_mod *styleBuffer,
const Style_Table_Entry *styleTable,
int nStyles, char unfinishedStyle,
Unfinished_Style_Cb unfinishedHighlightCB,
void *cbArg);
int position_style(int lineStartPos, int lineLen, int lineIndex,
int dispIndex);
Fl_Font textfont() const {return textfont_;}
void textfont(Fl_Font f) {textfont_ = f;}
uchar textsize() const {return textsize_;}
void textsize(uchar s) {textsize_ = s;}
Fl_Color textcolor() const {return (Fl_Color)textcolor_;}
void textcolor(unsigned n) {textcolor_ = n;}
int wrapped_column(int row, int column);
int wrapped_row(int row);
void wrap_mode(int wrap, int wrap_margin);
virtual void resize(int X, int Y, int W, int H);
protected:
// Most (all?) of this stuff should only be called from resize() or
// draw().
// Anything with "vline" indicates thats it deals with currently
// visible lines.
virtual void draw();
void draw_text(int X, int Y, int W, int H);
void draw_range(int start, int end);
void draw_cursor(int, int);
void draw_string(int style, int x, int y, int toX, const char *string,
int nChars);
void draw_vline(int visLineNum, int leftClip, int rightClip,
int leftCharIndex, int rightCharIndex);
void draw_line_numbers(bool clearAll);
void clear_rect(int style, int x, int y, int width, int height);
void display_insert();
void offset_line_starts(int newTopLineNum);
void calc_line_starts(int startLine, int endLine);
void update_line_starts(int pos, int charsInserted, int charsDeleted,
int linesInserted, int linesDeleted, int *scrolled);
void calc_last_char();
int position_to_line( size_t pos, int* lineNum);//int pos, int* lineNum );
int string_width(const char* string, int length, int style);
static void scroll_timer_cb(void*);
static void buffer_predelete_cb(int pos, int nDeleted, void* cbArg);
static void buffer_modified_cb(int pos, int nInserted, int nDeleted,
int nRestyled, const char* deletedText,
void* cbArg);
static void h_scrollbar_cb(Fl_Scrollbar* w, Fl_Text_Display_mod* d);
static void v_scrollbar_cb( Fl_Scrollbar* w, Fl_Text_Display_mod* d);
void update_v_scrollbar();
void update_h_scrollbar();
int measure_vline(int visLineNum);
int longest_vline();
int empty_vlines();
int vline_length(int visLineNum);
int xy_to_position(int x, int y, int PosType = CHARACTER_POS);
void xy_to_rowcol(int x, int y, int* row, int* column,
int PosType = CHARACTER_POS);
int position_to_xy(int pos, int* x, int* y);
void maintain_absolute_top_line_number(int state);
int get_absolute_top_line_number();
void absolute_top_line_number(int oldFirstChar);
int maintaining_absolute_top_line_number();
void reset_absolute_top_line_number();
int position_to_linecol(int pos, int* lineNum, int* column);
void scroll_(int topLineNum, int horizOffset);
void extend_range_for_styles(int* start, int* end);
void find_wrap_range(const char *deletedText, int pos, int nInserted,
int nDeleted, int *modRangeStart, int *modRangeEnd,
int *linesInserted, int *linesDeleted);
void measure_deleted_lines(int pos, int nDeleted);
void wrapped_line_counter(Fl_Text_Buffer_mod *buf, int startPos, int maxPos,
int maxLines, bool startPosIsLineStart,
int styleBufOffset, int *retPos, int *retLines,
int *retLineStart, int *retLineEnd,
bool countLastLineMissingNewLine = true);
void find_line_end(int pos, bool start_pos_is_line_start, int *lineEnd,
int *nextLineStart);
int measure_proportional_character(char c, int colNum, int pos);
int wrap_uses_character(int lineEndPos);
int range_touches_selection(Fl_Text_Selection *sel, int rangeStart,
int rangeEnd);
static const int DEFAULT_TOP_MARGIN;
static const int DEFAULT_BOTTOM_MARGIN;
static const int DEFAULT_LEFT_MARGIN;
static const int DEFAULT_RIGHT_MARGIN;
int TOP_MARGIN, BOTTOM_MARGIN, LEFT_MARGIN, RIGHT_MARGIN;
int damage_range1_start, damage_range1_end;
int damage_range2_start, damage_range2_end;
int mCursorPos;
int mCursorOn;
int mCursorOldY; /* Y pos. of cursor for blanking */
int mCursorToHint; /* Tells the buffer modified callback
where to move the cursor, to reduce
the number of redraw calls */
int mCursorStyle; /* One of enum cursorStyles above */
int mCursorPreferredCol; /* Column for vert. cursor movement */
int mNVisibleLines; /* # of visible (displayed) lines */
int mNBufferLines; /* # of newlines in the buffer */
Fl_Text_Buffer_mod* mBuffer; /* Contains text to be displayed */
Fl_Text_Buffer_mod* mStyleBuffer; /* Optional parallel buffer containing
color and font information */
int mFirstChar, mLastChar; /* Buffer positions of first and last
displayed character (lastChar points
either to a newline or one character
beyond the end of the buffer) */
int mContinuousWrap; /* Wrap long lines when displaying */
int mWrapMargin; /* Margin in # of char positions for
wrapping in continuousWrap mode */
int* mLineStarts;
int mTopLineNum; /* Line number of top displayed line
of file (first line of file is 1) */
int mAbsTopLineNum; /* In continuous wrap mode, the line
number of the top line if the text
were not wrapped (note that this is
only maintained as needed). */
int mNeedAbsTopLineNum; /* Externally settable flag to continue
maintaining absTopLineNum even if
it isn't needed for line # display */
int mHorizOffset; /* Horizontal scroll pos. in pixels */
int mTopLineNumHint; /* Line number of top displayed line
of file (first line of file is 1) */
int mHorizOffsetHint; /* Horizontal scroll pos. in pixels */
int mNStyles; /* Number of entries in styleTable */
const Style_Table_Entry *mStyleTable; /* Table of fonts and colors for
coloring/syntax-highlighting */
char mUnfinishedStyle; /* Style buffer entry which triggers
on-the-fly reparsing of region */
Unfinished_Style_Cb mUnfinishedHighlightCB; /* Callback to parse "unfinished" */
/* regions */
void* mHighlightCBArg; /* Arg to unfinishedHighlightCB */
int mMaxsize;
int mFixedFontWidth; /* Font width if all current fonts are
fixed and match in width, else -1 */
int mSuppressResync; /* Suppress resynchronization of line
starts during buffer updates */
int mNLinesDeleted; /* Number of lines deleted during
buffer modification (only used
when resynchronization is suppressed) */
int mModifyingTabDistance; /* Whether tab distance is being
modified */
Fl_Color mCursor_color;
Fl_Scrollbar* mHScrollBar;
Fl_Scrollbar* mVScrollBar;
int scrollbar_width_;
Fl_Align scrollbar_align_;
int dragPos, dragType, dragging;
int display_insert_position_hint;
struct { int x, y, w, h; } text_area;
Fl_Font textfont_;
uchar textsize_;
unsigned textcolor_;
// The following are not presently used from the original NEdit code,
// but are being put here so that future versions of Fl_Text_Display
// can implement line numbers without breaking binary compatibility.
int mLineNumLeft, mLineNumWidth;
/* Line number margin and width */
};
#endif
//
// End of "$Id: Fl_Text_Display.H 4502 2005-08-10 23:11:51Z matt $".
//

View file

@ -1,491 +0,0 @@
//
// "$Id: Fl_Text_Display_mod.H 8306 2011-01-24 17:04:22Z matt $"
//
// Header file for Fl_Text_Display_mod class.
//
// Copyright 2001-2010 by Bill Spitzak and others.
// Original code Copyright Mark Edel. Permission to distribute under
// the LGPL for the FLTK library granted by Mark Edel.
// ----------------------------------------------------------------------------
// Copyright (C) 2014
// David Freese, W1HKJ
//
// This file is part of flmsg
//
// flrig is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// flrig 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
/* \file
Fl_Text_Display_mod widget . */
#ifndef Fl_Text_Display_mod_H
#define Fl_Text_Display_mod_H
#include <string>
#include <FL/fl_draw.H>
#include <FL/Fl_Group.H>
#include <FL/Fl_Widget.H>
#include <FL/Fl_Scrollbar.H>
#include "Fl_Text_Buffer_mod.H"
/**
\brief Rich text display widget.
This is the FLTK text display widget. It allows the user to view multiple lines
of text and supports highlighting and scrolling. The buffer that is displayed
in the widget is managed by the Fl_Text_Buffer_mod class. A single Text Buffer
can be displayed by multiple Text Displays.
*/
class FL_EXPORT Fl_Text_Display_mod: public Fl_Group {
public:
/**
text display cursor shapes enumeration
*/
enum {
NORMAL_CURSOR, /**< I-beam */
CARET_CURSOR, /**< caret under the text */
DIM_CURSOR, /**< dim I-beam */
BLOCK_CURSOR, /**< unfille box under the current character */
HEAVY_CURSOR /**< thick I-beam */
};
/**
the character position is the left edge of a character, whereas
the cursor is thought to be between the centers of two consecutive
characters.
*/
enum {
CURSOR_POS,
CHARACTER_POS
};
/**
drag types - they match Fl::event_clicks() so that single clicking to
start a collection selects by character, double clicking selects by
word and triple clicking selects by line.
*/
enum {
DRAG_NONE = -2,
DRAG_START_DND = -1,
DRAG_CHAR = 0,
DRAG_WORD = 1,
DRAG_LINE = 2
};
/**
wrap types - used in wrap_mode()
*/
enum {
WRAP_NONE, /**< don't wrap text at all */
WRAP_AT_COLUMN, /**< wrap text at the given text column */
WRAP_AT_PIXEL, /**< wrap text at a pixel position */
WRAP_AT_BOUNDS /**< wrap text so that it fits into the widget width */
};
friend void fl_text_drag_me(int pos, Fl_Text_Display_mod* d);
typedef void (*Unfinished_Style_Cb)(int, void *);
/**
This structure associates the color, font, andsize of a string to draw
with an attribute mask matching attr
*/
struct Style_Table_Entry {
Fl_Color color;
Fl_Font font;
Fl_Fontsize size;
unsigned attr;
};
Fl_Text_Display_mod(int X, int Y, int W, int H, const char *l = 0);
~Fl_Text_Display_mod();
virtual int handle(int e);
void buffer(Fl_Text_Buffer_mod* buf);
/**
Sets the current text buffer associated with the text widget.
Multiple text widgets can be associated with the same text buffer.
\param buf new text buffer
*/
void buffer(Fl_Text_Buffer_mod& buf) { buffer(&buf); }
/**
Gets the current text buffer associated with the text widget.
Multiple text widgets can be associated with the same text buffer.
\return current text buffer
*/
Fl_Text_Buffer_mod* buffer() const { return mBuffer; }
void redisplay_range(int start, int end);
void scroll(int topLineNum, int horizOffset);
void insert(const char* text);
void overstrike(const char* text);
void insert_position(int newPos);
/**
Gets the position of the text insertion cursor for text display.
\return insert position index into text buffer
*/
int insert_position() const { return mCursorPos; }
int position_to_xy(int pos, int* x, int* y) const;
int in_selection(int x, int y) const;
void show_insert_position();
int move_right();
int move_left();
int move_up();
int move_down();
int count_lines(int start, int end, bool start_pos_is_line_start) const;
int line_start(int pos) const;
int line_end(int startPos, bool startPosIsLineStart) const;
int skip_lines(int startPos, int nLines, bool startPosIsLineStart);
int rewind_lines(int startPos, int nLines);
void next_word(void);
void previous_word(void);
void show_cursor(int b = 1);
/**
Hides the text cursor.
*/
void hide_cursor() { show_cursor(0); }
void cursor_style(int style);
/**
Gets the text cursor color.
\return cursor color
*/
Fl_Color cursor_color() const {return mCursor_color;}
/**
Sets the text cursor color.
\param n new cursor color
*/
void cursor_color(Fl_Color n) {mCursor_color = n;}
/**
Gets the width/height of the scrollbars.
/return width of scrollbars
*/
int scrollbar_width() const { return scrollbar_width_; }
/**
Sets the width/height of the scrollbars.
\param W width of scrollbars
*/
void scrollbar_width(int W) { scrollbar_width_ = W; }
/**
Gets the scrollbar alignment type.
\return scrollbar alignment
*/
Fl_Align scrollbar_align() const { return scrollbar_align_; }
/**
Sets the scrollbar alignment type.
\param a new scrollbar alignment
*/
void scrollbar_align(Fl_Align a) { scrollbar_align_ = a; }
/**
Moves the insert position to the beginning of the current word.
\param pos start calculation at this index
\return beginning of the words
*/
int word_start(int pos) const { return buffer()->word_start(pos); }
/**
Moves the insert position to the end of the current word.
\param pos start calculation at this index
\return index of first character after the end of the word
*/
int word_end(int pos) const { return buffer()->word_end(pos); }
void highlight_data(Fl_Text_Buffer_mod *styleBuffer,
const Style_Table_Entry *styleTable,
int nStyles, char unfinishedStyle,
Unfinished_Style_Cb unfinishedHighlightCB,
void *cbArg);
int position_style(int lineStartPos, int lineLen, int lineIndex) const;
/**
\todo FIXME : get set methods pointing on shortcut_
have no effects as shortcut_ is unused in this class and derived!
\return the current shortcut key
*/
int shortcut() const {return shortcut_;}
/**
\todo FIXME : get set methods pointing on shortcut_
have no effects as shortcut_ is unused in this class and derived!
\param s the new shortcut key
*/
void shortcut(int s) {shortcut_ = s;}
/**
Gets the default font used when drawing text in the widget.
\return current text font face unless overridden by a style
*/
Fl_Font textfont() const {return textfont_;}
/**
Sets the default font used when drawing text in the widget.
\param s default text font face
*/
void textfont(Fl_Font s) {textfont_ = s; mColumnScale = 0;}
/**
Gets the default size of text in the widget.
\return current text height unless overridden by a style
*/
Fl_Fontsize textsize() const {return textsize_;}
/**
Sets the default size of text in the widget.
\param s new text size
*/
void textsize(Fl_Fontsize s) {textsize_ = s; mColumnScale = 0;}
/**
Gets the default color of text in the widget.
\return text color unless overridden by a style
*/
Fl_Color textcolor() const {return textcolor_;}
/**
Sets the default color of text in the widget.
\param n new text color
*/
void textcolor(Fl_Color n) {textcolor_ = n;}
int wrapped_column(int row, int column) const;
int wrapped_row(int row) const;
void wrap_mode(int wrap, int wrap_margin);
virtual void resize(int X, int Y, int W, int H);
/**
Convert an x pixel position into a column number.
\param x number of pixels from the left margin
\return an approximate column number based on the main font
*/
double x_to_col(double x) const;
/**
Convert a column number into an x pixel position.
\param col an approximate column number based on the main font
\return number of pixels from the left margin to the left of an
average sized character
*/
double col_to_x(double col) const;
protected:
// Most (all?) of this stuff should only be called from resize() or
// draw().
// Anything with "vline" indicates thats it deals with currently
// visible lines.
virtual void draw();
void draw_text(int X, int Y, int W, int H);
void draw_range(int start, int end);
void draw_cursor(int, int);
void draw_string(int style, int x, int y, int toX, const char *string,
int nChars) const;
void draw_vline(int visLineNum, int leftClip, int rightClip,
int leftCharIndex, int rightCharIndex);
int find_x(const char *s, int len, int style, int x) const;
enum {
DRAW_LINE,
FIND_INDEX,
FIND_INDEX_FROM_ZERO,
GET_WIDTH
};
int handle_vline(int mode,
int lineStart, int lineLen, int leftChar, int rightChar,
int topClip, int bottomClip,
int leftClip, int rightClip) const;
void draw_line_numbers(bool clearAll);
void clear_rect(int style, int x, int y, int width, int height) const;
void display_insert();
void offset_line_starts(int newTopLineNum);
void calc_line_starts(int startLine, int endLine);
void update_line_starts(int pos, int charsInserted, int charsDeleted,
int linesInserted, int linesDeleted, int *scrolled);
void calc_last_char();
int position_to_line( int pos, int* lineNum ) const;
double string_width(const char* string, int length, int style) const;
static void scroll_timer_cb(void*);
static void buffer_predelete_cb(int pos, int nDeleted, void* cbArg);
static void buffer_modified_cb(int pos, int nInserted, int nDeleted,
int nRestyled, const char* deletedText,
void* cbArg);
static void h_scrollbar_cb(Fl_Scrollbar* w, Fl_Text_Display_mod* d);
static void v_scrollbar_cb( Fl_Scrollbar* w, Fl_Text_Display_mod* d);
void update_v_scrollbar();
void update_h_scrollbar();
int measure_vline(int visLineNum) const;
int longest_vline() const;
int empty_vlines() const;
int vline_length(int visLineNum) const;
int xy_to_position(int x, int y, int PosType = CHARACTER_POS) const;
void xy_to_rowcol(int x, int y, int* row, int* column,
int PosType = CHARACTER_POS) const;
void maintain_absolute_top_line_number(int state);
int get_absolute_top_line_number() const;
void absolute_top_line_number(int oldFirstChar);
int maintaining_absolute_top_line_number() const;
void reset_absolute_top_line_number();
int position_to_linecol(int pos, int* lineNum, int* column) const;
int scroll_(int topLineNum, int horizOffset);
void extend_range_for_styles(int* start, int* end);
void find_wrap_range(const char *deletedText, int pos, int nInserted,
int nDeleted, int *modRangeStart, int *modRangeEnd,
int *linesInserted, int *linesDeleted);
void measure_deleted_lines(int pos, int nDeleted);
void wrapped_line_counter(Fl_Text_Buffer_mod *buf, int startPos, int maxPos,
int maxLines, bool startPosIsLineStart,
int styleBufOffset, int *retPos, int *retLines,
int *retLineStart, int *retLineEnd,
bool countLastLineMissingNewLine = true) const;
void find_line_end(int pos, bool start_pos_is_text_start, int *lineEnd,
int *nextLineStart) const;
double measure_proportional_character(const char *s, int colNum, int pos) const;
int wrap_uses_character(int lineEndPos) const;
static const int DEFAULT_TOP_MARGIN;
static const int DEFAULT_BOTTOM_MARGIN;
static const int DEFAULT_LEFT_MARGIN;
static const int DEFAULT_RIGHT_MARGIN;
int TOP_MARGIN, BOTTOM_MARGIN, LEFT_MARGIN, RIGHT_MARGIN;
int damage_range1_start, damage_range1_end;
int damage_range2_start, damage_range2_end;
int mCursorPos;
int mCursorOn;
int mCursorOldY; /* Y pos. of cursor for blanking */
int mCursorToHint; /* Tells the buffer modified callback
where to move the cursor, to reduce
the number of redraw calls */
int mCursorStyle; /* One of enum cursorStyles above */
int mCursorPreferredXPos; /* Pixel position for vert. cursor movement */
int mNVisibleLines; /* # of visible (displayed) lines */
int mNBufferLines; /* # of newlines in the buffer */
Fl_Text_Buffer_mod* mBuffer; /* Contains text to be displayed */
Fl_Text_Buffer_mod* mStyleBuffer; /* Optional parallel buffer containing
color and font information */
int mFirstChar, mLastChar; /* Buffer positions of first and last
displayed character (lastChar points
either to a newline or one character
beyond the end of the buffer) */
int mContinuousWrap; /* Wrap long lines when displaying */
int mFastDisplay; /* force continuous wrap and insertion of eol characters
used in FTextRX */
std::string s_text; /* current contents of line text buffer */
std::string s_style; /* current contents of line stype buffer */
int mWrapMarginPix; /* Margin in # of pixels for
wrapping in continuousWrap mode */
int* mLineStarts;
int mTopLineNum; /* Line number of top displayed line
of file (first line of file is 1) */
int mAbsTopLineNum; /* In continuous wrap mode, the line
number of the top line if the text
were not wrapped (note that this is
only maintained as needed). */
int mNeedAbsTopLineNum; /* Externally settable flag to continue
maintaining absTopLineNum even if
it isn't needed for line # display */
int mHorizOffset; /* Horizontal scroll pos. in pixels */
int mTopLineNumHint; /* Line number of top displayed line
of file (first line of file is 1) */
int mHorizOffsetHint; /* Horizontal scroll pos. in pixels */
int mNStyles; /* Number of entries in styleTable */
const Style_Table_Entry *mStyleTable; /* Table of fonts and colors for
coloring/syntax-highlighting */
char mUnfinishedStyle; /* Style buffer entry which triggers
on-the-fly reparsing of region */
Unfinished_Style_Cb mUnfinishedHighlightCB; /* Callback to parse "unfinished" */
/* regions */
void* mHighlightCBArg; /* Arg to unfinishedHighlightCB */
int mMaxsize;
int mSuppressResync; /* Suppress resynchronization of line
starts during buffer updates */
int mNLinesDeleted; /* Number of lines deleted during
buffer modification (only used
when resynchronization is suppressed) */
int mModifyingTabDistance; /* Whether tab distance is being
modified */
mutable double mColumnScale; /* Width in pixels of an average character. This
value is calculated as needed (lazy eval); it
needs to be mutable so that it can be calculated
within a method marked as "const" */
Fl_Color mCursor_color;
Fl_Scrollbar* mHScrollBar;
Fl_Scrollbar* mVScrollBar;
int scrollbar_width_;
Fl_Align scrollbar_align_;
int dragPos, dragType, dragging;
int display_insert_position_hint;
struct { int x, y, w, h; } text_area;
int shortcut_;
Fl_Font textfont_;
Fl_Fontsize textsize_;
Fl_Color textcolor_;
// The following are not presently used from the original NEdit code,
// but are being put here so that future versions of Fl_Text_Display_mod
// can implement line numbers without breaking binary compatibility.
/* Line number margin and width */
int mLineNumLeft, mLineNumWidth;
};
#endif
//
// End of "$Id: Fl_Text_Display_mod.H 8306 2011-01-24 17:04:22Z matt $".
//

View file

@ -1,27 +1,145 @@
// ----------------------------------------------------------------------------
// Copyright (C) 2014
// David Freese, W1HKJ
//
// This file is part of flmsg
// "$Id: Fl_Text_Editor_mod.H 7903 2010-11-28 21:06:39Z matt $"
//
// flrig is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
// Header file for Fl_Text_Editor_mod class.
//
// flrig is distributed in the hope that it will be useful,
// Copyright 2001-2010 by Bill Spitzak and others.
// Original code Copyright Mark Edel. Permission to distribute under
// the LGPL for the FLTK library granted by Mark Edel.
//
// 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 General Public License for more details.
// 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 General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
// 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.
// 51 Franklin Street, Fifth Floor
// Boston, MA 02110-1301 USA.
//
// Please report all bugs and problems on the following page:
//
// http://www.fltk.org/str.php
//
/* \file
Fl_Text_Editor_mod widget . */
#ifndef Fl_Text_Editor_mod_H
#define Fl_Text_Editor_mod_H
#include "Fl_Text_Display_mod.H"
#include <config.h>
#if FLMSG_FLTK_API_MINOR < 3
# include "Fl_Text_Editor_mod_1_1.H"
#else
# include "Fl_Text_Editor_mod_1_3.H"
// key will match in any state
#define Fl_Text_Editor_mod_ANY_STATE (-1L)
/**
This is the FLTK text editor widget. It allows the user to
edit multiple lines of text and supports highlighting and
scrolling. The buffer that is displayed in the widget is managed
by the Fl_Text_Buffer_mod
class.
*/
class FL_EXPORT Fl_Text_Editor_mod : public Fl_Text_Display_mod {
public:
/** Key function binding callback type */
typedef int (*Key_Func)(int key, Fl_Text_Editor_mod* editor);
/** Simple linked list associating a key/state to a function */
struct Key_Binding {
int key; ///< the key pressed
int state; ///< the state of key modifiers
Key_Func function; ///< associated function
Key_Binding* next; ///< next key binding in the list
};
Fl_Text_Editor_mod(int X, int Y, int W, int H, const char* l = 0);
~Fl_Text_Editor_mod() { remove_all_key_bindings(); }
virtual int handle(int e);
/**
Sets the current insert mode; if non-zero, new text
is inserted before the current cursor position. Otherwise, new
text replaces text at the current cursor position.
*/
void insert_mode(int b) { insert_mode_ = b; }
/**
Gets the current insert mode; if non-zero, new text
is inserted before the current cursor position. Otherwise, new
text replaces text at the current cursor position.
*/
int insert_mode() { return insert_mode_; }
void add_key_binding(int key, int state, Key_Func f, Key_Binding** list);
/** Adds a key of state "state" with the function "function" */
void add_key_binding(int key, int state, Key_Func f)
{ add_key_binding(key, state, f, &key_bindings); }
void remove_key_binding(int key, int state, Key_Binding** list);
/** Removes the key binding associated with the key "key" of state "state". */
void remove_key_binding(int key, int state)
{ remove_key_binding(key, state, &key_bindings); }
void remove_all_key_bindings(Key_Binding** list);
/** Removes all of the key bindings associated with the text editor or list. */
void remove_all_key_bindings() { remove_all_key_bindings(&key_bindings); }
void add_default_key_bindings(Key_Binding** list);
Key_Func bound_key_function(int key, int state, Key_Binding* list);
/** Returns the function associated with a key binding. */
Key_Func bound_key_function(int key, int state)
{ return bound_key_function(key, state, key_bindings); }
/** Sets the default key function for unassigned keys. */
void default_key_function(Key_Func f) { default_key_function_ = f; }
// functions for the built in default bindings
static int kf_default(int c, Fl_Text_Editor_mod* e);
static int kf_ignore(int c, Fl_Text_Editor_mod* e);
static int kf_backspace(int c, Fl_Text_Editor_mod* e);
static int kf_enter(int c, Fl_Text_Editor_mod* e);
static int kf_move(int c, Fl_Text_Editor_mod* e);
static int kf_shift_move(int c, Fl_Text_Editor_mod* e);
static int kf_ctrl_move(int c, Fl_Text_Editor_mod* e);
static int kf_c_s_move(int c, Fl_Text_Editor_mod* e);
static int kf_meta_move(int c, Fl_Text_Editor_mod* e);
static int kf_m_s_move(int c, Fl_Text_Editor_mod* e);
static int kf_home(int, Fl_Text_Editor_mod* e);
static int kf_end(int c, Fl_Text_Editor_mod* e);
static int kf_left(int c, Fl_Text_Editor_mod* e);
static int kf_up(int c, Fl_Text_Editor_mod* e);
static int kf_right(int c, Fl_Text_Editor_mod* e);
static int kf_down(int c, Fl_Text_Editor_mod* e);
static int kf_page_up(int c, Fl_Text_Editor_mod* e);
static int kf_page_down(int c, Fl_Text_Editor_mod* e);
static int kf_insert(int c, Fl_Text_Editor_mod* e);
static int kf_delete(int c, Fl_Text_Editor_mod* e);
static int kf_copy(int c, Fl_Text_Editor_mod* e);
static int kf_cut(int c, Fl_Text_Editor_mod* e);
static int kf_paste(int c, Fl_Text_Editor_mod* e);
static int kf_select_all(int c, Fl_Text_Editor_mod* e);
static int kf_undo(int c, Fl_Text_Editor_mod* e);
protected:
int handle_key();
void maybe_do_callback();
#ifndef FL_DOXYGEN
int insert_mode_;
Key_Binding* key_bindings;
static Key_Binding* global_key_bindings;
Key_Func default_key_function_;
#endif
};
#endif
//
// End of "$Id: Fl_Text_Editor_mod.H 7903 2010-11-28 21:06:39Z matt $".
//

View file

@ -1,108 +0,0 @@
//
// "$Id: Fl_Text_Editor.H 4288 2005-04-16 00:13:17Z mike $"
//
// Header file for Fl_Text_Editor class.
//
// Copyright 2001-2005 by Bill Spitzak and others.
// Original code Copyright Mark Edel. Permission to distribute under
// the LGPL for the FLTK library granted by Mark Edel.
// ----------------------------------------------------------------------------
// Copyright (C) 2014
// David Freese, W1HKJ
//
// This file is part of flmsg
//
// flrig is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// flrig 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#ifndef FL_TEXT_EDITOR_MOD_H
#define FL_TEXT_EDITOR_MOD_H
#include "Fl_Text_Display_mod.H"
// key will match in any state
#define FL_TEXT_EDITOR_ANY_STATE (-1L)
class Fl_Text_Editor_mod : public Fl_Text_Display_mod {
public:
typedef int (*Key_Func)(int key, Fl_Text_Editor_mod* editor);
struct Key_Binding {
int key;
int state;
Key_Func function;
Key_Binding* next;
};
Fl_Text_Editor_mod(int X, int Y, int W, int H, const char* l = 0);
~Fl_Text_Editor_mod() { remove_all_key_bindings(); }
virtual int handle(int e);
void insert_mode(int b) { insert_mode_ = b; }
int insert_mode() { return insert_mode_; }
void add_key_binding(int key, int state, Key_Func f, Key_Binding** list);
void add_key_binding(int key, int state, Key_Func f)
{ add_key_binding(key, state, f, &key_bindings); }
void remove_key_binding(int key, int state, Key_Binding** list);
void remove_key_binding(int key, int state)
{ remove_key_binding(key, state, &key_bindings); }
void remove_all_key_bindings(Key_Binding** list);
void remove_all_key_bindings() { remove_all_key_bindings(&key_bindings); }
void add_default_key_bindings(Key_Binding** list);
Key_Func bound_key_function(int key, int state, Key_Binding* list);
Key_Func bound_key_function(int key, int state)
{ return bound_key_function(key, state, key_bindings); }
void default_key_function(Key_Func f) { default_key_function_ = f; }
// functions for the built in default bindings
static int kf_default(int c, Fl_Text_Editor_mod* e);
static int kf_ignore(int c, Fl_Text_Editor_mod* e);
static int kf_backspace(int c, Fl_Text_Editor_mod* e);
static int kf_enter(int c, Fl_Text_Editor_mod* e);
static int kf_move(int c, Fl_Text_Editor_mod* e);
static int kf_shift_move(int c, Fl_Text_Editor_mod* e);
static int kf_ctrl_move(int c, Fl_Text_Editor_mod* e);
static int kf_c_s_move(int c, Fl_Text_Editor_mod* e);
static int kf_home(int, Fl_Text_Editor_mod* e);
static int kf_end(int c, Fl_Text_Editor_mod* e);
static int kf_left(int c, Fl_Text_Editor_mod* e);
static int kf_up(int c, Fl_Text_Editor_mod* e);
static int kf_right(int c, Fl_Text_Editor_mod* e);
static int kf_down(int c, Fl_Text_Editor_mod* e);
static int kf_page_up(int c, Fl_Text_Editor_mod* e);
static int kf_page_down(int c, Fl_Text_Editor_mod* e);
static int kf_insert(int c, Fl_Text_Editor_mod* e);
static int kf_delete(int c, Fl_Text_Editor_mod* e);
static int kf_copy(int c, Fl_Text_Editor_mod* e);
static int kf_cut(int c, Fl_Text_Editor_mod* e);
static int kf_paste(int c, Fl_Text_Editor_mod* e);
static int kf_select_all(int c, Fl_Text_Editor_mod* e);
static int kf_undo(int c, Fl_Text_Editor_mod* e);
protected:
int handle_key();
void maybe_do_callback();
int insert_mode_;
Key_Binding* key_bindings;
static Key_Binding* global_key_bindings;
Key_Func default_key_function_;
};
#endif
//
// End of "$Id: Fl_Text_Editor.H 4288 2005-04-16 00:13:17Z mike $".
//

View file

@ -1,141 +0,0 @@
//
// "$Id: Fl_Text_Editor_mod.H 7903 2010-11-28 21:06:39Z matt $"
//
// Header file for Fl_Text_Editor_mod class.
//
// Copyright 2001-2010 by Bill Spitzak and others.
// Original code Copyright Mark Edel. Permission to distribute under
// the LGPL for the FLTK library granted by Mark Edel.
//
// ----------------------------------------------------------------------------
// Copyright (C) 2014
// David Freese, W1HKJ
//
// This file is part of flmsg
//
// flrig is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// flrig 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
/* \file
Fl_Text_Editor_mod widget . */
#ifndef Fl_Text_Editor_mod_H
#define Fl_Text_Editor_mod_H
#include "Fl_Text_Display_mod.H"
// key will match in any state
#define Fl_Text_Editor_mod_ANY_STATE (-1L)
/**
This is the FLTK text editor widget. It allows the user to
edit multiple lines of text and supports highlighting and
scrolling. The buffer that is displayed in the widget is managed
by the Fl_Text_Buffer_mod
class.
*/
class FL_EXPORT Fl_Text_Editor_mod : public Fl_Text_Display_mod {
public:
/** Key function binding callback type */
typedef int (*Key_Func)(int key, Fl_Text_Editor_mod* editor);
/** Simple linked list associating a key/state to a function */
struct Key_Binding {
int key; ///< the key pressed
int state; ///< the state of key modifiers
Key_Func function; ///< associated function
Key_Binding* next; ///< next key binding in the list
};
Fl_Text_Editor_mod(int X, int Y, int W, int H, const char* l = 0);
~Fl_Text_Editor_mod() { remove_all_key_bindings(); }
virtual int handle(int e);
/**
Sets the current insert mode; if non-zero, new text
is inserted before the current cursor position. Otherwise, new
text replaces text at the current cursor position.
*/
void insert_mode(int b) { insert_mode_ = b; }
/**
Gets the current insert mode; if non-zero, new text
is inserted before the current cursor position. Otherwise, new
text replaces text at the current cursor position.
*/
int insert_mode() { return insert_mode_; }
void add_key_binding(int key, int state, Key_Func f, Key_Binding** list);
/** Adds a key of state "state" with the function "function" */
void add_key_binding(int key, int state, Key_Func f)
{ add_key_binding(key, state, f, &key_bindings); }
void remove_key_binding(int key, int state, Key_Binding** list);
/** Removes the key binding associated with the key "key" of state "state". */
void remove_key_binding(int key, int state)
{ remove_key_binding(key, state, &key_bindings); }
void remove_all_key_bindings(Key_Binding** list);
/** Removes all of the key bindings associated with the text editor or list. */
void remove_all_key_bindings() { remove_all_key_bindings(&key_bindings); }
void add_default_key_bindings(Key_Binding** list);
Key_Func bound_key_function(int key, int state, Key_Binding* list);
/** Returns the function associated with a key binding. */
Key_Func bound_key_function(int key, int state)
{ return bound_key_function(key, state, key_bindings); }
/** Sets the default key function for unassigned keys. */
void default_key_function(Key_Func f) { default_key_function_ = f; }
// functions for the built in default bindings
static int kf_default(int c, Fl_Text_Editor_mod* e);
static int kf_ignore(int c, Fl_Text_Editor_mod* e);
static int kf_backspace(int c, Fl_Text_Editor_mod* e);
static int kf_enter(int c, Fl_Text_Editor_mod* e);
static int kf_move(int c, Fl_Text_Editor_mod* e);
static int kf_shift_move(int c, Fl_Text_Editor_mod* e);
static int kf_ctrl_move(int c, Fl_Text_Editor_mod* e);
static int kf_c_s_move(int c, Fl_Text_Editor_mod* e);
static int kf_meta_move(int c, Fl_Text_Editor_mod* e);
static int kf_m_s_move(int c, Fl_Text_Editor_mod* e);
static int kf_home(int, Fl_Text_Editor_mod* e);
static int kf_end(int c, Fl_Text_Editor_mod* e);
static int kf_left(int c, Fl_Text_Editor_mod* e);
static int kf_up(int c, Fl_Text_Editor_mod* e);
static int kf_right(int c, Fl_Text_Editor_mod* e);
static int kf_down(int c, Fl_Text_Editor_mod* e);
static int kf_page_up(int c, Fl_Text_Editor_mod* e);
static int kf_page_down(int c, Fl_Text_Editor_mod* e);
static int kf_insert(int c, Fl_Text_Editor_mod* e);
static int kf_delete(int c, Fl_Text_Editor_mod* e);
static int kf_copy(int c, Fl_Text_Editor_mod* e);
static int kf_cut(int c, Fl_Text_Editor_mod* e);
static int kf_paste(int c, Fl_Text_Editor_mod* e);
static int kf_select_all(int c, Fl_Text_Editor_mod* e);
static int kf_undo(int c, Fl_Text_Editor_mod* e);
protected:
int handle_key();
void maybe_do_callback();
#ifndef FL_DOXYGEN
int insert_mode_;
Key_Binding* key_bindings;
static Key_Binding* global_key_bindings;
Key_Func default_key_function_;
#endif
};
#endif
//
// End of "$Id: Fl_Text_Editor_mod.H 7903 2010-11-28 21:06:39Z matt $".
//

View file

@ -2,14 +2,14 @@
// Copyright (C) 2014
// David Freese, W1HKJ
//
// This file is part of flmsg
// This file is part of fldigi
//
// flrig is free software; you can redistribute it and/or modify
// fldigi is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// flrig is distributed in the hope that it will be useful,
// fldigi 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 General Public License for more details.
@ -23,11 +23,27 @@
#include <FL/Fl_Input.H>
#include "config.h"
class Fl_Input2 : public Fl_Input
{
private:
int ascii_cnt; // restart the numeric keypad entries.
int ascii_chr; // character value of ASCII > 0x80
int handle_key_ascii(int key);
char *utf8text;
int utf8cnt;
public:
Fl_Input2(int x, int y, int w, int h, const char* l = 0);
int handle(int event);
#if FLMSG_FLTK_API_MINOR > 3
int position() { return Fl_Input::insert_position(); }
int position(int p, int m) { return Fl_Input::insert_position(p, m); }
int position(int p) { return Fl_Input::insert_position(p, p); }
#endif
};
#endif // FL_INPUT2_

View file

@ -7,7 +7,7 @@
// Copyright (C) 2008-2009
// Dave Freese, W1HKJ
//
// This file is part of flmsg.
// This file is part of FLAMP.
//
// This is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@ -27,7 +27,6 @@
#include <config.h>
#include <cstring>
#include <string>
#include <cstdlib>
#include <cstdio>
#include <cmath>
@ -54,6 +53,7 @@
#include "debug.h"
/// FTextBase constructor.
/// Word wrapping is enabled by default at column 80, but see \c reset_wrap_col.
/// @param x
@ -62,15 +62,9 @@
/// @param h
/// @param l
#if flmsg_FLTK_API_MAJOR == 1 && flmsg_FLTK_API_MINOR < 3
FTextBase::FTextBase(int x, int y, int w, int h, const char *l)
: Fl_Text_Editor_mod(x, y, w, h, l),
wrap(true), wrap_col(80), max_lines(0), scroll_hint(false)
#else
FTextBase::FTextBase(int x, int y, int w, int h, const char *l)
: Fl_Text_Editor_mod(x, y, w, h, l),
wrap(WRAP_AT_BOUNDS), wrap_col(80), max_lines(0), scroll_hint(false)
#endif
{
oldw = oldh = olds = -1;
oldf = (Fl_Font)-1;
@ -149,15 +143,9 @@ void FTextBase::add(unsigned char c, int attr)
void FTextBase::set_word_wrap(bool b)
{
#if flmsg_FLTK_API_MAJOR == 1 && flmsg_FLTK_API_MINOR < 3
if ((wrap = b)) wrap_mode(true, 0);
else wrap_mode(false, 0);
show_insert_position();
#else
if ((wrap = b)) wrap_mode(WRAP_AT_BOUNDS, 0);
else wrap_mode(WRAP_NONE, 0);
show_insert_position();
#endif
}
void FTextBase::setFont(Fl_Font f, int attr)
@ -207,7 +195,6 @@ void FTextBase::resize(int X, int Y, int W, int H)
if (need_wrap_reset)
reset_wrap_col();
#if flmsg_FLTK_API_MAJOR == 1 && flmsg_FLTK_API_MINOR == 3
TOP_MARGIN = DEFAULT_TOP_MARGIN;
int r = H - Fl::box_dh(box()) - TOP_MARGIN - BOTTOM_MARGIN;
if (mHScrollBar->visible())
@ -217,16 +204,7 @@ void FTextBase::resize(int X, int Y, int W, int H)
//printf("H %d, textsize %d, lines %d, extra %d\n", r, msize, r / msize, r % msize);
if (r %= msize)
TOP_MARGIN += r;
#else
if (need_margin_reset && textsize() > 0) {
TOP_MARGIN = DEFAULT_TOP_MARGIN;
int r = H - Fl::box_dh(box()) - TOP_MARGIN - BOTTOM_MARGIN;
if (mHScrollBar->visible())
r -= scrollbar_width();
if (r %= textsize())
TOP_MARGIN += r;
}
#endif
if (scroll_hint) {
mTopLineNumHint = mNBufferLines;
mHorizOffsetHint = 0;
@ -911,7 +889,7 @@ void FTextEdit::changed_cb(int pos, int nins, int ndel, int nsty, const char *dt
}
else if (nsty > 0) // restyled, e.g. selected, text
return e->buffer_modified_cb(pos, nins, ndel, nsty, dtext, e);
// No changes, e.g., a paste with an empty clipboard.
return;
}
@ -933,9 +911,9 @@ void FTextEdit::changed_cb(int pos, int nins, int ndel, int nsty, const char *dt
}
else if (ndel > 0)
e->sbuf->remove(pos, pos + ndel);
e->sbuf->select(pos, pos + nins - ndel);
e->buffer_modified_cb(pos, nins, ndel, nsty, dtext, e);
// We may need to scroll if the text was inserted by the
// add() methods, e.g. by a macro

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,27 +1,667 @@
// ----------------------------------------------------------------------------
// Copyright (C) 2014
// David Freese, W1HKJ
//
// This file is part of flmsg
// "$Id: Fl_Text_Editor_mod.cxx 8034 2010-12-15 12:21:55Z AlbrechtS $"
//
// flrig is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
// Copyright 2001-2010 by Bill Spitzak and others.
// Original code Copyright Mark Edel. Permission to distribute under
// the LGPL for the FLTK library granted by Mark Edel.
//
// flrig is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// 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 General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
// 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.
// 51 Franklin Street, Fifth Floor
// Boston, MA 02110-1301 USA.
//
// Please report all bugs and problems on the following page:
//
// http://www.fltk.org/str.php
//
#include <stdio.h>
#include <stdlib.h>
#include "missing_strings.h"
#include <ctype.h>
#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include <FL/fl_ask.H>
#include "Fl_Text_Editor_mod.H"
#include <config.h>
#include "debug.h"
#if FLMSG_FLTK_API_MINOR < 3
# include "Fl_Text_Editor_mod_1_1.cxx"
#else
# include "Fl_Text_Editor_mod_1_3.cxx"
#if FLCLUSTER_FLTK_API_MAJOR == 1 && FLCLUSTER_FLTK_API_MINOR < 3
# error "FLTK versions less then 1.3 are no longer supported"
#endif
/* Keyboard Control Matrix
key\modifier plain Ctrl Alt Meta
---------------------------------------
left 1/1 13/9 0/13 0/9
right 2/2 14/10 0/14 0/10
up 3/19 21/7 0/15 0/17
down 4/20 22/8 0/16 0/18
home 9/5 17/0 0/0 0/0
end 10/6 18/0 0/0 0/0
page up 11/7 23/0 0/11 0/0
page down 12/8 24/0 0/12 0/0
(FLTK action / OS X action)
(adding the shift key extends the selection, all other combinations are no-op)
0: no-op
1: move cursor to the left, at line beginning wrap to end of prev line, at doc start no-op
2: move cursor to the right, at line end move to beginning of the next line, at doc end no-op
3: move cursor up, at doc top no-op
4: move cursor down, at doc bottom no-op
5: scroll display to top of text (cursor unchanged)
6: scroll display to end of text (cursor unchanged)
7: scroll text down one page (cursor unchanged)
8: scroll text up one page (cursor unchanged)
9: move cursor to beginning of line
10: move cursor to end of line
11: move cursor up one page and scroll down
12: move cursor down one page and scroll up
13: move to the beginning of the word or the previous word
14: move to the end of the word or the next word
15: if start of line: start of prev line, else start of this line
16: if end of line: end of next line, else end of this line
17: move cursor to the beginning of the document
18: move cursor to the end of the document
19: move cursor up, at doc top: home, at doc start: no-op)
20: move cursor down, at doc bot: end, at doc end: no-op)
21: scroll text down one line (cursor unchanged)
22: scroll text up one line (cursor unchanged)
23: move cursor to the beginning of the top of the screen
24: move cursor to the beginning of the bottom of the window
*/
/** The constructor creates a new text editor widget.*/
Fl_Text_Editor_mod::Fl_Text_Editor_mod(int X, int Y, int W, int H, const char* l)
: Fl_Text_Display_mod(X, Y, W, H, l) {
mCursorOn = 1;
insert_mode_ = 1;
key_bindings = 0;
// handle the default key bindings
add_default_key_bindings(&key_bindings);
// handle everything else
default_key_function(kf_default);
}
#ifndef FL_DOXYGEN
Fl_Text_Editor_mod::Key_Binding* Fl_Text_Editor_mod::global_key_bindings = 0;
#endif
// These are the default key bindings every widget should start with
static struct {
int key;
int state;
Fl_Text_Editor_mod::Key_Func func;
} default_key_bindings[] = {
{ FL_Escape, Fl_Text_Editor_mod_ANY_STATE, Fl_Text_Editor_mod::kf_ignore },
{ FL_Enter, Fl_Text_Editor_mod_ANY_STATE, Fl_Text_Editor_mod::kf_enter },
{ FL_KP_Enter, Fl_Text_Editor_mod_ANY_STATE, Fl_Text_Editor_mod::kf_enter },
{ FL_BackSpace, Fl_Text_Editor_mod_ANY_STATE, Fl_Text_Editor_mod::kf_backspace },
{ FL_Insert, Fl_Text_Editor_mod_ANY_STATE, Fl_Text_Editor_mod::kf_insert },
{ FL_Delete, Fl_Text_Editor_mod_ANY_STATE, Fl_Text_Editor_mod::kf_delete },
{ FL_Home, 0, Fl_Text_Editor_mod::kf_move },
{ FL_End, 0, Fl_Text_Editor_mod::kf_move },
{ FL_Left, 0, Fl_Text_Editor_mod::kf_move },
{ FL_Up, 0, Fl_Text_Editor_mod::kf_move },
{ FL_Right, 0, Fl_Text_Editor_mod::kf_move },
{ FL_Down, 0, Fl_Text_Editor_mod::kf_move },
{ FL_Page_Up, 0, Fl_Text_Editor_mod::kf_move },
{ FL_Page_Down, 0, Fl_Text_Editor_mod::kf_move },
{ FL_Home, FL_SHIFT, Fl_Text_Editor_mod::kf_shift_move },
{ FL_End, FL_SHIFT, Fl_Text_Editor_mod::kf_shift_move },
{ FL_Left, FL_SHIFT, Fl_Text_Editor_mod::kf_shift_move },
{ FL_Up, FL_SHIFT, Fl_Text_Editor_mod::kf_shift_move },
{ FL_Right, FL_SHIFT, Fl_Text_Editor_mod::kf_shift_move },
{ FL_Down, FL_SHIFT, Fl_Text_Editor_mod::kf_shift_move },
{ FL_Page_Up, FL_SHIFT, Fl_Text_Editor_mod::kf_shift_move },
{ FL_Page_Down, FL_SHIFT, Fl_Text_Editor_mod::kf_shift_move },
{ FL_Home, FL_CTRL, Fl_Text_Editor_mod::kf_ctrl_move },
{ FL_End, FL_CTRL, Fl_Text_Editor_mod::kf_ctrl_move },
{ FL_Left, FL_CTRL, Fl_Text_Editor_mod::kf_ctrl_move },
{ FL_Up, FL_CTRL, Fl_Text_Editor_mod::kf_ctrl_move },
{ FL_Right, FL_CTRL, Fl_Text_Editor_mod::kf_ctrl_move },
{ FL_Down, FL_CTRL, Fl_Text_Editor_mod::kf_ctrl_move },
{ FL_Page_Up, FL_CTRL, Fl_Text_Editor_mod::kf_ctrl_move },
{ FL_Page_Down, FL_CTRL, Fl_Text_Editor_mod::kf_ctrl_move },
{ FL_Home, FL_CTRL|FL_SHIFT, Fl_Text_Editor_mod::kf_c_s_move },
{ FL_End, FL_CTRL|FL_SHIFT, Fl_Text_Editor_mod::kf_c_s_move },
{ FL_Left, FL_CTRL|FL_SHIFT, Fl_Text_Editor_mod::kf_c_s_move },
{ FL_Up, FL_CTRL|FL_SHIFT, Fl_Text_Editor_mod::kf_c_s_move },
{ FL_Right, FL_CTRL|FL_SHIFT, Fl_Text_Editor_mod::kf_c_s_move },
{ FL_Down, FL_CTRL|FL_SHIFT, Fl_Text_Editor_mod::kf_c_s_move },
{ FL_Page_Up, FL_CTRL|FL_SHIFT, Fl_Text_Editor_mod::kf_c_s_move },
{ FL_Page_Down, FL_CTRL|FL_SHIFT, Fl_Text_Editor_mod::kf_c_s_move },
//{ FL_Clear, 0, Fl_Text_Editor_mod::delete_to_eol },
{ 'z', FL_CTRL, Fl_Text_Editor_mod::kf_undo },
{ '/', FL_CTRL, Fl_Text_Editor_mod::kf_undo },
{ FL_Home, FL_SHIFT, Fl_Text_Editor_mod::kf_undo },
{ 'x', FL_CTRL, Fl_Text_Editor_mod::kf_cut },
{ FL_Delete, FL_SHIFT, Fl_Text_Editor_mod::kf_cut },
{ 'c', FL_CTRL, Fl_Text_Editor_mod::kf_copy },
{ FL_Insert, FL_CTRL, Fl_Text_Editor_mod::kf_copy },
{ 'v', FL_CTRL, Fl_Text_Editor_mod::kf_paste },
{ FL_Insert, FL_SHIFT, Fl_Text_Editor_mod::kf_paste },
{ 'a', FL_CTRL, Fl_Text_Editor_mod::kf_select_all },
#ifdef __APPLE__
// Define CMD+key accelerators...
{ 'z', FL_COMMAND, Fl_Text_Editor_mod::kf_undo },
{ 'x', FL_COMMAND, Fl_Text_Editor_mod::kf_cut },
{ 'c', FL_COMMAND, Fl_Text_Editor_mod::kf_copy },
{ 'v', FL_COMMAND, Fl_Text_Editor_mod::kf_paste },
{ 'a', FL_COMMAND, Fl_Text_Editor_mod::kf_select_all },
{ FL_Left, FL_COMMAND, Fl_Text_Editor_mod::kf_meta_move },
{ FL_Right, FL_COMMAND, Fl_Text_Editor_mod::kf_meta_move },
{ FL_Up, FL_COMMAND, Fl_Text_Editor_mod::kf_meta_move },
{ FL_Down, FL_COMMAND, Fl_Text_Editor_mod::kf_meta_move },
{ FL_Left, FL_COMMAND|FL_SHIFT, Fl_Text_Editor_mod::kf_m_s_move },
{ FL_Right, FL_COMMAND|FL_SHIFT, Fl_Text_Editor_mod::kf_m_s_move },
{ FL_Up, FL_COMMAND|FL_SHIFT, Fl_Text_Editor_mod::kf_m_s_move },
{ FL_Down, FL_COMMAND|FL_SHIFT, Fl_Text_Editor_mod::kf_m_s_move },
#endif // __APPLE__
{ 0, 0, 0 }
};
/** Adds all of the default editor key bindings to the specified key binding list.*/
void Fl_Text_Editor_mod::add_default_key_bindings(Key_Binding** list) {
for (int i = 0; default_key_bindings[i].key; i++) {
add_key_binding(default_key_bindings[i].key,
default_key_bindings[i].state,
default_key_bindings[i].func,
list);
}
}
/** Returns the function associated with a key binding.*/
Fl_Text_Editor_mod::Key_Func Fl_Text_Editor_mod::bound_key_function(int key, int state, Key_Binding* list) {
Key_Binding* cur;
if (!list) return 0;
for (cur = list; cur; cur = cur->next)
if (cur->key == key)
if (cur->state == Fl_Text_Editor_mod_ANY_STATE || cur->state == state)
break;
if (!cur) return 0;
return cur->function;
}
/** Removes all of the key bindings associated with the text editor or list.*/
void Fl_Text_Editor_mod::remove_all_key_bindings(Key_Binding** list) {
Key_Binding *cur, *next;
for (cur = *list; cur; cur = next) {
next = cur->next;
delete cur;
}
*list = 0;
}
/** Removes the key binding associated with the key "key" of state "state" */
void Fl_Text_Editor_mod::remove_key_binding(int key, int state, Key_Binding** list) {
Key_Binding *cur, *last = 0;
for (cur = *list; cur; last = cur, cur = cur->next)
if (cur->key == key && cur->state == state) break;
if (!cur) return;
if (last) last->next = cur->next;
else *list = cur->next;
delete cur;
}
/** Adds a key of state "state" with the function "function" */
void Fl_Text_Editor_mod::add_key_binding(int key, int state, Key_Func function,
Key_Binding** list) {
Key_Binding* kb = new Key_Binding;
kb->key = key;
kb->state = state;
kb->function = function;
kb->next = *list;
*list = kb;
}
////////////////////////////////////////////////////////////////
static void kill_selection(Fl_Text_Editor_mod* e) {
if (e->buffer()->selected()) {
e->insert_position(e->buffer()->primary_selection()->start());
e->buffer()->remove_selection();
}
}
/** Inserts the text associated with the key */
int Fl_Text_Editor_mod::kf_default(int c, Fl_Text_Editor_mod* e) {
// FIXME: this function is a mess! Fix this!
if (!c || (!isprint(c) && c != '\t')) return 0;
char s[2] = "\0";
s[0] = (char)c;
kill_selection(e);
if (e->insert_mode()) e->insert(s);
else e->overstrike(s);
e->show_insert_position();
e->set_changed();
if (e->when()&FL_WHEN_CHANGED) e->do_callback();
return 1;
}
/** Ignores the keypress */
int Fl_Text_Editor_mod::kf_ignore(int, Fl_Text_Editor_mod*) {
return 0; // don't handle
}
/** Does a backspace in the current buffer.*/
int Fl_Text_Editor_mod::kf_backspace(int, Fl_Text_Editor_mod* e) {
if (!e->buffer()->selected() && e->move_left()) {
int p1 = e->insert_position();
int p2 = e->buffer()->next_char(p1);
e->buffer()->select(p1, p2);
}
kill_selection(e);
e->show_insert_position();
e->set_changed();
if (e->when()&FL_WHEN_CHANGED) e->do_callback();
return 1;
}
/** Inserts a newline at the current cursor position */
int Fl_Text_Editor_mod::kf_enter(int, Fl_Text_Editor_mod* e) {
kill_selection(e);
e->insert("\n");
e->show_insert_position();
e->set_changed();
if (e->when()&FL_WHEN_CHANGED) e->do_callback();
return 1;
}
extern void fl_text_drag_me(int pos, Fl_Text_Display_mod* d);
/** Moves the text cursor in the direction indicated by key c.*/
int Fl_Text_Editor_mod::kf_move(int c, Fl_Text_Editor_mod* e) {
int i;
int selected = e->buffer()->selected();
if (!selected)
e->dragPos = e->insert_position();
e->buffer()->unselect();
Fl::copy("", 0, 0);
switch (c) {
case FL_Home:
e->insert_position(e->buffer()->line_start(e->insert_position()));
break;
case FL_End:
e->insert_position(e->buffer()->line_end(e->insert_position()));
break;
case FL_Left:
e->move_left();
break;
case FL_Right:
e->move_right();
break;
case FL_Up:
e->move_up();
break;
case FL_Down:
e->move_down();
break;
case FL_Page_Up:
for (i = 0; i < e->mNVisibleLines - 1; i++) e->move_up();
break;
case FL_Page_Down:
for (i = 0; i < e->mNVisibleLines - 1; i++) e->move_down();
break;
}
e->show_insert_position();
return 1;
}
/** Extends the current selection in the direction of key c.*/
int Fl_Text_Editor_mod::kf_shift_move(int c, Fl_Text_Editor_mod* e) {
kf_move(c, e);
fl_text_drag_me(e->insert_position(), e);
char *copy = e->buffer()->selection_text();
if (copy) {
Fl::copy(copy, strlen(copy), 0);
free(copy);
}
return 1;
}
/** Moves the current text cursor in the direction indicated by control key */
int Fl_Text_Editor_mod::kf_ctrl_move(int c, Fl_Text_Editor_mod* e) {
if (!e->buffer()->selected())
e->dragPos = e->insert_position();
if (c != FL_Up && c != FL_Down) {
e->buffer()->unselect();
Fl::copy("", 0, 0);
e->show_insert_position();
}
switch (c) {
case FL_Home:
e->insert_position(0);
e->scroll(0, 0);
break;
case FL_End:
e->insert_position(e->buffer()->length());
e->scroll(e->count_lines(0, e->buffer()->length(), 1), 0);
break;
case FL_Left:
e->previous_word();
break;
case FL_Right:
e->next_word();
break;
case FL_Up:
e->scroll(e->mTopLineNum-1, e->mHorizOffset);
break;
case FL_Down:
e->scroll(e->mTopLineNum+1, e->mHorizOffset);
break;
case FL_Page_Up:
e->insert_position(e->mLineStarts[0]);
break;
case FL_Page_Down:
e->insert_position(e->mLineStarts[e->mNVisibleLines-2]);
break;
}
return 1;
}
/** Moves the current text cursor in the direction indicated by meta key */
int Fl_Text_Editor_mod::kf_meta_move(int c, Fl_Text_Editor_mod* e) {
if (!e->buffer()->selected())
e->dragPos = e->insert_position();
if (c != FL_Up && c != FL_Down) {
e->buffer()->unselect();
Fl::copy("", 0, 0);
e->show_insert_position();
}
switch (c) {
case FL_Up: // top of buffer
e->insert_position(0);
e->scroll(0, 0);
break;
case FL_Down: // end of buffer
e->insert_position(e->buffer()->length());
e->scroll(e->count_lines(0, e->buffer()->length(), 1), 0);
break;
case FL_Left: // beginning of line
kf_move(FL_Home, e);
break;
case FL_Right: // end of line
kf_move(FL_End, e);
break;
}
return 1;
}
/** Extends the current selection in the direction indicated by meta key c. */
int Fl_Text_Editor_mod::kf_m_s_move(int c, Fl_Text_Editor_mod* e) {
kf_meta_move(c, e);
fl_text_drag_me(e->insert_position(), e);
return 1;
}
/** Extends the current selection in the direction indicated by control key c. */
int Fl_Text_Editor_mod::kf_c_s_move(int c, Fl_Text_Editor_mod* e) {
kf_ctrl_move(c, e);
fl_text_drag_me(e->insert_position(), e);
return 1;
}
/** Moves the text cursor to the beginning of the current line.*/
int Fl_Text_Editor_mod::kf_home(int, Fl_Text_Editor_mod* e) {
return kf_move(FL_Home, e);
}
/** Moves the text cursor to the end of the current line.*/
int Fl_Text_Editor_mod::kf_end(int, Fl_Text_Editor_mod* e) {
return kf_move(FL_End, e);
}
/** Moves the text cursor one character to the left.*/
int Fl_Text_Editor_mod::kf_left(int, Fl_Text_Editor_mod* e) {
return kf_move(FL_Left, e);
}
/** Moves the text cursor one line up.*/
int Fl_Text_Editor_mod::kf_up(int, Fl_Text_Editor_mod* e) {
return kf_move(FL_Up, e);
}
/** Moves the text cursor one character to the right.*/
int Fl_Text_Editor_mod::kf_right(int, Fl_Text_Editor_mod* e) {
return kf_move(FL_Right, e);
}
/** Moves the text cursor one line down.*/
int Fl_Text_Editor_mod::kf_down(int, Fl_Text_Editor_mod* e) {
return kf_move(FL_Down, e);
}
/** Moves the text cursor up one page.*/
int Fl_Text_Editor_mod::kf_page_up(int, Fl_Text_Editor_mod* e) {
return kf_move(FL_Page_Up, e);
}
/** Moves the text cursor down one page.*/
int Fl_Text_Editor_mod::kf_page_down(int, Fl_Text_Editor_mod* e) {
return kf_move(FL_Page_Down, e);
}
/** Toggles the insert mode in the text editor.*/
int Fl_Text_Editor_mod::kf_insert(int, Fl_Text_Editor_mod* e) {
e->insert_mode(e->insert_mode() ? 0 : 1);
return 1;
}
/** Does a delete of selected text or the current character in the current buffer.*/
int Fl_Text_Editor_mod::kf_delete(int, Fl_Text_Editor_mod* e) {
if (!e->buffer()->selected()) {
int p1 = e->insert_position();
int p2 = e->buffer()->next_char(p1);
e->buffer()->select(p1, p2);
}
kill_selection(e);
e->show_insert_position();
e->set_changed();
if (e->when()&FL_WHEN_CHANGED) e->do_callback();
return 1;
}
/** Does a copy of selected text or the current character in the current buffer.*/
int Fl_Text_Editor_mod::kf_copy(int, Fl_Text_Editor_mod* e) {
if (!e->buffer()->selected()) return 1;
const char *copy = e->buffer()->selection_text();
if (*copy) Fl::copy(copy, strlen(copy), 1);
free((void*)copy);
e->show_insert_position();
return 1;
}
/** Does a cut of selected text in the current buffer.*/
int Fl_Text_Editor_mod::kf_cut(int c, Fl_Text_Editor_mod* e) {
kf_copy(c, e);
kill_selection(e);
e->set_changed();
if (e->when()&FL_WHEN_CHANGED) e->do_callback();
return 1;
}
/** Does a paste of selected text in the current buffer.*/
int Fl_Text_Editor_mod::kf_paste(int, Fl_Text_Editor_mod* e) {
kill_selection(e);
Fl::paste(*e, 1);
e->show_insert_position();
e->set_changed();
if (e->when()&FL_WHEN_CHANGED) e->do_callback();
return 1;
}
/** Selects all text in the current buffer.*/
int Fl_Text_Editor_mod::kf_select_all(int, Fl_Text_Editor_mod* e) {
e->buffer()->select(0, e->buffer()->length());
const char *copy = e->buffer()->selection_text();
if (*copy) Fl::copy(copy, strlen(copy), 0);
free((void*)copy);
return 1;
}
/** Undo last edit in the current buffer. Also deselect previous selection. */
int Fl_Text_Editor_mod::kf_undo(int , Fl_Text_Editor_mod* e) {
e->buffer()->unselect();
Fl::copy("", 0, 0);
int crsr;
int ret = e->buffer()->undo(&crsr);
e->insert_position(crsr);
e->show_insert_position();
e->set_changed();
if (e->when()&FL_WHEN_CHANGED) e->do_callback();
return ret;
}
/** Handles a key press in the editor */
int Fl_Text_Editor_mod::handle_key() {
// Call FLTK's rules to try to turn this into a printing character.
// This uses the right-hand ctrl key as a "compose prefix" and returns
// the changes that should be made to the text, as a number of
// bytes to delete and a string to insert:
int del = 0;
int key = Fl::event_key(), state = Fl::event_state();//, c = Fl::event_text()[0];
if (key == FL_Caps_Lock) return 0;
if (Fl::compose(del)) {
if (del) {
int dp = insert_position(), di = del;
while (di--) dp = buffer()->prev_char_clipped(dp);
buffer()->select(dp, insert_position());
}
kill_selection(this);
if (Fl::event_length()) {
if (insert_mode()) insert(Fl::event_text());
else overstrike(Fl::event_text());
}
show_insert_position();
set_changed();
if (when()&FL_WHEN_CHANGED) do_callback();
return 1;
}
state &= FL_SHIFT|FL_CTRL|FL_ALT|FL_META; // only care about these states
Key_Func f;
f = bound_key_function(key, state, global_key_bindings);
if (!f && key_bindings) f = bound_key_function(key, state, key_bindings);
if (f) return f(key, this);
if (default_key_function_ && !state) return default_key_function_(key, this);
return 0;
}
/** does or does not a callback according to changed() and when() settings */
void Fl_Text_Editor_mod::maybe_do_callback() {
if (changed() || (when()&FL_WHEN_NOT_CHANGED)) do_callback();
}
int Fl_Text_Editor_mod::handle(int event) {
static int dndCursorPos;
if (!buffer()) return 0;
switch (event) {
case FL_FOCUS:
show_cursor(mCursorOn); // redraws the cursor
if (buffer()->selected()) redraw(); // Redraw selections...
Fl::focus(this);
return 1;
case FL_UNFOCUS:
show_cursor(mCursorOn); // redraws the cursor
if (buffer()->selected()) redraw(); // Redraw selections...
case FL_HIDE:
if (when() & FL_WHEN_RELEASE) maybe_do_callback();
return 1;
case FL_KEYBOARD:
if (active_r() && window() && this == Fl::belowmouse())
window()->cursor(FL_CURSOR_NONE);
return handle_key();
case FL_PASTE:
if (!Fl::event_text()) {
fl_beep();
return 1;
}
buffer()->remove_selection();
if (insert_mode()) insert(Fl::event_text());
else overstrike(Fl::event_text());
show_insert_position();
set_changed();
if (when()&FL_WHEN_CHANGED) do_callback();
return 1;
case FL_ENTER:
// MRS: WIN32 only? Need to test!
// case FL_MOVE:
show_cursor(mCursorOn);
return 1;
case FL_PUSH:
if (Fl::event_button() == 2) {
// don't let the text_display see this event
if (Fl_Group::handle(event)) return 1;
dragType = DRAG_NONE;
if(buffer()->selected()) {
buffer()->unselect();
}
int pos = xy_to_position(Fl::event_x(), Fl::event_y(), CURSOR_POS);
insert_position(pos);
Fl::paste(*this, 0);
Fl::focus(this);
set_changed();
if (when()&FL_WHEN_CHANGED) do_callback();
return 1;
}
break;
case FL_SHORTCUT:
if (!(shortcut() ? Fl::test_shortcut(shortcut()) : test_shortcut()))
return 0;
if (Fl::visible_focus() && handle(FL_FOCUS)) {
Fl::focus(this);
return 1;
}
break;
// Handle drag'n'drop attempt by the user. This is a simplified
// implementation which allows dnd operations onto the scroll bars.
case FL_DND_ENTER: // save the current cursor position
if (Fl::visible_focus() && handle(FL_FOCUS))
Fl::focus(this);
show_cursor(mCursorOn);
dndCursorPos = insert_position();
/* fall through */
case FL_DND_DRAG: // show a temporary insertion cursor
insert_position(xy_to_position(Fl::event_x(), Fl::event_y(), CURSOR_POS));
return 1;
case FL_DND_LEAVE: // restore original cursor
insert_position(dndCursorPos);
return 1;
case FL_DND_RELEASE: // keep insertion cursor and wait for the FL_PASTE event
buffer()->unselect(); // FL_PASTE must not destroy current selection!
return 1;
}
return Fl_Text_Display_mod::handle(event);
}
//
// End of "$Id: Fl_Text_Editor_mod.cxx 8034 2010-12-15 12:21:55Z AlbrechtS $".
//

View file

@ -1,494 +0,0 @@
// "$Id: Fl_Text_Editor.cxx 5671 2007-02-08 07:58:47Z matt $"
//
// Copyright 2001-2006 by Bill Spitzak and others.
// Original code Copyright Mark Edel. Permission to distribute under
// the LGPL for the FLTK library granted by Mark Edel.
// ----------------------------------------------------------------------------
// Copyright (C) 2014
// David Freese, W1HKJ
//
// This file is part of flmsg
//
// flrig is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// flrig 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include "Fl_Text_Editor_mod.H"
#include <FL/fl_ask.H>
#include "missing_strings.h"
Fl_Text_Editor_mod::Fl_Text_Editor_mod(int X, int Y, int W, int H, const char* l)
: Fl_Text_Display_mod(X, Y, W, H, l) {
mCursorOn = 1;
insert_mode_ = 1;
key_bindings = 0;
// handle the default key bindings
add_default_key_bindings(&key_bindings);
// handle everything else
default_key_function(kf_default);
}
Fl_Text_Editor_mod::Key_Binding* Fl_Text_Editor_mod::global_key_bindings = 0;
// These are the default key bindings every widget should start with
static struct {
int key;
int state;
Fl_Text_Editor_mod::Key_Func func;
} default_key_bindings[] = {
{ FL_Escape, FL_TEXT_EDITOR_ANY_STATE, Fl_Text_Editor_mod::kf_ignore },
{ FL_Enter, FL_TEXT_EDITOR_ANY_STATE, Fl_Text_Editor_mod::kf_enter },
{ FL_KP_Enter, FL_TEXT_EDITOR_ANY_STATE, Fl_Text_Editor_mod::kf_enter },
{ FL_BackSpace, FL_TEXT_EDITOR_ANY_STATE, Fl_Text_Editor_mod::kf_backspace },
{ FL_Insert, FL_TEXT_EDITOR_ANY_STATE, Fl_Text_Editor_mod::kf_insert },
{ FL_Delete, FL_TEXT_EDITOR_ANY_STATE, Fl_Text_Editor_mod::kf_delete },
{ FL_Home, 0, Fl_Text_Editor_mod::kf_move },
{ FL_End, 0, Fl_Text_Editor_mod::kf_move },
{ FL_Left, 0, Fl_Text_Editor_mod::kf_move },
{ FL_Up, 0, Fl_Text_Editor_mod::kf_move },
{ FL_Right, 0, Fl_Text_Editor_mod::kf_move },
{ FL_Down, 0, Fl_Text_Editor_mod::kf_move },
{ FL_Page_Up, 0, Fl_Text_Editor_mod::kf_move },
{ FL_Page_Down, 0, Fl_Text_Editor_mod::kf_move },
{ FL_Home, FL_SHIFT, Fl_Text_Editor_mod::kf_shift_move },
{ FL_End, FL_SHIFT, Fl_Text_Editor_mod::kf_shift_move },
{ FL_Left, FL_SHIFT, Fl_Text_Editor_mod::kf_shift_move },
{ FL_Up, FL_SHIFT, Fl_Text_Editor_mod::kf_shift_move },
{ FL_Right, FL_SHIFT, Fl_Text_Editor_mod::kf_shift_move },
{ FL_Down, FL_SHIFT, Fl_Text_Editor_mod::kf_shift_move },
{ FL_Page_Up, FL_SHIFT, Fl_Text_Editor_mod::kf_shift_move },
{ FL_Page_Down, FL_SHIFT, Fl_Text_Editor_mod::kf_shift_move },
{ FL_Home, FL_CTRL, Fl_Text_Editor_mod::kf_ctrl_move },
{ FL_End, FL_CTRL, Fl_Text_Editor_mod::kf_ctrl_move },
{ FL_Left, FL_CTRL, Fl_Text_Editor_mod::kf_ctrl_move },
{ FL_Up, FL_CTRL, Fl_Text_Editor_mod::kf_ctrl_move },
{ FL_Right, FL_CTRL, Fl_Text_Editor_mod::kf_ctrl_move },
{ FL_Down, FL_CTRL, Fl_Text_Editor_mod::kf_ctrl_move },
{ FL_Page_Up, FL_CTRL, Fl_Text_Editor_mod::kf_ctrl_move },
{ FL_Page_Down, FL_CTRL, Fl_Text_Editor_mod::kf_ctrl_move },
{ FL_Home, FL_CTRL|FL_SHIFT, Fl_Text_Editor_mod::kf_c_s_move },
{ FL_End, FL_CTRL|FL_SHIFT, Fl_Text_Editor_mod::kf_c_s_move },
{ FL_Left, FL_CTRL|FL_SHIFT, Fl_Text_Editor_mod::kf_c_s_move },
{ FL_Up, FL_CTRL|FL_SHIFT, Fl_Text_Editor_mod::kf_c_s_move },
{ FL_Right, FL_CTRL|FL_SHIFT, Fl_Text_Editor_mod::kf_c_s_move },
{ FL_Down, FL_CTRL|FL_SHIFT, Fl_Text_Editor_mod::kf_c_s_move },
{ FL_Page_Up, FL_CTRL|FL_SHIFT, Fl_Text_Editor_mod::kf_c_s_move },
{ FL_Page_Down, FL_CTRL|FL_SHIFT, Fl_Text_Editor_mod::kf_c_s_move },
//{ FL_Clear, 0, Fl_Text_Editor_mod::delete_to_eol },
{ 'z', FL_CTRL, Fl_Text_Editor_mod::kf_undo },
{ '/', FL_CTRL, Fl_Text_Editor_mod::kf_undo },
{ 'x', FL_CTRL, Fl_Text_Editor_mod::kf_cut },
{ FL_Delete, FL_SHIFT, Fl_Text_Editor_mod::kf_cut },
{ 'c', FL_CTRL, Fl_Text_Editor_mod::kf_copy },
{ FL_Insert, FL_CTRL, Fl_Text_Editor_mod::kf_copy },
{ 'v', FL_CTRL, Fl_Text_Editor_mod::kf_paste },
{ FL_Insert, FL_SHIFT, Fl_Text_Editor_mod::kf_paste },
{ 'a', FL_CTRL, Fl_Text_Editor_mod::kf_select_all },
#ifdef __APPLE__
// Define CMD+key accelerators...
{ 'z', FL_COMMAND, Fl_Text_Editor_mod::kf_undo },
{ 'x', FL_COMMAND, Fl_Text_Editor_mod::kf_cut },
{ 'c', FL_COMMAND, Fl_Text_Editor_mod::kf_copy },
{ 'v', FL_COMMAND, Fl_Text_Editor_mod::kf_paste },
{ 'a', FL_COMMAND, Fl_Text_Editor_mod::kf_select_all },
#endif // __APPLE__
{ 0, 0, 0 }
};
void Fl_Text_Editor_mod::add_default_key_bindings(Key_Binding** list) {
for (int i = 0; default_key_bindings[i].key; i++) {
add_key_binding(default_key_bindings[i].key,
default_key_bindings[i].state,
default_key_bindings[i].func,
list);
}
}
Fl_Text_Editor_mod::Key_Func
Fl_Text_Editor_mod::bound_key_function(int key, int state, Key_Binding* list) {
Key_Binding* cur;
if (!list) return 0;
for (cur = list; cur; cur = cur->next)
if (cur->key == key)
if (cur->state == FL_TEXT_EDITOR_ANY_STATE || cur->state == state)
break;
if (!cur) return 0;
return cur->function;
}
void
Fl_Text_Editor_mod::remove_all_key_bindings(Key_Binding** list) {
Key_Binding *cur, *next;
for (cur = *list; cur; cur = next) {
next = cur->next;
delete cur;
}
*list = 0;
}
void
Fl_Text_Editor_mod::remove_key_binding(int key, int state, Key_Binding** list) {
Key_Binding *cur, *last = 0;
for (cur = *list; cur; last = cur, cur = cur->next)
if (cur->key == key && cur->state == state) break;
if (!cur) return;
if (last) last->next = cur->next;
else *list = cur->next;
delete cur;
}
void
Fl_Text_Editor_mod::add_key_binding(int key, int state, Key_Func function,
Key_Binding** list) {
Key_Binding* kb = new Key_Binding;
kb->key = key;
kb->state = state;
kb->function = function;
kb->next = *list;
*list = kb;
}
////////////////////////////////////////////////////////////////
#define NORMAL_INPUT_MOVE 0
static void kill_selection(Fl_Text_Editor_mod* e) {
if (e->buffer()->selected()) {
e->insert_position(e->buffer()->primary_selection()->start());
e->buffer()->remove_selection();
}
}
int Fl_Text_Editor_mod::kf_default(int c, Fl_Text_Editor_mod* e) {
if (!c || (!isprint(c) && c != '\t')) return 0;
char s[2] = "\0";
s[0] = (char)c;
kill_selection(e);
if (e->insert_mode()) e->insert(s);
else e->overstrike(s);
e->show_insert_position();
e->set_changed();
if (e->when()&FL_WHEN_CHANGED) e->do_callback();
return 1;
}
int Fl_Text_Editor_mod::kf_ignore(int, Fl_Text_Editor_mod*) {
return 0; // don't handle
}
int Fl_Text_Editor_mod::kf_backspace(int, Fl_Text_Editor_mod* e) {
if (!e->buffer()->selected() && e->move_left())
e->buffer()->select(e->insert_position(), e->insert_position()+1);
kill_selection(e);
e->show_insert_position();
e->set_changed();
if (e->when()&FL_WHEN_CHANGED) e->do_callback();
return 1;
}
int Fl_Text_Editor_mod::kf_enter(int, Fl_Text_Editor_mod* e) {
kill_selection(e);
e->insert("\n");
e->show_insert_position();
e->set_changed();
if (e->when()&FL_WHEN_CHANGED) e->do_callback();
return 1;
}
extern void fl_text_drag_me(int pos, Fl_Text_Display_mod* d);
int Fl_Text_Editor_mod::kf_move(int c, Fl_Text_Editor_mod* e) {
int i;
int selected = e->buffer()->selected();
if (!selected)
e->dragPos = e->insert_position();
e->buffer()->unselect();
switch (c) {
case FL_Home:
e->insert_position(e->buffer()->line_start(e->insert_position()));
break;
case FL_End:
e->insert_position(e->buffer()->line_end(e->insert_position()));
break;
case FL_Left:
e->move_left();
break;
case FL_Right:
e->move_right();
break;
case FL_Up:
e->move_up();
break;
case FL_Down:
e->move_down();
break;
case FL_Page_Up:
for (i = 0; i < e->mNVisibleLines - 1; i++) e->move_up();
break;
case FL_Page_Down:
for (i = 0; i < e->mNVisibleLines - 1; i++) e->move_down();
break;
}
e->show_insert_position();
return 1;
}
int Fl_Text_Editor_mod::kf_shift_move(int c, Fl_Text_Editor_mod* e) {
kf_move(c, e);
fl_text_drag_me(e->insert_position(), e);
return 1;
}
int Fl_Text_Editor_mod::kf_ctrl_move(int c, Fl_Text_Editor_mod* e) {
if (!e->buffer()->selected())
e->dragPos = e->insert_position();
if (c != FL_Up && c != FL_Down) {
e->buffer()->unselect();
e->show_insert_position();
}
switch (c) {
case FL_Home:
e->insert_position(0);
e->scroll(0, 0);
break;
case FL_End:
e->insert_position(e->buffer()->length());
e->scroll(e->count_lines(0, e->buffer()->length(), 1), 0);
break;
case FL_Left:
e->previous_word();
break;
case FL_Right:
e->next_word();
break;
case FL_Up:
e->scroll(e->mTopLineNum-1, e->mHorizOffset);
break;
case FL_Down:
e->scroll(e->mTopLineNum+1, e->mHorizOffset);
break;
case FL_Page_Up:
e->insert_position(e->mLineStarts[0]);
break;
case FL_Page_Down:
e->insert_position(e->mLineStarts[e->mNVisibleLines-2]);
break;
}
return 1;
}
int Fl_Text_Editor_mod::kf_c_s_move(int c, Fl_Text_Editor_mod* e) {
kf_ctrl_move(c, e);
fl_text_drag_me(e->insert_position(), e);
return 1;
}
int Fl_Text_Editor_mod::kf_home(int, Fl_Text_Editor_mod* e) {
return kf_move(FL_Home, e);
}
int Fl_Text_Editor_mod::kf_end(int, Fl_Text_Editor_mod* e) {
return kf_move(FL_End, e);
}
int Fl_Text_Editor_mod::kf_left(int, Fl_Text_Editor_mod* e) {
return kf_move(FL_Left, e);
}
int Fl_Text_Editor_mod::kf_up(int, Fl_Text_Editor_mod* e) {
return kf_move(FL_Up, e);
}
int Fl_Text_Editor_mod::kf_right(int, Fl_Text_Editor_mod* e) {
return kf_move(FL_Right, e);
}
int Fl_Text_Editor_mod::kf_down(int, Fl_Text_Editor_mod* e) {
return kf_move(FL_Down, e);
}
int Fl_Text_Editor_mod::kf_page_up(int, Fl_Text_Editor_mod* e) {
return kf_move(FL_Page_Up, e);
}
int Fl_Text_Editor_mod::kf_page_down(int, Fl_Text_Editor_mod* e) {
return kf_move(FL_Page_Down, e);
}
int Fl_Text_Editor_mod::kf_insert(int, Fl_Text_Editor_mod* e) {
e->insert_mode(e->insert_mode() ? 0 : 1);
return 1;
}
int Fl_Text_Editor_mod::kf_delete(int, Fl_Text_Editor_mod* e) {
if (!e->buffer()->selected())
e->buffer()->select(e->insert_position(), e->insert_position()+1);
kill_selection(e);
e->show_insert_position();
e->set_changed();
if (e->when()&FL_WHEN_CHANGED) e->do_callback();
return 1;
}
int Fl_Text_Editor_mod::kf_copy(int, Fl_Text_Editor_mod* e) {
if (!e->buffer()->selected()) return 1;
const char *copy = e->buffer()->selection_text();
if (*copy) Fl::copy(copy, strlen(copy), 1);
free((void*)copy);
e->show_insert_position();
return 1;
}
int Fl_Text_Editor_mod::kf_cut(int c, Fl_Text_Editor_mod* e) {
kf_copy(c, e);
kill_selection(e);
e->set_changed();
if (e->when()&FL_WHEN_CHANGED) e->do_callback();
return 1;
}
int Fl_Text_Editor_mod::kf_paste(int, Fl_Text_Editor_mod* e) {
kill_selection(e);
Fl::paste(*e, 1);
e->show_insert_position();
e->set_changed();
if (e->when()&FL_WHEN_CHANGED) e->do_callback();
return 1;
}
int Fl_Text_Editor_mod::kf_select_all(int, Fl_Text_Editor_mod* e) {
e->buffer()->select(0, e->buffer()->length());
return 1;
}
int Fl_Text_Editor_mod::kf_undo(int , Fl_Text_Editor_mod* e) {
e->buffer()->unselect();
int crsr;
int ret = e->buffer()->undo(&crsr);
e->insert_position(crsr);
e->show_insert_position();
e->set_changed();
if (e->when()&FL_WHEN_CHANGED) e->do_callback();
return ret;
}
int Fl_Text_Editor_mod::handle_key() {
// Call FLTK's rules to try to turn this into a printing character.
// This uses the right-hand ctrl key as a "compose prefix" and returns
// the changes that should be made to the text, as a number of
// bytes to delete and a std::string to insert:
int del;
if (Fl::compose(del)) {
if (del) buffer()->select(insert_position()-del, insert_position());
kill_selection(this);
if (Fl::event_length()) {
if (insert_mode()) insert(Fl::event_text());
else overstrike(Fl::event_text());
}
show_insert_position();
set_changed();
if (when()&FL_WHEN_CHANGED) do_callback();
return 1;
}
int key = Fl::event_key(), state = Fl::event_state(), c = Fl::event_text()[0];
state &= FL_SHIFT|FL_CTRL|FL_ALT|FL_META; // only care about these states
Key_Func f;
f = bound_key_function(key, state, global_key_bindings);
if (!f) f = bound_key_function(key, state, key_bindings);
if (f) return f(key, this);
if (default_key_function_ && !state) return default_key_function_(c, this);
return 0;
}
void Fl_Text_Editor_mod::maybe_do_callback() {
// printf("Fl_Text_Editor_mod::maybe_do_callback()\n");
// printf("changed()=%d, when()=%x\n", changed(), when());
if (changed() || (when()&FL_WHEN_NOT_CHANGED)) do_callback();
}
int Fl_Text_Editor_mod::handle(int event) {
if (!buffer()) return 0;
switch (event) {
case FL_FOCUS:
show_cursor(mCursorOn); // redraws the cursor
if (buffer()->selected()) redraw(); // Redraw selections...
Fl::focus(this);
return 1;
case FL_UNFOCUS:
show_cursor(mCursorOn); // redraws the cursor
if (buffer()->selected()) redraw(); // Redraw selections...
case FL_HIDE:
if (when() & FL_WHEN_RELEASE) maybe_do_callback();
return 1;
case FL_KEYBOARD:
if (active_r() && window() && this == Fl::belowmouse())
window()->cursor(FL_CURSOR_NONE);
return handle_key();
case FL_PASTE:
if (!Fl::event_text()) {
fl_beep();
return 1;
}
buffer()->remove_selection();
if (insert_mode()) insert(Fl::event_text());
else overstrike(Fl::event_text());
show_insert_position();
set_changed();
if (when()&FL_WHEN_CHANGED) do_callback();
return 1;
case FL_ENTER:
// MRS: WIN32 only? Need to test!
// case FL_MOVE:
show_cursor(mCursorOn);
return 1;
case FL_PUSH:
if (Fl::event_button() == 2) {
// don't let the text_display see this event
if (Fl_Group::handle(event)) return 1;
dragType = -1;
Fl::paste(*this, 0);
Fl::focus(this);
set_changed();
if (when()&FL_WHEN_CHANGED) do_callback();
return 1;
}
break;
}
return Fl_Text_Display_mod::handle(event);
}
//
// End of "$Id: Fl_Text_Editor.cxx 5671 2007-02-08 07:58:47Z matt $".
//

View file

@ -1,656 +0,0 @@
// "$Id: Fl_Text_Editor_mod.cxx 8034 2010-12-15 12:21:55Z AlbrechtS $"
//
// Copyright 2001-2010 by Bill Spitzak and others.
// Original code Copyright Mark Edel. Permission to distribute under
// the LGPL for the FLTK library granted by Mark Edel.
// ----------------------------------------------------------------------------
// Copyright (C) 2014
// David Freese, W1HKJ
//
// This file is part of flmsg
//
// flrig is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// flrig 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include "missing_strings.h"
#include <ctype.h>
#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include <FL/fl_ask.H>
#include "Fl_Text_Editor_mod.H"
#include "debug.h"
/* Keyboard Control Matrix
key\modifier plain Ctrl Alt Meta
left 1/1 13/9 0/13 0/9
right 2/2 14/10 0/14 0/10
up 3/19 21/7 0/15 0/17
down 4/20 22/8 0/16 0/18
home 9/5 17/0 0/0 0/0
end 10/6 18/0 0/0 0/0
page up 11/7 23/0 0/11 0/0
page down 12/8 24/0 0/12 0/0
(FLTK action / OS X action)
(adding the shift key extends the selection, all other combinations are no-op)
0: no-op
1: move cursor to the left, at line beginning wrap to end of prev line, at doc start no-op
2: move cursor to the right, at line end move to beginning of the next line, at doc end no-op
3: move cursor up, at doc top no-op
4: move cursor down, at doc bottom no-op
5: scroll display to top of text (cursor unchanged)
6: scroll display to end of text (cursor unchanged)
7: scroll text down one page (cursor unchanged)
8: scroll text up one page (cursor unchanged)
9: move cursor to beginning of line
10: move cursor to end of line
11: move cursor up one page and scroll down
12: move cursor down one page and scroll up
13: move to the beginning of the word or the previous word
14: move to the end of the word or the next word
15: if start of line: start of prev line, else start of this line
16: if end of line: end of next line, else end of this line
17: move cursor to the beginning of the document
18: move cursor to the end of the document
19: move cursor up, at doc top: home, at doc start: no-op)
20: move cursor down, at doc bot: end, at doc end: no-op)
21: scroll text down one line (cursor unchanged)
22: scroll text up one line (cursor unchanged)
23: move cursor to the beginning of the top of the screen
24: move cursor to the beginning of the bottom of the window
*/
/** The constructor creates a new text editor widget.*/
Fl_Text_Editor_mod::Fl_Text_Editor_mod(int X, int Y, int W, int H, const char* l)
: Fl_Text_Display_mod(X, Y, W, H, l) {
mCursorOn = 1;
insert_mode_ = 1;
key_bindings = 0;
// handle the default key bindings
add_default_key_bindings(&key_bindings);
// handle everything else
default_key_function(kf_default);
}
#ifndef FL_DOXYGEN
Fl_Text_Editor_mod::Key_Binding* Fl_Text_Editor_mod::global_key_bindings = 0;
#endif
// These are the default key bindings every widget should start with
static struct {
int key;
int state;
Fl_Text_Editor_mod::Key_Func func;
} default_key_bindings[] = {
{ FL_Escape, Fl_Text_Editor_mod_ANY_STATE, Fl_Text_Editor_mod::kf_ignore },
{ FL_Enter, Fl_Text_Editor_mod_ANY_STATE, Fl_Text_Editor_mod::kf_enter },
{ FL_KP_Enter, Fl_Text_Editor_mod_ANY_STATE, Fl_Text_Editor_mod::kf_enter },
{ FL_BackSpace, Fl_Text_Editor_mod_ANY_STATE, Fl_Text_Editor_mod::kf_backspace },
{ FL_Insert, Fl_Text_Editor_mod_ANY_STATE, Fl_Text_Editor_mod::kf_insert },
{ FL_Delete, Fl_Text_Editor_mod_ANY_STATE, Fl_Text_Editor_mod::kf_delete },
{ FL_Home, 0, Fl_Text_Editor_mod::kf_move },
{ FL_End, 0, Fl_Text_Editor_mod::kf_move },
{ FL_Left, 0, Fl_Text_Editor_mod::kf_move },
{ FL_Up, 0, Fl_Text_Editor_mod::kf_move },
{ FL_Right, 0, Fl_Text_Editor_mod::kf_move },
{ FL_Down, 0, Fl_Text_Editor_mod::kf_move },
{ FL_Page_Up, 0, Fl_Text_Editor_mod::kf_move },
{ FL_Page_Down, 0, Fl_Text_Editor_mod::kf_move },
{ FL_Home, FL_SHIFT, Fl_Text_Editor_mod::kf_shift_move },
{ FL_End, FL_SHIFT, Fl_Text_Editor_mod::kf_shift_move },
{ FL_Left, FL_SHIFT, Fl_Text_Editor_mod::kf_shift_move },
{ FL_Up, FL_SHIFT, Fl_Text_Editor_mod::kf_shift_move },
{ FL_Right, FL_SHIFT, Fl_Text_Editor_mod::kf_shift_move },
{ FL_Down, FL_SHIFT, Fl_Text_Editor_mod::kf_shift_move },
{ FL_Page_Up, FL_SHIFT, Fl_Text_Editor_mod::kf_shift_move },
{ FL_Page_Down, FL_SHIFT, Fl_Text_Editor_mod::kf_shift_move },
{ FL_Home, FL_CTRL, Fl_Text_Editor_mod::kf_ctrl_move },
{ FL_End, FL_CTRL, Fl_Text_Editor_mod::kf_ctrl_move },
{ FL_Left, FL_CTRL, Fl_Text_Editor_mod::kf_ctrl_move },
{ FL_Up, FL_CTRL, Fl_Text_Editor_mod::kf_ctrl_move },
{ FL_Right, FL_CTRL, Fl_Text_Editor_mod::kf_ctrl_move },
{ FL_Down, FL_CTRL, Fl_Text_Editor_mod::kf_ctrl_move },
{ FL_Page_Up, FL_CTRL, Fl_Text_Editor_mod::kf_ctrl_move },
{ FL_Page_Down, FL_CTRL, Fl_Text_Editor_mod::kf_ctrl_move },
{ FL_Home, FL_CTRL|FL_SHIFT, Fl_Text_Editor_mod::kf_c_s_move },
{ FL_End, FL_CTRL|FL_SHIFT, Fl_Text_Editor_mod::kf_c_s_move },
{ FL_Left, FL_CTRL|FL_SHIFT, Fl_Text_Editor_mod::kf_c_s_move },
{ FL_Up, FL_CTRL|FL_SHIFT, Fl_Text_Editor_mod::kf_c_s_move },
{ FL_Right, FL_CTRL|FL_SHIFT, Fl_Text_Editor_mod::kf_c_s_move },
{ FL_Down, FL_CTRL|FL_SHIFT, Fl_Text_Editor_mod::kf_c_s_move },
{ FL_Page_Up, FL_CTRL|FL_SHIFT, Fl_Text_Editor_mod::kf_c_s_move },
{ FL_Page_Down, FL_CTRL|FL_SHIFT, Fl_Text_Editor_mod::kf_c_s_move },
//{ FL_Clear, 0, Fl_Text_Editor_mod::delete_to_eol },
{ 'z', FL_CTRL, Fl_Text_Editor_mod::kf_undo },
{ '/', FL_CTRL, Fl_Text_Editor_mod::kf_undo },
{ FL_Home, FL_SHIFT, Fl_Text_Editor_mod::kf_undo },
{ 'x', FL_CTRL, Fl_Text_Editor_mod::kf_cut },
{ FL_Delete, FL_SHIFT, Fl_Text_Editor_mod::kf_cut },
{ 'c', FL_CTRL, Fl_Text_Editor_mod::kf_copy },
{ FL_Insert, FL_CTRL, Fl_Text_Editor_mod::kf_copy },
{ 'v', FL_CTRL, Fl_Text_Editor_mod::kf_paste },
{ FL_Insert, FL_SHIFT, Fl_Text_Editor_mod::kf_paste },
{ 'a', FL_CTRL, Fl_Text_Editor_mod::kf_select_all },
#ifdef __APPLE__
// Define CMD+key accelerators...
{ 'z', FL_COMMAND, Fl_Text_Editor_mod::kf_undo },
{ 'x', FL_COMMAND, Fl_Text_Editor_mod::kf_cut },
{ 'c', FL_COMMAND, Fl_Text_Editor_mod::kf_copy },
{ 'v', FL_COMMAND, Fl_Text_Editor_mod::kf_paste },
{ 'a', FL_COMMAND, Fl_Text_Editor_mod::kf_select_all },
{ FL_Left, FL_COMMAND, Fl_Text_Editor_mod::kf_meta_move },
{ FL_Right, FL_COMMAND, Fl_Text_Editor_mod::kf_meta_move },
{ FL_Up, FL_COMMAND, Fl_Text_Editor_mod::kf_meta_move },
{ FL_Down, FL_COMMAND, Fl_Text_Editor_mod::kf_meta_move },
{ FL_Left, FL_COMMAND|FL_SHIFT, Fl_Text_Editor_mod::kf_m_s_move },
{ FL_Right, FL_COMMAND|FL_SHIFT, Fl_Text_Editor_mod::kf_m_s_move },
{ FL_Up, FL_COMMAND|FL_SHIFT, Fl_Text_Editor_mod::kf_m_s_move },
{ FL_Down, FL_COMMAND|FL_SHIFT, Fl_Text_Editor_mod::kf_m_s_move },
#endif // __APPLE__
{ 0, 0, 0 }
};
/** Adds all of the default editor key bindings to the specified key binding list.*/
void Fl_Text_Editor_mod::add_default_key_bindings(Key_Binding** list) {
for (int i = 0; default_key_bindings[i].key; i++) {
add_key_binding(default_key_bindings[i].key,
default_key_bindings[i].state,
default_key_bindings[i].func,
list);
}
}
/** Returns the function associated with a key binding.*/
Fl_Text_Editor_mod::Key_Func Fl_Text_Editor_mod::bound_key_function(int key, int state, Key_Binding* list) {
Key_Binding* cur;
if (!list) return 0;
for (cur = list; cur; cur = cur->next)
if (cur->key == key)
if (cur->state == Fl_Text_Editor_mod_ANY_STATE || cur->state == state)
break;
if (!cur) return 0;
return cur->function;
}
/** Removes all of the key bindings associated with the text editor or list.*/
void Fl_Text_Editor_mod::remove_all_key_bindings(Key_Binding** list) {
Key_Binding *cur, *next;
for (cur = *list; cur; cur = next) {
next = cur->next;
delete cur;
}
*list = 0;
}
/** Removes the key binding associated with the key "key" of state "state" */
void Fl_Text_Editor_mod::remove_key_binding(int key, int state, Key_Binding** list) {
Key_Binding *cur, *last = 0;
for (cur = *list; cur; last = cur, cur = cur->next)
if (cur->key == key && cur->state == state) break;
if (!cur) return;
if (last) last->next = cur->next;
else *list = cur->next;
delete cur;
}
/** Adds a key of state "state" with the function "function" */
void Fl_Text_Editor_mod::add_key_binding(int key, int state, Key_Func function,
Key_Binding** list) {
Key_Binding* kb = new Key_Binding;
kb->key = key;
kb->state = state;
kb->function = function;
kb->next = *list;
*list = kb;
}
////////////////////////////////////////////////////////////////
static void kill_selection(Fl_Text_Editor_mod* e) {
if (e->buffer()->selected()) {
e->insert_position(e->buffer()->primary_selection()->start());
e->buffer()->remove_selection();
}
}
/** Inserts the text associated with the key */
int Fl_Text_Editor_mod::kf_default(int c, Fl_Text_Editor_mod* e) {
// FIXME: this function is a mess! Fix this!
if (!c || (!isprint(c) && c != '\t')) return 0;
char s[2] = "\0";
s[0] = (char)c;
kill_selection(e);
if (e->insert_mode()) e->insert(s);
else e->overstrike(s);
e->show_insert_position();
e->set_changed();
if (e->when()&FL_WHEN_CHANGED) e->do_callback();
return 1;
}
/** Ignores the keypress */
int Fl_Text_Editor_mod::kf_ignore(int, Fl_Text_Editor_mod*) {
return 0; // don't handle
}
/** Does a backspace in the current buffer.*/
int Fl_Text_Editor_mod::kf_backspace(int, Fl_Text_Editor_mod* e) {
if (!e->buffer()->selected() && e->move_left()) {
int p1 = e->insert_position();
int p2 = e->buffer()->next_char(p1);
e->buffer()->select(p1, p2);
}
kill_selection(e);
e->show_insert_position();
e->set_changed();
if (e->when()&FL_WHEN_CHANGED) e->do_callback();
return 1;
}
/** Inserts a newline at the current cursor position */
int Fl_Text_Editor_mod::kf_enter(int, Fl_Text_Editor_mod* e) {
kill_selection(e);
e->insert("\n");
e->show_insert_position();
e->set_changed();
if (e->when()&FL_WHEN_CHANGED) e->do_callback();
return 1;
}
extern void fl_text_drag_me(int pos, Fl_Text_Display_mod* d);
/** Moves the text cursor in the direction indicated by key c.*/
int Fl_Text_Editor_mod::kf_move(int c, Fl_Text_Editor_mod* e) {
int i;
int selected = e->buffer()->selected();
if (!selected)
e->dragPos = e->insert_position();
e->buffer()->unselect();
Fl::copy("", 0, 0);
switch (c) {
case FL_Home:
e->insert_position(e->buffer()->line_start(e->insert_position()));
break;
case FL_End:
e->insert_position(e->buffer()->line_end(e->insert_position()));
break;
case FL_Left:
e->move_left();
break;
case FL_Right:
e->move_right();
break;
case FL_Up:
e->move_up();
break;
case FL_Down:
e->move_down();
break;
case FL_Page_Up:
for (i = 0; i < e->mNVisibleLines - 1; i++) e->move_up();
break;
case FL_Page_Down:
for (i = 0; i < e->mNVisibleLines - 1; i++) e->move_down();
break;
}
e->show_insert_position();
return 1;
}
/** Extends the current selection in the direction of key c.*/
int Fl_Text_Editor_mod::kf_shift_move(int c, Fl_Text_Editor_mod* e) {
kf_move(c, e);
fl_text_drag_me(e->insert_position(), e);
char *copy = e->buffer()->selection_text();
if (copy) {
Fl::copy(copy, strlen(copy), 0);
free(copy);
}
return 1;
}
/** Moves the current text cursor in the direction indicated by control key */
int Fl_Text_Editor_mod::kf_ctrl_move(int c, Fl_Text_Editor_mod* e) {
if (!e->buffer()->selected())
e->dragPos = e->insert_position();
if (c != FL_Up && c != FL_Down) {
e->buffer()->unselect();
Fl::copy("", 0, 0);
e->show_insert_position();
}
switch (c) {
case FL_Home:
e->insert_position(0);
e->scroll(0, 0);
break;
case FL_End:
e->insert_position(e->buffer()->length());
e->scroll(e->count_lines(0, e->buffer()->length(), 1), 0);
break;
case FL_Left:
e->previous_word();
break;
case FL_Right:
e->next_word();
break;
case FL_Up:
e->scroll(e->mTopLineNum-1, e->mHorizOffset);
break;
case FL_Down:
e->scroll(e->mTopLineNum+1, e->mHorizOffset);
break;
case FL_Page_Up:
e->insert_position(e->mLineStarts[0]);
break;
case FL_Page_Down:
e->insert_position(e->mLineStarts[e->mNVisibleLines-2]);
break;
}
return 1;
}
/** Moves the current text cursor in the direction indicated by meta key */
int Fl_Text_Editor_mod::kf_meta_move(int c, Fl_Text_Editor_mod* e) {
if (!e->buffer()->selected())
e->dragPos = e->insert_position();
if (c != FL_Up && c != FL_Down) {
e->buffer()->unselect();
Fl::copy("", 0, 0);
e->show_insert_position();
}
switch (c) {
case FL_Up: // top of buffer
e->insert_position(0);
e->scroll(0, 0);
break;
case FL_Down: // end of buffer
e->insert_position(e->buffer()->length());
e->scroll(e->count_lines(0, e->buffer()->length(), 1), 0);
break;
case FL_Left: // beginning of line
kf_move(FL_Home, e);
break;
case FL_Right: // end of line
kf_move(FL_End, e);
break;
}
return 1;
}
/** Extends the current selection in the direction indicated by meta key c. */
int Fl_Text_Editor_mod::kf_m_s_move(int c, Fl_Text_Editor_mod* e) {
kf_meta_move(c, e);
fl_text_drag_me(e->insert_position(), e);
return 1;
}
/** Extends the current selection in the direction indicated by control key c. */
int Fl_Text_Editor_mod::kf_c_s_move(int c, Fl_Text_Editor_mod* e) {
kf_ctrl_move(c, e);
fl_text_drag_me(e->insert_position(), e);
return 1;
}
/** Moves the text cursor to the beginning of the current line.*/
int Fl_Text_Editor_mod::kf_home(int, Fl_Text_Editor_mod* e) {
return kf_move(FL_Home, e);
}
/** Moves the text cursor to the end of the current line.*/
int Fl_Text_Editor_mod::kf_end(int, Fl_Text_Editor_mod* e) {
return kf_move(FL_End, e);
}
/** Moves the text cursor one character to the left.*/
int Fl_Text_Editor_mod::kf_left(int, Fl_Text_Editor_mod* e) {
return kf_move(FL_Left, e);
}
/** Moves the text cursor one line up.*/
int Fl_Text_Editor_mod::kf_up(int, Fl_Text_Editor_mod* e) {
return kf_move(FL_Up, e);
}
/** Moves the text cursor one character to the right.*/
int Fl_Text_Editor_mod::kf_right(int, Fl_Text_Editor_mod* e) {
return kf_move(FL_Right, e);
}
/** Moves the text cursor one line down.*/
int Fl_Text_Editor_mod::kf_down(int, Fl_Text_Editor_mod* e) {
return kf_move(FL_Down, e);
}
/** Moves the text cursor up one page.*/
int Fl_Text_Editor_mod::kf_page_up(int, Fl_Text_Editor_mod* e) {
return kf_move(FL_Page_Up, e);
}
/** Moves the text cursor down one page.*/
int Fl_Text_Editor_mod::kf_page_down(int, Fl_Text_Editor_mod* e) {
return kf_move(FL_Page_Down, e);
}
/** Toggles the insert mode in the text editor.*/
int Fl_Text_Editor_mod::kf_insert(int, Fl_Text_Editor_mod* e) {
e->insert_mode(e->insert_mode() ? 0 : 1);
return 1;
}
/** Does a delete of selected text or the current character in the current buffer.*/
int Fl_Text_Editor_mod::kf_delete(int, Fl_Text_Editor_mod* e) {
if (!e->buffer()->selected()) {
int p1 = e->insert_position();
int p2 = e->buffer()->next_char(p1);
e->buffer()->select(p1, p2);
}
kill_selection(e);
e->show_insert_position();
e->set_changed();
if (e->when()&FL_WHEN_CHANGED) e->do_callback();
return 1;
}
/** Does a copy of selected text or the current character in the current buffer.*/
int Fl_Text_Editor_mod::kf_copy(int, Fl_Text_Editor_mod* e) {
if (!e->buffer()->selected()) return 1;
const char *copy = e->buffer()->selection_text();
if (*copy) Fl::copy(copy, strlen(copy), 1);
free((void*)copy);
e->show_insert_position();
return 1;
}
/** Does a cut of selected text in the current buffer.*/
int Fl_Text_Editor_mod::kf_cut(int c, Fl_Text_Editor_mod* e) {
kf_copy(c, e);
kill_selection(e);
e->set_changed();
if (e->when()&FL_WHEN_CHANGED) e->do_callback();
return 1;
}
/** Does a paste of selected text in the current buffer.*/
int Fl_Text_Editor_mod::kf_paste(int, Fl_Text_Editor_mod* e) {
kill_selection(e);
Fl::paste(*e, 1);
e->show_insert_position();
e->set_changed();
if (e->when()&FL_WHEN_CHANGED) e->do_callback();
return 1;
}
/** Selects all text in the current buffer.*/
int Fl_Text_Editor_mod::kf_select_all(int, Fl_Text_Editor_mod* e) {
e->buffer()->select(0, e->buffer()->length());
const char *copy = e->buffer()->selection_text();
if (*copy) Fl::copy(copy, strlen(copy), 0);
free((void*)copy);
return 1;
}
/** Undo last edit in the current buffer. Also deselect previous selection. */
int Fl_Text_Editor_mod::kf_undo(int , Fl_Text_Editor_mod* e) {
e->buffer()->unselect();
Fl::copy("", 0, 0);
int crsr;
int ret = e->buffer()->undo(&crsr);
e->insert_position(crsr);
e->show_insert_position();
e->set_changed();
if (e->when()&FL_WHEN_CHANGED) e->do_callback();
return ret;
}
/** Handles a key press in the editor */
int Fl_Text_Editor_mod::handle_key() {
// Call FLTK's rules to try to turn this into a printing character.
// This uses the right-hand ctrl key as a "compose prefix" and returns
// the changes that should be made to the text, as a number of
// bytes to delete and a std::string to insert:
int del = 0;
int key = Fl::event_key(), state = Fl::event_state();//, c = Fl::event_text()[0];
if (key == FL_Caps_Lock) return 0;
if (Fl::compose(del)) {
if (del) {
int dp = insert_position(), di = del;
while (di--) dp = buffer()->prev_char_clipped(dp);
buffer()->select(dp, insert_position());
}
kill_selection(this);
if (Fl::event_length()) {
if (insert_mode()) insert(Fl::event_text());
else overstrike(Fl::event_text());
}
show_insert_position();
set_changed();
if (when()&FL_WHEN_CHANGED) do_callback();
return 1;
}
state &= FL_SHIFT|FL_CTRL|FL_ALT|FL_META; // only care about these states
Key_Func f;
f = bound_key_function(key, state, global_key_bindings);
if (!f && key_bindings) f = bound_key_function(key, state, key_bindings);
if (f) return f(key, this);
if (default_key_function_ && !state) return default_key_function_(key, this);
return 0;
}
/** does or does not a callback according to changed() and when() settings */
void Fl_Text_Editor_mod::maybe_do_callback() {
if (changed() || (when()&FL_WHEN_NOT_CHANGED)) do_callback();
}
int Fl_Text_Editor_mod::handle(int event) {
static int dndCursorPos;
if (!buffer()) return 0;
switch (event) {
case FL_FOCUS:
show_cursor(mCursorOn); // redraws the cursor
if (buffer()->selected()) redraw(); // Redraw selections...
Fl::focus(this);
return 1;
case FL_UNFOCUS:
show_cursor(mCursorOn); // redraws the cursor
if (buffer()->selected()) redraw(); // Redraw selections...
case FL_HIDE:
if (when() & FL_WHEN_RELEASE) maybe_do_callback();
return 1;
case FL_KEYBOARD:
if (active_r() && window() && this == Fl::belowmouse())
window()->cursor(FL_CURSOR_NONE);
return handle_key();
case FL_PASTE:
if (!Fl::event_text()) {
fl_beep();
return 1;
}
buffer()->remove_selection();
if (insert_mode()) insert(Fl::event_text());
else overstrike(Fl::event_text());
show_insert_position();
set_changed();
if (when()&FL_WHEN_CHANGED) do_callback();
return 1;
case FL_ENTER:
// MRS: WIN32 only? Need to test!
// case FL_MOVE:
show_cursor(mCursorOn);
return 1;
case FL_PUSH:
if (Fl::event_button() == 2) {
// don't let the text_display see this event
if (Fl_Group::handle(event)) return 1;
dragType = DRAG_NONE;
if(buffer()->selected()) {
buffer()->unselect();
}
int pos = xy_to_position(Fl::event_x(), Fl::event_y(), CURSOR_POS);
insert_position(pos);
Fl::paste(*this, 0);
Fl::focus(this);
set_changed();
if (when()&FL_WHEN_CHANGED) do_callback();
return 1;
}
break;
case FL_SHORTCUT:
if (!(shortcut() ? Fl::test_shortcut(shortcut()) : test_shortcut()))
return 0;
if (Fl::visible_focus() && handle(FL_FOCUS)) {
Fl::focus(this);
return 1;
}
break;
// Handle drag'n'drop attempt by the user. This is a simplified
// implementation which allows dnd operations onto the scroll bars.
case FL_DND_ENTER: // save the current cursor position
if (Fl::visible_focus() && handle(FL_FOCUS))
Fl::focus(this);
show_cursor(mCursorOn);
dndCursorPos = insert_position();
/* fall through */
case FL_DND_DRAG: // show a temporary insertion cursor
insert_position(xy_to_position(Fl::event_x(), Fl::event_y(), CURSOR_POS));
return 1;
case FL_DND_LEAVE: // restore original cursor
insert_position(dndCursorPos);
return 1;
case FL_DND_RELEASE: // keep insertion cursor and wait for the FL_PASTE event
buffer()->unselect(); // FL_PASTE must not destroy current selection!
return 1;
}
return Fl_Text_Display_mod::handle(event);
}
//
// End of "$Id: Fl_Text_Editor_mod.cxx 8034 2010-12-15 12:21:55Z AlbrechtS $".
//

View file

@ -255,7 +255,12 @@ void set_message_icon(const char** pixmap)
Fl_Widget* msg = fl_message_icon();
msg->label("");
msg->align(FL_ALIGN_TOP_LEFT | FL_ALIGN_INSIDE);
msg->color(msg->parent()->color());
if (!msg->parent())
msg->color(FL_BACKGROUND_COLOR);
else
msg->color(msg->parent()->color());
msg->box(FL_NO_BOX);
msg->image(msg_icon = new Fl_Pixmap(pixmap));
}