ref: 7127cb9afb7ff6e609b6b9b3cecf3705bdeb5cf7
parent: 96f08d8dc0198c6c1ac478349ed76398c5cf7401
author: Ali Gholami Rudi <ali@rudi.ir>
date: Sat Nov 17 17:23:45 EST 2012
filling output lines
--- a/dev.c
+++ b/dev.c
@@ -126,9 +126,9 @@
/* glyph handling functions */
-struct glyph *dev_glyph(char *c)
+struct glyph *dev_glyph(char *c, int fn)
{
- struct glyph *g = font_find(fn_font[n_f], c);
+ struct glyph *g = font_find(fn_font[fn], c);
int i;
if (g)
return g;
@@ -139,9 +139,9 @@
return NULL;
}
-struct glyph *dev_glyph_byid(char *id)
+struct glyph *dev_glyph_byid(char *id, int fn)
{
- return font_glyph(fn_font[n_f], id);
+ return font_glyph(fn_font[fn], id);
}
struct glyph *dev_ligature(char **s, int n)
--- a/out.c
+++ b/out.c
@@ -1,10 +1,24 @@
+#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "xroff.h"
-static int out_blank = 0;
+#define LINELEN 1024
+struct word {
+ int beg; /* word beginning offset in buf */
+ int end; /* word ending offset in buf */
+ int wid; /* word width */
+ int blanks; /* blanks before word */
+};
+
+static char buf[LINELEN]; /* output buffer */
+static int buflen;
+static struct word words[LINELEN]; /* words in the buffer */
+static int nwords;
+static int wid; /* total width of the buffer */
+
static int utf8len(int c)
{
if (c <= 0x7f)
@@ -33,34 +47,156 @@
for (i = 1; i < l; i++)
s[i] = tr_next();
s[l] = '\0';
+ memcpy(buf + buflen, s, l + 1);
+ buflen += l;
return l;
}
-static void out_sp(int n)
+static char *utf8get(char *d, char *s)
{
+ int l = utf8len(*s);
+ int i;
+ for (i = 0; i < l; i++)
+ d[i] = s[i];
+ d[l] = '\0';
+ return s + l;
+}
+
+static char *readint(char *s, int *d)
+{
+ *d = 0;
+ while (isdigit(*s))
+ *d = *d * 10 + *s++ - '0';
+ return s;
+}
+
+static int o_s, o_f;
+
+static void flush(char *s)
+{
+ struct glyph *g;
+ char c[LLEN];
+ int o_blank = 0;
printf("H%d", n_o + n_i);
- printf("v%d\n", n_v * (n + 1));
- out_blank = 0;
+ while (*s) {
+ s = utf8get(c, s);
+ if (c[0] == '\\') {
+ s = utf8get(c, s);
+ if (c[0] == 's') {
+ s = readint(s, &o_s);
+ printf("s%d\n", o_s);
+ continue;
+ }
+ if (c[0] == 'f') {
+ s = readint(s, &o_f);
+ printf("f%d\n", o_f);
+ continue;
+ }
+ if (c[0] == '(') {
+ s = utf8get(c, s);
+ s = utf8get(c + strlen(c), s);
+ }
+ }
+ g = dev_glyph(c, o_f);
+ if (g) {
+ if (o_blank)
+ printf("h%d", dev_spacewid() * o_s / dev_uwid);
+ if (utf8len(c[0]) == strlen(c)) {
+ printf("c%s%s", c, c[1] ? "\n" : "");
+ } else {
+ printf("C%s\n", c);
+ }
+ printf("h%d", g->wid * o_s / dev_uwid);
+ o_blank = 0;
+ } else {
+ o_blank = 1;
+ }
+ }
}
+static void down(int n)
+{
+ printf("v%d\n", n);
+}
+
+static void adjust(char *s)
+{
+ struct word *last = words;
+ int w = 0;
+ int lendiff;
+ int i;
+ while (last < words + nwords && w + last->wid + last->blanks <= n_l) {
+ w += last->wid + last->blanks;
+ last++;
+ }
+ if (last > words)
+ last--;
+ memcpy(s, buf, last->end);
+ s[last->end] = '\0';
+ lendiff = last + 1 < words + nwords ? last[1].beg : buflen;
+ memmove(buf, buf + lendiff, buflen - lendiff);
+ buflen -= lendiff;
+ nwords -= last - words + 1;
+ memmove(words, last + 1, nwords * sizeof(words[0]));
+ wid -= w;
+ for (i = 0; i < nwords; i++) {
+ words[i].beg -= lendiff;
+ words[i].end -= lendiff;
+ }
+ if (nwords)
+ wid -= words[0].blanks;
+ words[0].blanks = 0;
+}
+
void tr_br(int argc, char **args)
{
- out_sp(0);
+ char out[LINELEN];
+ buf[buflen] = '\0';
+ if (buflen) {
+ adjust(out);
+ flush(out);
+ down(n_v);
+ }
+ o_s = n_s;
+ o_f = n_f;
}
void tr_sp(int argc, char **args)
{
- out_sp(argc > 1 ? atoi(args[1]) : 1);
+ tr_br(0, NULL);
+ if (argc > 1)
+ down(n_v * atoi(args[1]));
}
+void tr_ps(int argc, char **args)
+{
+ if (argc >= 2)
+ n_s = atoi(args[1]);
+ buflen += sprintf(buf + buflen, "\\s%d", n_s);
+}
+
+void tr_ft(int argc, char **args)
+{
+ int fn;
+ if (argc < 2)
+ return;
+ fn = dev_font(args[1]);
+ if (fn >= 0)
+ n_f = fn;
+ buflen += sprintf(buf + buflen, "\\f%d", n_f);
+}
+
void render(void)
{
char c[LLEN];
struct glyph *g;
- int fp = n_f;
- int ps = n_s;
+ struct word *word = NULL;
+ int word_beg;
+ int blanks = 0;
+ tr_br(0, NULL);
while (nextchar(c) > 0) {
g = NULL;
+ word_beg = buflen - strlen(c);
if (c[0] == '\\') {
nextchar(c);
if (c[0] == '(') {
@@ -69,27 +205,24 @@
c[l] = '\0';
}
}
- g = dev_glyph(c);
- if (ps != n_s) {
- printf("s%d\n", n_s);
- ps = n_s;
+ g = dev_glyph(c, n_f);
+ if (!g) {
+ blanks = dev_spacewid() * n_s / dev_uwid;
+ word = NULL;
+ continue;
}
- if (fp != n_f) {
- printf("f%d\n", n_f);
- fp = n_f;
+ if (!word) {
+ word = &words[nwords++];
+ word->beg = word_beg;
+ word->wid = 0;
+ word->blanks = blanks;
+ wid += blanks;
}
- if (g) {
- if (out_blank)
- printf("h%d", dev_spacewid() * n_s / dev_uwid);
- if (utf8len(c[0]) == strlen(c)) {
- printf("c%s%s", c, c[1] ? "\n" : "");
- } else {
- printf("C%s\n", c);
- }
- printf("h%d", g->wid * n_s / dev_uwid);
- out_blank = 0;
- } else {
- out_blank = 1;
- }
+ word->end = buflen;
+ word->wid += g->wid * n_s / dev_uwid;
+ wid += g->wid * n_s / dev_uwid;
+ if (wid > n_l)
+ tr_br(0, NULL);
}
+ tr_br(0, NULL);
}
--- a/tr.c
+++ b/tr.c
@@ -10,20 +10,10 @@
static int tr_nl = 1;
-static void tr_ft(int argc, char **args)
+static void tr_ll(int argc, char **args)
{
- int fn;
- if (argc < 2)
- return;
- fn = dev_font(args[1]);
- if (fn >= 0)
- n_f = fn;
-}
-
-static void tr_ps(int argc, char **args)
-{
if (argc >= 2)
- n_s = atoi(args[1]);
+ n_l = atoi(args[1]) * SC_PT;
}
static void tr_vs(int argc, char **args)
@@ -32,16 +22,10 @@
n_v = atoi(args[1]) * SC_PT;
}
-static void tr_ll(int argc, char **args)
-{
- if (argc >= 2)
- n_v = atoi(args[1]) * SC_PT;
-}
-
static void tr_in(int argc, char **args)
{
if (argc >= 2)
- n_v = atoi(args[1]) * SC_PT;
+ n_i = atoi(args[1]) * SC_PT;
}
static void tr_readcmd(char *s)
@@ -92,8 +76,8 @@
{"ps", tr_ps},
{"sp", tr_sp},
{"vs", tr_vs},
- {"vs", tr_ll},
- {"vs", tr_in},
+ {"ll", tr_ll},
+ {"in", tr_in},
};
int tr_next(void)
--- a/xroff.h
+++ b/xroff.h
@@ -59,8 +59,8 @@
struct glyph *font_find(struct font *fn, char *name);
/* glyph handling functions */
-struct glyph *dev_glyph(char *c);
-struct glyph *dev_glyph_byid(char *id);
+struct glyph *dev_glyph(char *c, int fn);
+struct glyph *dev_glyph_byid(char *id, int fn);
int dev_spacewid(void);
/* different layers of neatroff */
@@ -79,3 +79,5 @@
void tr_br(int argc, char **args);
void tr_sp(int argc, char **args);
void tr_nr(int argc, char **args);
+void tr_ps(int argc, char **args);
+void tr_ft(int argc, char **args);