#include #include #include #include #include #include #include "crinkle.h" #include "paint.h" #include "patchlevel.h" #include "copyright.h" #define VERSION 2 #define SIDE 1.0 char scroll_Id[]="$Id: xmountains.c,v 1.43 2010/12/17 09:25:36 spb Exp $"; extern Graph g; Parm fold_param; char *display; extern char *geom; extern int swosh; /* {{{ my version on getopt*/ int optind=1; char *optarg; int opterr=1; int my_getopt (argc, argv, pat) int argc; char **argv; char *pat; { char *flag; if((optind >= argc) || (argv[optind][0] != '-')) { return -1; } if( argv[optind][1] == '-' ) { optind++; return -1; } if( argv[optind][1] == ':' ) { if( opterr ) { fprintf(stderr,"getopt: found \":\" in optstring\n"); } return '?'; } for(flag=pat;*flag;flag++) { if( *flag == argv[optind][1] ) { optind++; if( *(flag+1) == ':' ) { if(optind >= argc ) { if( opterr ) { fprintf(stderr,"getopt: no option for flag %c\n",*flag); } return '?'; } optarg = argv[optind]; optind++; } return *flag; } } if( opterr ) { fprintf(stderr,"getopt: flag %s not recognized\n",argv[optind]); } optind++; return '?'; } /* }}} */ double atof(); #ifdef ANSI void init_graphics (int, Window, int,int, Graph *, Gun *, Gun *, Gun *); void clear_col( int ); void finish_graphics(); void plot_pixel (int, int, unsigned char); void scroll_screen ( int ); void zap_events(); #else void init_graphics (); void clear_col(); void finish_graphics(); void plot_pixel (); void scroll_screen (); void zap_events(); #endif void finish_prog(); int s_height=768, s_width=1024; int mapwid; /* Go through argv and find and extract any "-window-id NNNN" or "-window-id 0xXXXX" option. (Maybe this can be done with getopt, but I can't be bothered to figure it out.) */ static unsigned long window_id_kludge (argcP, argv) int *argcP; char **argv; { unsigned long id = 0; int i; int j; for (i = 1; i < *argcP; i++) { if (!strcmp (argv[i], "-window-id") && i+1 < *argcP) { char c; char *str = argv[i+1]; if (1 != ((str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) ? sscanf (str+2, "%lx %c", &id, &c) : sscanf (str, "%lu %c", &id, &c))) continue; /* remove "-window-id xxx" from the arglist */ for (j = i+2; j < *argcP; j++) argv[j-2] = argv[j]; *argcP -= 2; } } return id; } void init_parameters(); void print_algorithm(); void seed_uni(int ijkl); void plot_column(Graph *g); main (argc,argv) int argc; char **argv; { int i; int e_events=FALSE; int request_clear=FALSE; int smooth=1; int snooze=10; int root= 0; unsigned long window_id = 0; int seed=0; int c, errflg=0; extern char *optarg; extern int optind; char *mesg[2]; Gun *clut[3]; FILE *pidfile; swosh = 0; /* default is ! -w */ init_parameters(); /* {{{ handle command line flags*/ window_id = window_id_kludge (&argc, argv); mesg[0]="false"; mesg[1]="true"; while((c = my_getopt(argc,argv,"whbxmqMEHl:r:f:t:I:A:S:T:W:C:a:p:B:n:R:g:d:c:e:v:Z:s:X:Y:P:F:G:"))!= -1) { switch(c){ case 'w': swosh = TRUE; /* update window only when pixmap is complete */ break; case 'b': root = 1- root; break; /* run on root window */ case 'x': fold_param.cross = 1- fold_param.cross; break; /* use cross updates */ case 'E': e_events = 1 - e_events; break; case 'q': request_clear = 1 - request_clear; break; case 'm': /* Map view only */ g.map = 1 - g.map; break; case 'M': /* put in reflections */ g.reflec = 1 - g.reflec; break; case 'l': /* Set # levels of recursion */ g.levels = atoi( optarg ); if( g.levels < 2 ) { g.levels = 2; } break; case 'F': /* Set # levels to force front to mean */ fold_param.force_front = atoi( optarg ); break; case 's': /* Set smoothing parameter */ smooth = atoi( optarg ); fold_param.rg1 = smooth & 1; fold_param.rg2 = smooth & 2; fold_param.rg3 = smooth & 4; break; case 't': /* Set width of lowest level */ g.stop = atoi( optarg ); if( g.stop < 0 ) { g.stop = 0; } break; case 'r': g.repeat = atoi( optarg ); if( g.repeat < 0 ) { g.repeat = -g.repeat; i= -1; }else{ i=1; } /* we want repeat to be a multiple of 2 as we are using * a textured field for the sky. */ g.repeat = i*(2 * ((g.repeat +1)/2)); break; case 'B': /* set band_size */ g.band_size = atoi( optarg ); if( g.band_size < 2 ) { g.band_size=2; } g.n_col = (BAND_BASE + (N_BANDS * g.band_size)); break; case 'n': /* set max number of colours */ g.n_col = atoi( optarg ); if( g.n_col < MIN_COL ) { g.n_col = MIN_COL; } g.band_size = (g.n_col - BAND_BASE)/N_BANDS; g.n_col = (BAND_BASE + (N_BANDS * g.band_size)); break; case 'R': /* set seed, read clock if 0 */ seed = atoi( optarg ); break; case 'Z': /* put sleep into wait events */ snooze = atoi( optarg ); if( snooze < 0 ) { snooze = 0; } break; case 'P': pidfile = fopen(optarg,"w"); if( pidfile ) { fprintf(pidfile,"%d\n",getpid()); fclose(pidfile); }else{ perror(optarg); } break; case 'f': /* set fractal dimension */ fold_param.fdim = atof( optarg ); if( fold_param.fdim < 0.5 ) { fold_param.fdim=0.5; } if( fold_param.fdim > 1.0 ) { fold_param.fdim=1.0; } break; case 'I': /* set Illumination angle */ g.phi = ((PI * atof( optarg ))/180.0); if ( g.phi < 0.0 ) { g.phi=0.0; } if( g.phi > PI/2.0 ) { g.phi = PI/2.0; } break; case 'A': /* set Illumination angle (horizontal)*/ g.alpha = ((PI * atof( optarg ))/180.0); if( g.alpha < -PI/3.0 ) { g.alpha = -PI/3.0; } if( g.alpha > PI/3.0 ) { g.alpha = PI/3.0; } break; case 'X': /* set mix */ fold_param.mix = atof( optarg ); break; case 'Y': /* set midmix */ fold_param.midmix = atof( optarg ); break; case 'S': /* set stretch */ g.stretch = atof( optarg ); break; case 'W': /* set sealevel */ g.sealevel = atof( optarg ); break; case 'G': /* set forceheight */ fold_param.forceval = atof( optarg ); break; case 'T': /* set shift */ g.base_shift = atof( optarg ); break; case 'C': g.contour = atof( optarg ); break; case 'a': /* set altitude */ g.altitude = atof( optarg ); break; case 'p': /* set distance */ g.distance = atof( optarg ); break; case 'c': g.contrast = atof( optarg ); if( g.contrast < 0.0 ) { g.contrast=0.0; } break; case 'e': g.ambient = atof( optarg ); if( g.ambient < 0.0 ) { g.ambient = 0.0; } if( g.ambient > 1.0 ) { g.ambient=1.0; } break; case 'v': g.vfract = atof( optarg ); if( g.vfract < 0.0 ) { g.vfract = 0.0; } break; case 'g': geom = optarg; break; case 'd': display = optarg; break; case 'H': print_algorithm(); errflg++; break; case 'h': case '?': errflg++; } } if( errflg ) { fprintf(stderr,"%s: version %d.%d\n",argv[0],VERSION,PATCHLEVEL); fprintf(stderr,"usage: %s -[hwbqgdPEmMrBZIASFTCapcevfRltxsXYH]\n",argv[0]); fprintf(stderr," -h Print this message\n"); fprintf(stderr," -w [%s] update window with complete images only\n",mesg[swosh]); fprintf(stderr," -b [%s] use root window \n",mesg[root]); fprintf(stderr," -q [%s] reset root window on exit\n",mesg[request_clear]); fprintf(stderr," -g string window geometry\n"); fprintf(stderr," -d string display\n"); fprintf(stderr," -P filename write PID to file\n"); fprintf(stderr," -E [%s] toggle explicit expose events \n",mesg[e_events]); fprintf(stderr," -m [%s] print map \n",mesg[g.map]); fprintf(stderr," -M [%s] implement reflections \n",mesg[g.reflec]); fprintf(stderr," -r int [%d] # columns before scrolling \n",g.repeat); fprintf(stderr," -B int [%d] # shades in a colour band\n",g.band_size); fprintf(stderr," -n int [%d] # number of colours\n",g.n_col); fprintf(stderr," -Z int [%d] time to sleep before scrolling\n",snooze); fprintf(stderr," -I float [%f] vertical angle of light \n",(g.phi*180.0)/PI); fprintf(stderr," -A float [%f] horizontal angle of light \n",(g.alpha*180.0)/PI); fprintf(stderr," -S float [%f] vertical stretch \n",g.stretch); fprintf(stderr," -T float [%f] vertical shift \n",g.base_shift); fprintf(stderr," -W float [%f] sealevel \n",g.sealevel); fprintf(stderr," -F int [%d] reduce variation in the foreground \n",fold_param.force_front); fprintf(stderr," -G float [%f] average foreground height \n",fold_param.forceval); fprintf(stderr," -C float [%f] contour parameter \n",g.contour); fprintf(stderr," -a float [%f] altitude of viewpoint \n",g.altitude); fprintf(stderr," -p float [%f] distance of viewpoint \n",g.distance); fprintf(stderr," -c float [%f] contrast\n",g.contrast); fprintf(stderr," -e float [%f] ambient light level\n",g.ambient); fprintf(stderr," -v float [%f] vertical light level\n",g.vfract); fprintf(stderr,"Fractal options:\n"); fprintf(stderr," -f float [%f] fractal dimension \n",fold_param.fdim); fprintf(stderr," -R int [%d] rng seed, read clock if 0 \n",seed); fprintf(stderr," -l int [%d] # levels of recursion \n",g.levels); fprintf(stderr," -t int [%d] # non fractal iterations \n",g.stop); fprintf(stderr," -x [%s] cross update \n",mesg[fold_param.cross]); fprintf(stderr," -s [%x] smoothing (0-7)\n",smooth); fprintf(stderr," -X float [%f] fraction of old value for rg2 & rg3\n",fold_param.mix); fprintf(stderr," -Y float [%f] fraction of old value for rg1\n",fold_param.midmix); fprintf(stderr," -window-id 0xNNNNN draw on existing external window.\n"); fprintf(stderr," -H print short description of algorithm.\n"); exit(1); } /* }}} */ for(i=0 ;i<3 ;i++) { clut[i] = (Gun *) malloc(g.n_col * sizeof(Gun)); if( ! clut[i] ) { fprintf(stderr,"malloc failed for clut\n"); exit(1); } } set_clut(g.n_col,clut[0], clut[1], clut[2]); init_graphics(root,window_id, !e_events, request_clear, &g, clut[0], clut[1], clut[2]); for(i=0;i<3;i++) { free(clut[i]); } seed_uni(seed); init_artist_variables(); if( SIG_ERR == signal(SIGINT, finish_prog )) { perror(argv[0]); exit(1); } if( SIG_ERR == signal(SIGTERM, finish_prog )) { perror(argv[0]); exit(1); } if( SIG_ERR == signal(SIGHUP, finish_prog )) { perror(argv[0]); exit(1); } if( SIG_ERR == signal(SIGQUIT, finish_prog )) { perror(argv[0]); exit(1); } /* This is a stand in for the event loop in a Widget set implementation * where we would call plot_column at regular intervals using * XTtimeout. However xmountains is an Xlib program * so I do the following. */ while( TRUE ) { plot_column(&g); zap_events(); #ifndef NO_SLEEP if( g.scroll ){ /* sleep if we are due a scroll next time */ /* sleeping is very bad because it will prevent * events being processed but I suppose it is better * than being a CPU hog, as a compremise always check for * events at least once a second, looping for longer sleep times. * process the events before a sleep to make sure the screen is up to date. * the events must always be processed at least once. */ for(i=0;i