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