shithub: neatpost

Download patch

ref: 825749e792f7641f276439a9da067475ce5f8113
parent: 4d6875d50c8bfce3ea6083d19f142dad1681f2d0
author: Ali Gholami Rudi <ali@rudi.ir>
date: Sat Jan 11 14:19:36 EST 2020

post: mark and name device functions

Bookmarks: \X'mark description page offset level'
Labels: \X'name name page offset'

--- a/pdf.c
+++ b/pdf.c
@@ -734,6 +734,14 @@
 	obj_end();
 }
 
+void outname(char *name, int page, int off)
+{
+}
+
+void outmark(int n, char (*desc)[256], int *page, int *off, int *level)
+{
+}
+
 void outinfo(char *kwd, char *val)
 {
 	if (!strcmp("Author", kwd))
--- a/post.c
+++ b/post.c
@@ -27,6 +27,14 @@
 static int ps_linewidth = 40;	/* drawing line thickness in thousandths of an em */
 static int o_pages;		/* output pages */
 
+/* bookmark management */
+static char (*mark_desc)[256];	/* bookmark description */
+static int *mark_page;		/* bookmark page */
+static int *mark_offset;	/* bookmark offset */
+static int *mark_level;		/* bookmark level */
+static int mark_n;		/* number of bookmarks */
+static int mark_sz;		/* allocated size of bookmark arrays */
+
 static int next(void)
 {
 	return getc(stdin);
@@ -294,6 +302,14 @@
 		if (path[0] && !strcmp("pdf", cmd))
 			outpdf(path, hwid, vwid);
 	}
+	if (!strcmp("name", cmd)) {
+		char name[1 << 10];
+		int page = 0, offset = 0;
+		int nspec;
+		nspec = sscanf(arg, "%s %d %d", name, &page, &offset);
+		if (name[0] && nspec > 1)
+			outname(name, page == o_pages ? 0 : page, offset);
+	}
 	if (!strcmp("link", cmd)) {
 		char link[1 << 12];
 		int hwid, vwid, nspec;
@@ -303,6 +319,21 @@
 		if (link[0] && nspec == 2)
 			outlink(link, hwid, vwid);
 	}
+	if (!strcmp("mark", cmd)) {
+		char *spec = arg;
+		if (mark_n == mark_sz) {
+			mark_sz = mark_sz == 0 ? 128 : mark_sz * 2;
+			mark_desc = mextend(mark_desc, mark_n, mark_sz, sizeof(mark_desc[0]));
+			mark_page = mextend(mark_page, mark_n, mark_sz, sizeof(mark_page[0]));
+			mark_offset = mextend(mark_offset, mark_n, mark_sz, sizeof(mark_offset[0]));
+			mark_level = mextend(mark_level, mark_n, mark_sz, sizeof(mark_level[0]));
+		}
+		spec = strcut(mark_desc[mark_n], spec);
+		sscanf(spec, "%d %d %d", &mark_page[mark_n],
+				&mark_offset[mark_n], &mark_level[mark_n]);
+		if (mark_desc[mark_n][0])
+			mark_n++;
+	}
 	if (!strcmp("info", cmd)) {
 		char *spec = arg;
 		char kwd[128];
@@ -439,6 +470,7 @@
 			postcmd(c);
 	if (o_pages)
 		docpageend(o_pages);
+	outmark(mark_n, mark_desc, mark_page, mark_offset, mark_level);
 }
 
 static struct paper {
@@ -530,5 +562,9 @@
 	post();
 	doctrailer(o_pages);
 	dev_close();
+	free(mark_desc);
+	free(mark_page);
+	free(mark_offset);
+	free(mark_level);
 	return 0;
 }
--- a/post.h
+++ b/post.h
@@ -60,6 +60,8 @@
 void outeps(char *eps, int hwid, int vwid);
 void outpdf(char *pdf, int hwid, int vwid);
 void outlink(char *dst, int hwid, int vwid);
+void outname(char *name, int page, int off);
+void outmark(int n, char (*desc)[256], int *page, int *off, int *level);
 void outinfo(char *kwd, char *val);
 void outpage(void);
 void outmnt(int f);
--- a/ps.c
+++ b/ps.c
@@ -7,6 +7,7 @@
 
 static char ps_title[256];	/* document title */
 static char ps_author[256];	/* document author */
+static int ps_height;		/* document height in basic units */
 static int o_f, o_s, o_m;	/* font and size */
 static int o_h, o_v;		/* current user position */
 static int p_f, p_s, p_m;	/* output postscript font */
@@ -322,6 +323,39 @@
 	}
 }
 
+void outname(char *name, int page, int off)
+{
+	o_flush();
+	outf("[ /Dest /%s", name);
+	if (page > 0)
+		outf(" /Page %d", page);
+	if (off > 0)
+		outf(" /View [/XYZ null %d null]",
+			(ps_height - off) * 72 / dev_res);
+	outf(" /DEST pdfmark\n");
+}
+
+void outmark(int n, char (*desc)[256], int *page, int *off, int *level)
+{
+	int i, j;
+	o_flush();
+	for (i = 0; i < n; i++) {
+		int cnt = 0;
+		for (j = i + 1; j < n && level[j] > level[i]; j++)
+			if (level[j] == level[i] + 1)
+				cnt++;
+		outf("[ /Title (%s)", desc[i]);
+		if (page[i] > 0)
+			outf(" /Page %d", page[i]);
+		if (cnt > 0)
+			outf(" /Count %d", cnt);
+		if (off[i] > 0)
+			outf(" /View [/XYZ null %d null]",
+				(ps_height - off[i]) * 72 / dev_res);
+		outf(" /OUT pdfmark\n");
+	}
+}
+
 void outinfo(char *kwd, char *val)
 {
 	if (!strcmp("Author", kwd))
@@ -352,7 +386,7 @@
 		out(" /Title (%s)", ps_title);
 	if (ps_author[0])
 		out(" /Author (%s)", ps_author);
-	out("/Creator (Neatroff) /DOCINFO pdfmark\n");
+	out(" /Creator (Neatroff) /DOCINFO pdfmark\n");
 	out("%%%%Trailer\n");
 	out("done\n");
 	out("%%%%DocumentFonts: %s\n", o_fonts);
@@ -463,6 +497,7 @@
 /* pagewidth and pageheight are in tenths of a millimetre */
 void docheader(char *title, int pagewidth, int pageheight, int linewidth)
 {
+	ps_height = pageheight * dev_res / 254;
 	out("%%!PS-Adobe-2.0\n");
 	out("%%%%Version: 1.0\n");
 	if (title)