Fix a Gtk warning when checking path input in the log viewer.
[anjuta-git-plugin.git] / libanjuta / anjuta-utils.c
blob1e01af3bb1ecaf26d74dfeb48675a22bad44935a
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 * anjuta-utils.c
4 * Copyright (C) Naba Kumar <naba@gnome.org>
5 *
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
21 /**
22 * SECTION:anjuta-utils
23 * @title: Utilities
24 * @short_description: Utility functions
25 * @see_also:
26 * @stability: Unstable
27 * @include: libanjuta/anjuta-utils.h
31 #ifdef HAVE_CONFIG_H
32 # include <config.h>
33 #endif
35 #include <errno.h>
36 #include <ctype.h>
37 #include <limits.h>
38 #include <stdlib.h>
39 #include <sys/stat.h>
40 #include <sys/types.h>
41 #include <sys/fcntl.h>
42 #include <sys/termios.h>
43 #include <dirent.h>
44 #include <unistd.h>
45 #include <stdio.h>
46 #include <string.h>
47 #ifndef G_OS_WIN32
48 #include <pwd.h>
49 #endif
51 #include <glib/gi18n.h>
52 #include <glib.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
62 gboolean
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;
68 gboolean error;
70 error = TRUE;
72 input_fp = fopen (src, "rb");
73 if (input_fp == NULL)
75 if( show_error)
76 anjuta_util_dialog_error_system (NULL, errno,
77 _("Unable to read file: %s."),
78 src);
79 return FALSE;
82 output_fp = fopen (dest, "wb");
83 if (output_fp == NULL)
85 if( show_error)
86 anjuta_util_dialog_error_system (NULL, errno,
87 _("Unable to create file: %s."),
88 dest);
89 fclose (input_fp);
90 return TRUE;
93 for (;;)
95 bytes_read = fread (buffer, 1, FILE_BUFFER_SIZE, input_fp);
96 if (bytes_read != FILE_BUFFER_SIZE && ferror (input_fp))
98 error = FALSE;
99 break;
102 if (bytes_read)
104 bytes_written = fwrite (buffer, 1, bytes_read, output_fp);
105 if (bytes_read != bytes_written)
107 error = FALSE;
108 break;
112 if (bytes_read != FILE_BUFFER_SIZE && feof (input_fp))
114 break;
118 fclose (input_fp);
119 fclose (output_fp);
121 if( show_error && (error == FALSE))
122 anjuta_util_dialog_error_system (NULL, errno,
123 _("Unable to complete file copy"));
124 return error;
127 void
128 anjuta_util_color_from_string (const gchar * val, guint16 * r, guint16 * g, guint16 * b)
130 GdkColor color;
131 if (gdk_color_parse(val, &color))
133 *r = color.red;
134 *g = color.green;
135 *b =color.blue;
139 gchar *
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() */
146 GdkColor*
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);
152 return color;
155 GtkWidget*
156 anjuta_util_button_new_with_stock_image (const gchar* text,
157 const gchar* stock_id)
159 GtkWidget *button;
160 GtkStockItem item;
161 GtkWidget *label;
162 GtkWidget *image;
163 GtkWidget *hbox;
164 GtkWidget *align;
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);
190 return button;
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);
201 return button;
204 GtkWidget*
205 anjuta_util_dialog_add_button (GtkDialog *dialog, const gchar* text,
206 const gchar* stock_id, gint response_id)
208 GtkWidget *button;
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);
223 return button;
226 void
227 anjuta_util_dialog_error (GtkWindow *parent, const gchar *mesg, ...)
229 gchar* message;
230 va_list args;
231 GtkWidget *dialog;
232 GtkWindow *real_parent;
234 va_start (args, mesg);
235 message = g_strdup_vprintf (mesg, args);
236 va_end (args);
238 if (parent && GTK_IS_WINDOW (parent))
240 real_parent = parent;
242 else
244 real_parent = NULL;
247 // Dialog to be HIG compliant
248 dialog = gtk_message_dialog_new (real_parent,
249 GTK_DIALOG_DESTROY_WITH_PARENT,
250 GTK_MESSAGE_ERROR,
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);
255 g_free (message);
258 void
259 anjuta_util_dialog_warning (GtkWindow *parent, const gchar * mesg, ...)
261 gchar* message;
262 va_list args;
263 GtkWidget *dialog;
264 GtkWindow *real_parent;
266 va_start (args, mesg);
267 message = g_strdup_vprintf (mesg, args);
268 va_end (args);
270 if (parent && GTK_IS_WINDOW (parent))
272 real_parent = parent;
274 else
276 real_parent = NULL;
279 // Dialog to be HIG compliant
280 dialog = gtk_message_dialog_new (real_parent,
281 GTK_DIALOG_DESTROY_WITH_PARENT,
282 GTK_MESSAGE_WARNING,
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);
287 g_free (message);
290 void
291 anjuta_util_dialog_info (GtkWindow *parent, const gchar * mesg, ...)
293 gchar* message;
294 va_list args;
295 GtkWidget *dialog;
296 GtkWindow *real_parent;
298 va_start (args, mesg);
299 message = g_strdup_vprintf (mesg, args);
300 va_end (args);
302 if (parent && GTK_IS_WINDOW (parent))
304 real_parent = parent;
306 else
308 real_parent = NULL;
310 // Dialog to be HIG compliant
311 dialog = gtk_message_dialog_new (real_parent,
312 GTK_DIALOG_DESTROY_WITH_PARENT,
313 GTK_MESSAGE_INFO,
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);
318 g_free (message);
321 void
322 anjuta_util_dialog_error_system (GtkWindow* parent, gint errnum,
323 const gchar * mesg, ... )
325 gchar* message;
326 gchar* tot_mesg;
327 va_list args;
328 GtkWidget *dialog;
329 GtkWindow *real_parent;
331 va_start (args, mesg);
332 message = g_strdup_vprintf (mesg, args);
333 va_end (args);
335 if (0 != errnum) {
336 tot_mesg = g_strconcat (message, _("\nSystem: "),
337 g_strerror(errnum), NULL);
338 g_free (message);
339 } else
340 tot_mesg = message;
342 if (parent && GTK_IS_WINDOW (parent))
344 real_parent = parent;
346 else
348 real_parent = NULL;
350 // Dialog to be HIG compliant
351 dialog = gtk_message_dialog_new (real_parent,
352 GTK_DIALOG_DESTROY_WITH_PARENT,
353 GTK_MESSAGE_ERROR,
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);
358 g_free (tot_mesg);
361 gboolean
362 anjuta_util_dialog_boolean_question (GtkWindow *parent, const gchar *mesg, ...)
364 gchar* message;
365 va_list args;
366 GtkWidget *dialog;
367 gint ret;
368 GtkWindow *real_parent;
370 va_start (args, mesg);
371 message = g_strdup_vprintf (mesg, args);
372 va_end (args);
374 if (parent && GTK_IS_WINDOW (parent))
376 real_parent = parent;
378 else
380 real_parent = NULL;
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);
390 g_free (message);
392 return (ret == GTK_RESPONSE_YES);
395 gboolean
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;
400 gint res;
401 gchar *markup;
402 GtkWindow *real_parent;
404 if (parent && GTK_IS_WINDOW (parent))
406 real_parent = parent;
408 else
410 real_parent = NULL;
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,
417 NULL);
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);
427 g_free (markup);
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);
445 if (default_value)
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)));
455 else
457 *return_value = NULL;
459 gtk_widget_destroy (dialog);
460 return (res == GTK_RESPONSE_OK);
463 gboolean
464 anjuta_util_prog_is_installed (const gchar * prog, gboolean show)
466 gchar* prog_path = g_find_program_in_path (prog);
467 if (prog_path)
469 g_free (prog_path);
470 return TRUE;
472 if (show)
474 anjuta_util_dialog_error (NULL, _("The \"%s\" utility is not installed.\n"
475 "Please install it."), prog);
477 return FALSE;
480 gchar *
481 anjuta_util_get_a_tmp_file (void)
483 static gint count = 0;
484 gchar *filename;
485 const gchar *tmpdir;
487 tmpdir = g_get_tmp_dir ();
488 filename =
489 g_strdup_printf ("%s/anjuta_%d.%d", tmpdir, count++, getpid ());
490 return filename;
493 /* GList of strings operations */
494 GList *
495 anjuta_util_glist_from_string (const gchar *string)
497 gchar *str, *temp, buff[256];
498 GList *list;
499 gchar *word_start, *word_end;
500 gboolean the_end;
502 list = NULL;
503 the_end = FALSE;
504 temp = g_strdup (string);
505 str = temp;
506 if (!str)
507 return NULL;
509 while (1)
511 gint i;
512 gchar *ptr;
514 /* Remove leading spaces */
515 while (isspace (*str) && *str != '\0')
516 str++;
517 if (*str == '\0')
518 break;
520 /* Find start and end of word */
521 word_start = str;
522 while (!isspace (*str) && *str != '\0')
523 str++;
524 word_end = str;
526 /* Copy the word into the buffer */
527 for (ptr = word_start, i = 0; ptr < word_end; ptr++, i++)
528 buff[i] = *ptr;
529 buff[i] = '\0';
530 if (strlen (buff))
531 list = g_list_append (list, g_strdup (buff));
532 if (*str == '\0')
533 break;
535 if (temp)
536 g_free (temp);
537 return list;
540 /* Prefix the strings */
541 void
542 anjuta_util_glist_strings_prefix (GList * list, const gchar *prefix)
544 GList *node;
545 node = list;
547 g_return_if_fail (prefix != NULL);
548 while (node)
550 gchar* tmp;
551 tmp = node->data;
552 node->data = g_strconcat (prefix, tmp, NULL);
553 if (tmp) g_free (tmp);
554 node = g_list_next (node);
558 /* Suffix the strings */
559 void
560 anjuta_util_glist_strings_sufix (GList * list, const gchar *sufix)
562 GList *node;
563 node = list;
565 g_return_if_fail (sufix != NULL);
566 while (node)
568 gchar* tmp;
569 tmp = node->data;
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 */
577 GList*
578 anjuta_util_glist_strings_dup (GList * list)
580 GList *node;
581 GList *new_list;
583 new_list = NULL;
584 node = list;
585 while (node)
587 if (node->data)
588 new_list = g_list_append (new_list, g_strdup(node->data));
589 else
590 new_list = g_list_append (new_list, NULL);
591 node = g_list_next (node);
593 return new_list;
596 /* Join list of strings using the given delimiter */
597 gchar*
598 anjuta_util_glist_strings_join (GList * list, gchar *delimiter)
600 GString *joined;
601 gboolean first = TRUE;
602 GList *node;
604 joined = g_string_new (NULL);
605 node = list;
606 while (node)
608 if (node->data)
610 if (!first)
611 g_string_append (joined, delimiter);
612 else
613 first = FALSE;
614 g_string_append (joined, node->data);
616 node = g_list_next (node);
618 if (joined->len > 0)
619 return g_string_free (joined, FALSE);
620 else
621 g_string_free (joined, TRUE);
622 return NULL;
625 gchar*
626 anjuta_util_get_real_path (const gchar *path)
628 if (path != NULL)
630 gchar *result;
631 #ifdef PATH_MAX
632 gchar buf[PATH_MAX+1];
634 result = realpath (path, buf);
635 if (result != NULL)
637 *(buf + PATH_MAX) = '\0'; /* ensure a terminator */
638 return g_strdup (buf);
640 #else
641 char *buf;
642 /* the string returned by realpath should be cleaned with
643 free(), not g_free() */
644 buf = realpath (path, NULL);
645 if (buf != NULL)
647 result = g_strdup (buf);
648 free (buf);
649 return result;
651 #endif
653 return NULL;
656 /* Dedup a list of paths - duplicates are removed from the tail.
657 ** Useful for deduping Recent Files and Recent Projects */
658 GList*
659 anjuta_util_glist_path_dedup(GList *list)
661 GList *nlist = NULL, *tmp, *tmp1;
662 gchar *path;
663 struct stat s;
664 for (tmp = list; tmp; tmp = g_list_next(tmp))
666 path = anjuta_util_get_real_path ((const gchar *) tmp->data);
667 if (path)
669 if (stat (path, &s) != 0)
671 g_free(path);
673 else
675 for (tmp1 = nlist; tmp1; tmp1 = g_list_next(tmp1))
677 if (0 == strcmp((const char *) tmp1->data, path))
679 g_free(path);
680 path = NULL;
681 break;
684 if (path)
685 nlist = g_list_prepend(nlist, path);
689 anjuta_util_glist_strings_free(list);
690 nlist = g_list_reverse(nlist);
691 return nlist;
694 static gint
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 */
704 GList*
705 anjuta_util_glist_strings_sort (GList * list)
707 return g_list_sort(list, (GCompareFunc)sort_node);
710 /* Free the strings and GList */
711 void
712 anjuta_util_glist_strings_free (GList * list)
714 GList *node;
715 node = list;
716 while (node)
718 if (node->data)
719 g_free (node->data);
720 node = g_list_next (node);
722 g_list_free (list);
726 anjuta_util_type_from_string (AnjutaUtilStringMap *map, const char *str)
728 int i = 0;
730 while (-1 != map[i].type)
732 if (0 == strcmp(map[i].name, str))
733 return map[i].type;
734 ++ i;
736 return -1;
739 const char*
740 anjuta_util_string_from_type (AnjutaUtilStringMap *map, int type)
742 int i = 0;
743 while (-1 != map[i].type)
745 if (map[i].type == type)
746 return map[i].name;
747 ++ i;
749 return "";
752 GList*
753 anjuta_util_glist_from_map (AnjutaUtilStringMap *map)
755 GList *out_list = NULL;
756 int i = 0;
757 while (-1 != map[i].type)
759 out_list = g_list_append(out_list, map[i].name);
760 ++ i;
762 return out_list;
766 GList *
767 anjuta_util_update_string_list (GList *p_list, const gchar *p_str, gint length)
769 gint i;
770 gchar *str;
771 if (!p_str)
772 return p_list;
773 for (i = 0; i < g_list_length (p_list); i++)
775 str = (gchar *) g_list_nth_data (p_list, i);
776 if (!str)
777 continue;
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);
782 return p_list;
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);
790 g_free (str);
792 return p_list;
795 gboolean
796 anjuta_util_create_dir (const gchar* path)
798 GFile *dir = g_file_new_for_path (path);
799 GError *err = NULL;
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,
806 NULL, NULL);
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);
812 return FALSE;
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);
820 return FALSE;
822 g_object_unref (dir);
824 return TRUE;
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 */
835 char *
836 anjuta_util_user_shell (void)
838 #ifndef G_OS_WIN32
839 struct passwd *pw;
840 int i;
841 const char *shell;
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. */
875 abort ();
877 /* Placate compiler. */
878 return NULL;
879 #else
880 /* g_find_program_in_path() always looks also in the Windows
881 * and System32 directories, so it should always find either cmd.exe
882 * or command.com.
884 char *retval = g_find_program_in_path ("cmd.exe");
886 if (retval == NULL)
887 retval = g_find_program_in_path ("command.com");
889 g_assert (retval != NULL);
891 return retval;
892 #endif
895 pid_t
896 anjuta_util_execute_shell (const gchar *dir, const gchar *command)
898 pid_t pid;
899 gchar *shell;
901 g_return_val_if_fail (command != NULL, -1);
903 shell = anjuta_util_user_shell ();
904 pid = fork();
905 if (pid == 0)
907 if(dir)
909 anjuta_util_create_dir (dir);
910 chdir (dir);
912 execlp (shell, shell, "-c", command, NULL);
913 g_warning (_("Cannot execute command: %s (using shell %s)\n"), command, shell);
914 _exit(1);
916 if (pid < 0)
917 g_warning (_("Cannot execute command: %s (using shell %s)\n"), command, shell);
918 g_free (shell);
919 // Anjuta will take care of child exit automatically.
920 return pid;
923 gchar *
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);
936 else
938 gsize rbytes, wbytes;
939 utf8_msg_string = g_locale_to_utf8 (str, -1, &rbytes, &wbytes, &error);
940 if (error != NULL) {
941 g_warning ("g_locale_to_utf8 failed: %s\n", error->message);
942 g_error_free (error);
943 /* g_free (utf8_msg_string);
944 return NULL; */
947 return utf8_msg_string;
950 GList*
951 anjuta_util_parse_args_from_string (const gchar* string)
953 gboolean escaped;
954 gchar quote = 0;
955 gboolean is_quote = FALSE;
956 gchar* buffer = g_new0(gchar, strlen(string) + 1);
957 const gchar *s;
958 gint idx;
959 GList* args = NULL;
961 idx = 0;
962 escaped = FALSE;
963 s = string;
965 while (*s) {
966 if (!isspace(*s))
967 break;
968 s++;
971 while (*s) {
972 if (escaped) {
973 /* The current char was escaped */
974 buffer[idx++] = *s;
975 escaped = FALSE;
976 } else if (*s == '\\') {
977 /* Current char is an escape */
978 escaped = TRUE;
979 } else if (is_quote && *s == quote) {
980 /* Current char ends a quotation */
981 is_quote = FALSE;
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 == '\'')) {
988 if (!is_quote) {
989 /* Current char starts a quotation */
990 quote = *s;
991 is_quote = TRUE;
992 } else {
993 /* Just a quote char inside quote */
994 buffer[idx++] = *s;
996 } else if (is_quote){
997 /* Any other char inside quote */
998 buffer[idx++] = *s;
999 } else if (isspace(*s)) {
1000 /* Any white space outside quote */
1001 if (idx > 0) {
1002 buffer[idx++] = '\0';
1003 args = g_list_append (args, g_strdup (buffer));
1004 idx = 0;
1006 } else {
1007 buffer[idx++] = *s;
1009 s++;
1011 if (idx > 0) {
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));
1015 idx = 0;
1017 if (is_quote) {
1018 g_warning ("Unclosed quotation encountered at the end of parsing");
1020 g_free (buffer);
1021 return args;
1024 gchar*
1025 anjuta_util_escape_quotes(const gchar* str)
1027 gchar *buffer;
1028 gint idx, max_size;
1029 const gchar *s = str;
1031 g_return_val_if_fail(str, NULL);
1032 idx = 0;
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);
1037 max_size -= 2;
1039 while(*s) {
1040 if (idx > max_size)
1041 break;
1042 if (*s == '\"' || *s == '\'' || *s == '\\')
1043 buffer[idx++] = '\\';
1044 buffer[idx++] = *s;
1045 s++;
1047 buffer[idx] = '\0';
1048 return buffer;
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;
1059 gchar* file_text;
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)
1066 return FALSE;
1067 else if (info.size == 0 || text == NULL)
1068 return TRUE;
1070 file_text = g_new0(gchar, info.size + 1);
1072 if (gnome_vfs_open(&handle, uri, GNOME_VFS_OPEN_READ != GNOME_VFS_OK))
1073 return TRUE;
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)
1082 return FALSE;
1083 return TRUE;
1085 else
1087 gnome_vfs_close(handle);
1088 return TRUE;
1092 gboolean
1093 anjuta_util_path_has_extension (const gchar *path, const gchar *ext)
1095 if (strlen (path) <= strlen (ext))
1096 return FALSE;
1097 if ((path[strlen (path) - strlen (ext) - 1] == '.') &&
1098 (strcmp (&path[strlen (path) - strlen (ext)], ext) == 0))
1099 return TRUE;
1100 return FALSE;
1103 gchar *
1104 anjuta_util_get_uri_mime_type (const gchar *uri)
1106 GnomeVFSURI *vfs_uri;
1107 const gchar *path;
1108 gchar *mime_type;
1110 g_return_val_if_fail (uri != NULL, NULL);
1112 vfs_uri = gnome_vfs_uri_new (uri);
1113 if (vfs_uri)
1114 path = gnome_vfs_uri_get_path (vfs_uri);
1115 else
1116 path = NULL;
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
1122 if (!path)
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");
1142 else
1144 mime_type = gnome_vfs_get_slow_mime_type (uri);
1147 if (vfs_uri)
1148 gnome_vfs_uri_unref (vfs_uri);
1149 return mime_type;
1152 #ifndef HAVE_LIBUTIL
1153 #include <grp.h>
1155 static int ptym_open (char *pts_name);
1156 static int ptys_open (int fdm, char * pts_name);
1159 login_tty(int ttyfd)
1161 int fd;
1162 char *fdname;
1164 #ifdef HAVE_SETSID
1165 setsid();
1166 #endif
1167 #ifdef HAVE_SETPGID
1168 setpgid(0, 0);
1169 #endif
1171 /* First disconnect from the old controlling tty. */
1172 #ifdef TIOCNOTTY
1173 fd = open("/dev/tty", O_RDWR|O_NOCTTY);
1174 if (fd >= 0)
1176 ioctl(fd, TIOCNOTTY, NULL);
1177 close(fd);
1179 else
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);
1185 if (fd >= 0)
1187 //syslog(LOG_WARNING, "Failed to disconnect from controlling tty.");
1188 close(fd);
1191 /* Make it our controlling tty. */
1192 #ifdef TIOCSCTTY
1193 ioctl(ttyfd, TIOCSCTTY, NULL);
1194 #endif /* TIOCSCTTY */
1196 fdname = ttyname (ttyfd);
1197 fd = open(fdname, O_RDWR);
1198 if (fd < 0)
1199 ;//syslog(LOG_WARNING, "open %s: %s", fdname, strerror(errno));
1200 else
1201 close(fd);
1203 /* Verify that we now have a controlling tty. */
1204 fd = open("/dev/tty", O_WRONLY);
1205 if (fd < 0)
1207 //syslog(LOG_WARNING, "open /dev/tty: %s", strerror(errno));
1208 return 1;
1211 close(fd);
1212 #if defined(HAVE_VHANGUP) && !defined(HAVE_REVOKE)
1214 RETSIGTYPE (*sig)();
1215 sig = signal(SIGHUP, SIG_IGN);
1216 vhangup();
1217 signal(SIGHUP, sig);
1219 #endif
1220 fd = open(fdname, O_RDWR);
1221 if (fd == -1)
1223 //syslog(LOG_ERR, "can't reopen ctty %s: %s", fdname, strerror(errno));
1224 return -1;
1227 close(ttyfd);
1229 if (fd != 0)
1230 close(0);
1231 if (fd != 1)
1232 close(1);
1233 if (fd != 2)
1234 close(2);
1236 dup2(fd, 0);
1237 dup2(fd, 1);
1238 dup2(fd, 2);
1239 if (fd > 2)
1240 close(fd);
1241 return 0;
1245 openpty(int *amaster, int *aslave, char *name, struct termios *termp,
1246 struct winsize *winp)
1248 char line[20];
1249 *amaster = ptym_open(line);
1250 if (*amaster < 0)
1251 return -1;
1252 *aslave = ptys_open(*amaster, line);
1253 if (*aslave < 0) {
1254 close(*amaster);
1255 return -1;
1257 if (name)
1258 strcpy(name, line);
1259 #ifndef TCSAFLUSH
1260 #define TCSAFLUSH TCSETAF
1261 #endif
1262 if (termp)
1263 (void) tcsetattr(*aslave, TCSAFLUSH, termp);
1264 #ifdef TIOCSWINSZ
1265 if (winp)
1266 (void) ioctl(*aslave, TIOCSWINSZ, (char *)winp);
1267 #endif
1268 return 0;
1271 static int
1272 ptym_open(char * pts_name)
1274 int fdm;
1275 #ifdef HAVE_PTSNAME
1276 char *ptr;
1278 strcpy(pts_name, "/dev/ptmx");
1279 fdm = open(pts_name, O_RDWR);
1280 if (fdm < 0)
1281 return -1;
1282 if (grantpt(fdm) < 0) { /* grant access to slave */
1283 close(fdm);
1284 return -2;
1286 if (unlockpt(fdm) < 0) { /* clear slave's lock flag */
1287 close(fdm);
1288 return -3;
1290 ptr = ptsname(fdm);
1291 if (ptr == NULL) { /* get slave's name */
1292 close (fdm);
1293 return -4;
1295 strcpy(pts_name, ptr); /* return name of slave */
1296 return fdm; /* return fd of master */
1297 #else
1298 char *ptr1, *ptr2;
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);
1308 if (fdm < 0) {
1309 if (errno == ENOENT) /* different from EIO */
1310 return -1; /* out of pty devices */
1311 else
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 */
1319 #endif
1322 static int
1323 ptys_open(int fdm, char * pts_name)
1325 int fds;
1326 #ifdef HAVE_PTSNAME
1327 /* following should allocate controlling terminal */
1328 fds = open(pts_name, O_RDWR);
1329 if (fds < 0) {
1330 close(fdm);
1331 return -5;
1333 if (ioctl(fds, I_PUSH, "ptem") < 0) {
1334 close(fdm);
1335 close(fds);
1336 return -6;
1338 if (ioctl(fds, I_PUSH, "ldterm") < 0) {
1339 close(fdm);
1340 close(fds);
1341 return -7;
1343 if (ioctl(fds, I_PUSH, "ttcompat") < 0) {
1344 close(fdm);
1345 close(fds);
1346 return -8;
1349 if (ioctl(fdm, I_PUSH, "pckt") < 0) {
1350 close(fdm);
1351 close(fds);
1352 return -8;
1355 if (ioctl(fdm, I_SRDOPT, RMSGN|RPROTDAT) < 0) {
1356 close(fdm);
1357 close(fds);
1358 return -8;
1361 return fds;
1362 #else
1363 int gid;
1364 struct group *grptr;
1366 grptr = getgrnam("tty");
1367 if (grptr != NULL)
1368 gid = grptr->gr_gid;
1369 else
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);
1375 if (fds < 0) {
1376 close(fdm);
1377 return -1;
1379 return fds;
1380 #endif
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)
1389 return (-1);
1390 switch (pid = fork()) {
1391 case -1:
1392 return (-1);
1393 case 0:
1395 * child
1397 close(master);
1398 login_tty(slave);
1399 return (0);
1402 * parent
1404 *amaster = master;
1405 close(slave);
1406 return (pid);
1409 int scandir(const char *dir, struct dirent ***namelist,
1410 int (*select)(const struct dirent *),
1411 int (*compar)(const struct dirent **, const struct dirent **))
1413 DIR *d;
1414 struct dirent *entry;
1415 register int i=0;
1416 size_t entrysize;
1418 if ((d=opendir(dir)) == NULL)
1419 return(-1);
1421 *namelist=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);
1433 i++;
1436 if (closedir(d)) return(-1);
1437 if (i == 0) return(-1);
1438 if (compar != NULL)
1439 qsort((void *)(*namelist), (size_t)i, sizeof(struct dirent *), compar);
1441 return(i);
1444 #endif /* HAVE_LIBUTIL */
1446 void
1447 anjuta_util_help_display (GtkWindow *parent,
1448 const gchar *doc_id,
1449 const gchar *file_name)
1452 GError *error = NULL;
1453 GdkScreen *screen;
1454 gchar *command;
1455 const gchar *lang;
1456 const gchar * const *langs;
1457 gchar *uri = NULL;
1458 gint i;
1460 g_return_if_fail (file_name != NULL);
1462 langs = g_get_language_names ();
1463 for (i = 0; langs[i]; i++)
1465 lang = langs[i];
1466 if (strchr (lang, '.'))
1467 continue;
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)) {
1473 break;
1475 g_free (uri);
1476 uri = NULL;
1479 if (uri == NULL)
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"));
1485 return;
1488 command = g_strconcat ("gnome-help ghelp://", uri, NULL);
1489 g_free (uri);
1491 screen = gtk_widget_get_screen (GTK_WIDGET (parent));
1492 gdk_spawn_command_line_on_screen (screen, command, &error);
1493 if (error != NULL)
1495 g_warning ("Error executing help application: %s",
1496 error->message);
1497 g_error_free (error);
1499 return;
1501 g_free (command);
1504 /* The following functions are taken from gedit */
1506 /* Note that this function replace home dir with ~ */
1507 gchar *
1508 anjuta_util_uri_get_dirname (const gchar *uri)
1510 gchar *res;
1511 gchar *str;
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 == '.'))
1519 g_free (str);
1521 return NULL;
1524 res = anjuta_util_replace_home_dir_with_tilde (str);
1526 g_free (str);
1528 return res;
1531 gchar*
1532 anjuta_util_replace_home_dir_with_tilde (const gchar *uri)
1534 gchar *tmp;
1535 gchar *home;
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 ();
1542 if (tmp == NULL)
1543 return g_strdup (uri);
1545 home = g_filename_to_utf8 (tmp, -1, NULL, NULL, NULL);
1546 if (home == NULL)
1547 return g_strdup (uri);
1549 if (strcmp (uri, home) == 0)
1551 g_free (home);
1553 return g_strdup ("~");
1556 tmp = home;
1557 home = g_strdup_printf ("%s/", tmp);
1558 g_free (tmp);
1560 if (g_str_has_prefix (uri, home))
1562 gchar *res;
1564 res = g_strdup_printf ("~/%s", uri + strlen (home));
1566 g_free (home);
1568 return res;
1571 g_free (home);
1573 return g_strdup (uri);
1576 gchar *
1577 anjuta_util_str_middle_truncate (const gchar *string,
1578 guint truncate_length)
1580 GString *truncated;
1581 guint length;
1582 guint n_chars;
1583 guint num_left_chars;
1584 guint right_offset;
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
1596 * side)
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
1629 static gchar*
1630 anjuta_util_construct_pathv (const gchar* str, va_list str_list)
1632 GPtrArray *str_arr;
1633 const gchar* tmp_str;
1634 gchar* path;
1636 str_arr = g_ptr_array_new();
1637 g_ptr_array_add (str_arr, (gpointer) str);
1639 /* Extract elements from va_list */
1640 if (str != NULL)
1642 while ((tmp_str = va_arg (str_list, const gchar*)) != NULL)
1644 g_ptr_array_add (str_arr, tmp_str);
1646 va_end (str_list);
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);
1655 return path;
1658 static GFile*
1659 anjuta_util_get_user_cache_filev (const gchar* path, va_list list)
1661 gchar *uri_str, *base_path, *dir;
1662 GFile *uri;
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);
1667 g_free (base_path);
1669 uri = g_file_new_for_path (uri_str);
1670 dir = g_path_get_dirname (uri_str);
1671 g_free(uri_str);
1672 if (!anjuta_util_create_dir (dir)) return NULL;
1674 return uri;
1677 GFile*
1678 anjuta_util_get_user_cache_file (const gchar* path, ...)
1680 va_list list;
1681 va_start (list, path);
1682 return anjuta_util_get_user_cache_filev (path, list);
1685 static GFile*
1686 anjuta_util_get_user_config_filev (const gchar* path, va_list list)
1688 gchar *uri_str, *base_path, *dir;
1689 GFile *uri;
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);
1694 g_free (base_path);
1696 uri = g_file_new_for_path (uri_str);
1697 dir = g_path_get_dirname (uri_str);
1698 g_free(uri_str);
1699 if (!anjuta_util_create_dir (dir)) return NULL;
1701 return uri;
1704 GFile*
1705 anjuta_util_get_user_config_file (const gchar* path, ...)
1707 va_list list;
1708 va_start (list, path);
1709 return anjuta_util_get_user_config_filev (path, list);
1712 static GFile*
1713 anjuta_util_get_user_data_filev (const gchar* path, va_list list)
1715 gchar *uri_str, *base_path, *dir;
1716 GFile *uri;
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);
1721 g_free (base_path);
1723 uri = g_file_new_for_path (uri_str);
1724 dir = g_path_get_dirname (uri_str);
1725 g_free(uri_str);
1726 if (!anjuta_util_create_dir (dir)) return NULL;
1728 return uri;
1731 GFile*
1732 anjuta_util_get_user_data_file (const gchar* path, ...)
1734 va_list list;
1735 va_start (list, path);
1736 return anjuta_util_get_user_data_filev (path, list);
1739 gchar*
1740 anjuta_util_get_user_cache_file_path (const gchar* path, ...)
1742 va_list list;
1743 GFile *file;
1744 gchar *file_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);
1750 return file_path;
1753 gchar*
1754 anjuta_util_get_user_config_file_path (const gchar* path, ...)
1756 va_list list;
1757 GFile *file;
1758 gchar *file_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);
1764 return file_path;
1767 gchar*
1768 anjuta_util_get_user_data_file_path (const gchar* path, ...)
1770 va_list list;
1771 GFile *file;
1772 gchar *file_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);
1778 return file_path;