document.c 14.8 KB
Newer Older
Moritz Lipp's avatar
Moritz Lipp committed
1
2
/* See LICENSE file for license and copyright information */

Moritz Lipp's avatar
Moritz Lipp committed
3
#define _BSD_SOURCE
4
#define _XOPEN_SOURCE 700
Moritz Lipp's avatar
Moritz Lipp committed
5
6
// TODO: Implement realpath

Moritz Lipp's avatar
Moritz Lipp committed
7
#include <stdlib.h>
Moritz Lipp's avatar
Moritz Lipp committed
8
#include <stdio.h>
Pavel Borzenkov's avatar
Pavel Borzenkov committed
9
#include <unistd.h>
Moritz Lipp's avatar
Moritz Lipp committed
10
#include <string.h>
Moritz Lipp's avatar
Moritz Lipp committed
11
#include <limits.h>
Moritz Lipp's avatar
Moritz Lipp committed
12
#include <sys/types.h>
13
#include <sys/stat.h>
Moritz Lipp's avatar
Moritz Lipp committed
14
15
#include <dirent.h>
#include <dlfcn.h>
16
17
18
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
19
#include <glib.h>
Moritz Lipp's avatar
Moritz Lipp committed
20
21

#include "document.h"
22
23
#include "utils.h"
#include "zathura.h"
Moritz Lipp's avatar
Update    
Moritz Lipp committed
24
#include "render.h"
Pavel Borzenkov's avatar
Pavel Borzenkov committed
25
#include "database.h"
Moritz Lipp's avatar
Moritz Lipp committed
26

27
28
29
30
#include <girara/datastructures.h>
#include <girara/utils.h>
#include <girara/statusbar.h>

31
32
33
34
35
/**
 * Register document plugin
 */
static bool zathura_document_plugin_register(zathura_t* zathura, zathura_document_plugin_t* new_plugin);

Moritz Lipp's avatar
Moritz Lipp committed
36
void
Sebastian Ramacher's avatar
Sebastian Ramacher committed
37
zathura_document_plugins_load(zathura_t* zathura)
Moritz Lipp's avatar
Moritz Lipp committed
38
{
39
  GIRARA_LIST_FOREACH(zathura->plugins.path, char*, iter, plugindir)
40

41
42
43
44
    /* read all files in the plugin directory */
    DIR* dir = opendir(plugindir);
    if (dir == NULL) {
      girara_error("could not open plugin directory: %s", plugindir);
45
      girara_list_iterator_next(iter);
46
47
48
      continue;
    }

49
50
51
    int fddir = dirfd(dir);
    struct dirent* entry;
    while ((entry = readdir(dir)) != NULL) {
Moritz Lipp's avatar
Moritz Lipp committed
52
53
54
55
      if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
        continue;
      }

56
57
58
59
60
      struct stat statbuf;
      if (fstatat(fddir, entry->d_name, &statbuf, 0) != 0) {
        girara_error("failed to fstatat %s/%s; errno is %d.", plugindir, entry->d_name, errno);
        continue;
      }
61

62
63
64
65
66
      /* check if entry is a file */
      if (S_ISREG(statbuf.st_mode) == 0) {
        girara_info("%s/%s is not a regular file. Skipping.", plugindir, entry->d_name);
        continue;
      }
Moritz Lipp's avatar
Moritz Lipp committed
67

68
69
70
      void* handle                      = NULL;
      zathura_document_plugin_t* plugin = NULL;
      char* path                        = NULL;
Moritz Lipp's avatar
Moritz Lipp committed
71

72
73
74
75
76
77
      /* get full path */
      path = g_build_filename(plugindir, entry->d_name, NULL);
      if (path == NULL) {
        g_error("failed to allocate memory!");
        break;
      }
Moritz Lipp's avatar
Moritz Lipp committed
78

79
80
81
82
83
84
85
      /* load plugin */
      handle = dlopen(path, RTLD_NOW);
      if (handle == NULL) {
        girara_error("could not load plugin %s (%s)", path, dlerror());
        g_free(path);
        continue;
      }
Moritz Lipp's avatar
Moritz Lipp committed
86

87
88
89
      /* resolve symbol */
      zathura_plugin_register_service_t register_plugin;
      *(void**)(&register_plugin) = dlsym(handle, PLUGIN_REGISTER_FUNCTION);
Moritz Lipp's avatar
Moritz Lipp committed
90

91
92
93
94
95
96
      if (register_plugin == NULL) {
        girara_error("could not find '%s' function in plugin %s", PLUGIN_REGISTER_FUNCTION, path);
        g_free(path);
        dlclose(handle);
        continue;
      }
Moritz Lipp's avatar
Moritz Lipp committed
97

98
99
100
      plugin = g_malloc0(sizeof(zathura_document_plugin_t));
      plugin->content_types = girara_list_new2(g_free);
      plugin->handle = handle;
101

102
      register_plugin(plugin);
103

104
      bool r = zathura_document_plugin_register(zathura, plugin);
105

106
107
      if (r == false) {
        girara_error("could not register plugin %s", path);
108
        zathura_document_plugin_free(plugin);
Sebastian Ramacher's avatar
Sebastian Ramacher committed
109
      } else {
110
111
        girara_info("successfully loaded plugin %s", path);
      }
112

113
      g_free(path);
114
115
    }

116
117
    if (closedir(dir) == -1) {
      girara_error("could not close plugin directory %s", plugindir);
118
    }
119
  GIRARA_LIST_FOREACH_END(zathura->plugins.path, char*, iter, plugindir);
Moritz Lipp's avatar
Moritz Lipp committed
120
121
122
}

void
123
zathura_document_plugin_free(zathura_document_plugin_t* plugin)
Moritz Lipp's avatar
Moritz Lipp committed
124
{
125
  if (plugin == NULL) {
Sebastian Ramacher's avatar
Sebastian Ramacher committed
126
    return;
Moritz Lipp's avatar
Moritz Lipp committed
127
128
  }

129
  dlclose(plugin->handle);
130
  girara_list_free(plugin->content_types);
131
  g_free(plugin);
Moritz Lipp's avatar
Moritz Lipp committed
132
133
}

134
135
static bool
zathura_document_plugin_register(zathura_t* zathura, zathura_document_plugin_t* new_plugin)
136
{
Sebastian Ramacher's avatar
Sebastian Ramacher committed
137
  if (new_plugin == NULL || new_plugin->content_types == NULL || new_plugin->open_function == NULL) {
Sebastian Ramacher's avatar
Sebastian Ramacher committed
138
    girara_error("plugin: could not register\n");
139
140
141
    return false;
  }

142
143
144
145
  bool atleastone = false;
  GIRARA_LIST_FOREACH(new_plugin->content_types, gchar*, iter, type)
    if (!zathura_type_plugin_mapping_new(zathura, type, new_plugin)) {
      girara_error("plugin: already registered for filetype %s\n", type);
Sebastian Ramacher's avatar
Sebastian Ramacher committed
146
147
    } else {
      atleastone = true;
148
    }
Sebastian Ramacher's avatar
Sebastian Ramacher committed
149
  GIRARA_LIST_FOREACH_END(new_plugin->content_types, gchar*, iter, type);
150

151
152
153
154
  if (atleastone) {
    girara_list_append(zathura->plugins.plugins, new_plugin);
  }
  return atleastone;
155
156
}

157
158
static const gchar*
guess_type(const char* path)
Moritz Lipp's avatar
Moritz Lipp committed
159
{
160
161
162
  gboolean uncertain;
  const gchar* content_type = g_content_type_guess(path, NULL, 0, &uncertain);
  if (content_type == NULL) {
163
    return NULL;
Moritz Lipp's avatar
Moritz Lipp committed
164
165
  }

166
167
  FILE* f = fopen(path, "r");
  if (f == NULL) {
168
    return NULL;
Moritz Lipp's avatar
Moritz Lipp committed
169
170
  }

171
172
173
174
175
176
177
  const int fd = fileno(f);
  guchar* content = NULL;
  size_t length = 0u;
  while (uncertain == TRUE) {
    g_free((void*)content_type);
    content_type = NULL;

Sebastian Ramacher's avatar
Sebastian Ramacher committed
178
179
    content = g_realloc(content, length + BUFSIZ);
    const ssize_t r = read(fd, content + length, BUFSIZ);
180
181
182
183
184
185
    if (r == -1) {
      break;
    }

    length += r;
    content_type = g_content_type_guess(NULL, content, length, &uncertain);
Moritz Lipp's avatar
Moritz Lipp committed
186
187
  }

188
  fclose(f);
189
190
191
  if (uncertain == TRUE) {
    g_free((void*)content_type);
    content_type = NULL;
192
  }
193

194
195
196
  g_free(content);
  return content_type;
}
197

198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
zathura_document_t*
zathura_document_open(zathura_t* zathura, const char* path, const char* password)
{
  if (path == NULL) {
    return NULL;
  }

  if (file_exists(path) == false) {
    girara_error("File '%s' does not exist", path);
    return NULL;
  }

  const gchar* content_type = guess_type(path);
  if (content_type == NULL) {
    girara_error("Could not determine file type.");
    return NULL;
214
215
  }

Moritz Lipp's avatar
Moritz Lipp committed
216
  /* determine real path */
217
  long path_max;
Moritz Lipp's avatar
Moritz Lipp committed
218
219
220
221
#ifdef PATH_MAX
  path_max = PATH_MAX;
#else
  path_max = pathconf(path,_PC_PATH_MAX);
222
  if (path_max <= 0)
Moritz Lipp's avatar
Moritz Lipp committed
223
224
225
    path_max = 4096;
#endif

Moritz Lipp's avatar
Moritz Lipp committed
226
227
228
229
  char* real_path              = NULL;
  zathura_document_t* document = NULL;

  real_path = malloc(sizeof(char) * path_max);
Moritz Lipp's avatar
Moritz Lipp committed
230
  if (real_path == NULL) {
231
232
    g_free((void*)content_type);
    return NULL;
Moritz Lipp's avatar
Moritz Lipp committed
233
234
  }

Moritz Lipp's avatar
Moritz Lipp committed
235
  if (realpath(path, real_path) == NULL) {
236
237
238
239
240
241
242
243
244
245
246
    g_free((void*)content_type);
    free(real_path);
    return NULL;
  }

  zathura_document_plugin_t* plugin = NULL;
  GIRARA_LIST_FOREACH(zathura->plugins.type_plugin_mapping, zathura_type_plugin_mapping_t*, iter, mapping)
    if (g_content_type_equals(content_type, mapping->type)) {
      plugin = mapping->plugin;
      break;
    }
Sebastian Ramacher's avatar
Sebastian Ramacher committed
247
  GIRARA_LIST_FOREACH_END(zathura->plugins.type_plugin_mapping, zathura_type_plugin_mapping_t*, iter, mapping);
248
249
250
251
  g_free((void*)content_type);

  if (plugin == NULL) {
    girara_error("unknown file type\n");
252
    goto error_free;
Moritz Lipp's avatar
Moritz Lipp committed
253
254
  }

Moritz Lipp's avatar
Moritz Lipp committed
255
  document = g_malloc0(sizeof(zathura_document_t));
Moritz Lipp's avatar
Moritz Lipp committed
256

Moritz Lipp's avatar
Moritz Lipp committed
257
  document->file_path           = real_path;
Moritz Lipp's avatar
Moritz Lipp committed
258
  document->password            = password;
Moritz Lipp's avatar
Moritz Lipp committed
259
  document->scale               = 1.0;
260
  document->zathura             = zathura;
Moritz Lipp's avatar
Moritz Lipp committed
261

Pavel Borzenkov's avatar
Pavel Borzenkov committed
262
263
264
  int offset = 0;
  zathura_db_get_fileinfo(zathura->database, document->file_path,
      &document->current_page_number, &offset, &document->scale);
265
  if (document->scale <= FLT_EPSILON) {
266
267
268
    girara_warning("document info: '%s' has non positive scale", document->file_path);
    document->scale = 1;
  }
Pavel Borzenkov's avatar
Pavel Borzenkov committed
269

270
271
272
273
  if (plugin->open_function != NULL) {
    if (plugin->open_function(document) == true) {
      /* update statusbar */
      girara_statusbar_item_set_text(zathura->ui.session, zathura->ui.statusbar.file, real_path);
274

275
276
277
278
279
280
281
282
283
      /* read all pages */
      document->pages = calloc(document->number_of_pages, sizeof(zathura_page_t*));
      if (document->pages == NULL) {
        goto error_free;
      }

      for (unsigned int page_id = 0; page_id < document->number_of_pages; page_id++) {
        zathura_page_t* page = zathura_page_get(document, page_id);
        if (page == NULL) {
Moritz Lipp's avatar
Moritz Lipp committed
284
          goto error_free;
Moritz Lipp's avatar
Moritz Lipp committed
285
        }
286
287

        document->pages[page_id] = page;
Moritz Lipp's avatar
Moritz Lipp committed
288
      }
289
290

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

294
  girara_error("could not open file\n");
Moritz Lipp's avatar
Moritz Lipp committed
295

Moritz Lipp's avatar
Moritz Lipp committed
296
297
error_free:

Moritz Lipp's avatar
Moritz Lipp committed
298
  free(real_path);
Moritz Lipp's avatar
Moritz Lipp committed
299

Moritz Lipp's avatar
Moritz Lipp committed
300
301
  if (document != NULL && document->pages != NULL) {
    for (unsigned int page_id = 0; page_id < document->number_of_pages; page_id++) {
Moritz Lipp's avatar
Moritz Lipp committed
302
303
304
305
306
307
      zathura_page_free(document->pages[page_id]);
    }

    free(document->pages);
  }

Moritz Lipp's avatar
Moritz Lipp committed
308
  g_free(document);
Moritz Lipp's avatar
Moritz Lipp committed
309
310
311
  return NULL;
}

Moritz Lipp's avatar
Moritz Lipp committed
312
313
bool
zathura_document_free(zathura_document_t* document)
Moritz Lipp's avatar
Moritz Lipp committed
314
{
Moritz Lipp's avatar
Moritz Lipp committed
315
  if (document == NULL) {
Moritz Lipp's avatar
Moritz Lipp committed
316
    return false;
Moritz Lipp's avatar
Moritz Lipp committed
317
318
  }

Moritz Lipp's avatar
Moritz Lipp committed
319
  /* free pages */
Moritz Lipp's avatar
Moritz Lipp committed
320
  for (unsigned int page_id = 0; page_id < document->number_of_pages; page_id++) {
Moritz Lipp's avatar
Moritz Lipp committed
321
    zathura_page_free(document->pages[page_id]);
Pavel Borzenkov's avatar
Pavel Borzenkov committed
322
    document->pages[page_id] = NULL;
Moritz Lipp's avatar
Moritz Lipp committed
323
324
325
326
327
  }

  free(document->pages);

  /* free document */
Sebastian Ramacher's avatar
Sebastian Ramacher committed
328
  bool r = true;
Moritz Lipp's avatar
Moritz Lipp committed
329
  if (document->functions.document_free == NULL) {
Moritz Lipp's avatar
Moritz Lipp committed
330
    girara_error("%s not implemented", __FUNCTION__);
Sebastian Ramacher's avatar
Sebastian Ramacher committed
331
332
  } else {
    r = document->functions.document_free(document);
Moritz Lipp's avatar
Moritz Lipp committed
333
334
  }

Moritz Lipp's avatar
Moritz Lipp committed
335
  if (document->file_path != NULL) {
Moritz Lipp's avatar
Moritz Lipp committed
336
337
338
    free(document->file_path);
  }

Moritz Lipp's avatar
Moritz Lipp committed
339
  g_free(document);
Moritz Lipp's avatar
Moritz Lipp committed
340
341

  return r;
Moritz Lipp's avatar
Moritz Lipp committed
342
343
344
345
346
}

bool
zathura_document_save_as(zathura_document_t* document, const char* path)
{
Moritz Lipp's avatar
Moritz Lipp committed
347
  if (document == NULL || path == NULL) {
Moritz Lipp's avatar
Moritz Lipp committed
348
349
350
    return false;
  }

Moritz Lipp's avatar
Moritz Lipp committed
351
  if (document->functions.document_save_as == NULL) {
Moritz Lipp's avatar
Moritz Lipp committed
352
    girara_error("%s not implemented", __FUNCTION__);
Moritz Lipp's avatar
Moritz Lipp committed
353
354
355
356
    return false;
  }

  return document->functions.document_save_as(document, path);
Moritz Lipp's avatar
Moritz Lipp committed
357
358
}

359
girara_tree_node_t*
Moritz Lipp's avatar
Moritz Lipp committed
360
zathura_document_index_generate(zathura_document_t* document)
Moritz Lipp's avatar
Moritz Lipp committed
361
{
Moritz Lipp's avatar
Moritz Lipp committed
362
  if (document == NULL) {
Moritz Lipp's avatar
Moritz Lipp committed
363
364
365
    return NULL;
  }

Moritz Lipp's avatar
Moritz Lipp committed
366
  if (document->functions.document_index_generate == NULL) {
Moritz Lipp's avatar
Moritz Lipp committed
367
    girara_error("%s not implemented", __FUNCTION__);
Moritz Lipp's avatar
Moritz Lipp committed
368
369
370
371
    return NULL;
  }

  return document->functions.document_index_generate(document);
Moritz Lipp's avatar
Moritz Lipp committed
372
373
}

Sebastian Ramacher's avatar
Sebastian Ramacher committed
374
girara_list_t*
Moritz Lipp's avatar
Moritz Lipp committed
375
zathura_document_attachments_get(zathura_document_t* document)
Moritz Lipp's avatar
Moritz Lipp committed
376
{
Moritz Lipp's avatar
Moritz Lipp committed
377
  if (document == NULL) {
Moritz Lipp's avatar
Moritz Lipp committed
378
379
380
    return NULL;
  }

Moritz Lipp's avatar
Moritz Lipp committed
381
  if (document->functions.document_attachments_get == NULL) {
Moritz Lipp's avatar
Moritz Lipp committed
382
    girara_error("%s not implemented", __FUNCTION__);
Moritz Lipp's avatar
Moritz Lipp committed
383
384
385
386
    return NULL;
  }

  return document->functions.document_attachments_get(document);
Moritz Lipp's avatar
Moritz Lipp committed
387
388
389
}

bool
Sebastian Ramacher's avatar
Sebastian Ramacher committed
390
zathura_document_attachments_free(girara_list_t* UNUSED(list))
Moritz Lipp's avatar
Moritz Lipp committed
391
392
393
394
{
  return false;
}

Moritz Lipp's avatar
Moritz Lipp committed
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
char*
zathura_document_meta_get(zathura_document_t* document, zathura_document_meta_t meta)
{
  if (document == NULL) {
    return NULL;
  }

  if (document->functions.document_meta_get == NULL) {
    girara_error("%s not implemented", __FUNCTION__);
    return NULL;
  }

  return document->functions.document_meta_get(document, meta);
}

Moritz Lipp's avatar
Moritz Lipp committed
410
zathura_page_t*
411
zathura_page_get(zathura_document_t* document, unsigned int page_id)
Moritz Lipp's avatar
Moritz Lipp committed
412
{
Moritz Lipp's avatar
Moritz Lipp committed
413
  if (document == NULL) {
Moritz Lipp's avatar
Moritz Lipp committed
414
415
416
    return NULL;
  }

Moritz Lipp's avatar
Moritz Lipp committed
417
  if (document->functions.page_get == NULL) {
Moritz Lipp's avatar
Moritz Lipp committed
418
    girara_error("%s not implemented", __FUNCTION__);
Moritz Lipp's avatar
Moritz Lipp committed
419
420
421
    return NULL;
  }

422
423
  zathura_page_t* page = document->functions.page_get(document, page_id);

Moritz Lipp's avatar
Moritz Lipp committed
424
  if (page != NULL) {
Moritz Lipp's avatar
Moritz Lipp committed
425
    page->number       = page_id;
426
    page->visible      = false;
Moritz Lipp's avatar
Moritz Lipp committed
427
428
    page->event_box    = gtk_event_box_new();
    page->drawing_area = gtk_drawing_area_new();
Moritz Lipp's avatar
Moritz Lipp committed
429
    page->surface      = NULL;
430
    page->document     = document;
Moritz Lipp's avatar
Update    
Moritz Lipp committed
431
    g_signal_connect(page->drawing_area, "expose-event", G_CALLBACK(page_expose_event), page);
Moritz Lipp's avatar
Moritz Lipp committed
432

Moritz Lipp's avatar
Moritz Lipp committed
433
    gtk_widget_set_size_request(page->drawing_area, page->width * document->scale, page->height * document->scale);
Moritz Lipp's avatar
Moritz Lipp committed
434
435
    gtk_container_add(GTK_CONTAINER(page->event_box), page->drawing_area);

436
437
438
439
    g_static_mutex_init(&(page->lock));
  }

  return page;
Moritz Lipp's avatar
Moritz Lipp committed
440
441
}

Moritz Lipp's avatar
Moritz Lipp committed
442
443
444
bool
zathura_page_free(zathura_page_t* page)
{
Moritz Lipp's avatar
Moritz Lipp committed
445
  if (page == NULL || page->document == NULL) {
Moritz Lipp's avatar
Moritz Lipp committed
446
447
448
    return false;
  }

Moritz Lipp's avatar
Moritz Lipp committed
449
  if (page->document->functions.page_free == NULL) {
Moritz Lipp's avatar
Moritz Lipp committed
450
    girara_error("%s not implemented", __FUNCTION__);
Moritz Lipp's avatar
Moritz Lipp committed
451
452
453
    return false;
  }

Pavel Borzenkov's avatar
Pavel Borzenkov committed
454
455
  g_static_mutex_free(&(page->lock));

Moritz Lipp's avatar
Moritz Lipp committed
456
457
458
  return page->document->functions.page_free(page);
}

Sebastian Ramacher's avatar
Sebastian Ramacher committed
459
girara_list_t*
Moritz Lipp's avatar
Moritz Lipp committed
460
zathura_page_search_text(zathura_page_t* page, const char* text)
Moritz Lipp's avatar
Moritz Lipp committed
461
{
Moritz Lipp's avatar
Moritz Lipp committed
462
  if (page == NULL || page->document == NULL || text == NULL) {
Moritz Lipp's avatar
Moritz Lipp committed
463
464
465
    return NULL;
  }

Moritz Lipp's avatar
Moritz Lipp committed
466
  if (page->document->functions.page_search_text == NULL) {
Moritz Lipp's avatar
Moritz Lipp committed
467
    girara_error("%s not implemented", __FUNCTION__);
Moritz Lipp's avatar
Moritz Lipp committed
468
469
470
471
    return NULL;
  }

  return page->document->functions.page_search_text(page, text);
Moritz Lipp's avatar
Moritz Lipp committed
472
473
}

Sebastian Ramacher's avatar
Sebastian Ramacher committed
474
girara_list_t*
Moritz Lipp's avatar
Moritz Lipp committed
475
zathura_page_links_get(zathura_page_t* page)
Moritz Lipp's avatar
Moritz Lipp committed
476
{
Moritz Lipp's avatar
Moritz Lipp committed
477
  if (page == NULL || page->document == NULL) {
Moritz Lipp's avatar
Moritz Lipp committed
478
479
480
    return NULL;
  }

Moritz Lipp's avatar
Moritz Lipp committed
481
  if (page->document->functions.page_links_get == NULL) {
Moritz Lipp's avatar
Moritz Lipp committed
482
    girara_error("%s not implemented", __FUNCTION__);
Moritz Lipp's avatar
Moritz Lipp committed
483
484
485
486
    return NULL;
  }

  return page->document->functions.page_links_get(page);
Moritz Lipp's avatar
Moritz Lipp committed
487
488
489
}

bool
Sebastian Ramacher's avatar
Sebastian Ramacher committed
490
zathura_page_links_free(girara_list_t* UNUSED(list))
Moritz Lipp's avatar
Moritz Lipp committed
491
492
493
494
{
  return false;
}

Sebastian Ramacher's avatar
Sebastian Ramacher committed
495
girara_list_t*
Moritz Lipp's avatar
Moritz Lipp committed
496
zathura_page_form_fields_get(zathura_page_t* page)
Moritz Lipp's avatar
Moritz Lipp committed
497
{
Moritz Lipp's avatar
Moritz Lipp committed
498
  if (page == NULL || page->document == NULL) {
Moritz Lipp's avatar
Moritz Lipp committed
499
500
501
    return NULL;
  }

Moritz Lipp's avatar
Moritz Lipp committed
502
  if (page->document->functions.page_form_fields_get == NULL) {
Moritz Lipp's avatar
Moritz Lipp committed
503
    girara_error("%s not implemented", __FUNCTION__);
Moritz Lipp's avatar
Moritz Lipp committed
504
505
506
507
    return NULL;
  }

  return page->document->functions.page_form_fields_get(page);
Moritz Lipp's avatar
Moritz Lipp committed
508
509
510
}

bool
Sebastian Ramacher's avatar
Sebastian Ramacher committed
511
zathura_page_form_fields_free(girara_list_t* UNUSED(list))
Moritz Lipp's avatar
Moritz Lipp committed
512
513
514
{
  return false;
}
Moritz Lipp's avatar
Moritz Lipp committed
515

Moritz Lipp's avatar
Moritz Lipp committed
516
517
bool
zathura_page_render(zathura_page_t* page, cairo_t* cairo)
Moritz Lipp's avatar
Moritz Lipp committed
518
{
Moritz Lipp's avatar
Moritz Lipp committed
519
  if (page == NULL || page->document == NULL || cairo == NULL) {
Moritz Lipp's avatar
Moritz Lipp committed
520
521
522
    return NULL;
  }

Moritz Lipp's avatar
Moritz Lipp committed
523
  if (page->document->functions.page_render_cairo == NULL) {
Moritz Lipp's avatar
Moritz Lipp committed
524
    girara_error("%s not implemented", __FUNCTION__);
Moritz Lipp's avatar
Moritz Lipp committed
525
526
527
    return NULL;
  }

Moritz Lipp's avatar
Moritz Lipp committed
528
  return page->document->functions.page_render_cairo(page, cairo);
Moritz Lipp's avatar
Moritz Lipp committed
529
}
530
531
532
533

zathura_index_element_t*
zathura_index_element_new(const char* title)
{
Moritz Lipp's avatar
Moritz Lipp committed
534
  if (title == NULL) {
535
    return NULL;
Moritz Lipp's avatar
Moritz Lipp committed
536
  }
537
538

  zathura_index_element_t* res = g_malloc0(sizeof(zathura_index_element_t));
Moritz Lipp's avatar
Moritz Lipp committed
539

540
  res->title = g_strdup(title);
Moritz Lipp's avatar
Moritz Lipp committed
541

542
543
544
545
546
547
  return res;
}

void
zathura_index_element_free(zathura_index_element_t* index)
{
Moritz Lipp's avatar
Moritz Lipp committed
548
  if (index == NULL) {
549
    return;
Moritz Lipp's avatar
Moritz Lipp committed
550
  }
551
552

  g_free(index->title);
Moritz Lipp's avatar
Moritz Lipp committed
553

Moritz Lipp's avatar
Moritz Lipp committed
554
  if (index->type == ZATHURA_LINK_EXTERNAL) {
555
    g_free(index->target.uri);
Moritz Lipp's avatar
Moritz Lipp committed
556
557
  }

558
559
  g_free(index);
}
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576

zathura_image_buffer_t*
zathura_image_buffer_create(unsigned int width, unsigned int height)
{
  zathura_image_buffer_t* image_buffer = malloc(sizeof(zathura_image_buffer_t));

  if (image_buffer == NULL) {
    return NULL;
  }

  image_buffer->data = calloc(width * height * 3, sizeof(unsigned char));

  if (image_buffer->data == NULL) {
    free(image_buffer);
    return NULL;
  }

Moritz Lipp's avatar
Moritz Lipp committed
577
578
579
  image_buffer->width     = width;
  image_buffer->height    = height;
  image_buffer->rowstride = width * 3;
580
581
582
583
584
585
586
587
588
589
590
591

  return image_buffer;
}

void
zathura_image_buffer_free(zathura_image_buffer_t* image_buffer)
{
  if (image_buffer == NULL) {
    return;
  }

  free(image_buffer->data);
Sebastian Ramacher's avatar
Sebastian Ramacher committed
592
  free(image_buffer);
593
}
594
595
596
597
598
599
600
601
602
603
604

bool
zathura_type_plugin_mapping_new(zathura_t* zathura, const gchar* type, zathura_document_plugin_t* plugin)
{
  g_return_val_if_fail(zathura && type && plugin, false);

  GIRARA_LIST_FOREACH(zathura->plugins.type_plugin_mapping, zathura_type_plugin_mapping_t*, iter, mapping)
    if (g_content_type_equals(type, mapping->type)) {
      girara_list_iterator_free(iter);
      return false;
    }
Sebastian Ramacher's avatar
Sebastian Ramacher committed
605
  GIRARA_LIST_FOREACH_END(zathura->plugins.type_plugin_mapping, zathura_type_plugin_mapping_t*, iter, mapping);
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623

  zathura_type_plugin_mapping_t* mapping = g_malloc(sizeof(zathura_type_plugin_mapping_t));
  mapping->type = g_strdup(type);
  mapping->plugin = plugin;
  girara_list_append(zathura->plugins.type_plugin_mapping, mapping);
  return true;
}

void
zathura_type_plugin_mapping_free(zathura_type_plugin_mapping_t* mapping)
{
  if (mapping == NULL) {
    return;
  }

  g_free((void*)mapping->type);
  g_free(mapping);
}