X-Git-Url: https://git.stderr.nl/gitweb?a=blobdiff_plain;f=libchimara%2Fchimara-glk.c;h=19925569823b16569e2246a0f457a74f974348cb;hb=f7db20369cdd1b699742a2037ca3ab99afe47ab2;hp=ca01f44510d7c7dd86a0db2fa9698385cea1197b;hpb=89081782541e85e079f64839ffb26b4e74273eb7;p=projects%2Fchimara%2Fchimara.git
diff --git a/libchimara/chimara-glk.c b/libchimara/chimara-glk.c
index ca01f44..1992556 100644
--- a/libchimara/chimara-glk.c
+++ b/libchimara/chimara-glk.c
@@ -32,7 +32,6 @@
* SECTION:chimara-glk
* @short_description: Widget which executes a Glk program
* @stability: Unstable
- * @include: libchimara/chimara-glk.h
*
* The #ChimaraGlk widget opens and runs a Glk program. The program must be
* compiled as a plugin module, with a function glk_main()
@@ -178,7 +177,7 @@ chimara_glk_init(ChimaraGlk *self)
priv->ignore_next_arrange_event = FALSE;
priv->char_input_queue = g_async_queue_new();
priv->line_input_queue = g_async_queue_new();
- /* Should be g_async_queue_new_full(g_free); but only in GTK >= 2.16 */
+ /* FIXME Should be g_async_queue_new_full(g_free); but only in GTK >= 2.16 */
priv->resource_map = NULL;
priv->resource_lock = g_mutex_new();
priv->resource_loaded = g_cond_new();
@@ -303,6 +302,9 @@ chimara_glk_finalize(GObject *object)
/* Unref input queues (this should destroy them since any Glk thread has stopped by now */
g_async_queue_unref(priv->char_input_queue);
g_async_queue_unref(priv->line_input_queue);
+ /* Destroy callback data if ownership retained */
+ if(priv->resource_load_callback_destroy_data)
+ priv->resource_load_callback_destroy_data(priv->resource_load_callback_data);
/* Free other stuff */
g_free(priv->current_dir);
@@ -329,7 +331,8 @@ request_recurse(winid_t win, GtkRequisition *requisition, guint spacing)
glui32 division = win->split_method & winmethod_DivisionMask;
glui32 direction = win->split_method & winmethod_DirMask;
-
+ unsigned border = ((win->split_method & winmethod_BorderMask) == winmethod_NoBorder)? 0 : spacing;
+
/* If the split is fixed, get the size of the fixed child */
if(division == winmethod_Fixed)
{
@@ -363,13 +366,13 @@ request_recurse(winid_t win, GtkRequisition *requisition, guint spacing)
{
case winmethod_Left:
case winmethod_Right:
- requisition->width = child1.width + child2.width + spacing;
+ requisition->width = child1.width + child2.width + border;
requisition->height = MAX(child1.height, child2.height);
break;
case winmethod_Above:
case winmethod_Below:
requisition->width = MAX(child1.width, child2.width);
- requisition->height = child1.height + child2.height + spacing;
+ requisition->height = child1.height + child2.height + border;
break;
}
}
@@ -413,12 +416,13 @@ allocate_recurse(winid_t win, GtkAllocation *allocation, guint spacing)
{
glui32 division = win->split_method & winmethod_DivisionMask;
glui32 direction = win->split_method & winmethod_DirMask;
+ unsigned border = ((win->split_method & winmethod_BorderMask) == winmethod_NoBorder)? 0 : spacing;
/* If the space gets too small to honor the spacing property, then just
ignore spacing in this window and below. */
- if( (spacing > allocation->width && (direction == winmethod_Left || direction == winmethod_Right))
- || (spacing > allocation->height && (direction == winmethod_Above || direction == winmethod_Below)) )
- spacing = 0;
+ if( (border > allocation->width && (direction == winmethod_Left || direction == winmethod_Right))
+ || (border > allocation->height && (direction == winmethod_Above || direction == winmethod_Below)) )
+ border = 0;
GtkAllocation child1, child2;
child1.x = allocation->x;
@@ -432,22 +436,22 @@ allocate_recurse(winid_t win, GtkAllocation *allocation, guint spacing)
{
case winmethod_Left:
child1.width = win->key_window?
- CLAMP(win->constraint_size * win->key_window->unit_width, 0, allocation->width - spacing)
+ CLAMP(win->constraint_size * win->key_window->unit_width, 0, allocation->width - border)
: 0;
break;
case winmethod_Right:
child2.width = win->key_window?
- CLAMP(win->constraint_size * win->key_window->unit_width, 0, allocation->width - spacing)
+ CLAMP(win->constraint_size * win->key_window->unit_width, 0, allocation->width - border)
: 0;
break;
case winmethod_Above:
child1.height = win->key_window?
- CLAMP(win->constraint_size * win->key_window->unit_height, 0, allocation->height - spacing)
+ CLAMP(win->constraint_size * win->key_window->unit_height, 0, allocation->height - border)
: 0;
break;
case winmethod_Below:
child2.height = win->key_window?
- CLAMP(win->constraint_size * win->key_window->unit_height, 0, allocation->height - spacing)
+ CLAMP(win->constraint_size * win->key_window->unit_height, 0, allocation->height - border)
: 0;
break;
}
@@ -458,16 +462,16 @@ allocate_recurse(winid_t win, GtkAllocation *allocation, guint spacing)
switch(direction)
{
case winmethod_Left:
- child1.width = MAX(0, (gint)ceil(fraction * (allocation->width - spacing)) );
+ child1.width = MAX(0, (gint)ceil(fraction * (allocation->width - border)) );
break;
case winmethod_Right:
- child2.width = MAX(0, (gint)ceil(fraction * (allocation->width - spacing)) );
+ child2.width = MAX(0, (gint)ceil(fraction * (allocation->width - border)) );
break;
case winmethod_Above:
- child1.height = MAX(0, (gint)ceil(fraction * (allocation->height - spacing)) );
+ child1.height = MAX(0, (gint)ceil(fraction * (allocation->height - border)) );
break;
case winmethod_Below:
- child2.height = MAX(0, (gint)ceil(fraction * (allocation->height - spacing)) );
+ child2.height = MAX(0, (gint)ceil(fraction * (allocation->height - border)) );
break;
}
}
@@ -476,27 +480,27 @@ allocate_recurse(winid_t win, GtkAllocation *allocation, guint spacing)
switch(direction)
{
case winmethod_Left:
- child2.width = MAX(0, allocation->width - spacing - child1.width);
- child2.x = child1.x + child1.width + spacing;
+ child2.width = MAX(0, allocation->width - border - child1.width);
+ child2.x = child1.x + child1.width + border;
child2.y = child1.y;
child1.height = child2.height = allocation->height;
break;
case winmethod_Right:
- child1.width = MAX(0, allocation->width - spacing - child2.width);
- child2.x = child1.x + child1.width + spacing;
+ child1.width = MAX(0, allocation->width - border - child2.width);
+ child2.x = child1.x + child1.width + border;
child2.y = child1.y;
child1.height = child2.height = allocation->height;
break;
case winmethod_Above:
- child2.height = MAX(0, allocation->height - spacing - child1.height);
+ child2.height = MAX(0, allocation->height - border - child1.height);
child2.x = child1.x;
- child2.y = child1.y + child1.height + spacing;
+ child2.y = child1.y + child1.height + border;
child1.width = child2.width = allocation->width;
break;
case winmethod_Below:
- child1.height = MAX(0, allocation->height - spacing - child2.height);
+ child1.height = MAX(0, allocation->height - border - child2.height);
child2.x = child1.x;
- child2.y = child1.y + child1.height + spacing;
+ child2.y = child1.y + child1.height + border;
child1.width = child2.width = allocation->width;
break;
}
@@ -813,7 +817,7 @@ chimara_glk_class_init(ChimaraGlkClass *klass)
_chimara_marshal_VOID__UINT_STRING,
G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_STRING);
/**
- * ChimaraGlk::iliad-update-screen:
+ * ChimaraGlk::iliad-screen-update:
* @self: The widget that received the signal
* @typing: Whether to perform a typing or full screen update
*
@@ -860,7 +864,10 @@ chimara_glk_class_init(ChimaraGlkClass *klass)
/**
* ChimaraGlk:spacing:
*
- * The amount of space between the Glk windows.
+ * The amount of space between the Glk windows. This space forms a visible
+ * border between windows; however, if you open a window using the
+ * %winmethod_NoBorder flag, there will be no spacing between it and its
+ * sibling window, no matter what the value of this property is.
*/
g_object_class_install_property(object_class, PROP_SPACING,
g_param_spec_uint("spacing", _("Spacing"),
@@ -1063,8 +1070,9 @@ chimara_glk_set_css_from_file(ChimaraGlk *glk, const gchar *filename, GError **e
int fd = open(filename, O_RDONLY);
if(fd == -1) {
- *error = g_error_new(G_IO_ERROR, g_io_error_from_errno(errno),
- _("Error opening file \"%s\": %s"), filename, g_strerror(errno));
+ if(error)
+ *error = g_error_new(G_IO_ERROR, g_io_error_from_errno(errno),
+ _("Error opening file \"%s\": %s"), filename, g_strerror(errno));
return FALSE;
}
@@ -1074,8 +1082,9 @@ chimara_glk_set_css_from_file(ChimaraGlk *glk, const gchar *filename, GError **e
scan_css_file(scanner, glk);
if(close(fd) == -1) {
- *error = g_error_new(G_IO_ERROR, g_io_error_from_errno(errno),
- _("Error closing file \"%s\": %s"), filename, g_strerror(errno));
+ if(error)
+ *error = g_error_new(G_IO_ERROR, g_io_error_from_errno(errno),
+ _("Error closing file \"%s\": %s"), filename, g_strerror(errno));
return FALSE;
}
return TRUE;
@@ -1415,16 +1424,16 @@ chimara_glk_is_line_input_pending(ChimaraGlk *glk)
/**
* chimara_glk_get_tag:
- * @glk: a #ChimarGlk widget
+ * @glk: a #ChimaraGlk widget
* @window: The type of window to retrieve the tag for
* @name: The name of the tag to retrieve
*
* Use this function to get a #GtkTextTag so style properties can be changed.
- * See also #chimara_glk_set_css_from_string.
+ * See also chimara_glk_set_css_from_string().
*
* The layout of the text in Chimara is controlled by two sets of tags: one set
* describing the style in text buffers and one for text grids. See also the
- * GLK specification for the difference between the two. The main narrative of
+ * Glk specification for the difference between the two. The main narrative of
* a game is usually rendered in text buffers, whereas text grids are mostly
* used for status bars and in game menus.
*
@@ -1443,9 +1452,12 @@ chimara_glk_is_line_input_pending(ChimaraGlk *glk)
* user2
* hyperlink
* pager
- *
+ *
+ *
+ * Returns: (transfer none): The #GtkTextTag corresponding to @name in the
+ * styles of @window.
*/
-GtkTextTag*
+GtkTextTag *
chimara_glk_get_tag(ChimaraGlk *glk, ChimaraGlkWindowType window, const gchar *name)
{
CHIMARA_GLK_USE_PRIVATE(glk, priv);
@@ -1464,27 +1476,23 @@ chimara_glk_get_tag(ChimaraGlk *glk, ChimaraGlkWindowType window, const gchar *n
}
/**
- * chimara_glk_get_tag:
- * @glk: a #ChimarGlk widget
- *
- * Retrieves the possible tag names to use in #chimara_glk_get_tag.
- */
-const gchar**
-chimara_glk_get_tag_names(ChimaraGlk *glk)
-{
- return style_get_tag_names();
-}
-
-/**
- * chimara_glk_get_num_tag_names:
+ * chimara_glk_get_tag_names:
* @glk: a #ChimaraGlk widget
+ * @num_tags: Return location for the number of tag names retrieved.
+ *
+ * Retrieves the possible tag names to use in chimara_glk_get_tag().
*
- * Retrieves the number of style tags returned by #chimara_glk_get_tag_names.
+ * Returns: (transfer none) (array length=num_tags) (element-type utf8):
+ * Array of strings containing the tag names. This array is owned by Chimara,
+ * do not free it.
*/
-gint
-chimara_glk_get_num_tag_names(ChimaraGlk *glk)
+const gchar **
+chimara_glk_get_tag_names(ChimaraGlk *glk, unsigned int *num_tags)
{
- return CHIMARA_NUM_STYLES;
+ g_return_val_if_fail(num_tags != NULL, NULL);
+
+ *num_tags = CHIMARA_NUM_STYLES;
+ return style_get_tag_names();
}
/**
@@ -1493,7 +1501,7 @@ chimara_glk_get_num_tag_names(ChimaraGlk *glk)
*
* Processes style updates and updates the widget to reflect the new style.
* Call this every time you change a property of a #GtkTextTag retrieved by
- * #chimara_glk_get_tag.
+ * chimara_glk_get_tag().
*/
void
chimara_glk_update_style(ChimaraGlk *glk)
@@ -1514,6 +1522,7 @@ chimara_glk_update_style(ChimaraGlk *glk)
* @glk: a #ChimaraGlk widget
* @func: a function to call for loading resources, or %NULL
* @user_data: user data to pass to @func, or %NULL
+ * @destroy_user_data: a function to call for freeing @user_data, or %NULL
*
* Sometimes it is preferable to load image and sound resources from somewhere
* else than a Blorb file, for example while developing a game. Section 14 of
@@ -1526,12 +1535,27 @@ chimara_glk_update_style(ChimaraGlk *glk)
* Note that @func is only called if no Blorb resource map has been set; having
* a resource map in place overrides this function.
*
+ * If you pass non-%NULL for @destroy_user_data, then @glk takes ownership of
+ * @user_data. When it is not needed anymore, it will be freed by calling
+ * @destroy_user_data on it. If you wish to retain ownership of @user_data, pass
+ * %NULL for @destroy_user_data.
+ *
* To deactivate the callback, call this function with @func set to %NULL.
*/
void
-chimara_glk_set_resource_load_callback(ChimaraGlk *glk, ChimaraResourceLoadFunc func, gpointer user_data)
+chimara_glk_set_resource_load_callback(ChimaraGlk *glk, ChimaraResourceLoadFunc func, gpointer user_data, GDestroyNotify destroy_user_data)
{
CHIMARA_GLK_USE_PRIVATE(glk, priv);
+
+ if(priv->resource_load_callback == func
+ && priv->resource_load_callback_data == user_data
+ && priv->resource_load_callback_destroy_data == destroy_user_data)
+ return;
+
+ if(priv->resource_load_callback_destroy_data)
+ priv->resource_load_callback_destroy_data(priv->resource_load_callback_data);
+
priv->resource_load_callback = func;
priv->resource_load_callback_data = user_data;
+ priv->resource_load_callback_destroy_data = destroy_user_data;
}