Rev 8436 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 8436 | Rev 8438 | ||
---|---|---|---|
1 | #include "fitz.h" |
1 | #include "fitz.h" |
2 | #include "mupdf.h" |
2 | #include "mupdf.h" |
3 | #include "pdfapp.h" |
3 | #include "pdfapp.h" |
4 | #include "kolibri.h" |
4 | #include "kolibri.h" |
5 | 5 | ||
6 | #include |
6 | #include |
7 | 7 | ||
8 | #define ZOOMSTEP 1.142857 |
8 | #define ZOOMSTEP 1.142857 |
9 | #define BEYOND_THRESHHOLD 40 |
9 | #define BEYOND_THRESHHOLD 40 |
10 | 10 | ||
11 | enum panning |
11 | enum panning |
12 | { |
12 | { |
13 | DONT_PAN = 0, |
13 | DONT_PAN = 0, |
14 | PAN_TO_TOP, |
14 | PAN_TO_TOP, |
15 | PAN_TO_BOTTOM |
15 | PAN_TO_BOTTOM |
16 | }; |
16 | }; |
17 | 17 | ||
18 | static void pdfapp_showpage(pdfapp_t *app, int loadpage, int drawpage, int repaint); |
18 | static void pdfapp_showpage(pdfapp_t *app, int loadpage, int drawpage, int repaint); |
19 | 19 | ||
20 | static void pdfapp_warn(pdfapp_t *app, const char *fmt, ...) |
20 | static void pdfapp_warn(pdfapp_t *app, const char *fmt, ...) |
21 | { |
21 | { |
22 | char buf[1024]; |
22 | char buf[1024]; |
23 | va_list ap; |
23 | va_list ap; |
24 | va_start(ap, fmt); |
24 | va_start(ap, fmt); |
25 | vsprintf(buf, fmt, ap); |
25 | vsprintf(buf, fmt, ap); |
26 | va_end(ap); |
26 | va_end(ap); |
27 | winwarn(app, buf); |
27 | winwarn(app, buf); |
28 | } |
28 | } |
29 | 29 | ||
30 | static void pdfapp_error(pdfapp_t *app, fz_error error) |
30 | static void pdfapp_error(pdfapp_t *app, fz_error error) |
31 | { |
31 | { |
32 | winerror(app, error); |
32 | winerror(app, error); |
33 | } |
33 | } |
34 | 34 | ||
35 | char *pdfapp_version(pdfapp_t *app) |
35 | char *pdfapp_version(pdfapp_t *app) |
36 | { |
36 | { |
37 | return |
37 | return |
38 | "MuPDF 0.9\n" |
38 | "MuPDF 0.9\n" |
39 | "Copyright 2006-2011 Artifex Sofware, Inc.\n"; |
39 | "Copyright 2006-2011 Artifex Sofware, Inc.\n"; |
40 | } |
40 | } |
41 | 41 | ||
42 | char *pdfapp_usage(pdfapp_t *app) |
42 | char *pdfapp_usage(pdfapp_t *app) |
43 | { |
43 | { |
44 | return " "; |
44 | return " "; |
45 | /* |
45 | /* |
46 | "L\t\t-- rotate left\n" |
46 | "L\t\t-- rotate left\n" |
47 | "R\t\t-- rotate right\n" |
47 | "R\t\t-- rotate right\n" |
48 | "h\t\t-- scroll left\n" |
48 | "h\t\t-- scroll left\n" |
49 | "j down\t\t-- scroll down\n" |
49 | "j down\t\t-- scroll down\n" |
50 | "k up\t\t-- scroll up\n" |
50 | "k up\t\t-- scroll up\n" |
51 | "l\t\t-- scroll right\n" |
51 | "l\t\t-- scroll right\n" |
52 | "+\t\t-- zoom in\n" |
52 | "+\t\t-- zoom in\n" |
53 | "-\t\t-- zoom out\n" |
53 | "-\t\t-- zoom out\n" |
54 | "w\t\t-- shrinkwrap\n" |
54 | "w\t\t-- shrinkwrap\n" |
55 | "r\t\t-- reload file\n" |
55 | "r\t\t-- reload file\n" |
56 | ". pgdn right space\t-- next page\n" |
56 | ". pgdn right space\t-- next page\n" |
57 | ", pgup left b\t-- previous page\n" |
57 | ", pgup left b\t-- previous page\n" |
58 | ">\t\t-- next 10 pages\n" |
58 | ">\t\t-- next 10 pages\n" |
59 | "<\t\t-- back 10 pages\n" |
59 | "<\t\t-- back 10 pages\n" |
60 | "m\t\t-- mark page for snap back\n" |
60 | "m\t\t-- mark page for snap back\n" |
61 | "t\t\t-- pop back to latest mark\n" |
61 | "t\t\t-- pop back to latest mark\n" |
62 | "1m\t\t-- mark page in register 1\n" |
62 | "1m\t\t-- mark page in register 1\n" |
63 | "1t\t\t-- go to page in register 1\n" |
63 | "1t\t\t-- go to page in register 1\n" |
64 | "123g\t\t-- go to page 123\n" |
64 | "123g\t\t-- go to page 123\n" |
65 | "/\t\t-- search for text\n" |
65 | "/\t\t-- search for text\n" |
66 | "n\t\t-- find next search result\n" |
66 | "n\t\t-- find next search result\n" |
67 | "N\t\t-- find previous search result\n" |
67 | "N\t\t-- find previous search result\n" |
68 | "c\t\t-- toggle between color and grayscale\n" |
68 | "c\t\t-- toggle between color and grayscale\n" |
69 | ; |
69 | ; |
70 | */ |
70 | */ |
71 | } |
71 | } |
72 | 72 | ||
73 | void pdfapp_init(pdfapp_t *app) |
73 | void pdfapp_init(pdfapp_t *app) |
74 | { |
74 | { |
75 | memset(app, 0, sizeof(pdfapp_t)); |
75 | memset(app, 0, sizeof(pdfapp_t)); |
76 | app->scrw = 640; |
76 | app->scrw = 640; |
77 | app->scrh = 480; |
77 | app->scrh = 480; |
78 | app->resolution = 72; |
78 | app->resolution = 72; |
79 | } |
79 | } |
80 | 80 | ||
81 | void pdfapp_invert(pdfapp_t *app, fz_bbox rect) |
81 | void pdfapp_invert(pdfapp_t *app, fz_bbox rect) |
82 | { |
82 | { |
83 | unsigned char *p; |
83 | unsigned char *p; |
84 | int x, y, n; |
84 | int x, y, n; |
85 | 85 | ||
86 | int x0 = CLAMP(rect.x0 - app->image->x, 0, app->image->w - 1); |
86 | int x0 = CLAMP(rect.x0 - app->image->x, 0, app->image->w - 1); |
87 | int x1 = CLAMP(rect.x1 - app->image->x, 0, app->image->w - 1); |
87 | int x1 = CLAMP(rect.x1 - app->image->x, 0, app->image->w - 1); |
88 | int y0 = CLAMP(rect.y0 - app->image->y, 0, app->image->h - 1); |
88 | int y0 = CLAMP(rect.y0 - app->image->y, 0, app->image->h - 1); |
89 | int y1 = CLAMP(rect.y1 - app->image->y, 0, app->image->h - 1); |
89 | int y1 = CLAMP(rect.y1 - app->image->y, 0, app->image->h - 1); |
90 | 90 | ||
91 | for (y = y0; y < y1; y++) |
91 | for (y = y0; y < y1; y++) |
92 | { |
92 | { |
93 | p = app->image->samples + (y * app->image->w + x0) * app->image->n; |
93 | p = app->image->samples + (y * app->image->w + x0) * app->image->n; |
94 | for (x = x0; x < x1; x++) |
94 | for (x = x0; x < x1; x++) |
95 | { |
95 | { |
96 | for (n = app->image->n; n > 0; n--, p++) |
96 | for (n = app->image->n; n > 0; n--, p++) |
97 | *p = 255 - *p; |
97 | *p = 255 - *p; |
98 | } |
98 | } |
99 | } |
99 | } |
100 | } |
100 | } |
101 | 101 | ||
102 | static void pdfapp_open_pdf(pdfapp_t *app, char *filename, int fd) |
102 | static void pdfapp_open_pdf(pdfapp_t *app, char *filename, int fd) |
103 | { |
103 | { |
104 | fz_error error; |
104 | fz_error error; |
105 | fz_stream *file; |
105 | fz_stream *file; |
106 | char *password = ""; |
106 | char *password = ""; |
107 | fz_obj *obj; |
107 | fz_obj *obj; |
108 | fz_obj *info; |
108 | fz_obj *info; |
109 | 109 | ||
110 | /* |
110 | /* |
111 | * Open PDF and load xref table |
111 | * Open PDF and load xref table |
112 | */ |
112 | */ |
113 | kol_board_puts("FZ OPEN\n"); |
113 | kol_board_puts("FZ OPEN\n"); |
114 | //file = fz_open_fd(fd); |
114 | //file = fz_open_fd(fd); |
115 | kol_board_puts("FZ ready\n"); |
115 | kol_board_puts("FZ ready\n"); |
116 | error = pdf_open_xref(&app->xref, filename, NULL); |
116 | error = pdf_open_xref(&app->xref, filename, NULL); |
117 | if (error){ |
117 | if (error){ |
118 | kol_board_puts("FZ can't open\n"); |
118 | kol_board_puts("FZ can't open\n"); |
119 | pdfapp_error(app, fz_rethrow(error, "cannot open document '%s'", filename));} |
119 | pdfapp_error(app, fz_rethrow(error, "cannot open document '%s'", filename));} |
120 | fz_close(file); |
120 | fz_close(file); |
121 | 121 | ||
122 | /* |
122 | /* |
123 | * Handle encrypted PDF files |
123 | * Handle encrypted PDF files |
124 | */ |
124 | */ |
125 | /* |
125 | /* |
126 | if (pdf_needs_password(app->xref)) |
126 | if (pdf_needs_password(app->xref)) |
127 | { |
127 | { |
128 | int okay = pdf_authenticate_password(app->xref, password); |
128 | int okay = pdf_authenticate_password(app->xref, password); |
129 | while (!okay) |
129 | while (!okay) |
130 | { |
130 | { |
131 | password = winpassword(app, filename); |
131 | password = winpassword(app, filename); |
132 | if (!password) |
132 | if (!password) |
133 | exit(1); |
133 | exit(1); |
134 | okay = pdf_authenticate_password(app->xref, password); |
134 | okay = pdf_authenticate_password(app->xref, password); |
135 | if (!okay) |
135 | if (!okay) |
136 | pdfapp_warn(app, "Invalid password."); |
136 | pdfapp_warn(app, "Invalid password."); |
137 | } |
137 | } |
138 | } |
138 | } |
139 | * */ |
139 | * */ |
140 | 140 | ||
141 | /* |
141 | /* |
142 | * Load meta information |
142 | * Load meta information |
143 | */ |
143 | */ |
144 | 144 | ||
145 | /* |
145 | /* |
146 | app->outline = pdf_load_outline(app->xref); |
146 | app->outline = pdf_load_outline(app->xref); |
147 | 147 | ||
148 | app->doctitle = filename; |
148 | app->doctitle = filename; |
149 | if (strrchr(app->doctitle, '\\')) |
149 | if (strrchr(app->doctitle, '\\')) |
150 | app->doctitle = strrchr(app->doctitle, '\\') + 1; |
150 | app->doctitle = strrchr(app->doctitle, '\\') + 1; |
151 | if (strrchr(app->doctitle, '/')) |
151 | if (strrchr(app->doctitle, '/')) |
152 | app->doctitle = strrchr(app->doctitle, '/') + 1; |
152 | app->doctitle = strrchr(app->doctitle, '/') + 1; |
153 | info = fz_dict_gets(app->xref->trailer, "Info"); |
153 | info = fz_dict_gets(app->xref->trailer, "Info"); |
154 | if (info) |
154 | if (info) |
155 | { |
155 | { |
156 | obj = fz_dict_gets(info, "Title"); |
156 | obj = fz_dict_gets(info, "Title"); |
157 | if (obj) |
157 | if (obj) |
158 | app->doctitle = pdf_to_utf8(obj); |
158 | app->doctitle = pdf_to_utf8(obj); |
159 | } */ |
159 | } */ |
160 | 160 | ||
161 | /* |
161 | /* |
162 | * Start at first page |
162 | * Start at first page |
163 | */ |
163 | */ |
164 | kol_board_puts("Start at first page\n"); |
164 | kol_board_puts("Start at first page\n"); |
165 | 165 | ||
166 | error = pdf_load_page_tree(app->xref); |
166 | error = pdf_load_page_tree(app->xref); |
167 | if (error) { |
167 | if (error) { |
168 | kol_board_puts("Can't load tree\n"); |
168 | kol_board_puts("Can't load tree\n"); |
169 | pdfapp_error(app, fz_rethrow(error, "cannot load page tree"));} |
169 | pdfapp_error(app, fz_rethrow(error, "cannot load page tree"));} |
170 | 170 | ||
171 | kol_board_puts("Page counter\n"); |
171 | kol_board_puts("Page counter\n"); |
172 | app->pagecount = pdf_count_pages(app->xref); |
172 | app->pagecount = pdf_count_pages(app->xref); |
173 | kol_board_puts("All is set!\n"); |
173 | kol_board_puts("All is set!\n"); |
174 | } |
174 | } |
175 | 175 | ||
176 | void pdfapp_open(pdfapp_t *app, char *filename, int fd, int reload) |
176 | void pdfapp_open(pdfapp_t *app, char *filename, int fd, int reload) |
177 | { |
177 | { |
178 | pdfapp_open_pdf(app, filename, fd); |
178 | pdfapp_open_pdf(app, filename, fd); |
179 | 179 | ||
180 | app->cache = fz_new_glyph_cache(); |
180 | app->cache = fz_new_glyph_cache(); |
181 | 181 | ||
182 | if (app->pageno < 1) |
182 | if (app->pageno < 1) |
183 | app->pageno = 1; |
183 | app->pageno = 1; |
184 | if (app->pageno > app->pagecount) |
184 | if (app->pageno > app->pagecount) |
185 | app->pageno = app->pagecount; |
185 | app->pageno = app->pagecount; |
186 | if (app->resolution < MINRES) |
186 | if (app->resolution < MINRES) |
187 | app->resolution = MINRES; |
187 | app->resolution = MINRES; |
188 | if (app->resolution > MAXRES) |
188 | if (app->resolution > MAXRES) |
189 | app->resolution = MAXRES; |
189 | app->resolution = MAXRES; |
190 | 190 | ||
191 | if (!reload) |
191 | if (!reload) |
192 | { |
192 | { |
193 | app->shrinkwrap = 1; |
193 | app->shrinkwrap = 1; |
194 | app->rotate = 0; |
194 | app->rotate = 0; |
195 | app->panx = 0; |
195 | app->panx = 0; |
196 | app->pany = 0; |
196 | app->pany = 0; |
197 | } |
197 | } |
198 | 198 | ||
199 | pdfapp_showpage(app, 1, 1, 1); |
199 | pdfapp_showpage(app, 1, 1, 1); |
200 | } |
200 | } |
201 | 201 | ||
202 | void pdfapp_close(pdfapp_t *app) |
202 | void pdfapp_close(pdfapp_t *app) |
203 | { |
203 | { |
204 | if (app->cache) |
204 | if (app->cache) |
205 | fz_free_glyph_cache(app->cache); |
205 | fz_free_glyph_cache(app->cache); |
206 | app->cache = NULL; |
206 | app->cache = NULL; |
207 | 207 | ||
208 | if (app->image) |
208 | if (app->image) |
209 | fz_drop_pixmap(app->image); |
209 | fz_drop_pixmap(app->image); |
210 | app->image = NULL; |
210 | app->image = NULL; |
211 | 211 | ||
212 | if (app->outline) |
212 | if (app->outline) |
213 | pdf_free_outline(app->outline); |
213 | pdf_free_outline(app->outline); |
214 | app->outline = NULL; |
214 | app->outline = NULL; |
215 | 215 | ||
216 | if (app->xref) |
216 | if (app->xref) |
217 | { |
217 | { |
218 | if (app->xref->store) |
218 | if (app->xref->store) |
219 | pdf_free_store(app->xref->store); |
219 | pdf_free_store(app->xref->store); |
220 | app->xref->store = NULL; |
220 | app->xref->store = NULL; |
221 | 221 | ||
222 | pdf_free_xref(app->xref); |
222 | pdf_free_xref(app->xref); |
223 | app->xref = NULL; |
223 | app->xref = NULL; |
224 | } |
224 | } |
225 | 225 | ||
226 | fz_flush_warnings(); |
226 | fz_flush_warnings(); |
227 | } |
227 | } |
228 | 228 | ||
229 | static fz_matrix pdfapp_viewctm(pdfapp_t *app) |
229 | static fz_matrix pdfapp_viewctm(pdfapp_t *app) |
230 | { |
230 | { |
231 | fz_matrix ctm; |
231 | fz_matrix ctm; |
232 | ctm = fz_identity; |
232 | ctm = fz_identity; |
233 | ctm = fz_concat(ctm, fz_translate(0, -app->page_bbox.y1)); |
233 | ctm = fz_concat(ctm, fz_translate(0, -app->page_bbox.y1)); |
234 | if (app->xref) |
234 | if (app->xref) |
235 | ctm = fz_concat(ctm, fz_scale(app->resolution/72.0f, -app->resolution/72.0f)); |
235 | ctm = fz_concat(ctm, fz_scale(app->resolution/72.0f, -app->resolution/72.0f)); |
236 | else |
236 | else |
237 | ctm = fz_concat(ctm, fz_scale(app->resolution/96.0f, app->resolution/96.0f)); |
237 | ctm = fz_concat(ctm, fz_scale(app->resolution/96.0f, app->resolution/96.0f)); |
238 | ctm = fz_concat(ctm, fz_rotate(app->rotate + app->page_rotate)); |
238 | ctm = fz_concat(ctm, fz_rotate(app->rotate + app->page_rotate)); |
239 | return ctm; |
239 | return ctm; |
240 | } |
240 | } |
241 | 241 | ||
242 | static void pdfapp_panview(pdfapp_t *app, int newx, int newy) |
242 | static void pdfapp_panview(pdfapp_t *app, int newx, int newy) |
243 | { |
243 | { |
244 | if (newx < 0) |
244 | if (newx < 0) |
245 | newx = 0; |
245 | newx = 0; |
246 | if (newy < 0) |
246 | if (newy < 0) |
247 | newy = 0; |
247 | newy = 0; |
248 | 248 | ||
249 | if (newx + app->image->w < app->winw) |
249 | if (newx + app->image->w < app->winw) |
250 | newx = app->winw - app->image->w; |
250 | newx = app->winw - app->image->w; |
251 | if (newy + app->image->h < app->winh) |
251 | if (newy + app->image->h < app->winh) |
252 | newy = app->winh - app->image->h; |
252 | newy = app->winh - app->image->h; |
253 | 253 | ||
254 | if (app->winw >= app->image->w) |
254 | if (app->winw >= app->image->w) |
255 | newx = (app->winw - app->image->w) / 2; |
255 | newx = (app->winw - app->image->w) / 2; |
256 | if (app->winh >= app->image->h) |
256 | if (app->winh >= app->image->h) |
257 | newy = (app->winh - app->image->h) / 2; |
257 | newy = (app->winh - app->image->h) / 2; |
258 | 258 | ||
259 | if (newx != app->panx || newy != app->pany) |
259 | if (newx != app->panx || newy != app->pany) |
260 | winrepaint(app); |
260 | winrepaint(app); |
261 | 261 | ||
262 | if (newy > app->image->h) { |
262 | if (newy > app->image->h) { |
263 | 263 | ||
264 | app->pageno++; |
264 | app->pageno++; |
265 | 265 | ||
266 | 266 | ||
267 | if (app->pageno > app->pagecount) |
267 | if (app->pageno > app->pagecount) |
268 | app->pageno = app->pagecount; |
268 | app->pageno = app->pagecount; |
269 | 269 | ||
270 | 270 | ||
271 | newy = 0; |
271 | newy = 0; |
272 | app->pany = newy; |
272 | app->pany = newy; |
273 | 273 | ||
274 | pdfapp_showpage(app, 1, 1, 1); |
274 | pdfapp_showpage(app, 1, 1, 1); |
275 | } |
275 | } |
276 | 276 | ||
277 | app->panx = newx; |
277 | app->panx = newx; |
278 | app->pany = newy; |
278 | app->pany = newy; |
279 | } |
279 | } |
280 | 280 | ||
281 | static void pdfapp_loadpage_pdf(pdfapp_t *app) |
281 | static void pdfapp_loadpage_pdf(pdfapp_t *app) |
282 | { |
282 | { |
283 | pdf_page *page; |
283 | pdf_page *page; |
284 | fz_error error; |
284 | fz_error error; |
285 | fz_device *mdev; |
285 | fz_device *mdev; |
286 | 286 | ||
287 | error = pdf_load_page(&page, app->xref, app->pageno - 1); |
287 | error = pdf_load_page(&page, app->xref, app->pageno - 1); |
288 | if (error) |
288 | if (error) |
289 | pdfapp_error(app, error); |
289 | pdfapp_error(app, error); |
290 | 290 | ||
291 | app->page_bbox = page->mediabox; |
291 | app->page_bbox = page->mediabox; |
292 | app->page_rotate = page->rotate; |
292 | app->page_rotate = page->rotate; |
293 | app->page_links = page->links; |
293 | app->page_links = page->links; |
294 | page->links = NULL; |
294 | page->links = NULL; |
295 | 295 | ||
296 | /* Create display list */ |
296 | /* Create display list */ |
297 | app->page_list = fz_new_display_list(); |
297 | app->page_list = fz_new_display_list(); |
298 | mdev = fz_new_list_device(app->page_list); |
298 | mdev = fz_new_list_device(app->page_list); |
299 | error = pdf_run_page(app->xref, page, mdev, fz_identity); |
299 | error = pdf_run_page(app->xref, page, mdev, fz_identity); |
300 | if (error) |
300 | if (error) |
301 | { |
301 | { |
302 | error = fz_rethrow(error, "cannot draw page %d in '%s'", app->pageno, app->doctitle); |
302 | error = fz_rethrow(error, "cannot draw page %d in '%s'", app->pageno, app->doctitle); |
303 | pdfapp_error(app, error); |
303 | pdfapp_error(app, error); |
304 | } |
304 | } |
305 | fz_free_device(mdev); |
305 | fz_free_device(mdev); |
306 | 306 | ||
307 | pdf_free_page(page); |
307 | pdf_free_page(page); |
308 | 308 | ||
309 | pdf_age_store(app->xref->store, 3); |
309 | pdf_age_store(app->xref->store, 3); |
310 | } |
310 | } |
311 | 311 | ||
312 | static void pdfapp_showpage(pdfapp_t *app, int loadpage, int drawpage, int repaint) |
312 | static void pdfapp_showpage(pdfapp_t *app, int loadpage, int drawpage, int repaint) |
313 | { |
313 | { |
314 | char buf[256]; |
314 | char buf[256]; |
315 | fz_device *idev; |
315 | fz_device *idev; |
316 | fz_device *tdev; |
316 | fz_device *tdev; |
317 | fz_colorspace *colorspace; |
317 | fz_colorspace *colorspace; |
318 | fz_matrix ctm; |
318 | fz_matrix ctm; |
319 | fz_bbox bbox; |
319 | fz_bbox bbox; |
320 | 320 | ||
321 | wincursor(app, WAIT); |
321 | wincursor(app, WAIT); |
322 | 322 | ||
323 | if (loadpage) |
323 | if (loadpage) |
324 | { |
324 | { |
325 | if (app->page_list) |
325 | if (app->page_list) |
326 | fz_free_display_list(app->page_list); |
326 | fz_free_display_list(app->page_list); |
327 | if (app->page_text) |
327 | if (app->page_text) |
328 | fz_free_text_span(app->page_text); |
328 | fz_free_text_span(app->page_text); |
329 | if (app->page_links) |
329 | if (app->page_links) |
330 | pdf_free_link(app->page_links); |
330 | pdf_free_link(app->page_links); |
331 | 331 | ||
332 | if (app->xref) |
332 | if (app->xref) |
333 | pdfapp_loadpage_pdf(app); |
333 | pdfapp_loadpage_pdf(app); |
334 | 334 | ||
335 | /* Zero search hit position */ |
335 | /* Zero search hit position */ |
336 | app->hit = -1; |
336 | app->hit = -1; |
337 | app->hitlen = 0; |
337 | app->hitlen = 0; |
338 | 338 | ||
339 | /* Extract text */ |
339 | /* Extract text */ |
340 | app->page_text = fz_new_text_span(); |
340 | app->page_text = fz_new_text_span(); |
341 | tdev = fz_new_text_device(app->page_text); |
341 | tdev = fz_new_text_device(app->page_text); |
342 | fz_execute_display_list(app->page_list, tdev, fz_identity, fz_infinite_bbox); |
342 | fz_execute_display_list(app->page_list, tdev, fz_identity, fz_infinite_bbox); |
343 | fz_free_device(tdev); |
343 | fz_free_device(tdev); |
344 | } |
344 | } |
345 | 345 | ||
346 | if (drawpage) |
346 | if (drawpage) |
347 | { |
347 | { |
348 | sprintf(buf, "%s - %d/%d (%d dpi)", app->doctitle, |
348 | sprintf(buf, "%s - %d/%d (%d dpi)", app->doctitle, |
349 | app->pageno, app->pagecount, app->resolution); |
349 | app->pageno, app->pagecount, app->resolution); |
350 | wintitle(app, buf); |
350 | /// wintitle(app, buf); |
351 | 351 | ||
352 | ctm = pdfapp_viewctm(app); |
352 | ctm = pdfapp_viewctm(app); |
353 | bbox = fz_round_rect(fz_transform_rect(ctm, app->page_bbox)); |
353 | bbox = fz_round_rect(fz_transform_rect(ctm, app->page_bbox)); |
354 | 354 | ||
355 | /* Draw */ |
355 | /* Draw */ |
356 | if (app->image) |
356 | if (app->image) |
357 | fz_drop_pixmap(app->image); |
357 | fz_drop_pixmap(app->image); |
358 | if (app->grayscale) |
358 | if (app->grayscale) |
359 | colorspace = fz_device_gray; |
359 | colorspace = fz_device_gray; |
360 | else |
360 | else |
361 | //#ifdef _WIN32 |
361 | //#ifdef _WIN32 |
362 | colorspace = fz_device_bgr; |
362 | colorspace = fz_device_bgr; |
363 | //#else |
363 | //#else |
364 | // colorspace = fz_device_rgb; |
364 | // colorspace = fz_device_rgb; |
365 | //#endif |
365 | //#endif |
366 | app->image = fz_new_pixmap_with_rect(colorspace, bbox); |
366 | app->image = fz_new_pixmap_with_rect(colorspace, bbox); |
367 | fz_clear_pixmap_with_color(app->image, 255); |
367 | fz_clear_pixmap_with_color(app->image, 255); |
368 | idev = fz_new_draw_device(app->cache, app->image); |
368 | idev = fz_new_draw_device(app->cache, app->image); |
369 | fz_execute_display_list(app->page_list, idev, ctm, bbox); |
369 | fz_execute_display_list(app->page_list, idev, ctm, bbox); |
370 | fz_free_device(idev); |
370 | fz_free_device(idev); |
371 | } |
371 | } |
372 | 372 | ||
373 | if (repaint) |
373 | if (repaint) |
374 | { |
374 | { |
375 | pdfapp_panview(app, app->panx, app->pany); |
375 | pdfapp_panview(app, app->panx, app->pany); |
376 | 376 | ||
377 | if (app->shrinkwrap) |
377 | if (app->shrinkwrap) |
378 | { |
378 | { |
379 | kol_board_puts ("SHRINK\n"); |
379 | kol_board_puts ("SHRINK\n"); |
380 | int w = app->image->w; |
380 | int w = app->image->w; |
381 | int h = app->image->h; |
381 | int h = app->image->h; |
382 | if (app->winw == w) |
382 | if (app->winw == w) |
383 | app->panx = 0; |
383 | app->panx = 0; |
384 | if (app->winh == h) |
384 | if (app->winh == h) |
385 | app->pany = 0; |
385 | app->pany = 0; |
386 | if (w > app->scrw * 90 / 100) |
386 | if (w > app->scrw * 90 / 100) |
387 | w = app->scrw * 90 / 100; |
387 | w = app->scrw * 90 / 100; |
388 | if (h > app->scrh * 90 / 100) |
388 | if (h > app->scrh * 90 / 100) |
389 | h = app->scrh * 90 / 100; |
389 | h = app->scrh * 90 / 100; |
390 | if (w != app->winw || h != app->winh) |
390 | if (w != app->winw || h != app->winh) |
391 | winresize(app, w, h); |
391 | winresize(app, w, h); |
392 | } |
392 | } |
393 | 393 | ||
394 | winrepaint(app); |
394 | winrepaint(app); |
395 | 395 | ||
396 | wincursor(app, ARROW); |
396 | wincursor(app, ARROW); |
397 | } |
397 | } |
398 | 398 | ||
399 | fz_flush_warnings(); |
399 | fz_flush_warnings(); |
400 | } |
400 | } |
401 | 401 | ||
402 | static void pdfapp_gotouri(pdfapp_t *app, fz_obj *uri) |
402 | static void pdfapp_gotouri(pdfapp_t *app, fz_obj *uri) |
403 | { |
403 | { |
404 | char *buf; |
404 | char *buf; |
405 | buf = fz_malloc(fz_to_str_len(uri) + 1); |
405 | buf = fz_malloc(fz_to_str_len(uri) + 1); |
406 | memcpy(buf, fz_to_str_buf(uri), fz_to_str_len(uri)); |
406 | memcpy(buf, fz_to_str_buf(uri), fz_to_str_len(uri)); |
407 | buf[fz_to_str_len(uri)] = 0; |
407 | buf[fz_to_str_len(uri)] = 0; |
408 | winopenuri(app, buf); |
408 | winopenuri(app, buf); |
409 | fz_free(buf); |
409 | fz_free(buf); |
410 | } |
410 | } |
411 | 411 | ||
412 | static void pdfapp_gotopage(pdfapp_t *app, fz_obj *obj) |
412 | static void pdfapp_gotopage(pdfapp_t *app, fz_obj *obj) |
413 | { |
413 | { |
414 | int number; |
414 | int number; |
415 | 415 | ||
416 | number = pdf_find_page_number(app->xref, obj); |
416 | number = pdf_find_page_number(app->xref, obj); |
417 | if (number < 0) |
417 | if (number < 0) |
418 | return; |
418 | return; |
419 | 419 | ||
420 | if (app->histlen + 1 == 256) |
420 | if (app->histlen + 1 == 256) |
421 | { |
421 | { |
422 | memmove(app->hist, app->hist + 1, sizeof(int) * 255); |
422 | memmove(app->hist, app->hist + 1, sizeof(int) * 255); |
423 | app->histlen --; |
423 | app->histlen --; |
424 | } |
424 | } |
425 | app->hist[app->histlen++] = app->pageno; |
425 | app->hist[app->histlen++] = app->pageno; |
426 | app->pageno = number + 1; |
426 | app->pageno = number + 1; |
427 | pdfapp_showpage(app, 1, 1, 1); |
427 | pdfapp_showpage(app, 1, 1, 1); |
428 | } |
428 | } |
429 | 429 | ||
430 | static inline fz_bbox bboxcharat(fz_text_span *span, int idx) |
430 | static inline fz_bbox bboxcharat(fz_text_span *span, int idx) |
431 | { |
431 | { |
432 | int ofs = 0; |
432 | int ofs = 0; |
433 | while (span) |
433 | while (span) |
434 | { |
434 | { |
435 | if (idx < ofs + span->len) |
435 | if (idx < ofs + span->len) |
436 | return span->text[idx - ofs].bbox; |
436 | return span->text[idx - ofs].bbox; |
437 | if (span->eol) |
437 | if (span->eol) |
438 | { |
438 | { |
439 | if (idx == ofs + span->len) |
439 | if (idx == ofs + span->len) |
440 | return fz_empty_bbox; |
440 | return fz_empty_bbox; |
441 | ofs ++; |
441 | ofs ++; |
442 | } |
442 | } |
443 | ofs += span->len; |
443 | ofs += span->len; |
444 | span = span->next; |
444 | span = span->next; |
445 | } |
445 | } |
446 | return fz_empty_bbox; |
446 | return fz_empty_bbox; |
447 | } |
447 | } |
448 | 448 | ||
449 | void pdfapp_inverthit(pdfapp_t *app) |
449 | void pdfapp_inverthit(pdfapp_t *app) |
450 | { |
450 | { |
451 | fz_bbox hitbox, bbox; |
451 | fz_bbox hitbox, bbox; |
452 | fz_matrix ctm; |
452 | fz_matrix ctm; |
453 | int i; |
453 | int i; |
454 | 454 | ||
455 | if (app->hit < 0) |
455 | if (app->hit < 0) |
456 | return; |
456 | return; |
457 | 457 | ||
458 | hitbox = fz_empty_bbox; |
458 | hitbox = fz_empty_bbox; |
459 | ctm = pdfapp_viewctm(app); |
459 | ctm = pdfapp_viewctm(app); |
460 | 460 | ||
461 | for (i = app->hit; i < app->hit + app->hitlen; i++) |
461 | for (i = app->hit; i < app->hit + app->hitlen; i++) |
462 | { |
462 | { |
463 | bbox = bboxcharat(app->page_text, i); |
463 | bbox = bboxcharat(app->page_text, i); |
464 | if (fz_is_empty_rect(bbox)) |
464 | if (fz_is_empty_rect(bbox)) |
465 | { |
465 | { |
466 | if (!fz_is_empty_rect(hitbox)) |
466 | if (!fz_is_empty_rect(hitbox)) |
467 | pdfapp_invert(app, fz_transform_bbox(ctm, hitbox)); |
467 | pdfapp_invert(app, fz_transform_bbox(ctm, hitbox)); |
468 | hitbox = fz_empty_bbox; |
468 | hitbox = fz_empty_bbox; |
469 | } |
469 | } |
470 | else |
470 | else |
471 | { |
471 | { |
472 | hitbox = fz_union_bbox(hitbox, bbox); |
472 | hitbox = fz_union_bbox(hitbox, bbox); |
473 | } |
473 | } |
474 | } |
474 | } |
475 | 475 | ||
476 | if (!fz_is_empty_rect(hitbox)) |
476 | if (!fz_is_empty_rect(hitbox)) |
477 | pdfapp_invert(app, fz_transform_bbox(ctm, hitbox)); |
477 | pdfapp_invert(app, fz_transform_bbox(ctm, hitbox)); |
478 | } |
478 | } |
479 | 479 | ||
480 | static inline int charat(fz_text_span *span, int idx) |
480 | static inline int charat(fz_text_span *span, int idx) |
481 | { |
481 | { |
482 | int ofs = 0; |
482 | int ofs = 0; |
483 | while (span) |
483 | while (span) |
484 | { |
484 | { |
485 | if (idx < ofs + span->len) |
485 | if (idx < ofs + span->len) |
486 | return span->text[idx - ofs].c; |
486 | return span->text[idx - ofs].c; |
487 | if (span->eol) |
487 | if (span->eol) |
488 | { |
488 | { |
489 | if (idx == ofs + span->len) |
489 | if (idx == ofs + span->len) |
490 | return ' '; |
490 | return ' '; |
491 | ofs ++; |
491 | ofs ++; |
492 | } |
492 | } |
493 | ofs += span->len; |
493 | ofs += span->len; |
494 | span = span->next; |
494 | span = span->next; |
495 | } |
495 | } |
496 | return 0; |
496 | return 0; |
497 | } |
497 | } |
498 | 498 | ||
499 | static int textlen(fz_text_span *span) |
499 | static int textlen(fz_text_span *span) |
500 | { |
500 | { |
501 | int len = 0; |
501 | int len = 0; |
502 | while (span) |
502 | while (span) |
503 | { |
503 | { |
504 | len += span->len; |
504 | len += span->len; |
505 | if (span->eol) |
505 | if (span->eol) |
506 | len ++; |
506 | len ++; |
507 | span = span->next; |
507 | span = span->next; |
508 | } |
508 | } |
509 | return len; |
509 | return len; |
510 | } |
510 | } |
511 | 511 | ||
512 | static int match(char *s, fz_text_span *span, int n) |
512 | static int match(char *s, fz_text_span *span, int n) |
513 | { |
513 | { |
514 | int orig = n; |
514 | int orig = n; |
515 | int c; |
515 | int c; |
516 | while ((c = *s++)) |
516 | while ((c = *s++)) |
517 | { |
517 | { |
518 | if (c == ' ' && charat(span, n) == ' ') |
518 | if (c == ' ' && charat(span, n) == ' ') |
519 | { |
519 | { |
520 | while (charat(span, n) == ' ') |
520 | while (charat(span, n) == ' ') |
521 | n++; |
521 | n++; |
522 | } |
522 | } |
523 | else |
523 | else |
524 | { |
524 | { |
525 | if (tolower(c) != tolower(charat(span, n))) |
525 | if (tolower(c) != tolower(charat(span, n))) |
526 | return 0; |
526 | return 0; |
527 | n++; |
527 | n++; |
528 | } |
528 | } |
529 | } |
529 | } |
530 | return n - orig; |
530 | return n - orig; |
531 | } |
531 | } |
532 | 532 | ||
533 | static void pdfapp_searchforward(pdfapp_t *app, enum panning *panto) |
533 | static void pdfapp_searchforward(pdfapp_t *app, enum panning *panto) |
534 | { |
534 | { |
535 | int matchlen; |
535 | int matchlen; |
536 | int test; |
536 | int test; |
537 | int len; |
537 | int len; |
538 | int startpage; |
538 | int startpage; |
539 | 539 | ||
540 | wincursor(app, WAIT); |
540 | wincursor(app, WAIT); |
541 | 541 | ||
542 | startpage = app->pageno; |
542 | startpage = app->pageno; |
543 | 543 | ||
544 | do |
544 | do |
545 | { |
545 | { |
546 | len = textlen(app->page_text); |
546 | len = textlen(app->page_text); |
547 | 547 | ||
548 | if (app->hit >= 0) |
548 | if (app->hit >= 0) |
549 | test = app->hit + strlen(app->search); |
549 | test = app->hit + strlen(app->search); |
550 | else |
550 | else |
551 | test = 0; |
551 | test = 0; |
552 | 552 | ||
553 | while (test < len) |
553 | while (test < len) |
554 | { |
554 | { |
555 | matchlen = match(app->search, app->page_text, test); |
555 | matchlen = match(app->search, app->page_text, test); |
556 | if (matchlen) |
556 | if (matchlen) |
557 | { |
557 | { |
558 | app->hit = test; |
558 | app->hit = test; |
559 | app->hitlen = matchlen; |
559 | app->hitlen = matchlen; |
560 | wincursor(app, HAND); |
560 | wincursor(app, HAND); |
561 | winrepaint(app); |
561 | winrepaint(app); |
562 | return; |
562 | return; |
563 | } |
563 | } |
564 | test++; |
564 | test++; |
565 | } |
565 | } |
566 | 566 | ||
567 | app->pageno++; |
567 | app->pageno++; |
568 | if (app->pageno > app->pagecount) |
568 | if (app->pageno > app->pagecount) |
569 | app->pageno = 1; |
569 | app->pageno = 1; |
570 | 570 | ||
571 | pdfapp_showpage(app, 1, 0, 0); |
571 | pdfapp_showpage(app, 1, 0, 0); |
572 | *panto = PAN_TO_TOP; |
572 | *panto = PAN_TO_TOP; |
573 | 573 | ||
574 | } while (app->pageno != startpage); |
574 | } while (app->pageno != startpage); |
575 | 575 | ||
576 | if (app->pageno == startpage) |
576 | if (app->pageno == startpage) |
577 | { |
577 | { |
578 | pdfapp_warn(app, "String '%s' not found.", app->search); |
578 | pdfapp_warn(app, "String '%s' not found.", app->search); |
579 | winrepaintsearch(app); |
579 | winrepaintsearch(app); |
580 | } |
580 | } |
581 | else |
581 | else |
582 | winrepaint(app); |
582 | winrepaint(app); |
583 | 583 | ||
584 | wincursor(app, HAND); |
584 | wincursor(app, HAND); |
585 | } |
585 | } |
586 | 586 | ||
587 | static void pdfapp_searchbackward(pdfapp_t *app, enum panning *panto) |
587 | static void pdfapp_searchbackward(pdfapp_t *app, enum panning *panto) |
588 | { |
588 | { |
589 | int matchlen; |
589 | int matchlen; |
590 | int test; |
590 | int test; |
591 | int len; |
591 | int len; |
592 | int startpage; |
592 | int startpage; |
593 | 593 | ||
594 | wincursor(app, WAIT); |
594 | wincursor(app, WAIT); |
595 | 595 | ||
596 | startpage = app->pageno; |
596 | startpage = app->pageno; |
597 | 597 | ||
598 | do |
598 | do |
599 | { |
599 | { |
600 | len = textlen(app->page_text); |
600 | len = textlen(app->page_text); |
601 | 601 | ||
602 | if (app->hit >= 0) |
602 | if (app->hit >= 0) |
603 | test = app->hit - 1; |
603 | test = app->hit - 1; |
604 | else |
604 | else |
605 | test = len; |
605 | test = len; |
606 | 606 | ||
607 | while (test >= 0) |
607 | while (test >= 0) |
608 | { |
608 | { |
609 | matchlen = match(app->search, app->page_text, test); |
609 | matchlen = match(app->search, app->page_text, test); |
610 | if (matchlen) |
610 | if (matchlen) |
611 | { |
611 | { |
612 | app->hit = test; |
612 | app->hit = test; |
613 | app->hitlen = matchlen; |
613 | app->hitlen = matchlen; |
614 | wincursor(app, HAND); |
614 | wincursor(app, HAND); |
615 | winrepaint(app); |
615 | winrepaint(app); |
616 | return; |
616 | return; |
617 | } |
617 | } |
618 | test--; |
618 | test--; |
619 | } |
619 | } |
620 | 620 | ||
621 | app->pageno--; |
621 | app->pageno--; |
622 | if (app->pageno < 1) |
622 | if (app->pageno < 1) |
623 | app->pageno = app->pagecount; |
623 | app->pageno = app->pagecount; |
624 | 624 | ||
625 | pdfapp_showpage(app, 1, 0, 0); |
625 | pdfapp_showpage(app, 1, 0, 0); |
626 | *panto = PAN_TO_BOTTOM; |
626 | *panto = PAN_TO_BOTTOM; |
627 | 627 | ||
628 | } while (app->pageno != startpage); |
628 | } while (app->pageno != startpage); |
629 | 629 | ||
630 | if (app->pageno == startpage) |
630 | if (app->pageno == startpage) |
631 | { |
631 | { |
632 | pdfapp_warn(app, "String '%s' not found.", app->search); |
632 | pdfapp_warn(app, "String '%s' not found.", app->search); |
633 | winrepaintsearch(app); |
633 | winrepaintsearch(app); |
634 | } |
634 | } |
635 | else |
635 | else |
636 | winrepaint(app); |
636 | winrepaint(app); |
637 | 637 | ||
638 | wincursor(app, HAND); |
638 | wincursor(app, HAND); |
639 | } |
639 | } |
640 | 640 | ||
641 | void pdfapp_onresize(pdfapp_t *app, int w, int h) |
641 | void pdfapp_onresize(pdfapp_t *app, int w, int h) |
642 | { |
642 | { |
643 | if (app->winw != w || app->winh != h) |
643 | if (app->winw != w || app->winh != h) |
644 | { |
644 | { |
645 | app->winw = w; |
645 | app->winw = w; |
646 | app->winh = h; |
646 | app->winh = h; |
647 | pdfapp_panview(app, app->panx, app->pany); |
647 | pdfapp_panview(app, app->panx, app->pany); |
648 | winrepaint(app); |
648 | winrepaint(app); |
649 | } |
649 | } |
650 | } |
650 | } |
651 | 651 | ||
652 | void pdfapp_onkey(pdfapp_t *app, int c) |
652 | void pdfapp_onkey(pdfapp_t *app, int c) |
653 | { |
653 | { |
654 | int oldpage = app->pageno; |
654 | int oldpage = app->pageno; |
655 | enum panning panto = PAN_TO_TOP; |
655 | enum panning panto = PAN_TO_TOP; |
656 | int loadpage = 1; |
656 | int loadpage = 1; |
657 | 657 | ||
658 | if (app->isediting) |
658 | if (app->isediting) |
659 | { |
659 | { |
660 | int n = strlen(app->search); |
660 | int n = strlen(app->search); |
661 | if (c < ' ') |
661 | if (c < ' ') |
662 | { |
662 | { |
663 | if (c == '\b' && n > 0) |
663 | if (c == '\b' && n > 0) |
664 | { |
664 | { |
665 | app->search[n - 1] = 0; |
665 | app->search[n - 1] = 0; |
666 | winrepaintsearch(app); |
666 | winrepaintsearch(app); |
667 | } |
667 | } |
668 | if (c == '\n' || c == '\r') |
668 | if (c == '\n' || c == '\r') |
669 | { |
669 | { |
670 | app->isediting = 0; |
670 | app->isediting = 0; |
671 | if (n > 0) |
671 | if (n > 0) |
672 | { |
672 | { |
673 | winrepaintsearch(app); |
673 | winrepaintsearch(app); |
674 | pdfapp_onkey(app, 'n'); |
674 | pdfapp_onkey(app, 'n'); |
675 | } |
675 | } |
676 | else |
676 | else |
677 | winrepaint(app); |
677 | winrepaint(app); |
678 | } |
678 | } |
679 | if (c == '\033') |
679 | if (c == '\033') |
680 | { |
680 | { |
681 | app->isediting = 0; |
681 | app->isediting = 0; |
682 | winrepaint(app); |
682 | winrepaint(app); |
683 | } |
683 | } |
684 | } |
684 | } |
685 | else |
685 | else |
686 | { |
686 | { |
687 | if (n + 2 < sizeof app->search) |
687 | if (n + 2 < sizeof app->search) |
688 | { |
688 | { |
689 | app->search[n] = c; |
689 | app->search[n] = c; |
690 | app->search[n + 1] = 0; |
690 | app->search[n + 1] = 0; |
691 | winrepaintsearch(app); |
691 | winrepaintsearch(app); |
692 | } |
692 | } |
693 | } |
693 | } |
694 | return; |
694 | return; |
695 | } |
695 | } |
696 | 696 | ||
697 | /* |
697 | /* |
698 | * Save numbers typed for later |
698 | * Save numbers typed for later |
699 | */ |
699 | */ |
700 | 700 | ||
701 | if (c >= '0' && c <= '9') |
701 | if (c >= '0' && c <= '9') |
702 | { |
702 | { |
703 | app->number[app->numberlen++] = c; |
703 | app->number[app->numberlen++] = c; |
704 | app->number[app->numberlen] = '\0'; |
704 | app->number[app->numberlen] = '\0'; |
705 | } |
705 | } |
706 | 706 | ||
707 | switch (c) |
707 | switch (c) |
708 | { |
708 | { |
709 | 709 | ||
710 | case '?': |
710 | case '?': |
711 | winhelp(app); |
711 | winhelp(app); |
712 | break; |
712 | break; |
713 | 713 | ||
714 | case 'q': |
714 | case 'q': |
715 | winclose(app); |
715 | winclose(app); |
716 | break; |
716 | break; |
717 | 717 | ||
718 | /* |
718 | /* |
719 | * Zoom and rotate |
719 | * Zoom and rotate |
720 | */ |
720 | */ |
721 | 721 | ||
722 | case '+': |
722 | case '+': |
723 | case '=': |
723 | case '=': |
724 | app->resolution *= ZOOMSTEP; |
724 | app->resolution *= ZOOMSTEP; |
725 | if (app->resolution > MAXRES) |
725 | if (app->resolution > MAXRES) |
726 | app->resolution = MAXRES; |
726 | app->resolution = MAXRES; |
727 | pdfapp_showpage(app, 0, 1, 1); |
727 | pdfapp_showpage(app, 0, 1, 1); |
728 | break; |
728 | break; |
729 | case '-': |
729 | case '-': |
730 | app->resolution /= ZOOMSTEP; |
730 | app->resolution /= ZOOMSTEP; |
731 | if (app->resolution < MINRES) |
731 | if (app->resolution < MINRES) |
732 | app->resolution = MINRES; |
732 | app->resolution = MINRES; |
733 | pdfapp_showpage(app, 0, 1, 1); |
733 | pdfapp_showpage(app, 0, 1, 1); |
734 | break; |
734 | break; |
735 | 735 | ||
736 | case 'L': |
736 | case 'L': |
737 | app->rotate -= 90; |
737 | app->rotate -= 90; |
738 | pdfapp_showpage(app, 0, 1, 1); |
738 | pdfapp_showpage(app, 0, 1, 1); |
739 | break; |
739 | break; |
740 | case 'R': |
740 | case 'R': |
741 | app->rotate += 90; |
741 | app->rotate += 90; |
742 | pdfapp_showpage(app, 0, 1, 1); |
742 | pdfapp_showpage(app, 0, 1, 1); |
743 | break; |
743 | break; |
744 | 744 | ||
745 | case 'c': |
745 | case 'c': |
746 | app->grayscale ^= 1; |
746 | app->grayscale ^= 1; |
747 | pdfapp_showpage(app, 0, 1, 1); |
747 | pdfapp_showpage(app, 0, 1, 1); |
748 | break; |
748 | break; |
749 | 749 | ||
750 | #ifndef NDEBUG |
750 | #ifndef NDEBUG |
751 | case 'a': |
751 | case 'a': |
752 | app->rotate -= 15; |
752 | app->rotate -= 15; |
753 | pdfapp_showpage(app, 0, 1, 1); |
753 | pdfapp_showpage(app, 0, 1, 1); |
754 | break; |
754 | break; |
755 | case 's': |
755 | case 's': |
756 | app->rotate += 15; |
756 | app->rotate += 15; |
757 | pdfapp_showpage(app, 0, 1, 1); |
757 | pdfapp_showpage(app, 0, 1, 1); |
758 | break; |
758 | break; |
759 | #endif |
759 | #endif |
760 | 760 | ||
761 | /* |
761 | /* |
762 | * Pan view, but dont need to repaint image |
762 | * Pan view, but dont need to repaint image |
763 | */ |
763 | */ |
764 | 764 | ||
765 | case 'w': |
765 | case 'w': |
766 | app->shrinkwrap = 1; |
766 | app->shrinkwrap = 1; |
767 | app->panx = app->pany = 0; |
767 | app->panx = app->pany = 0; |
768 | pdfapp_showpage(app, 0, 0, 1); |
768 | pdfapp_showpage(app, 0, 0, 1); |
769 | break; |
769 | break; |
770 | 770 | ||
771 | case 'h': |
771 | case 'h': |
772 | app->panx += app->image->w / 10; |
772 | app->panx += app->image->w / 10; |
773 | pdfapp_showpage(app, 0, 0, 1); |
773 | pdfapp_showpage(app, 0, 0, 1); |
774 | break; |
774 | break; |
775 | 775 | ||
776 | case 'j': |
776 | case 'j': |
777 | app->pany -= app->image->h / 10; |
777 | app->pany -= app->image->h / 10; |
778 | pdfapp_showpage(app, 0, 0, 1); |
778 | pdfapp_showpage(app, 0, 0, 1); |
779 | break; |
779 | break; |
780 | 780 | ||
781 | case 'k': |
781 | case 'k': |
782 | app->pany += app->image->h / 10; |
782 | app->pany += app->image->h / 10; |
783 | pdfapp_showpage(app, 0, 0, 1); |
783 | pdfapp_showpage(app, 0, 0, 1); |
784 | break; |
784 | break; |
785 | 785 | ||
786 | case 'l': |
786 | case 'l': |
787 | app->panx -= app->image->w / 10; |
787 | app->panx -= app->image->w / 10; |
788 | pdfapp_showpage(app, 0, 0, 1); |
788 | pdfapp_showpage(app, 0, 0, 1); |
789 | break; |
789 | break; |
790 | 790 | ||
791 | /* |
791 | /* |
792 | * Page navigation |
792 | * Page navigation |
793 | */ |
793 | */ |
794 | 794 | ||
795 | case 'g': |
795 | case 'g': |
796 | case '\n': |
796 | case '\n': |
797 | case '\r': |
797 | case '\r': |
798 | if (app->numberlen > 0) |
798 | if (app->numberlen > 0) |
799 | app->pageno = atoi(app->number); |
799 | app->pageno = atoi(app->number); |
800 | else |
800 | else |
801 | app->pageno = 1; |
801 | app->pageno = 1; |
802 | break; |
802 | break; |
803 | 803 | ||
804 | case 'G': |
804 | case 'G': |
805 | app->pageno = app->pagecount; |
805 | app->pageno = app->pagecount; |
806 | break; |
806 | break; |
807 | 807 | ||
808 | case 'm': |
808 | case 'm': |
809 | if (app->numberlen > 0) |
809 | if (app->numberlen > 0) |
810 | { |
810 | { |
811 | int idx = atoi(app->number); |
811 | int idx = atoi(app->number); |
812 | 812 | ||
813 | if (idx >= 0 && idx < nelem(app->marks)) |
813 | if (idx >= 0 && idx < nelem(app->marks)) |
814 | app->marks[idx] = app->pageno; |
814 | app->marks[idx] = app->pageno; |
815 | } |
815 | } |
816 | else |
816 | else |
817 | { |
817 | { |
818 | if (app->histlen + 1 == 256) |
818 | if (app->histlen + 1 == 256) |
819 | { |
819 | { |
820 | memmove(app->hist, app->hist + 1, sizeof(int) * 255); |
820 | memmove(app->hist, app->hist + 1, sizeof(int) * 255); |
821 | app->histlen --; |
821 | app->histlen --; |
822 | } |
822 | } |
823 | app->hist[app->histlen++] = app->pageno; |
823 | app->hist[app->histlen++] = app->pageno; |
824 | } |
824 | } |
825 | break; |
825 | break; |
826 | 826 | ||
827 | case 't': |
827 | case 't': |
828 | if (app->numberlen > 0) |
828 | if (app->numberlen > 0) |
829 | { |
829 | { |
830 | int idx = atoi(app->number); |
830 | int idx = atoi(app->number); |
831 | 831 | ||
832 | if (idx >= 0 && idx < nelem(app->marks)) |
832 | if (idx >= 0 && idx < nelem(app->marks)) |
833 | if (app->marks[idx] > 0) |
833 | if (app->marks[idx] > 0) |
834 | app->pageno = app->marks[idx]; |
834 | app->pageno = app->marks[idx]; |
835 | } |
835 | } |
836 | else if (app->histlen > 0) |
836 | else if (app->histlen > 0) |
837 | app->pageno = app->hist[--app->histlen]; |
837 | app->pageno = app->hist[--app->histlen]; |
838 | break; |
838 | break; |
839 | 839 | ||
840 | /* |
840 | /* |
841 | * Back and forth ... |
841 | * Back and forth ... |
842 | */ |
842 | */ |
843 | 843 | ||
844 | case ',': |
844 | case ',': |
845 | panto = PAN_TO_BOTTOM; |
845 | panto = PAN_TO_BOTTOM; |
846 | if (app->numberlen > 0) |
846 | if (app->numberlen > 0) |
847 | app->pageno -= atoi(app->number); |
847 | app->pageno -= atoi(app->number); |
848 | else |
848 | else |
849 | app->pageno--; |
849 | app->pageno--; |
850 | break; |
850 | break; |
851 | 851 | ||
852 | case '.': |
852 | case '.': |
853 | panto = PAN_TO_TOP; |
853 | panto = PAN_TO_TOP; |
854 | if (app->numberlen > 0) |
854 | if (app->numberlen > 0) |
855 | app->pageno += atoi(app->number); |
855 | app->pageno += atoi(app->number); |
856 | else |
856 | else |
857 | app->pageno++; |
857 | app->pageno++; |
858 | break; |
858 | break; |
859 | 859 | ||
860 | case 'b': |
860 | case 'b': |
861 | panto = DONT_PAN; |
861 | panto = DONT_PAN; |
862 | if (app->numberlen > 0) |
862 | if (app->numberlen > 0) |
863 | app->pageno -= atoi(app->number); |
863 | app->pageno -= atoi(app->number); |
864 | else |
864 | else |
865 | app->pageno--; |
865 | app->pageno--; |
866 | break; |
866 | break; |
867 | 867 | ||
868 | case ' ': |
868 | case ' ': |
869 | panto = DONT_PAN; |
869 | panto = DONT_PAN; |
870 | if (app->numberlen > 0) |
870 | if (app->numberlen > 0) |
871 | app->pageno += atoi(app->number); |
871 | app->pageno += atoi(app->number); |
872 | else |
872 | else |
873 | app->pageno++; |
873 | app->pageno++; |
874 | break; |
874 | break; |
875 | 875 | ||
876 | case ']': |
876 | case ']': |
877 | panto = PAN_TO_TOP; |
877 | panto = PAN_TO_TOP; |
878 | app->pageno++; |
878 | app->pageno++; |
879 | break; |
879 | break; |
880 | 880 | ||
881 | case '[': |
881 | case '[': |
882 | panto = PAN_TO_TOP; |
882 | panto = PAN_TO_TOP; |
883 | app->pageno--; |
883 | app->pageno--; |
884 | break; |
884 | break; |
885 | 885 | ||
886 | 886 | ||
887 | case '<': |
887 | case '<': |
888 | panto = PAN_TO_TOP; |
888 | panto = PAN_TO_TOP; |
889 | app->pageno -= 10; |
889 | app->pageno -= 10; |
890 | break; |
890 | break; |
891 | case '>': |
891 | case '>': |
892 | panto = PAN_TO_TOP; |
892 | panto = PAN_TO_TOP; |
893 | app->pageno += 10; |
893 | app->pageno += 10; |
894 | break; |
894 | break; |
895 | 895 | ||
896 | /* |
896 | /* |
897 | * Reloading the file... |
897 | * Reloading the file... |
898 | */ |
898 | */ |
899 | 899 | ||
900 | case 'r': |
900 | case 'r': |
901 | panto = DONT_PAN; |
901 | panto = DONT_PAN; |
902 | oldpage = -1; |
902 | oldpage = -1; |
903 | winreloadfile(app); |
903 | winreloadfile(app); |
904 | break; |
904 | break; |
905 | 905 | ||
906 | /* |
906 | /* |
907 | * Searching |
907 | * Searching |
908 | */ |
908 | */ |
909 | 909 | ||
910 | case '/': |
910 | case '/': |
911 | app->isediting = 1; |
911 | app->isediting = 1; |
912 | app->search[0] = 0; |
912 | app->search[0] = 0; |
913 | app->hit = -1; |
913 | app->hit = -1; |
914 | app->hitlen = 0; |
914 | app->hitlen = 0; |
915 | winrepaintsearch(app); |
915 | winrepaintsearch(app); |
916 | break; |
916 | break; |
917 | 917 | ||
918 | case 'n': |
918 | case 'n': |
919 | pdfapp_searchforward(app, &panto); |
919 | pdfapp_searchforward(app, &panto); |
920 | loadpage = 0; |
920 | loadpage = 0; |
921 | break; |
921 | break; |
922 | 922 | ||
923 | case 'N': |
923 | case 'N': |
924 | pdfapp_searchbackward(app, &panto); |
924 | pdfapp_searchbackward(app, &panto); |
925 | loadpage = 0; |
925 | loadpage = 0; |
926 | break; |
926 | break; |
927 | 927 | ||
928 | } |
928 | } |
929 | 929 | ||
930 | if (c < '0' || c > '9') |
930 | if (c < '0' || c > '9') |
931 | app->numberlen = 0; |
931 | app->numberlen = 0; |
932 | 932 | ||
933 | if (app->pageno < 1) |
933 | if (app->pageno < 1) |
934 | app->pageno = 1; |
934 | app->pageno = 1; |
935 | if (app->pageno > app->pagecount) |
935 | if (app->pageno > app->pagecount) |
936 | app->pageno = app->pagecount; |
936 | app->pageno = app->pagecount; |
937 | 937 | ||
938 | if (app->pageno != oldpage) |
938 | if (app->pageno != oldpage) |
939 | { |
939 | { |
940 | switch (panto) |
940 | switch (panto) |
941 | { |
941 | { |
942 | case PAN_TO_TOP: |
942 | case PAN_TO_TOP: |
943 | app->pany = 0; |
943 | app->pany = 0; |
944 | break; |
944 | break; |
945 | case PAN_TO_BOTTOM: |
945 | case PAN_TO_BOTTOM: |
946 | app->pany = -2000; |
946 | app->pany = -2000; |
947 | break; |
947 | break; |
948 | case DONT_PAN: |
948 | case DONT_PAN: |
949 | break; |
949 | break; |
950 | } |
950 | } |
951 | pdfapp_showpage(app, loadpage, 1, 1); |
951 | pdfapp_showpage(app, loadpage, 1, 1); |
952 | } |
952 | } |
953 | } |
953 | } |
954 | 954 | ||
955 | void pdfapp_onmouse(pdfapp_t *app, int x, int y, int btn, int modifiers, int state) |
955 | void pdfapp_onmouse(pdfapp_t *app, int x, int y, int btn, int modifiers, int state) |
956 | { |
956 | { |
957 | pdf_link *link; |
957 | pdf_link *link; |
958 | fz_matrix ctm; |
958 | fz_matrix ctm; |
959 | fz_point p; |
959 | fz_point p; |
960 | 960 | ||
961 | p.x = x - app->panx + app->image->x; |
961 | p.x = x - app->panx + app->image->x; |
962 | p.y = y - app->pany + app->image->y; |
962 | p.y = y - app->pany + app->image->y; |
963 | 963 | ||
964 | ctm = pdfapp_viewctm(app); |
964 | ctm = pdfapp_viewctm(app); |
965 | ctm = fz_invert_matrix(ctm); |
965 | ctm = fz_invert_matrix(ctm); |
966 | 966 | ||
967 | p = fz_transform_point(ctm, p); |
967 | p = fz_transform_point(ctm, p); |
968 | 968 | ||
969 | for (link = app->page_links; link; link = link->next) |
969 | for (link = app->page_links; link; link = link->next) |
970 | { |
970 | { |
971 | if (p.x >= link->rect.x0 && p.x <= link->rect.x1) |
971 | if (p.x >= link->rect.x0 && p.x <= link->rect.x1) |
972 | if (p.y >= link->rect.y0 && p.y <= link->rect.y1) |
972 | if (p.y >= link->rect.y0 && p.y <= link->rect.y1) |
973 | break; |
973 | break; |
974 | } |
974 | } |
975 | 975 | ||
976 | if (link) |
976 | if (link) |
977 | { |
977 | { |
978 | wincursor(app, HAND); |
978 | wincursor(app, HAND); |
979 | if (btn == 1 && state == 1) |
979 | if (btn == 1 && state == 1) |
980 | { |
980 | { |
981 | if (link->kind == PDF_LINK_URI) |
981 | if (link->kind == PDF_LINK_URI) |
982 | pdfapp_gotouri(app, link->dest); |
982 | pdfapp_gotouri(app, link->dest); |
983 | else if (link->kind == PDF_LINK_GOTO) |
983 | else if (link->kind == PDF_LINK_GOTO) |
984 | pdfapp_gotopage(app, fz_array_get(link->dest, 0)); /* [ pageobj ... ] */ |
984 | pdfapp_gotopage(app, fz_array_get(link->dest, 0)); /* [ pageobj ... ] */ |
985 | return; |
985 | return; |
986 | } |
986 | } |
987 | } |
987 | } |
988 | else |
988 | else |
989 | { |
989 | { |
990 | wincursor(app, ARROW); |
990 | wincursor(app, ARROW); |
991 | } |
991 | } |
992 | 992 | ||
993 | if (state == 1) |
993 | if (state == 1) |
994 | { |
994 | { |
995 | if (btn == 1 && !app->iscopying) |
995 | if (btn == 1 && !app->iscopying) |
996 | { |
996 | { |
997 | app->ispanning = 1; |
997 | app->ispanning = 1; |
998 | app->selx = x; |
998 | app->selx = x; |
999 | app->sely = y; |
999 | app->sely = y; |
1000 | app->beyondy = 0; |
1000 | app->beyondy = 0; |
1001 | } |
1001 | } |
1002 | if (btn == 3 && !app->ispanning) |
1002 | if (btn == 3 && !app->ispanning) |
1003 | { |
1003 | { |
1004 | app->iscopying = 1; |
1004 | app->iscopying = 1; |
1005 | app->selx = x; |
1005 | app->selx = x; |
1006 | app->sely = y; |
1006 | app->sely = y; |
1007 | app->selr.x0 = x; |
1007 | app->selr.x0 = x; |
1008 | app->selr.x1 = x; |
1008 | app->selr.x1 = x; |
1009 | app->selr.y0 = y; |
1009 | app->selr.y0 = y; |
1010 | app->selr.y1 = y; |
1010 | app->selr.y1 = y; |
1011 | } |
1011 | } |
1012 | if (btn == 4 || btn == 5) /* scroll wheel */ |
1012 | if (btn == 4 || btn == 5) /* scroll wheel */ |
1013 | { |
1013 | { |
1014 | int dir = btn == 4 ? 1 : -1; |
1014 | int dir = btn == 4 ? 1 : -1; |
1015 | app->ispanning = app->iscopying = 0; |
1015 | app->ispanning = app->iscopying = 0; |
1016 | if (modifiers & (1<<2)) |
1016 | if (modifiers & (1<<2)) |
1017 | { |
1017 | { |
1018 | /* zoom in/out if ctrl is pressed */ |
1018 | /* zoom in/out if ctrl is pressed */ |
1019 | if (dir > 0) |
1019 | if (dir > 0) |
1020 | app->resolution *= ZOOMSTEP; |
1020 | app->resolution *= ZOOMSTEP; |
1021 | else |
1021 | else |
1022 | app->resolution /= ZOOMSTEP; |
1022 | app->resolution /= ZOOMSTEP; |
1023 | if (app->resolution > MAXRES) |
1023 | if (app->resolution > MAXRES) |
1024 | app->resolution = MAXRES; |
1024 | app->resolution = MAXRES; |
1025 | if (app->resolution < MINRES) |
1025 | if (app->resolution < MINRES) |
1026 | app->resolution = MINRES; |
1026 | app->resolution = MINRES; |
1027 | pdfapp_showpage(app, 0, 1, 1); |
1027 | pdfapp_showpage(app, 0, 1, 1); |
1028 | } |
1028 | } |
1029 | else |
1029 | else |
1030 | { |
1030 | { |
1031 | /* scroll up/down, or left/right if |
1031 | /* scroll up/down, or left/right if |
1032 | shift is pressed */ |
1032 | shift is pressed */ |
1033 | int isx = (modifiers & (1<<0)); |
1033 | int isx = (modifiers & (1<<0)); |
1034 | int xstep = isx ? 20 * dir : 0; |
1034 | int xstep = isx ? 20 * dir : 0; |
1035 | int ystep = !isx ? 20 * dir : 0; |
1035 | int ystep = !isx ? 20 * dir : 0; |
1036 | pdfapp_panview(app, app->panx + xstep, app->pany + ystep); |
1036 | pdfapp_panview(app, app->panx + xstep, app->pany + ystep); |
1037 | } |
1037 | } |
1038 | } |
1038 | } |
1039 | } |
1039 | } |
1040 | 1040 | ||
1041 | else if (state == -1) |
1041 | else if (state == -1) |
1042 | { |
1042 | { |
1043 | if (app->iscopying) |
1043 | if (app->iscopying) |
1044 | { |
1044 | { |
1045 | app->iscopying = 0; |
1045 | app->iscopying = 0; |
1046 | app->selr.x0 = MIN(app->selx, x) - app->panx + app->image->x; |
1046 | app->selr.x0 = MIN(app->selx, x) - app->panx + app->image->x; |
1047 | app->selr.x1 = MAX(app->selx, x) - app->panx + app->image->x; |
1047 | app->selr.x1 = MAX(app->selx, x) - app->panx + app->image->x; |
1048 | app->selr.y0 = MIN(app->sely, y) - app->pany + app->image->y; |
1048 | app->selr.y0 = MIN(app->sely, y) - app->pany + app->image->y; |
1049 | app->selr.y1 = MAX(app->sely, y) - app->pany + app->image->y; |
1049 | app->selr.y1 = MAX(app->sely, y) - app->pany + app->image->y; |
1050 | winrepaint(app); |
1050 | winrepaint(app); |
1051 | if (app->selr.x0 < app->selr.x1 && app->selr.y0 < app->selr.y1) |
1051 | if (app->selr.x0 < app->selr.x1 && app->selr.y0 < app->selr.y1) |
1052 | windocopy(app); |
1052 | windocopy(app); |
1053 | } |
1053 | } |
1054 | if (app->ispanning) |
1054 | if (app->ispanning) |
1055 | app->ispanning = 0; |
1055 | app->ispanning = 0; |
1056 | } |
1056 | } |
1057 | 1057 | ||
1058 | else if (app->ispanning) |
1058 | else if (app->ispanning) |
1059 | { |
1059 | { |
1060 | int newx = app->panx + x - app->selx; |
1060 | int newx = app->panx + x - app->selx; |
1061 | int newy = app->pany + y - app->sely; |
1061 | int newy = app->pany + y - app->sely; |
1062 | /* Scrolling beyond limits implies flipping pages */ |
1062 | /* Scrolling beyond limits implies flipping pages */ |
1063 | /* Are we requested to scroll beyond limits? */ |
1063 | /* Are we requested to scroll beyond limits? */ |
1064 | if (newy + app->image->h < app->winh || newy > 0) |
1064 | if (newy + app->image->h < app->winh || newy > 0) |
1065 | { |
1065 | { |
1066 | /* Yes. We can assume that deltay != 0 */ |
1066 | /* Yes. We can assume that deltay != 0 */ |
1067 | int deltay = y - app->sely; |
1067 | int deltay = y - app->sely; |
1068 | /* Check whether the panning has occured in the |
1068 | /* Check whether the panning has occured in the |
1069 | * direction that we are already crossing the |
1069 | * direction that we are already crossing the |
1070 | * limit it. If not, we can conclude that we |
1070 | * limit it. If not, we can conclude that we |
1071 | * have switched ends of the page and will thus |
1071 | * have switched ends of the page and will thus |
1072 | * start over counting. |
1072 | * start over counting. |
1073 | */ |
1073 | */ |
1074 | if( app->beyondy == 0 || (app->beyondy ^ deltay) >= 0 ) |
1074 | if( app->beyondy == 0 || (app->beyondy ^ deltay) >= 0 ) |
1075 | { |
1075 | { |
1076 | /* Updating how far we are beyond and |
1076 | /* Updating how far we are beyond and |
1077 | * flipping pages if beyond threshhold |
1077 | * flipping pages if beyond threshhold |
1078 | */ |
1078 | */ |
1079 | app->beyondy += deltay; |
1079 | app->beyondy += deltay; |
1080 | if (app->beyondy > BEYOND_THRESHHOLD) |
1080 | if (app->beyondy > BEYOND_THRESHHOLD) |
1081 | { |
1081 | { |
1082 | if( app->pageno > 1 ) |
1082 | if( app->pageno > 1 ) |
1083 | { |
1083 | { |
1084 | app->pageno--; |
1084 | app->pageno--; |
1085 | pdfapp_showpage(app, 1, 1, 1); |
1085 | pdfapp_showpage(app, 1, 1, 1); |
1086 | newy = -app->image->h; |
1086 | newy = -app->image->h; |
1087 | } |
1087 | } |
1088 | app->beyondy = 0; |
1088 | app->beyondy = 0; |
1089 | } |
1089 | } |
1090 | else if (app->beyondy < -BEYOND_THRESHHOLD) |
1090 | else if (app->beyondy < -BEYOND_THRESHHOLD) |
1091 | { |
1091 | { |
1092 | if( app->pageno < app->pagecount ) |
1092 | if( app->pageno < app->pagecount ) |
1093 | { |
1093 | { |
1094 | app->pageno++; |
1094 | app->pageno++; |
1095 | pdfapp_showpage(app, 1, 1, 1); |
1095 | pdfapp_showpage(app, 1, 1, 1); |
1096 | newy = 0; |
1096 | newy = 0; |
1097 | } |
1097 | } |
1098 | app->beyondy = 0; |
1098 | app->beyondy = 0; |
1099 | } |
1099 | } |
1100 | } |
1100 | } |
1101 | else |
1101 | else |
1102 | app->beyondy = 0; |
1102 | app->beyondy = 0; |
1103 | } |
1103 | } |
1104 | /* Although at this point we've already determined that |
1104 | /* Although at this point we've already determined that |
1105 | * or that no scrolling will be performed in |
1105 | * or that no scrolling will be performed in |
1106 | * y-direction, the x-direction has not yet been taken |
1106 | * y-direction, the x-direction has not yet been taken |
1107 | * care off. Therefore |
1107 | * care off. Therefore |
1108 | */ |
1108 | */ |
1109 | pdfapp_panview(app, newx, newy); |
1109 | pdfapp_panview(app, newx, newy); |
1110 | 1110 | ||
1111 | app->selx = x; |
1111 | app->selx = x; |
1112 | app->sely = y; |
1112 | app->sely = y; |
1113 | } |
1113 | } |
1114 | 1114 | ||
1115 | else if (app->iscopying) |
1115 | else if (app->iscopying) |
1116 | { |
1116 | { |
1117 | app->selr.x0 = MIN(app->selx, x) - app->panx + app->image->x; |
1117 | app->selr.x0 = MIN(app->selx, x) - app->panx + app->image->x; |
1118 | app->selr.x1 = MAX(app->selx, x) - app->panx + app->image->x; |
1118 | app->selr.x1 = MAX(app->selx, x) - app->panx + app->image->x; |
1119 | app->selr.y0 = MIN(app->sely, y) - app->pany + app->image->y; |
1119 | app->selr.y0 = MIN(app->sely, y) - app->pany + app->image->y; |
1120 | app->selr.y1 = MAX(app->sely, y) - app->pany + app->image->y; |
1120 | app->selr.y1 = MAX(app->sely, y) - app->pany + app->image->y; |
1121 | winrepaint(app); |
1121 | winrepaint(app); |
1122 | } |
1122 | } |
1123 | 1123 | ||
1124 | } |
1124 | } |
1125 | 1125 | ||
1126 | void pdfapp_oncopy(pdfapp_t *app, unsigned short *ucsbuf, int ucslen) |
1126 | void pdfapp_oncopy(pdfapp_t *app, unsigned short *ucsbuf, int ucslen) |
1127 | { |
1127 | { |
1128 | fz_bbox hitbox; |
1128 | fz_bbox hitbox; |
1129 | fz_matrix ctm; |
1129 | fz_matrix ctm; |
1130 | fz_text_span *span; |
1130 | fz_text_span *span; |
1131 | int c, i, p; |
1131 | int c, i, p; |
1132 | int seen; |
1132 | int seen; |
1133 | 1133 | ||
1134 | int x0 = app->selr.x0; |
1134 | int x0 = app->selr.x0; |
1135 | int x1 = app->selr.x1; |
1135 | int x1 = app->selr.x1; |
1136 | int y0 = app->selr.y0; |
1136 | int y0 = app->selr.y0; |
1137 | int y1 = app->selr.y1; |
1137 | int y1 = app->selr.y1; |
1138 | 1138 | ||
1139 | ctm = pdfapp_viewctm(app); |
1139 | ctm = pdfapp_viewctm(app); |
1140 | 1140 | ||
1141 | p = 0; |
1141 | p = 0; |
1142 | for (span = app->page_text; span; span = span->next) |
1142 | for (span = app->page_text; span; span = span->next) |
1143 | { |
1143 | { |
1144 | seen = 0; |
1144 | seen = 0; |
1145 | 1145 | ||
1146 | for (i = 0; i < span->len; i++) |
1146 | for (i = 0; i < span->len; i++) |
1147 | { |
1147 | { |
1148 | hitbox = fz_transform_bbox(ctm, span->text[i].bbox); |
1148 | hitbox = fz_transform_bbox(ctm, span->text[i].bbox); |
1149 | c = span->text[i].c; |
1149 | c = span->text[i].c; |
1150 | if (c < 32) |
1150 | if (c < 32) |
1151 | c = '?'; |
1151 | c = '?'; |
1152 | if (hitbox.x1 >= x0 && hitbox.x0 <= x1 && hitbox.y1 >= y0 && hitbox.y0 <= y1) |
1152 | if (hitbox.x1 >= x0 && hitbox.x0 <= x1 && hitbox.y1 >= y0 && hitbox.y0 <= y1) |
1153 | { |
1153 | { |
1154 | if (p < ucslen - 1) |
1154 | if (p < ucslen - 1) |
1155 | ucsbuf[p++] = c; |
1155 | ucsbuf[p++] = c; |
1156 | seen = 1; |
1156 | seen = 1; |
1157 | } |
1157 | } |
1158 | } |
1158 | } |
1159 | 1159 | ||
1160 | if (seen && span->eol) |
1160 | if (seen && span->eol) |
1161 | { |
1161 | { |
1162 | #ifdef _WIN32 |
1162 | #ifdef _WIN32 |
1163 | if (p < ucslen - 1) |
1163 | if (p < ucslen - 1) |
1164 | ucsbuf[p++] = '\r'; |
1164 | ucsbuf[p++] = '\r'; |
1165 | #endif |
1165 | #endif |
1166 | if (p < ucslen - 1) |
1166 | if (p < ucslen - 1) |
1167 | ucsbuf[p++] = '\n'; |
1167 | ucsbuf[p++] = '\n'; |
1168 | } |
1168 | } |
1169 | } |
1169 | } |
1170 | 1170 | ||
1171 | ucsbuf[p] = 0; |
1171 | ucsbuf[p] = 0; |
1172 | }>>>=>=>>>>>>>>0)); |
1172 | }>>>=>=>>>>>>>>0)); |
1173 | ><0)); |
1173 | ><0)); |
1174 | >>2)) |
1174 | >>2)) |
1175 | ><2)) |
1175 | ><2)) |
1176 | >=>=>>>': |
1176 | >=>=>>>': |
1177 | >>>>=>>>>>>>>>>>>>>>>>>\t\t--> |
1177 | >>>>=>>>>>>>>>>>>>>>>>>\t\t--> |