Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1203 lines
29 KiB

  1. /* File: D:\WACKER\tdll\printset.c (Created: 02-Feb-1994)
  2. *
  3. * Copyright 1994 by Hilgraeve Inc. -- Monroe, MI
  4. * All rights reserved
  5. *
  6. * $Revision: 11 $
  7. * $Date: 7/08/02 6:46p $
  8. */
  9. #include <windows.h>
  10. #pragma hdrstop
  11. #include <stdio.h>
  12. #include <limits.h>
  13. #include <term\res.h>
  14. #include "stdtyp.h"
  15. #include "mc.h"
  16. #include "misc.h"
  17. #include "assert.h"
  18. #include "print.h"
  19. #include "print.hh"
  20. #include "globals.h"
  21. #include "session.h"
  22. #include "term.h"
  23. #include "tdll.h"
  24. #include "htchar.h"
  25. #include "load_res.h"
  26. #include "open_msc.h"
  27. #include "open_msc.h"
  28. #include "sf.h"
  29. #include "file_msc.h"
  30. static int printsetPrintToFile(const HPRINT hPrint);
  31. static UINT_PTR APIENTRY printPageSetupHook( HWND hdlg, UINT uiMsg, WPARAM wParam,
  32. LPARAM lParam );
  33. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  34. * FUNCTION:
  35. * printsetSetup
  36. *
  37. * DESCRIPTION:
  38. * This function is used to display the common print dialogs.
  39. *
  40. * ARGUMENTS:
  41. * hPrint - An external print handle.
  42. * hwnd - owner window handle
  43. *
  44. * RETURNS:
  45. * void
  46. *
  47. */
  48. void printsetSetup(const HPRINT hPrint, const HWND hwnd)
  49. {
  50. const HHPRINT hhPrint = (HHPRINT)hPrint;
  51. #ifdef INCL_USE_NEWPRINTDLG
  52. PRINTDLGEX pd;
  53. HRESULT hResult;
  54. #else
  55. PRINTDLG pd;
  56. #endif
  57. LPDEVNAMES pstDevNames;
  58. PDEVMODE pstDevMode;
  59. TCHAR *pszPrinterName;
  60. TCHAR *pTemp;
  61. DWORD dwSize;
  62. DWORD dwError;
  63. #if defined(_DEBUG)
  64. TCHAR ach[100];
  65. #endif
  66. if (hhPrint == 0)
  67. {
  68. assert(FALSE);
  69. return;
  70. }
  71. // Initialize basic structure elements.
  72. //
  73. #ifdef INCL_USE_NEWPRINTDLG
  74. memset (&pd, 0, sizeof(PRINTDLGEX));
  75. pd.lStructSize = sizeof(PRINTDLGEX);
  76. pd.Flags2 = 0;
  77. pd.nStartPage = START_PAGE_GENERAL;
  78. pd.dwResultAction = 0;
  79. #else
  80. memset (&pd, 0, sizeof(PRINTDLG));
  81. pd.lStructSize = sizeof(PRINTDLG);
  82. #endif
  83. pd.Flags = PD_NOWARNING | PD_NOPAGENUMS;
  84. pd.hwndOwner = hwnd;
  85. if (SendMessage(sessQueryHwndTerminal(hhPrint->hSession),
  86. WM_TERM_Q_MARKED, 0, 0))
  87. {
  88. pd.Flags |= PD_SELECTION;
  89. }
  90. // Use the previously stored information to initialize the print
  91. // common dialogs. printGetDefaults initializes this information
  92. // when a print handle is created.
  93. //
  94. if (hhPrint->pstDevMode)
  95. {
  96. // Allocate memory for the DEVMODE information and then
  97. // initialize it with the stored values from the Print Handle.
  98. //
  99. dwSize = hhPrint->pstDevMode->dmSize +
  100. hhPrint->pstDevMode->dmDriverExtra;
  101. if ((pd.hDevMode = GlobalAlloc(GMEM_MOVEABLE, dwSize)))
  102. {
  103. if ((pstDevMode = GlobalLock(pd.hDevMode)))
  104. {
  105. if (dwSize)
  106. MemCopy(pstDevMode, hhPrint->pstDevMode, dwSize);
  107. GlobalUnlock(pd.hDevMode);
  108. }
  109. }
  110. }
  111. if (hhPrint->pstDevNames)
  112. {
  113. // Allocate memory for the DEVNAMES structure in pd, then
  114. // initialize it with the stored values from the Print Handle.
  115. // This sequence determines the variable structure size of
  116. // DEVNAMES.
  117. //
  118. pTemp = (TCHAR *)hhPrint->pstDevNames;
  119. pTemp += hhPrint->pstDevNames->wOutputOffset;
  120. pTemp += StrCharGetByteCount(pTemp) + sizeof(TCHAR);
  121. dwSize = (DWORD)(pTemp - (TCHAR*)hhPrint->pstDevNames);
  122. if ((pd.hDevNames = GlobalAlloc(GMEM_MOVEABLE, dwSize)))
  123. {
  124. if ((pstDevNames = GlobalLock(pd.hDevNames)))
  125. {
  126. if (dwSize)
  127. MemCopy(pstDevNames, hhPrint->pstDevNames, dwSize);
  128. GlobalUnlock(pd.hDevNames);
  129. }
  130. }
  131. }
  132. // Initialize the PrintToFilename array every time before we go
  133. // into the dialog.
  134. //
  135. TCHAR_Fill(hhPrint->achPrintToFileName,
  136. TEXT('\0'),
  137. sizeof(hhPrint->achPrintToFileName) / sizeof(TCHAR));
  138. // Display the dialog.
  139. //
  140. #ifdef INCL_USE_NEWPRINTDLG
  141. pd.Flags2 = 0;
  142. hResult = PrintDlgEx( &pd );
  143. if ( hResult != S_OK)
  144. #else
  145. if (!PrintDlg(&pd))
  146. #endif
  147. {
  148. dwError = CommDlgExtendedError();
  149. #if defined(_DEBUG)
  150. if (dwError != 0)
  151. {
  152. wsprintf(ach, "PrintDlg error 0x%x", dwError);
  153. MessageBox(hwnd, ach, "Debug", MB_ICONINFORMATION | MB_OK);
  154. }
  155. #endif
  156. // If user canceled, we're done
  157. //
  158. if (dwError == 0)
  159. goto Cleanup;
  160. // Some error occured, try to bring-up dialog with default
  161. // data.
  162. //
  163. if (pd.hDevNames)
  164. {
  165. GlobalFree(pd.hDevNames);
  166. pd.hDevNames = 0;
  167. }
  168. if (pd.hDevMode)
  169. {
  170. GlobalFree(pd.hDevMode);
  171. pd.hDevMode = 0;
  172. }
  173. pd.Flags &= ~PD_NOWARNING;
  174. #ifdef INCL_USE_NEWPRINTDLG
  175. hResult = PrintDlgEx(&pd);
  176. if ( hResult != S_OK)
  177. #else
  178. if (!PrintDlg(&pd))
  179. #endif
  180. {
  181. #if defined(_DEBUG)
  182. dwError = CommDlgExtendedError();
  183. if (dwError != 0)
  184. {
  185. wsprintf(ach, "PrintDlg error 0x%x", dwError);
  186. MessageBox(hwnd, ach, "Debug", MB_ICONINFORMATION | MB_OK);
  187. }
  188. #endif
  189. goto Cleanup;
  190. }
  191. }
  192. #ifdef INCL_USE_NEWPRINTDLG
  193. // in the NT 5 print dialog, if the user cancels, the print dialog returns S_OK.
  194. // So we need to check the result code to see if we should save the settings.
  195. if ( pd.dwResultAction == PD_RESULT_CANCEL )
  196. goto Cleanup;
  197. #endif
  198. // Store the flags returned from the dialog in the Print Handle.
  199. // This has several pieces of info that will be used by the actual
  200. // printing routines (i.e. print all, print selected).
  201. //
  202. hhPrint->nSelectionFlags = pd.Flags;
  203. // Store the printer name and location in the Print Handle
  204. // every time.
  205. //
  206. pstDevNames = GlobalLock(pd.hDevNames);
  207. if (!pstDevNames)
  208. {
  209. assert(FALSE);
  210. GlobalUnlock(pd.hDevMode);
  211. goto Cleanup;
  212. }
  213. pszPrinterName = (TCHAR *)pstDevNames;
  214. pszPrinterName += pstDevNames->wDeviceOffset;
  215. StrCharCopyN(hhPrint->achPrinterName, pszPrinterName, PRINTER_NAME_LEN);
  216. GlobalUnlock(pd.hDevNames);
  217. // Save the DEVMODE information in the Print Handle. This memory
  218. // must be freed and allocated every time as the size of the
  219. // DEVMODE structure changes.
  220. //
  221. pstDevMode = GlobalLock(pd.hDevMode);
  222. dwSize = pstDevMode->dmSize + pstDevMode->dmDriverExtra;
  223. if (hhPrint->pstDevMode)
  224. free(hhPrint->pstDevMode);
  225. hhPrint->pstDevMode = (LPDEVMODE)malloc(dwSize);
  226. if (hhPrint->pstDevMode == 0)
  227. {
  228. assert(FALSE);
  229. GlobalUnlock(pd.hDevMode);
  230. goto Cleanup;
  231. }
  232. if (dwSize)
  233. MemCopy(hhPrint->pstDevMode, pstDevMode, dwSize);
  234. GlobalUnlock(pd.hDevMode);
  235. // Save the DEVNAMES information in the Print Handle. Because the
  236. // size of the information in this structure varies, it is freed and
  237. // allocated each time it is saved.
  238. //
  239. pstDevNames = GlobalLock(pd.hDevNames);
  240. // Determine the size of the structure.
  241. //
  242. pTemp = (TCHAR *)pstDevNames;
  243. pTemp += pstDevNames->wOutputOffset;
  244. pTemp += StrCharGetByteCount(pTemp) + sizeof(TCHAR);
  245. dwSize = (DWORD)(pTemp - (TCHAR*)pstDevNames);
  246. if (hhPrint->pstDevNames)
  247. {
  248. free(hhPrint->pstDevNames);
  249. hhPrint->pstDevNames = NULL;
  250. }
  251. hhPrint->pstDevNames = (LPDEVNAMES)malloc(dwSize);
  252. if (hhPrint->pstDevNames == 0)
  253. {
  254. assert(0);
  255. GlobalUnlock(pd.hDevNames);
  256. goto Cleanup;
  257. }
  258. if (dwSize)
  259. MemCopy(hhPrint->pstDevNames, pstDevNames, dwSize);
  260. GlobalUnlock(pd.hDevNames);
  261. // Has the user selected Print To File? Yes, you do need to look
  262. // for the string "FILE:" to determinae this! If so, we will put
  263. // up our own common dialog to get the save as file name.
  264. //
  265. pTemp = (CHAR *)hhPrint->pstDevNames +
  266. hhPrint->pstDevNames->wOutputOffset;
  267. if (StrCharCmp("FILE:", pTemp) == 0)
  268. {
  269. if (printsetPrintToFile(hPrint) != 0)
  270. {
  271. goto Cleanup;
  272. }
  273. }
  274. #ifdef INCL_USE_NEWPRINTDLG
  275. // in the NT 5 print dialog, if the user cancels or click 'apply', the print dialog returns S_OK.
  276. // So we need to check the result code to see if we should now print
  277. if ( pd.dwResultAction != PD_RESULT_PRINT )
  278. goto Cleanup;
  279. #endif
  280. // Print the selected text.
  281. //
  282. printsetPrint(hPrint);
  283. // Cleanup any memory that may have been allocated.
  284. //
  285. Cleanup:
  286. if (pd.hDevNames)
  287. GlobalFree(pd.hDevNames);
  288. if (pd.hDevMode)
  289. GlobalFree(pd.hDevMode);
  290. return;
  291. }
  292. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  293. * FUNCTION:
  294. * printsetPrint
  295. *
  296. * DESCRIPTION:
  297. * This function prints the selected text from then terninal and/or the
  298. * backscroll buffer.
  299. *
  300. * ARGUMENTS:
  301. * hPrint - An external Print handle.
  302. *
  303. * RETURNS:
  304. * void
  305. *
  306. */
  307. void printsetPrint(const HPRINT hPrint)
  308. {
  309. const HHPRINT hhPrint = (HHPRINT)hPrint;
  310. int iLineHeight;
  311. int iVertRes;
  312. int iStatus,
  313. nRet;
  314. int iPrintableWidth;
  315. RECT stRect;
  316. DWORD dwCnt, dwTime1, dwTime2;
  317. POINT pX, pY;
  318. ECHAR *pechBuf;
  319. TCHAR *pV,
  320. *pLS,
  321. *pLE,
  322. *pEnd,
  323. *pNext;
  324. if (hPrint == 0)
  325. {
  326. assert(FALSE);
  327. return;
  328. }
  329. // Get the text to print for selected text.
  330. //
  331. if (hhPrint->nSelectionFlags & PD_SELECTION)
  332. {
  333. if (!CopyMarkedTextFromTerminal(hhPrint->hSession,
  334. &pV,
  335. &dwCnt,
  336. FALSE))
  337. {
  338. if (pV)
  339. {
  340. free(pV);
  341. pV = NULL;
  342. }
  343. assert(FALSE);
  344. return;
  345. }
  346. if (dwCnt == 0)
  347. {
  348. if (pV)
  349. {
  350. free(pV);
  351. pV = NULL;
  352. }
  353. assert(FALSE);
  354. return;
  355. }
  356. }
  357. // Get the text to print into a buffer for an ALL selection.
  358. //
  359. else
  360. {
  361. pX.x = 0;
  362. pX.y = INT_MIN;
  363. pY.x = INT_MAX;
  364. pY.y = INT_MAX;
  365. nRet = CopyTextFromTerminal(hhPrint->hSession,
  366. &pX,
  367. &pY,
  368. &pechBuf,
  369. &dwCnt,
  370. FALSE);
  371. if (nRet == FALSE)
  372. {
  373. if (pechBuf)
  374. {
  375. free(pechBuf);
  376. pechBuf = NULL;
  377. }
  378. assert(FALSE);
  379. return;
  380. }
  381. // Strip Out Any repeated Characters in the string
  382. StrCharStripDBCSString(pechBuf,
  383. (long)StrCharGetEcharByteCount(pechBuf), pechBuf);
  384. // hMem currently points to an array of ECHAR's, convert this to
  385. // TCHARS before giving the results to the caller.
  386. pV = malloc((ULONG)StrCharGetEcharByteCount(pechBuf) + 1);
  387. CnvrtECHARtoMBCS(pV, (ULONG)StrCharGetEcharByteCount(pechBuf) + 1,
  388. pechBuf,StrCharGetEcharByteCount(pechBuf)+1); // mrw:5/17/95
  389. free(pechBuf);
  390. pechBuf = NULL;
  391. dwCnt = (ULONG)StrCharGetByteCount(pV);
  392. }
  393. // Create the DC.
  394. //
  395. hhPrint->hDC = printCtrlCreateDC(hPrint);
  396. if (hhPrint->hDC == 0)
  397. {
  398. if (pV)
  399. {
  400. free(pV);
  401. pV = NULL;
  402. }
  403. assert(FALSE);
  404. return;
  405. }
  406. printSetFont( hhPrint );
  407. printSetMargins( hhPrint );
  408. // Initialize the DC. Set the abort flag, determine the number
  409. // of lines per page, get the title of the window which will be used
  410. // as the name of the document to print.
  411. //
  412. hhPrint->fError = FALSE;
  413. hhPrint->fUserAbort = FALSE;
  414. hhPrint->nLinesPrinted = 0;
  415. hhPrint->nPage = 1;
  416. EnableWindow(sessQueryHwnd(hhPrint->hSession), FALSE);
  417. GetTextMetrics(hhPrint->hDC, &hhPrint->tm);
  418. iLineHeight = hhPrint->tm.tmHeight + hhPrint->tm.tmExternalLeading;
  419. iVertRes = GetDeviceCaps(hhPrint->hDC, VERTRES);
  420. iVertRes -= (hhPrint->marginsDC.top + hhPrint->marginsDC.bottom);
  421. if (iLineHeight == 0) //need to prevent a divide by zero error
  422. iLineHeight = 1;
  423. hhPrint->nLinesPerPage = max( iVertRes / iLineHeight, 1);
  424. GetWindowText(sessQueryHwnd(hhPrint->hSession),
  425. hhPrint->achDoc,
  426. sizeof(hhPrint->achDoc));
  427. // Create the Print Abort Dialog.
  428. //
  429. hhPrint->lpfnPrintDlgProc = printsetDlgProc;
  430. hhPrint->hwndPrintDlg = DoModelessDialog(glblQueryDllHinst(),
  431. MAKEINTRESOURCE(IDD_PRINTABORT),
  432. sessQueryHwnd(hhPrint->hSession),
  433. hhPrint->lpfnPrintDlgProc,
  434. (LPARAM)hhPrint);
  435. // Setup the Print Abort Procedure.
  436. //
  437. hhPrint->lpfnPrintAbortProc = printsetAbortProc;
  438. nRet = SetAbortProc(hhPrint->hDC,
  439. (ABORTPROC)hhPrint->lpfnPrintAbortProc);
  440. // Initialize and start the document.
  441. //
  442. hhPrint->di.cbSize = sizeof(DOCINFO);
  443. hhPrint->di.lpszDocName = hhPrint->achDoc;
  444. hhPrint->di.lpszDatatype = NULL;
  445. hhPrint->di.fwType = 0;
  446. // Initialize di.lpszOutput for either printing to a file,
  447. // or to a printer.
  448. //
  449. if (hhPrint->achPrintToFileName[0] == TEXT('\0'))
  450. {
  451. hhPrint->di.lpszOutput = (LPTSTR)NULL;
  452. }
  453. else
  454. {
  455. hhPrint->di.lpszOutput = (LPTSTR)hhPrint->achPrintToFileName;
  456. }
  457. // StartDoc.
  458. //
  459. iStatus = StartDoc(hhPrint->hDC, &hhPrint->di);
  460. DbgOutStr("\r\nStartDoc: %d", iStatus, 0, 0, 0, 0);
  461. if (iStatus == SP_ERROR)
  462. {
  463. printCtrlDeleteDC(hPrint);
  464. if (IsWindow(hhPrint->hwndPrintDlg))
  465. DestroyWindow(hhPrint->hwndPrintDlg);
  466. printTellError(hhPrint->hSession, hPrint, iStatus);
  467. assert(FALSE);
  468. return;
  469. }
  470. // StartPage.
  471. // Get more info on this.
  472. //
  473. iStatus = StartPage(hhPrint->hDC);
  474. DbgOutStr("\r\nStartPage: %d", iStatus, 0, 0, 0, 0);
  475. printSetFont( hhPrint );
  476. if (iStatus == SP_ERROR)
  477. {
  478. assert(FALSE);
  479. }
  480. // Move through the buffer that contins the text to print, and
  481. // get it done.
  482. //
  483. // pLS = pointerLineStart
  484. // pLE = pointerLineEnd
  485. // pEnd = pointerEndOfBuffer
  486. //
  487. pLS = pV;
  488. pLE = pV;
  489. pEnd = pV + (dwCnt - 1);
  490. while ((pLE <= pEnd) && !hhPrint->fError && !hhPrint->fUserAbort)
  491. {
  492. if (*pLE == TEXT('\r') || *pLE == TEXT('\0'))
  493. {
  494. pNext = pLE;
  495. // Remove trailing CR\LF\NULL as these mean nothing to
  496. // a Windows DC.
  497. //
  498. while (pLE >= pLS)
  499. {
  500. if (*pLE == TEXT('\r') || *pLE == TEXT('\n') ||
  501. *pLE == TEXT('\0'))
  502. {
  503. pLE--;
  504. continue;
  505. }
  506. break;
  507. }
  508. // Send the text out to the printer, bump the line count.
  509. //
  510. hhPrint->cx = hhPrint->marginsDC.left;
  511. hhPrint->cy = hhPrint->nLinesPrinted * hhPrint->tm.tmHeight +
  512. hhPrint->marginsDC.top;
  513. iPrintableWidth = GetDeviceCaps( hhPrint->hDC, HORZRES );
  514. iPrintableWidth -= hhPrint->marginsDC.right;
  515. stRect.left = hhPrint->cx;
  516. stRect.right = iPrintableWidth;
  517. stRect.top = hhPrint->cy;
  518. stRect.bottom = hhPrint->cy + hhPrint->tm.tmHeight;
  519. ExtTextOut( hhPrint->hDC, hhPrint->cx, hhPrint->cy, ETO_CLIPPED,
  520. &stRect, pLS, (UINT)((pLE - pLS) + 1), NULL );
  521. hhPrint->nLinesPrinted += 1;
  522. if (hhPrint->nLinesPrinted == 1)
  523. {
  524. DbgOutStr("\r\nPost WM_PRINT_NEWPAGE", 0, 0, 0, 0, 0);
  525. PostMessage(hhPrint->hwndPrintDlg,
  526. WM_PRINT_NEWPAGE,
  527. 0,
  528. (LPARAM)hhPrint);
  529. }
  530. // Check for a new page condition.
  531. //
  532. if ((hhPrint->nLinesPrinted >= hhPrint->nLinesPerPage))
  533. {
  534. hhPrint->nLinesPrinted = 0;
  535. hhPrint->nPage++;
  536. iStatus = EndPage(hhPrint->hDC);
  537. if (iStatus < 0)
  538. {
  539. hhPrint->fError = TRUE;
  540. printTellError(hhPrint->hSession, hPrint, iStatus);
  541. }
  542. else
  543. {
  544. iStatus = StartPage(hhPrint->hDC);
  545. DbgOutStr("\r\nStartPage: %d", iStatus, 0, 0, 0, 0);
  546. printSetFont( hhPrint );
  547. if (iStatus <= 0)
  548. {
  549. DbgShowLastError();
  550. printTellError(hhPrint->hSession, hPrint, iStatus);
  551. }
  552. }
  553. }
  554. pLS = pLE = (pNext + 1);
  555. continue;
  556. }
  557. pLE++;
  558. }
  559. // Did we issue an EndPage for this page yet?
  560. //
  561. if (hhPrint->nLinesPrinted > 0)
  562. {
  563. iStatus = EndPage(hhPrint->hDC);
  564. DbgOutStr("\r\nEndPage: %d", iStatus, 0, 0, 0, 0);
  565. if (iStatus <= 0)
  566. {
  567. DbgShowLastError();
  568. printTellError(hhPrint->hSession, hPrint, iStatus);
  569. }
  570. }
  571. // Call EndDoc.
  572. //
  573. iStatus = EndDoc(hhPrint->hDC);
  574. if (iStatus <= 0)
  575. {
  576. DbgShowLastError();
  577. DbgOutStr("\r\nEndDoc: %d", iStatus, 0, 0, 0, 0);
  578. printTellError(hhPrint->hSession, hPrint, iStatus);
  579. }
  580. // Final cleanup before exit.
  581. //
  582. if (!hhPrint->fUserAbort)
  583. {
  584. dwTime1 = (DWORD)GetWindowLongPtr(hhPrint->hwndPrintDlg, GWLP_USERDATA);
  585. dwTime2 = GetTickCount();
  586. if (dwTime2 - dwTime1 < 3000)
  587. Sleep( 3000 - (dwTime2 - dwTime1));
  588. EnableWindow(sessQueryHwnd(hhPrint->hSession), TRUE);
  589. DestroyWindow(hhPrint->hwndPrintDlg);
  590. }
  591. printCtrlDeleteDC(hPrint);
  592. if (pV)
  593. {
  594. free(pV);
  595. pV = NULL;
  596. }
  597. return;
  598. }
  599. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  600. * FUNCTION:
  601. * printsetAbortProc
  602. *
  603. * DESCRIPTION:
  604. * This is the print abort procedure used when printing selected text.
  605. * Note that this abort proc is not used for print echo, or for host
  606. * directed printing.
  607. *
  608. * ARGUMENTS:
  609. * HDC - A printer DC.
  610. * nCode - The status of the call.
  611. *
  612. * RETURNS:
  613. * The abort status.
  614. *
  615. */
  616. BOOL CALLBACK printsetAbortProc(HDC hdcPrn, INT nCode)
  617. {
  618. MSG msg;
  619. HHPRINT hhPrint = (HHPRINT)printCtrlLookupDC(hdcPrn);
  620. DbgOutStr("\r\nprintsetAbortProc Code: %d", nCode, 0, 0, 0, 0);
  621. while (!hhPrint->fUserAbort &&
  622. PeekMessage((LPMSG)&msg, (HWND)0, 0, 0, PM_REMOVE))
  623. {
  624. if (!hhPrint->hwndPrintDlg ||
  625. !IsDialogMessage(hhPrint->hwndPrintDlg, &msg))
  626. {
  627. TranslateMessage(&msg);
  628. DispatchMessage(&msg);
  629. }
  630. }
  631. return !hhPrint->fUserAbort;
  632. }
  633. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  634. * FUNCTION:
  635. * printsetDlgProc
  636. *
  637. * DESCRIPTION:
  638. * This is the dialog procedure for printing selected text. It contains
  639. * a CANCEL button that may be used to abort the printing process.
  640. *
  641. * ARGUMENTS:
  642. * Note that a print handle is passed into this procedure in the lPar
  643. * variable.
  644. *
  645. * RETURNS:
  646. *
  647. */
  648. LRESULT CALLBACK printsetDlgProc(HWND hwnd, UINT uMsg, WPARAM wPar, LPARAM lPar)
  649. {
  650. TCHAR achBuf[80];
  651. TCHAR achMessage[80];
  652. DWORD dwTime;
  653. HHPRINT hhPrint;
  654. LPTSTR acPtrs[3];
  655. switch (uMsg)
  656. {
  657. case WM_INITDIALOG:
  658. DbgOutStr("\r\nprintsetDlgProc", 0, 0, 0, 0, 0);
  659. hhPrint = (HHPRINT)lPar;
  660. SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR)lPar);
  661. mscCenterWindowOnWindow(hwnd, sessQueryHwnd(hhPrint->hSession));
  662. LoadString(glblQueryDllHinst(),
  663. IDS_PRINT_NOW_PRINTING,
  664. achBuf,
  665. sizeof(achBuf) / sizeof(TCHAR));
  666. wsprintf(achMessage, achBuf, 1);
  667. SetDlgItemText(hwnd, 101, achMessage);
  668. LoadString(glblQueryDllHinst(),
  669. IDS_PRINT_OF_DOC,
  670. achBuf,
  671. sizeof(achBuf) / sizeof(TCHAR));
  672. wsprintf(achMessage, achBuf, hhPrint->achDoc);
  673. SetDlgItemText(hwnd, 102, achMessage);
  674. LoadString(glblQueryDllHinst(),
  675. IDS_PRINT_ON_DEV,
  676. achBuf,
  677. sizeof(achBuf) / sizeof(TCHAR));
  678. acPtrs[0] = hhPrint->achPrinterName;
  679. acPtrs[1] = (TCHAR *)hhPrint->pstDevNames +
  680. hhPrint->pstDevNames->wOutputOffset;
  681. FormatMessage(
  682. FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  683. achBuf,
  684. 0, /* Message ID, ignored */
  685. 0, /* also ignored */
  686. achMessage, /* result */
  687. sizeof(achMessage) / sizeof(TCHAR),
  688. (va_list *)&acPtrs[0]);
  689. SetDlgItemText(hwnd, 103, achMessage);
  690. dwTime = GetTickCount();
  691. SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)dwTime);
  692. return TRUE;
  693. case WM_COMMAND:
  694. DbgOutStr("\r\nprintsetDlgProc - CANCEL", 0, 0, 0, 0, 0);
  695. hhPrint = (HHPRINT)GetWindowLongPtr(hwnd, DWLP_USER);
  696. hhPrint->fUserAbort = TRUE;
  697. EnableWindow(sessQueryHwnd(hhPrint->hSession), TRUE);
  698. DestroyWindow(hwnd);
  699. hhPrint->hwndPrintDlg = 0;
  700. return TRUE;
  701. case WM_PRINT_NEWPAGE:
  702. DbgOutStr("\r\nprintsetDlgProc", 0, 0, 0, 0, 0);
  703. hhPrint = (HHPRINT)GetWindowLongPtr(hwnd, DWLP_USER);
  704. LoadString(glblQueryDllHinst(),
  705. IDS_PRINT_NOW_PRINTING,
  706. achBuf,
  707. sizeof(achBuf) / sizeof(TCHAR));
  708. wsprintf(achMessage, achBuf, hhPrint->nPage);
  709. SetDlgItemText(hwnd, 101, achMessage);
  710. return TRUE;
  711. default:
  712. break;
  713. }
  714. return FALSE;
  715. }
  716. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  717. * FUNCTION:
  718. * printPageSetup
  719. *
  720. * DESCRIPTION:
  721. * Invokes the common page-setup dialog
  722. *
  723. * ARGUMENTS:
  724. * HPRINT hPrint - public print handle
  725. * HWND hwnd - window handle used for parent
  726. *
  727. * RETURNS:
  728. * 0=OK,else error
  729. *
  730. */
  731. int printPageSetup(const HPRINT hPrint, const HWND hwnd)
  732. {
  733. HHPRINT hhPrint = (HHPRINT)hPrint;
  734. PAGESETUPDLG psd;
  735. LPDEVNAMES pstDevNames;
  736. PDEVMODE pstDevMode;
  737. TCHAR *pszPrinterName;
  738. TCHAR *pTemp;
  739. DWORD dwSize;
  740. RECT stMinMargins = {0,0,0,0};
  741. if (hPrint == 0)
  742. return -1;
  743. memset(&psd, 0, sizeof(psd));
  744. psd.lStructSize = sizeof(psd);
  745. psd.hwndOwner = hwnd;
  746. psd.hInstance = glblQueryDllHinst();
  747. psd.Flags = PSD_ENABLEPAGESETUPTEMPLATE | PSD_ENABLEPAGESETUPHOOK |
  748. PSD_MINMARGINS | PSD_MARGINS;
  749. psd.rtMargin = hhPrint->margins;
  750. psd.rtMinMargin = stMinMargins;
  751. psd.lCustData = (LPARAM)hhPrint;
  752. psd.lpPageSetupTemplateName = MAKEINTRESOURCE(IDD_CUSTOM_PAGE_SETUP);
  753. psd.lpfnPageSetupHook = printPageSetupHook;
  754. // Use the previously stored information to initialize the print
  755. // common dialogs. printGetDefaults initializes this information
  756. // when a print handle is created.
  757. //
  758. if (hhPrint->pstDevMode)
  759. {
  760. // Allocate memory for the DEVMODE information and then
  761. // initialize it with the stored values from the Print Handle.
  762. //
  763. dwSize = hhPrint->pstDevMode->dmSize +
  764. hhPrint->pstDevMode->dmDriverExtra;
  765. if ((psd.hDevMode = GlobalAlloc(GMEM_MOVEABLE, dwSize)))
  766. {
  767. if ((pstDevMode = GlobalLock(psd.hDevMode)))
  768. {
  769. if (dwSize)
  770. MemCopy(pstDevMode, hhPrint->pstDevMode, dwSize);
  771. GlobalUnlock(psd.hDevMode);
  772. }
  773. }
  774. }
  775. if (hhPrint->pstDevNames)
  776. {
  777. // Allocate memory for the DEVNAMES structure in pd, then
  778. // initialize it with the stored values from the Print Handle.
  779. // This sequence determines the variable structure size of
  780. // DEVNAMES.
  781. //
  782. pTemp = (TCHAR *)hhPrint->pstDevNames;
  783. pTemp += hhPrint->pstDevNames->wOutputOffset;
  784. pTemp += StrCharGetByteCount(pTemp) + sizeof(TCHAR);
  785. dwSize = (DWORD)(pTemp - (TCHAR*)hhPrint->pstDevNames);
  786. if ((psd.hDevNames = GlobalAlloc(GMEM_MOVEABLE, dwSize)))
  787. {
  788. if ((pstDevNames = GlobalLock(psd.hDevNames)))
  789. {
  790. if (dwSize)
  791. MemCopy(pstDevNames, hhPrint->pstDevNames, dwSize);
  792. GlobalUnlock(psd.hDevNames);
  793. }
  794. }
  795. }
  796. if (!PageSetupDlg(&psd))
  797. {
  798. #if defined(_DEBUG)
  799. TCHAR ach[100];
  800. DWORD dwError = CommDlgExtendedError();
  801. if (dwError != 0)
  802. {
  803. wsprintf(ach, "PrintDlg error 0x%x", dwError);
  804. MessageBox(hwnd, ach, "Debug", MB_ICONINFORMATION | MB_OK);
  805. }
  806. #endif
  807. return -2;
  808. }
  809. // store the margin settings in the print handle.
  810. //
  811. hhPrint->margins = psd.rtMargin;
  812. // Store the printer name and location in the Print Handle
  813. // every time.
  814. //
  815. pstDevNames = GlobalLock(psd.hDevNames);
  816. pszPrinterName = (TCHAR *)pstDevNames;
  817. pszPrinterName += pstDevNames->wDeviceOffset;
  818. StrCharCopyN(hhPrint->achPrinterName, pszPrinterName, PRINTER_NAME_LEN);
  819. GlobalUnlock(psd.hDevNames);
  820. // Save the DEVMODE information in the Print Handle. This memory
  821. // must be freed and allocated every time as the size of the
  822. // DEVMODE structure changes.
  823. //
  824. pstDevMode = GlobalLock(psd.hDevMode);
  825. dwSize = pstDevMode->dmSize + pstDevMode->dmDriverExtra;
  826. if (hhPrint->pstDevMode)
  827. {
  828. free(hhPrint->pstDevMode);
  829. hhPrint->pstDevMode = NULL;
  830. }
  831. hhPrint->pstDevMode = (LPDEVMODE)malloc(dwSize);
  832. if (hhPrint->pstDevMode == 0)
  833. {
  834. assert(FALSE);
  835. GlobalUnlock(psd.hDevMode);
  836. goto Cleanup;
  837. }
  838. if (dwSize)
  839. MemCopy(hhPrint->pstDevMode, pstDevMode, dwSize);
  840. GlobalUnlock(psd.hDevMode);
  841. // Save the DEVNAMES information in the Print Handle. Because the
  842. // size of the information in this structure varies, it is freed and
  843. // allocated each time it is saved.
  844. //
  845. pstDevNames = GlobalLock(psd.hDevNames);
  846. // Determine the size of the structure.
  847. //
  848. pTemp = (TCHAR *)pstDevNames;
  849. pTemp += pstDevNames->wOutputOffset;
  850. pTemp += StrCharGetByteCount(pTemp) + sizeof(TCHAR);
  851. dwSize = (DWORD)(pTemp - (TCHAR*)pstDevNames);
  852. if (hhPrint->pstDevNames)
  853. {
  854. free(hhPrint->pstDevNames);
  855. hhPrint->pstDevNames = NULL;
  856. }
  857. hhPrint->pstDevNames = (LPDEVNAMES)malloc(dwSize);
  858. if (hhPrint->pstDevNames == 0)
  859. {
  860. assert(0);
  861. GlobalUnlock(psd.hDevNames);
  862. goto Cleanup;
  863. }
  864. if (dwSize)
  865. MemCopy(hhPrint->pstDevNames, pstDevNames, dwSize);
  866. GlobalUnlock(psd.hDevNames);
  867. // Cleanup any memory that may have been allocated.
  868. //
  869. Cleanup:
  870. if (psd.hDevNames)
  871. GlobalFree(psd.hDevNames);
  872. if (psd.hDevMode)
  873. GlobalFree(psd.hDevMode);
  874. return 0;
  875. }
  876. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  877. * FUNCTION:
  878. * printPageSetupHook
  879. *
  880. * DESCRIPTION:
  881. * A hook function to process the font button on the page setup dialog
  882. *
  883. * ARGUMENTS:
  884. * hdlg - handle to the dialog box window
  885. * uiMsg - message identifier
  886. * wParam - message parameter
  887. * lParam - message parameter
  888. *
  889. * RETURNS:
  890. * 0 = message not processed 1 = message processeed
  891. *
  892. * Author:
  893. * Dwayne Newsome 02/19/97
  894. *
  895. */
  896. static UINT_PTR APIENTRY printPageSetupHook( HWND hdlg, UINT uiMsg, WPARAM wParam,
  897. LPARAM lParam )
  898. {
  899. static HHPRINT hhPrint;
  900. static PAGESETUPDLG * pPageSetup;
  901. UINT processed = 0;
  902. LPDEVNAMES pstDevNames;
  903. TCHAR * pszPrinterName;
  904. //
  905. // on the init dialog message save a pointer to the pagesetup dialog and
  906. // save the print handle
  907. //
  908. if ( uiMsg == WM_INITDIALOG )
  909. {
  910. pPageSetup = ( PAGESETUPDLG *) lParam;
  911. hhPrint = (HHPRINT) pPageSetup->lCustData;
  912. }
  913. //
  914. // Looking for the font button click here, if we get it set the currently
  915. // selected printers name in the saved print handle and display the font
  916. // dialog. We save the printer name so the font dialog can show the
  917. // correct fonts for the currently selected printer.
  918. //
  919. else if ( uiMsg == WM_COMMAND )
  920. {
  921. if ( HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == 1027 )
  922. {
  923. processed = 1;
  924. pstDevNames = GlobalLock(pPageSetup->hDevNames);
  925. pszPrinterName = (TCHAR *)pstDevNames;
  926. pszPrinterName += pstDevNames->wDeviceOffset;
  927. StrCharCopyN(hhPrint->achPrinterName, pszPrinterName, PRINTER_NAME_LEN);
  928. GlobalUnlock(pPageSetup->hDevNames);
  929. DisplayFontDialog( hhPrint->hSession, TRUE );
  930. }
  931. }
  932. return processed;
  933. }
  934. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  935. * FUNCTION:
  936. * printsetPrintToFile
  937. *
  938. * DESCRIPTION:
  939. *
  940. *
  941. * ARGUMENTS:
  942. * HPRINT hPrint - public print handle
  943. *
  944. *
  945. * RETURNS:
  946. * 0=OK,else error
  947. *
  948. */
  949. static int printsetPrintToFile(const HPRINT hPrint)
  950. {
  951. const HHPRINT hhPrint = (HHPRINT)hPrint;
  952. TCHAR acTitle[64],
  953. acMask[128],
  954. acDir[256],
  955. acFile[256];
  956. LPTSTR pszPrintFile;
  957. HWND hWnd;
  958. HINSTANCE hInst;
  959. LPTSTR pszStr;
  960. TCHAR_Fill(acTitle, TEXT('\0'), sizeof(acTitle) / sizeof(TCHAR));
  961. TCHAR_Fill(acMask, TEXT('\0'), sizeof(acMask) / sizeof(TCHAR));
  962. TCHAR_Fill(acDir, TEXT('\0'), sizeof(acDir) / sizeof(TCHAR));
  963. TCHAR_Fill(acFile, TEXT('\0'), sizeof(acFile) / sizeof(TCHAR));
  964. hWnd = glblQueryHwndFrame();
  965. hInst = glblQueryDllHinst();
  966. LoadString(hInst,
  967. IDS_PRINT_TOFILE,
  968. acTitle,
  969. sizeof(acTitle) / sizeof(TCHAR));
  970. LoadString(hInst,
  971. IDS_PRINT_FILENAME,
  972. acFile,
  973. sizeof(acFile) / sizeof(TCHAR));
  974. resLoadFileMask(hInst,
  975. IDS_PRINT_FILTER_1,
  976. 2,
  977. acMask,
  978. sizeof(acMask) / sizeof(TCHAR));
  979. // Figure out which directory to propose to the user for the 'print to'
  980. // file. If we have a session file, use that session files directory,
  981. // otherwise use the current directory.
  982. //
  983. if (sfGetSessionFileName(sessQuerySysFileHdl(hhPrint->hSession),
  984. sizeof(acDir) / sizeof(TCHAR),
  985. acDir) == SF_OK)
  986. {
  987. mscStripName(acDir);
  988. }
  989. else
  990. {
  991. //Changed to use working folder rather than current folder - mpt 8-18-99
  992. if ( !GetWorkingDirectory( acDir, sizeof(acDir) / sizeof(TCHAR)) )
  993. {
  994. GetCurrentDirectory(sizeof(acDir) / sizeof(TCHAR), acDir);
  995. }
  996. }
  997. pszStr = StrCharLast(acDir);
  998. // Remove trailing backslash from the directory name if there is one.
  999. //
  1000. if (pszStr && *pszStr == TEXT('\\'))
  1001. *pszStr = TEXT('\0');
  1002. pszPrintFile = gnrcSaveFileDialog(hWnd,
  1003. (LPCTSTR)acTitle,
  1004. (LPCTSTR)acDir,
  1005. (LPCTSTR)acMask ,
  1006. (LPCTSTR)acFile);
  1007. if (pszPrintFile == NULL)
  1008. {
  1009. return(1);
  1010. }
  1011. // pszPrintFile gets allocated in gnrcSaveFileDlg.
  1012. //
  1013. StrCharCopyN(hhPrint->achPrintToFileName, pszPrintFile, PRINTER_NAME_LEN);
  1014. free(pszPrintFile);
  1015. pszPrintFile = NULL;
  1016. return(0);
  1017. }