ref: 07e35081b3f754c61e9a081f320db0e942f72e4a
parent: 03ef6990eb2f07e46b801914363ad43412d4da3d
author: Ali Gholami Rudi <ali@rudi.ir>
date: Sat Jun 22 15:25:59 EDT 2013
wb: ligature support
--- a/dev.c
+++ b/dev.c
@@ -144,11 +144,6 @@
return font_glyph(fn_font[fn], id);
}
-struct glyph *dev_ligature(char **s, int n)
-{
- return NULL;
-}
-
int dev_kernpair(char *c1, char *c2)
{
return 0;
@@ -182,4 +177,15 @@
{
/* the original troff rounds the widths up */
return (wid * sz + dev_uwid / 2) / dev_uwid;
+}
+
+/* return 1 if lig is a ligature in the font mounted at f */
+int dev_lig(int f, char *lig)
+{
+ struct font *fn = fn_font[f];
+ int i;
+ for (i = 0; i < fn->nlig; i++)
+ if (!strcmp(lig, fn->lig[i]))
+ return 1;
+ return 0;
}
--- a/font.c
+++ b/font.c
@@ -93,9 +93,12 @@
continue;
}
if (!strcmp("ligatures", tok)) {
- while (fscanf(fin, "%s", tok) == 1)
+ while (fscanf(fin, "%s", tok) == 1) {
if (!strcmp("0", tok))
break;
+ if (fn->nlig < NLIGS)
+ strcpy(fn->lig[fn->nlig++], tok);
+ }
skipline(fin);
continue;
}
--- a/ren.c
+++ b/ren.c
@@ -670,7 +670,8 @@
}
if (c[0] == c_ni)
nextchar(c + 1, next);
- wb_put(wb, c);
+ if (!n_lg || wb_lig(wb, c))
+ wb_put(wb, c);
}
/* read the argument of \w and push its width */
--- a/roff.c
+++ b/roff.c
@@ -14,6 +14,7 @@
{
n_o = SC_IN;
n_p = SC_IN * 11;
+ n_lg = 1;
}
static void compile(void)
--- a/roff.h
+++ b/roff.h
@@ -9,6 +9,7 @@
#define PATHLEN 1024 /* path length */
#define NFILES 16 /* number of input files */
#define NFONTS 32 /* number of fonts */
+#define NLIGS 32 /* number of font ligatures */
#define FNLEN 32 /* font name length */
#define NGLYPHS 512 /* glyphs in fonts */
#define GNLEN 32 /* glyph name length */
@@ -92,6 +93,8 @@
char c[NGLYPHS][GNLEN]; /* character names in charset */
struct glyph *g[NGLYPHS]; /* character glyphs in charset */
int n; /* number of characters in charset */
+ char lig[NLIGS][GNLEN * 4]; /* font ligatures */
+ int nlig; /* number of font ligatures */
};
/* output device functions */
@@ -100,6 +103,7 @@
int dev_mnt(int pos, char *id, char *name);
int dev_font(char *id);
int charwid(int wid, int sz);
+int dev_lig(int f, char *c);
/* font-related functions */
struct font *font_open(char *path);
@@ -139,6 +143,7 @@
char *s;
int sz;
int n;
+ int prev_n; /* n before the last sbuf_append() */
};
void sbuf_init(struct sbuf *sbuf);
@@ -149,6 +154,8 @@
void sbuf_printf(struct sbuf *sbuf, char *s, ...);
void sbuf_putnl(struct sbuf *sbuf);
int sbuf_empty(struct sbuf *sbuf);
+char *sbuf_last(struct sbuf *sbuf);
+void sbuf_pop(struct sbuf *sbuf);
/* word buffer */
struct wb {
@@ -159,6 +166,7 @@
int els_neg, els_pos; /* extra line spacing */
int h, v; /* buffer vertical and horizontal positions */
int ct, sb, st; /* \w registers */
+ int prev_h; /* previous value of h */
};
void wb_init(struct wb *wb);
@@ -182,6 +190,7 @@
int wb_wid(struct wb *wb);
int wb_empty(struct wb *wb);
void wb_wconf(struct wb *wb, int *ct, int *st, int *sb);
+int wb_lig(struct wb *wb, char *c);
/* hyphenation flags */
#define HY_MASK 0x0f /* enable hyphenation */
@@ -302,6 +311,7 @@
#define n_lb (*nreg(REG(0, 'b'))) /* input line beg */
#define n_ce (*nreg(REG(0, 'c'))) /* .ce remaining */
#define n_f0 (*nreg(REG(0, 'f'))) /* last .f */
+#define n_lg (*nreg(REG(0, 'g'))) /* .lg mode */
#define n_hy (*nreg(REG(0, 'h'))) /* .hy mode */
#define n_i0 (*nreg(REG(0, 'i'))) /* last .i */
#define n_l0 (*nreg(REG(0, 'l'))) /* last .l */
--- a/sbuf.c
+++ b/sbuf.c
@@ -35,6 +35,7 @@
if (sbuf->n + len + 1 >= sbuf->sz)
sbuf_extend(sbuf, sbuf->n + len + 1);
memcpy(sbuf->s + sbuf->n, s, len);
+ sbuf->prev_n = sbuf->n;
sbuf->n += len;
}
@@ -63,6 +64,17 @@
{
sbuf->s[sbuf->n] = '\0';
return sbuf->s;
+}
+
+char *sbuf_last(struct sbuf *sbuf)
+{
+ return sbuf->prev_n < sbuf->n ? sbuf_buf(sbuf) + sbuf->prev_n : NULL;
+}
+
+void sbuf_pop(struct sbuf *sbuf)
+{
+ if (sbuf->prev_n < sbuf->n)
+ sbuf->n = sbuf->prev_n;
}
void sbuf_done(struct sbuf *sbuf)
--- a/tr.c
+++ b/tr.c
@@ -411,6 +411,12 @@
n_hy = args[1] ? atoi(args[1]) : 1;
}
+static void tr_lg(char **args)
+{
+ if (args[1])
+ n_lg = atoi(args[1]);
+}
+
static char *arg_regname(char *s, int len)
{
char *e = s + 2;
@@ -612,6 +618,7 @@
{"if", tr_if, mkargs_null},
{"ig", tr_ig},
{"in", tr_in},
+ {"lg", tr_lg},
{"ll", tr_ll},
{"ls", tr_ls},
{"lt", tr_lt},
--- a/wb.c
+++ b/wb.c
@@ -103,6 +103,25 @@
}
}
+/* return zero if c formed a ligature with its previous character */
+int wb_lig(struct wb *wb, char *c)
+{
+ char *p = sbuf_last(&wb->sbuf);
+ char lig[GNLEN];
+ if (!p || strlen(p) + strlen(c) + 4 > GNLEN)
+ return 1;
+ if (p[0] == c_ec && p[1] == '(')
+ p += 2;
+ sprintf(lig, "%s%s", p, c);
+ if (dev_lig(R_F(wb), lig)) {
+ wb->h = wb->prev_h;
+ sbuf_pop(&wb->sbuf);
+ wb_put(wb, lig);
+ return 0;
+ }
+ return 1;
+}
+
int wb_part(struct wb *wb)
{
return wb->part;