Skip to content

AFNI/NIfTI Server

Sections
Personal tools
You are here: Home » AFNI » Documentation

Doxygen Source Code Documentation


Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Search  

SUMA_xColBar.c

Go to the documentation of this file.
00001 /*! File to contain functions for creating interface
00002 for mapping data to color maps. Lots of functions from
00003 xim.c display.c and pbar.c*/
00004 
00005 #include "SUMA_suma.h"
00006  
00007 #undef STAND_ALONE
00008 
00009 #if defined SUMA_SHOW_CMAP_STAND_ALONE
00010 #define STAND_ALONE
00011 #endif
00012 
00013 #ifdef STAND_ALONE
00014 /* these global variables must be declared even if they will not be used by this main */
00015 SUMA_SurfaceViewer *SUMAg_cSV; /*!< Global pointer to current Surface Viewer structure*/
00016 SUMA_SurfaceViewer *SUMAg_SVv; /*!< Global pointer to the vector containing the various Surface Viewer Structures 
00017                                     SUMAg_SVv contains SUMA_MAX_SURF_VIEWERS structures */
00018 int SUMAg_N_SVv = 0; /*!< Number of SVs realized by X */
00019 SUMA_DO *SUMAg_DOv;   /*!< Global pointer to Displayable Object structure vector*/
00020 int SUMAg_N_DOv = 0; /*!< Number of DOs stored in DOv */
00021 SUMA_CommonFields *SUMAg_CF; /*!< Global pointer to structure containing info common to all viewers */
00022 #else
00023 extern SUMA_CommonFields *SUMAg_CF;
00024 extern SUMA_DO *SUMAg_DOv;
00025 extern SUMA_SurfaceViewer *SUMAg_SVv;
00026 extern int SUMAg_N_SVv; 
00027 extern int SUMAg_N_DOv;  
00028 #endif
00029 
00030 /* the method for hiding a surface viewer (and other controllers), used to have three options prior to Fri Jan  3 10:21:52 EST 2003
00031 Now only SUMA_USE_WITHDRAW and NOT SUMA_USE_DESTROY should be used*/
00032 #define SUMA_USE_WITHDRAW
00033 
00034 /*!
00035    \brief Reads a ppm image and turns i into an rgba vector for ease of
00036    use with OpenGL. 
00037    Depends heavily on afni's mri_read_ppm
00038 */
00039 unsigned char *SUMA_read_ppm(char *fname, int *width, int *height, int verb)
00040 {
00041    static char FuncName[]={"SUMA_read_ppm"};
00042    char stmp[500];
00043    unsigned char *imar = NULL;
00044    byte * rgb , *cp=NULL;
00045    float alf = 0;
00046    MRI_IMAGE * im=NULL;
00047    int ir, ic, i1d, i1df, imx, i1d3, i1d4;
00048    SUMA_Boolean LocalHead = NOPE;
00049    
00050    if (!fname) { if (verb) SUMA_SL_Err("NULL fname");  SUMA_RETURN(imar); }
00051    im = mri_read_ppm( fname ) ;
00052    if (!im) { 
00053       if (verb) { snprintf(stmp, 500 * sizeof(char), "Failed to read %s", fname); SUMA_SL_Err(stmp); }
00054       SUMA_RETURN(imar); 
00055    }
00056    
00057    rgb = MRI_RGB_PTR(im) ;
00058    *height = im->ny ;
00059    *width = im->nx ;
00060    imx = im->ny * im->nx;
00061    
00062    if (LocalHead) fprintf (SUMA_STDERR,"%s:\nNx (width) = %d, Ny (height) = %d\n", FuncName, im->nx, im->ny);
00063    
00064    imar = (unsigned char *) SUMA_malloc(sizeof(unsigned char) * im->nx * im->ny * 4);
00065    if (!imar) {
00066       SUMA_SL_Crit("Failed to allocate.");
00067       mri_free(im) ;
00068       SUMA_RETURN(imar); 
00069    }
00070    
00071    for (ir = 0; ir < im->ny; ++ir) {
00072       for (ic = 0; ic < im->nx; ++ic) {
00073          i1d = ic + ir * im->nx; /* equivalent 1d index into row major image data */
00074          i1df = ic + (im->ny - ir - 1) * im->nx; /* column flipped index */
00075          i1d4 = 4 * i1d; i1d3 = 3*i1df; 
00076          imar[i1d4] = (unsigned char)rgb[i1d3]; alf  = (float)imar[i1d4];   ++i1d3; ++i1d4; 
00077          imar[i1d4] = (unsigned char)rgb[i1d3]; alf += (float)imar[i1d4];   ++i1d3; ++i1d4; 
00078          imar[i1d4] = (unsigned char)rgb[i1d3]; alf += (float)imar[i1d4];            ++i1d4; 
00079          imar[i1d4] = (unsigned char)(alf/3.0); 
00080       }
00081    } 
00082 
00083    mri_free(im) ; im = NULL;
00084    
00085    SUMA_RETURN(imar); 
00086 }
00087 
00088 void SUMA_cmap_wid_graphicsInit (Widget w, XtPointer clientData, XtPointer call)
00089 {
00090    static char FuncName[]={"SUMA_cmap_wid_graphicsInit"};
00091    XVisualInfo *SUMAg_cVISINFO;
00092    SUMA_SurfaceObject *SO=NULL;
00093    SUMA_Boolean LocalHead = NOPE;
00094    
00095    SUMA_ENTRY;
00096    
00097    SUMA_LH("called");
00098    
00099    SO = (SUMA_SurfaceObject *)clientData;
00100    if (!SO) { SUMA_SL_Err("NULL SO"); SUMA_RETURNe; }
00101    
00102    XtVaGetValues(w, GLwNvisualInfo, &SUMAg_cVISINFO, NULL);
00103    SO->SurfCont->cmp_ren->cmap_context = glXCreateContext(XtDisplay(w), SUMAg_cVISINFO,
00104             0,                  /* No sharing. */
00105             True);              /* Direct rendering if possible. */
00106    
00107    /* Setup OpenGL state. */
00108    if (!glXMakeCurrent(XtDisplay(w), XtWindow(w), SO->SurfCont->cmp_ren->cmap_context)) {
00109       fprintf (SUMA_STDERR, "Error %s: Failed in glXMakeCurrent.\n \tContinuing ...\n", FuncName);
00110    }
00111    
00112    /* call context_Init to setup colors and lighting */   
00113    SUMA_cmap_context_Init(SO);
00114 
00115    SUMA_RETURNe;
00116 }
00117 
00118 /*!
00119    Originally intended to setup for an Ortho2D mode for an image display
00120    But we don't like 2D. So this ends up being very much like 
00121    SUMA_context_Init, lookt here for reference if need be.
00122 */
00123 void SUMA_cmap_context_Init(SUMA_SurfaceObject *SO)
00124 {
00125    static char FuncName[]={"SUMA_cmap_context_Init"};
00126    GLfloat mat_specular[] = { 0.0, 0.0, 0.0, 1.0};
00127    GLfloat mat_shininess[] = { 0 };
00128    GLfloat mat_ambient[] = { 0.0, 0.0, 0.0, 1.0};
00129    GLfloat mat_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
00130    GLfloat mat_emission[] = { SUMA_MAT_EMISSION_INIT  };
00131    GLfloat clear_color[] = { 0.0, 0.0, 0.0, 0.0};
00132    GLfloat light0_color[] = { 1.0, 1.0, 1.0, 1.0};
00133    GLfloat lmodel_ambient[] = {1.0, 1.0, 1.0, 1.0};
00134    GLfloat light0_position[] = {0.0, 0.0, -1.0, 0.0};
00135    GLfloat ViewFrom[]={0.0, 0.0, 300};
00136    GLfloat ViewCenter[]={0.0, 0.0, 0.0};
00137    GLfloat ViewCamUp[]={0.0, 1.0, 0.0};
00138    GLfloat CmapOrig[]={SUMA_CMAP_ORIGIN};
00139    GLfloat CmapTL[]={SUMA_CMAP_TOPLEFT};
00140    int i;
00141    
00142    SUMA_ENTRY;
00143 
00144    glClearColor (clear_color[0], clear_color[1], clear_color[2], clear_color[3]);
00145    glShadeModel (GL_SMOOTH);
00146 
00147    SUMA_SET_GL_RENDER_MODE(SRM_Fill); 
00148    
00149       
00150    /* Set the material properties*/
00151    glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
00152    glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
00153    glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
00154    glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
00155    glMaterialfv(GL_FRONT, GL_EMISSION, mat_emission);
00156     
00157    /* set the directional light properties */
00158    glLightfv(GL_LIGHT0, GL_POSITION, light0_position);
00159    glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_color);
00160    glLightfv(GL_LIGHT0, GL_SPECULAR, light0_color);
00161 
00162    /* set the ambient light */
00163    glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
00164  
00165    glEnable(GL_LIGHTING); /* prepare GL to perform lighting calculations */
00166    glEnable(GL_LIGHT0); /*Turn lights ON */
00167    glEnable(GL_DEPTH_TEST);
00168    
00169    /*setup the view point and then setup the lights. Those lights will remain in place regardless of the rotations/translations
00170    done on the surface */
00171    for (i=0; i<2; ++i) { ViewCenter[i] = (CmapTL[i] - CmapOrig[i]) / 2.0;  }
00172    ViewFrom[0] = ViewCenter[0]; ViewFrom[1] = ViewCenter[1]; ViewFrom[2] = SUMA_CMAP_VIEW_FROM;
00173     
00174    glMatrixMode(GL_MODELVIEW);
00175    glLoadIdentity();
00176    gluLookAt ( ViewFrom[0], ViewFrom[1], ViewFrom[2],  
00177                ViewCenter[0], ViewCenter[1], ViewCenter[2],
00178                ViewCamUp[0], ViewCamUp[1], ViewCamUp[2] );
00179    
00180    
00181    SUMA_RETURNe;
00182    
00183 }
00184 
00185 void SUMA_DrawCmap(SUMA_COLOR_MAP *Cmap)
00186 {
00187    static char FuncName[]={"SUMA_DrawCmap"};
00188    float orig[3]={ SUMA_CMAP_ORIGIN };
00189    int i;
00190    float topright[3] = { SUMA_CMAP_TOPLEFT };
00191    SUMA_Boolean LocalHead = NOPE;
00192    
00193    SUMA_ENTRY;
00194    
00195    SUMA_LH("called");
00196 
00197    if (!Cmap->SO) {
00198       SUMA_LH("Creating Cmap's SO");
00199       Cmap->SO = SUMA_Cmap_To_SO(Cmap, orig, topright, 0);
00200       if (!Cmap->SO) { SUMA_SL_Err("Failed to create SO"); }
00201    }
00202     
00203    /* This allows each node to follow the color specified when it was drawn */ 
00204    glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); 
00205    glEnable(GL_COLOR_MATERIAL);
00206 
00207    /*Now setup various pointers*/
00208    glEnableClientState (GL_COLOR_ARRAY);
00209    glEnableClientState (GL_VERTEX_ARRAY);
00210    glEnableClientState (GL_NORMAL_ARRAY);
00211    glColorPointer (4, GL_FLOAT, 0, Cmap->SO->PermCol);
00212    glVertexPointer (3, GL_FLOAT, 0, Cmap->SO->glar_NodeList);
00213    glNormalPointer (GL_FLOAT, 0, Cmap->SO->glar_NodeNormList);
00214 
00215    SUMA_SET_GL_RENDER_MODE(SRM_Fill); 
00216    glDrawElements (GL_TRIANGLES, (GLsizei)Cmap->SO->N_FaceSet*3, GL_UNSIGNED_INT, Cmap->SO->glar_FaceSetList);
00217    
00218    /* Here you could draw a contour around the color cells. 
00219    But you'll need to raise the contour over the filled polygons because they'll get
00220    covered otherwise */ 
00221    #if 0
00222    { 
00223       GLfloat *LineCol=NULL;   
00224       LineCol = (GLfloat *)SUMA_calloc(Cmap->SO->N_Node*4, sizeof(GLfloat));
00225       for (i=0; i<Cmap->SO->N_Node; ++i) { LineCol[4*i] = LineCol[4*i+1] = LineCol[4*i+2] = 0.1; LineCol[4*i+3] = 1.0; }
00226       glColorPointer (4, GL_FLOAT, 0, LineCol);
00227       SUMA_SET_GL_RENDER_MODE(SRM_Line); 
00228       glDrawElements (GL_TRIANGLES, (GLsizei)Cmap->SO->N_FaceSet*3, GL_UNSIGNED_INT, Cmap->SO->glar_FaceSetList);
00229       SUMA_free(LineCol); LineCol = NULL;
00230    }
00231    #endif
00232    
00233    SUMA_RETURNe;
00234 }
00235 
00236 void SUMA_cmap_wid_display(SUMA_SurfaceObject *SO)
00237 {   
00238    static char FuncName[]={"SUMA_cmap_wid_display"};
00239    int i;
00240    GLfloat rotationMatrix[4][4];
00241    float currentQuat[]={0.0, 0.0, 0.0, 1.0};
00242    GLfloat clear_color[] = { 0.8, 0.8, 0.8, 0.0};
00243    GLfloat RotaCenter[]={0.0, 0.0, 0.0};
00244    SUMA_COLOR_MAP *Cmap = NULL;
00245    SUMA_Boolean LocalHead = NOPE; /* local headline debugging messages */   
00246     
00247    SUMA_ENTRY;
00248    
00249    SUMA_LH("in, lots of inefficiencies here, make sure you revisit");
00250    
00251    /* now you need to set the clear_color since it can be changed per viewer Thu Dec 12 2002 */
00252    glClearColor (clear_color[0], clear_color[1],clear_color[2],clear_color[3]);
00253       
00254    if (LocalHead) fprintf (SUMA_STDOUT,"%s: Building Rotation matrix ...\n", FuncName);
00255    SUMA_build_rotmatrix(rotationMatrix, currentQuat);
00256     
00257    if (LocalHead) fprintf (SUMA_STDOUT,"%s: performing glClear ...\n", FuncName);
00258    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /* clear the Color Buffer and the depth buffer */
00259    
00260    /* careful here, you might want to turn the next block into a macro like SUMA_SET_GL_PROJECTION */
00261    if (LocalHead) fprintf (SUMA_STDOUT,"%s: Setting up matrix mode and perspective ...\nFOV=%f\n", FuncName, SUMA_CMAP_FOV_INITIAL);
00262    glMatrixMode (GL_PROJECTION);
00263    glLoadIdentity ();
00264    gluPerspective(SO->SurfCont->cmp_ren->FOV, (double)SUMA_CMAP_WIDTH/SUMA_CMAP_HEIGHT, SUMA_PERSPECTIVE_NEAR, SUMA_PERSPECTIVE_FAR); /*lower angle is larger zoom,*/
00265 
00266    glMatrixMode(GL_MODELVIEW);
00267    glPushMatrix();
00268    glTranslatef (SO->SurfCont->cmp_ren->translateVec[0], SO->SurfCont->cmp_ren->translateVec[1], SO->SurfCont->cmp_ren->translateVec[2] );
00269    if (0){
00270    SUMA_SL_Note("no need for shananigans\n"
00271                   "But to illustrate ...\n");
00272    glTranslatef (RotaCenter[0], RotaCenter[1], RotaCenter[2]);
00273    glMultMatrixf(&rotationMatrix[0][0]);
00274    glTranslatef (-RotaCenter[0], -RotaCenter[1], -RotaCenter[2]);
00275    }
00276    
00277    /* find out what colormap is to be displayed */
00278    if (SO->SurfCont->curColPlane) {
00279       /* what's the Cmap for that plane ? */
00280       Cmap = SUMA_CmapOfPlane (SO->SurfCont->curColPlane );
00281       if (Cmap) SUMA_DrawCmap(Cmap); /* create the colormap */
00282    } else {
00283       SUMA_SL_Err("NULL SO->SurfCont->curColPlane");
00284    }   
00285    glPopMatrix();   
00286 
00287    if (LocalHead) fprintf (SUMA_STDOUT,"%s: Flushing or swapping ...\n", FuncName);
00288    
00289    if (SUMAg_SVv[0].X->DOUBLEBUFFER)
00290       glXSwapBuffers(XtDisplay(SO->SurfCont->cmp_ren->cmap_wid), XtWindow(SO->SurfCont->cmp_ren->cmap_wid));
00291    else  
00292       glFlush();
00293 
00294    /* Avoid indirect rendering latency from queuing. */
00295    if (!glXIsDirect(XtDisplay(SO->SurfCont->cmp_ren->cmap_wid), SO->SurfCont->cmp_ren->cmap_context))
00296       glFinish();
00297 
00298    SUMA_RETURNe;
00299 }
00300 
00301 Boolean SUMA_cmap_wid_handleRedisplay(XtPointer clientData)
00302 {
00303    static char FuncName[]={"SUMA_cmap_wid_handleRedisplay"};
00304    SUMA_SurfaceObject *SO=NULL;
00305    SUMA_Boolean LocalHead = NOPE;
00306    
00307    SUMA_ENTRY;
00308    
00309    SUMA_LH("Called");
00310   
00311    SO = (SUMA_SurfaceObject *)clientData;
00312    if (!SO) { SUMA_SL_Err("NULL SO"); SUMA_RETURN(NOPE); }
00313    
00314    SUMA_LH("Making cmap_wid current");
00315    if (!glXMakeCurrent(XtDisplay(SO->SurfCont->cmp_ren->cmap_wid), XtWindow(SO->SurfCont->cmp_ren->cmap_wid), SO->SurfCont->cmp_ren->cmap_context)) {
00316       fprintf (SUMA_STDERR, "Error %s: Failed in glXMakeCurrent.\n \tContinuing ...\n", FuncName);
00317    }
00318    
00319    SUMA_cmap_wid_display(SO);
00320    glFinish();
00321    
00322    /* insist on a glXMakeCurrent for surface viewer */
00323    SUMA_LH("Making sv's GLXAREA current");
00324    SUMA_SiSi_I_Insist();
00325    
00326    SUMA_RETURN(YUP);
00327 }
00328 
00329 void SUMA_cmap_wid_postRedisplay(Widget w, XtPointer clientData, XtPointer call)
00330 {
00331    static char FuncName[]={"SUMA_cmap_wid_postRedisplay"};
00332    static XtPointer elvis;
00333    int isv;
00334    SUMA_SurfaceObject *SO=NULL;
00335    SUMA_Boolean LocalHead = NOPE;
00336    
00337    SUMA_ENTRY;
00338    
00339    SUMA_LH("cold");
00340    
00341    SO = (SUMA_SurfaceObject *)clientData;
00342    if (!SO) { SUMA_SL_Err("NULL SO"); SUMA_RETURNe; }
00343 
00344    SUMA_register_workproc( SUMA_cmap_wid_handleRedisplay , (XtPointer)SO );
00345    
00346    SUMA_RETURNe;
00347 }
00348 
00349 void SUMA_cmap_wid_expose(Widget w, XtPointer clientData, XtPointer call)
00350 {
00351    static char FuncName[]={"SUMA_cmap_wid_expose"};
00352    SUMA_SurfaceObject *SO=NULL;
00353    SUMA_Boolean LocalHead = NOPE;
00354    
00355    SUMA_ENTRY;
00356    
00357    SUMA_LH("called");
00358    SO = (SUMA_SurfaceObject *)clientData;
00359    if (!SO) { SUMA_SL_Err("NULL SO"); SUMA_RETURNe; }
00360    
00361    SUMA_cmap_wid_postRedisplay(w, (XtPointer)SO, NULL);
00362 
00363    SUMA_RETURNe;
00364 }
00365 
00366 void SUMA_cmap_wid_resize(Widget w, XtPointer clientData, XtPointer call)
00367 {
00368    static char FuncName[]={"SUMA_cmap_wid_resize"};
00369    SUMA_SurfaceObject *SO=NULL;
00370    SUMA_Boolean LocalHead = NOPE;
00371    
00372    SUMA_ENTRY;
00373    
00374    SUMA_LH("called");
00375    SO = (SUMA_SurfaceObject *)clientData;
00376    if (!SO) { SUMA_SL_Err("NULL SO"); SUMA_RETURNe; }
00377    
00378    SUMA_RETURNe;
00379 }
00380 
00381 void SUMA_cmap_wid_input(Widget w, XtPointer clientData, XtPointer callData)
00382 {
00383    static char FuncName[]={"SUMA_cmap_wid_input"};
00384    GLwDrawingAreaCallbackStruct *cd;
00385    KeySym keysym;
00386    XKeyEvent Kev;
00387    XButtonEvent Bev;
00388    XMotionEvent Mev;
00389    char buffer[10], cbuf = '\0', cbuf2='\0';
00390    SUMA_SurfaceObject *SO=NULL;
00391    int xls;
00392    static Time B1time = 0;
00393    static int pButton, mButton, rButton;
00394    static SUMA_Boolean DoubleClick = NOPE;
00395    DList *list = NULL;
00396    SUMA_EngineData *ED = NULL; 
00397    static float height_two_col, width;
00398    int ncol;
00399    SUMA_COLOR_MAP *ColMap = NULL;
00400    static float fov_lim = -1.0;
00401    static SUMA_SurfaceObject *SOcmap=NULL;
00402    SUMA_Boolean LocalHead = NOPE;
00403     
00404    SUMA_ENTRY;
00405    
00406    SUMA_LH("called");
00407    SO = (SUMA_SurfaceObject *)clientData;             /* THIS SO is for the main surface, NOT THE colormap's */
00408    if (!SO) { SUMA_SL_Err("NULL SO"); SUMA_RETURNe; }
00409    
00410    ColMap = SUMA_CmapOfPlane (SO->SurfCont->curColPlane );
00411    if (!ColMap) { SUMA_SL_Err("No Cmap"); SUMA_RETURNe; };
00412    if (ColMap->SO != SOcmap) {
00413       SUMA_LH("New colormap SO");
00414       /* calculate FOV limit for zooming in */
00415       SOcmap = ColMap->SO;
00416       ncol = SOcmap->N_FaceSet / 2;
00417       height_two_col = (SOcmap->MaxDims[1] - SOcmap->MinDims[1]) / (float)ncol * 2.0; /* no need to show more than 2 cols */
00418       width = (SOcmap->MaxDims[0] - SOcmap->MinDims[0]);
00419       fov_lim = 2.0 * atan( (double)height_two_col / ( 2.0 * (double)SUMA_CMAP_VIEW_FROM ) ) * 180 / SUMA_PI; 
00420       if (LocalHead) {
00421          SUMA_Print_Surface_Object(SOcmap, NULL);
00422          fprintf(SUMA_STDERR,"%s: ncol=%d, height = %f, height of 2 col =%f, width=%f, d = %d, fov_lim = %f\n", 
00423             FuncName, ncol, (SOcmap->MaxDims[1] - SOcmap->MinDims[1]), height_two_col,  width, SUMA_CMAP_VIEW_FROM, fov_lim);
00424       }
00425    }  
00426 
00427    /* make sure the color map is the current context */
00428    if (!glXMakeCurrent(XtDisplay(w), XtWindow(w), SO->SurfCont->cmp_ren->cmap_context)) {
00429       fprintf (SUMA_STDERR, "Error %s: Failed in glXMakeCurrent.\n ", FuncName);
00430       SUMA_RETURNe;
00431    }
00432 
00433    /* get the callData pointer */
00434    cd = (GLwDrawingAreaCallbackStruct *) callData;
00435 
00436    Kev = *(XKeyEvent *) &cd->event->xkey; /* RickR's suggestion to comply with ANSI C, no type casting of structures July 04*/
00437    Bev = *(XButtonEvent *) &cd->event->xbutton;
00438    Mev = *(XMotionEvent *) &cd->event->xmotion;
00439    
00440    switch (Kev.type) { /* switch event type */
00441    case KeyPress:
00442       xls = XLookupString((XKeyEvent *) cd->event, buffer, 8, &keysym, NULL);
00443       
00444       /* XK_* are found in keysymdef.h */ 
00445       switch (keysym) { /* keysym */
00446          case XK_r:
00447             {
00448                GLvoid *pixels;
00449                SUMA_LH("Recording");
00450                pixels = SUMA_grabPixels(1, SUMA_CMAP_WIDTH, SUMA_CMAP_HEIGHT);
00451                if (pixels) {
00452                  ISQ_snapsave (SUMA_CMAP_WIDTH, -SUMA_CMAP_HEIGHT, (unsigned char *)pixels, SO->SurfCont->cmp_ren->cmap_wid ); 
00453                  SUMA_free(pixels);
00454                }else {
00455                   SUMA_SLP_Err("Failed to record image.");
00456                }
00457             }
00458             break;
00459          case XK_h:
00460             if (Kev.state & ControlMask){
00461               if (!list) list = SUMA_CreateList();
00462               ED = SUMA_InitializeEngineListData (SE_Help_Cmap);
00463               SUMA_RegisterEngineListCommand ( list, ED,
00464                                          SEF_vp, (void *)ColMap,
00465                                          SES_SumaWidget, NULL, NOPE,
00466                                          SEI_Head, NULL); 
00467               if (!SUMA_Engine (&list)) {
00468                   fprintf(stderr, "Error %s: SUMA_Engine call failed.\n", FuncName);
00469               }    
00470             }
00471             break;
00472          case XK_Z:
00473             {
00474                static SUMA_Boolean BeepedAlready = NOPE;
00475                SO->SurfCont->cmp_ren->FOV /= FOV_IN_FACT; 
00476                if (SO->SurfCont->cmp_ren->FOV < fov_lim) { 
00477                   if (!BeepedAlready) {
00478                      SUMA_BEEP; BeepedAlready = YUP;
00479                   }
00480                   SO->SurfCont->cmp_ren->FOV = fov_lim; 
00481                } else BeepedAlready = NOPE;
00482                if (LocalHead) fprintf(SUMA_STDERR,"%s: Zoom in FOV = %f\n", FuncName, SO->SurfCont->cmp_ren->FOV);
00483                SUMA_cmap_wid_postRedisplay(w, (XtPointer)SO, NULL);
00484             }
00485             break;
00486 
00487          case XK_z:
00488             {
00489                static SUMA_Boolean BeepedAlready = NOPE;
00490                SO->SurfCont->cmp_ren->FOV /= FOV_OUT_FACT; 
00491                if (SO->SurfCont->cmp_ren->FOV > SUMA_CMAP_FOV_INITIAL) { 
00492                   if (!BeepedAlready) {
00493                      SUMA_BEEP; BeepedAlready = YUP;
00494                   }
00495                   SO->SurfCont->cmp_ren->FOV = SUMA_CMAP_FOV_INITIAL; 
00496                } else BeepedAlready = NOPE;
00497                if (LocalHead) fprintf(SUMA_STDERR,"%s: Zoom out FOV = %f\n", FuncName, SO->SurfCont->cmp_ren->FOV);
00498                SUMA_cmap_wid_postRedisplay(w, (XtPointer)SO, NULL);
00499             }
00500             break;
00501          case XK_Home:   
00502             SO->SurfCont->cmp_ren->FOV = SUMA_CMAP_FOV_INITIAL;
00503             SO->SurfCont->cmp_ren->translateVec[0] = SO->SurfCont->cmp_ren->translateVec[1] = SO->SurfCont->cmp_ren->translateVec[2] = 0.0;
00504             SUMA_cmap_wid_postRedisplay(w, (XtPointer)SO, NULL);
00505             break;
00506          case XK_Up:   /*KEY_UP:*/
00507             {
00508                static SUMA_Boolean BeepedAlready = NOPE;   
00509                float tstep = height_two_col / 2 * SO->SurfCont->cmp_ren->FOV/(float)SUMA_CMAP_FOV_INITIAL; 
00510                SO->SurfCont->cmp_ren->translateVec[1] += tstep ;
00511                if (LocalHead) fprintf(SUMA_STDERR,"%s: translateVec[1] = %f\n", FuncName, SO->SurfCont->cmp_ren->translateVec[1]);
00512                if (SO->SurfCont->cmp_ren->translateVec[1] >  SUMA_CMAP_HEIGHT - 20) {
00513                   if (!BeepedAlready) {
00514                      SUMA_BEEP; BeepedAlready = YUP;
00515                   }
00516                      SO->SurfCont->cmp_ren->translateVec[1] -= tstep; 
00517                } else BeepedAlready = NOPE;
00518                SUMA_cmap_wid_postRedisplay(w, (XtPointer)SO, NULL);
00519             }
00520             break;
00521          case XK_Down:   /*KEY_DOWN:*/
00522             {
00523                static SUMA_Boolean BeepedAlready = NOPE;  
00524                float tstep = height_two_col / 2 * SO->SurfCont->cmp_ren->FOV/(float)SUMA_CMAP_FOV_INITIAL; 
00525                SO->SurfCont->cmp_ren->translateVec[1] -=  tstep;
00526                if (SO->SurfCont->cmp_ren->translateVec[1] <  -SUMA_CMAP_HEIGHT + 20) {
00527                   if (!BeepedAlready) {
00528                      SUMA_BEEP; BeepedAlready = YUP;
00529                   }
00530                      SO->SurfCont->cmp_ren->translateVec[1] += tstep; 
00531                } else BeepedAlready = NOPE;
00532                SUMA_cmap_wid_postRedisplay(w, (XtPointer)SO, NULL);
00533             }
00534             break;
00535          
00536       } /* keysym */
00537    break;
00538    
00539    case ButtonPress:
00540       if (LocalHead) fprintf(stdout,"In ButtonPress\n");      
00541       pButton = Bev.button;
00542       if (SUMAg_CF->SwapButtons_1_3 || (SUMAg_CF->ROI_mode && SUMAg_CF->Pen_mode)) {
00543          if (pButton == Button1) pButton = Button3;
00544          else if (pButton == Button3) pButton = Button1;
00545       }
00546      
00547      /* trap for double click */
00548       if (Bev.time - B1time < SUMA_DOUBLE_CLICK_MAX_DELAY) {
00549          if (LocalHead) fprintf(SUMA_STDERR, "%s: Double click.\n", FuncName);
00550          DoubleClick = YUP;
00551       } else {
00552          DoubleClick = NOPE;
00553       }
00554       B1time = Bev.time; 
00555             
00556       switch (pButton) { /* switch type of button Press */
00557          case Button1:
00558             break;
00559          default:
00560             break;
00561       } /* switch type of button Press */
00562       break;
00563       
00564    case ButtonRelease:
00565       if (LocalHead) fprintf(SUMA_STDERR,"%s: In ButtonRelease\n", FuncName); 
00566       rButton = Bev.button;
00567       if (SUMAg_CF->SwapButtons_1_3 || (SUMAg_CF->ROI_mode && SUMAg_CF->Pen_mode)) {
00568          if (rButton == Button1) rButton = Button3;
00569          else if (rButton == Button3) rButton = Button1;
00570       }
00571       switch (rButton) { /* switch type of button Press */
00572          case Button3:
00573             break;
00574          default:
00575             break;
00576       } /* switch type of button Press */
00577       break;
00578       
00579    case MotionNotify:
00580       if (LocalHead) fprintf(stdout,"In MotionNotify\n"); 
00581       if (SUMAg_CF->SwapButtons_1_3 || (SUMAg_CF->ROI_mode && SUMAg_CF->Pen_mode)) {
00582         if (((Mev.state & Button3MotionMask) && (Mev.state & Button2MotionMask)) || ((Mev.state & Button2MotionMask) && (Mev.state & ShiftMask))) {
00583             mButton = SUMA_Button_12_Motion;
00584          } else if(Mev.state & Button3MotionMask) {
00585             mButton = SUMA_Button_1_Motion;
00586          }else if(Mev.state & Button2MotionMask) { 
00587             mButton = SUMA_Button_2_Motion;
00588          }else if(Mev.state & Button1MotionMask) { 
00589             mButton = SUMA_Button_3_Motion;
00590          }else {
00591             break;
00592          } 
00593       } else {
00594          if (((Mev.state & Button1MotionMask) && (Mev.state & Button2MotionMask)) || ((Mev.state & Button2MotionMask) && (Mev.state & ShiftMask))) {
00595             mButton = SUMA_Button_12_Motion;
00596          } else if(Mev.state & Button1MotionMask) {
00597             mButton = SUMA_Button_1_Motion;
00598          }else if(Mev.state & Button2MotionMask) { 
00599             mButton = SUMA_Button_2_Motion;
00600          } else if(Mev.state & Button3MotionMask) { 
00601             mButton = SUMA_Button_3_Motion;
00602          }else {
00603             break;
00604          }
00605       }
00606       
00607       switch (mButton) {
00608          case SUMA_Button_12_Motion:
00609          case SUMA_Button_2_Shift_Motion:
00610             break;
00611          default:
00612             break;
00613       }
00614       
00615       
00616       break;
00617   }/* switch event type */
00618 
00619   /* set up flag to make sure sv regains context */
00620   SUMA_SiSi_I_Insist();
00621    
00622   SUMA_RETURNe;
00623 }
00624 
00625 void SUMA_cb_set_threshold_label(Widget w, XtPointer clientData, XtPointer call)
00626 {
00627    static char FuncName[]={"SUMA_cb_set_threshold_label"};
00628    SUMA_SurfaceObject *SO=NULL;
00629    XmScaleCallbackStruct * cbs = (XmScaleCallbackStruct *) call ;
00630    float fff ;
00631    int dec;
00632    char slabel[100];
00633    SUMA_Boolean LocalHead = NOPE;
00634 
00635    SUMA_ENTRY;
00636    
00637    SUMA_LH("called");
00638    SO = (SUMA_SurfaceObject *)clientData;
00639    if (!SO) { SUMA_SL_Err("NULL SO"); SUMA_RETURNe; }
00640    
00641    XtVaGetValues(w, XmNuserData, &dec, NULL);
00642    if (SO->SurfCont->curColPlane->OptScl->ThrMode != SUMA_ABS_LESS_THAN) 
00643       sprintf(slabel, "%5s", MV_format_fval((float)cbs->value / pow(10.0, dec))); 
00644    else {
00645       /* used to use this:
00646       sprintf(slabel, "|%5s|", .... 
00647       but that does not work in the editable field ... */
00648       sprintf(slabel, "%5s", MV_format_fval((float)cbs->value / pow(10.0, dec))); 
00649    }
00650    /* SUMA_SET_LABEL(SO->SurfCont->thr_lb,  slabel);*/
00651       SUMA_INSERT_CELL_STRING(SO->SurfCont->SetThrScaleTable, 0,0,slabel); 
00652 
00653    
00654    /* You must use the line below if you are calling this function on the fly */
00655    /* SUMA_FORCE_SCALE_HEIGHT(SO);  */
00656    
00657    #if SUMA_SEPARATE_SURF_CONTROLLERS
00658       SUMA_UpdateColPlaneShellAsNeeded(SO);
00659    #endif
00660    
00661    SUMA_RETURNe;
00662 }
00663 
00664 void SUMA_cb_set_threshold(Widget w, XtPointer clientData, XtPointer call)
00665 {
00666    static char FuncName[]={"SUMA_cb_set_threshold"};
00667    SUMA_SurfaceObject *SO=NULL;
00668    XmScaleCallbackStruct * cbs = (XmScaleCallbackStruct *) call ;
00669    float fff ;
00670    int dec;
00671    SUMA_Boolean LocalHead = NOPE;
00672 
00673    SUMA_ENTRY;
00674    
00675    SUMA_LH("called");
00676    SO = (SUMA_SurfaceObject *)clientData;
00677    if (!SO) { SUMA_SL_Err("NULL SO"); SUMA_RETURNe; }
00678    XtVaGetValues(w, XmNuserData, &dec, NULL);
00679    SO->SurfCont->curColPlane->OptScl->ThreshRange[0] = (float)cbs->value / pow(10.0, dec); 
00680    if (LocalHead) {
00681       fprintf(SUMA_STDERR,"%s:\nThreshold set to %f\n",FuncName, SO->SurfCont->curColPlane->OptScl->ThreshRange[0]); 
00682    }
00683    
00684    if (SO->SurfCont->curColPlane->OptScl->UseThr && SO->SurfCont->curColPlane->OptScl->tind >=0) {
00685       SUMA_ColorizePlane(SO->SurfCont->curColPlane);
00686       SUMA_RemixRedisplay(SO);
00687    }
00688 
00689    /* call this one since it is not being called as the slider is dragged. */
00690    SUMA_cb_set_threshold_label(w, clientData, call);   
00691 
00692    /* sad as it is */
00693    SUMA_FORCE_SCALE_HEIGHT(SO); 
00694 
00695    #if SUMA_SEPARATE_SURF_CONTROLLERS
00696       SUMA_UpdateColPlaneShellAsNeeded(SO);
00697    #endif
00698    
00699    SUMA_UpdateNodeValField(SO);
00700    SUMA_UpdateNodeLblField(SO);
00701    
00702    SUMA_RETURNe;
00703 
00704 }
00705 
00706 void SUMA_cb_SwitchIntensity(Widget w, XtPointer client_data, XtPointer call)
00707 {
00708    static char FuncName[]={"SUMA_cb_SwitchIntensity"};
00709    int imenu = 0;
00710    char srange[500];
00711    SUMA_MenuCallBackData *datap=NULL;
00712    SUMA_SurfaceObject *SO = NULL;
00713    SUMA_Boolean LocalHead = NOPE;
00714    
00715    SUMA_ENTRY;
00716    
00717    /* get the surface object that the setting belongs to */
00718    datap = (SUMA_MenuCallBackData *)client_data;
00719    SO = (SUMA_SurfaceObject *)datap->ContID;
00720    imenu = (int)datap->callback_data; 
00721    
00722    if (!SO->SurfCont->curColPlane) { SUMA_RETURNe; }
00723    if (LocalHead) {
00724       fprintf(SUMA_STDERR, "%s:\n request to switch intensity to col. %d\n", FuncName, imenu - 1);
00725       fprintf(SUMA_STDERR, "SO->Label = %s\n", SO->Label);
00726    }
00727    
00728    SO->SurfCont->curColPlane->OptScl->find = imenu - 1;
00729 
00730    SUMA_InitRangeTable(SO, 0) ;
00731 
00732    if (!SO->SurfCont->curColPlane->Show) { SUMA_RETURNe; } /* nothing else to do */
00733    
00734    
00735    if (!SUMA_ColorizePlane (SO->SurfCont->curColPlane)) {
00736          SUMA_SLP_Err("Failed to colorize plane.\n");
00737          SUMA_RETURNe;
00738    }
00739    
00740    
00741    SUMA_RemixRedisplay(SO);
00742 
00743    #if SUMA_SEPARATE_SURF_CONTROLLERS
00744       SUMA_UpdateColPlaneShellAsNeeded(SO);
00745    #endif
00746  
00747    SUMA_UpdateNodeValField(SO);
00748    SUMA_UpdateNodeLblField(SO);
00749 
00750    SUMA_RETURNe;
00751 }
00752 
00753 void SUMA_cb_SwitchThreshold(Widget w, XtPointer client_data, XtPointer call)
00754 {
00755    static char FuncName[]={"SUMA_cb_SwitchThreshold"};
00756    int imenu = 0;
00757    char srange[500];
00758    SUMA_MenuCallBackData *datap=NULL;
00759    SUMA_SurfaceObject *SO = NULL;
00760    float range[2]; int loc[2];  
00761    SUMA_Boolean LocalHead = NOPE;
00762    
00763    SUMA_ENTRY;
00764    
00765    /* get the surface object that the setting belongs to */
00766    datap = (SUMA_MenuCallBackData *)client_data;
00767    SO = (SUMA_SurfaceObject *)datap->ContID;
00768    imenu = (int)datap->callback_data; 
00769    
00770    if (!SO->SurfCont->curColPlane) { SUMA_RETURNe; }
00771    
00772    if (LocalHead) {
00773       fprintf(SUMA_STDERR, "%s:\n request to switch threshold to col. %d\n", FuncName, imenu -1);
00774    }
00775    SO->SurfCont->curColPlane->OptScl->tind = imenu - 1;
00776    
00777    if (SUMA_GetDsetColRange(SO->SurfCont->curColPlane->dset_link, SO->SurfCont->curColPlane->OptScl->tind, range, loc)) {   
00778       SUMA_SetScaleRange(SO, range );
00779    }else {
00780       SUMA_SLP_Err("Failed to get range");
00781       SUMA_RETURNe;
00782    }
00783     
00784    SUMA_InitRangeTable(SO, -1) ;
00785    
00786    SUMA_UpdateNodeValField(SO);
00787    
00788    if (!SO->SurfCont->curColPlane->OptScl->UseThr) { SUMA_RETURNe; } /* nothing else to do */
00789 
00790    if (!SUMA_ColorizePlane (SO->SurfCont->curColPlane)) {
00791          SUMA_SLP_Err("Failed to colorize plane.\n");
00792          SUMA_RETURNe;
00793    }
00794    
00795    SUMA_RemixRedisplay(SO);
00796 
00797    #if SUMA_SEPARATE_SURF_CONTROLLERS
00798       SUMA_UpdateColPlaneShellAsNeeded(SO);
00799    #endif
00800    
00801    SUMA_UpdateNodeLblField(SO);
00802    
00803    SUMA_RETURNe;
00804 }
00805 
00806 void SUMA_cb_SwitchBrightness(Widget w, XtPointer client_data, XtPointer call)
00807 {
00808    static char FuncName[]={"SUMA_cb_SwitchBrightness"};
00809    int imenu = 0;
00810    SUMA_MenuCallBackData *datap=NULL;
00811    SUMA_SurfaceObject *SO = NULL;
00812    SUMA_Boolean LocalHead = NOPE;
00813    
00814    SUMA_ENTRY;
00815    
00816    /* get the surface object that the setting belongs to */
00817    datap = (SUMA_MenuCallBackData *)client_data;
00818    SO = (SUMA_SurfaceObject *)datap->ContID;
00819    imenu = (int)datap->callback_data; 
00820    
00821    if (LocalHead) {
00822       fprintf(SUMA_STDERR, "%s:\n request to switch brightness to col. %d\n", FuncName, imenu - 1);
00823    }
00824    
00825    SO->SurfCont->curColPlane->OptScl->bind = imenu - 1;
00826 
00827    SUMA_InitRangeTable(SO, 1) ;
00828 
00829    SUMA_UpdateNodeValField(SO);
00830    if (!SO->SurfCont->curColPlane->OptScl->UseBrt) { SUMA_RETURNe; } /* nothing else to do */
00831    
00832    if (!SUMA_ColorizePlane (SO->SurfCont->curColPlane)) {
00833          SUMA_SLP_Err("Failed to colorize plane.\n");
00834          SUMA_RETURNe;
00835    }
00836    
00837 
00838    SUMA_RemixRedisplay(SO);
00839    
00840    #if SUMA_SEPARATE_SURF_CONTROLLERS
00841       SUMA_UpdateColPlaneShellAsNeeded(SO);
00842    #endif
00843    
00844    SUMA_UpdateNodeLblField(SO);
00845 
00846    SUMA_RETURNe;
00847 }
00848 /*! 
00849    \brief function that handlges switching colormap from the menu widget
00850    \sa SUMA_cb_SelectSwitchCmap 
00851 */ 
00852 void SUMA_cb_SwitchCmap(Widget w, XtPointer client_data, XtPointer call)
00853 {
00854    static char FuncName[]={"SUMA_cb_SwitchCmap"};
00855    SUMA_MenuCallBackData *datap=NULL;
00856    SUMA_SurfaceObject *SO = NULL;
00857    SUMA_COLOR_MAP *CM = NULL;
00858    SUMA_Boolean LocalHead = NOPE;
00859    
00860    SUMA_ENTRY;
00861    
00862    /* get the surface object that the setting belongs to */
00863    datap = (SUMA_MenuCallBackData *)client_data;
00864    SO = (SUMA_SurfaceObject *)datap->ContID;
00865    CM = (SUMA_COLOR_MAP *)datap->callback_data; 
00866    
00867    if (LocalHead) {
00868       fprintf(SUMA_STDERR, "%s:\n request to switch colormap to  (%s)\n", 
00869          FuncName, CM->Name);
00870    }
00871    
00872    if (!SUMA_SwitchColPlaneCmap(SO, CM)) {
00873       SUMA_SL_Err("Failed in SUMA_SwitchColPlaneCmap");
00874    }
00875    
00876    /* Now you'll need to close the list widget if a choice has been made */
00877    if (SUMAg_CF->X->SwitchCmapLst) {
00878       if (!SUMAg_CF->X->SwitchCmapLst->isShaded) 
00879          SUMA_cb_CloseSwitchCmap( w,  (XtPointer)SUMAg_CF->X->SwitchCmapLst,  call);
00880    }
00881    
00882    #if SUMA_SEPARATE_SURF_CONTROLLERS
00883       SUMA_UpdateColPlaneShellAsNeeded(SO);
00884    #endif
00885    
00886    /* update Lbl fields */
00887    SUMA_UpdateNodeLblField(SO);
00888 
00889    SUMA_RETURNe;
00890 }
00891 
00892 void SUMA_cb_ShowZero_tb_toggled (Widget w, XtPointer data, XtPointer client_data)
00893 {
00894    static char FuncName[]={"SUMA_cb_SymIrange_tb_toggled"};
00895    SUMA_SurfaceObject *SO = NULL;
00896    SUMA_TABLE_FIELD *TF=NULL;
00897    SUMA_Boolean LocalHead = NOPE;
00898    
00899    SUMA_ENTRY;
00900    
00901    SUMA_LH("Called");
00902    
00903    SO = (SUMA_SurfaceObject *)data;
00904    
00905    if (!SO->SurfCont->curColPlane) SUMA_RETURNe;
00906    
00907    SO->SurfCont->curColPlane->OptScl->MaskZero = !SO->SurfCont->curColPlane->OptScl->MaskZero;
00908    
00909    if (!SO->SurfCont->curColPlane->Show) { SUMA_RETURNe; } /* nothing else to do */
00910    
00911    if (!SUMA_ColorizePlane (SO->SurfCont->curColPlane)) {
00912          SUMA_SLP_Err("Failed to colorize plane.\n");
00913          SUMA_RETURNe;
00914    }
00915    
00916    SUMA_RemixRedisplay(SO);
00917  
00918    SUMA_UpdateNodeLblField(SO);
00919    
00920 
00921 }
00922  
00923 
00924 void SUMA_cb_SymIrange_tb_toggled (Widget w, XtPointer data, XtPointer client_data)
00925 {
00926    static char FuncName[]={"SUMA_cb_SymIrange_tb_toggled"};
00927    SUMA_SurfaceObject *SO = NULL;
00928    SUMA_TABLE_FIELD *TF=NULL;
00929    SUMA_Boolean LocalHead = NOPE;
00930    
00931    SUMA_ENTRY;
00932    
00933    SUMA_LH("Called");
00934    
00935    SO = (SUMA_SurfaceObject *)data;
00936    
00937    if (!SO->SurfCont->curColPlane) SUMA_RETURNe;
00938    
00939    SO->SurfCont->curColPlane->SymIrange = !SO->SurfCont->curColPlane->SymIrange;
00940    
00941    if (SO->SurfCont->curColPlane->SymIrange) {
00942       /* manual setting of range. DO NOT Call SUMA_InitRangeTable because it will automatically update the I range under certain conditions*/
00943       TF = SO->SurfCont->SetRangeTable;
00944       SO->SurfCont->curColPlane->OptScl->IntRange[1] = 
00945          SUMA_LARG_ABS(SO->SurfCont->curColPlane->OptScl->IntRange[0], SO->SurfCont->curColPlane->OptScl->IntRange[1]);
00946       SO->SurfCont->curColPlane->OptScl->IntRange[0] = -SO->SurfCont->curColPlane->OptScl->IntRange[1];
00947       SUMA_INSERT_CELL_VALUE(TF, 1, 1, SO->SurfCont->curColPlane->OptScl->IntRange[0]);
00948       SUMA_INSERT_CELL_VALUE(TF, 1, 2, SO->SurfCont->curColPlane->OptScl->IntRange[1]);
00949    }
00950    
00951    if (!SO->SurfCont->curColPlane->Show) { SUMA_RETURNe; } /* nothing else to do */
00952    
00953    
00954    if (!SUMA_ColorizePlane (SO->SurfCont->curColPlane)) {
00955          SUMA_SLP_Err("Failed to colorize plane.\n");
00956          SUMA_RETURNe;
00957    }
00958    
00959    SUMA_RemixRedisplay(SO);
00960  
00961    SUMA_UpdateNodeValField(SO);
00962    SUMA_UpdateNodeLblField(SO);
00963    
00964 
00965    SUMA_RETURNe;
00966 }
00967 
00968 void SUMA_cb_AbsThresh_tb_toggled (Widget w, XtPointer data, XtPointer client_data)
00969 {
00970    static char FuncName[]={"SUMA_cb_AbsThresh_tb_toggled"};
00971    SUMA_SurfaceObject *SO = NULL;
00972    char slabel[100];
00973    float range[2]; int loc[2];  
00974    SUMA_Boolean LocalHead = NOPE;
00975    
00976    SUMA_ENTRY;
00977    
00978    SUMA_LH("Called");
00979    
00980    SO = (SUMA_SurfaceObject *)data;
00981    
00982    if (!SO->SurfCont->curColPlane) SUMA_RETURNe;
00983 
00984    if (SO->SurfCont->curColPlane->OptScl->ThrMode != SUMA_ABS_LESS_THAN) {
00985       SO->SurfCont->curColPlane->OptScl->ThrMode = SUMA_ABS_LESS_THAN;
00986       /* used to use this:
00987       sprintf(slabel, "|%5s|", .... 
00988       but that does not work in the editable field ... */
00989       sprintf(slabel, "%5s", MV_format_fval(fabs(SO->SurfCont->curColPlane->OptScl->ThreshRange[0])));
00990    } else {
00991       SO->SurfCont->curColPlane->OptScl->ThrMode = SUMA_LESS_THAN;
00992       sprintf(slabel, "%5s", MV_format_fval(SO->SurfCont->curColPlane->OptScl->ThreshRange[0]));
00993    }
00994    /* SUMA_SET_LABEL(SO->SurfCont->thr_lb,  slabel); */
00995    SUMA_INSERT_CELL_STRING(SO->SurfCont->SetThrScaleTable, 0,0,slabel); 
00996    if (SUMA_GetDsetColRange(SO->SurfCont->curColPlane->dset_link, SO->SurfCont->curColPlane->OptScl->tind, range, loc)) {   
00997       SUMA_SetScaleRange(SO, range );
00998    }else {
00999       SUMA_SLP_Err("Failed to get range");
01000       SUMA_RETURNe;
01001    }
01002       
01003    if (!SO->SurfCont->curColPlane->OptScl->UseThr) { SUMA_RETURNe; } /* nothing else to do */
01004 
01005    if (!SUMA_ColorizePlane (SO->SurfCont->curColPlane)) {
01006          SUMA_SLP_Err("Failed to colorize plane.\n");
01007          SUMA_RETURNe;
01008    }
01009    
01010    SUMA_RemixRedisplay(SO);
01011 
01012    SUMA_UpdateNodeLblField(SO);
01013 
01014    SUMA_RETURNe;
01015 }
01016 
01017 void SUMA_cb_SwithInt_toggled (Widget w, XtPointer data, XtPointer client_data)
01018 {
01019    static char FuncName[]={"SUMA_cb_SwithInt_toggled"};
01020    SUMA_SurfaceObject *SO = NULL;
01021    SUMA_Boolean LocalHead = NOPE;
01022    
01023    SUMA_ENTRY;
01024    
01025    SUMA_LH("Called");
01026    
01027    SO = (SUMA_SurfaceObject *)data;
01028    
01029    if (!SO->SurfCont->curColPlane) SUMA_RETURNe;
01030 
01031    /* make sure ok to turn on */
01032    if (SO->SurfCont->curColPlane->OptScl->find < 0) {
01033       SUMA_BEEP;
01034       SUMA_SLP_Note("no intensity column set");
01035       XmToggleButtonSetState (SO->SurfCont->Int_tb, NOPE, NOPE);
01036       SUMA_RETURNe;
01037    }
01038       
01039    /* this button's the same as the Show button */
01040    SO->SurfCont->curColPlane->Show = XmToggleButtonGetState (SO->SurfCont->Int_tb);
01041    XmToggleButtonSetState (SO->SurfCont->ColPlaneShow_tb, SO->SurfCont->curColPlane->Show, NOPE);
01042    
01043    SUMA_ColorizePlane(SO->SurfCont->curColPlane);
01044    SUMA_RemixRedisplay(SO);
01045    SUMA_UpdateNodeLblField(SO);
01046 
01047    #if SUMA_SEPARATE_SURF_CONTROLLERS
01048       SUMA_UpdateColPlaneShellAsNeeded(SO);
01049    #endif
01050    SUMA_RETURNe;
01051 }
01052 
01053 void SUMA_cb_SwithThr_toggled (Widget w, XtPointer data, XtPointer client_data)
01054 {
01055    static char FuncName[]={"SUMA_cb_SwithThr_toggled"};
01056    SUMA_SurfaceObject *SO = NULL;
01057    SUMA_Boolean LocalHead = NOPE;
01058    
01059    SUMA_ENTRY;
01060    
01061    SUMA_LH("Called");
01062    
01063    SO = (SUMA_SurfaceObject *)data;
01064    
01065    if (!SO->SurfCont->curColPlane) SUMA_RETURNe;
01066    
01067    /* make sure ok to turn on */
01068    if (SO->SurfCont->curColPlane->OptScl->tind < 0) {
01069       SUMA_BEEP;
01070       SUMA_SLP_Note("no threshold column set");
01071       XmToggleButtonSetState (SO->SurfCont->Thr_tb, NOPE, NOPE);
01072       SUMA_RETURNe;
01073    }
01074       
01075    SO->SurfCont->curColPlane->OptScl->UseThr = XmToggleButtonGetState (SO->SurfCont->Thr_tb);
01076       
01077    SUMA_ColorizePlane(SO->SurfCont->curColPlane);
01078    SUMA_RemixRedisplay(SO);
01079    
01080    SUMA_UpdateNodeLblField(SO);
01081    
01082    #if SUMA_SEPARATE_SURF_CONTROLLERS
01083       SUMA_UpdateColPlaneShellAsNeeded(SO);
01084    #endif
01085    SUMA_RETURNe;
01086 }
01087 
01088 void SUMA_cb_SwithBrt_toggled (Widget w, XtPointer data, XtPointer client_data)
01089 {
01090    static char FuncName[]={"SUMA_cb_SwithBrt_toggled"};
01091    SUMA_SurfaceObject *SO = NULL;
01092    SUMA_Boolean LocalHead = NOPE;
01093    
01094    SUMA_ENTRY;
01095    
01096    SUMA_LH("Called");
01097    
01098    SO = (SUMA_SurfaceObject *)data;
01099    
01100    if (!SO->SurfCont->curColPlane) SUMA_RETURNe;
01101    
01102    /* make sure ok to turn on */
01103    if (SO->SurfCont->curColPlane->OptScl->bind < 0) {
01104       SUMA_BEEP;
01105       SUMA_SLP_Note("no brightness column set");
01106       XmToggleButtonSetState (SO->SurfCont->Brt_tb, NOPE, NOPE);
01107       SUMA_RETURNe;
01108    }
01109    
01110    SO->SurfCont->curColPlane->OptScl->UseBrt = XmToggleButtonGetState (SO->SurfCont->Brt_tb);
01111    
01112    SUMA_ColorizePlane(SO->SurfCont->curColPlane);
01113    SUMA_RemixRedisplay(SO);
01114    SUMA_UpdateNodeLblField(SO);
01115 
01116    #if SUMA_SEPARATE_SURF_CONTROLLERS
01117       SUMA_UpdateColPlaneShellAsNeeded(SO);
01118    #endif
01119    SUMA_RETURNe;
01120 }
01121 
01122 SUMA_MenuItem CoordBias_Menu[] = {
01123    {  "-", &xmPushButtonWidgetClass, 
01124       '\0', NULL, NULL, 
01125       SUMA_cb_SetCoordBias, (XtPointer) SW_CoordBias_None, NULL},
01126       
01127    {  "x", &xmPushButtonWidgetClass, 
01128       '\0', NULL, NULL, 
01129       SUMA_cb_SetCoordBias, (XtPointer) SW_CoordBias_X, NULL},
01130    
01131    {  "y", &xmPushButtonWidgetClass, 
01132       '\0', NULL, NULL, 
01133       SUMA_cb_SetCoordBias, (XtPointer) SW_CoordBias_Y, NULL},
01134     
01135    {  "z", &xmPushButtonWidgetClass, 
01136       '\0', NULL, NULL, 
01137       SUMA_cb_SetCoordBias, (XtPointer) SW_CoordBias_Z, NULL},
01138         
01139    {  "n", &xmPushButtonWidgetClass, 
01140       '\0', NULL, NULL, 
01141       SUMA_cb_SetCoordBias, (XtPointer) SW_CoordBias_N, NULL},
01142    
01143    {NULL},
01144 };
01145 
01146 SUMA_MenuItem CmapMode_Menu[] = {
01147    {  "Int", &xmPushButtonWidgetClass, 
01148       '\0', NULL, NULL, 
01149       SUMA_cb_SetCmapMode, (XtPointer) SW_Interp, NULL},
01150       
01151    {  "NN", &xmPushButtonWidgetClass, 
01152       '\0', NULL, NULL, 
01153       SUMA_cb_SetCmapMode, (XtPointer) SW_NN, NULL},
01154    
01155    {  "Dir", &xmPushButtonWidgetClass, 
01156       '\0', NULL, NULL, 
01157       SUMA_cb_SetCmapMode, (XtPointer) SW_Direct, NULL},
01158     
01159    {NULL},
01160 };
01161 
01162 /*!
01163    \brief sets the colormap interpolation mode
01164    - expects a SUMA_MenuCallBackData * in  client_data
01165    with SO as client_data->ContID and Menubutton in client_data->callback_data
01166 */
01167 void SUMA_cb_SetCmapMode(Widget widget, XtPointer client_data, XtPointer call_data)
01168 {
01169    static char FuncName[]={"SUMA_cb_SetCmapMode"};
01170    SUMA_MenuCallBackData *datap=NULL;
01171    int imenu;
01172    SUMA_SurfaceObject *SO = NULL;
01173    SUMA_Boolean NewDisp = NOPE;
01174    SUMA_Boolean LocalHead = NOPE;
01175    
01176    SUMA_ENTRY;
01177    
01178    /* get the surface object that the setting belongs to */
01179    datap = (SUMA_MenuCallBackData *)client_data;
01180    SO = (SUMA_SurfaceObject *)datap->ContID;
01181    imenu = (int)datap->callback_data; 
01182    NewDisp = NOPE;
01183    switch (imenu) {
01184       case SW_Interp:
01185          if (SO->SurfCont->curColPlane->OptScl->interpmode != SUMA_INTERP) {
01186             SO->SurfCont->curColPlane->OptScl->interpmode = SUMA_INTERP;
01187             NewDisp = YUP;
01188          }
01189          break;
01190       case SW_NN:
01191          if (SO->SurfCont->curColPlane->OptScl->interpmode != SUMA_NO_INTERP) {
01192             SO->SurfCont->curColPlane->OptScl->interpmode = SUMA_NO_INTERP;
01193             NewDisp = YUP;
01194          }
01195          break;
01196       case SW_Direct:
01197          if (SO->SurfCont->curColPlane->OptScl->interpmode != SUMA_DIRECT) {
01198             SO->SurfCont->curColPlane->OptScl->interpmode = SUMA_DIRECT;
01199             NewDisp = YUP;
01200          }
01201          break;
01202       default: 
01203          fprintf (SUMA_STDERR, "Error %s: Unexpected widget index.\n", FuncName);
01204          break;
01205    }
01206    
01207    /* redisplay all viewers showing SO*/
01208    if (NewDisp) {
01209       SUMA_ColorizePlane(SO->SurfCont->curColPlane);
01210       SUMA_RemixRedisplay(SO);
01211    }
01212    
01213    SUMA_UpdateNodeNodeField(SO);
01214    SUMA_UpdateNodeLblField(SO);
01215    
01216    SUMA_RETURNe;
01217 }
01218 
01219 /*!
01220    \brief sets the coordinate bias mode
01221    - expects a SUMA_MenuCallBackData * in  client_data
01222    with SO as client_data->ContID and Menubutton in client_data->callback_data
01223 */
01224 void SUMA_cb_SetCoordBias(Widget widget, XtPointer client_data, XtPointer call_data)
01225 {
01226    static char FuncName[]={"SUMA_cb_SetCoordBias"};
01227    SUMA_MenuCallBackData *datap=NULL;
01228    int imenu;
01229    SUMA_SurfaceObject *SO = NULL;
01230    SUMA_Boolean NewDisp = NOPE;
01231    SUMA_Boolean LocalHead = NOPE;
01232    
01233    SUMA_ENTRY;
01234    
01235    /* get the surface object that the setting belongs to */
01236    datap = (SUMA_MenuCallBackData *)client_data;
01237    SO = (SUMA_SurfaceObject *)datap->ContID;
01238    imenu = (int)datap->callback_data; 
01239    NewDisp = NOPE;
01240    switch (imenu) {
01241       case SW_CoordBias_None:
01242          if (SO->SurfCont->curColPlane->OptScl->DoBias != SW_CoordBias_None) {
01243             if (SO->SurfCont->curColPlane->OptScl->BiasVect) {
01244                SUMA_RemoveCoordBias(SO->SurfCont->curColPlane);
01245             }
01246             NewDisp = YUP;
01247          }
01248          break;
01249       case SW_CoordBias_X:
01250          if (SO->SurfCont->curColPlane->OptScl->DoBias != SW_CoordBias_X) { /* something needs to be done */
01251                /* bias other than on other dimension exists, transfer it to new dimension*/
01252                SUMA_TransferCoordBias(SO->SurfCont->curColPlane, SW_CoordBias_X);
01253             NewDisp = YUP;
01254          }
01255          break;
01256       case SW_CoordBias_Y:
01257          if (SO->SurfCont->curColPlane->OptScl->DoBias != SW_CoordBias_Y) { /* something needs to be done */
01258                /* bias other than on other dimension exists, transfer it to new dimension*/
01259                SUMA_TransferCoordBias(SO->SurfCont->curColPlane, SW_CoordBias_Y);
01260             NewDisp = YUP;
01261          }
01262          break;
01263       case SW_CoordBias_Z:
01264          if (SO->SurfCont->curColPlane->OptScl->DoBias != SW_CoordBias_Z) { /* something needs to be done */
01265                /* bias other than on other dimension exists, transfer it to new dimension*/
01266                SUMA_TransferCoordBias(SO->SurfCont->curColPlane, SW_CoordBias_Z);
01267             NewDisp = YUP;
01268          }
01269          break;
01270       case SW_CoordBias_N:
01271          if (SO->SurfCont->curColPlane->OptScl->DoBias != SW_CoordBias_N) { /* something needs to be done */
01272                /* bias other than on other dimension exists, transfer it to new dimension*/
01273                SUMA_TransferCoordBias(SO->SurfCont->curColPlane, SW_CoordBias_N);
01274             NewDisp = YUP;
01275          }
01276          break;
01277       default: 
01278          fprintf (SUMA_STDERR, "Error %s: Unexpected widget index.\n", FuncName);
01279          break;
01280    }
01281    
01282    /* redisplay all viewers showing SO*/
01283    if (NewDisp) {
01284       SUMA_ColorizePlane(SO->SurfCont->curColPlane);
01285       SUMA_RemixRedisplay(SO);
01286    }
01287    
01288    SUMA_UpdateNodeNodeField(SO);
01289    
01290    #if SUMA_SEPARATE_SURF_CONTROLLERS
01291       SUMA_UpdateColPlaneShellAsNeeded(SO);
01292    #endif
01293    SUMA_RETURNe;
01294 }
01295 
01296 /*!
01297    \brief Function to call a redisplay of all viewers showing SO 
01298 */
01299 SUMA_Boolean SUMA_RedisplayAllShowing(char *SO_idcode_str, SUMA_SurfaceViewer *SVv, int N_SVv)
01300 {
01301    static char FuncName[]={"SUMA_RedisplayAllShowing"};
01302    SUMA_SurfaceViewer *sv;
01303    SUMA_SurfaceObject *SO1 = NULL, *SO2 = NULL;
01304    int i, k, dov_id;   
01305    DList *list=NULL;
01306    SUMA_Boolean LocalHead = NOPE;
01307    
01308    SUMA_ENTRY;
01309    
01310    if (!SO_idcode_str || !SVv) {
01311       fprintf (SUMA_STDERR,"Error %s: NULL SVv or SO_idcode_str. BAD\n", FuncName);
01312       SUMA_RETURN (NOPE);
01313    }
01314    dov_id = SUMA_findSO_inDOv (SO_idcode_str, SUMAg_DOv, SUMAg_N_DOv);
01315    if (dov_id < 0) {
01316       fprintf (SUMA_STDERR,"Error %s: Failed to find object with idcode %s.\n", FuncName, SO_idcode_str);
01317       SUMA_RETURN (NOPE);
01318    }
01319    SO1 = (SUMA_SurfaceObject *)SUMAg_DOv[dov_id].OP;
01320 
01321    /* search all viewers */
01322    for (i=0; i < N_SVv; ++i) {
01323       if (LocalHead) fprintf (SUMA_STDERR,"%s: Searching viewer %d.\n", FuncName, i);
01324       sv = &(SVv[i]);
01325       /* search for SO in RegisteredDO */
01326       for (k=0; k < sv->N_DO; ++k) {
01327          if (SUMA_isSO(SUMAg_DOv[sv->RegisteredDO[k]])) {
01328             SO2 = (SUMA_SurfaceObject *)SUMAg_DOv[sv->RegisteredDO[k]].OP;
01329             if (SUMA_WhatAreYouToMe(SO1, SO2) == SUMA_SO1_is_SO2) { /* same surface */
01330                /* Get a redisplay for that puppy */
01331                if (!list) list = SUMA_CreateList ();
01332                SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_Redisplay, SES_SumaWidget, sv);
01333             }
01334          }  
01335       } 
01336    }
01337    
01338    if (!SUMA_Engine(&list)) {
01339       SUMA_SLP_Err("Failed to redisplay.");
01340       SUMA_RETURN(NOPE);
01341    }
01342    
01343    SUMA_RETURN(YUP);
01344 }
01345 
01346 SUMA_TABLE_FIELD * SUMA_AllocTableField(void)
01347 {
01348    static char FuncName[]={"SUMA_AllocTableField"};
01349    SUMA_TABLE_FIELD *TF = NULL;
01350 
01351    SUMA_ENTRY;
01352    TF = (SUMA_TABLE_FIELD *)SUMA_malloc(sizeof(SUMA_TABLE_FIELD));
01353    if (!TF) {
01354       SUMA_SL_Crit("Failed to allocate");
01355       SUMA_RETURN(TF);
01356    }
01357    TF->Ni = -1;
01358    TF->Nj = -1;
01359    TF->rc = NULL;
01360    TF->cells = NULL;
01361    TF->cwidth = NULL;
01362    TF->editable = NOPE;
01363    TF->type = SUMA_string;
01364    TF->NewValueCallback = NULL;
01365    TF->NewValueCallbackData = NULL;
01366    TF->TitLabelEVHandler = NULL;
01367    TF->TitLabelEVHandlerData = NULL;
01368    TF->CellEVHandler = NULL;
01369    TF->CellEVHandlerData = NULL;
01370    TF->cell_modified = -1;
01371    TF->num_value = NULL;
01372    TF->str_value = NULL;
01373    SUMA_RETURN(TF);
01374 }
01375 
01376 /*!
01377    Called when user clicks on range table cell
01378    Expect SO in cd
01379 */
01380 void SUMA_RangeTableCell_EV ( Widget w , XtPointer cd ,
01381                       XEvent *ev , Boolean *continue_to_dispatch )
01382 {
01383    static char FuncName[]={"SUMA_RangeTableCell_EV"};
01384    SUMA_SurfaceObject *SO = (SUMA_SurfaceObject *)cd;
01385    SUMA_SurfaceObject *curSO = *(SO->SurfCont->curSOp);
01386    SUMA_TABLE_FIELD *TF = SO->SurfCont->RangeTable;
01387    XButtonEvent * bev = (XButtonEvent *) ev ;
01388    int  i, j, n, Found;
01389    void *cv=NULL;
01390    SUMA_Boolean LocalHead = NOPE;
01391    
01392    SUMA_ENTRY;
01393    
01394    SUMA_LH("Called");
01395    
01396    /* see note in bbox.c optmenu_EV for the condition below*/
01397    if( bev->button == Button2 ) {
01398      XUngrabPointer( bev->display , CurrentTime ) ;
01399      SUMA_RETURNe ;
01400    }
01401    
01402    if( w == NULL || TF == NULL || SO == NULL ) { SUMA_RETURNe ; }
01403 
01404    switch (bev->button) {
01405       case Button1:
01406          SUMA_LH("Button 1");
01407          break;
01408       case Button2:
01409          SUMA_LH("Button 2");
01410          break;
01411       case Button3:
01412          SUMA_LH("Button 3");
01413          break;
01414       default:
01415          SUMA_RETURNe;
01416    }
01417    
01418    /* which cell is calling? */
01419    n = 0;
01420    Found = -1;
01421    while (n<TF->Nj*TF->Ni && Found == -1) {
01422       if (TF->cells[n] == w) {
01423          Found = n;
01424       } else ++n;
01425    }
01426    
01427    if (Found <0) {
01428       SUMA_SL_Err("Widget not found ????");
01429       SUMA_RETURNe;
01430    }
01431    
01432    /* find out widget's place in table*/
01433    i = Found % TF->Ni; j = Found / TF->Ni ;
01434    n = Found; 
01435    
01436    switch (j) {
01437       case 0:
01438       case 1:
01439       case 3:
01440          break;
01441       case 2:
01442       case 4:
01443          SUMA_LH("Call to jump to a node");
01444          XtVaGetValues(TF->cells[n], XmNvalue, &cv, NULL);
01445          if (LocalHead) {
01446             fprintf(SUMA_STDERR,"%s:\nTable cell[%d, %d]=%s, node = %d\n", 
01447                   FuncName, i, j, (char *)cv, atoi((char *)cv));
01448          }
01449          /* look for a viewer that is showing this surface and has this surface in focus*/
01450          for (i=0; i<SUMAg_N_SVv; ++i) {
01451             if (LocalHead) fprintf (SUMA_STDERR,"%s: Checking viewer %d.\n", FuncName, i);
01452             if (!SUMAg_SVv[i].isShaded && SUMAg_SVv[i].X->TOPLEVEL) {
01453                /* is this viewer showing curSO ? */
01454                if (SUMA_isVisibleSO(&(SUMAg_SVv[i]), SUMAg_DOv, curSO)) {
01455                   if ((SUMAg_DOv[SUMAg_SVv[i].Focus_SO_ID].OP) == curSO) {
01456                         SUMA_JumpIndex((char *)cv, (void *)(&(SUMAg_SVv[i])));
01457                   }
01458                }
01459             }
01460          }
01461 
01462          break;
01463       default:
01464          SUMA_SL_Err("Did not know you had so many");
01465          break;
01466    }
01467    
01468    SUMA_RETURNe;
01469 }
01470 /*!
01471    Called when user clicks on table title 
01472    Expects SO in TF->NewValueCallbackData
01473 */
01474 void SUMA_SetRangeTableTit_EV ( Widget w , XtPointer cd ,
01475                       XEvent *ev , Boolean *continue_to_dispatch )
01476 {
01477    static char FuncName[]={"SUMA_SetRangeTableTit_EV"};
01478    Dimension lw ;
01479    Widget * children , wl = NULL;
01480    XButtonEvent * bev = (XButtonEvent *) ev ;
01481    int  num_children , i, j, Found, AutoHist;
01482    SUMA_TABLE_FIELD *TF = (SUMA_TABLE_FIELD *)cd;
01483    SUMA_SurfaceObject *SO = (SUMA_SurfaceObject *)TF->NewValueCallbackData;
01484    SUMA_Boolean LocalHead = NOPE;
01485    
01486    SUMA_ENTRY;
01487    
01488    SUMA_LH("Called");
01489    
01490    /* see note in bbox.c optmenu_EV for the condition below*/
01491    if( bev->button == Button2 ){
01492      XUngrabPointer( bev->display , CurrentTime ) ;
01493      SUMA_RETURNe ;
01494    }
01495    
01496    if( w == NULL || TF == NULL ) SUMA_RETURNe ;
01497 
01498    switch (bev->button) {
01499       case Button1:
01500          SUMA_LH("Button 1");
01501          break;
01502       case Button2:
01503          SUMA_LH("Button 2");
01504          break;
01505       case Button3:
01506          SUMA_LH("Button 3");
01507          break;
01508       default:
01509          SUMA_RETURNe;
01510    }
01511    
01512    /* which column title (i == 0) widget is calling ? */
01513    /* check the first column */
01514    i = 0; j = 0;
01515    Found = 0;
01516    while (j<TF->Nj && !Found) {
01517       if (TF->cells[j*TF->Ni+i] == w) {
01518          Found = 1;
01519       } else ++j;
01520    }
01521    
01522    if (!Found) { /* maybe it is a row title */
01523       i = 0; j = 0;
01524       Found = 0;
01525       while (i<TF->Ni && !Found) {
01526          if (TF->cells[j*TF->Ni+i] == w) {
01527             Found = 1;
01528          } else ++i;
01529       }
01530    }
01531    
01532    if (Found >= 0) {
01533       if (LocalHead) fprintf(SUMA_STDERR,"%s: Click on cell [%d %d]\n", FuncName, i, j);
01534    } else {
01535       SUMA_SL_Err("CEll not found!");
01536       SUMA_RETURNe;
01537    }
01538    if (!SO->SurfCont->curColPlane) {
01539       SUMA_SL_Err("No curColPlane!");
01540       SUMA_RETURNe;
01541    }
01542    
01543    /* Now do something */
01544    if (j == 0) { /* clicked on one of the row's titles */
01545       switch (i) {
01546          case 1:
01547             if (bev->button == Button1) { /* toggle lock */
01548                SO->SurfCont->curColPlane->OptScl->AutoIntRange = !SO->SurfCont->curColPlane->OptScl->AutoIntRange;
01549                SO->SurfCont->IntRangeLocked = !SO->SurfCont->IntRangeLocked;
01550                MCW_invert_widget(w);
01551             }else if (bev->button == Button3) { /* reset to autorange values */
01552                AutoHist = SO->SurfCont->curColPlane->OptScl->AutoIntRange; 
01553                SO->SurfCont->curColPlane->OptScl->AutoIntRange = 1;
01554                SUMA_InitRangeTable(SO, 0); /* overkill but little overhead */
01555                SUMA_ColorizePlane(SO->SurfCont->curColPlane);
01556                SUMA_RemixRedisplay(SO);
01557                SO->SurfCont->curColPlane->OptScl->AutoIntRange = AutoHist; 
01558             }
01559             break;
01560          case 2:
01561             if (bev->button == Button1) { /* toggle lock */
01562                SO->SurfCont->curColPlane->OptScl->AutoBrtRange = !SO->SurfCont->curColPlane->OptScl->AutoBrtRange;
01563                SO->SurfCont->BrtRangeLocked = !SO->SurfCont->BrtRangeLocked;
01564                MCW_invert_widget(w);   
01565             }else if (bev->button == Button3) { /* reset to autorange values */
01566                AutoHist = SO->SurfCont->curColPlane->OptScl->AutoBrtRange; 
01567                SO->SurfCont->curColPlane->OptScl->AutoBrtRange = 1;
01568                SUMA_InitRangeTable(SO, 1); /* overkill but little overhead */
01569                SUMA_ColorizePlane(SO->SurfCont->curColPlane);
01570                SUMA_RemixRedisplay(SO);
01571                SO->SurfCont->curColPlane->OptScl->AutoBrtRange = AutoHist; 
01572             }
01573             break;
01574          case 3:
01575             break;
01576          default:
01577             break;
01578       }
01579    }
01580    if (i == 0) { /* clicked on one of the column's titles */
01581       switch (j) {
01582          case 1:
01583             break;
01584          case 2:
01585             break;
01586          case 3:
01587             break;
01588          default:
01589             break;
01590       }
01591    }
01592    
01593    /* update the Xhair Info block */
01594    if (SO->SurfCont->curColPlane->OptScl->DoBias != SW_CoordBias_None) {
01595       SUMA_UpdateNodeNodeField(SO);    
01596    }
01597    SUMA_UpdateNodeLblField(SO);
01598 
01599    SUMA_RETURNe;
01600 
01601 }
01602 
01603 
01604 SUMA_TABLE_FIELD * SUMA_FreeTableField(SUMA_TABLE_FIELD *TF)
01605 {
01606    static char FuncName[]={"SUMA_FreeTableField"};
01607    int i;
01608    
01609    SUMA_ENTRY;
01610 
01611    if (!TF) SUMA_RETURN(NULL);
01612 
01613    if (TF->cells) SUMA_free(TF->cells);
01614    if (TF->cwidth) SUMA_free(TF->cwidth);
01615    if (TF->num_value) SUMA_free(TF->num_value);
01616    if (TF->str_value) { 
01617       for (i=0; i<TF->Nj*TF->Ni; ++i) if (TF->str_value[i]) SUMA_free(TF->str_value[i]); 
01618       SUMA_free(TF->str_value);
01619    }
01620    SUMA_free(TF);
01621 
01622    SUMA_RETURN(NULL);
01623 
01624 }
01625 
01626 /*!
01627    \brief sets a cell entry widget to be in Edit or No Edit modes
01628    \param TF
01629    \param i (int) the row index
01630    \param j (int) the col index
01631    \param Mode (int) 0 no edit, 1 yes edit
01632 */
01633 void  SUMA_SetCellEditMode(SUMA_TABLE_FIELD *TF, int i, int j, int Mode)
01634 {
01635    static char FuncName[]={"SUMA_SetCellEditMode"};
01636    int n;
01637    SUMA_Boolean LocalHead = NOPE;
01638    
01639    SUMA_ENTRY;                        
01640 
01641    if (!TF) { SUMA_SL_Err("NULL TF"); SUMA_RETURNe; }
01642    n = j * TF->Ni + i;
01643    
01644    /* remove calls anyway */
01645    XtRemoveCallback (TF->cells[n], XmNactivateCallback, SUMA_TableF_cb_label_change, (XtPointer)TF);
01646    XtRemoveCallback (TF->cells[n], XmNmodifyVerifyCallback, SUMA_TableF_cb_label_Modify, (XtPointer)TF);
01647    /* remove event handlers */
01648    XtRemoveEventHandler( TF->cells[n] ,        
01649                          LeaveWindowMask ,  
01650                          FALSE ,           
01651                          SUMA_leave_TableField,
01652                          (XtPointer) TF);
01653    switch (Mode) {
01654       case 0:
01655          /* non edit */
01656          XtVaSetValues(TF->cells[n],
01657                        XmNeditable, False, 
01658                        XmNshadowThickness , 1,          /* hide the border */
01659                        XmNcursorPositionVisible, False, /* hide the cursor */
01660                        NULL);
01661          break;
01662       case 1:
01663          /* si edit */
01664          XtVaSetValues(TF->cells[n],
01665                        XmNeditable, True, 
01666                        XmNshadowThickness , 2,         
01667                        XmNcursorPositionVisible, True, 
01668                        NULL);
01669          
01670          XtAddCallback (TF->cells[n], XmNactivateCallback, SUMA_TableF_cb_label_change, (XtPointer)TF);
01671          XtAddCallback (TF->cells[n], XmNmodifyVerifyCallback, SUMA_TableF_cb_label_Modify, (XtPointer)TF);
01672          /* add event handler to notify when widget was left */
01673          XtInsertEventHandler( TF->cells[n] ,        /* notify when */
01674                                   LeaveWindowMask ,  /* pointer leaves */
01675                                   FALSE ,            /* this window */
01676                                   SUMA_leave_TableField,
01677                                   (XtPointer) TF ,
01678                                   XtListTail ) ;     /* last in queue */
01679          break;
01680       default:
01681          SUMA_SL_Err("What?");
01682          break;
01683    }
01684    SUMA_RETURNe;
01685 }
01686 
01687 /*!
01688    \brief create a table widget
01689    \param parent (Widget) 
01690    \param Ni (int) number of entries in column (including title, if any)
01691    \param Nj (int) number of entries in row (including title, if any)
01692    \param col_tit (char **) if not NULL then this should be Nj strings
01693                             to appear as titles above each column
01694    \param row_tit (char **) if not NULL then this should be Ni strings
01695                             to appear as titles before each row
01696    \param cwidth (int *) number of characters to allow for each column. No auto sizing allowed
01697    \param editable (SUMA_Boolean) if YUP then fields are editable by user
01698    \param NewValueCallback(void * data) (void) function called when user changes value
01699    \param cb_data (void *) pointer to data sent back to call back
01700    \param TF (SUMA_TABLE_FIELD *) structure containing table info and the index
01701                                  for the newly modified field.
01702 */
01703 void SUMA_CreateTable(  Widget parent,
01704                         int Ni, int Nj, 
01705                         char **row_tit, char **col_tit,
01706                         char **row_hint, char **col_hint,
01707                         char **row_help, char **col_help, 
01708                         int *cwidth, SUMA_Boolean editable, SUMA_VARTYPE type,
01709                         void (*NewValueCallback)(void * data), void *cb_data,
01710                         void (*TitLabelEVHandler)(Widget w , XtPointer cd , XEvent *ev , Boolean *ctd), void *TitLabelEVHandlerData,
01711                         void (*CellEVHandler)(Widget w , XtPointer cd , XEvent *ev , Boolean *ctd), void *CellEVHandlerData,
01712                         SUMA_TABLE_FIELD *TF) 
01713 {
01714    static char FuncName[]={"SUMA_CreateTable"};
01715    int i, j, n, titw, xmw;
01716    char *tmp;
01717    Widget rco, rcc;
01718    XtPointer cd;
01719    SUMA_Boolean LocalHead = NOPE;
01720    
01721    SUMA_ENTRY;                        
01722 
01723    if (!TF) { SUMA_SL_Err("NULL TF"); SUMA_RETURNe; }
01724    TF->Ni = Ni; TF->Nj = Nj; TF->editable = editable; 
01725    TF->cwidth = (int *)SUMA_calloc(TF->Nj, sizeof(int)); for (j=0; j<TF->Nj; ++j) TF->cwidth[j] = cwidth[j];
01726    if(col_tit) TF->HasColTit = YUP; else TF->HasColTit = NOPE;
01727    if(row_tit) TF->HasRowTit = YUP; else TF->HasRowTit = NOPE;
01728    TF->cells = (Widget *)SUMA_malloc(sizeof(Widget)*TF->Ni*TF->Nj);
01729    if (!TF->cells) {  SUMA_SL_Crit("Failed to allocate"); SUMA_RETURNe; }
01730    TF->NewValueCallback = NewValueCallback;
01731    TF->NewValueCallbackData = cb_data;
01732    TF->TitLabelEVHandler = TitLabelEVHandler;
01733    TF->TitLabelEVHandlerData = TitLabelEVHandlerData;
01734    TF->CellEVHandler = CellEVHandler;
01735    TF->CellEVHandlerData = CellEVHandlerData;
01736    TF->type = type;
01737    switch (TF->type) {
01738       case SUMA_int:
01739       case SUMA_float:
01740          TF->num_value= (float *)SUMA_calloc(TF->Nj*TF->Ni, sizeof(float));
01741          break;
01742       case SUMA_string:
01743          TF->str_value= (char **)SUMA_malloc(TF->Nj*TF->Ni * sizeof(char *));
01744          for (i=0; i<TF->Nj*TF->Ni; ++i) TF->str_value[i] = NULL;
01745          break;
01746       default:
01747          SUMA_SL_Err("Comme tu es bete!");
01748          SUMA_RETURNe;
01749          break;  
01750    }
01751    /* An outer row column to keep the inner one from resizing with parent 
01752    YOU COULD HAVE SET XmNadjustLast to False, instead ....*/
01753    TF->rc = XtVaCreateManagedWidget ("rowcolumn",
01754       xmRowColumnWidgetClass, parent,
01755       XmNorientation , XmHORIZONTAL ,
01756       XmNpacking, XmPACK_TIGHT,
01757       XmNmarginHeight, 0,
01758       XmNmarginWidth, 0,
01759       NULL);
01760        
01761    /* Le row column to contain the table's columns*/
01762    rco = XtVaCreateManagedWidget ("rowcolumn",
01763       xmRowColumnWidgetClass, TF->rc,
01764       XmNorientation , XmVERTICAL ,
01765       XmNpacking, XmPACK_TIGHT,
01766       XmNnumColumns, 1,
01767       XmNmarginHeight, 0,
01768       XmNmarginWidth, 0, 
01769       NULL);
01770 
01771    /* must fill up row by row, each column is a separate bloody rc to allow for alignments */
01772    for (i=0; i<TF->Ni; ++i) {   /* for each row */
01773       rcc = XtVaCreateManagedWidget ("rowcolumn",
01774          xmRowColumnWidgetClass, rco,
01775          XmNorientation , XmHORIZONTAL ,
01776          XmNmarginHeight, 0,
01777          XmNmarginHeight, 0,
01778          XmNmarginWidth, 0, 
01779          NULL);
01780       
01781       if (i == 0 && TF->HasColTit) { /* This is left here to show that I tried using different packing methods
01782                                        to get the title to appear centered with the cell entries below.
01783                                        That did nothing. Setting packing to tight in all cases and padding
01784                                        the titles to fit the cell entry widths works fine */
01785          XtVaSetValues (rcc, XmNpacking, XmPACK_TIGHT, NULL); 
01786       } else {
01787          XtVaSetValues (rcc, XmNpacking, XmPACK_TIGHT, NULL); 
01788       }
01789       
01790       for (j=0; j<TF->Nj; ++j) { /* for each column */
01791          n = j * TF->Ni + i;
01792          switch (SUMA_cellvariety(TF, n)) {
01793             case SUMA_ROW_TIT_CELL: /* row's title */
01794                if (LocalHead) fprintf(SUMA_STDERR,"%s:\nAdding [%d %d] (%d) %s\n", FuncName, i, j, n, row_tit[i]);
01795                #if 0
01796                   TF->cells[n] = XtVaCreateManagedWidget(row_tit[i],  
01797                                                 xmLabelWidgetClass, rcc, 
01798                                                 NULL);
01799                #else
01800                   TF->cells[n] = XtVaCreateManagedWidget("column title",   
01801                                                    xmTextFieldWidgetClass, rcc,
01802                                                    XmNvalue, row_tit[i],
01803                                                    XmNmarginHeight, 0,
01804                                                    XmNmarginWidth, 0,
01805                                                    XmNmarginTop, 0,
01806                                                    XmNmarginBottom, 0,
01807                                                    XmNmarginLeft, 0,
01808                                                    XmNmarginRight, 0,
01809                                                    XmNeditable, False, 
01810                                                    XmNshadowThickness , 0,          /* hide the border */
01811                                                    XmNcursorPositionVisible, False, /* hide the cursor */
01812                                                    XmNcolumns, strlen(row_tit[i]), 
01813                                                    NULL);
01814                #endif
01815                if (!TF->TitLabelEVHandlerData) cd = (XtPointer) TF; else cd = (XtPointer)TF->TitLabelEVHandlerData;
01816                if (TF->TitLabelEVHandler) {
01817                   /* insert handler to catch clicks on titles */
01818                   XtInsertEventHandler( TF->cells[n] ,      /* handle events in title cell */
01819                               ButtonPressMask ,  /* button presses */
01820                               FALSE ,            /* nonmaskable events? */
01821                               TF->TitLabelEVHandler,  /* handler */
01822                               cd ,   /* client data */
01823                               XtListTail ) ; 
01824                }
01825                if (row_hint)  MCW_register_hint( TF->cells[n], row_hint[i] );
01826                if (row_help)  MCW_register_help( TF->cells[n], row_help[i] ) ;
01827                break;
01828                
01829             case SUMA_COL_TIT_CELL: /* column's title */
01830                if (LocalHead) fprintf(SUMA_STDERR,"%s:\nAdding [%d %d] (%d) %s\n", FuncName, i, j, n, col_tit[j]);
01831                /* padd to fit cell entry fields*/
01832                if (i == 0 && j != 0 && TF->HasColTit) { 
01833                   titw = TF->cwidth[j]; 
01834                   /* set the margins to meet those of cell entries */
01835                   xmw = 5;
01836                } else {
01837                   titw = TF->cwidth[j];
01838                   /* set the margins to meet those of Labels */
01839                   xmw = 0;
01840                }
01841                #if 0
01842                   TF->cells[n] = XtVaCreateManagedWidget(tmp,  
01843                                                 xmLabelWidgetClass, rcc,
01844                                                 NULL);
01845                #else 
01846                   TF->cells[n] = XtVaCreateManagedWidget("column title",   
01847                                                    xmTextFieldWidgetClass, rcc,
01848                                                    XmNvalue, col_tit[j],
01849                                                    XmNmarginHeight, 0,
01850                                                    XmNmarginWidth, xmw,
01851                                                    XmNmarginTop, 0,
01852                                                    XmNmarginBottom, 0,
01853                                                    XmNmarginLeft, 0,
01854                                                    XmNmarginRight, 0,
01855                                                    XmNeditable, False, 
01856                                                    XmNshadowThickness , 0,          /* hide the border */
01857                                                    XmNcursorPositionVisible, False, /* hide the cursor */
01858                                                    XmNcolumns, titw, 
01859                                                    NULL);
01860                #endif
01861                if (i == 0 && j != 0) { 
01862                   XtVaSetValues( TF->cells[n], XmNalignment, XmALIGNMENT_BEGINNING, NULL);
01863                }
01864                
01865                /* insert handler to catch clicks on titles */
01866                if (!TF->TitLabelEVHandlerData) cd = (XtPointer) TF; else cd = (XtPointer)TF->TitLabelEVHandlerData;
01867                if (TF->TitLabelEVHandler) {
01868                   /* insert handler to catch clicks on titles */
01869                   XtInsertEventHandler( TF->cells[n] ,      /* handle events in title cell */
01870                               ButtonPressMask ,  /* button presses */
01871                               FALSE ,            /* nonmaskable events? */
01872                               TF->TitLabelEVHandler,  /* handler */
01873                               cd ,   /* client data */
01874                               XtListTail ) ; 
01875                }                 
01876                if (col_hint)  MCW_register_hint( TF->cells[n], col_hint[j] );
01877                if (col_help)  MCW_register_help( TF->cells[n], col_help[j] ) ;
01878                break;
01879             case SUMA_ENTRY_CELL: /* entry cell */
01880                if (LocalHead) fprintf(SUMA_STDERR,"%s:\nAdding [%d %d] (%d) entry cell\n", FuncName, i, j, n);
01881                TF->cells[n] = XtVaCreateManagedWidget("entry",  
01882                                                    xmTextFieldWidgetClass, rcc,
01883                                                    XmNuserData, (XtPointer)n,
01884                                                    XmNvalue, "-",
01885                                                    XmNmarginHeight, 0,
01886                                                    XmNmarginTop, 0,
01887                                                    XmNmarginBottom, 0, 
01888                                                    NULL);
01889                if (col_help || col_hint || row_help || row_hint)  
01890                   MCW_register_help( TF->cells[n], "Hints and help messages\n"
01891                                                    "are attached to table's\n"
01892                                                    "column and row titles."  ) ;
01893                if (TF->cwidth[j] > 0) {  XtVaSetValues(TF->cells[n], XmNcolumns, TF->cwidth[j], NULL); }
01894                if (!TF->editable) { 
01895                   SUMA_SetCellEditMode(TF, i, j, 0);
01896                } else {
01897                   SUMA_SetCellEditMode(TF, i, j, 1);
01898                }
01899                /* insert handlers if any */
01900                if (!TF->CellEVHandlerData) cd = (XtPointer) TF; else cd = (XtPointer)TF->CellEVHandlerData;
01901                if (TF->CellEVHandler) {
01902                   /* insert handler to catch clicks on cells */
01903                   XtInsertEventHandler( TF->cells[n] ,      /* handle events in cell */
01904                               ButtonPressMask ,  /* button presses */
01905                               FALSE ,            /* nonmaskable events? */
01906                               TF->CellEVHandler,  /* handler */
01907                               cd ,   /* client data */
01908                               XtListTail ) ; 
01909                }                 
01910                break;
01911             default:
01912                SUMA_SL_Err("Bad cell type");
01913                SUMA_RETURNe;
01914                break;
01915          }     
01916       } /* for i */
01917    } /* for j */
01918    
01919    SUMA_RETURNe;
01920 }
01921 
01922 SUMA_CELL_VARIETY SUMA_cellvariety (SUMA_TABLE_FIELD *TF, int n)
01923 {
01924    static char FuncName[]={"SUMA_cellvariety"};
01925    int i, j;
01926    SUMA_Boolean LocalHead = NOPE;
01927    
01928    SUMA_ENTRY;
01929    
01930    if (!TF) SUMA_RETURN(SUMA_ERROR_CELL);
01931    i = n % TF->Ni;
01932    j = n / TF->Ni;
01933    if (TF->HasColTit && i == 0) SUMA_RETURN(SUMA_COL_TIT_CELL);
01934    if (TF->HasRowTit && j == 0) SUMA_RETURN(SUMA_ROW_TIT_CELL);
01935    SUMA_RETURN(SUMA_ENTRY_CELL);
01936 }
01937 
01938 /*!
01939    \brief This function is called when mouse pointer leaves label field
01940    It only acts if  TF->modified 
01941 */
01942 void SUMA_leave_TableField( Widget w , XtPointer client_data ,
01943                            XEvent * ev , Boolean * continue_to_dispatch )
01944 {
01945    static char FuncName[]={"SUMA_leave_TableField"};
01946    SUMA_TABLE_FIELD *TF=NULL; 
01947    XLeaveWindowEvent * lev = (XLeaveWindowEvent *) ev ;
01948    XmAnyCallbackStruct cbs ;
01949    SUMA_Boolean LocalHead = NOPE;
01950 
01951    SUMA_ENTRY;
01952    
01953    SUMA_LH("Called");
01954    TF = (SUMA_TABLE_FIELD *)client_data ;
01955    if( lev->type != LeaveNotify || TF->cell_modified < 0) SUMA_RETURNe; 
01956 
01957    if (LocalHead) fprintf (SUMA_STDERR, "%s: Leave notification.\n", FuncName);
01958    
01959    SUMA_TableF_cb_label_change( w , (XtPointer)TF , NULL ) ;
01960 
01961    SUMA_RETURNe;
01962 }
01963 
01964 /*!
01965    \brief This function is called when the label field is activated by the user
01966 
01967 */
01968 void SUMA_TableF_cb_label_change (Widget w, XtPointer client_data, XtPointer call_data)
01969 {
01970    static char FuncName[]={"SUMA_TableF_cb_label_change"};
01971    SUMA_TABLE_FIELD *TF=NULL;
01972    float val;
01973    XmAnyCallbackStruct *cbs = (XmAnyCallbackStruct *) call_data;
01974    void *n;
01975    SUMA_Boolean DoCallBacks;
01976    SUMA_Boolean LocalHead = NOPE;
01977 
01978    SUMA_ENTRY;
01979    
01980    SUMA_LH("Called");
01981    /* make call to NewValue callback */
01982    TF = (SUMA_TABLE_FIELD *)client_data;
01983    
01984    DoCallBacks = NOPE;
01985    if (call_data) { /* do the call backs if carriage return even if nothing is modified */
01986       if (LocalHead) 
01987          fprintf (SUMA_STDERR,"%s: cbs->reason = %d (CR=%d)\n", FuncName, cbs->reason, XmCR_ACTIVATE);
01988       if (cbs->reason == XmCR_ACTIVATE) { 
01989          DoCallBacks = YUP;
01990       }
01991    }
01992    
01993    if (TF->cell_modified >= 0) {
01994       DoCallBacks = YUP;   /* do the callbacks even if no carriage return ... */
01995       if (TF->type == SUMA_int || TF->type == SUMA_float) {
01996          /* Check if the string is numerical */
01997          XtVaGetValues (w, XmNvalue, &n, NULL);
01998          #if 0
01999          /* Don't use that, returns 0 if bad syntax is used */ 
02000          val = strtod ((char *)n, NULL); 
02001          if (errno) {
02002             /* bad syntax, reset value*/
02003             if (LocalHead) fprintf (SUMA_STDERR, "%s: Bad syntax.\n", FuncName);
02004             SUMA_RegisterMessage (SUMAg_CF->MessageList, "Bad value in text field", FuncName, SMT_Error, SMA_Log);
02005             SUMA_TableF_SetString (TF);
02006          }else {
02007             if (TF->type == SUMA_int) {
02008                if (TF->num_value[TF->cell_modified] == (int)val) { 
02009                   SUMA_LH("Same value"); 
02010                   TF->cell_modified = -1;
02011                   SUMA_RETURNe; 
02012                }
02013                TF->num_value[TF->cell_modified] = (int)val;
02014             } else if (TF->type == SUMA_float) {
02015                if (TF->num_value[TF->cell_modified] == val) { 
02016                   SUMA_LH("Same value"); 
02017                   TF->cell_modified = -1;
02018                   SUMA_RETURNe; 
02019                }
02020                TF->num_value[TF->cell_modified] = val;
02021             }
02022             SUMA_TableF_SetString (TF);
02023          }
02024          #else
02025          if (SUMA_StringToNum((char *)n, &val, 1) != 1) {
02026             SUMA_BEEP;
02027             /* bad syntax, reset value*/
02028             if (LocalHead) fprintf (SUMA_STDERR, "%s: Bad syntax.\n", FuncName);
02029             SUMA_RegisterMessage (SUMAg_CF->MessageList, "Bad value in text field", FuncName, SMT_Error, SMA_Log);
02030             SUMA_TableF_SetString (TF);
02031          }else {
02032             if (TF->type == SUMA_int) {
02033                if (TF->num_value[TF->cell_modified] == (int)val) { 
02034                   SUMA_LH("Same value"); 
02035                   TF->cell_modified = -1;
02036                   SUMA_RETURNe; 
02037                }
02038                TF->num_value[TF->cell_modified] = (int)val;
02039             } else if (TF->type == SUMA_float) {
02040                if (TF->num_value[TF->cell_modified] == val) { 
02041                   SUMA_LH("Same value"); 
02042                   TF->cell_modified = -1;
02043                   SUMA_RETURNe; 
02044                }
02045                TF->num_value[TF->cell_modified] = val;
02046             }
02047             SUMA_TableF_SetString (TF);
02048          }
02049          #endif  
02050       }
02051    } else {
02052       SUMA_LH("no cells modified");
02053    }
02054 
02055    if (DoCallBacks) {
02056       SUMA_LH("CallBacks ...");
02057       if (TF->cell_modified < 0) {
02058          /* figure out which one, user insists on value */
02059          SUMA_WHICH_CELL(TF, w, TF->cell_modified);
02060       }
02061       if (!TF->NewValueCallbackData) {
02062          SUMA_LH("No Callback data.");
02063          if (TF->NewValueCallback) TF->NewValueCallback((void*)TF);
02064       } else {
02065          SUMA_LH("Callback data.");
02066          if (TF->NewValueCallback) TF->NewValueCallback(TF->NewValueCallbackData);
02067       }
02068    }
02069    
02070    TF->cell_modified = -1;
02071    SUMA_RETURNe;
02072 }
02073 
02074 /*!
02075    threshold value to scale value (position)
02076    NOTE val's value might change if it is outside the slider range
02077    or if it is negative when the slider is in |T| mode
02078 */
02079 int SUMA_ThreshVal2ScalePos(SUMA_SurfaceObject *SO, float *val)
02080 {
02081    static char FuncName[]={"SUMA_ThreshVal2ScalePos"};
02082    int min_v, max_v, cv, scl, dec;
02083    float ftmp;
02084    Widget w = NULL;
02085    SUMA_Boolean LocalHead = NOPE;
02086 
02087    SUMA_ENTRY;
02088    
02089    if (!SO) { SUMA_SL_Err("Null SO"); SUMA_RETURN(0); }
02090    w = SO->SurfCont->thr_sc;
02091    if (!w) { SUMA_SL_Err("Null widget"); SUMA_RETURN(0); }
02092    
02093    XtVaGetValues(w, XmNuserData, &dec, NULL);
02094    XtVaGetValues( w,
02095                   XmNmaximum, &max_v,
02096                   XmNminimum, &min_v,
02097                   XmNvalue, &cv,
02098                   XmNscaleMultiple, &scl,  
02099                   NULL);
02100    if (*val < 0 && SO->SurfCont->curColPlane->OptScl->ThrMode == SUMA_ABS_LESS_THAN) {
02101       *val = -*val;
02102    } 
02103    if (LocalHead) fprintf (SUMA_STDERR, "%s:\n min %d max %d scalemult %d decimals %d\nCurrent scale value %d\n", 
02104                FuncName, min_v, max_v, scl, dec, cv);  
02105 
02106    /* what is the new slider value to be ?*/
02107    ftmp = *val * pow(10.0, dec);
02108    if (ftmp > 0) cv = (int) (ftmp+0.5);
02109    else cv = (int) (ftmp-0.5);              
02110 
02111    /* Now check on the new cv */
02112    if (cv < min_v) {
02113       cv = min_v;
02114       /* must update threshold value in options structure*/
02115       *val = (float)cv / pow(10.0, dec); 
02116    } else if (cv > max_v) {
02117       cv = max_v;
02118       *val = (float)cv / pow(10.0, dec); 
02119    }
02120 
02121    SUMA_RETURN(cv);
02122 }
02123 
02124 /*!
02125    set the threshold bar when a new value is entered
02126 */
02127 void SUMA_SetScaleThr(void *data) 
02128 {
02129    static char FuncName[]={"SUMA_SetScaleThr"};
02130    SUMA_SurfaceObject *SO=(SUMA_SurfaceObject *)data, *curSO = NULL;
02131    SUMA_TABLE_FIELD *TF=NULL;
02132    int cv, max_v, min_v;
02133    float val;
02134    SUMA_Boolean LocalHead = NOPE;
02135    
02136    SUMA_ENTRY;
02137     
02138    SUMA_LH("Called");
02139    curSO = *(SO->SurfCont->curSOp);
02140    TF = SO->SurfCont->SetThrScaleTable;
02141    if (TF->cell_modified<0) SUMA_RETURNe;
02142    val = TF->num_value[TF->cell_modified];
02143    
02144    cv = SUMA_ThreshVal2ScalePos (SO, &val );
02145 
02146    if (LocalHead) fprintf(SUMA_STDERR,"%s:\nChecksums, new value is %f, cv to be set to %d\n", 
02147       FuncName, TF->num_value[TF->cell_modified], cv);   
02148 
02149    /* check on value */
02150    if (TF->num_value[TF->cell_modified] != val) { /* a change in value (plateau effect) */
02151       TF->num_value[TF->cell_modified] = val;
02152       SUMA_INSERT_CELL_VALUE(TF, 0, 0, TF->num_value[TF->cell_modified]);
02153    }
02154    
02155    if (LocalHead) fprintf(SUMA_STDERR,"%s:\nSet thresholdiation, new value is %f\n", FuncName, TF->num_value[TF->cell_modified]);
02156    /* if value OK, set threshold bar*/
02157    SO->SurfCont->curColPlane->OptScl->ThreshRange[0] = TF->num_value[TF->cell_modified];
02158    XtVaSetValues(SO->SurfCont->thr_sc,  
02159             XmNvalue, cv, 
02160             NULL);   
02161 
02162    SUMA_LH("Colorize if necessary");
02163    /* colorize if necessary */
02164    if (!SO->SurfCont->curColPlane->OptScl->UseThr) { SUMA_RETURNe; } /* nothing else to do */
02165 
02166    if (!SUMA_ColorizePlane (SO->SurfCont->curColPlane)) {
02167          SUMA_SLP_Err("Failed to colorize plane.\n");
02168          SUMA_RETURNe;
02169    }
02170    
02171    SUMA_RemixRedisplay(SO);
02172 
02173    SUMA_UpdateNodeLblField(SO);
02174 
02175    SUMA_RETURNe;  
02176 }
02177 
02178 /*!
02179    \brief Sends the Focus triangle  when new value is entered
02180 */
02181 void SUMA_TriInput (void *data)
02182 {
02183    static char FuncName[]={"SUMA_TriInput"};
02184    SUMA_SurfaceObject *SO=(SUMA_SurfaceObject *)data, *curSO = NULL;
02185    SUMA_TABLE_FIELD *TF=NULL;
02186    int i, n, j;
02187    void *cv=NULL;
02188    float fv3[3];
02189    char str[100];
02190    SUMA_Boolean LocalHead = NOPE;
02191    
02192    SUMA_ENTRY;
02193     
02194    SUMA_LH("Called");
02195    curSO = *(SO->SurfCont->curSOp);
02196    TF = SO->SurfCont->FaceTable;
02197    if (TF->cell_modified<0) SUMA_RETURNe;
02198    n = TF->cell_modified;
02199    i = n % TF->Ni;
02200    j = n / TF->Ni;
02201    
02202    if ((int)TF->num_value[n] < 0 || (int)TF->num_value[n] >= curSO->N_FaceSet) {
02203       SUMA_SLP_Err("Triangle index n must be positive\n"
02204                    "and less than the number of nodes \n"
02205                    "forming the surface.\n");
02206       TF->num_value[n] = SO->SelectedFaceSet;
02207       SUMA_TableF_SetString (TF);
02208       TF->cell_modified = -1;
02209       SUMA_RETURNe;
02210    }
02211 
02212    switch (j) {
02213       case 1:
02214          XtVaGetValues(TF->cells[n], XmNvalue, &cv, NULL);
02215          if (LocalHead) {
02216             fprintf(SUMA_STDERR,"%s:\nTable cell[%d, %d]=%s, Tri = %d\n", 
02217                   FuncName, i, j, (char *)cv, (int)TF->num_value[n]);
02218          }
02219 
02220          /* look for a viewer that is showing this surface and has this surface in focus*/
02221          for (i=0; i<SUMAg_N_SVv; ++i) {
02222             if (LocalHead) fprintf (SUMA_STDERR,"%s: Checking viewer %d.\n", FuncName, i);
02223             if (!SUMAg_SVv[i].isShaded && SUMAg_SVv[i].X->TOPLEVEL) {
02224                /* is this viewer showing curSO ? */
02225                if (SUMA_isVisibleSO(&(SUMAg_SVv[i]), SUMAg_DOv, curSO)) {
02226                   if ((SUMAg_DOv[SUMAg_SVv[i].Focus_SO_ID].OP) == curSO) {
02227                      SUMA_JumpFocusFace((char *)cv, (void *)(&(SUMAg_SVv[i])));
02228                   }
02229                }
02230             }
02231          }
02232          break;
02233       default:
02234          SUMA_SL_Err("Should not get this input");
02235          break;
02236    }
02237    SUMA_RETURNe;  
02238 }
02239 /*!
02240    \brief Sends the node flying when new value is entered
02241 */
02242 void SUMA_NodeInput (void *data)
02243 {
02244    static char FuncName[]={"SUMA_NodeInput"};
02245    SUMA_SurfaceObject *SO=(SUMA_SurfaceObject *)data, *curSO = NULL;
02246    SUMA_TABLE_FIELD *TF=NULL;
02247    int i, n, j;
02248    void *cv=NULL;
02249    float fv3[3];
02250    char str[100];
02251    SUMA_Boolean LocalHead = NOPE;
02252    
02253    SUMA_ENTRY;
02254     
02255    SUMA_LH("Called");
02256    curSO = *(SO->SurfCont->curSOp);
02257    TF = SO->SurfCont->NodeTable;
02258    if (TF->cell_modified<0) SUMA_RETURNe;
02259    n = TF->cell_modified;
02260    i = n % TF->Ni;
02261    j = n / TF->Ni;
02262    
02263    if ((int)TF->num_value[n] < 0 || (int)TF->num_value[n] >= curSO->N_Node) {
02264       SUMA_SLP_Err("Node index must be positive and \n"
02265                    "less than the number of nodes \n"
02266                    "forming the surface.\n");
02267       TF->num_value[n] = SO->SelectedNode;
02268       SUMA_TableF_SetString (TF);
02269       TF->cell_modified = -1;
02270       SUMA_RETURNe;
02271    }
02272    
02273    switch (j) {
02274       case 1:
02275          XtVaGetValues(TF->cells[n], XmNvalue, &cv, NULL);
02276          if (LocalHead) {
02277             fprintf(SUMA_STDERR,"%s:\nTable cell[%d, %d]=%s, node = %d\n", 
02278                   FuncName, i, j, (char *)cv, (int)TF->num_value[n]);
02279          }
02280 
02281          /* look for a viewer that is showing this surface and has this surface in focus*/
02282          for (i=0; i<SUMAg_N_SVv; ++i) {
02283             if (LocalHead) fprintf (SUMA_STDERR,"%s: Checking viewer %d.\n", FuncName, i);
02284             if (!SUMAg_SVv[i].isShaded && SUMAg_SVv[i].X->TOPLEVEL) {
02285                /* is this viewer showing curSO ? */
02286                if (SUMA_isVisibleSO(&(SUMAg_SVv[i]), SUMAg_DOv, curSO)) {
02287                   if ((SUMAg_DOv[SUMAg_SVv[i].Focus_SO_ID].OP) == curSO) {
02288                         SUMA_JumpIndex((char *)cv, (void *)(&(SUMAg_SVv[i])));
02289                   }
02290                }
02291             }
02292          }
02293          break;
02294       default:
02295          SUMA_SL_Err("Should not get this input");
02296          break;
02297    }
02298    SUMA_RETURNe;  
02299 }
02300 
02301 /*!
02302    \brief Sends the cross hair flying when new value is entered
02303 */
02304 void SUMA_XhairInput (void* data)
02305 {
02306    static char FuncName[]={"SUMA_XhairInput"};
02307    SUMA_SurfaceObject *SO=(SUMA_SurfaceObject *)data, *curSO = NULL;
02308    SUMA_SurfaceViewer *sv=NULL;
02309    SUMA_TABLE_FIELD *TF=NULL;
02310    int i, n, j;
02311    void *cv=NULL;
02312    float fv3[3];
02313    char str[100];
02314    SUMA_Boolean LocalHead = NOPE;
02315    
02316    SUMA_ENTRY;
02317    
02318    SUMA_LH("Called");
02319    curSO = *(SO->SurfCont->curSOp);
02320    TF = SO->SurfCont->XhairTable;
02321    if (TF->cell_modified<0) SUMA_RETURNe;
02322    SUMA_LH("Cell modified, modifying ...");
02323    n = TF->cell_modified;
02324    i = n % TF->Ni;
02325    j = n / TF->Ni;
02326    XtVaGetValues(TF->cells[n], XmNvalue, &cv, NULL);
02327    if (LocalHead) {
02328       fprintf(SUMA_STDERR,"%s:\nTable cell[%d, %d]=%s\n", FuncName, i, j, (char *)cv);
02329    }
02330    /* Now parse that string into 3 numbers */
02331    if (SUMA_StringToNum ((char *)cv, fv3, 3) != 3) {
02332       SUMA_BEEP;
02333       str[0]='\0';
02334    } else {
02335       SUMA_XHAIR_STRING(fv3, str);
02336    }
02337    XtVaSetValues(TF->cells[n], XmNvalue, str, NULL);
02338    
02339    /* look for a viewer that is showing this surface */
02340    for (i=0; i<SUMAg_N_SVv; ++i) {
02341       if (LocalHead) fprintf (SUMA_STDERR,"%s: Checking viewer %d.\n", FuncName, i);
02342       if (!SUMAg_SVv[i].isShaded && SUMAg_SVv[i].X->TOPLEVEL) {
02343          /* is this viewer showing curSO ? */
02344          sv = &(SUMAg_SVv[i]);
02345          if (SUMA_isVisibleSO(sv, SUMAg_DOv, curSO)) {
02346             /* is this a new coordinate? Avoid calls due to cosmetic text changes */
02347             if (sv->Ch->c[0] != fv3[0] || sv->Ch->c[1] != fv3[1] || sv->Ch->c[2] != fv3[2]) {
02348                if (LocalHead) fprintf(SUMA_STDERR, "%s: Calling for jump to %s\n", FuncName, str);
02349                SUMA_JumpXYZ(str, (void *)(&(SUMAg_SVv[i])));
02350             }
02351          }
02352       }
02353    }
02354    SUMA_RETURNe;
02355 }
02356 
02357 /*!
02358    \brief Sets the range values when new value is input to the table 
02359 */
02360 void SUMA_SetRangeValue (void *data)
02361 {
02362    static char FuncName[]={"SUMA_SetRangeValue"};
02363    SUMA_SurfaceObject *SO=NULL;
02364    SUMA_TABLE_FIELD *TF=NULL;
02365    int i, n, j;
02366    void *cv=NULL;
02367    SUMA_OVERLAYS *ColPlane = NULL;
02368    SUMA_Boolean NewDisp = NOPE;
02369    SUMA_Boolean LocalHead = NOPE;
02370    
02371    SUMA_ENTRY;
02372    
02373    SUMA_LH("Called");
02374    SO = (SUMA_SurfaceObject *)data;
02375    TF = SO->SurfCont->SetRangeTable;
02376    if (TF->cell_modified<0) SUMA_RETURNe;
02377    
02378    ColPlane = SO->SurfCont->curColPlane;
02379    
02380    n = TF->cell_modified;
02381    i = n % TF->Ni;
02382    j = n / TF->Ni;
02383    XtVaGetValues(TF->cells[n], XmNvalue, &cv, NULL);
02384    if (LocalHead) {
02385       fprintf(SUMA_STDERR,"%s:\nTable cell[%d, %d]=%s\n", FuncName, i, j, (char *)cv);
02386    }
02387    NewDisp = NOPE;
02388    if (1) {
02389    /* What are we dealing with ? */
02390    switch (i) {
02391       case 1:  /* That's the Int. range */
02392          SUMA_LH("Setting Int. Range");
02393          if (j == 1) {
02394             if (ColPlane->SymIrange) {
02395                ColPlane->OptScl->IntRange[0] = -fabs((double)TF->num_value[n]);
02396                ColPlane->OptScl->IntRange[1] = -ColPlane->OptScl->IntRange[0];
02397                SUMA_INSERT_CELL_VALUE(TF, 1, 1, ColPlane->OptScl->IntRange[0]);
02398                SUMA_INSERT_CELL_VALUE(TF, 1, 2, ColPlane->OptScl->IntRange[1]);
02399             } else {
02400                if (TF->num_value[n] > ColPlane->OptScl->IntRange[1]) {
02401                   SUMA_BEEP; TF->num_value[n] = ColPlane->OptScl->IntRange[0];
02402                   SUMA_SLP_Err("Lower bound > Upper bound!");
02403                   SUMA_TableF_SetString(TF);
02404                } else {
02405                   if (LocalHead) fprintf (SUMA_STDERR,"%s: IntRange[0] was %f, will be %f\n", FuncName, ColPlane->OptScl->IntRange[0], TF->num_value[n]);
02406                   ColPlane->OptScl->IntRange[0] = TF->num_value[n];
02407                }
02408             }
02409          } else if (j==2) {
02410              if (ColPlane->SymIrange) {
02411                ColPlane->OptScl->IntRange[1] = fabs((double)TF->num_value[n]);
02412                ColPlane->OptScl->IntRange[0] = -ColPlane->OptScl->IntRange[1];
02413                SUMA_INSERT_CELL_VALUE(TF, 1, 1, ColPlane->OptScl->IntRange[0]);
02414                SUMA_INSERT_CELL_VALUE(TF, 1, 2, ColPlane->OptScl->IntRange[1]);
02415              } else {
02416                if (TF->num_value[n] < ColPlane->OptScl->IntRange[0]) {
02417                   SUMA_BEEP; TF->num_value[n] = ColPlane->OptScl->IntRange[1];
02418                   SUMA_SLP_Err("Upper bound < Lower bound!");
02419                   SUMA_TableF_SetString(TF);
02420                } else {
02421                   ColPlane->OptScl->IntRange[1] = TF->num_value[n];
02422                }
02423             }
02424          } else { SUMA_SL_Err("What's going on John ?"); }
02425          if (ColPlane->Show) NewDisp = YUP;
02426          break;
02427       case 2:  /* That's the Brt.. range */
02428          SUMA_LH("Setting Brt. Range");
02429          if (j == 1) {
02430             if (TF->num_value[n] > ColPlane->OptScl->BrightRange[1]) {
02431                SUMA_BEEP; TF->num_value[n] = ColPlane->OptScl->BrightRange[0];
02432                SUMA_SLP_Err("Lower bound > Upper bound!");
02433                SUMA_TableF_SetString(TF);
02434             } else {
02435                ColPlane->OptScl->BrightRange[0] = TF->num_value[n];
02436             }
02437          } else if (j==2) {
02438             if (TF->num_value[n] < ColPlane->OptScl->BrightRange[0]) {
02439                SUMA_BEEP; TF->num_value[n] = ColPlane->OptScl->BrightRange[1];
02440                SUMA_SLP_Err("Upper bound < Lower bound!");
02441                SUMA_TableF_SetString(TF);
02442             } else {
02443                ColPlane->OptScl->BrightRange[1] = TF->num_value[n];
02444             }
02445          } else { SUMA_SL_Err("What's going on Ron ?"); }
02446          if (ColPlane->OptScl->UseBrt) NewDisp = YUP;
02447          break;
02448       case 3:  /* That's the Brt. Map Range */
02449          SUMA_LH("Setting BrtMap. Range");
02450          if (j == 1) {
02451             if (TF->num_value[n] > ColPlane->OptScl->BrightMap[1]) {
02452                SUMA_BEEP; TF->num_value[n] = ColPlane->OptScl->BrightMap[0];
02453                SUMA_SLP_Err("Lower bound > Upper bound!");
02454                SUMA_TableF_SetString(TF);
02455             } else if (TF->num_value[n] < 0) {
02456                SUMA_BEEP; TF->num_value[n] = ColPlane->OptScl->BrightMap[0];
02457                SUMA_SLP_Err("Value must be >= 0");
02458                SUMA_TableF_SetString(TF);
02459             } else {
02460                ColPlane->OptScl->BrightMap[0] = TF->num_value[n];
02461             }
02462          } else if (j==2) {
02463             if (TF->num_value[n] < ColPlane->OptScl->BrightMap[0]) {
02464                SUMA_BEEP; TF->num_value[n] = ColPlane->OptScl->BrightMap[1];
02465                SUMA_SLP_Err("Upper bound < Lower bound!");
02466                SUMA_TableF_SetString(TF);
02467             } else {
02468                ColPlane->OptScl->BrightMap[1] = TF->num_value[n];
02469             }
02470          } else { SUMA_SL_Err("What's going on Mon ?"); }
02471          if (ColPlane->OptScl->UseBrt) NewDisp = YUP;
02472          break;
02473       case 4:  /* That's the coordinate bias Range */
02474          SUMA_LH("Setting CoordBias. Range");
02475          if (j == 1) {
02476             if (TF->num_value[n] > ColPlane->OptScl->CoordBiasRange[1]) {
02477                SUMA_BEEP; TF->num_value[n] = ColPlane->OptScl->CoordBiasRange[0];
02478                SUMA_SLP_Err("Lower bound > Upper bound!");
02479                SUMA_TableF_SetString(TF);
02480             } else { /* OK */
02481                ColPlane->OptScl->CoordBiasRange[0] = TF->num_value[n];
02482             }
02483          } else if (j==2) {
02484             if (TF->num_value[n] < ColPlane->OptScl->CoordBiasRange[0]) {
02485                SUMA_BEEP; TF->num_value[n] = ColPlane->OptScl->CoordBiasRange[1];
02486                SUMA_SLP_Err("Upper bound < Lower bound!");
02487                SUMA_TableF_SetString(TF);
02488             } else { /* OK */
02489                ColPlane->OptScl->CoordBiasRange[1] = TF->num_value[n];
02490             }
02491          } else { SUMA_SL_Err("What's going on Hon ?"); }
02492          NewDisp = YUP; /* You might want to disable this feature if the ColPlane is not shown */
02493          break;
02494       default:
02495          SUMA_SL_Err("You make me sick");
02496          break;
02497    }
02498    }
02499    
02500    /* Now, you need to redraw the deal */
02501    if (NewDisp) {
02502       SUMA_ColorizePlane(SO->SurfCont->curColPlane);
02503       SUMA_RemixRedisplay(SO);
02504    }   
02505    
02506    /* update the Xhair Info block */
02507    if (SO->SurfCont->curColPlane->OptScl->DoBias != SW_CoordBias_None) {
02508       SUMA_UpdateNodeNodeField(SO);    
02509    }
02510    SUMA_UpdateNodeLblField(SO);
02511 
02512    SUMA_RETURNe;
02513 }
02514 /*!
02515    \brief updates string based on value entered in table field. 
02516    Nothing is done unless field is numeric
02517 */
02518 void SUMA_TableF_SetString (SUMA_TABLE_FIELD * TF)
02519 {
02520    static char FuncName[]={"SUMA_TableF_SetString"};
02521    char buf[36];
02522 
02523    SUMA_ENTRY;
02524 
02525    if (TF->cell_modified < 0) { 
02526       /* nothing to do, user hit enter in field without modification */
02527       SUMA_RETURNe;
02528    }
02529    if (TF->type == SUMA_int) {
02530       sprintf (buf, "%-4d", (int)TF->num_value[TF->cell_modified]);
02531    }else if (TF->type == SUMA_float) {
02532       sprintf (buf, "%s", 
02533          MV_format_fval2(TF->num_value[TF->cell_modified], TF->cwidth[TF->cell_modified / TF->Ni]));
02534    }else {
02535       /* fair enough, must be stringy */
02536    }
02537    
02538    XtVaSetValues (TF->cells[TF->cell_modified], XmNvalue, buf, NULL);
02539    SUMA_RETURNe;
02540 }
02541 
02542 /*!
02543    \brief This function is called when label field has been modified by user keyboard input.
02544    All it does is set TF->cell_modified to the 1D index of that cell
02545 
02546 */
02547 void SUMA_TableF_cb_label_Modify (Widget w, XtPointer client_data, XtPointer call_data)
02548 {
02549    static char FuncName[]={"SUMA_TableF_cb_label_Modify"};
02550    SUMA_TABLE_FIELD *TF=NULL;
02551    int ud;
02552    static int CurrentCell = -1; 
02553    SUMA_Boolean LocalHead = NOPE;
02554    
02555    SUMA_ENTRY;
02556    SUMA_LH("Called");
02557    TF = (SUMA_TABLE_FIELD *)client_data ;
02558    
02559    if (!TF->editable) { /* this does not apply */
02560       SUMA_RETURNe;
02561    }
02562    if (TF->cell_modified != -1) { 
02563       /* make sure it is the last one you'd been working on 
02564       This check fails when I am dealing with mutliple tables
02565       If you need it, store a value for each cell and 
02566       check them individually*/
02567       if (0 && CurrentCell >= 0  && TF->cell_modified != CurrentCell) {
02568          SUMA_SL_Err("cell_modified not reset.");
02569          SUMA_RETURNe;
02570       }
02571    } 
02572    XtVaGetValues(w, XmNuserData, &ud, NULL);
02573    if (TF->cell_modified == -1) {
02574       /* fresh start, keep track */
02575       CurrentCell = ud;
02576    } 
02577    TF->cell_modified = ud;
02578 
02579    SUMA_RETURNe;
02580 }
02581 
02582 
02583 /*!
02584    \brief This function sets the color mapping options including the switch datasets and what have you
02585    It is called each time one loads a new data set and is meant to be called if the user adds a new
02586    colormap (not supported at the moment).
02587    \param NewMap --> New ColorMap was added.
02588    \param NewDset --> New Dataset was added.
02589    DO NOT CALL THIS FUNCTION if: 
02590    You are switching color maps, you are switching Intensity/threshold and so on
02591    DO call this function if you load or switch between dsets
02592    Do call this function if you load a new color map
02593    
02594 */
02595 void SUMA_set_cmap_options(SUMA_SurfaceObject *SO, SUMA_Boolean NewDset, SUMA_Boolean NewMap)
02596 {
02597    static char FuncName[]={"SUMA_set_cmap_options"};
02598    SUMA_MenuItem *SwitchInt_Menu = NULL, *SwitchThr_Menu = NULL, *SwitchBrt_Menu = NULL;
02599    int N_items;
02600    SUMA_Boolean LocalHead = NOPE;
02601    
02602    SUMA_ENTRY;
02603    
02604    if (!SO) SUMA_RETURNe;
02605    if (!SO->SurfCont) SUMA_RETURNe;
02606    if (!SO->SurfCont->opts_form || !SO->SurfCont->opts_rc) SUMA_RETURNe;
02607    if (!SO->SurfCont->curColPlane) SUMA_RETURNe;
02608    if (!NewDset && !NewMap && SO->SurfCont->rcvo && SO->SurfCont->rccm) {
02609       SUMA_SL_Err("Nothing to do");
02610       SUMA_RETURNe;
02611    }
02612    /* row column to contain all switching stuffs */
02613    if (!SO->SurfCont->rcvo){
02614       SO->SurfCont->rcvo = XtVaCreateWidget ("rowcolumn",
02615          xmRowColumnWidgetClass, SO->SurfCont->opts_rc,
02616          XmNpacking, XmPACK_TIGHT, 
02617          XmNorientation , XmVERTICAL ,
02618          XmNmarginHeight, 0 ,
02619          XmNmarginWidth , 0 ,
02620          NULL);
02621       NewDset = YUP; /* The first time around */
02622    } else {
02623       /* (no need ..) */
02624       /* XtUnmanageChild(SO->SurfCont->rcvo);  */
02625    }  
02626    
02627    if (NewDset) { /* The intensity / threshold / Brightness block*/
02628       if (!SO->SurfCont->rcsw) {
02629          SO->SurfCont->rcsw = XtVaCreateWidget ("rowcolumn",
02630             xmRowColumnWidgetClass, SO->SurfCont->rcvo,
02631             XmNpacking, XmPACK_TIGHT, 
02632             XmNorientation , XmHORIZONTAL ,
02633             XmNheight, 105,               /* don't let that change dynamically,  */
02634             XmNresizeHeight, False,       /* it messes up the frame size, when you switch dsets*/
02635             XmNmarginHeight, 0 ,
02636             XmNmarginWidth , 0 ,
02637             NULL);
02638        } else {
02639          /* (no need ..) */
02640          /*XtUnmanageChild(SO->SurfCont->rcsw); */
02641        }
02642       if (!SO->SurfCont->rcsw_v1) {
02643          SO->SurfCont->rcsw_v1 = XtVaCreateWidget ("rowcolumn",
02644             xmRowColumnWidgetClass, SO->SurfCont->rcsw,
02645             XmNpacking, XmPACK_COLUMN, 
02646             XmNorientation , XmVERTICAL ,
02647             XmNnumColumns, 1,
02648             XmNmarginHeight, 0 ,
02649             XmNmarginWidth , 0 ,
02650             NULL);
02651       }
02652       if (!SO->SurfCont->rcsw_v2) {
02653          SO->SurfCont->rcsw_v2 = XtVaCreateWidget ("rowcolumn",
02654             xmRowColumnWidgetClass, SO->SurfCont->rcsw,
02655             XmNpacking, XmPACK_COLUMN, 
02656             XmNorientation , XmVERTICAL ,
02657             XmNnumColumns, 1,
02658             XmNmarginHeight, 0 ,
02659             XmNmarginWidth , 0 ,
02660             NULL);
02661       }
02662       SwitchInt_Menu = SUMA_FormSwitchColMenuVector(SO, 0, &N_items);      
02663       if (LocalHead) fprintf (SUMA_STDERR,"%s: %d items.\n", FuncName, N_items);
02664       if (SwitchInt_Menu || !N_items) {
02665          if (SO->SurfCont->SwitchIntMenu) {
02666             SUMA_LH("Freeing old menu");
02667             XtDestroyWidget(SO->SurfCont->SwitchIntMenu[0]); /*kill the menu widget */
02668             SUMA_free(SO->SurfCont->SwitchIntMenu);   /* free the vector */
02669          }
02670          /* create a new one allocate for one more spot for the parent widget. 
02671             (more additions for sub-menus, see how SUMA_BuildMenu works )*/
02672          SO->SurfCont->SwitchIntMenu = (Widget *)SUMA_malloc(sizeof(Widget)*(N_items+1));  
02673          SUMA_BuildMenuReset(13);
02674          SUMA_BuildMenu (SO->SurfCont->rcsw_v1, XmMENU_OPTION, /* populate it */
02675                            "I", '\0', YUP, SwitchInt_Menu, 
02676                            (void *)SO, 
02677                            "Select Intensity (I) column", 
02678                            SUMA_SurfContHelp_SelInt,
02679                            SO->SurfCont->SwitchIntMenu );
02680          if (LocalHead) SUMA_ShowMeTheChildren(SO->SurfCont->SwitchIntMenu[0]);
02681          XtManageChild (SO->SurfCont->SwitchIntMenu[0]);
02682          /* Now destroy the SwitchInt_Menu */
02683          SwitchInt_Menu = SUMA_FreeMenuVector(SwitchInt_Menu, N_items);
02684          /* setup the history to the proper widget */
02685          XtVaSetValues( SO->SurfCont->SwitchIntMenu[0], XmNmenuHistory , 
02686                         SO->SurfCont->SwitchIntMenu[SO->SurfCont->curColPlane->OptScl->find+1] , NULL ) ; 
02687       } else {
02688          SUMA_SL_Err("NULL SwitchInt_Menu");
02689       }
02690       
02691       SwitchThr_Menu = SUMA_FormSwitchColMenuVector(SO, 1, &N_items);
02692       if (SwitchThr_Menu || !N_items) {
02693          if (SO->SurfCont->SwitchThrMenu) {
02694             SUMA_LH("Freeing old menu");
02695             XtDestroyWidget(SO->SurfCont->SwitchThrMenu[0]); /*kill the menu widget */
02696             SUMA_free(SO->SurfCont->SwitchThrMenu);   /* free the vector */
02697          }
02698          /* create a new one allocate for one more spot for the parent widget. 
02699             (more additions for sub-menus, see how SUMA_BuildMenu works )*/
02700          SO->SurfCont->SwitchThrMenu = (Widget *)SUMA_malloc(sizeof(Widget)*(N_items+1));  
02701          SUMA_BuildMenuReset(13);         
02702          SUMA_BuildMenu (SO->SurfCont->rcsw_v1, XmMENU_OPTION, /* populate it */
02703                            "T", '\0', YUP, SwitchThr_Menu, 
02704                            (void *)SO,  
02705                            "Select Threshold (T) column", 
02706                            SUMA_SurfContHelp_SelThr ,    
02707                            SO->SurfCont->SwitchThrMenu );
02708          XtManageChild (SO->SurfCont->SwitchThrMenu[0]);
02709          /* Now destroy the SwitchThr_Menu */
02710          SwitchThr_Menu = SUMA_FreeMenuVector(SwitchThr_Menu, N_items);
02711          /* setup the history to the proper widget */
02712          XtVaSetValues( SO->SurfCont->SwitchThrMenu[0], XmNmenuHistory , 
02713                         SO->SurfCont->SwitchThrMenu[SO->SurfCont->curColPlane->OptScl->tind+1] , NULL ) ; 
02714       } else {
02715          SUMA_SL_Err("NULL SwitchThr_Menu");
02716       }
02717 
02718       SwitchBrt_Menu = SUMA_FormSwitchColMenuVector(SO, 2, &N_items);
02719       if (SwitchBrt_Menu || !N_items) {
02720          if (SO->SurfCont->SwitchBrtMenu) {
02721             SUMA_LH("Freeing old menu");
02722             XtDestroyWidget(SO->SurfCont->SwitchBrtMenu[0]); /*kill the menu widget */
02723             SUMA_free(SO->SurfCont->SwitchBrtMenu);   /* free the vector */
02724          }
02725          /* create a new one allocate for one more spot for the parent widget. 
02726             (more additions for sub-menus, see how SUMA_BuildMenu works )*/         
02727          SO->SurfCont->SwitchBrtMenu = (Widget *)SUMA_malloc(sizeof(Widget)*(N_items+1));  
02728          SUMA_BuildMenuReset(13);
02729          SUMA_BuildMenu (SO->SurfCont->rcsw_v1, XmMENU_OPTION, /* populate it */
02730                            "B", '\0', YUP, SwitchBrt_Menu, 
02731                            (void *)SO,  
02732                            "Select Brightness (B) column", 
02733                            SUMA_SurfContHelp_SelBrt,
02734                            SO->SurfCont->SwitchBrtMenu );
02735          XtManageChild (SO->SurfCont->SwitchBrtMenu[0]);
02736          /* Now destroy the SwitchBrt_Menu */
02737          SwitchBrt_Menu = SUMA_FreeMenuVector(SwitchBrt_Menu, N_items);
02738          /* setup the history to the proper widget */
02739          XtVaSetValues( SO->SurfCont->SwitchBrtMenu[0], XmNmenuHistory , 
02740                         SO->SurfCont->SwitchBrtMenu[SO->SurfCont->curColPlane->OptScl->bind+1] , NULL ) ; 
02741  
02742       } else {
02743          SUMA_SL_Err("NULL SwitchBrt_Menu");
02744       }
02745       
02746      if (1) {
02747      /* put the toggle buttons */
02748          if (!SO->SurfCont->Int_tb) {
02749             SO->SurfCont->Int_tb = XtVaCreateManagedWidget("v", 
02750                xmToggleButtonWidgetClass, SO->SurfCont->rcsw_v2, NULL);
02751             XtAddCallback (SO->SurfCont->Int_tb, 
02752                   XmNvalueChangedCallback, SUMA_cb_SwithInt_toggled, SO);
02753             MCW_register_hint(SO->SurfCont->Int_tb,   "View (ON)/Hide Dset node colors");
02754             MCW_register_help(SO->SurfCont->Int_tb,   SUMA_SurfContHelp_SelIntTgl);
02755 
02756             SUMA_SET_SELECT_COLOR(SO->SurfCont->Int_tb);
02757          } 
02758          XmToggleButtonSetState (SO->SurfCont->Int_tb, SO->SurfCont->curColPlane->Show, NOPE);
02759          
02760          if (!SO->SurfCont->Thr_tb) {
02761             SO->SurfCont->Thr_tb = XtVaCreateManagedWidget("v", 
02762                xmToggleButtonWidgetClass, SO->SurfCont->rcsw_v2, NULL);
02763             XtAddCallback (SO->SurfCont->Thr_tb, 
02764                   XmNvalueChangedCallback, SUMA_cb_SwithThr_toggled, SO);
02765             SUMA_SET_SELECT_COLOR(SO->SurfCont->Thr_tb);
02766             MCW_register_hint(SO->SurfCont->Thr_tb,   "Apply (ON)/Ignore thresholding");
02767             MCW_register_help(SO->SurfCont->Thr_tb,   SUMA_SurfContHelp_SelThrTgl);
02768          }
02769          if (SO->SurfCont->curColPlane->OptScl->tind >=0) {
02770             XmToggleButtonSetState (SO->SurfCont->Thr_tb, SO->SurfCont->curColPlane->OptScl->UseThr, NOPE);
02771          }else {
02772             XmToggleButtonSetState (SO->SurfCont->Thr_tb, NOPE, NOPE);
02773          }
02774          
02775          if (!SO->SurfCont->Brt_tb) {
02776             SO->SurfCont->Brt_tb = XtVaCreateManagedWidget("v", 
02777                xmToggleButtonWidgetClass, SO->SurfCont->rcsw_v2, NULL);
02778             XtAddCallback (SO->SurfCont->Brt_tb, 
02779                      XmNvalueChangedCallback, SUMA_cb_SwithBrt_toggled, SO);
02780             SUMA_SET_SELECT_COLOR(SO->SurfCont->Brt_tb);
02781             MCW_register_hint(SO->SurfCont->Brt_tb,   "View (ON)/Ignore brightness modulation");
02782             MCW_register_help(SO->SurfCont->Brt_tb,   SUMA_SurfContHelp_SelBrtTgl);
02783          }
02784          if (SO->SurfCont->curColPlane->OptScl->bind >=0) {
02785             XmToggleButtonSetState (SO->SurfCont->Brt_tb, SO->SurfCont->curColPlane->OptScl->UseBrt, NOPE);
02786          } else {
02787             XmToggleButtonSetState (SO->SurfCont->Brt_tb, NOPE, NOPE);
02788          }
02789       }
02790       if (!XtIsManaged(SO->SurfCont->rcsw_v1)) XtManageChild (SO->SurfCont->rcsw_v1);
02791       if (!XtIsManaged(SO->SurfCont->rcsw_v2)) XtManageChild (SO->SurfCont->rcsw_v2);
02792       if (!XtIsManaged(SO->SurfCont->rcsw)) XtManageChild (SO->SurfCont->rcsw);
02793    } /* The intensity / threshold / Brightness block */
02794    
02795    {/*  The Color map range and selector block */
02796       char *col_tit[]=  {  " ", "Min", "Max", NULL};
02797       char *col_hint[]= {  "Clipping ranges", 
02798                            "Minimum clip value", 
02799                            "Maximum clip value" , NULL};
02800       char *col_help[]= {  SUMA_SurfContHelp_SetRngTbl_r0, 
02801                            SUMA_SurfContHelp_SetRngTbl_c1, 
02802                            SUMA_SurfContHelp_SetRngTbl_c2 , NULL};
02803       char *row_tit[]=  {  " ", "I", "B", " " , "C", NULL};
02804       char *row_hint[]= {  "Clipping ranges ", 
02805                            "Intensity clipping range (much more with BHelp)", 
02806                            "Brightness modulation clipping range (much more with BHelp)", 
02807                            "Brightness modulation factor range (much more with BHelp)" , 
02808                            "Coordinate bias range (much more with BHelp)", NULL};
02809       char *row_help[]= {  SUMA_SurfContHelp_SetRngTbl_r0, 
02810                            SUMA_SurfContHelp_SetRngTbl_r1,
02811                            SUMA_SurfContHelp_SetRngTbl_r2, 
02812                            SUMA_SurfContHelp_SetRngTbl_r3, 
02813                            SUMA_SurfContHelp_SetRngTbl_r4, NULL};
02814       if (!SO->SurfCont->rccm) {
02815          SO->SurfCont->rccm = XtVaCreateWidget ("rowcolumn",
02816             xmRowColumnWidgetClass, SO->SurfCont->rcvo,
02817             XmNpacking, XmPACK_TIGHT, 
02818             XmNorientation , XmVERTICAL ,
02819             XmNmarginHeight, 0,
02820             XmNmarginWidth, 0,
02821             NULL);
02822          NewMap = YUP; /* the first time around */
02823       }
02824        
02825       if (NewMap) {/* new colormaps */
02826          SUMA_LH("NewMap set");
02827          if (!SO->SurfCont->SetRangeTable->cells) {
02828             int colw[3] = { 1, 8, 8 };
02829             /* create the widgets for the range table */
02830             SUMA_LH("Creating table");
02831             SUMA_CreateTable( SO->SurfCont->rccm,
02832                            5, 3, 
02833                            row_tit, col_tit,  
02834                            row_hint, col_hint,  
02835                            row_help, col_help,  
02836                            colw, YUP, SUMA_float, 
02837                            SUMA_SetRangeValue, (void *)SO,
02838                            SUMA_SetRangeTableTit_EV, NULL,
02839                            NULL, NULL,  
02840                            SO->SurfCont->SetRangeTable);
02841          }
02842          if (!SO->SurfCont->CoordBiasMenu[SW_CoordBias]) {
02843                Widget rc = NULL; /* one pass through this block ONLY */
02844                rc = XtVaCreateWidget ("rowcolumn",
02845                   xmRowColumnWidgetClass, SO->SurfCont->rccm,
02846                   XmNpacking, XmPACK_TIGHT, 
02847                   XmNorientation , XmHORIZONTAL ,
02848                   XmNmarginHeight, 0 ,
02849                   XmNmarginWidth , 0 ,
02850                   NULL);
02851                
02852                SUMA_LH("Forming map mode menu");
02853                SUMA_BuildMenuReset(0);
02854                SUMA_BuildMenu ( rc, XmMENU_OPTION, 
02855                                "Col", '\0', YUP, CmapMode_Menu, 
02856                                (void *)SO,  
02857                                "Switch between color mapping modes.", 
02858                                SUMA_SurfContHelp_Col,
02859                                SO->SurfCont->CmapModeMenu);
02860                XtManageChild (SO->SurfCont->CmapModeMenu[SW_CmapMode]);
02861                
02862                SUMA_LH("Forming new bias menu");
02863                SUMA_BuildMenuReset(0);
02864                SUMA_BuildMenu ( rc, XmMENU_OPTION, 
02865                                "Bias", '\0', YUP, CoordBias_Menu, 
02866                                (void *)SO, 
02867                                "Coordinate bias direction", 
02868                                SUMA_SurfContHelp_Bias, 
02869                                SO->SurfCont->CoordBiasMenu);
02870                XtManageChild (SO->SurfCont->CoordBiasMenu[SW_CoordBias]);
02871                
02872                XtManageChild(rc);
02873          }
02874             
02875          if (!SO->SurfCont->rccm_swcmap) {
02876             SUMA_LH("Creating rccm_swcmap");
02877             SO->SurfCont->rccm_swcmap =  XtVaCreateWidget ("rowcolumn",
02878                xmRowColumnWidgetClass, SO->SurfCont->rccm,
02879                XmNpacking, XmPACK_TIGHT, 
02880                XmNorientation , XmHORIZONTAL ,
02881                XmNmarginHeight, 0 ,
02882                XmNmarginWidth , 0 ,
02883                NULL);
02884          }
02885 
02886          {
02887             SUMA_CreateUpdatableCmapMenu(SO); 
02888 
02889             #if 0
02890                /* Not any more, menu is now stuck in its own rc */
02891                /* the loader, needs to be recreated with colormap menu  */
02892                if (SO->SurfCont->CmapLoad_pb) { 
02893                   XtDestroyWidget(SO->SurfCont->CmapLoad_pb); 
02894                   SO->SurfCont->CmapLoad_pb = NULL;
02895                }
02896             #endif
02897             if (!SO->SurfCont->CmapLoad_pb) { 
02898                SUMA_LH("Forming CmapLoad button");
02899                SO->SurfCont->CmapLoad_pb = XtVaCreateManagedWidget ("New", 
02900                                  xmPushButtonWidgetClass, SO->SurfCont->rccm_swcmap, 
02901                                  NULL);
02902                XtAddCallback (SO->SurfCont->CmapLoad_pb, XmNactivateCallback, SUMA_cb_Cmap_Load, (XtPointer) SO);
02903                MCW_register_hint(SO->SurfCont->CmapLoad_pb , "Load new colormap");
02904                MCW_register_help(SO->SurfCont->CmapLoad_pb ,  SUMA_SurfContHelp_CmpNew);
02905             }
02906          } /* new colormaps */
02907          if (!XtIsManaged(SO->SurfCont->rccm_swcmap)) XtManageChild (SO->SurfCont->rccm_swcmap); 
02908       }
02909       
02910       SUMA_LH("Working the lock stuff ...");
02911       /* You'll need to fix the table's locking widget colors */
02912       if ( SO->SurfCont->IntRangeLocked == SO->SurfCont->curColPlane->OptScl->AutoIntRange) {
02913          SUMA_LH("   Do the Int");
02914          /* need to put things in sync */
02915          SO->SurfCont->IntRangeLocked = !SO->SurfCont->IntRangeLocked;
02916          MCW_invert_widget(SO->SurfCont->SetRangeTable->cells[1]);
02917       }
02918       if ( SO->SurfCont->BrtRangeLocked == SO->SurfCont->curColPlane->OptScl->AutoBrtRange) {
02919          SUMA_LH("   Do the Brt");
02920          /* need to put things in sync */
02921          SO->SurfCont->BrtRangeLocked = !SO->SurfCont->BrtRangeLocked;
02922          MCW_invert_widget(SO->SurfCont->SetRangeTable->cells[2]);
02923       } 
02924 
02925       /* Set the CoordBias's menu history to reflect current setting */
02926       SUMA_LH("Updating CoorBias chooser History");
02927       XtVaSetValues(  SO->SurfCont->CoordBiasMenu[0], XmNmenuHistory , 
02928                       SO->SurfCont->CoordBiasMenu[SO->SurfCont->curColPlane->OptScl->DoBias] , NULL ) ; 
02929  
02930       /* Set the Col's menu history to reflect current setting */
02931       SUMA_LH("Updating Col chooser History");
02932       XtVaSetValues(  SO->SurfCont->CmapModeMenu[0], XmNmenuHistory , 
02933                       SO->SurfCont->CmapModeMenu[SO->SurfCont->curColPlane->OptScl->interpmode] , NULL ) ; 
02934  
02935       /* add the selectors for symmetric range and absolute threshold */
02936       if (!SO->SurfCont->AbsThresh_tb) {
02937          Widget rc;
02938          rc = XtVaCreateWidget ("rowcolumn",
02939                xmRowColumnWidgetClass, SO->SurfCont->rccm,
02940                XmNpacking, XmPACK_TIGHT, 
02941                XmNorientation , XmHORIZONTAL ,
02942                XmNmarginHeight, 0 ,
02943                XmNmarginWidth , 0 ,
02944                NULL);
02945          /* create the absolute threshold toggle button */
02946          SO->SurfCont->AbsThresh_tb = XtVaCreateManagedWidget("|T|", 
02947                xmToggleButtonWidgetClass, rc, 
02948                NULL);
02949          XtAddCallback (SO->SurfCont->AbsThresh_tb, 
02950                XmNvalueChangedCallback, SUMA_cb_AbsThresh_tb_toggled, SO);
02951          MCW_register_hint(SO->SurfCont->AbsThresh_tb , "Absolute threshold ON/OFF");
02952          MCW_register_help(SO->SurfCont->AbsThresh_tb ,  SUMA_SurfContHelp_AbsThr );
02953          
02954          SUMA_SET_SELECT_COLOR(SO->SurfCont->AbsThresh_tb);
02955          
02956          /* create the symmetric range toggle button */
02957          SO->SurfCont->SymIrange_tb = XtVaCreateManagedWidget("sym I", 
02958                xmToggleButtonWidgetClass, rc, NULL);
02959          XtAddCallback (SO->SurfCont->SymIrange_tb, 
02960                XmNvalueChangedCallback, SUMA_cb_SymIrange_tb_toggled, SO);
02961          MCW_register_hint(SO->SurfCont->SymIrange_tb, "Intensity range symmetry about 0 ");
02962          MCW_register_help(SO->SurfCont->SymIrange_tb,   SUMA_SurfContHelp_Isym);
02963          SUMA_SET_SELECT_COLOR(SO->SurfCont->SymIrange_tb);
02964          
02965          /* add a button for zero masking */
02966          SO->SurfCont->ShowZero_tb = XtVaCreateManagedWidget("shw 0", 
02967                xmToggleButtonWidgetClass, rc, NULL);
02968          XtAddCallback (SO->SurfCont->ShowZero_tb, 
02969                XmNvalueChangedCallback, SUMA_cb_ShowZero_tb_toggled, SO);
02970          MCW_register_hint(SO->SurfCont->ShowZero_tb,   "Color masking of nodes with intensity = 0 ");
02971          MCW_register_help(SO->SurfCont->ShowZero_tb,    SUMA_SurfContHelp_Shw0);
02972          SUMA_SET_SELECT_COLOR(SO->SurfCont->ShowZero_tb);
02973          XtManageChild (rc);
02974       }
02975       
02976       /* do the initialization */
02977       
02978       if (SO->SurfCont->curColPlane->OptScl->ThrMode == SUMA_ABS_LESS_THAN) {
02979          XmToggleButtonSetState( SO->SurfCont->AbsThresh_tb, True, NOPE);
02980       } else {
02981          XmToggleButtonSetState( SO->SurfCont->AbsThresh_tb, False, NOPE);
02982       }
02983       if (!SO->SurfCont->curColPlane->SymIrange) {
02984          XmToggleButtonSetState( SO->SurfCont->SymIrange_tb, False, NOPE);
02985       } else {
02986          XmToggleButtonSetState( SO->SurfCont->SymIrange_tb, True, NOPE);
02987       }
02988       if (!SO->SurfCont->curColPlane->OptScl->MaskZero) {
02989          XmToggleButtonSetState( SO->SurfCont->ShowZero_tb, True, NOPE);
02990       } else {
02991          XmToggleButtonSetState( SO->SurfCont->ShowZero_tb, False, NOPE);
02992       }
02993       
02994       if (!XtIsManaged(SO->SurfCont->rccm)) XtManageChild (SO->SurfCont->rccm);
02995    
02996    }/*  The Color map range and selector block */
02997    
02998    if (1){ /* The Range values block*/
02999       char *col_tit[]=  {  " ", "Min", "Node", "Max", "Node", NULL};
03000       char *col_hint[]= {  "Full range in Dset", 
03001                            "Minimum value in Dset column", 
03002                            "Node index at minimum", 
03003                            "Maximum value in Dset column", 
03004                            "Node index at maximum", NULL};
03005       char *col_help[]= {  SUMA_SurfContHelp_RangeTbl_c0, 
03006                            SUMA_SurfContHelp_RangeTbl_c1,
03007                            SUMA_SurfContHelp_RangeTbl_c2, 
03008                            SUMA_SurfContHelp_RangeTbl_c3, 
03009                            SUMA_SurfContHelp_RangeTbl_c4, NULL};
03010       char *row_tit[]=  {  " ", "I", "T", "B", NULL};
03011       char *row_hint[]= {  "Full range in Dset", 
03012                            "Range of values in intensity (I) column", 
03013                            "Range of values in threshold (T) column", 
03014                            "Range of values in brightness (B) column", NULL};
03015       char *row_help[]= {  SUMA_SurfContHelp_RangeTbl_c0, 
03016                            SUMA_SurfContHelp_RangeTbl_r1, 
03017                            SUMA_SurfContHelp_RangeTbl_r2, 
03018                            SUMA_SurfContHelp_RangeTbl_r3, NULL};
03019       if (!SO->SurfCont->rcswr) {
03020          SO->SurfCont->rcswr = XtVaCreateWidget ("rowcolumn",
03021             xmRowColumnWidgetClass, SO->SurfCont->opts_form,
03022             XmNpacking, XmPACK_TIGHT, 
03023             XmNorientation , XmVERTICAL ,
03024             XmNrightAttachment, XmATTACH_FORM , 
03025             XmNleftAttachment,  XmATTACH_NONE,
03026             XmNtopAttachment, XmATTACH_WIDGET ,
03027             XmNtopWidget, SO->SurfCont->opts_rc,
03028             NULL);
03029       }
03030       
03031       if (!SO->SurfCont->RangeTable->cells) {
03032          int colw[5] = { 1, 6, 6, 6, 6 };
03033          /* create the widgets for the range table */
03034          SUMA_CreateTable( SO->SurfCont->rcswr,
03035                            4, 5, 
03036                            row_tit, col_tit,  
03037                            row_hint, col_hint,  
03038                            row_help, col_help,  
03039                            colw, NOPE, SUMA_string, 
03040                            NULL, NULL,
03041                            NULL, NULL,  
03042                            SUMA_RangeTableCell_EV, (void *)SO, 
03043                            SO->SurfCont->RangeTable);
03044       }
03045 
03046       if (!XtIsManaged(SO->SurfCont->rcswr)) XtManageChild (SO->SurfCont->rcswr);
03047    } /* The Range values block */
03048          
03049    if (NewDset) {
03050       /* initialize tables of range values */
03051       SUMA_InitRangeTable(SO, 2);
03052    }
03053    
03054    if (!XtIsManaged(SO->SurfCont->rcvo)) XtManageChild (SO->SurfCont->rcvo);
03055    SUMA_FORCE_SCALE_HEIGHT(SO); /* Unfortunately, you need to resize after managing */
03056 
03057    SUMA_RETURNe;
03058 }
03059 
03060 /*!
03061    A function to create the cmap selection menu
03062    in a manner that can be recreated if the menu
03063    contents change. You can call this function
03064    repeatedly whenever menu contents change 
03065 */
03066 void SUMA_CreateUpdatableCmapMenu(SUMA_SurfaceObject *SO) 
03067 {
03068    static char FuncName[]={"SUMA_CreateUpdatableCmapMenu"};
03069    SUMA_MenuItem *SwitchCmap_Menu = NULL;
03070    SUMA_Boolean LocalHead = NOPE;
03071 
03072    SUMA_ENTRY;
03073 
03074    if (!SUMAg_CF->scm) {   
03075       SUMAg_CF->scm = SUMA_Build_Color_maps();
03076       if (!SUMAg_CF->scm) {
03077          SUMA_SL_Err("Failed to build color maps.\n");
03078          SUMA_RETURNe;
03079       }
03080    }
03081    
03082    if (!SO->SurfCont->rc_CmapCont) { /* first pass, create placement container */
03083       SO->SurfCont->rc_CmapCont = XtVaCreateWidget ("rowcolumn",
03084       xmRowColumnWidgetClass, SO->SurfCont->rccm_swcmap,
03085       XmNpacking, XmPACK_TIGHT, 
03086       XmNorientation , XmHORIZONTAL ,
03087       XmNmarginHeight, 0 ,
03088       XmNmarginWidth , 0 ,
03089       NULL);   
03090    }
03091 
03092    SUMA_LH("Forming CmapMenu");
03093    SwitchCmap_Menu = SUMA_FormSwitchCmapMenuVector(SUMAg_CF->scm->CMv, SUMAg_CF->scm->N_maps);
03094    if (SwitchCmap_Menu) {
03095       /*SO->SurfCont->cmapswtch_pb = XtVaCreateManagedWidget ("Switch", 
03096                         xmPushButtonWidgetClass, rcc, 
03097                         NULL);
03098       XtAddCallback (SO->SurfCont->cmapswtch_pb, XmNactivateCallback, SUMA_cb_ColMap_Switch, (XtPointer) SO);
03099       */
03100       if (SO->SurfCont->SwitchCmapMenu) {
03101          SUMA_LH("Freeing old menu");
03102          XtDestroyWidget(SO->SurfCont->SwitchCmapMenu[0]); /*kill the menu widget */
03103          SUMA_free(SO->SurfCont->SwitchCmapMenu);   /* free the vector */
03104       }
03105       /* create a new one allocate for one more spot for the parent widget. 
03106          (more additions for sub-menus, see how SUMA_BuildMenu works )*/
03107       SO->SurfCont->SwitchCmapMenu = (Widget *)SUMA_malloc(sizeof(Widget)*(SUMAg_CF->scm->N_maps+1));  
03108       SUMA_BuildMenuReset(10);
03109       SO->SurfCont->N_CmapMenu = SUMA_BuildMenu (SO->SurfCont->rc_CmapCont, XmMENU_OPTION, /* populate it */
03110                         "Cmp", '\0', YUP, SwitchCmap_Menu, 
03111                         (void *)SO,  
03112                         "Switch between available color maps. (BHelp for more)", 
03113                         SUMA_SurfContHelp_Cmp, 
03114                         SO->SurfCont->SwitchCmapMenu );
03115       XtInsertEventHandler( SO->SurfCont->SwitchCmapMenu[0] ,      /* handle events in optmenu */
03116                         ButtonPressMask ,  /* button presses */
03117                         FALSE ,            /* nonmaskable events? */
03118                         SUMA_optmenu_EV ,  /* handler */
03119                         (XtPointer) SO ,   /* client data */
03120                         XtListTail ) ;
03121       XtManageChild (SO->SurfCont->SwitchCmapMenu[0]);
03122       /* Now destroy the SwitchCmap_Menu */
03123       SwitchCmap_Menu = SUMA_FreeMenuVector(SwitchCmap_Menu, SUMAg_CF->scm->N_maps);
03124    }
03125 
03126    XtManageChild(SO->SurfCont->rc_CmapCont);
03127 
03128    SUMA_RETURNe;
03129 }
03130 
03131 /*!
03132    \brief updates table with data value range
03133             and the table where user sets mapping
03134             range (that last one depends on what)
03135    SO: You know what
03136    what: (int)   -1: Do NOTHING with user accessible mapping ranges
03137                   0: intensity only
03138                   1: brightness modulation only
03139                   2: Set all user accessible mapping ranges
03140 */
03141 SUMA_Boolean SUMA_InitRangeTable(SUMA_SurfaceObject *SO, int what) 
03142 {
03143    static char FuncName[]={"SUMA_InitRangeTable"};
03144    char srange_min[50], srange_max[50], srange_minloc[50], srange_maxloc[50];
03145    SUMA_TABLE_FIELD *TF, *TFs;
03146    int i, j, i1D, fi, bi, ti;
03147    float range[2];
03148    NI_element *nel;
03149    SUMA_SCALE_TO_MAP_OPT *OptScl;
03150    SUMA_Boolean DoIs = NOPE, DoBs = NOPE, ColorizeBaby;
03151    SUMA_Boolean LocalHead = NOPE;
03152    
03153    SUMA_ENTRY;
03154 
03155    if (!SO->SurfCont) SUMA_RETURN(NOPE);
03156    TF = SO->SurfCont->RangeTable; 
03157    TFs = SO->SurfCont->SetRangeTable; 
03158    if (!TF || !TFs) SUMA_RETURN(NOPE);
03159    OptScl = SO->SurfCont->curColPlane->OptScl;
03160    fi = OptScl->find;
03161    ti = OptScl->tind;
03162    bi = OptScl->bind;
03163    ColorizeBaby = NOPE;
03164    
03165    switch (what) {
03166       case -1:
03167          DoIs = NOPE;
03168          DoBs = NOPE;
03169          break;
03170       case 2:
03171          DoIs = YUP;
03172          DoBs = YUP;
03173          break;
03174       case 0:
03175          DoIs = YUP;
03176          break;
03177       case 1:
03178          DoBs = YUP;
03179          break;
03180       default:
03181          SUMA_SL_Err("That's stupid Joe!");
03182          SUMA_RETURN(NOPE);
03183          break;
03184    }
03185    
03186    /* TF Range table Int*/
03187    SUMA_LH("Setting Int.");
03188    SUMA_RANGE_STRING(SO->SurfCont->curColPlane->dset_link, fi, srange_min, srange_max, srange_minloc, srange_maxloc, range); 
03189    SUMA_INSERT_CELL_STRING(TF, 1, 1, srange_min);/* min */
03190    SUMA_INSERT_CELL_STRING(TF, 1, 2, srange_minloc);/* minloc */
03191    SUMA_INSERT_CELL_STRING(TF, 1, 3, srange_max);/* max */
03192    SUMA_INSERT_CELL_STRING(TF, 1, 4, srange_maxloc);/* maxloc */
03193    /* TFs Range table Int*/
03194    if (DoIs) {
03195       if (SO->SurfCont->curColPlane->OptScl->AutoIntRange) { 
03196          if (!SO->SurfCont->curColPlane->ForceIntRange[0] && !SO->SurfCont->curColPlane->ForceIntRange[1]) {
03197             if (  OptScl->IntRange[0] != range[0] ||
03198                   OptScl->IntRange[1] != range[1] ) {
03199                ColorizeBaby = YUP;      
03200                OptScl->IntRange[0] = range[0]; OptScl->IntRange[1] = range[1]; 
03201             }
03202          } else {
03203             SUMA_LH("Using ForceIntRange");
03204             if (  OptScl->IntRange[0] != SO->SurfCont->curColPlane->ForceIntRange[0] ||
03205                   OptScl->IntRange[1] != SO->SurfCont->curColPlane->ForceIntRange[1] ) {
03206                ColorizeBaby = YUP;      
03207                OptScl->IntRange[0] = SO->SurfCont->curColPlane->ForceIntRange[0];
03208                OptScl->IntRange[1] = SO->SurfCont->curColPlane->ForceIntRange[1];
03209             }
03210          }
03211 
03212          /* enforce the SymIrange option */
03213          if (SO->SurfCont->curColPlane->SymIrange) {
03214             if (  OptScl->IntRange[1] != SUMA_LARG_ABS(OptScl->IntRange[0], OptScl->IntRange[1]) ||
03215                   OptScl->IntRange[0] != -OptScl->IntRange[1]) {
03216                ColorizeBaby = YUP;   
03217                OptScl->IntRange[1] = SUMA_LARG_ABS(OptScl->IntRange[0], OptScl->IntRange[1]);
03218                OptScl->IntRange[0] = -OptScl->IntRange[1];
03219             }
03220          }
03221 
03222          SUMA_INSERT_CELL_VALUE(TFs, 1, 1, OptScl->IntRange[0]);/* min */ 
03223          SUMA_INSERT_CELL_VALUE(TFs, 1, 2, OptScl->IntRange[1]);/* max */
03224       }else {
03225          /* Make sure viewer is showing same values as in OptScl */
03226          SUMA_LH("Imposing...");
03227          if (  OptScl->IntRange[0] != TFs->num_value[1*TFs->Ni+1] ||
03228                OptScl->IntRange[1] != TFs->num_value[2*TFs->Ni+1] ) {
03229             SUMA_INSERT_CELL_VALUE(TFs, 1, 1, OptScl->IntRange[0]);/* min */ 
03230             SUMA_INSERT_CELL_VALUE(TFs, 1, 2, OptScl->IntRange[1]);/* max */
03231          }
03232       }
03233    } 
03234    /* TF Range table Thr*/
03235    SUMA_LH("Setting Thr.");
03236    SUMA_RANGE_STRING(SO->SurfCont->curColPlane->dset_link, ti, srange_min, srange_max, srange_minloc, srange_maxloc, range); 
03237    SUMA_INSERT_CELL_STRING(TF, 2, 1, srange_min);/* min */
03238    SUMA_INSERT_CELL_STRING(TF, 2, 2, srange_minloc);/* minloc */
03239    SUMA_INSERT_CELL_STRING(TF, 2, 3, srange_max);/* max */
03240    SUMA_INSERT_CELL_STRING(TF, 2, 4, srange_maxloc);/* maxloc */
03241   
03242    /* TF Range table Brt*/
03243    SUMA_LH("Setting Brt.");
03244    SUMA_RANGE_STRING(SO->SurfCont->curColPlane->dset_link, bi, srange_min, srange_max, srange_minloc, srange_maxloc, range); 
03245    SUMA_INSERT_CELL_STRING(TF, 3, 1, srange_min);/* min */
03246    SUMA_INSERT_CELL_STRING(TF, 3, 2, srange_minloc);/* minloc */
03247    SUMA_INSERT_CELL_STRING(TF, 3, 3, srange_max);/* max */
03248    SUMA_INSERT_CELL_STRING(TF, 3, 4, srange_maxloc);/* maxloc */
03249    /* TFs Range table Brt*/
03250    if (DoBs) {
03251       if (SO->SurfCont->curColPlane->OptScl->AutoBrtRange) { 
03252          if (  OptScl->BrightRange[0] != range[0] ||
03253                OptScl->BrightRange[1] != range[1] ) {
03254             ColorizeBaby = YUP;      
03255             OptScl->BrightRange[0] = range[0]; OptScl->BrightRange[1] = range[1]; 
03256          }
03257          SUMA_INSERT_CELL_VALUE(TFs, 2, 1, OptScl->BrightRange[0]);/* min */
03258          SUMA_INSERT_CELL_VALUE(TFs, 2, 2, OptScl->BrightRange[1]);/* max */
03259          /* TFs Range table BrtMap*/
03260          SUMA_INSERT_CELL_VALUE(TFs, 3, 1, OptScl->BrightMap[0]);/* min */
03261          SUMA_INSERT_CELL_VALUE(TFs, 3, 2, OptScl->BrightMap[1]);/* max */
03262       } else {
03263          /* Make sure viewer is showing same values as in OptScl */
03264          if (  OptScl->BrightRange[0] != TFs->num_value[1*TFs->Ni+2] ||
03265                OptScl->BrightRange[1] != TFs->num_value[2*TFs->Ni+2] ||
03266                OptScl->BrightMap[0]   != TFs->num_value[1*TFs->Ni+3] ||
03267                OptScl->BrightMap[1]   != TFs->num_value[2*TFs->Ni+3]   ) {
03268             SUMA_INSERT_CELL_VALUE(TFs, 2, 1, OptScl->BrightRange[0]);/* min */
03269             SUMA_INSERT_CELL_VALUE(TFs, 2, 2, OptScl->BrightRange[1]);/* max */
03270             /* TFs Range table BrtMap*/
03271             SUMA_INSERT_CELL_VALUE(TFs, 3, 1, OptScl->BrightMap[0]);/* min */
03272             SUMA_INSERT_CELL_VALUE(TFs, 3, 2, OptScl->BrightMap[1]);/* max */
03273          }
03274       } 
03275    }
03276    
03277    /* TFs Range table CoordBias*/
03278    SUMA_INSERT_CELL_VALUE(TFs, 4, 1, OptScl->CoordBiasRange[0]);/* min */
03279    SUMA_INSERT_CELL_VALUE(TFs, 4, 2, OptScl->CoordBiasRange[1]);/* max */
03280    
03281    if (ColorizeBaby) {
03282       if (!SUMA_ColorizePlane (SO->SurfCont->curColPlane)) {
03283          SUMA_SLP_Err("Failed to colorize plane.\n");
03284          SUMA_RETURN(NOPE);
03285       }
03286    }
03287    SUMA_RETURN(YUP);
03288 }
03289 
03290 SUMA_ASSEMBLE_LIST_STRUCT * SUMA_AssembleCmapList(SUMA_COLOR_MAP **CMv, int N_maps) 
03291 {
03292    static char FuncName[]={"SUMA_AssembleCmapList"};
03293    SUMA_ASSEMBLE_LIST_STRUCT *clist_str = NULL;  
03294    int i;
03295    SUMA_Boolean LocalHead = NOPE;
03296    
03297    SUMA_ENTRY;
03298    
03299    clist_str = SUMA_CreateAssembleListStruct();
03300    clist_str->clist = (char **)SUMA_calloc(N_maps, sizeof(char *));
03301    clist_str->oplist = (void **)SUMA_calloc(N_maps, sizeof(void *));
03302    clist_str->N_clist = N_maps;
03303    
03304    for (i=0; i<N_maps; ++i) {
03305       clist_str->clist[i] = SUMA_copy_string(CMv[i]->Name);
03306       clist_str->oplist[i] = (void*)CMv[i];
03307    }
03308    
03309    SUMA_RETURN(clist_str);
03310 }
03311 
03312 /*!
03313    \brief opens a list selection for choosing a Dset column 
03314 */
03315 SUMA_Boolean SUMA_DsetColSelectList(SUMA_SurfaceObject *SO, int type)
03316 {
03317    static char FuncName[]={"SUMA_DsetColSelectList"};
03318    SUMA_LIST_WIDGET *LW = NULL;
03319    SUMA_Boolean LocalHead = NOPE;
03320    
03321    SUMA_ENTRY;
03322    
03323    SUMA_LH("Called");
03324    
03325    SUMA_RETURN(YUP);
03326 }
03327 /*!
03328    \brief opens a list selection for choosing a color map 
03329 */
03330 SUMA_Boolean SUMA_CmapSelectList(SUMA_SurfaceObject *SO, int refresh, int bringup)
03331 {
03332    static char FuncName[]={"SUMA_CmapSelectList"};
03333    SUMA_LIST_WIDGET *LW = NULL;
03334    SUMA_Boolean LocalHead = NOPE;
03335    
03336    SUMA_ENTRY;
03337 
03338    if (!SUMAg_CF->scm) {   
03339       SUMAg_CF->scm = SUMA_Build_Color_maps();
03340       if (!SUMAg_CF->scm) {
03341          SUMA_SL_Err("Failed to build color maps.\n");
03342          SUMA_RETURN(NOPE);
03343       }
03344    }
03345       
03346    /* Widget is common to all SUMA */
03347    LW = SUMAg_CF->X->SwitchCmapLst;
03348    
03349    if (!LW) {
03350       SUMA_LH("Allocating widget");
03351       /* need to create widget */
03352       LW = SUMA_AllocateScrolledList   (  "Switch Cmap", SUMA_LSP_SINGLE,
03353                                           NOPE,          NOPE,
03354                                           SO->SurfCont->TopLevelShell, SWP_POINTER_OFF,
03355                                           SUMA_cb_SelectSwitchCmap, (void *)SO,
03356                                           SUMA_cb_SelectSwitchCmap, (void *)SO,
03357                                           SUMA_cb_CloseSwitchCmap, NULL);
03358                                           
03359       SUMAg_CF->X->SwitchCmapLst = LW;
03360       refresh = 1; /* no doubt aboot it */
03361    } else {
03362       if ((void *)SO != LW->Default_Data || (void *)SO != LW->Select_Data) {
03363          /* just update the callback data info in LW */
03364          SUMA_UpdateScrolledListData(LW, (void *)SO, (void *)SO, NULL);
03365       }
03366    }
03367 
03368    if (refresh) {
03369       /* Now creating list*/
03370       if (LW->ALS) {
03371          if (LocalHead) SUMA_S_Err("Freeing the hag.");
03372          LW->ALS = SUMA_FreeAssembleListStruct(LW->ALS);
03373       }
03374       SUMA_LH("Assembling");
03375       LW->ALS = SUMA_AssembleCmapList(SUMAg_CF->scm->CMv, SUMAg_CF->scm->N_maps);
03376       if (!LW->ALS) {
03377          SUMA_SL_Err("Failed to assemble list");
03378          SUMA_RETURN(NOPE);
03379       }
03380       if (LW->ALS->N_clist < 0) {
03381          SUMA_SL_Err("Failed in SUMA_AssembleCmapList");
03382          SUMA_RETURN(NOPE);
03383       }
03384       if (!LW->ALS->N_clist) {
03385          SUMA_SLP_Note ("No cmaps to choose from.");
03386          SUMA_RETURN(NOPE);
03387       }
03388    }
03389    
03390    if (bringup) SUMA_CreateScrolledList ( LW->ALS->clist, LW->ALS->N_clist, NOPE, LW);
03391    
03392    SUMA_RETURN(YUP);
03393 }
03394 
03395 /*!
03396    This function will fail if the strings have been trunctated 
03397    Consider writing SetMenuChoiceUserData
03398 */ 
03399 SUMA_Boolean SUMA_SetCmapMenuChoice(SUMA_SurfaceObject *SO, char *str)
03400 {
03401    static char FuncName[]={"SUMA_SetCmapMenuChoice"};
03402    int i, Nbutt = 0;
03403    Widget whist, *w = NULL;
03404    SUMA_Boolean LocalHead = NOPE;
03405    
03406    SUMA_ENTRY;
03407    
03408    w = SO->SurfCont->SwitchCmapMenu;
03409    if (!w) SUMA_RETURN(NOPE);
03410    
03411    /* what's your history joe ? */
03412    XtVaGetValues(  w[0], XmNmenuHistory , &whist , NULL ) ;  
03413    if (!whist) {
03414       SUMA_SL_Err("NULL whist!");
03415       SUMA_RETURN(NOPE);
03416    }
03417 
03418    if (LocalHead) { 
03419       fprintf (SUMA_STDERR,"%s: The history is NAMED: %s (%d buttons total)\n", FuncName, XtName(whist), Nbutt);
03420    } 
03421       
03422 
03423    /* Now search the widgets in w for a widget labeled str */
03424    for (i=0; i< SO->SurfCont->N_CmapMenu; ++i) {
03425       if (LocalHead) fprintf (SUMA_STDERR,"I have %s\n", XtName(w[i]));
03426       if (strcmp(str, XtName(w[i])) == 0) {
03427          SUMA_LH("Match!");
03428          XtVaSetValues(  w[0], XmNmenuHistory , w[i] , NULL ) ;  
03429          SUMA_RETURN(YUP);
03430      }
03431    }
03432    
03433    SUMA_RETURN(NOPE);
03434 }
03435 
03436 /*!
03437    \brief function that handles switching colormap from the list widget 
03438    \sa SUMA_cb_SwitchCmap
03439 */
03440 void SUMA_cb_SelectSwitchCmap (Widget w, XtPointer client_data, XtPointer call_data)
03441 {
03442    static char FuncName[]={"SUMA_cb_SelectSwitchCmap"};
03443    SUMA_SurfaceObject *SO = NULL;
03444    SUMA_MenuCallBackData data;
03445    SUMA_LIST_WIDGET *LW = NULL;
03446    SUMA_Boolean CloseShop = NOPE, Found = NOPE;
03447    XmListCallbackStruct *cbs = (XmListCallbackStruct *) call_data;
03448    char *choice=NULL;
03449    int ichoice = -1;
03450    SUMA_COLOR_MAP *CM = NULL;
03451    SUMA_Boolean LocalHead = NOPE;
03452    
03453    SUMA_ENTRY;
03454    
03455    SUMA_LH("Called");
03456    SO = (SUMA_SurfaceObject *)client_data;
03457    LW = SUMAg_CF->X->SwitchCmapLst;
03458    
03459    if (!LW) {
03460       SUMA_S_Err("NULL LW!");
03461       SUMA_RETURNe;
03462    }
03463    
03464    
03465    if (cbs->reason == XmCR_SINGLE_SELECT) {
03466       if (LocalHead) fprintf (SUMA_STDERR,"%s: Single selection, list widget %s... \n", FuncName, LW->Label);
03467    } else {
03468       if (LocalHead) fprintf (SUMA_STDERR,"%s: Default selection, list widget %s... \n", FuncName, LW->Label);
03469       /*double click or enter on that one, close shop after selection */
03470       CloseShop = YUP;
03471    }
03472    
03473    XmStringGetLtoR (cbs->item, XmFONTLIST_DEFAULT_TAG, &choice);
03474    
03475    if (LocalHead) fprintf (SUMA_STDERR,"%s: Selected item: %s {%s} (%d)\n", FuncName, choice, choice, cbs->item_position);
03476    /* because of sorting, choice cannot be used as an index into clist and oplist in ALS */
03477    Found = NOPE;
03478    ichoice = 0;
03479    do {
03480       if (LocalHead) fprintf (SUMA_STDERR,"%s: Comparing:\n%s\n%s\n", FuncName, LW->ALS->clist[ichoice], choice);
03481       if (strncmp(LW->ALS->clist[ichoice], choice, strlen(choice)) == 0) Found = YUP; 
03482       else ++ichoice;
03483    } while (ichoice < LW->ALS->N_clist && !Found);
03484    
03485    if (!Found) {
03486       SUMA_SLP_Err("Choice not found.");
03487       SUMA_RETURNe;
03488    }
03489    
03490    XtFree (choice);
03491    
03492    /* now retrieve that choice from the SUMA_ASSEMBLE_LIST_STRUCT structure and initialize the drawing window */
03493    if (LW->ALS) {
03494       if (LocalHead) fprintf (SUMA_STDERR,"%s: N_clist = %d\n", FuncName, LW->ALS->N_clist); 
03495       if (LW->ALS->N_clist > ichoice) {
03496          CM = (SUMA_COLOR_MAP *)LW->ALS->oplist[ichoice];
03497          if (LocalHead) fprintf (SUMA_STDERR,"%s: Retrieved Colmap named %s\n", FuncName, CM->Name);
03498          /* Now you need to set the button menu to reflect the choice made */
03499          if (!SUMA_SetCmapMenuChoice (SO, LW->ALS->clist[ichoice])) {
03500             SUMA_SL_Err("Failed in SUMA_SetCmapMenuChoice");
03501          }
03502          if (!SUMA_SwitchColPlaneCmap(SO, CM)) {
03503             SUMA_SL_Err("Failed in SUMA_SwitchColPlaneCmap");
03504          }
03505       }
03506    } else {
03507       if (LocalHead) fprintf (SUMA_STDERR,"%s: NULL ALS\n", FuncName); 
03508    }
03509 
03510    if (CloseShop) {
03511       SUMA_cb_CloseSwitchCmap( w,  (XtPointer)LW,  call_data);
03512    }  
03513    
03514    /* update Lbl fields */
03515    SUMA_UpdateNodeLblField(SO);
03516 
03517    SUMA_RETURNe;
03518 }
03519 
03520 SUMA_Boolean SUMA_SwitchColPlaneCmap(SUMA_SurfaceObject *SO, SUMA_COLOR_MAP *CM)
03521 {
03522    static char FuncName[]={"SUMA_SwitchColPlaneCmap"};
03523    SUMA_OVERLAYS *over = NULL;
03524    SUMA_Boolean LocalHead = NOPE;
03525    
03526    SUMA_ENTRY;
03527    
03528    SUMA_LH("Called");
03529    if (!SO || !CM) { SUMA_RETURN(NOPE); }
03530    if (!SO->SurfCont) { SUMA_RETURN(NOPE); }
03531    
03532    over = SO->SurfCont->curColPlane;
03533    if (!over) { SUMA_RETURN(NOPE); }
03534    
03535    SUMA_STRING_REPLACE(over->cmapname, CM->Name);
03536    if (!SUMA_ColorizePlane (over)) {
03537          SUMA_SLP_Err("Failed to colorize plane.\n");
03538          SUMA_RETURN(NOPE);
03539    }
03540    
03541    /* reset zoom and translation vectors */
03542    SO->SurfCont->cmp_ren->FOV = SUMA_CMAP_FOV_INITIAL;
03543    SO->SurfCont->cmp_ren->translateVec[0] = SO->SurfCont->cmp_ren->translateVec[1] = SO->SurfCont->cmp_ren->translateVec[2] = 0.0;
03544 
03545    /* update the color map display */
03546    SUMA_cmap_wid_postRedisplay(NULL, (XtPointer)SO, NULL);
03547                
03548    SUMA_RemixRedisplay(SO);
03549 
03550    
03551    SUMA_RETURN(YUP);
03552 }
03553 /*!
03554    \brief function that handles closing switch colormap list widget 
03555    expects LW in client_data
03556 */
03557 void SUMA_cb_CloseSwitchCmap (Widget w, XtPointer client_data, XtPointer call)
03558 {
03559    static char FuncName[]={"SUMA_cb_CloseSwitchCmap"};
03560    SUMA_LIST_WIDGET *LW = NULL;
03561    SUMA_Boolean LocalHead = NOPE;
03562    
03563    SUMA_ENTRY;
03564    
03565    SUMA_LH("Called");
03566    
03567    LW = (SUMA_LIST_WIDGET *)client_data;
03568    
03569    #if defined SUMA_USE_WITHDRAW 
03570       if (LocalHead) fprintf (SUMA_STDERR,"%s: Withdrawing list widget %s...\n", FuncName, LW->Label);
03571       
03572       XWithdrawWindow(SUMAg_CF->X->DPY_controller1, 
03573          XtWindow(LW->toplevel),
03574          XScreenNumberOfScreen(XtScreen(LW->toplevel)));
03575    #elif defined SUMA_USE_DESTROY 
03576          if (LocalHead) fprintf (SUMA_STDERR,"%s: Destroying list widget %s...\n", FuncName, LW->Label);
03577          XtDestroyWidget(LW->toplevel);
03578          LW->toplevel = NULL;
03579    #endif
03580    
03581    LW->isShaded = YUP; 
03582    
03583    
03584    
03585    SUMA_RETURNe;
03586 }
03587 
03588 /* based on bbox.c's optmenu_EV */
03589 void SUMA_optmenu_EV( Widget w , XtPointer cd ,
03590                       XEvent *ev , Boolean *continue_to_dispatch )
03591 {
03592    static char FuncName[]={"SUMA_optmenu_EV"};
03593    Dimension lw ;
03594    Widget * children , wl = NULL;
03595    XButtonEvent * bev = (XButtonEvent *) ev ;
03596    int  num_children , ic ;
03597    SUMA_SurfaceObject *SO = (SUMA_SurfaceObject *)cd;
03598    SUMA_Boolean LocalHead = NOPE;
03599    
03600    SUMA_ENTRY;
03601    
03602    SUMA_LH("Called");
03603    
03604    /* see note in bbox.c optmenu_EV for the condition below*/
03605    if( bev->button == Button2 ){
03606      XUngrabPointer( bev->display , CurrentTime ) ;
03607      SUMA_RETURNe ;
03608    }
03609    
03610    if( w == NULL || SO == NULL ) SUMA_RETURNe ;
03611 
03612    if( bev->button != Button3 ) SUMA_RETURNe ;
03613    
03614    if (LocalHead) {
03615       SUMA_LH("Les enfants de w");
03616       SUMA_ShowMeTheChildren(w);
03617    }
03618    
03619    /* get the widget named "OptionLabel" */
03620    wl = XtNameToWidget(w, "OptionLabel");
03621    if (!wl) { 
03622       SUMA_SL_Err("Failed to find la widget"); /* do continue */
03623    } else {  /* confine yourself to the label, young man */
03624       XtVaGetValues( wl , XmNwidth, &lw , NULL ) ;
03625       if( bev->x > lw ) SUMA_RETURNe ;
03626    }
03627    
03628    /* Need to create a list */
03629    SUMA_LH("Now creating list ");
03630    if (strcmp(XtName(w), "I") == 0) {
03631       if (!SUMA_DsetColSelectList(SO, 0)) {
03632          SUMA_SLP_Err("Failed to create DsetList");
03633          SUMA_RETURNe;
03634       }
03635    } else if (strcmp(XtName(w), "T") == 0){
03636       if (!SUMA_DsetColSelectList(SO, 1)) {
03637          SUMA_SLP_Err("Failed to create DsetList");
03638          SUMA_RETURNe;
03639       }
03640    } else if (strcmp(XtName(w), "B") == 0){
03641       if (!SUMA_DsetColSelectList(SO, 2)) {
03642          SUMA_SLP_Err("Failed to create DsetList");
03643          SUMA_RETURNe;
03644       }
03645    } else if (strcmp(XtName(w), "Cmp") == 0){
03646       if (!SUMA_CmapSelectList(SO, 0, 1)) {
03647          SUMA_SLP_Err("Failed to create DsetList");
03648          SUMA_RETURNe;
03649       }
03650    } else {
03651       SUMA_SLP_Err("wahtchyoutalkinaboutwillis?");
03652       SUMA_RETURNe;
03653    }
03654    SUMA_RETURNe;
03655 
03656 }
03657 
03658 
03659 void SUMA_CreateXhairWidgets(Widget parent, SUMA_SurfaceObject *SO)
03660 {
03661    static char FuncName[]={"SUMA_CreateXhairWidgets"};
03662    char *Xhair_tit[]=   {  "Xhr ", NULL};
03663    char *Xhair_hint[]=  {  "Crosshair coordinates.", NULL};
03664    char *Xhair_help[]=  {  SUMA_SurfContHelp_Xhr , NULL};
03665    char *Node_tit[]=    {  "Node"   , NULL};
03666    char *Node_hint[]=   {  "Node index", NULL};
03667    char *Node_help[]=   {  SUMA_SurfContHelp_Node , NULL};
03668    char *Face_tit[]=    {  "Tri ", NULL};
03669    char *Face_hint[]=   {  "1- Triangle index, 2- Nodes forming tiangle", NULL};
03670    char *Face_help[]=   {  SUMA_SurfContHelp_Tri , NULL};
03671    char *Data_tit[]=    {  "    ", "Intens", "Thresh", "Bright" , NULL};
03672    char *Data_colhint[]=      {  "Data Values at node in focus", 
03673                                  "Intensity (I) value", 
03674                                  "Threshold (T) value", 
03675                                  "Brightness modulation (B) value" , NULL};
03676    char *Data_colhelp[]=      {  SUMA_SurfContHelp_NodeValTblc0, 
03677                                  SUMA_SurfContHelp_NodeValTblc1, 
03678                                  SUMA_SurfContHelp_NodeValTblc2, 
03679                                  SUMA_SurfContHelp_NodeValTblc3 , NULL}; 
03680    
03681    char *Data_rtit[]=      {  "    ", "Val " , NULL};
03682    char *Data_rowhint[]=   {  "Data Values at node in focus", 
03683                               "Data Values at node in focus" , NULL};
03684    char *Data_rowhelp[]=   {  SUMA_SurfContHelp_NodeValTblr0, 
03685                               SUMA_SurfContHelp_NodeValTblr0 , NULL};
03686    
03687    char *Label_tit[]=   {  "Lbl ", NULL};
03688    char *Label_hint[]=  {  "Color at node in focus", NULL};
03689    char *Label_help[]=  {  SUMA_SurfContHelp_NodeLabelTblr0 , NULL};
03690    
03691    Widget rcc;
03692    
03693    SUMA_Boolean LocalHead = NOPE;
03694    
03695    SUMA_ENTRY;
03696    
03697    /* a row column to contain them all */
03698    rcc = XtVaCreateWidget ("rowcolumn",
03699       xmRowColumnWidgetClass, parent,
03700       XmNpacking, XmPACK_TIGHT,
03701       XmNleftAttachment,XmATTACH_FORM ,  
03702       XmNorientation , XmVERTICAL ,
03703       XmNmarginHeight , 0 ,
03704       XmNmarginWidth  , 0 ,
03705       NULL);
03706    
03707    /* a simple table with the xhair coordinate */
03708    SUMA_LH("Creating Xhair coordinates table");
03709    {
03710       int colw[] = { 4, 27 };
03711       SUMA_CreateTable(rcc, 
03712          1, 2,
03713          Xhair_tit, NULL,
03714          Xhair_hint, NULL,
03715          Xhair_help, NULL,
03716          colw, YUP, SUMA_string,
03717          SUMA_XhairInput, (void*)SO,
03718          NULL, NULL, 
03719          NULL, NULL,  
03720          SO->SurfCont->XhairTable);
03721    }
03722    /* a table for a node's index */      
03723    SUMA_LH("Creating node table");
03724    {
03725       int colw[]={4, 6, 19};
03726       SUMA_CreateTable(rcc, 
03727          1, 3,
03728          Node_tit, NULL,
03729          Node_hint, NULL,
03730          Node_help, NULL,
03731          colw, YUP, SUMA_int,
03732          SUMA_NodeInput, (void*)SO,
03733          NULL, NULL, 
03734          NULL, NULL,  
03735          SO->SurfCont->NodeTable);
03736       /* disable the 3rd entry cell */
03737       SUMA_SetCellEditMode(SO->SurfCont->NodeTable, 0, 2, 0);
03738    }
03739    /* a table for the triangle in focus */      
03740    SUMA_LH("Creating Face  table");
03741    {
03742       int colw[]={4, 6, 19}  ; 
03743       SUMA_CreateTable(rcc, 
03744          1, 3,
03745          Face_tit, NULL,
03746          Face_hint, NULL,
03747          Face_help, NULL,
03748          colw, YUP, SUMA_int,
03749          SUMA_TriInput, (void*)SO,
03750          NULL, NULL, 
03751          NULL, NULL,  
03752          SO->SurfCont->FaceTable);
03753       /* disable the 3rd entry cell */
03754       SUMA_SetCellEditMode(SO->SurfCont->FaceTable, 0, 2, 0);   
03755    }
03756    /* a table for the Dset values at node in focus */      
03757    SUMA_LH("Creating Dset Val  table");
03758    {
03759       int colw[]={ 4, 7, 7, 7};
03760       SUMA_CreateTable(rcc, 
03761          2, 4,
03762          Data_rtit, Data_tit,
03763          Data_rowhint, Data_colhint,
03764          Data_rowhelp, Data_colhelp,
03765          colw, NOPE, SUMA_float,
03766          NULL, NULL,
03767          NULL, NULL, 
03768          NULL, NULL,  
03769          SO->SurfCont->DataTable);
03770    }
03771    /* a table for a node's label*/      
03772    SUMA_LH("Creating label  table");
03773    {
03774       int colw[]={4, 26};
03775       SUMA_CreateTable(rcc, 
03776          1, 2,
03777          Label_tit, NULL,
03778          Label_hint, NULL,
03779          Label_help, NULL, 
03780          colw, NOPE, SUMA_string,
03781          NULL, NULL,
03782          NULL, NULL, 
03783          NULL, NULL,  
03784          SO->SurfCont->LabelTable);
03785    }      
03786    XtManageChild(rcc);
03787    SUMA_RETURNe;
03788    
03789 }
03790 
03791 void SUMA_CreateCmapWidgets(Widget parent, SUMA_SurfaceObject *SO)
03792 {
03793    static char FuncName[]={"SUMA_CreateCmapWidgets"};
03794    char slabel[100];
03795    Widget rct, rcc, rco;
03796    XtVarArgsList arglist=NULL;
03797    SUMA_Boolean LocalHead = NOPE;
03798    
03799    SUMA_ENTRY;
03800 
03801    if (SO->SurfCont->opts_rc) {
03802       SUMA_SL_Err("Non null opts_rc\nThis should not be.");
03803       SUMA_RETURNe;
03804    }
03805    
03806    SO->SurfCont->opts_form = XtVaCreateWidget ("form",
03807       xmFormWidgetClass, parent,
03808       NULL);
03809    
03810    SO->SurfCont->opts_rc = XtVaCreateWidget ("rowcolumn",
03811       xmRowColumnWidgetClass, SO->SurfCont->opts_form,
03812       XmNpacking, XmPACK_TIGHT,
03813       XmNleftAttachment,XmATTACH_FORM ,  
03814       XmNorientation , XmHORIZONTAL ,
03815       XmNmarginHeight , 0 ,
03816       XmNmarginWidth  , 0 ,
03817       NULL);
03818 
03819    { /* the threshold bar */
03820       rct = XtVaCreateWidget ("rowcolumn",
03821          xmRowColumnWidgetClass, SO->SurfCont->opts_rc,
03822          XmNpacking, XmPACK_TIGHT, 
03823          XmNresizeHeight, False, /* important that this rc is not to be resized automatically,
03824                                     otherwise, the fix SUMA_FORCE_SCALE_HEIGHT will fail */
03825          XmNresizeWidth, False,
03826          XmNwidth, SUMA_SCALE_WIDTH, 
03827          XmNorientation , XmVERTICAL ,
03828          XmNmarginHeight , 0 ,
03829          XmNmarginWidth  , 0 ,
03830          NULL);
03831       /* convenient common arguments for scales */
03832       arglist = XtVaCreateArgsList( NULL,
03833                                     XmNshowValue, True,
03834                                     XmNmaximum, 255,
03835                                     XmNscaleMultiple, 5,
03836                                     XmNheight,  SUMA_SCALE_HEIGHT,
03837                                     XmNuserData, (XtPointer)0,
03838                                     NULL);
03839                   
03840       /* put a string on top of the scale
03841       Can use XmNtitleString but it is placed on the side. 
03842       Too much waisted space */
03843       #if 0
03844       sprintf(slabel,"Thr.");
03845       SO->SurfCont->thr_lb = XtVaCreateManagedWidget (slabel, 
03846                                           xmLabelWidgetClass, rct,
03847                                           XmNwidth, SUMA_SCALE_WIDTH,
03848                                           XmNrecomputeSize, False,   /* don't let it change size, it messes up the slider */ 
03849                                           NULL);
03850       #else
03851       {
03852          int colw[]={6};
03853          char *lhint[]={ "Threshold Value", NULL};
03854          char *lhelp[]={ SUMA_SurfContHelp_SetThreshTblr0, NULL};
03855          if (!SO->SurfCont->SetThrScaleTable->cells) {
03856             SUMA_CreateTable( rct,
03857                               1, 1, 
03858                               NULL, NULL,  
03859                               lhint, NULL,  
03860                               lhelp, NULL,  
03861                               colw, YUP, SUMA_float, 
03862                               SUMA_SetScaleThr, (void *)SO,
03863                               NULL, NULL,
03864                               NULL, NULL,  
03865                               SO->SurfCont->SetThrScaleTable);                                     
03866          }
03867       }
03868       #endif
03869       /* add a vertical scale for the intensity */
03870       SO->SurfCont->thr_sc = XtVaCreateManagedWidget("Thr.",
03871                                           xmScaleWidgetClass, rct,
03872                                           XtVaNestedList, arglist,
03873                                           NULL);
03874 
03875       XtAddCallback (SO->SurfCont->thr_sc, XmNvalueChangedCallback, SUMA_cb_set_threshold, (XtPointer) SO);
03876       
03877       XtAddCallback (SO->SurfCont->thr_sc, XmNdragCallback, SUMA_cb_set_threshold_label, (XtPointer) SO); 
03878       
03879       #if 0
03880       /* put a string for the pvalue */
03881       sprintf(slabel,"[N/A]");
03882       SO->SurfCont->thrstat_lb = XtVaCreateManagedWidget (slabel, 
03883                                           xmLabelWidgetClass, rct,
03884                                           NULL);
03885       #endif
03886       XtManageChild (rct);
03887 
03888    }/* the threshold bar */
03889                      
03890    if (arglist) XtFree(arglist); arglist = NULL;
03891    
03892    {/* the color bar */
03893       Widget rcc2;
03894       rcc = XtVaCreateWidget ("rowcolumn",
03895          xmRowColumnWidgetClass, SO->SurfCont->opts_rc,
03896          XmNpacking, XmPACK_TIGHT, 
03897          XmNorientation , XmVERTICAL ,
03898          XmNmarginHeight , 0 ,
03899          XmNmarginWidth  , 0 ,
03900          NULL);
03901       
03902       sprintf(slabel,"   ");
03903       SO->SurfCont->cmaptit_lb = XtVaCreateManagedWidget (slabel, 
03904                                           xmLabelWidgetClass, rcc,
03905                                           NULL);
03906       /* need another rc for the cmap to avoid having the glxarea resized by cmaptit_lb
03907       and SwitchCmapMenu */
03908       rcc2 = XtVaCreateWidget ("rowcolumn",
03909          xmRowColumnWidgetClass, rcc,
03910          XmNpacking, XmPACK_TIGHT, 
03911          XmNorientation , XmHORIZONTAL ,
03912          XmNmarginHeight , 0 ,
03913          XmNmarginWidth  , 0 ,
03914          NULL);
03915       
03916       /* open me a glxarea */
03917       SO->SurfCont->cmp_ren->cmap_wid = XtVaCreateManagedWidget("glxarea",
03918                                           glwDrawingAreaWidgetClass, rcc2,
03919                                           GLwNvisualInfo, SUMAg_SVv[0].X->VISINFO,
03920                                           XtNcolormap, SUMAg_SVv[0].X->CMAP,
03921                                           XmNwidth,   SUMA_CMAP_WIDTH,
03922                                           XmNheight,  SUMA_CMAP_HEIGHT,
03923                                           NULL);
03924 
03925       XtManageChild (rcc2);
03926       
03927       /* add me some callbacks */
03928       XtAddCallback(SO->SurfCont->cmp_ren->cmap_wid, GLwNginitCallback, SUMA_cmap_wid_graphicsInit, (XtPointer )SO);
03929       XtAddCallback(SO->SurfCont->cmp_ren->cmap_wid, GLwNexposeCallback, SUMA_cmap_wid_expose, (XtPointer )SO);
03930       XtAddCallback(SO->SurfCont->cmp_ren->cmap_wid, GLwNresizeCallback, SUMA_cmap_wid_resize, (XtPointer )SO);
03931       XtAddCallback(SO->SurfCont->cmp_ren->cmap_wid, GLwNinputCallback, SUMA_cmap_wid_input, (XtPointer )SO);
03932       
03933       XtManageChild (rcc);
03934    }  /* the colorbar */
03935    
03936    /* The options will be created as needed, when colorplanes are switched.
03937    see SUMA_InitializeColPlaneShell */
03938    
03939    XtManageChild (SO->SurfCont->opts_rc);
03940    XtManageChild (SO->SurfCont->opts_form);
03941    SUMA_RETURNe;
03942 } 
03943 
03944 SUMA_MenuItem *SUMA_FreeMenuVector(SUMA_MenuItem *menu, int Nels)
03945 {
03946    static char FuncName[]={"SUMA_FreeMenuVector"};
03947    int i;
03948    
03949    SUMA_ENTRY;
03950    
03951    if (!menu) {SUMA_RETURN(NULL);}
03952    if (Nels <= 0) {SUMA_RETURN(NULL);}
03953    
03954    for (i=0; i<Nels; ++i) {
03955       if (menu[i].label) SUMA_free(menu[i].label);
03956       if (menu[i].accelerator) SUMA_free(menu[i].accelerator);
03957       if (menu[i].accel_text) SUMA_free(menu[i].accel_text);
03958       if (menu[i].subitems) { SUMA_SL_Err("Don't know how to free subitems yet."); }
03959    }
03960    SUMA_free(menu);
03961    
03962    SUMA_RETURN(NULL);
03963 }
03964 
03965 SUMA_MenuItem *SUMA_FormSwitchColMenuVector(SUMA_SurfaceObject *SO, int what, int *N_items)
03966 {
03967    static char FuncName[]={"SUMA_FormSwitchColMenuVector"};
03968    SUMA_MenuItem *menu = NULL;
03969    int i;
03970    void (*callback)();
03971    NI_element *nel = NULL;
03972    SUMA_Boolean LocalHead = NOPE;
03973 
03974    SUMA_ENTRY;
03975    
03976    if (!SO) { SUMA_SL_Err("NULL SO"); SUMA_RETURN (menu);}
03977    if (!SO->SurfCont) { SUMA_SL_Err("NULL SO->SurfCont"); SUMA_RETURN (menu);}
03978    if (!SO->SurfCont->curColPlane) { SUMA_SL_Err("NULL SO->SurfCont->curColPlane"); SUMA_RETURN (menu);}
03979    if (!SO->SurfCont->curColPlane->dset_link) { SUMA_SL_Err("NULL SO->SurfCont->curColPlane->dset_link"); SUMA_RETURN (menu);}
03980 
03981    nel = SO->SurfCont->curColPlane->dset_link->dnel;
03982    if (!nel) { SUMA_SL_Err("NULL nel"); SUMA_RETURN (menu);}
03983    if (!nel->vec_num) { SUMA_SL_Err("no vecs"); SUMA_RETURN (menu);}
03984    
03985    /* decide on callback */
03986    switch (what) {
03987       case 0: 
03988          callback = SUMA_cb_SwitchIntensity;
03989          break;
03990       case 1:
03991          callback = SUMA_cb_SwitchThreshold;
03992          break;
03993       case 2:
03994          callback = SUMA_cb_SwitchBrightness;
03995          break;
03996       default:
03997          SUMA_SL_Err("No such what");
03998          SUMA_RETURN(menu);
03999    }
04000    
04001    /* Allocate for menu */
04002    menu = (SUMA_MenuItem *)SUMA_malloc(sizeof(SUMA_MenuItem)*(nel->vec_num+1));
04003    
04004 
04005    /* fillup menu */
04006    for (i=0; i < nel->vec_num; ++i) {
04007       menu[i].label = SUMA_DsetColLabelCopy(SO->SurfCont->curColPlane->dset_link, i, 1);
04008       menu[i].class = &xmPushButtonWidgetClass;
04009       menu[i].mnemonic = '\0';
04010       menu[i].accelerator = NULL;
04011       menu[i].accel_text = NULL;
04012       menu[i].callback = callback;
04013       menu[i].callback_data = (XtPointer)i+1; /* DO NOT USE THE zeroth item */
04014       menu[i].subitems = NULL;
04015    }
04016    
04017    /* add the stop sign. That's what SUMA_BuildMenu uses to figure out the number of elements */
04018    menu[nel->vec_num].label = NULL;
04019    
04020    *N_items = nel->vec_num;
04021       
04022    SUMA_RETURN (menu);
04023 }
04024 
04025 void SUMA_ShowMeTheChildren(Widget w)
04026 {
04027    static char FuncName[]={"SUMA_ShowMeTheChildren"};
04028    Widget * children ;
04029    int  num_children , ic , Nbutt=0;
04030    
04031    SUMA_ENTRY;
04032    
04033    XtVaGetValues( w ,         XmNchildren    , &children ,
04034                               XmNnumChildren , &num_children , 
04035                               XmNbuttonCount, &Nbutt,
04036                               NULL ) ;
04037    
04038    fprintf (SUMA_STDERR, "%s: The (%d) children of %s (%d N_butts):\n", FuncName, num_children, XtName(w), Nbutt);
04039    for( ic=0 ; ic < num_children ; ic++ ){
04040       /* what's the name jane ? */
04041       XtVaGetValues (children[ic], XmNbuttonCount, &Nbutt, NULL);
04042       fprintf (SUMA_STDERR, "%d: %s (%d N_butts)\n", ic, XtName(children[ic]), Nbutt);
04043    }
04044    
04045    SUMA_RETURNe;
04046 }
04047 
04048 SUMA_MenuItem *SUMA_FormSwitchCmapMenuVector(SUMA_COLOR_MAP **CMv, int N_maps)
04049 {
04050    static char FuncName[]={"SUMA_FormSwitchCmapMenuVector"};
04051    SUMA_MenuItem *menu = NULL;
04052    int i;
04053    void (*callback)();
04054    NI_element *nel = NULL;
04055    SUMA_Boolean LocalHead = NOPE;
04056 
04057    SUMA_ENTRY;
04058    
04059    if (!CMv) { SUMA_SL_Err("NULL CMv"); SUMA_RETURN (menu);}
04060    if (N_maps <=0) { SUMA_SL_Err("N_maps <=0"); SUMA_RETURN (menu);}
04061 
04062    callback = SUMA_cb_SwitchCmap;
04063    
04064    /* Allocate for menu */
04065    menu = (SUMA_MenuItem *)SUMA_malloc(sizeof(SUMA_MenuItem)*(N_maps+1));
04066    
04067    /* fillup menu */
04068    for (i=0; i < N_maps; ++i) {
04069       menu[i].label = SUMA_copy_string(CMv[i]->Name);
04070       menu[i].class = &xmPushButtonWidgetClass;
04071       menu[i].mnemonic = '\0';
04072       menu[i].accelerator = NULL;
04073       menu[i].accel_text = NULL;
04074       menu[i].callback = callback;
04075       menu[i].callback_data = (XtPointer)CMv[i]; /* (used to be i+1)DO NOT USE THE 0 for the first button. 0th index is reserved for the rc widget */
04076       menu[i].subitems = NULL;
04077    }
04078    
04079    /* add the stop sign. That's what SUMA_BuildMenu uses to figure out the number of elements */
04080    menu[N_maps].label = NULL;
04081       
04082    SUMA_RETURN (menu);
04083 }
04084 
04085 void SUMA_SetScaleRange(SUMA_SurfaceObject *SO, float range[2])   
04086 {
04087    static char FuncName[]={"SUMA_SetScaleRange"};
04088    int min_v, max_v, scl, dec, cv;
04089    Widget w ;
04090    float ftmp;
04091    char slabel[100];
04092    SUMA_Boolean LocalHead = NOPE;
04093    
04094    SUMA_ENTRY;
04095    
04096    if (!SO) { 
04097       SUMA_SL_Err("NULL SO");
04098       SUMA_RETURNe; 
04099    }  
04100    if (!SO->SurfCont->thr_sc) { 
04101       SUMA_SL_Err("NULL widget");
04102       SUMA_RETURNe; 
04103    }
04104    
04105    w = SO->SurfCont->thr_sc;
04106    
04107    if (range[1] <= range[0]) range[1] = range[0] + 1;
04108    
04109    if (SO->SurfCont->curColPlane->OptScl->ThrMode == SUMA_ABS_LESS_THAN) {
04110       SUMA_LH("Absolutizing Threshold Range");
04111       if (fabs((double)range[0]) > fabs((double)range[1])) {
04112          range[1] = fabs((double)range[0]); range[0] = 0.0;
04113       } else {
04114          range[1] = fabs((double)range[1]); range[0] = 0.0;
04115       }
04116    }
04117     
04118    if (range[1] - range[0] > pow(10.0,SUMAg_CF->SUMA_ThrScalePowerBias)) { /* no need for power */
04119       dec = 0;
04120       min_v = (int)(range[0] ); 
04121       max_v = (int)(range[1] ); 
04122       scl = (max_v -min_v) / 10; 
04123    } else {
04124       /* what power of 10 is needed (based on Bob's settings in afni_wid.c)? */
04125       dec = (int)ceil( log((double)(range[1] - range[0] + 0.001)) / log (10) );
04126       /* Add the scale bias, so that dec is at least = bias*/
04127       if (dec < SUMAg_CF->SUMA_ThrScalePowerBias) dec = SUMAg_CF->SUMA_ThrScalePowerBias;
04128       min_v = (int)(range[0] * pow(10.0, dec)); 
04129       max_v = (int)(range[1] * pow(10.0, dec) + 0.001); 
04130       scl = (max_v -min_v) / 10; 
04131       
04132    }  
04133    if (max_v <= min_v || scl < 0) { /* happens when max_v is so large that you get trash when typecast to int.
04134                            That's the case when you're using the number of nodes in a surface for example
04135                            and you set dec to something demented like 6 ! Need a clever function here */
04136       SUMA_SLP_Note("Bad auto scaling \nparameters for threshold bar.\nUsing defaults"); 
04137       min_v = (int)(range[0]); 
04138       max_v = (int)(range[1])+1; 
04139       scl = (max_v - min_v) / 10;
04140       dec = 1;     
04141    }
04142    
04143    #if 0
04144    /* make sure the current value is not less than the min or greater than the max */
04145    XtVaGetValues(w, XmNvalue, &cv, NULL);
04146    #else
04147    /* what was the slider's previous value in this dset ?*/
04148    ftmp = SO->SurfCont->curColPlane->OptScl->ThreshRange[0] * pow(10.0, dec);
04149    if (ftmp > 0) cv = (int) (ftmp+0.5);
04150    else cv = (int) (ftmp-0.5);
04151    #endif
04152 
04153    if (LocalHead) fprintf (SUMA_STDERR, "%s:\n min %d max %d scalemult %d decimals %d\nCurrent scale value %d\n", 
04154                   FuncName, min_v, max_v, scl, dec, cv);  
04155    if (cv < min_v) {
04156       cv = min_v;
04157       /* must update threshold value in options structure*/
04158       SO->SurfCont->curColPlane->OptScl->ThreshRange[0] = (float)cv / pow(10.0, dec); 
04159    } else if (cv > max_v) {
04160       cv = max_v;
04161       SO->SurfCont->curColPlane->OptScl->ThreshRange[0] = (float)cv / pow(10.0, dec); 
04162    }
04163    /* set the slider bar */
04164    XtVaSetValues(w,  
04165             XmNmaximum, max_v, 
04166             XmNminimum, min_v,
04167             XmNvalue, cv, 
04168             XmNscaleMultiple, scl,  
04169             XmNdecimalPoints , dec,
04170             XmNuserData, (XtPointer)dec,   
04171             NULL);   
04172             
04173    /* set the label on top */
04174    if (SO->SurfCont->curColPlane->OptScl->ThrMode != SUMA_ABS_LESS_THAN) 
04175       sprintf(slabel, "%5s", MV_format_fval((float)cv / pow(10.0, dec))); 
04176    else {
04177       /* used to use this:
04178       sprintf(slabel, "|%5s|", .... 
04179       but that does not work in the editable field ... */
04180       sprintf(slabel, "%5s", MV_format_fval((float)cv / pow(10.0, dec))); 
04181    }
04182    /* SUMA_SET_LABEL(SO->SurfCont->thr_lb,  slabel);*/
04183       SUMA_INSERT_CELL_STRING(SO->SurfCont->SetThrScaleTable, 0,0,slabel); 
04184 
04185             
04186    SUMA_RETURNe;
04187 }
04188 
04189 
04190 /*!
04191    \brief A function to update the field showing
04192    Xhair coordinates.
04193    Xhair is a property of the viewer rather than
04194    the surface but it makes more sense to display
04195    the coordinates, in certain cases, in the 
04196    surface controllers
04197 */
04198 SUMA_Boolean SUMA_UpdateXhairField(SUMA_SurfaceViewer *sv)
04199 {
04200    static char FuncName[]={"SUMA_UpdateXhairField"};
04201    int i, N_SOlist, SOlist[SUMA_MAX_DISPLAYABLE_OBJECTS];
04202    SUMA_DO *dov = SUMAg_DOv;
04203    SUMA_SurfaceObject *SO=NULL, *curSO=NULL;
04204    char str[100];
04205    SUMA_Boolean LocalHead = NOPE;
04206    
04207    SUMA_ENTRY; 
04208    
04209    if (!sv) SUMA_RETURN(NOPE);
04210    
04211    /* Which surfaces are visible in this SV ? */
04212    N_SOlist = SUMA_VisibleSOs(sv, dov, SOlist);
04213    for (i=0; i<N_SOlist; ++i) {
04214       if (LocalHead) fprintf (SUMA_STDERR, "%s: working %d/%d shown surfaces ...\n", 
04215                                           FuncName, i, N_SOlist);
04216       SO = (SUMA_SurfaceObject *)dov[SOlist[i]].OP;
04217       if (SO->SurfCont) { /* does this surface have surface controller ? */
04218          /* is this controller, displaying information for that surface ? */
04219          curSO = *(SO->SurfCont->curSOp);
04220          if (curSO == SO) {
04221             /* OK, show the coordinate */
04222             if (LocalHead) fprintf(SUMA_STDERR,"%s: Setting cross hair at %f %f %f\n", 
04223                FuncName, sv->Ch->c[0],sv->Ch->c[1],sv->Ch->c[2]);
04224             SUMA_XHAIR_STRING(sv->Ch->c, str);
04225             SUMA_LH(str);
04226             XtVaSetValues(SO->SurfCont->XhairTable->cells[1], XmNvalue, str, NULL);
04227          }
04228       }
04229       
04230    }
04231    
04232    SUMA_RETURN(YUP);
04233    
04234 }
04235  
04236 SUMA_Boolean SUMA_UpdateNodeField(SUMA_SurfaceObject *SO)
04237 {
04238    static char FuncName[]={"SUMA_UpdateNodeField"};
04239    SUMA_SurfaceObject *curSO=NULL;
04240    
04241    SUMA_ENTRY; 
04242    
04243    if (!SO) SUMA_RETURN(NOPE);
04244    
04245    if (SO->SurfCont) {
04246       curSO = *(SO->SurfCont->curSOp);
04247       if (curSO == SO) {
04248          SUMA_UpdateNodeNodeField(SO);
04249          /* Now get the data values at that node */
04250          SUMA_UpdateNodeValField(SO);
04251          /* now find that node in the colored list */
04252          SUMA_UpdateNodeLblField(SO);
04253                   
04254       }
04255    }
04256          
04257    SUMA_RETURN(YUP);
04258    
04259 }
04260 
04261 SUMA_Boolean SUMA_UpdateNodeNodeField(SUMA_SurfaceObject *SO)
04262 {
04263    static char FuncName[]={"SUMA_UpdateNodeNodeField"};
04264    char str[100];
04265 
04266    SUMA_ENTRY; 
04267 
04268    if (!SO || !SO->SurfCont || !SO->SurfCont->NodeTable) SUMA_RETURN(NOPE);
04269    if (SO->SelectedNode < 0 || SO->SelectedNode >= SO->N_Node) SUMA_RETURN(NOPE);
04270    
04271    sprintf(str, "%d", SO->SelectedNode);
04272    SO->SurfCont->NodeTable->num_value[1] = SO->SelectedNode;
04273    XtVaSetValues(SO->SurfCont->NodeTable->cells[1], XmNvalue, str, NULL);
04274    sprintf(str, "%s",          MV_format_fval2(SO->NodeList[3*SO->SelectedNode], 7));
04275    sprintf(str, "%s, %s", str, MV_format_fval2(SO->NodeList[3*SO->SelectedNode+1], 7));
04276    sprintf(str, "%s, %s", str, MV_format_fval2(SO->NodeList[3*SO->SelectedNode+2], 7) );
04277    XtVaSetValues(SO->SurfCont->NodeTable->cells[2], XmNvalue, str, NULL);
04278 
04279    SUMA_RETURN(YUP);
04280 }
04281 
04282 SUMA_Boolean SUMA_UpdateNodeValField(SUMA_SurfaceObject *SO)
04283 {
04284    static char FuncName[]={"SUMA_UpdateNodeValField"};
04285    SUMA_OVERLAYS *Sover=NULL;
04286    char *str_int=NULL, *str_thr=NULL, *str_brt=NULL;
04287    double dval;
04288    int Found = -1;
04289    SUMA_Boolean LocalHead = NOPE;
04290 
04291    SUMA_ENTRY;
04292 
04293    if (!SO) {
04294       SUMA_LH("Null SO");
04295       SUMA_RETURN(NOPE);
04296    }
04297    Sover = SO->SurfCont->curColPlane;
04298    
04299    if (!Sover) {
04300       SUMA_LH("Null Sover");
04301       SUMA_RETURN(NOPE);
04302    }
04303    
04304    /* 1- Where is this node in the data set ? */
04305    Found = SUMA_GetNodeRow_FromNodeIndex(Sover->dset_link, SO->SelectedNode, SO->N_Node);
04306    if (LocalHead) {
04307       fprintf(SUMA_STDERR,"%s: Node index %d is at row %d in dset.", FuncName, SO->SelectedNode, Found);
04308    }
04309 
04310    if (Found >= 0) {
04311       /* 2- What is the value of the intensity */
04312       str_int = SUMA_GetDsetValInCol(Sover->dset_link, Sover->OptScl->find, Found, &dval);
04313       if (str_int) {
04314          SUMA_LH(str_int);
04315          SUMA_INSERT_CELL_STRING(SO->SurfCont->DataTable, 1, 1, str_int);
04316       } else {
04317          SUMA_SL_Err("Failed to get str_int");
04318       }
04319       str_thr = SUMA_GetDsetValInCol(Sover->dset_link, Sover->OptScl->tind, Found, &dval);
04320       if (str_thr) {
04321          SUMA_LH(str_thr);
04322          SUMA_INSERT_CELL_STRING(SO->SurfCont->DataTable, 1, 2, str_thr);
04323       } else {
04324          SUMA_SL_Err("Failed to get str_thr");
04325       }
04326       str_brt = SUMA_GetDsetValInCol(Sover->dset_link, Sover->OptScl->bind, Found, &dval);
04327       if (str_brt) {
04328          SUMA_LH(str_brt);
04329          SUMA_INSERT_CELL_STRING(SO->SurfCont->DataTable, 1, 3, str_brt);
04330       } else {
04331          SUMA_SL_Err("Failed to get str_brt");
04332       }
04333       if (str_int) SUMA_free(str_int); str_int = NULL;
04334       if (str_thr) SUMA_free(str_thr); str_thr = NULL;
04335       if (str_brt) SUMA_free(str_brt); str_brt = NULL;
04336    } else {
04337       SUMA_INSERT_CELL_STRING(SO->SurfCont->DataTable, 1, 1, "NoData");
04338       SUMA_INSERT_CELL_STRING(SO->SurfCont->DataTable, 1, 2, "NoData");
04339       SUMA_INSERT_CELL_STRING(SO->SurfCont->DataTable, 1, 3, "NoData");
04340    }
04341    SUMA_RETURN(NOPE);
04342 }
04343 
04344 SUMA_Boolean SUMA_UpdateNodeLblField(SUMA_SurfaceObject *SO)
04345 {
04346    static char FuncName[]={"SUMA_UpdateNodeLblField"};
04347    int Found = -1;
04348    char str_col[100];
04349    SUMA_OVERLAYS *Sover=NULL;
04350    SUMA_Boolean LocalHead = NOPE;
04351 
04352    SUMA_ENTRY;
04353 
04354    if (!SO) SUMA_RETURN(NOPE);
04355 
04356    Sover = SO->SurfCont->curColPlane;
04357    if (!Sover) {
04358       SUMA_RETURN(NOPE);
04359    }
04360    
04361    if (!Sover->Show) {
04362       SUMA_LH("Col plane hidden");
04363       sprintf(str_col,"hidden color overlay");
04364       SUMA_INSERT_CELL_STRING(SO->SurfCont->LabelTable, 0, 1, str_col);
04365       SUMA_RETURN(YUP);
04366    }
04367     
04368    Found = SUMA_GetNodeOverInd(Sover, SO->SelectedNode);
04369 
04370    if (Found < 0) {
04371       SUMA_Boolean Reasoned = NOPE;
04372       SUMA_LH("Node not found.\nLikely masked by threshold");
04373       sprintf(str_col,"masked");
04374       /* try to find out why it is masked */
04375       if (!Reasoned && SO->SurfCont->DataTable) {
04376          SUMA_LH("Checking if there is no data for this node");
04377          {
04378             void *n=NULL;
04379             XtVaGetValues(SO->SurfCont->DataTable->cells[1*SO->SurfCont->DataTable->Ni+1], XmNvalue, &n, NULL);
04380             if (strcmp((char *)n, "NoData") == 0) {
04381                /* no data at all */
04382                sprintf(str_col,"no data for this node");
04383                Reasoned = YUP;
04384             }
04385          }
04386       }
04387       if (!Reasoned && SO->SurfCont->DataTable) { /* is the value 0 ? */
04388          SUMA_LH("Checking if node value is zero & zero is not being shown");
04389          if (Sover->OptScl->MaskZero && SO->SurfCont->DataTable->num_value[1*SO->SurfCont->DataTable->Ni+1]) {
04390             sprintf(str_col,"masked by zero value");  
04391          }   
04392       }
04393       SUMA_INSERT_CELL_STRING(SO->SurfCont->LabelTable, 0, 1, str_col);
04394    } else {
04395       /* Now we know what the index of this node is in the overlay plane (and the data) */
04396       sprintf(str_col,"%s",              MV_format_fval2(Sover->ColVec[3*Found],5));
04397       sprintf(str_col,"%s, %s", str_col, MV_format_fval2(Sover->ColVec[3*Found+1],5)); 
04398       sprintf(str_col,"%s, %s", str_col, MV_format_fval2(Sover->ColVec[3*Found+2],5));
04399       SUMA_LH(str_col);
04400       SUMA_INSERT_CELL_STRING(SO->SurfCont->LabelTable, 0, 1, str_col);
04401    }
04402 
04403    SUMA_RETURN(YUP);
04404 }
04405 
04406 SUMA_Boolean SUMA_UpdateTriField(SUMA_SurfaceObject *SO)
04407 {
04408    static char FuncName[]={"SUMA_UpdateTriField"};
04409    SUMA_SurfaceObject *curSO=NULL;
04410    char str[100];
04411    SUMA_Boolean LocalHead = NOPE;
04412    
04413    SUMA_ENTRY; 
04414    
04415    if (!SO) SUMA_RETURN(NOPE);
04416    
04417    if (SO->SurfCont) {
04418       curSO = *(SO->SurfCont->curSOp);
04419       if (curSO == SO) {
04420          if (SO->SelectedFaceSet >= 0) {
04421             sprintf(str, "%d", SO->SelectedFaceSet);
04422             SO->SurfCont->FaceTable->num_value[1] = SO->SelectedFaceSet;
04423             XtVaSetValues(SO->SurfCont->FaceTable->cells[1], XmNvalue, str, NULL);
04424             sprintf(str, "%d, %d, %d", 
04425                SO->FaceSetList[3*SO->SelectedFaceSet], SO->FaceSetList[3*SO->SelectedFaceSet+1],
04426                SO->FaceSetList[3*SO->SelectedFaceSet+2]);
04427             XtVaSetValues(SO->SurfCont->FaceTable->cells[2], XmNvalue, str, NULL);
04428          } else {
04429             XtVaSetValues(SO->SurfCont->FaceTable->cells[1], XmNvalue, "-1", NULL);
04430             SO->SurfCont->FaceTable->num_value[1] = -1;
04431             XtVaSetValues(SO->SurfCont->FaceTable->cells[2], XmNvalue, "x, x, x", NULL);
04432          }
04433       }
04434    }
04435          
04436    SUMA_RETURN(YUP);
04437    
04438 }
04439 
04440 /*!
04441    \brief set the values of the cross-hair group in the surface controller
04442    
04443    \sa SUMA_Init_SurfCont_SurfParam
04444    \sa SUMA_InitializeColPlaneShell
04445    \sa the set of SUMA_UpdateNode*Field functions
04446 */
04447 SUMA_Boolean SUMA_Init_SurfCont_CrossHair(SUMA_SurfaceObject *SO)
04448 {
04449    static char FuncName[]={"SUMA_Init_SurfCont_CrossHair"};
04450    int i;
04451    SUMA_Boolean LocalHead = NOPE;
04452 
04453    SUMA_ENTRY;
04454 
04455    if (!SO) SUMA_RETURN(YUP);
04456 
04457    /* set the cross hair and related fields */
04458    SUMA_UpdateTriField(SO);
04459    SUMA_UpdateNodeField(SO);
04460    /* look for a viewer that is showing this surface and has this surface in focus*/
04461    for (i=0; i<SUMAg_N_SVv; ++i) {
04462       if (LocalHead) fprintf (SUMA_STDERR,"%s: Checking viewer %d.\n", FuncName, i);
04463       if (!SUMAg_SVv[i].isShaded && SUMAg_SVv[i].X->TOPLEVEL) {
04464          /* is this viewer showing SO ? */
04465          if (SUMA_isVisibleSO(&(SUMAg_SVv[i]), SUMAg_DOv, SO)) {
04466             if ((SUMAg_DOv[SUMAg_SVv[i].Focus_SO_ID].OP) == SO) {
04467                SUMA_UpdateXhairField(&(SUMAg_SVv[i]));
04468             }
04469          }
04470       }
04471    }
04472 
04473    SUMA_RETURN(YUP);
04474 }
04475 
04476 /*!
04477    Load Cmap callback 
04478    Expect SO in data
04479 */
04480 void SUMA_cb_Cmap_Load(Widget w, XtPointer data, XtPointer client_data)
04481 {
04482    static char FuncName[]={"SUMA_cb_Cmap_Load"};
04483    SUMA_LIST_WIDGET *LW=NULL;
04484    SUMA_SurfaceObject *SO=NULL;
04485    DList *list = NULL;
04486    SUMA_EngineData *ED = NULL;
04487    DListElmt *NextElm = NULL;
04488    SUMA_Boolean LocalHead = NOPE;
04489     
04490    SUMA_ENTRY;
04491    
04492    SUMA_LH("Called");
04493    
04494    SO = (SUMA_SurfaceObject *)data;
04495    
04496    if (!list) list = SUMA_CreateList();
04497    ED = SUMA_InitializeEngineListData (SE_OpenCmapFileSelection);
04498    if (!(NextElm = SUMA_RegisterEngineListCommand (  list, ED,
04499                                           SEF_vp, (void *)SO,
04500                                           SES_Suma, NULL, NOPE,
04501                                           SEI_Head, NULL))) {
04502       fprintf (SUMA_STDERR, "Error %s: Failed to register command.\n", FuncName);
04503    }
04504    SUMA_RegisterEngineListCommand (  list, ED,
04505                                      SEF_ip, (void *)SO->SurfCont->TopLevelShell,
04506                                      SES_Suma, NULL, NOPE,
04507                                      SEI_In, NextElm);
04508    if (!SUMA_Engine (&list)) {
04509       fprintf(SUMA_STDERR, "Error %s: SUMA_Engine call failed.\n", FuncName);
04510    }
04511    
04512    SUMA_RETURNe;
04513 }
04514 
04515 /*! Loads a colormap file and adds it to the list of colormaps */
04516 /*!
04517    \brief Loads a Dset file and adds it to the list of datasets
04518    
04519    \param dlg (SUMA_SELECTION_DIALOG_STRUCT *) struture from selection dialogue
04520 */
04521 void SUMA_LoadCmapFile (char *filename, void *data)
04522 {
04523    static char FuncName[]={"SUMA_LoadCmapFile"};
04524    SUMA_SurfaceObject *SO = NULL;
04525    SUMA_OVERLAY_PLANE_DATA sopd;
04526    SUMA_IRGB *irgb=NULL;
04527    int OverInd = -1, lnp=-1, loc[2];
04528    char *np=NULL;
04529    int bringup = 0;
04530    SUMA_DSET_FORMAT form;
04531    DList *list=NULL;
04532    SUMA_LIST_WIDGET *LW=NULL;
04533    SUMA_COLOR_MAP *Cmap=NULL;
04534    SUMA_PARSED_NAME * pn=NULL;
04535    SUMA_Boolean LocalHead = NOPE;
04536       
04537    SUMA_ENTRY;
04538 
04539    if (!data) {
04540       SUMA_SLP_Err("Null data"); 
04541       SUMA_RETURNe;
04542    }
04543    
04544    if (!SUMAg_CF->scm) {   
04545       SUMAg_CF->scm = SUMA_Build_Color_maps();
04546       if (!SUMAg_CF->scm) {
04547          SUMA_SL_Err("Failed to build color maps.\n");
04548          SUMA_RETURNe;
04549       }
04550    }
04551    
04552    SO = (SUMA_SurfaceObject *)data;
04553    
04554    if (LocalHead) {
04555       fprintf (SUMA_STDERR,"%s: Received request to load %s for surface %s.\n", FuncName, filename, SO->Label);
04556    }
04557 
04558    /* find out if file exists and how many values it contains */
04559    if (!SUMA_filexists(filename)) {
04560       SUMA_SLP_Err("File not found");
04561       SUMA_RETURNe;
04562    }
04563 
04564    /* take a stab at the format */
04565    form = SUMA_GuessFormatFromExtension(filename);
04566    
04567    /* load the baby */
04568    Cmap = NULL;
04569    switch (form) {
04570       case  SUMA_1D:
04571          Cmap = SUMA_Read_Color_Map_1D (filename);
04572          if (Cmap == NULL) {
04573             SUMA_SLP_Err("Could not load colormap.");
04574             SUMA_RETURNe; 
04575          }
04576          break;
04577       case SUMA_ASCII_NIML:
04578       case SUMA_BINARY_NIML:
04579       case SUMA_NIML:
04580          SUMA_SLP_Err("Not ready for this format yet.");
04581          break;
04582       default:
04583          SUMA_SLP_Err(  "Format not recognized.\n"
04584                         "I won't try to guess.\n"
04585                         "Do use the proper extension.");
04586          break;
04587    }
04588    
04589    if (!Cmap) SUMA_RETURNe;
04590 
04591    /* have Cmap, add to dbase */
04592 
04593    /* remove path from name for pretty purposes */
04594    pn = SUMA_ParseFname(Cmap->Name);
04595    SUMA_STRING_REPLACE(Cmap->Name, pn->FileName_NoExt);
04596    SUMA_Free_Parsed_Name(pn); pn = NULL;
04597    SUMAg_CF->scm->CMv = SUMA_Add_ColorMap (Cmap, SUMAg_CF->scm->CMv, &(SUMAg_CF->scm->N_maps)); 
04598    
04599    /* Now you need to close any pre-existing switch Cmap window */
04600    bringup = 0;
04601    if (SUMAg_CF->X->SwitchCmapLst) {
04602       if (SUMAg_CF->X->SwitchCmapLst->toplevel && !SUMAg_CF->X->SwitchCmapLst->isShaded) {
04603          /* close that baby */
04604          SUMA_cb_CloseSwitchCmap( NULL,  (XtPointer)SUMAg_CF->X->SwitchCmapLst,  NULL);
04605          bringup = 1;
04606       }
04607    }
04608    /* refresh the list */
04609    SUMA_CmapSelectList(SO, 1, bringup);
04610    
04611    /* update the menu buttons */
04612    SUMA_CreateUpdatableCmapMenu(SO);
04613    
04614    /* Set the menu button to the current choice */
04615    if (!SUMA_SetCmapMenuChoice (SO, Cmap->Name)) {
04616       SUMA_SL_Err("Failed in SUMA_SetCmapMenuChoice");
04617    }
04618 
04619    /* switch to the recently loaded  cmap */
04620    if (!SUMA_SwitchColPlaneCmap(SO, Cmap)) {
04621       SUMA_SL_Err("Failed in SUMA_SwitchColPlaneCmap");
04622    }
04623    
04624    /* update Lbl fields */
04625    SUMA_UpdateNodeLblField(SO);
04626 
04627    SUMA_RETURNe;
04628 }
04629 
04630 #ifdef SUMA_SHOW_CMAP_STAND_ALONE
04631 
04632 /* This was to test the X way of displaying a colormap. 
04633 TO HELL WITH IT, used OpenGL instead
04634 */
04635 
04636 static MCW_DC *cmapdc = NULL;
04637 static char * vcl[] =  { "StaticGray"  , "GrayScale" , "StaticColor" ,
04638                          "PseudoColor" , "TrueColor" , "DirectColor"  } ;
04639 
04640 static XImage * xim    = NULL ;
04641 static int      xim_ww = 0 ;
04642 static int      xim_hh = 0 ;
04643 
04644 
04645 /*-------------------------------------------------------------------*/
04646 #ifdef __GNUC__
04647 # define INLINE inline
04648 #else
04649 # define INLINE /*nada*/
04650 #endif
04651 /*-------------------------------------------------------------------*/
04652 /*! Local copy of function from display.c (and from xim.c)
04653 ---------------------------------------------------------------------*/
04654 static INLINE Pixel SUMA_tc_rgb_to_pixel( MCW_DC * dc, byte rr, byte gg, byte bb )
04655 {
04656    static MCW_DC * dcold=NULL ;
04657    DC_colordef * cd = dc->cdef ;
04658    static unsigned long pold=0 ;
04659    static byte rold=0 , gold=0 , bold=0 ;
04660    unsigned long r , g , b ;
04661 
04662    if( cd == NULL ){ reload_DC_colordef(dc) ; cd = dc->cdef ; }
04663 
04664    if( rr == 0   && gg == 0   && bb == 0   ) return 0 ;          /* common */
04665    if( rr == 255 && gg == 255 && bb == 255 ) return cd->whpix ;  /* cases  */
04666 
04667    if( dc == dcold && rr == rold && gg == gold && bb == bold ) /* Remembrance of Things Past? */
04668       return (Pixel) pold ;
04669 
04670    rold = rr ; gold = gg ; bold = bb ; dcold = dc ;            /* OK, remember for next time */
04671 
04672    r = (cd->rrshift<0) ? (rr<<(-cd->rrshift))
04673                        : (rr>>cd->rrshift)   ; r = r & cd->rrmask ;
04674 
04675    g = (cd->ggshift<0) ? (gg<<(-cd->ggshift))
04676                        : (gg>>cd->ggshift)   ; g = g & cd->ggmask ;
04677 
04678    b = (cd->bbshift<0) ? (bb<<(-cd->bbshift))
04679                        : (bb>>cd->bbshift)   ; b = b & cd->bbmask ;
04680 
04681    pold = r | g | b ;  /* assemble color from components */
04682    return (Pixel) pold ;
04683 }
04684 
04685 XImage *SUMA_cmap_to_XImage (Widget wid, SUMA_COLOR_MAP *cm)
04686 {
04687    static char FuncName[]={"SUMA_cmap_to_XImage"};
04688    Pixel * par ;
04689    int ii;
04690    SUMA_Boolean LocalHead = NOPE;
04691    
04692    SUMA_ENTRY;
04693    
04694    if (!cm) { SUMA_SL_Err("NULL cm"); SUMA_RETURN(xim); }
04695    if (!wid) { SUMA_SL_Err("NULL wid"); SUMA_RETURN(xim); }
04696    
04697    if (!cmapdc) {
04698       SUMA_LH("Initializing cmapdc");
04699       cmapdc = MCW_new_DC( wid, 128, 0, NULL,NULL, 1.0, 0 );
04700       SUMA_LH("Initialization done");
04701       if (!cmapdc) { SUMA_SL_Err("Failed in MCW_new_DC"); SUMA_RETURN(xim); }
04702       switch( cmapdc->visual_class ){
04703          case TrueColor:   break ;
04704          case PseudoColor: 
04705             SUMA_SL_Err("No PseudoColor support here.");
04706             SUMA_RETURN(xim);
04707       }   
04708    } 
04709    
04710    /* create XImage*/
04711    par = (Pixel *) malloc(sizeof(Pixel)*cm->N_Col); 
04712    if( par == NULL ) {
04713       SUMA_SL_Err("Failed to allocate");
04714       SUMA_RETURN(NULL) ;
04715    }
04716    SUMA_LH("rgb to pixel");
04717    for( ii=0 ; ii < cm->N_Col ; ii++ ) {
04718      par[ii] = SUMA_tc_rgb_to_pixel(  cmapdc , 
04719                                  (byte)(cm->M[ii][0]/255.0),
04720                                  (byte)(cm->M[ii][1]/255.0),
04721                                  (byte)(cm->M[ii][2]/255.0) ) ;
04722 
04723    }
04724    
04725    SUMA_LH("pixar_to_XImage");
04726    xim = pixar_to_XImage( cmapdc , cm->N_Col , 1 , par ) ;
04727    
04728    free(par);   
04729    SUMA_RETURN(xim);
04730 }
04731 
04732 void usage_ShowCmap()
04733 {
04734    static char FuncName[]={"usage_ShowCmap"};
04735    char * s = NULL;
04736       s = SUMA_help_basics();
04737       printf ( "\nUsage:  \n"
04738                "%s\n"
04739                "\n", s); SUMA_free(s); s = NULL;
04740       s = SUMA_New_Additions(0, 1); printf("%s\n", s);SUMA_free(s); s = NULL;
04741      printf("      Ziad S. Saad SSCC/NIMH/NIH ziad@nih.gov \n\t\t Tue Dec 30\n"
04742             "\n");   
04743 }
04744 void fred_CB( Widget w , XtPointer cd , XtPointer cb ){ exit(0); }
04745 void elvis_CB( Widget w , XtPointer cd , XtPointer cb )
04746 {
04747    static int needGC = 1 ;
04748    static  GC myGC ;
04749    XmDrawingAreaCallbackStruct * cbs = (XmDrawingAreaCallbackStruct *) cb ;
04750    XExposeEvent * ev = (XExposeEvent *) cbs->event ;
04751    Dimension nx , ny ;
04752    int ii , jj ;
04753 
04754    if( cbs->reason != XmCR_EXPOSE || ev->count > 0 ) return ;
04755 
04756    if( needGC ){
04757      XGCValues  gcv;
04758      gcv.function = GXcopy ;
04759      myGC  = XCreateGC( XtDisplay(w) , XtWindow(w) , GCFunction , &gcv ) ;
04760      needGC = 0 ;
04761    }
04762 
04763    XtVaGetValues( w , XmNwidth  , &nx , XmNheight , &ny , NULL ) ;
04764 
04765    ii = 0 ;
04766    do{
04767       jj = 0 ;
04768       do{
04769          XPutImage( XtDisplay(w),XtWindow(w),myGC,xim,0,0,ii,jj,xim_ww,xim_hh) ;
04770          jj += xim_hh + 4 ;
04771       } while( jj < ny ) ;
04772       ii += xim_ww ;
04773    } while( ii < nx ) ;
04774 
04775    return ;
04776 }
04777 
04778 
04779 int main (int argc,char *argv[])
04780 {/* Main */
04781    static char FuncName[]={"ShowCmap"};
04782    int kar, i;
04783    SUMA_Boolean brk;
04784    SUMA_COLOR_MAP *cmap;
04785    int icmap;
04786 
04787    SUMA_Boolean LocalHead = NOPE;
04788    
04789    SUMA_mainENTRY;
04790    
04791    SUMA_STANDALONE_INIT;
04792    
04793    if (!SUMAg_CF->scm) {   
04794       SUMAg_CF->scm = SUMA_Build_Color_maps();
04795       if (!SUMAg_CF->scm) {
04796          SUMA_SL_Err("Failed to build color maps.\n");
04797          SUMA_RETURN(0);
04798       }
04799    }
04800    
04801    icmap = SUMA_Find_ColorMap ("bgyr64", SUMAg_CF->scm->CMv, SUMAg_CF->scm->N_maps, -2 );
04802    if (icmap < 0) { SUMA_SL_Err("Failed to find ColMap"); SUMA_RETURN(0); }
04803    cmap = SUMAg_CF->scm->CMv[icmap];
04804    
04805    #ifdef Xway
04806    {
04807       XtAppContext    app;            /* the application context */
04808       Widget          top;            /* toplevel widget */
04809       Display         *dpy;           /* display */
04810       Colormap        colormap;       /* created colormap */
04811       XVisualInfo     vinfo;          /* template for find visual */
04812       Visual          *vis ;          /* the Visual itself */
04813       XVisualInfo     *vinfo_list;    /* returned list of visuals */
04814       int             count;          /* number of matchs (only 1?) */
04815       int             vid , stat ;
04816       Widget          fred , fff ;
04817       
04818       SUMA_S_Note("XtVaCreateWidget");
04819       top = XtVaAppInitialize( &app , "test" , NULL , 0 , &argc , argv , NULL , NULL ) ;
04820       dpy = XtDisplay (top);
04821       SUMA_S_Note("XGetVisualInfo");
04822 
04823       vinfo.screen = DefaultScreen(dpy);
04824       vinfo_list = XGetVisualInfo (dpy, VisualScreenMask, &vinfo, &count);
04825       if( count == 0 || vinfo_list == NULL ){fprintf(stderr,"no match\n");exit(1);}
04826       vinfo = vinfo_list[0] ;
04827       vid = vinfo.visualid ;
04828       vis = vinfo.visual ;
04829 
04830       SUMA_S_Note("XCreateColormap");
04831       colormap = XCreateColormap( dpy, RootWindowOfScreen(XtScreen(top)) ,
04832                                  vis , AllocNone ) ;
04833 
04834       XtVaSetValues( top ,
04835                        XtNborderColor , 0 ,
04836                        XtNbackground  , 0 ,
04837                        XtNdepth       , vinfo.depth ,
04838                        XtNcolormap    , colormap ,
04839                        XtNvisual      , vis ,
04840                     NULL ) ;
04841 
04842       fff = XtVaCreateWidget( "dialog" , xmFormWidgetClass , top ,
04843                               XmNborderWidth , 0 ,
04844                               NULL ) ;
04845 
04846       #ifndef LABEL_ARG
04847       #define LABEL_ARG(str) \
04848         XtVaTypedArg , XmNlabelString , XmRString , (str) , strlen(str)+1
04849       #endif
04850 
04851       fred = XtVaCreateManagedWidget( "dialog" , xmPushButtonWidgetClass , fff ,
04852                                        LABEL_ARG("Jumpback") ,
04853                                        XmNtopAttachment    , XmATTACH_FORM ,
04854                                        XmNleftAttachment   , XmATTACH_FORM ,
04855                                        XmNrightAttachment  , XmATTACH_FORM ,
04856                                       NULL ) ;
04857       XtAddCallback( fred , XmNactivateCallback , fred_CB , NULL ) ;
04858 
04859       fred = XtVaCreateManagedWidget( "dialog" , xmDrawingAreaWidgetClass , fff ,
04860                                        XmNtopAttachment    , XmATTACH_WIDGET ,
04861                                        XmNtopWidget        , fred ,
04862                                        XmNleftAttachment   , XmATTACH_FORM ,
04863                                        XmNrightAttachment  , XmATTACH_FORM ,
04864                                        XmNbottomAttachment , XmATTACH_FORM ,
04865                                      NULL ) ;
04866 
04867       XtAddCallback( fred , XmNexposeCallback , elvis_CB , NULL ) ;
04868 
04869       SUMA_SL_Note("SUMA_cmap_to_XImage");
04870       xim = SUMA_cmap_to_XImage(fred, cmap);
04871 
04872       SUMA_SL_Note("XPutImage");
04873       xim_ww = cmap->N_Col;
04874       xim_hh = 20;
04875 
04876       XtVaSetValues( top ,
04877                       XmNwidth , xim_ww ,
04878                       XmNheight , xim_hh+40 ,
04879                     NULL ) ;
04880 
04881       XtManageChild(fff) ;
04882       XtRealizeWidget(top);
04883       XtAppMainLoop(app);
04884    }
04885    #else 
04886    {  /* do the deed with OPENGL */
04887       
04888    
04889    }
04890    #endif
04891    if (!SUMA_Free_CommonFields(SUMAg_CF)) SUMA_error_message(FuncName,"SUMAg_CF Cleanup Failed!",1);
04892    SUMA_RETURN (0);
04893 }
04894 
04895 #endif   /* end of SUMA_SHOW_CMAP_STAND_ALONE */
 

Powered by Plone

This site conforms to the following standards: