📄 fl_input_.cxx
字号:
//// "$Id: Fl_Input_.cxx,v 1.1.1.1 2003/08/07 21:18:40 jasonk Exp $"//// Common input widget routines for the Fast Light Tool Kit (FLTK).//// Copyright 1998-1999 by Bill Spitzak and others.//// This library is free software; you can redistribute it and/or// modify it under the terms of the GNU Library General Public// License as published by the Free Software Foundation; either// version 2 of the License, or (at your option) any later version.//// This library is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU// Library General Public License for more details.//// You should have received a copy of the GNU Library General Public// License along with this library; if not, write to the Free Software// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307// USA.//// Please report all bugs and problems to "fltk-bugs@easysw.com".//// This is the base class for Fl_Input. You can use it directly// if you are one of those people who like to define their own// set of editing keys. It may also be useful for adding scrollbars// to the input field.#include <FL/Fl.H>#include <FL/Fl_Input_.H>#include <FL/fl_draw.H>#include <math.h>#include <string.h>#include <stdlib.h>#include <ctype.h>#define MAXBUF 1024////////////////////////////////////////////////////////////////// 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!// To try the wordwrap define this://#define WORDWRAP//#ifdef WORDWRAPstatic int wordwrap; // width for wordwrapping, should be are to Fl_Input_.//#endif// Copy string p..e to the buffer, replacing characters with ^X and \nnn// as necessary. Truncate if necessary so the resulting string and// null terminator fits in a buffer of size n. Return new end pointer.const char* Fl_Input_::expand(const char* p, char* buf) const { char* o = buf; char* e = buf+(MAXBUF-4);//#ifdef WORDWRAP const char* lastspace = p; char* lastspace_out = o; int width_to_lastspace = 0;//#endif if (type()==FL_SECRET_INPUT) { while (o<e && p < value_+size_) {*o++ = '*'; p++;} } else while (o<e) {//#ifdef WORDWRAP if (ww_) { if (wordwrap && (p >= value_+size_ || *p==' ' || *p=='\n')) { width_to_lastspace += fl_width(lastspace, p-lastspace); if (p > lastspace+1) { if (width_to_lastspace > wordwrap) { p = lastspace; o = lastspace_out; break; } } lastspace = p; lastspace_out = o; } } // end of if//#endif if (p >= value_+size_) break; int c = *p++ & 255; if (c < ' ' || c == 127) { if (c=='\n' && type()==FL_MULTILINE_INPUT) {p--; break;} if (c == '\t' && type()==FL_MULTILINE_INPUT) { for (c = (o-buf)%8; c<8 && o<e; c++) *o++ = ' '; } else { *o++ = '^'; *o++ = c ^ 0x40; } } else if (c >= 128 && c < 0xA0) { *o++ = '\\'; *o++ = (c>>6)+'0'; *o++ = ((c>>3)&7)+'0'; *o++ = (c&7)+'0'; } else if (c == 0xA0) { // nbsp *o++ = ' '; } else { *o++ = c; } } *o = 0; return p;}// After filling in such a buffer, find the width to edouble Fl_Input_::expandpos( const char* p, // real string const char* e, // pointer into real string const char* buf, // conversion of real string by expand() int* returnn // return offset into buf here) const { int n = 0; if (type()==FL_SECRET_INPUT) n = e-p; else while (p<e) { int c = *p++ & 255; if (c < ' ' || c == 127) { if (c == '\t' && type()==FL_MULTILINE_INPUT) n += 8-(n%8); else n += 2; } else if (c >= 128 && c < 0xA0) { n += 4; } else { n++; } } if (returnn) *returnn = n; return fl_width(buf, n);}////////////////////////////////////////////////////////////////// minimal update:// Characters from mu_p to end of widget are redrawn.// If erase_cursor_only, small part at mu_p is redrawn.// Right now minimal update just keeps unchanged characters from// being erased, so they don't blink.void Fl_Input_::minimal_update(int p) { if (damage() & FL_DAMAGE_ALL) return; // don't waste time if it won't be done if (damage() & FL_DAMAGE_EXPOSE) { if (p < mu_p) mu_p = p; } else { mu_p = p; } damage(FL_DAMAGE_EXPOSE); erase_cursor_only = 0;}void Fl_Input_::minimal_update(int p, int q) { if (q < p) p = q; minimal_update(p);}////////////////////////////////////////////////////////////////static double up_down_pos;static int was_up_down;void Fl_Input_::setfont() const { fl_font(textfont(), textsize());}void Fl_Input_::drawtext(int X, int Y, int W, int H) {#ifdef PDA X += 1; Y += 1; W -= 2; H -= 2;#endif int do_mu = !(damage()&FL_DAMAGE_ALL); if (Fl::focus()!=this && !size()) { if (do_mu) { // we have to erase it if cursor was there fl_color(color()); fl_rectf(X, Y, W, H); } return; } int selstart, selend; if (Fl::focus()!=this && /*Fl::selection_owner()!=this &&*/ Fl::pushed()!=this) selstart = selend = 0; else if (position() <= mark()) { selstart = position(); selend = mark(); } else { selend = position(); selstart = mark(); } setfont();//#ifdef WORDWRAP if (ww_) if (type()==FL_MULTILINE_INPUT) wordwrap = W; else wordwrap = 0;//#endif const char *p, *e; char buf[MAXBUF]; // count how many lines and put the last one into the buffer: // And figure out where the cursor is: int height = fl_height(); int lines; int curx, cury; for (p=value(), curx=cury=lines=0; ;) { e = expand(p, buf); if (position() >= p-value() && position() <= e-value()) { curx = int(expandpos(p, value()+position(), buf, 0)+.5); if (Fl::focus()==this && !was_up_down) up_down_pos = curx; cury = lines*height; if (Fl::focus()==this) { int fullw = int(expandpos(p, e, buf, 0)); if (curx > xscroll_+W-20) { xscroll_ = curx+20-W; if (xscroll_ > fullw-W+2) xscroll_ = fullw-W+2; mu_p = 0; erase_cursor_only = 0; } if (curx < xscroll_+20 && xscroll_) { if (fullw > W-2) xscroll_ = curx-20; else xscroll_ = 0; mu_p = 0; erase_cursor_only = 0; } if (xscroll_ < 0) xscroll_ = 0; } } lines++; if (e >= value_+size_) break; if (*e == '\n' || *e == ' ') e++; p = e; } // adjust the scrolling: if (type()==FL_MULTILINE_INPUT) { int newy = yscroll_; if (cury < newy) newy = cury; if (cury > newy+H-height) newy = cury-H+height; if (newy < -1) newy = -1; if (newy != yscroll_) {yscroll_ = newy; mu_p = 0; erase_cursor_only = 0;} } else { yscroll_ = -(H-height)/2; } fl_clip(X, Y, W, H); Fl_Color color = active_r() ? textcolor() : inactive(textcolor()); p = value(); // visit each line and draw it: int desc = height-fl_descent(); int ypos = -yscroll_; for (; ypos < H;) { // re-expand line unless it is the last one calculated above: if (lines>1) e = expand(p, buf); if (ypos <= -height) goto CONTINUE; // clipped off top if (do_mu) { // for minimal update: const char* pp = value()+mu_p; // pointer to where minimal update starts if (e >= pp && (!erase_cursor_only || p <= pp)) { // we must erase this // calculate area to erase: int x1 = -xscroll_; if (p < pp) x1 += int(expandpos(p, pp, buf, 0)); // erase it: fl_color(this->color()); fl_rectf(X+x1, Y+ypos, erase_cursor_only?2:W-x1, height); // it now draws entire line over it // this should not draw letters to left of erased area, but // that is nyi. } } // Draw selection area if required: if (selstart < selend && selstart <= e-value() && selend > p-value()) { const char* pp = value()+selstart; int x1 = -xscroll_; int offset1 = 0; if (pp > p) { fl_color(color); x1 += int(expandpos(p, pp, buf, &offset1)); fl_draw(buf, offset1, X-xscroll_, Y+ypos+desc); } pp = value()+selend; int x2 = W; int offset2; if (pp <= e) x2 = int(expandpos(p, pp, buf, &offset2))-xscroll_; else offset2 = strlen(buf); fl_color(selection_color()); fl_rectf(X+int(x1+.5), Y+ypos, int(x2-x1), height); fl_color(contrast(textcolor(), selection_color())); fl_draw(buf+offset1, offset2-offset1, X+x1, Y+ypos+desc); if (pp < e) { fl_color(color); fl_draw(buf+offset2, X+x2, Y+ypos+desc); } } else { // draw the cursor: if (Fl::focus() == this && selstart == selend && position() >= p-value() && position() <= e-value()) { fl_color(cursor_color()); fl_rectf(X+curx-xscroll_, Y+ypos, 2, height); } fl_color(color); fl_draw(buf, X-xscroll_, Y+ypos+desc); } CONTINUE: ypos += height; if (e >= value_+size_) break; if (*e == '\n' || *e == ' ') e++; p = e; } // for minimal update, erase all lines below last one if necessary: if (type()==FL_MULTILINE_INPUT && do_mu && ypos<H && (!erase_cursor_only || p <= value()+mu_p)) { if (ypos < 0) ypos = 0; fl_color(this->color()); fl_rectf(X, Y+ypos, W, H-ypos); } fl_pop_clip();}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_::lineboundary(int i) const { if (i<=0 || i>=size()) return 1; if (type() != FL_MULTILINE_INPUT) return 0; return index(i-1) == '\n' || index(i) == '\n';}#include <stdio.h>void Fl_Input_::handle_mouse(int X, int Y,#ifdef WORDWRAP int W,#else int /*W*/,#endif int /*H*/, int drag) { was_up_down = 0; if (!size()) return; setfont(); const char *p, *e; char buf[MAXBUF]; int theline = (type()==FL_MULTILINE_INPUT) ? (Fl::event_y()-Y+yscroll_)/fl_height() : 0; int newpos = 0;#ifdef WORDWRAP if (type()==FL_MULTILINE_INPUT) wordwrap = W; else wordwrap = 0;#endif for (p=value();; ) { e = expand(p, buf); theline--; if (theline < 0) break; if (*e == '\n' || *e == ' ') e++; p = e; if (e >= value_+size_) break; } const char *l, *r, *t; double f0 = Fl::event_x()-X+xscroll_; for (l = p, r = e; l<r; ) { double f; t = l+(r-l+1)/2; f = X-xscroll_+expandpos(p, t, buf, 0); if (f <= Fl::event_x()) {l = t; f0 = Fl::event_x()-f;} else r = t-1; } if (l < e) { // see if closer to character on right: double f1 = X-xscroll_+expandpos(p, l+1, buf, 0)-Fl::event_x(); if (f1 < f0) l = l+1; } newpos = l-value(); int newmark = drag ? mark() : newpos; if (Fl::event_clicks()) { if (newpos >= newmark) { if (newpos == newmark) { if (newpos < size()) newpos++; else newmark--;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -