6 static int cwid(char *c
)
8 struct glyph
*g
= dev_glyph(c
, n_f
);
9 return charwid(n_f
, n_s
, g
? g
->wid
: SC_DW
);
12 static int hchar(char *c
)
17 return c
[1] == '_' || c
[1] == '-';
18 return (c
[2] == 'r' && c
[3] == 'u') || (c
[2] == 'u' && c
[3] == 'l') ||
19 (c
[2] == 'r' && c
[3] == 'n');
22 static int vchar(char *c
)
24 if (c
[0] != c_ec
|| c
[1] != '(')
26 return (c
[2] == 'b' && c
[3] == 'v') || (c
[2] == 'b' && c
[3] == 'r');
29 void ren_hline(struct wb
*wb
, int l
, char *c
)
33 /* negative length; moving backwards */
40 /* length less than character width */
44 wb_hmov(wb
, -(w
- l
) / 2);
55 for (i
= 0; i
< n
; i
++)
59 wb_hmov(wb
, -(w
- l
+ 1) / 2);
62 static void ren_vline(struct wb
*wb
, int l
, char *c
)
64 int w
, n
, i
, rem
, hw
, neg
;
66 w
= SC_HT
; /* character height */
67 hw
= cwid(c
); /* character width */
68 /* negative length; moving backwards */
75 /* length less than character width */
79 wb_vmov(wb
, -w
+ l
/ 2);
92 for (i
= 0; i
< n
; i
++) {
105 void ren_hlcmd(struct wb
*wb
, char *arg
)
107 char lc
[GNLEN
] = {c_ec
, '(', 'r', 'u'};
108 int l
= eval_up(&arg
, 'm');
109 if (arg
[0] == c_ec
&& arg
[1] == '&') /* \& can be used as a separator */
112 ren_hline(wb
, l
, *arg
? arg
: lc
);
115 void ren_vlcmd(struct wb
*wb
, char *arg
)
117 char lc
[GNLEN
] = {c_ec
, '(', 'b', 'r'};
118 int l
= eval_up(&arg
, 'v');
119 if (arg
[0] == c_ec
&& arg
[1] == '&') /* \& can be used as a separator */
122 ren_vline(wb
, l
, *arg
? arg
: lc
);
125 static int tok_num(char **s
, int scale
)
131 while (**s
&& !isspace(**s
))
134 return eval(tok
, scale
);
137 void ren_dcmd(struct wb
*wb
, char *s
)
143 h1
= tok_num(&s
, 'm');
144 v1
= tok_num(&s
, 'v');
145 wb_drawl(wb
, h1
, v1
);
148 h1
= tok_num(&s
, 'm');
152 h1
= tok_num(&s
, 'm');
153 v1
= tok_num(&s
, 'v');
154 wb_drawe(wb
, h1
, v1
);
157 h1
= tok_num(&s
, 'm');
158 v1
= tok_num(&s
, 'v');
159 h2
= tok_num(&s
, 'm');
160 v2
= tok_num(&s
, 'v');
161 wb_drawa(wb
, h1
, v1
, h2
, v2
);
166 h1
= tok_num(&s
, 'm');
167 v1
= tok_num(&s
, 'v');
168 wb_drawxdot(wb
, h1
, v1
);
175 * the implementation of \b and \o
177 * ren_bcmd() and ren_ocmd() call ren_char(), which requires
178 * next() and back() functions, similar to ren_next() and ren_back().
179 * ln_*() here provide such an interface for the given string,
180 * added via ln_push(). ln_*() may be called recursively to
181 * handle \o'\b"ab"c'.
185 static int ln_next(void)
187 return *ln_s
? (unsigned char) *ln_s
++ : -1;
190 static void ln_back(int c
)
195 static char *ln_push(char *s
)
202 static void ln_pop(char *s
)
207 void ren_bcmd(struct wb
*wb
, char *arg
)
212 char *ln_prev
= ln_push(arg
);
217 ren_char(&wb2
, ln_next
, ln_back
);
218 if (wb_wid(&wb2
) > w
)
220 wb_hmov(&wb2
, -wb_wid(&wb2
));
221 wb_vmov(&wb2
, SC_HT
);
226 center
= -(n
* SC_HT
+ SC_EM
) / 2;
227 wb_vmov(wb
, center
+ SC_HT
);
234 void ren_ocmd(struct wb
*wb
, char *arg
)
239 char *ln_prev
= ln_push(arg
);
245 ren_char(&wb3
, ln_next
, ln_back
);
249 wb_hmov(&wb2
, -wc
/ 2);
251 wb_hmov(&wb2
, -wc
/ 2);