1 #include <stdio.h>
2 #include <stdlib.h>
3 
4 #include "x11.h"
5 #include "x11-athena.h"
6 
7 #include <X11/Xaw/XawInit.h>
8 #include <X11/Xaw/Label.h>
9 #include <X11/Xaw/Box.h>
10 #include <X11/Xaw/MenuButton.h>
11 #include <X11/Xaw/SimpleMenu.h>
12 #include <X11/Xaw/SmeBSB.h>
13 #include <X11/Xaw/SmeLine.h>
14 #include <X11/Xaw/AsciiText.h>
15 
16 #include "util.h"
17 
18 #include "Game.h"
19 #include "UI.h"
20 
21 static Widget base, menubar, field;
22 static Widget dialogs[DIALOG_MAX + 1];
23 static Widget pausebutton;
24 
25 static void
x11_athena_popup_dialog(int index)26 x11_athena_popup_dialog(int index) {
27 	x11_popup(dialogs[index]);
28 }
29 
30 static void
popup(Widget w,XtPointer client_data,XtPointer call_data)31 popup(Widget w, XtPointer client_data, XtPointer call_data) {
32 	UNUSED(w);
33 	UNUSED(call_data);
34 	x11_athena_popup_dialog((int)client_data);
35 }
36 
37 static Widget
new_menu_item(Widget pshell,int dialog)38 new_menu_item(Widget pshell, int dialog) {
39 	Widget menu_item = XtCreateManagedWidget(UI_menu_string(dialog),
40 						 smeBSBObjectClass,
41 						 pshell, NULL, 0);
42 	XtAddCallback(menu_item, XtNcallback, popup, (void *) dialog);
43 	return menu_item;
44 }
45 
46 static Widget
CreateMenuBar(const char * name,Widget parent)47 CreateMenuBar(const char *name, Widget parent) {
48 	Widget menubar, pshell;
49 	Widget game_menu, info_menu;
50 
51 	menubar = XtVaCreateManagedWidget(name, boxWidgetClass, parent,
52 					  XtNborderWidth, 0,
53 					  XtNorientation, XtEhorizontal, NULL);
54 
55 	game_menu = XtCreateManagedWidget("Game", menuButtonWidgetClass,
56 					  menubar, NULL, 0);
57 	pshell = XtCreatePopupShell("menu", simpleMenuWidgetClass,
58 				    game_menu, NULL, 0);
59 
60 	new_menu_item(pshell, DIALOG_NEWGAME);
61 	pausebutton = new_menu_item(pshell, DIALOG_PAUSEGAME);
62 	new_menu_item(pshell, DIALOG_WARPLEVEL);
63 	new_menu_item(pshell, DIALOG_HIGHSCORE);
64 	new_menu_item(pshell, DIALOG_QUITGAME);
65 
66 	info_menu = XtCreateManagedWidget("Info", menuButtonWidgetClass,
67 					  menubar, NULL, 0);
68 	pshell = XtCreatePopupShell("menu", simpleMenuWidgetClass,
69 				    info_menu, NULL, 0);
70 
71 	new_menu_item(pshell, DIALOG_STORY);
72 	new_menu_item(pshell, DIALOG_RULES);
73 	new_menu_item(pshell, DIALOG_ABOUT);
74 
75 	return menubar;
76 }
77 
78 static void
close_window(Widget w,XtPointer client_data,XtPointer call_data)79 close_window (Widget w, XtPointer client_data, XtPointer call_data) {
80 	UNUSED(client_data);
81 	UNUSED(call_data);
82 	XtPopdown(XtParent(XtParent(w)));
83 }
84 
85 static Widget
CreateRowCol(const char * name,Widget parent)86 CreateRowCol(const char *name, Widget parent) {
87 	return XtCreateManagedWidget(name, boxWidgetClass, parent, NULL, 0);
88 }
89 
90 static void
CreatePixmapBox(int index,Widget parent,Pixmap logo,Pixmap pixmap)91 CreatePixmapBox(int index, Widget parent, Pixmap logo, Pixmap pixmap) {
92 	Widget base, pshell, button;
93 	const char *text = UI_dialog_string(index);
94 
95 	pshell = XtCreatePopupShell(UI_menu_string(index),
96 				    transientShellWidgetClass, parent, NULL, 0);
97 
98 	base = CreateRowCol("", pshell);
99 
100 	XtVaCreateManagedWidget("", labelWidgetClass, base,
101 		XtNbitmap, logo, XtNborderWidth, 0, NULL);
102 
103 	if (pixmap)
104 		XtVaCreateManagedWidget("", labelWidgetClass, base,
105 					XtNbitmap, pixmap, XtNborderWidth,
106 					0, NULL);
107 	if (text != NULL)
108 		XtVaCreateManagedWidget("", labelWidgetClass, base,
109 			XtNlabel, text, XtNborderWidth, 0, NULL);
110 
111 	button = XtVaCreateManagedWidget("OK", commandWidgetClass, base, NULL);
112 	XtAddCallback(button, XtNcallback, close_window, NULL);
113 	dialogs[index] = base;
114 }
115 
116 static void
CreateEnterText(int index,Widget parent,XtCallbackProc callback)117 CreateEnterText(int index, Widget parent, XtCallbackProc callback) {
118 	Widget base, pshell, button, textfield;
119 	pshell = XtCreatePopupShell(UI_menu_string(index),
120 				    transientShellWidgetClass, parent, NULL, 0);
121 	base = CreateRowCol("", pshell);
122 	XtVaCreateManagedWidget("", labelWidgetClass, base,
123 		XtNlabel, UI_dialog_string(index), XtNborderWidth, 0, NULL);
124 
125 	textfield = XtVaCreateManagedWidget("", asciiTextWidgetClass, base,
126 		XtNeditType, XawtextEdit, XtNstring, "", XtNwidth, 200, NULL);
127 
128 	button = XtVaCreateManagedWidget("OK", commandWidgetClass, base, NULL);
129 	XtAddCallback(button, XtNcallback, callback, textfield);
130 	XtAddCallback(button, XtNcallback, close_window, NULL);
131 	button = XtVaCreateManagedWidget("Cancel", commandWidgetClass, base,
132 		NULL);
133 	XtAddCallback(button, XtNcallback, close_window, NULL);
134 	dialogs[index] = base;
135 }
136 
137 static void
CreateDialog(int index,Widget parent,int hascancel,Pixmap icon,const char * buttonlabel,XtCallbackProc callback)138 CreateDialog(int index, Widget parent, int hascancel, Pixmap icon,
139 	     const char *buttonlabel, XtCallbackProc callback)
140 {
141 	Widget base, pshell, button;
142 	const char *text = UI_dialog_string(index);
143 	char ttext[16];
144 
145 	pshell = XtCreatePopupShell(UI_menu_string(index),
146 				    transientShellWidgetClass, parent, NULL, 0);
147 	base = CreateRowCol("base", pshell);
148 	if (icon)
149 		XtVaCreateManagedWidget("", labelWidgetClass, base,
150 					XtNbitmap, icon,
151 					XtNborderWidth, 0, NULL);
152 	if (text != NULL && strlen(text) < sizeof(ttext)) {
153 		sprintf(ttext, "%-*s", (int)sizeof(ttext) - 1, text);
154 		text = ttext;
155 	}
156 	XtVaCreateManagedWidget("label", labelWidgetClass, base,
157 		XtNlabel, text, XtNborderWidth, 0, NULL);
158 
159 	if (!buttonlabel)
160 		buttonlabel="OK";
161 	button = XtVaCreateManagedWidget(buttonlabel, commandWidgetClass,
162 					 base, NULL);
163 	if (callback)
164 		XtAddCallback(button, XtNcallback, callback, NULL);
165 	XtAddCallback(button, XtNcallback, close_window, NULL);
166 
167 	if (hascancel) {
168 		button = XtVaCreateManagedWidget("Cancel", commandWidgetClass,
169 						 base, NULL);
170 		XtAddCallback(button, XtNcallback, close_window, NULL);
171 	}
172 	dialogs[index] = base;
173 }
174 
175 static Widget
CreateDrawingArea(const char * name,Widget parent,int width,int height)176 CreateDrawingArea(const char *name, Widget parent, int width, int height) {
177 	return XtVaCreateManagedWidget(name, coreWidgetClass, parent, XtNwidth,
178 		width, XtNheight, height, NULL);
179 }
180 
181 static void
x11_athena_update_dialog(int index,const char * str)182 x11_athena_update_dialog(int index, const char *str) {
183 	WidgetList t;
184 	XtVaGetValues(dialogs[index], XtNchildren, &t, NULL);
185 	XtVaSetValues(t[0], XtNlabel, str, NULL);
186 }
187 
188 static void
x11_athena_make_main_window(int size)189 x11_athena_make_main_window(int size) {
190 	x11_setup_resources();
191 	base = XtVaCreateManagedWidget("base", boxWidgetClass, x11_toplevel(),
192 				       XtNhSpace, 0, XtNvSpace, 0, NULL);
193 	menubar = CreateMenuBar("menubar", base);
194 	field = CreateDrawingArea("field", base, size, size);
195 	x11_setup();
196 	x11_set_drawingarea(field, size);
197 	x11_add_event_handlers(field);
198 }
199 
200 static void
new_game(Widget w,XtPointer client_data,XtPointer call_data)201 new_game(Widget w, XtPointer client_data, XtPointer call_data) {
202 	UNUSED(w);
203 	UNUSED(client_data);
204 	UNUSED(call_data);
205 	Game_start(1);
206 }
207 
208 static void
quit_game(Widget w,XtPointer client_data,XtPointer call_data)209 quit_game(Widget w, XtPointer client_data, XtPointer call_data) {
210 	UNUSED(w);
211 	UNUSED(client_data);
212 	UNUSED(call_data);
213 	Game_quit();
214 }
215 
216 static void
warp_apply(Widget w,XtPointer client_data,XtPointer call_data)217 warp_apply(Widget w, XtPointer client_data, XtPointer call_data) {
218 	char *str;
219 	char *endp;
220 	int newlevel;
221 	Widget text = (Widget) client_data;
222 
223 	UNUSED(w);
224 	UNUSED(call_data);
225 
226 	XtVaGetValues(text, XtNstring, &str, NULL);
227 	newlevel = strtol(str, &endp, 10);
228 	if (*endp != '\0')
229 		return;
230 	Game_warp_to_level(newlevel);
231 }
232 
233 static void
enter_name(Widget w,XtPointer client_data,XtPointer call_data)234 enter_name(Widget w, XtPointer client_data, XtPointer call_data) {
235 	char *str;
236 	Widget text = (Widget) client_data;
237 
238 	UNUSED(w);
239 	UNUSED(call_data);
240 
241 	XtVaGetValues(text, XtNstring, &str, NULL);
242 	Game_add_high_score(str);
243 }
244 
245 static void
x11_athena_create_dialogs(Picture * logo,Picture * icon,Picture * about)246 x11_athena_create_dialogs(Picture *logo, Picture *icon, Picture *about) {
247 	CreateDialog(DIALOG_NEWGAME, base, 1, (Pixmap)NULL, NULL, new_game);
248 	CreateDialog(DIALOG_PAUSEGAME, base, 0, icon->pix, "Continue", NULL);
249 	CreateEnterText(DIALOG_WARPLEVEL, base, warp_apply);
250 	CreateDialog(DIALOG_HIGHSCORE, base, 0, (Pixmap)NULL, NULL, NULL);
251 	CreateDialog(DIALOG_QUITGAME, base, 1, (Pixmap)NULL, NULL, quit_game);
252 
253 	CreatePixmapBox(DIALOG_STORY, base, logo->pix, (Pixmap)NULL);
254 	CreatePixmapBox(DIALOG_RULES, base, logo->pix, (Pixmap)NULL);
255 	CreatePixmapBox(DIALOG_ABOUT, base, logo->pix, about->pix);
256 
257 	CreateDialog(DIALOG_SCORE, base, 0, (Pixmap)NULL, NULL, NULL);
258 	CreateDialog(DIALOG_ENDGAME, base, 0, (Pixmap)NULL, "Nuts!", NULL);
259 	CreateEnterText(DIALOG_ENTERNAME, base, enter_name);
260 }
261 
262 static void
x11_athena_set_pausebutton(int active)263 x11_athena_set_pausebutton(int active) {
264 	if (pausebutton != NULL)
265 		XtSetSensitive(pausebutton, active);
266 }
267 
268 static struct UI_methods x11_athena_methods = {
269 	x11_set_cursor,
270 	x11_load_cursor,
271 	x11_load_picture,
272 	x11_set_icon,
273 	x11_picture_width,
274 	x11_picture_height,
275 	x11_graphics_init,
276 	x11_clear_window,
277 	x11_refresh_window,
278 	x11_draw_image,
279 	x11_draw_line,
280 	x11_draw_string,
281 	x11_start_timer,
282 	x11_stop_timer,
283 	x11_timer_active,
284 	x11_athena_popup_dialog,
285 	x11_main_loop,
286 	x11_initialize,
287 	x11_athena_make_main_window,
288 	x11_athena_create_dialogs,
289 	x11_athena_set_pausebutton,
290 	x11_athena_update_dialog,
291 };
292 
293 void
x11_athena_setmethods(UI_methods ** methodsp)294 x11_athena_setmethods(UI_methods **methodsp) {
295 	*methodsp = &x11_athena_methods;
296 }
297