ref: d81da34389f192fee51865798fc86ff7e521617a
parent: 5d3333450b2456279531d67e9ca11ce08446da9a
author: Ali Gholami Rudi <[email protected]>
date: Wed May 15 17:45:14 EDT 2013
dir: support text direction with .>>, .<<, \> and \< The following troff requests specify text direction: * .<< and .>> change the direction of text (.<< for r2l and .>> to l2r); the default direction is l2r. * \< and \> change text direction temporarily. Text direction processing starts after the first invocation of .>> or .<<. As an example, one can write: .<< This is a paragraph in a right-to-left language with some embedded \>left-to-right words\< in it. .>> The current text direction and temporary direction are available through .td and .cd number registers respectively; 0 for l2r and 1 for r2l. To indent the right side of output lines, two new requests have been added: .in2 and .ti2 are equivalent to .in and .ti but for the right side. The .I number register stores the current right-side indentation.
--- a/Makefile
+++ b/Makefile
@@ -6,7 +6,7 @@
CFLAGS = -Wall -O2 "-DTROFFFDIR=\"$(FDIR)\"" "-DTROFFMDIR=\"$(MDIR)\""
LDFLAGS =
OBJS = roff.o dev.o font.o in.o cp.o tr.o ren.o out.o reg.o sbuf.o fmt.o \
- eval.o draw.o wb.o hyph.o map.o clr.o char.o dict.o iset.o
+ eval.o draw.o wb.o hyph.o map.o clr.o char.o dict.o iset.o dir.o
all: roff
%.o: %.c roff.h
--- a/char.c
+++ b/char.c
@@ -253,7 +253,7 @@
*r = '\0';
if (**s == ']')
(*s)++;
- } else if (strchr("CDfhmsvXx", r[1])) {
+ } else if (strchr("CDfhmsvXx<>", r[1])) {
int c = r[1];
r[0] = '\0';
if (strchr(ESC_P, c))
--- /dev/null
+++ b/dir.c
@@ -1,0 +1,161 @@
+/* output text direction */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "roff.h"
+
+int dir_do; /* enable text direction processing */
+
+static char *dbuf; /* text in n_td direction */
+static int dbuf_sz, dbuf_n; /* dbuf[] size and length */
+static char *rbuf; /* text in (1 - n_td) direction */
+static int rbuf_sz, rbuf_n; /* rbuf[] size and length */
+static int dir_cd; /* current direction */
+
+/* append s to the start (dir == 0) or end (dir == 1) of d */
+static void dir_copy(char **d, int *d_n, int *d_sz, char *s, int s_n, int dir)
+{
+ while (*d_n + s_n + 1 > *d_sz) {
+ int sz = *d_sz ? *d_sz * 2 : 512;
+ char *n = malloc(sz + 1);
+ if (*d_sz)
+ memcpy(dir ? n + *d_sz : n, *d, *d_sz);
+ free(*d);
+ *d_sz = sz;
+ *d = n;
+ }
+ if (dir > 0)
+ memcpy(*d + *d_sz - *d_n - s_n, s, s_n);
+ else
+ memcpy(*d + *d_n, s, s_n);
+ *d_n += s_n;
+}
+
+/* copy rbuf (the text in reverse direction) to dbuf */
+static void dir_flush(void)
+{
+ char *s = rbuf + (n_td > 0 ? 0 : rbuf_sz - rbuf_n);
+ dir_copy(&dbuf, &dbuf_n, &dbuf_sz, s, rbuf_n, n_td);
+ rbuf_n = 0;
+}
+
+/* append s to dbuf or rbuf based on the current text direction */
+static void dir_append(char *s)
+{
+ int dir = dir_cd > 0;
+ if (dir == n_td && rbuf_n)
+ dir_flush();
+ if (dir == n_td)
+ dir_copy(&dbuf, &dbuf_n, &dbuf_sz, s, strlen(s), dir);
+ else
+ dir_copy(&rbuf, &rbuf_n, &rbuf_sz, s, strlen(s), dir);
+}
+
+static void setfont(int f)
+{
+ char cmd[32];
+ sprintf(cmd, "%cf(%02d", c_ec, f);
+ if (f >= 0)
+ dir_append(cmd);
+}
+
+static void setsize(int s)
+{
+ char cmd[32];
+ sprintf(cmd, s <= 99 ? "%cs(%02d" : "%cs[%d]", c_ec, s);
+ if (s >= 0)
+ dir_append(cmd);
+}
+
+static void setcolor(int m)
+{
+ char cmd[32];
+ sprintf(cmd, "%cm[%s]", c_ec, clr_str(m));
+ if (m >= 0)
+ dir_append(cmd);
+}
+
+void dir_fix(struct sbuf *sbuf, char *src)
+{
+ char cmd[ILNLEN];
+ char *prev_s = src;
+ char *r, *c;
+ int f = -1, s = -1, m = -1;
+ int t, n;
+ dir_cd = n_td;
+ while ((t = escread(&src, &c)) >= 0) {
+ cmd[0] = '\0';
+ switch (t) {
+ case 0:
+ case 'D':
+ case 'h':
+ case 'v':
+ case 'x':
+ memcpy(cmd, prev_s, src - prev_s);
+ cmd[src - prev_s] = '\0';
+ dir_append(cmd);
+ break;
+ case 'f':
+ n = atoi(c);
+ if (f != n) {
+ setfont(f);
+ f = n;
+ setfont(f);
+ }
+ break;
+ case 'm':
+ n = clr_get(c);
+ if (m != n) {
+ setcolor(m);
+ m = n;
+ setcolor(m);
+ }
+ break;
+ case 's':
+ n = atoi(c);
+ if (s != n) {
+ setsize(s);
+ s = n;
+ setsize(s);
+ }
+ break;
+ case 'X':
+ sprintf(cmd, "%c%c%s", c_ec, t, c);
+ dir_append(cmd);
+ break;
+ case '<':
+ setcolor(m);
+ setfont(f);
+ setsize(s);
+ dir_cd = 1;
+ setsize(s);
+ setfont(f);
+ setcolor(m);
+ break;
+ case '>':
+ setcolor(m);
+ setfont(f);
+ setsize(s);
+ dir_cd = 0;
+ setsize(s);
+ setfont(f);
+ setcolor(m);
+ break;
+ }
+ prev_s = src;
+ }
+ setcolor(m);
+ setfont(f);
+ setsize(s);
+ dir_flush();
+ r = n_td > 0 ? dbuf + dbuf_sz - dbuf_n : dbuf;
+ r[dbuf_n] = '\0';
+ dbuf_n = 0;
+ sbuf_append(sbuf, r);
+}
+
+void dir_done(void)
+{
+ free(rbuf);
+ free(dbuf);
+}
--- a/fmt.c
+++ b/fmt.c
@@ -16,7 +16,7 @@
#include <string.h>
#include "roff.h"
-#define FMT_LLEN(f) MAX(0, (f)->ll - (f)->li)
+#define FMT_LLEN(f) MAX(0, (f)->ll - (f)->li - (f)->lI)
#define FMT_FILL(f) (!n_ce && n_u)
#define FMT_ADJ(f) (n_u && !n_na && !n_ce && (n_j & AD_B) == AD_B)
@@ -35,7 +35,7 @@
struct line {
struct sbuf sbuf;
- int wid, li, ll;
+ int wid, li, ll, lI;
int elsn, elsp;
};
@@ -54,7 +54,7 @@
int gap; /* space before the next word */
int nls; /* newlines before the next word */
int nls_sup; /* suppressed newlines */
- int li, ll; /* current line indentation and length */
+ int li, ll, lI; /* current line indentation and length */
int filled; /* filled all words in the last fmt_fill() */
int eos; /* last word ends a sentence */
int fillreq; /* fill after the last word (\p) */
@@ -65,12 +65,15 @@
{
f->ll = n_l;
f->li = n_ti >= 0 ? n_ti : n_i;
+ f->lI = n_tI >= 0 ? n_tI : n_I;
n_ti = -1;
+ n_tI = -1;
}
static int fmt_confchanged(struct fmt *f)
{
- return f->ll != n_l || f->li != (n_ti >= 0 ? n_ti : n_i);
+ return f->ll != n_l || f->li != (n_ti >= 0 ? n_ti : n_i) ||
+ f->lI != (n_tI >= 0 ? n_tI : n_I);
}
/* move words inside an fmt struct */
@@ -144,7 +147,7 @@
/* return the next line in the buffer */
char *fmt_nextline(struct fmt *f, int *w,
- int *li, int *ll, int *els_neg, int *els_pos)
+ int *li, int *lI, int *ll, int *els_neg, int *els_pos)
{
struct line *l;
if (f->lines_head == f->lines_tail)
@@ -151,6 +154,7 @@
return NULL;
l = &f->lines[f->lines_tail++];
*li = l->li;
+ *lI = l->lI;
*ll = l->ll;
*w = l->wid;
*els_neg = l->elsn;
@@ -172,6 +176,7 @@
}
l = &f->lines[f->lines_head++];
l->li = f->li;
+ l->lI = f->lI;
l->ll = f->ll;
sbuf_init(&l->sbuf);
return l;
@@ -326,7 +331,7 @@
char *beg;
char *end;
int n, i;
- int cf, cs, cm;
+ int cf, cs, cm, ccd;
n = fmt_hyphmarks(src, hyidx, hyins, hygap);
if (n <= 0) {
fmt_wb2word(f, fmt_mkword(f), wb, 0, 1, gap, wb_cost(wb));
@@ -347,12 +352,12 @@
if (i < n && hygap[i]) /* remove \~ */
end -= strlen(c_nb);
wb_catstr(&wbc, beg, end);
- wb_fnszget(&wbc, &cf, &cs, &cm);
+ wb_fnszget(&wbc, &cf, &cs, &cm, &ccd);
icost = i == n ? wb_cost(&wbc) : hygap[i] * 10000000;
igap = i == 0 ? gap : hygap[i - 1] * wb_swid(&wbc);
fmt_wb2word(f, fmt_mkword(f), &wbc, ihy, istr, igap, icost);
wb_reset(&wbc);
- wb_fnszset(&wbc, cf, cs, cm); /* restoring wbc */
+ wb_fnszset(&wbc, cf, cs, cm, ccd); /* restoring wbc */
}
wb_done(&wbc);
}
--- a/reg.c
+++ b/reg.c
@@ -41,6 +41,7 @@
".hy", ".hycost", ".hycost2", ".hycost3", ".hlm",
".L0", ".m0", ".n0", ".s0", ".ss", ".ssh", ".sss", ".pmll", ".pmllcost",
".ti", ".lt", ".lt0", ".v0",
+ ".I", ".I0", ".tI", ".td", ".cd",
};
/* return the address of a number register */
@@ -230,6 +231,7 @@
env = envs[id];
n_f = 1;
n_i = 0;
+ n_I = 0;
n_j = AD_B;
n_l = SC_IN * 65 / 10;
n_L = 1;
@@ -343,7 +345,7 @@
/* saving and restoring registers around diverted lines */
struct odiv {
- int f, s, m, f0, s0, m0;
+ int f, s, m, f0, s0, m0, cd;
};
static struct odiv odivs[NPREV]; /* state before diverted text */
@@ -359,6 +361,7 @@
o->f0 = n_f0;
o->s0 = n_s0;
o->m0 = n_m0;
+ o->cd = n_cd;
}
/* end outputting diverted line */
@@ -371,6 +374,7 @@
n_f0 = o->f0;
n_s0 = o->s0;
n_m0 = o->m0;
+ n_cd = o->cd;
}
void tr_ta(char **args)
--- a/ren.c
+++ b/ren.c
@@ -238,10 +238,10 @@
}
/* line adjustment */
-static int ren_ljust(struct sbuf *spre, int w, int ad, int li, int ll)
+static int ren_ljust(struct sbuf *spre, int w, int ad, int li, int lI, int ll)
{
int ljust = li;
- int llen = ll - ljust;
+ int llen = ll - lI - li;
n_n = w;
if ((ad & AD_B) == AD_C)
ljust += llen > w ? (llen - w) / 2 : 0;
@@ -271,6 +271,17 @@
}
}
+static void ren_dir(struct sbuf *sbuf)
+{
+ struct sbuf fixed;
+ sbuf_init(&fixed);
+ dir_fix(&fixed, sbuf_buf(sbuf));
+ sbuf_done(sbuf);
+ sbuf_init(sbuf);
+ sbuf_append(sbuf, sbuf_buf(&fixed));
+ sbuf_done(&fixed);
+}
+
static int zwid(void)
{
struct glyph *g = dev_glyph("0", n_f);
@@ -317,13 +328,15 @@
/* process a line and print it with ren_out() */
static int ren_line(char *line, int w, int ad, int body,
- int li, int ll, int els_neg, int els_pos)
+ int li, int lI, int ll, int els_neg, int els_pos)
{
- struct sbuf sbeg, send;
+ struct sbuf sbeg, send, sbuf;
int prev_d, lspc, ljust;
ren_first();
sbuf_init(&sbeg);
sbuf_init(&send);
+ sbuf_init(&sbuf);
+ sbuf_append(&sbuf, line);
lspc = MAX(1, n_L) * n_v; /* line space, ignoreing \x */
prev_d = n_d;
if (!n_ns || line[0] || els_neg || els_pos) {
@@ -332,10 +345,12 @@
ren_sp(0, 0);
if (line[0] && n_nm && body)
ren_lnum(&sbeg);
- ljust = ren_ljust(&sbeg, w, ad, li, ll);
+ if (!ren_div && dir_do)
+ ren_dir(&sbuf);
+ ljust = ren_ljust(&sbeg, w, ad, li, lI, ll);
if (line[0] && body && n_mc)
ren_mc(&send, w, ljust);
- ren_out(sbuf_buf(&sbeg), line, sbuf_buf(&send));
+ ren_out(sbuf_buf(&sbeg), sbuf_buf(&sbuf), sbuf_buf(&send));
n_ns = 0;
if (els_pos)
ren_sp(els_pos, 1);
@@ -342,6 +357,7 @@
}
sbuf_done(&sbeg);
sbuf_done(&send);
+ sbuf_done(&sbuf);
n_a = els_pos;
if (detect_traps(prev_d, n_d) || detect_pagelimit(lspc - n_v)) {
if (!ren_pagelimit(lspc - n_v))
@@ -357,17 +373,19 @@
static int ren_passline(struct fmt *fmt)
{
char *buf;
- int ll, li, els_neg, els_pos, w, ret;
+ int ll, li, lI, els_neg, els_pos, w, ret;
int ad = n_j;
ren_first();
if (!fmt_morewords(fmt))
return 0;
- buf = fmt_nextline(fmt, &w, &li, &ll, &els_neg, &els_pos);
+ buf = fmt_nextline(fmt, &w, &li, &lI, &ll, &els_neg, &els_pos);
if ((n_cp && !n_u) || n_na)
ad = AD_L;
+ else if ((ad & AD_B) == AD_B)
+ ad = n_td > 0 ? AD_R : AD_L;
if (n_ce)
ad = AD_C;
- ret = ren_line(buf, w, ad, 1, li, ll, els_neg, els_pos);
+ ret = ren_line(buf, w, ad, 1, li, lI, ll, els_neg, els_pos);
free(buf);
return ret;
}
@@ -546,6 +564,42 @@
n_ti = eval_re(args[1], n_i, 'm');
}
+void tr_l2r(char **args)
+{
+ dir_do = 1;
+ if (args[0][0] == c_cc)
+ ren_br();
+ n_td = 0;
+ n_cd = 0;
+}
+
+void tr_r2l(char **args)
+{
+ dir_do = 1;
+ if (args[0][0] == c_cc)
+ ren_br();
+ n_td = 1;
+ n_cd = 1;
+}
+
+void tr_in2(char **args)
+{
+ int I = args[1] ? eval_re(args[1], n_I, 'm') : n_I0;
+ if (args[0][0] == c_cc)
+ ren_br();
+ n_I0 = n_I;
+ n_I = MAX(0, I);
+ n_tI = -1;
+}
+
+void tr_ti2(char **args)
+{
+ if (args[0][0] == c_cc)
+ ren_br();
+ if (args[1])
+ n_tI = eval_re(args[1], n_I, 'm');
+}
+
static void ren_ft(char *s)
{
int fn = !s || !*s || !strcmp("P", s) ? n_f0 : dev_pos(s);
@@ -710,6 +764,11 @@
case ',':
wb_italiccorrectionleft(wb);
break;
+ case '<':
+ case '>':
+ n_cd = c == '<';
+ wb_flushdir(wb);
+ break;
}
}
@@ -739,7 +798,7 @@
wb_hmov(wb, w - wb_wid(wb));
return;
}
- if (strchr(" bCcDdefHhjkLlmNoprSsuvXxZz0^|!{}&/,", c[1])) {
+ if (strchr(" bCcDdefHhjkLlmNoprSsuvXxZz0^|!{}&/,<>", c[1])) {
char *arg = NULL;
if (strchr(ESC_P, c[1]))
arg = unquotednext(c[1], next, back);
@@ -875,7 +934,7 @@
wb_cpy(&wb, &wb2, n_lt - wb_wid(&wb2));
/* flushing the line */
ren_line(wb_buf(&wb), wb_wid(&wb), AD_L, 0,
- 0, n_lt, wb.els_neg, wb.els_pos);
+ 0, 0, n_lt, wb.els_neg, wb.els_pos);
wb_done(&wb2);
wb_done(&wb);
}
--- a/roff.c
+++ b/roff.c
@@ -157,5 +157,6 @@
env_done();
dev_close();
map_done();
+ dir_done();
return ret;
}
--- a/roff.h
+++ b/roff.h
@@ -225,8 +225,8 @@
/* word buffer */
struct wb {
struct sbuf sbuf;
- int f, s, m; /* the last output font and size */
- int r_f, r_s, r_m; /* current font and size; use n_f and n_s if -1 */
+ int f, s, m, cd; /* the last output font and size */
+ int r_f, r_s, r_m, r_cd;/* current font and size; use n_f and n_s if -1 */
int part; /* partial input (\c) */
int cost; /* the extra cost of line break after this word */
int els_neg, els_pos; /* extra line spacing */
@@ -274,8 +274,9 @@
int *llx, int *lly, int *urx, int *ury);
void wb_reset(struct wb *wb);
char *wb_buf(struct wb *wb);
-void wb_fnszget(struct wb *wb, int *fn, int *sz, int *m);
-void wb_fnszset(struct wb *wb, int fn, int sz, int m);
+void wb_fnszget(struct wb *wb, int *fn, int *sz, int *m, int *cd);
+void wb_fnszset(struct wb *wb, int fn, int sz, int m, int cd);
+void wb_flushdir(struct wb *wb);
int wb_hywid(struct wb *wb);
int wb_swid(struct wb *wb);
int c_eossent(char *s);
@@ -321,7 +322,7 @@
int fmt_morelines(struct fmt *fmt);
int fmt_morewords(struct fmt *fmt);
char *fmt_nextline(struct fmt *fmt, int *w,
- int *li, int *ll, int *els_neg, int *els_pos);
+ int *li, int *lI, int *ll, int *els_neg, int *els_pos);
/* rendering */
int render(void); /* the main loop */
@@ -383,6 +384,11 @@
void tr_popren(char **args);
void tr_transparent(char **args);
+void tr_in2(char **args);
+void tr_ti2(char **args);
+void tr_l2r(char **args);
+void tr_r2l(char **args);
+
void tr_init(void);
void tr_done(void);
@@ -426,6 +432,12 @@
char *map_name(int id); /* return the name mapped to id */
void map_done(void);
+/* text direction */
+extern int dir_do;
+
+void dir_fix(struct sbuf *sbuf, char *s);
+void dir_done(void);
+
/* colors */
#define CLR_R(c) (((c) >> 16) & 0xff)
#define CLR_G(c) (((c) >> 8) & 0xff)
@@ -444,6 +456,7 @@
#define n_i (*nreg(DOTMAP('i')))
#define n_it (*nreg(map(".it"))) /* .it trap macro */
#define n_itn (*nreg(map(".itn"))) /* .it lines left */
+#define n_I (*nreg(DOTMAP('I'))) /* base indent */
#define n_j (*nreg(DOTMAP('j')))
#define n_l (*nreg(DOTMAP('l')))
#define n_L (*nreg(DOTMAP('L')))
@@ -462,6 +475,8 @@
#define n_u (*nreg(DOTMAP('u')))
#define n_v (*nreg(DOTMAP('v')))
#define n_ct (*nreg(map("ct")))
+#define n_td (*nreg(map(".td"))) /* text direction */
+#define n_cd (*nreg(map(".cd"))) /* current direction */
#define n_dl (*nreg(map("dl")))
#define n_dn (*nreg(map("dn")))
#define n_ln (*nreg(map("ln")))
@@ -481,6 +496,8 @@
#define n_i0 (*nreg(map(".i0"))) /* last .i */
#define n_ti (*nreg(map(".ti"))) /* pending .ti */
#define n_kn (*nreg(map(".kn"))) /* .kn mode */
+#define n_tI (*nreg(map(".tI"))) /* pending .ti2 */
+#define n_I0 (*nreg(map(".I0"))) /* last .I */
#define n_l0 (*nreg(map(".l0"))) /* last .l */
#define n_L0 (*nreg(map(".L0"))) /* last .L */
#define n_m0 (*nreg(map(".m0"))) /* last .m */
--- a/tr.c
+++ b/tr.c
@@ -1020,6 +1020,8 @@
{TR_DIVEND, tr_divend},
{TR_DIVVS, tr_divvs},
{TR_POPREN, tr_popren},
+ {">>", tr_l2r},
+ {"<<", tr_r2l},
{"ab", tr_ab, mkargs_eol},
{"ad", tr_ad},
{"af", tr_af},
@@ -1075,6 +1077,7 @@
{"if", tr_if, mkargs_null},
{"ig", tr_ig},
{"in", tr_in},
+ {"in2", tr_in2},
{"it", tr_it},
{"kn", tr_kn},
{"lc", tr_lc},
@@ -1116,6 +1119,7 @@
{"ta", tr_ta},
{"tc", tr_tc},
{"ti", tr_ti},
+ {"ti2", tr_ti2},
{"tkf", tr_tkf},
{"tl", tr_tl, mkargs_null},
{"tm", tr_tm, mkargs_eol},
--- a/wb.c
+++ b/wb.c
@@ -9,6 +9,7 @@
#define R_F(wb) ((wb)->r_f >= 0 ? (wb)->r_f : n_f) /* current font */
#define R_S(wb) ((wb)->r_s >= 0 ? (wb)->r_s : n_s) /* current size */
#define R_M(wb) ((wb)->r_m >= 0 ? (wb)->r_m : n_m) /* current color */
+#define R_CD(b) ((wb)->r_cd >= 0 ? (wb)->r_cd : n_cd) /* current direction */
/* italic correction */
#define glyph_ic(g) (MAX(0, (g)->urx - (g)->wid))
#define glyph_icleft(g) (MAX(0, -(g)->llx))
@@ -26,9 +27,11 @@
wb->f = -1;
wb->s = -1;
wb->m = -1;
+ wb->cd = -1;
wb->r_f = -1;
wb->r_s = -1;
wb->r_m = -1;
+ wb->r_cd = -1;
wb->llx = BBMAX;
wb->lly = BBMAX;
wb->urx = BBMIN;
@@ -63,6 +66,12 @@
(!n_cp && wb->m != R_M(wb));
}
+/* pending direction change */
+static int wb_pendingdir(struct wb *wb)
+{
+ return wb->cd != R_CD(wb);
+}
+
/* append font and size to the buffer if needed */
static void wb_flushfont(struct wb *wb)
{
@@ -84,10 +93,22 @@
wb_stsb(wb);
}
+/* append current text direction to the buffer if needed */
+void wb_flushdir(struct wb *wb)
+{
+ if (wb->cd != R_CD(wb)) {
+ wb_flushsub(wb);
+ if (dir_do)
+ sbuf_printf(&wb->sbuf, "%c%c", c_ec, R_CD(wb) > 0 ? '<' : '>');
+ wb->cd = R_CD(wb);
+ }
+}
+
/* apply font and size changes and flush the collected subword */
static void wb_flush(struct wb *wb)
{
wb_flushsub(wb);
+ wb_flushdir(wb);
wb_flushfont(wb);
}
@@ -220,10 +241,12 @@
dst_n = font_layout(fn, gsrc, sidx - beg, wb->s,
gdst, dmap, x, y, xadv, yadv, n_lg, n_kn);
for (i = 0; i < dst_n; i++) {
- if (x[i])
- wb_hmov(wb, font_wid(fn, wb->s, x[i]));
- if (y[i])
- wb_vmov(wb, font_wid(fn, wb->s, y[i]));
+ int xd[2] = {x[i], xadv[i] - x[i]};
+ int yd[2] = {y[i], yadv[i] - y[i]};
+ if (xd[wb->cd])
+ wb_hmov(wb, font_wid(fn, wb->s, xd[wb->cd]));
+ if (yd[wb->cd])
+ wb_vmov(wb, font_wid(fn, wb->s, yd[wb->cd]));
if (src_hyph[beg + dmap[i]])
wb_putbuf(wb, c_hc);
if (gdst[i] == gsrc[dmap[i]])
@@ -230,10 +253,10 @@
wb_putbuf(wb, wb->sub_c[beg + dmap[i]]);
else
wb_putbuf(wb, gdst[i]->name);
- if (x[i] || xadv[i])
- wb_hmov(wb, font_wid(fn, wb->s, xadv[i] - x[i]));
- if (y[i] || yadv[i])
- wb_vmov(wb, font_wid(fn, wb->s, yadv[i] - y[i]));
+ if (xd[1 - wb->cd])
+ wb_hmov(wb, font_wid(fn, wb->s, xd[1 - wb->cd]));
+ if (yd[1 - wb->cd])
+ wb_vmov(wb, font_wid(fn, wb->s, yd[1 - wb->cd]));
}
for (; sidx < wb->sub_n && c_hymark(wb->sub_c[sidx]); sidx++)
wb_putbuf(wb, wb->sub_c[sidx]);
@@ -249,6 +272,8 @@
wb->part = 0;
return;
}
+ if (wb_pendingdir(wb))
+ wb_flushdir(wb);
if (c[0] == ' ') {
wb_flushsub(wb);
wb_hmov(wb, font_swid(dev_font(R_F(wb)), R_S(wb), n_ss));
@@ -411,6 +436,11 @@
case 'X':
wb_etc(wb, s);
break;
+ case '<':
+ case '>':
+ wb->r_cd = t == '<';
+ wb_flushdir(wb);
+ break;
}
}
@@ -429,6 +459,7 @@
wb->r_s = -1;
wb->r_f = -1;
wb->r_m = -1;
+ wb->r_cd = -1;
wb_reset(src);
src->part = part;
wb_collect(wb, collect);
@@ -497,19 +528,21 @@
wb->icleft = 1;
}
-void wb_fnszget(struct wb *wb, int *fn, int *sz, int *m)
+void wb_fnszget(struct wb *wb, int *fn, int *sz, int *m, int *cd)
{
wb_flushsub(wb);
*fn = wb->r_f;
*sz = wb->r_s;
*m = wb->r_m;
+ *cd = wb->r_cd;
}
-void wb_fnszset(struct wb *wb, int fn, int sz, int m)
+void wb_fnszset(struct wb *wb, int fn, int sz, int m, int cd)
{
wb->r_f = fn;
wb->r_s = sz;
wb->r_m = m;
+ wb->r_cd = cd;
}
void wb_catstr(struct wb *wb, char *s, char *end)