Fix confusing behavior of class Fl_Text_Selection.

Fl_Text_Selection got a new method length() and returns 0 in length()
and in all offsets (start(), end(), position()) if no text is selected
(selected() == false).

The behavior in FLTK 1.3 and earlier versions (returning undefined
values if !selected()) was confusing.


git-svn-id: file:///fltk/svn/fltk/branches/branch-1.4@12356 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
Albrecht Schlosser 2017-07-26 12:32:13 +00:00
parent 4c999258f1
commit 6b24b20966
3 changed files with 141 additions and 60 deletions

View File

@ -18,6 +18,10 @@ Changes in FLTK 1.4.0 Released: ??? ?? 2017
New Features and Extensions
- (add new items here)
- Fl_Text_Selection got a new method length() and returns 0 in length()
and in all offsets (start(), end(), position()) if no text is selected
(selected() == false). The behavior in FLTK 1.3 and earlier versions
(returning undefined values if !selected()) was confusing.
- Added support for MacOS 10.13 "High Sierra".
- New method Fl_Group::bounds() replaces Fl_Group::sizes() which is now
deprecated. Fl_Group::bounds() uses the new class Fl_Rect that contains

View File

@ -3,7 +3,7 @@
//
// Header file for Fl_Text_Buffer class.
//
// Copyright 2001-2016 by Bill Spitzak and others.
// Copyright 2001-2017 by Bill Spitzak and others.
// Original code Copyright Mark Edel. Permission to distribute under
// the LGPL for the FLTK library granted by Mark Edel.
//
@ -61,71 +61,108 @@
/**
\class Fl_Text_Selection
\brief This is an internal class for Fl_Text_Buffer 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_Text_Selection
\brief This is an internal class for Fl_Text_Buffer to manage text selections.
All methods use byte (not UTF-8 character) offsets and start at 0. This
class works correctly with UTF-8 strings assuming that the parameters
for all calls are on character boundaries.
If the selection is inactive (not currently used), then selected()
returns \p false and start() and end() return 0 (zero).
The stored offsets are in ascending order, hence the following conditions
are true (pseudo code):
\code
if ( !selected() ) : (start() == 0) && (end() == 0) && (start() == end())
if ( selected() ) : start() < end()
always : 0 <= start() <= end()
always : length() == end() - start()
\endcode
The selection size in bytes can always (unconditionally) be computed by
\code
int size = sel->end() - sel->start();
\endcode
\see length()
\note
The \b protected member variables \p mStart and \p mEnd are not
necessarily 0 (zero) if mSelected == \p false because they are
not cleared when \p selected(false) is called (as of Jul 2017).
This may be changed in the future.
*/
class FL_EXPORT Fl_Text_Selection {
friend class Fl_Text_Buffer;
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);
// Sets the selection range and selected().
void set(int startpos, int endpos);
/**
\brief Updates a selection after text was modified.
Updates an individual selection for changes in the corresponding text
\param pos byte offset into text buffer at which the change occurred
\param nDeleted number of bytes deleted from the buffer
\param nInserted number of bytes inserted into the buffer
*/
// Updates a selection after text was modified.
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 Returns the byte offset to the first selected character.
The returned offset is only valid if selected() returns true.
If the selection is not valid the returned offset is 0 since FLTK 1.4.0.
\note In FLTK 1.3.x the returned offset could be non-zero even if
selected() would have returned 0.
\return byte offset or 0 if not selected.
*/
int start() const { return mSelected ? mStart : 0; }
/**
\brief Return the byte offset to the character after the last selected character.
\return byte offset
*/
int end() const { return mEnd; }
\brief Returns the byte offset to the character after the last selected character.
The returned offset is only valid if selected() returns true (non-zero).
The offset is 0 if no text is selected (since FLTK 1.4.0).
\note In FLTK 1.3.x the returned offset could be non-zero even if
selected() would have returned 0.
\return byte offset or 0 if not selected.
*/
int end() const { return mSelected ? mEnd : 0; }
/**
\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.
*/
\return \p true if any text has been selected, or \p false
if no text is selected.
*/
bool selected() const { return mSelected; }
/**
\brief Modify the 'selected' flag.
\param b new flag
*/
\brief Modifies 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.
*/
\brief Returns the size in bytes of the selection.
This is a convenience method. It always returns the same as
\code
end() - start()
\endcode
and it returns 0 if selected() == false.
\return size in bytes or 0 if not selected.
\since FLTK 1.4.0
*/
int length() const { return mSelected ? mEnd - mStart : 0; }
// Returns true if position \p pos is in this Fl_Text_Selection.
int includes(int pos) const;
/**
\brief Return the positions of this selection.
\param start return byte offset to first selected character
\param end return byte offset pointing after last selected character
\return true if selected
*/
int position(int* start, int* end) const;
// Returns true if selected() and the positions of this selection.
int position(int *startpos, int *endpos) const;
protected:

View File

@ -1,7 +1,7 @@
//
// "$Id$"
//
// Copyright 2001-2016 by Bill Spitzak and others.
// Copyright 2001-2017 by Bill Spitzak and others.
// Original code Copyright Mark Edel. Permission to distribute under
// the LGPL for the FLTK library granted by Mark Edel.
//
@ -1214,36 +1214,66 @@ void Fl_Text_Buffer::remove_(int start, int end)
}
/*
simple setter.
Unicode safe. Start and end must be at a character boundary.
*/
/**
\brief Sets the selection range.
\p startpos and \p endpos must be at a character boundary.
If \p startpos != \p endpos selected() is set to true, else to false.
If \p startpos is greater than \p endpos they are swapped so that
\p startpos \<= \p endpos.
\param[in] startpos byte offset to first selected character
\param[in] endpos byte offset pointing after last selected character
*/
void Fl_Text_Selection::set(int startpos, int endpos)
{
mSelected = startpos != endpos;
mSelected = (startpos != endpos);
mStart = min(startpos, endpos);
mEnd = max(startpos, endpos);
}
/*
simple getter.
Unicode safe. Start and end will be at a character boundary.
*/
/**
\brief Returns the status and the positions of this selection.
This method returns the same as \p selected() as an \p int (0 or 1)
in its return value and the offsets to the start of the selection
in \p startpos and to the byte after the last selected character
in \p endpos, if selected() is \p true.
If selected() is \p false, both offsets are set to 0.
\note In FLTK 1.3.x \p startpos and \p endpos were \b not \b modified
if selected() was false.
\param startpos return byte offset to first selected character
\param endpos return byte offset pointing after last selected character
\return whether the selection is active (selected()) or not
\retval 0 if not selected
\retval 1 if selected
\see selected(), start(), end()
*/
int Fl_Text_Selection::position(int *startpos, int *endpos) const {
if (!mSelected)
if (!mSelected) {
*startpos = 0;
*endpos = 0;
return 0;
}
*startpos = mStart;
*endpos = mEnd;
return 1;
}
/*
Return if a position is inside the selected area.
Unicode safe. Pos must be at a character boundary.
*/
/**
Returns true if position \p pos is in the Fl_Text_Selection.
\p pos must be at a character boundary.
*/
int Fl_Text_Selection::includes(int pos) const {
return (selected() && pos >= start() && pos < end() );
}
@ -1447,7 +1477,17 @@ void Fl_Text_Buffer::update_selections(int pos, int nDeleted,
}
/**
\brief Updates a selection after text was modified.
Updates an individual selection for changes in the corresponding text.
\param pos byte offset into text buffer at which the change occurred
\param nDeleted number of bytes deleted from the buffer
\param nInserted number of bytes inserted into the buffer
*/
// unicode safe, assuming the arguments are on character boundaries
void Fl_Text_Selection::update(int pos, int nDeleted, int nInserted)
{
if (!mSelected || pos > mEnd)