1 /*
2  *	xtrojka (c) 1994,1995,1996 Maarten Los
3  *
4  *	#include "COPYRIGHT"
5  *
6  *	created:	27.xi.1995
7  *	modified:	24.xii.1995
8  *
9  *	This module is a low-level menu handler
10  */
11 
12 #include <X11/Intrinsic.h>
13 #include <X11/StringDefs.h>
14 #include <X11/Shell.h>
15 
16 #include <X11/Xaw/Command.h>
17 #include <X11/Xaw/Box.h>
18 
19 #include <stdlib.h>
20 
21 #include "xtrojka.h"
22 #include "tr_core.h"
23 #include "menu_tool.h"
24 #include "menu.h"
25 #include "debug.h"
26 
27 
28 extern Widget trojkamenu_but;
29 extern Widget speedmenu_but;
30 extern XtAppContext app_context;
31 
32 
33 Widget trojkamenu_itembox[TROJKAMENU_ITEMS];
34 Widget trojkamenu_shell, trojkamenu_box;
35 ITEM_LIST trojkamenu_item[TROJKAMENU_ITEMS] = {
36 	{ "new_game",		"^N" },
37 	{ "abort_game",		"^A" },
38 	{ "-", 			NO_HOT },
39 	{ "wizard",	 	"^W" },
40 	{ "slick", 		"^S" },
41 	{ "-",			NO_HOT },
42 	{ "quit",		"^Q" }
43 };
44 
45 
46 Widget speedmenu_itembox[SPEEDMENU_ITEMS];
47 Widget speedmenu_shell, speedmenu_box;
48 ITEM_LIST speedmenu_item[SPEEDMENU_ITEMS] = {
49 	{ "boring",	NO_HOT },
50 	{ "",		NO_HOT },
51 	{ "slow",	NO_HOT },
52 	{ "",		NO_HOT },
53 	{ "normal",	NO_HOT },
54 	{ "",		NO_HOT },
55 	{ "fast",	NO_HOT },
56 	{ "",		NO_HOT },
57 	{ "nerd_speed", NO_HOT }
58 };
59 
60 static MENU_BLOCK *trojka_menu;
61 static MENU_BLOCK *speed_menu;
62 
63 
64 /*
65  *	the functions
66  */
init_menu_sys(void)67 void init_menu_sys(void)
68 {
69 /*
70  *	this function inits the menus' for xtrojka
71  */
72 	int i;
73 	String label;
74 	char tmp[255];
75 
76 	DEBUG("menu_tool.c", "init_menu_sys")
77 
78 	init_trojkamenu();
79 	init_speedmenu();
80 
81 	format_menu(trojkamenu_item, trojkamenu_itembox, TROJKAMENU_ITEMS);
82 	format_menu(speedmenu_item, speedmenu_itembox, SPEEDMENU_ITEMS);
83 
84 	/*
85 	 *	add speed digits to the speed menu
86 	 */
87 	for(i = 0; i < SPEEDMENU_ITEMS; i++) {
88 		XtVaGetValues(speedmenu_itembox[i],
89 			XtNlabel, &label,
90 			NULL);
91 		sprintf(tmp," %d%s", i+1, label);
92 		XtVaSetValues(speedmenu_itembox[i],
93 			XtNlabel, tmp,
94 			NULL);
95 	}
96 }
97 
98 
99 
init_trojkamenu(void)100 void init_trojkamenu(void)
101 {
102 	int i;
103 
104 	DEBUG("menu_tool.c", "init_trojkamenu");
105 
106 	/*
107 	 *	create the menu and add the items to it
108 	 */
109 	trojka_menu = create_menu("trojka",
110 				trojkamenu_but,
111 				&trojkamenu_shell,
112 				&trojkamenu_box,
113 				trojkamenu_select_callback);
114 
115 	for(i = 0; i < TROJKAMENU_ITEMS; i++) {
116 		add_menu(trojka_menu, trojkamenu_item[i].name,
117 			&(trojkamenu_itembox[i]));
118 	}
119 }
120 
121 
init_speedmenu(void)122 void init_speedmenu(void)
123 {
124 	int i;
125 
126 	DEBUG("menu_tool.c", "init_speedmenu");
127 
128 	speed_menu = create_menu("speed",
129 				speedmenu_but,
130 				&speedmenu_shell,
131 				&speedmenu_box,
132 				speedmenu_select_callback);
133 
134 	for(i = 0; i < SPEEDMENU_ITEMS; i++) {
135 		add_menu(speed_menu, speedmenu_item[i].name,
136 				&(speedmenu_itembox[i]));
137 	}
138 }
139 
140 
141 
create_menu(name,parent_button,shell,menu_box,std_callback)142 MENU_BLOCK *create_menu(name, parent_button, shell, menu_box, std_callback)
143 String name;
144 Widget parent_button;
145 Widget *shell, *menu_box;
146 void (*std_callback)();
147 /*
148  *	make a menu
149  */
150 {
151 	char tmp[255];
152 	char shell_name[255];
153 	XtTranslations mytrans;
154 	MENU_BLOCK *mb;
155 
156 	DEBUG("menu_tool.c", "build_menu");
157 
158 	if((mb = (MENU_BLOCK*)malloc(sizeof(MENU_BLOCK))) == NULL)
159 		XtAppError(app_context, "create_menu: No memory for menu");
160 
161 	sprintf(shell_name,"%s_shell", name);
162 
163 	*shell = XtCreatePopupShell(
164 		shell_name,
165 		overrideShellWidgetClass,
166 		parent_button,
167 		NULL,
168 		0
169 	);
170 
171 	sprintf(tmp,"%s_menu", name);
172 	*menu_box = XtVaCreateManagedWidget(
173 		tmp,
174 		boxWidgetClass,
175 		*shell,
176 		XtNhSpace, 0,
177 		XtNvSpace, 0,
178 		NULL
179 	);
180 
181 	sprintf(tmp,"<EnterWindow>: highlight() \n\
182 		 <LeaveWindow>: reset() \n\
183 		 <BtnDown>: set() XtMenuPopup(%s) reset()", shell_name);
184 	mytrans = XtParseTranslationTable(tmp);
185 	XtOverrideTranslations(parent_button, mytrans);
186 
187 	sprintf(tmp, "<BtnUp>: XtMenuPopdown(%s) ", shell_name);
188 	mytrans = XtParseTranslationTable(tmp);
189 	XtOverrideTranslations(*shell, mytrans);
190 
191 	mb->menu_button = parent_button;
192 	mb->menu_shell = *shell;
193 	mb->menu_box = *menu_box;
194 	mb->item_count = 0;
195 	mb->std_callback = std_callback;
196 
197 	XtAddCallback(*shell,
198 		XtNpopupCallback,
199 		popup_callback,
200 		mb
201 	);
202 
203 	return mb;
204 }
205 
206 
add_menu(menu,res_name,widget)207 void add_menu(menu, res_name, widget)
208 MENU_BLOCK *menu;
209 String res_name;
210 Widget *widget;
211 {
212 	XtTranslations mytrans;
213 
214 	DEBUG("menu_tool.c", "add_menu");
215 
216 	mytrans = XtParseTranslationTable(
217 		"<EnterWindow>: set() \n\
218 		 <LeaveWindow>: unset() \n\
219 		 <BtnDown>: notify() unset()"
220 	);
221 
222 	*widget = XtVaCreateManagedWidget(
223 		res_name, commandWidgetClass,
224 		menu->menu_box,
225 		XtNborderWidth, 0,
226 		NULL
227 	);
228 
229 	if(res_name[0] != '-') {
230 		XtAddCallback(*widget,
231 			XtNcallback,
232 			menu->std_callback,
233 			(XtPointer)menu->item_count);
234 		XtOverrideTranslations(*widget, mytrans);
235 	} else
236 		XtSetSensitive(*widget, False);
237 
238 	menu->item_count++;
239 }
240 
241 
242 
format_menu(item_list,bar_list,items)243 void format_menu(item_list, bar_list, items)
244 ITEM_LIST *item_list;
245 Widget *bar_list;
246 int items;
247 {
248 	int l, i, max, has_hotkey;
249 	String resource_label;
250 
251 	DEBUG("menu_tool.c", "format_menu");
252 	/*
253 	 *	find the longest in the menu list
254 	 */
255 	max = 0;
256 	has_hotkey = False;
257 
258 
259 	for(i = 0; i < items; i++) {
260 		XtVaGetValues(bar_list[i],
261 			XtNlabel, &resource_label,
262 			NULL);
263 		if((l = strlen(resource_label)) > max)
264 			max = l;
265 		if(strcmp(item_list[i].hotkey, NO_HOT))
266 			has_hotkey = True;
267 	}
268 
269 	for(i = 0; i < items; i++)  {
270 		XtVaGetValues(bar_list[i],
271 			XtNlabel, &resource_label,
272 			NULL);
273 		XtVaSetValues(bar_list[i],
274 			XtNlabel, format_item(	resource_label,
275 						item_list[i].hotkey,
276 						max, has_hotkey),
277 			NULL
278 		);
279 	}
280 }
281 
282 
283 
popup_callback(w,client_data,call_data)284 void popup_callback(w, client_data, call_data)
285 Widget w;
286 XtPointer client_data;
287 XtPointer call_data;
288 {
289 	Position x,y;
290 	Dimension height;
291 	MENU_BLOCK *mb;
292 
293 	mb = (MENU_BLOCK*)client_data;
294 
295 	DEBUG("menu_tool.c", "popup_callback")
296 
297 	XtTranslateCoords(mb->menu_button, (Position)0, (Position)0, &x,&y);
298 	XtVaGetValues(mb->menu_button, XtNheight, &height, NULL);
299 	XtVaSetValues(mb->menu_shell, XtNx, x-1, XtNy, y+height, NULL);
300 }
301 
302 
303 
trojkamenu_select_callback(w,client_data,call_data)304 void trojkamenu_select_callback(w, client_data, call_data)
305 Widget w;
306 XtPointer client_data;
307 XtPointer call_data;
308 {
309 	int item;
310 
311 	DEBUG("menu_tool.c", "trojkamenu_select_callback")
312 
313 	XtPopdown(trojka_menu->menu_shell);
314 	item = (int)client_data;
315 	handle_trojkamenu(item);
316 }
317 
318 
speedmenu_select_callback(w,client_data,call_data)319 void speedmenu_select_callback(w, client_data, call_data)
320 Widget w;
321 XtPointer client_data;
322 XtPointer call_data;
323 {
324 	int item;
325 
326 	DEBUG("menu_tool.c", "speedmenu_select_callback")
327 
328 	item = (int)client_data;
329 	XtPopdown(speedmenu_shell);
330 	handle_speedmenu(item);
331 }
332 
333 
enable(menu,item,enabled)334 void enable(menu, item, enabled)
335 int menu;
336 int item;
337 flag enabled;
338 {
339 /*
340  * 	enables or disables a menu-item
341  */
342 	DEBUG("menu_tool.c", "enable")
343 
344 	switch(menu) {
345 		case trojka_M:
346 			XtSetSensitive(trojkamenu_itembox[item], enabled);
347 			break;
348 		case speed_M:
349 			XtSetSensitive(speedmenu_itembox[item], enabled);
350 			break;
351 	}
352 }
353 
354 
check_wizard_item(checked)355 void check_wizard_item(checked)
356 flag checked;
357 {
358 /*
359  *	(un)checks the wizard item in the trojka menu
360  */
361 	DEBUG("menu_tool.c", "check_wizard_item")
362 
363 	check_item(trojkamenu_itembox[trojka_Mwizardmode], checked);
364 }
365 
366 
check_slick_item(checked)367 void check_slick_item(checked)
368 flag checked;
369 {
370 /*
371  *	(un)checks the slick item in the trojka menu
372  */
373 	DEBUG("menu_tool.c", "check_slick_item")
374 
375 	check_item(trojkamenu_itembox[trojka_Mslick], checked);
376 }
377 
check_speed_item(speed,on)378 void check_speed_item(speed, on)
379 int speed;
380 flag on;
381 /*
382  *	(un)checks the menu item of speed
383  */
384 {
385 	DEBUG("menu_tool.c", "check_speed_item")
386 
387 	check_item(speedmenu_itembox[speed], on);
388 }
389 
390 
check_item(item,checked)391 void check_item(item, checked)
392 Widget item;
393 flag checked;
394 {
395 	String label;
396 	char new_label[255];
397 
398 	DEBUG("menu_tool.c", "check_item")
399 
400 	XtVaGetValues(item, XtNlabel, &label, NULL);
401 	strcpy(new_label, label);
402 	new_label[0] = checked ? CHECKMARK : ' ';
403 	XtVaSetValues(item, XtNlabel, new_label, NULL);
404 }
405 
406 
format_item(item,hotkey,swidth,has_hotkey)407 char *format_item(item, hotkey, swidth, has_hotkey)
408 char *item;
409 char *hotkey;
410 int swidth;
411 flag has_hotkey;
412 {
413 	char format[255];
414 	static char string[255];
415 	int i;
416 
417 	DEBUG("menu_tool.c", "format_item");
418 
419 	/*
420 	 *	handle separator bar
421 	 */
422 
423 	if(item[0] == SEPARATOR) {
424 
425 		swidth += (ITEM_WHITE+ (HOTKEY_WHITE * 2)+(HOTKEY_LEN));
426 		for(i = 0; i < swidth; i++)
427 			string[i] = SEPARATOR;
428 
429 		return string;
430 	}
431 
432 
433 	/*
434 	 *	build formatting string and use it to fill in the itemstring
435 	 */
436 	if(has_hotkey) {
437 
438 
439 		sprintf(format,"%%%ds%%-%ds%%%ds%%%ds%%%ds",
440 			ITEM_WHITE, swidth, HOTKEY_WHITE, HOTKEY_LEN,
441 			HOTKEY_WHITE);
442 		if(strcmp(hotkey, NO_HOT))
443 			sprintf(string, format, " ", item, " ",
444 				hotkey, " ");
445 		else
446 			sprintf(string, format, " ", item, " ",
447 				" ", " ");
448 	} else {
449 
450 		sprintf(format,"%%%ds%%-%ds%%%ds",
451 			ITEM_WHITE, swidth, ITEM_WHITE);
452 		sprintf(string, format, " ", item, " ");
453 	}
454 
455 	return string;
456 }
457 
458