2.5
[blender-staging.git] / source / blender / windowmanager / intern / wm_keymap.c
1 /**
2  * $Id:
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. 
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2007 Blender Foundation.
21  * All rights reserved.
22  *
23  * 
24  * Contributor(s): Blender Foundation
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 #include <string.h>
30
31 #include "DNA_screen_types.h"
32 #include "DNA_windowmanager_types.h"
33
34 #include "MEM_guardedalloc.h"
35
36 #include "BLI_blenlib.h"
37
38 #include "BKE_blender.h"
39 #include "BKE_context.h"
40 #include "BKE_idprop.h"
41 #include "BKE_library.h"
42 #include "BKE_main.h"
43 #include "BKE_utildefines.h"
44
45 #include "RNA_access.h"
46 #include "RNA_types.h"
47
48 #include "WM_api.h"
49 #include "WM_types.h"
50 #include "wm_window.h"
51 #include "wm_event_system.h"
52 #include "wm_event_types.h"
53
54 /* ***************** generic call, exported **************** */
55
56 static void keymap_event_set(wmKeymapItem *kmi, short type, short val, int modifier, short keymodifier)
57 {
58         kmi->type= type;
59         kmi->val= val;
60         kmi->keymodifier= keymodifier;
61         
62         if(modifier == KM_ANY) {
63                 kmi->shift= kmi->ctrl= kmi->alt= kmi->oskey= KM_ANY;
64         }
65         else {
66                 
67                 /* defines? */
68                 if(modifier & KM_SHIFT)
69                         kmi->shift= 1;
70                 else if(modifier & KM_SHIFT2)
71                         kmi->shift= 2;
72                 if(modifier & KM_CTRL)
73                         kmi->ctrl= 1;
74                 else if(modifier & KM_CTRL2)
75                         kmi->ctrl= 2;
76                 if(modifier & KM_ALT)
77                         kmi->alt= 1;
78                 else if(modifier & KM_ALT2)
79                         kmi->alt= 2;
80                 if(modifier & KM_OSKEY)
81                         kmi->oskey= 1;
82                 else if(modifier & KM_OSKEY2)
83                         kmi->oskey= 2;  
84         }
85 }
86
87 static void keymap_properties_set(wmKeymapItem *kmi)
88 {
89         if(!kmi->ptr) {
90                 kmi->ptr= MEM_callocN(sizeof(PointerRNA), "wmKeymapItemPtr");
91                 WM_operator_properties_create(kmi->ptr, kmi->idname);
92         }
93 }
94
95 /* if item was added, then bail out */
96 wmKeymapItem *WM_keymap_verify_item(ListBase *lb, char *idname, short type, short val, int modifier, short keymodifier)
97 {
98         wmKeymapItem *kmi;
99         
100         for(kmi= lb->first; kmi; kmi= kmi->next)
101                 if(strncmp(kmi->idname, idname, OP_MAX_TYPENAME)==0)
102                         break;
103         if(kmi==NULL) {
104                 kmi= MEM_callocN(sizeof(wmKeymapItem), "keymap entry");
105                 
106                 BLI_addtail(lb, kmi);
107                 BLI_strncpy(kmi->idname, idname, OP_MAX_TYPENAME);
108                 
109                 keymap_event_set(kmi, type, val, modifier, keymodifier);
110                 keymap_properties_set(kmi);
111         }
112         return kmi;
113 }
114
115 /* always add item */
116 wmKeymapItem *WM_keymap_add_item(ListBase *lb, char *idname, short type, short val, int modifier, short keymodifier)
117 {
118         wmKeymapItem *kmi= MEM_callocN(sizeof(wmKeymapItem), "keymap entry");
119         
120         BLI_addtail(lb, kmi);
121         BLI_strncpy(kmi->idname, idname, OP_MAX_TYPENAME);
122
123         keymap_event_set(kmi, type, val, modifier, keymodifier);
124         keymap_properties_set(kmi);
125         return kmi;
126 }
127
128 /* ****************** storage in WM ************ */
129
130 /* name id's are for storing general or multiple keymaps, 
131    space/region ids are same as DNA_space_types.h */
132 /* gets free'd in wm.c */
133
134 ListBase *WM_keymap_listbase(wmWindowManager *wm, const char *nameid, int spaceid, int regionid)
135 {
136         wmKeyMap *km;
137         
138         for(km= wm->keymaps.first; km; km= km->next)
139                 if(km->spaceid==spaceid && km->regionid==regionid)
140                         if(0==strncmp(nameid, km->nameid, KMAP_MAX_NAME))
141                                 break;
142
143         if(km==NULL) {
144                 km= MEM_callocN(sizeof(struct wmKeyMap), "keymap list");
145                 BLI_strncpy(km->nameid, nameid, KMAP_MAX_NAME);
146                 km->spaceid= spaceid;
147                 km->regionid= regionid;
148                 BLI_addtail(&wm->keymaps, km);
149         }
150         
151         return &km->keymap;
152 }
153
154 /* ***************** get string from key events **************** */
155
156 char *WM_key_event_string(short type)
157 {
158         /* not returned: CAPSLOCKKEY, UNKNOWNKEY, COMMANDKEY, GRLESSKEY */
159
160         switch(type) {
161         case AKEY:
162                 return "A";
163                 break;
164         case BKEY:
165                 return "B";
166                 break;
167         case CKEY:
168                 return "C";
169                 break;
170         case DKEY:
171                 return "D";
172                 break;
173         case EKEY:
174                 return "E";
175                 break;
176         case FKEY:
177                 return "F";
178                 break;
179         case GKEY:
180                 return "G";
181                 break;
182         case HKEY:
183                 return "H";
184                 break;
185         case IKEY:
186                 return "I";
187                 break;
188         case JKEY:
189                 return "J";
190                 break;
191         case KKEY:
192                 return "K";
193                 break;
194         case LKEY:
195                 return "L";
196                 break;
197         case MKEY:
198                 return "M";
199                 break;
200         case NKEY:
201                 return "N";
202                 break;
203         case OKEY:
204                 return "O";
205                 break;
206         case PKEY:
207                 return "P";
208                 break;
209         case QKEY:
210                 return "Q";
211                 break;
212         case RKEY:
213                 return "R";
214                 break;
215         case SKEY:
216                 return "S";
217                 break;
218         case TKEY:
219                 return "T";
220                 break;
221         case UKEY:
222                 return "U";
223                 break;
224         case VKEY:
225                 return "V";
226                 break;
227         case WKEY:
228                 return "W";
229                 break;
230         case XKEY:
231                 return "X";
232                 break;
233         case YKEY:
234                 return "Y";
235                 break;
236         case ZKEY:
237                 return "Z";
238                 break;
239
240         case ZEROKEY:
241                 return "Zero";
242                 break;
243         case ONEKEY:
244                 return "One";
245                 break;
246         case TWOKEY:
247                 return "Two";
248                 break;
249         case THREEKEY:
250                 return "Three";
251                 break;
252         case FOURKEY:
253                 return "Four";
254                 break;
255         case FIVEKEY:
256                 return "Five";
257                 break;
258         case SIXKEY:
259                 return "Six";
260                 break;
261         case SEVENKEY:
262                 return "Seven";
263                 break;
264         case EIGHTKEY:
265                 return "Eight";
266                 break;
267         case NINEKEY:
268                 return "Nine";
269                 break;
270
271         case LEFTCTRLKEY:
272                 return "Leftctrl";
273                 break;
274         case LEFTALTKEY:
275                 return "Leftalt";
276                 break;
277         case RIGHTALTKEY:
278                 return "Rightalt";
279                 break;
280         case RIGHTCTRLKEY:
281                 return "Rightctrl";
282                 break;
283         case RIGHTSHIFTKEY:
284                 return "Rightshift";
285                 break;
286         case LEFTSHIFTKEY:
287                 return "Leftshift";
288                 break;
289
290         case ESCKEY:
291                 return "Esc";
292                 break;
293         case TABKEY:
294                 return "Tab";
295                 break;
296         case RETKEY:
297                 return "Ret";
298                 break;
299         case SPACEKEY:
300                 return "Space";
301                 break;
302         case LINEFEEDKEY:
303                 return "Linefeed";
304                 break;
305         case BACKSPACEKEY:
306                 return "Backspace";
307                 break;
308         case DELKEY:
309                 return "Del";
310                 break;
311         case SEMICOLONKEY:
312                 return "Semicolon";
313                 break;
314         case PERIODKEY:
315                 return "Period";
316                 break;
317         case COMMAKEY:
318                 return "Comma";
319                 break;
320         case QUOTEKEY:
321                 return "Quote";
322                 break;
323         case ACCENTGRAVEKEY:
324                 return "Accentgrave";
325                 break;
326         case MINUSKEY:
327                 return "Minus";
328                 break;
329         case SLASHKEY:
330                 return "Slash";
331                 break;
332         case BACKSLASHKEY:
333                 return "Backslash";
334                 break;
335         case EQUALKEY:
336                 return "Equal";
337                 break;
338         case LEFTBRACKETKEY:
339                 return "Leftbracket";
340                 break;
341         case RIGHTBRACKETKEY:
342                 return "Rightbracket";
343                 break;
344
345         case LEFTARROWKEY:
346                 return "Leftarrow";
347                 break;
348         case DOWNARROWKEY:
349                 return "Downarrow";
350                 break;
351         case RIGHTARROWKEY:
352                 return "Rightarrow";
353                 break;
354         case UPARROWKEY:
355                 return "Uparrow";
356                 break;
357
358         case PAD2:
359                 return "Numpad 2";
360                 break;
361         case PAD4:
362                 return "Numpad 4";
363                 break;
364         case PAD6:
365                 return "Numpad 6";
366                 break;
367         case PAD8:
368                 return "Numpad 8";
369                 break;
370         case PAD1:
371                 return "Numpad 1";
372                 break;
373         case PAD3:
374                 return "Numpad 3";
375                 break;
376         case PAD5:
377                 return "Numpad 5";
378                 break;
379         case PAD7:
380                 return "Numpad 7";
381                 break;
382         case PAD9:
383                 return "Numpad 9";
384                 break;
385
386         case PADPERIOD:
387                 return "Numpad .";
388                 break;
389         case PADSLASHKEY:
390                 return "Numpad /";
391                 break;
392         case PADASTERKEY:
393                 return "Numpad *";
394                 break;
395
396         case PAD0:
397                 return "Numpad 0";
398                 break;
399         case PADMINUS:
400                 return "Numpad -";
401                 break;
402         case PADENTER:
403                 return "Numpad Enter";
404                 break;
405         case PADPLUSKEY:
406                 return "Numpad +";
407                 break;
408
409         case F1KEY:
410                 return "F1";
411                 break;
412         case F2KEY:
413                 return "F2";
414                 break;
415         case F3KEY:
416                 return "F3";
417                 break;
418         case F4KEY:
419                 return "F4";
420                 break;
421         case F5KEY:
422                 return "F5";
423                 break;
424         case F6KEY:
425                 return "F6";
426                 break;
427         case F7KEY:
428                 return "F7";
429                 break;
430         case F8KEY:
431                 return "F8";
432                 break;
433         case F9KEY:
434                 return "F9";
435                 break;
436         case F10KEY:
437                 return "F10";
438                 break;
439         case F11KEY:
440                 return "F11";
441                 break;
442         case F12KEY:
443                 return "F12";
444                 break;
445
446         case PAUSEKEY:
447                 return "Pause";
448                 break;
449         case INSERTKEY:
450                 return "Insert";
451                 break;
452         case HOMEKEY:
453                 return "Home";
454                 break;
455         case PAGEUPKEY:
456                 return "Pageup";
457                 break;
458         case PAGEDOWNKEY:
459                 return "Pagedown";
460                 break;
461         case ENDKEY:
462                 return "End";
463                 break;
464         }
465         
466         return "";
467 }
468
469 static char *wm_keymap_item_to_string(wmKeymapItem *kmi, char *str, int len)
470 {
471         char buf[100];
472
473         buf[0]= 0;
474
475         if(kmi->shift)
476                 strcat(buf, "Shift ");
477
478         if(kmi->ctrl)
479                 strcat(buf, "Ctrl ");
480
481         if(kmi->alt)
482                 strcat(buf, "Alt ");
483
484         if(kmi->oskey)
485                 strcat(buf, "OS ");
486
487         strcat(buf, WM_key_event_string(kmi->type));
488         BLI_strncpy(str, buf, len);
489
490         return str;
491 }
492
493 static char *wm_keymap_item_find(ListBase *handlers, const char *opname, int opcontext, IDProperty *properties, char *str, int len)
494 {
495         wmEventHandler *handler;
496         wmKeymapItem *kmi;
497
498         /* find keymap item in handlers */
499         for(handler=handlers->first; handler; handler=handler->next)
500                 if(handler->keymap)
501                         for(kmi=handler->keymap->first; kmi; kmi=kmi->next)
502                                 if(strcmp(kmi->idname, opname) == 0 && WM_key_event_string(kmi->type)[0])
503                                         if(kmi->ptr && IDP_EqualsProperties(properties, kmi->ptr->data))
504                                                 return wm_keymap_item_to_string(kmi, str, len);
505         
506         return NULL;
507 }
508
509 char *WM_key_event_operator_string(const bContext *C, const char *opname, int opcontext, IDProperty *properties, char *str, int len)
510 {
511         char *found= NULL;
512
513         /* look into multiple handler lists to find the item */
514         if(CTX_wm_window(C))
515                 if((found= wm_keymap_item_find(&CTX_wm_window(C)->handlers, opname, opcontext, properties, str, len)))
516                         return found;
517
518         if(CTX_wm_area(C))
519                 if((found= wm_keymap_item_find(&CTX_wm_area(C)->handlers, opname, opcontext, properties, str, len)))
520                         return found;
521
522         if(ELEM(opcontext, WM_OP_EXEC_REGION_WIN, WM_OP_INVOKE_REGION_WIN)) {
523                 if(CTX_wm_area(C)) {
524                         ARegion *ar= CTX_wm_area(C)->regionbase.first;
525                         for(; ar; ar= ar->next)
526                                 if(ar->regiontype==RGN_TYPE_WINDOW)
527                                         break;
528
529                         if(ar)
530                                 if((found= wm_keymap_item_find(&ar->handlers, opname, opcontext, properties, str, len)))
531                                         return found;
532                 }
533         }
534         else {
535                 if(CTX_wm_region(C))
536                         if((found= wm_keymap_item_find(&CTX_wm_region(C)->handlers, opname, opcontext, properties, str, len)))
537                                 return found;
538         }
539
540         return NULL;
541 }
542