/* $Id: gtkyn.c,v 1.12.2.1 2005/01/22 19:09:35 j_ali Exp $ */ /* GTK+ NetHack Copyright (c) Issei Numata 1999-2000 Copyright (c) Slash'EM Development Team 2000-2003 GTK+ NetHack may be freely redistributed. See license for details. */ #include #include #include #include #include "winGTK.h" static struct yn_params { const char *query; const char *resp; CHAR_P def; int *count; int isdir; int watch; GtkWidget *w; } params; static gint yn_clicked(GtkWidget *widget, gpointer data) { nh_key_add((char)GPOINTER_TO_INT(data)); return TRUE; } static gint yn_destroy(GtkWidget *widget, gpointer data) { params.w = 0; params.watch++; return FALSE; } static int yn_valid_response(int keysym) { if (!*params.resp || index(params.resp, keysym)) return keysym; else if (keysym == '\n' || keysym == ' ' || keysym == '\033') return params.def; else return 0; } static gint yn_key_press(GtkWidget *widget, GdkEventKey *event, gpointer data) { char keysym; keysym = params.isdir ? nh_dir_keysym(event) : 0; if (!keysym) keysym = nh_keysym(event); keysym = yn_valid_response(keysym); if (keysym) nh_key_add(keysym); return TRUE; } static gboolean yn_show_window(gpointer data) { GtkWidget *window; GtkWidget *frame; GtkWidget *vbox; GtkWidget *hbox; GtkWidget *table = NULL; GtkWidget *y, *n, *q; GtkWidget *d; gchar buf[NH_BUFSIZ], *bp; if (nh_key_check()) /* Avoid race condition */ return FALSE; if (*params.resp) { sprintf(buf, "%s [", params.query); bp = eos(buf); strcpy(bp, params.resp); bp = index(bp, '\033'); if (bp) *bp = '\0'; bp = eos(buf); *bp++ = ']'; if (params.def) sprintf(bp, "(%c) ", params.def); else { *bp++ = ' '; *bp = '\0'; } } else sprintf(buf, "%s ", params.query); window = params.w; gtk_signal_connect(GTK_OBJECT(window), "destroy", GTK_SIGNAL_FUNC(yn_destroy), 0); frame = nh_gtk_new_and_add(gtk_frame_new(buf), window, ""); gtk_container_border_width(GTK_CONTAINER(frame), NH_PAD); vbox = nh_gtk_new_and_add(gtk_vbox_new(FALSE, 0), frame, ""); if (*params.resp) { hbox = nh_gtk_new_and_pack(gtk_hbox_new(FALSE, 0), vbox, "", FALSE, FALSE, NH_PAD); if (!strcmp(params.resp, "yn") || !strcmp(params.resp, "ynq")) { y = nh_gtk_new_and_pack(gtk_button_new_from_stock(GTK_STOCK_YES), hbox, "", FALSE, FALSE, NH_PAD); gtk_signal_connect(GTK_OBJECT(y), "clicked", GTK_SIGNAL_FUNC(yn_clicked), (gpointer)'y'); } if (!strcmp(params.resp, "yn") || !strcmp(params.resp, "ynq") || !strcmp(params.resp, "ynaq") || !strcmp(params.resp, "yn#aq")) { n = nh_gtk_new_and_pack(gtk_button_new_from_stock(GTK_STOCK_NO), hbox, "", FALSE, FALSE, NH_PAD); gtk_signal_connect(GTK_OBJECT(n), "clicked", GTK_SIGNAL_FUNC(yn_clicked), (gpointer)'n'); } if (!strcmp(params.resp, "ynaq") || !strcmp(params.resp, "yn#aq")) { q = nh_gtk_new_and_pack(gtk_button_new_with_label("All"), hbox, "", FALSE, FALSE, NH_PAD); gtk_signal_connect(GTK_OBJECT(q), "clicked", GTK_SIGNAL_FUNC(yn_clicked), (gpointer)'a'); } if (!strcmp(params.resp, "ynq") || !strcmp(params.resp, "ynaq") || !strcmp(params.resp, "yn#aq")) { q = nh_gtk_new_and_pack(gtk_button_new_from_stock(GTK_STOCK_CANCEL), hbox, "", FALSE, FALSE, NH_PAD); gtk_signal_connect(GTK_OBJECT(q), "clicked", GTK_SIGNAL_FUNC(yn_clicked), (gpointer)'q'); } } else { hbox = nh_gtk_new_and_pack(gtk_hbox_new(FALSE, 0), vbox, "", FALSE, FALSE, NH_PAD); if (index(params.query, '*')) { q = nh_gtk_new_and_pack(gtk_button_new_with_label("List"), hbox, "", FALSE, FALSE, NH_PAD); gtk_signal_connect(GTK_OBJECT(q), "clicked", GTK_SIGNAL_FUNC(yn_clicked), (gpointer)'?'); q = nh_gtk_new_and_pack(gtk_button_new_with_label("All List"), hbox, "", FALSE, FALSE, NH_PAD); gtk_signal_connect(GTK_OBJECT(q), "clicked", GTK_SIGNAL_FUNC(yn_clicked), (gpointer)'*'); } else if (params.isdir) { /* maybe direction */ int i, j; struct { char *str; int key; } dirstr[4][3] = { { {"Y", 'y'}, {"K", 'k'}, {"U", 'u'}, }, { {"H", 'h'}, {".", '.'}, {"L", 'l'}, }, { {"B", 'b'}, {"J", 'j'}, {"N", 'n'}, }, { {"Up", '<'}, {"", 0}, {"Down", '>'}, } }, np_dirstr[4][3] = { { {"7", '7'}, {"8", '8'}, {"9", '9'}, }, { {"4", '4'}, {".", '.'}, {"6", '6'}, }, { {"1", '1'}, {"2", '2'}, {"3", '3'}, }, { {"Up", '<'}, {"", 0}, {"Down", '>'}, } }; table = nh_gtk_new_and_pack(gtk_table_new(4, 3, TRUE), hbox, "", FALSE, FALSE, NH_PAD); for(i = 0; i < 4; i++) for(j = 0; j < 3; j++) { d = nh_gtk_new_and_attach( gtk_button_new_with_label(copts.num_pad ? np_dirstr[i][j].str : dirstr[i][j].str), table, "", j, j+1, i, i+1); gtk_signal_connect(GTK_OBJECT(d), "clicked", GTK_SIGNAL_FUNC(yn_clicked), copts.num_pad ? (gpointer)np_dirstr[i][j].key : (gpointer)dirstr[i][j].key); } } } gtk_widget_show_all(window); return FALSE; } char GTK_ext_yn_function(const char *query, const char *resp, CHAR_P def, int *count) { int keysym = 0, exiting; guint timeout_id; while (nh_key_check()) { keysym = nh_key_get(); keysym = yn_valid_response(keysym); } if (!keysym) { params.query = query; params.resp = resp; params.def = def; params.count = count; params.watch = 0; params.isdir = !*resp && strstr(query, "In what direction"); params.w = nh_gtk_window_dialog(FALSE); nh_position_popup_dialog(GTK_WIDGET(params.w)); nh_gtk_focus_set_master(GTK_WINDOW(params.w), GTK_SIGNAL_FUNC(yn_key_press), 0, TRUE); timeout_id = g_timeout_add(500, yn_show_window, 0); exiting = main_hook(¶ms.watch); g_source_remove(timeout_id); if (exiting || params.watch) { /* Either exiting or dialog was created and then closed by user */ nh_key_add(def); } if (params.w) { gtk_widget_destroy(params.w); params.w = 0; } keysym = nh_key_get(); } return keysym; }