Source code of Windows XP (NT5)
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.

658 lines
18 KiB

  1. /************************************************************/
  2. /* Windows Write, Copyright 1985-1990 Microsoft Corporation */
  3. /************************************************************/
  4. #define NOGDICAPMASKS
  5. #define NOVIRTUALKEYCODES
  6. #define NOWINSTYLES
  7. #define NOSYSMETRICS
  8. #define NOMENUS
  9. #define NOCLIPBOARD
  10. #define NOKEYSTATE
  11. #define NOSYSCOMMANDS
  12. #define NORASTEROPS
  13. #define NOSHOWWINDOW
  14. #define NOATOM
  15. #define NOCREATESTRUCT
  16. #define NODRAWTEXT
  17. #define NOMB
  18. #define NOMETAFILE
  19. #define NOWH
  20. #define NOWNDCLASS
  21. #define NOSOUND
  22. #define NOCOLOR
  23. #define NOSCROLL
  24. #define NOCOMM
  25. #include <windows.h>
  26. #include "mw.h"
  27. #include "dlgdefs.h"
  28. #include "cmddefs.h"
  29. #include "machdefs.h"
  30. #include "docdefs.h"
  31. #include "propdefs.h"
  32. #include "printdef.h"
  33. #include "str.h"
  34. #include "fmtdefs.h"
  35. #include <commdlg.h>
  36. #include <cderr.h>
  37. #include <print.h>
  38. #include <stdlib.h>
  39. extern CHAR (**hszPrinter)[];
  40. extern CHAR (**hszPrDriver)[];
  41. extern CHAR (**hszPrPort)[];
  42. extern BOOL vfPrDefault;
  43. #ifdef JAPAN // added 08 Jun. 1992 by Hiraisi
  44. BOOL FAR PASCAL _export fnPrintHook( HWND, UINT, WPARAM, LPARAM );
  45. extern HANDLE hMmwModInstance;
  46. BOOL fWriting = FALSE;
  47. BOOL bWriting = FALSE;
  48. #endif //JAPAN
  49. BOOL vbCollate = TRUE;
  50. static void GetPrNames(BOOL bPrDialog);
  51. PRINTDLG PD = {0,0,0,0,0}; /* Common print dlg structure, initialized in the init code */
  52. void PrinterSetupDlg(BOOL bGetDevmodeOnly /* not used */)
  53. {
  54. extern HWND vhWnd;
  55. BOOL bDevMode = PD.hDevMode ? TRUE : FALSE;
  56. PD.Flags |= PD_PRINTSETUP;
  57. PD.Flags &= ~PD_RETURNDEFAULT;
  58. if (vfPrDefault && !PD.hDevNames)
  59. if (PD.hDevMode)
  60. {
  61. /*
  62. So dlg will show that default is selected. Its a pity
  63. to do this because hDevMode is perfectly good. Alternative
  64. is to build a DevNames structure which we could do, but
  65. that would just allocate a new devmode anyways.
  66. */
  67. GlobalFree(PD.hDevMode);
  68. PD.hDevMode = 0;
  69. }
  70. #ifdef JAPAN // added 08 Jun. 1992 by Hiraisi
  71. PD.hInstance = NULL;
  72. PD.lpPrintTemplateName = (LPCSTR)NULL;
  73. PD.Flags &= ~PD_ENABLEPRINTTEMPLATE;
  74. PD.Flags &= ~PD_ENABLEPRINTHOOK;
  75. #endif //JAPAN
  76. TryPrnSetupAgain:
  77. if (!PrintDlg(&PD))
  78. {
  79. /* Bug #11531: When PrintDlg returns 0, it could me we gave it garbage in
  80. * the DevNames or DevMode structures, perhaps due to the user making
  81. * changes through Control Panel that we don't monitor. Clean out the
  82. * appropriate structure and try again. Note that these errors can't be
  83. * returned to us again after cleaning out the structure.
  84. * 23 August 1991 Clark R. Cyr
  85. */
  86. switch (CommDlgExtendedError())
  87. {
  88. case PDERR_PRINTERNOTFOUND:
  89. case PDERR_DNDMMISMATCH:
  90. if (PD.hDevNames)
  91. {
  92. GlobalFree(PD.hDevNames);
  93. PD.hDevNames = 0;
  94. }
  95. if (PD.hDevMode)
  96. {
  97. GlobalFree(PD.hDevMode);
  98. PD.hDevMode = 0;
  99. }
  100. goto TryPrnSetupAgain;
  101. default:
  102. return;
  103. }
  104. }
  105. PD.Flags &= ~PD_PRINTSETUP;
  106. GetPrNames(FALSE); // this gets new PrinterDC
  107. ResetFontTables();
  108. #if defined(OLE)
  109. ObjSetTargetDevice(TRUE);
  110. #endif
  111. InvalidateRect(vhWnd, (LPRECT)NULL, fFalse);
  112. return;
  113. }
  114. void fnPrPrinter(
  115. void)
  116. {
  117. /* This routine is the outside world's interface to the print code. */
  118. extern int docCur;
  119. extern int vfPrPages, vpgnBegin, vpgnEnd, vcCopies;
  120. extern WORD fPrintOnly;
  121. extern CHAR (**hszPrPort)[];
  122. HANDLE hPort=NULL;
  123. LPDEVNAMES lpDevNames;
  124. int Len3;
  125. char szPort[cchMaxFile];
  126. extern struct SEL selCur;
  127. BOOL bDevMode = PD.hDevMode ? TRUE : FALSE;
  128. #ifdef JAPAN // added 08 Jun. 1992 by Hiraisi
  129. FARPROC lpfnPrintHook;
  130. BOOL bReturn;
  131. #endif
  132. PD.Flags &= ~(PD_RETURNDEFAULT|PD_PRINTSETUP|PD_SELECTION); /*turn off PRINTSETUP flag */
  133. if (vbCollate)
  134. PD.Flags |= PD_COLLATE;
  135. else
  136. PD.Flags &= ~PD_COLLATE;
  137. if (selCur.cpFirst == selCur.cpLim) // no selection
  138. PD.Flags |= PD_NOSELECTION;
  139. else
  140. PD.Flags &= ~PD_NOSELECTION;
  141. if (vfPrDefault && !PD.hDevNames)
  142. if (PD.hDevMode)
  143. {
  144. /*
  145. So dlg will show that default is selected. Its a pity
  146. to do this beause hDevMode is perfectly good. Alternative
  147. is to build a DevNames structure.
  148. */
  149. GlobalFree(PD.hDevMode);
  150. PD.hDevMode = 0;
  151. }
  152. #ifdef JAPAN // added 08 Jun. 1992 by Hiraisi
  153. PD.hInstance = hMmwModInstance;
  154. PD.Flags |= PD_ENABLEPRINTTEMPLATE;
  155. PD.lpPrintTemplateName = (LPCSTR)MAKEINTRESOURCE( dlgPrint );
  156. PD.Flags |= PD_ENABLEPRINTHOOK;
  157. lpfnPrintHook = MakeProcInstance( fnPrintHook, hMmwModInstance );
  158. PD.lpfnPrintHook = (FARPROC)lpfnPrintHook;
  159. TryPrintAgain:
  160. bReturn = PrintDlg(&PD);
  161. FreeProcInstance( lpfnPrintHook );
  162. if (!bReturn)
  163. #else
  164. TryPrintAgain:
  165. if (!PrintDlg(&PD))
  166. #endif
  167. {
  168. switch (CommDlgExtendedError())
  169. {
  170. case PDERR_PRINTERNOTFOUND:
  171. case PDERR_DNDMMISMATCH:
  172. if (PD.hDevNames)
  173. {
  174. GlobalFree(PD.hDevNames);
  175. PD.hDevNames = 0;
  176. }
  177. if (PD.hDevMode)
  178. {
  179. GlobalFree(PD.hDevMode);
  180. PD.hDevMode = 0;
  181. }
  182. goto TryPrintAgain;
  183. default:
  184. if (!bDevMode && PD.hDevMode)
  185. {
  186. GlobalFree(PD.hDevMode);
  187. PD.hDevMode = 0;
  188. }
  189. return;
  190. }
  191. }
  192. #ifdef JAPAN // added 08 Jun. 1992 by Hiraisi
  193. fWriting = bWriting;
  194. #endif
  195. if (PD.Flags & PD_PAGENUMS) /* Page Range specified? */
  196. {
  197. vfPrPages = TRUE;
  198. if (PD.nFromPage)
  199. vpgnBegin = PD.nFromPage;
  200. if (PD.nToPage)
  201. vpgnEnd = PD.nToPage;
  202. if (vpgnEnd < vpgnBegin)
  203. {
  204. int temp = vpgnBegin;
  205. vpgnBegin = vpgnEnd;
  206. vpgnEnd = temp;
  207. }
  208. }
  209. else /* No, print all pages */
  210. vfPrPages = FALSE;
  211. vcCopies = PD.nCopies;
  212. vbCollate = PD.Flags & PD_COLLATE;
  213. GetPrNames(TRUE);
  214. /** At this point, we have the following :
  215. vfPrPages = true if print page range else print all pages
  216. vpgnBegin = starting page number (if vfPrPages)
  217. vpgnEnd = ending page number (if vfPrPages)
  218. vcCopies = number of copies to print
  219. vbCollate = whuddya think?
  220. **/
  221. #if defined(OLE)
  222. ObjSetTargetDevice(TRUE);
  223. #endif
  224. if (PD.Flags & PD_SELECTION)
  225. {
  226. int docTmp;
  227. BOOL bIssueError;
  228. extern WORD ferror;
  229. extern typeCP cpMinCur, cpMacCur, cpMinDocument;
  230. extern struct DOD (**hpdocdod)[];
  231. typeCP cpMinCurT = cpMinCur;
  232. typeCP cpMacCurT = cpMacCur;
  233. typeCP cpMinDocumentT = cpMinDocument;
  234. docTmp = DocCreate(fnNil, HszCreate(""), dtyNormal);
  235. if (docTmp != docNil)
  236. {
  237. ClobberDoc( docTmp, docCur, selCur.cpFirst, selCur.cpLim-selCur.cpFirst );
  238. if (!ferror)
  239. {
  240. cpMinCur = cp0;
  241. cpMacCur = (**hpdocdod) [docTmp].cpMac;
  242. PrintDoc(docTmp, TRUE);
  243. cpMinCur = cpMinCurT;
  244. cpMacCur = cpMacCurT;
  245. }
  246. }
  247. cpMinDocument = cpMinDocumentT; /* destroyed possibly by DocCreate */
  248. bIssueError = ferror;
  249. if (ferror)
  250. ferror = FALSE; // to enable the following:
  251. if (docTmp != docNil)
  252. KillDoc (docTmp); // do this first to free memory to assist messagebox if necessary
  253. if (bIssueError)
  254. Error(IDPMTPRFAIL);
  255. }
  256. else
  257. PrintDoc(docCur, TRUE);
  258. }
  259. BOOL FInitHeaderFooter(fHeader, ppgn, phrgpld, pcpld)
  260. BOOL fHeader;
  261. unsigned *ppgn;
  262. struct PLD (***phrgpld)[];
  263. int *pcpld;
  264. {
  265. /* This routine initializes the array of print line descriptors used in
  266. positioning the header/footer on the printed page. FALSE is returned if an
  267. error occurs; TRUE otherwise. */
  268. extern typeCP cpMinHeader;
  269. extern typeCP cpMacHeader;
  270. extern typeCP cpMinFooter;
  271. extern typeCP cpMacFooter;
  272. extern int docCur;
  273. extern struct PAP vpapAbs;
  274. extern struct SEP vsepAbs;
  275. extern int dxaPrOffset;
  276. extern int dyaPrOffset;
  277. extern int dxpPrPage;
  278. extern int dxaPrPage;
  279. extern int dypPrPage;
  280. extern int dyaPrPage;
  281. extern struct FLI vfli;
  282. extern int vfOutOfMemory;
  283. typeCP cpMin;
  284. typeCP cpMac;
  285. /* Get the cpMin and the cpMac for the header/footer. */
  286. if (fHeader)
  287. {
  288. cpMin = cpMinHeader;
  289. cpMac = cpMacHeader;
  290. }
  291. else
  292. {
  293. cpMin = cpMinFooter;
  294. cpMac = cpMacFooter;
  295. }
  296. /* Is there a header/footer. */
  297. if (cpMac - cpMin > ccpEol)
  298. {
  299. int cpld = 0;
  300. int cpldReal = 0;
  301. int cpldMax;
  302. int xp;
  303. int yp;
  304. int ichCp = 0;
  305. typeCP cpMacDoc = CpMacText(docCur);
  306. /* Compute the page number of the start of the headers/footers. */
  307. CacheSect(docCur, cpMin);
  308. if ((*ppgn = vsepAbs.pgnStart) == pgnNil)
  309. {
  310. *ppgn = 1;
  311. }
  312. /* Does the header/footer appear on the first page. */
  313. CachePara(docCur, cpMin);
  314. if (!(vpapAbs.rhc & RHC_fFirst))
  315. {
  316. (*ppgn)++;
  317. }
  318. /* Calculate the bounds of the header/footer in pixels. */
  319. xp = MultDiv(vsepAbs.xaLeft - dxaPrOffset, dxpPrPage, dxaPrPage);
  320. yp = fHeader ? MultDiv(vsepAbs.yaRH1 - dyaPrOffset, dypPrPage,
  321. dyaPrPage) : 0;
  322. /* Initialize the array of print line descriptors for the header/footer.
  323. */
  324. if (FNoHeap(*phrgpld = (struct PLD (**)[])HAllocate((cpldMax = cpldRH) *
  325. cwPLD)))
  326. {
  327. *phrgpld = NULL;
  328. return (FALSE);
  329. }
  330. /* We now have to calculate the array of print line descriptors for the
  331. header/footer. */
  332. cpMac -= ccpEol;
  333. while (cpMin < cpMac)
  334. {
  335. /* Format this line of the header/footer for the printer. */
  336. FormatLine(docCur, cpMin, ichCp, cpMacDoc, flmPrinting);
  337. /* Bail out if an error occurred. */
  338. if (vfOutOfMemory)
  339. {
  340. return (FALSE);
  341. }
  342. /* Is the array of print line descriptors big enough? */
  343. if (cpld >= cpldMax && !FChngSizeH(*phrgpld, (cpldMax += cpldRH) *
  344. cwPLD, FALSE))
  345. {
  346. return (FALSE);
  347. }
  348. /* Fill the print line descriptor for this line. */
  349. {
  350. register struct PLD *ppld = &(***phrgpld)[cpld++];
  351. ppld->cp = cpMin;
  352. ppld->ichCp = ichCp;
  353. ppld->rc.left = xp + vfli.xpLeft;
  354. ppld->rc.right = xp + vfli.xpReal;
  355. ppld->rc.top = yp;
  356. ppld->rc.bottom = yp + vfli.dypLine;
  357. }
  358. /* Keep track of the non-blank lines in the header/footer */
  359. if ((vfli.ichReal > 0) || vfli.fGraphics)
  360. {
  361. cpldReal = cpld;
  362. }
  363. /* Bump the counters. */
  364. cpMin = vfli.cpMac;
  365. ichCp = vfli.ichCpMac;
  366. yp += vfli.dypLine;
  367. }
  368. /* If this is a footer, then we have to move the positions of the lines
  369. around so that the footer ends where the user has requested. */
  370. if (!fHeader && cpldReal > 0)
  371. {
  372. register struct PLD *ppld = &(***phrgpld)[cpldReal - 1];
  373. int dyp = MultDiv(vsepAbs.yaRH2 - dyaPrOffset, dypPrPage, dyaPrPage)
  374. - ppld->rc.bottom;
  375. int ipld;
  376. for (ipld = cpldReal; ipld > 0; ipld--, ppld--)
  377. {
  378. ppld->rc.top += dyp;
  379. ppld->rc.bottom += dyp;
  380. }
  381. }
  382. /* Record the number of non-blank lines in the head/footer. */
  383. *pcpld = cpldReal;
  384. }
  385. else
  386. {
  387. /* Indicate there is no header/footer. */
  388. *ppgn = pgnNil;
  389. *phrgpld = NULL;
  390. *pcpld = 0;
  391. }
  392. return (TRUE);
  393. }
  394. static void GetPrNames(BOOL bPrDialog)
  395. {
  396. HANDLE hPrinter = NULL, hDriver = NULL, hPort = NULL;
  397. LPDEVNAMES lpDevNames;
  398. char szPrinter[cchMaxFile], szDriver[cchMaxFile], szPort[cchMaxFile];
  399. int Len1, Len2, Len3; /* count of words in each string */
  400. hPrinter = NULL;
  401. hDriver = NULL;
  402. hPort = NULL;
  403. lpDevNames = MAKELP(PD.hDevNames,0);
  404. if (lpDevNames == NULL)
  405. /* we're in trouble */
  406. return;
  407. lstrcpy(szPrinter, (LPSTR)lpDevNames+lpDevNames->wDeviceOffset);
  408. lstrcpy(szDriver, (LPSTR)lpDevNames+lpDevNames->wDriverOffset);
  409. if (bPrDialog && (PD.Flags & PD_PRINTTOFILE))
  410. lstrcpy(szPort, (LPSTR)"FILE:");
  411. else
  412. lstrcpy(szPort, (LPSTR)lpDevNames+lpDevNames->wOutputOffset);
  413. vfPrDefault = lpDevNames->wDefault & DN_DEFAULTPRN;
  414. if (FNoHeap((hPrinter = (CHAR (**)[])HAllocate(Len1 =
  415. CwFromCch(CchSz(szPrinter))))))
  416. goto err;
  417. if (FNoHeap((hDriver = (CHAR (**)[])HAllocate(Len2 =
  418. CwFromCch(CchSz(szDriver))))))
  419. goto err;
  420. if (FNoHeap((hPort = (CHAR (**)[])HAllocate(Len3 =
  421. CwFromCch(CchSz(szPort))))))
  422. goto err;
  423. /* Free old printer, driver and port handles */
  424. if (hszPrinter)
  425. FreeH(hszPrinter);
  426. if (hszPrDriver)
  427. FreeH(hszPrDriver);
  428. if (hszPrPort)
  429. FreeH(hszPrPort);
  430. /* Set printer, driver and port handles */
  431. hszPrinter = hPrinter;
  432. hszPrDriver = hDriver;
  433. hszPrPort = hPort;
  434. /* copy strings into the memory corresponding to the new handles */
  435. blt(szPrinter, *hszPrinter, Len1);
  436. blt(szDriver, *hszPrDriver, Len2);
  437. blt(szPort, *hszPrPort, Len3);
  438. FreePrinterDC();
  439. GetPrinterDC(FALSE);
  440. return;
  441. err:
  442. if (FNoHeap(hPrinter))
  443. FreeH(hPrinter);
  444. if (FNoHeap(hDriver))
  445. FreeH(hDriver);
  446. if (FNoHeap(hPort))
  447. FreeH(hPort);
  448. }
  449. BOOL fnPrGetDevmode(void)
  450. /* Set the devmode structure for the currently-selected printer,
  451. Assumes all needed values are correctly initialized!
  452. Return whether an error. */
  453. {
  454. int nCount;
  455. HANDLE hDevice=NULL;
  456. FARPROC lpfnDevMode;
  457. BOOL bRetval=FALSE;
  458. char szDrvName[_MAX_PATH];
  459. if (PD.hDevMode) // then already set (why called?)
  460. return FALSE;
  461. else if (PD.hDevNames) // then device is not extended
  462. return TRUE;
  463. if (hszPrinter == NULL || hszPrDriver == NULL || hszPrPort == NULL)
  464. return TRUE;
  465. if (**hszPrinter == '\0' || **hszPrDriver == '\0' || **hszPrPort == '\0')
  466. return TRUE;
  467. /* is this necessary for GetModuleHandle? For sure if calling LoadLibrary(). */
  468. wsprintf((LPSTR)szDrvName, (LPSTR)"%s%s", (LPSTR)*hszPrDriver, (LPSTR)".DRV");
  469. #if 1
  470. SetErrorMode(1); /* No kernel error dialogs */
  471. if ((hDevice = LoadLibrary((LPSTR)szDrvName)) < 32)
  472. {
  473. bRetval = TRUE;
  474. goto end;
  475. }
  476. #else
  477. hDevice = GetModuleHandle((LPSTR)szDrvName);
  478. #endif
  479. if ((lpfnDevMode = GetProcAddress(hDevice, (LPSTR)"ExtDeviceMode")) == NULL)
  480. {
  481. #ifdef DEBUG
  482. OutputDebugString("Unable to get extended device\n\r");
  483. #endif
  484. bRetval = TRUE;
  485. goto end;
  486. }
  487. /* get sizeof devmode structure */
  488. nCount = (*lpfnDevMode)(NULL,
  489. hDevice,
  490. (LPSTR)NULL,
  491. (LPSTR)(*hszPrinter),
  492. (LPSTR)(*hszPrPort),
  493. (LPSTR)NULL,
  494. (LPSTR)NULL,
  495. NULL);
  496. if ((PD.hDevMode =
  497. GlobalAlloc(GMEM_MOVEABLE,(DWORD)nCount)) == NULL)
  498. {
  499. bRetval = TRUE;
  500. goto end;
  501. }
  502. if ((*lpfnDevMode)( NULL,
  503. hDevice,
  504. MAKELP(PD.hDevMode,0),
  505. (LPSTR)(*hszPrinter),
  506. (LPSTR)(*hszPrPort),
  507. (LPSTR)NULL,
  508. (LPSTR)NULL,
  509. DM_COPY) != IDOK)
  510. {
  511. GlobalFree(PD.hDevMode);
  512. PD.hDevMode = NULL;
  513. bRetval = TRUE;
  514. goto end;
  515. }
  516. end:
  517. #if 1
  518. if (hDevice >= 32)
  519. FreeLibrary(hDevice);
  520. #endif
  521. SetErrorMode(0); /* reset kernel error dialogs */
  522. /* can't allow hDevNames to be out of sync with hDevmode */
  523. if (PD.hDevNames)
  524. {
  525. GlobalFree(PD.hDevNames);
  526. PD.hDevNames = NULL;
  527. }
  528. return bRetval;
  529. }
  530. #ifdef JAPAN // added 08 Jun. 1992 by Hiraisi
  531. #include <dlgs.h>
  532. BOOL FAR PASCAL _export fnPrintHook( hDlg, uMsg, wParam, lParam )
  533. HWND hDlg;
  534. UINT uMsg;
  535. WPARAM wParam;
  536. LPARAM lParam;
  537. {
  538. switch( uMsg ){
  539. case WM_INITDIALOG:
  540. CheckRadioButton(hDlg, rad4, rad5, fWriting ? rad5 : rad4 );
  541. return TRUE;
  542. case WM_COMMAND:
  543. switch( wParam ){
  544. case rad4:
  545. case rad5:
  546. if( HIWORD(lParam) == BN_CLICKED ){
  547. CheckRadioButton(hDlg, rad4, rad5, wParam );
  548. bWriting = ( wParam == rad4 ? FALSE : TRUE );
  549. return TRUE;
  550. }
  551. default:
  552. break;
  553. }
  554. default:
  555. break;
  556. }
  557. return FALSE;
  558. }
  559. #endif
  560.