11 #include "xincludes.h"
17 #include "pcb-printf.h"
20 #include "../hidint.h"
21 #include "hid/common/hid_resource.h"
28 #ifdef HAVE_LIBDMALLOC
33 /* Common value for systems that don't define it. */
41 #define stdarg(t,v) XtSetArg(args[n], t, v), n++
43 static void note_accelerator (char *acc
, Resource
* node
);
44 static void note_widget_flag (Widget w
, char *type
, char *name
);
46 static const char getxy_syntax
[] =
49 static const char getxy_help
[] =
52 /* %start-doc actions GetXY
54 Prompts the user for a coordinate, if one is not already selected.
59 GetXY (int argc
, char **argv
, Coord x
, Coord y
)
64 static const char debug_syntax
[] =
67 static const char debug_help
[] =
70 /* %start-doc actions Debug
72 This action exists to help debug scripts; it simply prints all its
77 static const char debugxy_syntax
[] =
80 static const char debugxy_help
[] =
81 "Debug action, with coordinates";
83 /* %start-doc actions DebugXY
85 Like @code{Debug}, but requires a coordinate. If the user hasn't yet
86 indicated a location on the board, the user will be prompted to click
92 Debug (int argc
, char **argv
, Coord x
, Coord y
)
96 for (i
= 0; i
< argc
; i
++)
97 printf (" [%d] `%s'", i
, argv
[i
]);
98 pcb_printf (" x,y %$mD\n", x
, y
);
102 static const char return_syntax
[] =
105 static const char return_help
[] =
106 "Simulate a passing or failing action.";
108 /* %start-doc actions Return
110 This is for testing. If passed a 0, does nothing and succeeds. If
111 passed a 1, does nothing but pretends to fail.
116 Return (int argc
, char **argv
, Coord x
, Coord y
)
118 return atoi (argv
[0]);
121 static const char dumpkeys_syntax
[] =
124 static const char dumpkeys_help
[] =
125 "Dump Lesstif key bindings.";
127 /* %start-doc actions DumpKeys
129 Causes the list of key bindings (from @code{pcb-menu.res}) to be
130 dumped to stdout. This is most useful when invoked from the command
134 pcb --action-string DumpKeys
139 static int do_dump_keys
= 0;
141 DumpKeys (int argc
, char **argv
, Coord x
, Coord y
)
147 /*-----------------------------------------------------------------------------*/
149 #define LB_SILK (MAX_LAYER+0)
150 #define LB_RATS (MAX_LAYER+1)
151 #define LB_NUMPICK (LB_RATS+1)
153 #define LB_PINS (MAX_LAYER+2)
154 #define LB_VIAS (MAX_LAYER+3)
155 #define LB_BACK (MAX_LAYER+4)
156 #define LB_MASK (MAX_LAYER+5)
157 #define LB_NUM (MAX_LAYER+6)
165 static LayerButtons
*layer_button_list
= 0;
166 static int num_layer_buttons
= 0;
167 static int fg_colors
[LB_NUM
];
170 extern Widget lesstif_m_layer
;
173 LayersChanged (int argc
, char **argv
, Coord x
, Coord y
)
179 if (!layer_button_list
)
181 if (PCB
&& PCB
->Data
)
183 DataType
*d
= PCB
->Data
;
184 for (i
= 0; i
< MAX_LAYER
; i
++)
185 fg_colors
[i
] = lesstif_parse_color (d
->Layer
[i
].Color
);
186 fg_colors
[LB_SILK
] = lesstif_parse_color (PCB
->ElementColor
);
187 fg_colors
[LB_RATS
] = lesstif_parse_color (PCB
->RatColor
);
188 fg_colors
[LB_PINS
] = lesstif_parse_color (PCB
->PinColor
);
189 fg_colors
[LB_VIAS
] = lesstif_parse_color (PCB
->ViaColor
);
191 lesstif_parse_color (PCB
->InvisibleObjectsColor
);
192 fg_colors
[LB_MASK
] = lesstif_parse_color (PCB
->MaskColor
);
193 bg_color
= lesstif_parse_color (Settings
.BackgroundColor
);
197 for (i
= 0; i
< MAX_LAYER
; i
++)
198 fg_colors
[i
] = lesstif_parse_color (Settings
.LayerColor
[i
]);
199 fg_colors
[LB_SILK
] = lesstif_parse_color (Settings
.ElementColor
);
200 fg_colors
[LB_RATS
] = lesstif_parse_color (Settings
.RatColor
);
201 fg_colors
[LB_PINS
] = lesstif_parse_color (Settings
.PinColor
);
202 fg_colors
[LB_VIAS
] = lesstif_parse_color (Settings
.ViaColor
);
204 lesstif_parse_color (Settings
.InvisibleObjectsColor
);
205 fg_colors
[LB_MASK
] = lesstif_parse_color (Settings
.MaskColor
);
206 bg_color
= lesstif_parse_color (Settings
.BackgroundColor
);
210 current_layer
= LB_RATS
;
211 else if (PCB
->SilkActive
)
212 current_layer
= LB_SILK
;
214 current_layer
= LayerStack
[0];
216 for (l
= 0; l
< num_layer_buttons
; l
++)
218 LayerButtons
*lb
= layer_button_list
+ l
;
219 for (i
= 0; i
< (lb
->is_pick
? LB_NUMPICK
: LB_NUM
); i
++)
224 set
= PCB
->ElementOn
;
236 set
= PCB
->InvisibleObjectsOn
;
239 set
= TEST_FLAG (SHOWMASKFLAG
, PCB
);
241 default: /* layers */
242 set
= PCB
->Data
->Layer
[i
].On
;
247 if (i
< MAX_LAYER
&& PCB
->Data
->Layer
[i
].Name
)
249 XmString s
= XmStringCreatePCB (PCB
->Data
->Layer
[i
].Name
);
250 stdarg (XmNlabelString
, s
);
256 stdarg (XmNforeground
, bg_color
);
257 stdarg (XmNbackground
, fg_colors
[i
]);
261 stdarg (XmNforeground
, fg_colors
[i
]);
262 stdarg (XmNbackground
, bg_color
);
264 stdarg (XmNset
, set
);
268 stdarg (XmNforeground
, bg_color
);
269 stdarg (XmNbackground
, fg_colors
[i
]);
270 stdarg (XmNset
, current_layer
== i
? True
: False
);
272 XtSetValues (lb
->w
[i
], args
, n
);
274 if (i
>= max_copper_layer
&& i
< MAX_LAYER
)
275 XtUnmanageChild(lb
->w
[i
]);
277 XtManageChild(lb
->w
[i
]);
282 switch (current_layer
)
291 name
= PCB
->Data
->Layer
[current_layer
].Name
;
295 stdarg (XmNbackground
, fg_colors
[current_layer
]);
296 stdarg (XmNforeground
, bg_color
);
297 stdarg (XmNlabelString
, XmStringCreatePCB (name
));
298 XtSetValues (lesstif_m_layer
, args
, n
);
301 lesstif_update_layer_groups ();
307 show_one_layer_button (int layer
, int set
)
313 stdarg (XmNforeground
, bg_color
);
314 stdarg (XmNbackground
, fg_colors
[layer
]);
318 stdarg (XmNforeground
, fg_colors
[layer
]);
319 stdarg (XmNbackground
, bg_color
);
321 stdarg (XmNset
, set
);
323 for (l
= 0; l
< num_layer_buttons
; l
++)
325 LayerButtons
*lb
= layer_button_list
+ l
;
327 XtSetValues (lb
->w
[layer
], args
, n
);
332 layer_button_callback (Widget w
, int layer
, XmPushButtonCallbackStruct
* pbcs
)
338 set
= PCB
->ElementOn
= !PCB
->ElementOn
;
339 PCB
->Data
->SILKLAYER
.On
= set
;
340 PCB
->Data
->BACKSILKLAYER
.On
= set
;
343 set
= PCB
->RatOn
= !PCB
->RatOn
;
346 set
= PCB
->PinOn
= !PCB
->PinOn
;
349 set
= PCB
->ViaOn
= !PCB
->ViaOn
;
352 set
= PCB
->InvisibleObjectsOn
= !PCB
->InvisibleObjectsOn
;
355 TOGGLE_FLAG (SHOWMASKFLAG
, PCB
);
356 set
= TEST_FLAG (SHOWMASKFLAG
, PCB
);
358 default: /* layers */
359 set
= PCB
->Data
->Layer
[layer
].On
= !PCB
->Data
->Layer
[layer
].On
;
363 show_one_layer_button (layer
, set
);
364 if (layer
< max_copper_layer
)
367 int group
= GetLayerGroupNumberByNumber (layer
);
368 for (i
= 0; i
< PCB
->LayerGroups
.Number
[group
]; i
++)
370 l
= PCB
->LayerGroups
.Entries
[group
][i
];
371 if (l
!= layer
&& l
< max_copper_layer
)
373 show_one_layer_button (l
, set
);
374 PCB
->Data
->Layer
[l
].On
= set
;
378 lesstif_invalidate_all ();
382 layerpick_button_callback (Widget w
, int layer
,
383 XmPushButtonCallbackStruct
* pbcs
)
387 PCB
->RatDraw
= (layer
== LB_RATS
);
388 PCB
->SilkActive
= (layer
== LB_SILK
);
389 if (layer
< max_copper_layer
)
390 ChangeGroupVisibility (layer
, 1, 1);
391 for (l
= 0; l
< num_layer_buttons
; l
++)
393 LayerButtons
*lb
= layer_button_list
+ l
;
396 for (i
= 0; i
< LB_NUMPICK
; i
++)
397 XmToggleButtonSetState (lb
->w
[i
], layer
== i
, False
);
408 name
= PCB
->Data
->Layer
[layer
].Name
;
412 stdarg (XmNbackground
, fg_colors
[layer
]);
413 stdarg (XmNforeground
, bg_color
);
414 stdarg (XmNlabelString
, XmStringCreatePCB (name
));
415 XtSetValues (lesstif_m_layer
, args
, n
);
416 lesstif_invalidate_all ();
419 static const char selectlayer_syntax
[] =
420 "SelectLayer(1..MAXLAYER|Silk|Rats)";
422 static const char selectlayer_help
[] =
423 "Select which layer is the current layer.";
425 /* %start-doc actions SelectLayer
427 The specified layer becomes the currently active layer. It is made
428 visible if it is not already visible
433 SelectLayer (int argc
, char **argv
, Coord x
, Coord y
)
440 for (i
= 0; i
< max_copper_layer
; ++i
)
441 if (strcasecmp (argv
[0], PCB
->Data
->Layer
[i
].Name
) == 0)
444 if (strcasecmp (argv
[0], "silk") == 0)
446 else if (strcasecmp (argv
[0], "rats") == 0)
449 newl
= atoi (argv
[0]) - 1;
450 layerpick_button_callback (0, newl
, 0);
454 static const char toggleview_syntax
[] =
455 "ToggleView(1..MAXLAYER)\n"
456 "ToggleView(layername)\n"
457 "ToggleView(Silk|Rats|Pins|Vias|Mask|BackSide)";
459 static const char toggleview_help
[] =
460 "Toggle the visibility of the specified layer or layer group.";
462 /* %start-doc actions ToggleView
464 If you pass an integer, that layer is specified by index (the first
465 layer is @code{1}, etc). If you pass a layer name, that layer is
466 specified by name. When a layer is specified, the visibility of the
467 layer group containing that layer is toggled.
469 If you pass a special layer name, the visibility of those components
470 (silk, rats, etc) is toggled. Note that if you have a layer named
471 the same as a special layer, the layer is chosen over the special layer.
476 ToggleView (int argc
, char **argv
, Coord x
, Coord y
)
482 if (isdigit ((int) argv
[0][0]))
484 l
= atoi (argv
[0]) - 1;
485 layer_button_callback (0, l
, 0);
487 else if (strcmp (argv
[0], "Silk") == 0)
488 layer_button_callback (0, LB_SILK
, 0);
489 else if (strcmp (argv
[0], "Rats") == 0)
490 layer_button_callback (0, LB_RATS
, 0);
491 else if (strcmp (argv
[0], "Pins") == 0)
492 layer_button_callback (0, LB_PINS
, 0);
493 else if (strcmp (argv
[0], "Vias") == 0)
494 layer_button_callback (0, LB_VIAS
, 0);
495 else if (strcmp (argv
[0], "Mask") == 0)
496 layer_button_callback (0, LB_MASK
, 0);
497 else if (strcmp (argv
[0], "BackSide") == 0)
498 layer_button_callback (0, LB_BACK
, 0);
502 for (i
= 0; i
< max_copper_layer
+ 2; i
++)
503 if (strcmp (argv
[0], PCB
->Data
->Layer
[i
].Name
) == 0)
510 layer_button_callback (0, l
, 0);
516 insert_layerview_buttons (Widget menu
)
522 s
= num_layer_buttons
* sizeof (LayerButtons
);
523 if (layer_button_list
)
524 layer_button_list
= (LayerButtons
*) realloc (layer_button_list
, s
);
526 layer_button_list
= (LayerButtons
*) malloc (s
);
527 lb
= layer_button_list
+ num_layer_buttons
- 1;
529 for (i
= 0; i
< LB_NUM
; i
++)
531 static char namestr
[] = "Label ";
532 char *name
= namestr
;
540 accel_idx
= max_copper_layer
;
544 accel_idx
= max_copper_layer
+ 1;
556 name
= "Solder Mask";
562 char buf
[20], av
[30];
565 sprintf (buf
, "Ctrl-%d", accel_idx
+ 1);
566 as
= XmStringCreatePCB (buf
);
567 stdarg (XmNacceleratorText
, as
);
568 ar
= resource_create (0);
569 sprintf (av
, "ToggleView(%d)", i
+ 1);
570 resource_add_val (ar
, 0, strdup (av
), 0);
571 resource_add_val (ar
, 0, strdup (av
), 0);
573 sprintf (av
, "Ctrl<Key>%d", accel_idx
+ 1);
574 note_accelerator (av
, ar
);
575 stdarg (XmNmnemonic
, accel_idx
+ '1');
577 btn
= XmCreateToggleButton (menu
, name
, args
, n
);
579 XtAddCallback (btn
, XmNvalueChangedCallback
,
580 (XtCallbackProc
) layer_button_callback
, (XtPointer
) (size_t) i
);
584 note_widget_flag (btn
, XmNset
, "showmask");
587 LayersChanged (0, 0, 0, 0);
591 insert_layerpick_buttons (Widget menu
)
597 s
= num_layer_buttons
* sizeof (LayerButtons
);
598 if (layer_button_list
)
599 layer_button_list
= (LayerButtons
*) realloc (layer_button_list
, s
);
601 layer_button_list
= (LayerButtons
*) malloc (s
);
602 lb
= layer_button_list
+ num_layer_buttons
- 1;
604 for (i
= 0; i
< LB_NUMPICK
; i
++)
606 static char namestr
[] = "Label ";
607 char *name
= namestr
;
609 char buf
[20], av
[30];
616 accel_idx
= max_copper_layer
;
617 strcpy (av
, "SelectLayer(Silk)");
621 accel_idx
= max_copper_layer
+ 1;
622 strcpy (av
, "SelectLayer(Rats)");
625 sprintf (av
, "SelectLayer(%d)", i
+ 1);
633 ar
= resource_create (0);
634 resource_add_val (ar
, 0, strdup (av
), 0);
635 resource_add_val (ar
, 0, strdup (av
), 0);
637 sprintf (buf
, "%d", i
+ 1);
638 as
= XmStringCreatePCB (buf
);
639 stdarg (XmNacceleratorText
, as
);
640 sprintf (av
, "<Key>%d", accel_idx
+ 1);
641 note_accelerator (av
, ar
);
642 stdarg (XmNmnemonic
, accel_idx
+ '1');
644 stdarg (XmNindicatorType
, XmONE_OF_MANY
);
645 btn
= XmCreateToggleButton (menu
, name
, args
, n
);
647 XtAddCallback (btn
, XmNvalueChangedCallback
,
648 (XtCallbackProc
) layerpick_button_callback
,
649 (XtPointer
) (size_t) i
);
653 LayersChanged (0, 0, 0, 0);
656 /*-----------------------------------------------------------------------------*/
661 const char *flagname
;
666 static WidgetFlagType
*wflags
= 0;
667 static int n_wflags
= 0;
668 static int max_wflags
= 0;
671 note_widget_flag (Widget w
, char *type
, char *name
)
673 if (n_wflags
>= max_wflags
)
676 wflags
= (WidgetFlagType
*) realloc (wflags
, max_wflags
* sizeof (WidgetFlagType
));
678 wflags
[n_wflags
].w
= w
;
679 wflags
[n_wflags
].flagname
= name
;
680 wflags
[n_wflags
].oldval
= -1;
681 wflags
[n_wflags
].xres
= type
;
686 lesstif_update_widget_flags ()
690 for (i
= 0; i
< n_wflags
; i
++)
692 int v
= hid_get_flag (wflags
[i
].flagname
);
694 XtSetArg (args
[0], wflags
[i
].xres
, v
? 1 : 0);
695 XtSetValues (wflags
[i
].w
, args
, 1);
696 wflags
[i
].oldval
= v
;
700 /*-----------------------------------------------------------------------------*/
702 HID_Action lesstif_menu_action_list
[] = {
703 {"DumpKeys", 0, DumpKeys
,
704 dumpkeys_help
, dumpkeys_syntax
},
706 debug_help
, debug_syntax
},
707 {"DebugXY", "Click X,Y for Debug", Debug
,
708 debugxy_help
, debugxy_syntax
},
710 getxy_help
, getxy_syntax
},
711 {"Return", 0, Return
,
712 return_help
, return_syntax
},
713 {"LayersChanged", 0, LayersChanged
,
714 layerschanged_help
, layerschanged_syntax
},
715 {"ToggleView", 0, ToggleView
,
716 toggleview_help
, toggleview_syntax
},
717 {"SelectLayer", 0, SelectLayer
,
718 selectlayer_help
, selectlayer_syntax
}
721 REGISTER_ACTIONS (lesstif_menu_action_list
)
725 do_color (char *value
, char *which
)
728 if (XParseColor (display
, cmap
, value
, &color
))
729 if (XAllocColor (display
, cmap
, &color
))
731 stdarg (which
, color
.pixel
);
736 typedef struct ToggleItem
738 struct ToggleItem
*next
;
741 XtCallbackProc callback
;
744 static ToggleItem
*toggle_items
= 0;
746 static int need_xy
= 0, have_xy
= 0, action_x
, action_y
;
749 radio_callback (Widget toggle
, ToggleItem
* me
,
750 XmToggleButtonCallbackStruct
* cbs
)
752 if (!cbs
->set
) /* uh uh, can't turn it off */
753 XmToggleButtonSetState (toggle
, 1, 0);
757 for (ti
= toggle_items
; ti
; ti
= ti
->next
)
758 if (strcmp (me
->group
, ti
->group
) == 0)
760 if (me
->item
== ti
->item
|| strcmp (me
->item
, ti
->item
) == 0)
761 XmToggleButtonSetState (ti
->w
, 1, 0);
763 XmToggleButtonSetState (ti
->w
, 0, 0);
765 me
->callback (toggle
, me
->node
, cbs
);
770 lesstif_button_event (Widget w
, XEvent
* e
)
773 action_x
= e
->xbutton
.x
;
774 action_y
= e
->xbutton
.y
;
783 lesstif_get_xy (const char *message
)
785 XmString ls
= XmStringCreatePCB ((char *)message
);
787 XtManageChild (m_click
);
789 stdarg (XmNlabelString
, ls
);
790 XtSetValues (m_click
, args
, n
);
791 //printf("need xy: msg `%s'\n", msg);
793 XBell (display
, 100);
797 XtAppNextEvent (app_context
, &e
);
798 XtDispatchEvent (&e
);
802 XtUnmanageChild (m_click
);
806 lesstif_get_coords (const char *msg
, Coord
*px
, Coord
*py
)
809 lesstif_get_xy (msg
);
811 lesstif_coords_to_pcb (action_x
, action_y
, px
, py
);
815 callback (Widget w
, Resource
* node
, XmPushButtonCallbackStruct
* pbcs
)
819 lesstif_show_crosshair (0);
820 if (pbcs
->event
&& pbcs
->event
->type
== KeyPress
)
823 Widget aw
= XtWindowToWidget (display
, pbcs
->event
->xkey
.window
);
824 action_x
= pbcs
->event
->xkey
.x
;
825 action_y
= pbcs
->event
->xkey
.y
;
828 Widget p
= work_area
;
834 XtGetValues (p
, args
, n
);
842 //pcb_printf("have xy from %s: %$mD\n", XtName(aw), action_x, action_y);
845 lesstif_need_idle_proc ();
846 for (vi
= 1; vi
< node
->c
; vi
++)
847 if (resource_type (node
->v
[vi
]) == 10)
848 if (hid_parse_actions (node
->v
[vi
].value
))
852 typedef struct acc_table_t
857 /* If M_Multi is set in mods, these are used to chain to the next
858 attribute table for multi-key accelerators. */
861 struct acc_table_t
*chain
;
863 /* If M_Multi isn't set, these are used to map a single key to an
872 static acc_table_t
*acc_table
;
873 static int acc_num
= 0;
876 acc_sort (const void *va
, const void *vb
)
878 acc_table_t
*a
= (acc_table_t
*) va
;
879 acc_table_t
*b
= (acc_table_t
*) vb
;
880 if (a
->key_char
!= b
->key_char
)
881 return a
->key_char
- b
->key_char
;
882 if (!(a
->mods
& M_Multi
))
883 if (a
->u
.a
.key
!= b
->u
.a
.key
)
884 return a
->u
.a
.key
- b
->u
.a
.key
;
885 return a
->mods
- b
->mods
;
893 printf ("in dumpkeys! %d\n", acc_num
);
894 qsort (acc_table
, acc_num
, sizeof (acc_table_t
), acc_sort
);
896 for (i
= 0; i
< acc_num
; i
++)
902 sprintf (mod
, "%s%s%s",
903 acc_table
[i
].mods
& M_Alt
? "Alt-" : "",
904 acc_table
[i
].mods
& M_Ctrl
? "Ctrl-" : "",
905 acc_table
[i
].mods
& M_Shift
? "Shift-" : "");
906 ch
[0] = toupper ((int) acc_table
[i
].key_char
);
907 printf ("%16s%s\t", mod
,
908 acc_table
[i
].key_char
? ch
: XKeysymToString (acc_table
[i
].
911 for (vi
= 1; vi
< acc_table
[i
].u
.a
.node
->c
; vi
++)
912 if (resource_type (acc_table
[i
].u
.a
.node
->v
[vi
]) == 10)
914 printf ("%s%s", tabs
, acc_table
[i
].u
.a
.node
->v
[vi
].value
);
924 find_or_create_acc (char mods
, char key
, KeySym sym
,
925 acc_table_t
**table
, int *n_ents
)
931 for (i
=(*n_ents
)-1; i
>=0; i
--)
935 && a
->key_char
== key
936 && (mods
& M_Multi
|| a
->u
.a
.key
== sym
))
941 max
= (*n_ents
+ 16) & ~15;
944 *table
= (acc_table_t
*) realloc (*table
, max
* sizeof (acc_table_t
));
946 *table
= (acc_table_t
*) malloc (max
* sizeof (acc_table_t
));
948 a
= & ((*table
)[(*n_ents
)-1]);
949 memset (a
, 0, sizeof(acc_table_t
));
953 if (!(mods
& M_Multi
))
960 note_accelerator (char *acc
, Resource
* node
)
962 char *orig_acc
= acc
;
969 while (isalpha ((int) acc
[0]))
971 if (strncmp (acc
, "Shift", 5) == 0)
976 else if (strncmp (acc
, "Ctrl", 4) == 0)
981 else if (strncmp (acc
, "Alt", 3) == 0)
988 printf ("Must be Shift/Ctrl/Alt: %s\n", acc
);
994 if (strncmp (acc
, "<Keys>", 6) == 0)
999 else if (strncmp (acc
, "<Key>", 5))
1001 fprintf (stderr
, "accelerator \"%s\" not <Key> or <Keys>\n", orig_acc
);
1005 /* We have a hard time specifying the Enter key the "usual" way. */
1006 if (strcmp (acc
, "<Key>Enter") == 0)
1010 if (acc
[0] && acc
[1] == 0)
1013 a
= find_or_create_acc (mods
, key_char
, 0, &acc_table
, &acc_num
);
1017 acc_table_t
**ap
= &acc_table
;
1021 while (acc
[0] && acc
[1])
1023 a
= find_or_create_acc (mods
, acc
[0], 0, ap
, np
);
1024 ap
= & (a
->u
.c
.chain
);
1025 np
= & (a
->u
.c
.n_chain
);
1028 a
= find_or_create_acc (mods
& ~M_Multi
, acc
[0], 0, ap
, np
);
1032 key
= XStringToKeysym (acc
);
1033 if (key
== NoSymbol
&& !key_char
)
1035 printf ("no symbol for %s\n", acc
);
1038 a
= find_or_create_acc (mods
, 0, key
, &acc_table
, &acc_num
);
1046 dump_multi (int ix
, int ind
, acc_table_t
*a
, int n
)
1051 if (a
->mods
& M_Multi
)
1053 printf("%*cacc[%d] mods %x char %c multi %p/%d\n",
1055 i
, a
->mods
, a
->key_char
,
1056 a
->u
.c
.chain
, a
->u
.c
.n_chain
);
1057 dump_multi(0, ind
+4, a
->u
.c
.chain
, a
->u
.c
.n_chain
);
1061 printf("%*cacc[%d] mods %x char %c key %d node `%s'\n",
1063 i
, a
->mods
, a
->key_char
,
1064 a
->u
.a
.key
, a
->u
.a
.node
->v
[0].value
);
1071 #define dump_multi(x,a,b,c)
1074 static acc_table_t
*cur_table
= 0;
1075 static int cur_ntable
= 0;
1077 /* We sort these such that the ones with explicit modifiers come
1078 before the ones with implicit modifiers. That way, a
1079 Shift<Key>Code gets chosen before a <Key>Code. */
1081 acc_sort_rev (const void *va
, const void *vb
)
1083 acc_table_t
*a
= (acc_table_t
*) va
;
1084 acc_table_t
*b
= (acc_table_t
*) vb
;
1085 if (a
->key_char
!= b
->key_char
)
1086 return a
->key_char
- b
->key_char
;
1087 if (!(a
->mods
& M_Multi
))
1088 if (a
->u
.a
.key
!= b
->u
.a
.key
)
1089 return a
->u
.a
.key
- b
->u
.a
.key
;
1090 return b
->mods
- a
->mods
;
1094 lesstif_key_event (XKeyEvent
* e
)
1096 char buf
[10], buf2
[10];
1101 static int sorted
= 0;
1102 acc_table_t
*my_table
= 0;
1107 qsort (acc_table
, acc_num
, sizeof (acc_table_t
), acc_sort_rev
);
1110 if (e
->state
& ShiftMask
)
1112 if (e
->state
& ControlMask
)
1114 if (e
->state
& Mod1Mask
)
1117 e
->state
&= ~(ControlMask
| Mod1Mask
);
1118 slen
= XLookupString (e
, buf
, sizeof (buf
), &sym
, NULL
);
1120 if (e
->state
& ShiftMask
)
1122 e
->state
&= ~ShiftMask
;
1123 slen2
= XLookupString (e
, buf2
, sizeof (buf2
), &sym2
, NULL
);
1145 case XK_ISO_Level3_Shift
:
1151 cur_table
= acc_table
;
1152 cur_ntable
= acc_num
;
1155 //printf("\nmods %x key %d str `%s' in %p/%d\n", mods, (int)sym, buf, cur_table, cur_ntable);
1157 #define KM(m) ((m) & ~M_Multi)
1158 for (i
= 0; i
< cur_ntable
; i
++)
1160 dump_multi (i
, 0, cur_table
+i
, 1);
1161 if (KM(cur_table
[i
].mods
) == mods
)
1163 if (sym
== acc_table
[i
].u
.a
.key
)
1166 if (KM(cur_table
[i
].mods
) == (mods
& ~M_Shift
))
1168 if (slen
== 1 && buf
[0] == cur_table
[i
].key_char
)
1170 if (sym
== cur_table
[i
].u
.a
.key
)
1173 if (mods
& M_Shift
&& KM(cur_table
[i
].mods
) == mods
)
1175 if (slen2
== 1 && buf2
[0] == cur_table
[i
].key_char
)
1177 if (sym2
== acc_table
[i
].u
.a
.key
)
1182 if (i
== cur_ntable
)
1184 if (cur_table
== acc_table
)
1185 lesstif_log ("Key \"%s\" not tied to an action\n", buf
);
1187 lesstif_log ("Key \"%s\" not tied to a multi-key action\n", buf
);
1191 if (cur_table
[i
].mods
& M_Multi
)
1193 cur_ntable
= cur_table
[i
].u
.c
.n_chain
;
1194 cur_table
= cur_table
[i
].u
.c
.chain
;
1195 dump_multi (0, 0, cur_table
, cur_ntable
);
1199 if (e
->window
== XtWindow (work_area
))
1208 /* Parsing actions may not return until more user interaction
1209 happens, so remember which table we're scanning. */
1210 my_table
= cur_table
;
1211 for (vi
= 1; vi
< my_table
[i
].u
.a
.node
->c
; vi
++)
1212 if (resource_type (my_table
[i
].u
.a
.node
->v
[vi
]) == 10)
1213 if (hid_parse_actions
1214 (my_table
[i
].u
.a
.node
->v
[vi
].value
))
1221 add_resource_to_menu (Widget menu
, Resource
* node
, XtCallbackProc callback
)
1228 for (i
= 0; i
< node
->c
; i
++)
1229 switch (resource_type (node
->v
[i
]))
1231 case 101: /* named subnode */
1233 stdarg (XmNtearOffModel
, XmTEAR_OFF_ENABLED
);
1234 sub
= XmCreatePulldownMenu (menu
, node
->v
[i
].name
, args
, n
);
1235 XtSetValues (sub
, args
, n
);
1237 stdarg (XmNsubMenuId
, sub
);
1238 btn
= XmCreateCascadeButton (menu
, node
->v
[i
].name
, args
, n
);
1239 XtManageChild (btn
);
1240 add_resource_to_menu (sub
, node
->v
[i
].subres
, callback
);
1243 case 1: /* unnamed subres */
1246 if ((v
= resource_value (node
->v
[i
].subres
, "fg")))
1248 do_color (v
, XmNforeground
);
1250 if ((v
= resource_value (node
->v
[i
].subres
, "bg")))
1252 do_color (v
, XmNbackground
);
1254 if ((v
= resource_value (node
->v
[i
].subres
, "font")))
1256 XFontStruct
*fs
= XLoadQueryFont (display
, v
);
1260 XmFontListCreate (fs
, XmSTRING_DEFAULT_CHARSET
);
1261 stdarg (XmNfontList
, fl
);
1265 if ((v
= resource_value (node
->v
[i
].subres
, "m")))
1267 stdarg (XmNmnemonic
, v
);
1269 if ((r
= resource_subres (node
->v
[i
].subres
, "a")))
1271 XmString as
= XmStringCreatePCB (r
->v
[0].value
);
1272 stdarg (XmNacceleratorText
, as
);
1273 //stdarg(XmNaccelerator, r->v[1].value);
1274 note_accelerator (r
->v
[1].value
, node
->v
[i
].subres
);
1277 for (j
= 0; j
< node
->v
[i
].subres
->c
; j
++)
1278 if (resource_type (node
->v
[i
].subres
->v
[j
]) == 10)
1280 v
= node
->v
[i
].subres
->v
[j
].value
;
1283 stdarg (XmNlabelString
, XmStringCreatePCB (v
));
1284 if (node
->v
[i
].subres
->flags
& FLAG_S
)
1287 stdarg (XmNtearOffModel
, XmTEAR_OFF_ENABLED
);
1288 sub
= XmCreatePulldownMenu (menu
, v
, args
+ nn
, n
- nn
);
1290 stdarg (XmNsubMenuId
, sub
);
1291 btn
= XmCreateCascadeButton (menu
, "menubutton", args
, n
);
1292 XtManageChild (btn
);
1293 add_resource_to_menu (sub
, node
->v
[i
].subres
, callback
);
1297 Resource
*radio
= resource_subres (node
->v
[i
].subres
, "radio");
1298 char *checked
= resource_value (node
->v
[i
].subres
, "checked");
1299 char *label
= resource_value (node
->v
[i
].subres
, "sensitive");
1302 ToggleItem
*ti
= (ToggleItem
*) malloc (sizeof (ToggleItem
));
1303 ti
->next
= toggle_items
;
1304 ti
->group
= radio
->v
[0].value
;
1305 ti
->item
= radio
->v
[1].value
;
1306 ti
->callback
= callback
;
1307 ti
->node
= node
->v
[i
].subres
;
1310 if (resource_value (node
->v
[i
].subres
, "set"))
1312 stdarg (XmNset
, True
);
1314 stdarg (XmNindicatorType
, XmONE_OF_MANY
);
1315 btn
= XmCreateToggleButton (menu
, "menubutton", args
, n
);
1317 XtAddCallback (btn
, XmNvalueChangedCallback
,
1318 (XtCallbackProc
) radio_callback
,
1323 if (strchr (checked
, ','))
1324 stdarg (XmNindicatorType
, XmONE_OF_MANY
);
1326 stdarg (XmNindicatorType
, XmN_OF_MANY
);
1327 btn
= XmCreateToggleButton (menu
, "menubutton", args
, n
);
1328 XtAddCallback (btn
, XmNvalueChangedCallback
,
1329 callback
, (XtPointer
) node
->v
[i
].subres
);
1331 else if (label
&& strcmp (label
, "false") == 0)
1333 stdarg (XmNalignment
, XmALIGNMENT_BEGINNING
);
1334 btn
= XmCreateLabel (menu
, "menulabel", args
, n
);
1338 btn
= XmCreatePushButton (menu
, "menubutton", args
, n
);
1339 XtAddCallback (btn
, XmNactivateCallback
,
1340 callback
, (XtPointer
) node
->v
[i
].subres
);
1343 for (j
= 0; j
< node
->v
[i
].subres
->c
; j
++)
1344 switch (resource_type (node
->v
[i
].subres
->v
[j
]))
1346 case 110: /* named value = X resource */
1348 char *n
= node
->v
[i
].subres
->v
[j
].name
;
1349 if (strcmp (n
, "fg") == 0)
1351 if (strcmp (n
, "bg") == 0)
1353 if (strcmp (n
, "m") == 0
1354 || strcmp (n
, "a") == 0
1355 || strcmp (n
, "sensitive") == 0)
1357 if (strcmp (n
, "checked") == 0)
1359 note_widget_flag (btn
, XmNset
,
1360 node
->v
[i
].subres
->v
[j
].value
);
1363 if (strcmp (n
, "active") == 0)
1365 note_widget_flag (btn
, XmNsensitive
,
1366 node
->v
[i
].subres
->v
[j
].value
);
1369 XtVaSetValues (btn
, XtVaTypedArg
,
1372 node
->v
[i
].subres
->v
[j
].value
,
1373 strlen (node
->v
[i
].subres
->v
[j
].value
) + 1,
1379 XtManageChild (btn
);
1383 case 10: /* unnamed value */
1385 if (node
->v
[i
].value
[0] == '@')
1387 if (strcmp (node
->v
[i
].value
, "@layerview") == 0)
1388 insert_layerview_buttons (menu
);
1389 if (strcmp (node
->v
[i
].value
, "@layerpick") == 0)
1390 insert_layerpick_buttons (menu
);
1391 if (strcmp (node
->v
[i
].value
, "@routestyles") == 0)
1392 lesstif_insert_style_buttons (menu
);
1394 else if (strcmp (node
->v
[i
].value
, "-") == 0)
1396 btn
= XmCreateSeparator (menu
, "sep", args
, n
);
1397 XtManageChild (btn
);
1401 btn
= XmCreatePushButton (menu
, node
->v
[i
].value
, args
, n
);
1402 XtManageChild (btn
);
1408 extern char *lesstif_pcbmenu_path
;
1411 lesstif_menu (Widget parent
, char *name
, Arg
* margs
, int mn
)
1413 Widget mb
= XmCreateMenuBar (parent
, name
, margs
, mn
);
1415 Resource
*r
= 0, *bir
;
1416 char *home_pcbmenu
, *home
;
1420 display
= XtDisplay (mb
);
1421 screen
= DefaultScreen (display
);
1422 cmap
= DefaultColormap (display
, screen
);
1424 /* homedir is set by the core */
1426 home_pcbmenu
= NULL
;
1429 Message ("Warning: could not determine home directory (from HOME)\n");
1433 home_pcbmenu
= Concat (home
, PCB_DIR_SEPARATOR_S
, ".pcb",
1434 PCB_DIR_SEPARATOR_S
, "pcb-menu.res", NULL
);
1437 if (access ("pcb-menu.res", R_OK
) == 0)
1438 filename
= "pcb-menu.res";
1439 else if (home_pcbmenu
!= NULL
&& (access (home_pcbmenu
, R_OK
) == 0))
1440 filename
= home_pcbmenu
;
1441 else if (access (lesstif_pcbmenu_path
, R_OK
) == 0)
1442 filename
= lesstif_pcbmenu_path
;
1446 bir
= resource_parse (0, pcb_menu_default
);
1449 fprintf (stderr
, "Error: internal menu resource didn't parse\n");
1454 r
= resource_parse (filename
, 0);
1459 if (home_pcbmenu
!= NULL
)
1461 free (home_pcbmenu
);
1464 mr
= resource_subres (r
, "MainMenu");
1466 mr
= resource_subres (bir
, "MainMenu");
1468 add_resource_to_menu (mb
, mr
, (XtCallbackProc
) callback
);
1470 mr
= resource_subres (r
, "Mouse");
1472 mr
= resource_subres (bir
, "Mouse");
1474 load_mouse_resource (mr
);