case.c \
charset.c charset.h \
chimara-glk.c chimara-glk.h chimara-glk-private.h \
+ dispatch.c \
event.c event.h \
fileref.c fileref.h \
garglk.c garglk.h \
#include <pango/pango.h>
#include "glk.h"
#include "gi_blorb.h"
+#include "gi_dispa.h"
#include "chimara-glk.h"
G_BEGIN_DECLS
giblorb_map_t *resource_map;
/* File stream pointing to the blorb used as current resource map */
strid_t resource_file;
+ /* Callbacks for registering and unregistering dispatch objects */
+ gidispatch_rock_t (*register_obj)(void *, glui32);
+ void (*unregister_obj)(void *, glui32, gidispatch_rock_t);
+ gidispatch_rock_t (*register_arr)(void *, glui32, char *);
+ void (*unregister_arr)(void *, glui32, char *, gidispatch_rock_t);
/* *** Platform-dependent Glk library data *** */
/* Flag for functions to find out if they are being called from startup code */
--- /dev/null
+#include <libchimara/glk.h>
+#include "chimara-glk-private.h"
+#include "window.h"
+#include "stream.h"
+#include "fileref.h"
+
+extern GPrivate *glk_data_key;
+
+void
+gidispatch_set_object_registry(gidispatch_rock_t (*regi)(void *obj, glui32 objclass), void (*unregi)(void *obj, glui32 objclass, gidispatch_rock_t objrock))
+{
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+ winid_t win;
+ strid_t str;
+ frefid_t fref;
+
+ glk_data->register_obj = regi;
+ glk_data->unregister_obj = unregi;
+
+ if(glk_data->register_obj)
+ {
+ /* It's now necessary to go through all existing objects, and register them. */
+ for(win = glk_window_iterate(NULL, NULL); win; win = glk_window_iterate(win, NULL))
+ win->disprock = (*glk_data->register_obj)(win, gidisp_Class_Window);
+ for(str = glk_stream_iterate(NULL, NULL); str; str = glk_stream_iterate(str, NULL))
+ str->disprock = (*glk_data->register_obj)(str, gidisp_Class_Stream);
+ for(fref = glk_fileref_iterate(NULL, NULL); fref; fref = glk_fileref_iterate(fref, NULL))
+ fref->disprock = (*glk_data->register_obj)(fref, gidisp_Class_Fileref);
+ }
+}
+
+gidispatch_rock_t
+gidispatch_get_objrock(void *obj, glui32 objclass)
+{
+ switch(objclass)
+ {
+ case gidisp_Class_Window:
+ return ((winid_t)obj)->disprock;
+ case gidisp_Class_Stream:
+ return ((strid_t)obj)->disprock;
+ case gidisp_Class_Fileref:
+ return ((frefid_t)obj)->disprock;
+ default:
+ {
+ gidispatch_rock_t dummy;
+ dummy.num = 0;
+ return dummy;
+ }
+ }
+}
+
+void
+gidispatch_set_retained_registry(gidispatch_rock_t (*regi)(void *array, glui32 len, char *typecode), void (*unregi)(void *array, glui32 len, char *typecode, gidispatch_rock_t objrock))
+{
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+ glk_data->register_arr = regi;
+ glk_data->unregister_arr = unregi;
+}
#include "fileref.h"
#include "magic.h"
#include "chimara-glk-private.h"
+#include "gi_dispa.h"
extern GPrivate *glk_data_key;
+/* Internal function: create a fileref using the given parameters. */
+frefid_t
+fileref_new(gchar *filename, glui32 rock, glui32 usage, glui32 orig_filemode)
+{
+ g_return_val_if_fail(filename != NULL, NULL);
+
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+
+ frefid_t f = g_new0(struct glk_fileref_struct, 1);
+ f->magic = MAGIC_FILEREF;
+ f->rock = rock;
+ if(glk_data->register_obj)
+ f->disprock = (*glk_data->register_obj)(f, gidisp_Class_Fileref);
+
+ f->filename = g_strdup(filename);
+ f->usage = usage;
+ f->orig_filemode = orig_filemode;
+
+ /* Add it to the global fileref list */
+ glk_data->fileref_list = g_list_prepend(glk_data->fileref_list, f);
+ f->fileref_list = glk_data->fileref_list;
+
+ return f;
+}
+
+static void
+fileref_close_common(frefid_t fref)
+{
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+
+ glk_data->fileref_list = g_list_delete_link(glk_data->fileref_list, fref->fileref_list);
+
+ if(glk_data->unregister_obj)
+ {
+ (*glk_data->unregister_obj)(fref, gidisp_Class_Fileref, fref->disprock);
+ fref->disprock.ptr = NULL;
+ }
+
+ if(fref->filename)
+ g_free(fref->filename);
+
+ fref->magic = MAGIC_FREE;
+ g_free(fref);
+}
+
/**
* glk_fileref_iterate:
* @fref: A file reference, or %NULL.
return fref->rock;
}
-/* Internal function: create a fileref using the given parameters. */
-frefid_t
-fileref_new(gchar *filename, glui32 rock, glui32 usage, glui32 orig_filemode)
-{
- g_return_val_if_fail(filename != NULL, NULL);
-
- ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
-
- frefid_t f = g_new0(struct glk_fileref_struct, 1);
- f->magic = MAGIC_FILEREF;
- f->rock = rock;
- f->filename = g_strdup(filename);
- f->usage = usage;
- f->orig_filemode = orig_filemode;
-
- /* Add it to the global fileref list */
- glk_data->fileref_list = g_list_prepend(glk_data->fileref_list, f);
- f->fileref_list = glk_data->fileref_list;
-
- return f;
-}
-
/**
* glk_fileref_create_temp:
* @usage: Bitfield with one or more of the <code>fileusage_</code> constants.
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
NULL);
- gtk_file_chooser_set_action(GTK_FILE_CHOOSER(chooser),
- GTK_FILE_CHOOSER_ACTION_OPEN);
+ gtk_file_chooser_set_action(GTK_FILE_CHOOSER(chooser), GTK_FILE_CHOOSER_ACTION_OPEN);
break;
case filemode_Write:
chooser = gtk_file_chooser_dialog_new("Select a file to save to", NULL,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
NULL);
- gtk_file_chooser_set_action(GTK_FILE_CHOOSER(chooser),
- GTK_FILE_CHOOSER_ACTION_SAVE);
- gtk_file_chooser_set_do_overwrite_confirmation(
- GTK_FILE_CHOOSER(chooser), TRUE);
+ gtk_file_chooser_set_action(GTK_FILE_CHOOSER(chooser), GTK_FILE_CHOOSER_ACTION_SAVE);
+ gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(chooser), TRUE);
break;
case filemode_ReadWrite:
case filemode_WriteAppend:
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
NULL);
- gtk_file_chooser_set_action(GTK_FILE_CHOOSER(chooser),
- GTK_FILE_CHOOSER_ACTION_SAVE);
+ gtk_file_chooser_set_action(GTK_FILE_CHOOSER(chooser), GTK_FILE_CHOOSER_ACTION_SAVE);
break;
default:
ILLEGAL_PARAM("Unknown file mode: %u", fmode);
gdk_threads_leave();
return NULL;
}
- gchar *filename =
- gtk_file_chooser_get_filename( GTK_FILE_CHOOSER(chooser) );
+ gchar *filename = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER(chooser) );
frefid_t f = fileref_new(filename, rock, usage, fmode);
g_free(filename);
gtk_widget_destroy(chooser);
glk_fileref_destroy(frefid_t fref)
{
VALID_FILEREF(fref, return);
-
- ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
-
- glk_data->fileref_list = g_list_delete_link(glk_data->fileref_list, fref->fileref_list);
- if(fref->filename)
- g_free(fref->filename);
-
- fref->magic = MAGIC_FREE;
- g_free(fref);
+ fileref_close_common(fref);
}
/**
#include <gtk/gtk.h>
#include "glk.h"
+#include "gi_dispa.h"
/**
* glk_fileref_struct:
{
/*< private >*/
glui32 magic, rock;
+ gidispatch_rock_t disprock;
/* Pointer to the list node in the global fileref list that contains this
fileref */
GList* fileref_list;
#include "charset.h"
#include "magic.h"
#include "input.h"
+#include "chimara-glk-private.h"
+
+extern GPrivate *glk_data_key;
/* Forward declarations */
static int flush_text_buffer(winid_t win);
g_return_if_fail(win->type != wintype_TextBuffer || win->type != wintype_TextGrid);
g_return_if_fail(initlen <= maxlen);
+ /* Register the buffer */
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+ if(glk_data->register_arr)
+ win->buffer_rock = (*glk_data->register_arr)(buf, maxlen, "&+#!Cn");
+
win->input_request_type = INPUT_REQUEST_LINE;
win->line_input_buffer = buf;
win->line_input_buffer_max_len = maxlen;
g_return_if_fail(win->type != wintype_TextBuffer || win->type != wintype_TextGrid);
g_return_if_fail(initlen <= maxlen);
+ /* Register the buffer */
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+ 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;
chars_written = flush_text_buffer(win);
}
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+ if(glk_data->unregister_arr)
+ {
+ if(win->input_request_type == INPUT_REQUEST_LINE_UNICODE)
+ (*glk_data->unregister_arr)(win->line_input_buffer_unicode, win->line_input_buffer_max_len, "&+#!Iu", win->buffer_rock);
+ else
+ (*glk_data->unregister_arr)(win->line_input_buffer, win->line_input_buffer_max_len, "&+#!Cn", win->buffer_rock);
+ }
+
if(event != NULL && chars_written > 0) {
event->type = evtype_LineInput;
event->val1 = chars_written;
int chars_written = flush_text_buffer(win);
event_throw(CHIMARA_GLK(gtk_widget_get_ancestor(win->widget, CHIMARA_TYPE_GLK)), evtype_LineInput, win, chars_written, 0);
+
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+ if(glk_data->unregister_arr)
+ {
+ if(win->input_request_type == INPUT_REQUEST_LINE_UNICODE)
+ (*glk_data->unregister_arr)(win->line_input_buffer_unicode, win->line_input_buffer_max_len, "&+#!Iu", win->buffer_rock);
+ else
+ (*glk_data->unregister_arr)(win->line_input_buffer, win->line_input_buffer_max_len, "&+#!Cn", win->buffer_rock);
+ }
}
}
int chars_written = flush_text_grid(win);
event_throw(CHIMARA_GLK(gtk_widget_get_ancestor(win->widget, CHIMARA_TYPE_GLK)), evtype_LineInput, win, chars_written, 0);
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+ if(glk_data->unregister_arr)
+ {
+ if(win->input_request_type == INPUT_REQUEST_LINE_UNICODE)
+ (*glk_data->unregister_arr)(win->line_input_buffer_unicode, win->line_input_buffer_max_len, "&+#!Iu", win->buffer_rock);
+ else
+ (*glk_data->unregister_arr)(win->line_input_buffer, win->line_input_buffer_max_len, "&+#!Cn", win->buffer_rock);
+ }
}
extern GPrivate *glk_data_key;
/* Internal function: create a stream with a specified rock value */
-static strid_t
-stream_new_common(glui32 rock, glui32 fmode, enum StreamType type)
+strid_t
+stream_new_common(glui32 rock)
{
ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
strid_t str = g_new0(struct glk_stream_struct, 1);
str->magic = MAGIC_STREAM;
str->rock = rock;
- str->file_mode = fmode;
- str->type = type;
+ if(glk_data->register_obj)
+ str->disprock = (*glk_data->register_obj)(str, gidisp_Class_Stream);
/* Add it to the global stream list */
glk_data->stream_list = g_list_prepend(glk_data->stream_list, str);
return str;
}
-/* Internal function: create a window stream to go with window. */
-strid_t
-window_stream_new(winid_t window)
+/* Internal function: Stuff to do upon closing any type of stream. */
+void
+stream_close_common(strid_t str, stream_result_t *result)
{
- /* Create stream and connect it to window */
- strid_t str = stream_new_common(0, filemode_Write, STREAM_TYPE_WINDOW);
- str->window = window;
- str->style = "normal";
- return str;
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+
+ /* Remove the stream from the global stream list */
+ glk_data->stream_list = g_list_delete_link(glk_data->stream_list, str->stream_list);
+
+ /* If it was the current output stream, set that to NULL */
+ if(glk_data->current_stream == str)
+ glk_data->current_stream = NULL;
+
+ /* If it was one or more windows' echo streams, set those to NULL */
+ winid_t win;
+ for(win = glk_window_iterate(NULL, NULL); win;
+ win = glk_window_iterate(win, NULL))
+ if(win->echo_stream == str)
+ win->echo_stream = NULL;
+
+ if(glk_data->unregister_obj)
+ {
+ (*glk_data->unregister_obj)(str, gidisp_Class_Stream, str->disprock);
+ str->disprock.ptr = NULL;
+ }
+
+ /* Return the character counts */
+ if(result)
+ {
+ result->readcount = str->read_count;
+ result->writecount = str->write_count;
+ }
+
+ str->magic = MAGIC_FREE;
+ g_free(str);
}
/**
{
g_return_val_if_fail(fmode != filemode_WriteAppend, NULL);
- strid_t str = stream_new_common(rock, fmode, STREAM_TYPE_MEMORY);
- str->buffer = buf;
+ strid_t str = stream_new_common(rock);
+ str->file_mode = fmode;
+ str->type = STREAM_TYPE_MEMORY;
str->mark = 0;
- str->buflen = buflen;
str->unicode = FALSE;
+
+ if(buf && buflen)
+ {
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+ str->buffer = buf;
+ str->buflen = buflen;
+ if(glk_data->register_arr)
+ str->buffer_rock = (*glk_data->register_arr)(buf, buflen, "&+#!Cn");
+ }
+
return str;
}
{
g_return_val_if_fail(fmode != filemode_WriteAppend, NULL);
- strid_t str = stream_new_common(rock, fmode, STREAM_TYPE_MEMORY);
- str->ubuffer = buf;
+ strid_t str = stream_new_common(rock);
+ str->file_mode = fmode;
+ str->type = STREAM_TYPE_MEMORY;
str->mark = 0;
- str->buflen = buflen;
str->unicode = TRUE;
+
+ if(buf && buflen)
+ {
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+ str->ubuffer = buf;
+ str->buflen = buflen;
+ if(glk_data->register_arr)
+ str->buffer_rock = (*glk_data->register_arr)(buf, buflen, "&+#!Iu");
+ }
+
return str;
}
}
}
- strid_t str = stream_new_common(rock, fmode, STREAM_TYPE_FILE);
+ strid_t str = stream_new_common(rock);
+ str->file_mode = fmode;
+ str->type = STREAM_TYPE_FILE;
str->file_pointer = fp;
str->binary = binary;
str->unicode = unicode;
return;
case STREAM_TYPE_MEMORY:
- /* Do nothing */
+ {
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+ if(glk_data->unregister_arr)
+ {
+ if(str->unicode)
+ (*glk_data->unregister_arr)(str->ubuffer, str->buflen, "&+#!Iu", str->buffer_rock);
+ else
+ (*glk_data->unregister_arr)(str->buffer, str->buflen, "&+#!Cn", str->buffer_rock);
+ }
+ }
break;
-
+
case STREAM_TYPE_FILE:
if(fclose(str->file_pointer) != 0)
IO_WARNING( "Failed to close file", str->filename, g_strerror(errno) );
stream_close_common(str, result);
}
-
-/* Internal function: Stuff to do upon closing any type of stream. */
-void
-stream_close_common(strid_t str, stream_result_t *result)
-{
- ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
-
- /* Remove the stream from the global stream list */
- glk_data->stream_list = g_list_delete_link(glk_data->stream_list, str->stream_list);
-
- /* If it was the current output stream, set that to NULL */
- if(glk_data->current_stream == str)
- glk_data->current_stream = NULL;
-
- /* If it was one or more windows' echo streams, set those to NULL */
- winid_t win;
- for(win = glk_window_iterate(NULL, NULL); win;
- win = glk_window_iterate(win, NULL))
- if(win->echo_stream == str)
- win->echo_stream = NULL;
-
- /* Return the character counts */
- if(result)
- {
- result->readcount = str->read_count;
- result->writecount = str->write_count;
- }
-
- str->magic = MAGIC_FREE;
- g_free(str);
-}
#include <gtk/gtk.h>
#include "glk.h"
+#include "gi_dispa.h"
#include "window.h"
#include "fileref.h"
{
/*< private >*/
glui32 magic, rock;
+ gidispatch_rock_t disprock;
/* Pointer to the list node in the global stream list that contains this
stream */
GList* stream_list;
glui32 *ubuffer;
glui32 mark;
glui32 buflen;
+ gidispatch_rock_t buffer_rock;
/* Specific to file streams */
FILE *file_pointer;
gboolean binary;
gchar *style; /* Name of the current style */
};
-G_GNUC_INTERNAL strid_t window_stream_new(winid_t window);
G_GNUC_INTERNAL strid_t file_stream_new(frefid_t fileref, glui32 fmode, glui32 rock, gboolean unicode);
+G_GNUC_INTERNAL strid_t stream_new_common(glui32 rock);
G_GNUC_INTERNAL void stream_close_common(strid_t str, stream_result_t *result);
#endif
#include "window.h"
#include "magic.h"
#include "chimara-glk-private.h"
+#include "gi_dispa.h"
extern GPrivate *glk_data_key;
+static winid_t
+window_new_common(glui32 rock)
+{
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+ winid_t win = g_new0(struct glk_window_struct, 1);
+
+ win->magic = MAGIC_WINDOW;
+ win->rock = rock;
+ if(glk_data->register_obj)
+ win->disprock = (*glk_data->register_obj)(win, gidisp_Class_Window);
+
+ win->window_node = g_node_new(win);
+
+ /* Every window has a window stream, but printing to it might have no effect */
+ win->window_stream = stream_new_common(0);
+ win->window_stream->file_mode = filemode_Write;
+ win->window_stream->type = STREAM_TYPE_WINDOW;
+ win->window_stream->window = win;
+ win->window_stream->style = "normal";
+
+ win->echo_stream = NULL;
+ win->input_request_type = INPUT_REQUEST_NONE;
+ win->line_input_buffer = NULL;
+ win->line_input_buffer_unicode = NULL;
+
+ return win;
+}
+
+static void
+window_close_common(winid_t win)
+{
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+
+ if(glk_data->unregister_obj)
+ {
+ (*glk_data->unregister_obj)(win, gidisp_Class_Window, win->disprock);
+ win->disprock.ptr = NULL;
+ }
+
+ g_node_destroy(win->window_node);
+ win->magic = MAGIC_FREE;
+ g_free(win);
+}
+
/**
* glk_window_iterate:
* @win: A window, or %NULL.
gdk_threads_enter();
/* Create the new window */
- winid_t win = g_new0(struct glk_window_struct, 1);
- win->magic = MAGIC_WINDOW;
- win->rock = rock;
+ winid_t win = window_new_common(rock);
win->type = wintype;
- win->window_node = g_node_new(win);
switch(wintype)
{
/* A blank window has no size */
win->unit_width = 0;
win->unit_height = 0;
- /* You can print to a blank window's stream, but it does nothing */
- win->window_stream = window_stream_new(win);
- win->echo_stream = NULL;
}
break;
pango_layout_set_font_description(zero, glk_data->monospace_font_desc);
pango_layout_get_pixel_size(zero, &(win->unit_width), &(win->unit_height));
g_object_unref(zero);
-
- /* Set the other parameters (width and height are set later) */
- win->window_stream = window_stream_new(win);
- win->echo_stream = NULL;
- win->input_request_type = INPUT_REQUEST_NONE;
- win->line_input_buffer = NULL;
- win->line_input_buffer_unicode = NULL;
+ /* width and height are set later */
/* Connect signal handlers */
win->keypress_handler = g_signal_connect( G_OBJECT(textview), "key-press-event", G_CALLBACK(on_window_key_press_event), win );
pango_layout_set_font_description(zero, glk_data->default_font_desc);
pango_layout_get_pixel_size(zero, &(win->unit_width), &(win->unit_height));
g_object_unref(zero);
-
- /* Set the other parameters */
- win->window_stream = window_stream_new(win);
- win->echo_stream = NULL;
- win->input_request_type = INPUT_REQUEST_NONE;
- win->line_input_buffer = NULL;
- win->line_input_buffer_unicode = NULL;
/* Connect signal handlers */
win->keypress_handler = g_signal_connect( G_OBJECT(textview), "key-press-event", G_CALLBACK(on_window_key_press_event), win );
{
/* When splitting, construct a new parent window
* copying most characteristics from the window that is being split */
- winid_t pair = g_new0(struct glk_window_struct, 1);
- pair->magic = MAGIC_WINDOW;
- pair->rock = 0;
+ winid_t pair = window_new_common(0);
pair->type = wintype_Pair;
- pair->window_node = g_node_new(pair);
- /* You can print to a pair window's window stream, but it has no effect */
- pair->window_stream = window_stream_new(pair);
- pair->echo_stream = NULL;
/* The pair window must know about its children's split method */
pair->key_window = win;
free_winids_below(win->window_node->children->data);
free_winids_below(win->window_node->children->next->data);
}
- win->magic = MAGIC_FREE;
- g_free(win);
+ window_close_common(win);
}
/**
/* Parent window changes from a split window into the sibling window */
/* The parent of any window is either a pair window or NULL */
GNode *pair_node = win->window_node->parent;
- g_node_destroy(win->window_node);
/* If win was not the root window: */
if(pair_node != NULL)
{
g_node_append(new_parent_node, sibling_node);
}
- winid_t pair = (winid_t) pair_node->data;
- g_node_destroy(pair_node);
-
- pair->magic = MAGIC_FREE;
- g_free(pair);
+ window_close_common( (winid_t) pair_node->data );
}
else /* it was the root window */
{
glk_data->root_window = NULL;
}
- win->magic = MAGIC_FREE;
- g_free(win);
+ window_close_common(win);
/* Schedule a redraw */
g_mutex_lock(glk_data->arrange_lock);
gdk_threads_leave();
}
-
#include <gtk/gtk.h>
#include "glk.h"
-
+#include "gi_dispa.h"
#include "stream.h"
#include "input.h"
#include "style.h"
{
/*< private >*/
glui32 magic, rock;
+ gidispatch_rock_t disprock;
/* Pointer to the node in the global tree that contains this window */
GNode *window_node;
/* Window parameters */
gchar *line_input_buffer;
glui32 *line_input_buffer_unicode;
glui32 line_input_buffer_max_len;
+ gidispatch_rock_t buffer_rock;
gboolean mouse_input_requested;
/* Line input field (text grids only) */
glui32 input_length;