/* * Copyright (c) 2020-2022, yzrh * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include "cnki.h" #include "iconv.h" #include "pdf.h" /* * It will write first, list, and count to *stat * so that when called recursively, it knows * what to do */ static int _outline(pdf_object_t **pdf, object_outline_tree_t **outline_tree, int id, int **stat) { *stat = malloc(3 * sizeof(int)); if (*stat == NULL) return 1; int size; char *str; int *ret; char buf[64]; char dictionary[1024]; object_outline_tree_t *ptr = *outline_tree; (*stat)[0] = ptr->id; (*stat)[2] = 0; while (ptr != NULL) { memset(dictionary, 0, 1024); strcat(dictionary, "<<\n"); size = 514; str = NULL; if (strconv(&str, "UTF-16BE", ptr->item->title, "GB18030", &size) == 0) { strcat(dictionary, "/Title \n"); } free(str); snprintf(buf, 64, "/Parent %d 0 R\n", id); strcat(dictionary, buf); if (ptr->up != NULL && ptr->up->id != id) { snprintf(buf, 64, "/Prev %d 0 R\n", ptr->up->id); strcat(dictionary, buf); } if (ptr->left != NULL) { snprintf(buf, 64, "/Next %d 0 R\n", ptr->left->id); strcat(dictionary, buf); } if (ptr->right != NULL) { _outline(pdf, &ptr->right, ptr->id, &ret); snprintf(buf, 64, "/First %d 0 R\n", ret[0]); strcat(dictionary, buf); snprintf(buf, 64, "/Last %d 0 R\n", ret[1]); strcat(dictionary, buf); snprintf(buf, 64, "/Count -%d\n", ret[2]); strcat(dictionary, buf); free(ret); } /* Page starts from 0 */ snprintf(buf, 64, "/Dest [%d /XYZ null null null]\n>>", atoi(ptr->item->page) - 1); strcat(dictionary, buf); pdf_obj_append(pdf, ptr->id, NULL, dictionary, NULL, 0); if (ptr->left == NULL) (*stat)[1] = ptr->id; (*stat)[2]++; ptr = ptr->left; } return 0; } static int _outline_free(object_outline_tree_t **outline_tree) { object_outline_tree_t *ptr = *outline_tree; for (;;) { if (ptr->right != NULL) _outline_free(&ptr->right); if (ptr->left != NULL) { ptr = ptr->left; free(ptr->up); } else { free(ptr); break; } } return 0; } int pdf_cnki_outline(pdf_object_t **pdf, object_outline_t **outline, int **ids) { if (*pdf == NULL || *outline == NULL || *ids == NULL) return 1; object_outline_tree_t *outline_tree = NULL; cnki_outline_tree(&outline_tree, outline, *ids); char buf[128]; int *ret; _outline(pdf, &outline_tree->left, outline_tree->id, &ret); _outline_free(&outline_tree); snprintf(buf, 128, "<<\n/Type Outlines\n/First %d 0 R\n/Last %d 0 R\n/Count %d\n>>", ret[0], ret[1], ret[2]); free(ret); pdf_obj_append(pdf, (*ids)[0], NULL, buf, NULL, 0); return 0; }