2 // nazghul - an old-school RPG engine
3 // Copyright (C) 2002, 2003 Gordon McNutt
5 // This program is free software; you can redistribute it and/or modify it
6 // under the terms of the GNU General Public License as published by the Free
7 // Software Foundation; either version 2 of the License, or (at your option)
10 // This program is distributed in the hope that it will be useful, but WITHOUT
11 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 // You should have received a copy of the GNU General Public License along with
16 // this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
17 // Suite 330, Boston, MA 02111-1307 USA
20 // gmcnutt@users.sourceforge.net
28 #include <sys/types.h>
38 #define EVENT_NONBLOCK (1 << 0)
39 #define EVENT_NOPLAYBACK (1 << 1)
41 #define getHandler(stack,type) \
42 (list_empty((stack)) ? NULL : (type*)(stack)->next)
43 #define pushHandler(stack,handler) (list_add((stack), &(handler)->list))
50 static struct list KeyHandlers;
51 static struct list TickHandlers;
52 static struct list QuitHandlers;
53 static struct list MouseButtonHandlers;
54 static struct list MouseMotionHandlers;
55 static struct list backlog;
57 static bool record_events;
59 static bool playback_events;
60 static int playback_fd;
61 static int event_playback_speed = 0;
63 static void (*eventHook) (void);
64 static int (*wait_event) (SDL_Event * event, int flags);
65 static int qcount = 0;
67 static struct list *popHandler(struct list *stack)
69 if (list_empty(stack)) {
73 struct list *lptr = stack->next;
78 static void backlog_enqueue(SDL_Event *event)
80 sdl_event_list_t *elem = (sdl_event_list_t*)malloc(sizeof(*elem));
82 list_add(&backlog, &elem->list);
86 static int backlog_dequeue(SDL_Event *event)
88 sdl_event_list_t *elem;
90 if (list_empty(&backlog))
93 elem = outcast(ptr, sdl_event_list_t, list);
94 list_remove(&elem->list);
101 static int mapKey(SDL_keysym * keysym)
103 int key = keysym->sym;
106 printf("sym='%c'[%d] mod=%02x unicode=%04x\n",
113 /* If the key has a UNICODE representation and its from the default
114 * Basic Latin code page then return it as an ASCII character. */
115 /* fixme: unicode is messing up ctrl+key sequences */
116 if (keysym->unicode) {
118 /* Map CR to LF (legacy code expects this) */
119 if (keysym->unicode == 0x000d)
122 /* Map all other Basic Latin codes to ASCII */
123 if (keysym->unicode < 0x7f)
124 return keysym->unicode & 0x7f;
126 /* Code page not supported... fall through */
129 /* Map arrow keys to equivalent numberpad entries */
130 if (key >= SDLK_UP && key <= SDLK_LEFT) {
131 static int map[] = { KEY_NORTH, KEY_SOUTH, KEY_EAST,
133 key = map[key - SDLK_UP];
136 /* Set the "shift" bit */
137 if (keysym->mod & KMOD_SHIFT) {
141 /* Unsupported? fallback to the SDL sym */
145 static int event_get_next_event(SDL_Event *event, int flags)
147 /* if a key handler exists */
148 if (getHandler(&KeyHandlers, struct KeyHandler)) {
150 /* if the backlog queue is not empty */
151 if (! backlog_dequeue(event)) {
153 /* get the event from the backlog queue */
158 if (flags & EVENT_NONBLOCK)
159 return SDL_PollEvent(event);
161 return SDL_WaitEvent(event);
164 static int playback_event(SDL_Event * event, int flags)
166 // For now use the expedient but non-portable technique of reading the
167 // binary data straight to the file.
169 int len = sizeof(SDL_Event);
170 char *ptr = (char *) event;
172 if (flags & EVENT_NOPLAYBACK)
177 n = read(playback_fd, ptr, len);
186 SDL_Delay(event_playback_speed);
191 static void record_event(SDL_Event * event)
193 // For now use the expedient but non-portable technique of writing the
194 // binary data straight to the file.
196 int len = sizeof(SDL_Event);
197 char *ptr = (char *) event;
199 n = write(record_fd, ptr, len);
209 static void event_handle_aux(int flags)
212 bool use_hook = false;
217 if (!wait_event(&event, flags)) {
221 record_event(&event);
223 switch (event.type) {
227 struct TickHandler *tickh;
228 tickh = getHandler(&TickHandlers,
232 if (tickh->fx(tickh)) {
242 struct KeyHandler *keyh;
243 keyh = getHandler(&KeyHandlers,
247 mapKey(&event.key.keysym);
249 if (keyh->fx(keyh, mapped_key,
250 event.key.keysym.mod)) {
254 /* enqueue this event */
255 backlog_enqueue(&event);
262 struct QuitHandler *quith;
264 getHandler(&QuitHandlers,
266 if (quith && quith->fx(quith))
271 case SDL_MOUSEBUTTONDOWN:
273 struct MouseButtonHandler *mouseh;
274 mouseh = getHandler(&MouseButtonHandlers,
275 struct MouseButtonHandler);
277 mouseh->fx(mouseh, &event.button)) {
283 case SDL_MOUSEMOTION:
285 struct MouseMotionHandler *mouseh;
286 mouseh = getHandler(&MouseMotionHandlers,
287 struct MouseMotionHandler);
289 mouseh->fx(mouseh, &event.motion)) {
299 if (use_hook && eventHook)
308 char *record_fname = cfg_get("record-filename");
309 char *playback_fname = cfg_get("playback-filename");
311 list_init(&KeyHandlers);
312 list_init(&TickHandlers);
313 list_init(&QuitHandlers);
314 list_init(&MouseButtonHandlers);
315 list_init(&MouseMotionHandlers);
318 wait_event = event_get_next_event;
321 if (record_fname != NULL) {
322 record_events = true;
323 record_fd = open(record_fname, O_WRONLY | O_CREAT, 00666);
324 if (record_fd == -1) {
325 perror(record_fname);
330 if (playback_fname != NULL) {
331 char *playback_spd_str = cfg_get("playback-speed");
332 playback_events = true;
333 playback_fd = open(playback_fname, O_RDONLY, 00666);
334 if (playback_fd == -1) {
335 perror(playback_fname);
338 // Override the normal wait_event routine
339 wait_event = playback_event;
341 /* Set the play back speed. */
342 if (playback_spd_str) {
343 event_playback_speed = atoi(playback_spd_str);
347 SDL_EnableUNICODE(1);
354 /* cleanup the backlog queue */
356 while (! backlog_dequeue(&event))
360 void eventHandle(void)
365 void eventHandlePending(void)
367 event_handle_aux(EVENT_NONBLOCK|EVENT_NOPLAYBACK);
370 void eventPushKeyHandler(struct KeyHandler *keyh)
372 pushHandler(&KeyHandlers, keyh);
375 struct KeyHandler * eventPopKeyHandler(void)
377 return (struct KeyHandler*)popHandler(&KeyHandlers);
380 void eventPushTickHandler(struct TickHandler *keyh)
382 pushHandler(&TickHandlers, keyh);
385 void eventPopTickHandler(void)
387 popHandler(&TickHandlers);
390 void eventPushQuitHandler(struct QuitHandler *keyh)
392 pushHandler(&QuitHandlers, keyh);
395 void eventPopQuitHandler(void)
397 popHandler(&QuitHandlers);
400 void eventPushMouseButtonHandler(struct MouseButtonHandler *keyh)
402 pushHandler(&MouseButtonHandlers, keyh);
405 void eventPopMouseButtonHandler(void)
407 popHandler(&MouseButtonHandlers);
410 void eventPushMouseMotionHandler(struct MouseMotionHandler *keyh)
412 pushHandler(&MouseMotionHandlers, keyh);
415 void eventPopMouseMotionHandler(void)
417 popHandler(&MouseMotionHandlers);
420 void eventAddHook(void (*fx) (void))
425 void eventRunKeyHandler(key_handler_fx_t fx, void *data)
427 struct KeyHandler kh;
430 eventPushKeyHandler(&kh);
432 eventPopKeyHandler();