libanjuta: Fix some warnings and made AnjutaPluginDescription a boxed type
[anjuta.git] / libanjuta / anjuta-utils.c
blob76b46b79dc591aa176c3e5c1e3faa4f06914162e
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, const gchar *mesg, ...)
386 gchar* message;
387 va_list args;
388 GtkWidget *dialog;
389 gint ret;
390 GtkWindow *real_parent;
392 va_start (args, mesg);
393 message = g_strdup_vprintf (mesg, args);
394 va_end (args);
396 if (parent && GTK_IS_WINDOW (parent))
398 real_parent = parent;
400 else
402 real_parent = NULL;
405 dialog = gtk_message_dialog_new (real_parent,
406 GTK_DIALOG_DESTROY_WITH_PARENT,
407 GTK_MESSAGE_QUESTION,
408 GTK_BUTTONS_YES_NO, "%s", message);
410 ret = gtk_dialog_run (GTK_DIALOG (dialog));
411 gtk_widget_destroy (dialog);
412 g_free (message);
414 return (ret == GTK_RESPONSE_YES);
417 gboolean
418 anjuta_util_dialog_input (GtkWindow *parent, const gchar *prompt,
419 const gchar *default_value, gchar **return_value)
421 GtkWidget *dialog, *label, *frame, *entry, *dialog_vbox, *vbox;
422 gint res;
423 gchar *markup;
424 GtkWindow *real_parent;
426 if (parent && GTK_IS_WINDOW (parent))
428 real_parent = parent;
430 else
432 real_parent = NULL;
435 dialog = gtk_dialog_new_with_buttons (prompt, real_parent,
436 GTK_DIALOG_DESTROY_WITH_PARENT,
437 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
438 GTK_STOCK_OK, GTK_RESPONSE_OK,
439 NULL);
440 gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
441 dialog_vbox = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
442 gtk_window_set_default_size (GTK_WINDOW (dialog), 400, -1);
443 gtk_widget_show (dialog_vbox);
445 markup = g_strconcat ("<b>", prompt, "</b>", NULL);
446 label = gtk_label_new (NULL);
447 gtk_label_set_markup (GTK_LABEL (label), markup);
448 gtk_widget_show (label);
449 g_free (markup);
451 frame = gtk_frame_new (NULL);
452 gtk_frame_set_label_widget (GTK_FRAME (frame), label);
453 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
454 gtk_container_set_border_width (GTK_CONTAINER (frame), 10);
455 gtk_widget_show (frame);
456 gtk_box_pack_start (GTK_BOX (dialog_vbox), frame, FALSE, FALSE, 0);
458 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
459 gtk_widget_show (vbox);
460 gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
461 gtk_container_add (GTK_CONTAINER (frame), vbox);
463 entry = gtk_entry_new ();
464 gtk_widget_show (entry);
465 gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
466 gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
467 if (default_value)
468 gtk_entry_set_text (GTK_ENTRY (entry), default_value);
470 res = gtk_dialog_run (GTK_DIALOG (dialog));
472 if (gtk_entry_get_text (GTK_ENTRY (entry)) &&
473 strlen (gtk_entry_get_text (GTK_ENTRY (entry))) > 0)
475 *return_value = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
477 else
479 *return_value = NULL;
481 gtk_widget_destroy (dialog);
482 return (res == GTK_RESPONSE_OK);
485 static void
486 on_install_files_done (GObject *proxy, GAsyncResult *result,
487 gpointer user_data)
489 GError *error = NULL;
490 g_dbus_proxy_call_finish ((GDBusProxy *) proxy, result, &error);
491 if (error)
494 Only dbus error is handled. Rest of the errors are from packagekit
495 which have already been notified to user by packagekit.
497 if (error->domain == G_DBUS_ERROR)
499 const gchar *error_message = NULL;
501 /* Service error which implies packagekit is missing */
502 if (error->code == G_DBUS_ERROR_SERVICE_UNKNOWN)
504 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.");
506 /* General dbus error implies failure to call dbus method */
507 else if (error->code != G_DBUS_ERROR_NO_REPLY)
509 error_message = error->message;
511 if (error_message)
512 anjuta_util_dialog_error (NULL,
513 _("Installation failed: %s"),
514 error_message);
516 g_error_free (error);
520 gboolean
521 anjuta_util_install_files (const gchar * const names)
523 GDBusConnection * connection;
524 GDBusProxy * proxy;
525 guint32 xid = 0;
526 gchar ** pkgv;
528 if (!names)
529 return FALSE;
531 connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
532 if (!connection)
533 return FALSE;
535 proxy = g_dbus_proxy_new_sync (connection,
536 G_DBUS_PROXY_FLAGS_NONE,
537 NULL,
538 "org.freedesktop.PackageKit",
539 "/org/freedesktop/PackageKit",
540 "org.freedesktop.PackageKit.Modify",
541 NULL,
542 NULL);
543 if (!proxy)
544 return FALSE;
546 pkgv = g_strsplit (names, ", ", 0);
547 g_dbus_proxy_call (proxy, "InstallProvideFiles",
548 g_variant_new ("(u^ass)",
549 xid,
550 pkgv,
551 ""),
552 G_DBUS_CALL_FLAGS_NONE,
554 NULL,
555 on_install_files_done,
556 NULL);
557 g_strfreev (pkgv);
558 return TRUE;
561 gboolean
562 anjuta_util_package_is_installed (const gchar * package, gboolean show)
564 gboolean installed = FALSE;
565 int status;
566 int exit_status;
567 pid_t pid;
569 if ((pid = fork()) == 0)
570 execlp ("pkg-config", "pkg-config", "--exists", package, NULL);
572 waitpid (pid, &status, 0);
573 exit_status = WEXITSTATUS (status);
574 installed = (exit_status == 0) ? TRUE : FALSE;
575 if (installed)
576 return TRUE;
578 if (show)
580 anjuta_util_dialog_error (NULL,
581 _("The \"%s\" package is not installed.\n"
582 "Please install it."), package);
585 return FALSE;
588 gboolean
589 anjuta_util_prog_is_installed (const gchar * prog, gboolean show)
591 gchar* prog_path = g_find_program_in_path (prog);
592 if (prog_path)
594 g_free (prog_path);
595 return TRUE;
597 if (show)
599 anjuta_util_dialog_error (NULL, _("The \"%s\" utility is not installed.\n"
600 "Please install it."), prog);
602 return FALSE;
605 gchar *
606 anjuta_util_get_a_tmp_file (void)
608 static gint count = 0;
609 gchar *filename;
610 const gchar *tmpdir;
612 tmpdir = g_get_tmp_dir ();
613 filename =
614 g_strdup_printf ("%s/anjuta_%d.%d", tmpdir, count++, getpid ());
615 return filename;
618 /* GList of strings operations */
619 GList *
620 anjuta_util_glist_from_string (const gchar *string)
622 gchar *str, *temp, buff[256];
623 GList *list;
624 gchar *word_start, *word_end;
626 list = NULL;
627 temp = g_strdup (string);
628 str = temp;
629 if (!str)
630 return NULL;
632 while (1)
634 gint i;
635 gchar *ptr;
637 /* Remove leading spaces */
638 while (isspace (*str) && *str != '\0')
639 str++;
640 if (*str == '\0')
641 break;
643 /* Find start and end of word */
644 word_start = str;
645 while (!isspace (*str) && *str != '\0')
646 str++;
647 word_end = str;
649 /* Copy the word into the buffer */
650 for (ptr = word_start, i = 0; ptr < word_end; ptr++, i++)
651 buff[i] = *ptr;
652 buff[i] = '\0';
653 if (strlen (buff))
654 list = g_list_append (list, g_strdup (buff));
655 if (*str == '\0')
656 break;
658 if (temp)
659 g_free (temp);
660 return list;
663 /* Prefix the strings */
664 void
665 anjuta_util_glist_strings_prefix (GList * list, const gchar *prefix)
667 GList *node;
668 node = list;
670 g_return_if_fail (prefix != NULL);
671 while (node)
673 gchar* tmp;
674 tmp = node->data;
675 node->data = g_strconcat (prefix, tmp, NULL);
676 if (tmp) g_free (tmp);
677 node = g_list_next (node);
681 /* Suffix the strings */
682 void
683 anjuta_util_glist_strings_sufix (GList * list, const gchar *sufix)
685 GList *node;
686 node = list;
688 g_return_if_fail (sufix != NULL);
689 while (node)
691 gchar* tmp;
692 tmp = node->data;
693 node->data = g_strconcat (tmp, sufix, NULL);
694 if (tmp) g_free (tmp);
695 node = g_list_next (node);
699 /* Duplicate list of strings */
700 GList*
701 anjuta_util_glist_strings_dup (GList * list)
703 GList *node;
704 GList *new_list;
706 new_list = NULL;
707 node = list;
708 while (node)
710 if (node->data)
711 new_list = g_list_append (new_list, g_strdup(node->data));
712 else
713 new_list = g_list_append (new_list, NULL);
714 node = g_list_next (node);
716 return new_list;
719 /* Join list of strings using the given delimiter */
720 gchar*
721 anjuta_util_glist_strings_join (GList * list, gchar *delimiter)
723 GString *joined;
724 gboolean first = TRUE;
725 GList *node;
727 joined = g_string_new (NULL);
728 node = list;
729 while (node)
731 if (node->data)
733 if (!first)
734 g_string_append (joined, delimiter);
735 else
736 first = FALSE;
737 g_string_append (joined, node->data);
739 node = g_list_next (node);
741 if (joined->len > 0)
742 return g_string_free (joined, FALSE);
743 else
744 g_string_free (joined, TRUE);
745 return NULL;
748 gchar*
749 anjuta_util_get_real_path (const gchar *path)
751 if (path != NULL)
753 gchar *result;
754 #ifdef PATH_MAX
755 gchar buf[PATH_MAX+1];
757 result = realpath (path, buf);
758 if (result != NULL)
760 *(buf + PATH_MAX) = '\0'; /* ensure a terminator */
761 return g_strdup (buf);
763 #else
764 char *buf;
765 /* the string returned by realpath should be cleaned with
766 free(), not g_free() */
767 buf = realpath (path, NULL);
768 if (buf != NULL)
770 result = g_strdup (buf);
771 free (buf);
772 return result;
774 #endif
776 return NULL;
780 * anjuta_util_get_current_dir:
782 * Get current working directory, unlike g_get_current_dir, keeps symbolic links
783 * in path name.
785 * Returns: The current working directory.
787 gchar*
788 anjuta_util_get_current_dir (void)
790 const gchar *pwd;
792 pwd = g_getenv ("PWD");
793 if (pwd != NULL)
795 return g_strdup (pwd);
797 else
799 return g_get_current_dir ();
803 static gboolean
804 is_valid_scheme_character (char c)
806 return g_ascii_isalnum (c) || c == '+' || c == '-' || c == '.';
809 /* Following RFC 2396, valid schemes are built like:
810 * scheme = alpha *( alpha | digit | "+" | "-" | "." )
812 static gboolean
813 has_valid_scheme (const char *uri)
815 const char *p;
817 p = uri;
819 if (!g_ascii_isalpha (*p))
820 return FALSE;
822 do {
823 p++;
824 } while (is_valid_scheme_character (*p));
826 return *p == ':';
830 * anjuta_util_file_new_for_commandline_arg:
832 * @arg: URI or relative or absolute file path
834 * Create a new file corresponding to arg, unlike g_file_new_for_commandline_arg,
835 * keeps symbolic links in path name.
837 * Returns: A new GFile object
839 GFile *
840 anjuta_util_file_new_for_commandline_arg (const gchar *arg)
842 GFile *file;
843 char *filename;
844 char *current_dir;
846 g_return_val_if_fail (arg != NULL, NULL);
848 if (g_path_is_absolute (arg))
849 return g_file_new_for_path (arg);
851 if (has_valid_scheme (arg))
852 return g_file_new_for_uri (arg);
854 current_dir = anjuta_util_get_current_dir ();
855 filename = g_build_filename (current_dir, arg, NULL);
856 g_free (current_dir);
858 file = g_file_new_for_path (filename);
859 g_free (filename);
861 return file;
865 /* Dedup a list of paths - duplicates are removed from the tail.
866 ** Useful for deduping Recent Files and Recent Projects */
867 GList*
868 anjuta_util_glist_path_dedup(GList *list)
870 GList *nlist = NULL, *tmp, *tmp1;
871 gchar *path;
872 struct stat s;
873 for (tmp = list; tmp; tmp = g_list_next(tmp))
875 path = anjuta_util_get_real_path ((const gchar *) tmp->data);
876 if (path)
878 if (stat (path, &s) != 0)
880 g_free(path);
882 else
884 for (tmp1 = nlist; tmp1; tmp1 = g_list_next(tmp1))
886 if (0 == strcmp((const char *) tmp1->data, path))
888 g_free(path);
889 path = NULL;
890 break;
893 if (path)
894 nlist = g_list_prepend(nlist, path);
898 anjuta_util_glist_strings_free(list);
899 nlist = g_list_reverse(nlist);
900 return nlist;
903 static gint
904 sort_node (gchar* a, gchar *b)
906 if ( !a && !b) return 0;
907 else if (!a) return -1;
908 else if (!b) return 1;
909 return strcmp (a, b);
912 /* Sort the list alphabatically */
913 GList*
914 anjuta_util_glist_strings_sort (GList * list)
916 return g_list_sort(list, (GCompareFunc)sort_node);
919 /* Free the strings and GList */
920 void
921 anjuta_util_glist_strings_free (GList * list)
923 g_list_foreach (list, (GFunc) g_free, NULL);
924 g_list_free (list);
928 anjuta_util_type_from_string (AnjutaUtilStringMap *map, const char *str)
930 int i = 0;
932 while (-1 != map[i].type)
934 if (0 == strcmp(map[i].name, str))
935 return map[i].type;
936 ++ i;
938 return -1;
941 const char*
942 anjuta_util_string_from_type (AnjutaUtilStringMap *map, int type)
944 int i = 0;
945 while (-1 != map[i].type)
947 if (map[i].type == type)
948 return map[i].name;
949 ++ i;
951 return "";
954 GList*
955 anjuta_util_glist_from_map (AnjutaUtilStringMap *map)
957 GList *out_list = NULL;
958 int i = 0;
959 while (-1 != map[i].type)
961 out_list = g_list_append(out_list, map[i].name);
962 ++ i;
964 return out_list;
968 GList *
969 anjuta_util_update_string_list (GList *p_list, const gchar *p_str, gint length)
971 gint i;
972 gchar *str;
973 if (!p_str)
974 return p_list;
975 for (i = 0; i < g_list_length (p_list); i++)
977 str = (gchar *) g_list_nth_data (p_list, i);
978 if (!str)
979 continue;
980 if (strcmp (p_str, str) == 0)
982 p_list = g_list_remove (p_list, str);
983 p_list = g_list_prepend (p_list, str);
984 return p_list;
987 p_list = g_list_prepend (p_list, g_strdup (p_str));
988 while (g_list_length (p_list) > length)
990 str = g_list_nth_data (p_list, g_list_length (p_list) - 1);
991 p_list = g_list_remove (p_list, str);
992 g_free (str);
994 return p_list;
997 gboolean
998 anjuta_util_create_dir (const gchar* path)
1000 GFile *dir = g_file_new_for_path (path);
1001 GError *err = NULL;
1002 gchar *parent;
1004 if (g_file_query_exists (dir, NULL))
1006 GFileInfo *info = g_file_query_info (dir,
1007 G_FILE_ATTRIBUTE_STANDARD_TYPE,
1008 G_FILE_QUERY_INFO_NONE,
1009 NULL, NULL);
1010 if (g_file_info_get_file_type (info) != G_FILE_TYPE_DIRECTORY)
1012 g_message ("Warning: %s is a file. \n "
1013 "It is trying to be treated as a directory.",g_file_get_path (dir));
1014 g_object_unref (dir);
1015 return FALSE;
1017 g_object_unref (info);
1019 else
1021 parent = g_path_get_dirname (path);
1022 if (anjuta_util_create_dir (parent))
1024 g_free (parent);
1025 if (!g_file_make_directory (dir, NULL, &err))
1027 g_warning ("Error directory:\n %s", err->message);
1028 g_object_unref (dir);
1029 return FALSE;
1032 else
1034 g_free (parent);
1035 g_object_unref (dir);
1036 return FALSE;
1039 g_object_unref (dir);
1041 return TRUE;
1045 * anjuta_util_user_shell:
1047 * Retrieves the user's preferred shell.
1049 * Returns: A newly allocated string that is the path to the shell.
1051 /* copied from deprecated gnome_util_user_shell in libgnome */
1052 gchar *
1053 anjuta_util_user_shell (void)
1055 #ifndef G_OS_WIN32
1056 struct passwd *pw;
1057 gint i;
1058 const gchar *shell;
1059 const gchar shells [][14] = {
1060 /* Note that on some systems shells can also
1061 * be installed in /usr/bin */
1062 "/bin/bash", "/usr/bin/bash",
1063 "/bin/zsh", "/usr/bin/zsh",
1064 "/bin/tcsh", "/usr/bin/tcsh",
1065 "/bin/ksh", "/usr/bin/ksh",
1066 "/bin/csh", "/bin/sh"
1069 if (geteuid () == getuid () &&
1070 getegid () == getgid ()) {
1071 /* only in non-setuid */
1072 if ((shell = g_getenv ("SHELL"))){
1073 if (access (shell, X_OK) == 0) {
1074 return g_strdup (shell);
1078 pw = getpwuid(getuid());
1079 if (pw && pw->pw_shell) {
1080 if (access (pw->pw_shell, X_OK) == 0) {
1081 return g_strdup (pw->pw_shell);
1085 for (i = 0; i != G_N_ELEMENTS (shells); i++) {
1086 if (access (shells [i], X_OK) == 0) {
1087 return g_strdup (shells[i]);
1091 /* If /bin/sh doesn't exist, your system is truly broken. */
1092 abort ();
1094 /* Placate compiler. */
1095 return NULL;
1096 #else
1097 /* g_find_program_in_path() always looks also in the Windows
1098 * and System32 directories, so it should always find either cmd.exe
1099 * or command.com.
1101 gchar *retval = g_find_program_in_path ("cmd.exe");
1103 if (retval == NULL)
1104 retval = g_find_program_in_path ("command.com");
1106 g_assert (retval != NULL);
1108 return retval;
1109 #endif
1113 * anjuta_util_user_terminal:
1115 * Retrieves the user's preferred terminal.
1117 * Returns: A newly allocated strings list. The first argument is the terminal
1118 * program name. The following are the arguments needed to execute
1119 * a command. The list has to be freed with g_strfreev
1121 /* copied from deprecated gnome_execute_terminal in libgnome */
1122 gchar **
1123 anjuta_util_user_terminal (void)
1125 /* FIXME: GSettings */
1126 #if 0
1127 GConfClient *client;
1128 gchar *terminal = NULL;
1129 gchar **argv = NULL;
1130 static const gchar *terms[] = {
1131 "xdg-terminal",
1132 "gnome-terminal",
1133 "nxterm",
1134 "color-xterm",
1135 "rxvt",
1136 "xterm",
1137 "dtterm",
1138 NULL
1140 const gchar **term;
1142 client = gconf_client_get_default ();
1143 terminal = gconf_client_get_string (client, "/desktop/gnome/applications/terminal/exec", NULL);
1144 g_object_unref (client);
1146 if (terminal)
1148 gchar *command_line;
1149 gchar *exec_flag;
1151 exec_flag = gconf_client_get_string (client, "/desktop/gnome/applications/terminal/exec_arg", NULL);
1152 command_line = g_strconcat (terminal, " ", exec_flag, NULL);
1154 g_shell_parse_argv (command_line, NULL, &argv, NULL);
1155 g_free (terminal);
1156 g_free (exec_flag);
1158 return argv;
1162 /* Search for common ones */
1163 for (term = terms; *term != NULL; term++)
1165 terminal = g_find_program_in_path (*term);
1166 if (terminal != NULL) break;
1169 /* Try xterm */
1170 g_warning (_("Cannot find a terminal; using "
1171 "xterm, even if it may not work"));
1172 terminal = g_strdup ("xterm");
1174 argv = g_new0 (char *, 3);
1175 argv[0] = terminal;
1176 /* Note that gnome-terminal takes -x and
1177 * as -e in gnome-terminal is broken we use that. */
1178 argv[1] = g_strdup (term == &terms[2] ? "-x" : "-e");
1180 return argv;
1181 #else
1182 g_warning ("anjuta_util_user_terminal: Not implemented");
1183 return NULL;
1184 #endif
1187 pid_t
1188 anjuta_util_execute_shell (const gchar *dir, const gchar *command)
1190 pid_t pid;
1191 gchar *shell;
1193 g_return_val_if_fail (command != NULL, -1);
1195 shell = anjuta_util_user_shell ();
1196 pid = fork();
1197 if (pid == 0)
1199 if(dir)
1201 anjuta_util_create_dir (dir);
1202 chdir (dir);
1204 execlp (shell, shell, "-c", command, NULL);
1205 g_warning (_("Cannot execute command: %s (using shell %s)\n"), command, shell);
1206 _exit(1);
1208 if (pid < 0)
1209 g_warning (_("Cannot execute command: %s (using shell %s)\n"), command, shell);
1210 g_free (shell);
1212 // Anjuta will take care of child exit automatically.
1213 return pid;
1216 pid_t
1217 anjuta_util_execute_terminal_shell (const gchar *dir, const gchar *command)
1219 pid_t pid;
1220 gchar *shell;
1221 gchar **term_argv;
1223 g_return_val_if_fail (command != NULL, -1);
1225 shell = anjuta_util_user_shell ();
1226 term_argv = anjuta_util_user_terminal ();
1227 pid = fork();
1228 if (pid == 0)
1230 if(dir)
1232 anjuta_util_create_dir (dir);
1233 chdir (dir);
1235 execlp (term_argv[0], term_argv[0], term_argv[1], shell, "-c", command, NULL);
1236 g_warning (_("Cannot execute command: %s (using shell %s)\n"), command, shell);
1237 _exit(1);
1239 if (pid < 0)
1240 g_warning (_("Cannot execute command: %s (using shell %s)\n"), command, shell);
1241 g_free (shell);
1242 g_strfreev (term_argv);
1244 // Anjuta will take care of child exit automatically.
1245 return pid;
1248 gchar *
1249 anjuta_util_convert_to_utf8 (const gchar *str)
1251 GError *error = NULL;
1252 gchar *utf8_msg_string = NULL;
1254 g_return_val_if_fail (str != NULL, NULL);
1255 g_return_val_if_fail (strlen (str) > 0, NULL);
1257 if (g_utf8_validate(str, -1, NULL))
1259 utf8_msg_string = g_strdup (str);
1261 else
1263 gsize rbytes, wbytes;
1264 utf8_msg_string = g_locale_to_utf8 (str, -1, &rbytes, &wbytes, &error);
1265 if (error != NULL) {
1266 g_warning ("g_locale_to_utf8 failed: %s\n", error->message);
1267 g_error_free (error);
1268 /* g_free (utf8_msg_string);
1269 return NULL; */
1272 return utf8_msg_string;
1275 #define LEFT_BRACE(ch) (ch == ')'? '(' : (ch == '}'? '{' : (ch == ']'? '[' : ch)))
1277 gboolean
1278 anjuta_util_jump_to_matching_brace (IAnjutaIterable *iter, gchar brace, gint limit)
1280 gchar point_ch = brace;
1281 gint cur_iteration = 0;
1282 gboolean use_limit = (limit > 0);
1283 GString *braces_stack = g_string_new ("");
1285 g_return_val_if_fail (point_ch == ')' || point_ch == ']' ||
1286 point_ch == '}', FALSE);
1288 /* DEBUG_PRINT ("%s", "Matching brace being"); */
1289 /* Push brace */
1290 g_string_prepend_c (braces_stack, point_ch);
1292 while (ianjuta_iterable_previous (iter, NULL))
1294 /* Check limit */
1295 cur_iteration++;
1296 if (use_limit && cur_iteration > limit)
1297 break;
1299 /* Skip comments and strings */
1300 IAnjutaEditorAttribute attrib =
1301 ianjuta_editor_cell_get_attribute (IANJUTA_EDITOR_CELL (iter), NULL);
1302 if (attrib == IANJUTA_EDITOR_COMMENT || attrib == IANJUTA_EDITOR_STRING)
1303 continue;
1305 /* DEBUG_PRINT ("%s", "point ch = %c", point_ch); */
1306 point_ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (iter), 0,
1307 NULL);
1308 if (point_ch == ')' || point_ch == ']' || point_ch == '}')
1310 /* Push brace */
1311 g_string_prepend_c (braces_stack, point_ch);
1312 continue;
1314 if (point_ch == LEFT_BRACE (braces_stack->str[0]))
1316 /* Pop brace */
1317 g_string_erase (braces_stack, 0, 1);
1319 /* Bail out if there is no more in stack */
1320 if (braces_stack->str[0] == '\0')
1322 /* DEBUG_PRINT ("%s", "Matching brace end -- found"); */
1323 return TRUE;
1326 /* DEBUG_PRINT ("%s", "Matching brace end -- not found"); */
1327 return FALSE;
1330 GList*
1331 anjuta_util_parse_args_from_string (const gchar* string)
1333 gboolean escaped;
1334 gchar quote = 0;
1335 gboolean is_quote = FALSE;
1336 gchar* buffer = g_new0(gchar, strlen(string) + 1);
1337 const gchar *s;
1338 gint idx;
1339 GList* args = NULL;
1341 idx = 0;
1342 escaped = FALSE;
1343 s = string;
1345 while (*s) {
1346 if (!isspace(*s))
1347 break;
1348 s++;
1351 while (*s) {
1352 if (escaped) {
1353 /* The current char was escaped */
1354 buffer[idx++] = *s;
1355 escaped = FALSE;
1356 } else if (*s == '\\') {
1357 /* Current char is an escape */
1358 escaped = TRUE;
1359 } else if (is_quote && *s == quote) {
1360 /* Current char ends a quotation */
1361 is_quote = FALSE;
1362 if (!isspace(*(s+1)) && (*(s+1) != '\0')) {
1363 /* If there is no space after the quotation or it is not
1364 the end of the string */
1365 g_warning ("Parse error while parsing program arguments");
1367 } else if ((*s == '\"' || *s == '\'')) {
1368 if (!is_quote) {
1369 /* Current char starts a quotation */
1370 quote = *s;
1371 is_quote = TRUE;
1372 } else {
1373 /* Just a quote char inside quote */
1374 buffer[idx++] = *s;
1376 } else if (is_quote){
1377 /* Any other char inside quote */
1378 buffer[idx++] = *s;
1379 } else if (isspace(*s)) {
1380 /* Any white space outside quote */
1381 if (idx > 0) {
1382 buffer[idx++] = '\0';
1383 args = g_list_append (args, g_strdup (buffer));
1384 idx = 0;
1386 } else {
1387 buffer[idx++] = *s;
1389 s++;
1391 if (idx > 0) {
1392 /* There are chars in the buffer. Flush as the last arg */
1393 buffer[idx++] = '\0';
1394 args = g_list_append (args, g_strdup (buffer));
1395 idx = 0;
1397 if (is_quote) {
1398 g_warning ("Unclosed quotation encountered at the end of parsing");
1400 g_free (buffer);
1401 return args;
1404 gchar*
1405 anjuta_util_escape_quotes(const gchar* str)
1407 gchar *buffer;
1408 gint idx, max_size;
1409 const gchar *s = str;
1411 g_return_val_if_fail(str, NULL);
1412 idx = 0;
1414 /* We are assuming there will be less than 2048 chars to escape */
1415 max_size = strlen(str) + 2048;
1416 buffer = g_new (gchar, max_size);
1417 max_size -= 2;
1419 while(*s) {
1420 if (idx > max_size)
1421 break;
1422 if (*s == '\"' || *s == '\'' || *s == '\\')
1423 buffer[idx++] = '\\';
1424 buffer[idx++] = *s;
1425 s++;
1427 buffer[idx] = '\0';
1428 return buffer;
1431 /* Diff the text contained in uri with text. Return true if files
1432 differ, FALSE if they are identical.*/
1434 gboolean anjuta_util_diff(const gchar* uri, const gchar* text)
1436 GFile *file;
1437 GFileInfo *file_info;
1438 guint64 size;
1439 gchar* file_text = NULL;
1440 gsize bytes_read;
1442 file = g_file_new_for_uri (uri);
1443 file_info = g_file_query_info (file,
1444 G_FILE_ATTRIBUTE_STANDARD_SIZE,
1445 G_FILE_QUERY_INFO_NONE,
1446 NULL,
1447 NULL);
1449 if (file_info == NULL)
1451 g_object_unref (file);
1452 return TRUE;
1455 size = g_file_info_get_attribute_uint64(file_info,
1456 G_FILE_ATTRIBUTE_STANDARD_SIZE);
1457 g_object_unref (file_info);
1459 if (size == 0 && text == NULL)
1461 g_object_unref (file);
1462 return FALSE;
1464 else if (size == 0 || text == NULL)
1466 g_object_unref (file);
1467 return TRUE;
1470 if (!g_file_load_contents(file,
1471 NULL,
1472 &file_text,
1473 &bytes_read,
1474 NULL,
1475 NULL))
1477 g_object_unref (file);
1478 return TRUE;
1480 g_object_unref (file);
1482 if (bytes_read != size)
1484 g_free (file_text);
1485 return TRUE;
1488 /* according to g_file_load_contents's documentation
1489 * file_text is guaranteed to end with \0.
1491 if (strcmp (file_text, text) == 0)
1493 g_free (file_text);
1494 return FALSE;
1497 g_free (file_text);
1498 return TRUE;
1502 * anjuta_util_is_project_file:
1503 * @filename: the file name
1505 * Return TRUE if the file is an anjuta project file. It is implemented by
1506 * checking only the file extension. So it does not check the existence
1507 * of the file. But it is working on an URI if it does not containt a
1508 * fragment.
1510 * Returns: TRUE if the file is a project file, else FALSE
1512 gboolean
1513 anjuta_util_is_project_file (const gchar *filename)
1515 gsize len = strlen (filename);
1516 return ((len > 8) && (strcmp (filename + len - 7, ".anjuta") == 0));
1520 * anjuta_util_is_template_file:
1521 * @filename: the file name
1523 * Return TRUE if the file is an template project file. It is implemented by
1524 * checking only the file extension. So it does not check the existence
1525 * of the file. But it is working on an URI if it does not containt a
1526 * fragment.
1528 * Returns: TRUE if the file is a template file, else FALSE
1530 gboolean
1531 anjuta_util_is_template_file (const gchar *filename)
1533 gsize len = strlen (filename);
1534 return ((len > 9) && (strcmp (filename + len - 8, ".wiz.tgz") == 0));
1538 * anjuta_util_get_file_mine_type:
1539 * @file: the file
1541 * Check if a file exists and return its mime type.
1543 * Returns: NULL if the corresponding file doesn't exist or the mime type as a newly
1544 * allocated string that must be freed with g_free().
1546 gchar *
1547 anjuta_util_get_file_mime_type (GFile *file)
1549 GFileInfo *info;
1550 gchar *mime_type = NULL;
1552 g_return_val_if_fail (file != NULL, NULL);
1554 /* Get file information, check that the file exist at the same time */
1555 info = g_file_query_info (file,
1556 G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
1557 G_FILE_QUERY_INFO_NONE,
1558 NULL,
1559 NULL);
1561 if (info != NULL)
1563 const gchar *extension;
1564 gchar *name;
1566 /* If Anjuta is not installed in system gnome prefix, the mime types
1567 * may not have been correctly registed. In that case, we use the
1568 * following mime detection
1570 name = g_file_get_basename (file);
1571 extension = strrchr(name, '.');
1572 if (extension != NULL)
1574 const static struct {gchar *extension; gchar *type;} anjuta_types[] = {
1575 {"anjuta", "application/x-anjuta"},
1576 {"prj", "application/x-anjuta-old"},
1577 {NULL, NULL}};
1578 gint i;
1580 for (i = 0; anjuta_types[i].extension != NULL; i++)
1582 if (strcmp(extension + 1, anjuta_types[i].extension) == 0)
1584 mime_type = g_strdup (anjuta_types[i].type);
1585 break;
1589 g_free (name);
1591 /* Use mime database if it is not an Anjuta type */
1592 if (mime_type == NULL)
1594 mime_type = g_content_type_get_mime_type (g_file_info_get_content_type(info));
1597 g_object_unref (info);
1600 return mime_type;
1603 gchar *
1604 anjuta_util_get_local_path_from_uri (const gchar *uri)
1606 GFile *file;
1607 gchar *local_path;
1609 file = g_file_new_for_uri (uri);
1610 local_path = g_file_get_path (file);
1611 g_object_unref (file);
1613 return local_path;
1616 #ifdef EMULATE_FORKPTY
1617 #include <grp.h>
1619 static int ptym_open (char *pts_name);
1620 static int ptys_open (int fdm, char * pts_name);
1623 login_tty(int ttyfd)
1625 int fd;
1626 char *fdname;
1628 #ifdef HAVE_SETSID
1629 setsid();
1630 #endif
1631 #ifdef HAVE_SETPGID
1632 setpgid(0, 0);
1633 #endif
1635 /* First disconnect from the old controlling tty. */
1636 #ifdef TIOCNOTTY
1637 fd = open("/dev/tty", O_RDWR|O_NOCTTY);
1638 if (fd >= 0)
1640 ioctl(fd, TIOCNOTTY, NULL);
1641 close(fd);
1643 else
1644 //syslog(LOG_WARNING, "NO CTTY");
1645 #endif /* TIOCNOTTY */
1647 /* Verify that we are successfully disconnected from the controlling tty. */
1648 fd = open("/dev/tty", O_RDWR|O_NOCTTY);
1649 if (fd >= 0)
1651 //syslog(LOG_WARNING, "Failed to disconnect from controlling tty.");
1652 close(fd);
1655 /* Make it our controlling tty. */
1656 #ifdef TIOCSCTTY
1657 ioctl(ttyfd, TIOCSCTTY, NULL);
1658 #endif /* TIOCSCTTY */
1660 fdname = ttyname (ttyfd);
1661 fd = open(fdname, O_RDWR);
1662 if (fd < 0)
1663 ;//syslog(LOG_WARNING, "open %s: %s", fdname, strerror(errno));
1664 else
1665 close(fd);
1667 /* Verify that we now have a controlling tty. */
1668 fd = open("/dev/tty", O_WRONLY);
1669 if (fd < 0)
1671 //syslog(LOG_WARNING, "open /dev/tty: %s", strerror(errno));
1672 return 1;
1675 close(fd);
1676 #if defined(HAVE_VHANGUP) && !defined(HAVE_REVOKE)
1678 RETSIGTYPE (*sig)();
1679 sig = signal(SIGHUP, SIG_IGN);
1680 vhangup();
1681 signal(SIGHUP, sig);
1683 #endif
1684 fd = open(fdname, O_RDWR);
1685 if (fd == -1)
1687 //syslog(LOG_ERR, "can't reopen ctty %s: %s", fdname, strerror(errno));
1688 return -1;
1691 close(ttyfd);
1693 if (fd != 0)
1694 close(0);
1695 if (fd != 1)
1696 close(1);
1697 if (fd != 2)
1698 close(2);
1700 dup2(fd, 0);
1701 dup2(fd, 1);
1702 dup2(fd, 2);
1703 if (fd > 2)
1704 close(fd);
1705 return 0;
1709 openpty(int *amaster, int *aslave, char *name, struct termios *termp,
1710 struct winsize *winp)
1712 char line[20];
1713 *amaster = ptym_open(line);
1714 if (*amaster < 0)
1715 return -1;
1716 *aslave = ptys_open(*amaster, line);
1717 if (*aslave < 0) {
1718 close(*amaster);
1719 return -1;
1721 if (name)
1722 strcpy(name, line);
1723 #ifndef TCSAFLUSH
1724 #define TCSAFLUSH TCSETAF
1725 #endif
1726 if (termp)
1727 (void) tcsetattr(*aslave, TCSAFLUSH, termp);
1728 #ifdef TIOCSWINSZ
1729 if (winp)
1730 (void) ioctl(*aslave, TIOCSWINSZ, (char *)winp);
1731 #endif
1732 return 0;
1735 static int
1736 ptym_open(char * pts_name)
1738 int fdm;
1739 #ifdef HAVE_PTSNAME
1740 char *ptr;
1742 strcpy(pts_name, "/dev/ptmx");
1743 fdm = open(pts_name, O_RDWR);
1744 if (fdm < 0)
1745 return -1;
1746 if (grantpt(fdm) < 0) { /* grant access to slave */
1747 close(fdm);
1748 return -2;
1750 if (unlockpt(fdm) < 0) { /* clear slave's lock flag */
1751 close(fdm);
1752 return -3;
1754 ptr = ptsname(fdm);
1755 if (ptr == NULL) { /* get slave's name */
1756 close (fdm);
1757 return -4;
1759 strcpy(pts_name, ptr); /* return name of slave */
1760 return fdm; /* return fd of master */
1761 #else
1762 char *ptr1, *ptr2;
1764 strcpy(pts_name, "/dev/ptyXY");
1765 /* array index: 012345689 (for references in following code) */
1766 for (ptr1 = "pqrstuvwxyzPQRST"; *ptr1 != 0; ptr1++) {
1767 pts_name[8] = *ptr1;
1768 for (ptr2 = "0123456789abcdef"; *ptr2 != 0; ptr2++) {
1769 pts_name[9] = *ptr2;
1770 /* try to open master */
1771 fdm = open(pts_name, O_RDWR);
1772 if (fdm < 0) {
1773 if (errno == ENOENT) /* different from EIO */
1774 return -1; /* out of pty devices */
1775 else
1776 continue; /* try next pty device */
1778 pts_name[5] = 't'; /* chage "pty" to "tty" */
1779 return fdm; /* got it, return fd of master */
1782 return -1; /* out of pty devices */
1783 #endif
1786 static int
1787 ptys_open(int fdm, char * pts_name)
1789 int fds;
1790 #ifdef HAVE_PTSNAME
1791 /* following should allocate controlling terminal */
1792 fds = open(pts_name, O_RDWR);
1793 if (fds < 0) {
1794 close(fdm);
1795 return -5;
1797 if (ioctl(fds, I_PUSH, "ptem") < 0) {
1798 close(fdm);
1799 close(fds);
1800 return -6;
1802 if (ioctl(fds, I_PUSH, "ldterm") < 0) {
1803 close(fdm);
1804 close(fds);
1805 return -7;
1807 if (ioctl(fds, I_PUSH, "ttcompat") < 0) {
1808 close(fdm);
1809 close(fds);
1810 return -8;
1813 if (ioctl(fdm, I_PUSH, "pckt") < 0) {
1814 close(fdm);
1815 close(fds);
1816 return -8;
1819 if (ioctl(fdm, I_SRDOPT, RMSGN|RPROTDAT) < 0) {
1820 close(fdm);
1821 close(fds);
1822 return -8;
1825 return fds;
1826 #else
1827 int gid;
1828 struct group *grptr;
1830 grptr = getgrnam("tty");
1831 if (grptr != NULL)
1832 gid = grptr->gr_gid;
1833 else
1834 gid = -1; /* group tty is not in the group file */
1835 /* following two functions don't work unless we're root */
1836 chown(pts_name, getuid(), gid);
1837 chmod(pts_name, S_IRUSR | S_IWUSR | S_IWGRP);
1838 fds = open(pts_name, O_RDWR);
1839 if (fds < 0) {
1840 close(fdm);
1841 return -1;
1843 return fds;
1844 #endif
1848 forkpty(int *amaster, char *name, struct termios *termp, struct winsize *winp)
1850 int master, slave, pid;
1852 if (openpty(&master, &slave, name, termp, winp) == -1)
1853 return (-1);
1854 switch (pid = fork()) {
1855 case -1:
1856 return (-1);
1857 case 0:
1859 * child
1861 close(master);
1862 login_tty(slave);
1863 return (0);
1866 * parent
1868 *amaster = master;
1869 close(slave);
1870 return (pid);
1873 int scandir(const char *dir, struct dirent ***namelist,
1874 int (*select)(const struct dirent *),
1875 int (*compar)(const struct dirent **, const struct dirent **))
1877 DIR *d;
1878 struct dirent *entry;
1879 register int i=0;
1880 size_t entrysize;
1882 if ((d=opendir(dir)) == NULL)
1883 return(-1);
1885 *namelist=NULL;
1886 while ((entry=readdir(d)) != NULL)
1888 if (select == NULL || (select != NULL && (*select)(entry)))
1890 *namelist=(struct dirent **)realloc((void *)(*namelist),
1891 (size_t)((i+1)*sizeof(struct dirent *)));
1892 if (*namelist == NULL) return(-1);
1893 entrysize=sizeof(struct dirent)-sizeof(entry->d_name)+strlen(entry->d_name)+1;
1894 (*namelist)[i]=(struct dirent *)malloc(entrysize);
1895 if ((*namelist)[i] == NULL) return(-1);
1896 memcpy((*namelist)[i], entry, entrysize);
1897 i++;
1900 if (closedir(d)) return(-1);
1901 if (i == 0) return(-1);
1902 if (compar != NULL)
1903 qsort((void *)(*namelist), (size_t)i, sizeof(struct dirent *), compar);
1905 return(i);
1908 #endif /* EMULATE_FORKPTY */
1910 void
1911 anjuta_util_help_display (GtkWidget *parent,
1912 const gchar *doc_id,
1913 const gchar *item)
1915 GError *error = NULL;
1916 gchar *command;
1919 command = g_strdup_printf ("yelp ghelp:%s%s%s",
1920 doc_id,
1921 item == NULL ? "" : "?",
1922 item == NULL ? "" : item);
1924 if (!g_spawn_command_line_async (command, &error) &&
1925 (error != NULL))
1927 g_warning ("Error executing help application: %s",
1928 error->message);
1929 g_error_free (error);
1931 g_free (command);
1935 /* The following functions are taken from gedit */
1937 /* Note that this function replace home dir with ~ */
1938 gchar *
1939 anjuta_util_uri_get_dirname (const gchar *uri)
1941 gchar *res;
1942 gchar *str;
1944 // CHECK: does it work with uri chaining? - Paolo
1945 str = g_path_get_dirname (uri);
1946 g_return_val_if_fail (str != NULL, ".");
1948 if ((strlen (str) == 1) && (*str == '.'))
1950 g_free (str);
1952 return NULL;
1955 res = anjuta_util_replace_home_dir_with_tilde (str);
1957 g_free (str);
1959 return res;
1962 gchar*
1963 anjuta_util_replace_home_dir_with_tilde (const gchar *uri)
1965 gchar *tmp;
1966 gchar *home;
1968 g_return_val_if_fail (uri != NULL, NULL);
1970 /* Note that g_get_home_dir returns a const string */
1971 tmp = (gchar *)g_get_home_dir ();
1973 if (tmp == NULL)
1974 return g_strdup (uri);
1976 home = g_filename_to_utf8 (tmp, -1, NULL, NULL, NULL);
1977 if (home == NULL)
1978 return g_strdup (uri);
1980 if (strcmp (uri, home) == 0)
1982 g_free (home);
1984 return g_strdup ("~");
1987 tmp = home;
1988 home = g_strdup_printf ("%s/", tmp);
1989 g_free (tmp);
1991 if (g_str_has_prefix (uri, home))
1993 gchar *res;
1995 res = g_strdup_printf ("~/%s", uri + strlen (home));
1997 g_free (home);
1999 return res;
2002 g_free (home);
2004 return g_strdup (uri);
2008 * anjuta_util_shell_expand:
2009 * @string: input string
2011 * Expand environment variables $(var_name) and tilde (~) in the input string.
2013 * Returns: a newly-allocated string that must be freed with g_free().
2015 gchar*
2016 anjuta_util_shell_expand (const gchar *string)
2018 GString* expand;
2020 if (string == NULL) return NULL;
2022 expand = g_string_sized_new (strlen (string));
2024 for (; *string != '\0'; string++)
2026 switch (*string)
2028 case '$':
2030 /* Variable expansion */
2031 const gchar *end;
2032 gint var_name_len;
2034 end = string + 1;
2035 while (isalnum (*end) || (*end == '_')) end++;
2036 var_name_len = end - string - 1;
2037 if (var_name_len > 0)
2039 const gchar *value;
2041 g_string_append_len (expand, string + 1, var_name_len);
2042 value = g_getenv (expand->str + expand->len - var_name_len);
2043 g_string_truncate (expand, expand->len - var_name_len);
2044 g_string_append (expand, value);
2045 string = end - 1;
2046 continue;
2048 break;
2050 case '~':
2052 /* User home directory expansion */
2053 if (isspace(string[1]) || (string[1] == G_DIR_SEPARATOR) || (string[1] == '\0'))
2055 g_string_append (expand, g_get_home_dir());
2056 continue;
2058 break;
2060 default:
2061 break;
2063 g_string_append_c (expand, *string);
2066 return g_string_free (expand, FALSE);
2069 gchar *
2070 anjuta_util_str_middle_truncate (const gchar *string,
2071 guint truncate_length)
2073 GString *truncated;
2074 guint length;
2075 guint n_chars;
2076 guint num_left_chars;
2077 guint right_offset;
2078 guint delimiter_length;
2079 const gchar *delimiter = "\342\200\246";
2081 g_return_val_if_fail (string != NULL, NULL);
2083 length = strlen (string);
2085 g_return_val_if_fail (g_utf8_validate (string, length, NULL), NULL);
2087 /* It doesnt make sense to truncate strings to less than
2088 * the size of the delimiter plus 2 characters (one on each
2089 * side)
2091 delimiter_length = g_utf8_strlen (delimiter, -1);
2092 if (truncate_length < (delimiter_length + 2)) {
2093 return g_strdup (string);
2096 n_chars = g_utf8_strlen (string, length);
2098 /* Make sure the string is not already small enough. */
2099 if (n_chars <= truncate_length) {
2100 return g_strdup (string);
2103 /* Find the 'middle' where the truncation will occur. */
2104 num_left_chars = (truncate_length - delimiter_length) / 2;
2105 right_offset = n_chars - truncate_length + num_left_chars + delimiter_length;
2107 truncated = g_string_new_len (string,
2108 g_utf8_offset_to_pointer (string, num_left_chars) - string);
2109 g_string_append (truncated, delimiter);
2110 g_string_append (truncated, g_utf8_offset_to_pointer (string, right_offset));
2112 return g_string_free (truncated, FALSE);
2116 * Functions to implement XDG Base Directory Specification
2117 * http://standards.freedesktop.org/basedir-spec/latest/index.html
2118 * Use this to save any config/cache/data files
2122 static gchar*
2123 anjuta_util_construct_pathv (const gchar* str, va_list str_list)
2125 GPtrArray *str_arr;
2126 const gchar* tmp_str;
2127 gchar* path;
2129 str_arr = g_ptr_array_new();
2130 g_ptr_array_add (str_arr, (gpointer) str);
2132 /* Extract elements from va_list */
2133 if (str != NULL)
2135 while ((tmp_str = va_arg (str_list, const gchar*)) != NULL)
2137 g_ptr_array_add (str_arr, (gpointer)tmp_str);
2139 va_end (str_list);
2142 /* Terminate the list */
2143 g_ptr_array_add (str_arr, NULL);
2145 path = g_build_filenamev ((gchar **)str_arr->pdata);
2146 g_ptr_array_free (str_arr, TRUE);
2148 return path;
2151 static GFile*
2152 anjuta_util_get_user_cache_filev (const gchar* path, va_list list)
2154 gchar *uri_str, *base_path, *dir;
2155 GFile *uri;
2156 const gchar anjuta_prefix[] = "anjuta";
2157 base_path = g_build_filename (g_get_user_cache_dir(), anjuta_prefix, path, NULL);
2159 uri_str = anjuta_util_construct_pathv (base_path, list);
2160 g_free (base_path);
2162 uri = g_file_new_for_path (uri_str);
2163 dir = g_path_get_dirname (uri_str);
2164 g_free(uri_str);
2165 if (!anjuta_util_create_dir (dir)) return NULL;
2167 return uri;
2170 GFile*
2171 anjuta_util_get_user_cache_file (const gchar* path, ...)
2173 va_list list;
2174 va_start (list, path);
2175 return anjuta_util_get_user_cache_filev (path, list);
2178 static GFile*
2179 anjuta_util_get_user_config_filev (const gchar* path, va_list list)
2181 gchar *uri_str, *base_path, *dir;
2182 GFile *uri;
2183 const gchar anjuta_prefix[] = "anjuta";
2184 base_path = g_build_filename (g_get_user_config_dir(), anjuta_prefix, path, NULL);
2186 uri_str = anjuta_util_construct_pathv (base_path, list);
2187 g_free (base_path);
2189 uri = g_file_new_for_path (uri_str);
2190 dir = g_path_get_dirname (uri_str);
2191 g_free(uri_str);
2192 if (!anjuta_util_create_dir (dir)) return NULL;
2194 return uri;
2197 GFile*
2198 anjuta_util_get_user_config_file (const gchar* path, ...)
2200 va_list list;
2201 va_start (list, path);
2202 return anjuta_util_get_user_config_filev (path, list);
2205 static GFile*
2206 anjuta_util_get_user_data_filev (const gchar* path, va_list list)
2208 gchar *uri_str, *base_path, *dir;
2209 GFile *uri;
2210 const gchar anjuta_prefix[] = "anjuta";
2211 base_path = g_build_filename (g_get_user_data_dir(), anjuta_prefix, path, NULL);
2213 uri_str = anjuta_util_construct_pathv (base_path, list);
2214 g_free (base_path);
2216 uri = g_file_new_for_path (uri_str);
2217 dir = g_path_get_dirname (uri_str);
2218 g_free(uri_str);
2219 if (!anjuta_util_create_dir (dir)) return NULL;
2221 return uri;
2224 GFile*
2225 anjuta_util_get_user_data_file (const gchar* path, ...)
2227 va_list list;
2228 va_start (list, path);
2229 return anjuta_util_get_user_data_filev (path, list);
2232 gchar*
2233 anjuta_util_get_user_cache_file_path (const gchar* path, ...)
2235 va_list list;
2236 GFile *file;
2237 gchar *file_path;
2238 va_start (list, path);
2239 file = anjuta_util_get_user_cache_filev (path, list);
2240 file_path = g_file_get_path (file);
2241 g_object_unref (file);
2243 return file_path;
2246 gchar*
2247 anjuta_util_get_user_config_file_path (const gchar* path, ...)
2249 va_list list;
2250 GFile *file;
2251 gchar *file_path;
2252 va_start (list, path);
2253 file = anjuta_util_get_user_config_filev (path, list);
2254 file_path = g_file_get_path (file);
2255 g_object_unref (file);
2257 return file_path;
2260 gchar*
2261 anjuta_util_get_user_data_file_path (const gchar* path, ...)
2263 va_list list;
2264 GFile *file;
2265 gchar *file_path;;
2266 va_start (list, path);
2267 file = anjuta_util_get_user_data_filev (path, list);
2268 file_path = g_file_get_path (file);
2269 g_object_unref (file);
2271 return file_path;
2274 GList *
2275 anjuta_util_convert_gfile_list_to_path_list (GList *list)
2277 GList *path_list;
2278 GList *current_file;
2279 gchar *path;
2281 path_list = NULL;
2283 for (current_file = list; current_file != NULL; current_file = g_list_next (current_file))
2285 path = g_file_get_path (current_file->data);
2287 /* Ignore files with invalid paths */
2288 if (path)
2289 path_list = g_list_append (path_list, path);
2292 return path_list;
2295 GList *
2296 anjuta_util_convert_gfile_list_to_relative_path_list (GList *list,
2297 const gchar *parent)
2299 GFile *parent_file;
2300 GList *path_list;
2301 GList *current_file;
2302 gchar *path;
2304 parent_file = g_file_new_for_path (parent);
2305 path_list = NULL;
2307 if (parent_file)
2309 for (current_file = list; current_file != NULL; current_file = g_list_next (current_file))
2311 path = g_file_get_relative_path (parent_file, current_file->data);
2313 /* Ignore files with invalid paths */
2314 if (path)
2315 path_list = g_list_append (path_list, path);
2318 g_object_unref (parent_file);
2321 return path_list;
2326 * anjuta_util_builder_new:
2327 * @filename: Builder file name to open
2328 * @error: Optional error object, if NULL display a dialog if the file is missing
2330 * Create a new GtkBuilder object and load the file in it. Display an error
2331 * if the file is missing. Use a dialog if error is NULL, just a warning
2332 * if the error can be reported.
2334 * Returns: The new GtkBuilder object
2336 GtkBuilder *
2337 anjuta_util_builder_new (const gchar *filename, GError **error)
2339 GtkBuilder *bxml = gtk_builder_new ();
2340 GError *err = NULL;
2342 /* Load glade file */
2343 if (!gtk_builder_add_from_file (bxml, filename, &err))
2345 g_object_unref (bxml);
2346 bxml = NULL;
2348 /* Display the error to the user if it cannot be reported to the caller */
2349 if (error == NULL)
2351 anjuta_util_dialog_error (NULL, _("Unable to load user interface file: %s"), err->message);
2353 else
2355 g_warning ("Couldn't load builder file: %s", err->message);
2357 g_propagate_error (error, err);
2360 /* Tag the builder object with the filename to allow better error message
2361 * with the following function */
2362 if (bxml != NULL)
2364 g_object_set_data_full (G_OBJECT (bxml), "filename", g_strdup (filename), g_free);
2367 return bxml;
2371 * anjuta_util_builder_get_objects:
2372 * @builder: Builder object
2373 * @first_widget: Name of first widget to get
2374 * ...: Address to store the first widget pointer, followed optionally by
2375 * more name/pointer pairs, followed by NULL
2377 * Create a new GtkBuilder object and load the file in it. Display an error
2378 * if the file is missing. Use a dialog if error is NULL, just a warning
2379 * if the error can be reported.
2381 * Returns: TRUE is everything works as expected.
2383 gboolean
2384 anjuta_util_builder_get_objects (GtkBuilder *builder, const gchar *first_widget,...)
2386 va_list args;
2387 const gchar *name;
2388 GObject **object_ptr;
2389 gboolean missing = FALSE;
2391 va_start (args, first_widget);
2393 for (name = first_widget; name; name = va_arg (args, char *))
2395 object_ptr = va_arg (args, void *);
2396 *object_ptr = gtk_builder_get_object (builder, name);
2398 /* Object not found, display a warning */
2399 if (!*object_ptr)
2401 const gchar *filename = (const gchar *)g_object_get_data (G_OBJECT (builder), "filename");
2402 if (filename)
2404 g_warning ("Missing widget '%s' in file %s", name, filename);
2406 else
2408 g_warning("Missing widget '%s'", name);
2410 missing = TRUE;
2413 va_end (args);
2415 return !missing;
2419 * anjuta_utils_drop_get_files:
2420 * @selection_data: the #GtkSelectionData from drag_data_received
2422 * Create a list of valid uri's from a uri-list drop.
2424 * Return value: (element-type GFile*): a list of GFiles
2426 GSList*
2427 anjuta_utils_drop_get_files (GtkSelectionData *selection_data)
2429 gchar **uris;
2430 gint i;
2431 GSList* files = NULL;
2433 uris = g_uri_list_extract_uris ((gchar *) gtk_selection_data_get_data (selection_data));
2435 for (i = 0; uris[i] != NULL; i++)
2437 GFile* file = g_file_new_for_uri (uris[i]);
2438 files = g_slist_append(files, file);
2441 return files;
2445 * anjuta_util_get_user_mail:
2447 * Returns: The e-mail Address of the logged-in user. The resulting string
2448 * must be free'd after use.
2450 gchar*
2451 anjuta_util_get_user_mail()
2453 /* FIXME: Use libfolks or something like it to query the mail address */
2454 return g_strconcat(g_get_user_name (), "@", g_get_host_name (), NULL);
2458 * anjuta_utils_clone_string_gptrarray:
2459 * @source: The source GPtrArray containing items representing strings
2461 * Clones the contents of source GPtrArray into a new allocated GPtrArray.
2463 * Return a new allocated GPtrArray with strings g_strdup (), NULL on error.
2464 * The returned array has set g_free as GDestroyNotity function, so that user
2465 * should only care to g_ptr_array_unref () without freeing the strings.
2467 GPtrArray *
2468 anjuta_util_clone_string_gptrarray (const GPtrArray* source)
2470 gint i;
2471 GPtrArray *dest;
2473 g_return_val_if_fail (source != NULL, NULL);
2475 dest = g_ptr_array_sized_new (source->len);
2476 g_ptr_array_set_free_func (dest, g_free);
2478 for (i = 0; i < source->len; i++)
2480 g_ptr_array_add (dest, g_strdup (g_ptr_array_index (source, i)));
2483 return dest;
2486 void
2487 anjuta_util_list_all_dir_children (GList **children, GFile *dir)
2489 GFileEnumerator *list;
2491 list = g_file_enumerate_children (dir,
2492 G_FILE_ATTRIBUTE_STANDARD_NAME,
2493 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
2494 NULL,
2495 NULL);
2497 if (list != NULL)
2499 GFileInfo *info;
2501 while ((info = g_file_enumerator_next_file (list, NULL, NULL)) != NULL)
2503 const gchar *name;
2504 GFile *file;
2506 name = g_file_info_get_name (info);
2507 file = g_file_get_child (dir, name);
2508 g_object_unref (info);
2510 if (g_file_query_file_type (file, G_FILE_QUERY_INFO_NONE, NULL) == G_FILE_TYPE_DIRECTORY)
2512 anjuta_util_list_all_dir_children (children, file);
2513 g_object_unref (file);
2515 else
2517 *children = g_list_prepend (*children, file);
2520 g_file_enumerator_close (list, NULL, NULL);
2521 g_object_unref (list);
2525 GPtrArray *
2526 anjuta_util_convert_string_list_to_array (GList *list)
2528 GList *node;
2529 GPtrArray *res;
2531 g_return_val_if_fail (list != NULL, NULL);
2533 res = g_ptr_array_new_with_free_func (g_free);
2535 node = list;
2536 while (node != NULL)
2538 g_ptr_array_add (res, g_strdup (node->data));
2540 node = g_list_next (node);
2543 return res;