|
|
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.