1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
4 * Copyright (C) Naba Kumar <naba@gnome.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 of the License, or
9 * (at your option) 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 Street, Fifth Floor, Boston, MA 02110-1301 USA
22 * SECTION:anjuta-utils
24 * @short_description: Utility functions
26 * @stability: Unstable
27 * @include: libanjuta/anjuta-utils.h
40 #include <sys/types.h>
41 #include <sys/fcntl.h>
42 #include <sys/termios.h>
49 #include <glib/gi18n.h>
51 #include <glib/gstdio.h>
57 #define WIN32_MEAN_AND_LEAN
61 #include <libanjuta/anjuta-utils.h>
62 #include <libanjuta/anjuta-debug.h>
63 #include <libanjuta/interfaces/ianjuta-editor-cell.h>
65 #define FILE_BUFFER_SIZE 1024
67 /* Common preferences */
68 #define ANJUTA_PREF_SCHEMA "org.gnome.anjuta"
70 #define LAST_EMAIL "email"
73 static gchar
*anjuta_prefix
= "anjuta";
76 anjuta_util_from_file_to_file (GInputStream
*istream
,
77 GOutputStream
*ostream
)
81 gchar buffer
[FILE_BUFFER_SIZE
];
83 while (bytes
!= 0 && bytes
!= -1)
85 bytes
= g_input_stream_read (istream
, buffer
,
91 g_output_stream_write (ostream
, buffer
,
100 g_warning ("%s", error
->message
);
101 g_error_free (error
);
105 if (!g_output_stream_close (ostream
, NULL
, &error
))
107 g_warning ("%s", error
->message
);
108 g_error_free (error
);
111 if (!g_input_stream_close (istream
, NULL
, &error
))
113 g_warning ("%s", error
->message
);
114 g_error_free (error
);
119 * anjuta_util_copy_file:
120 * @src: the file where copy
121 * @dest: the path to copy the @src
122 * @show_error: %TRUE to show a dialog error
124 * Copies @src to @dest and shows a dialog error in case is needed.
126 * Returns: %TRUE if there was an error copying the file.
129 anjuta_util_copy_file (const gchar
* src
, const gchar
* dest
, gboolean show_error
)
131 GFile
*src_file
, *dest_file
;
132 GFileInputStream
*istream
;
133 GFileOutputStream
*ostream
;
134 GError
*error
= NULL
;
135 gboolean toret
= FALSE
;
137 src_file
= g_file_new_for_path (src
);
138 dest_file
= g_file_new_for_path (dest
);
140 istream
= g_file_read (src_file
, NULL
, &error
);
144 ostream
= g_file_create (dest_file
, G_FILE_CREATE_NONE
,
149 anjuta_util_from_file_to_file (G_INPUT_STREAM (istream
), G_OUTPUT_STREAM (ostream
));
154 anjuta_util_dialog_error_system (NULL
, error
->code
,
157 g_warning ("%s", error
->message
);
162 g_object_unref (src_file
);
163 g_object_unref (dest_file
);
169 anjuta_util_color_from_string (const gchar
* val
, guint16
* r
, guint16
* g
, guint16
* b
)
172 if (gdk_color_parse(val
, &color
))
181 anjuta_util_string_from_color (guint16 r
, guint16 g
, guint16 b
)
183 return g_strdup_printf("#%02x%02x%02x", r
>> 8, g
>> 8, b
>> 8);
187 anjuta_util_button_new_with_stock_image (const gchar
* text
,
188 const gchar
* stock_id
)
198 button
= gtk_button_new ();
200 child
= gtk_bin_get_child (GTK_BIN (button
));
202 gtk_container_remove (GTK_CONTAINER (button
), child
);
204 if (gtk_stock_lookup (stock_id
, &item
))
206 label
= gtk_label_new_with_mnemonic (text
);
208 gtk_label_set_mnemonic_widget (GTK_LABEL (label
), GTK_WIDGET (button
));
210 image
= gtk_image_new_from_stock (stock_id
, GTK_ICON_SIZE_BUTTON
);
211 hbox
= gtk_box_new (GTK_ORIENTATION_HORIZONTAL
, 2);
213 align
= gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
215 gtk_box_pack_start (GTK_BOX (hbox
), image
, FALSE
, FALSE
, 0);
216 gtk_box_pack_end (GTK_BOX (hbox
), label
, FALSE
, FALSE
, 0);
218 gtk_container_add (GTK_CONTAINER (button
), align
);
219 gtk_container_add (GTK_CONTAINER (align
), hbox
);
220 gtk_widget_show_all (align
);
225 label
= gtk_label_new_with_mnemonic (text
);
226 gtk_label_set_mnemonic_widget (GTK_LABEL (label
), GTK_WIDGET (button
));
228 gtk_misc_set_alignment (GTK_MISC (label
), 0.5, 0.5);
230 gtk_widget_show (label
);
231 gtk_container_add (GTK_CONTAINER (button
), label
);
237 anjuta_util_dialog_add_button (GtkDialog
*dialog
, const gchar
* text
,
238 const gchar
* stock_id
, gint response_id
)
242 g_return_val_if_fail (GTK_IS_DIALOG (dialog
), NULL
);
243 g_return_val_if_fail (text
!= NULL
, NULL
);
244 g_return_val_if_fail (stock_id
!= NULL
, NULL
);
246 button
= anjuta_util_button_new_with_stock_image (text
, stock_id
);
247 g_return_val_if_fail (button
!= NULL
, NULL
);
249 gtk_widget_set_can_default (button
, TRUE
);
251 gtk_widget_show (button
);
253 gtk_dialog_add_action_widget (dialog
, button
, response_id
);
259 anjuta_util_dialog_error (GtkWindow
*parent
, const gchar
*mesg
, ...)
264 GtkWindow
*real_parent
;
266 va_start (args
, mesg
);
267 message
= g_strdup_vprintf (mesg
, args
);
270 if (parent
&& GTK_IS_WINDOW (parent
))
272 real_parent
= parent
;
279 // Dialog to be HIG compliant
280 dialog
= gtk_message_dialog_new (real_parent
,
281 GTK_DIALOG_DESTROY_WITH_PARENT
,
283 GTK_BUTTONS_CLOSE
, "%s", message
);
284 g_signal_connect (G_OBJECT (dialog
), "response",
285 G_CALLBACK (gtk_widget_destroy
), NULL
);
286 gtk_widget_show (dialog
);
291 anjuta_util_dialog_warning (GtkWindow
*parent
, const gchar
* mesg
, ...)
296 GtkWindow
*real_parent
;
298 va_start (args
, mesg
);
299 message
= g_strdup_vprintf (mesg
, args
);
302 if (parent
&& GTK_IS_WINDOW (parent
))
304 real_parent
= parent
;
311 // Dialog to be HIG compliant
312 dialog
= gtk_message_dialog_new (real_parent
,
313 GTK_DIALOG_DESTROY_WITH_PARENT
,
315 GTK_BUTTONS_CLOSE
, "%s", message
);
316 g_signal_connect (G_OBJECT (dialog
), "response",
317 G_CALLBACK (gtk_widget_destroy
), NULL
);
318 gtk_widget_show (dialog
);
323 anjuta_util_dialog_info (GtkWindow
*parent
, const gchar
* mesg
, ...)
328 GtkWindow
*real_parent
;
330 va_start (args
, mesg
);
331 message
= g_strdup_vprintf (mesg
, args
);
334 if (parent
&& GTK_IS_WINDOW (parent
))
336 real_parent
= parent
;
342 // Dialog to be HIG compliant
343 dialog
= gtk_message_dialog_new (real_parent
,
344 GTK_DIALOG_DESTROY_WITH_PARENT
,
346 GTK_BUTTONS_CLOSE
, "%s", message
);
347 g_signal_connect (G_OBJECT (dialog
), "response",
348 G_CALLBACK (gtk_widget_destroy
), NULL
);
349 gtk_widget_show (dialog
);
354 anjuta_util_dialog_error_system (GtkWindow
* parent
, gint errnum
,
355 const gchar
* mesg
, ... )
361 GtkWindow
*real_parent
;
363 va_start (args
, mesg
);
364 message
= g_strdup_vprintf (mesg
, args
);
368 /* Avoid space in translated string */
369 tot_mesg
= g_strconcat (message
, "\n", _("System:"), " ",
370 g_strerror(errnum
), NULL
);
375 if (parent
&& GTK_IS_WINDOW (parent
))
377 real_parent
= parent
;
383 // Dialog to be HIG compliant
384 dialog
= gtk_message_dialog_new (real_parent
,
385 GTK_DIALOG_DESTROY_WITH_PARENT
,
387 GTK_BUTTONS_CLOSE
, "%s", tot_mesg
);
388 g_signal_connect (G_OBJECT (dialog
), "response",
389 G_CALLBACK (gtk_widget_destroy
), NULL
);
390 gtk_widget_show (dialog
);
395 anjuta_util_dialog_boolean_question (GtkWindow
*parent
, gboolean default_to_yes
,
396 const gchar
*mesg
, ...)
402 GtkWindow
*real_parent
;
404 va_start (args
, mesg
);
405 message
= g_strdup_vprintf (mesg
, args
);
408 if (parent
&& GTK_IS_WINDOW (parent
))
410 real_parent
= parent
;
417 dialog
= gtk_message_dialog_new (real_parent
,
418 GTK_DIALOG_DESTROY_WITH_PARENT
,
419 GTK_MESSAGE_QUESTION
,
420 GTK_BUTTONS_YES_NO
, "%s", message
);
422 gtk_dialog_set_default_response (GTK_DIALOG (dialog
), GTK_RESPONSE_YES
);
424 ret
= gtk_dialog_run (GTK_DIALOG (dialog
));
425 gtk_widget_destroy (dialog
);
428 return (ret
== GTK_RESPONSE_YES
);
432 anjuta_util_dialog_input (GtkWindow
*parent
, const gchar
*prompt
,
433 const gchar
*default_value
, gchar
**return_value
)
435 GtkWidget
*dialog
, *label
, *frame
, *entry
, *dialog_vbox
, *vbox
;
438 GtkWindow
*real_parent
;
440 if (parent
&& GTK_IS_WINDOW (parent
))
442 real_parent
= parent
;
449 dialog
= gtk_dialog_new_with_buttons (prompt
, real_parent
,
450 GTK_DIALOG_DESTROY_WITH_PARENT
,
451 GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
,
452 GTK_STOCK_OK
, GTK_RESPONSE_OK
,
454 gtk_dialog_set_default_response (GTK_DIALOG (dialog
), GTK_RESPONSE_OK
);
455 dialog_vbox
= gtk_dialog_get_content_area (GTK_DIALOG (dialog
));
456 gtk_window_set_default_size (GTK_WINDOW (dialog
), 400, -1);
457 gtk_widget_show (dialog_vbox
);
459 markup
= g_strconcat ("<b>", prompt
, "</b>", NULL
);
460 label
= gtk_label_new (NULL
);
461 gtk_label_set_markup (GTK_LABEL (label
), markup
);
462 gtk_widget_show (label
);
465 frame
= gtk_frame_new (NULL
);
466 gtk_frame_set_label_widget (GTK_FRAME (frame
), label
);
467 gtk_frame_set_shadow_type (GTK_FRAME (frame
), GTK_SHADOW_NONE
);
468 gtk_container_set_border_width (GTK_CONTAINER (frame
), 10);
469 gtk_widget_show (frame
);
470 gtk_box_pack_start (GTK_BOX (dialog_vbox
), frame
, FALSE
, FALSE
, 0);
472 vbox
= gtk_box_new (GTK_ORIENTATION_VERTICAL
, 0);
473 gtk_widget_show (vbox
);
474 gtk_container_set_border_width (GTK_CONTAINER (vbox
), 10);
475 gtk_container_add (GTK_CONTAINER (frame
), vbox
);
477 entry
= gtk_entry_new ();
478 gtk_widget_show (entry
);
479 gtk_entry_set_activates_default (GTK_ENTRY (entry
), TRUE
);
480 gtk_box_pack_start (GTK_BOX (vbox
), entry
, FALSE
, FALSE
, 0);
482 gtk_entry_set_text (GTK_ENTRY (entry
), default_value
);
484 res
= gtk_dialog_run (GTK_DIALOG (dialog
));
486 if (gtk_entry_get_text (GTK_ENTRY (entry
)) &&
487 strlen (gtk_entry_get_text (GTK_ENTRY (entry
))) > 0)
489 *return_value
= g_strdup (gtk_entry_get_text (GTK_ENTRY (entry
)));
493 *return_value
= NULL
;
495 gtk_widget_destroy (dialog
);
496 return (res
== GTK_RESPONSE_OK
);
500 on_install_files_done (GObject
*proxy
, GAsyncResult
*result
,
503 GError
*error
= NULL
;
504 g_dbus_proxy_call_finish ((GDBusProxy
*) proxy
, result
, &error
);
508 Only dbus error is handled. Rest of the errors are from packagekit
509 which have already been notified to user by packagekit.
511 if (error
->domain
== G_DBUS_ERROR
)
513 const gchar
*error_message
= NULL
;
515 /* Service error which implies packagekit is missing */
516 if (error
->code
== G_DBUS_ERROR_SERVICE_UNKNOWN
)
518 error_message
= _("You do not seem to have PackageKit installed. PackageKit is required for installing missing packages. Please install \"packagekit-gnome\" package from your distribution, or install the missing packages manually.");
520 /* General dbus error implies failure to call dbus method */
521 else if (error
->code
!= G_DBUS_ERROR_NO_REPLY
)
523 error_message
= error
->message
;
526 anjuta_util_dialog_error (NULL
,
527 _("Installation failed: %s"),
530 g_error_free (error
);
535 anjuta_util_install_files (const gchar
* const names
)
537 GDBusConnection
* connection
;
545 connection
= g_bus_get_sync (G_BUS_TYPE_SESSION
, NULL
, NULL
);
549 proxy
= g_dbus_proxy_new_sync (connection
,
550 G_DBUS_PROXY_FLAGS_NONE
,
552 "org.freedesktop.PackageKit",
553 "/org/freedesktop/PackageKit",
554 "org.freedesktop.PackageKit.Modify",
560 pkgv
= g_strsplit (names
, ", ", 0);
561 g_dbus_proxy_call (proxy
, "InstallProvideFiles",
562 g_variant_new ("(u^ass)",
566 G_DBUS_CALL_FLAGS_NONE
,
569 on_install_files_done
,
576 anjuta_util_package_is_installed (const gchar
* package
, gboolean show
)
578 const gchar
* const argv
[] = { "pkg-config", "--exists", package
, NULL
};
582 if (!g_spawn_sync (NULL
, (gchar
**)argv
, NULL
, G_SPAWN_SEARCH_PATH
, NULL
,
583 NULL
, NULL
, NULL
, &exit_status
, &err
))
587 anjuta_util_dialog_error (NULL
,
588 _("Failed to run \"%s\". "
589 "The returned error was: \"%s\"."),
590 "pkg-config --exists", err
->message
);
596 if (g_spawn_check_exit_status (exit_status
, NULL
))
601 anjuta_util_dialog_error (NULL
,
602 _("The \"%s\" package is not installed.\n"
603 "Please install it."), package
);
610 anjuta_util_prog_is_installed (const gchar
* prog
, gboolean show
)
612 gchar
* prog_path
= g_find_program_in_path (prog
);
620 anjuta_util_dialog_error (NULL
, _("The \"%s\" utility is not installed.\n"
621 "Please install it."), prog
);
627 anjuta_util_get_a_tmp_file (void)
629 static gint count
= 0;
633 tmpdir
= g_get_tmp_dir ();
635 g_strdup_printf ("%s/anjuta_%d.%d", tmpdir
, count
++, getpid ());
639 /* GList of strings operations */
641 anjuta_util_glist_from_string (const gchar
*string
)
643 gchar
*str
, *temp
, buff
[256];
645 gchar
*word_start
, *word_end
;
648 temp
= g_strdup (string
);
658 /* Remove leading spaces */
659 while (isspace (*str
) && *str
!= '\0')
664 /* Find start and end of word */
666 while (!isspace (*str
) && *str
!= '\0')
670 /* Copy the word into the buffer */
671 for (ptr
= word_start
, i
= 0; ptr
< word_end
; ptr
++, i
++)
675 list
= g_list_append (list
, g_strdup (buff
));
684 /* Prefix the strings */
686 anjuta_util_glist_strings_prefix (GList
* list
, const gchar
*prefix
)
691 g_return_if_fail (prefix
!= NULL
);
696 node
->data
= g_strconcat (prefix
, tmp
, NULL
);
697 if (tmp
) g_free (tmp
);
698 node
= g_list_next (node
);
702 /* Suffix the strings */
704 anjuta_util_glist_strings_sufix (GList
* list
, const gchar
*sufix
)
709 g_return_if_fail (sufix
!= NULL
);
714 node
->data
= g_strconcat (tmp
, sufix
, NULL
);
715 if (tmp
) g_free (tmp
);
716 node
= g_list_next (node
);
720 /* Duplicate list of strings */
722 anjuta_util_glist_strings_dup (GList
* list
)
732 new_list
= g_list_append (new_list
, g_strdup(node
->data
));
734 new_list
= g_list_append (new_list
, NULL
);
735 node
= g_list_next (node
);
740 /* Join list of strings using the given delimiter */
742 anjuta_util_glist_strings_join (GList
* list
, gchar
*delimiter
)
745 gboolean first
= TRUE
;
748 joined
= g_string_new (NULL
);
755 g_string_append (joined
, delimiter
);
758 g_string_append (joined
, node
->data
);
760 node
= g_list_next (node
);
763 return g_string_free (joined
, FALSE
);
765 g_string_free (joined
, TRUE
);
770 anjuta_util_get_real_path (const gchar
*path
)
777 gchar buf
[PATH_MAX
+1];
779 result
= realpath (path
, buf
);
782 *(buf
+ PATH_MAX
) = '\0'; /* ensure a terminator */
783 return g_strdup (buf
);
787 /* the string returned by realpath should be cleaned with
788 free(), not g_free() */
789 buf
= realpath (path
, NULL
);
792 result
= g_strdup (buf
);
801 /* Get length of path */
802 rc
= GetFullPathName (path
, 1, &dummy
, NULL
);
806 return g_strdup (path
);
810 result
= g_malloc (len
);
812 /* Get the real path */
813 rc
= GetFullPathName (path
, len
, result
, NULL
);
814 if (rc
== 0 || rc
> len
)
816 /* Another weird failure */
818 return g_strdup (path
);
828 * anjuta_util_get_current_dir:
830 * Get current working directory, unlike g_get_current_dir, keeps symbolic links
833 * Returns: The current working directory.
836 anjuta_util_get_current_dir (void)
840 pwd
= g_getenv ("PWD");
843 return g_strdup (pwd
);
847 return g_get_current_dir ();
852 is_valid_scheme_character (char c
)
854 return g_ascii_isalnum (c
) || c
== '+' || c
== '-' || c
== '.';
857 /* Following RFC 2396, valid schemes are built like:
858 * scheme = alpha *( alpha | digit | "+" | "-" | "." )
861 has_valid_scheme (const char *uri
)
867 if (!g_ascii_isalpha (*p
))
872 } while (is_valid_scheme_character (*p
));
878 * anjuta_util_file_new_for_commandline_arg:
879 * @arg: URI or relative or absolute file path
881 * Create a new file corresponding to arg, unlike g_file_new_for_commandline_arg,
882 * keeps symbolic links in path name.
884 * Returns: (transfer full): A new GFile object
887 anjuta_util_file_new_for_commandline_arg (const gchar
*arg
)
893 g_return_val_if_fail (arg
!= NULL
, NULL
);
895 if (g_path_is_absolute (arg
))
896 return g_file_new_for_path (arg
);
898 if (has_valid_scheme (arg
))
899 return g_file_new_for_uri (arg
);
901 current_dir
= anjuta_util_get_current_dir ();
902 filename
= g_build_filename (current_dir
, arg
, NULL
);
903 g_free (current_dir
);
905 file
= g_file_new_for_path (filename
);
912 /* Dedup a list of paths - duplicates are removed from the tail.
913 ** Useful for deduping Recent Files and Recent Projects */
915 anjuta_util_glist_path_dedup(GList
*list
)
917 GList
*nlist
= NULL
, *tmp
, *tmp1
;
920 for (tmp
= list
; tmp
; tmp
= g_list_next(tmp
))
922 path
= anjuta_util_get_real_path ((const gchar
*) tmp
->data
);
925 if (stat (path
, &s
) != 0)
931 for (tmp1
= nlist
; tmp1
; tmp1
= g_list_next(tmp1
))
933 if (0 == strcmp((const char *) tmp1
->data
, path
))
941 nlist
= g_list_prepend(nlist
, path
);
945 anjuta_util_glist_strings_free(list
);
946 nlist
= g_list_reverse(nlist
);
951 sort_node (gchar
* a
, gchar
*b
)
953 if ( !a
&& !b
) return 0;
954 else if (!a
) return -1;
955 else if (!b
) return 1;
956 return strcmp (a
, b
);
959 /* Sort the list alphabatically */
961 anjuta_util_glist_strings_sort (GList
* list
)
963 return g_list_sort(list
, (GCompareFunc
)sort_node
);
966 /* Free the strings and GList */
968 anjuta_util_glist_strings_free (GList
* list
)
970 g_list_foreach (list
, (GFunc
) g_free
, NULL
);
975 anjuta_util_type_from_string (AnjutaUtilStringMap
*map
, const char *str
)
979 while (-1 != map
[i
].type
)
981 if (0 == strcmp(map
[i
].name
, str
))
989 anjuta_util_string_from_type (AnjutaUtilStringMap
*map
, int type
)
992 while (-1 != map
[i
].type
)
994 if (map
[i
].type
== type
)
1002 anjuta_util_glist_from_map (AnjutaUtilStringMap
*map
)
1004 GList
*out_list
= NULL
;
1006 while (-1 != map
[i
].type
)
1008 out_list
= g_list_append(out_list
, map
[i
].name
);
1016 anjuta_util_update_string_list (GList
*p_list
, const gchar
*p_str
, gint length
)
1022 for (i
= 0; i
< g_list_length (p_list
); i
++)
1024 str
= (gchar
*) g_list_nth_data (p_list
, i
);
1027 if (strcmp (p_str
, str
) == 0)
1029 p_list
= g_list_remove (p_list
, str
);
1030 p_list
= g_list_prepend (p_list
, str
);
1034 p_list
= g_list_prepend (p_list
, g_strdup (p_str
));
1035 while (g_list_length (p_list
) > length
)
1037 str
= g_list_nth_data (p_list
, g_list_length (p_list
) - 1);
1038 p_list
= g_list_remove (p_list
, str
);
1045 anjuta_util_create_dir (const gchar
* path
)
1047 GFile
*dir
= g_file_new_for_path (path
);
1051 if (g_file_query_exists (dir
, NULL
))
1053 GFileInfo
*info
= g_file_query_info (dir
,
1054 G_FILE_ATTRIBUTE_STANDARD_TYPE
,
1055 G_FILE_QUERY_INFO_NONE
,
1057 if (g_file_info_get_file_type (info
) != G_FILE_TYPE_DIRECTORY
)
1059 g_message ("Warning: %s is a file. \n "
1060 "It is trying to be treated as a directory.",g_file_get_path (dir
));
1061 g_object_unref (dir
);
1064 g_object_unref (info
);
1068 parent
= g_path_get_dirname (path
);
1069 if (anjuta_util_create_dir (parent
))
1072 if (!g_file_make_directory (dir
, NULL
, &err
))
1074 g_warning ("Error directory:\n %s", err
->message
);
1075 g_object_unref (dir
);
1082 g_object_unref (dir
);
1086 g_object_unref (dir
);
1092 * anjuta_util_user_shell:
1094 * Retrieves the user's preferred shell.
1096 * Returns: A newly allocated string that is the path to the shell.
1098 /* copied from deprecated gnome_util_user_shell in libgnome */
1100 anjuta_util_user_shell (void)
1106 const gchar shells
[][14] = {
1107 /* Note that on some systems shells can also
1108 * be installed in /usr/bin */
1109 "/bin/bash", "/usr/bin/bash",
1110 "/bin/zsh", "/usr/bin/zsh",
1111 "/bin/tcsh", "/usr/bin/tcsh",
1112 "/bin/ksh", "/usr/bin/ksh",
1113 "/bin/csh", "/bin/sh"
1116 if (geteuid () == getuid () &&
1117 getegid () == getgid ()) {
1118 /* only in non-setuid */
1119 if ((shell
= g_getenv ("SHELL"))){
1120 if (access (shell
, X_OK
) == 0) {
1121 return g_strdup (shell
);
1125 pw
= getpwuid(getuid());
1126 if (pw
&& pw
->pw_shell
) {
1127 if (access (pw
->pw_shell
, X_OK
) == 0) {
1128 return g_strdup (pw
->pw_shell
);
1132 for (i
= 0; i
!= G_N_ELEMENTS (shells
); i
++) {
1133 if (access (shells
[i
], X_OK
) == 0) {
1134 return g_strdup (shells
[i
]);
1138 /* If /bin/sh doesn't exist, your system is truly broken. */
1141 /* Placate compiler. */
1144 /* g_find_program_in_path() always looks also in the Windows
1145 * and System32 directories, so it should always find either cmd.exe
1148 gchar
*retval
= g_find_program_in_path ("cmd.exe");
1151 retval
= g_find_program_in_path ("command.com");
1153 g_assert (retval
!= NULL
);
1160 * anjuta_util_user_terminal:
1162 * Retrieves the user's preferred terminal.
1164 * Returns: (transfer full): A newly allocated strings list. The first argument
1165 * is the terminal program name. The following are the arguments needed to
1166 * execute a command. The list has to be freed with g_strfreev
1168 /* copied from deprecated gnome_execute_terminal in libgnome */
1170 anjuta_util_user_terminal (void)
1172 gchar
*terminal
= NULL
;
1173 gchar
**argv
= NULL
;
1174 static const gchar
*terms
[] = {
1185 GSettingsSchema
*schema
;
1187 schema
= g_settings_schema_source_lookup (g_settings_schema_source_get_default (),
1188 "org.gnome.desktop.default-applications.terminal",
1193 GSettings
*settings
= g_settings_new ("org.gnome.desktop.default-applications.terminal");
1195 argv
= g_new0 (gchar
*, 3);
1196 argv
[0] = g_settings_get_string (settings
, "exec");
1197 argv
[1] = g_settings_get_string (settings
, "exec-arg");
1199 g_settings_schema_unref (schema
);
1200 g_object_unref (settings
);
1206 /* Search for common ones */
1207 for (term
= terms
; *term
!= NULL
; term
++)
1209 terminal
= g_find_program_in_path (*term
);
1210 if (terminal
!= NULL
) break;
1214 g_warning (_("Cannot find a terminal; using "
1215 "xterm, even if it may not work"));
1216 terminal
= g_strdup ("xterm");
1218 argv
= g_new0 (char *, 3);
1220 /* Note that gnome-terminal takes -x and
1221 * as -e in gnome-terminal is broken we use that. */
1222 argv
[1] = g_strdup (term
== &terms
[2] ? "-x" : "-e");
1228 close_pid (GPid pid
,
1232 g_spawn_close_pid (pid
);
1236 anjuta_util_execute_shell (const gchar
*dir
, const gchar
*command
)
1240 GError
*error
= NULL
;
1242 g_return_val_if_fail (command
!= NULL
, -1);
1244 argv
= g_new0 (gchar
*, 4);
1246 argv
[0] = anjuta_util_user_shell ();
1248 argv
[1] = g_strdup ("-c");
1250 argv
[2] = g_strdup ("/C");
1252 argv
[3] = g_strdup (command
);
1255 anjuta_util_create_dir (dir
);
1257 if (!g_spawn_async (dir
, argv
, NULL
,
1258 G_SPAWN_SEARCH_PATH
| G_SPAWN_DO_NOT_REAP_CHILD
,
1259 NULL
, NULL
, &pid
, &error
))
1261 g_warning (_("Cannot execute command: %s (using shell %s): %s\n"),
1262 command
, argv
[0], error
->message
);
1266 g_child_watch_add (pid
, close_pid
, NULL
);
1270 // Anjuta will take care of child exit automatically.
1275 anjuta_util_execute_terminal_shell (const gchar
*dir
, const gchar
*command
)
1282 GError
*error
= NULL
;
1284 g_return_val_if_fail (command
!= NULL
, -1);
1286 shell
= anjuta_util_user_shell ();
1287 term_argv
= anjuta_util_user_terminal ();
1288 argv
= g_new0 (gchar
*, g_strv_length (term_argv
) + 4);
1293 for (; term_argv
[i
]; i
++)
1294 argv
[i
] = term_argv
[i
];
1299 argv
[i
++] = g_strdup ("-c");
1301 argv
[i
++] = g_strdup ("/C");
1303 argv
[i
++] = g_strdup (command
);
1306 anjuta_util_create_dir (dir
);
1308 if (!g_spawn_async (dir
, argv
, NULL
,
1309 G_SPAWN_SEARCH_PATH
| G_SPAWN_DO_NOT_REAP_CHILD
,
1310 NULL
, NULL
, &pid
, &error
))
1312 g_warning (_("Cannot execute command: %s (using shell %s): %s\n"),
1313 command
, shell
, error
->message
);
1317 g_child_watch_add (pid
, close_pid
, NULL
);
1322 // Anjuta will take care of child exit automatically.
1327 anjuta_util_convert_to_utf8 (const gchar
*str
)
1329 GError
*error
= NULL
;
1330 gchar
*utf8_msg_string
= NULL
;
1332 g_return_val_if_fail (str
!= NULL
, NULL
);
1333 g_return_val_if_fail (strlen (str
) > 0, NULL
);
1335 if (g_utf8_validate(str
, -1, NULL
))
1337 utf8_msg_string
= g_strdup (str
);
1341 gsize rbytes
, wbytes
;
1342 utf8_msg_string
= g_locale_to_utf8 (str
, -1, &rbytes
, &wbytes
, &error
);
1343 if (error
!= NULL
) {
1344 g_warning ("g_locale_to_utf8 failed: %s\n", error
->message
);
1345 g_error_free (error
);
1346 /* g_free (utf8_msg_string);
1350 return utf8_msg_string
;
1353 #define LEFT_BRACE(ch) (ch == ')'? '(' : (ch == '}'? '{' : (ch == ']'? '[' : ch)))
1356 anjuta_util_jump_to_matching_brace (IAnjutaIterable
*iter
, gchar brace
, gint limit
)
1358 gchar point_ch
= brace
;
1359 gint cur_iteration
= 0;
1360 gboolean use_limit
= (limit
> 0);
1361 GString
*braces_stack
= g_string_new ("");
1363 g_return_val_if_fail (point_ch
== ')' || point_ch
== ']' ||
1364 point_ch
== '}', FALSE
);
1366 /* DEBUG_PRINT ("%s", "Matching brace being"); */
1368 g_string_prepend_c (braces_stack
, point_ch
);
1370 while (ianjuta_iterable_previous (iter
, NULL
))
1374 if (use_limit
&& cur_iteration
> limit
)
1377 /* Skip comments and strings */
1378 IAnjutaEditorAttribute attrib
=
1379 ianjuta_editor_cell_get_attribute (IANJUTA_EDITOR_CELL (iter
), NULL
);
1380 if (attrib
== IANJUTA_EDITOR_COMMENT
|| attrib
== IANJUTA_EDITOR_STRING
)
1383 /* DEBUG_PRINT ("%s", "point ch = %c", point_ch); */
1384 point_ch
= ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (iter
), 0,
1386 if (point_ch
== ')' || point_ch
== ']' || point_ch
== '}')
1389 g_string_prepend_c (braces_stack
, point_ch
);
1392 if (point_ch
== LEFT_BRACE (braces_stack
->str
[0]))
1395 g_string_erase (braces_stack
, 0, 1);
1397 /* Bail out if there is no more in stack */
1398 if (braces_stack
->str
[0] == '\0')
1400 /* DEBUG_PRINT ("%s", "Matching brace end -- found"); */
1404 /* DEBUG_PRINT ("%s", "Matching brace end -- not found"); */
1409 * anjuta_util_parse_args_from_string:
1410 * @string: arguments
1412 * Parse arguments from a string to a GList.
1414 * Returns: (element-type utf8) (transfer full): A newly allocated GList of
1418 anjuta_util_parse_args_from_string (const gchar
* string
)
1422 gboolean is_quote
= FALSE
;
1423 gchar
* buffer
= g_new0(gchar
, strlen(string
) + 1);
1440 /* The current char was escaped */
1443 } else if (*s
== '\\') {
1444 /* Current char is an escape */
1446 } else if (is_quote
&& *s
== quote
) {
1447 /* Current char ends a quotation */
1449 if (!isspace(*(s
+1)) && (*(s
+1) != '\0')) {
1450 /* If there is no space after the quotation or it is not
1451 the end of the string */
1452 g_warning ("Parse error while parsing program arguments");
1454 } else if ((*s
== '\"' || *s
== '\'')) {
1456 /* Current char starts a quotation */
1460 /* Just a quote char inside quote */
1463 } else if (is_quote
){
1464 /* Any other char inside quote */
1466 } else if (isspace(*s
)) {
1467 /* Any white space outside quote */
1469 buffer
[idx
++] = '\0';
1470 args
= g_list_append (args
, g_strdup (buffer
));
1479 /* There are chars in the buffer. Flush as the last arg */
1480 buffer
[idx
++] = '\0';
1481 args
= g_list_append (args
, g_strdup (buffer
));
1485 g_warning ("Unclosed quotation encountered at the end of parsing");
1492 anjuta_util_escape_quotes(const gchar
* str
)
1496 const gchar
*s
= str
;
1498 g_return_val_if_fail(str
, NULL
);
1501 /* We are assuming there will be less than 2048 chars to escape */
1502 max_size
= strlen(str
) + 2048;
1503 buffer
= g_new (gchar
, max_size
);
1509 if (*s
== '\"' || *s
== '\'' || *s
== '\\')
1510 buffer
[idx
++] = '\\';
1518 /* Diff the text contained in uri with text. Return true if files
1519 differ, FALSE if they are identical.*/
1521 gboolean
anjuta_util_diff(const gchar
* uri
, const gchar
* text
)
1524 GFileInfo
*file_info
;
1526 gchar
* file_text
= NULL
;
1529 file
= g_file_new_for_uri (uri
);
1530 file_info
= g_file_query_info (file
,
1531 G_FILE_ATTRIBUTE_STANDARD_SIZE
,
1532 G_FILE_QUERY_INFO_NONE
,
1536 if (file_info
== NULL
)
1538 g_object_unref (file
);
1542 size
= g_file_info_get_attribute_uint64(file_info
,
1543 G_FILE_ATTRIBUTE_STANDARD_SIZE
);
1544 g_object_unref (file_info
);
1546 if (size
== 0 && text
== NULL
)
1548 g_object_unref (file
);
1551 else if (size
== 0 || text
== NULL
)
1553 g_object_unref (file
);
1557 if (!g_file_load_contents(file
,
1564 g_object_unref (file
);
1567 g_object_unref (file
);
1569 if (bytes_read
!= size
)
1575 /* according to g_file_load_contents's documentation
1576 * file_text is guaranteed to end with \0.
1578 if (strcmp (file_text
, text
) == 0)
1589 * anjuta_util_is_project_file:
1590 * @filename: the file name
1592 * Return %TRUE if the file is an anjuta project file. It is implemented by
1593 * checking only the file extension. So it does not check the existence
1594 * of the file. But it is working on an URI if it does not containt a
1597 * Returns: %TRUE if the file is a project file, else %FALSE
1600 anjuta_util_is_project_file (const gchar
*filename
)
1602 gsize len
= strlen (filename
);
1603 return ((len
> 8) && (strcmp (filename
+ len
- 7, ".anjuta") == 0));
1607 * anjuta_util_is_template_file:
1608 * @filename: the file name
1610 * Return %TRUE if the file is an template project file. It is implemented by
1611 * checking only the file extension. So it does not check the existence
1612 * of the file. But it is working on an URI if it does not containt a
1615 * Returns: %TRUE if the file is a template file, else %FALSE
1618 anjuta_util_is_template_file (const gchar
*filename
)
1620 gsize len
= strlen (filename
);
1621 return ((len
> 9) && (strcmp (filename
+ len
- 8, ".wiz.tgz") == 0));
1625 * anjuta_util_get_file_info_mine_type:
1626 * @info: the file information object
1628 * Return the mime type corresponding to a file infor object.
1630 * Returns: (transfer full) (allow-none): The mime type as a newly allocated
1631 * string that must be freed with g_free() or %NULL if the mime type cannot be found.
1634 anjuta_util_get_file_info_mime_type (GFileInfo
*info
)
1636 gchar
*mime_type
= NULL
;
1637 const gchar
*extension
;
1640 g_return_val_if_fail (info
!= NULL
, NULL
);
1643 /* If Anjuta is not installed in system gnome prefix, the mime types
1644 * may not have been correctly registed. In that case, we use the
1645 * following mime detection
1647 name
= g_file_info_get_name (info
);
1648 extension
= strrchr(name
, '.');
1649 if ((extension
!= NULL
) && (extension
!= name
))
1651 const static struct {gchar
*extension
; gchar
*type
;} anjuta_types
[] = {
1652 {"anjuta", "application/x-anjuta"},
1653 {"prj", "application/x-anjuta-old"},
1657 for (i
= 0; anjuta_types
[i
].extension
!= NULL
; i
++)
1659 if (strcmp(extension
+ 1, anjuta_types
[i
].extension
) == 0)
1661 mime_type
= g_strdup (anjuta_types
[i
].type
);
1667 /* Use mime database if it is not an Anjuta type */
1668 if (mime_type
== NULL
)
1670 mime_type
= g_content_type_get_mime_type (g_file_info_get_content_type(info
));
1677 * anjuta_util_get_file_mine_type:
1680 * Check if a file exists and return its mime type.
1682 * Returns: (transfer full) (allow-none): %NULL if the corresponding file doesn't
1683 * exist or the mime type as a newly allocated string that must be freed with
1687 anjuta_util_get_file_mime_type (GFile
*file
)
1690 gchar
*mime_type
= NULL
;
1692 g_return_val_if_fail (file
!= NULL
, NULL
);
1694 /* Get file information, check that the file exist at the same time */
1695 info
= g_file_query_info (file
,
1696 G_FILE_ATTRIBUTE_STANDARD_NAME
","
1697 G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE
,
1698 G_FILE_QUERY_INFO_NONE
,
1704 mime_type
= anjuta_util_get_file_info_mime_type (info
);
1705 g_object_unref (info
);
1712 anjuta_util_get_local_path_from_uri (const gchar
*uri
)
1717 file
= g_file_new_for_uri (uri
);
1718 local_path
= g_file_get_path (file
);
1719 g_object_unref (file
);
1724 #ifdef EMULATE_FORKPTY
1727 static int ptym_open (char *pts_name
);
1728 static int ptys_open (int fdm
, char * pts_name
);
1731 login_tty(int ttyfd
)
1743 /* First disconnect from the old controlling tty. */
1745 fd
= open("/dev/tty", O_RDWR
|O_NOCTTY
);
1748 ioctl(fd
, TIOCNOTTY
, NULL
);
1752 //syslog(LOG_WARNING, "NO CTTY");
1753 #endif /* TIOCNOTTY */
1755 /* Verify that we are successfully disconnected from the controlling tty. */
1756 fd
= open("/dev/tty", O_RDWR
|O_NOCTTY
);
1759 //syslog(LOG_WARNING, "Failed to disconnect from controlling tty.");
1763 /* Make it our controlling tty. */
1765 ioctl(ttyfd
, TIOCSCTTY
, NULL
);
1766 #endif /* TIOCSCTTY */
1768 fdname
= ttyname (ttyfd
);
1769 fd
= open(fdname
, O_RDWR
);
1771 ;//syslog(LOG_WARNING, "open %s: %s", fdname, strerror(errno));
1775 /* Verify that we now have a controlling tty. */
1776 fd
= open("/dev/tty", O_WRONLY
);
1779 //syslog(LOG_WARNING, "open /dev/tty: %s", strerror(errno));
1784 #if defined(HAVE_VHANGUP) && !defined(HAVE_REVOKE)
1786 RETSIGTYPE (*sig
)();
1787 sig
= signal(SIGHUP
, SIG_IGN
);
1789 signal(SIGHUP
, sig
);
1792 fd
= open(fdname
, O_RDWR
);
1795 //syslog(LOG_ERR, "can't reopen ctty %s: %s", fdname, strerror(errno));
1817 openpty(int *amaster
, int *aslave
, char *name
, struct termios
*termp
,
1818 struct winsize
*winp
)
1821 *amaster
= ptym_open(line
);
1824 *aslave
= ptys_open(*amaster
, line
);
1832 #define TCSAFLUSH TCSETAF
1835 (void) tcsetattr(*aslave
, TCSAFLUSH
, termp
);
1838 (void) ioctl(*aslave
, TIOCSWINSZ
, (char *)winp
);
1844 ptym_open(char * pts_name
)
1850 strcpy(pts_name
, "/dev/ptmx");
1851 fdm
= open(pts_name
, O_RDWR
);
1854 if (grantpt(fdm
) < 0) { /* grant access to slave */
1858 if (unlockpt(fdm
) < 0) { /* clear slave's lock flag */
1863 if (ptr
== NULL
) { /* get slave's name */
1867 strcpy(pts_name
, ptr
); /* return name of slave */
1868 return fdm
; /* return fd of master */
1872 strcpy(pts_name
, "/dev/ptyXY");
1873 /* array index: 012345689 (for references in following code) */
1874 for (ptr1
= "pqrstuvwxyzPQRST"; *ptr1
!= 0; ptr1
++) {
1875 pts_name
[8] = *ptr1
;
1876 for (ptr2
= "0123456789abcdef"; *ptr2
!= 0; ptr2
++) {
1877 pts_name
[9] = *ptr2
;
1878 /* try to open master */
1879 fdm
= open(pts_name
, O_RDWR
);
1881 if (errno
== ENOENT
) /* different from EIO */
1882 return -1; /* out of pty devices */
1884 continue; /* try next pty device */
1886 pts_name
[5] = 't'; /* chage "pty" to "tty" */
1887 return fdm
; /* got it, return fd of master */
1890 return -1; /* out of pty devices */
1895 ptys_open(int fdm
, char * pts_name
)
1899 /* following should allocate controlling terminal */
1900 fds
= open(pts_name
, O_RDWR
);
1905 if (ioctl(fds
, I_PUSH
, "ptem") < 0) {
1910 if (ioctl(fds
, I_PUSH
, "ldterm") < 0) {
1915 if (ioctl(fds
, I_PUSH
, "ttcompat") < 0) {
1921 if (ioctl(fdm
, I_PUSH
, "pckt") < 0) {
1927 if (ioctl(fdm
, I_SRDOPT
, RMSGN
|RPROTDAT
) < 0) {
1936 struct group
*grptr
;
1938 grptr
= getgrnam("tty");
1940 gid
= grptr
->gr_gid
;
1942 gid
= -1; /* group tty is not in the group file */
1943 /* following two functions don't work unless we're root */
1944 chown(pts_name
, getuid(), gid
);
1945 chmod(pts_name
, S_IRUSR
| S_IWUSR
| S_IWGRP
);
1946 fds
= open(pts_name
, O_RDWR
);
1956 forkpty(int *amaster
, char *name
, struct termios
*termp
, struct winsize
*winp
)
1958 int master
, slave
, pid
;
1960 if (openpty(&master
, &slave
, name
, termp
, winp
) == -1)
1962 switch (pid
= fork()) {
1981 int scandir(const char *dir
, struct dirent
***namelist
,
1982 int (*select
)(const struct dirent
*),
1983 int (*compar
)(const struct dirent
**, const struct dirent
**))
1986 struct dirent
*entry
;
1990 if ((d
=opendir(dir
)) == NULL
)
1994 while ((entry
=readdir(d
)) != NULL
)
1996 if (select
== NULL
|| (select
!= NULL
&& (*select
)(entry
)))
1998 *namelist
=(struct dirent
**)realloc((void *)(*namelist
),
1999 (size_t)((i
+1)*sizeof(struct dirent
*)));
2000 if (*namelist
== NULL
) return(-1);
2001 entrysize
=sizeof(struct dirent
)-sizeof(entry
->d_name
)+strlen(entry
->d_name
)+1;
2002 (*namelist
)[i
]=(struct dirent
*)malloc(entrysize
);
2003 if ((*namelist
)[i
] == NULL
) return(-1);
2004 memcpy((*namelist
)[i
], entry
, entrysize
);
2008 if (closedir(d
)) return(-1);
2009 if (i
== 0) return(-1);
2011 qsort((void *)(*namelist
), (size_t)i
, sizeof(struct dirent
*), compar
);
2016 #endif /* EMULATE_FORKPTY */
2019 anjuta_util_help_display (GtkWidget
*parent
,
2020 const gchar
*doc_id
,
2023 GError
*error
= NULL
;
2027 command
= g_strdup_printf ("yelp help:%s%s%s",
2029 item
== NULL
? "" : "/",
2030 item
== NULL
? "" : item
);
2032 if (!g_spawn_command_line_async (command
, &error
) &&
2035 g_warning ("Error executing help application: %s",
2037 g_error_free (error
);
2043 /* The following functions are taken from gedit */
2045 /* Note that this function replace home dir with ~ */
2047 anjuta_util_uri_get_dirname (const gchar
*uri
)
2052 // CHECK: does it work with uri chaining? - Paolo
2053 str
= g_path_get_dirname (uri
);
2054 g_return_val_if_fail (str
!= NULL
, ".");
2056 if ((strlen (str
) == 1) && (*str
== '.'))
2063 res
= anjuta_util_replace_home_dir_with_tilde (str
);
2071 anjuta_util_replace_home_dir_with_tilde (const gchar
*uri
)
2076 g_return_val_if_fail (uri
!= NULL
, NULL
);
2078 /* Note that g_get_home_dir returns a const string */
2079 tmp
= (gchar
*)g_get_home_dir ();
2082 return g_strdup (uri
);
2084 home
= g_filename_to_utf8 (tmp
, -1, NULL
, NULL
, NULL
);
2086 return g_strdup (uri
);
2088 if (strcmp (uri
, home
) == 0)
2092 return g_strdup ("~");
2096 home
= g_strdup_printf ("%s/", tmp
);
2099 if (g_str_has_prefix (uri
, home
))
2103 res
= g_strdup_printf ("~/%s", uri
+ strlen (home
));
2112 return g_strdup (uri
);
2116 * anjuta_util_shell_expand:
2117 * @string: input string
2119 * Expand environment variables $(var_name) and tilde (~) in the input string.
2121 * Returns: (transfer full): a newly-allocated string that must be freed with g_free().
2124 anjuta_util_shell_expand (const gchar
*string
)
2128 if (string
== NULL
) return NULL
;
2130 expand
= g_string_sized_new (strlen (string
));
2132 for (; *string
!= '\0'; string
++)
2138 /* Variable expansion */
2143 while (isalnum (*end
) || (*end
== '_')) end
++;
2144 var_name_len
= end
- string
- 1;
2145 if (var_name_len
> 0)
2149 g_string_append_len (expand
, string
+ 1, var_name_len
);
2150 value
= g_getenv (expand
->str
+ expand
->len
- var_name_len
);
2151 g_string_truncate (expand
, expand
->len
- var_name_len
);
2152 g_string_append (expand
, value
);
2160 /* User home directory expansion */
2161 if (isspace(string
[1]) || (string
[1] == G_DIR_SEPARATOR
) || (string
[1] == '\0'))
2163 g_string_append (expand
, g_get_home_dir());
2171 g_string_append_c (expand
, *string
);
2174 return g_string_free (expand
, FALSE
);
2178 anjuta_util_str_middle_truncate (const gchar
*string
,
2179 guint truncate_length
)
2184 guint num_left_chars
;
2186 guint delimiter_length
;
2187 const gchar
*delimiter
= "\342\200\246";
2189 g_return_val_if_fail (string
!= NULL
, NULL
);
2191 length
= strlen (string
);
2193 g_return_val_if_fail (g_utf8_validate (string
, length
, NULL
), NULL
);
2195 /* It doesnt make sense to truncate strings to less than
2196 * the size of the delimiter plus 2 characters (one on each
2199 delimiter_length
= g_utf8_strlen (delimiter
, -1);
2200 if (truncate_length
< (delimiter_length
+ 2)) {
2201 return g_strdup (string
);
2204 n_chars
= g_utf8_strlen (string
, length
);
2206 /* Make sure the string is not already small enough. */
2207 if (n_chars
<= truncate_length
) {
2208 return g_strdup (string
);
2211 /* Find the 'middle' where the truncation will occur. */
2212 num_left_chars
= (truncate_length
- delimiter_length
) / 2;
2213 right_offset
= n_chars
- truncate_length
+ num_left_chars
+ delimiter_length
;
2215 truncated
= g_string_new_len (string
,
2216 g_utf8_offset_to_pointer (string
, num_left_chars
) - string
);
2217 g_string_append (truncated
, delimiter
);
2218 g_string_append (truncated
, g_utf8_offset_to_pointer (string
, right_offset
));
2220 return g_string_free (truncated
, FALSE
);
2224 * Functions to implement XDG Base Directory Specification
2225 * http://standards.freedesktop.org/basedir-spec/latest/index.html
2226 * Use this to save any config/cache/data files
2231 anjuta_util_set_anjuta_prefix (const gchar
*prefix
)
2233 anjuta_prefix
= g_strdup (prefix
);
2237 anjuta_util_construct_pathv (const gchar
* str
, va_list str_list
)
2240 const gchar
* tmp_str
;
2243 str_arr
= g_ptr_array_new();
2244 g_ptr_array_add (str_arr
, (gpointer
) str
);
2246 /* Extract elements from va_list */
2249 while ((tmp_str
= va_arg (str_list
, const gchar
*)) != NULL
)
2251 g_ptr_array_add (str_arr
, (gpointer
)tmp_str
);
2256 /* Terminate the list */
2257 g_ptr_array_add (str_arr
, NULL
);
2259 path
= g_build_filenamev ((gchar
**)str_arr
->pdata
);
2260 g_ptr_array_free (str_arr
, TRUE
);
2266 anjuta_util_get_user_cache_filev (const gchar
* path
, va_list list
)
2268 gchar
*uri_str
, *base_path
, *dir
;
2270 base_path
= g_build_filename (g_get_user_cache_dir(), anjuta_prefix
, path
, NULL
);
2272 uri_str
= anjuta_util_construct_pathv (base_path
, list
);
2275 uri
= g_file_new_for_path (uri_str
);
2276 dir
= g_path_get_dirname (uri_str
);
2278 if (!anjuta_util_create_dir (dir
)) return NULL
;
2284 anjuta_util_get_user_cache_file (const gchar
* path
, ...)
2287 va_start (list
, path
);
2288 return anjuta_util_get_user_cache_filev (path
, list
);
2292 anjuta_util_get_user_config_filev (const gchar
* path
, va_list list
)
2294 gchar
*uri_str
, *base_path
, *dir
;
2296 base_path
= g_build_filename (g_get_user_config_dir(), anjuta_prefix
, path
, NULL
);
2298 uri_str
= anjuta_util_construct_pathv (base_path
, list
);
2301 uri
= g_file_new_for_path (uri_str
);
2302 dir
= g_path_get_dirname (uri_str
);
2304 if (!anjuta_util_create_dir (dir
)) return NULL
;
2310 anjuta_util_get_user_config_file (const gchar
* path
, ...)
2313 va_start (list
, path
);
2314 return anjuta_util_get_user_config_filev (path
, list
);
2318 anjuta_util_get_user_data_filev (const gchar
* path
, va_list list
)
2320 gchar
*uri_str
, *base_path
, *dir
;
2322 base_path
= g_build_filename (g_get_user_data_dir(), anjuta_prefix
, path
, NULL
);
2324 uri_str
= anjuta_util_construct_pathv (base_path
, list
);
2327 uri
= g_file_new_for_path (uri_str
);
2328 dir
= g_path_get_dirname (uri_str
);
2330 if (!anjuta_util_create_dir (dir
)) return NULL
;
2336 anjuta_util_get_user_data_file (const gchar
* path
, ...)
2339 va_start (list
, path
);
2340 return anjuta_util_get_user_data_filev (path
, list
);
2344 anjuta_util_get_user_cache_file_path (const gchar
* path
, ...)
2349 va_start (list
, path
);
2350 file
= anjuta_util_get_user_cache_filev (path
, list
);
2351 file_path
= g_file_get_path (file
);
2352 g_object_unref (file
);
2358 anjuta_util_get_user_config_file_path (const gchar
* path
, ...)
2363 va_start (list
, path
);
2364 file
= anjuta_util_get_user_config_filev (path
, list
);
2365 file_path
= g_file_get_path (file
);
2366 g_object_unref (file
);
2372 anjuta_util_get_user_data_file_path (const gchar
* path
, ...)
2377 va_start (list
, path
);
2378 file
= anjuta_util_get_user_data_filev (path
, list
);
2379 file_path
= g_file_get_path (file
);
2380 g_object_unref (file
);
2386 anjuta_util_convert_gfile_list_to_path_list (GList
*list
)
2389 GList
*current_file
;
2394 for (current_file
= list
; current_file
!= NULL
; current_file
= g_list_next (current_file
))
2396 path
= g_file_get_path (current_file
->data
);
2398 /* Ignore files with invalid paths */
2400 path_list
= g_list_append (path_list
, path
);
2407 anjuta_util_convert_gfile_list_to_relative_path_list (GList
*list
,
2408 const gchar
*parent
)
2412 GList
*current_file
;
2415 parent_file
= g_file_new_for_path (parent
);
2420 for (current_file
= list
; current_file
!= NULL
; current_file
= g_list_next (current_file
))
2422 path
= g_file_get_relative_path (parent_file
, current_file
->data
);
2424 /* Ignore files with invalid paths */
2426 path_list
= g_list_append (path_list
, path
);
2429 g_object_unref (parent_file
);
2437 * anjuta_util_builder_new:
2438 * @filename: Builder file name to open
2439 * @error: Optional error object, if %NULL display a dialog if the file is missing
2441 * Create a new GtkBuilder object and load the file in it. Display an error
2442 * if the file is missing. Use a dialog if error is %NULL, just a warning
2443 * if the error can be reported.
2445 * Returns: The new GtkBuilder object
2448 anjuta_util_builder_new (const gchar
*filename
, GError
**error
)
2450 GtkBuilder
*bxml
= gtk_builder_new ();
2453 /* Load glade file */
2454 if (!gtk_builder_add_from_file (bxml
, filename
, &err
))
2456 g_object_unref (bxml
);
2459 /* Display the error to the user if it cannot be reported to the caller */
2462 anjuta_util_dialog_error (NULL
, _("Unable to load user interface file: %s"), err
->message
);
2466 g_warning ("Couldn't load builder file: %s", err
->message
);
2468 g_propagate_error (error
, err
);
2471 /* Tag the builder object with the filename to allow better error message
2472 * with the following function */
2475 g_object_set_data_full (G_OBJECT (bxml
), "filename", g_strdup (filename
), g_free
);
2482 * anjuta_util_builder_get_objects:
2483 * @builder: Builder object
2484 * @first_widget: Name of first widget to get
2485 * ...: Address to store the first widget pointer, followed optionally by
2486 * more name/pointer pairs, followed by %NULL
2488 * Create a new GtkBuilder object and load the file in it. Display an error
2489 * if the file is missing. Use a dialog if error is %NULL, just a warning
2490 * if the error can be reported.
2492 * Returns: %TRUE is everything works as expected.
2495 anjuta_util_builder_get_objects (GtkBuilder
*builder
, const gchar
*first_widget
,...)
2499 GObject
**object_ptr
;
2500 gboolean missing
= FALSE
;
2502 va_start (args
, first_widget
);
2504 for (name
= first_widget
; name
; name
= va_arg (args
, char *))
2506 object_ptr
= va_arg (args
, void *);
2507 *object_ptr
= gtk_builder_get_object (builder
, name
);
2509 /* Object not found, display a warning */
2512 const gchar
*filename
= (const gchar
*)g_object_get_data (G_OBJECT (builder
), "filename");
2515 g_warning ("Missing widget '%s' in file %s", name
, filename
);
2519 g_warning("Missing widget '%s'", name
);
2530 * anjuta_utils_drop_get_files:
2531 * @selection_data: the #GtkSelectionData from drag_data_received
2533 * Create a list of valid uri's from a uri-list drop.
2535 * Return value: (element-type GFile*): a list of GFiles
2538 anjuta_utils_drop_get_files (GtkSelectionData
*selection_data
)
2542 GSList
* files
= NULL
;
2544 uris
= g_uri_list_extract_uris ((gchar
*) gtk_selection_data_get_data (selection_data
));
2546 for (i
= 0; uris
[i
] != NULL
; i
++)
2548 GFile
* file
= g_file_new_for_uri (uris
[i
]);
2549 files
= g_slist_append(files
, file
);
2556 * anjuta_util_get_user_mail:
2558 * Returns: The e-mail Address of the logged-in user. The resulting string
2559 * must be free'd after use.
2562 anjuta_util_get_user_mail()
2564 /* FIXME: Use libfolks or something like it to query the mail address */
2567 GSettings
*settings
;
2569 settings
= g_settings_new (ANJUTA_PREF_SCHEMA
);
2570 id
= g_settings_get_string (settings
, LAST_EMAIL
);
2571 g_object_unref (settings
);
2575 return g_strconcat(g_get_user_name (), "@", g_get_host_name (), NULL
);
2582 * anjuta_util_get_user_mail:
2583 * @id: The e-mail address to be used in future
2586 void anjuta_util_set_user_mail(const gchar
* id
)
2588 GSettings
*settings
;
2590 settings
= g_settings_new (ANJUTA_PREF_SCHEMA
);
2591 g_settings_set_string (settings
, LAST_EMAIL
, id
);
2592 g_object_unref (settings
);
2597 * anjuta_utils_clone_string_gptrarray:
2598 * @source: The source GPtrArray containing items representing strings
2600 * Clones the contents of source GPtrArray into a new allocated GPtrArray.
2602 * Return a new allocated GPtrArray with strings g_strdup (), %NULL on error.
2603 * The returned array has set g_free as GDestroyNotity function, so that user
2604 * should only care to g_ptr_array_unref () without freeing the strings.
2607 anjuta_util_clone_string_gptrarray (const GPtrArray
* source
)
2612 g_return_val_if_fail (source
!= NULL
, NULL
);
2614 dest
= g_ptr_array_sized_new (source
->len
);
2615 g_ptr_array_set_free_func (dest
, g_free
);
2617 for (i
= 0; i
< source
->len
; i
++)
2619 g_ptr_array_add (dest
, g_strdup (g_ptr_array_index (source
, i
)));
2626 anjuta_util_list_all_dir_children (GList
**children
, GFile
*dir
)
2628 GFileEnumerator
*list
;
2630 list
= g_file_enumerate_children (dir
,
2631 G_FILE_ATTRIBUTE_STANDARD_NAME
,
2632 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS
,
2640 while ((info
= g_file_enumerator_next_file (list
, NULL
, NULL
)) != NULL
)
2645 name
= g_file_info_get_name (info
);
2646 file
= g_file_get_child (dir
, name
);
2647 g_object_unref (info
);
2649 if (g_file_query_file_type (file
, G_FILE_QUERY_INFO_NONE
, NULL
) == G_FILE_TYPE_DIRECTORY
)
2651 anjuta_util_list_all_dir_children (children
, file
);
2652 g_object_unref (file
);
2656 *children
= g_list_prepend (*children
, file
);
2659 g_file_enumerator_close (list
, NULL
, NULL
);
2660 g_object_unref (list
);
2665 anjuta_util_convert_string_list_to_array (GList
*list
)
2670 g_return_val_if_fail (list
!= NULL
, NULL
);
2672 res
= g_ptr_array_new_with_free_func (g_free
);
2675 while (node
!= NULL
)
2677 g_ptr_array_add (res
, g_strdup (node
->data
));
2679 node
= g_list_next (node
);