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