ref: 52bd1c9b13849dd92d9e3619bcf0a89d4067f849
parent: d6629cca62b8f16e016c42e644907404319650e9
author: Ali Gholami Rudi <ali@rudi.ir>
date: Wed Nov 21 16:21:04 EST 2012
ren: implement \s and \f
--- a/out.c
+++ b/out.c
@@ -50,8 +50,10 @@
}
}
-static char *escarg(char *s, char *d)
+static char *escarg(char *s, char *d, int cmd)
{
+ if (cmd == 's' && (*s == '-' || *s == '+'))
+ *d++ = *s++;
if (*s == '(') {
s++;
*d++ = *s++;
@@ -64,6 +66,8 @@
s++;
} else {
*d++ = *s++;
+ if (cmd == 's' && s[-1] >= '1' && s[-1] <= '3' && isdigit(*s))
+ *d++ = *s++;
}
*d = '\0';
return s;
@@ -74,7 +78,6 @@
struct glyph *g;
char c[LLEN];
char arg[LINELEN];
- int o_blank = 0;
printf("v%d\n", n_v);
printf("H%d\n", n_o + n_i);
while (*s) {
@@ -84,8 +87,8 @@
if (c[0] == '(') {
s = utf8get(c, s);
s = utf8get(c + strlen(c), s);
- } else if (strchr("sf", c[0])) {
- s = escarg(s, arg);
+ } else if (strchr("sfh", c[0])) {
+ s = escarg(s, arg, c[0]);
if (c[0] == 's') {
out_ps(tr_int(arg, o_s, '\0'));
continue;
@@ -94,21 +97,20 @@
out_ft(dev_font(arg));
continue;
}
+ if (c[0] == 'h') {
+ printf("h%d", tr_int(arg, 0, 'm'));
+ continue;
+ }
}
}
g = dev_glyph(c, o_f);
if (g) {
- if (o_blank)
- printf("h%d", charwid(dev_spacewid(), o_s));
if (utf8len(c[0]) == strlen(c)) {
printf("c%s%s", c, c[1] ? "\n" : "");
} else {
printf("C%s\n", c);
}
- printf("h%d", charwid(g->wid, o_s));
- o_blank = 0;
- } else {
- o_blank = 1;
}
+ printf("h%d", charwid(g ? g->wid : dev_spacewid(), o_s));
}
}
--- a/ren.c
+++ b/ren.c
@@ -16,16 +16,20 @@
static struct word words[LINELEN]; /* words in the buffer */
static int nwords;
static int wid; /* total width of the buffer */
+static int ren_backed = -1; /* pushed back character */
static int ren_next(void)
{
- int c = tr_next();
- if (c < 0)
- return -1;
- buf[buflen++] = c;
+ int c = ren_backed >= 0 ? ren_backed : tr_next();
+ ren_backed = -1;
return c;
}
+static void ren_back(int c)
+{
+ ren_backed = c;
+}
+
static int nextchar(char *s)
{
int c = ren_next();
@@ -48,6 +52,7 @@
static void adjust(char *s)
{
struct word *last = words;
+ struct word *cur;
int w = 0;
int lendiff;
int i;
@@ -61,8 +66,13 @@
}
if (last > words)
last--;
- memcpy(s, buf, last->end);
- s[last->end] = '\0';
+ for (cur = words; cur <= last; cur++) {
+ if (cur > words)
+ s += sprintf(s, "\\h'%du'", cur->blanks);
+ memcpy(s, buf + cur->beg, cur->end - cur->beg);
+ s += cur->end - cur->beg;
+ }
+ *s = '\0';
lendiff = last + 1 < words + nwords ? last[1].beg : buflen;
memmove(buf, buf + lendiff, buflen - lendiff);
buflen -= lendiff;
@@ -97,7 +107,9 @@
static void ren_ps(char *s)
{
- n_s = tr_int(s, n_s, '\0');
+ int ps = !*s || !strcmp("0", s) ? n_s0 : tr_int(s, n_s, '\0');
+ n_s0 = n_s;
+ n_s = ps;
}
void tr_ps(int argc, char **args)
@@ -104,25 +116,21 @@
{
if (argc >= 2)
ren_ps(args[1]);
- buflen += sprintf(buf + buflen, "\\s(%2d", n_s);
}
-static int ren_ft(char *name)
+static void ren_ft(char *s)
{
- int fn = dev_font(name);
- if (fn >= 0)
+ int fn = !*s || !strcmp("P", s) ? n_f0 : dev_font(s);
+ if (fn >= 0) {
+ n_f0 = n_f;
n_f = fn;
- return fn;
+ }
}
void tr_ft(int argc, char **args)
{
- int fn;
- if (argc < 2)
- return;
- fn = ren_ft(args[1]);
- if (fn >= 0)
- buflen += sprintf(buf + buflen, "\\f%d", n_f);
+ if (argc > 1)
+ ren_ft(args[1]);
}
void tr_fp(int argc, char **args)
@@ -133,10 +141,14 @@
errmsg("troff: failed to mount %s\n", args[2]);
}
-static void escarg(char *s)
+static void escarg(char *s, int cmd)
{
int c;
c = ren_next();
+ if (cmd == 's' && (c == '-' || c == '+')) {
+ *s++ = c;
+ c = ren_next();
+ }
if (c == '(') {
*s++ = ren_next();
*s++ = ren_next();
@@ -154,6 +166,13 @@
return;
}
*s++ = c;
+ if (cmd == 's' && c >= '1' && c <= '3') {
+ c = ren_next();
+ if (isdigit(c))
+ *s++ = c;
+ else
+ ren_back(c);
+ }
*s = '\0';
}
@@ -162,14 +181,32 @@
char c[LLEN];
char arg[LINELEN];
struct glyph *g;
+ int g_wid;
struct word *word = NULL;
- int word_beg;
int blanks = 0;
+ int newline = 0;
+ int r_s = n_s;
+ int r_f = n_f;
+ int esc = 0;
tr_br(0, NULL);
while (nextchar(c) > 0) {
g = NULL;
- word_beg = buflen - strlen(c);
+ if (!word && wid > n_l)
+ tr_br(0, NULL);
+ if (c[0] == ' ' || c[0] == '\n') {
+ if (word) {
+ word->end = buflen;
+ word = NULL;
+ }
+ if (c[0] == '\n')
+ newline = 1;
+ else
+ blanks += charwid(dev_spacewid(), n_s);
+ continue;
+ }
+ esc = 0;
if (c[0] == '\\') {
+ esc = 1;
nextchar(c);
if (c[0] == '(') {
int l = nextchar(c);
@@ -176,7 +213,7 @@
l += nextchar(c + l);
c[l] = '\0';
} else if (strchr("sf", c[0])) {
- escarg(arg);
+ escarg(arg, c[0]);
if (c[0] == 'f')
ren_ft(arg);
if (c[0] == 's')
@@ -184,27 +221,34 @@
continue;
}
}
- g = dev_glyph(c, n_f);
- if (!g) {
- blanks += charwid(dev_spacewid(), n_s);
- word = NULL;
- continue;
- }
if (!word) {
word = &words[nwords++];
- word->beg = word_beg;
+ word->beg = buflen;
word->wid = 0;
- word->blanks = blanks;
+ if (newline)
+ word->blanks = charwid(dev_spacewid(), n_s);
+ else
+ word->blanks = blanks;
wid += blanks;
+ newline = 0;
blanks = 0;
}
- word->end = buflen;
- word->wid += charwid(g->wid, n_s);
- wid += charwid(g->wid, n_s);
- if (wid > n_l) {
- word = NULL;
- tr_br(0, NULL);
+ if (r_s != n_s) {
+ buflen += sprintf(buf + buflen, "\\s(%02d", n_s);
+ r_s = n_s;
}
+ if (r_f != n_f) {
+ buflen += sprintf(buf + buflen, "\\f(%02d", n_f);
+ r_f = n_f;
+ }
+ if (utf8len(c[0]) == strlen(c))
+ buflen += sprintf(buf + buflen, "%s%s", esc ? "\\" : "", c);
+ else
+ buflen += sprintf(buf + buflen, "\\(%s", c);
+ g = dev_glyph(c, n_f);
+ g_wid = charwid(g ? g->wid : dev_spacewid(), n_s);
+ word->wid += g_wid;
+ wid += g_wid;
}
tr_br(0, NULL);
}
--- a/xroff.c
+++ b/xroff.c
@@ -11,6 +11,8 @@
n_i = 0;
n_s = 10;
n_v = 12 * SC_PT;
+ n_s0 = n_s;
+ n_f0 = n_f;
}
static void compile(void)
--- a/xroff.h
+++ b/xroff.h
@@ -23,6 +23,8 @@
#define n_l nreg[N_ID('.', 'l')]
#define n_v nreg[N_ID('.', 'v')]
#define n_i nreg[N_ID('.', 'i')]
+#define n_f0 nreg[N_ID('\0', 'f')] /* last font */
+#define n_s0 nreg[N_ID('\0', 's')] /* last size */
/* device related variables */
extern int dev_res;