1 /*****************************************************************************
2    Major portions of this software are copyrighted by the Medical College
3    of Wisconsin, 1994-2000, and are released under the Gnu General Public
4    License, Version 2.  See the file README.Copyright for details.
5 ******************************************************************************/
6 // drg - added this coxplot.h inclusion for macos10.15
7 // implicit declaration of find_color_name not allowed
8 #include "coxplot.h"
9 
10 #include "display.h"
11 #include "mrilib.h"
12 
13 static char *x11_vcl[] =  { "StaticGray"  , "GrayScale" , "StaticColor" ,
14                             "PseudoColor" , "TrueColor" , "DirectColor"  } ;
15 
16 MCW_DC *first_dc = NULL ;              /* 26 Jun 2003 */
17 
18 int npane_big = 256 ;                  /* 06 May 2016 */
19 
20 extern int find_color_name( char *cnam, float *rr, float *gg, float *bb ) ; ;
21 
22 /*--------------------------------------------------------------------------*/
23 #undef  USE_TURBO                      /* 22 Aug 2019 - made obsolete below */
24 #define USE_PBARDEFS                   /* 24 Oct 2019 */
25 
26 #ifdef  USE_PBARDEFS
27 
28 # undef USE_TURBO
29 # include "pbardefs_float.h"
30 
31 # define NPBARF 4
32 static char *pbarfname[NPBARF] = { magma_name, plasma_name, viridis_name, googleturbo_name } ;
33 static float  *pbarfar[NPBARF] = { magma_data, plasma_data, viridis_data, googleturbo_data } ;
34 
35 #endif
36 
37 /* use 256 colors for the colorbar? */
38 
39 #if defined(USE_TURBO) || defined(USE_PBARDEFS)
40 # define USE_256
41 #else
42 # undef  USE_256
43 #endif
44 /*------------------------------------------------------------------------*/
45 
46 /*------------------------------------------------------------------------
47   Returns position of highest set bit in 'ul' as an integer (0-31),
48   or returns -1 if no bit is set.
49 --------------------------------------------------------------------------*/
50 
highbit(unsigned long ul)51 static int highbit(unsigned long ul)
52 {
53   int i;  unsigned long hb;
54 
55   hb = 0x80;  hb = hb << 24;   /* hb = 0x80000000UL */
56   for (i=31; ((ul & hb) == 0) && i>=0;  i--, ul<<=1);
57   return i;
58 }
59 
60 /*-------------------------------------------------------------------------
61    Setup the number of bytes per pixel.  For depth 24, this might
62    be 3 or 4, depending on the server.  RWCox -- 23 Aug 1998.
63 ---------------------------------------------------------------------------*/
64 
setup_byper(MCW_DC * dc)65 static void setup_byper( MCW_DC *dc )
66 {
67    XPixmapFormatValues * xpv ;
68    int                  nxpv = 0 , ii ;
69 
70    xpv = XListPixmapFormats( dc->display , &nxpv ) ;
71 
72    if( xpv == NULL || nxpv == 0 ){
73       dc->byper = dc->depth / 8 ; dc->bypad = 1 ;  /* defaults */
74       return ;
75    }
76 
77    /* scan for this depth in the array of pixmap formats */
78 
79    for( ii=0 ; ii < nxpv ; ii++ ){
80       if( xpv[ii].depth == dc->depth ){
81          dc->byper = xpv[ii].bits_per_pixel / 8 ;  /* bytes, not bits */
82          dc->bypad = xpv[ii].scanline_pad   / 8 ;
83          XFree(xpv) ; return ;
84       }
85    }
86 
87    dc->byper = dc->depth / 8 ; dc->bypad = 1 ;  /* defaults */
88    XFree(xpv) ; return ;
89 }
90 
91 /*------------------------------------------------------------------------
92   Create and initialize a new MCW_DC structure.
93 
94     wid  = widget used to get info about Display, etc.
95     ncol = number of colors to use for images
96     novr = number of overlay colors
97     covr = array of strings of overlay color names  [used for XAlloc...]
98     lovr = array of strings of overlay color labels [used for display]
99     gam  = gamma value to use
100 
101   22 Aug 1998: Modified to support TrueColor visuals,
102                as well as the original PseudoColor -- RWCox.
103 
104   14 Sep 1998: Modified to add argument
105     newcmap = if nonzero, create a new Colormap;
106               if zero, use the default Colormap for the display
107               this option is only for PseudoColor
108               [does anyone use PseudoColor any more?]
109 ------------------------------------------------------------------------*/
110 
111 static MCW_DCOV * only_ovc = NULL ;  /* Dec 1997 */
112 
MCW_new_DC(Widget wid,int ncol,int novr,char * covr[],char * lovr[],double gam,int newcmap)113 MCW_DC * MCW_new_DC( Widget wid , int ncol ,
114                      int novr , char * covr[] , char * lovr[] ,
115                      double gam , int newcmap )
116 {
117    MCW_DC *dc ;
118    int ok , ii , new_ovc ;
119    unsigned int nplmsk = 0 ;  /* dummy arguments for XAllocColorCells */
120    unsigned long plane_masks[1] ;
121 
122 ENTRY("MCW_new_DC") ;
123 
124    if( ncol < 4 || novr < 0 || ncol > MAX_COLORS || novr > MAX_COLORS ){
125       fprintf(stderr,"\n*** MCW_new_DC: ILLEGAL number of colors: %d %d\n",ncol,novr) ;
126       ncol = 4 ; novr = 0 ;
127    }
128 
129 if(PRINT_TRACING){
130  char str[256]; sprintf(str,"ncol=%d novr=%d gam=%g",ncol,novr,gam); STATUS(str);
131 }
132 
133    dc = myXtNew(MCW_DC) ;
134 
135    dc->appcontext = XtWidgetToApplicationContext( wid ) ;
136    dc->display    = XtDisplay( wid ) ;
137    dc->screen     = XtScreen( wid ) ;
138    dc->screen_num = XScreenNumberOfScreen(   dc->screen ) ;
139    dc->visual     = DefaultVisualOfScreen(   dc->screen ) ;
140    dc->origGC     = DefaultGCOfScreen(       dc->screen ) ;
141    dc->planes     = PlanesOfScreen(          dc->screen ) ;
142    dc->depth      = DefaultDepthOfScreen(    dc->screen ) ;
143 
144    dc->cdef       = NULL ;  /* 11 Feb 1999: will be loaded later */
145 
146    setup_byper(dc) ;        /* 23 Aug 1998 */
147 
148    dc->default_colormap = DefaultColormapOfScreen( dc->screen ) ; /* 01 Sep 1998 */
149 
150    dc->colormap = DefaultColormapOfScreen( dc->screen ) ; /* may be changed later */
151 
152    dc->parent_widget = wid ;  /* 06 Oct 1996 */
153 
154    dc->does_backingstore = DoesBackingStore(dc->screen) ; /* 27 Feb 2001 */
155    dc->does_saveunders   = DoesSaveUnders(dc->screen) ;
156 
157    /** 07 Aug 1998: get more information about the visual **/
158 
159    { XVisualInfo vinfo , *vinfo_list ;
160      int count ;
161 
162      dc->visual_id  = XVisualIDFromVisual( dc->visual ) ;
163      vinfo.visualid = dc->visual_id ;
164      vinfo_list     = XGetVisualInfo(dc->display,VisualIDMask,&vinfo,&count) ;
165      if( count > 0 && vinfo_list != NULL ){
166         dc->visual_info       = vinfo_list ;
167         dc->visual_redmask    = dc->visual_info->red_mask ;
168         dc->visual_greenmask  = dc->visual_info->green_mask ;
169         dc->visual_bluemask   = dc->visual_info->blue_mask ;
170         dc->visual_redshift   = 7 - highbit(dc->visual_redmask) ;
171         dc->visual_greenshift = 7 - highbit(dc->visual_greenmask) ;
172         dc->visual_blueshift  = 7 - highbit(dc->visual_bluemask) ;
173 #if defined(__cplusplus) || defined(c_plusplus)
174         dc->visual_class      = dc->visual_info->c_class ;
175 #else
176         dc->visual_class      = dc->visual_info->class ;
177 #endif
178         if( dc->visual_class != PseudoColor &&
179             dc->visual_class != TrueColor      ){
180 
181            fprintf(stderr,"\n\n"
182                           " ** The default X11 visual type on your computer is set to %s.\n"
183                           " ** AFNI programs only work with PseudoColor or TrueColor visuals.\n"
184                           " ** You must have your superuser modify your system's setup.\a\n" ,
185                    x11_vcl[dc->visual_class] ) ;
186 
187            dc->visual_class = PseudoColor ;  /* let the program fail later */
188         }
189 
190 #if 0
191         if( dc->visual_class == TrueColor ){  /* removed 28 Oct 1999 */
192            static int done = 0 ;
193            if( !done )
194               fprintf(stderr,
195                  "\n"
196                  " ** The default X11 visual type on your computer is %d bit TrueColor.\n"
197                  " ** Support for this is experimental.  AFNI was developed to use 4..12\n"
198                  " ** bit PseudoColor visuals for image display -- RW Cox, 22 Aug 1998.\n" ,
199                  dc->depth ) ;
200            done = 1 ;
201         }
202 #endif
203 
204 #if 0
205         fprintf(stderr,"\n"
206                        "DC: redmask=%lx greenmask=%lx bluemask=%lx\n"
207                        "    redshift=%d greenshift=%d blueshift=%d\n"
208                        "    class=%d=%s depth=%d\n",
209                 dc->visual_redmask , dc->visual_greenmask , dc->visual_bluemask ,
210                 dc->visual_redshift , dc->visual_greenshift , dc->visual_blueshift ,
211                 dc->visual_class , x11_vcl[dc->visual_class] , dc->depth ) ;
212 #endif
213 
214      } else {                            /* should never occur! */
215         dc->visual_info  = NULL ;
216         dc->visual_class = PseudoColor ; /* we hope this still works [probably not] */
217      }
218    }
219 
220 #if 0
221  {  long reqmax ;
222     reqmax = XMaxRequestSize(dc->display) ;
223     printf("max X11 request size = %d\n",reqmax) ;
224  }
225 #endif
226 
227 #define DEPTH_BOT  4
228 #define DEPTH_TOP 32
229 
230    if( dc->depth < DEPTH_BOT || dc->depth > DEPTH_TOP ){
231       fprintf(stderr,"\n\n"
232                      " ** Your X11 display is set to %d bitplanes for image display.\n"
233                      " ** AFNI programs can only deal with between %d and %d bitplanes.\n"
234                      " ** You must have your superuser modify your system's setup.\a\n" ,
235               dc->depth , DEPTH_BOT , DEPTH_TOP ) ;
236       exit(1) ;
237    }
238 
239    dc->width   = WidthOfScreen(  dc->screen ) ;
240    dc->height  = HeightOfScreen( dc->screen ) ;
241 
242    if( dc->visual_class == TrueColor ){   /* 23 Feb 2011 */
243 #ifndef USE_256
244      if( ncol < 160 ) ncol = 160 ;
245 #else
246      if( ncol < 256 ) ncol = 256 ;
247 #endif
248    }
249 
250    dc->ncol_im = ncol ;
251    dc->gamma   = dc->gamma_init = gam  ;
252 
253    if( dc->visual_class == PseudoColor ){                  /* 22 Aug 1998 */
254 
255       if( newcmap ){                                       /* 14 Sep 1998 */
256          int ncold , cc ;
257          XColor xcold ;
258 
259          /* make a new colormap */
260 
261          dc->colormap = XCreateColormap( dc->display , RootWindowOfScreen(dc->screen) ,
262                                          dc->visual  , AllocNone ) ;
263 
264          /* allocate some colors from the old one (to reduce flashing) */
265 
266 #define NREUSE 9
267          ncold = dc->visual_info->colormap_size ;
268          if( ncold > NREUSE ) ncold = NREUSE ;
269          for( cc=0 ; cc < ncold ; cc++ ){
270             xcold.pixel = cc ;
271             XQueryColors( dc->display , dc->default_colormap , &xcold , 1 ) ;
272             XAllocColor( dc->display , dc->colormap , &xcold ) ;
273          }
274       }
275 
276       ok = XAllocColorCells( dc->display , dc->colormap ,
277                              True , plane_masks , nplmsk ,
278                              dc->pix_im , dc->ncol_im ) ;
279 
280       if( ! ok ){
281          fprintf(stderr,
282                  "\a\n** XAllocColorCells fails for %d colors\n",dc->ncol_im) ;
283          fprintf(stderr,
284                  "\n** try the -ncolor option to reduce # of colors\n");
285          exit(1) ;
286       }
287 
288       dc->pix_im_ready = 1 ;
289    } else if( dc->visual_class == TrueColor ){
290       dc->pix_im_ready = 0 ;
291    }
292 
293    DC_init_im_col( dc ) ;
294    DC_init_im_gry( dc ) ;
295 
296    dc->use_xcol_im = False ;
297    DC_set_image_colors( dc ) ;  /* 22 Aug 1998: replaces XStoreColors */
298 
299    /* set up overlay colors from list of names
300       (since the XImage routines use negative indices
301        to indicate overlays, the 0th overlay color is not used) */
302 
303    /* Dec 1997: put all overlay stuff into a single place */
304 
305    new_ovc = 0 ;
306    if( only_ovc == NULL ){ only_ovc = myXtNew(MCW_DCOV) ; new_ovc = 1 ; }
307    dc->ovc = only_ovc ;
308 
309    if( new_ovc ){
310       only_ovc->xcol_ov[0]  = dc->xgry_im[0] ;
311       only_ovc->pix_ov[0]   = dc->pix_im[0] ;
312       only_ovc->name_ov[0]  = XtNewString("none") ;
313       only_ovc->label_ov[0] = only_ovc->name_ov[0] ;
314       only_ovc->ncol_ov     = 1 ;
315 
316       only_ovc->bright_ov[0] = 0.0 ;  /* 20 Dec 1999 */
317 
318       dc->ovc->r_ov[0] = 0 ;          /* 04 Mar 2002 */
319       dc->ovc->g_ov[0] = 0 ;
320       dc->ovc->b_ov[0] = 0 ;
321    }
322 
323    for( ii=0 ; ii < novr ; ii++ ){
324 
325      ok = DC_add_overlay_color( dc , covr[ii] , lovr[ii] ) ;
326 
327      if( ok < 0 )
328         fprintf(stderr,
329           "\n*** can't get X11 colormap entry for overlay color %s" , lovr[ii] ) ;
330 #ifdef DISPLAY_DEBUG
331      else {
332         printf("\n*** overlay color %s has pixel %d at index %d" ,
333                dc->ovc->name_ov[ok] , (int)dc->ovc->pix_ov[ok] , ok ) ;
334         fflush(stdout) ;
335      }
336 #endif
337    }
338    OVC_mostest( dc->ovc ) ;
339 
340    /*-- May 1996: create new GC for use with text and graphics. --*/
341    /*-- Note that myGC is used only for text in afni_graph.c,  --*/
342    /*-- but is used for drawing graphics in some other places. --*/
343 
344    { XGCValues gcv;
345      int ifont ;
346      XFontStruct *mfinfo = NULL ;
347      char *xdef , dashlist[2] = {6,4} ;
348 
349      /* create the GC */
350 
351      gcv.function = GXcopy ;
352      dc->myGC     = XCreateGC( dc->display,
353                                RootWindowOfScreen(dc->screen) ,
354                                GCFunction , &gcv ) ;
355 
356      /** XSetFillRule( dc->display, dc->myGC, WindingRule ) ; **/
357 
358      /**** find some font to load into myGC ****/
359 
360      /* first try */
361 
362      xdef = XGetDefault(dc->display,"AFNI","gfont") ;  /* from ~/.Xdefaults */
363      if( xdef != NULL ){
364        mfinfo = XLoadQueryFont(dc->display,xdef) ;
365        /** if( mfinfo != NULL ) INFO_message("gfontX = %s",xdef) ; **/
366      }
367 
368      /* second try */
369 
370      if( mfinfo == NULL ){
371        xdef = getenv("AFNI_GRAPH_FONT") ;              /* from ~/.afnirc */
372        if( xdef != NULL ){
373          mfinfo = XLoadQueryFont(dc->display,xdef) ;
374          /** if( mfinfo != NULL ) INFO_message("gfontA = %s",xdef) ; **/
375        }
376      }
377 
378      /* third try: a list of fonts in display.h */
379 
380      if( mfinfo == NULL ){
381         for( ifont=0 ; tfont_hopefuls[ifont] != NULL ; ifont++ ){
382            mfinfo = XLoadQueryFont(dc->display, tfont_hopefuls[ifont]) ;
383            if( mfinfo != NULL ) break ; /* found one! */
384         }
385         /** if( mfinfo != NULL ) INFO_message("gfont[%d] = %s",ifont,tfont_hopefuls[ifont]) ; **/
386      }
387 
388      /* store font that we found above */
389 
390      if( mfinfo == NULL ){  /* This has never happened, to my knowledge */
391         ERROR_message("Cannot load any text fonts in display.c :(") ;
392      } else {
393         XSetFont( dc->display, dc->myGC, mfinfo->fid ); /* put font into myGC */
394      }
395      dc->myFontStruct = mfinfo ; /* save font info into AFNI display context (dc) */
396 
397      /*** set initial colors in myGC ***/
398 
399      XSetForeground(dc->display , dc->myGC , dc->ovc->pixov_darkest ) ;
400      XSetBackground(dc->display , dc->myGC , dc->ovc->pixov_brightest ) ;
401      XSetDashes(    dc->display , dc->myGC , 0 , dashlist , 2 ) ;
402    }
403 
404    dc->parent = dc->aux = NULL ;
405 
406 #ifdef DISPLAY_DEBUG
407    printf("\n") ;
408 #endif
409 
410 #if 0
411    reload_DC_colordef( dc ) ;  /* 11 Feb 1999 */
412 #else
413    dc->cdef = NULL ;
414 #endif
415 
416    if( first_dc == NULL ) first_dc = dc ;  /* 26 Jun 2003 */
417 
418    RETURN(dc) ;
419 }
420 
421 /*-----------------------------------------------------------------------
422    Set the image display to grayscale
423 -------------------------------------------------------------------------*/
424 
DC_palette_setgray(MCW_DC * dc)425 void DC_palette_setgray( MCW_DC *dc )
426 {
427    dc->use_xcol_im = False ;
428    DC_set_image_colors( dc ) ;  /* 22 Aug 1998 */
429    return ;
430 }
431 
432 /*-----------------------------------------------------------------------
433    Set the image display to colorscale
434 -------------------------------------------------------------------------*/
435 
DC_palette_setcolor(MCW_DC * dc)436 void DC_palette_setcolor( MCW_DC *dc )
437 {
438    dc->use_xcol_im = True ;
439    DC_set_image_colors( dc ) ;  /* 22 Aug 1998 */
440    return ;
441 }
442 
443 /*-----------------------------------------------------------------------
444    Restore the color and grayscale palettes to their defaults
445 -------------------------------------------------------------------------*/
446 
DC_palette_restore(MCW_DC * dc,double new_gamma)447 void DC_palette_restore( MCW_DC *dc , double new_gamma )
448 {
449    dc->gamma = (new_gamma > 0 ) ? new_gamma : dc->gamma_init ;
450    DC_init_im_col( dc ) ;
451    DC_init_im_gry( dc ) ;
452    DC_set_image_colors( dc ) ;  /* 22 Aug 1998 */
453 }
454 
455 /*-----------------------------------------------------------------------
456    Initialize the grayscale image palette.
457    Modified 22 Aug 1998 for TrueColor support.
458 -------------------------------------------------------------------------*/
459 
mypow(double x,double y)460 static double mypow( double x , double y )  /* replaces the math library pow */
461 {
462    double b ;
463    if( x <= 0.0 ) return 0.0 ;
464    if( y == 1.0 ) return x ;
465    b = log(x) ; b = exp( y*b ) ;
466    return b ;
467 }
468 
DC_init_im_gry(MCW_DC * dc)469 void DC_init_im_gry( MCW_DC *dc )
470 {
471    int i, k, m, nc ;
472    float a , gamm , b ;
473 
474    char *env ;                    /* 11 Apr 2000 */
475    float atop=255.0 , abot=33.0 ;
476 
477 #if 0
478    env = getenv("AFNI_GRAYSCALE_TOP") ;
479    if( env != NULL ){
480       float val = strtod(env,NULL) ;
481       if( val <= 255.0 && val >= 100.0 ) atop = val ;
482    }
483 #endif
484 
485    env = getenv("AFNI_GRAYSCALE_BOT") ;
486    if( env != NULL ){
487       float val = strtod(env,NULL) ;
488       if( val < atop && val >= 0.0 ) abot = val ;
489    }
490 
491    nc   = dc->ncol_im ;
492    gamm = dc->gamma ;
493    a    = (atop-abot) / nc ;
494 
495    for (i=0; i < nc ; i++) {
496       b = log( (a*i+abot)/255.0 ) ;   /* The code that used to be here */
497       b = exp( gamm * b ) ;           /* (using pow) was replaced due  */
498       k = (int)( 255.0 * b + 0.5 ) ;  /* to some bug in gcc on Linux.  */
499 
500       m = BYTE_TO_INTEN(k) ;
501 
502       dc->xint_im[i]       = m ;
503       dc->xgry_im[i].red   = m ;
504       dc->xgry_im[i].green = m ;
505       dc->xgry_im[i].blue  = m ;
506       dc->xgry_im[i].flags = DoRed|DoGreen|DoBlue;
507 
508       if( dc->visual_class == PseudoColor )        /* 22 Aug 1998 */
509          dc->xgry_im[i].pixel = dc->pix_im[i];
510    }
511 
512    return ;
513 }
514 
515 /*----------------------------------------------------------------------*/
516 /*! Return a color from the spectrum.  Input "an" is between 0 and 360.
517     Adapted from Ziad Saad. -- 01 Feb 2003 - RWCox.
518 ------------------------------------------------------------------------*/
519 
DC_spectrum_ZSS(double an,double gamm)520 rgbyte DC_spectrum_ZSS( double an , double gamm )
521 {
522    int r,g,b , m ;
523    rgbyte color ;
524 
525    if( gamm <= 0.0 ) gamm = 1.0 ;
526 
527    while( an <   0.0 ) an += 360.0 ;
528    while( an > 360.0 ) an -= 360.0 ;
529 
530    an = an / 90.0 ;
531 
532    if( an <= 1.0 ){
533      r = 255.*mypow(1.0-an,gamm)+0.5 ;
534      g = 255.*mypow(0.5*an,gamm)+0.5 ;
535      b = 255.*mypow(an    ,gamm)+0.5 ;
536    } else if( an <= 2.0 ){
537      r = 0 ;
538      g = 255.*mypow(0.5*an,gamm)+0.5 ;
539      b = 255.*mypow(2.0-an,gamm)+0.5 ;
540    } else if( an <= 3.0 ){
541      r = 255.*mypow(an-2.0,gamm)+0.5 ;
542      g = 255 ;
543      b = 0   ;
544    } else {
545      r = 255 ;
546      g = 255.*mypow(4.0-an,gamm)+0.5 ;
547      b = 0   ;
548    }
549 
550 #if 0
551    m = MAX(r,g) ; m = MAX(m,b) ;
552    if( m < 255 ){ float s=255.0/m; r *= s; g *= s; b *= s; }
553 #endif
554 
555    color.r = r ; color.g = g ; color.b = b ; return color ;
556 }
557 
558 /*----------------------------------------------------------------------*/
559 /*! Return a color from the spectrum.  Input "an" is between 0 and 360.
560     Adapted from Andrzej Jesmanowicz. -- 30 Jan 2003 - RWCox.
561 ------------------------------------------------------------------------*/
562 
DC_spectrum_AJJ(double an,double gamm)563 rgbyte DC_spectrum_AJJ( double an , double gamm )
564 {
565    int r,g,b , m ;
566    double ak,ab,s,c,sb,cb ;
567    rgbyte color ;
568 
569    if( gamm <= 0.0 ) gamm = 1.0 ;
570 
571 #if 0
572    ak = 105.; s  = 255.0-ak; c  = s /60.;     /* AJ's choices */
573    ab =  65.; sb = 255.0-ab; cb = sb/60.;
574 #else
575    ak =   5.; s  = 255.0-ak; c  = s /60.;     /* RWC's choices */
576    ab =   5.; sb = 255.0-ab; cb = sb/60.;
577 #endif
578 
579    while( an <   0.0 ) an += 360.0 ;
580    while( an > 360.0 ) an -= 360.0 ;
581 
582    if( an < 120. ){
583      r = 255.*mypow((ak + MIN(s,(120. - an)*c))/255., gamm) +.5;
584      g = 255.*mypow((ak + MIN(s,an*c))/255., gamm) +.5;
585      m = MAX(r,g) ;
586      b = 0;
587    } else if( an < 240. ){
588      r = 0;
589      g = 255.*mypow((ak + MIN(s ,(240. - an)*c ))/255., gamm) +.5;
590      b = 255.*mypow((ab + MIN(sb,(an - 120.)*cb))/255., gamm) +.5;
591      m = MAX(g,b) ;
592    } else {
593      r = 255.*mypow((ak + MIN(s,(an - 240.)*c ))/255., gamm) +.5;
594      g = 0;
595      b = 255.*mypow((ab + MIN(s,(360. - an)*cb))/255., gamm) +.5;
596      m = MAX(r,b) ;
597    }
598 
599 #if 0
600    if( m < 255 ){ s = 255.0/m ; r *= s ; g *= s ; b *= s ; }
601 #endif
602 
603    color.r = r ; color.g = g ; color.b = b ; return color ;
604 }
605 
606 /*----------------------------------------------------------------------------*/
607 #ifdef USE_TURBO   /* https://ai.googleblog.com/2019/08/turbo-improved-rainbow-colormap-for.html */
608 static byte const turbo_srgb_bytes[256][3] = {
609    {48,18,59},{50,21,67},{51,24,74},{52,27,81},{53,30,88},{54,33,95},{55,36,102},{56,39,109},{57,42,115},
610    {58,45,121},{59,47,128},{60,50,134},{61,53,139},{62,56,145},{63,59,151},{63,62,156},{64,64,162},{65,67,167},
611    {65,70,172},{66,73,177},{66,75,181},{67,78,186},{68,81,191},{68,84,195},{68,86,199},{69,89,203},{69,92,207},
612    {69,94,211},{70,97,214},{70,100,218},{70,102,221},{70,105,224},{70,107,227},{71,110,230},{71,113,233},{71,115,235},
613    {71,118,238},{71,120,240},{71,123,242},{70,125,244},{70,128,246},{70,130,248},{70,133,250},{70,135,251},{69,138,252},
614    {69,140,253},{68,143,254},{67,145,254},{66,148,255},{65,150,255},{64,153,255},{62,155,254},{61,158,254},{59,160,253},
615    {58,163,252},{56,165,251},{55,168,250},{53,171,248},{51,173,247},{49,175,245},{47,178,244},{46,180,242},{44,183,240},
616    {42,185,238},{40,188,235},{39,190,233},{37,192,231},{35,195,228},{34,197,226},{32,199,223},{31,201,221},{30,203,218},
617    {28,205,216},{27,208,213},{26,210,210},{26,212,208},{25,213,205},{24,215,202},{24,217,200},{24,219,197},{24,221,194},
618    {24,222,192},{24,224,189},{25,226,187},{25,227,185},{26,228,182},{28,230,180},{29,231,178},{31,233,175},{32,234,172},
619    {34,235,170},{37,236,167},{39,238,164},{42,239,161},{44,240,158},{47,241,155},{50,242,152},{53,243,148},{56,244,145},
620    {60,245,142},{63,246,138},{67,247,135},{70,248,132},{74,248,128},{78,249,125},{82,250,122},{85,250,118},{89,251,115},
621    {93,252,111},{97,252,108},{101,253,105},{105,253,102},{109,254,98},{113,254,95},{117,254,92},{121,254,89},{125,255,86},
622    {128,255,83},{132,255,81},{136,255,78},{139,255,75},{143,255,73},{146,255,71},{150,254,68},{153,254,66},{156,254,64},
623    {159,253,63},{161,253,61},{164,252,60},{167,252,58},{169,251,57},{172,251,56},{175,250,55},{177,249,54},{180,248,54},
624    {183,247,53},{185,246,53},{188,245,52},{190,244,52},{193,243,52},{195,241,52},{198,240,52},{200,239,52},{203,237,52},
625    {205,236,52},{208,234,52},{210,233,53},{212,231,53},{215,229,53},{217,228,54},{219,226,54},{221,224,55},{223,223,55},
626    {225,221,55},{227,219,56},{229,217,56},{231,215,57},{233,213,57},{235,211,57},{236,209,58},{238,207,58},{239,205,58},
627    {241,203,58},{242,201,58},{244,199,58},{245,197,58},{246,195,58},{247,193,58},{248,190,57},{249,188,57},{250,186,57},
628    {251,184,56},{251,182,55},{252,179,54},{252,177,54},{253,174,53},{253,172,52},{254,169,51},{254,167,50},{254,164,49},
629    {254,161,48},{254,158,47},{254,155,45},{254,153,44},{254,150,43},{254,147,42},{254,144,41},{253,141,39},{253,138,38},
630    {252,135,37},{252,132,35},{251,129,34},{251,126,33},{250,123,31},{249,120,30},{249,117,29},{248,114,28},{247,111,26},
631    {246,108,25},{245,105,24},{244,102,23},{243,99,21},{242,96,20},{241,93,19},{240,91,18},{239,88,17},{237,85,16},
632    {236,83,15},{235,80,14},{234,78,13},{232,75,12},{231,73,12},{229,71,11},{228,69,10},{226,67,10},{225,65,9},
633    {223,63,8},{221,61,8},{220,59,7},{218,57,7},{216,55,6},{214,53,6},{212,51,5},{210,49,5},{208,47,5},
634    {206,45,4},{204,43,4},{202,42,4},{200,40,3},{197,38,3},{195,37,3},{193,35,2},{190,33,2},{188,32,2},
635    {185,30,2},{183,29,2},{180,27,1},{178,26,1},{175,24,1},{172,23,1},{169,22,1},{167,20,1},{164,19,1},
636    {161,18,1},{158,16,1},{155,15,1},{152,14,1},{149,13,1},{146,11,1},{142,10,1},{139,9,2},{136,8,2},
637    {133,7,2},{129,6,2},{126,5,2},{122,4,3}
638 };
639 #endif
640 /*----------------------------------------------------------------------------*/
641 
642 /*-----------------------------------------------------------------------
643    Initialize the color image palette.
644    Modified 22 Aug 1998 for TrueColor support.
645 -------------------------------------------------------------------------*/
646 
DC_init_im_col(MCW_DC * dc)647 void DC_init_im_col( MCW_DC *dc )
648 {
649    int i, r=0, g=0, b=0, nc ;
650    double gamm ;
651 
652 #ifdef USE_256
653    int kt ; float tfac ;
654 #else
655    double da, an, c, s, sb, cb, ak, ab , a1,a2 ;
656 #endif
657 
658 #ifdef USE_PBARDEFS          /* 24 Oct 2019 */
659    static int mypbar = -1 ;
660    static float *mypbarf = NULL ;
661 #endif
662 
663 #ifdef USE_PBARDEFS
664    mypbar = -1 ; mypbarf = NULL ; /* reset the color pbar to use */
665 #endif
666    if( dc == NULL ) return ;
667 
668    nc   = dc->ncol_im ;
669    gamm = dc->gamma ;
670 
671 #ifdef USE_256 /* setup for getting colors directly from a table */
672    tfac = 255.4f / (float)(nc-1) ;
673 #else  /* setup for calculating AJJ's old color circle (from FD) */
674    a1 = 0.0   ;
675    a2 = AFNI_numenv("AFNI_IMAGE_COLORANGLE") ;  /* 08 Nov 2011 */
676    if( a2 < 90.0 || a2 > 360.0 ) a2 = 240.0 ;   /* set range   */
677 
678    ak = 105.; s  = 150.; c  = s/60.;
679    ab = 65.;  sb = 190.; cb = s/60.;
680 
681    an = a1;   da = (a2 - a1)/nc ; an = an-da+360.;
682 #endif
683 
684    for( i=0 ; i < nc ; i++ ){
685 
686 #ifdef USE_TURBO        /* directly use Google Turbo */
687      kt = (int)rint(tfac*i) ; if( kt < 0 ) kt=0; else if( kt > 255 ) kt=255 ;
688      r  = turbo_srgb_bytes[kt][0] ;
689      g  = turbo_srgb_bytes[kt][1] ;
690      b  = turbo_srgb_bytes[kt][2] ;
691 #elif defined(USE_PBARDEFS)          /* 24 Oct 2019 */
692      if( mypbar < 0 ){
693        char *eee = getenv("AFNI_IMAGE_COLORSCALE") ; /* figure out which */
694        if( eee == NULL || *eee == '\0' ){           /* colorscale to use */
695          mypbar = NPBARF-1 ;
696        } else {
697          int qq ;
698          for( qq=0 ; qq < NPBARF ; qq++ ){
699            if( strcasecmp(eee,pbarfname[qq]) == 0 ) break ;
700          }
701          if( qq == NPBARF ) qq-- ;
702          mypbar = qq ;
703        }
704        mypbarf = pbarfar[mypbar] ;
705      }
706      kt = (int)rint(tfac*i) ; if( kt < 0 ) kt=0; else if( kt > 255 ) kt=255 ;
707      r  = (int)(255.4f*mypow(mypbarf[3*kt+0],gamm/1.555)) ;
708      g  = (int)(255.4f*mypow(mypbarf[3*kt+1],gamm/1.555)) ;
709      b  = (int)(255.4f*mypow(mypbarf[3*kt+2],gamm/1.555)) ;
710 #else  /* the olden AJJ way, from program FD */
711      an += da; an = fmod(an,360.);
712 
713      if((an >= 0) && (an < 120.)) {
714           r = 255.*mypow((ak + MIN(s,(120. - an)*c))/255., gamm) +.5;
715           g = 255.*mypow((ak + MIN(s,an*c))/255., gamm) +.5;
716           b = 0;
717      } else if((an >= 120.) && (an < 240.)) {
718           r = 0;
719           g = 255.*mypow((ak + MIN(s ,(240. - an)*c))/255., gamm) +.5;
720           b = 255.*mypow((ab + MIN(sb,(an - 120.)*cb))/255., gamm) +.5;
721      } else if(an >= 240.) {
722           r = 255.*mypow((ak + MIN(s,(an - 240.)*c))/255., gamm) +.5;
723           g = 0;
724           b = 255.*mypow((ak + MIN(s,(360. - an)*c))/255., gamm) +.5;
725      }
726 #endif
727 
728      dc->xcol_im[i].red   = BYTE_TO_INTEN(r) ;
729      dc->xcol_im[i].green = BYTE_TO_INTEN(g) ;
730      dc->xcol_im[i].blue  = BYTE_TO_INTEN(b) ;
731      dc->xcol_im[i].flags = DoRed|DoGreen|DoBlue;
732 
733      if( dc->visual_class == PseudoColor )        /* 22 Aug 1998 */
734         dc->xcol_im[i].pixel = dc->pix_im[i];
735    }
736    return ;
737 }
738 
739 #if 0 /*******************************************************************/
740 /* --------------------------------------------------------------------------
741    Given an triple of bytes (0..255), make a color and return its pixel value
742 -----------------------------------------------------------------------------*/
743 
744 Pixel RGB_byte_to_color( MCW_DC *dc , int r , int g , int b )
745 {
746    XColor  any_col;
747 
748    any_col.red   = BYTE_TO_INTEN(r);
749    any_col.green = BYTE_TO_INTEN(g);
750    any_col.blue  = BYTE_TO_INTEN(b);
751    any_col.flags = DoRed | DoGreen | DoBlue;
752    XAllocColor( dc->display , dc->colormap , &any_col );
753    return any_col.pixel ;
754 }
755 
756 /*--------------------------------------------------------------------------
757   Given a color named by a string, allocate it and return its pixel value
758 ----------------------------------------------------------------------------*/
759 
760 Pixel Name_to_color( MCW_DC *dc , char * name )
761 {
762    XColor cell , exact ;
763    int ok ;
764 
765    ok = XAllocNamedColor( dc->display , dc->colormap , name , &cell , &exact ) ;
766 
767    if( ok ) return cell.pixel ;
768    else     return BlackPixelOfScreen( dc->screen ) ;
769 }
770 #endif /********************************************************************/
771 
772 /*--------------------------------------------------------------------------
773    Given a color name, allocate it, put it into the DC overlay table,
774    and return its index (negative if an error occurred)
775    Dec 1997: modified to use read-write color cells,
776              and recycle them if the same label is passed in.
777    22 Aug 1998: modified for TrueColor support
778 ----------------------------------------------------------------------------*/
779 
DC_add_overlay_color(MCW_DC * dc,char * name,char * label)780 int DC_add_overlay_color( MCW_DC *dc , char *name , char *label )
781 {
782    int ii , ok , newcol ;
783    Pixel newpix ;
784    XColor cell ;
785 
786 ENTRY("DC_add_overlay_color") ;
787 
788    if( name == NULL || strlen(name) == 0 ) RETURN(-1) ;  /* error */
789    if( label == NULL ) label = name ;
790 
791 if(PRINT_TRACING){
792  char str[256]; sprintf(str,"color=%s label=%s",name,label); STATUS(str);
793 }
794 
795    /** see if label is already in the table **/
796 
797    for( ii=1 ; ii < dc->ovc->ncol_ov ; ii++ )
798       if( strcmp(label,dc->ovc->label_ov[ii]) == 0 ) break ;
799 
800    newcol = (ii == dc->ovc->ncol_ov) ;     /** need a new color cell? **/
801    if( ii == dc->ovc->ncol_ov ){           /** Yes **/
802       unsigned int nplmsk = 0 ;
803       unsigned long plane_masks[1] ;
804 
805 STATUS("creating new color table entry") ;
806 
807       if( ii >= MAX_COLORS ) RETURN(-1) ;   /* too many overlay colors! */
808 
809       if( dc->visual_class == PseudoColor ){  /* 22 Aug 1998 */
810          ok = XAllocColorCells( dc->display , dc->colormap ,
811                                 True , plane_masks , nplmsk , &newpix , 1 ) ;
812          if( !ok ) RETURN(-1) ;                /* couldn't get a new cell */
813          cell.pixel = newpix ;
814       }
815 
816    } else {                                /** Reusing an old cell **/
817 
818       if( strcmp(name,dc->ovc->name_ov[ii]) == 0 ) RETURN(ii) ; /* no change! */
819 
820 STATUS("re-defining old color table entry") ;
821 
822       if( dc->visual_class == PseudoColor )  /* 22 Aug 1998 */
823          cell.pixel = dc->ovc->pix_ov[ii] ;
824       else if( dc->visual_class == TrueColor )
825          XFreeColors( dc->display, dc->colormap, dc->ovc->pix_ov+ii, 1, 0 ) ;
826    }
827 
828    ok = XParseColor( dc->display , dc->colormap , name, &cell ) ;
829    if( !ok ) RETURN(-1) ;
830 
831    if( newcol ){                      /** made a new cell **/
832       dc->ovc->ncol_ov++ ;
833    } else {                           /** free old cell stuff **/
834       myXtFree( dc->ovc->name_ov[ii] ) ;
835       myXtFree( dc->ovc->label_ov[ii] ) ;
836    }
837 
838    if( dc->visual_class == PseudoColor )                  /* 22 Aug 1998 */
839       XStoreColor( dc->display , dc->colormap , &cell ) ;
840    else if( dc->visual_class == TrueColor )
841       XAllocColor( dc->display , dc->colormap , &cell ) ;
842 
843 if(PRINT_TRACING){
844  char str[256]; sprintf(str,"overlay color index=%d",ii); STATUS(str);
845 }
846 
847    dc->ovc->xcol_ov[ii]  = cell ;                      /* save cell info */
848    dc->ovc->pix_ov[ii]   = cell.pixel ;
849    dc->ovc->name_ov[ii]  = XtNewString(name) ;
850    dc->ovc->label_ov[ii] = XtNewString(label) ;
851 
852    dc->ovc->r_ov[ii] = INTEN_TO_BYTE(cell.red) ;       /* 06 Mar 2001 */
853    dc->ovc->g_ov[ii] = INTEN_TO_BYTE(cell.green) ;
854    dc->ovc->b_ov[ii] = INTEN_TO_BYTE(cell.blue) ;
855 
856    if( dc->visual_class == PseudoColor ) /* 11 Feb 1999: */
857      FREE_DC_colordef(dc->cdef) ;        /* will need to be recomputed */
858 
859    dc->ovc->bright_ov[ii] = BRIGHTNESS( DCOV_REDBYTE(dc,ii) ,       /* 20 Dec 1999 */
860                                         DCOV_GREENBYTE(dc,ii) ,
861                                         DCOV_BLUEBYTE(dc,ii)   ) ;
862    RETURN(ii) ;
863 }
864 
865 /*-------------------------------------------------------------------------*/
866 
DC_find_overlay_color(MCW_DC * dc,char * label)867 int DC_find_overlay_color( MCW_DC *dc , char *label )
868 {
869    int ii ;
870    if( dc == NULL || label == NULL ) return -1 ;
871    for( ii=0 ; ii < dc->ovc->ncol_ov ; ii++ )
872      if( strcasecmp(label,dc->ovc->label_ov[ii]) == 0 ) return ii ;
873    return -1 ;
874 }
875 
876 /*-------------------------------------------------------------------------*/
877 
DC_find_closest_overlay_color(MCW_DC * dc,char * cname)878 int DC_find_closest_overlay_color( MCW_DC *dc , char *cname )
879 {
880    float rr,gg,bb ; int b_rr,b_gg,b_bb ;
881    int ii , jj;
882 
883    if( dc == NULL || cname == NULL || *cname == '\0' ) return -1 ;
884 
885 #if 0
886    if( strcmp(cname,"none") == 0 ) return -1 ;
887 #endif
888 
889    ii = DC_find_overlay_color( dc , cname ) ;
890    if( ii >= 0 ) return ii ;
891 
892    ii = DC_parse_color( dc, cname, &rr,&gg,&bb ) ;
893    if( ii ) return -1 ;
894 
895    b_rr = (int)(255.9*rr) ;
896    b_gg = (int)(255.9*gg) ;
897    b_bb = (int)(255.9*bb) ;
898 
899    jj = 0 ; rr = 9999999.9 ;
900    for( ii=0 ; ii < dc->ovc->ncol_ov ; ii++ ){
901      gg = abs(b_rr-(int)dc->ovc->r_ov[ii])
902          +abs(b_gg-(int)dc->ovc->g_ov[ii])
903          +abs(b_bb-(int)dc->ovc->b_ov[ii]) ;
904      if( gg < rr ){ jj = ii ; rr = gg ; }
905    }
906 
907    return jj ;
908 }
909 
910 /*-------------------------------------------------------------------------
911   load the tmp? arrays (alas, GLOBAL data, a sin against God and Man)
912   from an array of colors
913 --------------------------------------------------------------------------*/
914 
915 static unsigned short tmp1[MAX_COLORS] , tmp2[MAX_COLORS] , tmp3[MAX_COLORS] ;
916 static int            tmpi[MAX_COLORS] ;
917 
load_tmp_colors(int nc,XColor * ccc)918 void load_tmp_colors( int nc , XColor *ccc )
919 {
920    register int i ;
921 
922    for( i=0 ; i < nc ; i++ ){
923       tmp1[i] = ccc[i].red ;
924       tmp2[i] = ccc[i].green ;
925       tmp3[i] = ccc[i].blue ;
926    }
927    return ;
928 }
929 
930 /*-------------------------------------------------------------------------
931   rotate active palette k steps
932 -------------------------------------------------------------------------*/
933 
DC_palette_rotate(MCW_DC * dc,int kk)934 void DC_palette_rotate( MCW_DC *dc , int kk )
935 {
936    register int i , j , nc , k ;
937    XColor * xc ;
938 
939    nc = dc->ncol_im ;
940 
941    if( dc->use_xcol_im ){
942       xc = & ( dc->xcol_im[0] ) ;  /* choose active palette */
943       k  = -kk ;                   /* direction of rotation */
944    } else {
945       xc = & ( dc->xgry_im[0] ) ;
946       k  = -kk ;
947    }
948 
949    load_tmp_colors( nc , xc ) ;    /* store RGB values in tmp? */
950 
951    for( i=0 ; i < nc ; i++ ){
952       j = (i+nc+k) % nc ;
953 
954       xc[i].red   = tmp1[j] ;
955       xc[i].green = tmp2[j] ;
956       xc[i].blue  = tmp3[j] ;
957    }
958 
959    if( ! dc->use_xcol_im ){  /* rotate xint_im as well for graymap */
960       for( i=0 ; i < nc ; i++ ) tmpi[i] = dc->xint_im[i] ;
961       for( i=0 ; i < nc ; i++ ) dc->xint_im[i] = tmpi[(i+nc+k)%nc] ;
962    }
963 
964    DC_set_image_colors( dc ) ;  /* 22 Aug 1998 */
965    return ;
966 }
967 
968 /*------------------------------------------------------------------------*/
969 
DC_palette_swap(MCW_DC * dc)970 void DC_palette_swap( MCW_DC *dc )
971 {
972    register int i, k , nc ;
973    XColor * xc ;
974 
975    nc = dc->ncol_im ;
976    k  = nc - 1 ;
977 
978    if( dc->use_xcol_im ){
979       xc = & ( dc->xcol_im[0] ) ;
980    } else {
981       xc = & ( dc->xgry_im[0] ) ;
982    }
983 
984    load_tmp_colors( nc , xc ) ;
985 
986    for(i=0; i < nc ; i++) {
987      xc[i].red   = tmp1[k-i];
988      xc[i].green = tmp2[k-i];
989      xc[i].blue  = tmp3[k-i];
990    }
991 
992    if( ! dc->use_xcol_im ){  /* swap xint_im as well for graymap */
993       for( i=0 ; i < nc ; i++ ) tmpi[i] = dc->xint_im[i] ;
994       for( i=0 ; i < nc ; i++ ) dc->xint_im[i] = tmpi[k-i] ;
995    }
996 
997    DC_set_image_colors( dc ) ;  /* 22 Aug 1998 */
998    return ;
999 }
1000 
1001 /*-----------------------------------------------------------------------*/
1002 
DC_palette_bright(MCW_DC * dc,int dd)1003 void DC_palette_bright(  MCW_DC *dc , int dd )
1004 {
1005    if( dc->use_xcol_im ) DC_color_bright( dc ,    dd ) ;
1006    else                  DC_gray_change(  dc , -2*dd ) ;
1007    return;
1008 }
1009 
1010 /*-----------------------------------------------------------------------*/
1011 
DC_color_bright(MCW_DC * dc,int dlev)1012 void DC_color_bright( MCW_DC *dc , int dlev )
1013 {
1014    register int i ;
1015    double c ;
1016    int      nc = dc->ncol_im ;
1017    XColor * xc = dc->xcol_im ;
1018 
1019    c = 1.0 - 0.005 * (double) dlev ;
1020 
1021    for( i=0 ; i < nc ; i++ ){
1022       xc[i].red   = CLIP_INTEN( c * xc[i].red   ) ;
1023       xc[i].green = CLIP_INTEN( c * xc[i].green ) ;
1024       xc[i].blue  = CLIP_INTEN( c * xc[i].blue  ) ;
1025    }
1026    DC_set_image_colors( dc ) ;  /* 22 Aug 1998 */
1027    return ;
1028 }
1029 
1030 /*------------------------------------------------------------------------*/
1031 
DC_gray_change(MCW_DC * dc,int dlev)1032 void DC_gray_change( MCW_DC *dc , int dlev )
1033 {
1034    register int i, k, delta ;
1035    int      nc = dc->ncol_im ;
1036    XColor * xc = dc->xgry_im ;
1037    int    * in = dc->xint_im ;
1038 
1039    if( dc->use_xcol_im ) return ;
1040 
1041    delta = dlev * abs( (in[nc-1] - in[0]) / nc ) ;
1042 
1043    for( i=0 ; i < nc ; i++ ){
1044       k = in[i] += delta ;
1045       xc[i].red = xc[i].green = xc[i].blue = CLIP_INTEN(k) ;
1046    }
1047    DC_set_image_colors( dc ) ;  /* 22 Aug 1998 */
1048    return ;
1049 }
1050 
1051 /*------------------------------------------------------------------------*/
1052 
DC_palette_squeeze(MCW_DC * dc,int dd)1053 void DC_palette_squeeze( MCW_DC *dc , int dd )
1054 {
1055    if( dc->use_xcol_im ) DC_color_squeeze( dc ,    dd ) ;
1056    else                  DC_gray_contrast( dc , -2*dd ) ;
1057    return;
1058 }
1059 
1060 /*------------------------------------------------------------------------*/
1061 
DC_color_squeeze(MCW_DC * dc,int dlev)1062 void DC_color_squeeze( MCW_DC *dc , int dlev )
1063 {
1064    return ;  /* not implemented */
1065 }
1066 
1067 /*------------------------------------------------------------------------*/
1068 
DC_gray_contrast(MCW_DC * dc,int dlev)1069 void DC_gray_contrast( MCW_DC *dc , int dlev )
1070 {
1071    register int i, k, delta ;
1072    int      nc = dc->ncol_im ;
1073    XColor * xc = dc->xgry_im ;
1074    int    * in = dc->xint_im ;
1075 
1076    if( dc->use_xcol_im ) return ;
1077 
1078    delta = dlev * (abs(in[nc-1] - in[0]) >> 6) / nc ;
1079    if( delta == 0 ) delta = dlev ;
1080 
1081    for( i=0 ; i < nc ; i++ ){
1082       k = in[i] += i * delta ;
1083       xc[i].red = xc[i].green = xc[i].blue = CLIP_INTEN(k) ;
1084    }
1085    DC_set_image_colors( dc ) ;  /* 22 Aug 1998 */
1086    return ;
1087 }
1088 
1089 /*------------------------------------------------------------------------*/
1090 
DC_gray_conbrio(MCW_DC * dc,int dlev)1091 void DC_gray_conbrio( MCW_DC *dc , int dlev )  /* 23 Oct 2003 */
1092 {
1093    register int i, k, bdelta,cdelta ;
1094    int      nc = dc->ncol_im ;
1095    XColor * xc = dc->xgry_im ;
1096    int    * in = dc->xint_im ;
1097 
1098    if( dc->use_xcol_im ) return ;
1099 
1100    bdelta = dlev *  abs(in[nc-1] - in[0])       / nc ;
1101    cdelta = dlev * (abs(in[nc-1] - in[0]) >> 6) / nc ;
1102    if( cdelta == 0 ) cdelta = dlev ;
1103 
1104    for( i=0 ; i < nc ; i++ ){
1105      k = in[i] += i * cdelta - bdelta ;
1106      xc[i].red = xc[i].green = xc[i].blue = CLIP_INTEN(k) ;
1107    }
1108    DC_set_image_colors( dc ) ;
1109    return ;
1110 }
1111 
1112 /*---------------------------------------------------------------------------*/
1113 
DC_char_height(MCW_DC * dc,char ccc)1114 int DC_char_height( MCW_DC *dc , char ccc )  /* 18 Apr 2011 */
1115 {
1116    int dret , fasc , fdes ; XCharStruct cst ; char str[2] ;
1117 
1118    if( dc == NULL || ccc == '\0' ) return 0 ;
1119    str[0] = ccc ; str[1] = '\0' ;
1120 
1121    cst.ascent = cst.descent = 0 ;
1122    XTextExtents( dc->myFontStruct , str , 1 ,
1123                  &dret , &fasc , &fdes , &cst ) ;
1124 
1125    return (int)(cst.ascent + cst.descent) ;
1126 }
1127 
1128 /*---------------------------------------------------------------------------*/
1129 
DC_char_adscent(MCW_DC * dc,char ccc)1130 int_pair DC_char_adscent( MCW_DC *dc , char ccc )  /* 18 Apr 2011 */
1131 {
1132    int dret , fasc , fdes ; XCharStruct cst ; char str[2] ; int_pair ad={0,0} ;
1133 
1134    if( dc == NULL || ccc == '\0' ) return ad ;
1135    str[0] = ccc ; str[1] = '\0' ;
1136 
1137    cst.ascent = cst.descent = 0 ;
1138    XTextExtents( dc->myFontStruct , str , 1 ,
1139                  &dret , &fasc , &fdes , &cst ) ;
1140 
1141    ad.i = (int)cst.ascent ; ad.j = (int)cst.descent ; return ad ;
1142 }
1143 
1144 /*---------------------------------------------------------------------------*/
1145 
DC_char_width(MCW_DC * dc,char ccc)1146 int DC_char_width( MCW_DC *dc , char ccc )  /* 18 Apr 2011 */
1147 {
1148    int dret , fasc , fdes ; XCharStruct cst ; char str[2] ;
1149 
1150    if( dc == NULL || ccc == '\0' ) return 0 ;
1151    str[0] = ccc ; str[1] = '\0' ;
1152 
1153    cst.width = 0 ;
1154    XTextExtents( dc->myFontStruct , str , 1 ,
1155                  &dret , &fasc , &fdes , &cst ) ;
1156 
1157    return (int)(cst.width) ;
1158 }
1159 
1160 /*-------------------------------------------------------------------*/
1161 
MCW_check_iconsize(int width,int height,MCW_DC * dc)1162 RwcBoolean MCW_check_iconsize( int width , int height , MCW_DC *dc )
1163 {
1164    int ii ;
1165    RwcBoolean good ;
1166    int nsl = 0 ;
1167    XIconSize * xsl = NULL ;
1168 
1169    /** elementary checks **/
1170 
1171    if( width < 1 || height < 1 ) return False ;
1172 
1173    XGetIconSizes( dc->display , RootWindowOfScreen(dc->screen) , &xsl , &nsl ) ;
1174 
1175    if( xsl == NULL || nsl < 1 )  return True ;
1176 
1177    good = False ;
1178 
1179    for( ii=0 ; ii < nsl ; ii++ ){
1180 
1181       if( width  >= xsl[ii].min_width  && width  <= xsl[ii].max_width  &&
1182           height >= xsl[ii].min_height && height <= xsl[ii].max_height &&
1183 
1184           (width  - xsl[ii].min_width ) % xsl[ii].width_inc  == 0 &&
1185           (height - xsl[ii].min_height) % xsl[ii].height_inc == 0   ) { good = True ; break ; }
1186    }
1187 
1188    XFree(xsl) ;
1189    return good ;
1190 }
1191 
1192 /*---------------------------------------------------------------------------
1193    Given a pixel index, return a pointer to its color (not very efficiently).
1194    11 Feb 1999: if use_cmap != 0, use the colormap instead of
1195                 the internal dc color arrays
1196 -----------------------------------------------------------------------------*/
1197 
DCpix_to_XColor(MCW_DC * dc,Pixel pp,int use_cmap)1198 XColor * DCpix_to_XColor( MCW_DC *dc , Pixel pp , int use_cmap )
1199 {
1200    XColor * ulc , * ovc ;
1201    int ii ;
1202 
1203    if( use_cmap ){              /* 11 Feb 1999 */
1204       static XColor xc ;
1205       byte rr,gg,bb ;
1206 
1207       DC_pixel_to_rgb( dc , pp , &rr,&gg,&bb ) ;
1208       xc.red   = BYTE_TO_INTEN(rr) ;
1209       xc.green = BYTE_TO_INTEN(gg) ;
1210       xc.blue  = BYTE_TO_INTEN(bb) ;
1211       return &xc ;
1212    }
1213 
1214    ulc = (dc->use_xcol_im) ? dc->xcol_im : dc->xgry_im ;
1215    ovc = dc->ovc->xcol_ov ;
1216 
1217    for( ii=0 ; ii < dc->ncol_im ; ii++ )
1218       if( pp == dc->pix_im[ii] ) return (ulc+ii) ;
1219 
1220    for( ii=0 ; ii < dc->ovc->ncol_ov ; ii++ )
1221       if( pp == dc->ovc->pix_ov[ii] ) return (ovc+ii) ;
1222 
1223    return ulc ;  /* not found, but must return something */
1224 }
1225 
1226 /*-------------------------------------------------------------------------*/
1227 
DC_fg_color(MCW_DC * dc,int nov)1228 void DC_fg_color( MCW_DC *dc , int nov )
1229 {
1230    XSetForeground( dc->display , dc->myGC , dc->ovc->pix_ov[nov] ) ;
1231    return ;
1232 }
1233 
DC_bg_color(MCW_DC * dc,int nov)1234 void DC_bg_color( MCW_DC *dc , int nov )
1235 {
1236    XSetBackground( dc->display , dc->myGC , dc->ovc->pix_ov[nov] ) ;
1237    return ;
1238 }
1239 
DC_fg_colorpix(MCW_DC * dc,Pixel pix)1240 void DC_fg_colorpix( MCW_DC *dc , Pixel pix )
1241 {
1242    XSetForeground( dc->display , dc->myGC , pix ) ;
1243    return ;
1244 }
1245 
DC_fg_colortext(MCW_DC * dc,char * cname)1246 void DC_fg_colortext( MCW_DC *dc , char * cname )
1247 {
1248    XColor any_col , rgb_col ;
1249 
1250    if( ! XAllocNamedColor( dc->display , dc->colormap ,
1251                            cname , &any_col, &rgb_col ) ){
1252 
1253       fprintf(stderr,"\n** XAllocNamedColor problem: %s **\n",cname ) ;
1254    } else {
1255       XSetForeground( dc->display , dc->myGC , any_col.pixel ) ;
1256    }
1257    return ;
1258 }
1259 
DC_linewidth(MCW_DC * dc,int lw)1260 void DC_linewidth( MCW_DC *dc , int lw )
1261 {
1262    XGCValues gcv ;
1263 
1264    if( lw >= 0 ){
1265       gcv.line_width = lw ;
1266       gcv.join_style = JoinBevel ;
1267       XChangeGC( dc->display , dc->myGC , GCLineWidth | GCJoinStyle , &gcv ) ;
1268    }
1269    return ;
1270 }
1271 
DC_linestyle(MCW_DC * dc,int lw)1272 void DC_linestyle( MCW_DC *dc , int lw )
1273 {
1274    XGCValues gcv ;
1275    gcv.line_style = lw ;
1276    XChangeGC( dc->display , dc->myGC , GCLineStyle , &gcv ) ;
1277    return ;
1278 }
1279 
1280 /*-------------------------------------------------------------------------
1281  May 1996: save the indices of the darkest and brightest overlays
1282  Dec 1997: moved into a separate routine
1283 ---------------------------------------------------------------------------*/
1284 
OVC_mostest(MCW_DCOV * ovc)1285 void OVC_mostest( MCW_DCOV * ovc )
1286 {
1287    float bright_inten , dark_inten , red_inten , green_inten , blue_inten , inten ;
1288    int   bright_ii    , dark_ii    , red_ii    , green_ii    , blue_ii ;
1289    float yellow_inten ;
1290    int   yellow_ii    ;
1291    int   ii ;
1292 
1293    if( ovc == NULL || ovc->ncol_ov < 2 ) return ;
1294 
1295    bright_inten = dark_inten = XCOL_BRIGHTNESS( ovc->xcol_ov[1] ) ;
1296    bright_ii    = dark_ii    = 1 ;
1297 
1298    red_inten   = XCOL_REDNESS  ( ovc->xcol_ov[1] ) ;  /* June 1997 */
1299    green_inten = XCOL_GREENNESS( ovc->xcol_ov[1] ) ;
1300    blue_inten  = XCOL_BLUENESS ( ovc->xcol_ov[1] ) ;
1301    red_ii = green_ii = blue_ii = 1 ;
1302 
1303    yellow_ii = 1 ;
1304    yellow_inten = XCOL_YELLOWNESS( ovc->xcol_ov[1] ) ;  /* 28 Jan 2004 */
1305 
1306    for( ii=2 ; ii < ovc->ncol_ov ; ii++ ){
1307       inten = XCOL_BRIGHTNESS( ovc->xcol_ov[ii] ) ;
1308       if( inten > bright_inten ){
1309          bright_inten = inten ; bright_ii = ii ;
1310       } else if( inten < dark_inten ){
1311          dark_inten = inten ; dark_ii = ii ;
1312       }
1313 
1314       inten = XCOL_REDNESS( ovc->xcol_ov[ii] ) ;
1315       if( inten > red_inten ){
1316          red_inten = inten ; red_ii = ii ;
1317       }
1318 
1319       inten = XCOL_GREENNESS( ovc->xcol_ov[ii] ) ;
1320       if( inten > green_inten ){
1321          green_inten = inten ; green_ii = ii ;
1322       }
1323 
1324       inten = XCOL_BLUENESS( ovc->xcol_ov[ii] ) ;
1325       if( inten > blue_inten ){
1326          blue_inten = inten ; blue_ii = ii ;
1327       }
1328 
1329       inten = XCOL_YELLOWNESS( ovc->xcol_ov[ii] ) ;
1330       if( inten > yellow_inten ){
1331          yellow_inten = inten ; yellow_ii = ii ;
1332       }
1333    }
1334    ovc->ov_brightest = bright_ii ; ovc->pixov_brightest = ovc->pix_ov[bright_ii] ;
1335    ovc->ov_darkest   = dark_ii   ; ovc->pixov_darkest   = ovc->pix_ov[dark_ii] ;
1336    ovc->ov_reddest   = red_ii    ; ovc->pixov_reddest   = ovc->pix_ov[red_ii] ;
1337    ovc->ov_greenest  = green_ii  ; ovc->pixov_greenest  = ovc->pix_ov[green_ii] ;
1338    ovc->ov_bluest    = blue_ii   ; ovc->pixov_bluest    = ovc->pix_ov[blue_ii] ;
1339    ovc->ov_yellowest = yellow_ii ; ovc->pixov_yellowest = ovc->pix_ov[yellow_ii] ;
1340 }
1341 
1342 /*-------------------------------------------------------------------------------
1343    Store the colors needed for image display,
1344    based on the value of dc->use_xcol_im (colors for image, or grayscale?).
1345    This replaces the use of XStoreColors directly in the code above.
1346    22 Aug 1998 -- RWCox.
1347 ---------------------------------------------------------------------------------*/
1348 
DC_set_image_colors(MCW_DC * dc)1349 void DC_set_image_colors( MCW_DC *dc )
1350 {
1351    int ii , nc ;
1352    XColor * xc ;
1353 
1354    nc = dc->ncol_im ;
1355    xc = (dc->use_xcol_im) ? (dc->xcol_im) : (dc->xgry_im) ;
1356 
1357    if( dc->visual_class == PseudoColor ){      /* actually change colormap */
1358 
1359       XStoreColors( dc->display , dc->colormap , xc , nc ) ;
1360 
1361 #if 0
1362       if( dc->cdef != NULL ) reload_DC_colordef( dc ) ;  /* 11 Feb 1999 */
1363 #else
1364       /* FREE_DC_colordef(dc->cdef) ; */
1365 #endif
1366 
1367    } else if( dc->visual_class == TrueColor ){  /* change internal pixel array */
1368 
1369       for( ii=0 ; ii < nc ; ii++ ){
1370          if( dc->pix_im_ready )
1371             XFreeColors( dc->display, dc->colormap, dc->pix_im+ii, 1, 0 ) ;
1372 
1373          XAllocColor( dc->display , dc->colormap , xc+ii ) ;
1374          dc->pix_im[ii] = xc[ii].pixel ;
1375       }
1376       dc->pix_im_ready = 1 ;
1377 
1378    }
1379 
1380    /* 06 Mar 2001: save RGB of colors into arrays for quick use later */
1381 
1382    for( ii=0 ; ii < nc ; ii++ ){
1383       dc->r_im[ii] = INTEN_TO_BYTE( xc[ii].red   ) ;
1384       dc->g_im[ii] = INTEN_TO_BYTE( xc[ii].green ) ;
1385       dc->b_im[ii] = INTEN_TO_BYTE( xc[ii].blue  ) ;
1386 #if 0
1387       dc->gray_im[ii] = BRIGHTNESS( dc->r_im[ii] , dc->g_im[ii] , dc->b_im[ii] ) ;
1388 #endif
1389    }
1390 
1391    return ;
1392 }
1393 
1394 /*--------------------------------------------------------------
1395    Yoke the widget to the DC -- 14 Sep 1998
1396 ----------------------------------------------------------------*/
1397 
DC_yokify(Widget w,MCW_DC * dc)1398 void DC_yokify( Widget w , MCW_DC *dc )
1399 {
1400    if( w == NULL || dc == NULL || !XtIsWidget(w) ) return ;
1401 
1402    XtVaSetValues( w ,
1403                      XmNvisual   , dc->visual ,
1404                      XmNcolormap , dc->colormap ,
1405                      XmNdepth    , dc->depth ,
1406                      XmNscreen   , dc->screen ,
1407                      XmNbackground  , 0 ,
1408                      XmNborderColor , 0 ,
1409                   NULL ) ;
1410    return ;
1411 }
1412 
1413 /*---------------------------------------------------------------------
1414    Load the colordef structure in the DC -- 11 Feb 1999
1415 -----------------------------------------------------------------------*/
1416 
reload_DC_colordef(MCW_DC * dc)1417 void reload_DC_colordef( MCW_DC *dc )
1418 {
1419    XVisualInfo * vin ;
1420    DC_colordef * cd ;   /* will be the output */
1421 
1422 ENTRY("reload_DC_colordef") ;
1423 
1424    /*--- sanity check ---*/
1425 
1426    if( dc == NULL || dc->visual_info == NULL ){
1427       fprintf(stderr,"reload_DC_colordef: entry values are NULL\n") ;
1428       EXRETURN ;
1429    }
1430 
1431    vin = dc->visual_info ;
1432 
1433    /*--- PseudoColor case ---*/
1434 
1435 #if defined(__cplusplus) || defined(c_plusplus)
1436    if( vin->c_class == PseudoColor ){
1437 #else
1438    if( vin->class == PseudoColor ){
1439 #endif
1440 
1441       int iz , count , ii ;
1442       XColor * xcol ;
1443 
1444       /* create output */
1445 
1446       cd = (DC_colordef *) malloc( sizeof(DC_colordef) ) ;
1447       cd->classKRH = PseudoColor ;
1448       cd->depth = vin->depth ;
1449 
1450       /* get all the colors in the colormap */
1451 
1452       count = vin->colormap_size ;
1453       xcol  = (XColor *) malloc( sizeof(XColor) * count ) ;
1454       for( ii=0 ; ii < count ; ii++ ) xcol[ii].pixel = ii ;
1455 
1456       XQueryColors( dc->display , dc->colormap , xcol , count ) ;
1457 
1458       /* store them in the output, truncated to 8 bit resolution */
1459 
1460       cd->ncolors = count ;
1461       cd->rr      = (byte *) malloc( count ) ;
1462       cd->gg      = (byte *) malloc( count ) ;
1463       cd->bb      = (byte *) malloc( count ) ;
1464 
1465       for( ii=0 ; ii < count ; ii++ ){
1466          cd->rr[ii] = xcol[ii].red   >> 8 ;
1467          cd->gg[ii] = xcol[ii].green >> 8 ;
1468          cd->bb[ii] = xcol[ii].blue  >> 8 ;
1469       }
1470 
1471       /* find a pure white color, if any */
1472 
1473       for( iz=0 ; iz < count ; iz++ )
1474          if( cd->rr[iz] == 255 && cd->gg[iz] == 255 && cd->bb[iz] == 255 ) break ;
1475 
1476       cd->nwhite = (iz < count) ? iz : -1 ;
1477 
1478       /* find first all zero color; discard others at end of colormap */
1479 
1480       for( iz=0 ; iz < count ; iz++ )
1481          if( cd->rr[iz] == 0 && cd->gg[iz] == 0 && cd->bb[iz] == 0 ) break ;
1482 
1483       cd->nblack = (iz < count) ? iz : -1 ;
1484 
1485       if( iz < count-1 ){  /* if found one before the end */
1486 
1487          for( ii=count-1 ; ii > iz ; ii-- )  /* scan backwards */
1488             if( cd->rr[ii] != 0 || cd->gg[ii] != 0 || cd->bb[ii] != 0 ) break ;
1489 
1490          count = ii+1 ;  /* number of colors left */
1491 
1492          if( count == 1 ){ /* colormap is all black?! */
1493             free(xcol) ; FREE_DC_colordef(cd) ;
1494             fprintf(stderr,"reload_DC_colordef: colormap is all black?\n") ;
1495             EXRETURN ;
1496          }
1497 
1498          cd->ncolors = count ;
1499       }
1500 
1501       FREE_DC_colordef(dc->cdef) ;  /* if already present, kill it */
1502 
1503       free(xcol) ; dc->cdef = cd ; EXRETURN ;
1504    }
1505 
1506    /*--- TrueColor case ---*/
1507 
1508 #if defined(__cplusplus) || defined(c_plusplus)
1509    if( vin->c_class == TrueColor ){
1510 #else
1511    if( vin->class == TrueColor ){
1512 #endif
1513 
1514       unsigned long r , g , b ;
1515       byte          rr, gg, bb ;
1516 
1517       /* create output */
1518 
1519       cd = (DC_colordef *) malloc( sizeof(DC_colordef) ) ;
1520       cd->classKRH = TrueColor ;
1521       cd->depth = vin->depth ;
1522 
1523       cd->rrmask  = vin->red_mask ;            /* bit masks for color  */
1524       cd->ggmask  = vin->green_mask ;          /* storage inside pixel */
1525       cd->bbmask  = vin->blue_mask ;
1526       cd->rrshift = 7 - highbit(cd->rrmask) ;  /* shift puts high bit of  */
1527       cd->ggshift = 7 - highbit(cd->ggmask) ;  /* a color byte into place */
1528       cd->bbshift = 7 - highbit(cd->bbmask) ;  /* +shift == >> ; - == <<  */
1529 
1530       /* compute the all white pixel as a common case */
1531 
1532       rr = gg = bb = 255 ;
1533 
1534       r = (cd->rrshift<0) ? (rr<<(-cd->rrshift))
1535                           : (rr>>cd->rrshift)   ; r = r & cd->rrmask ;
1536 
1537       g = (cd->ggshift<0) ? (gg<<(-cd->ggshift))
1538                           : (gg>>cd->ggshift)   ; g = g & cd->ggmask ;
1539 
1540       b = (cd->bbshift<0) ? (bb<<(-cd->bbshift))
1541                           : (bb>>cd->bbshift)   ; b = b & cd->bbmask ;
1542 
1543       cd->whpix = r | g | b ;
1544 
1545       cd->rr = cd->gg = cd->bb = NULL ;        /* not used */
1546 
1547       FREE_DC_colordef(dc->cdef) ;  /* if already present, kill it */
1548 
1549       dc->cdef = cd ; EXRETURN ;
1550    }
1551 
1552    /*--- Illegal Visual class! [do nothing]---*/
1553 
1554 #if defined(__cplusplus) || defined(c_plusplus)
1555    fprintf(stderr,"reload_DC_colordef: illegal Visual class %s\n",
1556                   x11_vcl[vin->c_class] ) ;
1557 #else
1558    fprintf(stderr,"reload_DC_colordef: illegal Visual class %s\n",
1559                   x11_vcl[vin->class] ) ;
1560 #endif
1561    EXRETURN ;
1562 }
1563 
1564 /*---------------------------------------------------------------------
1565    Compute the Pixel that is closest to the given (r,g,b) color
1566 -----------------------------------------------------------------------*/
1567 
1568 Pixel DC_rgb_to_pixel( MCW_DC *dc, byte rr, byte gg, byte bb )
1569 {
1570    static MCW_DC *dcold = NULL ;
1571    DC_colordef *cd = dc->cdef ;
1572 
1573    if( cd == NULL ){ reload_DC_colordef(dc) ; cd = dc->cdef ; }
1574 
1575    switch( cd->classKRH ){
1576 
1577       /*--- TrueColor case: make color by appropriate bit twiddling ---*/
1578       /*--- The code below is duplicated in xim.c for efficiency :) ---*/
1579 
1580       case TrueColor:{
1581          static unsigned long pold=0 ;
1582          static byte rold=0 , gold=0 , bold=0 ;
1583          unsigned long r , g , b ;
1584 
1585          if( rr == 0   && gg == 0   && bb == 0   ) return 0 ;          /* common */
1586          if( rr == 255 && gg == 255 && bb == 255 ) return cd->whpix ;  /* cases  */
1587 
1588          if( dc == dcold && rr == rold && gg == gold && bb == bold ) /* Remembrance of Things Past? */
1589             return (Pixel) pold ;
1590 
1591          rold = rr ; gold = gg ; bold = bb ; dcold = dc ;            /* OK, remember for next time */
1592 
1593          r = (cd->rrshift<0) ? (rr<<(-cd->rrshift))
1594                              : (rr>>cd->rrshift)   ; r = r & cd->rrmask ;
1595 
1596          g = (cd->ggshift<0) ? (gg<<(-cd->ggshift))
1597                              : (gg>>cd->ggshift)   ; g = g & cd->ggmask ;
1598 
1599          b = (cd->bbshift<0) ? (bb<<(-cd->bbshift))
1600                              : (bb>>cd->bbshift)   ; b = b & cd->bbmask ;
1601 
1602          pold = r | g | b ;  /* assemble color from components */
1603          return (Pixel) pold ;
1604       }
1605 
1606       /*--- PseudoColor case: find closest match in colormap.
1607             Red, green, and blue are weighted according
1608               to their importance to the human visual system.
1609             This code is slower than the TrueColor case above,
1610             which is due to the search through the PseudoColor palette. */
1611 
1612       case PseudoColor:{
1613 
1614 #define RW 2  /* the weights alluded to above */
1615 #define GW 4
1616 #define BW 1
1617 #define RGBSUM 4  /* max allowed difference */
1618 
1619          static int iold=0 , rold=0,gold=0,bold=0 ;
1620          int ii , rdif,gdif,bdif,dif , ibest,dbest ;
1621 
1622          if( cd->nblack >= 0 && rr == 0 && gg == 0 && bb == 0 )       /* deal with  */
1623             return (Pixel) cd->nblack ;                               /* 2 special  */
1624                                                                       /* and common */
1625          if( cd->nwhite >= 0 && rr == 255 && gg == 255 && bb == 255 ) /* cases      */
1626             return (Pixel) cd->nwhite ;
1627 
1628          if( dc == dcold ){     /* check in with the last call - maybe it's good */
1629             rdif = rold - rr ;
1630             gdif = gold - gg ;
1631             bdif = bold - bb ; dif = RW*abs(rdif)+GW*abs(gdif)+BW*abs(bdif) ;
1632             if( dif <= RGBSUM ) return (Pixel) iold ;     /* Remembrance of Things Past? */
1633          }
1634 
1635          rold = rr ; gold = gg ; bold = bb ; dcold = dc ; /* No? Remember for next time. */
1636 
1637          /* check first color in palette; if it is "close enough" (RGBSUM), use it */
1638 
1639          rdif = cd->rr[0] - rr ;
1640          gdif = cd->gg[0] - gg ;
1641          bdif = cd->bb[0] - bb ; dif = RW*abs(rdif)+GW*abs(gdif)+BW*abs(bdif) ;
1642          if( dif <= RGBSUM ){ iold = 0 ; return 0 ; }
1643 
1644          /* scan thru the rest of the colors in palette,
1645             either finding one close enough, or finding the closest one */
1646 
1647          ibest = 0 ; dbest = dif ;
1648          for( ii=1 ; ii < cd->ncolors ; ii++ ){
1649             rdif = cd->rr[ii] - rr ;
1650             gdif = cd->gg[ii] - gg ;
1651             bdif = cd->bb[ii] - bb ; dif = RW*abs(rdif)+GW*abs(gdif)+BW*abs(bdif) ;
1652             if( dif <= RGBSUM ){ iold  = ii ; return (Pixel) ii ; }
1653             if( dif < dbest   ){ ibest = ii ; dbest = dif ; }
1654          }
1655          iold = ibest ; return (Pixel) ibest ;
1656       }
1657    }
1658 
1659    /*--- Illegal case! ---*/
1660 
1661    return 0 ;  /* Black is always valid (but not very colorful) */
1662 }
1663 
1664 /*---------------------------------------------------------------------
1665    Compute the Pixel that is closest to the given (r,g,b) color,
1666    but if the pixel isn't gray (r=g=b), the color must be from
1667    the specified set of overlay colors.  [20 Dec 1999 - RW Cox]
1668 -----------------------------------------------------------------------*/
1669 
1670 Pixel DC_rgb_to_ovpix( MCW_DC *dc, byte rr, byte gg, byte bb )
1671 {
1672    static MCW_DC *dcold=NULL ;
1673    static Pixel pold=0 ;
1674    static int rold=0,gold=0,bold=0 ;
1675    int ii , rdif,gdif,bdif,dif , ibest,dbest ;
1676 
1677    if( rr == gg && rr == bb ) return DC_rgb_to_pixel(dc,rr,gg,bb) ;
1678 
1679    if( dc == NULL || dc->ovc == NULL || dc->ovc->ncol_ov == 0 ) return 0 ;
1680 
1681    if( dc == dcold ){                   /* check if we just saw this */
1682       rdif = rold - rr ;
1683       gdif = gold - gg ;
1684       bdif = bold - bb ;
1685       dif  = RW*abs(rdif)+GW*abs(gdif)+BW*abs(bdif) ;
1686       if( dif <= RGBSUM ) return pold ;
1687    }
1688 
1689    rold = rr ; gold = gg ; bold = bb ; dcold = dc ;  /* remember for next time */
1690 
1691    rdif = DCOV_REDBYTE(dc,0)   - rr ;
1692    gdif = DCOV_GREENBYTE(dc,0) - gg ;
1693    bdif = DCOV_BLUEBYTE(dc,0)  - bb ;
1694    dif  = RW*abs(rdif)+GW*abs(gdif)+BW*abs(bdif) ;
1695    if( dif <= RGBSUM ){ pold = dc->ovc->pix_ov[0] ; return pold ; }
1696 
1697    ibest = 0 ; dbest = dif ;
1698    for( ii=1 ; ii < dc->ovc->ncol_ov ; ii++ ){
1699       rdif = DCOV_REDBYTE(dc,ii)   - rr ;
1700       gdif = DCOV_GREENBYTE(dc,ii) - gg ;
1701       bdif = DCOV_BLUEBYTE(dc,ii)  - bb ;
1702       dif  = RW*abs(rdif)+GW*abs(gdif)+BW*abs(bdif) ;
1703       if( dif <= RGBSUM ){ pold = dc->ovc->pix_ov[ii] ; return pold ; }
1704       if( dif < dbest   ){ ibest = ii ; dbest = dif ; }
1705    }
1706    pold = dc->ovc->pix_ov[ibest] ; return pold ;
1707 }
1708 
1709 /*---------------------------------------------------------------------
1710    Convert color to triple in overlay color list that is closest.
1711 -----------------------------------------------------------------------*/
1712 
1713 void DC_rgb_to_ovrgb( MCW_DC *dc , int nlist , int * list , int shade ,
1714                                     byte *rrin , byte *ggin, byte *bbin )
1715 {
1716    int jj,jtop,ii , rdif,gdif,bdif,dif , ibest,dbest ;
1717    byte rr=*rrin , gg=*ggin , bb=*bbin , mm , rt,gt,bt , rtbest,gtbest,btbest;
1718    float brig , fac ;
1719 
1720    if( rr == gg && rr == bb ) return ;  /* if grayscale, is OK */
1721 
1722    if( dc == NULL || dc->ovc == NULL || dc->ovc->ncol_ov == 0 ) return ;
1723 
1724    /* start with the gray color with the same brightness */
1725 
1726    brig = BRIGHTNESS(rr,gg,bb) ; mm = (byte)(brig + 0.499) ;
1727    dbest = RW*abs(mm-rr)+GW*abs(mm-gg)+BW*abs(mm-bb) ;    /* diff from gray */
1728    if( dbest <= RGBSUM ){
1729       *rrin = *ggin = *bbin = mm ; return ;
1730    }
1731    ibest = 0 ; rtbest = gtbest = btbest = mm ;
1732 
1733    /* now check the colors in the list given, or the entire set if no list */
1734 
1735    jtop = (nlist > 0) ? nlist : dc->ovc->ncol_ov ;
1736    for( jj=0 ; jj < jtop ; jj++ ){
1737       ii = (nlist > 0) ? list[jj] : jj ;
1738       if( ii <= 0 || ii >= dc->ovc->ncol_ov || dc->ovc->bright_ov[ii] <= 0.0 ) continue ;
1739 
1740       rt = DCOV_REDBYTE(dc,ii) ; gt = DCOV_GREENBYTE(dc,ii) ; bt = DCOV_BLUEBYTE(dc,ii) ;
1741       if( shade ){
1742         fac = brig / dc->ovc->bright_ov[ii] ;
1743         rt  = (byte)( fac*rt + 0.499 ) ;
1744         gt  = (byte)( fac*gt + 0.499 ) ;
1745         bt  = (byte)( fac*bt + 0.499 ) ;
1746       }
1747       dif = RW*abs(rt-rr)+GW*abs(gt-gg)+BW*abs(bt-bb) ;
1748       if( dif <= RGBSUM ){
1749          *rrin = rt ; *ggin = gt ; *bbin = bt ; return ;
1750       }
1751       if( dif < dbest ){
1752          ibest = ii ; dbest = dif ; rtbest = rt ; gtbest = gt ; btbest = bt ;
1753       }
1754    }
1755 
1756    *rrin = rtbest ; *ggin = gtbest ; *bbin = btbest ; return ;
1757 }
1758 
1759 /*---------------------------------------------------------------------
1760    Compute the (r,g,b) color corresponding to a given Pixel
1761 -----------------------------------------------------------------------*/
1762 
1763 void DC_pixel_to_rgb( MCW_DC *dc , Pixel ppp ,
1764                       byte * rr , byte * gg , byte * bb )
1765 {
1766    DC_colordef * cd = dc->cdef ;
1767 
1768    if( cd == NULL ){ reload_DC_colordef(dc) ; cd = dc->cdef ; }
1769 
1770    switch( cd->classKRH ){
1771 
1772       /*--- TrueColor case: unmake color by appropriate bit twiddling ---*/
1773 
1774       case TrueColor:{
1775          unsigned long r , g , b ;
1776 
1777          if( ppp == 0         ){ *rr = *bb = *gg = 0   ; return ; }  /* common cases */
1778          if( ppp == cd->whpix ){ *rr = *bb = *gg = 255 ; return ; }
1779 
1780          r   = ppp & cd->rrmask ;
1781          *rr = (cd->rrshift<0) ? (r>>(-cd->rrshift)) : (r<<cd->rrshift) ;
1782 
1783          g   = ppp & cd->ggmask ;
1784          *gg = (cd->ggshift<0) ? (g>>(-cd->ggshift)) : (g<<cd->ggshift) ;
1785 
1786          b   = ppp & cd->bbmask ;
1787          *bb = (cd->bbshift<0) ? (b>>(-cd->bbshift)) : (b<<cd->bbshift) ;
1788 
1789          return ;
1790       }
1791 
1792       /*--- PseudoColor case: extract from colormap ---*/
1793 
1794       case PseudoColor:{
1795          int ii = (int) ppp ;
1796          *rr = cd->rr[ii] ; *gg = cd->gg[ii] ; *bb = cd->bb[ii] ; return ;
1797       }
1798    }
1799 
1800    return ;
1801 }
1802 
1803 /*-------------------------------------------------------------------------
1804    21 Sep 2001: compute an (r,g,b) triple (floating point, 0..1)
1805                 for the given color string;
1806                 return value is 0 for good, 1 for bad
1807                 (if bad, *rr, *gg, *bb aren't touched)
1808 ---------------------------------------------------------------------------*/
1809 
1810 int DC_parse_color( MCW_DC *dc, char *str, float *rr, float *gg, float *bb )
1811 {
1812    XColor cell ; int ok ;
1813 
1814    if( str == NULL || *str == '\0' ) return 1 ;
1815 
1816    if( strncmp(str,"AJJ:",4) == 0 ){                  /* 07 Feb 2003 */
1817      float ang=-6666.0 ;
1818      sscanf(str+4,"%f",&ang) ;
1819      if( ang != -6666.0 ){
1820        rgbyte col = DC_spectrum_AJJ( ang , 0.8 ) ;
1821        *rr = col.r / 255.0f ; *gg = col.g / 255.0f ; *bb = col.b / 255.0f ;
1822        return 0 ;
1823      }
1824      return 1 ;
1825    }
1826 
1827    if( strncmp(str,"RGB:",4) == 0 ){                  /* 18 Sep 2007 */
1828      float ir=-1.0f,ig=-1.0f,ib=-1.0f ; char s1,s2 ;
1829      sscanf( str+4 ,"%f%c%f%c%f" , &ir,&s1,&ig,&s2,&ib ) ;
1830      if( ir >= 0.0f && ig >= 0.0f && ib >= 0.0f ){
1831        ir = MIN(ir,255.0f);  ig = MIN(ig,255.0f);  ib = MIN(ib,255.0f);
1832       *rr = ir / 255.0f   ; *gg = ig / 255.0f   ; *bb = ib / 255.0f   ;
1833       return 0 ;
1834      }
1835    }
1836 
1837    ok = find_color_name(str,rr,gg,bb) ; if( ok >= 0 ) return 0 ; /* 02 Dec 2015 */
1838 
1839    /* let X11 try to understand the input string */
1840 
1841    ok = XParseColor( dc->display , dc->colormap , str , &cell ) ;
1842    if( ok ){
1843       *rr = cell.red   / 65535.0f ;
1844       *gg = cell.green / 65535.0f ;
1845       *bb = cell.blue  / 65535.0f ;
1846       return 0 ;
1847    }
1848 
1849    return 1 ;
1850 }
1851 
1852 /* Create those AJJ maps */
1853 int NJ_bigmaps_init(int bigmap_num, char ***bigmap_namep, rgbyte ***bigmapp)
1854 {
1855    char **bigmap_name=NULL;
1856    rgbyte **bigmap = NULL;
1857    int ii=0 ,mm=0, NPB_2=NPANE_BIG/2;
1858 
1859    if (  !bigmap_namep || !bigmapp ||
1860          bigmap_num != NBIGMAP_INIT) return 1;
1861 
1862    {
1863      bigmap_name    = (char **) malloc(sizeof(char *)*bigmap_num) ;
1864      /* copy all names */
1865      for(mm = 0; mm < bigmap_num; mm++ )
1866         bigmap_name[mm] = strdup(BIGMAP_NAMES[mm]) ;
1867 
1868      bigmap = (rgbyte **)malloc(sizeof(rgbyte *)*bigmap_num) ;
1869 
1870      /* ZSS: The +1 is to stop a a MCW_malloc post-corruption which happens
1871      under certain compiler/OS combinations. The likely cause is the uneven
1872      byte size of rgbyte which might be causing misalignment problems at the
1873      very end          March 27 2012 */
1874 
1875      /* allocate all RGB arrays */
1876      for(mm = 0; mm < bigmap_num; mm++ )
1877         bigmap[mm] = (rgbyte *) malloc(sizeof(rgbyte)*(NPANE_BIG+1)) ;
1878 
1879      /* fill RGB arrays */
1880      for( ii=0 ; ii < NPANE_BIG ; ii++ ){
1881        bigmap[0][ii] = DC_spectrum_AJJ(      ii*((AJJ_BLU+8.0)/(NPANE_BIG-1.0))-4.0,0.8);
1882        bigmap[4][ii] = DC_spectrum_AJJ( 60.0-ii*(AJJ_YEL/(NPANE_BIG-1.0))          ,0.7);
1883        bigmap[5][ii] = DC_spectrum_AJJ(      ii*(360.0  /(NPANE_BIG-1.0))          ,0.8);
1884        bigmap[6][ii] = DC_spectrum_ZSS(360.0-ii*(360.0  /(NPANE_BIG-1.0))          ,1.0);
1885        if( ii < NBIG_MBOT ){
1886          bigmap[1][ii] = DC_spectrum_AJJ(         ii*(AJJ_YEL/(NBIG_MBOT-1.0)) , 0.8 );
1887          bigmap[2][ii] = DC_spectrum_AJJ( AJJ_YEL-ii*(AJJ_YEL/(NBIG_MBOT-1.0)) , 0.8 );
1888          bigmap[3][ii] = bigmap[2][ii] ;
1889        } else if( ii > NBIG_MTOP ){
1890          bigmap[1][ii] = DC_spectrum_AJJ( AJJ_CYN+(ii-NBIG_MTOP-1)*(60.0/(NPANE_BIG-NBIG_MTOP-2.0)),0.8);
1891          bigmap[2][ii] = DC_spectrum_AJJ( AJJ_BLU-(ii-NBIG_MTOP-1)*(60.0/(NPANE_BIG-NBIG_MTOP-2.0)),0.8);
1892          bigmap[3][ii] = bigmap[2][ii] ;
1893        } else {
1894          bigmap[1][ii].r = bigmap[1][ii].g = bigmap[1][ii].b = 0 ;
1895          bigmap[2][ii]   = DC_spectrum_AJJ( 360.0-(ii-NBIG_MBOT+1)*(120.0/(NBIG_MTOP-NBIG_MBOT+2.0)),0.8) ;
1896          bigmap[3][ii].r = bigmap[3][ii].g = bigmap[3][ii].b = 0 ;
1897        }
1898      }
1899 
1900      /* map[7] = "Reds_and_Blues" 10 Nov, 2014 [rickr] */
1901      for( ii=0     ; ii < NPB_2     ; ii++ ) {
1902         bigmap[7][ii] = DC_spectrum_AJJ(AJJ_YEL-ii*(AJJ_YEL/(NPB_2-1.0)), 0.8);
1903         bigmap[8][ii] = DC_spectrum_AJJ(AJJ_YEL-ii*(AJJ_YEL/(NPB_2-1.0)), 0.8);
1904      }
1905      for( ii=NPB_2 ; ii < NPANE_BIG ; ii++ ) {
1906         bigmap[7][ii] = DC_spectrum_AJJ(AJJ_BLU-(ii-NBIG_MTOP-1)*
1907                                 (60.0/(NPANE_BIG-NPB_2-2.0)),0.8);
1908         bigmap[8][ii] = DC_spectrum_AJJ(AJJ_BLU-(ii-NBIG_MTOP-1)*
1909                                 (60.0/(NPANE_BIG-NPB_2-2.0)),0.8);
1910      }
1911 
1912      /* add greens to map[8] for "Reds_and_Blues_w_Green" */
1913      bigmap[8][NPB_2-1] = bigmap[8][NPB_2] =
1914         DC_spectrum_AJJ( (NPB_2)*((AJJ_BLU+8.0)/(NPANE_BIG-1.0))-4.0,0.8);
1915    }
1916    *bigmapp = bigmap;
1917    *bigmap_namep = bigmap_name;
1918    return 0;
1919 }
1920 
1921 /* want to check this from the command line     4 Mar 2009 [rickr] */
1922 void show_motif_version_string(void)
1923 {
1924    char * verstr = "** VERSION STRING NOT DEFINED**";
1925    char * typestr = source_is_lesstif() ? "LessTif" : "Motif";
1926 
1927 #ifdef XmVERSION_STRING
1928    verstr = XmVERSION_STRING;
1929 #endif
1930 
1931 #ifdef AFNI_MOTIF_TYPE
1932    typestr = AFNI_MOTIF_TYPE;
1933 #endif
1934 
1935    fprintf(stderr, "-- Motif source = %s, USING_LESSTIF = %d\n",
1936            typestr, using_lesstif_is_defined());
1937    fprintf(stderr, "   %s\n", verstr);
1938 }
1939 
1940 int source_is_lesstif(void)
1941 {
1942 #ifdef LESSTIF_VERSION
1943    return 1;
1944 #endif
1945    return 0;
1946 }
1947 
1948 int using_lesstif_is_defined(void)
1949 {
1950 #ifdef USING_LESSTIF
1951    return 1;
1952 #endif
1953    return 0;
1954 }
1955