#include "event.h"
#include "magic.h"
#include "glk.h"
+#include "window.h"
+#include "input.h"
#include <string.h>
#include "chimara-glk.h"
g_mutex_unlock(priv->event_lock);
}
+/* Helper function: Wait for an event in the event queue. If it is a forced
+ * input event, but no windows have an input request of that type, then wait
+ * for the next event and put the forced input event back on top of the queue.
+ */
+static void
+get_appropriate_event(event_t *event)
+{
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+
+ g_mutex_lock(glk_data->event_lock);
+
+ event_t *retrieved_event = NULL;
+
+ /* Wait for an event */
+ if( g_queue_is_empty(glk_data->event_queue) )
+ g_cond_wait(glk_data->event_queue_not_empty, glk_data->event_lock);
+
+ retrieved_event = g_queue_pop_tail(glk_data->event_queue);
+
+ /* Signal that the event queue is no longer full */
+ g_cond_signal(glk_data->event_queue_not_full);
+
+ g_mutex_unlock(glk_data->event_lock);
+
+ if(retrieved_event->type == evtype_ForcedCharInput)
+ {
+ /* Check for forced character input in the queue */
+ winid_t win;
+ for(win = glk_window_iterate(NULL, NULL); win; win = glk_window_iterate(win, NULL))
+ if(win->input_request_type == INPUT_REQUEST_CHARACTER || win->input_request_type == INPUT_REQUEST_CHARACTER_UNICODE)
+ break;
+ if(win)
+ {
+ force_char_input_from_queue(win, event);
+ g_free(retrieved_event);
+ }
+ else
+ {
+ get_appropriate_event(event);
+ g_mutex_lock(glk_data->event_lock);
+ g_queue_push_tail(glk_data->event_queue, retrieved_event);
+ g_cond_signal(glk_data->event_queue_not_empty);
+ g_mutex_unlock(glk_data->event_lock);
+ }
+ }
+ else if(retrieved_event->type == evtype_ForcedLineInput)
+ {
+ /* Check for forced line input in the queue */
+ winid_t win;
+ for(win = glk_window_iterate(NULL, NULL); win; win = glk_window_iterate(win, NULL))
+ if(win->input_request_type == INPUT_REQUEST_LINE || win->input_request_type == INPUT_REQUEST_LINE_UNICODE)
+ break;
+ if(win)
+ {
+ force_line_input_from_queue(win, event);
+ g_free(retrieved_event);
+ }
+ else
+ {
+ get_appropriate_event(event);
+ g_mutex_lock(glk_data->event_lock);
+ g_queue_push_tail(glk_data->event_queue, retrieved_event);
+ g_cond_signal(glk_data->event_queue_not_empty);
+ g_mutex_unlock(glk_data->event_lock);
+ }
+ }
+ else
+ {
+ if(retrieved_event == NULL)
+ {
+ WARNING("Retrieved NULL event from non-empty event queue");
+ return;
+ }
+ memcpy(event, retrieved_event, sizeof(event_t));
+ g_free(retrieved_event);
+ }
+}
+
/**
* glk_select:
* @event: Pointer to an #event_t.
{
g_return_if_fail(event != NULL);
- ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
-
- g_mutex_lock(glk_data->event_lock);
-
- /* Wait for an event */
- while( g_queue_is_empty(glk_data->event_queue) )
- g_cond_wait(glk_data->event_queue_not_empty, glk_data->event_lock);
-
- event_t *retrieved_event = g_queue_pop_tail(glk_data->event_queue);
- if(retrieved_event == NULL)
- {
- g_mutex_unlock(glk_data->event_lock);
- WARNING("Retrieved NULL event from non-empty event queue");
- return;
+ /* Flush all window buffers */
+ winid_t win;
+ for(win = glk_window_iterate(NULL, NULL); win != NULL; win = glk_window_iterate(win, NULL)) {
+ if(win->type == wintype_TextBuffer || win->type == wintype_TextGrid)
+ flush_window_buffer(win);
}
- memcpy(event, retrieved_event, sizeof(event_t));
- g_free(retrieved_event);
- /* Signal that the event queue is no longer full */
- g_cond_signal(glk_data->event_queue_not_full);
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+
+ get_appropriate_event(event);
- g_mutex_unlock(glk_data->event_lock);
-
/* Check for interrupt */
glk_tick();
+
+ /* If the event was a line input event, the library must release the buffer */
+ if(event->type == evtype_LineInput && glk_data->unregister_arr)
+ {
+ if(event->win->input_request_type == INPUT_REQUEST_LINE_UNICODE)
+ (*glk_data->unregister_arr)(event->win->line_input_buffer_unicode, event->win->line_input_buffer_max_len, "&+#!Iu", event->win->buffer_rock);
+ else
+ (*glk_data->unregister_arr)(event->win->line_input_buffer, event->win->line_input_buffer_max_len, "&+#!Cn", event->win->buffer_rock);
+ }
/* If an abort event was generated, the thread should have exited by now */
g_assert(event->type != evtype_Abort);
* intended for you to test conditions which may have occurred while you are
* computing, and not interfacing with the player. For example, time may pass
* during slow computations; you can use glk_select_poll() to see if a
- * %evtype_Timer event has occured. (See <link
+ * %evtype_Timer event has occurred. (See <link
* linkend="chimara-Timer-Events">Timer Events</link>.)
*
* At the moment, glk_select_poll() checks for %evtype_Timer, %evtype_Arrange,
/* If an abort event was generated, the thread should have exited by now */
g_assert(event->type != evtype_Abort);
-}
\ No newline at end of file
+}