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)  

fl_shortcut.cxx

Go to the documentation of this file.
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 //