From 1b0d1da6b49faed60c644253f445cf9cb53841ba Mon Sep 17 00:00:00 2001 From: Sebastian Ramacher Date: Sat, 25 Dec 2010 00:47:52 +0100 Subject: [PATCH] create index of PDF documents --- ft/document.c | 25 +++++++++++++++++++ ft/document.h | 14 +++++++++++ ft/pdf/pdf.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 106 insertions(+), 1 deletion(-) diff --git a/ft/document.c b/ft/document.c index e049486..a0dacad 100644 --- a/ft/document.c +++ b/ft/document.c @@ -298,3 +298,28 @@ zathura_page_render(zathura_page_t* page) return page->document->functions.page_render(page); } + +zathura_index_element_t* +zathura_index_element_new(const char* title) +{ + if (!title) + return NULL; + + zathura_index_element_t* res = g_malloc0(sizeof(zathura_index_element_t)); + if (!res) + return NULL; + res->title = g_strdup(title); + return res; +} + +void +zathura_index_element_free(zathura_index_element_t* index) +{ + if (!index) + return; + + g_free(index->title); + if (index->type == ZATHURA_LINK_EXTERNAL) + g_free(index->target.uri); + g_free(index); +} diff --git a/ft/document.h b/ft/document.h index c322f0d..f193837 100644 --- a/ft/document.h +++ b/ft/document.h @@ -50,6 +50,17 @@ typedef struct zathura_link_s } target; } zathura_link_t; +typedef struct zathura_index_element_s +{ + char* title; + zathura_link_type_t type; + union + { + unsigned int page_number; + char* uri; + } target; +} zathura_index_element_t; + typedef enum zathura_form_type_e { ZATHURA_FORM_CHECKBOX, @@ -113,4 +124,7 @@ zathura_list_t* zathura_page_form_fields_get(zathura_page_t* page); bool zathura_page_form_fields_free(zathura_list_t* list); cairo_surface_t* zathura_page_render(zathura_page_t* page); +zathura_index_element_t* zathura_index_element_new(const char* title); +void zathura_index_element_free(zathura_index_element_t* index); + #endif // DOCUMENT_H diff --git a/ft/pdf/pdf.c b/ft/pdf/pdf.c index 688d59b..a2d6454 100644 --- a/ft/pdf/pdf.c +++ b/ft/pdf/pdf.c @@ -83,10 +83,76 @@ pdf_document_free(zathura_document_t* document) return true; } +static void +build_index(pdf_document_t* pdf, girara_tree_node_t* root, PopplerIndexIter* iter) +{ + if (!root || !iter) + return; + + do + { + PopplerAction* action = poppler_index_iter_get_action(iter); + if (!action) + continue; + + gchar* markup = g_markup_escape_text(action->any.title, -1); + zathura_index_element_t* indexelement = zathura_index_element_new(markup); + if (action->type == POPPLER_ACTION_URI) + { + indexelement->type = ZATHURA_LINK_EXTERNAL; + indexelement->target.uri = g_strdup(action->uri.uri); + } + else if (action->type == POPPLER_ACTION_GOTO_DEST) + { + indexelement->type = ZATHURA_LINK_TO_PAGE; + if (action->goto_dest.dest->type == POPPLER_DEST_NAMED) + { + PopplerDest* dest = poppler_document_find_dest(pdf->document, action->goto_dest.dest->named_dest); + if (dest) + { + indexelement->target.page_number = dest->page_num - 1; + poppler_dest_free(dest); + } + } + else + indexelement->target.page_number = action->goto_dest.dest->page_num - 1; + } + else + { + poppler_action_free(action); + zathura_index_element_free(indexelement); + continue; + } + poppler_action_free(action); + + girara_tree_node_t* node = girara_node_append_data(root, indexelement); + PopplerIndexIter* child = poppler_index_iter_get_child(iter); + if (child) + build_index(pdf, node, child); + poppler_index_iter_free(child); + } while (poppler_index_iter_next(iter)); +} + girara_tree_node_t* pdf_document_index_generate(zathura_document_t* document) { - return NULL; + if (!document || !document->data) { + return NULL; + } + + pdf_document_t* pdf_document = (pdf_document_t*) document->data; + PopplerIndexIter* iter = poppler_index_iter_new(pdf_document->document); + if (!iter) { + // XXX: error message? + return NULL; + } + + girara_tree_node_t* root = girara_node_new(zathura_index_element_new("ROOT")); + girara_node_set_free_function(root, (girara_free_function_t)zathura_index_element_free); + build_index(pdf_document, root, iter); + + poppler_index_iter_free(iter); + return root; } bool