#ifdef'd xmlerror.h
[dia.git] / app / app_procs.c
blobd8302c9373950e2ae3b26c913fa8744e03a0fe9e
1 /* Dia -- an diagram creation/manipulation program
2 * Copyright (C) 1998 Alexander Larsson
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 #include <config.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <sys/types.h>
24 #include <errno.h>
25 #ifdef HAVE_DIRENT_H
26 #include <dirent.h>
27 #endif
28 #include <sys/stat.h>
29 #include <string.h>
30 #include <signal.h>
31 #include <locale.h>
32 #ifdef HAVE_UNISTD_H
33 #include <unistd.h>
34 #endif
35 #ifdef HAVE_UNICODE
36 #include <unicode.h>
37 #endif
39 #include <gtk/gtk.h>
40 #include <gmodule.h>
42 #if (defined (HAVE_LIBPOPT) && defined (HAVE_POPT_H)) || defined (GNOME)
43 #define HAVE_POPT
44 #endif
46 #ifdef GNOME
47 #include <gnome.h>
48 #else
49 #ifdef HAVE_POPT_H
50 #include <popt.h>
51 #endif
52 #endif
54 #include <parser.h>
55 #if defined(LIBXML_VERSION) && LIBXML_VERSION >= 20000
56 #include <xmlerror.h>
57 #endif
59 #ifdef G_OS_WIN32
60 #include <direct.h>
61 #define mkdir(s,a) _mkdir(s)
62 #endif
64 #include "intl.h"
65 #include "app_procs.h"
66 #include "object.h"
67 #include "color.h"
68 #include "tool.h"
69 #include "interface.h"
70 #include "modify_tool.h"
71 #include "group.h"
72 #include "message.h"
73 #include "display.h"
74 #include "layer_dialog.h"
75 #include "load_save.h"
76 #include "preferences.h"
77 #include "dia_dirs.h"
78 #include "render_eps.h"
79 #include "sheet.h"
80 #include "plug-ins.h"
81 #include "recent_files.h"
83 #if defined(HAVE_LIBPNG) && defined(HAVE_LIBART)
84 extern DiaExportFilter png_export_filter;
85 #endif
87 static void create_user_dirs(void);
88 static PluginInitResult internal_plugin_init(PluginInfo *info);
90 static gboolean dia_is_interactive = TRUE;
92 #ifdef GNOME
94 static void
95 session_die (gpointer client_data)
97 gtk_main_quit ();
100 static int
101 save_state (GnomeClient *client,
102 gint phase,
103 GnomeRestartStyle save_style,
104 gint shutdown,
105 GnomeInteractStyle interact_style,
106 gint fast,
107 gpointer client_data)
109 gchar *argv[20];
110 gint i = 0;
111 GList *l;
112 Diagram *dia;
114 argv[i++] = "dia";
116 for(l = open_diagrams; l != NULL; l = g_list_next(l)) {
117 dia = (Diagram *)l->data;
118 if(!dia->unsaved) {
119 argv[i++] = dia->filename;
123 gnome_client_set_restart_command (client, i, argv);
124 gnome_client_set_clone_command (client, i, argv);
126 return TRUE;
128 #endif
130 char *
131 build_output_file_name(const char *infname, const char *format)
133 /* FIXME: probably overly confident... */
134 char *p = strrchr(infname,'.');
135 char *tmp;
136 if (!p) {
137 return g_strconcat(infname,".",format,NULL);
139 tmp = g_malloc0(strlen(infname)+1+strlen(format)+1);
140 memcpy(tmp,infname,p-infname);
141 strcat(tmp,".");
142 strcat(tmp,format);
143 return tmp;
146 const char *argv0 = NULL;
148 gboolean
149 do_convert(const char *infname,
150 const char *outfname)
152 DiaExportFilter *ef = NULL;
153 DiaImportFilter *inf = NULL;
154 DiagramData *diagdata = NULL;
156 dia_is_interactive = FALSE;
158 if (0==strcmp(infname,outfname)) {
159 fprintf(stderr,
160 _("%s error: input and output file name is identical: %s"),
161 argv0, infname);
162 exit(1);
165 diagdata = new_diagram_data();
166 inf = filter_guess_import_filter(infname);
167 if (!inf)
168 inf = &dia_import_filter;
169 if (!inf->import(infname,diagdata,inf->user_data)) {
170 fprintf(stderr,
171 _("%s error: need valid input file %s\n"),
172 argv0,infname);
173 exit(1);
175 ef = filter_guess_export_filter(outfname);
176 if (!ef) {
177 fprintf(stderr,
178 _("%s error: don't know how to export into %s\n"),
179 argv0,outfname);
180 exit(1);
182 ef->export(diagdata, outfname, infname, ef->user_data);
183 /* if (!quiet) */ fprintf(stdout,
184 _("%s --> %s\n"),
185 infname,outfname);
186 diagram_data_destroy(diagdata);
187 return TRUE;
190 void debug_break(void); /* shut gcc up */
191 void
192 debug_break(void)
194 /* Break here. All symbols are loaded. */
197 gboolean
198 app_is_interactive(void)
200 return dia_is_interactive;
203 #ifdef G_OS_WIN32
204 static void
205 myXmlErrorReporting (void *ctx, const char* msg, ...)
207 va_list args;
208 gchar *string;
210 va_start(args, msg);
211 string = g_strdup_vprintf (msg, args);
212 g_print (string);
213 va_end(args);
215 g_free(string);
217 #endif
219 void
220 app_init (int argc, char **argv)
222 gboolean nosplash = FALSE;
223 #ifdef GNOME
224 GnomeClient *client;
225 #endif
226 char *export_file_name = NULL;
227 char *export_file_format = NULL;
228 gboolean made_conversions = FALSE;
230 #ifdef HAVE_POPT
231 #ifndef GNOME
232 int rc = 0;
233 #endif
234 poptContext poptCtx = NULL;
235 struct poptOption options[] =
237 {"export", 'e', POPT_ARG_STRING, NULL /* &export_file_name */, 0,
238 N_("Export loaded file and exit"), N_("OUTPUT")},
239 {"export-to-format",'t', POPT_ARG_STRING, NULL /* &export_file_format */,
240 0, N_("Export to file format and exit"), N_("eps,png,wmf,cgm,dxf,fig")},
241 {"nosplash", 'n', POPT_ARG_NONE, &nosplash, 0,
242 N_("Don't show the splash screen"), NULL },
243 #ifndef GNOME
244 {"help", 'h', POPT_ARG_NONE, 0, 1, N_("Show this help message") },
245 #endif
246 {(char *) NULL, '\0', 0, NULL, 0}
248 #endif
250 #ifdef HAVE_POPT
251 options[0].arg = &export_file_name;
252 options[1].arg = &export_file_format;
253 #endif
255 argv0 = (argc > 0) ? argv[0] : "(none)";
257 gtk_set_locale();
258 setlocale(LC_NUMERIC, "C");
260 #ifdef HAVE_UNICODE
261 unicode_init();
262 #endif
264 bindtextdomain(PACKAGE, LOCALEDIR);
265 #if defined GTK_TALKS_UTF8 && defined ENABLE_NLS
266 bind_textdomain_codeset(PACKAGE,"UTF-8");
267 #endif
268 textdomain(PACKAGE);
270 if (argv) {
271 #ifdef GNOME
272 gnome_init_with_popt_table(PACKAGE, VERSION, argc, argv, options,
273 0, &poptCtx);
275 client = gnome_master_client();
276 if(client == NULL) {
277 g_warning(_("Can't connect to session manager!\n"));
279 else {
280 gtk_signal_connect(GTK_OBJECT (client), "save_yourself",
281 GTK_SIGNAL_FUNC (save_state), NULL);
282 gtk_signal_connect(GTK_OBJECT (client), "die",
283 GTK_SIGNAL_FUNC (session_die), NULL);
285 #else
286 #ifdef HAVE_POPT
287 poptCtx = poptGetContext(PACKAGE, argc, (const char **)argv, options, 0);
288 poptSetOtherOptionHelp(poptCtx, _("[OPTION...] [FILE...]"));
289 while (rc >= 0) {
290 if((rc = poptGetNextOpt(poptCtx)) < -1) {
291 fprintf(stderr,
292 _("Error on option %s: %s.\nRun '%s --help' to see a full list of available command line options.\n"),
293 poptBadOption(poptCtx, 0),
294 poptStrerror(rc),
295 argv[0]);
296 exit(1);
298 if(rc == 1) {
299 poptPrintHelp(poptCtx, stderr, 0);
300 exit(0);
303 if (export_file_format && export_file_name) {
304 fprintf(stderr,
305 _("%s error: can specify only one of -f or -o."),
306 argv[0]);
307 exit(1);
311 #endif
312 gtk_init (&argc, &argv);
313 #endif
316 LIBXML_TEST_VERSION;
318 #ifdef G_OS_WIN32
319 xmlSetGenericErrorFunc(NULL, myXmlErrorReporting);
320 #endif
322 stdprops_init();
324 dia_image_init();
326 gdk_rgb_init();
328 gtk_rc_parse ("diagtkrc");
330 if (!nosplash)
331 app_splash_init("");
333 create_user_dirs();
335 color_init();
337 font_init();
339 /* Init cursors: */
340 default_cursor = gdk_cursor_new(GDK_LEFT_PTR);
341 ddisplay_set_all_cursor(default_cursor);
343 object_registry_init();
345 dia_register_plugins();
346 dia_register_builtin_plugin(internal_plugin_init);
348 load_all_sheets(); /* new mechanism */
350 debug_break();
352 if (object_get_type("Standard - Box") == NULL) {
353 message_error(_("Couldn't find standard objects when looking for "
354 "object-libs, exiting...\n"));
355 fprintf(stderr, _("Couldn't find standard objects when looking for "
356 "object-libs, exiting...\n"));
357 exit(1);
360 prefs_load();
362 create_layer_dialog();
364 /* further initialization *before* reading files */
365 active_tool = create_modify_tool();
367 create_toolbox();
369 /*fill recent file menu */
370 recent_file_history_init();
372 create_tree_window();
374 /*autosave_restore_documents();*/
376 if (argv) {
377 #ifdef HAVE_POPT
378 while (poptPeekArg(poptCtx)) {
379 Diagram *diagram = NULL;
380 DDisplay *ddisp = NULL;
381 char *in_file_name = (char *)poptGetArg(poptCtx);
383 if (export_file_name) {
384 made_conversions |= do_convert(in_file_name,export_file_name);
385 } else if (export_file_format) {
386 export_file_name = build_output_file_name(in_file_name,
387 export_file_format);
388 made_conversions |= do_convert(in_file_name,export_file_name);
389 g_free(export_file_name);
390 } else {
391 diagram = diagram_load (in_file_name, NULL);
392 if (diagram != NULL) {
393 diagram_update_extents(diagram);
394 layer_dialog_set_diagram(diagram);
396 ddisp = new_display(diagram);
400 poptFreeContext(poptCtx);
401 #else
402 int i;
404 for (i=1; i<argc; i++) {
405 Diagram *diagram = NULL;
406 DDisplay *ddisp;
407 char *in_file_name = argv[i]; /* unless it's an option... */
409 if (0==strcmp(argv[i],"-t")) {
410 if (i < (argc-1)) {
411 i++;
412 export_file_format = argv[i];
413 continue;
415 } else if (0 == strcmp(argv[i],"-e")) {
416 if (i < (argc-1)) {
417 i++;
418 export_file_name = argv[i];
419 continue;
423 if (export_file_name) {
424 made_conversions |= do_convert(in_file_name,export_file_name);
425 } else if (export_file_format) {
426 export_file_name = build_output_file_name(in_file_name,
427 export_file_format);
428 made_conversions |= do_convert(in_file_name,export_file_name);
429 g_free(export_file_name);
430 } else {
431 diagram = diagram_load(in_file_name, NULL);
433 if (diagram != NULL) {
434 diagram_update_extents(diagram);
435 layer_dialog_set_diagram(diagram);
437 ddisp = new_display(diagram);
439 /* Error messages are done in diagram_load() */
442 #endif
444 if (made_conversions) exit(0);
447 static void
448 set_true_callback(GtkWidget *w, int *data)
450 *data = TRUE;
453 void
454 app_exit(void)
456 GList *list;
457 GSList *slist;
458 gchar *filename;
460 * The following "solves" a crash related to a second call of app_exit,
461 * after gtk_main_quit was called. It may be a win32 gtk-1.3.x bug only
462 * but the check shouldn't hurt on *ix either. --hb
464 static gboolean app_exit_once = FALSE;
466 g_return_if_fail (!app_exit_once);
468 if (diagram_modified_exists()) {
469 GtkWidget *dialog;
470 GtkWidget *vbox;
471 GtkWidget *label;
472 #ifndef GNOME
473 GtkWidget *button;
474 #endif
475 int result = FALSE;
477 #ifdef GNOME
478 dialog = gnome_dialog_new(_("Quit, are you sure?"), NULL);
479 vbox = GNOME_DIALOG(dialog)->vbox;
480 gnome_dialog_set_close(GNOME_DIALOG(dialog), TRUE);
481 #else
482 dialog = gtk_dialog_new();
483 vbox = GTK_DIALOG(dialog)->vbox;
484 gtk_window_set_title (GTK_WINDOW (dialog), _("Quit, are you sure?"));
485 gtk_container_set_border_width (GTK_CONTAINER (dialog), 0);
486 #endif
488 gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
489 GTK_SIGNAL_FUNC(gtk_main_quit), NULL);
491 label = gtk_label_new (_("Modified diagrams exists.\n"
492 "Are you sure you want to quit?"));
494 gtk_misc_set_padding (GTK_MISC (label), 10, 10);
495 gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
497 gtk_widget_show (label);
499 #ifdef GNOME
500 gnome_dialog_append_button_with_pixmap(GNOME_DIALOG(dialog),
501 _("Quit"), GNOME_STOCK_PIXMAP_QUIT);
502 gnome_dialog_append_button(GNOME_DIALOG(dialog),GNOME_STOCK_BUTTON_CANCEL);
504 result = (gnome_dialog_run(GNOME_DIALOG(dialog)) == 0);
505 #else
506 button = gtk_button_new_with_label (_("Quit"));
507 GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
508 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area),
509 button, TRUE, TRUE, 0);
510 gtk_signal_connect (GTK_OBJECT (button), "clicked",
511 GTK_SIGNAL_FUNC(set_true_callback),
512 &result);
513 gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
514 GTK_SIGNAL_FUNC (gtk_widget_destroy),
515 GTK_OBJECT (dialog));
516 gtk_widget_show (button);
518 button = gtk_button_new_with_label (_("Cancel"));
519 GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
520 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area),
521 button, TRUE, TRUE, 0);
522 gtk_widget_grab_default (button);
523 gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
524 GTK_SIGNAL_FUNC (gtk_widget_destroy),
525 GTK_OBJECT (dialog));
527 gtk_widget_show (button);
529 gtk_widget_show (dialog);
531 /* Make dialog modal: */
532 gtk_widget_grab_focus(dialog);
533 gtk_grab_add(dialog);
535 gtk_main();
536 #endif
538 if (result == FALSE)
539 return;
542 /* Save menu accelerators */
543 filename = dia_config_filename("menus" G_DIR_SEPARATOR_S "toolbox");
544 if (filename!=NULL) {
545 GtkPatternSpec pattern;
547 gtk_pattern_spec_init(&pattern, "*<Toolbox>*");
549 gtk_item_factory_dump_rc (filename, &pattern, TRUE);
550 g_free (filename);
551 gtk_pattern_spec_free_segs(&pattern);
554 /* Free loads of stuff (toolbox) */
556 list = open_diagrams;
557 while (list!=NULL) {
558 Diagram *dia = (Diagram *)list->data;
559 list = g_list_next(list);
561 slist = dia->displays;
562 while (slist!=NULL) {
563 DDisplay *ddisp = (DDisplay *)slist->data;
564 slist = g_slist_next(slist);
566 gtk_widget_destroy(ddisp->shell);
569 /* The diagram is freed when the last display is destroyed */
573 /* save pluginrc */
574 dia_pluginrc_write();
576 /* save recent file history */
577 recent_file_history_write();
579 gtk_main_quit();
580 app_exit_once = TRUE;
583 static void create_user_dirs(void)
585 gchar *dir, *subdir;
587 #ifdef G_OS_WIN32
588 /* not necessary to quit the program with g_error, everywhere else
589 * dia_config_filename appears to be used. Spit out a warning ...
591 if (!g_get_home_dir())
593 g_warning(_("Could not create per-user Dia config directory"));
594 return; /* ... and return. Probably removes my one and only FAQ. --HB */
596 #endif
597 dir = g_strconcat(g_get_home_dir(), G_DIR_SEPARATOR_S ".dia", NULL);
598 if (mkdir(dir, 0755) && errno != EEXIST)
599 #ifndef G_OS_WIN32
600 g_error(_("Could not create per-user Dia config directory"));
601 #else /* HB: it this really a reason to exit the program on *nix ? */
602 g_warning(_("Could not create per-user Dia config directory. Please make "
603 "sure that the environment variable HOME points to an existing directory."));
604 #endif
606 /* it is no big deal if these directories can't be created */
607 subdir = g_strconcat(dir, G_DIR_SEPARATOR_S "objects", NULL);
608 mkdir(subdir, 0755);
609 g_free(subdir);
610 subdir = g_strconcat(dir, G_DIR_SEPARATOR_S "shapes", NULL);
611 mkdir(subdir, 0755);
612 g_free(subdir);
613 subdir = g_strconcat(dir, G_DIR_SEPARATOR_S "sheets", NULL);
614 mkdir(subdir, 0755);
615 g_free(subdir);
617 g_free(dir);
620 static PluginInitResult
621 internal_plugin_init(PluginInfo *info)
623 if (!dia_plugin_info_init(info, "Internal",
624 _("Objects and filters internal to dia"),
625 NULL, NULL))
626 return DIA_PLUGIN_INIT_ERROR;
628 /* register the group object type */
629 object_register_type(&group_type);
631 /* register import filters */
632 filter_register_import(&dia_import_filter);
634 /* register export filters */
635 filter_register_export(&dia_export_filter);
636 filter_register_export(&eps_export_filter);
637 #if defined(HAVE_LIBPNG) && defined(HAVE_LIBART)
638 filter_register_export(&png_export_filter);
639 #endif
641 return DIA_PLUGIN_INIT_OK;