From 5a06246277a255fe6e0e465ce0f190541b7b0e16 Mon Sep 17 00:00:00 2001 From: Marijn van Vliet Date: Fri, 22 May 2009 20:09:30 +0000 Subject: [PATCH] * Added initial support for styles! (no style hints as of yet though) * Added glkstart.c, a dummy file to help us implement the unixstart functionality git-svn-id: http://lassie.dyndns-server.com/svn/gargoyle-gtk@72 ddfedd41-794f-dd11-ae45-00112f111e67 --- src/Makefile.am | 2 +- src/chimara-glk-private.h | 2 +- src/chimara-glk.c | 2 +- src/glkstart.c | 24 +++++ src/main.c | 2 +- src/stream.c | 1 + src/stream.h | 2 + src/strio.c | 2 +- src/style.c | 197 +++++++++++++++++++++++++++++++++++++- src/style.h | 12 +++ src/window.c | 3 + src/window.h | 2 + 12 files changed, 242 insertions(+), 9 deletions(-) create mode 100644 src/glkstart.c create mode 100644 src/style.h diff --git a/src/Makefile.am b/src/Makefile.am index 29d42f7..4a2806e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -29,11 +29,11 @@ libchimara_la_SOURCES = \ input.c input.h \ stream.c stream.h \ strio.c \ - style.c \ timer.c timer.h \ window.c window.h \ gi_blorb.c gi_blorb.h \ resource.c resource.h \ + style.c style.h \ glkstart.h libchimara_la_CPPFLAGS = \ -DG_LOG_DOMAIN=\"Chimara\" diff --git a/src/chimara-glk-private.h b/src/chimara-glk-private.h index 9520f1b..ba638a0 100644 --- a/src/chimara-glk-private.h +++ b/src/chimara-glk-private.h @@ -52,7 +52,7 @@ struct _ChimaraGlkPrivate { /* Current resource blorb map */ giblorb_map_t *resource_map; /* File stream pointing to the blorb used as current resource map */ - strid_t *resource_file; + strid_t resource_file; }; #define CHIMARA_GLK_PRIVATE(obj) \ diff --git a/src/chimara-glk.c b/src/chimara-glk.c index 14d1e44..16e6749 100644 --- a/src/chimara-glk.c +++ b/src/chimara-glk.c @@ -923,7 +923,7 @@ chimara_glk_run(ChimaraGlk *glk, gchar *plugin, GError **error) /* Set the thread's private data */ /* TODO: Do this with a GPrivate */ glk_data = priv; - + /* Run in a separate thread */ priv->thread = g_thread_create(glk_enter, glk_main, TRUE, error); diff --git a/src/glkstart.c b/src/glkstart.c new file mode 100644 index 0000000..e9baf36 --- /dev/null +++ b/src/glkstart.c @@ -0,0 +1,24 @@ +/* glkstart.c: Unix-specific startup code -- sample file. + Designed by Andrew Plotkin + http://www.eblong.com/zarf/glk/index.html + + This is Unix startup code for the simplest possible kind of Glk + program -- no command-line arguments; no startup files; no nothing. + + Remember, this is a sample file. You should copy it into the Glk + program you are compiling, and modify it to your needs. This should + *not* be compiled into the Glk library itself. +*/ + +#include "glk.h" +#include "glkstart.h" + +glkunix_argumentlist_t glkunix_arguments[] = { + { NULL, glkunix_arg_End, NULL } +}; + +int glkunix_startup_code(glkunix_startup_t *data) +{ + return TRUE; +} + diff --git a/src/main.c b/src/main.c index 9362559..c34e4c5 100644 --- a/src/main.c +++ b/src/main.c @@ -118,7 +118,7 @@ main(int argc, char *argv[]) g_object_unref( G_OBJECT(builder) ); - if( !chimara_glk_run(CHIMARA_GLK(glk), "../interpreters/nitfol/.libs/nitfol.so", &error) ) { + if( !chimara_glk_run(CHIMARA_GLK(glk), ".libs/first.so", &error) ) { error_dialog(GTK_WINDOW(window), error, "Error starting Glk library: "); return 1; } diff --git a/src/stream.c b/src/stream.c index 42d77ba..8043992 100644 --- a/src/stream.c +++ b/src/stream.c @@ -33,6 +33,7 @@ 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; + str->style = "normal"; return str; } diff --git a/src/stream.h b/src/stream.h index 578b140..0ea398e 100644 --- a/src/stream.h +++ b/src/stream.h @@ -43,6 +43,8 @@ struct glk_stream_struct FILE *file_pointer; gboolean binary; gchar *filename; /* Displayable filename in UTF-8 for error handling */ + + gchar *style; /* Name of the current style */ }; G_GNUC_INTERNAL strid_t window_stream_new(winid_t window); diff --git a/src/strio.c b/src/strio.c index e30d52b..921b75c 100644 --- a/src/strio.c +++ b/src/strio.c @@ -77,7 +77,7 @@ write_utf8_to_window(winid_t win, gchar *s) GtkTextIter iter; gtk_text_buffer_get_end_iter(buffer, &iter); - gtk_text_buffer_insert(buffer, &iter, s, -1); + gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, s, -1, win->window_stream->style, NULL); gdk_threads_leave(); } diff --git a/src/style.c b/src/style.c index bce1516..d2eb235 100644 --- a/src/style.c +++ b/src/style.c @@ -1,8 +1,197 @@ -#include "glk.h" +#include "style.h" +extern ChimaraGlkPrivate *glk_data; + +/** + * glk_set_style: + * @styl The style to apply + * + * This changes the style of the current output stream. After a style change, + * new text which is printed to that stream will be given the new style. For a + * window stream, the text will appear in that style. For other types of + * streams, this has no effect. + */ +void +glk_set_style(glui32 style) +{ + g_return_if_fail(glk_data->current_stream != NULL); + glk_set_style_stream(glk_data->current_stream, style); +} + +/* Internal function: mapping from style enum to tag name */ +gchar* +get_tag_name(glui32 style) +{ + switch(style) { + case style_Normal: return "normal"; + case style_Emphasized: return "emphasized"; + case style_Preformatted: return "preformatted"; + case style_Header: return "header"; + case style_Subheader: return "subheader"; + case style_Alert: return "alert"; + case style_Note: return "note"; + case style_BlockQuote: return "block-quote"; + case style_Input: return "input"; + case style_User1: return "user1"; + case style_User2: return "user2"; + } + + WARNING("Unsupported style"); + return "normal"; +} + +void +glk_set_style_stream(strid_t stream, glui32 style) { + stream->style = get_tag_name(style); +} + +/* Internal function: call this to initialize the default styles to a textbuffer. */ void -glk_set_style(glui32 styl) +style_init_textbuffer(GtkTextBuffer *buffer) { - /* No nothing yet */ - return; + g_return_if_fail(buffer != NULL); + + gtk_text_buffer_create_tag(buffer, "normal", NULL); + gtk_text_buffer_create_tag(buffer, "emphasized", "style", PANGO_STYLE_ITALIC, NULL); + gtk_text_buffer_create_tag(buffer, "preformatted", "font-desc", glk_data->monospace_font_desc, NULL); + gtk_text_buffer_create_tag(buffer, "header", "size-points", 16.0, "weight", PANGO_WEIGHT_BOLD, NULL); + gtk_text_buffer_create_tag(buffer, "subheader", "size-points", 12.0, "weight", PANGO_WEIGHT_BOLD, NULL); + gtk_text_buffer_create_tag(buffer, "alert", "foreground", "#aa0000", "weight", PANGO_WEIGHT_BOLD, NULL); + gtk_text_buffer_create_tag(buffer, "note", "foreground", "#aaaa00", "weight", PANGO_WEIGHT_BOLD, NULL); + gtk_text_buffer_create_tag(buffer, "block-quote", "justification", GTK_JUSTIFY_CENTER, "style", PANGO_STYLE_ITALIC, NULL); + gtk_text_buffer_create_tag(buffer, "input", NULL); + gtk_text_buffer_create_tag(buffer, "user1", NULL); + gtk_text_buffer_create_tag(buffer, "user2", NULL); +} + +void +color_format(glui32 val, gchar *buffer) +{ + sprintf(buffer, "#%02X%02X%02X", + ((val & 0xff0000) >> 16), + ((val & 0x00ff00) >> 8), + (val & 0x0000ff) + ); +} + +/* Internal function: changes a GTK tag to correspond with the given style. */ +void +apply_stylehint_to_tag(GtkTextTag *tag, glui32 hint, glsi32 val) +{ + g_return_if_fail(tag != NULL); + + GObject *tag_object = G_OBJECT(tag); + gint reverse_color = 0; + + /* FIXME where should we keep track of this? + g_object_get(tag, "reverse_color", &reverse_color, NULL); + */ + + int i = 0; + gchar color[20]; + switch(hint) { + case stylehint_Indentation: + g_object_set(tag_object, "left_margin", 5*val, NULL); + g_object_set(tag_object, "right_margin", 5*val, NULL); + break; + + case stylehint_ParaIndentation: + g_object_set(tag_object, "indent", 5*val, NULL); + break; + + case stylehint_Justification: + switch(val) { + case stylehint_just_LeftFlush: i = GTK_JUSTIFY_LEFT; break; + case stylehint_just_LeftRight: i = GTK_JUSTIFY_FILL; break; + case stylehint_just_Centered: i = GTK_JUSTIFY_CENTER; break; + case stylehint_just_RightFlush: i = GTK_JUSTIFY_RIGHT; break; + default: + WARNING("Unknown justification"); + i = GTK_JUSTIFY_LEFT; + } + g_object_set(tag_object, "justification", i, NULL); + break; + + case stylehint_Weight: + switch(val) { + case -1: i = PANGO_WEIGHT_LIGHT; break; + case 0: i = PANGO_WEIGHT_NORMAL; break; + case 1: i = PANGO_WEIGHT_BOLD; break; + default: WARNING("Unknown font weight"); + } + g_object_set(tag_object, "weight", i, NULL); + break; + + case stylehint_Size: + g_object_set(tag_object, "size", 14+(2*val), NULL); + break; + + case stylehint_Oblique: + g_object_set(tag_object, "style", val ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL, NULL); + break; + + case stylehint_Proportional: + g_object_set(tag_object, "font-desc", val ? glk_data->default_font_desc : glk_data->monospace_font_desc, NULL); + break; + + case stylehint_TextColor: + color_format(val, color); + + if(!reverse_color) + g_object_set(tag_object, "foreground", color, NULL); + else + g_object_set(tag_object, "background", color, NULL); + + break; + + case stylehint_BackColor: + color_format(val, color); + + if(!reverse_color) + g_object_set(tag_object, "background", color, NULL); + else + g_object_set(tag_object, "foreground", color, NULL); + + break; + + case stylehint_ReverseColor: + if(reverse_color != val) { + /* Flip the fore- and background colors */ + gchar* foreground_color; + gchar* background_color; + g_object_get(tag_object, "foreground", &foreground_color, NULL); + g_object_get(tag_object, "background", &background_color, NULL); + g_object_set(tag_object, "foreground", background_color, NULL); + g_object_set(tag_object, "background", foreground_color, NULL); + g_free(foreground_color); + g_free(background_color); + } + break; + + default: + WARNING("Unknown style hint"); + } +} + +void +glk_stylehint_set(glui32 wintype, glui32 style, glui32 hint, glsi32 val) +{ + + gchar *tag_name = get_tag_name(style); + + /* Iterate over all the window and update their styles if nessecary */ + winid_t win = glk_window_iterate(NULL, NULL); + while(win != NULL) { + if(wintype != wintype_TextBuffer) + continue; /* FIXME: add support for text grid windows */ + + if(wintype == wintype_AllTypes || glk_window_get_type(win) == wintype) { + GtkWidget *textview = win->widget; + GtkTextBuffer *textbuffer = gtk_text_view_get_buffer( GTK_TEXT_VIEW(textview) ); + GtkTextTagTable *table = gtk_text_buffer_get_tag_table(textbuffer); + GtkTextTag *to_change = gtk_text_tag_table_lookup(table, tag_name); + + apply_stylehint_to_tag(to_change, hint, val); + } + } } diff --git a/src/style.h b/src/style.h new file mode 100644 index 0000000..fcd5302 --- /dev/null +++ b/src/style.h @@ -0,0 +1,12 @@ +#ifndef STYLE_H +#define STYLE_H + +#include +#include "glk.h" +#include "magic.h" +#include "chimara-glk-private.h" +#include "stream.h" + +G_GNUC_INTERNAL void style_init_textbuffer(GtkTextBuffer *buffer); + +#endif diff --git a/src/window.c b/src/window.c index 719816f..5f2bd5b 100644 --- a/src/window.c +++ b/src/window.c @@ -486,6 +486,9 @@ glk_window_open(winid_t split, glui32 method, glui32 size, glui32 wintype, (for line input) */ gtk_text_buffer_create_tag(textbuffer, "uneditable", "editable", FALSE, "editable-set", TRUE, NULL); + /* Create the default styles available to the window stream */ + style_init_textbuffer(textbuffer); + /* Mark the position where the user will input text */ GtkTextIter end; gtk_text_buffer_get_end_iter(textbuffer, &end); diff --git a/src/window.h b/src/window.h index 39c4314..b3b824a 100644 --- a/src/window.h +++ b/src/window.h @@ -8,6 +8,8 @@ #include "error.h" #include "callbacks.h" #include "input.h" +#include "style.h" + enum InputRequestType { -- 2.30.2