1    | /***************************************
2    |   $Header: /cvsroot/petscgraphics/tsview.c,v 1.34 2004/05/25 14:03:38 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   |   h/?           Print this information\n\
31   |   q/x           Quit tsview\n"
32   | 
33   | #include "illuminator.h"
34   | #include <sys/dir.h> /* For scandir(), alphasort, struct dirent */
35   | #include <libgen.h>  /* For dirname(), basename() */
36   | #include <string.h>  /* For strdup() */
37   | #include <stdlib.h>            /* Needed for readline stuff below */
38   | #include <term.h>              /* ncurses header for readline */
39   | #include <readline/readline.h> /* For command line editing */
40   | #include <readline/history.h>  /* For command line history */
41   | 
42   | /* Build with -DDEBUG for debugging output */
43   | #undef DPRINTF
44   | #ifdef DEBUG
45   | #define DPRINTF(fmt, args...) PetscPrintf (PETSC_COMM_WORLD, "%s: " fmt, __FUNCT__, args)
46   | #else
47   | #define DPRINTF(fmt, args...)
48   | #endif
49   | 
50   | char *basefilename;
51   | 
52   | 
53   | #undef __FUNCT__
54   | #define __FUNCT__ "myfilter"
55   | 
56   | /*++++++++++++++++++++++++++++++++++++++
57   |   This function returns non-zero for "qualifying" file names which start with
58   |   the stored files' basename and end with
59   |   +latex+{\tt .cpu0000.meta}.
60   |   +html+ <tt>.cpu0000.meta</tt>.
61   |   It is used as the
62   |   +latex+{\tt select()} function for {\tt scandir()} in {\tt main()}.
63   |   +html+ <tt>select()</tt> function for <tt>scandir()</tt> in <tt>main()</tt>.
64   | 
65   |   int myfilter Returns non-zero for qualifying filenames.
66   | 
67   |   const struct dirent *direntry Directory entry with filename to test.
68   |   ++++++++++++++++++++++++++++++++++++++*/
69   | 
70   | int myfilter (const struct dirent *direntry)
71   | {
72   |   if ((!strncmp (direntry->d_name, basefilename, strlen(basefilename))))
73   |     return (!strncmp (direntry->d_name + strlen(direntry->d_name) - 13,
74   | 		      ".cpu0000.meta", 13));
75   |   return 0;
76   | }
77   | 
78   | 
79   | /*+++++++++++++++++++++++++++++++++++++
80   | 
81   | Functions for reading the command line
82   | and avoiding reading empty lines
83   | 
84   | Probably this function is not Petsc
85   | safe, but we'll see.
86   | 
87   | +++++++++++++++++++++++++++++++++++++*/
88   | 
89   | /* A static variable for holding the line. */
90   | static char *line_read = (char *)NULL;
91   | 
92   | /* Read a string, and return a pointer to it.
93   |    Returns NULL on EOF. */
94   | 
95   | 
96   | 
97   | char* rl_gets (char* message)
98   | {
99   |   /* If the buffer has already been allocated,
100  |      return the memory to the free pool. */
101  |   if (line_read)
102  |     {
103  |       free (line_read);
104  |       line_read = (char *)NULL;
105  |     }
106  | 
107  |   /* Get a line from the user. */
108  |   line_read = readline (message);
109  | 
110  |   /* If the line has any text in it,
111  |      save it on the history. */
112  |   if (line_read && *line_read)
113  |     add_history (line_read);
114  | 
115  |   return (line_read);
116  | }
117  | 
118  | 
119  | /*
120  |   Failed attempt to make a Petsc safe readline
121  |   Lefted here for reference
122  | 
123  |   It is based on PetscSynchronizedFGets, but instead of using
124  |   fgets() it uses rl_gets()
125  | 
126  | */
127  | 
128  | int PetscSynchronizedFReadline(MPI_Comm comm,char* message,char* string)
129  | {
130  |   int ierr,rank, len;
131  |   PetscFunctionBegin;
132  |   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
133  | 
134  |   /* First processor prints immediately to stdin*/
135  |   if (!rank) {
136  |     string = rl_gets(message);
137  |   }
138  |   
139  |   len = strlen(string);
140  | 
141  |   ierr = MPI_Bcast(string,len,MPI_BYTE,0,comm);CHKERRQ(ierr);
142  |   PetscFunctionReturn(0);
143  | }
144  | 
145  | 
146  | #undef __FUNCT__
147  | #define __FUNCT__ "main"
148  | 
149  | /*++++++++++++++++++++++++++++++++++++++
150  |   This is
151  |   +latex+{\tt main()}.
152  |   +html+ <tt>main()</tt>.
153  | 
154  |   int main It returns an int to the OS.
155  | 
156  |   int argc Argument count.
157  | 
158  |   char *argv[] Arguments.
159  |   ++++++++++++++++++++++++++++++++++++++*/
160  | 
161  | int main (int argc, char *argv[])
162  | {
163  |   int total_entries, current_entry, dims, i, ierr, windowsize=300, plots=0,
164  |     increment=1;
165  |   struct dirent **namelist;
166  |   char **files, *thefilename, *filec, *dirc, *basedirname;
167  |   PetscViewer theviewer;
168  |   PetscTruth loaded = PETSC_FALSE, transp=PETSC_TRUE,
169  |     xcut=PETSC_FALSE, ycut=PETSC_FALSE, zcut=PETSC_FALSE;
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 = DATriangulate (theda, global, display_field, minmax,
369  | 				    plots, plot_vals, plot_colors,
370  | 				    xcut, ycut, zcut);
371  | 	    }
372  | 	  else
373  | 	    {
374  | 	      ierr = DATriangulate (theda, global, display_field, minmax,
375  | 				    PETSC_DECIDE, PETSC_NULL, PETSC_NULL,
376  | 				    xcut, ycut, zcut);
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  | 	      xcut = !xcut;
605  | 	    if (instring[1] == 'y' || instring[1] == 'Y')
606  | 	      ycut = !ycut;
607  | 	    if (instring[1] == 'z' || instring[1] == 'Z')
608  | 	      zcut = !zcut;
609  | 	    break;
610  | 	  }
611  | 	default:
612  | 	  current_entry+=increment;
613  | 	}
614  |       if (current_entry < 0)
615  | 	current_entry = total_entries-1;
616  |       if (current_entry >= total_entries)
617  | 	current_entry = 0;
618  |     }
619  | 
620  |   free (filec);
621  |   free (dirc);
622  | }