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

3
#define _DEFAULT_SOURCE
Sebastian Ramacher's avatar
Sebastian Ramacher committed
4
#define _XOPEN_SOURCE 700
5

6
#include <errno.h>
Moritz Lipp's avatar
Moritz Lipp committed
7
#include <stdlib.h>
Pavel Borzenkov's avatar
Pavel Borzenkov committed
8
#include <unistd.h>
9
#include <math.h>
10
#include <string.h>
Moritz Lipp's avatar
Moritz Lipp committed
11

12 13 14 15 16
#include <girara/datastructures.h>
#include <girara/utils.h>
#include <girara/session.h>
#include <girara/statusbar.h>
#include <girara/settings.h>
17
#include <girara/shortcuts.h>
18
#include <girara/template.h>
19
#include <glib/gstdio.h>
20
#include <glib/gi18n.h>
21

Moritz Lipp's avatar
Moritz Lipp committed
22 23 24 25
#ifdef G_OS_UNIX
#include <glib-unix.h>
#endif

26
#include "bookmarks.h"
Moritz Lipp's avatar
Moritz Lipp committed
27 28
#include "callbacks.h"
#include "config.h"
29 30 31 32
#ifdef WITH_SQLITE
#include "database-sqlite.h"
#endif
#include "database-plain.h"
33
#include "document.h"
Moritz Lipp's avatar
Moritz Lipp committed
34
#include "shortcuts.h"
Moritz Lipp's avatar
Moritz Lipp committed
35
#include "zathura.h"
Moritz Lipp's avatar
Moritz Lipp committed
36
#include "utils.h"
Moritz Lipp's avatar
Moritz Lipp committed
37
#include "marks.h"
Sebastian Ramacher's avatar
Sebastian Ramacher committed
38
#include "render.h"
Moritz Lipp's avatar
Moritz Lipp committed
39
#include "page.h"
40
#include "page-widget.h"
41
#include "plugin.h"
42
#include "adjustment.h"
Sebastian Ramacher's avatar
Sebastian Ramacher committed
43
#include "dbus-interface.h"
44
#include "css-definitions.h"
45
#include "synctex.h"
Moritz Lipp's avatar
Moritz Lipp committed
46

Moritz Lipp's avatar
Moritz Lipp committed
47
typedef struct zathura_document_info_s {
Moritz Lipp's avatar
Moritz Lipp committed
48 49 50
  zathura_t* zathura;
  const char* path;
  const char* password;
51
  int page_number;
Sebastian Ramacher's avatar
Sebastian Ramacher committed
52
  const char* mode;
53
  const char* synctex;
Moritz Lipp's avatar
Moritz Lipp committed
54 55
} zathura_document_info_t;

56

57
static gboolean document_info_open(gpointer data);
58 59 60
static void zathura_jumplist_reset_current(zathura_t* zathura);
static void zathura_jumplist_append_jump(zathura_t* zathura);
static void zathura_jumplist_save(zathura_t* zathura);
Moritz Lipp's avatar
Moritz Lipp committed
61

Moritz Lipp's avatar
Moritz Lipp committed
62 63 64 65
#ifdef G_OS_UNIX
static gboolean zathura_signal_sigterm(gpointer data);
#endif

Moritz Lipp's avatar
Moritz Lipp committed
66
/* function implementation */
Moritz Lipp's avatar
Moritz Lipp committed
67
zathura_t*
68
zathura_create(void)
69
{
70 71 72 73
  zathura_t* zathura = g_try_malloc0(sizeof(zathura_t));
  if (zathura == NULL) {
    return NULL;
  }
74

75
  /* global settings */
76
  zathura->global.search_direction = FORWARD;
77

78
  /* plugins */
Moritz Lipp's avatar
Moritz Lipp committed
79 80
  zathura->plugins.manager = zathura_plugin_manager_new();
  if (zathura->plugins.manager == NULL) {
81
    goto error_out;
Moritz Lipp's avatar
Moritz Lipp committed
82
  }
83

84 85 86
  /* UI */
  if ((zathura->ui.session = girara_session_create()) == NULL) {
    goto error_out;
Sebastian Ramacher's avatar
Sebastian Ramacher committed
87 88
  }

Moritz Lipp's avatar
Moritz Lipp committed
89 90 91 92 93
#ifdef G_OS_UNIX
  /* signal handler */
  zathura->signals.sigterm = g_unix_signal_add(SIGTERM, zathura_signal_sigterm, zathura);
#endif

94 95 96 97 98 99 100 101 102 103
  zathura->ui.session->global.data = zathura;

  return zathura;

error_out:

  zathura_free(zathura);

  return NULL;
}
Sebastian Ramacher's avatar
Sebastian Ramacher committed
104

105 106 107 108 109
bool
zathura_init(zathura_t* zathura)
{
  if (zathura == NULL) {
    return false;
110 111
  }

112
  /* create zathura (config/data) directory */
113 114 115 116 117 118 119
  if (g_mkdir_with_parents(zathura->config.config_dir, 0771) == -1) {
    girara_error("Could not create '%s': %s", zathura->config.config_dir, strerror(errno));
  }

  if (g_mkdir_with_parents(zathura->config.data_dir, 0771) == -1) {
    girara_error("Could not create '%s': %s", zathura->config.data_dir, strerror(errno));
  }
120

121 122 123
  /* load plugins */
  zathura_plugin_manager_load(zathura->plugins.manager);

124 125
  /* configuration */
  config_load_default(zathura);
126
  config_load_files(zathura);
127

128
  /* UI */
Sebastian Ramacher's avatar
Sebastian Ramacher committed
129
  if (girara_session_init(zathura->ui.session, "zathura") == false) {
Moritz Lipp's avatar
Moritz Lipp committed
130
    goto error_free;
131 132 133
  }

  /* girara events */
Moritz Lipp's avatar
Moritz Lipp committed
134 135
  zathura->ui.session->events.buffer_changed  = cb_buffer_changed;
  zathura->ui.session->events.unknown_command = cb_unknown_command;
136

137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
  /* zathura signals */
  zathura->signals.refresh_view = g_signal_new("refresh-view",
                                               GTK_TYPE_WIDGET,
                                               G_SIGNAL_RUN_LAST,
                                               0,
                                               NULL,
                                               NULL,
                                               g_cclosure_marshal_generic,
                                               G_TYPE_NONE,
                                               1,
                                               G_TYPE_POINTER);

  g_signal_connect(G_OBJECT(zathura->ui.session->gtk.view), "refresh-view",
                   G_CALLBACK(cb_refresh_view), zathura);

152
  /* page view */
153
  zathura->ui.page_widget = gtk_grid_new();
154 155
  gtk_grid_set_row_homogeneous(GTK_GRID(zathura->ui.page_widget), TRUE);
  gtk_grid_set_column_homogeneous(GTK_GRID(zathura->ui.page_widget), TRUE);
Moritz Lipp's avatar
Moritz Lipp committed
156
  if (zathura->ui.page_widget == NULL) {
157 158 159
    goto error_free;
  }

160
  g_signal_connect(G_OBJECT(zathura->ui.session->gtk.window), "size-allocate", G_CALLBACK(cb_view_resized), zathura);
161

162
  GtkAdjustment* hadjustment = gtk_scrolled_window_get_hadjustment(
163
                 GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view));
164 165 166

  /* Connect hadjustment signals */
  g_signal_connect(G_OBJECT(hadjustment), "value-changed",
167
      G_CALLBACK(cb_view_hadjustment_value_changed), zathura);
168 169 170 171
  g_signal_connect(G_OBJECT(hadjustment), "changed",
      G_CALLBACK(cb_view_hadjustment_changed), zathura);

  GtkAdjustment* vadjustment = gtk_scrolled_window_get_vadjustment(
172
                 GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view));
173 174 175 176 177 178

  /* Connect vadjustment signals */
  g_signal_connect(G_OBJECT(vadjustment), "value-changed",
      G_CALLBACK(cb_view_vadjustment_value_changed), zathura);
  g_signal_connect(G_OBJECT(vadjustment), "changed",
      G_CALLBACK(cb_view_vadjustment_changed), zathura);
Moritz Lipp's avatar
Moritz Lipp committed
179

180
  /* page view alignment */
181 182
  gtk_widget_set_halign(zathura->ui.page_widget, GTK_ALIGN_CENTER);
  gtk_widget_set_valign(zathura->ui.page_widget, GTK_ALIGN_CENTER);
183

184 185 186 187
  gtk_widget_set_hexpand_set(zathura->ui.page_widget, TRUE);
  gtk_widget_set_hexpand(zathura->ui.page_widget, FALSE);
  gtk_widget_set_vexpand_set(zathura->ui.page_widget, TRUE);
  gtk_widget_set_vexpand(zathura->ui.page_widget, FALSE);
188

189
  gtk_widget_show(zathura->ui.page_widget);
Moritz Lipp's avatar
Moritz Lipp committed
190

191
  /* statusbar */
Moritz Lipp's avatar
Moritz Lipp committed
192 193
  zathura->ui.statusbar.file = girara_statusbar_item_add(zathura->ui.session, TRUE, TRUE, TRUE, NULL);
  if (zathura->ui.statusbar.file == NULL) {
Moritz Lipp's avatar
Moritz Lipp committed
194
    goto error_free;
Moritz Lipp's avatar
Moritz Lipp committed
195 196
  }

Moritz Lipp's avatar
Moritz Lipp committed
197 198
  zathura->ui.statusbar.buffer = girara_statusbar_item_add(zathura->ui.session, FALSE, FALSE, FALSE, NULL);
  if (zathura->ui.statusbar.buffer == NULL) {
Moritz Lipp's avatar
Moritz Lipp committed
199
    goto error_free;
Moritz Lipp's avatar
Moritz Lipp committed
200 201
  }

Moritz Lipp's avatar
Moritz Lipp committed
202
  zathura->ui.statusbar.page_number = girara_statusbar_item_add(zathura->ui.session, FALSE, FALSE, FALSE, NULL);
Moritz Lipp's avatar
Moritz Lipp committed
203
  if (zathura->ui.statusbar.page_number == NULL) {
Moritz Lipp's avatar
Moritz Lipp committed
204
    goto error_free;
Moritz Lipp's avatar
Moritz Lipp committed
205 206
  }

Sebastian Ramacher's avatar
Sebastian Ramacher committed
207
  girara_statusbar_item_set_text(zathura->ui.session, zathura->ui.statusbar.file, _("[No name]"));
Moritz Lipp's avatar
Moritz Lipp committed
208

Moritz Lipp's avatar
Moritz Lipp committed
209
  /* signals */
210
  g_signal_connect(G_OBJECT(zathura->ui.session->gtk.window), "destroy", G_CALLBACK(cb_destroy), zathura);
211

212
  /* database */
213 214 215 216
  char* database = NULL;
  girara_setting_get(zathura->ui.session, "database", &database);

  if (g_strcmp0(database, "plain") == 0) {
217
    girara_debug("Using plain database backend.");
218 219 220
    zathura->database = zathura_plaindatabase_new(zathura->config.data_dir);
#ifdef WITH_SQLITE
  } else if (g_strcmp0(database, "sqlite") == 0) {
221
    girara_debug("Using sqlite database backend.");
222 223 224 225
    char* tmp = g_build_filename(zathura->config.data_dir, "bookmarks.sqlite", NULL);
    zathura->database = zathura_sqldatabase_new(tmp);
    g_free(tmp);
#endif
226
  } else if (g_strcmp0(database, "null") != 0) {
227 228 229
    girara_error("Database backend '%s' is not supported.", database);
  }

230
  if (zathura->database == NULL && g_strcmp0(database, "null") != 0) {
Sebastian Ramacher's avatar
Sebastian Ramacher committed
231
    girara_error("Unable to initialize database. Bookmarks won't be available.");
232
  } else {
Sebastian Ramacher's avatar
Sebastian Ramacher committed
233
    g_object_set(G_OBJECT(zathura->ui.session->command_history), "io", zathura->database, NULL);
234
  }
235
  g_free(database);
236

237
  /* bookmarks */
238
  zathura->bookmarks.bookmarks = girara_sorted_list_new2((girara_compare_function_t) zathura_bookmarks_compare,
Moritz Lipp's avatar
Moritz Lipp committed
239
                                 (girara_free_function_t) zathura_bookmark_free);
240

241
  /* jumplist */
242 243
  int jumplist_size = 20;
  girara_setting_get(zathura->ui.session, "jumplist-size", &jumplist_size);
244

245 246
  zathura->jumplist.max_size = jumplist_size < 0 ? 0 : jumplist_size;
  zathura->jumplist.list = NULL;
247 248
  zathura->jumplist.size = 0;
  zathura->jumplist.cur = NULL;
249

250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280
  /* CSS for index mode */
  GiraraTemplate* csstemplate = girara_session_get_template(zathura->ui.session);

  static const char* index_settings[] = {
    "index-fg",
    "index-bg",
    "index-active-fg",
    "index-active-bg"
  };

  for (size_t s = 0; s < LENGTH(index_settings); ++s) {
    girara_template_add_variable(csstemplate, index_settings[s]);

    char* tmp_value = NULL;
    GdkRGBA rgba = { 0, 0, 0, 0 };
    girara_setting_get(zathura->ui.session, index_settings[s], &tmp_value);
    if (tmp_value != NULL) {
      gdk_rgba_parse(&rgba, tmp_value);
      g_free(tmp_value);
    }

    char* color = gdk_rgba_to_string(&rgba);
    girara_template_set_variable_value(csstemplate,
        index_settings[s], color);
    g_free(color);
  }

  char* css = g_strdup_printf("%s\n%s", girara_template_get_base(csstemplate), CSS_TEMPLATE_INDEX);
  girara_template_set_base(csstemplate, css);
  g_free(css);

281 282 283 284 285 286 287 288 289 290
  /* Shortcut helpers */
  zathura->shortcut.mouse.x = 0;
  zathura->shortcut.mouse.y = 0;

  zathura->shortcut.toggle_page_mode.pages = 2;

  zathura->shortcut.toggle_presentation_mode.pages = 1;
  zathura->shortcut.toggle_presentation_mode.first_page_column_list = NULL;
  zathura->shortcut.toggle_presentation_mode.zoom = 1.0;

291
  /* Start D-Bus service */
Sebastian Ramacher's avatar
Sebastian Ramacher committed
292 293 294 295
  bool dbus = true;
  girara_setting_get(zathura->ui.session, "dbus-service", &dbus);
  if (dbus == true) {
    zathura->dbus = zathura_dbus_new(zathura);
296 297
  }

298
  return true;
Moritz Lipp's avatar
Moritz Lipp committed
299 300 301

error_free:

Moritz Lipp's avatar
Moritz Lipp committed
302
  if (zathura->ui.page_widget != NULL) {
303
    g_object_unref(zathura->ui.page_widget);
304 305
  }

306
  return false;
Moritz Lipp's avatar
Moritz Lipp committed
307 308 309 310 311 312 313 314 315
}

void
zathura_free(zathura_t* zathura)
{
  if (zathura == NULL) {
    return;
  }

Moritz Lipp's avatar
Moritz Lipp committed
316
  document_close(zathura, false);
317

318
  /* stop D-Bus */
Sebastian Ramacher's avatar
Sebastian Ramacher committed
319 320 321
  if (zathura->dbus != NULL) {
    g_object_unref(zathura->dbus);
    zathura->dbus = NULL;
322 323
  }

Moritz Lipp's avatar
Moritz Lipp committed
324 325 326 327
  if (zathura->ui.session != NULL) {
    girara_session_destroy(zathura->ui.session);
  }

328 329 330
  /* shortcut */
  g_free(zathura->shortcut.toggle_presentation_mode.first_page_column_list);

331 332 333 334 335 336
  /* stdin support */
  if (zathura->stdin_support.file != NULL) {
    g_unlink(zathura->stdin_support.file);
    g_free(zathura->stdin_support.file);
  }

337 338 339
  /* bookmarks */
  girara_list_free(zathura->bookmarks.bookmarks);

340
  /* database */
Sebastian Ramacher's avatar
Sebastian Ramacher committed
341 342 343
  if (zathura->database != NULL) {
    g_object_unref(G_OBJECT(zathura->database));
  }
344

345
  /* free print settings */
Moritz Lipp's avatar
Moritz Lipp committed
346
  if (zathura->print.settings != NULL) {
347 348 349 350 351 352
    g_object_unref(zathura->print.settings);
  }

  if (zathura->print.page_setup != NULL) {
    g_object_unref(zathura->print.page_setup);
  }
353

Moritz Lipp's avatar
Moritz Lipp committed
354
  /* free registered plugins */
Moritz Lipp's avatar
Moritz Lipp committed
355
  zathura_plugin_manager_free(zathura->plugins.manager);
356 357 358 359

  /* free config variables */
  g_free(zathura->config.config_dir);
  g_free(zathura->config.data_dir);
Sebastian Ramacher's avatar
Sebastian Ramacher committed
360
  g_free(zathura->config.cache_dir);
361

362 363 364 365 366 367 368 369 370
  /* free jumplist */
  if (zathura->jumplist.list != NULL) {
    girara_list_free(zathura->jumplist.list);
  }

  if (zathura->jumplist.cur != NULL) {
    girara_list_iterator_free(zathura->jumplist.cur);
  }

371
  g_free(zathura);
372 373
}

374
#ifdef GDK_WINDOWING_X11
375 376 377 378 379 380 381
void
zathura_set_xid(zathura_t* zathura, Window xid)
{
  g_return_if_fail(zathura != NULL);

  zathura->ui.session->gtk.embed = xid;
}
382
#endif
383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400

void
zathura_set_config_dir(zathura_t* zathura, const char* dir)
{
  g_return_if_fail(zathura != NULL);

  if (dir != NULL) {
    zathura->config.config_dir = g_strdup(dir);
  } else {
    gchar* path = girara_get_xdg_path(XDG_CONFIG);
    zathura->config.config_dir = g_build_filename(path, "zathura", NULL);
    g_free(path);
  }
}

void
zathura_set_data_dir(zathura_t* zathura, const char* dir)
{
Sebastian Ramacher's avatar
Sebastian Ramacher committed
401 402
  g_return_if_fail(zathura != NULL);

403 404 405 406 407 408 409
  if (dir != NULL) {
    zathura->config.data_dir = g_strdup(dir);
  } else {
    gchar* path = girara_get_xdg_path(XDG_DATA);
    zathura->config.data_dir = g_build_filename(path, "zathura", NULL);
    g_free(path);
  }
Sebastian Ramacher's avatar
Sebastian Ramacher committed
410
}
411

Sebastian Ramacher's avatar
Sebastian Ramacher committed
412 413 414
void
zathura_set_cache_dir(zathura_t* zathura, const char* dir)
{
415
  g_return_if_fail(zathura != NULL);
Sebastian Ramacher's avatar
Sebastian Ramacher committed
416 417 418 419 420 421 422 423

  if (dir != NULL) {
    zathura->config.cache_dir = g_strdup(dir);
  } else {
    gchar* path = girara_get_xdg_path(XDG_CACHE);
    zathura->config.cache_dir = g_build_filename(path, "zathura", NULL);
    g_free(path);
  }
424 425 426 427 428 429 430 431 432 433 434
}

void
zathura_set_plugin_dir(zathura_t* zathura, const char* dir)
{
  g_return_if_fail(zathura != NULL);
  g_return_if_fail(zathura->plugins.manager != NULL);

  if (dir != NULL) {
    girara_list_t* paths = girara_split_path_array(dir);
    GIRARA_LIST_FOREACH(paths, char*, iter, path)
Moritz Lipp's avatar
Moritz Lipp committed
435
    zathura_plugin_manager_add_dir(zathura->plugins.manager, path);
436 437 438 439 440 441
    GIRARA_LIST_FOREACH_END(paths, char*, iter, path);
    girara_list_free(paths);
  } else {
#ifdef ZATHURA_PLUGINDIR
    girara_list_t* paths = girara_split_path_array(ZATHURA_PLUGINDIR);
    GIRARA_LIST_FOREACH(paths, char*, iter, path)
Moritz Lipp's avatar
Moritz Lipp committed
442
    zathura_plugin_manager_add_dir(zathura->plugins.manager, path);
443 444 445 446 447 448 449 450 451 452 453 454 455 456 457
    GIRARA_LIST_FOREACH_END(paths, char*, iter, path);
    girara_list_free(paths);
#endif
  }

}

void
zathura_set_argv(zathura_t* zathura, char** argv)
{
  g_return_if_fail(zathura != NULL);

  zathura->global.arguments = argv;
}

458
static gchar*
459
prepare_document_open_from_stdin(zathura_t* zathura, const char* path)
460 461 462
{
  g_return_val_if_fail(zathura, NULL);

463 464 465 466 467 468 469 470 471 472 473 474 475 476
  int infileno = -1;
  if (g_strcmp0(path, "-") == 0) {
    infileno = fileno(stdin);
  } else if (g_str_has_prefix(path, "/proc/self/fd/") == true) {
    char* begin = g_strrstr(path, "/") + 1;
    gint64 temp = g_ascii_strtoll(begin, NULL, 0);
    if (temp > INT_MAX || temp < 0) {
      return NULL;
    }
    infileno = (int) temp;
  } else {
    return NULL;
  }

477 478 479
  GError* error = NULL;
  gchar* file = NULL;
  gint handle = g_file_open_tmp("zathura.stdin.XXXXXX", &file, &error);
Moritz Lipp's avatar
Moritz Lipp committed
480
  if (handle == -1) {
481 482 483 484
    if (error != NULL) {
      girara_error("Can not create temporary file: %s", error->message);
      g_error_free(error);
    }
485 486 487
    return NULL;
  }

488 489 490
  // read and dump to temporary file
  if (infileno == -1) {
    girara_error("Can not read from file descriptor.");
491 492 493 494 495 496 497 498
    close(handle);
    g_unlink(file);
    g_free(file);
    return NULL;
  }

  char buffer[BUFSIZ];
  ssize_t count = 0;
499
  while ((count = read(infileno, buffer, BUFSIZ)) > 0) {
Moritz Lipp's avatar
Moritz Lipp committed
500
    if (write(handle, buffer, count) != count) {
501 502 503 504 505 506 507
      girara_error("Can not write to temporary file: %s", file);
      close(handle);
      g_unlink(file);
      g_free(file);
      return NULL;
    }
  }
Moritz Lipp's avatar
Moritz Lipp committed
508

509 510
  close(handle);

Moritz Lipp's avatar
Moritz Lipp committed
511
  if (count != 0) {
512
    girara_error("Can not read from file descriptor.");
513 514 515 516 517 518 519 520
    g_unlink(file);
    g_free(file);
    return NULL;
  }

  return file;
}

521
static gboolean
Moritz Lipp's avatar
Moritz Lipp committed
522 523 524 525 526
document_info_open(gpointer data)
{
  zathura_document_info_t* document_info = data;
  g_return_val_if_fail(document_info != NULL, FALSE);

527
  if (document_info->zathura != NULL && document_info->path != NULL) {
528
    char* file = NULL;
529 530 531
    if (g_strcmp0(document_info->path, "-") == 0 ||
        g_str_has_prefix(document_info->path, "/proc/self/fd/") == true) {
      file = prepare_document_open_from_stdin(document_info->zathura, document_info->path);
532 533
      if (file == NULL) {
        girara_notify(document_info->zathura->ui.session, GIRARA_ERROR,
534
                      _("Could not read file from stdin and write it to a temporary file."));
535 536
      } else {
        document_info->zathura->stdin_support.file = g_strdup(file);
537 538 539 540 541 542
      }
    } else {
      file = g_strdup(document_info->path);
    }

    if (file != NULL) {
543 544 545 546 547 548 549
      if (document_info->synctex != NULL) {
        document_open_synctex(document_info->zathura, file,
                              document_info->password, document_info->synctex);
      } else {
        document_open(document_info->zathura, file, document_info->password,
                      document_info->page_number);
      }
550
      g_free(file);
Sebastian Ramacher's avatar
Sebastian Ramacher committed
551 552 553 554 555 556 557 558 559 560 561 562

      if (document_info->mode != NULL) {
        if (g_strcmp0(document_info->mode, "presentation") == 0) {
          sc_toggle_presentation(document_info->zathura->ui.session, NULL, NULL,
                                 0);
        } else if (g_strcmp0(document_info->mode, "fullscreen") == 0) {
          sc_toggle_fullscreen(document_info->zathura->ui.session, NULL, NULL,
                               0);
        } else {
          girara_error("Unknown mode: %s", document_info->mode);
        }
      }
563
    }
Moritz Lipp's avatar
Moritz Lipp committed
564 565
  }

566
  g_free(document_info);
Moritz Lipp's avatar
Moritz Lipp committed
567
  return FALSE;
568 569
}

570
static char*
571
get_formatted_filename(zathura_t* zathura, const char* file_path, bool statusbar)
572 573
{
  bool basename_only = false;
Sebastian Ramacher's avatar
Sebastian Ramacher committed
574
  if (statusbar == true) {
575 576 577 578 579
    girara_setting_get(zathura->ui.session, "window-title-basename", &basename_only);
  } else {
    girara_setting_get(zathura->ui.session, "statusbar-basename", &basename_only);
  }

580 581
  if (basename_only == false) {
    bool home_tilde = false;
582 583 584 585 586 587
    if (statusbar) {
      girara_setting_get(zathura->ui.session, "statusbar-home-tilde", &home_tilde);
    } else {
      girara_setting_get(zathura->ui.session, "window-title-home-tilde", &home_tilde);
    }

Sebastian Ramacher's avatar
Sebastian Ramacher committed
588
    const size_t file_path_len = file_path ? strlen(file_path) : 0;
589

Sebastian Ramacher's avatar
Sebastian Ramacher committed
590 591 592
    if (home_tilde == true) {
      char* home = girara_get_home_directory(NULL);
      const size_t home_len = home ? strlen(home) : 0;
593

Sidharth Kapur's avatar
Sidharth Kapur committed
594 595 596 597
      if (home_len > 1
          && file_path_len >= home_len
          && g_str_has_prefix(file_path, home)
          && (!file_path[home_len] || file_path[home_len] == '/')) {
Sebastian Ramacher's avatar
Sebastian Ramacher committed
598
        g_free(home);
Sebastian Ramacher's avatar
Sebastian Ramacher committed
599
        return g_strdup_printf("~%s", &file_path[home_len]);
600
      } else {
Sebastian Ramacher's avatar
Sebastian Ramacher committed
601
        g_free(home);
602
        return g_strdup(file_path);
603 604
      }
    } else {
605
      return g_strdup(file_path);
606 607
    }
  } else {
608
    const char* basename = zathura_document_get_basename(zathura->document);
609
    return g_strdup(basename);
610 611 612
  }
}

613 614 615 616 617 618 619 620 621 622
static gboolean
document_open_password_dialog(gpointer data)
{
  zathura_password_dialog_info_t* password_dialog_info = data;

  girara_dialog(password_dialog_info->zathura->ui.session, _("Enter password:"), true, NULL,
                (girara_callback_inputbar_activate_t) cb_password_dialog, password_dialog_info);
  return FALSE;
}

Moritz Lipp's avatar
Moritz Lipp committed
623
bool
624 625
document_open(zathura_t* zathura, const char* path, const char* password,
              int page_number)
Moritz Lipp's avatar
Moritz Lipp committed
626
{
627
  if (zathura == NULL || zathura->plugins.manager == NULL || path == NULL) {
628
    goto error_out;
Moritz Lipp's avatar
Moritz Lipp committed
629 630
  }

631
  gchar* file_uri = NULL;
632 633
  zathura_error_t error = ZATHURA_ERROR_OK;
  zathura_document_t* document = zathura_document_open(zathura->plugins.manager, path, password, &error);
Moritz Lipp's avatar
Moritz Lipp committed
634

Moritz Lipp's avatar
Moritz Lipp committed
635
  if (document == NULL) {
636
    if (error == ZATHURA_ERROR_INVALID_PASSWORD) {
637
      girara_debug("Invalid or no password.");
638 639 640
      zathura_password_dialog_info_t* password_dialog_info = malloc(sizeof(zathura_password_dialog_info_t));
      if (password_dialog_info != NULL) {
        password_dialog_info->zathura = zathura;
Sebastian Ramacher's avatar
Sebastian Ramacher committed
641
        password_dialog_info->path = g_strdup(path);
642

Sebastian Ramacher's avatar
Sebastian Ramacher committed
643
        if (password_dialog_info->path != NULL) {
644
          gdk_threads_add_idle(document_open_password_dialog, password_dialog_info);
645 646 647 648 649 650 651
          goto error_out;
        } else {
          free(password_dialog_info);
        }
      }
      goto error_out;
    }
Moritz Lipp's avatar
Moritz Lipp committed
652 653 654
    if (error == ZATHURA_ERROR_OK ) {
      girara_notify(zathura->ui.session, GIRARA_ERROR, _("Unsupported file type. Please install the necessary plugin."));
    }
655
    goto error_out;
Moritz Lipp's avatar
Moritz Lipp committed
656 657
  }

658 659
  const char* file_path        = zathura_document_get_path(document);
  unsigned int number_of_pages = zathura_document_get_number_of_pages(document);
660

661 662 663 664 665 666
  if (number_of_pages == 0) {
    girara_notify(zathura->ui.session, GIRARA_WARNING,
        _("Document does not contain any pages"));
    goto error_free;
  }

667
  /* read history file */
668 669 670 671 672 673
  zathura_fileinfo_t file_info = {
    .current_page = 0,
    .page_offset = 0,
    .scale = 1,
    .rotation = 0,
    .pages_per_row = 0,
674
    .first_page_column_list = NULL,
675 676 677
    .position_x = 0,
    .position_y = 0
  };
678 679 680 681
  bool known_file = false;
  if (zathura->database != NULL) {
    known_file = zathura_db_get_fileinfo(zathura->database, file_path, &file_info);
  }
682

Moritz Lipp's avatar
Moritz Lipp committed
683
  /* set page offset */
684
  zathura_document_set_page_offset(document, file_info.page_offset);
685

686
  /* check for valid scale value */
687 688 689
  if (file_info.scale <= DBL_EPSILON) {
    file_info.scale = 1;
  }
Moritz Lipp's avatar
Moritz Lipp committed
690 691
  zathura_document_set_scale(document,
      zathura_correct_scale_value(zathura->ui.session, file_info.scale));
692 693

  /* check current page number */
694 695 696 697 698 699
  /* if it wasn't specified on the command-line, get it from file_info */
  if (page_number == ZATHURA_PAGE_NUMBER_UNSPECIFIED)
    page_number = file_info.current_page;
  if (page_number < 0)
    page_number += number_of_pages;
  if ((unsigned)page_number > number_of_pages) {
700 701
    girara_warning("document info: '%s' has an invalid page number", file_path);
    zathura_document_set_current_page_number(document, 0);
702
  } else {
703
    zathura_document_set_current_page_number(document, page_number);
704 705 706
  }

  /* check for valid rotation */
707
  if (file_info.rotation % 90 != 0) {
708 709 710
    girara_warning("document info: '%s' has an invalid rotation", file_path);
    zathura_document_set_rotation(document, 0);
  } else {
711
    zathura_document_set_rotation(document, file_info.rotation % 360);
712 713 714 715 716 717 718 719 720 721 722
  }

  /* jump to first page if setting enabled */
  bool always_first_page = false;
  girara_setting_get(zathura->ui.session, "open-first-page", &always_first_page);
  if (always_first_page == true) {
    zathura_document_set_current_page_number(document, 0);
  }

  /* apply open adjustment */
  char* adjust_open = "best-fit";
723
  if (known_file == false && girara_setting_get(zathura->ui.session, "adjust-open", &(adjust_open)) == true) {
724 725 726 727 728 729 730 731
    if (g_strcmp0(adjust_open, "best-fit") == 0) {
      zathura_document_set_adjust_mode(document, ZATHURA_ADJUST_BESTFIT);
    } else if (g_strcmp0(adjust_open, "width") == 0) {
      zathura_document_set_adjust_mode(document, ZATHURA_ADJUST_WIDTH);
    } else {
      zathura_document_set_adjust_mode(document, ZATHURA_ADJUST_NONE);
    }
    g_free(adjust_open);
732 733
  } else {
    zathura_document_set_adjust_mode(document, ZATHURA_ADJUST_NONE);
734 735
  }

736 737 738 739 740
  /* initialize bisect state */
  zathura->bisect.start = 0;
  zathura->bisect.last_jump = zathura_document_get_current_page_number(document);
  zathura->bisect.end = number_of_pages - 1;

741
  /* update statusbar */
742 743 744
  char* filename = get_formatted_filename(zathura, file_path, true);
  girara_statusbar_item_set_text(zathura->ui.session, zathura->ui.statusbar.file, filename);
  g_free(filename);
745

Moritz Lipp's avatar
Moritz Lipp committed
746
  /* install file monitor */
747
  file_uri = g_filename_to_uri(file_path, NULL, NULL);
Moritz Lipp's avatar
Moritz Lipp committed
748 749 750 751 752
  if (file_uri == NULL) {
    goto error_free;
  }

  if (zathura->file_monitor.file == NULL) {
753 754 755 756
    zathura->file_monitor.file = g_file_new_for_uri(file_uri);
    if (zathura->file_monitor.file == NULL) {
      goto error_free;
    }
Moritz Lipp's avatar
Moritz Lipp committed
757 758 759
  }

  if (zathura->file_monitor.monitor == NULL) {
760 761 762 763 764
    zathura->file_monitor.monitor = g_file_monitor_file(zathura->file_monitor.file, G_FILE_MONITOR_NONE, NULL, NULL);
    if (zathura->file_monitor.monitor == NULL) {
      goto error_free;
    }
    g_signal_connect(G_OBJECT(zathura->file_monitor.monitor), "changed", G_CALLBACK(cb_file_monitor), zathura->ui.session);
Moritz Lipp's avatar
Moritz Lipp committed
765 766 767
  }

  if (zathura->file_monitor.file_path == NULL) {
768
    zathura->file_monitor.file_path = g_strdup(file_path);
769 770 771
    if (zathura->file_monitor.file_path == NULL) {
      goto error_free;
    }
Moritz Lipp's avatar
Moritz Lipp committed
772 773
  }

774
  if (password != NULL) {
775
    g_free(zathura->file_monitor.password);
776
    zathura->file_monitor.password = g_strdup(password);
Moritz Lipp's avatar
Moritz Lipp committed
777 778 779 780 781
    if (zathura->file_monitor.password == NULL) {
      goto error_free;
    }
  }

Moritz Lipp's avatar
Moritz Lipp committed
782 783 784 785 786 787
  /* create marks list */
  zathura->global.marks = girara_list_new2((girara_free_function_t) mark_free);
  if (zathura->global.marks == NULL) {
    goto error_free;
  }

Moritz Lipp's avatar
Moritz Lipp committed
788
  zathura->document = document;
Moritz Lipp's avatar
Moritz Lipp committed
789

790 791 792 793 794 795 796 797 798
  /* page cache size */
  int cache_size = 0;
  girara_setting_get(zathura->ui.session, "page-cache-size", &cache_size);
  if (cache_size <= 0) {
    girara_warning("page-cache-size is not positive, using %d instead",
        ZATHURA_PAGE_CACHE_DEFAULT_SIZE);
    cache_size = ZATHURA_PAGE_CACHE_DEFAULT_SIZE;
  }

799
  /* threads */
800
  zathura->sync.render_thread = zathura_renderer_new(cache_size);
801 802 803 804 805

  if (zathura->sync.render_thread == NULL) {
    goto error_free;
  }

Sebastian Ramacher's avatar
Sebastian Ramacher committed
806
  /* set up recolor info in ZathuraRenderer */
807 808 809 810 811 812 813 814 815
  char* recolor_dark = NULL;
  char* recolor_light = NULL;
  girara_setting_get(zathura->ui.session, "recolor-darkcolor", &recolor_dark);
  girara_setting_get(zathura->ui.session, "recolor-lightcolor", &recolor_light);
  zathura_renderer_set_recolor_colors_str(zathura->sync.render_thread,
      recolor_light, recolor_dark);
  g_free(recolor_dark);
  g_free(recolor_light);

816 817 818 819 820
  bool recolor = false;
  girara_setting_get(zathura->ui.session, "recolor", &recolor);
  zathura_renderer_enable_recolor(zathura->sync.render_thread, recolor);
  girara_setting_get(zathura->ui.session, "recolor-keephue", &recolor);
  zathura_renderer_enable_recolor_hue(zathura->sync.render_thread, recolor);
821 822
  girara_setting_get(zathura->ui.session, "recolor-reverse-video", &recolor);
  zathura_renderer_enable_recolor_reverse_video(zathura->sync.render_thread, recolor);
823

824 825 826 827 828 829
  /* get view port size */
  GtkAdjustment* hadjustment = gtk_scrolled_window_get_hadjustment(
                 GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view));
  GtkAdjustment* vadjustment = gtk_scrolled_window_get_vadjustment(
                 GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view));

830
  const unsigned int view_width = (unsigned int)floor(gtk_adjustment_get_page_size(hadjustment));
831
  zathura_document_set_viewport_width(zathura->document, view_width);
832
  const unsigned int view_height = (unsigned int)floor(gtk_adjustment_get_page_size(vadjustment));
833 834
  zathura_document_set_viewport_height(zathura->document, view_height);

835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851
  /* create blank pages */
  zathura->pages = calloc(number_of_pages, sizeof(GtkWidget*));
  if (zathura->pages == NULL) {
    goto error_free;
  }

  for (unsigned int page_id = 0; page_id < number_of_pages; page_id++) {
    zathura_page_t* page = zathura_document_get_page(document, page_id);
    if (page == NULL) {
      goto error_free;
    }

    GtkWidget* page_widget = zathura_page_widget_new(zathura, page);
    if (page_widget == NULL) {
      goto error_free;
    }

akbjker's avatar
akbjker committed
852
    g_object_ref(page_widget);
853 854
    zathura->pages[page_id] = page_widget;

855 856 857
    gtk_widget_set_halign(page_widget, GTK_ALIGN_CENTER);
    gtk_widget_set_valign(page_widget, GTK_ALIGN_CENTER);

858 859 860
    g_signal_connect(G_OBJECT(page_widget), "text-selected",
        G_CALLBACK(cb_page_widget_text_selected), zathura);
    g_signal_connect(G_OBJECT(page_widget), "image-selected",
861
        G_CALLBACK(cb_page_widget_image_selected), zathura);
862 863 864 865
    g_signal_connect(G_OBJECT(page_widget), "enter-link",
        G_CALLBACK(cb_page_widget_link), (gpointer) true);
    g_signal_connect(G_OBJECT(page_widget), "leave-link",
        G_CALLBACK(cb_page_widget_link), (gpointer) false);
866 867
    g_signal_connect(G_OBJECT(page_widget), "scaled-button-release",
        G_CALLBACK(cb_page_widget_scaled_button_release), zathura);
868 869
  }

870
  /* view mode */
871
  unsigned int pages_per_row = 1;
872
  char* first_page_column_list = NULL;
873 874 875 876
  unsigned int page_padding = 1;

  girara_setting_get(zathura->ui.session, "page-padding", &page_padding);

877 878 879 880 881
  if (file_info.pages_per_row > 0) {
    pages_per_row = file_info.pages_per_row;
  } else {
    girara_setting_get(zathura->ui.session, "pages-per-row", &pages_per_row);
  }
Moritz Lipp's avatar
Moritz Lipp committed
882

883
  /* read first_page_column list */
884
  if (file_info.first_page_column_list != NULL && strcmp(file_info.first_page_column_list, "")) {
885
    first_page_column_list = file_info.first_page_column_list;
886
    file_info.first_page_column_list = NULL;
887
  } else {
888
    girara_setting_get(zathura->ui.session, "first-page-column", &first_page_column_list);
889 890
  }

891 892 893
  /* find value for first_page_column */
  unsigned int first_page_column = find_first_page_column(first_page_column_list, pages_per_row);

Moritz Lipp's avatar
Moritz Lipp committed
894
  girara_setting_set(zathura->ui.session, "pages-per-row", &pages_per_row);
895
  girara_setting_set(zathura->ui.session, "first-page-column", first_page_column_list);
896
  g_free(file_info.first_page_column_list);
897
  g_free(first_page_column_list);
898 899 900

  page_widget_set_mode(zathura, page_padding, pages_per_row, first_page_column);
  zathura_document_set_page_layout(zathura->document, page_padding, pages_per_row, first_page_column);
Moritz Lipp's avatar
Moritz Lipp committed
901

902
  girara_set_view(zathura->ui.session, zathura->ui.page_widget);
Moritz Lipp's avatar
Moritz Lipp committed
903

Moritz Lipp's avatar
Moritz Lipp committed
904

905
  /* bookmarks */
906 907
  if (zathura->database != NULL) {
    if (zathura_bookmarks_load(zathura, file_path) == false) {
908
      girara_debug("Failed to load bookmarks.");
909
    }
910

911 912 913 914
    /* jumplist */
    if (zathura_jumplist_load(zathura, file_path) == false) {
      zathura->jumplist.list = girara_list_new2(g_free);
    }
915 916
  }

Moritz Lipp's avatar
Moritz Lipp committed
917
  /* update title */
918 919 920
  char* formatted_filename = get_formatted_filename(zathura, file_path, false);
  girara_set_window_title(zathura->ui.session, formatted_filename);
  g_free(formatted_filename);
Moritz Lipp's avatar
Moritz Lipp committed
921

922
  g_free(file_uri);
Moritz Lipp's avatar
Moritz Lipp committed
923

924
  /* adjust_view */
925
  adjust_view(zathura);
926 927 928 929 930 931 932 933 934
  for (unsigned int page_id = 0; page_id < number_of_pages; page_id++) {
    /* set widget size */
    zathura_page_t* page = zathura_document_get_page(document, page_id);
    unsigned int page_height = 0;
    unsigned int page_width  = 0;

    /* adjust_view calls render_all in some cases and render_all calls
     * gtk_widget_set_size_request. To be sure that it's really called, do it
     * here once again. */
Sebastian Ramacher's avatar
Sebastian Ramacher committed
935 936
    const double height = zathura_page_get_height(page);
    const double width = zathura_page_get_width(page);
937 938 939 940 941 942
    page_calc_height_width(zathura->document, height, width, &page_height, &page_width, true);
    gtk_widget_set_size_request(zathura->pages[page_id], page_width, page_height);

    /* show widget */
    gtk_widget_show(zathura->pages[page_id]);
  }
943

944
  /* Set page */
945
  page_set(zathura, zathura_document_get_current_page_number(document));
946 947

  /* Set position (only if restoring from history file) */
Sebastian Ramacher's avatar
CS  
Sebastian Ramacher committed
948 949 950
  if (file_info.current_page == zathura_document_get_current_page_number(document) &&
      (file_info.position_x != 0 || file_info.position_y != 0)) {
    position_set(zathura, file_info.position_x, file_info.position_y);
951 952
  }

953 954
  update_visible_pages(zathura);

Moritz Lipp's avatar
Moritz Lipp committed
955
  return true;
956 957 958

error_free:

Moritz Lipp's avatar
Moritz Lipp committed
959 960 961 962
  if (file_uri != NULL) {
    g_free(file_uri);
  }

963 964 965 966 967
  zathura_document_free(document);

error_out:

  return false;
Moritz Lipp's avatar
Moritz Lipp committed
968 969
}

970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994
bool
document_open_synctex(zathura_t* zathura, const char* path,
                      const char* password, const char* synctex)
{
  bool ret = document_open(zathura, path, password,
                           ZATHURA_PAGE_NUMBER_UNSPECIFIED);
  if (ret == false) {
    return false;
  }
  if (synctex == NULL) {
    return true;
  }

  int line = 0;
  int column = 0;
  char* input_file = NULL;
  if (synctex_parse_input(synctex, &input_file, &line, &column) == false) {
    return false;
  }

  ret = synctex_view(zathura, input_file, line, column);
  g_free(input_file);
  return ret;
}

995
void
996
document_open_idle(zathura_t* zathura, const char* path, const char* password,
997
                   int page_number, const char* mode, const char* synctex)
998 999 1000 1001 1002
{
  if (zathura == NULL || path == NULL) {
    return;
  }

1003 1004 1005 1006
  zathura_document_info_t* document_info = g_try_malloc0(sizeof(zathura_document_info_t));
  if (document_info == NULL) {
    return;
  }
1007

1008 1009 1010 1011
  document_info->zathura     = zathura;
  document_info->path        = path;
  document_info->password    = password;
  document_info->page_number = page_number;
Sebastian Ramacher's avatar
Sebastian Ramacher committed
1012
  document_info->mode        = mode;
1013
  document_info->synctex     = synctex;
1014 1015 1016 1017

  gdk_threads_add_idle(document_info_open, document_info);
}

1018 1019 1020 1021 1022 1023 1024 1025
bool
document_save(zathura_t* zathura, const char* path, bool overwrite)
{
  g_return_val_if_fail(zathura, false);
  g_return_val_if_fail(zathura->document, false);
  g_return_val_if_fail(path, false);

  gchar* file_path = girara_fix_path(path);
1026 1027 1028 1029 1030 1031 1032 1033 1034
  /* use current basename if path points to a directory  */
  if (g_file_test(file_path, G_FILE_TEST_IS_DIR) == TRUE) {
    char* basename = g_path_get_basename(zathura_document_get_path(zathura->document));
    char* tmp = file_path;
    file_path = g_strconcat(file_path, "/", basename, NULL);
    g_free(tmp);
    g_free(basename);
  }

Moritz Lipp's avatar
Moritz Lipp committed
1035
  if ((overwrite == false) && g_file_test(file_path, G_FILE_TEST_EXISTS)) {
1036
    girara_error("File already exists: %s. Use :write! to overwrite it.", file_path);
1037
    g_free(file_path);
1038 1039 1040
    return false;
  }

1041
  zathura_error_t error = zathura_document_save_as(zathura->document, file_path);
1042
  g_free(file_path);
1043

1044
  return (error == ZATHURA_ERROR_OK) ? true : false;
1045 1046
}

Pavel Borzenkov's avatar
Pavel Borzenkov committed
1047
static void
1048
remove_page_from_table(GtkWidget* page, gpointer UNUSED(permanent))
Pavel Borzenkov's avatar
Pavel Borzenkov committed
1049
{
1050
  gtk_container_remove(GTK_CONTAINER(gtk_widget_get_parent(page)), page);
Pavel Borzenkov's avatar
Pavel Borzenkov committed
1051 1052
}

Moritz Lipp's avatar
Moritz Lipp committed
1053
bool
Moritz Lipp's avatar
Moritz Lipp committed
1054
document_close(zathura_t* zathura, bool keep_monitor)
Moritz Lipp's avatar
Moritz Lipp committed
1055
{
Moritz Lipp's avatar
Moritz Lipp committed
1056
  if (zathura == NULL || zathura->document == NULL) {
Moritz Lipp's avatar
Moritz Lipp committed
1057 1058 1059
    return false;
  }

1060 1061 1062
  /* stop rendering */
  zathura_renderer_stop(zathura->sync.render_thread);

Moritz Lipp's avatar
Moritz Lipp committed
1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086
  /* remove monitor */
  if (keep_monitor == false) {
    if (zathura->file_monitor.monitor != NULL) {
      g_file_monitor_cancel(zathura->file_monitor.monitor);
      g_object_unref(zathura->file_monitor.monitor);
      zathura->file_monitor.monitor = NULL;
    }

    if (zathura->file_monitor.file != NULL) {
      g_object_unref(zathura->file_monitor.file);
      zathura->file_monitor.file = NULL;
    }

    if (zathura->file_monitor.file_path != NULL) {
      g_free(zathura->file_monitor.file_path);
      zathura->file_monitor.file_path = NULL;
    }

    if (zathura->file_monitor.password != NULL) {
      g_free(zathura->file_monitor.password);
      zathura->file_monitor.password = NULL;
    }
  }

Moritz Lipp's avatar
Moritz Lipp committed
1087 1088 1089 1090 1091 1092
  /* remove marks */
  if (zathura->global.marks != NULL) {
    girara_list_free(zathura->global.marks);
    zathura->global.marks = NULL;
  }

1093 1094
  /* store file information */
  const char* path = zathura_document_get_path(zathura->document);
1095

1096
  zathura_fileinfo_t file_info = { 0, 0, 1, 0, 1, "1:2", 0, 0 };
1097 1098 1099 1100 1101
  file_info.current_page = zathura_document_get_current_page_number(zathura->document);
  file_info.page_offset  = zathura_document_get_page_offset(zathura->document);
  file_info.scale        = zathura_document_get_scale(zathura->document);
  file_info.rotation     = zathura_document_get_rotation(zathura->document);

1102
  girara_setting_get(zathura->ui.session, "pages-per-row", &(file_info.pages_per_row));
1103
  girara_setting_get(zathura->ui.session, "first-page-column", &(file_info.first_page_column_list));
1104 1105

  /* get position */
1106 1107
  file_info.position_x = zathura_document_get_position_x(zathura->document);
  file_info.position_y = zathura_document_get_position_y(zathura->document);
1108

1109 1110 1111 1112 1113 1114 1115
  if (zathura->database != NULL) {
    /* save file info */
    zathura_db_set_fileinfo(zathura->database, path, &file_info);

    /* save jumplist */
    zathura_db_save_jumplist(zathura->database, path, zathura->jumplist.list);
  }
Sebastian Ramacher's avatar
Sebastian Ramacher committed
1116

1117 1118 1119
  /* free buffers */
  g_free(file_info