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