Merge pull request #492 from dhrdlicka/feature/postscript

Updates to the generic PostScript printer
This commit is contained in:
OBattler
2019-12-13 04:44:15 +01:00
committed by GitHub
3 changed files with 122 additions and 84 deletions

View File

@@ -96,6 +96,7 @@
#define IDS_2120 2120 // "Unable to initialize SDL..."
#define IDS_2121 2121 // "Are you sure you want to..."
#define IDS_2122 2122 // "Are you sure you want to..."
#define IDS_2123 2123 // "Unable to initialize Ghostscript..."
#define IDS_4096 4096 // "Hard disk (%s)"
#define IDS_4097 4097 // "%01i:%01i"
@@ -174,7 +175,7 @@
#define IDS_LANG_ENUS IDS_7168
#define STR_NUM_2048 75
#define STR_NUM_2048 76
#define STR_NUM_3072 11
#define STR_NUM_4096 18
#define STR_NUM_4352 7

View File

@@ -8,7 +8,7 @@
*
* Implementation of a generic PostScript printer.
*
* Version: @(#)prt_ps.c 1.0.1 2019/12/06
* Version: @(#)prt_ps.c 1.0.2 2019/12/08
*
* Authors: David Hrdlička, <hrdlickadavid@outlook.com>
*
@@ -23,6 +23,7 @@
#include <string.h>
#include <wchar.h>
#include "../86box.h"
#include "../lang/language.h"
#include "../lpt.h"
#include "../timer.h"
#include "../pit.h"
@@ -38,7 +39,10 @@
#include <ghostscript/ierrors.h>
#define PATH_GHOSTSCRIPT_DLL "gsdll32.dll"
#define PATH_GHOSTSCRIPT_DLL "gsdll32.dll"
#define PATH_GHOSTSCRIPT_SO "libgs.so"
#define POSTSCRIPT_BUFFER_LENGTH 65536
static GSDLLAPI int (*ghostscript_revision)(gsapi_revision_t *pr, int len);
static GSDLLAPI int (*ghostscript_new_instance)(void **pinstance, void *caller_handle);
@@ -58,7 +62,6 @@ static dllimp_t ghostscript_imports[] = {
};
static void *ghostscript_handle = NULL;
static bool ghostscript_initialized = false;
typedef struct
{
@@ -82,14 +85,16 @@ typedef struct
wchar_t filename[260];
char buffer[65536];
char buffer[POSTSCRIPT_BUFFER_LENGTH];
uint16_t buffer_pos;
} ps_t;
static void
reset_ps(ps_t *dev)
{
if (dev == NULL) return;
if (dev == NULL) {
return;
}
dev->ack = false;
@@ -139,25 +144,29 @@ convert_to_pdf(ps_t *dev)
gsargv[8] = input_fn;
code = ghostscript_new_instance(&instance, dev);
if(code < 0)
if (code < 0) {
return code;
}
code = ghostscript_set_arg_encoding(instance, GS_ARG_ENCODING_UTF16LE);
if (code == 0)
if (code == 0) {
code = ghostscript_init_with_args(instance, 9, (char **) gsargv);
}
if (code == 0 || code == gs_error_Quit)
if (code == 0 || code == gs_error_Quit) {
code = ghostscript_exit(instance);
else
} else {
ghostscript_exit(instance);
}
ghostscript_delete_instance(instance);
if (code == 0 || code == gs_error_Quit)
if (code == 0) {
plat_remove(input_fn);
else
} else {
plat_remove(output_fn);
}
return code;
}
@@ -165,20 +174,24 @@ convert_to_pdf(ps_t *dev)
static void
finish_document(ps_t *dev)
{
if (ghostscript_handle != NULL)
if (ghostscript_handle != NULL) {
convert_to_pdf(dev);
}
dev->filename[0] = 0;
}
static void
write_buffer(ps_t *dev)
write_buffer(ps_t *dev, bool newline)
{
wchar_t path[1024];
FILE *fp;
if (dev->filename[0] == 0)
{
if (dev->buffer[0] == 0) {
return;
}
if (dev->filename[0] == 0) {
plat_tempfile(dev->filename, NULL, L".ps");
}
@@ -187,14 +200,18 @@ write_buffer(ps_t *dev)
wcscat(path, dev->filename);
fp = plat_fopen(path, L"a");
if (fp == NULL)
if (fp == NULL) {
return;
}
fseek(fp, 0, SEEK_END);
fprintf(fp, "%s\n", dev->buffer);
fprintf(fp, "%.*s%s", POSTSCRIPT_BUFFER_LENGTH, dev->buffer, newline ? "\n" : "");
fclose(fp);
dev->buffer[0] = 0;
dev->buffer_pos = 0;
}
static void
@@ -202,9 +219,7 @@ timeout_timer(void *priv)
{
ps_t *dev = (ps_t *) priv;
if (dev == NULL) return;
write_buffer(dev);
write_buffer(dev, false);
finish_document(dev);
timer_disable(&dev->timeout_timer);
@@ -215,58 +230,84 @@ ps_write_data(uint8_t val, void *p)
{
ps_t *dev = (ps_t *) p;
if (dev == NULL) return;
if (dev == NULL) {
return;
}
dev->data = (char) val;
}
static bool
process_nonprintable(ps_t *dev)
{
switch (dev->data) {
case '\b':
dev->buffer_pos--;
break;
case '\r':
dev->buffer_pos = 0;
if (dev->autofeed)
write_buffer(dev, true);
break;
case '\v':
case '\f':
case '\n':
write_buffer(dev, true);
break;
case 0x04: // Ctrl+D
write_buffer(dev, false);
finish_document(dev);
break;
/* Characters that should be written to the buffer as-is */
case '\t':
return false;
}
return true;
}
static void
process_data(ps_t *dev)
{
if (dev->data < 0x20 || dev->data == 0x7F) {
if (process_nonprintable(dev)) {
return;
}
}
if (dev->buffer_pos == POSTSCRIPT_BUFFER_LENGTH) {
write_buffer(dev, false);
}
dev->buffer[dev->buffer_pos++] = dev->data;
dev->buffer[dev->buffer_pos] = 0;
}
static void
ps_write_ctrl(uint8_t val, void *p)
{
ps_t *dev = (ps_t *) p;
if (dev == NULL) return;
if (dev == NULL) {
return;
}
dev->autofeed = val & 0x02 ? true : false;
if (val & 0x08)
{
if (val & 0x08) {
dev->select = true;
}
if((val & 0x04) && !(dev->ctrl & 0x04))
{
if ((val & 0x04) && !(dev->ctrl & 0x04)) {
// reset printer
dev->select = false;
reset_ps(dev);
}
if(!(val & 0x01) && (dev->ctrl & 0x01))
{
if (dev->data < 0x20 && dev->data != '\t')
{
switch (dev->data)
{
case '\b':
dev->buffer[dev->buffer_pos--] = 0;
break;
case '\r':
dev->buffer_pos = 0;
if(!dev->autofeed)
break;
case '\n':
write_buffer(dev);
dev->buffer[0] = 0;
dev->buffer_pos = 0;
break;
}
}
else
{
dev->buffer[dev->buffer_pos++] = dev->data;
dev->buffer[dev->buffer_pos] = 0;
}
if (!(val & 0x01) && (dev->ctrl & 0x01)) {
process_data(dev);
dev->ack = true;
@@ -285,40 +326,18 @@ ps_read_status(void *p)
ret |= 0x80;
if(!dev->ack)
if (!dev->ack) {
ret |= 0x40;
}
return(ret);
}
static void
ghostscript_init()
{
gsapi_revision_t rev;
ghostscript_initialized = true;
/* Try loading the DLL. */
ghostscript_handle = dynld_module(PATH_GHOSTSCRIPT_DLL, ghostscript_imports);
if (ghostscript_handle == NULL) {
ui_msgbox(MBX_ERROR, L"Couldn't initialize Ghostscript!");
return;
}
if (ghostscript_revision(&rev, sizeof(rev)) == 0)
{
pclog("Loaded %s, rev %ld (%ld)\n", rev.product, rev.revision, rev.revisiondate);
}
else
{
ghostscript_handle = NULL;
}
}
static void *
ps_init(void *lpt)
{
ps_t *dev;
gsapi_revision_t rev;
dev = (ps_t *) malloc(sizeof(ps_t));
memset(dev, 0x00, sizeof(ps_t));
@@ -327,14 +346,25 @@ ps_init(void *lpt)
reset_ps(dev);
if(! ghostscript_initialized)
ghostscript_init();
/* Try loading the DLL. */
ghostscript_handle = dynld_module(PATH_GHOSTSCRIPT_DLL, ghostscript_imports);
if (ghostscript_handle == NULL) {
ui_msgbox(MBX_ERROR, (wchar_t *) IDS_2123);
} else {
if (ghostscript_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));
plat_append_filename(dev->printer_path, usr_path, L"printer");
if (! plat_dir_check(dev->printer_path))
if (!plat_dir_check(dev->printer_path)) {
plat_dir_create(dev->printer_path);
}
plat_path_slash(dev->printer_path);
timer_add(&dev->pulse_timer, pulse_timer, dev, 0);
@@ -348,14 +378,20 @@ ps_close(void *p)
{
ps_t *dev = (ps_t *) p;
if (dev == NULL) return;
if (dev == NULL) {
return;
}
if (dev->buffer[0] != 0)
{
write_buffer(dev);
if (dev->buffer[0] != 0) {
write_buffer(dev, false);
finish_document(dev);
}
if (ghostscript_handle != NULL) {
dynld_close(ghostscript_handle);
ghostscript_handle = NULL;
}
free(dev);
}

View File

@@ -903,6 +903,7 @@ BEGIN
IDS_2120 "Unable to initialize SDL, SDL2.dll is required"
IDS_2121 "Are you sure you want to hard reset the emulated machine?"
IDS_2122 "Are you sure you want to quit 86Box?"
IDS_2123 "Unable to initialize Ghostscript, gsdll32.dll is required for automatic convertion of PostScript files to PDF.\n\nAny documents sent to the generic PostScript printer will be saved as PostScript files (.ps)."
END
STRINGTABLE DISCARDABLE