Modified the UGetCursor() routine to return a valid response if the
[xcircuit.git] / keybindings.c
blob7518591a10b2b749fce30594ac3d42002b826375
1 /*--------------------------------------------------------------*/
2 /* keybindings.c: List of key bindings */
3 /* Copyright (c) 2002 Tim Edwards, Johns Hopkins University */
4 /*--------------------------------------------------------------*/
6 /*----------------------------------------------------------------------*/
7 /* written by Tim Edwards, 2/27/01 */
8 /*----------------------------------------------------------------------*/
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <ctype.h> /* for tolower(), toupper() */
14 #include <math.h>
16 #ifndef XC_WIN32
17 #include <X11/Intrinsic.h>
18 #include <X11/StringDefs.h>
19 #endif
21 #if !defined(XC_WIN32) || defined(TCL_WRAPPER)
22 #define XK_MISCELLANY
23 #define XK_LATIN1
24 #define XK_XKB_KEYS
25 #include <X11/keysymdef.h>
26 #endif
28 /*----------------------------------------------------------------------*/
29 /* Local includes */
30 /*----------------------------------------------------------------------*/
32 #ifdef TCL_WRAPPER
33 #include <tk.h>
34 #endif
36 #include "xcircuit.h"
38 /*----------------------------------------------------------------------*/
39 /* Function prototypes */
40 /*----------------------------------------------------------------------*/
42 #include "prototypes.h"
44 /*----------------------------------------------------------------------*/
45 /* Global variables */
46 /*----------------------------------------------------------------------*/
48 keybinding *keylist = NULL;
50 extern Display *dpy;
51 extern char _STR[150], _STR2[250];
52 extern int pressmode;
53 extern XCWindowData *areawin;
55 /*----------------------------------------------------------------------*/
56 /* Key modifiers (convenience definitions) */
57 /* Use Mod5Mask for a "hold" ("press") definition. */
58 /* Why Mod5Mask? Mod2Mask is used by fvwm2 for some obscure purpose, */
59 /* so I went to the other end (Mod5Mask is just below Button1Mask). */
60 /* Thanks to John Heil for reporting the problem and confirming the */
61 /* Mod5Mask solution. */
62 /*----------------------------------------------------------------------*/
64 #define ALT (Mod1Mask << 16)
65 #define CTRL (ControlMask << 16)
66 #define CAPSLOCK (LockMask << 16)
67 #define SHIFT (ShiftMask << 16)
68 #define BUTTON1 (Button1Mask << 16)
69 #define BUTTON2 (Button2Mask << 16)
70 #define BUTTON3 (Button3Mask << 16)
71 #define BUTTON4 (Button4Mask << 16)
72 #define BUTTON5 (Button5Mask << 16)
73 #define HOLD (Mod4Mask << 16)
75 #define ALL_WINDOWS (xcWidget)NULL
77 /*--------------------------------------------------------------*/
78 /* This list declares all the functions which can be bound to */
79 /* keys. It must match the order of the enumeration listed in */
80 /* xcircuit.h! */
81 /*--------------------------------------------------------------*/
83 static char *function_names[NUM_FUNCTIONS + 1] = {
84 "Page", "Anchor", "Superscript", "Subscript", "Normalscript",
85 "Nextfont", "Boldfont", "Italicfont", "Normalfont", "Underline",
86 "Overline", "ISO Encoding", "Halfspace", "Quarterspace",
87 "Special", "Tab Stop", "Tab Forward", "Tab Backward",
88 "Text Return", "Text Delete", "Text Right", "Text Left",
89 "Text Up", "Text Down", "Text Split",
90 "Text Home", "Text End", "Linebreak", "Parameter",
91 "Parameterize Point", "Change Style", "Delete Point", "Insert Point",
92 "Append Point", "Next Point", "Attach", "Next Library", "Library Directory",
93 "Library Move", "Library Copy", "Library Edit", "Library Delete",
94 "Library Duplicate", "Library Hide", "Library Virtual Copy",
95 "Page Directory", "Library Pop", "Virtual Copy",
96 "Help", "Redraw", "View", "Zoom In", "Zoom Out", "Pan",
97 "Double Snap", "Halve Snap", "Write", "Rotate", "Flip X",
98 "Flip Y", "Snap", "Snap To",
99 "Pop", "Push", "Delete", "Select", "Box", "Arc", "Text",
100 "Exchange", "Copy", "Move", "Join", "Unjoin", "Spline", "Edit",
101 "Undo", "Redo", "Select Save", "Unselect", "Dashed", "Dotted",
102 "Solid", "Prompt", "Dot", "Wire", "Cancel", "Nothing", "Exit",
103 "Netlist", "Swap", "Pin Label", "Pin Global", "Info Label", "Graphic",
104 "Select Box", "Connectivity", "Continue Element", "Finish Element",
105 "Continue Copy", "Finish Copy", "Finish", "Cancel Last", "Sim",
106 "SPICE", "PCB", "SPICE Flat", "Rescale", "Reorder", "Color",
107 "Margin Stop", "Text Delete Param",
108 NULL /* sentinel */
111 /*--------------------------------------------------------------*/
112 /* Return TRUE if the indicated key (keysym + bit-shifted state)*/
113 /* is bound to some function. */
114 /*--------------------------------------------------------------*/
116 Boolean ismacro(xcWidget window, int keywstate)
118 keybinding *ksearch;
120 for (ksearch = keylist; ksearch != NULL; ksearch = ksearch->nextbinding)
121 if (ksearch->window == ALL_WINDOWS || ksearch->window == window)
122 if (keywstate == ksearch->keywstate)
123 return True;
125 return False;
128 /*--------------------------------------------------------------*/
129 /* Return the first key binding for the indicated function */
130 /*--------------------------------------------------------------*/
132 int firstbinding(xcWidget window, int function)
134 keybinding *ksearch;
135 int keywstate = -1;
137 for (ksearch = keylist; ksearch != NULL; ksearch = ksearch->nextbinding) {
138 if (ksearch->function == function) {
139 if (ksearch->window == window)
140 return ksearch->keywstate;
141 else if (ksearch->window == ALL_WINDOWS)
142 keywstate = ksearch->keywstate;
145 return keywstate;
148 /*--------------------------------------------------------------*/
149 /* Find the first function bound to the indicated key that is */
150 /* compatible with the current state (eventmode). Window- */
151 /* specific bindings shadow ALL_WINDOWS bindings. Return the */
152 /* function number if found, or -1 if no compatible functions */
153 /* are bound to the key state. */
154 /*--------------------------------------------------------------*/
156 int boundfunction(xcWidget window, int keywstate, short *retnum)
158 keybinding *ksearch;
159 int tempfunc = -1;
161 for (ksearch = keylist; ksearch != NULL; ksearch = ksearch->nextbinding) {
162 if (keywstate == ksearch->keywstate) {
163 if (compatible_function(ksearch->function)) {
164 if (ksearch->window == window) {
165 if (retnum != NULL) *retnum = (ksearch->value);
166 return ksearch->function;
168 else if (ksearch->window == ALL_WINDOWS) {
169 if (retnum != NULL) *retnum = (ksearch->value);
170 tempfunc = ksearch->function;
175 return tempfunc;
178 /*--------------------------------------------------------------*/
179 /* Check if an entry exists for a given key-function pair */
180 /*--------------------------------------------------------------*/
182 int isbound(xcWidget window, int keywstate, int function, short value)
184 keybinding *ksearch;
186 for (ksearch = keylist; ksearch != NULL; ksearch = ksearch->nextbinding)
187 if (keywstate == ksearch->keywstate && function == ksearch->function)
188 if (window == ALL_WINDOWS || window == ksearch->window ||
189 ksearch->window == ALL_WINDOWS)
190 if (value == -1 || value == ksearch->value || ksearch->value == -1)
191 return TRUE;
193 return FALSE;
196 /*--------------------------------------------------------------*/
197 /* Return the string associated with a function, or NULL if the */
198 /* function value is out-of-bounds. */
199 /*--------------------------------------------------------------*/
201 char *func_to_string(int function)
203 if ((function < 0) || (function >= NUM_FUNCTIONS)) return NULL;
204 return function_names[function];
207 /*--------------------------------------------------------------*/
208 /* Identify a function with the string version of its name */
209 /*--------------------------------------------------------------*/
211 int string_to_func(const char *funcstring, short *value)
213 int i;
215 for (i = 0; i < NUM_FUNCTIONS; i++)
217 if (function_names[i] == NULL) {
218 Fprintf(stderr, "Error: resolve bindings and function strings!\n");
219 return -1; /* should not happen? */
221 if (!strcmp(funcstring, function_names[i]))
222 return i;
225 /* Check if this string might have a value attached */
227 if (value != NULL)
228 for (i = 0; i < NUM_FUNCTIONS; i++)
229 if (!strncmp(funcstring, function_names[i], strlen(function_names[i]))) {
230 sscanf(funcstring + strlen(function_names[i]), "%hd", value);
231 return i;
234 return -1;
237 /*--------------------------------------------------------------*/
238 /* Make a key sym from a string representing the key state */
239 /*--------------------------------------------------------------*/
241 int string_to_key(const char *keystring)
243 int ct, keywstate = 0;
244 const char *kptr = keystring;
246 while(1) {
247 if (*kptr == '\0') return -1;
248 if (!strncmp(kptr, "XK_", 3))
249 kptr += 3;
250 else if (!strncmp(kptr, "Shift_", 6)) {
251 keywstate |= SHIFT;
252 kptr += 6;
254 else if (!strncmp(kptr, "Capslock_", 9)) {
255 keywstate |= CAPSLOCK;
256 kptr += 9;
258 else if (!strncmp(kptr, "Control_", 8)) {
259 keywstate |= CTRL;
260 kptr += 8;
262 else if (!strncmp(kptr, "Alt_", 4)) {
263 keywstate |= ALT;
264 kptr += 4;
266 else if (!strncmp(kptr, "Meta_", 5)) {
267 keywstate |= ALT;
268 kptr += 5;
270 else if (!strncmp(kptr, "Hold_", 5)) {
271 keywstate |= HOLD;
272 kptr += 5;
274 else if (*kptr == '^') {
275 kptr++;
276 ct = (int)tolower(*kptr);
277 keywstate |= CTRL | ct;
278 break;
280 else if (*(kptr + 1) == '\0') {
281 if ((*kptr) < 32)
282 keywstate |= CTRL | (int)('A' + (*kptr) - 1);
283 else
284 keywstate |= (int)(*kptr);
285 break;
287 else {
288 if (!strncmp(kptr, "Button", 6)) {
289 switch (*(kptr + 6)) {
290 case '1': keywstate = (Button1Mask << 16); break;
291 case '2': keywstate = (Button2Mask << 16); break;
292 case '3': keywstate = (Button3Mask << 16); break;
293 case '4': keywstate = (Button4Mask << 16); break;
294 case '5': keywstate = (Button5Mask << 16); break;
297 else {
298 /* When any modifier keys are used, presence of SHIFT */
299 /* requires that the corresponding key be uppercase, */
300 /* and lack of SHIFT requires lowercase. Enforce it */
301 /* here so that it is not necessary for the user to */
302 /* do so. */
303 if (*(kptr + 1) == '\0') {
304 if (keywstate & SHIFT)
305 ct = (int)toupper(*kptr);
306 else
307 ct = (int)tolower(*kptr);
308 keywstate |= ct;
310 else
311 keywstate |= XStringToKeysym(kptr);
313 break;
316 return keywstate;
319 /*--------------------------------------------------------------*/
320 /* Convert a function into a string representing all of its */
321 /* key bindings. */
322 /*--------------------------------------------------------------*/
324 char *function_binding_to_string(xcWidget window, int function)
326 keybinding *ksearch;
327 char *retstr, *tmpstr;
328 Bool first = True;
330 retstr = (char *)malloc(1);
331 retstr[0] = '\0';
332 for (ksearch = keylist; ksearch != NULL; ksearch = ksearch->nextbinding) {
333 if (function == ksearch->function) {
334 if (ksearch->window == ALL_WINDOWS || ksearch->window == window) {
335 tmpstr = key_to_string(ksearch->keywstate);
336 if (tmpstr != NULL) {
337 retstr = (char *)realloc(retstr, strlen(retstr) + strlen(tmpstr) +
338 ((first) ? 1 : 3));
339 if (!first) strcat(retstr, ", ");
340 strcat(retstr, tmpstr);
341 free(tmpstr);
343 first = False;
347 if (retstr[0] == '\0') {
348 retstr = (char *)realloc(retstr, 10);
349 strcat(retstr, "<unbound>");
351 return(retstr);
354 /*--------------------------------------------------------------*/
355 /* Convert a key into a string representing all of its function */
356 /* bindings. */
357 /*--------------------------------------------------------------*/
359 char *key_binding_to_string(xcWidget window, int keywstate)
361 keybinding *ksearch;
362 char *retstr, *tmpstr;
363 Bool first = True;
365 retstr = (char *)malloc(1);
366 retstr[0] = '\0';
367 for (ksearch = keylist; ksearch != NULL; ksearch = ksearch->nextbinding) {
368 if (keywstate == ksearch->keywstate) {
369 if (ksearch->window == ALL_WINDOWS || ksearch->window == window) {
370 tmpstr = function_names[ksearch->function];
371 if (tmpstr != NULL) {
372 retstr = (char *)realloc(retstr, strlen(retstr) + strlen(tmpstr) +
373 ((first) ? 1 : 3));
374 if (!first) strcat(retstr, ", ");
375 strcat(retstr, tmpstr);
377 first = False;
381 if (retstr[0] == '\0') {
382 retstr = (char *)realloc(retstr, 10);
383 strcat(retstr, "<unbound>");
385 return(retstr);
388 /*--------------------------------------------------------------*/
389 /* Return an allocated string name of the function that */
390 /* is bound to the indicated key state for the indicated */
391 /* window and compattible with the current event mode. */
392 /*--------------------------------------------------------------*/
394 char *compat_key_to_string(xcWidget window, int keywstate)
396 char *retstr, *tmpstr;
397 int function;
399 function = boundfunction(window, keywstate, NULL);
400 tmpstr = func_to_string(function);
402 /* Pass back "Nothing" for unbound key states, since a */
403 /* wrapper script may want to use the result as an action. */
405 if (tmpstr == NULL) {
406 retstr = (char *)malloc(8);
407 strcpy(retstr, "Nothing");
409 else
410 retstr = strdup(tmpstr);
412 return(retstr);
415 /*--------------------------------------------------------------*/
416 /* Convert a key sym into a string */
417 /*--------------------------------------------------------------*/
419 char *key_to_string(int keywstate)
421 static char hex[17] = "0123456789ABCDEF";
422 char *kptr, *str = NULL;
423 KeySym ks;
424 int kmod;
426 ks = keywstate & 0xffff;
427 kmod = keywstate >> 16;
428 #if defined(XC_WIN32) && defined(TCL_WRAPPER)
429 if (ks != NoSymbol) str = XKeysymToString_TkW32(ks);
430 #else
431 if (ks != NoSymbol) str = XKeysymToString(ks);
432 #endif
434 kptr = (char *)malloc(32);
435 kptr[0] = '\0';
436 if (kmod & Mod1Mask) strcat(kptr, "Alt_");
437 if (kmod & Mod4Mask) strcat(kptr, "Hold_");
438 if (kmod & ControlMask) strcat(kptr, "Control_");
439 if (kmod & LockMask) strcat(kptr, "Capslock_");
440 if (kmod & ShiftMask) strcat(kptr, "Shift_");
442 if (str != NULL) {
443 /* 33 is length of all modifiers concatenated + 1 */
444 kptr = (char *)realloc(kptr, strlen(str) + 33);
445 strcat(kptr, str);
447 else {
448 kptr = (char *)realloc(kptr, 40);
449 if (kmod & Button1Mask) strcat(kptr, "Button1");
450 else if (kmod & Button2Mask) strcat(kptr, "Button2");
451 else if (kmod & Button3Mask) strcat(kptr, "Button3");
452 else if (kmod & Button4Mask) strcat(kptr, "Button4");
453 else if (kmod & Button5Mask) strcat(kptr, "Button5");
454 else {
455 kptr[0] = '0';
456 kptr[1] = 'x';
457 kptr[2] = hex[(kmod & 0xf)];
458 kptr[3] = hex[(keywstate & 0xf000) >> 12];
459 kptr[4] = hex[(keywstate & 0x0f00) >> 8];
460 kptr[5] = hex[(keywstate & 0x00f0) >> 4];
461 kptr[6] = hex[(keywstate & 0x000f) ];
462 kptr[7] = '\0';
465 return kptr;
468 /*--------------------------------------------------------------*/
469 /* Print the bindings for the (polygon) edit functions */
470 /*--------------------------------------------------------------*/
472 void printeditbindings()
474 char *tstr;
476 _STR2[0] = '\0';
478 tstr = key_to_string(firstbinding(areawin->area, XCF_Edit_Delete));
479 strcat(_STR2, tstr);
480 strcat(_STR2, "=");
481 strcat(_STR2, func_to_string(XCF_Edit_Delete));
482 strcat(_STR2, ", ");
483 free(tstr);
485 tstr = key_to_string(firstbinding(areawin->area, XCF_Edit_Insert));
486 strcat(_STR2, tstr);
487 strcat(_STR2, "=");
488 strcat(_STR2, func_to_string(XCF_Edit_Insert));
489 strcat(_STR2, ", ");
490 free(tstr);
492 tstr = key_to_string(firstbinding(areawin->area, XCF_Edit_Param));
493 strcat(_STR2, tstr);
494 strcat(_STR2, "=");
495 strcat(_STR2, func_to_string(XCF_Edit_Param));
496 strcat(_STR2, ", ");
497 free(tstr);
499 tstr = key_to_string(firstbinding(areawin->area, XCF_Edit_Next));
500 strcat(_STR2, tstr);
501 strcat(_STR2, "=");
502 strcat(_STR2, func_to_string(XCF_Edit_Next));
503 free(tstr);
505 /* Use W3printf(). In the Tcl version, this prints to the */
506 /* message window but does not duplicate the output to */
507 /* stdout, where it would be just an annoyance. */
509 W3printf("%s", _STR2);
512 /*--------------------------------------------------------------*/
513 /* Remove a key binding from the list */
514 /* */
515 /* Note: This routine needs to correctly handle ALL_WINDOWS */
516 /* bindings that shadow specific window bindings. */
517 /*--------------------------------------------------------------*/
519 int remove_binding(xcWidget window, int keywstate, int function)
521 keybinding *ksearch, *klast = NULL;
523 for (ksearch = keylist; ksearch != NULL; ksearch = ksearch->nextbinding) {
524 if (window == ALL_WINDOWS || window == ksearch->window) {
525 if ((function == ksearch->function)
526 && (keywstate == ksearch->keywstate)) {
527 if (klast == NULL)
528 keylist = ksearch->nextbinding;
529 else
530 klast->nextbinding = ksearch->nextbinding;
531 free(ksearch);
532 return 0;
535 klast = ksearch;
537 return -1;
540 /*--------------------------------------------------------------*/
541 /* Wrapper for remove_binding */
542 /*--------------------------------------------------------------*/
544 void remove_keybinding(xcWidget window, const char *keystring, const char *fstring)
546 int function = string_to_func(fstring, NULL);
547 int keywstate = string_to_key(keystring);
549 if ((function < 0) || (remove_binding(window, keywstate, function) < 0)) {
550 Wprintf("Key binding \'%s\' to \'%s\' does not exist in list.",
551 keystring, fstring);
555 /*--------------------------------------------------------------*/
556 /* Add a key binding to the list */
557 /*--------------------------------------------------------------*/
559 int add_vbinding(xcWidget window, int keywstate, int function, short value)
561 keybinding *newbinding;
563 /* If key is already bound to the function, ignore it */
565 if (isbound(window, keywstate, function, value)) return 1;
567 /* Add the new key binding */
569 newbinding = (keybinding *)malloc(sizeof(keybinding));
570 newbinding->window = window;
571 newbinding->keywstate = keywstate;
572 newbinding->function = function;
573 newbinding->value = value;
574 newbinding->nextbinding = keylist;
575 keylist = newbinding;
576 return 0;
579 /*--------------------------------------------------------------*/
580 /* Wrapper function for key binding without any values */
581 /*--------------------------------------------------------------*/
583 int add_binding(xcWidget window, int keywstate, int function)
585 return add_vbinding(window, keywstate, function, (short)-1);
588 /*--------------------------------------------------------------*/
589 /* Wrapper function for key binding with function as string */
590 /*--------------------------------------------------------------*/
592 int add_keybinding(xcWidget window, const char *keystring, const char *fstring)
594 short value = -1;
595 int function = string_to_func(fstring, &value);
596 int keywstate = string_to_key(keystring);
598 if (function < 0)
599 return -1;
600 else
601 return add_vbinding(window, keywstate, function, value);
604 /*--------------------------------------------------------------*/
605 /* Create list of default key bindings. */
606 /* These are conditional upon any bindings set in the startup */
607 /* file .xcircuitrc. */
608 /*--------------------------------------------------------------*/
610 void default_keybindings()
612 add_vbinding(ALL_WINDOWS, XK_1, XCF_Page, 1);
613 add_vbinding(ALL_WINDOWS, XK_2, XCF_Page, 2);
614 add_vbinding(ALL_WINDOWS, XK_3, XCF_Page, 3);
615 add_vbinding(ALL_WINDOWS, XK_4, XCF_Page, 4);
616 add_vbinding(ALL_WINDOWS, XK_5, XCF_Page, 5);
617 add_vbinding(ALL_WINDOWS, XK_6, XCF_Page, 6);
618 add_vbinding(ALL_WINDOWS, XK_7, XCF_Page, 7);
619 add_vbinding(ALL_WINDOWS, XK_8, XCF_Page, 8);
620 add_vbinding(ALL_WINDOWS, XK_9, XCF_Page, 9);
621 add_vbinding(ALL_WINDOWS, XK_0, XCF_Page, 10);
623 add_vbinding(ALL_WINDOWS, SHIFT | XK_KP_1, XCF_Anchor, 0);
624 add_vbinding(ALL_WINDOWS, SHIFT | XK_KP_2, XCF_Anchor, 1);
625 add_vbinding(ALL_WINDOWS, SHIFT | XK_KP_3, XCF_Anchor, 2);
626 add_vbinding(ALL_WINDOWS, SHIFT | XK_KP_4, XCF_Anchor, 3);
627 add_vbinding(ALL_WINDOWS, SHIFT | XK_KP_5, XCF_Anchor, 4);
628 add_vbinding(ALL_WINDOWS, SHIFT | XK_KP_6, XCF_Anchor, 5);
629 add_vbinding(ALL_WINDOWS, SHIFT | XK_KP_7, XCF_Anchor, 6);
630 add_vbinding(ALL_WINDOWS, SHIFT | XK_KP_8, XCF_Anchor, 7);
631 add_vbinding(ALL_WINDOWS, SHIFT | XK_KP_9, XCF_Anchor, 8);
633 add_vbinding(ALL_WINDOWS, XK_KP_End, XCF_Anchor, 0);
634 add_vbinding(ALL_WINDOWS, XK_KP_Down, XCF_Anchor, 1);
635 add_vbinding(ALL_WINDOWS, XK_KP_Next, XCF_Anchor, 2);
636 add_vbinding(ALL_WINDOWS, XK_KP_Left, XCF_Anchor, 3);
637 add_vbinding(ALL_WINDOWS, XK_KP_Begin, XCF_Anchor, 4);
638 add_vbinding(ALL_WINDOWS, XK_KP_Right, XCF_Anchor, 5);
639 add_vbinding(ALL_WINDOWS, XK_KP_Home, XCF_Anchor, 6);
640 add_vbinding(ALL_WINDOWS, XK_KP_Up, XCF_Anchor, 7);
641 add_vbinding(ALL_WINDOWS, XK_KP_Prior, XCF_Anchor, 8);
643 add_binding(ALL_WINDOWS, XK_Delete, XCF_Text_Delete);
644 add_binding(ALL_WINDOWS, ALT | XK_Delete, XCF_Text_Delete_Param);
645 add_binding(ALL_WINDOWS, XK_Return, XCF_Text_Return);
646 add_binding(ALL_WINDOWS, BUTTON1, XCF_Text_Return);
647 add_binding(ALL_WINDOWS, XK_BackSpace, XCF_Text_Delete);
648 add_binding(ALL_WINDOWS, XK_Left, XCF_Text_Left);
649 add_binding(ALL_WINDOWS, XK_Right, XCF_Text_Right);
650 add_binding(ALL_WINDOWS, XK_Up, XCF_Text_Up);
651 add_binding(ALL_WINDOWS, XK_Down, XCF_Text_Down);
652 add_binding(ALL_WINDOWS, ALT | XK_x, XCF_Text_Split);
653 add_binding(ALL_WINDOWS, XK_Home, XCF_Text_Home);
654 add_binding(ALL_WINDOWS, XK_End, XCF_Text_End);
655 add_binding(ALL_WINDOWS, XK_Tab, XCF_TabForward);
656 add_binding(ALL_WINDOWS, SHIFT | XK_Tab, XCF_TabBackward);
657 #ifdef XK_ISO_Left_Tab
658 add_binding(ALL_WINDOWS, SHIFT | XK_ISO_Left_Tab, XCF_TabBackward);
659 #endif
660 add_binding(ALL_WINDOWS, ALT | XK_Tab, XCF_TabStop);
661 add_binding(ALL_WINDOWS, XK_KP_Add, XCF_Superscript);
662 add_binding(ALL_WINDOWS, XK_KP_Subtract, XCF_Subscript);
663 add_binding(ALL_WINDOWS, XK_KP_Enter, XCF_Normalscript);
664 add_vbinding(ALL_WINDOWS, ALT | XK_f, XCF_Font, 1000);
665 add_binding(ALL_WINDOWS, ALT | XK_b, XCF_Boldfont);
666 add_binding(ALL_WINDOWS, ALT | XK_i, XCF_Italicfont);
667 add_binding(ALL_WINDOWS, ALT | XK_n, XCF_Normalfont);
668 add_binding(ALL_WINDOWS, ALT | XK_u, XCF_Underline);
669 add_binding(ALL_WINDOWS, ALT | XK_o, XCF_Overline);
670 add_binding(ALL_WINDOWS, ALT | XK_e, XCF_ISO_Encoding);
671 add_binding(ALL_WINDOWS, ALT | XK_Return, XCF_Linebreak);
672 add_binding(ALL_WINDOWS, ALT | XK_h, XCF_Halfspace);
673 add_binding(ALL_WINDOWS, ALT | XK_q, XCF_Quarterspace);
674 #ifndef TCL_WRAPPER
675 add_binding(ALL_WINDOWS, ALT | XK_p, XCF_Parameter);
676 #endif
677 add_binding(ALL_WINDOWS, XK_backslash, XCF_Special);
678 add_binding(ALL_WINDOWS, ALT | XK_c, XCF_Special);
679 add_binding(ALL_WINDOWS, XK_p, XCF_Edit_Param);
680 add_binding(ALL_WINDOWS, XK_d, XCF_Edit_Delete);
681 add_binding(ALL_WINDOWS, XK_Delete, XCF_Edit_Delete);
682 add_binding(ALL_WINDOWS, XK_i, XCF_Edit_Insert);
683 add_binding(ALL_WINDOWS, XK_Insert, XCF_Edit_Insert);
684 add_binding(ALL_WINDOWS, XK_e, XCF_Edit_Next);
685 add_binding(ALL_WINDOWS, BUTTON1, XCF_Edit_Next);
686 add_binding(ALL_WINDOWS, XK_A, XCF_Attach);
687 add_binding(ALL_WINDOWS, XK_V, XCF_Virtual);
688 add_binding(ALL_WINDOWS, XK_l, XCF_Next_Library);
689 add_binding(ALL_WINDOWS, XK_L, XCF_Library_Directory);
690 add_binding(ALL_WINDOWS, XK_c, XCF_Library_Copy);
691 add_binding(ALL_WINDOWS, XK_E, XCF_Library_Edit);
692 add_binding(ALL_WINDOWS, XK_e, XCF_Library_Edit);
693 add_binding(ALL_WINDOWS, XK_D, XCF_Library_Delete);
694 add_binding(ALL_WINDOWS, XK_C, XCF_Library_Duplicate);
695 add_binding(ALL_WINDOWS, XK_H, XCF_Library_Hide);
696 add_binding(ALL_WINDOWS, XK_V, XCF_Library_Virtual);
697 add_binding(ALL_WINDOWS, XK_M, XCF_Library_Move);
698 add_binding(ALL_WINDOWS, XK_m, XCF_Library_Move);
699 add_binding(ALL_WINDOWS, XK_P, XCF_Page_Directory);
700 add_binding(ALL_WINDOWS, XK_less, XCF_Library_Pop);
701 add_binding(ALL_WINDOWS, HOLD | BUTTON1, XCF_Library_Pop);
702 add_binding(ALL_WINDOWS, XK_h, XCF_Help);
703 add_binding(ALL_WINDOWS, XK_question, XCF_Help);
704 add_binding(ALL_WINDOWS, XK_space, XCF_Redraw);
705 add_binding(ALL_WINDOWS, XK_Redo, XCF_Redraw);
706 add_binding(ALL_WINDOWS, XK_Undo, XCF_Redraw);
707 add_binding(ALL_WINDOWS, XK_Home, XCF_View);
708 add_binding(ALL_WINDOWS, XK_v, XCF_View);
709 add_binding(ALL_WINDOWS, XK_Z, XCF_Zoom_In);
710 add_binding(ALL_WINDOWS, XK_z, XCF_Zoom_Out);
711 add_vbinding(ALL_WINDOWS, XK_p, XCF_Pan, 0);
712 add_binding(ALL_WINDOWS, XK_plus, XCF_Double_Snap);
713 add_binding(ALL_WINDOWS, XK_minus, XCF_Halve_Snap);
714 add_vbinding(ALL_WINDOWS, XK_Left, XCF_Pan, 1);
715 add_vbinding(ALL_WINDOWS, XK_Right, XCF_Pan, 2);
716 add_vbinding(ALL_WINDOWS, XK_Up, XCF_Pan, 3);
717 add_vbinding(ALL_WINDOWS, XK_Down, XCF_Pan, 4);
718 add_binding(ALL_WINDOWS, XK_W, XCF_Write);
719 add_vbinding(ALL_WINDOWS, XK_O, XCF_Rotate, -5);
720 add_vbinding(ALL_WINDOWS, XK_o, XCF_Rotate, 5);
721 add_vbinding(ALL_WINDOWS, XK_R, XCF_Rotate, -15);
722 add_vbinding(ALL_WINDOWS, XK_r, XCF_Rotate, 15);
723 add_binding(ALL_WINDOWS, XK_f, XCF_Flip_X);
724 add_binding(ALL_WINDOWS, XK_F, XCF_Flip_Y);
725 add_binding(ALL_WINDOWS, XK_S, XCF_Snap);
726 add_binding(ALL_WINDOWS, XK_less, XCF_Pop);
727 add_binding(ALL_WINDOWS, XK_greater, XCF_Push);
728 add_binding(ALL_WINDOWS, XK_Delete, XCF_Delete);
729 add_binding(ALL_WINDOWS, XK_d, XCF_Delete);
730 add_binding(ALL_WINDOWS, XK_F19, XCF_Select);
731 add_binding(ALL_WINDOWS, XK_b, XCF_Box);
732 add_binding(ALL_WINDOWS, XK_a, XCF_Arc);
733 add_binding(ALL_WINDOWS, XK_t, XCF_Text);
734 add_binding(ALL_WINDOWS, XK_X, XCF_Exchange);
735 add_binding(ALL_WINDOWS, XK_c, XCF_Copy);
736 add_binding(ALL_WINDOWS, XK_j, XCF_Join);
737 add_binding(ALL_WINDOWS, XK_J, XCF_Unjoin);
738 add_binding(ALL_WINDOWS, XK_s, XCF_Spline);
739 add_binding(ALL_WINDOWS, XK_e, XCF_Edit);
740 add_binding(ALL_WINDOWS, XK_u, XCF_Undo);
741 add_binding(ALL_WINDOWS, XK_U, XCF_Redo);
742 add_binding(ALL_WINDOWS, XK_M, XCF_Select_Save);
743 add_binding(ALL_WINDOWS, XK_m, XCF_Select_Save);
744 add_binding(ALL_WINDOWS, XK_x, XCF_Unselect);
745 add_binding(ALL_WINDOWS, XK_bar, XCF_Dashed);
746 add_binding(ALL_WINDOWS, XK_colon, XCF_Dotted);
747 add_binding(ALL_WINDOWS, XK_underscore, XCF_Solid);
748 add_binding(ALL_WINDOWS, XK_percent, XCF_Prompt);
749 add_binding(ALL_WINDOWS, XK_period, XCF_Dot);
750 #ifndef TCL_WRAPPER
751 /* TCL_WRAPPER version req's binding to specific windows */
752 add_binding(ALL_WINDOWS, BUTTON1, XCF_Wire);
753 #endif
754 add_binding(ALL_WINDOWS, XK_w, XCF_Wire);
755 add_binding(ALL_WINDOWS, CTRL | ALT | XK_q, XCF_Exit);
756 add_binding(ALL_WINDOWS, HOLD | BUTTON1, XCF_Move);
757 add_binding(ALL_WINDOWS, BUTTON1, XCF_Continue_Element);
758 add_binding(ALL_WINDOWS, BUTTON1, XCF_Continue_Copy);
759 add_binding(ALL_WINDOWS, BUTTON1, XCF_Finish);
760 add_binding(ALL_WINDOWS, XK_Escape, XCF_Cancel);
761 add_binding(ALL_WINDOWS, ALT | XK_r, XCF_Rescale);
762 add_binding(ALL_WINDOWS, ALT | XK_s, XCF_SnapTo);
763 add_binding(ALL_WINDOWS, ALT | XK_q, XCF_Netlist);
764 add_binding(ALL_WINDOWS, XK_slash, XCF_Swap);
765 add_binding(ALL_WINDOWS, XK_T, XCF_Pin_Label);
766 add_binding(ALL_WINDOWS, XK_G, XCF_Pin_Global);
767 add_binding(ALL_WINDOWS, XK_I, XCF_Info_Label);
768 add_binding(ALL_WINDOWS, ALT | XK_w, XCF_Connectivity);
770 /* These are for test purposes only. Menu selection is */
771 /* preferred. */
773 /* add_binding(ALL_WINDOWS, ALT | XK_d, XCF_Sim); */
774 /* add_binding(ALL_WINDOWS, ALT | XK_a, XCF_SPICE); */
775 /* add_binding(ALL_WINDOWS, ALT | XK_f, XCF_SPICEflat); */
776 /* add_binding(ALL_WINDOWS, ALT | XK_p, XCF_PCB); */
778 /* Avoid spurious Num_Lock messages */
779 add_binding(ALL_WINDOWS, XK_Num_Lock, XCF_Nothing);
781 /* 2-button vs. 3-button mouse bindings (set with -2 */
782 /* commandline option; 3-button bindings default) */
784 if (pressmode == 1) {
785 add_binding(ALL_WINDOWS, BUTTON3, XCF_Text_Return);
786 add_binding(ALL_WINDOWS, BUTTON3, XCF_Select);
787 add_binding(ALL_WINDOWS, HOLD | BUTTON3, XCF_SelectBox);
788 add_binding(ALL_WINDOWS, BUTTON3, XCF_Finish_Element);
789 add_binding(ALL_WINDOWS, BUTTON3, XCF_Finish_Copy);
791 add_binding(ALL_WINDOWS, XK_BackSpace, XCF_Cancel_Last);
792 add_binding(ALL_WINDOWS, XK_BackSpace, XCF_Cancel);
794 else {
795 add_binding(ALL_WINDOWS, BUTTON2, XCF_Text_Return);
796 add_binding(ALL_WINDOWS, SHIFT | BUTTON1, XCF_Text_Return);
797 add_binding(ALL_WINDOWS, BUTTON2, XCF_Select);
798 add_binding(ALL_WINDOWS, SHIFT | BUTTON1, XCF_Select);
799 add_binding(ALL_WINDOWS, HOLD | BUTTON2, XCF_SelectBox);
800 add_binding(ALL_WINDOWS, SHIFT | HOLD | BUTTON1, XCF_Select);
801 add_binding(ALL_WINDOWS, BUTTON2, XCF_Finish_Element);
802 add_binding(ALL_WINDOWS, SHIFT | BUTTON1, XCF_Finish_Element);
803 add_binding(ALL_WINDOWS, BUTTON2, XCF_Finish_Copy);
804 add_binding(ALL_WINDOWS, SHIFT | BUTTON1, XCF_Finish_Copy);
805 add_binding(ALL_WINDOWS, BUTTON3, XCF_Cancel_Last);
806 add_binding(ALL_WINDOWS, BUTTON3, XCF_Cancel);
810 #ifndef TCL_WRAPPER
811 /*----------------------------------------------*/
812 /* Mode-setting rebindings (non-Tcl version) */
813 /*----------------------------------------------*/
815 static int button1mode = XCF_Wire;
817 /*--------------------------------------------------------------*/
818 /* Re-bind BUTTON1 to the indicated function and optional value */
819 /*--------------------------------------------------------------*/
821 void mode_rebinding(int newmode, int newvalue)
823 xcWidget window = areawin->area;
825 remove_binding(window, BUTTON1, button1mode);
826 add_vbinding(window, BUTTON1, newmode, (short)newvalue);
827 button1mode = newmode;
828 toolcursor(newmode);
831 /*--------------------------------------------------------------*/
832 /* Execute the function associated with the indicated BUTTON1 */
833 /* mode, but return the keybinding to its previous state. */
834 /*--------------------------------------------------------------*/
836 void mode_tempbinding(int newmode, int newvalue)
838 short saveval;
839 XPoint cpos;
840 xcWidget window = areawin->area;
842 if (boundfunction(window, BUTTON1, &saveval) == button1mode) {
843 remove_binding(window, BUTTON1, button1mode);
844 add_vbinding(window, BUTTON1, newmode, (short)newvalue);
845 cpos = UGetCursor();
846 eventdispatch(BUTTON1, (int)cpos.x, (int)cpos.y);
847 remove_binding(window, BUTTON1, newmode);
848 add_vbinding(window, BUTTON1, button1mode, saveval);
850 else
851 fprintf(stderr, "Error: No such button1 binding %s\n",
852 func_to_string(button1mode));
855 #endif /* TCL_WRAPPER */
857 #undef ALT
858 #undef CTRL
859 #undef CAPSLOCK
860 #undef SHIFT
861 #undef BUTTON1
862 #undef BUTTON2
863 #undef BUTTON3
865 /*--------------------------------------------------------------*/