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
#ifndef UNICODE
7
#define UNICODE
8
#endif
9
#ifndef _UNICODE
10
#define _UNICODE
11
#endif
12
#define WIN32_LEAN_AND_MEAN
13
#include 
14
#include 
15
#include 
16
 
17
#ifndef WM_MOUSEWHEEL
18
#define WM_MOUSEWHEEL 0x020A
19
#endif
20
 
21
#define ID_ABOUT	0x1000
22
#define ID_DOCINFO	0x1001
23
 
24
static HWND hwndframe = NULL;
25
static HWND hwndview = NULL;
26
static HDC hdc;
27
static HBRUSH bgbrush;
28
static HBRUSH shbrush;
29
static BITMAPINFO *dibinf;
30
static HCURSOR arrowcurs, handcurs, waitcurs;
31
static LRESULT CALLBACK frameproc(HWND, UINT, WPARAM, LPARAM);
32
static LRESULT CALLBACK viewproc(HWND, UINT, WPARAM, LPARAM);
33
 
34
static int justcopied = 0;
35
 
36
static pdfapp_t gapp;
37
 
38
static wchar_t wbuf[1024];
39
static char filename[1024];
40
 
41
/*
42
 * Create registry keys to associate MuPDF with PDF and XPS files.
43
 */
44
 
45
#define OPEN_KEY(parent, name, ptr) \
46
	RegCreateKeyExA(parent, name, 0, 0, 0, KEY_WRITE, 0, &ptr, 0)
47
 
48
#define SET_KEY(parent, name, value) \
49
	RegSetValueExA(parent, name, 0, REG_SZ, value, strlen(value) + 1)
50
 
51
void install_app(char *argv0)
52
{
53
	char buf[512];
54
	HKEY software, classes, mupdf, dotpdf, dotxps;
55
	HKEY shell, open, command, supported_types;
56
	HKEY pdf_progids, xps_progids;
57
 
58
	OPEN_KEY(HKEY_CURRENT_USER, "Software", software);
59
	OPEN_KEY(software, "Classes", classes);
60
	OPEN_KEY(classes, ".pdf", dotpdf);
61
	OPEN_KEY(dotpdf, "OpenWithProgids", pdf_progids);
62
	OPEN_KEY(classes, ".xps", dotxps);
63
	OPEN_KEY(dotxps, "OpenWithProgids", xps_progids);
64
	OPEN_KEY(classes, "MuPDF", mupdf);
65
	OPEN_KEY(mupdf, "SupportedTypes", supported_types);
66
	OPEN_KEY(mupdf, "shell", shell);
67
	OPEN_KEY(shell, "open", open);
68
	OPEN_KEY(open, "command", command);
69
 
70
	sprintf(buf, "\"%s\" \"%%1\"", argv0);
71
 
72
	SET_KEY(open, "FriendlyAppName", "MuPDF");
73
	SET_KEY(command, "", buf);
74
	SET_KEY(supported_types, ".pdf", "");
75
	SET_KEY(supported_types, ".xps", "");
76
	SET_KEY(pdf_progids, "MuPDF", "");
77
	SET_KEY(xps_progids, "MuPDF", "");
78
 
79
	RegCloseKey(dotxps);
80
	RegCloseKey(dotpdf);
81
	RegCloseKey(mupdf);
82
	RegCloseKey(classes);
83
	RegCloseKey(software);
84
}
85
 
86
/*
87
 * Dialog boxes
88
 */
89
 
90
void winwarn(pdfapp_t *app, char *msg)
91
{
92
	MessageBoxA(hwndframe, msg, "MuPDF: Warning", MB_ICONWARNING);
93
}
94
 
95
void winerror(pdfapp_t *app, fz_error error)
96
{
97
	char msgbuf[160 * 30];
98
	int i;
99
 
100
	/* TODO: redirect stderr to a log file and display here */
101
	fz_catch(error, "displaying error message to user");
102
 
103
	fz_strlcpy(msgbuf, "An error has occurred.\n\n", sizeof msgbuf);
104
	for (i = 0; i < fz_get_error_count(); i++)
105
	{
106
		fz_strlcat(msgbuf, fz_get_error_line(i), sizeof msgbuf);
107
		fz_strlcat(msgbuf, "\n", sizeof msgbuf);
108
	}
109
 
110
	MessageBoxA(hwndframe, msgbuf, "MuPDF: Error", MB_ICONERROR);
111
	exit(1);
112
}
113
 
114
void win32error(char *msg)
115
{
116
	LPSTR buf;
117
	int code = GetLastError();
118
	FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
119
		FORMAT_MESSAGE_FROM_SYSTEM |
120
		FORMAT_MESSAGE_IGNORE_INSERTS,
121
		NULL,
122
		code,
123
		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
124
		(LPSTR)&buf, 0, NULL);
125
	winerror(&gapp, fz_throw("%s:\n%s", msg, buf));
126
}
127
 
128
int winfilename(wchar_t *buf, int len)
129
{
130
	OPENFILENAME ofn;
131
	buf[0] = 0;
132
	memset(&ofn, 0, sizeof(OPENFILENAME));
133
	ofn.lStructSize = sizeof(OPENFILENAME);
134
	ofn.hwndOwner = hwndframe;
135
	ofn.lpstrFile = buf;
136
	ofn.nMaxFile = len;
137
	ofn.lpstrInitialDir = NULL;
138
	ofn.lpstrTitle = L"MuPDF: Open PDF file";
139
	ofn.lpstrFilter = L"Documents (*.pdf;*.xps)\0*.xps;*.pdf\0PDF Files (*.pdf)\0*.pdf\0XPS Files (*.xps)\0*.xps\0All Files\0*\0\0";
140
	ofn.Flags = OFN_FILEMUSTEXIST|OFN_HIDEREADONLY;
141
	return GetOpenFileNameW(&ofn);
142
}
143
 
144
static char pd_filename[256] = "The file is encrypted.";
145
static char pd_password[256] = "";
146
static int pd_okay = 0;
147
 
148
INT CALLBACK
149
dlogpassproc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
150
{
151
	switch(message)
152
	{
153
	case WM_INITDIALOG:
154
		SetDlgItemTextA(hwnd, 4, pd_filename);
155
		return TRUE;
156
	case WM_COMMAND:
157
		switch(wParam)
158
		{
159
		case 1:
160
			pd_okay = 1;
161
			GetDlgItemTextA(hwnd, 3, pd_password, sizeof pd_password);
162
			EndDialog(hwnd, 1);
163
			return TRUE;
164
		case 2:
165
			pd_okay = 0;
166
			EndDialog(hwnd, 1);
167
			return TRUE;
168
		}
169
		break;
170
	}
171
	return FALSE;
172
}
173
 
174
char *winpassword(pdfapp_t *app, char *filename)
175
{
176
	char buf[1024], *s;
177
	int code;
178
	strcpy(buf, filename);
179
	s = buf;
180
	if (strrchr(s, '\\')) s = strrchr(s, '\\') + 1;
181
	if (strrchr(s, '/')) s = strrchr(s, '/') + 1;
182
	if (strlen(s) > 32)
183
		strcpy(s + 30, "...");
184
	sprintf(pd_filename, "The file \"%s\" is encrypted.", s);
185
	code = DialogBoxW(NULL, L"IDD_DLOGPASS", hwndframe, dlogpassproc);
186
	if (code <= 0)
187
		win32error("cannot create password dialog");
188
	if (pd_okay)
189
		return pd_password;
190
	return NULL;
191
}
192
 
193
INT CALLBACK
194
dloginfoproc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
195
{
196
	char buf[256];
197
	pdf_xref *xref = gapp.xref;
198
	fz_obj *info, *obj;
199
 
200
	switch(message)
201
	{
202
	case WM_INITDIALOG:
203
 
204
		SetDlgItemTextW(hwnd, 0x10, wbuf);
205
 
206
		if (!xref)
207
		{
208
			SetDlgItemTextA(hwnd, 0x11, "XPS");
209
			SetDlgItemTextA(hwnd, 0x12, "None");
210
			SetDlgItemTextA(hwnd, 0x13, "n/a");
211
			return TRUE;
212
		}
213
 
214
		sprintf(buf, "PDF %d.%d", xref->version / 10, xref->version % 10);
215
		SetDlgItemTextA(hwnd, 0x11, buf);
216
 
217
		if (xref->crypt)
218
		{
219
			sprintf(buf, "Standard V%d %d-bit %s", pdf_get_crypt_revision(xref),
220
				pdf_get_crypt_length(xref), pdf_get_crypt_method(xref));
221
			SetDlgItemTextA(hwnd, 0x12, buf);
222
			strcpy(buf, "");
223
			if (pdf_has_permission(xref, PDF_PERM_PRINT))
224
				strcat(buf, "print, ");
225
			if (pdf_has_permission(xref, PDF_PERM_CHANGE))
226
				strcat(buf, "modify, ");
227
			if (pdf_has_permission(xref, PDF_PERM_COPY))
228
				strcat(buf, "copy, ");
229
			if (pdf_has_permission(xref, PDF_PERM_NOTES))
230
				strcat(buf, "annotate, ");
231
			if (strlen(buf) > 2)
232
				buf[strlen(buf)-2] = 0;
233
			else
234
				strcpy(buf, "none");
235
			SetDlgItemTextA(hwnd, 0x13, buf);
236
		}
237
		else
238
		{
239
			SetDlgItemTextA(hwnd, 0x12, "None");
240
			SetDlgItemTextA(hwnd, 0x13, "n/a");
241
		}
242
 
243
		info = fz_dict_gets(xref->trailer, "Info");
244
		if (!info)
245
			return TRUE;
246
 
247
#define SETUCS(ID) \
248
		{ \
249
			unsigned short *ucs; \
250
			ucs = pdf_to_ucs2(obj); \
251
			SetDlgItemTextW(hwnd, ID, ucs); \
252
			fz_free(ucs); \
253
		}
254
 
255
		if ((obj = fz_dict_gets(info, "Title")))
256
			SETUCS(0x20);
257
		if ((obj = fz_dict_gets(info, "Author")))
258
			SETUCS(0x21);
259
		if ((obj = fz_dict_gets(info, "Subject")))
260
			SETUCS(0x22);
261
		if ((obj = fz_dict_gets(info, "Keywords")))
262
			SETUCS(0x23);
263
		if ((obj = fz_dict_gets(info, "Creator")))
264
			SETUCS(0x24);
265
		if ((obj = fz_dict_gets(info, "Producer")))
266
			SETUCS(0x25);
267
		if ((obj = fz_dict_gets(info, "CreationDate")))
268
			SETUCS(0x26);
269
		if ((obj = fz_dict_gets(info, "ModDate")))
270
			SETUCS(0x27);
271
		return TRUE;
272
 
273
	case WM_COMMAND:
274
		EndDialog(hwnd, 1);
275
		return TRUE;
276
	}
277
	return FALSE;
278
}
279
 
280
void info()
281
{
282
	int code = DialogBoxW(NULL, L"IDD_DLOGINFO", hwndframe, dloginfoproc);
283
	if (code <= 0)
284
		win32error("cannot create info dialog");
285
}
286
 
287
INT CALLBACK
288
dlogaboutproc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
289
{
290
	switch(message)
291
	{
292
	case WM_INITDIALOG:
293
		SetDlgItemTextA(hwnd, 2, pdfapp_version(&gapp));
294
		SetDlgItemTextA(hwnd, 3, pdfapp_usage(&gapp));
295
		return TRUE;
296
	case WM_COMMAND:
297
		EndDialog(hwnd, 1);
298
		return TRUE;
299
	}
300
	return FALSE;
301
}
302
 
303
void winhelp(pdfapp_t*app)
304
{
305
	int code = DialogBoxW(NULL, L"IDD_DLOGABOUT", hwndframe, dlogaboutproc);
306
	if (code <= 0)
307
		win32error("cannot create help dialog");
308
}
309
 
310
/*
311
 * Main window
312
 */
313
 
314
void winopen()
315
{
316
	WNDCLASS wc;
317
	HMENU menu;
318
	RECT r;
319
	ATOM a;
320
 
321
	/* Create and register window frame class */
322
	memset(&wc, 0, sizeof(wc));
323
	wc.style = 0;
324
	wc.lpfnWndProc = frameproc;
325
	wc.cbClsExtra = 0;
326
	wc.cbWndExtra = 0;
327
	wc.hInstance = GetModuleHandle(NULL);
328
	wc.hIcon = LoadIconA(wc.hInstance, "IDI_ICONAPP");
329
	wc.hCursor = NULL; //LoadCursor(NULL, IDC_ARROW);
330
	wc.hbrBackground = NULL;
331
	wc.lpszMenuName = NULL;
332
	wc.lpszClassName = L"FrameWindow";
333
	a = RegisterClassW(&wc);
334
	if (!a)
335
		win32error("cannot register frame window class");
336
 
337
	/* Create and register window view class */
338
	memset(&wc, 0, sizeof(wc));
339
	wc.style = CS_HREDRAW | CS_VREDRAW;
340
	wc.lpfnWndProc = viewproc;
341
	wc.cbClsExtra = 0;
342
	wc.cbWndExtra = 0;
343
	wc.hInstance = GetModuleHandle(NULL);
344
	wc.hIcon = NULL;
345
	wc.hCursor = NULL;
346
	wc.hbrBackground = NULL;
347
	wc.lpszMenuName = NULL;
348
	wc.lpszClassName = L"ViewWindow";
349
	a = RegisterClassW(&wc);
350
	if (!a)
351
		win32error("cannot register view window class");
352
 
353
	/* Get screen size */
354
	SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0);
355
	gapp.scrw = r.right - r.left;
356
	gapp.scrh = r.bottom - r.top;
357
 
358
	/* Create cursors */
359
	arrowcurs = LoadCursor(NULL, IDC_ARROW);
360
	handcurs = LoadCursor(NULL, IDC_HAND);
361
	waitcurs = LoadCursor(NULL, IDC_WAIT);
362
 
363
	/* And a background color */
364
	bgbrush = CreateSolidBrush(RGB(0x70,0x70,0x70));
365
	shbrush = CreateSolidBrush(RGB(0x40,0x40,0x40));
366
 
367
	/* Init DIB info for buffer */
368
	dibinf = malloc(sizeof(BITMAPINFO) + 12);
369
	assert(dibinf != NULL);
370
	dibinf->bmiHeader.biSize = sizeof(dibinf->bmiHeader);
371
	dibinf->bmiHeader.biPlanes = 1;
372
	dibinf->bmiHeader.biBitCount = 32;
373
	dibinf->bmiHeader.biCompression = BI_RGB;
374
	dibinf->bmiHeader.biXPelsPerMeter = 2834;
375
	dibinf->bmiHeader.biYPelsPerMeter = 2834;
376
	dibinf->bmiHeader.biClrUsed = 0;
377
	dibinf->bmiHeader.biClrImportant = 0;
378
	dibinf->bmiHeader.biClrUsed = 0;
379
 
380
	/* Create window */
381
	hwndframe = CreateWindowW(L"FrameWindow", // window class name
382
	NULL, // window caption
383
	WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
384
	CW_USEDEFAULT, CW_USEDEFAULT, // initial position
385
	300, // initial x size
386
	300, // initial y size
387
	0, // parent window handle
388
	0, // window menu handle
389
	0, // program instance handle
390
	0); // creation parameters
391
	if (!hwndframe)
392
		win32error("cannot create frame: %s");
393
 
394
	hwndview = CreateWindowW(L"ViewWindow", // window class name
395
	NULL,
396
	WS_VISIBLE | WS_CHILD,
397
	CW_USEDEFAULT, CW_USEDEFAULT,
398
	CW_USEDEFAULT, CW_USEDEFAULT,
399
	hwndframe, 0, 0, 0);
400
	if (!hwndview)
401
		win32error("cannot create view: %s");
402
 
403
	hdc = NULL;
404
 
405
	SetWindowTextW(hwndframe, L"MuPDF");
406
 
407
	menu = GetSystemMenu(hwndframe, 0);
408
	AppendMenuW(menu, MF_SEPARATOR, 0, NULL);
409
	AppendMenuW(menu, MF_STRING, ID_ABOUT, L"About MuPDF...");
410
	AppendMenuW(menu, MF_STRING, ID_DOCINFO, L"Document Properties...");
411
 
412
	SetCursor(arrowcurs);
413
}
414
 
415
void winclose(pdfapp_t *app)
416
{
417
	pdfapp_close(app);
418
	exit(0);
419
}
420
 
421
void wincursor(pdfapp_t *app, int curs)
422
{
423
	if (curs == ARROW)
424
		SetCursor(arrowcurs);
425
	if (curs == HAND)
426
		SetCursor(handcurs);
427
	if (curs == WAIT)
428
		SetCursor(waitcurs);
429
}
430
 
431
void wintitle(pdfapp_t *app, char *title)
432
{
433
	wchar_t wide[256], *dp;
434
	char *sp;
435
	int rune;
436
 
437
	dp = wide;
438
	sp = title;
439
	while (*sp && dp < wide + 255)
440
	{
441
		sp += chartorune(&rune, sp);
442
		*dp++ = rune;
443
	}
444
	*dp = 0;
445
 
446
	SetWindowTextW(hwndframe, wide);
447
}
448
 
449
void windrawrect(pdfapp_t *app, int x0, int y0, int x1, int y1)
450
{
451
	RECT r;
452
	r.left = x0;
453
	r.top = y0;
454
	r.right = x1;
455
	r.bottom = y1;
456
	FillRect(hdc, &r, (HBRUSH)GetStockObject(WHITE_BRUSH));
457
}
458
 
459
void windrawstring(pdfapp_t *app, int x, int y, char *s)
460
{
461
	HFONT font = (HFONT)GetStockObject(ANSI_FIXED_FONT);
462
	SelectObject(hdc, font);
463
	TextOutA(hdc, x, y - 12, s, strlen(s));
464
}
465
 
466
void winblitsearch()
467
{
468
	if (gapp.isediting)
469
	{
470
		char buf[sizeof(gapp.search) + 50];
471
		sprintf(buf, "Search: %s", gapp.search);
472
		windrawrect(&gapp, 0, 0, gapp.winw, 30);
473
		windrawstring(&gapp, 10, 20, buf);
474
	}
475
}
476
 
477
void winblit()
478
{
479
	int x0 = gapp.panx;
480
	int y0 = gapp.pany;
481
	int x1 = gapp.panx + gapp.image->w;
482
	int y1 = gapp.pany + gapp.image->h;
483
	RECT r;
484
 
485
	if (gapp.image)
486
	{
487
		if (gapp.iscopying || justcopied)
488
		{
489
			pdfapp_invert(&gapp, gapp.selr);
490
			justcopied = 1;
491
		}
492
 
493
		pdfapp_inverthit(&gapp);
494
 
495
		dibinf->bmiHeader.biWidth = gapp.image->w;
496
		dibinf->bmiHeader.biHeight = -gapp.image->h;
497
		dibinf->bmiHeader.biSizeImage = gapp.image->h * 4;
498
 
499
		if (gapp.image->n == 2)
500
		{
501
			int i = gapp.image->w * gapp.image->h;
502
			unsigned char *color = malloc(i*4);
503
			unsigned char *s = gapp.image->samples;
504
			unsigned char *d = color;
505
			for (; i > 0 ; i--)
506
			{
507
				d[2] = d[1] = d[0] = *s++;
508
				d[3] = *s++;
509
				d += 4;
510
			}
511
			SetDIBitsToDevice(hdc,
512
				gapp.panx, gapp.pany, gapp.image->w, gapp.image->h,
513
				0, 0, 0, gapp.image->h, color,
514
				dibinf, DIB_RGB_COLORS);
515
			free(color);
516
		}
517
		if (gapp.image->n == 4)
518
		{
519
			SetDIBitsToDevice(hdc,
520
				gapp.panx, gapp.pany, gapp.image->w, gapp.image->h,
521
				0, 0, 0, gapp.image->h, gapp.image->samples,
522
				dibinf, DIB_RGB_COLORS);
523
		}
524
 
525
		pdfapp_inverthit(&gapp);
526
 
527
		if (gapp.iscopying || justcopied)
528
		{
529
			pdfapp_invert(&gapp, gapp.selr);
530
			justcopied = 1;
531
		}
532
	}
533
 
534
	/* Grey background */
535
	r.top = 0; r.bottom = gapp.winh;
536
	r.left = 0; r.right = x0;
537
	FillRect(hdc, &r, bgbrush);
538
	r.left = x1; r.right = gapp.winw;
539
	FillRect(hdc, &r, bgbrush);
540
	r.left = 0; r.right = gapp.winw;
541
	r.top = 0; r.bottom = y0;
542
	FillRect(hdc, &r, bgbrush);
543
	r.top = y1; r.bottom = gapp.winh;
544
	FillRect(hdc, &r, bgbrush);
545
 
546
	/* Drop shadow */
547
	r.left = x0 + 2;
548
	r.right = x1 + 2;
549
	r.top = y1;
550
	r.bottom = y1 + 2;
551
	FillRect(hdc, &r, shbrush);
552
	r.left = x1;
553
	r.right = x1 + 2;
554
	r.top = y0 + 2;
555
	r.bottom = y1;
556
	FillRect(hdc, &r, shbrush);
557
 
558
	winblitsearch();
559
}
560
 
561
void winresize(pdfapp_t *app, int w, int h)
562
{
563
	ShowWindow(hwndframe, SW_SHOWDEFAULT);
564
	w += GetSystemMetrics(SM_CXFRAME) * 2;
565
	h += GetSystemMetrics(SM_CYFRAME) * 2;
566
	h += GetSystemMetrics(SM_CYCAPTION);
567
	SetWindowPos(hwndframe, 0, 0, 0, w, h, SWP_NOZORDER | SWP_NOMOVE);
568
}
569
 
570
void winrepaint(pdfapp_t *app)
571
{
572
	InvalidateRect(hwndview, NULL, 0);
573
}
574
 
575
void winrepaintsearch(pdfapp_t *app)
576
{
577
	// TODO: invalidate only search area and
578
	// call only search redraw routine.
579
	InvalidateRect(hwndview, NULL, 0);
580
}
581
 
582
/*
583
 * Event handling
584
 */
585
 
586
void windocopy(pdfapp_t *app)
587
{
588
	HGLOBAL handle;
589
	unsigned short *ucsbuf;
590
 
591
	if (!OpenClipboard(hwndframe))
592
		return;
593
	EmptyClipboard();
594
 
595
	handle = GlobalAlloc(GMEM_MOVEABLE, 4096 * sizeof(unsigned short));
596
	if (!handle)
597
	{
598
		CloseClipboard();
599
		return;
600
	}
601
 
602
	ucsbuf = GlobalLock(handle);
603
	pdfapp_oncopy(&gapp, ucsbuf, 4096);
604
	GlobalUnlock(handle);
605
 
606
	SetClipboardData(CF_UNICODETEXT, handle);
607
	CloseClipboard();
608
 
609
	justcopied = 1;	/* keep inversion around for a while... */
610
}
611
 
612
void winreloadfile(pdfapp_t *app)
613
{
614
	int fd;
615
 
616
	pdfapp_close(app);
617
 
618
	fd = _wopen(wbuf, O_BINARY | O_RDONLY, 0666);
619
	if (fd < 0)
620
		winerror(&gapp, fz_throw("cannot reload file '%s'", filename));
621
 
622
	pdfapp_open(app, filename, fd, 1);
623
}
624
 
625
void winopenuri(pdfapp_t *app, char *buf)
626
{
627
	ShellExecuteA(hwndframe, "open", buf, 0, 0, SW_SHOWNORMAL);
628
}
629
 
630
void handlekey(int c)
631
{
632
	if (GetCapture() == hwndview)
633
		return;
634
 
635
	if (justcopied)
636
	{
637
		justcopied = 0;
638
		winrepaint(&gapp);
639
	}
640
 
641
	/* translate VK into ascii equivalents */
642
	if (c > 256)
643
	{
644
		switch (c - 256)
645
		{
646
		case VK_F1: c = '?'; break;
647
		case VK_ESCAPE: c = '\033'; break;
648
		case VK_DOWN: c = 'j'; break;
649
		case VK_UP: c = 'k'; break;
650
		case VK_LEFT: c = 'b'; break;
651
		case VK_RIGHT: c = ' '; break;
652
		case VK_PRIOR: c = ','; break;
653
		case VK_NEXT: c = '.'; break;
654
		}
655
	}
656
 
657
	pdfapp_onkey(&gapp, c);
658
	winrepaint(&gapp);
659
}
660
 
661
void handlemouse(int x, int y, int btn, int state)
662
{
663
	if (state != 0 && justcopied)
664
	{
665
		justcopied = 0;
666
		winrepaint(&gapp);
667
	}
668
 
669
	if (state == 1)
670
		SetCapture(hwndview);
671
	if (state == -1)
672
		ReleaseCapture();
673
 
674
	pdfapp_onmouse(&gapp, x, y, btn, 0, state);
675
}
676
 
677
LRESULT CALLBACK
678
frameproc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
679
{
680
	switch(message)
681
	{
682
	case WM_SETFOCUS:
683
		PostMessage(hwnd, WM_APP+5, 0, 0);
684
		return 0;
685
	case WM_APP+5:
686
		SetFocus(hwndview);
687
		return 0;
688
 
689
	case WM_DESTROY:
690
		PostQuitMessage(0);
691
		return 0;
692
 
693
	case WM_SYSCOMMAND:
694
		if (wParam == ID_ABOUT)
695
		{
696
			winhelp(&gapp);
697
			return 0;
698
		}
699
		if (wParam == ID_DOCINFO)
700
		{
701
			info();
702
			return 0;
703
		}
704
		if (wParam == SC_MAXIMIZE)
705
			gapp.shrinkwrap = 0;
706
		break;
707
 
708
	case WM_SIZE:
709
	{
710
		// More generally, you should use GetEffectiveClientRect
711
		// if you have a toolbar etc.
712
		RECT rect;
713
		GetClientRect(hwnd, &rect);
714
		MoveWindow(hwndview, rect.left, rect.top,
715
		rect.right-rect.left, rect.bottom-rect.top, TRUE);
716
		return 0;
717
	}
718
 
719
	case WM_SIZING:
720
		gapp.shrinkwrap = 0;
721
		break;
722
 
723
	case WM_NOTIFY:
724
	case WM_COMMAND:
725
		return SendMessage(hwndview, message, wParam, lParam);
726
	}
727
 
728
	return DefWindowProc(hwnd, message, wParam, lParam);
729
}
730
 
731
LRESULT CALLBACK
732
viewproc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
733
{
734
	static int oldx = 0;
735
	static int oldy = 0;
736
	int x = (signed short) LOWORD(lParam);
737
	int y = (signed short) HIWORD(lParam);
738
 
739
	switch (message)
740
	{
741
	case WM_SIZE:
742
		if (wParam == SIZE_MINIMIZED)
743
			return 0;
744
		if (wParam == SIZE_MAXIMIZED)
745
			gapp.shrinkwrap = 0;
746
		pdfapp_onresize(&gapp, LOWORD(lParam), HIWORD(lParam));
747
		break;
748
 
749
	/* Paint events are low priority and automagically catenated
750
	 * so we don't need to do any fancy waiting to defer repainting.
751
	 */
752
	case WM_PAINT:
753
	{
754
		//puts("WM_PAINT");
755
		PAINTSTRUCT ps;
756
		hdc = BeginPaint(hwnd, &ps);
757
		winblit();
758
		hdc = NULL;
759
		EndPaint(hwnd, &ps);
760
		return 0;
761
	}
762
 
763
	case WM_ERASEBKGND:
764
		return 1; // well, we don't need to erase to redraw cleanly
765
 
766
	/* Mouse events */
767
 
768
	case WM_LBUTTONDOWN:
769
		SetFocus(hwndview);
770
		oldx = x; oldy = y;
771
		handlemouse(x, y, 1, 1);
772
		return 0;
773
	case WM_MBUTTONDOWN:
774
		SetFocus(hwndview);
775
		oldx = x; oldy = y;
776
		handlemouse(x, y, 2, 1);
777
		return 0;
778
	case WM_RBUTTONDOWN:
779
		SetFocus(hwndview);
780
		oldx = x; oldy = y;
781
		handlemouse(x, y, 3, 1);
782
		return 0;
783
 
784
	case WM_LBUTTONUP:
785
		oldx = x; oldy = y;
786
		handlemouse(x, y, 1, -1);
787
		return 0;
788
	case WM_MBUTTONUP:
789
		oldx = x; oldy = y;
790
		handlemouse(x, y, 2, -1);
791
		return 0;
792
	case WM_RBUTTONUP:
793
		oldx = x; oldy = y;
794
		handlemouse(x, y, 3, -1);
795
		return 0;
796
 
797
	case WM_MOUSEMOVE:
798
		oldx = x; oldy = y;
799
		handlemouse(x, y, 0, 0);
800
		return 0;
801
 
802
	/* Mouse wheel */
803
 
804
	case WM_MOUSEWHEEL:
805
		if ((signed short)HIWORD(wParam) > 0)
806
			handlekey(LOWORD(wParam) & MK_SHIFT ? '+' : 'k');
807
		else
808
			handlekey(LOWORD(wParam) & MK_SHIFT ? '-' : 'j');
809
		return 0;
810
 
811
	/* Keyboard events */
812
 
813
	case WM_KEYDOWN:
814
		/* only handle special keys */
815
		switch (wParam)
816
		{
817
		case VK_F1:
818
		case VK_LEFT:
819
		case VK_UP:
820
		case VK_PRIOR:
821
		case VK_RIGHT:
822
		case VK_DOWN:
823
		case VK_NEXT:
824
		case VK_ESCAPE:
825
			handlekey(wParam + 256);
826
			handlemouse(oldx, oldy, 0, 0);	/* update cursor */
827
			return 0;
828
		}
829
		return 1;
830
 
831
	/* unicode encoded chars, including escape, backspace etc... */
832
	case WM_CHAR:
833
		if (wParam < 256)
834
		{
835
			handlekey(wParam);
836
			handlemouse(oldx, oldy, 0, 0);	/* update cursor */
837
		}
838
		return 0;
839
	}
840
 
841
	fflush(stdout);
842
 
843
	/* Pass on unhandled events to Windows */
844
	return DefWindowProc(hwnd, message, wParam, lParam);
845
}
846
 
847
int WINAPI
848
WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
849
{
850
	int argc;
851
	LPWSTR *argv = CommandLineToArgvW(GetCommandLineW(), &argc);
852
	char argv0[256];
853
	MSG msg;
854
	int fd;
855
	int code;
856
 
857
	fz_accelerate();
858
 
859
	pdfapp_init(&gapp);
860
 
861
	GetModuleFileNameA(NULL, argv0, sizeof argv0);
862
	install_app(argv0);
863
 
864
	winopen();
865
 
866
	if (argc == 2)
867
	{
868
		wcscpy(wbuf, argv[1]);
869
	}
870
	else
871
	{
872
		if (!winfilename(wbuf, nelem(wbuf)))
873
			exit(0);
874
	}
875
 
876
	fd = _wopen(wbuf, O_BINARY | O_RDONLY, 0666);
877
	if (fd < 0)
878
		winerror(&gapp, fz_throw("cannot open file '%s'", filename));
879
 
880
	code = WideCharToMultiByte(CP_UTF8, 0, wbuf, -1, filename, sizeof filename, NULL, NULL);
881
	if (code == 0)
882
		win32error("cannot convert filename to utf-8");
883
 
884
	pdfapp_open(&gapp, filename, fd, 0);
885
 
886
	while (GetMessage(&msg, NULL, 0, 0))
887
	{
888
		TranslateMessage(&msg);
889
		DispatchMessage(&msg);
890
	}
891
 
892
	pdfapp_close(&gapp);
893
 
894
	return 0;
895
}