home *** CD-ROM | disk | FTP | other *** search
/ The UNIX CD Bookshelf / OREILLY_TUCB_UNIX_CD.iso / upt / examples / SOURCES / IPL / PART05.Z / PART05
Encoding:
Text File  |  1998-07-24  |  28.6 KB  |  1,011 lines

  1. Subject:  v21i036:  2D graphic system with table beautifier, Part05/14
  2. Newsgroups: comp.sources.unix
  3. Approved: rsalz@uunet.UU.NET
  4. X-Checksum-Snefru: 1b6bf460 122c0f5d 23857f75 f1550da6
  5.  
  6. Submitted-by: Steve Grubb <uunet!lsr-vax!scg>
  7. Posting-number: Volume 21, Issue 36
  8. Archive-name: ipl/part05
  9.  
  10. # ipl part05
  11. #    This is a shell archive.
  12. #    Remove everything above and including the cut line.
  13. #    Then run the rest of the file through sh.
  14. #---------------------- cut here -----------------------------
  15. #!/bin/sh
  16. # shar:    Shell Archiver
  17. #    Run the following text with /bin/sh to create:
  18. #        src/areadef.c
  19. #        src/areadress.c
  20. #        src/areas.h
  21. #        src/arrow.c
  22. #        src/bargraph.c
  23. #        src/boxplot.c
  24. #        src/constraint_check.c
  25. cat << SHAR_EOF > src/areadef.c
  26. /* Set up a graphics area and do axes, etc. */
  27. #include "ipl.x"
  28. #include "areas.h"
  29.  
  30. Areadef( )
  31. {
  32. char paper[12],
  33.     areaname[30],
  34.     s1[12], s2[12], s3[12], s4[12],
  35.     uin[12];
  36. double    xlo,
  37.     xhi,
  38.     ylo,
  39.     yhi,
  40.     dxlo,
  41.     dxhi,
  42.     dylo,
  43.     dyhi;
  44. int    n,
  45.     areasrc,
  46.     p,
  47.     bad,
  48.     loadflag,
  49.     i;
  50.  
  51. /* see where area is coming from..  */
  52. areasrc = 0;
  53. gget( uin, "Area" ); if( strlen( uin ) > 0 ) areasrc = 1;
  54. gget( uin, "Area.rectangle" ); if( strlen( uin ) > 0 ) areasrc = 2;
  55. gget( uin, "Area.left" ); if( strlen( uin ) > 0 ) areasrc = 3;
  56. if( areasrc < 1 ) { 
  57.     fprintf( stderr, "Area or Area.rectangle, or Area.left+right+top+bottom must be specified.\n" ); 
  58.     gdp_exit(); 
  59.     }
  60.  
  61. if( areasrc == 1 ) {  /* preset area name */
  62.     gget( areaname, "Area" );
  63.     for( i = 0; i < Nareas; i++ ) if( strncmp( areaname, Areacoords[i], strlen( areaname )) ==0 ) break;
  64.     if( i == Nareas ) { fprintf( stderr, "Can't find preset area '%s'.\n", areaname ); gdp_exit(); }
  65.     if( Paper == 0 ) /* portrait */
  66.         n = sscanf( Areacoords[i], "%*s %s %s %s %s", s1, s2, s3, s4 );
  67.     else n = sscanf( Areacoords[i], "%*s %*s %*s %*s %*s %s %s %s %s", s1, s2, s3, s4 ); /* landscape */
  68.     if( n != 4 ) { fprintf( stderr, "Error in area presets.\n" ); gdp_exit(); }
  69.     xlo = atof( s1 ); ylo = atof( s2 ); xhi = atof( s3 ); yhi = atof( s4 ); 
  70.     }
  71. else if( areasrc == 2 ) { /* rectangle */
  72.     gget( uin, "Area.rectangle" );
  73.     if( strlen( uin ) > 0 ) n = sscanf( uin, "%lf %lf %lf %lf", &xlo, &ylo, &xhi, &yhi );
  74.     if( n != 4 ) { 
  75.         fprintf( stderr, "Area.rectangle must contain two coord pairs (low left, up right).\n" ); 
  76.         gdp_exit(); 
  77.         }
  78.     }
  79. else if( areasrc == 3 ) { /* left, right, bottom, top */
  80.     int bad = NO;
  81.     xlo = atof( uin );
  82.     gget( uin, "Area.left" );if( !goodnum( uin, &p ))bad = YES; xlo = atof( uin );
  83.     gget( uin, "Area.right" );if( !goodnum( uin, &p ))bad = YES; xhi = atof( uin );
  84.     gget( uin, "Area.bottom" ); if( !goodnum( uin, &p ))bad = YES; ylo = atof( uin );
  85.     gget( uin, "Area.top" ); if( !goodnum( uin, &p ))bad = YES; yhi = atof( uin );
  86.     if( bad ) { fprintf( stderr, "Area.left+right+bottom+top incompletely specified." ); gdp_exit(); }
  87.     }
  88.  
  89. /* scale discipline */
  90. gget( uin, "Xscaletype" );
  91. if( strcmp( uin, "log" )==0 ) Scale_discipline_x = LOG; 
  92. else if( strcmp( uin, "yymm" )==0 ) Scale_discipline_x = YYMM; 
  93. else Scale_discipline_x = LINEAR;
  94.  
  95. gget( uin, "Yscaletype" );
  96. if( strcmp( uin, "log" )==0 ) Scale_discipline_y = LOG; 
  97. else Scale_discipline_y = LINEAR;
  98.  
  99. /* scale bounds */
  100. bad = NO;
  101. gget( uin, "Xmin" ); if( ! goodnum( uin, &p )) bad = YES; dxlo = atof( uin );
  102. gget( uin, "Xmax" ); if( ! goodnum( uin, &p )) bad = YES; dxhi = atof( uin );
  103. gget( uin, "Ymin" ); if( ! goodnum( uin, &p )) bad = YES; dylo = atof( uin );
  104. gget( uin, "Ymax" ); if( ! goodnum( uin, &p )) bad = YES; dyhi = atof( uin );
  105. if( bad ) { fprintf( stderr, "Scale bounds (Xmin, Xmax, Ymin, Ymax) not all specified.\n" ); gdp_exit(); }
  106.  
  107.  
  108. /* tic increment */
  109. bad = NO;
  110. gget( uin, "Xinc" ); if( ! goodnum( uin, &p )) bad = YES; DXtic = atof( uin );
  111. gget( uin, "Yinc" ); if( ! goodnum( uin, &p )) bad = YES; DYtic = atof( uin );
  112. if( bad ) { fprintf( stderr, "Tic increments incomplete.\n" ); }
  113.  
  114. /* get tic numbering format */
  115. gget( DXticfmt, "Xticfmt" );
  116. gget( DYticfmt, "Yticfmt" );
  117.  
  118. /* fprintf( stderr, "Scaling in x: %5.1f to %5.1f by %3.1f   in y: %5.1f to %5.1f by %3.1f\n", 
  119.     dxlo, dxhi, DXtic, dylo, dyhi, DYtic ); */
  120.  
  121.  
  122. setscale_x( xlo, xhi, dxlo, dxhi );
  123. setscale_y( ylo, yhi, dylo, dyhi );
  124.  
  125.  
  126. /* do the graphic work for axes, ticks, etc. */
  127. areadress( );
  128.  
  129. }
  130. SHAR_EOF
  131. ############################
  132.  
  133. cat << SHAR_EOF > src/areadress.c
  134. /* areadress() - do axis scaling stubs, labels, and title */
  135. /*  ..gets called by areadef (only) */
  136. #include "ipl.x" 
  137. #define LINE 1
  138. #define SHADE 2
  139. #define WLINE 3
  140. #define NUMERIC 0
  141. #define FROM_FILE 1
  142. #define VAR 2
  143. #define LITERAL 3
  144.  
  145.  
  146. areadress( )
  147. {
  148. char     str[50], 
  149.     do_x[10], do_y[10],
  150.     shade[12],
  151.     month[6], year[6];
  152. int     i, j,
  153.     n,
  154.     tl, tr, 
  155.     sl, sr, 
  156.     grid, 
  157.     even, 
  158.     minor,
  159.     stub0or1,
  160.     varfield,
  161.     nrows,
  162.     no_lone_tics,
  163.     stubisrc;
  164. double     tcl = 0.08, 
  165.     mtcl = 0.035, /* tic length, major and minor */
  166.     stop,
  167.     xstubyofs,
  168.     ystubxofs,
  169.     sh,
  170.     f, g, h;
  171. FILE     *fp;
  172.  
  173. /* set to uer's standard font */
  174. gget( Buf, "Font" );
  175. NTfont( Buf );
  176.  
  177.  
  178. /* frame of the graphics area */
  179. gget( Buf, "Frame" );
  180. if( strcmp( Buf, "double" ) == 0 ) ab_rect( Xlo-mtcl, Ylo-mtcl, Xhi+mtcl, Yhi+mtcl, 1.0, 1 );
  181. if( strcmp( Buf, "none" ) != 0 ) ab_rect( Xlo, Ylo, Xhi, Yhi, 1.0, 1 );
  182. /* shade the area */
  183. gget( Buf, "Shade" );
  184. if( strlen( Buf ) > 0 ) {
  185.     sh = atof( Buf );
  186.     ab_rect( Xlo, Ylo, Xhi, Yhi, sh, 0 );
  187.     }
  188.  
  189. gget( Buf, "Ystub.ticlen" ); tcl = atof( Buf );
  190. gget( Buf, "Ystub.ticlen.minor" ); mtcl = atof( Buf );
  191.  
  192. /**** Y ****/
  193. /* draw axis line */
  194. gget( do_y, "Yaxis" ); 
  195. if( do_y[0] == 'n' ) goto BEGIN_X; /* if 'no', skip all the y axis code */
  196.  
  197.  
  198. /* stub text can be numeric, from a data field, from a file, or literally specified. */
  199. gget( Buf, "Ystub" ); 
  200. if( strcmp( Buf, "num" )==0 ) stubisrc = NUMERIC;
  201. else if( Buf[0] == '@' ) { 
  202.     stubisrc = VAR;
  203.     varfield = atoi( &Buf[1] ); 
  204.     if( varfield < 1 || varfield > N_d_fields ) { fprintf( stderr, "bad stub var field\n" ); gdp_exit(); }
  205.     }
  206. else if( strlen( Buf ) < 1 ) fprintf( stderr, "Warning, Ystub not specified.\n" );
  207. else     {
  208.     stubisrc = FROM_FILE;
  209.     fp = fopen( Buf, "r" );
  210.     if( fp != NULL ) {
  211.         gget( Buf, "Ystub.fileline" );
  212.         for( i = 0; i < atoi( Buf ); i++ ) fgets( str, 30, fp );
  213.         }
  214.     else if( fp == NULL ) {
  215.         sprintf( Buf2, "%s/%s", Templatepath, Buf );
  216.         fp = fopen( Buf2, "r" );
  217.         if( fp != NULL ) {
  218.             gget( Buf, "Ystub.fileline" );
  219.             for( i = 0; i < atoi( Buf ); i++ ) fgets( str, 30, fp );
  220.             }
  221.         else if( fp == NULL ) {
  222.             text_tofile( Buf, Tempfile );
  223.             fp = fopen( Tempfile, "r" );
  224.             }
  225.         }
  226.     }
  227.  
  228.  
  229. /* sides to put tics on */
  230. gget( Buf, "Ystub.tics" ); 
  231. if( smember( Buf, "left both" )) tl = YES; else tl = NO;
  232. if( smember( Buf, "right both" )) tr = YES; else tr = NO;
  233.  
  234. /* sides to put stubs on */
  235. gget( Buf, "Ystub.stubs" ); 
  236. if( smember( Buf, "left both" )) sl = YES; else sl = NO;
  237. if( smember( Buf, "right both" )) sr = YES; else sr = NO;
  238.  
  239. /* point size of stubs */
  240. gget( Buf, "Ystub.size" ); NTptsize( atoi( Buf ) );
  241.  
  242. /* shade level for shaded blocks */
  243. gget( shade, "Ystub.shade" );
  244.  
  245. /* grid style */
  246. gget( Buf, "Ystub.grid" ); 
  247. if( strcmp( Buf, "line" )==0 ) grid = LINE;
  248. else if( strcmp( Buf, "shade" )==0 ) grid = SHADE;
  249. else if( strcmp( Buf, "wline" )==0 ) grid = WLINE;
  250. else grid = NO;
  251.  
  252. /* minor tics */
  253. gget( Buf, "Ystub.minor" ); minor = atoi( Buf );
  254.  
  255. gget( Buf, "Ystub.xofs" ); ystubxofs = - atof( Buf ); /* note sign change */
  256. gget( Buf, "Ystub.nolonetics" ); if( Buf[0] == 'y' ) no_lone_tics = 1; else no_lone_tics = 0;
  257.  
  258. /**** loop for doing y axis tics and stubs ****/
  259. even = YES;
  260. n = 0; /* counter for stub from var */
  261. gget( Buf, "Ystart.0or1" ); stub0or1 = atoi( Buf );
  262. if( stub0or1 ) { f = DYlo + (stub0or1 * DYtic); stop = DYhi - DYtic; }
  263. else { f = DYlo; stop = DYhi; }
  264. for( ; f <= stop +.0001; f+= DYtic ) {
  265.  
  266.     /* get stub text */
  267.     if( stubisrc == NUMERIC )sprintf( str, DYticfmt, f );
  268.     else if( stubisrc == VAR ) {
  269.         if( n < N_d_rows ) strcpy( str, D[ n++ ][ atoi( &Buf[1] ) -1 ] );
  270.         else str[0] = '\0';
  271.         }
  272.     else if( stubisrc == FROM_FILE) { 
  273.         if( fgets( str, 30, fp ) == NULL ) str[0] = '\0';
  274.         str[ strlen( str )-1 ] = '\0'; 
  275.         if( str[0] == '!' ) { str[0] = ' '; sscanf( &str[1], "%lf", &f ); if( f > stop ) break; }
  276.         }
  277.  
  278.     if( no_lone_tics && strlen( str ) < 1 ) { even = !even; continue; }
  279.  
  280.     if( tl ) { NTm( DXlo, f ); NTlin( da_x( DXlo ) - tcl , da_y( f ) ); } /* tics, left */
  281.     if( tr ) { NTm( DXhi, f ); NTlin( da_x( DXhi ) + tcl , da_y( f ) ); } /* tics, right */
  282.     if( f <= (DYhi-DYtic)+.0001 ) for( i = 0, g = f; i < minor; i++ ) {  /* minor tics */
  283.         g+= DYtic / (double) minor ;
  284.         if( tl ) { NTm( DXlo, g ); NTlin( da_x( DXlo ) - mtcl , da_y( g ) ); } /* tics, left */
  285.         if( tr ) { NTm( DXhi, g ); NTlin( da_x( DXhi ) + mtcl , da_y( g ) ); } /* tics, right */
  286.         }
  287.     if( sl ) { NTmov( da_x( DXlo ) - 2, da_y( f ) - 0.03 ); NTrightjust( str, (2+ystubxofs) ); } /* text left */
  288.     if( sr ) { NTmov( da_x( DXhi ) - ystubxofs , da_y( f ) - 0.03 ); NTtext( str ); }    /* text right */
  289.     if( grid == LINE ) {     /* lines */
  290.         NTlinetype( "0", 0.3, 0 );
  291.         NTm( DXlo, f ); 
  292.         NTl( DXhi, f ); 
  293.         NTnormline();
  294.         }
  295.     if( grid == WLINE ) ab_rect( da_x( DXlo ), da_y( f ) - 0.02, da_x( DXhi ), da_y( f )+ 0.02, 1.0, 0 );
  296.     if( grid == SHADE && even && f <= (DYhi-DYtic)+.0001 ) { /* shaded blocks */
  297.         rect( DXlo, f, DXhi, f+DYtic, atof( shade ), 0 );
  298.         } 
  299.     even = !even;
  300.     }
  301. if( stubisrc == FROM_FILE ) fclose( fp );
  302. if( smember( do_y, "left both" ) ) { NTmov( Xlo, Ylo ); NTlin( Xlo, Yhi ); }
  303. if( smember( do_y, "right both" ) ) { NTmov( Xhi, Ylo ); NTlin( Xhi, Yhi ); }
  304.  
  305.  
  306.  
  307. /**** X ****/
  308. /* draw axis line */
  309. BEGIN_X:
  310. gget( do_x, "Xaxis" ); 
  311. if( do_x[0] == 'n' ) goto TITLES; /* dont do any of this */
  312.  
  313. gget( Buf, "Xstub.ticlen" ); tcl = atof( Buf );
  314. gget( Buf, "Xstub.ticlen.minor" ); mtcl = atof( Buf );
  315.  
  316. /* Figure out where stub text will come from.. either
  317.  * plain numeric, from a data field, from a file, or literally specified.
  318.  * Also available for x axis only is month/year, which actually comes from a file. */
  319.  
  320. gget( Buf, "Xstub" ); 
  321.  
  322. if( strcmp( Buf, "num" )==0 ) stubisrc = NUMERIC;
  323. else if( Buf[0] == '@' ) { 
  324.     stubisrc = VAR; 
  325.     varfield = atoi( &Buf[1] ); 
  326.     if( varfield < 1 || varfield > N_d_fields ) { fprintf( stderr, "bad stub var field\n" ); gdp_exit(); }
  327.     }
  328. else if( strcmp( Buf, "month" )==0 ) { 
  329.     int start;
  330.     if( Scale_discipline_x == YYMM ) {
  331.         gget( Buf, "Xmin" );
  332.         sprintf( month, "%02d", atoi( Buf ) % 100 );
  333.         sprintf( year, "%02d", atoi( Buf ) / 100 );
  334.         }
  335.     else    {
  336.         gget( month, "Xstub.startmonth" );
  337.         gget( year, "Xstub.startyear" );
  338.         }
  339.     if( month[0] == '\0' || year[0] == '\0' ) {
  340.         fprintf( stderr, "Warning, Xstub.startmonth (1-12) or Xstub.startyear (70-90) are missing.\n" );
  341.         }
  342.     start = (((atoi(year)%100)*12) + atoi( month )) - (70*12);
  343.     fp = fopen( MONTHSTUB_PATH, "r" );
  344.     if( fp == NULL ) { fprintf( stderr, "Can't open month stub file.\n" ); gdp_exit(); }
  345.     for( i = 0; i < start; i++ ) fgets( str, 30, fp );
  346.     stubisrc = FROM_FILE;
  347.     }
  348. else     {
  349.     stubisrc = FROM_FILE;
  350.     fp = fopen( Buf, "r" );
  351.     if( fp != NULL ) {
  352.         gget( Buf, "Xstub.fileline" );
  353.         for( i = 0; i < atoi( Buf ); i++ ) fgets( str, 30, fp );
  354.         }
  355.     else if( fp == NULL ) {
  356.         sprintf( Buf2, "%s/%s", Templatepath, Buf );
  357.         fp = fopen( Buf2, "r" );
  358.         if( fp != NULL ) {
  359.             gget( Buf, "Xstub.fileline" );
  360.             for( i = 0; i < atoi( Buf ); i++ ) fgets( str, 30, fp );
  361.             }
  362.  
  363.         else if( fp == NULL ) {
  364.             text_tofile( Buf, Tempfile );
  365.             fp = fopen( Tempfile, "r" );
  366.             }
  367.         }
  368.     }
  369.  
  370.  
  371. gget( Buf, "Xstub.tics" ); 
  372. if( smember( Buf, "bottom both" )) tl = YES; else tl = NO;
  373. if( smember( Buf, "top both" )) tr = YES; else tr = NO;
  374.  
  375. gget( Buf, "Xstub.stubs" ); 
  376. if( smember( Buf, "bottom both" )) sl = YES; else sl = NO;
  377. if( smember( Buf, "top both" )) sr = YES; else sr = NO;
  378.  
  379. gget( Buf, "Xstub.size" ); NTptsize( atoi( Buf ) );
  380. gget( shade, "Xstub.shade" );
  381.  
  382. gget( Buf, "Xstub.grid" ); 
  383. if( strcmp( Buf, "line" )==0 ) grid = LINE; 
  384. else if( strcmp( Buf, "shade" )==0 ) grid = SHADE;
  385. else if( strcmp( Buf, "wline" )==0 ) grid = WLINE;
  386. else grid = NO;
  387.  
  388. gget( Buf, "Xstub.minor" ); minor = atoi( Buf );
  389. gget( Buf, "Xstub.nolonetics" ); if( Buf[0] == 'y' ) no_lone_tics = 1; else no_lone_tics = 0;
  390.  
  391. /**** loop for doing x axis tics and stubs ****/
  392. n = 0;
  393. even = YES;
  394. gget( Buf, "Xstub.yofs" ); xstubyofs = - atof( Buf ); /* note sign change */
  395. gget( Buf, "Xstart.0or1" ); stub0or1 = atoi( Buf );
  396. if( stub0or1 ) { f = DXlo + (stub0or1 * DXtic ); stop = DXhi - DXtic; }
  397. else { f = DXlo; stop = DXhi; }
  398. for( ; f <= stop + .0001; f+= DXtic ) {
  399.  
  400.     /* get stub text */
  401.     if( stubisrc == NUMERIC )sprintf( str, DXticfmt, f );
  402.     else if( stubisrc == VAR ) {
  403.         if( n < N_d_rows ) strcpy( str, D[ n++ ][ varfield -1 ] );
  404.         else str[0] = '\0';
  405.         }
  406.     else if( stubisrc == FROM_FILE) { 
  407.         if( fgets( str, 30, fp ) == NULL ) str[0] = '\0';
  408.         else str[ strlen( str )-1 ] = '\0'; 
  409.         if( str[0] == '!' ) { str[0] = ' '; sscanf( &str[1], "%lf", &f ); if( f > stop ) break; }
  410.         }
  411.  
  412.     if( no_lone_tics && strlen( str ) < 1 ) { even = !even; continue; }
  413.  
  414.     if( tl ) { NTm( f, DYlo ); NTlin( da_x( f ), da_y( DYlo ) - tcl ); }
  415.     if( tr ) { NTm( f, DYhi ); NTlin( da_x( f ), da_y( DYhi ) + tcl ); }
  416.     if( f <= (stop-DXtic)+.0001 ) for( i = 0, g = f; i < minor; i++ ) {  /* minor tics */
  417.         g+= DXtic / (double) minor ;
  418.         if( tl ) { NTm( g, DYlo ); NTlin( da_x( g ), da_y( DYlo ) - mtcl ); }
  419.         if( tr ) { NTm( g, DYhi ); NTlin( da_x( g ), da_y( DYhi ) + mtcl ); }
  420.         }
  421.  
  422.     if( sl ) {    /* tokens are stacked, max=3 */
  423.         char s[3][30];
  424.         for( i = 0; i < strlen( str ); i++ ) { 
  425.             if( str[i] == ' ' )str[i] = '_';
  426.             else if( str[i] == '~' ) str[i] = '\n' ;
  427.             }
  428.         nrows = sscanf( str, "%s %s %s", s[0], s[1], s[2] ); 
  429.         h = da_y( DYlo ) + xstubyofs;
  430.         for( i = 0; i < nrows; i++ ) {
  431.             for( j = 0; j < strlen( s[i] ); j++ ) if( s[i][j]== '_' ) s[i][j]=' ';
  432.             NTmov( da_x( f ) - 1, h ); NTcentext( s[i], 2 ); 
  433.             h -= Chh;
  434.             }
  435.         }
  436.     if( sr ){ 
  437.         char s[3][30];
  438.         for( i = 0; i < strlen( str ); i++ ) { 
  439.             if( str[i] == ' ' )str[i] = '_';
  440.             else if( str[i] == '~' ) str[i] = '\n' ;
  441.             }
  442.         nrows = sscanf( str, "%s %s %s", s[0], s[1], s[2] ); 
  443.         h = -(xstubyofs) + da_y( DYhi ) + ((nrows-2)*Chh); /* */
  444.         for( i = 0; i < nrows; i++ ) {
  445.             for( j = 0; j < strlen( s[i] ); j++ ) if( s[i][j]== '_' ) s[i][j]=' ';
  446.             NTmov( da_x( f ) - 1, h ); NTcentext( s[i], 2 ); 
  447.             h -= Chh;
  448.             }
  449.         }
  450.  
  451.  
  452.     if( grid == LINE ) { 
  453.         NTlinetype( "0", 0.3, 0 );
  454.         NTm( f, DYlo ); 
  455.         NTl( f, DYhi ); 
  456.         NTnormline();
  457.         }
  458.     if( grid == WLINE ) ab_rect( da_x( f ) - 0.02, da_y( DYlo ), da_x( f ) + 0.02, da_y( DYhi ), 1.0, 0 );
  459.         
  460.     if( grid == SHADE && even && f <= (stop-DXtic)+.0001 ) { 
  461.         rect( f, DYlo, f+DXtic, DYhi, atof( shade ), 0 );
  462.         } 
  463.     even = !even;
  464.     }
  465. if( stubisrc == FROM_FILE ) fclose( fp );
  466. if( smember( do_x, "top both" ) ) { NTmov( Xlo, Yhi ); NTlin( Xhi, Yhi ); }
  467. if( smember( do_x, "bottom both" ) ){ NTmov( Xlo, Ylo ); NTlin( Xhi, Ylo ); }
  468.  
  469. TITLES:
  470.  
  471.  
  472. /**** do axis identifiers ****/
  473.     {
  474.     int n, c1, c2, c3;
  475.     double ofs;
  476.     gget( Buf, "Xlabel" );
  477.     if( strlen( Buf ) > 0 ) {
  478.         gget( Buf2, "Xlabel.size" ); NTptsize( atof( Buf2 ) );
  479.         gget( Buf2, "Xlabel.position" ); ofs = atof( Buf2 );
  480.         getln( "" );
  481.         for( i = 0; i < countln( Buf ); i++ ) {
  482.             NTmov( Xlo, Ylo - ofs ); 
  483.             NTcentext( getln( Buf ), (Xhi-Xlo) );
  484.             ofs += Chh; 
  485.             }
  486.         }
  487.  
  488.     gget( Buf, "Ylabel" );
  489.     if( strlen( Buf ) > 0 ) {
  490.         gget( Buf2, "Ylabel.size" ); NTptsize( atof( Buf2 ) );
  491.         gget( Buf2, "Ylabel.position" ); ofs = atof( Buf2 );
  492.         NTchardir( 90 );
  493.         getln( "" );
  494.         for( i = 0; i < countln( Buf ); i++ ) {
  495.             NTmov( Xlo-ofs, Ylo ); 
  496.             NTcentext( getln( Buf ), (Yhi-Ylo) ); 
  497.             ofs -= Chh;
  498.             }
  499.         NTchardir( 0 );
  500.         }
  501.     }
  502.  
  503. /**** area title ****/
  504.     {
  505.     int i = 1, c;
  506.     double ofs;
  507.     char just[20];
  508.  
  509.     gget( Buf, "Subtitle" );
  510.     if( strlen( Buf ) > 0 ) {
  511.         gget( Buf2, "Subtitle.font" ); NTfont( Buf2 );
  512.         gget( Buf2, "Subtitle.size" ); NTptsize( atof( Buf2 ) );
  513.         gget( Buf2, "Subtitle.above" ); ofs = atof( Buf2 );
  514.         gget( Buf2, "Subtitle.justify" ); strcpy( just, Buf2 );
  515.  
  516.         getln( "" );
  517.         for( i = 0; i < countln( Buf ); i++ ) {
  518.             NTmov( Xlo+0.1, Yhi+ofs );
  519.             if( strcmp( just, "center" )==0 ) NTcentext( getln( Buf ), Xhi-(Xlo+0.1) );
  520.             else if( strcmp( just, "right" )==0 )NTrightjust( getln( Buf ), Xhi-(Xlo+0.1) );
  521.             else NTtext( getln( Buf ) );
  522.             ofs -= Chh;
  523.             }
  524.         }
  525.     }
  526. /* restore standard font */
  527. gget( Buf, "Font" ); NTfont( Buf );
  528. }
  529.  
  530. SHAR_EOF
  531. ############################
  532.  
  533. cat << SHAR_EOF > src/areas.h
  534. /* # area.coords
  535. #   The following is a list of predefined graphics areas (windows) on the page.
  536. # Some use the whole page; those beginning with '2' are for doing two plots 
  537. # per page, 3 for three plots per page, etc.
  538. #   These names can be used as the Area in Proc Areadef.  If none
  539. # of these is suitable, Area.left, Area.right, etc. can be defined explicitly.
  540. # Coordinates are in inches, with the origin in the lower left.
  541. #
  542. #                 ---portrait----    ---landscape---
  543. # format is: 
  544. # AREA NAME (must be followed by space(s))
  545. #               XLO YLO XHI YHI    XLO YLO XHI YHI
  546. # */
  547.  
  548. char *Areacoords[30] = {
  549. "standard     1.2 3.5 7.4 8.0   1.5 1.5 9.0 6.2",
  550. "square       1.2 2.0 7.2 8.0   2.2 0.8 8.2 6.8",
  551. "dist1        1.2 6.5 7.2 8.0   2.2 5.3 8.2 6.8",
  552. "whole        1.2 1.0 7.4 9.0   1.5 1.2 9.0 7.0",
  553. "2hi          1.0 6.0 7.6 9.5   1.0 4.5 9.0 7.5",
  554. "2lo          1.0 1.5 7.6 5.0   1.0 0.75 9.0 3.75",
  555. "2left        1.0 1.0 4.0 9.5   1.0 1.0 5.25 6.5",
  556. "2right       5.0 1.0 8.0 9.5   6.25 1.0 10.5 6.5",
  557. "3hi          1.0 7.0 7.6 9.0   1.0 5.5 9.0 7.5",
  558. "3mid         1.0 4.0 7.6 6.0   1.0 3.0 9.0 5.0",
  559. "3lo          1.0 1.0 7.6 3.0   1.0 0.5 9.0 2.5",
  560. "4nw          1.0 6.0 4.0 9.0   1.0 4.0 5.25 7.0",
  561. "4ne          4.5 6.0 7.5 9.0   6.25 4.0 10.5 7.0",
  562. "4sw          1.0 1.5 4.0 4.5   1.0 0.5 5.25 3.5",
  563. "4se          4.5 1.5 7.5 4.5   6.25 0.5 10.5 3.5",
  564. "map          0.4 2.0 6.8 8.4   1.4 0.8 7.8 7.2",
  565. "usamap       .5  5 8 9.5        .5  1 10.5 7",
  566. "lifetab      1.0 1.0 7.0 4.5   1.5 1.0 7.5 4.5",
  567. "nicetab      1.0 0.5 7.5 10    1.5 0.5 9.0 7.0",
  568. "narrowtab    2.0 0.5 6.0 10    3.0 0.5 8.0 7.0",
  569. "narrowleft   1.0 0.4 4.0 10.5  1.0 1.0 5.25 6.5",
  570. "narrowright  5.0 0.4 8.0 10.5  6.25 1.0 10.5 6.5" ,
  571. "tabhi        1.0 5.5 8.0 10.5  1.0 4.3 10.0 8.0",
  572. "tablo        1.0 0.5 8.0 5.5   1.0 0.5 10.0 4.2"
  573.     } ;
  574. int Nareas = 25;
  575. SHAR_EOF
  576. ############################
  577.  
  578. cat << SHAR_EOF > src/arrow.c
  579. #include "ipl.x"
  580.  
  581. Arrow( )
  582. {
  583. double x1, y1, x2, y2;
  584. gget( Buf, "Points" );
  585. sscanf( Buf, "%lf %lf %lf %lf", &x1, &y1, &x2, &y2 );
  586. arr( x1, y1, x2, y2, 0.3, 0.2, 0.0 );
  587. }
  588.  
  589.  
  590. arr( x1, y1, x2, y2, delt_th, r, sh )
  591. double x1, y1, x2, y2, delt_th, r, sh;
  592. {
  593. double vx, vy, ax1, ay1, ax2, ay2, th0, th1, th2, atan();
  594. vx = x2 - x1;
  595. vy = y2 - y1;
  596.  
  597. th0 = atan( vy / vx );
  598. th1 = th0 + delt_th;
  599. th2 = th0 - delt_th;
  600.  
  601. if( x2 < x1 ) {
  602.     ax1 = x2 + (r * cos( th1 ));
  603.     ay1 = y2 + (r * sin( th1 ));
  604.     ax2 = x2 + (r * cos( th2 ));
  605.     ay2 = y2 + (r * sin( th2 ));
  606.     }
  607. else     {
  608.     ax1 = x2 - (r * cos( th1 ));
  609.     ay1 = y2 - (r * sin( th1 ));
  610.     ax2 = x2 - (r * cos( th2 ));
  611.     ay2 = y2 - (r * sin( th2 ));
  612.     }
  613.  
  614. NTmov( x2, y2 );
  615. NTpath( ax1, ay1 );
  616. NTpath( ax2, ay2 );
  617. NTshade( sh );
  618. NTmov( x1, y1 );
  619. NTlin( x2, y2 );
  620. }
  621. SHAR_EOF
  622. ############################
  623.  
  624. cat << SHAR_EOF > src/bargraph.c
  625. /* horizontal (standard) bar graphs */
  626. #include "ipl.x"
  627. #define STACK    0
  628. #define CLUSTER 1
  629.  
  630.  
  631. Bargraph( )
  632. {
  633. int     k[8], 
  634.     idf[8],
  635.     format,
  636.     label,
  637.     n,
  638.     nc,
  639.     i, j, jj,
  640.     p,
  641.     xfld,
  642.     xset,
  643.     start,
  644.     outline;
  645.  
  646. double s[8],
  647.     accum,
  648.     zer,
  649.     curx,
  650.     xspace,
  651.     subspace,
  652.     y,
  653.     y2,
  654.     f,
  655.     lblpos,
  656.     sep,
  657.     msep = 0.03;
  658. char str[10];
  659.  
  660.  
  661. /* get the data field list */
  662. gget( Buf, "Field" ); 
  663. n = 0;
  664. while( n < 1 ) { 
  665.     n = sscanf( Buf, "%d %d %d %d %d %d %d %d", &k[0], &k[1], &k[2], &k[3], &k[4], &k[5], &k[6], &k[7] );
  666.     if( N_d_fields == 1 ) strcpy( Buf, "1" );
  667.     else if( n < 1 ) { fprintf( stderr, "Field parameter(s) for bar graph are missing.\n" ); gdp_exit(); }
  668.     }
  669. for( i = 0; i < n; i++ ) 
  670.     if( k[i] < 1 || k[i] > N_d_fields ) { fprintf( stderr, "Field is bad\n" ); gdp_exit(); }
  671.  
  672. /* get the label field list, if any */
  673. gget( Buf, "Idfield" ); 
  674. if( strlen( Buf ) > 0 ) { 
  675.     label = YES;
  676.     sscanf( Buf, "%d %d %d %d %d %d %d %d", &idf[0], &idf[1], &idf[2], &idf[3], &idf[4], &idf[5], &idf[6], &idf[7] );
  677.     for( i = 0; i < n; i++ ) 
  678.         if( idf[i] < 1 || idf[i] > N_d_fields ) { fprintf( stderr, "Idfield is bad\n" ); gdp_exit(); }
  679.     }
  680. else label = NO;
  681.  
  682. gget( Buf, "Format" );  
  683. if( strcmp( Buf, "stack" )==0 ) format = STACK;
  684. else format = CLUSTER;
  685.  
  686. DXtic = 1.0;
  687.  
  688. /* get bar shades */
  689. gget( Buf, "Shade" ); 
  690. sscanf( Buf, "%lf %lf %lf %lf %lf %lf %lf %lf", &s[0], &s[1], &s[2], &s[3], &s[4], &s[5], &s[6], &s[7] );
  691.  
  692. /* get zero line */
  693. gget( Buf, "Zeroat" ); 
  694. if( goodnum( Buf, &p )) zer = atof( Buf );
  695. else zer = DYlo;
  696.  
  697. /* get label size */
  698. if( label ) { gget( Buf, "Idfield.size" ); NTptsize( atof( Buf ) ) };
  699.  
  700. /* distance of label from bar top */
  701. if( label ) { gget( Buf, "Idfield.position" ); lblpos = atof( Buf ); }
  702.  
  703. /* outline or not */
  704. gget( Buf, "Outlinebars" ); if( Buf[0] == 'y' ) outline = YES; else outline = NO;
  705.  
  706. /* x distance between major bar spaces */
  707. gget( Buf, "Separation" ); sep = atof( Buf );
  708.  
  709. gget( Buf, "Separation.sub" ); msep = atof( Buf );
  710.  
  711. xspace = ( (Xhi-Xlo)/((DXhi-DXlo)+1) ) - (sep*Scale_x);
  712.  
  713. if( format == CLUSTER ) nc = n; else nc = 1;
  714.  
  715. gget( Buf, "Killwild" ); /* option for aborting plot if any values out of range */
  716. if( atof( Buf ) != 0 ) {
  717.     for( i = 1; i <= N_d_rows; i++ ) {
  718.         if( atof( D[i-1][ k[0] -1 ] ) > atof( Buf ) ) {
  719.             fprintf( stderr, "Note: This Bargraph terminated due to a value of %s.\n", D[i-1][k[0]-1] );
  720.             return( 0 );
  721.             }
  722.         }
  723.     }
  724.  
  725. gget( Buf, "Xfield" ); /* allow placement of bars by a data field */
  726. if( strlen( Buf ) > 0 ) {
  727.     xset = 1;
  728.     xfld = atoi( Buf );
  729.     if( xfld < 1 || xfld > N_d_fields ) { fprintf( stderr, "Yfield bad.\n" ); gdp_exit(); }
  730.     }
  731. else xset = 0;
  732.  
  733. gget( Buf, "Xstart.0or1" ); /* allow starting at 0 or 1 */
  734. if( Buf[0] == '0' ) { start = 0; }
  735. else { start = 1; }
  736.  
  737. for( i = 1; i <= N_d_rows; i++ ) {
  738.     if( xset ) curx = da_x( atof( D[i-1][xfld-1] ) ) - (xspace/2);
  739.     else curx = da_x((double)(DXlo+i+(start-1))) - (xspace/2);
  740.  
  741.     subspace = ( xspace / nc );
  742.     for( j = 0; j < nc; j++ ) {
  743.         if( !goodnum( D[i-1][ k[j]-1 ], &p )) {
  744.             fprintf( stderr, "Warning, row %d, field %d, is bad (%s)\n", i, k[j], D[i-1][ k[j]-1] );
  745.             curx += subspace;
  746.             continue;
  747.             }
  748.         y = atof(D[i-1][ k[j]-1 ]);
  749.         if( y != DYlo )
  750.             ab_rect( curx, da_y(zer), curx+(subspace-msep), da_y(y), s[j], (s[j]==1)?1:outline );
  751.         if( label ) {
  752.             if( y < zer || format == STACK ) f = (-lblpos)-Chh; else f = lblpos;
  753.             strcpy( str, D[i-1][ idf[j]-1 ] );
  754.             NTmov( curx, da_y(y)+f );
  755.             NTcentext( str, subspace-msep );
  756.             }
  757.         if( format == STACK ) for( jj = 1; jj < n; jj++ ) {
  758.             if( !goodnum( D[i-1][ k[jj] -1 ], &p ) ) {
  759.                 fprintf( stderr, "Warning, row %d, field %d, is bad (%s)\n", i, k[jj], D[i-1][k[jj]-1] );
  760.                 continue;
  761.                 }
  762.             y2 = y + atof( D[i-1][ k[jj] -1 ] );
  763.             if( y2 != DYlo )
  764.                 ab_rect( curx, da_y(y), curx+(subspace-msep), da_y(y2), s[jj], (s[jj]==1)?1:outline );
  765.             if( label ) {
  766.                 if( y2 < zer || format == STACK ) f = (-lblpos)-Chh; else f = lblpos;
  767.                 NTmov( curx, da_y(y2)+f );
  768.                 strcpy( str, D[i-1][ idf[jj]-1 ] );
  769.                 NTcentext( str, subspace-msep );
  770.                 }
  771.             y = y2;
  772.             }
  773.  
  774.         curx += subspace;
  775.         }
  776.     }
  777.  
  778. gget( Buf, "Segment" );
  779. if( Buf[0] == 'y' ) 
  780.     for( f = DYlo+DYtic; f < DYhi; f += DYtic ) 
  781.         rect( DXlo + 0.2, f-(DYhi*0.003), DXhi - 0.2, f+(DYhi*0.004), 1.0, 0 );
  782. }
  783. SHAR_EOF
  784. ############################
  785.  
  786. cat << SHAR_EOF > src/boxplot.c
  787. #include "ipl.x"
  788. Boxplot( )
  789. {
  790. int f[8], row, i, doends;
  791. double val[8];
  792. double w, x;
  793.  
  794. gget( Buf, "Linethick" );
  795. NTlinetype( "0", atof( Buf ), 1.0 );
  796.  
  797. gget( Buf, "Label.size" );
  798. if( atoi( Buf ) > 0 ) NTptsize( atoi( Buf ) );
  799.  
  800. gget( Buf, "Ends" );
  801. if( Buf[0] == 'y' ) doends = 1;
  802. else doends = 0;
  803.  
  804. gget( Buf, "Fields" );
  805. if( strlen( Buf ) > 0 ) {
  806.     if( sscanf( Buf, "%d %d %d %d %d %d", &f[0], &f[1], &f[2], &f[3], &f[4], &f[5] ) != 6 ) {
  807.         fprintf( stderr, "Fields should specify six data fields (n, and the 5,25,50,75,95 percentiles)\n" );
  808.         gdp_exit();
  809.         }
  810.     }
  811.  
  812. gget( Buf, "Datarow" );
  813.  
  814. row = atoi( Buf );
  815. for( i = 0; i < 6; i++ ) {
  816.     if( f[i] < 1 || f[i] > N_d_fields ) { fprintf( stderr, "Pfields bad.\n" ); gdp_exit(); }
  817.     else if( row > 0 && row <= N_d_rows ) val[i] = atof( D[ row - 1 ][ f[i]-1 ] );
  818.     else { fprintf( stderr, "Datarow bad.\n" ); gdp_exit(); }
  819.     }
  820.  
  821. gget( Buf, "Xloc" ); x = atof( Buf );
  822. gget( Buf, "Width" ); w = atof( Buf );
  823.  
  824. NTm( x-(w/2), val[2] ); /* lower edge of box */
  825. NTp( x+(w/2), val[2] );
  826. NTp( x+(w/2), val[4] );
  827. NTp( x-(w/2), val[4] );
  828. NTp( x-(w/2), val[2] ); /* upper edge */
  829. NTshade( 1.0 );
  830.  
  831. NTm( x, val[1] ); /* lower tail */
  832. NTl( x, val[2] );
  833. if( doends ) { NTm( x-(w/2.7), val[1] ); NTl( x+(w/2.7), val[1] ); }
  834.  
  835. NTm( x-(w/2), val[2] ); /* lower edge of box */
  836. NTl( x+(w/2), val[2] );
  837. NTl( x+(w/2), val[4] );
  838. NTl( x-(w/2), val[4] );
  839. NTl( x-(w/2), val[2] ); /* upper edge */
  840.  
  841. NTm( x, val[4] );
  842. NTl( x, val[5] ); /* upper tail */
  843. if( doends ) { NTm( x-(w/2.7), val[5] ); NTl( x+(w/2.7), val[5] ); }
  844.  
  845. NTm( x-(w/2), val[3] ); /* median line */
  846. NTl( x+(w/2), val[3] );
  847.  
  848. gget( Buf, "Printn" );
  849. if( Buf[0] == 'y' ) {
  850.     NTmov( da_x(x) -1, Ylo-0.15 );  /* print N */
  851.     sprintf( Buf, "N = %d", (int) (val[0]) );
  852.     NTcentext( Buf, 2 );
  853.     }
  854.  
  855. NTnormline();
  856. }
  857. SHAR_EOF
  858. ############################
  859.  
  860. cat << SHAR_EOF > src/constraint_check.c
  861. /* constraint_check() - checks user parameter value against constraints
  862.    from param. database, if any.  If violated, returns 0, otherwise, returns 1.
  863.  
  864.    Supported constraint types are:    example:        sample input:
  865.     numeric range            0 to 12            2
  866.     any number            number            3.1415
  867.     set                {center,left,right}    left
  868.     character size            charsize        6
  869.     vector (x,y)            coordpair        3.55 2.00
  870.     character string        token            hello
  871.     *    a list of tokens sep. by space    list            0 0.2 0.4 0.7 1
  872.     *    multi-line text            text            Hello world,
  873.                                 is there anyone there?
  874.     * No enforcement done here for these types..
  875. */
  876. #include <stdio.h>
  877. #include "../install.h"
  878.  
  879. constraint_check( value, constraint )
  880. char value[], constraint[];
  881. {
  882. char token[30], val[30], cn[5][8];
  883. double atof(), fval, high, low;
  884. int i, j, multi, rtnval, nct, ix;
  885.  
  886. if( strlen( value ) < 1 ) return( 1 ); /* empty */
  887.  
  888. if( smember( constraint, "list text" )) return( 1 );
  889.  
  890. /* anything else should be single token (or series of single tokens with like types) */
  891. nct = sscanf( constraint, "%*s %s %s %s %s %s", cn[0], cn[1], cn[2], cn[3], cn[4] );
  892. multi = 0;
  893. for( i = 0; i < nct; i++ ) if( strncmp( &cn[i][1], "list", 4 )==0 ) multi = 1;
  894.  
  895.  
  896. /* check members of list.. */
  897. rtnval = 1;
  898. ix = 0;
  899. while( 1 ) {
  900.     strcpy( val, getok( value, &ix ) );
  901.     if( val[0] == '\0' ) break;
  902.     i = 0;
  903.  
  904.     /* sets */
  905.     if( constraint[i] == '{' ) {
  906.         for( j = i; j < strlen( constraint ); j++ ) if( member( constraint[j], "{,}"  )) constraint[j] = ' ';
  907.         while( 1 ) {
  908.             strcpy( token, getok( constraint, &i ) );
  909.             if( token[0] == '\0' ) { 
  910.                 fprintf( stderr, "'%s' illegal.  Legal vals are: { %s }.", val, constraint ); 
  911.                 rtnval = 0;
  912.                 break;
  913.                 }
  914.             if( strcmp( token, val )==0 ) { rtnval = 1; break; }
  915.             }
  916.         }
  917.     
  918.     /* numeric ranges */
  919.     j = i;
  920.     low = atof( getok( constraint, &j ) );
  921.     if( strcmp( getok( constraint, &j ), "to" )==0 ) {
  922.         high = atof( getok( constraint, &j ) );
  923.         fval = atof( val );
  924.         if( fval < low || fval > high ) 
  925.             { fprintf( stderr, "'%s' out of range. Range is %5.2f to %5.2f.", val, low, high ); rtnval = 0; }
  926.         else rtnval = 1;
  927.         }
  928.     
  929.     /* generic number */
  930.     j = i;
  931.     if( strcmp( getok( constraint, &j ), "number" ) == 0 ) {
  932.         if( ! goodnum( val, &j ) ) 
  933.             { fprintf( stderr, "'%s' is not a number." , val ); rtnval = 0; }
  934.         else rtnval = 1;
  935.         }
  936.     
  937.     /* coordinate pair */
  938.     j = i;
  939.     if( strcmp( getok( constraint, &j ), "coordpair" ) == 0 ) {
  940.         char val1[12], val2[12];
  941.         sscanf( value, "%s %s", val1, val2 );
  942.         if( !goodnum( val1, &j ) || !goodnum( val2, &j ) )
  943.             { fprintf( stderr, "'%s' is not a coordinate pair.", value ); rtnval = 0; }
  944.         else rtnval = 1;
  945.         }
  946.     
  947.     /* 2coordpair (rectangle) */
  948.     j = i;
  949.     if( strcmp( getok( constraint, &j ), "2coordpair" ) == 0 ) {
  950.         char val1[12], val2[12], val3[12], val4[12];
  951.         sscanf( value, "%s %s %s %s", val1, val2, val3, val4 );
  952.         if( !goodnum( val1, &j ) || !goodnum( val2, &j ) ||
  953.             !goodnum( val3, &j ) || !goodnum( val4, &j ) )
  954.             { fprintf( stderr, "'%s' is not a 2coordpair.", value ); rtnval = 0; }
  955.         else rtnval = 1;
  956.         }
  957.     
  958.     /* char size */
  959.     j = i;
  960.     if( strcmp( getok( constraint, &j ), "charsize" ) == 0 ) {
  961.         fval = atof( val );
  962.         if( fval < 1 || fval > 36.0 ) {
  963.             fprintf( stderr, "'%s' is not a legal char size (1 to 32).", val );
  964.             rtnval = 0;
  965.             }
  966.         else rtnval = 1;
  967.         }
  968.  
  969.     /* data field */
  970.     j = i;
  971.     if( strcmp( getok( constraint, &j ), "dfield" ) == 0 ) {
  972.         if( atoi( val ) > 0 && atoi( val ) <= MAX_D_COLS ) rtnval = 1;
  973.         else {
  974.             fprintf( stderr, "'%s' is not a legal data field number (1 to %d).", val, MAX_D_COLS );
  975.             rtnval = 0;
  976.             }
  977.         }
  978.  
  979.     /* font */
  980.     j = i;
  981.     if( strcmp( getok( constraint, &j ), "font" ) == 0 ) {
  982.         if( val[0] != '/' ) {
  983.             fprintf( stderr, "'%s': first character in font name should be '/'.", val );
  984.             rtnval = 0;
  985.             }
  986.         else rtnval = 1;
  987.         }
  988.  
  989.     /* color */
  990.     j = i;
  991.     if( strcmp( getok( constraint, &j ), "color" ) == 0 ) {
  992.         if( atof( val ) < 0.0 || atof( val ) > 1.0 ) {
  993.             fprintf( stderr, "'%s': color must be a number from 0.0 to 1.0.", val );
  994.             rtnval = 0;
  995.             }
  996.         else rtnval = 1;
  997.         }
  998.  
  999.  
  1000.  
  1001.     if( rtnval == 0 || !multi ) break;
  1002.     }
  1003.  
  1004. return( rtnval );
  1005. }
  1006. SHAR_EOF
  1007. ############################
  1008.  
  1009.  
  1010.