13 #include "xincludes.h"
20 #include "../hidint.h"
27 #ifdef HAVE_LIBDMALLOC
34 /* Common value for systems that don't define it. */
43 #define stdarg(t,v) XtSetArg(args[n], t, v), n++
45 static void note_accelerator (char *acc
, Resource
* node
);
47 static const char getxy_syntax
[] =
50 static const char getxy_help
[] =
53 /* %start-doc actions GetXY
55 Prompts the user for a coordinate, if one is not already selected.
60 GetXY (int argc
, char **argv
, int x
, int y
)
65 static const char debug_syntax
[] =
68 static const char debug_help
[] =
71 /* %start-doc actions Debug
73 This action exists to help debug scripts; it simply prints all its
78 static const char debugxy_syntax
[] =
81 static const char debugxy_help
[] =
82 "Debug action, with coordinates";
84 /* %start-doc actions DebugXY
86 Like @code{Debug}, but requires a coordinate. If the user hasn't yet
87 indicated a location on the board, the user will be prompted to click
93 Debug (int argc
, char **argv
, int x
, int y
)
97 for (i
= 0; i
< argc
; i
++)
98 printf (" [%d] `%s'", i
, argv
[i
]);
99 printf (" x,y %d,%d\n", x
, y
);
103 static const char return_syntax
[] =
106 static const char return_help
[] =
107 "Simulate a passing or failing action.";
109 /* %start-doc actions Return
111 This is for testing. If passed a 0, does nothing and succeeds. If
112 passed a 1, does nothing but pretends to fail.
117 Return (int argc
, char **argv
, int x
, int y
)
119 return atoi (argv
[0]);
122 static const char dumpkeys_syntax
[] =
125 static const char dumpkeys_help
[] =
126 "Dump Lesstif key bindings.";
128 /* %start-doc actions DumpKeys
130 Causes the list of key bindings (from @code{pcb-menu.res}) to be
131 dumped to stdout. This is most useful when invoked from the command
135 pcb --action-string DumpKeys
140 static int do_dump_keys
= 0;
142 DumpKeys (int argc
, char **argv
, int x
, int y
)
148 /*-----------------------------------------------------------------------------*/
150 #define LB_SILK (MAX_LAYER+0)
151 #define LB_RATS (MAX_LAYER+1)
152 #define LB_NUMPICK (LB_RATS+1)
154 #define LB_PINS (MAX_LAYER+2)
155 #define LB_VIAS (MAX_LAYER+3)
156 #define LB_BACK (MAX_LAYER+4)
157 #define LB_MASK (MAX_LAYER+5)
158 #define LB_NUM (MAX_LAYER+6)
166 static LayerButtons
*layer_button_list
= 0;
167 static int num_layer_buttons
= 0;
168 static int fg_colors
[LB_NUM
];
171 extern Widget lesstif_m_layer
;
174 LayersChanged (int argc
, char **argv
, int x
, int y
)
180 if (!layer_button_list
)
182 if (PCB
&& PCB
->Data
)
184 DataType
*d
= PCB
->Data
;
185 for (i
= 0; i
< MAX_LAYER
; i
++)
186 fg_colors
[i
] = lesstif_parse_color (d
->Layer
[i
].Color
);
187 fg_colors
[LB_SILK
] = lesstif_parse_color (PCB
->ElementColor
);
188 fg_colors
[LB_RATS
] = lesstif_parse_color (PCB
->RatColor
);
189 fg_colors
[LB_PINS
] = lesstif_parse_color (PCB
->PinColor
);
190 fg_colors
[LB_VIAS
] = lesstif_parse_color (PCB
->ViaColor
);
192 lesstif_parse_color (PCB
->InvisibleObjectsColor
);
193 fg_colors
[LB_MASK
] = lesstif_parse_color (PCB
->MaskColor
);
194 bg_color
= lesstif_parse_color (Settings
.BackgroundColor
);
198 for (i
= 0; i
< MAX_LAYER
; i
++)
199 fg_colors
[i
] = lesstif_parse_color (Settings
.LayerColor
[i
]);
200 fg_colors
[LB_SILK
] = lesstif_parse_color (Settings
.ElementColor
);
201 fg_colors
[LB_RATS
] = lesstif_parse_color (Settings
.RatColor
);
202 fg_colors
[LB_PINS
] = lesstif_parse_color (Settings
.PinColor
);
203 fg_colors
[LB_VIAS
] = lesstif_parse_color (Settings
.ViaColor
);
205 lesstif_parse_color (Settings
.InvisibleObjectsColor
);
206 fg_colors
[LB_MASK
] = lesstif_parse_color (Settings
.MaskColor
);
207 bg_color
= lesstif_parse_color (Settings
.BackgroundColor
);
211 current_layer
= LB_RATS
;
212 else if (PCB
->SilkActive
)
213 current_layer
= LB_SILK
;
215 current_layer
= LayerStack
[0];
217 for (l
= 0; l
< num_layer_buttons
; l
++)
219 LayerButtons
*lb
= layer_button_list
+ l
;
220 for (i
= 0; i
< (lb
->is_pick
? LB_NUMPICK
: LB_NUM
); i
++)
225 set
= PCB
->ElementOn
;
237 set
= PCB
->InvisibleObjectsOn
;
240 set
= TEST_FLAG (SHOWMASKFLAG
, PCB
);
242 default: /* layers */
243 set
= PCB
->Data
->Layer
[i
].On
;
248 if (i
< MAX_LAYER
&& PCB
->Data
->Layer
[i
].Name
)
250 XmString s
= XmStringCreateLocalized (PCB
->Data
->Layer
[i
].Name
);
251 stdarg (XmNlabelString
, s
);
257 stdarg (XmNforeground
, bg_color
);
258 stdarg (XmNbackground
, fg_colors
[i
]);
262 stdarg (XmNforeground
, fg_colors
[i
]);
263 stdarg (XmNbackground
, bg_color
);
265 stdarg (XmNset
, set
);
269 stdarg (XmNforeground
, bg_color
);
270 stdarg (XmNbackground
, fg_colors
[i
]);
271 stdarg (XmNset
, current_layer
== i
? True
: False
);
273 XtSetValues (lb
->w
[i
], args
, n
);
275 if (i
>= max_layer
&& i
< MAX_LAYER
)
276 XtUnmanageChild(lb
->w
[i
]);
278 XtManageChild(lb
->w
[i
]);
283 switch (current_layer
)
292 name
= PCB
->Data
->Layer
[current_layer
].Name
;
296 stdarg (XmNbackground
, fg_colors
[current_layer
]);
297 stdarg (XmNforeground
, bg_color
);
298 stdarg (XmNlabelString
, XmStringCreateLocalized (name
));
299 XtSetValues (lesstif_m_layer
, args
, n
);
302 lesstif_update_layer_groups ();
308 show_one_layer_button (int layer
, int set
)
314 stdarg (XmNforeground
, bg_color
);
315 stdarg (XmNbackground
, fg_colors
[layer
]);
319 stdarg (XmNforeground
, fg_colors
[layer
]);
320 stdarg (XmNbackground
, bg_color
);
322 stdarg (XmNset
, set
);
324 for (l
= 0; l
< num_layer_buttons
; l
++)
326 LayerButtons
*lb
= layer_button_list
+ l
;
328 XtSetValues (lb
->w
[layer
], args
, n
);
333 layer_button_callback (Widget w
, int layer
, XmPushButtonCallbackStruct
* pbcs
)
339 set
= PCB
->ElementOn
= !PCB
->ElementOn
;
340 PCB
->Data
->SILKLAYER
.On
= set
;
341 PCB
->Data
->BACKSILKLAYER
.On
= set
;
344 set
= PCB
->RatOn
= !PCB
->RatOn
;
347 set
= PCB
->PinOn
= !PCB
->PinOn
;
350 set
= PCB
->ViaOn
= !PCB
->ViaOn
;
353 set
= PCB
->InvisibleObjectsOn
= !PCB
->InvisibleObjectsOn
;
356 TOGGLE_FLAG (SHOWMASKFLAG
, PCB
);
357 set
= TEST_FLAG (SHOWMASKFLAG
, PCB
);
359 default: /* layers */
360 set
= PCB
->Data
->Layer
[layer
].On
= !PCB
->Data
->Layer
[layer
].On
;
364 show_one_layer_button (layer
, set
);
365 if (layer
< max_layer
)
368 int group
= GetLayerGroupNumberByNumber (layer
);
369 for (i
= 0; i
< PCB
->LayerGroups
.Number
[group
]; i
++)
371 l
= PCB
->LayerGroups
.Entries
[group
][i
];
372 if (l
!= layer
&& l
< max_layer
)
374 show_one_layer_button (l
, set
);
375 PCB
->Data
->Layer
[l
].On
= set
;
379 lesstif_invalidate_all ();
383 layerpick_button_callback (Widget w
, int layer
,
384 XmPushButtonCallbackStruct
* pbcs
)
388 PCB
->RatDraw
= (layer
== LB_RATS
);
389 PCB
->SilkActive
= (layer
== LB_SILK
);
390 if (layer
< max_layer
)
391 ChangeGroupVisibility (layer
, 1, 1);
392 for (l
= 0; l
< num_layer_buttons
; l
++)
394 LayerButtons
*lb
= layer_button_list
+ l
;
397 for (i
= 0; i
< LB_NUMPICK
; i
++)
398 XmToggleButtonSetState (lb
->w
[i
], layer
== i
, False
);
409 name
= PCB
->Data
->Layer
[layer
].Name
;
413 stdarg (XmNbackground
, fg_colors
[layer
]);
414 stdarg (XmNforeground
, bg_color
);
415 stdarg (XmNlabelString
, XmStringCreateLocalized (name
));
416 XtSetValues (lesstif_m_layer
, args
, n
);
417 lesstif_invalidate_all ();
420 static const char selectlayer_syntax
[] =
421 "SelectLayer(1..MAXLAYER|Silk|Rats)";
423 static const char selectlayer_help
[] =
424 "Select which layer is the current layer.";
426 /* %start-doc actions SelectLayer
428 The specified layer becomes the currently active layer. It is made
429 visible if it is not already visible
434 SelectLayer (int argc
, char **argv
, int x
, int y
)
439 if (strcasecmp (argv
[0], "silk") == 0)
441 else if (strcasecmp (argv
[0], "rats") == 0)
444 newl
= atoi (argv
[0]) - 1;
445 layerpick_button_callback (0, newl
, 0);
449 static const char toggleview_syntax
[] =
450 "ToggleView(1..MAXLAYER)\n"
451 "ToggleView(layername)\n"
452 "ToggleView(Silk|Rats|Pins|Vias|Mask|BackSide)";
454 static const char toggleview_help
[] =
455 "Toggle the visibility of the specified layer or layer group.";
457 /* %start-doc actions ToggleView
459 If you pass an integer, that layer is specified by index (the first
460 layer is @code{1}, etc). If you pass a layer name, that layer is
461 specified by name. When a layer is specified, the visibility of the
462 layer group containing that layer is toggled.
464 If you pass a special layer name, the visibility of those components
465 (silk, rats, etc) is toggled. Note that if you have a layer named
466 the same as a special layer, the layer is chosen over the special layer.
471 ToggleView (int argc
, char **argv
, int x
, int y
)
477 if (isdigit ((int) argv
[0][0]))
479 l
= atoi (argv
[0]) - 1;
480 layer_button_callback (0, l
, 0);
482 else if (strcmp (argv
[0], "Silk") == 0)
483 layer_button_callback (0, LB_SILK
, 0);
484 else if (strcmp (argv
[0], "Rats") == 0)
485 layer_button_callback (0, LB_RATS
, 0);
486 else if (strcmp (argv
[0], "Pins") == 0)
487 layer_button_callback (0, LB_PINS
, 0);
488 else if (strcmp (argv
[0], "Vias") == 0)
489 layer_button_callback (0, LB_VIAS
, 0);
490 else if (strcmp (argv
[0], "Mask") == 0)
491 layer_button_callback (0, LB_MASK
, 0);
492 else if (strcmp (argv
[0], "BackSide") == 0)
493 layer_button_callback (0, LB_BACK
, 0);
497 for (i
= 0; i
< max_layer
+ 2; i
++)
498 if (strcmp (argv
[0], PCB
->Data
->Layer
[i
].Name
) == 0)
505 layer_button_callback (0, l
, 0);
511 insert_layerview_buttons (Widget menu
)
517 s
= num_layer_buttons
* sizeof (LayerButtons
);
518 if (layer_button_list
)
519 layer_button_list
= (LayerButtons
*) realloc (layer_button_list
, s
);
521 layer_button_list
= (LayerButtons
*) malloc (s
);
522 lb
= layer_button_list
+ num_layer_buttons
- 1;
524 for (i
= 0; i
< LB_NUM
; i
++)
526 static char namestr
[] = "Label ";
527 char *name
= namestr
;
548 name
= "Solder Mask";
552 if (i
< MAX_LAYER
&& i
< 9)
554 char buf
[20], av
[30];
557 sprintf (buf
, "Ctrl-%d", i
+ 1);
558 as
= XmStringCreateLocalized (buf
);
559 stdarg (XmNacceleratorText
, as
);
560 ar
= resource_create (0);
561 sprintf (av
, "ToggleView(%d)", i
+ 1);
562 resource_add_val (ar
, 0, strdup (av
), 0);
563 resource_add_val (ar
, 0, strdup (av
), 0);
565 sprintf (av
, "Ctrl<Key>%d", i
+ 1);
566 note_accelerator (av
, ar
);
567 stdarg (XmNmnemonic
, i
+ '1');
569 btn
= XmCreateToggleButton (menu
, name
, args
, n
);
571 XtAddCallback (btn
, XmNvalueChangedCallback
,
572 (XtCallbackProc
) layer_button_callback
, (XtPointer
) (size_t) i
);
576 LayersChanged (0, 0, 0, 0);
580 insert_layerpick_buttons (Widget menu
)
586 s
= num_layer_buttons
* sizeof (LayerButtons
);
587 if (layer_button_list
)
588 layer_button_list
= (LayerButtons
*) realloc (layer_button_list
, s
);
590 layer_button_list
= (LayerButtons
*) malloc (s
);
591 lb
= layer_button_list
+ num_layer_buttons
- 1;
593 for (i
= 0; i
< LB_NUMPICK
; i
++)
595 static char namestr
[] = "Label ";
596 char *name
= namestr
;
609 if (i
< MAX_LAYER
&& i
< 9)
611 char buf
[20], av
[30];
614 sprintf (buf
, "%d", i
+ 1);
615 as
= XmStringCreateLocalized (buf
);
616 stdarg (XmNacceleratorText
, as
);
617 ar
= resource_create (0);
621 strcpy (av
, "SelectLayer(Silk)");
624 strcpy (av
, "SelectLayer(Rats)");
627 sprintf (av
, "SelectLayer(%d)", i
+ 1);
630 resource_add_val (ar
, 0, strdup (av
), 0);
631 resource_add_val (ar
, 0, strdup (av
), 0);
633 sprintf (av
, "<Key>%d", i
+ 1);
634 note_accelerator (av
, ar
);
635 stdarg (XmNmnemonic
, i
+ '1');
637 stdarg (XmNindicatorType
, XmONE_OF_MANY
);
638 btn
= XmCreateToggleButton (menu
, name
, args
, n
);
640 XtAddCallback (btn
, XmNvalueChangedCallback
,
641 (XtCallbackProc
) layerpick_button_callback
,
642 (XtPointer
) (size_t) i
);
646 LayersChanged (0, 0, 0, 0);
649 /*-----------------------------------------------------------------------------*/
654 const char *flagname
;
659 static WidgetFlagType
*wflags
= 0;
660 static int n_wflags
= 0;
661 static int max_wflags
= 0;
664 note_widget_flag (Widget w
, char *type
, char *name
)
666 if (n_wflags
>= max_wflags
)
670 MyRealloc (wflags
, max_wflags
* sizeof (WidgetFlagType
),
673 wflags
[n_wflags
].w
= w
;
674 wflags
[n_wflags
].flagname
= name
;
675 wflags
[n_wflags
].oldval
= -1;
676 wflags
[n_wflags
].xres
= type
;
681 lesstif_update_widget_flags ()
685 for (i
= 0; i
< n_wflags
; i
++)
687 int v
= hid_get_flag (wflags
[i
].flagname
);
689 XtSetArg (args
[0], wflags
[i
].xres
, v
? 1 : 0);
690 XtSetValues (wflags
[i
].w
, args
, 1);
691 wflags
[i
].oldval
= v
;
695 /*-----------------------------------------------------------------------------*/
697 HID_Action lesstif_menu_action_list
[] = {
698 {"DumpKeys", 0, DumpKeys
,
699 dumpkeys_help
, dumpkeys_syntax
},
701 debug_help
, debug_syntax
},
702 {"DebugXY", "Click X,Y for Debug", Debug
,
703 debugxy_help
, debugxy_syntax
},
705 getxy_help
, getxy_syntax
},
706 {"Return", 0, Return
,
707 return_help
, return_syntax
},
708 {"LayersChanged", 0, LayersChanged
,
709 layerschanged_help
, layerschanged_syntax
},
710 {"ToggleView", 0, ToggleView
,
711 toggleview_help
, toggleview_syntax
},
712 {"SelectLayer", 0, SelectLayer
,
713 selectlayer_help
, selectlayer_syntax
}
716 REGISTER_ACTIONS (lesstif_menu_action_list
)
720 do_color (char *value
, char *which
)
723 if (XParseColor (display
, cmap
, value
, &color
))
724 if (XAllocColor (display
, cmap
, &color
))
726 stdarg (which
, color
.pixel
);
731 typedef struct ToggleItem
733 struct ToggleItem
*next
;
736 XtCallbackProc callback
;
739 static ToggleItem
*toggle_items
= 0;
741 static int need_xy
= 0, have_xy
= 0, action_x
, action_y
;
744 radio_callback (Widget toggle
, ToggleItem
* me
,
745 XmToggleButtonCallbackStruct
* cbs
)
747 if (!cbs
->set
) /* uh uh, can't turn it off */
748 XmToggleButtonSetState (toggle
, 1, 0);
752 for (ti
= toggle_items
; ti
; ti
= ti
->next
)
753 if (strcmp (me
->group
, ti
->group
) == 0)
755 if (me
->item
== ti
->item
|| strcmp (me
->item
, ti
->item
) == 0)
756 XmToggleButtonSetState (ti
->w
, 1, 0);
758 XmToggleButtonSetState (ti
->w
, 0, 0);
760 me
->callback (toggle
, me
->node
, cbs
);
765 lesstif_button_event (Widget w
, XEvent
* e
)
768 action_x
= e
->xbutton
.x
;
769 action_y
= e
->xbutton
.y
;
778 lesstif_get_xy (const char *message
)
780 XmString ls
= XmStringCreateLocalized ((char *)message
);
782 XtManageChild (m_click
);
784 stdarg (XmNlabelString
, ls
);
785 XtSetValues (m_click
, args
, n
);
786 //printf("need xy: msg `%s'\n", msg);
788 XBell (display
, 100);
792 XtAppNextEvent (app_context
, &e
);
793 XtDispatchEvent (&e
);
797 XtUnmanageChild (m_click
);
801 lesstif_get_coords (const char *msg
, int *px
, int *py
)
804 lesstif_get_xy (msg
);
805 lesstif_coords_to_pcb (action_x
, action_y
, px
, py
);
809 lesstif_call_action (const char *aname
, int argc
, char **argv
)
812 HID_Action
*a
= hid_find_action (aname
);
816 printf ("no action %s(", aname
);
817 for (i
= 0; i
< argc
; i
++)
818 printf ("%s%s", i
? ", " : "", argv
[i
]);
823 if (a
->need_coord_msg
&& !have_xy
)
826 if (strcmp (aname
, "GetXY") == 0)
829 msg
= a
->need_coord_msg
;
830 lesstif_get_xy (msg
);
832 lesstif_coords_to_pcb (action_x
, action_y
, &px
, &py
);
834 if (Settings
.verbose
)
837 printf ("Action: \033[34m%s(", aname
);
838 for (i
= 0; i
< argc
; i
++)
839 printf ("%s%s", i
? "," : "", argv
[i
]);
840 printf (")\033[0m\n");
842 return a
->trigger_cb (argc
, argv
, px
, py
);
846 callback (Widget w
, Resource
* node
, XmPushButtonCallbackStruct
* pbcs
)
850 lesstif_show_crosshair (0);
851 if (pbcs
->event
&& pbcs
->event
->type
== KeyPress
)
854 Widget aw
= XtWindowToWidget (display
, pbcs
->event
->xkey
.window
);
855 action_x
= pbcs
->event
->xkey
.x
;
856 action_y
= pbcs
->event
->xkey
.y
;
859 Widget p
= work_area
;
865 XtGetValues (p
, args
, n
);
873 //printf("have xy from %s: %d %d\n", XtName(aw), action_x, action_y);
876 lesstif_need_idle_proc ();
877 for (vi
= 1; vi
< node
->c
; vi
++)
878 if (resource_type (node
->v
[vi
]) == 10)
879 if (hid_parse_actions (node
->v
[vi
].value
, lesstif_call_action
))
883 typedef struct acc_table_t
888 /* If M_Multi is set in mods, these are used to chain to the next
889 attribute table for multi-key accelerators. */
892 struct acc_table_t
*chain
;
894 /* If M_Multi isn't set, these are used to map a single key to an
903 static acc_table_t
*acc_table
;
904 static int acc_num
= 0;
907 acc_sort (const void *va
, const void *vb
)
909 acc_table_t
*a
= (acc_table_t
*) va
;
910 acc_table_t
*b
= (acc_table_t
*) vb
;
911 if (a
->key_char
!= b
->key_char
)
912 return a
->key_char
- b
->key_char
;
913 if (!(a
->mods
& M_Multi
))
914 if (a
->u
.a
.key
!= b
->u
.a
.key
)
915 return a
->u
.a
.key
- b
->u
.a
.key
;
916 return a
->mods
- b
->mods
;
924 printf ("in dumpkeys! %d\n", acc_num
);
925 qsort (acc_table
, acc_num
, sizeof (acc_table_t
), acc_sort
);
927 for (i
= 0; i
< acc_num
; i
++)
933 sprintf (mod
, "%s%s%s",
934 acc_table
[i
].mods
& M_Alt
? "Alt-" : "",
935 acc_table
[i
].mods
& M_Ctrl
? "Ctrl-" : "",
936 acc_table
[i
].mods
& M_Shift
? "Shift-" : "");
937 ch
[0] = toupper (acc_table
[i
].key_char
);
938 printf ("%16s%s\t", mod
,
939 acc_table
[i
].key_char
? ch
: XKeysymToString (acc_table
[i
].
942 for (vi
= 1; vi
< acc_table
[i
].u
.a
.node
->c
; vi
++)
943 if (resource_type (acc_table
[i
].u
.a
.node
->v
[vi
]) == 10)
945 printf ("%s%s", tabs
, acc_table
[i
].u
.a
.node
->v
[vi
].value
);
955 find_or_create_acc (char mods
, char key
, KeySym sym
,
956 acc_table_t
**table
, int *n_ents
)
962 for (i
=(*n_ents
)-1; i
>=0; i
--)
966 && a
->key_char
== key
967 && (mods
& M_Multi
|| a
->u
.a
.key
== sym
))
972 max
= (*n_ents
+ 16) & ~15;
975 *table
= (acc_table_t
*) realloc (*table
, max
* sizeof (acc_table_t
));
977 *table
= (acc_table_t
*) malloc (max
* sizeof (acc_table_t
));
979 a
= & ((*table
)[(*n_ents
)-1]);
980 memset (a
, 0, sizeof(acc_table_t
));
984 if (!(mods
& M_Multi
))
991 note_accelerator (char *acc
, Resource
* node
)
993 char *orig_acc
= acc
;
1000 while (isalpha ((int) acc
[0]))
1002 if (strncmp (acc
, "Shift", 5) == 0)
1007 else if (strncmp (acc
, "Ctrl", 4) == 0)
1012 else if (strncmp (acc
, "Alt", 3) == 0)
1019 printf ("Must be Shift/Ctrl/Alt: %s\n", acc
);
1025 if (strncmp (acc
, "<Keys>", 6) == 0)
1030 else if (strncmp (acc
, "<Key>", 5))
1032 fprintf (stderr
, "accelerator \"%s\" not <Key> or <Keys>\n", orig_acc
);
1036 /* We have a hard time specifying the Enter key the "usual" way. */
1037 if (strcmp (acc
, "<Key>Enter") == 0)
1041 if (acc
[0] && acc
[1] == 0)
1044 a
= find_or_create_acc (mods
, key_char
, 0, &acc_table
, &acc_num
);
1048 acc_table_t
**ap
= &acc_table
;
1052 while (acc
[0] && acc
[1])
1054 a
= find_or_create_acc (mods
, acc
[0], 0, ap
, np
);
1055 ap
= & (a
->u
.c
.chain
);
1056 np
= & (a
->u
.c
.n_chain
);
1059 a
= find_or_create_acc (mods
& ~M_Multi
, acc
[0], 0, ap
, np
);
1063 key
= XStringToKeysym (acc
);
1064 if (key
== NoSymbol
&& !key_char
)
1066 printf ("no symbol for %s\n", acc
);
1069 a
= find_or_create_acc (mods
, 0, key
, &acc_table
, &acc_num
);
1077 dump_multi (int ix
, int ind
, acc_table_t
*a
, int n
)
1082 if (a
->mods
& M_Multi
)
1084 printf("%*cacc[%d] mods %x char %c multi %p/%d\n",
1086 i
, a
->mods
, a
->key_char
,
1087 a
->u
.c
.chain
, a
->u
.c
.n_chain
);
1088 dump_multi(0, ind
+4, a
->u
.c
.chain
, a
->u
.c
.n_chain
);
1092 printf("%*cacc[%d] mods %x char %c key %d node `%s'\n",
1094 i
, a
->mods
, a
->key_char
,
1095 a
->u
.a
.key
, a
->u
.a
.node
->v
[0].value
);
1102 #define dump_multi(x,a,b,c)
1105 static acc_table_t
*cur_table
= 0;
1106 static int cur_ntable
= 0;
1108 /* We sort these such that the ones with explicit modifiers come
1109 before the ones with implicit modifiers. That way, a
1110 Shift<Key>Code gets chosen before a <Key>Code. */
1112 acc_sort_rev (const void *va
, const void *vb
)
1114 acc_table_t
*a
= (acc_table_t
*) va
;
1115 acc_table_t
*b
= (acc_table_t
*) vb
;
1116 if (a
->key_char
!= b
->key_char
)
1117 return a
->key_char
- b
->key_char
;
1118 if (!(a
->mods
& M_Multi
))
1119 if (a
->u
.a
.key
!= b
->u
.a
.key
)
1120 return a
->u
.a
.key
- b
->u
.a
.key
;
1121 return b
->mods
- a
->mods
;
1125 lesstif_key_event (XKeyEvent
* e
)
1127 char buf
[10], buf2
[10];
1132 static int sorted
= 0;
1137 qsort (acc_table
, acc_num
, sizeof (acc_table_t
), acc_sort_rev
);
1140 if (e
->state
& ShiftMask
)
1142 if (e
->state
& ControlMask
)
1144 if (e
->state
& Mod1Mask
)
1147 e
->state
&= ~(ControlMask
| Mod1Mask
);
1148 slen
= XLookupString (e
, buf
, sizeof (buf
), &sym
, NULL
);
1150 if (e
->state
& ShiftMask
)
1152 e
->state
&= ~ShiftMask
;
1153 slen2
= XLookupString (e
, buf2
, sizeof (buf2
), &sym2
, NULL
);
1180 cur_table
= acc_table
;
1181 cur_ntable
= acc_num
;
1184 //printf("\nmods %x key %d str `%s' in %p/%d\n", mods, (int)sym, buf, cur_table, cur_ntable);
1186 #define KM(m) ((m) & ~M_Multi)
1187 for (i
= 0; i
< cur_ntable
; i
++)
1189 dump_multi (i
, 0, cur_table
+i
, 1);
1190 if (KM(cur_table
[i
].mods
) == mods
)
1192 if (sym
== acc_table
[i
].u
.a
.key
)
1195 if (KM(cur_table
[i
].mods
) == (mods
& ~M_Shift
))
1197 if (slen
== 1 && buf
[0] == cur_table
[i
].key_char
)
1199 if (sym
== cur_table
[i
].u
.a
.key
)
1202 if (mods
& M_Shift
&& KM(cur_table
[i
].mods
) == mods
)
1204 if (slen2
== 1 && buf2
[0] == cur_table
[i
].key_char
)
1206 if (sym2
== acc_table
[i
].u
.a
.key
)
1211 if (i
== cur_ntable
)
1213 if (cur_table
== acc_table
)
1214 lesstif_log ("Key \"%s\" not tied to an action\n", buf
);
1216 lesstif_log ("Key \"%s\" not tied to a multi-key action\n", buf
);
1220 if (cur_table
[i
].mods
& M_Multi
)
1222 cur_ntable
= cur_table
[i
].u
.c
.n_chain
;
1223 cur_table
= cur_table
[i
].u
.c
.chain
;
1224 dump_multi (0, 0, cur_table
, cur_ntable
);
1228 if (e
->window
== XtWindow (work_area
))
1237 for (vi
= 1; vi
< cur_table
[i
].u
.a
.node
->c
; vi
++)
1238 if (resource_type (cur_table
[i
].u
.a
.node
->v
[vi
]) == 10)
1239 if (hid_parse_actions
1240 (cur_table
[i
].u
.a
.node
->v
[vi
].value
, lesstif_call_action
))
1247 add_resource_to_menu (Widget menu
, Resource
* node
, XtCallbackProc callback
)
1254 for (i
= 0; i
< node
->c
; i
++)
1255 switch (resource_type (node
->v
[i
]))
1257 case 101: /* named subnode */
1259 stdarg (XmNtearOffModel
, XmTEAR_OFF_ENABLED
);
1260 sub
= XmCreatePulldownMenu (menu
, node
->v
[i
].name
, args
, n
);
1261 XtSetValues (sub
, args
, n
);
1263 stdarg (XmNsubMenuId
, sub
);
1264 btn
= XmCreateCascadeButton (menu
, node
->v
[i
].name
, args
, n
);
1265 XtManageChild (btn
);
1266 add_resource_to_menu (sub
, node
->v
[i
].subres
, callback
);
1269 case 1: /* unnamed subres */
1272 if ((v
= resource_value (node
->v
[i
].subres
, "fg")))
1274 do_color (v
, XmNforeground
);
1276 if ((v
= resource_value (node
->v
[i
].subres
, "bg")))
1278 do_color (v
, XmNbackground
);
1280 if ((v
= resource_value (node
->v
[i
].subres
, "font")))
1282 XFontStruct
*fs
= XLoadQueryFont (display
, v
);
1286 XmFontListCreate (fs
, XmSTRING_DEFAULT_CHARSET
);
1287 stdarg (XmNfontList
, fl
);
1291 if ((v
= resource_value (node
->v
[i
].subres
, "m")))
1293 stdarg (XmNmnemonic
, v
);
1295 if ((r
= resource_subres (node
->v
[i
].subres
, "a")))
1297 XmString as
= XmStringCreateLocalized (r
->v
[0].value
);
1298 stdarg (XmNacceleratorText
, as
);
1299 //stdarg(XmNaccelerator, r->v[1].value);
1300 note_accelerator (r
->v
[1].value
, node
->v
[i
].subres
);
1303 for (j
= 0; j
< node
->v
[i
].subres
->c
; j
++)
1304 if (resource_type (node
->v
[i
].subres
->v
[j
]) == 10)
1306 v
= node
->v
[i
].subres
->v
[j
].value
;
1309 stdarg (XmNlabelString
, XmStringCreateLocalized (v
));
1310 if (node
->v
[i
].subres
->flags
& FLAG_S
)
1313 stdarg (XmNtearOffModel
, XmTEAR_OFF_ENABLED
);
1314 sub
= XmCreatePulldownMenu (menu
, v
, args
+ nn
, n
- nn
);
1316 stdarg (XmNsubMenuId
, sub
);
1317 btn
= XmCreateCascadeButton (menu
, "menubutton", args
, n
);
1318 XtManageChild (btn
);
1319 add_resource_to_menu (sub
, node
->v
[i
].subres
, callback
);
1323 Resource
*radio
= resource_subres (node
->v
[i
].subres
, "radio");
1324 char *checked
= resource_value (node
->v
[i
].subres
, "checked");
1325 char *label
= resource_value (node
->v
[i
].subres
, "sensitive");
1328 ToggleItem
*ti
= (ToggleItem
*) malloc (sizeof (ToggleItem
));
1329 ti
->next
= toggle_items
;
1330 ti
->group
= radio
->v
[0].value
;
1331 ti
->item
= radio
->v
[1].value
;
1332 ti
->callback
= callback
;
1333 ti
->node
= node
->v
[i
].subres
;
1336 if (resource_value (node
->v
[i
].subres
, "set"))
1338 stdarg (XmNset
, True
);
1340 stdarg (XmNindicatorType
, XmONE_OF_MANY
);
1341 btn
= XmCreateToggleButton (menu
, "menubutton", args
, n
);
1343 XtAddCallback (btn
, XmNvalueChangedCallback
,
1344 (XtCallbackProc
) radio_callback
,
1349 if (strchr (checked
, ','))
1350 stdarg (XmNindicatorType
, XmONE_OF_MANY
);
1352 stdarg (XmNindicatorType
, XmN_OF_MANY
);
1353 btn
= XmCreateToggleButton (menu
, "menubutton", args
, n
);
1354 XtAddCallback (btn
, XmNvalueChangedCallback
,
1355 callback
, (XtPointer
) node
->v
[i
].subres
);
1357 else if (label
&& strcmp (label
, "false") == 0)
1359 stdarg (XmNalignment
, XmALIGNMENT_BEGINNING
);
1360 btn
= XmCreateLabel (menu
, "menulabel", args
, n
);
1364 btn
= XmCreatePushButton (menu
, "menubutton", args
, n
);
1365 XtAddCallback (btn
, XmNactivateCallback
,
1366 callback
, (XtPointer
) node
->v
[i
].subres
);
1369 for (j
= 0; j
< node
->v
[i
].subres
->c
; j
++)
1370 switch (resource_type (node
->v
[i
].subres
->v
[j
]))
1372 case 110: /* named value = X resource */
1374 char *n
= node
->v
[i
].subres
->v
[j
].name
;
1375 if (strcmp (n
, "fg") == 0)
1377 if (strcmp (n
, "bg") == 0)
1379 if (strcmp (n
, "m") == 0
1380 || strcmp (n
, "a") == 0
1381 || strcmp (n
, "sensitive") == 0)
1383 if (strcmp (n
, "checked") == 0)
1385 note_widget_flag (btn
, XmNset
,
1386 node
->v
[i
].subres
->v
[j
].value
);
1389 if (strcmp (n
, "active") == 0)
1391 note_widget_flag (btn
, XmNsensitive
,
1392 node
->v
[i
].subres
->v
[j
].value
);
1395 XtVaSetValues (btn
, XtVaTypedArg
,
1398 node
->v
[i
].subres
->v
[j
].value
,
1399 strlen (node
->v
[i
].subres
->v
[j
].value
) + 1,
1405 XtManageChild (btn
);
1409 case 10: /* unnamed value */
1411 if (node
->v
[i
].value
[0] == '@')
1413 if (strcmp (node
->v
[i
].value
, "@layerview") == 0)
1414 insert_layerview_buttons (menu
);
1415 if (strcmp (node
->v
[i
].value
, "@layerpick") == 0)
1416 insert_layerpick_buttons (menu
);
1417 if (strcmp (node
->v
[i
].value
, "@routestyles") == 0)
1418 lesstif_insert_style_buttons (menu
);
1420 else if (strcmp (node
->v
[i
].value
, "-") == 0)
1422 btn
= XmCreateSeparator (menu
, "sep", args
, n
);
1423 XtManageChild (btn
);
1427 btn
= XmCreatePushButton (menu
, node
->v
[i
].value
, args
, n
);
1428 XtManageChild (btn
);
1434 static char *pcbmenu_path
= "pcb-menu.res";
1436 static HID_Attribute pcbmenu_attr
[] = {
1437 {"pcb-menu", "Location of pcb-menu.res file",
1438 HID_String
, 0, 0, {0, PCBLIBDIR
"/pcb-menu.res", 0}, 0, &pcbmenu_path
}
1441 REGISTER_ATTRIBUTES(pcbmenu_attr
)
1444 lesstif_menu (Widget parent
, char *name
, Arg
* margs
, int mn
)
1446 Widget mb
= XmCreateMenuBar (parent
, name
, margs
, mn
);
1448 Resource
*r
= 0, *bir
;
1453 display
= XtDisplay (mb
);
1454 screen
= DefaultScreen (display
);
1455 cmap
= DefaultColormap (display
, screen
);
1457 home_pcbmenu
= Concat (getenv ("HOME"), "/.pcb/pcb-menu.res", NULL
);
1459 if (access ("pcb-menu.res", R_OK
) == 0)
1460 filename
= "pcb-menu.res";
1461 else if (access (home_pcbmenu
, R_OK
) == 0)
1462 filename
= home_pcbmenu
;
1463 else if (access (pcbmenu_path
, R_OK
) == 0)
1464 filename
= pcbmenu_path
;
1468 bir
= resource_parse (0, pcb_menu_default
);
1471 fprintf (stderr
, "Error: internal menu resource didn't parse\n");
1476 r
= resource_parse (filename
, 0);
1481 mr
= resource_subres (r
, "MainMenu");
1483 mr
= resource_subres (bir
, "MainMenu");
1485 add_resource_to_menu (mb
, mr
, (XtCallbackProc
) callback
);
1487 mr
= resource_subres (r
, "Mouse");
1489 mr
= resource_subres (bir
, "Mouse");
1491 lesstif_note_mouse_resource (mr
);