1 /* Copyright (C) 2012 by Ben Martin */ 2 /* 3 * Redistribution and use in source and binary forms, with or without 4 * modification, are permitted provided that the following conditions are met: 5 6 * Redistributions of source code must retain the above copyright notice, this 7 * list of conditions and the following disclaimer. 8 9 * Redistributions in binary form must reproduce the above copyright notice, 10 * this list of conditions and the following disclaimer in the documentation 11 * and/or other materials provided with the distribution. 12 13 * The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #ifndef FONTFORGE_HOTKEYS_H 29 #define FONTFORGE_HOTKEYS_H 30 31 #include "basics.h" 32 #include "dlist.h" 33 #include "gdraw.h" 34 35 #define HOTKEY_ACTION_MAX_SIZE 200 36 #define HOTKEY_TEXT_MAX_SIZE 100 37 38 39 /** 40 * A hotkey binds some keyboard combination to an abstract "action" 41 * 42 * A major use of the action is to be able to pick off menu items from 43 * various windows as an action path. For example, 44 * CharView.Menu.File.Open is an action for the file/open menu item in 45 * the charview/glyph editing window. 46 * 47 * This namespace convension uses dot separated strings. The window 48 * type as the first string, followed by "Menu", followed by each menu 49 * item on the path down to the menu that should be invoked when the 50 * hotkey is pressed. 51 * 52 * The same system can be extended to allow python code to be 53 * executed. The current plan is to use Python instead of Menu. There 54 * is no reason that the syntax can not be varied slightly for Python, 55 * for example to allow something like 56 * 57 * CharView.Python.MyFooFunction( 7, "fdsfsd" ): Alt+t 58 * 59 * Where everything after the "Python." is to be the name of a valid 60 * python function to execute, in this case a call to MyFooFunction. 61 * While we could allow raw python code inthere too, it's probably 62 * simpler for the fontforge code to rely on calling a function 63 * instead. There is no reason that arguments can not be supplied as 64 * above. 65 * 66 * The hotkeys are actually made effective (ie execute something), in 67 * the GMenuBarCheckKey() function in gmenu.c. That code would need 68 * some extending to allow the execution of a python function instead 69 * of the current code which only executes a menu item which is named 70 * in the action. 71 * 72 * I am tempted there to move the execution of an action hack into 73 * hotkeys.c with GMenuBarCheckKey() passing the window and menubar to 74 * the new hotkeyExecuteAction() function which itself could handle 75 * working out if it is a CharView.Python prefix action and 76 * dispatching accordingly. The gain to that is that other code might 77 * also like to execute a hotkey independant of the existing code. For 78 * example, python code might execute an "action" through that 79 * function. 80 * 81 * The part I haven't personally investigated is the code to dispatch 82 * a python function from C. I've done similar with other codebases 83 * but haven't seen how it's done in ff. Others might like to put some 84 * hints here for whoever (maybe me!) writes the code to allow python 85 * dispatch from hotkeys. 86 * 87 * In a similar way, I was thinking of just having a top level 88 * directory of Action.Foo to allow generic, but maybe too low level 89 * for a menuitem things to be made available to the hotkey system. 90 * Perhaps an Action.ActionsList which just enumerates these actions 91 * to the console would be handy to allow folks to see what the code 92 * current version of ff offers in terms of actions. 93 * 94 */ 95 typedef struct hotkey { 96 /** 97 * Hotkeys are stored in a doubly linked list. Having this entry 98 * first makes a pointer to a hotkey able to e treated as a list 99 * node. 100 */ 101 struct dlistnode listnode; 102 103 /** 104 * The name of the action this hotkey is to perform. For example, 105 * CharView.Menu.File.Open 106 */ 107 char action[HOTKEY_ACTION_MAX_SIZE+1]; 108 109 /** 110 * A directly machine usable represetation of the modifiers that 111 * must be in use for this hotkey to be fired. For example, shift, 112 * control etc. 113 */ 114 uint16 state; 115 116 /** 117 * A directly machine usable represetation of the key that is to 118 * be pressed fo r this hotkey. This would be a number for a key 119 * so that 'k' might be 642 120 */ 121 uint16 keysym; 122 123 /** 124 * If this hotkey is user defined this is true. If this is true 125 * then the hotkey should be saved back to the user 126 * ~/.FontForge/hotkeys file instead of any system file. 127 */ 128 int isUserDefined; 129 130 /** 131 * The plain text representation for the key combination that is 132 * to be pressed for this hotkey. For example, "Ctrl+k". Note that 133 * the modifiers are not localized in this string, it is as it 134 * would appear in the hotkeys file and system hotkeys 135 * definitations. 136 */ 137 char text[HOTKEY_TEXT_MAX_SIZE+1]; 138 } Hotkey; 139 140 /** 141 * Load the list of hotkey from both system and user catalogs. These 142 * include the locale versions like en_GB which provide the shipped 143 * defaults and the user overrides in ~/.FontForge/hotkeys. 144 */ 145 extern void hotkeysLoad(void); 146 147 /** 148 * Save all user defined hotkeys back to ~/.FontForge/hotkeys. 149 */ 150 extern void hotkeysSave(void); 151 152 /** 153 * Return the non localized string definition of the keys that must 154 * be pressed for this action. The return value might be Shift+Ctl+8 155 */ 156 extern char* hotkeysGetKeyDescriptionFromAction( char* action ); 157 158 /** 159 * Find the hotkey that matches the given event for the given window. 160 * The window is needed because hotkeys can bind to specific windows 161 * like the fontview, metricsview or charview. 162 * 163 * Do not free the return value, it's not yours! 164 */ 165 extern Hotkey* hotkeyFindByEvent( GWindow w, GEvent *event ); 166 167 /** 168 * Like hotkeyFindByEvent but this gives you access to all the hotkeys 169 * that are to be triggered for the given event on the given window. 170 * 171 * You should call dlist_free_external() on the return value. The 172 * hotkeys returned are not yours to free, but the list nodes that 173 * point to the hotkeys *ARE* yours to free. 174 */ 175 extern struct dlistnodeExternal* hotkeyFindAllByEvent( GWindow w, GEvent *event ); 176 177 /** 178 * Strip off any modifier definitation from the given fill hotkey string 179 * definition. Given a string like Shift+Ctl+8 returns 8. 180 * No memory allocations are performed, the return value is null or a pointer 181 * into the hktext string. 182 */ 183 extern char* hotkeyTextWithoutModifiers( char* hktext ); 184 185 /** 186 * Convert text like Control to the command key unicode value. 187 * Caller must free the returned value 188 */ 189 extern char* hotkeyTextToMacModifiers( char* keydesc ); 190 191 /** 192 * Given a menu path like File/Open find the hotkey which will trigger 193 * that menu item. The window is needed because there might be a 194 * menuitem with the same text path in fontview and charview which the 195 * user has decided should have different hotkeys 196 * 197 * Do not free the return value, it's not yours! 198 */ 199 extern Hotkey* hotkeyFindByMenuPath( GWindow w, char* path ); 200 extern Hotkey* hotkeyFindByMenuPathInSubMenu( GWindow w, char* subMenuName, char* path ); 201 202 /** 203 * Immediate keys are hotkeys like the ` key to turn on preview mode in charview. 204 * They are perhaps toggle keys, or just keys which code wants to respond to a keypress 205 * but also allow the user to configure what that key is using their hotkeys file. 206 * Instead of doing event->u.chr.keysym == '`' code can pass the event and a text name 207 * like "TogglePreview" and a window (to determine the prefix like CharView) and this 208 * function will tell you if that event matches the key that the user has defined to 209 * trigger your event. 210 */ 211 extern Hotkey* isImmediateKey( GWindow w, char* path, GEvent *event ); 212 213 214 215 /** 216 * Set a hotkey to trigger the given action. If append is not true 217 * then any other hotkey bindings using keydefinition for the window 218 * type specified in the action you passed are first removed. 219 * 220 * The new hotkey is returned. 221 */ 222 extern Hotkey* hotkeySet( char* action, char* keydefinition, int append ); 223 224 extern void HotkeyParse( Hotkey* hk, const char *shortcut ); 225 226 /** 227 * Set to true if the hotkey system can use the Command key for its 228 * own actions. 229 */ 230 extern void hotkeySystemSetCanUseMacCommand( int v ); 231 extern int hotkeySystemGetCanUseMacCommand(void); 232 233 #endif /* FONTFORGE_HOTKEYS_H */ 234