term: cast characters read from the pty to unsigned char
[fbpad.git] / pad.c
blob1f4d8c4b6c2a256b3093beab1eec2d9e2588b01b
1 #include <ctype.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include "config.h"
6 #include "draw.h"
7 #include "font.h"
8 #include "util.h"
9 #include "pad.h"
11 #define NCACHE (1 << 11)
12 #define MAXFBWIDTH (1 << 12)
14 static unsigned int cd[] = {
15 COLOR0, COLOR1, COLOR2, COLOR3,
16 COLOR4, COLOR5, COLOR6, COLOR7,
17 COLOR8, COLOR9, COLOR10, COLOR11,
18 COLOR12, COLOR13, COLOR14, COLOR15};
19 static int rows, cols;
20 static int fnrows, fncols;
21 static struct font *fonts[3];
23 int pad_init(void)
25 int i;
26 char *paths[] = {FR, FI, FB};
27 if (fb_init())
28 return 1;
29 if (sizeof(fbval_t) != FBM_BPP(fb_mode())) {
30 fprintf(stderr, "pad_init: fbval_t doesn't match fb depth\n");
31 return 1;
33 for (i = 0; i < 3; i++)
34 fonts[i] = paths[i] ? font_open(paths[i]) : NULL;
35 if (!fonts[0]) {
36 fprintf(stderr, "pad: bad font <%s>\n", paths[0]);
37 return -1;
39 fnrows = font_rows(fonts[0]);
40 fncols = font_cols(fonts[0]);
41 rows = fb_rows() / fnrows;
42 cols = fb_cols() / fncols;
43 return 0;
46 void pad_free(void)
48 int i;
49 for (i = 0; i < 3; i++)
50 if (fonts[i])
51 font_free(fonts[i]);
52 fb_free();
55 #define CR(a) (((a) >> 16) & 0x0000ff)
56 #define CG(a) (((a) >> 8) & 0x0000ff)
57 #define CB(a) ((a) & 0x0000ff)
58 #define COLORMERGE(f, b, c) ((b) + (((f) - (b)) * (c) >> 8u))
60 static unsigned mixed_color(int fg, int bg, unsigned val)
62 unsigned int fore = cd[fg], back = cd[bg];
63 unsigned char r = COLORMERGE(CR(fore), CR(back), val);
64 unsigned char g = COLORMERGE(CG(fore), CG(back), val);
65 unsigned char b = COLORMERGE(CB(fore), CB(back), val);
66 return FB_VAL(r, g, b);
69 static unsigned color2fb(int c)
71 return FB_VAL(CR(cd[c]), CG(cd[c]), CB(cd[c]));
74 static fbval_t cache[NCACHE][MAXDOTS];
75 static struct glyph {
76 int c;
77 short fg, bg;
78 } glyphs[NCACHE];
80 static struct glyph *glyph_entry(int c, int fg, int bg)
82 return &glyphs[((c - 32) ^ (fg << 6) ^ (bg << 5)) & (NCACHE - 1)];
85 static fbval_t *glyph_cache(int c, short fg, short bg)
87 struct glyph *g = glyph_entry(c, fg, bg);
88 if (g->c == c && g->fg == fg && g->bg == bg)
89 return cache[g - glyphs];
90 return NULL;
93 static fbval_t *glyph_add(int c, short fg, short bg)
95 struct glyph *g = glyph_entry(c, fg, bg);
96 g->c = c;
97 g->fg = fg;
98 g->bg = bg;
99 return cache[g - glyphs];
102 static void bmp2fb(fbval_t *d, char *s, int fg, int bg, int nr, int nc)
104 int i, j;
105 for (i = 0; i < fnrows; i++) {
106 for (j = 0; j < fncols; j++) {
107 unsigned v = i < nr && j < nc ?
108 (unsigned char) s[i * nc + j] : 0;
109 d[i * fncols + j] = mixed_color(fg, bg, v);
114 static fbval_t *ch2fb(int fn, int c, short fg, short bg)
116 char bits[MAXDOTS];
117 fbval_t *fbbits;
118 if (c < 0 || (c < 128 && (!isprint(c) || isspace(c))))
119 return NULL;
120 if ((fbbits = glyph_cache(c, fg, bg)))
121 return fbbits;
122 if (font_bitmap(fonts[fn], bits, c))
123 return NULL;
124 fbbits = glyph_add(c, fg, bg);
125 bmp2fb(fbbits, bits, FN_C(fg), FN_C(bg),
126 font_rows(fonts[fn]), font_cols(fonts[fn]));
127 return fbbits;
130 static void fb_box(int sr, int sc, int er, int ec, fbval_t val)
132 static fbval_t line[MAXFBWIDTH];
133 int cn = ec - sc;
134 int i;
135 for (i = 0; i < cn; i++)
136 line[i] = val;
137 for (i = sr; i < er; i++)
138 fb_set(i, sc, line, cn);
141 static int fnsel(int fg, int bg)
143 if ((fg | bg) & FN_B)
144 return fonts[2] ? 2 : 0;
145 if ((fg | bg) & FN_I)
146 return fonts[1] ? 1 : 0;
147 return 0;
150 void pad_put(int ch, int r, int c, int fg, int bg)
152 int sr = fnrows * r;
153 int sc = fncols * c;
154 int i;
155 fbval_t *bits = ch2fb(fnsel(fg, bg), ch, fg, bg);
156 if (!bits)
157 bits = ch2fb(0, ch, fg, bg);
158 if (!bits)
159 fb_box(sr, sc, sr + fnrows, sc + fncols, color2fb(FN_C(bg)));
160 else
161 for (i = 0; i < fnrows; i++)
162 fb_set(sr + i, sc, bits + (i * fncols), fncols);
165 void pad_blank(int c)
167 fb_box(0, 0, fb_rows(), fb_cols(), color2fb(FN_C(c)));
170 void pad_blankrow(int r, int bg)
172 int sr = r * fnrows;
173 int er = r == rows - 1 ? fb_rows() : (r + 1) * fnrows;
174 fb_box(sr, 0, er, fb_cols(), color2fb(FN_C(bg)));
177 int pad_rows(void)
179 return rows;
182 int pad_cols(void)
184 return cols;