1    | /***************************************
2    |   $Header: /cvsroot/petscgraphics/tsview.c,v 1.35 2004/07/02 20:50:41 hazelsct Exp $
3    | 
4    |   This program views the output of a time series saved using
5    |   +latex+{\tt IlluMultiSave()}.
6    |   +html+ <tt>IlluMultiSave()</tt>.
7    |   It basically just switches between timesteps; future versions may be more
8    |   interesting.  The neat part of it is that it loads multiprocessor data and
9    |   displays it on a single CPU.
10   |   ***************************************/
11   | 
12   | static char help[] = "Displays the output of of a timestep series saved using IlluMultiSave().\n\
13   | Usage:\n\
14   | \n\
15   |   tsview <basename> [-no_transparency]\n\
16   | \n\
17   | Then interactively flip through the timesteps (h or ? lists commands).\n";
18   | 
19   | #define HELP_STRING "tsview commands:\n\
20   |   <enter>       Display next timestep\n\
21   |   b             Display previous timestep\n\
22   |   i increment   Set the next timestep increment\n\
23   |   ###           Jump to timestep ###\n\
24   |   t             Toggle Geomview transparency (3-D only)\n\
25   |   v             Change field displayed (3-D only)\n\
26   |   p [v1 v2 ...] Set contour values for plotting or \"auto\" (3-D only)\n\
27   |   r             Reloads entries in a directory\n\
28   |   s size        Set maximum dimension of PETSc viewer windows (2-D only)\n\
29   |   cx, cy, cz    Toggle xcut, ycut, zcut (cut last row/plane of periodic DA)\n\
30   |   gx30-90, y,z  Set plot x range to 30-90, same for y and z\n\
31   |   h/?           Print this information\n\
32   |   q/x           Quit tsview\n"
33   | 
34   | #include "illuminator.h"
35   | #include <sys/dir.h> /* For scandir(), alphasort, struct dirent */
36   | #include <libgen.h>  /* For dirname(), basename() */
37   | #include <string.h>  /* For strdup() */
38   | #include <stdlib.h>            /* Needed for readline stuff below */
39   | #include <term.h>              /* ncurses header for readline */
40   | #include <readline/readline.h> /* For command line editing */
41   | #include <readline/history.h>  /* For command line history */
42   | 
43   | /* Build with -DDEBUG for debugging output */
44   | #undef DPRINTF
45   | #ifdef DEBUG
46   | #define DPRINTF(fmt, args...) PetscPrintf (PETSC_COMM_WORLD, "%s: " fmt, __FUNCT__, args)
47   | #else
48   | #define DPRINTF(fmt, args...)
49   | #endif
50   | 
51   | char *basefilename;
52   | 
53   | 
54   | #undef __FUNCT__
55   | #define __FUNCT__ "myfilter"
56   | 
57   | /*++++++++++++++++++++++++++++++++++++++
58   |   This function returns non-zero for "qualifying" file names which start with
59   |   the stored files' basename and end with
60   |   +latex+{\tt .cpu0000.meta}.
61   |   +html+ <tt>.cpu0000.meta</tt>.
62   |   It is used as the
63   |   +latex+{\tt select()} function for {\tt scandir()} in {\tt main()}.
64   |   +html+ <tt>select()</tt> function for <tt>scandir()</tt> in <tt>main()</tt>.
65   | 
66   |   int myfilter Returns non-zero for qualifying filenames.
67   | 
68   |   const struct dirent *direntry Directory entry with filename to test.
69   |   ++++++++++++++++++++++++++++++++++++++*/
70   | 
71   | int myfilter (const struct dirent *direntry)
72   | {
73   |   if ((!strncmp (direntry->d_name, basefilename, strlen(basefilename))))
74   |     return (!strncmp (direntry->d_name + strlen(direntry->d_name) - 13,
75   | 		      ".cpu0000.meta", 13));
76   |   return 0;
77   | }
78   | 
79   | 
80   | /*+++++++++++++++++++++++++++++++++++++
81   | 
82   | Functions for reading the command line
83   | and avoiding reading empty lines
84   | 
85   | Probably this function is not Petsc
86   | safe, but we'll see.
87   | 
88   | +++++++++++++++++++++++++++++++++++++*/
89   | 
90   | /* A static variable for holding the line. */
91   | static char *line_read = (char *)NULL;
92   | 
93   | /* Read a string, and return a pointer to it.
94   |    Returns NULL on EOF. */
95   | 
96   | 
97   | 
98   | char* rl_gets (char* message)
99   | {
100  |   /* If the buffer has already been allocated,
101  |      return the memory to the free pool. */
102  |   if (line_read)
103  |     {
104  |       free (line_read);
105  |       line_read = (char *)NULL;
106  |     }
107  | 
108  |   /* Get a line from the user. */
109  |   line_read = readline (message);
110  | 
111  |   /* If the line has any text in it,
112  |      save it on the history. */
113  |   if (line_read && *line_read)
114  |     add_history (line_read);
115  | 
116  |   return (line_read);
117  | }
118  | 
119  | 
120  | /*
121  |   Failed attempt to make a Petsc safe readline
122  |   Lefted here for reference
123  | 
124  |   It is based on PetscSynchronizedFGets, but instead of using
125  |   fgets() it uses rl_gets()
126  | 
127  | */
128  | 
129  | int PetscSynchronizedFReadline(MPI_Comm comm,char* message,char* string)
130  | {
131  |   int ierr,rank, len;
132  |   PetscFunctionBegin;
133  |   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
134  | 
135  |   /* First processor prints immediately to stdin*/
136  |   if (!rank) {
137  |     string = rl_gets(message);
138  |   }
139  |   
140  |   len = strlen(string);
141  | 
142  |   ierr = MPI_Bcast(string,len,MPI_BYTE,0,comm);CHKERRQ(ierr);
143  |   PetscFunctionReturn(0);
144  | }
145  | 
146  | 
147  | #undef __FUNCT__
148  | #define __FUNCT__ "main"
149  | 
150  | /*++++++++++++++++++++++++++++++++++++++
151  |   This is
152  |   +latex+{\tt main()}.
153  |   +html+ <tt>main()</tt>.
154  | 
155  |   int main It returns an int to the OS.
156  | 
157  |   int argc Argument count.
158  | 
159  |   char *argv[] Arguments.
160  |   ++++++++++++++++++++++++++++++++++++++*/
161  | 
162  | int main (int argc, char *argv[])
163  | {
164  |   int total_entries, current_entry, dims, i, ierr, windowsize=300, plots=0,
165  |     increment=1, xmin=0,xmax=-1, ymin=0,ymax=-1, zmin=0,zmax=-1;
166  |   struct dirent **namelist;
167  |   char **files, *thefilename, *filec, *dirc, *basedirname;
168  |   PetscViewer theviewer;
169  |   PetscTruth loaded = PETSC_FALSE, transp=PETSC_TRUE;
170  | 
171  |   if (argc<2)
172  |     {
173  |       ierr = PetscPrintf (PETSC_COMM_WORLD, "Usage: tsview basename\n");
174  |       CHKERRQ (ierr);
175  |       return 1;
176  |     }
177  | 
178  |   /*+ After
179  |     +latex+{\tt PETSc}
180  |     +html+ <tt>PETSc</tt>
181  |     initialization, it gets the list of files matching the basename. +*/
182  |   ierr = PetscInitialize (&argc, &argv, (char *)0, help); CHKERRQ (ierr);
183  | 
184  |   DPRINTF ("Command line:",0); CHKERRQ (ierr);
185  | #ifdef DEBUG
186  |   for (i=0; i<argc; i++)
187  |     {
188  |       ierr = PetscPrintf (PETSC_COMM_WORLD, " %s", argv[i]); CHKERRQ (ierr);
189  |     }
190  |   ierr = PetscPrintf (PETSC_COMM_WORLD, "\n"); CHKERRQ (ierr);
191  | #endif
192  | 
193  |   filec = strdup (argv[1]);
194  |   dirc = strdup (argv[1]);
195  |   basefilename = basename (filec);
196  |   basedirname = dirname (dirc);
197  | 
198  |   ierr = PetscOptionsHasName (PETSC_NULL, "-no_transparency", &transp);
199  |   CHKERRQ (ierr);
200  |   transp = !transp;
201  | 
202  |   total_entries = scandir (basedirname, &namelist, myfilter, alphasort);
203  |   if (!total_entries)
204  |     {
205  |       ierr = PetscPrintf (PETSC_COMM_WORLD, "No such files, exiting\n");
206  |       CHKERRQ (ierr);
207  |       exit (1);
208  |     }
209  |   if (total_entries < 0)
210  |     {
211  |       ierr = PetscPrintf (PETSC_COMM_WORLD, "Error scanning directory %s\n",
212  | 			  basedirname); CHKERRQ (ierr);
213  |       ierr = PetscFinalize (); CHKERRQ(ierr);
214  |       return 1;
215  |     }
216  |   ierr = PetscPrintf (PETSC_COMM_WORLD, "%d eligible files:\n", total_entries);
217  |   CHKERRQ (ierr);
218  | 
219  |   if (!(files = (char **) malloc (total_entries * sizeof (char *))))
220  |     {
221  |       ierr = PetscPrintf (PETSC_COMM_WORLD, "Error allocating memory\n");
222  |       CHKERRQ (ierr);
223  |       ierr = PetscFinalize (); CHKERRQ(ierr);
224  |       return 1;
225  |     }
226  |   for (i=0; i<total_entries; i++)
227  |     {
228  |       int filength = strlen(namelist[i]->d_name);
229  | 
230  |       files [i] = (char *) malloc ((filength-12)*sizeof(char));
231  |       strncpy (files [i], namelist[i]->d_name, filength-13);
232  |       files [i] [filength-13] = '\0';
233  |       free (namelist[i]);
234  |       ierr = PetscPrintf (PETSC_COMM_WORLD, "[%d] %s\n", i, files [i]);
235  |       CHKERRQ (ierr);
236  |     }
237  |   free (namelist);
238  | 
239  |   /*+In the main loop, the various timesteps are displayed, with options:
240  |     +latex+\begin{itemize} \item
241  |     +html+ <ul><li>
242  |     A number jumps to that entry in the files table.
243  |     +latex+\item {\stt <return>}
244  |     +html+ <li><tt>&lt;return&gt;</tt>
245  |     loads the next file.
246  |     +latex+\item {\tt b}
247  |     +html+ <li><tt>b</tt>
248  |     goes back one file.
249  |     +latex+\item {\tt q}
250  |     +html+ <li><tt>q</tt>
251  |     quits the program.
252  |     +latex+\end{itemize}
253  |     +html+ </ul>
254  |     +*/
255  |   current_entry=0;
256  |   while (1)
257  |     {
258  |       DA theda;
259  |       Vec global;
260  |       int usermetacount=0, fields, display_field;
261  |       char basis [strlen(argv[1]) + 20], **usermetanames, **usermetadata,
262  | 	*instring;
263  |       PetscScalar minmax[6], plot_vals[6], plot_colors[24] =
264  | 	{ 1.,0.,0.,.5, 1.,1.,0.,.5, 0.,1.,0.,.5, 0.,1.,1.,.5, 0.,0.,1.,.5,
265  | 	  1.,0.,1.,.5 };
266  |       field_plot_type *fieldtypes;
267  | 
268  |       /* Load the vector */
269  |       strcpy (basis, basedirname);
270  |       strcat (basis, "/");
271  |       strcat (basis, files[current_entry]);
272  |       ierr = PetscPrintf (PETSC_COMM_WORLD, "Loading entry %d, basename %s\n",
273  | 			  current_entry, basis);
274  |       if (loaded)
275  | 	{
276  | 	  ierr = IlluMultiRead (theda, global, basis, &usermetacount,
277  | 				&usermetanames, &usermetadata);
278  | 	  CHKERRQ (ierr);
279  | 	}
280  |       else
281  | 	{
282  | 	  DPRINTF ("Loading first timestep, creating distributed array\n",0);
283  | 	  display_field = 0;
284  | 	  minmax [0] = minmax [2] = minmax [4] = 0.;
285  | 	  minmax [1] = minmax [3] = minmax [5] = 1.;
286  | 	  ierr = IlluMultiLoad (basis, &theda, minmax+1, minmax+3, minmax+5,
287  | 				&fieldtypes, &usermetacount, &usermetanames,
288  | 				&usermetadata); CHKERRQ (ierr);
289  | 	  ierr = DAGetGlobalVector (theda, &global); CHKERRQ (ierr);
290  | 	  loaded = PETSC_TRUE;
291  | 
292  | 	  ierr = DAGetInfo (theda, &dims, PETSC_NULL,PETSC_NULL,PETSC_NULL,
293  | 			    PETSC_NULL,PETSC_NULL,PETSC_NULL, &fields,
294  | 			    PETSC_NULL,PETSC_NULL,PETSC_NULL); CHKERRQ (ierr);
295  | 
296  | 	  /* Usermetadata xwidth, ywidth, zwidth override minmax in case
297  | 	     version is 0.1. */
298  | 	  for (i=0; i<usermetacount; i++)
299  | 	    {
300  | 	      if (!strncmp (usermetanames [i], "xwidth", 6))
301  | 		sscanf (usermetadata [i], "%lf", minmax+1);
302  | 	      else if (!strncmp (usermetanames [i], "ywidth", 6))
303  | 		sscanf (usermetadata [i], "%lf", minmax+3);
304  | 	      else if (!strncmp (usermetanames [i], "zwidth", 6))
305  | 		sscanf (usermetadata [i], "%lf", minmax+5);
306  | 	    }
307  | 
308  | 	  if (dims<3)
309  | 	    {
310  | 	      int width=windowsize, height=windowsize;
311  | 
312  | 	      ierr = PetscPrintf (PETSC_COMM_WORLD,
313  | 				  "For viewing 2-D data, try tsview-ng!\n");
314  | 	      CHKERRQ (ierr);
315  | 
316  | 	      if (minmax[1]<minmax[3])
317  | 		width  *= minmax[1]/minmax[3];
318  | 	      else
319  | 		height *= minmax[3]/minmax[1];
320  | 
321  | 	      ierr = PetscViewerDrawOpen
322  | 		(PETSC_COMM_WORLD, 0, "", PETSC_DECIDE, PETSC_DECIDE,
323  | 		 width, height, &theviewer); CHKERRQ (ierr);
324  | 	    }
325  | 	  else
326  | 	    {
327  | 	      ierr = GeomviewBegin (PETSC_COMM_WORLD);
328  | 	    }
329  | 	}
330  | 
331  |       /* Print user data */
332  |       ierr = PetscPrintf (PETSC_COMM_WORLD, "User data:\n"); CHKERRQ (ierr);
333  |       for (i=0; i<usermetacount; i++)
334  | 	{
335  | 	  ierr = PetscPrintf (PETSC_COMM_WORLD, "%s = %s\n", usermetanames [i],
336  | 			      usermetadata [i]); CHKERRQ (ierr);
337  | 	}
338  | 
339  |       /* View the vector */
340  |       if (dims<3)
341  | 	{
342  | 	  ierr = VecView (global, theviewer); CHKERRQ (ierr);
343  | 	}
344  |       else
345  | 	{
346  | 	  /*+ The Illuminator-based 3-D viewer can only display one field at a
347  | 	    time.  At the beginning, that is field 0, and is cycled using the
348  | 	    +latex+{\tt v}
349  | 	    +html+ <tt>v</tt>
350  | 	    command. +*/
351  | 	  PetscScalar minval, maxval;
352  | 	  char *fieldname;
353  | 
354  | 	  ierr = VecStrideMin (global, display_field, PETSC_NULL, &minval);
355  | 	  CHKERRQ (ierr);
356  | 	  ierr = VecStrideMax (global, display_field, PETSC_NULL, &maxval);
357  | 	  CHKERRQ (ierr);
358  | 	  ierr = DAGetFieldName (theda, display_field, &fieldname);
359  | 	  CHKERRQ (ierr);
360  | 	  ierr = PetscPrintf (PETSC_COMM_WORLD,
361  | 			      "Displaying field %d [%g-%g]: %s\n",
362  | 			      display_field, minval, maxval, fieldname);
363  | 	  CHKERRQ (ierr);
364  | 
365  | 	  DPRINTF ("Calculating triangle locations\n",0);
366  | 	  if (plots)
367  | 	    {
368  | 	      ierr = DATriangulateRange (theda, global, display_field, minmax,
369  | 					 plots, plot_vals, plot_colors,
370  | 					 xmin,xmax, ymin,ymax, zmin,zmax);
371  | 	    }
372  | 	  else
373  | 	    {
374  | 	      ierr = DATriangulateRange (theda, global, display_field, minmax,
375  | 					 PETSC_DECIDE, PETSC_NULL, PETSC_NULL,
376  | 					 xmin,xmax, ymin,ymax, zmin,zmax);
377  | 	      CHKERRQ (ierr);
378  | 	    }
379  | 	  DPRINTF ("Consolidating triangles on head node and visualizing\n",0);
380  | 	  ierr = GeomviewDisplayTriangulation
381  | 	    (PETSC_COMM_WORLD, minmax, fieldname, transp);
382  | 	  CHKERRQ (ierr);
383  | 	}
384  | 
385  |       /* Free user data */
386  |       for (i=0; i<usermetacount; i++)
387  | 	{
388  | 	  free (usermetanames [i]);
389  | 	  free (usermetadata [i]);
390  | 	}
391  |       free (usermetanames);
392  |       free (usermetadata);
393  | 
394  |       /* Get user input */
395  |       /* ierr = PetscPrintf (PETSC_COMM_WORLD, "What to do? (h for options) ");
396  |       CHKERRQ (ierr);
397  |       ierr = PetscSynchronizedFGets (PETSC_COMM_WORLD, stdin, 99, instring);
398  |       CHKERRQ (ierr); */
399  |       /* This is probably not PETSc-safe */
400  |       instring = rl_gets("What to do? (h for options)> ");
401  | 
402  |       switch (instring [0])
403  | 	{
404  | 	case 'q':
405  | 	case 'Q':
406  | 	case 'x':
407  | 	case 'X':
408  | 	  {
409  | 	    if (dims < 3)
410  | 	      {
411  | 		ierr = PetscViewerDestroy (theviewer); CHKERRQ (ierr);
412  | 	      }
413  | 	    else
414  | 	      {
415  | 		ierr = GeomviewEnd (PETSC_COMM_WORLD); CHKERRQ (ierr);
416  | 	      }
417  | 	    ierr = PetscFinalize(); CHKERRQ (ierr);
418  | 	    return 0;
419  | 	  }
420  | 	case 't':
421  | 	case 'T':
422  | 	  {
423  | 	    transp=!transp;
424  | 	    break;
425  | 	  }
426  | 	case 'h':
427  | 	case 'H':
428  | 	case '?':
429  | 	  {
430  | 	    ierr = PetscPrintf (PETSC_COMM_WORLD, HELP_STRING);
431  | 	    break;
432  | 	  }
433  | 	case '0':
434  | 	case '1':
435  | 	case '2':
436  | 	case '3':
437  | 	case '4':
438  | 	case '5':
439  | 	case '6':
440  | 	case '7':
441  | 	case '8':
442  | 	case '9':
443  | 	  {
444  | 	    current_entry = atoi (instring);
445  | 	    break;
446  | 	  }
447  | 	case 'b':
448  | 	case 'B':
449  | 	  {
450  | 	    current_entry--;
451  | 	    break;
452  | 	  }
453  | 	case 'i':
454  | 	case 'I':
455  | 	  {
456  | 	    /* printf ("instring=\"%s\"\n",instring); */
457  | 	    if (instring[1] && instring[2])
458  | 	      {
459  | 		sscanf (instring, "i %d", &increment);
460  | 	      }
461  | 	    else
462  | 	      {
463  | 		ierr=PetscPrintf (PETSC_COMM_WORLD,
464  | 				  "Increment: %d\n",increment);
465  | 		CHKERRQ (ierr);
466  | 	      }
467  | 	    break;
468  | 	  }
469  | 	case 'v':
470  | 	case 'V':
471  | 	  {
472  | 	    if (dims == 3)
473  | 	      display_field = (display_field+1) % fields;
474  | 	    break;
475  | 	  }
476  | 	case 'r':
477  | 	case 'R':
478  | 	  {
479  | 	    total_entries = scandir (basedirname, &namelist, myfilter,
480  | 				     alphasort);
481  | 
482  | 	    if (!(files = (char **) realloc (files,total_entries * sizeof (char *))))
483  | 	      {
484  | 		ierr = PetscPrintf (PETSC_COMM_WORLD, "Error allocating memory\n");
485  | 		CHKERRQ (ierr);
486  | 		ierr = PetscFinalize (); CHKERRQ(ierr);
487  | 		return 1;
488  | 	      }
489  | 	    for (i=0; i<total_entries; i++)
490  | 	      {
491  | 		int filength = strlen(namelist[i]->d_name);
492  | 	
493  | 		files [i] = (char *) malloc ((filength-12)*sizeof(char));
494  | 		strncpy (files [i], namelist[i]->d_name, filength-13);
495  | 		files [i] [filength-13] = '\0';
496  | 		free (namelist[i]);
497  | 		ierr = PetscPrintf (PETSC_COMM_WORLD, "[%d] %s\n", i, files [i]);
498  | 		CHKERRQ (ierr);
499  | 	      }
500  | 	    free (namelist);
501  | 	    
502  | 	    ierr = PetscPrintf (PETSC_COMM_WORLD, "Total Entries: %d\n",
503  | 				total_entries);
504  | 	    CHKERRQ (ierr);
505  | 	    break;
506  | 	  }
507  | 	case 's':
508  | 	case 'S':
509  | 	  {
510  | 	    if (instring[1] && instring[2] && dims<3)
511  | 	      {
512  | 		sscanf (instring+2, "%d", &windowsize);
513  | 
514  | 		if (windowsize)
515  | 		  {
516  | 		    int width=windowsize, height=windowsize;
517  | 
518  | 		    ierr = PetscViewerDestroy (theviewer); CHKERRQ (ierr);
519  | 
520  | 		    if (minmax[1]<minmax[3])
521  | 		      width  *= minmax[1]/minmax[3];
522  | 		    else
523  | 		      height *= minmax[3]/minmax[1];
524  | 
525  | 		    ierr = PetscViewerDrawOpen
526  | 		      (PETSC_COMM_WORLD, 0, "", PETSC_DECIDE, PETSC_DECIDE,
527  | 		       width, height, &theviewer); CHKERRQ (ierr);
528  | 		  }
529  | 		else
530  | 		  {
531  | 		    ierr=PetscPrintf (PETSC_COMM_WORLD,
532  | 				      "Usage: \"s ###\" (2-D only)\n");
533  | 		    CHKERRQ (ierr);
534  | 		  }
535  | 	      }
536  | 	    else
537  | 	      {
538  | 		ierr=PetscPrintf (PETSC_COMM_WORLD,
539  | 				  "Usage: \"s ###\" (2-D only)\n");
540  | 		CHKERRQ (ierr);
541  | 	      }
542  | 	    break;
543  | 	  }
544  | 	case 'p':
545  | 	case 'P':
546  | 	  {
547  | 	    int count=0, newplots=0;
548  | 
549  | 	    if (dims<3)
550  | 	      {
551  | 		ierr=PetscPrintf (PETSC_COMM_WORLD,
552  | 				  "The 'p' command is for 2-D only.\n");
553  | 		CHKERRQ (ierr);
554  | 		break;
555  | 	      }
556  | 
557  | 	    if (instring[1]=='\0' || instring[2]=='\0')
558  | 	      {
559  | 		ierr = PetscPrintf (PETSC_COMM_WORLD,
560  | 				    "Current plot contour isoquants:");
561  | 		CHKERRQ (ierr);
562  | 		if (plots == 0)
563  | 		  {
564  | 		    ierr = PetscPrintf (PETSC_COMM_WORLD,
565  | 					" auto (20%%, 40%%, 60%%, 80%%)");
566  | 		    CHKERRQ (ierr);
567  | 		  }
568  | 		for (count=0; count<plots; count++)
569  | 		  {
570  | 		    ierr = PetscPrintf (PETSC_COMM_WORLD, " %g",
571  | 					plot_vals[count]); CHKERRQ (ierr);
572  | 		  }
573  | 		ierr = PetscPrintf (PETSC_COMM_WORLD, "\n"); CHKERRQ (ierr);
574  | 		break;
575  | 	      }
576  | 
577  | 	    while (newplots<6 && instring[count] != '\0')
578  | 	      {
579  | 		while ((instring[count] < '0' || instring[count] > '9') &&
580  | 		       instring[count] != '-' && instring[count] != '.' &&
581  | 		       instring[count] != '\0')
582  | 		  count++;
583  | 
584  | 		if (instring[count])
585  | 		  {
586  | #if defined(PETSC_USE_SINGLE)
587  | 		    sscanf (instring+count, "%f", plot_vals+newplots);
588  | #else
589  | 		    sscanf (instring+count, "%lf", plot_vals+newplots);
590  | #endif
591  | 		    newplots++;
592  | 		    while ((instring[count] >= '0' && instring[count] <= '9')||
593  | 			   instring[count] == '-' || instring[count] == '.')
594  | 		      count++;
595  | 		  }
596  | 	      }
597  | 	    plots = newplots;
598  | 	    break;
599  | 	  }
600  | 	case 'c':
601  | 	case 'C':
602  | 	  {
603  | 	    if (instring[1] == 'x' || instring[1] == 'X')
604  | 	      xmax = (xmax == -2) ? -1 : -2;
605  | 	    if (instring[1] == 'y' || instring[1] == 'Y')
606  | 	      ymax = (ymax == -2) ? -1 : -2;
607  | 	    if (instring[1] == 'z' || instring[1] == 'Z')
608  | 	      zmax = (zmax == -2) ? -1 : -2;
609  | 	    DPRINTF ("x %d-%d, y %d-%d, z %d-%d\n", xmin, xmax, ymin, ymax,
610  | 		     zmin, zmax);
611  | 	    break;
612  | 	  }
613  | 	case 'g':
614  | 	case 'G':
615  | 	  {
616  | 	    int mingrid, maxgrid;
617  | 	    sscanf (instring+2, "%d-%d", &mingrid, &maxgrid);
618  | 	    if (instring[1] == 'x' || instring[1] == 'X')
619  | 	      {
620  | 		xmin = mingrid;
621  | 		xmax = maxgrid;
622  | 	      }
623  | 	    if (instring[1] == 'y' || instring[1] == 'Y')
624  | 	      {
625  | 		ymin = mingrid;
626  | 		ymax = maxgrid;
627  | 	      }
628  | 	    if (instring[1] == 'z' || instring[1] == 'Z')
629  | 	      {
630  | 		zmin = mingrid;
631  | 		zmax = maxgrid;
632  | 	      }
633  | 	    DPRINTF ("x %d-%d, y %d-%d, z %d-%d\n", xmin, xmax, ymin, ymax,
634  | 		     zmin, zmax);
635  | 	    break;
636  | 	  }
637  | 	default:
638  | 	  current_entry+=increment;
639  | 	}
640  |       if (current_entry < 0)
641  | 	current_entry = total_entries-1;
642  |       if (current_entry >= total_entries)
643  | 	current_entry = 0;
644  |     }
645  | 
646  |   free (filec);
647  |   free (dirc);
648  | }