index.c 2.61 KB
Newer Older
1 2 3 4 5 6 7 8
/* See LICENSE file for license and copyright information */

#define _POSIX_C_SOURCE 1

#include <girara/datastructures.h>

#include "plugin.h"

Moritz Lipp's avatar
Moritz Lipp committed
9 10
static void build_index(fz_context* ctx, fz_document* document, fz_outline*
    outline, girara_tree_node_t* root);
11 12 13 14 15 16 17 18 19 20 21 22

girara_tree_node_t*
pdf_document_index_generate(zathura_document_t* document, mupdf_document_t* mupdf_document, zathura_error_t* error)
{
  if (document == NULL || mupdf_document == NULL) {
    if (error != NULL) {
      *error = ZATHURA_ERROR_INVALID_ARGUMENTS;
    }
    return NULL;
  }

  /* get outline */
Moritz Lipp's avatar
Moritz Lipp committed
23
  fz_outline* outline = fz_load_outline(mupdf_document->ctx, mupdf_document->document);
24 25 26 27 28 29 30 31 32
  if (outline == NULL) {
    if (error != NULL) {
      *error = ZATHURA_ERROR_UNKNOWN;
    }
    return NULL;
  }

  /* generate index */
  girara_tree_node_t* root = girara_node_new(zathura_index_element_new("ROOT"));
Moritz Lipp's avatar
Moritz Lipp committed
33
  build_index(mupdf_document->ctx, mupdf_document->document, outline, root);
34 35

  /* free outline */
Moritz Lipp's avatar
Moritz Lipp committed
36
  fz_drop_outline(mupdf_document->ctx, outline);
37 38 39 40 41

  return root;
}

static void
Moritz Lipp's avatar
Moritz Lipp committed
42
build_index(fz_context* ctx, fz_document* document, fz_outline* outline, girara_tree_node_t* root)
43 44 45 46 47 48 49
{
  if (outline == NULL || root == NULL) {
    return;
  }

  while (outline != NULL) {
    zathura_index_element_t* index_element = zathura_index_element_new(outline->title);
50 51 52
    zathura_link_target_t target           = { ZATHURA_LINK_DESTINATION_UNKNOWN, NULL, 0, -1, -1, -1, -1, 0 };
    zathura_link_type_t type               = ZATHURA_LINK_INVALID;
    zathura_rectangle_t rect               = { .x1 = 0, .y1 = 0, .x2 = 0, .y2 = 0 };
53

54 55 56
    if (outline->uri == NULL) {
      type = ZATHURA_LINK_NONE;
    } else if (fz_is_external_link(ctx, outline->uri) == 1) {
Moritz Lipp's avatar
Moritz Lipp committed
57 58 59 60
      if (strstr(outline->uri, "file://") == outline->uri) {
        type         = ZATHURA_LINK_GOTO_REMOTE;
        target.value = outline->uri;
      } else {
61
        type         = ZATHURA_LINK_URI;
Moritz Lipp's avatar
Moritz Lipp committed
62 63 64 65 66 67 68 69 70 71 72 73
        target.value = outline->uri;
      }
    } else {
      float x = 0;
      float y = 0;

      type                    = ZATHURA_LINK_GOTO_DEST;
      target.destination_type = ZATHURA_LINK_DESTINATION_XYZ;
      target.page_number      = fz_resolve_link(ctx, document, outline->uri, &x, &y);
      target.left  = x;
      target.top   = y;
      target.scale = 0.0;
74 75 76 77
    }

    index_element->link = zathura_link_new(type, rect, target);
    if (index_element->link == NULL) {
78
      outline = outline->next;
79 80 81 82 83 84
      continue;
    }

    girara_tree_node_t* node = girara_node_append_data(root, index_element);

    if (outline->down != NULL) {
Moritz Lipp's avatar
Moritz Lipp committed
85
      build_index(ctx, document, outline->down, node);
86 87 88 89 90 91
    }

    outline = outline->next;
  }
}