home *** CD-ROM | disk | FTP | other *** search
/ swCHIP 1991 January / swCHIP_95-1.bin / utility / gsview13 / src / gvpdisp.c < prev    next >
C/C++ Source or Header  |  1995-12-09  |  10KB  |  370 lines

  1. /* Copyright (C) 1993, 1994, Russell Lang.  All rights reserved.
  2.   
  3.   This file is part of GSview.
  4.   
  5.   This program is distributed with NO WARRANTY OF ANY KIND.  No author
  6.   or distributor accepts any responsibility for the consequences of using it,
  7.   or for whether it serves any particular purpose or works at all, unless he
  8.   or she says so in writing.  Refer to the GSview Free Public Licence 
  9.   (the "Licence") for full details.
  10.   
  11.   Every copy of GSview must include a copy of the Licence, normally in a 
  12.   plain ASCII text file named LICENCE.  The Licence grants you the right 
  13.   to copy, modify and redistribute GSview, but only under certain conditions 
  14.   described in the Licence.  Among other things, the Licence requires that 
  15.   the copyright notice and this notice be preserved on all copies.
  16. */
  17.  
  18. /* gvpdisp.c */
  19. /* Display GSview routines for PM */
  20. #include "gvpm.h"
  21.  
  22.  
  23. /* execute program */
  24. BOOL
  25. exec_pgm(char *name, char *arg, BOOL withpipe, PROG* prog)
  26. {
  27.     STARTDATA sdata;
  28.     APIRET rc;
  29.     char buf[256];
  30.     CHAR progname[256];
  31.     PROG pg;
  32.     int pipe_handle[2];
  33.     PTIB pptib;
  34.     PPIB pppib;
  35.  
  36.     if (prog->valid)
  37.         stop_pgm(prog);
  38.     memset(&pg, 0, sizeof(PROG));
  39.  
  40.     if (DosGetInfoBlocks(&pptib, &pppib)) {
  41.         error_message("\nexec_pgm: Couldn't get environment\n");
  42.         return FALSE;
  43.     }
  44.     /* Look for program in same directory as this EXE */
  45.     progname[0] = '\0';
  46.     if (!strchr(name, '\\'))
  47.         strcpy(progname, szExePath);
  48.     strcat(progname, name);
  49.  
  50.     if (withpipe) {
  51.         /* redirect stdin of new program */
  52. #ifdef __BORLANDC__
  53.         if (_pipe(pipe_handle, 4096, O_BINARY))
  54. #else
  55.         if (pipe(pipe_handle))        /* create a pipe */
  56. #endif
  57.          {
  58.         error_message("exec_pgm: error opening pipe");
  59.         return FALSE;
  60.         }
  61.         if (dup2(pipe_handle[0], 0) < 0) {    /* duplicate read handle to stdin handle */
  62.         error_message("error duplicating pipe");
  63.         return FALSE;
  64.         }
  65.         close(pipe_handle[0]);            /* close surplus handle */
  66.         pg.input = fdopen(pipe_handle[1], "w");    /* open a stream to the write handle */
  67. /*
  68. sprintf(buf,"exec_pgm: input stream = %p, handle = %d", pg.input, pipe_handle[1]);
  69. rmsg(buf);
  70. */
  71.         if (pg.input == (FILE *)NULL) {
  72.         error_message("exec_pgm: error opening write stream for pipe");
  73.         return FALSE;
  74.         }
  75.     }
  76.     
  77.     /* because new program is a different EXE type, 
  78.      * we must use start session not DosExecPgm() */
  79.     sdata.Length = sizeof(sdata);
  80.     sdata.Related = SSF_RELATED_CHILD;    /* to be a child  */
  81.     sdata.FgBg = SSF_FGBG_BACK;        /* start in background */
  82.     sdata.TraceOpt = 0;
  83.     sdata.PgmTitle = name;
  84.     sdata.PgmName = progname;
  85.     sdata.PgmInputs = arg;
  86.     sdata.TermQ = gsview.term_queue_name;
  87.     sdata.Environment = pppib->pib_pchenv;    /* use Parent's environment */
  88.     /* with pipe needs to inherit redirected stdin */
  89.     sdata.InheritOpt = withpipe ? SSF_INHERTOPT_PARENT : 0;
  90.     sdata.SessionType = SSF_TYPE_DEFAULT;        /* default is text */
  91.     sdata.IconFile = NULL;
  92.     sdata.PgmHandle = 0;
  93.     sdata.PgmControl = 0;
  94.     sdata.InitXPos = 0;
  95.     sdata.InitYPos = 0;
  96.     sdata.InitXSize = 0;
  97.     sdata.InitYSize = 0;
  98.     sdata.ObjectBuffer = NULL;
  99.     sdata.ObjectBuffLen = 0;
  100.  
  101. /*
  102. sprintf(buf,"exec_pgm: %s %s\n",sdata.PgmName, sdata.PgmInputs);
  103. message_box(buf, 0);
  104. */
  105.     rc = DosStartSession(&sdata, &pg.session_id, &pg.process_id);
  106.     if (rc == ERROR_FILE_NOT_FOUND) {
  107.         /* didn't find it in same directory as this EXE so try PATH */
  108.         sdata.PgmName = name;
  109.         rc = DosStartSession(&sdata, &pg.session_id, &pg.process_id);
  110.     }
  111.     if (rc) {
  112.         if (withpipe)
  113.             fclose(pg.input);
  114.         sprintf(buf,"\"%s %s\", rc = %d\n", sdata.PgmName, sdata.PgmInputs, rc);
  115.         gserror(IDS_CANNOTRUN, buf, MB_ICONHAND, SOUND_ERROR);
  116.         load_string(IDS_TOPICINSTALL, szHelpTopic, sizeof(szHelpTopic));
  117.         get_help();
  118.         return FALSE;
  119.     }
  120.     pg.valid = TRUE;
  121.     *prog = pg;    /* give details back to caller */
  122.     return TRUE;
  123. }
  124.  
  125.  
  126. /* stop specified program */
  127. void
  128. stop_pgm(PROG* prog)
  129. {
  130. QMSG q_mess;        /* queue message */
  131. int i = 0;
  132.     if (!prog->valid) {
  133.         cleanup_pgm(prog);
  134.         return;
  135.     }
  136.     DosStopSession(STOP_SESSION_SPECIFIED, prog->session_id);
  137.     while (prog->valid && term_tid && (i < 100)) {
  138.         /* wait for termination queue message to cause cleanup_pgm() to be called */
  139.           if (WinGetMsg(hab, &q_mess, 0L, 0, 0))
  140.             WinDispatchMsg(hab, &q_mess);
  141.         i++;
  142.     }
  143.     if (i >= 100)
  144.         gserror(0, "can't stop program", MB_ICONHAND, SOUND_ERROR);
  145. /* cleanup should already have occurred */
  146.     cleanup_pgm(prog);
  147. }
  148.  
  149.  
  150. /* cleanup after program has stopped */
  151. void
  152. cleanup_pgm(PROG* prog)
  153. {
  154.     prog->valid = FALSE;
  155.     if (prog->input)
  156.         fclose(prog->input);
  157.     prog->input = (FILE *)NULL;
  158.     prog->session_id = 0;
  159.     prog->process_id = (PID)0;
  160. }
  161.  
  162. BOOL
  163. pdf_convert(char *name, char *arg, PROG* prog)
  164. {
  165.     STARTDATA sdata;
  166.     APIRET rc;
  167.     char buf[256];
  168.     CHAR progname[256];
  169.     int pipe_handle[2];
  170.     PTIB pptib;
  171.     PPIB pppib;
  172.  
  173.     REQUESTDATA Request;
  174.     ULONG DataLength;
  175.     PVOID DataAddress;
  176.     BYTE ElemPriority;
  177.     char term_queue_name[MAXSTR];
  178.     HQUEUE term_queue;    /* termination queue for child sessions */
  179.  
  180.     if (DosGetInfoBlocks(&pptib, &pppib)) {
  181.         error_message("\nexec_pgm: Couldn't get environment\n");
  182.         return FALSE;
  183.     }
  184.  
  185.     /* create termination queue so we can wait for conversion to finish */
  186.     sprintf(term_queue_name, "\\QUEUES\\PDF_%s", gsview.id);
  187.     if ( (rc = DosCreateQueue(&term_queue, QUE_FIFO, term_queue_name)) != 0 ) {
  188.         sprintf(buf,"Failed to create: \"%s\", rc = %d\n", term_queue_name, rc);
  189.         error_message(buf);
  190.         return FALSE;
  191.     }
  192.  
  193.     /* Look for program in same directory as this EXE */
  194.     progname[0] = '\0';
  195.     if (!strchr(name, '\\'))
  196.         strcpy(progname, szExePath);
  197.     strcat(progname, name);
  198.     
  199.     /* because new program is a different EXE type, 
  200.      * we must use start session not DosExecPgm() */
  201.     sdata.Length = sizeof(sdata);
  202.     sdata.Related = SSF_RELATED_CHILD;    /* to be a child  */
  203.     sdata.FgBg = SSF_FGBG_BACK;        /* start in background */
  204.     sdata.TraceOpt = 0;
  205.     sdata.PgmTitle = name;
  206.     sdata.PgmName = progname;
  207.     sdata.PgmInputs = arg;
  208.     sdata.TermQ = term_queue_name;
  209.     sdata.Environment = pppib->pib_pchenv;    /* use Parent's environment */
  210.     sdata.InheritOpt = 0;
  211.     sdata.SessionType = SSF_TYPE_DEFAULT;        /* default is text */
  212.     sdata.IconFile = NULL;
  213.     sdata.PgmHandle = 0;
  214.     sdata.PgmControl = 0;
  215.     sdata.InitXPos = 0;
  216.     sdata.InitYPos = 0;
  217.     sdata.InitXSize = 0;
  218.     sdata.InitYSize = 0;
  219.     sdata.ObjectBuffer = NULL;
  220.     sdata.ObjectBuffLen = 0;
  221.  
  222. /*
  223. sprintf(buf,"pdf_convert: %s %s\n",sdata.PgmName, sdata.PgmInputs);
  224. message_box(buf, 0);
  225. */
  226.     rc = DosStartSession(&sdata, &prog->session_id, &prog->process_id);
  227.     if (rc == ERROR_FILE_NOT_FOUND) {
  228.         /* didn't find it in same directory as this EXE so try PATH */
  229.         sdata.PgmName = name;
  230.         rc = DosStartSession(&sdata, &prog->session_id, &prog->process_id);
  231.     }
  232.     if (rc) {
  233.         DosCloseQueue(term_queue);
  234.         sprintf(buf,"\"%s %s\", rc = %d\n", sdata.PgmName, sdata.PgmInputs, rc);
  235.         gserror(IDS_CANNOTRUN, buf, MB_ICONHAND, SOUND_ERROR);
  236.         load_string(IDS_TOPICINSTALL, szHelpTopic, sizeof(szHelpTopic));
  237.         get_help();
  238.         return FALSE;
  239.     }
  240.  
  241.     /* wait for PDF converter to finish */
  242.     DosReadQueue(term_queue, &Request, &DataLength, &DataAddress, 
  243.             0, DCWW_WAIT, &ElemPriority, (HEV)NULL);
  244.     if (DataAddress != NULL)
  245.         DosFreeMem(DataAddress);
  246.  
  247.     DosCloseQueue(term_queue);
  248.  
  249.     cleanup_pgm(prog);
  250.     return TRUE;
  251. }
  252.  
  253.  
  254. BOOL
  255. gs_open()
  256. {
  257. char progname[256];
  258. char progargs[256];
  259. char *args;
  260. BOOL flag;
  261. ULONG count;
  262.     /* return if already open */
  263.     if (gsprog.valid)
  264.         return TRUE;
  265.  
  266.     gs_size();
  267.     args = strchr(option.gscommand, ' ');
  268.     if (args) {
  269.         strncpy(progname, option.gscommand, (int)(args-option.gscommand));
  270.         progname[(int)(args-option.gscommand)] = '\0';
  271.         args++;
  272.     }
  273.     else {
  274.         strncpy(progname, option.gscommand, MAXSTR);
  275.         args = "";
  276.     }
  277.     
  278.     sprintf(progargs,"%s -dBitsPerPixel=%d %s -r%gx%g -g%ux%u -sGSVIEW=%s -",
  279.         args, (option.depth ? option.depth : display.bitcount*display.planes), 
  280.         option.safer ? "-dSAFER" : "",
  281.         option.xdpi, option.ydpi, 
  282.                 display.width, display.height,
  283.         gsview.id);
  284.     display.saved = FALSE;
  285.     display.page = FALSE;
  286.     display.sync = FALSE;
  287.     zoom = FALSE;
  288.     display.do_endfile = FALSE;
  289.     display.do_resize = FALSE;
  290.     load_string(IDS_WAITGSOPEN, szWait, sizeof(szWait));
  291.     info_wait(TRUE);
  292.     flag = exec_pgm(progname, progargs, TRUE, &gsprog);
  293.     if (!flag)
  294.         display.do_display = FALSE;
  295.     return flag;
  296. }
  297.  
  298. /* don't create any windows in this routine - can be called from display thread */
  299. /* close Ghostscript */
  300. BOOL
  301. gs_close()
  302. {
  303.     if (display.busy) {
  304.         display.abort = TRUE;
  305.         DosWaitEventSem(display.done, 60000);
  306.     }
  307.     stop_pgm(&gsprog);
  308.     display.saved = FALSE;
  309.     display.epsf_clipped = FALSE;
  310.     display.page = FALSE;
  311.     display.sync = FALSE;
  312.     /* mark bitmap as unused */
  313.     if (DosRequestMutexSem(gsview.bmp_mutex, 10000) == ERROR_TIMEOUT)
  314.         message_box("gs_close: mutex timeout", 0);
  315.     DosEnterCritSec();
  316.     DosFreeMem((PVOID)bitmap.pbmi);
  317.     bitmap.valid = FALSE;
  318.     DosExitCritSec();
  319.     DosReleaseMutexSem(gsview.bmp_mutex);
  320.     return TRUE;
  321. }
  322.  
  323. /* send a NEXT_PAGE message to Ghostscript */
  324. void
  325. next_page()
  326. {
  327.     DosPostEventSem(gsview.next_event);
  328.     display.page = FALSE;
  329. }
  330.  
  331. /* return TRUE if file length or modification time changed */
  332. BOOL
  333. psfile_changed(void)
  334. {
  335. time_t thisftime;
  336. long thisflength;
  337. struct stat fstatus;
  338.     fstat(fileno(psfile.file), &fstatus);
  339.     thisftime = fstatus.st_mtime;
  340.     thisflength = fstatus.st_size;
  341.     return ( (thisflength != psfile.length) ||
  342.         memcmp(&thisftime, &psfile.datetime, sizeof(thisftime)) );
  343. }
  344.  
  345. void
  346. psfile_savestat(void)
  347. {
  348. struct stat fstatus;
  349.     fstat(fileno(psfile.file), &fstatus);
  350.     psfile.datetime = fstatus.st_mtime;
  351.     psfile.length = fstatus.st_size;
  352. }
  353.  
  354.  
  355. /* true if pipe has just been reset */
  356. BOOL is_pipe_done(void)
  357. {
  358.     if (display.end)
  359.        return TRUE;
  360. /*
  361.     if (display.sync)
  362.        return TRUE;
  363. */
  364.     if (!gsprog.valid)
  365.        return TRUE;
  366.     return FALSE;
  367. }
  368.  
  369.  
  370.