From: P. F. Chimento Date: Sun, 30 Jan 2011 15:41:28 +0000 (+0100) Subject: Merge branch 'master' of github.com:wmvanvliet/Chimara X-Git-Tag: v0.9~153 X-Git-Url: https://git.stderr.nl/gitweb?a=commitdiff_plain;h=bf5bc4b0d129685482eefea499f39f874744e2fd;hp=edf59e1a751771655752b61e211053e08a8cbe3a;p=projects%2Fchimara%2Fchimara.git Merge branch 'master' of github.com:wmvanvliet/Chimara Conflicts: player/style.css --- diff --git a/libchimara/garglk.c b/libchimara/garglk.c index 19be504..9e503b3 100644 --- a/libchimara/garglk.c +++ b/libchimara/garglk.c @@ -1,8 +1,12 @@ +#include #include +#include #include #include "chimara-glk-private.h" #include "stream.h" #include "fileref.h" +#include "style.h" +#include "garglk.h" extern GPrivate *glk_data_key; @@ -162,8 +166,128 @@ garglk_unput_string_uni(glui32 *str) void garglk_set_zcolors_stream(strid_t str, glui32 fg, glui32 bg) { +#ifdef DEBUG_STYLES + g_printf("garglk_set_zcolors_stream(str->rock=%d, fg=%08X, bg=%08X)\n", str->rock, fg, bg); +#endif + VALID_STREAM(str, return); - WARNING(_("Not implemented")); + g_return_if_fail(str->window != NULL); + + winid_t window = str->window; + + gdk_threads_enter(); + + GtkTextBuffer *buffer = gtk_text_view_get_buffer( GTK_TEXT_VIEW(window->widget) ); + GtkTextTagTable *tags = gtk_text_buffer_get_tag_table(buffer); + GdkColor fore, back; + GdkColor *fore_pointer = NULL; + GdkColor *back_pointer = NULL; + gchar *fore_name; + gchar *back_name; + + switch(fg) { + case zcolor_Transparent: + case zcolor_Cursor: + WARNING(_("zcolor_Transparent, zcolor_Cursor not implemented")); + // Fallthrough to default + case zcolor_Default: + fore_name = g_strdup("default"); + break; + case zcolor_Current: + { + if(window->zcolor) { + // Get the current foreground color + GdkColor *current_color; + g_object_get(window->zcolor, "foreground-gdk", ¤t_color, NULL); + fore_name = gdkcolor_to_hex(current_color); + + // Copy the color and use it + fore.red = current_color->red; + fore.green = current_color->green; + fore.blue = current_color->blue; + fore_pointer = &fore; + } else { + fore_name = g_strdup("default"); + } + break; + } + default: + glkcolor_to_gdkcolor(fg, &fore); + fore_pointer = &fore; + fore_name = glkcolor_to_hex(fg); + } + + switch(bg) { + case zcolor_Transparent: + case zcolor_Cursor: + WARNING(_("zcolor_Transparent, zcolor_Cursor not implemented")); + // Fallthrough to default + case zcolor_Default: + back_name = g_strdup("default"); + break; + case zcolor_Current: + { + if(window->zcolor) { + // Get the current background color + GdkColor *current_color; + g_object_get(window->zcolor, "background-gdk", ¤t_color, NULL); + back_name = gdkcolor_to_hex(current_color); + + // Copy the color and use it + back.red = current_color->red; + back.green = current_color->green; + back.blue = current_color->blue; + back_pointer = &back; + } else { + back_name = g_strdup("default"); + } + break; + } + default: + glkcolor_to_gdkcolor(bg, &back); + back_pointer = &back; + back_name = glkcolor_to_hex(bg); + } + + if(fore_pointer == NULL && back_pointer == NULL) { + // NULL value means to ignore the zcolor property altogether + window->zcolor = NULL; + } else { + char *name = g_strdup_printf("zcolor:#%s/#%s", fore_name, back_name); + g_free(fore_name); + g_free(back_name); + + // See if we have used this color combination before + GtkTextTag *tag = gtk_text_tag_table_lookup(tags, name); + + if(tag == NULL) { + // Create a new texttag with the specified colors + tag = gtk_text_buffer_create_tag( + buffer, + name, + "foreground-gdk", fore_pointer, + "foreground-set", fore_pointer != NULL, + "background-gdk", back_pointer, + "background-set", back_pointer != NULL, + NULL + ); + } + + // From now on, text will be drawn in the specified colors + window->zcolor = tag; + + // Update the reversed version if necessary + if(str->window->zcolor_reversed) { + gint reversed = GPOINTER_TO_INT( g_object_get_data( G_OBJECT(str->window->zcolor_reversed), "reverse-color" ) ); + + gdk_threads_leave(); + garglk_set_reversevideo_stream(str, reversed != 0); + gdk_threads_enter(); + } + + } + + gdk_threads_leave(); } /** @@ -184,30 +308,79 @@ garglk_set_zcolors(glui32 fg, glui32 bg) { ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key); g_return_if_fail(glk_data->current_stream != NULL); - g_return_if_fail(glk_data->current_stream->window != NULL); - - garglk_set_zcolors_stream(glk_data->current_stream, fg, bg); -} -static void -apply_reverse_color(GtkTextTag *tag, gpointer data) -{ - const gchar *tag_name; - g_object_get(tag, "name", &tag_name, NULL); - - if( g_str_has_prefix(tag_name, "glk-") ) - g_object_set_data( G_OBJECT(tag), "reverse_color", data ); + garglk_set_zcolors_stream(glk_data->current_stream, fg, bg); } /* TODO document */ void garglk_set_reversevideo_stream(strid_t str, glui32 reverse) { +#ifdef DEBUG_STYLES + g_printf("garglk_set_reversevideo_stream(str->rock=%d, reverse=%d)\n", str->rock, reverse); +#endif + VALID_STREAM(str, return); + g_return_if_fail(str->window != NULL); + g_return_if_fail(str->window->type != wintype_TextBuffer || str->window->type != wintype_TextGrid); + + // Determine the current colors - GtkTextBuffer *buffer = gtk_text_view_get_buffer( GTK_TEXT_VIEW(str->window->widget) ); + // If all fails, use black/white + // FIXME: Use system theme here + GdkColor foreground, background; + gdk_color_parse("black", &foreground); + gdk_color_parse("white", &background); + GdkColor *current_foreground = &foreground; + GdkColor *current_background = &background; + + gdk_threads_enter(); + + style_stream_colors(str, ¤t_foreground, ¤t_background); + + if(reverse) { + GdkColor *temp = current_foreground; + current_foreground = current_background; + current_background = temp; + } + + // Name the color + gchar *name = g_strdup_printf( + "zcolor:#%04X%04X%04X/#%04X%04X%04X", + current_foreground->red, + current_foreground->green, + current_foreground->blue, + current_background->red, + current_background->green, + current_background->blue + ); + + // Create a tag for the new colors if it doesn't exist yet + GtkTextBuffer *buffer = gtk_text_view_get_buffer( GTK_TEXT_VIEW(str->window->widget) ); GtkTextTagTable *tags = gtk_text_buffer_get_tag_table(buffer); - gtk_text_tag_table_foreach( tags, apply_reverse_color, GINT_TO_POINTER(reverse) ); + GtkTextTag *tag = gtk_text_tag_table_lookup(tags, name); + if(tag == NULL) { + tag = gtk_text_buffer_create_tag( + buffer, + name, + "foreground-gdk", current_foreground, + "foreground-set", TRUE, + "background-gdk", current_background, + "background-set", TRUE, + NULL + ); + g_object_set_data( G_OBJECT(tag), "reverse-color", GINT_TO_POINTER(reverse) ); + } + + // From now on, text will be drawn in the specified colors + str->window->zcolor_reversed = tag; + + // Update the background of the gtktextview to correspond with the current background color + if(current_background != NULL) { + gtk_widget_modify_base(str->window->widget, GTK_STATE_NORMAL, current_background); + } + + gdk_threads_leave(); } /** diff --git a/libchimara/strio.c b/libchimara/strio.c index b1df8ae..d440832 100644 --- a/libchimara/strio.c +++ b/libchimara/strio.c @@ -31,6 +31,9 @@ write_utf8_to_window_buffer(winid_t win, gchar *s) void flush_window_buffer(winid_t win) { +#ifdef DEBUG_STYLES + g_printf("%s\n", win->buffer->str); +#endif if(win->type != wintype_TextBuffer && win->type != wintype_TextGrid) return; @@ -44,20 +47,45 @@ flush_window_buffer(winid_t win) switch(win->type) { case wintype_TextBuffer: { - GtkTextIter iter; - gtk_text_buffer_get_end_iter(buffer, &iter); + GtkTextIter start, end; + gtk_text_buffer_get_end_iter(buffer, &end); + gint start_offset; GtkTextTagTable *tags = gtk_text_buffer_get_tag_table(buffer); + GtkTextTag *default_tag = gtk_text_tag_table_lookup(tags, "default"); GtkTextTag *style_tag = gtk_text_tag_table_lookup(tags, win->window_stream->style); GtkTextTag *glk_style_tag = gtk_text_tag_table_lookup(tags, win->window_stream->glk_style); + start_offset = gtk_text_iter_get_offset(&end); + gtk_text_buffer_insert(buffer, &end, win->buffer->str, -1); + gtk_text_buffer_get_iter_at_offset(buffer, &start, start_offset); + + // Default style + gtk_text_buffer_apply_tag(buffer, default_tag, &start, &end); + + // Player's style overrides + gtk_text_buffer_apply_tag(buffer, style_tag, &start, &end); + + // GLK Program's style overrides + gtk_text_buffer_apply_tag(buffer, glk_style_tag, &start, &end); + + // Link style overrides if(win->window_stream->hyperlink_mode) { GtkTextTag *link_style_tag = gtk_text_tag_table_lookup(tags, "hyperlink"); GtkTextTag *link_tag = win->current_hyperlink->tag; - gtk_text_buffer_insert_with_tags(buffer, &iter, win->buffer->str, -1, default_tag, style_tag, glk_style_tag, link_style_tag, link_tag, NULL); - } else { - gtk_text_buffer_insert_with_tags(buffer, &iter, win->buffer->str, -1, default_tag, style_tag, glk_style_tag, NULL); + gtk_text_buffer_apply_tag(buffer, link_style_tag, &start, &end); + gtk_text_buffer_apply_tag(buffer, link_tag, &start, &end); + } + + // GLK Program's style overrides using garglk_set_zcolors() + if(win->zcolor != NULL) { + gtk_text_buffer_apply_tag(buffer, win->zcolor, &start, &end); + } + + // GLK Program's style overrides using garglk_set_reversevideo() + if(win->zcolor_reversed != NULL) { + gtk_text_buffer_apply_tag(buffer, win->zcolor_reversed, &start, &end); } ChimaraGlk *glk = CHIMARA_GLK(gtk_widget_get_ancestor(win->widget, CHIMARA_TYPE_GLK)); @@ -75,51 +103,91 @@ flush_window_buffer(winid_t win) GtkTextMark *cursor = gtk_text_buffer_get_mark(buffer, "cursor_position"); /* Get cursor position */ - GtkTextIter start; - gtk_text_buffer_get_iter_at_mark(buffer, &start, cursor); + GtkTextIter start, insert; + gint start_offset; + + gtk_text_buffer_get_iter_at_mark(buffer, &insert, cursor); /* Spaces available on this line */ - gint available_space = win->width - gtk_text_iter_get_line_offset(&start); + gint available_space = win->width - gtk_text_iter_get_line_offset(&insert); - while(chars_left > available_space && !gtk_text_iter_is_end(&start)) + GtkTextTagTable *tags = gtk_text_buffer_get_tag_table(buffer); + GtkTextTag *default_tag = gtk_text_tag_table_lookup(tags, "default"); + GtkTextTag *style_tag = gtk_text_tag_table_lookup(tags, win->window_stream->style); + GtkTextTag *glk_style_tag = gtk_text_tag_table_lookup(tags, win->window_stream->glk_style); + GtkTextTag *link_style_tag = gtk_text_tag_table_lookup(tags, "hyperlink"); + + while(chars_left > available_space && !gtk_text_iter_is_end(&insert)) { - GtkTextIter end = start; + GtkTextIter end = insert; gtk_text_iter_forward_to_line_end(&end); - gtk_text_buffer_delete(buffer, &start, &end); + gtk_text_buffer_delete(buffer, &insert, &end); + + start_offset = gtk_text_iter_get_offset(&insert); + gtk_text_buffer_insert(buffer, &insert, win->buffer->str + (length - chars_left), available_space); + gtk_text_buffer_get_iter_at_offset(buffer, &start, start_offset); + + // Default style + gtk_text_buffer_apply_tag(buffer, default_tag, &start, &insert); + + // Player's style overrides + gtk_text_buffer_apply_tag(buffer, style_tag, &start, &insert); - GtkTextTagTable *tags = gtk_text_buffer_get_tag_table(buffer); - GtkTextTag *default_tag = gtk_text_tag_table_lookup(tags, "default"); - GtkTextTag *style_tag = gtk_text_tag_table_lookup(tags, win->window_stream->style); - GtkTextTag *glk_style_tag = gtk_text_tag_table_lookup(tags, win->window_stream->glk_style); + // GLK Program's style overrides + gtk_text_buffer_apply_tag(buffer, glk_style_tag, &start, &insert); + // Link style overrides if(win->window_stream->hyperlink_mode) { - GtkTextTag *link_style_tag = gtk_text_tag_table_lookup(tags, "hyperlink"); GtkTextTag *link_tag = win->current_hyperlink->tag; - gtk_text_buffer_insert_with_tags(buffer, &start, win->buffer->str + (length - chars_left), available_space, default_tag, style_tag, glk_style_tag, link_style_tag, link_tag, NULL); - } else { - gtk_text_buffer_insert_with_tags(buffer, &start, win->buffer->str + (length - chars_left), available_space, default_tag, style_tag, glk_style_tag, NULL); + gtk_text_buffer_apply_tag(buffer, link_style_tag, &start, &insert); + gtk_text_buffer_apply_tag(buffer, link_tag, &start, &insert); + } + + // GLK Program's style overrides using garglk_set_zcolors() + if(win->zcolor != NULL) + gtk_text_buffer_apply_tag(buffer, win->zcolor, &start, &insert); + + // GLK Program's style overrides using garglk_set_reversevideo() + if(win->zcolor_reversed != NULL) { + gtk_text_buffer_apply_tag(buffer, win->zcolor_reversed, &start, &insert); } chars_left -= available_space; - gtk_text_iter_forward_line(&start); + gtk_text_iter_forward_line(&insert); available_space = win->width; } - if(!gtk_text_iter_is_end(&start)) + if(!gtk_text_iter_is_end(&insert)) { - GtkTextIter end = start; + GtkTextIter end = insert; gtk_text_iter_forward_chars(&end, chars_left); - gtk_text_buffer_delete(buffer, &start, &end); + gtk_text_buffer_delete(buffer, &insert, &end); - GtkTextTagTable *tags = gtk_text_buffer_get_tag_table(buffer); - GtkTextTag *default_tag = gtk_text_tag_table_lookup(tags, "default"); - GtkTextTag *style_tag = gtk_text_tag_table_lookup(tags, win->window_stream->style); - GtkTextTag *glk_style_tag = gtk_text_tag_table_lookup(tags, win->window_stream->glk_style); + start_offset = gtk_text_iter_get_offset(&insert); + gtk_text_buffer_insert(buffer, &insert, win->buffer->str + (length - chars_left), -1); + gtk_text_buffer_get_iter_at_offset(buffer, &start, start_offset); + // Default style + gtk_text_buffer_apply_tag(buffer, default_tag, &start, &insert); + + // Player's style overrides + gtk_text_buffer_apply_tag(buffer, style_tag, &start, &insert); + + // GLK Program's style overrides + gtk_text_buffer_apply_tag(buffer, glk_style_tag, &start, &insert); + + // Link style overrides if(win->window_stream->hyperlink_mode) { - GtkTextTag *link_style_tag = gtk_text_tag_table_lookup(tags, "hyperlink"); GtkTextTag *link_tag = win->current_hyperlink->tag; - gtk_text_buffer_insert_with_tags(buffer, &start, win->buffer->str + (length - chars_left), -1, default_tag, style_tag, glk_style_tag, link_style_tag, link_tag, NULL); - } else { - gtk_text_buffer_insert_with_tags(buffer, &start, win->buffer->str + (length - chars_left), -1, default_tag, style_tag, glk_style_tag, NULL); + gtk_text_buffer_apply_tag(buffer, link_style_tag, &start, &insert); + gtk_text_buffer_apply_tag(buffer, link_tag, &start, &insert); + } + + // GLK Program's style overrides using garglk_set_zcolors() + if(win->zcolor != NULL) + gtk_text_buffer_apply_tag(buffer, win->zcolor, &start, &insert); + + // GLK Program's style overrides using garglk_set_reversevideo() + if(win->zcolor_reversed != NULL) { + gtk_text_buffer_apply_tag(buffer, win->zcolor_reversed, &start, &insert); } } diff --git a/libchimara/style.c b/libchimara/style.c index e9bfd88..0df3bbd 100644 --- a/libchimara/style.c +++ b/libchimara/style.c @@ -13,10 +13,10 @@ extern GPrivate *glk_data_key; static gboolean style_accept(GScanner *scanner, GTokenType token); static gboolean style_accept_style_selector(GScanner *scanner, ChimaraGlk *glk); static gboolean style_accept_style_hint(GScanner *scanner, GtkTextTag *current_tag); -static void style_add_tag_to_textbuffer(gpointer key, gpointer tag, gpointer tag_table); static void style_copy_tag_to_textbuffer(gpointer key, gpointer tag, gpointer target_table); static void text_tag_to_attr_list(GtkTextTag *tag, PangoAttrList *list); GtkTextTag* gtk_text_tag_copy(GtkTextTag *tag); +static void style_cascade_colors(GtkTextTag *tag, GtkTextTag *glk_tag, GtkTextTag *default_tag, GdkColor **foreground, GdkColor **background); /** * glk_set_style: @@ -111,6 +111,10 @@ get_glk_tag_name(glui32 style) */ void glk_set_style_stream(strid_t str, glui32 styl) { +#ifdef DEBUG_STYLES + g_printf("glk_set_style(str->rock=%d, styl=%d)\n", str->rock, styl); +#endif + if(str->window == NULL) return; @@ -160,17 +164,6 @@ style_init_textgrid(GtkTextBuffer *buffer) g_hash_table_foreach(glk_data->glk_styles->text_grid, style_copy_tag_to_textbuffer, gtk_text_buffer_get_tag_table(buffer)); } -/* Internal function used to iterate over the default text tag table, applying them to a textbuffer */ -static void -style_add_tag_to_textbuffer(gpointer key, gpointer tag, gpointer tag_table) -{ - g_return_if_fail(key != NULL); - g_return_if_fail(tag != NULL); - g_return_if_fail(tag_table != NULL); - - gtk_text_tag_table_add(tag_table, tag); -} - /* Internal function used to iterate over a style table, copying it */ static void style_copy_tag_to_textbuffer(gpointer key, gpointer tag, gpointer target_table) @@ -219,10 +212,11 @@ gtk_text_tag_copy(GtkTextTag *tag) #undef _COPY_FLAG /* Copy the data that was added manually */ - gpointer reverse_color = g_object_get_data( G_OBJECT(tag), "reverse_color" ); + gpointer reverse_color = g_object_get_data( G_OBJECT(tag), "reverse-color" ); - if(reverse_color) - g_object_set_data( G_OBJECT(copy), "reverse_color", reverse_color ); + if(reverse_color) { + g_object_set_data( G_OBJECT(copy), "reverse-color", reverse_color ); + } return copy; } @@ -394,21 +388,6 @@ reset_default_styles(ChimaraGlk *glk) /* TODO: write this function */ } -/* Copy the default styles to the current styles - FIXME: This function is temporary and will not be needed later on */ -void -copy_default_styles_to_current_styles(ChimaraGlk *glk) -{ - /* - CHIMARA_GLK_USE_PRIVATE(glk, priv); - g_hash_table_foreach(priv->styles->text_grid, style_table_copy, priv->glk_styles->text_grid); - g_hash_table_foreach(priv->styles->text_buffer, style_table_copy, priv->glk_styles->text_buffer); - - GtkTextTag *pager_tag = GTK_TEXT_TAG( g_hash_table_lookup(priv->styles->text_buffer, "pager") ); - text_tag_to_attr_list(pager_tag, priv->pager_attr_list); - */ -} - /* Create the CSS file scanner */ GScanner * create_css_file_scanner(void) @@ -657,19 +636,6 @@ style_accept_style_hint(GScanner *scanner, GtkTextTag *current_tag) return TRUE; } -/* Internal function: parses a glk color to a #hex-value */ -static void -glkcolor_to_hex(glui32 val, gchar *buffer) -{ - g_return_if_fail(buffer != NULL); - - sprintf(buffer, "#%02X%02X%02X", - ((val & 0xff0000) >> 16), - ((val & 0x00ff00) >> 8), - (val & 0x0000ff) - ); -} - /* Internal function: parses a glk color to a GdkColor */ void glkcolor_to_gdkcolor(glui32 val, GdkColor *color) @@ -679,6 +645,26 @@ glkcolor_to_gdkcolor(glui32 val, GdkColor *color) color->blue = 256 * (val & 0x0000ff); } +/* Internal function: parses a glk color to a hex string */ +gchar* +glkcolor_to_hex(glui32 val) +{ + return g_strdup_printf("%04X%04X%04X", + 256 * ((val & 0xff0000) >> 16), + 256 * ((val & 0x00ff00) >> 8), + 256 * (val & 0x0000ff) + ); +} + +/* Internal function: parses a gdk color to a hex string */ +gchar* +gdkcolor_to_hex(GdkColor *color) +{ + return g_strdup_printf("%04X%04X%04X", + color->red, color->green, color->blue + ); +} + /* Internal function: parses a GdkColor to a glk color */ static glui32 gdkcolor_to_glkcolor(GdkColor *color) @@ -689,7 +675,7 @@ gdkcolor_to_glkcolor(GdkColor *color) /* Internal function: changes a GTK tag to correspond with the given style. */ static void -apply_stylehint_to_tag(GtkTextTag *tag, GtkTextTag *default_tag, glui32 wintype, glui32 hint, glsi32 val) +apply_stylehint_to_tag(GtkTextTag *tag, glui32 wintype, glui32 styl, glui32 hint, glsi32 val) { g_return_if_fail(tag != NULL); @@ -699,7 +685,7 @@ apply_stylehint_to_tag(GtkTextTag *tag, GtkTextTag *default_tag, glui32 wintype, gint reverse_color = GPOINTER_TO_INT( g_object_get_data(tag_object, "reverse-color") ); int i = 0; - gchar color[20]; + GdkColor color; switch(hint) { case stylehint_Indentation: g_object_set(tag_object, "left-margin", 5*val, "left-margin-set", TRUE, NULL); @@ -749,7 +735,6 @@ apply_stylehint_to_tag(GtkTextTag *tag, GtkTextTag *default_tag, glui32 wintype, step be a scaling of 1.2 */ scale = pow(1.2, (double)val); } - g_printerr("Setting tag to %f\n", scale); g_object_set(tag_object, "scale", scale, "scale-set", TRUE, NULL); } break; @@ -771,56 +756,66 @@ apply_stylehint_to_tag(GtkTextTag *tag, GtkTextTag *default_tag, glui32 wintype, break; case stylehint_TextColor: - glkcolor_to_hex(val, color); + glkcolor_to_gdkcolor(val, &color); if(!reverse_color) - g_object_set(tag_object, "foreground", color, "foreground-set", TRUE, NULL); + g_object_set(tag_object, "foreground-gdk", &color, "foreground-set", TRUE, NULL); else - g_object_set(tag_object, "background", color, "background-set", TRUE, NULL); + g_object_set(tag_object, "background-gdk", &color, "background-set", TRUE, NULL); break; case stylehint_BackColor: - glkcolor_to_hex(val, color); + glkcolor_to_gdkcolor(val, &color); if(!reverse_color) - g_object_set(tag_object, "background", color, "background-set", TRUE, NULL); + g_object_set(tag_object, "background-gdk", &color, "background-set", TRUE, NULL); else - g_object_set(tag_object, "foreground", color, "background-set", TRUE, NULL); + g_object_set(tag_object, "foreground-gdk", &color, "background-set", TRUE, NULL); break; case stylehint_ReverseColor: - if(reverse_color != val) { + { + // Determine the current colors + + // If all fails, use black/white + // FIXME: Use system theme here + GdkColor foreground, background; + gdk_color_parse("black", &foreground); + gdk_color_parse("white", &background); + GdkColor *current_foreground = &foreground; + GdkColor *current_background = &background; + + if(wintype == wintype_TextBuffer) { + GtkTextTag* default_tag = g_hash_table_lookup(glk_data->styles->text_buffer, "default"); + GtkTextTag* base_tag = g_hash_table_lookup(glk_data->styles->text_buffer, get_tag_name(styl)); + style_cascade_colors(base_tag, tag, default_tag, ¤t_foreground, ¤t_background); + } + else if(wintype == wintype_TextGrid) { + GtkTextTag* default_tag = g_hash_table_lookup(glk_data->styles->text_grid, "default"); + GtkTextTag* base_tag = g_hash_table_lookup(glk_data->styles->text_grid, get_tag_name(styl)); + style_cascade_colors(base_tag, tag, default_tag, ¤t_foreground, ¤t_background); + } + + if(val) { /* Flip the fore- and background colors */ - GdkColor* foreground_color; - GdkColor* background_color; - gint f_set, b_set, df_set, db_set = 0; - g_object_get(tag_object, "foreground-set", &f_set, "background-set", &b_set, NULL); - g_object_get(default_tag, "foreground-set", &df_set, "background-set", &db_set, NULL); - - if(f_set) - g_object_get(tag_object, "foreground-gdk", &foreground_color, NULL); - else if(df_set) - g_object_get(default_tag, "foreground-gdk", &foreground_color, NULL); - if(b_set) - g_object_get(tag_object, "background-gdk", &background_color, NULL); - else if(db_set) - g_object_get(default_tag, "background-gdk", &background_color, NULL); - - if(b_set || db_set) - g_object_set(tag_object, "foreground-gdk", background_color, NULL); - else - g_object_set(tag_object, "foreground", "#ffffff", NULL); - - if(f_set || df_set) - g_object_set(tag_object, "background-gdk", foreground_color, NULL); - else - g_object_set(tag_object, "background", "#000000", NULL); - - g_object_set_data( tag_object, "reverse-color", GINT_TO_POINTER(val != 0) ); + GdkColor *temp = current_foreground; + current_foreground = current_background; + current_background = temp; } + + g_object_set(tag, + "foreground-gdk", current_foreground, + "foreground-set", TRUE, + "background-gdk", current_background, + "background-set", TRUE, + NULL + ); + + g_object_set_data( tag_object, "reverse-color", GINT_TO_POINTER(val != 0) ); break; + } default: WARNING("Unknown style hint"); @@ -928,19 +923,21 @@ query_tag(GtkTextTag *tag, glui32 wintype, glui32 hint) void glk_stylehint_set(glui32 wintype, glui32 styl, glui32 hint, glsi32 val) { +#ifdef DEBUG_STYLES + g_printf("glk_stylehint_set(wintype=%d, styl=%d, hint=%d, val=%d)\n", wintype, styl, hint, val); +#endif + ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key); - GtkTextTag *to_change, *default_tag; + GtkTextTag *to_change; if(wintype == wintype_TextBuffer || wintype == wintype_AllTypes) { to_change = g_hash_table_lookup( glk_data->glk_styles->text_buffer, get_glk_tag_name(styl) ); - default_tag = g_hash_table_lookup( glk_data->styles->text_buffer, get_tag_name(styl) ); - apply_stylehint_to_tag(to_change, default_tag, wintype_TextBuffer, hint, val); + apply_stylehint_to_tag(to_change, wintype_TextBuffer, styl, hint, val); } if(wintype == wintype_TextGrid || wintype == wintype_AllTypes) { to_change = g_hash_table_lookup( glk_data->glk_styles->text_grid, get_glk_tag_name(styl) ); - default_tag = g_hash_table_lookup( glk_data->styles->text_grid, get_tag_name(styl) ); - apply_stylehint_to_tag(to_change, default_tag, wintype_TextGrid, hint, val); + apply_stylehint_to_tag(to_change, wintype_TextGrid, styl, hint, val); } } @@ -961,6 +958,10 @@ glk_stylehint_set(glui32 wintype, glui32 styl, glui32 hint, glsi32 val) void glk_stylehint_clear(glui32 wintype, glui32 styl, glui32 hint) { +#ifdef DEBUG_STYLES + g_printf("glk_stylehint_clear(wintype=%d, styl=%d, hint=%d)\n", wintype, styl, hint); +#endif + ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key); GtkTextTag *tag; @@ -1000,6 +1001,10 @@ glk_stylehint_clear(glui32 wintype, glui32 styl, glui32 hint) glui32 glk_style_distinguish(winid_t win, glui32 styl1, glui32 styl2) { +#ifdef DEBUG_STYLES + g_printf("glk_style_distinguish(win->rock=%d, styl1=%d, styl2=%d)\n", win->rock, styl1, styl2); +#endif + /* FIXME */ return styl1 != styl2; } @@ -1076,6 +1081,10 @@ glk_style_distinguish(winid_t win, glui32 styl1, glui32 styl2) glui32 glk_style_measure(winid_t win, glui32 styl, glui32 hint, glui32 *result) { +#ifdef DEBUG_STYLES + g_printf("glk_style_measure(win->rock=%d, styl=%d, hint=%d, result=...)\n", win->rock, styl, hint); +#endif + ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key); GtkTextTag *tag; @@ -1189,3 +1198,67 @@ style_update(ChimaraGlk *glk) GtkTextTag *pager_tag = GTK_TEXT_TAG( g_hash_table_lookup(priv->styles->text_buffer, "pager") ); text_tag_to_attr_list(pager_tag, priv->pager_attr_list); } + +/* Determine the current colors used to render the text for a given stream. + * This can be set in a number of places */ +static void +style_cascade_colors(GtkTextTag *tag, GtkTextTag *glk_tag, GtkTextTag *default_tag, GdkColor **foreground, GdkColor **background) +{ + gboolean foreground_set = FALSE; + gboolean background_set = FALSE; + gint reverse_color; + + // Default color + reverse_color = GPOINTER_TO_INT( g_object_get_data(G_OBJECT(default_tag), "reverse-color") ); + g_object_get(default_tag, "foreground-set", &foreground_set, "background-set", &background_set, NULL); + if(foreground_set) + g_object_get(default_tag, "foreground-gdk", reverse_color ? background:foreground, NULL); + if(background_set) + g_object_get(default_tag, "background-gdk", reverse_color ? foreground:background, NULL); + + // Player defined color + reverse_color = GPOINTER_TO_INT( g_object_get_data(G_OBJECT(tag), "reverse-color") ); + g_object_get(tag, "foreground-set", &foreground_set, "background-set", &background_set, NULL); + if(foreground_set) + g_object_get(tag, "foreground-gdk", reverse_color ? background:foreground, NULL); + if(background_set) + g_object_get(tag, "background-gdk", reverse_color ? foreground:background, NULL); + + // GLK defined color + reverse_color = GPOINTER_TO_INT( g_object_get_data(G_OBJECT(glk_tag), "reverse-color") ); + g_object_get(glk_tag, "foreground-set", &foreground_set, "background-set", &background_set, NULL); + if(foreground_set) + g_object_get(glk_tag, "foreground-gdk", reverse_color ? background:foreground, NULL); + if(background_set) + g_object_get(glk_tag, "background-gdk", reverse_color ? foreground:background, NULL); + +} + +/* Determine the current colors used to render the text for a given stream. + * This can be set in a number of places */ +void +style_stream_colors(strid_t str, GdkColor **foreground, GdkColor **background) +{ + VALID_STREAM(str, return); + g_return_if_fail(str->window != NULL); + g_return_if_fail(str->window->type != wintype_TextBuffer || str->window->type != wintype_TextGrid); + + GtkTextBuffer *buffer = gtk_text_view_get_buffer( GTK_TEXT_VIEW(str->window->widget) ); + GtkTextTagTable *tags = gtk_text_buffer_get_tag_table(buffer); + GtkTextTag* default_tag = gtk_text_tag_table_lookup(tags, "default"); + GtkTextTag* tag = gtk_text_tag_table_lookup(tags, str->style); + GtkTextTag* glk_tag = gtk_text_tag_table_lookup(tags, str->glk_style); + + style_cascade_colors(tag, glk_tag, default_tag, foreground, background); + + gboolean foreground_set, background_set; + + // Windows can have zcolors defined + if(str->window->zcolor) { + g_object_get(str->window->zcolor, "foreground-set", &foreground_set, "background-set", &background_set, NULL); + if(foreground_set) + g_object_get(str->window->zcolor, "foreground-gdk", foreground, NULL); + if(background_set) + g_object_get(str->window->zcolor, "background-gdk", background, NULL); + } +} diff --git a/libchimara/style.h b/libchimara/style.h index 5766f84..6140473 100644 --- a/libchimara/style.h +++ b/libchimara/style.h @@ -3,6 +3,7 @@ #include #include +#include #include "glk.h" #include "chimara-glk.h" @@ -13,12 +14,14 @@ G_GNUC_INTERNAL void style_init(ChimaraGlk *glk); G_GNUC_INTERNAL void style_update(ChimaraGlk *glk); G_GNUC_INTERNAL const gchar** style_get_tag_names(); G_GNUC_INTERNAL void reset_default_styles(ChimaraGlk *glk); -/*G_GNUC_INTERNAL void copy_default_styles_to_current_styles(ChimaraGlk *glk);*/ G_GNUC_INTERNAL GScanner *create_css_file_scanner(void); G_GNUC_INTERNAL void scan_css_file(GScanner *scanner, ChimaraGlk *glk); G_GNUC_INTERNAL PangoFontDescription *get_current_font(guint32 wintype); G_GNUC_INTERNAL GtkTextTag* gtk_text_tag_copy(GtkTextTag *tag); G_GNUC_INTERNAL void glkcolor_to_gdkcolor(glui32 val, GdkColor *color); +G_GNUC_INTERNAL gchar* glkcolor_to_hex(glui32 val); +G_GNUC_INTERNAL gchar* gdkcolor_to_hex(GdkColor *color); +G_GNUC_INTERNAL void style_stream_colors(strid_t str, GdkColor **foreground, GdkColor **background); typedef struct StyleSet { GHashTable *text_grid; @@ -27,4 +30,17 @@ typedef struct StyleSet { #define CHIMARA_NUM_STYLES 13 +//#define DEBUG_STYLES + +#define ACTUAL_FG(tag) \ + (GPOINTER_TO_INT( g_object_get_data(G_OBJECT((tag)), "reverse-color")) ? "background-gdk":"foreground-gdk") + +#define ACTUAL_BG(tag) \ + (GPOINTER_TO_INT( g_object_get_data(G_OBJECT((tag)), "reverse-color")) ? "foreground-gdk":"background-gdk") + +#define ASSIGN_COLOR(to, from) \ + (to)->red = (from)->red; \ + (to)->green = (from)->green; \ + (to)->blue = (from)->blue; + #endif diff --git a/libchimara/window.c b/libchimara/window.c index 5b970f5..6272c67 100644 --- a/libchimara/window.c +++ b/libchimara/window.c @@ -951,9 +951,29 @@ glk_window_clear(winid_t win) gtk_text_buffer_set_text(textbuffer, text, -1); g_free(text); - GtkTextIter begin; - gtk_text_buffer_get_start_iter(textbuffer, &begin); - gtk_text_buffer_move_mark_by_name(textbuffer, "cursor_position", &begin); + GtkTextIter start, end; + gtk_text_buffer_get_start_iter(textbuffer, &start); + gtk_text_buffer_get_end_iter(textbuffer, &end); + + /* Determine default style */ + GtkTextTagTable *tags = gtk_text_buffer_get_tag_table(textbuffer); + GtkTextTag *default_tag = gtk_text_tag_table_lookup(tags, "default"); + GtkTextTag *style_tag = gtk_text_tag_table_lookup(tags, "normal"); + GtkTextTag *glk_style_tag = gtk_text_tag_table_lookup(tags, "normal"); + + // Default style + gtk_text_buffer_apply_tag(textbuffer, default_tag, &start, &end); + + // Player's style overrides + gtk_text_buffer_apply_tag(textbuffer, style_tag, &start, &end); + + // GLK Program's style overrides + gtk_text_buffer_apply_tag(textbuffer, glk_style_tag, &start, &end); + + if(win->zcolor != NULL) + gtk_text_buffer_apply_tag(textbuffer, win->zcolor, &start, &end); + + gtk_text_buffer_move_mark_by_name(textbuffer, "cursor_position", &start); gdk_threads_leave(); } diff --git a/libchimara/window.h b/libchimara/window.h index bb9a2f6..2945511 100644 --- a/libchimara/window.h +++ b/libchimara/window.h @@ -82,6 +82,8 @@ struct glk_window_struct gulong pager_adjustment_handler; /* Window buffer */ GString *buffer; + GtkTextTag *zcolor; + GtkTextTag *zcolor_reversed; /* Hyperlinks */ GHashTable *hyperlinks; struct hyperlink *current_hyperlink; diff --git a/player/chimara.menus b/player/chimara.menus index ec43fb9..927bc82 100644 --- a/player/chimara.menus +++ b/player/chimara.menus @@ -3,7 +3,7 @@ - + diff --git a/player/main.c b/player/main.c index 860cdfb..7eef7f7 100644 --- a/player/main.c +++ b/player/main.c @@ -155,6 +155,7 @@ create_window(void) const gchar *patterns[] = { "*.z[1-8]", "*.[zg]lb", "*.[zg]blorb", "*.ulx", "*.blb", "*.blorb", NULL }; + for(ptr = patterns; *ptr; ptr++) gtk_recent_filter_add_pattern(filter, *ptr); GtkRecentChooser *recent = GTK_RECENT_CHOOSER(load_object("recent")); @@ -214,7 +215,7 @@ create_window(void) g_signal_connect(glk, "notify::story-name", G_CALLBACK(change_window_title), window); /* Create preferences window */ - preferences_create(CHIMARA_GLK(glk)); + //preferences_create(CHIMARA_GLK(glk)); } int diff --git a/player/style.css b/player/style.css index 7a37d70..9788fd3 100644 --- a/player/style.css +++ b/player/style.css @@ -30,7 +30,9 @@ grid { } buffer { + color: #303030; font-size: 11; + margin-bottom: 5; } grid.user1 { @@ -38,6 +40,10 @@ grid.user1 { background-color: #ffffff; } +buffer.emphasized { + font-size: 14; +} + buffer.header { font-weight: bold; } diff --git a/tests/plugin-loader.c b/tests/plugin-loader.c index 766305d..1c560ac 100644 --- a/tests/plugin-loader.c +++ b/tests/plugin-loader.c @@ -17,7 +17,7 @@ * contributor may be used to endorse or promote products derived * from this software without specific prior written permission. * - * main.c IS PROVIDED BY Philip en Marijn ``AS IS'' AND ANY EXPRESS + * plugin-loader.c IS PROVIDED BY Philip en Marijn ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL Philip en Marijn OR ANY OTHER CONTRIBUTORS diff --git a/tests/style.css b/tests/style.css deleted file mode 100644 index 2504e9f..0000000 --- a/tests/style.css +++ /dev/null @@ -1,80 +0,0 @@ -/* Possible windows: - * grid - * buffer - * - * Possible selectors: - * normal - * emphasized - * preformatted - * header - * subheader - * alert - * note - * block-quote - * input - * user1 - * user2 - * hyperlink - * - * Possible style hints: - * font-family (string) - * font-size (float) - * font-weight (normal/bold) - * font-style (normal/italic) - * color (#hex-value) - * background-color (#hex-value) - * text-align (left/right/center) - */ -grid.normal { - font-size: 10; -} - -grid.user1 { - color: #303030; - background-color: #ffffff; -} - -buffer.normal { - font-size: 10; -} - -buffer.header { - font-size: 14; - font-weight: bold; - text-align: center; -} - -buffer.subheader { - font-size: 12; - font-weight: bold; -} - -buffer.alert { - color: #aa0000; - font-weight: bold; -} - -buffer.note { - color: #aaaa00; - font-weight: bold; -} - -buffer.block-quote { - text-align: center; - font-style: italic; -} - -buffer.input { - color: #0000aa; - font-style: italic; -} - -buffer.user1 { -} - -buffer.user2 { -} - -buffer.hyperlink { - color: #ff0000; -} diff --git a/tests/styletest.c b/tests/styletest.c index 8ed7737..4e9a503 100644 --- a/tests/styletest.c +++ b/tests/styletest.c @@ -3,6 +3,7 @@ #include #include #include +#include void print_help(); void do_style_test(); @@ -111,7 +112,12 @@ do_style_test() { glk_set_style(style_User2); glk_put_string("User2\n"); + glk_set_style(style_Header); + garglk_set_zcolors(0xFF0000, 0x00FFFF); + glk_put_string("Zcolor test\n"); + glk_set_style(style_Normal); + garglk_set_zcolors(0x000000, 0xFFFFFF); } void