ref: fab9c27fa0b1d53979eb6718015928784a097ed8
parent: 7e51746ad98afe340fb62e9ea196d77414401fd7
author: Ali Gholami Rudi <ali@rudi.ir>
date: Sat Jul 6 21:03:12 EDT 2013
clr: set text color with \m[#rgb]
--- a/Makefile
+++ b/Makefile
@@ -5,7 +5,7 @@
all: roff
%.o: %.c roff.h
$(CC) -c $(CFLAGS) $<
-roff: roff.o dev.o font.o in.o cp.o tr.o ren.o out.o reg.o sbuf.o adj.o eval.o draw.o wb.o hyph.o map.o
+roff: roff.o dev.o font.o in.o cp.o tr.o ren.o out.o reg.o sbuf.o adj.o eval.o draw.o wb.o hyph.o map.o clr.o
$(CC) -o $@ $^ $(LDFLAGS)
clean:
rm -f *.o roff
--- /dev/null
+++ b/clr.c
@@ -1,0 +1,56 @@
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "roff.h"
+
+/* returns a static buffer */
+char *clr_str(int c)
+{
+ static char clr_buf[32];
+ if (!c)
+ return "0";
+ sprintf(clr_buf, "#%02x%02x%02x", CLR_R(c), CLR_G(c), CLR_B(c));
+ return clr_buf;
+}
+
+static struct color {
+ char *name;
+ int value;
+} colors[] = {
+ {"black", CLR_RGB(0, 0, 0)},
+ {"red", CLR_RGB(0xff, 0, 0)},
+ {"green", CLR_RGB(0, 0xff, 0)},
+ {"yellow", CLR_RGB(0xff, 0xff, 0)},
+ {"blue", CLR_RGB(0, 0, 0xff)},
+ {"magenta", CLR_RGB(0xff, 0, 0xff)},
+ {"cyan", CLR_RGB(0, 0xff, 0xff)},
+ {"white", CLR_RGB(0xff, 0xff, 0xff)},
+};
+
+/* read color component */
+static int clrcomp(char *s, int len)
+{
+ static char *digs = "0123456789abcdef";
+ int n = 0;
+ int i;
+ for (i = 0; i < len; i++)
+ if (strchr(digs, tolower(s[i])))
+ n = n * 16 + (strchr(digs, tolower(s[i])) - digs);
+ return len == 1 ? n << 4 : n;
+}
+
+int clr_get(char *s)
+{
+ int i;
+ if (s[0] == '#' && strlen(s) == 7)
+ return CLR_RGB(clrcomp(s + 1, 2), clrcomp(s + 3, 2), clrcomp(s + 5, 2));
+ if (s[0] == '#' && strlen(s) == 4)
+ return CLR_RGB(clrcomp(s + 1, 1), clrcomp(s + 2, 1), clrcomp(s + 3, 1));
+ if (isdigit(s[0]) && atoi(s) >= 0 && atoi(s) < LEN(colors))
+ return colors[atoi(s)].value;
+ for (i = 0; i < LEN(colors); i++)
+ if (!strcmp(colors[i].name, s))
+ return colors[i].value;
+ return 0;
+}
--- a/out.c
+++ b/out.c
@@ -190,7 +190,7 @@
*r++ = *(*s)++;
if (**s == ']')
(*s)++;
- } else if (strchr("CDfhsvXx", d[1])) {
+ } else if (strchr("CDfhmsvXx", d[1])) {
int c = d[1];
escarg(s, d, d[1]);
return c == 'C' ? 0 : c;
@@ -231,6 +231,10 @@
break;
case 'h':
outnn("h%d", eval(c, 'm'));
+ break;
+ case 'm':
+ if (!n_cp)
+ out("m%s\n", clr_str(clr_get(c)));
break;
case 's':
out_ps(eval_re(c, o_s, '\0'));
--- a/reg.c
+++ b/reg.c
@@ -31,6 +31,7 @@
REG('.', 'j'),
REG('.', 'l'),
REG('.', 'L'),
+ REG('.', 'm'),
REG('.', 's'),
REG('.', 'u'),
REG('.', 'v'),
@@ -41,6 +42,7 @@
REG(0, 'l'),
REG(0, 'L'),
REG(0, 'n'),
+ REG(0, 'm'),
REG(0, 's'),
REG(0, 't'),
REG(0, 'T'),
--- a/ren.c
+++ b/ren.c
@@ -485,6 +485,13 @@
}
}
+static void ren_m(char *s)
+{
+ int m = !s || !*s ? n_m0 : clr_get(s);
+ n_m0 = n_m;
+ n_m = m;
+}
+
static void escarg_ren(char *d, int cmd, int (*next)(void), void (*back)(int))
{
char delim[GNLEN];
@@ -574,6 +581,9 @@
case 'l':
ren_hline(wb, arg);
break;
+ case 'm':
+ ren_m(arg);
+ break;
case 'o':
ren_over(wb, arg);
break;
@@ -672,7 +682,7 @@
ren_transparent(arg);
}
return;
- } else if (strchr(" bCcDdfhkLloprsuvXxz0^|{}&", c[1])) {
+ } else if (strchr(" bCcDdfhkLlmoprsuvXxz0^|{}&", c[1])) {
escarg_ren(arg, c[1], next, back);
if (c[1] != 'C') {
ren_cmd(wb, c[1], arg);
--- a/roff.h
+++ b/roff.h
@@ -29,7 +29,7 @@
/* escape sequences */
#define ESC_Q "bCDhHlLNoSvwxX" /* quoted escape sequences */
-#define ESC_P "*fgkns" /* 1 or 2-char escape sequences */
+#define ESC_P "*fgkmns" /* 1 or 2-char escape sequences */
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) < (b) ? (b) : (a))
@@ -175,8 +175,8 @@
/* word buffer */
struct wb {
struct sbuf sbuf;
- int f, s; /* the last output font and size */
- int r_f, r_s; /* current font and size; use n_f and n_s if -1 */
+ int f, s, m; /* the last output font and size */
+ int r_f, r_s, r_m; /* current font and size; use n_f and n_s if -1 */
int part; /* partial input (\c) */
int els_neg, els_pos; /* extra line spacing */
int h, v; /* buffer vertical and horizontal positions */
@@ -308,6 +308,15 @@
#define NREGS2 (NREGS * 2)
#define REG(c1, c2) ((c1) * 256 + (c2))
+/* colors */
+#define CLR_R(c) (((c) >> 16) & 0xff)
+#define CLR_G(c) (((c) >> 8) & 0xff)
+#define CLR_B(c) ((c) & 0xff)
+#define CLR_RGB(r, g, b) (((r) << 16) | ((g) << 8) | (b))
+
+char *clr_str(int c);
+int clr_get(char *s);
+
/* builtin number registers; n_X for .X register */
#define n_a (*nreg(REG('.', 'a')))
#define n_cp (*nreg(REG('.', 'C')))
@@ -319,6 +328,7 @@
#define n_l (*nreg(REG('.', 'l')))
#define n_L (*nreg(REG('.', 'L')))
#define n_n (*nreg(REG('.', 'n')))
+#define n_m (*nreg(REG('.', 'm')))
#define n_o (*nreg(REG('.', 'o')))
#define n_p (*nreg(REG('.', 'p')))
#define n_s (*nreg(REG('.', 's')))
@@ -340,7 +350,8 @@
#define n_kn (*nreg(REG(0, 'k'))) /* .kn mode */
#define n_l0 (*nreg(REG(0, 'l'))) /* last .l */
#define n_L0 (*nreg(REG(0, 'L'))) /* last .L */
-#define n_mk (*nreg(REG(0, 'm'))) /* .mk internal register */
+#define n_m0 (*nreg(REG(0, 'm'))) /* last .m */
+#define n_mk (*nreg(REG(0, 'M'))) /* .mk internal register */
#define n_na (*nreg(REG(0, 'n'))) /* .na mode */
#define n_ns (*nreg(REG(0, 'N'))) /* .ns mode */
#define n_o0 (*nreg(REG(0, 'o'))) /* last .o */
--- a/wb.c
+++ b/wb.c
@@ -5,6 +5,7 @@
#define R_F(wb) ((wb)->r_f >= 0 ? (wb)->r_f : n_f) /* current font */
#define R_S(wb) ((wb)->r_s >= 0 ? (wb)->r_s : n_s) /* current size */
+#define R_M(wb) ((wb)->r_m >= 0 ? (wb)->r_m : n_m) /* current color */
void wb_init(struct wb *wb)
{
@@ -12,8 +13,10 @@
sbuf_init(&wb->sbuf);
wb->f = -1;
wb->s = -1;
+ wb->m = -1;
wb->r_f = -1;
wb->r_s = -1;
+ wb->r_m = -1;
}
void wb_done(struct wb *wb)
@@ -39,6 +42,10 @@
sbuf_printf(&wb->sbuf, "%cs(%02d", c_ec, R_S(wb));
wb->s = R_S(wb);
}
+ if (!n_cp && wb->m != R_M(wb)) {
+ sbuf_printf(&wb->sbuf, "%cm[%s]", c_ec, clr_str(R_M(wb)));
+ wb->m = R_M(wb);
+ }
wb_stsb(wb);
}
@@ -217,6 +224,9 @@
case 'h':
wb_hmov(wb, atoi(s));
break;
+ case 'm':
+ wb->r_m = clr_get(s);
+ break;
case 's':
wb->r_s = atoi(s);
break;
@@ -242,6 +252,7 @@
part = src->part;
wb->r_s = -1;
wb->r_f = -1;
+ wb->r_m = -1;
wb_reset(src);
src->part = part;
}
@@ -364,6 +375,7 @@
wb_putc(w1, 0, "hy");
w2->r_s = w1->r_s;
w2->r_f = w1->r_f;
+ w2->r_m = w1->r_m;
while ((c = out_readc(&s, d)) >= 0)
wb_putc(w2, c, d);
}