home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / app / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-12-17  |  12.9 KB  |  490 lines

  1. /* The GIMP -- an image manipulation program
  2.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  3.  *
  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.
  8.  *
  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.
  13.  *
  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.
  17.  */
  18.  
  19. #include "config.h"
  20.  
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <signal.h>
  24. #include <string.h>
  25. #include <sys/types.h>
  26.  
  27. #ifdef HAVE_SYS_WAIT_H
  28. #include <sys/wait.h>
  29. #endif
  30.  
  31. #ifdef HAVE_UNISTD_H
  32. #include <unistd.h>
  33. #endif
  34.  
  35. #ifndef  WAIT_ANY
  36. #define  WAIT_ANY -1
  37. #endif   /*  WAIT_ANY  */
  38.  
  39. #include <gtk/gtk.h>
  40.  
  41. #include "libgimp/gimpfeatures.h"
  42. #include "libgimp/gimpenv.h"
  43.  
  44. #ifndef  G_OS_WIN32
  45. #include "libgimp/gimpsignal.h"
  46. #endif
  47.  
  48. #include "apptypes.h"
  49.  
  50. #include "appenv.h"
  51. #include "app_procs.h"
  52. #include "errors.h"
  53. #include "user_install.h"
  54.  
  55. #include "libgimp/gimpintl.h"
  56.  
  57. #ifdef G_OS_WIN32
  58. #include <windows.h>
  59. #else
  60. static void   gimp_sigfatal_handler (gint sig_num);
  61. static void   gimp_sigchld_handler  (gint sig_num);
  62. #endif
  63.  
  64. static void   init                  (void);
  65. static void   gimp_error_handler    (const gchar    *domain,
  66.                      GLogLevelFlags  flags,
  67.                      const gchar    *msg,
  68.                      gpointer        user_data);
  69.  
  70. /* GLOBAL data */
  71. gboolean no_interface      = FALSE;
  72. gboolean no_data           = FALSE;
  73. gboolean no_splash         = FALSE;
  74. gboolean no_splash_image   = FALSE;
  75. gboolean be_verbose        = FALSE;
  76. gboolean use_shm           = FALSE;
  77. gboolean use_debug_handler = FALSE;
  78. gboolean console_messages  = FALSE;
  79. gboolean restore_session   = FALSE;
  80. gboolean double_speed      = FALSE;
  81.  
  82. GimpSet *image_context = NULL;
  83.  
  84. MessageHandlerType message_handler = CONSOLE;
  85.  
  86. gchar  *prog_name         = NULL; /* The path name we are invoked with */
  87. gchar  *alternate_gimprc        = NULL;
  88. gchar  *alternate_system_gimprc = NULL;
  89. gchar **batch_cmds              = NULL;
  90.  
  91.  
  92. /* LOCAL data */
  93. static gint    gimp_argc = 0;
  94. static gchar **gimp_argv = NULL;
  95.  
  96. /*
  97.  *  argv processing: 
  98.  *      Arguments are either switches, their associated
  99.  *      values, or image files.  As switches and their
  100.  *      associated values are processed, those slots in
  101.  *      the argv[] array are NULLed. We do this because
  102.  *      unparsed args are treated as images to load on
  103.  *      startup.
  104.  *
  105.  *
  106.  *      The GTK switches are processed first (X switches are
  107.  *      processed here, not by any X routines).  Then the
  108.  *      general GIMP switches are processed.  Any args
  109.  *      left are assumed to be image files the GIMP should
  110.  *      display.
  111.  *
  112.  *      The exception is the batch switch.  When this is
  113.  *      encountered, all remaining args are treated as batch
  114.  *      commands.
  115.  */
  116.  
  117. int
  118. main (int    argc,
  119.       char **argv)
  120. {
  121.   gboolean show_version = FALSE;
  122.   gboolean show_help    = FALSE;
  123.   gint i, j;
  124. #ifdef HAVE_PUTENV
  125.   gchar *display_env;
  126. #endif
  127.  
  128.   g_atexit (g_mem_profile);
  129.  
  130.   /* Initialize variables */
  131.  
  132.   prog_name = argv[0];
  133.  
  134.   /* Initialize i18n support */
  135.   INIT_LOCALE ("gimp");
  136.  
  137. #ifdef ENABLE_NLS
  138.   bindtextdomain ("gimp-libgimp", LOCALEDIR);
  139. #endif
  140.  
  141.   gtk_init (&argc, &argv);
  142.  
  143.   setlocale (LC_NUMERIC, "C");  /* gtk seems to zap this during init.. */
  144.  
  145. #ifdef HAVE_PUTENV
  146.   display_env = g_strconcat ("DISPLAY=", gdk_get_display (), NULL);
  147.   putenv (display_env);
  148. #endif
  149.  
  150. #if defined (HAVE_SHM_H) || defined (G_OS_WIN32)
  151.   use_shm = TRUE;
  152. #endif
  153.  
  154.   batch_cmds    = g_new (char *, argc);
  155.   batch_cmds[0] = NULL;
  156.  
  157.   for (i = 1; i < argc; i++)
  158.     {
  159.       if ((strcmp (argv[i], "--no-interface") == 0) ||
  160.       (strcmp (argv[i], "-i") == 0))
  161.     {
  162.       no_interface = TRUE;
  163.        argv[i] = NULL;
  164.     }
  165.       else if ((strcmp (argv[i], "--batch") == 0) ||
  166.            (strcmp (argv[i], "-b") == 0))
  167.     {
  168.       argv[i] = NULL;
  169.       for (j = 0, i++ ; i < argc; j++, i++)
  170.         {
  171.           batch_cmds[j] = argv[i];
  172.           argv[i] = NULL;
  173.         }
  174.       batch_cmds[j] = NULL;
  175.  
  176.       if (batch_cmds[0] == NULL)  /* We need at least one batch command */
  177.         show_help = TRUE;
  178.     }
  179.       else if (strcmp (argv[i], "--system-gimprc") == 0)  
  180.     {
  181.        argv[i] = NULL;
  182.       if (argc <= ++i) 
  183.             {
  184.           show_help = TRUE;
  185.         }
  186.           else 
  187.             {
  188.           alternate_system_gimprc = argv[i];
  189.           argv[i] = NULL;
  190.             }
  191.     } 
  192.       else if ((strcmp (argv[i], "--gimprc") == 0) || 
  193.                (strcmp (argv[i], "-g") == 0))
  194.     {
  195.       argv[i] = NULL;
  196.       if (argc <= ++i) 
  197.             {
  198.           show_help = TRUE;
  199.         }
  200.           else
  201.             {
  202.           alternate_gimprc = argv[i];
  203.           argv[i] = NULL;
  204.             }
  205.     }
  206.       else if ((strcmp (argv[i], "--help") == 0) ||
  207.            (strcmp (argv[i], "-h") == 0))
  208.     {
  209.       show_help = TRUE;
  210.        argv[i] = NULL;
  211.     }
  212.       else if ((strcmp (argv[i], "--version") == 0) ||
  213.                (strcmp (argv[i], "-v") == 0))
  214.     {
  215.       show_version = TRUE;
  216.        argv[i] = NULL;
  217.     }
  218.       else if ((strcmp (argv[i], "--no-data") == 0) ||
  219.            (strcmp (argv[i], "-d") == 0))
  220.     {
  221.       no_data = TRUE;
  222.        argv[i] = NULL;
  223.     }
  224.       else if ((strcmp (argv[i], "--no-splash") == 0) ||
  225.            (strcmp (argv[i], "-s") == 0))
  226.     {
  227.       no_splash = TRUE;
  228.        argv[i] = NULL;
  229.     }
  230.       else if ((strcmp (argv[i], "--no-splash-image") == 0) ||
  231.            (strcmp (argv[i], "-S") == 0))
  232.     {
  233.       no_splash_image = TRUE;
  234.        argv[i] = NULL;
  235.     }
  236.       else if (strcmp (argv[i], "--verbose") == 0)
  237.     {
  238.       be_verbose = TRUE;
  239.        argv[i] = NULL;
  240.     }
  241.       else if (strcmp (argv[i], "--no-shm") == 0)
  242.     {
  243.       use_shm = FALSE;
  244.        argv[i] = NULL;
  245.     }
  246.       else if (strcmp (argv[i], "--debug-handlers") == 0)
  247.     {
  248.       use_debug_handler = TRUE;
  249.        argv[i] = NULL;
  250.     }
  251.       else if ((strcmp (argv[i], "--console-messages") == 0) ||
  252.            (strcmp (argv[i], "-c") == 0))
  253.     {
  254.       console_messages = TRUE;
  255.        argv[i] = NULL;
  256.     }
  257.       else if ((strcmp (argv[i], "--restore-session") == 0) ||
  258.            (strcmp (argv[i], "-r") == 0))
  259.     {
  260.       restore_session = TRUE;
  261.        argv[i] = NULL;
  262.     }
  263.       else if (strcmp (argv[i], "--enable-stack-trace") == 0)  
  264.     {
  265.        argv[i] = NULL;
  266.       if (argc <= ++i) 
  267.             {
  268.           show_help = TRUE;
  269.         }
  270.           else 
  271.             {
  272.           if (! strcmp (argv[i], "never"))
  273.         stack_trace_mode = STACK_TRACE_NEVER;
  274.           else if (! strcmp (argv[i], "query"))
  275.         stack_trace_mode = STACK_TRACE_QUERY;
  276.           else if (! strcmp (argv[i], "always"))
  277.         stack_trace_mode = STACK_TRACE_ALWAYS;
  278.           else
  279.         show_help = TRUE;
  280.  
  281.           argv[i] = NULL;
  282.             }
  283.     }
  284.       /*
  285.        *    ANYTHING ELSE starting with a '-' is an error.
  286.        */
  287.       else if (argv[i][0] == '-')
  288.     {
  289.         g_print (_("\nInvalid option.\n"));
  290.         show_help = TRUE;
  291.     }
  292.     }
  293.  
  294. #ifdef G_OS_WIN32
  295.   /* Common windoze apps don't have a console at all. So does Gimp 
  296.    * - if appropiate. This allows to compile as console application
  297.    * with all it's benfits (like inheriting the console) but hide
  298.    * it, if the user doesn't want it.
  299.    */
  300.   if (!show_help && !show_version && !be_verbose && !console_messages)
  301.     FreeConsole ();
  302. #endif
  303.  
  304.   if (show_version)
  305.     g_print ( "%s %s\n", _("GIMP version"), GIMP_VERSION);
  306.  
  307.   if (show_help)
  308.     {
  309.       g_print (_("\nUsage: %s [option ... ] [file ... ]\n\n"), argv[0]);
  310.       g_print (_("Options:\n"));
  311.       g_print (_("  -b, --batch <commands>   Run in batch mode.\n"));
  312.       g_print (_("  -c, --console-messages   Display warnings to console instead of a dialog box.\n"));
  313.       g_print (_("  -d, --no-data            Do not load brushes, gradients, palettes, patterns.\n"));
  314.       g_print (_("  -i, --no-interface       Run without a user interface.\n"));
  315.       g_print (_("  -g, --gimprc <gimprc>    Use an alternate gimprc file.\n"));
  316.       g_print (_("  -h, --help               Output this help.\n"));
  317.       g_print (_("  -r, --restore-session    Try to restore saved session.\n"));
  318.       g_print (_("  -s, --no-splash          Do not show the startup window.\n"));
  319.       g_print (_("  -S, --no-splash-image    Do not add an image to the startup window.\n"));
  320.       g_print (_("  -v, --version            Output version information.\n"));
  321.       g_print (_("  --verbose                Show startup messages.\n"));      
  322.       g_print (_("  --no-shm                 Do not use shared memory between GIMP and plugins.\n"));
  323.       g_print (_("  --no-xshm                Do not use the X Shared Memory extension.\n"));
  324.       g_print (_("  --debug-handlers         Enable non-fatal debugging signal handlers.\n"));
  325.       g_print (_("  --display <display>      Use the designated X display.\n"));
  326.       g_print (_("  --system-gimprc <gimprc> Use an alternate system gimprc file.\n"));
  327.       g_print ("  --enable-stack-trace <never | query | always>\n");
  328.       g_print (_("                           Debugging mode for fatal signals.\n\n"));
  329.     }
  330.  
  331.   if (show_version || show_help)
  332.     {
  333. #ifdef G_OS_WIN32
  334.       /* Give them time to read the message if it was printed in a
  335.        * separate console window. I would really love to have
  336.        * some way of asking for confirmation to close the console
  337.        * window.
  338.        */
  339.       HANDLE console;
  340.       DWORD mode;
  341.  
  342.       console = GetStdHandle (STD_OUTPUT_HANDLE);
  343.       if (GetConsoleMode (console, &mode) != 0)
  344.     {
  345.       g_print (_("(This console window will close in ten seconds)\n"));
  346.       Sleep(10000);
  347.     }
  348. #endif
  349.       exit (0);
  350.     }
  351.  
  352.   g_log_set_handler ("Gimp",
  353.              G_LOG_LEVEL_MESSAGE,
  354.              gimp_message_func,
  355.              NULL);
  356.  
  357.   /* g_set_message_handler ((GPrintFunc) gimp_message_func); */
  358.  
  359. #ifndef G_OS_WIN32
  360.  
  361.   /* No use catching these on Win32, the user won't get any 
  362.    * stack trace from glib anyhow. It's better to let Windows inform
  363.    * about the program error, and offer debugging (if the user
  364.    * has installed MSVC or some other compiler that knows how to
  365.    * install itself as a handler for program errors).
  366.    */
  367.  
  368.   /* Handle fatal signals */
  369.  
  370.   gimp_signal_private (SIGHUP,  gimp_sigfatal_handler, 0);
  371.   gimp_signal_private (SIGINT,  gimp_sigfatal_handler, 0);
  372.   gimp_signal_private (SIGQUIT, gimp_sigfatal_handler, 0);
  373.   gimp_signal_private (SIGABRT, gimp_sigfatal_handler, 0);
  374.   gimp_signal_private (SIGBUS,  gimp_sigfatal_handler, 0);
  375.   gimp_signal_private (SIGSEGV, gimp_sigfatal_handler, 0);
  376.   gimp_signal_private (SIGTERM, gimp_sigfatal_handler, 0);
  377.   gimp_signal_private (SIGFPE,  gimp_sigfatal_handler, 0);
  378.  
  379.   /* Ignore SIGPIPE because plug_in.c handles broken pipes */
  380.  
  381.   gimp_signal_private (SIGPIPE, SIG_IGN, 0);
  382.  
  383.   /* Collect dead children */
  384.  
  385.   gimp_signal_private (SIGCHLD, gimp_sigchld_handler, SA_RESTART);
  386.  
  387. #endif /* G_OS_WIN32 */
  388.  
  389.   g_log_set_handler (NULL,
  390.              G_LOG_LEVEL_ERROR | G_LOG_FLAG_FATAL,
  391.              gimp_error_handler,
  392.              NULL);
  393.  
  394.   /* Keep the command line arguments--for use in gimp_init */
  395.   gimp_argc = argc - 1;
  396.   gimp_argv = argv + 1;
  397.  
  398.   /* Check the user_installation */
  399.   user_install_verify (init);
  400.  
  401.   /* Main application loop */
  402.   if (!app_exit_finish_done ())
  403.     gtk_main ();
  404.  
  405.   return 0;
  406. }
  407.  
  408. #ifdef G_OS_WIN32
  409.  
  410. /* In case we build this as a windowed application */
  411.  
  412. #ifdef __GNUC__
  413. #  ifndef _stdcall
  414. #    define _stdcall  __attribute__((stdcall))
  415. #  endif
  416. #endif
  417.  
  418. int _stdcall
  419. WinMain (struct HINSTANCE__ *hInstance,
  420.      struct HINSTANCE__ *hPrevInstance,
  421.      char               *lpszCmdLine,
  422.      int                 nCmdShow)
  423. {
  424.   return main (__argc, __argv);
  425. }
  426.  
  427. #endif
  428.  
  429. static void
  430. init (void)
  431. {
  432.   /*  Continue initializing  */
  433.   gimp_init (gimp_argc, gimp_argv);
  434. }
  435.  
  436.  
  437. static void
  438. gimp_error_handler (const gchar    *domain,
  439.             GLogLevelFlags  flags,
  440.             const gchar    *msg,
  441.             gpointer        user_data)
  442. {
  443.   gimp_fatal_error ("%s", msg);
  444. }
  445.  
  446. #ifndef G_OS_WIN32
  447.  
  448. /* gimp core signal handler for fatal signals */
  449.  
  450. static void
  451. gimp_sigfatal_handler (gint sig_num)
  452. {
  453.   switch (sig_num)
  454.     {
  455.     case SIGHUP:
  456.     case SIGINT:
  457.     case SIGQUIT:
  458.     case SIGABRT:
  459.     case SIGTERM:
  460.       gimp_terminate (g_strsignal (sig_num));
  461.       break;
  462.  
  463.     case SIGBUS:
  464.     case SIGSEGV:
  465.     case SIGFPE:
  466.     default:
  467.       gimp_fatal_error (g_strsignal (sig_num));
  468.       break;
  469.     }
  470. }
  471.  
  472. /* gimp core signal handler for death-of-child signals */
  473.  
  474. static void
  475. gimp_sigchld_handler (gint sig_num)
  476. {
  477.   gint pid;
  478.   gint status;
  479.  
  480.   while (TRUE)
  481.     {
  482.       pid = waitpid (WAIT_ANY, &status, WNOHANG);
  483.  
  484.       if (pid <= 0)
  485.     break;
  486.     }
  487. }
  488.  
  489. #endif /* !G_OS_WIN32 */
  490.