pad: redraw the cursor after scrolling
[fbpad.git] / pad.c
blobce6012da04d8c3b33bfe3ae5aecdd660a7575f74
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"
9 #define MAXSQUARES 1 << 15
10 #define SQRADDR(r, c) (&screen[(r) * cols + (c)])
12 static int rows, cols;
13 static int row, col;
14 static int fg, bg;
16 static struct square {
17 int c;
18 int fg;
19 int bg;
20 } screen[MAXSQUARES];
22 static unsigned int cd[] = {
23 0x0a0a0a, 0xc04444, 0x339933, 0xcccc66,
24 0x5566bc, 0xcd66af, 0xa166cd, 0xeeeeee,
25 0x71a3b7, 0xc08888, 0x779977, 0xcccc99,
26 0x8899bc, 0xcd99af, 0xa199cd, 0xdedede};
28 void pad_init(void)
30 fb_init();
31 font_init();
32 rows = fb_rows() / font_rows();
33 cols = fb_cols() / font_cols();
36 void pad_free(void)
38 fb_free();
41 #define CR(a) (((a) >> 16) & 0x0000ff)
42 #define CG(a) (((a) >> 8) & 0x0000ff)
43 #define CB(a) ((a) & 0x0000ff)
44 #define COLORMERGE(f, b, c) ((b) + (((f) - (b)) * (c) >> 8u))
46 static u16_t mixed_color(int fg, int bg, u8_t val)
48 unsigned int fore = cd[fg], back = cd[bg];
49 u8_t r = COLORMERGE(CR(fore), CR(back), val);
50 u8_t g = COLORMERGE(CG(fore), CG(back), val);
51 u8_t b = COLORMERGE(CB(fore), CB(back), val);
52 return fb_color(r, g, b);
55 static u16_t color2fb(int c)
57 return mixed_color(fg, c, 0);
60 void pad_fg(int c)
62 fg = c;
65 void pad_bg(int c)
67 bg = c;
70 static void pad_show(int r, int c, int reverse)
72 int sr = font_rows() * r;
73 int sc = font_cols() * c;
74 struct square *sqr = SQRADDR(r, c);
75 int fgcolor = sqr->c ? sqr->fg : fg;
76 int bgcolor = sqr->c ? sqr->bg : bg;
77 int i;
78 char *bits;
79 if (reverse) {
80 int t = bgcolor;
81 bgcolor = fgcolor;
82 fgcolor = t;
84 fb_box(sr, sc, sr + font_rows(), sc + font_cols(), color2fb(bgcolor));
85 if (!isprint(sqr->c))
86 return;
87 bits = font_bitmap(sqr->c, 0);
88 for (i = 0; i < font_rows() * font_cols(); i++)
89 if (bits[i])
90 fb_put(sr + i / font_cols(), sc + i % font_cols(),
91 mixed_color(fgcolor, bgcolor, bits[i]));
94 void pad_put(int ch, int r, int c)
96 struct square *sqr = SQRADDR(r, c);
97 if (!ch || !strchr("\a\b\f\n\r\v", ch)) {
98 sqr->c = ch;
99 sqr->fg = fg;
100 sqr->bg = bg;
102 pad_show(r, c, 0);
105 static void pad_empty(int sr, int er)
107 memset(SQRADDR(sr, 0), 0, (er - sr) * sizeof(screen[0]) * cols);
110 void pad_scroll(int sr, int nr, int n)
112 pad_show(row, col, 0);
113 fb_scroll(sr * font_rows(), nr * font_rows(),
114 n * font_rows(), color2fb(bg));
115 memmove(SQRADDR(sr + n, 0), SQRADDR(sr, 0),
116 nr * cols * sizeof(screen[0]));
117 if (n > 0)
118 pad_empty(sr, sr + n);
119 else
120 pad_empty(sr + nr + n, sr + nr);
121 pad_show(row, col, 1);
124 static void advance(int c)
126 switch (c) {
127 case '\n':
128 row++;
129 col = 0;
130 break;
131 case '\t':
132 col = (col / 8 + 1) * 8;
133 break;
134 case '\b':
135 if (col)
136 col--;
137 break;
138 case '\r':
139 col = 0;
140 break;
141 case '\a':
142 case '\f':
143 case '\v':
144 break;
145 default:
146 col++;
148 if (col >= cols) {
149 row++;
150 col = 0;
152 if (row >= rows) {
153 int n = rows - row - 1;
154 int nr = rows + n;
155 row = rows - 1;
156 pad_scroll(-n, nr, n);
160 void pad_add(int c)
162 pad_put(c, row, col);
163 advance(c);
164 pad_show(row, col, 1);
167 void pad_blank(void)
169 fb_box(0, 0, fb_rows(), fb_cols(), color2fb(bg));
170 memset(screen, 0, sizeof(screen));
173 void pad_move(int r, int c)
175 pad_show(row, col, 0);
176 row = MIN(r, rows - 1);
177 col = MIN(c, cols - 1);
178 pad_show(row, col, 1);
181 int pad_row(void)
183 return row;
186 int pad_col(void)
188 return col;
191 int pad_rows(void)
193 return rows;
196 int pad_cols(void)
198 return cols;