|
|
1.1 root 1: /*
2: Hatari
3:
4: Printer communication. When bytes are sent to the ST they are sent on to these functions
5: via 'Printer_TransferByteTo()'. This will then open a file or Windows printer and direct
6: the output to this. These bytes are buffered up(to improve speed) and this also allow us
7: to detect when the stream goes into idle - at which point we close the file/printer(Windows
8: printing will only occur when we close).
9: NOTE - Tab's are converted to spaces as the PC 'Tab' setting differs to that of the ST.
10: NOTE - As the ST differs so greatly from modern Windows printing we are limited in the way
11: we can output data - Printer no longer respond to communication over the LPT port(DOS can
12: not use modern printers). As such, we can only print out basic text based documents - the
13: output to file option allows text to be loaded into a Windows word-processor and formatted
14: correctly using that.
15: */
16:
17: #include "main.h"
18: #include "debug.h"
19: #include "dialog.h"
20: #include "file.h"
21: #include "printer.h"
22: #include "screen.h"
23: #include "statusBar.h"
24: #include "view.h"
25:
26: #define PRINTER_TAB_SETTING 8 /* A 'Tab' on the ST is 8 spaces */
27: #define PRINTER_IDLE_CLOSE (4*50) /* After 4 seconds, close printer */
28:
29: #define PRINTER_BUFFER_SIZE 2048 /* 2k buffer which when full will be written to printer/file */
30:
31: //static HFILE PrinterFile;
32: //static OFSTRUCT PrinterFileInfo;
33: static unsigned char PrinterBuffer[PRINTER_BUFFER_SIZE]; // Buffer to store character before output
34: static int nPrinterBufferChars,nPrinterBufferCharsOnLine; // # characters in above buffer
35: static BOOL bConnectedPrinter=FALSE;
36: static BOOL bPrinterDiscFile=FALSE,bPrinterWindows=FALSE;
37: //static PRINTDLG pd; // Printer Dlg
38: static BOOL bStartedPage; // Have set up new page?
39: static BOOL bAlreadyOpenedPrintingFile=FALSE; // TRUE if already opened file, so can add to end
40: static int PrinterX,PrinterY; // X,Y to print to on page
41: static int nPrinterWidthPels,nPrinterHeightPels; // Width/Height of page
42: static int nIdleCount=0; // Frames printer has been idle
43:
44: //-----------------------------------------------------------------------
45: /*
46: Initialise Printer
47: */
48: void Printer_Init(void)
49: {
50: }
51:
52: //-----------------------------------------------------------------------
53: /*
54: Uninitialise Printer
55: */
56: void Printer_UnInit(void)
57: {
58: // Close any open files
59: Printer_CloseAllConnections();
60: }
61:
62: //-----------------------------------------------------------------------
63: /*
64: Close all open files, on disc or Windows printers
65: */
66: void Printer_CloseAllConnections(void)
67: {
68: // Empty buffer
69: Printer_EmptyInternalBuffer();
70:
71: // Close any open files
72: Printer_CloseDiscFile();
73: // And printers
74: Printer_CloseWindowsPrinter();
75:
76: // Signal finished with printing
77: bConnectedPrinter = FALSE;
78: }
79:
80: //-----------------------------------------------------------------------
81: /*
82: Open file on disc, to which all printer output will be sent
83: */
84: BOOL Printer_OpenDiscFile(void)
85: {
86: /* FIXME */
87: /*
88: // Close existing
89: Printer_CloseAllConnections();
90:
91: // Open file
92: bPrinterDiscFile = TRUE;
93: // Do we have a filename for output?
94: if (strlen(ConfigureParams.Printer.szPrintToFileName)<=0) {
95: // First, Return back into a Window
96: Screen_ReturnFromFullScreen();
97: View_ToggleWindowsMouse(MOUSE_WINDOWS);
98: // Ask for filename
99: if (!File_OpenSelectDlg(hWnd,ConfigureParams.Printer.szPrintToFileName,FILEFILTER_ALLFILES,FALSE,TRUE))
100: bPrinterDiscFile = FALSE;
101: // Revert back to ST mouse mode
102: View_ToggleWindowsMouse(MOUSE_ST);
103: }
104:
105: // OK to print?
106: if (bPrinterDiscFile) {
107: // Open file to print to - if previously opened, just re-open to add to end
108: if (!bAlreadyOpenedPrintingFile)
109: PrinterFile = OpenFile(ConfigureParams.Printer.szPrintToFileName,&PrinterFileInfo,OF_CREATE | OF_WRITE);
110: else {
111: // Re-open and position at end of file
112: PrinterFile = OpenFile(ConfigureParams.Printer.szPrintToFileName,&PrinterFileInfo,OF_WRITE);
113: _llseek(PrinterFile,0,FILE_END);
114: }
115:
116: if (PrinterFile==HFILE_ERROR)
117: bPrinterDiscFile = FALSE;
118: else
119: bAlreadyOpenedPrintingFile = TRUE;
120: }
121: */
122: return(bPrinterDiscFile);
123: }
124:
125: //-----------------------------------------------------------------------
126: /*
127: Close file on disc, if we have one open
128: */
129: void Printer_CloseDiscFile(void)
130: {
131: // Do have file open?
132: if (bPrinterDiscFile) {
133: // Close
134: //FIXME _lclose(PrinterFile);
135:
136: bPrinterDiscFile = FALSE;
137: }
138: }
139:
140: //-----------------------------------------------------------------------
141: /*
142: Empty to disc file
143: */
144: void Printer_EmptyDiscFile(void)
145: {
146: // Do have file open?
147: if (bPrinterDiscFile) {
148: // Write bytes out
149: //FIXME _hwrite(PrinterFile,(char *)PrinterBuffer,nPrinterBufferChars);
150: // Reset
151: Printer_ResetInternalBuffer();
152: }
153: }
154:
155: //-----------------------------------------------------------------------
156: /*
157: Start new printer page
158: */
159: void Printer_StartNewPage(void)
160: {
161: // Reset coords on printer(start printing 'top-left')
162: PrinterX = PrinterY = 0;
163: // Set new page
164: //FIXME StartPage(pd.hDC);
165: // Set flag
166: bStartedPage = TRUE;
167: }
168:
169: //-----------------------------------------------------------------------
170: /*
171: Send character to Windows printer, add to XY position
172: */
173: void Printer_PrintCharacter(char Char)
174: {
175: /*FIXME*/
176: /*
177: SIZE CharSize;
178:
179: // Have started page? If not, begin new one
180: if (!bStartedPage)
181: Printer_StartNewPage();
182:
183: // Find width/height of character
184: GetTextExtentPoint32(pd.hDC, &Char,1, &CharSize);
185:
186: // Handle returns to new lines...
187: if (Char==0xa) {
188: PrinterY += CharSize.cy;
189: return;
190: }
191: if (Char==0xd) {
192: PrinterX = 0;
193: return;
194: }
195:
196: // Will fit on page?
197: if ((PrinterX+CharSize.cx)>=nPrinterWidthPels) {
198: PrinterY += CharSize.cy; // Off right of page, start new line
199: PrinterX = 0;
200: }
201: if ((PrinterY+CharSize.cy)>=nPrinterHeightPels) {
202: if (bStartedPage)
203: EndPage(pd.hDC); // Off bottom of page, start new one
204: Printer_StartNewPage();
205: }
206:
207: // Print character
208: TextOut(pd.hDC, PrinterX,PrinterY, &Char, 1);
209: PrinterX += CharSize.cx;
210: */
211: }
212:
213: //-----------------------------------------------------------------------
214: /*
215: Open Windows printer - Always return TRUE as sucess so we can 'print' without constantly
216: bringing up the Printer dialog if they happened to press 'Cancel'.
217: */
218: BOOL Printer_OpenWindowsPrinter(void)
219: {
220: /* FIXME */
221: /*
222: DOCINFO di;
223: int nError;
224:
225: // Close existing
226: Printer_CloseAllConnections();
227:
228: // First, Return back into a Window
229: Screen_ReturnFromFullScreen();
230: View_ToggleWindowsMouse(MOUSE_WINDOWS);
231:
232: // Initialize the PRINTDLG members.
233: pd.lStructSize = sizeof(PRINTDLG);
234: pd.hDevMode = (HANDLE) NULL;
235: pd.hDevNames = (HANDLE) NULL;
236: pd.Flags = PD_RETURNDC | PD_ALLPAGES | PD_NOSELECTION | PD_DISABLEPRINTTOFILE | PD_HIDEPRINTTOFILE;
237: pd.hwndOwner = hWnd;
238: pd.hDC = (HDC) NULL;
239: pd.nFromPage = 1;
240: pd.nToPage = 1;
241: pd.nMinPage = 0;
242: pd.nMaxPage = 0;
243: pd.nCopies = 1;
244: pd.hInstance = (HINSTANCE)NULL;
245: pd.lCustData = 0L;
246: pd.lpfnPrintHook = (LPPRINTHOOKPROC) NULL;
247: pd.lpfnSetupHook = (LPSETUPHOOKPROC) NULL;
248: pd.lpPrintTemplateName = (LPSTR) NULL;
249: pd.lpSetupTemplateName = (LPSTR) NULL;
250: pd.hPrintTemplate = (HANDLE) NULL;
251: pd.hSetupTemplate = (HANDLE) NULL;
252:
253: // Display the PRINT dialog box.
254: if (PrintDlg(&pd)!=0) {
255: // Initialize the members of a DOCINFO structure.
256: di.cbSize = sizeof(DOCINFO);
257: di.lpszDocName = "Hatari Print Output";
258: di.lpszOutput = (LPTSTR) NULL;
259: di.lpszDatatype = (LPTSTR) NULL;
260: di.fwType = 0;
261:
262: // Begin a print job by calling the StartDoc function.
263: nError = StartDoc(pd.hDC, &di);
264: if (nError == SP_ERROR) {
265: // Report error
266: Main_SysError("Unable to start Printing operation.",PROG_NAME);
267: // Delete the printer DC.
268: DeleteDC(pd.hDC);
269: // Fail printing
270: bPrinterWindows = FALSE;
271:
272: return(TRUE);
273: }
274:
275: // Get Printer Information
276: nPrinterWidthPels = GetDeviceCaps(pd.hDC, HORZRES);
277: nPrinterHeightPels = GetDeviceCaps(pd.hDC, VERTRES);
278: // Ready for first page
279: bStartedPage = FALSE;
280:
281: // All OK
282: bPrinterWindows = TRUE;
283: }
284: else
285: bPrinterWindows = FALSE;
286:
287: // Revert back to ST mouse mode
288: View_ToggleWindowsMouse(MOUSE_ST);
289: */
290: return(TRUE);
291: }
292:
293: //-----------------------------------------------------------------------
294: /*
295: Close Windows printer
296: */
297: void Printer_CloseWindowsPrinter(void)
298: {
299: /* FIXME */
300: /*
301: // Do have file open?
302: if (bPrinterWindows) {
303: // End page
304: if (bStartedPage)
305: EndPage(pd.hDC);
306: // Inform the driver that document has ended.
307: EndDoc(pd.hDC);
308: // Delete the printer DC.
309: DeleteDC(pd.hDC);
310:
311: bPrinterWindows = FALSE;
312: }
313: */
314: }
315:
316: //-----------------------------------------------------------------------
317: /*
318: Empty Windows printer
319: */
320: void Printer_EmptyWindowsPrinter(void)
321: {
322: int i;
323:
324: // Do have file open?
325: if (bPrinterWindows) {
326: // Write bytes out
327: for(i=0; i<nPrinterBufferChars; i++)
328: Printer_PrintCharacter(PrinterBuffer[i]);
329: // Reset
330: Printer_ResetInternalBuffer();
331: }
332: }
333:
334: //-----------------------------------------------------------------------
335: /*
336: Reset Printer Buffer
337: */
338: void Printer_ResetInternalBuffer(void)
339: {
340: nPrinterBufferChars = 0;
341: }
342:
343: //-----------------------------------------------------------------------
344: /*
345: Reset character line
346: */
347: void Printer_ResetCharsOnLine(void)
348: {
349: nPrinterBufferCharsOnLine = 0;
350: }
351:
352: //-----------------------------------------------------------------------
353: /*
354: Empty Printer Buffer
355: */
356: BOOL Printer_EmptyInternalBuffer(void)
357: {
358: // Write bytes to file
359: if (nPrinterBufferChars>0) {
360: if (bPrinterDiscFile)
361: Printer_EmptyDiscFile();
362: else if (bPrinterWindows)
363: Printer_EmptyWindowsPrinter();
364:
365: return(TRUE);
366: }
367:
368: // Nothing to do
369: return(FALSE);
370: }
371:
372: //-----------------------------------------------------------------------
373: /*
374: Return TRUE if byte is standard ASCII character which is OK to output
375: */
376: BOOL Printer_ValidByte(unsigned char Byte)
377: {
378: // Return/New line?
379: if ( (Byte==0x0d) || (Byte==0x0a) )
380: return(TRUE);
381: // Normal character?
382: if ( (Byte>=32) && (Byte<127) )
383: return(TRUE);
384: // Tab
385: if (Byte=='\t')
386: return(TRUE);
387: return(FALSE);
388: }
389:
390: //-----------------------------------------------------------------------
391: /*
392: Add byte to our internal buffer, and when full write out - needed to speed
393: */
394: void Printer_AddByteToInternalBuffer(unsigned char Byte)
395: {
396: // Is buffer full? If so empty
397: if (nPrinterBufferChars==PRINTER_BUFFER_SIZE)
398: Printer_EmptyInternalBuffer();
399: // Add character
400: PrinterBuffer[nPrinterBufferChars++] = Byte;
401: // Add count of character on line
402: if ( !((Byte==0xd) || (Byte==0xa)) )
403: nPrinterBufferCharsOnLine++;
404: }
405:
406: //-----------------------------------------------------------------------
407: /*
408: Add 'Tab' to internal buffer
409: */
410: void Printer_AddTabToInternalBuffer(void)
411: {
412: int i,NumSpaces;
413:
414: // Is buffer full? If so empty
415: if (nPrinterBufferChars>=(PRINTER_BUFFER_SIZE-PRINTER_TAB_SETTING))
416: Printer_EmptyInternalBuffer();
417: // Add tab - convert to 'PRINTER_TAB_SETTING' space
418: NumSpaces = PRINTER_TAB_SETTING-(nPrinterBufferCharsOnLine%PRINTER_TAB_SETTING);
419: for(i=0; i<NumSpaces; i++) {
420: PrinterBuffer[nPrinterBufferChars++] = ' ';
421: nPrinterBufferCharsOnLine++;
422: }
423: }
424:
425: //-----------------------------------------------------------------------
426: /*
427: Pass byte from emulator to printer
428: */
429: BOOL Printer_TransferByteTo(unsigned char Byte)
430: {
431: /* FIXME */
432: /*
433: // Do we want to output to a printer/file?
434: if (!ConfigureParams.Printer.bEnablePrinting)
435: return(FALSE); //Failed
436:
437: // Have we made a connection to our printer/file?
438: if (!bConnectedPrinter) {
439: // Open file, to Windows printer
440: if (ConfigureParams.Printer.bPrintToFile)
441: bConnectedPrinter = Printer_OpenDiscFile();
442: else
443: bConnectedPrinter = Printer_OpenWindowsPrinter();
444: // Reset
445: Printer_ResetInternalBuffer();
446: Printer_ResetCharsOnLine();
447: }
448:
449: // Is all OK?
450: if (bConnectedPrinter) {
451: // Add byte to our buffer, if is useable character
452: if (Printer_ValidByte(Byte)) {
453: if (Byte=='\t')
454: Printer_AddTabToInternalBuffer();
455: else
456: Printer_AddByteToInternalBuffer(Byte);
457: if (Byte==0xd)
458: nPrinterBufferCharsOnLine = 0;
459: }
460: // Show icon on status bar
461: StatusBar_SetIcon(STATUS_ICON_PRINTER,ICONSTATE_UPDATE);
462:
463: return(TRUE); //OK
464: }
465: else
466: return(FALSE); //Failed
467: */
468: }
469:
470: //-----------------------------------------------------------------------
471: /*
472: Empty printer buffer, and if remains idle for set time close connection(ie close file, stop printer)
473: */
474: void Printer_CheckIdleStatus(void)
475: {
476: // Is anything waiting for printer?
477: if (Printer_EmptyInternalBuffer()) {
478: nIdleCount = 0;
479: }
480: else {
481: nIdleCount++;
482: // Has printer been idle?
483: if (nIdleCount>=PRINTER_IDLE_CLOSE) {
484: // Close printer output
485: Printer_CloseAllConnections();
486: nIdleCount = 0;
487: }
488: }
489: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.