|
fltk 1.3.0rc3
About: FLTK (Fast Light Tool Kit) is a cross-platform C++ GUI toolkit for UNIX/Linux (X11), Microsoft Windows, and MacOS X. Release candidate.
SfR Fresh Dox: fltk-1.3.0rc3-source.tar.gz ("inofficial" and yet experimental doxygen-generated source code documentation) ![]() |
00001 // 00002 // "$Id: Fl_Input.cxx 8115 2010-12-27 00:16:57Z greg.ercolano $" 00003 // 00004 // Input widget for the Fast Light Tool Kit (FLTK). 00005 // 00006 // Copyright 1998-2010 by Bill Spitzak and others. 00007 // 00008 // This library is free software; you can redistribute it and/or 00009 // modify it under the terms of the GNU Library General Public 00010 // License as published by the Free Software Foundation; either 00011 // version 2 of the License, or (at your option) any later version. 00012 // 00013 // This library is distributed in the hope that it will be useful, 00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 // Library General Public License for more details. 00017 // 00018 // You should have received a copy of the GNU Library General Public 00019 // License along with this library; if not, write to the Free Software 00020 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 00021 // USA. 00022 // 00023 // Please report all bugs and problems on the following page: 00024 // 00025 // http://www.fltk.org/str.php 00026 // 00027 00028 // This is the "user interface", it decodes user actions into what to 00029 // do to the text. See also Fl_Input_.cxx, where the text is actually 00030 // manipulated (and some ui, in particular the mouse, is done...). 00031 // In theory you can replace this code with another subclass to change 00032 // the keybindings. 00033 00034 #include <stdio.h> 00035 #include <stdlib.h> 00036 #include <FL/Fl.H> 00037 #include <FL/Fl_Window.H> 00038 #include <FL/Fl_Input.H> 00039 #include <FL/fl_draw.H> 00040 #include <FL/fl_ask.H> 00041 #include "flstring.h" 00042 00043 #ifdef HAVE_LOCALE_H 00044 # include <locale.h> 00045 #endif 00046 00047 00048 void Fl_Input::draw() { 00049 if (input_type() == FL_HIDDEN_INPUT) return; 00050 Fl_Boxtype b = box(); 00051 if (damage() & FL_DAMAGE_ALL) draw_box(b, color()); 00052 Fl_Input_::drawtext(x()+Fl::box_dx(b), y()+Fl::box_dy(b), 00053 w()-Fl::box_dw(b), h()-Fl::box_dh(b)); 00054 } 00055 00056 // kludge so shift causes selection to extend: 00057 int Fl_Input::shift_position(int p) { 00058 return position(p, Fl::event_state(FL_SHIFT) ? mark() : p); 00059 } 00060 00061 int Fl_Input::shift_up_down_position(int p) { 00062 return up_down_position(p, Fl::event_state(FL_SHIFT)); 00063 } 00064 00065 // Old text from FLTK 1.1 for reference: 00066 // If you define NORMAL_INPUT_MOVE as zero you will get the peculiar fltk 00067 // behavior where moving off the end of an input field will move the 00068 // cursor into the next field: 00069 // define it as 1 to prevent cursor movement from going to next field: 00070 // 00071 // Note: this has been replaced by Fl::option(Fl::OPTION_ARROW_FOCUS) 00072 // in FLTK 1.3. This option has "inverted" values: 00073 // 1 = Arrow keys move focus (previously 0) 00074 // 0 = Arrow keys don't move focus (previously 1) 00075 // Hence we define ... 00076 // 00077 #define NORMAL_INPUT_MOVE (Fl::option(Fl::OPTION_ARROW_FOCUS) ? 0 : 1) 00078 00079 #define ctrl(x) ((x)^0x40) 00080 00081 // List of characters that are legal in a floating point input field. 00082 // This text string is created at run-time to take the current locale 00083 // into account (for example, continental Europe uses a comma instead 00084 // of a decimal point). For back compatibility reasons, we always 00085 // allow the decimal point. 00086 #ifdef HAVE_LOCALECONV 00087 static const char *standard_fp_chars = ".eE+-"; 00088 static const char *legal_fp_chars = 0L; 00089 #else 00090 static const char *legal_fp_chars = ".eE+-"; 00091 #endif 00092 00093 // Move cursor up specified #lines 00094 // If OPTION_ARROW_FOCUS is disabled, return 1 to prevent focus navigation. 00095 // 00096 int Fl_Input::kf_lines_up(int repeat_num) { 00097 int i = position(); 00098 if (!line_start(i)) { 00099 //UNNEEDED if (input_type()==FL_MULTILINE_INPUT && !Fl::option(Fl::OPTION_ARROW_FOCUS)) return 1; 00100 return NORMAL_INPUT_MOVE; 00101 } 00102 while(repeat_num--) { 00103 i = line_start(i); 00104 if (!i) break; 00105 i--; 00106 } 00107 shift_up_down_position(line_start(i)); 00108 return 1; 00109 } 00110 00111 // Move cursor down specified #lines 00112 // If OPTION_ARROW_FOCUS is disabled, return 1 to prevent focus navigation. 00113 // 00114 int Fl_Input::kf_lines_down(int repeat_num) { 00115 int i = position(); 00116 if (line_end(i) >= size()) { 00117 //UNNEEDED if (input_type()==FL_MULTILINE_INPUT && !Fl::option(Fl::OPTION_ARROW_FOCUS)) return 1; 00118 return NORMAL_INPUT_MOVE; 00119 } 00120 while (repeat_num--) { 00121 i = line_end(i); 00122 if (i >= size()) break; 00123 i++; 00124 } 00125 shift_up_down_position(i); 00126 return 1; 00127 } 00128 00129 // Move up a page 00130 int Fl_Input::kf_page_up() { 00131 return kf_lines_up(linesPerPage()); 00132 } 00133 00134 // Move down a page 00135 int Fl_Input::kf_page_down() { 00136 return kf_lines_down(linesPerPage()); 00137 } 00138 00139 // Toggle insert mode 00140 int Fl_Input::kf_insert_toggle() { 00141 if (readonly()) { fl_beep(); return 1; } 00142 return 1; // \todo: needs insert mode 00143 } 00144 00145 // Delete word right 00146 int Fl_Input::kf_delete_word_right() { 00147 if (readonly()) { fl_beep(); return 1; } 00148 if (mark() != position()) return cut(); 00149 cut(position(), word_end(position())); 00150 return 1; 00151 } 00152 00153 // Delete word left 00154 int Fl_Input::kf_delete_word_left() { 00155 if (readonly()) { fl_beep(); return 1; } 00156 if (mark() != position()) return cut(); 00157 cut(word_start(position()), position()); 00158 return 1; 00159 } 00160 00161 // Delete to start of line 00162 int Fl_Input::kf_delete_sol() { 00163 if (readonly()) { fl_beep(); return 1; } 00164 if (mark() != position()) return cut(); 00165 cut(line_start(position()), position()); 00166 return 1; 00167 } 00168 00169 // Delete to end of line 00170 int Fl_Input::kf_delete_eol() { 00171 if (readonly()) { fl_beep(); return 1; } 00172 if (mark() != position()) return cut(); 00173 cut(position(), line_end(position())); 00174 return 1; 00175 } 00176 00177 int Fl_Input::kf_delete_char_right() { 00178 if (readonly()) { fl_beep(); return 1; } 00179 if (mark() != position()) return cut(); 00180 else return cut(1); 00181 } 00182 00183 int Fl_Input::kf_delete_char_left() { 00184 if (readonly()) { fl_beep(); return 1; } 00185 if (mark() != position()) cut(); 00186 else cut(-1); 00187 return 1; 00188 } 00189 00190 // Move cursor to start of line 00191 int Fl_Input::kf_move_sol() { 00192 return shift_position(line_start(position())) + NORMAL_INPUT_MOVE; 00193 } 00194 00195 // Move cursor to end of line 00196 int Fl_Input::kf_move_eol() { 00197 return shift_position(line_end(position())) + NORMAL_INPUT_MOVE; 00198 } 00199 00200 // Clear to end of line 00201 int Fl_Input::kf_clear_eol() { 00202 if (readonly()) { fl_beep(); return 1; } 00203 if (position()>=size()) return 0; 00204 int i = line_end(position()); 00205 if (i == position() && i < size()) i++; 00206 cut(position(), i); 00207 return copy_cuts(); 00208 } 00209 00210 // Move cursor one character to the left 00211 // If OPTION_ARROW_FOCUS is disabled, return 1 to prevent focus navigation. 00212 // 00213 int Fl_Input::kf_move_char_left() { 00214 int i = shift_position(position()-1) + NORMAL_INPUT_MOVE; 00215 return Fl::option(Fl::OPTION_ARROW_FOCUS) ? i : 1; 00216 } 00217 00218 // Move cursor one character to the right 00219 // If OPTION_ARROW_FOCUS is disabled, return 1 to prevent focus navigation. 00220 // 00221 int Fl_Input::kf_move_char_right() { 00222 int i = shift_position(position()+1) + NORMAL_INPUT_MOVE; 00223 return Fl::option(Fl::OPTION_ARROW_FOCUS) ? i : 1; 00224 } 00225 00226 // Move cursor word-left 00227 int Fl_Input::kf_move_word_left() { 00228 shift_position(word_start(position())); 00229 return 1; 00230 } 00231 00232 // Move cursor word-right 00233 int Fl_Input::kf_move_word_right() { 00234 shift_position(word_end(position())); 00235 return 1; 00236 } 00237 00238 // Move cursor up one line and to the start of line (paragraph up) 00239 int Fl_Input::kf_move_up_and_sol() { 00240 if (line_start(position())==position() && position()>0) 00241 return shift_position(line_start(position()-1)) + NORMAL_INPUT_MOVE; 00242 else 00243 return shift_position(line_start(position())) + NORMAL_INPUT_MOVE; 00244 } 00245 00246 // Move cursor down one line and to the end of line (paragraph down) 00247 int Fl_Input::kf_move_down_and_eol() { 00248 if (line_end(position())==position() && position()<size()) 00249 return shift_position(line_end(position()+1)) + NORMAL_INPUT_MOVE; 00250 else 00251 return shift_position(line_end(position())) + NORMAL_INPUT_MOVE; 00252 } 00253 00254 // Move to top of document 00255 int Fl_Input::kf_top() { 00256 shift_position(0); 00257 return 1; 00258 } 00259 00260 // Move to bottom of document 00261 int Fl_Input::kf_bottom() { 00262 shift_position(size()); 00263 return 1; 00264 } 00265 00266 // Select all text in the widget 00267 int Fl_Input::kf_select_all() { 00268 position(0,size()); 00269 return 1; 00270 } 00271 00272 // Undo. 00273 int Fl_Input::kf_undo() { 00274 if (readonly()) { fl_beep(); return 1; } 00275 return undo(); 00276 } 00277 00278 // Redo. (currently unimplemented.. toggles undo() instead) 00279 int Fl_Input::kf_redo() { 00280 if (readonly()) { fl_beep(); return 1; } 00281 return kf_undo(); // currently we don't support multilevel undo 00282 } 00283 00284 // Do a copy operation 00285 int Fl_Input::kf_copy() { 00286 return copy(1); 00287 } 00288 00289 // Do a paste operation 00290 int Fl_Input::kf_paste() { 00291 if (readonly()) { fl_beep(); return 1; } 00292 Fl::paste(*this, 1); 00293 return 1; 00294 } 00295 00296 // Do a cut with copy 00297 int Fl_Input::kf_copy_cut() { 00298 if (readonly()) { fl_beep(); return 1; } 00299 copy(1); 00300 return cut(); 00301 } 00302 00303 // Handle a keystroke. 00304 // Returns 1 if handled by us, 0 if not. 00305 // 00306 int Fl_Input::handle_key() { 00307 00308 char ascii = Fl::event_text()[0]; 00309 00310 int del; 00311 if (Fl::compose(del)) { 00312 00313 // Insert characters into numeric fields after checking for legality: 00314 if (input_type() == FL_FLOAT_INPUT || input_type() == FL_INT_INPUT) { 00315 Fl::compose_reset(); // ignore any foreign letters... 00316 00317 // initialize the list of legal characters inside a floating point number 00318 #ifdef HAVE_LOCALECONV 00319 if (!legal_fp_chars) { 00320 int len = strlen(standard_fp_chars); 00321 struct lconv *lc = localeconv(); 00322 if (lc) { 00323 if (lc->decimal_point) len += strlen(lc->decimal_point); 00324 if (lc->mon_decimal_point) len += strlen(lc->mon_decimal_point); 00325 if (lc->positive_sign) len += strlen(lc->positive_sign); 00326 if (lc->negative_sign) len += strlen(lc->negative_sign); 00327 } 00328 // the following line is not a true memory leak because the array is only 00329 // allocated once if required, and automatically freed when the program quits 00330 char *chars = (char*)malloc(len+1); 00331 legal_fp_chars = chars; 00332 strcpy(chars, standard_fp_chars); 00333 if (lc) { 00334 if (lc->decimal_point) strcat(chars, lc->decimal_point); 00335 if (lc->mon_decimal_point) strcat(chars, lc->mon_decimal_point); 00336 if (lc->positive_sign) strcat(chars, lc->positive_sign); 00337 if (lc->negative_sign) strcat(chars, lc->negative_sign); 00338 } 00339 } 00340 #endif // HAVE_LOCALECONV 00341 00342 // find the insert position 00343 int ip = position()<mark() ? position() : mark(); 00344 // This is complex to allow "0xff12" hex to be typed: 00345 if ( (!ip && (ascii == '+' || ascii == '-')) 00346 || (ascii >= '0' && ascii <= '9') 00347 || (ip==1 && index(0)=='0' && (ascii=='x' || ascii == 'X')) 00348 || (ip>1 && index(0)=='0' && (index(1)=='x'||index(1)=='X') 00349 && ((ascii>='A'&& ascii<='F') || (ascii>='a'&& ascii<='f'))) 00350 || (input_type()==FL_FLOAT_INPUT && ascii && strchr(legal_fp_chars, ascii))) 00351 { 00352 if (readonly()) fl_beep(); 00353 else replace(position(), mark(), &ascii, 1); 00354 } 00355 return 1; 00356 } 00357 00358 if (del || Fl::event_length()) { 00359 if (readonly()) fl_beep(); 00360 else replace(position(), del ? position()-del : mark(), 00361 Fl::event_text(), Fl::event_length()); 00362 } 00363 return 1; 00364 } 00365 00366 unsigned int mods = Fl::event_state() & (FL_META|FL_CTRL|FL_ALT); 00367 unsigned int shift = Fl::event_state() & FL_SHIFT; 00368 unsigned int multiline = (input_type() == FL_MULTILINE_INPUT) ? 1 : 0; 00369 // 00370 // The following lists apps that support these keypresses. 00371 // Prefixes: '!' indicates NOT supported, '?' indicates un-verified. 00372 // 00373 // HIG=Human Interface Guide, 00374 // TE=TextEdit.app, SA=Safari.app, WOX=MS Word/OSX -- OSX 10.4.x 00375 // NP=Notepad, WP=WordPad, WOW=MS Word/Windows -- WinXP 00376 // GE=gedit, KE=kedit -- Ubuntu8.04 00377 // OF=old FLTK behavior (<=1.1.10) 00378 // 00379 // Example: (NP,WP,!WO) means supported in notepad + wordpad, but NOT word. 00380 // 00381 switch (Fl::event_key()) { 00382 00383 case FL_Insert: 00384 // Note: Mac has no "Insert" key; it's the "Help" key. 00385 // This keypress is apparently not possible on macs. 00386 // 00387 if (mods==0 && shift) return kf_paste(); // Shift-Insert (WP,NP,WOW,GE,KE,OF) 00388 if (mods==0) return kf_insert_toggle(); // Insert (Standard) 00389 if (mods==FL_CTRL) return kf_copy(); // Ctrl-Insert (WP,NP,WOW,GE,KE,OF) 00390 return 0; // ignore other combos, pass to parent 00391 00392 case FL_Delete: { 00393 #ifdef __APPLE__ 00394 if (mods==0) return kf_delete_char_right(); // Delete (OSX-HIG,TE,SA,WOX) 00395 if (mods==FL_CTRL) return kf_delete_char_right(); // Ctrl-Delete (??? TE,!SA,!WOX) 00396 if (mods==FL_ALT) return kf_delete_word_right(); // Alt-Delete (OSX-HIG,TE,SA) 00397 return 0; // ignore other combos, pass to parent 00398 #else 00399 int selected = (position() != mark()) ? 1 : 0; 00400 if (mods==0 && shift && selected) 00401 return kf_copy_cut(); // Shift-Delete with selection (WP,NP,WOW,GE,KE,OF) 00402 if (mods==0 && shift && !selected) 00403 return kf_delete_char_right(); // Shift-Delete no selection (WP,NP,WOW,GE,KE,!OF) 00404 if (mods==0) return kf_delete_char_right(); // Delete (Standard) 00405 if (mods==FL_CTRL) return kf_delete_word_right(); // Ctrl-Delete (WP,!NP,WOW,GE,KE,!OF) 00406 return 0; // ignore other combos, pass to parent 00407 #endif 00408 } 00409 00410 case FL_Left: 00411 #ifdef __APPLE__ 00412 if (mods==0) return kf_move_char_left(); // Left (OSX-HIG) 00413 if (mods==FL_ALT) return kf_move_word_left(); // Alt-Left (OSX-HIG) 00414 if (mods==FL_META) return kf_move_sol(); // Meta-Left (OSX-HIG) 00415 if (mods==FL_CTRL) return kf_move_sol(); // Ctrl-Left (TE/SA) 00416 return 0; // ignore other combos, pass to parent 00417 #else 00418 if (mods==0) return kf_move_char_left(); // Left (WP,NP,WOW,GE,KE,OF) 00419 if (mods==FL_CTRL) return kf_move_word_left(); // Ctrl-Left (WP,NP,WOW,GE,KE,!OF) 00420 if (mods==FL_META) return kf_move_char_left(); // Meta-Left (WP,NP,?WOW,GE,KE) 00421 return 0; // ignore other combos, pass to parent 00422 #endif 00423 00424 case FL_Right: 00425 #ifdef __APPLE__ 00426 if (mods==0) return kf_move_char_right(); // Right (OSX-HIG) 00427 if (mods==FL_ALT) return kf_move_word_right(); // Alt-Right (OSX-HIG) 00428 if (mods==FL_META) return kf_move_eol(); // Meta-Right (OSX-HIG) 00429 if (mods==FL_CTRL) return kf_move_eol(); // Ctrl-Right (TE/SA) 00430 return 0; // ignore other combos, pass to parent 00431 #else 00432 if (mods==0) return kf_move_char_right(); // Right (WP,NP,WOW,GE,KE,OF) 00433 if (mods==FL_CTRL) return kf_move_word_right(); // Ctrl-Right (WP,NP,WOW,GE,KE,!OF) 00434 if (mods==FL_META) return kf_move_char_right(); // Meta-Right (WP,NP,?WOW,GE,KE,!OF) 00435 return 0; // ignore other combos, pass to parent 00436 #endif 00437 00438 case FL_Up: 00439 #ifdef __APPLE__ 00440 if (mods==0) return kf_lines_up(1); // Up (OSX-HIG) 00441 if (mods==FL_CTRL) return kf_page_up(); // Ctrl-Up (TE !HIG) 00442 if (mods==FL_ALT) return kf_move_up_and_sol(); // Alt-Up (OSX-HIG) 00443 if (mods==FL_META) return kf_top(); // Meta-Up (OSX-HIG) 00444 return 0; // ignore other combos, pass to parent 00445 #else 00446 if (mods==0) return kf_lines_up(1); // Up (WP,NP,WOW,GE,KE,OF) 00447 if (mods==FL_CTRL) return kf_move_up_and_sol(); // Ctrl-Up (WP,!NP,WOW,GE,!KE,OF) 00448 return 0; // ignore other combos, pass to parent 00449 #endif 00450 00451 case FL_Down: 00452 #ifdef __APPLE__ 00453 if (mods==0) return kf_lines_down(1); // Dn (OSX-HIG) 00454 if (mods==FL_CTRL) return kf_page_down(); // Ctrl-Dn (TE !HIG) 00455 if (mods==FL_ALT) return kf_move_down_and_eol(); // Alt-Dn (OSX-HIG) 00456 if (mods==FL_META) return kf_bottom(); // Meta-Dn (OSX-HIG) 00457 return 0; // ignore other combos, pass to parent 00458 #else 00459 if (mods==0) return kf_lines_down(1); // Dn (WP,NP,WOW,GE,KE,OF) 00460 if (mods==FL_CTRL) return kf_move_down_and_eol(); // Ctrl-Down (WP,!NP,WOW,GE,!KE,OF) 00461 return 0; // ignore other combos, pass to parent 00462 #endif 00463 00464 case FL_Page_Up: 00465 // Fl_Input has no scroll control, so instead we move the cursor by one page 00466 // OSX-HIG recommends Alt increase one semantic unit, Meta next higher.. 00467 #ifdef __APPLE__ 00468 if (mods==0) return kf_page_up(); // PgUp (OSX-HIG) 00469 if (mods==FL_ALT) return kf_page_up(); // Alt-PageUp (OSX-HIG) 00470 if (mods==FL_META) return kf_top(); // Meta-PageUp (OSX-HIG,!TE) 00471 return 0; // ignore other combos, pass to parent 00472 #else 00473 if (mods==0) return kf_page_up(); // PageUp (WP,NP,WOW,GE,KE) 00474 if (mods==FL_CTRL) return kf_page_up(); // Ctrl-PageUp (!WP,!NP,!WOW,!GE,KE,OF) 00475 if (mods==FL_ALT) return kf_page_up(); // Alt-PageUp (!WP,!NP,!WOW,!GE,KE,OF) 00476 return 0; // ignore other combos, pass to parent 00477 #endif 00478 00479 case FL_Page_Down: 00480 #ifdef __APPLE__ 00481 // Fl_Input has no scroll control, so instead we move the cursor by one page 00482 // OSX-HIG recommends Alt increase one semantic unit, Meta next higher.. 00483 if (mods==0) return kf_page_down(); // PgDn (OSX-HIG) 00484 if (mods==FL_ALT) return kf_page_down(); // Alt-PageDn (OSX-HIG) 00485 if (mods==FL_META) return kf_bottom(); // Meta-PageDn (OSX-HIG,!TE) 00486 return 0; // ignore other combos, pass to parent 00487 #else 00488 if (mods==0) return kf_page_down(); // PageDn (WP,NP,WOW,GE,KE) 00489 if (mods==FL_CTRL) return kf_page_down(); // Ctrl-PageDn (!WP,!NP,!WOW,!GE,KE,OF) 00490 if (mods==FL_ALT) return kf_page_down(); // Alt-PageDn (!WP,!NP,!WOW,!GE,KE,OF) 00491 return 0; // ignore other combos, pass to parent 00492 #endif 00493 00494 case FL_Home: 00495 #ifdef __APPLE__ 00496 if (mods==0) return kf_top(); // Home (OSX-HIG) 00497 if (mods==FL_ALT) return kf_top(); // Alt-Home (???) 00498 return 0; // ignore other combos, pass to parent 00499 #else 00500 if (mods==0) return kf_move_sol(); // Home (WP,NP,WOW,GE,KE,OF) 00501 if (mods==FL_CTRL) return kf_top(); // Ctrl-Home (WP,NP,WOW,GE,KE,OF) 00502 return 0; // ignore other combos, pass to parent 00503 #endif 00504 00505 case FL_End: 00506 #ifdef __APPLE__ 00507 if (mods==0) return kf_bottom(); // End (OSX-HIG) 00508 if (mods==FL_ALT) return kf_bottom(); // Alt-End (???) 00509 return 0; // ignore other combos, pass to parent 00510 #else 00511 if (mods==0) return kf_move_eol(); // End (WP,NP,WOW,GE,KE,OF) 00512 if (mods==FL_CTRL) return kf_bottom(); // Ctrl-End (WP,NP,WOW,GE,KE,OF) 00513 return 0; // ignore other combos, pass to parent 00514 #endif 00515 00516 case FL_BackSpace: 00517 #ifdef __APPLE__ 00518 if (mods==0) return kf_delete_char_left(); // Backspace (OSX-HIG) 00519 if (mods==FL_CTRL) return kf_delete_char_left(); // Ctrl-Backspace (TE/SA) 00520 if (mods==FL_ALT) return kf_delete_word_left(); // Alt-Backspace (OSX-HIG) 00521 if (mods==FL_META) return kf_delete_sol(); // Meta-Backspace (OSX-HIG,!TE) 00522 return 0; // ignore other combos, pass to parent 00523 #else 00524 if (mods==0) return kf_delete_char_left(); // Backspace (WP,NP,WOW,GE,KE,OF) 00525 if (mods==FL_CTRL) return kf_delete_word_left(); // Ctrl-Backspace (WP,!NP,WOW,GE,KE,!OF) 00526 return 0; // ignore other combos, pass to parent 00527 #endif 00528 00529 case FL_Enter: 00530 case FL_KP_Enter: 00531 if (when() & FL_WHEN_ENTER_KEY) { 00532 position(size(), 0); 00533 maybe_do_callback(); 00534 return 1; 00535 } else if (multiline && !readonly()) { 00536 return replace(position(), mark(), "\n", 1); 00537 } return 0; // reserved for shortcuts 00538 00539 case FL_Tab: 00540 // Handle special case for multiline input with 'old tab behavior'; 00541 // tab handled as a normal insertable character. 00542 // 00543 if (mods==0 && !shift // Tab? 00544 && !tab_nav() // old tab behavior enabled? 00545 && multiline) { // multiline input? 00546 break; // insert tab character 00547 } 00548 if (mods==0) return 0; // Tab, Shift-Tab? nav focus (Standard/OSX-HIG) 00549 return 0; // ignore other combos, pass to parent 00550 00551 case 'a': 00552 if (mods==FL_COMMAND) return kf_select_all(); // Ctrl-A, Mac:Meta-A (Standard/OSX-HIG) 00553 break; // handle other combos elsewhere 00554 case 'c': 00555 if (mods==FL_COMMAND) return kf_copy(); // Ctrl-C, Mac:Meta-C (Standard/OSX-HIG) 00556 break; // handle other combos elsewhere 00557 case 'v': 00558 if (mods==FL_COMMAND) return kf_paste(); // Ctrl-V, Mac:Meta-V (Standard/OSX-HIG) 00559 break; // handle other combos elsewhere 00560 case 'x': 00561 if (mods==FL_COMMAND) return kf_copy_cut(); // Ctrl-X, Mac:Meta-X (Standard/OSX-HIG) 00562 break; 00563 case 'z': 00564 if (mods==FL_COMMAND && !shift) return kf_undo(); // Ctrl-Z, Mac:Meta-Z (Standard/OSX-HIG) 00565 if (mods==FL_COMMAND && shift) return kf_redo(); // Shift-Ctrl-Z, Mac:Shift-Meta-Z (Standard/OSX-HIG) 00566 break; // handle other combos elsewhere 00567 } 00568 00569 switch (ascii) { 00570 case ctrl('H'): 00571 return kf_delete_char_left(); // Ctrl-H (!WP,!NP,!WOW,!WOX,TE,SA,GE,KE,OF) 00572 case ctrl('I'): // Ctrl-I (literal Tab) (!WP,NP,!WOW,!GE,KE,OF) 00573 case ctrl('J'): // Ctrl-J (literal Line Feed/Enter) (Standard) 00574 case ctrl('L'): // Ctrl-L (literal Form Feed) (Standard) 00575 case ctrl('M'): // Ctrl-M (literal Cr) (Standard) 00576 if (readonly()) { fl_beep(); return 1; } 00577 // insert a few selected control characters literally: 00578 if (input_type() != FL_FLOAT_INPUT && input_type() != FL_INT_INPUT) 00579 return replace(position(), mark(), &ascii, 1); 00580 break; 00581 } 00582 00583 return 0; // ignored 00584 } 00585 00586 int Fl_Input::handle(int event) { 00587 static int dnd_save_position, dnd_save_mark, drag_start = -1, newpos; 00588 static Fl_Widget *dnd_save_focus; 00589 switch (event) { 00590 case FL_FOCUS: 00591 switch (Fl::event_key()) { 00592 case FL_Right: 00593 position(0); 00594 break; 00595 case FL_Left: 00596 position(size()); 00597 break; 00598 case FL_Down: 00599 up_down_position(0); 00600 break; 00601 case FL_Up: 00602 up_down_position(line_start(size())); 00603 break; 00604 case FL_Tab: 00605 position(size(),0); 00606 break; 00607 default: 00608 position(position(),mark());// turns off the saved up/down arrow position 00609 break; 00610 } 00611 break; 00612 00613 case FL_KEYBOARD: 00614 // Handle special case for multiline input with 'old tab behavior' 00615 // where tab is entered as a character: make sure user attempt to 'tab over' 00616 // widget doesn't destroy the field, replacing it with a tab character. 00617 // 00618 if (Fl::event_key() == FL_Tab // Tab key? 00619 && !Fl::event_state(FL_SHIFT) // no shift? 00620 && !tab_nav() // with tab navigation disabled? 00621 && input_type() == FL_MULTILINE_INPUT // with a multiline input? 00622 && (mark()==0 && position()==size())) { // while entire field selected? 00623 // Set cursor to the end of the selection... 00624 if (mark() > position()) 00625 position(mark()); 00626 else 00627 position(position()); 00628 return (1); 00629 } else { 00630 if (active_r() && window() && this == Fl::belowmouse()) 00631 window()->cursor(FL_CURSOR_NONE); 00632 return handle_key(); 00633 } 00634 //NOTREACHED 00635 00636 case FL_PUSH: 00637 if (Fl::dnd_text_ops()) { 00638 int oldpos = position(), oldmark = mark(); 00639 Fl_Boxtype b = box(); 00640 Fl_Input_::handle_mouse(x()+Fl::box_dx(b), y()+Fl::box_dy(b), 00641 w()-Fl::box_dw(b), h()-Fl::box_dh(b), 0); 00642 newpos = position(); 00643 position( oldpos, oldmark ); 00644 if (Fl::focus()==this && !Fl::event_state(FL_SHIFT) && input_type()!=FL_SECRET_INPUT && 00645 ( (newpos >= mark() && newpos < position()) || 00646 (newpos >= position() && newpos < mark()) ) ) { 00647 // user clicked in the selection, may be trying to drag 00648 drag_start = newpos; 00649 return 1; 00650 } 00651 drag_start = -1; 00652 } 00653 00654 if (Fl::focus() != this) { 00655 Fl::focus(this); 00656 handle(FL_FOCUS); 00657 } 00658 break; 00659 00660 case FL_DRAG: 00661 if (Fl::dnd_text_ops()) { 00662 if (drag_start >= 0) { 00663 if (Fl::event_is_click()) return 1; // debounce the mouse 00664 // save the position because sometimes we don't get DND_ENTER: 00665 dnd_save_position = position(); 00666 dnd_save_mark = mark(); 00667 // drag the data: 00668 copy(0); Fl::dnd(); 00669 return 1; 00670 } 00671 } 00672 break; 00673 00674 case FL_RELEASE: 00675 if (Fl::event_button() == 2) { 00676 Fl::event_is_click(0); // stop double click from picking a word 00677 Fl::paste(*this, 0); 00678 } else if (!Fl::event_is_click()) { 00679 // copy drag-selected text to the clipboard. 00680 copy(0); 00681 } else if (Fl::event_is_click() && drag_start >= 0) { 00682 // user clicked in the field and wants to reset the cursor position... 00683 position(drag_start, drag_start); 00684 drag_start = -1; 00685 } else if (Fl::event_clicks()) { 00686 // user double or triple clicked to select word or whole text 00687 copy(0); 00688 } 00689 00690 // For output widgets, do the callback so the app knows the user 00691 // did something with the mouse... 00692 if (readonly()) do_callback(); 00693 00694 return 1; 00695 00696 case FL_DND_ENTER: 00697 Fl::belowmouse(this); // send the leave events first 00698 dnd_save_position = position(); 00699 dnd_save_mark = mark(); 00700 dnd_save_focus = Fl::focus(); 00701 if (dnd_save_focus != this) { 00702 Fl::focus(this); 00703 handle(FL_FOCUS); 00704 } 00705 // fall through: 00706 case FL_DND_DRAG: 00707 //int p = mouse_position(X, Y, W, H); 00708 #if DND_OUT_XXXX 00709 if (Fl::focus()==this && (p>=dnd_save_position && p<=dnd_save_mark || 00710 p>=dnd_save_mark && p<=dnd_save_position)) { 00711 position(dnd_save_position, dnd_save_mark); 00712 return 0; 00713 } 00714 #endif 00715 { 00716 Fl_Boxtype b = box(); 00717 Fl_Input_::handle_mouse(x()+Fl::box_dx(b), y()+Fl::box_dy(b), 00718 w()-Fl::box_dw(b), h()-Fl::box_dh(b), 0); 00719 } 00720 return 1; 00721 00722 case FL_DND_LEAVE: 00723 position(dnd_save_position, dnd_save_mark); 00724 #if DND_OUT_XXXX 00725 if (!focused()) 00726 #endif 00727 if (dnd_save_focus != this) { 00728 Fl::focus(dnd_save_focus); 00729 handle(FL_UNFOCUS); 00730 } 00731 #if !(defined(__APPLE__) || defined(WIN32)) 00732 Fl::first_window()->cursor(FL_CURSOR_MOVE); 00733 #endif 00734 return 1; 00735 00736 case FL_DND_RELEASE: 00737 take_focus(); 00738 return 1; 00739 00740 /* TODO: this will scroll the area, but stop if the cursor would become invisible. 00741 That clipping happens in drawtext(). Do we change the clipping or should 00742 we move the cursor (ouch)? 00743 case FL_MOUSEWHEEL: 00744 if (Fl::e_dy > 0) { 00745 yscroll( yscroll() - Fl::e_dy*15 ); 00746 } else if (Fl::e_dy < 0) { 00747 yscroll( yscroll() - Fl::e_dy*15 ); 00748 } 00749 return 1; 00750 */ 00751 } 00752 Fl_Boxtype b = box(); 00753 return Fl_Input_::handletext(event, 00754 x()+Fl::box_dx(b), y()+Fl::box_dy(b), 00755 w()-Fl::box_dw(b), h()-Fl::box_dh(b)); 00756 } 00757 00762 Fl_Input::Fl_Input(int X, int Y, int W, int H, const char *l) 00763 : Fl_Input_(X, Y, W, H, l) { 00764 } 00765 00766 // 00767 // End of "$Id: Fl_Input.cxx 8115 2010-12-27 00:16:57Z greg.ercolano $". 00768 //