diff options
Diffstat (limited to 'gs/src/dwmain.cpp')
-rw-r--r-- | gs/src/dwmain.cpp | 412 |
1 files changed, 412 insertions, 0 deletions
diff --git a/gs/src/dwmain.cpp b/gs/src/dwmain.cpp new file mode 100644 index 000000000..75d573e2e --- /dev/null +++ b/gs/src/dwmain.cpp @@ -0,0 +1,412 @@ +/* Copyright (C) 1996, 1997, Russell Lang. All rights reserved. + + This file is part of Aladdin Ghostscript. + + Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author + or distributor accepts any responsibility for the consequences of using it, + or for whether it serves any particular purpose or works at all, unless he + or she says so in writing. Refer to the Aladdin Ghostscript Free Public + License (the "License") for full details. + + Every copy of Aladdin Ghostscript must include a copy of the License, + normally in a plain ASCII text file named PUBLIC. The License grants you + the right to copy, modify and redistribute Aladdin Ghostscript, but only + under certain conditions described in the License. Among other things, the + License requires that the copyright notice and this notice be preserved on + all copies. +*/ + + +// dwmain.cpp +// Ghostscript DLL loader for Windows + +#define STRICT +#include <windows.h> +#include <shellapi.h> +#ifndef __WIN32__ +#include <toolhelp.h> +static BOOL dllfix(void); +#endif +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <dos.h> +extern "C" { +#include "gscdefs.h" +#define GSREVISION gs_revision +#include "gsdll.h" +} +#include "dwmain.h" +#include "dwdll.h" +#include "dwtext.h" +#include "dwimg.h" + +#if defined(_MSC_VER) && defined(__WIN32__) +#define _export +#endif + +/* public handles */ +HINSTANCE ghInstance; + +/* redirected stdio */ +TextWindow tw; + +const LPSTR szAppName = "Ghostscript"; + +#ifdef __WIN32__ +const LPSTR szIniName = "GSWIN32.INI"; +const char *szDllName = "GSDLL32.DLL"; +#else +const LPSTR szIniName = "GSWIN.INI"; +const char *szDllName = "GSDLL16.DLL"; +#endif +const LPSTR szIniSection = "Text"; + +int dll_exit_status; + +int FAR _export gsdll_callback(int message, char FAR *str, unsigned long count); + +// the Ghostscript DLL class +gsdll_class gsdll; + +char start_string[] = "systemdict /start get exec\n"; + +// program really starts at WinMain +int +new_main(int argc, char *argv[]) +{ +typedef char FAR * FARARGV_PTR; +FARARGV_PTR *far_argv; +int rc; + + // load DLL + if (gsdll.load(ghInstance, szDllName, GSREVISION)) { + char buf[256]; + gsdll.get_last_error(buf, sizeof(buf)); + tw.puts(buf); + return 1; + } + + +#ifdef __WIN32__ + far_argv = argv; +#else + far_argv = new FARARGV_PTR[argc+1]; + if (!far_argv) + return 1; + for (int i = 0; i<argc; i++) + far_argv[i] = argv[i]; // convert from near to far pointers + far_argv[i+1] = NULL; +#endif + + // initialize the interpreter + rc = gsdll.init(gsdll_callback, tw.get_handle(), argc, far_argv); + if (rc == GSDLL_INIT_QUIT) { + gsdll.unload(); + return 0; + } + if (rc) { + char buf[256]; + gsdll.get_last_error(buf, sizeof(buf)); + tw.puts(buf); + gsdll.unload(); +#ifndef __WIN32__ + if (rc == GSDLL_INIT_IN_USE) + dllfix(); // offer option to unload NASTY! +#endif + return rc; + } + + // if (!batch) + gsdll.execute(start_string, strlen(start_string)); + +#ifdef UNUSED + int len; + char line[256]; + do { + len = tw.read_line(line, sizeof(line)); + } while ( len && !gsdll.execute(line, len) ); +#endif + + gsdll.unload(); + + return 0; +} + + +/* our exit handler */ +/* also called from Text Window WM_CLOSE */ +void win_exit(void) +{ + if (dll_exit_status) { + /* display message box so error messages in text window can be read */ + char buf[80]; + if (IsIconic(tw.get_handle())) + ShowWindow(tw.get_handle(), SW_SHOWNORMAL); + BringWindowToTop(tw.get_handle()); /* make text window visible */ + sprintf(buf, "Exit code %d\nSee text window for details",dll_exit_status); + MessageBox((HWND)NULL, buf, szAppName, MB_OK | MB_ICONSTOP); + } +} + +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 + tw.font(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) +{ +#if defined(_MSC_VER) /* MSC doesn't give us _argc and _argv[] so ... */ +#define MAXCMDTOKENS 128 + int _argc=0; + LPSTR _argv[MAXCMDTOKENS]; + LPSTR p, q; +#ifdef __WIN32__ + _argv[_argc] = "gswin32.exe"; +#else + _argv[_argc] = "gswin.exe"; +#endif + // Parse command line handling quotes. + p = lpszCmdLine; + while (*p) { + // for each argument + while ((*p) && (*p == ' ')) + p++; // skip over leading spaces + if (*p == '\042') { + p++; // skip " + q = p; + // scan to end of argument + // doesn't handle embedded quotes + while ((*p) && (*p != '\042')) + p++; + _argv[++_argc] = q; + if (*p) + *p++ = '\0'; + } + else if (*p) { + // delimited by spaces + q = p; + while ((*p) && (*p != ' ')) + p++; + _argv[++_argc] = q; + if (*p) + *p++ = '\0'; + } + } + _argv[++_argc] = (LPSTR)NULL; +#endif + + if (hPrevInstance) { + MessageBox((HWND)NULL,"Can't run twice", szAppName, MB_ICONHAND | MB_OK); + return FALSE; + } + + /* copy the hInstance into a variable so it can be used */ + ghInstance = hInstance; + + + /* start up the text window */ + if (!hPrevInstance) { + HICON hicon = LoadIcon(hInstance, (LPSTR)MAKEINTRESOURCE(GSTEXT_ICON)); + tw.register_class(hInstance, hicon); + } + set_font(); + tw.size(80, 80); + tw.drag("(", ") run\r"); + + // create the text window + if (tw.create(szAppName, cmdShow)) + exit(1); + + // initialize for image windows + ImageWindow::hwndtext = tw.get_handle(); + ImageWindow::hInstance = hInstance; + + dll_exit_status = new_main(_argc, _argv); + + win_exit(); + + tw.destroy(); + + return dll_exit_status; +} + + +int FAR _export +gsdll_callback(int message, char FAR *str, unsigned long count) +{ +char buf[256]; +ImageWindow *iw; + switch (message) { + case GSDLL_POLL: + { + MSG msg; + while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + // If text window closed then abort Ghostscript + if (!IsWindow(tw.get_handle())) + return -1; + break; + case GSDLL_STDIN: + return tw.read_line(str, count); + case GSDLL_STDOUT: + if (str != (char *)NULL) + tw.write_buf(str, count); + return count; + case GSDLL_DEVICE: +#ifdef DEBUG + sprintf(buf,"Callback: DEVICE %p %s\n", (char *)str, + count ? "open" : "close"); + tw.puts(buf); +#endif + if (count) { + iw = new ImageWindow; + iw->open(str); + } + else { + iw = FindImageWindow(str); + iw->close(); + } + break; + case GSDLL_SYNC: +#ifdef DEBUG + sprintf(buf,"Callback: SYNC %p\n", (char *)str); + tw.puts(buf); +#endif + iw = FindImageWindow(str); + iw->sync(); + break; + case GSDLL_PAGE: +#ifdef DEBUG + sprintf(buf,"Callback: PAGE %p\n", (char *)str); + tw.puts(buf); +#endif + iw = FindImageWindow(str); + iw->page(); + break; + case GSDLL_SIZE: +#ifdef DEBUG + sprintf(buf,"Callback: SIZE %p width=%d height=%d\n", (char *)str, + (int)(count & 0xffff), (int)((count>>16) & 0xffff) ); + tw.puts(buf); +#endif + iw = FindImageWindow(str); + iw->size( (int)(count & 0xffff), (int)((count>>16) & 0xffff) ); + break; + default: + sprintf(buf,"Callback: Unknown message=%d\n",message); + tw.puts(buf); + break; + } + return 0; +} + + +#ifndef __WIN32__ +// This is a hack to cope with a GPF occuring in either Ghostscript +// or a driver loaded by Ghostscript. If a GPF occurs, gswin16.exe +// is unloaded, but not gsdll16.dll. +// Attempts to reload gswin16.exe will fail because gsdll16.dll +// is already in use. If this occurs, this code will unload +// gsdll16.dll, EVEN IF SOMEONE ELSE IS USING IT. + +// The DLL module name as it appears in the module definition file +#define GSDLLNAME "GSDLL16" +// These are the names of EXE modules that are known users +// of the Ghostscript DLL. +// If one of these is running, it is not safe to unload the DLL. +#define GSEXE "GSWIN16" + +typedef HMODULE (WINAPI *TOOLMFN)(MODULEENTRY FAR *, LPCSTR); + +static BOOL +dllfix(void) +{ +HMODULE hdll; // module handle of DLL +HMODULE hgswin16; // module handle of Ghostscript +MODULEENTRY me_dll; // to contain details about DLL module +MODULEENTRY me_gswin16; // details about Ghostscript +HINSTANCE htool; // module handle of TOOLHELP.DLL +TOOLMFN lpfnModuleFindName = NULL; +char buf[256]; +BOOL err = FALSE; + + // load TOOLHELP.DLL + htool = LoadLibrary("TOOLHELP.DLL"); + if ( htool <= HINSTANCE_ERROR ) + err = TRUE; + + // get address of toolhelp function + if (!err) { + lpfnModuleFindName = (TOOLMFN)GetProcAddress(htool, "ModuleFindName"); + err = !lpfnModuleFindName; + } + + // find handle for DLL + if (!err) { + memset(&me_dll, 0, sizeof(me_dll)); + me_dll.dwSize = sizeof(me_dll); + hdll = lpfnModuleFindName(&me_dll, GSDLLNAME); + } + + // look for Ghostscript EXE module + // This should be found because we are it + if (!err) { + memset(&me_gswin16, 0, sizeof(me_gswin16)); + me_gswin16.dwSize = sizeof(me_gswin16); + hgswin16 = lpfnModuleFindName(&me_gswin16, GSEXE); + } + +#ifdef DEBUG + // for debugging, show what we have found + if (hdll) { + wsprintf(buf, "Found %s\nModule Handle=%d\nModule Usage=%d\nModule Path=%s", + me_dll.szModule, me_dll.hModule, me_dll.wcUsage, me_dll.szExePath); + MessageBox((HWND)NULL, buf, szAppName, MB_OK); + } + if (hgswin16) { + wsprintf(buf, "Found %s\nModule Handle=%d\nModule Usage=%d\nModule Path=%s", + me_gswin16.szModule, me_gswin16.hModule, me_gswin16.wcUsage, + me_gswin16.szExePath); + MessageBox((HWND)NULL, buf, szAppName, MB_OK); + } +#endif + + // if DLL loaded and Ghostscript is not running... + if (!err && + hdll && // Ghostscript DLL loaded + (hgswin16 && me_gswin16.wcUsage == 1) // Only one copy of Ghostscript EXE + ) { + wsprintf(buf, "%s is loaded but does not appear to be in use by Ghostscript. Unload it?", GSDLLNAME); + if (MessageBox((HWND)NULL, buf, szAppName, MB_YESNO | MB_ICONHAND) == IDYES) + // If DLL is really in use, we about to cause a disaster + while (GetModuleUsage(hdll)) + FreeLibrary(hdll); + } + + if (htool) + FreeLibrary(htool); + return err; +} +#endif + |