tomwalters@0
|
1 /****************************************************************************
|
tomwalters@0
|
2 *
|
tomwalters@0
|
3 * x11plot - a no-scale plot for X11 windows. Mike Allerhand, March 1989.
|
tomwalters@0
|
4 * Also for overplotting multiple files.
|
tomwalters@0
|
5 *
|
tomwalters@0
|
6 * usage: x11plot [options] filename1 [filename2 ...]
|
tomwalters@0
|
7 * where filename is a stream of binary shorts.
|
tomwalters@0
|
8 * Alternatively, input can be piped, as in:
|
tomwalters@0
|
9 * cat filename | x11plot [options]
|
tomwalters@0
|
10 *
|
tomwalters@0
|
11 * mouse:
|
tomwalters@0
|
12 * left button = print pointer coordinates.
|
tomwalters@0
|
13 * centre button = re-draw plot (but not any printed coordinates).
|
tomwalters@0
|
14 * right button = exit program (destroy windows).
|
tomwalters@0
|
15 *
|
tomwalters@0
|
16 ****************************************************************************/
|
tomwalters@0
|
17 #include <stdio.h>
|
tomwalters@0
|
18 #include <math.h>
|
tomwalters@0
|
19 #include "x11coord.h"
|
tomwalters@0
|
20
|
tomwalters@0
|
21
|
tomwalters@0
|
22 /****************************************************************************
|
tomwalters@0
|
23 * Defaults
|
tomwalters@0
|
24 ****************************************************************************/
|
tomwalters@0
|
25 #define UNSET (-9999)
|
tomwalters@0
|
26
|
tomwalters@0
|
27 #define DEFAMPL 1000
|
tomwalters@0
|
28 #define DEFSCALE 256
|
tomwalters@0
|
29 #define DEFSAMPLERATE 20000
|
tomwalters@0
|
30
|
tomwalters@0
|
31 char DEFUNITS[] = "p" ;
|
tomwalters@0
|
32
|
tomwalters@0
|
33
|
tomwalters@0
|
34 #define SAMPLES 0
|
tomwalters@0
|
35 #define SECONDS 1
|
tomwalters@0
|
36 #define MILLISECONDS 2
|
tomwalters@0
|
37
|
tomwalters@0
|
38 int xscale_units ;
|
tomwalters@0
|
39 char *unitstr = DEFUNITS ;
|
tomwalters@0
|
40
|
tomwalters@0
|
41
|
tomwalters@0
|
42 float argXd0=UNSET, argYd0=UNSET;
|
tomwalters@0
|
43 float argXd1=UNSET, argYd1=UNSET;
|
tomwalters@0
|
44
|
tomwalters@0
|
45 int Yincr=0; /* Increment y-origin for successive files */
|
tomwalters@0
|
46
|
tomwalters@0
|
47 int plotxorg = PLOTXORG ;
|
tomwalters@0
|
48 int plotyorg = PLOTYORG ;
|
tomwalters@0
|
49 int plotheight = PLOTHEIGHT ;
|
tomwalters@0
|
50 int plotwidth = PLOTWIDTH ;
|
tomwalters@0
|
51
|
tomwalters@0
|
52
|
tomwalters@0
|
53 /****************************************************************************
|
tomwalters@0
|
54 * Input-file arguments
|
tomwalters@0
|
55 ****************************************************************************/
|
tomwalters@0
|
56 int m; /* num files to read */
|
tomwalters@0
|
57 int n; /* length read from file */
|
tomwalters@0
|
58 int s; /* start position in file */
|
tomwalters@0
|
59 short z = 1; /* Flag for drawing zero line */
|
tomwalters@0
|
60 short v = 1; /* Flag for calibrating box */
|
tomwalters@0
|
61
|
tomwalters@0
|
62 int samplerate = DEFSAMPLERATE ;
|
tomwalters@0
|
63
|
tomwalters@0
|
64 short **data ; /* data values for each file */
|
tomwalters@0
|
65 XPoint **point ; /* XPoints (pixel coords) for each file */
|
tomwalters@0
|
66 int *npoints ; /* number of points actually read in from each file */
|
tomwalters@0
|
67
|
tomwalters@0
|
68 /****************************************************************************
|
tomwalters@0
|
69 * main
|
tomwalters@0
|
70 * The window is plotted when an expose event is (automatically) generated.
|
tomwalters@0
|
71 * The plotting routines are called from within the event monitor.
|
tomwalters@0
|
72 ****************************************************************************/
|
tomwalters@0
|
73 main(argc, argv)
|
tomwalters@0
|
74 int argc ;
|
tomwalters@0
|
75 char *argv[] ;
|
tomwalters@0
|
76 {
|
tomwalters@0
|
77 FILE *fp, *fopen();
|
tomwalters@0
|
78 Window w ;
|
tomwalters@0
|
79 float n0=DEFSCALE, s0=0 ;
|
tomwalters@0
|
80 int i ;
|
tomwalters@0
|
81
|
tomwalters@0
|
82 while (--argc > 0 && **++argv == '-')
|
tomwalters@0
|
83 switch (*++*argv) {
|
tomwalters@0
|
84 case 'n': n0 = atof(++*argv); break;
|
tomwalters@0
|
85 case 's': s0 = atof(++*argv); break;
|
tomwalters@0
|
86 case 'y': argYd0 = atof(++*argv); break;
|
tomwalters@0
|
87 case 'a': argYd1 = atof(++*argv); break;
|
tomwalters@0
|
88 case 'z': z = 0; break;
|
tomwalters@0
|
89 case 'v': v = 0; break;
|
tomwalters@0
|
90 case 'Y': Yincr = atoi(++*argv); break;
|
tomwalters@0
|
91 case 'S': samplerate = atoi(++*argv); break;
|
tomwalters@0
|
92 case 'u': unitstr = ++*argv ; break;
|
tomwalters@0
|
93 case 'F': theFontString = ++*argv ; break;
|
tomwalters@0
|
94 case 'H':
|
tomwalters@0
|
95 default: help();
|
tomwalters@0
|
96 }
|
tomwalters@0
|
97
|
tomwalters@0
|
98 if (argc==0) m=1; /* 1 file from stdin. */
|
tomwalters@0
|
99 else m=argc; /* m files given as args. */
|
tomwalters@0
|
100
|
tomwalters@0
|
101 if ( strcmp( unitstr, "p" ) == 0 ) xscale_units = SAMPLES ;
|
tomwalters@0
|
102 else if ( strcmp( unitstr, "s" ) == 0 ) xscale_units = SECONDS ;
|
tomwalters@0
|
103 else if ( strcmp( unitstr, "ms" ) == 0 ) xscale_units = MILLISECONDS ;
|
tomwalters@0
|
104 else {
|
tomwalters@0
|
105 fprintf( stderr, "x11plot: unknown x-axis units\n" );
|
tomwalters@0
|
106 exit( 1 );
|
tomwalters@0
|
107 }
|
tomwalters@0
|
108
|
tomwalters@0
|
109 n = to_samples( n0 ) ;
|
tomwalters@0
|
110 s = to_samples( s0 ) ;
|
tomwalters@0
|
111
|
tomwalters@0
|
112
|
tomwalters@0
|
113 /* Allocate a data and an XPoint matrix for m files, each of n points */
|
tomwalters@0
|
114 if ( (data = (short **) malloc(m * sizeof(short *)) ) == NULL ||
|
tomwalters@0
|
115 (point = (XPoint **) malloc(m * sizeof(XPoint *)) ) == NULL ||
|
tomwalters@0
|
116 (npoints = (int *) malloc(m * sizeof( int )) ) == NULL ) {
|
tomwalters@0
|
117 fprintf( stderr, "x11plot: malloc out of space\n");
|
tomwalters@0
|
118 exit( 1 ) ;
|
tomwalters@0
|
119 }
|
tomwalters@0
|
120
|
tomwalters@0
|
121 /* For each of m files ... */
|
tomwalters@0
|
122 for ( i=0 ; i<m ; i++, argv++ ) {
|
tomwalters@0
|
123
|
tomwalters@0
|
124 /* Allocate space for data and XPoints */
|
tomwalters@0
|
125 if ( (data[i] = (short *) malloc(n * sizeof(short )) ) == NULL ||
|
tomwalters@0
|
126 (point[i] = (XPoint *) malloc(n * sizeof(XPoint)) ) == NULL ) {
|
tomwalters@0
|
127 fprintf( stderr,"x11plot: malloc out of space\n");
|
tomwalters@0
|
128 exit( 1 ) ;
|
tomwalters@0
|
129 }
|
tomwalters@0
|
130
|
tomwalters@0
|
131 /* Open file, seek start of data in file and read data in*/
|
tomwalters@0
|
132 if (argc==0) fp=stdin;
|
tomwalters@0
|
133 else if ((fp = fopen(*argv, "r")) == NULL) {
|
tomwalters@0
|
134 fprintf(stderr,"can't open %s\n", *argv);
|
tomwalters@0
|
135 exit(1);
|
tomwalters@0
|
136 }
|
tomwalters@0
|
137 if (s > 0) seekstart(s,fp);
|
tomwalters@0
|
138
|
tomwalters@0
|
139 if ( ( npoints[i] = fread( data[i], sizeof(short), n, fp ) ) < n ) {
|
tomwalters@0
|
140 if (argc==0)
|
tomwalters@0
|
141 fprintf(stderr,"Warning: %d points read from stdin.\n", npoints[i]);
|
tomwalters@0
|
142 else
|
tomwalters@0
|
143 fprintf(stderr,"Warning: %d points read from input stream %s.\n", npoints[i], *argv);
|
tomwalters@0
|
144 }
|
tomwalters@0
|
145
|
tomwalters@0
|
146 fclose(fp);
|
tomwalters@0
|
147 }
|
tomwalters@0
|
148
|
tomwalters@0
|
149 /* Set argument defaults etc. */
|
tomwalters@0
|
150
|
tomwalters@0
|
151 if (argXd0==UNSET) argXd0 = 0 ;
|
tomwalters@0
|
152 if (argXd1==UNSET) argXd1 = (float) n ;
|
tomwalters@0
|
153
|
tomwalters@0
|
154 if (argYd0==UNSET) {
|
tomwalters@0
|
155 if (argYd1==UNSET) argYd1 = 2*DEFAMPL;
|
tomwalters@0
|
156 else argYd1 = 2*argYd1;
|
tomwalters@0
|
157 argYd0 = argYd1/2;
|
tomwalters@0
|
158 }
|
tomwalters@0
|
159 else {
|
tomwalters@0
|
160 if (argYd1==UNSET) argYd1 = DEFAMPL+argYd0;
|
tomwalters@0
|
161 else argYd1 = argYd1+argYd0;
|
tomwalters@0
|
162 }
|
tomwalters@0
|
163 argYd0 = (-argYd0);
|
tomwalters@0
|
164
|
tomwalters@0
|
165 mapwaves() ;
|
tomwalters@0
|
166 xopen();
|
tomwalters@0
|
167 xgc( 1, theFontString ) ;
|
tomwalters@0
|
168 w = xcreate("x11plot", ButtonPressMask | ExposureMask | StructureNotifyMask ) ;
|
tomwalters@0
|
169
|
tomwalters@0
|
170 xevent_monitor(w);
|
tomwalters@0
|
171 }
|
tomwalters@0
|
172
|
tomwalters@0
|
173
|
tomwalters@0
|
174 /****************************************************************************
|
tomwalters@0
|
175 * Seek s points from current position in stream.
|
tomwalters@0
|
176 * This general seek works even when fp is stdin, unlike fseek.
|
tomwalters@0
|
177 ****************************************************************************/
|
tomwalters@0
|
178 seekstart(s,fp)
|
tomwalters@0
|
179 int s;
|
tomwalters@0
|
180 FILE *fp;
|
tomwalters@0
|
181 {
|
tomwalters@0
|
182 int i;
|
tomwalters@0
|
183 short p;
|
tomwalters@0
|
184
|
tomwalters@0
|
185 for (i=0 ; i<s && fread(&p, sizeof(short), 1, fp) ; i++)
|
tomwalters@0
|
186 ;
|
tomwalters@0
|
187 if (i<s) {
|
tomwalters@0
|
188 fprintf(stderr,"seek overshot end-of-file\n");
|
tomwalters@0
|
189 exit( 1 ) ;
|
tomwalters@0
|
190 }
|
tomwalters@0
|
191 }
|
tomwalters@0
|
192
|
tomwalters@0
|
193
|
tomwalters@0
|
194 /****************************************************************************
|
tomwalters@0
|
195 * X11 Event Monitor.
|
tomwalters@0
|
196 * The window is plotted when an expose event is (automatically) generated.
|
tomwalters@0
|
197 * The plotting routines are called from within the event monitor.
|
tomwalters@0
|
198 ****************************************************************************/
|
tomwalters@0
|
199 xevent_monitor(w)
|
tomwalters@0
|
200 Window w;
|
tomwalters@0
|
201 {
|
tomwalters@0
|
202 XEvent event;
|
tomwalters@0
|
203 XWindowAttributes attribs ;
|
tomwalters@0
|
204
|
tomwalters@0
|
205 for ( ; ; ) {
|
tomwalters@0
|
206 XNextEvent(theDisplay,&event);
|
tomwalters@0
|
207 switch (event.type) {
|
tomwalters@0
|
208 case ButtonPress:
|
tomwalters@0
|
209 switch(event.xbutton.button) {
|
tomwalters@0
|
210 case Button1 : /* Left */
|
tomwalters@0
|
211 report(w, event);
|
tomwalters@0
|
212 break;
|
tomwalters@0
|
213 case Button2 : /* Centre */
|
tomwalters@0
|
214 clearplot( w, plotwidth, plotheight ) ;
|
tomwalters@0
|
215 drawwaves( w ) ;
|
tomwalters@0
|
216 break;
|
tomwalters@0
|
217 case Button3 : /* Right */
|
tomwalters@0
|
218 XDestroyWindow(theDisplay,w);
|
tomwalters@0
|
219 return;
|
tomwalters@0
|
220 default:
|
tomwalters@0
|
221 fprintf(stderr,"button %d not used\n", event.xbutton.button);
|
tomwalters@0
|
222 }
|
tomwalters@0
|
223 break;
|
tomwalters@0
|
224 case ConfigureNotify :
|
tomwalters@0
|
225 plotwidth = event.xconfigure.width ;
|
tomwalters@0
|
226 plotheight = event.xconfigure.height ;
|
tomwalters@0
|
227 mapwaves() ;
|
tomwalters@0
|
228 clearplot( w, plotwidth, plotheight ) ;
|
tomwalters@0
|
229 /* drawwaves( w ) ; */
|
tomwalters@0
|
230 break;
|
tomwalters@0
|
231 case Expose:
|
tomwalters@0
|
232 if (event.xexpose.count == 0) {
|
tomwalters@0
|
233 drawwaves( w ) ;
|
tomwalters@0
|
234 }
|
tomwalters@0
|
235 break;
|
tomwalters@0
|
236 }
|
tomwalters@0
|
237 }
|
tomwalters@0
|
238 }
|
tomwalters@0
|
239
|
tomwalters@0
|
240
|
tomwalters@0
|
241
|
tomwalters@0
|
242 /****************************************************************************
|
tomwalters@0
|
243 * Set the parameters for mapping data coords onto pixel coords.
|
tomwalters@0
|
244 * For each data file, map the data onto pixel coords in the corresponding
|
tomwalters@0
|
245 * XPoints array.
|
tomwalters@0
|
246 ****************************************************************************/
|
tomwalters@0
|
247 mapwaves()
|
tomwalters@0
|
248 {
|
tomwalters@0
|
249 int i, j, n ;
|
tomwalters@0
|
250 short *dat ;
|
tomwalters@0
|
251 XPoint *pix ;
|
tomwalters@0
|
252
|
tomwalters@0
|
253 set_window_parameters( plotxorg, plotyorg, plotwidth, plotheight );
|
tomwalters@0
|
254 set_bordered_box(10);
|
tomwalters@0
|
255 set_data_parameters(0,0, argXd0,argYd0, argXd1,argYd1);
|
tomwalters@0
|
256
|
tomwalters@0
|
257 for ( i = 0 ; i < m ; i++ ) {
|
tomwalters@0
|
258 dat = data[i] ;
|
tomwalters@0
|
259 pix = point[i] ;
|
tomwalters@0
|
260 n = npoints[i] ;
|
tomwalters@0
|
261 for ( j = 0 ; j < n ; j++ ) {
|
tomwalters@0
|
262 pix[j].x = px(j) ;
|
tomwalters@0
|
263 if ( ( pix[j].y = py(dat[j]) ) > pbottom() ) pix[j].y = pbottom();
|
tomwalters@0
|
264 else if ( pix[j].y < ptop() ) pix[j].y = ptop();
|
tomwalters@0
|
265 }
|
tomwalters@0
|
266 if ( Yincr > 0 ) /* Increment Y-origin for successive files (Y decreases upwards) */
|
tomwalters@0
|
267 set_data_parameters(0,0, argXd0,argYd0-((i+1)*Yincr), argXd1,argYd1);
|
tomwalters@0
|
268 }
|
tomwalters@0
|
269
|
tomwalters@0
|
270 if ( Yincr > 0 ) /* Reset original values so that "report" works for first file */
|
tomwalters@0
|
271 set_data_parameters(0,0, argXd0,argYd0, argXd1,argYd1);
|
tomwalters@0
|
272 }
|
tomwalters@0
|
273
|
tomwalters@0
|
274
|
tomwalters@0
|
275
|
tomwalters@0
|
276 clearplot( w, width, height ) /* clear the plot window */
|
tomwalters@0
|
277 Window w;
|
tomwalters@0
|
278 int width, height ;
|
tomwalters@0
|
279 {
|
tomwalters@0
|
280 XClearArea( theDisplay, w, 0, 0, width, height, 0 ) ;
|
tomwalters@0
|
281 }
|
tomwalters@0
|
282
|
tomwalters@0
|
283 drawwaves( w ) /* draw the mapped data for all files */
|
tomwalters@0
|
284 Window w;
|
tomwalters@0
|
285 {
|
tomwalters@0
|
286 int i ;
|
tomwalters@0
|
287
|
tomwalters@0
|
288 draw_box(w);
|
tomwalters@0
|
289 if (v) draw_calibration( w );
|
tomwalters@0
|
290 if (z) draw_Xaxis(w,0); /* Draw zero line */
|
tomwalters@0
|
291
|
tomwalters@0
|
292 for ( i = 0 ; i < m ; i++ )
|
tomwalters@0
|
293 XDrawLines(theDisplay, w, theGC, point[i], npoints[i], CoordModeOrigin ) ;
|
tomwalters@0
|
294
|
tomwalters@0
|
295 XFlush(theDisplay);
|
tomwalters@0
|
296 }
|
tomwalters@0
|
297
|
tomwalters@0
|
298
|
tomwalters@0
|
299 draw_calibration( w )
|
tomwalters@0
|
300 Window w ;
|
tomwalters@0
|
301 {
|
tomwalters@0
|
302 float d0, d1 ;
|
tomwalters@0
|
303
|
tomwalters@0
|
304 switch ( xscale_units ) {
|
tomwalters@0
|
305 case SAMPLES : d0 = (float) s ;
|
tomwalters@0
|
306 d1 = d0 + (float) n ;
|
tomwalters@0
|
307 break ;
|
tomwalters@0
|
308 case SECONDS : d0 = (float) s / samplerate ;
|
tomwalters@0
|
309 d1 = d0 + (float) n / samplerate ;
|
tomwalters@0
|
310 break ;
|
tomwalters@0
|
311 case MILLISECONDS : d0 = (float) s * 1000. / samplerate ;
|
tomwalters@0
|
312 d1 = d0 + (float) n * 1000. / samplerate ;
|
tomwalters@0
|
313 break ;
|
tomwalters@0
|
314 }
|
tomwalters@0
|
315
|
tomwalters@0
|
316 calibrate_Axis( w, pleft(),pright(), d0,d1, pbottom(), 'x' ) ;
|
tomwalters@0
|
317 calibrate_Axis( w, pbottom(),ptop(), _Yd0,_Yd1, pleft(), 'y' ) ;
|
tomwalters@0
|
318 }
|
tomwalters@0
|
319
|
tomwalters@0
|
320
|
tomwalters@0
|
321
|
tomwalters@0
|
322 /****************************************************************************
|
tomwalters@0
|
323 * Report position of cursor on screen.
|
tomwalters@0
|
324 ****************************************************************************/
|
tomwalters@0
|
325 report(w, event)
|
tomwalters@0
|
326 Window w;
|
tomwalters@0
|
327 XEvent event;
|
tomwalters@0
|
328 {
|
tomwalters@0
|
329 char str[32];
|
tomwalters@0
|
330 int x, y; /* pixel coords of cursor, wrt window origin */
|
tomwalters@0
|
331 int X, Y; /* data system coords */
|
tomwalters@0
|
332 float xscale;
|
tomwalters@0
|
333 int XCALIBSPACE = 100; /* Space for calib value labels for X axis (ie in Y direction) */
|
tomwalters@0
|
334 int YCALIBSPACE = 190; /* Space for calib value labels for Y axis (ie in X direction) */
|
tomwalters@0
|
335
|
tomwalters@0
|
336 x = event.xbutton.x;
|
tomwalters@0
|
337 y = event.xbutton.y;
|
tomwalters@0
|
338 xscale = (float)pwidth()/n;
|
tomwalters@0
|
339 /* X = s + (x-Xp0)/xscale; */ /* addition of s offset assumes time scale only */
|
tomwalters@0
|
340 X = xp(x);
|
tomwalters@0
|
341 Y = yp(y);
|
tomwalters@0
|
342 sprintf(str,"(%d,%d)", X, Y);
|
tomwalters@0
|
343 XDrawLine(theDisplay, w, theGC, x-10, y, x+10, y);
|
tomwalters@0
|
344 XDrawLine(theDisplay, w, theGC, x, y-10, x, y+10);
|
tomwalters@0
|
345 XDrawString(theDisplay, w, theGC, x+5, y-5, str, strlen(str));
|
tomwalters@0
|
346 }
|
tomwalters@0
|
347
|
tomwalters@0
|
348
|
tomwalters@0
|
349 /****************************************************************************
|
tomwalters@0
|
350 * Convert length to samples according to given xscale_units.
|
tomwalters@0
|
351 ****************************************************************************/
|
tomwalters@0
|
352
|
tomwalters@0
|
353 to_samples( x )
|
tomwalters@0
|
354 float x ;
|
tomwalters@0
|
355 {
|
tomwalters@0
|
356 int samples ;
|
tomwalters@0
|
357
|
tomwalters@0
|
358 switch ( xscale_units ) {
|
tomwalters@0
|
359 case SAMPLES : samples = x ;
|
tomwalters@0
|
360 break ;
|
tomwalters@0
|
361 case SECONDS : samples = x * samplerate ;
|
tomwalters@0
|
362 break ;
|
tomwalters@0
|
363 case MILLISECONDS : samples = x * samplerate * 0.001 ;
|
tomwalters@0
|
364 break ;
|
tomwalters@0
|
365 }
|
tomwalters@0
|
366 return samples ;
|
tomwalters@0
|
367 }
|
tomwalters@0
|
368
|
tomwalters@0
|
369
|
tomwalters@0
|
370 help ()
|
tomwalters@0
|
371 {
|
tomwalters@0
|
372 printf ("\nx11plot: plot n points, read as binary shorts.\n");
|
tomwalters@0
|
373 printf ("Usage: a) x11plot [options] filename1 [filename2 ... ]\n");
|
tomwalters@0
|
374 printf (" b) cat filename | x11plot [options]\n");
|
tomwalters@0
|
375 printf (" where filename is an input stream of 16-bit binary numbers (shorts)\n");
|
tomwalters@0
|
376 printf ("Options:\n");
|
tomwalters@0
|
377 printf ("-S [int] = Samplerate in Hz (default 20000).\n");
|
tomwalters@0
|
378 printf ("-u [string] = Units (s, ms, or default p (samples)).\n");
|
tomwalters@0
|
379 printf ("\n");
|
tomwalters@0
|
380 printf ("-n [int] = Length plotted (default=%d samples).\n", DEFSCALE);
|
tomwalters@0
|
381 printf ("-s [int] = Offset from start of file (default=0 samples).\n");
|
tomwalters@0
|
382 printf ("\n");
|
tomwalters@0
|
383 printf ("-a [float] = Amplitude between zero-line and top of box (default=%d).\n", DEFAMPL);
|
tomwalters@0
|
384 printf ("-y [int] = Amplitude between zero-line and bottom of box (default=a).\n");
|
tomwalters@0
|
385 printf ("-Y [int] = Increment Y-origin for successive files (default=0).\n");
|
tomwalters@0
|
386 printf ("\n");
|
tomwalters@0
|
387 printf ("-v = Suppress calibration.\n");
|
tomwalters@0
|
388 printf ("-z = Suppress zero-line.\n");
|
tomwalters@0
|
389 printf ("-F [font] = Font name (default=%s)\n", theFontString);
|
tomwalters@0
|
390 exit (0);
|
tomwalters@0
|
391 }
|
tomwalters@0
|
392
|