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