fltk  1.3.5-source
About: FLTK (Fast Light Tool Kit) is a cross-platform C++ GUI toolkit for UNIX/Linux (X11), Microsoft Windows, and MacOS X.
  Fossies Dox: fltk-1.3.5-source.tar.bz2  ("inofficial" and yet experimental doxygen-generated source code documentation)  

fl_shortcut.cxx
Go to the documentation of this file.
1 //
2 // "$Id$"
3 //
4 // Shortcut support routines for the Fast Light Tool Kit (FLTK).
5 //
6 // Copyright 1998-2016 by Bill Spitzak and others.
7 //
8 // This library is free software. Distribution and use rights are outlined in
9 // the file "COPYING" which should have been included with this file. If this
10 // file is missing or damaged, see the license at:
11 //
12 // http://www.fltk.org/COPYING.php
13 //
14 // Please report all bugs and problems on the following page:
15 //
16 // http://www.fltk.org/str.php
17 //
18 
19 // Code to test and parse fltk shortcut numbers.
20 //
21 // A shortcut is a keysym or'd with shift flags. In the simplest
22 // sense a shortcut is matched if the shift state is exactly as
23 // given and the key returning that keysym is pressed.
24 //
25 // To make it easier to match some things it is more complex:
26 //
27 // Only FL_META, FL_ALT, FL_SHIFT, and FL_CTRL must be "off". A
28 // zero in the other shift flags indicates "don't care".
29 //
30 // It also checks against the first character of Fl::event_text(),
31 // and zero for FL_SHIFT means "don't care".
32 // This allows punctuation shortcuts like "#" to work (rather than
33 // calling it "shift+3" on a US keyboard)
34 
35 #include <FL/Fl.H>
36 #include <FL/Fl_Widget.H>
37 #include <FL/Fl_Button.H>
38 #include <FL/fl_draw.H>
39 #include <stdlib.h>
40 #include <ctype.h>
41 #include "flstring.h"
42 #if !defined(WIN32) && !defined(__APPLE__)
43 #include <FL/x.H>
44 #endif
45 
54 int Fl::test_shortcut(unsigned int shortcut) {
55  if (!shortcut) return 0;
56 
57  unsigned int v = shortcut & FL_KEY_MASK;
58  if (((unsigned)fl_tolower(v))!=v) {
59  shortcut |= FL_SHIFT;
60  }
61 
62  int shift = Fl::event_state();
63  // see if any required shift flags are off:
64  if ((shortcut&shift) != (shortcut&0x7fff0000)) return 0;
65  // record shift flags that are wrong:
66  int mismatch = (shortcut^shift)&0x7fff0000;
67  // these three must always be correct:
68  if (mismatch&(FL_META|FL_ALT|FL_CTRL)) return 0;
69 
70  unsigned int key = shortcut & FL_KEY_MASK;
71 
72  // if shift is also correct, check for exactly equal keysyms:
73  if (!(mismatch&(FL_SHIFT)) && key == (unsigned)Fl::event_key()) return 1;
74 
75  // try matching utf8, ignore shift:
76  unsigned int firstChar = fl_utf8decode(Fl::event_text(), Fl::event_text()+Fl::event_length(), 0);
77  if ( ! (FL_CAPS_LOCK&shift) && key==firstChar) return 1;
78 
79  // kludge so that Ctrl+'_' works (as opposed to Ctrl+'^_'):
80  if ((shift&FL_CTRL) && key >= 0x3f && key <= 0x5F
81  && firstChar==(key^0x40)) return 1; // firstChar should be within a-z
82  return 0;
83 }
84 
85 // This table must be in numeric order by fltk (X) keysym number:
86 struct Keyname {unsigned int key; const char* name;};
87 #if defined(WIN32)
88 static Keyname table[] = {
89  {' ', "Space"},
90  {FL_BackSpace, "Backspace"},
91  {FL_Tab, "Tab"},
92  {0xff0b/*XK_Clear*/, "Clear"},
93  {FL_Enter, "Enter"}, // X says "Enter"
94  {FL_Pause, "Pause"},
95  {FL_Scroll_Lock, "Scroll_Lock"},
96  {FL_Escape, "Escape"},
97  {FL_Home, "Home"},
98  {FL_Left, "Left"},
99  {FL_Up, "Up"},
100  {FL_Right, "Right"},
101  {FL_Down, "Down"},
102  {FL_Page_Up, "Page_Up"}, // X says "Prior"
103  {FL_Page_Down,"Page_Down"}, // X says "Next"
104  {FL_End, "End"},
105  {FL_Print, "Print"},
106  {FL_Insert, "Insert"},
107  {FL_Menu, "Menu"},
108  {FL_Num_Lock, "Num_Lock"},
109  {FL_KP_Enter, "KP_Enter"},
110  {FL_Shift_L, "Shift_L"},
111  {FL_Shift_R, "Shift_R"},
112  {FL_Control_L,"Control_L"},
113  {FL_Control_R,"Control_R"},
114  {FL_Caps_Lock,"Caps_Lock"},
115  {FL_Meta_L, "Meta_L"},
116  {FL_Meta_R, "Meta_R"},
117  {FL_Alt_L, "Alt_L"},
118  {FL_Alt_R, "Alt_R"},
119  {FL_Delete, "Delete"}
120 };
121 #elif defined(__APPLE__)
122 static Keyname table[] = {
123  // v - this column may contain UTF-8 characters
124  {' ', "Space"},
125  {FL_BackSpace,"\xe2\x8c\xab"}, // erase to the left
126  {FL_Tab, "\xe2\x87\xa5"}, // rightwards arrow to bar
127  {0xff0b, "\xe2\x8c\xa6"}, // erase to the right
128  {FL_Enter, "\xe2\x86\xa9"}, // leftwards arrow with hook
129  {FL_Pause, "Pause"},
130  {FL_Scroll_Lock, "Scroll_Lock"},
131  {FL_Escape, "\xe2\x90\x9b"},
132  {FL_Home, "\xe2\x86\x96"}, // north west arrow
133  {FL_Left, "\xe2\x86\x90"}, // leftwards arrow
134  {FL_Up, "\xe2\x86\x91"}, // upwards arrow
135  {FL_Right, "\xe2\x86\x92"}, // rightwards arrow
136  {FL_Down, "\xe2\x86\x93"}, // downwards arrow
137  {FL_Page_Up, "\xe2\x87\x9e"}, // upwards arrow with double stroke
138  {FL_Page_Down,"\xe2\x87\x9f"}, // downwards arrow with double stroke
139  {FL_End, "\xe2\x86\x98"}, // south east arrow
140  {FL_Print, "Print"},
141  {FL_Insert, "Insert"},
142  {FL_Menu, "Menu"},
143  {FL_Num_Lock, "Num_Lock"},
144  {FL_KP_Enter, "\xe2\x8c\xa4"}, // up arrow head between two horizontal bars
145  {FL_Shift_L, "Shift_L"},
146  {FL_Shift_R, "Shift_R"},
147  {FL_Control_L,"Control_L"},
148  {FL_Control_R,"Control_R"},
149  {FL_Caps_Lock,"\xe2\x87\xaa"}, // upwards white arrow from bar
150  {FL_Meta_L, "Meta_L"},
151  {FL_Meta_R, "Meta_R"},
152  {FL_Alt_L, "Alt_L"},
153  {FL_Alt_R, "Alt_R"},
154  {FL_Delete, "\xe2\x8c\xa7"} // x in a rectangle box
155 };
156 #endif
157 
199 const char* fl_shortcut_label(unsigned int shortcut) {
200  return fl_shortcut_label(shortcut, 0L);
201 }
202 
203 /*
204  This static function adds a modifier key name to a character
205  buffer and returns the pointer behind the modifier name and a
206  trailing '+' character.
207 
208  Exceptions:
209  (1) Last character = '\' : remove it, done (don't add '+')
210  (2) Last character = '+' : user added '+', don't add another one
211 
212  In case of buffer overflow the modifier key name is replaced with "..."
213  if that fits or not added at all. This should rarely (never) happen.
214 */
215 
216 static char *add_modifier_key(char *p, const char *end, const char *name) {
217  int ln = strlen(name);
218  if (p+ln > end) { // string too long
219  if (p+4 <= end) { // can replace with "..." ?
220  strcpy(p,"...");
221  p += 3;
222  } else
223  return p;
224  } else {
225  strcpy(p,name);
226  p += ln;
227  }
228  if (p[-1] == '\\') // remove (last) '\' character
229  p--;
230  else if (p[-1] == '+') // don't add another '+' character
231  {/*empty*/}
232  else // not a '\' or '+'
233  *p++ = '+'; // add a '+' character
234  return p;
235 }
236 
247 const char* fl_shortcut_label(unsigned int shortcut, const char **eom) {
248  static char buf[80];
249  char *p = buf;
250  char *end = &buf[sizeof(buf)-20]; // account for key name (max. ~10 + x)
251  if (eom) *eom = p;
252  if (!shortcut) {*p = 0; return buf;}
253  // fix upper case shortcuts
254  unsigned int key = shortcut & FL_KEY_MASK;
255  if (((unsigned)fl_tolower(key)) != key) {
256  shortcut |= FL_SHIFT;
257  }
258 
259  // Add modifier key names.
260  // Note: if necessary we could change the order here depending on the platform.
261  // However, as discussed in fltk.development, the order appears to be the
262  // same on all platforms, with exceptions in _some_ Linux applications.
263 
264  if (shortcut & FL_CTRL) {p = add_modifier_key(p, end, fl_local_ctrl);}
265  if (shortcut & FL_ALT) {p = add_modifier_key(p, end, fl_local_alt);}
266  if (shortcut & FL_SHIFT) {p = add_modifier_key(p, end, fl_local_shift);}
267  if (shortcut & FL_META) {p = add_modifier_key(p, end, fl_local_meta);}
268  if (eom) *eom = p;
269 
270  // add key name
271 #if defined(WIN32) || defined(__APPLE__) // if not X
272  if (key >= FL_F && key <= FL_F_Last) {
273  *p++ = 'F';
274  if (key > FL_F+9) *p++ = (key-FL_F)/10+'0';
275  *p++ = (key-FL_F)%10 + '0';
276  } else {
277  // binary search the table for a match:
278  int a = 0;
279  int b = sizeof(table)/sizeof(*table);
280  while (a < b) {
281  int c = (a+b)/2;
282  if (table[c].key == key) {
283  if (p > buf) {
284  strcpy(p,table[c].name);
285  return buf;
286  } else {
287  const char *sp = table[c].name;
288  if (eom) *eom = sp;
289  return sp;
290  }
291  }
292  if (table[c].key < key) a = c+1;
293  else b = c;
294  }
295  if (key >= FL_KP && key <= FL_KP_Last) {
296  // mark keypad keys with KP_ prefix
297  strcpy(p,"KP_"); p += 3;
298  *p++ = uchar(key & 127);
299  } else {
300  // if none found, use the keystroke as a match:
301  p += fl_utf8encode(fl_toupper(key), p);
302  }
303  }
304  *p = 0;
305  return buf;
306 #else
307  const char* q;
308  if (key == FL_Enter || key == '\r') q="Enter"; // don't use Xlib's "Return":
309  else if (key > 32 && key < 0x100) q = 0;
310  else q = XKeysymToString(key);
311  if (!q) {
312  p += fl_utf8encode(fl_toupper(key), p);
313  *p = 0;
314  return buf;
315  }
316  if (p > buf) {
317  strcpy(p,q);
318  return buf;
319  } else {
320  if (eom) *eom = q;
321  return q;
322  }
323 #endif
324 }
325 
326 // Emulation of XForms named shortcuts
396 unsigned int fl_old_shortcut(const char* s) {
397  if (!s || !*s) return 0;
398  if (s[1]==0 && strchr("@!",s[0])) return s[0]; // maintain legacy behavior for "!" and "@"
399  unsigned int n = 0;
400  if (*s == '#') {n |= FL_ALT; s++;}
401  if (*s == '+') {n |= FL_SHIFT; s++;}
402  if (*s == '^') {n |= FL_CTRL; s++;}
403  if (*s == '!') {n |= FL_META; s++;} // added in 1.3.3
404  if (*s == '@') {n |= FL_COMMAND; s++;} // added in 1.3.3
405  if (*s && s[1]) return n | (int)strtol(s,0,0); // allow 0xf00 to get any key
406  return n | *s;
407 }
408 
409 // Tests for &x shortcuts in button labels:
410 
423 unsigned int Fl_Widget::label_shortcut(const char *t) {
424  if (!t) return 0;
425  for (;;) {
426  if (*t==0) return 0;
427  if (*t=='&') {
428  unsigned int s = fl_utf8decode(t+1, 0, 0);
429  if (s==0) return 0;
430  else if (s==(unsigned int)'&') t++;
431  else return s;
432  }
433  t++;
434  }
435 }
436 
456 int Fl_Widget::test_shortcut(const char *t, const bool require_alt) {
457  if (!t) return 0;
458  // for menubars etc. shortcuts must work only if the Alt modifier is pressed
459  if (require_alt && Fl::event_state(FL_ALT)==0) return 0;
460  unsigned int c = fl_utf8decode(Fl::event_text(), Fl::event_text()+Fl::event_length(), 0);
461 #ifdef __APPLE__
462  // this line makes underline shortcuts work the same way they do on MSWindow
463  // and Linux.
464  if (c && Fl::event_state(FL_ALT))
465  c = Fl::event_key();
466 #endif
467  if (!c) return 0;
468  unsigned int ls = label_shortcut(t);
469  if (c == ls)
470  return 1;
471 #ifdef __APPLE__
472  // On OS X, we need to simulate the upper case keystroke as well
473  if (Fl::event_state(FL_ALT) && c<128 && isalpha(c) && (unsigned)toupper(c)==ls)
474  return 1;
475 #endif
476  return 0;
477 }
478 
495  if (!(flags()&SHORTCUT_LABEL)) return 0;
496  return test_shortcut(label());
497 }
498 
499 //
500 // End of "$Id$".
501 //
Fl_Widget.H
FL_Up
#define FL_Up
The up arrow key.
Definition: Enumerations.H:481
fl_old_shortcut
unsigned int fl_old_shortcut(const char *s)
Definition: fl_shortcut.cxx:396
FL_Shift_L
#define FL_Shift_L
The lefthand shift key.
Definition: Enumerations.H:497
FL_Enter
#define FL_Enter
The enter key.
Definition: Enumerations.H:471
Fl.H
buf
static char * buf
Definition: fl_encoding_mac_roman.cxx:76
Keyname::key
unsigned int key
Definition: fl_shortcut.cxx:86
FL_BackSpace
#define FL_BackSpace
The backspace key.
Definition: Enumerations.H:468
FL_META
#define FL_META
One of the meta/Windows keys is down.
Definition: Enumerations.H:563
fl_shortcut_label
const char * fl_shortcut_label(unsigned int shortcut)
Definition: fl_shortcut.cxx:199
Fl::event_state
static int event_state()
Definition: Fl.H:704
Keyname::name
const char * name
Definition: fl_shortcut.cxx:86
FL_SHIFT
#define FL_SHIFT
One of the shift keys is down.
Definition: Enumerations.H:557
FL_Page_Down
#define FL_Page_Down
The page-down key.
Definition: Enumerations.H:485
x.H
Fl::event_text
static const char * event_text()
Definition: Fl.H:792
fl_local_meta
const char * fl_local_meta
string pointer used in shortcuts, you can change it to another language
Definition: Fl.cxx:97
Keyname
Definition: fl_shortcut.cxx:86
FL_KP_Enter
#define FL_KP_Enter
The enter key on the keypad, same as Fl_KP+'\r'.
Definition: Enumerations.H:493
Fl::event_key
static int event_key()
Definition: Fl.H:723
b
long b
Definition: jpegint.h:397
key
int key
Definition: Fl_Text_Editor.cxx:91
FL_Print
#define FL_Print
The print (or print-screen) key.
Definition: Enumerations.H:487
FL_Page_Up
#define FL_Page_Up
The page-up key.
Definition: Enumerations.H:484
fl_local_shift
const char * fl_local_shift
string pointer used in shortcuts, you can change it to another language
Definition: Fl.cxx:98
FL_Down
#define FL_Down
The down arrow key.
Definition: Enumerations.H:483
fl_utf8decode
unsigned fl_utf8decode(const char *p, const char *end, int *len)
Definition: fl_utf.c:137
FL_CAPS_LOCK
#define FL_CAPS_LOCK
The caps lock is on.
Definition: Enumerations.H:558
fl_local_ctrl
const char * fl_local_ctrl
string pointer used in shortcuts, you can change it to another language
Definition: Fl.cxx:96
Fl::test_shortcut
static int test_shortcut(Fl_Shortcut)
Definition: fl_shortcut.cxx:54
FL_End
#define FL_End
The end key.
Definition: Enumerations.H:486
FL_Meta_R
#define FL_Meta_R
The right meta/Windows key.
Definition: Enumerations.H:503
p
static menustate * p
Definition: Fl_Menu.cxx:606
FL_Left
#define FL_Left
The left arrow key.
Definition: Enumerations.H:480
FL_Right
#define FL_Right
The right arrow key.
Definition: Enumerations.H:482
FL_Alt_R
#define FL_Alt_R
The right alt key.
Definition: Enumerations.H:505
FL_Tab
#define FL_Tab
The tab key.
Definition: Enumerations.H:469
FL_ALT
#define FL_ALT
One of the alt keys is down.
Definition: Enumerations.H:560
FL_Home
#define FL_Home
The home key.
Definition: Enumerations.H:479
fl_draw.H
utility header to pull drawing functions together
FL_Control_R
#define FL_Control_R
The righthand control key.
Definition: Enumerations.H:500
Fl_Widget::flags
unsigned int flags() const
Definition: Fl_Widget.H:147
FL_COMMAND
#define FL_COMMAND
An alias for FL_CTRL on WIN32 and X11, or FL_META on MacOS X.
Definition: Enumerations.H:580
FL_KP_Last
#define FL_KP_Last
The last keypad key; use to range-check keypad.
Definition: Enumerations.H:494
FL_Pause
#define FL_Pause
The pause key.
Definition: Enumerations.H:472
table
static symbol table[]
Definition: factory.cxx:1109
Fl_Widget::test_shortcut
int test_shortcut()
Definition: fl_shortcut.cxx:494
fl_local_alt
const char * fl_local_alt
string pointer used in shortcuts, you can change it to another language
Definition: Fl.cxx:95
FL_KEY_MASK
#define FL_KEY_MASK
All keys are 16 bit for now.
Definition: Enumerations.H:573
Fl::event_length
static int event_length()
Definition: Fl.H:799
Fl_Widget::label_shortcut
static unsigned int label_shortcut(const char *t)
Definition: fl_shortcut.cxx:423
FL_KP
#define FL_KP
One of the keypad numbers; use FL_KP + 'n' for digit n.
Definition: Enumerations.H:492
Fl_Widget::label
const char * label() const
Definition: Fl_Widget.H:421
FL_Control_L
#define FL_Control_L
The lefthand control key.
Definition: Enumerations.H:499
FL_Scroll_Lock
#define FL_Scroll_Lock
The scroll lock key.
Definition: Enumerations.H:473
FL_Shift_R
#define FL_Shift_R
The righthand shift key.
Definition: Enumerations.H:498
FL_Menu
#define FL_Menu
The menu key.
Definition: Enumerations.H:489
fl_utf8encode
int fl_utf8encode(unsigned ucs, char *buf)
Definition: fl_utf.c:309
FL_Num_Lock
#define FL_Num_Lock
The num lock key.
Definition: Enumerations.H:491
FL_Meta_L
#define FL_Meta_L
The left meta/Windows key.
Definition: Enumerations.H:502
Fl_Button.H
FL_Alt_L
#define FL_Alt_L
The left alt key.
Definition: Enumerations.H:504
add_modifier_key
static char * add_modifier_key(char *p, const char *end, const char *name)
Definition: fl_shortcut.cxx:216
flstring.h
fl_toupper
int fl_toupper(unsigned int ucs)
Definition: fl_utf8.cxx:237
Fl_Widget::SHORTCUT_LABEL
the label contains a shortcut we need to draw
Definition: Fl_Widget.H:162
FL_Insert
#define FL_Insert
The insert key.
Definition: Enumerations.H:488
FL_F
#define FL_F
One of the function keys; use FL_F + n for function key n.
Definition: Enumerations.H:495
FL_Caps_Lock
#define FL_Caps_Lock
The caps lock key.
Definition: Enumerations.H:501
uchar
unsigned char uchar
Definition: fl_types.h:30
symbol::name
const char * name
Definition: factory.cxx:1107
name
static const char * name
Definition: Fl_arg.cxx:53
FL_CTRL
#define FL_CTRL
One of the ctrl keys is down.
Definition: Enumerations.H:559
FL_Delete
#define FL_Delete
The delete key.
Definition: Enumerations.H:506
FL_F_Last
#define FL_F_Last
The last function key; use to range-check function keys.
Definition: Enumerations.H:496
fl_tolower
int fl_tolower(unsigned int ucs)
Definition: fl_utf8.cxx:229
FL_Escape
#define FL_Escape
The escape key.
Definition: Enumerations.H:474