Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Gimp/app/   (Gimp Bildeditor Version 3.2.0©)  Datei vom 14.2.2026 mit Größe 35 kB image not shown  

Quelle  main.c   Sprache: C

 

/* GIMP - The GNU Image Manipulation Program
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */


#include "config.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif

#ifdef __GLIBC__
#include <malloc.h>
#endif

#include <locale.h>

#include <gio/gio.h>
#include <glib/gstdio.h>

#ifdef G_OS_WIN32
#include <io.h> /* get_osfhandle */

#endif /* G_OS_WIN32 */

#if defined(ENABLE_RELOCATABLE_RESOURCES) && defined(__APPLE__)
#include <libgen.h> /* dirname */
#include <sys/stat.h>
#endif /* __APPLE__ */

#ifndef GIMP_CONSOLE_COMPILATION
#include <gtk/gtk.h>
#ifdef GDK_WINDOWING_X11
#include <gdk/gdkx.h>
#endif
#else
#include <gdk-pixbuf/gdk-pixbuf.h>
#endif

#include <babl/babl.h>

#include "libgimpbase/gimpbase.h"
#include "libgimpbase/gimpbase-private.h"

#include "pdb/pdb-types.h"

#include "config/gimpearlyrc.h"
#include "config/gimpconfig-dump.h"

#include "core/gimp.h"
#include "core/gimpbacktrace.h"

#include "pdb/gimppdb.h"
#include "pdb/gimpprocedure.h"
#include "pdb/internal-procs.h"

#include "about.h"
#include "app.h"
#include "language.h"
#include "sanity.h"
#include "signals.h"
#include "unique.h"

#ifdef G_OS_WIN32
#include <windows.h>
#include <conio.h>
#endif

#include "gimp-log.h"
#include "gimp-intl.h"
#include "gimp-version.h"


static gboolean  gimp_option_fatal_warnings   (const gchar  *option_name,
                                               const gchar  *value,
                                               gpointer      data,
                                               GError      **error);
static gboolean  gimp_option_stack_trace_mode (const gchar  *option_name,
                                               const gchar  *value,
                                               gpointer      data,
                                               GError      **error);
static gboolean  gimp_option_pdb_compat_mode  (const gchar  *option_name,
                                               const gchar  *value,
                                               gpointer      data,
                                               GError      **error);
static gboolean  gimp_option_dump_gimprc      (const gchar  *option_name,
                                               const gchar  *value,
                                               gpointer      data,
                                               GError      **error);
static gboolean  gimp_option_dump_pdb_procedures_deprecated
                                              (const gchar  *option_name,
                                               const gchar  *value,
                                               gpointer      data,
                                               GError      **error);

static void      gimp_show_version_and_exit   (void) G_GNUC_NORETURN;
static void      gimp_show_license_and_exit   (void) G_GNUC_NORETURN;

static void      gimp_init_i18n               (void);
static void      gimp_init_malloc             (void);

#if defined (G_OS_WIN32) && !defined (GIMP_CONSOLE_COMPILATION)
static void      gimp_attach_console_window     (void);
#else
#define gimp_attach_console_window() /* as nothing */
#endif

static const gchar        *system_gimprc     = NULL;
static const gchar        *user_gimprc       = NULL;
static const gchar        *session_name      = NULL;
static const gchar        *batch_interpreter = NULL;
static const gchar       **batch_commands    = NULL;
static const gchar       **filenames         = NULL;
static gboolean            quit              = FALSE;
static gboolean            as_new            = FALSE;
static gboolean            no_interface      = FALSE;
static gboolean            no_data           = FALSE;
static gboolean            no_fonts          = FALSE;
static gboolean            no_splash         = FALSE;
static gboolean            be_verbose        = FALSE;
static gboolean            new_instance      = FALSE;
#if defined (USE_SYSV_SHM) || defined (USE_POSIX_SHM) || defined (G_OS_WIN32)
static gboolean            use_shm           = TRUE;
#else
static gboolean            use_shm           = FALSE;
#endif
static gboolean            use_cpu_accel     = TRUE;
static gboolean            console_messages  = FALSE;
static gboolean            use_debug_handler = FALSE;

#if defined (GIMP_UNSTABLE) || ! defined (GIMP_RELEASE)
static gboolean            show_playground   = TRUE;
static gboolean            show_debug_menu   = TRUE;
static GimpStackTraceMode  stack_trace_mode  = GIMP_STACK_TRACE_QUERY;
static GimpPDBCompatMode   pdb_compat_mode   = GIMP_PDB_COMPAT_WARN;
#else
static gboolean            show_playground   = FALSE;
static gboolean            show_debug_menu   = FALSE;
static GimpStackTraceMode  stack_trace_mode  = GIMP_STACK_TRACE_NEVER;
static GimpPDBCompatMode   pdb_compat_mode   = GIMP_PDB_COMPAT_ON;
#endif


static const GOptionEntry main_entries[] =
{
  { "version", 'v', G_OPTION_FLAG_NO_ARG,
    G_OPTION_ARG_CALLBACK, (GOptionArgFunc) gimp_show_version_and_exit,
    N_("Show version information and exit"), NULL
  },
  {
    "license", 0, G_OPTION_FLAG_NO_ARG,
    G_OPTION_ARG_CALLBACK, (GOptionArgFunc) gimp_show_license_and_exit,
    N_("Show license information and exit"), NULL
  },
  {
    "verbose", 0, 0,
    G_OPTION_ARG_NONE, &be_verbose,
    N_("Be more verbose"), NULL
  },
  {
    "new-instance", 'n', 0,
    G_OPTION_ARG_NONE, &new_instance,
    N_("Start a new GIMP instance"), NULL
  },
  {
    "as-new", 'a', 0,
    G_OPTION_ARG_NONE, &as_new,
    N_("Open images as new"), NULL
  },
  {
    "no-interface", 'i',
#ifdef GIMP_CONSOLE_COMPILATION
    /* The CLI option is not removed for gimp-console because it allows
     * to set the same options on either the GUI or the console
     * binaries, as a no-brainer. We in fact also use this in build
     * scripts which may make use of either one of the binaries to
     * construct some images.
     * Yet it's unnecessary to show this option in the CLI tool usage as
     * it's basically a no-op.
     */

    G_OPTION_FLAG_HIDDEN,
#else
    0,
#endif
    G_OPTION_ARG_NONE, &no_interface,
    N_("Run without a user interface"), NULL
  },
  {
    "no-data", 'd', 0,
    G_OPTION_ARG_NONE, &no_data,
    N_("Do not load brushes, gradients, patterns, ..."), NULL
  },
  {
    "no-fonts", 'f', 0,
    G_OPTION_ARG_NONE, &no_fonts,
    N_("Do not load any fonts"), NULL
  },
  {
    "no-splash", 's', 0,
    G_OPTION_ARG_NONE, &no_splash,
    N_("Do not show a splash screen"), NULL
  },
  {
    "no-shm", 0, G_OPTION_FLAG_REVERSE,
    G_OPTION_ARG_NONE, &use_shm,
    N_("Do not use shared memory between GIMP and plug-ins"), NULL
  },
  {
    "no-cpu-accel", 0, G_OPTION_FLAG_REVERSE,
    G_OPTION_ARG_NONE, &use_cpu_accel,
    N_("Do not use special CPU acceleration functions"), NULL
  },
  {
    "session", 0, 0,
    G_OPTION_ARG_FILENAME, &session_name,
    N_("Use an alternate sessionrc file"), "<name>"
  },
  {
    "gimprc", 'g', 0,
    G_OPTION_ARG_FILENAME, &user_gimprc,
    N_("Use an alternate user gimprc file"), "<filename>"
  },
  {
    "system-gimprc", 0, 0,
    G_OPTION_ARG_FILENAME, &system_gimprc,
    N_("Use an alternate system gimprc file"), "<filename>"
  },
  {
    "batch", 'b', 0,
    G_OPTION_ARG_STRING_ARRAY, &batch_commands,
    N_("Batch command to run (can be used multiple times)"), "<command>"
  },
  {
    "batch-interpreter", 0, 0,
    G_OPTION_ARG_STRING, &batch_interpreter,
    N_("The procedure to process batch commands with"), "<proc>"
  },
  {
    "quit", 0, 0,
    G_OPTION_ARG_NONE, &quit,
    N_("Quit immediately after performing requested actions"), NULL
  },
  {
    "console-messages", 'c', 0,
    G_OPTION_ARG_NONE, &console_messages,
    N_("Send messages to console instead of using a dialog"), NULL
  },
  {
    "pdb-compat-mode", 0, 0,
    G_OPTION_ARG_CALLBACK, gimp_option_pdb_compat_mode,
    /*  don't translate the mode names (off|on|warn)  */
    N_("PDB compatibility mode (off|on|warn)"), "<mode>"
  },
  {
    "stack-trace-mode", 0, 0,
    G_OPTION_ARG_CALLBACK, gimp_option_stack_trace_mode,
    /*  don't translate the mode names (never|query|always)  */
    N_("Debug in case of a crash (never|query|always)"), "<mode>"
  },
  {
    "debug-handlers", 0, 0,
    G_OPTION_ARG_NONE, &use_debug_handler,
    N_("Enable non-fatal debugging signal handlers"), NULL
  },
  {
    "g-fatal-warnings", 0, G_OPTION_FLAG_NO_ARG,
    G_OPTION_ARG_CALLBACK, gimp_option_fatal_warnings,
    N_("Make all warnings fatal"), NULL
  },
  {
    "dump-gimprc", 0, G_OPTION_FLAG_NO_ARG,
    G_OPTION_ARG_CALLBACK, gimp_option_dump_gimprc,
    N_("Output a gimprc file with default settings"), NULL
  },
  {
    "dump-gimprc-system", 0, G_OPTION_FLAG_NO_ARG | G_OPTION_FLAG_HIDDEN,
    G_OPTION_ARG_CALLBACK, gimp_option_dump_gimprc,
    NULL, NULL
  },
  {
    "dump-gimprc-manpage", 0, G_OPTION_FLAG_NO_ARG | G_OPTION_FLAG_HIDDEN,
    G_OPTION_ARG_CALLBACK, gimp_option_dump_gimprc,
    NULL, NULL
  },
  {
    "dump-pdb-procedures-deprecated", 0,
    G_OPTION_FLAG_NO_ARG | G_OPTION_FLAG_HIDDEN,
    G_OPTION_ARG_CALLBACK, gimp_option_dump_pdb_procedures_deprecated,
    N_("Output a sorted list of deprecated procedures in the PDB"), NULL
  },
  {
    "show-playground", 0, 0,
    G_OPTION_ARG_NONE, &show_playground,
    N_("Show a preferences page with experimental features"), NULL
  },
  {
    "show-debug-menu", 0, 0,
    G_OPTION_ARG_NONE, &show_debug_menu,
    N_("Show an image submenu with debug actions"), NULL
  },
  {
    G_OPTION_REMAINING, 0, 0,
    G_OPTION_ARG_FILENAME_ARRAY, &filenames,
    NULL, NULL
  },
  { NULL }
};

#if defined(ENABLE_RELOCATABLE_RESOURCES) && defined(__APPLE__)
static void
gimp_macos_setenv (const char * progname)
{
  /* helper to set environment variables for GIMP to be relocatable.
   * Due to the changes on macOS 10.15, it is not recommended to set it in
   * a shell wrapper inside Contents/MacOS (like AppImage's AppRun) anymore.
   * LSEnvironment on Info.plist, limited to bundle scope, would not be enough.
   * That way, we make sure our python is called instead of system one etc
   */

  gchar  *resolved_path;
  /* on some OSX installations open file limit is 256 and GIMP needs more */
  struct  rlimit limit;

  limit.rlim_cur = 10000;
  limit.rlim_max = 10000;
  setrlimit (RLIMIT_NOFILE, &limit);
  resolved_path = g_canonicalize_filename (progname, NULL);
  if (resolved_path && ! g_getenv ("GIMP_NO_WRAPPER"))
    {
      gchar   *path;
      gchar   *tmp;
      gchar   *bin_dir;
      gchar   *lib_dir;
      gchar   *share_dir;
      gchar   *etc_dir;
      size_t   path_len;
      struct   stat sb;
      gboolean need_pythonhome = TRUE;

      bin_dir = g_path_get_dirname (resolved_path);
      tmp = g_strdup_printf ("%s/../Resources/lib", bin_dir);
      lib_dir = g_canonicalize_filename (tmp, NULL);
      g_free (tmp);
      tmp = g_strdup_printf ("%s/../Resources/share", bin_dir);
      share_dir = g_canonicalize_filename (tmp, NULL);
      g_free (tmp);
      tmp = g_strdup_printf ("%s/../Resources/etc", bin_dir);
      etc_dir = g_canonicalize_filename (tmp, NULL);
      g_free (tmp);

      /* Detect if we are running from bundle or from prefix */
      if (share_dir && !stat (share_dir, &sb) && S_ISDIR (sb.st_mode))
        {
          g_print ("GIMP is started as MacOS application\n");
        }
      else
        {
          tmp = g_strdup_printf ("%s/../share", bin_dir);
          share_dir = g_canonicalize_filename (tmp, NULL);
          g_free (tmp);
          if (share_dir && !stat (share_dir, &sb) && S_ISDIR (sb.st_mode))
            {
              g_free (share_dir);

              g_print ("GIMP is started in the build directory\n");

              tmp = g_strdup_printf ("%s/..", bin_dir); /* running in build dir */
              share_dir = g_canonicalize_filename (tmp, NULL);
              g_free (tmp);
            }
          else
            {
              g_free (share_dir);
              return;
            }
        }

      /* Detect we were built in homebrew for MacOS (for PYTHONHOME purposes) */
      tmp = g_strdup_printf ("%s/../Frameworks/Python.framework", share_dir);
      if (tmp && !stat (tmp, &sb) && S_ISDIR (sb.st_mode))
        {
          g_print ("GIMP was built with homebrew\n");
          need_pythonhome = FALSE;
        }
      g_free (tmp);
      /* Detect we were built in MacPorts for MacOS (for PYTHONHOME purposes) */
      tmp = g_strdup_printf ("%s/../Library/Frameworks/Python.framework", share_dir);
      if (tmp && !stat (tmp, &sb) && S_ISDIR (sb.st_mode))
        {
          g_print ("GIMP was built with MacPorts\n");
          need_pythonhome = FALSE;
        }
      g_free (tmp);

      /* Minimum runtime paths */
      path_len = strlen (g_getenv ("PATH") ? g_getenv ("PATH") : "") + strlen (bin_dir) + 2;
      path = g_try_malloc (path_len);
      if (path == NULL)
        {
          g_warning ("Failed to allocate memory");
          app_exit (EXIT_FAILURE);
        }
      if (g_getenv ("PATH"))
        g_snprintf (path, path_len, "%s:%s", bin_dir, g_getenv ("PATH"));
      else
        g_snprintf (path, path_len, "%s", bin_dir);
      g_free (bin_dir);
      g_setenv ("PATH", path, TRUE);
      g_free (path);
      if (g_getenv ("XDG_DATA_DIRS"))
        tmp = g_strdup_printf ("%s:%s", share_dir, g_getenv ("XDG_DATA_DIRS"));
      else
        tmp = g_strdup_printf ("%s", share_dir);
      g_setenv ("XDG_DATA_DIRS", tmp, TRUE);
      g_free (tmp);
      if (g_getenv ("HOME") != NULL)
        {
          tmp = g_strdup_printf ("%s/Library/Application Support/GIMP/%s/cache",
                                 g_getenv ("HOME"), GIMP_APP_VERSION);
          g_setenv ("XDG_CACHE_HOME", tmp, TRUE);
          g_free (tmp);
        }

      /* Bare minimum to run GTK apps */
      tmp = g_strdup_printf ("%s/gio/modules", lib_dir);
      g_setenv ("GIO_MODULE_DIR", tmp, TRUE);
      g_free (tmp);
      tmp = g_strdup_printf ("%s/gdk-pixbuf-2.0/2.10.0/loaders.cache", lib_dir);
      g_setenv ("GDK_PIXBUF_MODULE_FILE", tmp, TRUE);
      g_free (tmp);
      tmp = g_strdup_printf ("%s/gtk-3.0/3.0.0", lib_dir);
      g_setenv ("GTK_PATH", tmp, TRUE);
      g_free (tmp);
      tmp = g_strdup_printf ("%s/gtk-3.0/3.0.0/immodules.cache", lib_dir);
      g_setenv ("GTK_IM_MODULE_FILE", tmp, TRUE);
      g_free (tmp);
      tmp = g_strdup ("quartz");
      g_setenv ("GTK_IM_MODULE", tmp, TRUE);
      g_free (tmp);

      /* Other needed runtime paths (related to features) */
      tmp = g_strdup_printf ("%s/fonts", etc_dir);
      g_setenv ("FONTCONFIG_PATH", tmp, TRUE);
      g_free (tmp);
      tmp = g_strdup_printf ("%s/libthai", share_dir);
      g_setenv ("LIBTHAI_DICTDIR", tmp, TRUE);
      g_free (tmp);
      tmp = g_strdup_printf ("%s/ghostscript/Resource/Init", share_dir);
      g_setenv ("GS_LIB", tmp, TRUE);
      g_free (tmp);
      tmp = g_strdup_printf ("%s/libwmf/fonts", share_dir);
      g_setenv ("WMF_FONTDIR", tmp, TRUE);
      g_free (tmp);
      tmp = g_strdup_printf ("%s/girepository-1.0", lib_dir);
      g_setenv ("GI_TYPELIB_PATH", tmp, TRUE);
      g_free (tmp);
      if (need_pythonhome)
        {
          tmp = g_strdup_printf ("%s/Library/Frameworks/Python.framework/Versions/%s", share_dir, PYTHON_VERSION);
          g_setenv ("PYTHONHOME", tmp, TRUE);
          g_free (tmp);
        }
      g_free (lib_dir);
      g_free (share_dir);
      g_free (etc_dir);
    }
  g_free (resolved_path);
}
#endif

/* gimp_early_configuration () is executed as soon as we can read
 * the "gimprc" files, but before any library initialization takes
 * place
 */

static void
gimp_early_configuration (void)
{
  GFile       *system_gimprc_file = NULL;
  GFile       *user_gimprc_file   = NULL;
  GimpEarlyRc *earlyrc;
  gchar       *language;

  if (system_gimprc)
    system_gimprc_file = g_file_new_for_commandline_arg (system_gimprc);

  if (user_gimprc)
    user_gimprc_file = g_file_new_for_commandline_arg (user_gimprc);

  /* GimpEarlyRc is responsible for reading "gimprc" files for the
   * sole purpose of getting some configuration data that is needed
   * in the early initialization phase
   */

  earlyrc = gimp_early_rc_new (system_gimprc_file,
                               user_gimprc_file,
                               be_verbose);

  /* Language needs to be determined first, before any GimpContext is
   * instantiated (which happens when the Gimp object is created)
   * because its properties need to be properly localized in the
   * settings language (if different from system language). Otherwise we
   * end up with pieces of GUI always using the system language (cf. bug
   * 787457)
   */

  language = gimp_early_rc_get_language (earlyrc);

  /*  change the locale if a language if specified  */
  language_init (language, NULL);
  if (language)
    g_free (language);

#if defined (G_OS_WIN32) && !defined (GIMP_CONSOLE_COMPILATION)

#if GTK_MAJOR_VERSION > 3
#warning For GTK4 and above use the proper backend-specific API instead of the GDK_WIN32_TABLET_INPUT_API environment variable
#endif

  /* Set a GdkWin32-specific environment variable to specify
   * the desired pen / touch input API to use on Windows
  */

  if (gtk_get_major_version () == 3 &&
      (gtk_get_minor_version () > 24 ||
       (gtk_get_minor_version () == 24 &&
        gtk_get_micro_version () >= 30)))
    {
      GimpWin32PointerInputAPI api = gimp_early_rc_get_win32_pointer_input_api (earlyrc);

      switch (api)
        {
        case GIMP_WIN32_POINTER_INPUT_API_WINTAB:
          g_setenv ("GDK_WIN32_TABLET_INPUT_API", "wintab", TRUE);
          break;
        case GIMP_WIN32_POINTER_INPUT_API_WINDOWS_INK:
          g_setenv ("GDK_WIN32_TABLET_INPUT_API", "winpointer", TRUE);
          break;
        }
    }

#endif

  g_object_unref (earlyrc);

  g_clear_object (&system_gimprc_file);
  g_clear_object (&user_gimprc_file);
}

static gboolean
gimp_options_group_parse_hook (GOptionContext   *context,
                               GOptionGroup     *group,
                               gpointer          data,
                               GError          **error)
{
  /*  early initialization from data stored in "gimprc" files  */
  gimp_early_configuration ();

  return TRUE;
}

int
main (int    argc,
      char **argv)
{
  GOptionContext *context;
  const gchar    *abort_message;
  GFile          *system_gimprc_file = NULL;
  GFile          *user_gimprc_file   = NULL;
  GOptionGroup   *gimp_group         = NULL;
  gchar          *backtrace_file     = NULL;
  GError         *error              = NULL;
#ifdef G_OS_WIN32
  gchar          *utf8_name;
  wchar_t        *name;
#endif
  gint            retval;
  gint            i;

  gimp_attach_console_window ();

#if defined(ENABLE_RELOCATABLE_RESOURCES) && defined(__APPLE__)
  /* remove MacOS session identifier from the command line args */
  gint newargc = 0;
  for (gint i = 0; i < argc; i++)
    {
      if (!g_str_has_prefix (argv[i], "-psn_"))
        {
          argv[newargc] = argv[i];
          newargc++;
        }
    }

  if (argc > newargc)
    {
      argv[newargc] = NULL; /* glib expects NULL terminated array */
      argc = newargc;
    }

  gimp_macos_setenv (argv[0]);
#endif

#if defined (__GNUC__) && defined (_WIN64)
  /* mingw-w64, at least the unstable build from late July 2008,
   * starts subsystem:windows programs in main(), but passes them
   * bogus argc and argv. __argc and __argv are OK, though, so just
   * use them.
   */

  argc = __argc;
  argv = __argv;
#endif

  /* Initialize GimpBacktrace early on.  In particular, we want the
   * Windows backend to catch the SET_THREAD_NAME exceptions of newly
   * created threads.
   */

  gimp_backtrace_init ();

  /* Start signal handlers early. */
  gimp_init_signal_handlers (&backtrace_file);

#ifdef G_OS_WIN32
  /* Make Inno aware of gimp process avoiding broken install/unninstall */
  utf8_name = g_strdup_printf ("GIMP-%s", GIMP_MUTEX_VERSION);
  name      = g_utf8_to_utf16 (utf8_name, -1, NULL, NULL, NULL);

  CreateMutexW (NULL, FALSE, name);

  g_free (utf8_name);
  g_free (name);

  /* Enable Anti-Aliasing*/
  g_setenv ("PANGOCAIRO_BACKEND", "fc", TRUE);

  /* Reduce risks */
  SetDllDirectoryW (L"");

  {
    const gchar *install_dir;
    gchar       *bin_dir;
    LPWSTR       w_bin_dir;
#ifdef ENABLE_RELOCATABLE_RESOURCES
    size_t       path_len;
    gchar       *path;
#endif

    /* On Windows, set DLL search path to $INSTALLDIR/bin so that .exe
     * plug-ins processes in the plug-ins directory can find libgimp and
     * file library DLLs.
     */

    w_bin_dir = NULL;
    install_dir = gimp_installation_directory ();
    bin_dir = g_build_filename (install_dir, "bin", NULL);

    w_bin_dir = g_utf8_to_utf16 (bin_dir, -1, NULL, NULL, NULL);
    if (w_bin_dir)
      {
        SetDllDirectoryW (w_bin_dir);
        g_free (w_bin_dir);
      }

#ifdef ENABLE_RELOCATABLE_RESOURCES
    /* We also set external PATH variable to other processes just in case
     * (see #14716 and many other issues labeled as 'DLL Hell').
     */

    path_len = strlen (g_getenv ("PATH") ? g_getenv ("PATH") : "") + strlen (bin_dir) + 2;
    path = g_try_malloc (path_len);
    if (path == NULL)
      {
        g_warning ("Failed to allocate memory");
        app_exit (EXIT_FAILURE);
      }
    if (g_getenv ("PATH"))
      g_snprintf (path, path_len, "%s;%s", bin_dir, g_getenv ("PATH"));
    else
      g_snprintf (path, path_len, "%s", bin_dir);
    g_setenv ("PATH", path, TRUE);
    g_free (path);
#endif

    g_free (bin_dir);
  }

#ifndef _WIN64
  {
    typedef BOOL (WINAPI *t_SetProcessDEPPolicy) (DWORD dwFlags);
    t_SetProcessDEPPolicy p_SetProcessDEPPolicy;

    p_SetProcessDEPPolicy =
      (t_SetProcessDEPPolicy) GetProcAddress (GetModuleHandleW (L"kernel32.dll"),
                                              "SetProcessDEPPolicy");
    if (p_SetProcessDEPPolicy)
      (*p_SetProcessDEPPolicy) (PROCESS_DEP_ENABLE |
                                PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION);
  }
#endif

  /* Group all our windows together on the taskbar */
  {
    typedef HRESULT (WINAPI *t_SetCurrentProcessExplicitAppUserModelID) (PCWSTR lpPathName);
    t_SetCurrentProcessExplicitAppUserModelID p_SetCurrentProcessExplicitAppUserModelID;

    p_SetCurrentProcessExplicitAppUserModelID =
      (t_SetCurrentProcessExplicitAppUserModelID) GetProcAddress (GetModuleHandleW (L"shell32.dll"),
                                                                  "SetCurrentProcessExplicitAppUserModelID");
    if (p_SetCurrentProcessExplicitAppUserModelID)
      (*p_SetCurrentProcessExplicitAppUserModelID) (L"gimp.GimpApplication");
  }
#endif

  gimp_init_malloc ();

  gimp_env_init (FALSE);

  gimp_log_init ();

  gimp_init_i18n ();

  g_set_application_name (GIMP_NAME);

#ifdef G_OS_WIN32
  argv = g_win32_get_command_line ();
#else
  argv = g_strdupv (argv);
#endif

  g_set_prgname (GIMP_DESKTOP_NAME);

  /* Check argv[] for "--verbose" first */
  for (i = 1; i < argc; i++)
    {
      const gchar *arg = argv[i];

      if (arg[0] != '-')
        continue;

      if ((strcmp (arg, "--verbose") == 0) || (strcmp (arg, "-v") == 0))
        {
          be_verbose = TRUE;
        }
    }

  /* Check argv[] for "--no-interface" before trying to initialize gtk+. */
  for (i = 1; i < argc; i++)
    {
      const gchar *arg = argv[i];

      if (arg[0] != '-')
        continue;

      if ((strcmp (arg, "--no-interface") == 0) || (strcmp (arg, "-i") == 0))
        {
          no_interface = TRUE;
        }
      else if ((strcmp (arg, "--version") == 0) || (strcmp (arg, "-v") == 0))
        {
          gimp_show_version_and_exit ();
        }
#if defined (G_OS_WIN32) && !defined (GIMP_CONSOLE_COMPILATION)
      else if ((strcmp (arg, "--help") == 0) ||
               (strcmp (arg, "-?") == 0) ||
               (strncmp (arg, "--help-", 7) == 0))
        {
          gimp_attach_console_window ();
        }
#endif
    }

#ifdef GIMP_CONSOLE_COMPILATION
  no_interface = TRUE;
#endif

  context = g_option_context_new (_("[FILE|URI...]"));
  g_option_context_set_summary (context, GIMP_NAME);

  g_option_context_add_main_entries (context, main_entries, GETTEXT_PACKAGE);

  /* The GIMP option group is just an empty option group, created for
   * the sole purpose of running a post-parse hook before any other of
   * dependent libraries are run. This makes it possible to apply
   * options from configuration data obtained from "gimprc" files,
   * before other libraries have a chance to run some of their
   * initialization code.
   */

  gimp_group = g_option_group_new ("gimp", "", "", NULL, NULL);
  g_option_group_set_parse_hooks (gimp_group, NULL,
                                  gimp_options_group_parse_hook);
  g_option_context_add_group (context, gimp_group);

  app_libs_init (context, no_interface);

  if (! g_option_context_parse_strv (context, &argv, &error))
    {
      if (error)
        {
          gimp_attach_console_window ();
          g_print ("%s\n", error->message);
          g_error_free (error);
        }
      else
        {
          g_print ("%s\n",
                   _("GIMP could not initialize the graphical user interface.\n"
                     "Make sure a proper setup for your display environment "
                     "exists."));
        }

      app_exit (EXIT_FAILURE);
    }

#if GLIB_CHECK_VERSION(2,72,0)
  /* g_set_prgname() can only be called several times since 2.72.0. */
#ifndef GIMP_CONSOLE_COMPILATION
  if (! no_interface)
    {
      GKeyFile *flatpak_keyfile;

      g_return_val_if_fail (gdk_display_get_default () != NULL, EXIT_FAILURE);

      flatpak_keyfile = g_key_file_new ();

      if (
#ifdef GDK_WINDOWING_X11
          ! GDK_IS_X11_DISPLAY (gdk_display_get_default ()) &&
#endif
          g_key_file_load_from_file (flatpak_keyfile, "/.flatpak-info",
                                     G_KEY_FILE_NONE, NULL))
        {
          /* Flatpak renames the desktop file. The .flatpak-info file
           * tells us the right desktop name we must associate our process
           * to, especially as we have flatpaks with different IDs.
           *
           * This logic should not apply on X11 which will instead
           * apparently use the StartupWMClass set in the desktop file and
           * expect it to be the same as the name set by g_set_prgname().
           *
           * Cf. #13183 and #14233.
           */

          gchar *flatpak_name = g_key_file_get_string (flatpak_keyfile,
                                                       "Application", "name", NULL);

          if (flatpak_name != NULL)
            {
              g_set_prgname (flatpak_name);
              g_free (flatpak_name);
            }
          /* The else case should never happen unless we are in some kind
           * of broken flatpak environment or somehow in a non-flatpak
           * environment with a .flatpak-info file at the root, which
           * seems improbable. Fail silently.
           */

        }

      g_key_file_free (flatpak_keyfile);
    }
#endif
#endif

  if (no_interface)
    new_instance = TRUE;

#ifndef GIMP_CONSOLE_COMPILATION
  if (! new_instance && gimp_unique_open (filenames, as_new))
    {
      int success = EXIT_SUCCESS;

      if (be_verbose)
        g_print ("%s\n",
                 _("Another GIMP instance is already running."));

      if (batch_commands &&
          ! gimp_unique_batch_run (batch_interpreter, batch_commands))
        success = EXIT_FAILURE;

      gdk_notify_startup_complete ();

      return success;
    }
#endif

  abort_message = sanity_check_early ();
  if (abort_message)
    app_abort (no_interface, abort_message);

  if (system_gimprc)
    system_gimprc_file = g_file_new_for_commandline_arg (system_gimprc);

  if (user_gimprc)
    user_gimprc_file = g_file_new_for_commandline_arg (user_gimprc);

  retval = app_run (argv[0],
                    filenames,
                    system_gimprc_file,
                    user_gimprc_file,
                    session_name,
                    batch_interpreter,
                    batch_commands,
                    quit,
                    as_new,
                    no_interface,
                    no_data,
                    no_fonts,
                    no_splash,
                    be_verbose,
                    use_shm,
                    use_cpu_accel,
                    console_messages,
                    use_debug_handler,
                    show_playground,
                    show_debug_menu,
                    stack_trace_mode,
                    pdb_compat_mode,
                    backtrace_file);

  g_free (backtrace_file);

  g_clear_object (&system_gimprc_file);
  g_clear_object (&user_gimprc_file);

  g_strfreev (argv);

  g_option_context_free (context);

  return retval;
}


#ifdef G_OS_WIN32

/* Provide WinMain in case we build GIMP as a subsystem:windows
 * application. Well, we do. When built with mingw, though, user code
 * execution still starts in main() in that case. So WinMain() gets
 * used on MSVC builds only.
 */


int WINAPI
WinMain (HINSTANCE hInstance,
         HINSTANCE hPrevInstance,
         LPSTR     lpCmdLine,
         int       nCmdShow)
{
  return main (__argc, __argv);
}

#ifndef GIMP_CONSOLE_COMPILATION

static void
wait_console_window (void)
{
  g_print (_ ("(Type any character to close this window)\n"));
}

static void
gimp_attach_console_window (void)
{
  /* If run on non-native shell, do nothing */
  if (g_getenv ("TERM") || g_getenv ("SHELL"))
    {
      g_printerr ("Non-native shell detected, GIMP may "
                  "behave unexpectedly on Unix shells in Windows.\n");
      return;
    }

  /* If run on native shell, attach to it */
  if (AttachConsole (ATTACH_PARENT_PROCESS) != 0)
    {
      /* 'r' is needed to prevent interleaving and '+' to support colors */
      freopen ("CONOUT$", "r+", stdout);
      freopen ("CONOUT$", "r+", stderr);
      _flushall ();

      {
        /* CTRL+C handling */
        HANDLE hIn = GetStdHandle (STD_INPUT_HANDLE);
        DWORD  mode;

        GetConsoleMode (hIn, &mode);
        mode |= ENABLE_PROCESSED_INPUT;
        SetConsoleMode (hIn, mode);
      }

      atexit (wait_console_window);
    }
}
#endif

#endif /* G_OS_WIN32 */


static gboolean
gimp_option_fatal_warnings (const gchar  *option_name,
                            const gchar  *value,
                            gpointer      data,
                            GError      **error)
{
  GLogLevelFlags fatal_mask;

  fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
  fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;

  g_log_set_always_fatal (fatal_mask);

  return TRUE;
}

static gboolean
gimp_option_stack_trace_mode (const gchar  *option_name,
                              const gchar  *value,
                              gpointer      data,
                              GError      **error)
{
  if (strcmp (value, "never") == 0)
    stack_trace_mode = GIMP_STACK_TRACE_NEVER;
  else if (strcmp (value, "query") == 0)
    stack_trace_mode = GIMP_STACK_TRACE_QUERY;
  else if (strcmp (value, "always") == 0)
    stack_trace_mode = GIMP_STACK_TRACE_ALWAYS;
  else
    return FALSE;

  return TRUE;
}

static gboolean
gimp_option_pdb_compat_mode (const gchar  *option_name,
                             const gchar  *value,
                             gpointer      data,
                             GError      **error)
{
  if (! strcmp (value, "off"))
    pdb_compat_mode = GIMP_PDB_COMPAT_OFF;
  else if (! strcmp (value, "on"))
    pdb_compat_mode = GIMP_PDB_COMPAT_ON;
  else if (! strcmp (value, "warn"))
    pdb_compat_mode = GIMP_PDB_COMPAT_WARN;
  else
    return FALSE;

  return TRUE;
}

static gboolean
gimp_option_dump_gimprc (const gchar  *option_name,
                         const gchar  *value,
                         gpointer      data,
                         GError      **error)
{
  GimpConfigDumpFormat format = GIMP_CONFIG_DUMP_NONE;

  gimp_attach_console_window ();

  if (strcmp (option_name, "--dump-gimprc") == 0)
    format = GIMP_CONFIG_DUMP_GIMPRC;
  if (strcmp (option_name, "--dump-gimprc-system") == 0)
    format = GIMP_CONFIG_DUMP_GIMPRC_SYSTEM;
  else if (strcmp (option_name, "--dump-gimprc-manpage") == 0)
    format = GIMP_CONFIG_DUMP_GIMPRC_MANPAGE;

  if (format)
    {
      Gimp     *gimp;
      gboolean  success;

      babl_init ();
      gimp = g_object_new (GIMP_TYPE_GIMP, NULL);
      gimp_load_config (gimp, NULL, NULL);

      success = gimp_config_dump (G_OBJECT (gimp), format);

      g_object_unref (gimp);

      app_exit (success ? EXIT_SUCCESS : EXIT_FAILURE);
    }

  return FALSE;
}

static gboolean
gimp_option_dump_pdb_procedures_deprecated (const gchar  *option_name,
                                            const gchar  *value,
                                            gpointer      data,
                                            GError      **error)
{
  Gimp  *gimp;
  GList *deprecated_procs;
  GList *iter;

  babl_init ();
  gimp = g_object_new (GIMP_TYPE_GIMP, NULL);
  gimp_load_config (gimp, NULL, NULL);

  /* Make sure to turn on compatibility mode so deprecated procedures
   * are included
   */

  gimp->pdb_compat_mode = GIMP_PDB_COMPAT_ON;

  /* Initialize the list of procedures */
  internal_procs_init (gimp->pdb);

  /* Get deprecated procedures */
  deprecated_procs = gimp_pdb_get_deprecated_procedures (gimp->pdb);

  for (iter = deprecated_procs; iter; iter = g_list_next (iter))
    {
      GimpProcedure *procedure = GIMP_PROCEDURE (iter->data);

      g_print ("%s\n", gimp_object_get_name (procedure));
    }

  g_list_free (deprecated_procs);

  g_object_unref (gimp);

  app_exit (EXIT_SUCCESS);

  return FALSE;
}

static void
gimp_show_version_and_exit (void)
{
  gimp_attach_console_window ();
  gimp_version_show (be_verbose);

  app_exit (EXIT_SUCCESS);
}

static void
gimp_show_license_and_exit (void)
{
  gimp_attach_console_window ();
  gimp_version_show (be_verbose);

  g_print ("\n%s\n\n", GIMP_LICENSE);

  app_exit (EXIT_SUCCESS);
}

static void
gimp_init_malloc (void)
{
#ifdef GIMP_GLIB_MEM_PROFILER
  g_mem_set_vtable (glib_mem_profiler_table);
  g_atexit (g_mem_profile);
#endif

#ifdef __GLIBC__
  /* Tweak memory allocation so that memory allocated in chunks >= 4k
   * (64x64 pixel 1bpp tile) gets returned to the system when free()'d.
   *
   * The default value for M_MMAP_THRESHOLD in glibc-2.3 is 128k.
   * This is said to be an empirically derived value that works well
   * in most systems. Lowering it to 4k is thus probably not the ideal
   * solution.
   *
   * An alternative to tuning this parameter would be to use
   * malloc_trim(), for example after releasing a large tile-manager.
   */

#if 0
  mallopt (M_MMAP_THRESHOLD, TILE_WIDTH * TILE_HEIGHT);
#endif
#endif
}

static void
gimp_init_i18n (void)
{
  /*  We may change the locale later if the user specifies a language
   *  in the gimprc file. Here we are just initializing the locale
   *  according to the environment variables and set up the paths to
   *  the message catalogs.
   */


  setlocale (LC_ALL, "");

  gimp_bind_text_domain (GETTEXT_PACKAGE"-libgimp", gimp_locale_directory ());
#ifdef HAVE_BIND_TEXTDOMAIN_CODESET
  bind_textdomain_codeset (GETTEXT_PACKAGE"-libgimp", "UTF-8");
#endif

  gimp_bind_text_domain (GETTEXT_PACKAGE, gimp_locale_directory ());
#ifdef HAVE_BIND_TEXTDOMAIN_CODESET
  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
#endif

#ifdef HAVE_ISO_CODES
  /* This iso-codes domain is the only external text domain our core
   * code is using. Let's make usre it's properly initialized.
   */

#ifdef ENABLE_RELOCATABLE_RESOURCES
  gimp_bind_text_domain ("iso_639_3", gimp_locale_directory ());
#else
  gimp_bind_text_domain ("iso_639_3", ISO_CODES_LOCALEDIR);
#endif

#ifdef HAVE_BIND_TEXTDOMAIN_CODESET
  bind_textdomain_codeset ("iso_639_3", "UTF-8");
#endif
#endif

  textdomain (GETTEXT_PACKAGE);
}

Messung
CHZG
859710094

¤ Dauer der Verarbeitung: 0.9 Sekunden  (vorverarbeitet am  2026-11-04) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover


Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.