libanjuta: bgo #696984 - Remove extra empty lines in documentation comments
[anjuta.git] / libanjuta / anjuta-utils.c
blob3632e624dc549f94ad5b02f7b3d5348053582392
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>
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 <sys/wait.h>
44 #include <dirent.h>
45 #include <unistd.h>
46 #include <stdio.h>
47 #include <string.h>
48 #ifndef G_OS_WIN32
49 #include <pwd.h>
50 #endif
52 #include <gio/gio.h>
53 #include <glib/gi18n.h>
54 #include <glib.h>
55 #include <glib/gstdio.h>
56 #include <gtk/gtk.h>
58 #include <libanjuta/anjuta-utils.h>
59 #include <libanjuta/anjuta-debug.h>
60 #include <libanjuta/interfaces/ianjuta-editor-cell.h>
62 #define FILE_BUFFER_SIZE 1024
64 static void
65 anjuta_util_from_file_to_file (GInputStream *istream,
66 GOutputStream *ostream)
68 gsize bytes = 1;
69 GError *error = NULL;
70 gchar buffer[FILE_BUFFER_SIZE];
72 while (bytes != 0 && bytes != -1)
74 bytes = g_input_stream_read (istream, buffer,
75 sizeof (buffer),
76 NULL, &error);
77 if (error)
78 break;
80 g_output_stream_write (ostream, buffer,
81 bytes,
82 NULL, &error);
83 if (error)
84 break;
87 if (error)
89 g_warning ("%s", error->message);
90 g_error_free (error);
91 error = NULL;
94 if (!g_output_stream_close (ostream, NULL, &error))
96 g_warning ("%s", error->message);
97 g_error_free (error);
98 error = NULL;
100 if (!g_input_stream_close (istream, NULL, &error))
102 g_warning ("%s", error->message);
103 g_error_free (error);
108 * anjuta_util_copy_file:
109 * @src: the file where copy
110 * @dest: the path to copy the @src
111 * @show_error: TRUE to show a dialog error
113 * Copies @src to @dest and shows a dialog error in case is needed.
115 * Returns: TRUE if there was an error copying the file.
117 gboolean
118 anjuta_util_copy_file (const gchar * src, const gchar * dest, gboolean show_error)
120 GFile *src_file, *dest_file;
121 GFileInputStream *istream;
122 GFileOutputStream *ostream;
123 GError *error = NULL;
124 gboolean toret = FALSE;
126 src_file = g_file_new_for_path (src);
127 dest_file = g_file_new_for_path (dest);
129 istream = g_file_read (src_file, NULL, &error);
130 if (error)
131 goto free;
133 ostream = g_file_create (dest_file, G_FILE_CREATE_NONE,
134 NULL, &error);
135 if (error)
136 goto free;
138 anjuta_util_from_file_to_file (G_INPUT_STREAM (istream), G_OUTPUT_STREAM (ostream));
140 free: if (error)
142 if (show_error)
143 anjuta_util_dialog_error_system (NULL, error->code,
144 error->message);
146 g_warning ("%s", error->message);
148 toret = TRUE;
151 g_object_unref (src_file);
152 g_object_unref (dest_file);
154 return toret;
157 void
158 anjuta_util_color_from_string (const gchar * val, guint16 * r, guint16 * g, guint16 * b)
160 GdkColor color;
161 if (gdk_color_parse(val, &color))
163 *r = color.red;
164 *g = color.green;
165 *b =color.blue;
169 gchar *
170 anjuta_util_string_from_color (guint16 r, guint16 g, guint16 b)
172 return g_strdup_printf("#%02x%02x%02x", r >> 8, g >> 8, b >> 8);
175 GtkWidget*
176 anjuta_util_button_new_with_stock_image (const gchar* text,
177 const gchar* stock_id)
179 GtkWidget *button;
180 GtkWidget *child;
181 GtkStockItem item;
182 GtkWidget *label;
183 GtkWidget *image;
184 GtkWidget *hbox;
185 GtkWidget *align;
187 button = gtk_button_new ();
189 child = gtk_bin_get_child (GTK_BIN (button));
190 if (child)
191 gtk_container_remove (GTK_CONTAINER (button), child);
193 if (gtk_stock_lookup (stock_id, &item))
195 label = gtk_label_new_with_mnemonic (text);
197 gtk_label_set_mnemonic_widget (GTK_LABEL (label), GTK_WIDGET (button));
199 image = gtk_image_new_from_stock (stock_id, GTK_ICON_SIZE_BUTTON);
200 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
202 align = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
204 gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
205 gtk_box_pack_end (GTK_BOX (hbox), label, FALSE, FALSE, 0);
207 gtk_container_add (GTK_CONTAINER (button), align);
208 gtk_container_add (GTK_CONTAINER (align), hbox);
209 gtk_widget_show_all (align);
211 return button;
214 label = gtk_label_new_with_mnemonic (text);
215 gtk_label_set_mnemonic_widget (GTK_LABEL (label), GTK_WIDGET (button));
217 gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5);
219 gtk_widget_show (label);
220 gtk_container_add (GTK_CONTAINER (button), label);
222 return button;
225 GtkWidget*
226 anjuta_util_dialog_add_button (GtkDialog *dialog, const gchar* text,
227 const gchar* stock_id, gint response_id)
229 GtkWidget *button;
231 g_return_val_if_fail (GTK_IS_DIALOG (dialog), NULL);
232 g_return_val_if_fail (text != NULL, NULL);
233 g_return_val_if_fail (stock_id != NULL, NULL);
235 button = anjuta_util_button_new_with_stock_image (text, stock_id);
236 g_return_val_if_fail (button != NULL, NULL);
238 gtk_widget_set_can_default (button, TRUE);
240 gtk_widget_show (button);
242 gtk_dialog_add_action_widget (dialog, button, response_id);
244 return button;
247 void
248 anjuta_util_dialog_error (GtkWindow *parent, const gchar *mesg, ...)
250 gchar* message;
251 va_list args;
252 GtkWidget *dialog;
253 GtkWindow *real_parent;
255 va_start (args, mesg);
256 message = g_strdup_vprintf (mesg, args);
257 va_end (args);
259 if (parent && GTK_IS_WINDOW (parent))
261 real_parent = parent;
263 else
265 real_parent = NULL;
268 // Dialog to be HIG compliant
269 dialog = gtk_message_dialog_new (real_parent,
270 GTK_DIALOG_DESTROY_WITH_PARENT,
271 GTK_MESSAGE_ERROR,
272 GTK_BUTTONS_CLOSE, "%s", message);
273 g_signal_connect (G_OBJECT (dialog), "response",
274 G_CALLBACK (gtk_widget_destroy), NULL);
275 gtk_widget_show (dialog);
276 g_free (message);
279 void
280 anjuta_util_dialog_warning (GtkWindow *parent, const gchar * mesg, ...)
282 gchar* message;
283 va_list args;
284 GtkWidget *dialog;
285 GtkWindow *real_parent;
287 va_start (args, mesg);
288 message = g_strdup_vprintf (mesg, args);
289 va_end (args);
291 if (parent && GTK_IS_WINDOW (parent))
293 real_parent = parent;
295 else
297 real_parent = NULL;
300 // Dialog to be HIG compliant
301 dialog = gtk_message_dialog_new (real_parent,
302 GTK_DIALOG_DESTROY_WITH_PARENT,
303 GTK_MESSAGE_WARNING,
304 GTK_BUTTONS_CLOSE, "%s", message);
305 g_signal_connect (G_OBJECT (dialog), "response",
306 G_CALLBACK (gtk_widget_destroy), NULL);
307 gtk_widget_show (dialog);
308 g_free (message);
311 void
312 anjuta_util_dialog_info (GtkWindow *parent, const gchar * mesg, ...)
314 gchar* message;
315 va_list args;
316 GtkWidget *dialog;
317 GtkWindow *real_parent;
319 va_start (args, mesg);
320 message = g_strdup_vprintf (mesg, args);
321 va_end (args);
323 if (parent && GTK_IS_WINDOW (parent))
325 real_parent = parent;
327 else
329 real_parent = NULL;
331 // Dialog to be HIG compliant
332 dialog = gtk_message_dialog_new (real_parent,
333 GTK_DIALOG_DESTROY_WITH_PARENT,
334 GTK_MESSAGE_INFO,
335 GTK_BUTTONS_CLOSE, "%s", message);
336 g_signal_connect (G_OBJECT (dialog), "response",
337 G_CALLBACK (gtk_widget_destroy), NULL);
338 gtk_widget_show (dialog);
339 g_free (message);
342 void
343 anjuta_util_dialog_error_system (GtkWindow* parent, gint errnum,
344 const gchar * mesg, ... )
346 gchar* message;
347 gchar* tot_mesg;
348 va_list args;
349 GtkWidget *dialog;
350 GtkWindow *real_parent;
352 va_start (args, mesg);
353 message = g_strdup_vprintf (mesg, args);
354 va_end (args);
356 if (0 != errnum) {
357 /* Avoid space in translated string */
358 tot_mesg = g_strconcat (message, "\n", _("System:"), " ",
359 g_strerror(errnum), NULL);
360 g_free (message);
361 } else
362 tot_mesg = message;
364 if (parent && GTK_IS_WINDOW (parent))
366 real_parent = parent;
368 else
370 real_parent = NULL;
372 // Dialog to be HIG compliant
373 dialog = gtk_message_dialog_new (real_parent,
374 GTK_DIALOG_DESTROY_WITH_PARENT,
375 GTK_MESSAGE_ERROR,
376 GTK_BUTTONS_CLOSE, "%s", tot_mesg);
377 g_signal_connect (G_OBJECT (dialog), "response",
378 G_CALLBACK (gtk_widget_destroy), NULL);
379 gtk_widget_show (dialog);
380 g_free (tot_mesg);
383 gboolean
384 anjuta_util_dialog_boolean_question (GtkWindow *parent, gboolean default_to_yes,
385 const gchar *mesg, ...)
387 gchar* message;
388 va_list args;
389 GtkWidget *dialog;
390 gint ret;
391 GtkWindow *real_parent;
393 va_start (args, mesg);
394 message = g_strdup_vprintf (mesg, args);
395 va_end (args);
397 if (parent && GTK_IS_WINDOW (parent))
399 real_parent = parent;
401 else
403 real_parent = NULL;
406 dialog = gtk_message_dialog_new (real_parent,
407 GTK_DIALOG_DESTROY_WITH_PARENT,
408 GTK_MESSAGE_QUESTION,
409 GTK_BUTTONS_YES_NO, "%s", message);
410 if (default_to_yes)
411 gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_YES);
413 ret = gtk_dialog_run (GTK_DIALOG (dialog));
414 gtk_widget_destroy (dialog);
415 g_free (message);
417 return (ret == GTK_RESPONSE_YES);
420 gboolean
421 anjuta_util_dialog_input (GtkWindow *parent, const gchar *prompt,
422 const gchar *default_value, gchar **return_value)
424 GtkWidget *dialog, *label, *frame, *entry, *dialog_vbox, *vbox;
425 gint res;
426 gchar *markup;
427 GtkWindow *real_parent;
429 if (parent && GTK_IS_WINDOW (parent))
431 real_parent = parent;
433 else
435 real_parent = NULL;
438 dialog = gtk_dialog_new_with_buttons (prompt, real_parent,
439 GTK_DIALOG_DESTROY_WITH_PARENT,
440 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
441 GTK_STOCK_OK, GTK_RESPONSE_OK,
442 NULL);
443 gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
444 dialog_vbox = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
445 gtk_window_set_default_size (GTK_WINDOW (dialog), 400, -1);
446 gtk_widget_show (dialog_vbox);
448 markup = g_strconcat ("<b>", prompt, "</b>", NULL);
449 label = gtk_label_new (NULL);
450 gtk_label_set_markup (GTK_LABEL (label), markup);
451 gtk_widget_show (label);
452 g_free (markup);
454 frame = gtk_frame_new (NULL);
455 gtk_frame_set_label_widget (GTK_FRAME (frame), label);
456 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
457 gtk_container_set_border_width (GTK_CONTAINER (frame), 10);
458 gtk_widget_show (frame);
459 gtk_box_pack_start (GTK_BOX (dialog_vbox), frame, FALSE, FALSE, 0);
461 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
462 gtk_widget_show (vbox);
463 gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
464 gtk_container_add (GTK_CONTAINER (frame), vbox);
466 entry = gtk_entry_new ();
467 gtk_widget_show (entry);
468 gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
469 gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
470 if (default_value)
471 gtk_entry_set_text (GTK_ENTRY (entry), default_value);
473 res = gtk_dialog_run (GTK_DIALOG (dialog));
475 if (gtk_entry_get_text (GTK_ENTRY (entry)) &&
476 strlen (gtk_entry_get_text (GTK_ENTRY (entry))) > 0)
478 *return_value = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
480 else
482 *return_value = NULL;
484 gtk_widget_destroy (dialog);
485 return (res == GTK_RESPONSE_OK);
488 static void
489 on_install_files_done (GObject *proxy, GAsyncResult *result,
490 gpointer user_data)
492 GError *error = NULL;
493 g_dbus_proxy_call_finish ((GDBusProxy *) proxy, result, &error);
494 if (error)
497 Only dbus error is handled. Rest of the errors are from packagekit
498 which have already been notified to user by packagekit.
500 if (error->domain == G_DBUS_ERROR)
502 const gchar *error_message = NULL;
504 /* Service error which implies packagekit is missing */
505 if (error->code == G_DBUS_ERROR_SERVICE_UNKNOWN)
507 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.");
509 /* General dbus error implies failure to call dbus method */
510 else if (error->code != G_DBUS_ERROR_NO_REPLY)
512 error_message = error->message;
514 if (error_message)
515 anjuta_util_dialog_error (NULL,
516 _("Installation failed: %s"),
517 error_message);
519 g_error_free (error);
523 gboolean
524 anjuta_util_install_files (const gchar * const names)
526 GDBusConnection * connection;
527 GDBusProxy * proxy;
528 guint32 xid = 0;
529 gchar ** pkgv;
531 if (!names)
532 return FALSE;
534 connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
535 if (!connection)
536 return FALSE;
538 proxy = g_dbus_proxy_new_sync (connection,
539 G_DBUS_PROXY_FLAGS_NONE,
540 NULL,
541 "org.freedesktop.PackageKit",
542 "/org/freedesktop/PackageKit",
543 "org.freedesktop.PackageKit.Modify",
544 NULL,
545 NULL);
546 if (!proxy)
547 return FALSE;
549 pkgv = g_strsplit (names, ", ", 0);
550 g_dbus_proxy_call (proxy, "InstallProvideFiles",
551 g_variant_new ("(u^ass)",
552 xid,
553 pkgv,
554 ""),
555 G_DBUS_CALL_FLAGS_NONE,
557 NULL,
558 on_install_files_done,
559 NULL);
560 g_strfreev (pkgv);
561 return TRUE;
564 gboolean
565 anjuta_util_package_is_installed (const gchar * package, gboolean show)
567 const gchar* const argv[] = { "pkg-config", "--exists", package, NULL };
568 int exit_status;
569 GError *err = NULL;
571 if (!g_spawn_sync (NULL, (gchar**)argv, NULL, G_SPAWN_SEARCH_PATH, NULL,
572 NULL, NULL, NULL, &exit_status, &err))
574 if (show)
576 anjuta_util_dialog_error (NULL,
577 _("Failed to run \"%s\". "
578 "The returned error was: \"%s\"."),
579 "pkg-config --exists", err->message);
581 g_error_free (err);
585 if (WIFEXITED (exit_status) && WEXITSTATUS (exit_status) == 0)
586 return TRUE;
588 if (show)
590 anjuta_util_dialog_error (NULL,
591 _("The \"%s\" package is not installed.\n"
592 "Please install it."), package);
595 return FALSE;
598 gboolean
599 anjuta_util_prog_is_installed (const gchar * prog, gboolean show)
601 gchar* prog_path = g_find_program_in_path (prog);
602 if (prog_path)
604 g_free (prog_path);
605 return TRUE;
607 if (show)
609 anjuta_util_dialog_error (NULL, _("The \"%s\" utility is not installed.\n"
610 "Please install it."), prog);
612 return FALSE;
615 gchar *
616 anjuta_util_get_a_tmp_file (void)
618 static gint count = 0;
619 gchar *filename;
620 const gchar *tmpdir;
622 tmpdir = g_get_tmp_dir ();
623 filename =
624 g_strdup_printf ("%s/anjuta_%d.%d", tmpdir, count++, getpid ());
625 return filename;
628 /* GList of strings operations */
629 GList *
630 anjuta_util_glist_from_string (const gchar *string)
632 gchar *str, *temp, buff[256];
633 GList *list;
634 gchar *word_start, *word_end;
636 list = NULL;
637 temp = g_strdup (string);
638 str = temp;
639 if (!str)
640 return NULL;
642 while (1)
644 gint i;
645 gchar *ptr;
647 /* Remove leading spaces */
648 while (isspace (*str) && *str != '\0')
649 str++;
650 if (*str == '\0')
651 break;
653 /* Find start and end of word */
654 word_start = str;
655 while (!isspace (*str) && *str != '\0')
656 str++;
657 word_end = str;
659 /* Copy the word into the buffer */
660 for (ptr = word_start, i = 0; ptr < word_end; ptr++, i++)
661 buff[i] = *ptr;
662 buff[i] = '\0';
663 if (strlen (buff))
664 list = g_list_append (list, g_strdup (buff));
665 if (*str == '\0')
666 break;
668 if (temp)
669 g_free (temp);
670 return list;
673 /* Prefix the strings */
674 void
675 anjuta_util_glist_strings_prefix (GList * list, const gchar *prefix)
677 GList *node;
678 node = list;
680 g_return_if_fail (prefix != NULL);
681 while (node)
683 gchar* tmp;
684 tmp = node->data;
685 node->data = g_strconcat (prefix, tmp, NULL);
686 if (tmp) g_free (tmp);
687 node = g_list_next (node);
691 /* Suffix the strings */
692 void
693 anjuta_util_glist_strings_sufix (GList * list, const gchar *sufix)
695 GList *node;
696 node = list;
698 g_return_if_fail (sufix != NULL);
699 while (node)
701 gchar* tmp;
702 tmp = node->data;
703 node->data = g_strconcat (tmp, sufix, NULL);
704 if (tmp) g_free (tmp);
705 node = g_list_next (node);
709 /* Duplicate list of strings */
710 GList*
711 anjuta_util_glist_strings_dup (GList * list)
713 GList *node;
714 GList *new_list;
716 new_list = NULL;
717 node = list;
718 while (node)
720 if (node->data)
721 new_list = g_list_append (new_list, g_strdup(node->data));
722 else
723 new_list = g_list_append (new_list, NULL);
724 node = g_list_next (node);
726 return new_list;
729 /* Join list of strings using the given delimiter */
730 gchar*
731 anjuta_util_glist_strings_join (GList * list, gchar *delimiter)
733 GString *joined;
734 gboolean first = TRUE;
735 GList *node;
737 joined = g_string_new (NULL);
738 node = list;
739 while (node)
741 if (node->data)
743 if (!first)
744 g_string_append (joined, delimiter);
745 else
746 first = FALSE;
747 g_string_append (joined, node->data);
749 node = g_list_next (node);
751 if (joined->len > 0)
752 return g_string_free (joined, FALSE);
753 else
754 g_string_free (joined, TRUE);
755 return NULL;
758 gchar*
759 anjuta_util_get_real_path (const gchar *path)
761 if (path != NULL)
763 gchar *result;
764 #ifdef PATH_MAX
765 gchar buf[PATH_MAX+1];
767 result = realpath (path, buf);
768 if (result != NULL)
770 *(buf + PATH_MAX) = '\0'; /* ensure a terminator */
771 return g_strdup (buf);
773 #else
774 char *buf;
775 /* the string returned by realpath should be cleaned with
776 free(), not g_free() */
777 buf = realpath (path, NULL);
778 if (buf != NULL)
780 result = g_strdup (buf);
781 free (buf);
782 return result;
784 #endif
786 return NULL;
790 * anjuta_util_get_current_dir:
792 * Get current working directory, unlike g_get_current_dir, keeps symbolic links
793 * in path name.
795 * Returns: The current working directory.
797 gchar*
798 anjuta_util_get_current_dir (void)
800 const gchar *pwd;
802 pwd = g_getenv ("PWD");
803 if (pwd != NULL)
805 return g_strdup (pwd);
807 else
809 return g_get_current_dir ();
813 static gboolean
814 is_valid_scheme_character (char c)
816 return g_ascii_isalnum (c) || c == '+' || c == '-' || c == '.';
819 /* Following RFC 2396, valid schemes are built like:
820 * scheme = alpha *( alpha | digit | "+" | "-" | "." )
822 static gboolean
823 has_valid_scheme (const char *uri)
825 const char *p;
827 p = uri;
829 if (!g_ascii_isalpha (*p))
830 return FALSE;
832 do {
833 p++;
834 } while (is_valid_scheme_character (*p));
836 return *p == ':';
840 * anjuta_util_file_new_for_commandline_arg:
841 * @arg: URI or relative or absolute file path
843 * Create a new file corresponding to arg, unlike g_file_new_for_commandline_arg,
844 * keeps symbolic links in path name.
846 * Returns: A new GFile object
848 GFile *
849 anjuta_util_file_new_for_commandline_arg (const gchar *arg)
851 GFile *file;
852 char *filename;
853 char *current_dir;
855 g_return_val_if_fail (arg != NULL, NULL);
857 if (g_path_is_absolute (arg))
858 return g_file_new_for_path (arg);
860 if (has_valid_scheme (arg))
861 return g_file_new_for_uri (arg);
863 current_dir = anjuta_util_get_current_dir ();
864 filename = g_build_filename (current_dir, arg, NULL);
865 g_free (current_dir);
867 file = g_file_new_for_path (filename);
868 g_free (filename);
870 return file;
874 /* Dedup a list of paths - duplicates are removed from the tail.
875 ** Useful for deduping Recent Files and Recent Projects */
876 GList*
877 anjuta_util_glist_path_dedup(GList *list)
879 GList *nlist = NULL, *tmp, *tmp1;
880 gchar *path;
881 struct stat s;
882 for (tmp = list; tmp; tmp = g_list_next(tmp))
884 path = anjuta_util_get_real_path ((const gchar *) tmp->data);
885 if (path)
887 if (stat (path, &s) != 0)
889 g_free(path);
891 else
893 for (tmp1 = nlist; tmp1; tmp1 = g_list_next(tmp1))
895 if (0 == strcmp((const char *) tmp1->data, path))
897 g_free(path);
898 path = NULL;
899 break;
902 if (path)
903 nlist = g_list_prepend(nlist, path);
907 anjuta_util_glist_strings_free(list);
908 nlist = g_list_reverse(nlist);
909 return nlist;
912 static gint
913 sort_node (gchar* a, gchar *b)
915 if ( !a && !b) return 0;
916 else if (!a) return -1;
917 else if (!b) return 1;
918 return strcmp (a, b);
921 /* Sort the list alphabatically */
922 GList*
923 anjuta_util_glist_strings_sort (GList * list)
925 return g_list_sort(list, (GCompareFunc)sort_node);
928 /* Free the strings and GList */
929 void
930 anjuta_util_glist_strings_free (GList * list)
932 g_list_foreach (list, (GFunc) g_free, NULL);
933 g_list_free (list);
937 anjuta_util_type_from_string (AnjutaUtilStringMap *map, const char *str)
939 int i = 0;
941 while (-1 != map[i].type)
943 if (0 == strcmp(map[i].name, str))
944 return map[i].type;
945 ++ i;
947 return -1;
950 const char*
951 anjuta_util_string_from_type (AnjutaUtilStringMap *map, int type)
953 int i = 0;
954 while (-1 != map[i].type)
956 if (map[i].type == type)
957 return map[i].name;
958 ++ i;
960 return "";
963 GList*
964 anjuta_util_glist_from_map (AnjutaUtilStringMap *map)
966 GList *out_list = NULL;
967 int i = 0;
968 while (-1 != map[i].type)
970 out_list = g_list_append(out_list, map[i].name);
971 ++ i;
973 return out_list;
977 GList *
978 anjuta_util_update_string_list (GList *p_list, const gchar *p_str, gint length)
980 gint i;
981 gchar *str;
982 if (!p_str)
983 return p_list;
984 for (i = 0; i < g_list_length (p_list); i++)
986 str = (gchar *) g_list_nth_data (p_list, i);
987 if (!str)
988 continue;
989 if (strcmp (p_str, str) == 0)
991 p_list = g_list_remove (p_list, str);
992 p_list = g_list_prepend (p_list, str);
993 return p_list;
996 p_list = g_list_prepend (p_list, g_strdup (p_str));
997 while (g_list_length (p_list) > length)
999 str = g_list_nth_data (p_list, g_list_length (p_list) - 1);
1000 p_list = g_list_remove (p_list, str);
1001 g_free (str);
1003 return p_list;
1006 gboolean
1007 anjuta_util_create_dir (const gchar* path)
1009 GFile *dir = g_file_new_for_path (path);
1010 GError *err = NULL;
1011 gchar *parent;
1013 if (g_file_query_exists (dir, NULL))
1015 GFileInfo *info = g_file_query_info (dir,
1016 G_FILE_ATTRIBUTE_STANDARD_TYPE,
1017 G_FILE_QUERY_INFO_NONE,
1018 NULL, NULL);
1019 if (g_file_info_get_file_type (info) != G_FILE_TYPE_DIRECTORY)
1021 g_message ("Warning: %s is a file. \n "
1022 "It is trying to be treated as a directory.",g_file_get_path (dir));
1023 g_object_unref (dir);
1024 return FALSE;
1026 g_object_unref (info);
1028 else
1030 parent = g_path_get_dirname (path);
1031 if (anjuta_util_create_dir (parent))
1033 g_free (parent);
1034 if (!g_file_make_directory (dir, NULL, &err))
1036 g_warning ("Error directory:\n %s", err->message);
1037 g_object_unref (dir);
1038 return FALSE;
1041 else
1043 g_free (parent);
1044 g_object_unref (dir);
1045 return FALSE;
1048 g_object_unref (dir);
1050 return TRUE;
1054 * anjuta_util_user_shell:
1056 * Retrieves the user's preferred shell.
1058 * Returns: A newly allocated string that is the path to the shell.
1060 /* copied from deprecated gnome_util_user_shell in libgnome */
1061 gchar *
1062 anjuta_util_user_shell (void)
1064 #ifndef G_OS_WIN32
1065 struct passwd *pw;
1066 gint i;
1067 const gchar *shell;
1068 const gchar shells [][14] = {
1069 /* Note that on some systems shells can also
1070 * be installed in /usr/bin */
1071 "/bin/bash", "/usr/bin/bash",
1072 "/bin/zsh", "/usr/bin/zsh",
1073 "/bin/tcsh", "/usr/bin/tcsh",
1074 "/bin/ksh", "/usr/bin/ksh",
1075 "/bin/csh", "/bin/sh"
1078 if (geteuid () == getuid () &&
1079 getegid () == getgid ()) {
1080 /* only in non-setuid */
1081 if ((shell = g_getenv ("SHELL"))){
1082 if (access (shell, X_OK) == 0) {
1083 return g_strdup (shell);
1087 pw = getpwuid(getuid());
1088 if (pw && pw->pw_shell) {
1089 if (access (pw->pw_shell, X_OK) == 0) {
1090 return g_strdup (pw->pw_shell);
1094 for (i = 0; i != G_N_ELEMENTS (shells); i++) {
1095 if (access (shells [i], X_OK) == 0) {
1096 return g_strdup (shells[i]);
1100 /* If /bin/sh doesn't exist, your system is truly broken. */
1101 abort ();
1103 /* Placate compiler. */
1104 return NULL;
1105 #else
1106 /* g_find_program_in_path() always looks also in the Windows
1107 * and System32 directories, so it should always find either cmd.exe
1108 * or command.com.
1110 gchar *retval = g_find_program_in_path ("cmd.exe");
1112 if (retval == NULL)
1113 retval = g_find_program_in_path ("command.com");
1115 g_assert (retval != NULL);
1117 return retval;
1118 #endif
1122 * anjuta_util_user_terminal:
1124 * Retrieves the user's preferred terminal.
1126 * Returns: A newly allocated strings list. The first argument is the terminal
1127 * program name. The following are the arguments needed to execute
1128 * a command. The list has to be freed with g_strfreev
1130 /* copied from deprecated gnome_execute_terminal in libgnome */
1131 gchar **
1132 anjuta_util_user_terminal (void)
1134 /* FIXME: GSettings */
1135 #if 0
1136 GConfClient *client;
1137 gchar *terminal = NULL;
1138 gchar **argv = NULL;
1139 static const gchar *terms[] = {
1140 "xdg-terminal",
1141 "gnome-terminal",
1142 "nxterm",
1143 "color-xterm",
1144 "rxvt",
1145 "xterm",
1146 "dtterm",
1147 NULL
1149 const gchar **term;
1151 client = gconf_client_get_default ();
1152 terminal = gconf_client_get_string (client, "/desktop/gnome/applications/terminal/exec", NULL);
1153 g_object_unref (client);
1155 if (terminal)
1157 gchar *command_line;
1158 gchar *exec_flag;
1160 exec_flag = gconf_client_get_string (client, "/desktop/gnome/applications/terminal/exec_arg", NULL);
1161 command_line = g_strconcat (terminal, " ", exec_flag, NULL);
1163 g_shell_parse_argv (command_line, NULL, &argv, NULL);
1164 g_free (terminal);
1165 g_free (exec_flag);
1167 return argv;
1171 /* Search for common ones */
1172 for (term = terms; *term != NULL; term++)
1174 terminal = g_find_program_in_path (*term);
1175 if (terminal != NULL) break;
1178 /* Try xterm */
1179 g_warning (_("Cannot find a terminal; using "
1180 "xterm, even if it may not work"));
1181 terminal = g_strdup ("xterm");
1183 argv = g_new0 (char *, 3);
1184 argv[0] = terminal;
1185 /* Note that gnome-terminal takes -x and
1186 * as -e in gnome-terminal is broken we use that. */
1187 argv[1] = g_strdup (term == &terms[2] ? "-x" : "-e");
1189 return argv;
1190 #else
1191 g_warning ("anjuta_util_user_terminal: Not implemented");
1192 return NULL;
1193 #endif
1196 pid_t
1197 anjuta_util_execute_shell (const gchar *dir, const gchar *command)
1199 pid_t pid;
1200 gchar *shell;
1202 g_return_val_if_fail (command != NULL, -1);
1204 shell = anjuta_util_user_shell ();
1205 pid = fork();
1206 if (pid == 0)
1208 if(dir)
1210 anjuta_util_create_dir (dir);
1211 chdir (dir);
1213 execlp (shell, shell, "-c", command, NULL);
1214 g_warning (_("Cannot execute command: %s (using shell %s)\n"), command, shell);
1215 _exit(1);
1217 if (pid < 0)
1218 g_warning (_("Cannot execute command: %s (using shell %s)\n"), command, shell);
1219 g_free (shell);
1221 // Anjuta will take care of child exit automatically.
1222 return pid;
1225 pid_t
1226 anjuta_util_execute_terminal_shell (const gchar *dir, const gchar *command)
1228 pid_t pid;
1229 gchar *shell;
1230 gchar **term_argv;
1232 g_return_val_if_fail (command != NULL, -1);
1234 shell = anjuta_util_user_shell ();
1235 term_argv = anjuta_util_user_terminal ();
1236 pid = fork();
1237 if (pid == 0)
1239 if(dir)
1241 anjuta_util_create_dir (dir);
1242 chdir (dir);
1244 execlp (term_argv[0], term_argv[0], term_argv[1], shell, "-c", command, NULL);
1245 g_warning (_("Cannot execute command: %s (using shell %s)\n"), command, shell);
1246 _exit(1);
1248 if (pid < 0)
1249 g_warning (_("Cannot execute command: %s (using shell %s)\n"), command, shell);
1250 g_free (shell);
1251 g_strfreev (term_argv);
1253 // Anjuta will take care of child exit automatically.
1254 return pid;
1257 gchar *
1258 anjuta_util_convert_to_utf8 (const gchar *str)
1260 GError *error = NULL;
1261 gchar *utf8_msg_string = NULL;
1263 g_return_val_if_fail (str != NULL, NULL);
1264 g_return_val_if_fail (strlen (str) > 0, NULL);
1266 if (g_utf8_validate(str, -1, NULL))
1268 utf8_msg_string = g_strdup (str);
1270 else
1272 gsize rbytes, wbytes;
1273 utf8_msg_string = g_locale_to_utf8 (str, -1, &rbytes, &wbytes, &error);
1274 if (error != NULL) {
1275 g_warning ("g_locale_to_utf8 failed: %s\n", error->message);
1276 g_error_free (error);
1277 /* g_free (utf8_msg_string);
1278 return NULL; */
1281 return utf8_msg_string;
1284 #define LEFT_BRACE(ch) (ch == ')'? '(' : (ch == '}'? '{' : (ch == ']'? '[' : ch)))
1286 gboolean
1287 anjuta_util_jump_to_matching_brace (IAnjutaIterable *iter, gchar brace, gint limit)
1289 gchar point_ch = brace;
1290 gint cur_iteration = 0;
1291 gboolean use_limit = (limit > 0);
1292 GString *braces_stack = g_string_new ("");
1294 g_return_val_if_fail (point_ch == ')' || point_ch == ']' ||
1295 point_ch == '}', FALSE);
1297 /* DEBUG_PRINT ("%s", "Matching brace being"); */
1298 /* Push brace */
1299 g_string_prepend_c (braces_stack, point_ch);
1301 while (ianjuta_iterable_previous (iter, NULL))
1303 /* Check limit */
1304 cur_iteration++;
1305 if (use_limit && cur_iteration > limit)
1306 break;
1308 /* Skip comments and strings */
1309 IAnjutaEditorAttribute attrib =
1310 ianjuta_editor_cell_get_attribute (IANJUTA_EDITOR_CELL (iter), NULL);
1311 if (attrib == IANJUTA_EDITOR_COMMENT || attrib == IANJUTA_EDITOR_STRING)
1312 continue;
1314 /* DEBUG_PRINT ("%s", "point ch = %c", point_ch); */
1315 point_ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (iter), 0,
1316 NULL);
1317 if (point_ch == ')' || point_ch == ']' || point_ch == '}')
1319 /* Push brace */
1320 g_string_prepend_c (braces_stack, point_ch);
1321 continue;
1323 if (point_ch == LEFT_BRACE (braces_stack->str[0]))
1325 /* Pop brace */
1326 g_string_erase (braces_stack, 0, 1);
1328 /* Bail out if there is no more in stack */
1329 if (braces_stack->str[0] == '\0')
1331 /* DEBUG_PRINT ("%s", "Matching brace end -- found"); */
1332 return TRUE;
1335 /* DEBUG_PRINT ("%s", "Matching brace end -- not found"); */
1336 return FALSE;
1339 GList*
1340 anjuta_util_parse_args_from_string (const gchar* string)
1342 gboolean escaped;
1343 gchar quote = 0;
1344 gboolean is_quote = FALSE;
1345 gchar* buffer = g_new0(gchar, strlen(string) + 1);
1346 const gchar *s;
1347 gint idx;
1348 GList* args = NULL;
1350 idx = 0;
1351 escaped = FALSE;
1352 s = string;
1354 while (*s) {
1355 if (!isspace(*s))
1356 break;
1357 s++;
1360 while (*s) {
1361 if (escaped) {
1362 /* The current char was escaped */
1363 buffer[idx++] = *s;
1364 escaped = FALSE;
1365 } else if (*s == '\\') {
1366 /* Current char is an escape */
1367 escaped = TRUE;
1368 } else if (is_quote && *s == quote) {
1369 /* Current char ends a quotation */
1370 is_quote = FALSE;
1371 if (!isspace(*(s+1)) && (*(s+1) != '\0')) {
1372 /* If there is no space after the quotation or it is not
1373 the end of the string */
1374 g_warning ("Parse error while parsing program arguments");
1376 } else if ((*s == '\"' || *s == '\'')) {
1377 if (!is_quote) {
1378 /* Current char starts a quotation */
1379 quote = *s;
1380 is_quote = TRUE;
1381 } else {
1382 /* Just a quote char inside quote */
1383 buffer[idx++] = *s;
1385 } else if (is_quote){
1386 /* Any other char inside quote */
1387 buffer[idx++] = *s;
1388 } else if (isspace(*s)) {
1389 /* Any white space outside quote */
1390 if (idx > 0) {
1391 buffer[idx++] = '\0';
1392 args = g_list_append (args, g_strdup (buffer));
1393 idx = 0;
1395 } else {
1396 buffer[idx++] = *s;
1398 s++;
1400 if (idx > 0) {
1401 /* There are chars in the buffer. Flush as the last arg */
1402 buffer[idx++] = '\0';
1403 args = g_list_append (args, g_strdup (buffer));
1404 idx = 0;
1406 if (is_quote) {
1407 g_warning ("Unclosed quotation encountered at the end of parsing");
1409 g_free (buffer);
1410 return args;
1413 gchar*
1414 anjuta_util_escape_quotes(const gchar* str)
1416 gchar *buffer;
1417 gint idx, max_size;
1418 const gchar *s = str;
1420 g_return_val_if_fail(str, NULL);
1421 idx = 0;
1423 /* We are assuming there will be less than 2048 chars to escape */
1424 max_size = strlen(str) + 2048;
1425 buffer = g_new (gchar, max_size);
1426 max_size -= 2;
1428 while(*s) {
1429 if (idx > max_size)
1430 break;
1431 if (*s == '\"' || *s == '\'' || *s == '\\')
1432 buffer[idx++] = '\\';
1433 buffer[idx++] = *s;
1434 s++;
1436 buffer[idx] = '\0';
1437 return buffer;
1440 /* Diff the text contained in uri with text. Return true if files
1441 differ, FALSE if they are identical.*/
1443 gboolean anjuta_util_diff(const gchar* uri, const gchar* text)
1445 GFile *file;
1446 GFileInfo *file_info;
1447 guint64 size;
1448 gchar* file_text = NULL;
1449 gsize bytes_read;
1451 file = g_file_new_for_uri (uri);
1452 file_info = g_file_query_info (file,
1453 G_FILE_ATTRIBUTE_STANDARD_SIZE,
1454 G_FILE_QUERY_INFO_NONE,
1455 NULL,
1456 NULL);
1458 if (file_info == NULL)
1460 g_object_unref (file);
1461 return TRUE;
1464 size = g_file_info_get_attribute_uint64(file_info,
1465 G_FILE_ATTRIBUTE_STANDARD_SIZE);
1466 g_object_unref (file_info);
1468 if (size == 0 && text == NULL)
1470 g_object_unref (file);
1471 return FALSE;
1473 else if (size == 0 || text == NULL)
1475 g_object_unref (file);
1476 return TRUE;
1479 if (!g_file_load_contents(file,
1480 NULL,
1481 &file_text,
1482 &bytes_read,
1483 NULL,
1484 NULL))
1486 g_object_unref (file);
1487 return TRUE;
1489 g_object_unref (file);
1491 if (bytes_read != size)
1493 g_free (file_text);
1494 return TRUE;
1497 /* according to g_file_load_contents's documentation
1498 * file_text is guaranteed to end with \0.
1500 if (strcmp (file_text, text) == 0)
1502 g_free (file_text);
1503 return FALSE;
1506 g_free (file_text);
1507 return TRUE;
1511 * anjuta_util_is_project_file:
1512 * @filename: the file name
1514 * Return TRUE if the file is an anjuta project file. It is implemented by
1515 * checking only the file extension. So it does not check the existence
1516 * of the file. But it is working on an URI if it does not containt a
1517 * fragment.
1519 * Returns: TRUE if the file is a project file, else FALSE
1521 gboolean
1522 anjuta_util_is_project_file (const gchar *filename)
1524 gsize len = strlen (filename);
1525 return ((len > 8) && (strcmp (filename + len - 7, ".anjuta") == 0));
1529 * anjuta_util_is_template_file:
1530 * @filename: the file name
1532 * Return TRUE if the file is an template project file. It is implemented by
1533 * checking only the file extension. So it does not check the existence
1534 * of the file. But it is working on an URI if it does not containt a
1535 * fragment.
1537 * Returns: TRUE if the file is a template file, else FALSE
1539 gboolean
1540 anjuta_util_is_template_file (const gchar *filename)
1542 gsize len = strlen (filename);
1543 return ((len > 9) && (strcmp (filename + len - 8, ".wiz.tgz") == 0));
1547 * anjuta_util_get_file_info_mine_type:
1548 * @info: the file information object
1550 * Return the mime type corresponding to a file infor object.
1552 * Returns: The mime type as a newly allocated string that must be freed with
1553 * g_free() or %NULL if the mime type cannot be found.
1555 gchar *
1556 anjuta_util_get_file_info_mime_type (GFileInfo *info)
1558 gchar *mime_type = NULL;
1559 const gchar *extension;
1560 const gchar *name;
1562 g_return_val_if_fail (info != NULL, NULL);
1565 /* If Anjuta is not installed in system gnome prefix, the mime types
1566 * may not have been correctly registed. In that case, we use the
1567 * following mime detection
1569 name = g_file_info_get_name (info);
1570 extension = strrchr(name, '.');
1571 if ((extension != NULL) && (extension != name))
1573 const static struct {gchar *extension; gchar *type;} anjuta_types[] = {
1574 {"anjuta", "application/x-anjuta"},
1575 {"prj", "application/x-anjuta-old"},
1576 {NULL, NULL}};
1577 gint i;
1579 for (i = 0; anjuta_types[i].extension != NULL; i++)
1581 if (strcmp(extension + 1, anjuta_types[i].extension) == 0)
1583 mime_type = g_strdup (anjuta_types[i].type);
1584 break;
1589 /* Use mime database if it is not an Anjuta type */
1590 if (mime_type == NULL)
1592 mime_type = g_content_type_get_mime_type (g_file_info_get_content_type(info));
1595 return mime_type;
1599 * anjuta_util_get_file_mine_type:
1600 * @file: the file
1602 * Check if a file exists and return its mime type.
1604 * Returns: NULL if the corresponding file doesn't exist or the mime type as a newly
1605 * allocated string that must be freed with g_free().
1607 gchar *
1608 anjuta_util_get_file_mime_type (GFile *file)
1610 GFileInfo *info;
1611 gchar *mime_type = NULL;
1613 g_return_val_if_fail (file != NULL, NULL);
1615 /* Get file information, check that the file exist at the same time */
1616 info = g_file_query_info (file,
1617 G_FILE_ATTRIBUTE_STANDARD_NAME ","
1618 G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
1619 G_FILE_QUERY_INFO_NONE,
1620 NULL,
1621 NULL);
1623 if (info != NULL)
1625 mime_type = anjuta_util_get_file_info_mime_type (info);
1626 g_object_unref (info);
1629 return mime_type;
1632 gchar *
1633 anjuta_util_get_local_path_from_uri (const gchar *uri)
1635 GFile *file;
1636 gchar *local_path;
1638 file = g_file_new_for_uri (uri);
1639 local_path = g_file_get_path (file);
1640 g_object_unref (file);
1642 return local_path;
1645 #ifdef EMULATE_FORKPTY
1646 #include <grp.h>
1648 static int ptym_open (char *pts_name);
1649 static int ptys_open (int fdm, char * pts_name);
1652 login_tty(int ttyfd)
1654 int fd;
1655 char *fdname;
1657 #ifdef HAVE_SETSID
1658 setsid();
1659 #endif
1660 #ifdef HAVE_SETPGID
1661 setpgid(0, 0);
1662 #endif
1664 /* First disconnect from the old controlling tty. */
1665 #ifdef TIOCNOTTY
1666 fd = open("/dev/tty", O_RDWR|O_NOCTTY);
1667 if (fd >= 0)
1669 ioctl(fd, TIOCNOTTY, NULL);
1670 close(fd);
1672 else
1673 //syslog(LOG_WARNING, "NO CTTY");
1674 #endif /* TIOCNOTTY */
1676 /* Verify that we are successfully disconnected from the controlling tty. */
1677 fd = open("/dev/tty", O_RDWR|O_NOCTTY);
1678 if (fd >= 0)
1680 //syslog(LOG_WARNING, "Failed to disconnect from controlling tty.");
1681 close(fd);
1684 /* Make it our controlling tty. */
1685 #ifdef TIOCSCTTY
1686 ioctl(ttyfd, TIOCSCTTY, NULL);
1687 #endif /* TIOCSCTTY */
1689 fdname = ttyname (ttyfd);
1690 fd = open(fdname, O_RDWR);
1691 if (fd < 0)
1692 ;//syslog(LOG_WARNING, "open %s: %s", fdname, strerror(errno));
1693 else
1694 close(fd);
1696 /* Verify that we now have a controlling tty. */
1697 fd = open("/dev/tty", O_WRONLY);
1698 if (fd < 0)
1700 //syslog(LOG_WARNING, "open /dev/tty: %s", strerror(errno));
1701 return 1;
1704 close(fd);
1705 #if defined(HAVE_VHANGUP) && !defined(HAVE_REVOKE)
1707 RETSIGTYPE (*sig)();
1708 sig = signal(SIGHUP, SIG_IGN);
1709 vhangup();
1710 signal(SIGHUP, sig);
1712 #endif
1713 fd = open(fdname, O_RDWR);
1714 if (fd == -1)
1716 //syslog(LOG_ERR, "can't reopen ctty %s: %s", fdname, strerror(errno));
1717 return -1;
1720 close(ttyfd);
1722 if (fd != 0)
1723 close(0);
1724 if (fd != 1)
1725 close(1);
1726 if (fd != 2)
1727 close(2);
1729 dup2(fd, 0);
1730 dup2(fd, 1);
1731 dup2(fd, 2);
1732 if (fd > 2)
1733 close(fd);
1734 return 0;
1738 openpty(int *amaster, int *aslave, char *name, struct termios *termp,
1739 struct winsize *winp)
1741 char line[20];
1742 *amaster = ptym_open(line);
1743 if (*amaster < 0)
1744 return -1;
1745 *aslave = ptys_open(*amaster, line);
1746 if (*aslave < 0) {
1747 close(*amaster);
1748 return -1;
1750 if (name)
1751 strcpy(name, line);
1752 #ifndef TCSAFLUSH
1753 #define TCSAFLUSH TCSETAF
1754 #endif
1755 if (termp)
1756 (void) tcsetattr(*aslave, TCSAFLUSH, termp);
1757 #ifdef TIOCSWINSZ
1758 if (winp)
1759 (void) ioctl(*aslave, TIOCSWINSZ, (char *)winp);
1760 #endif
1761 return 0;
1764 static int
1765 ptym_open(char * pts_name)
1767 int fdm;
1768 #ifdef HAVE_PTSNAME
1769 char *ptr;
1771 strcpy(pts_name, "/dev/ptmx");
1772 fdm = open(pts_name, O_RDWR);
1773 if (fdm < 0)
1774 return -1;
1775 if (grantpt(fdm) < 0) { /* grant access to slave */
1776 close(fdm);
1777 return -2;
1779 if (unlockpt(fdm) < 0) { /* clear slave's lock flag */
1780 close(fdm);
1781 return -3;
1783 ptr = ptsname(fdm);
1784 if (ptr == NULL) { /* get slave's name */
1785 close (fdm);
1786 return -4;
1788 strcpy(pts_name, ptr); /* return name of slave */
1789 return fdm; /* return fd of master */
1790 #else
1791 char *ptr1, *ptr2;
1793 strcpy(pts_name, "/dev/ptyXY");
1794 /* array index: 012345689 (for references in following code) */
1795 for (ptr1 = "pqrstuvwxyzPQRST"; *ptr1 != 0; ptr1++) {
1796 pts_name[8] = *ptr1;
1797 for (ptr2 = "0123456789abcdef"; *ptr2 != 0; ptr2++) {
1798 pts_name[9] = *ptr2;
1799 /* try to open master */
1800 fdm = open(pts_name, O_RDWR);
1801 if (fdm < 0) {
1802 if (errno == ENOENT) /* different from EIO */
1803 return -1; /* out of pty devices */
1804 else
1805 continue; /* try next pty device */
1807 pts_name[5] = 't'; /* chage "pty" to "tty" */
1808 return fdm; /* got it, return fd of master */
1811 return -1; /* out of pty devices */
1812 #endif
1815 static int
1816 ptys_open(int fdm, char * pts_name)
1818 int fds;
1819 #ifdef HAVE_PTSNAME
1820 /* following should allocate controlling terminal */
1821 fds = open(pts_name, O_RDWR);
1822 if (fds < 0) {
1823 close(fdm);
1824 return -5;
1826 if (ioctl(fds, I_PUSH, "ptem") < 0) {
1827 close(fdm);
1828 close(fds);
1829 return -6;
1831 if (ioctl(fds, I_PUSH, "ldterm") < 0) {
1832 close(fdm);
1833 close(fds);
1834 return -7;
1836 if (ioctl(fds, I_PUSH, "ttcompat") < 0) {
1837 close(fdm);
1838 close(fds);
1839 return -8;
1842 if (ioctl(fdm, I_PUSH, "pckt") < 0) {
1843 close(fdm);
1844 close(fds);
1845 return -8;
1848 if (ioctl(fdm, I_SRDOPT, RMSGN|RPROTDAT) < 0) {
1849 close(fdm);
1850 close(fds);
1851 return -8;
1854 return fds;
1855 #else
1856 int gid;
1857 struct group *grptr;
1859 grptr = getgrnam("tty");
1860 if (grptr != NULL)
1861 gid = grptr->gr_gid;
1862 else
1863 gid = -1; /* group tty is not in the group file */
1864 /* following two functions don't work unless we're root */
1865 chown(pts_name, getuid(), gid);
1866 chmod(pts_name, S_IRUSR | S_IWUSR | S_IWGRP);
1867 fds = open(pts_name, O_RDWR);
1868 if (fds < 0) {
1869 close(fdm);
1870 return -1;
1872 return fds;
1873 #endif
1877 forkpty(int *amaster, char *name, struct termios *termp, struct winsize *winp)
1879 int master, slave, pid;
1881 if (openpty(&master, &slave, name, termp, winp) == -1)
1882 return (-1);
1883 switch (pid = fork()) {
1884 case -1:
1885 return (-1);
1886 case 0:
1888 * child
1890 close(master);
1891 login_tty(slave);
1892 return (0);
1895 * parent
1897 *amaster = master;
1898 close(slave);
1899 return (pid);
1902 int scandir(const char *dir, struct dirent ***namelist,
1903 int (*select)(const struct dirent *),
1904 int (*compar)(const struct dirent **, const struct dirent **))
1906 DIR *d;
1907 struct dirent *entry;
1908 register int i=0;
1909 size_t entrysize;
1911 if ((d=opendir(dir)) == NULL)
1912 return(-1);
1914 *namelist=NULL;
1915 while ((entry=readdir(d)) != NULL)
1917 if (select == NULL || (select != NULL && (*select)(entry)))
1919 *namelist=(struct dirent **)realloc((void *)(*namelist),
1920 (size_t)((i+1)*sizeof(struct dirent *)));
1921 if (*namelist == NULL) return(-1);
1922 entrysize=sizeof(struct dirent)-sizeof(entry->d_name)+strlen(entry->d_name)+1;
1923 (*namelist)[i]=(struct dirent *)malloc(entrysize);
1924 if ((*namelist)[i] == NULL) return(-1);
1925 memcpy((*namelist)[i], entry, entrysize);
1926 i++;
1929 if (closedir(d)) return(-1);
1930 if (i == 0) return(-1);
1931 if (compar != NULL)
1932 qsort((void *)(*namelist), (size_t)i, sizeof(struct dirent *), compar);
1934 return(i);
1937 #endif /* EMULATE_FORKPTY */
1939 void
1940 anjuta_util_help_display (GtkWidget *parent,
1941 const gchar *doc_id,
1942 const gchar *item)
1944 GError *error = NULL;
1945 gchar *command;
1948 command = g_strdup_printf ("yelp help:%s%s%s",
1949 doc_id,
1950 item == NULL ? "" : "/",
1951 item == NULL ? "" : item);
1953 if (!g_spawn_command_line_async (command, &error) &&
1954 (error != NULL))
1956 g_warning ("Error executing help application: %s",
1957 error->message);
1958 g_error_free (error);
1960 g_free (command);
1964 /* The following functions are taken from gedit */
1966 /* Note that this function replace home dir with ~ */
1967 gchar *
1968 anjuta_util_uri_get_dirname (const gchar *uri)
1970 gchar *res;
1971 gchar *str;
1973 // CHECK: does it work with uri chaining? - Paolo
1974 str = g_path_get_dirname (uri);
1975 g_return_val_if_fail (str != NULL, ".");
1977 if ((strlen (str) == 1) && (*str == '.'))
1979 g_free (str);
1981 return NULL;
1984 res = anjuta_util_replace_home_dir_with_tilde (str);
1986 g_free (str);
1988 return res;
1991 gchar*
1992 anjuta_util_replace_home_dir_with_tilde (const gchar *uri)
1994 gchar *tmp;
1995 gchar *home;
1997 g_return_val_if_fail (uri != NULL, NULL);
1999 /* Note that g_get_home_dir returns a const string */
2000 tmp = (gchar *)g_get_home_dir ();
2002 if (tmp == NULL)
2003 return g_strdup (uri);
2005 home = g_filename_to_utf8 (tmp, -1, NULL, NULL, NULL);
2006 if (home == NULL)
2007 return g_strdup (uri);
2009 if (strcmp (uri, home) == 0)
2011 g_free (home);
2013 return g_strdup ("~");
2016 tmp = home;
2017 home = g_strdup_printf ("%s/", tmp);
2018 g_free (tmp);
2020 if (g_str_has_prefix (uri, home))
2022 gchar *res;
2024 res = g_strdup_printf ("~/%s", uri + strlen (home));
2026 g_free (home);
2028 return res;
2031 g_free (home);
2033 return g_strdup (uri);
2037 * anjuta_util_shell_expand:
2038 * @string: input string
2040 * Expand environment variables $(var_name) and tilde (~) in the input string.
2042 * Returns: a newly-allocated string that must be freed with g_free().
2044 gchar*
2045 anjuta_util_shell_expand (const gchar *string)
2047 GString* expand;
2049 if (string == NULL) return NULL;
2051 expand = g_string_sized_new (strlen (string));
2053 for (; *string != '\0'; string++)
2055 switch (*string)
2057 case '$':
2059 /* Variable expansion */
2060 const gchar *end;
2061 gint var_name_len;
2063 end = string + 1;
2064 while (isalnum (*end) || (*end == '_')) end++;
2065 var_name_len = end - string - 1;
2066 if (var_name_len > 0)
2068 const gchar *value;
2070 g_string_append_len (expand, string + 1, var_name_len);
2071 value = g_getenv (expand->str + expand->len - var_name_len);
2072 g_string_truncate (expand, expand->len - var_name_len);
2073 g_string_append (expand, value);
2074 string = end - 1;
2075 continue;
2077 break;
2079 case '~':
2081 /* User home directory expansion */
2082 if (isspace(string[1]) || (string[1] == G_DIR_SEPARATOR) || (string[1] == '\0'))
2084 g_string_append (expand, g_get_home_dir());
2085 continue;
2087 break;
2089 default:
2090 break;
2092 g_string_append_c (expand, *string);
2095 return g_string_free (expand, FALSE);
2098 gchar *
2099 anjuta_util_str_middle_truncate (const gchar *string,
2100 guint truncate_length)
2102 GString *truncated;
2103 guint length;
2104 guint n_chars;
2105 guint num_left_chars;
2106 guint right_offset;
2107 guint delimiter_length;
2108 const gchar *delimiter = "\342\200\246";
2110 g_return_val_if_fail (string != NULL, NULL);
2112 length = strlen (string);
2114 g_return_val_if_fail (g_utf8_validate (string, length, NULL), NULL);
2116 /* It doesnt make sense to truncate strings to less than
2117 * the size of the delimiter plus 2 characters (one on each
2118 * side)
2120 delimiter_length = g_utf8_strlen (delimiter, -1);
2121 if (truncate_length < (delimiter_length + 2)) {
2122 return g_strdup (string);
2125 n_chars = g_utf8_strlen (string, length);
2127 /* Make sure the string is not already small enough. */
2128 if (n_chars <= truncate_length) {
2129 return g_strdup (string);
2132 /* Find the 'middle' where the truncation will occur. */
2133 num_left_chars = (truncate_length - delimiter_length) / 2;
2134 right_offset = n_chars - truncate_length + num_left_chars + delimiter_length;
2136 truncated = g_string_new_len (string,
2137 g_utf8_offset_to_pointer (string, num_left_chars) - string);
2138 g_string_append (truncated, delimiter);
2139 g_string_append (truncated, g_utf8_offset_to_pointer (string, right_offset));
2141 return g_string_free (truncated, FALSE);
2145 * Functions to implement XDG Base Directory Specification
2146 * http://standards.freedesktop.org/basedir-spec/latest/index.html
2147 * Use this to save any config/cache/data files
2151 static gchar*
2152 anjuta_util_construct_pathv (const gchar* str, va_list str_list)
2154 GPtrArray *str_arr;
2155 const gchar* tmp_str;
2156 gchar* path;
2158 str_arr = g_ptr_array_new();
2159 g_ptr_array_add (str_arr, (gpointer) str);
2161 /* Extract elements from va_list */
2162 if (str != NULL)
2164 while ((tmp_str = va_arg (str_list, const gchar*)) != NULL)
2166 g_ptr_array_add (str_arr, (gpointer)tmp_str);
2168 va_end (str_list);
2171 /* Terminate the list */
2172 g_ptr_array_add (str_arr, NULL);
2174 path = g_build_filenamev ((gchar **)str_arr->pdata);
2175 g_ptr_array_free (str_arr, TRUE);
2177 return path;
2180 static GFile*
2181 anjuta_util_get_user_cache_filev (const gchar* path, va_list list)
2183 gchar *uri_str, *base_path, *dir;
2184 GFile *uri;
2185 const gchar anjuta_prefix[] = "anjuta";
2186 base_path = g_build_filename (g_get_user_cache_dir(), anjuta_prefix, path, NULL);
2188 uri_str = anjuta_util_construct_pathv (base_path, list);
2189 g_free (base_path);
2191 uri = g_file_new_for_path (uri_str);
2192 dir = g_path_get_dirname (uri_str);
2193 g_free(uri_str);
2194 if (!anjuta_util_create_dir (dir)) return NULL;
2196 return uri;
2199 GFile*
2200 anjuta_util_get_user_cache_file (const gchar* path, ...)
2202 va_list list;
2203 va_start (list, path);
2204 return anjuta_util_get_user_cache_filev (path, list);
2207 static GFile*
2208 anjuta_util_get_user_config_filev (const gchar* path, va_list list)
2210 gchar *uri_str, *base_path, *dir;
2211 GFile *uri;
2212 const gchar anjuta_prefix[] = "anjuta";
2213 base_path = g_build_filename (g_get_user_config_dir(), anjuta_prefix, path, NULL);
2215 uri_str = anjuta_util_construct_pathv (base_path, list);
2216 g_free (base_path);
2218 uri = g_file_new_for_path (uri_str);
2219 dir = g_path_get_dirname (uri_str);
2220 g_free(uri_str);
2221 if (!anjuta_util_create_dir (dir)) return NULL;
2223 return uri;
2226 GFile*
2227 anjuta_util_get_user_config_file (const gchar* path, ...)
2229 va_list list;
2230 va_start (list, path);
2231 return anjuta_util_get_user_config_filev (path, list);
2234 static GFile*
2235 anjuta_util_get_user_data_filev (const gchar* path, va_list list)
2237 gchar *uri_str, *base_path, *dir;
2238 GFile *uri;
2239 const gchar anjuta_prefix[] = "anjuta";
2240 base_path = g_build_filename (g_get_user_data_dir(), anjuta_prefix, path, NULL);
2242 uri_str = anjuta_util_construct_pathv (base_path, list);
2243 g_free (base_path);
2245 uri = g_file_new_for_path (uri_str);
2246 dir = g_path_get_dirname (uri_str);
2247 g_free(uri_str);
2248 if (!anjuta_util_create_dir (dir)) return NULL;
2250 return uri;
2253 GFile*
2254 anjuta_util_get_user_data_file (const gchar* path, ...)
2256 va_list list;
2257 va_start (list, path);
2258 return anjuta_util_get_user_data_filev (path, list);
2261 gchar*
2262 anjuta_util_get_user_cache_file_path (const gchar* path, ...)
2264 va_list list;
2265 GFile *file;
2266 gchar *file_path;
2267 va_start (list, path);
2268 file = anjuta_util_get_user_cache_filev (path, list);
2269 file_path = g_file_get_path (file);
2270 g_object_unref (file);
2272 return file_path;
2275 gchar*
2276 anjuta_util_get_user_config_file_path (const gchar* path, ...)
2278 va_list list;
2279 GFile *file;
2280 gchar *file_path;
2281 va_start (list, path);
2282 file = anjuta_util_get_user_config_filev (path, list);
2283 file_path = g_file_get_path (file);
2284 g_object_unref (file);
2286 return file_path;
2289 gchar*
2290 anjuta_util_get_user_data_file_path (const gchar* path, ...)
2292 va_list list;
2293 GFile *file;
2294 gchar *file_path;;
2295 va_start (list, path);
2296 file = anjuta_util_get_user_data_filev (path, list);
2297 file_path = g_file_get_path (file);
2298 g_object_unref (file);
2300 return file_path;
2303 GList *
2304 anjuta_util_convert_gfile_list_to_path_list (GList *list)
2306 GList *path_list;
2307 GList *current_file;
2308 gchar *path;
2310 path_list = NULL;
2312 for (current_file = list; current_file != NULL; current_file = g_list_next (current_file))
2314 path = g_file_get_path (current_file->data);
2316 /* Ignore files with invalid paths */
2317 if (path)
2318 path_list = g_list_append (path_list, path);
2321 return path_list;
2324 GList *
2325 anjuta_util_convert_gfile_list_to_relative_path_list (GList *list,
2326 const gchar *parent)
2328 GFile *parent_file;
2329 GList *path_list;
2330 GList *current_file;
2331 gchar *path;
2333 parent_file = g_file_new_for_path (parent);
2334 path_list = NULL;
2336 if (parent_file)
2338 for (current_file = list; current_file != NULL; current_file = g_list_next (current_file))
2340 path = g_file_get_relative_path (parent_file, current_file->data);
2342 /* Ignore files with invalid paths */
2343 if (path)
2344 path_list = g_list_append (path_list, path);
2347 g_object_unref (parent_file);
2350 return path_list;
2355 * anjuta_util_builder_new:
2356 * @filename: Builder file name to open
2357 * @error: Optional error object, if NULL display a dialog if the file is missing
2359 * Create a new GtkBuilder object and load the file in it. Display an error
2360 * if the file is missing. Use a dialog if error is NULL, just a warning
2361 * if the error can be reported.
2363 * Returns: The new GtkBuilder object
2365 GtkBuilder *
2366 anjuta_util_builder_new (const gchar *filename, GError **error)
2368 GtkBuilder *bxml = gtk_builder_new ();
2369 GError *err = NULL;
2371 /* Load glade file */
2372 if (!gtk_builder_add_from_file (bxml, filename, &err))
2374 g_object_unref (bxml);
2375 bxml = NULL;
2377 /* Display the error to the user if it cannot be reported to the caller */
2378 if (error == NULL)
2380 anjuta_util_dialog_error (NULL, _("Unable to load user interface file: %s"), err->message);
2382 else
2384 g_warning ("Couldn't load builder file: %s", err->message);
2386 g_propagate_error (error, err);
2389 /* Tag the builder object with the filename to allow better error message
2390 * with the following function */
2391 if (bxml != NULL)
2393 g_object_set_data_full (G_OBJECT (bxml), "filename", g_strdup (filename), g_free);
2396 return bxml;
2400 * anjuta_util_builder_get_objects:
2401 * @builder: Builder object
2402 * @first_widget: Name of first widget to get
2403 * ...: Address to store the first widget pointer, followed optionally by
2404 * more name/pointer pairs, followed by NULL
2406 * Create a new GtkBuilder object and load the file in it. Display an error
2407 * if the file is missing. Use a dialog if error is NULL, just a warning
2408 * if the error can be reported.
2410 * Returns: TRUE is everything works as expected.
2412 gboolean
2413 anjuta_util_builder_get_objects (GtkBuilder *builder, const gchar *first_widget,...)
2415 va_list args;
2416 const gchar *name;
2417 GObject **object_ptr;
2418 gboolean missing = FALSE;
2420 va_start (args, first_widget);
2422 for (name = first_widget; name; name = va_arg (args, char *))
2424 object_ptr = va_arg (args, void *);
2425 *object_ptr = gtk_builder_get_object (builder, name);
2427 /* Object not found, display a warning */
2428 if (!*object_ptr)
2430 const gchar *filename = (const gchar *)g_object_get_data (G_OBJECT (builder), "filename");
2431 if (filename)
2433 g_warning ("Missing widget '%s' in file %s", name, filename);
2435 else
2437 g_warning("Missing widget '%s'", name);
2439 missing = TRUE;
2442 va_end (args);
2444 return !missing;
2448 * anjuta_utils_drop_get_files:
2449 * @selection_data: the #GtkSelectionData from drag_data_received
2451 * Create a list of valid uri's from a uri-list drop.
2453 * Return value: (element-type GFile*): a list of GFiles
2455 GSList*
2456 anjuta_utils_drop_get_files (GtkSelectionData *selection_data)
2458 gchar **uris;
2459 gint i;
2460 GSList* files = NULL;
2462 uris = g_uri_list_extract_uris ((gchar *) gtk_selection_data_get_data (selection_data));
2464 for (i = 0; uris[i] != NULL; i++)
2466 GFile* file = g_file_new_for_uri (uris[i]);
2467 files = g_slist_append(files, file);
2470 return files;
2474 * anjuta_util_get_user_mail:
2476 * Returns: The e-mail Address of the logged-in user. The resulting string
2477 * must be free'd after use.
2479 gchar*
2480 anjuta_util_get_user_mail()
2482 /* FIXME: Use libfolks or something like it to query the mail address */
2483 return g_strconcat(g_get_user_name (), "@", g_get_host_name (), NULL);
2487 * anjuta_utils_clone_string_gptrarray:
2488 * @source: The source GPtrArray containing items representing strings
2490 * Clones the contents of source GPtrArray into a new allocated GPtrArray.
2492 * Return a new allocated GPtrArray with strings g_strdup (), NULL on error.
2493 * The returned array has set g_free as GDestroyNotity function, so that user
2494 * should only care to g_ptr_array_unref () without freeing the strings.
2496 GPtrArray *
2497 anjuta_util_clone_string_gptrarray (const GPtrArray* source)
2499 gint i;
2500 GPtrArray *dest;
2502 g_return_val_if_fail (source != NULL, NULL);
2504 dest = g_ptr_array_sized_new (source->len);
2505 g_ptr_array_set_free_func (dest, g_free);
2507 for (i = 0; i < source->len; i++)
2509 g_ptr_array_add (dest, g_strdup (g_ptr_array_index (source, i)));
2512 return dest;
2515 void
2516 anjuta_util_list_all_dir_children (GList **children, GFile *dir)
2518 GFileEnumerator *list;
2520 list = g_file_enumerate_children (dir,
2521 G_FILE_ATTRIBUTE_STANDARD_NAME,
2522 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
2523 NULL,
2524 NULL);
2526 if (list != NULL)
2528 GFileInfo *info;
2530 while ((info = g_file_enumerator_next_file (list, NULL, NULL)) != NULL)
2532 const gchar *name;
2533 GFile *file;
2535 name = g_file_info_get_name (info);
2536 file = g_file_get_child (dir, name);
2537 g_object_unref (info);
2539 if (g_file_query_file_type (file, G_FILE_QUERY_INFO_NONE, NULL) == G_FILE_TYPE_DIRECTORY)
2541 anjuta_util_list_all_dir_children (children, file);
2542 g_object_unref (file);
2544 else
2546 *children = g_list_prepend (*children, file);
2549 g_file_enumerator_close (list, NULL, NULL);
2550 g_object_unref (list);
2554 GPtrArray *
2555 anjuta_util_convert_string_list_to_array (GList *list)
2557 GList *node;
2558 GPtrArray *res;
2560 g_return_val_if_fail (list != NULL, NULL);
2562 res = g_ptr_array_new_with_free_func (g_free);
2564 node = list;
2565 while (node != NULL)
2567 g_ptr_array_add (res, g_strdup (node->data));
2569 node = g_list_next (node);
2572 return res;