"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 }