diff options
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/luapplib/ppxref.c')
-rw-r--r-- | Build/source/texk/web2c/luatexdir/luapplib/ppxref.c | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/luatexdir/luapplib/ppxref.c b/Build/source/texk/web2c/luatexdir/luapplib/ppxref.c new file mode 100644 index 00000000000..984f6cbe327 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/ppxref.c @@ -0,0 +1,162 @@ + +#include "pplib.h" + +#define PPXREF_MAP_INIT 16 // number of xref sections + +ppxref * ppxref_create (ppdoc *pdf, size_t initsize, size_t xrefoffset) +{ + ppxref *xref; + + if (initsize == 0) // unknown + initsize = PPXREF_MAP_INIT; + xref = (ppxref *)ppheap_take(&pdf->heap, sizeof(ppxref) + initsize * sizeof(ppxsec)); + xref->sects = (ppxsec *)(xref + 1); + xref->size = 0; + xref->space = initsize; + xref->count = 0; + xref->trailer.type = PPNONE; + xref->trailer.dict = NULL; + xref->prev = NULL; + xref->pdf = pdf; + xref->offset = xrefoffset; + //xref->crypt = NULL; + return xref; +} + +ppxsec * ppxref_push_section (ppxref *xref, ppheap **pheap) +{ + ppxsec *sects; + if (xref->size < xref->space) + return &xref->sects[xref->size++]; + xref->space <<= 1; + sects = xref->sects; + xref->sects = (ppxsec *)ppheap_take(pheap, xref->space * sizeof(ppxsec)); // waste but rare + memcpy(xref->sects, sects, xref->size * sizeof(ppxsec)); + return &xref->sects[xref->size++]; +} + +static void ppxref_sort_sects (ppxsec *left, ppxsec *right) +{ + ppxsec *l, *r, *m, t; + ppuint first, last; + l = left, r = right, m = l + ((r - l) / 2); + first = m->first, last = m->last; + do + { // don't take first/last from pointer + while (l->first < first) ++l; + while (r->first > last) --r; + if (l <= r) + { + t = *l; + *l = *r; + *r = t; + ++l, --r; + } + } while (l <= r); + if (l < right) + ppxref_sort_sects(l, right); + if (r > left) + ppxref_sort_sects(left, r); +} + +int ppxref_sort (ppxref *xref) +{ + if (xref->size == 0) + return 0; + ppxref_sort_sects(xref->sects, xref->sects + xref->size - 1); + return 1; +} + +ppref * ppxref_find_local (ppxref *xref, ppuint refnumber) +{ + ppxsec *left, *right, *mid; + //if (xref->size == 0) // we don't allow that + // return NULL; + left = xref->sects; + right = xref->sects + xref->size - 1; + do + { + mid = left + ((right - left) / 2); + if (refnumber > mid->last) + left = mid + 1; + else if (refnumber < mid->first) + right = mid - 1; + else + return &mid->refs[refnumber - mid->first]; + } while (left <= right); + return NULL; +} + +ppref * ppxref_find (ppxref *xref, ppuint refnumber) +{ + ppref *ref; + ppxref *other; + + if ((ref = ppxref_find_local(xref, refnumber)) != NULL) + return ref; + if (xref->pdf->flags & PPDOC_LINEARIZED) + { + for (other = xref->pdf->xref; other != NULL; other = other->prev) + if (other != xref && (ref = ppxref_find_local(other, refnumber)) != NULL) + return ref; + } + else + { + for (other = xref->prev; other != NULL; other = other->prev) + if ((ref = ppxref_find_local(other, refnumber)) != NULL) + return ref; + /* This shouldn't happen, but I've met documents that have no linearized dict, + but their xrefs are prepared as for linearized; with "older" xrefs referring + to "newer". */ + for (other = xref->pdf->xref; other != NULL && other != xref; other = other->prev) + if ((ref = ppxref_find_local(other, refnumber)) != NULL) + return ref; + } + return NULL; +} + +ppdict * ppxref_trailer (ppxref *xref) +{ + switch (xref->trailer.type) + { + case PPDICT: + return xref->trailer.dict; + case PPSTREAM: + return xref->trailer.stream->dict; + default: + break; + } + return NULL; +} + +ppxref * ppdoc_xref (ppdoc *pdf) +{ + return pdf->xref; +} + +ppxref * ppxref_prev (ppxref *xref) +{ + return xref->prev; +} + +ppdict * ppxref_catalog (ppxref *xref) +{ + ppdict *trailer; + return (trailer = ppxref_trailer(xref)) != NULL ? ppdict_rget_dict(trailer, "Root") : NULL; +} + +ppdict * ppxref_info (ppxref *xref) +{ + ppdict *trailer; + return (trailer = ppxref_trailer(xref)) != NULL ? ppdict_rget_dict(trailer, "Info") : NULL; +} + +ppref * ppxref_pages (ppxref *xref) +{ + ppdict *dict; + ppref *ref; + + if ((dict = ppxref_catalog(xref)) == NULL || (ref = ppdict_get_ref(dict, "Pages")) == NULL) + return NULL; + return ref->object.type == PPDICT ? ref : NULL; +} |