I'll post the patch here because I cannot upload it (File Upload: ArtifactFile: Could not open file for writing). Sorry for the inconvenience. Here's the patch:
diff --git a/INSTALL b/INSTALL
index 6be2b89..10a6d81 100644
--- a/INSTALL
+++ b/INSTALL
@@ -41,6 +41,9 @@ ALSA_Headers
for Alsa support under linux. Part of the linux kernel sources
Licensed under LGPL
+FreeType2
+ For printer support (optional). Get it from http://www.freetype.org/.
+
If you want compile from the CVS under a unix system, you'll also need
automake (>=1.6), autoconf(>=2.50). Should be available at http://www.gnu.org
diff --git a/README b/README
index 71cb23e..8baa66d 100644
--- a/README
+++ b/README
@@ -47,9 +47,9 @@ well as the description of the MOUNT command (section 4).
diff --git a/autogen.sh b/autogen.sh
old mode 100755
new mode 100644
index 4d7d5ba..e3b71d9
diff --git a/configure.in b/configure.in
index a773aa0..09c2f73 100644
--- a/configure.in
+++ b/configure.in
@@ -302,10 +302,12 @@ else
fi
AH_TEMPLATE(C_SSHOT,[Define to 1 to enable screenshots, requires libpng])
+AH_TEMPLATE(C_LIBPNG,[Define to 1 if you have libpng])
AC_CHECK_HEADER(png.h,have_png_h=yes,)
AC_CHECK_LIB(png, png_check_sig, have_png_lib=yes, ,-lz)
if test x$have_png_lib = xyes -a x$have_png_h = xyes ; then
LIBS="$LIBS -lpng -lz"
+ AC_DEFINE(C_LIBPNG,1)
AC_DEFINE(C_SSHOT,1)
else
AC_MSG_WARN([Can't find libpng, screenshot support disabled])
@@ -378,6 +380,17 @@ else
AC_MSG_WARN([Can't find libSDL_sound, libSDL_sound support disabled])
fi
+AH_TEMPLATE(C_PRINTER,[Define to 1 to use printer support])
+AC_ARG_ENABLE(printer,AC_HELP_STRING([--disable-printer],[Disable printer support]),,enable_printer=yes)
+AC_PATH_PROG(FREETYPE_CONFIG, freetype-config, no)
+if test "$FREETYPE_CONFIG" = "no" ; then
+ AC_MSG_WARN([Can't find FreeType2, printer disabled])
+else
+ AC_DEFINE(C_PRINTER,1)
+ CXXFLAGS="$CXXFLAGS $FREETYPE_CONFIG --cflags"
+ LIBS="$LIBS $FREETYPE_CONFIG --libs"
+fi
+
dnl Check for mprotect. Needed for 64 bits linux
AH_TEMPLATE(C_HAVE_MPROTECT,[Define to 1 if you have the mprotect function])
AC_CHECK_HEADER([sys/mman.h], [
diff --git a/include/Makefile.am b/include/Makefile.am
index ce2c03c..209d791 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -33,5 +33,6 @@ shell.h \
support.h \
timer.h \
vga.h \
-video.h
+video.h \
+printer.h
diff --git a/include/printer.h b/include/printer.h
new file mode 100644
index 0000000..4c41b82
--- /dev/null
+++ b/include/printer.h
@@ -0,0 +1,233 @@
+/
+ * Copyright (C) 2002-2004 The DOSBox Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ /
+
+#include <dosbox.h>
+
+#if C_PRINTER
+
+#if !defined __PRINTER_H
+#define __PRINTER_H
+
+#include "SDL.h"
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#if defined (WIN32)
+#include <windows.h>
+#include <winspool.h>
+#endif
+
+#define STYLE_PROP 0x01
+#define STYLE_CONDENSED 0x02
+#define STYLE_BOLD 0x04
+#define STYLE_DOUBLESTRIKE 0x08
+#define STYLE_DOUBLEWIDTH 0x10
+#define STYLE_ITALICS 0x20
+#define STYLE_UNDERLINE 0x40
+#define STYLE_SUPERSCRIPT 0x80
+#define STYLE_SUBSCRIPT 0x100
+#define STYLE_STRIKETHROUGH 0x200
+#define STYLE_OVERSCORE 0x400
+#define STYLE_DOUBLEWIDTHONELINE 0x800
+#define STYLE_DOUBLEHEIGHT 0x1000
+
+#define SCORE_NONE 0x00
+#define SCORE_SINGLE 0x01
+#define SCORE_DOUBLE 0x02
+#define SCORE_SINGLEBROKEN 0x05
+#define SCORE_DOUBLEBROKEN 0x06
+
+#define QUALITY_DRAFT 0x01
+#define QUALITY_LQ 0x02
+
+enum Typeface
+{
+ roman = 0,
+ sansserif,
+ courier,
+ prestige,
+ script,
+ ocrb,
+ ocra,
+ orator,
+ orators,
+ scriptc,
+ romant,
+ sansserifh,
+ svbusaba = 30,
+ svjittra = 31
+};
+
+
+class CPrinter {
+public:
+
+ CPrinter (Bit16u dpi, Bit16u width, Bit16u height, char output, bool multipageOutput);
+ virtual ~CPrinter();
+
+ // Process one character sent to virtual printer
+ void printChar(Bit8u ch);
+
+ // Hard Reset (like switching printer off and on)
+ void resetPrinterHard();
+
+ // Set Autofeed value
+ void setAutofeed(bool feed);
+
+ // Get Autofeed value
+ bool getAutofeed();
+
+ // True if printer is unable to process more data right now (do not use printChar)
+ bool isBusy();
+
+ // True if the last sent character was received
+ bool ack();
+
+ // Manual formfeed
+ void formFeed();
+
+ // Returns true if the current page is blank
+ bool isBlank();
+
+private:
+
+ // Checks if given char belongs to a command and process it. If false, the character
+ // should be printed
+ bool processCommandChar(Bit8u ch);
+
+ // Resets the printer to the factory settings
+ void resetPrinter();
+
+ // Reload font. Must be called after changing dpi, style or cpi
+ void updateFont();
+
+ // Clears page. If save is true, saves the current page to a bitmap
+ void newPage(bool save);
+
+ // Blits the given glyph on the page surface. If add is true, the values of bitmap are
+ // added to the values of the pixels in the page
+ void blitGlyph(FT_Bitmap bitmap, Bit16u destx, Bit16u desty, bool add);
+
+ // Draws an anti-aliased line from (fromx, y) to (tox, y). If broken is true, gaps are included
+ void drawLine(Bit8u fromx, Bit8u tox, Bit8u y, bool broken);
+
+ // Setup the bitGraph structure
+ void setupBitImage(Bit8u dens, Bit16u numCols);
+
+ // Process a character that is part of bit image. Must be called iff bitGraph.remBytes > 0.
+ void printBitGraph(Bit8u ch);
+
+ // Copies the codepage mapping from the constant array to CurMap
+ void selectCodepage(Bit16u cp);
+
+ // Output current page
+ void outputPage();
+
+ // Prints out a byte using ASCII85 encoding (only outputs something every four bytes). When b>255, closes the ASCII85 string
+ void fprintASCII85(FILE f, Bit16u b);
+
+ // Closes a multipage document
+ void finishMultipage();
+
+ // Returns value of the num-th pixel (couting left-right, top-down) in a safe way
+ Bit8u getPixel(Bit32u num);
+
+ FT_Library FTlib; // FreeType2 library used to render the characters
+
+ SDL_Surface page; // Surface representing the current page
+ FT_Face curFont; // The font currently used to render characters
+
+ Real64 curX, curY; // Position of the print head (in inch)
+
+ Bit16u dpi; // dpi of the page
+ Bit16u ESCCmd; // ESC-command that is currently processed
+ bool ESCSeen; // True if last read character was an ESC (0x1B)
+
+ Bit8u numParam, neededParam; // Numbers of parameters already read/needed to process command
+
+ Bit8u params[20]; // Buffer for the read params
+ Bit16u style; // Style of font (see STYLE_ constants)
+ Real64 cpi, actcpi; // CPI value set by program and the actual one (taking in account font types)
+ Bit8u score; // Score for lines (see SCORE_ constants)
+
+ Real64 topMargin, bottomMargin, rightMargin, leftMargin; // Margins of the page (in inch)
+ Real64 pageWidth, pageHeight; // Size of page (in inch)
+ Real64 defaultPageWidth, defaultPageHeight; // Default size of page (in inch)
+ Real64 lineSpacing; // Size of one line (in inch)
+
+ Real64 horiztabs[32]; // Stores the set horizontal tabs (in inch)
+ Bit8u numHorizTabs; // Number of configured tabs
+
+ Real64 verttabs[16]; // Stores the set vertical tabs (in inch)
+ Bit8u numVertTabs; // Number of configured tabs
+
+ Bit8u curCharTable; // Currently used char table und charset
+ Bit8u printQuality; // Print quality (see QUALITY_ constants)
+
+ Typeface LQtypeFace; // Typeface used in LQ printing mode
+
+ Real64 extraIntraSpace; // Extra space between two characters (set by program, in inch)
+
+ bool charRead; // True if a character was read since the printer was last initialized
+ bool autoFeed; // True if a LF should automatically added after a CR
+ bool printUpperContr; // True if the upper command characters should be printed
+
+ struct bitGraphicParams // Holds information about printing bit images
+ {
+ Bit16u horizDens, vertDens; // Density of image to print (in dpi)
+ bool adjacent; // Print adjacent pixels? (ignored)
+ Bit8u bytesColumn; // Bytes per column
+ Bit16u remBytes; // Bytes left to read before image is done
+ Bit8u column[6]; // Bytes of the current and last column
+ Bit8u readBytesColumn; // Bytes read so far for the current column
+ } bitGraph;
+
+ Bit8u densk, densl, densy, densz; // Image density modes used in ESC K/L/Y/Z commands
+
+ Bit16u curMap[256]; // Currently used ASCII => Unicode mapping
+ Bit16u charTables[4]; // Charactertables
+
+ Real64 definedUnit; // Unit used by some ESC/P2 commands (negative => use default)
+
+ bool multipoint; // If multipoint mode is enabled
+ Real64 multiPointSize; // Point size of font in multipoint mode
+ Real64 multicpi; // CPI used in multipoint mode
+
+ Real64 hmi; // Horizontal motion index (in inch; overrides CPI settings)
+
+ Bit8u msb; // MSB mode
+ Bit16u numPrintAsChar; // Number of bytes to print as characters (even when normally control codes)
+
+#if defined (WIN32)
+ HDC printerDC; // Win32 printer device
+#endif
+
+ char output; // Output method selected by user
+ void outputHandle; // If not null, additional pages will be appended to the given handle
+ bool multipageOutput; // If true, all pages are combined to one file/print job etc. until the "eject page" button is pressed
+ Bit16u multiPageCounter; // Current page (when printing multipages)
+
+ Bit8u ASCII85Buffer[4]; // Buffer used in ASCII85 encoding
+ Bit8u ASCII85BufferPos; // Position in ASCII85 encode buffer
+ Bit8u ASCII85CurCol; // Columns printed so far in the current lines
+};
+
+#endif
+
+#endif
diff --git a/src/dos/Makefile.am b/src/dos/Makefile.am
index 3bdfbf5..f2cf307 100644
--- a/src/dos/Makefile.am
+++ b/src/dos/Makefile.am
@@ -5,6 +5,6 @@ EXTRA_DIST = scsidefs.h wnaspi32.h dos_codepages.h dos_keyboard_layout_data.h
libdos_a_SOURCES = dos.cpp dos_devices.cpp dos_execute.cpp dos_files.cpp dos_ioctl.cpp dos_memory.cpp \
dos_misc.cpp dos_classes.cpp dos_programs.cpp dos_tables.cpp \
drives.cpp drives.h drive_virtual.cpp drive_local.cpp drive_cache.cpp drive_fat.cpp \
- drive_iso.cpp dev_con.h dos_mscdex.cpp dos_keyboard_layout.cpp \
+ drive_iso.cpp dev_con.h dev_lpt.h dos_mscdex.cpp dos_keyboard_layout.cpp \
cdrom.h cdrom.cpp cdrom_ioctl_win32.cpp cdrom_aspi_win32.cpp cdrom_ioctl_linux.cpp cdrom_image.cpp \
cdrom_ioctl_os2.cpp
diff --git a/src/dos/dev_lpt.h b/src/dos/dev_lpt.h
new file mode 100644
index 0000000..a13e481
--- /dev/null
+++ b/src/dos/dev_lpt.h
@@ -0,0 +1,71 @@
+/
+ * Copyright (C) 2002-2004 The DOSBox Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ /
+
+#include "dos_inc.h"
+#include "inout.h"
+
+class device_LPT : public DOS_Device {
+public:
+ // Creates a LPT device that communicates with the num-th parallel port, i.e. is LPTnum
+ device_LPT(char name, Bit8u num);
+ bool Read(Bit8u * data,Bit16u * size);
+ bool Write(Bit8u * data,Bit16u * size);
+ bool Seek(Bit32u * pos,Bit32u type);
+ bool Close();
+ Bit16u GetInformation(void);
+private:
+ Bit8u num; // This device is LPTnum
+};
+
+bool device_LPT::Read(Bit8u * data,Bit16u * size)
+{
+ size=0;
+ LOG(LOG_DOSMISC,LOG_NORMAL)("LPTDEVICE:Read called");
+ return true;
+}
+
+
+bool device_LPT::Write(Bit8u * data,Bit16u * size)
+{
+ for (Bit16u i=0; i<size; i++)
+ IO_WriteB(real_readw(0x0040, 0x0008 + ((num-1)2)), data[i]);
+
+ return true;
+}
+
+bool device_LPT::Seek(Bit32u * pos,Bit32u type)
+{
+ pos = 0;
+ return true;
+}
+
+bool device_LPT::Close()
+{
+ return false;
+}
+
+Bit16u device_LPT::GetInformation(void)
+{
+ return 0x80A0;
+};
+
+device_LPT::device_LPT(char name, Bit8u num)
+{
+ this->name = name;
+ this->num = num;
+}
diff --git a/src/dos/dos.cpp b/src/dos/dos.cpp
index 5b0539d..b48db9e 100644
--- a/src/dos/dos.cpp
+++ b/src/dos/dos.cpp
@@ -29,6 +29,8 @@
#include "regs.h"
#include "dos_inc.h"
#include "setup.h"
+/// Added ... maybe superfluous
+#include "inout.h"
#include "support.h"
#include "serialport.h"</winspool.h></windows.h></ft2build.h></dosbox.h>
@@ -103,8 +105,13 @@ static Bitu DOS_21Handler(void) {
}
break;
case 0x05: / Write Character to PRINTER /
- E_Exit("DOS:Unhandled call %02X",reg_ah);
+#ifdef C_PRINTER
+ // DOS function only allows printing to LPT1 and returns nothing
+ IO_WriteB(real_readw(0x0040, 0x0008), reg_dl);
break;
+#else
+ E_Exit("DOS:Unhandled call %02X",reg_ah);
+#endif
case 0x06: / Direct Console Output / Input /
switch (reg_dl) {
case 0xFF: / Input /
diff --git a/src/dos/dos_devices.cpp b/src/dos/dos_devices.cpp
index e052a59..41ccc1b 100644
--- a/src/dos/dos_devices.cpp
+++ b/src/dos/dos_devices.cpp
@@ -31,6 +31,9 @@
Logged In: YES
user_id=995396
Originator: YES
Hmm ... I'll try to upload the patch again.
Logged In: YES
user_id=995396
Originator: YES
Third try ... I hope that sf.net fixed the problem.
Logged In: YES
user_id=995396
Originator: YES
I'll post the patch here because I cannot upload it (File Upload: ArtifactFile: Could not open file for writing). Sorry for the inconvenience. Here's the patch:
diff --git a/INSTALL b/INSTALL
index 6be2b89..10a6d81 100644
--- a/INSTALL
+++ b/INSTALL
@@ -41,6 +41,9 @@ ALSA_Headers
for Alsa support under linux. Part of the linux kernel sources
Licensed under LGPL
+FreeType2
+ For printer support (optional). Get it from http://www.freetype.org/.
+
If you want compile from the CVS under a unix system, you'll also need
automake (>=1.6), autoconf(>=2.50). Should be available at http://www.gnu.org
diff --git a/README b/README
index 71cb23e..8baa66d 100644
--- a/README
+++ b/README
@@ -47,9 +47,9 @@ well as the description of the MOUNT command (section 4).
-=======
-2. FAQ:
-=======
+====================================
+2. FAQ (Frequently Asked Questions):
+====================================
Some Frequently Asked Questions:
diff --git a/autogen.sh b/autogen.sh
old mode 100755
new mode 100644
index 4d7d5ba..e3b71d9
diff --git a/configure.in b/configure.in
index a773aa0..09c2f73 100644
--- a/configure.in
+++ b/configure.in
@@ -302,10 +302,12 @@ else
fi
AH_TEMPLATE(C_SSHOT,[Define to 1 to enable screenshots, requires libpng])
+AH_TEMPLATE(C_LIBPNG,[Define to 1 if you have libpng])
AC_CHECK_HEADER(png.h,have_png_h=yes,)
AC_CHECK_LIB(png, png_check_sig, have_png_lib=yes, ,-lz)
if test x$have_png_lib = xyes -a x$have_png_h = xyes ; then
LIBS="$LIBS -lpng -lz"
+ AC_DEFINE(C_LIBPNG,1)
AC_DEFINE(C_SSHOT,1)
else
AC_MSG_WARN([Can't find libpng, screenshot support disabled])
@@ -378,6 +380,17 @@ else
AC_MSG_WARN([Can't find libSDL_sound, libSDL_sound support disabled])
fi
+AH_TEMPLATE(C_PRINTER,[Define to 1 to use printer support])
+AC_ARG_ENABLE(printer,AC_HELP_STRING([--disable-printer],[Disable printer support]),,enable_printer=yes)
+AC_PATH_PROG(FREETYPE_CONFIG, freetype-config, no)
+if test "$FREETYPE_CONFIG" = "no" ; then
+ AC_MSG_WARN([Can't find FreeType2, printer disabled])
+else
+ AC_DEFINE(C_PRINTER,1)
+ CXXFLAGS="$CXXFLAGS
$FREETYPE_CONFIG --cflags"+ LIBS="$LIBS
$FREETYPE_CONFIG --libs"+fi
+
dnl Check for mprotect. Needed for 64 bits linux
AH_TEMPLATE(C_HAVE_MPROTECT,[Define to 1 if you have the mprotect function])
AC_CHECK_HEADER([sys/mman.h], [
diff --git a/include/Makefile.am b/include/Makefile.am
index ce2c03c..209d791 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -33,5 +33,6 @@ shell.h \
support.h \
timer.h \
vga.h \
-video.h
+video.h \
+printer.h
diff --git a/include/printer.h b/include/printer.h
new file mode 100644
index 0000000..4c41b82
--- /dev/null
+++ b/include/printer.h
@@ -0,0 +1,233 @@
+/
+ * Copyright (C) 2002-2004 The DOSBox Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ /
+
+#include <dosbox.h>
+
+#if C_PRINTER
+
+#if !defined __PRINTER_H
+#define __PRINTER_H
+
+#include "SDL.h"
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#if defined (WIN32)
+#include <windows.h>
+#include <winspool.h>
+#endif
+
+#define STYLE_PROP 0x01
+#define STYLE_CONDENSED 0x02
+#define STYLE_BOLD 0x04
+#define STYLE_DOUBLESTRIKE 0x08
+#define STYLE_DOUBLEWIDTH 0x10
+#define STYLE_ITALICS 0x20
+#define STYLE_UNDERLINE 0x40
+#define STYLE_SUPERSCRIPT 0x80
+#define STYLE_SUBSCRIPT 0x100
+#define STYLE_STRIKETHROUGH 0x200
+#define STYLE_OVERSCORE 0x400
+#define STYLE_DOUBLEWIDTHONELINE 0x800
+#define STYLE_DOUBLEHEIGHT 0x1000
+
+#define SCORE_NONE 0x00
+#define SCORE_SINGLE 0x01
+#define SCORE_DOUBLE 0x02
+#define SCORE_SINGLEBROKEN 0x05
+#define SCORE_DOUBLEBROKEN 0x06
+
+#define QUALITY_DRAFT 0x01
+#define QUALITY_LQ 0x02
+
+enum Typeface
+{
+ roman = 0,
+ sansserif,
+ courier,
+ prestige,
+ script,
+ ocrb,
+ ocra,
+ orator,
+ orators,
+ scriptc,
+ romant,
+ sansserifh,
+ svbusaba = 30,
+ svjittra = 31
+};
+
+
+class CPrinter {
+public:
+
+ CPrinter (Bit16u dpi, Bit16u width, Bit16u height, char output, bool multipageOutput);
+ virtual ~CPrinter();
+
+ // Process one character sent to virtual printer
+ void printChar(Bit8u ch);
+
+ // Hard Reset (like switching printer off and on)
+ void resetPrinterHard();
+
+ // Set Autofeed value
+ void setAutofeed(bool feed);
+
+ // Get Autofeed value
+ bool getAutofeed();
+
+ // True if printer is unable to process more data right now (do not use printChar)
+ bool isBusy();
+
+ // True if the last sent character was received
+ bool ack();
+
+ // Manual formfeed
+ void formFeed();
+
+ // Returns true if the current page is blank
+ bool isBlank();
+
+private:
+
+ // Checks if given char belongs to a command and process it. If false, the character
+ // should be printed
+ bool processCommandChar(Bit8u ch);
+
+ // Resets the printer to the factory settings
+ void resetPrinter();
+
+ // Reload font. Must be called after changing dpi, style or cpi
+ void updateFont();
+
+ // Clears page. If save is true, saves the current page to a bitmap
+ void newPage(bool save);
+
+ // Blits the given glyph on the page surface. If add is true, the values of bitmap are
+ // added to the values of the pixels in the page
+ void blitGlyph(FT_Bitmap bitmap, Bit16u destx, Bit16u desty, bool add);
+
+ // Draws an anti-aliased line from (fromx, y) to (tox, y). If broken is true, gaps are included
+ void drawLine(Bit8u fromx, Bit8u tox, Bit8u y, bool broken);
+
+ // Setup the bitGraph structure
+ void setupBitImage(Bit8u dens, Bit16u numCols);
+
+ // Process a character that is part of bit image. Must be called iff bitGraph.remBytes > 0.
+ void printBitGraph(Bit8u ch);
+
+ // Copies the codepage mapping from the constant array to CurMap
+ void selectCodepage(Bit16u cp);
+
+ // Output current page
+ void outputPage();
+
+ // Prints out a byte using ASCII85 encoding (only outputs something every four bytes). When b>255, closes the ASCII85 string
+ void fprintASCII85(FILE f, Bit16u b);
+
+ // Closes a multipage document
+ void finishMultipage();
+
+ // Returns value of the num-th pixel (couting left-right, top-down) in a safe way
+ Bit8u getPixel(Bit32u num);
+
+ FT_Library FTlib; // FreeType2 library used to render the characters
+
+ SDL_Surface page; // Surface representing the current page
+ FT_Face curFont; // The font currently used to render characters
+
+ Real64 curX, curY; // Position of the print head (in inch)
+
+ Bit16u dpi; // dpi of the page
+ Bit16u ESCCmd; // ESC-command that is currently processed
+ bool ESCSeen; // True if last read character was an ESC (0x1B)
+
+ Bit8u numParam, neededParam; // Numbers of parameters already read/needed to process command
+
+ Bit8u params[20]; // Buffer for the read params
+ Bit16u style; // Style of font (see STYLE_ constants)
+ Real64 cpi, actcpi; // CPI value set by program and the actual one (taking in account font types)
+ Bit8u score; // Score for lines (see SCORE_ constants)
+
+ Real64 topMargin, bottomMargin, rightMargin, leftMargin; // Margins of the page (in inch)
+ Real64 pageWidth, pageHeight; // Size of page (in inch)
+ Real64 defaultPageWidth, defaultPageHeight; // Default size of page (in inch)
+ Real64 lineSpacing; // Size of one line (in inch)
+
+ Real64 horiztabs[32]; // Stores the set horizontal tabs (in inch)
+ Bit8u numHorizTabs; // Number of configured tabs
+
+ Real64 verttabs[16]; // Stores the set vertical tabs (in inch)
+ Bit8u numVertTabs; // Number of configured tabs
+
+ Bit8u curCharTable; // Currently used char table und charset
+ Bit8u printQuality; // Print quality (see QUALITY_ constants)
+
+ Typeface LQtypeFace; // Typeface used in LQ printing mode
+
+ Real64 extraIntraSpace; // Extra space between two characters (set by program, in inch)
+
+ bool charRead; // True if a character was read since the printer was last initialized
+ bool autoFeed; // True if a LF should automatically added after a CR
+ bool printUpperContr; // True if the upper command characters should be printed
+
+ struct bitGraphicParams // Holds information about printing bit images
+ {
+ Bit16u horizDens, vertDens; // Density of image to print (in dpi)
+ bool adjacent; // Print adjacent pixels? (ignored)
+ Bit8u bytesColumn; // Bytes per column
+ Bit16u remBytes; // Bytes left to read before image is done
+ Bit8u column[6]; // Bytes of the current and last column
+ Bit8u readBytesColumn; // Bytes read so far for the current column
+ } bitGraph;
+
+ Bit8u densk, densl, densy, densz; // Image density modes used in ESC K/L/Y/Z commands
+
+ Bit16u curMap[256]; // Currently used ASCII => Unicode mapping
+ Bit16u charTables[4]; // Charactertables
+
+ Real64 definedUnit; // Unit used by some ESC/P2 commands (negative => use default)
+
+ bool multipoint; // If multipoint mode is enabled
+ Real64 multiPointSize; // Point size of font in multipoint mode
+ Real64 multicpi; // CPI used in multipoint mode
+
+ Real64 hmi; // Horizontal motion index (in inch; overrides CPI settings)
+
+ Bit8u msb; // MSB mode
+ Bit16u numPrintAsChar; // Number of bytes to print as characters (even when normally control codes)
+
+#if defined (WIN32)
+ HDC printerDC; // Win32 printer device
+#endif
+
+ char output; // Output method selected by user
+ void outputHandle; // If not null, additional pages will be appended to the given handle
+ bool multipageOutput; // If true, all pages are combined to one file/print job etc. until the "eject page" button is pressed
+ Bit16u multiPageCounter; // Current page (when printing multipages)
+
+ Bit8u ASCII85Buffer[4]; // Buffer used in ASCII85 encoding
+ Bit8u ASCII85BufferPos; // Position in ASCII85 encode buffer
+ Bit8u ASCII85CurCol; // Columns printed so far in the current lines
+};
+
+#endif
+
+#endif
diff --git a/src/dos/Makefile.am b/src/dos/Makefile.am
index 3bdfbf5..f2cf307 100644
--- a/src/dos/Makefile.am
+++ b/src/dos/Makefile.am
@@ -5,6 +5,6 @@ EXTRA_DIST = scsidefs.h wnaspi32.h dos_codepages.h dos_keyboard_layout_data.h
libdos_a_SOURCES = dos.cpp dos_devices.cpp dos_execute.cpp dos_files.cpp dos_ioctl.cpp dos_memory.cpp \
dos_misc.cpp dos_classes.cpp dos_programs.cpp dos_tables.cpp \
drives.cpp drives.h drive_virtual.cpp drive_local.cpp drive_cache.cpp drive_fat.cpp \
- drive_iso.cpp dev_con.h dos_mscdex.cpp dos_keyboard_layout.cpp \
+ drive_iso.cpp dev_con.h dev_lpt.h dos_mscdex.cpp dos_keyboard_layout.cpp \
cdrom.h cdrom.cpp cdrom_ioctl_win32.cpp cdrom_aspi_win32.cpp cdrom_ioctl_linux.cpp cdrom_image.cpp \
cdrom_ioctl_os2.cpp
diff --git a/src/dos/dev_lpt.h b/src/dos/dev_lpt.h
new file mode 100644
index 0000000..a13e481
--- /dev/null
+++ b/src/dos/dev_lpt.h
@@ -0,0 +1,71 @@
+/
+ * Copyright (C) 2002-2004 The DOSBox Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ /
+
+#include "dos_inc.h"
+#include "inout.h"
+
+class device_LPT : public DOS_Device {
+public:
+ // Creates a LPT device that communicates with the num-th parallel port, i.e. is LPTnum
+ device_LPT(char name, Bit8u num);
+ bool Read(Bit8u * data,Bit16u * size);
+ bool Write(Bit8u * data,Bit16u * size);
+ bool Seek(Bit32u * pos,Bit32u type);
+ bool Close();
+ Bit16u GetInformation(void);
+private:
+ Bit8u num; // This device is LPTnum
+};
+
+bool device_LPT::Read(Bit8u * data,Bit16u * size)
+{
+ size=0;
+ LOG(LOG_DOSMISC,LOG_NORMAL)("LPTDEVICE:Read called");
+ return true;
+}
+
+
+bool device_LPT::Write(Bit8u * data,Bit16u * size)
+{
+ for (Bit16u i=0; i<size; i++)
+ IO_WriteB(real_readw(0x0040, 0x0008 + ((num-1)2)), data[i]);
+
+ return true;
+}
+
+bool device_LPT::Seek(Bit32u * pos,Bit32u type)
+{
+ pos = 0;
+ return true;
+}
+
+bool device_LPT::Close()
+{
+ return false;
+}
+
+Bit16u device_LPT::GetInformation(void)
+{
+ return 0x80A0;
+};
+
+device_LPT::device_LPT(char name, Bit8u num)
+{
+ this->name = name;
+ this->num = num;
+}
diff --git a/src/dos/dos.cpp b/src/dos/dos.cpp
index 5b0539d..b48db9e 100644
--- a/src/dos/dos.cpp
+++ b/src/dos/dos.cpp
@@ -29,6 +29,8 @@
#include "regs.h"
#include "dos_inc.h"
#include "setup.h"
+/// Added ... maybe superfluous
+#include "inout.h"
#include "support.h"
#include "serialport.h"</winspool.h></windows.h></ft2build.h></dosbox.h>
@@ -103,8 +105,13 @@ static Bitu DOS_21Handler(void) {
}
break;
case 0x05: / Write Character to PRINTER /
- E_Exit("DOS:Unhandled call %02X",reg_ah);
+#ifdef C_PRINTER
+ // DOS function only allows printing to LPT1 and returns nothing
+ IO_WriteB(real_readw(0x0040, 0x0008), reg_dl);
break;
+#else
+ E_Exit("DOS:Unhandled call %02X",reg_ah);
+#endif
case 0x06: / Direct Console Output / Input /
switch (reg_dl) {
case 0xFF: / Input /
diff --git a/src/dos/dos_devices.cpp b/src/dos/dos_devices.cpp
index e052a59..41ccc1b 100644
--- a/src/dos/dos_devices.cpp
+++ b/src/dos/dos_devices.cpp
@@ -31,6 +31,9 @@
#include "dev_con.h"
+#ifdef C_PRINTER
+#include "dev_lpt.h"
+#endif
DOS_Device * Devices[DOS_DEVICES];
@@ -142,6 +145,12 @@ Bit8u DOS_FindDevice(char const * name) {
char dot = strrchr(name_start,'.');
if(dot) dot = 0; //no ext checking
+#ifdef C_PRINTER
+ // PRN is a alias for the printer port
+ if (strcmp(name, "PRN") == 0)
+ name = "LPT1";
+#endif
+
/ loop through devices /
for(Bit8u index = 0;index < DOS_DEVICES;index++) {
if (Devices[index]) {
@@ -185,6 +194,11 @@ void DOS_SetupDevices(void) {
newdev2=new device_NUL();
DOS_AddDevice(newdev2);
DOS_Device * newdev3;
+#ifdef C_PRINTER
+ newdev3=new device_LPT("LPT1", 1);
+ DOS_AddDevice(newdev3);
+#else
newdev3=new device_LPT1();
DOS_AddDevice(newdev3);
+#endif
}
diff --git a/src/dos/dos_ioctl.cpp b/src/dos/dos_ioctl.cpp
index 4b1ae04..1c8e033 100644
--- a/src/dos/dos_ioctl.cpp
+++ b/src/dos/dos_ioctl.cpp
@@ -60,6 +60,11 @@ bool DOS_IOCTL(void) {
}
reg_ax=reg_dx; //Destroyed officially
return true;
+ case 0x01: / Set Device Information /
+ // Fake success
+ reg_ax=0x0000;
+ LOG(LOG_IOCTL,LOG_NORMAL)("01:Faked success: Setting device info of handle %d to %02X",handle, reg_dl);
+ return true;
case 0x02: / Read from Device Control Channel /
if (Files[handle]->GetInformation() & 0xc000) {
/ is character device with IOCTL support /
@@ -125,6 +130,10 @@ bool DOS_IOCTL(void) {
}
reg_ax=0x300;
return true;
+ case 0x0A: / Is Device of Handle Remote? /
+ reg_dx=0x8000;
+ LOG(LOG_IOCTL,LOG_NORMAL)("0A:Faked output: device of handle %d is remote",handle);
+ return true;
case 0x0D: / Generic block device request /
{
if (Drives[drive]->isRemovable()) {
diff --git a/src/dosbox.cpp b/src/dosbox.cpp
index 388a9cd..a40a747 100644
--- a/src/dosbox.cpp
+++ b/src/dosbox.cpp
@@ -112,6 +112,10 @@ void SHELL_Init(void);
void INT10_Init(Section*);
+#if C_PRINTER
+void PRINTER_Init(Section* sec);
+#endif
+
static LoopHandler * loop;
bool SDLNetInited;
@@ -662,6 +666,39 @@ void DOSBOX_Init(void) {
#endif
// secprop->AddInitFunction(&CREDITS_Init);
+#if C_PRINTER
+ secprop=control->AddSection_prop("printer",&PRINTER_Init);
+ Pbool = secprop->Add_bool("printer", Property::Changeable::OnlyAtStart, true);
+ Pbool->Set_help("Enable printer emulation.");
+
+ Pint = secprop->Add_int("dpi", Property::Changeable::OnlyAtStart, 360);
+ Pint->Set_help("Resolution of printer (default 360).");
+
+ Pint = secprop->Add_int("width", Property::Changeable::OnlyAtStart, 85);
+ Pint->Set_help("Width of paper in 1/10 inch (default 85 = 8.5'').");
+
+ Pint = secprop->Add_int("height", Property::Changeable::OnlyAtStart, 110);
+ Pint->Set_help("Height of paper in 1/10 inch (default 110 = 11.0'').");
+
+ const char* printerOutputs[] = {
+#ifdef C_LIBPNG
+ "png",
+#endif
+ "ps",
+ "bmp",
+#if defined (WIN32)
+ "printer",
+#endif
+ 0 };
+
+ Pstring = secprop->Add_string("output", Property::Changeable::OnlyAtStart, "ps");
+ Pstring->Set_help("Output method for finished pages.");
+ Pstring->Set_values(printerOutputs);
+
+ Pbool = secprop->Add_bool("multipage", Property::Changeable::OnlyAtStart, false);
+ Pbool->Set_help("Adds all pages to one Postscript file or printer job until ALT-F8 is pressed.");
+#endif
+
//TODO ?
secline=control->AddSection_line("autoexec",&AUTOEXEC_Init);
MSG_Add("AUTOEXEC_CONFIGFILE_HELP",
diff --git a/src/hardware/Makefile.am b/src/hardware/Makefile.am
index 7a9f7bf..30e31ac 100644
--- a/src/hardware/Makefile.am
+++ b/src/hardware/Makefile.am
@@ -10,6 +10,5 @@ libhardware_a_SOURCES = adlib.cpp dma.cpp gameblaster.cpp hardware.cpp iohandler
memory.cpp mixer.cpp pcspeaker.cpp pic.cpp sblaster.cpp tandy_sound.cpp timer.cpp \
vga.cpp vga_attr.cpp vga_crtc.cpp vga_dac.cpp vga_draw.cpp vga_gfx.cpp vga_other.cpp \
vga_memory.cpp vga_misc.cpp vga_seq.cpp vga_xga.cpp vga_s3.cpp vga_tseng.cpp vga_paradise.cpp \
- cmos.cpp disney.cpp gus.cpp mpu401.cpp ipx.cpp ipxserver.cpp
-
+ cmos.cpp disney.cpp gus.cpp mpu401.cpp ipx.cpp ipxserver.cpp printer.cpp
diff --git a/src/hardware/printer.cpp b/src/hardware/printer.cpp
new file mode 100644
index 0000000..5e6628b
--- /dev/null
+++ b/src/hardware/printer.cpp
@@ -0,0 +1,2206 @@
+/
+ * Copyright (C) 2002-2004 The DOSBox Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ /
+
+#include "printer.h"
+
+#if C_PRINTER
+
+#include <math.h>
+#include "inout.h"
+#include "keyboard.h"
+#include "mapper.h"
+#include "mem.h"
+#include "support.h"
+#include "setup.h"
+
+#ifdef C_LIBPNG
+#include <png.h>
+#endif
+
+#define LPTPORT 0x378
+
+static CPrinter defaultPrinter = NULL;
+
+#define PARAM16(I) (params[I+1]256+params[I])
+#define PIXX ((Bitu)floor(curXdpi+0.5))
+#define PIXY ((Bitu)floor(curYdpi+0.5))
+
+static Bit16u confdpi, confwidth, confheight;
+static char confoutputDevice[50];
+static bool confmultipageOutput;
+
+// Various ASCII codepage to unicode maps
+
+static const Bit16u cp437Map[256] = {
+0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f,
+0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f,
+0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f,
+0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f,
+0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f,
+0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f,
+0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f,
+0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f,
+0x00c7,0x00fc,0x00e9,0x00e2,0x00e4,0x00e0,0x00e5,0x00e7,0x00ea,0x00eb,0x00e8,0x00ef,0x00ee,0x00ec,0x00c4,0x00c5,
+0x00c9,0x00e6,0x00c6,0x00f4,0x00f6,0x00f2,0x00fb,0x00f9,0x00ff,0x00d6,0x00dc,0x00a2,0x00a3,0x00a5,0x20a7,0x0192,
+0x00e1,0x00ed,0x00f3,0x00fa,0x00f1,0x00d1,0x00aa,0x00ba,0x00bf,0x2310,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00bb,
+0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556,0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510,
+0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567,
+0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b,0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580,
+0x03b1,0x00df,0x0393,0x03c0,0x03a3,0x03c3,0x00b5,0x03c4,0x03a6,0x0398,0x03a9,0x03b4,0x221e,0x03c6,0x03b5,0x2229,
+0x2261,0x00b1,0x2265,0x2264,0x2320,0x2321,0x00f7,0x2248,0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x00a0
+};
+
+static const Bit16u cp737Map[256] = {
+0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f,
+0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f,
+0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f,
+0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f,
+0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f,
+0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f,
+0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f,
+0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f,
+0x0391,0x0392,0x0393,0x0394,0x0395,0x0396,0x0397,0x0398,0x0399,0x039a,0x039b,0x039c,0x039d,0x039e,0x039f,0x03a0,
+0x03a1,0x03a3,0x03a4,0x03a5,0x03a6,0x03a7,0x03a8,0x03a9,0x03b1,0x03b2,0x03b3,0x03b4,0x03b5,0x03b6,0x03b7,0x03b8,
+0x03b9,0x03ba,0x03bb,0x03bc,0x03bd,0x03be,0x03bf,0x03c0,0x03c1,0x03c3,0x03c2,0x03c4,0x03c5,0x03c6,0x03c7,0x03c8,
+0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556,0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510,
+0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567,
+0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b,0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580,
+0x03c9,0x03ac,0x03ad,0x03ae,0x03ca,0x03af,0x03cc,0x03cd,0x03cb,0x03ce,0x0386,0x0388,0x0389,0x038a,0x038c,0x038e,
+0x038f,0x00b1,0x2265,0x2264,0x03aa,0x03ab,0x00f7,0x2248,0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x00a0
+};
+
+static const Bit16u cp775Map[256] = {
+0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f,
+0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f,
+0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f,
+0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f,
+0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f,
+0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f,
+0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f,
+0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f,
+0x0106,0x00fc,0x00e9,0x0101,0x00e4,0x0123,0x00e5,0x0107,0x0142,0x0113,0x0156,0x0157,0x012b,0x0179,0x00c4,0x00c5,
+0x00c9,0x00e6,0x00c6,0x014d,0x00f6,0x0122,0x00a2,0x015a,0x015b,0x00d6,0x00dc,0x00f8,0x00a3,0x00d8,0x00d7,0x00a4,
+0x0100,0x012a,0x00f3,0x017b,0x017c,0x017a,0x201d,0x00a6,0x00a9,0x00ae,0x00ac,0x00bd,0x00bc,0x0141,0x00ab,0x00bb,
+0x2591,0x2592,0x2593,0x2502,0x2524,0x0104,0x010c,0x0118,0x0116,0x2563,0x2551,0x2557,0x255d,0x012e,0x0160,0x2510,
+0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x0172,0x016a,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x017d,
+0x0105,0x010d,0x0119,0x0117,0x012f,0x0161,0x0173,0x016b,0x017e,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580,
+0x00d3,0x00df,0x014c,0x0143,0x00f5,0x00d5,0x00b5,0x0144,0x0136,0x0137,0x013b,0x013c,0x0146,0x0112,0x0145,0x2019,
+0x00ad,0x00b1,0x201c,0x00be,0x00b6,0x00a7,0x00f7,0x201e,0x00b0,0x2219,0x00b7,0x00b9,0x00b3,0x00b2,0x25a0,0x00a0
+};
+
+static const Bit16u cp850Map[256] = {
+0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f,
+0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f,
+0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f,
+0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f,
+0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f,
+0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f,
+0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f,
+0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f,
+0x00c7,0x00fc,0x00e9,0x00e2,0x00e4,0x00e0,0x00e5,0x00e7,0x00ea,0x00eb,0x00e8,0x00ef,0x00ee,0x00ec,0x00c4,0x00c5,
+0x00c9,0x00e6,0x00c6,0x00f4,0x00f6,0x00f2,0x00fb,0x00f9,0x00ff,0x00d6,0x00dc,0x00f8,0x00a3,0x00d8,0x00d7,0x0192,
+0x00e1,0x00ed,0x00f3,0x00fa,0x00f1,0x00d1,0x00aa,0x00ba,0x00bf,0x00ae,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00bb,
+0x2591,0x2592,0x2593,0x2502,0x2524,0x00c1,0x00c2,0x00c0,0x00a9,0x2563,0x2551,0x2557,0x255d,0x00a2,0x00a5,0x2510,
+0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x00e3,0x00c3,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x00a4,
+0x00f0,0x00d0,0x00ca,0x00cb,0x00c8,0x0131,0x00cd,0x00ce,0x00cf,0x2518,0x250c,0x2588,0x2584,0x00a6,0x00cc,0x2580,
+0x00d3,0x00df,0x00d4,0x00d2,0x00f5,0x00d5,0x00b5,0x00fe,0x00de,0x00da,0x00db,0x00d9,0x00fd,0x00dd,0x00af,0x00b4,
+0x00ad,0x00b1,0x2017,0x00be,0x00b6,0x00a7,0x00f7,0x00b8,0x00b0,0x00a8,0x00b7,0x00b9,0x00b3,0x00b2,0x25a0,0x00a0
+};
+
+static const Bit16u cp852Map[256] = {
+0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f,
+0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f,
+0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f,
+0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f,
+0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f,
+0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f,
+0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f,
+0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f,
+0x00c7,0x00fc,0x00e9,0x00e2,0x00e4,0x016f,0x0107,0x00e7,0x0142,0x00eb,0x0150,0x0151,0x00ee,0x0179,0x00c4,0x0106,
+0x00c9,0x0139,0x013a,0x00f4,0x00f6,0x013d,0x013e,0x015a,0x015b,0x00d6,0x00dc,0x0164,0x0165,0x0141,0x00d7,0x010d,
+0x00e1,0x00ed,0x00f3,0x00fa,0x0104,0x0105,0x017d,0x017e,0x0118,0x0119,0x00ac,0x017a,0x010c,0x015f,0x00ab,0x00bb,
+0x2591,0x2592,0x2593,0x2502,0x2524,0x00c1,0x00c2,0x011a,0x015e,0x2563,0x2551,0x2557,0x255d,0x017b,0x017c,0x2510,
+0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x0102,0x0103,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x00a4,
+0x0111,0x0110,0x010e,0x00cb,0x010f,0x0147,0x00cd,0x00ce,0x011b,0x2518,0x250c,0x2588,0x2584,0x0162,0x016e,0x2580,
+0x00d3,0x00df,0x00d4,0x0143,0x0144,0x0148,0x0160,0x0161,0x0154,0x00da,0x0155,0x0170,0x00fd,0x00dd,0x0163,0x00b4,
+0x00ad,0x02dd,0x02db,0x02c7,0x02d8,0x00a7,0x00f7,0x00b8,0x00b0,0x00a8,0x02d9,0x0171,0x0158,0x0159,0x25a0,0x00a0
+};
+
+static const Bit16u cp855Map[256] = {
+0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f,
+0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f,
+0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f,
+0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f,
+0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f,
+0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f,
+0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f,
+0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f,
+0x0452,0x0402,0x0453,0x0403,0x0451,0x0401,0x0454,0x0404,0x0455,0x0405,0x0456,0x0406,0x0457,0x0407,0x0458,0x0408,
+0x0459,0x0409,0x045a,0x040a,0x045b,0x040b,0x045c,0x040c,0x045e,0x040e,0x045f,0x040f,0x044e,0x042e,0x044a,0x042a,
+0x0430,0x0410,0x0431,0x0411,0x0446,0x0426,0x0434,0x0414,0x0435,0x0415,0x0444,0x0424,0x0433,0x0413,0x00ab,0x00bb,
+0x2591,0x2592,0x2593,0x2502,0x2524,0x0445,0x0425,0x0438,0x0418,0x2563,0x2551,0x2557,0x255d,0x0439,0x0419,0x2510,
+0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x043a,0x041a,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x00a4,
+0x043b,0x041b,0x043c,0x041c,0x043d,0x041d,0x043e,0x041e,0x043f,0x2518,0x250c,0x2588,0x2584,0x041f,0x044f,0x2580,
+0x042f,0x0440,0x0420,0x0441,0x0421,0x0442,0x0422,0x0443,0x0423,0x0436,0x0416,0x0432,0x0412,0x044c,0x042c,0x2116,
+0x00ad,0x044b,0x042b,0x0437,0x0417,0x0448,0x0428,0x044d,0x042d,0x0449,0x0429,0x0447,0x0427,0x00a7,0x25a0,0x00a0
+};
+
+static const Bit16u cp857Map[256] = {
+0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f,
+0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f,
+0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f,
+0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f,
+0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f,
+0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f,
+0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f,
+0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f,
+0x00c7,0x00fc,0x00e9,0x00e2,0x00e4,0x00e0,0x00e5,0x00e7,0x00ea,0x00eb,0x00e8,0x00ef,0x00ee,0x0131,0x00c4,0x00c5,
+0x00c9,0x00e6,0x00c6,0x00f4,0x00f6,0x00f2,0x00fb,0x00f9,0x0130,0x00d6,0x00dc,0x00f8,0x00a3,0x00d8,0x015e,0x015f,
+0x00e1,0x00ed,0x00f3,0x00fa,0x00f1,0x00d1,0x011e,0x011f,0x00bf,0x00ae,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00bb,
+0x2591,0x2592,0x2593,0x2502,0x2524,0x00c1,0x00c2,0x00c0,0x00a9,0x2563,0x2551,0x2557,0x255d,0x00a2,0x00a5,0x2510,
+0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x00e3,0x00c3,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x00a4,
+0x00ba,0x00aa,0x00ca,0x00cb,0x00c8,0x0000,0x00cd,0x00ce,0x00cf,0x2518,0x250c,0x2588,0x2584,0x00a6,0x00cc,0x2580,
+0x00d3,0x00df,0x00d4,0x00d2,0x00f5,0x00d5,0x00b5,0x0000,0x00d7,0x00da,0x00db,0x00d9,0x00ec,0x00ff,0x00af,0x00b4,
+0x00ad,0x00b1,0x0000,0x00be,0x00b6,0x00a7,0x00f7,0x00b8,0x00b0,0x00a8,0x00b7,0x00b9,0x00b3,0x00b2,0x25a0,0x00a0
+};
+
+static const Bit16u cp860Map[256] = {
+0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f,
+0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f,
+0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f,
+0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f,
+0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f,
+0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f,
+0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f,
+0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f,
+0x00c7,0x00fc,0x00e9,0x00e2,0x00e3,0x00e0,0x00c1,0x00e7,0x00ea,0x00ca,0x00e8,0x00cd,0x00d4,0x00ec,0x00c3,0x00c2,
+0x00c9,0x00c0,0x00c8,0x00f4,0x00f5,0x00f2,0x00da,0x00f9,0x00cc,0x00d5,0x00dc,0x00a2,0x00a3,0x00d9,0x20a7,0x00d3,
+0x00e1,0x00ed,0x00f3,0x00fa,0x00f1,0x00d1,0x00aa,0x00ba,0x00bf,0x00d2,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00bb,
+0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556,0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510,
+0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567,
+0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b,0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580,
+0x03b1,0x00df,0x0393,0x03c0,0x03a3,0x03c3,0x00b5,0x03c4,0x03a6,0x0398,0x03a9,0x03b4,0x221e,0x03c6,0x03b5,0x2229,
+0x2261,0x00b1,0x2265,0x2264,0x2320,0x2321,0x00f7,0x2248,0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x00a0
+};
+
+static const Bit16u cp861Map[256] = {
+0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f,
+0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f,
+0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f,
+0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f,
+0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f,
+0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f,
+0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f,
+0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f,
+0x00c7,0x00fc,0x00e9,0x00e2,0x00e4,0x00e0,0x00e5,0x00e7,0x00ea,0x00eb,0x00e8,0x00d0,0x00f0,0x00de,0x00c4,0x00c5,
+0x00c9,0x00e6,0x00c6,0x00f4,0x00f6,0x00fe,0x00fb,0x00dd,0x00fd,0x00d6,0x00dc,0x00f8,0x00a3,0x00d8,0x20a7,0x0192,
+0x00e1,0x00ed,0x00f3,0x00fa,0x00c1,0x00cd,0x00d3,0x00da,0x00bf,0x2310,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00bb,
+0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556,0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510,
+0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567,
+0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b,0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580,
+0x03b1,0x00df,0x0393,0x03c0,0x03a3,0x03c3,0x00b5,0x03c4,0x03a6,0x0398,0x03a9,0x03b4,0x221e,0x03c6,0x03b5,0x2229,
+0x2261,0x00b1,0x2265,0x2264,0x2320,0x2321,0x00f7,0x2248,0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x00a0
+};
+
+static const Bit16u cp862Map[256] = {
+0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f,
+0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f,
+0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f,
+0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f,
+0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f,
+0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f,
+0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f,
+0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f,
+0x05d0,0x05d1,0x05d2,0x05d3,0x05d4,0x05d5,0x05d6,0x05d7,0x05d8,0x05d9,0x05da,0x05db,0x05dc,0x05dd,0x05de,0x05df,
+0x05e0,0x05e1,0x05e2,0x05e3,0x05e4,0x05e5,0x05e6,0x05e7,0x05e8,0x05e9,0x05ea,0x00a2,0x00a3,0x00a5,0x20a7,0x0192,
+0x00e1,0x00ed,0x00f3,0x00fa,0x00f1,0x00d1,0x00aa,0x00ba,0x00bf,0x2310,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00bb,
+0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556,0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510,
+0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567,
+0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b,0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580,
+0x03b1,0x00df,0x0393,0x03c0,0x03a3,0x03c3,0x00b5,0x03c4,0x03a6,0x0398,0x03a9,0x03b4,0x221e,0x03c6,0x03b5,0x2229,
+0x2261,0x00b1,0x2265,0x2264,0x2320,0x2321,0x00f7,0x2248,0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x00a0
+};
+
+static const Bit16u cp863Map[256] = {
+0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f,
+0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f,
+0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f,
+0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f,
+0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f,
+0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f,
+0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f,
+0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f,
+0x00c7,0x00fc,0x00e9,0x00e2,0x00c2,0x00e0,0x00b6,0x00e7,0x00ea,0x00eb,0x00e8,0x00ef,0x00ee,0x2017,0x00c0,0x00a7,
+0x00c9,0x00c8,0x00ca,0x00f4,0x00cb,0x00cf,0x00fb,0x00f9,0x00a4,0x00d4,0x00dc,0x00a2,0x00a3,0x00d9,0x00db,0x0192,
+0x00a6,0x00b4,0x00f3,0x00fa,0x00a8,0x00b8,0x00b3,0x00af,0x00ce,0x2310,0x00ac,0x00bd,0x00bc,0x00be,0x00ab,0x00bb,
+0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556,0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510,
+0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567,
+0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b,0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580,
+0x03b1,0x00df,0x0393,0x03c0,0x03a3,0x03c3,0x00b5,0x03c4,0x03a6,0x0398,0x03a9,0x03b4,0x221e,0x03c6,0x03b5,0x2229,
+0x2261,0x00b1,0x2265,0x2264,0x2320,0x2321,0x00f7,0x2248,0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x00a0
+};
+
+static const Bit16u cp864Map[256] = {
+0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f,
+0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f,
+0x0020,0x0021,0x0022,0x0023,0x0024,0x066a,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f,
+0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f,
+0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f,
+0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f,
+0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f,
+0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f,
+0x00b0,0x00b7,0x2219,0x221a,0x2592,0x2500,0x2502,0x253c,0x2524,0x252c,0x251c,0x2534,0x2510,0x250c,0x2514,0x2518,
+0x03b2,0x221e,0x03c6,0x00b1,0x00bd,0x00bc,0x2248,0x00ab,0x00bb,0xfef7,0xfef8,0x0000,0x0000,0xfefb,0xfefc,0x0000,
+0x00a0,0x00ad,0xfe82,0x00a3,0x00a4,0xfe84,0x0000,0x0000,0xfe8e,0xfe8f,0xfe95,0xfe99,0x060c,0xfe9d,0xfea1,0xfea5,
+0x0660,0x0661,0x0662,0x0663,0x0664,0x0665,0x0666,0x0667,0x0668,0x0669,0xfed1,0x061b,0xfeb1,0xfeb5,0xfeb9,0x061f,
+0x00a2,0xfe80,0xfe81,0xfe83,0xfe85,0xfeca,0xfe8b,0xfe8d,0xfe91,0xfe93,0xfe97,0xfe9b,0xfe9f,0xfea3,0xfea7,0xfea9,
+0xfeab,0xfead,0xfeaf,0xfeb3,0xfeb7,0xfebb,0xfebf,0xfec1,0xfec5,0xfecb,0xfecf,0x00a6,0x00ac,0x00f7,0x00d7,0xfec9,
+0x0640,0xfed3,0xfed7,0xfedb,0xfedf,0xfee3,0xfee7,0xfeeb,0xfeed,0xfeef,0xfef3,0xfebd,0xfecc,0xfece,0xfecd,0xfee1,
+0xfe7d,0x0651,0xfee5,0xfee9,0xfeec,0xfef0,0xfef2,0xfed0,0xfed5,0xfef5,0xfef6,0xfedd,0xfed9,0xfef1,0x25a0,
+};
+
+static const Bit16u cp865Map[256] = {
+0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f,
+0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f,
+0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f,
+0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f,
+0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f,
+0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f,
+0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f,
+0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f,
+0x00c7,0x00fc,0x00e9,0x00e2,0x00e4,0x00e0,0x00e5,0x00e7,0x00ea,0x00eb,0x00e8,0x00ef,0x00ee,0x00ec,0x00c4,0x00c5,
+0x00c9,0x00e6,0x00c6,0x00f4,0x00f6,0x00f2,0x00fb,0x00f9,0x00ff,0x00d6,0x00dc,0x00f8,0x00a3,0x00d8,0x20a7,0x0192,
+0x00e1,0x00ed,0x00f3,0x00fa,0x00f1,0x00d1,0x00aa,0x00ba,0x00bf,0x2310,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00a4,
+0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556,0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510,
+0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567,
+0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b,0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580,
+0x03b1,0x00df,0x0393,0x03c0,0x03a3,0x03c3,0x00b5,0x03c4,0x03a6,0x0398,0x03a9,0x03b4,0x221e,0x03c6,0x03b5,0x2229,
+0x2261,0x00b1,0x2265,0x2264,0x2320,0x2321,0x00f7,0x2248,0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x00a0
+};
+
+static const Bit16u cp866Map[256] = {
+0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f,
+0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f,
+0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f,
+0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f,
+0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f,
+0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f,
+0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f,
+0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f,
+0x0410,0x0411,0x0412,0x0413,0x0414,0x0415,0x0416,0x0417,0x0418,0x0419,0x041a,0x041b,0x041c,0x041d,0x041e,0x041f,
+0x0420,0x0421,0x0422,0x0423,0x0424,0x0425,0x0426,0x0427,0x0428,0x0429,0x042a,0x042b,0x042c,0x042d,0x042e,0x042f,
+0x0430,0x0431,0x0432,0x0433,0x0434,0x0435,0x0436,0x0437,0x0438,0x0439,0x043a,0x043b,0x043c,0x043d,0x043e,0x043f,
+0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556,0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510,
+0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567,
+0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b,0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580,
+0x0440,0x0441,0x0442,0x0443,0x0444,0x0445,0x0446,0x0447,0x0448,0x0449,0x044a,0x044b,0x044c,0x044d,0x044e,0x044f,
+0x0401,0x0451,0x0404,0x0454,0x0407,0x0457,0x040e,0x045e,0x00b0,0x2219,0x00b7,0x221a,0x2116,0x00a4,0x25a0,0x00a0
+};
+
+static const Bit16u codepages[15] = {0, 437, 932, 850, 851, 853, 855, 860, 863, 865, 852, 857, 862, 864, 866};
+
+// TODO: Implement all international charsets
+static const Bit16u intCharSets[15][12] =
+{
+ {0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e}, // USA
+ {0x0023, 0x0024, 0x00e0, 0x00ba, 0x00e7, 0x00a7, 0x005e, 0x0060, 0x00e9, 0x00f9, 0x00e8, 0x00a8}, // France
+ {0x0023, 0x0024, 0x00a7, 0x00c4, 0x00d6, 0x00dc, 0x005e, 0x0060, 0x00e4, 0x00f6, 0x00fc, 0x00df}, // Germany
+ {0x00a3, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e}, // UK
+ {0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e},
+ {0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e},
+ {0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e},
+ {0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e},
+ {0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e},
+ {0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e},
+ {0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e},
+ {0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e},
+ {0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e},
+ {0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e},
+ {0x0023, 0x0024, 0x00a7, 0x00c4, 0x0027, 0x0022, 0x00b6, 0x0060, 0x00a9, 0x00ae, 0x2020, 0x2122} // Legal
+};
+
+CPrinter::CPrinter(Bit16u dpi, Bit16u width, Bit16u height, char output, bool multipageOutput)
+{
+ if (FT_Init_FreeType(&FTlib))
+ {
+ LOG(LOG_MISC,LOG_ERROR)("PRINTER: Unable to init Freetype2. Printing disabled");
+ page = NULL;
+ }
+ else
+ {
+ this->dpi = dpi;
+ this->output = output;
+ this->multipageOutput = multipageOutput;
+
+ defaultPageWidth = (Real64)width/(Real64)10;
+ defaultPageHeight = (Real64)height/(Real64)10;
+
+ // Create page
+ page = SDL_CreateRGBSurface(
+ SDL_SWSURFACE,
+ (Bitu)(defaultPageWidthdpi),
+ (Bitu)(defaultPageHeightdpi),
+ 8,
+ 0,
+ 0,
+ 0,
+ 0);
+
+ // Set a grey palette
+ SDL_Palette palette = page->format->palette;
+
+ for (Bitu i=0; i<255; i++)
+ palette->colors[i].r = palette->colors[i].g = palette->colors[i].b = 255-i;
+
+ curFont = NULL;
+ charRead = false;
+ autoFeed = false;
+ outputHandle = NULL;
+
+ resetPrinter();
+
+ if (strcasecmp(output, "printer") == 0)
+ {
+#if defined (WIN32)
+ // Show Print dialog to obtain a printer device context
+
+ PRINTDLG pd;
+ pd.lStructSize = sizeof(PRINTDLG);
+ pd.hDevMode = (HANDLE) NULL;
+ pd.hDevNames = (HANDLE) NULL;
+ pd.Flags = PD_RETURNDC;
+ pd.hwndOwner = NULL;
+ pd.hDC = (HDC) NULL;
+ pd.nFromPage = 1;
+ pd.nToPage = 1;
+ pd.nMinPage = 0;
+ pd.nMaxPage = 0;
+ pd.nCopies = 1;
+ pd.hInstance = NULL;
+ pd.lCustData = 0L;
+ pd.lpfnPrintHook = (LPPRINTHOOKPROC) NULL;
+ pd.lpfnSetupHook = (LPSETUPHOOKPROC) NULL;
+ pd.lpPrintTemplateName = (LPSTR) NULL;
+ pd.lpSetupTemplateName = (LPSTR) NULL;
+ pd.hPrintTemplate = (HANDLE) NULL;
+ pd.hSetupTemplate = (HANDLE) NULL;
+ PrintDlg(&pd);
+ printerDC = pd.hDC;
+#endif
+ }
+
+ LOG(LOG_MISC,LOG_NORMAL)("PRINTER: Enabled");
+ }
+};
+
+void CPrinter::resetPrinterHard()
+{
+ charRead = false;
+ resetPrinter();
+}
+
+void CPrinter::resetPrinter()
+{
+ curX = curY = 0.0;
+ ESCSeen = false;
+ ESCCmd = 0;
+ numParam = neededParam = 0;
+ topMargin = 0.0;
+ leftMargin = 0.0;
+ rightMargin = pageWidth = defaultPageWidth;
+ bottomMargin = pageHeight = defaultPageHeight;
+ lineSpacing = (Real64)1/6;
+ cpi = 10.0;
+ curCharTable = 1;
+ style = 0;
+ extraIntraSpace = 0.0;
+ printUpperContr = true;
+ bitGraph.remBytes = 0;
+ densk = 0;
+ densl = 1;
+ densy = 2;
+ densz = 3;
+ charTables[0] = 0; // Italics
+ charTables[1] = charTables[2] = charTables[3] = 437;
+ definedUnit = -1;
+ multipoint = false;
+ multiPointSize = 0.0;
+ multicpi = 0.0;
+ hmi = -1.0;
+ msb = 255;
+ numPrintAsChar = 0;
+ LQtypeFace = roman;
+
+ selectCodepage(charTables[curCharTable]);
+
+ updateFont();
+
+ newPage(false);
+
+ // Default tabs => Each eight characters
+ for (Bitu i=0;i<32;i++)
+ horiztabs[i] = i8(1/(Real64)cpi);
+ numHorizTabs = 32;
+
+ numVertTabs = 255;
+}
+
+
+CPrinter::~CPrinter(void)
+{
+ finishMultipage();
+ if (page != NULL)
+ {
+ SDL_FreeSurface(page);
+ page = NULL;
+ FT_Done_FreeType(FTlib);
+ }
+#if defined (WIN32)
+ DeleteDC(printerDC);
+#endif
+};
+
+void CPrinter::selectCodepage(Bit16u cp)
+{
+ Bit16u mapToUse = NULL;
+
+ switch(cp)
+ {
+ case 0: // Italics, use cp437
+ case 437:
+ mapToUse = (Bit16u)&cp437Map;
+ break;
+ case 737:
+ mapToUse = (Bit16u)&cp737Map;
+ break;
+ case 775:
+ mapToUse = (Bit16u)&cp775Map;
+ break;
+ case 850:
+ mapToUse = (Bit16u)&cp850Map;
+ break;
+ case 852:
+ mapToUse = (Bit16u)&cp852Map;
+ break;
+ case 855:
+ mapToUse = (Bit16u)&cp855Map;
+ break;
+ case 857:
+ mapToUse = (Bit16u)&cp857Map;
+ break;
+ case 860:
+ mapToUse = (Bit16u)&cp860Map;
+ break;
+ case 861:
+ mapToUse = (Bit16u)&cp861Map;
+ break;
+ case 863:
+ mapToUse = (Bit16u)&cp863Map;
+ break;
+ case 864:
+ mapToUse = (Bit16u)&cp864Map;
+ break;
+ case 865:
+ mapToUse = (Bit16u)&cp865Map;
+ break;
+ case 866:
+ mapToUse = (Bit16u)&cp866Map;
+ break;
+ default:
+ LOG(LOG_MISC,LOG_WARN)("Unsupported codepage %i. Using CP437 instead.", cp);
+ mapToUse = (Bit16u)&cp437Map;
+ }
+
+ for (int i=0; i<256; i++)
+ curMap[i] = mapToUse[i];
+}
+
+void CPrinter::updateFont()
+{
+ if (curFont != NULL)
+ FT_Done_Face(curFont);
+
+ char fontName;
+
+ switch (LQtypeFace)
+ {
+ case roman:
+ fontName = "roman.ttf";
+ break;
+ case sansserif:
+ fontName = "sansserif.ttf";
+ break;
+ case courier:
+ fontName = "courier.ttf";
+ break;
+ case script:
+ fontName = "script.ttf";
+ break;
+ case ocra:
+ case ocrb:
+ fontName = "ocra.ttf";
+ break;
+ default:
+ fontName = "roman.ttf";
+ }
+
+ if (FT_New_Face(FTlib, fontName, 0, &curFont))
+ {
+ LOG(LOG_MISC,LOG_ERROR)("Unable to load font %s", fontName);
+ curFont = NULL;
+ }
+
+ Real64 horizPoints = 10.5;
+ Real64 vertPoints = 10.5;
+
+ if (!multipoint)
+ {
+ actcpi = cpi;
+
+ if (cpi != 10 && !(style & STYLE_CONDENSED))
+ {
+ horizPoints = (Real64)10/(Real64)cpi;
+ vertPoints = (Real64)10/(Real64)cpi;
+ }
+
+ if (!style & STYLE_PROP)
+ {
+ if (cpi == 10 && (style & STYLE_CONDENSED))
+ {
+ actcpi = 17.14;
+ horizPoints = (Real64)10/(Real64)17.14;
+ vertPoints = (Real64)10/(Real64)17.14;
+ }
+
+ if (cpi == 12 && (style & STYLE_CONDENSED))
+ {
+ actcpi = 20.0;
+ horizPoints = (Real64)10/(Real64)20.0;
+ vertPoints = (Real64)10/(Real64)20.0;
+ }
+ }
+
+ if (style & (STYLE_PROP | STYLE_CONDENSED))
+ {
+ horizPoints /= (Real64)2.0;
+ vertPoints /= (Real64)2.0;
+ }
+
+ if ((style & STYLE_DOUBLEWIDTH) || (style & STYLE_DOUBLEWIDTHONELINE))
+ {
+ actcpi /= 2;
+ horizPoints = (Real64)2.0;
+ }
+
+ if (style & STYLE_DOUBLEHEIGHT)
+ vertPoints = (Real64)2.0;
+ }
+ else
+ {
+ actcpi = multicpi;
+ horizPoints = vertPoints = multiPointSize;
+ }
+
+ if ((style & STYLE_SUPERSCRIPT) || (style & STYLE_SUBSCRIPT))
+ {
+ horizPoints = (Real64)2/(Real64)3;
+ vertPoints = (Real64)2/(Real64)3;
+ actcpi /= (Real64)2/(Real64)3;
+ }
+
+
+ FT_Set_Char_Size(curFont, (Bit16u)horizPoints64, (Bit16u)vertPoints64, dpi, dpi);
+
+ if (style & STYLE_ITALICS || charTables[curCharTable] == 0)
+ {
+ FT_Matrix matrix;
+ matrix.xx = 0x10000L;
+ matrix.xy = (FT_Fixed)(0.20 * 0x10000L);
+ matrix.yx = 0;
+ matrix.yy = 0x10000L;
+ FT_Set_Transform(curFont, &matrix, 0);
+ }
+}
+
+bool CPrinter::processCommandChar(Bit8u ch)
+{
+ if (ESCSeen)
+ {
+ ESCCmd = ch;
+ ESCSeen = false;
+ numParam = 0;
+
+ switch (ESCCmd)
+ {
+ case 0x02: // Undocumented
+ case 0x0e: // Select double-width printing (one line) (ESC SO)
+ case 0x0f: // Select condensed printing (ESC SI)
+ case 0x23: // Cancel MSB control (ESC #)
+ case 0x30: // Select 1/8-inch line spacing (ESC 0)
+ case 0x32: // Select 1/6-inch line spacing (ESC 2)
+ case 0x34: // Select italic font (ESC 4)
+ case 0x35: // Cancel italic font (ESC 5)
+ case 0x36: // Enable printing of upper control codes (ESC 6)
+ case 0x37: // Enable upper control codes (ESC 7)
+ case 0x3c: // Unidirectional mode (one line) (ESC <)
+ case 0x3d: // Set MSB to 0 (ESC =)
+ case 0x3e: // Set MSB to 1 (ESC >)
+ case 0x40: // Initialize printer (ESC @)
+ case 0x45: // Select bold font (ESC E)
+ case 0x46: // Cancel bold font (ESC F)
+ case 0x47: // Select double-strike printing (ESC G)
+ case 0x48: // Cancel double-strike printing (ESC H)
+ case 0x4d: // Select 10.5-point, 12-cpi (ESC M)
+ case 0x4f: // Cancel bottom margin
+ case 0x50: // Select 10.5-point, 10-cpi (ESC P)
+ case 0x54: // Cancel superscript/subscript printing (ESC T)
+ case 0x67: // Select 10.5-point, 15-cpi (ESC g)
+ case 0x73: // Select low-speed mode (ESC s)
+ neededParam = 0;
+ break;
+ case 0x19: // Control paper loading/ejecting (ESC EM)
+ case 0x20: // Set intercharacter space (ESC SP)
+ case 0x21: // Master select (ESC !)
+ case 0x2b: // Set n/360-inch line spacing (ESC +)
+ case 0x2d: // Turn underline on/off (ESC -)
+ case 0x2f: // Select vertical tab channel (ESC /)
+ case 0x33: // Set n/180-inch line spacing (ESC 3)
+ case 0x41: // Set n/60-inch line spacing
+ case 0x43: // Set page length in lines (ESC C)
+ case 0x4a: // Advance print position vertically (ESC J n)
+ case 0x4e: // Set bottom margin (ESC N)
+ case 0x51: // Set right margin (ESC Q)
+ case 0x52: // Select an international character set (ESC R)
+ case 0x53: // Select superscript/subscript printing (ESC S)
+ case 0x55: // Turn unidirectional mode on/off (ESC U)
+ case 0x57: // Turn double-width printing on/off (ESC W)
+ case 0x61: // Select justification (ESC a)
+ case 0x6b: // Select typeface (ESC k)
+ case 0x6c: // Set left margin (ESC 1)
+ case 0x70: // Turn proportional mode on/off (ESC p)
+ case 0x72: // Select printing color (ESC r)
+ case 0x74: // Select character table (ESC t)
+ case 0x77: // Turn double-height printing on/off (ESC w)
+ case 0x78: // Select LQ or draft (ESC x)
+ neededParam = 1;
+ break;
+ case 0x24: // Set absolute horizontal print position (ESC $)
+ case 0x3f: // Reassign bit-image mode (ESC ?)
+ case 0x4b: // Select 60-dpi graphics (ESC K)
+ case 0x4c: // Select 120-dpi graphics (ESC L)
+ case 0x59: // Select 120-dpi, double-speed graphics (ESC Y)
+ case 0x5a: // Select 240-dpi graphics (ESC Z)
+ case 0x5c: // Set relative horizontal print position (ESC )
+ case 0x63: // Set horizontal motion index (HMI) (ESC c)
+ neededParam = 2;
+ break;
+ case 0x2a: // Select bit image (ESC )
+ case 0x58: // Select font by pitch and point (ESC X)
+ neededParam = 3;
+ break;
+ case 0x62: // Set vertical tabs in VFU channels (ESC b)
+ case 0x42: // Set vertical tabs (ESC B)
+ numVertTabs = 0;
+ return true;
+ case 0x44: // Set horizontal tabs (ESC D)
+ numHorizTabs = 0;
+ return true;
+ case 0x25: // Select user-defined set (ESC %)
+ case 0x26: // Define user-defined characters (ESC &)
+ case 0x3a: // Copy ROM to RAM (ESC :)
+ LOG(LOG_MISC,LOG_ERROR)("User-defined characters not supported!");
+ return true;
+ case 0x28: // Two bytes sequence
+ return true;
+ default:
+ LOG(LOG_MISC,LOG_ERROR)("PRINTER: Unknown command ESC %c (%02X). Unable to skip parameters.", ESCCmd, ESCCmd);
+ neededParam = 0;
+ ESCCmd = 0;
+ return true;
+ }
+
+ if (neededParam > 0)
+ return true;
+ }
+
+ // Two bytes sequence
+ if (ESCCmd == 0x28)
+ {
+ ESCCmd = 0x200 + ch;
+
+ switch (ESCCmd)
+ {
+ case 0x242: // Bar code setup and print (ESC (B)
+ case 0x25e: // Print data as characters (ESC (^)
+ neededParam = 2;
+ break;
+ case 0x255: // Set unit (ESC (U)
+ neededParam = 3;
+ break;
+ case 0x243: // Set page length in defined unit (ESC (C)
+ case 0x256: // Set absolute vertical print position (ESC (V)
+ case 0x276: // Set relative vertical print position (ESC (v)
+ neededParam = 4;
+ break;
+ case 0x228: // Assign character table (ESC (t)
+ case 0x22d: // Select line/score (ESC (-)
+ neededParam = 5;
+ break;
+ case 0x263: // Set page format (ESC (c)
+ neededParam = 6;
+ break;
+ default:
+ // ESC ( commands are always followed by a "number of parameters" word parameter
+ LOG(LOG_MISC,LOG_ERROR)("PRINTER: Skipping unsupported command ESC ( %c (%02X).", ESCCmd, ESCCmd);
+ neededParam = 2;
+ ESCCmd = 0x101;
+ return true;
+ }
+
+ if (neededParam > 0)
+ return true;
+ }
+
+ // Ignore VFU channel setting
+ if (ESCCmd == 0x62)
+ {
+ ESCCmd = 0x42;
+ return true;
+ }
+
+ // Collect vertical tabs
+ if (ESCCmd == 0x42)
+ {
+ if (ch == 0 || (numVertTabs>0 && verttabs[numVertTabs-1] > (Real64)chlineSpacing)) // Done
+ ESCCmd = 0;
+ else
+ if (numVertTabs < 16)
+ verttabs[numVertTabs++] = (Real64)chlineSpacing;
+ }
+
+ // Collect horizontal tabs
+ if (ESCCmd == 0x44)
+ {
+ if (ch == 0 || (numHorizTabs>0 && horiztabs[numHorizTabs-1] > (Real64)ch(1/(Real64)cpi))) // Done
+ ESCCmd = 0;
+ else
+ if (numHorizTabs < 32)
+ horiztabs[numHorizTabs++] = (Real64)ch(1/(Real64)cpi);
+ }
+
+ if (numParam < neededParam)
+ {
+ params[numParam++] = ch;
+
+ if (numParam < neededParam)
+ return true;
+ }
+
+ if (ESCCmd != 0)
+ {
+ switch (ESCCmd)
+ {
+ case 0x02: // Undocumented
+ // Ignore
+ break;
+ case 0x0e: // Select double-width printing (one line) (ESC SO)
+ if (!multipoint)
+ {
+ hmi = -1;
+ style |= STYLE_DOUBLEWIDTHONELINE;
+ updateFont();
+ }
+ break;
+ case 0x0f: // Select condensed printing (ESC SI)
+ if (!multipoint)
+ {
+ hmi = -1;
+ style |= STYLE_CONDENSED;
+ updateFont();
+ }
+ break;
+ case 0x19: // Control paper loading/ejecting (ESC EM)
+ // We are not really loading paper, so most commands can be ignored
+ if (params[0] == 'R')
+ newPage(true);
+ break;
+ case 0x20: // Set intercharacter space (ESC SP)
+ if (!multipoint)
+ {
+ extraIntraSpace = (Real64)params[0] / (printQuality==QUALITY_DRAFT?120:180);
+ hmi = -1;
+ updateFont();
+ }
+ break;
+ case 0x21: // Master select (ESC !)
+ cpi = params[0] & 0x01 ? 12:10;
+
+ // Reset first seven bits
+ style &= 0xFF80;
+ if (params[0] & 0x02)
+ style |= STYLE_PROP;
+ if (params[0] & 0x04)
+ style |= STYLE_CONDENSED;
+ if (params[0] & 0x08)
+ style |= STYLE_BOLD;
+ if (params[0] & 0x10)
+ style |= STYLE_DOUBLESTRIKE;
+ if (params[0] & 0x20)
+ style |= STYLE_DOUBLEWIDTH;
+ if (params[0] & 0x40)
+ style |= STYLE_ITALICS;
+ if (params[0] & 0x80)
+ {
+ score = SCORE_SINGLE;
+ style |= STYLE_UNDERLINE;
+ }
+
+ hmi = -1;
+ multipoint = false;
+ updateFont();
+ break;
+ case 0x23: // Cancel MSB control (ESC #)
+ msb = 255;
+ break;
+ case 0x24: // Set absolute horizontal print position (ESC $)
+ {
+ Real64 unitSize = definedUnit;
+ if (unitSize < 0)
+ unitSize = (Real64)60.0;
+
+ Real64 newX = leftMargin + ((Real64)PARAM16(0)/unitSize);
+ if (newX <= rightMargin)
+ curX = newX;
+ }
+ break;
+ case 0x2a: // Select bit image (ESC )
+ setupBitImage(params[0], PARAM16(1));
+ break;
+ case 0x2b: // Set n/360-inch line spacing (ESC +)
+ lineSpacing = (Real64)params[0]/360;
+ break;
+ case 0x2d: // Turn underline on/off (ESC -)
+ if (params[0] == 0 || params[0] == 48)
+ style &= 0xFFFF - STYLE_UNDERLINE;
+ if (params[0] == 1 || params[0] == 49)
+ {
+ style |= STYLE_UNDERLINE;
+ score = SCORE_SINGLE;
+ }
+ updateFont();
+ break;
+ case 0x2f: // Select vertical tab channel (ESC /)
+ // Ignore
+ break;
+ case 0x30: // Select 1/8-inch line spacing (ESC 0)
+ lineSpacing = (Real64)1/8;
+ break;
+ case 0x32: // Select 1/6-inch line spacing (ESC 2)
+ lineSpacing = (Real64)1/6;
+ break;
+ case 0x33: // Set n/180-inch line spacing (ESC 3)
+ lineSpacing = (Real64)params[0]/180;
+ break;
+ case 0x34: // Select italic font (ESC 4)
+ style |= STYLE_ITALICS;
+ updateFont();
+ break;
+ case 0x35: // Cancel italic font (ESC 5)
+ style &= 0xFFFF - STYLE_ITALICS;
+ updateFont();
+ break;
+ case 0x36: // Enable printing of upper control codes (ESC 6)
+ printUpperContr = true;
+ break;
+ case 0x37: // Enable upper control codes (ESC 7)
+ printUpperContr = false;
+ break;
+ case 0x3c: // Unidirectional mode (one line) (ESC <)
+ // We don't have a print head, so just ignore this
+ break;
+ case 0x3d: // Set MSB to 0 (ESC =)
+ msb = 0;
+ break;
+ case 0x3e: // Set MSB to 1 (ESC >)
+ msb = 1;
+ break;
+ case 0x3f: // Reassign bit-image mode (ESC ?)
+ if (params[0] == 75)
+ densk = params[1];
+ if (params[0] == 76)
+ densl = params[1];
+ if (params[0] == 89)
+ densy = params[1];
+ if (params[0] == 90)
+ densz = params[1];
+ break;
+ case 0x40: // Initialize printer (ESC @)
+ resetPrinter();
+ break;
+ case 0x41: // Set n/60-inch line spacing
+ lineSpacing = (Real64)params[0]/60;
+ break;
+ case 0x43: // Set page length in lines (ESC C)
+ if (params[0] != 0)
+ pageHeight = bottomMargin = (Real64)params[0] * lineSpacing;
+ else // == 0 => Set page length in inches
+ {
+ neededParam = 1;
+ numParam = 0;
+ ESCCmd = 0x100;
+ return true;
+ }
+ break;
+ case 0x45: // Select bold font (ESC E)
+ style |= STYLE_BOLD;
+ updateFont();
+ break;
+ case 0x46: // Cancel bold font (ESC F)
+ style &= 0xFFFF - STYLE_BOLD;
+ updateFont();
+ break;
+ case 0x47: // Select dobule-strike printing (ESC G)
+ style |= STYLE_DOUBLESTRIKE;
+ break;
+ case 0x48: // Cancel double-strike printing (ESC H)
+ style &= 0xFFFF - STYLE_DOUBLESTRIKE;
+ break;
+ case 0x4a: // Advance print position vertically (ESC J n)
+ curY += (Real64)((Real64)params[0] / 180);
+ if (curY > bottomMargin)
+ newPage(true);
+ break;
+ case 0x4b: // Select 60-dpi graphics (ESC K)
+ setupBitImage(densk, PARAM16(0));
+ break;
+ case 0x4c: // Select 120-dpi graphics (ESC L)
+ setupBitImage(densl, PARAM16(0));
+ break;
+ case 0x4d: // Select 10.5-point, 12-cpi (ESC M)
+ cpi = 12;
+ hmi = -1;
+ multipoint = false;
+ updateFont();
+ break;
+ case 0x4e: // Set bottom margin (ESC N)
+ topMargin = 0.0;
+ bottomMargin = (Real64)params[0] * lineSpacing;
+ break;
+ case 0x4f: // Cancel bottom (and top) margin
+ topMargin = 0.0;
+ bottomMargin = pageHeight;
+ break;
+ case 0x50: // Select 10.5-point, 10-cpi (ESC P)
+ cpi = 10;
+ hmi = -1;
+ multipoint = false;
+ updateFont();
+ break;
+ case 0x51: // Set right margin
+ rightMargin = (Real64)(params[0]-1.0) / (Real64)cpi;
+ break;
+ case 0x52: // Select an international character set (ESC R)
+ if (params[0] <= 13 || params[0] == 64)
+ {
+ if (params[0] == 64)
+ params[0] = 14;
+
+ curMap[0x23] = intCharSets[params[0]][0];
+ curMap[0x24] = intCharSets[params[0]][1];
+ curMap[0x40] = intCharSets[params[0]][2];
+ curMap[0x5b] = intCharSets[params[0]][3];
+ curMap[0x5c] = intCharSets[params[0]][4];
+ curMap[0x5d] = intCharSets[params[0]][5];
+ curMap[0x5e] = intCharSets[params[0]][6];
+ curMap[0x60] = intCharSets[params[0]][7];
+ curMap[0x7b] = intCharSets[params[0]][8];
+ curMap[0x7c] = intCharSets[params[0]][9];
+ curMap[0x7d] = intCharSets[params[0]][10];
+ curMap[0x7e] = intCharSets[params[0]][11];
+ }
+ break;
+ case 0x53: // Select superscript/subscript printing (ESC S)
+ if (params[0] == 0 || params[0] == 48)
+ style |= STYLE_SUBSCRIPT;
+ if (params[0] == 1 || params[1] == 49)
+ style |= STYLE_SUPERSCRIPT;
+ updateFont();
+ break;
+ case 0x54: // Cancel superscript/subscript printing (ESC T)
+ style &= 0xFFFF - STYLE_SUPERSCRIPT - STYLE_SUBSCRIPT;
+ updateFont();
+ break;
+ case 0x55: // Turn unidirectional mode on/off (ESC U)
+ // We don't have a print head, so just ignore this
+ break;
+ case 0x57: // Turn double-width printing on/off (ESC W)
+ if (!multipoint)
+ {
+ hmi = -1;
+ if (params[0] == 0 || params[0] == 48)
+ style &= 0xFFFF - STYLE_DOUBLEWIDTH;
+ if (params[0] == 1 || params[0] == 49)
+ style |= STYLE_DOUBLEWIDTH;
+ updateFont();
+ }
+ break;
+ case 0x58: // Select font by pitch and point (ESC X)
+ multipoint = true;
+ // Copy currently non-multipoint CPI if no value was set so far
+ if (multicpi == 0)
+ multicpi = cpi;
+ if (params[0] > 0) // Set CPI
+ {
+ if (params[0] == 1) // Proportional spacing
+ style |= STYLE_PROP;
+ else if (params[0] >= 5)
+ multicpi = (Real64)360 / (Real64)params[0];
+ }
+ if (multiPointSize == 0)
+ multiPointSize = (Real64)10.5;
+ if (PARAM16(1) > 0) // Set points
+ multiPointSize = ((Real64)PARAM16(1)) / 2;
+ updateFont();
+ break;
+ case 0x59: // Select 120-dpi, double-speed graphics (ESC Y)
+ setupBitImage(densy, PARAM16(0));
+ break;
+ case 0x5a: // Select 240-dpi graphics (ESC Z)
+ setupBitImage(densz, PARAM16(0));
+ break;
+ case 0x5c: // Set relative horizontal print position (ESC )
+ {
+ Bit16s toMove = PARAM16(0);
+ Real64 unitSize = definedUnit;
+ if (unitSize < 0)
+ unitSize = (Real64)(printQuality==QUALITY_DRAFT?120.0:180.0);
+ curX += (Real64)((Real64)toMove / unitSize);
+ }
+ break;
+ case 0x61: // Select justification (ESC a)
+ // Ignore
+ break;
+ case 0x63: // Set horizontal motion index (HMI) (ESC c)
+ hmi = (Real64)PARAM16(0) / (Real64)360.0;
+ extraIntraSpace = 0.0;
+ break;
+ case 0x67: // Select 10.5-point, 15-cpi (ESC g)
+ cpi = 15;
+ hmi = -1;
+ multipoint = false;
+ updateFont();
+ break;
+ case 0x6b: // Select typeface (ESC k)
+ if (params[0] <= 11 || params[0] == 30 || params[0] == 31)
+ LQtypeFace = (Typeface)params[0];
+ updateFont();
+ break;
+ case 0x6c: // Set left margin (ESC 1)
+ leftMargin = (Real64)(params[0]-1.0) / (Real64)cpi;
+ if (curX < leftMargin)
+ curX = leftMargin;
+ break;
+ case 0x70: // Turn proportional mode on/off (ESC p)
+ if (params[0] == 0 || params[0] == 48)
+ style &= (0xffff - STYLE_PROP);
+ if (params[0] == 1 || params[0] == 49)
+ {
+ style |= STYLE_PROP;
+ printQuality = QUALITY_LQ;
+ }
+ multipoint = false;
+ hmi = -1;
+ updateFont();
+ break;
+ case 0x72: // Select printing color (ESC r)
+ if (params[0] != 0)
+ LOG(LOG_MISC,LOG_WARN)("PRINTER: Color printing not supported");
+ break;
+ case 0x73: // Select low-speed mode (ESC s)
+ // Ignore
+ break;
+ case 0x74: // Select character table (ESC t)
+ if (params[0] < 4)
+ curCharTable = params[0];
+ if (params[0] >= 48 && params[0] <= 51)
+ curCharTable = params[0] - 48;
+ selectCodepage(charTables[curCharTable]);
+ updateFont();
+ break;
+ case 0x77: // Turn double-height printing on/off (ESC w)
+ if (!multipoint)
+ {
+ if (params[0] == 0 || params[0] == 48)
+ style &= 0xFFFF - STYLE_DOUBLEHEIGHT;
+ if (params[0] == 1 || params[0] == 49)
+ style |= STYLE_DOUBLEHEIGHT;
+ updateFont();
+ }
+ break;
+ case 0x78: // Select LQ or draft (ESC x)
+ if (params[0] == 0 || params[0] == 48)
+ printQuality = QUALITY_DRAFT;
+ if (params[0] == 1 || params[0] == 49)
+ printQuality = QUALITY_LQ;
+ break;
+ case 0x100: // Set page length in inches (ESC C NUL)
+ pageHeight = (Real64)params[0];
+ bottomMargin = pageHeight;
+ topMargin = 0.0;
+ break;
+ case 0x101: // Skip unsupported ESC ( command
+ neededParam = PARAM16(0);
+ numParam = 0;
+ break;
+ case 0x228: // Assign character table (ESC (t)
+ if (params[2] < 4 && params[3] < 16)
+ {
+ charTables[params[2]] = codepages[params[3]];
+ if (params[2] == curCharTable)
+ selectCodepage(charTables[curCharTable]);
+ }
+ break;
+ case 0x22d: // Select line/score (ESC (-)
+ style &= 0xFFFF - STYLE_UNDERLINE - STYLE_STRIKETHROUGH - STYLE_OVERSCORE;
+ score = params[4];
+ if (score)
+ {
+ if (params[3] == 1)
+ style |= STYLE_UNDERLINE;
+ if (params[3] == 2)
+ style |= STYLE_STRIKETHROUGH;
+ if (params[3] == 3)
+ style |= STYLE_OVERSCORE;
+ }
+ updateFont();
+ break;
+ case 0x242: // Bar code setup and print (ESC (B)
+ LOG(LOG_MISC,LOG_ERROR)("PRINTER: Bardcode printing not supported");
+ // Find out how many bytes to skip
+ neededParam = PARAM16(0);
+ numParam = 0;
+ break;
+ case 0x243: // Set page length in defined unit (ESC (C)
+ if (params[0] != 0 && definedUnit > 0)
+ {
+ pageHeight = bottomMargin = ((Real64)PARAM16(2)) * definedUnit;
+ topMargin = 0.0;
+ }
+ break;
+ case 0x255: // Set unit (ESC (U)
+ definedUnit = (Real64)3600 / (Real64)params[2];
+ break;
+ case 0x256: // Set absolute vertical print position (ESC (V)
+ {
+ Real64 unitSize = definedUnit;
+ if (unitSize < 0)
+ unitSize = (Real64)360.0;
+ Real64 newPos = topMargin + (((Real64)PARAM16(2)) * unitSize);
+ if (newPos > bottomMargin)
+ newPage(true);
+ else
+ curY = newPos;
+ }
+ break;
+ case 0x25e: // Print data as characters (ESC (^)
+ numPrintAsChar = PARAM16(0);
+ break;
+ case 0x263: // Set page format (ESC (c)
+ if (definedUnit > 0)
+ {
+ topMargin = ((Real64)PARAM16(2)) * definedUnit;
+ bottomMargin = ((Real64)PARAM16(4)) * definedUnit;
+ }
+ break;
+ case 0x276: // Set relative vertical print position (ESC (v)
+ {
+ Real64 unitSize = definedUnit;
+ if (unitSize < 0)
+ unitSize = (Real64)360.0;
+ Real64 newPos = curY + ((Real64)((Bit16s)PARAM16(2)) * unitSize);
+ if (newPos > topMargin)
+ {
+ if (newPos > bottomMargin)
+ newPage(true);
+ else
+ curY = newPos;
+ }
+ }
+ break;
+ default:
+ if (ESCCmd < 0x100)
+ LOG(LOG_MISC,LOG_WARN)("PRINTER: Skipped unsupported command ESC %c (%02X)", ESCCmd, ESCCmd);
+ else
+ LOG(LOG_MISC,LOG_WARN)("PRINTER: Skipped unsupported command ESC ( %c (%02X)", ESCCmd-0x200, ESCCmd-0x200);
+ }
+
+ ESCCmd = 0;
+ return true;
+ }
+
+ switch (ch)
+ {
+ case 0x07: // Beeper (BEL)
+ // BEEEP!
+ return true;
+ case 0x08: // Backspace (BS)
+ {
+ Real64 newX = curX - (1/(Real64)actcpi);
+ if (hmi > 0)
+ newX = curX - hmi;
+ if (newX >= leftMargin)
+ curX = newX;
+ }
+ return true;
+ case 0x09: // Tab horizontally (HT)
+ {
+ // Find tab right to current pos
+ Real64 moveTo = -1;
+ for (Bit8u i=0; i<numhoriztabs; i++)="" +="" if="" (horiztabs<span="">[i] > curX)
+ moveTo = horiztabs[i];
+ // Nothing found => Ignore
+ if (moveTo > 0 && moveTo < rightMargin)
+ curX = moveTo;
+ }
+ return true;
+ case 0x0b: // Tab vertically (VT)
+ if (numVertTabs == 0) // All tabs cancelled => Act like CR
+ curX = leftMargin;
+ else if (numVertTabs == 255) // No tabs set since reset => Act like LF
+ {
+ curX = leftMargin;
+ curY += lineSpacing;
+ if (curY > bottomMargin)
+ newPage(true);
+ }
+ else
+ {
+ // Find tab below current pos
+ Real64 moveTo = -1;
+ for (Bit8u i=0; i<numverttabs; i++)="" +="" if="" (verttabs<span="">[i] > curY)
+ moveTo = verttabs[i];
+
+ // Nothing found => Act like FF
+ if (moveTo > bottomMargin || moveTo < 0)
+ newPage(true);
+ else
+ curY = moveTo;
+ }
+ if (style & STYLE_DOUBLEWIDTHONELINE)
+ {
+ style &= 0xFFFF - STYLE_DOUBLEWIDTHONELINE;
+ updateFont();
+ }
+ return true;
+ case 0x0c: // Form feed (FF)
+ if (style & STYLE_DOUBLEWIDTHONELINE)
+ {
+ style &= 0xFFFF - STYLE_DOUBLEWIDTHONELINE;
+ updateFont();
+ }
+ newPage(true);
+ return true;
+ case 0x0d: // Carriage Return (CR)
+ curX = leftMargin;
+ if (!autoFeed)
+ return true;
+ case 0x0a: // Line feed
+ if (style & STYLE_DOUBLEWIDTHONELINE)
+ {
+ style &= 0xFFFF - STYLE_DOUBLEWIDTHONELINE;
+ updateFont();
+ }
+ curX = leftMargin;
+ curY += lineSpacing;
+ if (curY > bottomMargin)
+ newPage(true);
+ return true;
+ case 0x0e: //Select Real64-width printing (one line) (SO)
+ if (!multipoint)
+ {
+ hmi = -1;
+ style |= STYLE_DOUBLEWIDTHONELINE;
+ updateFont();
+ }
+ return true;
+ case 0x0f: // Select condensed printing (SI)
+ if (!multipoint)
+ {
+ hmi = -1;
+ style |= STYLE_CONDENSED;
+ updateFont();
+ }
+ return true;
+ case 0x11: // Select printer (DC1)
+ // Ignore
+ return true;
+ case 0x12: // Cancel condensed printing (DC2)
+ hmi = -1;
+ style &= 0xFFFF - STYLE_CONDENSED;
+ updateFont();
+ return true;
+ case 0x13: // Deselect printer (DC3)
+ // Ignore
+ return true;
+ case 0x14: // Cancel double-width printing (one line) (DC4)
+ hmi = -1;
+ style &= 0xFFFF - STYLE_DOUBLEWIDTHONELINE;
+ updateFont();
+ return true;
+ case 0x18: // Cancel line (CAN)
+ return true;
+ case 0x1b: // ESC
+ ESCSeen = true;
+ return true;
+ default:
+ return false;
+ }
+
+ return false;
+}
+
+void CPrinter::newPage(bool save)
+{
+ if (save)
+ outputPage();
+
+ curY = topMargin;
+
+ SDL_Rect rect;
+ rect.x = 0;
+ rect.y = 0;
+ rect.w = page->w;
+ rect.h = page->h;
+ SDL_FillRect(page, &rect, SDL_MapRGB(page->format, 255, 255, 255));
+}
+
+void CPrinter::printChar(Bit8u ch)
+{
+ charRead = true;
+
+ if (page == NULL)
+ return;
+
+ // Don't think that DOS programs uses this but well: Apply MSB if desired
+ if (msb != 255)
+ {
+ if (msb == 0)
+ ch &= 0x7F;
+ if (msb == 1)
+ ch |= 0x80;
+ }
+
+ // Are we currently printing a bit graphic?
+ if (bitGraph.remBytes > 0)
+ {
+ printBitGraph(ch);
+ return;
+ }
+
+ // Print everything?
+ if (numPrintAsChar > 0)
+ numPrintAsChar--;
+ else if (processCommandChar(ch))
+ return;
+
+ // Do not print if no font is available
+ if (!curFont)
+ return;
+
+ // Find the glyph for the char to render
+ FT_UInt index = FT_Get_Char_Index(curFont, curMap[ch]);
+
+ // Load the glyph
+ FT_Load_Glyph(curFont, index, FT_LOAD_DEFAULT);
+
+ // Render a high-quality bitmap
+ FT_Render_Glyph(curFont->glyph, FT_RENDER_MODE_NORMAL);
+
+ Bit16u penX = PIXX + curFont->glyph->bitmap_left;
+ Bit16u penY = PIXY - curFont->glyph->bitmap_top + curFont->size->metrics.ascender/64;
+
+ if (style & STYLE_SUBSCRIPT)
+ penY += curFont->glyph->bitmap.rows / 2;
+
+ // Copy bitmap into page
+ SDL_LockSurface(page);
+
+ blitGlyph(curFont->glyph->bitmap, penX, penY, false);
+
+ // Doublestrike => Print the glyph a second time one pixel below
+ if (style & STYLE_DOUBLESTRIKE)
+ blitGlyph(curFont->glyph->bitmap, penX, penY+1, true);
+
+ // Bold => Print the glyph a second time one pixel to the right
+ if (style & STYLE_BOLD)
+ blitGlyph(curFont->glyph->bitmap, penX+1, penY, true);
+
+ SDL_UnlockSurface(page);
+
+ // For line printing
+ Bit16u lineStart = PIXX;
+
+ if (style & STYLE_PROP)
+ curX += (Real64)((Real64)(curFont->glyph->advance.x)/(Real64)(dpi64));
+ else
+ {
+ if (hmi < 0)
+ curX += 1/(Real64)actcpi;
+ else
+ curX += hmi;
+ }
+
+ curX += extraIntraSpace;
+
+ // Draw lines if desired
+ if (score != SCORE_NONE && (style & (STYLE_UNDERLINE|STYLE_STRIKETHROUGH|STYLE_OVERSCORE)))
+ {
+ // Find out where to put the line
+ Bit16u lineY = PIXY;
+
+ if (style & STYLE_UNDERLINE)
+ lineY = penY + 5 + curFont->glyph->bitmap.rows;
+ if (style & STYLE_STRIKETHROUGH)
+ lineY = PIXY + curFont->size->metrics.ascender/128;
+ if (style & STYLE_OVERSCORE)
+ lineY = PIXY - ((score == SCORE_DOUBLE || score == SCORE_DOUBLEBROKEN)?5:0);
+
+ drawLine(penX, PIXX, lineY, score==SCORE_SINGLEBROKEN || score==SCORE_DOUBLEBROKEN);
+
+ if (score == SCORE_DOUBLE || score == SCORE_DOUBLEBROKEN)
+ drawLine(lineStart, PIXX, lineY + 5, score==SCORE_SINGLEBROKEN || score==SCORE_DOUBLEBROKEN);
+ }
+}
+
+void CPrinter::blitGlyph(FT_Bitmap bitmap, Bit16u destx, Bit16u desty, bool add)
+{
+ for (int y=0; y<bitmap.rows; y++)
+ {
+ for (int x=0; x<bitmap.width; x++)
+ {
+ // Read pixel from glyph bitmap
+ Bit8u source = bitmap.buffer + x + ybitmap.pitch;
+
+ // Ignore background and don't go over the border
+ if (source != 0 && (destx+x < page->w) && (desty+y < page->h))
+ {
+ Bit8u target = (Bit8u)page->pixels + (x+destx) + (y+desty)page->pitch;
+ if (add)
+ {
+ if (target + source > 255)
+ target = 255;
+ else
+ target += source;
+ }
+ else
+ target = source;
+ }
+ }
+ }
+}
+
+void CPrinter::drawLine(Bit8u fromx, Bit8u tox, Bit8u y, bool broken)
+{
+ SDL_LockSurface(page);
+
+ Bitu breakmod = dpi / 15;
+ Bitu gapstart = (breakmod * 4)/5;
+
+ // Draw anti-aliased line
+ for (int x=fromx; x<=tox; x++)
+ {
+ // Skip parts if broken line or going over the border
+ if ((!broken || (x%breakmod <= gapstart)) && (x < page->w))
+ {
+ if (y > 0 && (y-1) < page->h)
+ ((Bit8u)page->pixels + x + (y-1)page->pitch) = 120;
+ if (y < page->h)
+ ((Bit8u)page->pixels + x + ypage->pitch) = !broken?255:120;
+ if (y+1 < page->h)
+ ((Bit8u)page->pixels + x + (y+1)page->pitch) = 120;
+ }
+ }
+
+ SDL_UnlockSurface(page);
+}
+
+void CPrinter::setAutofeed(bool feed)
+{
+ autoFeed = feed;
+}
+
+bool CPrinter::getAutofeed()
+{
+ return autoFeed;
+}
+
+bool CPrinter::isBusy()
+{
+ // We're never busy
+ return false;
+}
+
+bool CPrinter::ack()
+{
+ // Acknowledge last char read
+ return charRead;
+}
+
+void CPrinter::setupBitImage(Bit8u dens, Bit16u numCols)
+{
+ switch (dens)
+ {
+ case 0:
+ bitGraph.horizDens = 60;
+ bitGraph.vertDens = 60;
+ bitGraph.adjacent = true;
+ bitGraph.bytesColumn = 1;
+ break;
+ case 1:
+ bitGraph.horizDens = 120;
+ bitGraph.vertDens = 60;
+ bitGraph.adjacent = true;
+ bitGraph.bytesColumn = 1;
+ break;
+ case 2:
+ bitGraph.horizDens = 120;
+ bitGraph.vertDens = 60;
+ bitGraph.adjacent = false;
+ bitGraph.bytesColumn = 1;
+ break;
+ case 3:
+ bitGraph.horizDens = 60;
+ bitGraph.vertDens = 240;
+ bitGraph.adjacent = false;
+ bitGraph.bytesColumn = 1;
+ break;
+ case 4:
+ bitGraph.horizDens = 80;
+ bitGraph.vertDens = 60;
+ bitGraph.adjacent = true;
+ bitGraph.bytesColumn = 1;
+ break;
+ case 6:
+ bitGraph.horizDens = 90;
+ bitGraph.vertDens = 60;
+ bitGraph.adjacent = true;
+ bitGraph.bytesColumn = 1;
+ break;
+ case 32:
+ bitGraph.horizDens = 60;
+ bitGraph.vertDens = 180;
+ bitGraph.adjacent = true;
+ bitGraph.bytesColumn = 3;
+ break;
+ case 33:
+ bitGraph.horizDens = 120;
+ bitGraph.vertDens = 180;
+ bitGraph.adjacent = true;
+ bitGraph.bytesColumn = 3;
+ break;
+ case 38:
+ bitGraph.horizDens = 90;
+ bitGraph.vertDens = 180;
+ bitGraph.adjacent = true;
+ bitGraph.bytesColumn = 3;
+ break;
+ case 39:
+ bitGraph.horizDens = 180;
+ bitGraph.vertDens = 180;
+ bitGraph.adjacent = true;
+ bitGraph.bytesColumn = 3;
+ break;
+ case 40:
+ bitGraph.horizDens = 360;
+ bitGraph.vertDens = 180;
+ bitGraph.adjacent = false;
+ bitGraph.bytesColumn = 3;
+ break;
+ case 71:
+ bitGraph.horizDens = 180;
+ bitGraph.vertDens = 360;
+ bitGraph.adjacent = true;
+ bitGraph.bytesColumn = 6;
+ break;
+ case 72:
+ bitGraph.horizDens = 360;
+ bitGraph.vertDens = 360;
+ bitGraph.adjacent = false;
+ bitGraph.bytesColumn = 6;
+ break;
+ case 73:
+ bitGraph.horizDens = 360;
+ bitGraph.vertDens = 360;
+ bitGraph.adjacent = true;
+ bitGraph.bytesColumn = 6;
+ break;
+ default:
+ LOG(LOG_MISC,LOG_ERROR)("PRINTER: Unsupported bit image density %i", dens);
+ }
+
+ bitGraph.remBytes = numCols * bitGraph.bytesColumn;
+ bitGraph.readBytesColumn = 0;
+}
+
+void CPrinter::printBitGraph(Bit8u ch)
+{
+ bitGraph.column[bitGraph.readBytesColumn++] = ch;
+ bitGraph.remBytes--;
+
+ // Only print after reading a full column
+ if (bitGraph.readBytesColumn < bitGraph.bytesColumn)
+ return;
+
+ Real64 oldY = curY;
+
+ SDL_LockSurface(page);
+
+ // When page dpi is greater than graphics dpi, the drawn pixels get "bigger"
+ Bitu pixsizeX = dpi/bitGraph.horizDens > 0?dpi/bitGraph.horizDens:1;
+ Bitu pixsizeY = dpi/bitGraph.vertDens > 0?dpi/bitGraph.vertDens:1;
+
+ for (Bit8u i=0; i<bitgraph.bytescolumn; i++)="" +="" {="" for="" (bits="" j="7;">=0; j--)
+ {
+ Bit8u pixel = (bitGraph.column[i] >> j) & 0x01;
+
+ if (pixel != 0)
+ {
+ for (Bitu xx=0; xx<pixsizeX; xx++)
+ for (Bitu yy=0; yy<pixsizeY; yy++)
+ if (((PIXX + xx) < page->w) && ((PIXY + yy) < page->h))
+ </bitgraph.bytescolumn;>((Bit8u)page->pixels + PIXX + xx + (PIXY+yy)page->pitch) = 255;
+ }
+
+ curY += (Real64)1/(Real64)bitGraph.vertDens;
+ }
+ }
+
+ SDL_UnlockSurface(page);
+
+ curY = oldY;
+
+ bitGraph.readBytesColumn = 0;
+
+ // Advance to the left
+ curX += (Real64)1/(Real64)bitGraph.horizDens;
+}
+
+void CPrinter::formFeed()
+{
+ // Don't output blank pages
+ newPage(!isBlank());
+
+ finishMultipage();
+}
+
+static void findNextName(char front, char ext, char fname)
+{
+ char buffer[10];
+ Bit16u num = 1;
+ FILE test = NULL;
+ do
+ {
+ strcpy(fname, front);
+ sprintf(&buffer[0], "%d", num++);
+ strcat(fname, &buffer[0]);
+ strcat(fname, ext);
+ test = fopen(fname, "rb");
+ if (test != NULL)
+ fclose(test);
+ }
+ while (test != NULL);
+}
+
+void CPrinter::outputPage()
+{
+ char fname[200];
+
+ if (strcasecmp(output, "printer") == 0)
+ {
+#if defined (WIN32)
+ Bit16u physW = GetDeviceCaps(printerDC, PHYSICALWIDTH);
+ Bit16u physH = GetDeviceCaps(printerDC, PHYSICALHEIGHT);
+
+ Real64 scaleW, scaleH;
+ //Bit32u topX, topY;
+
+ if (page->w > physW)
+ scaleW = (Real64)page->w / (Real64)physW;
+ else
+ scaleW = (Real64)physW / (Real64)page->w;
+
+ if (page->h > physH)
+ scaleH = (Real64)page->h / (Real64)physH;
+ else
+ scaleH = (Real64)physH / (Real64)page->h;
+
+ HDC memHDC = CreateCompatibleDC(printerDC);
+ HBITMAP bitmap = CreateCompatibleBitmap(memHDC, page->w, page->h);
+ SelectObject(memHDC, bitmap);
+
+ // Start new printer job?
+ if (outputHandle == NULL)
+ {
+ DOCINFO docinfo;
+ docinfo.cbSize = sizeof(docinfo);
+ docinfo.lpszDocName = "DOSBOX Printer";
+ docinfo.lpszOutput = NULL;
+ docinfo.lpszDatatype = NULL;
+ docinfo.fwType = 0;
+
+ StartDoc(printerDC, &docinfo);
+ multiPageCounter = 1;
+ }
+
+ StartPage(printerDC);
+ SDL_LockSurface(page);
+
+ SDL_Palette sdlpal = page->format->palette;
+
+ for (Bit16u y=0; y<page->h; y++)
+ {
+ for (Bit16u x=0; x<page->w; x++)
+ {
+ Bit8u pixel = </page-></page->((Bit8u)page->pixels + x + (ypage->pitch));
+ Bit32u color = 0;
+ color |= sdlpal->colors[pixel].r;
+ color |= ((Bit32u)sdlpal->colors[pixel].g) << 8;
+ color |= ((Bit32u)sdlpal->colors[pixel].b) << 16;
+ SetPixel(memHDC, x, y, color);
+ }
+ }
+
+ SDL_UnlockSurface(page);
+
+ StretchBlt(printerDC, 0, 0, physW, physH, memHDC, 0, 0, page->w, page->h, SRCCOPY);
+
+ EndPage(printerDC);
+
+ if (multipageOutput)
+ {
+ multiPageCounter++;
+ outputHandle = printerDC;
+ }
+ else
+ {
+ EndDoc(printerDC);
+ outputHandle = NULL;
+ }
+
+ DeleteDC(memHDC);
+#else
+ LOG(LOG_MISC,LOG_ERROR)("PRINTER: Direct printing not supported under this OS");
+#endif
+ }
+#ifdef C_LIBPNG
+ else if (strcasecmp(output, "png") == 0)
+ {
+ // Find a page that does not exists
+ findNextName("page", ".png", &fname[0]);
+
+ png_structp png_ptr;
+ png_infop info_ptr;
+ png_bytep * row_pointers;
+ png_color palette[256];
+
+ / Open the actual file /
+ FILE * fp=fopen(fname,"wb");
+ if (!fp)
+ {
+ LOG(LOG_MISC,LOG_ERROR)("PRINTER: Can't open file %s for printer output", fname);
+ return;
+ }
+
+ / First try to alloacte the png structures /
+ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL,NULL, NULL);
+ if (!png_ptr) return;
+ info_ptr = png_create_info_struct(png_ptr);
+ if (!info_ptr) {
+ png_destroy_write_struct(&png_ptr,(png_infopp)NULL);
+ return;
+ }
+
+ / Finalize the initing of png library /
+ png_init_io(png_ptr, fp);
+ png_set_compression_level(png_ptr,Z_BEST_COMPRESSION);
+
+ / set other zlib parameters /
+ png_set_compression_mem_level(png_ptr, 8);
+ png_set_compression_strategy(png_ptr,Z_DEFAULT_STRATEGY);
+ png_set_compression_window_bits(png_ptr, 15);
+ png_set_compression_method(png_ptr, 8);
+ png_set_compression_buffer_size(png_ptr, 8192);
+
+
+ png_set_IHDR(png_ptr, info_ptr, page->w, page->h,
+ 8, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,
+ PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
+ for (Bitu i=0; i!=256; ++i)
+ {
+ palette[i].red = page->format->palette->colors[i].r;
+ palette[i].green = page->format->palette->colors[i].g;
+ palette[i].blue = page->format->palette->colors[i].b;
+ }
+ png_set_PLTE(png_ptr, info_ptr, palette,256);
+
+ SDL_LockSurface(page);
+
+ // Allocate an array of scanline pointers
+ row_pointers = (png_bytep)malloc(page->hsizeof(png_bytep));
+ for (int i=0; i!=page->h; ++i)
+ row_pointers[i] = ((Bit8u)page->pixels+(ipage->pitch));
+
+ // tell the png library what to encode.
+ png_set_rows(png_ptr, info_ptr, row_pointers);
+
+ // Write image to file
+ png_write_png(png_ptr, info_ptr, 0, NULL);
+
+ SDL_UnlockSurface(page);
+
+ /close file/
+ fclose(fp);
+
+ /Destroy PNG structs/
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+
+ /clean up dynamically allocated RAM./
+ free(row_pointers);
+ }
+#endif
+ else if (strcasecmp(output, "ps") == 0)
+ {
+ FILE psfile = NULL;
+
+ // Continue postscript file?
+ if (outputHandle != NULL)
+ psfile = (FILE)outputHandle;
+
+ // Create new file?
+ if (psfile == NULL)
+ {
+ if (!multipageOutput)
+ findNextName("page", ".ps", &fname[0]);
+ else
+ findNextName("doc", ".ps", &fname[0]);
+
+ psfile = fopen(fname, "wb");
+ if (!psfile)
+ {
+ LOG(LOG_MISC,LOG_ERROR)("PRINTER: Can't open file %s for printer output", fname);
+ return;
+ }
+
+ // Print header
+ fprintf(psfile, "%%!PS-Adobe-3.0\n");
+ fprintf(psfile, "%%%%Pages: (atend)\n");
+ fprintf(psfile, "%%%%BoundingBox: 0 0 %i %i\n", (Bit16u)(defaultPageWidth74), (Bit16u)(defaultPageHeight74));
+ fprintf(psfile, "%%%%Creator: DOSBOX Virtual Printer\n");
+ fprintf(psfile, "%%%%DocumentData: Clean7Bit\n");
+ fprintf(psfile, "%%%%LanguageLevel: 2\n");
+ fprintf(psfile, "%%%%EndComments\n");
+ multiPageCounter = 1;
+ }
+
+ fprintf(psfile, "%%%%Page: %i %i\n", multiPageCounter, multiPageCounter);
+ fprintf(psfile, "%i %i scale\n", (Bit16u)(defaultPageWidth74), (Bit16u)(defaultPageHeight74));
+ fprintf(psfile, "%i %i 8 [%i 0 0 -%i 0 %i]\n", page->w, page->h, page->w, page->h, page->h);
+ fprintf(psfile, "currentfile\n");
+ fprintf(psfile, "/ASCII85Decode filter\n");
+ fprintf(psfile, "/RunLengthDecode filter\n");
+ fprintf(psfile, "image\n");
+
+ SDL_LockSurface(page);
+
+ Bit32u pix = 0;
+ Bit32u numpix = page->hpage->w;
+ ASCII85BufferPos = ASCII85CurCol = 0;
+
+ //Bit8u buffer[5];
+
+ while (pix < numpix)
+ {
+ // Compress data using RLE
+
+ if ((pix < numpix-2) && (getPixel(pix) == getPixel(pix+1)) && (getPixel(pix) == getPixel(pix+2)))
+ {
+ // Found three or more pixels with the same color
+ Bit8u sameCount = 3;
+ Bit8u col = getPixel(pix);
+ while (sameCount < 128 && sameCount+pix < numpix && col == getPixel(pix+sameCount))
+ sameCount++;
+
+ fprintASCII85(psfile, 257-sameCount);
+ fprintASCII85(psfile, 255-col);
+
+ // Skip ahead
+ pix += sameCount;
+ }
+ else
+ {
+ // Find end of heterogenous area
+ Bit8u diffCount = 1;
+ while (diffCount < 128 && diffCount+pix < numpix &&
+ (
+ (diffCount+pix < numpix-2)
+ || (getPixel(pix+diffCount) != getPixel(pix+diffCount+1))
+ || (getPixel(pix+diffCount) != getPixel(pix+diffCount+2))
+ ))
+ diffCount++;
+
+ fprintASCII85(psfile, diffCount-1);
+ for (Bit8u i=0; i<diffCount; i++)
+ fprintASCII85(psfile, 255-getPixel(pix++));
+ }
+ }
+
+ // Write EOD for RLE and ASCII85
+ fprintASCII85(psfile, 128);
+ fprintASCII85(psfile, 256);
+
+ SDL_UnlockSurface(page);
+
+ fprintf(psfile, "showpage\n");
+
+ if (multipageOutput)
+ {
+ multiPageCounter++;
+ outputHandle = psfile;
+ }
+ else
+ {
+ fprintf(psfile, "%%%%Pages: 1\n");
+ fprintf(psfile, "%%%%EOF\n");
+ fclose(psfile);
+ outputHandle = NULL;
+ }
+ }
+ else
+ {
+ // Find a page that does not exists
+ findNextName("page", ".bmp", &fname[0]);
+ SDL_SaveBMP(page, fname);
+ }
+}
+
+void CPrinter::fprintASCII85(FILE f, Bit16u b)
+{
+ if (b != 256)
+ {
+ if (b < 256)
+ ASCII85Buffer[ASCII85BufferPos++] = (Bit8u)b;
+
+ if (ASCII85BufferPos == 4 || b == 257)
+ {
+ Bit32u num = (Bit32u)ASCII85Buffer[0] << 24 | (Bit32u)ASCII85Buffer[1] << 16 | (Bit32u)ASCII85Buffer[2] << 8 | (Bit32u)ASCII85Buffer[3];
+
+ // Deal with special case
+ if (num == 0 && b != 257)
+ {
+ fprintf(f, "z");
+ if (++ASCII85CurCol >= 79)
+ {
+ ASCII85CurCol = 0;
+ fprintf(f, "\n");
+ }
+ }
+ else
+ {
+ char buffer[5];
+ for (Bit8s i=4; i>=0; i--)
+ {
+ buffer[i] = (Bit8u)((Bit32u)num % (Bit32u)85);
+ buffer[i] += 33;
+ num /= (Bit32u)85;
+ }
+
+ // Make sure a line never starts with a % (which may be mistaken as start of a comment)
+ if (ASCII85CurCol == 0 && buffer[0] == '%')
+ fprintf(f, " ");
+
+ for (int i=0; i<((b != 257)?5:ASCII85BufferPos+1); i++)
+ {
+ fprintf(f, "%c", buffer[i]);
+ if (++ASCII85CurCol >= 79)
+ {
+ ASCII85CurCol = 0;
+ fprintf(f, "\n");
+ }
+ }
+ }
+
+ ASCII85BufferPos = 0;
+ }
+
+ }
+ else // Close string
+ {
+ // Partial tupel if there are still bytes in the buffer
+ if (ASCII85BufferPos > 0)
+ {
+ for (Bit8u i = ASCII85BufferPos; i < 4; i++)
+ ASCII85Buffer[i] = 0;
+
+ fprintASCII85(f, 257);
+ }
+
+ fprintf(f, "~");
+ fprintf(f, ">\n");
+ }
+}
+
+void CPrinter::finishMultipage()
+{
+ if (outputHandle != NULL)
+ {
+ if (strcasecmp(output, "ps") == 0)
+ {
+ FILE psfile = (FILE)outputHandle;
+ fprintf(psfile, "%%%%Pages: %i\n", multiPageCounter);
+ fprintf(psfile, "%%%%EOF\n");
+ fclose(psfile);
+ }
+ else if (strcasecmp(output, "printer") == 0)
+ {
+#if defined (WIN32)
+ EndDoc(printerDC);
+#endif
+ }
+ outputHandle = NULL;
+ }
+}
+
+bool CPrinter::isBlank()
+{
+ bool blank = true;
+
+ SDL_LockSurface(page);
+
+ for (Bit16u y=0; y<page->h; y++)
+ for (Bit16u x=0; x<page->w; x++)
+ if (((Bit8u)page->pixels + x + (ypage->pitch)) != 0)
+ blank = false;
+
+ SDL_UnlockSurface(page);
+
+ return blank;
+}
+
+Bit8u CPrinter::getPixel(Bit32u num)
+{
+ // Respect the pitch
+ return ((Bit8u)page->pixels + (num % page->w) + ((num / page->w) * page->pitch));
+}
+
+void PRINTER_writedata(Bitu port,Bitu val,Bitu iolen)
+{
+ if (!defaultPrinter)
+ defaultPrinter = new CPrinter(confdpi, confwidth, confheight, confoutputDevice, confmultipageOutput);
+
+ defaultPrinter->printChar(val);
+}
+
+Bitu PRINTER_readstatus(Bitu port,Bitu iolen)
+{
+ // Don't create a CPrinter unless the program really wants to print
+ // Return standard: No error, printer online, no ack and not busy
+ if (!defaultPrinter)
+ return 0xD8;
+
+ // Printer is always online and never reports an error
+ Bit8u status = 0x18;
+
+ if (!defaultPrinter->isBusy())
+ status |= 0x80;
+
+ if (!defaultPrinter->ack())
+ status |= 0x40;
+
+ return status;
+}
+
+void PRINTER_writecontrol(Bitu port,Bitu val,Bitu iolen)
+{
+ if (defaultPrinter)
+ defaultPrinter->setAutofeed((val & 0x02) != 0);
+
+ if ((val & 0x04) && defaultPrinter)
+ defaultPrinter->resetPrinterHard();
+}
+
+Bitu PRINTER_readcontrol(Bitu port,Bitu iolen)
+{
+ // Don't create a CPrinter unless the program really wants to print
+ if (!defaultPrinter)
+ return 0x08;
+
+ return 0x08 | (defaultPrinter->getAutofeed()?0x02:0x00);
+}
+
+static void FormFeed(void)
+{
+ if (defaultPrinter)
+ defaultPrinter->formFeed();
+}
+
+static void ForceFormFeed(bool pressed)
+{
+ if (!pressed)
+ return;
+ FormFeed();
+}
+
+void PRINTER_Shutdown(Section sec)
+{
+ if (defaultPrinter)
+ {
+ delete defaultPrinter;
+ defaultPrinter = NULL;
+ }
+}
+
+void PRINTER_Init(Section* sec)
+{
+ Section_prop * section=static_cast<section_prop *="">(sec);
+ section->AddDestroyFunction(&PRINTER_Shutdown);
+
+ // Set base address of LPT1 in the BIOS variable segment
+ real_writew(0x0040, 0x0008, LPTPORT);
+
+ if(!section->Get_bool("printer"))
+ return;
+
+ confdpi = section->Get_int("dpi");
+ confwidth = section->Get_int("width");
+ confheight = section->Get_int("height");
+ strcpy(&confoutputDevice[0], section->Get_string("output"));
+ confmultipageOutput = section->Get_bool("multipage");
+
+ IO_RegisterWriteHandler(LPTPORT,PRINTER_writedata,0xFF); // LPT1 DATA
+ IO_RegisterReadHandler(LPTPORT+1,PRINTER_readstatus,0xFF); // LPT1 STATUS
+ IO_RegisterWriteHandler(LPTPORT+2,PRINTER_writecontrol,0xFF); // LPT1 CONTROL
+ IO_RegisterReadHandler(LPTPORT+2,PRINTER_readcontrol,0xFF); // LPT1 CONTROL
+
+ MAPPER_AddHandler(ForceFormFeed,MK_f8,MMOD2,"formfeed","Send FF to printer");
+}
+
+#endif
diff --git a/src/ints/bios.cpp b/src/ints/bios.cpp
index 8c560dc..78abaab 100644
--- a/src/ints/bios.cpp
+++ b/src/ints/bios.cpp
@@ -370,16 +370,58 @@ static Bitu INT12_Handler(void) {
return CBRET_NONE;
};</section_prop></page-></page-></numverttabs;></numhoriztabs;></png.h></math.h>
+
+#ifdef C_PRINTER
+// Get status of the num-th (0-3) parallel port
+static Bit8u getPrinterStatus(Bit8u num)
+{
+ Bit8u stat = IO_ReadB(real_readw(0x0040, 0x0008+num2)+1);
+
+ // Bit3 == 0 or Bit4 == 0 => Error, report an time-out
+ if ((stat & 0x18) != 0x18)
+ return 0x01;
+
+ // No error, printer is online
+ Bit8u ret = 0x10;
+
+ // Forward ACK message
+ if (!(stat & 0x40))
+ ret |= 0x40;
+
+ // Printer busy?
+ if (stat & 0x80)
+ ret |= 0x80;
+
+ return ret;
+}
+#endif
+
static Bitu INT17_Handler(void) {
- LOG(LOG_BIOS,LOG_NORMAL)("INT17:Function %X",reg_ah);
+ //LOG(LOG_BIOS,LOG_NORMAL)("INT17:Function %X",reg_ah);
switch(reg_ah) {
case 0x00: / PRINTER: Write Character /
+#ifdef C_PRINTER
+ IO_WriteB(real_readw(0x0040, 0x0008+reg_dx2), reg_al);
+ // FIXME: Possible data loss
+ reg_ah=getPrinterStatus(reg_dx);
+#else
reg_ah=1; / Report a timeout /
+#endif
break;
case 0x01: / PRINTER: Initialize port /
+#ifdef C_PRINTER
+ IO_WriteB(real_readw(0x0040, 0x0008+reg_dx2)+2, IO_ReadB(real_readw(0x0040, 0x0008+reg_dx2)+2) | 0x04);
+ // FIXME: Possible data loss
+ reg_ah=getPrinterStatus(reg_dx);
+#endif
break;
case 0x02: / PRINTER: Get Status /
+#ifdef C_PRINTER
+ // FIXME: Possible data loss
+ reg_ah=getPrinterStatus(reg_dx);
+#else
reg_ah=0;
+#endif
break;
case 0x20: / Some sort of printerdriver install check/
break;
Logged In: YES
user_id=995396
Originator: YES
You can download it from here too: http://s244184881.online.de/downloads/virtual-printer.patch