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
));