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
This commit is contained in:
parent
f7e4caec25
commit
823b1f8460
@ -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).
|
// Input base class header file for the Fast Light Tool Kit (FLTK).
|
||||||
//
|
//
|
||||||
@ -66,8 +66,10 @@ class Fl_Input_ : public Fl_Widget {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
FL_EXPORT int wordboundary(int i) const;
|
FL_EXPORT int word_start(int i) const;
|
||||||
FL_EXPORT int lineboundary(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 void drawtext(int, int, int, int);
|
||||||
FL_EXPORT int up_down_position(int, int keepmark=0);
|
FL_EXPORT int up_down_position(int, int keepmark=0);
|
||||||
FL_EXPORT void handle_mouse(int, int, int, int, int keepmark=0);
|
FL_EXPORT void handle_mouse(int, int, int, int, int keepmark=0);
|
||||||
@ -120,5 +122,5 @@ public:
|
|||||||
#endif
|
#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 $".
|
||||||
//
|
//
|
||||||
|
@ -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).
|
// Input widget for the Fast Light Tool Kit (FLTK).
|
||||||
//
|
//
|
||||||
@ -119,11 +119,7 @@ int Fl_Input::handle_key() {
|
|||||||
int i;
|
int i;
|
||||||
switch (ascii) {
|
switch (ascii) {
|
||||||
case ctrl('A'):
|
case ctrl('A'):
|
||||||
if (type() == FL_MULTILINE_INPUT)
|
return shift_position(line_start(position())) + NORMAL_INPUT_MOVE;
|
||||||
for (i=position(); i && index(i-1)!='\n'; i--) ;
|
|
||||||
else
|
|
||||||
i = 0;
|
|
||||||
return shift_position(i) + NORMAL_INPUT_MOVE;
|
|
||||||
case ctrl('B'):
|
case ctrl('B'):
|
||||||
return shift_position(position()-1) + NORMAL_INPUT_MOVE;
|
return shift_position(position()-1) + NORMAL_INPUT_MOVE;
|
||||||
case ctrl('C'): // copy
|
case ctrl('C'): // copy
|
||||||
@ -133,11 +129,7 @@ int Fl_Input::handle_key() {
|
|||||||
if (mark() != position()) return cut();
|
if (mark() != position()) return cut();
|
||||||
else return cut(1);
|
else return cut(1);
|
||||||
case ctrl('E'):
|
case ctrl('E'):
|
||||||
if (type() == FL_MULTILINE_INPUT)
|
return shift_position(line_end(position())) + NORMAL_INPUT_MOVE;
|
||||||
for (i=position(); index(i) && index(i)!='\n'; i++) ;
|
|
||||||
else
|
|
||||||
i = size();
|
|
||||||
return shift_position(i) + NORMAL_INPUT_MOVE;
|
|
||||||
case ctrl('F'):
|
case ctrl('F'):
|
||||||
return shift_position(position()+1) + NORMAL_INPUT_MOVE;
|
return shift_position(position()+1) + NORMAL_INPUT_MOVE;
|
||||||
case ctrl('H'):
|
case ctrl('H'):
|
||||||
@ -146,26 +138,19 @@ int Fl_Input::handle_key() {
|
|||||||
return 1;
|
return 1;
|
||||||
case ctrl('K'):
|
case ctrl('K'):
|
||||||
if (position()>=size()) return 0;
|
if (position()>=size()) return 0;
|
||||||
if (type() == FL_MULTILINE_INPUT) {
|
i = line_end(position());
|
||||||
if (index(position()) == '\n')
|
if (i == position() && i < size()) i++;
|
||||||
i = position() + 1;
|
|
||||||
else
|
|
||||||
for (i=position()+1; index(i) && index(i) != '\n'; i++);
|
|
||||||
} else
|
|
||||||
i = size();
|
|
||||||
cut(position(), i);
|
cut(position(), i);
|
||||||
return copy_cuts();
|
return copy_cuts();
|
||||||
case ctrl('N'):
|
case ctrl('N'):
|
||||||
if (type()!=FL_MULTILINE_INPUT) return 0;
|
i = line_end(position());
|
||||||
for (i=position(); index(i)!='\n'; i++)
|
if (i >= size()) return NORMAL_INPUT_MOVE;
|
||||||
if (!index(i)) return NORMAL_INPUT_MOVE;
|
|
||||||
shift_up_down_position(i+1);
|
shift_up_down_position(i+1);
|
||||||
return 1;
|
return 1;
|
||||||
case ctrl('P'):
|
case ctrl('P'):
|
||||||
if (type()!=FL_MULTILINE_INPUT) return 0;
|
i = line_start(position());
|
||||||
for (i = position(); i > 0 && index(i-1) != '\n'; i--) ;
|
|
||||||
if (!i) return NORMAL_INPUT_MOVE;
|
if (!i) return NORMAL_INPUT_MOVE;
|
||||||
shift_up_down_position(i-1);
|
shift_up_down_position(line_start(i-1));
|
||||||
return 1;
|
return 1;
|
||||||
case ctrl('U'):
|
case ctrl('U'):
|
||||||
return cut(0, size());
|
return cut(0, size());
|
||||||
@ -208,7 +193,7 @@ int Fl_Input::handle(int event) {
|
|||||||
up_down_position(0);
|
up_down_position(0);
|
||||||
break;
|
break;
|
||||||
case FL_Up:
|
case FL_Up:
|
||||||
up_down_position(size());
|
up_down_position(line_start(size()));
|
||||||
break;
|
break;
|
||||||
case FL_Tab:
|
case FL_Tab:
|
||||||
case 0xfe20: // XK_ISO_Left_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 $".
|
||||||
//
|
//
|
||||||
|
@ -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).
|
// 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.
|
// Wordwrap kludge. This works ok but is commented out because
|
||||||
// Really the whole multi-line-input should be moved to a seperate
|
// we want to move multi-line functionality to it's own subclass.
|
||||||
// (and much more complex) subclass. Single-line and multi-line
|
|
||||||
// input are really a *lot* different!
|
|
||||||
// To try the wordwrap define this:
|
// To try the wordwrap define this:
|
||||||
//#define WORDWRAP
|
//#define WORDWRAP
|
||||||
#ifdef WORDWRAP
|
#ifdef WORDWRAP
|
||||||
@ -60,17 +58,19 @@ const char* Fl_Input_::expand(const char* p, char* buf) const {
|
|||||||
const char* lastspace = p;
|
const char* lastspace = p;
|
||||||
char* lastspace_out = o;
|
char* lastspace_out = o;
|
||||||
int width_to_lastspace = 0;
|
int width_to_lastspace = 0;
|
||||||
|
int word_count = 0;
|
||||||
#endif
|
#endif
|
||||||
if (type()==FL_SECRET_INPUT) {
|
if (type()==FL_SECRET_INPUT) {
|
||||||
while (o<e && p < value_+size_) {*o++ = '*'; p++;}
|
while (o<e && p < value_+size_) {*o++ = '*'; p++;}
|
||||||
} else while (o<e) {
|
} else while (o<e) {
|
||||||
#ifdef WORDWRAP
|
#ifdef WORDWRAP
|
||||||
if (wordwrap && (p >= value_+size_ || *p==' ' || *p=='\n')) {
|
if (wordwrap && (p >= value_+size_ || isspace(*p))) {
|
||||||
width_to_lastspace += fl_width(lastspace, p-lastspace);
|
width_to_lastspace += (int)fl_width(lastspace_out, o-lastspace_out);
|
||||||
if (p > lastspace+1) {
|
if (p > lastspace+1) {
|
||||||
if (width_to_lastspace > wordwrap) {
|
if (word_count && width_to_lastspace > wordwrap) {
|
||||||
p = lastspace; o = lastspace_out; break;
|
p = lastspace; o = lastspace_out; break;
|
||||||
}
|
}
|
||||||
|
word_count++;
|
||||||
}
|
}
|
||||||
lastspace = p;
|
lastspace = p;
|
||||||
lastspace_out = o;
|
lastspace_out = o;
|
||||||
@ -216,8 +216,7 @@ void Fl_Input_::drawtext(int X, int Y, int W, int H) {
|
|||||||
}
|
}
|
||||||
lines++;
|
lines++;
|
||||||
if (e >= value_+size_) break;
|
if (e >= value_+size_) break;
|
||||||
if (*e == '\n' || *e == ' ') e++;
|
p = e+1;
|
||||||
p = e;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// adjust the scrolling:
|
// adjust the scrolling:
|
||||||
@ -296,8 +295,7 @@ void Fl_Input_::drawtext(int X, int Y, int W, int H) {
|
|||||||
CONTINUE:
|
CONTINUE:
|
||||||
ypos += height;
|
ypos += height;
|
||||||
if (e >= value_+size_) break;
|
if (e >= value_+size_) break;
|
||||||
if (*e == '\n' || *e == ' ') e++;
|
p = e+1;
|
||||||
p = e;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// for minimal update, erase all lines below last one if necessary:
|
// 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));
|
return (c&128 || isalnum(c) || strchr("#%&-/@\\_~", c));
|
||||||
}
|
}
|
||||||
|
|
||||||
int Fl_Input_::wordboundary(int i) const {
|
int Fl_Input_::word_end(int i) const {
|
||||||
if (i<=0 || i>=size()) return 1;
|
if (type() == FL_SECRET_INPUT) return size();
|
||||||
return isword(index(i-1)) != isword(index(i));
|
//while (i < size() && !isword(index(i))) i++;
|
||||||
|
while (i < size() && isword(index(i))) i++;
|
||||||
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Fl_Input_::lineboundary(int i) const {
|
int Fl_Input_::word_start(int i) const {
|
||||||
if (i<=0 || i>=size()) return 1;
|
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;
|
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,
|
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();; ) {
|
for (p=value();; ) {
|
||||||
e = expand(p, buf);
|
e = expand(p, buf);
|
||||||
theline--; if (theline < 0) break;
|
theline--; if (theline < 0) break;
|
||||||
if (*e == '\n' || *e == ' ') e++;
|
|
||||||
p = e;
|
|
||||||
if (e >= value_+size_) break;
|
if (e >= value_+size_) break;
|
||||||
|
p = e+1;
|
||||||
}
|
}
|
||||||
const char *l, *r, *t; double f0 = Fl::event_x()-X+xscroll_;
|
const char *l, *r, *t; double f0 = Fl::event_x()-X+xscroll_;
|
||||||
for (l = p, r = e; l<r; ) {
|
for (l = p, r = e; l<r; ) {
|
||||||
@ -375,18 +416,20 @@ void Fl_Input_::handle_mouse(int X, int Y,
|
|||||||
if (newpos < size()) newpos++;
|
if (newpos < size()) newpos++;
|
||||||
else newmark--;
|
else newmark--;
|
||||||
}
|
}
|
||||||
if (Fl::event_clicks()>1 || type()==FL_SECRET_INPUT) {
|
if (Fl::event_clicks() > 1) {
|
||||||
while (!lineboundary(newpos)) newpos++;
|
newpos = line_end(newpos);
|
||||||
while (!lineboundary(newmark)) newmark--;
|
newmark = line_start(newmark);
|
||||||
} else {
|
} else {
|
||||||
while (!wordboundary(newpos)) newpos++;
|
newpos = word_end(newpos);
|
||||||
while (!wordboundary(newmark)) newmark--;
|
newmark = word_start(newmark);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (Fl::event_clicks()>1 || type()==FL_SECRET_INPUT) {
|
if (Fl::event_clicks() > 1) {
|
||||||
while (!lineboundary(newpos)) newpos--;
|
newpos = line_start(newpos);
|
||||||
|
newmark = line_end(newmark);
|
||||||
} else {
|
} else {
|
||||||
while (!wordboundary(newpos)) newpos--;
|
newpos = word_start(newpos);
|
||||||
|
newmark = word_end(newmark);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if the multiple click does not increase the selection, revert
|
// 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) {
|
int Fl_Input_::up_down_position(int i, int keepmark) {
|
||||||
while (i > 0 && index(i-1) != '\n') i--; // go to start of line
|
// unlike before, i must be at the start of the line already!
|
||||||
double oldwid = 0.0;
|
|
||||||
setfont();
|
setfont();
|
||||||
while (index(i) && index(i)!='\n') {
|
#ifdef WORDWRAP
|
||||||
double tt = oldwid + fl_width(index(i));
|
if (type()==FL_MULTILINE_INPUT)
|
||||||
if ((oldwid+tt)/2 >= up_down_pos) break;
|
wordwrap = w()-Fl::box_dw(box())-6;
|
||||||
oldwid = tt;
|
else wordwrap = 0;
|
||||||
i++;
|
#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;
|
was_up_down = 1;
|
||||||
return j;
|
return j;
|
||||||
}
|
}
|
||||||
@ -536,6 +588,16 @@ int Fl_Input_::replace(int b, int e, const char* text, int ilen) {
|
|||||||
undowidget = this;
|
undowidget = this;
|
||||||
mark_ = position_ = undoat = b+ilen;
|
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);
|
minimal_update(b);
|
||||||
if (when()&FL_WHEN_CHANGED) do_callback(); else set_changed();
|
if (when()&FL_WHEN_CHANGED) do_callback(); else set_changed();
|
||||||
return 1;
|
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:
|
// strip trailing control characters and spaces before pasting:
|
||||||
const char* t = Fl::event_text();
|
const char* t = Fl::event_text();
|
||||||
const char* e = t+Fl::event_length();
|
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);}
|
return replace(position(), mark(), t, e-t);}
|
||||||
|
|
||||||
default:
|
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 $".
|
||||||
//
|
//
|
||||||
|
Loading…
Reference in New Issue
Block a user