ref: 3c5e855b56948641dc46927cd50870c80412593a
parent: f148a9d90d6581768c5197dc4e777edc0f6baf0d
author: Ali Gholami Rudi <ali@rudi.ir>
date: Sat May 11 14:42:32 EDT 2013
wb: hyphenation at dashes and hyphenation marks
--- a/adj.c
+++ b/adj.c
@@ -128,7 +128,7 @@
struct wb w1, w2;
wb_init(&w1);
wb_init(&w2);
- if (wb_hyph(&a->wbs[n], w, &w1, &w2)) {
+ if (wb_hyph(&a->wbs[n], w, &w1, &w2, n == 0 ? HY_ANY : 0)) {
wb_done(&w1);
wb_done(&w2);
return;
--- a/out.c
+++ b/out.c
@@ -199,7 +199,7 @@
c[1] = '\0';
}
if (!t) {
- if (c[0] == '\t' || c[0] == '')
+ if (c[0] == '\t' || c[0] == '' || !strcmp(c_hc, c))
continue;
g = dev_glyph(c, o_f);
if (utf8len(c[0]) == strlen(c))
--- a/reg.c
+++ b/reg.c
@@ -11,6 +11,7 @@
int eregs[NENVS]; /* environment-specific number registers */
int tabs[NTABS]; /* tab stops */
struct adj *adj; /* per environment line buffer */
+ char hc[GNLEN]; /* hyphenation character */
};
static int nregs[NREGS]; /* global number registers */
@@ -32,6 +33,7 @@
REG('.', 'v'),
REG(0, 'c'),
REG(0, 'f'),
+ REG(0, 'h'),
REG(0, 'i'),
REG(0, 'l'),
REG(0, 'L'),
@@ -168,6 +170,8 @@
n_f0 = n_f;
n_na = 0;
n_lt = SC_IN * 65 / 10;
+ n_hy = 1;
+ strcpy(env->hc, "\\%");
adj_ll(env->adj, n_l);
adj_in(env->adj, n_i);
for (i = 0; i < NTABS; i++)
@@ -209,6 +213,11 @@
struct adj *env_adj(void)
{
return env->adj;
+}
+
+char *env_hc(void)
+{
+ return env->hc;
}
/* saving and restoring registers around diverted lines */
--- a/tr.c
+++ b/tr.c
@@ -394,6 +394,21 @@
c_ec = -1;
}
+static void tr_hc(char **args)
+{
+ strcpy(c_hc, args[1] ? args[1] : "\\%");
+}
+
+static void tr_nh(char **args)
+{
+ n_hy = 0;
+}
+
+static void tr_hy(char **args)
+{
+ n_hy = args[1] ? atoi(args[1]) : 1;
+}
+
static char *arg_regname(char *s, int len)
{
char *e = s + 2;
@@ -586,6 +601,8 @@
{"fi", tr_fi},
{"fp", tr_fp},
{"ft", tr_ft},
+ {"hc", tr_hc},
+ {"hy", tr_hy},
{"ie", tr_if, mkargs_null},
{"if", tr_if, mkargs_null},
{"ig", tr_ig},
@@ -597,6 +614,7 @@
{"na", tr_na},
{"ne", tr_ne},
{"nf", tr_nf},
+ {"nh", tr_nh},
{"nr", tr_nr, mkargs_reg1},
{"ns", tr_ns},
{"nx", tr_nx},
--- a/wb.c
+++ b/wb.c
@@ -88,9 +88,11 @@
g = dev_glyph(c, R_F(wb));
wb_font(wb);
sbuf_append(&wb->sbuf, c);
- wb->h += charwid(g ? g->wid : SC_DW, R_S(wb));
- wb->ct |= g ? g->type : 0;
- wb_stsb(wb);
+ if (strcmp(c_hc, c)) {
+ wb->h += charwid(g ? g->wid : SC_DW, R_S(wb));
+ wb->ct |= g ? g->type : 0;
+ wb_stsb(wb);
+ }
}
int wb_part(struct wb *wb)
@@ -221,8 +223,87 @@
*sb = -wb->sb;
}
+/* skip troff requests; return 1 if read c_hc */
+static int skipreqs(char **s, struct wb *w1)
+{
+ char d[ILNLEN];
+ char *r = *s;
+ int c;
+ wb_reset(w1);
+ while ((c = out_readc(s, d)) > 0) {
+ wb_putc(w1, c, d);
+ r = *s;
+ }
+ if (c < 0 || !strcmp(c_hc, d))
+ return 1;
+ *s = r;
+ return 0;
+}
+
+static char *dashpos(char *s, int w, struct wb *w1, int any)
+{
+ char d[ILNLEN];
+ char *r = NULL;
+ int c;
+ skipreqs(&s, w1);
+ while ((c = out_readc(&s, d)) == 0) {
+ wb_putc(w1, c, d);
+ if (wb_wid(w1) > w && (!any || r))
+ break;
+ if (!strcmp("-", d) || (d[0] == c_ec && (!strcmp("(em", d + 1) ||
+ !strcmp("(hy", d + 1))))
+ r = s;
+ }
+ return r;
+}
+
+static char *hyphpos(char *s, int w, struct wb *w1, int any)
+{
+ char hy[GNLEN] = {c_ec, '(', 'h', 'y'};
+ char d[ILNLEN];
+ char *r = NULL;
+ struct glyph *g;
+ int c;
+ skipreqs(&s, w1);
+ while ((c = out_readc(&s, d)) == 0) {
+ wb_putc(w1, c, d);
+ g = dev_glyph(hy, R_F(w1));
+ if (!g || (wb_wid(w1) + charwid(g->wid, R_S(w1)) > w && (!any || r)))
+ break;
+ if (!strcmp(c_hc, d))
+ r = s;
+ }
+ return r;
+}
+
+static void dohyph(char *s, char *pos, int dash, struct wb *w1, struct wb *w2)
+{
+ char d[ILNLEN];
+ char hy[GNLEN] = {c_ec, '(', 'h', 'y'};
+ int c = -1;
+ wb_reset(w1);
+ wb_reset(w2);
+ while (s != pos && (c = out_readc(&s, d)) >= 0)
+ wb_putc(w1, c, d);
+ if (dash)
+ wb_putc(w1, 0, hy);
+ w2->r_s = w1->r_s;
+ w2->r_f = w1->r_f;
+ while ((c = out_readc(&s, d)) >= 0)
+ wb_putc(w2, c, d);
+}
+
/* hyphenate wb into w1 and w2; return zero on success */
-int wb_hyph(struct wb *wb, int w, struct wb *w1, struct wb *w2)
+int wb_hyph(struct wb *wb, int w, struct wb *w1, struct wb *w2, int flags)
{
- return 1;
+ char *s = sbuf_buf(&wb->sbuf);
+ char *dp, *hp, *p;
+ if (skipreqs(&s, w1))
+ return 1;
+ dp = dashpos(sbuf_buf(&wb->sbuf), w, w1, flags & HY_ANY);
+ hp = hyphpos(sbuf_buf(&wb->sbuf), w, w1, flags & HY_ANY);
+ p = flags & HY_ANY ? MIN(dp, hp) : MAX(dp, hp);
+ if (p)
+ dohyph(sbuf_buf(&wb->sbuf), p, p != dp, w1, w2);
+ return !p;
}
--- a/xroff.h
+++ b/xroff.h
@@ -37,6 +37,7 @@
extern int c_cc; /* basic control character (.) */
extern int c_c2; /* no-break control character (') */
#define c_ni 4 /* non-interpreted copy mode escape */
+#define c_hc env_hc()/* hyphenation character */
/* number registers */
int num_get(int id, int inc);
@@ -65,6 +66,7 @@
void env_init(void);
void env_free(void);
struct adj *env_adj(void);
+char *env_hc(void);
int tab_next(int pos);
/* device related variables */
@@ -176,11 +178,14 @@
void wb_drawxdot(struct wb *wb, int h, int v);
void wb_drawxend(struct wb *wb);
void wb_cat(struct wb *wb, struct wb *src);
-int wb_hyph(struct wb *wb, int w, struct wb *w1, struct wb *w2);
+int wb_hyph(struct wb *wb, int w, struct wb *w1, struct wb *w2, int flags);
int wb_wid(struct wb *wb);
int wb_empty(struct wb *wb);
void wb_wconf(struct wb *wb, int *ct, int *st, int *sb);
+/* hyphenation flags */
+#define HY_ANY 1 /* break at any possible position */
+
/* adjustment */
#define AD_L 0
#define AD_B 1
@@ -286,6 +291,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_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 */
#define n_L0 (*nreg(REG(0, 'L'))) /* last .L */