main.c 6.72 KB
Newer Older
1 2
/* See LICENSE file for license and copyright information */

3 4 5 6
#define _BSD_SOURCE
#define _XOPEN_SOURCE 700

#include <errno.h>
7
#include <girara/utils.h>
8 9 10
#include <glib/gi18n.h>
#include <glib/gstdio.h>
#include <limits.h>
Moritz Lipp's avatar
Moritz Lipp committed
11
#include <locale.h>
12 13 14
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Sebastian Ramacher's avatar
Sebastian Ramacher committed
15
#include <unistd.h>
16 17

#include "zathura.h"
18
#include "utils.h"
Sebastian Ramacher's avatar
Sebastian Ramacher committed
19
#include "dbus-interface.h"
20 21

/* main function */
22 23
int
main(int argc, char* argv[])
24
{
25
  /* init locale */
26 27 28 29 30
  setlocale(LC_ALL, "");
  bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
  bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
  textdomain(GETTEXT_PACKAGE);

31
  /* init gtk */
32
#if !GLIB_CHECK_VERSION(2, 31, 0)
33
  g_thread_init(NULL);
34
#endif
35
#if !GTK_CHECK_VERSION(3, 6, 0)
36
  gdk_threads_init();
37
#endif
38 39
  gtk_init(&argc, &argv);

40 41 42 43 44 45 46
  /* parse command line arguments */
  gchar* config_dir     = NULL;
  gchar* data_dir       = NULL;
  gchar* plugin_path    = NULL;
  gchar* loglevel       = NULL;
  gchar* password       = NULL;
  gchar* synctex_editor = NULL;
47
  gchar* synctex_fwd    = NULL;
Sebastian Ramacher's avatar
Sebastian Ramacher committed
48
  gchar* mode           = NULL;
49 50
  bool forkback         = false;
  bool print_version    = false;
Moritz Lipp's avatar
Moritz Lipp committed
51
  bool synctex          = false;
52
  int page_number       = ZATHURA_PAGE_NUMBER_UNSPECIFIED;
53
  int synctex_pid       = -1;
Sebastian Ramacher's avatar
Sebastian Ramacher committed
54
  Window embed          = 0;
55 56

  GOptionEntry entries[] = {
57 58 59 60 61 62 63 64 65 66 67
    { "reparent",               'e',  0, G_OPTION_ARG_INT,      &embed,          _("Reparents to window specified by xid"),              "xid"  },
    { "config-dir",             'c',  0, G_OPTION_ARG_FILENAME, &config_dir,     _("Path to the config directory"),                      "path" },
    { "data-dir",               'd',  0, G_OPTION_ARG_FILENAME, &data_dir,       _("Path to the data directory"),                        "path" },
    { "plugins-dir",            'p',  0, G_OPTION_ARG_STRING,   &plugin_path,    _("Path to the directories containing plugins"),        "path" },
    { "fork",                   '\0', 0, G_OPTION_ARG_NONE,     &forkback,       _("Fork into the background"),                          NULL },
    { "password",               'w',  0, G_OPTION_ARG_STRING,   &password,       _("Document password"),                                 "password" },
    { "page",                   'P',  0, G_OPTION_ARG_INT,      &page_number,    _("Page number to go to"),                              "number" },
    { "debug",                  'l',  0, G_OPTION_ARG_STRING,   &loglevel,       _("Log level (debug, info, warning, error)"),           "level" },
    { "version",                'v',  0, G_OPTION_ARG_NONE,     &print_version,  _("Print version information"),                         NULL },
    { "synctex",                's',  0, G_OPTION_ARG_NONE,     &synctex,        _("Enable synctex support"),                            NULL },
    { "synctex-editor-command", 'x',  0, G_OPTION_ARG_STRING,   &synctex_editor, _("Synctex editor (forwarded to the synctex command)"), "cmd" },
Sebastian Ramacher's avatar
Sebastian Ramacher committed
68
    { "synctex-forward",        '\0', 0, G_OPTION_ARG_STRING,   &synctex_fwd,    _("Move to given synctex position"),                    "position" },
69
    { "synctex-pid",            '\0', 0, G_OPTION_ARG_INT,      &synctex_pid,    _("Highlight given position in the given process"),     "pid" },
Sebastian Ramacher's avatar
Sebastian Ramacher committed
70
    { "mode",                   '\0', 0, G_OPTION_ARG_STRING,   &mode,           _("Start in a non-default mode"),                       "mode" },
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
    { NULL, '\0', 0, 0, NULL, NULL, NULL }
  };

  GOptionContext* context = g_option_context_new(" [file1] [file2] [...]");
  g_option_context_add_main_entries(context, entries, NULL);

  GError* error = NULL;
  if (g_option_context_parse(context, &argc, &argv, &error) == false) {
    girara_error("Error parsing command line arguments: %s\n", error->message);
    g_option_context_free(context);
    g_error_free(error);

    return -1;
  }
  g_option_context_free(context);

Sebastian Ramacher's avatar
Sebastian Ramacher committed
87 88 89 90 91 92 93 94 95
  /* Set log level. */
  if (loglevel == NULL || g_strcmp0(loglevel, "info") == 0) {
    girara_set_debug_level(GIRARA_INFO);
  } else if (g_strcmp0(loglevel, "warning") == 0) {
    girara_set_debug_level(GIRARA_WARNING);
  } else if (g_strcmp0(loglevel, "error") == 0) {
    girara_set_debug_level(GIRARA_ERROR);
  }

Sebastian Ramacher's avatar
Sebastian Ramacher committed
96
  /* handle synctex forward synchronization */
97 98
  if (synctex_fwd != NULL) {
    if (argc != 2) {
99
      girara_error("Too many arguments or missing filename while running with --synctex-forward");
100 101 102
      return -1;
    }

103 104 105 106 107 108
    char* real_path = realpath(argv[1], NULL);
    if (real_path == NULL) {
      girara_error("Failed to determine real path: %s", strerror(errno));
      return -1;
    }

109
    if (zathura_dbus_synctex_position(real_path, synctex_fwd, synctex_pid) == true) {
Sebastian Ramacher's avatar
Sebastian Ramacher committed
110
      free(real_path);
111
      return 0;
112
    } else {
113
      girara_error("Could not find open instance for '%s' or got no usable output from 'synctex view'.", real_path);
Sebastian Ramacher's avatar
Sebastian Ramacher committed
114
      free(real_path);
115
      return -1;
116 117 118
    }
  }

Sebastian Ramacher's avatar
Sebastian Ramacher committed
119 120 121 122 123
  /* check mode */
  if (mode != NULL && g_strcmp0(mode, "presentation") != 0 && g_strcmp0(mode, "fullscreen") != 0) {
    girara_error("Invalid argument for --mode: %s", mode);
    return -1;
  }
124

125 126
  /* Fork into the background if the user really wants to ... */
  if (forkback == true) {
127
    const int pid = fork();
128
    if (pid > 0) { /* parent */
129
      return 0;
130 131 132 133 134 135 136
    } else if (pid < 0) { /* error */
      girara_error("Couldn't fork.");
    }

    setsid();
  }

137 138 139 140 141 142
  /* create zathura session */
  zathura_t* zathura = zathura_create();
  if (zathura == NULL) {
    return -1;
  }

143 144 145 146 147 148 149 150
  zathura_set_xid(zathura, embed);
  zathura_set_config_dir(zathura, config_dir);
  zathura_set_data_dir(zathura, data_dir);
  zathura_set_plugin_dir(zathura, plugin_path);
  zathura_set_synctex_editor_command(zathura, synctex_editor);
  zathura_set_argv(zathura, argv);

  /* Init zathura */
151
  if (zathura_init(zathura) == false) {
152 153 154 155 156
    girara_error("Could not initialize zathura.");
    zathura_free(zathura);
    return -1;
  }

Moritz Lipp's avatar
Moritz Lipp committed
157
  /* Enable/Disable synctex support */
158
  zathura_set_synctex(zathura, synctex);
Moritz Lipp's avatar
Moritz Lipp committed
159

160 161 162 163 164 165 166 167 168 169 170 171 172
  /* Print version */
  if (print_version == true) {
    char* string = zathura_get_version_string(zathura, false);
    if (string != NULL) {
      fprintf(stdout, "%s\n", string);
    }
    zathura_free(zathura);

    return 0;
  }

  /* open document if passed */
  if (argc > 1) {
173 174
    if (page_number > 0)
      --page_number;
Sebastian Ramacher's avatar
Sebastian Ramacher committed
175
    document_open_idle(zathura, argv[1], password, page_number, mode);
176 177 178 179 180 181 182 183 184 185 186 187 188 189

    /* open additional files */
    for (int i = 2; i < argc; i++) {
      char* new_argv[] = {
        *(zathura->global.arguments),
        argv[i],
        NULL
      };

      g_spawn_async(NULL, new_argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, NULL);
    }
  }

  /* run zathura */
190
#if !GTK_CHECK_VERSION(3, 6, 0)
191
  gdk_threads_enter();
192
#endif
193
  gtk_main();
194
#if !GTK_CHECK_VERSION(3, 6, 0)
195
  gdk_threads_leave();
196
#endif
197

198
  /* free zathura */
199 200 201 202
  zathura_free(zathura);

  return 0;
}