I would love to see the attached patch integrated into gv.

The main purpose of the patch is to fix gv when input comes from stdin,
such as
cat <file1.ps> <file2.ps> | gv -

However, the patch also fixes several bugs that have crept into gv
over the years (I have been patching my local version of gv for
more than a decade).

Bug fixes:

1. A few years back gv was updated to use the standard gnu getopt.
This is fine, but the update overrode getopt's built-in option counter,
with an
opt_counter++
for each option.  This is not only bad programming practice, but breaks
getopt's built-in behaviour in some circumstances, such as when
there are multiple arguments.

2. Broken --arguments fixed.
   Broken --safer fixed.

3. The - argument, indicating input from stdin, which has been broken
for many years, is fixed.   Indeed, it has been broken for so long
that the man page no longer documents it.  However, the - argument
is implemented in gv, and should not be allowed to disappear for
lack of attention.

Andrew Hamilton

--- gv-3.6.6/src/main.c.orig	2008-08-24 04:33:48.000000000 -0600
+++ gv-3.6.6/src/main.c	2009-02-07 08:32:35.000000000 -0700
@@ -341,7 +341,6 @@
     Dimension    maximum_width,maximum_height;
     unsigned int gwidth=0,gheight=0;
     int          dim_forced;
-    int          opt_counter=0;
     int          c;
 
 /*###  initializing global variables ####################################*/
@@ -442,11 +441,9 @@
 	 {
 	 case CENTER_ARG:
 	   center_p = 1;
-	   opt_counter++;
 	   break;
 	 case NOCENTER_ARG:
 	   nocenter_p = 1;
-	   opt_counter++;
 	   break;
 	 case SCALE_ARG:
 	   if (strstr(optarg, "."))
@@ -460,29 +457,23 @@
 	      scale_p = 1;
 	      scale_value = optarg;
 	   }
-	   opt_counter++;
 	   break;
 	 case MAGSTEP_ARG:
 	   magstep_p = 1;
 	   magstep_value = optarg;
-	   opt_counter++;
 	   break;
 	 case SCALEBASE_ARG:
 	   scalebase_p = 1;
 	   scalebase_value = optarg;
-	   opt_counter++;
 	   break;
 	 case RESIZE_ARG:
 	   resize_p = 1;
-	   opt_counter++;
 	   break;
 	 case NORESIZE_ARG:
 	   noresize_p = 1;
-	   opt_counter++;
 	   break;
 	 case FULLSCREEN_ARG:
 	   fullscreen_p = 1;
-	   opt_counter++;
 	   break;
 	 case PRESENTATION_ARG:
 	   fullscreen_p = 1;
@@ -490,86 +481,66 @@
 	   widgetless_p = 1;
 	   scale_p = 1;
 	   scale_value = "-1000";
-	   opt_counter++;
 	   break;
 	 case SWAP_ARG:
 	   swap_p = 1;
-	   opt_counter++;
 	   break;
 	 case NOSWAP_ARG:
 	   noswap_p = 1;
-	   opt_counter++;
 	   break;
 	 case DSC_ARG:
 	   dsc_p = 1;
-	   opt_counter++;
 	   break;
 	 case NODSC_ARG:
 	   nodsc_p = 1;
-	   opt_counter++;
 	   break;
 	 case EOF_ARG:
 	   eof_p = 1;
-	   opt_counter++;
 	   break;
 	 case NOEOF_ARG:
 	   noeof_p = 1;
-	   opt_counter++;
 	   break;
 	 case WATCH_ARG:
 	   watch_p = 1;
-	   opt_counter++;
 	   break;
 	 case NOWATCH_ARG:
 	   nowatch_p = 1;
-	   opt_counter++;
 	   break;
 	 case AD_ARG:
 	   ad_p = 1;
 	   ad_value = optarg;
-	   opt_counter++;
 	   break;
 	 case STYLE_ARG:
 	   style_p = 1;
 	   style_value = optarg;
-	   opt_counter++;
 	   break;
 	 case ARGUMENTS_ARG:
 	   arguments_p = 1;
 	   arguments_value = optarg;
-	   opt_counter++;
 	   break;
 	 case PIXMAP_ARG:
 	   pixmap_p = 1;
-	   opt_counter++;
 	   break;
 	 case NOPIXMAP_ARG:
 	   nopixmap_p = 1;
-	   opt_counter++;
 	   break;
 	 case SAFER_ARG:
 	   safer_p = 1;
-	   opt_counter++;
 	   break;
 	 case NOSAFER_ARG:
 	   nosafer_p = 1;
-	   opt_counter++;
 	   break;
 	 case ANTIALIAS_ARG:
 	   antialias_p = 1;
-	   opt_counter++;
 	   break;
 	 case NOANTIALIAS_ARG:
 	   noantialias_p = 1;
-	   opt_counter++;
 	   break;
 	 case COLOR_ARG:
 	   color_p = 1;
-	   opt_counter++;
 	   break;
 	 case GRAYSCALE_ARG:
 	   grayscale_p = 1;
-	   opt_counter++;
 	   break;
 	 case HELP_ARG:
 	   /* Show some help and return */
@@ -577,37 +548,29 @@
 	   exit(0);
 	 case QUIET_ARG:
 	   quiet_p = 1;
-	   opt_counter++;
 	   break;
 	 case INFOSILENT_ARG:
 	   infoverbose_p = 0;
-	   opt_counter++;
 	   break;
 	 case INFOERRORS_ARG:
 	   infoverbose_p = 1;
-	   opt_counter++;
 	   break;
 	 case INFOALL_ARG:
 	   infoverbose_p = 2;
-	   opt_counter++;
 	   break;
 	 case DEBUG_ARG:
 	   debug_p = 1;
-	   opt_counter++;
 	   break;
 	 case MONOCHROME_ARG:
 	   monochrome_p = 1;
-	   opt_counter++;
 	   break;
 	 case NOQUIET_ARG:
 	   noquiet_p = 1;
-	   opt_counter++;
 	   break;
 	 case MEDIA_ARG:
 	   {
 	     media_p = 1;
 	     media_value = optarg;
-	     opt_counter++;
 	     break;
 	   }
 	    
@@ -615,7 +578,6 @@
 	   {
 	     orientation_p = 1;
 	     orientation_value = optarg;
-	     opt_counter++;
 	     break;
 	   }
 
@@ -623,7 +585,6 @@
 	   {
 	     page_p = 1;
 	     page_value = optarg;
-	     opt_counter++;
 	     break;
 	   }
 
@@ -634,17 +595,14 @@
 
 	 case PASSWORD_ARG:
 	   gv_pdf_password = GV_XtNewString(optarg);
-	   opt_counter++;
 	   break;
 
 	 case SPARTAN_ARG:
 	   spartan_p = 1;
-	   opt_counter++;
 	   break;
 
 	 case WIDGETLESS_ARG:
 	   widgetless_p = 1;
-	   opt_counter++;
 	   break;
 
 	 case VERSION_ARG:
@@ -1182,9 +1140,9 @@
 
    INFMESSAGE(checking gv_filename and opening psfile)
 
-   if (argc == (opt_counter + 2)) 
+   if (argc == optind + 1) 
      {
-       gv_filename=GV_XtNewString(argv[opt_counter + 1]);
+       gv_filename=GV_XtNewString(argv[optind]);
      }
 
    if (gv_filename && strcmp(gv_filename, "-")) {
@@ -1415,21 +1373,39 @@
   main_setInternResource(db,&gv_gs_cmd_conv_pdf,"gsCmdConvPDF");
   main_setInternResource(db,&gv_gs_x11_device,"gsX11Device");
   main_setInternResource(db,&gv_gs_x11_alpha_device,"gsX11AlphaDevice");
+
   main_setInternResource(db,&gv_gs_arguments,"gsArguments");
+  s = resource_getResource(db,gv_class,gv_name,"arguments","Arguments");
+  if (s) gv_gs_arguments = s;
+
   s = resource_getResource(db,gv_class,gv_name,"gsSafer",NULL);
-  if (!strcasecmp(s,"true"))  gv_gs_safer = 1; else gv_gs_safer = 0;
+  if (s && !strcasecmp(s,"true"))  gv_gs_safer = 1; else gv_gs_safer = 0;
+  s = resource_getResource(db,gv_class,gv_name,"safer","Safer");
+  if (s) {
+    if (!strcasecmp(s,"true"))  gv_gs_safer = 1;
+    else if (!strcasecmp(s,"false"))  gv_gs_safer = 0;
+  }
+
   s = resource_getResource(db,gv_class,gv_name,"gsQuiet",NULL);
-  if (!strcasecmp(s,"true"))  gv_gs_quiet = 1; else gv_gs_quiet = 0;
+  if (s && !strcasecmp(s,"true"))  gv_gs_quiet = 1; else gv_gs_quiet = 0;
+  s = resource_getResource(db,gv_class,gv_name,"quiet","Quiet");
+  if (s) {
+    if (!strcasecmp(s,"true"))  gv_gs_quiet = 1;
+    else if (!strcasecmp(s,"false"))  gv_gs_quiet = 0;
+  }
+
   s = resource_getResource(db,gv_class,gv_name,"infoVerbose",NULL);
   if (!strcasecmp(s, "Silent"))      gv_infoVerbose=0;
   else if (!strcasecmp(s, "Errors")) gv_infoVerbose=1;
   else if (!strcasecmp(s, "All"))    gv_infoVerbose=2;
   else gv_infoVerbose = 1;
+
   s = resource_getResource(db,gv_class,gv_name,"xinerama",NULL);
   if (!strcasecmp(s, "Off"))      gv_xinerama=0;
   else if (!strcasecmp(s, "On")) gv_xinerama=1;
   else if (!strcasecmp(s, "Auto"))    gv_xinerama=-1;
   else gv_xinerama = 0;
+
   ENDMESSAGE(main_setGhostscriptResources)
 }
 
--- gv-3.6.6/src/misc.c.orig	2008-09-09 11:11:04.000000000 -0600
+++ gv-3.6.6/src/misc.c	2009-02-07 08:22:51.000000000 -0700
@@ -1064,7 +1064,7 @@
     misc_setSensitive(w_printAllPages     , show_printAllPages     , (gv_psfile   != NULL));
     misc_setSensitive(w_checkFile         , show_checkFile         , (gv_filename != NULL));
     misc_setSensitive(w_updateFile        , show_updateFile        , (gv_filename != NULL));
-    misc_setSensitive(w_showThisPage      , show_showThisPage      , (gv_psfile   != NULL));
+    misc_setSensitive(w_showThisPage      , show_showThisPage      , (gv_psfile   != NULL || (gv_gs_arguments && *gv_gs_arguments)));
     misc_setSensitive(w_prevPage          , show_prevPage          , (toc_text    != NULL));
     misc_setSensitive(w_nextPage          , show_nextPage          , (gv_filename != NULL));
     misc_setSensitive(w_toggleCurrentPage , show_toggleCurrentPage , (toc_text    != NULL));
@@ -1079,7 +1079,7 @@
     XtSetSensitive(saveAllEntry,     (gv_psfile   != NULL));
     XtSetSensitive(saveMarkedEntry,  (toc_text    != NULL));
     XtSetSensitive(nextEntry,        (gv_filename != NULL));
-    XtSetSensitive(redisplayEntry,   (gv_psfile   != NULL));
+    XtSetSensitive(redisplayEntry,   (gv_psfile   != NULL || (gv_gs_arguments && *gv_gs_arguments)));
     XtSetSensitive(prevEntry,        (toc_text    != NULL));
     XtSetSensitive(currentEntry,     (toc_text    != NULL));
     XtSetSensitive(oddEntry,         (toc_text    != NULL));
--- gv-3.6.6/src/miscmenu.c.orig	2008-06-08 08:08:32.000000000 -0600
+++ gv-3.6.6/src/miscmenu.c	2009-02-07 08:22:51.000000000 -0700
@@ -257,7 +257,7 @@
 	    Boolean b;
 	    if      (e->sensitivity_type==1) b = (toc_text != NULL);
 	    else if (e->sensitivity_type==2) b = (gv_filename != NULL);
-	    else    b = (gv_psfile != NULL);
+	    else    b = (gv_psfile != NULL || (gv_gs_arguments && *gv_gs_arguments));
 	    XtSetSensitive(entry,b);
 	  }
 	} else {
--- gv-3.6.6/src/Ghostview.c.orig	2008-09-09 11:11:04.000000000 -0600
+++ gv-3.6.6/src/Ghostview.c	2009-02-07 08:35:55.000000000 -0700
@@ -1423,6 +1423,7 @@
 	 }
 	 while (isspace(*dptr)) dptr++;
     }
+    argv[argc++] = "-dNOPROMPT";
     argv[argc++] = "-dNOPAUSE";
     if (gv_pdf_password)
     {
@@ -1465,21 +1466,6 @@
 	}
     }
 
-    if (arguments_p == 1) {
-	cptr = arguments = GV_XtNewString(arguments_value);
-	while (isspace(*cptr)) cptr++;
-	while (*cptr) {
-	    argv[argc++] = cptr;
-	    while (*cptr && !isspace(*cptr)) cptr++;
-	    if (*cptr) *cptr++ = '\0';
-	    if (argc + 2 >= NUM_ARGS) {
-		fprintf(stderr, "Too many arguments to interpreter.\n");
-		exit(EXIT_STATUS_ERROR);
-	    }
-	    while (isspace(*cptr)) cptr++;
-	}
-    }
-
 #   ifdef ALLOW_PDF
     if (gvw->ghostview.filename && strcmp(gvw->ghostview.filename,"-")) {
           if ( *(gvw->ghostview.filename) == '-' ) {
@@ -1492,12 +1478,24 @@
              argv[argc++] = gvw->ghostview.filename;
           argv[argc++] = "-c";
           argv[argc++] = "quit";
+    } else
+#   endif
+    if (gvw->ghostview.filename && !strcmp(gvw->ghostview.filename,"-")) {
+       /* The ghostscript documentation states that the "-" argument
+	  tells gs that input is coming from a pipe rather than from stdin.
+	  One of the side effects of the "-" argument is that gs does not
+	  flush output at each line of input, but rather accumulates input
+	  and flushes only when the buffer is full.  Since we want gs to
+	  flush output at each line of input, we therefore cannot send "-".
+	  Unfortunately not sending "-" has the side effect that gs no
+	  longer reads correctly through either multiple PostScript files
+	  or PostScript files with multiple pages.  Ah well.
+	  Should gs ever acquire a -DFLUSH argument, then send gs that argument,
+	  and uncomment the following line.  */
+       /* argv[argc++] = "-"; */
     } else {
        argv[argc++] = "-";
     }
-#   else
-       argv[argc++] = "-";
-#   endif
     argv[argc++] = NULL;
 
     if (gvw->ghostview.filename == NULL) {
@@ -1529,8 +1527,21 @@
     }
 
     gvw->ghostview.changed = False;
-    gvw->ghostview.busy = True;
-    ChangeCursor(gvw,CURSOR_BUSY);
+    if (!((gvw->ghostview.filename && strcmp(gvw->ghostview.filename, "-") == 0)
+       && (gv_gs_arguments && *gv_gs_arguments))) {
+       gvw->ghostview.busy = True;
+       ChangeCursor(gvw,CURSOR_BUSY);
+    }
+
+/*
+    printf("StartInterpreter:\n");
+    printf("%s", argv[0]);
+    for (argc = 1; argv[argc] != NULL; argc++) {
+        printf(" %s", argv[argc]);
+    }
+    printf("\n");
+*/
+
     gvw->ghostview.interpreter_pid = fork();
 
     if (gvw->ghostview.interpreter_pid == 0) { /* child */
@@ -1622,6 +1633,7 @@
       }
     if (gvw->ghostview.interpreter_input >= 0) 
       {
+	INFMESSAGE(removing interpreter input)
 	close(gvw->ghostview.interpreter_input);
 	gvw->ghostview.interpreter_input = -1;
 	if (gvw->ghostview.interpreter_input_id != None) 
@@ -1641,11 +1653,13 @@
 	  }
       }
     if (gvw->ghostview.interpreter_output >= 0) {
+        INFMESSAGE(closing interpreter output)
 	close(gvw->ghostview.interpreter_output);
 	gvw->ghostview.interpreter_output = -1;
 	XtRemoveInput(gvw->ghostview.interpreter_output_id);
     }
     if (gvw->ghostview.interpreter_error >= 0) {
+        INFMESSAGE(closing interpreter error)
 	close(gvw->ghostview.interpreter_error);
 	gvw->ghostview.interpreter_error = -1;
 	XtRemoveInput(gvw->ghostview.interpreter_error_id);
@@ -2164,8 +2178,11 @@
     }
 
     if (!gvw->ghostview.busy) {
-	gvw->ghostview.busy = True;
-        ChangeCursor(gvw,CURSOR_BUSY);
+	if (!((gvw->ghostview.filename && strcmp(gvw->ghostview.filename, "-") == 0)
+	   && (gv_gs_arguments && *gv_gs_arguments))) {
+	    gvw->ghostview.busy = True;
+	    ChangeCursor(gvw,CURSOR_BUSY);
+	}
 	event.xclient.type = ClientMessage;
 	event.xclient.display = XtDisplay(w);
 	event.xclient.window = gvw->ghostview.mwin;
--- gv-3.6.6/src/zoom.c.orig	2008-09-02 05:42:44.000000000 -0600
+++ gv-3.6.6/src/zoom.c	2009-02-07 08:43:42.000000000 -0700
@@ -106,14 +106,16 @@
 
     BEGINMESSAGE(zoom_createZoom)
 
-    if (!gv_psfile) {
+    if (!(gv_psfile != NULL || (gv_gs_arguments && *gv_gs_arguments))) {
        INFMESSAGE(no file) ENDMESSAGE(zoom_createZoom)
        return;
     }
-    stat(gv_filename, &sbuf);
 
-    if (mtime != sbuf.st_mtime) {
-       INFMESSAGE1(file has changed) ENDMESSAGE1(zoom_createZoom)return;
+    if (strcmp(gv_filename, "-")) {
+       stat(gv_filename, &sbuf);
+       if (mtime != sbuf.st_mtime) {
+	  INFMESSAGE1(file has changed) ENDMESSAGE1(zoom_createZoom)return;
+       }
     }
 
     filename = (gv_filename_dsc ? gv_filename_dsc : (gv_filename_unc ? gv_filename_unc : gv_filename));
@@ -230,11 +232,17 @@
     XtPopup(zshell, XtGrabNone);
 
     if (toc_text) {
-	zoomfile = fopen(filename, "r");
-	if (zoomfile == NULL) {
-           ENDMESSAGE(zoom_createZoom)
-	   return;
+	if (!filename) {
+	    zoomfile = NULL;
+	} else if (strcmp(filename, "-")) {
+	    zoomfile = fopen(filename, "r");
+	} else {
+	    zoomfile = stdin;
         }
+	if (zoomfile == NULL) {
+	    ENDMESSAGE(zoom_createZoom)
+	    return;
+	}
 	
         GhostviewEnableInterpreter(zpage);
 	
--- gv-3.6.6/src/resource.c.orig	2009-02-07 12:47:12.000000000 -0700
+++ gv-3.6.6/src/resource.c	2009-02-07 12:43:41.000000000 -0700
@@ -333,6 +333,10 @@
      {
        resource_putResource (&db, app_name, ".style", style_value);
      }
+   if (arguments_p)
+     {
+       resource_putResource (&db, app_name, ".arguments", arguments_value);
+     }
   
   /* ### style resources ######################## */
   INFMESSAGE(checking for style resources)

Reply via email to