1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <sys/types.h>
5 #include <sys/stat.h>
6 
7 #include <gtk/gtk.h>
8 
9 #include "util.h"
10 
11 #include "gtk.h"
12 
13 #include "Game.h"
14 #include "UI.h"
15 
16 struct MCursor {
17 	GdkCursor *cursor;
18 };
19 
20 struct Picture {
21 	gint width, height;
22 	GdkPixmap *pix;
23 	GdkBitmap *mask;
24 	GdkGC *gc;
25 };
26 
27 static const char *pictdir;
28 
29 static GtkWidget *toplevel, *base, *menubar, *field;
30 static GtkWidget *dialogs[DIALOG_MAX + 1];
31 static GtkWidget *pausebutton;
32 static guint timer;
33 static GdkGC *stdgc;
34 static GdkPixmap *offscreen;
35 static GdkFont *font;
36 static GdkColor white, black;
37 static int screensize;
38 
39 /*
40  * Callback functions
41  */
42 
43 static void
gtk_ui_popup_dialog(int index)44 gtk_ui_popup_dialog(int index) {
45 	GtkWidget *popup;
46 	int tx, ty, tw, th;
47 	int px, py, pw, ph;
48 
49 	popup = dialogs[index];
50 
51 	gdk_window_get_origin(toplevel->window, &tx, &ty);
52 	gdk_window_get_size(toplevel->window, &tw, &th);
53 	gdk_window_get_size(popup->window, &pw, &ph);
54 	px = tx + (tw - pw) / 2;
55 	py = ty + (th - ph) / 2;
56 	gtk_window_set_position(GTK_WINDOW(popup), GTK_WIN_POS_NONE);
57 	gtk_widget_set_uposition(popup, px, py);
58 	gtk_widget_show_all(popup);
59 	gtk_main();
60 }
61 
62 static void
popdown(void)63 popdown(void) {
64 	gtk_main_quit();
65 }
66 
67 static void
new_game(void)68 new_game(void) {
69 	Game_start(1);
70 }
71 
72 static void
quit_game(void)73 quit_game(void) {
74 	Game_quit();
75 }
76 
77 static void
warp_apply(GtkWidget * text)78 warp_apply(GtkWidget *text) {
79 	char *str;
80 	char *endp;
81 	int newlevel;
82 
83 	str = gtk_entry_get_text(GTK_ENTRY(text));
84 	newlevel = strtol(str, &endp, 10);
85 	if (*endp != '\0')
86 		return;
87 	Game_warp_to_level(newlevel);
88 }
89 
90 static void
enter_name(GtkWidget * text)91 enter_name(GtkWidget *text) {
92 	char *str;
93 
94 	str = gtk_entry_get_text(GTK_ENTRY(text));
95 	Game_add_high_score(str);
96 }
97 
98 /*
99  * Event handlers
100  */
101 
102 static gboolean
leave_window(GtkWidget * widget,GdkEvent * event,gpointer user_data)103 leave_window(GtkWidget *widget, GdkEvent *event, gpointer user_data) {
104 	UNUSED(widget);
105 	UNUSED(event);
106 	UNUSED(user_data);
107 
108 	UI_pause_game();
109 	return FALSE;
110 }
111 
112 static gboolean
enter_window(GtkWidget * widget,GdkEvent * event,gpointer user_data)113 enter_window(GtkWidget *widget, GdkEvent *event, gpointer user_data) {
114 	UNUSED(widget);
115 	UNUSED(event);
116 	UNUSED(user_data);
117 
118 	UI_resume_game();
119 	return FALSE;
120 }
121 
122 static gboolean
redraw_window(GtkWidget * widget,GdkEvent * event,gpointer user_data)123 redraw_window(GtkWidget *widget, GdkEvent *event, gpointer user_data) {
124 	UNUSED(widget);
125 	UNUSED(event);
126 	UNUSED(user_data);
127 
128 	UI_refresh();
129 	return FALSE;
130 }
131 
132 static gboolean
button_press(GtkWidget * widget,GdkEvent * event,gpointer user_data)133 button_press(GtkWidget *widget, GdkEvent *event, gpointer user_data) {
134 	GdkEventButton *buttonevent = (GdkEventButton *) event;
135 
136 	UNUSED(widget);
137 	UNUSED(user_data);
138 
139 	Game_button_press((int)buttonevent->x, (int)buttonevent->y);
140 	return FALSE;
141 }
142 
143 static gboolean
button_release(GtkWidget * widget,GdkEvent * event,gpointer user_data)144 button_release(GtkWidget *widget, GdkEvent *event, gpointer user_data) {
145 	GdkEventButton *buttonevent = (GdkEventButton *) event;
146 
147 	UNUSED(widget);
148 	UNUSED(user_data);
149 
150 	Game_button_release((int)buttonevent->x, (int)buttonevent->y);
151 	return FALSE;
152 }
153 
154 static int
timer_tick(gpointer arg)155 timer_tick(gpointer arg) {
156 	UNUSED(arg);
157 
158 	UI_restart_timer();
159 	Game_update();
160 	return TRUE;
161 }
162 
163 /*
164  * Cursor handling
165  */
166 
167 #include "bitmaps/apple.xbm"
168 #include "bitmaps/bsd.xbm"
169 #include "bitmaps/hurd.xbm"
170 #include "bitmaps/linux.xbm"
171 #include "bitmaps/next.xbm"
172 #include "bitmaps/os2.xbm"
173 #include "bitmaps/palm.xbm"
174 #include "bitmaps/redhat.xbm"
175 #include "bitmaps/sgi.xbm"
176 #include "bitmaps/sun.xbm"
177 #include "bitmaps/bucket.xbm"
178 #include "bitmaps/hand_down.xbm"
179 #include "bitmaps/hand_down_mask.xbm"
180 #include "bitmaps/hand_up.xbm"
181 #include "bitmaps/hand_up_mask.xbm"
182 
183 typedef struct cursormap {
184 	const char *name;
185 	int width, height;
186 	const char *data, *maskdata;
187 } cursormap;
188 
189 #define CURSOR_ADD(x) \
190 	{#x, x ## _width, x ## _height, x ## _bits, NULL}
191 
192 #define CURSOR_ADD_MASKED(x) \
193 	{#x, x ## _width, x ## _height, x ## _bits, x ## _mask_bits}
194 
195 static cursormap cursors[] = {
196 	CURSOR_ADD(apple), CURSOR_ADD(bsd), CURSOR_ADD(hurd),
197 	CURSOR_ADD(linux), CURSOR_ADD(next), CURSOR_ADD(os2), CURSOR_ADD(palm),
198 	CURSOR_ADD(redhat), CURSOR_ADD(sgi), CURSOR_ADD(sun),
199 	CURSOR_ADD(bucket),
200 	CURSOR_ADD_MASKED(hand_up), CURSOR_ADD_MASKED(hand_down),
201 	{NULL, 0, 0, NULL, NULL},
202 };
203 
204 static void
gtk_ui_set_cursor(MCursor * cursor)205 gtk_ui_set_cursor(MCursor *cursor) {
206 	gdk_window_set_cursor(field->window, cursor->cursor);
207 }
208 
209 static void
gtk_ui_load_cursor(const char * name,int masked,MCursor ** cursorp)210 gtk_ui_load_cursor(const char *name, int masked, MCursor **cursorp) {
211 	MCursor *cursor;
212 	GdkBitmap *bitmap, *mask;
213 	cursormap *c;
214 
215 	cursor = xalloc(sizeof *cursor);
216 
217 	for (c = cursors; c->name != NULL; c++)
218 		if (strcmp(name, c->name) == 0)
219 			break;
220 	if (c->name == NULL)
221 		fatal("couldn't load cursor: %s", name);
222 	bitmap = gdk_bitmap_create_from_data(field->window, c->data,
223 					     c->width, c->height);
224 
225 	if (masked == CURSOR_SEP_MASK)
226 		mask = gdk_bitmap_create_from_data(field->window, c->maskdata,
227 						   c->width, c->height);
228 	else
229 		mask = bitmap;
230 	cursor->cursor = gdk_cursor_new_from_pixmap(bitmap, mask,
231 						    &black, &white,
232 						    c->width/2, c->height/2);
233 	*cursorp = cursor;
234 }
235 
236 /*
237  * Pixmap handling
238  */
239 
240 static void
gtk_ui_load_picture(const char * name,int trans,Picture ** pictp)241 gtk_ui_load_picture(const char *name, int trans, Picture **pictp) {
242 	Picture *pict;
243 	char file[255];
244 	GdkBitmap *mask;
245 
246 	UNUSED(trans);
247 
248 	pict = xalloc(sizeof *pict);
249 
250 	sprintf(file, "%s/pixmaps/%s.xpm", pictdir, name);
251 	pict->pix = gdk_pixmap_create_from_xpm(toplevel->window, &mask,
252 					       NULL, file);
253 	if (pict->pix == NULL)
254 		fatal("error reading %s", file);
255 	pict->mask = mask;
256 	pict->gc = gdk_gc_new(toplevel->window);
257 	gdk_gc_set_exposures(pict->gc, FALSE);
258 	gdk_gc_set_clip_mask(pict->gc, mask);
259 	gdk_window_get_size(pict->pix, &pict->width, &pict->height);
260 
261 	*pictp = pict;
262 }
263 
264 static void
gtk_ui_set_icon(Picture * icon)265 gtk_ui_set_icon(Picture *icon) {
266 	gdk_window_set_icon(toplevel->window, NULL, icon->pix, icon->mask);
267 }
268 
269 static int
gtk_ui_picture_width(Picture * pict)270 gtk_ui_picture_width(Picture *pict) {
271 	return (pict->width);
272 }
273 
274 static int
gtk_ui_picture_height(Picture * pict)275 gtk_ui_picture_height(Picture *pict) {
276 	return (pict->height);
277 }
278 
279 /*
280  * Graphics operations
281  */
282 
283 static void
gtk_ui_clear_window(void)284 gtk_ui_clear_window(void) {
285 	gdk_draw_rectangle(offscreen, field->style->white_gc, TRUE, 0, 0,
286 			   screensize, screensize);
287 }
288 
289 static void
gtk_ui_refresh_window(void)290 gtk_ui_refresh_window(void) {
291 	gdk_draw_pixmap(field->window, stdgc, offscreen, 0, 0, 0, 0,
292 			screensize, screensize);
293 }
294 
295 static void
gtk_ui_draw_image(Picture * pict,int x,int y)296 gtk_ui_draw_image(Picture *pict, int x, int y) {
297 	gdk_gc_set_clip_origin(pict->gc, x, y);
298 	gdk_draw_pixmap(offscreen, pict->gc, pict->pix, 0, 0, x, y,
299 			pict->width, pict->height);
300 }
301 
302 static void
gtk_ui_draw_line(int x1,int y1,int x2,int y2)303 gtk_ui_draw_line(int x1, int y1, int x2, int y2) {
304 	gdk_draw_line(offscreen, stdgc, x1, y1, x2, y2);
305 }
306 
307 static void
gtk_ui_draw_string(const char * str,int x,int y)308 gtk_ui_draw_string(const char *str, int x, int y) {
309 	gdk_draw_string(offscreen, font, stdgc, x, y, str);
310 }
311 
312 /*
313  * Timer operations
314  */
315 
316 static void
gtk_ui_start_timer(int ms)317 gtk_ui_start_timer(int ms) {
318 	if (timer == 0)
319 		timer = gtk_timeout_add(ms, timer_tick, NULL);
320 }
321 
322 static void
gtk_ui_stop_timer(void)323 gtk_ui_stop_timer(void) {
324 	if (timer != 0)
325 		gtk_timeout_remove(timer);
326 	timer = 0;
327 }
328 
329 static int
gtk_ui_timer_active(void)330 gtk_ui_timer_active(void) {
331 	return (!!timer);
332 }
333 
334 /*
335  * Main Loop
336  */
337 static void
gtk_ui_main_loop(void)338 gtk_ui_main_loop(void) {
339 	gtk_main();
340 }
341 
342 /*
343  * Initialization
344  */
345 static void
gtk_ui_initialize(int * argc,char ** argv)346 gtk_ui_initialize(int *argc, char **argv) {
347 	struct stat stats;
348 
349 	gtk_init(argc, &argv);
350 	toplevel = gtk_window_new(GTK_WINDOW_TOPLEVEL);
351 
352 	timer = 0;
353 	gtk_window_set_title(GTK_WINDOW(toplevel), "XBill");
354 
355 	gtk_signal_connect(GTK_OBJECT(toplevel), "delete_event",
356 			   GTK_SIGNAL_FUNC(quit_game), NULL);
357 
358 	if (stat(IMAGES, &stats) == 0)
359 		pictdir = IMAGES;
360 	else
361 		pictdir = ".";
362 }
363 
364 static GtkWidget *
new_menu_item(GtkWidget * menu,int dialog)365 new_menu_item(GtkWidget *menu, int dialog) {
366 	GtkWidget *menu_item;
367 
368 	menu_item = gtk_menu_item_new_with_label(UI_menu_string(dialog));
369 	gtk_menu_append(GTK_MENU(menu), menu_item);
370 	gtk_signal_connect_object(GTK_OBJECT(menu_item), "activate",
371 				  gtk_ui_popup_dialog, (gpointer) dialog);
372 	return (menu_item);
373 }
374 
375 static GtkWidget *
CreateMenuBar(void)376 CreateMenuBar(void) {
377 	GtkWidget *menubar;
378 	GtkWidget *game_item, *game_menu;
379 	GtkWidget *info_item, *info_menu;
380 	GtkWidget *tearoff;
381 
382 	menubar = gtk_menu_bar_new();
383 
384 	game_item = gtk_menu_item_new_with_label("Game");
385 	game_menu = gtk_menu_new();
386 
387 	tearoff = gtk_tearoff_menu_item_new();
388 	gtk_menu_append(GTK_MENU(game_menu), tearoff);
389 
390 	new_menu_item(game_menu, DIALOG_NEWGAME);
391 	pausebutton = new_menu_item(game_menu, DIALOG_PAUSEGAME);
392 	new_menu_item(game_menu, DIALOG_WARPLEVEL);
393 	new_menu_item(game_menu, DIALOG_HIGHSCORE);
394 	new_menu_item(game_menu, DIALOG_QUITGAME);
395 
396 	gtk_menu_bar_append(GTK_MENU_BAR(menubar), game_item);
397 	gtk_menu_item_set_submenu(GTK_MENU_ITEM(game_item), game_menu);
398 
399 	info_item = gtk_menu_item_new_with_label("Info");
400 	info_menu = gtk_menu_new();
401 
402 	tearoff = gtk_tearoff_menu_item_new();
403 	gtk_menu_append(GTK_MENU(info_menu), tearoff);
404 
405 	new_menu_item(info_menu, DIALOG_STORY);
406 	new_menu_item(info_menu, DIALOG_RULES);
407 	new_menu_item(info_menu, DIALOG_ABOUT);
408 
409 	gtk_menu_bar_append(GTK_MENU_BAR(menubar), info_item);
410 	gtk_menu_item_set_submenu(GTK_MENU_ITEM(info_item), info_menu);
411 
412 	return menubar;
413 }
414 
415 static GtkWidget *
CreateDrawingArea(int width,int height)416 CreateDrawingArea(int width, int height) {
417 	GtkWidget *w = gtk_drawing_area_new();
418 	gtk_drawing_area_size(GTK_DRAWING_AREA(w), width, height);
419 	return w;
420 }
421 
422 static void
gtk_ui_make_main_window(int size)423 gtk_ui_make_main_window(int size) {
424 	GdkWindowHints flags;
425 	GdkGeometry geom;
426 	gint winwidth, winheight;
427 
428 	screensize = size;
429 
430 	base = gtk_vbox_new(FALSE, 0);
431 	gtk_container_add(GTK_CONTAINER(toplevel), base);
432 
433 	menubar = CreateMenuBar();
434 	gtk_box_pack_start(GTK_BOX(base), menubar, FALSE, FALSE, 0);
435 
436 	field = CreateDrawingArea(size, size);
437 	gtk_box_pack_start(GTK_BOX(base), field, FALSE, FALSE, 0);
438 
439 	gtk_signal_connect(GTK_OBJECT(field), "button-press-event",
440 			   GTK_SIGNAL_FUNC(button_press), NULL);
441 	gtk_signal_connect(GTK_OBJECT(field), "button-release-event",
442 			   GTK_SIGNAL_FUNC(button_release), NULL);
443 	gtk_signal_connect(GTK_OBJECT(field), "enter-notify-event",
444 			   GTK_SIGNAL_FUNC(enter_window), NULL);
445 	gtk_signal_connect(GTK_OBJECT(field), "leave-notify-event",
446 			   GTK_SIGNAL_FUNC(leave_window), NULL);
447 	gtk_signal_connect(GTK_OBJECT(field), "expose-event",
448 			   GTK_SIGNAL_FUNC(redraw_window), NULL);
449 	gtk_widget_set_events(field, GDK_BUTTON_PRESS_MASK |
450 			      GDK_BUTTON_RELEASE_MASK |
451 			      GDK_ENTER_NOTIFY_MASK |
452 			      GDK_LEAVE_NOTIFY_MASK |
453 			      GDK_EXPOSURE_MASK);
454 
455 	gtk_widget_show_all(toplevel);
456 
457 	gdk_window_get_size(toplevel->window, &winwidth, &winheight);
458 	geom.min_width = geom.max_width = geom.base_width = winwidth;
459 	geom.min_height = geom.max_height = geom.base_height = winheight;
460 	geom.width_inc = geom.height_inc = 0;
461 	flags = GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE | GDK_HINT_BASE_SIZE |
462 		GDK_HINT_RESIZE_INC;
463 	gdk_window_set_geometry_hints(toplevel->window, &geom, flags);
464 
465 	gdk_color_parse("white", &white);
466 	gdk_color_parse("black", &black);
467 }
468 
469 static void
gtk_ui_graphics_init(void)470 gtk_ui_graphics_init(void) {
471 	offscreen = gdk_pixmap_new(field->window, screensize, screensize, -1);
472 	stdgc = gdk_gc_new(offscreen);
473 	gdk_gc_set_exposures(stdgc, FALSE);
474 	gdk_gc_set_line_attributes(stdgc, 2, GDK_LINE_SOLID, GDK_CAP_ROUND,
475 				   GDK_JOIN_MITER);
476 	font = gdk_font_load("fixed");
477 }
478 
479 static GtkWidget *
new_button(GtkWidget * dialog,const char * text,GtkSignalFunc func,GtkObject * obj)480 new_button(GtkWidget *dialog, const char *text, GtkSignalFunc func,
481 	   GtkObject *obj)
482 {
483 	GtkWidget *button = gtk_button_new_with_label(text);
484 	if (func != NULL)
485 		gtk_signal_connect_object(GTK_OBJECT(button), "clicked",
486 					  func, obj);
487 	gtk_signal_connect_object(GTK_OBJECT(button), "clicked",
488 				  GTK_SIGNAL_FUNC(gtk_widget_hide),
489 				  GTK_OBJECT(dialog));
490 	gtk_signal_connect_object(GTK_OBJECT(button), "clicked",
491 				  GTK_SIGNAL_FUNC(popdown), NULL);
492 	gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
493 			  button);
494 	gtk_widget_show(button);
495 	return button;
496 }
497 
498 static void
CreateDialog(int index,int hascancel,Picture * icon,const char * buttonlabel,GtkSignalFunc func)499 CreateDialog(int index, int hascancel, Picture *icon,
500 	     const char *buttonlabel, GtkSignalFunc func)
501 {
502 	GtkWidget *dialog, *pixmap, *label, *hbox;
503 
504 	dialog = gtk_dialog_new();
505 	gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
506 
507 	hbox = gtk_hbox_new(FALSE, 0);
508 
509 	if (icon != NULL) {
510 		pixmap = gtk_pixmap_new(icon->pix, icon->mask);
511 		gtk_container_add(GTK_CONTAINER(hbox), pixmap);
512 	}
513 
514 	label = gtk_label_new(UI_dialog_string(index));
515 	gtk_container_add(GTK_CONTAINER(hbox), label);
516 
517 	gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox);
518 	gtk_widget_show_all(hbox);
519 
520 	if (buttonlabel == NULL)
521 		buttonlabel = "OK";
522 	new_button(dialog, buttonlabel, func, NULL);
523 
524 	if (hascancel)
525 		new_button(dialog, "Cancel", NULL, NULL);
526 
527 	gtk_widget_realize(dialog);
528 	dialogs[index] = dialog;
529 }
530 
531 static void
CreateEnterText(int index,GtkSignalFunc func)532 CreateEnterText(int index, GtkSignalFunc func) {
533 	GtkWidget *dialog, *label, *entry;
534 
535 	dialog = gtk_dialog_new();
536 	gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
537 
538 	label = gtk_label_new(UI_dialog_string(index));
539 	gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label);
540 	gtk_widget_show(label);
541 
542 	entry = gtk_entry_new_with_max_length(20);
543 	gtk_signal_connect_object(GTK_OBJECT(entry), "activate",
544 				  func, GTK_OBJECT(entry));
545 	gtk_signal_connect_object(GTK_OBJECT(entry), "activate",
546 				  GTK_SIGNAL_FUNC(gtk_widget_hide),
547 				  GTK_OBJECT(dialog));
548 	gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), entry);
549 	gtk_widget_show(entry);
550 
551 	new_button(dialog, "OK", func, GTK_OBJECT(entry));
552 
553 	gtk_widget_realize(dialog);
554 	dialogs[index] = dialog;
555 }
556 
557 static void
CreatePixmapBox(int index,Picture * logo,Picture * pix)558 CreatePixmapBox(int index, Picture *logo, Picture *pix) {
559 	GtkWidget *dialog, *pixmap, *label;
560 	const char *text = UI_dialog_string(index);
561 
562 	dialog = gtk_dialog_new();
563 	gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
564 
565 	pixmap = gtk_pixmap_new(logo->pix, logo->mask);
566 	gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), pixmap);
567 	gtk_widget_show(pixmap);
568 
569 	if (pix != NULL) {
570 		pixmap = gtk_pixmap_new(pix->pix, pix->mask);
571 		gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox),
572 				  pixmap);
573 		gtk_widget_show(pixmap);
574 	}
575 
576 	if (text != NULL) {
577 		label = gtk_label_new(text);
578 		gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox),
579 				  label);
580 		gtk_widget_show(label);
581 	}
582 
583 	new_button(dialog, "OK", NULL, NULL);
584 
585 	gtk_widget_realize(dialog);
586 	dialogs[index] = dialog;
587 }
588 
589 static void
gtk_ui_create_dialogs(Picture * logo,Picture * icon,Picture * about)590 gtk_ui_create_dialogs(Picture *logo, Picture *icon, Picture *about) {
591 	CreateDialog(DIALOG_NEWGAME, 1, NULL, NULL, new_game);
592 	CreateDialog(DIALOG_PAUSEGAME, 0, icon, "Continue", NULL);
593 	CreateEnterText(DIALOG_WARPLEVEL, warp_apply);
594 	CreateDialog(DIALOG_HIGHSCORE, 0, NULL, NULL, NULL);
595 	CreateDialog(DIALOG_QUITGAME, 1, NULL, NULL, quit_game);
596 
597 	CreatePixmapBox(DIALOG_STORY, logo, NULL);
598 	CreatePixmapBox(DIALOG_RULES, logo, NULL);
599 	CreatePixmapBox(DIALOG_ABOUT, logo, about);
600 
601 	CreateDialog(DIALOG_SCORE, 0, NULL, NULL, NULL);
602 	CreateDialog(DIALOG_ENDGAME, 0, NULL, "Nuts!", NULL);
603 	CreateEnterText(DIALOG_ENTERNAME, enter_name);
604 }
605 
606 static void
set_label(GtkWidget * dialog,const char * str)607 set_label(GtkWidget *dialog, const char *str) {
608 	GList *list;
609 	GtkWidget *hbox = NULL;
610 
611 	list = gtk_container_children(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox));
612 	while (list != NULL) {
613 		GtkWidget *w = (GtkWidget *) list->data;
614 		list = g_list_next(list);
615 		if (GTK_IS_HBOX(w)) {
616 			hbox = w;
617 			break;
618 		}
619 	}
620 	if (hbox == NULL)
621 		return;
622 	list = gtk_container_children(GTK_CONTAINER(hbox));
623 	while (list != NULL) {
624 		GtkWidget *w = (GtkWidget *) list->data;
625 		list = g_list_next(list);
626 		if (GTK_IS_LABEL(w)) {
627 			gtk_label_set_text(GTK_LABEL(w), str);
628 			return;
629 		}
630 	}
631 }
632 
633 static void
gtk_ui_update_dialog(int index,const char * str)634 gtk_ui_update_dialog(int index, const char *str) {
635 	set_label(dialogs[index], str);
636 }
637 
638 static void
gtk_ui_set_pausebutton(int active)639 gtk_ui_set_pausebutton(int active) {
640 	if (pausebutton != NULL)
641 		gtk_widget_set_sensitive(pausebutton, active);
642 }
643 
644 static struct UI_methods gtk_methods = {
645 	gtk_ui_set_cursor,
646 	gtk_ui_load_cursor,
647 	gtk_ui_load_picture,
648 	gtk_ui_set_icon,
649 	gtk_ui_picture_width,
650 	gtk_ui_picture_height,
651 	gtk_ui_graphics_init,
652 	gtk_ui_clear_window,
653 	gtk_ui_refresh_window,
654 	gtk_ui_draw_image,
655 	gtk_ui_draw_line,
656 	gtk_ui_draw_string,
657 	gtk_ui_start_timer,
658 	gtk_ui_stop_timer,
659 	gtk_ui_timer_active,
660 	gtk_ui_popup_dialog,
661 	gtk_ui_main_loop,
662 	gtk_ui_initialize,
663 	gtk_ui_make_main_window,
664 	gtk_ui_create_dialogs,
665 	gtk_ui_set_pausebutton,
666 	gtk_ui_update_dialog,
667 };
668 
669 void
gtk_ui_setmethods(UI_methods ** methodsp)670 gtk_ui_setmethods(UI_methods **methodsp) {
671 	*methodsp = &gtk_methods;
672 }
673