forked from 86Box/86Box
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
15d2ee2
commit a44936f
Showing
6 changed files
with
127 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,13 +6,16 @@ | |
* | ||
* This file is part of the 86Box distribution. | ||
* | ||
* Implementation of a generic PostScript printer. | ||
* Implementation of a generic PostScript printer and a | ||
* generic PCL 5e printer. | ||
* | ||
* | ||
* | ||
* Authors: David Hrdlička, <[email protected]> | ||
* Cacodemon345 | ||
* | ||
* Copyright 2019 David Hrdlička. | ||
* Copyright 2024 Cacodemon345. | ||
*/ | ||
|
||
#include <inttypes.h> | ||
|
@@ -44,15 +47,20 @@ | |
#ifdef _WIN32 | ||
# if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) | ||
# define PATH_GHOSTSCRIPT_DLL "gsdll32.dll" | ||
# define PATH_GHOSTPCL_DLL "gpcl6dll32.dll" | ||
# else | ||
# define PATH_GHOSTSCRIPT_DLL "gsdll64.dll" | ||
# define PATH_GHOSTPCL_DLL "gpcl6dll64.dll" | ||
# endif | ||
#elif defined __APPLE__ | ||
# define PATH_GHOSTSCRIPT_DLL "libgs.dylib" | ||
# define PATH_GHOSTPCL_DLL "libgpcl6.dylib" | ||
#else | ||
# define PATH_GHOSTSCRIPT_DLL "libgs.so.9" | ||
# define PATH_GHOSTSCRIPT_DLL_ALT1 "libgs.so.10" | ||
# define PATH_GHOSTSCRIPT_DLL_ALT2 "libgs.so" | ||
# define PATH_GHOSTPCL_DLL "libgpcl6.so.10" | ||
# define PATH_GHOSTPCL_DLL_ALT "libgpcl6.so" | ||
#endif | ||
|
||
#define POSTSCRIPT_BUFFER_LENGTH 65536 | ||
|
@@ -72,6 +80,8 @@ typedef struct ps_t { | |
bool int_pending; | ||
bool error; | ||
bool autofeed; | ||
bool pcl; | ||
bool pcl_escape; | ||
uint8_t ctrl; | ||
|
||
char printer_path[260]; | ||
|
@@ -141,28 +151,32 @@ pulse_timer(void *priv) | |
static int | ||
convert_to_pdf(ps_t *dev) | ||
{ | ||
volatile int code; | ||
volatile int code, arg = 0; | ||
void *instance = NULL; | ||
char input_fn[1024]; | ||
char output_fn[1024]; | ||
char *gsargv[9]; | ||
char *gsargv[11]; | ||
|
||
strcpy(input_fn, dev->printer_path); | ||
path_slash(input_fn); | ||
strcat(input_fn, dev->filename); | ||
|
||
strcpy(output_fn, input_fn); | ||
strcpy(output_fn + strlen(output_fn) - 3, ".pdf"); | ||
|
||
gsargv[0] = ""; | ||
gsargv[1] = "-dNOPAUSE"; | ||
gsargv[2] = "-dBATCH"; | ||
gsargv[3] = "-dSAFER"; | ||
gsargv[4] = "-sDEVICE=pdfwrite"; | ||
gsargv[5] = "-q"; | ||
gsargv[6] = "-o"; | ||
gsargv[7] = output_fn; | ||
gsargv[8] = input_fn; | ||
strcpy(output_fn + strlen(output_fn) - (dev->pcl ? 4 : 3), ".pdf"); | ||
|
||
gsargv[arg++] = ""; | ||
gsargv[arg++] = "-dNOPAUSE"; | ||
gsargv[arg++] = "-dBATCH"; | ||
gsargv[arg++] = "-dSAFER"; | ||
gsargv[arg++] = "-sDEVICE=pdfwrite"; | ||
if (dev->pcl) { | ||
gsargv[arg++] = "-LPCL"; | ||
gsargv[arg++] = "-lPCL5E"; | ||
} | ||
gsargv[arg++] = "-q"; | ||
gsargv[arg++] = "-o"; | ||
gsargv[arg++] = output_fn; | ||
gsargv[arg++] = input_fn; | ||
|
||
code = gsapi_new_instance(&instance, dev); | ||
if (code < 0) | ||
|
@@ -171,7 +185,7 @@ convert_to_pdf(ps_t *dev) | |
code = gsapi_set_arg_encoding(instance, GS_ARG_ENCODING_UTF8); | ||
|
||
if (code == 0) | ||
code = gsapi_init_with_args(instance, 9, gsargv); | ||
code = gsapi_init_with_args(instance, arg, gsargv); | ||
|
||
if (code == 0 || code == gs_error_Quit) | ||
code = gsapi_exit(instance); | ||
|
@@ -198,19 +212,22 @@ write_buffer(ps_t *dev, bool finish) | |
return; | ||
|
||
if (dev->filename[0] == 0) | ||
plat_tempfile(dev->filename, NULL, ".ps"); | ||
plat_tempfile(dev->filename, NULL, dev->pcl ? ".pcl" : ".ps"); | ||
|
||
strcpy(path, dev->printer_path); | ||
path_slash(path); | ||
strcat(path, dev->filename); | ||
|
||
fp = plat_fopen(path, "a"); | ||
fp = plat_fopen(path, dev->pcl ? "ab" : "a"); | ||
if (fp == NULL) | ||
return; | ||
|
||
fseek(fp, 0, SEEK_END); | ||
|
||
fprintf(fp, "%.*s", POSTSCRIPT_BUFFER_LENGTH, dev->buffer); | ||
if (dev->pcl) | ||
fwrite(dev->buffer, 1, dev->buffer_pos, fp); | ||
else | ||
fprintf(fp, "%.*s", POSTSCRIPT_BUFFER_LENGTH, dev->buffer); | ||
|
||
fclose(fp); | ||
|
||
|
@@ -249,8 +266,25 @@ ps_write_data(uint8_t val, void *priv) | |
static void | ||
process_data(ps_t *dev) | ||
{ | ||
/* Check for non-printable characters */ | ||
if ((dev->data < 0x20) || (dev->data == 0x7f)) { | ||
/* On PCL, check for escape sequences. */ | ||
if (dev->pcl) { | ||
if (dev->data == 0x1B) | ||
dev->pcl_escape = true; | ||
else if (dev->pcl_escape) { | ||
dev->pcl_escape = false; | ||
if (dev->data == 0xE) { | ||
dev->buffer[dev->buffer_pos++] = dev->data; | ||
dev->buffer[dev->buffer_pos] = 0; | ||
|
||
if (dev->buffer_pos > 2) | ||
write_buffer(dev, true); | ||
|
||
return; | ||
} | ||
} | ||
} | ||
/* On PostScript, check for non-printable characters. */ | ||
else if ((dev->data < 0x20) || (dev->data == 0x7f)) { | ||
switch (dev->data) { | ||
/* The following characters are considered white-space | ||
by the PostScript specification */ | ||
|
@@ -376,6 +410,51 @@ ps_init(void *lpt) | |
return dev; | ||
} | ||
|
||
static void * | ||
pcl_init(void *lpt) | ||
{ | ||
ps_t *dev; | ||
gsapi_revision_t rev; | ||
|
||
dev = (ps_t *) malloc(sizeof(ps_t)); | ||
memset(dev, 0x00, sizeof(ps_t)); | ||
dev->ctrl = 0x04; | ||
dev->lpt = lpt; | ||
dev->pcl = true; | ||
|
||
/* Try loading the DLL. */ | ||
ghostscript_handle = dynld_module(PATH_GHOSTPCL_DLL, ghostscript_imports); | ||
#ifdef PATH_GHOSTPCL_DLL_ALT | ||
if (ghostscript_handle == NULL) { | ||
ghostscript_handle = dynld_module(PATH_GHOSTPCL_DLL_ALT, ghostscript_imports); | ||
} | ||
#endif | ||
if (ghostscript_handle == NULL) { | ||
ui_msgbox_header(MBX_ERROR, plat_get_string(STRING_GHOSTPCL_ERROR_TITLE), plat_get_string(STRING_GHOSTPCL_ERROR_DESC)); | ||
} else { | ||
if (gsapi_revision(&rev, sizeof(rev)) == 0) { | ||
pclog("Loaded %s, rev %ld (%ld)\n", rev.product, rev.revision, rev.revisiondate); | ||
} else { | ||
dynld_close(ghostscript_handle); | ||
ghostscript_handle = NULL; | ||
} | ||
} | ||
|
||
/* Cache print folder path. */ | ||
memset(dev->printer_path, 0x00, sizeof(dev->printer_path)); | ||
path_append_filename(dev->printer_path, usr_path, "printer"); | ||
if (!plat_dir_check(dev->printer_path)) | ||
plat_dir_create(dev->printer_path); | ||
path_slash(dev->printer_path); | ||
|
||
timer_add(&dev->pulse_timer, pulse_timer, dev, 0); | ||
timer_add(&dev->timeout_timer, timeout_timer, dev, 0); | ||
|
||
reset_ps(dev); | ||
|
||
return dev; | ||
} | ||
|
||
static void | ||
ps_close(void *priv) | ||
{ | ||
|
@@ -406,3 +485,15 @@ const lpt_device_t lpt_prt_ps_device = { | |
.read_status = ps_read_status, | ||
.read_ctrl = NULL | ||
}; | ||
|
||
const lpt_device_t lpt_prt_pcl_device = { | ||
.name = "Generic PCL5e Printer", | ||
.internal_name = "pcl", | ||
.init = pcl_init, | ||
.close = ps_close, | ||
.write_data = ps_write_data, | ||
.write_ctrl = ps_write_ctrl, | ||
.read_data = NULL, | ||
.read_status = ps_read_status, | ||
.read_ctrl = NULL | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters