1 /* NetHack 3.6 gnsignal.c $NHDT-Date: 1432512805 2015/05/25 00:13:25 $ $NHDT-Branch: master $:$NHDT-Revision: 1.11 $ */
2 /* Copyright (C) 1998 by Anthony Taylor <tonyt@ptialaska.net> */
3 /* NetHack may be freely redistributed. See license for details. */
7 #include <gdk/gdkkeysyms.h>
13 int g_askingQuestion = 0;
14 static int s_done = FALSE;
19 * Create some signals and attach them to the GtkWidget class.
20 * These are the signals:
22 * ghack_curs : NONE:INT,INT
26 * ghack_putstr : NONE:INT,POINTER
28 * POINTER = char* string to print
30 * ghack_print_glyph : NONE:INT,INT,POINTER
33 * INT 3 = GtkPixmap* to rendered glyph
35 * ghack_clear : NONE:NONE
37 * ghack_display : NONE:BOOL
38 * BOOL = blocking flag
40 * ghack_start_menu : NONE:NONE
42 * ghack_add_menu : NONE:POINTER
43 * POINTER = GHackMenuItem*
45 * ghack_end_menu : NONE:POINTER
46 * POINTER = char* to closing string
48 * ghack_select_menu : NONE:POINTER,INT,POINTER
49 * POINTER = int pointer-- filled with number
50 * of selected items on return
51 * INT = number of items selected
52 * POINTER = structure to fill
54 * ghack_cliparound : NONE:INT,INT
60 ghack_init_signals(void)
62 ghack_signals[GHSIG_CURS] = gtk_object_class_user_signal_new(
63 gtk_type_class(gtk_widget_get_type()), "ghack_curs", GTK_RUN_FIRST,
64 gtk_marshal_NONE__INT_INT, GTK_TYPE_NONE, 2, GTK_TYPE_INT,
67 ghack_signals[GHSIG_PUTSTR] = gtk_object_class_user_signal_new(
68 gtk_type_class(gtk_widget_get_type()), "ghack_putstr", GTK_RUN_FIRST,
69 gtk_marshal_NONE__INT_POINTER, GTK_TYPE_NONE, 2, GTK_TYPE_INT,
72 ghack_signals[GHSIG_PRINT_GLYPH] = gtk_object_class_user_signal_new(
73 gtk_type_class(gtk_widget_get_type()), "ghack_print_glyph",
74 GTK_RUN_FIRST, gtk_marshal_NONE__INT_INT_POINTER, GTK_TYPE_NONE, 3,
75 GTK_TYPE_INT, GTK_TYPE_INT, GTK_TYPE_POINTER);
77 ghack_signals[GHSIG_CLEAR] = gtk_object_class_user_signal_new(
78 gtk_type_class(gtk_widget_get_type()), "ghack_clear", GTK_RUN_FIRST,
79 gtk_marshal_NONE__NONE, GTK_TYPE_NONE, 0);
81 ghack_signals[GHSIG_DISPLAY] = gtk_object_class_user_signal_new(
82 gtk_type_class(gtk_widget_get_type()), "ghack_display", GTK_RUN_FIRST,
83 gtk_marshal_NONE__BOOL, GTK_TYPE_NONE, 1, GTK_TYPE_BOOL);
85 ghack_signals[GHSIG_START_MENU] = gtk_object_class_user_signal_new(
86 gtk_type_class(gtk_widget_get_type()), "ghack_start_menu",
87 GTK_RUN_FIRST, gtk_marshal_NONE__NONE, GTK_TYPE_NONE, 0);
89 ghack_signals[GHSIG_ADD_MENU] = gtk_object_class_user_signal_new(
90 gtk_type_class(gtk_widget_get_type()), "ghack_add_menu",
91 GTK_RUN_FIRST, gtk_marshal_NONE__POINTER, GTK_TYPE_NONE, 1,
94 ghack_signals[GHSIG_END_MENU] = gtk_object_class_user_signal_new(
95 gtk_type_class(gtk_widget_get_type()), "ghack_end_menu",
96 GTK_RUN_FIRST, gtk_marshal_NONE__POINTER, GTK_TYPE_NONE, 1,
99 ghack_signals[GHSIG_SELECT_MENU] = gtk_object_class_user_signal_new(
100 gtk_type_class(gtk_widget_get_type()), "ghack_select_menu",
101 GTK_RUN_FIRST, gtk_marshal_NONE__POINTER_INT_POINTER, GTK_TYPE_NONE,
102 3, GTK_TYPE_POINTER, GTK_TYPE_INT, GTK_TYPE_POINTER);
104 ghack_signals[GHSIG_CLIPAROUND] = gtk_object_class_user_signal_new(
105 gtk_type_class(gtk_widget_get_type()), "ghack_cliparound",
106 GTK_RUN_FIRST, gtk_marshal_NONE__INT_INT, GTK_TYPE_NONE, 2,
107 GTK_TYPE_INT, GTK_TYPE_INT);
109 ghack_signals[GHSIG_FADE_HIGHLIGHT] = gtk_object_class_user_signal_new(
110 gtk_type_class(gtk_widget_get_type()), "ghack_fade_highlight",
111 GTK_RUN_FIRST, gtk_marshal_NONE__NONE, GTK_TYPE_NONE, 0);
113 ghack_signals[GHSIG_DELAY] = gtk_object_class_user_signal_new(
114 gtk_type_class(gtk_widget_get_type()), "gnome_delay_output",
115 GTK_RUN_FIRST, gtk_marshal_NONE__INT, GTK_TYPE_NONE, 1, GTK_TYPE_INT);
118 /* For want of a better place, I'm putting the delay output stuff here
122 timeout_callback(gpointer data)
129 ghack_delay(GtkWidget *win, int numMillisecs, gpointer data)
132 gtk_timeout_add((unsigned int) numMillisecs, timeout_callback, NULL);
133 while (s_done == FALSE)
134 gtk_main_iteration();
138 ghack_handle_button_press(GtkWidget *widget, GdkEventButton *event,
144 if (event->type != GDK_BUTTON_PRESS)
147 gnome_canvas_window_to_world(GNOME_CANVAS(widget), event->x, event->y,
150 g_message("I got a click at %f,%f with button %d \n",
151 x1, y1, event->button);
154 /* We allocate storage here, so we need to remember if (g_numClicks>0)
155 * to blow this away when closing the app using something like
156 * while (g_clickBuffer)
158 * g_free((GHClick)g_clickBuffer->data);
159 * g_clickBuffer = g_clickBuffer->next;
161 * g_list_free( g_clickBuffer );
164 click = g_new(GHClick, 1);
166 click->x = (int) x1 / ghack_glyph_width();
167 click->y = (int) y1 / ghack_glyph_height();
168 click->mod = (event->button == 1) ? CLICK_1 : CLICK_2;
170 g_clickBuffer = g_list_prepend(g_clickBuffer, click);
171 /* Could use g_list_length(), but it is stupid and just
172 * traverses the list while counting, so we'll just do
173 * the counting ourselves in advance. */
179 #define M(c) (0x80 | (c))
181 #define M(c) ((c) -128)
185 #define C(c) (0x1f & (c))
189 ghack_handle_key_press(GtkWidget *widget, GdkEventKey *event, gpointer data)
191 static int was_pound = 0;
193 int ctl = GDK_CONTROL_MASK;
194 int alt = GDK_MOD1_MASK;
196 /* Turn this on to debug key events */
198 g_message("I got a \"%s\" key (%d) %s%s",
199 gdk_keyval_name (event->keyval), event->keyval,
200 (event->state&ctl)? "+CONTROL":"", (event->state&alt)? "+ALT":"");
203 switch (event->keyval) {
204 /* special keys to do stuff with */
206 /* Set up the direction keys */
208 /* First handle the arrow keys -- these always mean move */
241 /* Now, handle the numberpad (move or numbers) */
244 if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)
253 if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)
262 if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)
271 if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)
281 if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)
290 if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)
299 if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)
306 case GDK_KP_Page_Down:
308 if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)
316 if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)
328 /* can't just ignore "#", it's a core feature */
333 /* We will probably want to do something with these later... */
352 /* various keys to ignore */
359 case GDK_Scroll_Lock:
371 case GDK_Mode_switch:
380 if ((event->state & alt) || was_pound) {
381 key = M(event->keyval);
382 } else if (event->state & ctl) {
383 key = C(event->keyval);
389 /* Ok, here is where we do clever stuff to overide the default
391 if (g_askingQuestion == 0) {
392 if (key == 'S' || key == M('S') || key == C('S')) {
393 ghack_save_game_cb(NULL, NULL);
397 g_keyBuffer = g_list_prepend(g_keyBuffer, GINT_TO_POINTER(key));