ref: 5c7624e050d8559ee996b251fc063a5df07d9d46
parent: 4b451268a4cf9a90e01efe84cadbb5417161d568
author: Ali Gholami Rudi <ali@rudi.ir>
date: Wed Apr 24 20:59:10 EDT 2013
ren: add \o, \z and \b
--- a/line.c
+++ b/line.c
@@ -83,7 +83,7 @@
arg += 2;
if (*arg)
lc = arg;
- w = n_s * SC_PT; /* character height */
+ w = SC_HT; /* character height */
hw = cwid(lc); /* character width */
/* negative length; moving backwards */
if (l < 0) {
@@ -120,4 +120,74 @@
if (neg)
vmov(adj, -l);
hmov(adj, hw);
+}
+
+static char *cutchar(char *d, char *s)
+{
+ s = utf8get(d, s);
+ if (d[0] == '\\') {
+ s = utf8get(d + 1, s);
+ if (d[1] == '(') {
+ s = utf8get(d + 2, s);
+ s = utf8get(d + strlen(d), s);
+ }
+ }
+ return s;
+}
+
+static int maxwid(char *s)
+{
+ char c[GNLEN * 4];
+ int w = 0;
+ while (*s) {
+ s = cutchar(c, s);
+ if (cwid(c) > w)
+ w = cwid(c);
+ }
+ return w;
+}
+
+static int nchars(char *s)
+{
+ char c[GNLEN * 4];
+ int n = 0;
+ while (*s) {
+ s = cutchar(c, s);
+ n++;
+ }
+ return n;
+}
+
+void ren_bracket(struct adj *adj, char *arg)
+{
+ char c[GNLEN * 4];
+ int ht, hc;
+ int w = maxwid(arg);
+ int n = nchars(arg);
+ ht = n * SC_HT;
+ hc = -(ht + SC_EM) / 2;
+ vmov(adj, hc + SC_HT);
+ while (*arg) {
+ arg = cutchar(c, arg);
+ adj_put(adj, cwid(arg), c);
+ hmov(adj, -cwid(c));
+ vmov(adj, SC_HT);
+ }
+ hmov(adj, w);
+ vmov(adj, hc);
+}
+
+void ren_over(struct adj *adj, char *arg)
+{
+ char c[GNLEN * 4];
+ int a;
+ int w = maxwid(arg);
+ while (*arg) {
+ arg = cutchar(c, arg);
+ a = (w - cwid(c)) / 2;
+ hmov(adj, a);
+ adj_put(adj, cwid(arg), c);
+ hmov(adj, -cwid(c) - a);
+ }
+ hmov(adj, w);
}
--- a/out.c
+++ b/out.c
@@ -51,7 +51,7 @@
return 1;
}
-static char *utf8get(char *d, char *s)
+char *utf8get(char *d, char *s)
{
int l = utf8len((unsigned char) *s);
int i;
--- a/ren.c
+++ b/ren.c
@@ -471,6 +471,9 @@
w = dev_spacewid();
adj_put(adj, w, "\\h'%du'", w);
break;
+ case 'b':
+ ren_bracket(adj, arg);
+ break;
case 'D':
w = out_draw(arg, draw_arg);
adj_put(adj, w, "\\D'%s'", draw_arg);
@@ -494,6 +497,9 @@
case 'l':
ren_hline(adj, arg);
break;
+ case 'o':
+ ren_over(adj, arg);
+ break;
case 'r':
adj_put(adj, 0, "\\v'%du'", eval("-1m", 0, 0));
break;
@@ -538,7 +544,8 @@
char arg[ILNLEN];
char widbuf[16];
struct glyph *g;
- int n;
+ int zerowid = 0;
+ int n, w;
nextchar(c, next);
if (c[0] == ' ' || c[0] == '\n') {
adj_put(adj, charwid(dev_spacewid(), n_s), c);
@@ -550,13 +557,22 @@
int l = nextchar(c + 2, next);
l += nextchar(c + 2 + l, next);
c[2 + l] = '\0';
- } else if (strchr(" DdfhkLlrsuvwXx0^|{}", c[1])) {
- if (c[1] == 'w') {
- n = ren_wid(next, back);
- sprintf(widbuf, "%d", n);
- in_push(widbuf, NULL);
- return 0;
+ } else if (c[1] == 'z') {
+ zerowid = 1;
+ nextchar(c, next);
+ if (c[0] == '\\') {
+ nextchar(c + 1, next);
+ if (c[1] == '(') {
+ nextchar(c + 2, next);
+ nextchar(c + strlen(c), next);
+ }
}
+ } else if (c[1] == 'w') {
+ n = ren_wid(next, back);
+ sprintf(widbuf, "%d", n);
+ in_push(widbuf, NULL);
+ return 0;
+ } else if (strchr(" bDdfhkLlorsuvXxz0^|{}", c[1])) {
escarg_ren(arg, c[1], next, back);
ren_cmd(adj, c[1], arg);
return 0;
@@ -572,7 +588,10 @@
ren_f = n_f;
}
g = dev_glyph(c, n_f);
- adj_put(adj, charwid(g ? g->wid : SC_DW, n_s), c);
+ w = charwid(g ? g->wid : SC_DW, n_s);
+ adj_put(adj, w, c);
+ if (zerowid)
+ adj_put(adj, -w, "\\h'%du'", -w);
return g ? g->type : 0;
}
--- a/xroff.h
+++ b/xroff.h
@@ -1,7 +1,9 @@
/* converting scales */
#define SC_IN (dev_res) /* inch in units */
#define SC_PT (SC_IN / 72) /* point in units */
-#define SC_DW (n_s * SC_IN / 72 / 3) /* default width */
+#define SC_EM (n_s * SC_IN / 72)
+#define SC_DW (SC_EM / 3) /* default width */
+#define SC_HT (n_s * SC_PT) /* character height */
/* predefined array limits */
#define PATHLEN 1024 /* path length */
@@ -122,6 +124,8 @@
void out(char *s, ...); /* output troff cmd */
void ren_hline(struct adj *adj, char *arg); /* horizontal line */
void ren_vline(struct adj *adj, char *arg); /* vertical line */
+void ren_bracket(struct adj *adj, char *arg); /* \b */
+void ren_over(struct adj *adj, char *arg); /* \o */
/* troff commands */
void tr_bp(char **args);
@@ -156,6 +160,7 @@
/* helpers */
void errmsg(char *msg, ...);
int utf8len(int c);
+char *utf8get(char *d, char *s);
/* variable length string buffer */
struct sbuf {