1 /* SPDX-License-Identifier: Zlib */
2
3 #include <stdlib.h>
4 #include <string.h>
5 #include <limits.h>
6 #include <glib.h>
7 #include <gio/gio.h>
8 #include <math.h>
9
10 #include <girara/datastructures.h>
11 #include <girara/utils.h>
12
13 #include "adjustment.h"
14 #include "document.h"
15 #include "utils.h"
16 #include "zathura.h"
17 #include "page.h"
18 #include "plugin.h"
19 #include "content-type.h"
20
21 /**
22 * Document
23 */
24 struct zathura_document_s {
25 char* file_path; /**< File path of the document */
26 char* uri; /**< URI of the document */
27 char* basename; /**< Basename of the document */
28 uint8_t hash_sha256[32]; /**< SHA256 hash of the document */
29 const char* password; /**< Password of the document */
30 unsigned int current_page_number; /**< Current page number */
31 unsigned int number_of_pages; /**< Number of pages */
32 double zoom; /**< Zoom value */
33 unsigned int rotate; /**< Rotation */
34 void* data; /**< Custom data */
35 zathura_adjust_mode_t adjust_mode; /**< Adjust mode (best-fit, width) */
36 int page_offset; /**< Page offset */
37 double cell_width; /**< width of a page cell in the document (not transformed by scale and rotation) */
38 double cell_height; /**< height of a page cell in the document (not transformed by scale and rotation) */
39 unsigned int view_width; /**< width of current viewport */
40 unsigned int view_height; /**< height of current viewport */
41 double view_ppi; /**< PPI of the current viewport */
42 zathura_device_factors_t device_factors; /**< x and y device scale factors (for e.g. HiDPI) */
43 unsigned int pages_per_row; /**< number of pages in a row */
44 unsigned int first_page_column; /**< column of the first page */
45 unsigned int page_padding; /**< padding between pages */
46 double position_x; /**< X adjustment */
47 double position_y; /**< Y adjustment */
48
49 /**
50 * Document pages
51 */
52 zathura_page_t** pages;
53
54 /**
55 * Used plugin
56 */
57 zathura_plugin_t* plugin;
58 };
59
60 static void
check_set_error(zathura_error_t * error,zathura_error_t code)61 check_set_error(zathura_error_t* error, zathura_error_t code) {
62 if (error != NULL) {
63 *error = code;
64 }
65 }
66
67 static bool
hash_file_sha256(uint8_t * dst,const char * path)68 hash_file_sha256(uint8_t* dst, const char* path)
69 {
70 FILE* f = fopen(path, "rb");
71 if (f == NULL) {
72 return false;
73 }
74
75 GChecksum* checksum = g_checksum_new(G_CHECKSUM_SHA256);
76 if (checksum == NULL) {
77 fclose(f);
78 return false;
79 }
80
81 uint8_t buf[BUFSIZ];
82 size_t read;
83 while ((read = fread(buf, 1, sizeof(buf), f)) != 0) {
84 g_checksum_update(checksum, buf, read);
85 }
86
87 if (ferror(f) != 0) {
88 g_checksum_free(checksum);
89 fclose(f);
90 return false;
91 }
92
93 fclose(f);
94 gsize dst_size = 32;
95 g_checksum_get_digest(checksum, dst, &dst_size);
96 g_checksum_free(checksum);
97 return true;
98 }
99
100 zathura_document_t*
zathura_document_open(zathura_t * zathura,const char * path,const char * uri,const char * password,zathura_error_t * error)101 zathura_document_open(zathura_t* zathura, const char* path, const char* uri,
102 const char* password, zathura_error_t* error)
103 {
104 if (zathura == NULL || path == NULL) {
105 return NULL;
106 }
107
108 GFile* file = g_file_new_for_path(path);
109 char* real_path = NULL;
110 char* content_type = NULL;
111 zathura_plugin_t* plugin = NULL;
112 zathura_document_t* document = NULL;
113
114 if (file == NULL) {
115 girara_error("Error while handling path '%s'.", path);
116 check_set_error(error, ZATHURA_ERROR_UNKNOWN);
117 goto error_free;
118 }
119
120 real_path = g_file_get_path(file);
121 if (real_path == NULL) {
122 girara_error("Error while handling path '%s'.", path);
123 check_set_error(error, ZATHURA_ERROR_UNKNOWN);
124 goto error_free;
125 }
126
127 content_type = zathura_content_type_guess(zathura->content_type_context, real_path, zathura_plugin_manager_get_content_types(zathura->plugins.manager));
128 if (content_type == NULL) {
129 girara_error("Could not determine file type.");
130 check_set_error(error, ZATHURA_ERROR_UNKNOWN);
131 goto error_free;
132 }
133
134 plugin = zathura_plugin_manager_get_plugin(zathura->plugins.manager, content_type);
135 if (plugin == NULL) {
136 girara_error("Unknown file type: '%s'", content_type);
137 check_set_error(error, ZATHURA_ERROR_UNKNOWN);
138
139 g_free((void*)content_type);
140 content_type = NULL;
141
142 goto error_free;
143 }
144
145 g_free(content_type);
146 content_type = NULL;
147
148 document = g_try_malloc0(sizeof(zathura_document_t));
149 if (document == NULL) {
150 check_set_error(error, ZATHURA_ERROR_OUT_OF_MEMORY);
151 goto error_free;
152 }
153
154 document->file_path = real_path;
155 document->uri = g_strdup(uri);
156 if (document->uri == NULL) {
157 document->basename = g_file_get_basename(file);
158 } else {
159 GFile*gf = g_file_new_for_uri(document->uri);
160 document->basename = g_file_get_basename(gf);
161 g_object_unref(gf);
162 }
163 hash_file_sha256(document->hash_sha256, document->file_path);
164 document->password = password;
165 document->zoom = 1.0;
166 document->plugin = plugin;
167 document->adjust_mode = ZATHURA_ADJUST_NONE;
168 document->cell_width = 0.0;
169 document->cell_height = 0.0;
170 document->view_height = 0;
171 document->view_width = 0;
172 document->view_ppi = 0.0;
173 document->device_factors.x = 1.0;
174 document->device_factors.y = 1.0;
175 document->position_x = 0.0;
176 document->position_y = 0.0;
177
178 real_path = NULL;
179 g_object_unref(file);
180 file = NULL;
181
182 /* open document */
183 const zathura_plugin_functions_t* functions = zathura_plugin_get_functions(plugin);
184 if (functions->document_open == NULL) {
185 girara_error("plugin has no open function\n");
186 goto error_free;
187 }
188
189 zathura_error_t int_error = functions->document_open(document);
190 if (int_error != ZATHURA_ERROR_OK) {
191 check_set_error(error, int_error);
192 girara_error("could not open document\n");
193 goto error_free;
194 }
195
196 /* read all pages */
197 document->pages = calloc(document->number_of_pages, sizeof(zathura_page_t*));
198 if (document->pages == NULL) {
199 check_set_error(error, ZATHURA_ERROR_OUT_OF_MEMORY);
200 goto error_free;
201 }
202
203 for (unsigned int page_id = 0; page_id < document->number_of_pages; page_id++) {
204 zathura_page_t* page = zathura_page_new(document, page_id, NULL);
205 if (page == NULL) {
206 check_set_error(error, ZATHURA_ERROR_OUT_OF_MEMORY);
207 goto error_free;
208 }
209
210 document->pages[page_id] = page;
211
212 /* cell_width and cell_height is the maximum of all the pages width and height */
213 const double width = zathura_page_get_width(page);
214 if (document->cell_width < width)
215 document->cell_width = width;
216
217 const double height = zathura_page_get_height(page);
218 if (document->cell_height < height)
219 document->cell_height = height;
220 }
221
222 return document;
223
224 error_free:
225
226 if (file != NULL) {
227 g_object_unref(file);
228 }
229
230 g_free(real_path);
231
232 if (document != NULL) {
233 zathura_document_free(document);
234 document = NULL; /* prevent double-free */
235 }
236
237 g_free(document);
238
239 return NULL;
240 }
241
242 zathura_error_t
zathura_document_free(zathura_document_t * document)243 zathura_document_free(zathura_document_t* document)
244 {
245 if (document == NULL || document->plugin == NULL) {
246 return ZATHURA_ERROR_INVALID_ARGUMENTS;
247 }
248
249 if (document->pages != NULL) {
250 /* free pages */
251 for (unsigned int page_id = 0; page_id < document->number_of_pages; page_id++) {
252 zathura_page_free(document->pages[page_id]);
253 document->pages[page_id] = NULL;
254 }
255 free(document->pages);
256 }
257
258 /* free document */
259 zathura_error_t error = ZATHURA_ERROR_OK;
260 const zathura_plugin_functions_t* functions = zathura_plugin_get_functions(document->plugin);
261 if (functions->document_free == NULL) {
262 error = ZATHURA_ERROR_NOT_IMPLEMENTED;
263 } else {
264 error = functions->document_free(document, document->data);
265 }
266
267 g_free(document->file_path);
268 g_free(document->uri);
269 g_free(document->basename);
270
271 g_free(document);
272
273 return error;
274 }
275
276 const char*
zathura_document_get_path(zathura_document_t * document)277 zathura_document_get_path(zathura_document_t* document)
278 {
279 if (document == NULL) {
280 return NULL;
281 }
282
283 return document->file_path;
284 }
285
286 const uint8_t*
zathura_document_get_hash(zathura_document_t * document)287 zathura_document_get_hash(zathura_document_t* document)
288 {
289 if (document == NULL) {
290 return NULL;
291 }
292
293 return document->hash_sha256;
294 }
295
296 const char*
zathura_document_get_uri(zathura_document_t * document)297 zathura_document_get_uri(zathura_document_t* document)
298 {
299 if (document == NULL) {
300 return NULL;
301 }
302
303 return document->uri;
304 }
305
306 const char*
zathura_document_get_basename(zathura_document_t * document)307 zathura_document_get_basename(zathura_document_t* document)
308 {
309 if (document == NULL) {
310 return NULL;
311 }
312
313 return document->basename;
314 }
315
316 const char*
zathura_document_get_password(zathura_document_t * document)317 zathura_document_get_password(zathura_document_t* document)
318 {
319 if (document == NULL) {
320 return NULL;
321 }
322
323 return document->password;
324 }
325
326 zathura_page_t*
zathura_document_get_page(zathura_document_t * document,unsigned int index)327 zathura_document_get_page(zathura_document_t* document, unsigned int index)
328 {
329 if (document == NULL || document->pages == NULL || (document->number_of_pages <= index)) {
330 return NULL;
331 }
332
333 return document->pages[index];
334 }
335
336 void*
zathura_document_get_data(zathura_document_t * document)337 zathura_document_get_data(zathura_document_t* document)
338 {
339 if (document == NULL) {
340 return NULL;
341 }
342
343 return document->data;
344 }
345
346 void
zathura_document_set_data(zathura_document_t * document,void * data)347 zathura_document_set_data(zathura_document_t* document, void* data)
348 {
349 if (document == NULL) {
350 return;
351 }
352
353 document->data = data;
354 }
355
356 unsigned int
zathura_document_get_number_of_pages(zathura_document_t * document)357 zathura_document_get_number_of_pages(zathura_document_t* document)
358 {
359 if (document == NULL) {
360 return 0;
361 }
362
363 return document->number_of_pages;
364 }
365
366 void
zathura_document_set_number_of_pages(zathura_document_t * document,unsigned int number_of_pages)367 zathura_document_set_number_of_pages(zathura_document_t* document, unsigned int number_of_pages)
368 {
369 if (document == NULL) {
370 return;
371 }
372
373 document->number_of_pages = number_of_pages;
374 }
375
376 unsigned int
zathura_document_get_current_page_number(zathura_document_t * document)377 zathura_document_get_current_page_number(zathura_document_t* document)
378 {
379 if (document == NULL) {
380 return 0;
381 }
382
383 return document->current_page_number;
384 }
385
386 void
zathura_document_set_current_page_number(zathura_document_t * document,unsigned int current_page)387 zathura_document_set_current_page_number(zathura_document_t* document, unsigned int
388 current_page)
389 {
390 if (document == NULL) {
391 return;
392 }
393
394 document->current_page_number = current_page;
395 }
396
397 double
zathura_document_get_position_x(zathura_document_t * document)398 zathura_document_get_position_x(zathura_document_t* document)
399 {
400 if (document == NULL) {
401 return 0;
402 }
403
404 return document->position_x;
405 }
406
407 double
zathura_document_get_position_y(zathura_document_t * document)408 zathura_document_get_position_y(zathura_document_t* document)
409 {
410 if (document == NULL) {
411 return 0;
412 }
413
414 return document->position_y;
415 }
416
417 void
zathura_document_set_position_x(zathura_document_t * document,double position_x)418 zathura_document_set_position_x(zathura_document_t* document, double position_x)
419 {
420 if (document == NULL) {
421 return;
422 }
423
424 document->position_x = position_x;
425 }
426
427 void
zathura_document_set_position_y(zathura_document_t * document,double position_y)428 zathura_document_set_position_y(zathura_document_t* document, double position_y)
429 {
430 if (document == NULL) {
431 return;
432 }
433
434 document->position_y = position_y;
435 }
436
437 double
zathura_document_get_zoom(zathura_document_t * document)438 zathura_document_get_zoom(zathura_document_t* document)
439 {
440 if (document == NULL) {
441 return 0;
442 }
443
444 return document->zoom;
445 }
446
447 void
zathura_document_set_zoom(zathura_document_t * document,double zoom)448 zathura_document_set_zoom(zathura_document_t* document, double zoom)
449 {
450 if (document == NULL) {
451 return;
452 }
453
454 document->zoom = zoom;
455 }
456
457 double
zathura_document_get_scale(zathura_document_t * document)458 zathura_document_get_scale(zathura_document_t* document)
459 {
460 if (document == NULL) {
461 return 0;
462 }
463
464 double ppi = document->view_ppi;
465 if (ppi < DBL_EPSILON) {
466 /* No PPI information -> use a typical value */
467 ppi = 100;
468 }
469
470 /* scale = pixels per point, and there are 72 points in one inch */
471 return document->zoom * ppi / 72.0;
472 }
473
474 unsigned int
zathura_document_get_rotation(zathura_document_t * document)475 zathura_document_get_rotation(zathura_document_t* document)
476 {
477 if (document == NULL) {
478 return 0;
479 }
480
481 return document->rotate;
482 }
483
484 void
zathura_document_set_rotation(zathura_document_t * document,unsigned int rotation)485 zathura_document_set_rotation(zathura_document_t* document, unsigned int rotation)
486 {
487 if (document == NULL) {
488 return;
489 }
490
491 rotation = rotation % 360;
492 if (rotation == 0 || rotation > 270) {
493 document->rotate = 0;
494 } else if (rotation <= 90) {
495 document->rotate = 90;
496 } else if (rotation <= 180) {
497 document->rotate = 180;
498 } else {
499 document->rotate = 270;
500 }
501 }
502
503 zathura_adjust_mode_t
zathura_document_get_adjust_mode(zathura_document_t * document)504 zathura_document_get_adjust_mode(zathura_document_t* document)
505 {
506 if (document == NULL) {
507 return ZATHURA_ADJUST_NONE;
508 }
509
510 return document->adjust_mode;
511 }
512
513 void
zathura_document_set_adjust_mode(zathura_document_t * document,zathura_adjust_mode_t mode)514 zathura_document_set_adjust_mode(zathura_document_t* document, zathura_adjust_mode_t mode)
515 {
516 if (document == NULL) {
517 return;
518 }
519
520 document->adjust_mode = mode;
521 }
522
523 int
zathura_document_get_page_offset(zathura_document_t * document)524 zathura_document_get_page_offset(zathura_document_t* document)
525 {
526 if (document == NULL) {
527 return 0;
528 }
529
530 return document->page_offset;
531 }
532
533 void
zathura_document_set_page_offset(zathura_document_t * document,unsigned int page_offset)534 zathura_document_set_page_offset(zathura_document_t* document, unsigned int page_offset)
535 {
536 if (document == NULL) {
537 return;
538 }
539
540 document->page_offset = page_offset;
541 }
542
543 void
zathura_document_set_viewport_width(zathura_document_t * document,unsigned int width)544 zathura_document_set_viewport_width(zathura_document_t* document, unsigned int width)
545 {
546 if (document == NULL) {
547 return;
548 }
549 document->view_width = width;
550 }
551
552 void
zathura_document_set_viewport_height(zathura_document_t * document,unsigned int height)553 zathura_document_set_viewport_height(zathura_document_t* document, unsigned int height)
554 {
555 if (document == NULL) {
556 return;
557 }
558 document->view_height = height;
559 }
560
561 void
zathura_document_set_viewport_ppi(zathura_document_t * document,double ppi)562 zathura_document_set_viewport_ppi(zathura_document_t* document, double ppi)
563 {
564 if (document == NULL) {
565 return;
566 }
567 document->view_ppi = ppi;
568 }
569
570 void
zathura_document_get_viewport_size(zathura_document_t * document,unsigned int * height,unsigned int * width)571 zathura_document_get_viewport_size(zathura_document_t* document,
572 unsigned int *height, unsigned int* width)
573 {
574 g_return_if_fail(document != NULL && height != NULL && width != NULL);
575 *height = document->view_height;
576 *width = document->view_width;
577 }
578
579 double
zathura_document_get_viewport_ppi(zathura_document_t * document)580 zathura_document_get_viewport_ppi(zathura_document_t* document)
581 {
582 if (document == NULL) {
583 return 0.0;
584 }
585 return document->view_ppi;
586 }
587
588 void
zathura_document_set_device_factors(zathura_document_t * document,double x_factor,double y_factor)589 zathura_document_set_device_factors(zathura_document_t* document,
590 double x_factor, double y_factor)
591 {
592 if (document == NULL) {
593 return;
594 }
595 if (fabs(x_factor) < DBL_EPSILON || fabs(y_factor) < DBL_EPSILON) {
596 girara_debug("Ignoring new device factors %0.2f and %0.2f: too small",
597 x_factor, y_factor);
598 return;
599 }
600
601 document->device_factors.x = x_factor;
602 document->device_factors.y = y_factor;
603 }
604
605 zathura_device_factors_t
zathura_document_get_device_factors(zathura_document_t * document)606 zathura_document_get_device_factors(zathura_document_t* document)
607 {
608 if (document == NULL) {
609 /* The function is guaranteed to not return zero values */
610 return (zathura_device_factors_t){1.0, 1.0};
611 }
612
613 return document->device_factors;
614 }
615
616 void
zathura_document_get_cell_size(zathura_document_t * document,unsigned int * height,unsigned int * width)617 zathura_document_get_cell_size(zathura_document_t* document,
618 unsigned int* height, unsigned int* width)
619 {
620 g_return_if_fail(document != NULL && height != NULL && width != NULL);
621
622 page_calc_height_width(document, document->cell_height, document->cell_width,
623 height, width, true);
624 }
625
626 void
zathura_document_get_document_size(zathura_document_t * document,unsigned int * height,unsigned int * width)627 zathura_document_get_document_size(zathura_document_t* document,
628 unsigned int* height, unsigned int* width)
629 {
630 g_return_if_fail(document != NULL && height != NULL && width != NULL);
631
632 const unsigned int npag = zathura_document_get_number_of_pages(document);
633 const unsigned int ncol = zathura_document_get_pages_per_row(document);
634
635 if (npag == 0 || ncol == 0) {
636 return;
637 }
638
639 const unsigned int c0 = zathura_document_get_first_page_column(document);
640 const unsigned int nrow = (npag + c0 - 1 + ncol - 1) / ncol; /* number of rows */
641 const unsigned int pad = zathura_document_get_page_padding(document);
642
643 unsigned int cell_height = 0;
644 unsigned int cell_width = 0;
645 zathura_document_get_cell_size(document, &cell_height, &cell_width);
646
647 *width = ncol * cell_width + (ncol - 1) * pad;
648 *height = nrow * cell_height + (nrow - 1) * pad;
649 }
650
651 void
zathura_document_set_page_layout(zathura_document_t * document,unsigned int page_padding,unsigned int pages_per_row,unsigned int first_page_column)652 zathura_document_set_page_layout(zathura_document_t* document, unsigned int page_padding,
653 unsigned int pages_per_row, unsigned int first_page_column)
654 {
655 g_return_if_fail(document != NULL);
656
657 document->page_padding = page_padding;
658 document->pages_per_row = pages_per_row;
659
660 if (first_page_column < 1) {
661 first_page_column = 1;
662 } else if (first_page_column > pages_per_row) {
663 first_page_column = ((first_page_column - 1) % pages_per_row) + 1;
664 }
665
666 document->first_page_column = first_page_column;
667 }
668
669 unsigned int
zathura_document_get_page_padding(zathura_document_t * document)670 zathura_document_get_page_padding(zathura_document_t* document)
671 {
672 if (document == NULL) {
673 return 0;
674 }
675 return document->page_padding;
676 }
677
678 unsigned int
zathura_document_get_pages_per_row(zathura_document_t * document)679 zathura_document_get_pages_per_row(zathura_document_t* document)
680 {
681 if (document == NULL) {
682 return 0;
683 }
684 return document->pages_per_row;
685 }
686
687 unsigned int
zathura_document_get_first_page_column(zathura_document_t * document)688 zathura_document_get_first_page_column(zathura_document_t* document)
689 {
690 if (document == NULL) {
691 return 0;
692 }
693 return document->first_page_column;
694 }
695
696 zathura_error_t
zathura_document_save_as(zathura_document_t * document,const char * path)697 zathura_document_save_as(zathura_document_t* document, const char* path)
698 {
699 if (document == NULL || document->plugin == NULL || path == NULL) {
700 return ZATHURA_ERROR_UNKNOWN;
701 }
702
703 const zathura_plugin_functions_t* functions = zathura_plugin_get_functions(document->plugin);
704 if (functions->document_save_as == NULL) {
705 return ZATHURA_ERROR_NOT_IMPLEMENTED;
706 }
707
708 return functions->document_save_as(document, document->data, path);
709 }
710
711 girara_tree_node_t*
zathura_document_index_generate(zathura_document_t * document,zathura_error_t * error)712 zathura_document_index_generate(zathura_document_t* document, zathura_error_t* error)
713 {
714 if (document == NULL || document->plugin == NULL) {
715 check_set_error(error, ZATHURA_ERROR_INVALID_ARGUMENTS);
716 return NULL;
717 }
718
719 const zathura_plugin_functions_t* functions = zathura_plugin_get_functions(document->plugin);
720 if (functions->document_index_generate == NULL) {
721 check_set_error(error, ZATHURA_ERROR_NOT_IMPLEMENTED);
722 return NULL;
723 }
724
725 return functions->document_index_generate(document, document->data, error);
726 }
727
728 girara_list_t*
zathura_document_attachments_get(zathura_document_t * document,zathura_error_t * error)729 zathura_document_attachments_get(zathura_document_t* document, zathura_error_t* error)
730 {
731 if (document == NULL || document->plugin == NULL) {
732 check_set_error(error, ZATHURA_ERROR_INVALID_ARGUMENTS);
733 return NULL;
734 }
735
736 const zathura_plugin_functions_t* functions = zathura_plugin_get_functions(document->plugin);
737 if (functions->document_attachments_get == NULL) {
738 check_set_error(error, ZATHURA_ERROR_NOT_IMPLEMENTED);
739 return NULL;
740 }
741
742 return functions->document_attachments_get(document, document->data, error);
743 }
744
745 zathura_error_t
zathura_document_attachment_save(zathura_document_t * document,const char * attachment,const char * file)746 zathura_document_attachment_save(zathura_document_t* document, const char* attachment, const char* file)
747 {
748 if (document == NULL || document->plugin == NULL) {
749 return ZATHURA_ERROR_INVALID_ARGUMENTS;
750 }
751
752 const zathura_plugin_functions_t* functions = zathura_plugin_get_functions(document->plugin);
753 if (functions->document_attachment_save == NULL) {
754 return ZATHURA_ERROR_NOT_IMPLEMENTED;
755 }
756
757 return functions->document_attachment_save(document, document->data, attachment, file);
758 }
759
760 girara_list_t*
zathura_document_get_information(zathura_document_t * document,zathura_error_t * error)761 zathura_document_get_information(zathura_document_t* document, zathura_error_t* error)
762 {
763 if (document == NULL || document->plugin == NULL) {
764 check_set_error(error, ZATHURA_ERROR_INVALID_ARGUMENTS);
765 return NULL;
766 }
767
768 const zathura_plugin_functions_t* functions = zathura_plugin_get_functions(document->plugin);
769 if (functions->document_get_information == NULL) {
770 check_set_error(error, ZATHURA_ERROR_NOT_IMPLEMENTED);
771 return NULL;
772 }
773
774 girara_list_t* result = functions->document_get_information(document, document->data, error);
775 if (result != NULL) {
776 girara_list_set_free_function(result, (girara_free_function_t) zathura_document_information_entry_free);
777 }
778
779 return result;
780 }
781
782 zathura_plugin_t*
zathura_document_get_plugin(zathura_document_t * document)783 zathura_document_get_plugin(zathura_document_t* document)
784 {
785 if (document == NULL) {
786 return NULL;
787 }
788
789 return document->plugin;
790 }
791