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.
23 #include <sys/types.h>
33 /* wants to be included early to avoid complains about setjmp.h */
35 #include <png.h> /* just for the version stuff */
41 #if (defined (HAVE_LIBPOPT) && defined (HAVE_POPT_H)) || defined (GNOME)
51 /* sorry about the mess, but one should not use conditional defined types in
52 * unconditional function call in the first place ... --hb */
53 typedef void* poptContext
;
57 /* apparently there is no clean way to use glib-2.6 GOption with gnome */
58 #if GLIB_CHECK_VERSION(2,5,5) && !defined GNOME
59 # define USE_GOPTION 1
61 # define USE_GOPTION 0
65 #include <pango/pangoft2.h>
68 #include <libxml/parser.h>
69 #include <libxml/xmlerror.h>
73 #define mkdir(s,a) _mkdir(s)
77 #include "app_procs.h"
81 #include "interface.h"
82 #include "modify_tool.h"
86 #include "layer_dialog.h"
87 #include "load_save.h"
88 #include "preferences.h"
90 #include "render_eps.h"
93 #include "recent_files.h"
96 #include "dynamic_refresh.h"
97 #include "dia_image.h"
98 #include "persistence.h"
102 #if defined(HAVE_LIBPNG) && defined(HAVE_LIBART)
103 extern DiaExportFilter png_export_filter
;
107 handle_initial_diagram(const char *input_file_name
,
108 const char *export_file_name
,
109 const char *export_file_format
,
113 static void create_user_dirs(void);
114 static PluginInitResult
internal_plugin_init(PluginInfo
*info
);
115 static void process_opts(int argc
, char **argv
,
117 GOptionContext
* context
, GOptionEntry options
[],
118 #elif defined HAVE_POPT
119 poptContext poptCtx
, struct poptOption options
[],
121 GSList
**files
, char **export_file_name
,
122 char **export_file_format
, char **size
,
123 char **show_layers
, gboolean
*nosplash
);
124 static gboolean
handle_all_diagrams(GSList
*files
, char *export_file_name
,
125 char *export_file_format
, char *size
, char *show_layers
);
126 static void print_credits(gboolean credits
);
128 static gboolean dia_is_interactive
= TRUE
;
130 stderr_message_internal(const char *title
, const char *fmt
,
131 va_list *args
, va_list *args2
);
134 stderr_message_internal(const char *title
, const char *fmt
,
135 va_list *args
, va_list *args2
)
137 static gchar
*buf
= NULL
;
138 static gint alloc
= 0;
141 len
= format_string_length_upper_bound (fmt
, args
);
147 alloc
= nearest_pow (MAX(len
+ 1, 1024));
149 buf
= g_new (char, alloc
);
152 vsprintf (buf
, fmt
, *args2
);
162 session_die (gpointer client_data
)
168 save_state (GnomeClient
*client
,
170 GnomeRestartStyle save_style
,
172 GnomeInteractStyle interact_style
,
174 gpointer client_data
)
183 for(l
= dia_open_diagrams(); l
!= NULL
; l
= g_list_next(l
)) {
184 dia
= (Diagram
*)l
->data
;
186 argv
[i
++] = dia
->filename
;
190 gnome_client_set_restart_command (client
, i
, argv
);
191 gnome_client_set_clone_command (client
, i
, argv
);
198 build_output_file_name(const char *infname
, const char *format
)
200 /* FIXME: probably overly confident... */
201 char *p
= strrchr(infname
,'.');
204 return g_strconcat(infname
,".",format
,NULL
);
206 tmp
= g_malloc0(strlen(infname
)+1+strlen(format
)+1);
207 memcpy(tmp
,infname
,p
-infname
);
213 /* Handle the string between commas. We have either of:
215 * 1. XX, the number XX
216 * 2. -XX, every number until XX
217 * 3. XX-, every number from XX until n_layers
218 * 4. XX-YY, every number between XX-YY
221 show_layers_parse_numbers(DiagramData
*diagdata
, gboolean
*visible_layers
, gint n_layers
, const char *str
)
224 unsigned long int low
= 0;
225 unsigned long int high
= n_layers
;
231 /* Case 2, starts with '-' */
235 high
= strtoul(str
, &p
, 10)+1;
236 /* This must be a number (otherwise we would have called parse_name) */
241 low
= strtoul(str
, &p
, 10);
242 high
= low
+1; /* Assume case 1 */
248 if (*str
== '\0') /* Case 3 */
252 high
= strtoul(str
, &p
, 10)+1;
259 /* This is not an errror */
260 g_print(_("Warning: invalid layer range %lu - %lu\n"), low
, high
-1 );
266 /* Set the visible layers */
267 for ( i
= low
; i
< high
; i
++ )
269 Layer
*lay
= (Layer
*)g_ptr_array_index(diagdata
->layers
, i
);
271 if (visible_layers
[i
] == TRUE
)
272 g_print(_("Warning: Layer %lu (%s) selected more than once.\n"), i
, lay
->name
);
273 visible_layers
[i
] = TRUE
;
278 show_layers_parse_word(DiagramData
*diagdata
, gboolean
*visible_layers
, gint n_layers
, const char *str
)
280 GPtrArray
*layers
= diagdata
->layers
;
281 gboolean found
= FALSE
;
283 /* Apply --show-layers=LAYER,LAYER,... switch. 13.3.2004 sampo@iki.fi */
288 for (k
= 0; k
< layers
->len
; k
++) {
289 lay
= (Layer
*)g_ptr_array_index(layers
, k
);
292 len
= strlen(lay
->name
);
293 if ((p
= strstr(str
, lay
->name
)) != NULL
) {
294 if (((p
== str
) || (p
[-1] == ',')) /* zap false positives */
295 && ((p
[len
] == 0) || (p
[len
] == ','))){
297 if (visible_layers
[k
] == TRUE
)
298 g_print(_("Warning: Layer %d (%s) selected more than once.\n"), k
, lay
->name
);
299 visible_layers
[k
] = TRUE
;
307 g_print(_("Warning: There is no layer named %s\n"), str
);
311 show_layers_parse_string(DiagramData
*diagdata
, gboolean
*visible_layers
, gint n_layers
, const char *str
)
316 pp
= g_strsplit(str
, ",", 100);
318 for (i
= 0; pp
[i
]; i
++) {
321 /* Skip the empty string */
325 /* If the string is only numbers and '-' chars, it is parsed as a
326 * number range. Otherwise it is parsed as a layer name.
328 if (strlen(p
) != strspn(p
, "0123456789-") )
329 show_layers_parse_word(diagdata
, visible_layers
, n_layers
, p
);
331 show_layers_parse_numbers(diagdata
, visible_layers
, n_layers
, p
);
339 handle_show_layers(DiagramData
*diagdata
, const char *show_layers
)
341 gboolean
*visible_layers
;
345 visible_layers
= g_malloc(diagdata
->layers
->len
* sizeof(gboolean
));
346 /* Assume all layers are non-visible */
347 for (i
=0;i
<diagdata
->layers
->len
;i
++)
348 visible_layers
[i
] = FALSE
;
350 /* Split the layer-range by commas */
351 show_layers_parse_string(diagdata
, visible_layers
, diagdata
->layers
->len
,
354 /* Set the visibility of the layers */
355 for (i
=0;i
<diagdata
->layers
->len
;i
++) {
356 layer
= g_ptr_array_index(diagdata
->layers
, i
);
358 if (visible_layers
[i
] == TRUE
)
359 layer
->visible
= TRUE
;
361 layer
->visible
= FALSE
;
363 g_free(visible_layers
);
367 const char *argv0
= NULL
;
369 /** Convert infname to outfname, using input filter inf and export filter
370 * ef. If either is null, try to guess them.
371 * size might be NULL.
374 do_convert(const char *infname
,
375 const char *outfname
, DiaExportFilter
*ef
,
379 DiaImportFilter
*inf
;
380 DiagramData
*diagdata
= NULL
;
382 inf
= filter_guess_import_filter(infname
);
384 inf
= &dia_import_filter
;
387 ef
= filter_guess_export_filter(outfname
);
389 g_critical(_("%s error: don't know how to export into %s\n"),
395 dia_is_interactive
= FALSE
;
397 if (0==strcmp(infname
,outfname
)) {
398 g_critical(_("%s error: input and output file name is identical: %s"),
403 diagdata
= g_object_new (DIA_TYPE_DIAGRAM_DATA
, NULL
);
405 if (!inf
->import_func(infname
,diagdata
,inf
->user_data
)) {
406 g_critical(_("%s error: need valid input file %s\n"),
411 /* Apply --show-layers */
413 handle_show_layers(diagdata
, show_layers
);
415 /* Do our best in providing the size to the filter, but don't abuse user_data
416 * too much for it. It _must not_ be changed after initialization and there
417 * are quite some filter selecting their output format by it. --hb
420 if (ef
== filter_get_by_name ("png-libart")) /* the warning we get is appropriate, don't cast */
421 ef
->export_func(diagdata
, outfname
, infname
, size
);
423 g_warning ("--size parameter unsupported for %s filter",
424 ef
->unique_name
? ef
->unique_name
: "selected");
425 ef
->export_func(diagdata
, outfname
, infname
, ef
->user_data
);
429 ef
->export_func(diagdata
, outfname
, infname
, ef
->user_data
);
430 /* if (!quiet) */ fprintf(stdout
,
433 g_object_unref(diagdata
);
437 void debug_break(void); /* shut gcc up */
438 int debug_break_dont_optimize
= 1;
442 if (debug_break_dont_optimize
> 0)
443 debug_break_dont_optimize
-= 1;
447 dump_dependencies(void)
450 g_print ("Compiler: GCC " __VERSION__
"\n");
451 #elif defined _MSC_VER
452 g_print ("Compiler: MSC %d\n", _MSC_VER
);
454 g_print ("Compiler: unknown\n");
456 /* some flags/defines which may be interesting */
458 #ifdef G_THREADS_ENABLED
467 #ifdef HAVE_GNOMEPRINT
475 /* print out all those dependies, both compile and runtime if possible
476 * Note: this is not meant to be complete but does only include libaries
477 * which may or have cause(d) us trouble in some versions
479 g_print ("Library versions\n");
481 g_print ("libpng : %s (%s)\n", png_get_header_ver(NULL
), PNG_LIBPNG_VER_STRING
);
485 FT_Library ft_library
;
486 FT_Int ft_major_version
;
487 FT_Int ft_minor_version
;
488 FT_Int ft_micro_version
;
490 if (FT_Init_FreeType (&ft_library
) == 0) {
491 FT_Library_Version (ft_library
,
496 g_print ("freetype: %d.%d.%d\n", ft_major_version
, ft_minor_version
, ft_micro_version
);
497 FT_Done_FreeType (ft_library
);
500 g_print ("freetype: ?.?.?\n");
504 gint libxml_version
= atoi(xmlParserVersion
);
506 g_print ("libxml : %d.%d.%d (%s)\n",
507 libxml_version
/ 100 / 100, libxml_version
/ 100 % 100, libxml_version
% 100, LIBXML_DOTTED_VERSION
);
509 g_print ("glib : %d.%d.%d (%d.%d.%d)\n",
510 glib_major_version
, glib_minor_version
, glib_micro_version
,
511 GLIB_MAJOR_VERSION
, GLIB_MINOR_VERSION
, GLIB_MICRO_VERSION
);
512 g_print ("pango : version not available\n"); /* Pango does not provide such */
515 gchar linkedname
[1024];
518 /* relying on PREFIX is wrong */
519 if ((len
= readlink (PREFIX
"/lib/libpango-1.0.so", linkedname
, 1023)) > 0) {
520 /* man 2 readlink : does not append a NUL character */
521 linkedname
[len
] = '\0';
522 g_print ("%s/%s\n", PREFIX
, linkedname
);
526 g_print ("gtk+ : %d.%d.%d (%d.%d.%d)\n",
527 gtk_major_version
, gtk_minor_version
, gtk_micro_version
,
528 GTK_MAJOR_VERSION
, GTK_MINOR_VERSION
, GTK_MICRO_VERSION
);
531 /* we could read $PREFIX/share/gnome-about/gnome-version.xml
532 * but is it worth the effort ? */
533 g_print ("gnome : %d.%d.%d (%d.%d.%d)\n"
534 gnome_major_version
, gnome_minor_version
, gnome_micro_version
,
535 GNOME_MAJOR_VERSION
, GNOME_MINOR_VERSION
, GNOME_MICRO_VERSION
);
540 app_is_interactive(void)
542 return dia_is_interactive
;
545 /** Handle loading of diagrams given on command line, including conversions.
546 * Returns TRUE if any automatic conversions were performed.
547 * Note to future hackers: 'size' is currently the only argument that can be
548 * sent to exporters. If more arguments are desired, please don't just add
549 * even more arguments, but create a more general system.
552 handle_initial_diagram(const char *in_file_name
,
553 const char *out_file_name
,
554 const char *export_file_format
,
557 DDisplay
*ddisp
= NULL
;
558 Diagram
*diagram
= NULL
;
559 gboolean made_conversions
= FALSE
;
561 if (export_file_format
) {
562 char *export_file_name
= NULL
;
563 DiaExportFilter
*ef
= NULL
;
565 /* First try guessing based on extension */
566 export_file_name
= build_output_file_name(in_file_name
,
569 /* to make the --size hack even uglier but work again for the only filter supporting it */
570 if ( size
&& strcmp(export_file_format
, "png") == 0)
571 ef
= filter_get_by_name ("png-libart");
573 ef
= filter_guess_export_filter(export_file_name
);
575 ef
= filter_get_by_name(export_file_format
);
577 g_critical(_("Can't find output format/filter %s\n"), export_file_format
);
580 g_free (export_file_name
);
581 export_file_name
= build_output_file_name(in_file_name
,
584 made_conversions
|= do_convert(in_file_name
,
585 (out_file_name
!= NULL
?out_file_name
:export_file_name
),
586 ef
, size
, show_layers
);
587 g_free(export_file_name
);
588 } else if (out_file_name
) {
589 DiaExportFilter
*ef
= NULL
;
591 /* if this looks like an ugly hack to you, agreed ;) */
592 if (size
&& strstr(out_file_name
, ".png"))
593 ef
= filter_get_by_name ("png-libart");
595 made_conversions
|= do_convert(in_file_name
, out_file_name
, ef
,
598 if (g_file_test(in_file_name
, G_FILE_TEST_EXISTS
)) {
599 diagram
= diagram_load (in_file_name
, NULL
);
601 diagram
= new_diagram (in_file_name
);
604 if (diagram
!= NULL
) {
605 diagram_update_extents(diagram
);
606 if (app_is_interactive()) {
607 layer_dialog_set_diagram(diagram
);
608 /* the display initial diagram holds two references */
609 ddisp
= new_display(diagram
);
611 g_object_unref(diagram
);
615 return made_conversions
;
620 myXmlErrorReporting (void *ctx
, const char* msg
, ...)
626 string
= g_strdup_vprintf (msg
, args
);
627 g_print ("%s", string
? string
: "xml error (null)?");
635 /* Translators: This is an option, not to be translated */
636 #define EPS_PANGO "eps-pango, "
642 /* Translators: This is an option, not to be translated */
649 app_init (int argc
, char **argv
)
651 static gboolean nosplash
= FALSE
;
652 static gboolean nonew
= FALSE
;
653 static gboolean credits
= FALSE
;
654 static gboolean version
= FALSE
;
655 static gboolean verbose
= FALSE
;
656 static gboolean log_to_stderr
= FALSE
;
660 static char *export_file_name
= NULL
;
661 static char *export_file_format
= NULL
;
662 static char *size
= NULL
;
663 static char *show_layers
= NULL
;
664 gboolean made_conversions
= FALSE
;
665 GSList
*files
= NULL
;
667 gchar
*export_format_string
=
668 /* Translators: The argument is a list of options, not to be translated */
669 g_strdup_printf(_("Select the filter/format out of: %s"),
670 "cgm, dia, dxf, eps, eps-builtin, " EPS_PANGO
671 "fig, mp, plt, hpgl, png ("
672 # if defined(HAVE_LIBPNG) && defined(HAVE_LIBART)
676 "cairo-png, cairo-alpha-png, "
678 /* we always have pixbuf but don't know exactly all it's *few* save formats */
680 "shape, svg, tex, " WMF
684 GOptionContext
*context
= NULL
;
685 static GOptionEntry options
[] =
687 {"export", 'e', 0, G_OPTION_ARG_STRING
, NULL
/* &export_file_name */,
688 N_("Export loaded file and exit"), N_("OUTPUT")},
689 {"filter",'t', 0, G_OPTION_ARG_STRING
, NULL
/* &export_file_format */,
690 NULL
/* &export_format_string */, N_("TYPE") },
691 {"size", 's', 0, G_OPTION_ARG_STRING
, NULL
,
692 N_("Export graphics size"), N_("WxH")},
693 {"show-layers", 'L', 0, G_OPTION_ARG_STRING
, NULL
,
694 N_("Show only specified layers (e.g. when exporting). Can be either the layer name or a range of layer numbers (X-Y)"),
695 N_("LAYER,LAYER,...")},
696 {"nosplash", 'n', 0, G_OPTION_ARG_NONE
, &nosplash
,
697 N_("Don't show the splash screen"), NULL
},
698 {"nonew", 'n', 0, G_OPTION_ARG_NONE
, &nonew
,
699 N_("Don't create empty diagram"), NULL
},
700 {"log-to-stderr", 'l', 0, G_OPTION_ARG_NONE
, &log_to_stderr
,
701 N_("Send error messages to stderr instead of showing dialogs."), NULL
},
702 {"credits", 'c', 0, G_OPTION_ARG_NONE
, &credits
,
703 N_("Display credits list and exit"), NULL
},
704 {"verbose", 0, 0, G_OPTION_ARG_NONE
, &verbose
,
705 N_("Generate verbose output"), NULL
},
706 {"version", 'v', 0, G_OPTION_ARG_NONE
, &version
,
707 N_("Display version and exit"), NULL
},
710 #elif defined HAVE_POPT
711 poptContext context
= NULL
;
712 struct poptOption options
[] =
714 {"export", 'e', POPT_ARG_STRING
, NULL
/* &export_file_name */, 0,
715 N_("Export loaded file and exit"), N_("OUTPUT")},
716 {"filter",'t', POPT_ARG_STRING
, NULL
/* &export_file_format */,
717 0, export_format_string
, N_("TYPE")
719 {"size", 's', POPT_ARG_STRING
, NULL
, 0,
720 N_("Export graphics size"), N_("WxH")},
721 {"show-layers", 'L', POPT_ARG_STRING
, NULL
, 0, /* 13.3.2004 sampo@iki.fi */
722 N_("Show only specified layers (e.g. when exporting). Can be either the layer name or a range of layer numbers (X-Y)"),
723 N_("LAYER,LAYER,...")},
724 {"nosplash", 'n', POPT_ARG_NONE
, &nosplash
, 0,
725 N_("Don't show the splash screen"), NULL
},
726 {"nonew", 'n', POPT_ARG_NONE
, &nonew
, 0,
727 N_("Don't create empty diagram"), NULL
},
728 {"log-to-stderr", 'l', POPT_ARG_NONE
, &log_to_stderr
, 0,
729 N_("Send error messages to stderr instead of showing dialogs."), NULL
},
730 {"credits", 'c', POPT_ARG_NONE
, &credits
, 0,
731 N_("Display credits list and exit"), NULL
},
732 {"verbose", 0, POPT_ARG_NONE
, &verbose
, 0,
733 N_("Generate verbose output"), NULL
},
734 {"version", 'v', POPT_ARG_NONE
, &version
, 0,
735 N_("Display version and exit"), NULL
},
736 {"help", 'h', POPT_ARG_NONE
, 0, 1, N_("Show this help message") },
737 {(char *) NULL
, '\0', 0, NULL
, 0}
742 options
[0].arg_data
= &export_file_name
;
743 options
[1].arg_data
= &export_file_format
;
744 options
[1].description
= export_format_string
;
745 options
[2].arg_data
= &size
;
746 options
[3].arg_data
= &show_layers
;
747 #elif defined HAVE_POPT
748 options
[0].arg
= &export_file_name
;
749 options
[1].arg
= &export_file_format
;
750 options
[2].arg
= &size
;
751 options
[3].arg
= &show_layers
;
754 argv0
= (argc
> 0) ? argv
[0] : "(none)";
757 setlocale(LC_NUMERIC
, "C");
760 /* calculate runtime directory */
762 gchar
* localedir
= dia_get_lib_directory ("locale");
764 bindtextdomain(GETTEXT_PACKAGE
, localedir
);
768 bindtextdomain(GETTEXT_PACKAGE
, LOCALEDIR
);
770 textdomain(GETTEXT_PACKAGE
);
772 process_opts(argc
, argv
,
773 #if defined HAVE_POPT || USE_GOPTION
777 &export_file_name
, &export_file_format
, &size
, &show_layers
, &nosplash
);
779 #if defined ENABLE_NLS && defined HAVE_BIND_TEXTDOMAIN_CODESET
780 bind_textdomain_codeset(GETTEXT_PACKAGE
,"UTF-8");
782 textdomain(GETTEXT_PACKAGE
);
784 if (argv
&& dia_is_interactive
&& !version
) {
786 GnomeProgram
*program
=
787 gnome_program_init (PACKAGE
, VERSION
, LIBGNOMEUI_MODULE
,
789 /* haven't found a quick way to pass GOption here */
790 GNOME_PARAM_POPT_TABLE
, options
,
791 GNOME_PROGRAM_STANDARD_PROPERTIES
,
793 g_object_get(program
, "popt-context", &context
, NULL
);
794 client
= gnome_master_client();
796 g_warning(_("Can't connect to session manager!\n"));
799 g_signal_connect(GTK_OBJECT (client
), "save_yourself",
800 G_CALLBACK (save_state
), NULL
);
801 g_signal_connect(GTK_OBJECT (client
), "die",
802 G_CALLBACK (session_die
), NULL
);
805 /* This smaller icon is 48x48, standard Gnome size */
806 gnome_window_icon_set_default_from_file (GNOME_ICONDIR
"/dia_gnome_icon.png");
809 # ifdef G_THREADS_ENABLED
810 g_thread_init (NULL
);
812 gtk_init(&argc
, &argv
);
816 #ifdef G_THREADS_ENABLED
817 g_thread_init (NULL
);
820 #ifdef GDK_WINDOWING_WIN32
822 * On windoze there is no command line without display so this call is harmless.
823 * But it is needed to avoid failing in gdk functions just because there is a
824 * display check. Still a little hack ...
826 gtk_init(&argc
, &argv
);
830 /* done with option parsing, don't leak */
831 g_free(export_format_string
);
834 #if (defined __TIME__) && (defined __DATE__)
835 /* TRANSLATOR: 2nd and 3rd %s are time and date respectively. */
836 printf(g_locale_from_utf8(_("Dia version %s, compiled %s %s\n"), -1, NULL
, NULL
, NULL
), VERSION
, __TIME__
, __DATE__
);
838 printf(g_locale_from_utf8(_("Dia version %s\n"), -1, NULL
, NULL
, NULL
), VERSION
);
845 if (!dia_is_interactive
)
846 log_to_stderr
= TRUE
;
849 set_message_func(stderr_message_internal
);
851 print_credits(credits
);
856 xmlSetGenericErrorFunc(NULL
, myXmlErrorReporting
);
861 if (dia_is_interactive
) {
866 gtk_rc_parse("diagtkrc");
873 if (dia_is_interactive
)
877 if (dia_is_interactive
) {
879 default_cursor
= gdk_cursor_new(GDK_LEFT_PTR
);
880 ddisplay_set_all_cursor(default_cursor
);
883 object_registry_init();
885 dia_register_plugins();
886 dia_register_builtin_plugin(internal_plugin_init
);
888 load_all_sheets(); /* new mechanism */
890 dia_object_defaults_load (NULL
, TRUE
/* prefs.object_defaults_create_lazy */);
894 if (object_get_type("Standard - Box") == NULL
) {
895 message_error(_("Couldn't find standard objects when looking for "
896 "object-libs; exiting...\n"));
897 g_critical( _("Couldn't find standard objects when looking for "
898 "object-libs in '%s'; exiting...\n"), dia_get_lib_directory("dia"));
904 /** Must load prefs after persistence */
907 if (dia_is_interactive
) {
909 /* further initialization *before* reading files */
910 active_tool
= create_modify_tool();
914 persistence_register_window_create("layer_window",
915 (NullaryFunc
*)&create_layer_dialog
);
918 /*fill recent file menu */
919 recent_file_history_init();
921 /* Set up autosave to check every 5 minutes */
922 gtk_timeout_add(5*60*1000, autosave_check_autosave
, NULL
);
924 create_tree_window();
926 persistence_register_window_create("sheets_main_dialog",
927 (NullaryFunc
*)&sheets_dialog_create
);
930 /* In current setup, we can't find the autosaved files. */
931 /*autosave_restore_documents();*/
935 made_conversions
= handle_all_diagrams(files
, export_file_name
,
936 export_file_format
, size
, show_layers
);
937 if (dia_is_interactive
&& files
== NULL
&& !nonew
) {
938 gchar
*filename
= g_filename_from_utf8(_("Diagram1.dia"), -1, NULL
, NULL
, NULL
);
939 Diagram
*diagram
= new_diagram (filename
);
942 if (diagram
!= NULL
) {
943 diagram_update_extents(diagram
);
944 diagram
->is_default
= TRUE
;
945 layer_dialog_set_diagram(diagram
);
946 new_display(diagram
);
950 if (made_conversions
) exit(0);
952 dynobj_refresh_init();
956 /* app_procs.c: warning: `set_true_callback' defined but not used */
958 set_true_callback(GtkWidget
*w
, int *data
)
971 * The following "solves" a crash related to a second call of app_exit,
972 * after gtk_main_quit was called. It may be a win32 gtk-1.3.x bug only
973 * but the check shouldn't hurt on *ix either. --hb
975 static gboolean app_exit_once
= FALSE
;
978 g_error(_("This shouldn't happen. Please file a bug report at bugzilla.gnome.org\n"
979 "describing how you can cause this message to appear.\n"));
983 if (diagram_modified_exists()) {
987 dialog
= gtk_message_dialog_new(
988 NULL
, GTK_DIALOG_MODAL
,
989 GTK_MESSAGE_QUESTION
,
990 GTK_BUTTONS_NONE
, /* no standard buttons */
991 _("Quitting without saving modified diagrams"));
992 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog
),
993 _("Modified diagrams exist. "
994 "Are you sure you want to quit Dia "
995 "without saving them?"));
997 gtk_window_set_title (GTK_WINDOW(dialog
), _("Quit Dia"));
999 button
= gtk_button_new_from_stock (GTK_STOCK_CANCEL
);
1000 gtk_dialog_add_action_widget (GTK_DIALOG(dialog
), button
, GTK_RESPONSE_CANCEL
);
1001 GTK_WIDGET_SET_FLAGS (button
, GTK_CAN_DEFAULT
);
1002 gtk_dialog_set_default_response (GTK_DIALOG(dialog
), GTK_RESPONSE_CANCEL
);
1004 button
= gtk_button_new_from_stock (GTK_STOCK_QUIT
);
1005 gtk_dialog_add_action_widget (GTK_DIALOG(dialog
), button
, GTK_RESPONSE_OK
);
1007 gtk_widget_show_all (dialog
);
1009 if (gtk_dialog_run(GTK_DIALOG(dialog
)) != GTK_RESPONSE_OK
) {
1010 gtk_widget_destroy(dialog
);
1013 gtk_widget_destroy(dialog
);
1019 dynobj_refresh_finish();
1021 dia_object_defaults_save (NULL
);
1023 /* Free loads of stuff (toolbox) */
1025 list
= dia_open_diagrams();
1026 while (list
!=NULL
) {
1027 Diagram
*dia
= (Diagram
*)list
->data
;
1028 list
= g_list_next(list
);
1030 slist
= dia
->displays
;
1031 while (slist
!=NULL
) {
1032 DDisplay
*ddisp
= (DDisplay
*)slist
->data
;
1033 slist
= g_slist_next(slist
);
1035 gtk_widget_destroy(ddisp
->shell
);
1038 /* The diagram is freed when the last display is destroyed */
1043 if (dia_is_interactive
)
1044 dia_pluginrc_write();
1048 /* This printf seems to prevent a race condition with unrefs. */
1050 g_print(_("Thank you for using Dia.\n"));
1052 app_exit_once
= TRUE
;
1057 static void create_user_dirs(void)
1059 gchar
*dir
, *subdir
;
1062 /* not necessary to quit the program with g_error, everywhere else
1063 * dia_config_filename appears to be used. Spit out a warning ...
1065 if (!g_get_home_dir())
1067 g_warning(_("Could not create per-user Dia config directory"));
1068 return; /* ... and return. Probably removes my one and only FAQ. --HB */
1071 dir
= g_strconcat(g_get_home_dir(), G_DIR_SEPARATOR_S
".dia", NULL
);
1072 if (mkdir(dir
, 0755) && errno
!= EEXIST
) {
1074 g_critical(_("Could not create per-user Dia config directory"));
1076 #else /* HB: it this really a reason to exit the program on *nix ? */
1077 g_warning(_("Could not create per-user Dia config directory. Please make "
1078 "sure that the environment variable HOME points to an existing directory."));
1082 /* it is no big deal if these directories can't be created */
1083 subdir
= g_strconcat(dir
, G_DIR_SEPARATOR_S
"objects", NULL
);
1084 mkdir(subdir
, 0755);
1086 subdir
= g_strconcat(dir
, G_DIR_SEPARATOR_S
"shapes", NULL
);
1087 mkdir(subdir
, 0755);
1089 subdir
= g_strconcat(dir
, G_DIR_SEPARATOR_S
"sheets", NULL
);
1090 mkdir(subdir
, 0755);
1096 static PluginInitResult
1097 internal_plugin_init(PluginInfo
*info
)
1099 if (!dia_plugin_info_init(info
, "Internal",
1100 _("Objects and filters internal to dia"),
1102 return DIA_PLUGIN_INIT_ERROR
;
1104 /* register the group object type */
1105 object_register_type(&group_type
);
1107 /* register import filters */
1108 filter_register_import(&dia_import_filter
);
1110 /* register export filters */
1111 /* Standard Dia format */
1112 filter_register_export(&dia_export_filter
);
1113 /* EPS with PS fonts */
1114 filter_register_export(&eps_export_filter
);
1115 #ifdef HAVE_FREETYPE
1116 /* EPS with Pango rendering */
1117 filter_register_export(&eps_ft2_export_filter
);
1119 #if defined(HAVE_LIBPNG) && defined(HAVE_LIBART)
1120 /* PNG with libart rendering */
1121 filter_register_export(&png_export_filter
);
1124 return DIA_PLUGIN_INIT_OK
;
1127 /* Note: running in locale encoding */
1129 process_opts(int argc
, char **argv
,
1131 GOptionContext
*context
, GOptionEntry options
[],
1132 #elif defined HAVE_POPT
1133 poptContext poptCtx
, struct poptOption options
[],
1135 GSList
**files
, char **export_file_name
,
1136 char **export_file_format
, char **size
,
1137 char **show_layers
, gboolean
* nosplash
)
1139 #if defined HAVE_POPT && !USE_GOPTION
1141 poptCtx
= poptGetContext(PACKAGE
, argc
, (const char **)argv
, options
, 0);
1142 poptSetOtherOptionHelp(poptCtx
, _("[OPTION...] [FILE...]"));
1144 if((rc
= poptGetNextOpt(poptCtx
)) < -1) {
1145 fprintf(stderr
,_("Error on option %s: %s.\nRun '%s --help' to see a full list of available command line options.\n"),
1146 poptBadOption(poptCtx
, 0),
1152 poptPrintHelp(poptCtx
, stderr
, 0);
1158 #if defined HAVE_POPT && !USE_GOPTION
1159 while (poptPeekArg(poptCtx
)) {
1160 char *in_file_name
= (char *)poptGetArg(poptCtx
);
1161 if (*in_file_name
!= '\0')
1162 *files
= g_slist_append(*files
, in_file_name
);
1164 poptFreeContext(poptCtx
);
1166 GError
*error
= NULL
;
1169 context
= g_option_context_new(_("[FILE...]"));
1170 g_option_context_add_main_entries (context
, options
, GETTEXT_PACKAGE
);
1171 # if GTK_CHECK_VERSION(2,5,7)
1172 /* at least Gentoo was providing GLib-2.6 but Gtk+-2.4.14 */
1173 g_option_context_add_group (context
, gtk_get_option_group (FALSE
));
1175 if (!g_option_context_parse (context
, &argc
, &argv
, &error
)) {
1176 if (error
) { /* IMO !error here is a bug upstream, triggered with --gdk-debug=updates */
1177 g_print ("%s", error
->message
);
1178 g_error_free (error
);
1180 g_print ("Invalid option?");
1183 g_option_context_free(context
);
1187 g_option_context_free(context
);
1190 for (i
= 1; i
< argc
; i
++) {
1191 if (!g_file_test (argv
[i
], G_FILE_TEST_IS_REGULAR
)) {
1192 g_print (_("'%s' not found!\n"), argv
[i
]);
1193 g_option_context_free(context
);
1196 *files
= g_slist_append(*files
, argv
[i
]);
1198 g_option_context_free(context
);
1202 for (i
=1; i
<argc
; i
++) {
1203 char *in_file_name
= argv
[i
]; /* unless it's an option... */
1205 if (0==strcmp(argv
[i
],"-t")) {
1208 *export_file_format
= argv
[i
];
1211 } else if (0 == strcmp(argv
[i
],"-e")) {
1214 *export_file_name
= argv
[i
];
1217 } else if (0 == strcmp(argv
[i
],"-s")) {
1223 } else if (0 == strcmp(argv
[i
],"-L")) {
1226 *show_layers
= argv
[i
];
1229 } else if (0 == strcmp(argv
[i
],"-n")) {
1233 *files
= g_slist_append(*files
, in_file_name
);
1237 if (*export_file_name
|| *export_file_format
|| *size
)
1238 dia_is_interactive
= FALSE
;
1242 handle_all_diagrams(GSList
*files
, char *export_file_name
,
1243 char *export_file_format
, char *size
, char *show_layers
)
1245 GSList
*node
= NULL
;
1246 gboolean made_conversions
= FALSE
;
1248 for (node
= files
; node
; node
= node
->next
) {
1250 handle_initial_diagram(node
->data
, export_file_name
,
1251 export_file_format
, size
, show_layers
);
1253 return made_conversions
;
1256 /* --credits option. Added by Andrew Ferrier.
1258 Hopefully we're not ignoring anything too crucial by
1259 quitting directly after the credits.
1261 The phrasing of the English here might need changing
1262 if we switch from plural to non-plural (say, only
1266 print_credits(gboolean credits
)
1270 const gint nauthors
= (sizeof(authors
) / sizeof(authors
[0])) - 1;
1271 const gint ndocumentors
= (sizeof(documentors
) / sizeof(documentors
[0])) - 1;
1273 g_print(_("The original author of Dia was:\n\n"));
1274 for (i
= 0; i
< NUMBER_OF_ORIG_AUTHORS
; i
++) {
1275 g_print("%s\n", authors
[i
]);
1278 g_print(_("\nThe current maintainers of Dia are:\n\n"));
1279 for (i
= NUMBER_OF_ORIG_AUTHORS
; i
< NUMBER_OF_ORIG_AUTHORS
+ NUMBER_OF_MAINTAINERS
; i
++) {
1280 g_print("%s\n", authors
[i
]);
1283 g_print(_("\nOther authors are:\n\n"));
1284 for (i
= NUMBER_OF_ORIG_AUTHORS
+ NUMBER_OF_MAINTAINERS
; i
< nauthors
; i
++) {
1285 g_print("%s\n", authors
[i
]);
1288 g_print(_("\nDia is documented by:\n\n"));
1289 for (i
= 0; i
< ndocumentors
; i
++) {
1290 g_print("%s\n", documentors
[i
]);
1297 /* parses a string of the form "[0-9]*x[0-9]*" and transforms it into
1298 two long values width and height. */
1300 parse_size(gchar
*size
, long *width
, long *height
)
1303 gchar
** array
= g_strsplit(size
, "x", 3);
1304 *width
= (array
[0])? strtol(array
[0], NULL
, 10): 0;
1305 *height
= (array
[1])? strtol(array
[1], NULL
, 10): 0;
1314 int app_is_embedded(void)