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_SVmanip.c

Go to the documentation of this file.
00001 
00002 #include "SUMA_suma.h"
00003 
00004 extern SUMA_CommonFields *SUMAg_CF;
00005 extern int SUMAg_N_DOv; 
00006 extern SUMA_DO *SUMAg_DOv;
00007 extern SUMA_SurfaceViewer *SUMAg_SVv;
00008 extern int SUMAg_N_SVv;
00009 
00010 /*!
00011    \brief a function that returns the first viewer that is in momentum mode 
00012    isv = SUMA_WhichViewerInMomentum( SVv,  N_SV,  sv); 
00013    
00014    \param SVv (SUMA_SurfaceViewer *) vector of surface viewers
00015    \param N_SV (int ) number of surface viewer structures in SVv
00016    \param sv (SUMA_SurfaceViewer *) if !NULL then the function returns the
00017             index of a surface viewer OTHER THAN sv that is in momentum mode.
00018             Otherwise the first surface viewer in momentum mode is returned
00019    \return isv (int) the index (into SVv) of the first viewer that is in
00020             momentum mode. If sv is not NULL then it is the index of the 
00021             first viewer OTHER THAN sv that is in momentum mode
00022             If none are found, ans = -1
00023    
00024    -  To turn the index into the viewer's label use: 
00025       if (isv >= 0) sprintf(slabel,"[%c] SUMA", 65+isv); 
00026       else sprintf(slabel,"[DOH] SUMA");
00027 */
00028 
00029 int SUMA_WhichViewerInMomentum(SUMA_SurfaceViewer *SVv, int N_SV, SUMA_SurfaceViewer *sv) 
00030 {
00031    static char FuncName[]={"SUMA_WhichViewerInMomentum"};
00032    int ii = -1;
00033    
00034    SUMA_ENTRY;
00035    
00036    if (!SVv) SUMA_RETURN(-1);
00037    
00038    for (ii=0; ii < SUMAg_N_SVv; ++ii) {
00039          if (SVv[ii].GVS[SVv[ii].StdView].ApplyMomentum) {
00040             if (!sv) { /* don't care which one */
00041                SUMA_RETURN(ii);
00042             } else if (&(SUMAg_SVv[ii]) != sv) { /* other than sv */
00043                SUMA_RETURN(ii);
00044             }
00045          }
00046    }
00047    
00048    SUMA_RETURN(-1);
00049    
00050 }
00051  
00052 /* This is used to hold the functions that manipulate SV, Surface Viewer Structures */
00053 /*! 
00054 \brief returns a string corresponding to the link type
00055 
00056 SUMA_Boolean SUMA_LockEnum_LockType (SUMA_LINK_TYPES i, char *Name);
00057 \param i (SUMA_LINK_TYPES) see enum type in SUMA_define.h
00058 \param Name (char *) a preallocated character string (no more than 50 chars)
00059 \return YUP/NOPE OK, error
00060 */
00061 SUMA_Boolean SUMA_LockEnum_LockType (SUMA_LINK_TYPES i, char *Name)
00062 {
00063    static char FuncName[]={"SUMA_LockEnum_LockType"};
00064    SUMA_ENTRY;   
00065    
00066    switch (i) {
00067       case SUMA_No_Lock:
00068          sprintf (Name, "No Lock");
00069          break;
00070       case SUMA_I_Lock:
00071          sprintf (Name, "Index Lock");
00072          break;
00073       case SUMA_XYZ_Lock:
00074          sprintf (Name, "XYZ Lock");
00075          break;
00076       default:
00077          sprintf (Name, "?");
00078          SUMA_RETURN (NOPE);
00079          
00080    }
00081    
00082    SUMA_RETURN (YUP);
00083 }
00084 /*!
00085 Create a SurfaceViewer data structure
00086 */
00087 SUMA_SurfaceViewer *SUMA_Alloc_SurfaceViewer_Struct (int N)
00088 {
00089    SUMA_SurfaceViewer *SV, *SVv;
00090    static char FuncName[]={"SUMA_Alloc_SurfaceViewer_Struct"};
00091    int i, j, n;
00092    
00093    SUMA_ENTRY;
00094 
00095    SVv =  (SUMA_SurfaceViewer *)SUMA_malloc(sizeof(SUMA_SurfaceViewer)*N);
00096    if (SVv == NULL) {
00097       fprintf(SUMA_STDERR,"Error %s: Failed to SUMA_malloc SV\n", FuncName);
00098       SUMA_RETURN (NULL);
00099    }
00100    for (i=0; i < N; ++i) {
00101       SV = &(SVv[i]);
00102       
00103       SV->N_GVS = SUMA_N_STANDARD_VIEWS;
00104       SV->GVS = (SUMA_GEOMVIEW_STRUCT *)SUMA_malloc(sizeof(SUMA_GEOMVIEW_STRUCT)*SV->N_GVS);
00105       if (!SV->GVS) {
00106          fprintf(SUMA_STDERR,"Error %s: Could not allocate for N_GVS.\n", FuncName);
00107          SUMA_RETURN (NULL);
00108       }
00109       SV->StdView = SUMA_3D; /* default */
00110       
00111       /* set the standards for all viewing modes here */
00112       SV->verbose = 1;
00113       {
00114          char *eee = getenv("SUMA_AdjustMouseMotionWithZoom");
00115          if (eee) {
00116             if (strcmp (eee, "YES") == 0) SV->ZoomCompensate = 1.0;
00117             else SV->ZoomCompensate = 0.0;
00118          } else {
00119             SV->ZoomCompensate = 1.0; 
00120          }
00121       }
00122       {
00123          char *eee = getenv("SUMA_ViewOrthographicProjection");
00124          if (eee) {
00125             if (strcmp (eee, "YES") == 0) SV->ortho = 1;
00126             else SV->ortho = 0;
00127          } else {
00128             SV->ortho = 0; 
00129          }
00130       }
00131 
00132       SV->Aspect = 1.0;
00133       SV->FOV = NULL;
00134       for (j=0; j < SV->N_GVS; ++j) {
00135          switch (j) {
00136             case SUMA_2D_Z0:
00137                SV->GVS[j].currentQuat[0] = 0.252199;
00138                SV->GVS[j].currentQuat[1] = -0.129341;
00139                SV->GVS[j].currentQuat[2] = -0.016295;
00140                SV->GVS[j].currentQuat[3] = 0.958854;
00141 
00142                SV->GVS[j].ApplyMomentum = False;
00143 
00144                SV->GVS[j].MinIdleDelta = 1;
00145                SV->GVS[j].TranslateGain = TRANSLATE_GAIN;
00146                SV->GVS[j].ArrowtranslateDeltaX = ARROW_TRANSLATE_DELTAX;
00147                SV->GVS[j].ArrowtranslateDeltaY = ARROW_TRANSLATE_DELTAY;
00148 
00149                SV->GVS[j].ViewCamUp[0] = 0.0;
00150                SV->GVS[j].ViewCamUp[1] = 1.0;
00151                SV->GVS[j].ViewCamUp[2] = 0.0;
00152 
00153                SV->GVS[j].ViewFrom[0] = 0.0;
00154                SV->GVS[j].ViewFrom[1] = 0.0;
00155                SV->GVS[j].ViewFrom[2] = SUMA_DEFAULT_VIEW_FROM;
00156 
00157                SV->GVS[j].ViewCenter[0] = 0.0;
00158                SV->GVS[j].ViewCenter[1] = 0.0;
00159                SV->GVS[j].ViewCenter[2] = 0.0;
00160 
00161                SV->GVS[j].RotaCenter[0] = 0.0;
00162                SV->GVS[j].RotaCenter[1] = 0.0;
00163                SV->GVS[j].RotaCenter[2] = 0.0;
00164                break;
00165             case SUMA_3D:
00166                SV->GVS[j].currentQuat[0] = 0.252199;
00167                SV->GVS[j].currentQuat[1] = -0.129341;
00168                SV->GVS[j].currentQuat[2] = -0.016295;
00169                SV->GVS[j].currentQuat[3] = 0.958854;
00170 
00171                SV->GVS[j].ApplyMomentum = False;
00172 
00173                SV->GVS[j].MinIdleDelta = 1;
00174                SV->GVS[j].TranslateGain = TRANSLATE_GAIN;
00175                SV->GVS[j].ArrowtranslateDeltaX = ARROW_TRANSLATE_DELTAX;
00176                SV->GVS[j].ArrowtranslateDeltaY = ARROW_TRANSLATE_DELTAY;
00177 
00178                SV->GVS[j].ViewCamUp[0] = 0.0;
00179                SV->GVS[j].ViewCamUp[1] = 1.0;
00180                SV->GVS[j].ViewCamUp[2] = 0.0;
00181 
00182                SV->GVS[j].ViewFrom[0] = 0.0;
00183                SV->GVS[j].ViewFrom[1] = 0.0;
00184                SV->GVS[j].ViewFrom[2] = 0.0;
00185 
00186                SV->GVS[j].ViewCenter[0] = 0.0;
00187                SV->GVS[j].ViewCenter[1] = 0.0;
00188                SV->GVS[j].ViewCenter[2] = 0.0;
00189 
00190                SV->GVS[j].RotaCenter[0] = 0.0;
00191                SV->GVS[j].RotaCenter[1] = 0.0;
00192                SV->GVS[j].RotaCenter[2] = 0.0;
00193                
00194                SV->GVS[j].translateVec[0] = 0.0;
00195                SV->GVS[j].translateVec[1] = 0.0;
00196                break;
00197             default:
00198                fprintf(SUMA_STDERR,"Error %s: Undefined viewing mode.\n", FuncName);
00199                SUMA_RETURN (NULL);
00200                
00201          }
00202       }
00203       
00204 
00205       SV->light0_position[0] = 0.0;
00206       SV->light0_position[1] = 0.0;
00207       
00208       SV->light0_position[2] = 1.0 * SUMA_INTITIAL_LIGHT0_SWITCH; 
00209       SV->light0_position[3] = 0.0;
00210 
00211       SV->light1_position[0] = 1.0;
00212       SV->light1_position[1] = 1.0;
00213       SV->light1_position[2] = 1.0;
00214       SV->light1_position[3] = 0.0;
00215 
00216       {
00217          static SUMA_Boolean err = NOPE;
00218          float fv3[3];
00219          char *eee = getenv("SUMA_BackgroundColor");
00220          if (eee && !err) {
00221             if (SUMA_StringToNum (eee, fv3, 3) != 3) { 
00222                err = YUP;
00223                SUMA_SL_Err("Syntax error in environment\n"
00224                            "variable SUMA_BackgroundColor");
00225                SV->clear_color[0] = SUMA_CLEAR_COLOR_R;
00226                SV->clear_color[1] = SUMA_CLEAR_COLOR_G;
00227                SV->clear_color[2] = SUMA_CLEAR_COLOR_B;
00228                SV->clear_color[3] = SUMA_CLEAR_COLOR_A;
00229             }else {
00230                SV->clear_color[0] = fv3[0];
00231                SV->clear_color[1] = fv3[1];
00232                SV->clear_color[2] = fv3[2];
00233                SV->clear_color[3] = SUMA_CLEAR_COLOR_A;  
00234             }
00235          }else {
00236             SV->clear_color[0] = SUMA_CLEAR_COLOR_R;
00237             SV->clear_color[1] = SUMA_CLEAR_COLOR_G;
00238             SV->clear_color[2] = SUMA_CLEAR_COLOR_B;
00239             SV->clear_color[3] = SUMA_CLEAR_COLOR_A;   
00240          } 
00241       }
00242       
00243       
00244       SV->WindWidth = 350;
00245       SV->WindHeight = 350;
00246       {
00247          char *eee = getenv("SUMA_ArrowRotAngle");
00248          if (eee) {
00249             float rotval = strtod(eee, NULL);
00250             if (rotval > 0.0 && rotval < 360.0) SV->ArrowRotationAngle = SUMA_PI * rotval / 180.0;
00251             else SV->ArrowRotationAngle = SUMA_PI * ARROW_ROTATION_ANGLE_DEG / 180.0;
00252          } else SV->ArrowRotationAngle = SUMA_PI * ARROW_ROTATION_ANGLE_DEG / 180.0;
00253       }
00254       
00255       SV->Open = NOPE;
00256       
00257       SV->RegisteredDO = (int *)SUMA_calloc( SUMA_MAX_DISPLAYABLE_OBJECTS, sizeof(int));
00258       if (SV->RegisteredDO == NULL) {
00259          fprintf(stderr,"Error SUMA_Alloc_SurfaceViewer_Struct: Failed to SUMA_malloc SV->RegisteredDO\n");
00260          SUMA_RETURN (NULL);
00261       }
00262       SV->N_DO = 0; /* Nothing is registered with the viewer yet */
00263 
00264       SV->ColList = (SUMA_COLORLIST_STRUCT *) SUMA_malloc( sizeof(SUMA_COLORLIST_STRUCT) * SUMA_MAX_DISPLAYABLE_OBJECTS);
00265       SV->N_ColList = 0; /* this number reflects the number of surfaces that have colorlist structures in SV */
00266       /* initialize fields */
00267       for (j=0; j<SUMA_MAX_DISPLAYABLE_OBJECTS; ++j) {
00268          SV->ColList[j].idcode_str = NULL;
00269          SV->ColList[j].glar_ColorList = NULL;
00270          SV->ColList[j].N_glar_ColorList = 0;
00271          SV->ColList[j].Remix = NOPE;
00272       }
00273       
00274       
00275       SV->ShowEyeAxis = 1;
00276       SV->ShowMeshAxis = 0;      /* Turned off Oct 15 04 in favor of WorldAxis */
00277       SV->ShowWorldAxis = SUMA_NO_WAX;
00278       
00279       
00280       SV->WAx = SUMA_Alloc_Axis ("Viewer World Axis");
00281 
00282       if (SV->WAx == NULL) {
00283          fprintf(SUMA_STDERR,"Error %s: Error Allocating axis\n", FuncName);
00284          SUMA_RETURN(NULL);
00285       }
00286       SV->WAx->type = SUMA_SCALE_BOX;
00287 
00288       SV->Ch = SUMA_Alloc_CrossHair ();
00289       if (SV->Ch == NULL) {
00290          fprintf(stderr,"Error SUMA_Alloc_SurfaceViewer_Struct: Failed in SUMA_Alloc_CrossHair\n");
00291          SUMA_RETURN (NULL); 
00292       } else SV->ShowCrossHair = 1;
00293       
00294       SV->X = (SUMA_X *)SUMA_malloc(sizeof(SUMA_X));
00295       if (SV->X == NULL) {
00296          fprintf(stderr,"Error SUMA_Alloc_SurfaceViewer_Struct: Failed to SUMA_malloc SV->X\n");
00297          SUMA_RETURN (NULL);
00298       }
00299 
00300       SV->X->Title = NULL;
00301       SV->X->LookAt_prmpt = NULL;
00302       SV->X->JumpIndex_prmpt = NULL;
00303       SV->X->JumpXYZ_prmpt = NULL;
00304       SV->X->JumpFocusNode_prmpt = NULL;
00305       SV->X->JumpFocusFace_prmpt = NULL;
00306       SV->X->HighlightBox_prmpt = NULL;
00307       SV->X->TOPLEVEL = NULL;
00308       SV->X->MOMENTUMID = 0;
00309       SV->X->REDISPLAYPENDING = 0;
00310       SV->X->DOUBLEBUFFER = True;
00311       SV->X->WIDTH = SV->X->HEIGHT = 300; /* if you change this, make sure you do so for fallbackResources in SUMA_display */
00312       SV->X->ViewCont = SUMA_CreateViewContStruct();
00313       
00314       SV->Focus_SO_ID = -1;
00315       SV->Focus_DO_ID = -1;
00316       
00317       SV->VSv = NULL;
00318       SV->N_VSv = 0;
00319       SV->LastNonMapStateID = -1;
00320       
00321       SV->iCurGroup = -1;
00322       SV->CurGroupName = NULL;
00323       
00324       SV->PolyMode = SRM_Fill;
00325       
00326       #if SUMA_BACKFACE_CULL
00327          SV->BF_Cull = YUP;
00328       #else
00329          SV->BF_Cull = NOPE;
00330       #endif
00331 
00332       SV->ShowForeground = YUP;
00333       SV->ShowBackground = YUP;
00334       
00335       {
00336          char *eee = getenv("SUMA_CenterOnPatch");
00337          if (eee) {
00338             if (strcmp (eee, "YES") == 0) SV->UsePatchDims = YUP;
00339             else SV->UsePatchDims = NOPE;
00340          } else {
00341             SV->UsePatchDims = NOPE;
00342          }
00343       }
00344       SV->Back_Modfact = SUMA_BACKGROUND_MODULATION_FACTOR;
00345       
00346       SV->isShaded = NOPE; 
00347       
00348       SV->LinkAfniCrossHair = YUP;
00349       
00350       SV->ResetGLStateVariables = YUP;
00351       SV->NewGeom = NOPE;
00352       SV->BS = NULL;
00353       
00354       SV->ShowRight = YUP;
00355       SV->ShowLeft = YUP;
00356       SV->Record = NOPE;
00357       SV->rdc = SUMA_RDC_NOT_SET;
00358    }
00359    SUMA_RETURN (SVv);
00360 }
00361 
00362 SUMA_Boolean SUMA_Free_SurfaceViewer_Struct (SUMA_SurfaceViewer *SV)
00363 {
00364    static char FuncName[]={"SUMA_Free_SurfaceViewer_Struct"};
00365    int i;
00366    
00367    SUMA_ENTRY;
00368 
00369    if (SV->WAx) SUMA_Free_Axis(SV->WAx);
00370    if (SV->Ch) SUMA_Free_CrossHair (SV->Ch);
00371    if (SV->X->Title) SUMA_free(SV->X->Title);
00372    if (SV->X->LookAt_prmpt) SUMA_FreePromptDialogStruct (SV->X->LookAt_prmpt);
00373    if (SV->X->JumpIndex_prmpt) SUMA_FreePromptDialogStruct (SV->X->JumpIndex_prmpt);
00374    if (SV->X->JumpXYZ_prmpt) SUMA_FreePromptDialogStruct (SV->X->JumpXYZ_prmpt);
00375    if (SV->X->JumpFocusNode_prmpt) SUMA_FreePromptDialogStruct (SV->X->JumpFocusNode_prmpt);
00376    if (SV->X->JumpFocusFace_prmpt) SUMA_FreePromptDialogStruct (SV->X->JumpFocusFace_prmpt);
00377    if (SV->X->HighlightBox_prmpt) SUMA_FreePromptDialogStruct (SV->X->HighlightBox_prmpt);
00378    if (SV->X->ViewCont) SUMA_FreeViewContStruct(SV->X->ViewCont);
00379    if (SV->X) SUMA_free(SV->X);
00380    if (SV->RegisteredDO) SUMA_free(SV->RegisteredDO);
00381    if (SV->VSv) {
00382       for (i=0; i < SV->N_VSv; ++i) {
00383          if (!SUMA_Free_ViewState (&(SV->VSv[i]))) {
00384             fprintf (SUMA_STDERR,"Error %s: failed in SUMA_Free_ViewState.\n", FuncName);
00385          }
00386       }
00387    }
00388    
00389    if (SV->CurGroupName) SUMA_free(SV->CurGroupName); SV->CurGroupName= NULL;
00390    
00391    if (SV->GVS) SUMA_free(SV->GVS);
00392    if (SV->State) SV->State = NULL; /* never free that one */ 
00393    if (SV->ColList) {
00394       for (i=0; i < SV->N_ColList; ++i) {
00395          if (!SUMA_EmptyColorList (SV, NULL)) fprintf (SUMA_STDERR,"Error %s: failed in SUMA_EmptyColorList.\n", FuncName);
00396       }
00397       /* done dumping structure contents, now free pointer */
00398       SUMA_free(SV->ColList); 
00399       SV->ColList = NULL; 
00400       SV->N_ColList = 0;
00401    }
00402    
00403    if (SV->BS) {
00404       SUMA_EmptyDestroyList(SV->BS);
00405    }
00406    
00407    SUMA_RETURN(YUP);
00408 }
00409 
00410 SUMA_Boolean SUMA_Free_SurfaceViewer_Struct_Vect (SUMA_SurfaceViewer *SVv, int N)
00411 {
00412    static char FuncName[]={"SUMA_Free_SurfaceViewer_Struct_Vect"};
00413    int i;
00414    SUMA_Boolean Ret= YUP;
00415    
00416    SUMA_ENTRY;
00417 
00418    for (i=0; i < N; ++i)  {
00419       if (&SVv[i] != NULL) {
00420          Ret = Ret * SUMA_Free_SurfaceViewer_Struct (&SVv[i]);
00421       }
00422    }
00423    
00424    if (SVv) SUMA_free(SVv);
00425    SUMA_RETURN(Ret);
00426 }
00427 
00428 /*!
00429 \brief ans = SUMA_FillColorList (sv, so);
00430 Creates a colorlist structure for a certain surface.   
00431 
00432 \param sv (SUMA_SurfaceViewer *) pointer to surface viewer
00433 \param so (SUMA_SurfaceObject *) pointer to surface object
00434 
00435 Remix flag is set to YUP since this function is called when surfaces are beging registered
00436 with a viewer and a remix is highly likely.
00437 
00438 \return ans YUP/NOPE
00439 
00440 */
00441 SUMA_Boolean SUMA_FillColorList (SUMA_SurfaceViewer *sv, SUMA_SurfaceObject *SO)
00442 {
00443    static char FuncName[]={"SUMA_FillColorList"};
00444    int i;
00445    SUMA_Boolean LocalHead = NOPE;
00446    
00447    SUMA_ENTRY;
00448    
00449    if (LocalHead) fprintf (SUMA_STDERR,"%s: Filling a color list for surface %s (%s).\n", FuncName, SO->Label, SO->idcode_str);
00450 
00451    if (!SO->idcode_str) {
00452       fprintf (SUMA_STDERR,"Error %s: SO->idcode_str is NULL.\n", FuncName);
00453       SUMA_RETURN (NOPE);
00454    }
00455    
00456    /* make sure SO->idcode_str is not in the list already */
00457    for (i=0; i<sv->N_ColList; ++i) {
00458       if (strcmp (SO->idcode_str, sv->ColList[i].idcode_str) == 0) {
00459          fprintf (SUMA_STDERR,"Error %s: SO->idcode_str is already in sv->ColList.\n", FuncName);
00460          SUMA_RETURN (NOPE);
00461       }
00462    }
00463    
00464    /* create the ColList struct */
00465    if (sv->ColList[sv->N_ColList].glar_ColorList) {
00466       fprintf (SUMA_STDERR,"Error %s: glar_ColorList is not NULL. Cannot reallocate.\n", FuncName);
00467       SUMA_RETURN (NOPE);
00468    }
00469    
00470    SUMA_LH("Pre-alloc\n");
00471    sv->ColList[sv->N_ColList].glar_ColorList = (GLfloat *) SUMA_calloc (SO->N_Node*4, sizeof(GLfloat));
00472    sv->ColList[sv->N_ColList].idcode_str = (char *)SUMA_malloc((strlen(SO->idcode_str)+1) * sizeof(char));
00473    SUMA_LH("Post-alloc\n");
00474    
00475    if (!sv->ColList[sv->N_ColList].glar_ColorList || !sv->ColList[sv->N_ColList].idcode_str) {
00476       fprintf (SUMA_STDERR,"Error %s: Failed to allocate for glar_ColorList or idcode_str.\n", FuncName);
00477       SUMA_RETURN (NOPE);
00478    }
00479    
00480    sv->ColList[sv->N_ColList].idcode_str = strcpy (sv->ColList[sv->N_ColList].idcode_str, SO->idcode_str);
00481    if (LocalHead) fprintf (SUMA_STDERR, "%s: sv->ColList[%d].idcode_str=%s is about to be filled.\n", \
00482                FuncName, sv->N_ColList, sv->ColList[sv->N_ColList].idcode_str);
00483 
00484    /* fill up with blanks, may be unecessary ... */
00485    sv->ColList[sv->N_ColList].N_glar_ColorList = SO->N_Node*4;
00486    i=0;
00487    while (i < sv->ColList[sv->N_ColList].N_glar_ColorList) {
00488       sv->ColList[sv->N_ColList].glar_ColorList[i] = SUMA_GRAY_NODE_COLOR; ++i;
00489       sv->ColList[sv->N_ColList].glar_ColorList[i] = SUMA_GRAY_NODE_COLOR; ++i;
00490       sv->ColList[sv->N_ColList].glar_ColorList[i] = SUMA_GRAY_NODE_COLOR; ++i;
00491       sv->ColList[sv->N_ColList].glar_ColorList[i] = SUMA_NODE_ALPHA; ++i;
00492    }
00493    sv->ColList[sv->N_ColList].Remix = YUP; 
00494 
00495    ++sv->N_ColList;
00496    
00497    SUMA_RETURN (YUP);
00498 
00499 }
00500 
00501 /*!
00502    glar_ColorList = SUMA_GetColorList (sv, DO_idstr);
00503    returns the pointer to the colorlist of the DO (or SO) with ID string DO_idstr
00504    
00505    \param sv (SUMA_SurfaceViewer *) pointer to surface viewer in question
00506    \param DO_idstr (char *) ID string of DO (usually a Surface Object) 
00507    \return glar_ColorList (GLfloat *) a pointer to the array containing node colors 
00508 */
00509 GLfloat * SUMA_GetColorList (SUMA_SurfaceViewer *sv, char *DO_idstr)
00510 {
00511    static char FuncName[]={"SUMA_GetColorList"};
00512    int i;
00513    GLfloat * glar_ColorList = NULL;
00514    SUMA_Boolean Found = NOPE;
00515    
00516    SUMA_ENTRY;
00517    
00518    if (!DO_idstr) {
00519       fprintf (SUMA_STDERR,"Error %s: DO_idstr is NULL, this should not be.\n", FuncName);
00520       SUMA_RETURN (NULL);
00521    }
00522    
00523    /* find the culprit */
00524    Found = NOPE;
00525    i = 0;
00526    while (!Found && i < sv->N_ColList) {
00527       if (strcmp (DO_idstr, sv->ColList[i].idcode_str) == 0) {
00528          Found = YUP;
00529          SUMA_RETURN (sv->ColList[i].glar_ColorList);      
00530       }
00531       ++i;
00532    }
00533    
00534    if (!Found) {
00535       fprintf (SUMA_STDERR,"Error %s: DO_idstr was not found.\n", FuncName);
00536       SUMA_RETURN (NULL);
00537    }
00538    
00539    /* should not get to this point */
00540    fprintf (SUMA_STDERR,"Error %s: Logic error. Should not get here.\n", FuncName);
00541    SUMA_RETURN (NULL);
00542 
00543 }
00544 
00545 /*!
00546 
00547 \brief Empty a colorlist structure 
00548 
00549 ans = SUMA_EmptyColorList (sv, DO_idstr)
00550 
00551 \param sv (SUMA_SurfaceViewer *) pointer to surface viewer in question
00552 \param DO_idstr (char *) ID string of DO (usually a Surface Object) If you want to delete all 
00553                         color lists, set this pointer to NULL
00554 \return ans (SUMA_Boolean) YUP/NOPE 
00555 
00556 */
00557 SUMA_Boolean SUMA_EmptyColorList (SUMA_SurfaceViewer *sv, char *DO_idstr)
00558 {
00559    static char FuncName[]={"SUMA_EmptyColorList"};
00560    int i;
00561    SUMA_Boolean Found = NOPE;
00562    
00563    SUMA_ENTRY;
00564    
00565    if (!sv->ColList) {
00566       fprintf (SUMA_STDERR,"Error %s: sv->ColList is NULL, this should not be.\n", FuncName);
00567       SUMA_RETURN (NOPE);
00568    } 
00569    
00570    if (!DO_idstr) {
00571       /* empty them all */
00572       for (i=0; i < sv->N_ColList; ++i) {
00573          if (sv->ColList[i].glar_ColorList) SUMA_free(sv->ColList[i].glar_ColorList);
00574          sv->ColList[i].glar_ColorList = NULL;
00575          sv->ColList[i].N_glar_ColorList = 0;
00576          if (sv->ColList[i].idcode_str) SUMA_free(sv->ColList[i].idcode_str); 
00577          sv->ColList[i].idcode_str = NULL;
00578          sv->ColList[i].Remix = NOPE;
00579       }   
00580    } else { /* just empty one */
00581       Found = NOPE;
00582       i = 0;
00583       while (!Found && i < sv->N_ColList) {
00584          if (strcmp (DO_idstr, sv->ColList[i].idcode_str) == 0) {
00585             Found = YUP;
00586             /* empty the load */
00587             if (sv->ColList[i].glar_ColorList) SUMA_free(sv->ColList[i].glar_ColorList);
00588             sv->ColList[i].glar_ColorList = NULL;
00589             sv->ColList[i].N_glar_ColorList = 0;
00590             if (sv->ColList[i].idcode_str) SUMA_free(sv->ColList[i].idcode_str); 
00591             sv->ColList[i].idcode_str = NULL;
00592             sv->ColList[i].Remix = NOPE;
00593             /* copy the last in the list here */
00594             if (i < sv->N_ColList) {
00595                sv->ColList[i].glar_ColorList = sv->ColList[sv->N_ColList-1].glar_ColorList;
00596                sv->ColList[i].N_glar_ColorList = sv->ColList[sv->N_ColList-1].N_glar_ColorList;
00597                sv->ColList[i].idcode_str = sv->ColList[sv->N_ColList-1].idcode_str;
00598                sv->ColList[i].Remix = sv->ColList[sv->N_ColList-1].Remix;
00599                
00600                /* mark the last element as empty */
00601                sv->ColList[sv->N_ColList-1].glar_ColorList = NULL;
00602                sv->ColList[sv->N_ColList-1].N_glar_ColorList = 0;
00603                sv->ColList[sv->N_ColList-1].idcode_str = NULL;
00604                sv->ColList[sv->N_ColList-1].Remix = NOPE;
00605                
00606                /* decrement the number of full elements in ColList */
00607                --sv->N_ColList;
00608             }
00609          } 
00610          ++i;
00611       }
00612       if (!Found) {
00613          fprintf (SUMA_STDERR,"Error %s: item %s was not found, this should not be.\n", FuncName, DO_idstr);
00614          SUMA_RETURN (NOPE);
00615       }
00616    }
00617    
00618    SUMA_RETURN (YUP);
00619 }
00620 
00621 /*!
00622    ans = SUMA_SetShownLocalRemixFlag (SUMA_SurfaceViewer *sv)
00623    Set Remix flags for all surfaces in sv->RegisteredDO regardless of their relationship.
00624    This is useful when you change the settings for background color modulation and the like.
00625    \param sv (SUMA_SurfaceViewer *) pointer to surface viewer 
00626    \return ans (SUMA_Boolean) YUP/NOPE
00627    \sa SUMA_SetRemixFlag
00628    \sa SUMA_SetLocalRemixFlag
00629 
00630 */
00631 SUMA_Boolean SUMA_SetShownLocalRemixFlag (SUMA_SurfaceViewer *sv)
00632 {
00633    static char FuncName[]={"SUMA_SetShownLocalRemixFlag"};
00634    int k;
00635       
00636    SUMA_ENTRY;
00637    
00638    for (k=0; k < sv->N_ColList; ++k) {
00639       sv->ColList[k].Remix = YUP;
00640    }
00641    
00642    SUMA_RETURN (YUP);
00643 }
00644 
00645 /*!
00646    ans = SUMA_SetLocalRemixFlag (char *idcode_str, SUMA_SurfaceViewer *sv);
00647    Search RegisteredDO for sv and if a Surface in RegisteredDO is related 
00648    to DO_idcode_str then its remix flag is set to yes.
00649    
00650    \param idcode_str (char *) IDcode of the surface that had its colorplanes modified
00651    \param sv (SUMA_SurfaceViewer *) pointer to surface viewer 
00652    \return ans (SUMA_Boolean) YUP/NOPE
00653    \sa SUMA_SetRemixFlag
00654    \sa SUMA_SetShownLocalRemixFlag
00655    
00656    Will I ever use that one, not common to have related surfaces in one view ... ?
00657 */
00658 SUMA_Boolean SUMA_SetLocalRemixFlag (char *SO_idcode_str, SUMA_SurfaceViewer *sv)
00659 {  
00660    static char FuncName[]={"SUMA_SetLocalRemixFlag"};
00661    SUMA_SurfaceObject *SO1 = NULL, *SO2 = NULL;
00662    int k, kk, dov_id;   
00663    SUMA_Boolean Found = NOPE;
00664    
00665    SUMA_ENTRY;
00666    
00667    if (!SO_idcode_str || !sv) {
00668       fprintf (SUMA_STDERR,"Error %s: NULL sv or SO_idcode_str. BAD\n", FuncName);
00669       SUMA_RETURN (NOPE);
00670    }
00671 
00672    dov_id = SUMA_findSO_inDOv (SO_idcode_str, SUMAg_DOv, SUMAg_N_DOv);
00673    if (dov_id < 0) {
00674       fprintf (SUMA_STDERR,"Error %s: Failed to find object with idcode %s.\n", FuncName, SO_idcode_str);
00675       SUMA_RETURN (NOPE);
00676    }
00677    SO1 = (SUMA_SurfaceObject *)SUMAg_DOv[dov_id].OP;
00678    
00679    /* search for relatives in RegisteredDO */
00680    for (k=0; k < sv->N_DO; ++k) {
00681       SO2 = (SUMA_SurfaceObject *)SUMAg_DOv[sv->RegisteredDO[k]].OP;
00682       if (SUMA_isRelated (SO1, SO2, 1)) { /* only for kinship of da first order */
00683          /* related, set flag for remixing SO2 */
00684          kk = 0;
00685          Found = NOPE;
00686          while (!Found && kk < sv->N_ColList) {
00687             if (strcmp (SO2->idcode_str, sv->ColList[kk].idcode_str) == 0) {
00688                Found = YUP;
00689                sv->ColList[kk].Remix = YUP;
00690             }
00691             ++kk;
00692          }
00693          if (!Found) {
00694             fprintf (SUMA_STDERR,"Error %s: Failed to find surface in ColList structs. BAD.\n", FuncName);
00695             SUMA_RETURN (NOPE);
00696          }
00697       }  
00698    } 
00699    
00700    SUMA_RETURN (YUP);
00701 }
00702 
00703 
00704 
00705 /*!
00706    ans = SUMA_SetRemixFlag (char *idcode_str, SUMA_SurfaceViewer *SVv, int N_SVv);
00707    Search RegisteredDO for each Surface Viewer and if a Surface in RegisteredDO is related 
00708    to DO_idcode_str then its remix flag is set to yes.
00709    
00710    \param idcode_str (char *) IDcode of the surface that had its colorplanes modified
00711    \param SVv (SUMA_SurfaceViewer *) vector of existing surface viewers (typically, that is SUMAg_SVv)
00712    \param N_SVv (int) number of surface viewers (typically that is N_SUMAg_SVv)
00713    \return ans (SUMA_Boolean) YUP/NOPE
00714    \sa SUMA_SetLocalRemixFlag
00715    \sa SUMA_SetShownLocalRemix
00716 
00717    DO NOT SET THE REMIXFLAG unless you have modified the colorplanes of a certain surface. This function will
00718    set a remix flags to all related surfaces that are being displayed in all viewers. You want to do this
00719    when one (or all) of the colorplanes is changed. Alternately, if you make changes that only affect the 
00720    surface as is it shown in the viewer (change background modulation for example), you want to do the remixing
00721    for the concerned surface or surfaces only in that viewer and not in all viewers open. Perhaps I should write 
00722    a function to set the remix flags for surfaces within the viewer only. Something like SUMA_SetLocalRemixFlag or 
00723    SUMA_SetShownLocalRemix.
00724    
00725 */
00726 SUMA_Boolean SUMA_SetRemixFlag (char *SO_idcode_str, SUMA_SurfaceViewer *SVv, int N_SVv)
00727 {
00728    static char FuncName[]={"SUMA_SetRemixFlag"};
00729    SUMA_SurfaceViewer *sv;
00730    SUMA_SurfaceObject *SO1 = NULL, *SO2 = NULL;
00731    int i, k, kk, dov_id;   
00732    SUMA_Boolean Found = NOPE;
00733    SUMA_Boolean LocalHead = NOPE;
00734    
00735    SUMA_ENTRY;
00736    
00737    if (!SO_idcode_str || !SVv) {
00738       fprintf (SUMA_STDERR,"Error %s: NULL SVv or SO_idcode_str. BAD\n", FuncName);
00739       SUMA_RETURN (NOPE);
00740    }
00741    
00742    dov_id = SUMA_findSO_inDOv (SO_idcode_str, SUMAg_DOv, SUMAg_N_DOv);
00743    if (dov_id < 0) {
00744       fprintf (SUMA_STDERR,"Error %s: Failed to find object with idcode %s.\n", FuncName, SO_idcode_str);
00745       SUMA_RETURN (NOPE);
00746    }
00747    SO1 = (SUMA_SurfaceObject *)SUMAg_DOv[dov_id].OP;
00748    
00749    /* search all viewers */
00750    for (i=0; i < N_SVv; ++i) {
00751       if (LocalHead) fprintf (SUMA_STDERR,"%s: Searching viewer %d.\n", FuncName, i);
00752       sv = &(SVv[i]);
00753       /* search for relatives in RegisteredDO */
00754       for (k=0; k < sv->N_DO; ++k) {
00755          if (SUMA_isSO(SUMAg_DOv[sv->RegisteredDO[k]])) {
00756             SO2 = (SUMA_SurfaceObject *)SUMAg_DOv[sv->RegisteredDO[k]].OP;
00757             if (SUMA_isRelated (SO1, SO2, 1)) { /* only 1st order kinship allowed */
00758                /* related, set flag for remixing SO2 */
00759                kk = 0;
00760                Found = NOPE;
00761                while (!Found && kk < sv->N_ColList) {
00762                   if (strcmp (SO2->idcode_str, sv->ColList[kk].idcode_str) == 0) {
00763                      Found = YUP;
00764                      sv->ColList[kk].Remix = YUP;
00765                   }
00766                   ++kk;
00767                }
00768                if (!Found) {
00769                   fprintf (SUMA_STDERR,"Error %s: Failed to find surface in ColList structs. BAD.\n", FuncName);
00770                   SUMA_RETURN (NOPE);
00771                }
00772             }
00773          }  
00774       } 
00775    }
00776    
00777    SUMA_RETURN (YUP);
00778 }
00779 
00780 /*!
00781    \brief sets remix flags for all color lists in viewers specified in SVv
00782    Use this function whenever global color changes occur
00783    
00784    \sa SUMA_SetRemixFlag for detailed help
00785 
00786 */
00787 SUMA_Boolean SUMA_SetAllRemixFlag (SUMA_SurfaceViewer *SVv, int N_SVv)
00788 {
00789    static char FuncName[]={"SUMA_SetAllRemixFlag"};
00790    SUMA_SurfaceViewer *sv;
00791    int i, kk;   
00792    SUMA_Boolean LocalHead = NOPE;
00793    
00794    SUMA_ENTRY;
00795    
00796    if (!SVv) {
00797       fprintf (SUMA_STDERR,"Error %s: NULL SVv . BAD\n", FuncName);
00798       SUMA_RETURN (NOPE);
00799    }
00800    
00801    /* search all viewers */
00802    for (i=0; i < N_SVv; ++i) {
00803       if (LocalHead) fprintf (SUMA_STDERR,"%s: Searching viewer %d.\n", FuncName, i);
00804       sv = &(SVv[i]);
00805       for (kk = 0; kk < sv->N_ColList; ++kk) sv->ColList[kk].Remix = YUP;
00806    }
00807    
00808    SUMA_RETURN (YUP);
00809 }
00810 
00811 /*!
00812 Updates the View Center and view from of SV based on the contents of RegisteredDO
00813 */
00814 
00815 SUMA_Boolean SUMA_UpdateViewPoint (SUMA_SurfaceViewer *SV, SUMA_DO *dov, int N_dov)
00816 {
00817    int i, do_id, TotWeight;
00818    float NewCenter[3], UsedCenter[3];
00819    SUMA_SurfaceObject *so_op;
00820    static char FuncName[]={"SUMA_UpdateViewPoint"};
00821       
00822    SUMA_ENTRY;
00823 
00824    NewCenter[0] = 0.0;
00825    NewCenter[1] = 0.0;
00826    NewCenter[2] = 0.0;
00827    TotWeight = 0;
00828    
00829    i = 0;
00830    while (i < SV->N_DO) {
00831       do_id = SV->RegisteredDO[i];
00832       switch (dov[do_id].ObjectType) {
00833          case SO_type:
00834             so_op = (SUMA_SurfaceObject *)dov[do_id].OP;
00835             if (SV->UsePatchDims) { SUMA_COPY_VEC(so_op->patchCenter, UsedCenter, 3, float, float);  } 
00836             else {  SUMA_COPY_VEC(so_op->Center, UsedCenter, 3, float, float); }
00837             if (so_op->ViewCenterWeight) {
00838                NewCenter[0] += so_op->ViewCenterWeight*UsedCenter[0];
00839                NewCenter[1] += so_op->ViewCenterWeight*UsedCenter[1];
00840                NewCenter[2] += so_op->ViewCenterWeight*UsedCenter[2];
00841                TotWeight += so_op->ViewCenterWeight;
00842             }
00843             break;
00844          default:
00845             break;
00846       } 
00847       ++i;
00848    }
00849    if (TotWeight) {
00850       SV->GVS[SV->StdView].ViewCenter[0] = NewCenter[0]/(float)TotWeight;
00851       SV->GVS[SV->StdView].ViewCenter[1] = NewCenter[1]/(float)TotWeight;
00852       SV->GVS[SV->StdView].ViewCenter[2] = NewCenter[2]/(float)TotWeight;
00853       SV->GVS[SV->StdView].ViewFrom[0] = SV->GVS[SV->StdView].ViewCenter[0];
00854       SV->GVS[SV->StdView].ViewFrom[1] = SV->GVS[SV->StdView].ViewCenter[1];
00855       SV->GVS[SV->StdView].ViewFrom[2] = SV->GVS[SV->StdView].ViewCenter[2]+SUMA_DEFAULT_VIEW_FROM;   
00856       SV->GVS[SV->StdView].ViewDistance = SUMA_DEFAULT_VIEW_FROM;   
00857       
00858    } else
00859    {/* default back to o.o, o.o, o.o */
00860       SV->GVS[SV->StdView].ViewCenter[0] = SV->GVS[SV->StdView].ViewCenter[1] = SV->GVS[SV->StdView].ViewCenter[2] = 0.0;
00861       SV->GVS[SV->StdView].ViewFrom[0] = SV->GVS[SV->StdView].ViewFrom[1] = 0.0; SV->GVS[SV->StdView].ViewFrom[2] = SUMA_DEFAULT_VIEW_FROM;
00862       SV->GVS[SV->StdView].ViewDistance = SUMA_DEFAULT_VIEW_FROM;   
00863    }
00864    
00865       /* Store that info in case subjects change things */
00866       SV->GVS[SV->StdView].ViewCenterOrig[0] = SV->GVS[SV->StdView].ViewCenter[0];
00867       SV->GVS[SV->StdView].ViewCenterOrig[1] = SV->GVS[SV->StdView].ViewCenter[1];
00868       SV->GVS[SV->StdView].ViewCenterOrig[2] = SV->GVS[SV->StdView].ViewCenter[2];
00869       SV->GVS[SV->StdView].ViewFromOrig[0] = SV->GVS[SV->StdView].ViewFrom[0];
00870       SV->GVS[SV->StdView].ViewFromOrig[1] = SV->GVS[SV->StdView].ViewFrom[1];
00871       SV->GVS[SV->StdView].ViewFromOrig[2] = SV->GVS[SV->StdView].ViewFrom[2];
00872 
00873    SUMA_RETURN (YUP);
00874    
00875    
00876 }
00877 /*!
00878 Updates the Rotation Center of SV based on the contents of RegisteredDO
00879 */
00880 SUMA_Boolean SUMA_UpdateRotaCenter (SUMA_SurfaceViewer *SV, SUMA_DO *dov, int N_dov)
00881 {
00882    int i, do_id, TotWeight;
00883    float NewCenter[3], UsedCenter[3];
00884    SUMA_SurfaceObject *so_op;
00885    static char FuncName[]={"SUMA_UpdateRotaCenter"};
00886    
00887    SUMA_ENTRY;
00888 
00889    NewCenter[0] = 0.0;
00890    NewCenter[1] = 0.0;
00891    NewCenter[2] = 0.0;
00892    TotWeight = 0;
00893    
00894    
00895    i = 0;
00896    while (i < SV->N_DO) {
00897       do_id = SV->RegisteredDO[i];
00898       switch (dov[do_id].ObjectType) {
00899          case SO_type:
00900             so_op = (SUMA_SurfaceObject *)dov[do_id].OP;
00901             if (SV->UsePatchDims) { SUMA_COPY_VEC(so_op->patchCenter, UsedCenter, 3, float, float);  } 
00902             else {  SUMA_COPY_VEC(so_op->Center, UsedCenter, 3, float, float); }
00903             if (so_op->RotationWeight) {
00904                NewCenter[0] += so_op->RotationWeight*UsedCenter[0];
00905                NewCenter[1] += so_op->RotationWeight*UsedCenter[1];
00906                NewCenter[2] += so_op->RotationWeight*UsedCenter[2];
00907                TotWeight += so_op->RotationWeight;
00908             }
00909             break;
00910          default:
00911             break;
00912       } 
00913       ++i;
00914    }
00915    if (TotWeight) {
00916       SV->GVS[SV->StdView].RotaCenter[0] = NewCenter[0]/(float)TotWeight;
00917       SV->GVS[SV->StdView].RotaCenter[1] = NewCenter[1]/(float)TotWeight;
00918       SV->GVS[SV->StdView].RotaCenter[2] = NewCenter[2]/(float)TotWeight;
00919    } else
00920    {/* default back to o.o, o.o, o.o */
00921       SV->GVS[SV->StdView].RotaCenter[0] = SV->GVS[SV->StdView].RotaCenter[1] = SV->GVS[SV->StdView].RotaCenter[2] = 0.0;
00922    }
00923    SUMA_RETURN (YUP);
00924    
00925 }
00926 
00927 /*!
00928 output the state variable contents of the Surface Viewer 
00929 */
00930 void SUMA_Show_SurfaceViewer_Struct (SUMA_SurfaceViewer *SV, FILE *Out, int detail)
00931 {
00932    static char FuncName[]={"SUMA_Show_SurfaceViewer_Struct"};
00933    char *s = NULL;  
00934    
00935    SUMA_ENTRY;
00936 
00937    if (Out == NULL) Out = stdout;
00938    
00939    s = SUMA_SurfaceViewer_StructInfo (SV, detail);
00940    
00941    if (s) {
00942       fprintf(Out, "%s", s);
00943       SUMA_free(s); s = NULL;
00944    }else {
00945       SUMA_SL_Err("Failed in SUMA_SurfaceViewer_StructInfo");
00946    }
00947    
00948    SUMA_RETURNe;
00949 }
00950 
00951 char *SUMA_SurfaceViewer_StructInfo (SUMA_SurfaceViewer *SV, int detail)
00952 {
00953    static char FuncName[]={"SUMA_SurfaceViewer_StructInfo"};
00954    SUMA_STRING *SS = NULL;
00955    char *s=NULL;
00956    int i;
00957       
00958    SUMA_ENTRY;
00959    
00960    SS = SUMA_StringAppend (NULL, NULL);
00961    
00962    if (!SV) {
00963       SS = SUMA_StringAppend (SS,"NULL SV.\n");
00964       SS = SUMA_StringAppend (SS, NULL);
00965       /* copy s pointer and free SS */
00966       s = SS->s;
00967       SUMA_free(SS);
00968       SUMA_RETURN(s);  
00969    }
00970    
00971    SS = SUMA_StringAppend(SS, "\nSV contents:\n");
00972    SS = SUMA_StringAppend_va(SS, "   verbose = %d\n", SV->verbose); 
00973    if (SV->ShowLeft) SS = SUMA_StringAppend_va(SS,"   Show Left = YES\n");
00974    else SS = SUMA_StringAppend_va(SS,"   Show Left = NO\n");
00975    if (SV->ShowRight) SS = SUMA_StringAppend_va(SS,"   Show Right = YES\n");
00976    else SS = SUMA_StringAppend_va(SS,"   Show Right = NO\n");
00977    
00978    if (SV->ortho) SS = SUMA_StringAppend_va(SS,"   Projection: Orthographic\n");
00979    else SS = SUMA_StringAppend_va(SS,"   Projection: Perspective\n");
00980    SS = SUMA_StringAppend_va(SS,"   Aspect = %f\n", SV->Aspect);
00981    SS = SUMA_StringAppend_va(SS,"   ViewFrom = [%f %f %f]\n", SV->GVS[SV->StdView].ViewFrom[0], SV->GVS[SV->StdView].ViewFrom[1], SV->GVS[SV->StdView].ViewFrom[2]);
00982    SS = SUMA_StringAppend_va(SS,"   ViewFromOrig = [%f %f %f]\n", SV->GVS[SV->StdView].ViewFromOrig[0], SV->GVS[SV->StdView].ViewFromOrig[1], SV->GVS[SV->StdView].ViewFromOrig[2]);
00983    SS = SUMA_StringAppend_va(SS,"   ViewCenter = [%f %f %f]\n", SV->GVS[SV->StdView].ViewCenter[0], SV->GVS[SV->StdView].ViewCenter[1], SV->GVS[SV->StdView].ViewCenter[2]);
00984    SS = SUMA_StringAppend_va(SS,"   ViewCenterOrig = [%f %f %f]\n", SV->GVS[SV->StdView].ViewCenterOrig[0], SV->GVS[SV->StdView].ViewCenterOrig[1], SV->GVS[SV->StdView].ViewCenterOrig[2]);
00985    SS = SUMA_StringAppend_va(SS,"   ViewCamUp = [%f %f %f]\n", SV->GVS[SV->StdView].ViewCamUp[0], SV->GVS[SV->StdView].ViewCamUp[1], SV->GVS[SV->StdView].ViewCamUp[2]);
00986    SS = SUMA_StringAppend_va(SS,"   RotaCenter = [%f %f %f]\n", SV->GVS[SV->StdView].RotaCenter[0], SV->GVS[SV->StdView].RotaCenter[1], SV->GVS[SV->StdView].RotaCenter[2]);
00987    SS = SUMA_StringAppend_va(SS,"   light0_position = [%f %f %f %f]\n", SV->light0_position[0], SV->light0_position[1], SV->light0_position[2], SV->light0_position[3]);
00988    SS = SUMA_StringAppend_va(SS,"   light1_position = [%f %f %f %f]\n", SV->light1_position[0], SV->light1_position[1], SV->light1_position[2], SV->light1_position[3]);
00989    SS = SUMA_StringAppend_va(SS,"   ZoomCompensate = %f\n", SV->ZoomCompensate);
00990    SS = SUMA_StringAppend_va(SS,"   WindWidth = %d\n", SV->WindWidth);
00991    SS = SUMA_StringAppend_va(SS,"   WindHeight = %d\n", SV->WindHeight);
00992    SS = SUMA_StringAppend_va(SS,"   ShowWorldAxis = %d\n", SV->ShowWorldAxis);
00993    if (SV->WAx) {
00994       SS = SUMA_StringAppend_va(SS,"   WorldAxis: Center = [%f %f %f] BR = [%f %f %f , %f %f %f]\n", 
00995                                     SV->WAx->Center[0], SV->WAx->Center[1], SV->WAx->Center[2],
00996                                     SV->WAx->BR[0][0], SV->WAx->BR[1][0],   SV->WAx->BR[2][0], 
00997                                     SV->WAx->BR[0][1], SV->WAx->BR[1][1],   SV->WAx->BR[2][1]);
00998    } else {
00999       SS = SUMA_StringAppend_va(SS,"   WorldAxis: NULL\n");
01000    }     
01001    SS = SUMA_StringAppend_va(SS,"   currentQuat = [%f %f %f %f]\n", SV->GVS[SV->StdView].currentQuat[0], SV->GVS[SV->StdView].currentQuat[1], SV->GVS[SV->StdView].currentQuat[2], SV->GVS[SV->StdView].currentQuat[3]);
01002    SS = SUMA_StringAppend_va(SS,"   deltaQuat = [%f %f %f %f]\n", SV->GVS[SV->StdView].deltaQuat[0], SV->GVS[SV->StdView].deltaQuat[1], SV->GVS[SV->StdView].deltaQuat[2], SV->GVS[SV->StdView].deltaQuat[3]);
01003    SS = SUMA_StringAppend_va(SS,"   ApplyMomentum = %d\n", SV->GVS[SV->StdView].ApplyMomentum);
01004    SS = SUMA_StringAppend_va(SS,"   MinIdleDelta = %d\n", SV->GVS[SV->StdView].MinIdleDelta);
01005    SS = SUMA_StringAppend_va(SS,"   zoomDelta = %f, zoomBegin = %f\n", SV->GVS[SV->StdView].zoomDelta, SV->GVS[SV->StdView].zoomBegin);
01006    SS = SUMA_StringAppend_va(SS,"   ArrowRotationAngle=%f rad (%f deg)\n", SV->ArrowRotationAngle, SV->ArrowRotationAngle * 180.0 / SUMA_PI);
01007    SS = SUMA_StringAppend_va(SS,"   spinDeltaX/Y = %.4f/%.4f\n", SV->GVS[SV->StdView].spinDeltaX, SV->GVS[SV->StdView].spinDeltaY);
01008    SS = SUMA_StringAppend_va(SS,"   spinBeginX/Y = %.4f/%.4f\n", SV->GVS[SV->StdView].spinBeginX, SV->GVS[SV->StdView].spinBeginY);   
01009    SS = SUMA_StringAppend_va(SS,"   TranslateGain = %f\n", SV->GVS[SV->StdView].TranslateGain);
01010    SS = SUMA_StringAppend_va(SS,"   ArrowtranslateDeltaX/Y = %f/%f\n", SV->GVS[SV->StdView].ArrowtranslateDeltaX, SV->GVS[SV->StdView].ArrowtranslateDeltaY);
01011    SS = SUMA_StringAppend_va(SS,"   translateBeginX/Y = %.4f/%.4f\n", SV->GVS[SV->StdView].translateBeginX, SV->GVS[SV->StdView].translateBeginY);
01012    SS = SUMA_StringAppend_va(SS,"   translateDeltaX/Y = %f/%f\n", SV->GVS[SV->StdView].translateDeltaX, SV->GVS[SV->StdView].translateDeltaY);
01013    SS = SUMA_StringAppend_va(SS,"   translateVec = [%f %f 0.0]\n", SV->GVS[SV->StdView].translateVec[0], SV->GVS[SV->StdView].translateVec[1]);
01014    SS = SUMA_StringAppend_va(SS,"   Show Mesh Axis %d\n", SV->ShowMeshAxis);
01015    SS = SUMA_StringAppend_va(SS,"   Show Eye Axis %d\n", SV->ShowEyeAxis);
01016    SS = SUMA_StringAppend_va(SS,"   Show Cross Hair %d\n", SV->ShowCrossHair);
01017    SS = SUMA_StringAppend_va(SS,"   PolyMode %d\n", SV->PolyMode);
01018    
01019    SS = SUMA_StringAppend_va(SS,"   Group Name %s, indexed %d\n", SV->CurGroupName, SV->iCurGroup);
01020    SS = SUMA_StringAppend_va(SS,"   Current State %s, indexed %d\n", SV->State, SV->iState);
01021    SS = SUMA_StringAppend_va(SS,"   N_DO = %d\n", SV->N_DO);
01022    SS = SUMA_StringAppend(SS, "   RegisteredDO = [");
01023 
01024    for (i=0; i< SV->N_DO; ++i) {
01025       SS = SUMA_StringAppend_va(SS,"%d, ", SV->RegisteredDO[i]); 
01026    } 
01027    SS = SUMA_StringAppend(SS,"]\n");
01028    if (SV->X == NULL) SS = SUMA_StringAppend_va(SS,"   X struct is NULL!\n");
01029    else {
01030    SS = SUMA_StringAppend_va(SS,"   X struct defined.\n");
01031    }
01032    
01033    SS = SUMA_StringAppend_va(SS,"   SO in focus %d\n", SV->Focus_SO_ID);
01034    SS = SUMA_StringAppend_va(SS,"   DO in focus %d\n", SV->Focus_DO_ID);
01035 
01036    /* show some state stuff */
01037    SS = SUMA_StringAppend(SS, "\nView States:\n");
01038    for (i=0; i < SV->N_VSv; ++i) {
01039       SS = SUMA_StringAppend_va(SS,"\nView State %d/%d (FOV = %f):\n", i, SV->N_VSv-1, SV->FOV[i]);
01040       s = SUMA_ViewStateInfo (&(SV->VSv[i]), 0);
01041       if (!s) {
01042          SS = SUMA_StringAppend(SS, "*** Error in SUMA_Show_ViewState ***\n");
01043       } else {
01044          SS = SUMA_StringAppend(SS, s);
01045          SUMA_free(s); s = NULL;
01046       }
01047    }
01048    SS = SUMA_StringAppend_va(SS, "\nStandard viewing mode: %d\n", SV->StdView );
01049    SS = SUMA_StringAppend_va(SS, "\nBackground Modulation Factor= %f\n", SV->Back_Modfact);
01050    SS = SUMA_StringAppend_va(SS, "\nLast non mappable visited %d\n", SV->LastNonMapStateID);
01051    
01052    SS = SUMA_StringAppend(SS,"\n");
01053    
01054    /* trim SS */
01055    SS = SUMA_StringAppend (SS, NULL);
01056    /* copy s pointer and free SS */
01057    s = SS->s;
01058    SUMA_free(SS);
01059       
01060    SUMA_RETURN(s);
01061 }
01062 
01063 /*! Show the ViewState structure */
01064 SUMA_Boolean SUMA_Show_ViewState(SUMA_ViewState *VS, FILE *Out, int detail) 
01065 {
01066    static char FuncName[]={"SUMA_Show_ViewState"};
01067    char *s = NULL;
01068    
01069    SUMA_ENTRY;
01070 
01071    if (Out == NULL) Out = stdout;
01072 
01073    s = SUMA_ViewStateInfo(VS,  detail);
01074    if (!s) {
01075       SUMA_SL_Err("Failed in SUMA_ViewStateInfo");
01076       SUMA_RETURN(NOPE);
01077    }  else {
01078       fprintf(Out, "%s", s);
01079       SUMA_free(s); s = NULL;
01080    }
01081    
01082    SUMA_RETURN(YUP);
01083 }
01084 
01085 /*! Show the ViewState structure */
01086 char *SUMA_ViewStateInfo(SUMA_ViewState *VS, int detail) 
01087 {
01088    static char FuncName[]={"SUMA_ViewStateInfo"};
01089    int i;
01090    SUMA_STRING *SS = NULL;
01091    char *s=NULL;   
01092 
01093    SUMA_ENTRY;
01094 
01095    SS = SUMA_StringAppend (NULL, NULL);
01096    
01097    if (!VS) {
01098       SS = SUMA_StringAppend (SS,"NULL VS.\n");
01099       SS = SUMA_StringAppend (SS, NULL);
01100       /* copy s pointer and free SS */
01101       s = SS->s;
01102       SUMA_free(SS);
01103       SUMA_RETURN(s);  
01104    }
01105 
01106    if (VS->Name) SS = SUMA_StringAppend_va(SS, "   Name: %s\n", VS->Name);
01107    else SS = SUMA_StringAppend_va(SS, "   Name: NULL\n");
01108    
01109    if (VS->Group) SS = SUMA_StringAppend_va(SS, "   Group: %s\n", VS->Group);
01110    else SS = SUMA_StringAppend_va(SS, "   Group: NULL\n");
01111    
01112    if (VS->N_MembSOs) {
01113       SS = SUMA_StringAppend_va(SS, "   %d MembSOs: ", VS->N_MembSOs);
01114       for (i=0; i < VS->N_MembSOs; ++i) SS = SUMA_StringAppend_va(SS, "%d, ", VS->MembSOs[i]);
01115       SS = SUMA_StringAppend_va(SS, "\n");
01116    } else {
01117       SS = SUMA_StringAppend_va(SS, "   No MembSOs\n");
01118    }
01119    
01120    if (VS->Hist) {
01121       if (VS->Hist->N_DO) {
01122          SS = SUMA_StringAppend_va(SS, "   Hist->N_DO = %d\nHist->RegisteredDO: ", VS->Hist->N_DO);
01123          for (i=0; i < VS->Hist->N_DO; ++i) {
01124             SS = SUMA_StringAppend_va(SS, "   %d, ", VS->Hist->RegisteredDO[i]);
01125          }
01126       }
01127    } else {
01128       SS = SUMA_StringAppend_va(SS, "   Hist is NULL\n");
01129    }
01130    
01131    SS = SUMA_StringAppend (SS, NULL);
01132    /* copy s pointer and free SS */
01133    s = SS->s;
01134    SUMA_free(SS);
01135    
01136    SUMA_RETURN (s);
01137 }
01138 
01139 /*!
01140    Create & free ViewState_Hist structure 
01141 */
01142 SUMA_ViewState_Hist *SUMA_Alloc_ViewState_Hist (void)
01143 {
01144    static char FuncName[]={"SUMA_Alloc_ViewState_Hist"};
01145    SUMA_ViewState_Hist *vsh;
01146    
01147    SUMA_ENTRY;
01148 
01149    vsh = (SUMA_ViewState_Hist *)SUMA_malloc(sizeof(SUMA_ViewState_Hist));
01150    if (vsh == NULL) {
01151       fprintf(SUMA_STDERR,"Error %s: Could not allocate for vsh.\n", FuncName);
01152       SUMA_RETURN (NULL);
01153    }
01154    vsh->RegisteredDO = NULL;
01155    vsh->N_DO = 0;
01156    SUMA_RETURN (vsh);
01157 }   
01158 SUMA_Boolean SUMA_Free_ViewState_Hist (SUMA_ViewState_Hist *vsh)
01159 {
01160    static char FuncName[]={"SUMA_Free_ViewState_Hist"};
01161    
01162    SUMA_ENTRY;
01163 
01164    if (vsh == NULL) SUMA_RETURN (YUP);
01165    if (vsh->RegisteredDO) SUMA_free(vsh->RegisteredDO);
01166    if (vsh) SUMA_free(vsh);
01167    SUMA_RETURN (YUP);
01168 }
01169 
01170 /*!
01171    Add a new SUMA_ViewState structure 
01172    This is meant to replace SUMA_Alloc_ViewState
01173    
01174    - Both csv->VSv and csv->N_VSv are updated here
01175 */
01176 SUMA_Boolean SUMA_New_ViewState (SUMA_SurfaceViewer *cs)
01177 {
01178    static char FuncName[]={"SUMA_New_ViewState"};
01179 
01180    SUMA_ENTRY;
01181 
01182    
01183    if (!cs->VSv) { /* a new baby */
01184       cs->N_VSv = 1;
01185       cs->VSv = (SUMA_ViewState *)SUMA_malloc(sizeof(SUMA_ViewState));
01186    } else { /* realloc */
01187       ++cs->N_VSv;
01188       cs->VSv = (SUMA_ViewState *)SUMA_realloc(cs->VSv, cs->N_VSv*sizeof(SUMA_ViewState) );
01189    }
01190    
01191    /* check on allocation */
01192    if (!cs->VSv) {
01193       SUMA_SL_Err("Failed to allocate");
01194       SUMA_RETURN(YUP);
01195    }
01196    
01197    /* initialization of last element */
01198    cs->VSv[cs->N_VSv-1].Name = NULL;
01199    cs->VSv[cs->N_VSv-1].Group = NULL;
01200    cs->VSv[cs->N_VSv-1].MembSOs = NULL;
01201    cs->VSv[cs->N_VSv-1].N_MembSOs = 0;
01202    cs->VSv[cs->N_VSv-1].Hist = SUMA_Alloc_ViewState_Hist ();
01203    if (cs->VSv[cs->N_VSv-1].Hist == NULL) {
01204       fprintf(SUMA_STDERR,"Error %s: Could not allocate for cs->VSv->Hist.\n", FuncName);
01205       SUMA_free(cs->VSv);
01206       SUMA_RETURN (NOPE);
01207    }
01208    
01209    /* Done */
01210    SUMA_RETURN(YUP);
01211    
01212 }
01213  
01214 /*!
01215    Create & free SUMA_ViewState structure 
01216 */
01217 SUMA_ViewState *SUMA_Alloc_ViewState (int N)
01218 {
01219    SUMA_ViewState *vs;
01220    int i;
01221    static char FuncName[]={"SUMA_Alloc_ViewState"};
01222    
01223    SUMA_ENTRY;
01224 
01225    SUMA_SL_Err("Should not be using this anymore.\n"
01226                "Start using SUMA_New_ViewState.\n"
01227                "     ZSS Jan 12 04 \n");
01228    SUMA_RETURN(NULL);
01229    vs = (SUMA_ViewState *)SUMA_malloc(sizeof(SUMA_ViewState)*N);
01230    if (vs == NULL) {
01231       fprintf(SUMA_STDERR,"Error %s: Could not allocate for vs.\n", FuncName);
01232       SUMA_RETURN (NULL);
01233    }
01234    for (i=0; i< N; ++i) {
01235       vs[i].Name = NULL;
01236       vs[i].Group = NULL;
01237       vs[i].MembSOs = NULL;
01238       vs[i].N_MembSOs = 0;
01239       vs[i].Hist = SUMA_Alloc_ViewState_Hist ();
01240       if (vs[i].Hist == NULL) {
01241          fprintf(SUMA_STDERR,"Error %s: Could not allocate for vs->Hist.\n", FuncName);
01242          SUMA_free(vs);
01243          SUMA_RETURN (NULL);
01244       }
01245    }
01246    SUMA_RETURN (vs);
01247 }   
01248 
01249 SUMA_Boolean SUMA_Free_ViewState (SUMA_ViewState *vs)
01250 {
01251    static char FuncName[]={"SUMA_Free_ViewState"};
01252    SUMA_ENTRY;
01253 
01254    if (vs == NULL) SUMA_RETURN (YUP);
01255    if (vs->Name) SUMA_free(vs->Name);
01256    if (vs->Group) SUMA_free(vs->Group);
01257    if (vs->MembSOs) SUMA_free(vs->MembSOs);
01258    if (vs->Hist) SUMA_Free_ViewState_Hist (vs->Hist);
01259    if (vs) SUMA_free(vs);
01260    SUMA_RETURN (YUP);
01261 }
01262 
01263 /*! 
01264    locate the index i (into SVv[i]) of sv 
01265    -1 if not found
01266 */
01267 int SUMA_WhichSV (SUMA_SurfaceViewer *sv, SUMA_SurfaceViewer *SVv, int N_SVv)
01268 {
01269    static char FuncName[]={"SUMA_WhichSV"};
01270    int i = 0;
01271    
01272    SUMA_ENTRY;
01273    
01274    if (!SVv || !sv) {
01275       fprintf (SUMA_STDERR, "Error %s: NULL SVv or sv.\n", FuncName);
01276       SUMA_RETURN (-1);
01277    }
01278    
01279    for (i=0; i<N_SVv; ++i) {
01280       if (&(SVv[i]) == sv) {
01281          SUMA_RETURN (i);
01282       } 
01283    }
01284    
01285    
01286    SUMA_RETURN (-1);
01287 }
01288 
01289 /*! 
01290    locate the index i (into csv->VSv[i]) of state 
01291    -1 if not found
01292 */
01293 int SUMA_WhichState (char *state, SUMA_SurfaceViewer *csv, char *ForceGroup)
01294 {
01295    static char FuncName[]={"SUMA_WhichState"};
01296    int i = 0;
01297    SUMA_Boolean LocalHead = NOPE;
01298    
01299    SUMA_ENTRY;
01300 
01301    if (!ForceGroup) {
01302       if (LocalHead) fprintf(SUMA_STDERR,"%s: Searching for: %s\n", 
01303                                  FuncName, state);
01304       while (i < csv->N_VSv) {
01305          if (LocalHead) fprintf(SUMA_STDERR,"   %d? %s ...\n", 
01306                                  i, csv->VSv[i].Name);
01307                                  
01308          if (!csv->VSv[i].Name || !state) {
01309             SUMA_SL_Err("Null Name or State \n");
01310             SUMA_RETURN (-1);
01311          }
01312          if (strcmp(csv->VSv[i].Name, state) == 0) {
01313             if (LocalHead) fprintf(SUMA_STDERR,"%s: FOUND, i=%d!\n", FuncName, i);
01314             SUMA_RETURN (i);
01315          }
01316          ++i;
01317       }
01318    } else {
01319       if (LocalHead) fprintf(SUMA_STDERR,"%s: Searching for: %s, %s...\n", 
01320                               FuncName, state, ForceGroup);
01321       while (i < csv->N_VSv) {
01322          if (LocalHead) fprintf(SUMA_STDERR,"   %d? %s, %s ...\n", 
01323                                  i, csv->VSv[i].Name, csv->VSv[i].Group);
01324          if (!csv->VSv[i].Name || !state || !csv->CurGroupName) {
01325             SUMA_SL_Err("Null Name or State or CurGroupName.\n");
01326             SUMA_RETURN (-1);
01327          }
01328          if (strcmp(csv->VSv[i].Name, state) == 0 && strcmp(csv->VSv[i].Group, ForceGroup) == 0 ) {
01329             if (LocalHead) fprintf(SUMA_STDERR,"%s: FOUND, i=%d!\n", FuncName, i);
01330             SUMA_RETURN (i);
01331          }
01332          ++i;
01333       }
01334    }
01335    SUMA_RETURN (-1);
01336 }
01337 
01338 /*! 
01339    register the different view states and surfaces belonging to different 
01340    view states in the surface viewer's structure
01341    Essentially, it creates the vector VSv that is a part of the surface viewer structure
01342 */
01343 SUMA_Boolean SUMA_RegisterSpecSO (SUMA_SurfSpecFile *Spec, SUMA_SurfaceViewer *csv, SUMA_DO* dov, int N_dov)
01344 {
01345    static char FuncName[]={"SUMA_RegisterSpecSO"};
01346    int is, i;
01347    static int iwarn=0;
01348    SUMA_SurfaceObject * SO;
01349    SUMA_Boolean LocalHead = NOPE;
01350    
01351    SUMA_ENTRY;
01352 
01353    if (LocalHead && SUMA_WhichSV(csv, SUMAg_SVv, SUMA_MAX_SURF_VIEWERS) != 0) {
01354       fprintf(SUMA_STDERR,"%s: Muted for viewer[%c]\n", FuncName, 65+SUMA_WhichSV(csv, SUMAg_SVv, SUMA_MAX_SURF_VIEWERS) );
01355       /* turn off the LocalHead, too much output*/
01356       LocalHead = NOPE;
01357    }
01358    
01359 
01360    /* allocate for space depending on the number of states present */
01361    
01362    if (LocalHead) fprintf(SUMA_STDERR,"%s: Entering, Spec->Group[0] = %s ...\n", 
01363       FuncName, Spec->Group[0]);
01364    
01365    if (Spec->N_Groups != 1) {
01366       SUMA_SL_Err("A spec file is to have 1 and only 1 group in it");
01367       SUMA_RETURN(NOPE);
01368    }
01369    
01370    #if 0
01371       /* the old way */
01372       if (!csv->VSv) { /* first pass */
01373          csv->VSv = SUMA_Alloc_ViewState (Spec->N_States);
01374          if (csv->VSv == NULL) {
01375             fprintf(SUMA_STDERR,"Error %s: Failed to allocate for VSv.\n", FuncName);
01376             SUMA_RETURN (NOPE);
01377          }
01378          csv->N_VSv = 0;
01379       } 
01380    #endif
01381    
01382    /* register the various states from each SO in DOv */
01383    if (LocalHead) fprintf(SUMA_STDERR,"%s: Cycling through DOvs, looking for surfaces of group %s\n", FuncName, Spec->Group[0]);
01384    for (i=0; i < N_dov; ++i) {
01385       if (SUMA_isSO_G(dov[i], Spec->Group[0])) {
01386          SO = (SUMA_SurfaceObject *)(dov[i].OP);
01387          is = SUMA_WhichState (SO->State, csv, SO->Group);
01388          if (is < 0) {
01389             /* add state if it is a new one */
01390             /* make room */
01391             if (LocalHead) {
01392                fprintf(SUMA_STDERR,"%s: For %s\nState:%s,Group:%s to be added\n", 
01393                   FuncName, SO->Label, SO->State, SO->Group);
01394             }
01395             SUMA_New_ViewState (csv);
01396             csv->VSv[csv->N_VSv-1].Name = SUMA_copy_string(SO->State);
01397             csv->VSv[csv->N_VSv-1].Group = SUMA_copy_string(SO->Group); /* ZSS Changed from Spec->Group[0] */
01398             if (!csv->VSv[csv->N_VSv-1].Name || !csv->VSv[csv->N_VSv-1].Group) {
01399                fprintf(SUMA_STDERR,"Error %s: Failed to allocate for csv->VSv[csv->N_VSv-1].Name or .Group.\n", FuncName);
01400                SUMA_RETURN (NOPE);
01401             }   
01402             csv->VSv[csv->N_VSv-1].N_MembSOs = 1;
01403          } else { /* old one, count it */
01404             if (LocalHead) {
01405                fprintf(SUMA_STDERR,"%s: For %s\n State:%s,Group:%s found\n", 
01406                   FuncName, SO->Label, SO->State, SO->Group);
01407             }
01408             csv->VSv[is].N_MembSOs += 1;
01409          }
01410       }
01411    }
01412    
01413    SUMA_LH("Allocating...");   
01414    
01415    /* allocate for FOV */
01416    if (!csv->FOV) {
01417       csv->FOV = (float *)SUMA_calloc(csv->N_VSv, sizeof(float));
01418    } else {
01419       csv->FOV = (float *)SUMA_realloc(csv->FOV, csv->N_VSv * sizeof(float));
01420    }
01421    
01422    /* allocate space for MembSOs counters will be reset for later use counting proceeds
01423    also initialize FOV*/
01424    if (!iwarn) {
01425       SUMA_LH(  "WARNING: This block is resetting FOV\n"
01426                   "to all surface views regardless\n"
01427                   "of whether a new addition was made or not.\n"
01428                   "This message will not be shown again in this session.\n"
01429                   "Well, looks like it does no bad thing...");
01430                   ++iwarn;
01431    }
01432    for (i=0; i < csv->N_VSv; ++i) {
01433       csv->FOV[i] = FOV_INITIAL;
01434       if (!csv->VSv[i].MembSOs) {
01435          csv->VSv[i].MembSOs = (int *) SUMA_calloc(csv->VSv[i].N_MembSOs, sizeof(int));
01436       } else {
01437          csv->VSv[i].MembSOs = (int *) SUMA_realloc(csv->VSv[i].MembSOs, csv->VSv[i].N_MembSOs * sizeof(int));
01438       }
01439       if (csv->VSv[i].MembSOs == NULL) {
01440          fprintf(SUMA_STDERR,"Error %s: Failed to allocate for csv->VSv[i].MembSOs.\n", FuncName);
01441          SUMA_RETURN (NOPE);
01442       }   
01443       csv->VSv[i].N_MembSOs = 0;
01444    }
01445 
01446    
01447    /*fprintf(SUMA_STDERR,"%s: placement ...\n", FuncName);*/
01448    
01449    /* now place each SO where it belongs, don't worry about the group they're in */
01450    for (i=0; i < N_dov; ++i) {
01451       if (SUMA_isSO(dov[i])) {
01452          SO = (SUMA_SurfaceObject *)(dov[i].OP);
01453          /* find out which state it goes in */
01454          if (!SO->State || !SO->Group) {
01455             fprintf(SUMA_STDERR,"Error %s: Sent me SO (%s) with null State (%s) or null Group (%s)!\n", FuncName, SO->Label, SO->State, SO->Group);
01456             if (LocalHead) SUMA_Print_Surface_Object (SO, NULL);      
01457             SUMA_RETURN (NOPE);
01458          } 
01459          is = SUMA_WhichState (SO->State, csv, SO->Group);
01460          if (is < 0) {
01461             fprintf(SUMA_STDERR,"Error %s: This should not be.\nFailed to find %s %s in csv\n", FuncName, SO->State, SO->Group);
01462             SUMA_RETURN (NOPE);
01463          }
01464          if (LocalHead) {
01465             fprintf (SUMA_STDERR,"%s: Trying to house %s in: State[%d]\n", \
01466             FuncName, SO->Label, is);
01467          }
01468          /* store it where it should be */
01469          csv->VSv[is].MembSOs[csv->VSv[is].N_MembSOs] = i; /* store it's id as valid member of the state*/
01470          csv->VSv[is].N_MembSOs += 1; /* count it, again */ 
01471       }
01472    }
01473    
01474    /*fprintf(SUMA_STDERR,"%s: Leaving ...\n", FuncName);*/
01475 
01476    SUMA_RETURN (YUP);
01477 }
01478 
01479 /*! allocate and intialize SUMA_CommonFields 
01480 \sa SUMA_Free_CommonFields
01481 */
01482 SUMA_CommonFields * SUMA_Create_CommonFields ()
01483 {
01484    static char FuncName[]={"SUMA_Create_CommonFields"};
01485    SUMA_CommonFields *cf;
01486    int i, portn = -1, n, portn2;
01487    char *eee=NULL;
01488    SUMA_Boolean LocalHead = NOPE;
01489    
01490    /* This is the function that creates the debugging flags, do not use them here */
01491    cf = NULL;
01492    
01493    /* allocate */
01494    /* DO NOT USE SUMA_malloc here, too early for that */
01495    cf = (SUMA_CommonFields *)malloc(sizeof(SUMA_CommonFields));
01496    
01497    if (cf == NULL) {
01498       fprintf(SUMA_STDERR,"Error %s: Failed to allocate.\n", FuncName);
01499       SUMA_RETURN (cf);
01500    }
01501    
01502    cf->Dev = NOPE;
01503    cf->InOut_Notify = NOPE;
01504    cf->InOut_Level = 0;
01505    cf->MemTrace = NOPE;
01506    #ifdef USE_SUMA_MALLOC
01507    SUMA_SL_Err("NO LONGER SUPPORTED");
01508    return(NULL);
01509    cf->Mem = SUMA_Create_MemTrace();
01510    #else
01511    cf->Mem = NULL;
01512    #endif
01513    
01514    eee = getenv("SUMA_AFNI_TCP_PORT");
01515    if (eee) {
01516       portn = atoi(eee);
01517       if (portn < 1024 ||  portn > 65535) {
01518          fprintf (SUMA_STDERR, "Warning %s:\n"
01519                                "Environment variable SUMA_AFNI_TCP_PORT %d is invalid.\n"
01520                                "port must be between 1025 and 65534.\n"
01521                                "Using default of %d\n", FuncName, portn, SUMA_TCP_PORT);
01522          portn = SUMA_TCP_PORT;
01523       } 
01524    } else {
01525       portn = SUMA_TCP_PORT;
01526    }   
01527    
01528    eee = getenv("SUMA_AFNI_TCP_PORT2");
01529    if (eee) {
01530       portn2 = atoi(eee);
01531       if (portn2 < 1024 ||  portn2 > 65535) {
01532          fprintf (SUMA_STDERR, "Warning %s:\n"
01533                                "Environment variable SUMA_AFNI_TCP_PORT2 %d is invalid.\n"
01534                                "port must be between 1025 and 65534.\n"
01535                                "Using default of %d\n", FuncName, portn2, portn+1);
01536          portn2 = portn+1;
01537       } 
01538    } else {
01539       portn2 = portn+1;
01540    }   
01541     
01542    for (i=0; i<SUMA_MAX_STREAMS; ++i) {
01543       cf->ns_v[i] = NULL;
01544       cf->ns_flags_v[i] = 0;
01545       cf->Connected_v[i] = NOPE;
01546       cf->TrackingId_v[i] = 0;
01547       cf->NimlStream_v[i][0] = '\0';
01548       cf->HostName_v[i][0] = '\0';
01549       if (i==0) cf->TCP_port[i] = portn;           /* AFNI listening */
01550       else if (i==1) cf->TCP_port[i] = portn2;     /* AFNI listening */
01551       else cf->TCP_port[i] = SUMA_TCP_LISTEN_PORT0 + i - 2;   /* SUMA listening */
01552    }
01553    cf->Listening = NOPE;
01554    cf->niml_work_on = NOPE;
01555    
01556    for (i=0; i<SUMA_MAX_SURF_VIEWERS; ++i) {
01557       cf->Locked[i] = SUMA_I_Lock;
01558       cf->ViewLocked[i] = NOPE;
01559    }
01560    
01561    eee = getenv("SUMA_SwapButtons_1_3");
01562    if (eee) {
01563       if (strcmp (eee, "YES") == 0) cf->SwapButtons_1_3 = YUP;
01564       else cf->SwapButtons_1_3 = NOPE;
01565    } else {
01566       cf->SwapButtons_1_3 = NOPE;
01567    }
01568 
01569    cf->X = (SUMA_X_AllView *)malloc(sizeof(SUMA_X_AllView));
01570    if (!cf->X) {
01571      fprintf(SUMA_STDERR,"Error %s: Failed to allocate.\n", FuncName);
01572      return (NULL); 
01573    }
01574    cf->X->SumaCont = SUMA_CreateSumaContStruct();
01575    cf->X->DrawROI = SUMA_CreateDrawROIStruct();
01576    cf->X->DPY_controller1 = NULL;
01577    
01578    eee = getenv("SUMA_ColorPattern");
01579    if (eee) {
01580       if (strcmp (eee, "AFNI") == 0) {
01581          cf->X->X_Resources = SXR_Afni;
01582          if (LocalHead) fprintf(SUMA_STDERR,"%s: Afni resources\n", FuncName);
01583       } else if (strcmp (eee, "EURO") == 0) {
01584          cf->X->X_Resources = SXR_Euro;
01585          if (LocalHead) fprintf(SUMA_STDERR,"%s: Euro resources\n", FuncName);
01586       } else if (strcmp (eee, "BONAIRE") == 0) {
01587          cf->X->X_Resources = SXR_Bonaire;
01588          if (LocalHead) fprintf(SUMA_STDERR,"%s: Bonaire resources\n", FuncName);
01589       } else if (strcmp (eee, "DEFAULT") == 0) {
01590          cf->X->X_Resources = SXR_default;
01591          if (LocalHead) fprintf(SUMA_STDERR,"%s: default resources\n", FuncName);
01592       } else {
01593          cf->X->X_Resources = SXR_Euro;
01594          fprintf(SUMA_STDERR,"%s:\nUnrecognized option %s for SUMA_ColorPattern.\nUsing default = EURO\n", FuncName, eee);
01595       }
01596    } else {
01597       cf->X->X_Resources = SXR_Euro;
01598       if (LocalHead) fprintf(SUMA_STDERR,"%s: Undefined environment. Using default\n", FuncName);
01599    }
01600    
01601    cf->X->Help_TextShell = NULL;
01602    cf->X->Help_Cmap_TextShell = NULL;
01603    cf->X->Log_TextShell = NULL;
01604    cf->X->FileSelectDlg = NULL;
01605    cf->X->N_ForeSmooth_prmpt = NULL;
01606    {
01607       char *eee = getenv("SUMA_NumForeSmoothing");
01608       if (eee) {
01609          int rotval = (int)strtod(eee, NULL);
01610          if (rotval >= 0) cf->X->NumForeSmoothing = rotval;
01611          else {
01612             fprintf (SUMA_STDERR,   "Warning %s:\n"
01613                                     "Bad value for environment variable SUMA_NumForeSmoothing\n"
01614                                     "Assuming default of 0", FuncName);
01615             cf->X->NumForeSmoothing = 0;
01616          }
01617       } else cf->X->NumForeSmoothing = 0;
01618    }
01619    
01620    {
01621       char *eee = getenv("SUMA_ThresholdScalePower");
01622       if (eee) {
01623          cf->SUMA_ThrScalePowerBias = (int)strtod(eee, NULL);
01624          if (cf->SUMA_ThrScalePowerBias < 2) {
01625             fprintf (SUMA_STDERR,   "Warning %s:\n"
01626                                     "Bad value for environment variable\n"
01627                                     "SUMA_ThresholdScalePower.\n"
01628                                     "Assuming default of 2", FuncName);
01629             cf->SUMA_ThrScalePowerBias = 2;
01630          }
01631       } else cf->SUMA_ThrScalePowerBias = 2; 
01632    }
01633    
01634    {
01635       char *eee = getenv("SUMA_WarnBeforeClose");
01636       if (eee) {
01637          if (strcmp(eee,"NO") == 0) cf->X->WarnClose = NOPE;
01638          else if (strcmp(eee,"YES") == 0) cf->X->WarnClose = YUP;
01639          else {
01640             fprintf (SUMA_STDERR,   "Warning %s:\n"
01641                                     "Bad value for environment variable SUMA_WarnBeforeClose\n"
01642                                     "Assuming default of YES", FuncName);
01643             cf->X->WarnClose = YUP;
01644          }
01645       } else cf->X->WarnClose = YUP;
01646    }
01647    cf->X->SwitchCmapLst = NULL;
01648    
01649    cf->MessageList = SUMA_CreateMessageList ();
01650    #ifdef USE_SUMA_MALLOC
01651    SUMA_SL_Err("NO LONGER SUPPORTED");
01652    return(NULL);
01653    /*SUMA_ShowMemTrace (cf->Mem, NULL);*/
01654    #endif
01655    cf->ROI_mode = NOPE;
01656    cf->Pen_mode = NOPE;
01657    
01658    cf->nimlROI_Datum_type = NI_rowtype_define("SUMA_NIML_ROI_DATUM", "int,int,int,int[#3]");
01659    if (cf->nimlROI_Datum_type < 0) {
01660       fprintf(SUMA_STDERR,"Error %s: Failed defining niml code.", FuncName);
01661       return(NULL);
01662    }
01663    if (LocalHead) fprintf(SUMA_STDERR, "%s: roi_type code = %d\n", FuncName, cf->nimlROI_Datum_type) ;
01664    
01665    cf->ROI_CM = NULL;
01666    cf->ROI_FillMode = SUMA_ROI_FILL_TO_THISROI;
01667    cf->ROI2afni = NOPE;
01668    
01669    eee = getenv("SUMA_ColorMixingMode");
01670    if (eee) {
01671       if (strcmp (eee, "ORIG") == 0) {
01672          cf->ColMixMode = SUMA_ORIG_MIX_MODE;
01673       } else if (strcmp (eee, "MOD1") == 0) {
01674          cf->ColMixMode = SUMA_4AML;
01675       } else {
01676          cf->ColMixMode = SUMA_ORIG_MIX_MODE;
01677          fprintf(SUMA_STDERR,"%s:\nUnrecognized option %s for SUMA_ColorMixingMode.\nUsing default = ORIG\n", FuncName, eee);
01678       } 
01679    } else {
01680       cf->ColMixMode = SUMA_ORIG_MIX_MODE;
01681    }
01682    
01683    cf->GroupList = NULL;
01684    cf->N_Group = -1;
01685    
01686    cf->scm = NULL;
01687    cf->DsetList = (DList *)SUMA_malloc(sizeof(DList));
01688    dlist_init (cf->DsetList, SUMA_FreeDset);
01689    
01690    cf->IgnoreVolreg = NOPE;
01691    cf->isGraphical = NOPE;
01692    return (cf);
01693 
01694 }
01695 
01696 /*!
01697 \brief creates the structure for storing the radio buttons used to control viewer locking
01698    Do not use CommonFields structure here.
01699 
01700 */ 
01701 SUMA_rb_group *SUMA_CreateLock_rbg (int N_rb_group, int N_but) 
01702 {
01703    static char FuncName[]={"SUMA_CreateLock_rbg"};
01704    SUMA_rb_group *Lock_rb;
01705 
01706    Lock_rb = (SUMA_rb_group *) malloc(sizeof(SUMA_rb_group));
01707    if (!Lock_rb) { 
01708       fprintf (SUMA_STDERR,"Error %s: Failed to allocate.\n", FuncName);
01709       return(NULL);
01710    }
01711    Lock_rb->N_rb_group = N_rb_group;
01712    Lock_rb->N_but = N_but;
01713    Lock_rb->tb = (Widget *) calloc(N_rb_group*N_but, sizeof(Widget));
01714    Lock_rb->rb = (Widget *) calloc(N_rb_group, sizeof(Widget));
01715    Lock_rb->atb = (Widget *) calloc(N_but, sizeof(Widget));
01716    Lock_rb->arb = NULL;
01717    if (!Lock_rb->tb || !Lock_rb->rb || !Lock_rb->atb) {
01718       fprintf (SUMA_STDERR,"Error %s: Failed to allocate.\n", FuncName);
01719       return(NULL);
01720    }
01721    return(Lock_rb);
01722 
01723 }
01724 
01725 /*!
01726    free SUMA_rb_group *
01727    Do not use CommonFields structure here.
01728 */
01729 void * SUMA_FreeLock_rbg (SUMA_rb_group *Lock_rb)
01730 {
01731   static char FuncName[]={"SUMA_FreeLock_rb"};
01732   
01733   if (Lock_rb->rb) free(Lock_rb->rb);
01734   if (Lock_rb->tb) free(Lock_rb->tb);
01735   if (Lock_rb->atb) free (Lock_rb->atb);
01736   if (Lock_rb) free(Lock_rb);
01737 
01738   return (NULL);
01739 }
01740 
01741 /*!
01742    \brief DrawROI = SUMA_CreateDrawROIStruct();
01743    allocates and initializes structure of type 
01744    
01745    \return SUMA_X_DrawROI *
01746 */
01747 SUMA_X_DrawROI *SUMA_CreateDrawROIStruct (void) 
01748 {
01749    static char FuncName[]={"SUMA_CreateDrawROIStruct"};
01750    SUMA_X_DrawROI *DrawROI = NULL;
01751    
01752    /* do not use commonfields related stuff here for obvious reasons */
01753    DrawROI = (SUMA_X_DrawROI *)malloc (sizeof(SUMA_X_DrawROI));
01754    DrawROI->AppShell = NULL;
01755    DrawROI->ROIval = (SUMA_ARROW_TEXT_FIELD *)malloc(sizeof(SUMA_ARROW_TEXT_FIELD));
01756    DrawROI->ROIlbl = (SUMA_ARROW_TEXT_FIELD *)malloc(sizeof(SUMA_ARROW_TEXT_FIELD));
01757    DrawROI->curDrawnROI = NULL;  /* DO NOT FREE THIS POINTER */
01758    DrawROI->SwitchROIlst = NULL;
01759    DrawROI->Delete_first = YUP;
01760    DrawROI->SaveMode = SW_DrawROI_SaveMode1D;
01761    DrawROI->SaveWhat = SW_DrawROI_SaveWhatThis;
01762    DrawROI->WhatDist = SW_DrawROI_WhatDistNothing;
01763    return (DrawROI);
01764 }
01765 
01766 /*!
01767    \brief SumaCont = SUMA_CreateSumaContStruct();
01768    allocates and initializes structure of type SUMA_X_SumaCont
01769    \return SUMA_X_SumaCont *
01770    
01771 */
01772 SUMA_X_SumaCont *SUMA_CreateSumaContStruct (void) 
01773 {
01774    static char FuncName[]={"SUMA_CreateSumaContStruct"};
01775    SUMA_X_SumaCont *SumaCont = NULL;
01776    /* do not use commonfields related stuff here for obvious reasons */
01777    SumaCont = (SUMA_X_SumaCont *)malloc(sizeof(SUMA_X_SumaCont));
01778    SumaCont->AppShell = NULL;
01779    SumaCont->quit_pb = NULL;
01780    SumaCont->quit_first = YUP;
01781    SumaCont->Lock_rbg = SUMA_CreateLock_rbg (SUMA_MAX_SURF_VIEWERS, 3);
01782    if (!SumaCont->Lock_rbg) {
01783       fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_CreateLock_rb.\n", FuncName);
01784       return (NULL);
01785    }
01786    SumaCont->LockView_tbg = (Widget *)calloc (SUMA_MAX_SURF_VIEWERS, sizeof(Widget));
01787    SumaCont->LockAllView_tb = NULL;
01788    SumaCont->SumaInfo_TextShell = NULL;
01789    return (SumaCont);
01790 }
01791 
01792 /*!
01793    \brief frees structure SUMA_X_SumaCont, returns null
01794    
01795 */
01796 void *SUMA_FreeSumaContStruct (SUMA_X_SumaCont *SumaCont)
01797 {
01798    static char FuncName[]={"SUMA_FreeSumaContStruct"};
01799 
01800    /* do not use commonfields related stuff here for obvious reasons */
01801    if (SumaCont->Lock_rbg) SUMA_FreeLock_rbg (SumaCont->Lock_rbg);
01802    if (SumaCont->LockView_tbg) free (SumaCont->LockView_tbg);
01803    if (SumaCont->SumaInfo_TextShell) { SUMA_SL_Warn("SumaCont->SumaInfo_TextShell is not being freed") };
01804    if (SumaCont) free(SumaCont);
01805    return (NULL);
01806 }
01807 
01808 /*!
01809    \brief frees structure SUMA_X_DrawROI, returns null
01810 */
01811 void *SUMA_FreeDrawROIStruct (SUMA_X_DrawROI *DrawROI)
01812 {  
01813    static char FuncName[]={"SUMA_FreeDrawROIStruct"};
01814    
01815    /* do not use commonfields related stuff here for obvious reasons,
01816    Well, you can, it is no big deal, memory tracing variables are wiped out at the end*/
01817    if (DrawROI->ROIval) free (DrawROI->ROIval);
01818    if (DrawROI->ROIlbl) free (DrawROI->ROIlbl);
01819    if (DrawROI->SwitchROIlst) SUMA_FreeScrolledList (DrawROI->SwitchROIlst);
01820    if (DrawROI) free(DrawROI);
01821    
01822    return (NULL);
01823 }
01824 /*!
01825    \brief ViewCont = SUMA_CreateViewContStruct();
01826    allocates and initializes structure of type SUMA_X_ViewCont
01827    \return SUMA_X_ViewCont *
01828    
01829 */
01830 SUMA_X_ViewCont *SUMA_CreateViewContStruct (void) 
01831 {
01832    static char FuncName[]={"SUMA_CreateViewContStruct"};
01833    SUMA_X_ViewCont *ViewCont = NULL;
01834    /* do not use commonfields related stuff here for obvious reasons */
01835    ViewCont = (SUMA_X_ViewCont *)malloc(sizeof(SUMA_X_ViewCont));
01836    ViewCont->TopLevelShell = NULL;
01837    ViewCont->ViewerInfo_TextShell = NULL;
01838    ViewCont->Info_lb = NULL;
01839    ViewCont->ViewerInfo_pb = NULL;
01840    ViewCont->Mainform = NULL;
01841    ViewCont->SwitchGrouplst = NULL; 
01842    ViewCont->SwitchStatelst = NULL; 
01843    ViewCont->ViewerInfo_pb = NULL;
01844    return (ViewCont);
01845 }
01846 
01847 /*!
01848    \brief frees structure SUMA_X_ViewCont, returns null
01849    
01850 */
01851 void *SUMA_FreeViewContStruct (SUMA_X_ViewCont *ViewCont)
01852 {
01853    static char FuncName[]={"SUMA_FreeViewContStruct"};
01854 
01855    /* do not use commonfields related stuff here for obvious reasons */
01856    if (ViewCont->TopLevelShell) {
01857       SUMA_SL_Warn("ViewCont->TopLevelShell is not being freed");
01858    }
01859    if (ViewCont->SwitchGrouplst) ViewCont->SwitchGrouplst = SUMA_FreeScrolledList(ViewCont->SwitchGrouplst);
01860    if (ViewCont->SwitchStatelst) ViewCont->SwitchStatelst = SUMA_FreeScrolledList(ViewCont->SwitchStatelst);
01861    if (ViewCont) free(ViewCont);
01862    return (NULL);
01863 }
01864 
01865 /*!
01866    \brief SurfCont = SUMA_CreateSurfContStruct();
01867    allocates and initializes structure of type SUMA_X_SurfCont
01868    \return SUMA_X_SurfCont *
01869    
01870 */
01871 SUMA_X_SurfCont *SUMA_CreateSurfContStruct (char *idcode_str) 
01872 {
01873    static char FuncName[]={"SUMA_CreateSurfContStruct"};
01874    SUMA_X_SurfCont *SurfCont = NULL;
01875    
01876    
01877    /* do not use commonfields related stuff here for obvious reasons */
01878    SurfCont = (SUMA_X_SurfCont *)malloc(sizeof(SUMA_X_SurfCont));
01879    
01880    /* take care of linking fields */
01881    if (idcode_str) sprintf(SurfCont->owner_id, "%s", idcode_str);
01882    else SurfCont->owner_id[0] = '\0';
01883    SurfCont->N_links = 0;
01884    SurfCont->LinkedPtrType = SUMA_LINKED_SURFCONT_TYPE;
01885    
01886    SurfCont->DsetMap_fr = NULL;
01887    SurfCont->ColPlane_fr = NULL;
01888    SurfCont->Xhair_fr = NULL;
01889    SurfCont->TopLevelShell = NULL;
01890    SurfCont->SurfInfo_pb = NULL;
01891    SurfCont->SurfInfo_label = NULL;
01892    SurfCont->SurfInfo_TextShell = NULL;
01893    SurfCont->ColPlaneOrder = (SUMA_ARROW_TEXT_FIELD *)malloc(sizeof(SUMA_ARROW_TEXT_FIELD));
01894    SurfCont->ColPlaneOpacity = (SUMA_ARROW_TEXT_FIELD *)malloc(sizeof(SUMA_ARROW_TEXT_FIELD));
01895    SurfCont->ColPlaneDimFact = (SUMA_ARROW_TEXT_FIELD *)malloc(sizeof(SUMA_ARROW_TEXT_FIELD));
01896    SurfCont->XhairTable = SUMA_AllocTableField();
01897    SurfCont->SetRangeTable = SUMA_AllocTableField();
01898    SurfCont->SetThrScaleTable = SUMA_AllocTableField();
01899    SurfCont->RangeTable = SUMA_AllocTableField();
01900    SurfCont->NodeTable = SUMA_AllocTableField();
01901    SurfCont->FaceTable = SUMA_AllocTableField();
01902    SurfCont->DataTable = SUMA_AllocTableField();
01903    SurfCont->LabelTable = SUMA_AllocTableField();
01904    SurfCont->ColPlaneShow_tb = NULL;
01905    SurfCont->ColPlaneShowOne_tb = NULL;
01906    SurfCont->SymIrange_tb = NULL;
01907    SurfCont->AbsThresh_tb = NULL;
01908    SurfCont->ShowZero_tb = NULL;
01909    SurfCont->SwitchDsetlst = NULL;
01910    SurfCont->ColPlaneLabelTable = SUMA_AllocTableField();;
01911    SurfCont->curColPlane = NULL;
01912    SurfCont->ShowCurOnly = NOPE;
01913    SurfCont->curSOp = (void **)malloc(sizeof(void*));
01914    SurfCont->PosRef = NULL;
01915    SurfCont->cmp_ren = (SUMA_CMAP_RENDER_AREA *)SUMA_malloc(sizeof(SUMA_CMAP_RENDER_AREA));
01916    SurfCont->cmp_ren->cmap_wid = NULL;
01917    SurfCont->cmp_ren->FOV = SUMA_CMAP_FOV_INITIAL;
01918    SurfCont->cmp_ren->cmap_context = NULL;
01919    SurfCont->cmp_ren->translateVec[0] = SurfCont->cmp_ren->translateVec[0] = SurfCont->cmp_ren->translateVec[1] = 0.0;
01920    SurfCont->thr_sc = NULL;
01921    SurfCont->brt_sc = NULL;
01922    SurfCont->thr_lb = NULL;
01923    SurfCont->thrstat_lb = NULL;
01924    SurfCont->cmaptit_lb = NULL;
01925    SurfCont->cmapswtch_pb = NULL;
01926    SurfCont->CmapLoad_pb = NULL;
01927    SurfCont->SwitchIntMenu = NULL;
01928    SurfCont->SwitchBrtMenu = NULL;
01929    SurfCont->SwitchThrMenu = NULL;
01930    SurfCont->SwitchCmapMenu = NULL;
01931    SurfCont->rc_CmapCont = NULL;
01932    SurfCont->N_CmapMenu = -1;
01933    SurfCont->CoordBiasMenu[SW_CoordBias] = NULL;
01934    SurfCont->opts_rc = NULL;
01935    SurfCont->opts_form = NULL;
01936    SurfCont->rcvo = NULL;
01937    SurfCont->rcsw = NULL;
01938    SurfCont->rcsw_v1 = NULL;
01939    SurfCont->rcsw_v2 = NULL;
01940    SurfCont->rcswr = NULL;
01941    SurfCont->rccm = NULL;
01942    SurfCont->rccm_swcmap = NULL;
01943    SurfCont->IntRange_lb = NULL;
01944    SurfCont->Int_tb = NULL;
01945    SurfCont->Thr_tb = NULL;
01946    SurfCont->Brt_tb = NULL;
01947    SurfCont->IntRangeLocked = 0;
01948    SurfCont->BrtRangeLocked = 0;
01949    /*SurfCont-> = NULL;
01950    SurfCont-> = NULL;
01951    SurfCont-> = NULL;*/
01952   return (SurfCont);
01953 }
01954  
01955 /*!
01956    \brief frees structure SUMA_X_SurfCont, returns null
01957    
01958 */
01959 void *SUMA_FreeSurfContStruct (SUMA_X_SurfCont *SurfCont)
01960 {
01961    static char FuncName[]={"SUMA_FreeSurfContStruct"};
01962 
01963    /* do not use commonfields related stuff here for obvious reasons */
01964    if (!SurfCont) return(NULL);
01965    
01966    if (SurfCont->N_links) {
01967       SurfCont = (SUMA_X_SurfCont*)SUMA_UnlinkFromPointer((void *)SurfCont);
01968       return (NULL);
01969    }
01970    
01971    /* no more links, go for it */
01972    if (SurfCont->ColPlaneOrder) free (SurfCont->ColPlaneOrder);
01973    if (SurfCont->ColPlaneOpacity) free (SurfCont->ColPlaneOpacity);
01974    if (SurfCont->ColPlaneDimFact) free (SurfCont->ColPlaneDimFact);
01975    if (SurfCont->SetRangeTable) SUMA_FreeTableField (SurfCont->SetRangeTable);
01976    if (SurfCont->RangeTable) SUMA_FreeTableField (SurfCont->RangeTable);
01977    if (SurfCont->XhairTable) SUMA_FreeTableField (SurfCont->XhairTable);
01978    if (SurfCont->NodeTable) SUMA_FreeTableField (SurfCont->NodeTable);
01979    if (SurfCont->FaceTable) SUMA_FreeTableField (SurfCont->FaceTable);
01980    if (SurfCont->DataTable) SUMA_FreeTableField (SurfCont->DataTable);
01981    if (SurfCont->LabelTable) SUMA_FreeTableField (SurfCont->LabelTable); 
01982    if (SurfCont->ColPlaneLabelTable) SUMA_FreeTableField (SurfCont->ColPlaneLabelTable); 
01983    if (SurfCont->SwitchDsetlst) SUMA_FreeScrolledList (SurfCont->SwitchDsetlst);
01984    if (SurfCont->SurfInfo_TextShell) { SUMA_SL_Warn("SurfCont->SurfInfo_TextShell is not being freed") };
01985    if (SurfCont->SwitchIntMenu) { XtDestroyWidget(SurfCont->SwitchIntMenu[0]); SUMA_free(SurfCont->SwitchIntMenu); }
01986    if (SurfCont->SwitchThrMenu) { XtDestroyWidget(SurfCont->SwitchThrMenu[0]); SUMA_free(SurfCont->SwitchThrMenu); }
01987    if (SurfCont->SwitchBrtMenu) { XtDestroyWidget(SurfCont->SwitchBrtMenu[0]); SUMA_free(SurfCont->SwitchBrtMenu); }
01988    if (SurfCont->SwitchCmapMenu) { XtDestroyWidget(SurfCont->SwitchCmapMenu[0]); SUMA_free(SurfCont->SwitchCmapMenu); }
01989    if (SurfCont->curSOp) free(SurfCont->curSOp);
01990    if (SurfCont->cmp_ren) free(SurfCont->cmp_ren);
01991    if (SurfCont) free(SurfCont);
01992    return (NULL);
01993 }
01994 
01995 /*! free SUMA_CommonFields 
01996 NOTE: the SUMA_CommonFields * itself is not freed. You'll have to free it manually with free function;
01997 \sa SUMA_Create_CommonFields
01998 */
01999 SUMA_Boolean SUMA_Free_CommonFields (SUMA_CommonFields *cf)
02000 {
02001    static char FuncName[]={"SUMA_Free_CommonFields"};
02002    int i;
02003    
02004    /* do not use commonfields related stuff here for obvious reasons */
02005    if (cf->GroupList) {
02006       for (i=0; i< cf->N_Group; ++i) if (cf->GroupList[i]) SUMA_free(cf->GroupList[i]);
02007       SUMA_free(cf->GroupList); cf->GroupList = NULL;
02008    }
02009    if (cf->ROI_CM) SUMA_Free_ColorMap(cf->ROI_CM); /* free the colormap */ cf->ROI_CM = NULL;
02010    if (cf->X->FileSelectDlg) SUMA_FreeFileSelectionDialogStruct(cf->X->FileSelectDlg); cf->X->FileSelectDlg = NULL;
02011    if (cf->X->SumaCont) SUMA_FreeSumaContStruct (cf->X->SumaCont); cf->X->SumaCont = NULL;
02012    if (cf->X->DrawROI) SUMA_FreeDrawROIStruct (cf->X->DrawROI); cf->X->DrawROI = NULL;
02013    if (cf->X->N_ForeSmooth_prmpt) SUMA_FreePromptDialogStruct (cf->X->N_ForeSmooth_prmpt); cf->X->N_ForeSmooth_prmpt = NULL;
02014    if (cf->X->SwitchCmapLst) SUMA_FreeScrolledList (cf->X->SwitchCmapLst);
02015    if (cf->X) free(cf->X); cf->X = NULL;
02016    if (cf->MessageList) SUMA_EmptyDestroyList(cf->MessageList); cf->MessageList = NULL;
02017    if (cf->scm) cf->scm = SUMA_DestroyAfniColors (cf->scm); cf->scm = NULL;
02018    if (cf->DsetList) {
02019       dlist_destroy(cf->DsetList); 
02020       SUMA_free(cf->DsetList); cf->DsetList = NULL;
02021    }
02022    #ifdef USE_SUMA_MALLOC
02023    SUMA_SL_Err("NO LONGER SUPPORTED");
02024    return(NOPE);
02025    if (cf->Mem) SUMA_Free_MemTrace (cf->Mem); cf->Mem = NULL;/* always free this right before the end */
02026    #endif
02027    
02028    /* if (cf) free(cf); */ /* don't free this stupid pointer since it is used
02029                         when main returns with SUMA_RETURN. 
02030                         It is not quite a leak since the OS will clean it up
02031                         after exit Thu Apr  8 2004*/
02032    
02033    return (YUP);
02034 }
02035 
02036 void SUMA_Show_CommonFields (SUMA_CommonFields *cf, FILE *out)
02037 {
02038    static char FuncName[]={"SUMA_Show_CommonFields"};
02039    char *s=NULL;
02040    
02041    s = SUMA_CommonFieldsInfo (cf, 1);
02042    
02043    if (!out) fprintf(SUMA_STDERR,"%s", s);
02044    else fprintf(out,"%s", s);
02045    
02046    SUMA_RETURNe;
02047 }
02048 
02049 char * SUMA_CommonFieldsInfo (SUMA_CommonFields *cf, int detail)
02050 {
02051    static char FuncName[]={"SUMA_CommonFieldsInfo"};
02052    int i;
02053    char *s=NULL;
02054    SUMA_STRING *SS=NULL;
02055    
02056    SUMA_ENTRY;
02057 
02058    SS = SUMA_StringAppend_va(NULL, NULL);
02059    
02060    if (cf == NULL) {
02061       SS = SUMA_StringAppend_va(SS," NULL cf structure.\n", FuncName);
02062       SS = SUMA_StringAppend_va(SS, NULL);
02063       s = SS->s; SUMA_free(SS); SS= NULL;
02064       SUMA_RETURN(s);
02065    }
02066    
02067    for (i=0; i < SUMA_MAX_STREAMS; ++i) {
02068       SS = SUMA_StringAppend_va(SS,"   HostName: %s\n", cf->HostName_v[i]);
02069       SS = SUMA_StringAppend_va(SS,"   NimlStream: %s\n", cf->NimlStream_v[i]);
02070    }
02071    
02072    SS = SUMA_StringAppend_va(SS,"   Available Groups: %d\n", cf->N_Group);
02073    for (i=0; i<cf->N_Group; ++i) {
02074       SS = SUMA_StringAppend_va(SS,"      Group[%d]: %s\n", i, cf->GroupList[i]);
02075    }
02076    
02077    #ifdef USE_SUMA_MALLOC
02078       SUMA_SL_Err("NO LONGER SUPPORTED");
02079       SUMA_RETURN(NULL);
02080    #else 
02081       SS = SUMA_StringAppend_va(SS,"   DBG_trace = %d\n", DBG_trace);
02082       SS = SUMA_StringAppend_va(SS,"   InOut_Notify = %d\n", cf->InOut_Notify);
02083       SS = SUMA_StringAppend_va(SS,"   MemTrace = %d\n", cf->MemTrace);
02084    #endif
02085    
02086    /* add the colormap info */
02087    if (cf->scm) {
02088       SS = SUMA_StringAppend(SS, "   Colormaps:\n");
02089       SS = SUMA_StringAppend(SS, SUMA_ColorMapVec_Info (cf->scm->CMv, cf->scm->N_maps, detail));
02090    } else {
02091       SS = SUMA_StringAppend_va(SS, "   No Colormaps.\n");
02092    }  
02093    
02094    /* clean up */
02095    SS = SUMA_StringAppend_va(SS, NULL);
02096    s = SS->s; SUMA_free(SS); SS= NULL;
02097    
02098    SUMA_RETURN(s);
02099 }
02100 
02101 /*!
02102    This function determines the most suitable standard view of a surface viewer
02103    This is based on the surface objects being displayed and their embedding dimension.
02104    The highest Embedding dimension of the lot determines what view to use 
02105    ans = SUMA_BestStandardView (SUMA_SurfaceViewer *sv, SUMA_DO *dov, int N_dov)
02106    
02107    \param sv (SUMA_SurfaceViewer *) Surface viewer structure
02108    \param dov (SUMA_DO *) vector of displayable objects
02109    \param N_dov (int) number of displayable objects
02110    \ret ans (SUMA_STANDARD_VIEWS) recommended view
02111    
02112 */   
02113 SUMA_STANDARD_VIEWS SUMA_BestStandardView (SUMA_SurfaceViewer *sv, SUMA_DO *dov, int N_dov)
02114 {
02115    static char FuncName[] = {"SUMA_BestStandardView"};
02116    SUMA_STANDARD_VIEWS ans;
02117    int i, maxdim = -1, is;
02118    SUMA_SurfaceObject *SO = NULL;
02119    
02120    SUMA_ENTRY;
02121 
02122    is = sv->iState;
02123    if (is < 0) {
02124       fprintf(SUMA_STDERR, "Error %s: sv->iState undefined.\n", FuncName);
02125       SUMA_RETURN (SUMA_Dunno); 
02126    }
02127    
02128    for (i=0; i<sv->VSv[is].N_MembSOs; ++i) {   
02129       SO = (SUMA_SurfaceObject *)(dov[sv->VSv[is].MembSOs[i]].OP);
02130       if (SO == NULL) {
02131          fprintf(SUMA_STDERR,"Error %s: SO is null ???\n.", FuncName);
02132          SUMA_RETURN (SUMA_Dunno);
02133       }
02134       if (SO->EmbedDim > maxdim) maxdim = SO->EmbedDim;
02135    }
02136    
02137    switch (maxdim) {
02138       case 2:
02139          SUMA_RETURN (SUMA_2D_Z0);
02140       case 3:
02141          SUMA_RETURN(SUMA_3D);
02142       default:
02143          fprintf(SUMA_STDERR,"Error %s: No provision for such a maximum embedding dimension of %d.\n", FuncName, maxdim);
02144          SUMA_RETURN(SUMA_Dunno);
02145    }
02146 
02147 }
02148 
02149 /*!
02150    \brief Apply the group of a surface to the surface viewer 
02151 */
02152 SUMA_Boolean SUMA_AdoptSurfGroup(SUMA_SurfaceViewer *csv, SUMA_SurfaceObject *SO)
02153 {
02154    static char FuncName[]={"SUMA_AdoptSurfGroup"};
02155 
02156    SUMA_ENTRY;
02157 
02158    csv->iCurGroup = SUMA_WhichGroup(SUMAg_CF, SO->Group);
02159    if (csv->iCurGroup < 0) {
02160       SUMA_SL_Err("Bad, unexpected error.\nGroup was not found");
02161       SUMA_RETURN(NOPE);
02162    }
02163    if (csv->CurGroupName) SUMA_free(csv->CurGroupName);
02164 
02165    csv->CurGroupName = SUMA_copy_string(SO->Group);
02166    SUMA_RETURN(YUP);
02167 }
02168 
02169 /*!
02170    \brief Apply a group to the surface viewer 
02171 */
02172 SUMA_Boolean SUMA_AdoptGroup(SUMA_SurfaceViewer *csv, char *group)
02173 {
02174    static char FuncName[]={"SUMA_AdoptSurfGroup"};
02175 
02176    SUMA_ENTRY;
02177 
02178    csv->iCurGroup = SUMA_WhichGroup(SUMAg_CF, group);
02179    if (csv->iCurGroup < 0) {
02180       SUMA_SL_Err("Bad, unexpected error.\nGroup was not found");
02181       SUMA_RETURN(NOPE);
02182    }
02183    if (csv->CurGroupName) SUMA_free(csv->CurGroupName);
02184 
02185    csv->CurGroupName = SUMA_copy_string(group);
02186    SUMA_RETURN(YUP);
02187 }
02188 
02189 /*!
02190 ans = SUMA_SetupSVforDOs (Spec, DOv, N_DOv, cSV);
02191 
02192 This functions registers all surfaces in a spec file with a surface viewer. 
02193 The following steps are performed:
02194 SUMA_RegisterSpecSO (register info on all surfaces loaded)
02195 SUMA_RegisterDO (only Surface Objects)
02196 SUMA_RegisterDO (all non SO objects)
02197 SUMA_BestStandardView (decide on best standard view)
02198 SUMA_UpdateRotaCenter (based on surfaces in first view)
02199 SUMA_UpdateViewPoint (based on surfaces in first view)
02200 SUMA_EyeAxisStandard (based on surfaces in first view)
02201 Set the Current SO pointer to the first surface object 
02202 if surface is SureFit, flip lights
02203 \param Spec (SUMA_SurfSpecFile)
02204 \param DOv (SUMA_DO *) Pointer to vector of displayable objects
02205 \param N_DOv (int) Number of displayable objects in DOv
02206 \param cSV (SUMA_SurfaceViewer *) Surface viewer structure
02207 \ret ans (SUMA_Boolean) YUP/NOPE
02208 */
02209 
02210 SUMA_Boolean SUMA_SetupSVforDOs (SUMA_SurfSpecFile Spec, SUMA_DO *DOv, int N_DOv, SUMA_SurfaceViewer *cSV)
02211 {
02212    static char FuncName[] = {"SUMA_SetupSVforDOs"};
02213    int kar;
02214    SUMA_SurfaceObject *SO;
02215    SUMA_Axis *EyeAxis;
02216    int EyeAxis_ID;
02217    SUMA_Boolean LocalHead = NOPE;
02218    
02219    SUMA_ENTRY;
02220 
02221    #if 0
02222    /* adds DOs individually, left for reference purposes */
02223    /* Register all DOs with SV */
02224    for (kar=0; kar < N_DOv; ++kar) {
02225       if (!SUMA_RegisterDO(kar, cSV)) {
02226          SUMA_error_message (FuncName,"Failed to register DO", 1);
02227          SUMA_RETURN(NOPE);
02228       }
02229    }
02230 
02231    /* register only the first surface and the remaining DOs */
02232    {
02233       SUMA_Boolean SurfIn = NOPE;
02234       for (kar=0; kar < N_DOv; ++kar) {
02235          if (!SUMA_isSO(DOv[kar]) || !SurfIn)
02236          { /* register the first surface only and other non SO objects */
02237             /*fprintf(SUMA_STDERR," to register DOv[%d] ...\n", kar);*/
02238             if (!SUMA_RegisterDO(kar, cSV)) {
02239                SUMA_error_message (FuncName,"Failed to register DO", 1);
02240                SUMA_RETURN(NOPE);
02241             }
02242          }
02243          if (SUMA_isSO(DOv[kar])) { SurfIn = YUP; }
02244       }
02245    }   
02246    #endif 
02247 
02248    #if 1
02249    /* register all surface specs */
02250       /* find out what group the viewer will have and assign the current group to be that of the new surfaces */
02251       if (LocalHead) {
02252          fprintf (SUMA_STDERR, "%s: Registering SpecSO with viewer [%d]%p, %d\n",
02253              FuncName, SUMA_WhichSV(cSV, SUMAg_SVv, SUMA_MAX_SURF_VIEWERS), cSV, SUMAg_N_SVv);
02254       }
02255       cSV->iCurGroup =  SUMA_WhichGroup(SUMAg_CF, Spec.Group[0]); /* only one group per spec */
02256       if (cSV->iCurGroup < 0) {
02257          SUMA_SL_Err("Group not found.\n");
02258          SUMA_RETURN(NOPE);
02259       } else {
02260          cSV->CurGroupName = SUMA_copy_string(SUMAg_CF->GroupList[cSV->iCurGroup]);
02261       }
02262       
02263       
02264       if (!SUMA_RegisterSpecSO(&Spec, cSV, DOv, N_DOv)) {
02265          fprintf(SUMA_STDERR,"Error %s: Failed in SUMA_RegisterSpecSO.\n", FuncName);
02266          SUMA_RETURN(NOPE);
02267       } 
02268       SUMA_LH("Done.");
02269 
02270    /* register all SOs of the first state */   
02271       if (LocalHead) {
02272          fprintf(SUMA_STDERR,"%s: Registering All SO of the first group ...\n", FuncName);
02273          fprintf(SUMA_STDERR,"%s: cSV->VSv[0].N_MembSOs = %d\n", FuncName, cSV->VSv[0].N_MembSOs);
02274       }
02275       cSV->State = cSV->VSv[0].Name;
02276       cSV->iState = 0;
02277       for (kar=0; kar < cSV->VSv[0].N_MembSOs; ++ kar) {
02278           if (LocalHead) fprintf(SUMA_STDERR," About to register DOv[%d] ...\n", cSV->VSv[0].MembSOs[kar]);
02279             if (!SUMA_RegisterDO(cSV->VSv[0].MembSOs[kar], cSV)) {
02280                SUMA_error_message (FuncName,"Failed to register DO", 1);
02281                SUMA_RETURN(NOPE);
02282             }
02283       }
02284       
02285       
02286    if (LocalHead)   fprintf(SUMA_STDERR,"%s: Done.\n", FuncName);
02287 
02288    /* register all non SO objects */
02289    if (LocalHead) fprintf(SUMA_STDERR,"%s: Registering All Non SO ...", FuncName);
02290       for (kar=0; kar < N_DOv; ++kar) {
02291          if (!SUMA_isSO(DOv[kar]))
02292          { 
02293             /*fprintf(SUMA_STDERR," About to register DOv[%d] ...\n", kar);*/
02294             if (!SUMA_RegisterDO(kar, cSV)) {
02295                SUMA_error_message (FuncName,"Failed to register DO", 1);
02296                SUMA_RETURN(NOPE);
02297             }
02298          }
02299       }
02300    if (LocalHead) fprintf(SUMA_STDERR,"%s: Done.\n", FuncName);
02301    #endif
02302 
02303    /* decide what the best state is */
02304    cSV->StdView = SUMA_BestStandardView (cSV, DOv, N_DOv);
02305    /*fprintf(SUMA_STDOUT,"%s: Standard View Now %d\n", FuncName, cSV->StdView);*/
02306    if (cSV->StdView == SUMA_Dunno) {
02307       fprintf(SUMA_STDERR,"Error %s: Could not determine the best standard view. Choosing default SUMA_3D\n", FuncName);
02308       cSV->StdView = SUMA_3D;
02309    }
02310 
02311    /* Set the Rotation Center */
02312    if (!SUMA_UpdateRotaCenter(cSV, DOv, N_DOv)) {
02313       fprintf (SUMA_STDERR,"Error %s: Failed to update center of rotation", FuncName);
02314       SUMA_RETURN(NOPE);
02315    }
02316 
02317    /* set the viewing points */
02318    if (!SUMA_UpdateViewPoint(cSV, DOv, N_DOv)) {
02319       fprintf (SUMA_STDERR,"Error %s: Failed to update view point", FuncName);
02320       SUMA_RETURN(NOPE);
02321    }
02322 
02323    /* Change the defaults of the eye axis to fit standard EyeAxis */
02324    EyeAxis_ID = SUMA_GetEyeAxis (cSV, DOv);
02325    if (EyeAxis_ID < 0) {
02326       fprintf (SUMA_STDERR,"Error %s: Failed to get Eye Axis.\n", FuncName);
02327       SUMA_RETURN(NOPE);
02328    }
02329    SUMA_EyeAxisStandard ((SUMA_Axis *)DOv[EyeAxis_ID].OP, cSV);
02330 
02331 
02332    /* Set the index Current SO pointer to the first surface object read of the first state, tiz NOT (Fri Jan 31 15:18:49 EST 2003) a surface of course*/
02333    cSV->Focus_SO_ID = cSV->VSv[0].MembSOs[0];
02334    /*set the GroupName info of the viewer correctly */
02335    SO = (SUMA_SurfaceObject *)(DOv[cSV->Focus_SO_ID].OP);
02336    if (!SUMA_AdoptSurfGroup(cSV,SO)) {
02337       SUMA_SL_Err("Failed to adopt surface's group");
02338       SUMA_RETURN(NOPE);
02339    }
02340    
02341    /* if surface is SureFit , flip lights */
02342    if (SO->FileType == SUMA_SUREFIT || SO->FileType == SUMA_OPENDX_MESH) {
02343       SUMA_LH("Flippo for safety");
02344       cSV->light0_position[0] *= -1;
02345       cSV->light0_position[1] *= -1;      
02346       cSV->light0_position[2] *= -1;
02347    }
02348    
02349    /* do the axis setup */
02350    SUMA_WorldAxisStandard (cSV->WAx, cSV);
02351 
02352 
02353    SUMA_RETURN(YUP);
02354 }
02355 
02356 /*!
02357    \brief updates the cursor in all viewers 
02358 */
02359 void SUMA_UpdateAllViewerCursor()
02360 {
02361    static char FuncName[]={"SUMA_UpdateAllViewerCursor"};
02362    int i;
02363    
02364    SUMA_ENTRY;
02365    
02366    for (i=0; i<SUMAg_N_SVv; ++i) {
02367       if (SUMAg_SVv[i].X) {
02368          SUMA_UpdateViewerCursor(&(SUMAg_SVv[i]));
02369       } 
02370    }
02371    
02372    SUMA_RETURNe;
02373 }
02374 
02375 /*!
02376    \brief updates the cursor in one viewer
02377 */
02378 void SUMA_UpdateViewerCursor(SUMA_SurfaceViewer *sv)   
02379 {  
02380    static char FuncName[]={"SUMA_UpdateViewerCursor"};
02381    SUMA_Boolean LocalHead = NOPE;
02382 
02383    SUMA_ENTRY;
02384 
02385    if (!sv->X) SUMA_RETURNe;
02386    if (!sv->X->GLXAREA) SUMA_RETURNe;
02387    if (SUMAg_CF->ROI_mode) {
02388       if (SUMAg_CF->Pen_mode) MCW_set_widget_cursor( sv->X->GLXAREA  , -XC_pencil ) ;
02389       else  MCW_set_widget_cursor( sv->X->GLXAREA  , -XC_target ) ;
02390    } else {
02391       MCW_set_widget_cursor( sv->X->GLXAREA  , -XC_top_left_arrow ) ;
02392    }
02393    SUMA_RETURNe;
02394 }
02395 
02396 /*!
02397    \brief updates the title string of a viewer window
02398 */
02399 
02400 void SUMA_UpdateViewerTitle_old(SUMA_SurfaceViewer *sv)   
02401 {  
02402    static char FuncName[]={"SUMA_UpdateViewerTitle_old"};
02403    int isv, i, N_SOlist, nalloc;  
02404    char slabel[30], sside[30], srec[10], cl='\0', cr='\0', smoment[30];   
02405    SUMA_SurfaceObject *SO = NULL;   
02406    int SOlist[SUMA_MAX_DISPLAYABLE_OBJECTS];   
02407    SUMA_Boolean LeftSide, RightSide, RightShown, LeftShown;
02408    SUMA_Boolean LocalHead = NOPE;
02409    
02410    SUMA_ENTRY;
02411 
02412    if (!sv->X) SUMA_RETURNe;
02413    if (!sv->X->TOPLEVEL) SUMA_RETURNe;
02414 
02415    isv = SUMA_WhichSV (sv, SUMAg_SVv, SUMAg_N_SVv);   
02416    
02417    if (sv->X->Title) SUMA_free(sv->X->Title);
02418    sv->X->Title = NULL;
02419       
02420    if (isv >= 0) sprintf(slabel,"[%c] SUMA", 65+isv); 
02421    else sprintf(slabel,"[DOH] SUMA"); 
02422    
02423    N_SOlist = SUMA_RegisteredSOs(sv, SUMAg_DOv, SOlist);   
02424    
02425    i = 0; 
02426    nalloc = 0;  
02427    LeftSide = NOPE;
02428    LeftShown = NOPE;
02429    RightSide = NOPE;
02430    RightShown = NOPE;
02431    while (i < N_SOlist) {   
02432       SO = (SUMA_SurfaceObject *)(SUMAg_DOv[SOlist[i]].OP);   
02433       if (SO->Label) { 
02434          nalloc +=  (strlen(SO->Label)+5);  
02435       }
02436       if (SO->Side == SUMA_LEFT) {
02437          SUMA_LH("Left found");
02438          LeftSide = YUP;
02439          if (sv->ShowLeft) LeftShown = YUP;
02440       } else if (SO->Side == SUMA_RIGHT) {
02441          SUMA_LH("Right found");
02442          RightSide = YUP;  
02443          if (sv->ShowRight) RightShown = YUP; 
02444       }
02445       
02446       ++i;   
02447    }
02448    if (LeftSide && LeftShown) cl = 'L';
02449    else if (LeftSide && !LeftShown) cl = 'h';
02450    else cl = 'x';
02451    if (RightSide && RightShown) cr = 'R';
02452    else if (RightSide && !RightShown) cr = 'h';
02453    else cr = 'x';
02454    
02455    
02456    sprintf(sside, ":%c%c:", cl, cr);
02457    
02458    if (sv->Record) sprintf(srec,":Rec");
02459    else srec[0] = '\0';
02460    
02461    if (sv->GVS[sv->StdView].ApplyMomentum) sprintf(smoment,":M");
02462    else smoment[0] = '\0';
02463    
02464    if (LocalHead) fprintf (SUMA_STDERR, "%s: Found %d surface models.\n", FuncName, N_SOlist);
02465    
02466    i = 0; 
02467    if (N_SOlist >= 0) {   
02468       SUMA_LH("title surfaces found");
02469       sv->X->Title = (char *)SUMA_calloc(nalloc + strlen(slabel)+ 13, sizeof(char));      
02470       sv->X->Title[0] = '\0';
02471       while (i < N_SOlist) {   
02472          SO = (SUMA_SurfaceObject *)(SUMAg_DOv[SOlist[i]].OP);   
02473          if (LocalHead) fprintf (SUMA_STDERR,"%s: sv->Focus_SO_ID = %d,  SOlist[%d] = %d\n", FuncName, sv->Focus_SO_ID, i, SOlist[i]);
02474          if (!i)  {
02475             if (sv->Focus_SO_ID == SOlist[i]) {
02476                sprintf (sv->X->Title,"%s%s%s%s [%s]", slabel, srec, smoment, sside, SO->Label); 
02477             } else {
02478                sprintf (sv->X->Title,"%s%s%s%s %s", slabel, srec, smoment, sside, SO->Label); 
02479             }
02480          } else {
02481             sv->X->Title = strcat (sv->X->Title, " & ");
02482             if (sv->Focus_SO_ID == SOlist[i]) {
02483                sv->X->Title = strcat (sv->X->Title, " [");
02484                sv->X->Title = strcat (sv->X->Title, SO->Label); 
02485                sv->X->Title = strcat (sv->X->Title, "] "); 
02486             } else  {
02487                sv->X->Title = strcat (sv->X->Title, SO->Label); 
02488             }
02489          }
02490          ++i;   
02491       }  
02492    } else {   
02493       SUMA_LH("No title could be made up");
02494       sv->X->Title = (char *)SUMA_calloc(strlen(slabel)+3, sizeof(char));  
02495       sprintf (sv->X->Title,"%s:-", slabel);   
02496    }  
02497    
02498    XtVaSetValues(sv->X->TOPLEVEL,  
02499             XmNtitle, sv->X->Title,  
02500             NULL);
02501             
02502    SUMA_RETURNe;   
02503 }
02504 /*!
02505    \brief updates the title string of a viewer window
02506 */
02507 
02508 void SUMA_UpdateViewerTitle(SUMA_SurfaceViewer *sv)   
02509 {  
02510    static char FuncName[]={"SUMA_UpdateViewerTitle"};
02511    int isv, i, N_SOlist;  
02512    char cl='\0', cr='\0', *s=NULL;   
02513    SUMA_SurfaceObject *SO = NULL;   
02514    int SOlist[SUMA_MAX_DISPLAYABLE_OBJECTS];   
02515    SUMA_STRING *SS = NULL;
02516    SUMA_Boolean LeftSide, RightSide, RightShown, LeftShown;
02517    SUMA_Boolean LocalHead = NOPE;
02518    
02519    SUMA_ENTRY;
02520 
02521    if (!sv->X) SUMA_RETURNe;
02522    if (!sv->X->TOPLEVEL) SUMA_RETURNe;
02523 
02524    SUMA_LH("Finding SV");
02525    isv = SUMA_WhichSV (sv, SUMAg_SVv, SUMAg_N_SVv);   
02526    
02527    if (sv->X->Title) SUMA_free(sv->X->Title);
02528    sv->X->Title = NULL;
02529    
02530    SS = SUMA_StringAppend_va(NULL, NULL);
02531    
02532    SUMA_LH("Number");
02533    if (isv >= 0) SS = SUMA_StringAppend_va(SS, "[%c] SUMA", 65+isv); 
02534    else SS = SUMA_StringAppend_va(SS,"[DOH] SUMA"); 
02535    
02536    SUMA_LH("Rec");
02537    if (sv->Record) SS = SUMA_StringAppend_va(SS,":Rec");
02538    
02539    SUMA_LH("Momentum");
02540    if (sv->GVS[sv->StdView].ApplyMomentum) SS = SUMA_StringAppend_va(SS,":M");
02541    
02542    SUMA_LH("Surf List");
02543    N_SOlist = SUMA_RegisteredSOs(sv, SUMAg_DOv, SOlist);   
02544    
02545    i = 0; 
02546    LeftSide = NOPE;
02547    LeftShown = NOPE;
02548    RightSide = NOPE;
02549    RightShown = NOPE;
02550    while (i < N_SOlist) {   
02551       SUMA_LH("   + +");
02552       SO = (SUMA_SurfaceObject *)(SUMAg_DOv[SOlist[i]].OP);   
02553       if (SO->Side == SUMA_LEFT) {
02554          SUMA_LH("Left found");
02555          LeftSide = YUP;
02556          if (sv->ShowLeft) LeftShown = YUP;
02557       } else if (SO->Side == SUMA_RIGHT) {
02558          SUMA_LH("Right found");
02559          RightSide = YUP;  
02560          if (sv->ShowRight) RightShown = YUP; 
02561       }
02562       
02563       ++i;   
02564    }
02565    
02566    if (LeftSide && LeftShown) cl = 'L';
02567    else if (LeftSide && !LeftShown) cl = 'h';
02568    else cl = 'x';
02569    if (RightSide && RightShown) cr = 'R';
02570    else if (RightSide && !RightShown) cr = 'h';
02571    else cr = 'x';
02572    
02573    SUMA_LH("Sides");
02574    
02575    SS = SUMA_StringAppend_va(SS, ":%c%c:", cl, cr);
02576    
02577    if (LocalHead) fprintf (SUMA_STDERR, "%s: Found %d surface models.\n", FuncName, N_SOlist);
02578    
02579    /* add the group's name */
02580    if (LocalHead) {
02581       if (sv->CurGroupName) fprintf (SUMA_STDERR, "%s: Calling with sv->CurGroupName = %p\n", FuncName, sv->CurGroupName);
02582       else fprintf (SUMA_STDERR, "%s: Calling with NULL sv->CurGroupName\n", FuncName);
02583    }
02584       
02585    if (sv->CurGroupName) SS = SUMA_StringAppend_va(SS," %s:", sv->CurGroupName);
02586    else SS = SUMA_StringAppend_va(SS," xx:");
02587    
02588    i = 0; 
02589    if (N_SOlist >= 0) {   
02590       SUMA_LH("title surfaces found");
02591       while (i < N_SOlist) {   
02592          SO = (SUMA_SurfaceObject *)(SUMAg_DOv[SOlist[i]].OP);   
02593          if (LocalHead) fprintf (SUMA_STDERR,"%s: sv->Focus_SO_ID = %d,  SOlist[%d] = %d\n", FuncName, sv->Focus_SO_ID, i, SOlist[i]);
02594          if (!i)  {
02595             if (sv->Focus_SO_ID == SOlist[i]) {
02596                SS = SUMA_StringAppend_va(SS," [%s]",  SO->Label); 
02597             } else {
02598                SS = SUMA_StringAppend_va(SS," %s",  SO->Label); 
02599             }
02600          } else {
02601             SS = SUMA_StringAppend_va(SS," & ");
02602             if (sv->Focus_SO_ID == SOlist[i]) {
02603                SS = SUMA_StringAppend_va(SS, " [");
02604                SS = SUMA_StringAppend_va(SS, "%s", SO->Label); 
02605                SS = SUMA_StringAppend_va(SS, "] "); 
02606             } else  {
02607                SS = SUMA_StringAppend_va(SS, "%s", SO->Label); 
02608             }
02609          }
02610          ++i;   
02611       }  
02612    } else {   
02613       SUMA_LH("No title could be made up");
02614       SS = SUMA_StringAppend_va(SS,":-");   
02615    }  
02616    
02617    /* compact SS */
02618    SS = SUMA_StringAppend_va(SS, NULL);
02619    
02620    sv->X->Title = SS->s;
02621    
02622    SUMA_free(SS); SS= NULL;
02623    
02624    XtVaSetValues(sv->X->TOPLEVEL,  
02625             XmNtitle, sv->X->Title,  
02626             NULL);
02627             
02628    SUMA_RETURNe;   
02629 }
02630 
02631 /*!
02632    \brief finds the index into the grouplist of a certain group
02633 */
02634 int SUMA_WhichGroup (SUMA_CommonFields *cf, char *nm)
02635 {
02636    static char FuncName[]={"SUMA_WhichGroup"};
02637    int i = -1;
02638    
02639    SUMA_ENTRY;
02640    
02641    if (!nm || !cf) {
02642       SUMA_SL_Err("Null nm or cf");
02643       SUMA_RETURN(i);
02644    }
02645    
02646    if (cf->N_Group <=0) { SUMA_RETURN(i); }
02647    
02648    for (i=0; i<cf->N_Group; ++i) {
02649       if (!strcmp(cf->GroupList[i], nm)) SUMA_RETURN(i);
02650    } 
02651    
02652    SUMA_RETURN(-1);
02653 }
02654 /*!
02655    \brief Register a new group with SUMA 
02656 */
02657 SUMA_Boolean SUMA_RegisterGroup (SUMA_CommonFields *cf, SUMA_SurfSpecFile *spec)
02658 {
02659    static char FuncName[]={"SUMA_RegisterGroup"};
02660    int n=0;
02661    SUMA_Boolean LocalHead = NOPE;
02662    
02663    SUMA_ENTRY;
02664    
02665    if (spec->N_Groups != 1) {
02666       SUMA_SL_Err("Spec->N_Groups != 1. This is unacceptable.\n");
02667       SUMA_RETURN(NOPE);
02668    }
02669    
02670    if (!cf->GroupList){
02671       cf->GroupList = (char **) SUMA_malloc(sizeof(char*)*SUMA_MAX_N_GROUPS);
02672       for (n=0; n<SUMA_MAX_N_GROUPS; ++n) cf->GroupList[n]=NULL;
02673       cf->N_Group = 0;
02674    }
02675    
02676    /* does the group exist already ? */
02677    if (SUMA_WhichGroup (cf, spec->Group[0]) < 0) {
02678       /* new group */
02679       SUMA_LH("Adding group");
02680       if (cf->N_Group >=  SUMA_MAX_N_GROUPS) {
02681          SUMA_SL_Err("Exceeding maximum number of groups allowed.\n");
02682          SUMA_RETURN(NOPE);
02683       }
02684       cf->GroupList[cf->N_Group] = SUMA_copy_string(spec->Group[0]);
02685       ++cf->N_Group;
02686    } else{ 
02687       /* an old group */
02688       SUMA_LH("Group exists already");
02689    }
02690    SUMA_RETURN(YUP);
02691    
02692 }
02693 
02694 /*!
02695    \brief Returns a list of the Groups available to a viewer. 
02696    
02697    \param sv (SUMA_SurfaceViewer *) pointer to surface viewer
02698    
02699    \return clist (SUMA_ASSEMBLE_LIST_STRUCT *) pointer to structure containing results
02700    
02701    \sa SUMA_FreeAssembleListStruct
02702    \sa SUMA_CreateAssembleListStruct
02703    
02704 */
02705 SUMA_ASSEMBLE_LIST_STRUCT * SUMA_AssembleGroupList (SUMA_SurfaceViewer *sv) 
02706 {
02707    static char FuncName[]={"SUMA_AssembleGroupList"};
02708    SUMA_ASSEMBLE_LIST_STRUCT *clist_str = NULL;
02709    int i=-1, N_clist=-1; 
02710    char *store=NULL;
02711    char **clist=NULL;
02712    void **oplist=NULL;
02713    DList *list=NULL, *listop = NULL;
02714    DListElmt *Elm = NULL, *Elmop = NULL;
02715    SUMA_Boolean Found = NOPE;
02716    SUMA_Boolean LocalHead = NOPE;
02717    
02718    SUMA_ENTRY;
02719    
02720    list = (DList *)SUMA_malloc(sizeof(DList));
02721    listop = (DList *)SUMA_malloc(sizeof(DList));
02722    
02723    clist = NULL;
02724    N_clist = -1;
02725    
02726    dlist_init(list, NULL);
02727    dlist_init(listop, NULL);
02728    
02729    for (i=0; i< SUMAg_CF->N_Group; ++i) {
02730       store = SUMA_copy_string(SUMAg_CF->GroupList[i]);
02731       if (!list->size) {
02732          dlist_ins_next(list, dlist_tail(list), (void*)store);
02733          dlist_ins_next(listop, dlist_tail(listop), NULL);
02734       } else { /* must sort first */
02735          Elm = NULL;
02736          Elmop = NULL;
02737          do {
02738             Found = NOPE;
02739             if (!Elm) {
02740                Elm = dlist_head(list);
02741                Elmop = dlist_head(listop);
02742             } else {
02743                Elm = dlist_next(Elm);
02744                Elmop = dlist_next(Elmop);
02745             }
02746 
02747             if (strcmp(store, (char*)Elm->data) <= 0) {
02748                dlist_ins_prev(list, Elm, (void *)store);
02749                dlist_ins_prev(listop, Elmop, NULL);
02750                Found = YUP;
02751             } else if (Elm == dlist_tail(list)) {
02752                /* reached the end, append */
02753                dlist_ins_next(list, Elm, (void *)store);
02754                dlist_ins_next(listop, Elmop, NULL);
02755                Found = YUP;
02756             }
02757          } while (!Found);
02758       }
02759    }
02760    
02761    if (!list->size) { /* Nothing found */
02762       N_clist = 0;
02763       
02764    }else {
02765    
02766       Elm = NULL;
02767       Elmop = NULL;
02768       clist = (char **)SUMA_calloc(list->size, sizeof(char *));
02769       oplist = (void **)SUMA_calloc(list->size, sizeof(void*));
02770       for (i=0; i< list->size; ++i) {
02771          if (!Elm) {
02772             Elm = dlist_head(list);
02773             Elmop = dlist_head(listop);
02774          } else {
02775             Elm = dlist_next(Elm);
02776             Elmop = dlist_next(Elmop);
02777          }
02778          clist[i] = (char*)Elm->data;
02779          oplist[i] = Elmop->data;
02780       }
02781 
02782       N_clist = list->size;
02783       /* destroy list */
02784       dlist_destroy(list);
02785       dlist_destroy(listop);
02786       SUMA_free(list);
02787       SUMA_free(listop);
02788    }
02789    
02790    clist_str = SUMA_CreateAssembleListStruct();
02791    clist_str->clist = clist;
02792    clist_str->oplist = oplist;
02793    clist_str->N_clist = N_clist;
02794    
02795    /* return */
02796    SUMA_RETURN (clist_str);  
02797 }
02798 
02799 /*!
02800    \brief   Switch viewer between two groups
02801 */
02802 SUMA_Boolean SUMA_SwitchGroups (SUMA_SurfaceViewer *sv, char *group) 
02803 {
02804    static char FuncName[]={"SUMA_SwitchGroups"};
02805    int ig, i, nxtstateID;
02806    SUMA_SurfaceObject *SO = NULL;
02807    DList *list = NULL;      
02808    SUMA_Boolean LocalHead = NOPE;
02809    
02810    SUMA_ENTRY;
02811    
02812    if (!group) {
02813       SUMA_SL_Err("NULL group");
02814       SUMA_RETURN(NOPE);
02815    }
02816    
02817    if (!strcmp(group, sv->CurGroupName)) {
02818       SUMA_LH("Same group, nothing to do.");
02819       SUMA_RETURN(YUP);
02820    }
02821    
02822    if (SUMAg_CF->N_Group == 1) {
02823       SUMA_LH("One group, nothing to do.");
02824       SUMA_RETURN(YUP);
02825    }
02826    
02827    /* which group are we going to ? */
02828    ig = SUMA_WhichGroup (SUMAg_CF, group);
02829    
02830    if (ig < 0) {
02831       SUMA_SL_Err("No such group");
02832       SUMA_RETURN(NOPE);
02833    }
02834    
02835    /* It does not seem necessary to close surface controllers or ROI controllers*/
02836 
02837    /* find me a surface in that new group  */
02838    SO = NULL;
02839    i = 0;
02840    while (!SUMA_isSO_G(SUMAg_DOv[i], group) && i < SUMAg_N_DOv) {
02841       ++i;
02842    } 
02843    if (i < SUMAg_N_DOv) { /* found a surface */
02844       SO = (SUMA_SurfaceObject *)SUMAg_DOv[i].OP;
02845    } else {
02846       SUMA_SL_Err("No candidate surface");
02847       SUMA_RETURN(NOPE);
02848    } 
02849    
02850    /* what is the state ID of that surface ? */
02851    nxtstateID = SUMA_WhichState(SO->State, sv, SO->Group);
02852    if (nxtstateID < 0) {
02853       SUMA_SL_Err("Bad! State not found.");
02854       SUMA_RETURN(NOPE);
02855    }
02856    
02857    if (!SUMA_SwitchState (SUMAg_DOv, SUMAg_N_DOv, sv,  nxtstateID, group)) {
02858       SUMA_SL_Err("Failed to switch states");
02859       SUMA_RETURN(NOPE);
02860    }  
02861 
02862    /* home call */
02863    
02864    #if 0
02865       /* now redisplay (won't work alone with multiple viewers, GL state problems) */
02866       if (!list) list = SUMA_CreateList();
02867       /* SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_Home, SES_Suma, sv); */
02868       SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_Redisplay, SES_Suma, sv);
02869 
02870       if (!SUMA_Engine (&list)) {
02871          fprintf(stderr, "Error %s: SUMA_Engine call failed.\n", FuncName);
02872       }
02873    #elif 0
02874                   /* redisplay all others (won't work alone with multiple viewers, GL state problems) */
02875                   if (!list) list = SUMA_CreateList ();
02876                   SUMA_REGISTER_TAIL_COMMAND_NO_DATA(list, SE_RedisplayNow_AllOtherVisible, SES_SumaWidget, sv);
02877                   SUMA_Engine (&list);
02878                
02879                   /* redisplay . DO NOT REDISPLAY WITH SE_Redisplay_AllVisible or you will have GL state synchronization problems */
02880                   sv->ResetGLStateVariables = YUP;
02881                   SUMA_handleRedisplay((XtPointer)sv->X->GLXAREA);
02882    #elif 1
02883             
02884             /* got to do this, in addition to SE_Redisplay_AllVisible
02885             to get the views to look good. I don't know why that is yet */
02886             for (i=0; i < SUMAg_N_SVv; ++i) {
02887                SUMA_SurfaceViewer *svtmp= &(SUMAg_SVv[i]);
02888                if (!svtmp->isShaded && svtmp->X->TOPLEVEL) {
02889                   if (!list) list = SUMA_CreateList();
02890                   SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_Home, SES_Suma, svtmp); 
02891                   SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_RedisplayNow, SES_Suma, svtmp); 
02892                   if (!SUMA_Engine (&list)) {
02893                         fprintf(stderr, "Error %s: SUMA_Engine call failed.\n", FuncName);
02894                   }
02895                }
02896             }
02897             
02898             if (!list) list = SUMA_CreateList();
02899             SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_Redisplay_AllVisible, SES_Suma, sv);
02900             if (!SUMA_Engine (&list)) {
02901                            fprintf(stderr, "Error %s: SUMA_Engine call failed.\n", FuncName);
02902             }
02903             
02904    #endif
02905 
02906    /* update titles */
02907    SUMA_UpdateViewerTitle(sv);
02908    
02909    
02910    SUMA_RETURN(YUP);
02911 }
 

Powered by Plone

This site conforms to the following standards: