"Fossies" - the Fresh Open Source Software Archive 
Member "xzgv-0.9.2/src/rcfile.c" (3 Sep 2017, 17295 Bytes) of package /linux/misc/old/xzgv-0.9.2.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "rcfile.c" see the
Fossies "Dox" file reference documentation.
1 /* xzgv - picture viewer for X, with file selector.
2 * Copyright (C) 1999-2003 Russell Marks. See main.c for license details.
3 *
4 * rcfile.c - config file handling.
5 */
6
7 #include <stdio.h>
8 #include <string.h>
9 #include <stdlib.h>
10 #include <ctype.h>
11 #include <gtk/gtk.h>
12 #include "getopt.h" /* for getopt_long() */
13 #include "rcfile.h"
14
15
16 /* stuff for geometry. The default geometry must not specify
17 * a position using `-' (and it shouldn't specify a position anyway :-)).
18 */
19
20 #define DEFAULT_GEOMETRY "92%x85%"
21
22 int mainwin_x,mainwin_y; /* position */
23 int mainwin_w,mainwin_h; /* size */
24 int mainwin_flags; /* says which of we have (with GEOM_BITS_*) */
25
26 int default_sel_width=200; /* initial selector width (also used for ~) */
27
28
29 /* configuration vars are declared and given default values here... */
30
31 int zoom=0; /* fit picture to window */
32 int zoom_reduce_only=0; /* when zooming, shrink only (don't enlarge) */
33 int zoom_panorama=0; /* when zooming, adapt to the smallest size (panorama) */
34 int zoom_panorama_sb=0; /* when panorama zooming, hide only one scrollbar */
35 int interp=0; /* interpolate pixels when scaling */
36 int have_statusbar=0; /* show statusbar */
37 int tn_msgs=0; /* say when reading thumbnails (on sbar) */
38 int thin_rows=0; /* use lower row height */
39 int auto_hide=0; /* auto-hide selector */
40 int revert=1; /* revert to normal scale/interp on pic load */
41 int revert_orient=1; /* revert to normal orientation on pic load */
42 int fullscreen=0; /* take up whole screen for window */
43 int show_tagged=0; /* echo currently-tagged files on exit */
44 int fast_recursive_update=0; /* if 0, use blocking tn update (slow :-/) */
45 int hicol_dither=-1; /* 15/16-bit dither. 0=don't, 1=do, -1=n/a;
46 default is whatever backend decides on */
47 int skip_parent=0; /* skip cursor past .. on initial dir */
48 int click_nextpic=1; /* click on viewer = next pic */
49 int mouse_scale_x=0; /* ctrl-click scales x if true, else y */
50 enum sorttypes filesel_sorttype=sort_name; /* sort order */
51 int image_bigness_threshold=2000000; /* images >= this num pixels are `big' */
52 int delete_single_prompt=1; /* prompt for deleting a single file */
53 int careful_jpeg=0; /* enable (don't disable) fancy upsampling */
54 int sort_timestamp_type=0; /* 0=mtime, 1=ctime, 2=atime */
55 int use_exif_orient=0; /* use Exif orientation tag for JPEGs */
56 int show_images_only=0; /* file selector shows only image files */
57
58
59 /* now non-config vars :-) */
60
61 static int line; /* current line in config file */
62 int in_config=0; /* true if reading config file */
63 char *config_file_name=NULL; /* full path to config file used */
64
65
66 /* required prototypes */
67 void get_bool(char *arg,void *dataptr);
68 void get_geom(char *arg,void *data);
69 void get_selwidth(char *arg,void *data);
70 void get_sortorder(char *arg,void *data);
71 void get_timetype(char *arg,void *data);
72 void get_int(char *arg,void *data);
73 void print_version(char *arg,void *dataptr);
74 void print_gtk_ver(char *arg,void *dataptr);
75 void usage_help(char *arg,void *dataptr);
76
77
78
79 struct cfglookup_tag
80 {
81 char *name;
82 int allow_config; /* if zero, only here for cmdline opt lookup */
83 void (*funcptr)(char *,void *);
84 void *dataptr;
85 };
86
87
88 /* include opt/var tables generated from options.src by mkopts.awk;
89 * rcfile_var.h has to be included after defs of above struct and
90 * some prototypes, so may as well keep them together.
91 */
92 #include "rcfile_opt.h"
93 #include "rcfile_var.h"
94
95 /* and this one defines the short-option string. */
96 #include "rcfile_short.h"
97
98
99 /* macro for `xzgv:'-ish error prefix, the format of which should
100 * differ when reading a config file.
101 */
102 #define CONFIG_ERR_PREFIX() \
103 do \
104 { \
105 if(in_config) \
106 fprintf(stderr,"xzgv:%s:%d: ",config_file_name,line); \
107 else \
108 fprintf(stderr,"xzgv: "); \
109 } \
110 while(0)
111
112
113
114 /* find next char which isn't NUL, space, or tab. */
115 void find_token(char **ptr)
116 {
117 while(*(*ptr) && strchr(" \t",*(*ptr))!=NULL)
118 (*ptr)++;
119 }
120
121
122 int token_length(char *ptr)
123 {
124 char *start=ptr;
125
126 while(*ptr && strchr(" \t",*ptr)==NULL)
127 ptr++;
128
129 return(ptr-start);
130 }
131
132
133 /* returns 1 if equal, 0 otherwise */
134 int token_compare(char *tptr,char *txt)
135 {
136 int tlen;
137
138 tlen=token_length(tptr);
139 if(tlen!=strlen(txt))
140 return(0);
141
142 return(strncmp(tptr,txt,tlen)==0);
143 }
144
145
146 void parse_config(FILE *in)
147 {
148 static char inpline[1024];
149 char *ptr;
150 int f,c,inpc,found=0;
151
152 line=0;
153
154 while(fgets(inpline,sizeof(inpline),in)!=NULL)
155 {
156 line++;
157
158 if(inpline[strlen(inpline)-1]=='\n') inpline[strlen(inpline)-1]=0;
159 if((ptr=strchr(inpline,'#'))!=NULL)
160 *ptr=0;
161
162 if(*inpline)
163 {
164 found=0;
165 ptr=inpline;
166 find_token(&ptr);
167 inpc=*ptr;
168
169 for(f=0;(c=cfglookup[f].name[0]);f++)
170 if(inpc==c && token_compare(ptr,cfglookup[f].name) &&
171 cfglookup[f].allow_config)
172 {
173 ptr+=token_length(ptr); /* skip current token */
174 find_token(&ptr); /* find next (if any) */
175 if(*ptr==0)
176 ptr=NULL;
177
178 /* we supply the token (or lack of one) whether they asked
179 * for it or not - it's up to them whether to use it or ignore it.
180 * first arg is NULL if no arg was present.
181 */
182 (*cfglookup[f].funcptr)(ptr,cfglookup[f].dataptr);
183 found=1;
184 break;
185 }
186
187 if(!found)
188 {
189 CONFIG_ERR_PREFIX();
190 fprintf(stderr,"bad variable name.\n");
191 exit(1);
192 }
193 }
194 }
195 }
196
197
198 void get_config()
199 {
200 static char cfgfile[1024];
201 FILE *in;
202 int got_rcfile=0;
203 char *home=getenv("HOME");
204
205 /* get initial geometry in place */
206 get_geom(DEFAULT_GEOMETRY,NULL);
207
208 in_config=1;
209
210 *cfgfile=0;
211 if(home && strlen(home)<sizeof(cfgfile)-strlen("/.xzgvrc")-1)
212 sprintf(cfgfile,"%s/.xzgvrc",home);
213
214 if((in=fopen(cfgfile,"r"))!=NULL)
215 got_rcfile=1,config_file_name="~/.xzgvrc"; /* shortened name for that */
216 else if((in=fopen(config_file_name="/etc/xzgv.conf","r"))!=NULL)
217 got_rcfile=1;
218
219 if(got_rcfile)
220 {
221 parse_config(in);
222 fclose(in);
223 }
224
225 in_config=0;
226 }
227
228
229 void get_bool(char *arg,void *data)
230 {
231 int *boolptr=(int *)data;
232
233 if(!arg)
234 {
235 if(!in_config)
236 {
237 /* if no arg, and not in config file, set the flag. */
238 *boolptr=1;
239 return;
240 }
241 else /* in config file, so it's an error */
242 {
243 CONFIG_ERR_PREFIX();
244 fprintf(stderr,"option-setting arg (on/off, yes/no, ...) missing.\n");
245 exit(1);
246 }
247 }
248
249 /* otherwise, set depending on value given. */
250 if(token_compare(arg,"on") || *arg=='y' || *arg=='1')
251 *boolptr=1;
252 else
253 if(token_compare(arg,"off") || *arg=='n' || *arg=='0')
254 *boolptr=0;
255 else
256 {
257 CONFIG_ERR_PREFIX();
258 fprintf(stderr,
259 "bad option-setting arg\n\t(use on/off, y/n, yes/no, or 1/0).\n");
260 exit(1);
261 }
262 }
263
264
265 /* caller must supply valid values at str, wp, and hp
266 * (latter two (default width/height) are needed in case they use a `-',
267 * specifying gap between right/bottom of window and right/bottom edge
268 * of screen)
269 */
270 void geom_parse(char *str,int *wp,int *hp,int *xp,int *yp,int *flagsp)
271 {
272 char *ptr=str,*oldptr;
273 int flags=0;
274 int next_is_y=0,next_is_h=0;
275 int next_is_pos=0;
276 double num;
277 int scrnw=(float)gdk_screen_width();
278 int scrnh=(float)gdk_screen_height();
279 int i,sub;
280
281 if(ptr==NULL) return;
282
283 while(*ptr)
284 {
285 if(!strchr("0123456789+-x.%",*ptr))
286 {
287 ptr++;
288 continue;
289 }
290
291 sub=0;
292 if(*ptr=='x')
293 {
294 next_is_h=1,ptr++;
295 continue;
296 }
297
298 if(*ptr=='+' || *ptr=='-')
299 {
300 if(*ptr=='-') sub=1;
301 ptr++;
302
303 if(next_is_pos)
304 next_is_y=1;
305 else
306 next_is_pos=1;
307 }
308
309 if(isdigit(*ptr) || *ptr=='+' || *ptr=='-' || *ptr=='%')
310 {
311 oldptr=ptr;
312
313 num=strtod(ptr,&ptr);
314
315 /* give up if we'd otherwise get stuck on a non-number */
316 if(ptr==oldptr)
317 break;
318
319 if(*ptr=='%')
320 {
321 ptr++;
322 num=num/100.*((next_is_y || next_is_h)?scrnh:scrnw);
323 }
324
325 i=(int)(num+0.5);
326
327 if(sub) /* subtract from screen width/height */
328 {
329 if(next_is_y)
330 i=scrnh-i-*hp;
331 else
332 i=scrnw-i-*wp;
333 }
334
335 if(next_is_pos)
336 {
337 if(next_is_y)
338 *yp=i,flags|=GEOM_BITS_Y_SET;
339 else
340 *xp=i,flags|=GEOM_BITS_X_SET;
341 }
342 else
343 if(next_is_h)
344 *hp=i,flags|=GEOM_BITS_H_SET;
345 else
346 *wp=i,flags|=GEOM_BITS_W_SET;
347 }
348 }
349
350 *flagsp=flags;
351 }
352
353
354 /* get geometry */
355 void get_geom(char *arg,void *data)
356 {
357 if(arg==NULL)
358 {
359 CONFIG_ERR_PREFIX();
360 fprintf(stderr,"missing geometry-specifying arg.\n");
361 exit(1);
362 }
363
364 geom_parse(arg,&mainwin_w,&mainwin_h,&mainwin_x,&mainwin_y,&mainwin_flags);
365 }
366
367
368 /* get selector width */
369 /* XXX doesn't do window percentage yet */
370 void get_selwidth(char *arg,void *data)
371 {
372 int tmp=arg?atoi(arg):0;
373 int *ptr=(int *)data;
374
375 if(arg==NULL)
376 {
377 CONFIG_ERR_PREFIX();
378 fprintf(stderr,"missing selector width arg.\n");
379 exit(1);
380 }
381
382 if(tmp<0) tmp=0;
383 if(tmp>32767) tmp=32767;
384
385 *ptr=tmp;
386 }
387
388
389 /* get sort order, determined by 1st letter of arg */
390 void get_sortorder(char *arg,void *data)
391 {
392 if(arg==NULL)
393 {
394 CONFIG_ERR_PREFIX();
395 fprintf(stderr,"missing sort-order arg.\n");
396 exit(1);
397 }
398
399 switch(tolower(*arg))
400 {
401 case 'n':
402 filesel_sorttype=sort_name;
403 break;
404 case 'e':
405 filesel_sorttype=sort_ext;
406 break;
407 case 's':
408 filesel_sorttype=sort_size;
409 break;
410 case 'd': case 't':
411 filesel_sorttype=sort_time;
412 break;
413
414 default:
415 CONFIG_ERR_PREFIX();
416 fprintf(stderr,"unrecognised sort order.\n");
417 exit(1);
418 }
419 }
420
421
422 /* get timestamp type for sort-by-time&date sort order,
423 * as determined by 1st letter of arg.
424 */
425 void get_timetype(char *arg,void *data)
426 {
427 if(arg==NULL)
428 {
429 CONFIG_ERR_PREFIX();
430 fprintf(stderr,"missing timestamp type arg.\n");
431 exit(1);
432 }
433
434 switch(tolower(*arg))
435 {
436 case 'm':
437 sort_timestamp_type=0;
438 break;
439 case 'c':
440 sort_timestamp_type=1;
441 break;
442 case 'a':
443 sort_timestamp_type=2;
444 break;
445
446 default:
447 CONFIG_ERR_PREFIX();
448 fprintf(stderr,"unrecognised timestamp type.\n");
449 exit(1);
450 }
451 }
452
453
454 void get_int(char *arg,void *data)
455 {
456 int *ptr=(int *)data;
457
458 if(arg==NULL)
459 {
460 CONFIG_ERR_PREFIX();
461 fprintf(stderr,"missing arg.\n");
462 exit(1);
463 }
464
465 *ptr=atoi(arg);
466 }
467
468
469 int parse_options(int argc,char *argv[])
470 {
471 const char *name; /* const needed because of struct option declaration */
472 int entry,ret,f,c,namec,found;
473
474 do
475 {
476 /* the GNU libc docs don't make it clear whether optarg is set to NULL
477 * when a *short* option doesn't have an arg, so I play it safe here.
478 */
479 optarg=NULL;
480
481 /* SHORTOPT_STRING is defined in rcfile_short.h, as gen'd from options.src */
482 ret=getopt_long(argc,argv,SHORTOPT_STRING,long_opts,&entry);
483
484 if(ret=='?')
485 {
486 /* no need for error message, it's already been done */
487 exit(1);
488 }
489
490 if(ret!=-1)
491 {
492 /* if we have a short option, it returns char code; find relevant
493 * long-option entry. It also returns char code for long options
494 * with equivalent short option - it doesn't hurt to look
495 * it up in that case as well though. It's not like this takes huge
496 * amounts of CPU... ;-)
497 */
498 if(isalnum(ret))
499 {
500 found=0;
501
502 for(f=0;long_opts[f].name;f++)
503 {
504 if(long_opts[f].val==ret)
505 {
506 entry=f;
507 found=1;
508 break;
509 }
510 }
511
512 if(!found)
513 {
514 fprintf(stderr,
515 "short option not found in long_opts[] - can't happen!\n");
516 continue;
517 }
518 }
519
520 /* now we have a valid entry in long_opts[], lookup name in
521 * cfglookup to get funcptr/dataptr and run the function.
522 */
523 name=long_opts[entry].name;
524 namec=*name;
525 found=0;
526
527 for(f=0;(c=cfglookup[f].name[0]);f++)
528 if(namec==c && strcmp(name,cfglookup[f].name)==0)
529 {
530 (*cfglookup[f].funcptr)(optarg,cfglookup[f].dataptr);
531 found=1;
532 break;
533 }
534
535 if(!found)
536 fprintf(stderr,
537 "long option not found in cfglookup[] - can't happen!\n");
538 }
539 }
540 while(ret!=-1);
541
542 return(argc-optind);
543 }
544
545
546 void print_version(char *arg,void *dataptr)
547 {
548 printf("xzgv " XZGV_VER "\n");
549 exit(0);
550 }
551
552
553 void print_gtk_ver(char *arg,void *dataptr)
554 {
555 printf("GTK+ %d.%d.%d\n",
556 gtk_major_version,gtk_minor_version,gtk_micro_version);
557 exit(0);
558 }
559
560
561 void usage_help(char *arg,void *dataptr)
562 {
563 printf("xzgv " XZGV_VER
564 " - copyright (c) 1999-2003 Russell Marks.\n");
565 puts(
566 "usage: xzgv [options] [dir | file ...]\n"
567 "\n"
568 " -a --auto-hide automatically hide selector on selecting a picture.\n"
569 " --careful-jpeg enable JPEG `fancy upsampling' (see info file\n"
570 " or man page).\n"
571 " --delete-single-prompt\n"
572 " (normally enabled, use --delete-single-prompt=off to\n"
573 " disable) if *disabled*, don't prompt for confirmation\n"
574 " when deleting a file.\n"
575 " --dither-hicol use dithering in 15/16-bit to increase apparent\n"
576 " colour depth, whatever Imlib's default setting is.\n"
577 " You can also use `--dither-hicol=off' to disable\n"
578 " this if you normally have Imlib use it.\n"
579 " --exif-orient in JPEG files, use Exif orientation tags (inserted\n"
580 " by e.g. digital cameras) to correct image orientation\n"
581 " before display.\n"
582 " --fast-recursive-update\n"
583 " when doing recursive thumbnail update, don't\n"
584 " read visible thumbnails for a directory before\n"
585 " doing the update (only slightly faster).\n"
586 " -f --fullscreen use the whole screen for the xzgv window, without\n"
587 " even window-manager decorations if possible. (But\n"
588 " your wm may not care to trust borderless programs.)\n"
589 " -g --geometry geom\n"
590 " use geometry `geom'. For example, `400x300' specifies\n"
591 " window size in pixels, `70%x50%' specifies size as\n"
592 " percentage of screen width/height, `+100+50' specifies\n"
593 " position relative to top-left, and `50%x30%-30%-20%'\n"
594 " is left as an exercise for the reader. :-) The default\n"
595 " geometry is `92%x85%'.\n"
596 " (See info file or man page for more details.)\n"
597 " -h --help give this usage help.\n"
598 " --image-bigness-threshold numpix\n"
599 " set the boundary `numpix' above which images are\n"
600 " considered `big', and rendered piece-by-piece rather\n"
601 " than all-at-once (which is nicer, but harder on\n"
602 " memory). Units are number of pixels in image (i.e.\n"
603 " width times height), and the default is 2000000 pixels.\n"
604 " --interpolate interpolate between the picture's pixels when\n"
605 " scaling up. Usually looks nicer, but it's slow.\n"
606 " --mouse-scale-x if enabled, control-click scales only the X axis -\n"
607 " the default is to scale only the Y axis.\n"
608 " --revert-orient (normally enabled, use --revert-orient=off to disable)\n"
609 " if *disabled*, orientation (flip/mirror/rotate) state\n"
610 " is retained between pictures.\n"
611 " --revert-scale (normally enabled, use --revert-scale=off to disable)\n"
612 " if *disabled*, scaling is retained between pictures.\n"
613 " --selector-width width\n"
614 " set initial/default selector width to `width'. (The\n"
615 " units used are pixels, and the normal setting 200.)\n"
616 " -T --show-tagged show names of tagged files on exit (they're listed\n"
617 " to stdout).\n"
618 " --show-thumbnail-messages\n"
619 " show on the status bar when thumbnails are being read.\n"
620 " The status bar must be enabled for the messages to be\n"
621 " visible, of course. :-)\n"
622 " -k --skip-parent for the first directory shown, skip the cursor past\n"
623 " `..' (the parent dir). Can be useful when you'd like\n"
624 " to immediately use space to `page' through the dir.\n"
625 " -o --sort-order set initial sorting order used in the selector.\n"
626 " Types are `name', `ext', `size', `date' (or `time');\n"
627 " only the first char (n/e/s/d/t) need be given.\n"
628 " (The default is name order.)\n"
629 " --sort-timestamp-type type\n"
630 " set timestamp type to use when using time/date sorting\n"
631 " order. Types are `mtime' (default), `ctime', and\n"
632 " `atime'; only the first char (m/c/a) need be given.\n"
633 " --statusbar show a status bar below the selector; this, for\n"
634 " example, says when a picture is being read.\n"
635 " -t --thin-rows use rows a third the normal height in the selector.\n"
636 " This can be very useful on lower-resolution screens,\n"
637 " or if you're really interested in filenames, not\n"
638 " thumbnails.\n"
639 " -v --version report version number.\n"
640 " --version-gtk report version of GTK+ being used by xzgv.\n"
641 " -z --zoom fit pictures in the viewer window, whatever their\n"
642 " actual size.\n"
643 " -r --zoom-reduce-only\n"
644 " when zooming, only *reduce* pictures to fit; i.e.\n"
645 " make big pictures viewable all-at-once while leaving\n"
646 " small pictures intact.\n"
647 "\n"
648 " dir start xzgv on a certain directory.\n"
649 " file ... view (only) the file(s) specified.\n"
650 "\n"
651 "All options are processed after any ~/.xzgvrc or /etc/xzgv.conf file.\n"
652 "Most long options (minus `--') can used in either file with e.g. `zoom on'.\n"
653 "\n"
654 "On/off settings (such as zoom) are enabled by e.g. `-z' or `--zoom';\n"
655 "however, the long-option form `--option=off' can be used to disable\n"
656 "them (needed when they are enabled by default - revert-scale, for\n"
657 "example - or to override them being enabled in a config file).\n"
658 "\n"
659 "(This syntax actually lets you both disable *and* enable options,\n"
660 "using (for the arg after `=') on/off, y/n, yes/no, or 1/0.)");
661
662 exit(0);
663 }