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>
51 #include <glib/gi18n.h>
53 #include <glib/gstdio.h>
55 #include <libanjuta/anjuta-utils.h>
56 #include <libanjuta/anjuta-debug.h>
58 #include <libgnomevfs/gnome-vfs.h>
60 #define FILE_BUFFER_SIZE 1024
63 anjuta_util_copy_file (gchar
* src
, gchar
* dest
, gboolean show_error
)
65 FILE *input_fp
, *output_fp
;
66 gchar buffer
[FILE_BUFFER_SIZE
];
67 gint bytes_read
, bytes_written
;
72 input_fp
= fopen (src
, "rb");
76 anjuta_util_dialog_error_system (NULL
, errno
,
77 _("Unable to read file: %s."),
82 output_fp
= fopen (dest
, "wb");
83 if (output_fp
== NULL
)
86 anjuta_util_dialog_error_system (NULL
, errno
,
87 _("Unable to create file: %s."),
95 bytes_read
= fread (buffer
, 1, FILE_BUFFER_SIZE
, input_fp
);
96 if (bytes_read
!= FILE_BUFFER_SIZE
&& ferror (input_fp
))
104 bytes_written
= fwrite (buffer
, 1, bytes_read
, output_fp
);
105 if (bytes_read
!= bytes_written
)
112 if (bytes_read
!= FILE_BUFFER_SIZE
&& feof (input_fp
))
121 if( show_error
&& (error
== FALSE
))
122 anjuta_util_dialog_error_system (NULL
, errno
,
123 _("Unable to complete file copy"));
128 anjuta_util_color_from_string (const gchar
* val
, guint16
* r
, guint16
* g
, guint16
* b
)
131 if (gdk_color_parse(val
, &color
))
140 anjuta_util_string_from_color (guint16 r
, guint16 g
, guint16 b
)
142 return g_strdup_printf("#%02x%02x%02x", r
>> 8, g
>> 8, b
>> 8);
145 /* Get a GdkColor from preferences. Free the color with gdk_color_free() */
147 anjuta_util_convert_color(AnjutaPreferences
* prefs
, const gchar
* pref_name
)
149 GdkColor
* color
= g_new0(GdkColor
, 1);
150 gchar
* color_string
= anjuta_preferences_get(prefs
, pref_name
);
151 gdk_color_parse(color_string
, color
);
156 anjuta_util_button_new_with_stock_image (const gchar
* text
,
157 const gchar
* stock_id
)
166 button
= gtk_button_new ();
168 if (GTK_BIN (button
)->child
)
169 gtk_container_remove (GTK_CONTAINER (button
),
170 GTK_BIN (button
)->child
);
172 if (gtk_stock_lookup (stock_id
, &item
))
174 label
= gtk_label_new_with_mnemonic (text
);
176 gtk_label_set_mnemonic_widget (GTK_LABEL (label
), GTK_WIDGET (button
));
178 image
= gtk_image_new_from_stock (stock_id
, GTK_ICON_SIZE_BUTTON
);
179 hbox
= gtk_hbox_new (FALSE
, 2);
181 align
= gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
183 gtk_box_pack_start (GTK_BOX (hbox
), image
, FALSE
, FALSE
, 0);
184 gtk_box_pack_end (GTK_BOX (hbox
), label
, FALSE
, FALSE
, 0);
186 gtk_container_add (GTK_CONTAINER (button
), align
);
187 gtk_container_add (GTK_CONTAINER (align
), hbox
);
188 gtk_widget_show_all (align
);
193 label
= gtk_label_new_with_mnemonic (text
);
194 gtk_label_set_mnemonic_widget (GTK_LABEL (label
), GTK_WIDGET (button
));
196 gtk_misc_set_alignment (GTK_MISC (label
), 0.5, 0.5);
198 gtk_widget_show (label
);
199 gtk_container_add (GTK_CONTAINER (button
), label
);
205 anjuta_util_dialog_add_button (GtkDialog
*dialog
, const gchar
* text
,
206 const gchar
* stock_id
, gint response_id
)
210 g_return_val_if_fail (GTK_IS_DIALOG (dialog
), NULL
);
211 g_return_val_if_fail (text
!= NULL
, NULL
);
212 g_return_val_if_fail (stock_id
!= NULL
, NULL
);
214 button
= anjuta_util_button_new_with_stock_image (text
, stock_id
);
215 g_return_val_if_fail (button
!= NULL
, NULL
);
217 GTK_WIDGET_SET_FLAGS (button
, GTK_CAN_DEFAULT
);
219 gtk_widget_show (button
);
221 gtk_dialog_add_action_widget (dialog
, button
, response_id
);
227 anjuta_util_dialog_error (GtkWindow
*parent
, const gchar
*mesg
, ...)
232 GtkWindow
*real_parent
;
234 va_start (args
, mesg
);
235 message
= g_strdup_vprintf (mesg
, args
);
238 if (parent
&& GTK_IS_WINDOW (parent
))
240 real_parent
= parent
;
247 // Dialog to be HIG compliant
248 dialog
= gtk_message_dialog_new (real_parent
,
249 GTK_DIALOG_DESTROY_WITH_PARENT
,
251 GTK_BUTTONS_CLOSE
, message
);
252 g_signal_connect (G_OBJECT (dialog
), "response",
253 G_CALLBACK (gtk_widget_destroy
), NULL
);
254 gtk_widget_show (dialog
);
259 anjuta_util_dialog_warning (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
, 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_info (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
;
310 // Dialog to be HIG compliant
311 dialog
= gtk_message_dialog_new (real_parent
,
312 GTK_DIALOG_DESTROY_WITH_PARENT
,
314 GTK_BUTTONS_CLOSE
, message
);
315 g_signal_connect (G_OBJECT (dialog
), "response",
316 G_CALLBACK (gtk_widget_destroy
), NULL
);
317 gtk_widget_show (dialog
);
322 anjuta_util_dialog_error_system (GtkWindow
* parent
, gint errnum
,
323 const gchar
* mesg
, ... )
329 GtkWindow
*real_parent
;
331 va_start (args
, mesg
);
332 message
= g_strdup_vprintf (mesg
, args
);
336 tot_mesg
= g_strconcat (message
, _("\nSystem: "),
337 g_strerror(errnum
), NULL
);
342 if (parent
&& GTK_IS_WINDOW (parent
))
344 real_parent
= parent
;
350 // Dialog to be HIG compliant
351 dialog
= gtk_message_dialog_new (real_parent
,
352 GTK_DIALOG_DESTROY_WITH_PARENT
,
354 GTK_BUTTONS_CLOSE
, tot_mesg
);
355 g_signal_connect (G_OBJECT (dialog
), "response",
356 G_CALLBACK (gtk_widget_destroy
), NULL
);
357 gtk_widget_show (dialog
);
362 anjuta_util_dialog_boolean_question (GtkWindow
*parent
, const gchar
*mesg
, ...)
368 GtkWindow
*real_parent
;
370 va_start (args
, mesg
);
371 message
= g_strdup_vprintf (mesg
, args
);
374 if (parent
&& GTK_IS_WINDOW (parent
))
376 real_parent
= parent
;
383 dialog
= gtk_message_dialog_new (real_parent
,
384 GTK_DIALOG_DESTROY_WITH_PARENT
,
385 GTK_MESSAGE_QUESTION
,
386 GTK_BUTTONS_YES_NO
, message
);
388 ret
= gtk_dialog_run (GTK_DIALOG (dialog
));
389 gtk_widget_destroy (dialog
);
392 return (ret
== GTK_RESPONSE_YES
);
396 anjuta_util_dialog_input (GtkWindow
*parent
, const gchar
*prompt
,
397 const gchar
*default_value
, gchar
**return_value
)
399 GtkWidget
*dialog
, *label
, *frame
, *entry
, *dialog_vbox
, *vbox
;
402 GtkWindow
*real_parent
;
404 if (parent
&& GTK_IS_WINDOW (parent
))
406 real_parent
= parent
;
413 dialog
= gtk_dialog_new_with_buttons (prompt
, real_parent
,
414 GTK_DIALOG_DESTROY_WITH_PARENT
,
415 GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
,
416 GTK_STOCK_OK
, GTK_RESPONSE_OK
,
418 gtk_dialog_set_default_response (GTK_DIALOG (dialog
), GTK_RESPONSE_OK
);
419 dialog_vbox
= GTK_DIALOG (dialog
)->vbox
;
420 gtk_window_set_default_size (GTK_WINDOW (dialog
), 400, -1);
421 gtk_widget_show (dialog_vbox
);
423 markup
= g_strconcat ("<b>", prompt
, "</b>", NULL
);
424 label
= gtk_label_new (NULL
);
425 gtk_label_set_markup (GTK_LABEL (label
), markup
);
426 gtk_widget_show (label
);
429 frame
= gtk_frame_new (NULL
);
430 gtk_frame_set_label_widget (GTK_FRAME (frame
), label
);
431 gtk_frame_set_shadow_type (GTK_FRAME (frame
), GTK_SHADOW_NONE
);
432 gtk_container_set_border_width (GTK_CONTAINER (frame
), 10);
433 gtk_widget_show (frame
);
434 gtk_box_pack_start (GTK_BOX (dialog_vbox
), frame
, FALSE
, FALSE
, 0);
436 vbox
= gtk_vbox_new (FALSE
, 0);
437 gtk_widget_show (vbox
);
438 gtk_container_set_border_width (GTK_CONTAINER (vbox
), 10);
439 gtk_container_add (GTK_CONTAINER (frame
), vbox
);
441 entry
= gtk_entry_new ();
442 gtk_widget_show (entry
);
443 gtk_entry_set_activates_default (GTK_ENTRY (entry
), TRUE
);
444 gtk_box_pack_start (GTK_BOX (vbox
), entry
, FALSE
, FALSE
, 0);
446 gtk_entry_set_text (GTK_ENTRY (entry
), default_value
);
448 res
= gtk_dialog_run (GTK_DIALOG (dialog
));
450 if (gtk_entry_get_text (GTK_ENTRY (entry
)) &&
451 strlen (gtk_entry_get_text (GTK_ENTRY (entry
))) > 0)
453 *return_value
= g_strdup (gtk_entry_get_text (GTK_ENTRY (entry
)));
457 *return_value
= NULL
;
459 gtk_widget_destroy (dialog
);
460 return (res
== GTK_RESPONSE_OK
);
464 anjuta_util_prog_is_installed (const gchar
* prog
, gboolean show
)
466 gchar
* prog_path
= g_find_program_in_path (prog
);
474 anjuta_util_dialog_error (NULL
, _("The \"%s\" utility is not installed.\n"
475 "Please install it."), prog
);
481 anjuta_util_get_a_tmp_file (void)
483 static gint count
= 0;
487 tmpdir
= g_get_tmp_dir ();
489 g_strdup_printf ("%s/anjuta_%d.%d", tmpdir
, count
++, getpid ());
493 /* GList of strings operations */
495 anjuta_util_glist_from_string (const gchar
*string
)
497 gchar
*str
, *temp
, buff
[256];
499 gchar
*word_start
, *word_end
;
504 temp
= g_strdup (string
);
514 /* Remove leading spaces */
515 while (isspace (*str
) && *str
!= '\0')
520 /* Find start and end of word */
522 while (!isspace (*str
) && *str
!= '\0')
526 /* Copy the word into the buffer */
527 for (ptr
= word_start
, i
= 0; ptr
< word_end
; ptr
++, i
++)
531 list
= g_list_append (list
, g_strdup (buff
));
540 /* Prefix the strings */
542 anjuta_util_glist_strings_prefix (GList
* list
, const gchar
*prefix
)
547 g_return_if_fail (prefix
!= NULL
);
552 node
->data
= g_strconcat (prefix
, tmp
, NULL
);
553 if (tmp
) g_free (tmp
);
554 node
= g_list_next (node
);
558 /* Suffix the strings */
560 anjuta_util_glist_strings_sufix (GList
* list
, const gchar
*sufix
)
565 g_return_if_fail (sufix
!= NULL
);
570 node
->data
= g_strconcat (tmp
, sufix
, NULL
);
571 if (tmp
) g_free (tmp
);
572 node
= g_list_next (node
);
576 /* Duplicate list of strings */
578 anjuta_util_glist_strings_dup (GList
* list
)
588 new_list
= g_list_append (new_list
, g_strdup(node
->data
));
590 new_list
= g_list_append (new_list
, NULL
);
591 node
= g_list_next (node
);
596 /* Join list of strings using the given delimiter */
598 anjuta_util_glist_strings_join (GList
* list
, gchar
*delimiter
)
601 gboolean first
= TRUE
;
604 joined
= g_string_new (NULL
);
611 g_string_append (joined
, delimiter
);
614 g_string_append (joined
, node
->data
);
616 node
= g_list_next (node
);
619 return g_string_free (joined
, FALSE
);
621 g_string_free (joined
, TRUE
);
626 anjuta_util_get_real_path (const gchar
*path
)
632 gchar buf
[PATH_MAX
+1];
634 result
= realpath (path
, buf
);
637 *(buf
+ PATH_MAX
) = '\0'; /* ensure a terminator */
638 return g_strdup (buf
);
642 /* the string returned by realpath should be cleaned with
643 free(), not g_free() */
644 buf
= realpath (path
, NULL
);
647 result
= g_strdup (buf
);
656 /* Dedup a list of paths - duplicates are removed from the tail.
657 ** Useful for deduping Recent Files and Recent Projects */
659 anjuta_util_glist_path_dedup(GList
*list
)
661 GList
*nlist
= NULL
, *tmp
, *tmp1
;
664 for (tmp
= list
; tmp
; tmp
= g_list_next(tmp
))
666 path
= anjuta_util_get_real_path ((const gchar
*) tmp
->data
);
669 if (stat (path
, &s
) != 0)
675 for (tmp1
= nlist
; tmp1
; tmp1
= g_list_next(tmp1
))
677 if (0 == strcmp((const char *) tmp1
->data
, path
))
685 nlist
= g_list_prepend(nlist
, path
);
689 anjuta_util_glist_strings_free(list
);
690 nlist
= g_list_reverse(nlist
);
695 sort_node (gchar
* a
, gchar
*b
)
697 if ( !a
&& !b
) return 0;
698 else if (!a
) return -1;
699 else if (!b
) return 1;
700 return strcmp (a
, b
);
703 /* Sort the list alphabatically */
705 anjuta_util_glist_strings_sort (GList
* list
)
707 return g_list_sort(list
, (GCompareFunc
)sort_node
);
710 /* Free the strings and GList */
712 anjuta_util_glist_strings_free (GList
* list
)
720 node
= g_list_next (node
);
726 anjuta_util_type_from_string (AnjutaUtilStringMap
*map
, const char *str
)
730 while (-1 != map
[i
].type
)
732 if (0 == strcmp(map
[i
].name
, str
))
740 anjuta_util_string_from_type (AnjutaUtilStringMap
*map
, int type
)
743 while (-1 != map
[i
].type
)
745 if (map
[i
].type
== type
)
753 anjuta_util_glist_from_map (AnjutaUtilStringMap
*map
)
755 GList
*out_list
= NULL
;
757 while (-1 != map
[i
].type
)
759 out_list
= g_list_append(out_list
, map
[i
].name
);
767 anjuta_util_update_string_list (GList
*p_list
, const gchar
*p_str
, gint length
)
773 for (i
= 0; i
< g_list_length (p_list
); i
++)
775 str
= (gchar
*) g_list_nth_data (p_list
, i
);
778 if (strcmp (p_str
, str
) == 0)
780 p_list
= g_list_remove (p_list
, str
);
781 p_list
= g_list_prepend (p_list
, str
);
785 p_list
= g_list_prepend (p_list
, g_strdup (p_str
));
786 while (g_list_length (p_list
) > length
)
788 str
= g_list_nth_data (p_list
, g_list_length (p_list
) - 1);
789 p_list
= g_list_remove (p_list
, str
);
796 anjuta_util_create_dir (const gchar
* path
)
798 GFile
*dir
= g_file_new_for_path (path
);
801 if (g_file_query_exists (dir
, NULL
))
803 GFileInfo
*info
= g_file_query_info (dir
,
804 G_FILE_ATTRIBUTE_STANDARD_TYPE
,
805 G_FILE_QUERY_INFO_NONE
,
807 if (g_file_info_get_file_type (info
) != G_FILE_TYPE_DIRECTORY
)
809 g_message ("Warning: %s is a file. \n \
810 It is trying to be treated as a directory.",g_file_get_path (dir
));
811 g_object_unref (dir
);
814 g_object_unref (info
);
816 else if (!g_file_make_directory (dir
, NULL
, &err
))
818 g_warning ("Error directory:\n %s", err
->message
);
819 g_object_unref (dir
);
822 g_object_unref (dir
);
828 * anjuta_util_user_shell:
830 * Retrieves the user's preferred shell.
832 * Returns: A newly allocated string that is the path to the shell.
834 /* copied from deprecated gnome_util_user_shell in libgnome */
836 anjuta_util_user_shell (void)
842 const char shells
[][14] = {
843 /* Note that on some systems shells can also
844 * be installed in /usr/bin */
845 "/bin/bash", "/usr/bin/bash",
846 "/bin/zsh", "/usr/bin/zsh",
847 "/bin/tcsh", "/usr/bin/tcsh",
848 "/bin/ksh", "/usr/bin/ksh",
849 "/bin/csh", "/bin/sh"
852 if (geteuid () == getuid () &&
853 getegid () == getgid ()) {
854 /* only in non-setuid */
855 if ((shell
= g_getenv ("SHELL"))){
856 if (access (shell
, X_OK
) == 0) {
857 return g_strdup (shell
);
861 pw
= getpwuid(getuid());
862 if (pw
&& pw
->pw_shell
) {
863 if (access (pw
->pw_shell
, X_OK
) == 0) {
864 return g_strdup (pw
->pw_shell
);
868 for (i
= 0; i
!= G_N_ELEMENTS (shells
); i
++) {
869 if (access (shells
[i
], X_OK
) == 0) {
870 return g_strdup (shells
[i
]);
874 /* If /bin/sh doesn't exist, your system is truly broken. */
877 /* Placate compiler. */
880 /* g_find_program_in_path() always looks also in the Windows
881 * and System32 directories, so it should always find either cmd.exe
884 char *retval
= g_find_program_in_path ("cmd.exe");
887 retval
= g_find_program_in_path ("command.com");
889 g_assert (retval
!= NULL
);
896 anjuta_util_execute_shell (const gchar
*dir
, const gchar
*command
)
901 g_return_val_if_fail (command
!= NULL
, -1);
903 shell
= anjuta_util_user_shell ();
909 anjuta_util_create_dir (dir
);
912 execlp (shell
, shell
, "-c", command
, NULL
);
913 g_warning (_("Cannot execute command: %s (using shell %s)\n"), command
, shell
);
917 g_warning (_("Cannot execute command: %s (using shell %s)\n"), command
, shell
);
919 // Anjuta will take care of child exit automatically.
924 anjuta_util_convert_to_utf8 (const gchar
*str
)
926 GError
*error
= NULL
;
927 gchar
*utf8_msg_string
= NULL
;
929 g_return_val_if_fail (str
!= NULL
, NULL
);
930 g_return_val_if_fail (strlen (str
) > 0, NULL
);
932 if (g_utf8_validate(str
, -1, NULL
))
934 utf8_msg_string
= g_strdup (str
);
938 gsize rbytes
, wbytes
;
939 utf8_msg_string
= g_locale_to_utf8 (str
, -1, &rbytes
, &wbytes
, &error
);
941 g_warning ("g_locale_to_utf8 failed: %s\n", error
->message
);
942 g_error_free (error
);
943 /* g_free (utf8_msg_string);
947 return utf8_msg_string
;
951 anjuta_util_parse_args_from_string (const gchar
* string
)
955 gboolean is_quote
= FALSE
;
956 gchar
* buffer
= g_new0(gchar
, strlen(string
) + 1);
973 /* The current char was escaped */
976 } else if (*s
== '\\') {
977 /* Current char is an escape */
979 } else if (is_quote
&& *s
== quote
) {
980 /* Current char ends a quotation */
982 if (!isspace(*(s
+1)) && (*(s
+1) != '\0')) {
983 /* If there is no space after the quotation or it is not
984 the end of the string */
985 g_warning ("Parse error while parsing program arguments");
987 } else if ((*s
== '\"' || *s
== '\'')) {
989 /* Current char starts a quotation */
993 /* Just a quote char inside quote */
996 } else if (is_quote
){
997 /* Any other char inside quote */
999 } else if (isspace(*s
)) {
1000 /* Any white space outside quote */
1002 buffer
[idx
++] = '\0';
1003 args
= g_list_append (args
, g_strdup (buffer
));
1012 /* There are chars in the buffer. Flush as the last arg */
1013 buffer
[idx
++] = '\0';
1014 args
= g_list_append (args
, g_strdup (buffer
));
1018 g_warning ("Unclosed quotation encountered at the end of parsing");
1025 anjuta_util_escape_quotes(const gchar
* str
)
1029 const gchar
*s
= str
;
1031 g_return_val_if_fail(str
, NULL
);
1034 /* We are assuming there will be less than 2048 chars to escape */
1035 max_size
= strlen(str
) + 2048;
1036 buffer
= g_new (gchar
, max_size
);
1042 if (*s
== '\"' || *s
== '\'' || *s
== '\\')
1043 buffer
[idx
++] = '\\';
1051 /* FIXME: Use gio instead */
1052 /* Diff the text contained in uri with text. Return true if files
1053 differ, FALSE if they are identical.
1054 FIXME: Find a better algorithm, this seems ineffective */
1056 gboolean
anjuta_util_diff(const gchar
* uri
, const gchar
* text
)
1058 GnomeVFSFileSize bytes_read
;
1060 GnomeVFSFileInfo info
;
1061 GnomeVFSHandle
* handle
= NULL
;
1063 gnome_vfs_get_file_info(uri
, &info
, GNOME_VFS_FILE_INFO_DEFAULT
);
1065 if (info
.size
== 0 && text
== NULL
)
1067 else if (info
.size
== 0 || text
== NULL
)
1070 file_text
= g_new0(gchar
, info
.size
+ 1);
1072 if (gnome_vfs_open(&handle
, uri
, GNOME_VFS_OPEN_READ
!= GNOME_VFS_OK
))
1075 if ((gnome_vfs_read(handle
, file_text
, info
.size
, &bytes_read
) == GNOME_VFS_OK
)
1076 && (bytes_read
== info
.size
))
1078 gnome_vfs_close(handle
);
1080 if ((g_utf8_strlen(file_text
, -1) == g_utf8_strlen(text
, -1))
1081 && strcmp(file_text
, text
) == 0)
1087 gnome_vfs_close(handle
);
1093 anjuta_util_path_has_extension (const gchar
*path
, const gchar
*ext
)
1095 if (strlen (path
) <= strlen (ext
))
1097 if ((path
[strlen (path
) - strlen (ext
) - 1] == '.') &&
1098 (strcmp (&path
[strlen (path
) - strlen (ext
)], ext
) == 0))
1104 anjuta_util_get_uri_mime_type (const gchar
*uri
)
1106 GnomeVFSURI
*vfs_uri
;
1110 g_return_val_if_fail (uri
!= NULL
, NULL
);
1112 vfs_uri
= gnome_vfs_uri_new (uri
);
1114 path
= gnome_vfs_uri_get_path (vfs_uri
);
1118 /* If Anjuta is not installed in system gnome prefix, the mime types
1119 * may not have been correctly registed. In that case, we use the
1120 * following mime detection
1124 mime_type
= gnome_vfs_get_slow_mime_type (uri
);
1126 else if (anjuta_util_path_has_extension (path
, "anjuta"))
1128 mime_type
= g_strdup ("application/x-anjuta");
1130 else if (anjuta_util_path_has_extension (path
, "prj"))
1132 mime_type
= g_strdup ("application/x-anjuta-old");
1134 else if (anjuta_util_path_has_extension (path
, "ui"))
1136 mime_type
= g_strdup ("text/xml");
1138 else if (anjuta_util_path_has_extension (path
, "glade"))
1140 mime_type
= g_strdup ("application/x-glade");
1144 mime_type
= gnome_vfs_get_slow_mime_type (uri
);
1148 gnome_vfs_uri_unref (vfs_uri
);
1152 #ifndef HAVE_LIBUTIL
1155 static int ptym_open (char *pts_name
);
1156 static int ptys_open (int fdm
, char * pts_name
);
1159 login_tty(int ttyfd
)
1171 /* First disconnect from the old controlling tty. */
1173 fd
= open("/dev/tty", O_RDWR
|O_NOCTTY
);
1176 ioctl(fd
, TIOCNOTTY
, NULL
);
1180 //syslog(LOG_WARNING, "NO CTTY");
1181 #endif /* TIOCNOTTY */
1183 /* Verify that we are successfully disconnected from the controlling tty. */
1184 fd
= open("/dev/tty", O_RDWR
|O_NOCTTY
);
1187 //syslog(LOG_WARNING, "Failed to disconnect from controlling tty.");
1191 /* Make it our controlling tty. */
1193 ioctl(ttyfd
, TIOCSCTTY
, NULL
);
1194 #endif /* TIOCSCTTY */
1196 fdname
= ttyname (ttyfd
);
1197 fd
= open(fdname
, O_RDWR
);
1199 ;//syslog(LOG_WARNING, "open %s: %s", fdname, strerror(errno));
1203 /* Verify that we now have a controlling tty. */
1204 fd
= open("/dev/tty", O_WRONLY
);
1207 //syslog(LOG_WARNING, "open /dev/tty: %s", strerror(errno));
1212 #if defined(HAVE_VHANGUP) && !defined(HAVE_REVOKE)
1214 RETSIGTYPE (*sig
)();
1215 sig
= signal(SIGHUP
, SIG_IGN
);
1217 signal(SIGHUP
, sig
);
1220 fd
= open(fdname
, O_RDWR
);
1223 //syslog(LOG_ERR, "can't reopen ctty %s: %s", fdname, strerror(errno));
1245 openpty(int *amaster
, int *aslave
, char *name
, struct termios
*termp
,
1246 struct winsize
*winp
)
1249 *amaster
= ptym_open(line
);
1252 *aslave
= ptys_open(*amaster
, line
);
1260 #define TCSAFLUSH TCSETAF
1263 (void) tcsetattr(*aslave
, TCSAFLUSH
, termp
);
1266 (void) ioctl(*aslave
, TIOCSWINSZ
, (char *)winp
);
1272 ptym_open(char * pts_name
)
1278 strcpy(pts_name
, "/dev/ptmx");
1279 fdm
= open(pts_name
, O_RDWR
);
1282 if (grantpt(fdm
) < 0) { /* grant access to slave */
1286 if (unlockpt(fdm
) < 0) { /* clear slave's lock flag */
1291 if (ptr
== NULL
) { /* get slave's name */
1295 strcpy(pts_name
, ptr
); /* return name of slave */
1296 return fdm
; /* return fd of master */
1300 strcpy(pts_name
, "/dev/ptyXY");
1301 /* array index: 012345689 (for references in following code) */
1302 for (ptr1
= "pqrstuvwxyzPQRST"; *ptr1
!= 0; ptr1
++) {
1303 pts_name
[8] = *ptr1
;
1304 for (ptr2
= "0123456789abcdef"; *ptr2
!= 0; ptr2
++) {
1305 pts_name
[9] = *ptr2
;
1306 /* try to open master */
1307 fdm
= open(pts_name
, O_RDWR
);
1309 if (errno
== ENOENT
) /* different from EIO */
1310 return -1; /* out of pty devices */
1312 continue; /* try next pty device */
1314 pts_name
[5] = 't'; /* chage "pty" to "tty" */
1315 return fdm
; /* got it, return fd of master */
1318 return -1; /* out of pty devices */
1323 ptys_open(int fdm
, char * pts_name
)
1327 /* following should allocate controlling terminal */
1328 fds
= open(pts_name
, O_RDWR
);
1333 if (ioctl(fds
, I_PUSH
, "ptem") < 0) {
1338 if (ioctl(fds
, I_PUSH
, "ldterm") < 0) {
1343 if (ioctl(fds
, I_PUSH
, "ttcompat") < 0) {
1349 if (ioctl(fdm
, I_PUSH
, "pckt") < 0) {
1355 if (ioctl(fdm
, I_SRDOPT
, RMSGN
|RPROTDAT
) < 0) {
1364 struct group
*grptr
;
1366 grptr
= getgrnam("tty");
1368 gid
= grptr
->gr_gid
;
1370 gid
= -1; /* group tty is not in the group file */
1371 /* following two functions don't work unless we're root */
1372 chown(pts_name
, getuid(), gid
);
1373 chmod(pts_name
, S_IRUSR
| S_IWUSR
| S_IWGRP
);
1374 fds
= open(pts_name
, O_RDWR
);
1384 forkpty(int *amaster
, char *name
, struct termios
*termp
, struct winsize
*winp
)
1386 int master
, slave
, pid
;
1388 if (openpty(&master
, &slave
, name
, termp
, winp
) == -1)
1390 switch (pid
= fork()) {
1409 int scandir(const char *dir
, struct dirent
***namelist
,
1410 int (*select
)(const struct dirent
*),
1411 int (*compar
)(const struct dirent
**, const struct dirent
**))
1414 struct dirent
*entry
;
1418 if ((d
=opendir(dir
)) == NULL
)
1422 while ((entry
=readdir(d
)) != NULL
)
1424 if (select
== NULL
|| (select
!= NULL
&& (*select
)(entry
)))
1426 *namelist
=(struct dirent
**)realloc((void *)(*namelist
),
1427 (size_t)((i
+1)*sizeof(struct dirent
*)));
1428 if (*namelist
== NULL
) return(-1);
1429 entrysize
=sizeof(struct dirent
)-sizeof(entry
->d_name
)+strlen(entry
->d_name
)+1;
1430 (*namelist
)[i
]=(struct dirent
*)malloc(entrysize
);
1431 if ((*namelist
)[i
] == NULL
) return(-1);
1432 memcpy((*namelist
)[i
], entry
, entrysize
);
1436 if (closedir(d
)) return(-1);
1437 if (i
== 0) return(-1);
1439 qsort((void *)(*namelist
), (size_t)i
, sizeof(struct dirent
*), compar
);
1444 #endif /* HAVE_LIBUTIL */
1447 anjuta_util_help_display (GtkWindow
*parent
,
1448 const gchar
*doc_id
,
1449 const gchar
*file_name
)
1452 GError
*error
= NULL
;
1456 const gchar
* const *langs
;
1460 g_return_if_fail (file_name
!= NULL
);
1462 langs
= g_get_language_names ();
1463 for (i
= 0; langs
[i
]; i
++)
1466 if (strchr (lang
, '.'))
1469 uri
= g_build_filename (DATADIR
, "/gnome/help/", doc_id
,
1470 lang
, file_name
, NULL
);
1472 if (g_file_test (uri
, G_FILE_TEST_EXISTS
)) {
1481 anjuta_util_dialog_error (parent
, _("Unable to display help. Please make sure Anjuta "
1482 "documentation package is install. It can be downloaded "
1483 "from http://anjuta.org"));
1488 command
= g_strconcat ("gnome-help ghelp://", uri
, NULL
);
1491 screen
= gtk_widget_get_screen (GTK_WIDGET (parent
));
1492 gdk_spawn_command_line_on_screen (screen
, command
, &error
);
1495 g_warning ("Error executing help application: %s",
1497 g_error_free (error
);
1504 /* The following functions are taken from gedit */
1506 /* Note that this function replace home dir with ~ */
1508 anjuta_util_uri_get_dirname (const gchar
*uri
)
1513 // CHECK: does it work with uri chaining? - Paolo
1514 str
= g_path_get_dirname (uri
);
1515 g_return_val_if_fail (str
!= NULL
, ".");
1517 if ((strlen (str
) == 1) && (*str
== '.'))
1524 res
= anjuta_util_replace_home_dir_with_tilde (str
);
1532 anjuta_util_replace_home_dir_with_tilde (const gchar
*uri
)
1537 g_return_val_if_fail (uri
!= NULL
, NULL
);
1539 /* Note that g_get_home_dir returns a const string */
1540 tmp
= (gchar
*)g_get_home_dir ();
1543 return g_strdup (uri
);
1545 home
= g_filename_to_utf8 (tmp
, -1, NULL
, NULL
, NULL
);
1547 return g_strdup (uri
);
1549 if (strcmp (uri
, home
) == 0)
1553 return g_strdup ("~");
1557 home
= g_strdup_printf ("%s/", tmp
);
1560 if (g_str_has_prefix (uri
, home
))
1564 res
= g_strdup_printf ("~/%s", uri
+ strlen (home
));
1573 return g_strdup (uri
);
1577 anjuta_util_str_middle_truncate (const gchar
*string
,
1578 guint truncate_length
)
1583 guint num_left_chars
;
1585 guint delimiter_length
;
1586 const gchar
*delimiter
= "\342\200\246";
1588 g_return_val_if_fail (string
!= NULL
, NULL
);
1590 length
= strlen (string
);
1592 g_return_val_if_fail (g_utf8_validate (string
, length
, NULL
), NULL
);
1594 /* It doesnt make sense to truncate strings to less than
1595 * the size of the delimiter plus 2 characters (one on each
1598 delimiter_length
= g_utf8_strlen (delimiter
, -1);
1599 if (truncate_length
< (delimiter_length
+ 2)) {
1600 return g_strdup (string
);
1603 n_chars
= g_utf8_strlen (string
, length
);
1605 /* Make sure the string is not already small enough. */
1606 if (n_chars
<= truncate_length
) {
1607 return g_strdup (string
);
1610 /* Find the 'middle' where the truncation will occur. */
1611 num_left_chars
= (truncate_length
- delimiter_length
) / 2;
1612 right_offset
= n_chars
- truncate_length
+ num_left_chars
+ delimiter_length
;
1614 truncated
= g_string_new_len (string
,
1615 g_utf8_offset_to_pointer (string
, num_left_chars
) - string
);
1616 g_string_append (truncated
, delimiter
);
1617 g_string_append (truncated
, g_utf8_offset_to_pointer (string
, right_offset
));
1619 return g_string_free (truncated
, FALSE
);
1623 * Functions to implement XDG Base Directory Specification
1624 * http://standards.freedesktop.org/basedir-spec/latest/index.html
1625 * Use this to save any config/cache/data files
1630 anjuta_util_construct_pathv (const gchar
* str
, va_list str_list
)
1633 const gchar
* tmp_str
;
1636 str_arr
= g_ptr_array_new();
1637 g_ptr_array_add (str_arr
, (gpointer
) str
);
1639 /* Extract elements from va_list */
1642 while ((tmp_str
= va_arg (str_list
, const gchar
*)) != NULL
)
1644 g_ptr_array_add (str_arr
, tmp_str
);
1649 /* Terminate the list */
1650 g_ptr_array_add (str_arr
, (gpointer
) NULL
);
1652 path
= g_build_filenamev ((gchar
*) str_arr
->pdata
);
1653 g_ptr_array_free (str_arr
, TRUE
);
1659 anjuta_util_get_user_cache_filev (const gchar
* path
, va_list list
)
1661 gchar
*uri_str
, *base_path
, *dir
;
1663 const gchar anjuta_prefix
[] = "anjuta";
1664 base_path
= g_build_filename (g_get_user_cache_dir(), anjuta_prefix
, path
, NULL
);
1666 uri_str
= anjuta_util_construct_pathv (base_path
, list
);
1669 uri
= g_file_new_for_path (uri_str
);
1670 dir
= g_path_get_dirname (uri_str
);
1672 if (!anjuta_util_create_dir (dir
)) return NULL
;
1678 anjuta_util_get_user_cache_file (const gchar
* path
, ...)
1681 va_start (list
, path
);
1682 return anjuta_util_get_user_cache_filev (path
, list
);
1686 anjuta_util_get_user_config_filev (const gchar
* path
, va_list list
)
1688 gchar
*uri_str
, *base_path
, *dir
;
1690 const gchar anjuta_prefix
[] = "anjuta";
1691 base_path
= g_build_filename (g_get_user_config_dir(), anjuta_prefix
, path
, NULL
);
1693 uri_str
= anjuta_util_construct_pathv (base_path
, list
);
1696 uri
= g_file_new_for_path (uri_str
);
1697 dir
= g_path_get_dirname (uri_str
);
1699 if (!anjuta_util_create_dir (dir
)) return NULL
;
1705 anjuta_util_get_user_config_file (const gchar
* path
, ...)
1708 va_start (list
, path
);
1709 return anjuta_util_get_user_config_filev (path
, list
);
1713 anjuta_util_get_user_data_filev (const gchar
* path
, va_list list
)
1715 gchar
*uri_str
, *base_path
, *dir
;
1717 const gchar anjuta_prefix
[] = "anjuta";
1718 base_path
= g_build_filename (g_get_user_data_dir(), anjuta_prefix
, path
, NULL
);
1720 uri_str
= anjuta_util_construct_pathv (base_path
, list
);
1723 uri
= g_file_new_for_path (uri_str
);
1724 dir
= g_path_get_dirname (uri_str
);
1726 if (!anjuta_util_create_dir (dir
)) return NULL
;
1732 anjuta_util_get_user_data_file (const gchar
* path
, ...)
1735 va_start (list
, path
);
1736 return anjuta_util_get_user_data_filev (path
, list
);
1740 anjuta_util_get_user_cache_file_path (const gchar
* path
, ...)
1745 va_start (list
, path
);
1746 file
= anjuta_util_get_user_cache_filev (path
, list
);
1747 file_path
= g_file_get_path (file
);
1748 g_object_unref (file
);
1754 anjuta_util_get_user_config_file_path (const gchar
* path
, ...)
1759 va_start (list
, path
);
1760 file
= anjuta_util_get_user_config_filev (path
, list
);
1761 file_path
= g_file_get_path (file
);
1762 g_object_unref (file
);
1768 anjuta_util_get_user_data_file_path (const gchar
* path
, ...)
1773 va_start (list
, path
);
1774 file
= anjuta_util_get_user_data_filev (path
, list
);
1775 file_path
= g_file_get_path (file
);
1776 g_object_unref (file
);