draw: draw.c is now independent of framebuffer depth
[cnoor.git] / txtwin.c
blob38b1d75c61dd26905cade31081038c205e83cd50
1 #include <ctype.h>
2 #include <errno.h>
3 #include <fcntl.h>
4 #include <locale.h>
5 #include <poll.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <sys/wait.h>
10 #include <pty.h>
12 #include <glib.h>
13 #include <pango/pango.h>
14 #include <pango/pangoft2.h>
16 #include "draw.h"
17 #include "util.h"
18 #include "config.h"
20 #define MAXTEXT (1 << 20)
21 #define DPI 196
22 #define PAGESTEPS 8
23 #define CTRLKEY(x) ((x) - 96)
25 struct txtwin {
26 int n;
29 static struct {
30 char name[1 << 4];
31 char desc[1 << 8];
32 } tags[1 << 4] = {
33 {"default", "<span size=\"xx-small\">"}
35 static int ntags = 1;
37 static char name[128];
38 static PangoContext *context;
39 static int width = 1;
40 static int height = 1;
41 static int head;
42 static PangoFontMap *fontmap;
43 static FT_Bitmap *bitmap;
44 static char text[MAXTEXT];
45 static char *pos = text;
46 static int count;
48 static FT_Bitmap *create_bitmap(int width, int height)
50 FT_Bitmap *bitmap = g_slice_new(FT_Bitmap);
51 bitmap->width = width;
52 bitmap->pitch = (bitmap->width + 3) & ~3;
53 bitmap->rows = height;
54 bitmap->buffer = g_malloc(bitmap->pitch * bitmap->rows);
55 bitmap->num_grays = 256;
56 bitmap->pixel_mode = ft_pixel_mode_grays;
57 memset(bitmap->buffer, 0, bitmap->pitch * bitmap->rows);
58 return bitmap;
61 static void destroy_bitmap(FT_Bitmap *bitmap)
63 g_free(bitmap->buffer);
64 g_slice_free(FT_Bitmap, bitmap);
67 #define COLORMERGE(f, b, c) ((b) + (((f) - (b)) * (c) >> 8u))
69 static void view_write(int sr)
71 int r, c;
72 fbval_t buf[1 << 14];
73 int nr = MIN(height - sr, fb_rows());
74 int nc = MIN(width, fb_cols());
75 for (r = 0; r < nr; r++) {
76 for (c = 0; c < nc; c++) {
77 int v = bitmap->buffer[(sr + r) * bitmap->pitch + c];
78 int r = COLORMERGE(0xd5, 0x00, 255 - v);
79 int g = COLORMERGE(0xdd, 0x00, 255 - v);
80 int b = COLORMERGE(0xff, 0x00, 255 - v);
81 buf[c] = fb_val(r, g, b);
83 fb_set(r, 0, buf, width);
87 static PangoLayout *make_layout(PangoContext *context, char *text, double size)
89 static PangoFontDescription *font_description;
90 PangoLayout *layout = pango_layout_new(context);
91 pango_layout_set_markup(layout, text, -1);
92 pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
93 pango_layout_set_width(layout, fb_cols() << 10);
94 pango_layout_set_height(layout, -1);
95 pango_layout_set_alignment(layout, PANGO_ALIGN_RIGHT);
96 pango_layout_set_font_description(layout, font_description);
97 pango_font_description_free(font_description);
98 return layout;
101 static void do_output(PangoContext *context, char *text)
103 PangoLayout *layout;
104 PangoRectangle logical_rect;
105 pango_context_set_language(context, pango_language_get_default());
106 pango_context_set_base_dir(context, PANGO_DIRECTION_RTL);
107 layout = make_layout(context, text, -1);
108 pango_layout_get_pixel_extents(layout, NULL, &logical_rect);
109 pango_ft2_render_layout(bitmap, layout, 0, 0);
110 width = MAX(width, MAX(logical_rect.x + logical_rect.width,
111 PANGO_PIXELS(pango_layout_get_width(layout))));
112 height = MAX(logical_rect.y + logical_rect.height,
113 PANGO_PIXELS(pango_layout_get_height(layout)));
114 g_object_unref(layout);
117 static int readkey(void)
119 char b;
120 if (read(STDIN_FILENO, &b, 1) <= 0)
121 return -1;
122 return b;
125 void txtwin_append(char *s, char *tag)
127 int i;
128 int t = 0;
129 for (i = 0; i < ntags; i++)
130 if (tag && !strcmp(tag, tags[i].name))
131 t = i;
132 snprintf(pos, MAXTEXT - (pos - text),
133 "%s%s</span>", tags[t].desc, s);
134 pos = strchr(pos, '\0');
137 void txtwin_tag(char *name, char *fg, char *bg, char *font)
139 strcpy(tags[ntags].name, name);
140 snprintf(tags[ntags].desc, sizeof(tags[ntags].desc),
141 "<span font=\"%s\">", font);
142 ntags++;
145 static int getcount(int def)
147 int result = count ? count : def;
148 count = 0;
149 return result;
152 static void printinfo(void)
154 printf("\x1b[H");
155 printf("CNOOR \t\t\t %d%% \t\t\t %s \x1b[K",
156 head * 100 / height, name);
157 fflush(stdout);
160 void txtwin_loop(void)
162 int step = fb_rows() / PAGESTEPS;
163 int c;
164 struct termios oldtermios, termios;
165 tcgetattr(STDIN_FILENO, &termios);
166 oldtermios = termios;
167 cfmakeraw(&termios);
168 tcsetattr(STDIN_FILENO, TCSAFLUSH, &termios);
169 bitmap = create_bitmap(width, height);
170 do_output(context, text);
171 destroy_bitmap(bitmap);
172 bitmap = create_bitmap(width, height);
173 do_output(context, text);
174 view_write(head);
175 while ((c = readkey()) != -1) {
176 switch (c) {
177 case 27:
178 count = 0;
179 break;
180 case 'q':
181 tcsetattr(STDIN_FILENO, 0, &oldtermios);
182 return;
183 default:
184 if (isdigit(c))
185 count = count * 10 + c - '0';
187 switch (c) {
188 case 'j':
189 head += step * getcount(1);
190 break;
191 case 'k':
192 head -= step * getcount(1);
193 break;
194 case CTRLKEY('f'):
195 case ' ':
196 head += fb_rows() * getcount(1) - step;
197 break;
198 case CTRLKEY('b'):
199 case 127:
200 head -= fb_rows() * getcount(1) - step;
201 break;
202 case CTRLKEY('l'):
203 break;
204 case 'G':
205 if (getcount(0))
206 head = 0;
207 else
208 head = height - fb_rows();
209 break;
210 case '%':
211 if (count)
212 head = height * getcount(0) / 100;
213 break;
214 case 'i':
215 printinfo();
216 continue;
217 default:
218 /* no need to redraw */
219 continue;
221 head = MAX(0, MIN(head, height - fb_rows()));
222 view_write(head);
226 void txtwin_gtk_init(int argc, char **argv)
228 g_type_init();
229 g_set_prgname("cpan");
230 setlocale(LC_ALL, "");
233 void txtwin_init(char *sura)
235 char *clear = "\x1b[2J\x1b[H";
236 char *hide = "\x1b[?25l";
237 fontmap = pango_ft2_font_map_new();
238 pango_ft2_font_map_set_resolution(PANGO_FT2_FONT_MAP(fontmap), DPI, DPI);
239 context = pango_font_map_create_context(PANGO_FONT_MAP(fontmap));
240 strcpy(name, sura);
241 if (fb_init())
242 exit(1);
243 if (FBM_BPP(fb_mode()) != sizeof(fbval_t)) {
244 fprintf(stderr, "cnoor: fbval_t doesn't match fb depth\n");
245 exit(1);
247 write(STDIN_FILENO, clear, strlen(clear));
248 write(STDIN_FILENO, hide, strlen(hide));
249 printinfo();
252 void txtwin_free(void)
254 char *show = "\x1b[?25h\n";
255 fb_free();
256 destroy_bitmap(bitmap);
257 g_object_unref(context);
258 g_object_unref(fontmap);
259 write(STDIN_FILENO, show, strlen(show));