1 /* SCCS Id: @(#)gnsignal.c 3.4 2000/07/16 */
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] =
63 gtk_object_class_user_signal_new (gtk_type_class (gtk_widget_get_type ()),
66 gtk_marshal_NONE__INT_INT,
72 ghack_signals[GHSIG_PUTSTR] =
73 gtk_object_class_user_signal_new (gtk_type_class (gtk_widget_get_type ()),
76 gtk_marshal_NONE__INT_POINTER,
82 ghack_signals[GHSIG_PRINT_GLYPH] =
83 gtk_object_class_user_signal_new (gtk_type_class (gtk_widget_get_type ()),
86 gtk_marshal_NONE__INT_INT_POINTER,
93 ghack_signals[GHSIG_CLEAR] =
94 gtk_object_class_user_signal_new (gtk_type_class (gtk_widget_get_type ()),
97 gtk_marshal_NONE__NONE,
101 ghack_signals[GHSIG_DISPLAY] =
102 gtk_object_class_user_signal_new (gtk_type_class (gtk_widget_get_type ()),
105 gtk_marshal_NONE__BOOL,
110 ghack_signals[GHSIG_START_MENU] =
111 gtk_object_class_user_signal_new (gtk_type_class (gtk_widget_get_type ()),
114 gtk_marshal_NONE__NONE,
118 ghack_signals[GHSIG_ADD_MENU] =
119 gtk_object_class_user_signal_new (gtk_type_class (gtk_widget_get_type ()),
122 gtk_marshal_NONE__POINTER,
127 ghack_signals[GHSIG_END_MENU] =
128 gtk_object_class_user_signal_new (gtk_type_class (gtk_widget_get_type ()),
131 gtk_marshal_NONE__POINTER,
136 ghack_signals[GHSIG_SELECT_MENU] =
137 gtk_object_class_user_signal_new (gtk_type_class (gtk_widget_get_type ()),
140 gtk_marshal_NONE__POINTER_INT_POINTER,
147 ghack_signals[GHSIG_CLIPAROUND] =
148 gtk_object_class_user_signal_new (gtk_type_class (gtk_widget_get_type ()),
151 gtk_marshal_NONE__INT_INT,
157 ghack_signals[GHSIG_FADE_HIGHLIGHT] =
158 gtk_object_class_user_signal_new (gtk_type_class (gtk_widget_get_type ()),
159 "ghack_fade_highlight",
161 gtk_marshal_NONE__NONE,
165 ghack_signals[GHSIG_DELAY] =
166 gtk_object_class_user_signal_new (gtk_type_class (gtk_widget_get_type ()),
167 "gnome_delay_output",
169 gtk_marshal_NONE__INT,
176 /* For want of a better place, I'm putting the delay output stuff here
179 static gint timeout_callback(gpointer data)
186 ghack_delay( GtkWidget *win, int numMillisecs, gpointer data)
189 gtk_timeout_add( (unsigned int) numMillisecs,
190 timeout_callback, NULL);
191 while( s_done==FALSE)
192 gtk_main_iteration();
197 ghack_handle_button_press(GtkWidget *widget, GdkEventButton *event,
203 if (event->type != GDK_BUTTON_PRESS)
206 gnome_canvas_window_to_world( GNOME_CANVAS( widget), event->x,
209 g_message("I got a click at %f,%f with button %d \n",
210 x1, y1, event->button);
213 /* We allocate storage here, so we need to remember if (g_numClicks>0)
214 * to blow this away when closing the app using something like
215 * while (g_clickBuffer)
217 * g_free((GHClick)g_clickBuffer->data);
218 * g_clickBuffer = g_clickBuffer->next;
220 * g_list_free( g_clickBuffer );
223 click = g_new( GHClick, 1);
225 click->x=(int)x1/ghack_glyph_width();
226 click->y=(int)y1/ghack_glyph_height();
227 click->mod=(event->button == 1)? CLICK_1 : CLICK_2;
229 g_clickBuffer = g_list_prepend (g_clickBuffer, click);
230 /* Could use g_list_length(), but it is stupid and just
231 * traverses the list while counting, so we'll just do
232 * the counting ourselves in advance. */
238 # define M(c) (0x80 | (c))
240 # define M(c) ((c) - 128)
244 #define C(c) (0x1f & (c))
249 ghack_handle_key_press(GtkWidget *widget, GdkEventKey *event, gpointer data)
251 static int was_pound = 0;
253 int ctl = GDK_CONTROL_MASK;
254 int alt = GDK_MOD1_MASK;
256 /* Turn this on to debug key events */
258 g_message("I got a \"%s\" key (%d) %s%s",
259 gdk_keyval_name (event->keyval), event->keyval,
260 (event->state&ctl)? "+CONTROL":"", (event->state&alt)? "+ALT":"");
263 switch (event->keyval) {
264 /* special keys to do stuff with */
266 /* Set up the direction keys */
268 /* First handle the arrow keys -- these always mean move */
271 if (iflags.num_pad) key='6'; else key='l'; break;
274 if (iflags.num_pad) key='4'; else key='h'; break;
277 if (iflags.num_pad) key='8'; else key='k'; break;
280 if (iflags.num_pad) key='2'; else key='j'; break;
282 if (iflags.num_pad) key='7'; else key='y'; break;
284 if (iflags.num_pad) key='1'; else key='b'; break;
286 if (iflags.num_pad) key='3'; else key='n'; break;
288 if (iflags.num_pad) key='9'; else key='u'; break;
289 case ' ': key='.'; break;
291 /* Now, handle the numberpad (move or numbers) */
294 if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK) && iflags.num_pad)
302 if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK) && iflags.num_pad)
310 if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK) && iflags.num_pad)
318 if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK) && iflags.num_pad)
327 if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK) && iflags.num_pad)
335 if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK) && iflags.num_pad)
343 if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK) && iflags.num_pad)
349 case GDK_KP_Page_Down:
351 if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK) && iflags.num_pad)
359 if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK) && iflags.num_pad)
370 /* can't just ignore "#", it's a core feature */
375 /* We will probably want to do something with these later... */
394 /* various keys to ignore */
401 case GDK_Scroll_Lock:
413 case GDK_Mode_switch:
422 if ((event->state & alt) || was_pound) {
423 key=M(event->keyval);
424 } else if (event->state & ctl) {
425 key=C(event->keyval);
431 /* Ok, here is where we do clever stuff to overide the default
433 if (g_askingQuestion == 0) {
435 if (key == 'S' || key == M('S') || key == C('S')) {
436 ghack_save_game_cb( NULL, NULL);
440 g_keyBuffer = g_list_prepend (g_keyBuffer, GINT_TO_POINTER( key));