Print this page
9718 update mandoc to 1.14.4
*** 1,9 ****
! /* $Id: term_ps.c,v 1.85 2017/06/07 17:38:26 schwarze Exp $ */
/*
* Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2014, 2015, 2016, 2017 Ingo Schwarze <schwarze@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
--- 1,10 ----
! /* $Id: term_ps.c,v 1.91 2017/11/10 23:42:52 schwarze Exp $ */
/*
* Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2014, 2015, 2016, 2017 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2017 Marc Espie <espie@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
*** 64,73 ****
--- 65,75 ----
#define PS_NEWPAGE (1 << 2) /* new page, no words yet */
#define PS_BACKSP (1 << 3) /* last character was backspace */
size_t pscol; /* visible column (AFM units) */
size_t pscolnext; /* used for overstrike */
size_t psrow; /* visible row (AFM units) */
+ size_t lastrow; /* psrow of the previous word */
char *psmarg; /* margin buf */
size_t psmargsz; /* margin buf size */
size_t psmargcur; /* cur index in margin buf */
char last; /* last non-backspace seen */
enum termfont lastf; /* last set font */
*** 75,84 ****
--- 77,87 ----
size_t scale; /* font scaling factor */
size_t pages; /* number of pages shown */
size_t lineheight; /* line height (AFM units) */
size_t top; /* body top (AFM units) */
size_t bottom; /* body bottom (AFM units) */
+ const char *medianame; /* for DocumentMedia and PageSize */
size_t height; /* page height (AFM units */
size_t width; /* page width (AFM units) */
size_t lastwidth; /* page width before last ll */
size_t left; /* body left (AFM units) */
size_t header; /* header pos (AFM units) */
*** 106,116 ****
static void ps_printf(struct termp *, const char *, ...)
__attribute__((__format__ (__printf__, 2, 3)));
static void ps_putchar(struct termp *, char);
static void ps_setfont(struct termp *, enum termfont);
static void ps_setwidth(struct termp *, int, int);
! static struct termp *pspdf_alloc(const struct manoutput *);
static void pdf_obj(struct termp *, size_t);
/*
* We define, for the time being, three fonts: bold, oblique/italic, and
* normal (roman). The following table hard-codes the font metrics for
--- 109,119 ----
static void ps_printf(struct termp *, const char *, ...)
__attribute__((__format__ (__printf__, 2, 3)));
static void ps_putchar(struct termp *, char);
static void ps_setfont(struct termp *, enum termfont);
static void ps_setwidth(struct termp *, int, int);
! static struct termp *pspdf_alloc(const struct manoutput *, enum termtype);
static void pdf_obj(struct termp *, size_t);
/*
* We define, for the time being, three fonts: bold, oblique/italic, and
* normal (roman). The following table hard-codes the font metrics for
*** 509,548 ****
};
void *
pdf_alloc(const struct manoutput *outopts)
{
! struct termp *p;
!
! if (NULL != (p = pspdf_alloc(outopts)))
! p->type = TERMTYPE_PDF;
!
! return p;
}
void *
ps_alloc(const struct manoutput *outopts)
{
! struct termp *p;
!
! if (NULL != (p = pspdf_alloc(outopts)))
! p->type = TERMTYPE_PS;
!
! return p;
}
static struct termp *
! pspdf_alloc(const struct manoutput *outopts)
{
struct termp *p;
unsigned int pagex, pagey;
size_t marginx, marginy, lineheight;
const char *pp;
p = mandoc_calloc(1, sizeof(*p));
p->tcol = p->tcols = mandoc_calloc(1, sizeof(*p->tcol));
p->maxtcol = 1;
p->enc = TERMENC_ASCII;
p->fontq = mandoc_reallocarray(NULL,
(p->fontsz = 8), sizeof(*p->fontq));
p->fontq[0] = p->fontl = TERMFONT_NONE;
--- 512,542 ----
};
void *
pdf_alloc(const struct manoutput *outopts)
{
! return pspdf_alloc(outopts, TERMTYPE_PDF);
}
void *
ps_alloc(const struct manoutput *outopts)
{
! return pspdf_alloc(outopts, TERMTYPE_PS);
}
static struct termp *
! pspdf_alloc(const struct manoutput *outopts, enum termtype type)
{
struct termp *p;
unsigned int pagex, pagey;
size_t marginx, marginy, lineheight;
const char *pp;
p = mandoc_calloc(1, sizeof(*p));
p->tcol = p->tcols = mandoc_calloc(1, sizeof(*p->tcol));
p->maxtcol = 1;
+ p->type = type;
p->enc = TERMENC_ASCII;
p->fontq = mandoc_reallocarray(NULL,
(p->fontsz = 8), sizeof(*p->fontq));
p->fontq[0] = p->fontl = TERMFONT_NONE;
*** 557,566 ****
--- 551,561 ----
p->setwidth = ps_setwidth;
p->width = ps_width;
/* Default to US letter (millimetres). */
+ p->ps->medianame = "Letter";
pagex = 216;
pagey = 279;
/*
* The ISO-269 paper sizes can be calculated automatically, but
*** 568,591 ****
* do that. So just do it the easy way for now. Since this
* only happens once, I'm not terribly concerned.
*/
pp = outopts->paper;
! if (pp && strcasecmp(pp, "letter")) {
! if (0 == strcasecmp(pp, "a3")) {
pagex = 297;
pagey = 420;
! } else if (0 == strcasecmp(pp, "a4")) {
pagex = 210;
pagey = 297;
! } else if (0 == strcasecmp(pp, "a5")) {
pagex = 148;
pagey = 210;
! } else if (0 == strcasecmp(pp, "legal")) {
pagex = 216;
pagey = 356;
! } else if (2 != sscanf(pp, "%ux%u", &pagex, &pagey))
warnx("%s: Unknown paper", pp);
}
/*
* This MUST be defined before any PNT2AFM or AFM2PNT
--- 563,592 ----
* do that. So just do it the easy way for now. Since this
* only happens once, I'm not terribly concerned.
*/
pp = outopts->paper;
! if (pp != NULL && strcasecmp(pp, "letter") != 0) {
! if (strcasecmp(pp, "a3") == 0) {
! p->ps->medianame = "A3";
pagex = 297;
pagey = 420;
! } else if (strcasecmp(pp, "a4") == 0) {
! p->ps->medianame = "A4";
pagex = 210;
pagey = 297;
! } else if (strcasecmp(pp, "a5") == 0) {
! p->ps->medianame = "A5";
pagex = 148;
pagey = 210;
! } else if (strcasecmp(pp, "legal") == 0) {
! p->ps->medianame = "Legal";
pagex = 216;
pagey = 356;
! } else if (sscanf(pp, "%ux%u", &pagex, &pagey) == 2)
! p->ps->medianame = "CustomSize";
! else
warnx("%s: Unknown paper", pp);
}
/*
* This MUST be defined before any PNT2AFM or AFM2PNT
*** 594,605 ****
p->ps->scale = 11;
/* Remember millimetres -> AFM units. */
! pagex = PNT2AFM(p, ((double)pagex * 2.834));
! pagey = PNT2AFM(p, ((double)pagey * 2.834));
/* Margins are 1/9 the page x and y. */
marginx = (size_t)((double)pagex / 9.0);
marginy = (size_t)((double)pagey / 9.0);
--- 595,606 ----
p->ps->scale = 11;
/* Remember millimetres -> AFM units. */
! pagex = PNT2AFM(p, ((double)pagex * 72.0 / 25.4));
! pagey = PNT2AFM(p, ((double)pagey * 72.0 / 25.4));
/* Margins are 1/9 the page x and y. */
marginx = (size_t)((double)pagex / 9.0);
marginy = (size_t)((double)pagey / 9.0);
*** 731,751 ****
int i;
size_t len, base;
/*
* Close out a page that we've already flushed to output. In
! * PostScript, we simply note that the page must be showed. In
* PDF, we must now create the Length, Resource, and Page node
* for the page contents.
*/
assert(p->ps->psmarg && p->ps->psmarg[0]);
ps_printf(p, "%s", p->ps->psmarg);
if (TERMTYPE_PS != p->type) {
- ps_printf(p, "ET\n");
-
len = p->ps->pdfbytes - p->ps->pdflastpg;
base = p->ps->pages * 4 + p->ps->pdfbody;
ps_printf(p, "endstream\nendobj\n");
--- 732,750 ----
int i;
size_t len, base;
/*
* Close out a page that we've already flushed to output. In
! * PostScript, we simply note that the page must be shown. In
* PDF, we must now create the Length, Resource, and Page node
* for the page contents.
*/
assert(p->ps->psmarg && p->ps->psmarg[0]);
ps_printf(p, "%s", p->ps->psmarg);
if (TERMTYPE_PS != p->type) {
len = p->ps->pdfbytes - p->ps->pdflastpg;
base = p->ps->pages * 4 + p->ps->pdfbody;
ps_printf(p, "endstream\nendobj\n");
*** 757,767 ****
pdf_obj(p, base + 2);
ps_printf(p, "<<\n/ProcSet [/PDF /Text]\n");
ps_printf(p, "/Font <<\n");
for (i = 0; i < (int)TERMFONT__MAX; i++)
ps_printf(p, "/F%d %d 0 R\n", i, 3 + i);
! ps_printf(p, ">>\n>>\n");
/* Page node. */
pdf_obj(p, base + 3);
ps_printf(p, "<<\n");
ps_printf(p, "/Type /Page\n");
--- 756,766 ----
pdf_obj(p, base + 2);
ps_printf(p, "<<\n/ProcSet [/PDF /Text]\n");
ps_printf(p, "/Font <<\n");
for (i = 0; i < (int)TERMFONT__MAX; i++)
ps_printf(p, "/F%d %d 0 R\n", i, 3 + i);
! ps_printf(p, ">>\n>>\nendobj\n");
/* Page node. */
pdf_obj(p, base + 3);
ps_printf(p, "<<\n");
ps_printf(p, "/Type /Page\n");
*** 822,832 ****
ps_printf(p, "]\n>>\nendobj\n");
pdf_obj(p, base);
ps_printf(p, "<<\n");
ps_printf(p, "/Type /Catalog\n");
ps_printf(p, "/Pages 2 0 R\n");
! ps_printf(p, ">>\n");
xref = p->ps->pdfbytes;
ps_printf(p, "xref\n");
ps_printf(p, "0 %zu\n", base + 1);
ps_printf(p, "0000000000 65535 f \n");
--- 821,831 ----
ps_printf(p, "]\n>>\nendobj\n");
pdf_obj(p, base);
ps_printf(p, "<<\n");
ps_printf(p, "/Type /Catalog\n");
ps_printf(p, "/Pages 2 0 R\n");
! ps_printf(p, ">>\nendobj\n");
xref = p->ps->pdfbytes;
ps_printf(p, "xref\n");
ps_printf(p, "0 %zu\n", base + 1);
ps_printf(p, "0000000000 65535 f \n");
*** 846,855 ****
--- 845,855 ----
}
static void
ps_begin(struct termp *p)
{
+ size_t width, height;
int i;
/*
* Print margins into margin buffer. Nothing gets output to the
* screen yet, so we don't need to initialise the primary state.
*** 863,872 ****
--- 863,873 ----
/*p->ps->pdfbytes = 0;*/
p->ps->psmargcur = 0;
p->ps->flags = PS_MARGINS;
p->ps->pscol = p->ps->left;
p->ps->psrow = p->ps->header;
+ p->ps->lastrow = 0; /* impossible row */
ps_setfont(p, TERMFONT_NONE);
(*p->headf)(p, p->argf);
(*p->endline)(p);
*** 887,911 ****
* Print header and initialise page state. Following this,
* stuff gets printed to the screen, so make sure we're sane.
*/
if (TERMTYPE_PS == p->type) {
ps_printf(p, "%%!PS-Adobe-3.0\n");
ps_printf(p, "%%%%DocumentData: Clean7Bit\n");
ps_printf(p, "%%%%Orientation: Portrait\n");
ps_printf(p, "%%%%Pages: (atend)\n");
ps_printf(p, "%%%%PageOrder: Ascend\n");
! ps_printf(p, "%%%%DocumentMedia: "
! "Default %zu %zu 0 () ()\n",
! (size_t)AFM2PNT(p, p->ps->width),
! (size_t)AFM2PNT(p, p->ps->height));
ps_printf(p, "%%%%DocumentNeededResources: font");
for (i = 0; i < (int)TERMFONT__MAX; i++)
ps_printf(p, " %s", fonts[i].name);
! ps_printf(p, "\n%%%%EndComments\n");
} else {
ps_printf(p, "%%PDF-1.1\n");
pdf_obj(p, 1);
ps_printf(p, "<<\n");
ps_printf(p, ">>\n");
--- 888,935 ----
* Print header and initialise page state. Following this,
* stuff gets printed to the screen, so make sure we're sane.
*/
if (TERMTYPE_PS == p->type) {
+ width = AFM2PNT(p, p->ps->width);
+ height = AFM2PNT(p, p->ps->height);
+
ps_printf(p, "%%!PS-Adobe-3.0\n");
ps_printf(p, "%%%%DocumentData: Clean7Bit\n");
ps_printf(p, "%%%%Orientation: Portrait\n");
ps_printf(p, "%%%%Pages: (atend)\n");
ps_printf(p, "%%%%PageOrder: Ascend\n");
! ps_printf(p, "%%%%DocumentMedia: man-%s %zu %zu 0 () ()\n",
! p->ps->medianame, width, height);
ps_printf(p, "%%%%DocumentNeededResources: font");
for (i = 0; i < (int)TERMFONT__MAX; i++)
ps_printf(p, " %s", fonts[i].name);
! ps_printf(p, "\n%%%%DocumentSuppliedResources: "
! "procset MandocProcs 1.0 0\n");
! ps_printf(p, "%%%%EndComments\n");
! ps_printf(p, "%%%%BeginProlog\n");
! ps_printf(p, "%%%%BeginResource: procset MandocProcs "
! "10170 10170\n");
! /* The font size is effectively hard-coded for now. */
! ps_printf(p, "/fs %zu def\n", p->ps->scale);
! for (i = 0; i < (int)TERMFONT__MAX; i++)
! ps_printf(p, "/f%d { /%s fs selectfont } def\n",
! i, fonts[i].name);
! ps_printf(p, "/s { 3 1 roll moveto show } bind def\n");
! ps_printf(p, "/c { exch currentpoint exch pop "
! "moveto show } bind def\n");
! ps_printf(p, "%%%%EndResource\n");
! ps_printf(p, "%%%%EndProlog\n");
! ps_printf(p, "%%%%BeginSetup\n");
! ps_printf(p, "%%%%BeginFeature: *PageSize %s\n",
! p->ps->medianame);
! ps_printf(p, "<</PageSize [%zu %zu]>>setpagedevice\n",
! width, height);
! ps_printf(p, "%%%%EndFeature\n");
! ps_printf(p, "%%%%EndSetup\n");
} else {
ps_printf(p, "%%PDF-1.1\n");
pdf_obj(p, 1);
ps_printf(p, "<<\n");
ps_printf(p, ">>\n");
*** 916,926 ****
ps_printf(p, "<<\n");
ps_printf(p, "/Type /Font\n");
ps_printf(p, "/Subtype /Type1\n");
ps_printf(p, "/Name /F%d\n", i);
ps_printf(p, "/BaseFont /%s\n", fonts[i].name);
! ps_printf(p, ">>\n");
}
}
p->ps->pdfbody = (size_t)TERMFONT__MAX + 3;
p->ps->pscol = p->ps->left;
--- 940,950 ----
ps_printf(p, "<<\n");
ps_printf(p, "/Type /Font\n");
ps_printf(p, "/Subtype /Type1\n");
ps_printf(p, "/Name /F%d\n", i);
ps_printf(p, "/BaseFont /%s\n", fonts[i].name);
! ps_printf(p, ">>\nendobj\n");
}
}
p->ps->pdfbody = (size_t)TERMFONT__MAX + 3;
p->ps->pscol = p->ps->left;
*** 941,953 ****
if (PS_NEWPAGE & p->ps->flags) {
if (TERMTYPE_PS == p->type) {
ps_printf(p, "%%%%Page: %zu %zu\n",
p->ps->pages + 1, p->ps->pages + 1);
! ps_printf(p, "/%s %zu selectfont\n",
! fonts[(int)p->ps->lastf].name,
! p->ps->scale);
} else {
pdf_obj(p, p->ps->pdfbody +
p->ps->pages * 4);
ps_printf(p, "<<\n");
ps_printf(p, "/Length %zu 0 R\n",
--- 965,975 ----
if (PS_NEWPAGE & p->ps->flags) {
if (TERMTYPE_PS == p->type) {
ps_printf(p, "%%%%Page: %zu %zu\n",
p->ps->pages + 1, p->ps->pages + 1);
! ps_printf(p, "f%d\n", (int)p->ps->lastf);
} else {
pdf_obj(p, p->ps->pdfbody +
p->ps->pages * 4);
ps_printf(p, "<<\n");
ps_printf(p, "/Length %zu 0 R\n",
*** 968,981 ****
ps_printf(p, "BT\n/F%d %zu Tf\n",
(int)p->ps->lastf, p->ps->scale);
ps_printf(p, "%.3f %.3f Td\n(",
AFM2PNT(p, p->ps->pscol),
AFM2PNT(p, p->ps->psrow));
! } else
! ps_printf(p, "%.3f %.3f moveto\n(",
! AFM2PNT(p, p->ps->pscol),
AFM2PNT(p, p->ps->psrow));
p->ps->flags |= PS_INLINE;
}
assert( ! (PS_NEWPAGE & p->ps->flags));
--- 990,1006 ----
ps_printf(p, "BT\n/F%d %zu Tf\n",
(int)p->ps->lastf, p->ps->scale);
ps_printf(p, "%.3f %.3f Td\n(",
AFM2PNT(p, p->ps->pscol),
AFM2PNT(p, p->ps->psrow));
! } else {
! ps_printf(p, "%.3f", AFM2PNT(p, p->ps->pscol));
! if (p->ps->psrow != p->ps->lastrow)
! ps_printf(p, " %.3f",
AFM2PNT(p, p->ps->psrow));
+ ps_printf(p, "(");
+ }
p->ps->flags |= PS_INLINE;
}
assert( ! (PS_NEWPAGE & p->ps->flags));
*** 1019,1032 ****
*/
if ( ! (PS_INLINE & p->ps->flags))
return;
! if (TERMTYPE_PS != p->type) {
ps_printf(p, ") Tj\nET\n");
! } else
! ps_printf(p, ") show\n");
p->ps->flags &= ~PS_INLINE;
}
/* If we have a `last' char that wasn't printed yet, print it now. */
--- 1044,1061 ----
*/
if ( ! (PS_INLINE & p->ps->flags))
return;
! if (TERMTYPE_PS != p->type)
ps_printf(p, ") Tj\nET\n");
! else if (p->ps->psrow == p->ps->lastrow)
! ps_printf(p, ")c\n");
! else {
! ps_printf(p, ")s\n");
! p->ps->lastrow = p->ps->psrow;
! }
p->ps->flags &= ~PS_INLINE;
}
/* If we have a `last' char that wasn't printed yet, print it now. */
*** 1241,1252 ****
if (PS_NEWPAGE & p->ps->flags)
return;
if (TERMTYPE_PS == p->type)
! ps_printf(p, "/%s %zu selectfont\n",
! fonts[(int)f].name, p->ps->scale);
else
ps_printf(p, "/F%d %zu Tf\n",
(int)f, p->ps->scale);
}
--- 1270,1280 ----
if (PS_NEWPAGE & p->ps->flags)
return;
if (TERMTYPE_PS == p->type)
! ps_printf(p, "f%d\n", (int)f);
else
ps_printf(p, "/F%d %zu Tf\n",
(int)f, p->ps->scale);
}