Subversion Repositories Kolibri OS

Rev

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  /* for tolower() */
6
#include  /* for tolower() */
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
}
1172
}
1173
>
1173
>
1174
>
1174
>
1175
>
1175
>
1176
>
1176
>
1177
>
1177
>