X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fmain.cpp;h=a1b21cc4d0f65b1cf1fb3ad2cba4787ab2648ec0;hb=9dc68827cbd515262ecb8d5ae8547d9e82c72e00;hp=67c5a84e87f43faf521ddbcc7a60bfc70c723fd1;hpb=246b1e7cbda3fac6085b27ad0f568928d6785a72;p=inkscape.git diff --git a/src/main.cpp b/src/main.cpp index 67c5a84e8..a1b21cc4d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,3 @@ -#define __MAIN_C__ - /** \file * Inkscape - an ambitious vector drawing program * @@ -15,6 +13,8 @@ * Pawel Palucha * Bryce Harrington * ... and various people who have worked with various projects + * Jon A. Cruz + * Abhishek Sharma * * Copyright (C) 1999-2004 authors * Copyright (C) 2001-2002 Ximian, Inc. @@ -28,13 +28,18 @@ #endif #include "path-prefix.h" +// This has to be included prior to anything that includes setjmp.h, it croaks otherwise +#include + #include #ifdef HAVE_IEEEFP_H #include #endif -#include +#include +#include #include +#include #include #ifndef POPT_TABLEEND @@ -42,7 +47,10 @@ #endif /* Not def: POPT_TABLEEND */ #include +#include +#include #include +#include #include #include #include @@ -50,6 +58,10 @@ #include "gc-core.h" +#ifdef AND +#undef AND +#endif + #include "macros.h" #include "file.h" #include "document.h" @@ -66,8 +78,7 @@ #include "svg/stringstream.h" #include "inkscape-private.h" -#include "inkscape-stock.h" -#include "inkscape_version.h" +#include "inkscape-version.h" #include "sp-namedview.h" #include "sp-guide.h" @@ -80,21 +91,18 @@ #include "debug/log-display-config.h" #include "helper/png-write.h" +#include "helper/geom.h" #include #include #include #include +#include #ifdef WIN32 -//#define REPLACEARGS_ANSI -//#define REPLACEARGS_DEBUG - #include "registrytool.h" - #include "extension/internal/win32.h" using Inkscape::Extension::Internal::PrintWin32; - #endif // WIN32 #include "extension/init.h" @@ -106,9 +114,11 @@ using Inkscape::Extension::Internal::PrintWin32; #define bind_textdomain_codeset(p,c) #endif -#include "application/application.h" - #include "main-cmdlineact.h" +#include "widgets/icon.h" +#include "ui/widget/panel.h" + +#include enum { SP_ARG_NONE, @@ -120,7 +130,7 @@ enum { SP_ARG_EXPORT_DPI, SP_ARG_EXPORT_AREA, SP_ARG_EXPORT_AREA_DRAWING, - SP_ARG_EXPORT_AREA_CANVAS, + SP_ARG_EXPORT_AREA_PAGE, SP_ARG_EXPORT_AREA_SNAP, SP_ARG_EXPORT_WIDTH, SP_ARG_EXPORT_HEIGHT, @@ -133,19 +143,20 @@ enum { SP_ARG_EXPORT_PS, SP_ARG_EXPORT_EPS, SP_ARG_EXPORT_PDF, + SP_ARG_EXPORT_LATEX, #ifdef WIN32 SP_ARG_EXPORT_EMF, #endif //WIN32 SP_ARG_EXPORT_TEXT_TO_PATH, - SP_ARG_EXPORT_FONT, - SP_ARG_EXPORT_BBOX_PAGE, + SP_ARG_EXPORT_IGNORE_FILTERS, SP_ARG_EXTENSIONDIR, - SP_ARG_FIT_PAGE_TO_DRAWING, SP_ARG_QUERY_X, SP_ARG_QUERY_Y, SP_ARG_QUERY_WIDTH, SP_ARG_QUERY_HEIGHT, + SP_ARG_QUERY_ALL, SP_ARG_QUERY_ID, + SP_ARG_SHELL, SP_ARG_VERSION, SP_ARG_VACUUM_DEFS, SP_ARG_VERB_LIST, @@ -157,20 +168,21 @@ enum { int sp_main_gui(int argc, char const **argv); int sp_main_console(int argc, char const **argv); static void sp_do_export_png(SPDocument *doc); -static void do_export_ps(SPDocument* doc, gchar const* uri, char const *mime); -static void do_export_pdf(SPDocument* doc, gchar const* uri, char const *mime); +static void do_export_ps_pdf(SPDocument* doc, gchar const* uri, char const *mime); #ifdef WIN32 static void do_export_emf(SPDocument* doc, gchar const* uri, char const *mime); #endif //WIN32 -static void do_query_dimension (SPDocument *doc, bool extent, NR::Dim2 const axis, const gchar *id); - +static void do_query_dimension (SPDocument *doc, bool extent, Geom::Dim2 const axis, const gchar *id); +static void do_query_all (SPDocument *doc); +static void do_query_all_recurse (SPObject *o); static gchar *sp_global_printer = NULL; static gchar *sp_export_png = NULL; static gchar *sp_export_dpi = NULL; static gchar *sp_export_area = NULL; static gboolean sp_export_area_drawing = FALSE; -static gboolean sp_export_area_canvas = FALSE; +static gboolean sp_export_area_page = FALSE; +static gboolean sp_export_latex = FALSE; static gchar *sp_export_width = NULL; static gchar *sp_export_height = NULL; static gchar *sp_export_id = NULL; @@ -187,20 +199,64 @@ static gchar *sp_export_pdf = NULL; static gchar *sp_export_emf = NULL; #endif //WIN32 static gboolean sp_export_text_to_path = FALSE; +static gboolean sp_export_ignore_filters = FALSE; static gboolean sp_export_font = FALSE; -static gboolean sp_export_bbox_page = FALSE; static gboolean sp_query_x = FALSE; static gboolean sp_query_y = FALSE; static gboolean sp_query_width = FALSE; static gboolean sp_query_height = FALSE; +static gboolean sp_query_all = FALSE; static gchar *sp_query_id = NULL; -static int sp_new_gui = FALSE; +static gboolean sp_shell = FALSE; static gboolean sp_vacuum_defs = FALSE; static gchar *sp_export_png_utf8 = NULL; static gchar *sp_export_svg_utf8 = NULL; static gchar *sp_global_printer_utf8 = NULL; + +/** + * Reset variables to default values. + */ +static void resetCommandlineGlobals() { + sp_global_printer = NULL; + sp_export_png = NULL; + sp_export_dpi = NULL; + sp_export_area = NULL; + sp_export_area_drawing = FALSE; + sp_export_area_page = FALSE; + sp_export_latex = FALSE; + sp_export_width = NULL; + sp_export_height = NULL; + sp_export_id = NULL; + sp_export_background = NULL; + sp_export_background_opacity = NULL; + sp_export_area_snap = FALSE; + sp_export_use_hints = FALSE; + sp_export_id_only = FALSE; + sp_export_svg = NULL; + sp_export_ps = NULL; + sp_export_eps = NULL; + sp_export_pdf = NULL; +#ifdef WIN32 + sp_export_emf = NULL; +#endif //WIN32 + sp_export_text_to_path = FALSE; + sp_export_ignore_filters = FALSE; + sp_export_font = FALSE; + sp_query_x = FALSE; + sp_query_y = FALSE; + sp_query_width = FALSE; + sp_query_height = FALSE; + sp_query_all = FALSE; + sp_query_id = NULL; + sp_vacuum_defs = FALSE; + + sp_export_png_utf8 = NULL; + sp_export_svg_utf8 = NULL; + sp_global_printer_utf8 = NULL; +} + #ifdef WIN32 static bool replaceArgs( int& argc, char**& argv ); #endif @@ -238,22 +294,22 @@ struct poptOption options[] = { {"export-dpi", 'd', POPT_ARG_STRING, &sp_export_dpi, SP_ARG_EXPORT_DPI, - N_("The resolution used for exporting SVG into bitmap (default 90)"), + N_("Resolution for exporting to bitmap and for rasterization of filters in PS/EPS/PDF (default 90)"), N_("DPI")}, {"export-area", 'a', POPT_ARG_STRING, &sp_export_area, SP_ARG_EXPORT_AREA, - N_("Exported area in SVG user units (default is the canvas; 0,0 is lower-left corner)"), + N_("Exported area in SVG user units (default is the page; 0,0 is lower-left corner)"), N_("x0:y0:x1:y1")}, {"export-area-drawing", 'D', POPT_ARG_NONE, &sp_export_area_drawing, SP_ARG_EXPORT_AREA_DRAWING, - N_("Exported area is the entire drawing (not canvas)"), + N_("Exported area is the entire drawing (not page)"), NULL}, - {"export-area-canvas", 'C', - POPT_ARG_NONE, &sp_export_area_canvas, SP_ARG_EXPORT_AREA_CANVAS, - N_("Exported area is the entire canvas"), + {"export-area-page", 'C', + POPT_ARG_NONE, &sp_export_area_page, SP_ARG_EXPORT_AREA_PAGE, + N_("Exported area is the entire page"), NULL}, {"export-area-snap", 0, @@ -318,6 +374,11 @@ struct poptOption options[] = { N_("Export document to a PDF file"), N_("FILENAME")}, + {"export-latex", 0, + POPT_ARG_NONE, &sp_export_latex, SP_ARG_EXPORT_LATEX, + N_("Export PDF/PS/EPS without text. Besides the PDF/PS/EPS, a LaTeX file is exported, putting the text on top of the PDF/PS/EPS file. Include the result in LaTeX like: \\input{latexfile.tex}"), + NULL}, + #ifdef WIN32 {"export-emf", 'M', POPT_ARG_STRING, &sp_export_emf, SP_ARG_EXPORT_EMF, @@ -327,17 +388,12 @@ struct poptOption options[] = { {"export-text-to-path", 'T', POPT_ARG_NONE, &sp_export_text_to_path, SP_ARG_EXPORT_TEXT_TO_PATH, - N_("Convert text object to paths on export (EPS)"), - NULL}, - - {"export-embed-fonts", 'F', - POPT_ARG_NONE, &sp_export_font, SP_ARG_EXPORT_FONT, - N_("Embed fonts on export (Type 1 only) (EPS)"), + N_("Convert text object to paths on export (PS, EPS, PDF)"), NULL}, - {"export-bbox-page", 'B', - POPT_ARG_NONE, &sp_export_bbox_page, SP_ARG_EXPORT_BBOX_PAGE, - N_("Export files with the bounding box set to the page size (EPS)"), + {"export-ignore-filters", 0, + POPT_ARG_NONE, &sp_export_ignore_filters, SP_ARG_EXPORT_IGNORE_FILTERS, + N_("Render filtered objects without filters, instead of rasterizing (PS, EPS, PDF)"), NULL}, {"query-x", 'X', @@ -364,6 +420,11 @@ struct poptOption options[] = { N_("Query the height of the drawing or, if specified, of the object with --query-id"), NULL}, + {"query-all", 'S', + POPT_ARG_NONE, &sp_query_all, SP_ARG_QUERY_ALL, + N_("List id,x,y,w,h for all objects"), + NULL}, + {"query-id", 'I', POPT_ARG_STRING, &sp_query_id, SP_ARG_QUERY_ID, N_("The ID of the object whose dimensions are queried"), @@ -395,12 +456,130 @@ struct poptOption options[] = { N_("Object ID to select when Inkscape opens."), N_("OBJECT-ID")}, + {"shell", 0, + POPT_ARG_NONE, &sp_shell, SP_ARG_SHELL, + N_("Start Inkscape in interactive shell mode."), + NULL}, + POPT_AUTOHELP POPT_TABLEEND }; static bool needToRecodeParams = true; -gchar* blankParam = ""; +gchar * blankParam = g_strdup(""); + + + +#ifdef WIN32 +/** + * Set up the PATH and PYTHONPATH environment variables on Windows + * @param exe Inkscape executable directory in UTF-8 + */ +static void _win32_set_inkscape_env(gchar const *exe) +{ + gchar const *path = g_getenv("PATH"); + gchar const *pythonpath = g_getenv("PYTHONPATH"); + + gchar *python = g_build_filename(exe, "python", NULL); + gchar *scripts = g_build_filename(exe, "python", "Scripts", NULL); + gchar *perl = g_build_filename(exe, "python", NULL); + gchar *pythonlib = g_build_filename(exe, "python", "Lib", NULL); + gchar *pythondll = g_build_filename(exe, "python", "DLLs", NULL); + + // Python 2.x needs short paths in PYTHONPATH. + // Otherwise it doesn't work when Inkscape is installed in Unicode directories. + // g_win32_locale_filename_from_utf8 is the GLib wrapper for GetShortPathName. + // Remove this once we move to Python 3.0. + gchar *python_s = g_win32_locale_filename_from_utf8(python); + gchar *pythonlib_s = g_win32_locale_filename_from_utf8(pythonlib); + gchar *pythondll_s = g_win32_locale_filename_from_utf8(pythondll); + + gchar *new_path; + gchar *new_pythonpath; + if (path) { + new_path = g_strdup_printf("%s;%s;%s;%s;%s", exe, python, scripts, perl, path); + } else { + new_path = g_strdup_printf("%s;%s;%s;%s", exe, python, scripts, perl); + } + if (pythonpath) { + new_pythonpath = g_strdup_printf("%s;%s;%s;%s", + python_s, pythonlib_s, pythondll_s, pythonpath); + } else { + new_pythonpath = g_strdup_printf("%s;%s;%s", + python_s, pythonlib_s, pythondll_s); + } + + g_setenv("PATH", new_path, TRUE); + g_setenv("PYTHONPATH", new_pythonpath, TRUE); + + /* + printf("PATH = %s\n\n", g_getenv("PATH")); + printf("PYTHONPATH = %s\n\n", g_getenv("PYTHONPATH")); + + gchar *p = g_find_program_in_path("python"); + if (p) { + printf("python in %s\n\n", p); + g_free(p); + } else { + printf("python not found\n\n"); + }*/ + + g_free(python); + g_free(scripts); + g_free(perl); + g_free(pythonlib); + g_free(pythondll); + + g_free(python_s); + g_free(pythonlib_s); + g_free(pythondll_s); + + g_free(new_path); + g_free(new_pythonpath); +} +#endif + +static void set_extensions_env() +{ + gchar const *pythonpath = g_getenv("PYTHONPATH"); + gchar *extdir; + gchar *new_pythonpath; + +#ifdef WIN32 + extdir = g_win32_locale_filename_from_utf8(INKSCAPE_EXTENSIONDIR); +#else + extdir = g_strdup(INKSCAPE_EXTENSIONDIR); +#endif + + // On some platforms, INKSCAPE_EXTENSIONDIR is not absolute, + // but relative to the directory that contains the Inkscape executable. + // Since we spawn Python chdir'ed into the script's directory, + // we need to obtain the absolute path here. + if (!g_path_is_absolute(extdir)) { + gchar *curdir = g_get_current_dir(); + gchar *extdir_new = g_build_filename(curdir, extdir, NULL); + g_free(extdir); + g_free(curdir); + extdir = extdir_new; + } + + if (pythonpath) { + new_pythonpath = g_strdup_printf("%s" G_SEARCHPATH_SEPARATOR_S "%s", + extdir, pythonpath); + g_free(extdir); + } else { + new_pythonpath = extdir; + } + + g_setenv("PYTHONPATH", new_pythonpath, TRUE); + g_free(new_pythonpath); + //printf("PYTHONPATH = %s\n", g_getenv("PYTHONPATH")); +} + +/** + * This is the classic main() entry point of the program, though on some + * architectures it might be called by something else. + */ int main(int argc, char **argv) { @@ -411,34 +590,54 @@ main(int argc, char **argv) fpsetmask(fpgetmask() & ~(FP_X_DZ | FP_X_INV)); #endif -#ifdef ENABLE_NLS #ifdef WIN32 - RegistryTool rt; - rt.setPathInfo(); - gchar *pathBuf = g_strconcat(g_path_get_dirname(argv[0]), "\\", PACKAGE_LOCALE_DIR, NULL); - bindtextdomain(GETTEXT_PACKAGE, pathBuf); - g_free(pathBuf); -#else -#ifdef ENABLE_BINRELOC + gchar *exedir = g_strdup(win32_getExePath().data()); + _win32_set_inkscape_env(exedir); + +# ifdef ENABLE_NLS + // obtain short path to executable dir and pass it + // to bindtextdomain (it doesn't understand UTF-8) + gchar *shortexedir = g_win32_locale_filename_from_utf8(exedir); + gchar *localepath = g_build_filename(shortexedir, PACKAGE_LOCALE_DIR, NULL); + bindtextdomain(GETTEXT_PACKAGE, localepath); + g_free(shortexedir); + g_free(localepath); +# endif + g_free(exedir); + + // Don't touch the registry (works fine without it) for Inkscape Portable + gchar const *val = g_getenv("INKSCAPE_PORTABLE_PROFILE_DIR"); + if (!val) { + RegistryTool rt; + rt.setPathInfo(); + } +#elif defined(ENABLE_NLS) +# ifdef ENABLE_BINRELOC bindtextdomain(GETTEXT_PACKAGE, BR_LOCALEDIR("")); -#else +# else bindtextdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR); +# endif #endif -#endif - // Allow the user to override the locale directory by setting + + // the bit below compiles regardless of platform +#ifdef ENABLE_NLS + // Allow the user to override the locale directory by setting // the environment variable INKSCAPE_LOCALEDIR. - char *inkscape_localedir = getenv("INKSCAPE_LOCALEDIR"); + char const *inkscape_localedir = g_getenv("INKSCAPE_LOCALEDIR"); if (inkscape_localedir != NULL) { bindtextdomain(GETTEXT_PACKAGE, inkscape_localedir); } -#endif + // common setup bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); - -#ifdef ENABLE_NLS textdomain(GETTEXT_PACKAGE); #endif + set_extensions_env(); + + // Prevents errors like "Unable to wrap GdkPixbuf..." (in nr-filter-image.cpp for example) + Gtk::Main::init_gtkmm_internals(); + LIBXML_TEST_VERSION Inkscape::GC::init(); @@ -446,21 +645,10 @@ main(int argc, char **argv) Inkscape::Debug::Logger::init(); gboolean use_gui; + #ifndef WIN32 - use_gui = (getenv("DISPLAY") != NULL); + use_gui = (g_getenv("DISPLAY") != NULL); #else - /* - Set the current directory to the directory of the - executable. This seems redundant, but is needed for - when inkscape.exe is executed from another directory. - We use relative paths on win32. - HKCR\svgfile\shell\open\command is a good example - */ - /// \todo FIXME BROKEN - non-UTF-8 sneaks in here. - char *homedir = g_path_get_dirname(argv[0]); - SetCurrentDirectory(homedir); - g_free(homedir); - use_gui = TRUE; #endif /* Test whether with/without GUI is forced */ @@ -472,19 +660,20 @@ main(int argc, char **argv) || !strcmp(argv[i], "-e") || !strncmp(argv[i], "--export-png", 12) || !strcmp(argv[i], "-l") - || !strncmp(argv[i], "--export-plain-svg", 12) + || !strncmp(argv[i], "--export-plain-svg", 18) || !strcmp(argv[i], "-i") || !strncmp(argv[i], "--export-area-drawing", 21) || !strcmp(argv[i], "-D") - || !strncmp(argv[i], "--export-area-canvas", 20) + || !strncmp(argv[i], "--export-area-page", 18) || !strcmp(argv[i], "-C") - || !strncmp(argv[i], "--export-id", 12) + || !strncmp(argv[i], "--export-id", 11) || !strcmp(argv[i], "-P") || !strncmp(argv[i], "--export-ps", 11) || !strcmp(argv[i], "-E") || !strncmp(argv[i], "--export-eps", 12) || !strcmp(argv[i], "-A") || !strncmp(argv[i], "--export-pdf", 12) + || !strncmp(argv[i], "--export-latex", 14) #ifdef WIN32 || !strcmp(argv[i], "-M") || !strncmp(argv[i], "--export-emf", 12) @@ -493,11 +682,14 @@ main(int argc, char **argv) || !strncmp(argv[i], "--query-width", 13) || !strcmp(argv[i], "-H") || !strncmp(argv[i], "--query-height", 14) + || !strcmp(argv[i], "-S") + || !strncmp(argv[i], "--query-all", 11) || !strcmp(argv[i], "-X") - || !strncmp(argv[i], "--query-x", 13) + || !strncmp(argv[i], "--query-x", 9) || !strcmp(argv[i], "-Y") - || !strncmp(argv[i], "--query-y", 14) + || !strncmp(argv[i], "--query-y", 9) || !strcmp(argv[i], "--vacuum-defs") + || !strcmp(argv[i], "--shell") ) { /* main_console handles any exports -- not the gui */ @@ -519,12 +711,20 @@ main(int argc, char **argv) } #endif // WIN32 - /// \todo Should this be a static object (see inkscape.cpp)? - Inkscape::NSApplication::Application app(argc, argv, use_gui, sp_new_gui); + int retcode; + + if (use_gui) { + retcode = sp_main_gui(argc, (const char **) argv); + } else { + retcode = sp_main_console(argc, (const char **) argv); + } - return app.run(); + return retcode; } + + + void fixupSingleFilename( gchar **orig, gchar **spare ) { if ( orig && *orig && **orig ) { @@ -541,6 +741,8 @@ void fixupSingleFilename( gchar **orig, gchar **spare ) } } + + GSList *fixupFilenameEncoding( GSList* fl ) { GSList *newFl = NULL; @@ -641,8 +843,8 @@ int sp_common_main( int argc, char const **argv, GSList **flDest ) } static void -snooper(GdkEvent *event, gpointer data) { - if(inkscape_mapalt()) /* returns the map of the keyboard modifier to map to Alt, zero if no mapping */ +snooper(GdkEvent *event, gpointer /*data*/) { + if (inkscape_mapalt()) /* returns the map of the keyboard modifier to map to Alt, zero if no mapping */ { GdkModifierType mapping=(GdkModifierType)inkscape_mapalt(); switch (event->type) { @@ -650,24 +852,84 @@ snooper(GdkEvent *event, gpointer data) { if(event->motion.state & mapping) { event->motion.state|=GDK_MOD1_MASK; } - break; + break; case GDK_BUTTON_PRESS: if(event->button.state & mapping) { event->button.state|=GDK_MOD1_MASK; } - break; + break; case GDK_KEY_PRESS: if(event->key.state & mapping) { event->key.state|=GDK_MOD1_MASK; } - break; + break; default: break; } } + + if (inkscape_trackalt()) { + // MacOS X with X11 has some problem with the default + // xmodmapping. A ~/.xmodmap solution does not work reliably due + // to the way we package our executable in a .app that can launch + // X11 or use an already-running X11. The same problem has been + // reported on Linux but there is no .app/X11 to get in the way + // of ~/.xmodmap fixes. So we make this a preference. + // + // For some reason, Gdk senses changes in Alt (Mod1) state for + // many message types, but not for keystrokes! So this ugly hack + // tracks what the state of Alt-pressing is, and ensures + // GDK_MOD1_MASK is in the event->key.state as appropriate. + // + static gboolean altL_pressed = FALSE; + static gboolean altR_pressed = FALSE; + static gboolean alt_pressed = FALSE; + guint get_group0_keyval(GdkEventKey* event); + guint keyval = 0; + switch (event->type) { + case GDK_MOTION_NOTIFY: + alt_pressed = TRUE && (event->motion.state & GDK_MOD1_MASK); + break; + case GDK_BUTTON_PRESS: + alt_pressed = TRUE && (event->button.state & GDK_MOD1_MASK); + break; + case GDK_KEY_PRESS: + keyval = get_group0_keyval(&event->key); + if (keyval == GDK_Alt_L) altL_pressed = TRUE; + if (keyval == GDK_Alt_R) altR_pressed = TRUE; + alt_pressed = alt_pressed || altL_pressed || altR_pressed; + alt_pressed = alt_pressed || (event->button.state & GDK_MOD1_MASK); + if (alt_pressed) + event->key.state |= GDK_MOD1_MASK; + else + event->key.state &= ~GDK_MOD1_MASK; + break; + case GDK_KEY_RELEASE: + keyval = get_group0_keyval(&event->key); + if (keyval == GDK_Alt_L) altL_pressed = FALSE; + if (keyval == GDK_Alt_R) altR_pressed = FALSE; + if (!altL_pressed && !altR_pressed) + alt_pressed = FALSE; + break; + default: + break; + } + //printf("alt_pressed: %s\n", alt_pressed? "+" : "-"); + } + gtk_main_do_event (event); } +static std::vector getDirectorySet(const gchar* userDir, const gchar* const * systemDirs) { + std::vector listing; + listing.push_back(userDir); + for ( const char* const* cur = systemDirs; *cur; cur++ ) + { + listing.push_back(*cur); + } + return listing; +} + int sp_main_gui(int argc, char const **argv) { @@ -677,19 +939,33 @@ sp_main_gui(int argc, char const **argv) int retVal = sp_common_main( argc, argv, &fl ); g_return_val_if_fail(retVal == 0, 1); - inkscape_gtk_stock_init(); + // Add possible icon entry directories + std::vector dataDirs = getDirectorySet( g_get_user_data_dir(), + g_get_system_data_dirs() ); + for (std::vector::iterator it = dataDirs.begin(); it != dataDirs.end(); ++it) + { + std::vector listing; + listing.push_back(*it); + listing.push_back("inkscape"); + listing.push_back("icons"); + Glib::ustring dir = Glib::build_filename(listing); + gtk_icon_theme_append_search_path(gtk_icon_theme_get_default(), dir.c_str()); + } - gdk_event_handler_set((GdkEventFunc)snooper, NULL, NULL); + // Add our icon directory to the search path for icon theme lookups. + gchar *usericondir = profile_path("icons"); + gtk_icon_theme_append_search_path(gtk_icon_theme_get_default(), usericondir); + gtk_icon_theme_append_search_path(gtk_icon_theme_get_default(), INKSCAPE_PIXMAPDIR); + g_free(usericondir); + gdk_event_handler_set((GdkEventFunc)snooper, NULL, NULL); Inkscape::Debug::log_display_config(); - /* Set default icon */ - gchar *filename = (gchar *) g_build_filename (INKSCAPE_APPICONDIR, "inkscape.png", NULL); - if (Inkscape::IO::file_test(filename, (GFileTest)(G_FILE_TEST_IS_REGULAR | G_FILE_TEST_IS_SYMLINK))) { - gtk_window_set_default_icon_from_file(filename, NULL); - } - g_free (filename); - filename = 0; + // Set default window icon. Obeys the theme. + gtk_window_set_default_icon_name("inkscape"); + // Do things that were previously in inkscape_gtk_stock_init(). + sp_icon_get_phys_size(GTK_ICON_SIZE_MENU); + Inkscape::UI::Widget::Panel::prep(); gboolean create_new = TRUE; @@ -717,53 +993,46 @@ sp_main_gui(int argc, char const **argv) return 0; } -int -sp_main_console(int argc, char const **argv) +/** + * Process file list + */ +void sp_process_file_list(GSList *fl) { - /* We are started in text mode */ - - /* Do this g_type_init(), so that we can use Xft/Freetype2 (Pango) - * in a non-Gtk environment. Used in libnrtype's - * FontInstance.cpp and FontFactory.cpp. - * http://mail.gnome.org/archives/gtk-list/2003-December/msg00063.html - */ - g_type_init(); - char **argv2 = const_cast(argv); - gtk_init_check( &argc, &argv2 ); - //setlocale(LC_ALL, ""); - - GSList *fl = NULL; - int retVal = sp_common_main( argc, argv, &fl ); - g_return_val_if_fail(retVal == 0, 1); - - if (fl == NULL) { - g_print("Nothing to do!\n"); - exit(0); - } - - inkscape_application_init(argv[0], false); - while (fl) { - SPDocument *doc; + const gchar *filename = (gchar *)fl->data; + + SPDocument *doc = NULL; + try { + doc = Inkscape::Extension::open(NULL, filename); + } catch (Inkscape::Extension::Input::no_extension_found &e) { + doc = NULL; + } catch (Inkscape::Extension::Input::open_failed &e) { + doc = NULL; + } - doc = Inkscape::Extension::open(NULL, (gchar *)fl->data); if (doc == NULL) { - doc = Inkscape::Extension::open(Inkscape::Extension::db.get(SP_MODULE_KEY_INPUT_SVG), (gchar *)fl->data); + try { + doc = Inkscape::Extension::open(Inkscape::Extension::db.get(SP_MODULE_KEY_INPUT_SVG), filename); + } catch (Inkscape::Extension::Input::no_extension_found &e) { + doc = NULL; + } catch (Inkscape::Extension::Input::open_failed &e) { + doc = NULL; + } } if (doc == NULL) { - g_warning("Specified document %s cannot be opened (is it valid SVG file?)", (gchar *) fl->data); + g_warning("Specified document %s cannot be opened (does not exist or not a valid SVG file)", filename); } else { if (sp_vacuum_defs) { - vacuum_document(doc); + doc->vacuumDocument(); } if (sp_vacuum_defs && !sp_export_svg) { // save under the name given in the command line - sp_repr_save_file(doc->rdoc, (gchar *)fl->data, SP_SVG_NS_URI); + sp_repr_save_file(doc->rdoc, filename, SP_SVG_NS_URI); } if (sp_global_printer) { sp_print_document_to_file(doc, sp_global_printer); } - if (sp_export_png || sp_export_id || sp_export_area_drawing) { + if (sp_export_png || (sp_export_id && sp_export_use_hints)) { sp_do_export_png(doc); } if (sp_export_svg) { @@ -771,40 +1040,147 @@ sp_main_console(int argc, char const **argv) Inkscape::XML::Node *repr; rdoc = sp_repr_document_new("svg:svg"); repr = rdoc->root(); - repr = sp_document_root(doc)->updateRepr(repr, SP_OBJECT_WRITE_BUILD); - sp_repr_save_file(repr->document(), sp_export_svg, SP_SVG_NS_URI); + repr = doc->getRoot()->updateRepr(rdoc, repr, SP_OBJECT_WRITE_BUILD); + sp_repr_save_rebased_file(repr->document(), sp_export_svg, SP_SVG_NS_URI, + doc->getBase(), sp_export_svg); } if (sp_export_ps) { - do_export_ps(doc, sp_export_ps, "image/x-postscript"); + do_export_ps_pdf(doc, sp_export_ps, "image/x-postscript"); } if (sp_export_eps) { - do_export_ps(doc, sp_export_eps, "image/x-e-postscript"); + do_export_ps_pdf(doc, sp_export_eps, "image/x-e-postscript"); } if (sp_export_pdf) { - do_export_pdf(doc, sp_export_pdf, "application/pdf"); + do_export_ps_pdf(doc, sp_export_pdf, "application/pdf"); } #ifdef WIN32 if (sp_export_emf) { do_export_emf(doc, sp_export_emf, "image/x-emf"); } #endif //WIN32 - if (sp_query_width || sp_query_height) { - do_query_dimension (doc, true, sp_query_width? NR::X : NR::Y, sp_query_id); + if (sp_query_all) { + do_query_all (doc); + } else if (sp_query_width || sp_query_height) { + do_query_dimension (doc, true, sp_query_width? Geom::X : Geom::Y, sp_query_id); } else if (sp_query_x || sp_query_y) { - do_query_dimension (doc, false, sp_query_x? NR::X : NR::Y, sp_query_id); + do_query_dimension (doc, false, sp_query_x? Geom::X : Geom::Y, sp_query_id); } - } + delete doc; + } fl = g_slist_remove(fl, fl->data); } +} + +/** + * Run the application as an interactive shell, parsing command lines from stdin + * Returns -1 on error. + */ +int sp_main_shell(char const* command_name) +{ + int retval = 0; + + const unsigned int buffer_size = 4096; + gchar *command_line = g_strnfill(buffer_size, 0); + g_strlcpy(command_line, command_name, buffer_size); + gsize offset = g_strlcat(command_line, " ", buffer_size); + gsize sizeLeft = buffer_size - offset; + gchar *useme = command_line + offset; + + fprintf(stdout, "Inkscape %s interactive shell mode. Type 'quit' to quit.\n", Inkscape::version_string); + fflush(stdout); + char* linedata = 0; + do { + fprintf(stdout, ">"); + fflush(stdout); + if ((linedata = fgets(useme, sizeLeft, stdin))) { + size_t len = strlen(useme); + if ( (len >= sizeLeft - 1) || (useme[len - 1] != '\n') ) { + fprintf(stdout, "ERROR: Command line too long\n"); + // Consume rest of line + retval = -1; // If the while loop completes, this remains -1 + while (fgets(useme, sizeLeft, stdin) && retval) { + len = strlen(command_line); + if ( (len < buffer_size) && (command_line[len-1] == '\n') ) { + retval = 0; + } + } + } else { + useme[--len] = '\0'; // Strip newline + if (useme[len - 1] == '\r') { + useme[--len] = '\0'; + } + if ( strcmp(useme, "quit") == 0 ) { + // Time to quit + fflush(stdout); + linedata = 0; // mark for exit + } else if ( len < 1 ) { + // blank string. Do nothing. + } else { + GError* parseError = 0; + gchar** argv = 0; + gint argc = 0; + if ( g_shell_parse_argv(command_line, &argc, &argv, &parseError) ) { + poptContext ctx = poptGetContext(NULL, argc, const_cast(argv), options, 0); + poptSetOtherOptionHelp(ctx, _("[OPTIONS...] [FILE...]\n\nAvailable options:")); + if ( ctx ) { + GSList *fl = sp_process_args(ctx); + sp_process_file_list(fl); + poptFreeContext(ctx); + } else { + retval = 1; // not sure why. But this was the previous return value + } + resetCommandlineGlobals(); + g_strfreev(argv); + } else { + g_warning("Cannot parse commandline: %s", useme); + } + } + } + } // if (linedata... + } while (linedata && (retval == 0)); + + g_free(command_line); + return retval; +} - inkscape_unref(); +int sp_main_console(int argc, char const **argv) +{ + /* We are started in text mode */ + + /* Do this g_type_init(), so that we can use Xft/Freetype2 (Pango) + * in a non-Gtk environment. Used in libnrtype's + * FontInstance.cpp and FontFactory.cpp. + * http://mail.gnome.org/archives/gtk-list/2003-December/msg00063.html + */ + g_type_init(); + char **argv2 = const_cast(argv); + gtk_init_check( &argc, &argv2 ); + //setlocale(LC_ALL, ""); + + GSList *fl = NULL; + int retVal = sp_common_main( argc, argv, &fl ); + g_return_val_if_fail(retVal == 0, 1); + + if (fl == NULL && !sp_shell) { + g_print("Nothing to do!\n"); + exit(0); + } + + inkscape_application_init(argv[0], false); + + if (sp_shell) { + sp_main_shell(argv[0]); // Run as interactive shell + exit(0); + } else { + sp_process_file_list(fl); // Normal command line invokation + } return 0; } static void -do_query_dimension (SPDocument *doc, bool extent, NR::Dim2 const axis, const gchar *id) +do_query_dimension (SPDocument *doc, bool extent, Geom::Dim2 const axis, const gchar *id) { SPObject *o = NULL; @@ -820,19 +1196,19 @@ do_query_dimension (SPDocument *doc, bool extent, NR::Dim2 const axis, const gch return; } } else { - o = SP_DOCUMENT_ROOT(doc); + o = doc->getRoot(); } if (o) { - sp_document_ensure_up_to_date (doc); + doc->ensureUpToDate(); SPItem *item = ((SPItem *) o); // "true" SVG bbox for scripting - NR::Maybe area = item->getBounds(sp_item_i2doc_affine(item)); + Geom::OptRect area = item->getBounds(item->i2doc_affine()); if (area) { Inkscape::SVGOStringStream os; if (extent) { - os << area->extent(axis); + os << area->dimensions()[axis]; } else { os << area->min()[axis]; } @@ -843,11 +1219,46 @@ do_query_dimension (SPDocument *doc, bool extent, NR::Dim2 const axis, const gch } } +static void do_query_all(SPDocument *doc) +{ + SPObject *o = doc->getRoot(); + + if (o) { + doc->ensureUpToDate(); + do_query_all_recurse(o); + } +} + +static void +do_query_all_recurse (SPObject *o) +{ + SPItem *item = ((SPItem *) o); + if (o->getId() && SP_IS_ITEM(item)) { + Geom::OptRect area = item->getBounds(item->i2doc_affine()); + if (area) { + Inkscape::SVGOStringStream os; + os << o->getId(); + os << "," << area->min()[Geom::X]; + os << "," << area->min()[Geom::Y]; + os << "," << area->dimensions()[Geom::X]; + os << "," << area->dimensions()[Geom::Y]; + g_print ("%s\n", os.str().c_str()); + } + } + + SPObject *child = o->children; + while (child) { + do_query_all_recurse (child); + child = child->next; + } +} + static void sp_do_export_png(SPDocument *doc) { const gchar *filename = NULL; + bool filename_from_hint = false; gdouble dpi = 0.0; if (sp_export_use_hints && (!sp_export_id && !sp_export_area_drawing)) { @@ -856,21 +1267,21 @@ sp_do_export_png(SPDocument *doc) GSList *items = NULL; - NRRect area; + Geom::Rect area; if (sp_export_id || sp_export_area_drawing) { SPObject *o = NULL; SPObject *o_area = NULL; if (sp_export_id && sp_export_area_drawing) { o = doc->getObjectById(sp_export_id); - o_area = SP_DOCUMENT_ROOT (doc); + o_area = doc->getRoot(); } else if (sp_export_id) { o = doc->getObjectById(sp_export_id); o_area = o; } else if (sp_export_area_drawing) { - o = SP_DOCUMENT_ROOT (doc); + o = doc->getRoot(); o_area = o; - } + } if (o) { if (!SP_IS_ITEM (o)) { @@ -894,6 +1305,7 @@ sp_do_export_png(SPDocument *doc) filename = sp_export_png; } else { filename = fn_hint; + filename_from_hint = true; } } else { g_warning ("Export filename hint not found for the object."); @@ -915,31 +1327,34 @@ sp_do_export_png(SPDocument *doc) } // write object bbox to area - sp_document_ensure_up_to_date (doc); - sp_item_invoke_bbox((SPItem *) o_area, &area, sp_item_i2r_affine((SPItem *) o_area), TRUE); + doc->ensureUpToDate(); + Geom::OptRect areaMaybe; + static_cast(o_area)->invoke_bbox( areaMaybe, static_cast(o_area)->i2d_affine(), TRUE); + if (areaMaybe) { + area = *areaMaybe; + } else { + g_warning("Unable to determine a valid bounding box. Nothing exported."); + return; + } } else { g_warning("Object with id=\"%s\" was not found in the document. Nothing exported.", sp_export_id); return; } } - + if (sp_export_area) { /* Try to parse area (given in SVG pixels) */ - if (!sscanf(sp_export_area, "%lg:%lg:%lg:%lg", &area.x0, &area.y0, &area.x1, &area.y1) == 4) { + gdouble x0,y0,x1,y1; + if (sscanf(sp_export_area, "%lg:%lg:%lg:%lg", &x0, &y0, &x1, &y1) != 4) { g_warning("Cannot parse export area '%s'; use 'x0:y0:x1:y1'. Nothing exported.", sp_export_area); return; } - if ((area.x0 >= area.x1) || (area.y0 >= area.y1)) { - g_warning("Export area '%s' has negative width or height. Nothing exported.", sp_export_area); - return; - } - } else if (sp_export_area_canvas || !(sp_export_id || sp_export_area_drawing)) { - /* Export the whole canvas */ - sp_document_ensure_up_to_date (doc); - area.x0 = SP_ROOT(doc->root)->x.computed; - area.y0 = SP_ROOT(doc->root)->y.computed; - area.x1 = area.x0 + sp_document_width (doc); - area.y1 = area.y0 + sp_document_height (doc); + area = Geom::Rect(Geom::Interval(x0,x1), Geom::Interval(y0,y1)); + } else if (sp_export_area_page || !(sp_export_id || sp_export_area_drawing)) { + /* Export the whole page: note: Inkscape uses 'page' in all menus and dialogs, not 'canvas' */ + doc->ensureUpToDate(); + Geom::Point origin (SP_ROOT(doc->root)->x.computed, SP_ROOT(doc->root)->y.computed); + area = Geom::Rect(origin, origin + doc->getDimensions()); } // set filename and dpi from options, if not yet set from the hints @@ -961,43 +1376,43 @@ sp_do_export_png(SPDocument *doc) } if (sp_export_area_snap) { - area.x0 = std::floor (area.x0); - area.y0 = std::floor (area.y0); - area.x1 = std::ceil (area.x1); - area.y1 = std::ceil (area.y1); + round_rectangle_outwards(area); } // default dpi - if (dpi == 0.0) + if (dpi == 0.0) { dpi = PX_PER_IN; + } - gint width = 0; - gint height = 0; + unsigned long int width = 0; + unsigned long int height = 0; if (sp_export_width) { - width = atoi(sp_export_width); - if ((width < 1) || (width > 65536)) { - g_warning("Export width %d out of range (1 - 65536). Nothing exported.", width); + errno=0; + width = strtoul(sp_export_width, NULL, 0); + if ((width < 1) || (width > PNG_UINT_31_MAX) || (errno == ERANGE) ) { + g_warning("Export width %lu out of range (1 - %lu). Nothing exported.", width, (unsigned long int)PNG_UINT_31_MAX); return; } - dpi = (gdouble) width * PX_PER_IN / (area.x1 - area.x0); + dpi = (gdouble) width * PX_PER_IN / area.width(); } if (sp_export_height) { - height = atoi(sp_export_height); - if ((height < 1) || (height > 65536)) { - g_warning("Export height %d out of range (1 - 65536). Nothing exported.", width); + errno=0; + height = strtoul(sp_export_height, NULL, 0); + if ((height < 1) || (height > PNG_UINT_31_MAX)) { + g_warning("Export height %lu out of range (1 - %lu). Nothing exported.", height, (unsigned long int)PNG_UINT_31_MAX); return; } - dpi = (gdouble) height * PX_PER_IN / (area.y1 - area.y0); + dpi = (gdouble) height * PX_PER_IN / area.height(); } if (!sp_export_width) { - width = (gint) ((area.x1 - area.x0) * dpi / PX_PER_IN + 0.5); + width = (unsigned long int) (area.width() * dpi / PX_PER_IN + 0.5); } if (!sp_export_height) { - height = (gint) ((area.y1 - area.y0) * dpi / PX_PER_IN + 0.5); + height = (unsigned long int) (area.height() * dpi / PX_PER_IN + 0.5); } guint32 bgcolor = 0x00000000; @@ -1030,31 +1445,49 @@ sp_do_export_png(SPDocument *doc) } } + gchar *path = 0; + if (filename_from_hint) { + //Make relative paths go from the document location, if possible: + if (!g_path_is_absolute(filename) && doc->getURI()) { + gchar *dirname = g_path_get_dirname(doc->getURI()); + if (dirname) { + path = g_build_filename(dirname, filename, NULL); + g_free(dirname); + } + } + if (!path) { + path = g_strdup(filename); + } + } else { + path = g_strdup(filename); + } + g_print("Background RRGGBBAA: %08x\n", bgcolor); - g_print("Area %g:%g:%g:%g exported to %d x %d pixels (%g dpi)\n", area.x0, area.y0, area.x1, area.y1, width, height, dpi); + g_print("Area %g:%g:%g:%g exported to %lu x %lu pixels (%g dpi)\n", area[Geom::X][0], area[Geom::Y][0], area[Geom::X][1], area[Geom::Y][1], width, height, dpi); g_print("Bitmap saved as: %s\n", filename); - if ((width >= 1) && (height >= 1) && (width < 65536) && (height < 65536)) { - sp_export_png_file(doc, filename, area.x0, area.y0, area.x1, area.y1, width, height, dpi, dpi, bgcolor, NULL, NULL, true, sp_export_id_only ? items : NULL); + if ((width >= 1) && (height >= 1) && (width <= PNG_UINT_31_MAX) && (height <= PNG_UINT_31_MAX)) { + sp_export_png_file(doc, path, area, width, height, dpi, dpi, bgcolor, NULL, NULL, true, sp_export_id_only ? items : NULL); } else { - g_warning("Calculated bitmap dimensions %d %d are out of range (1 - 65535). Nothing exported.", width, height); + g_warning("Calculated bitmap dimensions %lu %lu are out of range (1 - %lu). Nothing exported.", width, height, (unsigned long int)PNG_UINT_31_MAX); } + g_free (path); g_slist_free (items); } /** - * Perform an export of either PS or EPS. + * Perform a PDF/PS/EPS export * * \param doc Document to export. * \param uri URI to export to. * \param mime MIME type to export as. */ -static void do_export_ps(SPDocument* doc, gchar const* uri, char const* mime) +static void do_export_ps_pdf(SPDocument* doc, gchar const* uri, char const* mime) { Inkscape::Extension::DB::OutputList o; Inkscape::Extension::db.get_output_list(o); @@ -1065,71 +1498,77 @@ static void do_export_ps(SPDocument* doc, gchar const* uri, char const* mime) if (i == o.end()) { - g_warning ("Could not find an extension to export this file."); + g_warning ("Could not find an extension to export to MIME type %s.", mime); return; } - bool old_text_to_path = false; - bool old_font_embedded = false; - bool old_bbox_page = false; - - try { - old_text_to_path = (*i)->get_param_bool("textToPath"); - (*i)->set_param_bool("textToPath", sp_export_text_to_path); - } - catch (...) { - g_warning ("Could not set export-text-to-path option for this export."); + if (sp_export_id) { + SPObject *o = doc->getObjectById(sp_export_id); + if (o == NULL) { + g_warning("Object with id=\"%s\" was not found in the document. Nothing exported.", sp_export_id); + return; + } + (*i)->set_param_string ("exportId", sp_export_id); + } else { + (*i)->set_param_string ("exportId", ""); } - try { - old_font_embedded = (*i)->get_param_bool("fontEmbedded"); - (*i)->set_param_bool("fontEmbedded", sp_export_font); - } - catch (...) { - g_warning ("Could not set export-font option for this export."); + if (sp_export_area_page && sp_export_area_drawing) { + g_warning ("You cannot use --export-area-page and --export-area-drawing at the same time; only the former will take effect."); + sp_export_area_drawing = false; } - try { - old_bbox_page = (*i)->get_param_bool("pageBoundingBox"); - (*i)->set_param_bool("pageBoundingBox", sp_export_bbox_page); - } - catch (...) { - g_warning ("Could not set export-bbox-page option for this export."); + if (sp_export_area_drawing) { + (*i)->set_param_bool ("areaDrawing", TRUE); + } else { + (*i)->set_param_bool ("areaDrawing", FALSE); } - (*i)->save(doc, uri); - - try { - (*i)->set_param_bool("textToPath", old_text_to_path); - (*i)->set_param_bool("fontEmbedded", old_font_embedded); - (*i)->set_param_bool("pageBoundingBox", old_bbox_page); + if (sp_export_area_page) { + if (sp_export_eps) { + g_warning ("EPS cannot have its bounding box extend beyond its content, so if your drawing is smaller than the page, --export-area-page will clip it to drawing."); + } + (*i)->set_param_bool ("areaPage", TRUE); + } else { + (*i)->set_param_bool ("areaPage", FALSE); } - catch (...) { + if (!sp_export_area_drawing && !sp_export_area_page && !sp_export_id) { + // neither is set, set page as default for ps/pdf and drawing for eps + if (sp_export_eps) { + try { + (*i)->set_param_bool("areaDrawing", TRUE); + } catch (...) {} + } } -} -/** - * Perform a PDF export - * - * \param doc Document to export. - * \param uri URI to export to. - * \param mime MIME type to export as. - */ + if (sp_export_text_to_path) { + (*i)->set_param_bool("textToPath", TRUE); + } else { + (*i)->set_param_bool("textToPath", FALSE); + } -static void do_export_pdf(SPDocument* doc, gchar const* uri, char const* mime) -{ - Inkscape::Extension::DB::OutputList o; - Inkscape::Extension::db.get_output_list(o); - Inkscape::Extension::DB::OutputList::const_iterator i = o.begin(); - while (i != o.end() && strcmp( (*i)->get_mimetype(), mime ) != 0) { - i++; + if (sp_export_latex) { + (*i)->set_param_bool("textToLaTeX", TRUE); + } else { + (*i)->set_param_bool("textToLaTeX", FALSE); } - if (i == o.end()) - { - g_warning ("Could not find an extension to export this file."); - return; + if (sp_export_ignore_filters) { + (*i)->set_param_bool("blurToBitmap", FALSE); + } else { + (*i)->set_param_bool("blurToBitmap", TRUE); + + gdouble dpi = 90.0; + if (sp_export_dpi) { + dpi = atof(sp_export_dpi); + if ((dpi < 1) || (dpi > 10000.0)) { + g_warning("DPI value %s out of range [1 - 10000]. Using 90 dpi instead.", sp_export_dpi); + dpi = 90; + } + } + + (*i)->set_param_int("resolution", (int) dpi); } (*i)->save(doc, uri); @@ -1155,7 +1594,7 @@ static void do_export_emf(SPDocument* doc, gchar const* uri, char const* mime) if (i == o.end()) { - g_warning ("Could not find an extension to export this file."); + g_warning ("Could not find an extension to export to MIME type %s.", mime); return; } @@ -1277,11 +1716,13 @@ bool replaceArgs( int& argc, char**& argv ) if ( wildcarded ) { #ifdef REPLACEARGS_ANSI - WIN32_FIND_DATAA data = {0}; + WIN32_FIND_DATAA data; #else - WIN32_FIND_DATAW data = {0}; + WIN32_FIND_DATAW data; #endif // REPLACEARGS_ANSI + memset((void *)&data, 0, sizeof(data)); + int baseLen = wcslen(parsed[i1]) + 2; wchar_t* base = new wchar_t[baseLen]; wcsncpy( base, parsed[i1], baseLen ); @@ -1443,7 +1884,7 @@ sp_process_args(poptContext ctx) GSList *fl = NULL; gint a; - while ((a = poptGetNextOpt(ctx)) >= 0) { + while ((a = poptGetNextOpt(ctx)) != -1) { switch (a) { case SP_ARG_FILE: { gchar const *fn = poptGetOptArg(ctx); @@ -1453,7 +1894,7 @@ sp_process_args(poptContext ctx) break; } case SP_ARG_VERSION: { - printf("Inkscape %s (%s)\n", INKSCAPE_VERSION, __DATE__); + printf("Inkscape %s (%s)\n", Inkscape::version_string, __DATE__); exit(0); break; } @@ -1481,6 +1922,11 @@ sp_process_args(poptContext ctx) } break; } + case POPT_ERROR_BADOPT: { + g_warning ("Invalid option %s", poptBadOption(ctx, 0)); + exit(1); + break; + } default: { break; }