Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4680 right-hear 1
#include "fitz.h"
2
#include "mupdf.h"
3
#include "muxps.h"
4
#include "pdfapp.h"
5
 
6
#include 
7
 
8
// #include 
9
#include 
10
#include 
11
#include 
12
#include 
13
 
14
 
15
 
16
#ifndef timeradd
17
#define timeradd(a, b, result) \
18
	do { \
19
		(result)->tv_sec = (a)->tv_sec + (b)->tv_sec; \
20
		(result)->tv_usec = (a)->tv_usec + (b)->tv_usec; \
21
		if ((result)->tv_usec >= 1000000) \
22
		{ \
23
			++(result)->tv_sec; \
24
			(result)->tv_usec -= 1000000; \
25
		} \
26
	} while (0)
27
#endif
28
 
29
#ifndef timersub
30
#define timersub(a, b, result) \
31
	do { \
32
		(result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
33
		(result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
34
		if ((result)->tv_usec < 0) { \
35
			--(result)->tv_sec; \
36
			(result)->tv_usec += 1000000; \
37
		} \
38
	} while (0)
39
#endif
40
 
41
extern int ximage_init(Display *display, int screen, Visual *visual);
42
extern int ximage_get_depth(void);
43
extern Visual *ximage_get_visual(void);
44
extern Colormap ximage_get_colormap(void);
45
extern void ximage_blit(Drawable d, GC gc, int dstx, int dsty,
46
	unsigned char *srcdata,
47
	int srcx, int srcy, int srcw, int srch, int srcstride);
48
 
49
static Display *xdpy;
50
static Atom XA_TARGETS;
51
static Atom XA_TIMESTAMP;
52
static Atom XA_UTF8_STRING;
53
static Atom WM_DELETE_WINDOW;
54
static int x11fd;
55
static int xscr;
56
static Window xwin;
57
static Pixmap xicon, xmask;
58
static GC xgc;
59
static XEvent xevt;
60
static int mapped = 0;
61
static Cursor xcarrow, xchand, xcwait;
62
static int justcopied = 0;
63
static int dirty = 0;
64
static int dirtysearch = 0;
65
static char *password = "";
66
static XColor xbgcolor;
67
static XColor xshcolor;
68
static int reqw = 0;
69
static int reqh = 0;
70
static char copylatin1[1024 * 16] = "";
71
static char copyutf8[1024 * 48] = "";
72
static Time copytime;
73
static char *filename;
74
 
75
static pdfapp_t gapp;
76
static int closing = 0;
77
static int reloading = 0;
78
 
79
/*
80
 * Dialog boxes
81
 */
82
 
83
void winwarn(pdfapp_t *app, char *msg)
84
{
85
	fprintf(stderr, "mupdf: %s\n", msg);
86
}
87
 
88
void winerror(pdfapp_t *app, fz_error error)
89
{
90
	fz_catch(error, "aborting");
91
	exit(1);
92
}
93
 
94
char *winpassword(pdfapp_t *app, char *filename)
95
{
96
	char *r = password;
97
	password = NULL;
98
	return r;
99
}
100
 
101
/*
102
 * X11 magic
103
 */
104
 
105
static void winopen(void)
106
{
107
 
108
 
109
	/*
110
	xwin = XCreateWindow(xdpy, DefaultRootWindow(xdpy),
111
		10, 10, 200, 100, 1,
112
		ximage_get_depth(),
113
		InputOutput,
114
		ximage_get_visual(),
115
		0,
116
		NULL); */
117
 
118
 __menuet__define_window(10,10,200,200,
119
     0,0,0);
120
 
121
}
122
 
123
void winclose(pdfapp_t *app)
124
{
125
	closing = 1;
126
}
127
 
128
void wincursor(pdfapp_t *app, int curs)
129
{
130
 
131
}
132
 
133
void wintitle(pdfapp_t *app, char *s)
134
{
135
 
136
}
137
 
138
void winhelp(pdfapp_t *app)
139
{
140
 
141
}
142
 
143
void winresize(pdfapp_t *app, int w, int h)
144
{
145
 
146
 
147
 
148
 
149
}
150
 
151
static void fillrect(int x, int y, int w, int h)
152
{
153
	if (w > 0 && h > 0)
154
		XFillRectangle(xdpy, xwin, xgc, x, y, w, h);
155
}
156
 
157
static void winblitsearch(pdfapp_t *app)
158
{
159
	if (gapp.isediting)
160
	{
161
		char buf[sizeof(gapp.search) + 50];
162
		sprintf(buf, "Search: %s", gapp.search);
163
		XSetForeground(xdpy, xgc, WhitePixel(xdpy, xscr));
164
		fillrect(0, 0, gapp.winw, 30);
165
		windrawstring(&gapp, 10, 20, buf);
166
	}
167
}
168
 
169
static void winblit(pdfapp_t *app)
170
{
171
	int x0 = gapp.panx;
172
	int y0 = gapp.pany;
173
	int x1 = gapp.panx + gapp.image->w;
174
	int y1 = gapp.pany + gapp.image->h;
175
 
176
	XSetForeground(xdpy, xgc, xbgcolor.pixel);
177
	fillrect(0, 0, x0, gapp.winh);
178
	fillrect(x1, 0, gapp.winw - x1, gapp.winh);
179
	fillrect(0, 0, gapp.winw, y0);
180
	fillrect(0, y1, gapp.winw, gapp.winh - y1);
181
 
182
	XSetForeground(xdpy, xgc, xshcolor.pixel);
183
	fillrect(x0+2, y1, gapp.image->w, 2);
184
	fillrect(x1, y0+2, 2, gapp.image->h);
185
 
186
	if (gapp.iscopying || justcopied)
187
	{
188
		pdfapp_invert(&gapp, gapp.selr);
189
		justcopied = 1;
190
	}
191
 
192
	pdfapp_inverthit(&gapp);
193
 
194
	if (gapp.image->n == 4)
195
		ximage_blit(xwin, xgc,
196
			x0, y0,
197
			gapp.image->samples,
198
			0, 0,
199
			gapp.image->w,
200
			gapp.image->h,
201
			gapp.image->w * gapp.image->n);
202
	else if (gapp.image->n == 2)
203
	{
204
		int i = gapp.image->w*gapp.image->h;
205
		unsigned char *color = malloc(i*4);
206
		if (color != NULL)
207
		{
208
			unsigned char *s = gapp.image->samples;
209
			unsigned char *d = color;
210
			for (; i > 0 ; i--)
211
			{
212
				d[2] = d[1] = d[0] = *s++;
213
				d[3] = *s++;
214
				d += 4;
215
			}
216
			ximage_blit(xwin, xgc,
217
				x0, y0,
218
				color,
219
				0, 0,
220
				gapp.image->w,
221
				gapp.image->h,
222
				gapp.image->w * 4);
223
			free(color);
224
		}
225
	}
226
 
227
	pdfapp_inverthit(&gapp);
228
 
229
	if (gapp.iscopying || justcopied)
230
	{
231
		pdfapp_invert(&gapp, gapp.selr);
232
		justcopied = 1;
233
	}
234
 
235
	winblitsearch(app);
236
}
237
 
238
void winrepaint(pdfapp_t *app)
239
{
240
	dirty = 1;
241
}
242
 
243
void winrepaintsearch(pdfapp_t *app)
244
{
245
	dirtysearch = 1;
246
}
247
 
248
void windrawstringxor(pdfapp_t *app, int x, int y, char *s)
249
{
250
	int prevfunction;
251
	XGCValues xgcv;
252
 
253
	XGetGCValues(xdpy, xgc, GCFunction, &xgcv);
254
	prevfunction = xgcv.function;
255
	xgcv.function = GXxor;
256
	XChangeGC(xdpy, xgc, GCFunction, &xgcv);
257
 
258
	XSetForeground(xdpy, xgc, WhitePixel(xdpy, DefaultScreen(xdpy)));
259
 
260
	XDrawString(xdpy, xwin, xgc, x, y, s, strlen(s));
261
	XFlush(xdpy);
262
 
263
	XGetGCValues(xdpy, xgc, GCFunction, &xgcv);
264
	xgcv.function = prevfunction;
265
	XChangeGC(xdpy, xgc, GCFunction, &xgcv);
266
 
267
	printf("drawstring '%s'\n", s);
268
}
269
 
270
void windrawstring(pdfapp_t *app, int x, int y, char *s)
271
{
272
	XSetForeground(xdpy, xgc, BlackPixel(xdpy, DefaultScreen(xdpy)));
273
	XDrawString(xdpy, xwin, xgc, x, y, s, strlen(s));
274
}
275
 
276
void windocopy(pdfapp_t *app)
277
{
278
/*	unsigned short copyucs2[16 * 1024];
279
	char *latin1 = copylatin1;
280
	char *utf8 = copyutf8;
281
	unsigned short *ucs2;
282
	int ucs;
283
 
284
	pdfapp_oncopy(&gapp, copyucs2, 16 * 1024);
285
 
286
	for (ucs2 = copyucs2; ucs2[0] != 0; ucs2++)
287
	{
288
		ucs = ucs2[0];
289
 
290
		utf8 += runetochar(utf8, &ucs);
291
 
292
		if (ucs < 256)
293
			*latin1++ = ucs;
294
		else
295
			*latin1++ = '?';
296
	}
297
 
298
	*utf8 = 0;
299
	*latin1 = 0;
300
 
301
	XSetSelectionOwner(xdpy, XA_PRIMARY, xwin, copytime);
302
 
303
	justcopied = 1;*/
304
}
305
 
306
void onselreq(Window requestor, Atom selection, Atom target, Atom property, Time time)
307
{
308
/*	XEvent nevt;
309
 
310
	if (property == None)
311
		property = target;
312
 
313
	nevt.xselection.type = SelectionNotify;
314
	nevt.xselection.send_event = True;
315
	nevt.xselection.display = xdpy;
316
	nevt.xselection.requestor = requestor;
317
	nevt.xselection.selection = selection;
318
	nevt.xselection.target = target;
319
	nevt.xselection.property = property;
320
	nevt.xselection.time = time;
321
 
322
	if (target == XA_TARGETS)
323
	{
324
		Atom atomlist[4];
325
		atomlist[0] = XA_TARGETS;
326
		atomlist[1] = XA_TIMESTAMP;
327
		atomlist[2] = XA_STRING;
328
		atomlist[3] = XA_UTF8_STRING;
329
		printf(" -> targets\n");
330
		XChangeProperty(xdpy, requestor, property, target,
331
			32, PropModeReplace,
332
			(unsigned char *)atomlist, sizeof(atomlist)/sizeof(Atom));
333
	}
334
 
335
	else if (target == XA_STRING)
336
	{
337
		XChangeProperty(xdpy, requestor, property, target,
338
			8, PropModeReplace,
339
			(unsigned char *)copylatin1, strlen(copylatin1));
340
	}
341
 
342
	else if (target == XA_UTF8_STRING)
343
	{
344
		XChangeProperty(xdpy, requestor, property, target,
345
			8, PropModeReplace,
346
			(unsigned char *)copyutf8, strlen(copyutf8));
347
	}
348
 
349
	else
350
	{
351
		nevt.xselection.property = None;
352
	}
353
 
354
	XSendEvent(xdpy, requestor, False, SelectionNotify, &nevt);
355
	* */
356
}
357
 
358
void winreloadfile(pdfapp_t *app)
359
{
360
	int fd;
361
 
362
	pdfapp_close(app);
363
 
364
	fd = open(filename, O_BINARY | O_RDONLY, 0666);
365
	if (fd < 0)
366
		winerror(app, fz_throw("cannot reload file '%s'", filename));
367
 
368
	pdfapp_open(app, filename, fd, 1);
369
}
370
 
371
void winopenuri(pdfapp_t *app, char *buf)
372
{
373
	/*
374
	char *browser = getenv("BROWSER");
375
	if (!browser)
376
		browser = "open";
377
	if (fork() == 0)
378
		execlp(browser, browser, buf, (char*)0);
379
		* */
380
 
381
}
382
 
383
static void onkey(int c)
384
{
385
/*	if (justcopied)
386
	{
387
		justcopied = 0;
388
		winrepaint(&gapp);
389
	}
390
	* */
391
 
392
	pdfapp_onkey(&gapp, c);
393
}
394
 
395
static void onmouse(int x, int y, int btn, int modifiers, int state)
396
{
397
/*	if (state != 0 && justcopied)
398
	{
399
		justcopied = 0;
400
		winrepaint(&gapp);
401
	}*/
402
 
403
	pdfapp_onmouse(&gapp, x, y, btn, modifiers, state);
404
}
405
 
406
static void signal_handler(int signal)
407
{
408
	/*
409
	if (signal == SIGHUP)
410
		reloading = 1;
411
		* */
412
 
413
}
414
 
415
static void usage(void)
416
{
417
	fprintf(stderr, "usage: mupdf [options] file.pdf [page]\n");
418
	fprintf(stderr, "\t-b -\tset anti-aliasing quality in bits (0=off, 8=best)\n");
419
	fprintf(stderr, "\t-p -\tpassword\n");
420
	fprintf(stderr, "\t-r -\tresolution\n");
421
	fprintf(stderr, "\t-A\tdisable accelerated functions\n");
422
	exit(1);
423
}
424
 
425
int main(int argc, char **argv)
426
{
427
	int c;
428
	int len;
429
	char buf[128];
430
	KeySym keysym;
431
	int oldx = 0;
432
	int oldy = 0;
433
	int resolution = 72;
434
	int pageno = 1;
435
	int accelerate = 1;
436
	int fd;
437
	fd_set fds;
438
	int width = -1;
439
	int height = -1;
440
 
441
	while ((c = fz_getopt(argc, argv, "p:r:b:A")) != -1)
442
	{
443
		switch (c)
444
		{
445
		case 'p': password = fz_optarg; break;
446
		case 'r': resolution = atoi(fz_optarg); break;
447
		case 'A': accelerate = 0; break;
448
		case 'b': fz_set_aa_level(atoi(fz_optarg)); break;
449
		default: usage();
450
		}
451
	}
452
 
453
	if (resolution < MINRES)
454
		resolution = MINRES;
455
	if (resolution > MAXRES)
456
		resolution = MAXRES;
457
 
458
	if (argc - fz_optind == 0)
459
		usage();
460
 
461
	filename = argv[fz_optind++];
462
 
463
	if (argc - fz_optind == 1)
464
		pageno = atoi(argv[fz_optind++]);
465
 
466
	if (accelerate)
467
		fz_accelerate();
468
 
469
	winopen();
470
 
471
	pdfapp_init(&gapp);
472
	gapp.scrw = DisplayWidth(xdpy, xscr);
473
	gapp.scrh = DisplayHeight(xdpy, xscr);
474
	gapp.resolution = resolution;
475
	gapp.pageno = pageno;
476
 
477
	fd = open(filename, O_BINARY | O_RDONLY, 0666);
478
	if (fd < 0)
479
		winerror(&gapp, fz_throw("cannot open file '%s'", filename));
480
 
481
	pdfapp_open(&gapp, filename, fd, 0);
482
 
483
	FD_ZERO(&fds);
484
	FD_SET(x11fd, &fds);
485
 
486
	signal(SIGHUP, signal_handler);
487
 
488
	while (!closing)
489
	{
490
		do
491
		{
492
			XNextEvent(xdpy, &xevt);
493
 
494
			switch (xevt.type)
495
			{
496
			case Expose:
497
				dirty = 1;
498
				break;
499
 
500
			case ConfigureNotify:
501
				if (gapp.image)
502
				{
503
					if (xevt.xconfigure.width != reqw ||
504
						xevt.xconfigure.height != reqh)
505
						gapp.shrinkwrap = 0;
506
				}
507
				width = xevt.xconfigure.width;
508
				height = xevt.xconfigure.height;
509
 
510
				break;
511
 
512
			case KeyPress:
513
				len = XLookupString(&xevt.xkey, buf, sizeof buf, &keysym, NULL);
514
 
515
				if (!gapp.isediting)
516
					switch (keysym)
517
					{
518
					case XK_Escape:
519
						len = 1; buf[0] = '\033';
520
						break;
521
 
522
					case XK_Up:
523
						len = 1; buf[0] = 'k';
524
						break;
525
					case XK_Down:
526
						len = 1; buf[0] = 'j';
527
						break;
528
 
529
					case XK_Left:
530
						len = 1; buf[0] = 'b';
531
						break;
532
					case XK_Right:
533
						len = 1; buf[0] = ' ';
534
						break;
535
 
536
					case XK_Page_Up:
537
						len = 1; buf[0] = ',';
538
						break;
539
					case XK_Page_Down:
540
						len = 1; buf[0] = '.';
541
						break;
542
					}
543
				if (len)
544
					onkey(buf[0]);
545
 
546
				onmouse(oldx, oldy, 0, 0, 0);
547
 
548
				break;
549
 
550
			case MotionNotify:
551
				oldx = xevt.xbutton.x;
552
				oldy = xevt.xbutton.y;
553
				onmouse(xevt.xbutton.x, xevt.xbutton.y, xevt.xbutton.button, xevt.xbutton.state, 0);
554
				break;
555
 
556
			case ButtonPress:
557
				onmouse(xevt.xbutton.x, xevt.xbutton.y, xevt.xbutton.button, xevt.xbutton.state, 1);
558
				break;
559
 
560
			case ButtonRelease:
561
				copytime = xevt.xbutton.time;
562
				onmouse(xevt.xbutton.x, xevt.xbutton.y, xevt.xbutton.button, xevt.xbutton.state, -1);
563
				break;
564
 
565
			case SelectionRequest:
566
				onselreq(xevt.xselectionrequest.requestor,
567
					xevt.xselectionrequest.selection,
568
					xevt.xselectionrequest.target,
569
					xevt.xselectionrequest.property,
570
					xevt.xselectionrequest.time);
571
				break;
572
 
573
			case ClientMessage:
574
				if (xevt.xclient.format == 32 && xevt.xclient.data.l[0] == WM_DELETE_WINDOW)
575
					closing = 1;
576
				break;
577
			}
578
		}
579
		while (!closing && XPending(xdpy));
580
 
581
		if (closing)
582
			continue;
583
 
584
		if (width != -1 || height != -1)
585
		{
586
			pdfapp_onresize(&gapp, width, height);
587
			width = -1;
588
			height = -1;
589
		}
590
 
591
		if (dirty || dirtysearch)
592
		{
593
			if (dirty)
594
				winblit(&gapp);
595
			else if (dirtysearch)
596
				winblitsearch(&gapp);
597
			dirty = 0;
598
			dirtysearch = 0;
599
		}
600
 
601
		if (XPending(xdpy))
602
			continue;
603
 
604
		if (select(x11fd + 1, &fds, NULL, NULL, NULL) < 0)
605
		{
606
			if (reloading)
607
			{
608
				winreloadfile(&gapp);
609
				reloading = 0;
610
			}
611
		}
612
	}
613
 
614
	pdfapp_close(&gapp);
615
 
616
	XDestroyWindow(xdpy, xwin);
617
 
618
	XFreePixmap(xdpy, xicon);
619
 
620
	XFreeCursor(xdpy, xcwait);
621
	XFreeCursor(xdpy, xchand);
622
	XFreeCursor(xdpy, xcarrow);
623
 
624
	XFreeGC(xdpy, xgc);
625
 
626
	XCloseDisplay(xdpy);
627
 
628
	return 0;
629
}