Browse Source

Starting to rework Fl_Text_Display from scratch to make wrapping work correctly. Fixed a few issues that made wrapping crash. Using ASCII range only with fixed character sizes should still wrap as expected?!

git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@7794 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
pull/49/head
Matthias Melcher 15 years ago
parent
commit
38dcb5a463
  1. 14
      FL/Fl_Text_Buffer.H
  2. 86
      FL/Fl_Text_Display.H
  3. 13
      src/Fl_Text_Buffer.cxx
  4. 179
      src/Fl_Text_Display.cxx
  5. 2
      test/editor.cxx

14
FL/Fl_Text_Buffer.H

@ -39,7 +39,7 @@
?? "length" is the number of characters in a string ?? "length" is the number of characters in a string
?? "size" is the number of bytes ?? "size" is the number of bytes
?? "index" is the position in a string in number of characters ?? "index" is the position in a string in number of characters
?? "offset" is the position in a strin in bytes (and must be kept on a charater boundary) ?? "offset" is the position in a string in bytes (and must be kept on a charater boundary)
(there seems to be no standard in Uncode documents, howevere "length" is commonly (there seems to be no standard in Uncode documents, howevere "length" is commonly
referencing the number of bytes. Maybe "bytes" and "glyphs" would be the most referencing the number of bytes. Maybe "bytes" and "glyphs" would be the most
obvious way to describe sizes?) obvious way to describe sizes?)
@ -154,6 +154,11 @@ 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 widgets. \brief This class manages unicode displayed in one or more Fl_Text_Display widgets.
All text in Fl_Text_Buffermust 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 class is used by the Fl_Text_Display 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 and Fl_Text_Editor to manage complex text data and is based upon the
excellent NEdit text editor engine - see http://www.nedit.org/. excellent NEdit text editor engine - see http://www.nedit.org/.
@ -193,7 +198,7 @@ public:
/** /**
Replaces the entire contents of the text buffer. Replaces the entire contents of the text buffer.
Text must be valid utf8. \param text Text must be valid utf8.
\todo unicode check \todo unicode check
*/ */
void text(const char* text); void text(const char* text);
@ -228,12 +233,16 @@ public:
/** /**
Convert a byte offset in buffer into a memory address. 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 const char *address(int pos) const
{ return (pos < mGapStart) ? mBuf+pos : mBuf+pos+mGapEnd-mGapStart; } { return (pos < mGapStart) ? mBuf+pos : mBuf+pos+mGapEnd-mGapStart; }
/** /**
Convert a byte offset in buffer into a memory address. 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) char *address(int pos)
{ return (pos < mGapStart) ? mBuf+pos : mBuf+pos+mGapEnd-mGapStart; } { return (pos < mGapStart) ? mBuf+pos : mBuf+pos+mGapEnd-mGapStart; }
@ -748,6 +757,7 @@ protected:
expensive and the length will be required by any caller who will continue 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 on to call redisplay). \p pos must be contiguous with the existing text in
the buffer (i.e. not past the end). the buffer (i.e. not past the end).
\return the number of bytes inserted
\todo unicode check \todo unicode check
*/ */
int insert_(int pos, const char* text); int insert_(int pos, const char* text);

86
FL/Fl_Text_Display.H

@ -40,22 +40,26 @@
#include "Fl_Text_Buffer.H" #include "Fl_Text_Buffer.H"
/** /**
This is the FLTK text display widget. It allows the user to \brief Rich text display widget.
view multiple lines of text and supports highlighting and
scrolling. The buffer that is displayed in the widget is managed This is the FLTK text display widget. It allows the user to view multiple lines
by the Fl_Text_Buffer of text and supports highlighting and scrolling. The buffer that is displayed
class. in the widget is managed by the Fl_Text_Buffer class. A single Text Buffer
*/ can be displayed by multiple Text Displays.
*/
class FL_EXPORT Fl_Text_Display: public Fl_Group class FL_EXPORT Fl_Text_Display: public Fl_Group
{ {
public: public:
/** /**
text display cursor shapes enumeration text display cursor shapes enumeration
*/ */
enum { enum {
NORMAL_CURSOR, CARET_CURSOR, DIM_CURSOR, NORMAL_CURSOR, /**< I-beam */
BLOCK_CURSOR, HEAVY_CURSOR CARET_CURSOR, /**< caret under the text */
DIM_CURSOR, /**< dim I-beam */
BLOCK_CURSOR, /**< unfille box under the current character */
HEAVY_CURSOR /**< thick I-beam */
}; };
/** /**
@ -64,31 +68,25 @@ class FL_EXPORT Fl_Text_Display: public Fl_Group
characters. characters.
*/ */
enum { enum {
CURSOR_POS, CHARACTER_POS CURSOR_POS,
CHARACTER_POS
}; };
/** /**
drag types- they match Fl::event_clicks() so that single clicking to drag types - they match Fl::event_clicks() so that single clicking to
start a collection selects by character, double clicking selects by start a collection selects by character, double clicking selects by
word and triple clicking selects by line. word and triple clicking selects by line.
*/ */
enum { enum {
DRAG_CHAR = 0, DRAG_WORD = 1, DRAG_LINE = 2 DRAG_CHAR = 0,
DRAG_WORD = 1,
DRAG_LINE = 2
}; };
friend void fl_text_drag_me(int pos, Fl_Text_Display* d); friend void fl_text_drag_me(int pos, Fl_Text_Display* d);
typedef void (*Unfinished_Style_Cb)(int, void *); typedef void (*Unfinished_Style_Cb)(int, void *);
/**
style attributes - currently not implemented!
*/
enum {
ATTR_NONE = 0,
ATTR_UNDERLINE = 1,
ATTR_HIDDEN = 2
};
/** /**
This structure associates the color,font,size of a string to draw This structure associates the color,font,size of a string to draw
with an attribute mask matching attr with an attribute mask matching attr
@ -96,7 +94,7 @@ class FL_EXPORT Fl_Text_Display: public Fl_Group
struct Style_Table_Entry { struct Style_Table_Entry {
Fl_Color color; Fl_Color color;
Fl_Font font; Fl_Font font;
int size; Fl_Fontsize size;
unsigned attr; unsigned attr;
}; };
@ -104,17 +102,20 @@ class FL_EXPORT Fl_Text_Display: public Fl_Group
~Fl_Text_Display(); ~Fl_Text_Display();
virtual int handle(int e); virtual int handle(int e);
void buffer(Fl_Text_Buffer* buf); void buffer(Fl_Text_Buffer* buf);
/** /**
Sets or gets the current text buffer associated with the text widget. Sets the current text buffer associated with the text widget.
Multiple text widgets can be associated with the same text buffer. Multiple text widgets can be associated with the same text buffer.
\param buf new text buffer
*/ */
void buffer(Fl_Text_Buffer& buf) { buffer(&buf); } void buffer(Fl_Text_Buffer& buf) { buffer(&buf); }
/** /**
Gets the current text buffer associated with the text widget. Gets the current text buffer associated with the text widget.
Multiple text widgets can be associated with the same text buffer. Multiple text widgets can be associated with the same text buffer.
\return current text buffer
*/ */
Fl_Text_Buffer* buffer() const { return mBuffer; } Fl_Text_Buffer* buffer() const { return mBuffer; }
@ -126,11 +127,13 @@ class FL_EXPORT Fl_Text_Display: public Fl_Group
/** /**
Gets the position of the text insertion cursor for text display 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 insert_position() const { return mCursorPos; }
int in_selection(int x, int y) const; int in_selection(int x, int y) const;
void show_insert_position(); void show_insert_position();
int move_right(); int move_right();
int move_left(); int move_left();
int move_up(); int move_up();
@ -142,6 +145,7 @@ class FL_EXPORT Fl_Text_Display: public Fl_Group
int rewind_lines(int startPos, int nLines); int rewind_lines(int startPos, int nLines);
void next_word(void); void next_word(void);
void previous_word(void); void previous_word(void);
void show_cursor(int b = 1); void show_cursor(int b = 1);
/** /**
@ -152,42 +156,52 @@ class FL_EXPORT Fl_Text_Display: public Fl_Group
void cursor_style(int style); void cursor_style(int style);
/** /**
Sets or gets the text cursor color. Gets the text cursor color.
\return cursor color
*/ */
Fl_Color cursor_color() const {return mCursor_color;} Fl_Color cursor_color() const {return mCursor_color;}
/** /**
Sets or gets the text cursor color. Sets the text cursor color.
\param n new cursor color
*/ */
void cursor_color(Fl_Color n) {mCursor_color = n;} void cursor_color(Fl_Color n) {mCursor_color = n;}
/** /**
Sets or gets the width/height of the scrollbars. Gets the width/height of the scrollbars.
/return width of scrollbars
*/ */
int scrollbar_width() const { return scrollbar_width_; } int scrollbar_width() const { return scrollbar_width_; }
/** /**
Sets or gets the width/height of the scrollbars. Sets the width/height of the scrollbars.
\param W width of scrollbars
*/ */
void scrollbar_width(int W) { scrollbar_width_ = W; } void scrollbar_width(int W) { scrollbar_width_ = W; }
/** /**
Gets the scrollbar alignment type Gets the scrollbar alignment type
\return scrollbar alignment
*/ */
Fl_Align scrollbar_align() const { return scrollbar_align_; } Fl_Align scrollbar_align() const { return scrollbar_align_; }
/** /**
Sets the scrollbar alignment type Sets the scrollbar alignment type
\param a new scrollbar alignment
*/ */
void scrollbar_align(Fl_Align a) { scrollbar_align_ = a; } void scrollbar_align(Fl_Align a) { scrollbar_align_ = a; }
/** /**
Moves the insert position to the beginning of the current word. Moves the insert position to the beginning of the current word.
\param pos start calculation at this index
\return beginning of the wors
*/ */
int word_start(int pos) const { return buffer()->word_start(pos); } int word_start(int pos) const { return buffer()->word_start(pos); }
/** /**
Moves the insert position to the end of the current word. 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); } int word_end(int pos) const { return buffer()->word_end(pos); }
@ -203,42 +217,50 @@ class FL_EXPORT Fl_Text_Display: public Fl_Group
/** /**
\todo FIXME : get set methods pointing on shortcut_ \todo FIXME : get set methods pointing on shortcut_
have no effects as shortcut_ is unused in this class and derived! have no effects as shortcut_ is unused in this class and derived!
\return the current shortcut key
*/ */
int shortcut() const {return shortcut_;} int shortcut() const {return shortcut_;}
/** /**
\todo FIXME : get set methods pointing on shortcut_ \todo FIXME : get set methods pointing on shortcut_
have no effects as shortcut_ is unused in this class and derived! have no effects as shortcut_ is unused in this class and derived!
\param s the new shortcut key
*/ */
void shortcut(int s) {shortcut_ = s;} void shortcut(int s) {shortcut_ = s;}
/** /**
Gets the default font used when drawing text in the widget. Gets the default font used when drawing text in the widget.
\return current text font face unless overriden by a style
*/ */
Fl_Font textfont() const {return textfont_;} Fl_Font textfont() const {return textfont_;}
/** /**
Sets the default font used when drawing text in the widget. Sets the default font used when drawing text in the widget.
\param s default text font face
*/ */
void textfont(Fl_Font s) {textfont_ = s;} void textfont(Fl_Font s) {textfont_ = s;}
/** /**
Gets the default size of text in the widget. Gets the default size of text in the widget.
\return current text height unless overriden by a style
*/ */
Fl_Fontsize textsize() const {return textsize_;} Fl_Fontsize textsize() const {return textsize_;}
/** /**
Sets the default size of text in the widget. Sets the default size of text in the widget.
\param s new text size
*/ */
void textsize(Fl_Fontsize s) {textsize_ = s;} void textsize(Fl_Fontsize s) {textsize_ = s;}
/** /**
Gets the default color of text in the widget. Gets the default color of text in the widget.
\return text color unless overriden by a style
*/ */
Fl_Color textcolor() const {return textcolor_;} Fl_Color textcolor() const {return textcolor_;}
/** /**
Sets the default color of text in the widget. Sets the default color of text in the widget.
\param n new text color
*/ */
void textcolor(Fl_Color n) {textcolor_ = n;} void textcolor(Fl_Color n) {textcolor_ = n;}
@ -248,7 +270,7 @@ class FL_EXPORT Fl_Text_Display: public Fl_Group
virtual void resize(int X, int Y, int W, int H); virtual void resize(int X, int Y, int W, int H);
protected: protected:
// Most (all?) of this stuff should only be called from resize() or // Most (all?) of this stuff should only be called from resize() or
// draw(). // draw().
// Anything with "vline" indicates thats it deals with currently // Anything with "vline" indicates thats it deals with currently
@ -266,7 +288,13 @@ class FL_EXPORT Fl_Text_Display: public Fl_Group
int leftCharIndex, int rightCharIndex); int leftCharIndex, int rightCharIndex);
int find_x(const char *s, int len, int style, int x) const; int find_x(const char *s, int len, int style, int x) const;
enum { DRAW_LINE, FIND_INDEX, GET_WIDTH };
enum {
DRAW_LINE,
FIND_INDEX,
GET_WIDTH
};
int handle_vline(int mode, int handle_vline(int mode,
int lineStart, int lineLen, int leftChar, int rightChar, int lineStart, int lineLen, int leftChar, int rightChar,
int topClip, int bottomClip, int topClip, int bottomClip,

13
src/Fl_Text_Buffer.cxx

@ -270,6 +270,10 @@ char Fl_Text_Buffer::byte_at(int pos) const {
*/ */
void Fl_Text_Buffer::insert(int pos, const char *text) void Fl_Text_Buffer::insert(int pos, const char *text)
{ {
/* check if there is actually any text */
if (!text || !*text)
return;
/* if pos is not contiguous to existing text, make it */ /* if pos is not contiguous to existing text, make it */
if (pos > mLength) if (pos > mLength)
pos = mLength; pos = mLength;
@ -1010,7 +1014,7 @@ int Fl_Text_Buffer::search_forward(int startPos, const char *searchString,
return 1; return 1;
} }
// FIXME: character is ucs-4 // FIXME: character is ucs-4
} while ((matchCase ? char_at(bp++) == *sp++ : } while ((matchCase ? char_at(bp++) == (unsigned int)*sp++ :
toupper(char_at(bp++)) == toupper(*sp++)) toupper(char_at(bp++)) == toupper(*sp++))
&& bp < length()); && bp < length());
startPos++; startPos++;
@ -1040,7 +1044,7 @@ int Fl_Text_Buffer::search_backward(int startPos, const char *searchString,
return 1; return 1;
} }
// FIXME: character is ucs-4 // FIXME: character is ucs-4
} while ((matchCase ? char_at(bp--) == *sp-- : } while ((matchCase ? char_at(bp--) == (unsigned int)*sp-- :
toupper(char_at(bp--)) == toupper(*sp--)) toupper(char_at(bp--)) == toupper(*sp--))
&& bp >= 0); && bp >= 0);
startPos--; startPos--;
@ -1128,6 +1132,9 @@ int Fl_Text_Buffer::findchars_backward(int startPos, const char *searchChars,
*/ */
int Fl_Text_Buffer::insert_(int pos, const char *text) int Fl_Text_Buffer::insert_(int pos, const char *text)
{ {
if (!text || !*text)
return 0;
int insertedLength = strlen(text); int insertedLength = strlen(text);
/* Prepare the buffer to receive the new text. If the new text fits in /* Prepare the buffer to receive the new text. If the new text fits in
@ -1246,7 +1253,7 @@ int Fl_Text_Selection::position(int *startpos, int *endpos) const {
*/ */
int Fl_Text_Selection::includes(int pos) const { int Fl_Text_Selection::includes(int pos) const {
return (selected() && pos >= start() && pos < end() ); return (selected() && pos >= start() && pos < end() );
} }
/* /*

179
src/Fl_Text_Display.cxx

@ -25,6 +25,8 @@
// http://www.fltk.org/str.php // http://www.fltk.org/str.php
// //
// TODO: check all functions for UTF-8/UCS-4 compatibility!
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <FL/fl_utf8.h> #include <FL/fl_utf8.h>
@ -79,7 +81,7 @@ static int scroll_x = 0;
/** Creates a new text display widget.*/ /** Creates a new text display widget.*/
Fl_Text_Display::Fl_Text_Display(int X, int Y, int W, int H, const char* l) Fl_Text_Display::Fl_Text_Display(int X, int Y, int W, int H, const char* l)
: Fl_Group(X, Y, W, H, l) { : Fl_Group(X, Y, W, H, l) {
int i; int i;
mMaxsize = 0; mMaxsize = 0;
@ -156,7 +158,7 @@ Fl_Text_Display::Fl_Text_Display(int X, int Y, int W, int H, const char* l)
Note, the text BUFFER that the text display displays is a separate Note, the text BUFFER that the text display displays is a separate
entity and is not freed, nor are the style buffer or style table. entity and is not freed, nor are the style buffer or style table.
*/ */
Fl_Text_Display::~Fl_Text_Display() { Fl_Text_Display::~Fl_Text_Display() {
if (scroll_direction) { if (scroll_direction) {
Fl::remove_timeout(scroll_timer_cb, this); Fl::remove_timeout(scroll_timer_cb, this);
@ -169,9 +171,11 @@ Fl_Text_Display::~Fl_Text_Display() {
if (mLineStarts) delete[] mLineStarts; if (mLineStarts) delete[] mLineStarts;
} }
/** /**
Attach a text buffer to display, replacing the current buffer (if any) Attach a text buffer to display, replacing the current buffer (if any)
*/ \param buf attach this text buffer
*/
void Fl_Text_Display::buffer( Fl_Text_Buffer *buf ) { void Fl_Text_Display::buffer( Fl_Text_Buffer *buf ) {
/* If the text display is already displaying a buffer, clear it off /* If the text display is already displaying a buffer, clear it off
of the display and remove our callback from it */ of the display and remove our callback from it */
@ -212,7 +216,7 @@ void Fl_Text_Display::buffer( Fl_Text_Buffer *buf ) {
Style buffers, tables and their associated memory are managed by the caller. Style buffers, tables and their associated memory are managed by the caller.
Styles are ranged from 65 ('A') to 126. Styles are ranged from 65 ('A') to 126.
*/ */
void Fl_Text_Display::highlight_data(Fl_Text_Buffer *styleBuffer, void Fl_Text_Display::highlight_data(Fl_Text_Buffer *styleBuffer,
const Style_Table_Entry *styleTable, const Style_Table_Entry *styleTable,
int nStyles, char unfinishedStyle, int nStyles, char unfinishedStyle,
@ -238,7 +242,7 @@ int Fl_Text_Display::longest_vline() const {
/** /**
Change the size of the displayed text area Change the size of the displayed text area
*/ */
void Fl_Text_Display::resize(int X, int Y, int W, int H) { void Fl_Text_Display::resize(int X, int Y, int W, int H) {
#ifdef DEBUG #ifdef DEBUG
printf("Fl_Text_Display::resize(X=%d, Y=%d, W=%d, H=%d)\n", X, Y, W, H); printf("Fl_Text_Display::resize(X=%d, Y=%d, W=%d, H=%d)\n", X, Y, W, H);
@ -403,7 +407,7 @@ void Fl_Text_Display::resize(int X, int Y, int W, int H) {
/** /**
Refresh a rectangle of the text display. left and top are in coordinates of Refresh a rectangle of the text display. left and top are in coordinates of
the text drawing window the text drawing window
*/ */
void Fl_Text_Display::draw_text( int left, int top, int width, int height ) { void Fl_Text_Display::draw_text( int left, int top, int width, int height ) {
int fontHeight, firstLine, lastLine, line; int fontHeight, firstLine, lastLine, line;
@ -468,7 +472,7 @@ void Fl_Text_Display::redisplay_range(int startpos, int endpos) {
If end points beyond the end of the buffer, refresh the whole display If end points beyond the end of the buffer, refresh the whole display
after pos, including blank lines which are not technically part of after pos, including blank lines which are not technically part of
any range of characters. any range of characters.
*/ */
void Fl_Text_Display::draw_range(int startpos, int endpos) { void Fl_Text_Display::draw_range(int startpos, int endpos) {
int i, startLine, lastLine, startIndex, endIndex; int i, startLine, lastLine, startIndex, endIndex;
@ -559,7 +563,7 @@ void Fl_Text_Display::show_cursor(int b) {
\li Fl_Text_Display::BLOCK_CURSOR - Shows an unfilled box around the current \li Fl_Text_Display::BLOCK_CURSOR - Shows an unfilled box around the current
character. character.
\li Fl_Text_Display::HEAVY_CURSOR - Shows a thick I beam. \li Fl_Text_Display::HEAVY_CURSOR - Shows a thick I beam.
*/ */
void Fl_Text_Display::cursor_style(int style) { void Fl_Text_Display::cursor_style(int style) {
mCursorStyle = style; mCursorStyle = style;
if (mCursorOn) show_cursor(); if (mCursorOn) show_cursor();
@ -568,7 +572,7 @@ void Fl_Text_Display::cursor_style(int style) {
/** /**
If <i>mode</i> is not zero, this call enables automatic word wrapping at column <i>pos</i>. If <i>mode</i> is not zero, this call enables automatic word wrapping at column <i>pos</i>.
Word-wrapping does not change the text buffer itself, only the way that the text is displayed. Word-wrapping does not change the text buffer itself, only the way that the text is displayed.
*/ */
void Fl_Text_Display::wrap_mode(int wrap, int wrapMargin) { void Fl_Text_Display::wrap_mode(int wrap, int wrapMargin) {
mWrapMargin = wrapMargin; mWrapMargin = wrapMargin;
mContinuousWrap = wrap; mContinuousWrap = wrap;
@ -604,7 +608,7 @@ void Fl_Text_Display::wrap_mode(int wrap, int wrapMargin) {
effect as inserting the text into the buffer using BufInsert and effect as inserting the text into the buffer using BufInsert and
then moving the insert position after the newly inserted text, except then moving the insert position after the newly inserted text, except
that it's optimized to do less redrawing. that it's optimized to do less redrawing.
*/ */
void Fl_Text_Display::insert(const char* text) { void Fl_Text_Display::insert(const char* text) {
int pos = mCursorPos; int pos = mCursorPos;
@ -671,7 +675,7 @@ void Fl_Text_Display::overstrike(const char* text) {
0 if the position is not displayed because it is VERTICALLY out 0 if the position is not displayed because it is VERTICALLY out
of view. If the position is horizontally out of view, returns the of view. If the position is horizontally out of view, returns the
X coordinate where the position would be if it were visible. X coordinate where the position would be if it were visible.
*/ */
int Fl_Text_Display::position_to_xy( int pos, int* X, int* Y ) const { int Fl_Text_Display::position_to_xy( int pos, int* X, int* Y ) const {
int lineStartPos, fontHeight, lineLen; int lineStartPos, fontHeight, lineLen;
@ -713,7 +717,7 @@ int Fl_Text_Display::position_to_xy( int pos, int* X, int* Y ) const {
calculation involving scanning large amounts of text in the buffer). calculation involving scanning large amounts of text in the buffer).
If continuous wrap mode is on, returns the absolute line number (as opposed If continuous wrap mode is on, returns the absolute line number (as opposed
to the wrapped line number which is used for scrolling). to the wrapped line number which is used for scrolling).
*/ */
int Fl_Text_Display::position_to_linecol( int pos, int* lineNum, int* column ) const { int Fl_Text_Display::position_to_linecol( int pos, int* lineNum, int* column ) const {
int retVal; int retVal;
@ -725,15 +729,13 @@ int Fl_Text_Display::position_to_linecol( int pos, int* lineNum, int* column ) c
pos < mFirstChar || pos > mLastChar) pos < mFirstChar || pos > mLastChar)
return 0; return 0;
*lineNum = mAbsTopLineNum + buffer()->count_lines(mFirstChar, pos); *lineNum = mAbsTopLineNum + buffer()->count_lines(mFirstChar, pos);
*column *column = buffer()->count_displayed_characters(buffer()->line_start(pos), pos);
= buffer()->count_displayed_characters(buffer()->line_start(pos), pos);
return 1; return 1;
} }
retVal = position_to_line( pos, lineNum ); retVal = position_to_line( pos, lineNum );
if ( retVal ) { if ( retVal ) {
*column = mBuffer->count_displayed_characters( *column = mBuffer->count_displayed_characters( mLineStarts[ *lineNum ], pos );
mLineStarts[ *lineNum ], pos );
*lineNum += mTopLineNum; *lineNum += mTopLineNum;
} }
return retVal; return retVal;
@ -741,12 +743,12 @@ int Fl_Text_Display::position_to_linecol( int pos, int* lineNum, int* column ) c
/** /**
Return 1 if position (X, Y) is inside of the primary Fl_Text_Selection Return 1 if position (X, Y) is inside of the primary Fl_Text_Selection
*/ */
int Fl_Text_Display::in_selection( int X, int Y ) const { int Fl_Text_Display::in_selection( int X, int Y ) const {
int pos = xy_to_position( X, Y, CHARACTER_POS ); int pos = xy_to_position( X, Y, CHARACTER_POS );
Fl_Text_Buffer *buf = mBuffer; Fl_Text_Buffer *buf = mBuffer;
return buf->primary_selection()->includes(pos); return buf->primary_selection()->includes(pos);
} }
/** /**
Correct a column number based on an unconstrained position (as returned by Correct a column number based on an unconstrained position (as returned by
@ -757,7 +759,7 @@ int Fl_Text_Display::in_selection( int X, int Y ) const {
which thinks that the unconstrained column is the number of characters which thinks that the unconstrained column is the number of characters
from the last newline. Obviously this is time consuming, because it from the last newline. Obviously this is time consuming, because it
invloves character re-counting. invloves character re-counting.
*/ */
int Fl_Text_Display::wrapped_column(int row, int column) const { int Fl_Text_Display::wrapped_column(int row, int column) const {
int lineStart, dispLineStart; int lineStart, dispLineStart;
@ -777,7 +779,7 @@ int Fl_Text_Display::wrapped_column(int row, int column) const {
top line of the display. Because rectangular selections are based on top line of the display. Because rectangular selections are based on
newlines, rather than display wrapping, and anywhere a rectangular selection newlines, rather than display wrapping, and anywhere a rectangular selection
needs a row, it needs it in terms of un-wrapped lines. needs a row, it needs it in terms of un-wrapped lines.
*/ */
int Fl_Text_Display::wrapped_row(int row) const{ int Fl_Text_Display::wrapped_row(int row) const{
if (!mContinuousWrap || row < 0 || row > mNVisibleLines) if (!mContinuousWrap || row < 0 || row > mNVisibleLines)
return row; return row;
@ -786,19 +788,19 @@ int Fl_Text_Display::wrapped_row(int row) const{
/** /**
Scroll the display to bring insertion cursor into view. Scroll the display to bring insertion cursor into view.
** **
Note: it would be nice to be able to do this without counting lines twice Note: it would be nice to be able to do this without counting lines twice
(scroll_() counts them too) and/or to count from the most efficient (scroll_() counts them too) and/or to count from the most efficient
starting point, but the efficiency of this routine is not as important to starting point, but the efficiency of this routine is not as important to
the overall performance of the text display. the overall performance of the text display.
*/ */
void Fl_Text_Display::display_insert() { void Fl_Text_Display::display_insert() {
int hOffset, topLine, X, Y; int hOffset, topLine, X, Y;
hOffset = mHorizOffset; hOffset = mHorizOffset;
topLine = mTopLineNum; topLine = mTopLineNum;
// FIXME: I don't understand this well enough to know if it is correct // FIXME: I don't understand this well enough to know if it is correct
// it is different than nedit 5.3 // it is different than nedit 5.3
if (insert_position() < mFirstChar) { if (insert_position() < mFirstChar) {
topLine -= count_lines(insert_position(), mFirstChar, false); topLine -= count_lines(insert_position(), mFirstChar, false);
} else if (mLineStarts[mNVisibleLines-2] != -1) { } else if (mLineStarts[mNVisibleLines-2] != -1) {
@ -816,9 +818,9 @@ void Fl_Text_Display::display_insert() {
if (!position_to_xy( mCursorPos, &X, &Y )) { if (!position_to_xy( mCursorPos, &X, &Y )) {
scroll_(topLine, hOffset); scroll_(topLine, hOffset);
if (!position_to_xy( mCursorPos, &X, &Y )) { if (!position_to_xy( mCursorPos, &X, &Y )) {
#ifdef DEBUG #ifdef DEBUG
printf ("*** display_insert/position_to_xy # GIVE UP !\n"); fflush(stdout); printf ("*** display_insert/position_to_xy # GIVE UP !\n"); fflush(stdout);
#endif // DEBUG #endif // DEBUG
return; /* Give up, it's not worth it (but why does it fail?) */ return; /* Give up, it's not worth it (but why does it fail?) */
} }
} }
@ -840,7 +842,7 @@ void Fl_Text_Display::show_insert_position() {
/* /*
Cursor movement functions Cursor movement functions
*/ */
/** /**
Moves the current insert position right one character. Moves the current insert position right one character.
@ -956,7 +958,7 @@ int Fl_Text_Display::move_down() {
turned on. If the caller knows that startPos is at a line start, it turned on. If the caller knows that startPos is at a line start, it
can pass "startPosIsLineStart" as True to make the call more efficient can pass "startPosIsLineStart" as True to make the call more efficient
by avoiding the additional step of scanning back to the last newline. by avoiding the additional step of scanning back to the last newline.
*/ */
int Fl_Text_Display::count_lines(int startPos, int endPos, int Fl_Text_Display::count_lines(int startPos, int endPos,
bool startPosIsLineStart) const { bool startPosIsLineStart) const {
int retLines, retPos, retLineStart, retLineEnd; int retLines, retPos, retLineStart, retLineEnd;
@ -987,7 +989,7 @@ int Fl_Text_Display::count_lines(int startPos, int endPos,
wrapping is turned on. If the caller knows that startPos is at a line start, wrapping is turned on. If the caller knows that startPos is at a line start,
it can pass "startPosIsLineStart" as True to make the call more efficient it can pass "startPosIsLineStart" as True to make the call more efficient
by avoiding the additional step of scanning back to the last newline. by avoiding the additional step of scanning back to the last newline.
*/ */
int Fl_Text_Display::skip_lines(int startPos, int nLines, int Fl_Text_Display::skip_lines(int startPos, int nLines,
bool startPosIsLineStart) { bool startPosIsLineStart) {
int retLines, retPos, retLineStart, retLineEnd; int retLines, retPos, retLineStart, retLineEnd;
@ -1012,7 +1014,7 @@ int Fl_Text_Display::skip_lines(int startPos, int nLines,
is turned on. If the caller knows that startPos is at a line start, it is turned on. If the caller knows that startPos is at a line start, it
can pass "startPosIsLineStart" as True to make the call more efficient can pass "startPosIsLineStart" as True to make the call more efficient
by avoiding the additional step of scanning back to the last newline. by avoiding the additional step of scanning back to the last newline.
** **
Note that the definition of the end of a line is less clear when continuous Note that the definition of the end of a line is less clear when continuous
wrap is on. With continuous wrap off, it's just a pointer to the newline wrap is on. With continuous wrap off, it's just a pointer to the newline
that ends the line. When it's on, it's the character beyond the last that ends the line. When it's on, it's the character beyond the last
@ -1022,7 +1024,7 @@ int Fl_Text_Display::skip_lines(int startPos, int nLines,
line had no whitespace. In this case, this routine returns a pointer to line had no whitespace. In this case, this routine returns a pointer to
the start of the next line. This is also consistent with the model used by the start of the next line. This is also consistent with the model used by
visLineLength. visLineLength.
*/ */
int Fl_Text_Display::line_end(int pos, bool startPosIsLineStart) const { int Fl_Text_Display::line_end(int pos, bool startPosIsLineStart) const {
int retLines, retPos, retLineStart, retLineEnd; int retLines, retPos, retLineStart, retLineEnd;
@ -1041,7 +1043,7 @@ int Fl_Text_Display::line_end(int pos, bool startPosIsLineStart) const {
/** /**
Same as BufStartOfLine, but returns the character after last wrap point Same as BufStartOfLine, but returns the character after last wrap point
rather than the last newline. rather than the last newline.
*/ */
int Fl_Text_Display::line_start(int pos) const { int Fl_Text_Display::line_start(int pos) const {
int retLines, retPos, retLineStart, retLineEnd; int retLines, retPos, retLineStart, retLineEnd;
@ -1057,7 +1059,7 @@ int Fl_Text_Display::line_start(int pos) const {
/** /**
Same as BufCountBackwardNLines, but takes in to account line breaks when Same as BufCountBackwardNLines, but takes in to account line breaks when
wrapping is turned on. wrapping is turned on.
*/ */
int Fl_Text_Display::rewind_lines(int startPos, int nLines) { int Fl_Text_Display::rewind_lines(int startPos, int nLines) {
Fl_Text_Buffer *buf = buffer(); Fl_Text_Buffer *buf = buffer();
int pos, lineStart, retLines, retPos, retLineStart, retLineEnd; int pos, lineStart, retLines, retPos, retLineStart, retLineEnd;
@ -1123,7 +1125,7 @@ void Fl_Text_Display::previous_word() {
/** /**
Callback attached to the text buffer to receive delete information before Callback attached to the text buffer to receive delete information before
the modifications are actually made. the modifications are actually made.
*/ */
void Fl_Text_Display::buffer_predelete_cb(int pos, int nDeleted, void *cbArg) { void Fl_Text_Display::buffer_predelete_cb(int pos, int nDeleted, void *cbArg) {
Fl_Text_Display *textD = (Fl_Text_Display *)cbArg; Fl_Text_Display *textD = (Fl_Text_Display *)cbArg;
if (textD->mContinuousWrap) if (textD->mContinuousWrap)
@ -1142,7 +1144,7 @@ void Fl_Text_Display::buffer_predelete_cb(int pos, int nDeleted, void *cbArg) {
/** /**
Callback attached to the text buffer to receive modification information Callback attached to the text buffer to receive modification information
*/ */
void Fl_Text_Display::buffer_modified_cb( int pos, int nInserted, int nDeleted, void Fl_Text_Display::buffer_modified_cb( int pos, int nInserted, int nDeleted,
int nRestyled, const char *deletedText, void *cbArg ) { int nRestyled, const char *deletedText, void *cbArg ) {
int linesInserted, linesDeleted, startDispPos, endDispPos; int linesInserted, linesDeleted, startDispPos, endDispPos;
@ -1269,7 +1271,7 @@ void Fl_Text_Display::buffer_modified_cb( int pos, int nInserted, int nDeleted,
want this line count maintained (for use via TextDPosToLineAndCol). want this line count maintained (for use via TextDPosToLineAndCol).
More specifically, this allows the line number reported in the statistics More specifically, this allows the line number reported in the statistics
line to be calibrated in absolute lines, rather than post-wrapped lines. line to be calibrated in absolute lines, rather than post-wrapped lines.
*/ */
void Fl_Text_Display::maintain_absolute_top_line_number(int state) { void Fl_Text_Display::maintain_absolute_top_line_number(int state) {
mNeedAbsTopLineNum = state; mNeedAbsTopLineNum = state;
reset_absolute_top_line_number(); reset_absolute_top_line_number();
@ -1278,7 +1280,7 @@ void Fl_Text_Display::maintain_absolute_top_line_number(int state) {
/** /**
Returns the absolute (non-wrapped) line number of the first line displayed. Returns the absolute (non-wrapped) line number of the first line displayed.
Returns 0 if the absolute top line number is not being maintained. Returns 0 if the absolute top line number is not being maintained.
*/ */
int Fl_Text_Display::get_absolute_top_line_number() const { int Fl_Text_Display::get_absolute_top_line_number() const {
if (!mContinuousWrap) if (!mContinuousWrap)
return mTopLineNum; return mTopLineNum;
@ -1289,7 +1291,7 @@ int Fl_Text_Display::get_absolute_top_line_number() const {
/** /**
Re-calculate absolute top line number for a change in scroll position. Re-calculate absolute top line number for a change in scroll position.
*/ */
void Fl_Text_Display::absolute_top_line_number(int oldFirstChar) { void Fl_Text_Display::absolute_top_line_number(int oldFirstChar) {
if (maintaining_absolute_top_line_number()) { if (maintaining_absolute_top_line_number()) {
if (mFirstChar < oldFirstChar) if (mFirstChar < oldFirstChar)
@ -1302,7 +1304,7 @@ void Fl_Text_Display::absolute_top_line_number(int oldFirstChar) {
/** /**
Return true if a separate absolute top line number is being maintained Return true if a separate absolute top line number is being maintained
(for displaying line numbers or showing in the statistics line). (for displaying line numbers or showing in the statistics line).
*/ */
int Fl_Text_Display::maintaining_absolute_top_line_number() const { int Fl_Text_Display::maintaining_absolute_top_line_number() const {
return mContinuousWrap && return mContinuousWrap &&
(mLineNumWidth != 0 || mNeedAbsTopLineNum); (mLineNumWidth != 0 || mNeedAbsTopLineNum);
@ -1312,7 +1314,7 @@ int Fl_Text_Display::maintaining_absolute_top_line_number() const {
Count lines from the beginning of the buffer to reestablish the Count lines from the beginning of the buffer to reestablish the
absolute (non-wrapped) top line number. If mode is not continuous wrap, absolute (non-wrapped) top line number. If mode is not continuous wrap,
or the number is not being maintained, does nothing. or the number is not being maintained, does nothing.
*/ */
void Fl_Text_Display::reset_absolute_top_line_number() { void Fl_Text_Display::reset_absolute_top_line_number() {
mAbsTopLineNum = 1; mAbsTopLineNum = 1;
absolute_top_line_number(0); absolute_top_line_number(0);
@ -1321,7 +1323,7 @@ void Fl_Text_Display::reset_absolute_top_line_number() {
/** /**
Find the line number of position "pos" relative to the first line of Find the line number of position "pos" relative to the first line of
displayed text. Returns 0 if the line is not displayed. displayed text. Returns 0 if the line is not displayed.
*/ */
int Fl_Text_Display::position_to_line( int pos, int *lineNum ) const { int Fl_Text_Display::position_to_line( int pos, int *lineNum ) const {
int i; int i;
@ -1431,6 +1433,10 @@ int Fl_Text_Display::handle_vline(
startX += w; startX += w;
startIndex = i; startIndex = i;
} }
if (len==-1) {
// FIXME: what happened? Is there an illegal charater, or an illegal index?
len = 1;
}
i += len; i += len;
} }
int w = string_width( lineStr+startIndex, i-startIndex, style ); int w = string_width( lineStr+startIndex, i-startIndex, style );
@ -1477,15 +1483,15 @@ int Fl_Text_Display::find_x(const char *s, int len, int style, int x) const {
"leftClip" and "rightClip" window coordinates and "leftCharIndex" and "leftClip" and "rightClip" window coordinates and "leftCharIndex" and
"rightCharIndex" character positions (not including the character at "rightCharIndex" character positions (not including the character at
position "rightCharIndex"). position "rightCharIndex").
*/ */
void Fl_Text_Display::draw_vline(int visLineNum, int leftClip, int rightClip, void Fl_Text_Display::draw_vline(int visLineNum, int leftClip, int rightClip,
int leftCharIndex, int rightCharIndex) { int leftCharIndex, int rightCharIndex) {
int Y, lineStartPos, lineLen, fontHeight; int Y, lineStartPos, lineLen, fontHeight;
int stdCharWidth; int stdCharWidth;
// printf("draw_vline(visLineNum=%d, leftClip=%d, rightClip=%d, leftCharIndex=%d, rightCharIndex=%d)\n", // printf("draw_vline(visLineNum=%d, leftClip=%d, rightClip=%d, leftCharIndex=%d, rightCharIndex=%d)\n",
// visLineNum, leftClip, rightClip, leftCharIndex, rightCharIndex); // visLineNum, leftClip, rightClip, leftCharIndex, rightCharIndex);
// printf("nNVisibleLines=%d\n", mNVisibleLines); // printf("nNVisibleLines=%d\n", mNVisibleLines);
/* If line is not displayed, skip it */ /* If line is not displayed, skip it */
if ( visLineNum < 0 || visLineNum >= mNVisibleLines ) if ( visLineNum < 0 || visLineNum >= mNVisibleLines )
@ -1497,7 +1503,7 @@ void Fl_Text_Display::draw_vline(int visLineNum, int leftClip, int rightClip,
/* Get the text, length, and buffer position of the line to display */ /* Get the text, length, and buffer position of the line to display */
lineStartPos = mLineStarts[ visLineNum ]; lineStartPos = mLineStarts[ visLineNum ];
// printf("lineStartPos=%d\n", lineStartPos); // printf("lineStartPos=%d\n", lineStartPos);
if ( lineStartPos == -1 ) { if ( lineStartPos == -1 ) {
lineLen = 0; lineLen = 0;
} else { } else {
@ -1523,7 +1529,7 @@ void Fl_Text_Display::draw_vline(int visLineNum, int leftClip, int rightClip,
lineStartPos, lineLen, leftCharIndex, rightCharIndex, lineStartPos, lineLen, leftCharIndex, rightCharIndex,
Y, Y+fontHeight, leftClip, rightClip); Y, Y+fontHeight, leftClip, rightClip);
return; return;
} }
/** /**
Draw a string or blank area according to parameter "style", using the Draw a string or blank area according to parameter "style", using the
@ -1532,7 +1538,7 @@ void Fl_Text_Display::draw_vline(int visLineNum, int leftClip, int rightClip,
characters, and draw "nChars", if style is FILL, erase characters, and draw "nChars", if style is FILL, erase
rectangle where text would have drawn from X to toX and from Y to rectangle where text would have drawn from X to toX and from Y to
the maximum Y extent of the current font(s). the maximum Y extent of the current font(s).
*/ */
void Fl_Text_Display::draw_string(int style, void Fl_Text_Display::draw_string(int style,
int X, int Y, int toX, int X, int Y, int toX,
const char *string, int nChars) const { const char *string, int nChars) const {
@ -1617,7 +1623,7 @@ void Fl_Text_Display::draw_string(int style,
/** /**
Clear a rectangle with the appropriate background color for "style" Clear a rectangle with the appropriate background color for "style"
*/ */
void Fl_Text_Display::clear_rect(int style, void Fl_Text_Display::clear_rect(int style,
int X, int Y, int X, int Y,
int width, int height) const { int width, int height) const {
@ -1646,7 +1652,7 @@ void Fl_Text_Display::clear_rect(int style,
/** /**
Draw a cursor with top center at X, y. Draw a cursor with top center at X, y.
*/ */
void Fl_Text_Display::draw_cursor( int X, int Y ) { void Fl_Text_Display::draw_cursor( int X, int Y ) {
typedef struct { typedef struct {
int x1, y1, x2, y2; int x1, y1, x2, y2;
@ -1718,16 +1724,16 @@ void Fl_Text_Display::draw_cursor( int X, int Y ) {
the number of characters past the beginning of the line, and "dispIndex", the number of characters past the beginning of the line, and "dispIndex",
the number of displayed characters past the beginning of the line. Passing the number of displayed characters past the beginning of the line. Passing
lineStartPos of -1 returns the drawing style for "no text". lineStartPos of -1 returns the drawing style for "no text".
** **
Why not just: position_style(pos)? Because style applies to blank areas Why not just: position_style(pos)? Because style applies to blank areas
of the window beyond the text boundaries, and because this routine must also of the window beyond the text boundaries, and because this routine must also
decide whether a position is inside of a rectangular Fl_Text_Selection, and do decide whether a position is inside of a rectangular Fl_Text_Selection, and do
so efficiently, without re-counting character positions from the start of the so efficiently, without re-counting character positions from the start of the
line. line.
** **
Note that style is a somewhat incorrect name, drawing method would Note that style is a somewhat incorrect name, drawing method would
be more appropriate. be more appropriate.
*/ */
int Fl_Text_Display::position_style( int lineStartPos, int lineLen, int lineIndex) const int Fl_Text_Display::position_style( int lineStartPos, int lineLen, int lineIndex) const
{ {
Fl_Text_Buffer * buf = mBuffer; Fl_Text_Buffer * buf = mBuffer;
@ -1760,7 +1766,7 @@ int Fl_Text_Display::position_style( int lineStartPos, int lineLen, int lineInde
/** /**
Find the width of a string in the font of a particular style Find the width of a string in the font of a particular style
*/ */
int Fl_Text_Display::string_width( const char *string, int length, int style ) const { int Fl_Text_Display::string_width( const char *string, int length, int style ) const {
Fl_Font font; Fl_Font font;
int fsize; int fsize;
@ -1787,7 +1793,7 @@ int Fl_Text_Display::string_width( const char *string, int length, int style ) c
position: CURSOR_POS means translate the coordinates to the nearest cursor position: CURSOR_POS means translate the coordinates to the nearest cursor
position, and CHARACTER_POS means return the position of the character position, and CHARACTER_POS means return the position of the character
closest to (X, Y). closest to (X, Y).
*/ */
int Fl_Text_Display::xy_to_position( int X, int Y, int posType ) const { int Fl_Text_Display::xy_to_position( int X, int Y, int posType ) const {
int lineStart, lineLen, fontHeight; int lineStart, lineLen, fontHeight;
int visLineNum; int visLineNum;
@ -1814,7 +1820,7 @@ int Fl_Text_Display::xy_to_position( int X, int Y, int posType ) const {
lineStart, lineLen, 0, 0, lineStart, lineLen, 0, 0,
0, 0, 0, 0,
text_area.x, X); text_area.x, X);
} }
/** /**
Translate window coordinates to the nearest row and column number for Translate window coordinates to the nearest row and column number for
@ -1823,7 +1829,7 @@ int Fl_Text_Display::xy_to_position( int X, int Y, int posType ) const {
specifies how to interpret the position: CURSOR_POS means translate the specifies how to interpret the position: CURSOR_POS means translate the
coordinates to the nearest position between characters, and CHARACTER_POS coordinates to the nearest position between characters, and CHARACTER_POS
means translate the position to the nearest character cell. means translate the position to the nearest character cell.
*/ */
void Fl_Text_Display::xy_to_rowcol( int X, int Y, int *row, void Fl_Text_Display::xy_to_rowcol( int X, int Y, int *row,
int *column, int posType ) const { int *column, int posType ) const {
int fontHeight = mMaxsize; int fontHeight = mMaxsize;
@ -1844,7 +1850,7 @@ void Fl_Text_Display::xy_to_rowcol( int X, int Y, int *row,
lines will still be visible, salvage the line starts values, otherwise, lines will still be visible, salvage the line starts values, otherwise,
count lines from the nearest known line start (start or end of buffer, or count lines from the nearest known line start (start or end of buffer, or
the closest value in the mLineStarts array) the closest value in the mLineStarts array)
*/ */
void Fl_Text_Display::offset_line_starts( int newTopLineNum ) { void Fl_Text_Display::offset_line_starts( int newTopLineNum ) {
int oldTopLineNum = mTopLineNum; int oldTopLineNum = mTopLineNum;
int oldFirstChar = mFirstChar; int oldFirstChar = mFirstChar;
@ -1901,7 +1907,7 @@ void Fl_Text_Display::offset_line_starts( int newTopLineNum ) {
display "textD" after a modification to the text buffer, given by the display "textD" after a modification to the text buffer, given by the
position where the change began "pos", and the nmubers of characters position where the change began "pos", and the nmubers of characters
and lines inserted and deleted. and lines inserted and deleted.
*/ */
void Fl_Text_Display::update_line_starts( int pos, int charsInserted, void Fl_Text_Display::update_line_starts( int pos, int charsInserted,
int charsDeleted, int linesInserted, int linesDeleted, int *scrolled ) { int charsDeleted, int linesInserted, int linesDeleted, int *scrolled ) {
int * lineStarts = mLineStarts; int * lineStarts = mLineStarts;
@ -1999,7 +2005,7 @@ void Fl_Text_Display::update_line_starts( int pos, int charsInserted,
"startLine" (or mFirstChar if startLine is 0) is good, and re-counts "startLine" (or mFirstChar if startLine is 0) is good, and re-counts
newlines to fill in the requested entries. Out of range values for newlines to fill in the requested entries. Out of range values for
"startLine" and "endLine" are acceptable. "startLine" and "endLine" are acceptable.
*/ */
void Fl_Text_Display::calc_line_starts( int startLine, int endLine ) { void Fl_Text_Display::calc_line_starts( int startLine, int endLine ) {
int startPos, bufLen = mBuffer->length(); int startPos, bufLen = mBuffer->length();
int line, lineEnd, nextLineStart, nVis = mNVisibleLines; int line, lineEnd, nextLineStart, nVis = mNVisibleLines;
@ -2056,7 +2062,7 @@ void Fl_Text_Display::calc_line_starts( int startLine, int endLine ) {
/** /**
Given a Fl_Text_Display with a complete, up-to-date lineStarts array, update Given a Fl_Text_Display with a complete, up-to-date lineStarts array, update
the lastChar entry to point to the last buffer position displayed. the lastChar entry to point to the last buffer position displayed.
*/ */
void Fl_Text_Display::calc_last_char() { void Fl_Text_Display::calc_last_char() {
int i; int i;
for (i = mNVisibleLines - 1; i >= 0 && mLineStarts[i] == -1; i--) ; for (i = mNVisibleLines - 1; i >= 0 && mLineStarts[i] == -1; i--) ;
@ -2099,7 +2105,7 @@ void Fl_Text_Display::scroll_(int topLineNum, int horizOffset) {
/** /**
Update the minimum, maximum, slider size, page increment, and value Update the minimum, maximum, slider size, page increment, and value
for vertical scroll bar. for vertical scroll bar.
*/ */
void Fl_Text_Display::update_v_scrollbar() { void Fl_Text_Display::update_v_scrollbar() {
/* The Vert. scroll bar value and slider size directly represent the top /* The Vert. scroll bar value and slider size directly represent the top
line number, and the number of visible lines respectively. The scroll line number, and the number of visible lines respectively. The scroll
@ -2118,7 +2124,7 @@ void Fl_Text_Display::update_v_scrollbar() {
/** /**
Update the minimum, maximum, slider size, page increment, and value Update the minimum, maximum, slider size, page increment, and value
for the horizontal scroll bar. for the horizontal scroll bar.
*/ */
void Fl_Text_Display::update_h_scrollbar() { void Fl_Text_Display::update_h_scrollbar() {
int sliderMax = max(longest_vline(), text_area.w + mHorizOffset); int sliderMax = max(longest_vline(), text_area.w + mHorizOffset);
mHScrollBar->value( mHorizOffset, text_area.w, 0, sliderMax ); mHScrollBar->value( mHorizOffset, text_area.w, 0, sliderMax );
@ -2126,7 +2132,7 @@ void Fl_Text_Display::update_h_scrollbar() {
/** /**
Callbacks for drag or valueChanged on scroll bars Callbacks for drag or valueChanged on scroll bars
*/ */
void Fl_Text_Display::v_scrollbar_cb(Fl_Scrollbar* b, Fl_Text_Display* textD) { void Fl_Text_Display::v_scrollbar_cb(Fl_Scrollbar* b, Fl_Text_Display* textD) {
if (b->value() == textD->mTopLineNum) return; if (b->value() == textD->mTopLineNum) return;
textD->scroll(b->value(), textD->mHorizOffset); textD->scroll(b->value(), textD->mHorizOffset);
@ -2142,7 +2148,7 @@ void Fl_Text_Display::h_scrollbar_cb(Fl_Scrollbar* b, Fl_Text_Display* textD) {
the character cell areas. Setting clearAll to True will clear out any the character cell areas. Setting clearAll to True will clear out any
stray marks outside of the character cell area, which might have been stray marks outside of the character cell area, which might have been
left from before a resize or font change. left from before a resize or font change.
*/ */
void Fl_Text_Display::draw_line_numbers(bool /*clearAll*/) { void Fl_Text_Display::draw_line_numbers(bool /*clearAll*/) {
#if 0 #if 0
// FIXME: don't want this yet, so will leave for another time // FIXME: don't want this yet, so will leave for another time
@ -2207,7 +2213,7 @@ static int min( int i1, int i2 ) {
/** /**
Count the number of newlines in a null-terminated text string; Count the number of newlines in a null-terminated text string;
*/ */
static int countlines( const char *string ) { static int countlines( const char *string ) {
const char * c; const char * c;
int lineCount = 0; int lineCount = 0;
@ -2221,27 +2227,26 @@ static int countlines( const char *string ) {
/** /**
Return the width in pixels of the displayed line pointed to by "visLineNum" Return the width in pixels of the displayed line pointed to by "visLineNum"
*/ */
int Fl_Text_Display::measure_vline( int visLineNum ) const { int Fl_Text_Display::measure_vline( int visLineNum ) const {
// FIXME: the horizontal scroll bar is still messed up. Clicking the right container is not possible. // FIXME: the horizontal scroll bar is still messed up. Clicking the right container is not possible.
int lineLen = vline_length( visLineNum ); int lineLen = vline_length( visLineNum );
int lineStartPos = mLineStarts[ visLineNum ]; int lineStartPos = mLineStarts[ visLineNum ];
if (lineStartPos < 0 || lineLen == 0) return 0; if (lineStartPos < 0 || lineLen == 0) return 0;
return handle_vline(GET_WIDTH, lineStartPos, lineLen, 0, 0, 0, 0, 0, 0); return handle_vline(GET_WIDTH, lineStartPos, lineLen, 0, 0, 0, 0, 0, 0);
} }
/** /**
Return true if there are lines visible with no corresponding buffer text Return true if there are lines visible with no corresponding buffer text
*/ */
int Fl_Text_Display::empty_vlines() const { int Fl_Text_Display::empty_vlines() const {
return mNVisibleLines > 0 && return (mNVisibleLines > 0) && (mLineStarts[ mNVisibleLines - 1 ] == -1);
mLineStarts[ mNVisibleLines - 1 ] == -1;
} }
/** /**
Return the length of a line (number of displayable characters) by examining Return the length of a line (number of displayable characters) by examining
entries in the line starts array rather than by scanning for newlines entries in the line starts array rather than by scanning for newlines
*/ */
int Fl_Text_Display::vline_length( int visLineNum ) const { int Fl_Text_Display::vline_length( int visLineNum ) const {
int nextLineStart, lineStartPos; int nextLineStart, lineStartPos;
@ -2270,7 +2275,7 @@ int Fl_Text_Display::vline_length( int visLineNum ) const {
what has to be counted and re-displayed, so the results can be useful what has to be counted and re-displayed, so the results can be useful
both for delimiting where the line starts need to be recalculated, and both for delimiting where the line starts need to be recalculated, and
for deciding what part of the text to redisplay. for deciding what part of the text to redisplay.
*/ */
void Fl_Text_Display::find_wrap_range(const char *deletedText, int pos, void Fl_Text_Display::find_wrap_range(const char *deletedText, int pos,
int nInserted, int nDeleted, int *modRangeStart, int *modRangeEnd, int nInserted, int nDeleted, int *modRangeStart, int *modRangeEnd,
int *linesInserted, int *linesDeleted) { int *linesInserted, int *linesDeleted) {
@ -2424,7 +2429,7 @@ void Fl_Text_Display::find_wrap_range(const char *deletedText, int pos,
is no longer available _after_ the modification. In other cases, we is no longer available _after_ the modification. In other cases, we
can still perform the calculation afterwards (possibly even more can still perform the calculation afterwards (possibly even more
efficiently). efficiently).
*/ */
void Fl_Text_Display::measure_deleted_lines(int pos, int nDeleted) { void Fl_Text_Display::measure_deleted_lines(int pos, int nDeleted) {
int retPos, retLines, retLineStart, retLineEnd; int retPos, retLines, retLineStart, retLineEnd;
Fl_Text_Buffer *buf = buffer(); Fl_Text_Buffer *buf = buffer();
@ -2497,16 +2502,16 @@ void Fl_Text_Display::measure_deleted_lines(int pos, int nDeleted) {
widget. In that case it must be a (partial) copy of the actual text buffer widget. In that case it must be a (partial) copy of the actual text buffer
and the styleBufOffset argument must indicate the starting position of the and the styleBufOffset argument must indicate the starting position of the
copy, to take into account the correct style information. copy, to take into account the correct style information.
** **
Returned values: Returned values:
** **
retPos: Position where counting ended. When counting lines, the retPos: Position where counting ended. When counting lines, the
position returned is the start of the line "maxLines" position returned is the start of the line "maxLines"
lines beyond "startPos". lines beyond "startPos".
retLines: Number of line breaks counted retLines: Number of line breaks counted
retLineStart: Start of the line where counting ended retLineStart: Start of the line where counting ended
retLineEnd: End position of the last line traversed retLineEnd: End position of the last line traversed
*/ */
void Fl_Text_Display::wrapped_line_counter(Fl_Text_Buffer *buf, int startPos, void Fl_Text_Display::wrapped_line_counter(Fl_Text_Buffer *buf, int startPos,
int maxPos, int maxLines, bool startPosIsLineStart, int styleBufOffset, int maxPos, int maxLines, bool startPosIsLineStart, int styleBufOffset,
int *retPos, int *retLines, int *retLineStart, int *retLineEnd, int *retPos, int *retLines, int *retLineStart, int *retLineEnd,
@ -2643,7 +2648,7 @@ void Fl_Text_Display::wrapped_line_counter(Fl_Text_Buffer *buf, int startPos,
Measure the width in pixels of the first character of string "s" at a Measure the width in pixels of the first character of string "s" at a
particular column "colNum" and buffer position "pos". This is for measuring particular column "colNum" and buffer position "pos". This is for measuring
characters in proportional or mixed-width highlighting fonts. characters in proportional or mixed-width highlighting fonts.
** **
A note about proportional and mixed-width fonts: the mixed width and A note about proportional and mixed-width fonts: the mixed width and
proportional font code in nedit does not get much use in general editing, proportional font code in nedit does not get much use in general editing,
because nedit doesn't allow per-language-mode fonts, and editing programs because nedit doesn't allow per-language-mode fonts, and editing programs
@ -2652,7 +2657,7 @@ void Fl_Text_Display::wrapped_line_counter(Fl_Text_Buffer *buf, int startPos,
width syntax highlighting cases where things don't redraw properly for width syntax highlighting cases where things don't redraw properly for
insertion/deletion, though static display and wrapping and resizing insertion/deletion, though static display and wrapping and resizing
should now be solid because they are now used for online help display. should now be solid because they are now used for online help display.
*/ */
int Fl_Text_Display::measure_proportional_character(const char *s, int colNum, int pos) const { int Fl_Text_Display::measure_proportional_character(const char *s, int colNum, int pos) const {
int charLen = fl_utf8len(*s), style = 0; int charLen = fl_utf8len(*s), style = 0;
if (mStyleBuffer) { if (mStyleBuffer) {
@ -2660,7 +2665,7 @@ int Fl_Text_Display::measure_proportional_character(const char *s, int colNum, i
style = *b; style = *b;
} }
return string_width(s, charLen, style); return string_width(s, charLen, style);
} }
/** /**
Finds both the end of the current line and the start of the next line. Why? Finds both the end of the current line and the start of the next line. Why?
@ -2671,7 +2676,7 @@ int Fl_Text_Display::measure_proportional_character(const char *s, int colNum, i
whether the trailing space or tab is being used as a line break or just a whether the trailing space or tab is being used as a line break or just a
normal character, and to find that out would otherwise require counting all normal character, and to find that out would otherwise require counting all
the way back to the beginning of the line. the way back to the beginning of the line.
*/ */
void Fl_Text_Display::find_line_end(int startPos, bool startPosIsLineStart, void Fl_Text_Display::find_line_end(int startPos, bool startPosIsLineStart,
int *lineEnd, int *nextLineStart) const { int *lineEnd, int *nextLineStart) const {
int retLines, retLineStart; int retLines, retLineStart;
@ -2698,14 +2703,14 @@ void Fl_Text_Display::find_line_end(int startPos, bool startPosIsLineStart,
line terminating character, and this distinction causes endless trouble line terminating character, and this distinction causes endless trouble
with all of the text display code which was originally written without with all of the text display code which was originally written without
continuous wrap mode and always expects to wrap at a newline character. continuous wrap mode and always expects to wrap at a newline character.
** **
Given the position of the end of the line, as returned by TextDEndOfLine Given the position of the end of the line, as returned by TextDEndOfLine
or BufEndOfLine, this returns true if there is a line terminating or BufEndOfLine, this returns true if there is a line terminating
character, and false if there's not. On the last character in the character, and false if there's not. On the last character in the
buffer, this function can't tell for certain whether a trailing space was buffer, this function can't tell for certain whether a trailing space was
used as a wrap point, and just guesses that it wasn't. So if an exact used as a wrap point, and just guesses that it wasn't. So if an exact
accounting is necessary, don't use this function. accounting is necessary, don't use this function.
*/ */
int Fl_Text_Display::wrap_uses_character(int lineEndPos) const { int Fl_Text_Display::wrap_uses_character(int lineEndPos) const {
char c; char c;
@ -2722,7 +2727,7 @@ int Fl_Text_Display::wrap_uses_character(int lineEndPos) const {
Extend the range of a redraw request (from *start to *end) with additional Extend the range of a redraw request (from *start to *end) with additional
redraw requests resulting from changes to the attached style buffer (which redraw requests resulting from changes to the attached style buffer (which
contains auxiliary information for coloring or styling text). contains auxiliary information for coloring or styling text).
*/ */
void Fl_Text_Display::extend_range_for_styles( int *startpos, int *endpos ) { void Fl_Text_Display::extend_range_for_styles( int *startpos, int *endpos ) {
Fl_Text_Selection * sel = mStyleBuffer->primary_selection(); Fl_Text_Selection * sel = mStyleBuffer->primary_selection();
int extended = 0; int extended = 0;
@ -2764,7 +2769,7 @@ void Fl_Text_Display::draw(void) {
// draw the non-text, non-scrollbar areas. // draw the non-text, non-scrollbar areas.
if (damage() & FL_DAMAGE_ALL) { if (damage() & FL_DAMAGE_ALL) {
// printf("drawing all (box = %d)\n", box()); // printf("drawing all (box = %d)\n", box());
// draw the box() // draw the box()
int W = w(), H = h(); int W = w(), H = h();
draw_box(box(), x(), y(), W, H, color()); draw_box(box(), x(), y(), W, H, color());
@ -2801,7 +2806,7 @@ void Fl_Text_Display::draw(void) {
// blank the previous cursor protrusions // blank the previous cursor protrusions
} }
else if (damage() & (FL_DAMAGE_SCROLL | FL_DAMAGE_EXPOSE)) { else if (damage() & (FL_DAMAGE_SCROLL | FL_DAMAGE_EXPOSE)) {
// printf("blanking previous cursor extrusions at Y: %d\n", mCursorOldY); // printf("blanking previous cursor extrusions at Y: %d\n", mCursorOldY);
// CET - FIXME - save old cursor position instead and just draw side needed? // CET - FIXME - save old cursor position instead and just draw side needed?
fl_push_clip(text_area.x-LEFT_MARGIN, fl_push_clip(text_area.x-LEFT_MARGIN,
text_area.y, text_area.y,
@ -2862,7 +2867,7 @@ void Fl_Text_Display::draw(void) {
int X, Y; int X, Y;
if (position_to_xy(mCursorPos, &X, &Y)) draw_cursor(X, Y); if (position_to_xy(mCursorPos, &X, &Y)) draw_cursor(X, Y);
// else puts("position_to_xy() failed - unable to draw cursor!"); // else puts("position_to_xy() failed - unable to draw cursor!");
//printf("drew cursor at pos: %d (%d,%d)\n", mCursorPos, X, Y); //printf("drew cursor at pos: %d (%d,%d)\n", mCursorPos, X, Y);
mCursorOldY = Y; mCursorOldY = Y;
fl_pop_clip(); fl_pop_clip();

2
test/editor.cxx

@ -785,6 +785,7 @@ Fl_Window* new_view() {
Fl_Menu_Bar* m = new Fl_Menu_Bar(0, 0, 660, 30); Fl_Menu_Bar* m = new Fl_Menu_Bar(0, 0, 660, 30);
m->copy(menuitems, w); m->copy(menuitems, w);
w->editor = new Fl_Text_Editor(0, 30, 660, 370); w->editor = new Fl_Text_Editor(0, 30, 660, 370);
w->editor->wrap_mode(1, 32);
w->editor->textfont(FL_COURIER); w->editor->textfont(FL_COURIER);
w->editor->textsize(TS); w->editor->textsize(TS);
w->editor->buffer(textbuf); w->editor->buffer(textbuf);
@ -812,6 +813,7 @@ int main(int argc, char **argv) {
" if ( fnfc.show() ) return;\n" " if ( fnfc.show() ) return;\n"
" save_file(fnfc.filename());\n" " save_file(fnfc.filename());\n"
"}\n\n" "}\n\n"
" 2 4 6 8 0 2 4 6 8 0 2 4 6 8 0 2 4 6 8 0\n\n"
"// Falsches Üben von Xylophonmusik quält jeden größeren Zwerg\n" "// Falsches Üben von Xylophonmusik quält jeden größeren Zwerg\n"
"// (= Wrongful practicing of xylophone music tortures every larger dwarf)\n" "// (= Wrongful practicing of xylophone music tortures every larger dwarf)\n"
"\n" "\n"

Loading…
Cancel
Save