comdlg32: Fix some alignment issues in the Dutch translation.
[wine/hramrach.git] / programs / wordpad / print.c
blob226052e30461dcfc1a91f7902f8e93e368e0462e
1 /*
2 * Wordpad implementation - Printing and print preview functions
4 * Copyright 2007-2008 by Alexander N. Sørnes <alex@thehandofagony.com>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <windows.h>
22 #include <richedit.h>
23 #include <commctrl.h>
25 #include "wordpad.h"
27 typedef struct _previewinfo
29 int page;
30 int pages_shown;
31 int saved_pages_shown;
32 int *pageEnds, pageCapacity;
33 int textlength;
34 HDC hdc;
35 HDC hdc2;
36 HDC hdcSized;
37 HDC hdcSized2;
38 RECT window;
39 RECT rcPage;
40 SIZE bmSize;
41 SIZE bmScaledSize;
42 SIZE spacing;
43 float zoomratio;
44 int zoomlevel;
45 LPWSTR wszFileName;
46 } previewinfo, *ppreviewinfo;
48 static HGLOBAL devMode;
49 static HGLOBAL devNames;
51 static RECT margins;
52 static previewinfo preview;
54 extern const WCHAR wszPreviewWndClass[];
56 static const WCHAR var_pagemargin[] = {'P','a','g','e','M','a','r','g','i','n',0};
57 static const WCHAR var_previewpages[] = {'P','r','e','v','i','e','w','P','a','g','e','s',0};
59 static LPWSTR get_print_file_filter(HWND hMainWnd)
61 static WCHAR wszPrintFilter[MAX_STRING_LEN*2+6+4+1];
62 const WCHAR files_prn[] = {'*','.','P','R','N',0};
63 const WCHAR files_all[] = {'*','.','*','\0'};
64 LPWSTR p;
65 HINSTANCE hInstance = GetModuleHandleW(0);
67 p = wszPrintFilter;
68 LoadStringW(hInstance, STRING_PRINTER_FILES_PRN, p, MAX_STRING_LEN);
69 p += lstrlenW(p) + 1;
70 lstrcpyW(p, files_prn);
71 p += lstrlenW(p) + 1;
72 LoadStringW(hInstance, STRING_ALL_FILES, p, MAX_STRING_LEN);
73 p += lstrlenW(p) + 1;
74 lstrcpyW(p, files_all);
75 p += lstrlenW(p) + 1;
76 *p = 0;
78 return wszPrintFilter;
81 void registry_set_pagemargins(HKEY hKey)
83 RegSetValueExW(hKey, var_pagemargin, 0, REG_BINARY, (LPBYTE)&margins, sizeof(RECT));
86 void registry_read_pagemargins(HKEY hKey)
88 DWORD size = sizeof(RECT);
90 if(!hKey || RegQueryValueExW(hKey, var_pagemargin, 0, NULL, (LPBYTE)&margins,
91 &size) != ERROR_SUCCESS || size != sizeof(RECT))
93 margins.top = 1417;
94 margins.bottom = 1417;
95 margins.left = 1757;
96 margins.right = 1757;
100 void registry_set_previewpages(HKEY hKey)
102 RegSetValueExW(hKey, var_previewpages, 0, REG_DWORD,
103 (LPBYTE)&preview.pages_shown, sizeof(DWORD));
106 void registry_read_previewpages(HKEY hKey)
108 DWORD size = sizeof(DWORD);
109 if(!hKey ||
110 RegQueryValueExW(hKey, var_previewpages, 0, NULL,
111 (LPBYTE)&preview.pages_shown, &size) != ERROR_SUCCESS ||
112 size != sizeof(DWORD))
114 preview.pages_shown = 1;
115 } else {
116 if (preview.pages_shown < 1) preview.pages_shown = 1;
117 else if (preview.pages_shown > 2) preview.pages_shown = 2;
122 static void AddTextButton(HWND hRebarWnd, UINT string, UINT command, UINT id)
124 REBARBANDINFOW rb;
125 HINSTANCE hInstance = GetModuleHandleW(0);
126 WCHAR text[MAX_STRING_LEN];
127 HWND hButton;
129 LoadStringW(hInstance, string, text, MAX_STRING_LEN);
130 hButton = CreateWindowW(WC_BUTTONW, text,
131 WS_VISIBLE | WS_CHILD, 5, 5, 100, 15,
132 hRebarWnd, ULongToHandle(command), hInstance, NULL);
134 rb.cbSize = REBARBANDINFOW_V6_SIZE;
135 rb.fMask = RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_STYLE | RBBIM_CHILD | RBBIM_IDEALSIZE | RBBIM_ID;
136 rb.fStyle = RBBS_NOGRIPPER | RBBS_VARIABLEHEIGHT;
137 rb.hwndChild = hButton;
138 rb.cyChild = rb.cyMinChild = 22;
139 rb.cx = rb.cxMinChild = 90;
140 rb.cxIdeal = 100;
141 rb.wID = id;
143 SendMessageW(hRebarWnd, RB_INSERTBAND, -1, (LPARAM)&rb);
146 static HDC make_dc(void)
148 if(devNames && devMode)
150 LPDEVNAMES dn = GlobalLock(devNames);
151 LPDEVMODEW dm = GlobalLock(devMode);
152 HDC ret;
154 ret = CreateDCW((LPWSTR)dn + dn->wDriverOffset,
155 (LPWSTR)dn + dn->wDeviceOffset, 0, dm);
157 GlobalUnlock(dn);
158 GlobalUnlock(dm);
160 return ret;
161 } else
163 return 0;
167 static LONG twips_to_centmm(int twips)
169 return MulDiv(twips, CENTMM_PER_INCH, TWIPS_PER_INCH);
172 static LONG centmm_to_twips(int mm)
174 return MulDiv(mm, TWIPS_PER_INCH, CENTMM_PER_INCH);
177 static LONG twips_to_pixels(int twips, int dpi)
179 return MulDiv(twips, dpi, TWIPS_PER_INCH);
182 static LONG devunits_to_twips(int units, int dpi)
184 return MulDiv(units, TWIPS_PER_INCH, dpi);
188 static RECT get_print_rect(HDC hdc)
190 RECT rc;
191 int width, height;
193 if(hdc)
195 int dpiY = GetDeviceCaps(hdc, LOGPIXELSY);
196 int dpiX = GetDeviceCaps(hdc, LOGPIXELSX);
197 width = devunits_to_twips(GetDeviceCaps(hdc, PHYSICALWIDTH), dpiX);
198 height = devunits_to_twips(GetDeviceCaps(hdc, PHYSICALHEIGHT), dpiY);
199 } else
201 width = centmm_to_twips(18500);
202 height = centmm_to_twips(27000);
205 rc.left = margins.left;
206 rc.right = width - margins.right;
207 rc.top = margins.top;
208 rc.bottom = height - margins.bottom;
210 return rc;
213 void target_device(HWND hMainWnd, DWORD wordWrap)
215 HWND hEditorWnd = GetDlgItem(hMainWnd, IDC_EDITOR);
217 if(wordWrap == ID_WORDWRAP_MARGIN)
219 int width = 0;
220 LRESULT result;
221 HDC hdc = make_dc();
222 RECT rc = get_print_rect(hdc);
224 width = rc.right - rc.left;
225 if(!hdc)
227 HDC hMaindc = GetDC(hMainWnd);
228 hdc = CreateCompatibleDC(hMaindc);
229 ReleaseDC(hMainWnd, hMaindc);
231 result = SendMessageW(hEditorWnd, EM_SETTARGETDEVICE, (WPARAM)hdc, width);
232 DeleteDC(hdc);
233 if (result)
234 return;
235 /* otherwise EM_SETTARGETDEVICE failed, so fall back on wrapping
236 * to window using the NULL DC. */
239 if (wordWrap != ID_WORDWRAP_NONE) {
240 SendMessageW(hEditorWnd, EM_SETTARGETDEVICE, 0, 0);
241 } else {
242 SendMessageW(hEditorWnd, EM_SETTARGETDEVICE, 0, 1);
247 static LPWSTR dialog_print_to_file(HWND hMainWnd)
249 OPENFILENAMEW ofn;
250 static WCHAR file[MAX_PATH] = {'O','U','T','P','U','T','.','P','R','N',0};
251 static const WCHAR defExt[] = {'P','R','N',0};
252 static LPWSTR file_filter;
254 if(!file_filter)
255 file_filter = get_print_file_filter(hMainWnd);
257 ZeroMemory(&ofn, sizeof(ofn));
259 ofn.lStructSize = sizeof(ofn);
260 ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
261 ofn.hwndOwner = hMainWnd;
262 ofn.lpstrFilter = file_filter;
263 ofn.lpstrFile = file;
264 ofn.nMaxFile = MAX_PATH;
265 ofn.lpstrDefExt = defExt;
267 if(GetSaveFileNameW(&ofn))
268 return file;
269 else
270 return FALSE;
273 static void char_from_pagenum(HWND hEditorWnd, FORMATRANGE *fr, int page)
275 int i;
277 fr->chrg.cpMin = 0;
279 for(i = 1; i < page; i++)
281 int bottom = fr->rc.bottom;
282 fr->chrg.cpMin = SendMessageW(hEditorWnd, EM_FORMATRANGE, FALSE, (LPARAM)fr);
283 fr->rc.bottom = bottom;
287 static HWND get_ruler_wnd(HWND hMainWnd)
289 return GetDlgItem(GetDlgItem(hMainWnd, IDC_REBAR), IDC_RULER);
292 void redraw_ruler(HWND hRulerWnd)
294 RECT rc;
296 GetClientRect(hRulerWnd, &rc);
297 InvalidateRect(hRulerWnd, &rc, TRUE);
300 static void update_ruler(HWND hRulerWnd)
302 SendMessageW(hRulerWnd, WM_USER, 0, 0);
303 redraw_ruler(hRulerWnd);
306 static void add_ruler_units(HDC hdcRuler, RECT* drawRect, BOOL NewMetrics, LONG EditLeftmost)
308 static HDC hdc;
310 if(NewMetrics)
312 static HBITMAP hBitmap;
313 int i, x, y, RulerTextEnd;
314 int CmPixels;
315 int QuarterCmPixels;
316 HFONT hFont;
317 WCHAR FontName[] = {'M','S',' ','S','a','n','s',' ','S','e','r','i','f',0};
319 if(hdc)
321 DeleteDC(hdc);
322 DeleteObject(hBitmap);
325 hdc = CreateCompatibleDC(0);
327 CmPixels = twips_to_pixels(centmm_to_twips(1000), GetDeviceCaps(hdc, LOGPIXELSX));
328 QuarterCmPixels = (int)((float)CmPixels / 4.0);
330 hBitmap = CreateCompatibleBitmap(hdc, drawRect->right, drawRect->bottom);
331 SelectObject(hdc, hBitmap);
332 FillRect(hdc, drawRect, GetStockObject(WHITE_BRUSH));
334 hFont = CreateFontW(10, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, FontName);
336 SelectObject(hdc, hFont);
337 SetBkMode(hdc, TRANSPARENT);
338 SetTextAlign(hdc, TA_CENTER);
339 y = (int)(((float)drawRect->bottom - (float)drawRect->top) / 2.0) + 1;
340 RulerTextEnd = drawRect->right - EditLeftmost + 1;
341 for(i = 1, x = EditLeftmost; x < (drawRect->right - EditLeftmost + 1); i ++)
343 WCHAR str[3];
344 WCHAR format[] = {'%','d',0};
345 int x2 = x;
347 x2 += QuarterCmPixels;
348 if(x2 > RulerTextEnd)
349 break;
351 MoveToEx(hdc, x2, y, NULL);
352 LineTo(hdc, x2, y+2);
354 x2 += QuarterCmPixels;
355 if(x2 > RulerTextEnd)
356 break;
358 MoveToEx(hdc, x2, y - 3, NULL);
359 LineTo(hdc, x2, y + 3);
361 x2 += QuarterCmPixels;
362 if(x2 > RulerTextEnd)
363 break;
365 MoveToEx(hdc, x2, y, NULL);
366 LineTo(hdc, x2, y+2);
368 x += CmPixels;
369 if(x > RulerTextEnd)
370 break;
372 wsprintfW(str, format, i);
373 TextOutW(hdc, x, 5, str, lstrlenW(str));
375 DeleteObject(hFont);
378 BitBlt(hdcRuler, 0, 0, drawRect->right, drawRect->bottom, hdc, 0, 0, SRCAND);
381 static void paint_ruler(HWND hWnd, LONG EditLeftmost, BOOL NewMetrics)
383 PAINTSTRUCT ps;
384 HDC hdc = BeginPaint(hWnd, &ps);
385 HDC hdcPrint = make_dc();
386 RECT printRect = get_print_rect(hdcPrint);
387 RECT drawRect;
388 HBRUSH hBrush = CreateSolidBrush(GetSysColor(COLOR_MENU));
390 GetClientRect(hWnd, &drawRect);
391 FillRect(hdc, &drawRect, hBrush);
393 drawRect.top += 3;
394 drawRect.bottom -= 3;
395 drawRect.left = EditLeftmost;
396 drawRect.right = twips_to_pixels(printRect.right - margins.left, GetDeviceCaps(hdc, LOGPIXELSX));
397 FillRect(hdc, &drawRect, GetStockObject(WHITE_BRUSH));
399 drawRect.top--;
400 drawRect.bottom++;
401 DrawEdge(hdc, &drawRect, EDGE_SUNKEN, BF_RECT);
403 drawRect.left = drawRect.right - 1;
404 drawRect.right = twips_to_pixels(printRect.right + margins.right - margins.left, GetDeviceCaps(hdc, LOGPIXELSX));
405 DrawEdge(hdc, &drawRect, EDGE_ETCHED, BF_RECT);
407 drawRect.left = 0;
408 drawRect.top = 0;
409 add_ruler_units(hdc, &drawRect, NewMetrics, EditLeftmost);
411 SelectObject(hdc, GetStockObject(BLACK_BRUSH));
412 DeleteObject(hBrush);
413 DeleteDC(hdcPrint);
414 EndPaint(hWnd, &ps);
417 LRESULT CALLBACK ruler_proc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
419 static WNDPROC pPrevRulerProc;
420 static LONG EditLeftmost;
421 static BOOL NewMetrics;
423 switch(msg)
425 case WM_USER:
426 if(wParam)
428 EditLeftmost = ((POINTL*)wParam)->x;
429 pPrevRulerProc = (WNDPROC)lParam;
431 NewMetrics = TRUE;
432 break;
434 case WM_PAINT:
435 paint_ruler(hWnd, EditLeftmost, NewMetrics);
436 break;
438 default:
439 return CallWindowProcW(pPrevRulerProc, hWnd, msg, wParam, lParam);
442 return 0;
445 static void print(LPPRINTDLGW pd, LPWSTR wszFileName)
447 FORMATRANGE fr;
448 DOCINFOW di;
449 HWND hEditorWnd = GetDlgItem(pd->hwndOwner, IDC_EDITOR);
450 int printedPages = 0;
452 fr.hdc = pd->hDC;
453 fr.hdcTarget = pd->hDC;
455 fr.rc = get_print_rect(fr.hdc);
456 fr.rcPage.left = 0;
457 fr.rcPage.right = fr.rc.right + margins.right;
458 fr.rcPage.top = 0;
459 fr.rcPage.bottom = fr.rc.bottom + margins.bottom;
461 ZeroMemory(&di, sizeof(di));
462 di.cbSize = sizeof(di);
463 di.lpszDocName = wszFileName;
465 if(pd->Flags & PD_PRINTTOFILE)
467 di.lpszOutput = dialog_print_to_file(pd->hwndOwner);
468 if(!di.lpszOutput)
469 return;
472 if(pd->Flags & PD_SELECTION)
474 SendMessageW(hEditorWnd, EM_EXGETSEL, 0, (LPARAM)&fr.chrg);
475 } else
477 GETTEXTLENGTHEX gt;
478 gt.flags = GTL_DEFAULT;
479 gt.codepage = 1200;
480 fr.chrg.cpMin = 0;
481 fr.chrg.cpMax = SendMessageW(hEditorWnd, EM_GETTEXTLENGTHEX, (WPARAM)&gt, 0);
483 if(pd->Flags & PD_PAGENUMS)
484 char_from_pagenum(hEditorWnd, &fr, pd->nToPage);
487 StartDocW(fr.hdc, &di);
490 int bottom = fr.rc.bottom;
491 if(StartPage(fr.hdc) <= 0)
492 break;
494 fr.chrg.cpMin = SendMessageW(hEditorWnd, EM_FORMATRANGE, TRUE, (LPARAM)&fr);
496 if(EndPage(fr.hdc) <= 0)
497 break;
498 bottom = fr.rc.bottom;
500 printedPages++;
501 if((pd->Flags & PD_PAGENUMS) && (printedPages > (pd->nToPage - pd->nFromPage)))
502 break;
504 while(fr.chrg.cpMin && fr.chrg.cpMin < fr.chrg.cpMax);
506 EndDoc(fr.hdc);
507 SendMessageW(hEditorWnd, EM_FORMATRANGE, FALSE, 0);
510 void dialog_printsetup(HWND hMainWnd)
512 PAGESETUPDLGW ps;
514 ZeroMemory(&ps, sizeof(ps));
515 ps.lStructSize = sizeof(ps);
516 ps.hwndOwner = hMainWnd;
517 ps.Flags = PSD_INHUNDREDTHSOFMILLIMETERS | PSD_MARGINS;
518 ps.rtMargin.left = twips_to_centmm(margins.left);
519 ps.rtMargin.right = twips_to_centmm(margins.right);
520 ps.rtMargin.top = twips_to_centmm(margins.top);
521 ps.rtMargin.bottom = twips_to_centmm(margins.bottom);
522 ps.hDevMode = devMode;
523 ps.hDevNames = devNames;
525 if(PageSetupDlgW(&ps))
527 margins.left = centmm_to_twips(ps.rtMargin.left);
528 margins.right = centmm_to_twips(ps.rtMargin.right);
529 margins.top = centmm_to_twips(ps.rtMargin.top);
530 margins.bottom = centmm_to_twips(ps.rtMargin.bottom);
531 devMode = ps.hDevMode;
532 devNames = ps.hDevNames;
533 update_ruler(get_ruler_wnd(hMainWnd));
537 void get_default_printer_opts(void)
539 PRINTDLGW pd;
540 ZeroMemory(&pd, sizeof(pd));
542 ZeroMemory(&pd, sizeof(pd));
543 pd.lStructSize = sizeof(pd);
544 pd.Flags = PD_RETURNDC | PD_RETURNDEFAULT;
545 pd.hDevMode = devMode;
547 PrintDlgW(&pd);
549 devMode = pd.hDevMode;
550 devNames = pd.hDevNames;
553 void print_quick(HWND hMainWnd, LPWSTR wszFileName)
555 PRINTDLGW pd;
557 ZeroMemory(&pd, sizeof(pd));
558 pd.hwndOwner = hMainWnd;
559 pd.hDC = make_dc();
561 print(&pd, wszFileName);
562 DeleteDC(pd.hDC);
565 void dialog_print(HWND hMainWnd, LPWSTR wszFileName)
567 PRINTDLGW pd;
568 HWND hEditorWnd = GetDlgItem(hMainWnd, IDC_EDITOR);
569 int from = 0;
570 int to = 0;
572 ZeroMemory(&pd, sizeof(pd));
573 pd.lStructSize = sizeof(pd);
574 pd.hwndOwner = hMainWnd;
575 pd.Flags = PD_RETURNDC | PD_USEDEVMODECOPIESANDCOLLATE;
576 pd.nMinPage = 1;
577 pd.nMaxPage = -1;
578 pd.hDevMode = devMode;
579 pd.hDevNames = devNames;
581 SendMessageW(hEditorWnd, EM_GETSEL, (WPARAM)&from, (LPARAM)&to);
582 if(from == to)
583 pd.Flags |= PD_NOSELECTION;
585 if(PrintDlgW(&pd))
587 devMode = pd.hDevMode;
588 devNames = pd.hDevNames;
589 print(&pd, wszFileName);
590 update_ruler(get_ruler_wnd(hMainWnd));
594 static void preview_bar_show(HWND hMainWnd, BOOL show)
596 HWND hReBar = GetDlgItem(hMainWnd, IDC_REBAR);
597 int i;
599 if(show)
601 REBARBANDINFOW rb;
602 HWND hStatic;
603 UINT num_pages_string = preview.pages_shown > 1 ? STRING_PREVIEW_ONEPAGE :
604 STRING_PREVIEW_TWOPAGES;
606 AddTextButton(hReBar, STRING_PREVIEW_PRINT, ID_PRINT, BANDID_PREVIEW_BTN1);
607 AddTextButton(hReBar, STRING_PREVIEW_NEXTPAGE, ID_PREVIEW_NEXTPAGE, BANDID_PREVIEW_BTN2);
608 AddTextButton(hReBar, STRING_PREVIEW_PREVPAGE, ID_PREVIEW_PREVPAGE, BANDID_PREVIEW_BTN3);
609 AddTextButton(hReBar, num_pages_string, ID_PREVIEW_NUMPAGES, BANDID_PREVIEW_BTN4);
610 AddTextButton(hReBar, STRING_PREVIEW_ZOOMIN, ID_PREVIEW_ZOOMIN, BANDID_PREVIEW_BTN5);
611 AddTextButton(hReBar, STRING_PREVIEW_ZOOMOUT, ID_PREVIEW_ZOOMOUT, BANDID_PREVIEW_BTN6);
612 AddTextButton(hReBar, STRING_PREVIEW_CLOSE, ID_FILE_EXIT, BANDID_PREVIEW_BTN7);
614 hStatic = CreateWindowW(WC_STATICW, NULL,
615 WS_VISIBLE | WS_CHILD, 0, 0, 0, 0,
616 hReBar, NULL, NULL, NULL);
618 rb.cbSize = REBARBANDINFOW_V6_SIZE;
619 rb.fMask = RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_STYLE | RBBIM_CHILD | RBBIM_IDEALSIZE | RBBIM_ID;
620 rb.fStyle = RBBS_NOGRIPPER | RBBS_VARIABLEHEIGHT;
621 rb.hwndChild = hStatic;
622 rb.cyChild = rb.cyMinChild = 22;
623 rb.cx = rb.cxMinChild = 90;
624 rb.cxIdeal = 100;
625 rb.wID = BANDID_PREVIEW_BUFFER;
627 SendMessageW(hReBar, RB_INSERTBAND, -1, (LPARAM)&rb);
628 } else
630 for(i = 0; i <= PREVIEW_BUTTONS; i++)
631 SendMessageW(hReBar, RB_DELETEBAND, SendMessageW(hReBar, RB_IDTOINDEX, BANDID_PREVIEW_BTN1+i, 0), 0);
635 static const int min_spacing = 10;
637 static void update_preview_scrollbars(HWND hwndPreview, RECT *window)
639 SCROLLINFO sbi;
640 sbi.cbSize = sizeof(sbi);
641 sbi.fMask = SIF_PAGE|SIF_RANGE;
642 sbi.nMin = 0;
643 if (preview.zoomlevel == 0)
645 /* Hide scrollbars when zoomed out. */
646 sbi.nMax = 0;
647 sbi.nPage = window->right;
648 SetScrollInfo(hwndPreview, SB_HORZ, &sbi, TRUE);
649 sbi.nPage = window->bottom;
650 SetScrollInfo(hwndPreview, SB_VERT, &sbi, TRUE);
651 } else {
652 sbi.nMax = preview.bmScaledSize.cx * preview.pages_shown +
653 min_spacing * (preview.pages_shown + 1);
654 sbi.nPage = window->right;
655 SetScrollInfo(hwndPreview, SB_HORZ, &sbi, TRUE);
656 /* Change in the horizontal scrollbar visibility affects the
657 * client rect, so update the client rect. */
658 GetClientRect(hwndPreview, window);
659 sbi.nMax = preview.bmScaledSize.cy + min_spacing * 2;
660 sbi.nPage = window->bottom;
661 SetScrollInfo(hwndPreview, SB_VERT, &sbi, TRUE);
665 static void update_preview_sizes(HWND hwndPreview, BOOL zoomLevelUpdated)
667 RECT window;
669 GetClientRect(hwndPreview, &window);
671 /* The zoom ratio isn't updated for partial zoom because of resizing the window. */
672 if (zoomLevelUpdated || preview.zoomlevel != 1)
674 float ratio, ratioHeight, ratioWidth;
675 if (preview.zoomlevel == 2)
677 ratio = 1.0;
678 } else {
679 ratioHeight = (window.bottom - min_spacing * 2) / (float)preview.bmSize.cy;
681 ratioWidth = (float)(window.right -
682 min_spacing * (preview.pages_shown + 1)) /
683 (preview.pages_shown * preview.bmSize.cx);
685 if(ratioWidth > ratioHeight)
686 ratio = ratioHeight;
687 else
688 ratio = ratioWidth;
690 if (preview.zoomlevel == 1)
691 ratio += (1.0 - ratio) / 2;
693 preview.zoomratio = ratio;
696 preview.bmScaledSize.cx = preview.bmSize.cx * preview.zoomratio;
697 preview.bmScaledSize.cy = preview.bmSize.cy * preview.zoomratio;
699 preview.spacing.cy = max(min_spacing, (window.bottom - preview.bmScaledSize.cy) / 2);
701 preview.spacing.cx = (window.right -
702 preview.bmScaledSize.cx * preview.pages_shown) /
703 (preview.pages_shown + 1);
704 if (preview.spacing.cx < min_spacing)
705 preview.spacing.cx = min_spacing;
707 update_preview_scrollbars(hwndPreview, &window);
710 static void draw_preview_page(HDC hdc, HDC* hdcSized, FORMATRANGE* lpFr, float ratio, int bmNewWidth, int bmNewHeight, int bmWidth, int bmHeight, BOOL draw_margins)
712 HBITMAP hBitmapScaled = CreateCompatibleBitmap(hdc, bmNewWidth, bmNewHeight);
713 HBITMAP oldbm;
714 HPEN hPen, oldPen;
715 int TopMargin = (int)((float)twips_to_pixels(lpFr->rc.top, GetDeviceCaps(hdc, LOGPIXELSX)) * ratio);
716 int BottomMargin = (int)((float)twips_to_pixels(lpFr->rc.bottom, GetDeviceCaps(hdc, LOGPIXELSX)) * ratio);
717 int LeftMargin = (int)((float)twips_to_pixels(lpFr->rc.left, GetDeviceCaps(hdc, LOGPIXELSY)) * ratio);
718 int RightMargin = (int)((float)twips_to_pixels(lpFr->rc.right, GetDeviceCaps(hdc, LOGPIXELSY)) * ratio);
720 if(*hdcSized) {
721 oldbm = SelectObject(*hdcSized, hBitmapScaled);
722 DeleteObject(oldbm);
723 } else {
724 *hdcSized = CreateCompatibleDC(hdc);
725 SelectObject(*hdcSized, hBitmapScaled);
728 StretchBlt(*hdcSized, 0, 0, bmNewWidth, bmNewHeight, hdc, 0, 0, bmWidth, bmHeight, SRCCOPY);
730 if (!draw_margins) return;
732 /* Draw margin lines */
733 hPen = CreatePen(PS_DOT, 1, RGB(0,0,0));
734 oldPen = SelectObject(*hdcSized, hPen);
736 MoveToEx(*hdcSized, 0, TopMargin, NULL);
737 LineTo(*hdcSized, bmNewWidth, TopMargin);
738 MoveToEx(*hdcSized, 0, BottomMargin, NULL);
739 LineTo(*hdcSized, bmNewWidth, BottomMargin);
741 MoveToEx(*hdcSized, LeftMargin, 0, NULL);
742 LineTo(*hdcSized, LeftMargin, bmNewHeight);
743 MoveToEx(*hdcSized, RightMargin, 0, NULL);
744 LineTo(*hdcSized, RightMargin, bmNewHeight);
746 SelectObject(*hdcSized, oldPen);
747 DeleteObject(hPen);
750 static BOOL is_last_preview_page(int page)
752 return preview.pageEnds[page - 1] >= preview.textlength;
755 /* Update for zoom ratio changes with same page. */
756 static void update_scaled_preview(HWND hMainWnd)
758 FORMATRANGE fr;
759 HWND hwndPreview;
761 /* This may occur on WM_CREATE before update_preview is called
762 * because a WM_SIZE message is generated from updating the
763 * scrollbars. */
764 if (!preview.hdc) return;
766 hwndPreview = GetDlgItem(hMainWnd, IDC_PREVIEW);
767 fr.hdcTarget = make_dc();
768 fr.rc = fr.rcPage = preview.rcPage;
769 fr.rc.left += margins.left;
770 fr.rc.top += margins.top;
771 fr.rc.bottom -= margins.bottom;
772 fr.rc.right -= margins.right;
774 draw_preview_page(preview.hdc, &preview.hdcSized, &fr, preview.zoomratio,
775 preview.bmScaledSize.cx, preview.bmScaledSize.cy,
776 preview.bmSize.cx, preview.bmSize.cy, TRUE);
778 if(preview.pages_shown > 1)
780 draw_preview_page(preview.hdc2, &preview.hdcSized2, &fr, preview.zoomratio,
781 preview.bmScaledSize.cx, preview.bmScaledSize.cy,
782 preview.bmSize.cx, preview.bmSize.cy,
783 !is_last_preview_page(preview.page));
786 InvalidateRect(hwndPreview, NULL, TRUE);
787 DeleteDC(fr.hdcTarget);
790 void init_preview(HWND hMainWnd, LPWSTR wszFileName)
792 HINSTANCE hInstance = GetModuleHandleW(0);
793 preview.page = 1;
794 preview.hdc = 0;
795 preview.hdc2 = 0;
796 preview.wszFileName = wszFileName;
797 preview.zoomratio = 0;
798 preview.zoomlevel = 0;
799 preview_bar_show(hMainWnd, TRUE);
801 CreateWindowExW(0, wszPreviewWndClass, NULL,
802 WS_VISIBLE | WS_CHILD | WS_VSCROLL | WS_HSCROLL,
803 0, 0, 200, 10, hMainWnd, (HMENU)IDC_PREVIEW, hInstance, NULL);
806 void close_preview(HWND hMainWnd)
808 HWND hwndPreview = GetDlgItem(hMainWnd, IDC_PREVIEW);
809 preview.window.right = 0;
810 preview.window.bottom = 0;
811 preview.page = 0;
812 HeapFree(GetProcessHeap(), 0, preview.pageEnds);
813 preview.pageEnds = NULL;
814 preview.pageCapacity = 0;
815 if (preview.zoomlevel > 0)
816 preview.pages_shown = preview.saved_pages_shown;
817 if(preview.hdc) {
818 HBITMAP oldbm = GetCurrentObject(preview.hdc, OBJ_BITMAP);
819 DeleteDC(preview.hdc);
820 DeleteObject(oldbm);
821 preview.hdc = NULL;
823 if(preview.hdc2) {
824 HBITMAP oldbm = GetCurrentObject(preview.hdc2, OBJ_BITMAP);
825 DeleteDC(preview.hdc2);
826 DeleteObject(oldbm);
827 preview.hdc2 = NULL;
829 if(preview.hdcSized) {
830 HBITMAP oldbm = GetCurrentObject(preview.hdcSized, OBJ_BITMAP);
831 DeleteDC(preview.hdcSized);
832 DeleteObject(oldbm);
833 preview.hdcSized = NULL;
835 if(preview.hdcSized2) {
836 HBITMAP oldbm = GetCurrentObject(preview.hdcSized2, OBJ_BITMAP);
837 DeleteDC(preview.hdcSized2);
838 DeleteObject(oldbm);
839 preview.hdcSized2 = NULL;
842 preview_bar_show(hMainWnd, FALSE);
843 DestroyWindow(hwndPreview);
846 BOOL preview_isactive(void)
848 return preview.page != 0;
851 static void draw_preview(HWND hEditorWnd, FORMATRANGE* lpFr, RECT* paper, int page)
853 int bottom;
855 if (!preview.pageEnds)
857 preview.pageCapacity = 32;
858 preview.pageEnds = HeapAlloc(GetProcessHeap(), 0,
859 sizeof(int) * preview.pageCapacity);
860 if (!preview.pageEnds) return;
861 } else if (page >= preview.pageCapacity) {
862 int *new_buffer;
863 new_buffer = HeapReAlloc(GetProcessHeap(), 0, preview.pageEnds,
864 sizeof(int) * preview.pageCapacity * 2);
865 if (!new_buffer) return;
866 preview.pageCapacity *= 2;
867 preview.pageEnds = new_buffer;
870 FillRect(lpFr->hdc, paper, GetStockObject(WHITE_BRUSH));
871 if (page > 1 && is_last_preview_page(page - 1)) return;
872 lpFr->chrg.cpMin = page <= 1 ? 0 : preview.pageEnds[page-2];
873 bottom = lpFr->rc.bottom;
874 preview.pageEnds[page-1] = SendMessageW(hEditorWnd, EM_FORMATRANGE, TRUE, (LPARAM)lpFr);
876 /* EM_FORMATRANGE sets fr.rc.bottom to indicate the area printed in,
877 * but we want to keep the original for drawing margins */
878 lpFr->rc.bottom = bottom;
879 SendMessageW(hEditorWnd, EM_FORMATRANGE, FALSE, 0);
882 static void update_preview_buttons(HWND hMainWnd)
884 HWND hReBar = GetDlgItem(hMainWnd, IDC_REBAR);
885 EnableWindow(GetDlgItem(hReBar, ID_PREVIEW_PREVPAGE), preview.page > 1);
886 EnableWindow(GetDlgItem(hReBar, ID_PREVIEW_NEXTPAGE),
887 !is_last_preview_page(preview.page) &&
888 !is_last_preview_page(preview.page + preview.pages_shown - 1));
889 EnableWindow(GetDlgItem(hReBar, ID_PREVIEW_NUMPAGES),
890 preview.pages_shown > 1 ||
891 (!is_last_preview_page(1) && preview.zoomlevel == 0));
892 EnableWindow(GetDlgItem(hReBar, ID_PREVIEW_ZOOMIN), preview.zoomlevel < 2);
893 EnableWindow(GetDlgItem(hReBar, ID_PREVIEW_ZOOMOUT), preview.zoomlevel > 0);
896 LRESULT print_preview(HWND hwndPreview)
898 HDC hdc;
899 RECT window, background;
900 PAINTSTRUCT ps;
901 POINT scrollpos;
903 hdc = BeginPaint(hwndPreview, &ps);
904 GetClientRect(hwndPreview, &window);
906 FillRect(hdc, &window, GetStockObject(GRAY_BRUSH));
908 scrollpos.x = GetScrollPos(hwndPreview, SB_HORZ);
909 scrollpos.y = GetScrollPos(hwndPreview, SB_VERT);
911 background.left = preview.spacing.cx - 2 - scrollpos.x;
912 background.right = background.left + preview.bmScaledSize.cx + 4;
913 background.top = preview.spacing.cy - 2 - scrollpos.y;
914 background.bottom = background.top + preview.bmScaledSize.cy + 4;
916 FillRect(hdc, &background, GetStockObject(BLACK_BRUSH));
918 if(preview.pages_shown > 1)
920 background.left += preview.bmScaledSize.cx + preview.spacing.cx;
921 background.right += preview.bmScaledSize.cx + preview.spacing.cx;
923 FillRect(hdc, &background, GetStockObject(BLACK_BRUSH));
926 BitBlt(hdc, preview.spacing.cx - scrollpos.x, preview.spacing.cy - scrollpos.y,
927 preview.bmScaledSize.cx, preview.bmScaledSize.cy,
928 preview.hdcSized, 0, 0, SRCCOPY);
930 if(preview.pages_shown > 1)
932 BitBlt(hdc, preview.spacing.cx * 2 + preview.bmScaledSize.cx - scrollpos.x,
933 preview.spacing.cy - scrollpos.y, preview.bmScaledSize.cx,
934 preview.bmScaledSize.cy, preview.hdcSized2, 0, 0, SRCCOPY);
937 preview.window = window;
939 EndPaint(hwndPreview, &ps);
941 return 0;
944 static void update_preview_statusbar(HWND hMainWnd)
946 HWND hStatusbar = GetDlgItem(hMainWnd, IDC_STATUSBAR);
947 HINSTANCE hInst = GetModuleHandleW(0);
948 WCHAR *p;
949 WCHAR wstr[MAX_STRING_LEN];
951 p = wstr;
952 if (preview.pages_shown < 2 || is_last_preview_page(preview.page))
954 static const WCHAR fmt[] = {' ','%','d','\0'};
955 p += LoadStringW(hInst, STRING_PREVIEW_PAGE, wstr, MAX_STRING_LEN);
956 wsprintfW(p, fmt, preview.page);
957 } else {
958 static const WCHAR fmt[] = {' ','%','d','-','%','d','\0'};
959 p += LoadStringW(hInst, STRING_PREVIEW_PAGES, wstr, MAX_STRING_LEN);
960 wsprintfW(p, fmt, preview.page, preview.page + 1);
962 SetWindowTextW(hStatusbar, wstr);
965 /* Update for page changes. */
966 static void update_preview(HWND hMainWnd)
968 RECT paper;
969 HWND hEditorWnd = GetDlgItem(hMainWnd, IDC_EDITOR);
970 HWND hwndPreview = GetDlgItem(hMainWnd, IDC_PREVIEW);
971 HBITMAP hBitmapCapture;
972 FORMATRANGE fr;
973 HDC hdc = GetDC(hwndPreview);
975 fr.hdcTarget = make_dc();
976 fr.rc = fr.rcPage = preview.rcPage;
977 fr.rc.left += margins.left;
978 fr.rc.top += margins.top;
979 fr.rc.bottom -= margins.bottom;
980 fr.rc.right -= margins.right;
982 fr.chrg.cpMin = 0;
983 fr.chrg.cpMax = preview.textlength;
985 paper.left = 0;
986 paper.right = preview.bmSize.cx;
987 paper.top = 0;
988 paper.bottom = preview.bmSize.cy;
990 if (!preview.hdc) {
991 preview.hdc = CreateCompatibleDC(hdc);
992 hBitmapCapture = CreateCompatibleBitmap(hdc, preview.bmSize.cx, preview.bmSize.cy);
993 SelectObject(preview.hdc, hBitmapCapture);
996 fr.hdc = preview.hdc;
997 draw_preview(hEditorWnd, &fr, &paper, preview.page);
999 if(preview.pages_shown > 1)
1001 if (!preview.hdc2)
1003 preview.hdc2 = CreateCompatibleDC(hdc);
1004 hBitmapCapture = CreateCompatibleBitmap(hdc,
1005 preview.bmSize.cx,
1006 preview.bmSize.cy);
1007 SelectObject(preview.hdc2, hBitmapCapture);
1010 fr.hdc = preview.hdc2;
1011 draw_preview(hEditorWnd, &fr, &fr.rcPage, preview.page + 1);
1013 DeleteDC(fr.hdcTarget);
1014 ReleaseDC(hwndPreview, hdc);
1016 update_scaled_preview(hMainWnd);
1017 update_preview_buttons(hMainWnd);
1018 update_preview_statusbar(hMainWnd);
1021 static void toggle_num_pages(HWND hMainWnd)
1023 HWND hReBar = GetDlgItem(hMainWnd, IDC_REBAR);
1024 WCHAR name[MAX_STRING_LEN];
1025 HINSTANCE hInst = GetModuleHandleW(0);
1026 int nPreviewPages;
1028 preview.pages_shown = preview.pages_shown > 1 ? 1 : 2;
1030 nPreviewPages = preview.zoomlevel > 0 ? preview.saved_pages_shown :
1031 preview.pages_shown;
1033 LoadStringW(hInst, nPreviewPages > 1 ? STRING_PREVIEW_ONEPAGE :
1034 STRING_PREVIEW_TWOPAGES,
1035 name, MAX_STRING_LEN);
1037 SetWindowTextW(GetDlgItem(hReBar, ID_PREVIEW_NUMPAGES), name);
1038 update_preview_sizes(GetDlgItem(hMainWnd, IDC_PREVIEW), TRUE);
1039 update_preview(hMainWnd);
1042 /* Returns the page shown that the point is in (1 or 2) or 0 if the point
1043 * isn't inside either page */
1044 int preview_page_hittest(POINT pt)
1046 RECT rc;
1047 rc.left = preview.spacing.cx;
1048 rc.right = rc.left + preview.bmScaledSize.cx;
1049 rc.top = preview.spacing.cy;
1050 rc.bottom = rc.top + preview.bmScaledSize.cy;
1051 if (PtInRect(&rc, pt))
1052 return 1;
1054 if (preview.pages_shown <= 1)
1055 return 0;
1057 rc.left += preview.bmScaledSize.cx + preview.spacing.cx;
1058 rc.right += preview.bmScaledSize.cx + preview.spacing.cx;
1059 if (PtInRect(&rc, pt))
1060 return is_last_preview_page(preview.page) ? 1 : 2;
1062 return 0;
1065 LRESULT CALLBACK preview_proc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
1067 switch(msg)
1069 case WM_CREATE:
1071 HWND hMainWnd = GetParent(hWnd);
1072 HWND hEditorWnd = GetDlgItem(hMainWnd, IDC_EDITOR);
1073 FORMATRANGE fr;
1074 GETTEXTLENGTHEX gt = {GTL_DEFAULT, 1200};
1075 HDC hdc = GetDC(hWnd);
1076 HDC hdcTarget = make_dc();
1078 fr.rc = preview.rcPage = get_print_rect(hdcTarget);
1079 preview.rcPage.bottom += margins.bottom;
1080 preview.rcPage.right += margins.right;
1081 preview.rcPage.top = preview.rcPage.left = 0;
1082 fr.rcPage = preview.rcPage;
1084 preview.bmSize.cx = twips_to_pixels(preview.rcPage.right, GetDeviceCaps(hdc, LOGPIXELSX));
1085 preview.bmSize.cy = twips_to_pixels(preview.rcPage.bottom, GetDeviceCaps(hdc, LOGPIXELSY));
1087 preview.textlength = SendMessageW(hEditorWnd, EM_GETTEXTLENGTHEX, (WPARAM)&gt, 0);
1089 fr.hdc = CreateCompatibleDC(hdc);
1090 fr.hdcTarget = hdcTarget;
1091 fr.chrg.cpMin = 0;
1092 fr.chrg.cpMax = preview.textlength;
1093 DeleteDC(fr.hdc);
1094 DeleteDC(hdcTarget);
1095 ReleaseDC(hWnd, hdc);
1097 update_preview_sizes(hWnd, TRUE);
1098 update_preview(hMainWnd);
1099 break;
1102 case WM_PAINT:
1103 return print_preview(hWnd);
1105 case WM_SIZE:
1107 update_preview_sizes(hWnd, FALSE);
1108 update_scaled_preview(hWnd);
1109 break;
1112 case WM_VSCROLL:
1113 case WM_HSCROLL:
1115 SCROLLINFO si;
1116 RECT rc;
1117 int nBar = (msg == WM_VSCROLL) ? SB_VERT : SB_HORZ;
1118 int origPos;
1120 GetClientRect(hWnd, &rc);
1121 si.cbSize = sizeof(si);
1122 si.fMask = SIF_ALL;
1123 GetScrollInfo(hWnd, nBar, &si);
1124 origPos = si.nPos;
1125 switch(LOWORD(wParam))
1127 case SB_TOP: /* == SB_LEFT */
1128 si.nPos = si.nMin;
1129 break;
1130 case SB_BOTTOM: /* == SB_RIGHT */
1131 si.nPos = si.nMax;
1132 break;
1133 case SB_LINEUP: /* == SB_LINELEFT */
1134 si.nPos -= si.nPage / 10;
1135 break;
1136 case SB_LINEDOWN: /* == SB_LINERIGHT */
1137 si.nPos += si.nPage / 10;
1138 break;
1139 case SB_PAGEUP: /* == SB_PAGELEFT */
1140 si.nPos -= si.nPage;
1141 break;
1142 case SB_PAGEDOWN: /* SB_PAGERIGHT */
1143 si.nPos += si.nPage;
1144 break;
1145 case SB_THUMBTRACK:
1146 si.nPos = si.nTrackPos;
1147 break;
1149 si.fMask = SIF_POS;
1150 SetScrollInfo(hWnd, nBar, &si, TRUE);
1151 GetScrollInfo(hWnd, nBar, &si);
1152 if (si.nPos != origPos)
1154 int amount = origPos - si.nPos;
1155 if (msg == WM_VSCROLL)
1156 ScrollWindow(hWnd, 0, amount, NULL, NULL);
1157 else
1158 ScrollWindow(hWnd, amount, 0, NULL, NULL);
1160 return 0;
1163 case WM_SETCURSOR:
1165 POINT pt;
1166 RECT rc;
1167 int bHittest = FALSE;
1168 DWORD messagePos = GetMessagePos();
1169 pt.x = (short)LOWORD(messagePos);
1170 pt.y = (short)HIWORD(messagePos);
1171 ScreenToClient(hWnd, &pt);
1173 GetClientRect(hWnd, &rc);
1174 if (PtInRect(&rc, pt))
1176 pt.x += GetScrollPos(hWnd, SB_HORZ);
1177 pt.y += GetScrollPos(hWnd, SB_VERT);
1178 bHittest = preview_page_hittest(pt);
1181 if (bHittest)
1182 SetCursor(LoadCursorW(GetModuleHandleW(0),
1183 MAKEINTRESOURCEW(IDC_ZOOM)));
1184 else
1185 SetCursor(LoadCursorW(NULL, (WCHAR*)IDC_ARROW));
1187 return TRUE;
1190 case WM_LBUTTONDOWN:
1192 int page;
1193 POINT pt;
1194 pt.x = (short)LOWORD(lParam) + GetScrollPos(hWnd, SB_HORZ);
1195 pt.y = (short)HIWORD(lParam) + GetScrollPos(hWnd, SB_VERT);
1196 if ((page = preview_page_hittest(pt)) > 0)
1198 HWND hMainWnd = GetParent(hWnd);
1200 /* Convert point from client coordinate to unzoomed page
1201 * coordinate. */
1202 pt.x -= preview.spacing.cx;
1203 if (page > 1)
1204 pt.x -= preview.bmScaledSize.cx + preview.spacing.cx;
1205 pt.y -= preview.spacing.cy;
1206 pt.x /= preview.zoomratio;
1207 pt.y /= preview.zoomratio;
1209 if (preview.zoomlevel == 0)
1210 preview.saved_pages_shown = preview.pages_shown;
1211 preview.zoomlevel = (preview.zoomlevel + 1) % 3;
1212 preview.zoomratio = 0;
1213 if (preview.zoomlevel == 0 && preview.saved_pages_shown > 1)
1215 toggle_num_pages(hMainWnd);
1216 } else if (preview.pages_shown > 1) {
1217 if (page >= 2) preview.page++;
1218 toggle_num_pages(hMainWnd);
1219 } else {
1220 update_preview_sizes(hWnd, TRUE);
1221 update_scaled_preview(hMainWnd);
1222 update_preview_buttons(hMainWnd);
1225 if (preview.zoomlevel > 0) {
1226 SCROLLINFO si;
1227 /* Convert the coordinate back to client coordinate. */
1228 pt.x *= preview.zoomratio;
1229 pt.y *= preview.zoomratio;
1230 pt.x += preview.spacing.cx;
1231 pt.y += preview.spacing.cy;
1232 /* Scroll to center view at that point on the page */
1233 si.cbSize = sizeof(si);
1234 si.fMask = SIF_PAGE;
1235 GetScrollInfo(hWnd, SB_HORZ, &si);
1236 pt.x -= si.nPage / 2;
1237 SetScrollPos(hWnd, SB_HORZ, pt.x, TRUE);
1238 GetScrollInfo(hWnd, SB_VERT, &si);
1239 pt.y -= si.nPage / 2;
1240 SetScrollPos(hWnd, SB_VERT, pt.y, TRUE);
1245 default:
1246 return DefWindowProcW(hWnd, msg, wParam, lParam);
1249 return 0;
1252 LRESULT preview_command(HWND hWnd, WPARAM wParam)
1254 switch(LOWORD(wParam))
1256 case ID_FILE_EXIT:
1257 PostMessageW(hWnd, WM_CLOSE, 0, 0);
1258 break;
1260 case ID_PREVIEW_NEXTPAGE:
1261 case ID_PREVIEW_PREVPAGE:
1263 if(LOWORD(wParam) == ID_PREVIEW_NEXTPAGE)
1264 preview.page++;
1265 else
1266 preview.page--;
1268 update_preview(hWnd);
1270 break;
1272 case ID_PREVIEW_NUMPAGES:
1273 toggle_num_pages(hWnd);
1274 break;
1276 case ID_PREVIEW_ZOOMIN:
1277 if (preview.zoomlevel < 2)
1279 if (preview.zoomlevel == 0)
1280 preview.saved_pages_shown = preview.pages_shown;
1281 preview.zoomlevel++;
1282 preview.zoomratio = 0;
1283 if (preview.pages_shown > 1)
1285 /* Forced switch to one page when zooming in. */
1286 toggle_num_pages(hWnd);
1287 } else {
1288 HWND hwndPreview = GetDlgItem(hWnd, IDC_PREVIEW);
1289 update_preview_sizes(hwndPreview, TRUE);
1290 update_scaled_preview(hWnd);
1291 update_preview_buttons(hWnd);
1294 break;
1296 case ID_PREVIEW_ZOOMOUT:
1297 if (preview.zoomlevel > 0)
1299 HWND hwndPreview = GetDlgItem(hWnd, IDC_PREVIEW);
1300 preview.zoomlevel--;
1301 preview.zoomratio = 0;
1302 if (preview.zoomlevel == 0 && preview.saved_pages_shown > 1) {
1303 toggle_num_pages(hWnd);
1304 } else {
1305 update_preview_sizes(hwndPreview, TRUE);
1306 update_scaled_preview(hWnd);
1307 update_preview_buttons(hWnd);
1310 break;
1312 case ID_PRINT:
1313 dialog_print(hWnd, preview.wszFileName);
1314 SendMessageW(hWnd, WM_CLOSE, 0, 0);
1315 break;
1318 return 0;