home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 21 / AACD 21.iso / AACD / Utilities / Ghostscript / src / dwmain.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-01-01  |  11.0 KB  |  439 lines

  1. /* Copyright (C) 1996-1998, Russell Lang.  All rights reserved.
  2.   
  3.   This file is part of AFPL Ghostscript.
  4.   
  5.   AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author or
  6.   distributor accepts any responsibility for the consequences of using it, or
  7.   for whether it serves any particular purpose or works at all, unless he or
  8.   she says so in writing.  Refer to the Aladdin Free Public License (the
  9.   "License") for full details.
  10.   
  11.   Every copy of AFPL Ghostscript must include a copy of the License, normally
  12.   in a plain ASCII text file named PUBLIC.  The License grants you the right
  13.   to copy, modify and redistribute AFPL Ghostscript, but only under certain
  14.   conditions described in the License.  Among other things, the License
  15.   requires that the copyright notice and this notice be preserved on all
  16.   copies.
  17. */
  18.  
  19.  
  20. // $Id: dwmain.cpp,v 1.2 2000/09/19 19:00:09 lpd Exp $
  21. // Ghostscript DLL loader for Windows
  22.  
  23. #define STRICT
  24. #include <windows.h>
  25. #include <shellapi.h>
  26. #ifndef __WIN32__
  27. #include <toolhelp.h>
  28. static BOOL dllfix(void);
  29. #endif
  30. #include <stdio.h>
  31. #include <string.h>
  32. #include <stdlib.h>
  33. #include <dos.h>
  34. extern "C" {
  35. #include "gscdefs.h"
  36. #define GSREVISION gs_revision
  37. #include "gsdll.h"
  38. }
  39. #include "dwmain.h"
  40. #include "dwdll.h"
  41. #include "dwtext.h"
  42. #include "dwimg.h"
  43.  
  44. #if defined(_MSC_VER) && defined(__WIN32__)
  45. #define _export
  46. #endif
  47.  
  48. /* public handles */
  49. HINSTANCE ghInstance;
  50.  
  51. /* redirected stdio */
  52. TextWindow tw;
  53.  
  54. const LPSTR szAppName = "Ghostscript";
  55.  
  56. #ifdef __WIN32__
  57. const LPSTR szIniName = "GSWIN32.INI";
  58. const char *szDllName = "GSDLL32.DLL";
  59. #else
  60. const LPSTR szIniName = "GSWIN.INI";
  61. const char *szDllName = "GSDLL16.DLL";
  62. #endif
  63. const LPSTR szIniSection = "Text";
  64.  
  65. int dll_exit_status;
  66.  
  67. int FAR _export gsdll_callback(int message, char FAR *str, unsigned long count);
  68.  
  69. // the Ghostscript DLL class
  70. gsdll_class gsdll;
  71.  
  72. char start_string[] = "systemdict /start get exec\n";
  73.  
  74. // program really starts at WinMain
  75. int
  76. new_main(int argc, char *argv[])
  77. {
  78. typedef char FAR * FARARGV_PTR;
  79. FARARGV_PTR *far_argv;
  80. int rc;
  81.  
  82.     // load DLL
  83.     if (gsdll.load(ghInstance, szDllName, GSREVISION)) {
  84.     char buf[256];
  85.     gsdll.get_last_error(buf, sizeof(buf));
  86.     tw.puts(buf);
  87.     return 1;
  88.     }
  89.  
  90.     
  91. #ifdef __WIN32__
  92.     far_argv = argv;
  93. #else
  94.     far_argv = new FARARGV_PTR[argc+1];
  95.     if (!far_argv)
  96.     return 1;
  97.     for (int i = 0; i<argc; i++)
  98.     far_argv[i] = argv[i];    // convert from near to far pointers
  99.     far_argv[i+1] = NULL;
  100. #endif
  101.  
  102.     // initialize the interpreter
  103.     rc = gsdll.init(gsdll_callback, tw.get_handle(), argc, far_argv);
  104.     if (rc == GSDLL_INIT_QUIT) {
  105.         gsdll.unload();
  106.     return 0;
  107.     }
  108.     if (rc) {
  109.     char buf[256];
  110.     gsdll.get_last_error(buf, sizeof(buf));
  111.     tw.puts(buf);
  112.         gsdll.unload();
  113. #ifndef __WIN32__
  114.     if (rc == GSDLL_INIT_IN_USE)
  115.         dllfix();   // offer option to unload NASTY!
  116. #endif
  117.     return rc;
  118.     }
  119.  
  120.     // if (!batch)
  121.     gsdll.execute(start_string, strlen(start_string));
  122.  
  123. #ifdef UNUSED
  124.     int len;
  125.     char line[256];
  126.     do {
  127.     len = tw.read_line(line, sizeof(line));
  128.     } while ( len && !gsdll.execute(line, len) );
  129. #endif
  130.     
  131.     gsdll.unload();
  132.  
  133.     return 0;
  134. }
  135.  
  136.  
  137. /* our exit handler */
  138. /* also called from Text Window WM_CLOSE */
  139. void win_exit(void)
  140. {
  141.     if (dll_exit_status) {
  142.     /* display message box so error messages in text window can be read */
  143.     char buf[80];
  144.     if (IsIconic(tw.get_handle()))
  145.         ShowWindow(tw.get_handle(), SW_SHOWNORMAL);
  146.     BringWindowToTop(tw.get_handle());  /* make text window visible */
  147.     sprintf(buf, "Exit code %d\nSee text window for details",dll_exit_status);
  148.     MessageBox((HWND)NULL, buf, szAppName, MB_OK | MB_ICONSTOP);
  149.     }
  150. }
  151.  
  152. void
  153. set_font(void)
  154. {
  155.     int fontsize;
  156.     char fontname[256];
  157.     char buf[32];
  158.  
  159.     // read ini file
  160.     GetPrivateProfileString(szIniSection, "FontName", "Courier New", fontname, sizeof(fontname), szIniName);
  161.     fontsize = GetPrivateProfileInt(szIniSection, "FontSize", 10, szIniName);
  162.  
  163.     // set font
  164.     tw.font(fontname, fontsize); 
  165.  
  166.     // write ini file
  167.     WritePrivateProfileString(szIniSection, "FontName", fontname, szIniName);
  168.     sprintf(buf, "%d", fontsize);
  169.     WritePrivateProfileString(szIniSection, "FontSize", buf, szIniName);
  170. }
  171.  
  172. int PASCAL 
  173. WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int cmdShow)
  174. {
  175. #define MAXCMDTOKENS 128
  176.     // BC++ 4.5 will give us _argc and _argv[], but they will be 
  177.     // incorrect if there is a space in the program name.
  178.     // Provide our own parsing code to create argc and argv[]. 
  179.     int argc;
  180.     LPSTR argv[MAXCMDTOKENS];
  181.     LPSTR p;
  182.     char command[256];
  183.     char *args;
  184.     char *d, *e;
  185.  
  186.     /* copy the hInstance into a variable so it can be used */
  187.     ghInstance = hInstance;
  188.  
  189.     if (hPrevInstance) {
  190.     MessageBox((HWND)NULL,"Can't run twice", szAppName, 
  191.         MB_ICONHAND | MB_OK);
  192.     return FALSE;
  193.     }
  194.  
  195.     // If called with "gswin32c.exe arg1 arg2"
  196.     // lpszCmdLine returns:
  197.     //    "arg1 arg2" if called with CreateProcess(NULL, command, ...)
  198.     //    "arg2"      if called with CreateProcess(command, args, ...)
  199.     // GetCommandLine() returns
  200.     //    ""gswin32c.exe" arg1 arg2" 
  201.     //          if called with CreateProcess(NULL, command, ...)
  202.     //    "  arg1 arg2"      
  203.     //          if called with CreateProcess(command, args, ...)
  204.     // Consequently we must use GetCommandLine() 
  205.     p = GetCommandLine();
  206.  
  207.     argc = 0;
  208.     args = (char *)malloc(lstrlen(p)+1);
  209.     if (args == (char *)NULL) {
  210.     fprintf(stdout, "Insufficient memory in WinMain()\n");
  211.     return 1;
  212.     }
  213.    
  214.     // Parse command line handling quotes.
  215.     d = args;
  216.     while (*p) {
  217.     // for each argument
  218.  
  219.     if (argc >= MAXCMDTOKENS - 1)
  220.         break;
  221.  
  222.         e = d;
  223.         while ((*p) && (*p != ' ')) {
  224.         if (*p == '\042') {
  225.         // Remove quotes, skipping over embedded spaces.
  226.         // Doesn't handle embedded quotes.
  227.         p++;
  228.         while ((*p) && (*p != '\042'))
  229.             *d++ =*p++;
  230.         }
  231.         else 
  232.         *d++ = *p;
  233.         if (*p)
  234.         p++;
  235.         }
  236.     *d++ = '\0';
  237.     argv[argc++] = e;
  238.  
  239.     while ((*p) && (*p == ' '))
  240.         p++;    // Skip over trailing spaces
  241.     }
  242.     argv[argc] = NULL;
  243.  
  244.     if (strlen(argv[0]) == 0) {
  245.     GetModuleFileName(hInstance, command, sizeof(command)-1);
  246.     argv[0] = command;
  247.     }
  248.  
  249.  
  250.     /* start up the text window */
  251.     if (!hPrevInstance) {
  252.     HICON hicon = LoadIcon(hInstance, (LPSTR)MAKEINTRESOURCE(GSTEXT_ICON));
  253.     tw.register_class(hInstance, hicon);
  254.     }
  255.     set_font();
  256.     tw.size(80, 80);
  257.     tw.drag("(", ") run\r");
  258.  
  259.     // create the text window
  260.     if (tw.create(szAppName, cmdShow))
  261.     exit(1);
  262.  
  263.     // initialize for image windows
  264.     ImageWindow::hwndtext = tw.get_handle();
  265.     ImageWindow::hInstance = hInstance;
  266.  
  267.     dll_exit_status = new_main(argc, argv);
  268.  
  269.     win_exit();
  270.  
  271.     tw.destroy();
  272.  
  273.     return dll_exit_status;
  274. }
  275.  
  276.  
  277. int FAR _export
  278. gsdll_callback(int message, char FAR *str, unsigned long count)
  279. {
  280. char buf[256];
  281. ImageWindow *iw;
  282.     switch (message) {
  283.     case GSDLL_POLL:
  284.         {
  285.         MSG msg;
  286.         while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
  287.             {
  288.             TranslateMessage(&msg);
  289.             DispatchMessage(&msg);
  290.             }
  291.         }
  292.         // If text window closed then abort Ghostscript
  293.         if (!IsWindow(tw.get_handle()))
  294.         return -1;
  295.         break;
  296.     case GSDLL_STDIN:
  297.         return tw.read_line(str, count);
  298.     case GSDLL_STDOUT:
  299.         if (str != (char *)NULL)
  300.         tw.write_buf(str, count);
  301.         return count;
  302.     case GSDLL_DEVICE:
  303. #ifdef DEBUG
  304.         sprintf(buf,"Callback: DEVICE %p %s\n", (char *)str,
  305.         count ? "open" : "close");
  306.         tw.puts(buf);
  307. #endif
  308.         if (count) {
  309.         iw = new ImageWindow;
  310.         iw->open(str);
  311.         }
  312.         else {
  313.         iw = FindImageWindow(str);
  314.         iw->close();
  315.         }
  316.         break;
  317.     case GSDLL_SYNC:
  318. #ifdef DEBUG
  319.         sprintf(buf,"Callback: SYNC %p\n", (char *)str);
  320.         tw.puts(buf);
  321. #endif
  322.         iw = FindImageWindow(str);
  323.         iw->sync();
  324.         break;
  325.     case GSDLL_PAGE:
  326. #ifdef DEBUG
  327.         sprintf(buf,"Callback: PAGE %p\n", (char *)str);
  328.         tw.puts(buf);
  329. #endif
  330.         iw = FindImageWindow(str);
  331.         iw->page();
  332.         break;
  333.     case GSDLL_SIZE:
  334. #ifdef DEBUG
  335.         sprintf(buf,"Callback: SIZE %p width=%d height=%d\n", (char *)str,
  336.         (int)(count & 0xffff), (int)((count>>16) & 0xffff) );
  337.         tw.puts(buf);
  338. #endif
  339.         iw = FindImageWindow(str);
  340.         iw->size( (int)(count & 0xffff), (int)((count>>16) & 0xffff) );
  341.         break;
  342.     default:
  343.         sprintf(buf,"Callback: Unknown message=%d\n",message);
  344.         tw.puts(buf);
  345.         break;
  346.     }
  347.     return 0;
  348. }
  349.  
  350.  
  351. #ifndef __WIN32__
  352. // This is a hack to cope with a GPF occuring in either Ghostscript
  353. // or a driver loaded by Ghostscript.  If a GPF occurs, gswin16.exe
  354. // is unloaded, but not gsdll16.dll.
  355. // Attempts to reload gswin16.exe will fail because gsdll16.dll
  356. // is already in use.  If this occurs, this code will unload
  357. // gsdll16.dll, EVEN IF SOMEONE ELSE IS USING IT.
  358.  
  359. // The DLL module name as it appears in the module definition file
  360. #define GSDLLNAME "GSDLL16"
  361. // These are the names of EXE modules that are known users
  362. // of the Ghostscript DLL.
  363. // If one of these is running, it is not safe to unload the DLL.
  364. #define GSEXE        "GSWIN16"
  365.  
  366. typedef HMODULE (WINAPI *TOOLMFN)(MODULEENTRY FAR *, LPCSTR);
  367.  
  368. static BOOL
  369. dllfix(void)
  370. {
  371. HMODULE hdll;            // module handle of DLL
  372. HMODULE hgswin16;        // module handle of Ghostscript
  373. MODULEENTRY me_dll;         // to contain details about DLL module
  374. MODULEENTRY me_gswin16;  // details about Ghostscript
  375. HINSTANCE htool;        // module handle of TOOLHELP.DLL
  376. TOOLMFN lpfnModuleFindName = NULL;
  377. char buf[256];
  378. BOOL err = FALSE;
  379.  
  380.     // load TOOLHELP.DLL
  381.     htool = LoadLibrary("TOOLHELP.DLL");
  382.     if ( htool <= HINSTANCE_ERROR )
  383.     err = TRUE;
  384.  
  385.     // get address of toolhelp function
  386.     if (!err) {
  387.     lpfnModuleFindName = (TOOLMFN)GetProcAddress(htool, "ModuleFindName");
  388.     err = !lpfnModuleFindName;
  389.     }
  390.  
  391.     // find handle for DLL
  392.     if (!err) {
  393.     memset(&me_dll, 0, sizeof(me_dll));
  394.     me_dll.dwSize = sizeof(me_dll);
  395.     hdll = lpfnModuleFindName(&me_dll, GSDLLNAME);
  396.     }
  397.  
  398.     // look for Ghostscript EXE module
  399.     // This should be found because we are it
  400.     if (!err) {
  401.     memset(&me_gswin16, 0, sizeof(me_gswin16));
  402.     me_gswin16.dwSize = sizeof(me_gswin16);
  403.     hgswin16 = lpfnModuleFindName(&me_gswin16, GSEXE);
  404.     }
  405.  
  406. #ifdef DEBUG
  407.     // for debugging, show what we have found
  408.     if (hdll) {
  409.     wsprintf(buf, "Found %s\nModule Handle=%d\nModule Usage=%d\nModule Path=%s",
  410.     me_dll.szModule, me_dll.hModule, me_dll.wcUsage, me_dll.szExePath);
  411.     MessageBox((HWND)NULL, buf, szAppName, MB_OK);
  412.     }
  413.     if (hgswin16) {
  414.     wsprintf(buf, "Found %s\nModule Handle=%d\nModule Usage=%d\nModule Path=%s",
  415.     me_gswin16.szModule, me_gswin16.hModule, me_gswin16.wcUsage,
  416.     me_gswin16.szExePath);
  417.     MessageBox((HWND)NULL, buf, szAppName, MB_OK);
  418.     }
  419. #endif
  420.  
  421.     // if DLL loaded and Ghostscript is not running...
  422.     if (!err &&
  423.     hdll &&         // Ghostscript DLL loaded
  424.     (hgswin16 && me_gswin16.wcUsage == 1) // Only one copy of Ghostscript EXE
  425.     ) {
  426.     wsprintf(buf, "%s is loaded but does not appear to be in use by Ghostscript. Unload it?", GSDLLNAME);
  427.     if (MessageBox((HWND)NULL, buf, szAppName, MB_YESNO | MB_ICONHAND) == IDYES)
  428.         // If DLL is really in use, we about to cause a disaster
  429.         while (GetModuleUsage(hdll))
  430.         FreeLibrary(hdll);
  431.     }
  432.  
  433.     if (htool)
  434.     FreeLibrary(htool);
  435.     return err;
  436. }
  437. #endif
  438.  
  439.