Working on correct line wrapping in Fl_Text_Display: starting to replace all byte based charracter calculations with utf8 functions. Current version wraps, but scroll bars are wrong. Non-wrapping text display starts to work better.
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@7797 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
parent
5027ca90d3
commit
0fb4feb11a
@ -713,6 +713,7 @@ public:
|
||||
\param ix index to the current char
|
||||
*/
|
||||
int prev_char(int ix) const;
|
||||
int prev_char_clipped(int ix) const;
|
||||
|
||||
/**
|
||||
Returns a pointer to the previous character.
|
||||
@ -726,6 +727,7 @@ public:
|
||||
\param ix index to the current char
|
||||
*/
|
||||
int next_char(int ix) const;
|
||||
int next_char_clipped(int ix) const;
|
||||
|
||||
/**
|
||||
Returns a pointer to the next character.
|
||||
|
||||
@ -1585,7 +1585,7 @@ int Fl_Text_Buffer::outputfile(const char *file, int start, int end,
|
||||
Return the previous character position.
|
||||
Uncode safe.
|
||||
*/
|
||||
int Fl_Text_Buffer::prev_char(int pos) const
|
||||
int Fl_Text_Buffer::prev_char_clipped(int pos) const
|
||||
{
|
||||
if (pos<=0)
|
||||
return 0;
|
||||
@ -1601,9 +1601,21 @@ int Fl_Text_Buffer::prev_char(int pos) const
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Return the previous character poosition.
|
||||
Returns -1 if the beginning of the buffer is reached.
|
||||
*/
|
||||
int Fl_Text_Buffer::prev_char(int pos) const
|
||||
{
|
||||
if (pos==0) return -1;
|
||||
return prev_char_clipped(pos);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Return the next character position.
|
||||
Uncode safe.
|
||||
Returns length() if the end of the buffer is reached.
|
||||
*/
|
||||
int Fl_Text_Buffer::next_char(int pos) const
|
||||
{
|
||||
@ -1614,6 +1626,19 @@ int Fl_Text_Buffer::next_char(int pos) const
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Return the next character poosition.
|
||||
If the end of the buffer is reached, it returns the current position.
|
||||
*/
|
||||
int Fl_Text_Buffer::next_char_clipped(int pos) const
|
||||
{
|
||||
int n = next_char(pos);
|
||||
if (pos==mLength) return pos;
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// End of "$Id$".
|
||||
//
|
||||
|
||||
@ -38,6 +38,14 @@
|
||||
#include <FL/Fl_Text_Display.H>
|
||||
#include <FL/Fl_Window.H>
|
||||
|
||||
#define ASSERT_UTF8
|
||||
|
||||
#ifdef ASSERT_UTF8
|
||||
#define IS_UTF8_ALIGNED(a) if (a && *a) assert(fl_utf8len(*(a))>0);
|
||||
#else
|
||||
#define IS_UTF8_ALIGNED(a)
|
||||
#endif
|
||||
|
||||
#undef min
|
||||
#undef max
|
||||
|
||||
@ -86,8 +94,6 @@ static int scroll_x = 0;
|
||||
|
||||
\param X, Y, W, H position and size of widget
|
||||
\param l label text, defaults to none
|
||||
|
||||
\todo Unicode?
|
||||
*/
|
||||
Fl_Text_Display::Fl_Text_Display(int X, int Y, int W, int H, const char* l)
|
||||
: Fl_Group(X, Y, W, H, l) {
|
||||
@ -169,8 +175,6 @@ 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
|
||||
entity and is not freed, nor are the style buffer or style table.
|
||||
|
||||
\todo Unicode?
|
||||
*/
|
||||
Fl_Text_Display::~Fl_Text_Display() {
|
||||
if (scroll_direction) {
|
||||
@ -189,8 +193,6 @@ Fl_Text_Display::~Fl_Text_Display() {
|
||||
/**
|
||||
Attach a text buffer to display, replacing the current buffer (if any)
|
||||
\param buf attach this text buffer
|
||||
|
||||
\todo Unicode?
|
||||
*/
|
||||
void Fl_Text_Display::buffer( Fl_Text_Buffer *buf ) {
|
||||
/* If the text display is already displaying a buffer, clear it off
|
||||
@ -221,7 +223,8 @@ void Fl_Text_Display::buffer( Fl_Text_Buffer *buf ) {
|
||||
|
||||
|
||||
/**
|
||||
Attach (or remove) highlight information in text display and redisplay.
|
||||
\brief Attach (or remove) highlight information in text display and redisplay.
|
||||
|
||||
Highlighting information consists of a style buffer which parallels the
|
||||
normal text buffer, but codes font and color information for the display;
|
||||
a style table which translates style buffer codes (indexed by buffer
|
||||
@ -245,8 +248,6 @@ void Fl_Text_Display::buffer( Fl_Text_Buffer *buf ) {
|
||||
this callback will be called
|
||||
\param cbArg and optional argument for the callback above, usuallay a pointer
|
||||
to the Text Display.
|
||||
|
||||
\todo Unicode?
|
||||
*/
|
||||
void Fl_Text_Display::highlight_data(Fl_Text_Buffer *styleBuffer,
|
||||
const Style_Table_Entry *styleTable,
|
||||
@ -269,8 +270,6 @@ void Fl_Text_Display::highlight_data(Fl_Text_Buffer *styleBuffer,
|
||||
/**
|
||||
\brief Find the longest line of all visible lines.
|
||||
\return the width of the longest visible line in pixels
|
||||
|
||||
\todo Unicode?
|
||||
*/
|
||||
int Fl_Text_Display::longest_vline() const {
|
||||
int longest = 0;
|
||||
@ -286,8 +285,6 @@ int Fl_Text_Display::longest_vline() const {
|
||||
Calling this function will trigger a recalculation of all lines visible and
|
||||
of all scrollbar sizes.
|
||||
\param X, Y, W, H new position and size of this widget
|
||||
|
||||
\todo Unicode?
|
||||
*/
|
||||
void Fl_Text_Display::resize(int X, int Y, int W, int H) {
|
||||
#ifdef DEBUG
|
||||
@ -295,8 +292,7 @@ void Fl_Text_Display::resize(int X, int Y, int W, int H) {
|
||||
#endif // DEBUG
|
||||
const int oldWidth = w();
|
||||
#ifdef DEBUG
|
||||
printf(" oldWidth=%d, mContinuousWrap=%d, mWrapMargin=%d\n", oldWidth,
|
||||
mContinuousWrap, mWrapMargin);
|
||||
printf(" oldWidth=%d, mContinuousWrap=%d, mWrapMargin=%d\n", oldWidth, mContinuousWrap, mWrapMargin);
|
||||
#endif // DEBUG
|
||||
Fl_Widget::resize(X,Y,W,H);
|
||||
if (!buffer()) return;
|
||||
@ -333,8 +329,7 @@ void Fl_Text_Display::resize(int X, int Y, int W, int H) {
|
||||
mNBufferLines = count_lines(0, buffer()->length(), true);
|
||||
mFirstChar = line_start(mFirstChar);
|
||||
mTopLineNum = count_lines(0, mFirstChar, true)+1;
|
||||
absolute_top_line_number(oldFirstChar);
|
||||
|
||||
absolute_top_line_number(oldFirstChar);
|
||||
#ifdef DEBUG
|
||||
printf(" mNBufferLines=%d\n", mNBufferLines);
|
||||
#endif // DEBUG
|
||||
@ -456,8 +451,6 @@ void Fl_Text_Display::resize(int X, int Y, int W, int H) {
|
||||
\brief Refresh a rectangle of the text display.
|
||||
\param left, top are in coordinates of the text drawing window.
|
||||
\param width, height isze in pixels
|
||||
|
||||
\todo Unicode?
|
||||
*/
|
||||
void Fl_Text_Display::draw_text( int left, int top, int width, int height ) {
|
||||
int fontHeight, firstLine, lastLine, line;
|
||||
@ -488,29 +481,11 @@ void Fl_Text_Display::draw_text( int left, int top, int width, int height ) {
|
||||
the widget.
|
||||
\param startpos index of first character needing redraw
|
||||
\param endpos index after last character needing redraw
|
||||
|
||||
\todo Unicode?
|
||||
*/
|
||||
void Fl_Text_Display::redisplay_range(int startpos, int endpos) {
|
||||
int ok = 0;
|
||||
while (!ok && startpos > 0) {
|
||||
// FIXME: character is ucs-4
|
||||
char c = buffer()->char_at( startpos );
|
||||
if (!((c & 0x80) && !(c & 0x40))) {
|
||||
ok = 1;
|
||||
} else {
|
||||
startpos--;
|
||||
}
|
||||
}
|
||||
while (!ok && endpos < buffer()->length()) {
|
||||
// FIXME: character is ucs-4
|
||||
char c = buffer()->char_at( endpos );
|
||||
if (!((c & 0x80) && !(c & 0x40))) {
|
||||
ok = 1;
|
||||
} else {
|
||||
endpos++;
|
||||
}
|
||||
}
|
||||
IS_UTF8_ALIGNED(buffer()->address(startpos))
|
||||
IS_UTF8_ALIGNED(buffer()->address(endpos))
|
||||
|
||||
if (damage_range1_start == -1 && damage_range1_end == -1) {
|
||||
damage_range1_start = startpos;
|
||||
damage_range1_end = endpos;
|
||||
@ -542,15 +517,16 @@ void Fl_Text_Display::redisplay_range(int startpos, int endpos) {
|
||||
|
||||
\param startpos index of first character to draw
|
||||
\param endpos index after last character to draw
|
||||
|
||||
\todo Unicode?
|
||||
*/
|
||||
void Fl_Text_Display::draw_range(int startpos, int endpos) {
|
||||
IS_UTF8_ALIGNED(buffer()->address(startpos))
|
||||
IS_UTF8_ALIGNED(buffer()->address(endpos))
|
||||
|
||||
int i, startLine, lastLine, startIndex, endIndex;
|
||||
|
||||
/* If the range is outside of the displayed text, just return */
|
||||
if ( endpos < mFirstChar || ( startpos > mLastChar &&
|
||||
!empty_vlines() ) ) return;
|
||||
if ( endpos < mFirstChar || ( startpos > mLastChar && !empty_vlines() ) )
|
||||
return;
|
||||
|
||||
/* Clean up the starting and ending values */
|
||||
if ( startpos < 0 ) startpos = 0;
|
||||
@ -573,8 +549,7 @@ void Fl_Text_Display::draw_range(int startpos, int endpos) {
|
||||
}
|
||||
|
||||
/* Get the starting and ending positions within the lines */
|
||||
startIndex = mLineStarts[ startLine ] == -1 ? 0 :
|
||||
startpos - mLineStarts[ startLine ];
|
||||
startIndex = mLineStarts[ startLine ] == -1 ? 0 : startpos - mLineStarts[ startLine ];
|
||||
if ( endpos >= mLastChar )
|
||||
endIndex = INT_MAX;
|
||||
else if ( mLineStarts[ lastLine ] == -1 )
|
||||
@ -607,13 +582,12 @@ void Fl_Text_Display::draw_range(int startpos, int endpos) {
|
||||
Move the insertion cursor in front of the character at \p newPos.
|
||||
This function may trigger a redraw.
|
||||
\param newPos new caret position
|
||||
|
||||
\todo Unicode?
|
||||
*/
|
||||
void Fl_Text_Display::insert_position( int newPos ) {
|
||||
IS_UTF8_ALIGNED(buffer()->address(newPos))
|
||||
|
||||
/* make sure new position is ok, do nothing if it hasn't changed */
|
||||
if ( newPos == mCursorPos )
|
||||
return;
|
||||
if ( newPos == mCursorPos ) return;
|
||||
if ( newPos < 0 ) newPos = 0;
|
||||
if ( newPos > mBuffer->length() ) newPos = mBuffer->length();
|
||||
|
||||
@ -621,12 +595,12 @@ void Fl_Text_Display::insert_position( int newPos ) {
|
||||
mCursorPreferredCol = -1;
|
||||
|
||||
/* erase the cursor at it's previous position */
|
||||
redisplay_range(mCursorPos - 1, mCursorPos + 1); // FIXME utf8
|
||||
redisplay_range(buffer()->prev_char_clipped(mCursorPos), buffer()->next_char(mCursorPos));
|
||||
|
||||
mCursorPos = newPos;
|
||||
|
||||
/* draw cursor at its new position */
|
||||
redisplay_range(mCursorPos - 1, mCursorPos + 1); // FIXME utf8
|
||||
redisplay_range(buffer()->prev_char_clipped(mCursorPos), buffer()->next_char(mCursorPos));
|
||||
}
|
||||
|
||||
|
||||
@ -635,12 +609,10 @@ void Fl_Text_Display::insert_position( int newPos ) {
|
||||
\brief Shows the text cursor.
|
||||
This function may trigger a redraw.
|
||||
\param b show(1) or hide(0) the text cursor (caret).
|
||||
|
||||
\todo Unicode?
|
||||
*/
|
||||
void Fl_Text_Display::show_cursor(int b) {
|
||||
mCursorOn = b;
|
||||
redisplay_range(mCursorPos - 1, mCursorPos + 1); // FIXME utf8
|
||||
redisplay_range(buffer()->prev_char_clipped(mCursorPos), buffer()->next_char(mCursorPos));
|
||||
}
|
||||
|
||||
|
||||
@ -653,14 +625,12 @@ void Fl_Text_Display::show_cursor(int b) {
|
||||
\li Fl_Text_Display::CARET_CURSOR - Shows a caret under the text.
|
||||
\li Fl_Text_Display::DIM_CURSOR - Shows a dimmed I beam.
|
||||
\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.
|
||||
|
||||
This call also switches the cursor on and may trigger a redraw.
|
||||
|
||||
\param style new cursor style
|
||||
|
||||
\todo Unicode?
|
||||
*/
|
||||
void Fl_Text_Display::cursor_style(int style) {
|
||||
mCursorStyle = style;
|
||||
@ -683,8 +653,6 @@ void Fl_Text_Display::cursor_style(int style) {
|
||||
\todo this does not work for multi-byte characters yet
|
||||
\todo we need new wrap modes to wrap at the window edge and based on pixel width
|
||||
or average character width.
|
||||
|
||||
\todo Unicode?
|
||||
*/
|
||||
void Fl_Text_Display::wrap_mode(int wrap, int wrapMargin) {
|
||||
mWrapMargin = wrapMargin;
|
||||
@ -726,10 +694,11 @@ void Fl_Text_Display::wrap_mode(int wrap, int wrapMargin) {
|
||||
that it's optimized to do less redrawing.
|
||||
|
||||
\param text new text in UTF-8 encoding.
|
||||
|
||||
\todo Unicode?
|
||||
*/
|
||||
void Fl_Text_Display::insert(const char* text) {
|
||||
IS_UTF8_ALIGNED(buffer()->address(mCursorPos))
|
||||
IS_UTF8_ALIGNED(text)
|
||||
|
||||
int pos = mCursorPos;
|
||||
|
||||
mCursorToHint = pos + strlen( text );
|
||||
@ -741,33 +710,36 @@ void Fl_Text_Display::insert(const char* text) {
|
||||
|
||||
/**
|
||||
\brief Replaces text at the current insert position.
|
||||
\param text new text in YTF-8 encoding
|
||||
\param text new text in UTF-8 encoding
|
||||
|
||||
\todo Unicode?
|
||||
\todo Unicode? Find out exactly what we do here and simplify.
|
||||
*/
|
||||
void Fl_Text_Display::overstrike(const char* text) {
|
||||
IS_UTF8_ALIGNED(buffer()->address(mCursorPos))
|
||||
IS_UTF8_ALIGNED(text)
|
||||
|
||||
int startPos = mCursorPos;
|
||||
Fl_Text_Buffer *buf = mBuffer;
|
||||
int lineStart = buf->line_start( startPos );
|
||||
int textLen = strlen( text );
|
||||
int i, p, endPos, indent, startIndent, endIndent;
|
||||
const char *c;
|
||||
char ch, *paddedText = NULL;
|
||||
unsigned int ch;
|
||||
char *paddedText = NULL;
|
||||
|
||||
/* determine how many displayed character positions are covered */
|
||||
startIndent = mBuffer->count_displayed_characters( lineStart, startPos );
|
||||
indent = startIndent;
|
||||
for ( c = text; *c != '\0'; c++ )
|
||||
for ( c = text; *c != '\0'; c += fl_utf8len(*c) )
|
||||
indent++;
|
||||
endIndent = indent;
|
||||
|
||||
/* find which characters to remove, and if necessary generate additional
|
||||
padding to make up for removed control characters at the end */
|
||||
indent = startIndent;
|
||||
for ( p = startPos; ; p++ ) {
|
||||
for ( p = startPos; ; p=buffer()->next_char(p) ) {
|
||||
if ( p == buf->length() )
|
||||
break;
|
||||
// FIXME: character is ucs-4
|
||||
ch = buf->char_at( p );
|
||||
if ( ch == '\n' )
|
||||
break;
|
||||
@ -810,10 +782,10 @@ void Fl_Text_Display::overstrike(const char* text) {
|
||||
\param pos character index
|
||||
\param[out] X, Y pixel position of character on screen
|
||||
\return 0 if charater vertically out of view, X position otherwise
|
||||
|
||||
\todo Unicode?
|
||||
*/
|
||||
int Fl_Text_Display::position_to_xy( int pos, int* X, int* Y ) const {
|
||||
IS_UTF8_ALIGNED(buffer()->address(pos))
|
||||
|
||||
int lineStartPos, fontHeight, lineLen;
|
||||
int visLineNum;
|
||||
|
||||
@ -849,7 +821,7 @@ int Fl_Text_Display::position_to_xy( int pos, int* X, int* Y ) const {
|
||||
|
||||
|
||||
/**
|
||||
\brief Find the line an column number of position "pos".
|
||||
\brief Find the line and column number of position "pos".
|
||||
|
||||
This only works for displayed lines. If the line is not displayed, the
|
||||
function returns 0 (without the mLineStarts array it could turn in to very long
|
||||
@ -864,18 +836,17 @@ int Fl_Text_Display::position_to_xy( int pos, int* X, int* Y ) const {
|
||||
\todo a column number makes little sense in the UTF-8/variable font width
|
||||
environment. We will have to further define what exactly we want to return.
|
||||
Please check teh functions that call this particular function.
|
||||
|
||||
\todo Unicode?
|
||||
*/
|
||||
int Fl_Text_Display::position_to_linecol( int pos, int* lineNum, int* column ) const {
|
||||
IS_UTF8_ALIGNED(buffer()->address(pos))
|
||||
|
||||
int retVal;
|
||||
|
||||
/* In continuous wrap mode, the absolute (non-wrapped) line count is
|
||||
maintained separately, as needed. Only return it if we're actually
|
||||
keeping track of it and pos is in the displayed text */
|
||||
if (mContinuousWrap) {
|
||||
if (!maintaining_absolute_top_line_number() ||
|
||||
pos < mFirstChar || pos > mLastChar)
|
||||
if (!maintaining_absolute_top_line_number() || pos < mFirstChar || pos > mLastChar)
|
||||
return 0;
|
||||
*lineNum = mAbsTopLineNum + buffer()->count_lines(mFirstChar, pos);
|
||||
*column = buffer()->count_displayed_characters(buffer()->line_start(pos), pos);
|
||||
@ -896,11 +867,10 @@ int Fl_Text_Display::position_to_linecol( int pos, int* lineNum, int* column ) c
|
||||
\brief Check if a pixel position is within the primary seection.
|
||||
\param X, Y pixel position to test
|
||||
\return 1 if position (X, Y) is inside of the primary Fl_Text_Selection
|
||||
|
||||
\todo Unicode?
|
||||
*/
|
||||
int Fl_Text_Display::in_selection( int X, int Y ) const {
|
||||
int pos = xy_to_position( X, Y, CHARACTER_POS );
|
||||
IS_UTF8_ALIGNED(buffer()->address(pos))
|
||||
Fl_Text_Buffer *buf = mBuffer;
|
||||
return buf->primary_selection()->includes(pos);
|
||||
}
|
||||
@ -936,8 +906,7 @@ int Fl_Text_Display::wrapped_column(int row, int column) const {
|
||||
if (dispLineStart == -1)
|
||||
return column;
|
||||
lineStart = buffer()->line_start(dispLineStart);
|
||||
return column
|
||||
+ buffer()->count_displayed_characters(lineStart, dispLineStart);
|
||||
return column + buffer()->count_displayed_characters(lineStart, dispLineStart);
|
||||
}
|
||||
|
||||
|
||||
@ -956,8 +925,6 @@ int Fl_Text_Display::wrapped_column(int row, int column) const {
|
||||
\return something unknown
|
||||
\todo What does this do and how is it useful? Column numbers mean little in
|
||||
this context. Which functions depend on this one?
|
||||
|
||||
\todo Unicode?
|
||||
*/
|
||||
int Fl_Text_Display::wrapped_row(int row) const{
|
||||
if (!mContinuousWrap || row < 0 || row > mNVisibleLines)
|
||||
@ -1186,6 +1153,9 @@ int Fl_Text_Display::move_down() {
|
||||
*/
|
||||
int Fl_Text_Display::count_lines(int startPos, int endPos,
|
||||
bool startPosIsLineStart) const {
|
||||
IS_UTF8_ALIGNED(buffer()->address(startPos))
|
||||
IS_UTF8_ALIGNED(buffer()->address(endPos))
|
||||
|
||||
int retLines, retPos, retLineStart, retLineEnd;
|
||||
|
||||
#ifdef DEBUG
|
||||
@ -1228,6 +1198,8 @@ int Fl_Text_Display::count_lines(int startPos, int endPos,
|
||||
*/
|
||||
int Fl_Text_Display::skip_lines(int startPos, int nLines,
|
||||
bool startPosIsLineStart) {
|
||||
IS_UTF8_ALIGNED(buffer()->address(startPos))
|
||||
|
||||
int retLines, retPos, retLineStart, retLineEnd;
|
||||
|
||||
/* if we're not wrapping use more efficient BufCountForwardNLines */
|
||||
@ -1272,6 +1244,8 @@ int Fl_Text_Display::skip_lines(int startPos, int nLines,
|
||||
\todo Unicode?
|
||||
*/
|
||||
int Fl_Text_Display::line_end(int pos, bool startPosIsLineStart) const {
|
||||
IS_UTF8_ALIGNED(buffer()->address(pos))
|
||||
|
||||
int retLines, retPos, retLineStart, retLineEnd;
|
||||
|
||||
/* If we're not wrapping use more efficien BufEndOfLine */
|
||||
@ -1300,6 +1274,8 @@ int Fl_Text_Display::line_end(int pos, bool startPosIsLineStart) const {
|
||||
\todo Unicode?
|
||||
*/
|
||||
int Fl_Text_Display::line_start(int pos) const {
|
||||
IS_UTF8_ALIGNED(buffer()->address(pos))
|
||||
|
||||
int retLines, retPos, retLineStart, retLineEnd;
|
||||
|
||||
/* If we're not wrapping, use the more efficient BufStartOfLine */
|
||||
@ -1325,6 +1301,8 @@ int Fl_Text_Display::line_start(int pos) const {
|
||||
\todo Unicode?
|
||||
*/
|
||||
int Fl_Text_Display::rewind_lines(int startPos, int nLines) {
|
||||
IS_UTF8_ALIGNED(buffer()->address(startPos))
|
||||
|
||||
Fl_Text_Buffer *buf = buffer();
|
||||
int pos, lineStart, retLines, retPos, retLineStart, retLineEnd;
|
||||
|
||||
@ -1451,6 +1429,7 @@ void Fl_Text_Display::buffer_modified_cb( int pos, int nInserted, int nDeleted,
|
||||
int linesInserted, linesDeleted, startDispPos, endDispPos;
|
||||
Fl_Text_Display *textD = ( Fl_Text_Display * ) cbArg;
|
||||
Fl_Text_Buffer *buf = textD->mBuffer;
|
||||
IS_UTF8_ALIGNED(buf->address(pos))
|
||||
int oldFirstChar = textD->mFirstChar;
|
||||
int scrolled, origCursorPos = textD->mCursorPos;
|
||||
int wrapModStart, wrapModEnd;
|
||||
@ -1667,6 +1646,8 @@ void Fl_Text_Display::reset_absolute_top_line_number() {
|
||||
\todo Unicode?
|
||||
*/
|
||||
int Fl_Text_Display::position_to_line( int pos, int *lineNum ) const {
|
||||
IS_UTF8_ALIGNED(buffer()->address(pos))
|
||||
|
||||
int i;
|
||||
|
||||
*lineNum = 0;
|
||||
@ -1725,6 +1706,10 @@ int Fl_Text_Display::handle_vline(
|
||||
int Y, int bottomClip,
|
||||
int leftClip, int rightClip) const
|
||||
{
|
||||
IS_UTF8_ALIGNED(buffer()->address(lineStartPos))
|
||||
IS_UTF8_ALIGNED(buffer()->address(leftChar))
|
||||
if (rightChar!=INT_MAX) IS_UTF8_ALIGNED(buffer()->address(rightChar))
|
||||
|
||||
// FIXME: we need to allow two modes for FIND_INDEX: one on the edge of the
|
||||
// FIXME: character for selection, and one on the character center for cursors.
|
||||
int i, X, startX, startIndex, style, charStyle;
|
||||
@ -1818,6 +1803,8 @@ int Fl_Text_Display::handle_vline(
|
||||
\todo Unicode?
|
||||
*/
|
||||
int Fl_Text_Display::find_x(const char *s, int len, int style, int x) const {
|
||||
IS_UTF8_ALIGNED(s)
|
||||
|
||||
// FIXME: use binary search which is much quicker!
|
||||
int i = 0;
|
||||
while (i<len) {
|
||||
@ -1917,6 +1904,8 @@ void Fl_Text_Display::draw_vline(int visLineNum, int leftClip, int rightClip,
|
||||
void Fl_Text_Display::draw_string(int style,
|
||||
int X, int Y, int toX,
|
||||
const char *string, int nChars) const {
|
||||
IS_UTF8_ALIGNED(string)
|
||||
|
||||
const Style_Table_Entry * styleRec;
|
||||
|
||||
/* Draw blank area rather than text, if that was the request */
|
||||
@ -2133,6 +2122,8 @@ void Fl_Text_Display::draw_cursor( int X, int Y ) {
|
||||
*/
|
||||
int Fl_Text_Display::position_style( int lineStartPos, int lineLen, int lineIndex) const
|
||||
{
|
||||
IS_UTF8_ALIGNED(buffer()->address(lineStartPos))
|
||||
|
||||
Fl_Text_Buffer * buf = mBuffer;
|
||||
Fl_Text_Buffer *styleBuf = mStyleBuffer;
|
||||
int pos, style = 0;
|
||||
@ -2170,12 +2161,12 @@ int Fl_Text_Display::position_style( int lineStartPos, int lineLen, int lineInde
|
||||
\param length number of bytes instring
|
||||
\param style index into style table
|
||||
\return width of text segemnt in pixels
|
||||
|
||||
\todo Unicode?
|
||||
*/
|
||||
int Fl_Text_Display::string_width( const char *string, int length, int style ) const {
|
||||
IS_UTF8_ALIGNED(string)
|
||||
|
||||
Fl_Font font;
|
||||
int fsize;
|
||||
Fl_Fontsize fsize;
|
||||
|
||||
if ( style & STYLE_LOOKUP_MASK ) {
|
||||
int si = (style & STYLE_LOOKUP_MASK) - 'A';
|
||||
@ -2357,6 +2348,8 @@ void Fl_Text_Display::offset_line_starts( int newTopLineNum ) {
|
||||
*/
|
||||
void Fl_Text_Display::update_line_starts( int pos, int charsInserted,
|
||||
int charsDeleted, int linesInserted, int linesDeleted, int *scrolled ) {
|
||||
IS_UTF8_ALIGNED(buffer()->address(pos))
|
||||
|
||||
int * lineStarts = mLineStarts;
|
||||
int i, lineOfPos, lineOfEnd, nVisLines = mNVisibleLines;
|
||||
int charDelta = charsInserted - charsDeleted;
|
||||
@ -2457,7 +2450,7 @@ void Fl_Text_Display::update_line_starts( int pos, int charsInserted,
|
||||
newlines to fill in the requested entries. Out of range values for
|
||||
"startLine" and "endLine" are acceptable.
|
||||
|
||||
\param startLine, endLine range of lines to scan.
|
||||
\param startLine, endLine range of lines to scan as line numbers
|
||||
|
||||
\todo Unicode?
|
||||
*/
|
||||
@ -2729,6 +2722,8 @@ static int min( int i1, int i2 ) {
|
||||
\todo Unicode?
|
||||
*/
|
||||
static int countlines( const char *string ) {
|
||||
IS_UTF8_ALIGNED(string)
|
||||
|
||||
const char * c;
|
||||
int lineCount = 0;
|
||||
|
||||
@ -2831,6 +2826,9 @@ int Fl_Text_Display::vline_length( int visLineNum ) const {
|
||||
void Fl_Text_Display::find_wrap_range(const char *deletedText, int pos,
|
||||
int nInserted, int nDeleted, int *modRangeStart, int *modRangeEnd,
|
||||
int *linesInserted, int *linesDeleted) {
|
||||
IS_UTF8_ALIGNED(deletedText)
|
||||
IS_UTF8_ALIGNED(buffer()->address(pos))
|
||||
|
||||
int length, retPos, retLines, retLineStart, retLineEnd;
|
||||
Fl_Text_Buffer *deletedTextBuf, *buf = buffer();
|
||||
int nVisLines = mNVisibleLines;
|
||||
@ -2855,6 +2853,7 @@ void Fl_Text_Display::find_wrap_range(const char *deletedText, int pos,
|
||||
} else
|
||||
countFrom = buf->line_start(pos);
|
||||
|
||||
IS_UTF8_ALIGNED(buffer()->address(countFrom))
|
||||
|
||||
/*
|
||||
** Move forward through the (new) text one line at a time, counting
|
||||
@ -2994,6 +2993,8 @@ void Fl_Text_Display::find_wrap_range(const char *deletedText, int pos,
|
||||
\todo Unicode?
|
||||
*/
|
||||
void Fl_Text_Display::measure_deleted_lines(int pos, int nDeleted) {
|
||||
IS_UTF8_ALIGNED(buffer()->address(pos))
|
||||
|
||||
int retPos, retLines, retLineStart, retLineEnd;
|
||||
Fl_Text_Buffer *buf = buffer();
|
||||
int nVisLines = mNVisibleLines;
|
||||
@ -3093,11 +3094,14 @@ void Fl_Text_Display::wrapped_line_counter(Fl_Text_Buffer *buf, int startPos,
|
||||
int maxPos, int maxLines, bool startPosIsLineStart, int styleBufOffset,
|
||||
int *retPos, int *retLines, int *retLineStart, int *retLineEnd,
|
||||
bool countLastLineMissingNewLine) const {
|
||||
IS_UTF8_ALIGNED(buf->address(startPos))
|
||||
if (maxPos<buf->length()) IS_UTF8_ALIGNED(buf->address(maxPos))
|
||||
|
||||
int lineStart, newLineStart = 0, b, p, colNum, wrapMargin;
|
||||
int maxWidth, i, foundBreak, width;
|
||||
bool countPixels;
|
||||
int nLines = 0;
|
||||
unsigned char c;
|
||||
unsigned int c;
|
||||
|
||||
/* If the font is fixed, or there's a wrap margin set, it's more efficient
|
||||
to measure in columns, than to count pixels. Determine if we can count
|
||||
@ -3128,9 +3132,8 @@ void Fl_Text_Display::wrapped_line_counter(Fl_Text_Buffer *buf, int startPos,
|
||||
*/
|
||||
colNum = 0;
|
||||
width = 0;
|
||||
for (p=lineStart; p<buf->length(); p++) {
|
||||
// FIXME: character is ucs-4
|
||||
c = (unsigned char)buf->char_at(p);
|
||||
for (p=lineStart; p<buf->length(); p=buffer()->next_char(p)) {
|
||||
c = buf->char_at(p); // UCS-4
|
||||
|
||||
/* If the character was a newline, count the line and start over,
|
||||
otherwise, add it to the width and column counts */
|
||||
@ -3144,18 +3147,22 @@ void Fl_Text_Display::wrapped_line_counter(Fl_Text_Buffer *buf, int startPos,
|
||||
}
|
||||
nLines++;
|
||||
if (nLines >= maxLines) {
|
||||
*retPos = p + 1;
|
||||
int p1 = buffer()->next_char(p);
|
||||
*retPos = p1;
|
||||
*retLines = nLines;
|
||||
*retLineStart = p + 1;
|
||||
*retLineStart = p1;
|
||||
*retLineEnd = p;
|
||||
return;
|
||||
}
|
||||
lineStart = p + 1;
|
||||
lineStart = buffer()->next_char(p);
|
||||
colNum = 0;
|
||||
width = 0;
|
||||
} else {
|
||||
const char *s = buf->address(p);
|
||||
colNum++;
|
||||
// FIXME: it is not a good idea to simply add character widths because on
|
||||
// some platforms, the width is a floating point value and depends on the
|
||||
// previous character as well.
|
||||
if (countPixels)
|
||||
width += measure_proportional_character(s, colNum, p+styleBufOffset);
|
||||
}
|
||||
@ -3164,29 +3171,26 @@ void Fl_Text_Display::wrapped_line_counter(Fl_Text_Buffer *buf, int startPos,
|
||||
and wrap there */
|
||||
if (colNum > wrapMargin || width > maxWidth) {
|
||||
foundBreak = false;
|
||||
for (b=p; b>=lineStart; b--) {
|
||||
// FIXME: character is ucs-4
|
||||
c = (unsigned char)buf->char_at(b);
|
||||
for (b=p; b>=lineStart; b=buffer()->prev_char(b)) {
|
||||
c = buf->char_at(b);
|
||||
if (c == '\t' || c == ' ') {
|
||||
newLineStart = b + 1;
|
||||
newLineStart = buffer()->next_char(b);
|
||||
if (countPixels) {
|
||||
colNum = 0;
|
||||
width = 0;
|
||||
for (i=b+1; i<p+1; i++) {
|
||||
width += measure_proportional_character(
|
||||
// FIXME: character is ucs-4
|
||||
buf->address(i), colNum,
|
||||
width += measure_proportional_character(buf->address(i), colNum,
|
||||
i+styleBufOffset);
|
||||
colNum++;
|
||||
}
|
||||
} else
|
||||
colNum = buf->count_displayed_characters(b+1, p+1);
|
||||
colNum = buf->count_displayed_characters(buffer()->next_char(b), buffer()->next_char(p));
|
||||
foundBreak = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!foundBreak) { /* no whitespace, just break at margin */
|
||||
newLineStart = max(p, lineStart+1);
|
||||
newLineStart = max(p, buffer()->next_char(lineStart));
|
||||
const char *s = buf->address(b);
|
||||
colNum++;
|
||||
if (countPixels)
|
||||
@ -3195,14 +3199,13 @@ void Fl_Text_Display::wrapped_line_counter(Fl_Text_Buffer *buf, int startPos,
|
||||
if (p >= maxPos) {
|
||||
*retPos = maxPos;
|
||||
*retLines = maxPos < newLineStart ? nLines : nLines + 1;
|
||||
*retLineStart = maxPos < newLineStart ? lineStart :
|
||||
newLineStart;
|
||||
*retLineStart = maxPos < newLineStart ? lineStart : newLineStart;
|
||||
*retLineEnd = maxPos;
|
||||
return;
|
||||
}
|
||||
nLines++;
|
||||
if (nLines >= maxLines) {
|
||||
*retPos = foundBreak ? b + 1 : max(p, lineStart+1);
|
||||
*retPos = foundBreak ? buffer()->next_char(b) : max(p, buffer()->next_char(lineStart));
|
||||
*retLines = nLines;
|
||||
*retLineStart = lineStart;
|
||||
*retLineEnd = foundBreak ? b : p;
|
||||
@ -3215,8 +3218,8 @@ void Fl_Text_Display::wrapped_line_counter(Fl_Text_Buffer *buf, int startPos,
|
||||
/* reached end of buffer before reaching pos or line target */
|
||||
*retPos = buf->length();
|
||||
*retLines = nLines;
|
||||
if (countLastLineMissingNewLine && colNum > 0)
|
||||
++(*retLines);
|
||||
if (countLastLineMissingNewLine && colNum > 0)
|
||||
*retLines = buffer()->next_char(*retLines);
|
||||
*retLineStart = lineStart;
|
||||
*retLineEnd = buf->length();
|
||||
}
|
||||
@ -3239,18 +3242,17 @@ void Fl_Text_Display::wrapped_line_counter(Fl_Text_Buffer *buf, int startPos,
|
||||
insertion/deletion, though static display and wrapping and resizing
|
||||
should now be solid because they are now used for online help display.
|
||||
|
||||
\param s ??
|
||||
\param colNum ??
|
||||
\param pos ??
|
||||
\return ??
|
||||
|
||||
\todo Unicode?
|
||||
\param s text string
|
||||
\param colNum unused
|
||||
\param pos offset within string
|
||||
\return width of character in pixels
|
||||
*/
|
||||
int Fl_Text_Display::measure_proportional_character(const char *s, int colNum, int pos) const {
|
||||
IS_UTF8_ALIGNED(s)
|
||||
|
||||
int charLen = fl_utf8len(*s), style = 0;
|
||||
if (mStyleBuffer) {
|
||||
const char *b = mStyleBuffer->address(pos);
|
||||
style = *b;
|
||||
style = mStyleBuffer->byte_at(pos);
|
||||
}
|
||||
return string_width(s, charLen, style);
|
||||
}
|
||||
@ -3278,12 +3280,16 @@ int Fl_Text_Display::measure_proportional_character(const char *s, int colNum, i
|
||||
*/
|
||||
void Fl_Text_Display::find_line_end(int startPos, bool startPosIsLineStart,
|
||||
int *lineEnd, int *nextLineStart) const {
|
||||
IS_UTF8_ALIGNED(buffer()->address(startPos))
|
||||
|
||||
int retLines, retLineStart;
|
||||
|
||||
/* if we're not wrapping use more efficient BufEndOfLine */
|
||||
if (!mContinuousWrap) {
|
||||
*lineEnd = buffer()->line_end(startPos);
|
||||
*nextLineStart = min(buffer()->length(), *lineEnd + 1);
|
||||
int le = buffer()->line_end(startPos);
|
||||
int ls = buffer()->next_char(le);
|
||||
*lineEnd = le;
|
||||
*nextLineStart = min(buffer()->length(), ls);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -3291,7 +3297,6 @@ void Fl_Text_Display::find_line_end(int startPos, bool startPosIsLineStart,
|
||||
wrapped_line_counter(buffer(), startPos, buffer()->length(),
|
||||
1, startPosIsLineStart, 0, nextLineStart, &retLines,
|
||||
&retLineStart, lineEnd);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -3314,21 +3319,20 @@ void Fl_Text_Display::find_line_end(int startPos, bool startPosIsLineStart,
|
||||
used as a wrap point, and just guesses that it wasn't. So if an exact
|
||||
accounting is necessary, don't use this function.
|
||||
|
||||
\param lineEndPos ??
|
||||
\return ??
|
||||
|
||||
\todo Unicode?
|
||||
\param lineEndPos index of character where the line wraps
|
||||
\return 1 if a \\n character causes the line wrap
|
||||
*/
|
||||
int Fl_Text_Display::wrap_uses_character(int lineEndPos) const {
|
||||
IS_UTF8_ALIGNED(buffer()->address(lineEndPos))
|
||||
|
||||
char c;
|
||||
|
||||
if (!mContinuousWrap || lineEndPos == buffer()->length())
|
||||
return 1;
|
||||
|
||||
// FIXME: character is ucs-4
|
||||
c = buffer()->char_at(lineEndPos);
|
||||
return c == '\n' || ((c == '\t' || c == ' ') &&
|
||||
lineEndPos + 1 != buffer()->length());
|
||||
lineEndPos + fl_utf8len(c) < buffer()->length());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -785,7 +785,7 @@ Fl_Window* new_view() {
|
||||
Fl_Menu_Bar* m = new Fl_Menu_Bar(0, 0, 660, 30);
|
||||
m->copy(menuitems, w);
|
||||
w->editor = new Fl_Text_Editor(0, 30, 660, 370);
|
||||
w->editor->wrap_mode(1, 32);
|
||||
//w->editor->wrap_mode(1, 32);
|
||||
w->editor->textfont(FL_COURIER);
|
||||
w->editor->textsize(TS);
|
||||
w->editor->buffer(textbuf);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user