font: don't segfault if font is wider than specified
[fbpad.git] / pad.c
blobff0575d89599c8bf25d9c89d000741e2362e736b
1 #include <ctype.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include "draw.h"
6 #include "font.h"
7 #include "util.h"
8 #include "pad.h"
10 #define SQRADDR(r, c) (&screen[(r) * cols + (c)])
12 static int rows, cols;
13 static int fg, bg;
15 static struct square screen[MAXCHARS];
17 static unsigned int cd[] = {
18 0x0a0a0a, 0xc04444, 0x339933, 0xcccc66,
19 0x5566bc, 0xcd66af, 0xa166cd, 0xeeeeee,
20 0x71a3b7, 0xc08888, 0x779977, 0xcccc99,
21 0x8899bc, 0xcd99af, 0xa199cd, 0xdedede};
23 void pad_init(void)
25 fb_init();
26 font_init();
27 rows = fb_rows() / font_rows();
28 cols = fb_cols() / font_cols();
31 void pad_free(void)
33 fb_free();
36 #define CR(a) (((a) >> 16) & 0x0000ff)
37 #define CG(a) (((a) >> 8) & 0x0000ff)
38 #define CB(a) ((a) & 0x0000ff)
39 #define COLORMERGE(f, b, c) ((b) + (((f) - (b)) * (c) >> 8u))
41 static u16_t mixed_color(int fg, int bg, u8_t val)
43 unsigned int fore = cd[fg], back = cd[bg];
44 u8_t r = COLORMERGE(CR(fore), CR(back), val);
45 u8_t g = COLORMERGE(CG(fore), CG(back), val);
46 u8_t b = COLORMERGE(CB(fore), CB(back), val);
47 return fb_color(r, g, b);
50 static u16_t color2fb(int c)
52 return mixed_color(fg, c, 0);
55 void pad_fg(int c)
57 fg = c;
60 void pad_bg(int c)
62 bg = c;
65 void pad_show(int r, int c, int reverse)
67 int sr = font_rows() * r;
68 int sc = font_cols() * c;
69 struct square *sqr = SQRADDR(r, c);
70 int fgcolor = sqr->c ? sqr->fg : fg;
71 int bgcolor = sqr->c ? sqr->bg : bg;
72 int i;
73 char *bits;
74 if (reverse) {
75 int t = bgcolor;
76 bgcolor = fgcolor;
77 fgcolor = t;
79 fb_box(sr, sc, sr + font_rows(), sc + font_cols(), color2fb(bgcolor));
80 if (!isprint(sqr->c))
81 return;
82 bits = font_bitmap(sqr->c, 0);
83 for (i = 0; i < font_rows() * font_cols(); i++)
84 if (bits[i])
85 fb_put(sr + i / font_cols(), sc + i % font_cols(),
86 mixed_color(fgcolor, bgcolor, bits[i]));
89 void pad_put(int ch, int r, int c)
91 struct square *sqr = SQRADDR(r, c);
92 if (!ch || !strchr("\a\b\f\n\r\v", ch)) {
93 sqr->c = ch;
94 sqr->fg = fg;
95 sqr->bg = bg;
97 pad_show(r, c, 0);
100 static void pad_empty(int sr, int er)
102 memset(SQRADDR(sr, 0), 0, (er - sr) * sizeof(screen[0]) * cols);
105 void pad_scroll(int sr, int nr, int n)
107 fb_scroll(sr * font_rows(), nr * font_rows(),
108 n * font_rows(), color2fb(bg));
109 memmove(SQRADDR(sr + n, 0), SQRADDR(sr, 0),
110 nr * cols * sizeof(screen[0]));
111 if (n > 0)
112 pad_empty(sr, sr + n);
113 else
114 pad_empty(sr + nr + n, sr + nr);
117 void pad_blank(void)
119 fb_box(0, 0, fb_rows(), fb_cols(), color2fb(bg));
120 memset(screen, 0, sizeof(screen));
123 int pad_rows(void)
125 return rows;
128 int pad_cols(void)
130 return cols;
133 void pad_save(struct pad_state *state)
135 state->fg = fg;
136 state->bg = bg;
137 memcpy(state->screen, screen, rows * cols * sizeof(screen[0]));
140 void pad_load(struct pad_state *state)
142 int i;
143 fg = state->fg;
144 bg = state->bg;
145 memcpy(screen, state->screen, rows * cols * sizeof(screen[0]));
146 for (i = 0; i < rows * cols; i++)
147 pad_show(i / cols, i % cols, 0);