fix maxleft calculation
[fbpdf.git] / fbpdf.c
blobe15b3253502bbc67cbcb5af571e82dc678e88457
1 #include <ctype.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <unistd.h>
6 #include <pty.h>
7 #include <cairo/cairo.h>
8 #include <glib/poppler.h>
9 #include "draw.h"
11 #define PAGESTEPS 8
12 #define CTRLKEY(x) ((x) - 96)
13 #define MAXAREA 2
15 static PopplerDocument *doc;
16 static PopplerPage *page;
17 static int num;
18 static cairo_t *cairo;
19 static cairo_surface_t *surface;
20 static int zoom = 15;
21 static int head;
22 static int left;
23 static int count;
25 static void draw()
27 unsigned char *img = cairo_image_surface_get_data(surface);
28 fbval_t slice[1 << 14];
29 int i, j;
30 int h = MIN(fb_rows(), cairo_image_surface_get_height(surface));
31 int w = MIN(fb_cols(), cairo_image_surface_get_width(surface));
32 int cols = cairo_image_surface_get_width(surface);
33 for (i = head; i < h + head; i++) {
34 for (j = left; j < w + left; j++) {
35 unsigned char *p = img + (i * cols + j) * 4;
36 slice[j - left] = fb_color(*p, *(p + 1), *(p + 2));
38 fb_set(i - head, 0, slice, w);
42 static int load_document(char *filename)
44 char abspath[PATH_MAX];
45 char uri[PATH_MAX + 16];
46 realpath(filename, abspath);
47 snprintf(uri, sizeof(uri), "file://%s", abspath);
48 doc = poppler_document_new_from_file(uri, NULL, NULL);
49 return !doc;
52 static void cleanup_page(void)
54 if (cairo)
55 cairo_destroy(cairo);
56 if (surface)
57 cairo_surface_destroy(surface);
58 if (page)
59 g_object_unref(G_OBJECT(page));
62 static void showpage(int p)
64 if (p < 0 || p >= poppler_document_get_n_pages(doc))
65 return;
66 cleanup_page();
67 surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
68 fb_cols() * MAXAREA, fb_rows() * MAXAREA);
69 cairo = cairo_create(surface);
70 cairo_scale(cairo, (float) zoom / 10, (float) zoom / 10);
71 cairo_set_source_rgb(cairo, 1.0, 1.0, 1.0);
72 cairo_paint(cairo);
73 num = p;
74 page = poppler_document_get_page(doc, p);
75 poppler_page_render(page, cairo);
76 head = 0;
77 draw();
80 static int readkey(void)
82 unsigned char b;
83 if (read(STDIN_FILENO, &b, 1) <= 0)
84 return -1;
85 return b;
88 static int getcount(int def)
90 int result = count ? count : def;
91 count = 0;
92 return result;
95 static void mainloop()
97 int step = fb_rows() / PAGESTEPS;
98 int hstep = fb_cols() / PAGESTEPS;
99 struct termios oldtermios, termios;
100 int maxhead, maxleft;
101 int c;
102 tcgetattr(STDIN_FILENO, &termios);
103 oldtermios = termios;
104 cfmakeraw(&termios);
105 tcsetattr(STDIN_FILENO, TCSAFLUSH, &termios);
106 showpage(0);
107 while ((c = readkey()) != -1) {
108 maxhead = cairo_image_surface_get_height(surface) - fb_rows();
109 maxleft = cairo_image_surface_get_width(surface) - fb_cols();
110 switch (c) {
111 case 'j':
112 head += step * getcount(1);
113 break;
114 case 'k':
115 head -= step * getcount(1);
116 break;
117 case 'l':
118 left += hstep * getcount(1);
119 break;
120 case 'h':
121 left -= hstep * getcount(1);
122 break;
123 case 'H':
124 head = 0;
125 break;
126 case 'L':
127 head = maxhead;
128 break;
129 case 'M':
130 head = maxhead / 2;
131 break;
132 case ' ':
133 head += fb_rows() * getcount(1) - step;
134 break;
135 case '\b':
136 head -= fb_rows() * getcount(1) - step;
137 break;
138 case CTRLKEY('f'):
139 case 'J':
140 showpage(num + getcount(1));
141 break;
142 case CTRLKEY('b'):
143 case 'K':
144 showpage(num - getcount(1));
145 break;
146 case 'G':
147 showpage(getcount(poppler_document_get_n_pages(doc)) - 1);
148 break;
149 case 'z':
150 zoom = getcount(15);
151 showpage(num);
152 break;
153 case 'q':
154 tcsetattr(STDIN_FILENO, 0, &oldtermios);
155 return;
156 case 27:
157 count = 0;
158 break;
159 default:
160 if (isdigit(c))
161 count = count * 10 + c - '0';
163 head = MAX(0, MIN(maxhead, head));
164 left = MAX(0, MIN(maxleft, left));
165 draw();
169 int main(int argc, char* argv[])
171 char *clear = "\x1b[2J\x1b[H";
172 char *msg = "\t\t\t\t---FBPDF---\n";
173 char *hide = "\x1b[?25l";
174 char *show = "\x1b[?25h";
175 if (argc < 2) {
176 printf("usage: fbpdf filename\n");
177 return 1;
179 g_type_init();
180 if (load_document(argv[1])) {
181 printf("cannot open file\n");
182 return 1;
184 write(STDIN_FILENO, clear, strlen(clear));
185 write(STDIN_FILENO, msg, strlen(msg));
186 write(STDIN_FILENO, hide, strlen(hide));
187 fb_init();
188 mainloop();
189 cleanup_page();
190 fb_free();
191 if (doc)
192 g_object_unref(G_OBJECT(doc));
193 write(STDIN_FILENO, show, strlen(show));
194 return 0;