Implemented search backwards for utf-8. Tested on MSWindows - OK. Tested on Linux (Ubuntu) - K.

git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@7808 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
Matthias Melcher 2010-11-07 20:13:50 +00:00
parent f099311481
commit accf34f276
4 changed files with 58 additions and 103 deletions

View File

@ -175,7 +175,6 @@ typedef void (*Fl_Text_Predelete_Cb)(int pos, int nDeleted, void* cbArg);
The Fl_Text_Buffer class is used by the Fl_Text_Display
and Fl_Text_Editor to manage complex text data and is based upon the
excellent NEdit text editor engine - see http://www.nedit.org/.
\todo unicode check
*/
class FL_EXPORT Fl_Text_Buffer {
public:
@ -212,7 +211,6 @@ public:
/**
Replaces the entire contents of the text buffer.
\param text Text must be valid utf8.
\todo unicode check
*/
void text(const char* text);
@ -270,7 +268,6 @@ public:
/**
Appends the text string to the end of the buffer.
\param t utf-8 encoded and nul terminated text
\todo unicode check
*/
void append(const char* t) { insert(length(), t); }
@ -295,14 +292,12 @@ public:
\param fromStart byte offset into buffer
\param fromEnd byte offset into buffer
\param toPos destination byte offset into buffer
\todo unicode check
*/
void copy(Fl_Text_Buffer* fromBuf, int fromStart, int fromEnd, int toPos);
/**
Undo text modification according to the undo variables or insert text
from the undo buffer
\todo unicode check
*/
int undo(int *cp=0);
@ -316,7 +311,6 @@ public:
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).
\todo unicode check
*/
int insertfile(const char *file, int pos, int buflen = 128*1024);
@ -325,14 +319,12 @@ public:
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).
\todo unicode check
*/
int appendfile(const char *file, int buflen = 128*1024)
{ return insertfile(file, length(), buflen); }
/**
Loads a text file into the buffer
\todo unicode check
*/
int loadfile(const char *file, int buflen = 128*1024)
{ select(0, length()); remove_selection(); return appendfile(file, buflen); }
@ -342,33 +334,28 @@ public:
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).
\todo unicode check
*/
int outputfile(const char *file, int start, int end, int buflen = 128*1024);
/**
Saves a text file from the current buffer
\todo unicode check
*/
int savefile(const char *file, int buflen = 128*1024)
{ return outputfile(file, 0, length(), buflen); }
/**
Gets the tab width.
\todo unicode check
*/
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.
\todo unicode check
*/
void tab_distance(int tabDist);
/**
Selects a range of characters in the buffer.
\todo unicode check
*/
void select(int start, int end);
@ -379,38 +366,32 @@ public:
/**
Cancels any previous selection on the primary text selection object
\todo unicode check
*/
void unselect();
/**
Gets the selection position
\todo unicode check
*/
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.
\todo unicode check
*/
char* selection_text();
/**
Removes the text in the primary selection.
\todo unicode check
*/
void remove_selection();
/**
Replaces the text in the primary selection.
\todo unicode check
*/
void replace_selection(const char* text);
/**
Selects a range of characters in the secondary selection.
\todo unicode check
*/
void secondary_select(int start, int end);
@ -422,39 +403,33 @@ public:
/**
Clears any selection in the secondary text selection object.
\todo unicode check
*/
void secondary_unselect();
/**
Returns the current selection in the secondary text selection object.
\todo unicode check
*/
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.
\todo unicode check
*/
char* secondary_selection_text();
/**
Removes the text from the buffer corresponding to the secondary text selection object.
\todo unicode check
*/
void remove_secondary_selection();
/**
Replaces the text from the buffer corresponding to the secondary
text selection object with the new string \p text.
\todo unicode check
*/
void replace_secondary_selection(const char* text);
/**
Highlights the specified text within the buffer.
\todo unicode check
*/
void highlight(int start, int end);
@ -466,20 +441,17 @@ public:
/**
Unhighlights text in the buffer.
\todo unicode check
*/
void unhighlight();
/**
Highlights the specified text between \p start and \p end within the buffer.
\todo unicode check
*/
int highlight_position(int* start, int* end);
/**
Returns the highlighted text. When you are done with the
text, free it using the free() function.
\todo unicode check
*/
char* highlight_text();
@ -492,13 +464,11 @@ public:
int nRestyled, const char* deletedText,
void* cbArg);
\endcode
\todo unicode check
*/
void add_modify_callback(Fl_Text_Modify_Cb bufModifiedCB, void* cbArg);
/**
Removes a modify callback.
\todo unicode check
*/
void remove_modify_callback(Fl_Text_Modify_Cb bufModifiedCB, void* cbArg);
@ -506,27 +476,23 @@ public:
Calls all modify callbacks that have been registered using
the add_modify_callback()
method.
\todo unicode check
*/
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.
\todo unicode check
*/
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.
\todo unicode check
*/
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.
\todo unicode check
*/
void call_predelete_callbacks() { call_predelete_callbacks(0, 0); }
@ -536,7 +502,6 @@ public:
using the free() function.
\param pos byte index into buffer
\return copy of utf8 text, must be free'd
\todo unicode check
*/
char* line_text(int pos) const;
@ -544,7 +509,6 @@ public:
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
\todo unicode check
*/
int line_start(int pos) const;
@ -554,7 +518,6 @@ public:
or a pointer to one character beyond the end of the buffer)
\param pos byte index into buffer
\return byte offset to line end
\todo unicode check
*/
int line_end(int pos) const;
@ -562,7 +525,6 @@ public:
Returns the position corresponding to the start of the word
\param pos byte index into buffer
\return byte offset to word start
\todo unicode check
*/
int word_start(int pos) const;
@ -570,7 +532,6 @@ public:
Returns the position corresponding to the end of the word.
\param pos byte index into buffer
\return byte offset to word end
\todo unicode check
*/
int word_end(int pos) const;
@ -579,7 +540,6 @@ public:
\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)
\todo unicode check
*/
int count_displayed_characters(int lineStartPos, int targetPos) const;
@ -590,21 +550,18 @@ public:
\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
\todo unicode check
*/
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.
\todo unicode check
*/
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
\todo unicode check
*/
int skip_lines(int startPos, int nLines);
@ -612,7 +569,6 @@ public:
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
\todo unicode check
*/
int rewind_lines(int startPos, int nLines);
@ -628,7 +584,6 @@ public:
\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
\todo unicode check
*/
int findchar_forward(int startPos, unsigned searchChar, int* foundPos) const;
@ -643,7 +598,6 @@ public:
\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
\todo unicode check
*/
int findchar_backward(int startPos, unsigned searchChar, int* foundPos) const;
@ -656,7 +610,6 @@ public:
\param foundPos byte offset where the string was found
\param matchCase if set, match character case
\return 1 if found, 0 if not
\todo unicode check
*/
int search_forward(int startPos, const char* searchString, int* foundPos,
int matchCase = 0) const;
@ -670,7 +623,6 @@ public:
\param foundPos byte offset where the string was found
\param matchCase if set, match character case
\return 1 if found, 0 if not
\todo unicode check
*/
int search_backward(int startPos, const char* searchString, int* foundPos,
int matchCase = 0) const;
@ -733,7 +685,6 @@ protected:
/**
Calls the stored modify callback procedure(s) for this buffer to update the
changed area(s) on the screen and any other listeners.
\todo unicode check
*/
void call_modify_callbacks(int pos, int nDeleted, int nInserted,
int nRestyled, const char* deletedText) const;
@ -741,7 +692,6 @@ protected:
/**
Calls the stored pre-delete callback procedure(s) for this buffer to update
the changed area(s) on the screen and any other listeners.
\todo unicode check
*/
void call_predelete_callbacks(int pos, int nDeleted) const;
@ -752,7 +702,6 @@ protected:
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
\todo unicode check
*/
int insert_(int pos, const char* text);
@ -760,27 +709,24 @@ protected:
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).
\todo unicode check
*/
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.
\todo unicode check
*/
void redisplay_selection(Fl_Text_Selection* oldSelection,
Fl_Text_Selection* newSelection) const;
/**
\todo unicode check
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.
\todo unicode check
*/
void reallocate_with_gap(int newGapStart, int newGapLen);
@ -788,19 +734,16 @@ protected:
/**
Removes the text from the buffer corresponding to \p sel.
\todo unicode check
*/
void remove_selection_(Fl_Text_Selection* sel);
/**
Replaces the \p text in selection \p sel.
\todo unicode check
*/
void replace_selection_(Fl_Text_Selection* sel, const char* text);
/**
Updates all of the selections in the buffer for changes in the buffer's text
\todo unicode check
*/
void update_selections(int pos, int nDeleted, int nInserted);

View File

@ -856,13 +856,11 @@ int Fl_Text_Buffer::word_end(int pos) const {
/*
Matt: I am not sure why we need this function. Does it still make sense in
the world of proportional characters?
Count the number of characters between two positions.
*/
int Fl_Text_Buffer::count_displayed_characters(int lineStartPos,
int targetPos) const
{
// FIXME: this is misleading and may be used to count bytes instead of characters!
IS_UTF8_ALIGNED(address(lineStartPos))
IS_UTF8_ALIGNED(address(targetPos))
@ -878,16 +876,13 @@ int Fl_Text_Buffer::count_displayed_characters(int lineStartPos,
/*
Matt: I am not sure why we need this function. Does it still make sense in
the world of proportional characters?
Skip ahead a number of characters from a given index.
This function breaks early if it encounters a newline character.
*/
// All values are number of bytes.
// - unicode ok?
int Fl_Text_Buffer::skip_displayed_characters(int lineStartPos, int nChars)
{
// FIXME: this is misleading and may be used to count bytes instead of characters!
IS_UTF8_ALIGNED(address(lineStartPos))
// FIXME: is this function still needed?
int pos = lineStartPos;
for (int charCount = 0; charCount < nChars && pos < mLength; charCount++) {
@ -1060,37 +1055,60 @@ int Fl_Text_Buffer::search_forward(int startPos, const char *searchString,
return 0;
}
/*
Find a matching string in the buffer.
NOT TESTED FOR UNICODE.
*/
int Fl_Text_Buffer::search_backward(int startPos, const char *searchString,
int *foundPos, int matchCase) const {
// FIXME: Unicode?
int *foundPos, int matchCase) const
{
IS_UTF8_ALIGNED(address(startPos))
IS_UTF8_ALIGNED(searchString)
if (!searchString)
return 0;
int bp;
const char *sp;
while (startPos > 0)
{
bp = startPos - 1;
sp = searchString + strlen(searchString) - 1;
do {
if (sp < searchString) {
*foundPos = bp + 1;
return 1;
if (matchCase) {
while (startPos >= 0) {
bp = startPos;
sp = searchString;
for (;;) {
char c = *sp;
// we reached the end of the "needle", so we found the string!
if (!c) {
*foundPos = startPos;
return 1;
}
int l = fl_utf8len(c);
if (memcmp(sp, address(bp), l))
break;
sp += l; bp += l;
}
// FIXME: character is ucs-4
} while ((matchCase ? char_at(bp--) == (unsigned int)*sp-- :
toupper(char_at(bp--)) == toupper(*sp--))
&& bp >= 0);
startPos--;
}
startPos = prev_char(startPos);
}
} else {
while (startPos >= 0) {
bp = startPos;
sp = searchString;
for (;;) {
// we reached the end of the "needle", so we found the string!
if (!*sp) {
*foundPos = startPos;
return 1;
}
int l;
unsigned int b = char_at(bp);
unsigned int s = fl_utf8decode(sp, 0, &l);
if (fl_tolower(b)!=fl_tolower(s))
break;
sp += l;
bp = next_char(bp);
}
startPos = prev_char(startPos);
}
}
return 0;
}
/*
Insert a string into the buffer.
Pos must be at a character boundary. Text must be a correct utf8 string.
@ -1422,7 +1440,6 @@ void Fl_Text_Buffer::update_selections(int pos, int nDeleted,
// unicode safe, assuming the arguments are on character boundaries
void Fl_Text_Selection::update(int pos, int nDeleted, int nInserted)
{
// FIXME: check if this is safe when seletion crosses selction boundaries
if (!mSelected || pos > mEnd)
return;
if (pos + nDeleted <= mStart) {

View File

@ -33,6 +33,7 @@
// TODO: verify all "byte counts" vs. "character counts"
// TODO: rendering of the Tab character
// TODO: rendering of the "optional hyphen"
// TODO: make line numbering work again
#include <stdio.h>
#include <stdlib.h>
@ -948,8 +949,6 @@ void Fl_Text_Display::display_insert() {
hOffset = mHorizOffset;
topLine = mTopLineNum;
// FIXME: I don't understand this well enough to know if it is correct
// it is different than nedit 5.3
if (insert_position() < mFirstChar) {
topLine -= count_lines(insert_position(), mFirstChar, false);
} else if (mLineStarts[mNVisibleLines-2] != -1) {
@ -1296,8 +1295,8 @@ int Fl_Text_Display::rewind_lines(int startPos, int nLines) {
// FIXME: this does not take UCS-4 encoding into account
static inline int fl_isseparator(unsigned int c) {
// FIXME: this does not take UCS-4 encoding into account
return c != '$' && c != '_' && (isspace(c) || ispunct(c));
}
@ -1333,7 +1332,7 @@ void Fl_Text_Display::previous_word() {
while (pos && fl_isseparator(buffer()->char_at(pos))) {
pos = buffer()->prev_char(pos);
}
// FIXME: character is ucs-4
while (pos && !fl_isseparator(buffer()->char_at(pos))) {
pos = buffer()->prev_char(pos);
}
@ -1663,7 +1662,7 @@ int Fl_Text_Display::position_to_line( int pos, int *lineNum ) const {
\retval FIND_INDEX x pixel position inside given block
\todo we need to handle hidden hyphens and tabs here!
\todo we handle all styles and selections
\todo we must provide code to get pixle positions of the middle of a character as well
\todo we must provide code to get pixel positions of the middle of a character as well
*/
int Fl_Text_Display::handle_vline(
int mode,
@ -2572,8 +2571,6 @@ void Fl_Text_Display::h_scrollbar_cb(Fl_Scrollbar* b, Fl_Text_Display* textD) {
*/
void Fl_Text_Display::draw_line_numbers(bool /*clearAll*/) {
#if 0
// FIXME: don't want this yet, so will leave for another time
int y, line, visLine, nCols, lineStart;
char lineNumString[12];
int lineHeight = mMaxsize ? mMaxsize : textsize_;
@ -2940,9 +2937,7 @@ void Fl_Text_Display::measure_deleted_lines(int pos, int nDeleted) {
} else
lineStart = retPos;
nLines++;
if (lineStart > pos + nDeleted &&
// FIXME: character is ucs-4
buf->char_at(lineStart-1) == '\n') {
if (lineStart > pos + nDeleted && buf->char_at(lineStart-1) == '\n') {
break;
}

View File

@ -378,11 +378,11 @@ int fl_latin12utf(const unsigned char *str, int len, char *buf)
*/
unsigned int fl_nonspacing(unsigned int ucs)
{
#ifdef __APPLE__
return (ucs==0x20); // FIXME: what does this really do?
#else
//#ifdef __APPLE__
// return (ucs==0x20); // FIXME: what does this really do?
//#else
return (unsigned int) XUtf8IsNonSpacing(ucs);
#endif
//#endif
}
#if defined(WIN32) && !defined(__CYGWIN__)