udapted vi.po
[rhythmbox.git] / lib / rb-util.c
blob739f479136dbf093cc04c169620e1eae58f202e8
1 /*
2 * arch-tag: Implementation of totally random functions that didn't fit elsewhere
4 * Copyright (C) 2003 Colin Walters <walters@verbum.org>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21 #include "config.h"
23 #include <string.h>
24 #include <stdarg.h>
25 #include <stdlib.h>
27 #include <gtk/gtk.h>
28 #include <libgnome/gnome-i18n.h>
29 #include <libgnomevfs/gnome-vfs.h>
30 #include <libgnomevfs/gnome-vfs-mime-handlers.h>
31 #include <gobject/gvaluecollector.h>
33 #include "rb-util.h"
34 #include "rb-debug.h"
36 static GPrivate * private_is_primary_thread;
38 gboolean
39 rb_true_function (gpointer dummy)
41 return TRUE;
44 gboolean
45 rb_false_function (gpointer dummy)
47 return FALSE;
50 gpointer
51 rb_null_function (gpointer dummy)
53 return NULL;
56 gpointer
57 rb_copy_function (gpointer data)
59 return data;
63 int
64 rb_gvalue_compare (GValue *a, GValue *b)
66 int retval;
67 const char *stra, *strb;
69 if (G_VALUE_TYPE (a) != G_VALUE_TYPE (b))
70 return -1;
72 switch (G_VALUE_TYPE (a))
74 case G_TYPE_BOOLEAN:
75 if (g_value_get_int (a) < g_value_get_int (b))
76 retval = -1;
77 else if (g_value_get_int (a) == g_value_get_int (b))
78 retval = 0;
79 else
80 retval = 1;
81 break;
82 case G_TYPE_CHAR:
83 if (g_value_get_char (a) < g_value_get_char (b))
84 retval = -1;
85 else if (g_value_get_char (a) == g_value_get_char (b))
86 retval = 0;
87 else
88 retval = 1;
89 break;
90 case G_TYPE_UCHAR:
91 if (g_value_get_uchar (a) < g_value_get_uchar (b))
92 retval = -1;
93 else if (g_value_get_uchar (a) == g_value_get_uchar (b))
94 retval = 0;
95 else
96 retval = 1;
97 break;
98 case G_TYPE_INT:
99 if (g_value_get_int (a) < g_value_get_int (b))
100 retval = -1;
101 else if (g_value_get_int (a) == g_value_get_int (b))
102 retval = 0;
103 else
104 retval = 1;
105 break;
106 case G_TYPE_UINT:
107 if (g_value_get_uint (a) < g_value_get_uint (b))
108 retval = -1;
109 else if (g_value_get_uint (a) == g_value_get_uint (b))
110 retval = 0;
111 else
112 retval = 1;
113 break;
114 case G_TYPE_LONG:
115 if (g_value_get_long (a) < g_value_get_long (b))
116 retval = -1;
117 else if (g_value_get_long (a) == g_value_get_long (b))
118 retval = 0;
119 else
120 retval = 1;
121 break;
122 case G_TYPE_ULONG:
123 if (g_value_get_ulong (a) < g_value_get_ulong (b))
124 retval = -1;
125 else if (g_value_get_ulong (a) == g_value_get_ulong (b))
126 retval = 0;
127 else
128 retval = 1;
129 break;
130 case G_TYPE_INT64:
131 if (g_value_get_int64 (a) < g_value_get_int64 (b))
132 retval = -1;
133 else if (g_value_get_int64 (a) == g_value_get_int64 (b))
134 retval = 0;
135 else
136 retval = 1;
137 break;
138 case G_TYPE_UINT64:
139 if (g_value_get_uint64 (a) < g_value_get_uint64 (b))
140 retval = -1;
141 else if (g_value_get_uint64 (a) == g_value_get_uint64 (b))
142 retval = 0;
143 else
144 retval = 1;
145 break;
146 case G_TYPE_ENUM:
147 /* this is somewhat bogus. */
148 if (g_value_get_enum (a) < g_value_get_enum (b))
149 retval = -1;
150 else if (g_value_get_enum (a) == g_value_get_enum (b))
151 retval = 0;
152 else
153 retval = 1;
154 break;
155 case G_TYPE_FLAGS:
156 /* this is even more bogus. */
157 if (g_value_get_flags (a) < g_value_get_flags (b))
158 retval = -1;
159 else if (g_value_get_flags (a) == g_value_get_flags (b))
160 retval = 0;
161 else
162 retval = 1;
163 break;
164 case G_TYPE_FLOAT:
165 if (g_value_get_float (a) < g_value_get_float (b))
166 retval = -1;
167 else if (g_value_get_float (a) == g_value_get_float (b))
168 retval = 0;
169 else
170 retval = 1;
171 break;
172 case G_TYPE_DOUBLE:
173 if (g_value_get_double (a) < g_value_get_double (b))
174 retval = -1;
175 else if (g_value_get_double (a) == g_value_get_double (b))
176 retval = 0;
177 else
178 retval = 1;
179 break;
180 case G_TYPE_STRING:
181 stra = g_value_get_string (a);
182 strb = g_value_get_string (b);
183 if (stra == NULL) stra = "";
184 if (strb == NULL) strb = "";
185 retval = g_utf8_collate (stra, strb);
186 break;
187 case G_TYPE_POINTER:
188 retval = (g_value_get_pointer (a) != g_value_get_pointer (b));
189 break;
190 case G_TYPE_BOXED:
191 retval = (g_value_get_boxed (a) != g_value_get_boxed (b));
192 break;
193 case G_TYPE_OBJECT:
194 retval = (g_value_get_object (a) != g_value_get_object (b));
195 break;
196 default:
197 g_assert_not_reached ();
198 retval = 0;
199 break;
201 return retval;
205 rb_compare_gtimeval (GTimeVal *a, GTimeVal *b)
207 if (a->tv_sec == b->tv_sec)
208 /* It's quite unlikely that microseconds are equal,
209 * so just ignore that case, we don't need a lot
210 * of precision.
212 return a->tv_usec > b->tv_usec ? 1 : -1;
213 else if (a->tv_sec > b->tv_sec)
214 return 1;
215 else
216 return -1;
219 /* Taken from totem/video-utils.c CVS HEAD 2004-04-22 */
220 static void
221 totem_pixbuf_mirror (GdkPixbuf *pixbuf)
223 int i, j, rowstride, offset, right;
224 guchar *pixels;
225 int width, height, size;
226 guint32 tmp;
228 pixels = gdk_pixbuf_get_pixels (pixbuf);
229 g_return_if_fail (pixels != NULL);
231 width = gdk_pixbuf_get_width (pixbuf);
232 height = gdk_pixbuf_get_height (pixbuf);
233 rowstride = gdk_pixbuf_get_rowstride (pixbuf);
234 size = height * width * sizeof (guint32);
236 for (i = 0; i < size; i += rowstride)
238 for (j = 0; j < rowstride; j += sizeof(guint32))
240 offset = i + j;
241 right = i + (((width - 1) * sizeof(guint32)) - j);
243 if (right <= offset)
244 break;
246 memcpy (&tmp, pixels + offset, sizeof(guint32));
247 memcpy (pixels + offset, pixels + right,
248 sizeof(guint32));
249 memcpy (pixels + right, &tmp, sizeof(guint32));
256 /* Same as gtk_image_new_from_stock except that it mirrors the icons for RTL
257 * languages
259 GtkWidget *
260 rb_image_new_from_stock (const gchar *stock_id, GtkIconSize size)
263 if (gtk_widget_get_default_direction () == GTK_TEXT_DIR_LTR) {
264 return gtk_image_new_from_stock (stock_id, size);
265 } else {
267 GtkWidget *image;
268 GdkPixbuf *pixbuf;
269 GdkPixbuf *mirror;
271 image = gtk_image_new ();
273 if (image == NULL) {
274 return NULL;
277 pixbuf = gtk_widget_render_icon (image, stock_id, size, NULL);
278 g_assert (pixbuf != NULL);
281 mirror = gdk_pixbuf_copy (pixbuf);
282 gdk_pixbuf_unref (pixbuf);
284 if (!mirror)
285 return NULL;
287 totem_pixbuf_mirror (mirror);
288 gtk_image_set_from_pixbuf (GTK_IMAGE (image), mirror);
289 gdk_pixbuf_unref (mirror);
291 return image;
294 return NULL;
297 void
298 rb_gtk_action_popup_menu (GtkUIManager *uimanager, const char *path)
300 GtkWidget *menu;
302 menu = gtk_ui_manager_get_widget (uimanager, path);
303 if (menu == NULL) {
304 g_warning ("Couldn't get menu widget for %s", path);
305 } else {
306 gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, 3,
307 gtk_get_current_event_time ());
311 static GList *
312 get_mount_points (void)
314 GnomeVFSVolumeMonitor *monitor;
315 GList *volumes;
316 GList *it;
317 GList *mount_points = NULL;
319 monitor = gnome_vfs_get_volume_monitor ();
320 /* FIXME: should also get the list of connected drivers (network
321 * shares I assume)
323 volumes = gnome_vfs_volume_monitor_get_mounted_volumes (monitor);
325 for (it = volumes; it != NULL; it = it->next) {
326 gchar *uri;
327 GnomeVFSVolume *volume;
329 volume = GNOME_VFS_VOLUME (it->data);
330 uri = gnome_vfs_volume_get_activation_uri (volume);
331 g_assert (uri != NULL);
332 mount_points = g_list_prepend (mount_points, uri);
335 g_list_foreach (volumes, (GFunc)gnome_vfs_volume_ref, NULL);
336 g_list_free (volumes);
338 return mount_points;
342 gchar *
343 rb_uri_get_mount_point (const char *uri)
345 GList *mount_points = get_mount_points ();
346 GList *it;
347 gchar *mount_point = NULL;
349 for (it = mount_points; it != NULL; it = it->next) {
350 if (g_str_has_prefix (uri, it->data)) {
351 if ((mount_point == NULL) || (strlen (mount_point) < strlen (it->data))) {
352 g_free (mount_point);
353 mount_point = g_strdup (it->data);
357 g_list_foreach (mount_points, (GFunc)g_free, NULL);
358 g_list_free (mount_points);
360 return mount_point;
363 gboolean
364 rb_uri_is_mounted (const char *uri)
366 GList *mount_points = get_mount_points ();
367 GList *it;
368 gboolean found = FALSE;
370 if ((uri == NULL) || (*uri == '\0')) {
371 return TRUE;
374 for (it = mount_points; it != NULL; it = it->next) {
375 if (strcmp (it->data, uri) == 0) {
376 found = TRUE;
377 break;
380 g_list_foreach (mount_points, (GFunc)g_free, NULL);
381 g_list_free (mount_points);
383 /* if (found == FALSE) {
384 g_print ("%s not mounted\n", uri);
387 return found;
390 gboolean
391 rb_is_main_thread (void)
393 if (g_thread_supported()) {
394 return GPOINTER_TO_UINT(g_private_get (private_is_primary_thread)) == 1;
395 } else {
396 return TRUE;
400 static gboolean
401 purge_useless_threads (gpointer data)
403 g_thread_pool_stop_unused_threads ();
404 return TRUE;
408 static GStaticRecMutex rb_gdk_mutex;
410 static void
411 _threads_enter (void)
413 g_static_rec_mutex_lock (&rb_gdk_mutex);
416 static void
417 _threads_leave (void)
419 g_static_rec_mutex_unlock (&rb_gdk_mutex);
422 void
423 rb_threads_init (void)
425 private_is_primary_thread = g_private_new (NULL);
426 g_private_set (private_is_primary_thread, GUINT_TO_POINTER (1));
428 g_static_rec_mutex_init (&rb_gdk_mutex);
429 gdk_threads_set_lock_functions (_threads_enter, _threads_leave);
430 gdk_threads_init ();
432 /* purge useless thread-pool threads occasionally */
433 g_timeout_add (30 * 1000, purge_useless_threads, NULL);
436 gchar **
437 rb_string_split_words (const gchar *string)
439 /*return g_slist_prepend (NULL, g_strdup (string));*/
441 GSList *words, *current;
442 gunichar *unicode, *cur_write, *cur_read;
443 gchar **ret;
444 gint i, wordcount = 1;
445 gboolean new_word = TRUE;
447 g_return_val_if_fail (string != NULL, NULL);
449 cur_write = cur_read = unicode = g_utf8_to_ucs4_fast (string, -1, NULL);
451 /* we may fail here, we expect valid utf-8 */
452 g_return_val_if_fail (unicode != NULL, NULL);
454 words = g_slist_prepend (NULL, unicode);
456 /* now normalize this text */
457 while (*cur_read) {
458 switch (g_unichar_type (*cur_read)) {
459 case G_UNICODE_UNASSIGNED:
460 rb_debug ("unassigned unicode character type found");
461 /* fall through */
462 case G_UNICODE_CONTROL:
463 case G_UNICODE_FORMAT:
464 case G_UNICODE_PRIVATE_USE:
466 case G_UNICODE_SURROGATE:
467 case G_UNICODE_LINE_SEPARATOR:
468 case G_UNICODE_PARAGRAPH_SEPARATOR:
469 case G_UNICODE_SPACE_SEPARATOR:
470 /* remove these and start a new word */
471 if (!new_word) {
472 /* end current word if it isn't ended yet */
473 *cur_write++ = 0;
474 new_word = TRUE;
477 break;
478 case G_UNICODE_COMBINING_MARK:
479 case G_UNICODE_ENCLOSING_MARK:
480 case G_UNICODE_NON_SPACING_MARK:
481 case G_UNICODE_CONNECT_PUNCTUATION:
482 case G_UNICODE_DASH_PUNCTUATION:
483 case G_UNICODE_CLOSE_PUNCTUATION:
484 case G_UNICODE_FINAL_PUNCTUATION:
485 case G_UNICODE_INITIAL_PUNCTUATION:
486 case G_UNICODE_OTHER_PUNCTUATION:
487 case G_UNICODE_OPEN_PUNCTUATION:
488 /* remove these */
489 /*break;*/
490 case G_UNICODE_LOWERCASE_LETTER:
491 case G_UNICODE_MODIFIER_LETTER:
492 case G_UNICODE_OTHER_LETTER:
493 case G_UNICODE_TITLECASE_LETTER:
494 case G_UNICODE_UPPERCASE_LETTER:
495 case G_UNICODE_DECIMAL_NUMBER:
496 case G_UNICODE_LETTER_NUMBER:
497 case G_UNICODE_OTHER_NUMBER:
498 case G_UNICODE_CURRENCY_SYMBOL:
499 case G_UNICODE_MODIFIER_SYMBOL:
500 case G_UNICODE_MATH_SYMBOL:
501 case G_UNICODE_OTHER_SYMBOL:
502 /* keep these unchanged */
503 *cur_write = *cur_read;
504 if (new_word) {
505 if (cur_write != unicode) {/* first insert has been done above */
506 words = g_slist_prepend (words, cur_write);
507 wordcount++;
509 new_word = FALSE;
511 cur_write++;
512 break;
513 default:
514 g_warning ("unknown unicode character type found");
515 break;
517 cur_read++;
520 if (!new_word) {
521 *cur_write++ = 0;
524 ret = g_new (gchar *, wordcount + 1);
525 current = words;
526 for (i = wordcount - 1; i >= 0; i--) {
527 ret[i] = g_ucs4_to_utf8 (current->data, -1, NULL, NULL, NULL);
528 current = g_slist_next (current);
530 ret[wordcount] = NULL;
532 g_slist_free (words);
533 g_free (unicode);
535 return ret;
538 gchar*
539 rb_search_fold (const char *original)
541 GString *string;
542 gunichar *unicode, *cur;
544 g_return_val_if_fail (original != NULL, NULL);
546 /* old behaviour is equivalent to: return g_utf8_casefold (original, -1); */
548 string = g_string_new (NULL);
549 unicode = g_utf8_to_ucs4_fast (original, -1, NULL);
551 for (cur = unicode; *cur != 0; cur++) {
552 switch (g_unichar_type (*cur)) {
553 case G_UNICODE_COMBINING_MARK:
554 case G_UNICODE_ENCLOSING_MARK:
555 case G_UNICODE_NON_SPACING_MARK:
556 case G_UNICODE_CONNECT_PUNCTUATION:
557 case G_UNICODE_DASH_PUNCTUATION:
558 case G_UNICODE_CLOSE_PUNCTUATION:
559 case G_UNICODE_FINAL_PUNCTUATION:
560 case G_UNICODE_INITIAL_PUNCTUATION:
561 case G_UNICODE_OTHER_PUNCTUATION:
562 case G_UNICODE_OPEN_PUNCTUATION:
563 /* remove these */
564 break;
566 case G_UNICODE_LOWERCASE_LETTER:
567 case G_UNICODE_MODIFIER_LETTER:
568 case G_UNICODE_OTHER_LETTER:
569 case G_UNICODE_TITLECASE_LETTER:
570 case G_UNICODE_UPPERCASE_LETTER:
571 /* convert to lower case */
572 *cur = g_unichar_tolower (*cur);
573 /* ... and fall through */\
574 case G_UNICODE_DECIMAL_NUMBER:
575 case G_UNICODE_LETTER_NUMBER:
576 case G_UNICODE_OTHER_NUMBER:
577 /* should be keep symbols? */
578 case G_UNICODE_CURRENCY_SYMBOL:
579 case G_UNICODE_MODIFIER_SYMBOL:
580 case G_UNICODE_MATH_SYMBOL:
581 case G_UNICODE_OTHER_SYMBOL:
582 g_string_append_unichar (string, *cur);
583 break;
585 case G_UNICODE_UNASSIGNED:
586 rb_debug ("unassigned unicode character type found");
587 /* fall through */
589 default:
590 /* leave these in */
591 g_string_append_unichar (string, *cur);
595 g_free (unicode);
597 return g_string_free (string, FALSE);
600 char *
601 rb_make_duration_string (guint duration)
603 char *str;
604 int hours, minutes, seconds;
606 hours = duration / (60 * 60);
607 minutes = (duration - (hours * 60 * 60)) / 60;
608 seconds = duration % 60;
610 if (hours == 0 && minutes == 0 && seconds == 0)
611 str = g_strdup (_("Unknown"));
612 else if (hours == 0)
613 str = g_strdup_printf (_("%d:%02d"), minutes, seconds);
614 else
615 str = g_strdup_printf (_("%d:%02d:%02d"), hours, minutes, seconds);
617 return str;
620 char *
621 rb_make_elapsed_time_string (guint elapsed, guint duration, gboolean show_remaining)
623 int seconds = 0, minutes = 0, hours = 0;
624 int seconds2 = 0, minutes2 = 0, hours2 = 0;
626 if (duration == 0)
627 return rb_make_duration_string (elapsed);
629 if (duration > 0) {
630 hours2 = duration / (60 * 60);
631 minutes2 = (duration - (hours2 * 60 * 60)) / 60;
632 seconds2 = duration % 60;
635 if (elapsed > 0) {
636 hours = elapsed / (60 * 60);
637 minutes = (elapsed - (hours * 60 * 60)) / 60;
638 seconds = elapsed % 60;
641 if (show_remaining) {
642 int remaining = duration - elapsed;
643 int remaining_hours = remaining / (60 * 60);
644 int remaining_minutes = (remaining - (remaining_hours * 60 * 60)) / 60;
645 /* remaining could conceivably be negative. This would
646 * be a bug, but the elapsed time will display right
647 * with the abs(). */
648 int remaining_seconds = abs (remaining % 60);
649 if (hours2 == 0)
650 return g_strdup_printf (_("%d:%02d of %d:%02d remaining"),
651 remaining_minutes, remaining_seconds,
652 minutes2, seconds2);
653 else
654 return g_strdup_printf (_("%d:%02d:%02d of %d:%02d:%02d remaining"),
655 remaining_hours, remaining_minutes, remaining_seconds,
656 hours2, minutes2, seconds2);
657 } else {
658 if (hours == 0 && hours2 == 0)
659 return g_strdup_printf (_("%d:%02d of %d:%02d"),
660 minutes, seconds,
661 minutes2, seconds2);
662 else
663 return g_strdup_printf (_("%d:%02d:%02d of %d:%02d:%02d"),
664 hours, minutes, seconds,
665 hours2, minutes2, seconds2);
669 gboolean
670 rb_string_list_equal (GList *a, GList *b)
672 GList *sorted_a_keys;
673 GList *sorted_b_keys;
674 GList *a_ptr, *b_ptr;
675 gboolean ret = TRUE;
677 if (a == b)
678 return TRUE;
680 if (g_list_length (a) != g_list_length (b))
681 return FALSE;
683 for (sorted_a_keys = NULL; a; a = a->next) {
684 sorted_a_keys = g_list_prepend (sorted_a_keys,
685 g_utf8_collate_key (a->data, -1));
687 for (sorted_b_keys = NULL; b; b = b->next) {
688 sorted_b_keys = g_list_prepend (sorted_b_keys,
689 g_utf8_collate_key (b->data, -1));
691 sorted_a_keys = g_list_sort (sorted_a_keys, (GCompareFunc) strcmp);
692 sorted_b_keys = g_list_sort (sorted_b_keys, (GCompareFunc) strcmp);
694 for (a_ptr = sorted_a_keys, b_ptr = sorted_b_keys;
695 a_ptr && b_ptr; a_ptr = a_ptr->next, b_ptr = b_ptr->next) {
696 if (strcmp (a_ptr->data, b_ptr->data)) {
697 ret = FALSE;
698 break;
701 g_list_foreach (sorted_a_keys, (GFunc) g_free, NULL);
702 g_list_foreach (sorted_b_keys, (GFunc) g_free, NULL);
703 g_list_free (sorted_a_keys);
704 g_list_free (sorted_b_keys);
705 return ret;
708 static void
709 list_copy_cb (const char *s, GList **list)
711 *list = g_list_prepend (*list, g_strdup (s));
714 GList *
715 rb_string_list_copy (GList *list)
717 GList *copy = NULL;
719 if (list == NULL)
720 return NULL;
722 g_list_foreach (list, (GFunc)list_copy_cb, &copy);
723 copy = g_list_reverse (copy);
725 return copy;
728 void
729 rb_list_deep_free (GList *list)
731 g_list_foreach (list, (GFunc)g_free, NULL);
732 g_list_free (list);
736 static void
737 collate_keys_cb (gpointer key, gpointer value, GList **list)
739 *list = g_list_prepend (*list, key);
742 static void
743 collate_values_cb (gpointer key, gpointer value, GList **list)
745 *list = g_list_prepend (*list, value);
748 GList*
749 rb_collate_hash_table_keys (GHashTable *table)
751 GList *list = NULL;
753 g_hash_table_foreach (table, (GHFunc)collate_keys_cb, &list);
754 list = g_list_reverse (list);
756 return list;
759 GList*
760 rb_collate_hash_table_values (GHashTable *table)
762 GList *list = NULL;
764 g_hash_table_foreach (table, (GHFunc)collate_values_cb, &list);
765 list = g_list_reverse (list);
767 return list;
771 * hacked up version of gnome_vfs_uri_list_parse,
772 * that it doesn't strip #s and and returns strings.
775 GList *
776 rb_uri_list_parse (const char *uri_list)
778 const gchar *p, *q;
779 gchar *retval;
780 GList *result = NULL;
782 g_return_val_if_fail (uri_list != NULL, NULL);
784 p = uri_list;
786 while (p != NULL) {
787 while (g_ascii_isspace (*p))
788 p++;
790 q = p;
791 while ((*q != '\0')
792 && (*q != '\n')
793 && (*q != '\r'))
794 q++;
796 if (q > p) {
797 q--;
798 while (q > p
799 && g_ascii_isspace (*q))
800 q--;
802 retval = g_malloc (q - p + 2);
803 strncpy (retval, p, q - p + 1);
804 retval[q - p + 1] = '\0';
806 if (retval != NULL)
807 result = g_list_prepend (result, retval);
809 p = strchr (p, '\n');
810 if (p != NULL)
811 p++;
814 return g_list_reverse (result);
817 const gchar*
818 rb_mime_get_friendly_name (const gchar *mime_type)
820 const gchar *name = NULL;
822 if (name == NULL && mime_type)
823 name = gnome_vfs_mime_get_description (mime_type);
824 if (name == NULL)
825 name = _("Unknown");
827 return name;
830 gboolean
831 rb_signal_accumulator_object_handled (GSignalInvocationHint *hint,
832 GValue *return_accu,
833 const GValue *handler_return,
834 gpointer dummy)
836 if (handler_return == NULL ||
837 !G_VALUE_HOLDS_OBJECT (handler_return) ||
838 g_value_get_object (handler_return) == NULL)
839 return TRUE;
841 g_value_unset (return_accu);
842 g_value_init (return_accu, G_VALUE_TYPE (handler_return));
843 g_value_copy (handler_return, return_accu);
845 return FALSE;
848 void
849 rb_value_array_append_data (GValueArray *array, GType type, ...)
851 GValue val = {0,};
852 va_list va;
853 gchar *err = NULL;
855 va_start (va, type);
857 g_value_init (&val, type);
858 G_VALUE_COLLECT (&val, va, 0, &err);
859 g_value_array_append (array, &val);
860 g_value_unset (&val);
862 if (err)
863 rb_debug ("unable to collect GValue: %s", err);
865 va_end (va);
868 void
869 rb_value_free (GValue *val)
871 g_value_unset (val);
872 g_free (val);