From b8f0bfa1731a8890b172087f77cea42be342d8fc Mon Sep 17 00:00:00 2001 From: "P. F. Chimento" Date: Mon, 25 Apr 2011 21:04:18 +0200 Subject: [PATCH] Minimum implementation of line terminators The function works, but no keys are allowed as line terminators. Prints a warning when ignoring disallowed line terminators. --- libchimara/gestalt.c | 10 ++++- libchimara/input.c | 94 +++++++++++++++++++++++++++++++++++++++++++- libchimara/input.h | 1 + libchimara/window.c | 4 ++ libchimara/window.h | 2 + 5 files changed, 107 insertions(+), 4 deletions(-) diff --git a/libchimara/gestalt.c b/libchimara/gestalt.c index 22683df..6dbffa1 100644 --- a/libchimara/gestalt.c +++ b/libchimara/gestalt.c @@ -1,6 +1,7 @@ #include /* Surprisingly, the only symbol needed is NULL */ #include #include "glk.h" +#include "input.h" /* Version of the Glk specification implemented by this library */ #define MAJOR_VERSION 0 @@ -108,6 +109,10 @@ glk_gestalt_ext(glui32 sel, glui32 val, glui32 *arr, glui32 arrlen) case gestalt_DrawImage: return val == wintype_Graphics || val == wintype_TextBuffer; + /* Which keycodes can be used as line terminators */ + case gestalt_LineTerminatorKey: + return is_valid_line_terminator(val)? 1 : 0; + /* Capabilities that are simply supported */ case gestalt_Unicode: case gestalt_Timer: @@ -117,6 +122,7 @@ glk_gestalt_ext(glui32 sel, glui32 val, glui32 *arr, glui32 arrlen) case gestalt_DateTime: case gestalt_UnicodeNorm: case gestalt_LineInputEcho: + case gestalt_LineTerminators: return 1; /* Capabilities supported if compiled with GStreamer */ @@ -131,8 +137,8 @@ glk_gestalt_ext(glui32 sel, glui32 val, glui32 *arr, glui32 arrlen) #endif /* Unsupported capabilities */ - case gestalt_LineTerminatorKey: - case gestalt_LineTerminators: + /* none! */ + /* Selector not supported */ default: return 0; diff --git a/libchimara/input.c b/libchimara/input.c index 0bcfd4d..1963bfd 100644 --- a/libchimara/input.c +++ b/libchimara/input.c @@ -3,6 +3,7 @@ #include "input.h" #include "pager.h" #include "chimara-glk-private.h" +#include "garglk.h" extern GPrivate *glk_data_key; @@ -244,6 +245,7 @@ glk_request_line_event(winid_t win, char *buf, glui32 maxlen, glui32 initlen) win->line_input_buffer = buf; win->line_input_buffer_max_len = maxlen; win->echo_current_line_input = win->echo_line_input; + win->current_extra_line_terminators = g_slist_copy(win->extra_line_terminators); gchar *inserttext = (initlen > 0)? g_strndup(buf, initlen) : g_strdup(""); switch(win->type) @@ -312,11 +314,10 @@ glk_request_line_event_uni(winid_t win, glui32 *buf, glui32 maxlen, glui32 initl if(glk_data->register_arr) win->buffer_rock = (*glk_data->register_arr)(buf, maxlen, "&+#!Iu"); - - win->input_request_type = INPUT_REQUEST_LINE_UNICODE; win->line_input_buffer_unicode = buf; win->line_input_buffer_max_len = maxlen; + win->current_extra_line_terminators = g_slist_copy(win->extra_line_terminators); gchar *utf8; if(initlen > 0) { @@ -1022,6 +1023,79 @@ glk_set_echo_line_event(winid_t win, glui32 val) win->echo_line_input = val? TRUE : FALSE; } +/* Internal function to convert from a Glk keycode to a GDK keyval. */ +static unsigned +keycode_to_gdk_keyval(glui32 keycode) +{ + switch (keycode) + { + case keycode_Left: + return GDK_Left; + case keycode_Right: + return GDK_Right; + case keycode_Up: + return GDK_Up; + case keycode_Down: + return GDK_Down; + case keycode_Return: + return GDK_Return; + case keycode_Delete: + return GDK_Delete; + case keycode_Escape: + return GDK_Escape; + case keycode_Tab: + return GDK_Tab; + case keycode_PageUp: + return GDK_Page_Up; + case keycode_PageDown: + return GDK_Page_Down; + case keycode_Home: + return GDK_Home; + case keycode_End: + return GDK_End; + case keycode_Func1: + return GDK_F1; + case keycode_Func2: + return GDK_F2; + case keycode_Func3: + return GDK_F3; + case keycode_Func4: + return GDK_F4; + case keycode_Func5: + return GDK_F5; + case keycode_Func6: + return GDK_F6; + case keycode_Func7: + return GDK_F7; + case keycode_Func8: + return GDK_F8; + case keycode_Func9: + return GDK_F9; + case keycode_Func10: + return GDK_F10; + case keycode_Func11: + return GDK_F11; + case keycode_Func12: + return GDK_F12; + case keycode_Erase: + return GDK_BackSpace; + } + unsigned keyval = gdk_unicode_to_keyval(keycode); + if(keyval < 0x01000000) /* magic number meaning illegal unicode point */ + return keyval; + return 0; +} + +/* Internal function to decide whether @keycode is a valid line terminator. */ +gboolean +is_valid_line_terminator(glui32 keycode) +{ + switch(keycode) { + default: + return FALSE; + } +} + /** * glk_set_terminators_line_event: * @win: The window for which to set the line input terminator keys. @@ -1055,4 +1129,20 @@ void glk_set_terminators_line_event(winid_t win, glui32 *keycodes, glui32 count) { VALID_WINDOW(win, return); + + g_slist_free(win->extra_line_terminators); + win->extra_line_terminators = NULL; + + if(keycodes == NULL || count == 0) + return; + + int i; + for(i = 0; i < count; i++) + { + unsigned key = keycode_to_gdk_keyval(keycodes[i]); + if(is_valid_line_terminator(keycodes[i])) + win->extra_line_terminators = g_slist_prepend(win->extra_line_terminators, GUINT_TO_POINTER(key)); + else + WARNING_S("Ignoring invalid line terminator", gdk_keyval_name(key)); + } } \ No newline at end of file diff --git a/libchimara/input.h b/libchimara/input.h index d93361c..54c27e7 100644 --- a/libchimara/input.h +++ b/libchimara/input.h @@ -20,5 +20,6 @@ G_GNUC_INTERNAL void on_input_entry_changed(GtkEditable *editable, winid_t win); G_GNUC_INTERNAL glui32 keyval_to_glk_keycode(guint keyval, gboolean unicode); G_GNUC_INTERNAL void force_char_input_from_queue(winid_t win, event_t *event); G_GNUC_INTERNAL void force_line_input_from_queue(winid_t win, event_t *event); +G_GNUC_INTERNAL gboolean is_valid_line_terminator(glui32 keycode); #endif diff --git a/libchimara/window.c b/libchimara/window.c index b4d8897..80aee2f 100644 --- a/libchimara/window.c +++ b/libchimara/window.c @@ -35,6 +35,8 @@ window_new_common(glui32 rock) win->history = NULL; win->echo_line_input = TRUE; win->echo_current_line_input = TRUE; + win->extra_line_terminators = NULL; + win->current_extra_line_terminators = NULL; /* Initialise the buffer */ win->buffer = g_string_sized_new(1024); @@ -65,6 +67,8 @@ window_close_common(winid_t win, gboolean destroy_node) g_list_foreach(win->history, (GFunc)g_free, NULL); g_list_free(win->history); + g_slist_free(win->extra_line_terminators); + g_slist_free(win->current_extra_line_terminators); g_string_free(win->buffer, TRUE); g_hash_table_destroy(win->hyperlinks); diff --git a/libchimara/window.h b/libchimara/window.h index 58a840f..c67654a 100644 --- a/libchimara/window.h +++ b/libchimara/window.h @@ -64,6 +64,8 @@ struct glk_window_struct gboolean mouse_input_requested; GList *history; GList *history_pos; + GSList *extra_line_terminators; + GSList *current_extra_line_terminators; /* Line input echoing (text buffers only) */ gboolean echo_line_input; gboolean echo_current_line_input; -- 2.30.2