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)
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 #include <libgnome/gnome-i18n.h>
26 #include <libgnomevfs/gnome-vfs.h>
29 static GPrivate
* private_is_primary_thread
;
32 rb_true_function (gpointer dummy
)
38 rb_false_function (gpointer dummy
)
44 rb_null_function (gpointer dummy
)
50 rb_gvalue_compare (GValue
*a
, GValue
*b
)
53 const char *stra
, *strb
;
55 switch (G_VALUE_TYPE (a
))
58 if (g_value_get_int (a
) < g_value_get_int (b
))
60 else if (g_value_get_int (a
) == g_value_get_int (b
))
66 if (g_value_get_char (a
) < g_value_get_char (b
))
68 else if (g_value_get_char (a
) == g_value_get_char (b
))
74 if (g_value_get_uchar (a
) < g_value_get_uchar (b
))
76 else if (g_value_get_uchar (a
) == g_value_get_uchar (b
))
82 if (g_value_get_int (a
) < g_value_get_int (b
))
84 else if (g_value_get_int (a
) == g_value_get_int (b
))
90 if (g_value_get_uint (a
) < g_value_get_uint (b
))
92 else if (g_value_get_uint (a
) == g_value_get_uint (b
))
98 if (g_value_get_long (a
) < g_value_get_long (b
))
100 else if (g_value_get_long (a
) == g_value_get_long (b
))
106 if (g_value_get_ulong (a
) < g_value_get_ulong (b
))
108 else if (g_value_get_ulong (a
) == g_value_get_ulong (b
))
114 if (g_value_get_int64 (a
) < g_value_get_int64 (b
))
116 else if (g_value_get_int64 (a
) == g_value_get_int64 (b
))
122 if (g_value_get_uint64 (a
) < g_value_get_uint64 (b
))
124 else if (g_value_get_uint64 (a
) == g_value_get_uint64 (b
))
130 /* this is somewhat bogus. */
131 if (g_value_get_enum (a
) < g_value_get_enum (b
))
133 else if (g_value_get_enum (a
) == g_value_get_enum (b
))
139 /* this is even more bogus. */
140 if (g_value_get_flags (a
) < g_value_get_flags (b
))
142 else if (g_value_get_flags (a
) == g_value_get_flags (b
))
148 if (g_value_get_float (a
) < g_value_get_float (b
))
150 else if (g_value_get_float (a
) == g_value_get_float (b
))
156 if (g_value_get_double (a
) < g_value_get_double (b
))
158 else if (g_value_get_double (a
) == g_value_get_double (b
))
164 stra
= g_value_get_string (a
);
165 strb
= g_value_get_string (b
);
166 if (stra
== NULL
) stra
= "";
167 if (strb
== NULL
) strb
= "";
168 retval
= g_utf8_collate (stra
, strb
);
174 g_assert_not_reached ();
182 rb_compare_gtimeval (GTimeVal
*a
, GTimeVal
*b
)
184 if (a
->tv_sec
== b
->tv_sec
)
185 /* It's quite unlikely that microseconds are equal,
186 * so just ignore that case, we don't need a lot
189 return a
->tv_usec
> b
->tv_usec
? 1 : -1;
190 else if (a
->tv_sec
> b
->tv_sec
)
196 /* Taken from totem/video-utils.c CVS HEAD 2004-04-22 */
198 totem_pixbuf_mirror (GdkPixbuf
*pixbuf
)
200 int i
, j
, rowstride
, offset
, right
;
202 int width
, height
, size
;
205 pixels
= gdk_pixbuf_get_pixels (pixbuf
);
206 g_return_if_fail (pixels
!= NULL
);
208 width
= gdk_pixbuf_get_width (pixbuf
);
209 height
= gdk_pixbuf_get_height (pixbuf
);
210 rowstride
= gdk_pixbuf_get_rowstride (pixbuf
);
211 size
= height
* width
* sizeof (guint32
);
213 for (i
= 0; i
< size
; i
+= rowstride
)
215 for (j
= 0; j
< rowstride
; j
+= sizeof(guint32
))
218 right
= i
+ (((width
- 1) * sizeof(guint32
)) - j
);
223 memcpy (&tmp
, pixels
+ offset
, sizeof(guint32
));
224 memcpy (pixels
+ offset
, pixels
+ right
,
226 memcpy (pixels
+ right
, &tmp
, sizeof(guint32
));
233 /* Same as gtk_image_new_from_stock except that it mirrors the icons for RTL
237 rb_image_new_from_stock (const gchar
*stock_id
, GtkIconSize size
)
240 if (gtk_widget_get_default_direction () == GTK_TEXT_DIR_LTR
) {
241 return gtk_image_new_from_stock (stock_id
, size
);
248 image
= gtk_image_new ();
254 pixbuf
= gtk_widget_render_icon (image
, stock_id
, size
, NULL
);
255 g_assert (pixbuf
!= NULL
);
258 mirror
= gdk_pixbuf_copy (pixbuf
);
259 gdk_pixbuf_unref (pixbuf
);
264 totem_pixbuf_mirror (mirror
);
265 gtk_image_set_from_pixbuf (GTK_IMAGE (image
), mirror
);
266 gdk_pixbuf_unref (mirror
);
275 rb_gtk_action_popup_menu (GtkUIManager
*uimanager
, const char *path
)
279 menu
= gtk_ui_manager_get_widget (uimanager
, path
);
280 gtk_menu_popup (GTK_MENU (menu
), NULL
, NULL
, NULL
, NULL
, 3,
281 gtk_get_current_event_time ());
285 get_mount_points (void)
287 GnomeVFSVolumeMonitor
*monitor
;
290 GList
*mount_points
= NULL
;
292 monitor
= gnome_vfs_get_volume_monitor ();
293 /* FIXME: should also get the list of connected drivers (network
296 volumes
= gnome_vfs_volume_monitor_get_mounted_volumes (monitor
);
298 for (it
= volumes
; it
!= NULL
; it
= it
->next
) {
300 GnomeVFSVolume
*volume
;
302 volume
= GNOME_VFS_VOLUME (it
->data
);
303 uri
= gnome_vfs_volume_get_activation_uri (volume
);
304 g_assert (uri
!= NULL
);
305 mount_points
= g_list_prepend (mount_points
, uri
);
308 g_list_foreach (volumes
, (GFunc
)gnome_vfs_volume_ref
, NULL
);
309 g_list_free (volumes
);
316 rb_uri_get_mount_point (const char *uri
)
318 GList
*mount_points
= get_mount_points ();
320 gchar
*mount_point
= NULL
;
322 for (it
= mount_points
; it
!= NULL
; it
= it
->next
) {
323 if (g_str_has_prefix (uri
, it
->data
)) {
324 if ((mount_point
== NULL
) || (strlen (mount_point
) < strlen (it
->data
))) {
325 g_free (mount_point
);
326 mount_point
= g_strdup (it
->data
);
330 g_list_foreach (mount_points
, (GFunc
)g_free
, NULL
);
331 g_list_free (mount_points
);
337 rb_uri_is_mounted (const char *uri
)
339 GList
*mount_points
= get_mount_points ();
341 gboolean found
= FALSE
;
343 if ((uri
== NULL
) || (*uri
== '\0')) {
347 for (it
= mount_points
; it
!= NULL
; it
= it
->next
) {
348 if (strcmp (it
->data
, uri
) == 0) {
353 g_list_foreach (mount_points
, (GFunc
)g_free
, NULL
);
354 g_list_free (mount_points
);
356 /* if (found == FALSE) {
357 g_print ("%s not mounted\n", uri);
364 rb_is_main_thread (void)
366 if (g_thread_supported()) {
367 return GPOINTER_TO_UINT(g_private_get (private_is_primary_thread
)) == 1;
375 rb_threads_init (void)
377 private_is_primary_thread
= g_private_new (NULL
);
378 g_private_set (private_is_primary_thread
, GUINT_TO_POINTER (1));
380 /* not really necessary, but in case it does something besides
381 * set up lock functions some day..
387 rb_string_split_words (const gchar
*string
)
389 /*return g_slist_prepend (NULL, g_strdup (string));*/
391 GSList
*words
, *current
;
392 gunichar
*unicode
, *cur_write
, *cur_read
;
394 gint i
, wordcount
= 1;
395 gboolean new_word
= TRUE
;
397 g_return_val_if_fail (string
!= NULL
, NULL
);
399 cur_write
= cur_read
= unicode
= g_utf8_to_ucs4_fast (string
, -1, NULL
);
401 /* we may fail here, we expect valid utf-8 */
402 g_return_val_if_fail (unicode
!= NULL
, NULL
);
404 words
= g_slist_prepend (NULL
, unicode
);
406 /* now normalize this text */
408 switch (g_unichar_type (*cur_read
)) {
409 case G_UNICODE_UNASSIGNED
:
410 g_warning ("unassigned unicode character type found");
412 case G_UNICODE_CONTROL
:
413 case G_UNICODE_FORMAT
:
414 case G_UNICODE_PRIVATE_USE
:
416 case G_UNICODE_SURROGATE
:
417 case G_UNICODE_LINE_SEPARATOR
:
418 case G_UNICODE_PARAGRAPH_SEPARATOR
:
419 case G_UNICODE_SPACE_SEPARATOR
:
420 /* remove these and start a new word */
422 /* end current word if it isn't ended yet */
428 case G_UNICODE_COMBINING_MARK
:
429 case G_UNICODE_ENCLOSING_MARK
:
430 case G_UNICODE_NON_SPACING_MARK
:
431 case G_UNICODE_CONNECT_PUNCTUATION
:
432 case G_UNICODE_DASH_PUNCTUATION
:
433 case G_UNICODE_CLOSE_PUNCTUATION
:
434 case G_UNICODE_FINAL_PUNCTUATION
:
435 case G_UNICODE_INITIAL_PUNCTUATION
:
436 case G_UNICODE_OTHER_PUNCTUATION
:
437 case G_UNICODE_OPEN_PUNCTUATION
:
440 case G_UNICODE_LOWERCASE_LETTER
:
441 case G_UNICODE_MODIFIER_LETTER
:
442 case G_UNICODE_OTHER_LETTER
:
443 case G_UNICODE_TITLECASE_LETTER
:
444 case G_UNICODE_UPPERCASE_LETTER
:
445 case G_UNICODE_DECIMAL_NUMBER
:
446 case G_UNICODE_LETTER_NUMBER
:
447 case G_UNICODE_OTHER_NUMBER
:
448 case G_UNICODE_CURRENCY_SYMBOL
:
449 case G_UNICODE_MODIFIER_SYMBOL
:
450 case G_UNICODE_MATH_SYMBOL
:
451 case G_UNICODE_OTHER_SYMBOL
:
452 /* keep these unchanged */
453 *cur_write
= *cur_read
;
455 if (cur_write
!= unicode
) {/* first insert has been done above */
456 words
= g_slist_prepend (words
, cur_write
);
464 g_warning ("unknown unicode character type found");
474 ret
= g_new (gchar
*, wordcount
+ 1);
476 for (i
= wordcount
- 1; i
>= 0; i
--) {
477 ret
[i
] = g_ucs4_to_utf8 (current
->data
, -1, NULL
, NULL
, NULL
);
478 current
= g_slist_next (current
);
480 ret
[wordcount
] = NULL
;
482 g_slist_free (words
);
489 rb_search_fold (const char *original
)
492 gunichar
*unicode
, *cur
;
494 g_return_val_if_fail (original
!= NULL
, NULL
);
496 /* old behaviour is equivalent to: return g_utf8_casefold (original, -1); */
498 string
= g_string_new (NULL
);
499 unicode
= g_utf8_to_ucs4_fast (original
, -1, NULL
);
501 for (cur
= unicode
; *cur
!= 0; cur
++) {
502 switch (g_unichar_type (*cur
)) {
503 case G_UNICODE_COMBINING_MARK
:
504 case G_UNICODE_ENCLOSING_MARK
:
505 case G_UNICODE_NON_SPACING_MARK
:
506 case G_UNICODE_CONNECT_PUNCTUATION
:
507 case G_UNICODE_DASH_PUNCTUATION
:
508 case G_UNICODE_CLOSE_PUNCTUATION
:
509 case G_UNICODE_FINAL_PUNCTUATION
:
510 case G_UNICODE_INITIAL_PUNCTUATION
:
511 case G_UNICODE_OTHER_PUNCTUATION
:
512 case G_UNICODE_OPEN_PUNCTUATION
:
516 case G_UNICODE_LOWERCASE_LETTER
:
517 case G_UNICODE_MODIFIER_LETTER
:
518 case G_UNICODE_OTHER_LETTER
:
519 case G_UNICODE_TITLECASE_LETTER
:
520 case G_UNICODE_UPPERCASE_LETTER
:
521 /* convert to lower case */
522 *cur
= g_unichar_tolower (*cur
);
523 /* ... and fall through */\
524 case G_UNICODE_DECIMAL_NUMBER
:
525 case G_UNICODE_LETTER_NUMBER
:
526 case G_UNICODE_OTHER_NUMBER
:
527 /* should be keep symbols? */
528 case G_UNICODE_CURRENCY_SYMBOL
:
529 case G_UNICODE_MODIFIER_SYMBOL
:
530 case G_UNICODE_MATH_SYMBOL
:
531 case G_UNICODE_OTHER_SYMBOL
:
532 g_string_append_unichar (string
, *cur
);
535 case G_UNICODE_UNASSIGNED
:
536 g_warning ("unassigned unicode character type found");
541 g_string_append_unichar (string
, *cur
);
547 return g_string_free (string
, FALSE
);
551 rb_make_duration_string (guint duration
)
554 int hours
, minutes
, seconds
;
556 hours
= duration
/ (60 * 60);
557 minutes
= (duration
- (hours
* 60 * 60)) / 60;
558 seconds
= duration
% 60;
560 if (hours
== 0 && minutes
== 0 && seconds
== 0)
561 str
= g_strdup (_("Unknown"));
563 str
= g_strdup_printf (_("%d:%02d"), minutes
, seconds
);
565 str
= g_strdup_printf (_("%d:%02d:%02d"), hours
, minutes
, seconds
);
571 rb_string_list_equal (GList
*a
, GList
*b
)
573 GList
*sorted_a_keys
;
574 GList
*sorted_b_keys
;
575 GList
*a_ptr
, *b_ptr
;
581 if (g_list_length (a
) != g_list_length (b
))
584 for (sorted_a_keys
= NULL
; a
; a
= a
->next
) {
585 sorted_a_keys
= g_list_prepend (sorted_a_keys
,
586 g_utf8_collate_key (a
->data
, -1));
588 for (sorted_b_keys
= NULL
; b
; b
= b
->next
) {
589 sorted_b_keys
= g_list_prepend (sorted_b_keys
,
590 g_utf8_collate_key (b
->data
, -1));
592 sorted_a_keys
= g_list_sort (sorted_a_keys
, (GCompareFunc
) strcmp
);
593 sorted_b_keys
= g_list_sort (sorted_b_keys
, (GCompareFunc
) strcmp
);
595 for (a_ptr
= sorted_a_keys
, b_ptr
= sorted_b_keys
;
596 a_ptr
&& b_ptr
; a_ptr
= a_ptr
->next
, b_ptr
= b_ptr
->next
) {
597 if (strcmp (a_ptr
->data
, b_ptr
->data
)) {
602 g_list_foreach (sorted_a_keys
, (GFunc
) g_free
, NULL
);
603 g_list_foreach (sorted_b_keys
, (GFunc
) g_free
, NULL
);
604 g_list_free (sorted_a_keys
);
605 g_list_free (sorted_b_keys
);
610 list_copy_cb (const char *s
, GList
**list
)
612 *list
= g_list_prepend (*list
, g_strdup (s
));
616 rb_string_list_copy (GList
*list
)
623 g_list_foreach (list
, (GFunc
)list_copy_cb
, ©
);
624 copy
= g_list_reverse (copy
);
630 rb_list_deep_free (GList
*list
)
632 g_list_foreach (list
, (GFunc
)g_free
, NULL
);
638 collate_keys_cb (gpointer key
, gpointer value
, GList
**list
)
640 *list
= g_list_prepend (*list
, key
);
644 collate_values_cb (gpointer key
, gpointer value
, GList
**list
)
646 *list
= g_list_prepend (*list
, value
);
650 rb_collate_hash_table_keys (GHashTable
*table
)
654 g_hash_table_foreach (table
, (GHFunc
)collate_keys_cb
, &list
);
655 list
= g_list_reverse (list
);
661 rb_collate_hash_table_values (GHashTable
*table
)
665 g_hash_table_foreach (table
, (GHFunc
)collate_values_cb
, &list
);
666 list
= g_list_reverse (list
);