|
|
1.1 root 1: /* 1.1.1.5 ! root 2: Hatari - printer.c 1.1 root 3: 1.1.1.5 ! root 4: This file is distributed under the GNU Public License, version 2 or at ! 5: your option any later version. Read the file gpl.txt for details. ! 6: ! 7: Printer communication. When bytes are sent from the ST they are sent to these functions 1.1 root 8: via 'Printer_TransferByteTo()'. This will then open a file or Windows printer and direct 9: the output to this. These bytes are buffered up(to improve speed) and this also allow us 1.1.1.5 ! root 10: to detect when the stream goes into idle - at which point we close the file/printer. 1.1 root 11: NOTE - Tab's are converted to spaces as the PC 'Tab' setting differs to that of the ST. 12: 1.1.1.5 ! root 13: Hack for simple printing by Matthias Arndt <[email protected]> ! 14: ! 15: ChangeLog: ! 16: ! 17: 9 Aug 2003: Matthias Arndt <[email protected]> ! 18: - initial rewrite ! 19: - removed MS Windows specific parts ! 20: - made printing to $HOME/hatari.prn possible 1.1.1.4 root 21: 1.1.1.5 ! root 22: 10 Aug 2003 Matthias Arndt ! 23: - corrected stupid string bug that altered the environment var HOME ! 24: ! 25: */ ! 26: char Printer_rcsid[] = "Hatari $Id: printer.c,v 1.14 2004/04/19 08:53:34 thothy Exp $"; 1.1.1.4 root 27: 1.1 root 28: #include "main.h" 29: #include "debug.h" 30: #include "dialog.h" 31: #include "file.h" 32: #include "printer.h" 33: #include "screen.h" 1.1.1.3 root 34: 1.1.1.5 ! root 35: /* #define PRINTER_DEBUG */ ! 36: ! 37: #define PRINTER_FILENAME "/hatari.prn" 1.1 root 38: 39: #define PRINTER_TAB_SETTING 8 /* A 'Tab' on the ST is 8 spaces */ 40: #define PRINTER_IDLE_CLOSE (4*50) /* After 4 seconds, close printer */ 41: 42: #define PRINTER_BUFFER_SIZE 2048 /* 2k buffer which when full will be written to printer/file */ 43: 1.1.1.2 root 44: static unsigned char PrinterBuffer[PRINTER_BUFFER_SIZE]; /* Buffer to store character before output */ 1.1.1.5 ! root 45: static size_t nPrinterBufferChars; /* # characters in above buffer */ ! 46: static int nPrinterBufferCharsOnLine; 1.1 root 47: static BOOL bConnectedPrinter=FALSE; 1.1.1.5 ! root 48: static BOOL bPrinterDiscFile=FALSE; ! 49: static int nIdleCount; 1.1 root 50: 1.1.1.5 ! root 51: static FILE *PrinterFileHandle; 1.1.1.2 root 52: 1.1.1.5 ! root 53: ! 54: /*----------------------------------------------------------------------- 1.1 root 55: Initialise Printer 1.1.1.5 ! root 56: -----------------------------------------------------------------------*/ 1.1 root 57: void Printer_Init(void) 58: { 1.1.1.5 ! root 59: #ifdef PRINTER_DEBUG ! 60: fprintf(stderr,"Printer_Init()\n"); ! 61: #endif ! 62: ! 63: /* A valid file name for printing is already set up in configuration.c. ! 64: * But we check it again since the user might have entered an invalid ! 65: * file name in the ~/.hatari.cfg file... */ ! 66: if(strlen(ConfigureParams.Printer.szPrintToFileName) <= 1) ! 67: { ! 68: /* construct filename for printing.... */ ! 69: if (getenv("HOME") != NULL ! 70: && strlen(getenv("HOME"))+strlen(PRINTER_FILENAME) < sizeof(ConfigureParams.Printer.szPrintToFileName)) ! 71: sprintf(ConfigureParams.Printer.szPrintToFileName, "%s%s", getenv("HOME"), PRINTER_FILENAME); ! 72: else ! 73: sprintf(ConfigureParams.Printer.szPrintToFileName, ".%s",PRINTER_FILENAME); ! 74: } ! 75: ! 76: #ifdef PRINTER_DEBUG ! 77: fprintf(stderr,"Filename for printing: %s \n", ConfigureParams.Printer.szPrintToFileName); ! 78: #endif 1.1 root 79: } 80: 1.1.1.2 root 81: 82: /*-----------------------------------------------------------------------*/ 1.1 root 83: /* 84: Uninitialise Printer 85: */ 86: void Printer_UnInit(void) 87: { 1.1.1.2 root 88: /* Close any open files */ 1.1 root 89: Printer_CloseAllConnections(); 1.1.1.5 ! root 90: #ifdef PRINTER_DEBUG ! 91: fprintf(stderr,"Printer_UnInit()\n"); ! 92: #endif ! 93: 1.1 root 94: } 95: 1.1.1.2 root 96: 97: /*-----------------------------------------------------------------------*/ 1.1 root 98: /* 99: Close all open files, on disc or Windows printers 100: */ 101: void Printer_CloseAllConnections(void) 102: { 1.1.1.2 root 103: /* Empty buffer */ 1.1 root 104: Printer_EmptyInternalBuffer(); 105: 1.1.1.2 root 106: /* Close any open files */ 1.1 root 107: Printer_CloseDiscFile(); 108: 1.1.1.2 root 109: /* Signal finished with printing */ 1.1 root 110: bConnectedPrinter = FALSE; 111: } 112: 1.1.1.2 root 113: 1.1.1.5 ! root 114: /*----------------------------------------------------------------------- 1.1 root 115: Open file on disc, to which all printer output will be sent 1.1.1.5 ! root 116: -----------------------------------------------------------------------*/ 1.1 root 117: BOOL Printer_OpenDiscFile(void) 118: { 119: 120: bPrinterDiscFile = TRUE; 121: 1.1.1.5 ! root 122: /* open printer file... */ ! 123: PrinterFileHandle = fopen(ConfigureParams.Printer.szPrintToFileName, "a+"); ! 124: if(!PrinterFileHandle) ! 125: bPrinterDiscFile=FALSE; 1.1 root 126: 127: return(bPrinterDiscFile); 128: } 129: 1.1.1.2 root 130: 1.1.1.5 ! root 131: /*----------------------------------------------------------------------- 1.1 root 132: Close file on disc, if we have one open 1.1.1.5 ! root 133: -----------------------------------------------------------------------*/ 1.1 root 134: void Printer_CloseDiscFile(void) 135: { 1.1.1.2 root 136: /* Do have file open? */ 1.1 root 137: if (bPrinterDiscFile) { 1.1.1.2 root 138: /* Close */ 1.1.1.5 ! root 139: fclose(PrinterFileHandle); 1.1 root 140: bPrinterDiscFile = FALSE; 141: } 142: } 143: 1.1.1.2 root 144: 1.1.1.5 ! root 145: /*----------------------------------------------------------------------- 1.1 root 146: Empty to disc file 1.1.1.5 ! root 147: -----------------------------------------------------------------------*/ 1.1 root 148: void Printer_EmptyDiscFile(void) 149: { 1.1.1.2 root 150: /* Do have file open? */ 1.1 root 151: if (bPrinterDiscFile) { 1.1.1.2 root 152: /* Write bytes out */ 1.1.1.5 ! root 153: if(fwrite((unsigned char *)PrinterBuffer,sizeof(unsigned char),nPrinterBufferChars,PrinterFileHandle) < nPrinterBufferChars) ! 154: { ! 155: /* we wrote less then all chars in the buffer --> ERROR */ ! 156: fprintf(stderr,"Printer_EmptyDiscFile(): ERROR not all chars were written\n"); ! 157: } 1.1.1.2 root 158: /* Reset */ 1.1 root 159: Printer_ResetInternalBuffer(); 160: } 161: } 162: 1.1.1.2 root 163: 1.1.1.5 ! root 164: /*----------------------------------------------------------------------- 1.1 root 165: Reset Printer Buffer 1.1.1.5 ! root 166: -----------------------------------------------------------------------*/ 1.1 root 167: void Printer_ResetInternalBuffer(void) 168: { 169: nPrinterBufferChars = 0; 170: } 171: 1.1.1.5 ! root 172: /*----------------------------------------------------------------------- 1.1 root 173: Reset character line 1.1.1.5 ! root 174: *----------------------------------------------------------------------*/ 1.1 root 175: void Printer_ResetCharsOnLine(void) 176: { 177: nPrinterBufferCharsOnLine = 0; 178: } 179: 1.1.1.2 root 180: 1.1.1.5 ! root 181: /*----------------------------------------------------------------------- 1.1 root 182: Empty Printer Buffer 1.1.1.5 ! root 183: -----------------------------------------------------------------------*/ 1.1 root 184: BOOL Printer_EmptyInternalBuffer(void) 185: { 1.1.1.2 root 186: /* Write bytes to file */ 1.1 root 187: if (nPrinterBufferChars>0) { 188: if (bPrinterDiscFile) 189: Printer_EmptyDiscFile(); 190: 191: return(TRUE); 192: } 193: 1.1.1.2 root 194: /* Nothing to do */ 1.1 root 195: return(FALSE); 196: } 197: 1.1.1.2 root 198: 1.1.1.5 ! root 199: /*----------------------------------------------------------------------- 1.1 root 200: Return TRUE if byte is standard ASCII character which is OK to output 1.1.1.5 ! root 201: -----------------------------------------------------------------------*/ 1.1 root 202: BOOL Printer_ValidByte(unsigned char Byte) 203: { 1.1.1.2 root 204: /* Return/New line? */ 1.1 root 205: if ( (Byte==0x0d) || (Byte==0x0a) ) 206: return(TRUE); 1.1.1.2 root 207: /* Normal character? */ 1.1 root 208: if ( (Byte>=32) && (Byte<127) ) 209: return(TRUE); 1.1.1.2 root 210: /* Tab */ 1.1 root 211: if (Byte=='\t') 212: return(TRUE); 213: return(FALSE); 214: } 215: 1.1.1.2 root 216: 217: /*-----------------------------------------------------------------------*/ 1.1 root 218: /* 219: Add byte to our internal buffer, and when full write out - needed to speed 220: */ 221: void Printer_AddByteToInternalBuffer(unsigned char Byte) 222: { 1.1.1.2 root 223: /* Is buffer full? If so empty */ 1.1 root 224: if (nPrinterBufferChars==PRINTER_BUFFER_SIZE) 225: Printer_EmptyInternalBuffer(); 1.1.1.2 root 226: /* Add character */ 1.1 root 227: PrinterBuffer[nPrinterBufferChars++] = Byte; 1.1.1.2 root 228: /* Add count of character on line */ 1.1 root 229: if ( !((Byte==0xd) || (Byte==0xa)) ) 230: nPrinterBufferCharsOnLine++; 231: } 232: 1.1.1.2 root 233: 1.1.1.5 ! root 234: /*----------------------------------------------------------------------- 1.1 root 235: Add 'Tab' to internal buffer 1.1.1.5 ! root 236: -----------------------------------------------------------------------*/ 1.1 root 237: void Printer_AddTabToInternalBuffer(void) 238: { 239: int i,NumSpaces; 240: 1.1.1.2 root 241: /* Is buffer full? If so empty */ 1.1 root 242: if (nPrinterBufferChars>=(PRINTER_BUFFER_SIZE-PRINTER_TAB_SETTING)) 243: Printer_EmptyInternalBuffer(); 1.1.1.2 root 244: /* Add tab - convert to 'PRINTER_TAB_SETTING' space */ 1.1 root 245: NumSpaces = PRINTER_TAB_SETTING-(nPrinterBufferCharsOnLine%PRINTER_TAB_SETTING); 246: for(i=0; i<NumSpaces; i++) { 247: PrinterBuffer[nPrinterBufferChars++] = ' '; 248: nPrinterBufferCharsOnLine++; 249: } 250: } 251: 1.1.1.2 root 252: 1.1.1.5 ! root 253: /*----------------------------------------------------------------------- 1.1 root 254: Pass byte from emulator to printer 1.1.1.5 ! root 255: -----------------------------------------------------------------------*/ 1.1 root 256: BOOL Printer_TransferByteTo(unsigned char Byte) 257: { 1.1.1.5 ! root 258: /* Do we want to output to a printer/file? */ 1.1 root 259: if (!ConfigureParams.Printer.bEnablePrinting) 1.1.1.5 ! root 260: return(FALSE); /* Failed if printing disabled */ 1.1 root 261: 1.1.1.5 ! root 262: /* Have we made a connection to our printer/file? */ 1.1 root 263: if (!bConnectedPrinter) { 1.1.1.5 ! root 264: bConnectedPrinter = Printer_OpenDiscFile(); ! 265: ! 266: /* Reset the printer */ 1.1 root 267: Printer_ResetInternalBuffer(); 268: Printer_ResetCharsOnLine(); 269: } 270: 1.1.1.5 ! root 271: /* Is all OK? */ 1.1 root 272: if (bConnectedPrinter) { 1.1.1.5 ! root 273: /* Add byte to our buffer, if is useable character */ 1.1 root 274: if (Printer_ValidByte(Byte)) { 275: if (Byte=='\t') 276: Printer_AddTabToInternalBuffer(); 277: else 278: Printer_AddByteToInternalBuffer(Byte); 279: if (Byte==0xd) 280: nPrinterBufferCharsOnLine = 0; 281: } 282: 1.1.1.5 ! root 283: return(TRUE); /* OK */ 1.1 root 284: } 285: else 1.1.1.5 ! root 286: 1.1.1.4 root 287: return(FALSE); /* Failed */ 1.1 root 288: } 289: 1.1.1.2 root 290: 1.1.1.5 ! root 291: /*----------------------------------------------------------------------- ! 292: Empty printer buffer, and if remains idle for set time close connection ! 293: (ie close file, stop printer) ! 294: -----------------------------------------------------------------------*/ 1.1 root 295: void Printer_CheckIdleStatus(void) 296: { 1.1.1.2 root 297: /* Is anything waiting for printer? */ 1.1 root 298: if (Printer_EmptyInternalBuffer()) { 299: nIdleCount = 0; 300: } 301: else { 302: nIdleCount++; 1.1.1.2 root 303: /* Has printer been idle? */ 1.1 root 304: if (nIdleCount>=PRINTER_IDLE_CLOSE) { 1.1.1.2 root 305: /* Close printer output */ 1.1 root 306: Printer_CloseAllConnections(); 307: nIdleCount = 0; 308: } 309: } 310: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.