summaryrefslogtreecommitdiff
path: root/src/Fl_Input.cxx
diff options
context:
space:
mode:
authorGreg Ercolano <erco@seriss.com>2010-12-20 06:42:38 +0000
committerGreg Ercolano <erco@seriss.com>2010-12-20 06:42:38 +0000
commitdf6de286e7421062372c468b6dca426c254ef379 (patch)
treecd2082dd898c5e3c507aff71dfd6bbc6bf559610 /src/Fl_Input.cxx
parent31f6505cb313c4448ccffef08e2d281ebe7c95d0 (diff)
Removed emacs shortcuts from Fl_Input,
conformed Fl_Input keystrokes to native environment (much research went into this, citations included). Tested editing functions on all three platforms. Doxygen docs updated. git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@8067 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'src/Fl_Input.cxx')
-rw-r--r--src/Fl_Input.cxx676
1 files changed, 383 insertions, 293 deletions
diff --git a/src/Fl_Input.cxx b/src/Fl_Input.cxx
index aee5f0510..b0d656e2c 100644
--- a/src/Fl_Input.cxx
+++ b/src/Fl_Input.cxx
@@ -90,12 +90,220 @@ static const char *legal_fp_chars = 0L;
static const char *legal_fp_chars = ".eE+-";
#endif
+// Move cursor up specified #lines
+// If OPTION_ARROW_FOCUS is disabled, return 1 to prevent focus navigation.
+//
+int Fl_Input::kf_lines_up(int repeat_num) {
+ int i = position();
+ if (!line_start(i)) {
+ //UNNEEDED if (input_type()==FL_MULTILINE_INPUT && !Fl::option(Fl::OPTION_ARROW_FOCUS)) return 1;
+ return NORMAL_INPUT_MOVE;
+ }
+ while(repeat_num--) {
+ i = line_start(i);
+ if (!i) break;
+ i--;
+ }
+ shift_up_down_position(line_start(i));
+ return 1;
+}
+
+// Move cursor down specified #lines
+// If OPTION_ARROW_FOCUS is disabled, return 1 to prevent focus navigation.
+//
+int Fl_Input::kf_lines_down(int repeat_num) {
+ int i = position();
+ if (line_end(i) >= size()) {
+ //UNNEEDED if (input_type()==FL_MULTILINE_INPUT && !Fl::option(Fl::OPTION_ARROW_FOCUS)) return 1;
+ return NORMAL_INPUT_MOVE;
+ }
+ while (repeat_num--) {
+ i = line_end(i);
+ if (i >= size()) break;
+ i++;
+ }
+ shift_up_down_position(i);
+ return 1;
+}
+
+// Move up a page
+int Fl_Input::kf_page_up() {
+ return kf_lines_up(linesPerPage());
+}
+
+// Move down a page
+int Fl_Input::kf_page_down() {
+ return kf_lines_down(linesPerPage());
+}
+
+// Toggle insert mode
+int Fl_Input::kf_insert_toggle() {
+ return 1; // \todo: needs insert mode
+}
+
+// Delete word right
+int Fl_Input::kf_delete_word_right() {
+ if (readonly()) { fl_beep(); return 1; }
+ if (mark() != position()) return cut();
+ cut(position(), word_end(position()));
+ return 1;
+}
+
+// Delete word left
+int Fl_Input::kf_delete_word_left() {
+ if (readonly()) { fl_beep(); return 1; }
+ if (mark() != position()) return cut();
+ cut(word_start(position()), position());
+ return 1;
+}
+
+// Delete to start of line
+int Fl_Input::kf_delete_sol() {
+ if (mark() != position()) return cut();
+ cut(line_start(position()), position());
+ return 1;
+}
+
+// Delete to end of line
+int Fl_Input::kf_delete_eol() {
+ if (readonly()) { fl_beep(); return 1; }
+ if (mark() != position()) return cut();
+ cut(position(), line_end(position()));
+ return 1;
+}
+
+int Fl_Input::kf_delete_char_right() {
+ if (readonly()) { fl_beep(); return 1; }
+ if (mark() != position()) return cut();
+ else return cut(1);
+}
+
+int Fl_Input::kf_delete_char_left() {
+ if (readonly()) { fl_beep(); return 1; }
+ if (mark() != position()) cut();
+ else cut(-1);
+ return 1;
+}
+
+// Move cursor to start of line
+int Fl_Input::kf_move_sol() {
+ return shift_position(line_start(position())) + NORMAL_INPUT_MOVE;
+}
+
+// Move cursor to end of line
+int Fl_Input::kf_move_eol() {
+ return shift_position(line_end(position())) + NORMAL_INPUT_MOVE;
+}
+
+// Clear to end of line
+int Fl_Input::kf_clear_eol() {
+ if (readonly()) { fl_beep(); return 1; }
+ if (position()>=size()) return 0;
+ int i = line_end(position());
+ if (i == position() && i < size()) i++;
+ cut(position(), i);
+ return copy_cuts();
+}
+
+// Move cursor one character to the left
+// If OPTION_ARROW_FOCUS is disabled, return 1 to prevent focus navigation.
+//
+int Fl_Input::kf_move_char_left() {
+ int i = shift_position(position()-1) + NORMAL_INPUT_MOVE;
+ return Fl::option(Fl::OPTION_ARROW_FOCUS) ? i : 1;
+}
+
+// Move cursor one character to the right
+// If OPTION_ARROW_FOCUS is disabled, return 1 to prevent focus navigation.
+//
+int Fl_Input::kf_move_char_right() {
+ int i = shift_position(position()+1) + NORMAL_INPUT_MOVE;
+ return Fl::option(Fl::OPTION_ARROW_FOCUS) ? i : 1;
+}
+
+// Move cursor word-left
+int Fl_Input::kf_move_word_left() {
+ shift_position(word_start(position()));
+ return 1;
+}
+
+// Move cursor word-right
+int Fl_Input::kf_move_word_right() {
+ shift_position(word_end(position()));
+ return 1;
+}
+
+// Move cursor up one line and to the start of line (paragraph up)
+int Fl_Input::kf_move_up_and_sol() {
+ if (line_start(position())==position() && position()>0)
+ return shift_position(line_start(position()-1)) + NORMAL_INPUT_MOVE;
+ else
+ return shift_position(line_start(position())) + NORMAL_INPUT_MOVE;
+}
+
+// Move cursor down one line and to the end of line (paragraph down)
+int Fl_Input::kf_move_down_and_eol() {
+ if (line_end(position())==position() && position()<size())
+ return shift_position(line_end(position()+1)) + NORMAL_INPUT_MOVE;
+ else
+ return shift_position(line_end(position())) + NORMAL_INPUT_MOVE;
+}
+
+// Move to top of document
+int Fl_Input::kf_top() {
+ shift_position(0);
+ return 1;
+}
+
+// Move to bottom of document
+int Fl_Input::kf_bottom() {
+ shift_position(size());
+ return 1;
+}
+
+// Select all text in the widget
+int Fl_Input::kf_select_all() {
+ position(0,size());
+ return 1;
+}
+
+// Undo.
+int Fl_Input::kf_undo() {
+ if (readonly()) { fl_beep(); return 1; }
+ return undo();
+}
+
+// Redo. (currently unimplemented.. toggles undo() instead)
+int Fl_Input::kf_redo() {
+ return kf_undo(); // currently we don't support multilevel undo
+}
+
+// Do a copy operation
+int Fl_Input::kf_copy() {
+ return copy(1);
+}
+
+// Do a paste operation
+int Fl_Input::kf_paste() {
+ if (readonly()) { fl_beep(); return 1; }
+ Fl::paste(*this, 1);
+ return 1;
+}
+
+// Do a cut with copy
+int Fl_Input::kf_copy_cut() {
+ if (readonly()) { fl_beep(); return 1; }
+ copy(1);
+ return cut();
+}
+
+// Handle a keystroke.
+// Returns 1 if handled by us, 0 if not.
+//
int Fl_Input::handle_key() {
char ascii = Fl::event_text()[0];
- int repeat_num=1;
-
int del;
if (Fl::compose(del)) {
@@ -153,349 +361,223 @@ int Fl_Input::handle_key() {
}
unsigned int mods = Fl::event_state() & (FL_META|FL_CTRL|FL_ALT);
+ unsigned int shift = Fl::event_state() & FL_SHIFT;
+ unsigned int multiline = (input_type() == FL_MULTILINE_INPUT) ? 1 : 0;
+ //
+ // The following lists apps that support these keypresses.
+ // Prefixes: '!' indicates NOT supported, '?' indicates un-verified.
+ //
+ // HIG=Human Interface Guide,
+ // TE=TextEdit.app, SA=Safari.app, WOX=MS Word/OSX -- OSX 10.4.x
+ // NP=Notepad, WP=WordPad, WOW=MS Word/Windows -- WinXP
+ // GE=gedit, KE=kedit -- Ubuntu8.04
+ // OF=old FLTK behavior (<=1.1.10)
+ //
+ // Example: (NP,WP,!WO) means supported in notepad + wordpad, but NOT word.
+ //
switch (Fl::event_key()) {
+
case FL_Insert:
- if (Fl::event_state() & FL_CTRL) ascii = ctrl('C');
- else if (Fl::event_state() & FL_SHIFT) ascii = ctrl('V');
- break;
- case FL_Delete:
+ // Note: Mac has no "Insert" key; it's the "Help" key.
+ // This keypress is apparently not possible on macs.
+ //
+ if (mods==0 && shift) return kf_paste(); // Shift-Insert (WP,NP,WOW,GE,KE,OF)
+ if (mods==0) return kf_insert_toggle(); // Insert (Standard)
+ if (mods==FL_CTRL) return kf_copy(); // Ctrl-Insert (WP,NP,WOW,GE,KE,OF)
+ return 0; // ignore other combos, pass to parent
+
+ case FL_Delete: {
#ifdef __APPLE__
- if (mods==0 || mods==FL_CTRL) { // delete next char
- ascii = ctrl('D');
- } else if (mods==FL_ALT) { // delete next word
- if (mark() != position()) return cut();
- cut(position(), word_end(position()));
- return 1;
- } else if (mods==FL_META) { // delete to the end of the line
- if (mark() != position()) return cut();
- cut(position(), line_end(position()));
- return 1;
- } else return 1;
+ if (mods==0) return kf_delete_char_right(); // Delete (OSX-HIG,TE,SA,WOX)
+ if (mods==FL_CTRL) return kf_delete_char_right(); // Ctrl-Delete (??? TE,!SA,!WOX)
+ if (mods==FL_ALT) return kf_delete_word_right(); // Alt-Delete (OSX-HIG,TE,SA)
+ return 0; // ignore other combos, pass to parent
#else
- if (mods) return 1; // Alt-Del/Ctrl-Del/Meta-Del: do nothing
- if (Fl::event_state() & FL_SHIFT) {
- ascii = ctrl('X'); // Shift-Del -> ^X
- } else {
- ascii = ctrl('D'); // Del -> ^D
- }
+ int selected = (position() != mark()) ? 1 : 0;
+ if (mods==0 && shift && selected)
+ return kf_copy_cut(); // Shift-Delete with selection (WP,NP,WOW,GE,KE,OF)
+ if (mods==0 && shift && !selected)
+ return kf_delete_char_right(); // Shift-Delete no selection (WP,NP,WOW,GE,KE,!OF)
+ if (mods==0) return kf_delete_char_right(); // Delete (Standard)
+ if (mods==FL_CTRL) return kf_delete_word_right(); // Ctrl-Delete (WP,!NP,WOW,GE,KE,!OF)
+ return 0; // ignore other combos, pass to parent
#endif
- break;
+ }
+
case FL_Left:
#ifdef __APPLE__
- if (mods==0) { // char left
- ascii = ctrl('B');
- } else if (mods==FL_ALT) { // word left
- shift_position(word_start(position()));
- return 1;
- } else if (mods==FL_CTRL || mods==FL_META) { // start of line
- shift_position(line_start(position()));
- return 1;
- } else return 1;
+ if (mods==0) return kf_move_char_left(); // Left (OSX-HIG)
+ if (mods==FL_ALT) return kf_move_word_left(); // Alt-Left (OSX-HIG)
+ if (mods==FL_META) return kf_move_sol(); // Meta-Left (OSX-HIG)
+ if (mods==FL_CTRL) return kf_move_sol(); // Ctrl-Left (TE/SA)
+ return 1; // other combos absorb and ignore
#else
- if (mods==0) { // char left
- ascii = ctrl('B');
- } else if (mods==FL_CTRL) { // word left
- shift_position(word_start(position()));
- return 1;
- } else return 1;
+ if (mods==0) return kf_move_char_left(); // Left (WP,NP,WOW,GE,KE,OF)
+ if (mods==FL_CTRL) return kf_move_word_left(); // Ctrl-Left (WP,NP,WOW,GE,KE,!OF)
+ if (mods==FL_META) return kf_move_char_left(); // Meta-Left (WP,NP,?WOW,GE,KE)
+ return 1; // other combos absorb and ignore
#endif
- break;
+
case FL_Right:
#ifdef __APPLE__
- if (mods==0) { // char right
- ascii = ctrl('F');
- } else if (mods==FL_ALT) { // word right
- shift_position(word_end(position()));
- return 1;
- } else if (mods==FL_CTRL || mods==FL_META) { // end of line
- shift_position(line_end(position()));
- return 1;
- } else return 1;
+ if (mods==0) return kf_move_char_right(); // Right (OSX-HIG)
+ if (mods==FL_ALT) return kf_move_word_right(); // Alt-Right (OSX-HIG)
+ if (mods==FL_META) return kf_move_eol(); // Meta-Right (OSX-HIG)
+ if (mods==FL_CTRL) return kf_move_eol(); // Ctrl-Right (TE/SA)
+ return 1; // other combos absorb and ignore
#else
- if (mods==0) { // char right
- ascii = ctrl('F');
- } else if (mods==FL_CTRL) { // word right
- shift_position(word_end(position()));
- return 1;
- } else return 1;
-#endif // __APPLE__
- break;
- case FL_Page_Up:
+ if (mods==0) return kf_move_char_right(); // Right (WP,NP,WOW,GE,KE,OF)
+ if (mods==FL_CTRL) return kf_move_word_right(); // Ctrl-Right (WP,NP,WOW,GE,KE,!OF)
+ if (mods==FL_META) return kf_move_char_right(); // Meta-Right (WP,NP,?WOW,GE,KE,!OF)
+ return 1; // other combos absorb and ignore
+#endif
+
+ case FL_Up:
#ifdef __APPLE__
- if (mods==0) { // scroll text one page
- // OS X scrolls the view, but does not move the cursor
- // Fl_Input has no scroll control, so instead we move the cursor by one page
- repeat_num = linesPerPage();
- ascii = ctrl('P');
- } else if (mods==FL_ALT) { // move cursor one page
- repeat_num = linesPerPage();
- ascii = ctrl('P');
- } else return 1;
- break;
+ if (mods==0) return kf_lines_up(1); // Up (OSX-HIG)
+ if (mods==FL_CTRL) return kf_page_up(); // Ctrl-Up (TE !HIG)
+ if (mods==FL_ALT) return kf_move_up_and_sol(); // Alt-Up (OSX-HIG)
+ if (mods==FL_META) return kf_top(); // Meta-Up (OSX-HIG)
+ return 1; // other combos absorb and ignore
#else
- repeat_num = linesPerPage();
- // fall through
+ if (mods==0) return kf_lines_up(1); // Up (WP,NP,WOW,GE,KE,OF)
+ if (mods==FL_CTRL) return kf_move_up_and_sol(); // Ctrl-Up (WP,!NP,WOW,GE,!KE,OF)
+ return 1; // other combos absorb and ignore
#endif
- case FL_Up:
+
+ case FL_Down:
#ifdef __APPLE__
- if (mods==0) { // line up
- ascii = ctrl('P');
- } else if (mods==FL_CTRL) { // scroll text down one page
- // OS X scrolls the view, but does not move the cursor
- // Fl_Input has no scroll control, so instead we move the cursor by one page
- repeat_num = linesPerPage();
- ascii = ctrl('P');
- } else if (mods==FL_ALT) { // line start and up
- if (line_start(position())==position() && position()>0)
- return shift_position(line_start(position()-1)) + NORMAL_INPUT_MOVE;
- else
- return shift_position(line_start(position())) + NORMAL_INPUT_MOVE;
- } else if (mods==FL_META) { // start of document
- shift_position(0);
- return 1;
- } else return 1;
+ if (mods==0) return kf_lines_down(1); // Dn (OSX-HIG)
+ if (mods==FL_CTRL) return kf_page_down(); // Ctrl-Dn (TE !HIG)
+ if (mods==FL_ALT) return kf_move_down_and_eol(); // Alt-Dn (OSX-HIG)
+ if (mods==FL_META) return kf_bottom(); // Meta-Dn (OSX-HIG)
+ return 1; // other combos absorb and ignore
#else
- if (mods==0) { // line up
- ascii = ctrl('P');
- } else if (mods==FL_CTRL) { // scroll text down one line
- // Fl_Input has no scroll control, so instead we move the cursor by one page
- ascii = ctrl('P');
- } else return 1;
+ if (mods==0) return kf_lines_down(1); // Dn (WP,NP,WOW,GE,KE,OF)
+ if (mods==FL_CTRL) return kf_move_down_and_eol(); // Ctrl-Down (WP,!NP,WOW,GE,!KE,OF)
+ return 1; // other combos absorb and ignore
#endif
- break;
- case FL_Page_Down:
+
+ case FL_Page_Up:
+ // Fl_Input has no scroll control, so instead we move the cursor by one page
+ // OSX-HIG recommends Alt increase one semantic unit, Meta next higher..
#ifdef __APPLE__
- if (mods==0) { // scroll text one page
- // OS X scrolls the view, but does not move the cursor
- // Fl_Input has no scroll control, so instead we move the cursor by one page
- repeat_num = linesPerPage();
- ascii = ctrl('N');
- } else if (mods==FL_ALT) { // move cursor one page
- repeat_num = linesPerPage();
- ascii = ctrl('N');
- } else return 1;
- break;
+ if (mods==0) return kf_page_up(); // PgUp (OSX-HIG)
+ if (mods==FL_ALT) return kf_page_up(); // Alt-PageUp (OSX-HIG)
+ if (mods==FL_META) return kf_top(); // Meta-PageUp (OSX-HIG,!TE)
+ return 1; // other combos absorb and ignore
#else
- repeat_num = linesPerPage();
- // fall through
+ if (mods==0) return kf_page_up(); // PageUp (WP,NP,WOW,GE,KE)
+ if (mods==FL_CTRL) return kf_page_up(); // Ctrl-PageUp (!WP,!NP,!WOW,!GE,KE,OF)
+ if (mods==FL_ALT) return kf_page_up(); // Alt-PageUp (!WP,!NP,!WOW,!GE,KE,OF)
+ return 1; // other combos absorb and ignore
#endif
- case FL_Down:
+
+ case FL_Page_Down:
#ifdef __APPLE__
- if (mods==0) { // line down
- ascii = ctrl('N');
- } else if (mods==FL_CTRL) {
- // OS X scrolls the view, but does not move the cursor
- // Fl_Input has no scroll control, so instead we move the cursor by one page
- repeat_num = linesPerPage();
- ascii = ctrl('N');
- } else if (mods==FL_ALT) { // line end and down
- if (line_end(position())==position() && position()<size())
- return shift_position(line_end(position()+1)) + NORMAL_INPUT_MOVE;
- else
- return shift_position(line_end(position())) + NORMAL_INPUT_MOVE;
- } else if (mods==FL_META) { // end of document
- shift_position(size());
- return 1;
- } else return 1;
+ // Fl_Input has no scroll control, so instead we move the cursor by one page
+ // OSX-HIG recommends Alt increase one semantic unit, Meta next higher..
+ if (mods==0) return kf_page_down(); // PgDn (OSX-HIG)
+ if (mods==FL_ALT) return kf_page_down(); // Alt-PageDn (OSX-HIG)
+ if (mods==FL_META) return kf_bottom(); // Meta-PageDn (OSX-HIG,!TE)
+ return 1; // other combos absorb and ignore
#else
- if (mods==0) { // line down
- ascii = ctrl('N');
- } else if (mods==FL_CTRL) { // scroll text up one line
- // Fl_Input has no scroll control, so instead we move the cursor by one page
- ascii = ctrl('N');
- } else return 1;
+ if (mods==0) return kf_page_down(); // PageDn (WP,NP,WOW,GE,KE)
+ if (mods==FL_CTRL) return kf_page_down(); // Ctrl-PageDn (!WP,!NP,!WOW,!GE,KE,OF)
+ if (mods==FL_ALT) return kf_page_down(); // Alt-PageDn (!WP,!NP,!WOW,!GE,KE,OF)
+ return 1; // other combos absorb and ignore
#endif
- break;
+
case FL_Home:
#ifdef __APPLE__
- if (mods==0) { // scroll display to the top
- // OS X scrolls the view, but does not move the cursor
- // Fl_Input has no scroll control, so instead we move the cursor by one page
- shift_position(0);
- return 1;
- } else return 1;
+ if (mods==0) return kf_top(); // Home (OSX-HIG)
+ if (mods==FL_ALT) return kf_top(); // Alt-Home (???)
+ return 1; // other combos absorb and ignore
#else
- if (mods==0) {
- ascii = ctrl('A');
- } else if (mods==FL_CTRL) {
- shift_position(0);
- return 1;
- }
+ if (mods==0) return kf_move_sol(); // Home (WP,NP,WOW,GE,KE,OF)
+ if (mods==FL_CTRL) return kf_top(); // Ctrl-Home (WP,NP,WOW,GE,KE,OF)
+ return 1; // other combos absorb and ignore
#endif
- break;
+
case FL_End:
#ifdef __APPLE__
- if (mods==0) { // scroll display to the bottom
- // OS X scrolls the view, but does not move the cursor
- // Fl_Input has no scroll control, so instead we move the cursor by one page
- shift_position(size());
- return 1;
- } else return 1;
+ if (mods==0) return kf_bottom(); // End (OSX-HIG)
+ if (mods==FL_ALT) return kf_bottom(); // Alt-End (???)
+ return 1; // other combos absorb and ignore
#else
- if (mods==0) {
- ascii = ctrl('E');
- } else if (mods==FL_CTRL) {
- shift_position(size());
- return 1;
- } else return 1;
+ if (mods==0) return kf_move_eol(); // End (WP,NP,WOW,GE,KE,OF)
+ if (mods==FL_CTRL) return kf_bottom(); // Ctrl-End (WP,NP,WOW,GE,KE,OF)
+ return 1; // other combos absorb and ignore
#endif
- break;
+
case FL_BackSpace:
#ifdef __APPLE__
- if (mods==0 || mods==FL_CTRL) { // delete previous char
- ascii = ctrl('H');
- } else if (mods==FL_ALT) { // delete previous word
- if (mark() != position()) return cut();
- cut(word_start(position()), position());
- return 1;
- } else if (mods==FL_META) { // delete to the beginning of the line
- if (mark() != position()) return cut();
- cut(line_start(position()), position());
- return 1;
- } else return 1;
+ if (mods==0) return kf_delete_char_left(); // Backspace (OSX-HIG)
+ if (mods==FL_CTRL) return kf_delete_char_left(); // Ctrl-Backspace (TE/SA)
+ if (mods==FL_ALT) return kf_delete_word_left(); // Alt-Backspace (OSX-HIG)
+ if (mods==FL_META) return kf_delete_sol(); // Meta-Backspace (OSX-HIG,!TE)
+ return 1; // other combos absorb and ignore
#else
- ascii = ctrl('H');
+ if (mods==0) return kf_delete_char_left(); // Backspace (WP,NP,WOW,GE,KE,OF)
+ if (mods==FL_CTRL) return kf_delete_word_left(); // Ctrl-Backspace (WP,!NP,WOW,GE,KE,!OF)
+ return 1; // other combos absorb and ignore
#endif
- break;
+
case FL_Enter:
case FL_KP_Enter:
if (when() & FL_WHEN_ENTER_KEY) {
position(size(), 0);
maybe_do_callback();
return 1;
- } else if (input_type() == FL_MULTILINE_INPUT && !readonly())
+ } else if (multiline && !readonly()) {
return replace(position(), mark(), "\n", 1);
- else
- return 0; // reserved for shortcuts
+ } return 0; // reserved for shortcuts
+
case FL_Tab:
- if (Fl::event_state(FL_CTRL|FL_SHIFT) || input_type()!=FL_MULTILINE_INPUT || readonly()) return 0;
- return replace(position(), mark(), &ascii, 1);
-#ifdef __APPLE__
- case 'c' :
- case 'v' :
- case 'x' :
- case 'z' :
- // printf("'%c' (0x%02x) pressed with%s%s%s%s\n", ascii, ascii,
- // Fl::event_state(FL_SHIFT) ? " FL_SHIFT" : "",
- // Fl::event_state(FL_CTRL) ? " FL_CTRL" : "",
- // Fl::event_state(FL_ALT) ? " FL_ALT" : "",
- // Fl::event_state(FL_META) ? " FL_META" : "");
- if (Fl::event_state(FL_META)) ascii -= 0x60;
- // printf("using '%c' (0x%02x)...\n", ascii, ascii);
+ // Handle special case for multiline input with 'old tab behavior';
+ // tab handled as a normal insertable character.
+ //
+ if (mods==0 && !shift // Tab?
+ //// PROPOSED && !tab_nav() // old tab behavior enabled?
+ && multiline) { // multiline input?
+ break; // insert tab character
+ }
+ if (mods==0) return 0; // Tab, Shift-Tab? nav focus (Standard/OSX-HIG)
+ return 0; // ignore other combos, pass to parent
+
+ case 'a':
+ if (mods==FL_COMMAND) return kf_select_all(); // Ctrl-A, Mac:Meta-A (Standard/OSX-HIG)
+ break; // handle other combos elsewhere
+ case 'c':
+ if (mods==FL_COMMAND) return kf_copy(); // Ctrl-C, Mac:Meta-C (Standard/OSX-HIG)
+ break; // handle other combos elsewhere
+ case 'v':
+ if (mods==FL_COMMAND) return kf_paste(); // Ctrl-V, Mac:Meta-V (Standard/OSX-HIG)
+ break; // handle other combos elsewhere
+ case 'x':
+ if (mods==FL_COMMAND) return kf_copy_cut(); // Ctrl-X, Mac:Meta-X (Standard/OSX-HIG)
break;
-#endif // __APPLE__
+ case 'z':
+ if (mods==FL_COMMAND && !shift) return kf_undo(); // Ctrl-Z, Mac:Meta-Z (Standard/OSX-HIG)
+ if (mods==FL_COMMAND && shift) return kf_redo(); // Shift-Ctrl-Z, Mac:Shift-Meta-Z (Standard/OSX-HIG)
+ break; // handle other combos elsewhere
}
- int i;
switch (ascii) {
- case ctrl('A'): // go to the beginning of the current line
- return shift_position(line_start(position())) + NORMAL_INPUT_MOVE;
- case ctrl('B'): // go one character backward
- i = shift_position(position()-1) + NORMAL_INPUT_MOVE;
- return Fl::option(Fl::OPTION_ARROW_FOCUS) ? i : 1;
- case ctrl('C'): // copy
- return copy(1);
- case ctrl('D'): // cut the next character
- case ctrl('?'):
- if (readonly()) {
- fl_beep();
- return 1;
- }
- if (mark() != position()) return cut();
- else return cut(1);
- case ctrl('E'): // go to the end of the line
- return shift_position(line_end(position())) + NORMAL_INPUT_MOVE;
- case ctrl('F'): // go to the next character
- i = shift_position(position()+1) + NORMAL_INPUT_MOVE;
- return Fl::option(Fl::OPTION_ARROW_FOCUS) ? i : 1;
- case ctrl('H'): // cut the previous character
- if (readonly()) {
- fl_beep();
- return 1;
- }
- if (mark() != position()) cut();
- else cut(-1);
- return 1;
- case ctrl('K'): // cut to the end of the line
- if (readonly()) {
- fl_beep();
- return 1;
- }
- if (position()>=size()) return 0;
- i = line_end(position());
- if (i == position() && i < size()) i++;
- cut(position(), i);
- return copy_cuts();
- case ctrl('N'): // go down one line
- i = position();
- if (line_end(i) >= size()) {
- if (input_type()==FL_MULTILINE_INPUT && !Fl::option(Fl::OPTION_ARROW_FOCUS)) return 1;
- return NORMAL_INPUT_MOVE;
- }
- while (repeat_num--) {
- i = line_end(i);
- if (i >= size()) break;
- i++;
- }
- shift_up_down_position(i);
- return 1;
- case ctrl('P'): // go up one line
- i = position();
- if (!line_start(i)) {
- if (input_type()==FL_MULTILINE_INPUT && !Fl::option(Fl::OPTION_ARROW_FOCUS)) return 1;
- return NORMAL_INPUT_MOVE;
- }
- while(repeat_num--) {
- i = line_start(i);
- if (!i) break;
- i--;
- }
- shift_up_down_position(line_start(i));
- return 1;
- case ctrl('U'): // clear the whole document?
- if (readonly()) {
- fl_beep();
- return 1;
- }
- return cut(0, size());
- case ctrl('V'): // paste text
- case ctrl('Y'):
- if (readonly()) {
- fl_beep();
- return 1;
- }
- Fl::paste(*this, 1);
- return 1;
- case ctrl('X'): // cut the selected text
- case ctrl('W'):
- if (readonly()) {
- fl_beep();
- return 1;
- }
- copy(1);
- return cut();
- case ctrl('Z'): // undo
- case ctrl('_'):
- if (readonly()) {
- fl_beep();
- return 1;
- }
- return undo();
- case ctrl('I'): // insert literal
- case ctrl('J'):
- case ctrl('L'):
- case ctrl('M'):
- if (readonly()) {
- fl_beep();
- return 1;
- }
+ case ctrl('H'):
+ return kf_delete_char_left(); // Ctrl-H (!WP,!NP,!WOW,!WOX,TE,SA,GE,KE,OF)
+ case ctrl('I'): // Ctrl-I (literal Tab) (!WP,NP,!WOW,!GE,KE,OF)
+ case ctrl('J'): // Ctrl-J (literal Line Feed/Enter) (Standard)
+ case ctrl('L'): // Ctrl-L (literal Form Feed) (Standard)
+ case ctrl('M'): // Ctrl-M (literal Cr) (Standard)
+ if (readonly()) { fl_beep(); return 1; }
// insert a few selected control characters literally:
if (input_type() != FL_FLOAT_INPUT && input_type() != FL_INT_INPUT)
return replace(position(), mark(), &ascii, 1);
break;
}
- return 0;
+ return 0; // ignored
}
int Fl_Input::handle(int event) {
@@ -526,8 +608,16 @@ int Fl_Input::handle(int event) {
break;
case FL_KEYBOARD:
- if (Fl::event_key() == FL_Tab && mark() != position()) {
- // Set the current cursor position to the end of the selection...
+ // Handle special case for multiline input with 'old tab behavior'
+ // where tab is entered as a character: make sure user attempt to 'tab over'
+ // widget doesn't destroy the field, replacing it with a tab character.
+ //
+ if (Fl::event_key() == FL_Tab // Tab key?
+ && !Fl::event_state(FL_SHIFT) // no shift?
+ //// PROPOSED && !tab_nav() // with tab navigation disabled?
+ && input_type() == FL_MULTILINE_INPUT // with a multiline input?
+ && (mark()==0 && position()==size())) { // while entire field selected?
+ // Set cursor to the end of the selection...
if (mark() > position())
position(mark());
else