summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBill Spitzak <spitzak@gmail.com>2000-06-20 07:56:09 +0000
committerBill Spitzak <spitzak@gmail.com>2000-06-20 07:56:09 +0000
commit823b1f8460c82110ff0cd28c94684d413d955ad7 (patch)
tree98b5b99f6519772c84c7a7478f13a7dcc5cf2cc0 /src
parentf7e4caec2575619b6578b866bb59630bb513049c (diff)
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
Diffstat (limited to 'src')
-rw-r--r--src/Fl_Input.cxx37
-rw-r--r--src/Fl_Input_.cxx138
2 files changed, 111 insertions, 64 deletions
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<e && p < value_+size_) {*o++ = '*'; p++;}
} else while (o<e) {
#ifdef WORDWRAP
- if (wordwrap && (p >= 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; l<r; ) {
@@ -375,18 +416,20 @@ void Fl_Input_::handle_mouse(int X, int Y,
if (newpos < size()) newpos++;
else newmark--;
}
- if (Fl::event_clicks()>1 || 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<r; ) {
+ t = l+(r-l+1)/2;
+ int f = (int)expandpos(p, t, buf, 0);
+ if (f <= up_down_pos) l = t; else r = t-1;
}
- int j = position(i, keepmark ? mark_ : i);
+ int j = l-value();
+ j = position(j, keepmark ? mark_ : j);
was_up_down = 1;
return j;
}
@@ -536,6 +588,16 @@ int Fl_Input_::replace(int b, int e, const char* text, int ilen) {
undowidget = this;
mark_ = position_ = undoat = b+ilen;
+#ifdef WORDWRAP
+ // Insertions into the word at the end of the line will cause it to
+ // wrap to the next line, so we must indicate that the changes may start
+ // right after the whitespace before the current word. This will
+ // result in sub-optimal update when such wrapping does not happen
+ // but it is too hard to figure out for now...
+ if (type() == FL_MULTILINE_INPUT)
+ while (b > 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 $".
//