* Added initial support for styles! (no style hints as of yet though)
authorrodin <rodin@ddfedd41-794f-dd11-ae45-00112f111e67>
Fri, 22 May 2009 20:09:30 +0000 (20:09 +0000)
committerrodin <rodin@ddfedd41-794f-dd11-ae45-00112f111e67>
Fri, 22 May 2009 20:09:30 +0000 (20:09 +0000)
 * Added glkstart.c, a dummy file to help us implement the unixstart functionality

12 files changed:
src/Makefile.am
src/chimara-glk-private.h
src/chimara-glk.c
src/glkstart.c [new file with mode: 0644]
src/main.c
src/stream.c
src/stream.h
src/strio.c
src/style.c
src/style.h [new file with mode: 0644]
src/window.c
src/window.h

index 29d42f74dada269ef7132096d96461f4fe92e8b1..4a2806e02a6b2302abfab7cc6e9e6917d2994f5d 100644 (file)
@@ -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\"
index 9520f1b909fcf0e08e8ec21e06b9a67fd0ab449c..ba638a0e6e8496833c41f457ca1851ef73171023 100644 (file)
@@ -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) \
index 14d1e44801f7b73e0c76c41bdded91eeeb7d0c3f..16e674969c10f9ae9feaf92804261b0b4414c8d5 100644 (file)
@@ -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 (file)
index 0000000..e9baf36
--- /dev/null
@@ -0,0 +1,24 @@
+/* glkstart.c: Unix-specific startup code -- sample file.
+    Designed by Andrew Plotkin <erkyrath@eblong.com>
+    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;
+}
+
index 936255952e6a914f53ab4b93fb27ee58f46b685a..c34e4c5f8883a1dd548041257d11f0c6b6d365d0 100644 (file)
@@ -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;
     }
index 42d77babc8aae0b68c71d80049c3849256d178ed..804399213ae7cbe87ebcbb96134130d5d4d51dd6 100644 (file)
@@ -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;
 }
 
index 578b1403ba8e3a68edd2dfb3ddec7c9b23ce32a7..0ea398e377fc98bf561e629ac9ce4434e4527fdc 100644 (file)
@@ -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);
index e30d52bdda39638a6eb1529e0c974b065cb8a695..921b75cc771f0331828220061dbfc9030726fcd1 100644 (file)
@@ -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();
 }
index bce151662326275c8c91563f92a33fe3b7a9e24b..d2eb235d698209463bc61cef27b042a41bcb7319 100644 (file)
@@ -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 (file)
index 0000000..fcd5302
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef STYLE_H
+#define STYLE_H
+
+#include <gtk/gtk.h>
+#include "glk.h"
+#include "magic.h"
+#include "chimara-glk-private.h"
+#include "stream.h"
+
+G_GNUC_INTERNAL void style_init_textbuffer(GtkTextBuffer *buffer);
+
+#endif
index 719816f58eeb77c1567228379c7e192b0f61c76a..5f2bd5b349673bb2b46a755e46c3da8906c93240 100644 (file)
@@ -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);
index 39c43149f9d6819e225cffd8d29279803e1c4325..b3b824a7a09a5782be52199ebdbad13d7c485e71 100644 (file)
@@ -8,6 +8,8 @@
 #include "error.h"
 #include "callbacks.h"
 #include "input.h"
+#include "style.h"
+
 
 enum InputRequestType
 {