1 #include <stdio.h>
2 #include <stdlib.h>
3
4 #include "x11.h"
5 #include "x11-motif.h"
6
7 #include <Xm/Xm.h>
8 #include <Xm/Label.h>
9 #include <Xm/RowColumn.h>
10 #include <Xm/DrawingA.h>
11 #include <Xm/PushB.h>
12 #include <Xm/CascadeB.h>
13 #include <Xm/MessageB.h>
14 #include <Xm/SelectioB.h>
15 #include <Xm/Text.h>
16
17 #include "util.h"
18
19 #include "Game.h"
20 #include "UI.h"
21
22 static Widget base, menubar, field;
23 static Widget dialogs[DIALOG_MAX + 1];
24 static Widget pausebutton;
25
26 static void
x11_motif_popup_dialog(int index)27 x11_motif_popup_dialog(int index) {
28 x11_popup(dialogs[index]);
29 }
30
31 static void
popup(Widget w,XtPointer client_data,XtPointer call_data)32 popup(Widget w, XtPointer client_data, XtPointer call_data) {
33 UNUSED(w);
34 UNUSED(call_data);
35 x11_motif_popup_dialog((int)client_data);
36 }
37
38 static Widget
new_menu_item(Widget pulldown,int dialog)39 new_menu_item(Widget pulldown, int dialog) {
40 Widget menu_item = XtCreateManagedWidget(UI_menu_string(dialog),
41 xmPushButtonWidgetClass,
42 pulldown, NULL, 0);
43 XtAddCallback(menu_item, XmNactivateCallback, popup, (void *) dialog);
44 return menu_item;
45 }
46
47 static Widget
CreateMenuBar(const char * name,Widget parent)48 CreateMenuBar(const char *name, Widget parent) {
49 Widget menubar, pulldown;
50 Widget game_menu, info_menu;
51
52 menubar = XmCreateMenuBar(parent, (char *)name, NULL, 0);
53 XtManageChild(menubar);
54
55 pulldown = XmCreatePulldownMenu(menubar, "menu", NULL, 0);
56 game_menu = XtVaCreateManagedWidget("Game",
57 xmCascadeButtonWidgetClass,
58 menubar, XmNsubMenuId,
59 pulldown, NULL);
60
61 new_menu_item(pulldown, DIALOG_NEWGAME);
62 pausebutton = new_menu_item(pulldown, DIALOG_PAUSEGAME);
63 new_menu_item(pulldown, DIALOG_WARPLEVEL);
64 new_menu_item(pulldown, DIALOG_HIGHSCORE);
65 new_menu_item(pulldown, DIALOG_QUITGAME);
66
67 pulldown = XmCreatePulldownMenu(menubar, "menu", NULL, 0);
68 info_menu = XtVaCreateManagedWidget("Info",
69 xmCascadeButtonWidgetClass,
70 menubar, XmNsubMenuId,
71 pulldown, NULL);
72
73 new_menu_item(pulldown, DIALOG_STORY);
74 new_menu_item(pulldown, DIALOG_RULES);
75 new_menu_item(pulldown, DIALOG_ABOUT);
76
77 return menubar;
78 }
79
80 static Widget
CreateRowCol(const char * name,Widget parent)81 CreateRowCol(const char *name, Widget parent) {
82 return XtVaCreateManagedWidget(name, xmRowColumnWidgetClass, parent,
83 XmNorientation, XmVERTICAL, NULL);
84 }
85
86 static void
CreatePixmapBox(int index,Widget parent,Pixmap logo,Pixmap pixmap)87 CreatePixmapBox(int index, Widget parent, Pixmap logo, Pixmap pixmap) {
88 Arg wargs[2];
89 XmString mstr;
90 Widget dialog, base;
91 const char *text = UI_dialog_string(index);
92
93 mstr = XmStringCreateLtoR("", XmSTRING_DEFAULT_CHARSET);
94 XtSetArg(wargs[0], XmNdialogStyle, XmDIALOG_APPLICATION_MODAL);
95 XtSetArg(wargs[1], XmNmessageString, mstr);
96 dialog = XmCreateMessageDialog(parent, (char *)UI_menu_string(index),
97 wargs, 2);
98
99 base = CreateRowCol("", dialog);
100
101 XtVaCreateManagedWidget("", xmLabelWidgetClass, base, XmNlabelType,
102 XmPIXMAP, XmNlabelPixmap, logo, NULL);
103
104 if (pixmap)
105 XtVaCreateManagedWidget("", xmLabelWidgetClass, base,
106 XmNlabelType, XmPIXMAP,
107 XmNlabelPixmap, pixmap, NULL);
108
109 if (text) {
110 mstr = XmStringCreateLtoR((char *)text,
111 XmSTRING_DEFAULT_CHARSET);
112 XtVaCreateManagedWidget(text, xmLabelWidgetClass, base,
113 XmNlabelString, mstr, NULL);
114 XmStringFree(mstr);
115 }
116
117 XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_CANCEL_BUTTON));
118 XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_HELP_BUTTON));
119 dialogs[index] = dialog;
120 }
121
122 static void
CreateEnterText(int index,Widget parent,XtCallbackProc callback)123 CreateEnterText(int index, Widget parent, XtCallbackProc callback) {
124 Widget dialog;
125 Arg wargs[2];
126 XmString mstr = XmStringCreateLtoR((char *) UI_dialog_string(index),
127 XmSTRING_DEFAULT_CHARSET);
128 XtSetArg(wargs[0], XmNdialogStyle, XmDIALOG_APPLICATION_MODAL);
129 XtSetArg(wargs[1], XmNselectionLabelString, mstr);
130 dialog = XmCreatePromptDialog(parent, (char *) UI_menu_string(index),
131 wargs, 2);
132 XtUnmanageChild(XmSelectionBoxGetChild(dialog, XmDIALOG_HELP_BUTTON));
133 XtUnmanageChild(XmSelectionBoxGetChild(dialog, XmDIALOG_APPLY_BUTTON));
134 XtAddCallback(dialog, XmNokCallback, callback,
135 XmSelectionBoxGetChild(dialog, XmDIALOG_TEXT));
136 dialogs[index] = dialog;
137 }
138
139 static void
CreateDialog(int index,Widget parent,int hascancel,Pixmap icon,const char * buttonlabel,XtCallbackProc callback)140 CreateDialog(int index, Widget parent, int hascancel, Pixmap icon,
141 const char *buttonlabel, XtCallbackProc callback)
142 {
143 Widget dialog;
144 Arg wargs[2];
145 XmString mstr = XmStringCreateLtoR((char *) UI_dialog_string(index),
146 XmSTRING_DEFAULT_CHARSET);
147 XtSetArg(wargs[0], XmNdialogStyle, XmDIALOG_APPLICATION_MODAL);
148 XtSetArg(wargs[1], XmNmessageString, mstr);
149 dialog = XmCreateMessageDialog(parent, (char *) UI_menu_string(index),
150 wargs, 2);
151 if (icon != (Pixmap) NULL)
152 XtVaSetValues(dialog, XmNsymbolPixmap, icon, NULL);
153 XmStringFree(mstr);
154 if (!hascancel)
155 XtUnmanageChild(XmMessageBoxGetChild(dialog,
156 XmDIALOG_CANCEL_BUTTON));
157 XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_HELP_BUTTON));
158 if (buttonlabel != NULL) {
159 mstr = XmStringCreateLtoR((char *) buttonlabel,
160 XmSTRING_DEFAULT_CHARSET);
161 XtVaSetValues(XmMessageBoxGetChild(dialog, XmDIALOG_OK_BUTTON),
162 XmNlabelString, mstr, NULL);
163 XmStringFree(mstr);
164 }
165 if (callback != NULL)
166 XtAddCallback(dialog, XmNokCallback, callback, NULL);
167 dialogs[index] = dialog;
168 }
169
170 static Widget
CreateDrawingArea(const char * name,Widget parent,int width,int height)171 CreateDrawingArea(const char *name, Widget parent, int width, int height) {
172 return XtVaCreateManagedWidget(name, xmDrawingAreaWidgetClass, parent,
173 XtNwidth, width, XtNheight, height,
174 XmNresizePolicy, FALSE, NULL);
175 }
176
177 static void
x11_motif_update_dialog(int index,const char * str)178 x11_motif_update_dialog(int index, const char *str) {
179 XmString mstr = XmStringCreateLtoR((char *) str,
180 XmSTRING_DEFAULT_CHARSET);
181 XtVaSetValues(
182 XmMessageBoxGetChild(dialogs[index], XmDIALOG_MESSAGE_LABEL),
183 XmNlabelString, mstr, NULL);
184 XmStringFree(mstr);
185 }
186
187 static void
x11_motif_make_main_window(int size)188 x11_motif_make_main_window(int size) {
189 x11_setup_resources();
190 base = CreateRowCol("base", x11_toplevel());
191 menubar = CreateMenuBar("menubar", base);
192 field = CreateDrawingArea("field", base, size, size);
193 x11_setup();
194 x11_set_drawingarea(field, size);
195 x11_add_event_handlers(field);
196 }
197
198 static void
new_game(Widget w,XtPointer client_data,XtPointer call_data)199 new_game(Widget w, XtPointer client_data, XtPointer call_data) {
200 UNUSED(w);
201 UNUSED(client_data);
202 UNUSED(call_data);
203 Game_start(1);
204 }
205
206 static void
quit_game(Widget w,XtPointer client_data,XtPointer call_data)207 quit_game(Widget w, XtPointer client_data, XtPointer call_data) {
208 UNUSED(w);
209 UNUSED(client_data);
210 UNUSED(call_data);
211 Game_quit();
212 }
213
214 static void
warp_apply(Widget w,XtPointer client_data,XtPointer call_data)215 warp_apply(Widget w, XtPointer client_data, XtPointer call_data) {
216 char *str;
217 char *endp;
218 int newlevel;
219 Widget text = (Widget) client_data;
220
221 UNUSED(w);
222 UNUSED(call_data);
223
224 str = XmTextGetString(text);
225 newlevel = strtol(str, &endp, 10);
226 if (*endp != '\0')
227 return;
228 XtFree(str);
229 Game_warp_to_level(newlevel);
230 }
231
232 static void
enter_name(Widget w,XtPointer client_data,XtPointer call_data)233 enter_name(Widget w, XtPointer client_data, XtPointer call_data) {
234 char *str;
235 Widget text = (Widget) client_data;
236
237 UNUSED(w);
238 UNUSED(call_data);
239
240 str = XmTextGetString(text);
241 Game_add_high_score(str);
242 XtFree(str);
243 }
244
245 static void
x11_motif_create_dialogs(Picture * logo,Picture * icon,Picture * about)246 x11_motif_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_motif_set_pausebutton(int active)263 x11_motif_set_pausebutton(int active) {
264 if (pausebutton != NULL)
265 XtSetSensitive(pausebutton, active);
266 }
267
268 static struct UI_methods x11_motif_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_motif_popup_dialog,
285 x11_main_loop,
286 x11_initialize,
287 x11_motif_make_main_window,
288 x11_motif_create_dialogs,
289 x11_motif_set_pausebutton,
290 x11_motif_update_dialog,
291 };
292
293 void
x11_motif_setmethods(UI_methods ** methodsp)294 x11_motif_setmethods(UI_methods **methodsp) {
295 *methodsp = &x11_motif_methods;
296 }
297