ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

print.c
Go to the documentation of this file.
00001 /*
00002  * Wordpad implementation - Printing and print preview functions
00003  *
00004  * Copyright 2007-2008 by Alexander N. Sørnes <alex@thehandofagony.com>
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00019  */
00020 
00021 #include <windows.h>
00022 #include <richedit.h>
00023 #include <commctrl.h>
00024 
00025 #include "wordpad.h"
00026 
00027 typedef struct _previewinfo
00028 {
00029     int page;
00030     int pages_shown;
00031     int saved_pages_shown;
00032     int *pageEnds, pageCapacity;
00033     int textlength;
00034     HDC hdc;
00035     HDC hdc2;
00036     RECT window;
00037     RECT rcPage;
00038     SIZE bmSize;
00039     SIZE bmScaledSize;
00040     SIZE spacing;
00041     float zoomratio;
00042     int zoomlevel;
00043     LPWSTR wszFileName;
00044 } previewinfo, *ppreviewinfo;
00045 
00046 static HGLOBAL devMode;
00047 static HGLOBAL devNames;
00048 
00049 static RECT margins;
00050 static previewinfo preview;
00051 
00052 extern const WCHAR wszPreviewWndClass[];
00053 
00054 static const WCHAR var_pagemargin[] = {'P','a','g','e','M','a','r','g','i','n',0};
00055 static const WCHAR var_previewpages[] = {'P','r','e','v','i','e','w','P','a','g','e','s',0};
00056 
00057 static LPWSTR get_print_file_filter(HWND hMainWnd)
00058 {
00059     static WCHAR wszPrintFilter[MAX_STRING_LEN*2+6+4+1];
00060     const WCHAR files_prn[] = {'*','.','P','R','N',0};
00061     const WCHAR files_all[] = {'*','.','*','\0'};
00062     LPWSTR p;
00063     HINSTANCE hInstance = GetModuleHandleW(0);
00064 
00065     p = wszPrintFilter;
00066     LoadStringW(hInstance, STRING_PRINTER_FILES_PRN, p, MAX_STRING_LEN);
00067     p += lstrlenW(p) + 1;
00068     lstrcpyW(p, files_prn);
00069     p += lstrlenW(p) + 1;
00070     LoadStringW(hInstance, STRING_ALL_FILES, p, MAX_STRING_LEN);
00071     p += lstrlenW(p) + 1;
00072     lstrcpyW(p, files_all);
00073     p += lstrlenW(p) + 1;
00074     *p = 0;
00075 
00076     return wszPrintFilter;
00077 }
00078 
00079 void registry_set_pagemargins(HKEY hKey)
00080 {
00081     RegSetValueExW(hKey, var_pagemargin, 0, REG_BINARY, (LPBYTE)&margins, sizeof(RECT));
00082 }
00083 
00084 void registry_read_pagemargins(HKEY hKey)
00085 {
00086     DWORD size = sizeof(RECT);
00087 
00088     if(!hKey || RegQueryValueExW(hKey, var_pagemargin, 0, NULL, (LPBYTE)&margins,
00089                      &size) != ERROR_SUCCESS || size != sizeof(RECT))
00090     {
00091         margins.top = 1417;
00092         margins.bottom = 1417;
00093         margins.left = 1757;
00094         margins.right = 1757;
00095     }
00096 }
00097 
00098 void registry_set_previewpages(HKEY hKey)
00099 {
00100     RegSetValueExW(hKey, var_previewpages, 0, REG_DWORD,
00101                    (LPBYTE)&preview.pages_shown, sizeof(DWORD));
00102 }
00103 
00104 void registry_read_previewpages(HKEY hKey)
00105 {
00106     DWORD size = sizeof(DWORD);
00107     if(!hKey ||
00108        RegQueryValueExW(hKey, var_previewpages, 0, NULL,
00109                         (LPBYTE)&preview.pages_shown, &size) != ERROR_SUCCESS ||
00110        size != sizeof(DWORD))
00111     {
00112         preview.pages_shown = 1;
00113     } else {
00114         if (preview.pages_shown < 1) preview.pages_shown = 1;
00115         else if (preview.pages_shown > 2) preview.pages_shown = 2;
00116     }
00117 }
00118 
00119 
00120 static void AddTextButton(HWND hRebarWnd, UINT string, UINT command, UINT id)
00121 {
00122     REBARBANDINFOW rb;
00123     HINSTANCE hInstance = GetModuleHandleW(0);
00124     WCHAR text[MAX_STRING_LEN];
00125     HWND hButton;
00126 
00127     LoadStringW(hInstance, string, text, MAX_STRING_LEN);
00128     hButton = CreateWindowW(WC_BUTTONW, text,
00129                             WS_VISIBLE | WS_CHILD, 5, 5, 100, 15,
00130                             hRebarWnd, ULongToHandle(command), hInstance, NULL);
00131 
00132     rb.cbSize = REBARBANDINFOW_V6_SIZE;
00133     rb.fMask = RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_STYLE | RBBIM_CHILD | RBBIM_IDEALSIZE | RBBIM_ID;
00134     rb.fStyle = RBBS_NOGRIPPER | RBBS_VARIABLEHEIGHT;
00135     rb.hwndChild = hButton;
00136     rb.cyChild = rb.cyMinChild = 22;
00137     rb.cx = rb.cxMinChild = 90;
00138     rb.cxIdeal = 100;
00139     rb.wID = id;
00140 
00141     SendMessageW(hRebarWnd, RB_INSERTBAND, -1, (LPARAM)&rb);
00142 }
00143 
00144 static HDC make_dc(void)
00145 {
00146     if(devNames && devMode)
00147     {
00148         LPDEVNAMES dn = GlobalLock(devNames);
00149         LPDEVMODEW dm = GlobalLock(devMode);
00150         HDC ret;
00151 
00152         ret = CreateDCW((LPWSTR)dn + dn->wDriverOffset,
00153                          (LPWSTR)dn + dn->wDeviceOffset, 0, dm);
00154 
00155         GlobalUnlock(dn);
00156         GlobalUnlock(dm);
00157 
00158         return ret;
00159     } else
00160     {
00161         return 0;
00162     }
00163 }
00164 
00165 static LONG twips_to_centmm(int twips)
00166 {
00167     return MulDiv(twips, CENTMM_PER_INCH, TWIPS_PER_INCH);
00168 }
00169 
00170 static LONG centmm_to_twips(int mm)
00171 {
00172     return MulDiv(mm, TWIPS_PER_INCH, CENTMM_PER_INCH);
00173 }
00174 
00175 static LONG twips_to_pixels(int twips, int dpi)
00176 {
00177     return MulDiv(twips, dpi, TWIPS_PER_INCH);
00178 }
00179 
00180 static LONG devunits_to_twips(int units, int dpi)
00181 {
00182     return MulDiv(units, TWIPS_PER_INCH, dpi);
00183 }
00184 
00185 
00186 static RECT get_print_rect(HDC hdc)
00187 {
00188     RECT rc;
00189     int width, height;
00190 
00191     if(hdc)
00192     {
00193         int dpiY = GetDeviceCaps(hdc, LOGPIXELSY);
00194         int dpiX = GetDeviceCaps(hdc, LOGPIXELSX);
00195         width = devunits_to_twips(GetDeviceCaps(hdc, PHYSICALWIDTH), dpiX);
00196         height = devunits_to_twips(GetDeviceCaps(hdc, PHYSICALHEIGHT), dpiY);
00197     } else
00198     {
00199         width = centmm_to_twips(18500);
00200         height = centmm_to_twips(27000);
00201     }
00202 
00203     rc.left = margins.left;
00204     rc.right = width - margins.right;
00205     rc.top = margins.top;
00206     rc.bottom = height - margins.bottom;
00207 
00208     return rc;
00209 }
00210 
00211 void target_device(HWND hMainWnd, DWORD wordWrap)
00212 {
00213     HWND hEditorWnd = GetDlgItem(hMainWnd, IDC_EDITOR);
00214 
00215     if(wordWrap == ID_WORDWRAP_MARGIN)
00216     {
00217         int width = 0;
00218         LRESULT result;
00219         HDC hdc = make_dc();
00220         RECT rc = get_print_rect(hdc);
00221 
00222         width = rc.right - rc.left;
00223         if(!hdc)
00224         {
00225             HDC hMaindc = GetDC(hMainWnd);
00226             hdc = CreateCompatibleDC(hMaindc);
00227             ReleaseDC(hMainWnd, hMaindc);
00228         }
00229         result = SendMessageW(hEditorWnd, EM_SETTARGETDEVICE, (WPARAM)hdc, width);
00230         DeleteDC(hdc);
00231         if (result)
00232             return;
00233         /* otherwise EM_SETTARGETDEVICE failed, so fall back on wrapping
00234          * to window using the NULL DC. */
00235     }
00236 
00237     if (wordWrap != ID_WORDWRAP_NONE) {
00238         SendMessageW(hEditorWnd, EM_SETTARGETDEVICE, 0, 0);
00239     } else {
00240         SendMessageW(hEditorWnd, EM_SETTARGETDEVICE, 0, 1);
00241     }
00242 
00243 }
00244 
00245 static LPWSTR dialog_print_to_file(HWND hMainWnd)
00246 {
00247     OPENFILENAMEW ofn;
00248     static WCHAR file[MAX_PATH] = {'O','U','T','P','U','T','.','P','R','N',0};
00249     static const WCHAR defExt[] = {'P','R','N',0};
00250     static LPWSTR file_filter;
00251 
00252     if(!file_filter)
00253         file_filter = get_print_file_filter(hMainWnd);
00254 
00255     ZeroMemory(&ofn, sizeof(ofn));
00256 
00257     ofn.lStructSize = sizeof(ofn);
00258     ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
00259     ofn.hwndOwner = hMainWnd;
00260     ofn.lpstrFilter = file_filter;
00261     ofn.lpstrFile = file;
00262     ofn.nMaxFile = MAX_PATH;
00263     ofn.lpstrDefExt = defExt;
00264 
00265     if(GetSaveFileNameW(&ofn))
00266         return file;
00267     else
00268         return FALSE;
00269 }
00270 
00271 static void char_from_pagenum(HWND hEditorWnd, FORMATRANGE *fr, int page)
00272 {
00273     int i;
00274 
00275     fr->chrg.cpMin = 0;
00276 
00277     for(i = 1; i < page; i++)
00278     {
00279         int bottom = fr->rc.bottom;
00280         fr->chrg.cpMin = SendMessageW(hEditorWnd, EM_FORMATRANGE, FALSE, (LPARAM)fr);
00281         fr->rc.bottom = bottom;
00282     }
00283 }
00284 
00285 static HWND get_ruler_wnd(HWND hMainWnd)
00286 {
00287     return GetDlgItem(GetDlgItem(hMainWnd, IDC_REBAR), IDC_RULER);
00288 }
00289 
00290 void redraw_ruler(HWND hRulerWnd)
00291 {
00292     RECT rc;
00293 
00294     GetClientRect(hRulerWnd, &rc);
00295     InvalidateRect(hRulerWnd, &rc, TRUE);
00296 }
00297 
00298 static void update_ruler(HWND hRulerWnd)
00299 {
00300      SendMessageW(hRulerWnd, WM_USER, 0, 0);
00301      redraw_ruler(hRulerWnd);
00302 }
00303 
00304 static void add_ruler_units(HDC hdcRuler, RECT* drawRect, BOOL NewMetrics, LONG EditLeftmost)
00305 {
00306     static HDC hdc;
00307 
00308     if(NewMetrics)
00309     {
00310         static HBITMAP hBitmap;
00311         int i, x, y, RulerTextEnd;
00312         int CmPixels;
00313         int QuarterCmPixels;
00314         HFONT hFont;
00315         WCHAR FontName[] = {'M','S',' ','S','a','n','s',' ','S','e','r','i','f',0};
00316 
00317         if(hdc)
00318         {
00319             DeleteDC(hdc);
00320             DeleteObject(hBitmap);
00321         }
00322 
00323         hdc = CreateCompatibleDC(0);
00324 
00325         CmPixels = twips_to_pixels(centmm_to_twips(1000), GetDeviceCaps(hdc, LOGPIXELSX));
00326         QuarterCmPixels = (int)((float)CmPixels / 4.0);
00327 
00328         hBitmap = CreateCompatibleBitmap(hdc, drawRect->right, drawRect->bottom);
00329         SelectObject(hdc, hBitmap);
00330         FillRect(hdc, drawRect, GetStockObject(WHITE_BRUSH));
00331 
00332         hFont = CreateFontW(10, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, FontName);
00333 
00334         SelectObject(hdc, hFont);
00335         SetBkMode(hdc, TRANSPARENT);
00336         SetTextAlign(hdc, TA_CENTER);
00337         y = (int)(((float)drawRect->bottom - (float)drawRect->top) / 2.0) + 1;
00338         RulerTextEnd = drawRect->right - EditLeftmost + 1;
00339         for(i = 1, x = EditLeftmost; x < (drawRect->right - EditLeftmost + 1); i ++)
00340         {
00341             WCHAR str[3];
00342             WCHAR format[] = {'%','d',0};
00343             int x2 = x;
00344 
00345             x2 += QuarterCmPixels;
00346             if(x2 > RulerTextEnd)
00347                 break;
00348 
00349             MoveToEx(hdc, x2, y, NULL);
00350             LineTo(hdc, x2, y+2);
00351 
00352             x2 += QuarterCmPixels;
00353             if(x2 > RulerTextEnd)
00354                 break;
00355 
00356             MoveToEx(hdc, x2, y - 3, NULL);
00357             LineTo(hdc, x2, y + 3);
00358 
00359             x2 += QuarterCmPixels;
00360             if(x2 > RulerTextEnd)
00361                 break;
00362 
00363             MoveToEx(hdc, x2, y, NULL);
00364             LineTo(hdc, x2, y+2);
00365 
00366             x += CmPixels;
00367             if(x > RulerTextEnd)
00368                 break;
00369 
00370             wsprintfW(str, format, i);
00371             TextOutW(hdc, x, 5, str, lstrlenW(str));
00372         }
00373         DeleteObject(hFont);
00374     }
00375 
00376     BitBlt(hdcRuler, 0, 0, drawRect->right, drawRect->bottom, hdc, 0, 0, SRCAND);
00377 }
00378 
00379 static void paint_ruler(HWND hWnd, LONG EditLeftmost, BOOL NewMetrics)
00380 {
00381     PAINTSTRUCT ps;
00382     HDC hdc = BeginPaint(hWnd, &ps);
00383     HDC hdcPrint = make_dc();
00384     RECT printRect = get_print_rect(hdcPrint);
00385     RECT drawRect;
00386     HBRUSH hBrush = CreateSolidBrush(GetSysColor(COLOR_MENU));
00387 
00388     GetClientRect(hWnd, &drawRect);
00389     FillRect(hdc, &drawRect, hBrush);
00390 
00391     drawRect.top += 3;
00392     drawRect.bottom -= 3;
00393     drawRect.left = EditLeftmost;
00394     drawRect.right = twips_to_pixels(printRect.right - margins.left, GetDeviceCaps(hdc, LOGPIXELSX));
00395     FillRect(hdc, &drawRect, GetStockObject(WHITE_BRUSH));
00396 
00397     drawRect.top--;
00398     drawRect.bottom++;
00399     DrawEdge(hdc, &drawRect, EDGE_SUNKEN, BF_RECT);
00400 
00401     drawRect.left = drawRect.right - 1;
00402     drawRect.right = twips_to_pixels(printRect.right + margins.right - margins.left, GetDeviceCaps(hdc, LOGPIXELSX));
00403     DrawEdge(hdc, &drawRect, EDGE_ETCHED, BF_RECT);
00404 
00405     drawRect.left = 0;
00406     drawRect.top = 0;
00407     add_ruler_units(hdc, &drawRect, NewMetrics, EditLeftmost);
00408 
00409     SelectObject(hdc, GetStockObject(BLACK_BRUSH));
00410     DeleteObject(hBrush);
00411     DeleteDC(hdcPrint);
00412     EndPaint(hWnd, &ps);
00413 }
00414 
00415 LRESULT CALLBACK ruler_proc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
00416 {
00417     static WNDPROC pPrevRulerProc;
00418     static LONG EditLeftmost;
00419     static BOOL NewMetrics;
00420 
00421     switch(msg)
00422     {
00423         case WM_USER:
00424             if(wParam)
00425             {
00426                 EditLeftmost = ((POINTL*)wParam)->x;
00427                 pPrevRulerProc = (WNDPROC)lParam;
00428             }
00429             NewMetrics = TRUE;
00430             break;
00431 
00432         case WM_PAINT:
00433             paint_ruler(hWnd, EditLeftmost, NewMetrics);
00434             break;
00435 
00436         default:
00437             return CallWindowProcW(pPrevRulerProc, hWnd, msg, wParam, lParam);
00438     }
00439 
00440     return 0;
00441 }
00442 
00443 static void print(LPPRINTDLGW pd, LPWSTR wszFileName)
00444 {
00445     FORMATRANGE fr;
00446     DOCINFOW di;
00447     HWND hEditorWnd = GetDlgItem(pd->hwndOwner, IDC_EDITOR);
00448     int printedPages = 0;
00449 
00450     fr.hdc = pd->hDC;
00451     fr.hdcTarget = pd->hDC;
00452 
00453     fr.rc = get_print_rect(fr.hdc);
00454     fr.rcPage.left = 0;
00455     fr.rcPage.right = fr.rc.right + margins.right;
00456     fr.rcPage.top = 0;
00457     fr.rcPage.bottom = fr.rc.bottom + margins.bottom;
00458 
00459     ZeroMemory(&di, sizeof(di));
00460     di.cbSize = sizeof(di);
00461     di.lpszDocName = wszFileName;
00462 
00463     if(pd->Flags & PD_PRINTTOFILE)
00464     {
00465         di.lpszOutput = dialog_print_to_file(pd->hwndOwner);
00466         if(!di.lpszOutput)
00467             return;
00468     }
00469 
00470     if(pd->Flags & PD_SELECTION)
00471     {
00472         SendMessageW(hEditorWnd, EM_EXGETSEL, 0, (LPARAM)&fr.chrg);
00473     } else
00474     {
00475         GETTEXTLENGTHEX gt;
00476         gt.flags = GTL_DEFAULT;
00477         gt.codepage = 1200;
00478         fr.chrg.cpMin = 0;
00479         fr.chrg.cpMax = SendMessageW(hEditorWnd, EM_GETTEXTLENGTHEX, (WPARAM)&gt, 0);
00480 
00481         if(pd->Flags & PD_PAGENUMS)
00482             char_from_pagenum(hEditorWnd, &fr, pd->nToPage);
00483     }
00484 
00485     StartDocW(fr.hdc, &di);
00486     do
00487     {
00488         if(StartPage(fr.hdc) <= 0)
00489             break;
00490 
00491         fr.chrg.cpMin = SendMessageW(hEditorWnd, EM_FORMATRANGE, TRUE, (LPARAM)&fr);
00492 
00493         if(EndPage(fr.hdc) <= 0)
00494             break;
00495 
00496         printedPages++;
00497         if((pd->Flags & PD_PAGENUMS) && (printedPages > (pd->nToPage - pd->nFromPage)))
00498             break;
00499     }
00500     while(fr.chrg.cpMin && fr.chrg.cpMin < fr.chrg.cpMax);
00501 
00502     EndDoc(fr.hdc);
00503     SendMessageW(hEditorWnd, EM_FORMATRANGE, FALSE, 0);
00504 }
00505 
00506 void dialog_printsetup(HWND hMainWnd)
00507 {
00508     PAGESETUPDLGW ps;
00509 
00510     ZeroMemory(&ps, sizeof(ps));
00511     ps.lStructSize = sizeof(ps);
00512     ps.hwndOwner = hMainWnd;
00513     ps.Flags = PSD_INHUNDREDTHSOFMILLIMETERS | PSD_MARGINS;
00514     ps.rtMargin.left = twips_to_centmm(margins.left);
00515     ps.rtMargin.right = twips_to_centmm(margins.right);
00516     ps.rtMargin.top = twips_to_centmm(margins.top);
00517     ps.rtMargin.bottom = twips_to_centmm(margins.bottom);
00518     ps.hDevMode = devMode;
00519     ps.hDevNames = devNames;
00520 
00521     if(PageSetupDlgW(&ps))
00522     {
00523         margins.left = centmm_to_twips(ps.rtMargin.left);
00524         margins.right = centmm_to_twips(ps.rtMargin.right);
00525         margins.top = centmm_to_twips(ps.rtMargin.top);
00526         margins.bottom = centmm_to_twips(ps.rtMargin.bottom);
00527         devMode = ps.hDevMode;
00528         devNames = ps.hDevNames;
00529         update_ruler(get_ruler_wnd(hMainWnd));
00530     }
00531 }
00532 
00533 void get_default_printer_opts(void)
00534 {
00535     PRINTDLGW pd;
00536     ZeroMemory(&pd, sizeof(pd));
00537 
00538     ZeroMemory(&pd, sizeof(pd));
00539     pd.lStructSize = sizeof(pd);
00540     pd.Flags = PD_RETURNDC | PD_RETURNDEFAULT;
00541     pd.hDevMode = devMode;
00542 
00543     PrintDlgW(&pd);
00544 
00545     devMode = pd.hDevMode;
00546     devNames = pd.hDevNames;
00547 }
00548 
00549 void print_quick(HWND hMainWnd, LPWSTR wszFileName)
00550 {
00551     PRINTDLGW pd;
00552 
00553     ZeroMemory(&pd, sizeof(pd));
00554     pd.hwndOwner = hMainWnd;
00555     pd.hDC = make_dc();
00556 
00557     print(&pd, wszFileName);
00558     DeleteDC(pd.hDC);
00559 }
00560 
00561 void dialog_print(HWND hMainWnd, LPWSTR wszFileName)
00562 {
00563     PRINTDLGW pd;
00564     HWND hEditorWnd = GetDlgItem(hMainWnd, IDC_EDITOR);
00565     int from = 0;
00566     int to = 0;
00567 
00568     ZeroMemory(&pd, sizeof(pd));
00569     pd.lStructSize = sizeof(pd);
00570     pd.hwndOwner = hMainWnd;
00571     pd.Flags = PD_RETURNDC | PD_USEDEVMODECOPIESANDCOLLATE;
00572     pd.nMinPage = 1;
00573     pd.nMaxPage = -1;
00574     pd.hDevMode = devMode;
00575     pd.hDevNames = devNames;
00576 
00577     SendMessageW(hEditorWnd, EM_GETSEL, (WPARAM)&from, (LPARAM)&to);
00578     if(from == to)
00579         pd.Flags |= PD_NOSELECTION;
00580 
00581     if(PrintDlgW(&pd))
00582     {
00583         devMode = pd.hDevMode;
00584         devNames = pd.hDevNames;
00585         print(&pd, wszFileName);
00586         update_ruler(get_ruler_wnd(hMainWnd));
00587     }
00588 }
00589 
00590 static void preview_bar_show(HWND hMainWnd, BOOL show)
00591 {
00592     HWND hReBar = GetDlgItem(hMainWnd, IDC_REBAR);
00593     int i;
00594 
00595     if(show)
00596     {
00597         REBARBANDINFOW rb;
00598         HWND hStatic;
00599         UINT num_pages_string = preview.pages_shown > 1 ? STRING_PREVIEW_ONEPAGE :
00600                                                           STRING_PREVIEW_TWOPAGES;
00601 
00602         AddTextButton(hReBar, STRING_PREVIEW_PRINT, ID_PRINT, BANDID_PREVIEW_BTN1);
00603         AddTextButton(hReBar, STRING_PREVIEW_NEXTPAGE, ID_PREVIEW_NEXTPAGE, BANDID_PREVIEW_BTN2);
00604         AddTextButton(hReBar, STRING_PREVIEW_PREVPAGE, ID_PREVIEW_PREVPAGE, BANDID_PREVIEW_BTN3);
00605         AddTextButton(hReBar, num_pages_string, ID_PREVIEW_NUMPAGES, BANDID_PREVIEW_BTN4);
00606         AddTextButton(hReBar, STRING_PREVIEW_ZOOMIN, ID_PREVIEW_ZOOMIN, BANDID_PREVIEW_BTN5);
00607         AddTextButton(hReBar, STRING_PREVIEW_ZOOMOUT, ID_PREVIEW_ZOOMOUT, BANDID_PREVIEW_BTN6);
00608         AddTextButton(hReBar, STRING_PREVIEW_CLOSE, ID_FILE_EXIT, BANDID_PREVIEW_BTN7);
00609 
00610         hStatic = CreateWindowW(WC_STATICW, NULL,
00611                                 WS_VISIBLE | WS_CHILD, 0, 0, 0, 0,
00612                                 hReBar, NULL, NULL, NULL);
00613 
00614         rb.cbSize = REBARBANDINFOW_V6_SIZE;
00615         rb.fMask = RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_STYLE | RBBIM_CHILD | RBBIM_IDEALSIZE | RBBIM_ID;
00616         rb.fStyle = RBBS_NOGRIPPER | RBBS_VARIABLEHEIGHT;
00617         rb.hwndChild = hStatic;
00618         rb.cyChild = rb.cyMinChild = 22;
00619         rb.cx = rb.cxMinChild = 90;
00620         rb.cxIdeal = 100;
00621         rb.wID = BANDID_PREVIEW_BUFFER;
00622 
00623         SendMessageW(hReBar, RB_INSERTBAND, -1, (LPARAM)&rb);
00624     } else
00625     {
00626         for(i = 0; i <= PREVIEW_BUTTONS; i++)
00627             SendMessageW(hReBar, RB_DELETEBAND, SendMessageW(hReBar, RB_IDTOINDEX, BANDID_PREVIEW_BTN1+i, 0), 0);
00628     }
00629 }
00630 
00631 static const int min_spacing = 10;
00632 
00633 static void update_preview_scrollbars(HWND hwndPreview, RECT *window)
00634 {
00635     SCROLLINFO sbi;
00636     sbi.cbSize = sizeof(sbi);
00637     sbi.fMask = SIF_PAGE|SIF_RANGE;
00638     sbi.nMin = 0;
00639     if (preview.zoomlevel == 0)
00640     {
00641         /* Hide scrollbars when zoomed out. */
00642         sbi.nMax = 0;
00643         sbi.nPage = window->right;
00644         SetScrollInfo(hwndPreview, SB_HORZ, &sbi, TRUE);
00645         sbi.nPage = window->bottom;
00646         SetScrollInfo(hwndPreview, SB_VERT, &sbi, TRUE);
00647     } else {
00648         sbi.nMax = preview.bmScaledSize.cx * preview.pages_shown +
00649                    min_spacing * (preview.pages_shown + 1);
00650         sbi.nPage = window->right;
00651         SetScrollInfo(hwndPreview, SB_HORZ, &sbi, TRUE);
00652         /* Change in the horizontal scrollbar visibility affects the
00653          * client rect, so update the client rect. */
00654         GetClientRect(hwndPreview, window);
00655         sbi.nMax = preview.bmScaledSize.cy + min_spacing * 2;
00656         sbi.nPage = window->bottom;
00657         SetScrollInfo(hwndPreview, SB_VERT, &sbi, TRUE);
00658     }
00659 }
00660 
00661 static void update_preview_sizes(HWND hwndPreview, BOOL zoomLevelUpdated)
00662 {
00663     RECT window;
00664 
00665     GetClientRect(hwndPreview, &window);
00666 
00667     /* The zoom ratio isn't updated for partial zoom because of resizing the window. */
00668     if (zoomLevelUpdated || preview.zoomlevel != 1)
00669     {
00670         float ratio, ratioHeight, ratioWidth;
00671         if (preview.zoomlevel == 2)
00672         {
00673             ratio = 1.0;
00674         } else {
00675             ratioHeight = (window.bottom - min_spacing * 2) / (float)preview.bmSize.cy;
00676 
00677             ratioWidth = (float)(window.right -
00678                                  min_spacing * (preview.pages_shown + 1)) /
00679                          (preview.pages_shown * preview.bmSize.cx);
00680 
00681             if(ratioWidth > ratioHeight)
00682                 ratio = ratioHeight;
00683             else
00684                 ratio = ratioWidth;
00685 
00686             if (preview.zoomlevel == 1)
00687                 ratio += (1.0 - ratio) / 2;
00688         }
00689         preview.zoomratio = ratio;
00690     }
00691 
00692     preview.bmScaledSize.cx = preview.bmSize.cx * preview.zoomratio;
00693     preview.bmScaledSize.cy = preview.bmSize.cy * preview.zoomratio;
00694 
00695     preview.spacing.cy = max(min_spacing, (window.bottom - preview.bmScaledSize.cy) / 2);
00696 
00697     preview.spacing.cx = (window.right -
00698                           preview.bmScaledSize.cx * preview.pages_shown) /
00699                          (preview.pages_shown + 1);
00700     if (preview.spacing.cx < min_spacing)
00701         preview.spacing.cx = min_spacing;
00702 
00703     update_preview_scrollbars(hwndPreview, &window);
00704 }
00705 
00706 static void draw_margin_lines(HDC hdc, int x, int y, float ratio)
00707 {
00708     HPEN hPen, oldPen;
00709     SIZE dpi;
00710     RECT page_margin = preview.rcPage;
00711 
00712     dpi.cx = GetDeviceCaps(hdc, LOGPIXELSX);
00713     dpi.cy = GetDeviceCaps(hdc, LOGPIXELSY);
00714 
00715     page_margin.left = preview.rcPage.left + margins.left;
00716     page_margin.top = preview.rcPage.top + margins.top;
00717     page_margin.bottom = preview.rcPage.bottom - margins.bottom;
00718     page_margin.right = preview.rcPage.right - margins.right;
00719 
00720     page_margin.left = (int)((float)twips_to_pixels(page_margin.left, dpi.cx) * ratio);
00721     page_margin.top = (int)((float)twips_to_pixels(page_margin.top, dpi.cy) * ratio);
00722     page_margin.bottom = (int)((float)twips_to_pixels(page_margin.bottom, dpi.cy) * ratio);
00723     page_margin.right = (int)((float)twips_to_pixels(page_margin.right, dpi.cx) * ratio);
00724 
00725     page_margin.left += x;
00726     page_margin.top += y;
00727     page_margin.bottom += y;
00728     page_margin.right += x;
00729 
00730     hPen = CreatePen(PS_DOT, 1, RGB(0,0,0));
00731     oldPen = SelectObject(hdc, hPen);
00732 
00733     MoveToEx(hdc, x, page_margin.top, NULL);
00734     LineTo(hdc, x + preview.bmScaledSize.cx, page_margin.top);
00735     MoveToEx(hdc, x, page_margin.bottom, NULL);
00736     LineTo(hdc, x + preview.bmScaledSize.cx, page_margin.bottom);
00737 
00738     MoveToEx(hdc, page_margin.left, y, NULL);
00739     LineTo(hdc, page_margin.left, y + preview.bmScaledSize.cy);
00740     MoveToEx(hdc, page_margin.right, y, NULL);
00741     LineTo(hdc, page_margin.right, y + preview.bmScaledSize.cy);
00742 
00743     SelectObject(hdc, oldPen);
00744     DeleteObject(hPen);
00745 }
00746 
00747 static BOOL is_last_preview_page(int page)
00748 {
00749     return preview.pageEnds[page - 1] >= preview.textlength;
00750 }
00751 
00752 void init_preview(HWND hMainWnd, LPWSTR wszFileName)
00753 {
00754     HINSTANCE hInstance = GetModuleHandleW(0);
00755     preview.page = 1;
00756     preview.hdc = 0;
00757     preview.hdc2 = 0;
00758     preview.wszFileName = wszFileName;
00759     preview.zoomratio = 0;
00760     preview.zoomlevel = 0;
00761     preview_bar_show(hMainWnd, TRUE);
00762 
00763     CreateWindowExW(0, wszPreviewWndClass, NULL,
00764             WS_VISIBLE | WS_CHILD | WS_VSCROLL | WS_HSCROLL,
00765             0, 0, 200, 10, hMainWnd, (HMENU)IDC_PREVIEW, hInstance, NULL);
00766 }
00767 
00768 void close_preview(HWND hMainWnd)
00769 {
00770     HWND hwndPreview = GetDlgItem(hMainWnd, IDC_PREVIEW);
00771     preview.window.right = 0;
00772     preview.window.bottom = 0;
00773     preview.page = 0;
00774     HeapFree(GetProcessHeap(), 0, preview.pageEnds);
00775     preview.pageEnds = NULL;
00776     preview.pageCapacity = 0;
00777     if (preview.zoomlevel > 0)
00778         preview.pages_shown = preview.saved_pages_shown;
00779     if(preview.hdc) {
00780         HBITMAP oldbm = GetCurrentObject(preview.hdc, OBJ_BITMAP);
00781         DeleteDC(preview.hdc);
00782         DeleteObject(oldbm);
00783         preview.hdc = NULL;
00784     }
00785     if(preview.hdc2) {
00786         HBITMAP oldbm = GetCurrentObject(preview.hdc2, OBJ_BITMAP);
00787         DeleteDC(preview.hdc2);
00788         DeleteObject(oldbm);
00789         preview.hdc2 = NULL;
00790     }
00791 
00792     preview_bar_show(hMainWnd, FALSE);
00793     DestroyWindow(hwndPreview);
00794 }
00795 
00796 BOOL preview_isactive(void)
00797 {
00798     return preview.page != 0;
00799 }
00800 
00801 static void draw_preview(HWND hEditorWnd, FORMATRANGE* lpFr, RECT* paper, int page)
00802 {
00803     int bottom;
00804 
00805     if (!preview.pageEnds)
00806     {
00807         preview.pageCapacity = 32;
00808         preview.pageEnds = HeapAlloc(GetProcessHeap(), 0,
00809                                     sizeof(int) * preview.pageCapacity);
00810         if (!preview.pageEnds) return;
00811     } else if (page >= preview.pageCapacity) {
00812         int *new_buffer;
00813         new_buffer = HeapReAlloc(GetProcessHeap(), 0, preview.pageEnds,
00814                                  sizeof(int) * preview.pageCapacity * 2);
00815         if (!new_buffer) return;
00816         preview.pageCapacity *= 2;
00817         preview.pageEnds = new_buffer;
00818     }
00819 
00820     FillRect(lpFr->hdc, paper, GetStockObject(WHITE_BRUSH));
00821     if (page > 1 && is_last_preview_page(page - 1)) return;
00822     lpFr->chrg.cpMin = page <= 1 ? 0 : preview.pageEnds[page-2];
00823     bottom = lpFr->rc.bottom;
00824     preview.pageEnds[page-1] = SendMessageW(hEditorWnd, EM_FORMATRANGE, TRUE, (LPARAM)lpFr);
00825 
00826     /* EM_FORMATRANGE sets fr.rc.bottom to indicate the area printed in,
00827      * but we want to keep the original for drawing margins */
00828     lpFr->rc.bottom = bottom;
00829     SendMessageW(hEditorWnd, EM_FORMATRANGE, FALSE, 0);
00830 }
00831 
00832 static void update_preview_buttons(HWND hMainWnd)
00833 {
00834     HWND hReBar = GetDlgItem(hMainWnd, IDC_REBAR);
00835     EnableWindow(GetDlgItem(hReBar, ID_PREVIEW_PREVPAGE), preview.page > 1);
00836     EnableWindow(GetDlgItem(hReBar, ID_PREVIEW_NEXTPAGE),
00837                  !is_last_preview_page(preview.page) &&
00838                  !is_last_preview_page(preview.page + preview.pages_shown - 1));
00839     EnableWindow(GetDlgItem(hReBar, ID_PREVIEW_NUMPAGES),
00840                  preview.pages_shown > 1 ||
00841                  (!is_last_preview_page(1) && preview.zoomlevel == 0));
00842     EnableWindow(GetDlgItem(hReBar, ID_PREVIEW_ZOOMIN), preview.zoomlevel < 2);
00843     EnableWindow(GetDlgItem(hReBar, ID_PREVIEW_ZOOMOUT), preview.zoomlevel > 0);
00844 }
00845 
00846 static LRESULT print_preview(HWND hwndPreview)
00847 {
00848     HPEN hPen, oldPen;
00849     HDC hdc;
00850     HRGN back_rgn, excl_rgn;
00851     RECT window, background;
00852     PAINTSTRUCT ps;
00853     int x, y;
00854 
00855     hdc = BeginPaint(hwndPreview, &ps);
00856     GetClientRect(hwndPreview, &window);
00857     back_rgn = CreateRectRgnIndirect(&window);
00858 
00859     x = preview.spacing.cx - GetScrollPos(hwndPreview, SB_HORZ);
00860     y = preview.spacing.cy - GetScrollPos(hwndPreview, SB_VERT);
00861 
00862     /* draw page outlines */
00863     hPen = CreatePen(PS_SOLID|PS_INSIDEFRAME, 2, RGB(0,0,0));
00864     oldPen = SelectObject(hdc, hPen);
00865     background.left = x - 2;
00866     background.right = x + preview.bmScaledSize.cx + 2;
00867     background.top = y - 2;
00868     background.bottom = y + preview.bmScaledSize.cy + 2;
00869     Rectangle(hdc, background.left, background.top,
00870               background.right, background.bottom);
00871     excl_rgn = CreateRectRgnIndirect(&background);
00872     CombineRgn(back_rgn, back_rgn, excl_rgn, RGN_DIFF);
00873     if(preview.pages_shown > 1)
00874     {
00875         background.left += preview.bmScaledSize.cx + preview.spacing.cx;
00876         background.right += preview.bmScaledSize.cx + preview.spacing.cx;
00877         Rectangle(hdc, background.left, background.top,
00878                   background.right, background.bottom);
00879         SetRectRgn(excl_rgn, background.left, background.top,
00880                    background.right, background.bottom);
00881         CombineRgn(back_rgn, back_rgn, excl_rgn, RGN_DIFF);
00882     }
00883     SelectObject(hdc, oldPen);
00884     DeleteObject(hPen);
00885     FillRgn(hdc, back_rgn, GetStockObject(GRAY_BRUSH));
00886     DeleteObject(excl_rgn);
00887     DeleteObject(back_rgn);
00888 
00889     StretchBlt(hdc, x, y, preview.bmScaledSize.cx, preview.bmScaledSize.cy,
00890                preview.hdc, 0, 0, preview.bmSize.cx, preview.bmSize.cy, SRCCOPY);
00891 
00892     draw_margin_lines(hdc, x, y, preview.zoomratio);
00893 
00894     if(preview.pages_shown > 1)
00895     {
00896         if (!is_last_preview_page(preview.page)) {
00897             x += preview.spacing.cx + preview.bmScaledSize.cx;
00898             StretchBlt(hdc, x, y,
00899                        preview.bmScaledSize.cx, preview.bmScaledSize.cy,
00900                        preview.hdc2, 0, 0,
00901                        preview.bmSize.cx, preview.bmSize.cy, SRCCOPY);
00902 
00903             draw_margin_lines(hdc, x, y, preview.zoomratio);
00904         } else {
00905             background.left += 2;
00906             background.right -= 2;
00907             background.top += 2;
00908             background.bottom -= 2;
00909             FillRect(hdc, &background, GetStockObject(WHITE_BRUSH));
00910         }
00911     }
00912 
00913     preview.window = window;
00914 
00915     EndPaint(hwndPreview, &ps);
00916 
00917     return 0;
00918 }
00919 
00920 static void update_preview_statusbar(HWND hMainWnd)
00921 {
00922     HWND hStatusbar = GetDlgItem(hMainWnd, IDC_STATUSBAR);
00923     HINSTANCE hInst = GetModuleHandleW(0);
00924     WCHAR *p;
00925     WCHAR wstr[MAX_STRING_LEN];
00926 
00927     p = wstr;
00928     if (preview.pages_shown < 2 || is_last_preview_page(preview.page))
00929     {
00930         static const WCHAR fmt[] = {' ','%','d','\0'};
00931         p += LoadStringW(hInst, STRING_PREVIEW_PAGE, wstr, MAX_STRING_LEN);
00932         wsprintfW(p, fmt, preview.page);
00933     } else {
00934         static const WCHAR fmt[] = {' ','%','d','-','%','d','\0'};
00935         p += LoadStringW(hInst, STRING_PREVIEW_PAGES, wstr, MAX_STRING_LEN);
00936         wsprintfW(p, fmt, preview.page, preview.page + 1);
00937     }
00938     SetWindowTextW(hStatusbar, wstr);
00939 }
00940 
00941 /* Update for page changes. */
00942 static void update_preview(HWND hMainWnd)
00943 {
00944     RECT paper;
00945     HWND hEditorWnd = GetDlgItem(hMainWnd, IDC_EDITOR);
00946     HWND hwndPreview = GetDlgItem(hMainWnd, IDC_PREVIEW);
00947     HBITMAP hBitmapCapture;
00948     FORMATRANGE fr;
00949     HDC hdc = GetDC(hwndPreview);
00950 
00951     fr.hdcTarget = make_dc();
00952     fr.rc = fr.rcPage = preview.rcPage;
00953     fr.rc.left += margins.left;
00954     fr.rc.top += margins.top;
00955     fr.rc.bottom -= margins.bottom;
00956     fr.rc.right -= margins.right;
00957 
00958     fr.chrg.cpMin = 0;
00959     fr.chrg.cpMax = preview.textlength;
00960 
00961     paper.left = 0;
00962     paper.right = preview.bmSize.cx;
00963     paper.top = 0;
00964     paper.bottom = preview.bmSize.cy;
00965 
00966     if (!preview.hdc) {
00967         preview.hdc = CreateCompatibleDC(hdc);
00968         hBitmapCapture = CreateCompatibleBitmap(hdc, preview.bmSize.cx, preview.bmSize.cy);
00969         SelectObject(preview.hdc, hBitmapCapture);
00970     }
00971 
00972     fr.hdc = preview.hdc;
00973     draw_preview(hEditorWnd, &fr, &paper, preview.page);
00974 
00975     if(preview.pages_shown > 1)
00976     {
00977         if (!preview.hdc2)
00978         {
00979             preview.hdc2 = CreateCompatibleDC(hdc);
00980             hBitmapCapture = CreateCompatibleBitmap(hdc,
00981                                                     preview.bmSize.cx,
00982                                                     preview.bmSize.cy);
00983             SelectObject(preview.hdc2, hBitmapCapture);
00984         }
00985 
00986         fr.hdc = preview.hdc2;
00987         draw_preview(hEditorWnd, &fr, &fr.rcPage, preview.page + 1);
00988     }
00989     DeleteDC(fr.hdcTarget);
00990     ReleaseDC(hwndPreview, hdc);
00991 
00992     InvalidateRect(hwndPreview, NULL, FALSE);
00993     update_preview_buttons(hMainWnd);
00994     update_preview_statusbar(hMainWnd);
00995 }
00996 
00997 static void toggle_num_pages(HWND hMainWnd)
00998 {
00999     HWND hReBar = GetDlgItem(hMainWnd, IDC_REBAR);
01000     WCHAR name[MAX_STRING_LEN];
01001     HINSTANCE hInst = GetModuleHandleW(0);
01002     int nPreviewPages;
01003 
01004     preview.pages_shown = preview.pages_shown > 1 ? 1 : 2;
01005 
01006     nPreviewPages = preview.zoomlevel > 0 ? preview.saved_pages_shown :
01007                                             preview.pages_shown;
01008 
01009     LoadStringW(hInst, nPreviewPages > 1 ? STRING_PREVIEW_ONEPAGE :
01010                                            STRING_PREVIEW_TWOPAGES,
01011                 name, MAX_STRING_LEN);
01012 
01013     SetWindowTextW(GetDlgItem(hReBar, ID_PREVIEW_NUMPAGES), name);
01014     update_preview_sizes(GetDlgItem(hMainWnd, IDC_PREVIEW), TRUE);
01015     update_preview(hMainWnd);
01016 }
01017 
01018 /* Returns the page shown that the point is in (1 or 2) or 0 if the point
01019  * isn't inside either page */
01020 static int preview_page_hittest(POINT pt)
01021 {
01022     RECT rc;
01023     rc.left = preview.spacing.cx;
01024     rc.right = rc.left + preview.bmScaledSize.cx;
01025     rc.top = preview.spacing.cy;
01026     rc.bottom = rc.top + preview.bmScaledSize.cy;
01027     if (PtInRect(&rc, pt))
01028         return 1;
01029 
01030     if (preview.pages_shown <= 1)
01031         return 0;
01032 
01033     rc.left += preview.bmScaledSize.cx + preview.spacing.cx;
01034     rc.right += preview.bmScaledSize.cx + preview.spacing.cx;
01035     if (PtInRect(&rc, pt))
01036         return is_last_preview_page(preview.page) ? 1 : 2;
01037 
01038     return 0;
01039 }
01040 
01041 LRESULT CALLBACK preview_proc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
01042 {
01043     switch(msg)
01044     {
01045         case WM_CREATE:
01046         {
01047             HWND hMainWnd = GetParent(hWnd);
01048             HWND hEditorWnd = GetDlgItem(hMainWnd, IDC_EDITOR);
01049             FORMATRANGE fr;
01050             GETTEXTLENGTHEX gt = {GTL_DEFAULT, 1200};
01051             HDC hdc = GetDC(hWnd);
01052             HDC hdcTarget = make_dc();
01053 
01054             fr.rc = preview.rcPage = get_print_rect(hdcTarget);
01055             preview.rcPage.bottom += margins.bottom;
01056             preview.rcPage.right += margins.right;
01057             preview.rcPage.top = preview.rcPage.left = 0;
01058             fr.rcPage = preview.rcPage;
01059 
01060             preview.bmSize.cx = twips_to_pixels(preview.rcPage.right, GetDeviceCaps(hdc, LOGPIXELSX));
01061             preview.bmSize.cy = twips_to_pixels(preview.rcPage.bottom, GetDeviceCaps(hdc, LOGPIXELSY));
01062 
01063             preview.textlength = SendMessageW(hEditorWnd, EM_GETTEXTLENGTHEX, (WPARAM)&gt, 0);
01064 
01065             fr.hdc = CreateCompatibleDC(hdc);
01066             fr.hdcTarget = hdcTarget;
01067             fr.chrg.cpMin = 0;
01068             fr.chrg.cpMax = preview.textlength;
01069             DeleteDC(fr.hdc);
01070             DeleteDC(hdcTarget);
01071             ReleaseDC(hWnd, hdc);
01072 
01073             update_preview_sizes(hWnd, TRUE);
01074             update_preview(hMainWnd);
01075             break;
01076         }
01077 
01078         case WM_PAINT:
01079             return print_preview(hWnd);
01080 
01081         case WM_SIZE:
01082         {
01083             update_preview_sizes(hWnd, FALSE);
01084             InvalidateRect(hWnd, NULL, FALSE);
01085             break;
01086         }
01087 
01088         case WM_VSCROLL:
01089         case WM_HSCROLL:
01090         {
01091             SCROLLINFO si;
01092             RECT rc;
01093             int nBar = (msg == WM_VSCROLL) ? SB_VERT : SB_HORZ;
01094             int origPos;
01095 
01096             GetClientRect(hWnd, &rc);
01097             si.cbSize = sizeof(si);
01098             si.fMask = SIF_ALL;
01099             GetScrollInfo(hWnd, nBar, &si);
01100             origPos = si.nPos;
01101             switch(LOWORD(wParam))
01102             {
01103                 case SB_TOP: /* == SB_LEFT */
01104                     si.nPos = si.nMin;
01105                     break;
01106                 case SB_BOTTOM: /* == SB_RIGHT */
01107                     si.nPos = si.nMax;
01108                     break;
01109                 case SB_LINEUP: /* == SB_LINELEFT */
01110                     si.nPos -= si.nPage / 10;
01111                     break;
01112                 case SB_LINEDOWN: /* == SB_LINERIGHT */
01113                     si.nPos += si.nPage / 10;
01114                     break;
01115                 case SB_PAGEUP: /* == SB_PAGELEFT */
01116                     si.nPos -= si.nPage;
01117                     break;
01118                 case SB_PAGEDOWN: /* SB_PAGERIGHT */
01119                     si.nPos += si.nPage;
01120                     break;
01121                 case SB_THUMBTRACK:
01122                     si.nPos = si.nTrackPos;
01123                     break;
01124             }
01125             si.fMask = SIF_POS;
01126             SetScrollInfo(hWnd, nBar, &si, TRUE);
01127             GetScrollInfo(hWnd, nBar, &si);
01128             if (si.nPos != origPos)
01129             {
01130                 int amount = origPos - si.nPos;
01131                 if (msg == WM_VSCROLL)
01132                     ScrollWindow(hWnd, 0, amount, NULL, NULL);
01133                 else
01134                     ScrollWindow(hWnd, amount, 0, NULL, NULL);
01135             }
01136             return 0;
01137         }
01138 
01139         case WM_SETCURSOR:
01140         {
01141             POINT pt;
01142             RECT rc;
01143             int bHittest = FALSE;
01144             DWORD messagePos = GetMessagePos();
01145             pt.x = (short)LOWORD(messagePos);
01146             pt.y = (short)HIWORD(messagePos);
01147             ScreenToClient(hWnd, &pt);
01148 
01149             GetClientRect(hWnd, &rc);
01150             if (PtInRect(&rc, pt))
01151             {
01152                 pt.x += GetScrollPos(hWnd, SB_HORZ);
01153                 pt.y += GetScrollPos(hWnd, SB_VERT);
01154                 bHittest = preview_page_hittest(pt);
01155             }
01156 
01157             if (bHittest)
01158                 SetCursor(LoadCursorW(GetModuleHandleW(0),
01159                                       MAKEINTRESOURCEW(IDC_ZOOM)));
01160             else
01161                 SetCursor(LoadCursorW(NULL, (WCHAR*)IDC_ARROW));
01162 
01163             return TRUE;
01164         }
01165 
01166         case WM_LBUTTONDOWN:
01167         {
01168             int page;
01169             POINT pt;
01170             pt.x = (short)LOWORD(lParam) + GetScrollPos(hWnd, SB_HORZ);
01171             pt.y = (short)HIWORD(lParam) + GetScrollPos(hWnd, SB_VERT);
01172             if ((page = preview_page_hittest(pt)) > 0)
01173             {
01174                 HWND hMainWnd = GetParent(hWnd);
01175 
01176                 /* Convert point from client coordinate to unzoomed page
01177                  * coordinate. */
01178                 pt.x -= preview.spacing.cx;
01179                 if (page > 1)
01180                     pt.x -= preview.bmScaledSize.cx + preview.spacing.cx;
01181                 pt.y -= preview.spacing.cy;
01182                 pt.x /= preview.zoomratio;
01183                 pt.y /= preview.zoomratio;
01184 
01185                 if (preview.zoomlevel == 0)
01186                     preview.saved_pages_shown = preview.pages_shown;
01187                 preview.zoomlevel = (preview.zoomlevel + 1) % 3;
01188                 preview.zoomratio = 0;
01189                 if (preview.zoomlevel == 0 && preview.saved_pages_shown > 1)
01190                 {
01191                     toggle_num_pages(hMainWnd);
01192                 } else if (preview.pages_shown > 1) {
01193                     if (page >= 2) preview.page++;
01194                     toggle_num_pages(hMainWnd);
01195                 } else {
01196                     update_preview_sizes(hWnd, TRUE);
01197                     InvalidateRect(hWnd, NULL, FALSE);
01198                     update_preview_buttons(hMainWnd);
01199                 }
01200 
01201                 if (preview.zoomlevel > 0) {
01202                     SCROLLINFO si;
01203                     /* Convert the coordinate back to client coordinate. */
01204                     pt.x *= preview.zoomratio;
01205                     pt.y *= preview.zoomratio;
01206                     pt.x += preview.spacing.cx;
01207                     pt.y += preview.spacing.cy;
01208                     /* Scroll to center view at that point on the page */
01209                     si.cbSize = sizeof(si);
01210                     si.fMask = SIF_PAGE;
01211                     GetScrollInfo(hWnd, SB_HORZ, &si);
01212                     pt.x -= si.nPage / 2;
01213                     SetScrollPos(hWnd, SB_HORZ, pt.x, TRUE);
01214                     GetScrollInfo(hWnd, SB_VERT, &si);
01215                     pt.y -= si.nPage / 2;
01216                     SetScrollPos(hWnd, SB_VERT, pt.y, TRUE);
01217                 }
01218             }
01219         }
01220 
01221         default:
01222             return DefWindowProcW(hWnd, msg, wParam, lParam);
01223     }
01224 
01225     return 0;
01226 }
01227 
01228 LRESULT preview_command(HWND hWnd, WPARAM wParam)
01229 {
01230     switch(LOWORD(wParam))
01231     {
01232         case ID_FILE_EXIT:
01233             PostMessageW(hWnd, WM_CLOSE, 0, 0);
01234             break;
01235 
01236         case ID_PREVIEW_NEXTPAGE:
01237         case ID_PREVIEW_PREVPAGE:
01238         {
01239             if(LOWORD(wParam) == ID_PREVIEW_NEXTPAGE)
01240                 preview.page++;
01241             else
01242                 preview.page--;
01243 
01244             update_preview(hWnd);
01245         }
01246         break;
01247 
01248         case ID_PREVIEW_NUMPAGES:
01249             toggle_num_pages(hWnd);
01250             break;
01251 
01252         case ID_PREVIEW_ZOOMIN:
01253             if (preview.zoomlevel < 2)
01254             {
01255                 if (preview.zoomlevel == 0)
01256                     preview.saved_pages_shown = preview.pages_shown;
01257                 preview.zoomlevel++;
01258                 preview.zoomratio = 0;
01259                 if (preview.pages_shown > 1)
01260                 {
01261                     /* Forced switch to one page when zooming in. */
01262                     toggle_num_pages(hWnd);
01263                 } else {
01264                     HWND hwndPreview = GetDlgItem(hWnd, IDC_PREVIEW);
01265                     update_preview_sizes(hwndPreview, TRUE);
01266                     InvalidateRect(hwndPreview, NULL, FALSE);
01267                     update_preview_buttons(hWnd);
01268                 }
01269             }
01270             break;
01271 
01272         case ID_PREVIEW_ZOOMOUT:
01273             if (preview.zoomlevel > 0)
01274             {
01275                 HWND hwndPreview = GetDlgItem(hWnd, IDC_PREVIEW);
01276                 preview.zoomlevel--;
01277                 preview.zoomratio = 0;
01278                 if (preview.zoomlevel == 0 && preview.saved_pages_shown > 1) {
01279                     toggle_num_pages(hWnd);
01280                 } else {
01281                     update_preview_sizes(hwndPreview, TRUE);
01282                     InvalidateRect(hwndPreview, NULL, FALSE);
01283                     update_preview_buttons(hWnd);
01284                 }
01285             }
01286             break;
01287 
01288         case ID_PRINT:
01289             dialog_print(hWnd, preview.wszFileName);
01290             SendMessageW(hWnd, WM_CLOSE, 0, 0);
01291             break;
01292     }
01293 
01294     return 0;
01295 }

Generated on Fri May 25 2012 04:15:48 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.