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 if (lppd->Flags & PD_COLLATE) { 1176 SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, IMAGE_ICON, 1177 (LPARAM)PrintStructures->hCollateIcon); 1178 CheckDlgButton(hDlg, chx2, 1); 1179 } else { 1180 SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, IMAGE_ICON, 1181 (LPARAM)PrintStructures->hNoCollateIcon); 1182 CheckDlgButton(hDlg, chx2, 0); 1183 } 1184 1185 if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) { 1186 /* if printer doesn't support it: no Collate */ 1187 if (!(lpdm->dmFields & DM_COLLATE)) { 1188 EnableWindow(GetDlgItem(hDlg, chx2), FALSE); 1189 EnableWindow(GetDlgItem(hDlg, ico3), FALSE); 1190 } 1191 } 1192 1193 /* nCopies */ 1194 { 1195 INT copies; 1196 if (lppd->hDevMode == 0) 1197 copies = lppd->nCopies; 1198 else 1199 copies = lpdm->u1.s1.dmCopies; 1200 if(copies == 0) copies = 1; 1201 else if(copies < 0) copies = MAX_COPIES; 1202 SetDlgItemInt(hDlg, edt3, copies, FALSE); 1203 } 1204 1205 if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) { 1206 /* if printer doesn't support it: no nCopies */ 1207 if (!(lpdm->dmFields & DM_COPIES)) { 1208 EnableWindow(GetDlgItem(hDlg, edt3), FALSE); 1209 EnableWindow(GetDlgItem(hDlg, stc5), FALSE); 1210 } 1211 } 1212 1213 /* print to file */ 1214 CheckDlgButton(hDlg, chx1, (lppd->Flags & PD_PRINTTOFILE) ? 1 : 0); 1215 if (lppd->Flags & PD_DISABLEPRINTTOFILE) 1216 EnableWindow(GetDlgItem(hDlg, chx1), FALSE); 1217 if (lppd->Flags & PD_HIDEPRINTTOFILE) 1218 ShowWindow(GetDlgItem(hDlg, chx1), SW_HIDE); 1219 1220 /* Fill print quality combo, PrintDlg16 */ 1221 if(GetDlgItem(hDlg, cmb1)) 1222 { 1223 DWORD numResolutions = DeviceCapabilitiesA(PrintStructures->lpPrinterInfo->pPrinterName, 1224 PrintStructures->lpPrinterInfo->pPortName, 1225 DC_ENUMRESOLUTIONS, NULL, lpdm); 1226 1227 if(numResolutions != -1) 1228 { 1229 HWND hQuality = GetDlgItem(hDlg, cmb1); 1230 LONG* Resolutions; 1231 char buf[255]; 1232 DWORD i; 1233 int dpiX, dpiY; 1234 HDC hPrinterDC = CreateDCA(PrintStructures->lpPrinterInfo->pDriverName, 1235 PrintStructures->lpPrinterInfo->pPrinterName, 1236 0, lpdm); 1237 1238 Resolutions = HeapAlloc(GetProcessHeap(), 0, numResolutions*sizeof(LONG)*2); 1239 DeviceCapabilitiesA(PrintStructures->lpPrinterInfo->pPrinterName, 1240 PrintStructures->lpPrinterInfo->pPortName, 1241 DC_ENUMRESOLUTIONS, (LPSTR)Resolutions, lpdm); 1242 1243 dpiX = GetDeviceCaps(hPrinterDC, LOGPIXELSX); 1244 dpiY = GetDeviceCaps(hPrinterDC, LOGPIXELSY); 1245 DeleteDC(hPrinterDC); 1246 1247 SendMessageA(hQuality, CB_RESETCONTENT, 0, 0); 1248 for(i = 0; i < (numResolutions * 2); i += 2) 1249 { 1250 BOOL IsDefault = FALSE; 1251 LRESULT Index; 1252 1253 if(Resolutions[i] == Resolutions[i+1]) 1254 { 1255 if(dpiX == Resolutions[i]) 1256 IsDefault = TRUE; 1257 sprintf(buf, "%d dpi", Resolutions[i]); 1258 } else 1259 { 1260 if(dpiX == Resolutions[i] && dpiY == Resolutions[i+1]) 1261 IsDefault = TRUE; 1262 sprintf(buf, "%d dpi x %d dpi", Resolutions[i], Resolutions[i+1]); 1263 } 1264 1265 Index = SendMessageA(hQuality, CB_ADDSTRING, 0, (LPARAM)buf); 1266 1267 if(IsDefault) 1268 SendMessageA(hQuality, CB_SETCURSEL, Index, 0); 1269 1270 SendMessageA(hQuality, CB_SETITEMDATA, Index, MAKELONG(dpiX,dpiY)); 1271 } 1272 HeapFree(GetProcessHeap(), 0, Resolutions); 1273 } 1274 } 1275 } else { /* PD_PRINTSETUP */ 1276 BOOL bPortrait = (lpdm->u1.s1.dmOrientation == DMORIENT_PORTRAIT); 1277 1278 PRINTDLG_SetUpPaperComboBoxA(hDlg, cmb2, 1279 PrintStructures->lpPrinterInfo->pPrinterName, 1280 PrintStructures->lpPrinterInfo->pPortName, 1281 lpdm); 1282 PRINTDLG_SetUpPaperComboBoxA(hDlg, cmb3, 1283 PrintStructures->lpPrinterInfo->pPrinterName, 1284 PrintStructures->lpPrinterInfo->pPortName, 1285 lpdm); 1286 CheckRadioButton(hDlg, rad1, rad2, bPortrait ? rad1: rad2); 1287 SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, IMAGE_ICON, 1288 (LPARAM)(bPortrait ? PrintStructures->hPortraitIcon : 1289 PrintStructures->hLandscapeIcon)); 1290 1291 } 1292 1293 /* help button */ 1294 if ((lppd->Flags & PD_SHOWHELP)==0) { 1295 /* hide if PD_SHOWHELP not specified */ 1296 ShowWindow(GetDlgItem(hDlg, pshHelp), SW_HIDE); 1297 } 1298 return TRUE; 1299 } 1300 1301 static BOOL PRINTDLG_ChangePrinterW(HWND hDlg, WCHAR *name, 1302 PRINT_PTRW *PrintStructures) 1303 { 1304 LPPRINTDLGW lppd = PrintStructures->lpPrintDlg; 1305 LPDEVMODEW lpdm = NULL; 1306 LONG dmSize; 1307 DWORD needed; 1308 HANDLE hprn; 1309 1310 HeapFree(GetProcessHeap(),0, PrintStructures->lpPrinterInfo); 1311 HeapFree(GetProcessHeap(),0, PrintStructures->lpDriverInfo); 1312 if(!OpenPrinterW(name, &hprn, NULL)) { 1313 ERR("Can't open printer %s\n", debugstr_w(name)); 1314 return FALSE; 1315 } 1316 GetPrinterW(hprn, 2, NULL, 0, &needed); 1317 PrintStructures->lpPrinterInfo = HeapAlloc(GetProcessHeap(),0,needed); 1318 GetPrinterW(hprn, 2, (LPBYTE)PrintStructures->lpPrinterInfo, needed, 1319 &needed); 1320 GetPrinterDriverW(hprn, NULL, 3, NULL, 0, &needed); 1321 PrintStructures->lpDriverInfo = HeapAlloc(GetProcessHeap(),0,needed); 1322 if (!GetPrinterDriverW(hprn, NULL, 3, (LPBYTE)PrintStructures->lpDriverInfo, 1323 needed, &needed)) { 1324 ERR("GetPrinterDriverA failed for %s, fix your config!\n",debugstr_w(PrintStructures->lpPrinterInfo->pPrinterName)); 1325 return FALSE; 1326 } 1327 ClosePrinter(hprn); 1328 1329 PRINTDLG_UpdatePrinterInfoTextsW(hDlg, PrintStructures->lpPrinterInfo); 1330 1331 HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode); 1332 PrintStructures->lpDevMode = NULL; 1333 1334 dmSize = DocumentPropertiesW(0, 0, name, NULL, NULL, 0); 1335 if(dmSize == -1) { 1336 ERR("DocumentProperties fails on %s\n", debugstr_w(name)); 1337 return FALSE; 1338 } 1339 PrintStructures->lpDevMode = HeapAlloc(GetProcessHeap(), 0, dmSize); 1340 dmSize = DocumentPropertiesW(0, 0, name, PrintStructures->lpDevMode, NULL, 1341 DM_OUT_BUFFER); 1342 if(lppd->hDevMode && (lpdm = GlobalLock(lppd->hDevMode)) && 1343 !lstrcmpW(lpdm->dmDeviceName, 1344 PrintStructures->lpDevMode->dmDeviceName)) { 1345 /* Supplied devicemode matches current printer so try to use it */ 1346 DocumentPropertiesW(0, 0, name, PrintStructures->lpDevMode, lpdm, 1347 DM_OUT_BUFFER | DM_IN_BUFFER); 1348 } 1349 if(lpdm) 1350 GlobalUnlock(lppd->hDevMode); 1351 1352 lpdm = PrintStructures->lpDevMode; /* use this as a shortcut */ 1353 1354 if(!(lppd->Flags & PD_PRINTSETUP)) { 1355 /* Print range (All/Range/Selection) */ 1356 if(lppd->nFromPage != 0xffff) 1357 SetDlgItemInt(hDlg, edt1, lppd->nFromPage, FALSE); 1358 if(lppd->nToPage != 0xffff) 1359 SetDlgItemInt(hDlg, edt2, lppd->nToPage, FALSE); 1360 1361 CheckRadioButton(hDlg, rad1, rad3, rad1); /* default */ 1362 if (lppd->Flags & PD_NOSELECTION) 1363 EnableWindow(GetDlgItem(hDlg, rad2), FALSE); 1364 else 1365 if (lppd->Flags & PD_SELECTION) 1366 CheckRadioButton(hDlg, rad1, rad3, rad2); 1367 if (lppd->Flags & PD_NOPAGENUMS) { 1368 EnableWindow(GetDlgItem(hDlg, rad3), FALSE); 1369 EnableWindow(GetDlgItem(hDlg, stc2),FALSE); 1370 EnableWindow(GetDlgItem(hDlg, edt1), FALSE); 1371 EnableWindow(GetDlgItem(hDlg, stc3),FALSE); 1372 EnableWindow(GetDlgItem(hDlg, edt2), FALSE); 1373 } else { 1374 if (lppd->Flags & PD_PAGENUMS) 1375 CheckRadioButton(hDlg, rad1, rad3, rad3); 1376 } 1377 1378 /* Collate pages */ 1379 if (lppd->Flags & PD_COLLATE) { 1380 SendDlgItemMessageW(hDlg, ico3, STM_SETIMAGE, IMAGE_ICON, 1381 (LPARAM)PrintStructures->hCollateIcon); 1382 CheckDlgButton(hDlg, chx2, 1); 1383 } else { 1384 SendDlgItemMessageW(hDlg, ico3, STM_SETIMAGE, IMAGE_ICON, 1385 (LPARAM)PrintStructures->hNoCollateIcon); 1386 CheckDlgButton(hDlg, chx2, 0); 1387 } 1388 1389 if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) { 1390 /* if printer doesn't support it: no Collate */ 1391 if (!(lpdm->dmFields & DM_COLLATE)) { 1392 EnableWindow(GetDlgItem(hDlg, chx2), FALSE); 1393 EnableWindow(GetDlgItem(hDlg, ico3), FALSE); 1394 } 1395 } 1396 1397 /* nCopies */ 1398 { 1399 INT copies; 1400 if (lppd->hDevMode == 0) 1401 copies = lppd->nCopies; 1402 else 1403 copies = lpdm->u1.s1.dmCopies; 1404 if(copies == 0) copies = 1; 1405 else if(copies < 0) copies = MAX_COPIES; 1406 SetDlgItemInt(hDlg, edt3, copies, FALSE); 1407 } 1408 1409 if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) { 1410 /* if printer doesn't support it: no nCopies */ 1411 if (!(lpdm->dmFields & DM_COPIES)) { 1412 EnableWindow(GetDlgItem(hDlg, edt3), FALSE); 1413 EnableWindow(GetDlgItem(hDlg, stc5), FALSE); 1414 } 1415 } 1416 1417 /* print to file */ 1418 CheckDlgButton(hDlg, chx1, (lppd->Flags & PD_PRINTTOFILE) ? 1 : 0); 1419 if (lppd->Flags & PD_DISABLEPRINTTOFILE) 1420 EnableWindow(GetDlgItem(hDlg, chx1), FALSE); 1421 if (lppd->Flags & PD_HIDEPRINTTOFILE) 1422 ShowWindow(GetDlgItem(hDlg, chx1), SW_HIDE); 1423 1424 } else { /* PD_PRINTSETUP */ 1425 BOOL bPortrait = (lpdm->u1.s1.dmOrientation == DMORIENT_PORTRAIT); 1426 1427 PRINTDLG_SetUpPaperComboBoxW(hDlg, cmb2, 1428 PrintStructures->lpPrinterInfo->pPrinterName, 1429 PrintStructures->lpPrinterInfo->pPortName, 1430 lpdm); 1431 PRINTDLG_SetUpPaperComboBoxW(hDlg, cmb3, 1432 PrintStructures->lpPrinterInfo->pPrinterName, 1433 PrintStructures->lpPrinterInfo->pPortName, 1434 lpdm); 1435 CheckRadioButton(hDlg, rad1, rad2, bPortrait ? rad1: rad2); 1436 SendDlgItemMessageW(hDlg, ico1, STM_SETIMAGE, IMAGE_ICON, 1437 (LPARAM)(bPortrait ? PrintStructures->hPortraitIcon : 1438 PrintStructures->hLandscapeIcon)); 1439 1440 } 1441 1442 /* help button */ 1443 if ((lppd->Flags & PD_SHOWHELP)==0) { 1444 /* hide if PD_SHOWHELP not specified */ 1445 ShowWindow(GetDlgItem(hDlg, pshHelp), SW_HIDE); 1446 } 1447 return TRUE; 1448 } 1449 1450 /*********************************************************************** 1451 * check_printer_setup [internal] 1452 */ 1453 static LRESULT check_printer_setup(HWND hDlg) 1454 { 1455 DWORD needed,num; 1456 WCHAR resourcestr[256],resultstr[256]; 1457 1458 EnumPrintersW(PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &needed, &num); 1459 if(needed == 0) 1460 { 1461 EnumPrintersW(PRINTER_ENUM_CONNECTIONS, NULL, 2, NULL, 0, &needed, &num); 1462 } 1463 if(needed > 0) 1464 return TRUE; 1465 else 1466 { 1467 LoadStringW(COMDLG32_hInstance, PD32_NO_DEVICES,resultstr, 255); 1468 LoadStringW(COMDLG32_hInstance, PD32_PRINT_TITLE,resourcestr, 255); 1469 MessageBoxW(hDlg, resultstr, resourcestr,MB_OK | MB_ICONWARNING); 1470 return FALSE; 1471 } 1472 } 1473 1474 /*********************************************************************** 1475 * PRINTDLG_WMInitDialog [internal] 1476 */ 1477 static LRESULT PRINTDLG_WMInitDialog(HWND hDlg, 1478 PRINT_PTRA* PrintStructures) 1479 { 1480 LPPRINTDLGA lppd = PrintStructures->lpPrintDlg; 1481 DEVNAMES *pdn; 1482 DEVMODEA *pdm; 1483 char *name = NULL; 1484 UINT comboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4; 1485 1486 /* load Collate ICONs */ 1487 /* We load these with LoadImage because they are not a standard 1488 size and we don't want them rescaled */ 1489 PrintStructures->hCollateIcon = 1490 LoadImageA(COMDLG32_hInstance, "PD32_COLLATE", IMAGE_ICON, 0, 0, 0); 1491 PrintStructures->hNoCollateIcon = 1492 LoadImageA(COMDLG32_hInstance, "PD32_NOCOLLATE", IMAGE_ICON, 0, 0, 0); 1493 1494 /* These can be done with LoadIcon */ 1495 PrintStructures->hPortraitIcon = 1496 LoadIconA(COMDLG32_hInstance, "PD32_PORTRAIT"); 1497 PrintStructures->hLandscapeIcon = 1498 LoadIconA(COMDLG32_hInstance, "PD32_LANDSCAPE"); 1499 1500 /* display the collate/no_collate icon */ 1501 SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, IMAGE_ICON, 1502 (LPARAM)PrintStructures->hNoCollateIcon); 1503 1504 if(PrintStructures->hCollateIcon == 0 || 1505 PrintStructures->hNoCollateIcon == 0 || 1506 PrintStructures->hPortraitIcon == 0 || 1507 PrintStructures->hLandscapeIcon == 0) { 1508 ERR("no icon in resource file\n"); 1509 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE); 1510 EndDialog(hDlg, FALSE); 1511 } 1512 1513 /* 1514 * if lppd->Flags PD_SHOWHELP is specified, a HELPMESGSTRING message 1515 * must be registered and the Help button must be shown. 1516 */ 1517 if (lppd->Flags & PD_SHOWHELP) { 1518 if((PrintStructures->HelpMessageID = 1519 RegisterWindowMessageA(HELPMSGSTRINGA)) == 0) { 1520 COMDLG32_SetCommDlgExtendedError(CDERR_REGISTERMSGFAIL); 1521 return FALSE; 1522 } 1523 } else 1524 PrintStructures->HelpMessageID = 0; 1525 1526 if(!(lppd->Flags &PD_PRINTSETUP)) { 1527 PrintStructures->hwndUpDown = 1528 CreateUpDownControl(WS_CHILD | WS_VISIBLE | WS_BORDER | 1529 UDS_NOTHOUSANDS | UDS_ARROWKEYS | 1530 UDS_ALIGNRIGHT | UDS_SETBUDDYINT, 0, 0, 0, 0, 1531 hDlg, UPDOWN_ID, COMDLG32_hInstance, 1532 GetDlgItem(hDlg, edt3), MAX_COPIES, 1, 1); 1533 } 1534 1535 /* FIXME: I allow more freedom than either Win95 or WinNT, 1536 * which do not agree on what errors should be thrown or not 1537 * in case nToPage or nFromPage is out-of-range. 1538 */ 1539 if (lppd->nMaxPage < lppd->nMinPage) 1540 lppd->nMaxPage = lppd->nMinPage; 1541 if (lppd->nMinPage == lppd->nMaxPage) 1542 lppd->Flags |= PD_NOPAGENUMS; 1543 if (lppd->nToPage < lppd->nMinPage) 1544 lppd->nToPage = lppd->nMinPage; 1545 if (lppd->nToPage > lppd->nMaxPage) 1546 lppd->nToPage = lppd->nMaxPage; 1547 if (lppd->nFromPage < lppd->nMinPage) 1548 lppd->nFromPage = lppd->nMinPage; 1549 if (lppd->nFromPage > lppd->nMaxPage) 1550 lppd->nFromPage = lppd->nMaxPage; 1551 1552 /* if we have the combo box, fill it */ 1553 if (GetDlgItem(hDlg,comboID)) { 1554 /* Fill Combobox 1555 */ 1556 pdn = GlobalLock(lppd->hDevNames); 1557 pdm = GlobalLock(lppd->hDevMode); 1558 if(pdn) 1559 name = (char*)pdn + pdn->wDeviceOffset; 1560 else if(pdm) 1561 name = (char*)pdm->dmDeviceName; 1562 PRINTDLG_SetUpPrinterListComboA(hDlg, comboID, name); 1563 if(pdm) GlobalUnlock(lppd->hDevMode); 1564 if(pdn) GlobalUnlock(lppd->hDevNames); 1565 1566 /* Now find selected printer and update rest of dlg */ 1567 name = HeapAlloc(GetProcessHeap(),0,256); 1568 if (GetDlgItemTextA(hDlg, comboID, name, 255)) 1569 PRINTDLG_ChangePrinterA(hDlg, name, PrintStructures); 1570 HeapFree(GetProcessHeap(),0,name); 1571 } else { 1572 /* else use default printer */ 1573 char name[200]; 1574 DWORD dwBufLen = ARRAY_SIZE(name); 1575 BOOL ret = GetDefaultPrinterA(name, &dwBufLen); 1576 1577 if (ret) 1578 PRINTDLG_ChangePrinterA(hDlg, name, PrintStructures); 1579 else 1580 FIXME("No default printer found, expect problems!\n"); 1581 } 1582 return TRUE; 1583 } 1584 1585 static LRESULT PRINTDLG_WMInitDialogW(HWND hDlg, 1586 PRINT_PTRW* PrintStructures) 1587 { 1588 LPPRINTDLGW lppd = PrintStructures->lpPrintDlg; 1589 DEVNAMES *pdn; 1590 DEVMODEW *pdm; 1591 WCHAR *name = NULL; 1592 UINT comboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4; 1593 1594 /* load Collate ICONs */ 1595 /* We load these with LoadImage because they are not a standard 1596 size and we don't want them rescaled */ 1597 PrintStructures->hCollateIcon = 1598 LoadImageW(COMDLG32_hInstance, pd32_collateW, IMAGE_ICON, 0, 0, 0); 1599 PrintStructures->hNoCollateIcon = 1600 LoadImageW(COMDLG32_hInstance, pd32_nocollateW, IMAGE_ICON, 0, 0, 0); 1601 1602 /* These can be done with LoadIcon */ 1603 PrintStructures->hPortraitIcon = 1604 LoadIconW(COMDLG32_hInstance, pd32_portraitW); 1605 PrintStructures->hLandscapeIcon = 1606 LoadIconW(COMDLG32_hInstance, pd32_landscapeW); 1607 1608 /* display the collate/no_collate icon */ 1609 SendDlgItemMessageW(hDlg, ico3, STM_SETIMAGE, IMAGE_ICON, 1610 (LPARAM)PrintStructures->hNoCollateIcon); 1611 1612 if(PrintStructures->hCollateIcon == 0 || 1613 PrintStructures->hNoCollateIcon == 0 || 1614 PrintStructures->hPortraitIcon == 0 || 1615 PrintStructures->hLandscapeIcon == 0) { 1616 ERR("no icon in resource file\n"); 1617 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE); 1618 EndDialog(hDlg, FALSE); 1619 } 1620 1621 /* 1622 * if lppd->Flags PD_SHOWHELP is specified, a HELPMESGSTRING message 1623 * must be registered and the Help button must be shown. 1624 */ 1625 if (lppd->Flags & PD_SHOWHELP) { 1626 if((PrintStructures->HelpMessageID = 1627 RegisterWindowMessageW(HELPMSGSTRINGW)) == 0) { 1628 COMDLG32_SetCommDlgExtendedError(CDERR_REGISTERMSGFAIL); 1629 return FALSE; 1630 } 1631 } else 1632 PrintStructures->HelpMessageID = 0; 1633 1634 if(!(lppd->Flags &PD_PRINTSETUP)) { 1635 PrintStructures->hwndUpDown = 1636 CreateUpDownControl(WS_CHILD | WS_VISIBLE | WS_BORDER | 1637 UDS_NOTHOUSANDS | UDS_ARROWKEYS | 1638 UDS_ALIGNRIGHT | UDS_SETBUDDYINT, 0, 0, 0, 0, 1639 hDlg, UPDOWN_ID, COMDLG32_hInstance, 1640 GetDlgItem(hDlg, edt3), MAX_COPIES, 1, 1); 1641 } 1642 1643 /* FIXME: I allow more freedom than either Win95 or WinNT, 1644 * which do not agree to what errors should be thrown or not 1645 * in case nToPage or nFromPage is out-of-range. 1646 */ 1647 if (lppd->nMaxPage < lppd->nMinPage) 1648 lppd->nMaxPage = lppd->nMinPage; 1649 if (lppd->nMinPage == lppd->nMaxPage) 1650 lppd->Flags |= PD_NOPAGENUMS; 1651 if (lppd->nToPage < lppd->nMinPage) 1652 lppd->nToPage = lppd->nMinPage; 1653 if (lppd->nToPage > lppd->nMaxPage) 1654 lppd->nToPage = lppd->nMaxPage; 1655 if (lppd->nFromPage < lppd->nMinPage) 1656 lppd->nFromPage = lppd->nMinPage; 1657 if (lppd->nFromPage > lppd->nMaxPage) 1658 lppd->nFromPage = lppd->nMaxPage; 1659 1660 /* if we have the combo box, fill it */ 1661 if (GetDlgItem(hDlg,comboID)) { 1662 /* Fill Combobox 1663 */ 1664 pdn = GlobalLock(lppd->hDevNames); 1665 pdm = GlobalLock(lppd->hDevMode); 1666 if(pdn) 1667 name = (WCHAR*)pdn + pdn->wDeviceOffset; 1668 else if(pdm) 1669 name = pdm->dmDeviceName; 1670 PRINTDLG_SetUpPrinterListComboW(hDlg, comboID, name); 1671 if(pdm) GlobalUnlock(lppd->hDevMode); 1672 if(pdn) GlobalUnlock(lppd->hDevNames); 1673 1674 /* Now find selected printer and update rest of dlg */ 1675 /* ansi is ok here */ 1676 name = HeapAlloc(GetProcessHeap(),0,256*sizeof(WCHAR)); 1677 if (GetDlgItemTextW(hDlg, comboID, name, 255)) 1678 PRINTDLG_ChangePrinterW(hDlg, name, PrintStructures); 1679 HeapFree(GetProcessHeap(),0,name); 1680 } else { 1681 /* else use default printer */ 1682 WCHAR name[200]; 1683 DWORD dwBufLen = ARRAY_SIZE(name); 1684 BOOL ret = GetDefaultPrinterW(name, &dwBufLen); 1685 1686 if (ret) 1687 PRINTDLG_ChangePrinterW(hDlg, name, PrintStructures); 1688 else 1689 FIXME("No default printer found, expect problems!\n"); 1690 } 1691 return TRUE; 1692 } 1693 1694 /*********************************************************************** 1695 * PRINTDLG_WMCommand [internal] 1696 */ 1697 static LRESULT PRINTDLG_WMCommandA(HWND hDlg, WPARAM wParam, 1698 PRINT_PTRA* PrintStructures) 1699 { 1700 LPPRINTDLGA lppd = PrintStructures->lpPrintDlg; 1701 UINT PrinterComboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4; 1702 LPDEVMODEA lpdm = PrintStructures->lpDevMode; 1703 1704 switch (LOWORD(wParam)) { 1705 case IDOK: 1706 TRACE(" OK button was hit\n"); 1707 if (!PRINTDLG_UpdatePrintDlgA(hDlg, PrintStructures)) { 1708 FIXME("Update printdlg was not successful!\n"); 1709 return(FALSE); 1710 } 1711 EndDialog(hDlg, TRUE); 1712 return(TRUE); 1713 1714 case IDCANCEL: 1715 TRACE(" CANCEL button was hit\n"); 1716 EndDialog(hDlg, FALSE); 1717 return(FALSE); 1718 1719 case pshHelp: 1720 TRACE(" HELP button was hit\n"); 1721 SendMessageA(lppd->hwndOwner, PrintStructures->HelpMessageID, 1722 (WPARAM) hDlg, (LPARAM) lppd); 1723 break; 1724 1725 case chx2: /* collate pages checkbox */ 1726 if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED) 1727 SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, IMAGE_ICON, 1728 (LPARAM)PrintStructures->hCollateIcon); 1729 else 1730 SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, IMAGE_ICON, 1731 (LPARAM)PrintStructures->hNoCollateIcon); 1732 break; 1733 case edt1: /* from page nr editbox */ 1734 case edt2: /* to page nr editbox */ 1735 if (HIWORD(wParam)==EN_CHANGE) { 1736 WORD nToPage; 1737 WORD nFromPage; 1738 nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE); 1739 nToPage = GetDlgItemInt(hDlg, edt2, NULL, FALSE); 1740 if (nFromPage != lppd->nFromPage || nToPage != lppd->nToPage) 1741 CheckRadioButton(hDlg, rad1, rad3, rad3); 1742 } 1743 break; 1744 1745 case edt3: 1746 if(HIWORD(wParam) == EN_CHANGE) { 1747 INT copies = GetDlgItemInt(hDlg, edt3, NULL, FALSE); 1748 if(copies <= 1) 1749 EnableWindow(GetDlgItem(hDlg, chx2), FALSE); 1750 else 1751 EnableWindow(GetDlgItem(hDlg, chx2), TRUE); 1752 } 1753 break; 1754 1755 case psh2: /* Properties button */ 1756 { 1757 HANDLE hPrinter; 1758 char PrinterName[256]; 1759 1760 GetDlgItemTextA(hDlg, PrinterComboID, PrinterName, 255); 1761 if (!OpenPrinterA(PrinterName, &hPrinter, NULL)) { 1762 FIXME(" Call to OpenPrinter did not succeed!\n"); 1763 break; 1764 } 1765 DocumentPropertiesA(hDlg, hPrinter, PrinterName, 1766 PrintStructures->lpDevMode, 1767 PrintStructures->lpDevMode, 1768 DM_IN_BUFFER | DM_OUT_BUFFER | DM_IN_PROMPT); 1769 ClosePrinter(hPrinter); 1770 break; 1771 } 1772 1773 case rad1: /* Paperorientation */ 1774 if (lppd->Flags & PD_PRINTSETUP) 1775 { 1776 lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT; 1777 SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, IMAGE_ICON, 1778 (LPARAM)(PrintStructures->hPortraitIcon)); 1779 } 1780 break; 1781 1782 case rad2: /* Paperorientation */ 1783 if (lppd->Flags & PD_PRINTSETUP) 1784 { 1785 lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE; 1786 SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, IMAGE_ICON, 1787 (LPARAM)(PrintStructures->hLandscapeIcon)); 1788 } 1789 break; 1790 1791 case cmb1: /* Printer Combobox in PRINT SETUP, quality combobox in PRINT16 */ 1792 if (PrinterComboID != LOWORD(wParam)) { 1793 break; 1794 } 1795 /* FALLTHROUGH */ 1796 case cmb4: /* Printer combobox */ 1797 if (HIWORD(wParam)==CBN_SELCHANGE) { 1798 char *PrinterName; 1799 INT index = SendDlgItemMessageW(hDlg, LOWORD(wParam), CB_GETCURSEL, 0, 0); 1800 INT length = SendDlgItemMessageW(hDlg, LOWORD(wParam), CB_GETLBTEXTLEN, index, 0); 1801 PrinterName = HeapAlloc(GetProcessHeap(),0,length+1); 1802 SendDlgItemMessageA(hDlg, LOWORD(wParam), CB_GETLBTEXT, index, (LPARAM)PrinterName); 1803 PRINTDLG_ChangePrinterA(hDlg, PrinterName, PrintStructures); 1804 HeapFree(GetProcessHeap(),0,PrinterName); 1805 } 1806 break; 1807 1808 case cmb2: /* Papersize */ 1809 { 1810 DWORD Sel = SendDlgItemMessageA(hDlg, cmb2, CB_GETCURSEL, 0, 0); 1811 if(Sel != CB_ERR) { 1812 lpdm->u1.s1.dmPaperSize = SendDlgItemMessageA(hDlg, cmb2, 1813 CB_GETITEMDATA, 1814 Sel, 0); 1815 GetDlgItemTextA(hDlg, cmb2, (char *)lpdm->dmFormName, CCHFORMNAME); 1816 } 1817 } 1818 break; 1819 1820 case cmb3: /* Bin */ 1821 { 1822 DWORD Sel = SendDlgItemMessageA(hDlg, cmb3, CB_GETCURSEL, 0, 0); 1823 if(Sel != CB_ERR) 1824 lpdm->u1.s1.dmDefaultSource = SendDlgItemMessageA(hDlg, cmb3, 1825 CB_GETITEMDATA, Sel, 1826 0); 1827 } 1828 break; 1829 } 1830 if(lppd->Flags & PD_PRINTSETUP) { 1831 switch (LOWORD(wParam)) { 1832 case rad1: /* orientation */ 1833 case rad2: 1834 if (IsDlgButtonChecked(hDlg, rad1) == BST_CHECKED) { 1835 if(lpdm->u1.s1.dmOrientation != DMORIENT_PORTRAIT) { 1836 lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT; 1837 SendDlgItemMessageA(hDlg, stc10, STM_SETIMAGE, IMAGE_ICON, 1838 (LPARAM)PrintStructures->hPortraitIcon); 1839 SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, IMAGE_ICON, 1840 (LPARAM)PrintStructures->hPortraitIcon); 1841 } 1842 } else { 1843 if(lpdm->u1.s1.dmOrientation != DMORIENT_LANDSCAPE) { 1844 lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE; 1845 SendDlgItemMessageA(hDlg, stc10, STM_SETIMAGE, IMAGE_ICON, 1846 (LPARAM)PrintStructures->hLandscapeIcon); 1847 SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, IMAGE_ICON, 1848 (LPARAM)PrintStructures->hLandscapeIcon); 1849 } 1850 } 1851 break; 1852 } 1853 } 1854 return FALSE; 1855 } 1856 1857 static LRESULT PRINTDLG_WMCommandW(HWND hDlg, WPARAM wParam, 1858 PRINT_PTRW* PrintStructures) 1859 { 1860 LPPRINTDLGW lppd = PrintStructures->lpPrintDlg; 1861 UINT PrinterComboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4; 1862 LPDEVMODEW lpdm = PrintStructures->lpDevMode; 1863 1864 switch (LOWORD(wParam)) { 1865 case IDOK: 1866 TRACE(" OK button was hit\n"); 1867 if (!PRINTDLG_UpdatePrintDlgW(hDlg, PrintStructures)) { 1868 FIXME("Update printdlg was not successful!\n"); 1869 return(FALSE); 1870 } 1871 EndDialog(hDlg, TRUE); 1872 return(TRUE); 1873 1874 case IDCANCEL: 1875 TRACE(" CANCEL button was hit\n"); 1876 EndDialog(hDlg, FALSE); 1877 return(FALSE); 1878 1879 case pshHelp: 1880 TRACE(" HELP button was hit\n"); 1881 SendMessageW(lppd->hwndOwner, PrintStructures->HelpMessageID, 1882 (WPARAM) hDlg, (LPARAM) lppd); 1883 break; 1884 1885 case chx2: /* collate pages checkbox */ 1886 if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED) 1887 SendDlgItemMessageW(hDlg, ico3, STM_SETIMAGE, IMAGE_ICON, 1888 (LPARAM)PrintStructures->hCollateIcon); 1889 else 1890 SendDlgItemMessageW(hDlg, ico3, STM_SETIMAGE, IMAGE_ICON, 1891 (LPARAM)PrintStructures->hNoCollateIcon); 1892 break; 1893 case edt1: /* from page nr editbox */ 1894 case edt2: /* to page nr editbox */ 1895 if (HIWORD(wParam)==EN_CHANGE) { 1896 WORD nToPage; 1897 WORD nFromPage; 1898 nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE); 1899 nToPage = GetDlgItemInt(hDlg, edt2, NULL, FALSE); 1900 if (nFromPage != lppd->nFromPage || nToPage != lppd->nToPage) 1901 CheckRadioButton(hDlg, rad1, rad3, rad3); 1902 } 1903 break; 1904 1905 case edt3: 1906 if(HIWORD(wParam) == EN_CHANGE) { 1907 INT copies = GetDlgItemInt(hDlg, edt3, NULL, FALSE); 1908 if(copies <= 1) 1909 EnableWindow(GetDlgItem(hDlg, chx2), FALSE); 1910 else 1911 EnableWindow(GetDlgItem(hDlg, chx2), TRUE); 1912 } 1913 break; 1914 1915 case psh2: /* Properties button */ 1916 { 1917 HANDLE hPrinter; 1918 WCHAR PrinterName[256]; 1919 1920 if (!GetDlgItemTextW(hDlg, PrinterComboID, PrinterName, 255)) break; 1921 if (!OpenPrinterW(PrinterName, &hPrinter, NULL)) { 1922 FIXME(" Call to OpenPrinter did not succeed!\n"); 1923 break; 1924 } 1925 DocumentPropertiesW(hDlg, hPrinter, PrinterName, 1926 PrintStructures->lpDevMode, 1927 PrintStructures->lpDevMode, 1928 DM_IN_BUFFER | DM_OUT_BUFFER | DM_IN_PROMPT); 1929 ClosePrinter(hPrinter); 1930 break; 1931 } 1932 1933 case rad1: /* Paperorientation */ 1934 if (lppd->Flags & PD_PRINTSETUP) 1935 { 1936 lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT; 1937 SendDlgItemMessageW(hDlg, ico1, STM_SETIMAGE, IMAGE_ICON, 1938 (LPARAM)(PrintStructures->hPortraitIcon)); 1939 } 1940 break; 1941 1942 case rad2: /* Paperorientation */ 1943 if (lppd->Flags & PD_PRINTSETUP) 1944 { 1945 lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE; 1946 SendDlgItemMessageW(hDlg, ico1, STM_SETIMAGE, IMAGE_ICON, 1947 (LPARAM)(PrintStructures->hLandscapeIcon)); 1948 } 1949 break; 1950 1951 case cmb1: /* Printer Combobox in PRINT SETUP */ 1952 /* FALLTHROUGH */ 1953 case cmb4: /* Printer combobox */ 1954 if (HIWORD(wParam)==CBN_SELCHANGE) { 1955 WCHAR *PrinterName; 1956 INT index = SendDlgItemMessageW(hDlg, LOWORD(wParam), CB_GETCURSEL, 0, 0); 1957 INT length = SendDlgItemMessageW(hDlg, LOWORD(wParam), CB_GETLBTEXTLEN, index, 0); 1958 1959 PrinterName = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(length+1)); 1960 SendDlgItemMessageW(hDlg, LOWORD(wParam), CB_GETLBTEXT, index, (LPARAM)PrinterName); 1961 PRINTDLG_ChangePrinterW(hDlg, PrinterName, PrintStructures); 1962 HeapFree(GetProcessHeap(),0,PrinterName); 1963 } 1964 break; 1965 1966 case cmb2: /* Papersize */ 1967 { 1968 DWORD Sel = SendDlgItemMessageW(hDlg, cmb2, CB_GETCURSEL, 0, 0); 1969 if(Sel != CB_ERR) { 1970 lpdm->u1.s1.dmPaperSize = SendDlgItemMessageW(hDlg, cmb2, 1971 CB_GETITEMDATA, 1972 Sel, 0); 1973 GetDlgItemTextW(hDlg, cmb2, lpdm->dmFormName, CCHFORMNAME); 1974 } 1975 } 1976 break; 1977 1978 case cmb3: /* Bin */ 1979 { 1980 DWORD Sel = SendDlgItemMessageW(hDlg, cmb3, CB_GETCURSEL, 0, 0); 1981 if(Sel != CB_ERR) 1982 lpdm->u1.s1.dmDefaultSource = SendDlgItemMessageW(hDlg, cmb3, 1983 CB_GETITEMDATA, Sel, 1984 0); 1985 } 1986 break; 1987 } 1988 if(lppd->Flags & PD_PRINTSETUP) { 1989 switch (LOWORD(wParam)) { 1990 case rad1: /* orientation */ 1991 case rad2: 1992 if (IsDlgButtonChecked(hDlg, rad1) == BST_CHECKED) { 1993 if(lpdm->u1.s1.dmOrientation != DMORIENT_PORTRAIT) { 1994 lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT; 1995 SendDlgItemMessageW(hDlg, stc10, STM_SETIMAGE, IMAGE_ICON, 1996 (LPARAM)PrintStructures->hPortraitIcon); 1997 SendDlgItemMessageW(hDlg, ico1, STM_SETIMAGE, IMAGE_ICON, 1998 (LPARAM)PrintStructures->hPortraitIcon); 1999 } 2000 } else { 2001 if(lpdm->u1.s1.dmOrientation != DMORIENT_LANDSCAPE) { 2002 lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE; 2003 SendDlgItemMessageW(hDlg, stc10, STM_SETIMAGE, IMAGE_ICON, 2004 (LPARAM)PrintStructures->hLandscapeIcon); 2005 SendDlgItemMessageW(hDlg, ico1, STM_SETIMAGE, IMAGE_ICON, 2006 (LPARAM)PrintStructures->hLandscapeIcon); 2007 } 2008 } 2009 break; 2010 } 2011 } 2012 return FALSE; 2013 } 2014 2015 /*********************************************************************** 2016 * PrintDlgProcA [internal] 2017 */ 2018 static INT_PTR CALLBACK PrintDlgProcA(HWND hDlg, UINT uMsg, WPARAM wParam, 2019 LPARAM lParam) 2020 { 2021 PRINT_PTRA* PrintStructures; 2022 INT_PTR res = FALSE; 2023 2024 if (uMsg!=WM_INITDIALOG) { 2025 PrintStructures = GetPropW(hDlg, printdlg_prop); 2026 if (!PrintStructures) 2027 return FALSE; 2028 } else { 2029 PrintStructures = (PRINT_PTRA*) lParam; 2030 SetPropW(hDlg, printdlg_prop, PrintStructures); 2031 if(!check_printer_setup(hDlg)) 2032 { 2033 EndDialog(hDlg,FALSE); 2034 return FALSE; 2035 } 2036 res = PRINTDLG_WMInitDialog(hDlg, PrintStructures); 2037 2038 if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK) 2039 res = PrintStructures->lpPrintDlg->lpfnPrintHook( 2040 hDlg, uMsg, wParam, (LPARAM)PrintStructures->lpPrintDlg 2041 ); 2042 return res; 2043 } 2044 2045 if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK) { 2046 res = PrintStructures->lpPrintDlg->lpfnPrintHook(hDlg,uMsg,wParam, 2047 lParam); 2048 if(res) return res; 2049 } 2050 2051 switch (uMsg) { 2052 case WM_COMMAND: 2053 return PRINTDLG_WMCommandA(hDlg, wParam, PrintStructures); 2054 2055 case WM_DESTROY: 2056 DestroyIcon(PrintStructures->hCollateIcon); 2057 DestroyIcon(PrintStructures->hNoCollateIcon); 2058 DestroyIcon(PrintStructures->hPortraitIcon); 2059 DestroyIcon(PrintStructures->hLandscapeIcon); 2060 if(PrintStructures->hwndUpDown) 2061 DestroyWindow(PrintStructures->hwndUpDown); 2062 return FALSE; 2063 } 2064 return res; 2065 } 2066 2067 static INT_PTR CALLBACK PrintDlgProcW(HWND hDlg, UINT uMsg, WPARAM wParam, 2068 LPARAM lParam) 2069 { 2070 PRINT_PTRW* PrintStructures; 2071 INT_PTR res = FALSE; 2072 2073 if (uMsg!=WM_INITDIALOG) { 2074 PrintStructures = GetPropW(hDlg, printdlg_prop); 2075 if (!PrintStructures) 2076 return FALSE; 2077 } else { 2078 PrintStructures = (PRINT_PTRW*) lParam; 2079 SetPropW(hDlg, printdlg_prop, PrintStructures); 2080 if(!check_printer_setup(hDlg)) 2081 { 2082 EndDialog(hDlg,FALSE); 2083 return FALSE; 2084 } 2085 res = PRINTDLG_WMInitDialogW(hDlg, PrintStructures); 2086 2087 if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK) 2088 res = PrintStructures->lpPrintDlg->lpfnPrintHook(hDlg, uMsg, wParam, (LPARAM)PrintStructures->lpPrintDlg); 2089 return res; 2090 } 2091 2092 if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK) { 2093 res = PrintStructures->lpPrintDlg->lpfnPrintHook(hDlg,uMsg,wParam, lParam); 2094 if(res) return res; 2095 } 2096 2097 switch (uMsg) { 2098 case WM_COMMAND: 2099 return PRINTDLG_WMCommandW(hDlg, wParam, PrintStructures); 2100 2101 case WM_DESTROY: 2102 DestroyIcon(PrintStructures->hCollateIcon); 2103 DestroyIcon(PrintStructures->hNoCollateIcon); 2104 DestroyIcon(PrintStructures->hPortraitIcon); 2105 DestroyIcon(PrintStructures->hLandscapeIcon); 2106 if(PrintStructures->hwndUpDown) 2107 DestroyWindow(PrintStructures->hwndUpDown); 2108 return FALSE; 2109 } 2110 return res; 2111 } 2112 2113 /************************************************************ 2114 * 2115 * PRINTDLG_GetDlgTemplate 2116 * 2117 */ 2118 static HGLOBAL PRINTDLG_GetDlgTemplateA(const PRINTDLGA *lppd) 2119 { 2120 HRSRC hResInfo; 2121 HGLOBAL hDlgTmpl; 2122 2123 if (lppd->Flags & PD_PRINTSETUP) { 2124 if(lppd->Flags & PD_ENABLESETUPTEMPLATEHANDLE) { 2125 hDlgTmpl = lppd->hSetupTemplate; 2126 } else if(lppd->Flags & PD_ENABLESETUPTEMPLATE) { 2127 hResInfo = FindResourceA(lppd->hInstance, 2128 lppd->lpSetupTemplateName, (LPSTR)RT_DIALOG); 2129 hDlgTmpl = LoadResource(lppd->hInstance, hResInfo); 2130 } else { 2131 hResInfo = FindResourceA(COMDLG32_hInstance, "PRINT32_SETUP", 2132 (LPSTR)RT_DIALOG); 2133 hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo); 2134 } 2135 } else { 2136 if(lppd->Flags & PD_ENABLEPRINTTEMPLATEHANDLE) { 2137 hDlgTmpl = lppd->hPrintTemplate; 2138 } else if(lppd->Flags & PD_ENABLEPRINTTEMPLATE) { 2139 hResInfo = FindResourceA(lppd->hInstance, 2140 lppd->lpPrintTemplateName, 2141 (LPSTR)RT_DIALOG); 2142 hDlgTmpl = LoadResource(lppd->hInstance, hResInfo); 2143 } else { 2144 hResInfo = FindResourceA(COMDLG32_hInstance, "PRINT32", 2145 (LPSTR)RT_DIALOG); 2146 hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo); 2147 } 2148 } 2149 return hDlgTmpl; 2150 } 2151 2152 static HGLOBAL PRINTDLG_GetDlgTemplateW(const PRINTDLGW *lppd) 2153 { 2154 HRSRC hResInfo; 2155 HGLOBAL hDlgTmpl; 2156 static const WCHAR xpsetup[] = { 'P','R','I','N','T','3','2','_','S','E','T','U','P',0}; 2157 static const WCHAR xprint[] = { 'P','R','I','N','T','3','2',0}; 2158 2159 if (lppd->Flags & PD_PRINTSETUP) { 2160 if(lppd->Flags & PD_ENABLESETUPTEMPLATEHANDLE) { 2161 hDlgTmpl = lppd->hSetupTemplate; 2162 } else if(lppd->Flags & PD_ENABLESETUPTEMPLATE) { 2163 hResInfo = FindResourceW(lppd->hInstance, 2164 lppd->lpSetupTemplateName, (LPWSTR)RT_DIALOG); 2165 hDlgTmpl = LoadResource(lppd->hInstance, hResInfo); 2166 } else { 2167 hResInfo = FindResourceW(COMDLG32_hInstance, xpsetup, (LPWSTR)RT_DIALOG); 2168 hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo); 2169 } 2170 } else { 2171 if(lppd->Flags & PD_ENABLEPRINTTEMPLATEHANDLE) { 2172 hDlgTmpl = lppd->hPrintTemplate; 2173 } else if(lppd->Flags & PD_ENABLEPRINTTEMPLATE) { 2174 hResInfo = FindResourceW(lppd->hInstance, 2175 lppd->lpPrintTemplateName, 2176 (LPWSTR)RT_DIALOG); 2177 hDlgTmpl = LoadResource(lppd->hInstance, hResInfo); 2178 } else { 2179 hResInfo = FindResourceW(COMDLG32_hInstance, xprint, (LPWSTR)RT_DIALOG); 2180 hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo); 2181 } 2182 } 2183 return hDlgTmpl; 2184 } 2185 2186 /*********************************************************************** 2187 * 2188 * PRINTDLG_CreateDC 2189 * 2190 */ 2191 static BOOL PRINTDLG_CreateDCA(LPPRINTDLGA lppd) 2192 { 2193 DEVNAMES *pdn = GlobalLock(lppd->hDevNames); 2194 DEVMODEA *pdm = GlobalLock(lppd->hDevMode); 2195 2196 if(lppd->Flags & PD_RETURNDC) { 2197 lppd->hDC = CreateDCA((char*)pdn + pdn->wDriverOffset, 2198 (char*)pdn + pdn->wDeviceOffset, 2199 (char*)pdn + pdn->wOutputOffset, 2200 pdm ); 2201 } else if(lppd->Flags & PD_RETURNIC) { 2202 lppd->hDC = CreateICA((char*)pdn + pdn->wDriverOffset, 2203 (char*)pdn + pdn->wDeviceOffset, 2204 (char*)pdn + pdn->wOutputOffset, 2205 pdm ); 2206 } 2207 GlobalUnlock(lppd->hDevNames); 2208 GlobalUnlock(lppd->hDevMode); 2209 return lppd->hDC != NULL; 2210 } 2211 2212 static BOOL PRINTDLG_CreateDCW(LPPRINTDLGW lppd) 2213 { 2214 DEVNAMES *pdn = GlobalLock(lppd->hDevNames); 2215 DEVMODEW *pdm = GlobalLock(lppd->hDevMode); 2216 2217 if(lppd->Flags & PD_RETURNDC) { 2218 lppd->hDC = CreateDCW((WCHAR*)pdn + pdn->wDriverOffset, 2219 (WCHAR*)pdn + pdn->wDeviceOffset, 2220 (WCHAR*)pdn + pdn->wOutputOffset, 2221 pdm ); 2222 } else if(lppd->Flags & PD_RETURNIC) { 2223 lppd->hDC = CreateICW((WCHAR*)pdn + pdn->wDriverOffset, 2224 (WCHAR*)pdn + pdn->wDeviceOffset, 2225 (WCHAR*)pdn + pdn->wOutputOffset, 2226 pdm ); 2227 } 2228 GlobalUnlock(lppd->hDevNames); 2229 GlobalUnlock(lppd->hDevMode); 2230 return lppd->hDC != NULL; 2231 } 2232 2233 /*********************************************************************** 2234 * PrintDlgA (COMDLG32.@) 2235 * 2236 * Displays the PRINT dialog box, which enables the user to specify 2237 * specific properties of the print job. 2238 * 2239 * PARAMS 2240 * lppd [IO] ptr to PRINTDLG32 struct 2241 * 2242 * RETURNS 2243 * nonzero if the user pressed the OK button 2244 * zero if the user cancelled the window or an error occurred 2245 * 2246 * BUGS 2247 * PrintDlg: 2248 * * The Collate Icons do not display, even though they are in the code. 2249 * * The Properties Button(s) should call DocumentPropertiesA(). 2250 */ 2251 2252 BOOL WINAPI PrintDlgA(LPPRINTDLGA lppd) 2253 { 2254 BOOL bRet = FALSE; 2255 LPVOID ptr; 2256 HINSTANCE hInst; 2257 2258 if (!lppd) 2259 { 2260 COMDLG32_SetCommDlgExtendedError(CDERR_INITIALIZATION); 2261 return FALSE; 2262 } 2263 2264 if(TRACE_ON(commdlg)) { 2265 char flagstr[1000] = ""; 2266 const struct pd_flags *pflag = pd_flags; 2267 for( ; pflag->name; pflag++) { 2268 if(lppd->Flags & pflag->flag) 2269 strcat(flagstr, pflag->name); 2270 } 2271 TRACE("(%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n" 2272 "pp. %d-%d, min p %d, max p %d, copies %d, hinst %p\n" 2273 "flags %08x (%s)\n", 2274 lppd, lppd->hwndOwner, lppd->hDevMode, lppd->hDevNames, 2275 lppd->nFromPage, lppd->nToPage, lppd->nMinPage, lppd->nMaxPage, 2276 lppd->nCopies, lppd->hInstance, lppd->Flags, flagstr); 2277 } 2278 2279 if(lppd->lStructSize != sizeof(PRINTDLGA)) { 2280 WARN("structure size failure!!!\n"); 2281 COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE); 2282 return FALSE; 2283 } 2284 2285 if(lppd->Flags & PD_RETURNDEFAULT) { 2286 PRINTER_INFO_2A *pbuf; 2287 DRIVER_INFO_3A *dbuf; 2288 HANDLE hprn; 2289 DWORD needed; 2290 2291 if(lppd->hDevMode || lppd->hDevNames) { 2292 WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n"); 2293 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE); 2294 return FALSE; 2295 } 2296 if(!PRINTDLG_OpenDefaultPrinter(&hprn)) { 2297 WARN("Can't find default printer\n"); 2298 COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN); 2299 return FALSE; 2300 } 2301 2302 GetPrinterA(hprn, 2, NULL, 0, &needed); 2303 pbuf = HeapAlloc(GetProcessHeap(), 0, needed); 2304 GetPrinterA(hprn, 2, (LPBYTE)pbuf, needed, &needed); 2305 2306 GetPrinterDriverA(hprn, NULL, 3, NULL, 0, &needed); 2307 dbuf = HeapAlloc(GetProcessHeap(),0,needed); 2308 if (!GetPrinterDriverA(hprn, NULL, 3, (LPBYTE)dbuf, needed, &needed)) { 2309 ERR("GetPrinterDriverA failed, le %d, fix your config for printer %s!\n", 2310 GetLastError(),pbuf->pPrinterName); 2311 HeapFree(GetProcessHeap(), 0, dbuf); 2312 HeapFree(GetProcessHeap(), 0, pbuf); 2313 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE); 2314 return FALSE; 2315 } 2316 ClosePrinter(hprn); 2317 2318 PRINTDLG_CreateDevNames(&(lppd->hDevNames), 2319 dbuf->pDriverPath, 2320 pbuf->pPrinterName, 2321 pbuf->pPortName); 2322 lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, pbuf->pDevMode->dmSize + 2323 pbuf->pDevMode->dmDriverExtra); 2324 ptr = GlobalLock(lppd->hDevMode); 2325 memcpy(ptr, pbuf->pDevMode, pbuf->pDevMode->dmSize + 2326 pbuf->pDevMode->dmDriverExtra); 2327 GlobalUnlock(lppd->hDevMode); 2328 HeapFree(GetProcessHeap(), 0, pbuf); 2329 HeapFree(GetProcessHeap(), 0, dbuf); 2330 bRet = TRUE; 2331 } else { 2332 HGLOBAL hDlgTmpl; 2333 PRINT_PTRA *PrintStructures; 2334 2335 /* load Dialog resources, 2336 * depending on Flags indicates Print32 or Print32_setup dialog 2337 */ 2338 hDlgTmpl = PRINTDLG_GetDlgTemplateA(lppd); 2339 if (!hDlgTmpl) { 2340 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE); 2341 return FALSE; 2342 } 2343 ptr = LockResource( hDlgTmpl ); 2344 if (!ptr) { 2345 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE); 2346 return FALSE; 2347 } 2348 2349 PrintStructures = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 2350 sizeof(PRINT_PTRA)); 2351 PrintStructures->lpPrintDlg = lppd; 2352 2353 /* and create & process the dialog . 2354 * -1 is failure, 0 is broken hwnd, everything else is ok. 2355 */ 2356 hInst = COMDLG32_hInstance; 2357 if (lppd->Flags & (PD_ENABLESETUPTEMPLATE | PD_ENABLEPRINTTEMPLATE)) hInst = lppd->hInstance; 2358 bRet = (0<DialogBoxIndirectParamA(hInst, ptr, lppd->hwndOwner, 2359 PrintDlgProcA, 2360 (LPARAM)PrintStructures)); 2361 2362 if(bRet) { 2363 DEVMODEA *lpdm = PrintStructures->lpDevMode, *lpdmReturn; 2364 PRINTER_INFO_2A *pi = PrintStructures->lpPrinterInfo; 2365 DRIVER_INFO_3A *di = PrintStructures->lpDriverInfo; 2366 2367 if (lppd->hDevMode == 0) { 2368 TRACE(" No hDevMode yet... Need to create my own\n"); 2369 lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, 2370 lpdm->dmSize + lpdm->dmDriverExtra); 2371 } else { 2372 lppd->hDevMode = GlobalReAlloc(lppd->hDevMode, 2373 lpdm->dmSize + lpdm->dmDriverExtra, 2374 GMEM_MOVEABLE); 2375 } 2376 lpdmReturn = GlobalLock(lppd->hDevMode); 2377 memcpy(lpdmReturn, lpdm, lpdm->dmSize + lpdm->dmDriverExtra); 2378 2379 PRINTDLG_CreateDevNames(&(lppd->hDevNames), 2380 di->pDriverPath, 2381 pi->pPrinterName, 2382 pi->pPortName 2383 ); 2384 GlobalUnlock(lppd->hDevMode); 2385 } 2386 HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode); 2387 HeapFree(GetProcessHeap(), 0, PrintStructures->lpPrinterInfo); 2388 HeapFree(GetProcessHeap(), 0, PrintStructures->lpDriverInfo); 2389 HeapFree(GetProcessHeap(), 0, PrintStructures); 2390 } 2391 if(bRet && (lppd->Flags & PD_RETURNDC || lppd->Flags & PD_RETURNIC)) 2392 bRet = PRINTDLG_CreateDCA(lppd); 2393 2394 TRACE("exit! (%d)\n", bRet); 2395 return bRet; 2396 } 2397 2398 /*********************************************************************** 2399 * PrintDlgW (COMDLG32.@) 2400 * 2401 * See PrintDlgA. 2402 */ 2403 BOOL WINAPI PrintDlgW(LPPRINTDLGW lppd) 2404 { 2405 BOOL bRet = FALSE; 2406 LPVOID ptr; 2407 HINSTANCE hInst; 2408 2409 if (!lppd) 2410 { 2411 COMDLG32_SetCommDlgExtendedError(CDERR_INITIALIZATION); 2412 return FALSE; 2413 } 2414 2415 if(TRACE_ON(commdlg)) { 2416 char flagstr[1000] = ""; 2417 const struct pd_flags *pflag = pd_flags; 2418 for( ; pflag->name; pflag++) { 2419 if(lppd->Flags & pflag->flag) 2420 strcat(flagstr, pflag->name); 2421 } 2422 TRACE("(%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n" 2423 "pp. %d-%d, min p %d, max p %d, copies %d, hinst %p\n" 2424 "flags %08x (%s)\n", 2425 lppd, lppd->hwndOwner, lppd->hDevMode, lppd->hDevNames, 2426 lppd->nFromPage, lppd->nToPage, lppd->nMinPage, lppd->nMaxPage, 2427 lppd->nCopies, lppd->hInstance, lppd->Flags, flagstr); 2428 } 2429 2430 if(lppd->lStructSize != sizeof(PRINTDLGW)) { 2431 WARN("structure size failure!!!\n"); 2432 COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE); 2433 return FALSE; 2434 } 2435 2436 if(lppd->Flags & PD_RETURNDEFAULT) { 2437 PRINTER_INFO_2W *pbuf; 2438 DRIVER_INFO_3W *dbuf; 2439 HANDLE hprn; 2440 DWORD needed; 2441 2442 if(lppd->hDevMode || lppd->hDevNames) { 2443 WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n"); 2444 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE); 2445 return FALSE; 2446 } 2447 if(!PRINTDLG_OpenDefaultPrinter(&hprn)) { 2448 WARN("Can't find default printer\n"); 2449 COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN); 2450 return FALSE; 2451 } 2452 2453 GetPrinterW(hprn, 2, NULL, 0, &needed); 2454 pbuf = HeapAlloc(GetProcessHeap(), 0, needed); 2455 GetPrinterW(hprn, 2, (LPBYTE)pbuf, needed, &needed); 2456 2457 GetPrinterDriverW(hprn, NULL, 3, NULL, 0, &needed); 2458 dbuf = HeapAlloc(GetProcessHeap(),0,needed); 2459 if (!GetPrinterDriverW(hprn, NULL, 3, (LPBYTE)dbuf, needed, &needed)) { 2460 ERR("GetPrinterDriverA failed, le %d, fix your config for printer %s!\n", 2461 GetLastError(),debugstr_w(pbuf->pPrinterName)); 2462 HeapFree(GetProcessHeap(), 0, dbuf); 2463 HeapFree(GetProcessHeap(), 0, pbuf); 2464 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE); 2465 return FALSE; 2466 } 2467 ClosePrinter(hprn); 2468 2469 PRINTDLG_CreateDevNamesW(&(lppd->hDevNames), 2470 dbuf->pDriverPath, 2471 pbuf->pPrinterName, 2472 pbuf->pPortName); 2473 lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, pbuf->pDevMode->dmSize + 2474 pbuf->pDevMode->dmDriverExtra); 2475 ptr = GlobalLock(lppd->hDevMode); 2476 memcpy(ptr, pbuf->pDevMode, pbuf->pDevMode->dmSize + 2477 pbuf->pDevMode->dmDriverExtra); 2478 GlobalUnlock(lppd->hDevMode); 2479 HeapFree(GetProcessHeap(), 0, pbuf); 2480 HeapFree(GetProcessHeap(), 0, dbuf); 2481 bRet = TRUE; 2482 } else { 2483 HGLOBAL hDlgTmpl; 2484 PRINT_PTRW *PrintStructures; 2485 2486 /* load Dialog resources, 2487 * depending on Flags indicates Print32 or Print32_setup dialog 2488 */ 2489 hDlgTmpl = PRINTDLG_GetDlgTemplateW(lppd); 2490 if (!hDlgTmpl) { 2491 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE); 2492 return FALSE; 2493 } 2494 ptr = LockResource( hDlgTmpl ); 2495 if (!ptr) { 2496 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE); 2497 return FALSE; 2498 } 2499 2500 PrintStructures = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 2501 sizeof(PRINT_PTRW)); 2502 PrintStructures->lpPrintDlg = lppd; 2503 2504 /* and create & process the dialog . 2505 * -1 is failure, 0 is broken hwnd, everything else is ok. 2506 */ 2507 hInst = COMDLG32_hInstance; 2508 if (lppd->Flags & (PD_ENABLESETUPTEMPLATE | PD_ENABLEPRINTTEMPLATE)) hInst = lppd->hInstance; 2509 bRet = (0<DialogBoxIndirectParamW(hInst, ptr, lppd->hwndOwner, 2510 PrintDlgProcW, 2511 (LPARAM)PrintStructures)); 2512 2513 if(bRet) { 2514 DEVMODEW *lpdm = PrintStructures->lpDevMode, *lpdmReturn; 2515 PRINTER_INFO_2W *pi = PrintStructures->lpPrinterInfo; 2516 DRIVER_INFO_3W *di = PrintStructures->lpDriverInfo; 2517 2518 if (lppd->hDevMode == 0) { 2519 TRACE(" No hDevMode yet... Need to create my own\n"); 2520 lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, 2521 lpdm->dmSize + lpdm->dmDriverExtra); 2522 } else { 2523 WORD locks; 2524 if((locks = (GlobalFlags(lppd->hDevMode) & GMEM_LOCKCOUNT))) { 2525 WARN("hDevMode has %d locks on it. Unlocking it now\n", locks); 2526 while(locks--) { 2527 GlobalUnlock(lppd->hDevMode); 2528 TRACE("Now got %d locks\n", locks); 2529 } 2530 } 2531 lppd->hDevMode = GlobalReAlloc(lppd->hDevMode, 2532 lpdm->dmSize + lpdm->dmDriverExtra, 2533 GMEM_MOVEABLE); 2534 } 2535 lpdmReturn = GlobalLock(lppd->hDevMode); 2536 memcpy(lpdmReturn, lpdm, lpdm->dmSize + lpdm->dmDriverExtra); 2537 2538 if (lppd->hDevNames != 0) { 2539 WORD locks; 2540 if((locks = (GlobalFlags(lppd->hDevNames) & GMEM_LOCKCOUNT))) { 2541 WARN("hDevNames has %d locks on it. Unlocking it now\n", locks); 2542 while(locks--) 2543 GlobalUnlock(lppd->hDevNames); 2544 } 2545 } 2546 PRINTDLG_CreateDevNamesW(&(lppd->hDevNames), 2547 di->pDriverPath, 2548 pi->pPrinterName, 2549 pi->pPortName 2550 ); 2551 GlobalUnlock(lppd->hDevMode); 2552 } 2553 HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode); 2554 HeapFree(GetProcessHeap(), 0, PrintStructures->lpPrinterInfo); 2555 HeapFree(GetProcessHeap(), 0, PrintStructures->lpDriverInfo); 2556 HeapFree(GetProcessHeap(), 0, PrintStructures); 2557 } 2558 if(bRet && (lppd->Flags & PD_RETURNDC || lppd->Flags & PD_RETURNIC)) 2559 bRet = PRINTDLG_CreateDCW(lppd); 2560 2561 TRACE("exit! (%d)\n", bRet); 2562 return bRet; 2563 } 2564 2565 /*********************************************************************** 2566 * 2567 * PageSetupDlg 2568 * rad1 - portrait 2569 * rad2 - landscape 2570 * cmb1 - printer select (not in standard dialog template) 2571 * cmb2 - paper size 2572 * cmb3 - source (tray?) 2573 * edt4 - border left 2574 * edt5 - border top 2575 * edt6 - border right 2576 * edt7 - border bottom 2577 * psh3 - "Printer..." 2578 */ 2579 2580 typedef struct 2581 { 2582 BOOL unicode; 2583 union 2584 { 2585 LPPAGESETUPDLGA dlga; 2586 LPPAGESETUPDLGW dlgw; 2587 } u; 2588 HWND hDlg; /* Page Setup dialog handle */ 2589 RECT rtDrawRect; /* Drawing rect for page */ 2590 } pagesetup_data; 2591 2592 static inline DWORD pagesetup_get_flags(const pagesetup_data *data) 2593 { 2594 return data->u.dlgw->Flags; 2595 } 2596 2597 static inline BOOL is_metric(const pagesetup_data *data) 2598 { 2599 return pagesetup_get_flags(data) & PSD_INHUNDREDTHSOFMILLIMETERS; 2600 } 2601 2602 static inline LONG tenths_mm_to_size(const pagesetup_data *data, LONG size) 2603 { 2604 if (is_metric(data)) 2605 return 10 * size; 2606 else 2607 return 10 * size * 100 / 254; 2608 } 2609 2610 static inline LONG thousandths_inch_to_size(const pagesetup_data *data, LONG size) 2611 { 2612 if (is_metric(data)) 2613 return size * 254 / 100; 2614 else 2615 return size; 2616 } 2617 2618 static WCHAR get_decimal_sep(void) 2619 { 2620 static WCHAR sep; 2621 2622 if(!sep) 2623 { 2624 WCHAR buf[] = {'.', 0}; 2625 GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, buf, ARRAY_SIZE(buf)); 2626 sep = buf[0]; 2627 } 2628 return sep; 2629 } 2630 2631 static void size2str(const pagesetup_data *data, DWORD size, LPWSTR strout) 2632 { 2633 static const WCHAR integer_fmt[] = {'%','d',0}; 2634 static const WCHAR hundredths_fmt[] = {'%','d','%','c','%','0','2','d',0}; 2635 static const WCHAR thousandths_fmt[] = {'%','d','%','c','%','0','3','d',0}; 2636 2637 /* FIXME use LOCALE_SDECIMAL when the edit parsing code can cope */ 2638 2639 if (is_metric(data)) 2640 { 2641 if(size % 100) 2642 wsprintfW(strout, hundredths_fmt, size / 100, get_decimal_sep(), size % 100); 2643 else 2644 wsprintfW(strout, integer_fmt, size / 100); 2645 } 2646 else 2647 { 2648 if(size % 1000) 2649 wsprintfW(strout, thousandths_fmt, size / 1000, get_decimal_sep(), size % 1000); 2650 else 2651 wsprintfW(strout, integer_fmt, size / 1000); 2652 2653 } 2654 } 2655 2656 static inline BOOL is_default_metric(void) 2657 { 2658 DWORD system; 2659 GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_IMEASURE | LOCALE_RETURN_NUMBER, 2660 (LPWSTR)&system, sizeof(system)); 2661 return system == 0; 2662 } 2663 2664 /********************************************** 2665 * rotate_rect 2666 * Cyclically permute the four members of rc 2667 * If sense is TRUE l -> t -> r -> b 2668 * otherwise l <- t <- r <- b 2669 */ 2670 static inline void rotate_rect(RECT *rc, BOOL sense) 2671 { 2672 INT tmp; 2673 if(sense) 2674 { 2675 tmp = rc->bottom; 2676 rc->bottom = rc->right; 2677 rc->right = rc->top; 2678 rc->top = rc->left; 2679 rc->left = tmp; 2680 } 2681 else 2682 { 2683 tmp = rc->left; 2684 rc->left = rc->top; 2685 rc->top = rc->right; 2686 rc->right = rc->bottom; 2687 rc->bottom = tmp; 2688 } 2689 } 2690 2691 static void pagesetup_set_orientation(pagesetup_data *data, WORD orient) 2692 { 2693 DEVMODEW *dm = GlobalLock(data->u.dlgw->hDevMode); 2694 2695 assert(orient == DMORIENT_PORTRAIT || orient == DMORIENT_LANDSCAPE); 2696 2697 if(data->unicode) 2698 dm->u1.s1.dmOrientation = orient; 2699 else 2700 { 2701 DEVMODEA *dmA = (DEVMODEA *)dm; 2702 dmA->u1.s1.dmOrientation = orient; 2703 } 2704 GlobalUnlock(data->u.dlgw->hDevMode); 2705 } 2706 2707 static WORD pagesetup_get_orientation(const pagesetup_data *data) 2708 { 2709 DEVMODEW *dm = GlobalLock(data->u.dlgw->hDevMode); 2710 WORD orient; 2711 2712 if(data->unicode) 2713 orient = dm->u1.s1.dmOrientation; 2714 else 2715 { 2716 DEVMODEA *dmA = (DEVMODEA *)dm; 2717 orient = dmA->u1.s1.dmOrientation; 2718 } 2719 GlobalUnlock(data->u.dlgw->hDevMode); 2720 return orient; 2721 } 2722 2723 static void pagesetup_set_papersize(pagesetup_data *data, WORD paper) 2724 { 2725 DEVMODEW *dm = GlobalLock(data->u.dlgw->hDevMode); 2726 2727 if(data->unicode) 2728 dm->u1.s1.dmPaperSize = paper; 2729 else 2730 { 2731 DEVMODEA *dmA = (DEVMODEA *)dm; 2732 dmA->u1.s1.dmPaperSize = paper; 2733 } 2734 GlobalUnlock(data->u.dlgw->hDevMode); 2735 } 2736 2737 static WORD pagesetup_get_papersize(const pagesetup_data *data) 2738 { 2739 DEVMODEW *dm = GlobalLock(data->u.dlgw->hDevMode); 2740 WORD paper; 2741 2742 if(data->unicode) 2743 paper = dm->u1.s1.dmPaperSize; 2744 else 2745 { 2746 DEVMODEA *dmA = (DEVMODEA *)dm; 2747 paper = dmA->u1.s1.dmPaperSize; 2748 } 2749 GlobalUnlock(data->u.dlgw->hDevMode); 2750 return paper; 2751 } 2752 2753 static void pagesetup_set_defaultsource(pagesetup_data *data, WORD source) 2754 { 2755 DEVMODEW *dm = GlobalLock(data->u.dlgw->hDevMode); 2756 2757 if(data->unicode) 2758 dm->u1.s1.dmDefaultSource = source; 2759 else 2760 { 2761 DEVMODEA *dmA = (DEVMODEA *)dm; 2762 dmA->u1.s1.dmDefaultSource = source; 2763 } 2764 GlobalUnlock(data->u.dlgw->hDevMode); 2765 } 2766 2767 typedef enum 2768 { 2769 devnames_driver_name, 2770 devnames_device_name, 2771 devnames_output_name 2772 } devnames_name; 2773 2774 2775 static inline WORD get_devname_offset(const DEVNAMES *dn, devnames_name which) 2776 { 2777 switch(which) 2778 { 2779 case devnames_driver_name: return dn->wDriverOffset; 2780 case devnames_device_name: return dn->wDeviceOffset; 2781 case devnames_output_name: return dn->wOutputOffset; 2782 } 2783 ERR("Shouldn't be here\n"); 2784 return 0; 2785 } 2786 2787 static WCHAR *pagesetup_get_a_devname(const pagesetup_data *data, devnames_name which) 2788 { 2789 DEVNAMES *dn; 2790 WCHAR *name; 2791 2792 dn = GlobalLock(data->u.dlgw->hDevNames); 2793 if(data->unicode) 2794 name = strdupW((WCHAR *)dn + get_devname_offset(dn, which)); 2795 else 2796 { 2797 int len = MultiByteToWideChar(CP_ACP, 0, (char*)dn + get_devname_offset(dn, which), -1, NULL, 0); 2798 name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 2799 MultiByteToWideChar(CP_ACP, 0, (char*)dn + get_devname_offset(dn, which), -1, name, len); 2800 } 2801 GlobalUnlock(data->u.dlgw->hDevNames); 2802 return name; 2803 } 2804 2805 static WCHAR *pagesetup_get_drvname(const pagesetup_data *data) 2806 { 2807 return pagesetup_get_a_devname(data, devnames_driver_name); 2808 } 2809 2810 static WCHAR *pagesetup_get_devname(const pagesetup_data *data) 2811 { 2812 return pagesetup_get_a_devname(data, devnames_device_name); 2813 } 2814 2815 static WCHAR *pagesetup_get_portname(const pagesetup_data *data) 2816 { 2817 return pagesetup_get_a_devname(data, devnames_output_name); 2818 } 2819 2820 static void pagesetup_release_a_devname(const pagesetup_data *data, WCHAR *name) 2821 { 2822 HeapFree(GetProcessHeap(), 0, name); 2823 } 2824 2825 static void pagesetup_set_devnames(pagesetup_data *data, LPCWSTR drv, LPCWSTR devname, LPCWSTR port) 2826 { 2827 DEVNAMES *dn; 2828 WCHAR def[256]; 2829 DWORD len = sizeof(DEVNAMES), drv_len, dev_len, port_len; 2830 2831 if(data->unicode) 2832 { 2833 drv_len = (lstrlenW(drv) + 1) * sizeof(WCHAR); 2834 dev_len = (lstrlenW(devname) + 1) * sizeof(WCHAR); 2835 port_len = (lstrlenW(port) + 1) * sizeof(WCHAR); 2836 } 2837 else 2838 { 2839 drv_len = WideCharToMultiByte(CP_ACP, 0, drv, -1, NULL, 0, NULL, NULL); 2840 dev_len = WideCharToMultiByte(CP_ACP, 0, devname, -1, NULL, 0, NULL, NULL); 2841 port_len = WideCharToMultiByte(CP_ACP, 0, port, -1, NULL, 0, NULL, NULL); 2842 } 2843 len += drv_len + dev_len + port_len; 2844 2845 if(data->u.dlgw->hDevNames) 2846 data->u.dlgw->hDevNames = GlobalReAlloc(data->u.dlgw->hDevNames, len, GMEM_MOVEABLE); 2847 else 2848 data->u.dlgw->hDevNames = GlobalAlloc(GMEM_MOVEABLE, len); 2849 2850 dn = GlobalLock(data->u.dlgw->hDevNames); 2851 2852 if(data->unicode) 2853 { 2854 WCHAR *ptr = (WCHAR *)(dn + 1); 2855 len = sizeof(DEVNAMES) / sizeof(WCHAR); 2856 dn->wDriverOffset = len; 2857 lstrcpyW(ptr, drv); 2858 ptr += drv_len / sizeof(WCHAR); 2859 len += drv_len / sizeof(WCHAR); 2860 dn->wDeviceOffset = len; 2861 lstrcpyW(ptr, devname); 2862 ptr += dev_len / sizeof(WCHAR); 2863 len += dev_len / sizeof(WCHAR); 2864 dn->wOutputOffset = len; 2865 lstrcpyW(ptr, port); 2866 } 2867 else 2868 { 2869 char *ptr = (char *)(dn + 1); 2870 len = sizeof(DEVNAMES); 2871 dn->wDriverOffset = len; 2872 WideCharToMultiByte(CP_ACP, 0, drv, -1, ptr, drv_len, NULL, NULL); 2873 ptr += drv_len; 2874 len += drv_len; 2875 dn->wDeviceOffset = len; 2876 WideCharToMultiByte(CP_ACP, 0, devname, -1, ptr, dev_len, NULL, NULL); 2877 ptr += dev_len; 2878 len += dev_len; 2879 dn->wOutputOffset = len; 2880 WideCharToMultiByte(CP_ACP, 0, port, -1, ptr, port_len, NULL, NULL); 2881 } 2882 2883 dn->wDefault = 0; 2884 len = ARRAY_SIZE(def); 2885 GetDefaultPrinterW(def, &len); 2886 if(!lstrcmpW(def, devname)) 2887 dn->wDefault = 1; 2888 2889 GlobalUnlock(data->u.dlgw->hDevNames); 2890 } 2891 2892 static DEVMODEW *pagesetup_get_devmode(const pagesetup_data *data) 2893 { 2894 DEVMODEW *dm = GlobalLock(data->u.dlgw->hDevMode); 2895 DEVMODEW *ret; 2896 2897 if(data->unicode) 2898 { 2899 /* We make a copy even in the unicode case because the ptr 2900 may get passed back to us in pagesetup_set_devmode. */ 2901 ret = HeapAlloc(GetProcessHeap(), 0, dm->dmSize + dm->dmDriverExtra); 2902 memcpy(ret, dm, dm->dmSize + dm->dmDriverExtra); 2903 } 2904 else 2905 ret = GdiConvertToDevmodeW((DEVMODEA *)dm); 2906 2907 GlobalUnlock(data->u.dlgw->hDevMode); 2908 return ret; 2909 } 2910 2911 static void pagesetup_release_devmode(const pagesetup_data *data, DEVMODEW *dm) 2912 { 2913 HeapFree(GetProcessHeap(), 0, dm); 2914 } 2915 2916 static void pagesetup_set_devmode(pagesetup_data *data, DEVMODEW *dm) 2917 { 2918 DEVMODEA *dmA = NULL; 2919 void *src, *dst; 2920 DWORD size; 2921 2922 if(data->unicode) 2923 { 2924 size = dm->dmSize + dm->dmDriverExtra; 2925 src = dm; 2926 } 2927 else 2928 { 2929 dmA = convert_to_devmodeA(dm); 2930 size = dmA->dmSize + dmA->dmDriverExtra; 2931 src = dmA; 2932 } 2933 2934 if(data->u.dlgw->hDevMode) 2935 data->u.dlgw->hDevMode = GlobalReAlloc(data->u.dlgw->hDevMode, size, 2936 GMEM_MOVEABLE); 2937 else 2938 data->u.dlgw->hDevMode = GlobalAlloc(GMEM_MOVEABLE, size); 2939 2940 dst = GlobalLock(data->u.dlgw->hDevMode); 2941 memcpy(dst, src, size); 2942 GlobalUnlock(data->u.dlgw->hDevMode); 2943 HeapFree(GetProcessHeap(), 0, dmA); 2944 } 2945 2946 static inline POINT *pagesetup_get_papersize_pt(const pagesetup_data *data) 2947 { 2948 return &data->u.dlgw->ptPaperSize; 2949 } 2950 2951 static inline RECT *pagesetup_get_margin_rect(const pagesetup_data *data) 2952 { 2953 return &data->u.dlgw->rtMargin; 2954 } 2955 2956 typedef enum 2957 { 2958 page_setup_hook, 2959 page_paint_hook 2960 } hook_type; 2961 2962 static inline LPPAGESETUPHOOK pagesetup_get_hook(const pagesetup_data *data, hook_type which) 2963 { 2964 switch(which) 2965 { 2966 case page_setup_hook: return data->u.dlgw->lpfnPageSetupHook; 2967 case page_paint_hook: return data->u.dlgw->lpfnPagePaintHook; 2968 } 2969 return NULL; 2970 } 2971 2972 /* This should only be used in calls to hook procs so we return the ptr 2973 already cast to LPARAM */ 2974 static inline LPARAM pagesetup_get_dlg_struct(const pagesetup_data *data) 2975 { 2976 return (LPARAM)data->u.dlgw; 2977 } 2978 2979 static inline void swap_point(POINT *pt) 2980 { 2981 LONG tmp = pt->x; 2982 pt->x = pt->y; 2983 pt->y = tmp; 2984 } 2985 2986 static BOOL pagesetup_update_papersize(pagesetup_data *data) 2987 { 2988 DEVMODEW *dm; 2989 LPWSTR devname, portname; 2990 int i, num; 2991 WORD *words = NULL, paperword; 2992 POINT *points = NULL; 2993 BOOL retval = FALSE; 2994 2995 dm = pagesetup_get_devmode(data); 2996 devname = pagesetup_get_devname(data); 2997 portname = pagesetup_get_portname(data); 2998 2999 num = DeviceCapabilitiesW(devname, portname, DC_PAPERS, NULL, dm); 3000 if (num <= 0) 3001 { 3002 FIXME("No papernames found for %s/%s\n", debugstr_w(devname), debugstr_w(portname)); 3003 goto end; 3004 } 3005 3006 words = HeapAlloc(GetProcessHeap(), 0, num * sizeof(WORD)); 3007 points = HeapAlloc(GetProcessHeap(), 0, num * sizeof(POINT)); 3008 3009 if (num != DeviceCapabilitiesW(devname, portname, DC_PAPERS, (LPWSTR)words, dm)) 3010 { 3011 FIXME("Number of returned words is not %d\n", num); 3012 goto end; 3013 } 3014 3015 if (num != DeviceCapabilitiesW(devname, portname, DC_PAPERSIZE, (LPWSTR)points, dm)) 3016 { 3017 FIXME("Number of returned sizes is not %d\n", num); 3018 goto end; 3019 } 3020 3021 paperword = pagesetup_get_papersize(data); 3022 3023 for (i = 0; i < num; i++) 3024 if (words[i] == paperword) 3025 break; 3026 3027 if (i == num) 3028 { 3029 FIXME("Papersize %d not found in list?\n", paperword); 3030 goto end; 3031 } 3032 3033 /* this is _10ths_ of a millimeter */ 3034 pagesetup_get_papersize_pt(data)->x = tenths_mm_to_size(data, points[i].x); 3035 pagesetup_get_papersize_pt(data)->y = tenths_mm_to_size(data, points[i].y); 3036 3037 if(pagesetup_get_orientation(data) == DMORIENT_LANDSCAPE) 3038 swap_point(pagesetup_get_papersize_pt(data)); 3039 3040 retval = TRUE; 3041 3042 end: 3043 HeapFree(GetProcessHeap(), 0, words); 3044 HeapFree(GetProcessHeap(), 0, points); 3045 pagesetup_release_a_devname(data, portname); 3046 pagesetup_release_a_devname(data, devname); 3047 pagesetup_release_devmode(data, dm); 3048 3049 return retval; 3050 } 3051 3052 /********************************************************************************************** 3053 * pagesetup_change_printer 3054 * 3055 * Redefines hDevMode and hDevNames HANDLES and initialises it. 3056 * 3057 */ 3058 static BOOL pagesetup_change_printer(LPWSTR name, pagesetup_data *data) 3059 { 3060 HANDLE hprn; 3061 DWORD needed; 3062 PRINTER_INFO_2W *prn_info = NULL; 3063 DRIVER_INFO_3W *drv_info = NULL; 3064 DEVMODEW *dm = NULL; 3065 BOOL retval = FALSE; 3066 3067 if(!OpenPrinterW(name, &hprn, NULL)) 3068 { 3069 ERR("Can't open printer %s\n", debugstr_w(name)); 3070 goto end; 3071 } 3072 3073 GetPrinterW(hprn, 2, NULL, 0, &needed); 3074 prn_info = HeapAlloc(GetProcessHeap(), 0, needed); 3075 GetPrinterW(hprn, 2, (LPBYTE)prn_info, needed, &needed); 3076 GetPrinterDriverW(hprn, NULL, 3, NULL, 0, &needed); 3077 drv_info = HeapAlloc(GetProcessHeap(), 0, needed); 3078 if(!GetPrinterDriverW(hprn, NULL, 3, (LPBYTE)drv_info, needed, &needed)) 3079 { 3080 ERR("GetPrinterDriverA failed for %s, fix your config!\n", debugstr_w(prn_info->pPrinterName)); 3081 goto end; 3082 } 3083 ClosePrinter(hprn); 3084 3085 needed = DocumentPropertiesW(0, 0, name, NULL, NULL, 0); 3086 if(needed == -1) 3087 { 3088 ERR("DocumentProperties fails on %s\n", debugstr_w(name)); 3089 goto end; 3090 } 3091 3092 dm = HeapAlloc(GetProcessHeap(), 0, needed); 3093 DocumentPropertiesW(0, 0, name, dm, NULL, DM_OUT_BUFFER); 3094 3095 pagesetup_set_devmode(data, dm); 3096 pagesetup_set_devnames(data, drv_info->pDriverPath, prn_info->pPrinterName, 3097 prn_info->pPortName); 3098 3099 retval = TRUE; 3100 end: 3101 HeapFree(GetProcessHeap(), 0, dm); 3102 HeapFree(GetProcessHeap(), 0, prn_info); 3103 HeapFree(GetProcessHeap(), 0, drv_info); 3104 return retval; 3105 } 3106 3107 /**************************************************************************************** 3108 * pagesetup_init_combos 3109 * 3110 * Fills Printers, Paper and Source combos 3111 * 3112 */ 3113 static void pagesetup_init_combos(HWND hDlg, pagesetup_data *data) 3114 { 3115 DEVMODEW *dm; 3116 LPWSTR devname, portname; 3117 3118 dm = pagesetup_get_devmode(data); 3119 devname = pagesetup_get_devname(data); 3120 portname = pagesetup_get_portname(data); 3121 3122 PRINTDLG_SetUpPrinterListComboW(hDlg, cmb1, devname); 3123 PRINTDLG_SetUpPaperComboBoxW(hDlg, cmb2, devname, portname, dm); 3124 PRINTDLG_SetUpPaperComboBoxW(hDlg, cmb3, devname, portname, dm); 3125 3126 pagesetup_release_a_devname(data, portname); 3127 pagesetup_release_a_devname(data, devname); 3128 pagesetup_release_devmode(data, dm); 3129 } 3130 3131 3132 /**************************************************************************************** 3133 * pagesetup_change_printer_dialog 3134 * 3135 * Pops up another dialog that lets the user pick another printer. 3136 * 3137 * For now we display the PrintDlg, this should display a striped down version of it. 3138 */ 3139 static void pagesetup_change_printer_dialog(HWND hDlg, pagesetup_data *data) 3140 { 3141 PRINTDLGW prnt; 3142 LPWSTR drvname, devname, portname; 3143 DEVMODEW *tmp_dm, *dm; 3144 3145 memset(&prnt, 0, sizeof(prnt)); 3146 prnt.lStructSize = sizeof(prnt); 3147 prnt.Flags = 0; 3148 prnt.hwndOwner = hDlg; 3149 3150 drvname = pagesetup_get_drvname(data); 3151 devname = pagesetup_get_devname(data); 3152 portname = pagesetup_get_portname(data); 3153 prnt.hDevNames = 0; 3154 PRINTDLG_CreateDevNamesW(&prnt.hDevNames, drvname, devname, portname); 3155 pagesetup_release_a_devname(data, portname); 3156 pagesetup_release_a_devname(data, devname); 3157 pagesetup_release_a_devname(data, drvname); 3158 3159 tmp_dm = pagesetup_get_devmode(data); 3160 prnt.hDevMode = GlobalAlloc(GMEM_MOVEABLE, tmp_dm->dmSize + tmp_dm->dmDriverExtra); 3161 dm = GlobalLock(prnt.hDevMode); 3162 memcpy(dm, tmp_dm, tmp_dm->dmSize + tmp_dm->dmDriverExtra); 3163 GlobalUnlock(prnt.hDevMode); 3164 pagesetup_release_devmode(data, tmp_dm); 3165 3166 if (PrintDlgW(&prnt)) 3167 { 3168 DEVMODEW *dm = GlobalLock(prnt.hDevMode); 3169 DEVNAMES *dn = GlobalLock(prnt.hDevNames); 3170 3171 pagesetup_set_devnames(data, (WCHAR*)dn + dn->wDriverOffset, 3172 (WCHAR*)dn + dn->wDeviceOffset, (WCHAR *)dn + dn->wOutputOffset); 3173 pagesetup_set_devmode(data, dm); 3174 GlobalUnlock(prnt.hDevNames); 3175 GlobalUnlock(prnt.hDevMode); 3176 pagesetup_init_combos(hDlg, data); 3177 } 3178 3179 GlobalFree(prnt.hDevMode); 3180 GlobalFree(prnt.hDevNames); 3181 3182 } 3183 3184 /****************************************************************************************** 3185 * pagesetup_change_preview 3186 * 3187 * Changes paper preview size / position 3188 * 3189 */ 3190 static void pagesetup_change_preview(const pagesetup_data *data) 3191 { 3192 LONG width, height, x, y; 3193 RECT tmp; 3194 const int shadow = 4; 3195 3196 if(pagesetup_get_orientation(data) == DMORIENT_LANDSCAPE) 3197 { 3198 width = data->rtDrawRect.right - data->rtDrawRect.left; 3199 height = pagesetup_get_papersize_pt(data)->y * width / pagesetup_get_papersize_pt(data)->x; 3200 } 3201 else 3202 { 3203 height = data->rtDrawRect.bottom - data->rtDrawRect.top; 3204 width = pagesetup_get_papersize_pt(data)->x * height / pagesetup_get_papersize_pt(data)->y; 3205 } 3206 x = (data->rtDrawRect.right + data->rtDrawRect.left - width) / 2; 3207 y = (data->rtDrawRect.bottom + data->rtDrawRect.top - height) / 2; 3208 TRACE("draw rect %s x=%d, y=%d, w=%d, h=%d\n", 3209 wine_dbgstr_rect(&data->rtDrawRect), x, y, width, height); 3210 3211 MoveWindow(GetDlgItem(data->hDlg, rct2), x + width, y + shadow, shadow, height, FALSE); 3212 MoveWindow(GetDlgItem(data->hDlg, rct3), x + shadow, y + height, width, shadow, FALSE); 3213 MoveWindow(GetDlgItem(data->hDlg, rct1), x, y, width, height, FALSE); 3214 3215 tmp = data->rtDrawRect; 3216 tmp.right += shadow; 3217 tmp.bottom += shadow; 3218 InvalidateRect(data->hDlg, &tmp, TRUE); 3219 } 3220 3221 static inline LONG *element_from_margin_id(RECT *rc, WORD id) 3222 { 3223 switch(id) 3224 { 3225 case edt4: return &rc->left; 3226 case edt5: return &rc->top; 3227 case edt6: return &rc->right; 3228 case edt7: return &rc->bottom; 3229 } 3230 return NULL; 3231 } 3232 3233 static void update_margin_edits(HWND hDlg, const pagesetup_data *data, WORD id) 3234 { 3235 WCHAR str[100]; 3236 WORD idx; 3237 3238 for(idx = edt4; idx <= edt7; idx++) 3239 { 3240 if(id == 0 || id == idx) 3241 { 3242 size2str(data, *element_from_margin_id(pagesetup_get_margin_rect(data), idx), str); 3243 SetDlgItemTextW(hDlg, idx, str); 3244 } 3245 } 3246 } 3247 3248 static void margin_edit_notification(HWND hDlg, const pagesetup_data *data, WORD msg, WORD id) 3249 { 3250 switch (msg) 3251 { 3252 case EN_CHANGE: 3253 { 3254 WCHAR buf[10]; 3255 LONG val = 0; 3256 LONG *value = element_from_margin_id(pagesetup_get_margin_rect(data), id); 3257 3258 if (GetDlgItemTextW(hDlg, id, buf, ARRAY_SIZE(buf)) != 0) 3259 { 3260 WCHAR *end; 3261 WCHAR decimal = get_decimal_sep(); 3262 3263 val = wcstol(buf, &end, 10); 3264 if(end != buf || *end == decimal) 3265 { 3266 int mult = is_metric(data) ? 100 : 1000; 3267 val *= mult; 3268 if(*end == decimal) 3269 { 3270 while(mult > 1) 3271 { 3272 end++; 3273 mult /= 10; 3274 if(iswdigit(*end)) 3275 val += (*end - '0') * mult; 3276 else 3277 break; 3278 } 3279 } 3280 } 3281 } 3282 *value = val; 3283 return; 3284 } 3285 3286 case EN_KILLFOCUS: 3287 update_margin_edits(hDlg, data, id); 3288 return; 3289 } 3290 } 3291 3292 static void set_margin_groupbox_title(HWND hDlg, const pagesetup_data *data) 3293 { 3294 WCHAR title[256]; 3295 3296 if(LoadStringW(COMDLG32_hInstance, is_metric(data) ? PD32_MARGINS_IN_MILLIMETERS : PD32_MARGINS_IN_INCHES, 3297 title, ARRAY_SIZE(title))) 3298 SetDlgItemTextW(hDlg, grp4, title); 3299 } 3300 3301 static void pagesetup_update_orientation_buttons(HWND hDlg, const pagesetup_data *data) 3302 { 3303 if (pagesetup_get_orientation(data) == DMORIENT_LANDSCAPE) 3304 CheckRadioButton(hDlg, rad1, rad2, rad2); 3305 else 3306 CheckRadioButton(hDlg, rad1, rad2, rad1); 3307 } 3308 3309 /**************************************************************************************** 3310 * pagesetup_printer_properties 3311 * 3312 * Handle invocation of the 'Properties' button (not present in the default template). 3313 */ 3314 static void pagesetup_printer_properties(HWND hDlg, pagesetup_data *data) 3315 { 3316 HANDLE hprn; 3317 LPWSTR devname; 3318 DEVMODEW *dm; 3319 LRESULT count; 3320 int i; 3321 3322 devname = pagesetup_get_devname(data); 3323 3324 if (!OpenPrinterW(devname, &hprn, NULL)) 3325 { 3326 FIXME("Call to OpenPrinter did not succeed!\n"); 3327 pagesetup_release_a_devname(data, devname); 3328 return; 3329 } 3330 3331 dm = pagesetup_get_devmode(data); 3332 DocumentPropertiesW(hDlg, hprn, devname, dm, dm, DM_IN_BUFFER | DM_OUT_BUFFER | DM_IN_PROMPT); 3333 pagesetup_set_devmode(data, dm); 3334 pagesetup_release_devmode(data, dm); 3335 pagesetup_release_a_devname(data, devname); 3336 ClosePrinter(hprn); 3337 3338 /* Changing paper */ 3339 pagesetup_update_papersize(data); 3340 pagesetup_update_orientation_buttons(hDlg, data); 3341 3342 /* Changing paper preview */ 3343 pagesetup_change_preview(data); 3344 3345 /* Selecting paper in combo */ 3346 count = SendDlgItemMessageW(hDlg, cmb2, CB_GETCOUNT, 0, 0); 3347 if(count != CB_ERR) 3348 { 3349 WORD paperword = pagesetup_get_papersize(data); 3350 for(i = 0; i < count; i++) 3351 { 3352 if(SendDlgItemMessageW(hDlg, cmb2, CB_GETITEMDATA, i, 0) == paperword) { 3353 SendDlgItemMessageW(hDlg, cmb2, CB_SETCURSEL, i, 0); 3354 break; 3355 } 3356 } 3357 } 3358 } 3359 3360 /******************************************************************************** 3361 * pagesetup_wm_command 3362 * process WM_COMMAND message for PageSetupDlg 3363 * 3364 * PARAMS 3365 * hDlg [in] Main dialog HANDLE 3366 * wParam [in] WM_COMMAND wParam 3367 * lParam [in] WM_COMMAND lParam 3368 * pda [in/out] ptr to PageSetupDataA 3369 */ 3370 3371 static BOOL pagesetup_wm_command(HWND hDlg, WPARAM wParam, LPARAM lParam, pagesetup_data *data) 3372 { 3373 WORD msg = HIWORD(wParam); 3374 WORD id = LOWORD(wParam); 3375 3376 TRACE("loword (lparam) %d, wparam 0x%lx, lparam %08lx\n", 3377 LOWORD(lParam),wParam,lParam); 3378 switch (id) { 3379 case IDOK: 3380 EndDialog(hDlg, TRUE); 3381 return TRUE ; 3382 3383 case IDCANCEL: 3384 EndDialog(hDlg, FALSE); 3385 return FALSE ; 3386 3387 case psh3: /* Printer... */ 3388 pagesetup_change_printer_dialog(hDlg, data); 3389 return TRUE; 3390 3391 case rad1: /* Portrait */ 3392 case rad2: /* Landscape */ 3393 if((id == rad1 && pagesetup_get_orientation(data) == DMORIENT_LANDSCAPE) || 3394 (id == rad2 && pagesetup_get_orientation(data) == DMORIENT_PORTRAIT)) 3395 { 3396 pagesetup_set_orientation(data, (id == rad1) ? DMORIENT_PORTRAIT : DMORIENT_LANDSCAPE); 3397 pagesetup_update_papersize(data); 3398 rotate_rect(pagesetup_get_margin_rect(data), (id == rad2)); 3399 update_margin_edits(hDlg, data, 0); 3400 pagesetup_change_preview(data); 3401 } 3402 break; 3403 case cmb1: /* Printer combo */ 3404 if(msg == CBN_SELCHANGE) 3405 { 3406 WCHAR *name; 3407 INT index = SendDlgItemMessageW(hDlg, id, CB_GETCURSEL, 0, 0); 3408 INT length = SendDlgItemMessageW(hDlg, id, CB_GETLBTEXTLEN, index, 0); 3409 name = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(length+1)); 3410 SendDlgItemMessageW(hDlg, id, CB_GETLBTEXT, index, (LPARAM)name); 3411 pagesetup_change_printer(name, data); 3412 pagesetup_init_combos(hDlg, data); 3413 HeapFree(GetProcessHeap(),0,name); 3414 } 3415 break; 3416 case cmb2: /* Paper combo */ 3417 if(msg == CBN_SELCHANGE) 3418 { 3419 DWORD paperword = SendDlgItemMessageW(hDlg, cmb2, CB_GETITEMDATA, 3420 SendDlgItemMessageW(hDlg, cmb2, CB_GETCURSEL, 0, 0), 0); 3421 if (paperword != CB_ERR) 3422 { 3423 pagesetup_set_papersize(data, paperword); 3424 pagesetup_update_papersize(data); 3425 pagesetup_change_preview(data); 3426 } else 3427 FIXME("could not get dialog text for papersize cmbbox?\n"); 3428 } 3429 break; 3430 case cmb3: /* Paper Source */ 3431 if(msg == CBN_SELCHANGE) 3432 { 3433 WORD source = SendDlgItemMessageW(hDlg, cmb3, CB_GETITEMDATA, 3434 SendDlgItemMessageW(hDlg, cmb3, CB_GETCURSEL, 0, 0), 0); 3435 pagesetup_set_defaultsource(data, source); 3436 } 3437 break; 3438 case psh2: /* Printer Properties button */ 3439 pagesetup_printer_properties(hDlg, data); 3440 break; 3441 case edt4: 3442 case edt5: 3443 case edt6: 3444 case edt7: 3445 margin_edit_notification(hDlg, data, msg, id); 3446 break; 3447 } 3448 InvalidateRect(GetDlgItem(hDlg, rct1), NULL, TRUE); 3449 return FALSE; 3450 } 3451 3452 /*********************************************************************** 3453 * default_page_paint_hook 3454 * Default hook paint procedure that receives WM_PSD_* messages from the dialog box 3455 * whenever the sample page is redrawn. 3456 */ 3457 static UINT_PTR default_page_paint_hook(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam, 3458 const pagesetup_data *data) 3459 { 3460 LPRECT lprc = (LPRECT) lParam; 3461 HDC hdc = (HDC) wParam; 3462 HPEN hpen, holdpen; 3463 LOGFONTW lf; 3464 HFONT hfont, holdfont; 3465 INT oldbkmode; 3466 TRACE("uMsg: WM_USER+%d\n",uMsg-WM_USER); 3467 /* Call user paint hook if enable */ 3468 if (pagesetup_get_flags(data) & PSD_ENABLEPAGEPAINTHOOK) 3469 if (pagesetup_get_hook(data, page_paint_hook)(hwndDlg, uMsg, wParam, lParam)) 3470 return TRUE; 3471 3472 switch (uMsg) { 3473 /* LPPAGESETUPDLG in lParam */ 3474 case WM_PSD_PAGESETUPDLG: 3475 /* Inform about the sample page rectangle */ 3476 case WM_PSD_FULLPAGERECT: 3477 /* Inform about the margin rectangle */ 3478 case WM_PSD_MINMARGINRECT: 3479 return FALSE; 3480 3481 /* Draw dashed rectangle showing margins */ 3482 case WM_PSD_MARGINRECT: 3483 hpen = CreatePen(PS_DASH, 1, GetSysColor(COLOR_3DSHADOW)); 3484 holdpen = SelectObject(hdc, hpen); 3485 Rectangle(hdc, lprc->left, lprc->top, lprc->right, lprc->bottom); 3486 DeleteObject(SelectObject(hdc, holdpen)); 3487 return TRUE; 3488 /* Draw the fake document */ 3489 case WM_PSD_GREEKTEXTRECT: 3490 /* select a nice scalable font, because we want the text really small */ 3491 SystemParametersInfoW(SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, 0); 3492 lf.lfHeight = 6; /* value chosen based on visual effect */ 3493 hfont = CreateFontIndirectW(&lf); 3494 holdfont = SelectObject(hdc, hfont); 3495 3496 /* if text not loaded, then do so now */ 3497 if (wszFakeDocumentText[0] == '\0') 3498 LoadStringW(COMDLG32_hInstance, 3499 IDS_FAKEDOCTEXT, 3500 wszFakeDocumentText, 3501 ARRAY_SIZE(wszFakeDocumentText)); 3502 3503 oldbkmode = SetBkMode(hdc, TRANSPARENT); 3504 DrawTextW(hdc, wszFakeDocumentText, -1, lprc, DT_TOP|DT_LEFT|DT_NOPREFIX|DT_WORDBREAK); 3505 SetBkMode(hdc, oldbkmode); 3506 3507 DeleteObject(SelectObject(hdc, holdfont)); 3508 return TRUE; 3509 3510 /* Envelope stamp */ 3511 case WM_PSD_ENVSTAMPRECT: 3512 /* Return address */ 3513 case WM_PSD_YAFULLPAGERECT: 3514 FIXME("envelope/stamp is not implemented\n"); 3515 return FALSE; 3516 default: 3517 FIXME("Unknown message %x\n",uMsg); 3518 return FALSE; 3519 } 3520 return TRUE; 3521 } 3522 3523 /*********************************************************************** 3524 * PagePaintProc 3525 * The main paint procedure for the PageSetupDlg function. 3526 * The Page Setup dialog box includes an image of a sample page that shows how 3527 * the user's selections affect the appearance of the printed output. 3528 * The image consists of a rectangle that represents the selected paper 3529 * or envelope type, with a dotted-line rectangle representing 3530 * the current margins, and partial (Greek text) characters 3531 * to show how text looks on the printed page. 3532 * 3533 * The following messages in the order sends to user hook procedure: 3534 * WM_PSD_PAGESETUPDLG Draw the contents of the sample page 3535 * WM_PSD_FULLPAGERECT Inform about the bounding rectangle 3536 * WM_PSD_MINMARGINRECT Inform about the margin rectangle (min margin?) 3537 * WM_PSD_MARGINRECT Draw the margin rectangle 3538 * WM_PSD_GREEKTEXTRECT Draw the Greek text inside the margin rectangle 3539 * If any of first three messages returns TRUE, painting done. 3540 * 3541 * PARAMS: 3542 * hWnd [in] Handle to the Page Setup dialog box 3543 * uMsg [in] Received message 3544 * 3545 * TODO: 3546 * WM_PSD_ENVSTAMPRECT Draw in the envelope-stamp rectangle (for envelopes only) 3547 * WM_PSD_YAFULLPAGERECT Draw the return address portion (for envelopes and other paper sizes) 3548 * 3549 * RETURNS: 3550 * FALSE if all done correctly 3551 * 3552 */ 3553 3554 3555 static LRESULT CALLBACK 3556 PRINTDLG_PagePaintProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 3557 { 3558 PAINTSTRUCT ps; 3559 RECT rcClient, rcMargin; 3560 HPEN hpen, holdpen; 3561 HDC hdc; 3562 HBRUSH hbrush, holdbrush; 3563 pagesetup_data *data; 3564 int papersize=0, orientation=0; /* FIXME: set these values for the user paint hook */ 3565 double scalx, scaly; 3566 3567 if (uMsg != WM_PAINT) 3568 return CallWindowProcA(lpfnStaticWndProc, hWnd, uMsg, wParam, lParam); 3569 3570 /* Processing WM_PAINT message */ 3571 data = GetPropW(hWnd, pagesetupdlg_prop); 3572 if (!data) { 3573 WARN("__WINE_PAGESETUPDLGDATA prop not set?\n"); 3574 return FALSE; 3575 } 3576 if (default_page_paint_hook(hWnd, WM_PSD_PAGESETUPDLG, MAKELONG(papersize, orientation), 3577 pagesetup_get_dlg_struct(data), data)) 3578 return FALSE; 3579 3580 hdc = BeginPaint(hWnd, &ps); 3581 GetClientRect(hWnd, &rcClient); 3582 3583 scalx = rcClient.right / (double)pagesetup_get_papersize_pt(data)->x; 3584 scaly = rcClient.bottom / (double)pagesetup_get_papersize_pt(data)->y; 3585 rcMargin = rcClient; 3586 3587 rcMargin.left += pagesetup_get_margin_rect(data)->left * scalx; 3588 rcMargin.top += pagesetup_get_margin_rect(data)->top * scaly; 3589 rcMargin.right -= pagesetup_get_margin_rect(data)->right * scalx; 3590 rcMargin.bottom -= pagesetup_get_margin_rect(data)->bottom * scaly; 3591 3592 /* if the space is too small then we make sure to not draw anything */ 3593 rcMargin.left = min(rcMargin.left, rcMargin.right); 3594 rcMargin.top = min(rcMargin.top, rcMargin.bottom); 3595 3596 if (!default_page_paint_hook(hWnd, WM_PSD_FULLPAGERECT, (WPARAM)hdc, (LPARAM)&rcClient, data) && 3597 !default_page_paint_hook(hWnd, WM_PSD_MINMARGINRECT, (WPARAM)hdc, (LPARAM)&rcMargin, data) ) 3598 { 3599 /* fill background */ 3600 hbrush = GetSysColorBrush(COLOR_3DHIGHLIGHT); 3601 FillRect(hdc, &rcClient, hbrush); 3602 holdbrush = SelectObject(hdc, hbrush); 3603 3604 hpen = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DSHADOW)); 3605 holdpen = SelectObject(hdc, hpen); 3606 3607 /* paint left edge */ 3608 MoveToEx(hdc, rcClient.left, rcClient.top, NULL); 3609 LineTo(hdc, rcClient.left, rcClient.bottom-1); 3610 3611 /* paint top edge */ 3612 MoveToEx(hdc, rcClient.left, rcClient.top, NULL); 3613 LineTo(hdc, rcClient.right, rcClient.top); 3614 3615 hpen = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DDKSHADOW)); 3616 DeleteObject(SelectObject(hdc, hpen)); 3617 3618 /* paint right edge */ 3619 MoveToEx(hdc, rcClient.right-1, rcClient.top, NULL); 3620 LineTo(hdc, rcClient.right-1, rcClient.bottom); 3621 3622 /* paint bottom edge */ 3623 MoveToEx(hdc, rcClient.left, rcClient.bottom-1, NULL); 3624 LineTo(hdc, rcClient.right, rcClient.bottom-1); 3625 3626 DeleteObject(SelectObject(hdc, holdpen)); 3627 DeleteObject(SelectObject(hdc, holdbrush)); 3628 3629 default_page_paint_hook(hWnd, WM_PSD_MARGINRECT, (WPARAM)hdc, (LPARAM)&rcMargin, data); 3630 3631 /* give text a bit of a space from the frame */ 3632 InflateRect(&rcMargin, -2, -2); 3633 3634 /* if the space is too small then we make sure to not draw anything */ 3635 rcMargin.left = min(rcMargin.left, rcMargin.right); 3636 rcMargin.top = min(rcMargin.top, rcMargin.bottom); 3637 3638 default_page_paint_hook(hWnd, WM_PSD_GREEKTEXTRECT, (WPARAM)hdc, (LPARAM)&rcMargin, data); 3639 } 3640 3641 EndPaint(hWnd, &ps); 3642 return FALSE; 3643 } 3644 3645 /******************************************************* 3646 * The margin edit controls are subclassed to filter 3647 * anything other than numbers and the decimal separator. 3648 */ 3649 static LRESULT CALLBACK pagesetup_margin_editproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) 3650 { 3651 if (msg == WM_CHAR) 3652 { 3653 WCHAR decimal = get_decimal_sep(); 3654 WCHAR wc = (WCHAR)wparam; 3655 if(!iswdigit(wc) && wc != decimal && wc != VK_BACK) return 0; 3656 } 3657 return CallWindowProcW(edit_wndproc, hwnd, msg, wparam, lparam); 3658 } 3659 3660 static void subclass_margin_edits(HWND hDlg) 3661 { 3662 int id; 3663 WNDPROC old_proc; 3664 3665 for(id = edt4; id <= edt7; id++) 3666 { 3667 old_proc = (WNDPROC)SetWindowLongPtrW(GetDlgItem(hDlg, id), 3668 GWLP_WNDPROC, 3669 (ULONG_PTR)pagesetup_margin_editproc); 3670 InterlockedCompareExchangePointer((void**)&edit_wndproc, old_proc, NULL); 3671 } 3672 } 3673 3674 /*********************************************************************** 3675 * pagesetup_dlg_proc 3676 * 3677 * Message handler for PageSetupDlg 3678 */ 3679 static INT_PTR CALLBACK pagesetup_dlg_proc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) 3680 { 3681 pagesetup_data *data; 3682 INT_PTR res = FALSE; 3683 HWND hDrawWnd; 3684 3685 if (uMsg == WM_INITDIALOG) { /*Init dialog*/ 3686 data = (pagesetup_data *)lParam; 3687 data->hDlg = hDlg; 3688 3689 hDrawWnd = GetDlgItem(hDlg, rct1); 3690 TRACE("set property to %p\n", data); 3691 SetPropW(hDlg, pagesetupdlg_prop, data); 3692 SetPropW(hDrawWnd, pagesetupdlg_prop, data); 3693 GetWindowRect(hDrawWnd, &data->rtDrawRect); /* Calculating rect in client coordinates where paper draws */ 3694 MapWindowPoints( 0, hDlg, (LPPOINT)&data->rtDrawRect, 2 ); 3695 lpfnStaticWndProc = (WNDPROC)SetWindowLongPtrW( 3696 hDrawWnd, 3697 GWLP_WNDPROC, 3698 (ULONG_PTR)PRINTDLG_PagePaintProc); 3699 3700 /* FIXME: Paint hook. Must it be at begin of initialization or at end? */ 3701 res = TRUE; 3702 if (pagesetup_get_flags(data) & PSD_ENABLEPAGESETUPHOOK) 3703 { 3704 if (!pagesetup_get_hook(data, page_setup_hook)(hDlg, uMsg, wParam, 3705 pagesetup_get_dlg_struct(data))) 3706 FIXME("Setup page hook failed?\n"); 3707 } 3708 3709 /* if printer button disabled */ 3710 if (pagesetup_get_flags(data) & PSD_DISABLEPRINTER) 3711 EnableWindow(GetDlgItem(hDlg, psh3), FALSE); 3712 /* if margin edit boxes disabled */ 3713 if (pagesetup_get_flags(data) & PSD_DISABLEMARGINS) 3714 { 3715 EnableWindow(GetDlgItem(hDlg, edt4), FALSE); 3716 EnableWindow(GetDlgItem(hDlg, edt5), FALSE); 3717 EnableWindow(GetDlgItem(hDlg, edt6), FALSE); 3718 EnableWindow(GetDlgItem(hDlg, edt7), FALSE); 3719 } 3720 3721 /* Set orientation radiobuttons properly */ 3722 pagesetup_update_orientation_buttons(hDlg, data); 3723 3724 /* if orientation disabled */ 3725 if (pagesetup_get_flags(data) & PSD_DISABLEORIENTATION) 3726 { 3727 EnableWindow(GetDlgItem(hDlg,rad1),FALSE); 3728 EnableWindow(GetDlgItem(hDlg,rad2),FALSE); 3729 } 3730 3731 /* We fill them out enabled or not */ 3732 if (!(pagesetup_get_flags(data) & PSD_MARGINS)) 3733 { 3734 /* default is 1 inch */ 3735 LONG size = thousandths_inch_to_size(data, 1000); 3736 SetRect(pagesetup_get_margin_rect(data), size, size, size, size); 3737 } 3738 update_margin_edits(hDlg, data, 0); 3739 subclass_margin_edits(hDlg); 3740 set_margin_groupbox_title(hDlg, data); 3741 3742 /* if paper disabled */ 3743 if (pagesetup_get_flags(data) & PSD_DISABLEPAPER) 3744 { 3745 EnableWindow(GetDlgItem(hDlg,cmb2),FALSE); 3746 EnableWindow(GetDlgItem(hDlg,cmb3),FALSE); 3747 } 3748 3749 /* filling combos: printer, paper, source. selecting current printer (from DEVMODEA) */ 3750 pagesetup_init_combos(hDlg, data); 3751 pagesetup_update_papersize(data); 3752 pagesetup_set_defaultsource(data, DMBIN_FORMSOURCE); /* FIXME: This is the auto select bin. Is this correct? */ 3753 3754 /* Drawing paper prev */ 3755 pagesetup_change_preview(data); 3756 return TRUE; 3757 } else { 3758 data = GetPropW(hDlg, pagesetupdlg_prop); 3759 if (!data) 3760 { 3761 WARN("__WINE_PAGESETUPDLGDATA prop not set?\n"); 3762 return FALSE; 3763 } 3764 if (pagesetup_get_flags(data) & PSD_ENABLEPAGESETUPHOOK) 3765 { 3766 res = pagesetup_get_hook(data, page_setup_hook)(hDlg, uMsg, wParam, lParam); 3767 if (res) return res; 3768 } 3769 } 3770 switch (uMsg) { 3771 case WM_COMMAND: 3772 return pagesetup_wm_command(hDlg, wParam, lParam, data); 3773 } 3774 return FALSE; 3775 } 3776 3777 static WCHAR *get_default_printer(void) 3778 { 3779 WCHAR *name = NULL; 3780 DWORD len = 0; 3781 3782 GetDefaultPrinterW(NULL, &len); 3783 if(len) 3784 { 3785 name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 3786 GetDefaultPrinterW(name, &len); 3787 } 3788 return name; 3789 } 3790 3791 static void pagesetup_dump_dlg_struct(const pagesetup_data *data) 3792 { 3793 if(TRACE_ON(commdlg)) 3794 { 3795 char flagstr[1000] = ""; 3796 const struct pd_flags *pflag = psd_flags; 3797 for( ; pflag->name; pflag++) 3798 { 3799 if(pagesetup_get_flags(data) & pflag->flag) 3800 { 3801 strcat(flagstr, pflag->name); 3802 strcat(flagstr, "|"); 3803 } 3804 } 3805 TRACE("%s: (%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n" 3806 "hinst %p, flags %08x (%s)\n", 3807 data->unicode ? "unicode" : "ansi", 3808 data->u.dlgw, data->u.dlgw->hwndOwner, data->u.dlgw->hDevMode, 3809 data->u.dlgw->hDevNames, data->u.dlgw->hInstance, 3810 pagesetup_get_flags(data), flagstr); 3811 } 3812 } 3813 3814 static void *pagesetup_get_template(pagesetup_data *data) 3815 { 3816 HRSRC res; 3817 HGLOBAL tmpl_handle; 3818 3819 if(pagesetup_get_flags(data) & PSD_ENABLEPAGESETUPTEMPLATEHANDLE) 3820 { 3821 tmpl_handle = data->u.dlgw->hPageSetupTemplate; 3822 } 3823 else if(pagesetup_get_flags(data) & PSD_ENABLEPAGESETUPTEMPLATE) 3824 { 3825 if(data->unicode) 3826 res = FindResourceW(data->u.dlgw->hInstance, 3827 data->u.dlgw->lpPageSetupTemplateName, (LPWSTR)RT_DIALOG); 3828 else 3829 res = FindResourceA(data->u.dlga->hInstance, 3830 data->u.dlga->lpPageSetupTemplateName, (LPSTR)RT_DIALOG); 3831 tmpl_handle = LoadResource(data->u.dlgw->hInstance, res); 3832 } 3833 else 3834 { 3835 res = FindResourceW(COMDLG32_hInstance, MAKEINTRESOURCEW(PAGESETUPDLGORD), 3836 (LPWSTR)RT_DIALOG); 3837 tmpl_handle = LoadResource(COMDLG32_hInstance, res); 3838 } 3839 return LockResource(tmpl_handle); 3840 } 3841 3842 static BOOL pagesetup_common(pagesetup_data *data) 3843 { 3844 BOOL ret; 3845 void *tmpl; 3846 3847 if(!pagesetup_get_dlg_struct(data)) 3848 { 3849 COMDLG32_SetCommDlgExtendedError(CDERR_INITIALIZATION); 3850 return FALSE; 3851 } 3852 3853 pagesetup_dump_dlg_struct(data); 3854 3855 if(data->u.dlgw->lStructSize != sizeof(PAGESETUPDLGW)) 3856 { 3857 COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE); 3858 return FALSE; 3859 } 3860 3861 if ((pagesetup_get_flags(data) & PSD_ENABLEPAGEPAINTHOOK) && 3862 (pagesetup_get_hook(data, page_paint_hook) == NULL)) 3863 { 3864 COMDLG32_SetCommDlgExtendedError(CDERR_NOHOOK); 3865 return FALSE; 3866 } 3867 3868 if(!(pagesetup_get_flags(data) & (PSD_INTHOUSANDTHSOFINCHES | PSD_INHUNDREDTHSOFMILLIMETERS))) 3869 data->u.dlgw->Flags |= is_default_metric() ? 3870 PSD_INHUNDREDTHSOFMILLIMETERS : PSD_INTHOUSANDTHSOFINCHES; 3871 3872 if (!data->u.dlgw->hDevMode || !data->u.dlgw->hDevNames) 3873 { 3874 WCHAR *def = get_default_printer(); 3875 if(!def) 3876 { 3877 if (!(pagesetup_get_flags(data) & PSD_NOWARNING)) 3878 { 3879 WCHAR errstr[256]; 3880 LoadStringW(COMDLG32_hInstance, PD32_NO_DEFAULT_PRINTER, errstr, 255); 3881 MessageBoxW(data->u.dlgw->hwndOwner, errstr, 0, MB_OK | MB_ICONERROR); 3882 } 3883 COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN); 3884 return FALSE; 3885 } 3886 pagesetup_change_printer(def, data); 3887 HeapFree(GetProcessHeap(), 0, def); 3888 } 3889 3890 if (pagesetup_get_flags(data) & PSD_RETURNDEFAULT) 3891 { 3892 pagesetup_update_papersize(data); 3893 return TRUE; 3894 } 3895 3896 tmpl = pagesetup_get_template(data); 3897 3898 ret = DialogBoxIndirectParamW(data->u.dlgw->hInstance, tmpl, 3899 data->u.dlgw->hwndOwner, 3900 pagesetup_dlg_proc, (LPARAM)data) > 0; 3901 return ret; 3902 } 3903 3904 /*********************************************************************** 3905 * PageSetupDlgA (COMDLG32.@) 3906 * 3907 * Displays the PAGE SETUP dialog box, which enables the user to specify 3908 * specific properties of a printed page such as 3909 * size, source, orientation and the width of the page margins. 3910 * 3911 * PARAMS 3912 * setupdlg [IO] PAGESETUPDLGA struct 3913 * 3914 * RETURNS 3915 * TRUE if the user pressed the OK button 3916 * FALSE if the user cancelled the window or an error occurred 3917 * 3918 * NOTES 3919 * The values of hDevMode and hDevNames are filled on output and can be 3920 * changed in PAGESETUPDLG when they are passed in PageSetupDlg. 3921 * 3922 */ 3923 BOOL WINAPI PageSetupDlgA(LPPAGESETUPDLGA setupdlg) 3924 { 3925 pagesetup_data data; 3926 3927 data.unicode = FALSE; 3928 data.u.dlga = setupdlg; 3929 3930 return pagesetup_common(&data); 3931 } 3932 3933 /*********************************************************************** 3934 * PageSetupDlgW (COMDLG32.@) 3935 * 3936 * See PageSetupDlgA. 3937 */ 3938 BOOL WINAPI PageSetupDlgW(LPPAGESETUPDLGW setupdlg) 3939 { 3940 pagesetup_data data; 3941 3942 data.unicode = TRUE; 3943 data.u.dlgw = setupdlg; 3944 3945 return pagesetup_common(&data); 3946 } 3947 3948 static void pdlgex_to_pdlg(const PRINTDLGEXW *pdlgex, PRINTDLGW *pdlg) 3949 { 3950 pdlg->lStructSize = sizeof(*pdlg); 3951 pdlg->hwndOwner = pdlgex->hwndOwner; 3952 pdlg->hDevMode = pdlgex->hDevMode; 3953 pdlg->hDevNames = pdlgex->hDevNames; 3954 pdlg->hDC = pdlgex->hDC; 3955 pdlg->Flags = pdlgex->Flags; 3956 if ((pdlgex->Flags & PD_NOPAGENUMS) || !pdlgex->nPageRanges || !pdlgex->lpPageRanges) 3957 { 3958 pdlg->nFromPage = 0; 3959 pdlg->nToPage = 65534; 3960 } 3961 else 3962 { 3963 pdlg->nFromPage = pdlgex->lpPageRanges[0].nFromPage; 3964 pdlg->nToPage = pdlgex->lpPageRanges[0].nToPage; 3965 } 3966 pdlg->nMinPage = pdlgex->nMinPage; 3967 pdlg->nMaxPage = pdlgex->nMaxPage; 3968 pdlg->nCopies = pdlgex->nCopies; 3969 pdlg->hInstance = pdlgex->hInstance; 3970 pdlg->lCustData = 0; 3971 pdlg->lpfnPrintHook = NULL; 3972 pdlg->lpfnSetupHook = NULL; 3973 pdlg->lpPrintTemplateName = pdlgex->lpPrintTemplateName; 3974 pdlg->lpSetupTemplateName = NULL; 3975 pdlg->hPrintTemplate = NULL; 3976 pdlg->hSetupTemplate = NULL; 3977 } 3978 3979 /* Only copy fields that are supposed to be changed. */ 3980 static void pdlg_to_pdlgex(const PRINTDLGW *pdlg, PRINTDLGEXW *pdlgex) 3981 { 3982 pdlgex->hDevMode = pdlg->hDevMode; 3983 pdlgex->hDevNames = pdlg->hDevNames; 3984 pdlgex->hDC = pdlg->hDC; 3985 if (!(pdlgex->Flags & PD_NOPAGENUMS) && pdlgex->nPageRanges && pdlgex->lpPageRanges) 3986 { 3987 pdlgex->lpPageRanges[0].nFromPage = pdlg->nFromPage; 3988 pdlgex->lpPageRanges[0].nToPage = pdlg->nToPage; 3989 } 3990 pdlgex->nMinPage = pdlg->nMinPage; 3991 pdlgex->nMaxPage = pdlg->nMaxPage; 3992 pdlgex->nCopies = pdlg->nCopies; 3993 } 3994 3995 struct callback_data 3996 { 3997 IPrintDialogCallback *callback; 3998 IObjectWithSite *object; 3999 }; 4000 4001 static UINT_PTR CALLBACK pdlgex_hook_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) 4002 { 4003 if (msg == WM_INITDIALOG) 4004 { 4005 PRINTDLGW *pd = (PRINTDLGW *)lp; 4006 struct callback_data *cb = (struct callback_data *)pd->lCustData; 4007 4008 if (cb->callback) 4009 { 4010 cb->callback->lpVtbl->SelectionChange(cb->callback); 4011 cb->callback->lpVtbl->InitDone(cb->callback); 4012 } 4013 } 4014 else 4015 { 4016 /* FIXME: store interface pointer somewhere in window properties and call it 4017 HRESULT hres; 4018 cb->callback->lpVtbl->HandleMessage(cb->callback, hwnd, msg, wp, lp, &hres); 4019 */ 4020 } 4021 4022 return 0; 4023 } 4024 4025 /*********************************************************************** 4026 * PrintDlgExA (COMDLG32.@) 4027 * 4028 * See PrintDlgExW. 4029 * 4030 * BUGS 4031 * Only a Stub 4032 * 4033 */ 4034 HRESULT WINAPI PrintDlgExA(LPPRINTDLGEXA lppd) 4035 { 4036 PRINTER_INFO_2A *pbuf; 4037 DRIVER_INFO_3A *dbuf; 4038 DEVMODEA *dm; 4039 HRESULT hr = S_OK; 4040 HANDLE hprn; 4041 4042 if ((lppd == NULL) || (lppd->lStructSize != sizeof(PRINTDLGEXA))) 4043 return E_INVALIDARG; 4044 4045 if (!IsWindow(lppd->hwndOwner)) 4046 return E_HANDLE; 4047 4048 if (lppd->nStartPage != START_PAGE_GENERAL) 4049 { 4050 if (!lppd->nPropertyPages) 4051 return E_INVALIDARG; 4052 4053 FIXME("custom property sheets (%d at %p) not supported\n", lppd->nPropertyPages, lppd->lphPropertyPages); 4054 } 4055 4056 /* Use PD_NOPAGENUMS or set nMaxPageRanges and lpPageRanges */ 4057 if (!(lppd->Flags & PD_NOPAGENUMS) && (!lppd->nMaxPageRanges || !lppd->lpPageRanges)) 4058 { 4059 return E_INVALIDARG; 4060 } 4061 4062 if (lppd->Flags & PD_RETURNDEFAULT) 4063 { 4064 if (lppd->hDevMode || lppd->hDevNames) 4065 { 4066 WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n"); 4067 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE); 4068 return E_INVALIDARG; 4069 } 4070 if (!PRINTDLG_OpenDefaultPrinter(&hprn)) 4071 { 4072 WARN("Can't find default printer\n"); 4073 COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN); 4074 return E_FAIL; 4075 } 4076 4077 pbuf = get_printer_infoA(hprn); 4078 if (!pbuf) 4079 { 4080 ClosePrinter(hprn); 4081 return E_FAIL; 4082 } 4083 4084 dbuf = get_driver_infoA(hprn); 4085 if (!dbuf) 4086 { 4087 HeapFree(GetProcessHeap(), 0, pbuf); 4088 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE); 4089 ClosePrinter(hprn); 4090 return E_FAIL; 4091 } 4092 dm = pbuf->pDevMode; 4093 } 4094 else 4095 { 4096 PRINTDLGA pdlg; 4097 struct callback_data cb_data = { 0 }; 4098 4099 FIXME("(%p) semi-stub\n", lppd); 4100 4101 if (lppd->lpCallback) 4102 { 4103 IUnknown_QueryInterface((IUnknown *)lppd->lpCallback, &IID_IPrintDialogCallback, (void **)&cb_data.callback); 4104 IUnknown_QueryInterface((IUnknown *)lppd->lpCallback, &IID_IObjectWithSite, (void **)&cb_data.object); 4105 } 4106 4107 /* 4108 * PRINTDLGEXA/W and PRINTDLGA/W layout is the same for A and W variants. 4109 */ 4110 pdlgex_to_pdlg((const PRINTDLGEXW *)lppd, (PRINTDLGW *)&pdlg); 4111 pdlg.Flags |= PD_ENABLEPRINTHOOK; 4112 pdlg.lpfnPrintHook = pdlgex_hook_proc; 4113 pdlg.lCustData = (LPARAM)&cb_data; 4114 4115 if (PrintDlgA(&pdlg)) 4116 { 4117 pdlg_to_pdlgex((const PRINTDLGW *)&pdlg, (PRINTDLGEXW *)lppd); 4118 lppd->dwResultAction = PD_RESULT_PRINT; 4119 } 4120 else 4121 lppd->dwResultAction = PD_RESULT_CANCEL; 4122 4123 if (cb_data.callback) 4124 cb_data.callback->lpVtbl->Release(cb_data.callback); 4125 if (cb_data.object) 4126 cb_data.object->lpVtbl->Release(cb_data.object); 4127 4128 return S_OK; 4129 } 4130 4131 ClosePrinter(hprn); 4132 4133 PRINTDLG_CreateDevNames(&(lppd->hDevNames), dbuf->pDriverPath, pbuf->pPrinterName, pbuf->pPortName); 4134 if (!lppd->hDevNames) 4135 hr = E_FAIL; 4136 4137 lppd->hDevMode = update_devmode_handleA(lppd->hDevMode, dm); 4138 if (hr == S_OK && lppd->hDevMode) { 4139 if (lppd->Flags & PD_RETURNDC) { 4140 lppd->hDC = CreateDCA(dbuf->pDriverPath, pbuf->pPrinterName, pbuf->pPortName, dm); 4141 if (!lppd->hDC) 4142 hr = E_FAIL; 4143 } 4144 else if (lppd->Flags & PD_RETURNIC) { 4145 lppd->hDC = CreateICA(dbuf->pDriverPath, pbuf->pPrinterName, pbuf->pPortName, dm); 4146 if (!lppd->hDC) 4147 hr = E_FAIL; 4148 } 4149 } 4150 else 4151 hr = E_FAIL; 4152 4153 HeapFree(GetProcessHeap(), 0, pbuf); 4154 HeapFree(GetProcessHeap(), 0, dbuf); 4155 4156 return hr; 4157 } 4158 4159 /*********************************************************************** 4160 * PrintDlgExW (COMDLG32.@) 4161 * 4162 * Display the property sheet style PRINT dialog box 4163 * 4164 * PARAMS 4165 * lppd [IO] ptr to PRINTDLGEX struct 4166 * 4167 * RETURNS 4168 * Success: S_OK 4169 * Failure: One of the following COM error codes: 4170 * E_OUTOFMEMORY Insufficient memory. 4171 * E_INVALIDARG One or more arguments are invalid. 4172 * E_POINTER Invalid pointer. 4173 * E_HANDLE Invalid handle. 4174 * E_FAIL Unspecified error. 4175 * 4176 * NOTES 4177 * This Dialog enables the user to specify specific properties of the print job. 4178 * The property sheet can also have additional application-specific and 4179 * driver-specific property pages. 4180 * 4181 * BUGS 4182 * Not fully implemented 4183 * 4184 */ 4185 HRESULT WINAPI PrintDlgExW(LPPRINTDLGEXW lppd) 4186 { 4187 PRINTER_INFO_2W *pbuf; 4188 DRIVER_INFO_3W *dbuf; 4189 DEVMODEW *dm; 4190 HRESULT hr = S_OK; 4191 HANDLE hprn; 4192 4193 if ((lppd == NULL) || (lppd->lStructSize != sizeof(PRINTDLGEXW))) { 4194 return E_INVALIDARG; 4195 } 4196 4197 if (!IsWindow(lppd->hwndOwner)) { 4198 return E_HANDLE; 4199 } 4200 4201 if (lppd->nStartPage != START_PAGE_GENERAL) 4202 { 4203 if (!lppd->nPropertyPages) 4204 return E_INVALIDARG; 4205 4206 FIXME("custom property sheets (%d at %p) not supported\n", lppd->nPropertyPages, lppd->lphPropertyPages); 4207 } 4208 4209 /* Use PD_NOPAGENUMS or set nMaxPageRanges and lpPageRanges */ 4210 if (!(lppd->Flags & PD_NOPAGENUMS) && (!lppd->nMaxPageRanges || !lppd->lpPageRanges)) 4211 { 4212 return E_INVALIDARG; 4213 } 4214 4215 if (lppd->Flags & PD_RETURNDEFAULT) { 4216 4217 if (lppd->hDevMode || lppd->hDevNames) { 4218 WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n"); 4219 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE); 4220 return E_INVALIDARG; 4221 } 4222 if (!PRINTDLG_OpenDefaultPrinter(&hprn)) { 4223 WARN("Can't find default printer\n"); 4224 COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN); 4225 return E_FAIL; 4226 } 4227 4228 pbuf = get_printer_infoW(hprn); 4229 if (!pbuf) 4230 { 4231 ClosePrinter(hprn); 4232 return E_FAIL; 4233 } 4234 4235 dbuf = get_driver_infoW(hprn); 4236 if (!dbuf) 4237 { 4238 HeapFree(GetProcessHeap(), 0, pbuf); 4239 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE); 4240 ClosePrinter(hprn); 4241 return E_FAIL; 4242 } 4243 dm = pbuf->pDevMode; 4244 } 4245 else 4246 { 4247 PRINTDLGW pdlg; 4248 struct callback_data cb_data = { 0 }; 4249 4250 FIXME("(%p) semi-stub\n", lppd); 4251 4252 if (lppd->lpCallback) 4253 { 4254 IUnknown_QueryInterface((IUnknown *)lppd->lpCallback, &IID_IPrintDialogCallback, (void **)&cb_data.callback); 4255 IUnknown_QueryInterface((IUnknown *)lppd->lpCallback, &IID_IObjectWithSite, (void **)&cb_data.object); 4256 } 4257 4258 pdlgex_to_pdlg(lppd, &pdlg); 4259 pdlg.Flags |= PD_ENABLEPRINTHOOK; 4260 pdlg.lpfnPrintHook = pdlgex_hook_proc; 4261 pdlg.lCustData = (LPARAM)&cb_data; 4262 4263 if (PrintDlgW(&pdlg)) 4264 { 4265 pdlg_to_pdlgex(&pdlg, lppd); 4266 lppd->dwResultAction = PD_RESULT_PRINT; 4267 } 4268 else 4269 lppd->dwResultAction = PD_RESULT_CANCEL; 4270 4271 if (cb_data.callback) 4272 cb_data.callback->lpVtbl->Release(cb_data.callback); 4273 if (cb_data.object) 4274 cb_data.object->lpVtbl->Release(cb_data.object); 4275 4276 return S_OK; 4277 } 4278 4279 ClosePrinter(hprn); 4280 4281 PRINTDLG_CreateDevNamesW(&(lppd->hDevNames), dbuf->pDriverPath, pbuf->pPrinterName, pbuf->pPortName); 4282 if (!lppd->hDevNames) 4283 hr = E_FAIL; 4284 4285 lppd->hDevMode = update_devmode_handleW(lppd->hDevMode, dm); 4286 if (hr == S_OK && lppd->hDevMode) { 4287 if (lppd->Flags & PD_RETURNDC) { 4288 lppd->hDC = CreateDCW(dbuf->pDriverPath, pbuf->pPrinterName, pbuf->pPortName, dm); 4289 if (!lppd->hDC) 4290 hr = E_FAIL; 4291 } 4292 else if (lppd->Flags & PD_RETURNIC) { 4293 lppd->hDC = CreateICW(dbuf->pDriverPath, pbuf->pPrinterName, pbuf->pPortName, dm); 4294 if (!lppd->hDC) 4295 hr = E_FAIL; 4296 } 4297 } 4298 else 4299 hr = E_FAIL; 4300 4301 HeapFree(GetProcessHeap(), 0, pbuf); 4302 HeapFree(GetProcessHeap(), 0, dbuf); 4303 4304 return hr; 4305 } 4306