term: enable switching signals using the second argument of term_exec()
[fbpad.git] / pad.c
blob5226831038106e6c31703c66f7053172d670c63f
1 #include <ctype.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include "conf.h"
6 #include "draw.h"
7 #include "fbpad.h"
9 static int fbroff, fbcoff, fbrows, fbcols;
10 static int rows, cols;
11 static int fnrows, fncols;
12 static int bpp;
13 static struct font *fonts[3];
15 static int gc_init(void);
16 static void gc_free(void);
18 int pad_init(void)
20 if (pad_font(FR, FI, FB))
21 return 1;
22 if (gc_init())
23 return 1;
24 rows = fb_rows() / fnrows;
25 cols = fb_cols() / fncols;
26 bpp = FBM_BPP(fb_mode());
27 pad_conf(0, 0, fb_rows(), fb_cols());
28 return 0;
31 void pad_conf(int roff, int coff, int _rows, int _cols)
33 fbroff = roff;
34 fbcoff = coff;
35 fbrows = _rows;
36 fbcols = _cols;
37 rows = fbrows / fnrows;
38 cols = fbcols / fncols;
41 void pad_free(void)
43 int i;
44 gc_free();
45 for (i = 0; i < 3; i++)
46 if (fonts[i])
47 font_free(fonts[i]);
50 #define CR(a) (((a) >> 16) & 0x0000ff)
51 #define CG(a) (((a) >> 8) & 0x0000ff)
52 #define CB(a) ((a) & 0x0000ff)
53 #define COLORMERGE(f, b, c) ((b) + (((f) - (b)) * (c) >> 8u))
55 static unsigned mixed_color(int fg, int bg, unsigned val)
57 unsigned char r = COLORMERGE(CR(fg), CR(bg), val);
58 unsigned char g = COLORMERGE(CG(fg), CG(bg), val);
59 unsigned char b = COLORMERGE(CB(fg), CB(bg), val);
60 return FB_VAL(r, g, b);
63 static unsigned color2fb(int c)
65 return FB_VAL(CR(c), CG(c), CB(c));
68 /* glyph bitmap cache: use CGLCNT lists of size CGLLEN each */
69 #define GCLCNT (1 << 7) /* glyph cache list count */
70 #define GCLLEN (1 << 4) /* glyph cache list length */
71 #define GCGLEN (fnrows * fncols * 4) /* bytes to store a glyph */
72 #define GCN (GCLCNT * GCLLEN) /* total glpyhs */
73 #define GCIDX(c) ((c) & (GCLCNT - 1))
75 static char *gc_mem; /* cached glyph's memory */
76 static int gc_next[GCLCNT]; /* the next slot to use in each list */
77 static int gc_glyph[GCN]; /* cached glyphs */
78 static int gc_bg[GCN];
79 static int gc_fg[GCN];
81 static int gc_init(void)
83 gc_mem = malloc(GCLCNT * GCLLEN * GCGLEN);
84 return !gc_mem;
87 static void gc_free(void)
89 free(gc_mem);
92 static char *gc_get(int c, int fg, int bg)
94 int idx = GCIDX(c) * GCLLEN;
95 int i;
96 for (i = idx; i < idx + GCLLEN; i++)
97 if (gc_glyph[i] == c && gc_fg[i] == fg && gc_bg[i] == bg)
98 return gc_mem + i * GCGLEN;
99 return NULL;
102 static char *gc_put(int c, int fg, int bg)
104 int lst = GCIDX(c);
105 int pos = gc_next[lst]++;
106 int idx = lst * GCLLEN + pos;
107 if (gc_next[lst] >= GCLLEN)
108 gc_next[lst] = 0;
109 gc_glyph[idx] = c;
110 gc_fg[idx] = fg;
111 gc_bg[idx] = bg;
112 return gc_mem + idx * GCGLEN;
115 static void bmp2fb(char *d, char *s, int fg, int bg, int nr, int nc)
117 int i, j, k;
118 for (i = 0; i < fnrows; i++) {
119 char *p = d + i * fncols * bpp;
120 for (j = 0; j < fncols; j++) {
121 unsigned v = i < nr && j < nc ?
122 (unsigned char) s[i * nc + j] : 0;
123 unsigned c = mixed_color(fg, bg, v);
124 for (k = 0; k < bpp; k++) /* little-endian */
125 *p++ = (c >> (k * 8)) & 0xff;
130 static char *ch2fb(int fn, int c, int fg, int bg)
132 static char bits[1024 * 4];
133 char *fbbits;
134 if (c < 0 || (c < 128 && (!isprint(c) || isspace(c))))
135 return NULL;
136 if ((fbbits = gc_get(c, fg, bg)))
137 return fbbits;
138 if (font_bitmap(fonts[fn], bits, c))
139 return NULL;
140 fbbits = gc_put(c, fg, bg);
141 bmp2fb(fbbits, bits, fg & FN_C, bg & FN_C,
142 font_rows(fonts[fn]), font_cols(fonts[fn]));
143 return fbbits;
146 static void fb_set(int r, int c, void *mem, int len)
148 memcpy(fb_mem(fbroff + r) + (fbcoff + c) * bpp, mem, len * bpp);
151 static char *rowbuf(unsigned c, int len)
153 static char row[32 * 1024];
154 char *p = row;
155 int i, k;
156 for (i = 0; i < len; i++)
157 for (k = 0; k < bpp; k++) /* little-endian */
158 *p++ = (c >> (k * 8)) & 0xff;
159 return row;
162 static void fb_box(int sr, int er, int sc, int ec, unsigned val)
164 char *row = rowbuf(val, ec - sc);
165 int i;
166 for (i = sr; i < er; i++)
167 fb_set(i, sc, row, ec - sc);
170 void pad_border(unsigned c, int wid)
172 int v = color2fb(c & FN_C);
173 if (fbroff < wid || fbcoff < wid)
174 return;
175 fb_box(-wid, 0, -wid, fbcols + wid, v);
176 fb_box(fbrows, fbrows + wid, -wid, fbcols + wid, v);
177 fb_box(-wid, fbrows + wid, -wid, 0, v);
178 fb_box(-wid, fbrows + wid, fbcols, fbcols + wid, v);
181 static int fnsel(int fg, int bg)
183 if ((fg | bg) & FN_B)
184 return fonts[2] ? 2 : 0;
185 if ((fg | bg) & FN_I)
186 return fonts[1] ? 1 : 0;
187 return 0;
190 void pad_put(int ch, int r, int c, int fg, int bg)
192 int sr = fnrows * r;
193 int sc = fncols * c;
194 char *bits;
195 int i;
196 bits = ch2fb(fnsel(fg, bg), ch, fg, bg);
197 if (!bits)
198 bits = ch2fb(0, ch, fg, bg);
199 if (!bits)
200 fb_box(sr, sr + fnrows, sc, sc + fncols, color2fb(bg & FN_C));
201 else
202 for (i = 0; i < fnrows; i++)
203 fb_set(sr + i, sc, bits + (i * fncols * bpp), fncols);
206 void pad_fill(int sr, int er, int sc, int ec, int c)
208 int fber = er >= 0 ? er * fnrows : fbrows;
209 int fbec = ec >= 0 ? ec * fncols : fbcols;
210 fb_box(sr * fnrows, fber, sc * fncols, fbec, color2fb(c & FN_C));
213 int pad_rows(void)
215 return rows;
218 int pad_cols(void)
220 return cols;
223 int pad_font(char *fr, char *fi, char *fb)
225 struct font *r = fr ? font_open(fr) : NULL;
226 if (!r)
227 return 1;
228 fonts[0] = r;
229 fonts[1] = fi ? font_open(fi) : NULL;
230 fonts[2] = fb ? font_open(fb) : NULL;
231 fnrows = font_rows(fonts[0]);
232 fncols = font_cols(fonts[0]);
233 return 0;
236 char *pad_fbdev(void)
238 static char fbdev[1024];
239 snprintf(fbdev, sizeof(fbdev), "FBDEV=%s:%dx%d%+d%+d",
240 fb_dev(), fbcols, fbrows, fbcoff, fbroff);
241 return fbdev;
244 /* character height */
245 int pad_crows(void)
247 return fnrows;
250 /* character width */
251 int pad_ccols(void)
253 return fncols;