Added "magic numbers" to the window, stream, and fileref structures, for better checking.
Added macros for checking and error reporting in magic.h.
## Process this file with automake to produce Makefile.in
+AM_CFLAGS = -Wall
+
data_DATA = chimara.ui
noinst_PROGRAMS = test-chimara
-DPACKAGE_LOCALE_DIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \
-DPACKAGE_SRC_DIR=\""$(srcdir)"\" \
-DPACKAGE_DATA_DIR=\""$(datadir)"\"
-test_chimara_CFLAGS = @TEST_CFLAGS@
+test_chimara_CFLAGS = @TEST_CFLAGS@ $(AM_CFLAGS)
test_chimara_LDADD = @TEST_LIBS@ -lchimara
lib_LTLIBRARIES = libchimara.la
fileref.c fileref.h \
gestalt.c \
glk.c glk.h \
+ magic.c magic.h \
input.c input.h \
stream.c stream.h \
strio.c \
style.c \
window.c window.h
-libchimara_la_CFLAGS = @CHIMARA_CFLAGS@
+libchimara_la_CPPFLAGS = \
+ -DG_LOG_DOMAIN=\"Chimara\"
+libchimara_la_CFLAGS = @CHIMARA_CFLAGS@ $(AM_CFLAGS)
libchimara_la_LIBADD = @CHIMARA_LIBS@
libchimara_la_LDFLAGS = -no-undefined -export-symbols-regex "^chimara_glk_|^glk_"
libchimara_includedir = $(includedir)/chimara/chimara
#include "charset.h"
+#include "magic.h"
#include <glib.h>
/* Internal function: change illegal (control) characters in a string to a
g_free(canonical);
if(retval == NULL)
- g_warning("Error during latin1->utf8 conversion: %s", error->message);
+ IO_WARNING("Error during latin1->utf8 conversion of string", s, error->message);
return retval;
}
gchar *retval = g_convert_with_fallback(s, -1, "ISO-8859-1", "UTF-8", PLACEHOLDER_STRING, NULL, bytes_written, &error);
if(retval == NULL)
- g_warning("Error during utf8->latin1 conversion: %s", error->message);
+ IO_WARNING("Error during utf8->latin1 conversion of string", s, error->message);
return retval;
}
gunichar *retval = g_utf8_to_ucs4_fast(s, -1, items_written);
if(retval == NULL)
- g_warning("Error during utf8->unicode conversion");
+ WARNING_S("Error during utf8->unicode conversion of string", s);
return retval;
}
gchar *retval = g_ucs4_to_utf8(buf, len, NULL, NULL, &error);
if(retval == NULL)
- g_warning("Error during unicode->utf8 conversion: %s", error->message);
+ WARNING_S("Error during unicode->utf8 conversion", error->message);
return retval;
}
#include "event.h"
+#include "magic.h"
#include "glk.h"
#include <string.h>
if(retrieved_event == NULL)
{
g_mutex_unlock(glk_data->event_lock);
- g_warning("%s: Retrieved NULL event from non-empty event queue", __func__);
+ WARNING("Retrieved NULL event from non-empty event queue");
return;
}
memcpy(event, retrieved_event, sizeof(event_t));
+#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <gtk/gtk.h>
#include <glib/gstdio.h>
#include "fileref.h"
+#include "magic.h"
#include "chimara-glk-private.h"
extern ChimaraGlkPrivate *glk_data;
frefid_t
glk_fileref_iterate(frefid_t fref, glui32 *rockptr)
{
+ VALID_FILEREF_OR_NULL(fref, return NULL);
+
GList *retnode;
if(fref == NULL)
glui32
glk_fileref_get_rock(frefid_t fref)
{
- g_return_val_if_fail(fref != NULL, 0);
+ VALID_FILEREF(fref, return 0);
return fref->rock;
}
g_return_val_if_fail(filename != NULL, NULL);
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;
gint handle = g_file_open_tmp("glkXXXXXX", &filename, &error);
if(handle == -1)
{
- g_warning("Error creating temporary file: %s", error->message);
+ WARNING_S("Error creating temporary file", error->message);
if(filename)
g_free(filename);
return NULL;
}
- if(close(handle) == -1) /* There is no g_close()? */
+ if(close(handle) == -1) /* There is no g_close() */
{
- g_warning("Error closing temporary file.");
+ IO_WARNING( "Error closing temporary file", filename, g_strerror(errno) );
if(filename)
g_free(filename);
return NULL;
GTK_FILE_CHOOSER_ACTION_SAVE);
break;
default:
- g_warning("glk_fileref_create_by_prompt: Unsupported mode");
+ ILLEGAL_PARAM("Unknown file mode: %u", fmode);
gdk_threads_leave();
return NULL;
}
&error);
if(osname == NULL)
{
- g_warning("Error during latin1->filename conversion: %s", error->message);
+ WARNING_S("Error during latin1->filename conversion", error->message);
return NULL;
}
frefid_t
glk_fileref_create_from_fileref(glui32 usage, frefid_t fref, glui32 rock)
{
+ VALID_FILEREF(fref, return NULL);
return fileref_new(fref->filename, rock, usage, fref->orig_filemode);
}
void
glk_fileref_destroy(frefid_t fref)
{
+ VALID_FILEREF(fref, return);
+
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);
}
void
glk_fileref_delete_file(frefid_t fref)
{
+ VALID_FILEREF(fref, return);
if( glk_fileref_does_file_exist(fref) )
if(g_unlink(fref->filename) == -1)
- g_warning("Error deleting file %s", fref->filename);
+ IO_WARNING( "Error deleting file", fref->filename, g_strerror(errno) );
}
/**
glui32
glk_fileref_does_file_exist(frefid_t fref)
{
+ VALID_FILEREF(fref, return 0);
if( g_file_test(fref->filename, G_FILE_TEST_EXISTS) )
return 1;
return 0;
struct glk_fileref_struct
{
/*< private >*/
- glui32 rock;
+ glui32 magic, rock;
/* 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"
/**
void
glk_request_char_event(winid_t win)
{
- g_return_if_fail(win);
+ VALID_WINDOW(win, return);
g_return_if_fail(win->input_request_type == INPUT_REQUEST_NONE);
g_return_if_fail(win->type != wintype_TextBuffer || win->type != wintype_TextGrid);
void
glk_request_char_event_uni(winid_t win)
{
- g_return_if_fail(win);
+ VALID_WINDOW(win, return);
g_return_if_fail(win->input_request_type == INPUT_REQUEST_NONE);
g_return_if_fail(win->type != wintype_TextBuffer || win->type != wintype_TextGrid);
void
glk_request_line_event(winid_t win, char* buf, glui32 maxlen, glui32 initlen)
{
- g_return_if_fail(win);
+ VALID_WINDOW(win, return);
g_return_if_fail(buf);
g_return_if_fail(win->input_request_type == INPUT_REQUEST_NONE);
g_return_if_fail(win->type != wintype_TextBuffer || win->type != wintype_TextGrid);
case wintype_TextGrid:
text_grid_request_line_event_common(win, maxlen, (initlen > 0), inserttext);
break;
- default:
- g_assert_not_reached();
}
g_free(inserttext);
}
void
glk_request_line_event_uni(winid_t win, glui32 *buf, glui32 maxlen, glui32 initlen)
{
- g_return_if_fail(win);
+ VALID_WINDOW(win, return);
g_return_if_fail(buf);
g_return_if_fail(win->input_request_type == INPUT_REQUEST_NONE);
g_return_if_fail(win->type != wintype_TextBuffer || win->type != wintype_TextGrid);
case wintype_TextGrid:
text_grid_request_line_event_common(win, maxlen, (initlen > 0), utf8);
break;
- default:
- g_assert_not_reached();
}
g_free(utf8);
}
event_throw(evtype_LineInput, win, copycount, 0);
}
else
- g_warning("%s: Wrong input request type.", __func__);
+ WARNING("Wrong input request type");
win->input_request_type = INPUT_REQUEST_NONE;
}
--- /dev/null
+#include <gtk/gtk.h>
+#include "glk.h"
+#include "magic.h"
+
+/* The "magic" mechanism was stolen from Evin Robertson's GtkGlk. */
+
+static gchar *
+magic_to_string(glui32 magic)
+{
+ switch(magic)
+ {
+ case MAGIC_WINDOW:
+ return "winid_t";
+ case MAGIC_STREAM:
+ return "strid_t";
+ case MAGIC_FILEREF:
+ return "frefid_t";
+ case MAGIC_SCHANNEL:
+ return "schanid_t";
+ default:
+ g_return_val_if_reached("unknown");
+ }
+}
+
+/* Internal function: check the object's magic number to make sure it is the
+ right type, and not freed. */
+gboolean
+magic_is_valid_or_null(const glui32 goodmagic, const glui32 realmagic, const gchar *function)
+{
+ if(realmagic != MAGIC_NULL)
+ {
+ if(realmagic != goodmagic)
+ {
+ if(realmagic == MAGIC_FREE)
+ g_critical("%s: Using a freed object", function);
+ else
+ g_critical( "%s: %s object not a %s", function, magic_to_string(realmagic), magic_to_string(goodmagic) );
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+
+/* Internal function: check the object's magic number to make sure it is
+ not NULL, the right type, and not freed. */
+gboolean
+magic_is_valid(const void *obj, const glui32 goodmagic, const glui32 realmagic, const gchar *function)
+{
+ if(obj == NULL)
+ {
+ g_critical( "%s: NULL %s pointer", function, magic_to_string(goodmagic) );
+ return FALSE;
+ }
+ return magic_is_valid_or_null(goodmagic, realmagic, function);
+}
--- /dev/null
+#ifndef __MAGIC_H__
+#define __MAGIC_H__
+
+#include <gtk/gtk.h>
+#include "glk.h"
+
+#define MAGIC_FREE 0x46524545 /* "FREE" */
+#define MAGIC_NULL 0x4E554C4C /* "NULL" */
+#define MAGIC_WINDOW 0x57494E44 /* "WIND" */
+#define MAGIC_STREAM 0x53545245 /* "STRE" */
+#define MAGIC_FILEREF 0x46494C45 /* "FILE" */
+#define MAGIC_SCHANNEL 0x53434841 /* "SCHA" */
+
+gboolean magic_is_valid_or_null(const glui32 goodmagic, const glui32 realmagic, const gchar *function);
+gboolean magic_is_valid(const void *obj, const glui32 goodmagic, const glui32 realmagic, const gchar *function);
+
+#define VALID_MAGIC(obj, goodmagic, die) \
+ if( !magic_is_valid(obj, goodmagic, obj->magic, G_STRFUNC) ) die
+#define VALID_MAGIC_OR_NULL(obj, goodmagic, die) \
+ if( !magic_is_valid_or_null(goodmagic, obj? obj->magic : MAGIC_NULL, G_STRFUNC) ) die
+
+#define VALID_WINDOW(o, d) VALID_MAGIC(o, MAGIC_WINDOW, d)
+#define VALID_WINDOW_OR_NULL(o, d) VALID_MAGIC_OR_NULL(o, MAGIC_WINDOW, d)
+#define VALID_STREAM(o, d) VALID_MAGIC(o, MAGIC_STREAM, d)
+#define VALID_STREAM_OR_NULL(o, d) VALID_MAGIC_OR_NULL(o, MAGIC_STREAM, d)
+#define VALID_FILEREF(o, d) VALID_MAGIC(o, MAGIC_FILEREF, d)
+#define VALID_FILEREF_OR_NULL(o, d) VALID_MAGIC_OR_NULL(o, MAGIC_FILEREF, d)
+#define VALID_SCHANNEL(o, d) VALID_MAGIC(o, MAGIC_SCHANNEL, d)
+#define VALID_SCHANNEL_OR_NULL(o, d) VALID_MAGIC_OR_NULL(o, MAGIC_SCHANNEL, d)
+
+/* This works with string variables as well as literal strings */
+#define ILLEGAL(str) g_critical("%s: %s", G_STRFUNC, str)
+/* This only works with literal strings */
+#define ILLEGAL_PARAM(str, param) g_critical("%s: " str, G_STRFUNC, param)
+
+#define WARNING(msg) g_warning("%s: %s", G_STRFUNC, msg)
+#define WARNING_S(msg, str) g_warning("%s: %s: %s", G_STRFUNC, msg, str)
+#define IO_WARNING(msg, str, errmsg) \
+ g_warning("%s: %s \"%s\": %s", G_STRFUNC, msg, str, errmsg)
+
+#endif /* __MAGIC_H__ */
g_object_unref( G_OBJECT(builder) );
- if( !chimara_glk_run(CHIMARA_GLK(glk), ".libs/model.so", &error) ) {
+ if( !chimara_glk_run(CHIMARA_GLK(glk), ".libs/gridtest.so", &error) ) {
error_dialog(GTK_WINDOW(window), error, "Error starting Glk library: ");
return 1;
}
#include "stream.h"
#include "fileref.h"
+#include "magic.h"
+#include <errno.h>
+#include <stdio.h>
#include <glib.h>
#include <glib/gstdio.h>
#include "chimara-glk-private.h"
extern ChimaraGlkPrivate *glk_data;
-/* Internal function: create a window stream to go with window. */
-strid_t
-window_stream_new(winid_t window)
+/* Internal function: create a stream with a specified rock value */
+static strid_t
+stream_new_common(glui32 rock, glui32 fmode, enum StreamType type)
{
- /* Create stream and connect it to window */
strid_t str = g_new0(struct glk_stream_struct, 1);
- str->file_mode = filemode_Write;
- str->type = STREAM_TYPE_WINDOW;
- str->window = window;
-
+ str->magic = MAGIC_STREAM;
+ str->rock = rock;
+ str->file_mode = fmode;
+ str->type = type;
+
/* Add it to the global stream list */
glk_data->stream_list = g_list_prepend(glk_data->stream_list, str);
str->stream_list = glk_data->stream_list;
+
+ return str;
+}
+/* Internal function: create a window stream to go with window. */
+strid_t
+window_stream_new(winid_t window)
+{
+ /* Create stream and connect it to window */
+ strid_t str = stream_new_common(0, filemode_Write, STREAM_TYPE_WINDOW);
+ str->window = window;
return str;
}
strid_t
glk_stream_iterate(strid_t str, glui32 *rockptr)
{
+ VALID_STREAM_OR_NULL(str, return NULL);
+
GList *retnode;
if(str == NULL)
glui32
glk_stream_get_rock(strid_t str)
{
- g_return_val_if_fail(str != NULL, 0);
+ VALID_STREAM(str, return 0);
return str->rock;
}
void
glk_stream_set_current(strid_t str)
{
+ VALID_STREAM_OR_NULL(str, return);
+
if(str != NULL && str->file_mode == filemode_Read)
{
- g_warning("%s: Cannot set current stream to non output stream", __func__);
+ ILLEGAL("Cannot set current stream to non output stream");
return;
}
void
glk_put_char(unsigned char ch)
{
- g_return_if_fail(glk_data->current_stream != NULL);
+ VALID_STREAM(glk_data->current_stream, return);
glk_put_char_stream(glk_data->current_stream, ch);
}
void
glk_put_char_uni(glui32 ch)
{
- g_return_if_fail(glk_data->current_stream != NULL);
+ VALID_STREAM(glk_data->current_stream, return);
glk_put_char_stream_uni(glk_data->current_stream, ch);
}
void
glk_put_string(char *s)
{
- g_return_if_fail(glk_data->current_stream != NULL);
+ VALID_STREAM(glk_data->current_stream, return);
glk_put_string_stream(glk_data->current_stream, s);
}
void
glk_put_string_uni(glui32 *s)
{
- g_return_if_fail(glk_data->current_stream != NULL);
+ VALID_STREAM(glk_data->current_stream, return);
glk_put_string_stream_uni(glk_data->current_stream, s);
}
void
glk_put_buffer(char *buf, glui32 len)
{
- g_return_if_fail(glk_data->current_stream != NULL);
+ VALID_STREAM(glk_data->current_stream, return);
glk_put_buffer_stream(glk_data->current_stream, buf, len);
}
void
glk_put_buffer_uni(glui32 *buf, glui32 len)
{
- g_return_if_fail(glk_data->current_stream != NULL);
+ VALID_STREAM(glk_data->current_stream, return);
glk_put_buffer_stream_uni(glk_data->current_stream, buf, len);
}
{
g_return_val_if_fail(fmode != filemode_WriteAppend, NULL);
- strid_t str = g_new0(struct glk_stream_struct, 1);
- str->rock = rock;
- str->file_mode = fmode;
- str->type = STREAM_TYPE_MEMORY;
+ strid_t str = stream_new_common(rock, fmode, STREAM_TYPE_MEMORY);
str->buffer = buf;
str->mark = 0;
str->buflen = buflen;
str->unicode = FALSE;
-
- /* Add it to the global stream list */
- glk_data->stream_list = g_list_prepend(glk_data->stream_list, str);
- str->stream_list = glk_data->stream_list;
-
return str;
}
{
g_return_val_if_fail(fmode != filemode_WriteAppend, NULL);
- strid_t str = g_new0(struct glk_stream_struct, 1);
- str->rock = rock;
- str->file_mode = fmode;
- str->type = STREAM_TYPE_MEMORY;
+ strid_t str = stream_new_common(rock, fmode, STREAM_TYPE_MEMORY);
str->ubuffer = buf;
str->mark = 0;
str->buflen = buflen;
str->unicode = TRUE;
-
- /* Add it to the global stream list */
- glk_data->stream_list = g_list_prepend(glk_data->stream_list, str);
- str->stream_list = glk_data->stream_list;
-
return str;
}
static strid_t
file_stream_new(frefid_t fileref, glui32 fmode, glui32 rock, gboolean unicode)
{
- g_return_val_if_fail(fileref != NULL, NULL);
+ VALID_FILEREF(fileref, return NULL);
gchar *modestr;
/* Binary mode is 0x000, text mode 0x100 */
{
case filemode_Read:
if(!g_file_test(fileref->filename, G_FILE_TEST_EXISTS)) {
- g_warning("glk_stream_open_file: Tried to open a file in read "
- "mode that didn't exist!");
+ ILLEGAL_PARAM("Tried to open a nonexistent file, '%s', in read mode", fileref->filename);
return NULL;
}
modestr = g_strdup(binary? "rb" : "r");
}
break;
default:
- g_warning("glk_stream_open_file: Invalid file mode");
+ ILLEGAL_PARAM("Invalid file mode: %u", fmode);
return NULL;
}
FILE *fp = g_fopen(fileref->filename, modestr);
g_free(modestr);
if(fp == NULL) {
- g_warning("glk_stream_open_file: Error opening file");
+ IO_WARNING( "Error opening file", fileref->filename, g_strerror(errno) );
return NULL;
}
GtkWidget *dialog = gtk_message_dialog_new(NULL, 0,
GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
- "File %s already exists. Overwrite?", fileref->filename);
+ "File '%s' already exists. Overwrite?", fileref->filename);
gint response = gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
gdk_threads_leave();
if(response != GTK_RESPONSE_YES) {
- fclose(fp);
+ if(fclose(fp) != 0)
+ IO_WARNING( "Error closing file", fileref->filename, g_strerror(errno) );
return NULL;
}
}
- strid_t str = g_new0(struct glk_stream_struct, 1);
- str->rock = rock;
- str->file_mode = fmode;
- str->type = STREAM_TYPE_FILE;
+ strid_t str = stream_new_common(rock, fmode, STREAM_TYPE_FILE);
str->file_pointer = fp;
str->binary = binary;
str->unicode = unicode;
str->filename = g_filename_to_utf8(fileref->filename, -1, NULL, NULL, NULL);
if(str->filename == NULL)
str->filename = g_strdup("Unknown file name"); /* fail silently */
- /* Add it to the global stream list */
- glk_data->stream_list = g_list_prepend(glk_data->stream_list, str);
- str->stream_list = glk_data->stream_list;
return str;
}
void
glk_stream_close(strid_t str, stream_result_t *result)
{
- g_return_if_fail(str != NULL);
+ VALID_STREAM(str, return);
/* Free resources associated with one specific type of stream */
switch(str->type)
{
case STREAM_TYPE_WINDOW:
- g_warning("%s: Attempted to close a window stream. Use glk_window_"
- "close() instead.", __func__);
+ ILLEGAL("Attempted to close a window stream. Use glk_window_close() instead.");
return;
case STREAM_TYPE_MEMORY:
case STREAM_TYPE_FILE:
if(fclose(str->file_pointer) != 0)
- g_warning("%s: Failed to close file '%s'.", __func__,
- str->filename);
+ IO_WARNING( "Failed to close file", str->filename, g_strerror(errno) );
g_free(str->filename);
break;
default:
- g_warning("%s: Closing this type of stream not supported.",
- __func__);
+ ILLEGAL_PARAM("Unknown stream type: %u", str->type);
return;
}
result->readcount = str->read_count;
result->writecount = str->write_count;
}
+
+ str->magic = MAGIC_FREE;
g_free(str);
}
struct glk_stream_struct
{
/*< private >*/
- glui32 rock;
+ glui32 magic, rock;
/* Pointer to the list node in the global stream list that contains this
stream */
GList* stream_list;
#include "charset.h"
+#include "magic.h"
#include "stream.h"
+#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <glib.h>
str->write_count += len;
break;
default:
- g_warning("%s: Writing to this kind of window unsupported.", __func__);
+ ILLEGAL_PARAM("Unknown window type: %u", str->window->type);
}
/* Now write the same buffer to the window's echo stream */
str->write_count += len;
break;
default:
- g_warning("%s: Writing to this kind of stream unsupported.", __func__);
+ ILLEGAL_PARAM("Unknown stream type: %u", str->type);
}
}
str->write_count += len;
break;
default:
- g_warning("%s: Writing to this kind of window unsupported.", __func__);
+ ILLEGAL_PARAM("Unknown window type: %u", str->window->type);
}
/* Now write the same buffer to the window's echo stream */
str->write_count += len;
break;
default:
- g_warning("%s: Writing to this kind of stream unsupported.", __func__);
+ ILLEGAL_PARAM("Unknown stream type: %u", str->type);
}
}
void
glk_put_char_stream(strid_t str, unsigned char ch)
{
- g_return_if_fail(str != NULL);
+ VALID_STREAM(str, return);
g_return_if_fail(str->file_mode != filemode_Read);
write_buffer_to_stream(str, (gchar *)&ch, 1);
void
glk_put_char_stream_uni(strid_t str, glui32 ch)
{
- g_return_if_fail(str != NULL);
+ VALID_STREAM(str, return);
g_return_if_fail(str->file_mode != filemode_Read);
write_buffer_to_stream_uni(str, &ch, 1);
void
glk_put_string_stream(strid_t str, char *s)
{
- g_return_if_fail(str != NULL);
+ VALID_STREAM(str, return);
g_return_if_fail(str->file_mode != filemode_Read);
write_buffer_to_stream(str, s, strlen(s));
void
glk_put_string_stream_uni(strid_t str, glui32 *s)
{
- g_return_if_fail(str != NULL);
+ VALID_STREAM(str, return);
g_return_if_fail(str->file_mode != filemode_Read);
/* An impromptu strlen() for glui32 arrays */
void
glk_put_buffer_stream(strid_t str, char *buf, glui32 len)
{
- g_return_if_fail(str != NULL);
+ VALID_STREAM(str, return);
g_return_if_fail(str->file_mode != filemode_Read);
write_buffer_to_stream(str, buf, len);
void
glk_put_buffer_stream_uni(strid_t str, glui32 *buf, glui32 len)
{
- g_return_if_fail(str != NULL);
+ VALID_STREAM(str, return);
g_return_if_fail(str->file_mode != filemode_Read);
write_buffer_to_stream_uni(str, buf, len);
glsi32 ch2 = utf8? read_utf8_char_from_file(fp) :
read_ucs4be_char_from_file(fp);
if(ch2 != 0x0A)
- fseek(fp, utf8? -1 : -4, SEEK_CUR);
+ if(fseek(fp, utf8? -1 : -4, SEEK_CUR) == -1);
+ WARNING_S("Seek failed on stream", g_strerror(errno) );
return TRUE;
}
return FALSE;
return ch;
}
default:
- g_warning("%s: Reading from this kind of stream unsupported.", __func__);
+ ILLEGAL_PARAM("Reading illegal on stream type: %u", str->type);
return -1;
}
}
glsi32
glk_get_char_stream(strid_t str)
{
- g_return_val_if_fail(str != NULL, -1);
+ VALID_STREAM(str, return -1);
g_return_val_if_fail(str->file_mode == filemode_Read || str->file_mode == filemode_ReadWrite, -1);
glsi32 ch = get_char_stream_common(str);
glsi32
glk_get_char_stream_uni(strid_t str)
{
- g_return_val_if_fail(str != NULL, -1);
+ VALID_STREAM(str, return -1);
g_return_val_if_fail(str->file_mode == filemode_Read || str->file_mode == filemode_ReadWrite, -1);
return get_char_stream_common(str);
glui32
glk_get_buffer_stream(strid_t str, char *buf, glui32 len)
{
- g_return_val_if_fail(str != NULL, 0);
+ VALID_STREAM(str, return 0);
g_return_val_if_fail(str->file_mode == filemode_Read || str->file_mode == filemode_ReadWrite, 0);
g_return_val_if_fail(buf != NULL, 0);
if(count % 4 != 0)
{
count -= count % 4;
- g_warning("%s: Incomplete character in binary Unicode file.", __func__);
+ WARNING("Incomplete character in binary Unicode file");
}
int foo;
return foo;
}
default:
- g_warning("%s: Reading from this kind of stream unsupported.", __func__);
+ ILLEGAL_PARAM("Reading illegal on stream type: %u", str->type);
return 0;
}
}
glui32
glk_get_buffer_stream_uni(strid_t str, glui32 *buf, glui32 len)
{
- g_return_val_if_fail(str != NULL, 0);
+ VALID_STREAM(str, return 0);
g_return_val_if_fail(str->file_mode == filemode_Read || str->file_mode == filemode_ReadWrite, 0);
g_return_val_if_fail(buf != NULL, 0);
if(count % 4 != 0)
{
count -= count % 4;
- g_warning("%s: Incomplete character in binary Unicode file.", __func__);
+ WARNING("Incomplete character in binary Unicode file");
}
int foo;
return foo;
}
default:
- g_warning("%s: Reading from this kind of stream unsupported.", __func__);
+ ILLEGAL_PARAM("Reading illegal on stream type: %u", str->type);
return 0;
}
}
glui32
glk_get_line_stream(strid_t str, char *buf, glui32 len)
{
- g_return_val_if_fail(str != NULL, 0);
+ VALID_STREAM(str, return 0);
g_return_val_if_fail(str->file_mode == filemode_Read || str->file_mode == filemode_ReadWrite, 0);
g_return_val_if_fail(buf != NULL, 0);
return foo;
}
default:
- g_warning("%s: Reading from this kind of stream unsupported.", __func__);
+ ILLEGAL_PARAM("Reading illegal on stream type: %u", str->type);
return 0;
}
}
glui32
glk_get_line_stream_uni(strid_t str, glui32 *buf, glui32 len)
{
- g_return_val_if_fail(str != NULL, 0);
+ VALID_STREAM(str, return 0);
g_return_val_if_fail(str->file_mode == filemode_Read || str->file_mode == filemode_ReadWrite, 0);
g_return_val_if_fail(buf != NULL, 0);
return foo;
}
default:
- g_warning("%s: Reading from this kind of stream unsupported.", __func__);
+ ILLEGAL_PARAM("Reading illegal on stream type: %u", str->type);
return 0;
}
}
glui32
glk_stream_get_position(strid_t str)
{
- g_return_val_if_fail(str != NULL, 0);
+ VALID_STREAM(str, return 0);
switch(str->type)
{
case STREAM_TYPE_FILE:
return ftell(str->file_pointer);
default:
- g_warning("%s: Seeking not supported on this type of stream.",
- __func__);
+ ILLEGAL_PARAM("Seeking illegal on stream type: %u", str->type);
return 0;
}
}
void
glk_stream_set_position(strid_t str, glsi32 pos, glui32 seekmode)
{
- g_return_if_fail(str != NULL);
+ VALID_STREAM(str, return);
g_return_if_fail(!(seekmode == seekmode_Start && pos < 0));
g_return_if_fail(!(seekmode == seekmode_End || pos > 0));
case seekmode_Current: str->mark += pos; break;
case seekmode_End: str->mark = str->buflen + pos; break;
default:
- g_assert_not_reached();
+ g_return_if_reached();
return;
}
break;
case seekmode_Current: whence = SEEK_CUR; break;
case seekmode_End: whence = SEEK_END; break;
default:
- g_assert_not_reached();
+ g_return_if_reached();
return;
}
- fseek(str->file_pointer, pos, whence);
+ if(fseek(str->file_pointer, pos, whence) == -1)
+ WARNING("Seek failed on file stream");
break;
}
default:
- g_warning("%s: Seeking not supported on this type of stream.", __func__);
+ ILLEGAL_PARAM("Seeking illegal on stream type: %u", str->type);
return;
}
}
#include "window.h"
+#include "magic.h"
#include "chimara-glk-private.h"
extern ChimaraGlkPrivate *glk_data;
winid_t
glk_window_iterate(winid_t win, glui32 *rockptr)
{
+ VALID_WINDOW_OR_NULL(win, return NULL);
+
GNode *retnode;
if(win == NULL)
glui32
glk_window_get_rock(winid_t win)
{
- g_return_val_if_fail(win != NULL, 0);
+ VALID_WINDOW(win, return 0);
return win->rock;
}
glui32
glk_window_get_type(winid_t win)
{
- g_return_val_if_fail(win != NULL, 0);
+ VALID_WINDOW(win, return 0);
return win->type;
}
winid_t
glk_window_get_parent(winid_t win)
{
- g_return_val_if_fail(win != NULL, NULL);
+ VALID_WINDOW(win, return NULL);
/* Value will also be NULL if win is the root window */
return (winid_t)win->window_node->parent->data;
}
winid_t
glk_window_get_sibling(winid_t win)
{
- g_return_val_if_fail(win != NULL, NULL);
+ VALID_WINDOW(win, return NULL);
if(G_NODE_IS_ROOT(win->window_node))
return NULL;
glk_window_open(winid_t split, glui32 method, glui32 size, glui32 wintype,
glui32 rock)
{
- /*
- if(split)
- {
- g_warning("glk_window_open: splitting of windows not implemented");
- return NULL;
- }
- */
+ VALID_WINDOW_OR_NULL(split, return NULL);
if(split == NULL && glk_data->root_window != NULL)
{
- g_warning("glk_window_open: there is already a root window");
+ ILLEGAL("Tried to open a new root window, but there is already a root window");
return NULL;
}
/* We only create one window and don't support any more than that */
winid_t win = g_new0(struct glk_window_struct, 1);
+ win->magic = MAGIC_WINDOW;
win->rock = rock;
win->type = wintype;
win->window_node = g_node_new(win);
default:
gdk_threads_leave();
- g_warning("%s: unsupported window type", __func__);
+ ILLEGAL_PARAM("Unknown window type: %u", wintype);
g_free(win);
g_node_destroy(glk_data->root_window);
glk_data->root_window = NULL;
void
glk_window_close(winid_t win, stream_result_t *result)
{
+ VALID_WINDOW(win, return);
+
GNode* parent_node;
- g_return_if_fail(win != NULL);
-
gdk_threads_enter();
switch(win->type)
break;
default:
- g_warning("%s: unsupported window type", __func__);
+ ILLEGAL_PARAM("Unknown window type: %u", win->type);
gdk_threads_leave();
return;
}
glk_data->root_window = parent_node->next;
else if(parent_node->prev)
glk_data->root_window = parent_node->prev;
- } else {
+ }
+ else
+ {
if(parent_node->next)
g_node_append(parent_node->parent, parent_node->next);
else if(parent_node->prev)
}
g_node_destroy(win->window_node);
+ win->magic = MAGIC_FREE;
g_free(win);
gdk_threads_leave();
void
glk_window_clear(winid_t win)
{
- g_return_if_fail(win != NULL);
+ VALID_WINDOW(win, return);
g_return_if_fail(win->input_request_type != INPUT_REQUEST_LINE && win->input_request_type != INPUT_REQUEST_LINE_UNICODE);
switch(win->type)
break;
default:
- g_warning("glk_window_clear: unsupported window type");
+ ILLEGAL_PARAM("Unknown window type: %d", win->type);
}
}
void
glk_set_window(winid_t win)
{
+ VALID_WINDOW_OR_NULL(win, return);
glk_stream_set_current( glk_window_get_stream(win) );
}
*/
strid_t glk_window_get_stream(winid_t win)
{
- g_return_val_if_fail(win != NULL, NULL);
+ VALID_WINDOW(win, return NULL);
return win->window_stream;
}
void
glk_window_set_echo_stream(winid_t win, strid_t str)
{
- g_return_if_fail(win != NULL);
+ VALID_WINDOW(win, return);
+ VALID_STREAM_OR_NULL(str, return);
/* Test for an infinite loop */
strid_t next = str;
{
if(next == win->window_stream)
{
- g_warning("%s: Infinite loop detected", __func__);
+ ILLEGAL("Infinite loop detected");
win->echo_stream = NULL;
return;
}
strid_t
glk_window_get_echo_stream(winid_t win)
{
- g_return_val_if_fail(win != NULL, NULL);
+ VALID_WINDOW(win, return NULL);
return win->echo_stream;
}
void
glk_window_get_size(winid_t win, glui32 *widthptr, glui32 *heightptr)
{
- g_return_if_fail(win != NULL);
+ VALID_WINDOW(win, return);
switch(win->type)
{
break;
default:
- g_warning("glk_window_get_size: Unsupported window type");
+ ILLEGAL_PARAM("Unknown window type: %u", win->type);
}
}
void
glk_window_move_cursor(winid_t win, glui32 xpos, glui32 ypos)
{
- g_return_if_fail(win != NULL);
+ VALID_WINDOW(win, return);
g_return_if_fail(win->type == wintype_TextGrid);
/* Calculate actual position if cursor is moved past the right edge */
struct glk_window_struct
{
/*< private >*/
- glui32 rock;
+ glui32 magic, rock;
/* Pointer to the node in the global tree that contains this window */
GNode *window_node;
/* Window parameters */