fixes entry
[aNetHack.git] / win / gnome / gnsignal.c
blobd9accadc310e6612efdf868a172e36d6e254ada9
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. */
5 #include "gnsignal.h"
6 #include "gnmain.h"
7 #include <gdk/gdkkeysyms.h>
9 GList *g_keyBuffer;
10 GList *g_clickBuffer;
11 int g_numKeys = 0;
12 int g_numClicks = 0;
13 int g_askingQuestion = 0;
14 static int s_done = FALSE;
17 * ghack_init_signals
19 * Create some signals and attach them to the GtkWidget class.
20 * These are the signals:
22 * ghack_curs : NONE:INT,INT
23 * INT 1 = x
24 * INT 2 = y
26 * ghack_putstr : NONE:INT,POINTER
27 * INT = attribute
28 * POINTER = char* string to print
30 * ghack_print_glyph : NONE:INT,INT,POINTER
31 * INT 1 = x
32 * INT 2 = y
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
55 * INT 1 = x
56 * INT 2 = y
59 void
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,
65 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,
70 GTK_TYPE_POINTER);
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,
92 GTK_TYPE_POINTER);
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,
97 GTK_TYPE_POINTER);
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
119 * -Erik
121 static gint
122 timeout_callback(gpointer data)
124 s_done = TRUE;
125 return FALSE;
128 void
129 ghack_delay(GtkWidget *win, int numMillisecs, gpointer data)
131 s_done = FALSE;
132 gtk_timeout_add((unsigned int) numMillisecs, timeout_callback, NULL);
133 while (s_done == FALSE)
134 gtk_main_iteration();
137 void
138 ghack_handle_button_press(GtkWidget *widget, GdkEventButton *event,
139 gpointer data)
141 GHClick *click;
142 double x1, y1;
144 if (event->type != GDK_BUTTON_PRESS)
145 return;
147 gnome_canvas_window_to_world(GNOME_CANVAS(widget), event->x, event->y,
148 &x1, &y1);
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. */
174 g_numClicks++;
177 #ifndef M
178 #ifndef NHSTDC
179 #define M(c) (0x80 | (c))
180 #else
181 #define M(c) ((c) -128)
182 #endif /* NHSTDC */
183 #endif
184 #ifndef C
185 #define C(c) (0x1f & (c))
186 #endif
188 void
189 ghack_handle_key_press(GtkWidget *widget, GdkEventKey *event, gpointer data)
191 static int was_pound = 0;
192 int key = 0;
193 int ctl = GDK_CONTROL_MASK;
194 int alt = GDK_MOD1_MASK;
196 /* Turn this on to debug key events */
197 #if 0
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":"");
201 #endif
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 */
209 case GDK_Right:
210 case GDK_rightarrow:
211 key = Cmd.move_E;
212 break;
213 case GDK_Left:
214 case GDK_leftarrow:
215 key = Cmd.move_W;
216 break;
217 case GDK_Up:
218 case GDK_uparrow:
219 key = Cmd.move_N;
220 break;
221 case GDK_Down:
222 case GDK_downarrow:
223 key = Cmd.move_S;
224 break;
225 case GDK_Home:
226 key = Cmd.move_NW;
227 break;
228 case GDK_End:
229 key = Cmd.move_SW;
230 break;
231 case GDK_Page_Down:
232 key = Cmd.move_SE;
233 break;
234 case GDK_Page_Up:
235 key = Cmd.move_NE;
236 break;
237 case ' ':
238 key = '.';
239 break;
241 /* Now, handle the numberpad (move or numbers) */
242 case GDK_KP_Right:
243 case GDK_KP_6:
244 if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)
245 && iflags.num_pad)
246 key = GDK_KP_6;
247 else
248 key = '6';
249 break;
251 case GDK_KP_Left:
252 case GDK_KP_4:
253 if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)
254 && iflags.num_pad)
255 key = GDK_KP_4;
256 else
257 key = '4';
258 break;
260 case GDK_KP_Up:
261 case GDK_KP_8:
262 if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)
263 && iflags.num_pad)
264 key = GDK_KP_8;
265 else
266 key = '8';
267 break;
269 case GDK_KP_Down:
270 case GDK_KP_2:
271 if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)
272 && iflags.num_pad)
273 key = GDK_KP_2;
274 else
275 key = '2';
276 break;
278 /* Move Top-Left */
279 case GDK_KP_Home:
280 case GDK_KP_7:
281 if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)
282 && iflags.num_pad)
283 key = GDK_KP_7;
284 else
285 key = '7';
286 break;
288 case GDK_KP_Page_Up:
289 case GDK_KP_9:
290 if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)
291 && iflags.num_pad)
292 key = GDK_KP_9;
293 else
294 key = '9';
295 break;
297 case GDK_KP_End:
298 case GDK_KP_1:
299 if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)
300 && iflags.num_pad)
301 key = GDK_KP_1;
302 else
303 key = '1';
304 break;
306 case GDK_KP_Page_Down:
307 case GDK_KP_3:
308 if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)
309 && iflags.num_pad)
310 key = GDK_KP_3;
311 else
312 key = '3';
313 break;
315 case GDK_KP_5:
316 if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)
317 && iflags.num_pad)
318 key = GDK_KP_5;
319 else
320 key = '5';
321 break;
323 case GDK_KP_Delete:
324 case GDK_KP_Decimal:
325 key = '.';
326 break;
328 /* can't just ignore "#", it's a core feature */
329 case GDK_numbersign:
330 key = '#';
331 break;
333 /* We will probably want to do something with these later... */
334 case GDK_KP_Begin:
335 case GDK_KP_F1:
336 case GDK_F1:
337 case GDK_KP_F2:
338 case GDK_F2:
339 case GDK_KP_F3:
340 case GDK_F3:
341 case GDK_KP_F4:
342 case GDK_F4:
343 case GDK_F5:
344 case GDK_F6:
345 case GDK_F7:
346 case GDK_F8:
347 case GDK_F9:
348 case GDK_F10:
349 case GDK_F11:
350 case GDK_F12:
351 break;
352 /* various keys to ignore */
353 case GDK_KP_Insert:
354 case GDK_Insert:
355 case GDK_Delete:
356 case GDK_Print:
357 case GDK_BackSpace:
358 case GDK_Pause:
359 case GDK_Scroll_Lock:
360 case GDK_Shift_Lock:
361 case GDK_Num_Lock:
362 case GDK_Caps_Lock:
363 case GDK_Control_L:
364 case GDK_Control_R:
365 case GDK_Shift_L:
366 case GDK_Shift_R:
367 case GDK_Alt_L:
368 case GDK_Alt_R:
369 case GDK_Meta_L:
370 case GDK_Meta_R:
371 case GDK_Mode_switch:
372 case GDK_Multi_key:
373 return;
375 default:
376 key = event->keyval;
377 break;
380 if ((event->state & alt) || was_pound) {
381 key = M(event->keyval);
382 } else if (event->state & ctl) {
383 key = C(event->keyval);
385 if (was_pound) {
386 was_pound = 0;
389 /* Ok, here is where we do clever stuff to overide the default
390 * game behavior */
391 if (g_askingQuestion == 0) {
392 if (key == 'S' || key == M('S') || key == C('S')) {
393 ghack_save_game_cb(NULL, NULL);
394 return;
397 g_keyBuffer = g_list_prepend(g_keyBuffer, GINT_TO_POINTER(key));
398 g_numKeys++;