summaryrefslogtreecommitdiff
path: root/gs/psi/dwmain.c
diff options
context:
space:
mode:
Diffstat (limited to 'gs/psi/dwmain.c')
-rw-r--r--gs/psi/dwmain.c530
1 files changed, 530 insertions, 0 deletions
diff --git a/gs/psi/dwmain.c b/gs/psi/dwmain.c
new file mode 100644
index 000000000..ab64edba2
--- /dev/null
+++ b/gs/psi/dwmain.c
@@ -0,0 +1,530 @@
+/* Copyright (C) 2001-2008 Artifex Software, Inc.
+ 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 that
+ license. Refer to licensing information at http://www.artifex.com/
+ or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
+ San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
+*/
+/* $Id$ */
+/* Ghostscript DLL loader for Windows */
+
+#include "windows_.h"
+#include <shellapi.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "gscdefs.h"
+#define GSREVISION gs_revision
+#include "ierrors.h"
+#include "iapi.h"
+#include "vdtrace.h"
+
+#include "dwres.h"
+#include "dwdll.h"
+#include "dwtext.h"
+#include "dwimg.h"
+#include "dwtrace.h"
+#include "dwreg.h"
+#include "gdevdsp.h"
+
+/* public handles */
+HINSTANCE ghInstance;
+
+/* redirected stdio */
+TW *tw;
+
+static const LPSTR szAppName = "Ghostscript";
+
+const LPSTR szIniName = "gswin32.ini";
+const char *szDllName = "gsdll32.dll";
+const LPSTR szIniSection = "Text";
+
+
+GSDLL gsdll;
+void *instance;
+HWND hwndtext;
+
+char start_string[] = "systemdict /start get exec\n";
+
+static int poll(void)
+{
+ MSG msg;
+ while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ /* If text window closing then abort Ghostscript */
+ if (tw->quitnow)
+ return e_Fatal;
+ return 0;
+}
+
+/*********************************************************************/
+/* stdio functions */
+static int GSDLLCALL
+gsdll_stdin(void *instance, char *buf, int len)
+{
+ return text_read_line(tw, buf, len);
+}
+
+static int GSDLLCALL
+gsdll_stdout(void *instance, const char *str, int len)
+{
+ text_write_buf(tw, str, len);
+ return len;
+}
+
+static int GSDLLCALL
+gsdll_stderr(void *instance, const char *str, int len)
+{
+ text_write_buf(tw, str, len);
+ return len;
+}
+
+/* Poll the caller for cooperative multitasking. */
+/* If this function is NULL, polling is not needed */
+static int GSDLLCALL gsdll_poll(void *handle)
+{
+ return poll();
+}
+/*********************************************************************/
+
+/* new dll display device */
+/*
+#define DISPLAY_DEBUG
+ */
+
+/* New device has been opened */
+/* This is the first event from this device. */
+static int display_open(void *handle, void *device)
+{
+ IMAGE *img;
+#ifdef DISPLAY_DEBUG
+ char buf[256];
+ sprintf(buf, "display_open(0x%x, 0x%x)\n", handle, device);
+ text_puts(tw, buf);
+#endif
+ img = image_new(handle, device); /* create and add to list */
+ if (img)
+ image_open(img);
+ return 0;
+}
+
+/* Device is about to be closed. */
+/* Device will not be closed until this function returns. */
+static int display_preclose(void *handle, void *device)
+{
+#ifdef DISPLAY_DEBUG
+ char buf[256];
+ sprintf(buf, "display_preclose(0x%x, 0x$x)\n", handle, device);
+ text_puts(tw, buf);
+#endif
+ /* do nothing - no thread synchonisation needed */
+ return 0;
+}
+
+/* Device has been closed. */
+/* This is the last event from this device. */
+static int display_close(void *handle, void *device)
+{
+ IMAGE *img;
+#ifdef DISPLAY_DEBUG
+ char buf[256];
+ sprintf(buf, "display_close(0x%x, 0x$x)\n", handle, device);
+ text_puts(tw, buf);
+#endif
+ img = image_find(handle, device);
+ if (img) {
+ image_delete(img); /* remove from list but don't free */
+ image_close(img);
+ }
+ return 0;
+}
+
+/* Device is about to be resized. */
+/* Resize will only occur if this function returns 0. */
+static int display_presize(void *handle, void *device, int width, int height,
+ int raster, unsigned int format)
+{
+#ifdef DISPLAY_DEBUG
+ char buf[256];
+ sprintf(buf, "display_presize(0x%x, 0x%x, width=%d height=%d raster=%d\n\
+ format=%d)\n",
+ handle, device, width, height, raster, format);
+ text_puts(tw, buf);
+#endif
+ return 0;
+}
+
+/* Device has been resized. */
+/* New pointer to raster returned in pimage */
+static int display_size(void *handle, void *device, int width, int height,
+ int raster, unsigned int format, unsigned char *pimage)
+{
+ IMAGE *img;
+#ifdef DISPLAY_DEBUG
+ char buf[256];
+ sprintf(buf, "display_size(0x%x, 0x%x, width=%d height=%d raster=%d\n\
+ format=%d image=0x%x)\n",
+ handle, device, width, height, raster, format, pimage);
+ text_puts(tw, buf);
+#endif
+ img = image_find(handle, device);
+ image_size(img, width, height, raster, format, pimage);
+ image_updatesize(img);
+ return 0;
+}
+
+/* flushpage */
+static int display_sync(void *handle, void *device)
+{
+ IMAGE *img;
+#ifdef DISPLAY_DEBUG
+ char buf[256];
+ sprintf(buf, "display_sync(0x%x, 0x%x)\n", handle, device);
+ text_puts(tw, buf);
+#endif
+ img = image_find(handle, device);
+ image_sync(img);
+ return 0;
+}
+
+/* showpage */
+/* If you want to pause on showpage, then don't return immediately */
+static int display_page(void *handle, void *device, int copies, int flush)
+{
+ IMAGE *img;
+#ifdef DISPLAY_DEBUG
+ char buf[256];
+ sprintf(buf, "display_page(0x%x, 0x%x, copies=%d flush=%d)\n",
+ handle, device, copies, flush);
+ text_puts(tw, buf);
+#endif
+ img = image_find(handle, device);
+ image_page(img);
+ return 0;
+}
+
+/* Poll the caller for cooperative multitasking. */
+/* If this function is NULL, polling is not needed */
+static int display_update(void *handle, void *device,
+ int x, int y, int w, int h)
+{
+ IMAGE *img;
+ img = image_find(handle, device);
+ image_poll(img); /* redraw the window periodically */
+ return poll();
+}
+
+int display_separation(void *handle, void *device,
+ int comp_num, const char *name,
+ unsigned short c, unsigned short m,
+ unsigned short y, unsigned short k)
+{
+ IMAGE *img;
+#ifdef DISPLAY_DEBUG
+ fprintf(stdout, "display_separation(0x%x, 0x%x, %d '%s' %d,%d,%d,%d)\n",
+ handle, device, comp_num, name, (int)c, (int)m, (int)y, (int)k);
+#endif
+ img = image_find(handle, device);
+ if (img)
+ image_separation(img, comp_num, name, c, m, y, k);
+ return 0;
+}
+
+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,
+ NULL, /* memalloc */
+ NULL, /* memfree */
+ display_separation
+};
+
+
+/*********************************************************************/
+
+/* program really starts at WinMain */
+int new_main(int argc, char *argv[])
+{
+ int code, code1;
+ int exit_status;
+ int exit_code;
+ int nargc;
+ char **nargv;
+ char dformat[64];
+ char ddpi[64];
+ char buf[256];
+
+ memset(buf, 0, sizeof(buf));
+ if (load_dll(&gsdll, buf, sizeof(buf))) {
+ text_puts(tw, "Can't load Ghostscript DLL\n");
+ text_puts(tw, buf);
+ text_puts(tw, "\n");
+ return 1;
+ }
+
+ if (gsdll.new_instance(&instance, NULL) < 0) {
+ text_puts(tw, "Can't create Ghostscript instance\n");
+ return 1;
+ }
+
+#ifdef DEBUG
+ visual_tracer_init();
+ gsdll.set_visual_tracer(&visual_tracer);
+#endif
+
+ gsdll.set_stdio(instance, gsdll_stdin, gsdll_stdout, gsdll_stderr);
+ gsdll.set_poll(instance, gsdll_poll);
+ gsdll.set_display_callback(instance, &display);
+
+ /* insert display device defaults as first arguments */
+ { int format = DISPLAY_COLORS_NATIVE | DISPLAY_ALPHA_NONE |
+ DISPLAY_DEPTH_1 | DISPLAY_LITTLEENDIAN | DISPLAY_BOTTOMFIRST;
+ HDC hdc = GetDC(NULL); /* get hdc for desktop */
+ int depth = GetDeviceCaps(hdc, PLANES) * GetDeviceCaps(hdc, BITSPIXEL);
+ sprintf(ddpi, "-dDisplayResolution=%d", GetDeviceCaps(hdc, LOGPIXELSY));
+ ReleaseDC(NULL, hdc);
+ 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;
+ sprintf(dformat, "-dDisplayFormat=%d", format);
+ }
+ nargc = argc + 2;
+ nargv = (char **)malloc((nargc + 1) * sizeof(char *));
+ nargv[0] = argv[0];
+ nargv[1] = dformat;
+ nargv[2] = ddpi;
+ memcpy(&nargv[3], &argv[1], argc * sizeof(char *));
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+ __try {
+#endif
+ code = gsdll.init_with_args(instance, nargc, nargv);
+ if (code == 0)
+ code = gsdll.run_string(instance, start_string, 0, &exit_code);
+ code1 = gsdll.exit(instance);
+ if (code == 0 || (code == e_Quit && code1 != 0))
+ code = code1;
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+ } __except(exception_code() == EXCEPTION_STACK_OVERFLOW) {
+ code = e_Fatal;
+ text_puts(tw, "*** C stack overflow. Quiting...\n");
+ }
+#endif
+
+ gsdll.delete_instance(instance);
+
+#ifdef DEBUG
+ visual_tracer_close();
+#endif
+
+ unload_dll(&gsdll);
+
+ free(nargv);
+
+ exit_status = 0;
+ switch (code) {
+ case 0:
+ case e_Quit:
+ break;
+ case e_Fatal:
+ exit_status = 1;
+ break;
+ case e_Info:
+ default:
+ exit_status = 255;
+ }
+
+ return exit_status;
+}
+
+
+
+void
+set_font(void)
+{
+ int fontsize;
+ char fontname[256];
+ char buf[32];
+
+ /* read ini file */
+ GetPrivateProfileString(szIniSection, "FontName", "Courier New", fontname, sizeof(fontname), szIniName);
+ fontsize = GetPrivateProfileInt(szIniSection, "FontSize", 10, szIniName);
+
+ /* set font */
+ text_font(tw, fontname, fontsize);
+
+ /* write ini file */
+ WritePrivateProfileString(szIniSection, "FontName", fontname, szIniName);
+ sprintf(buf, "%d", fontsize);
+ WritePrivateProfileString(szIniSection, "FontSize", buf, szIniName);
+}
+
+int PASCAL
+WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int cmdShow)
+{
+ int dll_exit_status;
+#define MAXCMDTOKENS 128
+ /* BC++ 4.5 will give us _argc and _argv[], but they will be */
+ /* incorrect if there is a space in the program name. */
+ /* Provide our own parsing code to create argc and argv[]. */
+ int argc;
+ LPSTR argv[MAXCMDTOKENS];
+ LPSTR p;
+ char command[256];
+ char *args;
+ char *d, *e;
+ char winposbuf[256];
+ int len = sizeof(winposbuf);
+ int x, y, cx, cy;
+
+ /* copy the hInstance into a variable so it can be used */
+ ghInstance = hInstance;
+
+ if (hPrevInstance) {
+ MessageBox((HWND)NULL,"Can't run twice", szAppName,
+ MB_ICONHAND | MB_OK);
+ return FALSE;
+ }
+
+ /* If called with "gswin32c.exe arg1 arg2"
+ * lpszCmdLine returns:
+ * "arg1 arg2" if called with CreateProcess(NULL, command, ...)
+ * "arg2" if called with CreateProcess(command, args, ...)
+ * GetCommandLine() returns
+ * ""gswin32c.exe" arg1 arg2"
+ * if called with CreateProcess(NULL, command, ...)
+ * " arg1 arg2"
+ * if called with CreateProcess(command, args, ...)
+ * Consequently we must use GetCommandLine()
+ */
+ p = GetCommandLine();
+
+ argc = 0;
+ args = (char *)malloc(lstrlen(p)+1);
+ if (args == (char *)NULL) {
+ fprintf(stdout, "Insufficient memory in WinMain()\n");
+ return 1;
+ }
+
+ /* Parse command line handling quotes. */
+ d = args;
+ while (*p) {
+ /* for each argument */
+
+ if (argc >= MAXCMDTOKENS - 1)
+ break;
+
+ e = d;
+ while ((*p) && (*p != ' ')) {
+ if (*p == '\042') {
+ /* Remove quotes, skipping over embedded spaces. */
+ /* Doesn't handle embedded quotes. */
+ p++;
+ while ((*p) && (*p != '\042'))
+ *d++ =*p++;
+ }
+ else
+ *d++ = *p;
+ if (*p)
+ p++;
+ }
+ *d++ = '\0';
+ argv[argc++] = e;
+
+ while ((*p) && (*p == ' '))
+ p++; /* Skip over trailing spaces */
+ }
+ argv[argc] = NULL;
+
+ if (strlen(argv[0]) == 0) {
+ GetModuleFileName(hInstance, command, sizeof(command)-1);
+ argv[0] = command;
+ }
+
+
+ tw = text_new();
+ if (tw == NULL) {
+ MessageBox((HWND)NULL, "Can't create text window",
+ szAppName, MB_OK | MB_ICONSTOP);
+ return 1;
+ }
+
+ /* start up the text window */
+ if (!hPrevInstance) {
+ HICON hicon = LoadIcon(hInstance, (LPSTR)MAKEINTRESOURCE(GSTEXT_ICON));
+ text_register_class(tw, hicon);
+ }
+ set_font();
+ text_size(tw, 80, 80);
+ text_drag(tw, "(", ") run\r");
+ if (win_get_reg_value("Text", winposbuf, &len) == 0) {
+ if (sscanf(winposbuf, "%d %d %d %d", &x, &y, &cx, &cy) == 4)
+ text_setpos(tw, x, y, cx, cy);
+ }
+
+ /* create the text window */
+ if (text_create(tw, szAppName, cmdShow))
+ exit(1);
+
+ hwndtext = text_get_handle(tw);
+ image_textwindow(hwndtext);
+
+ dll_exit_status = new_main(argc, argv);
+
+ if (dll_exit_status && !tw->quitnow) {
+ /* display error message in text window */
+ MSG msg;
+ text_puts(tw, "\nClose this window with the close button on the title bar or the system menu.\n");
+ if (IsIconic(text_get_handle(tw)))
+ ShowWindow(text_get_handle(tw), SW_SHOWNORMAL);
+ BringWindowToTop(text_get_handle(tw)); /* make text window visible */
+ FlashWindow(text_get_handle(tw), TRUE);
+ /* Wait until error message is read */
+ while (!tw->quitnow && GetMessage(&msg, (HWND)NULL, 0, 0)) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+
+ /* Save the text window size */
+ if (text_getpos(tw, &x, &y, &cx, &cy) == 0) {
+ sprintf(winposbuf, "%d %d %d %d", x, y, cx, cy);
+ win_set_reg_value("Text", winposbuf);
+ }
+
+ text_destroy(tw);
+ tw = NULL;
+
+ return dll_exit_status;
+}
+
+
+