diff -u pl/dwplmain.c ../ghostpcl_1.38/pl/dwplmain.c --- pl/dwplmain.c Wed Jan 15 10:25:49 2003 +++ ../ghostpcl_1.38/pl/dwplmain.c Sat Jan 18 01:27:53 2003 @@ -0,0 +1,372 @@ +/* Copyright (C) 1996-2003 Ghostgum Software Pty Ltd. All rights reserved. + + This software is provided AS-IS with no warranty, either express or + implied. + + This software is distributed under license and may not be copied, + modified or distributed except as expressly authorized under the terms + of the license contained in the file LICENSE in this distribution. + + For more information about licensing, please refer to + http://www.ghostscript.com/licensing/. For information on + commercial licensing, go to http://www.artifex.com/licensing/ or + contact Artifex Software, Inc., 101 Lucas Valley Road #110, + San Rafael, CA 94903, U.S.A., +1(415)492-9861. +*/ + +/* $Id$ */ + +#include +#include +#include +#include +#include +# define GSDLLEXPORT __declspec(dllimport) +#include "plapi.h" +#include "gdevdsp.h" +#include "dwmain.h" +#include "dwimg.h" + +BOOL quitnow = FALSE; +HANDLE hthread; +DWORD thread_id; +HWND hwndtext = NULL; /* for dwimg.c, but not used */ +HWND hwndforeground; /* our best guess for our console window handle */ + +/*********************************************************************/ +/* stdio functions */ +static int GSDLLCALL +gsdll_stdin(void *instance, char *buf, int len) +{ + return _read(fileno(stdin), buf, len); +} + +static int GSDLLCALL +gsdll_stdout(void *instance, const char *str, int len) +{ + fwrite(str, 1, len, stdout); + fflush(stdout); + return len; +} + +static int GSDLLCALL +gsdll_stderr(void *instance, const char *str, int len) +{ + fwrite(str, 1, len, stderr); + fflush(stderr); + return len; +} + +/*********************************************************************/ +/* dll device */ + +/* We must run windows from another thread, since main thread */ +/* is running Ghostscript and blocks on stdin. */ + +/* We notify second thread of events using PostThreadMessage() + * with the following messages. Apparently Japanese Windows sends + * WM_USER+1 with lParam == 0 and crashes. So we use WM_USER+101. + * Fix from Akira Kakuto + */ +#define DISPLAY_OPEN WM_USER+101 +#define DISPLAY_CLOSE WM_USER+102 +#define DISPLAY_SIZE WM_USER+103 +#define DISPLAY_SYNC WM_USER+104 +#define DISPLAY_PAGE WM_USER+105 + +/* +#define DISPLAY_DEBUG +*/ + +/* The second thread is the message loop */ +static void winthread(void *arg) +{ + MSG msg; + thread_id = GetCurrentThreadId(); + hthread = GetCurrentThread(); + + while (!quitnow && GetMessage(&msg, (HWND)NULL, 0, 0)) { + switch (msg.message) { + case DISPLAY_OPEN: + image_open((IMAGE *)msg.lParam); + break; + case DISPLAY_CLOSE: + { + IMAGE *img = (IMAGE *)msg.lParam; + HANDLE hmutex = img->hmutex; + image_close(img); + CloseHandle(hmutex); + } + break; + case DISPLAY_SIZE: + image_updatesize((IMAGE *)msg.lParam); + break; + case DISPLAY_SYNC: + image_sync((IMAGE *)msg.lParam); + break; + case DISPLAY_PAGE: + image_page((IMAGE *)msg.lParam); + break; + default: + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + quitnow = FALSE; +} + + +/* New device has been opened */ +/* Tell user to use another device */ +int display_open(void *handle, void *device) +{ + IMAGE *img; +#ifdef DISPLAY_DEBUG + fprintf(stdout, "display_open(0x%x, 0x%x)\n", handle, device); +#endif + img = image_new(handle, device); /* create and add to list */ + img->hmutex = CreateMutex(NULL, FALSE, NULL); + if (img) + PostThreadMessage(thread_id, DISPLAY_OPEN, 0, (LPARAM)img); + return 0; +} + +int display_preclose(void *handle, void *device) +{ + IMAGE *img; +#ifdef DISPLAY_DEBUG + fprintf(stdout, "display_preclose(0x%x, 0x%x)\n", handle, device); +#endif + img = image_find(handle, device); + if (img) { + /* grab mutex to stop other thread using bitmap */ + WaitForSingleObject(img->hmutex, 120000); + } + return 0; +} + +int display_close(void *handle, void *device) +{ + IMAGE *img; +#ifdef DISPLAY_DEBUG + fprintf(stdout, "display_close(0x%x, 0x%x)\n", handle, device); +#endif + img = image_find(handle, device); + if (img) { + /* This is a hack to pass focus from image window to console */ + if (GetForegroundWindow() == img->hwnd) + SetForegroundWindow(hwndforeground); + + image_delete(img); /* remove from list, but don't free */ + PostThreadMessage(thread_id, DISPLAY_CLOSE, 0, (LPARAM)img); + } + return 0; +} + +int display_presize(void *handle, void *device, int width, int height, + int raster, unsigned int format) +{ + IMAGE *img; +#ifdef DISPLAY_DEBUG + fprintf(stdout, "display_presize(0x%x 0x%x, %d, %d, %d, %d, %ld)\n", + handle, device, width, height, raster, format); +#endif + img = image_find(handle, device); + if (img) { + /* grab mutex to stop other thread using bitmap */ + WaitForSingleObject(img->hmutex, 120000); + } + return 0; +} + +int display_size(void *handle, void *device, int width, int height, + int raster, unsigned int format, unsigned char *pimage) +{ + IMAGE *img; +#ifdef DISPLAY_DEBUG + fprintf(stdout, "display_size(0x%x 0x%x, %d, %d, %d, %d, %ld, 0x%x)\n", + handle, device, width, height, raster, format, pimage); +#endif + img = image_find(handle, device); + if (img) { + image_size(img, width, height, raster, format, pimage); + /* release mutex to allow other thread to use bitmap */ + ReleaseMutex(img->hmutex); + PostThreadMessage(thread_id, DISPLAY_SIZE, 0, (LPARAM)img); + } + return 0; +} + +int display_sync(void *handle, void *device) +{ + IMAGE *img; +#ifdef DISPLAY_DEBUG + fprintf(stdout, "display_sync(0x%x, 0x%x)\n", handle, device); +#endif + img = image_find(handle, device); + if (img) + PostThreadMessage(thread_id, DISPLAY_SYNC, 0, (LPARAM)img); + return 0; +} + +int display_page(void *handle, void *device, int copies, int flush) +{ + IMAGE *img; +#ifdef DISPLAY_DEBUG + fprintf(stdout, "display_page(0x%x, 0x%x, copies=%d, flush=%d)\n", + handle, device, copies, flush); +#endif + img = image_find(handle, device); + if (img) + PostThreadMessage(thread_id, DISPLAY_PAGE, 0, (LPARAM)img); + return 0; +} + +int display_update(void *handle, void *device, + int x, int y, int w, int h) +{ + /* Unneeded for polling - we are running Windows on another thread. */ + /* Eventually we will add code here which provides progressive + * update of the display during rendering. + */ + return 0; +} + +/* +#define DISPLAY_DEBUG_USE_ALLOC +*/ +#ifdef DISPLAY_DEBUG_USE_ALLOC +/* This code isn't used, but shows how to use this function */ +void *display_memalloc(void *handle, void *device, unsigned long size) +{ + void *mem; +#ifdef DISPLAY_DEBUG + fprintf(stdout, "display_memalloc(0x%x 0x%x %d)\n", + handle, device, size); +#endif + mem = malloc(size); +#ifdef DISPLAY_DEBUG + fprintf(stdout, " returning 0x%x\n", (int)mem); +#endif + return mem; +} + +int display_memfree(void *handle, void *device, void *mem) +{ +#ifdef DISPLAY_DEBUG + fprintf(stdout, "display_memfree(0x%x, 0x%x, 0x%x)\n", + handle, device, mem); +#endif + free(mem); + return 0; +} +#endif + + + +display_callback display = { + sizeof(display_callback), + DISPLAY_VERSION_MAJOR, + DISPLAY_VERSION_MINOR, + display_open, + display_preclose, + display_close, + display_presize, + display_size, + display_sync, + display_page, + display_update, +#ifdef DISPLAY_DEBUG_USE_ALLOC + display_memalloc, /* memalloc */ + display_memfree /* memfree */ +#else + NULL, /* memalloc */ + NULL /* memfree */ +#endif +}; + + +/*********************************************************************/ +int main(int argc, char *argv[]) +{ + int code; + int exit_status; + gsapi_instance_t *instance; + HDC hdc = GetDC(NULL); /* get hdc for desktop */ + int depth = GetDeviceCaps(hdc, PLANES) * GetDeviceCaps(hdc, BITSPIXEL); + unsigned int format; + + if (!_isatty(fileno(stdin))) + _setmode(fileno(stdin), _O_BINARY); + _setmode(fileno(stdout), _O_BINARY); + _setmode(fileno(stderr), _O_BINARY); + + hwndforeground = GetForegroundWindow(); /* assume this is ours */ + + if (pl_new_instance(&instance, NULL) < 0) { + fprintf(stderr, "Can't create GhostPCL instance\n"); + return 1; + } + + if (_beginthread(winthread, 65535, NULL) == -1) { + fprintf(stderr, "GUI thread creation failed\n"); + } + else { + int n = 30; + /* wait for thread to start */ + Sleep(0); + while (n && (hthread == INVALID_HANDLE_VALUE)) { + n--; + Sleep(100); + } + while (n && (PostThreadMessage(thread_id, WM_USER, 0, 0) == 0)) { + n--; + Sleep(100); + } + if (n == 0) + fprintf(stderr, "Can't post message to GUI thread\n"); + } + + pl_set_stdio(instance, gsdll_stdin, gsdll_stdout, gsdll_stderr); + + if (depth == 32) + format = DISPLAY_COLORS_RGB | DISPLAY_UNUSED_LAST | + DISPLAY_DEPTH_8 | DISPLAY_LITTLEENDIAN | DISPLAY_BOTTOMFIRST; + else if (depth == 16) + format = DISPLAY_COLORS_NATIVE | DISPLAY_ALPHA_NONE | + DISPLAY_DEPTH_16 | DISPLAY_LITTLEENDIAN | DISPLAY_BOTTOMFIRST | + DISPLAY_NATIVE_555; + else if (depth > 8) + format = DISPLAY_COLORS_RGB | DISPLAY_ALPHA_NONE | + DISPLAY_DEPTH_8 | DISPLAY_LITTLEENDIAN | DISPLAY_BOTTOMFIRST; + else if (depth >= 8) + format = DISPLAY_COLORS_NATIVE | DISPLAY_ALPHA_NONE | + DISPLAY_DEPTH_8 | DISPLAY_LITTLEENDIAN | DISPLAY_BOTTOMFIRST; + else if (depth >= 4) + format = DISPLAY_COLORS_NATIVE | DISPLAY_ALPHA_NONE | + DISPLAY_DEPTH_4 | DISPLAY_LITTLEENDIAN | DISPLAY_BOTTOMFIRST; + else + format = DISPLAY_COLORS_NATIVE | DISPLAY_ALPHA_NONE | + DISPLAY_DEPTH_1 | DISPLAY_LITTLEENDIAN | DISPLAY_BOTTOMFIRST; + pl_set_display(instance, &display, 0, format); + + code = pl_run_args(instance, argc, argv); + + pl_delete_instance(instance); + + /* close other thread */ + quitnow = TRUE; + PostThreadMessage(thread_id, WM_QUIT, 0, (LPARAM)0); + Sleep(0); + while (quitnow) + Sleep(50); + thread_id = 0; + hthread = INVALID_HANDLE_VALUE; + + exit_status = 0; + if (code < 0) + exit_status = 1; + + return exit_status; +} + diff -u pl/plalloc.c ../ghostpcl_1.38/pl/plalloc.c --- pl/plalloc.c Thu Nov 14 20:03:58 2002 +++ ../ghostpcl_1.38/pl/plalloc.c Sat Jan 18 00:12:46 2003 @@ -178,7 +178,7 @@ else dprintf2("Recovered %d blocks, %d bytes\n", blk_count, total_size); - head = NULL; + mem->head = NULL; } } diff -u pl/plalloc.h ../ghostpcl_1.38/pl/plalloc.h --- pl/plalloc.h Wed Jan 15 09:59:41 2003 +++ ../ghostpcl_1.38/pl/plalloc.h Wed Jan 15 09:59:38 2003 @@ -14,6 +14,7 @@ /* A simple memory allocator for use by pcl and pxl */ gs_memory_t *pl_alloc_init(void); +gs_memory_t * pl_pjl_alloc_init(void); /* If true PL_KEEP_GLOBAL_FREE_LIST will force all memory allocations to be stored diff -u pl/plapi.h ../ghostpcl_1.38/pl/plapi.h --- pl/plapi.h Mon Sep 03 15:55:26 2001 +++ ../ghostpcl_1.38/pl/plapi.h Wed Jan 15 09:11:43 2003 @@ -43,12 +43,18 @@ # ifndef GSDLLAPI # define GSDLLAPI __stdcall # endif +# ifndef GSDLLCALL +# define GSDLLCALL __stdcall +# endif #endif /* _Windows */ #if defined(OS2) && defined(__IBMC__) # ifndef GSDLLAPI # define GSDLLAPI _System # endif +# ifndef GSDLLCALL +# define GSDLLCALL _System +# endif #endif /* OS2 && __IBMC */ #ifdef __MACINTOSH__ @@ -61,14 +67,61 @@ #ifndef GSDLLAPI # define GSDLLAPI #endif +#ifndef GSDLLCALL +# define GSDLLCALL +#endif #if defined(__IBMC__) # define GSDLLAPIPTR * GSDLLAPI +# define GSDLLCALLPTR * GSDLLCALL #else # define GSDLLAPIPTR GSDLLAPI * +# define GSDLLCALLPTR GSDLLCALL * +#endif + +typedef struct gsapi_instance_s gsapi_instance_t; + +#ifndef display_callback_DEFINED +# define display_callback_DEFINED +typedef struct display_callback_s display_callback; #endif +GSDLLEXPORT int GSDLLAPI +pl_new_instance(gsapi_instance_t **pinstance, void *caller_handle); + +GSDLLEXPORT int GSDLLAPI +pl_set_stdio(gsapi_instance_t *instance, + int (GSDLLCALLPTR stdin_fn)(void *caller_handle, char *buf, int len), + int (GSDLLCALLPTR stdout_fn)(void *caller_handle, const char *str, int len), + int (GSDLLCALLPTR stderr_fn)(void *caller_handle, const char *str, int len)); + +GSDLLEXPORT int GSDLLAPI +pl_set_display(gsapi_instance_t *instance, + display_callback *callback, void *handle, unsigned int format); + +GSDLLEXPORT int GSDLLAPI +pl_run_args(gsapi_instance_t *inst, int argc, char * argv[]); + +GSDLLEXPORT void GSDLLAPI +pl_delete_instance(gsapi_instance_t *instance); + +/* function prototypes */ +typedef int (GSDLLAPIPTR PFN_pl_new_instance)( + gsapi_instance_t **pinstance, void *caller_handle); +typedef void (GSDLLAPIPTR PFN_pl_delete_instance)( + gsapi_instance_t *instance); +typedef int (GSDLLAPIPTR PFN_pl_set_stdio)(gsapi_instance_t *instance, + int (GSDLLCALLPTR stdin_fn)(void *caller_handle, char *buf, int len), + int (GSDLLCALLPTR stdout_fn)(void *caller_handle, const char *str, int len), + int (GSDLLCALLPTR stderr_fn)(void *caller_handle, const char *str, int len)); +typedef int (GSDLLAPIPTR PFN_pl_set_display)( + gsapi_instance_t *instance, display_callback *callback, void *handle, + unsigned int format); +typedef int (GSDLLAPIPTR PFN_pl_run_args)( + gsapi_instance_t *instance, int argc, char **argv); + +/* OLD INTERFACE */ /* Run this just like you would pcl6 on the command line. * * Returns: 0 success diff -u pl/plapi2.h ../ghostpcl_1.38/pl/plapi2.h --- pl/plapi2.h Wed Jan 15 10:25:56 2003 +++ ../ghostpcl_1.38/pl/plapi2.h Wed Jan 15 09:39:53 2003 @@ -0,0 +1,26 @@ +/* Ghostscript/GhostPCL common API structure */ + +#ifndef gsapi_instance_DEFINED +# define gsapi_instance_DEFINED +typedef struct gsapi_instance_s gsapi_instance_t; +#endif +#ifndef pl_main_instance_DEFINED +# define pl_main_instance_DEFINED +typedef struct pl_main_instance_s pl_main_instance_t; +#endif +#ifndef gs_main_instance_DEFINED +# define gs_main_instance_DEFINED +typedef struct gs_main_instance_s gs_main_instance; +#endif + +struct gsapi_instance_s { + void *caller_handle; /* identifies caller of Ghostscript/GhostPCL */ + int (GSDLLCALL *stdin_fn)(void *caller_handle, char *buf, int len); + int (GSDLLCALL *stdout_fn)(void *caller_handle, const char *str, int len); + int (GSDLLCALL *stderr_fn)(void *caller_handle, const char *str, int len); + display_callback *display; /* callback structure for display device */ + void *display_handle; + unsigned int display_format; + pl_main_instance_t *pl; + gs_main_instance *gs; +}; diff -u pl/plmain.c ../ghostpcl_1.38/pl/plmain.c --- pl/plmain.c Fri Jan 17 22:24:33 2003 +++ ../ghostpcl_1.38/pl/plmain.c Sat Jan 18 01:32:58 2003 @@ -47,6 +47,9 @@ #include "pltop.h" #include "pltoputl.h" #include "plapi.h" +#include "plapi2.h" +#include "gdevdsp.h" /* display_callback */ +#include "gdevdsp2.h" /* gx_device_display */ /* @@ -76,12 +79,13 @@ extern pl_interp_implementation_t const * const pdl_implementation[]; /* zero-terminated list */ /* Define the usage message. */ -private const char *pl_usage = "\ -Usage: %s [option* file]+...\n\ +private const char *pl_usage1 = "Usage: "; +private const char *pl_usage2 = "\ + [option* file]+...\n\ Options: -dNOPAUSE -E[#] -h -C -L -n -K -P -Z...\n\ -sDEVICE= -gx -r[x] -d{First|Last}Page=<#>\n\ -sOutputFile= (-s