From 823b1f8460c82110ff0cd28c94684d413d955ad7 Mon Sep 17 00:00:00 2001 From: Bill Spitzak Date: Tue, 20 Jun 2000 07:56:09 +0000 Subject: [PATCH] Fixes to WORDWRAP modification to Fl_Input based on work done by Alexander Rabi Beels. This will not affect things much because WORDWRAP is normally disabled. However it fixes a few bugs with word+line selection and with up/down arrows working when there are tabs or control characters in the text. I modified his patches so no changes are needed to the header files to enable wordwrap and so that very long words scroll horizontally rather than break between letters. git-svn-id: file:///fltk/svn/fltk/branches/branch-1.0@1223 ea41ed52-d2ee-0310-a9c1-e6b18d33e121 --- FL/Fl_Input_.H | 10 ++-- src/Fl_Input.cxx | 37 ++++--------- src/Fl_Input_.cxx | 138 +++++++++++++++++++++++++++++++++------------- 3 files changed, 117 insertions(+), 68 deletions(-) diff --git a/FL/Fl_Input_.H b/FL/Fl_Input_.H index f02e77487..5151e8207 100644 --- a/FL/Fl_Input_.H +++ b/FL/Fl_Input_.H @@ -1,5 +1,5 @@ // -// "$Id: Fl_Input_.H,v 1.6.2.2 2000/06/05 21:20:24 mike Exp $" +// "$Id: Fl_Input_.H,v 1.6.2.3 2000/06/20 07:56:06 bill Exp $" // // Input base class header file for the Fast Light Tool Kit (FLTK). // @@ -66,8 +66,10 @@ class Fl_Input_ : public Fl_Widget { protected: - FL_EXPORT int wordboundary(int i) const; - FL_EXPORT int lineboundary(int i) const; + FL_EXPORT int word_start(int i) const; + FL_EXPORT int word_end(int i) const; + FL_EXPORT int line_start(int i) const; + FL_EXPORT int line_end(int i) const; FL_EXPORT void drawtext(int, int, int, int); FL_EXPORT int up_down_position(int, int keepmark=0); FL_EXPORT void handle_mouse(int, int, int, int, int keepmark=0); @@ -120,5 +122,5 @@ public: #endif // -// End of "$Id: Fl_Input_.H,v 1.6.2.2 2000/06/05 21:20:24 mike Exp $". +// End of "$Id: Fl_Input_.H,v 1.6.2.3 2000/06/20 07:56:06 bill Exp $". // diff --git a/src/Fl_Input.cxx b/src/Fl_Input.cxx index 3e6194982..89a511dd5 100644 --- a/src/Fl_Input.cxx +++ b/src/Fl_Input.cxx @@ -1,5 +1,5 @@ // -// "$Id: Fl_Input.cxx,v 1.10.2.11 2000/06/10 21:31:00 bill Exp $" +// "$Id: Fl_Input.cxx,v 1.10.2.12 2000/06/20 07:56:08 bill Exp $" // // Input widget for the Fast Light Tool Kit (FLTK). // @@ -119,11 +119,7 @@ int Fl_Input::handle_key() { int i; switch (ascii) { case ctrl('A'): - if (type() == FL_MULTILINE_INPUT) - for (i=position(); i && index(i-1)!='\n'; i--) ; - else - i = 0; - return shift_position(i) + NORMAL_INPUT_MOVE; + return shift_position(line_start(position())) + NORMAL_INPUT_MOVE; case ctrl('B'): return shift_position(position()-1) + NORMAL_INPUT_MOVE; case ctrl('C'): // copy @@ -133,11 +129,7 @@ int Fl_Input::handle_key() { if (mark() != position()) return cut(); else return cut(1); case ctrl('E'): - if (type() == FL_MULTILINE_INPUT) - for (i=position(); index(i) && index(i)!='\n'; i++) ; - else - i = size(); - return shift_position(i) + NORMAL_INPUT_MOVE; + return shift_position(line_end(position())) + NORMAL_INPUT_MOVE; case ctrl('F'): return shift_position(position()+1) + NORMAL_INPUT_MOVE; case ctrl('H'): @@ -146,26 +138,19 @@ int Fl_Input::handle_key() { return 1; case ctrl('K'): if (position()>=size()) return 0; - if (type() == FL_MULTILINE_INPUT) { - if (index(position()) == '\n') - i = position() + 1; - else - for (i=position()+1; index(i) && index(i) != '\n'; i++); - } else - i = size(); + i = line_end(position()); + if (i == position() && i < size()) i++; cut(position(), i); return copy_cuts(); case ctrl('N'): - if (type()!=FL_MULTILINE_INPUT) return 0; - for (i=position(); index(i)!='\n'; i++) - if (!index(i)) return NORMAL_INPUT_MOVE; + i = line_end(position()); + if (i >= size()) return NORMAL_INPUT_MOVE; shift_up_down_position(i+1); return 1; case ctrl('P'): - if (type()!=FL_MULTILINE_INPUT) return 0; - for (i = position(); i > 0 && index(i-1) != '\n'; i--) ; + i = line_start(position()); if (!i) return NORMAL_INPUT_MOVE; - shift_up_down_position(i-1); + shift_up_down_position(line_start(i-1)); return 1; case ctrl('U'): return cut(0, size()); @@ -208,7 +193,7 @@ int Fl_Input::handle(int event) { up_down_position(0); break; case FL_Up: - up_down_position(size()); + up_down_position(line_start(size())); break; case FL_Tab: case 0xfe20: // XK_ISO_Left_Tab @@ -259,5 +244,5 @@ Fl_Input::Fl_Input(int x, int y, int w, int h, const char *l) } // -// End of "$Id: Fl_Input.cxx,v 1.10.2.11 2000/06/10 21:31:00 bill Exp $". +// End of "$Id: Fl_Input.cxx,v 1.10.2.12 2000/06/20 07:56:08 bill Exp $". // diff --git a/src/Fl_Input_.cxx b/src/Fl_Input_.cxx index 083a83bed..03c87fcc5 100644 --- a/src/Fl_Input_.cxx +++ b/src/Fl_Input_.cxx @@ -1,5 +1,5 @@ // -// "$Id: Fl_Input_.cxx,v 1.21.2.7 2000/06/08 07:38:29 bill Exp $" +// "$Id: Fl_Input_.cxx,v 1.21.2.8 2000/06/20 07:56:09 bill Exp $" // // Common input widget routines for the Fast Light Tool Kit (FLTK). // @@ -40,10 +40,8 @@ //////////////////////////////////////////////////////////////// -// Wordwrap kludge. It "sort of" works but there are lots of bugs. -// Really the whole multi-line-input should be moved to a seperate -// (and much more complex) subclass. Single-line and multi-line -// input are really a *lot* different! +// Wordwrap kludge. This works ok but is commented out because +// we want to move multi-line functionality to it's own subclass. // To try the wordwrap define this: //#define WORDWRAP #ifdef WORDWRAP @@ -60,17 +58,19 @@ const char* Fl_Input_::expand(const char* p, char* buf) const { const char* lastspace = p; char* lastspace_out = o; int width_to_lastspace = 0; + int word_count = 0; #endif if (type()==FL_SECRET_INPUT) { while (o= value_+size_ || *p==' ' || *p=='\n')) { - width_to_lastspace += fl_width(lastspace, p-lastspace); + if (wordwrap && (p >= value_+size_ || isspace(*p))) { + width_to_lastspace += (int)fl_width(lastspace_out, o-lastspace_out); if (p > lastspace+1) { - if (width_to_lastspace > wordwrap) { + if (word_count && width_to_lastspace > wordwrap) { p = lastspace; o = lastspace_out; break; } + word_count++; } lastspace = p; lastspace_out = o; @@ -216,8 +216,7 @@ void Fl_Input_::drawtext(int X, int Y, int W, int H) { } lines++; if (e >= value_+size_) break; - if (*e == '\n' || *e == ' ') e++; - p = e; + p = e+1; } // adjust the scrolling: @@ -296,8 +295,7 @@ void Fl_Input_::drawtext(int X, int Y, int W, int H) { CONTINUE: ypos += height; if (e >= value_+size_) break; - if (*e == '\n' || *e == ' ') e++; - p = e; + p = e+1; } // for minimal update, erase all lines below last one if necessary: @@ -315,15 +313,59 @@ static int isword(char c) { return (c&128 || isalnum(c) || strchr("#%&-/@\\_~", c)); } -int Fl_Input_::wordboundary(int i) const { - if (i<=0 || i>=size()) return 1; - return isword(index(i-1)) != isword(index(i)); +int Fl_Input_::word_end(int i) const { + if (type() == FL_SECRET_INPUT) return size(); + //while (i < size() && !isword(index(i))) i++; + while (i < size() && isword(index(i))) i++; + return i; } -int Fl_Input_::lineboundary(int i) const { - if (i<=0 || i>=size()) return 1; +int Fl_Input_::word_start(int i) const { + if (type() == FL_SECRET_INPUT) return 0; +// if (i >= size() || !isword(index(i))) +// while (i > 0 && !isword(index(i-1))) i--; + while (i > 0 && isword(index(i-1))) i--; + return i; +} + +int Fl_Input_::line_end(int i) const { + if (type() != FL_MULTILINE_INPUT) return size(); +#ifdef WORDWRAP + // go to the start of the paragraph: + int j = i; + while (j > 0 && index(j-1) != '\n') j--; + // now measure lines until we get past i, end of that line is real eol: + wordwrap = w()-Fl::box_dw(box())-6; + setfont(); + for (const char* p=value()+j; ;) { + char buf[MAXBUF]; + p = expand(p, buf); + if (p-value() >= i) return p-value(); + p++; + } +#else + while (i < size() && index(i) != '\n') i++; + return i; +#endif +} + +int Fl_Input_::line_start(int i) const { if (type() != FL_MULTILINE_INPUT) return 0; - return index(i-1) == '\n' || index(i) == '\n'; + int j = i; + while (j > 0 && index(j-1) != '\n') j--; +#ifdef WORDWRAP + // now measure lines until we get past i, start of that line is real eol: + wordwrap = w()-Fl::box_dw(box())-6; + setfont(); + for (const char* p=value()+j; ;) { + char buf[MAXBUF]; + const char* e = expand(p, buf); + if (e-value() >= i) return p-value(); + p = e+1; + } +#else + return j; +#endif } void Fl_Input_::handle_mouse(int X, int Y, @@ -350,9 +392,8 @@ void Fl_Input_::handle_mouse(int X, int Y, for (p=value();; ) { e = expand(p, buf); theline--; if (theline < 0) break; - if (*e == '\n' || *e == ' ') e++; - p = e; if (e >= value_+size_) break; + p = e+1; } const char *l, *r, *t; double f0 = Fl::event_x()-X+xscroll_; for (l = p, r = e; l1 || type()==FL_SECRET_INPUT) { - while (!lineboundary(newpos)) newpos++; - while (!lineboundary(newmark)) newmark--; + if (Fl::event_clicks() > 1) { + newpos = line_end(newpos); + newmark = line_start(newmark); } else { - while (!wordboundary(newpos)) newpos++; - while (!wordboundary(newmark)) newmark--; + newpos = word_end(newpos); + newmark = word_start(newmark); } } else { - if (Fl::event_clicks()>1 || type()==FL_SECRET_INPUT) { - while (!lineboundary(newpos)) newpos--; + if (Fl::event_clicks() > 1) { + newpos = line_start(newpos); + newmark = line_end(newmark); } else { - while (!wordboundary(newpos)) newpos--; + newpos = word_start(newpos); + newmark = word_end(newmark); } } // if the multiple click does not increase the selection, revert @@ -429,16 +472,25 @@ int Fl_Input_::position(int p, int m) { } int Fl_Input_::up_down_position(int i, int keepmark) { - while (i > 0 && index(i-1) != '\n') i--; // go to start of line - double oldwid = 0.0; + // unlike before, i must be at the start of the line already! + setfont(); - while (index(i) && index(i)!='\n') { - double tt = oldwid + fl_width(index(i)); - if ((oldwid+tt)/2 >= up_down_pos) break; - oldwid = tt; - i++; +#ifdef WORDWRAP + if (type()==FL_MULTILINE_INPUT) + wordwrap = w()-Fl::box_dw(box())-6; + else wordwrap = 0; +#endif + char buf[MAXBUF]; + const char* p = value()+i; + const char* e = expand(p, buf); + const char *l, *r, *t; + for (l = p, r = e; l 0 && !isspace(index(b))) b--; +#endif + minimal_update(b); if (when()&FL_WHEN_CHANGED) do_callback(); else set_changed(); return 1; @@ -638,7 +700,7 @@ int Fl_Input_::handletext(int event, int X, int Y, int W, int H) { // strip trailing control characters and spaces before pasting: const char* t = Fl::event_text(); const char* e = t+Fl::event_length(); - if (type()!=FL_MULTILINE_INPUT) while (e > t && *(uchar*)(e-1) <= ' ') e--; + if (type() != FL_MULTILINE_INPUT) while (e > t && isspace(*(e-1))) e--; return replace(position(), mark(), t, e-t);} default: @@ -747,5 +809,5 @@ Fl_Input_::~Fl_Input_() { } // -// End of "$Id: Fl_Input_.cxx,v 1.21.2.7 2000/06/08 07:38:29 bill Exp $". +// End of "$Id: Fl_Input_.cxx,v 1.21.2.8 2000/06/20 07:56:09 bill Exp $". //