|
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_shortcut.cxx 7914 2010-11-29 19:26:11Z manolo $" 00003 // 00004 // Shortcut support routines 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 // Code to test and parse fltk shortcut numbers. 00029 // 00030 // A shortcut is a keysym or'd with shift flags. In the simplest 00031 // sense a shortcut is matched if the shift state is exactly as 00032 // given and the key returning that keysym is pressed. 00033 // 00034 // To make it easier to match some things it is more complex: 00035 // 00036 // Only FL_META, FL_ALT, FL_SHIFT, and FL_CTRL must be "off". A 00037 // zero in the other shift flags indicates "dont care". 00038 // 00039 // It also checks against the first character of Fl::event_text(), 00040 // and zero for FL_SHIFT means "don't care". 00041 // This allows punctuation shortcuts like "#" to work (rather than 00042 // calling it "shift+3" on a US keyboard) 00043 00044 #include <FL/Fl.H> 00045 #include <FL/Fl_Widget.H> 00046 #include <FL/Fl_Button.H> 00047 #include <FL/fl_draw.H> 00048 #include <ctype.h> 00049 #include "flstring.h" 00050 #if !defined(WIN32) && !defined(__APPLE__) 00051 #include <FL/x.H> 00052 #endif 00053 00063 int Fl::test_shortcut(unsigned int shortcut) { 00064 if (!shortcut) return 0; 00065 00066 unsigned int v = shortcut & FL_KEY_MASK; 00067 if (((unsigned)fl_tolower(v))!=v) { 00068 shortcut |= FL_SHIFT; 00069 } 00070 00071 int shift = Fl::event_state(); 00072 // see if any required shift flags are off: 00073 if ((shortcut&shift) != (shortcut&0x7fff0000)) return 0; 00074 // record shift flags that are wrong: 00075 int mismatch = (shortcut^shift)&0x7fff0000; 00076 // these three must always be correct: 00077 if (mismatch&(FL_META|FL_ALT|FL_CTRL)) return 0; 00078 00079 unsigned int key = shortcut & FL_KEY_MASK; 00080 00081 // if shift is also correct, check for exactly equal keysyms: 00082 if (!(mismatch&(FL_SHIFT)) && key == (unsigned)Fl::event_key()) return 1; 00083 00084 // try matching utf8, ignore shift: 00085 unsigned int firstChar = fl_utf8decode(Fl::event_text(), Fl::event_text()+Fl::event_length(), 0); 00086 if ( ! (FL_CAPS_LOCK&shift) && key==firstChar) return 1; 00087 00088 // kludge so that Ctrl+'_' works (as opposed to Ctrl+'^_'): 00089 if ((shift&FL_CTRL) && key >= 0x3f && key <= 0x5F 00090 && firstChar==(key^0x40)) return 1; // firstChar should be within a-z 00091 return 0; 00092 } 00093 00094 // This table must be in numeric order by fltk (X) keysym number: 00095 struct Keyname {unsigned int key; const char* name;}; 00096 #if defined(WIN32) 00097 static Keyname table[] = { 00098 {' ', "Space"}, 00099 {FL_BackSpace, "Backspace"}, 00100 {FL_Tab, "Tab"}, 00101 {0xff0b/*XK_Clear*/, "Clear"}, 00102 {FL_Enter, "Enter"}, // X says "Enter" 00103 {FL_Pause, "Pause"}, 00104 {FL_Scroll_Lock, "Scroll_Lock"}, 00105 {FL_Escape, "Escape"}, 00106 {FL_Home, "Home"}, 00107 {FL_Left, "Left"}, 00108 {FL_Up, "Up"}, 00109 {FL_Right, "Right"}, 00110 {FL_Down, "Down"}, 00111 {FL_Page_Up, "Page_Up"}, // X says "Prior" 00112 {FL_Page_Down,"Page_Down"}, // X says "Next" 00113 {FL_End, "End"}, 00114 {FL_Print, "Print"}, 00115 {FL_Insert, "Insert"}, 00116 {FL_Menu, "Menu"}, 00117 {FL_Num_Lock, "Num_Lock"}, 00118 {FL_KP_Enter, "KP_Enter"}, 00119 {FL_Shift_L, "Shift_L"}, 00120 {FL_Shift_R, "Shift_R"}, 00121 {FL_Control_L,"Control_L"}, 00122 {FL_Control_R,"Control_R"}, 00123 {FL_Caps_Lock,"Caps_Lock"}, 00124 {FL_Meta_L, "Meta_L"}, 00125 {FL_Meta_R, "Meta_R"}, 00126 {FL_Alt_L, "Alt_L"}, 00127 {FL_Alt_R, "Alt_R"}, 00128 {FL_Delete, "Delete"} 00129 }; 00130 #elif defined(__APPLE__) 00131 static Keyname table[] = { 00132 // v - this column contains utf8 characters 00133 {' ', "Space"}, 00134 {FL_BackSpace,"\xe2\x8c\xab"}, // erase to the left 00135 {FL_Tab, "\xe2\x87\xa5"}, // rightwards arrow to bar 00136 {0xff0b, "\xe2\x8c\xa6"}, // erase to the right 00137 {FL_Enter, "\xe2\x86\xa9"}, // leftwards arrow with hook 00138 {FL_Pause, "Pause"}, 00139 {FL_Scroll_Lock, "Scroll_Lock"}, 00140 {FL_Escape, "\xe2\x90\x9b"}, 00141 {FL_Home, "\xe2\x86\x96"}, // north west arrow 00142 {FL_Left, "\xe2\x86\x90"}, // leftwards arrow 00143 {FL_Up, "\xe2\x86\x91"}, // upwards arrow 00144 {FL_Right, "\xe2\x86\x92"}, // rightwards arrow 00145 {FL_Down, "\xe2\x86\x93"}, // downwards arrow 00146 {FL_Page_Up, "\xe2\x87\x9e"}, // upwards arrow with double stroke 00147 {FL_Page_Down,"\xe2\x87\x9f"}, // downward arrow with double stroke 00148 {FL_End, "\xe2\x86\x98"}, // south east arrow 00149 {FL_Print, "Print"}, 00150 {FL_Insert, "Insert"}, 00151 {FL_Menu, "Menu"}, 00152 {FL_Num_Lock, "Num_Lock"}, 00153 {FL_KP_Enter, "\xe2\x8c\xa4"}, // up arrow head between two horizontal bars 00154 {FL_Shift_L, "Shift_L"}, 00155 {FL_Shift_R, "Shift_R"}, 00156 {FL_Control_L,"Control_L"}, 00157 {FL_Control_R,"Control_R"}, 00158 {FL_Caps_Lock,"\xe2\x87\xaa"}, // upwards white arrow from bar 00159 {FL_Meta_L, "Meta_L"}, 00160 {FL_Meta_R, "Meta_R"}, 00161 {FL_Alt_L, "Alt_L"}, 00162 {FL_Alt_R, "Alt_R"}, 00163 {FL_Delete, "\xe2\x8c\xa7"} // x in a rectangle box 00164 }; 00165 #endif 00166 00179 const char* fl_shortcut_label(unsigned int shortcut) { 00180 return fl_shortcut_label(shortcut, 0L); 00181 } 00182 00191 const char* fl_shortcut_label(unsigned int shortcut, const char **eom) { 00192 static char buf[20]; 00193 char *p = buf; 00194 if (eom) *eom = p; 00195 if (!shortcut) {*p = 0; return buf;} 00196 // fix upper case shortcuts 00197 unsigned int v = shortcut & FL_KEY_MASK; 00198 if (((unsigned)fl_tolower(v))!=v) { 00199 shortcut |= FL_SHIFT; 00200 } 00201 #ifdef __APPLE__ 00202 // this column contains utf8 characters - v 00203 if (shortcut & FL_SHIFT) {strcpy(p,"\xe2\x87\xa7"); p += 3;} // upwards white arrow 00204 if (shortcut & FL_CTRL) {strcpy(p,"\xe2\x8c\x83"); p += 3;} // up arrowhead 00205 if (shortcut & FL_ALT) {strcpy(p,"\xe2\x8c\xa5"); p += 3;} // alternative key symbol 00206 if (shortcut & FL_META) {strcpy(p,"\xe2\x8c\x98"); p += 3;} // place of interest sign 00207 #else 00208 if (shortcut & FL_META) {strcpy(p,"Meta+"); p += 5;} 00209 if (shortcut & FL_ALT) {strcpy(p,"Alt+"); p += 4;} 00210 if (shortcut & FL_SHIFT) {strcpy(p,"Shift+"); p += 6;} 00211 if (shortcut & FL_CTRL) {strcpy(p,"Ctrl+"); p += 5;} 00212 #endif // __APPLE__ 00213 if (eom) *eom = p; 00214 unsigned int key = shortcut & FL_KEY_MASK; 00215 #if defined(WIN32) || defined(__APPLE__) // if not X 00216 if (key >= FL_F && key <= FL_F_Last) { 00217 *p++ = 'F'; 00218 if (key > FL_F+9) *p++ = (key-FL_F)/10+'0'; 00219 *p++ = (key-FL_F)%10 + '0'; 00220 } else { 00221 // binary search the table for a match: 00222 int a = 0; 00223 int b = sizeof(table)/sizeof(*table); 00224 while (a < b) { 00225 int c = (a+b)/2; 00226 if (table[c].key == key) { 00227 if (p > buf) { 00228 strcpy(p,table[c].name); 00229 return buf; 00230 } else { 00231 const char *sp = table[c].name; 00232 if (eom) *eom = sp; 00233 return sp; 00234 } 00235 } 00236 if (table[c].key < key) a = c+1; 00237 else b = c; 00238 } 00239 if (key >= FL_KP && key <= FL_KP_Last) { 00240 // mark keypad keys with KP_ prefix 00241 strcpy(p,"KP_"); p += 3; 00242 *p++ = uchar(key & 127); 00243 } else { 00244 // if none found, use the keystroke as a match: 00245 p += fl_utf8encode(fl_toupper(key), p); 00246 } 00247 } 00248 *p = 0; 00249 return buf; 00250 #else 00251 const char* q; 00252 if (key == FL_Enter || key == '\r') q="Enter"; // don't use Xlib's "Return": 00253 else if (key > 32 && key < 0x100) q = 0; 00254 else q = XKeysymToString(key); 00255 if (!q) { 00256 p += fl_utf8encode(fl_toupper(key), p); 00257 *p = 0; 00258 return buf; 00259 } 00260 if (p > buf) { 00261 strcpy(p,q); 00262 return buf; 00263 } else { 00264 if (eom) *eom = q; 00265 return q; 00266 } 00267 #endif 00268 } 00269 00270 // Emulation of XForms named shortcuts 00271 #include <stdlib.h> 00285 unsigned int fl_old_shortcut(const char* s) { 00286 if (!s || !*s) return 0; 00287 unsigned int n = 0; 00288 if (*s == '#') {n |= FL_ALT; s++;} 00289 if (*s == '+') {n |= FL_SHIFT; s++;} 00290 if (*s == '^') {n |= FL_CTRL; s++;} 00291 if (*s && s[1]) return n | (int)strtol(s,0,0); // allow 0xf00 to get any key 00292 return n | *s; 00293 } 00294 00295 // Tests for &x shortcuts in button labels: 00296 00309 unsigned int Fl_Widget::label_shortcut(const char *t) { 00310 if (!t) return 0; 00311 for (;;) { 00312 if (*t==0) return 0; 00313 if (*t=='&') { 00314 unsigned int s = fl_utf8decode(t+1, 0, 0); 00315 if (s==0) return 0; 00316 else if (s==(unsigned int)'&') t++; 00317 else return s; 00318 } 00319 t++; 00320 } 00321 } 00322 00342 int Fl_Widget::test_shortcut(const char *t, const bool require_alt) { 00343 if (!t) return 0; 00344 // for menubars etc. shortcuts must work only if the Alt modifier is pressed 00345 if (require_alt && Fl::event_state(FL_ALT)==0) return 0; 00346 unsigned int c = fl_utf8decode(Fl::event_text(), Fl::event_text()+Fl::event_length(), 0); 00347 if (!c) return 0; 00348 if (c == label_shortcut(t)) 00349 return 1; 00350 return 0; 00351 } 00352 00368 int Fl_Widget::test_shortcut() { 00369 if (!(flags()&SHORTCUT_LABEL)) return 0; 00370 return test_shortcut(label()); 00371 } 00372 00373 // 00374 // End of "$Id: fl_shortcut.cxx 7914 2010-11-29 19:26:11Z manolo $". 00375 //