shithub: neatroff

Download patch

ref: e59abf73546274ddadf77fed7eb9f9d452cdbb6a
parent: 284841844342e3be754905fa9eb6e05fd6d9f74c
author: Ali Gholami Rudi <ali@rudi.ir>
date: Sun Nov 24 13:50:20 EST 2013

tr: add .fmap to map character names to glyphs

--- a/font.c
+++ b/font.c
@@ -3,30 +3,40 @@
 #include <string.h>
 #include "roff.h"
 
-struct glyph *font_find(struct font *fn, char *name)
+/* look up a character in chead[]/cnext[] table */
+static int font_cidx(struct font *fn, char *name)
 {
 	int i = fn->chead[(unsigned char) name[0]];
-	while (i >= 0) {
-		if (!strcmp(name, fn->c[i]))
-			return fn->g[i];
+	while (i >= 0 && strcmp(name, fn->c[i]))
 		i = fn->cnext[i];
-	}
-	return NULL;
+	return i;
 }
 
-struct glyph *font_glyph(struct font *fn, char *id)
+/* look up a character in ghead[]/gnext[] table */
+static int font_gidx(struct font *fn, char *id)
 {
 	int i = fn->ghead[(unsigned char) id[0]];
-	while (i >= 0) {
-		if (!strcmp(fn->glyphs[i].id, id))
-			return &fn->glyphs[i];
+	while (i >= 0 && strcmp(fn->glyphs[i].id, id))
 		i = fn->gnext[i];
-	}
-	return NULL;
+	return i;
 }
 
-struct glyph *font_glyphput(struct font *fn, char *id, char *name, int wid, int type)
+struct glyph *font_find(struct font *fn, char *name)
 {
+	int i = font_cidx(fn, name);
+	if (i < 0)
+		return NULL;
+	return fn->g_map[i] ? fn->g_map[i] : fn->g[i];
+}
+
+struct glyph *font_glyph(struct font *fn, char *id)
+{
+	int i = font_gidx(fn, id);
+	return i >= 0 ? &fn->glyphs[i] : NULL;
+}
+
+static struct glyph *font_glyphput(struct font *fn, char *id, char *name, int wid, int type)
+{
 	int i = fn->nglyphs++;
 	struct glyph *g;
 	g = &fn->glyphs[i];
@@ -40,6 +50,31 @@
 	return g;
 }
 
+/* map character name to the given glyph */
+int font_map(struct font *fn, char *name, struct glyph *g)
+{
+	int i = font_cidx(fn, name);
+	if (g && g->font != fn)
+		return 1;
+	if (i < 0) {
+		if (fn->n >= NGLYPHS)
+			return 1;
+		i = fn->n++;
+		strcpy(fn->c[i], name);
+		fn->cnext[i] = fn->chead[(unsigned char) name[0]];
+		fn->chead[(unsigned char) name[0]] = i;
+	}
+	fn->g_map[i] = g;
+	return 0;
+}
+
+/* return nonzero if character name has been mapped with font_map() */
+int font_mapped(struct font *fn, char *name)
+{
+	int i = font_cidx(fn, name);
+	return i >= 0 && fn->g_map[i];
+}
+
 /* glyph index in fn->glyphs[] */
 static int font_idx(struct font *fn, struct glyph *g)
 {
@@ -115,7 +150,9 @@
 		return 1;
 	if (!strcmp("---", name))
 		sprintf(name, "c%04d", fn->n);
-	if (strcmp("\"", tok)) {
+	if (!strcmp("\"", tok)) {
+		glyph = fn->g[fn->n - 1];
+	} else {
 		wid = atoi(tok);
 		if (fscanf(fin, "%d %s", &type, id) != 2)
 			return 1;
@@ -122,8 +159,6 @@
 		glyph = font_glyph(fn, id);
 		if (!glyph)
 			glyph = font_glyphput(fn, id, name, wid, type);
-	} else {
-		glyph = fn->g[fn->n - 1];
 	}
 	strcpy(fn->c[fn->n], name);
 	fn->g[fn->n] = glyph;
--- a/out.c
+++ b/out.c
@@ -126,6 +126,8 @@
 	struct glyph *g = dev_glyph(c, o_f);
 	int cwid = charwid(o_f, o_s, g ? g->wid : SC_DW);
 	int bwid = charwid_base(o_f, o_s, g ? g->wid : SC_DW);
+	if (g && font_mapped(g->font, c))
+		c = g->name;
 	if (dev_getcs(o_f))
 		outnn("h%d", (cwid - bwid) / 2);
 	outg(c, g ? dev_fontpos(g->font) : o_f);
--- a/roff.h
+++ b/roff.h
@@ -110,6 +110,7 @@
 	/* charset section characters */
 	char c[NGLYPHS][GNLEN];		/* character names in charset */
 	struct glyph *g[NGLYPHS];	/* character glyphs in charset */
+	struct glyph *g_map[NGLYPHS];	/* character remapped via font_map() */
 	int n;				/* number of characters in charset */
 	/* glyph table based on the first character of their id fields in glyphs[] */
 	int ghead[256];			/* glyph list heads */
@@ -148,6 +149,8 @@
 int font_lig(struct font *fn, char **c, int n);
 int font_kern(struct font *fn, char *c1, char *c2);
 int font_islig(struct font *fn, char *s);
+int font_map(struct font *fn, char *name, struct glyph *gl);
+int font_mapped(struct font *fn, char *name);
 
 /* glyph handling functions */
 struct glyph *dev_glyph(char *c, int fn);
--- a/tr.c
+++ b/tr.c
@@ -637,6 +637,16 @@
 	cdef_add(args[1], args[2], args[3]);
 }
 
+static void tr_fmap(char **args)
+{
+	struct font *fn;
+	if (!args[2])
+		return;
+	fn = dev_font(dev_pos(args[1]));
+	if (fn)
+		font_map(fn, args[2], args[3] ? font_glyph(fn, args[3]) : NULL);
+}
+
 static char *arg_regname(char *s, int len)
 {
 	char *e = n_cp ? s + 2 : s + len;
@@ -838,6 +848,7 @@
 	{"ex", tr_ex},
 	{"fc", tr_fc},
 	{"fi", tr_fi},
+	{"fmap", tr_fmap},
 	{"fp", tr_fp},
 	{"fspecial", tr_fspecial},
 	{"ft", tr_ft},