Fix search/replace mistakes...AnjutaSyncCommand should compile now.
[anjuta-git-plugin.git] / libanjuta / anjuta-utils.c
blob55e0c3b6a1c60f2d112f92833b098f7f4f8d523a
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 * anjuta-utils.c
4 * Copyright (C) Naba Kumar <naba@gnome.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 /**
22 * SECTION:anjuta-utils
23 * @title: Utilities
24 * @short_description: Utility functions
25 * @see_also:
26 * @stability: Unstable
27 * @include: libanjuta/anjuta-utils.h
31 #ifdef HAVE_CONFIG_H
32 # include <config.h>
33 #endif
35 #include <errno.h>
36 #include <ctype.h>
37 #include <limits.h>
38 #include <stdlib.h>
39 #include <sys/stat.h>
40 #include <sys/types.h>
41 #include <sys/fcntl.h>
42 #include <sys/termios.h>
43 #include <dirent.h>
44 #include <unistd.h>
45 #include <stdio.h>
46 #include <string.h>
48 #include <glib/gi18n.h>
49 #include <glib.h>
51 #include <libgnome/gnome-util.h>
53 #include <libanjuta/anjuta-utils.h>
54 #include <libanjuta/anjuta-debug.h>
56 #include <libgnomevfs/gnome-vfs.h>
58 #define FILE_BUFFER_SIZE 1024
60 gboolean
61 anjuta_util_copy_file (gchar * src, gchar * dest, gboolean show_error)
63 FILE *input_fp, *output_fp;
64 gchar buffer[FILE_BUFFER_SIZE];
65 gint bytes_read, bytes_written;
66 gboolean error;
68 error = TRUE;
70 input_fp = fopen (src, "rb");
71 if (input_fp == NULL)
73 if( show_error)
74 anjuta_util_dialog_error_system (NULL, errno,
75 _("Unable to read file: %s."),
76 src);
77 return FALSE;
80 output_fp = fopen (dest, "wb");
81 if (output_fp == NULL)
83 if( show_error)
84 anjuta_util_dialog_error_system (NULL, errno,
85 _("Unable to create file: %s."),
86 dest);
87 fclose (input_fp);
88 return TRUE;
91 for (;;)
93 bytes_read = fread (buffer, 1, FILE_BUFFER_SIZE, input_fp);
94 if (bytes_read != FILE_BUFFER_SIZE && ferror (input_fp))
96 error = FALSE;
97 break;
100 if (bytes_read)
102 bytes_written = fwrite (buffer, 1, bytes_read, output_fp);
103 if (bytes_read != bytes_written)
105 error = FALSE;
106 break;
110 if (bytes_read != FILE_BUFFER_SIZE && feof (input_fp))
112 break;
116 fclose (input_fp);
117 fclose (output_fp);
119 if( show_error && (error == FALSE))
120 anjuta_util_dialog_error_system (NULL, errno,
121 _("Unable to complete file copy"));
122 return error;
125 void
126 anjuta_util_color_from_string (const gchar * val, guint16 * r, guint16 * g, guint16 * b)
128 GdkColor color;
129 if (gdk_color_parse(val, &color))
131 *r = color.red;
132 *g = color.green;
133 *b =color.blue;
137 gchar *
138 anjuta_util_string_from_color (guint16 r, guint16 g, guint16 b)
140 return g_strdup_printf("#%02x%02x%02x", r >> 8, g >> 8, b >> 8);
143 /* Get a GdkColor from preferences. Free the color with gdk_color_free() */
144 GdkColor*
145 anjuta_util_convert_color(AnjutaPreferences* prefs, const gchar* pref_name)
147 GdkColor* color = g_new0(GdkColor, 1);
148 gchar* color_string = anjuta_preferences_get(prefs, pref_name);
149 gdk_color_parse(color_string, color);
150 return color;
153 GtkWidget*
154 anjuta_util_button_new_with_stock_image (const gchar* text,
155 const gchar* stock_id)
157 GtkWidget *button;
158 GtkStockItem item;
159 GtkWidget *label;
160 GtkWidget *image;
161 GtkWidget *hbox;
162 GtkWidget *align;
164 button = gtk_button_new ();
166 if (GTK_BIN (button)->child)
167 gtk_container_remove (GTK_CONTAINER (button),
168 GTK_BIN (button)->child);
170 if (gtk_stock_lookup (stock_id, &item))
172 label = gtk_label_new_with_mnemonic (text);
174 gtk_label_set_mnemonic_widget (GTK_LABEL (label), GTK_WIDGET (button));
176 image = gtk_image_new_from_stock (stock_id, GTK_ICON_SIZE_BUTTON);
177 hbox = gtk_hbox_new (FALSE, 2);
179 align = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
181 gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
182 gtk_box_pack_end (GTK_BOX (hbox), label, FALSE, FALSE, 0);
184 gtk_container_add (GTK_CONTAINER (button), align);
185 gtk_container_add (GTK_CONTAINER (align), hbox);
186 gtk_widget_show_all (align);
188 return button;
191 label = gtk_label_new_with_mnemonic (text);
192 gtk_label_set_mnemonic_widget (GTK_LABEL (label), GTK_WIDGET (button));
194 gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5);
196 gtk_widget_show (label);
197 gtk_container_add (GTK_CONTAINER (button), label);
199 return button;
202 GtkWidget*
203 anjuta_util_dialog_add_button (GtkDialog *dialog, const gchar* text,
204 const gchar* stock_id, gint response_id)
206 GtkWidget *button;
208 g_return_val_if_fail (GTK_IS_DIALOG (dialog), NULL);
209 g_return_val_if_fail (text != NULL, NULL);
210 g_return_val_if_fail (stock_id != NULL, NULL);
212 button = anjuta_util_button_new_with_stock_image (text, stock_id);
213 g_return_val_if_fail (button != NULL, NULL);
215 GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
217 gtk_widget_show (button);
219 gtk_dialog_add_action_widget (dialog, button, response_id);
221 return button;
224 void
225 anjuta_util_dialog_error (GtkWindow *parent, const gchar *mesg, ...)
227 gchar* message;
228 va_list args;
229 GtkWidget *dialog;
230 GtkWindow *real_parent;
232 va_start (args, mesg);
233 message = g_strdup_vprintf (mesg, args);
234 va_end (args);
236 if (parent && GTK_IS_WINDOW (parent))
238 real_parent = parent;
240 else
242 real_parent = NULL;
245 // Dialog to be HIG compliant
246 dialog = gtk_message_dialog_new (real_parent,
247 GTK_DIALOG_DESTROY_WITH_PARENT,
248 GTK_MESSAGE_ERROR,
249 GTK_BUTTONS_CLOSE, message);
250 g_signal_connect (G_OBJECT (dialog), "response",
251 G_CALLBACK (gtk_widget_destroy), NULL);
252 gtk_widget_show (dialog);
253 g_free (message);
256 void
257 anjuta_util_dialog_warning (GtkWindow *parent, const gchar * mesg, ...)
259 gchar* message;
260 va_list args;
261 GtkWidget *dialog;
262 GtkWindow *real_parent;
264 va_start (args, mesg);
265 message = g_strdup_vprintf (mesg, args);
266 va_end (args);
268 if (parent && GTK_IS_WINDOW (parent))
270 real_parent = parent;
272 else
274 real_parent = NULL;
277 // Dialog to be HIG compliant
278 dialog = gtk_message_dialog_new (real_parent,
279 GTK_DIALOG_DESTROY_WITH_PARENT,
280 GTK_MESSAGE_WARNING,
281 GTK_BUTTONS_CLOSE, message);
282 g_signal_connect (G_OBJECT (dialog), "response",
283 G_CALLBACK (gtk_widget_destroy), NULL);
284 gtk_widget_show (dialog);
285 g_free (message);
288 void
289 anjuta_util_dialog_info (GtkWindow *parent, const gchar * mesg, ...)
291 gchar* message;
292 va_list args;
293 GtkWidget *dialog;
294 GtkWindow *real_parent;
296 va_start (args, mesg);
297 message = g_strdup_vprintf (mesg, args);
298 va_end (args);
300 if (parent && GTK_IS_WINDOW (parent))
302 real_parent = parent;
304 else
306 real_parent = NULL;
308 // Dialog to be HIG compliant
309 dialog = gtk_message_dialog_new (real_parent,
310 GTK_DIALOG_DESTROY_WITH_PARENT,
311 GTK_MESSAGE_INFO,
312 GTK_BUTTONS_CLOSE, message);
313 g_signal_connect (G_OBJECT (dialog), "response",
314 G_CALLBACK (gtk_widget_destroy), NULL);
315 gtk_widget_show (dialog);
316 g_free (message);
319 void
320 anjuta_util_dialog_error_system (GtkWindow* parent, gint errnum,
321 const gchar * mesg, ... )
323 gchar* message;
324 gchar* tot_mesg;
325 va_list args;
326 GtkWidget *dialog;
327 GtkWindow *real_parent;
329 va_start (args, mesg);
330 message = g_strdup_vprintf (mesg, args);
331 va_end (args);
333 if (0 != errnum) {
334 tot_mesg = g_strconcat (message, _("\nSystem: "),
335 g_strerror(errnum), NULL);
336 g_free (message);
337 } else
338 tot_mesg = message;
340 if (parent && GTK_IS_WINDOW (parent))
342 real_parent = parent;
344 else
346 real_parent = NULL;
348 // Dialog to be HIG compliant
349 dialog = gtk_message_dialog_new (real_parent,
350 GTK_DIALOG_DESTROY_WITH_PARENT,
351 GTK_MESSAGE_ERROR,
352 GTK_BUTTONS_CLOSE, tot_mesg);
353 g_signal_connect (G_OBJECT (dialog), "response",
354 G_CALLBACK (gtk_widget_destroy), NULL);
355 gtk_widget_show (dialog);
356 g_free (tot_mesg);
359 gboolean
360 anjuta_util_dialog_boolean_question (GtkWindow *parent, const gchar *mesg, ...)
362 gchar* message;
363 va_list args;
364 GtkWidget *dialog;
365 gint ret;
366 GtkWindow *real_parent;
368 va_start (args, mesg);
369 message = g_strdup_vprintf (mesg, args);
370 va_end (args);
372 if (parent && GTK_IS_WINDOW (parent))
374 real_parent = parent;
376 else
378 real_parent = NULL;
381 dialog = gtk_message_dialog_new (real_parent,
382 GTK_DIALOG_DESTROY_WITH_PARENT,
383 GTK_MESSAGE_QUESTION,
384 GTK_BUTTONS_YES_NO, message);
386 ret = gtk_dialog_run (GTK_DIALOG (dialog));
387 gtk_widget_destroy (dialog);
388 g_free (message);
390 return (ret == GTK_RESPONSE_YES);
393 gboolean
394 anjuta_util_dialog_input (GtkWindow *parent, const gchar *prompt,
395 const gchar *default_value, gchar **return_value)
397 GtkWidget *dialog, *label, *frame, *entry, *dialog_vbox, *vbox;
398 gint res;
399 gchar *markup;
400 GtkWindow *real_parent;
402 if (parent && GTK_IS_WINDOW (parent))
404 real_parent = parent;
406 else
408 real_parent = NULL;
411 dialog = gtk_dialog_new_with_buttons (prompt, real_parent,
412 GTK_DIALOG_DESTROY_WITH_PARENT,
413 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
414 GTK_STOCK_OK, GTK_RESPONSE_OK,
415 NULL);
416 gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
417 dialog_vbox = GTK_DIALOG (dialog)->vbox;
418 gtk_window_set_default_size (GTK_WINDOW (dialog), 400, -1);
419 gtk_widget_show (dialog_vbox);
421 markup = g_strconcat ("<b>", prompt, "</b>", NULL);
422 label = gtk_label_new (NULL);
423 gtk_label_set_markup (GTK_LABEL (label), markup);
424 gtk_widget_show (label);
425 g_free (markup);
427 frame = gtk_frame_new (NULL);
428 gtk_frame_set_label_widget (GTK_FRAME (frame), label);
429 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
430 gtk_container_set_border_width (GTK_CONTAINER (frame), 10);
431 gtk_widget_show (frame);
432 gtk_box_pack_start (GTK_BOX (dialog_vbox), frame, FALSE, FALSE, 0);
434 vbox = gtk_vbox_new (FALSE, 0);
435 gtk_widget_show (vbox);
436 gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
437 gtk_container_add (GTK_CONTAINER (frame), vbox);
439 entry = gtk_entry_new ();
440 gtk_widget_show (entry);
441 gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
442 gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
443 if (default_value)
444 gtk_entry_set_text (GTK_ENTRY (entry), default_value);
446 res = gtk_dialog_run (GTK_DIALOG (dialog));
448 if (gtk_entry_get_text (GTK_ENTRY (entry)) &&
449 strlen (gtk_entry_get_text (GTK_ENTRY (entry))) > 0)
451 *return_value = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
453 else
455 *return_value = NULL;
457 gtk_widget_destroy (dialog);
458 return (res == GTK_RESPONSE_OK);
461 gboolean
462 anjuta_util_prog_is_installed (gchar * prog, gboolean show)
464 gchar* prog_path = g_find_program_in_path (prog);
465 if (prog_path)
467 g_free (prog_path);
468 return TRUE;
470 if (show)
472 anjuta_util_dialog_error (NULL, _("The \"%s\" utility is not installed.\n"
473 "Please install it."), prog);
475 return FALSE;
478 gchar *
479 anjuta_util_get_a_tmp_file (void)
481 static gint count = 0;
482 gchar *filename;
483 const gchar *tmpdir;
485 tmpdir = g_get_tmp_dir ();
486 filename =
487 g_strdup_printf ("%s/anjuta_%d.%d", tmpdir, count++, getpid ());
488 return filename;
491 /* GList of strings operations */
492 GList *
493 anjuta_util_glist_from_string (const gchar *string)
495 gchar *str, *temp, buff[256];
496 GList *list;
497 gchar *word_start, *word_end;
498 gboolean the_end;
500 list = NULL;
501 the_end = FALSE;
502 temp = g_strdup (string);
503 str = temp;
504 if (!str)
505 return NULL;
507 while (1)
509 gint i;
510 gchar *ptr;
512 /* Remove leading spaces */
513 while (isspace (*str) && *str != '\0')
514 str++;
515 if (*str == '\0')
516 break;
518 /* Find start and end of word */
519 word_start = str;
520 while (!isspace (*str) && *str != '\0')
521 str++;
522 word_end = str;
524 /* Copy the word into the buffer */
525 for (ptr = word_start, i = 0; ptr < word_end; ptr++, i++)
526 buff[i] = *ptr;
527 buff[i] = '\0';
528 if (strlen (buff))
529 list = g_list_append (list, g_strdup (buff));
530 if (*str == '\0')
531 break;
533 if (temp)
534 g_free (temp);
535 return list;
538 /* Prefix the strings */
539 void
540 anjuta_util_glist_strings_prefix (GList * list, const gchar *prefix)
542 GList *node;
543 node = list;
545 g_return_if_fail (prefix != NULL);
546 while (node)
548 gchar* tmp;
549 tmp = node->data;
550 node->data = g_strconcat (prefix, tmp, NULL);
551 if (tmp) g_free (tmp);
552 node = g_list_next (node);
556 /* Suffix the strings */
557 void
558 anjuta_util_glist_strings_sufix (GList * list, const gchar *sufix)
560 GList *node;
561 node = list;
563 g_return_if_fail (sufix != NULL);
564 while (node)
566 gchar* tmp;
567 tmp = node->data;
568 node->data = g_strconcat (tmp, sufix, NULL);
569 if (tmp) g_free (tmp);
570 node = g_list_next (node);
574 /* Duplicate list of strings */
575 GList*
576 anjuta_util_glist_strings_dup (GList * list)
578 GList *node;
579 GList *new_list;
581 new_list = NULL;
582 node = list;
583 while (node)
585 if (node->data)
586 new_list = g_list_append (new_list, g_strdup(node->data));
587 else
588 new_list = g_list_append (new_list, NULL);
589 node = g_list_next (node);
591 return new_list;
594 gchar*
595 anjuta_util_get_real_path (const gchar *path)
597 if (path != NULL)
599 gchar *result;
600 #ifdef PATH_MAX
601 gchar buf[PATH_MAX+1];
603 result = realpath (path, buf);
604 if (result != NULL)
606 *(buf + PATH_MAX) = '\0'; /* ensure a terminator */
607 return g_strdup (buf);
609 #else
610 char *buf;
611 /* the string returned by realpath should be cleaned with
612 free(), not g_free() */
613 buf = realpath (path, NULL);
614 if (buf != NULL)
616 result = g_strdup (buf);
617 free (buf);
618 return result;
620 #endif
622 return NULL;
625 /* Dedup a list of paths - duplicates are removed from the tail.
626 ** Useful for deduping Recent Files and Recent Projects */
627 GList*
628 anjuta_util_glist_path_dedup(GList *list)
630 GList *nlist = NULL, *tmp, *tmp1;
631 gchar *path;
632 struct stat s;
633 for (tmp = list; tmp; tmp = g_list_next(tmp))
635 path = anjuta_util_get_real_path ((const gchar *) tmp->data);
636 if (path)
638 if (stat (path, &s) != 0)
640 g_free(path);
642 else
644 for (tmp1 = nlist; tmp1; tmp1 = g_list_next(tmp1))
646 if (0 == strcmp((const char *) tmp1->data, path))
648 g_free(path);
649 path = NULL;
650 break;
653 if (path)
654 nlist = g_list_prepend(nlist, path);
658 anjuta_util_glist_strings_free(list);
659 nlist = g_list_reverse(nlist);
660 return nlist;
663 static gint
664 sort_node (gchar* a, gchar *b)
666 if ( !a && !b) return 0;
667 else if (!a) return -1;
668 else if (!b) return 1;
669 return strcmp (a, b);
672 /* Sort the list alphabatically */
673 GList*
674 anjuta_util_glist_strings_sort (GList * list)
676 return g_list_sort(list, (GCompareFunc)sort_node);
679 /* Free the strings and GList */
680 void
681 anjuta_util_glist_strings_free (GList * list)
683 GList *node;
684 node = list;
685 while (node)
687 if (node->data)
688 g_free (node->data);
689 node = g_list_next (node);
691 g_list_free (list);
695 anjuta_util_type_from_string (AnjutaUtilStringMap *map, const char *str)
697 int i = 0;
699 while (-1 != map[i].type)
701 if (0 == strcmp(map[i].name, str))
702 return map[i].type;
703 ++ i;
705 return -1;
708 const char*
709 anjuta_util_string_from_type (AnjutaUtilStringMap *map, int type)
711 int i = 0;
712 while (-1 != map[i].type)
714 if (map[i].type == type)
715 return map[i].name;
716 ++ i;
718 return "";
721 GList*
722 anjuta_util_glist_from_map (AnjutaUtilStringMap *map)
724 GList *out_list = NULL;
725 int i = 0;
726 while (-1 != map[i].type)
728 out_list = g_list_append(out_list, map[i].name);
729 ++ i;
731 return out_list;
735 GList *
736 anjuta_util_update_string_list (GList *p_list, const gchar *p_str, gint length)
738 gint i;
739 gchar *str;
740 if (!p_str)
741 return p_list;
742 for (i = 0; i < g_list_length (p_list); i++)
744 str = (gchar *) g_list_nth_data (p_list, i);
745 if (!str)
746 continue;
747 if (strcmp (p_str, str) == 0)
749 p_list = g_list_remove (p_list, str);
750 p_list = g_list_prepend (p_list, str);
751 return p_list;
754 p_list = g_list_prepend (p_list, g_strdup (p_str));
755 while (g_list_length (p_list) > length)
757 str = g_list_nth_data (p_list, g_list_length (p_list) - 1);
758 p_list = g_list_remove (p_list, str);
759 g_free (str);
761 return p_list;
764 gboolean
765 anjuta_util_create_dir (const gchar * d)
767 if (g_file_test (d, G_FILE_TEST_IS_DIR))
768 return TRUE;
769 if (mkdir (d, 0755))
770 return FALSE;
771 return TRUE;
774 pid_t
775 anjuta_util_execute_shell (const gchar *dir, const gchar *command)
777 pid_t pid;
778 gchar *shell;
780 g_return_val_if_fail (command != NULL, -1);
782 shell = gnome_util_user_shell ();
783 pid = fork();
784 if (pid == 0)
786 if(dir)
788 anjuta_util_create_dir (dir);
789 chdir (dir);
791 execlp (shell, shell, "-c", command, NULL);
792 g_warning (_("Cannot execute command: %s (using shell %s)\n"), command, shell);
793 _exit(1);
795 if (pid < 0)
796 g_warning (_("Cannot execute command: %s (using shell %s)\n"), command, shell);
797 g_free (shell);
798 // Anjuta will take care of child exit automatically.
799 return pid;
802 gchar *
803 anjuta_util_convert_to_utf8 (const gchar *str)
805 GError *error = NULL;
806 gchar *utf8_msg_string = NULL;
808 g_return_val_if_fail (str != NULL, NULL);
809 g_return_val_if_fail (strlen (str) > 0, NULL);
811 if (g_utf8_validate(str, -1, NULL))
813 utf8_msg_string = g_strdup (str);
815 else
817 gsize rbytes, wbytes;
818 utf8_msg_string = g_locale_to_utf8 (str, -1, &rbytes, &wbytes, &error);
819 if (error != NULL) {
820 g_warning ("g_locale_to_utf8 failed: %s\n", error->message);
821 g_error_free (error);
822 /* g_free (utf8_msg_string);
823 return NULL; */
826 return utf8_msg_string;
829 GList*
830 anjuta_util_parse_args_from_string (const gchar* string)
832 gboolean escaped;
833 gchar quote = 0;
834 gboolean is_quote = FALSE;
835 gchar* buffer = g_new0(gchar, strlen(string) + 1);
836 const gchar *s;
837 gint idx;
838 GList* args = NULL;
840 idx = 0;
841 escaped = FALSE;
842 s = string;
844 while (*s) {
845 if (!isspace(*s))
846 break;
847 s++;
850 while (*s) {
851 if (escaped) {
852 /* The current char was escaped */
853 buffer[idx++] = *s;
854 escaped = FALSE;
855 } else if (*s == '\\') {
856 /* Current char is an escape */
857 escaped = TRUE;
858 } else if (is_quote && *s == quote) {
859 /* Current char ends a quotation */
860 is_quote = FALSE;
861 if (!isspace(*(s+1)) && (*(s+1) != '\0')) {
862 /* If there is no space after the quotation or it is not
863 the end of the string */
864 g_warning ("Parse error while parsing program arguments");
866 } else if ((*s == '\"' || *s == '\'')) {
867 if (!is_quote) {
868 /* Current char starts a quotation */
869 quote = *s;
870 is_quote = TRUE;
871 } else {
872 /* Just a quote char inside quote */
873 buffer[idx++] = *s;
875 } else if (is_quote){
876 /* Any other char inside quote */
877 buffer[idx++] = *s;
878 } else if (isspace(*s)) {
879 /* Any white space outside quote */
880 if (idx > 0) {
881 buffer[idx++] = '\0';
882 args = g_list_append (args, g_strdup (buffer));
883 idx = 0;
885 } else {
886 buffer[idx++] = *s;
888 s++;
890 if (idx > 0) {
891 /* There are chars in the buffer. Flush as the last arg */
892 buffer[idx++] = '\0';
893 args = g_list_append (args, g_strdup (buffer));
894 idx = 0;
896 if (is_quote) {
897 g_warning ("Unclosed quotation encountered at the end of parsing");
899 return args;
902 gchar*
903 anjuta_util_escape_quotes(const gchar* str)
905 gchar *buffer;
906 gint idx, max_size;
907 const gchar *s = str;
909 g_return_val_if_fail(str, NULL);
910 idx = 0;
912 /* We are assuming there will be less than 2048 chars to escape */
913 max_size = strlen(str) + 2048;
914 buffer = g_new (gchar, max_size);
915 max_size -= 2;
917 while(*s) {
918 if (idx > max_size)
919 break;
920 if (*s == '\"' || *s == '\'' || *s == '\\')
921 buffer[idx++] = '\\';
922 buffer[idx++] = *s;
923 s++;
925 buffer[idx] = '\0';
926 return buffer;
929 /* Diff the text contained in uri with text. Return true if files
930 differ, FALSE if they are identical.
931 FIXME: Find a better algorithm, this seems ineffective */
933 gboolean anjuta_util_diff(const gchar* uri, const gchar* text)
935 GnomeVFSFileSize bytes_read;
936 gchar* file_text;
937 GnomeVFSFileInfo info;
938 GnomeVFSHandle* handle = NULL;
940 gnome_vfs_get_file_info(uri, &info, GNOME_VFS_FILE_INFO_DEFAULT);
942 if (info.size == 0 && text == NULL)
943 return FALSE;
944 else if (info.size == 0 || text == NULL)
945 return TRUE;
947 file_text = g_new0(gchar, info.size + 1);
949 if (gnome_vfs_open(&handle, uri, GNOME_VFS_OPEN_READ != GNOME_VFS_OK))
950 return TRUE;
952 if ((gnome_vfs_read(handle, file_text, info.size, &bytes_read) == GNOME_VFS_OK)
953 && (bytes_read == info.size))
955 gnome_vfs_close(handle);
957 if ((g_utf8_strlen(file_text, -1) == g_utf8_strlen(text, -1))
958 && strcmp(file_text, text) == 0)
959 return FALSE;
960 return TRUE;
962 else
964 gnome_vfs_close(handle);
965 return TRUE;
969 gboolean
970 anjuta_util_path_has_extension (const gchar *path, const gchar *ext)
972 if (strlen (path) <= strlen (ext))
973 return FALSE;
974 if ((path[strlen (path) - strlen (ext) - 1] == '.') &&
975 (strcmp (&path[strlen (path) - strlen (ext)], ext) == 0))
976 return TRUE;
977 return FALSE;
980 gchar *
981 anjuta_util_get_uri_mime_type (const gchar *uri)
983 GnomeVFSURI *vfs_uri;
984 const gchar *path;
985 gchar *mime_type;
987 g_return_val_if_fail (uri != NULL, NULL);
989 vfs_uri = gnome_vfs_uri_new (uri);
990 if (vfs_uri)
991 path = gnome_vfs_uri_get_path (vfs_uri);
992 else
993 path = NULL;
995 /* If Anjuta is not installed in system gnome prefix, the mime types
996 * may not have been correctly registed. In that case, we use the
997 * following mime detection
999 if (!path)
1001 mime_type = gnome_vfs_get_mime_type (uri);
1003 else if (anjuta_util_path_has_extension (path, "anjuta"))
1005 mime_type = g_strdup ("application/x-anjuta");
1007 else if (anjuta_util_path_has_extension (path, "prj"))
1009 mime_type = g_strdup ("application/x-anjuta-old");
1011 else if (anjuta_util_path_has_extension (path, "ui"))
1013 mime_type = g_strdup ("text/xml");
1015 else if (anjuta_util_path_has_extension (path, "glade"))
1017 mime_type = g_strdup ("application/x-glade");
1019 else
1021 mime_type = gnome_vfs_get_mime_type (uri);
1024 if (vfs_uri)
1025 gnome_vfs_uri_unref (vfs_uri);
1026 return mime_type;
1029 #ifndef HAVE_LIBUTIL
1030 #include <grp.h>
1032 static int ptym_open (char *pts_name);
1033 static int ptys_open (int fdm, char * pts_name);
1036 login_tty(int ttyfd)
1038 int fd;
1039 char *fdname;
1041 #ifdef HAVE_SETSID
1042 setsid();
1043 #endif
1044 #ifdef HAVE_SETPGID
1045 setpgid(0, 0);
1046 #endif
1048 /* First disconnect from the old controlling tty. */
1049 #ifdef TIOCNOTTY
1050 fd = open("/dev/tty", O_RDWR|O_NOCTTY);
1051 if (fd >= 0)
1053 ioctl(fd, TIOCNOTTY, NULL);
1054 close(fd);
1056 else
1057 //syslog(LOG_WARNING, "NO CTTY");
1058 #endif /* TIOCNOTTY */
1060 /* Verify that we are successfully disconnected from the controlling tty. */
1061 fd = open("/dev/tty", O_RDWR|O_NOCTTY);
1062 if (fd >= 0)
1064 //syslog(LOG_WARNING, "Failed to disconnect from controlling tty.");
1065 close(fd);
1068 /* Make it our controlling tty. */
1069 #ifdef TIOCSCTTY
1070 ioctl(ttyfd, TIOCSCTTY, NULL);
1071 #endif /* TIOCSCTTY */
1073 fdname = ttyname (ttyfd);
1074 fd = open(fdname, O_RDWR);
1075 if (fd < 0)
1076 ;//syslog(LOG_WARNING, "open %s: %s", fdname, strerror(errno));
1077 else
1078 close(fd);
1080 /* Verify that we now have a controlling tty. */
1081 fd = open("/dev/tty", O_WRONLY);
1082 if (fd < 0)
1084 //syslog(LOG_WARNING, "open /dev/tty: %s", strerror(errno));
1085 return 1;
1088 close(fd);
1089 #if defined(HAVE_VHANGUP) && !defined(HAVE_REVOKE)
1091 RETSIGTYPE (*sig)();
1092 sig = signal(SIGHUP, SIG_IGN);
1093 vhangup();
1094 signal(SIGHUP, sig);
1096 #endif
1097 fd = open(fdname, O_RDWR);
1098 if (fd == -1)
1100 //syslog(LOG_ERR, "can't reopen ctty %s: %s", fdname, strerror(errno));
1101 return -1;
1104 close(ttyfd);
1106 if (fd != 0)
1107 close(0);
1108 if (fd != 1)
1109 close(1);
1110 if (fd != 2)
1111 close(2);
1113 dup2(fd, 0);
1114 dup2(fd, 1);
1115 dup2(fd, 2);
1116 if (fd > 2)
1117 close(fd);
1118 return 0;
1122 openpty(int *amaster, int *aslave, char *name, struct termios *termp,
1123 struct winsize *winp)
1125 char line[20];
1126 *amaster = ptym_open(line);
1127 if (*amaster < 0)
1128 return -1;
1129 *aslave = ptys_open(*amaster, line);
1130 if (*aslave < 0) {
1131 close(*amaster);
1132 return -1;
1134 if (name)
1135 strcpy(name, line);
1136 #ifndef TCSAFLUSH
1137 #define TCSAFLUSH TCSETAF
1138 #endif
1139 if (termp)
1140 (void) tcsetattr(*aslave, TCSAFLUSH, termp);
1141 #ifdef TIOCSWINSZ
1142 if (winp)
1143 (void) ioctl(*aslave, TIOCSWINSZ, (char *)winp);
1144 #endif
1145 return 0;
1148 static int
1149 ptym_open(char * pts_name)
1151 int fdm;
1152 #ifdef HAVE_PTSNAME
1153 char *ptr;
1155 strcpy(pts_name, "/dev/ptmx");
1156 fdm = open(pts_name, O_RDWR);
1157 if (fdm < 0)
1158 return -1;
1159 if (grantpt(fdm) < 0) { /* grant access to slave */
1160 close(fdm);
1161 return -2;
1163 if (unlockpt(fdm) < 0) { /* clear slave's lock flag */
1164 close(fdm);
1165 return -3;
1167 ptr = ptsname(fdm);
1168 if (ptr == NULL) { /* get slave's name */
1169 close (fdm);
1170 return -4;
1172 strcpy(pts_name, ptr); /* return name of slave */
1173 return fdm; /* return fd of master */
1174 #else
1175 char *ptr1, *ptr2;
1177 strcpy(pts_name, "/dev/ptyXY");
1178 /* array index: 012345689 (for references in following code) */
1179 for (ptr1 = "pqrstuvwxyzPQRST"; *ptr1 != 0; ptr1++) {
1180 pts_name[8] = *ptr1;
1181 for (ptr2 = "0123456789abcdef"; *ptr2 != 0; ptr2++) {
1182 pts_name[9] = *ptr2;
1183 /* try to open master */
1184 fdm = open(pts_name, O_RDWR);
1185 if (fdm < 0) {
1186 if (errno == ENOENT) /* different from EIO */
1187 return -1; /* out of pty devices */
1188 else
1189 continue; /* try next pty device */
1191 pts_name[5] = 't'; /* chage "pty" to "tty" */
1192 return fdm; /* got it, return fd of master */
1195 return -1; /* out of pty devices */
1196 #endif
1199 static int
1200 ptys_open(int fdm, char * pts_name)
1202 int fds;
1203 #ifdef HAVE_PTSNAME
1204 /* following should allocate controlling terminal */
1205 fds = open(pts_name, O_RDWR);
1206 if (fds < 0) {
1207 close(fdm);
1208 return -5;
1210 if (ioctl(fds, I_PUSH, "ptem") < 0) {
1211 close(fdm);
1212 close(fds);
1213 return -6;
1215 if (ioctl(fds, I_PUSH, "ldterm") < 0) {
1216 close(fdm);
1217 close(fds);
1218 return -7;
1220 if (ioctl(fds, I_PUSH, "ttcompat") < 0) {
1221 close(fdm);
1222 close(fds);
1223 return -8;
1226 if (ioctl(fdm, I_PUSH, "pckt") < 0) {
1227 close(fdm);
1228 close(fds);
1229 return -8;
1232 if (ioctl(fdm, I_SRDOPT, RMSGN|RPROTDAT) < 0) {
1233 close(fdm);
1234 close(fds);
1235 return -8;
1238 return fds;
1239 #else
1240 int gid;
1241 struct group *grptr;
1243 grptr = getgrnam("tty");
1244 if (grptr != NULL)
1245 gid = grptr->gr_gid;
1246 else
1247 gid = -1; /* group tty is not in the group file */
1248 /* following two functions don't work unless we're root */
1249 chown(pts_name, getuid(), gid);
1250 chmod(pts_name, S_IRUSR | S_IWUSR | S_IWGRP);
1251 fds = open(pts_name, O_RDWR);
1252 if (fds < 0) {
1253 close(fdm);
1254 return -1;
1256 return fds;
1257 #endif
1261 forkpty(int *amaster, char *name, struct termios *termp, struct winsize *winp)
1263 int master, slave, pid;
1265 if (openpty(&master, &slave, name, termp, winp) == -1)
1266 return (-1);
1267 switch (pid = fork()) {
1268 case -1:
1269 return (-1);
1270 case 0:
1272 * child
1274 close(master);
1275 login_tty(slave);
1276 return (0);
1279 * parent
1281 *amaster = master;
1282 close(slave);
1283 return (pid);
1286 int scandir(const char *dir, struct dirent ***namelist,
1287 int (*select)(const struct dirent *),
1288 int (*compar)(const struct dirent **, const struct dirent **))
1290 DIR *d;
1291 struct dirent *entry;
1292 register int i=0;
1293 size_t entrysize;
1295 if ((d=opendir(dir)) == NULL)
1296 return(-1);
1298 *namelist=NULL;
1299 while ((entry=readdir(d)) != NULL)
1301 if (select == NULL || (select != NULL && (*select)(entry)))
1303 *namelist=(struct dirent **)realloc((void *)(*namelist),
1304 (size_t)((i+1)*sizeof(struct dirent *)));
1305 if (*namelist == NULL) return(-1);
1306 entrysize=sizeof(struct dirent)-sizeof(entry->d_name)+strlen(entry->d_name)+1;
1307 (*namelist)[i]=(struct dirent *)malloc(entrysize);
1308 if ((*namelist)[i] == NULL) return(-1);
1309 memcpy((*namelist)[i], entry, entrysize);
1310 i++;
1313 if (closedir(d)) return(-1);
1314 if (i == 0) return(-1);
1315 if (compar != NULL)
1316 qsort((void *)(*namelist), (size_t)i, sizeof(struct dirent *), compar);
1318 return(i);
1321 #endif /* HAVE_LIBUTIL */
1323 void
1324 anjuta_util_help_display (GtkWindow *parent,
1325 const gchar *doc_id,
1326 const gchar *file_name)
1329 GError *error = NULL;
1330 GdkScreen *screen;
1331 gchar *command;
1332 const gchar *lang;
1333 const gchar * const *langs;
1334 gchar *uri = NULL;
1335 gint i;
1337 g_return_if_fail (file_name != NULL);
1339 langs = g_get_language_names ();
1340 for (i = 0; langs[i]; i++)
1342 lang = langs[i];
1343 if (strchr (lang, '.'))
1344 continue;
1346 uri = g_build_filename (DATADIR, "/gnome/help/", doc_id,
1347 lang, file_name, NULL);
1349 if (g_file_test (uri, G_FILE_TEST_EXISTS)) {
1350 break;
1352 g_free (uri);
1353 uri = NULL;
1356 if (uri == NULL)
1358 anjuta_util_dialog_error (parent, _("Unable to display help. Please make sure Anjuta "
1359 "documentation package is install. It can be downloaded "
1360 "from http://anjuta.org"));
1362 return;
1365 command = g_strconcat ("gnome-help ghelp://", uri, NULL);
1366 g_free (uri);
1368 screen = gtk_widget_get_screen (GTK_WIDGET (parent));
1369 gdk_spawn_command_line_on_screen (screen, command, &error);
1370 if (error != NULL)
1372 g_warning ("Error executing help application: %s",
1373 error->message);
1374 g_error_free (error);
1376 return;
1378 g_free (command);