ref: 05ce05cf03e9a81cfa8b65f45e91739d83741fe3
parent: 73e0f630cdbbeb348edeb7eada032b368968b624
author: Ali Gholami Rudi <ali@rudi.ir>
date: Thu May 8 16:24:26 EDT 2014
ren: executing traps while half of an input line is read The old scheme did not work well while formatting whole paragraphs.
--- a/fmt.c
+++ b/fmt.c
@@ -49,6 +49,7 @@
/* current line */
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 filled; /* filled all words in the last fmt_fill() */
int eos; /* last word ends a sentence */
@@ -170,6 +171,7 @@
return 1;
f->filled = 0;
f->nls--;
+ f->nls_sup = 0;
l->wid = fmt_wordscopy(f, 0, f->nwords, &l->sbuf, &l->elsn, &l->elsp);
f->nwords = 0;
f->fillreq = 0;
@@ -265,24 +267,33 @@
wb_done(&wbc);
}
+/* the amount of space necessary before the next word */
+static int fmt_wordgap(struct fmt *f)
+{
+ if ((f->nls || f->nls_sup) && !f->gap && f->nwords >= 1)
+ return (f->nwords && f->eos) ? FMT_SWID(f) * 2 : FMT_SWID(f);
+ return f->gap;
+}
+
/* insert wb into fmt */
int fmt_word(struct fmt *f, struct wb *wb)
{
+ if (wb_empty(wb))
+ return 0;
if (f->nwords + NHYPHS >= NWORDS || fmt_confchanged(f))
if (fmt_fill(f))
return 1;
- if (wb_empty(wb))
- return 0;
if (FMT_FILL(f) && f->nls && f->gap)
- fmt_sp(f);
+ if (fmt_sp(f))
+ return 1;
if (!f->nwords) /* apply the new .l and .i */
fmt_confupdate(f);
- if (f->nls && !f->gap && f->nwords >= 1)
- f->gap = (f->nwords && f->eos) ? FMT_SWID(f) * 2 : FMT_SWID(f);
+ f->gap = fmt_wordgap(f);
f->eos = wb_eos(wb);
fmt_insertword(f, wb, f->filled ? 0 : f->gap);
f->filled = 0;
f->nls = 0;
+ f->nls_sup = 0;
f->gap = 0;
return 0;
}
@@ -468,8 +479,7 @@
int fmt_wid(struct fmt *fmt)
{
- return fmt_wordslen(fmt, 0, fmt->nwords) +
- (fmt->nls ? FMT_SWID(fmt) : fmt->gap);
+ return fmt_wordslen(fmt, 0, fmt->nwords) + fmt_wordgap(fmt);
}
int fmt_morewords(struct fmt *fmt)
@@ -480,4 +490,13 @@
int fmt_morelines(struct fmt *fmt)
{
return fmt->l_head != fmt->l_tail;
+}
+
+/* suppress the last newline */
+void fmt_suppressnl(struct fmt *fmt)
+{
+ if (fmt->nls) {
+ fmt->nls--;
+ fmt->nls_sup = 1;
+ }
}
--- a/ren.c
+++ b/ren.c
@@ -26,8 +26,8 @@
static int trap_em = -1; /* end macro */
static struct wb ren_wb; /* the main ren.c word buffer */
-static int ren_nl; /* just after newline */
-static int ren_cnl; /* current char is a newline */
+static int ren_nl; /* just after a newline */
+static int ren_partial; /* reading an input line in render_rec() */
static int ren_unbuf[8]; /* ren_back() buffer */
static int ren_un;
static int ren_aborted; /* .ab executed */
@@ -140,12 +140,14 @@
trap_exec(trap_reg(-1));
}
-static void ren_first(void)
+static int ren_first(void)
{
if (bp_first && !cdiv) {
bp_first = 0;
ren_page(bp_next, 1);
+ return 0;
}
+ return 1;
}
/* when nodiv, do not append .sp to diversions */
@@ -170,11 +172,15 @@
static void trap_exec(int reg)
{
char cmd[16];
+ int partial = ren_partial;
if (str_get(reg)) {
sprintf(cmd, "%c%s %d\n", c_cc, TR_POPREN, ren_level);
in_pushnl(cmd, NULL);
in_pushnl(str_get(reg), NULL);
render_rec(++ren_level);
+ /* executed the trap while in the middle of an input line */
+ if (partial)
+ fmt_suppressnl(cfmt);
}
}
@@ -310,7 +316,6 @@
static int ren_line(char *line, int w, int ad, int body,
int li, int ll, int els_neg, int els_pos)
{
- char cmd[16];
struct sbuf sbeg, send;
int prev_d, lspc, ljust;
ren_first();
@@ -336,11 +341,8 @@
ren_sp(els_pos, 1);
n_a = els_pos;
if (detect_traps(prev_d, n_d) || detect_pagelimit(lspc - n_v)) {
- sprintf(cmd, "%c&", c_ec);
- if (!ren_cnl) /* prevent unwanted newlines */
- in_push(cmd, NULL);
- if (!ren_traps(prev_d, n_d, 0))
- ren_pagelimit(lspc - n_v);
+ if (!ren_pagelimit(lspc - n_v))
+ ren_traps(prev_d, n_d, 0);
return 1;
}
if (lspc - n_v && down(lspc - n_v))
@@ -453,6 +455,8 @@
void tr_ne(char **args)
{
int n = args[1] ? eval(args[1], 'v') : n_v;
+ if (!ren_first())
+ return;
if (!ren_traps(n_d, n_d + n - 1, 1))
ren_pagelimit(n);
}
@@ -955,20 +959,21 @@
}
}
if (c >= 0)
- ren_cnl = c == '\n';
+ ren_partial = c != '\n';
/* add wb (the current word) to cfmt */
if (c == ' ' || c == '\n') {
if (!wb_part(wb)) { /* not after a \c */
while (fmt_word(cfmt, wb))
ren_fmtpop(cfmt);
+ wb_reset(wb);
if (c == '\n')
while (fmt_newline(cfmt))
ren_fmtpop(cfmt);
- if (c == ' ')
- fmt_space(cfmt);
- wb_reset(wb);
if (!(n_j & AD_P))
ren_fmtpopall(cfmt);
+ ren_fmtpop(cfmt);
+ if (c == ' ')
+ fmt_space(cfmt);
}
}
/* flush the line if necessary */
--- a/roff.h
+++ b/roff.h
@@ -309,6 +309,7 @@
void fmt_free(struct fmt *fmt);
int fmt_wid(struct fmt *fmt);
void fmt_space(struct fmt *fmt);
+void fmt_suppressnl(struct fmt *fmt);
int fmt_word(struct fmt *fmt, struct wb *wb);
int fmt_newline(struct fmt *fmt);
int fmt_fillreq(struct fmt *f);