13 #include "xincludes.h"
21 #include "../hidint.h"
22 #include "hid/common/hid_resource.h"
29 #ifdef HAVE_LIBDMALLOC
36 /* Common value for systems that don't define it. */
45 #define stdarg(t,v) XtSetArg(args[n], t, v), n++
47 static void note_accelerator (char *acc
, Resource
* node
);
48 static void note_widget_flag (Widget w
, char *type
, char *name
);
50 static const char getxy_syntax
[] =
53 static const char getxy_help
[] =
56 /* %start-doc actions GetXY
58 Prompts the user for a coordinate, if one is not already selected.
63 GetXY (int argc
, char **argv
, int x
, int y
)
68 static const char debug_syntax
[] =
71 static const char debug_help
[] =
74 /* %start-doc actions Debug
76 This action exists to help debug scripts; it simply prints all its
81 static const char debugxy_syntax
[] =
84 static const char debugxy_help
[] =
85 "Debug action, with coordinates";
87 /* %start-doc actions DebugXY
89 Like @code{Debug}, but requires a coordinate. If the user hasn't yet
90 indicated a location on the board, the user will be prompted to click
96 Debug (int argc
, char **argv
, int x
, int y
)
100 for (i
= 0; i
< argc
; i
++)
101 printf (" [%d] `%s'", i
, argv
[i
]);
102 printf (" x,y %d,%d\n", x
, y
);
106 static const char return_syntax
[] =
109 static const char return_help
[] =
110 "Simulate a passing or failing action.";
112 /* %start-doc actions Return
114 This is for testing. If passed a 0, does nothing and succeeds. If
115 passed a 1, does nothing but pretends to fail.
120 Return (int argc
, char **argv
, int x
, int y
)
122 return atoi (argv
[0]);
125 static const char dumpkeys_syntax
[] =
128 static const char dumpkeys_help
[] =
129 "Dump Lesstif key bindings.";
131 /* %start-doc actions DumpKeys
133 Causes the list of key bindings (from @code{pcb-menu.res}) to be
134 dumped to stdout. This is most useful when invoked from the command
138 pcb --action-string DumpKeys
143 static int do_dump_keys
= 0;
145 DumpKeys (int argc
, char **argv
, int x
, int y
)
151 /*-----------------------------------------------------------------------------*/
153 #define LB_SILK (MAX_LAYER+0)
154 #define LB_RATS (MAX_LAYER+1)
155 #define LB_NUMPICK (LB_RATS+1)
157 #define LB_PINS (MAX_LAYER+2)
158 #define LB_VIAS (MAX_LAYER+3)
159 #define LB_BACK (MAX_LAYER+4)
160 #define LB_MASK (MAX_LAYER+5)
161 #define LB_NUM (MAX_LAYER+6)
169 static LayerButtons
*layer_button_list
= 0;
170 static int num_layer_buttons
= 0;
171 static int fg_colors
[LB_NUM
];
174 extern Widget lesstif_m_layer
;
177 LayersChanged (int argc
, char **argv
, int x
, int y
)
183 if (!layer_button_list
)
185 if (PCB
&& PCB
->Data
)
187 DataType
*d
= PCB
->Data
;
188 for (i
= 0; i
< MAX_LAYER
; i
++)
189 fg_colors
[i
] = lesstif_parse_color (d
->Layer
[i
].Color
);
190 fg_colors
[LB_SILK
] = lesstif_parse_color (PCB
->ElementColor
);
191 fg_colors
[LB_RATS
] = lesstif_parse_color (PCB
->RatColor
);
192 fg_colors
[LB_PINS
] = lesstif_parse_color (PCB
->PinColor
);
193 fg_colors
[LB_VIAS
] = lesstif_parse_color (PCB
->ViaColor
);
195 lesstif_parse_color (PCB
->InvisibleObjectsColor
);
196 fg_colors
[LB_MASK
] = lesstif_parse_color (PCB
->MaskColor
);
197 bg_color
= lesstif_parse_color (Settings
.BackgroundColor
);
201 for (i
= 0; i
< MAX_LAYER
; i
++)
202 fg_colors
[i
] = lesstif_parse_color (Settings
.LayerColor
[i
]);
203 fg_colors
[LB_SILK
] = lesstif_parse_color (Settings
.ElementColor
);
204 fg_colors
[LB_RATS
] = lesstif_parse_color (Settings
.RatColor
);
205 fg_colors
[LB_PINS
] = lesstif_parse_color (Settings
.PinColor
);
206 fg_colors
[LB_VIAS
] = lesstif_parse_color (Settings
.ViaColor
);
208 lesstif_parse_color (Settings
.InvisibleObjectsColor
);
209 fg_colors
[LB_MASK
] = lesstif_parse_color (Settings
.MaskColor
);
210 bg_color
= lesstif_parse_color (Settings
.BackgroundColor
);
214 current_layer
= LB_RATS
;
215 else if (PCB
->SilkActive
)
216 current_layer
= LB_SILK
;
218 current_layer
= LayerStack
[0];
220 for (l
= 0; l
< num_layer_buttons
; l
++)
222 LayerButtons
*lb
= layer_button_list
+ l
;
223 for (i
= 0; i
< (lb
->is_pick
? LB_NUMPICK
: LB_NUM
); i
++)
228 set
= PCB
->ElementOn
;
240 set
= PCB
->InvisibleObjectsOn
;
243 set
= TEST_FLAG (SHOWMASKFLAG
, PCB
);
245 default: /* layers */
246 set
= PCB
->Data
->Layer
[i
].On
;
251 if (i
< MAX_LAYER
&& PCB
->Data
->Layer
[i
].Name
)
253 XmString s
= XmStringCreateLocalized (PCB
->Data
->Layer
[i
].Name
);
254 stdarg (XmNlabelString
, s
);
260 stdarg (XmNforeground
, bg_color
);
261 stdarg (XmNbackground
, fg_colors
[i
]);
265 stdarg (XmNforeground
, fg_colors
[i
]);
266 stdarg (XmNbackground
, bg_color
);
268 stdarg (XmNset
, set
);
272 stdarg (XmNforeground
, bg_color
);
273 stdarg (XmNbackground
, fg_colors
[i
]);
274 stdarg (XmNset
, current_layer
== i
? True
: False
);
276 XtSetValues (lb
->w
[i
], args
, n
);
278 if (i
>= max_copper_layer
&& i
< MAX_LAYER
)
279 XtUnmanageChild(lb
->w
[i
]);
281 XtManageChild(lb
->w
[i
]);
286 switch (current_layer
)
295 name
= PCB
->Data
->Layer
[current_layer
].Name
;
299 stdarg (XmNbackground
, fg_colors
[current_layer
]);
300 stdarg (XmNforeground
, bg_color
);
301 stdarg (XmNlabelString
, XmStringCreateLocalized (name
));
302 XtSetValues (lesstif_m_layer
, args
, n
);
305 lesstif_update_layer_groups ();
311 show_one_layer_button (int layer
, int set
)
317 stdarg (XmNforeground
, bg_color
);
318 stdarg (XmNbackground
, fg_colors
[layer
]);
322 stdarg (XmNforeground
, fg_colors
[layer
]);
323 stdarg (XmNbackground
, bg_color
);
325 stdarg (XmNset
, set
);
327 for (l
= 0; l
< num_layer_buttons
; l
++)
329 LayerButtons
*lb
= layer_button_list
+ l
;
331 XtSetValues (lb
->w
[layer
], args
, n
);
336 layer_button_callback (Widget w
, int layer
, XmPushButtonCallbackStruct
* pbcs
)
342 set
= PCB
->ElementOn
= !PCB
->ElementOn
;
343 PCB
->Data
->SILKLAYER
.On
= set
;
344 PCB
->Data
->BACKSILKLAYER
.On
= set
;
347 set
= PCB
->RatOn
= !PCB
->RatOn
;
350 set
= PCB
->PinOn
= !PCB
->PinOn
;
353 set
= PCB
->ViaOn
= !PCB
->ViaOn
;
356 set
= PCB
->InvisibleObjectsOn
= !PCB
->InvisibleObjectsOn
;
359 TOGGLE_FLAG (SHOWMASKFLAG
, PCB
);
360 set
= TEST_FLAG (SHOWMASKFLAG
, PCB
);
362 default: /* layers */
363 set
= PCB
->Data
->Layer
[layer
].On
= !PCB
->Data
->Layer
[layer
].On
;
367 show_one_layer_button (layer
, set
);
368 if (layer
< max_copper_layer
)
371 int group
= GetLayerGroupNumberByNumber (layer
);
372 for (i
= 0; i
< PCB
->LayerGroups
.Number
[group
]; i
++)
374 l
= PCB
->LayerGroups
.Entries
[group
][i
];
375 if (l
!= layer
&& l
< max_copper_layer
)
377 show_one_layer_button (l
, set
);
378 PCB
->Data
->Layer
[l
].On
= set
;
382 lesstif_invalidate_all ();
386 layerpick_button_callback (Widget w
, int layer
,
387 XmPushButtonCallbackStruct
* pbcs
)
391 PCB
->RatDraw
= (layer
== LB_RATS
);
392 PCB
->SilkActive
= (layer
== LB_SILK
);
393 if (layer
< max_copper_layer
)
394 ChangeGroupVisibility (layer
, 1, 1);
395 for (l
= 0; l
< num_layer_buttons
; l
++)
397 LayerButtons
*lb
= layer_button_list
+ l
;
400 for (i
= 0; i
< LB_NUMPICK
; i
++)
401 XmToggleButtonSetState (lb
->w
[i
], layer
== i
, False
);
412 name
= PCB
->Data
->Layer
[layer
].Name
;
416 stdarg (XmNbackground
, fg_colors
[layer
]);
417 stdarg (XmNforeground
, bg_color
);
418 stdarg (XmNlabelString
, XmStringCreateLocalized (name
));
419 XtSetValues (lesstif_m_layer
, args
, n
);
420 lesstif_invalidate_all ();
423 static const char selectlayer_syntax
[] =
424 "SelectLayer(1..MAXLAYER|Silk|Rats)";
426 static const char selectlayer_help
[] =
427 "Select which layer is the current layer.";
429 /* %start-doc actions SelectLayer
431 The specified layer becomes the currently active layer. It is made
432 visible if it is not already visible
437 SelectLayer (int argc
, char **argv
, int x
, int y
)
442 if (strcasecmp (argv
[0], "silk") == 0)
444 else if (strcasecmp (argv
[0], "rats") == 0)
447 newl
= atoi (argv
[0]) - 1;
448 layerpick_button_callback (0, newl
, 0);
452 static const char toggleview_syntax
[] =
453 "ToggleView(1..MAXLAYER)\n"
454 "ToggleView(layername)\n"
455 "ToggleView(Silk|Rats|Pins|Vias|Mask|BackSide)";
457 static const char toggleview_help
[] =
458 "Toggle the visibility of the specified layer or layer group.";
460 /* %start-doc actions ToggleView
462 If you pass an integer, that layer is specified by index (the first
463 layer is @code{1}, etc). If you pass a layer name, that layer is
464 specified by name. When a layer is specified, the visibility of the
465 layer group containing that layer is toggled.
467 If you pass a special layer name, the visibility of those components
468 (silk, rats, etc) is toggled. Note that if you have a layer named
469 the same as a special layer, the layer is chosen over the special layer.
474 ToggleView (int argc
, char **argv
, int x
, int y
)
480 if (isdigit ((int) argv
[0][0]))
482 l
= atoi (argv
[0]) - 1;
483 layer_button_callback (0, l
, 0);
485 else if (strcmp (argv
[0], "Silk") == 0)
486 layer_button_callback (0, LB_SILK
, 0);
487 else if (strcmp (argv
[0], "Rats") == 0)
488 layer_button_callback (0, LB_RATS
, 0);
489 else if (strcmp (argv
[0], "Pins") == 0)
490 layer_button_callback (0, LB_PINS
, 0);
491 else if (strcmp (argv
[0], "Vias") == 0)
492 layer_button_callback (0, LB_VIAS
, 0);
493 else if (strcmp (argv
[0], "Mask") == 0)
494 layer_button_callback (0, LB_MASK
, 0);
495 else if (strcmp (argv
[0], "BackSide") == 0)
496 layer_button_callback (0, LB_BACK
, 0);
500 for (i
= 0; i
< max_copper_layer
+ 2; i
++)
501 if (strcmp (argv
[0], PCB
->Data
->Layer
[i
].Name
) == 0)
508 layer_button_callback (0, l
, 0);
514 insert_layerview_buttons (Widget menu
)
520 s
= num_layer_buttons
* sizeof (LayerButtons
);
521 if (layer_button_list
)
522 layer_button_list
= (LayerButtons
*) realloc (layer_button_list
, s
);
524 layer_button_list
= (LayerButtons
*) malloc (s
);
525 lb
= layer_button_list
+ num_layer_buttons
- 1;
527 for (i
= 0; i
< LB_NUM
; i
++)
529 static char namestr
[] = "Label ";
530 char *name
= namestr
;
551 name
= "Solder Mask";
555 if (i
< MAX_LAYER
&& i
< 9)
557 char buf
[20], av
[30];
560 sprintf (buf
, "Ctrl-%d", i
+ 1);
561 as
= XmStringCreateLocalized (buf
);
562 stdarg (XmNacceleratorText
, as
);
563 ar
= resource_create (0);
564 sprintf (av
, "ToggleView(%d)", i
+ 1);
565 resource_add_val (ar
, 0, strdup (av
), 0);
566 resource_add_val (ar
, 0, strdup (av
), 0);
568 sprintf (av
, "Ctrl<Key>%d", i
+ 1);
569 note_accelerator (av
, ar
);
570 stdarg (XmNmnemonic
, i
+ '1');
572 btn
= XmCreateToggleButton (menu
, name
, args
, n
);
574 XtAddCallback (btn
, XmNvalueChangedCallback
,
575 (XtCallbackProc
) layer_button_callback
, (XtPointer
) (size_t) i
);
579 note_widget_flag (btn
, XmNset
, "showmask");
582 LayersChanged (0, 0, 0, 0);
586 insert_layerpick_buttons (Widget menu
)
592 s
= num_layer_buttons
* sizeof (LayerButtons
);
593 if (layer_button_list
)
594 layer_button_list
= (LayerButtons
*) realloc (layer_button_list
, s
);
596 layer_button_list
= (LayerButtons
*) malloc (s
);
597 lb
= layer_button_list
+ num_layer_buttons
- 1;
599 for (i
= 0; i
< LB_NUMPICK
; i
++)
601 static char namestr
[] = "Label ";
602 char *name
= namestr
;
615 if (i
< MAX_LAYER
&& i
< 9)
617 char buf
[20], av
[30];
620 sprintf (buf
, "%d", i
+ 1);
621 as
= XmStringCreateLocalized (buf
);
622 stdarg (XmNacceleratorText
, as
);
623 ar
= resource_create (0);
627 strcpy (av
, "SelectLayer(Silk)");
630 strcpy (av
, "SelectLayer(Rats)");
633 sprintf (av
, "SelectLayer(%d)", i
+ 1);
636 resource_add_val (ar
, 0, strdup (av
), 0);
637 resource_add_val (ar
, 0, strdup (av
), 0);
639 sprintf (av
, "<Key>%d", i
+ 1);
640 note_accelerator (av
, ar
);
641 stdarg (XmNmnemonic
, i
+ '1');
643 stdarg (XmNindicatorType
, XmONE_OF_MANY
);
644 btn
= XmCreateToggleButton (menu
, name
, args
, n
);
646 XtAddCallback (btn
, XmNvalueChangedCallback
,
647 (XtCallbackProc
) layerpick_button_callback
,
648 (XtPointer
) (size_t) i
);
652 LayersChanged (0, 0, 0, 0);
655 /*-----------------------------------------------------------------------------*/
660 const char *flagname
;
665 static WidgetFlagType
*wflags
= 0;
666 static int n_wflags
= 0;
667 static int max_wflags
= 0;
670 note_widget_flag (Widget w
, char *type
, char *name
)
672 if (n_wflags
>= max_wflags
)
675 wflags
= realloc (wflags
, max_wflags
* sizeof (WidgetFlagType
));
677 wflags
[n_wflags
].w
= w
;
678 wflags
[n_wflags
].flagname
= name
;
679 wflags
[n_wflags
].oldval
= -1;
680 wflags
[n_wflags
].xres
= type
;
685 lesstif_update_widget_flags ()
689 for (i
= 0; i
< n_wflags
; i
++)
691 int v
= hid_get_flag (wflags
[i
].flagname
);
693 XtSetArg (args
[0], wflags
[i
].xres
, v
? 1 : 0);
694 XtSetValues (wflags
[i
].w
, args
, 1);
695 wflags
[i
].oldval
= v
;
699 /*-----------------------------------------------------------------------------*/
701 HID_Action lesstif_menu_action_list
[] = {
702 {"DumpKeys", 0, DumpKeys
,
703 dumpkeys_help
, dumpkeys_syntax
},
705 debug_help
, debug_syntax
},
706 {"DebugXY", "Click X,Y for Debug", Debug
,
707 debugxy_help
, debugxy_syntax
},
709 getxy_help
, getxy_syntax
},
710 {"Return", 0, Return
,
711 return_help
, return_syntax
},
712 {"LayersChanged", 0, LayersChanged
,
713 layerschanged_help
, layerschanged_syntax
},
714 {"ToggleView", 0, ToggleView
,
715 toggleview_help
, toggleview_syntax
},
716 {"SelectLayer", 0, SelectLayer
,
717 selectlayer_help
, selectlayer_syntax
}
720 REGISTER_ACTIONS (lesstif_menu_action_list
)
724 do_color (char *value
, char *which
)
727 if (XParseColor (display
, cmap
, value
, &color
))
728 if (XAllocColor (display
, cmap
, &color
))
730 stdarg (which
, color
.pixel
);
735 typedef struct ToggleItem
737 struct ToggleItem
*next
;
740 XtCallbackProc callback
;
743 static ToggleItem
*toggle_items
= 0;
745 static int need_xy
= 0, have_xy
= 0, action_x
, action_y
;
748 radio_callback (Widget toggle
, ToggleItem
* me
,
749 XmToggleButtonCallbackStruct
* cbs
)
751 if (!cbs
->set
) /* uh uh, can't turn it off */
752 XmToggleButtonSetState (toggle
, 1, 0);
756 for (ti
= toggle_items
; ti
; ti
= ti
->next
)
757 if (strcmp (me
->group
, ti
->group
) == 0)
759 if (me
->item
== ti
->item
|| strcmp (me
->item
, ti
->item
) == 0)
760 XmToggleButtonSetState (ti
->w
, 1, 0);
762 XmToggleButtonSetState (ti
->w
, 0, 0);
764 me
->callback (toggle
, me
->node
, cbs
);
769 lesstif_button_event (Widget w
, XEvent
* e
)
772 action_x
= e
->xbutton
.x
;
773 action_y
= e
->xbutton
.y
;
782 lesstif_get_xy (const char *message
)
784 XmString ls
= XmStringCreateLocalized ((char *)message
);
786 XtManageChild (m_click
);
788 stdarg (XmNlabelString
, ls
);
789 XtSetValues (m_click
, args
, n
);
790 //printf("need xy: msg `%s'\n", msg);
792 XBell (display
, 100);
796 XtAppNextEvent (app_context
, &e
);
797 XtDispatchEvent (&e
);
801 XtUnmanageChild (m_click
);
805 lesstif_get_coords (const char *msg
, int *px
, int *py
)
808 lesstif_get_xy (msg
);
810 lesstif_coords_to_pcb (action_x
, action_y
, px
, py
);
814 callback (Widget w
, Resource
* node
, XmPushButtonCallbackStruct
* pbcs
)
818 lesstif_show_crosshair (0);
819 if (pbcs
->event
&& pbcs
->event
->type
== KeyPress
)
822 Widget aw
= XtWindowToWidget (display
, pbcs
->event
->xkey
.window
);
823 action_x
= pbcs
->event
->xkey
.x
;
824 action_y
= pbcs
->event
->xkey
.y
;
827 Widget p
= work_area
;
833 XtGetValues (p
, args
, n
);
841 //printf("have xy from %s: %d %d\n", XtName(aw), action_x, action_y);
844 lesstif_need_idle_proc ();
845 for (vi
= 1; vi
< node
->c
; vi
++)
846 if (resource_type (node
->v
[vi
]) == 10)
847 if (hid_parse_actions (node
->v
[vi
].value
))
851 typedef struct acc_table_t
856 /* If M_Multi is set in mods, these are used to chain to the next
857 attribute table for multi-key accelerators. */
860 struct acc_table_t
*chain
;
862 /* If M_Multi isn't set, these are used to map a single key to an
871 static acc_table_t
*acc_table
;
872 static int acc_num
= 0;
875 acc_sort (const void *va
, const void *vb
)
877 acc_table_t
*a
= (acc_table_t
*) va
;
878 acc_table_t
*b
= (acc_table_t
*) vb
;
879 if (a
->key_char
!= b
->key_char
)
880 return a
->key_char
- b
->key_char
;
881 if (!(a
->mods
& M_Multi
))
882 if (a
->u
.a
.key
!= b
->u
.a
.key
)
883 return a
->u
.a
.key
- b
->u
.a
.key
;
884 return a
->mods
- b
->mods
;
892 printf ("in dumpkeys! %d\n", acc_num
);
893 qsort (acc_table
, acc_num
, sizeof (acc_table_t
), acc_sort
);
895 for (i
= 0; i
< acc_num
; i
++)
901 sprintf (mod
, "%s%s%s",
902 acc_table
[i
].mods
& M_Alt
? "Alt-" : "",
903 acc_table
[i
].mods
& M_Ctrl
? "Ctrl-" : "",
904 acc_table
[i
].mods
& M_Shift
? "Shift-" : "");
905 ch
[0] = toupper ((int) acc_table
[i
].key_char
);
906 printf ("%16s%s\t", mod
,
907 acc_table
[i
].key_char
? ch
: XKeysymToString (acc_table
[i
].
910 for (vi
= 1; vi
< acc_table
[i
].u
.a
.node
->c
; vi
++)
911 if (resource_type (acc_table
[i
].u
.a
.node
->v
[vi
]) == 10)
913 printf ("%s%s", tabs
, acc_table
[i
].u
.a
.node
->v
[vi
].value
);
923 find_or_create_acc (char mods
, char key
, KeySym sym
,
924 acc_table_t
**table
, int *n_ents
)
930 for (i
=(*n_ents
)-1; i
>=0; i
--)
934 && a
->key_char
== key
935 && (mods
& M_Multi
|| a
->u
.a
.key
== sym
))
940 max
= (*n_ents
+ 16) & ~15;
943 *table
= (acc_table_t
*) realloc (*table
, max
* sizeof (acc_table_t
));
945 *table
= (acc_table_t
*) malloc (max
* sizeof (acc_table_t
));
947 a
= & ((*table
)[(*n_ents
)-1]);
948 memset (a
, 0, sizeof(acc_table_t
));
952 if (!(mods
& M_Multi
))
959 note_accelerator (char *acc
, Resource
* node
)
961 char *orig_acc
= acc
;
968 while (isalpha ((int) acc
[0]))
970 if (strncmp (acc
, "Shift", 5) == 0)
975 else if (strncmp (acc
, "Ctrl", 4) == 0)
980 else if (strncmp (acc
, "Alt", 3) == 0)
987 printf ("Must be Shift/Ctrl/Alt: %s\n", acc
);
993 if (strncmp (acc
, "<Keys>", 6) == 0)
998 else if (strncmp (acc
, "<Key>", 5))
1000 fprintf (stderr
, "accelerator \"%s\" not <Key> or <Keys>\n", orig_acc
);
1004 /* We have a hard time specifying the Enter key the "usual" way. */
1005 if (strcmp (acc
, "<Key>Enter") == 0)
1009 if (acc
[0] && acc
[1] == 0)
1012 a
= find_or_create_acc (mods
, key_char
, 0, &acc_table
, &acc_num
);
1016 acc_table_t
**ap
= &acc_table
;
1020 while (acc
[0] && acc
[1])
1022 a
= find_or_create_acc (mods
, acc
[0], 0, ap
, np
);
1023 ap
= & (a
->u
.c
.chain
);
1024 np
= & (a
->u
.c
.n_chain
);
1027 a
= find_or_create_acc (mods
& ~M_Multi
, acc
[0], 0, ap
, np
);
1031 key
= XStringToKeysym (acc
);
1032 if (key
== NoSymbol
&& !key_char
)
1034 printf ("no symbol for %s\n", acc
);
1037 a
= find_or_create_acc (mods
, 0, key
, &acc_table
, &acc_num
);
1045 dump_multi (int ix
, int ind
, acc_table_t
*a
, int n
)
1050 if (a
->mods
& M_Multi
)
1052 printf("%*cacc[%d] mods %x char %c multi %p/%d\n",
1054 i
, a
->mods
, a
->key_char
,
1055 a
->u
.c
.chain
, a
->u
.c
.n_chain
);
1056 dump_multi(0, ind
+4, a
->u
.c
.chain
, a
->u
.c
.n_chain
);
1060 printf("%*cacc[%d] mods %x char %c key %d node `%s'\n",
1062 i
, a
->mods
, a
->key_char
,
1063 a
->u
.a
.key
, a
->u
.a
.node
->v
[0].value
);
1070 #define dump_multi(x,a,b,c)
1073 static acc_table_t
*cur_table
= 0;
1074 static int cur_ntable
= 0;
1076 /* We sort these such that the ones with explicit modifiers come
1077 before the ones with implicit modifiers. That way, a
1078 Shift<Key>Code gets chosen before a <Key>Code. */
1080 acc_sort_rev (const void *va
, const void *vb
)
1082 acc_table_t
*a
= (acc_table_t
*) va
;
1083 acc_table_t
*b
= (acc_table_t
*) vb
;
1084 if (a
->key_char
!= b
->key_char
)
1085 return a
->key_char
- b
->key_char
;
1086 if (!(a
->mods
& M_Multi
))
1087 if (a
->u
.a
.key
!= b
->u
.a
.key
)
1088 return a
->u
.a
.key
- b
->u
.a
.key
;
1089 return b
->mods
- a
->mods
;
1093 lesstif_key_event (XKeyEvent
* e
)
1095 char buf
[10], buf2
[10];
1100 static int sorted
= 0;
1105 qsort (acc_table
, acc_num
, sizeof (acc_table_t
), acc_sort_rev
);
1108 if (e
->state
& ShiftMask
)
1110 if (e
->state
& ControlMask
)
1112 if (e
->state
& Mod1Mask
)
1115 e
->state
&= ~(ControlMask
| Mod1Mask
);
1116 slen
= XLookupString (e
, buf
, sizeof (buf
), &sym
, NULL
);
1118 if (e
->state
& ShiftMask
)
1120 e
->state
&= ~ShiftMask
;
1121 slen2
= XLookupString (e
, buf2
, sizeof (buf2
), &sym2
, NULL
);
1148 cur_table
= acc_table
;
1149 cur_ntable
= acc_num
;
1152 //printf("\nmods %x key %d str `%s' in %p/%d\n", mods, (int)sym, buf, cur_table, cur_ntable);
1154 #define KM(m) ((m) & ~M_Multi)
1155 for (i
= 0; i
< cur_ntable
; i
++)
1157 dump_multi (i
, 0, cur_table
+i
, 1);
1158 if (KM(cur_table
[i
].mods
) == mods
)
1160 if (sym
== acc_table
[i
].u
.a
.key
)
1163 if (KM(cur_table
[i
].mods
) == (mods
& ~M_Shift
))
1165 if (slen
== 1 && buf
[0] == cur_table
[i
].key_char
)
1167 if (sym
== cur_table
[i
].u
.a
.key
)
1170 if (mods
& M_Shift
&& KM(cur_table
[i
].mods
) == mods
)
1172 if (slen2
== 1 && buf2
[0] == cur_table
[i
].key_char
)
1174 if (sym2
== acc_table
[i
].u
.a
.key
)
1179 if (i
== cur_ntable
)
1181 if (cur_table
== acc_table
)
1182 lesstif_log ("Key \"%s\" not tied to an action\n", buf
);
1184 lesstif_log ("Key \"%s\" not tied to a multi-key action\n", buf
);
1188 if (cur_table
[i
].mods
& M_Multi
)
1190 cur_ntable
= cur_table
[i
].u
.c
.n_chain
;
1191 cur_table
= cur_table
[i
].u
.c
.chain
;
1192 dump_multi (0, 0, cur_table
, cur_ntable
);
1196 if (e
->window
== XtWindow (work_area
))
1205 for (vi
= 1; vi
< cur_table
[i
].u
.a
.node
->c
; vi
++)
1206 if (resource_type (cur_table
[i
].u
.a
.node
->v
[vi
]) == 10)
1207 if (hid_parse_actions
1208 (cur_table
[i
].u
.a
.node
->v
[vi
].value
))
1215 add_resource_to_menu (Widget menu
, Resource
* node
, XtCallbackProc callback
)
1222 for (i
= 0; i
< node
->c
; i
++)
1223 switch (resource_type (node
->v
[i
]))
1225 case 101: /* named subnode */
1227 stdarg (XmNtearOffModel
, XmTEAR_OFF_ENABLED
);
1228 sub
= XmCreatePulldownMenu (menu
, node
->v
[i
].name
, args
, n
);
1229 XtSetValues (sub
, args
, n
);
1231 stdarg (XmNsubMenuId
, sub
);
1232 btn
= XmCreateCascadeButton (menu
, node
->v
[i
].name
, args
, n
);
1233 XtManageChild (btn
);
1234 add_resource_to_menu (sub
, node
->v
[i
].subres
, callback
);
1237 case 1: /* unnamed subres */
1240 if ((v
= resource_value (node
->v
[i
].subres
, "fg")))
1242 do_color (v
, XmNforeground
);
1244 if ((v
= resource_value (node
->v
[i
].subres
, "bg")))
1246 do_color (v
, XmNbackground
);
1248 if ((v
= resource_value (node
->v
[i
].subres
, "font")))
1250 XFontStruct
*fs
= XLoadQueryFont (display
, v
);
1254 XmFontListCreate (fs
, XmSTRING_DEFAULT_CHARSET
);
1255 stdarg (XmNfontList
, fl
);
1259 if ((v
= resource_value (node
->v
[i
].subres
, "m")))
1261 stdarg (XmNmnemonic
, v
);
1263 if ((r
= resource_subres (node
->v
[i
].subres
, "a")))
1265 XmString as
= XmStringCreateLocalized (r
->v
[0].value
);
1266 stdarg (XmNacceleratorText
, as
);
1267 //stdarg(XmNaccelerator, r->v[1].value);
1268 note_accelerator (r
->v
[1].value
, node
->v
[i
].subres
);
1271 for (j
= 0; j
< node
->v
[i
].subres
->c
; j
++)
1272 if (resource_type (node
->v
[i
].subres
->v
[j
]) == 10)
1274 v
= node
->v
[i
].subres
->v
[j
].value
;
1277 stdarg (XmNlabelString
, XmStringCreateLocalized (v
));
1278 if (node
->v
[i
].subres
->flags
& FLAG_S
)
1281 stdarg (XmNtearOffModel
, XmTEAR_OFF_ENABLED
);
1282 sub
= XmCreatePulldownMenu (menu
, v
, args
+ nn
, n
- nn
);
1284 stdarg (XmNsubMenuId
, sub
);
1285 btn
= XmCreateCascadeButton (menu
, "menubutton", args
, n
);
1286 XtManageChild (btn
);
1287 add_resource_to_menu (sub
, node
->v
[i
].subres
, callback
);
1291 Resource
*radio
= resource_subres (node
->v
[i
].subres
, "radio");
1292 char *checked
= resource_value (node
->v
[i
].subres
, "checked");
1293 char *label
= resource_value (node
->v
[i
].subres
, "sensitive");
1296 ToggleItem
*ti
= (ToggleItem
*) malloc (sizeof (ToggleItem
));
1297 ti
->next
= toggle_items
;
1298 ti
->group
= radio
->v
[0].value
;
1299 ti
->item
= radio
->v
[1].value
;
1300 ti
->callback
= callback
;
1301 ti
->node
= node
->v
[i
].subres
;
1304 if (resource_value (node
->v
[i
].subres
, "set"))
1306 stdarg (XmNset
, True
);
1308 stdarg (XmNindicatorType
, XmONE_OF_MANY
);
1309 btn
= XmCreateToggleButton (menu
, "menubutton", args
, n
);
1311 XtAddCallback (btn
, XmNvalueChangedCallback
,
1312 (XtCallbackProc
) radio_callback
,
1317 if (strchr (checked
, ','))
1318 stdarg (XmNindicatorType
, XmONE_OF_MANY
);
1320 stdarg (XmNindicatorType
, XmN_OF_MANY
);
1321 btn
= XmCreateToggleButton (menu
, "menubutton", args
, n
);
1322 XtAddCallback (btn
, XmNvalueChangedCallback
,
1323 callback
, (XtPointer
) node
->v
[i
].subres
);
1325 else if (label
&& strcmp (label
, "false") == 0)
1327 stdarg (XmNalignment
, XmALIGNMENT_BEGINNING
);
1328 btn
= XmCreateLabel (menu
, "menulabel", args
, n
);
1332 btn
= XmCreatePushButton (menu
, "menubutton", args
, n
);
1333 XtAddCallback (btn
, XmNactivateCallback
,
1334 callback
, (XtPointer
) node
->v
[i
].subres
);
1337 for (j
= 0; j
< node
->v
[i
].subres
->c
; j
++)
1338 switch (resource_type (node
->v
[i
].subres
->v
[j
]))
1340 case 110: /* named value = X resource */
1342 char *n
= node
->v
[i
].subres
->v
[j
].name
;
1343 if (strcmp (n
, "fg") == 0)
1345 if (strcmp (n
, "bg") == 0)
1347 if (strcmp (n
, "m") == 0
1348 || strcmp (n
, "a") == 0
1349 || strcmp (n
, "sensitive") == 0)
1351 if (strcmp (n
, "checked") == 0)
1353 note_widget_flag (btn
, XmNset
,
1354 node
->v
[i
].subres
->v
[j
].value
);
1357 if (strcmp (n
, "active") == 0)
1359 note_widget_flag (btn
, XmNsensitive
,
1360 node
->v
[i
].subres
->v
[j
].value
);
1363 XtVaSetValues (btn
, XtVaTypedArg
,
1366 node
->v
[i
].subres
->v
[j
].value
,
1367 strlen (node
->v
[i
].subres
->v
[j
].value
) + 1,
1373 XtManageChild (btn
);
1377 case 10: /* unnamed value */
1379 if (node
->v
[i
].value
[0] == '@')
1381 if (strcmp (node
->v
[i
].value
, "@layerview") == 0)
1382 insert_layerview_buttons (menu
);
1383 if (strcmp (node
->v
[i
].value
, "@layerpick") == 0)
1384 insert_layerpick_buttons (menu
);
1385 if (strcmp (node
->v
[i
].value
, "@routestyles") == 0)
1386 lesstif_insert_style_buttons (menu
);
1388 else if (strcmp (node
->v
[i
].value
, "-") == 0)
1390 btn
= XmCreateSeparator (menu
, "sep", args
, n
);
1391 XtManageChild (btn
);
1395 btn
= XmCreatePushButton (menu
, node
->v
[i
].value
, args
, n
);
1396 XtManageChild (btn
);
1402 extern char *lesstif_pcbmenu_path
;
1405 lesstif_menu (Widget parent
, char *name
, Arg
* margs
, int mn
)
1407 Widget mb
= XmCreateMenuBar (parent
, name
, margs
, mn
);
1409 Resource
*r
= 0, *bir
;
1410 char *home_pcbmenu
, *home
;
1414 display
= XtDisplay (mb
);
1415 screen
= DefaultScreen (display
);
1416 cmap
= DefaultColormap (display
, screen
);
1418 /* homedir is set by the core */
1420 home_pcbmenu
= NULL
;
1423 Message ("Warning: could not determine home directory (from HOME)\n");
1427 home_pcbmenu
= Concat (home
, PCB_DIR_SEPARATOR_S
, ".pcb",
1428 PCB_DIR_SEPARATOR_S
, "pcb-menu.res", NULL
);
1431 if (access ("pcb-menu.res", R_OK
) == 0)
1432 filename
= "pcb-menu.res";
1433 else if (home_pcbmenu
!= NULL
&& (access (home_pcbmenu
, R_OK
) == 0))
1434 filename
= home_pcbmenu
;
1435 else if (access (lesstif_pcbmenu_path
, R_OK
) == 0)
1436 filename
= lesstif_pcbmenu_path
;
1440 bir
= resource_parse (0, pcb_menu_default
);
1443 fprintf (stderr
, "Error: internal menu resource didn't parse\n");
1448 r
= resource_parse (filename
, 0);
1453 if (home_pcbmenu
!= NULL
)
1455 free (home_pcbmenu
);
1458 mr
= resource_subres (r
, "MainMenu");
1460 mr
= resource_subres (bir
, "MainMenu");
1462 add_resource_to_menu (mb
, mr
, (XtCallbackProc
) callback
);
1464 mr
= resource_subres (r
, "Mouse");
1466 mr
= resource_subres (bir
, "Mouse");
1468 load_mouse_resource (mr
);