|
|
1.1 root 1: /***************************************************************************
2: * *
3: * MODULE : MpPrint() *
4: * *
5: * PURPOSE : Printing code for MultiPad. *
6: * *
7: * FUNCTIONS : GetPrinterDC () - Creates a printer DC for the *
8: * default device. *
9: * *
10: * AbortProc () - Export proc. for GDI to check*
11: * print abort. *
12: * *
13: * PrintDlgProc () - Dialog function for the print*
14: * cancel dialog. *
15: * *
16: * PrintFile () - Prints the contents of the *
17: * edit control. *
18: * *
19: * GetInitializationData () - Gets DC initialisation data *
20: * from a DC supporting *
21: * ExtDeviceMode(). *
22: * *
23: ***************************************************************************/
24: #include "multipad.h"
25:
26: BOOL fAbort; /* TRUE if the user has aborted the print job */
27: HWND hwndPDlg; /* Handle to the cancel print dialog */
28: CHAR szDevice[160]; /* Contains the device, the driver, and the port */
29: PSTR szDriver; /* Pointer to the driver name */
30: PSTR szPort; /* Port, ie, LPT1 */
31: PSTR szTitle; /* Global pointer to job title */
32: INT iPrinter = 0; /* level of available printer support. */
33: /* 0 - no printer available */
34: /* 1 - printer available */
35: /* 2 - driver supports 3.0 device initialization */
36: HANDLE hInitData=NULL; /* handle to initialization data */
37:
38: CHAR szExtDeviceMode[] = "EXTDEVICEMODE";
39:
40: /****************************************************************************
41: * *
42: * FUNCTION : GetPrinterDC () *
43: * *
44: * PURPOSE : Creates a printer display context for the default device. *
45: * As a side effect, it sets the szDevice and szPort variables*
46: * It also sets iPrinter to the supported level of printing. *
47: * *
48: * RETURNS : HDC - A handle to printer DC. *
49: * *
50: ****************************************************************************/
51: HDC APIENTRY GetPrinterDC(BOOL bInformation)
52: {
53: HDC hdc;
54: LPDEVMODE lpdevmode = NULL;
55:
56: iPrinter = 0;
57:
58: /* Get the printer information from win.ini into a buffer and
59: * null terminate it.
60: */
61: GetProfileString ( "windows", "device", "" ,szDevice, sizeof(szDevice));
62: for (szDriver = szDevice; *szDriver && *szDriver != ','; szDriver++)
63: ;
64: if (*szDriver)
65: *szDriver++ = 0;
66:
67: /* From the current position in the buffer, null teminate the
68: * list of ports
69: */
70: for (szPort = szDriver; *szPort && *szPort != ','; szPort++)
71: ;
72: if (*szPort)
73: *szPort++ = 0;
74:
75: /* if the device, driver and port buffers all contain meaningful data,
76: * proceed.
77: */
78: if (!*szDevice || !*szDriver || !*szPort){
79: *szDevice = 0;
80: return NULL;
81: }
82:
83: /* Create the printer display context */
84: if (hInitData){
85: /* Get a pointer to the initialization data */
86: lpdevmode = (LPDEVMODE) LocalLock (hInitData);
87:
88: if (lstrcmp (szDevice, (LPSTR)lpdevmode)){
89: /* User has changed the device... cancel this setup, as it is
90: * invalid (although if we worked harder we could retain some
91: * of it).
92: */
93: lpdevmode = NULL;
94: LocalUnlock (hInitData);
95: LocalFree (hInitData);
96: hInitData = NULL;
97: }
98: }
99:
100: if (bInformation)
101: hdc = CreateIC (szDriver, szDevice, szPort, lpdevmode);
102: else
103: hdc = CreateDC (szDriver, szDevice, szPort, lpdevmode);
104:
105: /* Unlock initialization data */
106: if (hInitData)
107: LocalUnlock (hInitData);
108:
109: if (!hdc)
110: return NULL;
111:
112:
113: iPrinter = 1;
114:
115: /* Find out if ExtDeviceMode() is supported and set flag appropriately */
116: if (GetProcAddress (LoadLibrary(szDriver), szExtDeviceMode))
117: iPrinter = 2;
118:
119: return hdc;
120:
121: }
122:
123: /****************************************************************************
124: * *
125: * FUNCTION : AbortProc() *
126: * *
127: * PURPOSE : To be called by GDI print code to check for user abort. *
128: * *
129: ****************************************************************************/
130: INT APIENTRY AbortProc (
131: HDC hdc,
132: WORD reserved)
133: {
134: MSG msg;
135:
136: /* Allow other apps to run, or get abort messages */
137: while (!fAbort && PeekMessage (&msg, NULL, 0, 0, TRUE))
138: if (!hwndPDlg || !IsDialogMessage (hwndPDlg, &msg)){
139: TranslateMessage (&msg);
140: DispatchMessage (&msg);
141: }
142: return !fAbort;
143:
144: UNREFERENCED_PARAMETER(hdc);
145: UNREFERENCED_PARAMETER(reserved);
146: }
147:
148: /****************************************************************************
149: * *
150: * FUNCTION : PrintDlgProc () *
151: * *
152: * PURPOSE : Dialog function for the print cancel dialog box. *
153: * *
154: * RETURNS : TRUE - OK to abort/ not OK to abort *
155: * FALSE - otherwise. *
156: * *
157: ****************************************************************************/
158: BOOL APIENTRY PrintDlgProc(HWND hwnd, UINT msg, WORD wParam, LONG lParam)
159: {
160: switch (msg){
161: case WM_INITDIALOG:
162: /* Set up information in dialog box */
163: SetDlgItemText (hwnd, IDD_PRINTDEVICE, (LPSTR)szDevice);
164: SetDlgItemText (hwnd, IDD_PRINTPORT, (LPSTR)szPort);
165: SetDlgItemText (hwnd, IDD_PRINTTITLE, (LPSTR)szTitle);
166: break;
167:
168: case WM_COMMAND:
169: /* abort printing if the only button gets hit */
170: fAbort = TRUE;
171: break;
172:
173: default:
174: return FALSE;
175: }
176: return TRUE;
177: UNREFERENCED_PARAMETER(wParam);
178: UNREFERENCED_PARAMETER(lParam);
179: }
180:
181: /****************************************************************************
182: * *
183: * FUNCTION : PrintFile () *
184: * *
185: * PURPOSE : Prints the contents of the edit control. *
186: * *
187: ****************************************************************************/
188:
189: VOID APIENTRY PrintFile(HWND hwnd)
190: {
191: HDC hdc;
192: INT yExtPage;
193: CHAR sz[32];
194: int cch;
195: WORD ich;
196: PSTR pch;
197: WORD iLine;
198: WORD nLinesEc;
199: WORD i;
200: HANDLE hT;
201: HWND hwndPDlg;
202: DWORD dy;
203: INT yExtSoFar;
204: WORD fError = TRUE;
205: HWND hwndEdit;
206:
207: hwndEdit = (HWND)GetWindowLong(hwnd,GWL_HWNDEDIT);
208:
209: /* Create the job title by loading the title string from STRINGTABLE */
210: cch = LoadString (hInst, IDS_PRINTJOB, sz, sizeof(sz));
211: szTitle = sz + cch;
212: cch += GetWindowText (hwnd, sz + cch, 32 - cch);
213: sz[31] = 0;
214:
215: /* Initialize the printer */
216: hdc = GetPrinterDC(FALSE);
217: if (!hdc)
218: goto getout5;
219:
220: /* Disable the main application window and create the Cancel dialog */
221: EnableWindow (hwndFrame, FALSE);
222:
223: hwndPDlg = CreateDialog (hInst, IDD_PRINT, hwnd, (DLGPROC) PrintDlgProc);
224:
225: if (!hwndPDlg)
226: goto getout3;
227: ShowWindow (hwndPDlg, SW_SHOW);
228: UpdateWindow (hwndPDlg);
229:
230: /* Allow the app. to inform GDI of the escape function to call */
231: if (Escape(hdc, SETABORTPROC, 0, (LPSTR)AbortProc, NULL) < 0)
232: goto getout1;
233:
234: /* Initialize the document */
235: if (Escape(hdc, STARTDOC, cch, (LPSTR)sz, NULL) < 0)
236: goto getout1;
237:
238: /* Get the height of one line and the height of a page */
239: {
240: SIZE tmp;
241: GetTextExtentPoint(hdc, "CC", 2, &tmp );
242: dy = tmp.cy;
243: }
244:
245: yExtPage = GetDeviceCaps(hdc, VERTRES);
246:
247: /* Get the lines in document and and a handle to the text buffer */
248: iLine = 0;
249: yExtSoFar = 0;
250: nLinesEc = (WORD)SendMessage (hwndEdit, EM_GETLINECOUNT, 0, 0L);
251: hT = (HANDLE)SendMessage (hwndEdit, EM_GETHANDLE, 0, 0L);
252:
253: /* While more lines print out the text */
254: while (iLine < nLinesEc){
255: if (yExtSoFar + (int) dy > yExtPage){
256: /* Reached the end of a page. Tell the device driver to eject a
257: * page
258: */
259: if (Escape(hdc, NEWFRAME, 0, NULL, NULL) < 0 || fAbort)
260: goto getout2;
261: yExtSoFar = 0;
262: }
263:
264: /* Get the length and position of the line in the buffer
265: * and lock from that offset into the buffer */
266: ich = (WORD)SendMessage (hwndEdit, EM_LINEINDEX, iLine, 0L);
267: cch = (WORD)SendMessage (hwndEdit, EM_LINELENGTH, ich, 0L);
268: pch = (PSTR)LocalLock(hT) + ich;
269:
270: /* Print the line and unlock the text handle */
271: TextOut (hdc, 0, yExtSoFar, (LPSTR)pch, cch);
272: LocalUnlock (hT);
273:
274: /* Test and see if the Abort flag has been set. If yes, exit. */
275: if (fAbort)
276: goto getout2;
277:
278: /* Move down the page */
279: yExtSoFar += dy;
280: iLine++;
281: }
282:
283: /* Eject the last page. */
284: if (Escape(hdc, NEWFRAME, 0, NULL, NULL) < 0)
285: goto getout2;
286:
287: /* Complete the document. */
288: if (Escape(hdc, ENDDOC, 0, NULL, NULL) < 0){
289: getout2:
290: /* Ran into a problem before NEWFRAME? Abort the document */
291: Escape( hdc, ABORTDOC, 0, NULL, NULL);
292: }
293: else
294: fError=FALSE;
295:
296: getout3:
297: /* Close the cancel dialog and re-enable main app. window */
298: EnableWindow (hwndFrame, TRUE);
299: DestroyWindow (hwndPDlg);
300:
301: getout1:
302: DeleteDC(hdc);
303:
304: getout5:
305: #ifdef WIN16
306: /* Get rid of dialog procedure instances */
307: FreeProcInstance (lpfnPDlg);
308: #endif
309:
310: #ifdef WIN16
311: getout4:
312: FreeProcInstance (lpfnAbort);
313: getout:
314: #endif
315:
316: /* Error? make sure the user knows... */
317: if (fError)
318: MPError (hwnd, MB_OK | MB_ICONEXCLAMATION, IDS_PRINTERROR, (LPSTR)szTitle);
319:
320: return;
321: UNREFERENCED_PARAMETER(i);
322: }
323:
324: /****************************************************************************
325: * *
326: * FUNCTION : GetInitializationData() *
327: * *
328: * PURPOSE : Gets DC initialization data from a printer driver *
329: * supporting ExtDeviceMode(). Called in response to the *
330: * File/Printer setup menu selection. *
331: * *
332: * This function allows the user to change the printer *
333: * settings FOR MULTIPAD ONLY. This allows Multipad to print *
334: * in a variety of settings without messing up any other *
335: * applications. In a more sophisticated application, this *
336: * setup could even be saved on a document-by-document basis. *
337: * *
338: ****************************************************************************/
339: BOOL APIENTRY GetInitializationData( HWND hwnd )
340: {
341: LPSTR lpOld;
342: LPSTR lpNew;
343: FARPROC lpfn;
344: HANDLE hT,hDrv;
345: CHAR sz[32];
346: int cb;
347: INT flag;
348:
349: /* Pop up dialog for user and retain data in app buffer */
350: flag = DM_PROMPT | DM_COPY;
351:
352: /* Load the device driver and find the ExtDeviceMode() function */
353: wsprintf (sz, "%s.drv", (LPSTR)szDriver);
354: if ((int)(hDrv = LoadLibrary (sz)) < 32)
355: return FALSE;
356: if (!(lpfn = GetProcAddress (hDrv, szExtDeviceMode)))
357: return FALSE;
358:
359: if (hInitData){
360: /* We have some old data... we want to modify the previously specified
361: * setup rather than starting with the default setup.
362: */
363: lpOld = (LPSTR)LocalLock(hInitData);
364: flag |= DM_MODIFY;
365: }
366: else
367: lpOld = NULL;
368:
369: /* Get the number of bytes needed for the init data */
370: cb = (*lpfn) (hwnd,
371: hDrv,
372: (LPDEVMODE)NULL,
373: (LPSTR)szDevice,
374: (LPSTR)szPort,
375: (LPDEVMODE)NULL,
376: (LPSTR)NULL,
377: 0);
378:
379: /* Grab some memory for the new data and lock it. */
380: hT = LocalAlloc (LHND,cb);
381: if(!hT){
382: MessageBox(hwnd, "<GetInitializationData> Not enough memory.", NULL, MB_OK | MB_ICONHAND);
383: LocalUnlock(hInitData);
384: LocalFree(hInitData);
385: FreeLibrary(hDrv);
386: return(FALSE);
387: }
388:
389: lpNew = (LPSTR)LocalLock (hT);
390:
391: /* Post the device mode dialog. 0 flag iff user hits OK button */
392: if ((*lpfn) (hwnd,
393: hDrv,
394: (LPDEVMODE)lpNew,
395: (LPSTR)szDevice,
396: (LPSTR)szPort,
397: (LPDEVMODE)lpOld,
398: (LPSTR)NULL,
399: flag)==IDOK)
400: flag = 0;
401:
402: /* Unlock the input structures */
403: LocalUnlock (hT);
404:
405: if (hInitData)
406: LocalUnlock (hInitData);
407:
408: /* If the user hit OK and everything worked, free the original init.
409: * data and retain the new one. Otherwise, toss the new buffer.
410: */
411: if (flag)
412: LocalFree (hT);
413: else{
414: if (hInitData)
415: LocalFree (hInitData);
416: hInitData = hT;
417: }
418:
419: FreeLibrary(hDrv);
420: return (!flag);
421: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.