ESC/P 2: 4 versions, filtering by version, selectable paper.

The four versions are:
- EX-1000 and 7 other early printers (including FX-80, the only Epson
  available OOTB for Windows 1.03), have ESC i and ESC j.
- 9-pin ESC/P, a superset of EX-1000 besides ESC i and ESC j.
- 24-pin ESC/P in 360 DPI instead of 240.
- ESC/P 2 with raster graphics.

As for paper, four sizes: Letter, A4, Legal, B4. The former ones are
mainly for EX-800, the latter two are sideways and meant for EX-1000.

I did some other minor changes, like converting a bunch of defines to enum.
This commit is contained in:
Lili1228
2026-01-31 14:41:04 +01:00
parent 8e1acfa3b1
commit e7fee34332
2 changed files with 373 additions and 211 deletions

View File

@@ -47,4 +47,8 @@
#define A4_PAGE_WIDTH 8.25
#define A4_PAGE_HEIGHT 11.75
/* Standard B4 */
#define B4_PAGE_WIDTH 9.875
#define B4_PAGE_HEIGHT 13.875
#endif /*EMU_PLAT_FALLTHROUGH_H*/

View File

@@ -72,31 +72,38 @@
#include <86box/prt_devs.h>
#include <86box/prt_papersizes.h>
enum {
LANG_EX1000 = 0, // last printer with ESC i and j
LANG_9PIN,
LANG_ESCP, // also known as 24/48-pin
LANG_ESCP2
};
enum {
PAPER_LETTER = 0,
PAPER_A4,
PAPER_LEGAL_SIDE,
PAPER_B4_SIDE
};
/* Default page values (for now.) */
#define COLOR_BLACK 7 << 5
#define PAGE_WIDTH LETTER_PAGE_WIDTH
#define PAGE_HEIGHT LETTER_PAGE_HEIGHT
#if 0
#define PAGE_LMARGIN 0.0
#define PAGE_RMARGIN PAGE_WIDTH
#define PAGE_TMARGIN 0.0
#define PAGE_BMARGIN PAGE_HEIGHT
#endif
#define PAGE_DPI 360
#define PAGE_CPI 10.0 /* standard 10 cpi */
#define PAGE_CPI 10.0 /* standard310 cpi */
#define PAGE_LPI 6.0 /* standard 6 lpi */
/* FreeType library handles - global so they can be shared. */
FT_Library ft_lib = NULL;
/* The fonts. */
#define FONT_DEFAULT 0
#define FONT_ROMAN 1
#define FONT_SANSSERIF 2
#define FONT_COURIER 3
#define FONT_SCRIPT 4
#define FONT_OCRA 5
#define FONT_OCRB 6
enum {
FONT_DEFAULT = 0,
FONT_ROMAN,
FONT_SANSSERIF,
FONT_COURIER,
FONT_SCRIPT,
FONT_OCRA,
FONT_OCRB
};
/* Font styles. */
#define STYLE_PROP 0x0001
@@ -125,20 +132,22 @@ FT_Library ft_lib = NULL;
#define QUALITY_LQ 0x02
/* Typefaces. */
#define TYPEFACE_ROMAN 0
#define TYPEFACE_SANSSERIF 1
#define TYPEFACE_COURIER 2
#define TYPEFACE_PRESTIGE 3
#define TYPEFACE_SCRIPT 4
#define TYPEFACE_OCRB 5
#define TYPEFACE_OCRA 6
#define TYPEFACE_ORATOR 7
#define TYPEFACE_ORATORS 8
#define TYPEFACE_SCRIPTC 9
#define TYPEFACE_ROMANT 10
#define TYPEFACE_SANSSERIFH 11
#define TYPEFACE_SVBUSABA 30
#define TYPEFACE_SVJITTRA 31
enum {
TYPEFACE_ROMAN = 0,
TYPEFACE_SANSSERIF,
TYPEFACE_COURIER,
TYPEFACE_PRESTIGE,
TYPEFACE_SCRIPT,
TYPEFACE_OCRB,
TYPEFACE_OCRA,
TYPEFACE_ORATOR,
TYPEFACE_ORATORS,
TYPEFACE_SCRIPTC,
TYPEFACE_ROMANT,
TYPEFACE_SANSSERIFH,
TYPEFACE_SVBUSABA = 30,
TYPEFACE_SVJITTRA
};
/* Some helper macros. */
#define PARAM16(x) (dev->esc_parms[x + 1] * 256 + dev->esc_parms[x])
@@ -164,6 +173,9 @@ typedef struct escp_t {
pc_timer_t pulse_timer;
pc_timer_t timeout_timer;
int lang;
int paper_size;
char page_fn[260];
uint8_t color;
@@ -423,6 +435,23 @@ fill_palette(uint8_t redmax, uint8_t greenmax, uint8_t bluemax, uint8_t colorID,
static void
reset_printer(escp_t *dev)
{
dev->top_margin = dev->left_margin = 0.0;
dev->right_margin = dev->page_width;
switch (dev->paper_size) {
case PAPER_A4:
dev->page_height = A4_PAGE_HEIGHT;
break;
case PAPER_LEGAL_SIDE:
dev->page_height = LEGAL_PAGE_WIDTH;
break;
case PAPER_B4_SIDE:
dev->page_height = B4_PAGE_WIDTH;
break;
case PAPER_LETTER:
default:
dev->page_height = LETTER_PAGE_HEIGHT;
}
dev->bottom_margin = dev->page_height;
/* TODO: these should be configurable. */
dev->color = COLOR_BLACK;
dev->curr_x = dev->curr_y = 0.0;
@@ -430,23 +459,20 @@ reset_printer(escp_t *dev)
dev->fss_seen = 0;
dev->esc_pending = 0;
dev->esc_parms_req = dev->esc_parms_curr = 0;
dev->top_margin = dev->left_margin = 0.0;
dev->right_margin = dev->page_width = PAGE_WIDTH;
dev->bottom_margin = dev->page_height = PAGE_HEIGHT;
dev->lpi = PAGE_LPI;
dev->linespacing = 1.0 / dev->lpi;
dev->cpi = PAGE_CPI;
dev->curr_char_table = 1;
dev->font_style = 0;
dev->print_quality = QUALITY_DRAFT;
dev->extra_intra_space = 0.0;
dev->print_upper_control = 1;
dev->bg_remaining_bytes = 0;
dev->density_k = 0;
dev->density_l = 1;
dev->density_y = 2;
dev->density_z = 3;
dev->char_tables[0] = 0; /* italics */
dev->lpi = PAGE_LPI;
dev->linespacing = 1.0 / dev->lpi;
dev->cpi = PAGE_CPI;
dev->curr_char_table = 1;
dev->font_style = 0;
dev->print_quality = QUALITY_DRAFT;
dev->extra_intra_space = 0.0;
dev->print_upper_control = 1;
dev->bg_remaining_bytes = 0;
dev->density_k = 0;
dev->density_l = 1;
dev->density_y = 2;
dev->density_z = 3;
dev->char_tables[0] = 0; /* italics */
dev->char_tables[1] = dev->char_tables[2] = dev->char_tables[3] = 437; /* all other tables use CP437 */
dev->defined_unit = -1.0;
dev->multipoint_mode = 0;
@@ -633,73 +659,55 @@ process_char(escp_t *dev, uint8_t ch)
escp_log("Command pending=%02x, font path=%s\n", dev->esc_pending, dev->fontpath);
switch (dev->esc_pending) {
case 0x02: // Undocumented
case 0x0a: // Reverse line feed
case 0x0c: // Return to top of current page
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 0x31: // Select 7/60-inch line spacing
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 0x38: // Disable paper-out detector
case 0x39: // Enable paper-out detector
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 0x5e: // Enable printing of all character codes on next character
case 0x67: // Select 10.5-point, 15-cpi (ESC g)
case '#': // Cancel MSB control
case '0': // Select 1/8-inch line spacing
case '1': // Select 7/60-inch line spacing
case '2': // Select 1/6-inch line spacing
case '4': // Select italic font
case '5': // Cancel italic font
case '6': // Enable printing of upper control codes
case '7': // Enable upper control codes
case '8': // Disable paper-out detector
case '9': // Enable paper-out detector
case '<': // Unidirectional mode (one line)
case '=': // Set MSB to 0
case '>': // Set MSB to 1
case '@': // Initialize printer
case 'E': // Select bold font
case 'F': // Cancel bold font
case 'G': // Select double-strike printing
case 'H': // Cancel double-strike printing
case 'M': // Select 10.5-point, 12-cpi
case 'O': // Cancel bottom margin
case 'P': // Select 10.5-point, 10-cpi
case 'T': // Cancel superscript/subscript printing
case '^': // Enable printing of all character codes on next character
dev->esc_parms_req = 0;
break;
case 'g': // Select 10.5-point, 15-cpi
dev->esc_parms_req = 0;
if (dev->lang == LANG_EX1000) {
dev->esc_pending = 0;
return 1;
}
break;
case 0x0a: // Reverse line feed (IBM's ESC LF)
case 0x0c: // Return to top of current page (IBM's ESC FF)
case 0x834: // Select italic font (FS 4) (= ESC 4)
case 0x835: // Cancel italic font (FS 5) (= ESC 5)
case 0x846: // Select forward feed mode (FS F)
case 0x852: // Select reverse feed mode (FS R)
dev->esc_parms_req = 0;
if (dev->lang < LANG_ESCP2) {
dev->esc_pending = 0;
return 1;
}
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 0x49: // Select character type and print pitch
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 0x66: // Absolute horizontal tab in columns [conflict]
case 0x68: // Select double or quadruple size
case 0x69: // Immediate print
case 0x6a: // Reverse paper feed
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 0x73: // Select low-speed mode (ESC s)
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)
case 0x7e: // Select/Deselect slash zero (ESC ~)
case 'h': // Select double or quadruple size (IBM's)
case '~': // Select/Deselect slash zero (IBM's?)
case 0x832: // Select 1/6-inch line spacing (FS 2) (= ESC 2)
case 0x833: // Set n/360-inch line spacing (FS 3) (= ESC +)
case 0x841: // Set n/60-inch line spacing (FS A) (= ESC A)
@@ -708,53 +716,142 @@ process_char(escp_t *dev, uint8_t ch)
case 0x849: // Select character table (FS I) (= ESC t)
case 0x853: // Select High Speed/High Density elite pitch (FS S)
case 0x856: // Turn double-height printing on/off (FS V) (= ESC w)
if (dev->lang < LANG_ESCP2) {
dev->esc_parms_req = 0;
dev->esc_pending = 0;
return 1;
}
case '+': // Set n/360-inch line spacing
if (dev->lang < LANG_ESCP) {
dev->esc_parms_req = 0;
dev->esc_pending = 0;
return 1;
}
case 'w': // Turn double-height printing on/off
if (dev->lang == LANG_EX1000) {
dev->esc_parms_req = 0;
dev->esc_pending = 0;
return 1;
}
case 0x19: // Control paper loading/ejecting (ESC EM)
case ' ': // Set intercharacter space
case '!': // Master select
case '-': // Turn underline on/off
case '/': // Select vertical tab channel
case '3': // Set n/180-inch line spacing
case 'A': // Set n/60-inch line spacing
case 'C': // Set page length in lines
case 'I': // Select character type and print pitch
case 'J': // Advance print position vertically
case 'N': // Set bottom margin
case 'Q': // Set right margin
case 'R': // Select an international character set
case 'S': // Select superscript/subscript printing
case 'U': // Turn unidirectional mode on/off
case 'W': // Turn double-width printing on/off
case 'a': // Select justification
case 'k': // Select typeface
case 'l': // Set left margin
case 'p': // Turn proportional mode on/off
case 'r': // Select printing color
case 's': // Select low-speed mode
case 't': // Select character table
case 'x': // Select LQ or draft
dev->esc_parms_req = 1;
break;
case 'f': // Absolute horizontal tab in columns
if (dev->lang != LANG_9PIN) {
dev->esc_parms_req = 0;
dev->esc_pending = 0;
return 1;
}
dev->esc_parms_req = 1;
break;
case 'i': // Immediate print
case 'j': // Reverse paper feed
if (dev->lang != LANG_EX1000) {
dev->esc_parms_req = 0;
dev->esc_pending = 0;
return 1;
}
dev->esc_parms_req = 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)
case 0x65: // Set vertical tab stops every n lines (ESC e)
case 'c': // Set horizontal motion index (HMI)
if (dev->lang < LANG_ESCP2) {
dev->esc_parms_req = 0;
dev->esc_pending = 0;
return 1;
}
case '$': // Set absolute horizontal print position
case '?': // Reassign bit-image mode
case 'K': // Select 60-dpi graphics
case 'L': // Select 120-dpi graphics
case 'Y': // Select 120-dpi, double-speed graphics
case 'Z': // Select 240-dpi graphics
case '\\': // Set relative horizontal print position
case 0x85a: // Print 24-bit hex-density graphics (FS Z)
dev->esc_parms_req = 2;
break;
case 'e': // Set vertical tab stops every n lines
if (dev->lang != LANG_9PIN) {
dev->esc_parms_req = 0;
dev->esc_pending = 0;
return 1;
}
dev->esc_parms_req = 2;
break;
case 0x2a: // Select bit image (ESC *)
case 0x58: // Select font by pitch and point (ESC X)
case 'X': // Select font by pitch and point
if (dev->lang < LANG_ESCP2) {
dev->esc_parms_req = 0;
dev->esc_pending = 0;
return 1;
}
case '*': // Select bit image
dev->esc_parms_req = 3;
break;
case 0x5b: // Select character height, width, line spacing
case '[': // Select character height, width, line spacing (IBM's)
if (dev->lang < LANG_ESCP2) {
dev->esc_parms_req = 0;
dev->esc_pending = 0;
return 1;
}
dev->esc_parms_req = 7;
break;
case 0x62: // Set vertical tabs in VFU channels (ESC b)
case 0x42: // Set vertical tabs (ESC B)
case 'b': // Set vertical tabs in VFU channels
case 'B': // Set vertical tabs
dev->num_vertical_tabs = 0;
return 1;
case 0x44: // Set horizontal tabs (ESC D)
case 'D': // Set horizontal tabs
dev->num_horizontal_tabs = 0;
return 1;
case 0x25: // Select user-defined set (ESC %)
case 0x26: // Define user-defined characters (ESC &)
case 0x3a: // Copy ROM to RAM (ESC :)
case '%': // Select user-defined set
case '&': // Define user-defined characters
case ':': // Copy ROM to RAM
escp_log("ESC/P: User-defined characters not supported (0x%02x).\n", dev->esc_pending);
return 1;
case 0x28: // Two bytes sequence
case '(': // Two bytes sequence
if (dev->lang == LANG_EX1000) {
dev->esc_parms_req = 0;
dev->esc_pending = 0;
}
/* return and wait for second ESC byte */
return 1;
case 0x2e:
fatal("ESC/P: Print Raster Graphics (2E) command is not implemented.\nTerminating the emulator to avoid endless PNG generation.\n");
exit(-1);
case '.':
if (dev->lang >= LANG_ESCP2) {
fatal("ESC/P: Print Raster Graphics (2E) command is not implemented.\nTerminating the emulator to avoid endless PNG generation.\n");
exit(-1);
}
dev->esc_parms_req = 0;
dev->esc_pending = 0;
return 1;
default:
escp_log("ESC/P: Unknown command ESC %c (0x%02x). Unable to skip parameters.\n",
@@ -776,50 +873,67 @@ process_char(escp_t *dev, uint8_t ch)
escp_log("Two-byte command pending=%03x, font path=%s\n", dev->esc_pending, dev->fontpath);
switch (dev->esc_pending) {
case 0x0242: // Bar code setup and print (ESC (B)
case 0x025e: // Print data as characters (ESC (^)
if (dev->lang < LANG_ESCP2)
default:
/* ESC ( commands are always followed by a "number of parameters" word parameter */
dev->esc_pending = 0x101; /* dummy value to be checked later */
case 0x0242: // Bar code setup and print (ESC (B)
dev->esc_parms_req = 2;
break;
case 0x0255: // Set unit (ESC (U)
if (dev->lang < LANG_ESCP2) {
dev->esc_parms_req = 2;
dev->esc_pending = 0x101;
break;
}
dev->esc_parms_req = 3;
break;
case 0x0243: // Set page length in defined unit (ESC (C)
case 0x0256: // Set absolute vertical print position (ESC (V)
case 0x0276: // Set relative vertical print position (ESC (v)
if (dev->lang < LANG_ESCP2) {
dev->esc_parms_req = 2;
dev->esc_pending = 0x101;
break;
}
dev->esc_parms_req = 4;
break;
case 0x0228: // Assign character table (ESC (t)
case 0x022d: // Select line/score (ESC (-)
if (dev->lang == LANG_9PIN) {
dev->esc_parms_req = 2;
dev->esc_pending = 0x101;
break;
}
case 0x0228: // Assign character table (ESC (t)
dev->esc_parms_req = 5;
break;
case 0x0263: // Set page format (ESC (c)
if (dev->lang < LANG_ESCP2) {
dev->esc_parms_req = 2;
dev->esc_pending = 0x101;
break;
}
dev->esc_parms_req = 6;
break;
default:
/* ESC ( commands are always followed by a "number of parameters" word parameter */
dev->esc_parms_req = 2;
dev->esc_pending = 0x101; /* dummy value to be checked later */
return 1;
}
/* If we need parameters, return and wait for them to appear. */
if (dev->esc_parms_req > 0)
return 1;
// Wait for more parameters.
return 1;
}
/* Ignore VFU channel setting. */
if (dev->esc_pending == 0x62) {
dev->esc_pending = 0x42;
if (dev->esc_pending == 'b') {
dev->esc_pending = 'B';
return 1;
}
/* Collect vertical tabs. */
if (dev->esc_pending == 0x42) {
if (dev->esc_pending == 'B') {
/* check if we're done */
if ((ch == 0) || (dev->num_vertical_tabs > 0 && dev->vertical_tabs[dev->num_vertical_tabs - 1] > (double) ch * dev->linespacing)) {
dev->esc_pending = 0;
@@ -830,7 +944,7 @@ process_char(escp_t *dev, uint8_t ch)
}
/* Collect horizontal tabs. */
if (dev->esc_pending == 0x44) {
if (dev->esc_pending == 'D') {
/* check if we're done... */
if ((ch == 0) || (dev->num_horizontal_tabs > 0 && dev->horizontal_tabs[dev->num_horizontal_tabs - 1] > (double) ch * (1.0 / dev->cpi))) {
dev->esc_pending = 0;
@@ -887,7 +1001,7 @@ process_char(escp_t *dev, uint8_t ch)
}
break;
case 0x21: /* master select (ESC !) */
case '!': /* master select */
dev->cpi = (dev->esc_parms[0]) & 0x01 ? 12.0 : 10.0;
/* Reset first seven bits. */
@@ -914,11 +1028,11 @@ process_char(escp_t *dev, uint8_t ch)
update_font(dev);
break;
case 0x23: /* cancel MSB control (ESC #) */
case '#': /* cancel MSB control */
dev->msb = 255;
break;
case 0x24: /* set abs horizontal print position (ESC $) */
case '$': /* set abs horizontal print position */
unit_size = dev->defined_unit;
if (unit_size < 0)
unit_size = 60.0;
@@ -932,12 +1046,12 @@ process_char(escp_t *dev, uint8_t ch)
setup_bit_image(dev, 40, PARAM16(0));
break;
case 0x2a: /* select bit image (ESC *) */
case '*': /* select bit image */
setup_bit_image(dev, dev->esc_parms[0], PARAM16(1));
break;
case 0x2b: /* set n/360-inch line spacing (ESC +) */
case 0x833: /* Set n/360-inch line spacing (FS 3) */
case '+': /* set n/360-inch line spacing */
dev->linespacing = (double) dev->esc_parms[0] / 360.0;
break;
@@ -951,58 +1065,58 @@ process_char(escp_t *dev, uint8_t ch)
update_font(dev);
break;
case 0x2f: /* select vertical tab channel (ESC /) */
case '/': /* select vertical tab channel */
/* Ignore */
break;
case 0x30: /* select 1/8-inch line spacing (ESC 0) */
case '0': /* select 1/8-inch line spacing */
dev->linespacing = 1.0 / 8.0;
break;
case 0x31: /* select 7/60-inch line spacing */
case '1': /* select 7/60-inch line spacing */
dev->linespacing = 7.0 / 60.0;
break;
case 0x32: /* select 1/6-inch line spacing (ESC 2) */
case '2': /* select 1/6-inch line spacing */
dev->linespacing = 1.0 / 6.0;
break;
case 0x33: /* set n/180-inch line spacing (ESC 3) */
case '3': /* set n/180-inch line spacing */
dev->linespacing = (double) dev->esc_parms[0] / 180.0;
break;
case 0x34: /* select italic font (ESC 4) */
case '4': /* select italic font */
dev->font_style |= STYLE_ITALICS;
update_font(dev);
break;
case 0x35: /* cancel italic font (ESC 5) */
case '5': /* cancel italic font */
dev->font_style &= ~STYLE_ITALICS;
update_font(dev);
break;
case 0x36: /* enable printing of upper control codes (ESC 6) */
case '6': /* enable printing of upper control codes */
dev->print_upper_control = 1;
break;
case 0x37: /* enable upper control codes (ESC 7) */
case '7': /* enable upper control codes */
dev->print_upper_control = 0;
break;
case 0x3c: /* unidirectional mode (one line) (ESC <) */
case '<': /* unidirectional mode (one line) */
/* We don't have a print head, so just
* ignore this. */
break;
case 0x3d: /* set MSB to 0 (ESC =) */
case '=': /* set MSB to 0 */
dev->msb = 0;
break;
case 0x3e: /* set MSB to 1 (ESC >) */
case '>': /* set MSB to 1 */
dev->msb = 1;
break;
case 0x3f: /* reassign bit-image mode (ESC ?) */
case '?': /* reassign bit-image mode */
if (dev->esc_parms[0] == 'K')
dev->density_k = dev->esc_parms[1];
if (dev->esc_parms[0] == 'L')
@@ -1013,16 +1127,16 @@ process_char(escp_t *dev, uint8_t ch)
dev->density_z = dev->esc_parms[1];
break;
case 0x40: /* initialize printer (ESC @) */
case '@': /* initialize printer */
reset_printer(dev);
break;
case 0x41: /* set n/60-inch line spacing */
case 0x841:
case 'A': /* set n/60-inch line spacing */
case 0x841: // FS A
dev->linespacing = (double) dev->esc_parms[0] / 60.0;
break;
case 0x43: /* set page length in lines (ESC C) */
case 'C': /* set page length in lines */
if (dev->esc_parms[0] != 0) {
dev->page_height = dev->bottom_margin = (double) dev->esc_parms[0] * dev->linespacing;
} else { /* == 0 => Set page length in inches */
@@ -1033,69 +1147,69 @@ process_char(escp_t *dev, uint8_t ch)
}
break;
case 0x45: /* select bold font (ESC E) */
case 'E': /* select bold font */
dev->font_style |= STYLE_BOLD;
update_font(dev);
break;
case 0x46: /* cancel bold font (ESC F) */
case 'F': /* cancel bold font */
dev->font_style &= ~STYLE_BOLD;
update_font(dev);
break;
case 0x47: /* select double-strike printing (ESC G) */
case 'G': /* select double-strike printing */
dev->font_style |= STYLE_DOUBLESTRIKE;
break;
case 0x48: /* cancel double-strike printing (ESC H) */
case 'H': /* cancel double-strike printing */
dev->font_style &= ~STYLE_DOUBLESTRIKE;
break;
case 0x4a: /* advance print pos vertically (ESC J n) */
case 'J': /* advance print pos vertically */
dev->curr_y += (double) ((double) dev->esc_parms[0] / 180.0);
if (dev->curr_y > dev->bottom_margin)
new_page(dev, 1, 0);
break;
case 0x4b: /* select 60-dpi graphics (ESC K) */
case 'K': /* select 60-dpi graphics */
/* TODO: graphics stuff */
setup_bit_image(dev, dev->density_k, PARAM16(0));
break;
case 0x4c: /* select 120-dpi graphics (ESC L) */
case 'L': /* select 120-dpi graphics */
/* TODO: graphics stuff */
setup_bit_image(dev, dev->density_l, PARAM16(0));
break;
case 0x4d: /* select 10.5-point, 12-cpi (ESC M) */
case 'M': /* select 10.5-point, 12-cpi */
dev->cpi = 12.0;
dev->hmi = -1;
dev->multipoint_mode = 0;
update_font(dev);
break;
case 0x4e: /* set bottom margin (ESC N) */
case 'N': /* set bottom margin */
dev->top_margin = 0.0;
dev->bottom_margin = (double) dev->esc_parms[0] * dev->linespacing;
break;
case 0x4f: /* cancel bottom (and top) margin */
case 'O': /* cancel bottom (and top) margin */
dev->top_margin = 0.0;
dev->bottom_margin = dev->page_height;
break;
case 0x50: /* select 10.5-point, 10-cpi (ESC P) */
case 'P': /* select 10.5-point, 10-cpi */
dev->cpi = 10.0;
dev->hmi = -1;
dev->multipoint_mode = 0;
update_font(dev);
break;
case 0x51: /* set right margin */
case 'Q': /* set right margin */
dev->right_margin = ((double) dev->esc_parms[0] - 1.0) / dev->cpi;
break;
case 0x52: /* select an intl character set (ESC R) */
case 'R': /* select an intl character set */
if ((dev->esc_parms[0] <= 13) || (dev->esc_parms[0] == 64)) {
if (dev->esc_parms[0] == 64)
dev->esc_parms[0] = 14;
@@ -1115,7 +1229,7 @@ process_char(escp_t *dev, uint8_t ch)
}
break;
case 0x53: /* select superscript/subscript printing (ESC S) */
case 'S': /* select superscript/subscript printing */
if ((dev->esc_parms[0] == 0) || (dev->esc_parms[0] == '0'))
dev->font_style |= STYLE_SUBSCRIPT;
if ((dev->esc_parms[0] == 1) || (dev->esc_parms[1] == '1'))
@@ -1123,16 +1237,16 @@ process_char(escp_t *dev, uint8_t ch)
update_font(dev);
break;
case 0x54: /* cancel superscript/subscript printing (ESC T) */
case 'T': /* cancel superscript/subscript printing */
dev->font_style &= 0xFFFF - STYLE_SUPERSCRIPT - STYLE_SUBSCRIPT;
update_font(dev);
break;
case 0x55: /* turn unidirectional mode on/off (ESC U) */
case 'U': /* turn unidirectional mode on/off */
/* We don't have a print head, so just ignore this. */
break;
case 0x57: /* turn double-width printing on/off (ESC W) */
case 'W': /* turn double-width printing on/off */
if (!dev->multipoint_mode) {
dev->hmi = -1;
if ((dev->esc_parms[0] == 0) || (dev->esc_parms[0] == '0'))
@@ -1143,7 +1257,7 @@ process_char(escp_t *dev, uint8_t ch)
}
break;
case 0x58: /* select font by pitch and point (ESC X) */
case 'X': /* select font by pitch and point */
dev->multipoint_mode = 1;
/* Copy currently non-multipoint CPI if no value was set so far. */
if (dev->multipoint_cpi == 0.0) {
@@ -1165,17 +1279,17 @@ process_char(escp_t *dev, uint8_t ch)
update_font(dev);
break;
case 0x59: /* select 120-dpi, double-speed graphics (ESC Y) */
case 'Y': /* select 120-dpi, double-speed graphics */
/* TODO: graphics stuff */
setup_bit_image(dev, dev->density_y, PARAM16(0));
break;
case 0x5a: /* select 240-dpi graphics (ESC Z) */
case 'Z': /* select 240-dpi graphics */
/* TODO: graphics stuff */
setup_bit_image(dev, dev->density_z, PARAM16(0));
break;
case 0x5c: /* set relative horizontal print pos (ESC \) */
case '\\': /* set relative horizontal print pos */
rel_move = PARAM16(0);
unit_size = dev->defined_unit;
if (unit_size < 0)
@@ -1183,16 +1297,16 @@ process_char(escp_t *dev, uint8_t ch)
dev->curr_x += ((double) rel_move / unit_size);
break;
case 0x61: /* select justification (ESC a) */
case 'a': /* select justification */
/* Ignore. */
break;
case 0x63: /* set horizontal motion index (HMI) (ESC c) */
case 'c': /* set horizontal motion index (HMI) */
dev->hmi = (double) PARAM16(0) / 360.0;
dev->extra_intra_space = 0.0;
break;
case 0x67: /* select 10.5-point, 15-cpi (ESC g) */
case 'g': /* select 10.5-point, 15-cpi */
dev->cpi = 15;
dev->hmi = -1;
dev->multipoint_mode = 0;
@@ -1204,7 +1318,7 @@ process_char(escp_t *dev, uint8_t ch)
dev->linespacing *= -1;
break;
case 0x6a: // Reverse paper feed (ESC j)
case 'j': // Reverse paper feed (ESC j)
reverse = (double) PARAM16(0) / (double) 216.0;
reverse = dev->curr_y - reverse;
if (reverse < dev->left_margin)
@@ -1213,20 +1327,20 @@ process_char(escp_t *dev, uint8_t ch)
dev->curr_y = reverse;
break;
case 0x6b: /* select typeface (ESC k) */
case 'k': /* select typeface */
if ((dev->esc_parms[0] <= 11) || (dev->esc_parms[0] == 30) ||
(dev->esc_parms[0] == 31))
dev->lq_typeface = dev->esc_parms[0];
update_font(dev);
break;
case 0x6c: /* set left margin (ESC 1) */
case 'l': /* set left margin */
dev->left_margin = ((double) dev->esc_parms[0] - 1.0) / dev->cpi;
if (dev->curr_x < dev->left_margin)
dev->curr_x = dev->left_margin;
break;
case 0x70: /* Turn proportional mode on/off (ESC p) */
case 'p': /* Turn proportional mode on/off */
if ((dev->esc_parms[0] == 0) || (dev->esc_parms[0] == '0'))
dev->font_style &= ~STYLE_PROP;
if ((dev->esc_parms[0] == 1) || (dev->esc_parms[0] == '1')) {
@@ -1238,18 +1352,18 @@ process_char(escp_t *dev, uint8_t ch)
update_font(dev);
break;
case 0x72: /* select printing color (ESC r) */
case 'r': /* select printing color */
if (dev->esc_parms[0] == 0 || dev->esc_parms[0] > 6)
dev->color = COLOR_BLACK;
else
dev->color = dev->esc_parms[0] << 5;
break;
case 0x73: /* select low-speed mode (ESC s) */
case 's': /* select low-speed mode */
/* Ignore. */
break;
case 0x74: /* select character table (ESC t) */
case 't': /* select character table */
case 0x849: /* Select character table (FS I) */
if (dev->esc_parms[0] < 4) {
dev->curr_char_table = dev->esc_parms[0];
@@ -1260,7 +1374,7 @@ process_char(escp_t *dev, uint8_t ch)
update_font(dev);
break;
case 0x77: /* turn double-height printing on/off (ESC w) */
case 'w': /* turn double-height printing on/off */
if (!dev->multipoint_mode) {
if ((dev->esc_parms[0] == 0) || (dev->esc_parms[0] == '0'))
dev->font_style &= ~STYLE_DOUBLEHEIGHT;
@@ -1270,7 +1384,7 @@ process_char(escp_t *dev, uint8_t ch)
}
break;
case 0x78: /* select LQ or draft (ESC x) */
case 'x': /* select LQ or draft */
if ((dev->esc_parms[0] == 0) || (dev->esc_parms[0] == '0')) {
dev->print_quality = QUALITY_DRAFT;
dev->font_style |= STYLE_CONDENSED;
@@ -1523,9 +1637,12 @@ process_char(escp_t *dev, uint8_t ch)
dev->esc_seen = 1;
return 1;
case 0x1c: /* FS (IBM commands) */
dev->fss_seen = 1;
return 1;
case 0x1c: /* FS (IBM Proprinter II)
TODO: Make an IBM printer. */
if (dev->lang == LANG_ESCP2) {
dev->fss_seen = 1;
return 1;
}
default:
/* This is a printable character -> print it. */
@@ -1998,6 +2115,8 @@ escp_init(const device_t *info)
dev->lpt = lpt_attach(write_data, write_ctrl, strobe, read_status, read_ctrl, NULL, NULL, dev);
dev->lang = device_get_config_int("language");
rom_get_full_path(dev->fontpath, "roms/printer/fonts/");
/* Create a full pathname for the font files. */
@@ -2014,9 +2133,28 @@ escp_init(const device_t *info)
plat_dir_create(dev->pagepath);
path_slash(dev->pagepath);
dev->page_width = PAGE_WIDTH;
dev->page_height = PAGE_HEIGHT;
dev->dpi = PAGE_DPI;
dev->paper_size = device_get_config_int("paper_size");
switch (dev->paper_size) {
case PAPER_A4:
dev->page_width = A4_PAGE_WIDTH;
dev->page_height = A4_PAGE_HEIGHT;
break;
case PAPER_LEGAL_SIDE:
dev->page_height = LEGAL_PAGE_WIDTH;
dev->page_width = LEGAL_PAGE_HEIGHT;
break;
case PAPER_B4_SIDE:
dev->page_height = B4_PAGE_WIDTH;
dev->page_width = B4_PAGE_HEIGHT;
break;
case PAPER_LETTER:
default:
dev->page_width = LETTER_PAGE_WIDTH;
dev->page_height = LETTER_PAGE_HEIGHT;
}
dev->dpi = dev->lang >= LANG_ESCP ? 360 : 240;
/* Create 8-bit grayscale buffer for the page. */
dev->page = (psurface_t *) malloc(sizeof(psurface_t));
@@ -2090,6 +2228,29 @@ escp_close(void *priv)
// clang-format off
#if 0
static const device_config_t lpt_prt_escp_config[] = {
{ .name = "", .description = "", .type = CONFIG_END }
};
#endif
static const device_config_t lpt_prt_escp_config[] = {
{
.name = "language",
.description = "Language",
.type = CONFIG_SELECTION,
.default_string = NULL,
.default_int = LANG_ESCP2,
.file_filter = NULL,
.spinner = { 0 },
.selection = {
{ .description = "EX-1000", .value = LANG_EX1000 },
#if 0
{ .description = "9-pin", .value = LANG_9PIN },
{ .description = "ESC/P", .value = LANG_ESCP },
#endif
{ .description = "ESC/P 2", .value = LANG_ESCP2 },
{ .description = "" }
},
.bios = { { 0 } }
},
{
.name = "paper_size",
.description = "Paper Size",
@@ -2099,15 +2260,16 @@ static const device_config_t lpt_prt_escp_config[] = {
.file_filter = NULL,
.spinner = { 0 },
.selection = {
{ .description = "Letter", .value = 0 },
{ .description = "A4", .value = 1 },
{ .description = "Letter", .value = PAPER_LETTER },
{ .description = "A4", .value = PAPER_A4 },
{ .description = "Legal (sideways)", .value = PAPER_LEGAL_SIDE },
{ .description = "B4 (sideways)", .value = PAPER_B4_SIDE },
{ .description = "" }
},
.bios = { { 0 } }
},
{ .name = "", .description = "", .type = CONFIG_END }
};
#endif
// clang-format on
const device_t lpt_prt_escp_device = {
@@ -2121,9 +2283,5 @@ const device_t lpt_prt_escp_device = {
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
#if 0
.config = lpt_prt_escp_config
#else
.config = NULL
#endif
};