summaryrefslogtreecommitdiff
path: root/patches/gtk2/g2bind.c
diff options
context:
space:
mode:
authorJosep Torra <n770galaxy@gmail.com>2013-01-04 09:30:48 +0100
committerJosep Torra <n770galaxy@gmail.com>2013-01-04 09:30:48 +0100
commit1f80a252d48b3f6eed4469d60c7d109de46eb362 (patch)
treebac9e7d498164f96bf4fea368c3776d58004f287 /patches/gtk2/g2bind.c
Initial commit
Diffstat (limited to 'patches/gtk2/g2bind.c')
-rw-r--r--patches/gtk2/g2bind.c1138
1 files changed, 1138 insertions, 0 deletions
diff --git a/patches/gtk2/g2bind.c b/patches/gtk2/g2bind.c
new file mode 100644
index 0000000..fb5fb3e
--- /dev/null
+++ b/patches/gtk2/g2bind.c
@@ -0,0 +1,1138 @@
+/* Binding the nethack engine to the gtk2 port
+ *
+ * $Id: g2bind.c,v 1.2 2004/06/27 00:17:32 miq Exp $
+ *
+ */
+
+
+/** define this if you want to see more dialogs to choose from, so more mouse instead of keys */
+#define MORE_DIALOGS
+
+
+// #include <gtk.h>
+#include <gdk/gdkkeysyms.h>
+
+#include "g2map.h" /* for get_tile */
+
+#include "g2bind.h"
+#include "g2main.h"
+#include "g2player.h"
+#include "g2text.h"
+#include "g2i18n.h"
+
+#include "func_tab.h"
+#include "decl.h" /* for inventory and such */
+#include "obj.h" /* for obj_to_glyph */
+#include "objclass.h" /* for gold */
+
+struct window_procs Gtk2_procs = {
+ "Gtk2",
+ WC_COLOR | WC_HILITE_PET | WC_INVERSE,
+ 0L,
+ gtk2_init_nhwindows,
+ gtk2_player_selection,
+ gtk2_askname,
+ gtk2_get_nh_event,
+ gtk2_exit_nhwindows,
+ gtk2_suspend_nhwindows,
+ gtk2_resume_nhwindows,
+ gtk2_create_nhwindow,
+ gtk2_clear_nhwindow,
+ gtk2_display_nhwindow,
+ gtk2_destroy_nhwindow,
+ gtk2_curs,
+ gtk2_putstr,
+ gtk2_display_file,
+ gtk2_start_menu,
+ gtk2_add_menu,
+ gtk2_end_menu,
+ gtk2_select_menu,
+ genl_message_menu, /* no need for X-specific handling */
+ gtk2_update_inventory,
+ gtk2_mark_synch,
+ gtk2_wait_synch,
+#ifdef CLIPPING
+ gtk2_cliparound,
+#endif
+#ifdef POSITIONBAR
+ donull,
+#endif
+ gtk2_print_glyph,
+ gtk2_raw_print,
+ gtk2_raw_print_bold,
+ gtk2_nhgetch,
+ gtk2_nh_poskey,
+ gtk2_nhbell,
+ gtk2_doprev_message,
+ gtk2_yn_function,
+ gtk2_getlin,
+ gtk2_get_ext_cmd,
+ gtk2_number_pad,
+ gtk2_delay_output,
+#ifdef CHANGE_COLOR /* only a Mac option currently */
+ donull,
+ donull,
+#endif
+ /* other defs that really should go away (they're tty specific) */
+ gtk2_start_screen,
+ gtk2_end_screen,
+ gtk2_outrip,
+ genl_preference_update,
+};
+
+#define G2_OUTPUT_DELAY 40 /* milliseconds to wait between delayed outputs */
+#ifndef HILDON
+static gboolean inventoryReady = FALSE;
+#endif
+static gboolean delayDone = FALSE;
+
+void
+gtk2_init_nhwindows (int *argcp, char **argv)
+{
+ g2_init_main_window (argcp, argv);
+ iflags.window_inited = TRUE;
+}
+
+void
+gtk2_player_selection (void)
+{
+ g2_do_player_selection (g2_get_main_window ());
+}
+
+void
+gtk2_askname (void)
+{
+ GtkWidget *inputDialog;
+ GtkWidget *spacerVbox;
+ GtkWidget *questionLabel;
+ GtkWidget *inputEntry;
+ gint response;
+
+ inputDialog = gtk_dialog_new_with_buttons (_("Choose your name?"),
+ GTK_WINDOW (g2_get_main_window
+ ()),
+ GTK_DIALOG_MODAL,
+ GTK_STOCK_CANCEL,
+ GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
+ spacerVbox = gtk_vbox_new (FALSE, 6);
+
+ gtk_container_set_border_width (GTK_CONTAINER (spacerVbox), 5);
+ questionLabel = gtk_label_new (_("What's your name?"));
+ gtk_misc_set_alignment (GTK_MISC (questionLabel), 0.0, 0.5);
+ gtk_box_pack_start (GTK_BOX (spacerVbox), questionLabel, TRUE, FALSE, 5);
+
+ inputEntry = gtk_entry_new ();
+ gtk_entry_set_max_length (GTK_ENTRY (inputEntry), PL_NSIZ - 1);
+ gtk_entry_set_text (GTK_ENTRY (inputEntry), plname);
+ gtk_entry_set_activates_default (GTK_ENTRY (inputEntry), TRUE);
+ gtk_box_pack_start (GTK_BOX (spacerVbox), inputEntry, TRUE, FALSE, 5);
+
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (inputDialog)->vbox), spacerVbox,
+ TRUE, TRUE, 0);
+ gtk_dialog_set_default_response (GTK_DIALOG (inputDialog), GTK_RESPONSE_OK);
+ gtk_widget_show_all (inputDialog);
+
+ response = gtk_dialog_run (GTK_DIALOG (inputDialog));
+ if (response == GTK_RESPONSE_OK) {
+ g_strlcpy (plname, gtk_entry_get_text (GTK_ENTRY (inputEntry)), PL_NSIZ);
+ } else {
+ // do nothing
+ }
+ gtk_widget_destroy (inputDialog);
+
+}
+
+void
+gtk2_get_nh_event (void)
+{
+ /* XXX: We do our own eventhandling ?! */
+}
+
+void
+gtk2_exit_nhwindows (const char *string)
+{
+ g2_exit_windows (string);
+}
+
+void
+gtk2_suspend_nhwindows (const char *string)
+{
+ g_print ("gtk2_suspend_nhwindows: currently unimplemented\n");
+}
+
+void
+gtk2_resume_nhwindows (void)
+{
+ g_print ("resume_nhwindows: currently unimplemented\n");
+}
+
+winid
+gtk2_create_nhwindow (int type)
+{
+ return g2_create_window (type);
+}
+
+void
+gtk2_clear_nhwindow (winid wid)
+{
+ g_signal_emit_by_name (G_OBJECT (wid), "clear", NULL);
+}
+
+void
+gtk2_display_nhwindow (winid wid, BOOLEAN_P block)
+{
+ g_signal_emit_by_name (G_OBJECT (wid), "display", block, NULL);
+ /* show the map and wait until user presses a key. This causes the output to
+ * block when detecting monsters, gold, food or finding a trap hidden under
+ * some item.
+ */
+ if (block && wid == WIN_MAP) {
+ gtk2_nhgetch ();
+ }
+}
+
+void
+gtk2_destroy_nhwindow (winid wid)
+{
+ /* XXX prevent our main windows from being destroyed! */
+ if (wid != WIN_MAP && wid != WIN_STATUS && wid != WIN_MESSAGE) {
+ gtk_widget_destroy (GTK_WIDGET (wid));
+ }
+}
+
+void
+gtk2_curs (winid wid, int x, int y)
+{
+ g_signal_emit_by_name (G_OBJECT (wid), "curs", x, y, NULL);
+}
+
+void
+gtk2_putstr (winid wid, int attr, const char *text)
+{
+ g_signal_emit_by_name (G_OBJECT (wid), "putstr", attr, text, NULL);
+}
+
+void
+gtk2_display_file (const char *filename, BOOLEAN_P must_exist)
+{
+ dlb *file;
+
+ file = dlb_fopen (filename, "r");
+ if (file) {
+ GtkWidget *textWindow;
+ gchar line[128];
+
+ /* read the contents and display it */
+ textWindow = g2_text_new ();
+ while (dlb_fgets (line, 128, file)) {
+ /* XXX strip newline from buffer, think of changing putstr to not add \n */
+ line[strlen (line) - 1] = '\0';
+ g_signal_emit_by_name (G_OBJECT (textWindow), "putstr", 0, line, NULL);
+ }
+ dlb_fclose (file);
+ g_signal_emit_by_name (G_OBJECT (textWindow), "display", TRUE, NULL);
+ gtk_widget_destroy (textWindow);
+ } else if (!file && must_exist) {
+ /* show error */
+ GtkWidget *errorDialog;
+ gchar message[128];
+
+ g_snprintf (message, 128, "Error! Could not find file: %s\n", filename);
+ errorDialog =
+ gtk_message_dialog_new (GTK_WINDOW (g2_get_main_window ()),
+ GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, message);
+ gtk_dialog_run (GTK_DIALOG (errorDialog));
+ gtk_widget_destroy (errorDialog);
+ }
+}
+
+void
+gtk2_start_menu (winid wid)
+{
+ g_signal_emit_by_name (G_OBJECT (wid), "start_menu", NULL);
+}
+
+void
+gtk2_add_menu (winid wid, int glyph, const ANY_P * identifier,
+ CHAR_P accelerator, CHAR_P group_accel, int attr,
+ const char *str, BOOLEAN_P presel)
+{
+ g_signal_emit_by_name (G_OBJECT (wid),
+ "add_menu", glyph, identifier, accelerator,
+ group_accel, attr, str, presel, NULL);
+}
+
+void
+gtk2_end_menu (winid wid, const char *prompt)
+{
+ g_signal_emit_by_name (G_OBJECT (wid), "end_menu", prompt, NULL);
+}
+
+int
+gtk2_select_menu (winid wid, int how, MENU_ITEM_P ** selected)
+{
+ gint returnValue;
+
+ g_signal_emit_by_name (G_OBJECT (wid),
+ "select_menu", how, selected, &returnValue);
+
+ return returnValue;
+}
+
+void
+gtk2_update_inventory (void)
+{
+ /* XXX we need to investigate segfault when restoring game and not delaying inventory update */
+#ifndef HILDON
+ if (flags.perm_invent && inventoryReady) {
+ display_inventory (NULL, 0);
+ }
+#endif
+}
+
+void
+gtk2_mark_synch (void)
+{
+ /* XXX: do we have to do to something? */
+ g_print ("mark_synch, unimplemented\n");
+}
+
+void
+gtk2_wait_synch (void)
+{
+ /* XXX: do we have to do to something? */
+ g_print ("wait_synch, unimplemented\n");
+}
+
+void
+gtk2_cliparound (int x, int y)
+{
+ /* XXX: Currently we assume that only the map can be clipped */
+ g_signal_emit_by_name (G_OBJECT (WIN_MAP), "cliparound", x, y, NULL);
+}
+
+void
+gtk2_print_glyph (winid wid, XCHAR_P x, XCHAR_P y, int glyph)
+{
+ g_signal_emit_by_name (G_OBJECT (wid), "print_glyph", x, y, glyph, NULL);
+}
+
+void
+gtk2_raw_print (const char *str)
+{
+ /* g_print("%s\n", str); */
+}
+
+void
+gtk2_raw_print_bold (const char *str)
+{
+ /* g_print("%s\n", str); */
+ /* tty_raw_print_bold(str); */
+}
+
+/* XXX: This is our event-loop thingy, that checks the keybuffer */
+int
+gtk2_nhgetch (void)
+{
+ int key;
+
+ do {
+ while (keyBuffer == NULL) {
+ gtk_main_iteration ();
+ }
+ key = GPOINTER_TO_INT (keyBuffer->data);
+ keyBuffer = g_slist_delete_link (keyBuffer, keyBuffer);
+ }
+ while (key == 0); /* key == 0 would be a pos event */
+
+ return key;
+}
+
+
+/** Nethack callback function.
+ * Nethack is waiting for a key input or a position.
+ * we call gtk_main_iteration until we have something.
+ */
+int
+gtk2_nh_poskey (int *x, int *y, int *mod)
+{
+ gint key;
+
+ /* XXX hack: we call set a flag for perm_invent and call display_inventory the first time */
+#ifndef HILDON
+ // if (!inventoryReady && flags.perm_invent) {
+ // inventoryReady = TRUE;
+ // display_inventory(NULL, 0);
+ // }
+ g_signal_emit_by_name(G_OBJECT(g2_get_equipment_window()), "update" , NULL);
+#endif
+ while (keyBuffer == NULL) {
+ gtk_main_iteration ();
+ }
+ g_signal_emit_by_name (G_OBJECT (WIN_STATUS), "player_acted", NULL);
+ key = GPOINTER_TO_INT (keyBuffer->data);
+ keyBuffer = g_slist_delete_link (keyBuffer, keyBuffer);
+
+ /* key == 0 means that we return a position event */
+ if (key == 0) {
+ *x = clickX;
+ *y = clickY;
+ *mod = clickMod;
+ }
+ return key;
+}
+
+void
+gtk2_nhbell (void)
+{
+ gdk_beep ();
+}
+
+int
+gtk2_doprev_message (void)
+{
+ /* do nothing, we have a nice textarea with a scrollbar */
+ return 0;
+}
+
+
+/** An event handler for key events.
+ * Closes the dialog and returns the pressed key as result.
+ * The user doesn't have to press the buttons to make actions.
+ */
+static gboolean
+g2_dialog_key_press_event (GtkWidget * widget, GdkEventKey * event,
+ gpointer data)
+{
+ gint key = event->keyval;
+
+ /* convert movement keys */
+ if (iflags.num_pad && g2_move_keys_with_numpad (event->keyval, &key)) {
+ gtk_dialog_response (GTK_DIALOG (widget), key);
+
+ } else if (g2_key_is_valid_input (key)) {
+ if (event->state & GDK_MOD1_MASK) {
+ /*g_print("modifier <ALT> pressed\n"); */
+ key = key | META_BIT;
+ } else if (event->state & GDK_CONTROL_MASK) {
+ /*g_print("modifier <CONTROL> pressed\n"); */
+ /* do not handle some menu accelerators which are not needed by nethack */
+ switch (key) {
+ case GDK_q:
+ return FALSE;
+ default:
+ break;
+ }
+ key = CTRL_BITS & key;
+ }
+
+ gtk_dialog_response (GTK_DIALOG (widget), key);
+ }
+
+
+ return TRUE;
+}
+
+
+/** Displays a yes/no/cancel dialog and returns the result */
+gchar
+gtk2_yn_dialog (const gchar * question, const gchar * choices, CHAR_P def)
+{
+ gchar res;
+ gint dialogResult;
+ GtkWidget *dialog =
+ gtk_message_dialog_new (GTK_WINDOW (g2_get_main_window ()),
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_QUESTION,
+ GTK_BUTTONS_NONE,
+ question);
+
+ /* -- add buttons */
+ if (g_strrstr (choices, "q") != NULL || g_strrstr (choices, "n") == NULL) { /* cancel should be always allowed */
+ gtk_dialog_add_button (GTK_DIALOG (dialog),
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
+ }
+ if (g_strrstr (choices, "n") != NULL) {
+ gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_NO, GTK_RESPONSE_NO);
+ }
+
+ if (g_strrstr (choices, "y") != NULL) {
+ gtk_dialog_add_button (GTK_DIALOG (dialog),
+ GTK_STOCK_YES, GTK_RESPONSE_YES);
+ }
+
+ if (g_strrstr (choices, "a") != NULL) {
+ gtk_dialog_add_button (GTK_DIALOG (dialog), _("All"), 'a');
+ }
+
+ if (g_strrstr (choices, "l") != NULL) {
+ gtk_dialog_add_button (GTK_DIALOG (dialog), _("Left"), 'l');
+ }
+
+ if (g_strrstr (choices, "r") != NULL) {
+ gtk_dialog_add_button (GTK_DIALOG (dialog), _("Right"), 'r');
+ }
+
+ /* -- set default action */
+ switch (def) {
+ case 'y':
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_YES);
+ break;
+ case 'n':
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_NO);
+ break;
+ case 'a':
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), 'a');
+ break;
+ case 'l':
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), 'l');
+ break;
+ case 'r':
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), 'r');
+ break;
+ case 'q':
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog),
+ GTK_RESPONSE_CANCEL);
+ break;
+ }
+
+ g_signal_connect (G_OBJECT (dialog), "key_press_event",
+ G_CALLBACK (g2_dialog_key_press_event), dialog);
+
+ res = 0;
+ do {
+ dialogResult = gtk_dialog_run (GTK_DIALOG (dialog));
+
+ switch (dialogResult) {
+ case GTK_RESPONSE_YES:
+ res = 'y';
+ break;
+ case GTK_RESPONSE_NO:
+ res = 'n';
+ break;
+ default:
+ if (dialogResult > ' ')
+ res = dialogResult;
+
+ else if (choices != NULL && g_strrstr (choices, "q") != NULL) {
+ res = 'q';
+ }
+ break;
+ }
+
+ }
+ while (res == 0);
+
+ gtk_widget_destroy (dialog);
+
+ return res;
+}
+
+
+/** a convinience function for adding something to a table */
+void
+table_attach_simple (GtkTable * table, GtkWidget * widget, gint x, gint y)
+{
+ gtk_table_attach (table, widget,
+ x, x + 1, y, y + 1, GTK_SHRINK, GTK_SHRINK, 0, 0);
+}
+
+
+
+typedef struct
+{
+ const gchar *name;
+ const gchar key;
+ const gchar num_key;
+ const gint xpos;
+ const gint ypos;
+} DirectionButton;
+
+static DirectionButton direction_buttons[] = {
+ {HACK_STOCK_DIR_NW, 'y', '7', 0, 0},
+ {HACK_STOCK_DIR_N, 'k', '8', 1, 0},
+ {HACK_STOCK_DIR_NE, 'u', '9', 2, 0},
+ {HACK_STOCK_DIR_W, 'h', '4', 0, 1},
+ {HACK_STOCK_DIR_SELF, '.', '.', 1, 1},
+ {HACK_STOCK_DIR_E, 'l', '6', 2, 1},
+ {HACK_STOCK_DIR_SW, 'b', '1', 0, 2},
+ {HACK_STOCK_DIR_S, 'j', '2', 1, 2},
+ {HACK_STOCK_DIR_SE, 'n', '3', 2, 2},
+ {GTK_STOCK_GO_UP, '<', '<', 3, 1},
+ {GTK_STOCK_GO_DOWN, '>', '>', 3, 2},
+};
+
+/* Callback activated by direction button press.
+ * just closes the dialog with the correct response */
+static void
+gtk2_direction_button_callback (GtkWidget * widget, gpointer data)
+{
+ GtkWidget *dialog = gtk_widget_get_ancestor (widget, GTK_TYPE_DIALOG);
+
+ if (dialog) {
+ if (iflags.num_pad)
+ gtk_dialog_response (GTK_DIALOG (dialog),
+ ((DirectionButton *) data)->num_key);
+ else
+ gtk_dialog_response (GTK_DIALOG (dialog),
+ ((DirectionButton *) data)->key);
+ }
+}
+
+
+gchar
+gtk2_yn_direction_dialog ()
+{
+
+ int i;
+ GtkWidget *directionDialog;
+ GtkWidget *vbox;
+ GtkWidget *table;
+ GtkWidget *button;
+ gint response;
+ gchar res;
+
+// gint window_width;
+// gint window_height;
+
+ directionDialog = gtk_dialog_new_with_buttons ("In what direction?",
+ GTK_WINDOW
+ (g2_get_main_window ()),
+ GTK_DIALOG_MODAL |
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, NULL);
+ gtk_dialog_set_has_separator (GTK_DIALOG (directionDialog), FALSE);
+
+ /* -- create the table and the direction buttons */
+ table = gtk_table_new (4, 3, FALSE);
+ for (i = 0; i < G_N_ELEMENTS (direction_buttons); i++) {
+ button = gtk_button_new_from_stock (direction_buttons[i].name);
+ table_attach_simple (GTK_TABLE (table), button,
+ direction_buttons[i].xpos, direction_buttons[i].ypos);
+ g_signal_connect (G_OBJECT (button), "clicked",
+ G_CALLBACK (gtk2_direction_button_callback), &(direction_buttons[i]));
+ }
+
+ /* -- and now pack everything together */
+ vbox = gtk_vbox_new (FALSE, 12);
+ gtk_container_set_border_width (GTK_CONTAINER (vbox), 12);
+
+ gtk_box_pack_start (GTK_BOX (vbox), table, TRUE, TRUE, 0);
+
+
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (directionDialog)->vbox), vbox,
+ FALSE, FALSE, 0);
+ gtk_dialog_set_default_response (GTK_DIALOG (directionDialog),
+ GTK_RESPONSE_OK);
+
+ g_signal_connect (G_OBJECT (directionDialog), "key_press_event",
+ G_CALLBACK (g2_dialog_key_press_event), directionDialog);
+
+ gtk_widget_show_all (directionDialog);
+ gtk_window_move (GTK_WINDOW (directionDialog), 10, 300);
+ response = gtk_dialog_run (GTK_DIALOG (directionDialog));
+
+ if (response > 0) {
+ res = response;
+ } else {
+ res = 0;
+ }
+ gtk_widget_destroy (directionDialog);
+
+ return res;
+}
+
+/** my own isAlpha function.
+ * @returns TRUE if the character is a alpha character
+ */
+gchar
+isAlpha (gchar c)
+{
+ return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) ? TRUE : FALSE;
+}
+
+
+/* Callback activated by item button press.
+ * just closes the dialog with the correct response */
+static void
+gtk2_item_button_callback (GtkWidget * widget, gpointer data)
+{
+ GtkWidget *dialog = gtk_widget_get_ancestor (widget, GTK_TYPE_DIALOG);
+
+ if (dialog) {
+ gtk_dialog_response (GTK_DIALOG (dialog), GPOINTER_TO_INT (data));
+ }
+}
+
+
+
+/** Produces a new item button for the gtk2_yn_item_dialog() */
+GtkWidget *
+newItemButton (gchar id, int glyph)
+{
+ gchar text[2];
+ GtkWidget *button;
+
+ text[0] = id;
+ text[1] = '\0';
+
+ button = gtk_button_new_from_stock (text);
+ // gtk_container_set_border_width(GTK_CONTAINER(button), 0);
+
+ if (glyph != NO_GLYPH) {
+ GdkPixbuf *tile = g2_get_tile_scaled (glyph, 16);
+ GtkWidget *image = gtk_image_new_from_pixbuf (tile);
+ GValue value = { 0, };
+ g_value_init (&value, G_TYPE_OBJECT);
+ g_value_set_object (&value, G_OBJECT (image));
+ g_object_set_property (G_OBJECT (button), "image", &value);
+ g_value_unset (&value);
+ }
+
+ g_signal_connect (G_OBJECT (button), "clicked",
+ G_CALLBACK (gtk2_item_button_callback), GINT_TO_POINTER ((int) id));
+
+ return button;
+}
+
+
+/** Returns the object for the given inventory character */
+struct obj *
+getObject (gchar c)
+{
+ struct obj *otmp;
+
+ for (otmp = invent; otmp; otmp = otmp->nobj)
+ if (otmp->invlet == c)
+ return otmp;
+
+ return NULL;
+}
+
+
+/** This dialog let's you choose some objects. (maybe to drop, e.g)*/
+gchar
+gtk2_yn_item_dialog (const gchar * question, const gchar * choice)
+{
+ gchar lastChar=0;
+ const gchar *pos;
+ int itemCount;
+ int itemWidth;
+ int itemNum;
+ GtkWidget *itemDialog;
+ GtkWidget *vbox;
+ GtkWidget *questionLabel;
+ GtkWidget *table;
+ gint response;
+ gchar res;
+
+ itemDialog = gtk_dialog_new_with_buttons (_("What item?"),
+ GTK_WINDOW (g2_get_main_window
+ ()),
+ GTK_DIALOG_MODAL |
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, NULL);
+ gtk_dialog_set_has_separator (GTK_DIALOG (itemDialog), FALSE);
+
+ gtk_dialog_add_button (GTK_DIALOG (itemDialog), _("Details"), '?');
+ gtk_dialog_add_button (GTK_DIALOG (itemDialog), _("All Items"), '*');
+
+ /* -- add a label */
+ questionLabel = gtk_label_new (question);
+ gtk_label_set_line_wrap (GTK_LABEL (questionLabel), TRUE);
+ gtk_label_set_selectable (GTK_LABEL (questionLabel), TRUE);
+ gtk_misc_set_alignment (GTK_MISC (questionLabel), 0.0, 0.0);
+
+
+ /* - start parsing the choice string */
+
+ /* - first count the item */
+ itemCount = 0;
+ for (pos = choice; *pos; pos++) {
+ if (*pos == '-' && itemCount == 0) { /* hands */
+ itemCount++;
+
+ } else if (*pos == '-' && isAlpha (lastChar) && isAlpha (*(pos + 1))) {
+ gchar c;
+
+ for (c = lastChar + 1; c < *(pos + 1); c++) {
+ itemCount++;
+ }
+ lastChar = c;
+
+ } else if (isAlpha (*pos)) {
+ itemCount++;
+ lastChar = *pos;
+
+ } else if (*pos == '$') {
+ itemCount++;
+ lastChar = *pos;
+
+ } else if (strstr (pos, " or ?*") == pos || *pos == ']') {
+ break;
+
+ } else {
+ lastChar = *pos;
+ }
+ }
+
+ if (itemCount <= 0)
+ itemCount = 1; /* prevent division by zero with parsing errors */
+
+ /* - figure out a width for our table */
+ if (itemCount < 5) {
+ itemWidth = itemCount;
+ } else if (itemCount < 20) {
+ itemWidth = 5;
+ } else {
+ itemWidth = 8;
+ }
+ table = gtk_table_new (itemWidth, itemCount / itemWidth, FALSE);
+ gtk_table_set_col_spacings (GTK_TABLE (table), 5);
+ gtk_table_set_row_spacings (GTK_TABLE (table), 5);
+
+ /* - now add them to our table */
+ itemNum = 0;
+ for (pos = choice; *pos; pos++) {
+ if (*pos == '-' && itemNum == 0) { /* hands */
+ table_attach_simple (GTK_TABLE (table),
+ newItemButton ('-',
+ LEATHER_GLOVES + GLYPH_OBJ_OFF),
+ itemNum % itemWidth, itemNum / itemWidth);
+ itemNum++;
+
+ } else if (*pos == '-' && isAlpha (lastChar) && isAlpha (*(pos + 1))) {
+ gchar c;
+
+ for (c = lastChar + 1; c < *(pos + 1); c++) {
+ table_attach_simple (GTK_TABLE (table),
+ newItemButton (c,
+ obj_to_glyph (getObject
+ (c))), itemNum % itemWidth, itemNum / itemWidth);
+ itemNum++;
+ }
+ lastChar = c;
+
+ } else if (isAlpha (*pos)) {
+
+ table_attach_simple (GTK_TABLE (table),
+ newItemButton (*pos,
+ obj_to_glyph (getObject
+ (*pos))), itemNum % itemWidth, itemNum / itemWidth);
+ itemNum++;
+ lastChar = *pos;
+
+ } else if (*pos == '$') {
+ table_attach_simple (GTK_TABLE (table),
+ newItemButton ('$',
+ GOLD_PIECE + GLYPH_OBJ_OFF),
+ itemNum % itemWidth, itemNum / itemWidth);
+ itemNum++;
+ lastChar = *pos;
+
+ } else if (strstr (pos, " or ?*") == pos || *pos == ']') {
+ break;
+
+ } else {
+ lastChar = *pos;
+ }
+ }
+
+
+
+ /* -- and now pack everything together */
+ vbox = gtk_vbox_new (FALSE, 12);
+ gtk_container_set_border_width (GTK_CONTAINER (vbox), 12);
+
+ gtk_box_pack_start (GTK_BOX (vbox), questionLabel, FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (vbox), table, TRUE, TRUE, 0);
+
+
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (itemDialog)->vbox), vbox, FALSE,
+ FALSE, 0);
+
+ g_signal_connect (G_OBJECT (itemDialog), "key_press_event",
+ G_CALLBACK (g2_dialog_key_press_event), itemDialog);
+
+ gtk_widget_show_all (itemDialog);
+ response = gtk_dialog_run (GTK_DIALOG (itemDialog));
+
+ if (response > 0) {
+ res = response;
+
+ } else {
+ res = 0;
+ }
+ gtk_widget_destroy (itemDialog);
+
+ return res;
+}
+
+
+gchar
+gtk2_yn_edit_dialog (const gchar * question, const gchar * choices, CHAR_P def)
+{
+ GtkWidget *inputDialog;
+ GtkWidget *spacerVbox;
+ GtkWidget *label;
+ GtkWidget *inputEntry;
+ gint response;
+ gchar res;
+
+ inputDialog = gtk_dialog_new_with_buttons ("Gtk2Hack - Question",
+ GTK_WINDOW (g2_get_main_window
+ ()),
+ GTK_DIALOG_MODAL,
+ GTK_STOCK_CANCEL,
+ GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
+ spacerVbox = gtk_vbox_new (FALSE, 6);
+ gtk_container_set_border_width (GTK_CONTAINER (spacerVbox), 5);
+
+ label = gtk_label_new (question);
+ gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+ gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+ gtk_box_pack_start (GTK_BOX (spacerVbox), label, TRUE, FALSE, 5);
+
+ if (choices) {
+ label = gtk_label_new (choices);
+ gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+ gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+ gtk_box_pack_start (GTK_BOX (spacerVbox), label, TRUE, FALSE, 5);
+ }
+
+ inputEntry = gtk_entry_new ();
+ gtk_entry_set_max_length (GTK_ENTRY (inputEntry), 1);
+ if (def >= 'a') {
+ char scratch[3];
+
+ scratch[0] = def;
+ scratch[1] = '\0';
+ gtk_entry_set_text (GTK_ENTRY (inputEntry), scratch);
+ }
+ gtk_entry_set_activates_default (GTK_ENTRY (inputEntry), TRUE);
+ gtk_box_pack_start (GTK_BOX (spacerVbox), inputEntry, TRUE, FALSE, 5);
+
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (inputDialog)->vbox), spacerVbox,
+ TRUE, TRUE, 0);
+ gtk_dialog_set_default_response (GTK_DIALOG (inputDialog), GTK_RESPONSE_OK);
+
+ /* We have a text entry, so the key press event should be left for the entry
+ g_signal_connect(G_OBJECT(inputDialog), "key_press_event",
+ G_CALLBACK(g2_dialog_key_press_event), inputDialog);
+ */
+
+ gtk_widget_show_all (inputDialog);
+ response = gtk_dialog_run (GTK_DIALOG (inputDialog));
+
+ if (response == GTK_RESPONSE_OK) {
+ res = gtk_entry_get_text (GTK_ENTRY (inputEntry))[0];
+
+ } else if (response > 0) {
+ res = response;
+
+ } else if (choices != NULL && g_strrstr (choices, "q") != NULL) {
+ res = 'q';
+
+ } else {
+ res = 0;
+ }
+ gtk_widget_destroy (inputDialog);
+
+ return res;
+}
+
+
+gchar
+gtk2_yn_function (const gchar * question, const gchar * choices, CHAR_P def)
+{
+
+ if (skip_question) {
+ int key;
+
+ skip_question = FALSE;
+ key = GPOINTER_TO_INT (keyBuffer->data);
+ keyBuffer = g_slist_delete_link (keyBuffer, keyBuffer);
+ return key;
+ }
+
+ /* a direction question? */
+ if (choices == NULL && strstr (question, "direction")) {
+#ifdef MINIPAD
+ int x, y, mod;
+ g_signal_emit_by_name (G_OBJECT (WIN_MESSAGE), "putstr", 0, question, NULL);
+ return gtk2_nh_poskey (&x, &y, &mod);
+#else
+ return gtk2_yn_direction_dialog ();
+#endif
+ /* a item question? */
+ } else if (choices == NULL && strstr (question, "or ?*]")) {
+ return gtk2_yn_item_dialog (question, strstr (question, "["));
+ /* Or a simple choice? */
+ } else if (choices != NULL &&
+ (strcmp (choices, "yn") == 0 ||
+ strcmp (choices, "ynq") == 0 ||
+ strcmp (choices, "ynaq") == 0 || strcmp (choices, "rl") == 0)) {
+ return gtk2_yn_dialog (question, choices, def);
+
+ } else {
+ return gtk2_yn_edit_dialog (question, choices, def);
+ }
+}
+
+void
+gtk2_getlin (const char *question, char *input)
+{
+ GtkWidget *inputDialog;
+ GtkWidget *spacerVbox;
+ GtkWidget *questionLabel;
+ GtkWidget *inputEntry;
+ gint response;
+
+ inputDialog = gtk_dialog_new_with_buttons (_("Gtk2Hack - Question"),
+ GTK_WINDOW (g2_get_main_window
+ ()),
+ GTK_DIALOG_MODAL,
+ GTK_STOCK_CANCEL,
+ GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
+ spacerVbox = gtk_vbox_new (FALSE, 6);
+ gtk_container_set_border_width (GTK_CONTAINER (spacerVbox), 5);
+ questionLabel = gtk_label_new (question);
+ gtk_misc_set_alignment (GTK_MISC (questionLabel), 0.0, 0.5);
+ inputEntry = gtk_entry_new ();
+ gtk_entry_set_max_length (GTK_ENTRY (inputEntry), BUFSIZ);
+ gtk_entry_set_activates_default (GTK_ENTRY (inputEntry), TRUE);
+ gtk_box_pack_start (GTK_BOX (spacerVbox), questionLabel, TRUE, FALSE, 5);
+ gtk_box_pack_start (GTK_BOX (spacerVbox), inputEntry, TRUE, FALSE, 5);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (inputDialog)->vbox), spacerVbox,
+ TRUE, TRUE, 0);
+ gtk_dialog_set_default_response (GTK_DIALOG (inputDialog), GTK_RESPONSE_OK);
+ gtk_widget_show_all (inputDialog);
+ response = gtk_dialog_run (GTK_DIALOG (inputDialog));
+ if (response == GTK_RESPONSE_OK) {
+ g_strlcpy (input, gtk_entry_get_text (GTK_ENTRY (inputEntry)), BUFSIZ);
+ } else {
+ g_strlcpy (input, "\033\000", 2);
+ }
+ gtk_widget_destroy (inputDialog);
+}
+
+static gint
+g2_get_command_index (gchar * cmd)
+{
+ gint possibleCommands = 0;
+ gint commandIndex = -1;
+ gint i = 0;
+
+ for (i = 0; extcmdlist[i].ef_txt; i++) {
+ if (g_str_has_prefix (extcmdlist[i].ef_txt, cmd)) {
+ commandIndex = i;
+ possibleCommands++;
+ }
+ }
+ if (possibleCommands == 1) {
+ return commandIndex;
+ } else {
+ return -1;
+ }
+}
+
+static gint
+g2_complete_ext_cmd (gchar * commandBuffer)
+{
+ gint commandIndex;
+
+ g_print ("complete_ext_cmd\n");
+
+ commandIndex = g2_get_command_index (commandBuffer);
+ if (commandIndex == -1) {
+ g_signal_emit_by_name (G_OBJECT (WIN_MESSAGE), "show_ext_command",
+ commandBuffer, NULL);
+ } else {
+ g_signal_emit_by_name (G_OBJECT (WIN_MESSAGE), "show_ext_command",
+ extcmdlist[commandIndex].ef_txt, NULL);
+ }
+ return commandIndex;
+}
+
+int
+gtk2_get_ext_cmd (void)
+{
+ gint key;
+ gchar commandBuffer[10];
+ gint bufferIndex = 0;
+ gint commandIndex = -1;
+
+ g_print ("get_ext_cmd\n");
+ g_signal_emit_by_name (G_OBJECT (WIN_MESSAGE), "show_ext_command", "", NULL);
+ do {
+ while (keyBuffer == NULL) {
+ gtk_main_iteration ();
+ }
+ key = GPOINTER_TO_INT (keyBuffer->data);
+ keyBuffer = g_slist_delete_link (keyBuffer, keyBuffer);
+ if (key == GDK_Escape) {
+ commandIndex = -1;
+ } else if (bufferIndex > 0 && key == GDK_BackSpace) {
+ bufferIndex--;
+ commandBuffer[bufferIndex] = '\0';
+ commandIndex = g2_complete_ext_cmd (commandBuffer);
+ } else if (bufferIndex < 9 && g_ascii_isalnum ((guchar) key)) {
+ commandBuffer[bufferIndex] = (gchar) key;
+ commandBuffer[bufferIndex + 1] = '\0';
+ bufferIndex++;
+ commandIndex = g2_complete_ext_cmd (commandBuffer);
+ }
+ } while (key != GDK_Return && key != GDK_KP_Enter && key != GDK_Escape);
+ g_signal_emit_by_name (G_OBJECT (WIN_MESSAGE), "putstr", 0, "", NULL);
+
+ return commandIndex;
+}
+
+void
+gtk2_number_pad (int state)
+{
+ /* XXX: do we have to do to something? */
+ g_print ("gtk2_number_pad: currently unimplemented\n");
+}
+
+static gint
+timeout (gpointer data)
+{
+ delayDone = TRUE;
+ return FALSE;
+}
+
+void
+gtk2_delay_output (void)
+{
+ delayDone = FALSE;
+ g_timeout_add (G2_OUTPUT_DELAY, timeout, NULL);
+ while (delayDone == FALSE) {
+ gtk_main_iteration ();
+ }
+}
+
+void
+gtk2_start_screen (void)
+{
+ /* XXX: do we have to do to something? */
+}
+
+void
+gtk2_end_screen (void)
+{
+ /* XXX: do we have to do to something? */
+}
+
+void
+gtk2_outrip (winid wid, int how)
+{
+ g_signal_emit_by_name (G_OBJECT (wid), "outrip", how, NULL);
+ g_print ("gtk2_outrip: weakly implemented\n");
+}
+
+void
+gtk2_delete_nhwindow_by_reference (GtkWidget * menuWin)
+{
+ g_print ("gtk2_delete_nhwindow_by_reference: currently unimplemented\n");
+}