commands.c 17.7 KB
Newer Older
1
/* SPDX-License-Identifier: Zlib */
Moritz Lipp's avatar
Moritz Lipp committed
2

Moritz Lipp's avatar
Moritz Lipp committed
3
#include <string.h>
4
#include <stdlib.h>
5
#include <glib/gi18n.h>
Moritz Lipp's avatar
Moritz Lipp committed
6

Moritz Lipp's avatar
Moritz Lipp committed
7
#include "commands.h"
Moritz Lipp's avatar
Moritz Lipp committed
8
#include "shortcuts.h"
9 10
#include "bookmarks.h"
#include "database.h"
Moritz Lipp's avatar
Moritz Lipp committed
11
#include "document.h"
Moritz Lipp's avatar
Moritz Lipp committed
12
#include "zathura.h"
13
#include "print.h"
14
#include "document.h"
Moritz Lipp's avatar
Moritz Lipp committed
15
#include "utils.h"
16
#include "page-widget.h"
Moritz Lipp's avatar
Moritz Lipp committed
17
#include "page.h"
Moritz Lipp's avatar
Moritz Lipp committed
18
#include "plugin.h"
19
#include "internal.h"
20
#include "render.h"
21
#include "adjustment.h"
Moritz Lipp's avatar
Moritz Lipp committed
22

23
#include <girara/session.h>
24
#include <girara/settings.h>
Moritz Lipp's avatar
Moritz Lipp committed
25
#include <girara/commands.h>
26
#include <girara/datastructures.h>
Sebastian Ramacher's avatar
Sebastian Ramacher committed
27
#include <girara/utils.h>
28

Moritz Lipp's avatar
Moritz Lipp committed
29
bool
30
cmd_bookmark_create(girara_session_t* session, girara_list_t* argument_list)
Moritz Lipp's avatar
Moritz Lipp committed
31
{
32 33 34 35
  g_return_val_if_fail(session != NULL, false);
  g_return_val_if_fail(session->global.data != NULL, false);
  zathura_t* zathura = session->global.data;
  if (zathura->document == NULL) {
36
    girara_notify(session, GIRARA_ERROR, _("No document opened."));
37 38 39 40 41
    return false;
  }

  const unsigned int argc = girara_list_size(argument_list);
  if (argc != 1) {
42
    girara_notify(session, GIRARA_ERROR, _("Invalid number of arguments given."));
43 44 45 46 47
    return false;
  }

  const char* bookmark_name = girara_list_nth(argument_list, 0);
  zathura_bookmark_t* bookmark = zathura_bookmark_get(zathura, bookmark_name);
48
  bool update = bookmark != NULL ? true : false;
49

50
  bookmark = zathura_bookmark_add(zathura, bookmark_name, zathura_document_get_current_page_number(zathura->document) + 1);
51
  if (bookmark == NULL) {
52 53 54 55 56
    if (update == true) {
      girara_notify(session, GIRARA_ERROR, _("Could not update bookmark: %s"), bookmark_name);
    } else {
      girara_notify(session, GIRARA_ERROR, _("Could not create bookmark: %s"), bookmark_name);
    }
57
    return false;
58 59 60 61 62 63
  } else {
    if (update == true) {
      girara_notify(session, GIRARA_INFO, _("Bookmark successfully updated: %s"), bookmark_name);
    } else {
      girara_notify(session, GIRARA_INFO, _("Bookmark successfully created: %s"), bookmark_name);
    }
64 65
  }

Moritz Lipp's avatar
Moritz Lipp committed
66 67 68 69
  return true;
}

bool
Moritz Lipp's avatar
Moritz Lipp committed
70
cmd_bookmark_delete(girara_session_t* session, girara_list_t* argument_list)
Moritz Lipp's avatar
Moritz Lipp committed
71
{
72 73 74 75
  g_return_val_if_fail(session != NULL, false);
  g_return_val_if_fail(session->global.data != NULL, false);
  zathura_t* zathura = session->global.data;
  if (zathura->document == NULL) {
76
    girara_notify(session, GIRARA_ERROR, _("No document opened."));
77 78 79 80 81
    return false;
  }

  const unsigned int argc = girara_list_size(argument_list);
  if (argc != 1) {
82
    girara_notify(session, GIRARA_ERROR, _("Invalid number of arguments given."));
83 84 85 86 87
    return false;
  }

  const char* bookmark = girara_list_nth(argument_list, 0);
  if (zathura_bookmark_remove(zathura, bookmark)) {
88
    girara_notify(session, GIRARA_INFO, _("Removed bookmark: %s"), bookmark);
89
  } else {
90
    girara_notify(session, GIRARA_ERROR, _("Failed to remove bookmark: %s"), bookmark);
91 92
  }

Moritz Lipp's avatar
Moritz Lipp committed
93 94 95 96
  return true;
}

bool
97
cmd_bookmark_open(girara_session_t* session, girara_list_t* argument_list)
Moritz Lipp's avatar
Moritz Lipp committed
98
{
99 100 101 102
  g_return_val_if_fail(session != NULL, false);
  g_return_val_if_fail(session->global.data != NULL, false);
  zathura_t* zathura = session->global.data;
  if (zathura->document == NULL) {
103
    girara_notify(session, GIRARA_ERROR, _("No document opened."));
104 105 106 107 108
    return false;
  }

  const unsigned int argc = girara_list_size(argument_list);
  if (argc != 1) {
109 110
    GString* string = g_string_new(NULL);

111
    GIRARA_LIST_FOREACH_BODY(zathura->bookmarks.bookmarks, zathura_bookmark_t*, bookmark,
112
      g_string_append_printf(string, "<b>%s</b>: %u\n", bookmark->id, bookmark->page);
113
    );
114 115 116 117 118 119 120 121 122

    if (strlen(string->str) > 0) {
      g_string_erase(string, strlen(string->str) - 1, 1);
      girara_notify(session, GIRARA_INFO, "%s", string->str);
    } else {
      girara_notify(session, GIRARA_INFO, _("No bookmarks available."));
    }

    g_string_free(string, TRUE);
123 124 125 126 127 128
    return false;
  }

  const char* bookmark_name = girara_list_nth(argument_list, 0);
  zathura_bookmark_t* bookmark = zathura_bookmark_get(zathura, bookmark_name);
  if (bookmark == NULL) {
129
    girara_notify(session, GIRARA_ERROR, _("No such bookmark: %s"), bookmark_name);
130 131 132
    return false;
  }

133
  zathura_jumplist_add(zathura);
134
  page_set(zathura, bookmark->page - 1);
Sebastian Ramacher's avatar
Sebastian Ramacher committed
135
  if (bookmark->x != DBL_MIN && bookmark->y != DBL_MIN) {
136
    position_set(zathura, bookmark->x, bookmark->y);
Sebastian Ramacher's avatar
Sebastian Ramacher committed
137
  }
138 139 140
  zathura_jumplist_add(zathura);

  return true;
Moritz Lipp's avatar
Moritz Lipp committed
141 142 143
}

bool
144
cmd_close(girara_session_t* session, girara_list_t* UNUSED(argument_list))
Moritz Lipp's avatar
Moritz Lipp committed
145
{
146 147 148
  g_return_val_if_fail(session != NULL, false);
  g_return_val_if_fail(session->global.data != NULL, false);
  zathura_t* zathura = session->global.data;
149 150 151
  if (zathura->document == NULL) {
    return true;
  }
152

153
  document_close(zathura, false);
Moritz Lipp's avatar
Moritz Lipp committed
154

Moritz Lipp's avatar
Moritz Lipp committed
155 156 157 158
  return true;
}

bool
Moritz Lipp's avatar
Moritz Lipp committed
159
cmd_info(girara_session_t* session, girara_list_t* UNUSED(argument_list))
Moritz Lipp's avatar
Moritz Lipp committed
160
{
Moritz Lipp's avatar
Moritz Lipp committed
161 162 163 164
  g_return_val_if_fail(session != NULL, false);
  g_return_val_if_fail(session->global.data != NULL, false);
  zathura_t* zathura = session->global.data;
  if (zathura->document == NULL) {
165
    girara_notify(session, GIRARA_ERROR, _("No document opened."));
Moritz Lipp's avatar
Moritz Lipp committed
166 167 168 169 170
    return false;
  }

  struct meta_field {
    char* name;
171
    zathura_document_information_type_t field;
Moritz Lipp's avatar
Moritz Lipp committed
172 173
  };

174 175 176 177 178 179 180 181
  const struct meta_field meta_fields[] = {
    { _("Title"),             ZATHURA_DOCUMENT_INFORMATION_TITLE },
    { _("Author"),            ZATHURA_DOCUMENT_INFORMATION_AUTHOR },
    { _("Subject"),           ZATHURA_DOCUMENT_INFORMATION_SUBJECT },
    { _("Keywords"),          ZATHURA_DOCUMENT_INFORMATION_KEYWORDS },
    { _("Creator"),           ZATHURA_DOCUMENT_INFORMATION_CREATOR },
    { _("Producer"),          ZATHURA_DOCUMENT_INFORMATION_PRODUCER },
    { _("Creation date"),     ZATHURA_DOCUMENT_INFORMATION_CREATION_DATE },
Sebastian Ramacher's avatar
Sebastian Ramacher committed
182 183
    { _("Modification date"), ZATHURA_DOCUMENT_INFORMATION_MODIFICATION_DATE },
    { _("Format"),            ZATHURA_DOCUMENT_INFORMATION_FORMAT }
Moritz Lipp's avatar
Moritz Lipp committed
184 185
  };

186 187 188 189
  girara_list_t* information = zathura_document_get_information(zathura->document, NULL);
  if (information == NULL) {
    girara_notify(session, GIRARA_INFO, _("No information available."));
    return false;
Moritz Lipp's avatar
Moritz Lipp committed
190 191
  }

192
  GString* string = g_string_new(NULL);
Moritz Lipp's avatar
Moritz Lipp committed
193

194 195 196 197 198 199
  GIRARA_LIST_FOREACH_BODY(information, zathura_document_information_entry_t*, entry,
    if (entry != NULL) {
      for (unsigned int i = 0; i < LENGTH(meta_fields); i++) {
        if (meta_fields[i].field == entry->type) {
          g_string_append_printf(string, "<b>%s:</b> %s\n", meta_fields[i].name, entry->value);
        }
200
      }
Moritz Lipp's avatar
Moritz Lipp committed
201
    }
202
  );
Moritz Lipp's avatar
Moritz Lipp committed
203 204 205

  if (strlen(string->str) > 0) {
    g_string_erase(string, strlen(string->str) - 1, 1);
206
    girara_notify(session, GIRARA_INFO, "%s", string->str);
207 208
  } else {
    girara_notify(session, GIRARA_INFO, _("No information available."));
Moritz Lipp's avatar
Moritz Lipp committed
209 210 211 212 213
  }

  g_string_free(string, TRUE);

  return false;
Moritz Lipp's avatar
Moritz Lipp committed
214 215
}

216
bool
217
cmd_help(girara_session_t* UNUSED(session), girara_list_t*
Moritz Lipp's avatar
Moritz Lipp committed
218
         UNUSED(argument_list))
219 220 221 222
{
  return true;
}

223 224 225 226 227 228 229 230 231 232 233 234 235 236
bool
cmd_hlsearch(girara_session_t* session, girara_list_t* UNUSED(argument_list))
{
  g_return_val_if_fail(session != NULL, false);
  g_return_val_if_fail(session->global.data != NULL, false);
  zathura_t* zathura = session->global.data;

  document_draw_search_results(zathura, true);
  render_all(zathura);

  return true;
}


237 238 239
bool
cmd_open(girara_session_t* session, girara_list_t* argument_list)
{
Sebastian Ramacher's avatar
Sebastian Ramacher committed
240 241 242 243 244 245
  g_return_val_if_fail(session != NULL, false);
  g_return_val_if_fail(session->global.data != NULL, false);
  zathura_t* zathura = session->global.data;

  const int argc = girara_list_size(argument_list);
  if (argc > 2) {
246
    girara_notify(session, GIRARA_ERROR, _("Too many arguments."));
Sebastian Ramacher's avatar
Sebastian Ramacher committed
247
    return false;
Moritz Lipp's avatar
Moritz Lipp committed
248
  } else if (argc >= 1) {
249 250
    if (zathura->document != NULL) {
      document_close(zathura, false);
251 252
    }

253 254 255
    document_open_idle(zathura, girara_list_nth(argument_list, 0),
                       (argc == 2) ? girara_list_nth(argument_list, 1) : NULL,
                       ZATHURA_PAGE_NUMBER_UNSPECIFIED, NULL, NULL);
Moritz Lipp's avatar
Moritz Lipp committed
256
  } else {
257
    girara_notify(session, GIRARA_ERROR, _("No arguments given."));
Sebastian Ramacher's avatar
Sebastian Ramacher committed
258 259 260
    return false;
  }

261 262 263
  return true;
}

Moritz Lipp's avatar
Moritz Lipp committed
264 265 266 267 268 269 270 271
bool
cmd_quit(girara_session_t* session, girara_list_t* UNUSED(argument_list))
{
  sc_quit(session, NULL, NULL, 0);

  return true;
}

Moritz Lipp's avatar
Moritz Lipp committed
272
bool
273
cmd_print(girara_session_t* session, girara_list_t* UNUSED(argument_list))
Moritz Lipp's avatar
Moritz Lipp committed
274
{
275 276 277 278
  g_return_val_if_fail(session != NULL, false);
  g_return_val_if_fail(session->global.data != NULL, false);
  zathura_t* zathura = session->global.data;

Pavel Borzenkov's avatar
Pavel Borzenkov committed
279
  if (zathura->document == NULL) {
Sebastian Ramacher's avatar
Sebastian Ramacher committed
280
    girara_notify(session, GIRARA_ERROR, _("No document opened."));
Pavel Borzenkov's avatar
Pavel Borzenkov committed
281 282
    return false;
  }
283

Sebastian Ramacher's avatar
Sebastian Ramacher committed
284
  if (zathura->global.sandbox == ZATHURA_SANDBOX_STRICT) {
valoq's avatar
valoq committed
285 286 287 288
    girara_notify(zathura->ui.session, GIRARA_ERROR, _("Printing is not permitted in strict sandbox mode"));
    return false;
  }

Moritz Lipp's avatar
Moritz Lipp committed
289
  print(zathura);
290

Moritz Lipp's avatar
Moritz Lipp committed
291 292 293
  return true;
}

294 295 296
bool
cmd_nohlsearch(girara_session_t* session, girara_list_t* UNUSED(argument_list))
{
297
  sc_nohlsearch(session, NULL, NULL, 0);
298 299 300 301

  return true;
}

Moritz Lipp's avatar
Moritz Lipp committed
302
bool
Moritz Lipp's avatar
Moritz Lipp committed
303
cmd_save(girara_session_t* session, girara_list_t* argument_list)
Moritz Lipp's avatar
Moritz Lipp committed
304
{
305 306 307 308
  g_return_val_if_fail(session != NULL, false);
  g_return_val_if_fail(session->global.data != NULL, false);
  zathura_t* zathura = session->global.data;

Pavel Borzenkov's avatar
Pavel Borzenkov committed
309
  if (zathura->document == NULL) {
Sebastian Ramacher's avatar
Sebastian Ramacher committed
310
    girara_notify(session, GIRARA_ERROR, _("No document opened."));
Pavel Borzenkov's avatar
Pavel Borzenkov committed
311 312
    return false;
  }
313 314

  if (girara_list_size(argument_list) == 1) {
315
    if (document_save(zathura, girara_list_nth(argument_list, 0), false) == true) {
316
      girara_notify(session, GIRARA_INFO, _("Document saved."));
317
    } else {
318
      girara_notify(session, GIRARA_INFO, _("Failed to save document."));
319
    }
Moritz Lipp's avatar
Moritz Lipp committed
320
  } else {
321
    girara_notify(session, GIRARA_ERROR, _("Invalid number of arguments."));
322 323 324 325 326 327 328 329 330 331 332 333 334
    return false;
  }

  return true;
}

bool
cmd_savef(girara_session_t* session, girara_list_t* argument_list)
{
  g_return_val_if_fail(session != NULL, false);
  g_return_val_if_fail(session->global.data != NULL, false);
  zathura_t* zathura = session->global.data;

Pavel Borzenkov's avatar
Pavel Borzenkov committed
335
  if (zathura->document == NULL) {
Sebastian Ramacher's avatar
Sebastian Ramacher committed
336
    girara_notify(session, GIRARA_ERROR, _("No document opened."));
337
    return false;
Pavel Borzenkov's avatar
Pavel Borzenkov committed
338
  }
339 340

  if (girara_list_size(argument_list) == 1) {
341
    if (document_save(zathura, girara_list_nth(argument_list, 0), true) == true) {
342
      girara_notify(session, GIRARA_INFO, _("Document saved."));
343
    } else {
344
      girara_notify(session, GIRARA_INFO, _("Failed to save document."));
345
    }
Moritz Lipp's avatar
Moritz Lipp committed
346
  } else {
347
    girara_notify(session, GIRARA_ERROR, _("Invalid number of arguments."));
348 349 350
    return false;
  }

Moritz Lipp's avatar
Moritz Lipp committed
351 352
  return true;
}
Moritz Lipp's avatar
Moritz Lipp committed
353 354

bool
Sebastian Ramacher's avatar
Sebastian Ramacher committed
355
cmd_search(girara_session_t* session, const char* input, girara_argument_t* argument)
Moritz Lipp's avatar
Moritz Lipp committed
356 357 358 359 360 361 362
{
  g_return_val_if_fail(session != NULL, false);
  g_return_val_if_fail(input != NULL, false);
  g_return_val_if_fail(argument != NULL, false);
  g_return_val_if_fail(session->global.data != NULL, false);
  zathura_t* zathura = session->global.data;

363
  if (zathura->document == NULL || strlen(input) == 0) {
Moritz Lipp's avatar
Moritz Lipp committed
364 365 366
    return false;
  }

367
  zathura_error_t error = ZATHURA_ERROR_OK;
368

369 370
  /* set search direction */
  zathura->global.search_direction = argument->n;
371 372 373 374

  unsigned int number_of_pages     = zathura_document_get_number_of_pages(zathura->document);
  unsigned int current_page_number = zathura_document_get_current_page_number(zathura->document);

375 376 377 378 379
  /* reset search highlighting */
  bool nohlsearch = false;
  girara_setting_get(session, "nohlsearch", &nohlsearch);

  /* search pages */
380
  for (unsigned int page_id = 0; page_id < number_of_pages; ++page_id) {
381
    unsigned int index = (page_id + current_page_number) % number_of_pages;
382
    zathura_page_t* page = zathura_document_get_page(zathura->document, index);
383
    if (page == NULL) {
384 385 386
      continue;
    }

387
    GtkWidget* page_widget = zathura_page_get_widget(zathura, page);
Sebastian Ramacher's avatar
Sebastian Ramacher committed
388 389
    GObject* obj_page_widget = G_OBJECT(page_widget);
    g_object_set(obj_page_widget, "draw-links", FALSE, NULL);
390

391
    zathura_renderer_lock(zathura->sync.render_thread);
392
    girara_list_t* result = zathura_page_search_text(page, input, &error);
393
    zathura_renderer_unlock(zathura->sync.render_thread);
394

395 396
    if (result == NULL || girara_list_size(result) == 0) {
      girara_list_free(result);
Sebastian Ramacher's avatar
Sebastian Ramacher committed
397
      g_object_set(obj_page_widget, "search-results", NULL, NULL);
398

399
      if (error == ZATHURA_ERROR_NOT_IMPLEMENTED) {
400 401 402 403
        break;
      } else {
        continue;
      }
404 405
    }

Sebastian Ramacher's avatar
Sebastian Ramacher committed
406
    g_object_set(obj_page_widget, "search-results", result, NULL);
407 408 409

    if (argument->n == BACKWARD) {
      /* start at bottom hit in page */
Sebastian Ramacher's avatar
Sebastian Ramacher committed
410
      g_object_set(obj_page_widget, "search-current", girara_list_size(result) - 1, NULL);
411
    } else {
Sebastian Ramacher's avatar
Sebastian Ramacher committed
412
      g_object_set(obj_page_widget, "search-current", 0, NULL);
413
    }
414 415
  }

416 417 418 419
  girara_argument_t* arg = g_try_malloc0(sizeof(girara_argument_t));
  if (arg == NULL) {
    return false;
  }
420 421

  arg->n = FORWARD;
422
  arg->data = (void*) input;
423 424 425
  sc_search(session, arg, NULL, 0);
  g_free(arg);

Moritz Lipp's avatar
Moritz Lipp committed
426 427
  return true;
}
Sebastian Ramacher's avatar
Sebastian Ramacher committed
428 429 430 431 432 433 434 435

bool
cmd_export(girara_session_t* session, girara_list_t* argument_list)
{
  g_return_val_if_fail(session != NULL, false);
  g_return_val_if_fail(session->global.data != NULL, false);
  zathura_t* zathura = session->global.data;
  if (zathura->document == NULL) {
436
    girara_notify(session, GIRARA_ERROR, _("No document opened."));
Sebastian Ramacher's avatar
Sebastian Ramacher committed
437 438 439
    return false;
  }

440
  if (girara_list_size(argument_list) != 2) {
441
    girara_notify(session, GIRARA_ERROR, _("Invalid number of arguments given."));
Sebastian Ramacher's avatar
Sebastian Ramacher committed
442 443 444
    return false;
  }

445
  const char* file_identifier = girara_list_nth(argument_list, 0);
446 447
  const char* file_name       = girara_list_nth(argument_list, 1);

448
  if (file_name == NULL || file_identifier == NULL) {
449 450 451
    return false;
  }

452 453 454 455 456 457 458 459 460 461 462 463
  char* export_path = girara_fix_path(file_name);
  if (export_path == NULL) {
    return false;
  }

  /* attachment */
  if (strncmp(file_identifier, "attachment-", strlen("attachment-")) == 0) {
    if (zathura_document_attachment_save(zathura->document, file_identifier + strlen("attachment-"), export_path) == false) {
      girara_notify(session, GIRARA_ERROR, _("Couldn't write attachment '%s' to '%s'."), file_identifier, file_name);
    } else {
      girara_notify(session, GIRARA_INFO, _("Wrote attachment '%s' to '%s'."), file_identifier, export_path);
    }
Moritz Lipp's avatar
Moritz Lipp committed
464
    /* image */
465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516
  } else if (strncmp(file_identifier, "image-p", strlen("image-p")) == 0 && strlen(file_identifier) >= 10) {
    /* parse page id */
    const char* input = file_identifier + strlen("image-p");
    int page_id = atoi(input);
    if (page_id == 0) {
      goto image_error;
    }

    /* parse image id */
    input = strstr(input, "-");
    if (input == NULL) {
      goto image_error;
    }

    int image_id = atoi(input + 1);
    if (image_id == 0) {
      goto image_error;
    }

    /* get image */
    zathura_page_t* page = zathura_document_get_page(zathura->document, page_id - 1);
    if (page == NULL) {
      goto image_error;
    }

    girara_list_t* images = zathura_page_images_get(page, NULL);
    if (images == NULL) {
      goto image_error;
    }

    zathura_image_t* image = girara_list_nth(images, image_id - 1);
    if (image == NULL) {
      goto image_error;
    }

    cairo_surface_t* surface = zathura_page_image_get_cairo(page, image, NULL);
    if (surface == NULL) {
      goto image_error;
    }

    if (cairo_surface_write_to_png(surface, export_path) == CAIRO_STATUS_SUCCESS) {
      girara_notify(session, GIRARA_INFO, _("Wrote image '%s' to '%s'."), file_identifier, export_path);
    } else {
      girara_notify(session, GIRARA_ERROR, _("Couldn't write image '%s' to '%s'."), file_identifier, file_name);
    }

    goto error_ret;

image_error:

    girara_notify(session, GIRARA_ERROR, _("Unknown image '%s'."), file_identifier);
    goto error_ret;
Moritz Lipp's avatar
Moritz Lipp committed
517
    /* unknown */
Sebastian Ramacher's avatar
Sebastian Ramacher committed
518
  } else {
519
    girara_notify(session, GIRARA_ERROR, _("Unknown attachment or image '%s'."), file_identifier);
Sebastian Ramacher's avatar
Sebastian Ramacher committed
520 521
  }

522 523 524
error_ret:

  g_free(export_path);
525

Sebastian Ramacher's avatar
Sebastian Ramacher committed
526 527
  return true;
}
528

Moritz Lipp's avatar
Moritz Lipp committed
529 530 531 532 533 534 535
bool
cmd_exec(girara_session_t* session, girara_list_t* argument_list)
{
  g_return_val_if_fail(session != NULL, false);
  g_return_val_if_fail(session->global.data != NULL, false);
  zathura_t* zathura = session->global.data;

valoq's avatar
valoq committed
536
  if (zathura->global.sandbox == ZATHURA_SANDBOX_STRICT) {
valoq's avatar
valoq committed
537 538 539 540
    girara_notify(zathura->ui.session, GIRARA_ERROR, _("Exec is not permitted in strict sandbox mode"));
    return false;
  }

Moritz Lipp's avatar
Moritz Lipp committed
541 542 543
  if (zathura->document != NULL) {
    const char* path = zathura_document_get_path(zathura->document);

544
    GIRARA_LIST_FOREACH_BODY_WITH_ITER(argument_list, char*, iter, value,
Sebastian Ramacher's avatar
Sebastian Ramacher committed
545 546 547 548 549 550 551 552 553 554
      char* r = girara_replace_substring(value, "$FILE", path);

      if (r != NULL) {
        char* s = girara_replace_substring(r, "%", path);
        g_free(r);

        if (s != NULL) {
          girara_list_iterator_set(iter, s);
        }
      }
555
    );
Moritz Lipp's avatar
Moritz Lipp committed
556 557 558 559 560
  }

  return girara_exec_with_argument_list(session, argument_list);
}

561 562 563 564 565 566 567 568 569 570 571 572
bool
cmd_offset(girara_session_t* session, girara_list_t* argument_list)
{
  g_return_val_if_fail(session != NULL, false);
  g_return_val_if_fail(session->global.data != NULL, false);
  zathura_t* zathura = session->global.data;
  if (zathura->document == NULL) {
    girara_notify(session, GIRARA_ERROR, _("No document opened."));
    return false;
  }

  /* no argument: take current page as offset */
Moritz Lipp's avatar
Moritz Lipp committed
573
  int page_offset = zathura_document_get_current_page_number(zathura->document);
574 575 576 577 578 579 580 581 582 583 584 585 586

  /* retrieve offset from argument */
  if (girara_list_size(argument_list) == 1) {
    const char* value = girara_list_nth(argument_list, 0);
    if (value != NULL) {
      page_offset = atoi(value);
      if (page_offset == 0 && strcmp(value, "0") != 0) {
        girara_notify(session, GIRARA_WARNING, _("Argument must be a number."));
        return false;
      }
    }
  }

Moritz Lipp's avatar
Moritz Lipp committed
587
  zathura_document_set_page_offset(zathura->document, page_offset);
588 589 590

  return true;
}
Moritz Lipp's avatar
Moritz Lipp committed
591 592 593 594 595 596 597 598

bool
cmd_version(girara_session_t* session, girara_list_t* UNUSED(argument_list))
{
  g_return_val_if_fail(session != NULL, false);
  g_return_val_if_fail(session->global.data != NULL, false);
  zathura_t* zathura = session->global.data;

599
  char* string = zathura_get_version_string(zathura, true);
Moritz Lipp's avatar
Moritz Lipp committed
600 601 602
  if (string == NULL) {
    return false;
  }
Moritz Lipp's avatar
Moritz Lipp committed
603 604

  /* display information */
605
  girara_notify(session, GIRARA_INFO, "%s", string);
Moritz Lipp's avatar
Moritz Lipp committed
606

607
  g_free(string);
Moritz Lipp's avatar
Moritz Lipp committed
608 609 610

  return true;
}