ReactOS  0.4.11-dev-721-g95bc44e
printdlg.c
Go to the documentation of this file.
1 /*
2  * COMMDLG - Print Dialog
3  *
4  * Copyright 1994 Martin Ayotte
5  * Copyright 1996 Albrecht Kleine
6  * Copyright 1999 Klaas van Gend
7  * Copyright 2000 Huw D M Davies
8  * Copyright 2010 Vitaly Perov
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 #include <ctype.h>
25 #include <stdlib.h>
26 #include <stdarg.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <assert.h>
30 
31 #define COBJMACROS
32 #define NONAMELESSUNION
33 #define NONAMELESSSTRUCT
34 #include "windef.h"
35 #include "winbase.h"
36 #include "wingdi.h"
37 #include "winuser.h"
38 #include "winspool.h"
39 #include "winerror.h"
40 #include "objbase.h"
41 #include "commdlg.h"
42 
43 #include "wine/unicode.h"
44 #include "wine/debug.h"
45 
46 #include "dlgs.h"
47 #include "cderr.h"
48 #include "cdlg.h"
49 
51 
52 /* Yes these constants are the same, but we're just copying win98 */
53 #define UPDOWN_ID 0x270f
54 #define MAX_COPIES 9999
55 
56 /* This PRINTDLGA internal structure stores
57  * pointers to several throughout useful structures.
58  */
59 
60 typedef struct
61 {
67  HICON hCollateIcon; /* PrintDlg only */
68  HICON hNoCollateIcon; /* PrintDlg only */
69  HICON hPortraitIcon; /* PrintSetupDlg only */
70  HICON hLandscapeIcon; /* PrintSetupDlg only */
72 } PRINT_PTRA;
73 
74 typedef struct
75 {
81  HICON hCollateIcon; /* PrintDlg only */
82  HICON hNoCollateIcon; /* PrintDlg only */
83  HICON hPortraitIcon; /* PrintSetupDlg only */
84  HICON hLandscapeIcon; /* PrintSetupDlg only */
86 } PRINT_PTRW;
87 
88 /* Debugging info */
89 struct pd_flags
90 {
93 };
94 
95 static const struct pd_flags psd_flags[] = {
96  {PSD_MINMARGINS,"PSD_MINMARGINS"},
97  {PSD_MARGINS,"PSD_MARGINS"},
98  {PSD_INTHOUSANDTHSOFINCHES,"PSD_INTHOUSANDTHSOFINCHES"},
99  {PSD_INHUNDREDTHSOFMILLIMETERS,"PSD_INHUNDREDTHSOFMILLIMETERS"},
100  {PSD_DISABLEMARGINS,"PSD_DISABLEMARGINS"},
101  {PSD_DISABLEPRINTER,"PSD_DISABLEPRINTER"},
102  {PSD_NOWARNING,"PSD_NOWARNING"},
103  {PSD_DISABLEORIENTATION,"PSD_DISABLEORIENTATION"},
104  {PSD_RETURNDEFAULT,"PSD_RETURNDEFAULT"},
105  {PSD_DISABLEPAPER,"PSD_DISABLEPAPER"},
106  {PSD_SHOWHELP,"PSD_SHOWHELP"},
107  {PSD_ENABLEPAGESETUPHOOK,"PSD_ENABLEPAGESETUPHOOK"},
108  {PSD_ENABLEPAGESETUPTEMPLATE,"PSD_ENABLEPAGESETUPTEMPLATE"},
109  {PSD_ENABLEPAGESETUPTEMPLATEHANDLE,"PSD_ENABLEPAGESETUPTEMPLATEHANDLE"},
110  {PSD_ENABLEPAGEPAINTHOOK,"PSD_ENABLEPAGEPAINTHOOK"},
111  {PSD_DISABLEPAGEPAINTING,"PSD_DISABLEPAGEPAINTING"},
112  {-1, NULL}
113 };
114 
115 static const struct pd_flags pd_flags[] = {
116  {PD_SELECTION, "PD_SELECTION "},
117  {PD_PAGENUMS, "PD_PAGENUMS "},
118  {PD_NOSELECTION, "PD_NOSELECTION "},
119  {PD_NOPAGENUMS, "PD_NOPAGENUMS "},
120  {PD_COLLATE, "PD_COLLATE "},
121  {PD_PRINTTOFILE, "PD_PRINTTOFILE "},
122  {PD_PRINTSETUP, "PD_PRINTSETUP "},
123  {PD_NOWARNING, "PD_NOWARNING "},
124  {PD_RETURNDC, "PD_RETURNDC "},
125  {PD_RETURNIC, "PD_RETURNIC "},
126  {PD_RETURNDEFAULT, "PD_RETURNDEFAULT "},
127  {PD_SHOWHELP, "PD_SHOWHELP "},
128  {PD_ENABLEPRINTHOOK, "PD_ENABLEPRINTHOOK "},
129  {PD_ENABLESETUPHOOK, "PD_ENABLESETUPHOOK "},
130  {PD_ENABLEPRINTTEMPLATE, "PD_ENABLEPRINTTEMPLATE "},
131  {PD_ENABLESETUPTEMPLATE, "PD_ENABLESETUPTEMPLATE "},
132  {PD_ENABLEPRINTTEMPLATEHANDLE, "PD_ENABLEPRINTTEMPLATEHANDLE "},
133  {PD_ENABLESETUPTEMPLATEHANDLE, "PD_ENABLESETUPTEMPLATEHANDLE "},
134  {PD_USEDEVMODECOPIES, "PD_USEDEVMODECOPIES[ANDCOLLATE] "},
135  {PD_DISABLEPRINTTOFILE, "PD_DISABLEPRINTTOFILE "},
136  {PD_HIDEPRINTTOFILE, "PD_HIDEPRINTTOFILE "},
137  {PD_NONETWORKBUTTON, "PD_NONETWORKBUTTON "},
138  {-1, NULL}
139 };
140 /* address of wndproc for subclassed Static control */
143 /* the text of the fake document to render for the Page Setup dialog */
145 static const WCHAR pd32_collateW[] = { 'P', 'D', '3', '2', '_', 'C', 'O', 'L', 'L', 'A', 'T', 'E', 0 };
146 static const WCHAR pd32_nocollateW[] = { 'P', 'D', '3', '2', '_', 'N', 'O', 'C', 'O', 'L', 'L', 'A', 'T', 'E', 0 };
147 static const WCHAR pd32_portraitW[] = { 'P', 'D', '3', '2', '_', 'P', 'O', 'R', 'T', 'R', 'A', 'I', 'T', 0 };
148 static const WCHAR pd32_landscapeW[] = { 'P', 'D', '3', '2', '_', 'L', 'A', 'N', 'D', 'S', 'C', 'A', 'P', 'E', 0 };
149 static const WCHAR printdlg_prop[] = {'_','_','W','I','N','E','_','P','R','I','N','T','D','L','G','D','A','T','A',0};
150 static const WCHAR pagesetupdlg_prop[] = { '_', '_', 'W', 'I', 'N', 'E', '_', 'P', 'A', 'G', 'E',
151  'S', 'E', 'T', 'U', 'P', 'D', 'L', 'G', 'D', 'A', 'T', 'A', 0 };
152 
153 
155 {
156  LPWSTR ret;
157  DWORD len;
158 
159  if(!p) return NULL;
160  len = (strlenW(p) + 1) * sizeof(WCHAR);
161  ret = HeapAlloc(GetProcessHeap(), 0, len);
162  memcpy(ret, p, len);
163  return ret;
164 }
165 
166 /***********************************************************************
167  * get_driver_info [internal]
168  *
169  * get DRIVER_INFO_3W for the current printer handle,
170  * alloc the buffer, when needed
171  */
173 {
174  DRIVER_INFO_3W *di3 = NULL;
175  DWORD needed = 0;
176  BOOL res;
177 
178  res = GetPrinterDriverW(hprn, NULL, 3, NULL, 0, &needed);
179  if (!res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {
180  di3 = HeapAlloc(GetProcessHeap(), 0, needed);
181  res = GetPrinterDriverW(hprn, NULL, 3, (LPBYTE)di3, needed, &needed);
182  }
183 
184  if (res)
185  return di3;
186 
187  TRACE("GetPrinterDriverW failed with %u\n", GetLastError());
188  HeapFree(GetProcessHeap(), 0, di3);
189  return NULL;
190 }
191 
193 {
194  DRIVER_INFO_3A *di3 = NULL;
195  DWORD needed = 0;
196  BOOL res;
197 
198  res = GetPrinterDriverA(hprn, NULL, 3, NULL, 0, &needed);
199  if (!res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {
200  di3 = HeapAlloc(GetProcessHeap(), 0, needed);
201  res = GetPrinterDriverA(hprn, NULL, 3, (LPBYTE)di3, needed, &needed);
202  }
203 
204  if (res)
205  return di3;
206 
207  TRACE("GetPrinterDriverA failed with %u\n", GetLastError());
208  HeapFree(GetProcessHeap(), 0, di3);
209  return NULL;
210 }
211 
212 
213 /***********************************************************************
214  * get_printer_info [internal]
215  *
216  * get PRINTER_INFO_2W for the current printer handle,
217  * alloc the buffer, when needed
218  */
220 {
221  PRINTER_INFO_2W *pi2 = NULL;
222  DWORD needed = 0;
223  BOOL res;
224 
225  res = GetPrinterW(hprn, 2, NULL, 0, &needed);
226  if (!res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {
227  pi2 = HeapAlloc(GetProcessHeap(), 0, needed);
228  res = GetPrinterW(hprn, 2, (LPBYTE)pi2, needed, &needed);
229  }
230 
231  if (res)
232  return pi2;
233 
234  TRACE("GetPrinterW failed with %u\n", GetLastError());
235  HeapFree(GetProcessHeap(), 0, pi2);
236  return NULL;
237 }
238 
240 {
241  PRINTER_INFO_2A *pi2 = NULL;
242  DWORD needed = 0;
243  BOOL res;
244 
245  res = GetPrinterA(hprn, 2, NULL, 0, &needed);
246  if (!res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {
247  pi2 = HeapAlloc(GetProcessHeap(), 0, needed);
248  res = GetPrinterA(hprn, 2, (LPBYTE)pi2, needed, &needed);
249  }
250 
251  if (res)
252  return pi2;
253 
254  TRACE("GetPrinterA failed with %u\n", GetLastError());
255  HeapFree(GetProcessHeap(), 0, pi2);
256  return NULL;
257 }
258 
259 
260 /***********************************************************************
261  * update_devmode_handle [internal]
262  *
263  * update a devmode handle for the given DEVMODE, alloc the buffer, when needed
264  */
266 {
267  SIZE_T size = GlobalSize(hdm);
268  LPVOID ptr;
269 
270  /* Increase / alloc the global memory block, when needed */
271  if ((dm->dmSize + dm->dmDriverExtra) > size) {
272  if (hdm)
273  hdm = GlobalReAlloc(hdm, dm->dmSize + dm->dmDriverExtra, 0);
274  else
275  hdm = GlobalAlloc(GMEM_MOVEABLE, dm->dmSize + dm->dmDriverExtra);
276  }
277 
278  if (hdm) {
279  ptr = GlobalLock(hdm);
280  if (ptr) {
281  memcpy(ptr, dm, dm->dmSize + dm->dmDriverExtra);
282  GlobalUnlock(hdm);
283  }
284  else
285  {
286  GlobalFree(hdm);
287  hdm = NULL;
288  }
289  }
290  return hdm;
291 }
292 
294 {
295  SIZE_T size = GlobalSize(hdm);
296  LPVOID ptr;
297 
298  /* Increase / alloc the global memory block, when needed */
299  if ((dm->dmSize + dm->dmDriverExtra) > size) {
300  if (hdm)
301  hdm = GlobalReAlloc(hdm, dm->dmSize + dm->dmDriverExtra, 0);
302  else
303  hdm = GlobalAlloc(GMEM_MOVEABLE, dm->dmSize + dm->dmDriverExtra);
304  }
305 
306  if (hdm) {
307  ptr = GlobalLock(hdm);
308  if (ptr) {
309  memcpy(ptr, dm, dm->dmSize + dm->dmDriverExtra);
310  GlobalUnlock(hdm);
311  }
312  else
313  {
314  GlobalFree(hdm);
315  hdm = NULL;
316  }
317  }
318  return hdm;
319 }
320 
321 /***********************************************************
322  * convert_to_devmodeA
323  *
324  * Creates an ansi copy of supplied devmode
325  */
327 {
328  DEVMODEA *dmA;
329  DWORD size;
330 
331  if (!dmW) return NULL;
332  size = dmW->dmSize - CCHDEVICENAME -
333  ((dmW->dmSize > FIELD_OFFSET(DEVMODEW, dmFormName)) ? CCHFORMNAME : 0);
334 
335  dmA = HeapAlloc(GetProcessHeap(), 0, size + dmW->dmDriverExtra);
336  if (!dmA) return NULL;
337 
340 
341  if (FIELD_OFFSET(DEVMODEW, dmFormName) >= dmW->dmSize)
342  {
343  memcpy(&dmA->dmSpecVersion, &dmW->dmSpecVersion,
344  dmW->dmSize - FIELD_OFFSET(DEVMODEW, dmSpecVersion));
345  }
346  else
347  {
348  memcpy(&dmA->dmSpecVersion, &dmW->dmSpecVersion,
349  FIELD_OFFSET(DEVMODEW, dmFormName) - FIELD_OFFSET(DEVMODEW, dmSpecVersion));
352 
353  memcpy(&dmA->dmLogPixels, &dmW->dmLogPixels, dmW->dmSize - FIELD_OFFSET(DEVMODEW, dmLogPixels));
354  }
355 
356  dmA->dmSize = size;
357  memcpy((char *)dmA + dmA->dmSize, (const char *)dmW + dmW->dmSize, dmW->dmDriverExtra);
358  return dmA;
359 }
360 
361 /***********************************************************************
362  * PRINTDLG_OpenDefaultPrinter
363  *
364  * Returns a winspool printer handle to the default printer in *hprn
365  * Caller must call ClosePrinter on the handle
366  *
367  * Returns TRUE on success else FALSE
368  */
370 {
371  WCHAR buf[260];
372  DWORD dwBufLen = ARRAY_SIZE(buf);
373  BOOL res;
374  if(!GetDefaultPrinterW(buf, &dwBufLen))
375  return FALSE;
376  res = OpenPrinterW(buf, hprn, NULL);
377  if (!res)
378  WARN("Could not open printer %s\n", debugstr_w(buf));
379  return res;
380 }
381 
382 /***********************************************************************
383  * PRINTDLG_SetUpPrinterListCombo
384  *
385  * Initializes printer list combox.
386  * hDlg: HWND of dialog
387  * id: Control id of combo
388  * name: Name of printer to select
389  *
390  * Initializes combo with list of available printers. Selects printer 'name'
391  * If name is NULL or does not exist select the default printer.
392  *
393  * Returns number of printers added to list.
394  */
396 {
397  DWORD needed, num;
398  INT i;
400  EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &needed, &num);
401  pi = HeapAlloc(GetProcessHeap(), 0, needed);
402  EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 2, (LPBYTE)pi, needed, &needed,
403  &num);
404 
405  SendDlgItemMessageA(hDlg, id, CB_RESETCONTENT, 0, 0);
406 
407  for(i = 0; i < num; i++) {
408  SendDlgItemMessageA(hDlg, id, CB_ADDSTRING, 0,
409  (LPARAM)pi[i].pPrinterName );
410  }
411  HeapFree(GetProcessHeap(), 0, pi);
412  if(!name ||
413  (i = SendDlgItemMessageA(hDlg, id, CB_FINDSTRINGEXACT, -1,
414  (LPARAM)name)) == CB_ERR) {
415 
416  char buf[260];
417  DWORD dwBufLen = ARRAY_SIZE(buf);
418  if (name != NULL)
419  WARN("Can't find %s in printer list so trying to find default\n",
420  debugstr_a(name));
421  if(!GetDefaultPrinterA(buf, &dwBufLen))
422  return num;
423  i = SendDlgItemMessageA(hDlg, id, CB_FINDSTRINGEXACT, -1, (LPARAM)buf);
424  if(i == CB_ERR)
425  FIXME("Can't find default printer in printer list\n");
426  }
427  SendDlgItemMessageA(hDlg, id, CB_SETCURSEL, i, 0);
428  return num;
429 }
430 
432 {
433  DWORD needed, num;
434  INT i;
436  EnumPrintersW(PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &needed, &num);
437  pi = HeapAlloc(GetProcessHeap(), 0, needed);
438  EnumPrintersW(PRINTER_ENUM_LOCAL, NULL, 2, (LPBYTE)pi, needed, &needed,
439  &num);
440 
441  for(i = 0; i < num; i++) {
442  SendDlgItemMessageW(hDlg, id, CB_ADDSTRING, 0,
443  (LPARAM)pi[i].pPrinterName );
444  }
445  HeapFree(GetProcessHeap(), 0, pi);
446  if(!name ||
447  (i = SendDlgItemMessageW(hDlg, id, CB_FINDSTRINGEXACT, -1,
448  (LPARAM)name)) == CB_ERR) {
449  WCHAR buf[260];
450  DWORD dwBufLen = ARRAY_SIZE(buf);
451  if (name != NULL)
452  WARN("Can't find %s in printer list so trying to find default\n",
453  debugstr_w(name));
454  if(!GetDefaultPrinterW(buf, &dwBufLen))
455  return num;
456  i = SendDlgItemMessageW(hDlg, id, CB_FINDSTRINGEXACT, -1, (LPARAM)buf);
457  if(i == CB_ERR)
458  TRACE("Can't find default printer in printer list\n");
459  }
460  SendDlgItemMessageW(hDlg, id, CB_SETCURSEL, i, 0);
461  return num;
462 }
463 
464 /***********************************************************************
465  * PRINTDLG_CreateDevNames [internal]
466  *
467  *
468  * creates a DevNames structure.
469  *
470  * (NB. when we handle unicode the offsets will be in wchars).
471  */
472 static BOOL PRINTDLG_CreateDevNames(HGLOBAL *hmem, const char* DeviceDriverName,
473  const char* DeviceName, const char* OutputPort)
474 {
475  long size;
476  char* pDevNamesSpace;
477  char* pTempPtr;
478  LPDEVNAMES lpDevNames;
479  char buf[260];
480  DWORD dwBufLen = ARRAY_SIZE(buf);
481  const char *p;
482 
483  p = strrchr( DeviceDriverName, '\\' );
484  if (p) DeviceDriverName = p + 1;
485 
486  size = strlen(DeviceDriverName) + 1
487  + strlen(DeviceName) + 1
488  + strlen(OutputPort) + 1
489  + sizeof(DEVNAMES);
490 
491  if(*hmem)
492  *hmem = GlobalReAlloc(*hmem, size, GMEM_MOVEABLE);
493  else
494  *hmem = GlobalAlloc(GMEM_MOVEABLE, size);
495  if (*hmem == 0)
496  return FALSE;
497 
498  pDevNamesSpace = GlobalLock(*hmem);
499  lpDevNames = (LPDEVNAMES) pDevNamesSpace;
500 
501  pTempPtr = pDevNamesSpace + sizeof(DEVNAMES);
502  strcpy(pTempPtr, DeviceDriverName);
503  lpDevNames->wDriverOffset = pTempPtr - pDevNamesSpace;
504 
505  pTempPtr += strlen(DeviceDriverName) + 1;
506  strcpy(pTempPtr, DeviceName);
507  lpDevNames->wDeviceOffset = pTempPtr - pDevNamesSpace;
508 
509  pTempPtr += strlen(DeviceName) + 1;
510  strcpy(pTempPtr, OutputPort);
511  lpDevNames->wOutputOffset = pTempPtr - pDevNamesSpace;
512 
513  GetDefaultPrinterA(buf, &dwBufLen);
514  lpDevNames->wDefault = (strcmp(buf, DeviceName) == 0) ? 1 : 0;
515  GlobalUnlock(*hmem);
516  return TRUE;
517 }
518 
519 static BOOL PRINTDLG_CreateDevNamesW(HGLOBAL *hmem, LPCWSTR DeviceDriverName,
520  LPCWSTR DeviceName, LPCWSTR OutputPort)
521 {
522  long size;
523  LPWSTR pDevNamesSpace;
524  LPWSTR pTempPtr;
525  LPDEVNAMES lpDevNames;
526  WCHAR bufW[260];
527  DWORD dwBufLen = ARRAY_SIZE(bufW);
528  const WCHAR *p;
529 
530  p = strrchrW( DeviceDriverName, '\\' );
531  if (p) DeviceDriverName = p + 1;
532 
533  size = sizeof(WCHAR)*lstrlenW(DeviceDriverName) + 2
534  + sizeof(WCHAR)*lstrlenW(DeviceName) + 2
535  + sizeof(WCHAR)*lstrlenW(OutputPort) + 2
536  + sizeof(DEVNAMES);
537 
538  if(*hmem)
539  *hmem = GlobalReAlloc(*hmem, size, GMEM_MOVEABLE);
540  else
541  *hmem = GlobalAlloc(GMEM_MOVEABLE, size);
542  if (*hmem == 0)
543  return FALSE;
544 
545  pDevNamesSpace = GlobalLock(*hmem);
546  lpDevNames = (LPDEVNAMES) pDevNamesSpace;
547 
548  pTempPtr = (LPWSTR)((LPDEVNAMES)pDevNamesSpace + 1);
549  lstrcpyW(pTempPtr, DeviceDriverName);
550  lpDevNames->wDriverOffset = pTempPtr - pDevNamesSpace;
551 
552  pTempPtr += lstrlenW(DeviceDriverName) + 1;
553  lstrcpyW(pTempPtr, DeviceName);
554  lpDevNames->wDeviceOffset = pTempPtr - pDevNamesSpace;
555 
556  pTempPtr += lstrlenW(DeviceName) + 1;
557  lstrcpyW(pTempPtr, OutputPort);
558  lpDevNames->wOutputOffset = pTempPtr - pDevNamesSpace;
559 
560  GetDefaultPrinterW(bufW, &dwBufLen);
561  lpDevNames->wDefault = (lstrcmpW(bufW, DeviceName) == 0) ? 1 : 0;
562  GlobalUnlock(*hmem);
563  return TRUE;
564 }
565 
566 /***********************************************************************
567  * PRINTDLG_UpdatePrintDlg [internal]
568  *
569  *
570  * updates the PrintDlg structure for return values.
571  *
572  * RETURNS
573  * FALSE if user is not allowed to close (i.e. wrong nTo or nFrom values)
574  * TRUE if successful.
575  */
577  PRINT_PTRA* PrintStructures)
578 {
579  LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
580  PDEVMODEA lpdm = PrintStructures->lpDevMode;
581  LPPRINTER_INFO_2A pi = PrintStructures->lpPrinterInfo;
582 
583 
584  if(!lpdm) {
585  FIXME("No lpdm ptr?\n");
586  return FALSE;
587  }
588 
589 
590  if(!(lppd->Flags & PD_PRINTSETUP)) {
591  /* check whether nFromPage and nToPage are within range defined by
592  * nMinPage and nMaxPage
593  */
594  if (IsDlgButtonChecked(hDlg, rad3) == BST_CHECKED) { /* Pages */
595  WORD nToPage;
596  WORD nFromPage;
597  BOOL translated;
598  nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
599  nToPage = GetDlgItemInt(hDlg, edt2, &translated, FALSE);
600 
601  /* if no ToPage value is entered, use the FromPage value */
602  if(!translated) nToPage = nFromPage;
603 
604  if (nFromPage < lppd->nMinPage || nFromPage > lppd->nMaxPage ||
605  nToPage < lppd->nMinPage || nToPage > lppd->nMaxPage) {
606  WCHAR resourcestr[256];
607  WCHAR resultstr[256];
609  wsprintfW(resultstr,resourcestr, lppd->nMinPage, lppd->nMaxPage);
610  LoadStringW(COMDLG32_hInstance, PD32_PRINT_TITLE, resourcestr, 255);
611  MessageBoxW(hDlg, resultstr, resourcestr, MB_OK | MB_ICONWARNING);
612  return FALSE;
613  }
614  lppd->nFromPage = nFromPage;
615  lppd->nToPage = nToPage;
616  lppd->Flags |= PD_PAGENUMS;
617  }
618  else
619  lppd->Flags &= ~PD_PAGENUMS;
620 
621  if (IsDlgButtonChecked(hDlg, rad2) == BST_CHECKED) /* Selection */
622  lppd->Flags |= PD_SELECTION;
623  else
624  lppd->Flags &= ~PD_SELECTION;
625 
626  if (IsDlgButtonChecked(hDlg, chx1) == BST_CHECKED) {/* Print to file */
627  static char file[] = "FILE:";
628  lppd->Flags |= PD_PRINTTOFILE;
629  pi->pPortName = file;
630  }
631 
632  if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED) { /* Collate */
633  FIXME("Collate lppd not yet implemented as output\n");
634  }
635 
636  /* set PD_Collate and nCopies */
637  if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
638  /* The application doesn't support multiple copies or collate...
639  */
640  lppd->Flags &= ~PD_COLLATE;
641  lppd->nCopies = 1;
642  /* if the printer driver supports it... store info there
643  * otherwise no collate & multiple copies !
644  */
645  if (lpdm->dmFields & DM_COLLATE)
646  lpdm->dmCollate =
647  (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED);
648  if (lpdm->dmFields & DM_COPIES)
649  lpdm->u1.s1.dmCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
650  } else {
651  /* Application is responsible for multiple copies */
652  if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
653  lppd->Flags |= PD_COLLATE;
654  else
655  lppd->Flags &= ~PD_COLLATE;
656  lppd->nCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
657  /* multiple copies already included in the document. Driver must print only one copy */
658  lpdm->u1.s1.dmCopies = 1;
659  }
660 
661  /* Print quality, PrintDlg16 */
662  if(GetDlgItem(hDlg, cmb1))
663  {
664  HWND hQuality = GetDlgItem(hDlg, cmb1);
665  int Sel = SendMessageA(hQuality, CB_GETCURSEL, 0, 0);
666 
667  if(Sel != CB_ERR)
668  {
669  LONG dpi = SendMessageA(hQuality, CB_GETITEMDATA, Sel, 0);
671  lpdm->u1.s1.dmPrintQuality = LOWORD(dpi);
672  lpdm->dmYResolution = HIWORD(dpi);
673  }
674  }
675  }
676  return TRUE;
677 }
678 
680  PRINT_PTRW* PrintStructures)
681 {
682  LPPRINTDLGW lppd = PrintStructures->lpPrintDlg;
683  PDEVMODEW lpdm = PrintStructures->lpDevMode;
684  LPPRINTER_INFO_2W pi = PrintStructures->lpPrinterInfo;
685 
686 
687  if(!lpdm) {
688  FIXME("No lpdm ptr?\n");
689  return FALSE;
690  }
691 
692 
693  if(!(lppd->Flags & PD_PRINTSETUP)) {
694  /* check whether nFromPage and nToPage are within range defined by
695  * nMinPage and nMaxPage
696  */
697  if (IsDlgButtonChecked(hDlg, rad3) == BST_CHECKED) { /* Pages */
698  WORD nToPage;
699  WORD nFromPage;
700  BOOL translated;
701  nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
702  nToPage = GetDlgItemInt(hDlg, edt2, &translated, FALSE);
703 
704  /* if no ToPage value is entered, use the FromPage value */
705  if(!translated) nToPage = nFromPage;
706 
707  if (nFromPage < lppd->nMinPage || nFromPage > lppd->nMaxPage ||
708  nToPage < lppd->nMinPage || nToPage > lppd->nMaxPage) {
709  WCHAR resourcestr[256];
710  WCHAR resultstr[256];
711  DWORD_PTR args[2];
713  resourcestr, 255);
714  args[0] = lppd->nMinPage;
715  args[1] = lppd->nMaxPage;
717  resourcestr, 0, 0, resultstr,
718  ARRAY_SIZE(resultstr),
719  (__ms_va_list*)args);
721  resourcestr, 255);
722  MessageBoxW(hDlg, resultstr, resourcestr,
724  return FALSE;
725  }
726  lppd->nFromPage = nFromPage;
727  lppd->nToPage = nToPage;
728  lppd->Flags |= PD_PAGENUMS;
729  }
730  else
731  lppd->Flags &= ~PD_PAGENUMS;
732 
733  if (IsDlgButtonChecked(hDlg, rad2) == BST_CHECKED) /* Selection */
734  lppd->Flags |= PD_SELECTION;
735  else
736  lppd->Flags &= ~PD_SELECTION;
737 
738  if (IsDlgButtonChecked(hDlg, chx1) == BST_CHECKED) {/* Print to file */
739  static WCHAR file[] = {'F','I','L','E',':',0};
740  lppd->Flags |= PD_PRINTTOFILE;
741  pi->pPortName = file;
742  }
743 
744  if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED) { /* Collate */
745  FIXME("Collate lppd not yet implemented as output\n");
746  }
747 
748  /* set PD_Collate and nCopies */
749  if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
750  /* The application doesn't support multiple copies or collate...
751  */
752  lppd->Flags &= ~PD_COLLATE;
753  lppd->nCopies = 1;
754  /* if the printer driver supports it... store info there
755  * otherwise no collate & multiple copies !
756  */
757  if (lpdm->dmFields & DM_COLLATE)
758  lpdm->dmCollate =
759  (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED);
760  if (lpdm->dmFields & DM_COPIES)
761  lpdm->u1.s1.dmCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
762  } else {
763  if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
764  lppd->Flags |= PD_COLLATE;
765  else
766  lppd->Flags &= ~PD_COLLATE;
767  lppd->nCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
768  }
769  }
770  return TRUE;
771 }
772 
773 /************************************************************************
774  * PRINTDLG_SetUpPaperComboBox
775  *
776  * Initialize either the papersize or inputslot combos of the Printer Setup
777  * dialog. We store the associated word (eg DMPAPER_A4) as the item data.
778  * We also try to re-select the old selection.
779  */
781  int nIDComboBox,
782  char* PrinterName,
783  char* PortName,
784  LPDEVMODEA dm)
785 {
786  int i;
787  int NrOfEntries;
788  char* Names;
789  WORD* Words;
790  DWORD Sel, old_Sel;
791  WORD oldWord = 0, newWord = 0; /* DMPAPER_ and DMBIN_ start at 1 */
792  int NamesSize;
793  int fwCapability_Names;
794  int fwCapability_Words;
795 
796  TRACE(" Printer: %s, Port: %s, ComboID: %d\n",PrinterName,PortName,nIDComboBox);
797 
798  /* query the dialog box for the current selected value */
799  Sel = SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETCURSEL, 0, 0);
800  if(Sel != CB_ERR) {
801  /* we enter here only if a different printer is selected after
802  * the Print Setup dialog is opened. The current settings are
803  * stored into the newly selected printer.
804  */
805  oldWord = SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETITEMDATA,
806  Sel, 0);
807  if(oldWord >= DMPAPER_USER) /* DMPAPER_USER == DMBIN_USER */
808  oldWord = 0; /* There's no point in trying to keep custom
809  paper / bin sizes across printers */
810  }
811 
812  if (dm)
813  newWord = (nIDComboBox == cmb2) ? dm->u1.s1.dmPaperSize : dm->u1.s1.dmDefaultSource;
814 
815  if (nIDComboBox == cmb2) {
816  NamesSize = 64;
817  fwCapability_Names = DC_PAPERNAMES;
818  fwCapability_Words = DC_PAPERS;
819  } else {
820  nIDComboBox = cmb3;
821  NamesSize = 24;
822  fwCapability_Names = DC_BINNAMES;
823  fwCapability_Words = DC_BINS;
824  }
825 
826  NrOfEntries = DeviceCapabilitiesA(PrinterName, PortName,
827  fwCapability_Names, NULL, dm);
828  if (NrOfEntries == 0)
829  WARN("no Name Entries found!\n");
830  else if (NrOfEntries < 0)
831  return FALSE;
832 
833  if(DeviceCapabilitiesA(PrinterName, PortName, fwCapability_Words, NULL, dm)
834  != NrOfEntries) {
835  ERR("Number of caps is different\n");
836  NrOfEntries = 0;
837  }
838 
839  Names = HeapAlloc(GetProcessHeap(),0, NrOfEntries*sizeof(char)*NamesSize);
840  Words = HeapAlloc(GetProcessHeap(),0, NrOfEntries*sizeof(WORD));
841  DeviceCapabilitiesA(PrinterName, PortName, fwCapability_Names, Names, dm);
842  NrOfEntries = DeviceCapabilitiesA(PrinterName, PortName,
843  fwCapability_Words, (LPSTR)Words, dm);
844 
845  /* reset any current content in the combobox */
846  SendDlgItemMessageA(hDlg, nIDComboBox, CB_RESETCONTENT, 0, 0);
847 
848  /* store new content */
849  for (i = 0; i < NrOfEntries; i++) {
850  DWORD pos = SendDlgItemMessageA(hDlg, nIDComboBox, CB_ADDSTRING, 0,
851  (LPARAM)(&Names[i*NamesSize]) );
852  SendDlgItemMessageA(hDlg, nIDComboBox, CB_SETITEMDATA, pos,
853  Words[i]);
854  }
855 
856  /* Look for old selection or the new default.
857  Can't do this is previous loop since item order will change as more items are added */
858  Sel = 0;
859  old_Sel = NrOfEntries;
860  for (i = 0; i < NrOfEntries; i++) {
861  if(SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETITEMDATA, i, 0) ==
862  oldWord) {
863  old_Sel = i;
864  break;
865  }
866  if(SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETITEMDATA, i, 0) == newWord)
867  Sel = i;
868  }
869 
870  if(old_Sel < NrOfEntries)
871  {
872  if (dm)
873  {
874  if(nIDComboBox == cmb2)
875  dm->u1.s1.dmPaperSize = oldWord;
876  else
877  dm->u1.s1.dmDefaultSource = oldWord;
878  }
879  Sel = old_Sel;
880  }
881 
882  SendDlgItemMessageA(hDlg, nIDComboBox, CB_SETCURSEL, Sel, 0);
883 
884  HeapFree(GetProcessHeap(),0,Words);
885  HeapFree(GetProcessHeap(),0,Names);
886  return TRUE;
887 }
888 
890  int nIDComboBox,
891  const WCHAR* PrinterName,
892  const WCHAR* PortName,
893  LPDEVMODEW dm)
894 {
895  int i;
896  int NrOfEntries;
897  WCHAR* Names;
898  WORD* Words;
899  DWORD Sel, old_Sel;
900  WORD oldWord = 0, newWord = 0; /* DMPAPER_ and DMBIN_ start at 1 */
901  int NamesSize;
902  int fwCapability_Names;
903  int fwCapability_Words;
904 
905  TRACE(" Printer: %s, Port: %s, ComboID: %d\n",debugstr_w(PrinterName),debugstr_w(PortName),nIDComboBox);
906 
907  /* query the dialog box for the current selected value */
908  Sel = SendDlgItemMessageW(hDlg, nIDComboBox, CB_GETCURSEL, 0, 0);
909  if(Sel != CB_ERR) {
910  /* we enter here only if a different printer is selected after
911  * the Print Setup dialog is opened. The current settings are
912  * stored into the newly selected printer.
913  */
914  oldWord = SendDlgItemMessageW(hDlg, nIDComboBox, CB_GETITEMDATA,
915  Sel, 0);
916 
917  if(oldWord >= DMPAPER_USER) /* DMPAPER_USER == DMBIN_USER */
918  oldWord = 0; /* There's no point in trying to keep custom
919  paper / bin sizes across printers */
920  }
921 
922  if (dm)
923  newWord = (nIDComboBox == cmb2) ? dm->u1.s1.dmPaperSize : dm->u1.s1.dmDefaultSource;
924 
925  if (nIDComboBox == cmb2) {
926  NamesSize = 64;
927  fwCapability_Names = DC_PAPERNAMES;
928  fwCapability_Words = DC_PAPERS;
929  } else {
930  nIDComboBox = cmb3;
931  NamesSize = 24;
932  fwCapability_Names = DC_BINNAMES;
933  fwCapability_Words = DC_BINS;
934  }
935 
936  NrOfEntries = DeviceCapabilitiesW(PrinterName, PortName,
937  fwCapability_Names, NULL, dm);
938  if (NrOfEntries == 0)
939  WARN("no Name Entries found!\n");
940  else if (NrOfEntries < 0)
941  return FALSE;
942 
943  if(DeviceCapabilitiesW(PrinterName, PortName, fwCapability_Words, NULL, dm)
944  != NrOfEntries) {
945  ERR("Number of caps is different\n");
946  NrOfEntries = 0;
947  }
948 
949  Names = HeapAlloc(GetProcessHeap(),0, NrOfEntries*sizeof(WCHAR)*NamesSize);
950  Words = HeapAlloc(GetProcessHeap(),0, NrOfEntries*sizeof(WORD));
951  DeviceCapabilitiesW(PrinterName, PortName, fwCapability_Names, Names, dm);
952  NrOfEntries = DeviceCapabilitiesW(PrinterName, PortName,
953  fwCapability_Words, Words, dm);
954 
955  /* reset any current content in the combobox */
956  SendDlgItemMessageW(hDlg, nIDComboBox, CB_RESETCONTENT, 0, 0);
957 
958  /* store new content */
959  for (i = 0; i < NrOfEntries; i++) {
960  DWORD pos = SendDlgItemMessageW(hDlg, nIDComboBox, CB_ADDSTRING, 0,
961  (LPARAM)(&Names[i*NamesSize]) );
962  SendDlgItemMessageW(hDlg, nIDComboBox, CB_SETITEMDATA, pos,
963  Words[i]);
964  }
965 
966  /* Look for old selection or the new default.
967  Can't do this is previous loop since item order will change as more items are added */
968  Sel = 0;
969  old_Sel = NrOfEntries;
970  for (i = 0; i < NrOfEntries; i++) {
971  if(SendDlgItemMessageW(hDlg, nIDComboBox, CB_GETITEMDATA, i, 0) ==
972  oldWord) {
973  old_Sel = i;
974  break;
975  }
976  if(SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETITEMDATA, i, 0) == newWord)
977  Sel = i;
978  }
979 
980  if(old_Sel < NrOfEntries)
981  {
982  if (dm)
983  {
984  if(nIDComboBox == cmb2)
985  dm->u1.s1.dmPaperSize = oldWord;
986  else
987  dm->u1.s1.dmDefaultSource = oldWord;
988  }
989  Sel = old_Sel;
990  }
991 
992  SendDlgItemMessageW(hDlg, nIDComboBox, CB_SETCURSEL, Sel, 0);
993 
994  HeapFree(GetProcessHeap(),0,Words);
995  HeapFree(GetProcessHeap(),0,Names);
996  return TRUE;
997 }
998 
999 
1000 /***********************************************************************
1001  * PRINTDLG_UpdatePrinterInfoTexts [internal]
1002  */
1004 {
1005  char StatusMsg[256];
1006  char ResourceString[256];
1007  int i;
1008 
1009  /* Status Message */
1010  StatusMsg[0]='\0';
1011 
1012  /* add all status messages */
1013  for (i = 0; i < 25; i++) {
1014  if (pi->Status & (1<<i)) {
1016  ResourceString, 255);
1017  strcat(StatusMsg,ResourceString);
1018  }
1019  }
1020  /* append "ready" */
1021  /* FIXME: status==ready must only be appended if really so.
1022  but how to detect? */
1024  ResourceString, 255);
1025  strcat(StatusMsg,ResourceString);
1026  SetDlgItemTextA(hDlg, stc12, StatusMsg);
1027 
1028  /* set all other printer info texts */
1029  SetDlgItemTextA(hDlg, stc11, pi->pDriverName);
1030 
1031  if (pi->pLocation != NULL && pi->pLocation[0] != '\0')
1032  SetDlgItemTextA(hDlg, stc14, pi->pLocation);
1033  else
1034  SetDlgItemTextA(hDlg, stc14, pi->pPortName);
1035  SetDlgItemTextA(hDlg, stc13, pi->pComment ? pi->pComment : "");
1036  return;
1037 }
1038 
1040 {
1041  WCHAR StatusMsg[256];
1042  WCHAR ResourceString[256];
1043  static const WCHAR emptyW[] = {0};
1044  int i;
1045 
1046  /* Status Message */
1047  StatusMsg[0]='\0';
1048 
1049  /* add all status messages */
1050  for (i = 0; i < 25; i++) {
1051  if (pi->Status & (1<<i)) {
1053  ResourceString, 255);
1054  lstrcatW(StatusMsg,ResourceString);
1055  }
1056  }
1057  /* append "ready" */
1058  /* FIXME: status==ready must only be appended if really so.
1059  but how to detect? */
1061  ResourceString, 255);
1062  lstrcatW(StatusMsg,ResourceString);
1063  SetDlgItemTextW(hDlg, stc12, StatusMsg);
1064 
1065  /* set all other printer info texts */
1066  SetDlgItemTextW(hDlg, stc11, pi->pDriverName);
1067  if (pi->pLocation != NULL && pi->pLocation[0] != '\0')
1068  SetDlgItemTextW(hDlg, stc14, pi->pLocation);
1069  else
1070  SetDlgItemTextW(hDlg, stc14, pi->pPortName);
1071  SetDlgItemTextW(hDlg, stc13, pi->pComment ? pi->pComment : emptyW);
1072 }
1073 
1074 
1075 /*******************************************************************
1076  *
1077  * PRINTDLG_ChangePrinter
1078  *
1079  */
1080 static BOOL PRINTDLG_ChangePrinterA(HWND hDlg, char *name, PRINT_PTRA *PrintStructures)
1081 {
1082  LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
1083  LPDEVMODEA lpdm = NULL;
1084  LONG dmSize;
1085  DWORD needed;
1086  HANDLE hprn;
1087 
1088  HeapFree(GetProcessHeap(),0, PrintStructures->lpPrinterInfo);
1089  HeapFree(GetProcessHeap(),0, PrintStructures->lpDriverInfo);
1090  if(!OpenPrinterA(name, &hprn, NULL)) {
1091  ERR("Can't open printer %s\n", name);
1092  return FALSE;
1093  }
1094  GetPrinterA(hprn, 2, NULL, 0, &needed);
1095  PrintStructures->lpPrinterInfo = HeapAlloc(GetProcessHeap(),0,needed);
1096  GetPrinterA(hprn, 2, (LPBYTE)PrintStructures->lpPrinterInfo, needed,
1097  &needed);
1098  GetPrinterDriverA(hprn, NULL, 3, NULL, 0, &needed);
1099  PrintStructures->lpDriverInfo = HeapAlloc(GetProcessHeap(),0,needed);
1100  if (!GetPrinterDriverA(hprn, NULL, 3, (LPBYTE)PrintStructures->lpDriverInfo,
1101  needed, &needed)) {
1102  ERR("GetPrinterDriverA failed for %s, fix your config!\n",PrintStructures->lpPrinterInfo->pPrinterName);
1103  return FALSE;
1104  }
1105  ClosePrinter(hprn);
1106 
1107  PRINTDLG_UpdatePrinterInfoTextsA(hDlg, PrintStructures->lpPrinterInfo);
1108 
1109  HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
1110  PrintStructures->lpDevMode = NULL;
1111 
1112  dmSize = DocumentPropertiesA(0, 0, name, NULL, NULL, 0);
1113  if(dmSize == -1) {
1114  ERR("DocumentProperties fails on %s\n", debugstr_a(name));
1115  return FALSE;
1116  }
1117  PrintStructures->lpDevMode = HeapAlloc(GetProcessHeap(), 0, dmSize);
1118  dmSize = DocumentPropertiesA(0, 0, name, PrintStructures->lpDevMode, NULL,
1119  DM_OUT_BUFFER);
1120  if(lppd->hDevMode && (lpdm = GlobalLock(lppd->hDevMode)) &&
1121  !lstrcmpA( (LPSTR) lpdm->dmDeviceName,
1122  (LPSTR) PrintStructures->lpDevMode->dmDeviceName)) {
1123  /* Supplied devicemode matches current printer so try to use it */
1124  DocumentPropertiesA(0, 0, name, PrintStructures->lpDevMode, lpdm,
1126  }
1127  if(lpdm)
1128  GlobalUnlock(lppd->hDevMode);
1129 
1130  lpdm = PrintStructures->lpDevMode; /* use this as a shortcut */
1131 
1132  if(!(lppd->Flags & PD_PRINTSETUP)) {
1133  /* Print range (All/Range/Selection) */
1134  if(lppd->nFromPage != 0xffff)
1135  SetDlgItemInt(hDlg, edt1, lppd->nFromPage, FALSE);
1136  if(lppd->nToPage != 0xffff)
1137  SetDlgItemInt(hDlg, edt2, lppd->nToPage, FALSE);
1138 
1139  CheckRadioButton(hDlg, rad1, rad3, rad1); /* default */
1140  if (lppd->Flags & PD_NOSELECTION)
1141  EnableWindow(GetDlgItem(hDlg, rad2), FALSE);
1142  else
1143  if (lppd->Flags & PD_SELECTION)
1144  CheckRadioButton(hDlg, rad1, rad3, rad2);
1145  if (lppd->Flags & PD_NOPAGENUMS) {
1146  EnableWindow(GetDlgItem(hDlg, rad3), FALSE);
1148  EnableWindow(GetDlgItem(hDlg, edt1), FALSE);
1150  EnableWindow(GetDlgItem(hDlg, edt2), FALSE);
1151  } else {
1152  if (lppd->Flags & PD_PAGENUMS)
1153  CheckRadioButton(hDlg, rad1, rad3, rad3);
1154  }
1155 
1156  /* Collate pages
1157  *
1158  * FIXME: The ico3 is not displayed for some reason. I don't know why.
1159  */
1160  if (lppd->Flags & PD_COLLATE) {
1162  (LPARAM)PrintStructures->hCollateIcon);
1163  CheckDlgButton(hDlg, chx2, 1);
1164  } else {
1166  (LPARAM)PrintStructures->hNoCollateIcon);
1167  CheckDlgButton(hDlg, chx2, 0);
1168  }
1169 
1170  if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
1171  /* if printer doesn't support it: no Collate */
1172  if (!(lpdm->dmFields & DM_COLLATE)) {
1173  EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
1174  EnableWindow(GetDlgItem(hDlg, ico3), FALSE);
1175  }
1176  }
1177 
1178  /* nCopies */
1179  {
1180  INT copies;
1181  if (lppd->hDevMode == 0)
1182  copies = lppd->nCopies;
1183  else
1184  copies = lpdm->u1.s1.dmCopies;
1185  if(copies == 0) copies = 1;
1186  else if(copies < 0) copies = MAX_COPIES;
1187  SetDlgItemInt(hDlg, edt3, copies, FALSE);
1188  }
1189 
1190  if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
1191  /* if printer doesn't support it: no nCopies */
1192  if (!(lpdm->dmFields & DM_COPIES)) {
1193  EnableWindow(GetDlgItem(hDlg, edt3), FALSE);
1194  EnableWindow(GetDlgItem(hDlg, stc5), FALSE);
1195  }
1196  }
1197 
1198  /* print to file */
1199  CheckDlgButton(hDlg, chx1, (lppd->Flags & PD_PRINTTOFILE) ? 1 : 0);
1200  if (lppd->Flags & PD_DISABLEPRINTTOFILE)
1201  EnableWindow(GetDlgItem(hDlg, chx1), FALSE);
1202  if (lppd->Flags & PD_HIDEPRINTTOFILE)
1203  ShowWindow(GetDlgItem(hDlg, chx1), SW_HIDE);
1204 
1205  /* Fill print quality combo, PrintDlg16 */
1206  if(GetDlgItem(hDlg, cmb1))
1207  {
1208  DWORD numResolutions = DeviceCapabilitiesA(PrintStructures->lpPrinterInfo->pPrinterName,
1209  PrintStructures->lpPrinterInfo->pPortName,
1210  DC_ENUMRESOLUTIONS, NULL, lpdm);
1211 
1212  if(numResolutions != -1)
1213  {
1214  HWND hQuality = GetDlgItem(hDlg, cmb1);
1215  LONG* Resolutions;
1216  char buf[255];
1217  DWORD i;
1218  int dpiX, dpiY;
1219  HDC hPrinterDC = CreateDCA(PrintStructures->lpPrinterInfo->pDriverName,
1220  PrintStructures->lpPrinterInfo->pPrinterName,
1221  0, lpdm);
1222 
1223  Resolutions = HeapAlloc(GetProcessHeap(), 0, numResolutions*sizeof(LONG)*2);
1225  PrintStructures->lpPrinterInfo->pPortName,
1226  DC_ENUMRESOLUTIONS, (LPSTR)Resolutions, lpdm);
1227 
1228  dpiX = GetDeviceCaps(hPrinterDC, LOGPIXELSX);
1229  dpiY = GetDeviceCaps(hPrinterDC, LOGPIXELSY);
1230  DeleteDC(hPrinterDC);
1231 
1232  SendMessageA(hQuality, CB_RESETCONTENT, 0, 0);
1233  for(i = 0; i < (numResolutions * 2); i += 2)
1234  {
1235  BOOL IsDefault = FALSE;
1236  LRESULT Index;
1237 
1238  if(Resolutions[i] == Resolutions[i+1])
1239  {
1240  if(dpiX == Resolutions[i])
1241  IsDefault = TRUE;
1242  sprintf(buf, "%d dpi", Resolutions[i]);
1243  } else
1244  {
1245  if(dpiX == Resolutions[i] && dpiY == Resolutions[i+1])
1246  IsDefault = TRUE;
1247  sprintf(buf, "%d dpi x %d dpi", Resolutions[i], Resolutions[i+1]);
1248  }
1249 
1250  Index = SendMessageA(hQuality, CB_ADDSTRING, 0, (LPARAM)buf);
1251 
1252  if(IsDefault)
1253  SendMessageA(hQuality, CB_SETCURSEL, Index, 0);
1254 
1255  SendMessageA(hQuality, CB_SETITEMDATA, Index, MAKELONG(dpiX,dpiY));
1256  }
1257  HeapFree(GetProcessHeap(), 0, Resolutions);
1258  }
1259  }
1260  } else { /* PD_PRINTSETUP */
1261  BOOL bPortrait = (lpdm->u1.s1.dmOrientation == DMORIENT_PORTRAIT);
1262 
1264  PrintStructures->lpPrinterInfo->pPrinterName,
1265  PrintStructures->lpPrinterInfo->pPortName,
1266  lpdm);
1268  PrintStructures->lpPrinterInfo->pPrinterName,
1269  PrintStructures->lpPrinterInfo->pPortName,
1270  lpdm);
1271  CheckRadioButton(hDlg, rad1, rad2, bPortrait ? rad1: rad2);
1273  (LPARAM)(bPortrait ? PrintStructures->hPortraitIcon :
1274  PrintStructures->hLandscapeIcon));
1275 
1276  }
1277 
1278  /* help button */
1279  if ((lppd->Flags & PD_SHOWHELP)==0) {
1280  /* hide if PD_SHOWHELP not specified */
1282  }
1283  return TRUE;
1284 }
1285 
1287  PRINT_PTRW *PrintStructures)
1288 {
1289  LPPRINTDLGW lppd = PrintStructures->lpPrintDlg;
1290  LPDEVMODEW lpdm = NULL;
1291  LONG dmSize;
1292  DWORD needed;
1293  HANDLE hprn;
1294 
1295  HeapFree(GetProcessHeap(),0, PrintStructures->lpPrinterInfo);
1296  HeapFree(GetProcessHeap(),0, PrintStructures->lpDriverInfo);
1297  if(!OpenPrinterW(name, &hprn, NULL)) {
1298  ERR("Can't open printer %s\n", debugstr_w(name));
1299  return FALSE;
1300  }
1301  GetPrinterW(hprn, 2, NULL, 0, &needed);
1302  PrintStructures->lpPrinterInfo = HeapAlloc(GetProcessHeap(),0,needed);
1303  GetPrinterW(hprn, 2, (LPBYTE)PrintStructures->lpPrinterInfo, needed,
1304  &needed);
1305  GetPrinterDriverW(hprn, NULL, 3, NULL, 0, &needed);
1306  PrintStructures->lpDriverInfo = HeapAlloc(GetProcessHeap(),0,needed);
1307  if (!GetPrinterDriverW(hprn, NULL, 3, (LPBYTE)PrintStructures->lpDriverInfo,
1308  needed, &needed)) {
1309  ERR("GetPrinterDriverA failed for %s, fix your config!\n",debugstr_w(PrintStructures->lpPrinterInfo->pPrinterName));
1310  return FALSE;
1311  }
1312  ClosePrinter(hprn);
1313 
1314  PRINTDLG_UpdatePrinterInfoTextsW(hDlg, PrintStructures->lpPrinterInfo);
1315 
1316  HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
1317  PrintStructures->lpDevMode = NULL;
1318 
1319  dmSize = DocumentPropertiesW(0, 0, name, NULL, NULL, 0);
1320  if(dmSize == -1) {
1321  ERR("DocumentProperties fails on %s\n", debugstr_w(name));
1322  return FALSE;
1323  }
1324  PrintStructures->lpDevMode = HeapAlloc(GetProcessHeap(), 0, dmSize);
1325  dmSize = DocumentPropertiesW(0, 0, name, PrintStructures->lpDevMode, NULL,
1326  DM_OUT_BUFFER);
1327  if(lppd->hDevMode && (lpdm = GlobalLock(lppd->hDevMode)) &&
1328  !lstrcmpW(lpdm->dmDeviceName,
1329  PrintStructures->lpDevMode->dmDeviceName)) {
1330  /* Supplied devicemode matches current printer so try to use it */
1331  DocumentPropertiesW(0, 0, name, PrintStructures->lpDevMode, lpdm,
1333  }
1334  if(lpdm)
1335  GlobalUnlock(lppd->hDevMode);
1336 
1337  lpdm = PrintStructures->lpDevMode; /* use this as a shortcut */
1338 
1339  if(!(lppd->Flags & PD_PRINTSETUP)) {
1340  /* Print range (All/Range/Selection) */
1341  if(lppd->nFromPage != 0xffff)
1342  SetDlgItemInt(hDlg, edt1, lppd->nFromPage, FALSE);
1343  if(lppd->nToPage != 0xffff)
1344  SetDlgItemInt(hDlg, edt2, lppd->nToPage, FALSE);
1345 
1346  CheckRadioButton(hDlg, rad1, rad3, rad1); /* default */
1347  if (lppd->Flags & PD_NOSELECTION)
1348  EnableWindow(GetDlgItem(hDlg, rad2), FALSE);
1349  else
1350  if (lppd->Flags & PD_SELECTION)
1351  CheckRadioButton(hDlg, rad1, rad3, rad2);
1352  if (lppd->Flags & PD_NOPAGENUMS) {
1353  EnableWindow(GetDlgItem(hDlg, rad3), FALSE);
1355  EnableWindow(GetDlgItem(hDlg, edt1), FALSE);
1357  EnableWindow(GetDlgItem(hDlg, edt2), FALSE);
1358  } else {
1359  if (lppd->Flags & PD_PAGENUMS)
1360  CheckRadioButton(hDlg, rad1, rad3, rad3);
1361  }
1362 
1363  /* Collate pages
1364  *
1365  * FIXME: The ico3 is not displayed for some reason. I don't know why.
1366  */
1367  if (lppd->Flags & PD_COLLATE) {
1369  (LPARAM)PrintStructures->hCollateIcon);
1370  CheckDlgButton(hDlg, chx2, 1);
1371  } else {
1373  (LPARAM)PrintStructures->hNoCollateIcon);
1374  CheckDlgButton(hDlg, chx2, 0);
1375  }
1376 
1377  if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
1378  /* if printer doesn't support it: no Collate */
1379  if (!(lpdm->dmFields & DM_COLLATE)) {
1380  EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
1381  EnableWindow(GetDlgItem(hDlg, ico3), FALSE);
1382  }
1383  }
1384 
1385  /* nCopies */
1386  {
1387  INT copies;
1388  if (lppd->hDevMode == 0)
1389  copies = lppd->nCopies;
1390  else
1391  copies = lpdm->u1.s1.dmCopies;
1392  if(copies == 0) copies = 1;
1393  else if(copies < 0) copies = MAX_COPIES;
1394  SetDlgItemInt(hDlg, edt3, copies, FALSE);
1395  }
1396 
1397  if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
1398  /* if printer doesn't support it: no nCopies */
1399  if (!(lpdm->dmFields & DM_COPIES)) {
1400  EnableWindow(GetDlgItem(hDlg, edt3), FALSE);
1401  EnableWindow(GetDlgItem(hDlg, stc5), FALSE);
1402  }
1403  }
1404 
1405  /* print to file */
1406  CheckDlgButton(hDlg, chx1, (lppd->Flags & PD_PRINTTOFILE) ? 1 : 0);
1407  if (lppd->Flags & PD_DISABLEPRINTTOFILE)
1408  EnableWindow(GetDlgItem(hDlg, chx1), FALSE);
1409  if (lppd->Flags & PD_HIDEPRINTTOFILE)
1410  ShowWindow(GetDlgItem(hDlg, chx1), SW_HIDE);
1411 
1412  } else { /* PD_PRINTSETUP */
1413  BOOL bPortrait = (lpdm->u1.s1.dmOrientation == DMORIENT_PORTRAIT);
1414 
1416  PrintStructures->lpPrinterInfo->pPrinterName,
1417  PrintStructures->lpPrinterInfo->pPortName,
1418  lpdm);
1420  PrintStructures->lpPrinterInfo->pPrinterName,
1421  PrintStructures->lpPrinterInfo->pPortName,
1422  lpdm);
1423  CheckRadioButton(hDlg, rad1, rad2, bPortrait ? rad1: rad2);
1425  (LPARAM)(bPortrait ? PrintStructures->hPortraitIcon :
1426  PrintStructures->hLandscapeIcon));
1427 
1428  }
1429 
1430  /* help button */
1431  if ((lppd->Flags & PD_SHOWHELP)==0) {
1432  /* hide if PD_SHOWHELP not specified */
1434  }
1435  return TRUE;
1436 }
1437 
1438  /***********************************************************************
1439  * check_printer_setup [internal]
1440  */
1442 {
1443  DWORD needed,num;
1444  WCHAR resourcestr[256],resultstr[256];
1445 
1446  EnumPrintersW(PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &needed, &num);
1447  if(needed == 0)
1448  {
1449  EnumPrintersW(PRINTER_ENUM_CONNECTIONS, NULL, 2, NULL, 0, &needed, &num);
1450  }
1451  if(needed > 0)
1452  return TRUE;
1453  else
1454  {
1456  LoadStringW(COMDLG32_hInstance, PD32_PRINT_TITLE,resourcestr, 255);
1457  MessageBoxW(hDlg, resultstr, resourcestr,MB_OK | MB_ICONWARNING);
1458  return FALSE;
1459  }
1460 }
1461 
1462 /***********************************************************************
1463  * PRINTDLG_WMInitDialog [internal]
1464  */
1466  PRINT_PTRA* PrintStructures)
1467 {
1468  LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
1469  DEVNAMES *pdn;
1470  DEVMODEA *pdm;
1471  char *name = NULL;
1472  UINT comboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
1473 
1474  /* load Collate ICONs */
1475  /* We load these with LoadImage because they are not a standard
1476  size and we don't want them rescaled */
1477  PrintStructures->hCollateIcon =
1478  LoadImageA(COMDLG32_hInstance, "PD32_COLLATE", IMAGE_ICON, 0, 0, 0);
1479  PrintStructures->hNoCollateIcon =
1480  LoadImageA(COMDLG32_hInstance, "PD32_NOCOLLATE", IMAGE_ICON, 0, 0, 0);
1481 
1482  /* These can be done with LoadIcon */
1483  PrintStructures->hPortraitIcon =
1484  LoadIconA(COMDLG32_hInstance, "PD32_PORTRAIT");
1485  PrintStructures->hLandscapeIcon =
1486  LoadIconA(COMDLG32_hInstance, "PD32_LANDSCAPE");
1487 
1488  /* display the collate/no_collate icon */
1490  (LPARAM)PrintStructures->hNoCollateIcon);
1491 
1492  if(PrintStructures->hCollateIcon == 0 ||
1493  PrintStructures->hNoCollateIcon == 0 ||
1494  PrintStructures->hPortraitIcon == 0 ||
1495  PrintStructures->hLandscapeIcon == 0) {
1496  ERR("no icon in resource file\n");
1498  EndDialog(hDlg, FALSE);
1499  }
1500 
1501  /*
1502  * if lppd->Flags PD_SHOWHELP is specified, a HELPMESGSTRING message
1503  * must be registered and the Help button must be shown.
1504  */
1505  if (lppd->Flags & PD_SHOWHELP) {
1506  if((PrintStructures->HelpMessageID =
1509  return FALSE;
1510  }
1511  } else
1512  PrintStructures->HelpMessageID = 0;
1513 
1514  if(!(lppd->Flags &PD_PRINTSETUP)) {
1515  PrintStructures->hwndUpDown =
1518  UDS_ALIGNRIGHT | UDS_SETBUDDYINT, 0, 0, 0, 0,
1520  GetDlgItem(hDlg, edt3), MAX_COPIES, 1, 1);
1521  }
1522 
1523  /* FIXME: I allow more freedom than either Win95 or WinNT,
1524  * which do not agree on what errors should be thrown or not
1525  * in case nToPage or nFromPage is out-of-range.
1526  */
1527  if (lppd->nMaxPage < lppd->nMinPage)
1528  lppd->nMaxPage = lppd->nMinPage;
1529  if (lppd->nMinPage == lppd->nMaxPage)
1530  lppd->Flags |= PD_NOPAGENUMS;
1531  if (lppd->nToPage < lppd->nMinPage)
1532  lppd->nToPage = lppd->nMinPage;
1533  if (lppd->nToPage > lppd->nMaxPage)
1534  lppd->nToPage = lppd->nMaxPage;
1535  if (lppd->nFromPage < lppd->nMinPage)
1536  lppd->nFromPage = lppd->nMinPage;
1537  if (lppd->nFromPage > lppd->nMaxPage)
1538  lppd->nFromPage = lppd->nMaxPage;
1539 
1540  /* if we have the combo box, fill it */
1541  if (GetDlgItem(hDlg,comboID)) {
1542  /* Fill Combobox
1543  */
1544  pdn = GlobalLock(lppd->hDevNames);
1545  pdm = GlobalLock(lppd->hDevMode);
1546  if(pdn)
1547  name = (char*)pdn + pdn->wDeviceOffset;
1548  else if(pdm)
1549  name = (char*)pdm->dmDeviceName;
1550  PRINTDLG_SetUpPrinterListComboA(hDlg, comboID, name);
1551  if(pdm) GlobalUnlock(lppd->hDevMode);
1552  if(pdn) GlobalUnlock(lppd->hDevNames);
1553 
1554  /* Now find selected printer and update rest of dlg */
1555  name = HeapAlloc(GetProcessHeap(),0,256);
1556  if (GetDlgItemTextA(hDlg, comboID, name, 255))
1557  PRINTDLG_ChangePrinterA(hDlg, name, PrintStructures);
1558  HeapFree(GetProcessHeap(),0,name);
1559  } else {
1560  /* else use default printer */
1561  char name[200];
1562  DWORD dwBufLen = ARRAY_SIZE(name);
1563  BOOL ret = GetDefaultPrinterA(name, &dwBufLen);
1564 
1565  if (ret)
1566  PRINTDLG_ChangePrinterA(hDlg, name, PrintStructures);
1567  else
1568  FIXME("No default printer found, expect problems!\n");
1569  }
1570  return TRUE;
1571 }
1572 
1574  PRINT_PTRW* PrintStructures)
1575 {
1576  LPPRINTDLGW lppd = PrintStructures->lpPrintDlg;
1577  DEVNAMES *pdn;
1578  DEVMODEW *pdm;
1579  WCHAR *name = NULL;
1580  UINT comboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
1581 
1582  /* load Collate ICONs */
1583  /* We load these with LoadImage because they are not a standard
1584  size and we don't want them rescaled */
1585  PrintStructures->hCollateIcon =
1587  PrintStructures->hNoCollateIcon =
1589 
1590  /* These can be done with LoadIcon */
1591  PrintStructures->hPortraitIcon =
1593  PrintStructures->hLandscapeIcon =
1595 
1596  /* display the collate/no_collate icon */
1598  (LPARAM)PrintStructures->hNoCollateIcon);
1599 
1600  if(PrintStructures->hCollateIcon == 0 ||
1601  PrintStructures->hNoCollateIcon == 0 ||
1602  PrintStructures->hPortraitIcon == 0 ||
1603  PrintStructures->hLandscapeIcon == 0) {
1604  ERR("no icon in resource file\n");
1606  EndDialog(hDlg, FALSE);
1607  }
1608 
1609  /*
1610  * if lppd->Flags PD_SHOWHELP is specified, a HELPMESGSTRING message
1611  * must be registered and the Help button must be shown.
1612  */
1613  if (lppd->Flags & PD_SHOWHELP) {
1614  if((PrintStructures->HelpMessageID =
1617  return FALSE;
1618  }
1619  } else
1620  PrintStructures->HelpMessageID = 0;
1621 
1622  if(!(lppd->Flags &PD_PRINTSETUP)) {
1623  PrintStructures->hwndUpDown =
1626  UDS_ALIGNRIGHT | UDS_SETBUDDYINT, 0, 0, 0, 0,
1628  GetDlgItem(hDlg, edt3), MAX_COPIES, 1, 1);
1629  }
1630 
1631  /* FIXME: I allow more freedom than either Win95 or WinNT,
1632  * which do not agree to what errors should be thrown or not
1633  * in case nToPage or nFromPage is out-of-range.
1634  */
1635  if (lppd->nMaxPage < lppd->nMinPage)
1636  lppd->nMaxPage = lppd->nMinPage;
1637  if (lppd->nMinPage == lppd->nMaxPage)
1638  lppd->Flags |= PD_NOPAGENUMS;
1639  if (lppd->nToPage < lppd->nMinPage)
1640  lppd->nToPage = lppd->nMinPage;
1641  if (lppd->nToPage > lppd->nMaxPage)
1642  lppd->nToPage = lppd->nMaxPage;
1643  if (lppd->nFromPage < lppd->nMinPage)
1644  lppd->nFromPage = lppd->nMinPage;
1645  if (lppd->nFromPage > lppd->nMaxPage)
1646  lppd->nFromPage = lppd->nMaxPage;
1647 
1648  /* if we have the combo box, fill it */
1649  if (GetDlgItem(hDlg,comboID)) {
1650  /* Fill Combobox
1651  */
1652  pdn = GlobalLock(lppd->hDevNames);
1653  pdm = GlobalLock(lppd->hDevMode);
1654  if(pdn)
1655  name = (WCHAR*)pdn + pdn->wDeviceOffset;
1656  else if(pdm)
1657  name = pdm->dmDeviceName;
1658  PRINTDLG_SetUpPrinterListComboW(hDlg, comboID, name);
1659  if(pdm) GlobalUnlock(lppd->hDevMode);
1660  if(pdn) GlobalUnlock(lppd->hDevNames);
1661 
1662  /* Now find selected printer and update rest of dlg */
1663  /* ansi is ok here */
1664  name = HeapAlloc(GetProcessHeap(),0,256*sizeof(WCHAR));
1665  if (GetDlgItemTextW(hDlg, comboID, name, 255))
1666  PRINTDLG_ChangePrinterW(hDlg, name, PrintStructures);
1667  HeapFree(GetProcessHeap(),0,name);
1668  } else {
1669  /* else use default printer */
1670  WCHAR name[200];
1671  DWORD dwBufLen = ARRAY_SIZE(name);
1672  BOOL ret = GetDefaultPrinterW(name, &dwBufLen);
1673 
1674  if (ret)
1675  PRINTDLG_ChangePrinterW(hDlg, name, PrintStructures);
1676  else
1677  FIXME("No default printer found, expect problems!\n");
1678  }
1679  return TRUE;
1680 }
1681 
1682 /***********************************************************************
1683  * PRINTDLG_WMCommand [internal]
1684  */
1686  PRINT_PTRA* PrintStructures)
1687 {
1688  LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
1689  UINT PrinterComboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
1690  LPDEVMODEA lpdm = PrintStructures->lpDevMode;
1691 
1692  switch (LOWORD(wParam)) {
1693  case IDOK:
1694  TRACE(" OK button was hit\n");
1695  if (!PRINTDLG_UpdatePrintDlgA(hDlg, PrintStructures)) {
1696  FIXME("Update printdlg was not successful!\n");
1697  return(FALSE);
1698  }
1699  EndDialog(hDlg, TRUE);
1700  return(TRUE);
1701 
1702  case IDCANCEL:
1703  TRACE(" CANCEL button was hit\n");
1704  EndDialog(hDlg, FALSE);
1705  return(FALSE);
1706 
1707  case pshHelp:
1708  TRACE(" HELP button was hit\n");
1709  SendMessageA(lppd->hwndOwner, PrintStructures->HelpMessageID,
1710  (WPARAM) hDlg, (LPARAM) lppd);
1711  break;
1712 
1713  case chx2: /* collate pages checkbox */
1714  if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
1716  (LPARAM)PrintStructures->hCollateIcon);
1717  else
1719  (LPARAM)PrintStructures->hNoCollateIcon);
1720  break;
1721  case edt1: /* from page nr editbox */
1722  case edt2: /* to page nr editbox */
1723  if (HIWORD(wParam)==EN_CHANGE) {
1724  WORD nToPage;
1725  WORD nFromPage;
1726  nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
1727  nToPage = GetDlgItemInt(hDlg, edt2, NULL, FALSE);
1728  if (nFromPage != lppd->nFromPage || nToPage != lppd->nToPage)
1729  CheckRadioButton(hDlg, rad1, rad3, rad3);
1730  }
1731  break;
1732 
1733  case edt3:
1734  if(HIWORD(wParam) == EN_CHANGE) {
1735  INT copies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
1736  if(copies <= 1)
1737  EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
1738  else
1739  EnableWindow(GetDlgItem(hDlg, chx2), TRUE);
1740  }
1741  break;
1742 
1743  case psh2: /* Properties button */
1744  {
1745  HANDLE hPrinter;
1746  char PrinterName[256];
1747 
1748  GetDlgItemTextA(hDlg, PrinterComboID, PrinterName, 255);
1749  if (!OpenPrinterA(PrinterName, &hPrinter, NULL)) {
1750  FIXME(" Call to OpenPrinter did not succeed!\n");
1751  break;
1752  }
1753  DocumentPropertiesA(hDlg, hPrinter, PrinterName,
1754  PrintStructures->lpDevMode,
1755  PrintStructures->lpDevMode,
1757  ClosePrinter(hPrinter);
1758  break;
1759  }
1760 
1761  case rad1: /* Paperorientation */
1762  if (lppd->Flags & PD_PRINTSETUP)
1763  {
1764  lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
1766  (LPARAM)(PrintStructures->hPortraitIcon));
1767  }
1768  break;
1769 
1770  case rad2: /* Paperorientation */
1771  if (lppd->Flags & PD_PRINTSETUP)
1772  {
1773  lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
1775  (LPARAM)(PrintStructures->hLandscapeIcon));
1776  }
1777  break;
1778 
1779  case cmb1: /* Printer Combobox in PRINT SETUP, quality combobox in PRINT16 */
1780  if (PrinterComboID != LOWORD(wParam)) {
1781  break;
1782  }
1783  /* FALLTHROUGH */
1784  case cmb4: /* Printer combobox */
1785  if (HIWORD(wParam)==CBN_SELCHANGE) {
1786  char *PrinterName;
1787  INT index = SendDlgItemMessageW(hDlg, LOWORD(wParam), CB_GETCURSEL, 0, 0);
1788  INT length = SendDlgItemMessageW(hDlg, LOWORD(wParam), CB_GETLBTEXTLEN, index, 0);
1789  PrinterName = HeapAlloc(GetProcessHeap(),0,length+1);
1790  SendDlgItemMessageA(hDlg, LOWORD(wParam), CB_GETLBTEXT, index, (LPARAM)PrinterName);
1791  PRINTDLG_ChangePrinterA(hDlg, PrinterName, PrintStructures);
1792  HeapFree(GetProcessHeap(),0,PrinterName);
1793  }
1794  break;
1795 
1796  case cmb2: /* Papersize */
1797  {
1798  DWORD Sel = SendDlgItemMessageA(hDlg, cmb2, CB_GETCURSEL, 0, 0);
1799  if(Sel != CB_ERR) {
1800  lpdm->u1.s1.dmPaperSize = SendDlgItemMessageA(hDlg, cmb2,
1802  Sel, 0);
1803  GetDlgItemTextA(hDlg, cmb2, (char *)lpdm->dmFormName, CCHFORMNAME);
1804  }
1805  }
1806  break;
1807 
1808  case cmb3: /* Bin */
1809  {
1810  DWORD Sel = SendDlgItemMessageA(hDlg, cmb3, CB_GETCURSEL, 0, 0);
1811  if(Sel != CB_ERR)
1812  lpdm->u1.s1.dmDefaultSource = SendDlgItemMessageA(hDlg, cmb3,
1813  CB_GETITEMDATA, Sel,
1814  0);
1815  }
1816  break;
1817  }
1818  if(lppd->Flags & PD_PRINTSETUP) {
1819  switch (LOWORD(wParam)) {
1820  case rad1: /* orientation */
1821  case rad2:
1822  if (IsDlgButtonChecked(hDlg, rad1) == BST_CHECKED) {
1823  if(lpdm->u1.s1.dmOrientation != DMORIENT_PORTRAIT) {
1824  lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
1826  (LPARAM)PrintStructures->hPortraitIcon);
1828  (LPARAM)PrintStructures->hPortraitIcon);
1829  }
1830  } else {
1831  if(lpdm->u1.s1.dmOrientation != DMORIENT_LANDSCAPE) {
1832  lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
1834  (LPARAM)PrintStructures->hLandscapeIcon);
1836  (LPARAM)PrintStructures->hLandscapeIcon);
1837  }
1838  }
1839  break;
1840  }
1841  }
1842  return FALSE;
1843 }
1844 
1846  PRINT_PTRW* PrintStructures)
1847 {
1848  LPPRINTDLGW lppd = PrintStructures->lpPrintDlg;
1849  UINT PrinterComboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
1850  LPDEVMODEW lpdm = PrintStructures->lpDevMode;
1851 
1852  switch (LOWORD(wParam)) {
1853  case IDOK:
1854  TRACE(" OK button was hit\n");
1855  if (!PRINTDLG_UpdatePrintDlgW(hDlg, PrintStructures)) {
1856  FIXME("Update printdlg was not successful!\n");
1857  return(FALSE);
1858  }
1859  EndDialog(hDlg, TRUE);
1860  return(TRUE);
1861 
1862  case IDCANCEL:
1863  TRACE(" CANCEL button was hit\n");
1864  EndDialog(hDlg, FALSE);
1865  return(FALSE);
1866 
1867  case pshHelp:
1868  TRACE(" HELP button was hit\n");
1869  SendMessageW(lppd->hwndOwner, PrintStructures->HelpMessageID,
1870  (WPARAM) hDlg, (LPARAM) lppd);
1871  break;
1872 
1873  case chx2: /* collate pages checkbox */
1874  if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
1876  (LPARAM)PrintStructures->hCollateIcon);
1877  else
1879  (LPARAM)PrintStructures->hNoCollateIcon);
1880  break;
1881  case edt1: /* from page nr editbox */
1882  case edt2: /* to page nr editbox */
1883  if (HIWORD(wParam)==EN_CHANGE) {
1884  WORD nToPage;
1885  WORD nFromPage;
1886  nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
1887  nToPage = GetDlgItemInt(hDlg, edt2, NULL, FALSE);
1888  if (nFromPage != lppd->nFromPage || nToPage != lppd->nToPage)
1889  CheckRadioButton(hDlg, rad1, rad3, rad3);
1890  }
1891  break;
1892 
1893  case edt3:
1894  if(HIWORD(wParam) == EN_CHANGE) {
1895  INT copies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
1896  if(copies <= 1)
1897  EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
1898  else
1899  EnableWindow(GetDlgItem(hDlg, chx2), TRUE);
1900  }
1901  break;
1902 
1903  case psh2: /* Properties button */
1904  {
1905  HANDLE hPrinter;
1906  WCHAR PrinterName[256];
1907 
1908  if (!GetDlgItemTextW(hDlg, PrinterComboID, PrinterName, 255)) break;
1909  if (!OpenPrinterW(PrinterName, &hPrinter, NULL)) {
1910  FIXME(" Call to OpenPrinter did not succeed!\n");
1911  break;
1912  }
1913  DocumentPropertiesW(hDlg, hPrinter, PrinterName,
1914  PrintStructures->lpDevMode,
1915  PrintStructures->lpDevMode,
1917  ClosePrinter(hPrinter);
1918  break;
1919  }
1920 
1921  case rad1: /* Paperorientation */
1922  if (lppd->Flags & PD_PRINTSETUP)
1923  {
1924  lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
1926  (LPARAM)(PrintStructures->hPortraitIcon));
1927  }
1928  break;
1929 
1930  case rad2: /* Paperorientation */
1931  if (lppd->Flags & PD_PRINTSETUP)
1932  {
1933  lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
1935  (LPARAM)(PrintStructures->hLandscapeIcon));
1936  }
1937  break;
1938 
1939  case cmb1: /* Printer Combobox in PRINT SETUP */
1940  /* FALLTHROUGH */
1941  case cmb4: /* Printer combobox */
1942  if (HIWORD(wParam)==CBN_SELCHANGE) {
1943  WCHAR *PrinterName;
1944  INT index = SendDlgItemMessageW(hDlg, LOWORD(wParam), CB_GETCURSEL, 0, 0);
1945  INT length = SendDlgItemMessageW(hDlg, LOWORD(wParam), CB_GETLBTEXTLEN, index, 0);
1946 
1947  PrinterName = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(length+1));
1948  SendDlgItemMessageW(hDlg, LOWORD(wParam), CB_GETLBTEXT, index, (LPARAM)PrinterName);
1949  PRINTDLG_ChangePrinterW(hDlg, PrinterName, PrintStructures);
1950  HeapFree(GetProcessHeap(),0,PrinterName);
1951  }
1952  break;
1953 
1954  case cmb2: /* Papersize */
1955  {
1956  DWORD Sel = SendDlgItemMessageW(hDlg, cmb2, CB_GETCURSEL, 0, 0);
1957  if(Sel != CB_ERR) {
1958  lpdm->u1.s1.dmPaperSize = SendDlgItemMessageW(hDlg, cmb2,
1960  Sel, 0);
1961  GetDlgItemTextW(hDlg, cmb2, lpdm->dmFormName, CCHFORMNAME);
1962  }
1963  }
1964  break;
1965 
1966  case cmb3: /* Bin */
1967  {
1968  DWORD Sel = SendDlgItemMessageW(hDlg, cmb3, CB_GETCURSEL, 0, 0);
1969  if(Sel != CB_ERR)
1970  lpdm->u1.s1.dmDefaultSource = SendDlgItemMessageW(hDlg, cmb3,
1971  CB_GETITEMDATA, Sel,
1972  0);
1973  }
1974  break;
1975  }
1976  if(lppd->Flags & PD_PRINTSETUP) {
1977  switch (LOWORD(wParam)) {
1978  case rad1: /* orientation */
1979  case rad2:
1980  if (IsDlgButtonChecked(hDlg, rad1) == BST_CHECKED) {
1981  if(lpdm->u1.s1.dmOrientation != DMORIENT_PORTRAIT) {
1982  lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
1984  (LPARAM)PrintStructures->hPortraitIcon);
1986  (LPARAM)PrintStructures->hPortraitIcon);
1987  }
1988  } else {
1989  if(lpdm->u1.s1.dmOrientation != DMORIENT_LANDSCAPE) {
1990  lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
1992  (LPARAM)PrintStructures->hLandscapeIcon);
1994  (LPARAM)PrintStructures->hLandscapeIcon);
1995  }
1996  }
1997  break;
1998  }
1999  }
2000  return FALSE;
2001 }
2002 
2003 /***********************************************************************
2004  * PrintDlgProcA [internal]
2005  */
2007  LPARAM lParam)
2008 {
2009  PRINT_PTRA* PrintStructures;
2010  INT_PTR res = FALSE;
2011 
2012  if (uMsg!=WM_INITDIALOG) {
2013  PrintStructures = GetPropW(hDlg, printdlg_prop);
2014  if (!PrintStructures)
2015  return FALSE;
2016  } else {
2017  PrintStructures = (PRINT_PTRA*) lParam;
2018  SetPropW(hDlg, printdlg_prop, PrintStructures);
2019  if(!check_printer_setup(hDlg))
2020  {
2021  EndDialog(hDlg,FALSE);
2022  return FALSE;
2023  }
2024  res = PRINTDLG_WMInitDialog(hDlg, PrintStructures);
2025 
2026  if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK)
2027  res = PrintStructures->lpPrintDlg->lpfnPrintHook(
2028  hDlg, uMsg, wParam, (LPARAM)PrintStructures->lpPrintDlg
2029  );
2030  return res;
2031  }
2032 
2033  if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK) {
2034  res = PrintStructures->lpPrintDlg->lpfnPrintHook(hDlg,uMsg,wParam,
2035  lParam);
2036  if(res) return res;
2037  }
2038 
2039  switch (uMsg) {
2040  case WM_COMMAND:
2041  return PRINTDLG_WMCommandA(hDlg, wParam, PrintStructures);
2042 
2043  case WM_DESTROY:
2044  DestroyIcon(PrintStructures->hCollateIcon);
2045  DestroyIcon(PrintStructures->hNoCollateIcon);
2046  DestroyIcon(PrintStructures->hPortraitIcon);
2047  DestroyIcon(PrintStructures->hLandscapeIcon);
2048  if(PrintStructures->hwndUpDown)
2049  DestroyWindow(PrintStructures->hwndUpDown);
2050  return FALSE;
2051  }
2052  return res;
2053 }
2054 
2056  LPARAM lParam)
2057 {
2058  PRINT_PTRW* PrintStructures;
2059  INT_PTR res = FALSE;
2060 
2061  if (uMsg!=WM_INITDIALOG) {
2062  PrintStructures = GetPropW(hDlg, printdlg_prop);
2063  if (!PrintStructures)
2064  return FALSE;
2065  } else {
2066  PrintStructures = (PRINT_PTRW*) lParam;
2067  SetPropW(hDlg, printdlg_prop, PrintStructures);
2068  if(!check_printer_setup(hDlg))
2069  {
2070  EndDialog(hDlg,FALSE);
2071  return FALSE;
2072  }
2073  res = PRINTDLG_WMInitDialogW(hDlg, PrintStructures);
2074 
2075  if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK)
2076  res = PrintStructures->lpPrintDlg->lpfnPrintHook(hDlg, uMsg, wParam, (LPARAM)PrintStructures->lpPrintDlg);
2077  return res;
2078  }
2079 
2080  if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK) {
2081  res = PrintStructures->lpPrintDlg->lpfnPrintHook(hDlg,uMsg,wParam, lParam);
2082  if(res) return res;
2083  }
2084 
2085  switch (uMsg) {
2086  case WM_COMMAND:
2087  return PRINTDLG_WMCommandW(hDlg, wParam, PrintStructures);
2088 
2089  case WM_DESTROY:
2090  DestroyIcon(PrintStructures->hCollateIcon);
2091  DestroyIcon(PrintStructures->hNoCollateIcon);
2092  DestroyIcon(PrintStructures->hPortraitIcon);
2093  DestroyIcon(PrintStructures->hLandscapeIcon);
2094  if(PrintStructures->hwndUpDown)
2095  DestroyWindow(PrintStructures->hwndUpDown);
2096  return FALSE;
2097  }
2098  return res;
2099 }
2100 
2101 /************************************************************
2102  *
2103  * PRINTDLG_GetDlgTemplate
2104  *
2105  */
2107 {
2108  HRSRC hResInfo;
2109  HGLOBAL hDlgTmpl;
2110 
2111  if (lppd->Flags & PD_PRINTSETUP) {
2112  if(lppd->Flags & PD_ENABLESETUPTEMPLATEHANDLE) {
2113  hDlgTmpl = lppd->hSetupTemplate;
2114  } else if(lppd->Flags & PD_ENABLESETUPTEMPLATE) {
2115  hResInfo = FindResourceA(lppd->hInstance,
2117  hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
2118  } else {
2119  hResInfo = FindResourceA(COMDLG32_hInstance, "PRINT32_SETUP",
2120  (LPSTR)RT_DIALOG);
2121  hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
2122  }
2123  } else {
2124  if(lppd->Flags & PD_ENABLEPRINTTEMPLATEHANDLE) {
2125  hDlgTmpl = lppd->hPrintTemplate;
2126  } else if(lppd->Flags & PD_ENABLEPRINTTEMPLATE) {
2127  hResInfo = FindResourceA(lppd->hInstance,
2128  lppd->lpPrintTemplateName,
2129  (LPSTR)RT_DIALOG);
2130  hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
2131  } else {
2132  hResInfo = FindResourceA(COMDLG32_hInstance, "PRINT32",
2133  (LPSTR)RT_DIALOG);
2134  hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
2135  }
2136  }
2137  return hDlgTmpl;
2138 }
2139 
2141 {
2142  HRSRC hResInfo;
2143  HGLOBAL hDlgTmpl;
2144  static const WCHAR xpsetup[] = { 'P','R','I','N','T','3','2','_','S','E','T','U','P',0};
2145  static const WCHAR xprint[] = { 'P','R','I','N','T','3','2',0};
2146 
2147  if (lppd->Flags & PD_PRINTSETUP) {
2148  if(lppd->Flags & PD_ENABLESETUPTEMPLATEHANDLE) {
2149  hDlgTmpl = lppd->hSetupTemplate;
2150  } else if(lppd->Flags & PD_ENABLESETUPTEMPLATE) {
2151  hResInfo = FindResourceW(lppd->hInstance,
2153  hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
2154  } else {
2155  hResInfo = FindResourceW(COMDLG32_hInstance, xpsetup, (LPWSTR)RT_DIALOG);
2156  hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
2157  }
2158  } else {
2159  if(lppd->Flags & PD_ENABLEPRINTTEMPLATEHANDLE) {
2160  hDlgTmpl = lppd->hPrintTemplate;
2161  } else if(lppd->Flags & PD_ENABLEPRINTTEMPLATE) {
2162  hResInfo = FindResourceW(lppd->hInstance,
2163  lppd->lpPrintTemplateName,
2164  (LPWSTR)RT_DIALOG);
2165  hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
2166  } else {
2167  hResInfo = FindResourceW(COMDLG32_hInstance, xprint, (LPWSTR)RT_DIALOG);
2168  hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
2169  }
2170  }
2171  return hDlgTmpl;
2172 }
2173 
2174 /***********************************************************************
2175  *
2176  * PRINTDLG_CreateDC
2177  *
2178  */
2180 {
2181  DEVNAMES *pdn = GlobalLock(lppd->hDevNames);
2182  DEVMODEA *pdm = GlobalLock(lppd->hDevMode);
2183 
2184  if(lppd->Flags & PD_RETURNDC) {
2185  lppd->hDC = CreateDCA((char*)pdn + pdn->wDriverOffset,
2186  (char*)pdn + pdn->wDeviceOffset,
2187  (char*)pdn + pdn->wOutputOffset,
2188  pdm );
2189  } else if(lppd->Flags & PD_RETURNIC) {
2190  lppd->hDC = CreateICA((char*)pdn + pdn->wDriverOffset,
2191  (char*)pdn + pdn->wDeviceOffset,
2192  (char*)pdn + pdn->wOutputOffset,
2193  pdm );
2194  }
2195  GlobalUnlock(lppd->hDevNames);
2196  GlobalUnlock(lppd->hDevMode);
2197  return lppd->hDC != NULL;
2198 }
2199 
2201 {
2202  DEVNAMES *pdn = GlobalLock(lppd->hDevNames);
2203  DEVMODEW *pdm = GlobalLock(lppd->hDevMode);
2204 
2205  if(lppd->Flags & PD_RETURNDC) {
2206  lppd->hDC = CreateDCW((WCHAR*)pdn + pdn->wDriverOffset,
2207  (WCHAR*)pdn + pdn->wDeviceOffset,
2208  (WCHAR*)pdn + pdn->wOutputOffset,
2209  pdm );
2210  } else if(lppd->Flags & PD_RETURNIC) {
2211  lppd->hDC = CreateICW((WCHAR*)pdn + pdn->wDriverOffset,
2212  (WCHAR*)pdn + pdn->wDeviceOffset,
2213  (WCHAR*)pdn + pdn->wOutputOffset,
2214  pdm );
2215  }
2216  GlobalUnlock(lppd->hDevNames);
2217  GlobalUnlock(lppd->hDevMode);
2218  return lppd->hDC != NULL;
2219 }
2220 
2221 /***********************************************************************
2222  * PrintDlgA (COMDLG32.@)
2223  *
2224  * Displays the PRINT dialog box, which enables the user to specify
2225  * specific properties of the print job.
2226  *
2227  * PARAMS
2228  * lppd [IO] ptr to PRINTDLG32 struct
2229  *
2230  * RETURNS
2231  * nonzero if the user pressed the OK button
2232  * zero if the user cancelled the window or an error occurred
2233  *
2234  * BUGS
2235  * PrintDlg:
2236  * * The Collate Icons do not display, even though they are in the code.
2237  * * The Properties Button(s) should call DocumentPropertiesA().
2238  */
2239 
2241 {
2242  BOOL bRet = FALSE;
2243  LPVOID ptr;
2244  HINSTANCE hInst;
2245 
2246  if (!lppd)
2247  {
2249  return FALSE;
2250  }
2251 
2252  if(TRACE_ON(commdlg)) {
2253  char flagstr[1000] = "";
2254  const struct pd_flags *pflag = pd_flags;
2255  for( ; pflag->name; pflag++) {
2256  if(lppd->Flags & pflag->flag)
2257  strcat(flagstr, pflag->name);
2258  }
2259  TRACE("(%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
2260  "pp. %d-%d, min p %d, max p %d, copies %d, hinst %p\n"
2261  "flags %08x (%s)\n",
2262  lppd, lppd->hwndOwner, lppd->hDevMode, lppd->hDevNames,
2263  lppd->nFromPage, lppd->nToPage, lppd->nMinPage, lppd->nMaxPage,
2264  lppd->nCopies, lppd->hInstance, lppd->Flags, flagstr);
2265  }
2266 
2267  if(lppd->lStructSize != sizeof(PRINTDLGA)) {
2268  WARN("structure size failure!!!\n");
2270  return FALSE;
2271  }
2272 
2273  if(lppd->Flags & PD_RETURNDEFAULT) {
2275  DRIVER_INFO_3A *dbuf;
2276  HANDLE hprn;
2277  DWORD needed;
2278 
2279  if(lppd->hDevMode || lppd->hDevNames) {
2280  WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
2282  return FALSE;
2283  }
2284  if(!PRINTDLG_OpenDefaultPrinter(&hprn)) {
2285  WARN("Can't find default printer\n");
2287  return FALSE;
2288  }
2289 
2290  GetPrinterA(hprn, 2, NULL, 0, &needed);
2291  pbuf = HeapAlloc(GetProcessHeap(), 0, needed);
2292  GetPrinterA(hprn, 2, (LPBYTE)pbuf, needed, &needed);
2293 
2294  GetPrinterDriverA(hprn, NULL, 3, NULL, 0, &needed);
2295  dbuf = HeapAlloc(GetProcessHeap(),0,needed);
2296  if (!GetPrinterDriverA(hprn, NULL, 3, (LPBYTE)dbuf, needed, &needed)) {
2297  ERR("GetPrinterDriverA failed, le %d, fix your config for printer %s!\n",
2298  GetLastError(),pbuf->pPrinterName);
2299  HeapFree(GetProcessHeap(), 0, dbuf);
2300  HeapFree(GetProcessHeap(), 0, pbuf);
2302  return FALSE;
2303  }
2304  ClosePrinter(hprn);
2305 
2307  dbuf->pDriverPath,
2308  pbuf->pPrinterName,
2309  pbuf->pPortName);
2310  lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, pbuf->pDevMode->dmSize +
2311  pbuf->pDevMode->dmDriverExtra);
2312  ptr = GlobalLock(lppd->hDevMode);
2313  memcpy(ptr, pbuf->pDevMode, pbuf->pDevMode->dmSize +
2314  pbuf->pDevMode->dmDriverExtra);
2315  GlobalUnlock(lppd->hDevMode);
2316  HeapFree(GetProcessHeap(), 0, pbuf);
2317  HeapFree(GetProcessHeap(), 0, dbuf);
2318  bRet = TRUE;
2319  } else {
2320  HGLOBAL hDlgTmpl;
2321  PRINT_PTRA *PrintStructures;
2322 
2323  /* load Dialog resources,
2324  * depending on Flags indicates Print32 or Print32_setup dialog
2325  */
2326  hDlgTmpl = PRINTDLG_GetDlgTemplateA(lppd);
2327  if (!hDlgTmpl) {
2329  return FALSE;
2330  }
2331  ptr = LockResource( hDlgTmpl );
2332  if (!ptr) {
2334  return FALSE;
2335  }
2336 
2337  PrintStructures = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2338  sizeof(PRINT_PTRA));
2339  PrintStructures->lpPrintDlg = lppd;
2340 
2341  /* and create & process the dialog .
2342  * -1 is failure, 0 is broken hwnd, everything else is ok.
2343  */
2344  hInst = COMDLG32_hInstance;
2345  if (lppd->Flags & (PD_ENABLESETUPTEMPLATE | PD_ENABLEPRINTTEMPLATE)) hInst = lppd->hInstance;
2346  bRet = (0<DialogBoxIndirectParamA(hInst, ptr, lppd->hwndOwner,
2347  PrintDlgProcA,
2348  (LPARAM)PrintStructures));
2349 
2350  if(bRet) {
2351  DEVMODEA *lpdm = PrintStructures->lpDevMode, *lpdmReturn;
2352  PRINTER_INFO_2A *pi = PrintStructures->lpPrinterInfo;
2353  DRIVER_INFO_3A *di = PrintStructures->lpDriverInfo;
2354 
2355  if (lppd->hDevMode == 0) {
2356  TRACE(" No hDevMode yet... Need to create my own\n");
2358  lpdm->dmSize + lpdm->dmDriverExtra);
2359  } else {
2360  lppd->hDevMode = GlobalReAlloc(lppd->hDevMode,
2361  lpdm->dmSize + lpdm->dmDriverExtra,
2362  GMEM_MOVEABLE);
2363  }
2364  lpdmReturn = GlobalLock(lppd->hDevMode);
2365  memcpy(lpdmReturn, lpdm, lpdm->dmSize + lpdm->dmDriverExtra);
2366 
2368  di->pDriverPath,
2369  pi->pPrinterName,
2370  pi->pPortName
2371  );
2372  GlobalUnlock(lppd->hDevMode);
2373  }
2374  HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
2375  HeapFree(GetProcessHeap(), 0, PrintStructures->lpPrinterInfo);
2376  HeapFree(GetProcessHeap(), 0, PrintStructures->lpDriverInfo);
2377  HeapFree(GetProcessHeap(), 0, PrintStructures);
2378  }
2379  if(bRet && (lppd->Flags & PD_RETURNDC || lppd->Flags & PD_RETURNIC))
2380  bRet = PRINTDLG_CreateDCA(lppd);
2381 
2382  TRACE("exit! (%d)\n", bRet);
2383  return bRet;
2384 }
2385 
2386 /***********************************************************************
2387  * PrintDlgW (COMDLG32.@)
2388  *
2389  * See PrintDlgA.
2390  */
2392 {
2393  BOOL bRet = FALSE;
2394  LPVOID ptr;
2395  HINSTANCE hInst;
2396 
2397  if (!lppd)
2398  {
2400  return FALSE;
2401  }
2402 
2403  if(TRACE_ON(commdlg)) {
2404  char flagstr[1000] = "";
2405  const struct pd_flags *pflag = pd_flags;
2406  for( ; pflag->name; pflag++) {
2407  if(lppd->Flags & pflag->flag)
2408  strcat(flagstr, pflag->name);
2409  }
2410  TRACE("(%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
2411  "pp. %d-%d, min p %d, max p %d, copies %d, hinst %p\n"
2412  "flags %08x (%s)\n",
2413  lppd, lppd->hwndOwner, lppd->hDevMode, lppd->hDevNames,
2414  lppd->nFromPage, lppd->nToPage, lppd->nMinPage, lppd->nMaxPage,
2415  lppd->nCopies, lppd->hInstance, lppd->Flags, flagstr);
2416  }
2417 
2418  if(lppd->lStructSize != sizeof(PRINTDLGW)) {
2419  WARN("structure size failure!!!\n");
2421  return FALSE;
2422  }
2423 
2424  if(lppd->Flags & PD_RETURNDEFAULT) {
2426  DRIVER_INFO_3W *dbuf;
2427  HANDLE hprn;
2428  DWORD needed;
2429 
2430  if(lppd->hDevMode || lppd->hDevNames) {
2431  WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
2433  return FALSE;
2434  }
2435  if(!PRINTDLG_OpenDefaultPrinter(&hprn)) {
2436  WARN("Can't find default printer\n");
2438  return FALSE;
2439  }
2440 
2441  GetPrinterW(hprn, 2, NULL, 0, &needed);
2442  pbuf = HeapAlloc(GetProcessHeap(), 0, needed);
2443  GetPrinterW(hprn, 2, (LPBYTE)pbuf, needed, &needed);
2444 
2445  GetPrinterDriverW(hprn, NULL, 3, NULL, 0, &needed);
2446  dbuf = HeapAlloc(GetProcessHeap(),0,needed);
2447  if (!GetPrinterDriverW(hprn, NULL, 3, (LPBYTE)dbuf, needed, &needed)) {
2448  ERR("GetPrinterDriverA failed, le %d, fix your config for printer %s!\n",
2449  GetLastError(),debugstr_w(pbuf->pPrinterName));
2450  HeapFree(GetProcessHeap(), 0, dbuf);
2451  HeapFree(GetProcessHeap(), 0, pbuf);
2453  return FALSE;
2454  }
2455  ClosePrinter(hprn);
2456 
2458  dbuf->pDriverPath,
2459  pbuf->pPrinterName,
2460  pbuf->pPortName);
2461  lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, pbuf->pDevMode->dmSize +
2462  pbuf->pDevMode->dmDriverExtra);
2463  ptr = GlobalLock(lppd->hDevMode);
2464  memcpy(ptr, pbuf->pDevMode, pbuf->pDevMode->dmSize +
2465  pbuf->pDevMode->dmDriverExtra);
2466  GlobalUnlock(lppd->hDevMode);
2467  HeapFree(GetProcessHeap(), 0, pbuf);
2468  HeapFree(GetProcessHeap(), 0, dbuf);
2469  bRet = TRUE;
2470  } else {
2471  HGLOBAL hDlgTmpl;
2472  PRINT_PTRW *PrintStructures;
2473 
2474  /* load Dialog resources,
2475  * depending on Flags indicates Print32 or Print32_setup dialog
2476  */
2477  hDlgTmpl = PRINTDLG_GetDlgTemplateW(lppd);
2478  if (!hDlgTmpl) {
2480  return FALSE;
2481  }
2482  ptr = LockResource( hDlgTmpl );
2483  if (!ptr) {
2485  return FALSE;
2486  }
2487 
2488  PrintStructures = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2489  sizeof(PRINT_PTRW));
2490  PrintStructures->lpPrintDlg = lppd;
2491 
2492  /* and create & process the dialog .
2493  * -1 is failure, 0 is broken hwnd, everything else is ok.
2494  */
2495  hInst = COMDLG32_hInstance;
2496  if (lppd->Flags & (PD_ENABLESETUPTEMPLATE | PD_ENABLEPRINTTEMPLATE)) hInst = lppd->hInstance;
2497  bRet = (0<DialogBoxIndirectParamW(hInst, ptr, lppd->hwndOwner,
2498  PrintDlgProcW,
2499  (LPARAM)PrintStructures));
2500 
2501  if(bRet) {
2502  DEVMODEW *lpdm = PrintStructures->lpDevMode, *lpdmReturn;
2503  PRINTER_INFO_2W *pi = PrintStructures->lpPrinterInfo;
2504  DRIVER_INFO_3W *di = PrintStructures->lpDriverInfo;
2505 
2506  if (lppd->hDevMode == 0) {
2507  TRACE(" No hDevMode yet... Need to create my own\n");
2509  lpdm->dmSize + lpdm->dmDriverExtra);
2510  } else {
2511  WORD locks;
2512  if((locks = (GlobalFlags(lppd->hDevMode) & GMEM_LOCKCOUNT))) {
2513  WARN("hDevMode has %d locks on it. Unlocking it now\n", locks);
2514  while(locks--) {
2515  GlobalUnlock(lppd->hDevMode);
2516  TRACE("Now got %d locks\n", locks);
2517  }
2518  }
2519  lppd->hDevMode = GlobalReAlloc(lppd->hDevMode,
2520  lpdm->dmSize + lpdm->dmDriverExtra,
2521  GMEM_MOVEABLE);
2522  }
2523  lpdmReturn = GlobalLock(lppd->hDevMode);
2524  memcpy(lpdmReturn, lpdm, lpdm->dmSize + lpdm->dmDriverExtra);
2525 
2526  if (lppd->hDevNames != 0) {
2527  WORD locks;
2528  if((locks = (GlobalFlags(lppd->hDevNames) & GMEM_LOCKCOUNT))) {
2529  WARN("hDevNames has %d locks on it. Unlocking it now\n", locks);
2530  while(locks--)
2531  GlobalUnlock(lppd->hDevNames);
2532  }
2533  }
2535  di->pDriverPath,
2536  pi->pPrinterName,
2537  pi->pPortName
2538  );
2539  GlobalUnlock(lppd->hDevMode);
2540  }
2541  HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
2542  HeapFree(GetProcessHeap(), 0, PrintStructures->lpPrinterInfo);
2543  HeapFree(GetProcessHeap(), 0, PrintStructures->lpDriverInfo);
2544  HeapFree(GetProcessHeap(), 0, PrintStructures);
2545  }
2546  if(bRet && (lppd->Flags & PD_RETURNDC || lppd->Flags & PD_RETURNIC))
2547  bRet = PRINTDLG_CreateDCW(lppd);
2548 
2549  TRACE("exit! (%d)\n", bRet);
2550  return bRet;
2551 }
2552 
2553 /***********************************************************************
2554  *
2555  * PageSetupDlg
2556  * rad1 - portrait
2557  * rad2 - landscape
2558  * cmb1 - printer select (not in standard dialog template)
2559  * cmb2 - paper size
2560  * cmb3 - source (tray?)
2561  * edt4 - border left
2562  * edt5 - border top
2563  * edt6 - border right
2564  * edt7 - border bottom
2565  * psh3 - "Printer..."
2566  */
2567 
2568 typedef struct
2569 {
2571  union
2572  {
2575  } u;
2576  HWND hDlg; /* Page Setup dialog handle */
2577  RECT rtDrawRect; /* Drawing rect for page */
2578 } pagesetup_data;
2579 
2581 {
2582  return data->u.dlgw->Flags;
2583 }
2584 
2585 static inline BOOL is_metric(const pagesetup_data *data)
2586 {
2588 }
2589 
2591 {
2592  if (is_metric(data))
2593  return 10 * size;
2594  else
2595  return 10 * size * 100 / 254;
2596 }
2597 
2599 {
2600  if (is_metric(data))
2601  return size * 254 / 100;
2602  else
2603  return size;
2604 }
2605 
2607 {
2608  static WCHAR sep;
2609 
2610  if(!sep)
2611  {
2612  WCHAR buf[] = {'.', 0};
2614  sep = buf[0];
2615  }
2616  return sep;
2617 }
2618 
2619 static void size2str(const pagesetup_data *data, DWORD size, LPWSTR strout)
2620 {
2621  WCHAR integer_fmt[] = {'%','d',0};
2622  WCHAR hundredths_fmt[] = {'%','d','%','c','%','0','2','d',0};
2623  WCHAR thousandths_fmt[] = {'%','d','%','c','%','0','3','d',0};
2624 
2625  /* FIXME use LOCALE_SDECIMAL when the edit parsing code can cope */
2626 
2627  if (is_metric(data))
2628  {
2629  if(size % 100)
2630  wsprintfW(strout, hundredths_fmt, size / 100, get_decimal_sep(), size % 100);
2631  else
2632  wsprintfW(strout, integer_fmt, size / 100);
2633  }
2634  else
2635  {
2636  if(size % 1000)
2637  wsprintfW(strout, thousandths_fmt, size / 1000, get_decimal_sep(), size % 1000);
2638  else
2639  wsprintfW(strout, integer_fmt, size / 1000);
2640 
2641  }
2642 }
2643 
2644 static inline BOOL is_default_metric(void)
2645 {
2646  DWORD system;
2647  GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_IMEASURE | LOCALE_RETURN_NUMBER,
2648  (LPWSTR)&system, sizeof(system));
2649  return system == 0;
2650 }
2651 
2652 /**********************************************
2653  * rotate_rect
2654  * Cyclically permute the four members of rc
2655  * If sense is TRUE l -> t -> r -> b
2656  * otherwise l <- t <- r <- b
2657  */
2658 static inline void rotate_rect(RECT *rc, BOOL sense)
2659 {
2660  INT tmp;
2661  if(sense)
2662  {
2663  tmp = rc->bottom;
2664  rc->bottom = rc->right;
2665  rc->right = rc->top;
2666  rc->top = rc->left;
2667  rc->left = tmp;
2668  }
2669  else
2670  {
2671  tmp = rc->left;
2672  rc->left = rc->top;
2673  rc->top = rc->right;
2674  rc->right = rc->bottom;
2675  rc->bottom = tmp;
2676  }
2677 }
2678 
2680 {
2681  DEVMODEW *dm = GlobalLock(data->u.dlgw->hDevMode);
2682 
2683  assert(orient == DMORIENT_PORTRAIT || orient == DMORIENT_LANDSCAPE);
2684 
2685  if(data->unicode)
2686  dm->u1.s1.dmOrientation = orient;
2687  else
2688  {
2689  DEVMODEA *dmA = (DEVMODEA *)dm;
2690  dmA->u1.s1.dmOrientation = orient;
2691  }
2692  GlobalUnlock(data->u.dlgw->hDevMode);
2693 }
2694 
2696 {
2697  DEVMODEW *dm = GlobalLock(data->u.dlgw->hDevMode);
2698  WORD orient;
2699 
2700  if(data->unicode)
2701  orient = dm->u1.s1.dmOrientation;
2702  else
2703  {
2704  DEVMODEA *dmA = (DEVMODEA *)dm;
2705  orient = dmA->u1.s1.dmOrientation;
2706  }
2707  GlobalUnlock(data->u.dlgw->hDevMode);
2708  return orient;
2709 }
2710 
2712 {
2713  DEVMODEW *dm = GlobalLock(data->u.dlgw->hDevMode);
2714 
2715  if(data->unicode)
2716  dm->u1.s1.dmPaperSize = paper;
2717  else
2718  {
2719  DEVMODEA *dmA = (DEVMODEA *)dm;
2720  dmA->u1.s1.dmPaperSize = paper;
2721  }
2722  GlobalUnlock(data->u.dlgw->hDevMode);
2723 }
2724 
2726 {
2727  DEVMODEW *dm = GlobalLock(data->u.dlgw->hDevMode);
2728  WORD paper;
2729 
2730  if(data->unicode)
2731  paper = dm->u1.s1.dmPaperSize;
2732  else
2733  {
2734  DEVMODEA *dmA = (DEVMODEA *)dm;
2735  paper = dmA->u1.s1.dmPaperSize;
2736  }
2737  GlobalUnlock(data->u.dlgw->hDevMode);
2738  return paper;
2739 }
2740 
2742 {
2743  DEVMODEW *dm = GlobalLock(data->u.dlgw->hDevMode);
2744 
2745  if(data->unicode)
2746  dm->u1.s1.dmDefaultSource = source;
2747  else
2748  {
2749  DEVMODEA *dmA = (DEVMODEA *)dm;
2750  dmA->u1.s1.dmDefaultSource = source;
2751  }
2752  GlobalUnlock(data->u.dlgw->hDevMode);
2753 }
2754 
2755 typedef enum
2756 {
2760 } devnames_name;
2761 
2762 
2764 {
2765  switch(which)
2766  {
2767  case devnames_driver_name: return dn->wDriverOffset;
2768  case devnames_device_name: return dn->wDeviceOffset;
2769  case devnames_output_name: return dn->wOutputOffset;
2770  }
2771  ERR("Shouldn't be here\n");
2772  return 0;
2773 }
2774 
2776 {
2777  DEVNAMES *dn;
2778  WCHAR *name;
2779 
2780  dn = GlobalLock(data->u.dlgw->hDevNames);
2781  if(data->unicode)
2782  name = strdupW((WCHAR *)dn + get_devname_offset(dn, which));
2783  else
2784  {
2785  int len = MultiByteToWideChar(CP_ACP, 0, (char*)dn + get_devname_offset(dn, which), -1, NULL, 0);
2786  name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2787  MultiByteToWideChar(CP_ACP, 0, (char*)dn + get_devname_offset(dn, which), -1, name, len);
2788  }
2789  GlobalUnlock(data->u.dlgw->hDevNames);
2790  return name;
2791 }
2792 
2794 {
2796 }
2797 
2799 {
2801 }
2802 
2804 {
2806 }
2807 
2809 {
2810  HeapFree(GetProcessHeap(), 0, name);
2811 }
2812 
2814 {
2815  DEVNAMES *dn;
2816  WCHAR def[256];
2817  DWORD len = sizeof(DEVNAMES), drv_len, dev_len, port_len;
2818 
2819  if(data->unicode)
2820  {
2821  drv_len = (strlenW(drv) + 1) * sizeof(WCHAR);
2822  dev_len = (strlenW(devname) + 1) * sizeof(WCHAR);
2823  port_len = (strlenW(port) + 1) * sizeof(WCHAR);
2824  }
2825  else
2826  {
2827  drv_len = WideCharToMultiByte(CP_ACP, 0, drv, -1, NULL, 0, NULL, NULL);
2828  dev_len = WideCharToMultiByte(CP_ACP, 0, devname, -1, NULL, 0, NULL, NULL);
2829  port_len = WideCharToMultiByte(CP_ACP, 0, port, -1, NULL, 0, NULL, NULL);
2830  }
2831  len += drv_len + dev_len + port_len;
2832 
2833  if(data->u.dlgw->hDevNames)
2834  data->u.dlgw->hDevNames = GlobalReAlloc(data->u.dlgw->hDevNames, len, GMEM_MOVEABLE);
2835  else
2836  data->u.dlgw->hDevNames = GlobalAlloc(GMEM_MOVEABLE, len);
2837 
2838  dn = GlobalLock(data->u.dlgw->hDevNames);
2839 
2840  if(data->unicode)
2841  {
2842  WCHAR *ptr = (WCHAR *)(dn + 1);
2843  len = sizeof(DEVNAMES) / sizeof(WCHAR);
2844  dn->wDriverOffset = len;
2845  strcpyW(ptr, drv);
2846  ptr += drv_len / sizeof(WCHAR);
2847  len += drv_len / sizeof(WCHAR);
2848  dn->wDeviceOffset = len;
2849  strcpyW(ptr, devname);
2850  ptr += dev_len / sizeof(WCHAR);
2851  len += dev_len / sizeof(WCHAR);
2852  dn->wOutputOffset = len;
2853  strcpyW(ptr, port);
2854  }
2855  else
2856  {
2857  char *ptr = (char *)(dn + 1);
2858  len = sizeof(DEVNAMES);
2859  dn->wDriverOffset = len;
2860  WideCharToMultiByte(CP_ACP, 0, drv, -1, ptr, drv_len, NULL, NULL);
2861  ptr += drv_len;
2862  len += drv_len;
2863  dn->wDeviceOffset = len;
2864  WideCharToMultiByte(CP_ACP, 0, devname, -1, ptr, dev_len, NULL, NULL);
2865  ptr += dev_len;
2866  len += dev_len;
2867  dn->wOutputOffset = len;
2868  WideCharToMultiByte(CP_ACP, 0, port, -1, ptr, port_len, NULL, NULL);
2869  }
2870 
2871  dn->wDefault = 0;
2872  len = ARRAY_SIZE(def);
2873  GetDefaultPrinterW(def, &len);
2874  if(!lstrcmpW(def, devname))
2875  dn->wDefault = 1;
2876 
2877  GlobalUnlock(data->u.dlgw->hDevNames);
2878 }
2879 
2881 {
2882  DEVMODEW *dm = GlobalLock(data->u.dlgw->hDevMode);
2883  DEVMODEW *ret;
2884 
2885  if(data->unicode)
2886  {
2887  /* We make a copy even in the unicode case because the ptr
2888  may get passed back to us in pagesetup_set_devmode. */
2889  ret = HeapAlloc(GetProcessHeap(), 0, dm->dmSize + dm->dmDriverExtra);
2890  memcpy(ret, dm, dm->dmSize + dm->dmDriverExtra);
2891  }
2892  else
2893  ret = GdiConvertToDevmodeW((DEVMODEA *)dm);
2894 
2895  GlobalUnlock(data->u.dlgw->hDevMode);
2896  return ret;
2897 }
2898 
2900 {
2901  HeapFree(GetProcessHeap(), 0, dm);
2902 }
2903 
2905 {
2906  DEVMODEA *dmA = NULL;
2907  void *src, *dst;
2908  DWORD size;
2909 
2910  if(data->unicode)
2911  {
2912  size = dm->dmSize + dm->dmDriverExtra;
2913  src = dm;
2914  }
2915  else
2916  {
2917  dmA = convert_to_devmodeA(dm);
2918  size = dmA->dmSize + dmA->dmDriverExtra;
2919  src = dmA;
2920  }
2921 
2922  if(data->u.dlgw->hDevMode)
2923  data->u.dlgw->hDevMode = GlobalReAlloc(data->u.dlgw->hDevMode, size,
2924  GMEM_MOVEABLE);
2925  else
2926  data->u.dlgw->hDevMode = GlobalAlloc(GMEM_MOVEABLE, size);
2927 
2928  dst = GlobalLock(data->u.dlgw->hDevMode);
2929  memcpy(dst, src, size);
2930  GlobalUnlock(data->u.dlgw->hDevMode);
2931  HeapFree(GetProcessHeap(), 0, dmA);
2932 }
2933 
2935 {
2936  return &data->u.dlgw->ptPaperSize;
2937 }
2938 
2940 {
2941  return &data->u.dlgw->rtMargin;
2942 }
2943 
2944 typedef enum
2945 {
2948 } hook_type;
2949 
2951 {
2952  switch(which)
2953  {
2954  case page_setup_hook: return data->u.dlgw->lpfnPageSetupHook;
2955  case page_paint_hook: return data->u.dlgw->lpfnPagePaintHook;
2956  }
2957  return NULL;
2958 }
2959 
2960 /* This should only be used in calls to hook procs so we return the ptr
2961  already cast to LPARAM */
2963 {
2964  return (LPARAM)data->u.dlgw;
2965 }
2966 
2967 static inline void swap_point(POINT *pt)
2968 {
2969  LONG tmp = pt->x;
2970  pt->x = pt->y;
2971  pt->y = tmp;
2972 }
2973 
2975 {
2976  DEVMODEW *dm;
2977  LPWSTR devname, portname;
2978  int i, num;
2979  WORD *words = NULL, paperword;
2980  POINT *points = NULL;
2981  BOOL retval = FALSE;
2982 
2983  dm = pagesetup_get_devmode(data);
2984  devname = pagesetup_get_devname(data);
2985  portname = pagesetup_get_portname(data);
2986 
2987  num = DeviceCapabilitiesW(devname, portname, DC_PAPERS, NULL, dm);
2988  if (num <= 0)
2989  {
2990  FIXME("No papernames found for %s/%s\n", debugstr_w(devname), debugstr_w(portname));
2991  goto end;
2992  }
2993 
2994  words = HeapAlloc(GetProcessHeap(), 0, num * sizeof(WORD));
2995  points = HeapAlloc(GetProcessHeap(), 0, num * sizeof(POINT));
2996 
2997  if (num != DeviceCapabilitiesW(devname, portname, DC_PAPERS, (LPWSTR)words, dm))
2998  {
2999  FIXME("Number of returned words is not %d\n", num);
3000  goto end;
3001  }
3002 
3003  if (num != DeviceCapabilitiesW(devname, portname, DC_PAPERSIZE, (LPWSTR)points, dm))
3004  {
3005  FIXME("Number of returned sizes is not %d\n", num);
3006  goto end;
3007  }
3008 
3009  paperword = pagesetup_get_papersize(data);
3010 
3011  for (i = 0; i < num; i++)
3012  if (words[i] == paperword)
3013  break;
3014 
3015  if (i == num)
3016  {
3017  FIXME("Papersize %d not found in list?\n", paperword);
3018  goto end;
3019  }
3020 
3021  /* this is _10ths_ of a millimeter */
3022  pagesetup_get_papersize_pt(data)->x = tenths_mm_to_size(data, points[i].x);
3023  pagesetup_get_papersize_pt(data)->y = tenths_mm_to_size(data, points[i].y);
3024 
3027 
3028  retval = TRUE;
3029 
3030 end:
3031  HeapFree(GetProcessHeap(), 0, words);
3032  HeapFree(GetProcessHeap(), 0, points);
3033  pagesetup_release_a_devname(data, portname);
3034  pagesetup_release_a_devname(data, devname);
3035  pagesetup_release_devmode(data, dm);
3036 
3037  return retval;
3038 }
3039 
3040 /**********************************************************************************************
3041  * pagesetup_change_printer
3042  *
3043  * Redefines hDevMode and hDevNames HANDLES and initialises it.
3044  *
3045  */
3047 {
3048  HANDLE hprn;
3049  DWORD needed;
3050  PRINTER_INFO_2W *prn_info = NULL;
3051  DRIVER_INFO_3W *drv_info = NULL;
3052  DEVMODEW *dm = NULL;
3053  BOOL retval = FALSE;
3054 
3055  if(!OpenPrinterW(name, &hprn, NULL))
3056  {
3057  ERR("Can't open printer %s\n", debugstr_w(name));
3058  goto end;
3059  }
3060 
3061  GetPrinterW(hprn, 2, NULL, 0, &needed);
3062  prn_info = HeapAlloc(GetProcessHeap(), 0, needed);
3063  GetPrinterW(hprn, 2, (LPBYTE)prn_info, needed, &needed);
3064  GetPrinterDriverW(hprn, NULL, 3, NULL, 0, &needed);
3065  drv_info = HeapAlloc(GetProcessHeap(), 0, needed);
3066  if(!GetPrinterDriverW(hprn, NULL, 3, (LPBYTE)drv_info, needed, &needed))
3067  {
3068  ERR("GetPrinterDriverA failed for %s, fix your config!\n", debugstr_w(prn_info->pPrinterName));
3069  goto end;
3070  }
3071  ClosePrinter(hprn);
3072 
3073  needed = DocumentPropertiesW(0, 0, name, NULL, NULL, 0);
3074  if(needed == -1)
3075  {
3076  ERR("DocumentProperties fails on %s\n", debugstr_w(name));
3077  goto end;
3078  }
3079 
3080  dm = HeapAlloc(GetProcessHeap(), 0, needed);
3081  DocumentPropertiesW(0, 0, name, dm, NULL, DM_OUT_BUFFER);
3082 
3083  pagesetup_set_devmode(data, dm);
3084  pagesetup_set_devnames(data, drv_info->pDriverPath, prn_info->pPrinterName,
3085  prn_info->pPortName);
3086 
3087  retval = TRUE;
3088 end:
3089  HeapFree(GetProcessHeap(), 0, dm);
3090  HeapFree(GetProcessHeap(), 0, prn_info);
3091  HeapFree(GetProcessHeap(), 0, drv_info);
3092  return retval;
3093 }
3094 
3095 /****************************************************************************************
3096  * pagesetup_init_combos
3097  *
3098  * Fills Printers, Paper and Source combos
3099  *
3100  */
3102 {
3103  DEVMODEW *dm;
3104  LPWSTR devname, portname;
3105 
3106  dm = pagesetup_get_devmode(data);
3107  devname = pagesetup_get_devname(data);
3108  portname = pagesetup_get_portname(data);
3109 
3110  PRINTDLG_SetUpPrinterListComboW(hDlg, cmb1, devname);
3111  PRINTDLG_SetUpPaperComboBoxW(hDlg, cmb2, devname, portname, dm);
3112  PRINTDLG_SetUpPaperComboBoxW(hDlg, cmb3, devname, portname, dm);
3113 
3114  pagesetup_release_a_devname(data, portname);
3115  pagesetup_release_a_devname(data, devname);
3116  pagesetup_release_devmode(data, dm);
3117 }
3118 
3119 
3120 /****************************************************************************************
3121  * pagesetup_change_printer_dialog
3122  *
3123  * Pops up another dialog that lets the user pick another printer.
3124  *
3125  * For now we display the PrintDlg, this should display a striped down version of it.
3126  */
3128 {
3129  PRINTDLGW prnt;
3130  LPWSTR drvname, devname, portname;
3131  DEVMODEW *tmp_dm, *dm;
3132 
3133  memset(&prnt, 0, sizeof(prnt));
3134  prnt.lStructSize = sizeof(prnt);
3135  prnt.Flags = 0;
3136  prnt.hwndOwner = hDlg;
3137 
3138  drvname = pagesetup_get_drvname(data);
3139  devname = pagesetup_get_devname(data);
3140  portname = pagesetup_get_portname(data);
3141  prnt.hDevNames = 0;
3142  PRINTDLG_CreateDevNamesW(&prnt.hDevNames, drvname, devname, portname);
3143  pagesetup_release_a_devname(data, portname);
3144  pagesetup_release_a_devname(data, devname);
3145  pagesetup_release_a_devname(data, drvname);
3146 
3147  tmp_dm = pagesetup_get_devmode(data);
3148  prnt.hDevMode = GlobalAlloc(GMEM_MOVEABLE, tmp_dm->dmSize + tmp_dm->dmDriverExtra);
3149  dm = GlobalLock(prnt.hDevMode);
3150  memcpy(dm, tmp_dm, tmp_dm->dmSize + tmp_dm->dmDriverExtra);
3151  GlobalUnlock(prnt.hDevMode);
3152  pagesetup_release_devmode(data, tmp_dm);
3153 
3154  if (PrintDlgW(&prnt))
3155  {
3156  DEVMODEW *dm = GlobalLock(prnt.hDevMode);
3157  DEVNAMES *dn = GlobalLock(prnt.hDevNames);
3158 
3159  pagesetup_set_devnames(data, (WCHAR*)dn + dn->wDriverOffset,
3160  (WCHAR*)dn + dn->wDeviceOffset, (WCHAR *)dn + dn->wOutputOffset);
3161  pagesetup_set_devmode(data, dm);
3162  GlobalUnlock(prnt.hDevNames);
3163  GlobalUnlock(prnt.hDevMode);
3164  pagesetup_init_combos(hDlg, data);
3165  }
3166 
3167  GlobalFree(prnt.hDevMode);
3168  GlobalFree(prnt.hDevNames);
3169 
3170 }
3171 
3172 /******************************************************************************************
3173  * pagesetup_change_preview
3174  *
3175  * Changes paper preview size / position
3176  *
3177  */
3179 {
3180  LONG width, height, x, y;
3181  RECT tmp;
3182  const int shadow = 4;
3183 
3185  {
3186  width = data->rtDrawRect.right - data->rtDrawRect.left;
3187  height = pagesetup_get_papersize_pt(data)->y * width / pagesetup_get_papersize_pt(data)->x;
3188  }
3189  else
3190  {
3191  height = data->rtDrawRect.bottom - data->rtDrawRect.top;
3192  width = pagesetup_get_papersize_pt(data)->x * height / pagesetup_get_papersize_pt(data)->y;
3193  }
3194  x = (data->rtDrawRect.right + data->rtDrawRect.left - width) / 2;
3195  y = (data->rtDrawRect.bottom + data->rtDrawRect.top - height) / 2;
3196  TRACE("draw rect %s x=%d, y=%d, w=%d, h=%d\n",
3197  wine_dbgstr_rect(&data->rtDrawRect), x, y, width, height);
3198 
3199  MoveWindow(GetDlgItem(data->hDlg, rct2), x + width, y + shadow, shadow, height, FALSE);
3200  MoveWindow(GetDlgItem(data->hDlg, rct3), x + shadow, y + height, width, shadow, FALSE);
3201  MoveWindow(GetDlgItem(data->hDlg, rct1), x, y, width, height, FALSE);
3202 
3203  tmp = data->rtDrawRect;
3204  tmp.right += shadow;
3205  tmp.bottom += shadow;
3206  InvalidateRect(data->hDlg, &tmp, TRUE);
3207 }
3208 
3209 static inline LONG *element_from_margin_id(RECT *rc, WORD id)
3210 {
3211  switch(id)
3212  {
3213  case edt4: return &rc->left;
3214  case edt5: return &rc->top;
3215  case edt6: return &rc->right;
3216  case edt7: return &rc->bottom;
3217  }
3218  return NULL;
3219 }
3220 
3221 static void update_margin_edits(HWND hDlg, const pagesetup_data *data, WORD id)
3222 {
3223  WCHAR str[100];
3224  WORD idx;
3225 
3226  for(idx = edt4; idx <= edt7; idx++)
3227  {
3228  if(id == 0 || id == idx)
3229  {
3231  SetDlgItemTextW(hDlg, idx, str);
3232  }
3233  }
3234 }
3235 
3237 {
3238  switch (msg)
3239  {
3240  case EN_CHANGE:
3241  {
3242  WCHAR buf[10];
3243  LONG val = 0;
3245 
3246  if (GetDlgItemTextW(hDlg, id, buf, ARRAY_SIZE(buf)) != 0)
3247  {
3248  WCHAR *end;
3249  WCHAR decimal = get_decimal_sep();
3250 
3251  val = strtolW(buf, &end, 10);
3252  if(end != buf || *end == decimal)
3253  {
3254  int mult = is_metric(data) ? 100 : 1000;
3255  val *= mult;
3256  if(*end == decimal)
3257  {
3258  while(mult > 1)
3259  {
3260  end++;
3261  mult /= 10;
3262  if(isdigitW(*end))
3263  val += (*end - '0') * mult;
3264  else
3265  break;
3266  }
3267  }
3268  }
3269  }
3270  *value = val;
3271  return;
3272  }
3273 
3274  case EN_KILLFOCUS:
3275  update_margin_edits(hDlg, data, id);
3276  return;
3277  }
3278 }
3279 
3281 {
3282  WCHAR title[256];
3283 
3285  title, ARRAY_SIZE(title)))
3286  SetDlgItemTextW(hDlg, grp4, title);
3287 }
3288 
3290 {
3292  CheckRadioButton(hDlg, rad1, rad2, rad2);
3293  else
3294  CheckRadioButton(hDlg, rad1, rad2, rad1);
3295 }
3296 
3297 /****************************************************************************************
3298  * pagesetup_printer_properties
3299  *
3300  * Handle invocation of the 'Properties' button (not present in the default template).
3301  */
3303 {
3304  HANDLE hprn;
3305  LPWSTR devname;
3306  DEVMODEW *dm;
3307  LRESULT count;
3308  int i;
3309 
3310  devname = pagesetup_get_devname(data);
3311 
3312  if (!OpenPrinterW(devname, &hprn, NULL))
3313  {
3314  FIXME("Call to OpenPrinter did not succeed!\n");
3315  pagesetup_release_a_devname(data, devname);
3316  return;
3317  }
3318 
3319  dm = pagesetup_get_devmode(data);
3320  DocumentPropertiesW(hDlg, hprn, devname, dm, dm, DM_IN_BUFFER | DM_OUT_BUFFER | DM_IN_PROMPT);
3321  pagesetup_set_devmode(data, dm);
3322  pagesetup_release_devmode(data, dm);
3323  pagesetup_release_a_devname(data, devname);
3324  ClosePrinter(hprn);
3325 
3326  /* Changing paper */
3329 
3330  /* Changing paper preview */
3332 
3333  /* Selecting paper in combo */
3334  count = SendDlgItemMessageW(hDlg, cmb2, CB_GETCOUNT, 0, 0);
3335  if(count != CB_ERR)
3336  {
3337  WORD paperword = pagesetup_get_papersize(data);
3338  for(i = 0; i < count; i++)
3339  {
3340  if(SendDlgItemMessageW(hDlg, cmb2, CB_GETITEMDATA, i, 0) == paperword) {
3341  SendDlgItemMessageW(hDlg, cmb2, CB_SETCURSEL, i, 0);
3342  break;
3343  }
3344  }
3345  }
3346 }
3347 
3348 /********************************************************************************
3349  * pagesetup_wm_command
3350  * process WM_COMMAND message for PageSetupDlg
3351  *
3352  * PARAMS
3353  * hDlg [in] Main dialog HANDLE
3354  * wParam [in] WM_COMMAND wParam
3355  * lParam [in] WM_COMMAND lParam
3356  * pda [in/out] ptr to PageSetupDataA
3357  */
3358 
3360 {
3361  WORD msg = HIWORD(wParam);
3362  WORD id = LOWORD(wParam);
3363 
3364  TRACE("loword (lparam) %d, wparam 0x%lx, lparam %08lx\n",
3365  LOWORD(lParam),wParam,lParam);
3366  switch (id) {
3367  case IDOK:
3368  EndDialog(hDlg, TRUE);
3369  return TRUE ;
3370 
3371  case IDCANCEL:
3372  EndDialog(hDlg, FALSE);
3373  return FALSE ;
3374 
3375  case psh3: /* Printer... */
3376  pagesetup_change_printer_dialog(hDlg, data);
3377  return TRUE;
3378 
3379  case rad1: /* Portrait */
3380  case rad2: /* Landscape */
3381  if((id == rad1 && pagesetup_get_orientation(data) == DMORIENT_LANDSCAPE) ||
3382  (id == rad2 && pagesetup_get_orientation(data) == DMORIENT_PORTRAIT))
3383  {
3386  rotate_rect(pagesetup_get_margin_rect(data), (id == rad2));
3387  update_margin_edits(hDlg, data, 0);
3389  }
3390  break;
3391  case cmb1: /* Printer combo */
3392  if(msg == CBN_SELCHANGE)
3393  {
3394  WCHAR *name;
3395  INT index = SendDlgItemMessageW(hDlg, id, CB_GETCURSEL, 0, 0);
3396  INT length = SendDlgItemMessageW(hDlg, id, CB_GETLBTEXTLEN, index, 0);
3397  name = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(length+1));
3398  SendDlgItemMessageW(hDlg, id, CB_GETLBTEXT, index, (LPARAM)name);
3399  pagesetup_change_printer(name, data);
3400  pagesetup_init_combos(hDlg, data);
3401  HeapFree(GetProcessHeap(),0,name);
3402  }
3403  break;
3404  case cmb2: /* Paper combo */
3405  if(msg == CBN_SELCHANGE)
3406  {
3407  DWORD paperword = SendDlgItemMessageW(hDlg, cmb2, CB_GETITEMDATA,
3408  SendDlgItemMessageW(hDlg, cmb2, CB_GETCURSEL, 0, 0), 0);
3409  if (paperword != CB_ERR)
3410  {
3411  pagesetup_set_papersize(data, paperword);
3414  } else
3415  FIXME("could not get dialog text for papersize cmbbox?\n");
3416  }
3417  break;
3418  case cmb3: /* Paper Source */
3419  if(msg == CBN_SELCHANGE)
3420  {
3422  SendDlgItemMessageW(hDlg, cmb3, CB_GETCURSEL, 0, 0), 0);
3423  pagesetup_set_defaultsource(data, source);
3424  }
3425  break;
3426  case psh2: /* Printer Properties button */
3427  pagesetup_printer_properties(hDlg, data);
3428  break;
3429  case edt4:
3430  case edt5:
3431  case edt6:
3432  case edt7:
3433  margin_edit_notification(hDlg, data, msg, id);
3434  break;
3435  }
3437  return FALSE;
3438 }
3439 
3440 /***********************************************************************
3441  * default_page_paint_hook
3442  * Default hook paint procedure that receives WM_PSD_* messages from the dialog box
3443  * whenever the sample page is redrawn.
3444  */
3446  const pagesetup_data *data)
3447 {
3448  LPRECT lprc = (LPRECT) lParam;
3449  HDC hdc = (HDC) wParam;
3450  HPEN hpen, holdpen;
3451  LOGFONTW lf;
3452  HFONT hfont, holdfont;
3453  INT oldbkmode;
3454  TRACE("uMsg: WM_USER+%d\n",uMsg-WM_USER);
3455  /* Call user paint hook if enable */
3457  if (pagesetup_get_hook(data, page_paint_hook)(hwndDlg, uMsg, wParam, lParam))
3458  return TRUE;
3459 
3460  switch (uMsg) {
3461  /* LPPAGESETUPDLG in lParam */
3462  case WM_PSD_PAGESETUPDLG:
3463  /* Inform about the sample page rectangle */
3464  case WM_PSD_FULLPAGERECT:
3465  /* Inform about the margin rectangle */
3466  case WM_PSD_MINMARGINRECT:
3467  return FALSE;
3468 
3469  /* Draw dashed rectangle showing margins */
3470  case WM_PSD_MARGINRECT:
3472  holdpen = SelectObject(hdc, hpen);
3473  Rectangle(hdc, lprc->left, lprc->top, lprc->right, lprc->bottom);
3474  DeleteObject(SelectObject(hdc, holdpen));
3475  return TRUE;
3476  /* Draw the fake document */
3477  case WM_PSD_GREEKTEXTRECT:
3478  /* select a nice scalable font, because we want the text really small */
3479  SystemParametersInfoW(SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, 0);
3480  lf.lfHeight = 6; /* value chosen based on visual effect */
3481  hfont = CreateFontIndirectW(&lf);
3482  holdfont = SelectObject(hdc, hfont);
3483 
3484  /* if text not loaded, then do so now */
3485  if (wszFakeDocumentText[0] == '\0')
3490 
3491  oldbkmode = SetBkMode(hdc, TRANSPARENT);
3493  SetBkMode(hdc, oldbkmode);
3494 
3495  DeleteObject(SelectObject(hdc, holdfont));
3496  return TRUE;
3497 
3498  /* Envelope stamp */
3499  case WM_PSD_ENVSTAMPRECT:
3500  /* Return address */
3501  case WM_PSD_YAFULLPAGERECT:
3502  FIXME("envelope/stamp is not implemented\n");
3503  return FALSE;
3504  default:
3505  FIXME("Unknown message %x\n",uMsg);
3506  return FALSE;
3507  }
3508  return TRUE;
3509 }
3510 
3511 /***********************************************************************
3512  * PagePaintProc
3513  * The main paint procedure for the PageSetupDlg function.
3514  * The Page Setup dialog box includes an image of a sample page that shows how
3515  * the user's selections affect the appearance of the printed output.
3516  * The image consists of a rectangle that represents the selected paper
3517  * or envelope type, with a dotted-line rectangle representing
3518  * the current margins, and partial (Greek text) characters
3519  * to show how text looks on the printed page.
3520  *
3521  * The following messages in the order sends to user hook procedure:
3522  * WM_PSD_PAGESETUPDLG Draw the contents of the sample page
3523  * WM_PSD_FULLPAGERECT Inform about the bounding rectangle
3524  * WM_PSD_MINMARGINRECT Inform about the margin rectangle (min margin?)
3525  * WM_PSD_MARGINRECT Draw the margin rectangle
3526  * WM_PSD_GREEKTEXTRECT Draw the Greek text inside the margin rectangle
3527  * If any of first three messages returns TRUE, painting done.
3528  *
3529  * PARAMS:
3530  * hWnd [in] Handle to the Page Setup dialog box
3531  * uMsg [in] Received message
3532  *
3533  * TODO:
3534  * WM_PSD_ENVSTAMPRECT Draw in the envelope-stamp rectangle (for envelopes only)
3535  * WM_PSD_YAFULLPAGERECT Draw the return address portion (for envelopes and other paper sizes)
3536  *
3537  * RETURNS:
3538  * FALSE if all done correctly
3539  *
3540  */
3541 
3542 
3543 static LRESULT CALLBACK
3545 {
3546  PAINTSTRUCT ps;
3547  RECT rcClient, rcMargin;
3548  HPEN hpen, holdpen;
3549  HDC hdc;
3550  HBRUSH hbrush, holdbrush;
3552  int papersize=0, orientation=0; /* FIXME: set these values for the user paint hook */
3553  double scalx, scaly;
3554 
3555  if (uMsg != WM_PAINT)
3556  return CallWindowProcA(lpfnStaticWndProc, hWnd, uMsg, wParam, lParam);
3557 
3558  /* Processing WM_PAINT message */
3559  data = GetPropW(hWnd, pagesetupdlg_prop);
3560  if (!data) {
3561  WARN("__WINE_PAGESETUPDLGDATA prop not set?\n");
3562  return FALSE;
3563  }
3564  if (default_page_paint_hook(hWnd, WM_PSD_PAGESETUPDLG, MAKELONG(papersize, orientation),
3565  pagesetup_get_dlg_struct(data), data))
3566  return FALSE;
3567 
3568  hdc = BeginPaint(hWnd, &ps);
3569  GetClientRect(hWnd, &rcClient);
3570 
3571  scalx = rcClient.right / (double)pagesetup_get_papersize_pt(data)->x;
3572  scaly = rcClient.bottom / (double)pagesetup_get_papersize_pt(data)->y;
3573  rcMargin = rcClient;
3574 
3575  rcMargin.left += pagesetup_get_margin_rect(data)->left * scalx;
3576  rcMargin.top += pagesetup_get_margin_rect(data)->top * scaly;
3577  rcMargin.right -= pagesetup_get_margin_rect(data)->right * scalx;
3578  rcMargin.bottom -= pagesetup_get_margin_rect(data)->bottom * scaly;
3579 
3580  /* if the space is too small then we make sure to not draw anything */
3581  rcMargin.left = min(rcMargin.left, rcMargin.right);
3582  rcMargin.top = min(rcMargin.top, rcMargin.bottom);
3583 
3584  if (!default_page_paint_hook(hWnd, WM_PSD_FULLPAGERECT, (WPARAM)hdc, (LPARAM)&rcClient, data) &&
3585  !default_page_paint_hook(hWnd, WM_PSD_MINMARGINRECT, (WPARAM)hdc, (LPARAM)&rcMargin, data) )
3586  {
3587  /* fill background */
3589  FillRect(hdc, &rcClient, hbrush);
3590  holdbrush = SelectObject(hdc, hbrush);
3591 
3593  holdpen = SelectObject(hdc, hpen);
3594 
3595  /* paint left edge */
3596  MoveToEx(hdc, rcClient.left, rcClient.top, NULL);
3597  LineTo(hdc, rcClient.left, rcClient.bottom-1);
3598 
3599  /* paint top edge */
3600  MoveToEx(hdc, rcClient.left, rcClient.top, NULL);
3601  LineTo(hdc, rcClient.right, rcClient.top);
3602 
3604  DeleteObject(SelectObject(hdc, hpen));
3605 
3606  /* paint right edge */
3607  MoveToEx(hdc, rcClient.right-1, rcClient.top, NULL);
3608  LineTo(hdc, rcClient.right-1, rcClient.bottom);
3609 
3610  /* paint bottom edge */
3611  MoveToEx(hdc, rcClient.left, rcClient.bottom-1, NULL);
3612  LineTo(hdc, rcClient.right, rcClient.bottom-1);
3613 
3614  DeleteObject(SelectObject(hdc, holdpen));
3615  DeleteObject(SelectObject(hdc, holdbrush));
3616 
3617  default_page_paint_hook(hWnd, WM_PSD_MARGINRECT, (WPARAM)hdc, (LPARAM)&rcMargin, data);
3618 
3619  /* give text a bit of a space from the frame */
3620  InflateRect(&rcMargin, -2, -2);
3621 
3622  /* if the space is too small then we make sure to not draw anything */
3623  rcMargin.left = min(rcMargin.left, rcMargin.right);
3624  rcMargin.top = min(rcMargin.top, rcMargin.bottom);
3625 
3626  default_page_paint_hook(hWnd, WM_PSD_GREEKTEXTRECT, (WPARAM)hdc, (LPARAM)&rcMargin, data);
3627  }
3628 
3629  EndPaint(hWnd, &ps);
3630  return FALSE;
3631 }
3632 
3633 /*******************************************************
3634  * The margin edit controls are subclassed to filter
3635  * anything other than numbers and the decimal separator.
3636  */
3638 {
3639  if (msg == WM_CHAR)
3640  {
3641  WCHAR decimal = get_decimal_sep();
3642  WCHAR wc = (WCHAR)wparam;
3643  if(!isdigitW(wc) && wc != decimal && wc != VK_BACK) return 0;
3644  }
3645  return CallWindowProcW(edit_wndproc, hwnd, msg, wparam, lparam);
3646 }
3647 
3648 static void subclass_margin_edits(HWND hDlg)
3649 {
3650  int id;
3651  WNDPROC old_proc;
3652 
3653  for(id = edt4; id <= edt7; id++)
3654  {
3655  old_proc = (WNDPROC)SetWindowLongPtrW(GetDlgItem(hDlg, id),
3656  GWLP_WNDPROC,
3659  }
3660 }
3661 
3662 /***********************************************************************
3663  * pagesetup_dlg_proc
3664  *
3665  * Message handler for PageSetupDlg
3666  */
3668 {
3670  INT_PTR res = FALSE;
3671  HWND hDrawWnd;
3672 
3673  if (uMsg == WM_INITDIALOG) { /*Init dialog*/
3674  data = (pagesetup_data *)lParam;
3675  data->hDlg = hDlg;
3676 
3677  hDrawWnd = GetDlgItem(hDlg, rct1);
3678  TRACE("set property to %p\n", data);
3679  SetPropW(hDlg, pagesetupdlg_prop, data);
3680  SetPropW(hDrawWnd, pagesetupdlg_prop, data);
3681  GetWindowRect(hDrawWnd, &data->rtDrawRect); /* Calculating rect in client coordinates where paper draws */
3682  MapWindowPoints( 0, hDlg, (LPPOINT)&data->rtDrawRect, 2 );
3684  hDrawWnd,
3685  GWLP_WNDPROC,
3687 
3688  /* FIXME: Paint hook. Must it be at begin of initialization or at end? */
3689  res = TRUE;
3691  {
3692  if (!pagesetup_get_hook(data, page_setup_hook)(hDlg, uMsg, wParam,
3693  pagesetup_get_dlg_struct(data)))
3694  FIXME("Setup page hook failed?\n");
3695  }
3696 
3697  /* if printer button disabled */
3699  EnableWindow(GetDlgItem(hDlg, psh3), FALSE);
3700  /* if margin edit boxes disabled */
3702  {
3703  EnableWindow(GetDlgItem(hDlg, edt4), FALSE);
3704  EnableWindow(GetDlgItem(hDlg, edt5), FALSE);
3705  EnableWindow(GetDlgItem(hDlg, edt6), FALSE);
3706  EnableWindow(GetDlgItem(hDlg, edt7), FALSE);
3707  }
3708 
3709  /* Set orientation radiobuttons properly */
3711 
3712  /* if orientation disabled */
3714  {
3717  }
3718 
3719  /* We fill them out enabled or not */
3720  if (!(pagesetup_get_flags(data) & PSD_MARGINS))
3721  {
3722  /* default is 1 inch */
3723  LONG size = thousandths_inch_to_size(data, 1000);
3724  SetRect(pagesetup_get_margin_rect(data), size, size, size, size);
3725  }
3726  update_margin_edits(hDlg, data, 0);
3727  subclass_margin_edits(hDlg);
3728  set_margin_groupbox_title(hDlg, data);
3729 
3730  /* if paper disabled */
3732  {
3735  }
3736 
3737  /* filling combos: printer, paper, source. selecting current printer (from DEVMODEA) */
3738  pagesetup_init_combos(hDlg, data);
3740  pagesetup_set_defaultsource(data, DMBIN_FORMSOURCE); /* FIXME: This is the auto select bin. Is this correct? */
3741 
3742  /* Drawing paper prev */
3744  return TRUE;
3745  } else {
3746  data = GetPropW(hDlg, pagesetupdlg_prop);
3747  if (!data)
3748  {
3749  WARN("__WINE_PAGESETUPDLGDATA prop not set?\n");
3750  return FALSE;
3751  }
3753  {
3754  res = pagesetup_get_hook(data, page_setup_hook)(hDlg, uMsg, wParam, lParam);
3755  if (res) return res;
3756  }
3757  }
3758  switch (uMsg) {
3759  case WM_COMMAND:
3760  return pagesetup_wm_command(hDlg, wParam, lParam, data);
3761  }
3762  return FALSE;
3763 }
3764 
3766 {
3767  WCHAR *name = NULL;
3768  DWORD len = 0;
3769 
3770  GetDefaultPrinterW(NULL, &len);
3771  if(len)
3772  {
3773  name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3774  GetDefaultPrinterW(name, &len);
3775  }
3776  return name;
3777 }
3778 
3780 {
3781  if(TRACE_ON(commdlg))
3782  {
3783  char flagstr[1000] = "";
3784  const struct pd_flags *pflag = psd_flags;
3785  for( ; pflag->name; pflag++)
3786  {
3787  if(pagesetup_get_flags(data) & pflag->flag)
3788  {
3789  strcat(flagstr, pflag->name);
3790  strcat(flagstr, "|");
3791  }
3792  }
3793  TRACE("%s: (%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
3794  "hinst %p, flags %08x (%s)\n",
3795  data->unicode ? "unicode" : "ansi",
3796  data->u.dlgw, data->u.dlgw->hwndOwner, data->u.dlgw->hDevMode,
3797  data->u.dlgw->hDevNames, data->u.dlgw->hInstance,
3798  pagesetup_get_flags(data), flagstr);
3799  }
3800 }
3801 
3803 {
3804  HRSRC res;
3805  HGLOBAL tmpl_handle;
3806 
3808  {
3809  tmpl_handle = data->u.dlgw->hPageSetupTemplate;
3810  }
3812  {
3813  if(data->unicode)
3814  res = FindResourceW(data->u.dlgw->hInstance,
3816  else
3817  res = FindResourceA(data->u.dlga->hInstance,
3818  data->u.dlga->lpPageSetupTemplateName, (LPSTR)RT_DIALOG);
3819  tmpl_handle = LoadResource(data->u.dlgw->hInstance, res);
3820  }
3821  else
3822  {
3823  res = FindResourceW(COMDLG32_hInstance, MAKEINTRESOURCEW(PAGESETUPDLGORD),
3824  (LPWSTR)RT_DIALOG);
3825  tmpl_handle = LoadResource(COMDLG32_hInstance, res);
3826  }
3827  return LockResource(tmpl_handle);
3828 }
3829 
3831 {
3832  BOOL ret;
3833  void *tmpl;
3834 
3835  if(!pagesetup_get_dlg_struct(data))
3836  {
3838  return FALSE;
3839  }
3840 
3842 
3843  if(data->u.dlgw->lStructSize != sizeof(PAGESETUPDLGW))
3844  {
3846  return FALSE;
3847  }
3848 
3851  {
3853  return FALSE;
3854  }
3855 
3857  data->u.dlgw->Flags |= is_default_metric() ?
3859 
3860  if (!data->u.dlgw->hDevMode || !data->u.dlgw->hDevNames)
3861  {
3862  WCHAR *def = get_default_printer();
3863  if(!def)
3864  {
3865  if (!(pagesetup_get_flags(data) & PSD_NOWARNING))
3866  {
3867  WCHAR errstr[256];
3869  MessageBoxW(data->u.dlgw->hwndOwner, errstr, 0, MB_OK | MB_ICONERROR);
3870  }
3872  return FALSE;
3873  }
3874  pagesetup_change_printer(def, data);
3875  HeapFree(GetProcessHeap(), 0, def);
3876  }
3877 
3879  {
3881  return TRUE;
3882  }
3883 
3884  tmpl = pagesetup_get_template(data);
3885 
3886  ret = DialogBoxIndirectParamW(data->u.dlgw->hInstance, tmpl,
3887  data->u.dlgw->hwndOwner,
3888  pagesetup_dlg_proc, (LPARAM)data) > 0;
3889  return ret;
3890 }
3891 
3892 /***********************************************************************
3893  * PageSetupDlgA (COMDLG32.@)
3894  *
3895  * Displays the PAGE SETUP dialog box, which enables the user to specify
3896  * specific properties of a printed page such as
3897  * size, source, orientation and the width of the page margins.
3898  *
3899  * PARAMS
3900  * setupdlg [IO] PAGESETUPDLGA struct
3901  *
3902  * RETURNS
3903  * TRUE if the user pressed the OK button
3904  * FALSE if the user cancelled the window or an error occurred
3905  *
3906  * NOTES
3907  * The values of hDevMode and hDevNames are filled on output and can be
3908  * changed in PAGESETUPDLG when they are passed in PageSetupDlg.
3909  *
3910  */
3912 {
3914 
3915  data.unicode = FALSE;
3916  data.u.dlga = setupdlg;
3917 
3918  return pagesetup_common(&data);
3919 }
3920 
3921 /***********************************************************************
3922  * PageSetupDlgW (COMDLG32.@)
3923  *
3924  * See PageSetupDlgA.
3925  */
3927 {
3929 
3930  data.unicode = TRUE;
3931  data.u.dlgw = setupdlg;
3932 
3933  return pagesetup_common(&data);
3934 }
3935 
3936 static void pdlgex_to_pdlg(const PRINTDLGEXW *pdlgex, PRINTDLGW *pdlg)
3937 {
3938  pdlg->lStructSize = sizeof(*pdlg);
3939  pdlg->hwndOwner = pdlgex->hwndOwner;
3940  pdlg->hDevMode = pdlgex->hDevMode;
3941  pdlg->hDevNames = pdlgex->hDevNames;
3942  pdlg->hDC = pdlgex->hDC;
3943  pdlg->Flags = pdlgex->Flags;
3944  if ((pdlgex->Flags & PD_NOPAGENUMS) || !pdlgex->nPageRanges || !pdlgex->lpPageRanges)
3945  {
3946  pdlg->nFromPage = 0;
3947  pdlg->nToPage = 65534;
3948  }
3949  else
3950  {
3951  pdlg->nFromPage = pdlgex->lpPageRanges[0].nFromPage;
3952  pdlg->nToPage = pdlgex->lpPageRanges[0].nToPage;
3953  }
3954  pdlg->nMinPage = pdlgex->nMinPage;
3955  pdlg->nMaxPage = pdlgex->nMaxPage;
3956  pdlg->nCopies = pdlgex->nCopies;
3957  pdlg->hInstance = pdlgex->hInstance;
3958  pdlg->lCustData = 0;
3959  pdlg->lpfnPrintHook = NULL;
3960  pdlg->lpfnSetupHook = NULL;
3961  pdlg->lpPrintTemplateName = pdlgex->lpPrintTemplateName;
3962  pdlg->lpSetupTemplateName = NULL;
3963  pdlg->hPrintTemplate = NULL;
3964  pdlg->hSetupTemplate = NULL;
3965 }
3966 
3967 /* Only copy fields that are supposed to be changed. */
3968 static void pdlg_to_pdlgex(const PRINTDLGW *pdlg, PRINTDLGEXW *pdlgex)
3969 {
3970  pdlgex->hDevMode = pdlg->hDevMode;
3971  pdlgex->hDevNames = pdlg->hDevNames;
3972  pdlgex->hDC = pdlg->hDC;
3973  if (!(pdlgex->Flags & PD_NOPAGENUMS) && pdlgex->nPageRanges && pdlgex->lpPageRanges)
3974  {
3975  pdlgex->lpPageRanges[0].nFromPage = pdlg->nFromPage;
3976  pdlgex->lpPageRanges[0].nToPage = pdlg->nToPage;
3977  }
3978  pdlgex->nMinPage = pdlg->nMinPage;
3979  pdlgex->nMaxPage = pdlg->nMaxPage;
3980  pdlgex->nCopies = pdlg->nCopies;
3981 }
3982 
3984 {
3985  IPrintDialogCallback *callback;
3987 };
3988 
3990 {
3991  if (msg == WM_INITDIALOG)
3992  {
3993  PRINTDLGW *pd = (PRINTDLGW *)lp;
3994  struct callback_data *cb = (struct callback_data *)pd->lCustData;
3995 
3996  if (cb->callback)
3997  {
3998  cb->callback->lpVtbl->SelectionChange(cb->callback);
3999  cb->callback->lpVtbl->InitDone(cb->callback);
4000  }
4001  }
4002  else
4003  {
4004 /* FIXME: store interface pointer somewhere in window properties and call it
4005  HRESULT hres;
4006  cb->callback->lpVtbl->HandleMessage(cb->callback, hwnd, msg, wp, lp, &hres);
4007 */
4008  }
4009 
4010  return 0;
4011 }
4012 
4013 /***********************************************************************
4014  * PrintDlgExA (COMDLG32.@)
4015  *
4016  * See PrintDlgExW.
4017  *
4018  * BUGS
4019  * Only a Stub
4020  *
4021  */
4022 HRESULT WINAPI PrintDlgExA(LPPRINTDLGEXA lppd)
4023 {
4025  DRIVER_INFO_3A *dbuf;
4026  DEVMODEA *dm;
4027  HRESULT hr = S_OK;
4028  HANDLE hprn;
4029 
4030  if ((lppd == NULL) || (lppd->lStructSize != sizeof(PRINTDLGEXA)))
4031  return E_INVALIDARG;
4032 
4033  if (!IsWindow(lppd->hwndOwner))
4034  return E_HANDLE;
4035 
4036  if (lppd->nStartPage != START_PAGE_GENERAL)
4037  {
4038  if (!lppd->nPropertyPages)
4039  return E_INVALIDARG;
4040 
4041  FIXME("custom property sheets (%d at %p) not supported\n", lppd->nPropertyPages, lppd->lphPropertyPages);
4042  }
4043 
4044  /* Use PD_NOPAGENUMS or set nMaxPageRanges and lpPageRanges */
4045  if (!(lppd->Flags & PD_NOPAGENUMS) && (!lppd->nMaxPageRanges || !lppd->lpPageRanges))
4046  {
4047  return E_INVALIDARG;
4048  }
4049 
4050  if (lppd->Flags & PD_RETURNDEFAULT)
4051  {
4052  if (lppd->hDevMode || lppd->hDevNames)
4053  {
4054  WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
4056  return E_INVALIDARG;
4057  }
4058  if (!PRINTDLG_OpenDefaultPrinter(&hprn))
4059  {
4060  WARN("Can't find default printer\n");
4062  return E_FAIL;
4063  }
4064 
4065  pbuf = get_printer_infoA(hprn);
4066  if (!pbuf)
4067  {
4068  ClosePrinter(hprn);
4069  return E_FAIL;
4070  }
4071 
4072  dbuf = get_driver_infoA(hprn);
4073  if (!dbuf)
4074  {
4075  HeapFree(GetProcessHeap(), 0, pbuf);
4077  ClosePrinter(hprn);
4078  return E_FAIL;
4079  }
4080  dm = pbuf->pDevMode;
4081  }
4082  else
4083  {
4084  PRINTDLGA pdlg;
4085  struct callback_data cb_data = { 0 };
4086 
4087  FIXME("(%p) semi-stub\n", lppd);
4088 
4089  if (lppd->lpCallback)
4090  {
4091  IUnknown_QueryInterface((IUnknown *)lppd->lpCallback, &IID_IPrintDialogCallback, (void **)&cb_data.callback);
4092  IUnknown_QueryInterface((IUnknown *)lppd->lpCallback, &IID_IObjectWithSite, (void **)&cb_data.object);
4093  }
4094 
4095  /*
4096  * PRINTDLGEXA/W and PRINTDLGA/W layout is the same for A and W variants.
4097  */
4098  pdlgex_to_pdlg((const PRINTDLGEXW *)lppd, (PRINTDLGW *)&pdlg);
4099  pdlg.Flags |= PD_ENABLEPRINTHOOK;
4101  pdlg.lCustData = (LPARAM)&cb_data;
4102 
4103  if (PrintDlgA(&pdlg))
4104  {
4105  pdlg_to_pdlgex((const PRINTDLGW *)&pdlg, (PRINTDLGEXW *)lppd);
4106  lppd->dwResultAction = PD_RESULT_PRINT;
4107  }
4108  else
4109  lppd->dwResultAction = PD_RESULT_CANCEL;
4110 
4111  if (cb_data.callback)
4112  cb_data.callback->lpVtbl->Release(cb_data.callback);
4113  if (cb_data.object)
4114  cb_data.object->lpVtbl->Release(cb_data.object);
4115 
4116  return S_OK;
4117  }
4118 
4119  ClosePrinter(hprn);
4120 
4121  PRINTDLG_CreateDevNames(&(lppd->hDevNames), dbuf->pDriverPath, pbuf->pPrinterName, pbuf->pPortName);
4122  if (!lppd->hDevNames)
4123  hr = E_FAIL;
4124 
4125  lppd->hDevMode = update_devmode_handleA(lppd->hDevMode, dm);
4126  if (hr == S_OK && lppd->hDevMode) {
4127  if (lppd->Flags & PD_RETURNDC) {
4128  lppd->hDC = CreateDCA(dbuf->pDriverPath, pbuf->pPrinterName, pbuf->pPortName, dm);
4129  if (!lppd->hDC)
4130  hr = E_FAIL;
4131  }
4132  else if (lppd->Flags & PD_RETURNIC) {
4133  lppd->hDC = CreateICA(dbuf->pDriverPath, pbuf->pPrinterName, pbuf->pPortName, dm);
4134  if (!lppd->hDC)
4135  hr = E_FAIL;
4136  }
4137  }
4138  else
4139  hr = E_FAIL;
4140 
4141  HeapFree(GetProcessHeap(), 0, pbuf);
4142  HeapFree(GetProcessHeap(), 0, dbuf);
4143 
4144  return hr;
4145 }
4146 
4147 /***********************************************************************
4148  * PrintDlgExW (COMDLG32.@)
4149  *
4150  * Display the property sheet style PRINT dialog box
4151  *
4152  * PARAMS
4153  * lppd [IO] ptr to PRINTDLGEX struct
4154  *
4155  * RETURNS
4156  * Success: S_OK
4157  * Failure: One of the following COM error codes:
4158  * E_OUTOFMEMORY Insufficient memory.
4159  * E_INVALIDARG One or more arguments are invalid.
4160  * E_POINTER Invalid pointer.
4161  * E_HANDLE Invalid handle.
4162  * E_FAIL Unspecified error.
4163  *
4164  * NOTES
4165  * This Dialog enables the user to specify specific properties of the print job.
4166  * The property sheet can also have additional application-specific and
4167  * driver-specific property pages.
4168  *
4169  * BUGS
4170  * Not fully implemented
4171  *
4172  */
4173 HRESULT WINAPI PrintDlgExW(LPPRINTDLGEXW lppd)
4174 {
4176  DRIVER_INFO_3W *dbuf;
4177  DEVMODEW *dm;
4178  HRESULT hr = S_OK;
4179  HANDLE hprn;
4180 
4181  if ((lppd == NULL) || (lppd->lStructSize != sizeof(PRINTDLGEXW))) {
4182  return E_INVALIDARG;
4183  }
4184 
4185  if (!IsWindow(lppd->hwndOwner)) {
4186  return E_HANDLE;
4187  }
4188 
4189  if (lppd->nStartPage != START_PAGE_GENERAL)
4190  {
4191  if (!lppd->nPropertyPages)
4192  return E_INVALIDARG;
4193 
4194  FIXME("custom property sheets (%d at %p) not supported\n", lppd->nPropertyPages, lppd->lphPropertyPages);
4195  }
4196 
4197  /* Use PD_NOPAGENUMS or set nMaxPageRanges and lpPageRanges */
4198  if (!(lppd->Flags & PD_NOPAGENUMS) && (!lppd->nMaxPageRanges || !lppd->lpPageRanges))
4199  {
4200  return E_INVALIDARG;
4201  }
4202 
4203  if (lppd->Flags & PD_RETURNDEFAULT) {
4204 
4205  if (lppd->hDevMode || lppd->hDevNames) {
4206  WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
4208  return E_INVALIDARG;
4209  }
4210  if (!PRINTDLG_OpenDefaultPrinter(&hprn)) {
4211  WARN("Can't find default printer\n");
4213  return E_FAIL;
4214  }
4215 
4216  pbuf = get_printer_infoW(hprn);
4217  if (!pbuf)
4218  {
4219  ClosePrinter(hprn);
4220  return E_FAIL;
4221  }
4222 
4223  dbuf = get_driver_infoW(hprn);
4224  if (!dbuf)
4225  {
4226  HeapFree(GetProcessHeap(), 0, pbuf);
4228  ClosePrinter(hprn);
4229  return E_FAIL;
4230  }
4231  dm = pbuf->pDevMode;
4232  }
4233  else
4234  {
4235  PRINTDLGW pdlg;
4236  struct callback_data cb_data = { 0 };
4237 
4238  FIXME("(%p) semi-stub\n", lppd);
4239 
4240  if (lppd->lpCallback)
4241  {
4242  IUnknown_QueryInterface((IUnknown *)lppd->lpCallback, &IID_IPrintDialogCallback, (void **)&cb_data.callback);
4243  IUnknown_QueryInterface((IUnknown *)lppd->lpCallback, &IID_IObjectWithSite, (void **)&cb_data.object);
4244  }
4245 
4246  pdlgex_to_pdlg(lppd, &pdlg);
4247  pdlg.Flags |= PD_ENABLEPRINTHOOK;
4249  pdlg.lCustData = (LPARAM)&cb_data;
4250 
4251  if (PrintDlgW(&pdlg))
4252  {
4253  pdlg_to_pdlgex(&pdlg, lppd);
4254  lppd->dwResultAction = PD_RESULT_PRINT;
4255  }
4256  else
4257  lppd->dwResultAction = PD_RESULT_CANCEL;
4258 
4259  if (cb_data.callback)
4260  cb_data.callback->lpVtbl->Release(cb_data.callback);
4261  if (cb_data.object)
4262  cb_data.object->lpVtbl->Release(cb_data.object);
4263 
4264  return S_OK;
4265  }
4266 
4267  ClosePrinter(hprn);
4268 
4269  PRINTDLG_CreateDevNamesW(&(lppd->hDevNames), dbuf->pDriverPath, pbuf->pPrinterName, pbuf->pPortName);
4270  if (!lppd->hDevNames)
4271  hr = E_FAIL;
4272 
4273  lppd->hDevMode = update_devmode_handleW(lppd->hDevMode, dm);
4274  if (hr == S_OK && lppd->hDevMode) {
4275  if (lppd->Flags & PD_RETURNDC) {
4276  lppd->hDC = CreateDCW(dbuf->pDriverPath, pbuf->pPrinterName, pbuf->pPortName, dm);
4277  if (!lppd->hDC)
4278  hr = E_FAIL;
4279  }
4280  else if (lppd->Flags & PD_RETURNIC) {
4281  lppd->hDC = CreateICW(dbuf->pDriverPath, pbuf->pPrinterName, pbuf->pPortName, dm);
4282  if (!lppd->hDC)
4283  hr = E_FAIL;
4284  }
4285  }
4286  else
4287  hr = E_FAIL;
4288 
4289  HeapFree(GetProcessHeap(), 0, pbuf);
4290  HeapFree(GetProcessHeap(), 0, dbuf);
4291 
4292  return hr;
4293 }
#define PD32_NO_DEVICES
Definition: cdlg.h:61
int WINAPIV wsprintfW(_Out_ LPWSTR, _In_ _Printf_format_string_ LPCWSTR,...)
LPCWSTR lpPageSetupTemplateName
Definition: commdlg.h:461
#define PD_ENABLEPRINTTEMPLATEHANDLE
Definition: commdlg.h:163
HICON hPortraitIcon
Definition: printdlg.c:69
struct tagDEVNAMES * LPDEVNAMES
static LRESULT CALLBACK pagesetup_margin_editproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
Definition: printdlg.c:3637
WINBOOL WINAPI GetPrinterDriverA(HANDLE hPrinter, LPSTR pEnvironment, DWORD Level, LPBYTE pDriverInfo, DWORD cbBuf, LPDWORD pcbNeeded)
Definition: printers.c:507
HANDLE HGLOBAL
Definition: windef.h:243
static const WCHAR pd32_portraitW[]
Definition: printdlg.c:147
static BOOL PRINTDLG_CreateDevNamesW(HGLOBAL *hmem, LPCWSTR DeviceDriverName, LPCWSTR DeviceName, LPCWSTR OutputPort)
Definition: printdlg.c:519
#define HDC
Definition: msvc.h:22
#define DC_BINNAMES
Definition: windef.h:363
#define PD_HIDEPRINTTOFILE
Definition: commdlg.h:168
#define CB_SETITEMDATA
Definition: winuser.h:1927
static void pagesetup_printer_properties(HWND hDlg, pagesetup_data *data)
Definition: printdlg.c:3302
const DOCKBAR PVOID HWND HWND * hwnd
Definition: tooldock.h:22
short dmPrintQuality
Definition: wingdi.h:1557
#define PRINTER_ENUM_CONNECTIONS
Definition: winspool.h:804
static WORD pagesetup_get_papersize(const pagesetup_data *data)
Definition: printdlg.c:2725
BOOL WINAPI CheckDlgButton(_In_ HWND, _In_ int, _In_ UINT)
#define WM_PSD_FULLPAGERECT
Definition: commdlg.h:189
#define CDERR_REGISTERMSGFAIL
Definition: cderr.h:17
static PRINTER_INFO_2W * get_printer_infoW(HANDLE hprn)
Definition: printdlg.c:219
#define DC_PAPERS
Definition: windef.h:353
PWSTR Names[NAMES_COUNT]
static BOOL PRINTDLG_ChangePrinterW(HWND hDlg, WCHAR *name, PRINT_PTRW *PrintStructures)
Definition: printdlg.c:1286
#define LOGPIXELSX
Definition: wingdi.h:716
BOOL WINAPI InflateRect(_Inout_ LPRECT, _In_ int, _In_ int)
static HICON
Definition: imagelist.c:84
#define CB_GETLBTEXTLEN
Definition: winuser.h:1914
UINT WINAPI GetDlgItemTextW(HWND hDlg, int nIDDlgItem, LPWSTR lpString, int nMaxCount)
Definition: dialog.c:2195
unsigned short WORD
Definition: ntddk_ex.h:93
#define PD_NOSELECTION
Definition: commdlg.h:149
Definition: get.c:139
static const char __ms_va_list
Definition: printf.c:70
#define TRUE
Definition: types.h:120
HGLOBAL NTAPI GlobalAlloc(UINT uFlags, SIZE_T dwBytes)
Definition: heapmem.c:368
HPEN WINAPI CreatePen(_In_ int, _In_ int, _In_ COLORREF)
#define IDOK
Definition: winuser.h:824
static POINT * pagesetup_get_papersize_pt(const pagesetup_data *data)
Definit