1 #include "SUMA_suma.h"
2 
3 extern SUMA_CommonFields *SUMAg_CF;
4 extern int SUMAg_N_DOv;
5 extern SUMA_DO *SUMAg_DOv;
6 extern SUMA_SurfaceViewer *SUMAg_SVv;
7 extern int SUMAg_N_SVv;
8 
9 /*!
10    SUMA's viewing paramters are tuned to show human brains in mm units.
11    When a human surface is entered in cm units, some scaling needs to be
12    done so that the surface appears nice.
13    For example, in the cm vs mm case, I got nasty shading errors because
14    the viewing distance was too far.
15    A similar problem might arise if the surface is very small, like a rat's
16    for example. So there should be some scaling needed for other species.
17 */
SUMA_DimSclFac(char * units,char * specie)18 float SUMA_DimSclFac(char *units, char *specie)
19 {
20    static char FuncName[]={"SUMA_DimSclFac"};
21    float scm=1.0;
22 
23    SUMA_ENTRY;
24 
25    scm = 1.0;
26 
27    if (!units) units = SUMA_EnvVal("SUMA_NodeCoordsUnits");
28    /* scaling for units */
29    if (units) {
30       if (!strcasecmp(units,"mm")) {
31          scm = 1.0;
32       } else if (!strcasecmp(units,"cm")) {
33          scm = 10.0;
34       } else {
35          SUMA_S_Warnv(
36             "Bad value of '%s' for units variable or\n"
37             " ENV 'SUMA_NodeCoordsUnits'. Using 'mm'\n",
38             units);
39       }
40    }
41 
42    /* scaling for species - not sure what to do yet. Wait until it is needed */
43    /* You'll need to set the factor be
44       scm = scm * AVERAGE_HUMAN_BRAIN_SIZE/AVERAGE_SPECIE_SIZE */
45 
46    /* might also want an automatic fix that guess at what to do */
47 
48    SUMA_RETURN(scm);
49 }
50 
51 /*!
52    \brief a function that returns the first viewer that is in momentum mode
53    isv = SUMA_WhichViewerInMomentum( SVv,  N_SV,  sv);
54 
55    \param SVv (SUMA_SurfaceViewer *) vector of surface viewers
56    \param N_SV (int ) number of surface viewer structures in SVv
57    \param sv (SUMA_SurfaceViewer *) if !NULL then the function returns the
58             index of a surface viewer OTHER THAN sv that is in momentum mode.
59             Otherwise the first surface viewer in momentum mode is returned
60    \return isv (int) the index (into SVv) of the first viewer that is in
61             momentum mode. If sv is not NULL then it is the index of the
62             first viewer OTHER THAN sv that is in momentum mode
63             If none are found, ans = -1
64 
65    -  To turn the index into the viewer's label use:
66       if (isv >= 0) sprintf(slabel,"[%c] SUMA", 65+isv);
67       else sprintf(slabel,"[DOH] SUMA");
68 */
69 
SUMA_WhichViewerInMomentum(SUMA_SurfaceViewer * SVv,int N_SV,SUMA_SurfaceViewer * sv)70 int SUMA_WhichViewerInMomentum(SUMA_SurfaceViewer *SVv, int N_SV,
71                                SUMA_SurfaceViewer *sv)
72 {
73    static char FuncName[]={"SUMA_WhichViewerInMomentum"};
74    int ii = -1;
75 
76    SUMA_ENTRY;
77 
78    if (!SVv) SUMA_RETURN(-1);
79 
80    for (ii=0; ii < SUMAg_N_SVv; ++ii) {
81          if (SVv[ii].GVS[SVv[ii].StdView].ApplyMomentum) {
82             if (!sv) { /* don't care which one */
83                SUMA_RETURN(ii);
84             } else if (&(SUMAg_SVv[ii]) != sv) { /* other than sv */
85                SUMA_RETURN(ii);
86             }
87          }
88    }
89 
90    SUMA_RETURN(-1);
91 
92 }
93 
94 /*!
95    return an appropriate fov setting
96 */
SUMA_sv_auto_fov(SUMA_SurfaceViewer * sv)97 float SUMA_sv_auto_fov(SUMA_SurfaceViewer *sv)
98 {
99    static char FuncName[]={"SUMA_sv_auto_fov"};
100    float mxdim = -1.0, fov = FOV_INITIAL,
101          maxv[3]={-1.0, -1.0, -1.0}, *xyzr,
102          minv[3]={1000000.0, 10000000.0, 1000000.0}, avgdim=30.0;
103    int i, N_sel=0, *Vis_IDs=NULL, k=0;
104    double CurrentDistance;
105    SUMA_DSET *dset=NULL;
106    SUMA_SurfaceObject *SO=NULL;
107    SUMA_Boolean LocalHead = NOPE;
108 
109    SUMA_ENTRY;
110 
111    if (sv->iState < 0) {
112       SUMA_S_Errv("Can't do this with no state set, returning %f!",
113                   FOV_INITIAL);
114       SUMA_RETURN(FOV_INITIAL);
115    }
116    if (sv->auto_FOV_val[sv->iState] > 0.0)
117       SUMA_RETURN(sv->auto_FOV_val[sv->iState]);
118 
119    /* automatic determination */
120    Vis_IDs = (int *)SUMA_malloc(sizeof(int)*SUMAg_N_DOv);
121    minv[0] = minv[1] = minv[2] = 1;
122    maxv[0] = maxv[1] = maxv[2] = 0;
123    N_sel = SUMA_Selectable_ADOs (sv, SUMAg_DOv, Vis_IDs);
124    if (!N_sel) {
125       SUMA_LH("Nothing selectable!");
126       SUMA_free(Vis_IDs); Vis_IDs= NULL;
127       SUMA_RETURN(FOV_INITIAL);
128    } else {
129       for (i=0; i<N_sel;++i) {
130          SUMA_LHv("Working object %s\n",iDO_label(Vis_IDs[i]));
131          switch (SUMAg_DOv[Vis_IDs[i]].ObjectType) {
132             case SO_type:
133                SO = (SUMA_SurfaceObject *)SUMAg_DOv[Vis_IDs[i]].OP;
134                if (minv[0] > maxv[0]) { /* init */
135                   for (k=0; k<3; ++k) {
136                      minv[k] = SO->MinDims[k];
137                      maxv[k] = SO->MaxDims[k];
138                   }
139                } else {
140                   for (k=0; k<3; ++k) {
141                      if (SO->MinDims[k] < minv[k])
142                         minv[k] = SO->MinDims[k];
143                      if (SO->MaxDims[k] > maxv[k])
144                         maxv[k] = SO->MaxDims[k];
145                   }
146                }
147 
148                /* Note that prior to Aug. 2013 k only went up to 1 (k<2),
149                   both below and above. Despite that, avgdim was dividing by 3,
150                   rather than the expected '2'. Not sure why that was, but
151                   for now, we're sticking with saner situation */
152                avgdim = 0.0;
153                for (k=0;k<3;++k) {
154                   if (maxv[k] - minv[k] > mxdim) mxdim = maxv[k] - minv[k];
155                   avgdim += maxv[k] - minv[k];
156                }
157                avgdim /= 3.0;
158                break;
159             case GRAPH_LINK_type:
160                if(!(dset=SUMA_find_GLDO_Dset(
161                               (SUMA_GraphLinkDO *)(SUMAg_DOv[Vis_IDs[i]].OP)))){
162                   SUMA_S_Err("Gilda");
163                   break;
164                }
165 
166                if (!SUMA_IS_REAL_VARIANT(iDO_variant(Vis_IDs[i]))) break;
167                xyzr = SUMA_GDSET_XYZ_Range(dset, iDO_variant(Vis_IDs[i]), NULL);
168                if (minv[0] > maxv[0]) { /* init */
169                   for (k=0; k<3; ++k) {
170                      minv[k] = xyzr[2*k];
171                      maxv[k] = xyzr[2*k+1];
172                   }
173                } else {
174                   for (k=0; k<3; ++k) {
175                      if (xyzr[2*k] < minv[k])  minv[k] = xyzr[2*k];
176                      if (xyzr[2*k+1] > maxv[k]) maxv[k] = xyzr[2*k+1];
177                   }
178                }
179                if (!strcmp(iDO_variant(Vis_IDs[i]), "GMATRIX")) {
180                   avgdim = 0.0; /* X Y dims only */
181                   for (k=0;k<2;++k) {
182                      if (maxv[k] - minv[k] > mxdim) mxdim = maxv[k] - minv[k];
183                      avgdim += maxv[k] - minv[k];
184                   }
185                   avgdim /= 2.0;
186                   /* increase dims a little to allow for text placement */
187                   avgdim *= 1.15; mxdim *= 1.15;
188                } else {
189                   avgdim = 0.0;
190                   for (k=0;k<3;++k) {
191                      if (maxv[k] - minv[k] > mxdim) mxdim = maxv[k] - minv[k];
192                      avgdim += maxv[k] - minv[k];
193                   }
194                   avgdim /= 3.0;
195                }
196                break;
197             case TRACT_type: {
198                SUMA_TractDO *tdo=(SUMA_TractDO *)SUMAg_DOv[Vis_IDs[i]].OP;
199                xyzr = SUMA_TDO_XYZ_Range(tdo, NULL);
200                if (minv[0] > maxv[0]) { /* init */
201                   for (k=0; k<3; ++k) {
202                      minv[k] = xyzr[2*k];
203                      maxv[k] = xyzr[2*k+1];
204                   }
205                } else {
206                   for (k=0; k<3; ++k) {
207                      if (xyzr[2*k] < minv[k])  minv[k] = xyzr[2*k];
208                      if (xyzr[2*k+1] > maxv[k]) maxv[k] = xyzr[2*k+1];
209                   }
210                }
211                avgdim = 0.0;
212                for (k=0;k<3;++k) {
213                   if (maxv[k] - minv[k] > mxdim) mxdim = maxv[k] - minv[k];
214                   avgdim += maxv[k] - minv[k];
215                }
216                avgdim /= 3.0;
217                break; }
218             case VO_type: {
219                SUMA_VolumeObject *vo=
220                      (SUMA_VolumeObject *)SUMAg_DOv[Vis_IDs[i]].OP;
221                xyzr = SUMA_VO_XYZ_Range(vo, NULL);
222                if (minv[0] > maxv[0]) { /* init */
223                   for (k=0; k<3; ++k) {
224                      minv[k] = xyzr[2*k];
225                      maxv[k] = xyzr[2*k+1];
226                   }
227                } else {
228                   for (k=0; k<3; ++k) {
229                      if (xyzr[2*k] < minv[k])  minv[k] = xyzr[2*k];
230                      if (xyzr[2*k+1] > maxv[k]) maxv[k] = xyzr[2*k+1];
231                   }
232                }
233                avgdim = 0.0;
234                for (k=0;k<3;++k) {
235                   if (maxv[k] - minv[k] > mxdim) mxdim = maxv[k] - minv[k];
236                   avgdim += maxv[k] - minv[k];
237                }
238                avgdim /= 3.0;
239                break; }
240             case CDOM_type: {
241                xyzr = SUMA_CIFTI_DO_XYZ_Range(
242 	             	(SUMA_CIFTI_DO*)SUMAg_DOv[Vis_IDs[i]].OP, NULL);
243                if (minv[0] > maxv[0]) { /* init */
244                   for (k=0; k<3; ++k) {
245                      minv[k] = xyzr[2*k];
246                      maxv[k] = xyzr[2*k+1];
247                   }
248                } else {
249                   for (k=0; k<3; ++k) {
250                      if (xyzr[2*k] < minv[k])  minv[k] = xyzr[2*k];
251                      if (xyzr[2*k+1] > maxv[k]) maxv[k] = xyzr[2*k+1];
252                   }
253                }
254                avgdim = 0.0;
255                for (k=0;k<3;++k) {
256                   if (maxv[k] - minv[k] > mxdim) mxdim = maxv[k] - minv[k];
257                   avgdim += maxv[k] - minv[k];
258                }
259                avgdim /= 3.0;
260                break; }
261             case MASK_type: {
262                SUMA_MaskDO *mo=
263                      (SUMA_MaskDO *)SUMAg_DOv[Vis_IDs[i]].OP;
264                xyzr = SUMA_MDO_XYZ_Range(mo, NULL);
265                if (minv[0] > maxv[0]) { /* init */
266                   for (k=0; k<3; ++k) {
267                      minv[k] = xyzr[2*k];
268                      maxv[k] = xyzr[2*k+1];
269                   }
270                } else {
271                   for (k=0; k<3; ++k) {
272                      if (xyzr[2*k] < minv[k])  minv[k] = xyzr[2*k];
273                      if (xyzr[2*k+1] > maxv[k]) maxv[k] = xyzr[2*k+1];
274                   }
275                }
276                avgdim = 0.0;
277                for (k=0;k<3;++k) {
278                   if (maxv[k] - minv[k] > mxdim) mxdim = maxv[k] - minv[k];
279                   avgdim += maxv[k] - minv[k];
280                }
281                avgdim /= 3.0;
282                break; }
283             default:
284                SUMA_LHv("Ignoring dims of %s\n", iDO_label(Vis_IDs[i]));
285                avgdim = 0.0;
286                for (k=0;k<3;++k) {
287                   if (maxv[k] - minv[k] > mxdim) mxdim = maxv[k] - minv[k];
288                   avgdim += maxv[k] - minv[k];
289                }
290                avgdim /= 3.0;
291                break;
292          }
293       }
294    }
295    SUMA_free(Vis_IDs); Vis_IDs= NULL;
296    SUMA_LHv("Have mxdim = %f, avgdim = %f (rat %.2f)\n",
297                 mxdim, avgdim, mxdim / avgdim);
298    /* Current avg. distance from camera */
299    CurrentDistance = sqrt((sv->GVS[sv->StdView].ViewFrom[0] -
300                            sv->GVS[sv->StdView].ViewCenter[0]) *
301                           (sv->GVS[sv->StdView].ViewFrom[0] -
302                            sv->GVS[sv->StdView].ViewCenter[0]) +
303                           (sv->GVS[sv->StdView].ViewFrom[1] -
304                            sv->GVS[sv->StdView].ViewCenter[1]) *
305                           (sv->GVS[sv->StdView].ViewFrom[1] -
306                            sv->GVS[sv->StdView].ViewCenter[1]) +
307                           (sv->GVS[sv->StdView].ViewFrom[2] -
308                            sv->GVS[sv->StdView].ViewCenter[2]) *
309                           (sv->GVS[sv->StdView].ViewFrom[2] -
310                            sv->GVS[sv->StdView].ViewCenter[2]));
311 
312    if (mxdim > 0 && mxdim < 1000) {
313       SUMA_LHv("sv %p mxdim=%f, avgdim=%f, rat=%f, DimSclFac = %f, "
314                "CurrentDist = %f\n",
315                 sv, mxdim, avgdim, mxdim / avgdim,
316                 sv->GVS[sv->StdView].DimSclFac, CurrentDistance);
317       if (mxdim / avgdim > 2.2) { /* crazy aspect, adopt average size */
318          mxdim = avgdim;
319       }
320       /* fov is the double of the angle at the camera of the square triangle
321          with depth = CurrentDistance and width = half the biggest distance
322          Not sure about the DimSclFac usage here, need to retest it at some
323          point.*/
324       /* make mxdim a little larger for some framing */
325       fov = 2.0*atan((double)(mxdim *1.1* sv->GVS[sv->StdView].DimSclFac)
326                                  / 2.0 / CurrentDistance)*180.0/SUMA_PI;
327       SUMA_LHv("Computed fov to be %f degrees\n",  fov);
328    } else {
329       static int nwarn=0;
330       fov = FOV_INITIAL;
331       if (!(nwarn % SUMA_MAX_SURF_VIEWERS)) {
332          SUMA_S_Errv("max dim too strange (%f)\nUsing default (%f).\n"
333                      "Similar messages will be decimated.\n",
334                      mxdim, fov);
335       }
336       ++nwarn;
337    }
338 
339    /* institutional memory */
340    sv->auto_FOV_val[sv->iState] = fov;
341 
342    SUMA_RETURN(fov);
343 }
344 
345 
346 /* This is used to hold the functions that manipulate SV, Surface Viewer Structures */
347 /*!
348 \brief returns a string corresponding to the link type
349 
350 SUMA_Boolean SUMA_LockEnum_LockType (SUMA_LINK_TYPES i, char *Name);
351 \param i (SUMA_LINK_TYPES) see enum type in SUMA_define.h
352 \param Name (char *) a preallocated character string (no more than 50 chars)
353 \return YUP/NOPE OK, error
354 */
SUMA_LockEnum_LockType(SUMA_LINK_TYPES i,char * Name)355 SUMA_Boolean SUMA_LockEnum_LockType (SUMA_LINK_TYPES i, char *Name)
356 {
357    static char FuncName[]={"SUMA_LockEnum_LockType"};
358    SUMA_ENTRY;
359 
360    switch (i) {
361       case SUMA_No_Lock:
362          sprintf (Name, "No Lock");
363          break;
364       case SUMA_I_Lock:
365          sprintf (Name, "Index Lock");
366          break;
367       case SUMA_XYZ_Lock:
368          sprintf (Name, "XYZ Lock");
369          break;
370       default:
371          sprintf (Name, "?");
372          SUMA_RETURN (NOPE);
373 
374    }
375 
376    SUMA_RETURN (YUP);
377 }
378 
379 /* Use this function to capture GVS as last displayed */
SUMA_CopyGeomViewStruct(SUMA_GEOMVIEW_STRUCT * gvs1,SUMA_GEOMVIEW_STRUCT * gvs2)380 SUMA_Boolean SUMA_CopyGeomViewStruct(SUMA_GEOMVIEW_STRUCT *gvs1,
381                                      SUMA_GEOMVIEW_STRUCT *gvs2)
382 {
383    static char FuncName[]={"SUMA_CopyGeomViewStruct"};
384 
385    SUMA_ENTRY;
386 
387    if (!gvs1 || !gvs2) SUMA_RETURN(NOPE);
388 
389    /* This assumes that SUMA_GEOMVIEW_STRUCT has no dynamic allocations */
390    memcpy(gvs2, gvs1, sizeof(SUMA_GEOMVIEW_STRUCT));
391    SUMA_RETURN(YUP);
392 }
393 
394 
395 /* overzealous but prudent */
SUMA_DiffGeomViewStruct(SUMA_GEOMVIEW_STRUCT gvs1,SUMA_GEOMVIEW_STRUCT gvs2,int level)396 SUMA_Boolean SUMA_DiffGeomViewStruct(SUMA_GEOMVIEW_STRUCT gvs1,
397                                      SUMA_GEOMVIEW_STRUCT gvs2,
398                                      int level)
399 {
400    static char FuncName[]={"SUMA_DiffGeomViewStruct"};
401 
402    SUMA_ENTRY;
403 
404    if (level <= 1) { /* big deal, should change position of object in space */
405       if (SUMA_VEC_DIFF3(gvs1.ViewFrom, gvs2.ViewFrom)) SUMA_RETURN(2);
406       if (SUMA_VEC_DIFF3(gvs1.ViewCenter, gvs2.ViewCenter)) SUMA_RETURN(4);
407       if (SUMA_VEC_DIFF3(gvs1.ViewCamUp, gvs2.ViewCamUp)) SUMA_RETURN(6);
408       if (gvs1.ViewDistance != gvs2.ViewDistance) SUMA_RETURN(7);
409       if (SUMA_VEC_DIFF3(gvs1.translateVec, gvs2.translateVec))
410                                                    SUMA_RETURN(15);
411       if (SUMA_VEC_DIFF3(gvs1.RotaCenter, gvs2.RotaCenter)) SUMA_RETURN(16);
412       if (SUMA_VEC_DIFF4(gvs1.deltaQuat, gvs2.deltaQuat)) SUMA_RETURN(24);
413       if (SUMA_VEC_DIFF4(gvs1.currentQuat, gvs2.currentQuat)) SUMA_RETURN(25);
414       if (gvs1.ApplyMomentum != gvs2.ApplyMomentum) SUMA_RETURN(26);
415 
416    }
417    if (level > 1) { /* any change */
418       if (gvs1.DimSclFac != gvs2.DimSclFac) SUMA_RETURN(1);
419       if (SUMA_VEC_DIFF3(gvs1.ViewFromOrig, gvs2.ViewFromOrig)) SUMA_RETURN(3);
420       if (SUMA_VEC_DIFF3(gvs1.ViewCenterOrig, gvs2.ViewCenterOrig))
421                                                                 SUMA_RETURN(5);
422       if (gvs1.translateBeginX != gvs2.translateBeginX) SUMA_RETURN(8);
423       if (gvs1.translateBeginY != gvs2.translateBeginY) SUMA_RETURN(9);
424       if (gvs1.translateDeltaX != gvs2.translateDeltaX) SUMA_RETURN(10);
425       if (gvs1.translateDeltaY != gvs2.translateDeltaY) SUMA_RETURN(11);
426       if (gvs1.TranslateGain != gvs2.TranslateGain) SUMA_RETURN(12);
427       if (gvs1.ArrowtranslateDeltaX != gvs2.ArrowtranslateDeltaX)
428                               SUMA_RETURN(13);
429       if (gvs1.ArrowtranslateDeltaY != gvs2.ArrowtranslateDeltaY)
430                               SUMA_RETURN(14);
431       if (gvs1.zoomDelta != gvs2.zoomDelta) SUMA_RETURN(17);
432       if (gvs1.zoomBegin != gvs2.zoomBegin) SUMA_RETURN(18);
433       if (gvs1.spinDeltaX != gvs2.spinDeltaX) SUMA_RETURN(19);
434       if (gvs1.spinDeltaY != gvs2.spinDeltaY) SUMA_RETURN(20);
435       if (gvs1.spinBeginX != gvs2.spinBeginX) SUMA_RETURN(21);
436       if (gvs1.spinBeginY != gvs2.spinBeginY) SUMA_RETURN(22);
437       if (gvs1.MinIdleDelta != gvs2.MinIdleDelta) SUMA_RETURN(23);
438       if (gvs1.vLHpry[0] != gvs2.vLHpry[0]) SUMA_RETURN(27);
439       if (gvs1.vLHpry0[0] != gvs2.vLHpry0[0]) SUMA_RETURN(28);
440       if (gvs1.vLHpry[1] != gvs2.vLHpry[1]) SUMA_RETURN(29);
441       if (gvs1.vLHpry0[1] != gvs2.vLHpry0[1]) SUMA_RETURN(30);
442       if (gvs1.vLHpry[2] != gvs2.vLHpry[2]) SUMA_RETURN(31);
443       if (gvs1.vLHpry0[2] != gvs2.vLHpry0[2]) SUMA_RETURN(32);
444       if (gvs1.LHlol != gvs2.LHlol) SUMA_RETURN(33);
445    }
446 
447    /* if (gvs1. != gvs2.) SUMA_RETURN(); */
448 
449    SUMA_RETURN(0); /* no difference */
450 }
451 
SUMA_VerifyRenderOrder(char * ord,void * unused)452 int SUMA_VerifyRenderOrder(char *ord, void *unused)
453 {
454    static char FuncName[]={"SUMA_VerifyRenderOrder"};
455 
456    if (SUMA_SetObjectDisplayOrder(ord, NULL) < 0) return(0);
457 
458    return(1);
459 }
460 
SUMA_SetObjectDisplayOrder(char * ord,int * otseq)461 int SUMA_SetObjectDisplayOrder(char *ord, int *otseq)
462 {
463    static char FuncName[]={"SUMA_SetObjectDisplayOrder"};
464    NI_str_array *sar = NULL;
465    int iii, cnt = 0, bad = 0, dummy[N_DO_TYPES], used[N_DO_TYPES];
466    SUMA_Boolean LocalHead = NOPE;
467 
468    SUMA_ENTRY;
469 
470    cnt = -1;
471 
472    if (!otseq) otseq = dummy;
473 
474    if (!ord || !strcmp(ord,"DEFAULT")) {
475       otseq[0] = VO_type;
476       otseq[1] = SO_type;
477       otseq[2] = GRAPH_LINK_type;
478       cnt = 3;
479       RETURN(cnt);
480    }
481 
482    memset(used, 0, N_DO_TYPES*sizeof(int));
483    deblank_name(ord);
484    if ((sar = SUMA_NI_decode_string_list( ord , ",;"))) {
485       cnt = 0;
486       for (iii=0; iii<sar->num; ++iii) {
487          if (sar->str[iii]) deblank_name(sar->str[iii]);
488          if (sar->str[iii]) {
489             bad = 0;
490                    if (!strncasecmp(sar->str[iii],"sur", 3)) {
491                if (!used[SO_type]) {
492                   otseq[cnt++] = SO_type;
493                   used[SO_type] = 1;
494                } else {
495                   SUMA_S_Err("Duplicate reference to surfaces in %s",
496                              sar->str[iii]);
497                   bad = 1;
498                }
499             } else if (!strncasecmp(sar->str[iii],"vol", 3)) {
500                if (!used[VO_type]) {
501                   otseq[cnt++] = VO_type;
502                   used[VO_type] = 1;
503                } else {
504                   SUMA_S_Err("Duplicate reference to volumes in %s",
505                              sar->str[iii]);
506                   bad = 1;
507                }
508             } else if (!strncasecmp(sar->str[iii],"gra", 3)) {
509                if (!used[GRAPH_LINK_type]) {
510                   otseq[cnt++] = GRAPH_LINK_type;
511                   used[GRAPH_LINK_type] = 1;
512                } else {
513                   SUMA_S_Err("Duplicate reference to graphs in %s",
514                              sar->str[iii]);
515                   bad = 1;
516                }
517             } else if (!strcmp(sar->str[iii],"S")) {
518                if (!used[SO_type]) {
519                   otseq[cnt++] = SO_type;
520                   used[SO_type] = 1;
521                } else {
522                   SUMA_S_Err("Duplicate reference to surfaces in %s",
523                              sar->str[iii]);
524                   bad = 1;
525                }
526             } else if (!strcmp(sar->str[iii],"V")) {
527                if (!used[VO_type]) {
528                   otseq[cnt++] = VO_type;;
529                   used[VO_type] = 1;
530                } else {
531                   SUMA_S_Err("Duplicate reference to volumes in %s",
532                              sar->str[iii]);
533                   bad = 1;
534                }
535             } else if (!strcmp(sar->str[iii],"G")) {
536                if (!used[GRAPH_LINK_type]) {
537                   otseq[cnt++] = GRAPH_LINK_type;
538                   used[GRAPH_LINK_type] = 1;
539                } else {
540                   SUMA_S_Err("Duplicate reference to graphs in %s",
541                              sar->str[iii]);
542                   bad = 1;
543                }
544             } else if (sar->num == 1) {
545                int OK=0, jjj;
546                char *ss=sar->str[0];
547                for (jjj=0; jjj<strlen(ss); ++jjj) {
548                   if (ss[jjj] == 'S' || ss[jjj] == 'V' || ss[jjj] == 'G') ++OK;
549                }
550                if (OK != strlen(ss)) {
551                   bad = 2;
552                }
553                for (jjj=0; jjj<strlen(ss); ++jjj) {
554                   switch (ss[jjj]) {
555                      case 'S':
556                         if (!used[SO_type]) {
557                            otseq[cnt++] = SO_type;
558                            used[SO_type] = 1;
559                         } else {
560                            SUMA_S_Err("Duplicate reference to surfaces in %s",
561                                       sar->str[0]);
562                            bad = 1;
563                         }
564                         break;
565                      case 'V':
566                         if (!used[VO_type]) {
567                            otseq[cnt++] = VO_type;
568                            used[VO_type] = 1;
569                         } else {
570                            SUMA_S_Err("Duplicate reference to volumes in %s",
571                                       sar->str[0]);
572                            bad = 1;
573                         }
574                         break;
575                      case 'G':
576                         if (!used[GRAPH_LINK_type]) {
577                            otseq[cnt++] = GRAPH_LINK_type;
578                            used[GRAPH_LINK_type] = 1;
579                         } else {
580                            SUMA_S_Err("Duplicate reference to graphs in %s",
581                                       sar->str[0]);
582                            bad = 1;
583                         }
584                         break;
585                   }
586                }
587             } else {
588                bad = 2;
589             }
590             if (bad) {
591                if (bad == 2 && otseq != dummy) {
592                SUMA_S_Warn("Object type %s in env SUMA_ObjectDisplayOrder '%s'\n"
593                            "was not recognized. For now only 'surface'\n"
594                            "'volume', and 'graph' are allowed.\n",
595                            sar->str[iii], ord);
596                }
597                if (otseq == dummy) SUMA_RETURN(-1);
598             }
599          }
600       }
601       sar = SUMA_free_NI_str_array(sar);
602    }
603    if (LocalHead && otseq != dummy) {
604       SUMA_LH("Sequence now:");
605       for (iii=0; iii<cnt; ++iii) {
606          fprintf(SUMA_STDERR,"%d ", otseq[iii]);
607       }
608       fprintf(SUMA_STDERR,"\n");
609    }
610 
611    if (ord && ord[0] != '\0' && cnt < 1 && otseq == dummy)
612             SUMA_RETURN(-1); /* an error flag used by SUMA_VerifyRenderOrder()*/
613 
614    SUMA_RETURN(cnt);
615 }
616 
617 /*!
618 Create a SurfaceViewer data structure
619 */
SUMA_Alloc_SurfaceViewer_Struct(int N)620 SUMA_SurfaceViewer *SUMA_Alloc_SurfaceViewer_Struct (int N)
621 {
622    static char FuncName[]={"SUMA_Alloc_SurfaceViewer_Struct"};
623    SUMA_SurfaceViewer *SV=NULL, *SVv=NULL;
624    int i=-1, j=-1, n=-1, iii=-1;
625    float a[3], lightpos[3];
626    char *lightstr;
627    SUMA_Boolean LocalHead = NOPE;
628 
629    SUMA_ENTRY;
630 
631    SVv =  (SUMA_SurfaceViewer *)SUMA_calloc(N, sizeof(SUMA_SurfaceViewer));
632    if (SVv == NULL) {
633       fprintf(SUMA_STDERR,"Error %s: Failed to SUMA_malloc SV\n", FuncName);
634       SUMA_RETURN (NULL);
635    }
636    for (i=0; i < N; ++i) {
637       SV = &(SVv[i]);
638       memset(SV, 0, sizeof(SUMA_SurfaceViewer));
639 
640       SV->C_mode = SUMA_CONV_NONE;
641       SV->C_filter = SUMA_C_newfilter(1, 1);
642       SV->LoadedTextures[0] = -1; /* plug */
643       SV->N_GVS = SUMA_N_STANDARD_VIEWS;
644       SV->GVS = (SUMA_GEOMVIEW_STRUCT *)
645                   SUMA_calloc(SV->N_GVS, sizeof(SUMA_GEOMVIEW_STRUCT));
646       SV->GVS_last_PickMode = (SUMA_GEOMVIEW_STRUCT *)
647                   SUMA_calloc(SV->N_GVS, sizeof(SUMA_GEOMVIEW_STRUCT));
648       if (!SV->GVS) {
649          fprintf(SUMA_STDERR,
650                   "Error %s: Could not allocate for N_GVS.\n",
651                   FuncName);
652          SUMA_RETURN (NULL);
653       }
654       SV->StdView = SUMA_3D; /* default */
655 
656       /* set the standards for all viewing modes here */
657       SV->verbose = 1;
658       {
659          char *eee = getenv("SUMA_AdjustMouseMotionWithZoom");
660          if (eee) {
661             if (strcasecmp (eee, "YES") == 0) SV->ZoomCompensate = 1.0;
662             else SV->ZoomCompensate = 0.0;
663          } else {
664             SV->ZoomCompensate = 1.0;
665          }
666       }
667       {
668          char *eee = getenv("SUMA_FreezeFOVAcrossStates");
669          if (eee) {
670             if (strcasecmp (eee, "YES") == 0) SV->FreezeZoomXstates = 1;
671             else SV->FreezeZoomXstates = 0;
672          } else {
673             SV->FreezeZoomXstates = 1;
674          }
675       }
676       {
677          char *eee = getenv("SUMA_ViewOrthographicProjection");
678          if (eee) {
679             if (strcasecmp (eee, "YES") == 0) SV->ortho = 1;
680             else SV->ortho = 0;
681          } else {
682             SV->ortho = 0;
683          }
684       }
685 
686       SV->ShowLabelAtXhair = 1;
687       if (!SUMA_isEnv("SUMA_ShowLabelsAtCrossHair","YES")) {
688          SV->ShowLabelAtXhair = 0;
689       }
690       SV->ShowSelectedDatum = 1;
691       SV->ShowSelectedFaceSet = 1;
692       SV->ShowSelectedEdge = 1;
693 
694       SV->SelAdo = (DList *)SUMA_calloc(1,sizeof(DList));
695       dlist_init (SV->SelAdo, SUMA_Free_SelectedDO_Datum);
696       SV->LastSel_ado_idcode_str = NULL;
697 
698       SV->Aspect = 1.0;
699       SV->FOV = NULL;
700       SV->auto_FOV_val = NULL;
701       SV->FOV_last_PickMode = NULL;
702 
703       for (j=0; j < SV->N_GVS; ++j) {
704          memset(&(SV->GVS[j]), 0, sizeof(SUMA_GEOMVIEW_STRUCT));
705          SV->GVS[j].DimSclFac = SUMA_DimSclFac(NULL, NULL);
706          switch (j) {
707             case SUMA_2D_Z0:
708             case SUMA_2D_Z0L:
709                /* Default top view, rotate by nothing */
710                SUMA_HOME_QUAT(j, SV->GVS[j].currentQuat);
711                SV->GVS[j].ApplyMomentum = False;
712 
713                SV->GVS[j].vLHpry[0] = 0.0;
714                SV->GVS[j].vLHpry0[0] = 0.0;
715                SV->GVS[j].vLHpry[1] = 0.0;
716                SV->GVS[j].vLHpry0[1] = 0.0;
717                SV->GVS[j].vLHpry[2] = 0.0;
718                SV->GVS[j].vLHpry0[2] = 0.0;
719                SV->GVS[j].LHlol = 0;
720                SV->GVS[j].MinIdleDelta = 1;
721                SV->GVS[j].TranslateGain = TRANSLATE_GAIN;
722                SV->GVS[j].ArrowtranslateDeltaX = ARROW_TRANSLATE_DELTAX;
723                SV->GVS[j].ArrowtranslateDeltaY = ARROW_TRANSLATE_DELTAY;
724 
725                SV->GVS[j].ViewCamUp[0] = 0.0;
726                SV->GVS[j].ViewCamUp[1] = 1.0;
727                SV->GVS[j].ViewCamUp[2] = 0.0;
728 
729                SV->GVS[j].ViewFrom[0] = 0.0;
730                SV->GVS[j].ViewFrom[1] = 0.0;
731                SV->GVS[j].ViewFrom[2] = SUMA_DEFAULT_VIEW_FROM;
732 
733                SV->GVS[j].ViewCenter[0] = 0.0;
734                SV->GVS[j].ViewCenter[1] = 0.0;
735                SV->GVS[j].ViewCenter[2] = 0.0;
736 
737                SV->GVS[j].RotaCenter[0] = 0.0;
738                SV->GVS[j].RotaCenter[1] = 0.0;
739                SV->GVS[j].RotaCenter[2] = 0.0;
740                break;
741             case SUMA_3D_Z0:
742             case SUMA_3D:
743                SUMA_HOME_QUAT(j, SV->GVS[j].currentQuat);
744 
745                SV->GVS[j].ApplyMomentum = False;
746 
747                SV->GVS[j].vLHpry[0] = 0.0;
748                SV->GVS[j].vLHpry0[0] = 0.0;
749                SV->GVS[j].vLHpry[1] = 0.0;
750                SV->GVS[j].vLHpry0[1] = 0.0;
751                SV->GVS[j].vLHpry[2] = 0.0;
752                SV->GVS[j].vLHpry0[2] = 0.0;
753                SV->GVS[j].LHlol = 0;
754                SV->GVS[j].MinIdleDelta = 1;
755                SV->GVS[j].TranslateGain = TRANSLATE_GAIN;
756                SV->GVS[j].ArrowtranslateDeltaX = ARROW_TRANSLATE_DELTAX;
757                SV->GVS[j].ArrowtranslateDeltaY = ARROW_TRANSLATE_DELTAY;
758 
759                SV->GVS[j].ViewCamUp[0] = 0.0;
760                SV->GVS[j].ViewCamUp[1] = 1.0;
761                SV->GVS[j].ViewCamUp[2] = 0.0;
762 
763                SV->GVS[j].ViewFrom[0] = 0.0;
764                SV->GVS[j].ViewFrom[1] = 0.0;
765                SV->GVS[j].ViewFrom[2] = 0.0;
766 
767                SV->GVS[j].ViewCenter[0] = 0.0;
768                SV->GVS[j].ViewCenter[1] = 0.0;
769                SV->GVS[j].ViewCenter[2] = 0.0;
770 
771                SV->GVS[j].RotaCenter[0] = 0.0;
772                SV->GVS[j].RotaCenter[1] = 0.0;
773                SV->GVS[j].RotaCenter[2] = 0.0;
774 
775                SV->GVS[j].translateVec[0] = 0.0;
776                SV->GVS[j].translateVec[1] = 0.0;
777                break;
778             default:
779                fprintf(SUMA_STDERR,
780                         "Error %s: Undefined viewing mode.\n", FuncName);
781                SUMA_RETURN (NULL);
782 
783          }
784       }
785 
786 
787       SV->light0_position[0] = 0.0;
788       SV->light0_position[1] = 0.0;
789 
790       SV->light0_position[2] = 1.0 * SUMA_INTITIAL_LIGHT0_SWITCH;
791       SV->lit_for = SUMA_INTITIAL_LIGHT0_SWITCH;
792 
793       SV->light0_position[3] = 0.0;
794 
795       lightstr = getenv("SUMA_Light0Position");
796       if (lightstr) {
797          if (SUMA_StringToNum (lightstr, (void *)lightpos, 3, 1) == 3) {
798             SV->light0_position[0] = lightpos[0];
799             SV->light0_position[1] = lightpos[1];
800             SV->light0_position[2] = lightpos[2];
801          }
802       }
803 
804       SV->light1_position[0] = 1.0;
805       SV->light1_position[1] = 1.0;
806       SV->light1_position[2] = 1.0;
807       SV->light1_position[3] = 0.0;
808 
809       lightstr = getenv("SUMA_Light1Position");
810       if (lightstr) {
811          if (SUMA_StringToNum (lightstr, (void *)lightpos, 3, 1) == 3) {
812             SV->light1_position[0] = lightpos[0];
813             SV->light1_position[1] = lightpos[1];
814             SV->light1_position[2] = lightpos[2];
815          }
816       }
817 
818 
819       SV->dim_spe = 1.0;
820       SV->dim_dif = 1.0;
821       SV->dim_emi = 1.0;
822       SV->dim_amb = 1.0;
823 
824       {
825          static SUMA_Boolean err = NOPE;
826          float fv3[3];
827          char *eee = getenv("SUMA_Light0Color");
828          if (eee && !err) {
829             if (SUMA_StringToNum (eee, (void *)fv3, 3, 1) != 3) {
830                err = YUP;
831                SUMA_SL_Err("Syntax error in environment\n"
832                            "variable SUMA_Light0Color");
833                SV->light0_color[0] = SUMA_LIGHT0_COLOR_R;
834                SV->light0_color[1] = SUMA_LIGHT0_COLOR_G;
835                SV->light0_color[2] = SUMA_LIGHT0_COLOR_B;
836                SV->light0_color[3] = SUMA_LIGHT0_COLOR_A;
837             }else {
838                SV->light0_color[0] = fv3[0];
839                SV->light0_color[1] = fv3[1];
840                SV->light0_color[2] = fv3[2];
841                SV->light0_color[3] = SUMA_LIGHT0_COLOR_A;
842             }
843          }else {
844             SV->light0_color[0] = SUMA_LIGHT0_COLOR_R;
845             SV->light0_color[1] = SUMA_LIGHT0_COLOR_G;
846             SV->light0_color[2] = SUMA_LIGHT0_COLOR_B;
847             SV->light0_color[3] = SUMA_LIGHT0_COLOR_A;
848          }
849       }
850 
851       {
852          static SUMA_Boolean err = NOPE;
853          float fv3[3];
854          char *eee = getenv("SUMA_AmbientLight");
855          if (eee && !err) {
856             if (SUMA_StringToNum (eee, (void *)fv3, 3, 1) != 3) {
857                err = YUP;
858                SUMA_SL_Err("Syntax error in environment\n"
859                            "variable SUMA_AmbientLight");
860                SV->lmodel_ambient[0] = SUMA_LMODEL_AMBIENT_COLOR_R;
861                SV->lmodel_ambient[1] = SUMA_LMODEL_AMBIENT_COLOR_G;
862                SV->lmodel_ambient[2] = SUMA_LMODEL_AMBIENT_COLOR_B;
863                SV->lmodel_ambient[3] = SUMA_LMODEL_AMBIENT_COLOR_A;
864             }else {
865                SV->lmodel_ambient[0] = fv3[0];
866                SV->lmodel_ambient[1] = fv3[1];
867                SV->lmodel_ambient[2] = fv3[2];
868                SV->lmodel_ambient[3] = SUMA_LMODEL_AMBIENT_COLOR_A;
869             }
870          }else {
871             SV->lmodel_ambient[0] = SUMA_LMODEL_AMBIENT_COLOR_R;
872             SV->lmodel_ambient[1] = SUMA_LMODEL_AMBIENT_COLOR_G;
873             SV->lmodel_ambient[2] = SUMA_LMODEL_AMBIENT_COLOR_B;
874             SV->lmodel_ambient[3] = SUMA_LMODEL_AMBIENT_COLOR_A;
875          }
876       }
877       {
878          static SUMA_Boolean err = NOPE;
879          float fv3[3];
880          char *eee = getenv("SUMA_BackgroundColor");
881          if (eee && !err) {
882             if (SUMA_StringToNum (eee, (void *)fv3, 3,1) != 3) {
883                err = YUP;
884                SUMA_SL_Err("Syntax error in environment\n"
885                            "variable SUMA_BackgroundColor");
886                SV->clear_color[0] = SUMA_CLEAR_COLOR_R;
887                SV->clear_color[1] = SUMA_CLEAR_COLOR_G;
888                SV->clear_color[2] = SUMA_CLEAR_COLOR_B;
889                SV->clear_color[3] = SUMA_CLEAR_COLOR_A;
890             }else {
891                SV->clear_color[0] = fv3[0];
892                SV->clear_color[1] = fv3[1];
893                SV->clear_color[2] = fv3[2];
894                SV->clear_color[3] = SUMA_CLEAR_COLOR_A;
895             }
896          }else {
897             SV->clear_color[0] = SUMA_CLEAR_COLOR_R;
898             SV->clear_color[1] = SUMA_CLEAR_COLOR_G;
899             SV->clear_color[2] = SUMA_CLEAR_COLOR_B;
900             SV->clear_color[3] = SUMA_CLEAR_COLOR_A;
901          }
902       }
903 
904       SV->wWindWidth  = 350;
905       SV->wWindHeight = 350;
906       SV->DrawAreaHeightOffset = -1; /* Not known yet */
907       SV->DrawAreaWidthOffset = -1; /* Not known yet */
908       {
909          char *eee = getenv("SUMA_ArrowRotAngle");
910          if (eee) {
911             float rotval = strtod(eee, NULL);
912             if (rotval > 0.0 && rotval < 360.0)
913                SV->ArrowRotationAngle = SUMA_PI * rotval / 180.0;
914             else
915                SV->ArrowRotationAngle = SUMA_PI *
916                                     ARROW_ROTATION_ANGLE_DEG / 180.0;
917          } else
918             SV->ArrowRotationAngle = SUMA_PI * ARROW_ROTATION_ANGLE_DEG / 180.0;
919       }
920       {
921          char *eee = getenv("SUMA_KeyZoomGain");
922          if (eee) {
923             float rotval = strtod(eee, NULL);
924             if (rotval > 0.0 && rotval < 50.0) SV->KeyZoomGain = rotval/100.0;
925             else SV->KeyZoomGain = 0.05;
926          } else SV->KeyZoomGain = 0.05;
927       }
928       {
929          char *eee = getenv("SUMA_KeyNodeJump");
930          if (eee) {
931             int KeyNodeJump = (int)strtod(eee, NULL);
932             if (KeyNodeJump > 0 && KeyNodeJump <= 10)
933                SV->KeyNodeJump = KeyNodeJump;
934             else SV->KeyNodeJump = 1;
935          } else SV->KeyNodeJump = 1;
936       }
937       {
938          char *eee = getenv("SUMA_ContourThickness");
939          if (eee) {
940             float th = strtod(eee, NULL);
941             if (th > 0 && th <= 100)
942                SV->ContThick = th;
943             else SV->ContThick = 1;
944          } else SV->ContThick = 1;
945       }
946 
947       {
948          char *eee = getenv("SUMA_FOV_Original");
949          if (eee) {
950             float fovinit = strtod(eee, NULL);
951             if (fovinit > 1.0 && fovinit < 100.0)  SV->FOV_original = fovinit;
952             else  if (fovinit < 0) SV->FOV_original = -1;
953             else SV->FOV_original = FOV_INITIAL;
954          } else SV->FOV_original = FOV_INITIAL;
955       }
956 
957       SV->Open = NOPE;
958 
959       SV->RegistDO = (SUMA_DO_LOCATOR *)
960          SUMA_calloc( SUMA_MAX_DISPLAYABLE_OBJECTS, sizeof(SUMA_DO_LOCATOR));
961       if (SV->RegistDO == NULL) {
962          SUMA_S_Err("Failed to SUMA_malloc SV->RegistDO");
963          SUMA_RETURN (NULL);
964       }
965       SV->N_DO = 0; /* Nothing is registered with the viewer yet */
966 
967       SV->ColList = (SUMA_COLORLIST_STRUCT **)
968         SUMA_calloc(SUMA_MAX_DISPLAYABLE_OBJECTS,sizeof(SUMA_COLORLIST_STRUCT*));
969       SV->N_ColList = 0; /* this number reflects the number of surfaces that
970                             have colorlist structures in SV */
971 
972       SV->ShowEyeAxis = 0;
973       SV->ShowMeshAxis = 0;      /* Turned off Oct 15 04 in favor of WorldAxis */
974       SV->ShowWorldAxis = SUMA_NO_WAX;
975 
976 
977       SV->WAx = SUMA_Alloc_Axis ("Viewer World Axis", AO_type);
978 
979       if (SV->WAx == NULL) {
980          fprintf(SUMA_STDERR,"Error %s: Error Allocating axis\n", FuncName);
981          SUMA_RETURN(NULL);
982       }
983       SV->WAx->atype = SUMA_SCALE_BOX;
984 
985       SV->Ch = SUMA_Alloc_CrossHair ();
986       if (SV->Ch == NULL) {
987          SUMA_S_Err("Failed in SUMA_Alloc_CrossHair");
988          SUMA_RETURN (NULL);
989       } else SV->ShowCrossHair = 1;
990 
991       SV->X = (SUMA_X *)SUMA_calloc(1,sizeof(SUMA_X));
992       if (SV->X == NULL) {
993          SUMA_S_Err("Failed to SUMA_malloc SV->X");
994          SUMA_RETURN (NULL);
995       }
996 
997       SV->X->Title = NULL;
998       SV->X->LookAt_prmpt = NULL;
999       SV->X->SetRot_prmpt = NULL;
1000       SV->X->JumpIndex_prmpt = NULL;
1001       SV->X->JumpXYZ_prmpt = NULL;
1002       SV->X->JumpFocusNode_prmpt = NULL;
1003       SV->X->JumpFocusFace_prmpt = NULL;
1004       SV->X->HighlightBox_prmpt = NULL;
1005       SV->X->SetRenderOrder_prmpt = NULL;
1006       SV->X->TOPLEVEL = NULL;
1007       SV->X->MOMENTUMID = 0;
1008       SV->X->REDISPLAYPENDING = 0;
1009       SV->X->DOUBLEBUFFER = True;
1010       SV->X->aWIDTH = SV->X->aHEIGHT = 300; /* if you change this, make sure you
1011                                    do so for fallbackResources in SUMA_display */
1012       SV->X->ViewCont = SUMA_CreateViewContStruct();
1013       SV->X->DPY = NULL;
1014       SV->X->FORM = SV->X->FRAME = SV->X->GLXAREA = NULL;
1015       SV->X->VISINFO = NULL;
1016       SV->X->REDISPLAYID = SV->X->MOMENTUMID = 0;
1017       SV->X->CMAP = 0;
1018       SV->X->GLXCONTEXT=NULL;
1019       SV->X->CrappyDrawable = 0;
1020       SV->X->gc=NULL;
1021       SV->X->ToggleCrossHair_View_tglbtn=NULL;
1022       SV->X->ToolsMenu = SUMA_Alloc_Menu_Widget(SW_N_Tools);
1023       SV->X->FileMenu = SUMA_Alloc_Menu_Widget(SW_N_File);
1024       SV->X->ViewMenu = SUMA_Alloc_Menu_Widget(SW_N_View);
1025       SV->X->HelpMenu = SUMA_Alloc_Menu_Widget(SW_N_Help);
1026 
1027       SV->Focus_DO_ID = -1;
1028 
1029       SV->State = NULL;
1030       SV->iState = -1;
1031       SV->VSv = NULL;
1032       SV->N_VSv = 0;
1033       SV->LastNonMapStateID = -1;
1034 
1035       SV->iCurGroup = -1;
1036       SV->CurGroupName = NULL;
1037       SUMA_AdoptGroup(SV, NULL); /* Set to the default so we have something */
1038 
1039       SV->PolyMode = SRM_Fill;
1040       SV->TransMode = STM_0;
1041       SV->MouseMode = SUMA_DEF_MMODE;
1042       SV->MouseMode_ado_idcode_str = NULL;
1043       SV->DO_DrawMask = SDODM_All;
1044 
1045       #if SUMA_BACKFACE_CULL
1046          SV->BF_Cull = YUP;
1047       #else
1048          SV->BF_Cull = NOPE;
1049       #endif
1050 
1051       SV->ShowForeground = YUP;
1052       SV->ShowBackground = YUP;
1053 
1054       {
1055          char *eee = getenv("SUMA_CenterOnPatch");
1056          if (eee) {
1057             if (strcasecmp (eee, "YES") == 0) SV->UsePatchDims = YUP;
1058             else SV->UsePatchDims = NOPE;
1059          } else {
1060             SV->UsePatchDims = NOPE;
1061          }
1062       }
1063       SV->Back_Modfact = SUMA_BACKGROUND_MODULATION_FACTOR;
1064 
1065       SV->isShaded = NOPE;
1066 
1067       SV->LinkAfniCrossHair = YUP;
1068 
1069       SV->ResetGLStateVariables = YUP;
1070       SV->NewGeom = NOPE;
1071       SV->BS = NULL;
1072 
1073       SV->ShowRight = YUP;
1074       SV->ShowLeft = YUP;
1075       SV->Record = NOPE;
1076       SV->rdc = SUMA_RDC_NOT_SET;
1077 
1078       SV->Blend_Mode = SUMA_NO_BLEND;
1079 
1080       SV->Do_3Drender = 0;
1081       memset(&(SV->SER), 0, sizeof(SUMA_EnablingRecord));
1082 
1083       SV->DO_PickMode = 0;
1084       SV->pick_colid_list = NULL;
1085       SV->PickPix[0] = SV->PickPix[1] = -1;
1086       SV->pickrenpix4 = NULL;
1087 
1088       /* Squence of types to be displayed. Anything not in the list
1089          gets displayed first */
1090       SV->N_otseq = SUMA_SetObjectDisplayOrder("DEFAULT", SV->otseq);
1091       {
1092          char *eee = getenv("SUMA_ObjectDisplayOrder");
1093          if (eee) {
1094             if ((SV->N_otseq = SUMA_SetObjectDisplayOrder(eee, SV->otseq))<0){
1095                SUMA_S_Warn("Failed to parse %s, reverting to default order",
1096                            eee);
1097                SV->N_otseq = SUMA_SetObjectDisplayOrder("DEFAULT", SV->otseq);
1098             }
1099          }
1100       }
1101 
1102       SV->PryAx = 3;
1103    }
1104    SUMA_RETURN (SVv);
1105 }
1106 
SUMA_Get_From_PickResult_List(SUMA_SurfaceViewer * sv,SUMA_ALL_DO * ado,char * variant)1107 SUMA_PICK_RESULT *SUMA_Get_From_PickResult_List(SUMA_SurfaceViewer *sv,
1108                               SUMA_ALL_DO *ado, char *variant)
1109 {
1110    static char FuncName[]={"SUMA_Get_From_PickResult_List"};
1111    DListElmt *el = NULL;
1112    SUMA_SEL_ADO_DATUM *ss = NULL;
1113    SUMA_PICK_RESULT *PR = NULL;
1114    SUMA_Boolean LocalHead = NOPE;
1115 
1116    SUMA_ENTRY;
1117 
1118    if (!sv || !sv->SelAdo || !ado) SUMA_RETURN(NULL);
1119    if (!variant) variant = "none";
1120    if (!dlist_size(sv->SelAdo)) SUMA_RETURN(NULL);
1121    SUMA_LH("Get %s", ADO_LABEL(ado));
1122    el = NULL;
1123    do {
1124       if (!el) el = dlist_head(sv->SelAdo);
1125       else el = dlist_next(el);
1126 
1127       ss = (SUMA_SEL_ADO_DATUM *)el->data;
1128       if (!strcmp(ss->ado_idcode_str, ADO_ID(ado)) &&
1129           !strcmp(ss->variant, variant)) {
1130          dlist_remove(sv->SelAdo, el, (void **)&ss);
1131          PR = ss->PR; ss->PR = NULL;
1132          SUMA_Free_SelectedDO_Datum(ss); ss = NULL;
1133          SUMA_RETURN(PR);
1134       }
1135    } while (el != dlist_tail(sv->SelAdo));
1136 
1137    SUMA_RETURN(NULL);
1138 }
1139 
SUMA_Add_To_PickResult_List(SUMA_SurfaceViewer * sv,SUMA_ALL_DO * ado,char * variant,SUMA_PICK_RESULT ** PR)1140 SUMA_Boolean SUMA_Add_To_PickResult_List(SUMA_SurfaceViewer *sv,
1141                                    SUMA_ALL_DO *ado,
1142                                    char *variant, SUMA_PICK_RESULT **PR)
1143 {
1144    static char FuncName[]={"SUMA_Add_To_PickResult_List"};
1145    DListElmt *el = NULL;
1146    SUMA_SEL_ADO_DATUM *ss = NULL;
1147    SUMA_Boolean LocalHead = NOPE;
1148 
1149    SUMA_ENTRY;
1150 
1151    if (!sv || !sv->SelAdo) SUMA_RETURN(NOPE);
1152    if (!variant) variant = "none";
1153    if (ado) { /* Add */
1154       SUMA_LH("Add %s", ADO_LABEL(ado));
1155       ss = (SUMA_SEL_ADO_DATUM *)
1156                      SUMA_calloc(1,sizeof(SUMA_SEL_ADO_DATUM));
1157       ss->ado_idcode_str = SUMA_copy_string(ADO_ID(ado));
1158       ss->variant = SUMA_copy_string(variant);
1159       if (PR) { ss->PR = *PR; *PR = NULL; }
1160       dlist_ins_next(sv->SelAdo, dlist_tail(sv->SelAdo),
1161                      (void *)ss);
1162    } else if (!strcmp(variant,"TERSUM")) { /* empty entire list */
1163       SUMA_LH("Cleanup your act %d entries", dlist_size(sv->SelAdo));
1164       if (dlist_size(sv->SelAdo)) {
1165          while (el = dlist_head(sv->SelAdo)) {
1166             dlist_remove(sv->SelAdo, el, (void **)&ss);
1167             SUMA_Free_SelectedDO_Datum(ss);
1168          }
1169       }
1170    } else {
1171       SUMA_LH("Nothing done (%p, %s)", ado, variant);
1172       SUMA_DUMP_TRACE("Whodunnit?");
1173    }
1174    SUMA_RETURN(YUP);
1175 }
1176 
SUMA_Show_PickList(DList * SelAdo,int detail,char * headstring,FILE * out)1177 void SUMA_Show_PickList(DList *SelAdo, int detail, char *headstring, FILE *out)
1178 {
1179    static char FuncName[]={"SUMA_Show_PickList"};
1180    char *s;
1181 
1182    SUMA_ENTRY;
1183 
1184    if (!out) out = SUMA_STDERR;
1185 
1186    if (headstring) fprintf(out, "%s", headstring);
1187 
1188    s = SUMA_PickList_Info(SelAdo, detail);
1189    if (s) fprintf(out, "%s", s);
1190 
1191    SUMA_ifree(s);
1192 
1193    SUMA_RETURNe;
1194 }
1195 
SUMA_PickList_Info(DList * SelAdo,int detail)1196 char *SUMA_PickList_Info(DList *SelAdo, int detail)
1197 {
1198    static char FuncName[]={"SUMA_Show_PickList_Info"};
1199    SUMA_STRING *SS = NULL;
1200    DListElmt *el = NULL;
1201    SUMA_SEL_ADO_DATUM *ss = NULL;
1202    char *s=NULL;
1203    SUMA_ALL_DO *ado=NULL;
1204    int ii;
1205    SUMA_Boolean LocalHead = NOPE;
1206 
1207    SUMA_ENTRY;
1208 
1209    SS = SUMA_StringAppend (NULL, NULL);
1210 
1211    if (!SelAdo) {
1212       SS = SUMA_StringAppend(SS, "NULL SelAdo");
1213       goto OUT;
1214    }
1215    SS = SUMA_StringAppend_va(SS,
1216             "SelAdo list of %d entries\n", dlist_size(SelAdo));
1217    el = NULL; ii = 0;
1218    do {
1219       if (!el) el = dlist_head(SelAdo);
1220       else el = dlist_next(el);
1221       if (!(ss = (SUMA_SEL_ADO_DATUM *)el->data)) {
1222          SS = SUMA_StringAppend_va(SS,"%d: NULL data!!!\n", ii);
1223       } else {
1224          if ((ado = SUMA_whichADOg(ss->ado_idcode_str))) {
1225             SS = SUMA_StringAppend_va(SS,"%d: ADO %s, variant %s\n",
1226                         ii, ADO_LABEL(ado), ss->variant);
1227          }else {
1228             SS = SUMA_StringAppend_va(SS,"%d: ADO NULL!!!\n",ii);
1229          }
1230       }
1231       ++ii;
1232    } while (el != dlist_tail(SelAdo));
1233 
1234    OUT:
1235    SS = SUMA_StringAppend (SS, NULL);
1236    s = SS->s;
1237    SUMA_free(SS);
1238 
1239    SUMA_RETURN(s);
1240 }
1241 
1242 
SUMA_Process_Selected_ADO(SUMA_SurfaceViewer * sv,int deepfirst)1243 SUMA_Boolean SUMA_Process_Selected_ADO(SUMA_SurfaceViewer *sv, int deepfirst)
1244 {
1245    static char FuncName[]={"SUMA_Process_Selected_ADO"};
1246    DListElmt *el = NULL;
1247    SUMA_SEL_ADO_DATUM *ss = NULL;
1248    SUMA_ALL_DO *ado=NULL;
1249    int ii, nn, *isrt;
1250    SUMA_SEL_ADO_DATUM **ssv=NULL;
1251    float *Pxyz, *Sxyz;
1252    SUMA_Boolean LocalHead = NOPE;
1253 
1254    SUMA_ENTRY;
1255 
1256    if (!sv || !sv->SelAdo) SUMA_RETURN(NOPE);
1257    if (!(nn=dlist_size(sv->SelAdo))) {
1258       SUMA_LH("Empty list");
1259       SUMA_RETURN(YUP);
1260    }
1261 
1262    if (LocalHead) {
1263       SUMA_Show_PickList(sv->SelAdo, 1, "Before sorting:\n", NULL);
1264    }
1265 
1266    if (nn > 1) {
1267       Pxyz = (float *)SUMA_calloc(3*nn, sizeof(float));
1268       Sxyz = (float *)SUMA_calloc(3*nn, sizeof(float));
1269       ssv = (SUMA_SEL_ADO_DATUM **)SUMA_calloc(nn, sizeof(SUMA_SEL_ADO_DATUM *));
1270 
1271 
1272       el = NULL; ii = 0;
1273       do {
1274          if (!el) el = dlist_head(sv->SelAdo);
1275          else el = dlist_next(el);
1276          if (!(ss = (SUMA_SEL_ADO_DATUM *)el->data)) {
1277             SUMA_S_Err("NULL data!!!"); SUMA_RETURN(NOPE);
1278          }
1279          if ((ado = SUMA_whichADOg(ss->ado_idcode_str))) {
1280             /* Collect the PickXYZs */
1281             Pxyz[3*ii] = ss->PR->PickXYZ[0];
1282             Pxyz[3*ii+1] = ss->PR->PickXYZ[1];
1283             Pxyz[3*ii+2] = ss->PR->PickXYZ[2];
1284             ssv[ii] = ss; /* Keep a copy */
1285             ++ii;
1286          } else {
1287             SUMA_LH("NULL ado?");
1288          }
1289       } while (el != dlist_tail(sv->SelAdo));
1290 
1291       nn = ii; /* in case we had null nonesense */
1292       if (!nn) {
1293          SUMA_LH("Nothing good in here");
1294          SUMA_ifree(ssv); SUMA_ifree(Pxyz); SUMA_ifree(Sxyz);
1295          SUMA_RETURN(YUP);
1296       }
1297 
1298       /* Now change all dems coords to eyeball land */
1299       SUMA_World2ScreenCoordsF(sv, nn, Pxyz, Sxyz, NULL, YUP, NOPE);
1300 
1301       /* Sort by depth */
1302       for (ii=0; ii<nn; ++ii) {
1303          Sxyz[ii] = Sxyz[3*ii+2];
1304       }
1305       isrt = SUMA_z_qsort (Sxyz, nn);
1306 
1307       /* Delete the list and recreate sorted */
1308       el = NULL;
1309       do {
1310          dlist_remove(sv->SelAdo, dlist_head(sv->SelAdo), (void **)&ss);
1311          /* Do not delete ss, we have a copy in ssv */
1312       } while (dlist_size(sv->SelAdo));
1313 
1314       /* Now recreate in ordered fashion */
1315       if (!deepfirst) {
1316          for (ii=0; ii<nn; ++ii)  {
1317             dlist_ins_next(sv->SelAdo, dlist_head(sv->SelAdo), ssv[isrt[ii]]);
1318             ssv[isrt[ii]]=NULL;
1319          }
1320       } else {
1321          for (ii=0; ii<nn; ++ii)  {
1322             dlist_ins_prev(sv->SelAdo, dlist_head(sv->SelAdo), ssv[isrt[ii]]);
1323             ssv[isrt[ii]]=NULL;
1324          }
1325       }
1326 
1327       SUMA_ifree(isrt); SUMA_ifree(ssv); SUMA_ifree(Pxyz); SUMA_ifree(Sxyz);
1328    }
1329 
1330    if (LocalHead) { /* Show me the list after sorting */
1331       if (deepfirst) {
1332          SUMA_Show_PickList(sv->SelAdo, 1,
1333                             "After sorting deepest first:\n", NULL);
1334       } else {
1335          SUMA_Show_PickList(sv->SelAdo, 1,
1336                             "After sorting deepest last:\n", NULL);
1337       }
1338    }
1339 
1340    /* Now apply the top pick */
1341    SUMA_LH("On to apply the PR");
1342    el = dlist_head(sv->SelAdo);
1343    ss = (SUMA_SEL_ADO_DATUM *)el->data;
1344    SUMA_Apply_PR(sv, &(ss->PR));
1345    SUMA_LH("Returning");
1346 
1347    SUMA_RETURN(YUP);
1348 }
1349 
SUMA_Free_SelectedDO_Datum(void * data)1350 void SUMA_Free_SelectedDO_Datum(void *data)
1351 {
1352    SUMA_SEL_ADO_DATUM *ss = (SUMA_SEL_ADO_DATUM *)data;
1353    if (ss) {
1354       SUMA_ifree(ss->ado_idcode_str);
1355       SUMA_ifree(ss->variant);
1356       if (ss->PR) ss->PR = SUMA_free_PickResult(ss->PR);
1357       SUMA_free(ss);
1358    }
1359 }
1360 
SUMA_SV_GetShowSelectedDatum(SUMA_SurfaceViewer * sv)1361 int SUMA_SV_GetShowSelectedDatum(SUMA_SurfaceViewer *sv)
1362 {
1363    static char FuncName[]={"SUMA_SV_GetShowSelectedDatum"};
1364 
1365    if (!sv) return(0);
1366    return(sv->ShowSelectedDatum);
1367 }
1368 
SUMA_SV_SetShowSelectedDatum(SUMA_SurfaceViewer * sv,int act,int callback)1369 SUMA_Boolean SUMA_SV_SetShowSelectedDatum(SUMA_SurfaceViewer *sv,
1370                                           int act, int callback)
1371 {
1372    static char FuncName[]={"SUMA_SV_SetShowSelectedDatum"};
1373 
1374    if (!sv) return(NOPE);
1375 
1376    sv->ShowSelectedDatum = act;
1377    XmToggleButtonSetState(sv->X->ViewMenu->mw[SW_ViewNodeInFocus],
1378                           act, callback);
1379    return(YUP);
1380 }
1381 
SUMA_SV_GetShowSelectedFaceSet(SUMA_SurfaceViewer * sv)1382 int SUMA_SV_GetShowSelectedFaceSet(SUMA_SurfaceViewer *sv)
1383 {
1384    static char FuncName[]={"SUMA_SV_GetShowSelectedFaceSet"};
1385 
1386    if (!sv) return(0);
1387    return(sv->ShowSelectedFaceSet);
1388 }
1389 
SUMA_SV_SetShowSelectedFaceSet(SUMA_SurfaceViewer * sv,int act,int callback)1390 SUMA_Boolean SUMA_SV_SetShowSelectedFaceSet(SUMA_SurfaceViewer *sv,
1391                                           int act, int callback)
1392 {
1393    static char FuncName[]={"SUMA_SV_SetShowSelectedFaceSet"};
1394 
1395    if (!sv || !sv->X) return(NOPE);
1396    sv->ShowSelectedFaceSet = act;
1397    XmToggleButtonSetState(sv->X->ViewMenu->mw[SW_ViewSelectedFaceset],
1398                           act, callback);
1399    return(YUP);
1400 }
1401 
1402 
SUMA_Free_SurfaceViewer_Struct(SUMA_SurfaceViewer * SV)1403 SUMA_Boolean SUMA_Free_SurfaceViewer_Struct (SUMA_SurfaceViewer *SV)
1404 {
1405    static char FuncName[]={"SUMA_Free_SurfaceViewer_Struct"};
1406    int i;
1407 
1408    SUMA_ENTRY;
1409 
1410    if (SV->WAx) SUMA_Free_Axis(SV->WAx);
1411    if (SV->C_filter) SUMA_C_free(SV->C_filter); SV->C_filter=NULL;
1412    if (SV->Ch) SUMA_Free_CrossHair (SV->Ch);
1413    if (SV->SelAdo) dlist_destroy(SV->SelAdo); SUMA_ifree(SV->SelAdo);
1414    SUMA_ifree(SV->LastSel_ado_idcode_str);
1415 
1416    if (SV->X->Title) SUMA_free(SV->X->Title);
1417    if (SV->X->LookAt_prmpt) SUMA_FreePromptDialogStruct (SV->X->LookAt_prmpt);
1418    if (SV->X->SetRot_prmpt) SUMA_FreePromptDialogStruct (SV->X->SetRot_prmpt);
1419    if (SV->X->JumpIndex_prmpt)
1420       SUMA_FreePromptDialogStruct (SV->X->JumpIndex_prmpt);
1421    if (SV->X->JumpXYZ_prmpt)
1422       SUMA_FreePromptDialogStruct (SV->X->JumpXYZ_prmpt);
1423    if (SV->X->JumpFocusNode_prmpt)
1424       SUMA_FreePromptDialogStruct (SV->X->JumpFocusNode_prmpt);
1425    if (SV->X->JumpFocusFace_prmpt)
1426       SUMA_FreePromptDialogStruct (SV->X->JumpFocusFace_prmpt);
1427    if (SV->X->HighlightBox_prmpt)
1428       SUMA_FreePromptDialogStruct (SV->X->HighlightBox_prmpt);
1429    if (SV->X->SetRenderOrder_prmpt)
1430       SUMA_FreePromptDialogStruct (SV->X->SetRenderOrder_prmpt);
1431    if (SV->X->ViewCont) SUMA_FreeViewContStruct(SV->X->ViewCont);
1432    if (SV->X) SUMA_free(SV->X);
1433    if (SV->RegistDO) SUMA_free(SV->RegistDO);
1434    if (SV->VSv) {
1435       for (i=0; i < SV->N_VSv; ++i) {
1436          if (!SUMA_Free_ViewState (&(SV->VSv[i]))) {
1437             fprintf (SUMA_STDERR,
1438                "Error %s: failed in SUMA_Free_ViewState.\n", FuncName);
1439          }
1440       }
1441    }
1442    SUMA_ifree(SV->pickrenpix4);
1443    SUMA_ifree(SV->MouseMode_ado_idcode_str);
1444 
1445    if (SV->CurGroupName) SUMA_free(SV->CurGroupName); SV->CurGroupName= NULL;
1446 
1447    if (SV->GVS) SUMA_free(SV->GVS);
1448    if (SV->State) SV->State = NULL; /* never free that one */
1449    if (SV->ColList) {
1450       for (i=0; i < SV->N_ColList; ++i) {
1451          if (!SUMA_EmptyColorList (SV, NULL))
1452             SUMA_S_Err("Failed in SUMA_EmptyColorList.");
1453       }
1454       /* done dumping structure contents, now free pointer */
1455       SUMA_ifree(SV->ColList);
1456       SV->N_ColList = 0;
1457    }
1458 
1459    if (SV->BS) {
1460       SUMA_EmptyDestroyList(SV->BS);
1461    }
1462 
1463    SUMA_ifree(SV->FOV);
1464    SUMA_ifree(SV->FOV_last_PickMode);
1465    SUMA_ifree(SV->auto_FOV_val);
1466 
1467    SUMA_RETURN(YUP);
1468 }
1469 
SUMA_Free_SurfaceViewer_Struct_Vect(SUMA_SurfaceViewer * SVv,int N)1470 SUMA_Boolean SUMA_Free_SurfaceViewer_Struct_Vect (SUMA_SurfaceViewer *SVv, int N)
1471 {
1472    static char FuncName[]={"SUMA_Free_SurfaceViewer_Struct_Vect"};
1473    int i;
1474    SUMA_Boolean Ret= YUP;
1475 
1476    SUMA_ENTRY;
1477 
1478    for (i=0; i < N; ++i)  {
1479       if (&SVv[i] != NULL) {
1480          Ret = Ret * SUMA_Free_SurfaceViewer_Struct (&SVv[i]);
1481       }
1482    }
1483 
1484    if (SVv) SUMA_free(SVv);
1485    SUMA_RETURN(Ret);
1486 }
1487 
1488 /*!
1489 \brief SUMA_ADO_FillColorList_Params(SUMA_ALL_DO *ADO,
1490                                      int *N_points, char *idcode);
1491 */
SUMA_ADO_FillColorList_Params(SUMA_ALL_DO * ADO,int * N_points,char ** idcode)1492 SUMA_Boolean SUMA_ADO_FillColorList_Params(SUMA_ALL_DO *ADO,
1493                                      int *N_points, char **idcode)
1494 {
1495    static char FuncName[]={"SUMA_ADO_FillColorList_Params"};
1496    SUMA_Boolean LocalHead = NOPE;
1497 
1498    SUMA_ENTRY;
1499 
1500    if (!ADO || !N_points || !idcode) {
1501       SUMA_RETURN(NOPE);
1502    }
1503    *N_points = -1; *idcode = NULL;
1504 
1505    switch (ADO->do_type) {
1506       case SO_type: {
1507          SUMA_SurfaceObject *SO=(SUMA_SurfaceObject *)ADO;
1508          *N_points = SO->N_Node;
1509          *idcode = SO->idcode_str;
1510          SUMA_LHv("Filling a color list for surface %s (%s).\n",
1511                   SO->Label, SO->idcode_str);
1512          } break;
1513       case GDSET_type: {
1514          SUMA_DSET *dset=(SUMA_DSET *)ADO;
1515          if (!SUMA_isGraphDset(dset)) {
1516             SUMA_S_Err("Dataset should be graph type");
1517             SUMA_RETURN(NOPE);
1518          }
1519          *N_points = 1+SUMA_GDSET_Max_Edge_Index(dset);
1520          *idcode = SDSET_ID(dset);
1521          SUMA_LHv("Filling a color list for dset %s (%s).\n",
1522                   SDSET_LABEL(dset), SDSET_ID(dset));
1523          } break;
1524       case GRAPH_LINK_type: {
1525          SUMA_DSET *dset=SUMA_find_GLDO_Dset((SUMA_GraphLinkDO *)ADO);
1526          if (dset)
1527             SUMA_RETURN(SUMA_ADO_FillColorList_Params(
1528                                     (SUMA_ALL_DO *)dset, N_points, idcode));
1529          } break;
1530       case CDOM_type:
1531       case MASK_type:
1532       case TRACT_type:
1533       case VO_type: {
1534          *N_points = SUMA_ADO_N_Datum(ADO);
1535          *idcode = ADO_ID(ADO);
1536          SUMA_LHv("Filling a color list for tract %s (%s) %d points.\n",
1537                   ADO_LABEL(ADO), ADO_ID(ADO), *N_points);
1538          break; }
1539       default:
1540          SUMA_S_Errv("Not ready for type %d (%s)\n",
1541                      ADO->do_type,
1542                      SUMA_ObjectTypeCode2ObjectTypeName(ADO->do_type));
1543          SUMA_RETURN(NOPE);
1544    }
1545 
1546    SUMA_RETURN(YUP);
1547 }
1548 
SUMA_BlankColorListStruct(SUMA_COLORLIST_STRUCT * cl)1549 SUMA_Boolean SUMA_BlankColorListStruct(SUMA_COLORLIST_STRUCT *cl)
1550 {
1551    static char FuncName[]={"SUMA_BlankColorListStruct"};
1552    int i = 0;
1553 
1554    SUMA_ENTRY;
1555 
1556    if (!cl || !cl->glar_ColorList_private) {
1557       SUMA_S_Err("NULL input");
1558       SUMA_RETURN(NOPE);
1559    }
1560    /* fill up with blanks, may be unecessary ... */
1561    i=0;
1562    while (i < cl->N_glar_ColorList) {
1563       cl->glar_ColorList_private[i] =
1564                                                 SUMA_GRAY_NODE_COLOR; ++i;
1565       cl->glar_ColorList_private[i] =
1566                                                 SUMA_GRAY_NODE_COLOR; ++i;
1567       cl->glar_ColorList_private[i] =
1568                                                 SUMA_GRAY_NODE_COLOR; ++i;
1569       cl->glar_ColorList_private[i] = SUMA_NODE_ALPHA; ++i;
1570    }
1571 
1572    SUMA_RETURN(YUP);
1573 }
1574 
1575 /*
1576    Accessor function to pointer cl->glar_ColorList_private
1577 */
SUMA_GetColorListPtr(SUMA_COLORLIST_STRUCT * cl)1578 GLfloat * SUMA_GetColorListPtr (SUMA_COLORLIST_STRUCT *cl)
1579 {
1580    static char FuncName[]={"SUMA_GetColorListPtr"};
1581 
1582    if (!cl) return(NULL);
1583    if (cl->glar_ColorList_private) {
1584       return(cl->glar_ColorList_private);
1585    } else if (cl->idcode_str) {
1586       SUMA_ALL_DO *ado = SUMA_whichADOg(cl->idcode_str);
1587       int N_points;
1588       char *idcode=NULL;
1589       SUMA_Boolean LocalHead = NOPE;
1590       SUMA_LH("Found but must allocate for colorlist");
1591       if (!SUMA_ADO_FillColorList_Params(ado, &N_points, &idcode)) {
1592          SUMA_S_Err("Failed to initialize params");
1593          return(NULL);
1594       }
1595       /* That previous call to get N_points may be a waste.
1596          The number of values is already in cl->N_glar_ColorList
1597          so just check for redundancy now */
1598       if (4*N_points != cl->N_glar_ColorList) {
1599          SUMA_S_Err("This should not happen: %d clashes with %d",
1600                     N_points, cl->N_glar_ColorList);
1601          return(NULL);
1602       }
1603       if (!(cl->glar_ColorList_private =
1604                (GLfloat *) SUMA_calloc (N_points*4, sizeof(GLfloat)))) {
1605          SUMA_S_Crit("Failed to allocate %d floats for glar_ColorList_private",
1606                      N_points*4);
1607          return(NULL);
1608       }
1609       if (!SUMA_BlankColorListStruct(cl)) {
1610          SUMA_S_Err("Failed to fill with gray?!?");
1611          return(NULL);
1612       }
1613       /* Will need mixing in all likelihood, go ahead, why not */
1614       cl->Remix = YUP;
1615       ++cl->RemixID;
1616       return(cl->glar_ColorList_private);
1617    }
1618    return(NULL);
1619 }
1620 
1621 
1622 
1623 /*!
1624 \brief ans = SUMA_FillColorList (sv, so);
1625 Creates a colorlist structure for a certain displayable.
1626 
1627 \param sv (SUMA_SurfaceViewer *) pointer to surface viewer
1628 \param so (SUMA_SurfaceObject *) pointer to surface object
1629 
1630 Remix flag is set to YUP since this function is called when DOs are
1631 being registered with a viewer and a remix is highly likely.
1632 
1633 \return ans YUP/NOPE
1634 
1635 */
SUMA_FillColorList(SUMA_SurfaceViewer * sv,SUMA_ALL_DO * ADO)1636 SUMA_Boolean SUMA_FillColorList (SUMA_SurfaceViewer *sv, SUMA_ALL_DO *ADO)
1637 {
1638    static char FuncName[]={"SUMA_FillColorList"};
1639    int i, N_points;
1640    char *idcode=NULL;
1641    SUMA_COLORLIST_STRUCT *clinh=NULL;
1642    SUMA_Boolean LocalHead = NOPE;
1643 
1644    SUMA_ENTRY;
1645 
1646    if (!sv) {
1647       SUMA_RETURN(NOPE);
1648    }
1649 
1650    switch(ADO->do_type) {
1651       case GRAPH_LINK_type: {
1652          SUMA_DSET *dset=SUMA_find_GLDO_Dset((SUMA_GraphLinkDO *)ADO);
1653          if (dset) SUMA_RETURN(SUMA_FillColorList(sv,(SUMA_ALL_DO *)dset));
1654          SUMA_S_Err("GLDO without dset!");
1655          SUMA_RETURN(NOPE);
1656       } break;
1657    }
1658 
1659 
1660    if (!SUMA_ADO_FillColorList_Params(ADO, &N_points, &idcode) ) {
1661       SUMA_S_Err("Failed to initialize variables");
1662       SUMA_RETURN(NOPE);
1663    }
1664 
1665    if (!idcode) {
1666       fprintf (SUMA_STDERR,"Error %s: idcode is NULL.\n", FuncName);
1667       SUMA_RETURN (NOPE);
1668    }
1669 
1670    /* make sure idcode is not in the list already */
1671    for (i=0; i<sv->N_ColList; ++i) {
1672       if (strcmp (idcode, sv->ColList[i]->idcode_str) == 0) {
1673          if (ADO->do_type != GDSET_type &&
1674              ADO->do_type != CDOM_type &&
1675              ADO->do_type != TRACT_type &&
1676              ADO->do_type != VO_type &&
1677              ADO->do_type != MASK_type
1678              ) {
1679             SUMA_S_Err("idcode is already in sv->ColList, \n"
1680                        "This is an error for a SurfaceObject, though I doubt\n"
1681                        "it is of serious consequence. Type is question is %s\n"
1682                        "for DO type %s\n", ADO_LABEL(ADO), ADO_TNAME(ADO));
1683             SUMA_RETURN (NOPE);
1684          } else {
1685             SUMA_LH("List for %s found",
1686                     SUMA_DO_dbg_info(idcode));
1687             /* No harm done, no need to get upset. */
1688             SUMA_RETURN(YUP);
1689          }
1690       }
1691    }
1692 
1693    SUMA_LH("Need to create or link to existing list."
1694            "will insert into position: %d", sv->N_ColList);
1695    if (sv->N_ColList >= SUMA_MAX_DISPLAYABLE_OBJECTS) {
1696       SUMA_SL_Crit("sv->N_ColList >= SUMA_MAX_DISPLAYABLE_OBJECTS");
1697       SUMA_RETURN (NOPE);
1698    }
1699 
1700    /* create the ColList struct */
1701    if (sv->ColList[sv->N_ColList]) {
1702       SUMA_S_Err("sv->ColorList[%d] is not NULL. Cannot reallocate.\n"
1703                   "not expecting this scenario at this stage", sv->N_ColList);
1704       SUMA_RETURN (NOPE);
1705    }
1706 
1707    /* Should we inherit? */
1708    clinh = NULL;
1709    switch (ADO->do_type) {
1710       case SO_type:
1711          /* Don't inherit, surfaces can have different colorings in
1712             different viewers */
1713          break;
1714       case VO_type: /* Those beasts cost a lot of memory, share with sv[0] */
1715          if (sv != SUMAg_SVv+0) {
1716             clinh = SUMA_GetColorListStruct (SUMAg_SVv, idcode);
1717          }
1718          break;
1719       default: /* For all others, make new copy, decide later whether
1720                   should inherit */
1721          break;
1722    }
1723    if (clinh) {
1724       SUMA_LH("Inheriting");
1725       sv->ColList[sv->N_ColList] =
1726                   (SUMA_COLORLIST_STRUCT*)SUMA_LinkToPointer((void *)clinh);
1727    } else {
1728       SUMA_LH("Recreating, N_points = %d", N_points);
1729       sv->ColList[sv->N_ColList] =
1730          (SUMA_COLORLIST_STRUCT *)SUMA_calloc(1, sizeof(SUMA_COLORLIST_STRUCT));
1731       sv->ColList[sv->N_ColList]->N_links = 0;
1732       memset(sv->ColList[sv->N_ColList]->per_sv_extra, PSV_NOTHING,
1733              SUMA_MAX_SURF_VIEWERS*sizeof(int));
1734       sv->ColList[sv->N_ColList]->owner_id[0] = '\0';
1735       sv->ColList[sv->N_ColList]->LinkedPtrType = SUMA_LINKED_COLORLIST_TYPE;
1736       sv->ColList[sv->N_ColList]->do_type = not_DO_type;
1737 
1738       sv->ColList[sv->N_ColList]->N_glar_ColorList = N_points*4;
1739 
1740       sv->ColList[sv->N_ColList]->idcode_str =
1741             (char *)SUMA_malloc((strlen(idcode)+1) * sizeof(char));
1742       if (!sv->ColList[sv->N_ColList]->idcode_str) {
1743          SUMA_S_Err("Failed to allocate for idcode_str.");
1744          SUMA_RETURN (NOPE);
1745       }
1746       sv->ColList[sv->N_ColList]->idcode_str =
1747          strcpy (sv->ColList[sv->N_ColList]->idcode_str, idcode);
1748 
1749       if (sv->Open) { /* ZSS: Feb 2014 */
1750          /* Only allocate if Viewer is open, otherwise
1751             don't allocate for float vector, let SUMA_GetColorList()
1752             take care of that */
1753          if (!SUMA_GetColorListPtr(sv->ColList[sv->N_ColList])) {
1754             SUMA_S_Err("Failed to allocate for glar_ColorList.");
1755             SUMA_RETURN (NOPE);
1756          }
1757       } else {
1758          sv->ColList[sv->N_ColList]->glar_ColorList_private = NULL;
1759       }
1760 
1761    }
1762 
1763    ++sv->N_ColList;
1764    SUMA_LH("N_ColList now %d, latest glar %p",
1765            sv->N_ColList, sv->ColList[sv->N_ColList-1]->glar_ColorList_private);
1766    SUMA_RETURN (YUP);
1767 }
1768 
1769 /*!
1770    glar_ColorList = SUMA_GetColorList (sv, DO_idstr);
1771    returns the pointer to the colorlist of the DO (or SO) with ID string DO_idstr
1772 
1773    \param sv (SUMA_SurfaceViewer *) pointer to surface viewer in question
1774    \param DO_idstr (char *) ID string of DO (usually a Surface Object)
1775    \return glar_ColorList (GLfloat *) a pointer to the array containing
1776       node colors
1777    \sa SUMA_GetColorListStruct, SUMA_GetColorListPtr
1778 */
SUMA_GetColorList(SUMA_SurfaceViewer * sv,char * DO_idstr)1779 GLfloat * SUMA_GetColorList (SUMA_SurfaceViewer *sv, char *DO_idstr)
1780 {
1781    static char FuncName[]={"SUMA_GetColorList"};
1782    int i;
1783    SUMA_Boolean Found = NOPE;
1784    SUMA_Boolean LocalHead = NOPE;
1785 
1786    SUMA_ENTRY_LH;
1787 
1788    if (!DO_idstr) {
1789       SUMA_S_Err("DO_idstr is NULL, this should not be.");
1790       SUMA_RETURN (NULL);
1791    }
1792 
1793    SUMA_LH("Looking for colorlist of %s",
1794             SUMA_DO_dbg_info(DO_idstr));
1795    /* find the culprit */
1796    Found = NOPE;
1797    i = 0;
1798    while (!Found && i < sv->N_ColList) {
1799       if (strcmp (DO_idstr, sv->ColList[i]->idcode_str) == 0) {
1800          Found = YUP;
1801          SUMA_RETURN (SUMA_GetColorListPtr(sv->ColList[i]));
1802       }
1803       ++i;
1804    }
1805 
1806    #if 0
1807    /* This should be deleted, but is left for Rick's joy at the moment.
1808    In the first pass, a CIFTI DO got its own colorplane and the colorization
1809    was done for the entire multi domain data set then to colorize a sub-domain
1810    the color list pointer was offset by the total number of data in sub-domains
1811    preceding it. That scheme however proved problematic when going back and forth
1812    between sub-domains and the whole dataset because datum indices in a
1813    multi-domain dataset are not unique.
1814    So this approach was scrapped in favor of dealing only with elementary
1815    datasets and domains */
1816    if (!Found) { /* Perhaps this DO is part of a CIFTI conglomorate */
1817       SUMA_CIFTI_DO *CO=NULL;
1818       int ksub;
1819       if ((CO = SUMA_find_CIFTI_subdom_container(DO_idstr, &ksub, NULL, 0))) {
1820       	 /* search again to find the pointer to the colorlist of the entire
1821 	 CIFTI domain */
1822 	 Found = NOPE;
1823       	 i = 0;
1824       	 while (!Found && i < sv->N_ColList) {
1825       	    if (strcmp (ADO_ID((SUMA_ALL_DO *)CO),
1826 	                sv->ColList[i]->idcode_str) == 0) {
1827                Found = YUP;
1828 	    } else ++i;
1829 	 }
1830          if (Found) {
1831 	    GLfloat *glc=NULL;
1832 	    SUMA_LH(
1833 	       "Found CIFTI container's colorlist for id %s, offset of 4*%d",
1834 	            DO_idstr, SUMA_CIFTI_SubDomFullOffset(CO, ksub));
1835 
1836 	    /* Now return the pointer offset to the sub-domain */
1837 	    glc = SUMA_GetColorListPtr(sv->ColList[i])+
1838 	             	      	       4*SUMA_CIFTI_SubDomFullOffset(CO, ksub);
1839 	    SUMA_RETURN(glc);
1840 	 } else {
1841 	    SUMA_LH("Found cobwebs");
1842 	 }
1843       }
1844    }
1845    #endif
1846 
1847    if (!Found) {
1848       SUMA_S_Err("DO_idstr %s was not found.\n", DO_idstr);
1849       SUMA_RETURN (NULL);
1850    }
1851 
1852    /* should not get to this point */
1853    SUMA_S_Err("Logic error. Should not get here.");
1854    SUMA_RETURN (NULL);
1855 
1856 }
1857 
1858 /* Return the color list structure for a particular object */
SUMA_GetColorListStruct(SUMA_SurfaceViewer * sv,char * DO_idstr)1859 SUMA_COLORLIST_STRUCT * SUMA_GetColorListStruct (SUMA_SurfaceViewer *sv,
1860                                                  char *DO_idstr)
1861 {
1862    static char FuncName[]={"SUMA_GetColorListStruct"};
1863    int i;
1864    SUMA_COLORLIST_STRUCT *cls = NULL;
1865    SUMA_Boolean Found = NOPE;
1866    SUMA_Boolean LocalHead = NOPE;
1867 
1868    SUMA_ENTRY_LH;
1869 
1870    if (!DO_idstr) {
1871       SUMA_S_Err("DO_idstr is NULL, this should not be.");
1872       SUMA_RETURN (NULL);
1873    }
1874 
1875    SUMA_LH("Looking for colorlist struct of %s",
1876             SUMA_DO_dbg_info(DO_idstr));
1877 
1878    /* find the culprit */
1879    Found = NOPE;
1880    i = 0;
1881    while (!Found && i < sv->N_ColList) {
1882       if (strcmp (DO_idstr, sv->ColList[i]->idcode_str) == 0) {
1883          Found = YUP;
1884          if (!SUMA_GetColorListPtr(sv->ColList[i])) {
1885             SUMA_RETURN(NULL);
1886          }
1887          SUMA_RETURN (sv->ColList[i]);
1888       }
1889       ++i;
1890    }
1891 
1892    if (!Found) {
1893       SUMA_S_Err("DO_idstr %s was not found.\n", DO_idstr);
1894       SUMA_RETURN (NULL);
1895    }
1896 
1897    /* should not get to this point */
1898    SUMA_S_Err("Logic error. Should not get here.");
1899    SUMA_RETURN (NULL);
1900 }
1901 
1902 /*!
1903    frees the Node Neighbor structure formed in SUMA_Build_FirstNeighb
1904 */
SUMA_Free_ColorList(SUMA_COLORLIST_STRUCT * cl)1905 SUMA_Boolean SUMA_Free_ColorList (SUMA_COLORLIST_STRUCT *cl)
1906 {
1907    static char FuncName[]={"SUMA_Free_ColorList"};
1908    SUMA_Boolean LocalHead = NOPE;
1909 
1910    SUMA_ENTRY;
1911 
1912    if (!cl) SUMA_RETURN(YUP);
1913 
1914    SUMA_LH("Entered to free colorlist of %s, (glar = %p)",
1915             SUMA_DO_dbg_info(cl->idcode_str), cl->glar_ColorList_private);
1916    if (LocalHead) SUMA_DUMP_TRACE("At Free ColorList");
1917 
1918    if (cl->N_links) {
1919       SUMA_LH("Just a link release");
1920       cl = (SUMA_COLORLIST_STRUCT *)SUMA_UnlinkFromPointer((void *)cl);
1921       SUMA_RETURN (YUP);
1922    }
1923 
1924    /* no more links, go for it */
1925    SUMA_LH("No more links freeing time");
1926    SUMA_ifree(cl->idcode_str);
1927    SUMA_ifree(cl->glar_ColorList_private);
1928    SUMA_ifree(cl);
1929    SUMA_RETURN (YUP);
1930 }
1931 
1932 /*!
1933 
1934 \brief Empty a colorlist structure
1935 
1936 ans = SUMA_EmptyColorList (sv, DO_idstr)
1937 
1938 \param sv (SUMA_SurfaceViewer *) pointer to surface viewer in question
1939 \param DO_idstr (char *) ID string of DO (usually a Surface Object) If you want to delete all
1940                         color lists, set this pointer to NULL
1941 \return ans (SUMA_Boolean) YUP/NOPE
1942 
1943 */
SUMA_EmptyColorList(SUMA_SurfaceViewer * sv,char * DO_idstr)1944 SUMA_Boolean SUMA_EmptyColorList (SUMA_SurfaceViewer *sv, char *DO_idstr)
1945 {
1946    static char FuncName[]={"SUMA_EmptyColorList"};
1947    int i;
1948    SUMA_Boolean Found = NOPE;
1949    SUMA_Boolean LocalHead = NOPE;
1950 
1951    SUMA_ENTRY;
1952 
1953    if (!sv->ColList) {
1954       SUMA_S_Err("sv->ColList is NULL, this should not be.");
1955       SUMA_RETURN (NOPE);
1956    }
1957 
1958    SUMA_LH("Emptying collist for sv %p, id %s", sv, DO_idstr);
1959    if (!DO_idstr) {
1960       /* empty them all */
1961       for (i=0; i < sv->N_ColList; ++i) {
1962          if (!SUMA_Free_ColorList(sv->ColList[i])) {
1963             SUMA_S_Err("Failed to free colorlist");
1964             SUMA_RETURN(NOPE);
1965          }
1966          sv->ColList[i]=NULL;
1967          sv->N_ColList = 0;
1968       }
1969 
1970    } else { /* just empty one */
1971       SUMA_LH("Emptying col list for %s", DO_idstr);
1972       Found = NOPE;
1973       i = 0;
1974       while (!Found && i < sv->N_ColList) {
1975          if (strcmp (DO_idstr, sv->ColList[i]->idcode_str) == 0) {
1976             Found = YUP;
1977             if (!SUMA_Free_ColorList(sv->ColList[i])) {
1978                SUMA_S_Err("Failed to free colorlist");
1979                SUMA_RETURN(NOPE);
1980             }
1981             /* copy the last in the list here */
1982             if (i < sv->N_ColList) {
1983                sv->ColList[i] = sv->ColList[sv->N_ColList-1];
1984 
1985                /* mark the last element as empty */
1986                sv->ColList[sv->N_ColList-1] = NULL;
1987                /* decrement the number of full elements in ColList */
1988                --sv->N_ColList;
1989             }
1990          }
1991          ++i;
1992       }
1993 
1994       if (!Found) {
1995          SUMA_S_Errv("item %s (%s) was not found, this should not be.\n",
1996                      DO_idstr, SUMA_DO_dbg_info(DO_idstr));
1997          SUMA_DUMP_TRACE("Whence the unfound");
1998          SUMA_RETURN (NOPE);
1999       }
2000    }
2001 
2002    SUMA_RETURN (YUP);
2003 }
2004 
2005 /*!
2006    ans = SUMA_SetShownLocalRemixFlag (SUMA_SurfaceViewer *sv)
2007    Set Remix flags for all surfaces in sv->RegistDO regardless of
2008    their relationship.
2009    This is useful when you change the settings for background color modulation
2010    and the like.
2011    \param sv (SUMA_SurfaceViewer *) pointer to surface viewer
2012    \return ans (SUMA_Boolean) YUP/NOPE
2013    \sa SUMA_SetRemixFlag
2014    \sa SUMA_SetLocalRemixFlag
2015 
2016 */
SUMA_SetShownLocalRemixFlag(SUMA_SurfaceViewer * sv)2017 SUMA_Boolean SUMA_SetShownLocalRemixFlag (SUMA_SurfaceViewer *sv)
2018 {
2019    static char FuncName[]={"SUMA_SetShownLocalRemixFlag"};
2020    int k;
2021 
2022    SUMA_ENTRY;
2023 
2024    for (k=0; k < sv->N_ColList; ++k) {
2025       sv->ColList[k]->Remix = YUP;
2026    }
2027 
2028    SUMA_RETURN (YUP);
2029 }
2030 
2031 /*!
2032    ans = SUMA_SetLocalRemixFlag (char *idcode_str, SUMA_SurfaceViewer *sv);
2033    Search RegistDO for sv and if a Surface in RegistDO is related
2034    to DO_idcode_str then its remix flag is set to yes.
2035 
2036    \param idcode_str (char *) IDcode of the surface that had its colorplanes
2037    modified
2038    \param sv (SUMA_SurfaceViewer *) pointer to surface viewer
2039    \return ans (SUMA_Boolean) YUP/NOPE
2040    \sa SUMA_SetRemixFlag
2041    \sa SUMA_SetShownLocalRemixFlag
2042 
2043    Will I ever use that one, not common to have related surfaces in one view ...?
2044 */
SUMA_SetLocalRemixFlag(char * DO_idcode_str,SUMA_SurfaceViewer * sv)2045 SUMA_Boolean SUMA_SetLocalRemixFlag (char *DO_idcode_str, SUMA_SurfaceViewer *sv)
2046 {
2047    static char FuncName[]={"SUMA_SetLocalRemixFlag"};
2048    SUMA_SurfaceObject *SO1 = NULL, *SO2 = NULL;
2049    int k, kk;
2050    void *pp = NULL;
2051    SUMA_DSET *dset=NULL;
2052    char *p2=NULL;
2053    SUMA_ALL_DO *ado2=NULL;
2054    SUMA_DO_Types tp;
2055    SUMA_Boolean Found = NOPE;
2056 
2057    SUMA_ENTRY;
2058 
2059    if (!DO_idcode_str || !sv) {
2060       SUMA_S_Err("NULL sv or DO_idcode_str. BAD");
2061       SUMA_RETURN (NOPE);
2062    }
2063 
2064    if (!(pp = SUMA_find_any_object(DO_idcode_str, &tp))) {
2065       SUMA_S_Errv("Bad id %s\n", DO_idcode_str);
2066       SUMA_RETURN (NOPE);
2067    }
2068 
2069    switch (tp) {
2070       case SO_type:
2071          SO1 = (SUMA_SurfaceObject *)pp;
2072          /* search for relatives in RegistDO */
2073          for (k=0; k < sv->N_DO; ++k) {
2074             ado2 = (SUMA_ALL_DO *)SUMAg_DOv[sv->RegistDO[k].dov_ind].OP;
2075             if (SUMA_isRelated((SUMA_ALL_DO *)SO1, ado2, 1)){
2076                                              /* kinship of da first order */
2077                SO2 = (SUMA_SurfaceObject *)SUMAg_DOv[sv->RegistDO[k].dov_ind].OP;
2078                /* related, set flag for remixing SO2 */
2079                kk = 0;
2080                Found = NOPE;
2081                while (!Found && kk < sv->N_ColList) {
2082                   if (strcmp(SO2->idcode_str,sv->ColList[kk]->idcode_str) == 0) {
2083                      Found = YUP;
2084                      sv->ColList[kk]->Remix = YUP;
2085                   }
2086                   ++kk;
2087                }
2088                if (!Found) {
2089                   SUMA_S_Err("Failed to find surface in ColList structs. BAD.");
2090                   SUMA_RETURN (NOPE);
2091                }
2092             }
2093          }
2094          break;
2095       case CDOM_type:
2096          SUMA_S_Err("Is this needed (perhaps once we have isotopic COs ? "
2097                     "If so then do it");
2098          SUMA_RETURN (NOPE);
2099          break;
2100       case GDSET_type:
2101          dset = (SUMA_DSET *)pp;
2102          for (k=0; k < sv->N_DO; ++k) {
2103             ado2 = (SUMA_ALL_DO *)SUMAg_DOv[sv->RegistDO[k].dov_ind].OP;
2104             if (SUMA_isRelated((SUMA_ALL_DO *)dset, ado2, 1)){
2105                kk = 0;
2106                Found = NOPE;
2107                while (!Found && kk < sv->N_ColList) {
2108                   if ((p2 = SUMA_ADO_idcode(ado2)) &&
2109                       !strcmp(p2, sv->ColList[kk]->idcode_str)) {
2110                      Found = YUP;
2111                      sv->ColList[kk]->Remix = YUP;
2112                   }
2113                   ++kk;
2114                }
2115                if (!Found) {
2116                   SUMA_S_Err("Failed to find DSET in ColList structs. BAD.");
2117                   SUMA_RETURN (NOPE);
2118                }
2119             }
2120          }
2121          break;
2122       default:
2123          SUMA_S_Errv("Type %d is not welcome here\n", tp);
2124          SUMA_RETURN(NOPE);
2125    }
2126 
2127    SUMA_RETURN (YUP);
2128 }
2129 
2130 
2131 
2132 /*!
2133    ans = SUMA_SetRemixFlag (char *idcode_str, SUMA_SurfaceViewer *SVv,
2134                             int N_SVv);
2135    Search RegistDO for each Surface Viewer and if a Surface in
2136    RegistDO is related to DO_idcode_str then its remix flag is set to yes.
2137 
2138    \param idcode_str (char *) IDcode of the surface that had its
2139                               colorplanes modified
2140    \param SVv (SUMA_SurfaceViewer *) vector of existing surface viewers
2141                                      (typically, that is SUMAg_SVv)
2142    \param N_SVv (int) number of surface viewers (typically that is N_SUMAg_SVv)
2143    \return ans (SUMA_Boolean) YUP/NOPE
2144    \sa SUMA_SetLocalRemixFlag
2145    \sa SUMA_SetShownLocalRemix
2146 
2147    DO NOT SET THE REMIXFLAG unless you have modified the colorplanes of a
2148    certain surface. This function will set a remix flags to all related surfaces
2149    that are being displayed in all viewers. You want to do this
2150    when one (or all) of the colorplanes is changed. Alternately, if you make
2151    changes that only affect the surface as is it shown in the viewer (change
2152    background modulation for example), you want to do the remixing
2153    for the concerned surface or surfaces only in that viewer and not in all
2154    viewers open. Perhaps I should write a function to set the remix flags
2155    for surfaces within the viewer only. Something like SUMA_SetLocalRemixFlag or
2156    SUMA_SetShownLocalRemix.
2157 
2158 */
SUMA_SetRemixFlag(char * DO_idcode_str,SUMA_SurfaceViewer * SVv,int N_SVv)2159 SUMA_Boolean SUMA_SetRemixFlag (char *DO_idcode_str, SUMA_SurfaceViewer *SVv,
2160                                 int N_SVv)
2161 {
2162    static char FuncName[]={"SUMA_SetRemixFlag"};
2163    SUMA_SurfaceViewer *sv;
2164    int i, k, kk;
2165    void *pp=NULL;
2166    SUMA_DO_Types tp;
2167    SUMA_ALL_DO*ado2;
2168    char *p2=NULL;
2169    SUMA_Boolean Found = NOPE;
2170    SUMA_Boolean LocalHead = NOPE;
2171 
2172    SUMA_ENTRY;
2173 
2174    if (!DO_idcode_str || !SVv) {
2175       fprintf (SUMA_STDERR,
2176                "Error %s: NULL SVv or DO_idcode_str. BAD\n", FuncName);
2177       SUMA_RETURN (NOPE);
2178    }
2179 
2180    SUMA_LH("Look for any object");
2181    SUMA_LHv("        id %s\n", DO_idcode_str);
2182    if (!(pp = SUMA_find_any_object(DO_idcode_str, &tp))) {
2183       SUMA_S_Errv("Bad id %s\n", DO_idcode_str);
2184       SUMA_RETURN (NOPE);
2185    }
2186    SUMA_LH("Switching...");
2187    switch (tp) {
2188       case SO_type: {
2189          SUMA_SurfaceObject *SO1 = NULL, *SO2 = NULL;
2190          SO1 = (SUMA_SurfaceObject *)pp;
2191          /* search all viewers */
2192          for (i=0; i < N_SVv; ++i) {
2193             if (LocalHead)
2194                fprintf (SUMA_STDERR,"%s: Searching viewer %d.\n", FuncName, i);
2195             sv = &(SVv[i]);
2196             /* search for relatives in RegistDO */
2197             for (k=0; k < sv->N_DO; ++k) {
2198                if (SUMA_isSO(SUMAg_DOv[sv->RegistDO[k].dov_ind])) {
2199                   SO2 = (SUMA_SurfaceObject *)
2200                            SUMAg_DOv[sv->RegistDO[k].dov_ind].OP;
2201                   if (SUMA_isRelated_SO(SO1, SO2, 1)) {
2202                      /* only 1st order kinship allowed */
2203                      /* related, set flag for remixing SO2 */
2204                      kk = 0;
2205                      Found = NOPE;
2206                      while (!Found && kk < sv->N_ColList) {
2207                         if (strcmp (SO2->idcode_str,
2208                                     sv->ColList[kk]->idcode_str) == 0) {
2209                            Found = YUP;
2210                            SUMA_LHv("Setting remix for %d\n", kk);
2211                            sv->ColList[kk]->Remix = YUP;
2212                         }
2213                         ++kk;
2214                      }
2215                      if (!Found) {
2216                         SUMA_S_Err("Failed to find surface in ColList structs.");
2217                         SUMA_RETURN (NOPE);
2218                      }
2219                   }
2220                }
2221             }
2222          }
2223          break; }
2224       case VO_type:
2225       case CDOM_type:
2226       case MASK_type:
2227       case TRACT_type: {
2228          SUMA_ALL_DO *ADO = (SUMA_ALL_DO*)pp;
2229          /* search all viewers */
2230          for (i=0; i < N_SVv; ++i) {
2231             if (LocalHead)
2232                fprintf (SUMA_STDERR,"%s: Searching viewer %d.\n", FuncName, i);
2233             sv = &(SVv[i]);
2234             /* search for relatives in RegistDO */
2235             for (k=0; k < sv->N_DO; ++k) {
2236                if (iDO_isTDO(sv->RegistDO[k].dov_ind) ||
2237                    iDO_isVO(sv->RegistDO[k].dov_ind)) {
2238                   ado2 = (SUMA_ALL_DO *)SUMAg_DOv[sv->RegistDO[k].dov_ind].OP;
2239                   if (SUMA_isRelated(ADO, ado2, 1)) {
2240                      SUMA_LHv("%s RELATED to %s\n",
2241                               SUMA_ADO_Label(ADO),
2242                               SUMA_ADO_Label(ado2));
2243                      kk = 0;
2244                      Found = NOPE;
2245                      while (!Found && kk < sv->N_ColList) {
2246                         p2=SUMA_ADO_idcode(ado2);
2247 
2248                         if ( p2 && !strcmp(p2, sv->ColList[kk]->idcode_str)) {
2249                            Found = YUP;
2250                            sv->ColList[kk]->Remix = YUP;
2251                         }
2252                         ++kk;
2253                      }
2254                      if (!Found) {
2255                         SUMA_S_Err("No relative in ColList structs. BAD.");
2256                         SUMA_RETURN (NOPE);
2257                      }
2258                   } else {
2259                      SUMA_LHv("%s Not related to %s\n",
2260                               SUMA_ADO_Label(ADO),
2261                               SUMA_ADO_Label(ado2));
2262                   }
2263                }
2264             }
2265          }
2266          break; }
2267       case GDSET_type: {
2268          SUMA_DSET *dset = (SUMA_DSET *)pp;
2269 
2270          if (!dset) {
2271             SUMA_S_Errv("Failed to find dset for dset %p, %s\n",
2272                         pp, SUMA_ADO_Label((SUMA_ALL_DO *)pp));
2273             SUMA_RETURN(NOPE);
2274          }
2275          /* search all viewers */
2276          for (i=0; i < N_SVv; ++i) {
2277             if (LocalHead)
2278                fprintf (SUMA_STDERR,"%s: Searching viewer %d.\n", FuncName, i);
2279             sv = &(SVv[i]);
2280             /* search for relatives in RegistDO */
2281             for (k=0; k < sv->N_DO; ++k) {
2282                if (iDO_isGLDO(sv->RegistDO[k].dov_ind)) {
2283                   ado2 = (SUMA_ALL_DO *)SUMAg_DOv[sv->RegistDO[k].dov_ind].OP;
2284                   if (SUMA_isRelated((SUMA_ALL_DO *)dset, ado2, 1)) {
2285                      SUMA_LHv("%s RELATED to %s\n",
2286                               SUMA_ADO_Label((SUMA_ALL_DO *)dset),
2287                               SUMA_ADO_Label(ado2));
2288                      kk = 0;
2289                      Found = NOPE;
2290                      while (!Found && kk < sv->N_ColList) {
2291                         switch (ado2->do_type) {
2292                            case GRAPH_LINK_type:
2293                               /* The idcode in ColList is that
2294                                  of the dataset for GLDO */
2295                               p2 = SDSET_ID(SUMA_find_GLDO_Dset(
2296                                                 (SUMA_GraphLinkDO *)ado2));
2297                               break;
2298                            default:
2299                               p2=SUMA_ADO_idcode(ado2);
2300                               break;
2301                         }
2302                         if ( p2 && !strcmp(p2, sv->ColList[kk]->idcode_str)) {
2303                            Found = YUP;
2304                            sv->ColList[kk]->Remix = YUP;
2305                         }
2306                         ++kk;
2307                      }
2308                      if (!Found) {
2309                         SUMA_S_Err("No relative in ColList structs. BAD.");
2310                         SUMA_RETURN (NOPE);
2311                      }
2312                   } else {
2313                      SUMA_LHv("%s Not related to %s\n",
2314                               SUMA_ADO_Label((SUMA_ALL_DO *)dset),
2315                               SUMA_ADO_Label(ado2));
2316                   }
2317                }
2318             }
2319          }
2320          break; }
2321       case GRAPH_LINK_type: {
2322          SUMA_GraphLinkDO *gldo = (SUMA_GraphLinkDO *)pp;
2323          SUMA_DSET *dset = SUMA_find_GLDO_Dset(gldo);
2324          SUMA_S_Warn("So do I need to call function with dset for you?");
2325          SUMA_RETURN (YUP);
2326          break; }
2327       default:
2328          SUMA_S_Errv("Type %d is not welcome here\n", tp);
2329          SUMA_RETURN(NOPE);
2330    }
2331 
2332    SUMA_RETURN (YUP);
2333 }
2334 
2335 /*!
2336    \brief sets remix flags for all color lists in viewers specified in SVv
2337    Use this function whenever global color changes occur
2338 
2339    \sa SUMA_SetRemixFlag for detailed help
2340 
2341 */
SUMA_SetAllRemixFlag(SUMA_SurfaceViewer * SVv,int N_SVv)2342 SUMA_Boolean SUMA_SetAllRemixFlag (SUMA_SurfaceViewer *SVv, int N_SVv)
2343 {
2344    static char FuncName[]={"SUMA_SetAllRemixFlag"};
2345    SUMA_SurfaceViewer *sv;
2346    int i, kk;
2347    SUMA_Boolean LocalHead = NOPE;
2348 
2349    SUMA_ENTRY;
2350 
2351    if (!SVv) {
2352       fprintf (SUMA_STDERR,"Error %s: NULL SVv . BAD\n", FuncName);
2353       SUMA_RETURN (NOPE);
2354    }
2355 
2356    /* search all viewers */
2357    for (i=0; i < N_SVv; ++i) {
2358       if (LocalHead)
2359          fprintf (SUMA_STDERR,"%s: Searching viewer %d.\n", FuncName, i);
2360       sv = &(SVv[i]);
2361       for (kk = 0; kk < sv->N_ColList; ++kk) sv->ColList[kk]->Remix = YUP;
2362    }
2363 
2364    SUMA_RETURN (YUP);
2365 }
2366 
SUMA_SetGLHome(SUMA_SurfaceViewer * sv)2367 SUMA_Boolean SUMA_SetGLHome(SUMA_SurfaceViewer *sv)
2368 {
2369    static char FuncName[]={"SUMA_SetGLHome"};
2370 
2371    SUMA_ENTRY;
2372    if (!sv) SUMA_RETURN(NOPE);
2373    SUMA_SET_AS_NEEDED_2D_VIEW_ANGLE(sv);
2374    sv->GVS[sv->StdView].translateVec[0]=0;
2375    sv->GVS[sv->StdView].translateVec[1]=0;
2376    glMatrixMode(GL_PROJECTION);
2377 
2378    sv->GVS[sv->StdView].ViewFrom[0] =
2379       sv->GVS[sv->StdView].ViewFromOrig[0];
2380    sv->GVS[sv->StdView].ViewFrom[1] =
2381       sv->GVS[sv->StdView].ViewFromOrig[1];
2382    sv->GVS[sv->StdView].ViewFrom[2] =
2383       sv->GVS[sv->StdView].ViewFromOrig[2];
2384    sv->GVS[sv->StdView].ViewCenter[0] =
2385       sv->GVS[sv->StdView].ViewCenterOrig[0];
2386    sv->GVS[sv->StdView].ViewCenter[1] =
2387       sv->GVS[sv->StdView].ViewCenterOrig[1];
2388    sv->GVS[sv->StdView].ViewCenter[2] =
2389       sv->GVS[sv->StdView].ViewCenterOrig[2];
2390 
2391    glMatrixMode(GL_MODELVIEW);
2392    glLoadIdentity();
2393    gluLookAt ( sv->GVS[sv->StdView].ViewFrom[0],
2394                sv->GVS[sv->StdView].ViewFrom[1],
2395                sv->GVS[sv->StdView].ViewFrom[2],
2396                sv->GVS[sv->StdView].ViewCenter[0],
2397                sv->GVS[sv->StdView].ViewCenter[1],
2398                sv->GVS[sv->StdView].ViewCenter[2],
2399                sv->GVS[sv->StdView].ViewCamUp[0],
2400                sv->GVS[sv->StdView].ViewCamUp[1],
2401                sv->GVS[sv->StdView].ViewCamUp[2]);
2402    SUMA_RETURN(YUP);
2403 }
2404 
SUMA_Fetch_VisX_Element(char * label,DList * dl)2405 DListElmt *SUMA_Fetch_VisX_Element(char *label, DList *dl)
2406 {
2407    static char FuncName[]={"SUMA_Fetch_VisX_Element"};
2408    DListElmt *el=NULL, *ref=NULL;
2409    SUMA_VIS_XFORM_DATUM *uu=NULL;
2410 
2411    SUMA_ENTRY;
2412 
2413    if (!label || !dl) {
2414      SUMA_S_Err("NULL label or NULL list");
2415      SUMA_RETURN(ref);
2416    }
2417    if (!dlist_size(dl)) SUMA_RETURN(ref);
2418 
2419    el = NULL;
2420    do {
2421       if (!el) el = dlist_head(dl);
2422       else el = dlist_next(el);
2423       uu = (SUMA_VIS_XFORM_DATUM *)el->data;
2424       if (uu && !strcmp(uu->label, label)) {
2425          ref = el;
2426       }
2427    } while(!ref && el != dlist_tail(dl));
2428    SUMA_RETURN(ref);
2429 }
2430 
SUMA_Fetch_VisX_Datum(char * label,DList * dl,SUMA_VISX_ADD_POSITIONS add,char * ref_pos_label)2431 SUMA_VIS_XFORM_DATUM *SUMA_Fetch_VisX_Datum (char *label, DList *dl,
2432                              SUMA_VISX_ADD_POSITIONS add, char *ref_pos_label)
2433 {
2434    static char FuncName[]={"SUMA_Fetch_VisX_Datum"};
2435    SUMA_VIS_XFORM_DATUM *xx=NULL, *uu=NULL;
2436    DListElmt *el=NULL, *ref=NULL;
2437 
2438    SUMA_ENTRY;
2439 
2440    if (!label || !dl) {
2441      SUMA_S_Err("NULL label or NULL list");
2442      SUMA_RETURN(xx);
2443    }
2444    if (!dlist_size(dl)) {
2445       if (add != ADD_NOT) {
2446          xx = SUMA_NewVisXdatum(label);
2447          dlist_ins_next(dl, dlist_tail(dl), xx);
2448       } else {
2449          SUMA_RETURN(xx);
2450       }
2451    } else {
2452       if ((el=SUMA_Fetch_VisX_Element(label, dl))) {
2453          if ((xx = (SUMA_VIS_XFORM_DATUM *)el->data)) {
2454             SUMA_RETURN(xx);
2455          }
2456       }
2457 
2458       /* should we add, and if so, where ? */
2459       if (add != ADD_NOT) {
2460          if (ref_pos_label) {
2461             ref = SUMA_Fetch_VisX_Element(ref_pos_label, dl);
2462          }
2463          xx = SUMA_NewVisXdatum(label);
2464          if (ref) {
2465             switch (add) {
2466                case ADD_AFTER:
2467                   dlist_ins_next(dl, ref, xx);
2468                   break;
2469                case ADD_BEFORE:
2470                   dlist_ins_prev(dl, ref, xx);
2471                   break;
2472                default:
2473                   SUMA_S_Errv("Bad add=%d\n", add);
2474                   break;
2475             }
2476          } else {
2477             switch (add) {
2478                case ADD_AFTER:
2479                   dlist_ins_next(dl, dlist_tail(dl), xx);
2480                   break;
2481                case ADD_BEFORE:
2482                   dlist_ins_prev(dl, dlist_head(dl), xx);
2483                   break;
2484                default:
2485                   SUMA_S_Errv("Bad add=%d\n", add);
2486                   break;
2487             }
2488          }
2489       }
2490       SUMA_RETURN(xx);
2491    }
2492 
2493    /* should not get here...*/
2494    SUMA_RETURN(xx);
2495 }
2496 
SUMA_Apply_VisX_Chain(float * xyz,int N,DList * dl,int inv)2497 SUMA_Boolean SUMA_Apply_VisX_Chain(float *xyz, int N, DList *dl, int inv)
2498 {
2499    static char FuncName[]={"SUMA_Apply_VisX_Chain"};
2500    SUMA_VIS_XFORM_DATUM *xx=NULL;
2501    DListElmt *el=NULL;
2502    int ii, iii, N3;
2503    SUMA_Boolean LocalHead = NOPE;
2504 
2505    SUMA_ENTRY;
2506 
2507    if (!dl || !xyz) {
2508       SUMA_S_Errv("No list (%p) or coords (%p)\n", dl, xyz);
2509       SUMA_RETURN(NOPE);
2510    }
2511    if (!dlist_size(dl)) {
2512       SUMA_S_Err("Empty list");
2513       SUMA_RETURN(NOPE);
2514    }
2515 
2516    N3 = 3*N;
2517    if (!inv) {
2518       do {
2519          if (!el) el = dlist_head(dl);
2520          else el = dlist_next(el);
2521          xx = (SUMA_VIS_XFORM_DATUM *)el->data;
2522          switch (xx->XformType) {
2523             case ID:
2524                break;
2525             case SHIFT:
2526                SUMA_LHv("Applying shift %s\n", xx->label);
2527                for (ii=0, iii=0; ii<N; ++ii) {
2528                   xyz[iii] += xx->Xform[0][3]; ++iii;
2529                   xyz[iii] += xx->Xform[1][3]; ++iii;
2530                   xyz[iii] += xx->Xform[2][3]; ++iii;
2531                }
2532                break;
2533             case AFFINE:
2534                SUMA_LHv("Applying affine %s\n", xx->label);
2535                SUMA_Apply_Coord_xform( xyz,N,3,
2536                                     xx->Xform, 0, NULL);
2537                break;
2538             case DISP:
2539                SUMA_LHv("Applying disp (%p) %s\n", xx->dxyz, xx->label);
2540                if (!xx->dxyz) SUMA_RETURN(NOPE);
2541                for (iii=0; iii<N3; ++iii) {
2542                   xyz[iii] += xx->dxyz[iii];
2543                }
2544                break;
2545             default:
2546                SUMA_RETURN(NOPE);
2547                break;
2548          }
2549       } while (el != dlist_tail(dl)) ;
2550    } else {
2551       do {
2552          if (!el) el = dlist_tail(dl);
2553          else el = dlist_prev(el);
2554          xx = (SUMA_VIS_XFORM_DATUM *)el->data;
2555          switch (xx->XformType) {
2556             case ID:
2557                break;
2558             case SHIFT:
2559                SUMA_LHv("Removing shift %s\n", xx->label);
2560                for (ii=0, iii=0; ii<N; ++ii) {
2561                   xyz[iii] -= xx->Xform[0][3]; ++iii;
2562                   xyz[iii] -= xx->Xform[1][3]; ++iii;
2563                   xyz[iii] -= xx->Xform[2][3]; ++iii;
2564                }
2565                break;
2566             case AFFINE:
2567                SUMA_LHv("Removing affine %s\n", xx->label);
2568                SUMA_Apply_Coord_xform( xyz,N,3,
2569                                     xx->Xform, 1, NULL);
2570                break;
2571             case DISP:
2572                SUMA_LHv("Removing displacement (%p) %s\n", xx->dxyz, xx->label);
2573                if (!xx->dxyz) SUMA_RETURN(NOPE);
2574                for (iii=0; iii<N3; ++iii) {
2575                   xyz[iii] -= xx->dxyz[iii];
2576                }
2577                break;
2578             default:
2579                SUMA_RETURN(NOPE);
2580                break;
2581          }
2582       } while (el != dlist_head(dl)) ;
2583    }
2584 
2585    SUMA_RETURN(YUP);
2586 }
2587 
2588 /*!
2589    Update view points of all viewers with this ADO registered
2590 */
SUMA_UpdateViewPoint_RegisteredADO(SUMA_ALL_DO * ado,byte keepzoom)2591 SUMA_Boolean SUMA_UpdateViewPoint_RegisteredADO(SUMA_ALL_DO *ado, byte keepzoom)
2592 {
2593    static char FuncName[]={"SUMA_UpdateViewPoint_RegisteredADO"};
2594    int ii;
2595    SUMA_SurfaceViewer *sv=NULL;
2596 
2597    SUMA_ENTRY;
2598 
2599    if (!ado) SUMA_RETURN(NOPE);
2600    for (ii=0; ii<SUMAg_N_SVv; ++ii) {
2601       sv = &(SUMAg_SVv[ii]);
2602       if (SUMA_ADO_isRegistered(sv, ado)) {
2603          SUMA_UpdateViewPoint(sv, SUMAg_DOv, SUMAg_N_DOv, keepzoom);
2604          SUMA_SetGLHome(sv);
2605       }
2606    }
2607 
2608    SUMA_RETURN(YUP);
2609 }
2610 
2611 
2612 /*!
2613 Updates the View Center and view from of SV based on the contents of RegistDO
2614 */
SUMA_UpdateViewPoint(SUMA_SurfaceViewer * SV,SUMA_DO * dov,int N_dov,byte KeepZoom)2615 SUMA_Boolean SUMA_UpdateViewPoint ( SUMA_SurfaceViewer *SV,
2616                                     SUMA_DO *dov, int N_dov, byte KeepZoom)
2617 {
2618    static char FuncName[]={"SUMA_UpdateViewPoint"};
2619    int i, do_id, TotWeight;
2620    float NewCenter[3], UsedCenter[3], *xyzr, odelta=0.0, oviewd=0.0;
2621    SUMA_SurfaceObject *so_op;
2622    SUMA_DSET *dset=NULL;
2623    SUMA_Boolean LocalHead = NOPE;
2624 
2625    SUMA_ENTRY;
2626 
2627    NewCenter[0] = 0.0;
2628    NewCenter[1] = 0.0;
2629    NewCenter[2] = 0.0;
2630    TotWeight = 0;
2631 
2632    i = 0;
2633    while (i < SV->N_DO) {
2634       do_id = SV->RegistDO[i].dov_ind;
2635       switch (dov[do_id].ObjectType) {
2636          case SO_type:
2637             so_op = (SUMA_SurfaceObject *)dov[do_id].OP;
2638             if (SV->UsePatchDims) {
2639                SUMA_LH("Using patch center");
2640                SUMA_COPY_VEC(so_op->patchCenter, UsedCenter, 3, float, float);
2641             } else {
2642                SUMA_LH("Using center of mass or sphere's center.");
2643                if (!SUMA_IS_GEOM_SYMM(so_op->isSphere) || so_op->VisX.Applied) {
2644                   SUMA_COPY_VEC(so_op->Center, UsedCenter, 3, float, float);
2645                } else {
2646                   SUMA_COPY_VEC( so_op->SphereCenter, UsedCenter, 3,
2647                                  float, float);
2648                }
2649             }
2650             if (so_op->VisX.Applied) {
2651                if (!SUMA_Apply_VisX_Chain( UsedCenter,1,so_op->VisX.Xchain, 0)) {
2652                   SUMA_S_Warn("Sir! Have you no decency left?");
2653                }
2654             }
2655             if (so_op->ViewCenterWeight) {
2656                NewCenter[0] += so_op->ViewCenterWeight*UsedCenter[0];
2657                NewCenter[1] += so_op->ViewCenterWeight*UsedCenter[1];
2658                NewCenter[2] += so_op->ViewCenterWeight*UsedCenter[2];
2659                TotWeight += so_op->ViewCenterWeight;
2660             }
2661             break;
2662          case GRAPH_LINK_type:
2663             if(!(dset=SUMA_find_GLDO_Dset((SUMA_GraphLinkDO *)(dov[do_id].OP)))){
2664                SUMA_S_Err("Gildaaaaaaaaaaaaaaaaaa");
2665                SUMA_RETURN(NOPE);
2666             }
2667 
2668             if (!SUMA_IS_REAL_VARIANT(iDO_variant(do_id))) break;
2669             xyzr = SUMA_GDSET_XYZ_Center(dset, iDO_variant(do_id), NULL);
2670             NewCenter[0] += GDSET_N_SEG_POINTS(dset)*xyzr[0];
2671             NewCenter[1] += GDSET_N_SEG_POINTS(dset)*xyzr[1];
2672             NewCenter[2] += GDSET_N_SEG_POINTS(dset)*xyzr[2];
2673             TotWeight += GDSET_N_SEG_POINTS(dset);
2674             break;
2675          case TRACT_type: {
2676             SUMA_TractDO *TDO=(SUMA_TractDO *)dov[do_id].OP;
2677             int N_tracts;
2678             if (TDO_HAS_GRID(TDO)) {
2679                xyzr = SUMA_TDO_Grid_Center(TDO, NULL);
2680             } else {
2681                xyzr = SUMA_TDO_Points_Center(TDO, NULL);
2682             }
2683             N_tracts = SUMA_TDO_N_tracts(TDO);
2684             NewCenter[0] += N_tracts*xyzr[0];
2685             NewCenter[1] += N_tracts*xyzr[1];
2686             NewCenter[2] += N_tracts*xyzr[2];
2687             TotWeight += N_tracts;
2688             break; }
2689          case MASK_type: {
2690             int N_pts;
2691             SUMA_MaskDO *MDO=(SUMA_MaskDO *)dov[do_id].OP;
2692             xyzr = SUMA_MDO_Center(MDO, NULL);
2693             N_pts = SUMA_ADO_N_Datum((SUMA_ALL_DO*)MDO);
2694             NewCenter[0] += N_pts*xyzr[0];
2695             NewCenter[1] += N_pts*xyzr[1];
2696             NewCenter[2] += N_pts*xyzr[2];
2697             TotWeight += N_pts;
2698             break; }
2699          case VO_type: {
2700             SUMA_VolumeObject *VO=(SUMA_VolumeObject *)dov[do_id].OP;
2701             xyzr = SUMA_VO_Grid_Center(VO, NULL);
2702             NewCenter[0] += VO_NVOX(VO)*xyzr[0];
2703             NewCenter[1] += VO_NVOX(VO)*xyzr[1];
2704             NewCenter[2] += VO_NVOX(VO)*xyzr[2];
2705             TotWeight += VO_NVOX(VO);
2706             break; }
2707          default:
2708             SUMA_LHv("Ignoring object %s, variant %s\n",
2709                      iDO_label(do_id), iDO_variant(do_id));
2710             break;
2711 
2712       }
2713       ++i;
2714    }
2715 
2716    odelta = SV->GVS[SV->StdView].ViewFrom[2] -SV->GVS[SV->StdView].ViewCenter[2];
2717    oviewd = SV->GVS[SV->StdView].ViewDistance;
2718    if (TotWeight) {
2719       SV->GVS[SV->StdView].ViewCenter[0] = NewCenter[0]/(float)TotWeight;
2720       SV->GVS[SV->StdView].ViewCenter[1] = NewCenter[1]/(float)TotWeight;
2721       SV->GVS[SV->StdView].ViewCenter[2] = NewCenter[2]/(float)TotWeight;
2722       SV->GVS[SV->StdView].ViewFrom[0] = SV->GVS[SV->StdView].ViewCenter[0];
2723       SV->GVS[SV->StdView].ViewFrom[1] = SV->GVS[SV->StdView].ViewCenter[1];
2724       if (!KeepZoom) {
2725          SV->GVS[SV->StdView].ViewFrom[2] =
2726             SV->GVS[SV->StdView].ViewCenter[2]+
2727             SUMA_DEFAULT_VIEW_FROM/SV->GVS[SV->StdView].DimSclFac;
2728          SV->GVS[SV->StdView].ViewDistance =
2729             SUMA_DEFAULT_VIEW_FROM/SV->GVS[SV->StdView].DimSclFac;
2730       } else {
2731          SV->GVS[SV->StdView].ViewFrom[2] =
2732             SV->GVS[SV->StdView].ViewCenter[2]+odelta;
2733          SV->GVS[SV->StdView].ViewDistance = oviewd;
2734       }
2735    } else {/* default back to o.o, o.o, o.o */
2736       SV->GVS[SV->StdView].ViewCenter[0] =
2737       SV->GVS[SV->StdView].ViewCenter[1] =
2738       SV->GVS[SV->StdView].ViewCenter[2] = 0.0;
2739       SV->GVS[SV->StdView].ViewFrom[0] =
2740       SV->GVS[SV->StdView].ViewFrom[1] = 0.0;
2741       if (!KeepZoom) {
2742          SV->GVS[SV->StdView].ViewFrom[2] =
2743                          SUMA_DEFAULT_VIEW_FROM/SV->GVS[SV->StdView].DimSclFac;
2744          SV->GVS[SV->StdView].ViewDistance =
2745                          SUMA_DEFAULT_VIEW_FROM/SV->GVS[SV->StdView].DimSclFac;
2746       }
2747    }
2748 
2749       /* Store that info in case subjects change things */
2750       SV->GVS[SV->StdView].ViewCenterOrig[0] =
2751                               SV->GVS[SV->StdView].ViewCenter[0];
2752       SV->GVS[SV->StdView].ViewCenterOrig[1] =
2753                               SV->GVS[SV->StdView].ViewCenter[1];
2754       SV->GVS[SV->StdView].ViewCenterOrig[2] =
2755                               SV->GVS[SV->StdView].ViewCenter[2];
2756       SV->GVS[SV->StdView].ViewFromOrig[0] = SV->GVS[SV->StdView].ViewFrom[0];
2757       SV->GVS[SV->StdView].ViewFromOrig[1] = SV->GVS[SV->StdView].ViewFrom[1];
2758       SV->GVS[SV->StdView].ViewFromOrig[2] = SV->GVS[SV->StdView].ViewFrom[2];
2759 
2760    SUMA_RETURN (YUP);
2761 }
2762 
2763 /*!
2764 Updates the Rotation Center of SV based on the contents of RegistDO
2765 */
SUMA_UpdateRotaCenter(SUMA_SurfaceViewer * SV,SUMA_DO * dov,int N_dov)2766 SUMA_Boolean SUMA_UpdateRotaCenter (
2767                SUMA_SurfaceViewer *SV, SUMA_DO *dov, int N_dov)
2768 {
2769    static char FuncName[]={"SUMA_UpdateRotaCenter"};
2770    int i, do_id, TotWeight;
2771    float NewCenter[3], UsedCenter[3];
2772    float *xyzr;
2773    SUMA_SurfaceObject *so_op;
2774    SUMA_DSET *dset=NULL;
2775    SUMA_Boolean LocalHead = NOPE;
2776 
2777    SUMA_ENTRY;
2778 
2779    NewCenter[0] = 0.0;
2780    NewCenter[1] = 0.0;
2781    NewCenter[2] = 0.0;
2782    TotWeight = 0;
2783 
2784 
2785    i = 0;
2786    while (i < SV->N_DO) {
2787       do_id = SV->RegistDO[i].dov_ind;
2788       switch (dov[do_id].ObjectType) {
2789          case SO_type:
2790             so_op = (SUMA_SurfaceObject *)dov[do_id].OP;
2791             if (SV->UsePatchDims) {
2792                SUMA_COPY_VEC(so_op->patchCenter, UsedCenter, 3, float, float);
2793             } else {
2794                if (SUMA_IS_GEOM_SYMM(so_op->isSphere) && !so_op->VisX.Applied) {
2795                   SUMA_COPY_VEC(so_op->SphereCenter, UsedCenter,
2796                                  3, float, float);
2797                } else {
2798                   SUMA_COPY_VEC(so_op->Center, UsedCenter, 3, float, float);
2799                }
2800             }
2801             SUMA_LHv("Used Center (%s) Pre Xform: [%f %f %f]\n",
2802                      so_op->Label, UsedCenter[0], UsedCenter[1], UsedCenter[2]);
2803             if (so_op->VisX.Applied) {
2804                if (!SUMA_Apply_VisX_Chain( UsedCenter,1,so_op->VisX.Xchain, 0)) {
2805                   SUMA_S_Warn("Oh please don't break my heart.");
2806                }
2807             }
2808             SUMA_LHv("Used Center (%s) Post Xform: [%f %f %f]\n",
2809                      so_op->Label, UsedCenter[0], UsedCenter[1], UsedCenter[2]);
2810             if (so_op->RotationWeight) {
2811                NewCenter[0] += so_op->RotationWeight*UsedCenter[0];
2812                NewCenter[1] += so_op->RotationWeight*UsedCenter[1];
2813                NewCenter[2] += so_op->RotationWeight*UsedCenter[2];
2814                TotWeight += so_op->RotationWeight;
2815             }
2816             break;
2817          case GRAPH_LINK_type:
2818             if(!(dset=SUMA_find_GLDO_Dset((SUMA_GraphLinkDO *)(dov[do_id].OP)))){
2819                SUMA_S_Err("Gildaaaaaaaaaaaaaaaaaa");
2820                SUMA_RETURN(NOPE);
2821             }
2822             if (!SUMA_IS_REAL_VARIANT(iDO_variant(do_id))) break;
2823             xyzr = SUMA_GDSET_XYZ_Center(dset, iDO_variant(do_id), NULL);
2824             NewCenter[0] += GDSET_N_SEG_POINTS(dset)*xyzr[0];
2825             NewCenter[1] += GDSET_N_SEG_POINTS(dset)*xyzr[1];
2826             NewCenter[2] += GDSET_N_SEG_POINTS(dset)*xyzr[2];
2827             TotWeight += GDSET_N_SEG_POINTS(dset);
2828             break;
2829          case MASK_type: {
2830             int N_pts;
2831             SUMA_MaskDO *MDO=(SUMA_MaskDO *)dov[do_id].OP;
2832             xyzr = SUMA_MDO_Center(MDO, NULL);
2833             N_pts = SUMA_ADO_N_Datum((SUMA_ALL_DO *)MDO);
2834             NewCenter[0] += N_pts*xyzr[0];
2835             NewCenter[1] += N_pts*xyzr[1];
2836             NewCenter[2] += N_pts*xyzr[2];
2837             TotWeight += N_pts;
2838             break; }
2839          case TRACT_type: {
2840             SUMA_TractDO *TDO=(SUMA_TractDO *)dov[do_id].OP;
2841             int N_tracts;
2842             if (TDO_HAS_GRID(TDO)) {
2843                xyzr = SUMA_TDO_Grid_Center(TDO, NULL);
2844             } else {
2845                xyzr = SUMA_TDO_Points_Center(TDO, NULL);
2846             }
2847             N_tracts = SUMA_TDO_N_tracts(TDO);
2848             NewCenter[0] += N_tracts*xyzr[0];
2849             NewCenter[1] += N_tracts*xyzr[1];
2850             NewCenter[2] += N_tracts*xyzr[2];
2851             TotWeight += N_tracts;
2852             break; }
2853          case VO_type: {
2854             SUMA_VolumeObject *VO=(SUMA_VolumeObject *)dov[do_id].OP;
2855             xyzr = SUMA_VO_Grid_Center(VO, NULL);
2856 
2857             NewCenter[0] += VO_NVOX(VO)*xyzr[0];
2858             NewCenter[1] += VO_NVOX(VO)*xyzr[1];
2859             NewCenter[2] += VO_NVOX(VO)*xyzr[2];
2860             TotWeight += VO_NVOX(VO);
2861             break; }
2862          case CDOM_type: {
2863 	    int kkk;
2864 	    xyzr = SUMA_ADO_Center((SUMA_ALL_DO *)dov[do_id].OP, NULL);
2865             kkk = SUMA_ADO_N_Datum((SUMA_ALL_DO *)dov[do_id].OP);
2866             NewCenter[0] += kkk*xyzr[0];
2867             NewCenter[1] += kkk*xyzr[1];
2868             NewCenter[2] += kkk*xyzr[2];
2869             TotWeight += kkk;
2870             break; }
2871 	 default:
2872             if (SUMA_is_iDO_Selectable(do_id)) {
2873                static int nwarn=0;
2874                if (!nwarn) {
2875                   SUMA_S_Warnv("Just ignored DO %s, I hope that's cool\n",
2876                             iDO_label(do_id));
2877                }
2878                ++nwarn;
2879             }
2880             SUMA_LHv("Ignoring object %s, variant %s\n",
2881                      iDO_label(do_id), iDO_variant(do_id));
2882             break;
2883       }
2884       ++i;
2885    }
2886    if (TotWeight) {
2887       SV->GVS[SV->StdView].RotaCenter[0] = NewCenter[0]/(float)TotWeight;
2888       SV->GVS[SV->StdView].RotaCenter[1] = NewCenter[1]/(float)TotWeight;
2889       SV->GVS[SV->StdView].RotaCenter[2] = NewCenter[2]/(float)TotWeight;
2890    } else
2891    {/* default back to o.o, o.o, o.o */
2892       SV->GVS[SV->StdView].RotaCenter[0] =
2893          SV->GVS[SV->StdView].RotaCenter[1] =
2894          SV->GVS[SV->StdView].RotaCenter[2] = 0.0;
2895    }
2896    SUMA_RETURN (YUP);
2897 
2898 }
2899 
2900 /*!
2901 output the state variable contents of the Surface Viewer
2902 */
SUMA_Show_SurfaceViewer_Struct(SUMA_SurfaceViewer * SV,FILE * Out,int detail)2903 void SUMA_Show_SurfaceViewer_Struct (SUMA_SurfaceViewer *SV, FILE *Out,
2904                                      int detail)
2905 {
2906    static char FuncName[]={"SUMA_Show_SurfaceViewer_Struct"};
2907    char *s = NULL;
2908 
2909    SUMA_ENTRY;
2910 
2911    if (Out == NULL) Out = stdout;
2912 
2913    s = SUMA_SurfaceViewer_StructInfo (SV, detail);
2914 
2915    if (s) {
2916       fprintf(Out, "%s", s);
2917       SUMA_free(s); s = NULL;
2918    }else {
2919       SUMA_SL_Err("Failed in SUMA_SurfaceViewer_StructInfo");
2920    }
2921 
2922    SUMA_RETURNe;
2923 }
2924 
SUMA_isViewerStateAnatomical(SUMA_SurfaceViewer * sv)2925 SUMA_Boolean SUMA_isViewerStateAnatomical(SUMA_SurfaceViewer *sv)
2926 {
2927    int i;
2928    if (!sv) return(NOPE);
2929    for (i=0; i < sv->N_VSv; ++i) {
2930       if (!strcmp(sv->State, sv->VSv[i].Name)) return(sv->VSv[i].AnatCorrect);
2931    }
2932    return(NOPE);
2933 }
2934 
SUMA_SurfaceViewer_StructInfo(SUMA_SurfaceViewer * SV,int detail)2935 char *SUMA_SurfaceViewer_StructInfo (SUMA_SurfaceViewer *SV, int detail)
2936 {
2937    static char FuncName[]={"SUMA_SurfaceViewer_StructInfo"};
2938    SUMA_STRING *SS = NULL;
2939    char *s=NULL;
2940    int i;
2941    SUMA_Boolean LocalHead = NOPE;
2942 
2943    SUMA_ENTRY;
2944 
2945    SS = SUMA_StringAppend (NULL, NULL);
2946 
2947    if (!SV) {
2948       SS = SUMA_StringAppend (SS,"NULL SV.\n");
2949       SS = SUMA_StringAppend (SS, NULL);
2950       /* copy s pointer and free SS */
2951       s = SS->s;
2952       SUMA_free(SS);
2953       SUMA_RETURN(s);
2954    }
2955 
2956    SS = SUMA_StringAppend(SS, "SV contents:\n");
2957    SS = SUMA_StringAppend_va(SS, "   verbose = %d\n", SV->verbose);
2958    if (SV->ShowLeft) SS = SUMA_StringAppend_va(SS,"   Show Left = YES\n");
2959    else SS = SUMA_StringAppend_va(SS,"   Show Left = NO\n");
2960    if (SV->ShowRight) SS = SUMA_StringAppend_va(SS,"   Show Right = YES\n");
2961    else SS = SUMA_StringAppend_va(SS,"   Show Right = NO\n");
2962 
2963    if (SV->ortho) SS = SUMA_StringAppend_va(SS,"   Projection: Orthographic\n");
2964    else SS = SUMA_StringAppend_va(SS,"   Projection: Perspective\n");
2965    SS = SUMA_StringAppend_va(SS,"   Display Labels At Crosshair: %s\n",
2966             SV->ShowLabelAtXhair ? "ON": "OFF");
2967    SS = SUMA_StringAppend_va(SS,"   Aspect = %f\n", SV->Aspect);
2968    SS = SUMA_StringAppend_va( SS,"   Freeze Zoom across states = %d\n",
2969                                SV->FreezeZoomXstates);
2970    SS = SUMA_StringAppend_va(SS, "   Dim. Scale Factor = %f\n",
2971                                  SV->GVS[SV->StdView].DimSclFac);
2972    SS = SUMA_StringAppend_va(SS, "   ViewDistance = %f\n",
2973                                  SV->GVS[SV->StdView].ViewDistance);
2974    SS = SUMA_StringAppend_va(SS, "   ViewFrom = [%f %f %f]\n",
2975                                  SV->GVS[SV->StdView].ViewFrom[0],
2976                                  SV->GVS[SV->StdView].ViewFrom[1],
2977                                  SV->GVS[SV->StdView].ViewFrom[2]);
2978    SS = SUMA_StringAppend_va(SS,"   ViewFromOrig = [%f %f %f]\n",
2979                                  SV->GVS[SV->StdView].ViewFromOrig[0],
2980                                  SV->GVS[SV->StdView].ViewFromOrig[1],
2981                                  SV->GVS[SV->StdView].ViewFromOrig[2]);
2982    SS = SUMA_StringAppend_va(SS,"   ViewCenter = [%f %f %f]\n",
2983                                  SV->GVS[SV->StdView].ViewCenter[0],
2984                                  SV->GVS[SV->StdView].ViewCenter[1],
2985                                  SV->GVS[SV->StdView].ViewCenter[2]);
2986    SS = SUMA_StringAppend_va(SS,"   ViewCenterOrig = [%f %f %f]\n",
2987                                  SV->GVS[SV->StdView].ViewCenterOrig[0],
2988                                  SV->GVS[SV->StdView].ViewCenterOrig[1],
2989                                  SV->GVS[SV->StdView].ViewCenterOrig[2]);
2990    SS = SUMA_StringAppend_va(SS,"   ViewCamUp = [%f %f %f]\n",
2991                                  SV->GVS[SV->StdView].ViewCamUp[0],
2992                                  SV->GVS[SV->StdView].ViewCamUp[1],
2993                                  SV->GVS[SV->StdView].ViewCamUp[2]);
2994    SS = SUMA_StringAppend_va(SS,"   RotaCenter = [%f %f %f]\n",
2995                                  SV->GVS[SV->StdView].RotaCenter[0],
2996                                  SV->GVS[SV->StdView].RotaCenter[1],
2997                                  SV->GVS[SV->StdView].RotaCenter[2]);
2998    SS = SUMA_StringAppend_va(SS, "   Convolution Filter = %d\n      [ ",
2999                                  SV->C_mode);
3000    if (SV->C_filter) {
3001       int ii, jj;
3002       for(jj = 0; jj < SV->C_filter->rows; jj++) {
3003          for(ii = 0; ii < SV->C_filter->cols; ii++) {
3004            SS = SUMA_StringAppend_va(SS, "%.3f ",
3005                             SV->C_filter->array[ii + jj * SV->C_filter->cols]);
3006          }
3007          if (jj < SV->C_filter->rows-1)
3008             SS = SUMA_StringAppend(SS, "\n        ");
3009          else SS = SUMA_StringAppend(SS, " ]\n" );
3010       }
3011    } else {
3012       SS = SUMA_StringAppend_va(SS, " NULL! ]\n");
3013    }
3014    SS = SUMA_StringAppend_va(SS,
3015                   "   light0_position = [%f %f %f %f] (lit for %d)\n",
3016                                  SV->light0_position[0],
3017                                  SV->light0_position[1],
3018                                  SV->light0_position[2],
3019                                  SV->light0_position[3],
3020                                  SV->lit_for);
3021    SS = SUMA_StringAppend_va(SS,"   light1_position = [%f %f %f %f]\n",
3022                                  SV->light1_position[0],
3023                                  SV->light1_position[1],
3024                                  SV->light1_position[2],
3025                                  SV->light1_position[3]);
3026    SS = SUMA_StringAppend_va(SS,"   ZoomCompensate = %f\n", SV->ZoomCompensate);
3027    SS = SUMA_StringAppend_va(SS,"   WindWidth/WIDTH/Offset = %d/%d/%d\n",
3028                         SV->wWindWidth, SV->X->aWIDTH, SV->DrawAreaWidthOffset);
3029    SS = SUMA_StringAppend_va(SS,"   WindHeight/HEIGHT/Offset = %d/%d/%d\n",
3030                       SV->wWindHeight, SV->X->aHEIGHT, SV->DrawAreaHeightOffset);
3031    SS = SUMA_StringAppend_va(SS,"   ShowWorldAxis = %d\n", SV->ShowWorldAxis);
3032    if (SV->WAx) {
3033       SS = SUMA_StringAppend_va(SS, "   WorldAxis: Center = [%f %f %f] \n"
3034                                     "              BR = [%f %f %f ,\n"
3035                                     "                    %f %f %f]\n",
3036                                     SV->WAx->Center[0], SV->WAx->Center[1],
3037                                     SV->WAx->Center[2],
3038                                     SV->WAx->BR[0][0], SV->WAx->BR[1][0],
3039                                     SV->WAx->BR[2][0],
3040                                     SV->WAx->BR[0][1], SV->WAx->BR[1][1],
3041                                     SV->WAx->BR[2][1]);
3042    } else {
3043       SS = SUMA_StringAppend_va(SS,"   WorldAxis: NULL\n");
3044    }
3045    SS = SUMA_StringAppend_va(SS,"   currentQuat = [%f %f %f %f]\n",
3046                         SV->GVS[SV->StdView].currentQuat[0],
3047                         SV->GVS[SV->StdView].currentQuat[1],
3048                         SV->GVS[SV->StdView].currentQuat[2],
3049                         SV->GVS[SV->StdView].currentQuat[3]);
3050    SS = SUMA_StringAppend_va(SS,"   deltaQuat = [%f %f %f %f]\n",
3051                         SV->GVS[SV->StdView].deltaQuat[0],
3052                         SV->GVS[SV->StdView].deltaQuat[1],
3053                         SV->GVS[SV->StdView].deltaQuat[2],
3054                         SV->GVS[SV->StdView].deltaQuat[3]);
3055    SS = SUMA_StringAppend_va(SS,"   ApplyMomentum = %d\n",
3056                         SV->GVS[SV->StdView].ApplyMomentum);
3057    SS = SUMA_StringAppend_va(SS,"   MinIdleDelta = %d\n",
3058                         SV->GVS[SV->StdView].MinIdleDelta);
3059    SS = SUMA_StringAppend_va(SS,"   zoomDelta = %f, zoomBegin = %f\n",
3060                SV->GVS[SV->StdView].zoomDelta, SV->GVS[SV->StdView].zoomBegin);
3061    SS = SUMA_StringAppend_va(SS,"   ArrowRotationAngle=%f rad (%f deg)\n",
3062                SV->ArrowRotationAngle, SV->ArrowRotationAngle * 180.0 / SUMA_PI);
3063    SS = SUMA_StringAppend_va(SS,"   KeyZoomGain=%f \n", SV->KeyZoomGain);
3064    SS = SUMA_StringAppend_va(SS,"   FOV_original=%f\n", SV->FOV_original);
3065    SS = SUMA_StringAppend_va(SS,"   spinDeltaX/Y = %.4f/%.4f\n",
3066                SV->GVS[SV->StdView].spinDeltaX, SV->GVS[SV->StdView].spinDeltaY);
3067    SS = SUMA_StringAppend_va(SS,"   spinBeginX/Y = %.4f/%.4f\n",
3068                SV->GVS[SV->StdView].spinBeginX, SV->GVS[SV->StdView].spinBeginY);
3069    SS = SUMA_StringAppend_va(SS,"   TranslateGain = %f\n",
3070                SV->GVS[SV->StdView].TranslateGain);
3071    SS = SUMA_StringAppend_va(SS,"   ArrowtranslateDeltaX/Y = %f/%f\n",
3072                SV->GVS[SV->StdView].ArrowtranslateDeltaX,
3073                SV->GVS[SV->StdView].ArrowtranslateDeltaY);
3074    SS = SUMA_StringAppend_va(SS,"   translateBeginX/Y = %.4f/%.4f\n",
3075                SV->GVS[SV->StdView].translateBeginX,
3076                SV->GVS[SV->StdView].translateBeginY);
3077    SS = SUMA_StringAppend_va(SS,"   translateDeltaX/Y = %f/%f\n",
3078                SV->GVS[SV->StdView].translateDeltaX,
3079                SV->GVS[SV->StdView].translateDeltaY);
3080    SS = SUMA_StringAppend_va(SS,"   translateVec = [%f %f 0.0]\n",
3081                SV->GVS[SV->StdView].translateVec[0],
3082                SV->GVS[SV->StdView].translateVec[1]);
3083    SS = SUMA_StringAppend_va(SS,
3084             "   LHpry = [%f %f %f], LHpry0 = [%f %f %f], LHlol = %d\n",
3085             SV->GVS[SV->StdView].vLHpry[0],
3086             SV->GVS[SV->StdView].vLHpry[1],
3087             SV->GVS[SV->StdView].vLHpry[2],
3088             SV->GVS[SV->StdView].vLHpry0[0],
3089             SV->GVS[SV->StdView].vLHpry0[1],
3090             SV->GVS[SV->StdView].vLHpry0[2],
3091                              SV->GVS[SV->StdView].LHlol);
3092    SS = SUMA_StringAppend_va(SS,"   Show Mesh Axis %d\n", SV->ShowMeshAxis);
3093    SS = SUMA_StringAppend_va(SS,"   Show Eye Axis %d\n", SV->ShowEyeAxis);
3094    SS = SUMA_StringAppend_va(SS,"   Show Cross Hair %d\n", SV->ShowCrossHair);
3095    SS = SUMA_StringAppend_va(SS,"   PolyMode %d\n", SV->PolyMode);
3096    SS = SUMA_StringAppend_va(SS,"   DO_DrawMask %d\n", SV->DO_DrawMask);
3097    SS = SUMA_StringAppend_va(SS,"   Blend_Mode %d\n", SV->Blend_Mode);
3098    if (SV->N_otseq) {
3099       SS = SUMA_StringAppend(SS,"Object rendering sequence:\n   ");
3100       for (i=0; i<SV->N_otseq; ++i) {
3101          SS = SUMA_StringAppend_va(SS,"%s%s",
3102                   SUMA_ObjectTypeCode2ObjectTypeName(SV->otseq[i]),
3103                   (i<SV->N_otseq-1)?", ":"");
3104       }
3105       SS = SUMA_StringAppend(SS,"\n");
3106    } else {
3107       SS = SUMA_StringAppend(SS,"No object ordering sequence");
3108    }
3109    SS = SUMA_StringAppend_va(SS,"   Group Name %s, indexed %d\n",
3110                                  SV->CurGroupName, SV->iCurGroup);
3111    SS = SUMA_StringAppend_va(SS,
3112             "   Current State %s, indexed %d, Anatomical %s\n",
3113                                  SV->State, SV->iState,
3114                                  SUMA_isViewerStateAnatomical(SV)?"YES":"NO");
3115    SS = SUMA_StringAppend_va(SS,"   N_DO = %d\n", SV->N_DO);
3116    SS = SUMA_StringAppend(SS, "   RegistDO = ");
3117    for (i=0; i< SV->N_DO; ++i) {
3118       SS = SUMA_StringAppend_va(SS,"[id %d] %s \n%s",
3119                   SV->RegistDO[i].dov_ind, iDO_label(SV->RegistDO[i].dov_ind),
3120                   (i<(SV->N_DO-1)) ? "               ":"");
3121    }
3122    SS = SUMA_StringAppend_va(SS,"   N_ColList = %d\n", SV->N_ColList);
3123    SS = SUMA_StringAppend(SS, "   ColList = ");
3124    for (i = 0; i < SV->N_ColList; ++i) {
3125       SS = SUMA_StringAppend_va(SS,
3126       "[%d] for DO %s, id %s, Remix %d, RemixID %d, %d colors, N_links = %d\n%s",
3127          i, iDO_label(SUMA_whichDO(SV->ColList[i]->idcode_str,
3128                            SUMAg_DOv, SUMAg_N_DOv)),
3129          SV->ColList[i]->idcode_str,
3130          SV->ColList[i]->Remix, SV->ColList[i]->RemixID,
3131          SV->ColList[i]->N_glar_ColorList, SV->ColList[i]->N_links,
3132          (i<(SV->N_ColList-1)) ? "             ":"");
3133    }
3134    if (SV->X == NULL) SS = SUMA_StringAppend_va(SS,"   X struct is NULL!\n");
3135    else {
3136    SS = SUMA_StringAppend_va(SS,"   X struct defined.\n");
3137    }
3138 
3139    SS = SUMA_StringAppend_va(SS,"   DO in focus %d\n", SV->Focus_DO_ID);
3140 
3141    /* show some state stuff */
3142    SS = SUMA_StringAppend_va(SS, "\nView States (%d total):\n", SV->N_VSv);
3143    for (i=0; i < SV->N_VSv; ++i) {
3144       SS = SUMA_StringAppend_va(SS,
3145                      "\nView State %d/%d (FOV = %f) (autoFOVval = %f):\n",
3146                            i, SV->N_VSv-1, SV->FOV[i], SV->auto_FOV_val[i]);
3147       s = SUMA_ViewStateInfo (&(SV->VSv[i]), 0);
3148       if (!s) {
3149          SS = SUMA_StringAppend(SS, "*** Error in SUMA_Show_ViewState ***\n");
3150       } else {
3151          SS = SUMA_StringAppend(SS, s);
3152          SUMA_free(s); s = NULL;
3153       }
3154    }
3155    SS = SUMA_StringAppend_va(SS, "\nStandard viewing mode: %d\n", SV->StdView );
3156    SS = SUMA_StringAppend_va(SS, "\nBackground Modulation Factor= %f\n",
3157                                  SV->Back_Modfact);
3158    SS = SUMA_StringAppend_va(SS, "\nLast non mappable visited %d\n",
3159                                  SV->LastNonMapStateID);
3160 
3161    s = SUMA_EnablingState_Info(&(SV->SER));
3162    SS = SUMA_StringAppend_va(SS,"Enabling state in sv->SER\n%s",s);
3163       SUMA_free(s); s = NULL;
3164 
3165    SS = SUMA_StringAppend(SS,"\n");
3166 
3167    /* trim SS */
3168    SS = SUMA_StringAppend (SS, NULL);
3169    /* copy s pointer and free SS */
3170    s = SS->s;
3171    SUMA_free(SS);
3172 
3173    SUMA_RETURN(s);
3174 }
3175 
3176 /*! Show the ViewState structure */
SUMA_Show_ViewState(SUMA_ViewState * VS,FILE * Out,int detail)3177 SUMA_Boolean SUMA_Show_ViewState(SUMA_ViewState *VS, FILE *Out, int detail)
3178 {
3179    static char FuncName[]={"SUMA_Show_ViewState"};
3180    char *s = NULL;
3181 
3182    SUMA_ENTRY;
3183 
3184    if (Out == NULL) Out = stdout;
3185 
3186    s = SUMA_ViewStateInfo(VS,  detail);
3187    if (!s) {
3188       SUMA_SL_Err("Failed in SUMA_ViewStateInfo");
3189       SUMA_RETURN(NOPE);
3190    }  else {
3191       fprintf(Out, "%s", s);
3192       SUMA_free(s); s = NULL;
3193    }
3194 
3195    SUMA_RETURN(YUP);
3196 }
3197 
3198 /*
3199    A function that must be called each time order of objects in
3200    SUMAg_DOv is disturbed
3201 */
SUMA_ViewState_MembsRefresh(SUMA_ViewState * VS)3202 SUMA_Boolean SUMA_ViewState_MembsRefresh(SUMA_ViewState *VS)
3203 {
3204    static char FuncName[]={"SUMA_ViewState_MembsRefresh"};
3205    int ii=0, found = -1;
3206    SUMA_Boolean LocalHead = NOPE;
3207 
3208    SUMA_ENTRY;
3209 
3210    if (!VS) SUMA_RETURN(NOPE);
3211 
3212    ii = 0;
3213    while (ii < VS->N_MembDO) {
3214       if ( VS->MembDO &&
3215           (found = SUMA_whichDOg(VS->MembDO[ii].idcode_str)) >= 0) {
3216          /* A good thing, refresh index mapping */
3217          VS->MembDO[ii].dov_ind = found;
3218       } else {
3219          SUMA_LH("A bad entry in MembDO at index %d/%d, cleaning",
3220                      ii, VS->N_MembDO);
3221          if (ii != VS->N_MembDO-1) {
3222             strcpy(VS->MembDO[ii].idcode_str,
3223                 VS->MembDO[VS->N_MembDO-1].idcode_str);
3224          }
3225          VS->MembDO[ii].dov_ind = VS->MembDO[VS->N_MembDO-1].dov_ind;
3226          VS->N_MembDO = VS->N_MembDO-1;
3227          VS->MembDO = (SUMA_DO_LOCATOR *)SUMA_realloc(VS->MembDO,
3228                             VS->N_MembDO*sizeof(SUMA_DO_LOCATOR));
3229       }
3230       ++ii;
3231    }
3232 
3233    SUMA_RETURN(YUP);
3234 }
3235 
SUMA_AllViewState_MembsRefresh(void)3236 SUMA_Boolean SUMA_AllViewState_MembsRefresh(void)
3237 {
3238    static char FuncName[]={"SUMA_AllViewState_MembsRefresh"};
3239    int i,j;
3240    SUMA_SurfaceViewer *sv;
3241    SUMA_Boolean state = YUP;
3242 
3243    SUMA_ENTRY;
3244 
3245    state = YUP;
3246    for (i=0; i<SUMAg_N_SVv; ++i) {
3247       sv = SUMAg_SVv+i;
3248       for (j=0; j<sv->N_VSv; ++j) {
3249          if (!SUMA_ViewState_MembsRefresh(sv->VSv+j)) state = NOPE;
3250       }
3251    }
3252 
3253    SUMA_RETURN(state);
3254 }
3255 
3256 /*! Search for certain types of DOs members of a particular state*/
SUMA_ViewState_Membs(SUMA_ViewState * VS,SUMA_DO_Types * ttv,int * uN_Membs)3257 int *SUMA_ViewState_Membs(SUMA_ViewState *VS, SUMA_DO_Types *ttv,
3258                           int *uN_Membs)
3259 {
3260    static char FuncName[]={"SUMA_ViewState_Membs"};
3261    int ii, jj, N_ttv;
3262    SUMA_DO_Types tt;
3263    int *Membs = NULL, N_Membs = 0;
3264    SUMA_Boolean LocalHead = NOPE;
3265 
3266    SUMA_ENTRY;
3267 
3268    if (uN_Membs) *uN_Membs = 0;
3269    SUMA_LHv("VS %p, Name %s, MembDOs %p, N_MembDOs %d\n",
3270             VS, (VS && VS->Name) ? VS->Name:"NULL",
3271                 (VS && VS->MembDO) ? VS->MembDO:NULL,
3272                 (VS && VS->N_MembDO) ? VS->N_MembDO:0);
3273    if (!VS || !VS->MembDO) SUMA_RETURN(Membs);
3274    jj = 0; N_ttv=0;
3275    while (ttv[jj] != NOT_SET_type) { ++N_ttv; ++jj; }
3276    if (!N_ttv) SUMA_RETURN(Membs);
3277 
3278    jj = 0;
3279    while (ttv[jj] != NOT_SET_type) {  tt = ttv[jj];
3280    for (ii=0; ii<VS->N_MembDO; ++ii) {
3281             SUMA_LHv("Checking %s type %s \n",
3282                      iDO_label(VS->MembDO[ii].dov_ind),
3283                      SUMA_ObjectTypeCode2ObjectTypeName(tt));
3284       if (iDO_type(VS->MembDO[ii].dov_ind) == tt) {
3285       switch (tt) {
3286          case SO_type:
3287                if (!Membs) Membs = (int *)
3288                         SUMA_malloc(N_ttv*(VS->N_MembDO+1)*sizeof(int));
3289                Membs[N_Membs++] = VS->MembDO[ii].dov_ind;
3290                Membs[N_Membs]=-1;/* a plug, if uN_Membs is NULL*/
3291             break;
3292          case GRAPH_LINK_type:
3293                if (!Membs) Membs = (int *)
3294                         SUMA_malloc(N_ttv*(VS->N_MembDO+1)*sizeof(int));
3295                Membs[N_Membs++] = VS->MembDO[ii].dov_ind;
3296                Membs[N_Membs]=-1;/* a plug, if uN_Membs is NULL*/
3297             break;
3298          case CDOM_type:
3299 	 case TRACT_type:
3300          case MASK_type:
3301          case VO_type:
3302                if (!Membs) Membs = (int *)
3303                         SUMA_malloc(N_ttv*(VS->N_MembDO+1)*sizeof(int));
3304                Membs[N_Membs++] = VS->MembDO[ii].dov_ind;
3305                Membs[N_Membs]=-1;/* a plug, if uN_Membs is NULL*/
3306             break;
3307          default:
3308             SUMA_S_Err("Not ready for type %d (%s)", tt, SUMA_otc2otn(tt));
3309             break;
3310         } }
3311    } ++jj;}
3312    if (uN_Membs) *uN_Membs = N_Membs;
3313 
3314    SUMA_RETURN(Membs);
3315 }
3316 
3317 /*! Show the ViewState structure */
SUMA_ViewStateInfo(SUMA_ViewState * VS,int detail)3318 char *SUMA_ViewStateInfo(SUMA_ViewState *VS, int detail)
3319 {
3320    static char FuncName[]={"SUMA_ViewStateInfo"};
3321    int i, ifound;
3322    SUMA_STRING *SS = NULL;
3323    char *s=NULL;
3324 
3325    SUMA_ENTRY;
3326 
3327    SS = SUMA_StringAppend (NULL, NULL);
3328 
3329    if (!VS) {
3330       SS = SUMA_StringAppend (SS,"NULL VS.\n");
3331       SS = SUMA_StringAppend (SS, NULL);
3332       /* copy s pointer and free SS */
3333       s = SS->s;
3334       SUMA_free(SS);
3335       SUMA_RETURN(s);
3336    }
3337 
3338    if (VS->Name) SS = SUMA_StringAppend_va(SS,
3339                      "   Name: %s, Anatomically Correct: %s\n",
3340                      VS->Name, VS->AnatCorrect?"YES":"NO");
3341    else SS = SUMA_StringAppend_va(SS, "   Name: NULL\n");
3342 
3343    if (VS->Group) SS = SUMA_StringAppend_va(SS, "   Group: %s\n", VS->Group);
3344    else SS = SUMA_StringAppend_va(SS, "   Group: NULL\n");
3345 
3346    if (VS->N_MembDO) {
3347       SS = SUMA_StringAppend_va(SS,
3348                   "   %2d MembDOs in VS->MembDO %p:\n               ",
3349                                  VS->N_MembDO, VS->MembDO);
3350       for (i=0; i < VS->N_MembDO; ++i) {
3351             ifound = SUMA_whichDOg(VS->MembDO[i].idcode_str);
3352             SS = SUMA_StringAppend_va(SS,
3353                         "id %s DOv[%d] %s (%s) -- id check: %s\n               ",
3354                         VS->MembDO[i].idcode_str, VS->MembDO[i].dov_ind,
3355                         iDO_label(VS->MembDO[i].dov_ind),
3356                         iDO_typename(VS->MembDO[i].dov_ind),
3357                (ifound == VS->MembDO[i].dov_ind)?"OK":"NO - Must run Refresh");
3358       }
3359    } else {
3360       SS = SUMA_StringAppend_va(SS, "   No  MembDOs in VS->MembDO %p\n",
3361                                  VS->MembDO);
3362    }
3363 
3364    if (VS->Hist) {
3365    } else {
3366       SS = SUMA_StringAppend_va(SS, "   Hist is NULL\n");
3367    }
3368 
3369    SS = SUMA_StringAppend (SS, NULL);
3370    /* copy s pointer and free SS */
3371    s = SS->s;
3372    SUMA_free(SS);
3373 
3374    SUMA_RETURN (s);
3375 }
3376 
3377 /*!
3378    Create & free ViewState_Hist structure
3379 */
SUMA_Alloc_ViewState_Hist(void)3380 SUMA_ViewState_Hist *SUMA_Alloc_ViewState_Hist (void)
3381 {
3382    static char FuncName[]={"SUMA_Alloc_ViewState_Hist"};
3383    SUMA_ViewState_Hist *vsh;
3384 
3385    SUMA_ENTRY;
3386 
3387    vsh = (SUMA_ViewState_Hist *)SUMA_calloc(1,sizeof(SUMA_ViewState_Hist));
3388    if (vsh == NULL) {
3389       fprintf(SUMA_STDERR,"Error %s: Could not allocate for vsh.\n", FuncName);
3390       SUMA_RETURN (NULL);
3391    }
3392    SUMA_RETURN (vsh);
3393 }
3394 
SUMA_Free_ViewState_Hist(SUMA_ViewState_Hist * vsh)3395 SUMA_Boolean SUMA_Free_ViewState_Hist (SUMA_ViewState_Hist *vsh)
3396 {
3397    static char FuncName[]={"SUMA_Free_ViewState_Hist"};
3398 
3399    SUMA_ENTRY;
3400 
3401    if (vsh == NULL) SUMA_RETURN (YUP);
3402    if (vsh) SUMA_free(vsh);
3403    SUMA_RETURN (YUP);
3404 }
3405 
3406 /*!
3407    Add a new SUMA_ViewState structure
3408    This is meant to replace SUMA_Alloc_ViewState
3409 
3410    - Both csv->VSv and csv->N_VSv are updated here
3411 */
SUMA_New_ViewState(SUMA_SurfaceViewer * cs)3412 SUMA_Boolean SUMA_New_ViewState (SUMA_SurfaceViewer *cs)
3413 {
3414    static char FuncName[]={"SUMA_New_ViewState"};
3415    int i;
3416 
3417    SUMA_ENTRY;
3418 
3419 
3420    if (!cs->VSv) { /* a new baby */
3421       cs->N_VSv = 1;
3422       cs->VSv = (SUMA_ViewState *)SUMA_calloc(1,sizeof(SUMA_ViewState));
3423    } else { /* realloc */
3424       ++cs->N_VSv;
3425       cs->VSv = (SUMA_ViewState *)SUMA_realloc(cs->VSv,
3426                                        cs->N_VSv*sizeof(SUMA_ViewState) );
3427    }
3428 
3429    /* check on allocation */
3430    if (!cs->VSv) {
3431       SUMA_SL_Err("Failed to allocate");
3432       SUMA_RETURN(YUP);
3433    }
3434 
3435    /* initialization of last element */
3436    cs->VSv[cs->N_VSv-1].Name = NULL;
3437    cs->VSv[cs->N_VSv-1].AnatCorrect = NOPE;
3438    cs->VSv[cs->N_VSv-1].Group = NULL;
3439    cs->VSv[cs->N_VSv-1].MembDO = NULL;
3440    cs->VSv[cs->N_VSv-1].N_MembDO = 0;
3441    cs->VSv[cs->N_VSv-1].Hist = SUMA_Alloc_ViewState_Hist ();
3442    if (cs->VSv[cs->N_VSv-1].Hist == NULL) {
3443       SUMA_S_Err("Could not allocate for cs->VSv->Hist.");
3444       SUMA_free(cs->VSv);
3445       SUMA_RETURN (NOPE);
3446    }
3447 
3448    /* allocate for FOV */
3449    if (!cs->FOV) {
3450       cs->FOV = (float *)SUMA_calloc(cs->N_VSv, sizeof(float));
3451       if (!cs->FOV_last_PickMode) {
3452          cs->FOV_last_PickMode = (float *)SUMA_calloc(cs->N_VSv, sizeof(float));
3453       }
3454       if (!cs->auto_FOV_val) {
3455          cs->auto_FOV_val  = (float *)SUMA_calloc(cs->N_VSv, sizeof(float));
3456       }
3457       for (i=0; i < cs->N_VSv; ++i) {
3458                   /* This will get reset in SUMA_SetupSVforDOs */
3459          cs->FOV[i] = cs->FOV_original;
3460          cs->auto_FOV_val[i] = -1.0;
3461       }
3462    } else {
3463       cs->FOV = (float *)SUMA_realloc(cs->FOV, cs->N_VSv * sizeof(float));
3464       cs->FOV[cs->N_VSv-1] = cs->FOV[0]; /*  used to be  = cs->FOV_original,
3465                            but it is best to set to 0th view,
3466                            gives user ability to set display
3467                            before auto-movie making via talk-suma */
3468       cs->FOV_last_PickMode = (float *)SUMA_realloc(cs->FOV_last_PickMode,
3469                                                       cs->N_VSv * sizeof(float));
3470       cs->auto_FOV_val  = (float *)SUMA_realloc(cs->auto_FOV_val,
3471                                                       cs->N_VSv * sizeof(float));
3472       cs->auto_FOV_val[cs->N_VSv-1] = -1.0;
3473    }
3474 
3475    /* Done */
3476    SUMA_RETURN(YUP);
3477 
3478 }
3479 
3480 /*!
3481    Create & free SUMA_ViewState structure
3482 */
SUMA_Alloc_ViewState(int N)3483 SUMA_ViewState *SUMA_Alloc_ViewState (int N)
3484 {
3485    SUMA_ViewState *vs;
3486    int i;
3487    static char FuncName[]={"SUMA_Alloc_ViewState"};
3488 
3489    SUMA_ENTRY;
3490 
3491    SUMA_SL_Err("Should not be using this anymore.\n"
3492                "Start using SUMA_New_ViewState.\n"
3493                "     ZSS Jan 12 04 \n");
3494    SUMA_RETURN(NULL);
3495    vs = (SUMA_ViewState *)SUMA_calloc(N,sizeof(SUMA_ViewState));
3496    if (vs == NULL) {
3497       fprintf(SUMA_STDERR,"Error %s: Could not allocate for vs.\n", FuncName);
3498       SUMA_RETURN (NULL);
3499    }
3500    for (i=0; i< N; ++i) {
3501       vs[i].Name = NULL;
3502       vs[i].Group = NULL;
3503       vs[i].MembDO = NULL;
3504       vs[i].N_MembDO = 0;
3505       vs[i].Hist = SUMA_Alloc_ViewState_Hist ();
3506       if (vs[i].Hist == NULL) {
3507          SUMA_S_Err("Could not allocate for vs->Hist.");
3508          SUMA_free(vs);
3509          SUMA_RETURN (NULL);
3510       }
3511    }
3512    SUMA_RETURN (vs);
3513 }
3514 
SUMA_Free_ViewState(SUMA_ViewState * vs)3515 SUMA_Boolean SUMA_Free_ViewState (SUMA_ViewState *vs)
3516 {
3517    static char FuncName[]={"SUMA_Free_ViewState"};
3518    SUMA_ENTRY;
3519 
3520    if (vs == NULL) SUMA_RETURN (YUP);
3521    if (vs->Name) SUMA_free(vs->Name);
3522    if (vs->Group) SUMA_free(vs->Group);
3523    if (vs->MembDO) SUMA_free(vs->MembDO);
3524    if (vs->Hist) SUMA_Free_ViewState_Hist (vs->Hist);
3525    if (vs) SUMA_free(vs);
3526    SUMA_RETURN (YUP);
3527 }
3528 
3529 /*!
3530    locate the index i (into SVv[i]) of sv
3531    -1 if not found
3532 */
SUMA_WhichSV(SUMA_SurfaceViewer * sv,SUMA_SurfaceViewer * SVv,int N_SVv)3533 int SUMA_WhichSV (SUMA_SurfaceViewer *sv, SUMA_SurfaceViewer *SVv, int N_SVv)
3534 {
3535    static char FuncName[]={"SUMA_WhichSV"};
3536    int i = 0;
3537 
3538    SUMA_ENTRY;
3539 
3540    if (!SVv || !sv) {
3541       fprintf (SUMA_STDERR, "Error %s: NULL SVv or sv.\n", FuncName);
3542       SUMA_RETURN (-1);
3543    }
3544 
3545    for (i=0; i<N_SVv; ++i) {
3546       if (&(SVv[i]) == sv) {
3547          SUMA_RETURN (i);
3548       }
3549    }
3550 
3551 
3552    SUMA_RETURN (-1);
3553 }
3554 
SUMA_WhichSVg(SUMA_SurfaceViewer * sv)3555 int SUMA_WhichSVg(SUMA_SurfaceViewer *sv)
3556 {
3557    return(SUMA_WhichSV(sv, SUMAg_SVv, SUMAg_N_SVv));
3558 }
3559 
SUMA_WhichSVc(SUMA_SurfaceViewer * sv,SUMA_SurfaceViewer * SVv,int N_SVv)3560 char SUMA_WhichSVc(SUMA_SurfaceViewer *sv, SUMA_SurfaceViewer *SVv, int N_SVv)
3561 {
3562    static char FuncName[]={"SUMA_WhichSVc"};
3563    int isv;
3564 
3565    isv = SUMA_WhichSV(sv, SVv, N_SVv);
3566    if (isv >= 0) return(65+isv);
3567    return('\0');
3568 }
3569 
3570 /* return 1st viewer that is open and has a
3571    particular surface visible AND in focus
3572 */
SUMA_OneViewerWithSOinFocus(SUMA_SurfaceObject * curSO)3573 SUMA_SurfaceViewer *SUMA_OneViewerWithSOinFocus(
3574                               SUMA_SurfaceObject *curSO)
3575 {
3576    static char FuncName[]={"SUMA_OneViewerWithSOinFocus"};
3577    int i=0;
3578    SUMA_SurfaceViewer *sv=NULL;
3579 
3580    SUMA_ENTRY;
3581 
3582    /* look for 1st viewer that is showing this
3583       surface and has this surface in focus*/
3584    for (i=0; i<SUMAg_N_SVv; ++i) {
3585       if (!SUMAg_SVv[i].isShaded && SUMAg_SVv[i].X->TOPLEVEL) {
3586          /* is this viewer showing curSO ? */
3587          if (SUMA_isVisibleDO(&(SUMAg_SVv[i]), SUMAg_DOv,
3588                                (SUMA_ALL_DO *)curSO)) {
3589             if ((SUMAg_DOv[SUMAg_SVv[i].Focus_DO_ID].OP) == curSO) {
3590                   sv = &(SUMAg_SVv[i]);
3591                   SUMA_RETURN(sv);
3592             }
3593          }
3594       }
3595    }
3596 
3597    SUMA_RETURN(sv);
3598 }
3599 
3600 /* return 1st viewer that is open and has a
3601    particular object visible AND in focus
3602 */
SUMA_OneViewerWithADOinFocus(SUMA_ALL_DO * ADO)3603 SUMA_SurfaceViewer *SUMA_OneViewerWithADOinFocus(SUMA_ALL_DO *ADO)
3604 {
3605    static char FuncName[]={"SUMA_OneViewerWithADOinFocus"};
3606    int i=0;
3607    SUMA_SurfaceViewer *sv=NULL;
3608 
3609    SUMA_ENTRY;
3610 
3611    /* look for 1st viewer that has this ADO in focus*/
3612    for (i=0; i<SUMAg_N_SVv; ++i) {
3613       if (!SUMAg_SVv[i].isShaded && SUMAg_SVv[i].X->TOPLEVEL) {
3614          /* is this viewer showing ADO ? */
3615          if (SUMA_isVisibleDO(&(SUMAg_SVv[i]), SUMAg_DOv, ADO)) {
3616             if ((SUMAg_DOv[SUMAg_SVv[i].Focus_DO_ID].OP) == ADO) {
3617                   sv = &(SUMAg_SVv[i]);
3618                   SUMA_RETURN(sv);
3619             }
3620          }
3621       }
3622    }
3623 
3624    SUMA_RETURN(sv);
3625 }
3626 
SUMA_OneViewerWithADOVisible(SUMA_ALL_DO * ADO)3627 SUMA_SurfaceViewer *SUMA_OneViewerWithADOVisible(SUMA_ALL_DO *ADO)
3628 {
3629    static char FuncName[]={"SUMA_OneViewerWithADOVisible"};
3630    int i=0;
3631    SUMA_SurfaceViewer *sv=NULL;
3632 
3633    SUMA_ENTRY;
3634 
3635    /* look for 1st viewer that is showing this
3636       surface and has this surface in focus*/
3637    for (i=0; i<SUMAg_N_SVv; ++i) {
3638       if (!SUMAg_SVv[i].isShaded && SUMAg_SVv[i].X->TOPLEVEL) {
3639          /* is this viewer showing ADO ? */
3640          if (SUMA_isVisibleDO(&(SUMAg_SVv[i]), SUMAg_DOv, ADO)) {
3641             sv = &(SUMAg_SVv[i]);
3642             SUMA_RETURN(sv);
3643          }
3644       }
3645    }
3646 
3647    SUMA_RETURN(sv);
3648 }
3649 
SUMA_OneViewerWithSOVisible(SUMA_SurfaceObject * curSO)3650 SUMA_SurfaceViewer *SUMA_OneViewerWithSOVisible(
3651                               SUMA_SurfaceObject *curSO)
3652 {
3653    static char FuncName[]={"SUMA_OneViewerWithSOVisible"};
3654    int i=0;
3655    SUMA_SurfaceViewer *sv=NULL;
3656 
3657    SUMA_ENTRY;
3658 
3659    /* look for 1st viewer that is showing this
3660       surface and has this surface in focus*/
3661    for (i=0; i<SUMAg_N_SVv; ++i) {
3662       if (!SUMAg_SVv[i].isShaded && SUMAg_SVv[i].X->TOPLEVEL) {
3663          /* is this viewer showing curSO ? */
3664          if (SUMA_isVisibleDO(&(SUMAg_SVv[i]), SUMAg_DOv,
3665                                (SUMA_ALL_DO *)curSO)) {
3666             sv = &(SUMAg_SVv[i]);
3667             SUMA_RETURN(sv);
3668          }
3669       }
3670    }
3671 
3672    SUMA_RETURN(sv);
3673 }
3674 
SUMA_OneViewerWithADORegistered(SUMA_ALL_DO * ADO)3675 SUMA_SurfaceViewer *SUMA_OneViewerWithADORegistered(SUMA_ALL_DO *ADO)
3676 {
3677    static char FuncName[]={"SUMA_OneViewerWithADORegistered"};
3678    int i=0;
3679    SUMA_SurfaceViewer *sv=NULL;
3680 
3681    SUMA_ENTRY;
3682 
3683    /* look for 1st viewer that is showing this
3684       surface and has this surface in focus*/
3685    for (i=0; i<SUMAg_N_SVv; ++i) {
3686       if (!SUMAg_SVv[i].isShaded && SUMAg_SVv[i].X->TOPLEVEL) {
3687          if (SUMA_ADO_isRegistered(SUMAg_SVv+i, ADO)) {
3688             sv = &(SUMAg_SVv[i]);
3689             SUMA_RETURN(sv);
3690          }
3691       }
3692    }
3693 
3694    SUMA_RETURN(sv);
3695 }
3696 
SUMA_OneViewerWithSORegistered(SUMA_SurfaceObject * curSO)3697 SUMA_SurfaceViewer *SUMA_OneViewerWithSORegistered(
3698                               SUMA_SurfaceObject *curSO)
3699 {
3700    static char FuncName[]={"SUMA_OneViewerWithSORegistered"};
3701    int i=0;
3702    SUMA_SurfaceViewer *sv=NULL;
3703 
3704    SUMA_ENTRY;
3705 
3706    /* look for 1st viewer that is showing this
3707       surface and has this surface in focus*/
3708    for (i=0; i<SUMAg_N_SVv; ++i) {
3709       if (!SUMAg_SVv[i].isShaded && SUMAg_SVv[i].X->TOPLEVEL) {
3710          /* is this viewer showing curSO ? */
3711          if (SUMA_isRegisteredSO(&(SUMAg_SVv[i]), SUMAg_DOv, curSO)) {
3712             sv = &(SUMAg_SVv[i]);
3713             SUMA_RETURN(sv);
3714          }
3715       }
3716    }
3717 
3718    SUMA_RETURN(sv);
3719 }
3720 
SUMA_BestViewerForADO(SUMA_ALL_DO * ado)3721 SUMA_SurfaceViewer *SUMA_BestViewerForADO(SUMA_ALL_DO *ado)
3722 
3723 {
3724    static char FuncName[]={"SUMA_BestViewerForADO"};
3725    int i=0;
3726    SUMA_SurfaceViewer *sv=NULL;
3727 
3728    SUMA_ENTRY;
3729 
3730    if (!ado) {
3731       SUMA_RETURN(&(SUMAg_SVv[0]));
3732    }
3733 
3734    switch (ado->do_type) {
3735       case SO_type: {
3736          SUMA_SurfaceObject *curSO = (SUMA_SurfaceObject *)ado;
3737          /* best bet, visible, and in focus */
3738          if ((sv=SUMA_OneViewerWithSOinFocus(curSO))) {
3739             SUMA_RETURN(sv);
3740          }
3741          /* just visible */
3742          if ((sv=SUMA_OneViewerWithSOVisible(curSO))) {
3743             SUMA_RETURN(sv);
3744          }
3745          /* registered */
3746          if ((sv=SUMA_OneViewerWithSORegistered(curSO))) {
3747             SUMA_RETURN(sv);
3748          }
3749          /* crap! */
3750          sv = &(SUMAg_SVv[0]);
3751          break; }
3752       case GRAPH_LINK_type:
3753       case GDSET_type:
3754       case CDOM_type:
3755       case VO_type:
3756       case MASK_type:
3757       case TRACT_type:
3758          if ((sv=SUMA_OneViewerWithADOinFocus(ado))) {
3759             SUMA_RETURN(sv);
3760          }
3761          /* just visible */
3762          if ((sv=SUMA_OneViewerWithADOVisible(ado))) {
3763             SUMA_RETURN(sv);
3764          }
3765          /* registered */
3766          if ((sv=SUMA_OneViewerWithADORegistered(ado))) {
3767             SUMA_RETURN(sv);
3768          }
3769          sv = &(SUMAg_SVv[0]);
3770          break;
3771       default:
3772          SUMA_S_Errv("Not ready for %s\n",
3773             SUMA_ObjectTypeCode2ObjectTypeName(ado->do_type));
3774          sv = &(SUMAg_SVv[0]);
3775          break;
3776    }
3777 
3778    SUMA_RETURN(sv);
3779 }
3780 
3781 /*!
3782    locate the index i (into csv->VSv[i]) of state
3783    -1 if not found
3784 */
SUMA_WhichState(char * state,SUMA_SurfaceViewer * csv,char * ForceGroup)3785 int SUMA_WhichState (char *state, SUMA_SurfaceViewer *csv, char *ForceGroup)
3786 {
3787    static char FuncName[]={"SUMA_WhichState"};
3788    int i = 0;
3789    SUMA_Boolean LocalHead = NOPE;
3790 
3791    SUMA_ENTRY;
3792 
3793    if (!ForceGroup || !strcmp(ForceGroup,"ANY")) {
3794       SUMA_LH("Searching for state: %s, %d states\n"
3795                "Viewer %p [%c], %d viewers realized out of %d total",
3796                state, csv->N_VSv,  csv,
3797                SUMA_WhichSVc(csv, SUMAg_SVv, SUMA_MAX_SURF_VIEWERS),
3798                SUMAg_N_SVv, SUMA_MAX_SURF_VIEWERS);
3799       while (i < csv->N_VSv) {
3800          if (LocalHead) fprintf(SUMA_STDERR,"   %d? %s ...\n",
3801                                  i, csv->VSv[i].Name);
3802 
3803          if (!csv->VSv[i].Name || !state) {
3804             SUMA_LH("Null Name or State \n");
3805             SUMA_RETURN (-1);
3806          }
3807          if (strcmp(csv->VSv[i].Name, state) == 0) {
3808             if (LocalHead)
3809                fprintf(SUMA_STDERR,"%s: FOUND, i=%d!\n", FuncName, i);
3810             SUMA_RETURN (i);
3811          }
3812          if (strcmp(state,"ANY_ANATOMICAL") == 0 && csv->VSv[i].AnatCorrect) {
3813             if (LocalHead)
3814                fprintf(SUMA_STDERR,"%s: FOUND, i=%d for ANY_ANATOMICAL!\n",
3815                         FuncName, i);
3816             SUMA_RETURN (i);
3817          }
3818          ++i;
3819       }
3820    } else {
3821       if (LocalHead) fprintf(SUMA_STDERR,"%s: Searching for: %s, %s...\n",
3822                               FuncName, state, ForceGroup);
3823       while (i < csv->N_VSv) {
3824          if (LocalHead) fprintf(SUMA_STDERR,"   %d? %s, %s ...\n",
3825                                  i, csv->VSv[i].Name, csv->VSv[i].Group);
3826          if (!csv->VSv[i].Name || !state || !csv->CurGroupName) {
3827             SUMA_LH("Null Name or State or CurGroupName.\n");
3828             SUMA_RETURN (-1);
3829          }
3830          if (strcmp(csv->VSv[i].Name, state) == 0              &&
3831                (strcmp(csv->VSv[i].Group, ForceGroup) == 0 ||
3832                 strcmp(csv->VSv[i].Group, "ANY") == 0         ) ) {
3833             if (LocalHead) fprintf(SUMA_STDERR,"%s: FOUND, i=%d!\n",
3834                FuncName, i);
3835             SUMA_RETURN (i);
3836          }
3837          ++i;
3838       }
3839    }
3840    SUMA_RETURN (-1);
3841 }
3842 
3843 /*!
3844    Return the viewer state for a particular displayable object
3845    dov_id (int): Identifier of object by index into SUMAg_DOv
3846    cSV (SUMA_SurfaceViewer *): Viewer in question. I null, all
3847                                viewers get the treatment
3848    addifmissing (int): If 1 then add state if not found
3849 
3850    Returns the index of the state into cSV->VSv, if cSV was null,
3851             the index would be into SUMAg_SVv[0]
3852             -1 if none were found and adding was not allowed.
3853             -2 in error
3854 */
SUMA_Which_iDO_State(int dov_id,SUMA_SurfaceViewer * cSV,int addifmissing)3855 int SUMA_Which_iDO_State(int dov_id, SUMA_SurfaceViewer *cSV, int addifmissing)
3856 {
3857    static char FuncName[]={"SUMA_Which_iDO_State"};
3858    int is = -2, do_all=0, iic, isd;
3859    char *sid=NULL;
3860    SUMA_Boolean LocalHead = NOPE;
3861 
3862    SUMA_ENTRY;
3863 
3864    if (SUMAg_N_SVv <= 0) SUMA_RETURN(is);
3865    if (!cSV) do_all=1;
3866    iic=SUMAg_N_SVv-1;
3867    do {
3868       if (do_all) cSV = &(SUMAg_SVv[iic]);
3869       is = SUMA_WhichState (SUMA_iDO_state(dov_id), cSV, SUMA_iDO_group(dov_id));
3870       SUMA_LHv("is %d, addifmissing %d", is, addifmissing);
3871       if (is < 0 && addifmissing) { /* add state, it is a new one */
3872          SUMA_LHv("For DO %s, type %s\n    State:%s to be added, group %s\n",
3873                   iDO_label(dov_id), iDO_typename(dov_id),
3874                   iDO_state(dov_id), iDO_group(dov_id));
3875          SUMA_New_ViewState (cSV);
3876          is = cSV->N_VSv-1;
3877          cSV->VSv[is].Name = SUMA_copy_string(SUMA_iDO_state(dov_id));
3878          cSV->VSv[is].AnatCorrect = SUMA_is_iDO_AnatCorrect(dov_id);
3879          cSV->VSv[is].Group = iDO_group(dov_id);
3880          if (!cSV->VSv[is].Name ||
3881              !cSV->VSv[is].Group) {
3882             SUMA_S_Err("Failed to allocate for cSV->VSv[is]."
3883                        "Name or .Group.");
3884             SUMA_RETURN (NOPE);
3885          }
3886          cSV->VSv[is].N_MembDO = 1;
3887          cSV->VSv[is].MembDO =
3888             (SUMA_DO_LOCATOR *)SUMA_calloc(cSV->VSv[is].N_MembDO,
3889                                            sizeof(SUMA_DO_LOCATOR));
3890          cSV->VSv[is].MembDO[cSV->VSv[is].N_MembDO-1].dov_ind = dov_id;
3891          sid = iDO_idcode(dov_id);
3892          strcpy(cSV->VSv[is].MembDO[cSV->VSv[is].N_MembDO-1].idcode_str, sid);
3893          if (LocalHead) {
3894             char *s = SUMA_ViewStateInfo (&(cSV->VSv[is]), 0);
3895             SUMA_LHv("State Info of cSV->VSv[%d] now:\n%s\n",is, s);
3896             SUMA_ifree(s);
3897          }
3898       }
3899       if (!cSV->State && cSV->N_VSv) {
3900          if (is < 0) isd = 0;
3901          else isd = is;
3902          /* happens if loading DOs without surfaces already loaded
3903             Should always have something decent if you can*/
3904          SUMA_LHv(
3905            "No state yet for cSV %p, defaulting to cSV->VSv[%d].Name -->%s<--\n",
3906                   cSV, isd, cSV->VSv[isd].Name);
3907          cSV->State = cSV->VSv[isd].Name;
3908          cSV->iState = isd;
3909       }
3910       --iic;
3911    } while (do_all && iic >= 0);
3912 
3913    SUMA_RETURN(is);
3914 }
3915 
3916 
3917 /*!
3918    register the different view states and surfaces belonging to different
3919    view states in the surface viewer's structure
3920    Essentially, it creates the vector VSv that is a part of the surface
3921    viewer structure
3922 */
SUMA_RegisterSpecSO(SUMA_SurfSpecFile * Spec,SUMA_SurfaceViewer * csv,SUMA_DO * dov,int N_dov,int viewopt)3923 SUMA_Boolean SUMA_RegisterSpecSO (SUMA_SurfSpecFile *Spec,
3924                                   SUMA_SurfaceViewer *csv,
3925                                   SUMA_DO* dov, int N_dov, int viewopt)
3926 {
3927    static char FuncName[]={"SUMA_RegisterSpecSO"};
3928    int is, i, old_N_VSv = 0;
3929    char *sid=NULL;
3930    SUMA_SurfaceObject * SO;
3931    SUMA_Boolean LocalHead = NOPE;
3932 
3933    SUMA_ENTRY;
3934 
3935    if (!viewopt) viewopt = UPDATE_ALL_VIEWING_PARAMS_MASK;
3936 
3937    if (LocalHead && SUMA_WhichSV(csv, SUMAg_SVv, SUMA_MAX_SURF_VIEWERS) != 0) {
3938       fprintf(SUMA_STDERR,"%s: Muted for viewer[%c]\n",
3939                            FuncName, SUMA_SV_CHAR(csv)    );
3940       /* turn off the LocalHead, too much output*/
3941       LocalHead = NOPE;
3942    }
3943 
3944 
3945    /* allocate for space depending on the number of states present */
3946 
3947    if (LocalHead) fprintf(SUMA_STDERR,"%s: Entering, Spec->Group[0] = %s ...\n",
3948       FuncName, Spec->Group[0]);
3949 
3950    if (Spec->N_Groups != 1) {
3951       SUMA_SL_Err("A spec file is to have 1 and only 1 group in it");
3952       SUMA_RETURN(NOPE);
3953    }
3954 
3955    #if 0
3956       /* the old way */
3957       if (!csv->VSv) { /* first pass */
3958          csv->VSv = SUMA_Alloc_ViewState (Spec->N_States);
3959          if (csv->VSv == NULL) {
3960             fprintf(SUMA_STDERR,
3961                     "Error %s: Failed to allocate for VSv.\n", FuncName);
3962             SUMA_RETURN (NOPE);
3963          }
3964          csv->N_VSv = 0;
3965       }
3966    #endif
3967 
3968    /* register the various states from each SO in DOv */
3969    SUMA_LHv("Cycling through DOvs, looking for surfaces/DOs of group %s\n",
3970             Spec->Group[0]);
3971    old_N_VSv = csv->N_VSv;
3972    for (i=0; i < N_dov; ++i) {
3973       switch (dov[i].ObjectType) {
3974          case SO_type:
3975             if (SUMA_isSO_G(dov[i], Spec->Group[0])) {
3976                SO = (SUMA_SurfaceObject *)(dov[i].OP);
3977                is = SUMA_WhichState (SO->State, csv, SO->Group);
3978                if (is < 0) {
3979                   /* add state if it is a new one */
3980                   /* make room */
3981                   if (LocalHead) {
3982                      fprintf(SUMA_STDERR,
3983                         "%s: For %s\nState:%s,Group:%s to be added\n",
3984                         FuncName, SO->Label, SO->State, SO->Group);
3985                   }
3986                   SUMA_New_ViewState (csv);
3987                   csv->VSv[csv->N_VSv-1].Name = SUMA_copy_string(SO->State);
3988                   csv->VSv[csv->N_VSv-1].AnatCorrect = SO->AnatCorrect;
3989                   csv->VSv[csv->N_VSv-1].Group = SUMA_copy_string(SO->Group);
3990                   if (!csv->VSv[csv->N_VSv-1].Name ||
3991                       !csv->VSv[csv->N_VSv-1].Group) {
3992                      SUMA_S_Err("Failed to allocate for csv->VSv[csv->N_VSv-1]."
3993                                 "Name or .Group.");
3994                      SUMA_RETURN (NOPE);
3995                   }
3996                   csv->VSv[csv->N_VSv-1].N_MembDO = 1;
3997                } else { /* old one, count it */
3998                   if (LocalHead) {
3999                      fprintf(SUMA_STDERR,
4000                         "%s: For %s\n State:%s,Group:%s found\n",
4001                         FuncName, SO->Label, SO->State, SO->Group);
4002                   }
4003                   csv->VSv[is].N_MembDO += 1;
4004                }
4005             }
4006             break;
4007          case TRACT_type:
4008          case MASK_type:
4009          case VO_type:
4010 	 case CDOM_type:
4011          case GRAPH_LINK_type:
4012             is = SUMA_WhichState (SUMA_iDO_state(i), csv,SUMA_iDO_group(i));
4013             if (is < 0) {
4014                if (LocalHead) {
4015                   fprintf(SUMA_STDERR,
4016                      "%s: For %s\nState:%s,Group:%s to be added\n",
4017                      FuncName, iDO_label(i),
4018                      SUMA_iDO_state(i), SUMA_iDO_group(i));
4019                }
4020                SUMA_New_ViewState (csv);
4021                csv->VSv[csv->N_VSv-1].Name = SUMA_copy_string(SUMA_iDO_state(i));
4022                csv->VSv[csv->N_VSv-1].AnatCorrect =
4023                                              SUMA_isDO_AnatCorrect(&(dov[i]));
4024                csv->VSv[csv->N_VSv-1].Group =
4025                                              SUMA_copy_string(SUMA_iDO_group(i));
4026                if (!csv->VSv[csv->N_VSv-1].Name ||
4027                    !csv->VSv[csv->N_VSv-1].Group) {
4028                   SUMA_S_Err("Failed to allocate for csv->VSv[csv->N_VSv-1]."
4029                              "Name or .Group.");
4030                   SUMA_RETURN (NOPE);
4031                }
4032                csv->VSv[csv->N_VSv-1].N_MembDO = 1;
4033             } else {
4034                if (LocalHead) {
4035                      fprintf(SUMA_STDERR,
4036                         "%s: For %s\n State:%s,Group:%s found\n",
4037                         FuncName, iDO_label(i),
4038                         SUMA_iDO_state(i), SUMA_iDO_group(i));
4039                   }
4040                   csv->VSv[is].N_MembDO += 1;
4041             }
4042             break;
4043          default:
4044             SUMA_LHv("Just ignored DO %s...\n", DO_label(dov[i].OP));
4045             break;
4046       }
4047    }
4048 
4049    SUMA_LH("Allocating...");
4050 
4051    /* allocate space for MembDOs
4052       counters will be reset for later use */
4053    for (i=0; i < csv->N_VSv; ++i) {
4054 
4055       if (!csv->VSv[i].MembDO) {
4056          csv->VSv[i].MembDO = (SUMA_DO_LOCATOR *)
4057                                  SUMA_calloc(csv->VSv[i].N_MembDO,
4058                                                    sizeof(SUMA_DO_LOCATOR));
4059       } else {
4060          csv->VSv[i].MembDO = (SUMA_DO_LOCATOR *)
4061                               SUMA_realloc(csv->VSv[i].MembDO,
4062                                  csv->VSv[i].N_MembDO * sizeof(SUMA_DO_LOCATOR));
4063       }
4064       if (csv->VSv[i].MembDO == NULL) {
4065          SUMA_S_Err("Failed to allocate for csv->VSv[i].MembDO.\n");
4066          SUMA_RETURN (NOPE);
4067       }
4068 
4069       csv->VSv[i].N_MembDO = 0;
4070    }
4071 
4072 
4073    /*fprintf(SUMA_STDERR,"%s: placement ...\n", FuncName);*/
4074 
4075    /* place each SO where it belongs, don't worry about the group they're in */
4076    for (i=0; i < N_dov; ++i) {
4077       switch (dov[i].ObjectType) {
4078          case SO_type:
4079             SO = (SUMA_SurfaceObject *)(dov[i].OP);
4080             /* find out which state it goes in */
4081             if (!SO->State || !SO->Group) {
4082                SUMA_S_Errv("Sent me SO (%s) with null State (%s) "
4083                            "or null Group (%s)!\n",
4084                            SO->Label, SO->State, SO->Group);
4085                if (LocalHead) SUMA_Print_Surface_Object (SO, NULL);
4086                SUMA_RETURN (NOPE);
4087             }
4088             is = SUMA_WhichState (SO->State, csv, SO->Group);
4089             if (is < 0) {
4090                SUMA_S_Errv("This should not be.\n"
4091                            "Failed to find %s %s in csv\n",
4092                            SO->State, SO->Group);
4093                SUMA_RETURN (NOPE);
4094             }
4095             if (LocalHead) {
4096                fprintf (SUMA_STDERR,"%s: Trying to house %s in: State[%d]\n", \
4097                FuncName, SO->Label, is);
4098             }
4099             /* store its id as a valid member of the state */
4100             csv->VSv[is].MembDO[csv->VSv[is].N_MembDO].dov_ind = i;
4101             strcpy(csv->VSv[is].MembDO[csv->VSv[is].N_MembDO].idcode_str,
4102                    SO->idcode_str);
4103             csv->VSv[is].N_MembDO += 1; /* count it, again */
4104             break;
4105          case TRACT_type:
4106          case MASK_type:
4107          case VO_type:
4108          case GRAPH_LINK_type:
4109 	 case CDOM_type:
4110             is = SUMA_WhichState (SUMA_iDO_state(i), csv,SUMA_iDO_group(i));
4111             if (is < 0) {
4112                SUMA_S_Errv("This should not be.\n"
4113                            "Failed to find %s %s in csv\n",
4114                            SUMA_iDO_state(i), SUMA_iDO_group(i));
4115                SUMA_RETURN (NOPE);
4116             }
4117             if (LocalHead) {
4118                fprintf (SUMA_STDERR,"%s: Trying to house %s in: State[%d]\n", \
4119                FuncName, SO->Label, is);
4120             }
4121             /* store its id as a valid member of the state */
4122             csv->VSv[is].MembDO[csv->VSv[is].N_MembDO].dov_ind = i;
4123             sid = iDO_idcode(i);
4124             strcpy(csv->VSv[is].MembDO[csv->VSv[is].N_MembDO].idcode_str, sid);
4125             csv->VSv[is].N_MembDO += 1; /* count it, again */
4126             break;
4127          default:
4128             if (SUMA_is_iDO_Selectable(i)) {
4129                static int nwarn=0;
4130                if (!nwarn) {
4131                   SUMA_S_Warnv("Just ignored DO %s, I hope that's cool\n",
4132                             iDO_label(i));
4133                }
4134                ++nwarn;
4135             }
4136             SUMA_LHv("Just ignored DO %s...\n", DO_label(dov[i].OP));
4137             break;
4138 
4139       }
4140    }
4141 
4142    /*fprintf(SUMA_STDERR,"%s: Leaving ...\n", FuncName);*/
4143 
4144    SUMA_RETURN (YUP);
4145 }
4146 
4147 /*! allocate and intialize SUMA_CommonFields
4148    No fancy allocation, No fancy macros.
4149 \sa SUMA_Free_CommonFields
4150 */
SUMA_Create_CommonFields()4151 SUMA_CommonFields * SUMA_Create_CommonFields ()
4152 {
4153    static char FuncName[]={"SUMA_Create_CommonFields"};
4154    SUMA_CommonFields *cf;
4155    int i, n, pb=-1;
4156    char *eee=NULL;
4157    float dsmw=5*60;
4158    SUMA_Boolean LocalHead = NOPE;
4159 
4160    /* This is the function that creates the debugging flags,
4161       do not use them here */
4162    cf = NULL;
4163 
4164    /* allocate */
4165    /* DO NOT USE SUMA_malloc here, too early for that */
4166    cf = (SUMA_CommonFields *)calloc(1,sizeof(SUMA_CommonFields));
4167 
4168    if (cf == NULL) {
4169       fprintf(SUMA_STDERR,"Error %s: Failed to allocate.\n", FuncName);
4170       return (cf);
4171    }
4172 
4173    cf->Dev = NOPE;
4174    cf->Fake_Cmap = NOPE;
4175    cf->InOut_Notify = NOPE;
4176    cf->Echo_KeyPress = NOPE;
4177    cf->InOut_Level = 0;
4178    cf->MemTrace = NOPE;
4179    cf->dcom = NULL;
4180    cf->N_dcom = 0;
4181    /* verify pointer size. I use INT_MAX and LONG_MAX
4182    to guess whether or not we have 64 bit pointers.
4183    I need to guess with #if to do proper type casting and
4184    avoid compiler warnings */
4185    cf->PointerSize = sizeof(void *);
4186    if (INT_MAX < LONG_MAX && cf->PointerSize < 8) {
4187       SUMA_S_Warn("Using INT_MAX and LONG_MAX fails to"
4188                   "guess pointer size.");
4189    }
4190 
4191    #ifdef USE_SUMA_MALLOC
4192    SUMA_SL_Err("NO LONGER SUPPORTED");
4193    return(NULL);
4194    cf->Mem = SUMA_Create_MemTrace();
4195    #else
4196    cf->Mem = NULL;
4197    #endif
4198 
4199 
4200    /* communications initialization happens in
4201       SUMA_init_ports_assignments() it cannot
4202       be done here because some parameters
4203       are not available yet.
4204       Setup here is to be sure there is no
4205       garbage lying around. */
4206    for (i=0; i<SUMA_MAX_STREAMS; ++i) {
4207       cf->ns_v[i] = NULL;
4208       cf->ns_to[i] = SUMA_WRITECHECKWAITMAX;
4209       cf->ns_flags_v[i] = 0;
4210       cf->Connected_v[i] = NOPE;
4211       cf->TrackingId_v[i] = 0;
4212       cf->NimlStream_v[i][0] = '\0';
4213       cf->HostName_v[i][0] = '\0';
4214       cf->TalkMode[i] = NI_BINARY_MODE;
4215       cf->TCP_port[i] = 0;
4216    }
4217    cf->Listening = NOPE;
4218    cf->niml_work_on = NOPE;
4219 
4220    /* viewer locking */
4221    for (i=0; i<SUMA_MAX_SURF_VIEWERS; ++i) {
4222       cf->Locked[i] = SUMA_I_Lock;
4223       if (SUMA_isEnv("SUMA_LockViewers","YES")) {
4224          cf->ViewLocked[i] = YUP;
4225       } else {
4226          cf->ViewLocked[i] = NOPE;
4227       }
4228    }
4229 
4230    eee = getenv("SUMA_SwapButtons_1_3");
4231    if (eee) {
4232       if (strcasecmp (eee, "YES") == 0) cf->SwapButtons_1_3 = YUP;
4233       else cf->SwapButtons_1_3 = NOPE;
4234    } else {
4235       cf->SwapButtons_1_3 = NOPE;
4236    }
4237 
4238    cf->X = (SUMA_X_AllView *)calloc(1,sizeof(SUMA_X_AllView));
4239    if (!cf->X) {
4240      fprintf(SUMA_STDERR,"Error %s: Failed to allocate.\n", FuncName);
4241      return (NULL);
4242    }
4243    cf->X->SumaCont = SUMA_CreateSumaContStruct();
4244    cf->X->DrawROI = SUMA_CreateDrawROIStruct();
4245    cf->X->AllMaskCont = NULL;
4246    cf->X->MaskStateID = 0;
4247    cf->X->DPY_controller1 = NULL;
4248    cf->X->Cr = (SUMA_GLCONTEXT_RECORD *)calloc(1, sizeof(SUMA_GLCONTEXT_RECORD));
4249    cf->X->Cr->last_context_DPY = NULL;
4250    cf->X->Cr->last_context_WDW = -1;
4251    cf->X->Cr->setting_function[0] = '\0';
4252    cf->X->Cr->widget_label[0] = '\0';
4253 
4254    eee = getenv("SUMA_ColorPattern");
4255    if (eee) {
4256       if (strcmp (eee, "AFNI") == 0) {
4257          cf->X->X_Resources = SXR_Afni;
4258          if (LocalHead) fprintf(SUMA_STDERR,"%s: Afni resources\n", FuncName);
4259       } else if (strcmp (eee, "EURO") == 0) {
4260          cf->X->X_Resources = SXR_Euro;
4261          if (LocalHead) fprintf(SUMA_STDERR,"%s: Euro resources\n", FuncName);
4262       } else if (strcmp (eee, "BONAIRE") == 0) {
4263          cf->X->X_Resources = SXR_Bonaire;
4264          if (LocalHead) fprintf(SUMA_STDERR,"%s: Bonaire resources\n", FuncName);
4265       } else if (strcmp (eee, "DEFAULT") == 0) {
4266          cf->X->X_Resources = SXR_default;
4267          if (LocalHead) fprintf(SUMA_STDERR,"%s: default resources\n", FuncName);
4268       } else if (strcmp (eee, "PRINT") == 0) {
4269          cf->X->X_Resources = SXR_Print;
4270          if (LocalHead) fprintf(SUMA_STDERR,"%s: Print resources\n", FuncName);
4271       } else {
4272          cf->X->X_Resources = SXR_Euro;
4273          fprintf(SUMA_STDERR,
4274                   "%s:\nUnrecognized option %s for SUMA_ColorPattern.\n"
4275                   "Using default = EURO\n", FuncName, eee);
4276       }
4277    } else {
4278       cf->X->X_Resources = SXR_Euro;
4279       if (LocalHead)
4280          fprintf( SUMA_STDERR,
4281                   "%s: Undefined environment. Using default\n", FuncName);
4282    }
4283 
4284    cf->X->Help_TextShell = NULL;
4285    cf->X->Help_Cmap_TextShell = NULL;
4286    cf->X->Help_Plot_TextShell = NULL;
4287    cf->X->Whereami_TextShell = NULL;
4288    cf->X->Log_TextShell = NULL;
4289    cf->X->FileSelectDlg = NULL;
4290    cf->X->N_ForeSmooth_prmpt = NULL;
4291    cf->X->N_FinalSmooth_prmpt = NULL;
4292    cf->X->Clip_prmpt = NULL;
4293    cf->X->ClipObj_prmpt = NULL;
4294    cf->X->TableTextFontList = NULL;
4295    cf->X->CommonSurfContTLW = NULL;
4296    cf->X->ButtonDown = 0;
4297    cf->X->roffx = -1; /* Not set */
4298    cf->X->roffy = -1; /* Not set */
4299    {
4300       char *eee = getenv("SUMA_WindowOffset");
4301       float fv3[3];
4302       if (eee) {
4303          if (!strcmp(eee,"Auto")) {
4304             cf->X->roffx = cf->X->roffy = -1;
4305          } else {
4306             if (SUMA_StringToNum (eee, (void *)fv3, 2,1) != 2) {
4307                SUMA_S_Err("Syntax error in environment\n"
4308                           "variable SUMA_WindowOffset of (%s). "
4309                           "Setting offset to 0", eee);
4310                cf->X->roffx = cf->X->roffy = 0;
4311             } else {
4312                cf->X->roffx = (int)fv3[0];
4313                cf->X->roffy = (int)fv3[1];
4314             }
4315          }
4316       } else { /* leave it for auto setup */
4317          cf->X->roffx = cf->X->roffy = -1;
4318       }
4319    }
4320    cf->X->SC_Notebook = NULL;
4321    cf->X->SameSurfContOpen = 0;
4322    {  /* Changed default to YES March 05 2014 */
4323       char *eee = getenv("SUMA_SameSurfCont");
4324       if (eee) {
4325          if (strcmp(eee,"NO") == 0) cf->X->UseSameSurfCont = NOPE;
4326          else if (strcmp(eee,"YES") == 0) cf->X->UseSameSurfCont = YUP;
4327          else {
4328             fprintf (SUMA_STDERR,
4329                      "Warning %s:\n"
4330                      "Bad value for environment variable UseSameSurfCont\n"
4331                      "Assuming default of YES", FuncName);
4332             cf->X->UseSameSurfCont = YUP;
4333          }
4334       } else cf->X->UseSameSurfCont = YUP;
4335    }
4336    {
4337       char *eee = getenv("SUMA_HomeAfterPrying");
4338       if (eee) {
4339          if (strcmp(eee,"NO") == 0) cf->Home_After_Prying = NOPE;
4340          else if (strcmp(eee,"YES") == 0) cf->Home_After_Prying = YUP;
4341          else {
4342             fprintf (SUMA_STDERR,
4343                      "Warning %s:\n"
4344                      "Bad value for environment variable SUMA_HomeAfterPrying\n"
4345                      "Assuming default of YES", FuncName);
4346             cf->Home_After_Prying = YUP;
4347          }
4348       } else cf->Home_After_Prying = YUP;
4349    }
4350    {
4351       char *eee = getenv("SUMA_NumForeSmoothing");
4352       if (eee) {
4353          int rotval = (int)strtod(eee, NULL);
4354          if (rotval >= 0) cf->X->NumForeSmoothing = rotval;
4355          else {
4356             fprintf (SUMA_STDERR,
4357                "Warning %s:\n"
4358                "Bad value for environment variable SUMA_NumForeSmoothing\n"
4359                "Assuming default of 0", FuncName);
4360             cf->X->NumForeSmoothing = 0;
4361          }
4362       } else cf->X->NumForeSmoothing = 0;
4363    }
4364 
4365    {
4366       char *eee = getenv("SUMA_NumFinalSmoothing");
4367       if (eee) {
4368          int rotval = (int)strtod(eee, NULL);
4369          if (rotval >= 0) cf->X->NumFinalSmoothing = rotval;
4370          else {
4371             fprintf (SUMA_STDERR,
4372                "Warning %s:\n"
4373                "Bad value for environment variable SUMA_NumFinalSmoothing\n"
4374                "Assuming default of 0", FuncName);
4375             cf->X->NumFinalSmoothing = 0;
4376          }
4377       } else cf->X->NumFinalSmoothing = 0;
4378    }
4379 
4380    {
4381       char *eee = getenv("SUMA_ThresholdScalePower");
4382       if (eee) {
4383          cf->SUMA_ThrScalePowerBias = (int)strtod(eee, NULL);
4384          if (cf->SUMA_ThrScalePowerBias < 2) {
4385             fprintf (SUMA_STDERR,   "Warning %s:\n"
4386                                     "Bad value for environment variable\n"
4387                                     "SUMA_ThresholdScalePower.\n"
4388                                     "Assuming default of 2", FuncName);
4389             cf->SUMA_ThrScalePowerBias = 2;
4390          }
4391       } else cf->SUMA_ThrScalePowerBias = 2;
4392    }
4393 
4394 
4395    {
4396       char *eee = getenv("SUMA_SnapshotOverSampling");
4397       if (eee) {
4398          cf->SUMA_SnapshotOverSampling = (int)strtod(eee, NULL);
4399          if (  cf->SUMA_SnapshotOverSampling < 1 ||
4400                cf->SUMA_SnapshotOverSampling>10) {
4401             fprintf (SUMA_STDERR,   "Warning %s:\n"
4402                                     "Bad value for environment variable\n"
4403                                     "SUMA_SnapshotOverSampling.\n"
4404                                     "Assuming default of 1", FuncName);
4405             cf->SUMA_SnapshotOverSampling = 1;
4406          }
4407       } else cf->SUMA_SnapshotOverSampling = 1;
4408    }
4409    {
4410       char *eee = getenv("SUMA_WarnBeforeClose");
4411       if (eee) {
4412          if (strcmp(eee,"NO") == 0) cf->X->WarnClose = NOPE;
4413          else if (strcmp(eee,"YES") == 0) cf->X->WarnClose = YUP;
4414          else {
4415             fprintf (SUMA_STDERR,
4416                      "Warning %s:\n"
4417                      "Bad value for environment variable SUMA_WarnBeforeClose\n"
4418                      "Assuming default of YES", FuncName);
4419             cf->X->WarnClose = YUP;
4420          }
4421       } else cf->X->WarnClose = YUP;
4422    }
4423    cf->X->SwitchCmapLst = NULL;
4424 
4425    cf->MessageList = SUMA_CreateMessageList ();
4426    #ifdef USE_SUMA_MALLOC
4427    SUMA_SL_Err("NO LONGER SUPPORTED");
4428    return(NULL);
4429    /*SUMA_ShowMemTrace (cf->Mem, NULL);*/
4430    #endif
4431    cf->ROI_mode = NOPE;
4432    cf->ROI_contmode = YUP;
4433    cf->Pen_mode = NOPE;
4434 
4435    cf->nimlROI_Datum_type =
4436       NI_rowtype_define("SUMA_NIML_ROI_DATUM", "int,int,int,int[#3]");
4437    if (cf->nimlROI_Datum_type < 0) {
4438       fprintf(SUMA_STDERR,"Error %s: Failed defining niml code.", FuncName);
4439       return(NULL);
4440    }
4441    if (LocalHead)
4442       fprintf(SUMA_STDERR, "%s: roi_type code = %d\n",
4443                   FuncName, cf->nimlROI_Datum_type) ;
4444 
4445    cf->ROI_CM = NULL;
4446    cf->ROI_FillMode = SUMA_ROI_FILL_TO_THISROI;
4447    cf->ROI2afni = NOPE;
4448 
4449    eee = getenv("SUMA_ColorMixingMode");
4450    if (eee) {
4451       if (strcmp (eee, "ORIG") == 0) {
4452          cf->ColMixMode = SUMA_ORIG_MIX_MODE;
4453       } else if (strcmp (eee, "MOD1") == 0) {
4454          cf->ColMixMode = SUMA_4AML;
4455       } else {
4456          cf->ColMixMode = SUMA_ORIG_MIX_MODE;
4457          fprintf(SUMA_STDERR,
4458                   "%s:\nUnrecognized option %s for SUMA_ColorMixingMode.\n"
4459                   "Using default = ORIG\n", FuncName, eee);
4460       }
4461    } else {
4462       cf->ColMixMode = SUMA_ORIG_MIX_MODE;
4463    }
4464 
4465 
4466    cf->GroupList = NULL;
4467    cf->N_Group = -1;
4468    SUMA_RegisterGroup(cf,"ANY"); /* register a default group that would
4469                                     match any group*/
4470 
4471    cf->scm = NULL;
4472    cf->DsetList = (DList *)SUMA_calloc(1,sizeof(DList));
4473    dlist_init (cf->DsetList, SUMA_FreeDset);
4474    {
4475       char *eee = getenv("SUMA_AllowDsetReplacement");
4476       if (eee) {
4477          if (strcmp(eee,"NO") == 0) cf->Allow_Dset_Replace = NOPE;
4478          else if (strcmp(eee,"YES") == 0) cf->Allow_Dset_Replace = YUP;
4479          else {
4480             fprintf (SUMA_STDERR,
4481                "Warning %s:\n"
4482                "Bad value for environment variable SUMA_AllowDsetReplacement\n"
4483                "Assuming default of YES", FuncName);
4484             cf->Allow_Dset_Replace = YUP;
4485          }
4486       } else cf->Allow_Dset_Replace = YUP;
4487    }
4488 
4489    cf->IgnoreVolreg = NOPE;
4490    cf->isGraphical = NOPE;
4491 
4492    cf->N_ClipPlanes = 0;
4493    for (i=0; i<SUMA_MAX_N_CLIP_PLANES; ++i) {
4494       cf->ClipPlanes[4*i] =
4495          cf->ClipPlanes[4*i+1] =
4496             cf->ClipPlanes[4*i+2] =
4497                cf->ClipPlanes[4*i+3]= 0.0;
4498       cf->ClipPlaneType[i] = SUMA_NO_CLIP_PLANE_TYPE;
4499       cf->ClipPlanesLabels[i][0]='\0';
4500    }
4501 
4502    for (i=0; i<SUMA_MAX_N_TIMER;++i) {
4503       cf->Timer[i].name[0] = '\0';
4504       cf->Timer[i].lastcall = -1.0;
4505    }
4506    cf->N_Timer = 0;
4507 
4508    {
4509       char *eee = getenv("SUMA_NoDuplicatesInRecorder");
4510       if (eee) {
4511          if (strcmp(eee,"NO") == 0) cf->NoDuplicatesInRecorder = 0;
4512          else if (strcmp(eee,"YES") == 0) cf->NoDuplicatesInRecorder = 1;
4513          else {
4514             fprintf (SUMA_STDERR,   "Warning %s:\n"
4515                                     "Bad value for environment variable:\n"
4516                                     "  SUMA_NoDuplicatesInRecorder\n"
4517                                     "Assuming default of YES", FuncName);
4518             cf->NoDuplicatesInRecorder = 1;
4519          }
4520       } else cf->NoDuplicatesInRecorder = 1;
4521    }
4522    /* if (SUMAg_CF->NoDuplicatesInRecorder)
4523             SNAP_NoDuplicates();
4524       else SNAP_OkDuplicates();
4525    */
4526    cf->cwd = SUMA_getcwd();
4527 
4528    {
4529       char *eee = getenv("SUMA_ColorMapRotationFraction");
4530       if (eee) {
4531          cf->CmapRotaFrac = atof(eee);
4532          if (cf->CmapRotaFrac < 0.01 || cf->CmapRotaFrac > 0.99) {
4533             SUMA_S_Warn(
4534                "Values for environment variable SUMA_ColorMapRotationFraction\n"
4535                "are outside valid range of [0.01 .. 0.99]. \n"
4536                "Setting value to default of 0.05.");
4537             cf->CmapRotaFrac = 0.05;
4538          }
4539       } else {
4540          cf->CmapRotaFrac = 0.05;
4541       }
4542    }
4543    {
4544       char *eee = getenv("SUMA_Transparency_Step");
4545       if (eee) {
4546          cf->TransModeStep = atof(eee);
4547          if (cf->TransModeStep < 1 || cf->TransModeStep > 8) {
4548             SUMA_S_Warn(
4549                "Values for environment variable SUMA_Transparency_Step\n"
4550                "are outside valid range of [1 .. 8]. \n"
4551                "Setting value to default of 4.");
4552             cf->TransModeStep = 4;
4553          }
4554       } else {
4555          cf->TransModeStep = 4;
4556       }
4557    }
4558 
4559    cf->xforms = (DList *)SUMA_calloc(1,sizeof(DList));
4560    dlist_init (cf->xforms, SUMA_FreeXform);
4561    cf->callbacks = (DList *)SUMA_calloc(1,sizeof(DList));
4562    dlist_init (cf->callbacks, SUMA_FreeCallback);
4563    cf->HoldClickCallbacks = 0;
4564    cf->PointerLastInViewer = -1;
4565 
4566    cf->giset = NULL;
4567    cf->ITset = NULL;
4568 
4569    cf->autorecord = SUMA_SetAutoRecord(getenv("SUMA_AutoRecordPrefix"));
4570 
4571    cf->SaveList = NULL;
4572 
4573    cf->YokeIntToNode = 0;
4574 
4575    cf->lev = NULL;
4576    return (cf);
4577 
4578 }
4579 
SUMA_SetAutoRecord(char * pref)4580 SUMA_PARSED_NAME *SUMA_SetAutoRecord(char *pref)
4581 {
4582    static char FuncName[]={"SUMA_SetAutoRecord"};
4583    SUMA_PARSED_NAME *pn=NULL;
4584 
4585    SUMA_ENTRY;
4586 
4587    if (!pref) SUMA_RETURN(SUMA_ParseFname("./autorecord", NULL));
4588 
4589    if (!(pn = SUMA_ParseFname(pref, NULL))) {
4590       SUMA_S_Errv("Failed to parse %s\n", pref);
4591       SUMA_RETURN(SUMA_ParseFname("./autorecord", NULL));
4592    }
4593 
4594 
4595    SUMA_RETURN(pn);
4596 }
4597 
4598 /*!
4599 \brief creates the structure for storing the radio buttons used to control viewer locking
4600    Do not use CommonFields structure here.
4601 
4602 */
SUMA_CreateLock_rbg(int N_rb_group,int N_but)4603 SUMA_rb_group *SUMA_CreateLock_rbg (int N_rb_group, int N_but)
4604 {
4605    static char FuncName[]={"SUMA_CreateLock_rbg"};
4606    SUMA_rb_group *Lock_rb;
4607 
4608    Lock_rb = (SUMA_rb_group *) calloc(1,sizeof(SUMA_rb_group));
4609    if (!Lock_rb) {
4610       fprintf (SUMA_STDERR,"Error %s: Failed to allocate.\n", FuncName);
4611       return(NULL);
4612    }
4613    Lock_rb->N_rb_group = N_rb_group;
4614    Lock_rb->N_but = N_but;
4615    Lock_rb->tb = (Widget *) calloc(N_rb_group*N_but, sizeof(Widget));
4616    Lock_rb->rb = (Widget *) calloc(N_rb_group, sizeof(Widget));
4617    Lock_rb->atb = (Widget *) calloc(N_but, sizeof(Widget));
4618    Lock_rb->arb = NULL;
4619    if (!Lock_rb->tb || !Lock_rb->rb || !Lock_rb->atb) {
4620       fprintf (SUMA_STDERR,"Error %s: Failed to allocate.\n", FuncName);
4621       return(NULL);
4622    }
4623    return(Lock_rb);
4624 
4625 }
4626 
4627 /*!
4628    free SUMA_rb_group *
4629    Do not use CommonFields structure here.
4630 */
SUMA_FreeLock_rbg(SUMA_rb_group * Lock_rb)4631 void * SUMA_FreeLock_rbg (SUMA_rb_group *Lock_rb)
4632 {
4633   static char FuncName[]={"SUMA_FreeLock_rb"};
4634 
4635   if (Lock_rb->rb) free(Lock_rb->rb);
4636   if (Lock_rb->tb) free(Lock_rb->tb);
4637   if (Lock_rb->atb) free (Lock_rb->atb);
4638   if (Lock_rb) free(Lock_rb);
4639 
4640   return (NULL);
4641 }
4642 
4643 /*!
4644    \brief DrawROI = SUMA_CreateDrawROIStruct();
4645    allocates and initializes structure of type
4646 
4647    \return SUMA_X_DrawROI *
4648 */
SUMA_CreateDrawROIStruct(void)4649 SUMA_X_DrawROI *SUMA_CreateDrawROIStruct (void)
4650 {
4651    static char FuncName[]={"SUMA_CreateDrawROIStruct"};
4652    SUMA_X_DrawROI *DrawROI = NULL;
4653 
4654    /* do not use commonfields related stuff here for obvious reasons */
4655    DrawROI = (SUMA_X_DrawROI *)calloc (1, sizeof(SUMA_X_DrawROI));
4656    DrawROI->AppShell = NULL;
4657    DrawROI->ROIval =
4658       (SUMA_ARROW_TEXT_FIELD *)calloc(1, sizeof(SUMA_ARROW_TEXT_FIELD));
4659    DrawROI->ROIlbl =
4660       (SUMA_ARROW_TEXT_FIELD *)calloc(1, sizeof(SUMA_ARROW_TEXT_FIELD));
4661    DrawROI->curDrawnROI = NULL;  /* DO NOT FREE THIS POINTER */
4662    DrawROI->SwitchROIlst = NULL;
4663    DrawROI->Delete_first = YUP;
4664    DrawROI->SaveMode = SW_DrawROI_SaveModeNIML;
4665    DrawROI->SaveWhat = SW_DrawROI_SaveWhatRelated;
4666    DrawROI->WhatDist = SW_DrawROI_WhatDistNothing;
4667    return (DrawROI);
4668 }
4669 
4670 /*!
4671    \brief SumaCont = SUMA_CreateSumaContStruct();
4672    allocates and initializes structure of type SUMA_X_SumaCont
4673    \return SUMA_X_SumaCont *
4674 
4675 */
SUMA_CreateSumaContStruct(void)4676 SUMA_X_SumaCont *SUMA_CreateSumaContStruct (void)
4677 {
4678    static char FuncName[]={"SUMA_CreateSumaContStruct"};
4679    SUMA_X_SumaCont *SumaCont = NULL;
4680    /* do not use commonfields related stuff here for obvious reasons */
4681    SumaCont = (SUMA_X_SumaCont *)calloc(1,sizeof(SUMA_X_SumaCont));
4682    SumaCont->AppShell = NULL;
4683    SumaCont->quit_pb = NULL;
4684    SumaCont->quit_first = YUP;
4685    SumaCont->Lock_rbg = SUMA_CreateLock_rbg (SUMA_MAX_SURF_VIEWERS, 3);
4686    if (!SumaCont->Lock_rbg) {
4687       fprintf (SUMA_STDERR,
4688                "Error %s: Failed in SUMA_CreateLock_rb.\n", FuncName);
4689       return (NULL);
4690    }
4691    SumaCont->LockView_tbg =
4692       (Widget *)calloc (SUMA_MAX_SURF_VIEWERS, sizeof(Widget));
4693    SumaCont->LockAllView_tb = NULL;
4694    SumaCont->SumaInfo_TextShell = NULL;
4695    return (SumaCont);
4696 }
4697 
4698 /*!
4699    \brief frees structure SUMA_X_SumaCont, returns null
4700 
4701 */
SUMA_FreeSumaContStruct(SUMA_X_SumaCont * SumaCont)4702 void *SUMA_FreeSumaContStruct (SUMA_X_SumaCont *SumaCont)
4703 {
4704    static char FuncName[]={"SUMA_FreeSumaContStruct"};
4705 
4706    /* do not use commonfields related stuff here for obvious reasons */
4707    if (SumaCont->Lock_rbg) SUMA_FreeLock_rbg (SumaCont->Lock_rbg);
4708    if (SumaCont->LockView_tbg) free (SumaCont->LockView_tbg);
4709    if (SumaCont->SumaInfo_TextShell) { SUMA_SL_Warn("SumaCont->SumaInfo_TextShell is not being freed") };
4710    if (SumaCont) free(SumaCont);
4711    return (NULL);
4712 }
4713 
4714 /*!
4715    \brief frees structure SUMA_X_DrawROI, returns null
4716 */
SUMA_FreeDrawROIStruct(SUMA_X_DrawROI * DrawROI)4717 void *SUMA_FreeDrawROIStruct (SUMA_X_DrawROI *DrawROI)
4718 {
4719    static char FuncName[]={"SUMA_FreeDrawROIStruct"};
4720 
4721    /* do not use commonfields related stuff here for obvious reasons,
4722    Well, you can, it is no big deal, memory tracing variables are wiped out at the end*/
4723    if (DrawROI->ROIval) free (DrawROI->ROIval);
4724    if (DrawROI->ROIlbl) free (DrawROI->ROIlbl);
4725    if (DrawROI->SwitchROIlst) SUMA_FreeScrolledList (DrawROI->SwitchROIlst);
4726    if (DrawROI) free(DrawROI);
4727 
4728    return (NULL);
4729 }
4730 /*!
4731    \brief ViewCont = SUMA_CreateViewContStruct();
4732    allocates and initializes structure of type SUMA_X_ViewCont
4733    \return SUMA_X_ViewCont *
4734 
4735 */
SUMA_CreateViewContStruct(void)4736 SUMA_X_ViewCont *SUMA_CreateViewContStruct (void)
4737 {
4738    static char FuncName[]={"SUMA_CreateViewContStruct"};
4739    SUMA_X_ViewCont *ViewCont = NULL;
4740    /* do not use commonfields related stuff here for obvious reasons */
4741    ViewCont = (SUMA_X_ViewCont *)calloc(1,sizeof(SUMA_X_ViewCont));
4742    ViewCont->TopLevelShell = NULL;
4743    ViewCont->ViewerInfo_TextShell = NULL;
4744    ViewCont->Info_lb = NULL;
4745    ViewCont->ViewerInfo_pb = NULL;
4746    ViewCont->Mainform = NULL;
4747    ViewCont->SwitchGrouplst = NULL;
4748    ViewCont->SwitchStatelst = NULL;
4749    ViewCont->ViewerInfo_pb = NULL;
4750    return (ViewCont);
4751 }
4752 
4753 /*!
4754    \brief frees structure SUMA_X_ViewCont, returns null
4755 
4756 */
SUMA_FreeViewContStruct(SUMA_X_ViewCont * ViewCont)4757 void *SUMA_FreeViewContStruct (SUMA_X_ViewCont *ViewCont)
4758 {
4759    static char FuncName[]={"SUMA_FreeViewContStruct"};
4760 
4761    /* do not use commonfields related stuff here for obvious reasons */
4762    if (ViewCont->TopLevelShell) {
4763       SUMA_SL_Warn("ViewCont->TopLevelShell is not being freed");
4764    }
4765    if (ViewCont->SwitchGrouplst)
4766       ViewCont->SwitchGrouplst = SUMA_FreeScrolledList(ViewCont->SwitchGrouplst);
4767    if (ViewCont->SwitchStatelst)
4768       ViewCont->SwitchStatelst = SUMA_FreeScrolledList(ViewCont->SwitchStatelst);
4769    if (ViewCont) free(ViewCont);
4770    return (NULL);
4771 }
4772 
4773 /*!
4774    \brief SurfCont = SUMA_CreateSurfContStruct();
4775    allocates and initializes structure of type SUMA_X_SurfCont
4776    \return SUMA_X_SurfCont *
4777 
4778    This function is now creating controllers for other types of
4779    displayable objects too.
4780 */
SUMA_CreateSurfContStruct(char * idcode_str,SUMA_DO_Types tp)4781 SUMA_X_SurfCont *SUMA_CreateSurfContStruct (char *idcode_str, SUMA_DO_Types tp)
4782 {
4783    static char FuncName[]={"SUMA_CreateSurfContStruct"};
4784    SUMA_X_SurfCont *SurfCont = NULL;
4785    char wname[64]={"UNNAMED"}, *s=NULL;
4786 
4787    /* do not use commonfields related stuff here for obvious reasons */
4788    SurfCont = (SUMA_X_SurfCont *)malloc(sizeof(SUMA_X_SurfCont));
4789    memset(SurfCont, 0, sizeof(SUMA_X_SurfCont));
4790 
4791    /* take care of linking fields */
4792    if (idcode_str) sprintf(SurfCont->owner_id, "%s", idcode_str);
4793    else SurfCont->owner_id[0] = '\0';
4794    SurfCont->N_links = 0;
4795    SurfCont->Open = 0;
4796    SurfCont->LinkedPtrType = SUMA_LINKED_SURFCONT_TYPE;
4797    SurfCont->do_type = tp;
4798 
4799    SurfCont->DsetMap_fr = NULL;
4800    SurfCont->ColPlane_fr = NULL;
4801    SurfCont->DispFrame = NULL;
4802    SurfCont->SurfFrame = NULL;
4803    SurfCont->Xhair_fr = NULL;
4804    SurfCont->TLS = NULL;
4805    SurfCont->Mainform = NULL;
4806    SurfCont->Page = NULL;
4807    SurfCont->SurfInfo_pb = NULL;
4808    SurfCont->SurfInfo_label = NULL;
4809    SurfCont->SurfInfo_TextShell = NULL;
4810    SurfCont->SurfContPage_label = NULL;
4811    SurfCont->SurfContPage =
4812       (SUMA_ARROW_TEXT_FIELD *)calloc(1, sizeof(SUMA_ARROW_TEXT_FIELD));
4813    SurfCont->NodeRadGainAF =
4814       (SUMA_ARROW_TEXT_FIELD *)calloc(1, sizeof(SUMA_ARROW_TEXT_FIELD));
4815    SurfCont->EdgeThickGainAF =
4816       (SUMA_ARROW_TEXT_FIELD *)calloc(1, sizeof(SUMA_ARROW_TEXT_FIELD));
4817    SurfCont->ColPlaneOrder =
4818       (SUMA_ARROW_TEXT_FIELD *)calloc(1, sizeof(SUMA_ARROW_TEXT_FIELD));
4819    SurfCont->ColPlaneOpacity =
4820       (SUMA_ARROW_TEXT_FIELD *)calloc(1, sizeof(SUMA_ARROW_TEXT_FIELD));
4821    SurfCont->ColPlaneDimFact =
4822       (SUMA_ARROW_TEXT_FIELD *)calloc(1, sizeof(SUMA_ARROW_TEXT_FIELD));
4823    SurfCont->ColPlaneAlphaThresh =
4824       (SUMA_ARROW_TEXT_FIELD *)calloc(1, sizeof(SUMA_ARROW_TEXT_FIELD));
4825    SurfCont->TractMaskGray =
4826       (SUMA_ARROW_TEXT_FIELD *)calloc(1, sizeof(SUMA_ARROW_TEXT_FIELD));
4827 
4828    s = SUMA_do_type_2_contwname(SurfCont->do_type);
4829    snprintf(wname,63,"%s->XhairTable", s);
4830    SurfCont->XhairTable = SUMA_AllocTableField(wname);
4831    snprintf(wname,63,"%s->MaskTable", s);
4832    SurfCont->MaskTable = SUMA_AllocTableField(wname);
4833    snprintf(wname,63,"%s->MaskEvalTable", s);
4834    SurfCont->MaskEvalTable = SUMA_AllocTableField(wname);
4835    SurfCont->MaskEval_tb = NULL;
4836    snprintf(wname,63,"%s->MaskLenTable", s);
4837    SurfCont->MaskLenTable = SUMA_AllocTableField(wname);
4838    SurfCont->MaskLen_tb = NULL;
4839    SurfCont->UseMaskEval = 0;
4840    SurfCont->DeleteMask_pb = NULL;
4841    SurfCont->DeleteMask_first = YUP;
4842    SurfCont->DeleteMask_row = -1;
4843    snprintf(wname,63,"%s->SetRangeTable", s);
4844    SurfCont->SetRangeTable = SUMA_AllocTableField(wname);
4845    snprintf(wname,63,"%s->SetThrScaleTable", s);
4846    SurfCont->SetThrScaleTable = SUMA_AllocTableField(wname);
4847    snprintf(wname,63,"%s->RangeTable", s);
4848    SurfCont->RangeTable = SUMA_AllocTableField(wname);
4849    snprintf(wname,63,"%s->NodeTable", s);
4850    SurfCont->NodeTable = SUMA_AllocTableField(wname);
4851    snprintf(wname,63,"%s->FaceTable", s);
4852    SurfCont->FaceTable = SUMA_AllocTableField(wname);
4853    snprintf(wname,63,"%s->DataTable", s);
4854    SurfCont->DataTable = SUMA_AllocTableField(wname);
4855    snprintf(wname,63,"%s->LabelTable", s);
4856    SurfCont->LabelTable = SUMA_AllocTableField(wname);
4857    /* SurfCont->ColPlaneShow_tb = NULL; Obsolete */
4858    SurfCont->ColPlaneShowOneFore_tb = NULL;
4859    SurfCont->SymIrange_tb = NULL;
4860    SurfCont->AbsThresh_tb = NULL;
4861    SurfCont->ShowZero_tb = NULL;
4862    SurfCont->SwitchDsetlst = NULL;
4863    snprintf(wname,63,"%s->ColPlaneLabelTable", s);
4864    SurfCont->ColPlaneLabelTable = SUMA_AllocTableField(wname);
4865    snprintf(wname,63,"%s->SetClustTable", s);
4866    SurfCont->SetClustTable = SUMA_AllocTableField(wname);
4867    snprintf(wname,63,"%s->Ax_slc", s);
4868    SurfCont->Ax_slc = SUMA_AllocSliceField(wname);
4869    snprintf(wname,63,"%s->Sa_slc", s);
4870    SurfCont->Sa_slc = SUMA_AllocSliceField(wname);
4871    snprintf(wname,63,"%s->Co_slc", s);
4872    SurfCont->Co_slc = SUMA_AllocSliceField(wname);
4873    snprintf(wname,63,"%s->VR", s);
4874    SurfCont->VR_fld = SUMA_AllocVRField(wname);
4875    SurfCont->curColPlane = NULL;
4876    {
4877       char *eee = getenv("SUMA_ShowOneOnly");
4878       if (eee) {
4879          SUMA_TO_LOWER(eee);
4880          if (strcmp (eee, "yes") == 0) SurfCont->ShowCurForeOnly = YUP;
4881             else SurfCont->ShowCurForeOnly = NOPE;
4882       } else {
4883          SurfCont->ShowCurForeOnly = YUP;
4884       }
4885    }
4886    {
4887       char *eee = getenv("SUMA_GraphHidden");
4888       if (eee) {
4889          SUMA_TO_LOWER(eee);
4890          if (strcmp (eee, "yes") == 0) SurfCont->GraphHidden = YUP;
4891             else SurfCont->GraphHidden = NOPE;
4892       } else {
4893          SurfCont->GraphHidden = YUP;
4894       }
4895    }
4896 
4897    SurfCont->prv_curDOp = (void **)calloc(1, sizeof(void*));
4898    SurfCont->prv_variant = NULL;
4899    SurfCont->PosRef = NULL;
4900    SurfCont->cmp_ren =
4901       (SUMA_CMAP_RENDER_AREA *)SUMA_calloc(1, sizeof(SUMA_CMAP_RENDER_AREA));
4902    SurfCont->cmp_ren->CrappyDrawable = 0;
4903    SurfCont->cmp_ren->cmap_wid = NULL;
4904    SurfCont->cmp_ren->FOV = SUMA_CMAP_FOV_INITIAL;
4905    SurfCont->cmp_ren->cmap_context = NULL;
4906    SurfCont->cmp_ren->translateVec[0] =
4907    SurfCont->cmp_ren->translateVec[0] =
4908    SurfCont->cmp_ren->translateVec[1] = 0.0;
4909    SurfCont->thr_sc = NULL;
4910    SurfCont->brt_sc = NULL;
4911    SurfCont->thr_lb = NULL;
4912    SurfCont->thrstat_lb = NULL;
4913    SurfCont->cmaptit_lb = NULL;
4914    SurfCont->cmapswtch_pb = NULL;
4915    SurfCont->CmapLoad_pb = NULL;
4916    SurfCont->SwitchIntMenu = NULL;
4917    SurfCont->SwitchBrtMenu = NULL;
4918    SurfCont->SwitchThrMenu = NULL;
4919    #if 0 /* Now in SwitchIntMenu */
4920    SurfCont->SwitchIntLst = NULL;
4921    SurfCont->SwitchThrLst = NULL;
4922    SurfCont->SwitchBrtLst = NULL;
4923    SurfCont->SwitchIntArrow = NULL;
4924    SurfCont->SwitchBrtArrow = NULL;
4925    SurfCont->SwitchThrArrow = NULL;
4926    #endif
4927    SurfCont->SwitchCmapMenu = NULL;
4928    SurfCont->Fake_pbar = NULL;
4929    SurfCont->rc_CmapCont = NULL;
4930    SurfCont->CoordBiasMenu = SUMA_Alloc_Menu_Widget(SW_N_CoordBias);
4931    SurfCont->LinkModeMenu = SUMA_Alloc_Menu_Widget(SW_N_LinkMode);
4932    SurfCont->CmapModeMenu = SUMA_Alloc_Menu_Widget(SW_N_CmapMode);
4933    SurfCont->opts_rc = NULL;
4934    SurfCont->opts_form = NULL;
4935    SurfCont->rcvo = NULL;
4936    SurfCont->rcsw = NULL;
4937    SurfCont->rcsw_v1 = NULL;
4938    SurfCont->rcsw_v2 = NULL;
4939    SurfCont->rcswr = NULL;
4940    SurfCont->rccm = NULL;
4941    SurfCont->rccm_swcmap = NULL;
4942    SurfCont->IntRange_lb = NULL;
4943    SurfCont->Int_tb = NULL;
4944    SurfCont->Thr_tb = NULL;
4945    SurfCont->Brt_tb = NULL;
4946    SurfCont->IntRangeLocked = 0;
4947    SurfCont->BrtRangeLocked = 0;
4948    SurfCont->rcclust = NULL;
4949 
4950    SurfCont->tract_length_mask[0] = 0.0;
4951       /* SUMA_floatEnv("TEMP_MIN_LENGTH", 0.0); */
4952    SurfCont->tract_length_mask[1] = -1.0;
4953       /* SUMA_floatEnv("TEMP_MAX_LENGTH", -1.0); */
4954    if (SurfCont->tract_length_mask[1]>=
4955        SurfCont->tract_length_mask[0])
4956       SurfCont->UseMaskLen = 0; /* leave it off, let it be activated in GUI */
4957    else
4958       SurfCont->UseMaskLen = 0;
4959 
4960    return (SurfCont);
4961 }
4962 
SUMA_GlobalMaskContStruct(char * idcode)4963 SUMA_X_SurfCont *SUMA_GlobalMaskContStruct(char *idcode)
4964 {
4965    static char FuncName[]={"SUMA_GlobalMaskContStruct"};
4966    if (!SUMAg_CF->X->AllMaskCont) {
4967       if (!(SUMAg_CF->X->AllMaskCont =
4968                SUMA_CreateSurfContStruct(idcode, MASK_type))){
4969          fprintf(SUMA_STDERR,
4970                  "Error %s: Failed to create global mask controller struct",
4971                  FuncName);
4972          return(NULL);
4973       }
4974    }
4975    /* Return a link to that struct */
4976    return((SUMA_X_SurfCont*)
4977                      SUMA_LinkToPointer((void *)SUMAg_CF->X->AllMaskCont));
4978 }
4979 
4980 /*!
4981    \brief frees structure SUMA_X_SurfCont, returns null
4982 
4983 */
SUMA_FreeSurfContStruct(SUMA_X_SurfCont * SurfCont)4984 void *SUMA_FreeSurfContStruct (SUMA_X_SurfCont *SurfCont)
4985 {
4986    static char FuncName[]={"SUMA_FreeSurfContStruct"};
4987 
4988    /* do not use commonfields related stuff here for obvious reasons */
4989    if (!SurfCont) return(NULL);
4990 
4991    if (SurfCont->N_links) {
4992       SurfCont = (SUMA_X_SurfCont*)SUMA_UnlinkFromPointer((void *)SurfCont);
4993       return (NULL);
4994    }
4995 
4996    /* no more links, go for it */
4997    if (SurfCont->TractMaskGray) free (SurfCont->TractMaskGray);
4998    if (SurfCont->SurfContPage) free (SurfCont->SurfContPage);
4999    if (SurfCont->NodeRadGainAF) free (SurfCont->NodeRadGainAF);
5000    if (SurfCont->EdgeThickGainAF) free (SurfCont->EdgeThickGainAF);
5001    if (SurfCont->ColPlaneOrder) free (SurfCont->ColPlaneOrder);
5002    if (SurfCont->ColPlaneOpacity) free (SurfCont->ColPlaneOpacity);
5003    if (SurfCont->ColPlaneDimFact) free (SurfCont->ColPlaneDimFact);
5004    if (SurfCont->ColPlaneAlphaThresh) free (SurfCont->ColPlaneAlphaThresh);
5005    if (SurfCont->SetRangeTable) SUMA_FreeTableField (SurfCont->SetRangeTable);
5006    if (SurfCont->RangeTable) SUMA_FreeTableField (SurfCont->RangeTable);
5007    if (SurfCont->MaskTable) SUMA_FreeTableField (SurfCont->MaskTable);
5008    if (SurfCont->MaskEvalTable) SUMA_FreeTableField (SurfCont->MaskEvalTable);
5009    if (SurfCont->MaskLenTable) SUMA_FreeTableField (SurfCont->MaskLenTable);
5010    if (SurfCont->XhairTable) SUMA_FreeTableField (SurfCont->XhairTable);
5011    if (SurfCont->NodeTable) SUMA_FreeTableField (SurfCont->NodeTable);
5012    if (SurfCont->FaceTable) SUMA_FreeTableField (SurfCont->FaceTable);
5013    if (SurfCont->DataTable) SUMA_FreeTableField (SurfCont->DataTable);
5014    if (SurfCont->LabelTable) SUMA_FreeTableField (SurfCont->LabelTable);
5015    if (SurfCont->Ax_slc) SUMA_FreeSliceField (SurfCont->Ax_slc);
5016    if (SurfCont->Sa_slc) SUMA_FreeSliceField (SurfCont->Sa_slc);
5017    if (SurfCont->Co_slc) SUMA_FreeSliceField (SurfCont->Co_slc);
5018    if (SurfCont->VR_fld) SUMA_FreeVRField (SurfCont->VR_fld);
5019    if (SurfCont->ColPlaneLabelTable)
5020       SUMA_FreeTableField (SurfCont->ColPlaneLabelTable);
5021    if (SurfCont->SetClustTable) SUMA_FreeTableField (SurfCont->SetClustTable);
5022    if (SurfCont->SwitchDsetlst) SUMA_FreeScrolledList (SurfCont->SwitchDsetlst);
5023    if (SurfCont->SurfInfo_TextShell) {
5024       SUMA_SL_Warn("SurfCont->SurfInfo_TextShell is not being freed") };
5025    SurfCont->SwitchIntMenu = SUMA_Free_Menu_Widget(SurfCont->SwitchIntMenu);
5026    SurfCont->SwitchThrMenu = SUMA_Free_Menu_Widget(SurfCont->SwitchThrMenu);
5027    SurfCont->SwitchBrtMenu = SUMA_Free_Menu_Widget(SurfCont->SwitchBrtMenu);
5028    SurfCont->SwitchCmapMenu = SUMA_Free_Menu_Widget(SurfCont->SwitchCmapMenu);
5029    SurfCont->DsetNodeRadMenu = SUMA_Free_Menu_Widget(SurfCont->DsetNodeRadMenu);
5030    SurfCont->DsetEdgeThickMenu =
5031                               SUMA_Free_Menu_Widget(SurfCont->DsetEdgeThickMenu);
5032    SurfCont->DsetEdgeStipMenu =
5033                               SUMA_Free_Menu_Widget(SurfCont->DsetEdgeStipMenu);
5034    SurfCont->TractStyleMenu =
5035                               SUMA_Free_Menu_Widget(SurfCont->TractStyleMenu);
5036    SurfCont->DsetAlphaValMenu =
5037                               SUMA_Free_Menu_Widget(SurfCont->DsetAlphaValMenu);
5038    SurfCont->TractMaskMenu = SUMA_Free_Menu_Widget(SurfCont->TractMaskMenu);
5039    if (SurfCont->prv_curDOp) free(SurfCont->prv_curDOp);
5040    if (SurfCont->prv_variant) free(SurfCont->prv_variant);
5041    if (SurfCont->cmp_ren) free(SurfCont->cmp_ren);
5042    if (SurfCont) free(SurfCont);
5043    return (NULL);
5044 }
5045 
SUMA_Free_Menu_Widget(SUMA_MENU_WIDGET * smw)5046 SUMA_MENU_WIDGET *SUMA_Free_Menu_Widget(SUMA_MENU_WIDGET *smw)
5047 {
5048    static char FuncName[]={"SUMA_Free_Menu_Widget"};
5049    if (!smw) return(NULL);
5050    if (smw->mw) {
5051       XtDestroyWidget(smw->mw[0]);
5052       SUMA_free(smw->mw);
5053    }
5054    if (smw->lw) {
5055       SUMA_cb_CloseSwitchLst (NULL, (XtPointer)smw->lw, NULL);
5056       smw->lw = SUMA_FreeScrolledList(smw->lw);
5057    }
5058    if (smw) SUMA_free(smw);
5059    return(NULL);
5060 }
5061 
SUMA_Alloc_Menu_Widget(int nw)5062 SUMA_MENU_WIDGET *SUMA_Alloc_Menu_Widget(int nw)
5063 {
5064    SUMA_MENU_WIDGET *smw=NULL;
5065    smw = (SUMA_MENU_WIDGET *)SUMA_calloc(1, sizeof(SUMA_MENU_WIDGET));
5066    if (nw) {
5067       smw->mw = (Widget *)SUMA_calloc(nw, sizeof(Widget));
5068       smw->N_mw = nw;
5069    }
5070    return(smw);
5071 }
5072 
5073 /*! free SUMA_CommonFields
5074 NOTE: the SUMA_CommonFields * itself is not freed. You'll have to free it manually with free function;
5075 \sa SUMA_Create_CommonFields
5076 */
SUMA_Free_CommonFields(SUMA_CommonFields * cf)5077 SUMA_Boolean SUMA_Free_CommonFields (SUMA_CommonFields *cf)
5078 {
5079    static char FuncName[]={"SUMA_Free_CommonFields"};
5080    int i;
5081 
5082    /* do not use commonfields related stuff here for obvious reasons */
5083    if (cf->cwd) SUMA_free(cf->cwd); cf->cwd = NULL;
5084    if (cf->GroupList) {
5085       for (i=0; i< cf->N_Group; ++i)
5086          if (cf->GroupList[i]) SUMA_free(cf->GroupList[i]);
5087       SUMA_free(cf->GroupList); cf->GroupList = NULL;
5088    }
5089    #if 0 /* not anymore!, that is now a pointer copy */
5090    if (cf->ROI_CM) SUMA_Free_ColorMap(cf->ROI_CM); /* free the colormap */
5091    #endif
5092    cf->ROI_CM = NULL;
5093    if (cf->X->FileSelectDlg)
5094       SUMA_FreeFileSelectionDialogStruct(cf->X->FileSelectDlg);
5095    cf->X->FileSelectDlg = NULL;
5096    if (cf->X->AllMaskCont) SUMA_FreeSurfContStruct(cf->X->AllMaskCont);
5097    SUMA_ifree(cf->X->Cr);
5098    for (i=0; i<cf->N_dcom; ++i) { SUMA_ifree(cf->dcom[i]); }
5099    SUMA_ifree(cf->dcom);
5100 
5101    if (cf->X->SumaCont)
5102       SUMA_FreeSumaContStruct (cf->X->SumaCont);
5103    SUMA_free_DocumentedWidgets();
5104 
5105    cf->X->SumaCont = NULL;
5106    if (cf->X->DrawROI)
5107       SUMA_FreeDrawROIStruct (cf->X->DrawROI);
5108    cf->X->DrawROI = NULL;
5109    if (cf->X->N_ForeSmooth_prmpt)
5110       SUMA_FreePromptDialogStruct (cf->X->N_ForeSmooth_prmpt);
5111    cf->X->N_ForeSmooth_prmpt = NULL;
5112    if (cf->X->N_FinalSmooth_prmpt)
5113       SUMA_FreePromptDialogStruct (cf->X->N_FinalSmooth_prmpt);
5114    cf->X->N_FinalSmooth_prmpt = NULL;
5115    if (cf->X->Clip_prmpt)
5116       SUMA_FreePromptDialogStruct (cf->X->Clip_prmpt);
5117    cf->X->Clip_prmpt = NULL;
5118    if (cf->X->ClipObj_prmpt)
5119       SUMA_FreePromptDialogStruct (cf->X->ClipObj_prmpt);
5120    cf->X->ClipObj_prmpt = NULL;
5121    if (cf->X->SwitchCmapLst) SUMA_FreeScrolledList (cf->X->SwitchCmapLst);
5122    if (cf->X) free(cf->X); cf->X = NULL;
5123    if (cf->MessageList)
5124       SUMA_EmptyDestroyList(cf->MessageList);
5125    cf->MessageList = NULL;
5126    if (cf->scm) cf->scm = SUMA_DestroyAfniColors (cf->scm); cf->scm = NULL;
5127    if (cf->DsetList) {
5128       dlist_destroy(cf->DsetList);  SUMA_free(cf->DsetList);
5129       cf->DsetList = NULL;
5130    }
5131    if (cf->xforms) {
5132       dlist_destroy(cf->xforms); SUMA_free(cf->xforms);
5133    }
5134    if (cf->callbacks) {
5135       dlist_destroy(cf->callbacks); SUMA_free(cf->callbacks);
5136    }
5137    #ifdef USE_SUMA_MALLOC
5138    SUMA_SL_Err("NO LONGER SUPPORTED");
5139    return(NOPE);
5140    if (cf->Mem) SUMA_Free_MemTrace (cf->Mem); cf->Mem = NULL;/* always free this right before the end */
5141    #endif
5142 
5143 
5144    if (cf->giset) {
5145       if (cf->giset->dset) {
5146          SUMA_S_Warn("dset is not being freed");
5147       }
5148       DESTROY_GICOR_setup(cf->giset); cf->giset=NULL;
5149    }
5150 
5151    if (cf->ITset) {
5152       Free_Insta_Tract_Setup(cf->ITset);
5153       SUMA_ifree(cf->ITset);
5154    }
5155 
5156    if (cf->autorecord) {
5157       cf->autorecord = SUMA_Free_Parsed_Name(cf->autorecord);
5158    }
5159 
5160    if (cf->SaveList) {
5161       dlist_destroy(cf->SaveList); SUMA_free(cf->SaveList);
5162    }
5163 
5164    if (cf->lev) {
5165       SUMA_free(cf->lev); cf->lev = NULL;
5166    }
5167 
5168    /* if (cf) free(cf); */ /* don't free this stupid pointer since it is used
5169                         when main returns with SUMA_ RETURN
5170                         (typo on purpose to avoid upsetting AnalyzeTrace.
5171                         It is not quite a leak since the OS will clean it up
5172                         after exit Thu Apr  8 2004*/
5173 
5174    return (YUP);
5175 }
5176 
SUMA_Show_Clip_Planes(SUMA_CommonFields * cf,FILE * out)5177 void SUMA_Show_Clip_Planes (SUMA_CommonFields *cf, FILE *out)
5178 {
5179    static char FuncName[]={"SUMA_Show_Clip_Planes"};
5180    char *s=NULL;
5181 
5182    SUMA_ENTRY;
5183 
5184    s = SUMA_Show_Clip_Planes_Info (cf);
5185 
5186 /*    //Don't output number of planes or their equations
5187    if (!out) fprintf(SUMA_STDERR,"%s", s);
5188    else fprintf(out,"%s", s);
5189 */
5190 
5191    SUMA_free(s);
5192 
5193    SUMA_RETURNe;
5194 }
5195 
SUMA_Clip_Type_to_Clip_Name(SUMA_CLIP_PLANE_TYPES tp)5196 const char * SUMA_Clip_Type_to_Clip_Name (SUMA_CLIP_PLANE_TYPES tp)
5197 {
5198    switch (tp) {
5199       case SUMA_NO_CLIP_PLANE_TYPE:
5200          return("No_type");
5201       case SUMA_SCREEN_CLIP:
5202          return("Screen_Clip");
5203       case SUMA_ALL_OBJECT_CLIP:
5204          return("All_Objects_Clip");
5205       default:
5206          return("Bad value");
5207    }
5208 }
5209 
SUMA_Show_Clip_Planes_Info(SUMA_CommonFields * cf)5210 char * SUMA_Show_Clip_Planes_Info (SUMA_CommonFields *cf)
5211 {
5212    static char FuncName[]={"SUMA_Show_Clip_Planes_Info"};
5213    int i;
5214    char *s=NULL;
5215    SUMA_STRING *SS=NULL;
5216 
5217    SUMA_ENTRY;
5218 
5219    SS = SUMA_StringAppend_va(NULL, NULL);
5220 
5221    if (cf == NULL) {
5222       SS = SUMA_StringAppend_va(SS," NULL cf structure.\n");
5223       SS = SUMA_StringAppend_va(SS, NULL);
5224       s = SS->s; SUMA_free(SS); SS= NULL;
5225       SUMA_RETURN(s);
5226    }
5227 
5228    SS = SUMA_StringAppend_va(SS," Number of Clip Planes: %d\n", cf->N_ClipPlanes);
5229    for (i=0; i<cf->N_ClipPlanes; ++i) {
5230       SS = SUMA_StringAppend_va(SS," %d: Clip plane >>%s<< of type %s. Eq: %.4fX + %.4fY + %.4fZ + %.4f = 0\n",
5231                      i, cf->ClipPlanesLabels[i], SUMA_Clip_Type_to_Clip_Name(cf->ClipPlaneType[i]),
5232                      (float)cf->ClipPlanes[4*i], (float)cf->ClipPlanes[4*i+1], (float)cf->ClipPlanes[4*i+2], (float)cf->ClipPlanes[4*i+3]);
5233    }
5234 
5235    SS = SUMA_StringAppend_va(SS, NULL);
5236    s = SS->s; SUMA_free(SS); SS= NULL;
5237 
5238    SUMA_RETURN(s);
5239 }
5240 
SUMA_Show_CommonFields(SUMA_CommonFields * cf,FILE * out)5241 void SUMA_Show_CommonFields (SUMA_CommonFields *cf, FILE *out)
5242 {
5243    static char FuncName[]={"SUMA_Show_CommonFields"};
5244    char *s=NULL;
5245 
5246    SUMA_ENTRY;
5247 
5248    s = SUMA_CommonFieldsInfo (cf,1);
5249 
5250    if (!out) fprintf(SUMA_STDERR,"%s", s);
5251    else fprintf(out,"%s", s);
5252 
5253    SUMA_free(s);
5254 
5255    SUMA_RETURNe;
5256 }
5257 
SUMA_CommonFieldsInfo(SUMA_CommonFields * cf,int detail)5258 char * SUMA_CommonFieldsInfo (SUMA_CommonFields *cf, int detail)
5259 {
5260    static char FuncName[]={"SUMA_CommonFieldsInfo"};
5261    int i;
5262    char *s=NULL;
5263    SUMA_DSET *dset=NULL;
5264    DListElmt *el=NULL;
5265    SUMA_STRING *SS=NULL;
5266 
5267    SUMA_ENTRY;
5268 
5269    SS = SUMA_StringAppend_va(NULL, NULL);
5270 
5271    if (cf == NULL) {
5272       SS = SUMA_StringAppend_va(SS," NULL cf structure.\n");
5273       SS = SUMA_StringAppend_va(SS, NULL);
5274       s = SS->s; SUMA_free(SS); SS= NULL;
5275       SUMA_RETURN(s);
5276    }
5277 
5278    SS = SUMA_StringAppend_va(SS,"   CWD: %s\n", cf->cwd);
5279    for (i=0; i < SUMA_MAX_STREAMS; ++i) {
5280       SS = SUMA_StringAppend_va(SS,"   HostName: %s\n", cf->HostName_v[i]);
5281       SS = SUMA_StringAppend_va(SS,"   NimlStream: %s\n", cf->NimlStream_v[i]);
5282    }
5283 
5284    if (cf->X) {
5285       SS = SUMA_StringAppend_va(SS,"   X struct\n",
5286                        "   NumForeSmoothing %d, NumFinalSmmothing %d\n"
5287                        "   WarnClose %d, UseSameSurfCont %d, \n"
5288                        "   SameSurfContOpen %d ButtonDown %d, WinOffsets %d %d\n"
5289                        , cf->X->NumForeSmoothing, cf->X->NumFinalSmoothing,
5290                        cf->X->WarnClose, cf->X->UseSameSurfCont,
5291                        cf->X->SameSurfContOpen, cf->X->ButtonDown,
5292                        cf->X->roffx, cf->X->roffy);
5293    } else {
5294       SS = SUMA_StringAppend(SS,"   NULL X struct\n");
5295    }
5296    SS = SUMA_StringAppend_va(SS,"   Available Groups: %d\n", cf->N_Group);
5297    for (i=0; i<cf->N_Group; ++i) {
5298       SS = SUMA_StringAppend_va(SS,"      Group[%d]: %s\n", i, cf->GroupList[i]);
5299    }
5300 
5301    #ifdef USE_SUMA_MALLOC
5302       SUMA_SL_Err("NO LONGER SUPPORTED");
5303       SUMA_RETURN(NULL);
5304    #else
5305       SS = SUMA_StringAppend_va(SS,"   DBG_trace = %d\n", DBG_trace);
5306       SS = SUMA_StringAppend_va(SS,"   InOut_Notify = %d\n", cf->InOut_Notify);
5307       SS = SUMA_StringAppend_va(SS,"   Echo_KeyPress = %d\n", cf->Echo_KeyPress);
5308       SS = SUMA_StringAppend_va(SS,"   MemTrace = %d\n", cf->MemTrace);
5309    #endif
5310       SS = SUMA_StringAppend_va(SS,"   PointerSize = %d\n", cf->PointerSize);
5311 
5312    /* add the displayable objects Info */
5313    s = SUMA_DOv_Info(SUMAg_DOv, SUMAg_N_DOv, 0);
5314    SS = SUMA_StringAppend_va(SS, "%s\n", s); SUMA_free(s); s = NULL;
5315 
5316    if (cf->DsetList) {
5317       SS = SUMA_StringAppend_va( SS, "DsetList (Allow Replacement = %d):\n",
5318                                  cf->Allow_Dset_Replace);
5319       el = NULL;
5320       do {
5321          if (!el) el = dlist_head(cf->DsetList);
5322          else el = dlist_next(el);
5323          if (el) {
5324             dset = (SUMA_DSET *)el->data;
5325             if (!dset) {
5326                SUMA_SLP_Err("Unexpected NULL dset element in list!\n"
5327                          "Please report this occurrence to saadz@mail.nih.gov.");
5328             } else {
5329               s = SUMA_DsetInfo (dset,0);
5330               SS = SUMA_StringAppend_va(SS, "\n%s\n", s); SUMA_free(s); s = NULL;
5331             }
5332          } else {
5333             SUMA_S_Err("Unexpected nullness");
5334          }
5335       } while ( (el != dlist_tail(cf->DsetList)));
5336    } else {
5337       SS = SUMA_StringAppend_va(SS, "NULL DsetList\n");
5338    }
5339 
5340    SS = SUMA_StringAppend_va( SS,
5341                               "SUMA's list of environment variables:\n");
5342    s = SUMA_env_list_help(0, TXT);
5343    SS = SUMA_StringAppend( SS, s); SUMA_free(s); s = NULL;
5344    SS = SUMA_StringAppend( SS, "\n");
5345 
5346    /* add the colormap info */
5347    if (cf->scm) {
5348       SS = SUMA_StringAppend(SS, "   Colormaps:\n");
5349       s = SUMA_ColorMapVec_Info (cf->scm->CMv,
5350                               cf->scm->N_maps, detail);
5351       SS = SUMA_StringAppend_va( SS, "%s\n",s); SUMA_free(s); s = NULL;
5352    } else {
5353       SS = SUMA_StringAppend_va(SS, "   No Colormaps.\n");
5354    }
5355 
5356    /* add xforms and callbacks */
5357    s = SUMA_Xforms_Info(cf->xforms, detail);
5358    SS = SUMA_StringAppend_va( SS, "%s\n",s); SUMA_free(s); s = NULL;
5359    s = SUMA_Callbacks_Info(cf->callbacks, detail);
5360    SS = SUMA_StringAppend_va( SS, "%s\n",s); SUMA_free(s); s = NULL;
5361 
5362    SS = SUMA_StringAppend_va(SS,
5363                 "Pointer last seen in viewer: %d\n", cf->PointerLastInViewer);
5364 
5365    s = SUMA_GISET_Info(cf->giset, 0);
5366 
5367    SS = SUMA_StringAppend_va(SS, "%s\n",s); SUMA_free(s); s = NULL;
5368 
5369    SS = SUMA_StringAppend_va(SS, "autorecord: %s\n",
5370                   cf->autorecord ? cf->autorecord->FullName:"NULL");
5371 
5372    SS = SUMA_StringAppend_va(SS, "SaveList: %d elements\n",
5373                   cf->SaveList ? dlist_size(cf->SaveList):0);
5374 
5375    SS = SUMA_StringAppend_va(SS, "Documented Widgets:\n%s",
5376                      SUMA_get_DocumentedWidgets() ?
5377                         SUMA_get_DocumentedWidgets():"NULL");
5378    /* clean up */
5379    SS = SUMA_StringAppend_va(SS, NULL);
5380    s = SS->s; SUMA_free(SS); SS= NULL;
5381 
5382    SUMA_RETURN(s);
5383 }
5384 
5385 /*!
5386    This function determines the most suitable standard view of a surface viewer
5387    This is based on the surface objects being displayed and
5388    their embedding dimension.
5389    The highest Embedding dimension of the lot determines what view to use
5390    ans = SUMA_BestStandardView (SUMA_SurfaceViewer *sv, SUMA_DO *dov, int N_dov)
5391 
5392    \param sv (SUMA_SurfaceViewer *) Surface viewer structure
5393    \param dov (SUMA_DO *) vector of displayable objects
5394    \param N_dov (int) number of displayable objects
5395    \ret ans (SUMA_STANDARD_VIEWS) recommended view
5396 
5397 */
SUMA_BestStandardView(SUMA_SurfaceViewer * sv,SUMA_DO * dov,int N_dov)5398 SUMA_STANDARD_VIEWS SUMA_BestStandardView (  SUMA_SurfaceViewer *sv,
5399                                              SUMA_DO *dov, int N_dov)
5400 {
5401    static char FuncName[] = {"SUMA_BestStandardView"};
5402    SUMA_STANDARD_VIEWS ans;
5403    int N_MembSOs, *MembSOs=NULL, i, maxdim = -1, is, balls, vslice=0;
5404    SUMA_SurfaceObject *SO = NULL;
5405    char *variant=NULL;
5406    SUMA_DO_Types ttv[10]={SO_type, GRAPH_LINK_type, TRACT_type,
5407                           VO_type, CDOM_type, MASK_type, NOT_SET_type};
5408    SUMA_SO_SIDE side=SUMA_NO_SIDE;
5409    SUMA_Boolean LocalHead = NOPE;
5410 
5411    SUMA_ENTRY;
5412 
5413    is = sv->iState;
5414    if (is < 0) {
5415       fprintf(SUMA_STDERR, "Error %s: sv->iState undefined.\n", FuncName);
5416       SUMA_RETURN (SUMA_N_STANDARD_VIEWS);
5417    }
5418 
5419    side = SUMA_LEFT;
5420    balls = 0; vslice = 0;
5421    MembSOs = SUMA_ViewState_Membs(&(sv->VSv[is]), ttv, &N_MembSOs);
5422    SUMA_LHv("Working on %d members\n", N_MembSOs);
5423    for (i=0; i<N_MembSOs; ++i) {
5424       switch (dov[MembSOs[i]].ObjectType) {
5425          case SO_type:
5426             SO = (SUMA_SurfaceObject *)(dov[MembSOs[i]].OP);
5427             if (SO == NULL) {
5428                fprintf(SUMA_STDERR,"Error %s: SO is null ???\n.", FuncName);
5429                SUMA_RETURN (SUMA_N_STANDARD_VIEWS);
5430             }
5431             if (SO->EmbedDim > maxdim) maxdim = SO->EmbedDim;
5432             if (SO->Side != SUMA_LEFT) side = SUMA_RIGHT;
5433             if (SUMA_IS_GEOM_SYMM(SO->isSphere)) balls = 1;
5434             break;
5435          case GRAPH_LINK_type:
5436             maxdim = 3;
5437             variant = SUMA_ADO_variant((SUMA_ALL_DO *)dov[MembSOs[i]].OP);
5438             if (!strcmp(variant,"GMATRIX")) {
5439                vslice = 1; /* a slice viewed from above */
5440             }
5441             break;
5442          case VO_type:
5443          case CDOM_type:
5444          case MASK_type:
5445          case TRACT_type:
5446             maxdim = 3;
5447             break;
5448          default:
5449             SUMA_S_Err("Should not be here");
5450             break;
5451       }
5452    }
5453    SUMA_ifree(MembSOs);
5454 
5455    switch (maxdim) {
5456       case 2:
5457          if (side == SUMA_LEFT) { /* left flat maps*/
5458             SUMA_RETURN (SUMA_2D_Z0L);
5459          } else { /* default */
5460             SUMA_RETURN (SUMA_2D_Z0);
5461          }
5462       case 3:
5463          if (!balls && !vslice) SUMA_RETURN(SUMA_3D);
5464          else SUMA_RETURN(SUMA_3D_Z0);
5465       default:
5466          fprintf(SUMA_STDERR,
5467             "Error %s: No provision for a maximum embedding dimension of %d.\n",
5468             FuncName, maxdim);
5469          SUMA_RETURN(SUMA_N_STANDARD_VIEWS);
5470    }
5471 
5472 }
5473 
5474 /*!
5475    \brief Apply the group of a surface to the surface viewer
5476 */
SUMA_AdoptSurfGroup(SUMA_SurfaceViewer * csv,SUMA_SurfaceObject * SO)5477 SUMA_Boolean SUMA_AdoptSurfGroup(SUMA_SurfaceViewer *csv, SUMA_SurfaceObject *SO)
5478 {
5479    static char FuncName[]={"SUMA_AdoptSurfGroup"};
5480 
5481    SUMA_ENTRY;
5482 
5483    csv->iCurGroup = SUMA_WhichGroup(SUMAg_CF, SO->Group);
5484    if (csv->iCurGroup < 0) {
5485       SUMA_SL_Err("Bad, unexpected error.\nGroup was not found");
5486       SUMA_RETURN(NOPE);
5487    }
5488    if (csv->CurGroupName) SUMA_free(csv->CurGroupName);
5489 
5490    csv->CurGroupName = SUMA_copy_string(SO->Group);
5491    SUMA_RETURN(YUP);
5492 }
5493 
5494 /*!
5495    \brief Apply a group to the surface viewer
5496 */
SUMA_AdoptGroup(SUMA_SurfaceViewer * csv,char * group)5497 SUMA_Boolean SUMA_AdoptGroup(SUMA_SurfaceViewer *csv, char *group)
5498 {
5499    static char FuncName[]={"SUMA_AdoptGroup"};
5500 
5501    SUMA_ENTRY;
5502 
5503    csv->iCurGroup = SUMA_WhichGroup(SUMAg_CF, group);
5504    if (csv->iCurGroup < 0) {
5505       SUMA_SL_Err("Bad, unexpected error.\nGroup was not found");
5506       SUMA_RETURN(NOPE);
5507    }
5508    if (csv->CurGroupName) SUMA_free(csv->CurGroupName);
5509 
5510    csv->CurGroupName = SUMA_copy_string(SUMAg_CF->GroupList[csv->iCurGroup]);
5511    SUMA_RETURN(YUP);
5512 }
5513 
5514 SUMA_Boolean
SUMA_SetViewerLightsForSO(SUMA_SurfaceViewer * cSV,SUMA_SurfaceObject * SO)5515    SUMA_SetViewerLightsForSO(SUMA_SurfaceViewer *cSV, SUMA_SurfaceObject *SO)
5516 {
5517    static char FuncName[]={"SUMA_SetViewerLightsForSO"};
5518    SUMA_Boolean LocalHead = NOPE;
5519 
5520    SUMA_ENTRY;
5521 
5522    if (!cSV || !SO) SUMA_RETURN(NOPE);
5523 
5524    if (cSV->lit_for == 0) { /* olde way */
5525       /* if surface is SureFit , flip lights */
5526       if (SO->normdir == 0 && (  SO->FileType == SUMA_SUREFIT ||
5527                                  SO->FileType == SUMA_OPENDX_MESH ||
5528                                  SO->FileType == SUMA_OBJ_MESH ||
5529                                  SO->FileType == SUMA_BRAIN_VOYAGER)) {
5530          SUMA_LH("Flippo for safety");
5531          cSV->light0_position[0] *= -1;
5532          cSV->light0_position[1] *= -1;
5533          cSV->light0_position[2] *= -1;
5534          glLightfv(GL_LIGHT0, GL_POSITION, cSV->light0_position);
5535       } else if (SO->normdir == -1) {
5536          SUMA_LH("Flippo for safety");
5537          cSV->light0_position[0] *= -1;
5538          cSV->light0_position[1] *= -1;
5539          cSV->light0_position[2] *= -1;
5540          glLightfv(GL_LIGHT0, GL_POSITION, cSV->light0_position);
5541       }
5542    } else {
5543       SUMA_LHv("Auto Flippo for safety, %d, %d\n", cSV->lit_for , SO->normdir);
5544       if (cSV->lit_for * SO->normdir < 0) {
5545          cSV->light0_position[0] *= -1;
5546          cSV->light0_position[1] *= -1;
5547          cSV->light0_position[2] *= -1;
5548          cSV->lit_for *= -1;
5549          glLightfv(GL_LIGHT0, GL_POSITION, cSV->light0_position);
5550       }
5551    }
5552 
5553    SUMA_RETURN(YUP);
5554 }
5555 
5556 
5557 /*!
5558 ans = SUMA_SetupSVforDOs (Spec, DOv, N_DOv, cSV, vo);
5559 
5560 This functions registers all surfaces in a spec file with a surface viewer.
5561 The following steps are performed:
5562 SUMA_RegisterSpecSO (register info on all surfaces loaded)
5563 SUMA_RegisterDO (only Surface Objects)
5564 SUMA_RegisterDO (all non SO objects)
5565 SUMA_BestStandardView (decide on best standard view)
5566 SUMA_UpdateRotaCenter (based on surfaces in first view) if vo & UPDATE_ROT_MASK
5567 SUMA_UpdateViewPoint (based on surfaces in first view)  if vo & UPDATE_VIEW_POINT_MASK
5568 SUMA_EyeAxisStandard (based on surfaces in first view)  if vo & UPDATE_EYE_AXIS_STD_MASK
5569 
5570 Set the Current SO pointer to the first surface object
5571 if surface is SureFit, flip lights
5572 \param Spec (SUMA_SurfSpecFile *)
5573 \param DOv (SUMA_DO *) Pointer to vector of displayable objects
5574 \param N_DOv (int) Number of displayable objects in DOv
5575 \param cSV (SUMA_SurfaceViewer *) Surface viewer structure
5576 \ret ans (SUMA_Boolean) YUP/NOPE
5577 */
5578 
SUMA_SetupSVforDOs(SUMA_SurfSpecFile * Spec,SUMA_DO * DOv,int N_DOv,SUMA_SurfaceViewer * cSV,int viewopt)5579 SUMA_Boolean SUMA_SetupSVforDOs (SUMA_SurfSpecFile *Spec, SUMA_DO *DOv,
5580                                  int N_DOv,
5581                                  SUMA_SurfaceViewer *cSV, int viewopt)
5582 {
5583    static char FuncName[] = {"SUMA_SetupSVforDOs"};
5584    int kar, ws, i;
5585    SUMA_SurfaceObject *SO;
5586    SUMA_Axis *EyeAxis;
5587    SUMA_DO_Types ttv[10]={SO_type, GRAPH_LINK_type, TRACT_type,
5588                           MASK_type, VO_type, CDOM_type, NOT_SET_type};
5589    int EyeAxis_ID, *MembDOs=NULL, N_MembDOs=0;
5590    int haveSpec=0;
5591    SUMA_Boolean LocalHead = NOPE;
5592 
5593    SUMA_ENTRY;
5594 
5595    if (!viewopt) {
5596       viewopt = UPDATE_ALL_VIEWING_PARAMS_MASK;
5597    }
5598 
5599    if (Spec && Spec->N_Groups > 0) haveSpec=1;
5600 
5601    /* register all surface specs */
5602    /* find out what group the viewer will have and assign the current
5603       group to be that of the new surfaces */
5604    if (LocalHead) {
5605       fprintf (SUMA_STDERR, "%s: Registering DOs with viewer [%d]%p, %d\n",
5606           FuncName, SUMA_WhichSV(cSV, SUMAg_SVv, SUMA_MAX_SURF_VIEWERS),
5607           cSV, SUMAg_N_SVv);
5608       if (haveSpec) {
5609          SUMA_LHv("HaveSpec, %d surfs, %d DOs, Group %s\n",
5610                   Spec->N_Surfs, Spec->N_DO, Spec->Group[0]);
5611       }
5612    }
5613 
5614 
5615    cSV->iCurGroup =  SUMA_WhichGroup(SUMAg_CF, haveSpec ? Spec->Group[0]:NULL);
5616                                                 /* only one group per spec */
5617    if (cSV->iCurGroup < 0) {
5618       SUMA_SL_Err("Group not found.\n");
5619       SUMA_RETURN(NOPE);
5620    } else {
5621       cSV->CurGroupName =
5622             SUMA_copy_string(SUMAg_CF->GroupList[cSV->iCurGroup]);
5623    }
5624 
5625 
5626    if (haveSpec && !SUMA_RegisterSpecSO(Spec, cSV, DOv, N_DOv, viewopt)) {
5627       SUMA_S_Err("Failed in SUMA_RegisterSpecSO.");
5628       SUMA_RETURN(NOPE);
5629    }
5630 
5631    /* register all SOs of the first state if no state is current
5632       or register all surfaces if they are of the current state and group
5633       (it is possible that no new surfaces are registered, but
5634         overhead is tiny)
5635 
5636       The logic fails when you load two different groups with the one surface
5637       in each having the same state as in the other.
5638       {G1, SO->State='a'} {G2, SO->State='a'} in that case both surfaces will
5639       show up at the same time when first loaded. You'll need to switch groups
5640       before you see just the one surface from that group.
5641 
5642       For now, I don't care to set this up properly since no one uses
5643       multi-group business.
5644    */
5645    if (!SUMA_IS_GOOD_STATE(cSV->State)) {
5646       SUMA_LHv("Looking for something better than %s\n", CNS(cSV->State));
5647       ws = SUMA_FirstGoodState(cSV);
5648    } else {
5649       ws =  SUMA_WhichState (cSV->State, cSV, cSV->CurGroupName) ;
5650    }
5651    if ( ws < 0) {
5652       /* This happens for example when running @DO.examples */
5653       SUMA_LH("No good state at this stage? Defaulting to ws = 0;");
5654       ws = 0;
5655    }
5656 
5657    /* Make sure we have something */
5658    do {
5659       SUMA_LHv("Seeking members of state %s\n", CNS(cSV->VSv[ws].Name) );
5660       MembDOs = SUMA_ViewState_Membs(&(cSV->VSv[ws]), ttv, &N_MembDOs);
5661       if (!N_MembDOs) ++ws;
5662    } while (!N_MembDOs && ws < cSV->N_VSv);
5663 
5664    if (!N_MembDOs) {
5665       SUMA_S_Err("Nothing to see (check ttv for necessary types)");
5666       SUMA_RETURN(NOPE);
5667    }
5668    SUMA_LHv("Registering All DOs of the %dth state %s...\n"
5669             "                 N_MembDOs = %d\n",
5670             ws, cSV->VSv[ws].Name,  N_MembDOs);
5671    cSV->State = cSV->VSv[ws].Name;
5672    cSV->iState = ws;
5673    for (kar=0; kar < N_MembDOs; ++ kar) {
5674        SUMA_LHv(" About to register DOv[%d] ...\n",
5675                   MembDOs[kar]);
5676        switch (DOv[MembDOs[kar]].ObjectType) {
5677          case SO_type:
5678             SO = (SUMA_SurfaceObject *)DOv[MembDOs[kar]].OP;
5679             SUMA_LHv("SO->Group %s, cSV->CurGroupName %s\n",
5680                         SO->Group, cSV->CurGroupName);
5681             if (!SUMA_RegisterDO(MembDOs[kar], cSV)) {
5682                SUMA_error_message (FuncName,"Failed to register DO", 1);
5683                SUMA_RETURN(NOPE);
5684             }
5685             break;
5686          case GRAPH_LINK_type:
5687             SUMA_LH(
5688                "Registration was done after loading in SUMA_LoadDsetOntoSO_eng\n"
5689                "No further action needed here");
5690             break;
5691          case TRACT_type:
5692             SUMA_LH(
5693                "Registration was done after loading in SUMA_LoadSegDO\n"
5694                "No further action needed here");
5695             break;
5696          case MASK_type:
5697          case CDOM_type:
5698          case VO_type:
5699             SUMA_LH(
5700                "Registration was done after loading in object\n"
5701                "No further action needed here");
5702             break;
5703          default:
5704             SUMA_S_Err("Ney, no good");
5705             break;
5706       }
5707    }
5708 
5709    /* Set the index Current SO pointer to the first surface object read of
5710    the first state, tiz NOT (Fri Jan 31 15:18:49 EST 2003) a surface of course*/
5711    cSV->Focus_DO_ID = MembDOs[0];
5712 
5713    SUMA_ifree(MembDOs);
5714 
5715    if (LocalHead)   fprintf(SUMA_STDERR,"%s: Done.\n", FuncName);
5716 
5717    /* register all non SO objects */
5718    if (LocalHead)
5719       fprintf(SUMA_STDERR,"%s: Registering All Non SO ...", FuncName);
5720       for (kar=0; kar < N_DOv; ++kar) {
5721          if (!SUMA_isSO(DOv[kar]))
5722          {
5723             /*fprintf(SUMA_STDERR," About to register DOv[%d] ...\n", kar);*/
5724             if (!SUMA_RegisterDO(kar, cSV)) {
5725                SUMA_error_message (FuncName,"Failed to register DO", 1);
5726                SUMA_RETURN(NOPE);
5727             }
5728          }
5729       }
5730    if (LocalHead) fprintf(SUMA_STDERR,"%s: Done.\n", FuncName);
5731 
5732    /* decide what the best state is */
5733    if (viewopt & UPDATE_STANDARD_VIEW_MASK) {
5734       cSV->StdView = SUMA_BestStandardView (cSV, DOv, N_DOv);
5735       if (LocalHead)
5736          fprintf(SUMA_STDERR,
5737                   "%s: Standard View Now %d\n", FuncName, cSV->StdView);
5738       if (cSV->StdView == SUMA_N_STANDARD_VIEWS) {
5739          fprintf(SUMA_STDERR,
5740                   "Error %s: Could not determine the best standard view. "
5741                   "Choosing default SUMA_3D\n", FuncName);
5742          cSV->StdView = SUMA_3D;
5743       }
5744    }
5745 
5746    if (viewopt & UPDATE_ROT_MASK) {
5747       /* Set the Rotation Center  */
5748       if (LocalHead)
5749          fprintf(SUMA_STDERR,"%s: Setting the Rotation Center \n", FuncName);
5750       if (!SUMA_UpdateRotaCenter(cSV, DOv, N_DOv)) {
5751          fprintf (SUMA_STDERR,
5752                   "Error %s: Failed to update center of rotation\n", FuncName);
5753          SUMA_RETURN(NOPE);
5754       }
5755    }
5756 
5757    if (viewopt & UPDATE_VIEW_POINT_MASK) {
5758       /* set the viewing points */
5759       SUMA_LH("setting the viewing points");
5760       if (!SUMA_UpdateViewPoint(cSV, DOv, N_DOv, 0)) {
5761          SUMA_S_Err("Failed to update view point");
5762          SUMA_RETURN(NOPE);
5763       }
5764    }
5765 
5766    if (viewopt & UPDATE_EYE_AXIS_STD_MASK) {
5767       /* Change the defaults of the eye axis to fit standard EyeAxis */
5768       SUMA_LH("Changing defaults of the eye axis to fit standard EyeAxis");
5769       EyeAxis_ID = SUMA_GetEyeAxis (cSV, DOv);
5770       if (EyeAxis_ID < 0) {
5771          fprintf (SUMA_STDERR,"Error %s: Failed to get Eye Axis.\n", FuncName);
5772          SUMA_RETURN(NOPE);
5773       }
5774       SUMA_EyeAxisStandard ((SUMA_Axis *)DOv[EyeAxis_ID].OP, cSV);
5775    }
5776 
5777 
5778 
5779    /*set the GroupName info of the viewer correctly */
5780    if ((SO = SUMA_SV_Focus_SO(cSV))) {
5781       if (!SUMA_AdoptSurfGroup(cSV,SO)) {
5782          SUMA_SL_Err("Failed to adopt surface's group");
5783          SUMA_RETURN(NOPE);
5784       }
5785 
5786       if (!SUMA_SetViewerLightsForSO(cSV, SO)) {
5787          SUMA_S_Warn("Failed to set viewer lights.\n"
5788                      "Use 'F' key to flip lights in SUMA if necessary.");
5789       }
5790    }
5791 
5792    /* do the axis setup */
5793    SUMA_WorldAxisStandard (cSV->WAx, cSV);
5794 
5795    /* do the FOV thingy */
5796    if (cSV->FOV[cSV->iState] == cSV->FOV_original || cSV->FOV[cSV->iState] < 0) {
5797       cSV->FOV[cSV->iState] = SUMA_sv_auto_fov(cSV);
5798    }
5799 
5800    SUMA_RETURN(YUP);
5801 }
5802 
5803 /*!
5804    \brief updates the cursor in all viewers
5805 */
SUMA_UpdateAllViewerCursor()5806 void SUMA_UpdateAllViewerCursor()
5807 {
5808    static char FuncName[]={"SUMA_UpdateAllViewerCursor"};
5809    int i;
5810 
5811    SUMA_ENTRY;
5812 
5813    for (i=0; i<SUMAg_N_SVv; ++i) {
5814       if (SUMAg_SVv[i].X) {
5815          SUMA_UpdateViewerCursor(&(SUMAg_SVv[i]));
5816       }
5817    }
5818 
5819    SUMA_RETURNe;
5820 }
5821 
5822 /*!
5823    \brief updates the cursor in one viewer
5824 */
SUMA_UpdateViewerCursor(SUMA_SurfaceViewer * sv)5825 void SUMA_UpdateViewerCursor(SUMA_SurfaceViewer *sv)
5826 {
5827    static char FuncName[]={"SUMA_UpdateViewerCursor"};
5828    SUMA_Boolean LocalHead = NOPE;
5829 
5830    SUMA_ENTRY;
5831 
5832    if (!sv->X) SUMA_RETURNe;
5833    if (!sv->X->GLXAREA) SUMA_RETURNe;
5834    if (SUMAg_CF->ROI_mode) {
5835       if (SUMAg_CF->Pen_mode)
5836          MCW_set_widget_cursor( sv->X->GLXAREA  , -XC_pencil ) ;
5837       else  MCW_set_widget_cursor( sv->X->GLXAREA  , -XC_target ) ;
5838    } else {
5839       if (0) {
5840          MCW_set_widget_cursor( sv->X->GLXAREA  , -XC_dotbox);
5841       } else {
5842          MCW_set_widget_cursor( sv->X->GLXAREA  , -XC_top_left_arrow ) ;
5843       }
5844    }
5845    SUMA_RETURNe;
5846 }
5847 
5848 /*!
5849    \brief updates the title string of a viewer window
5850 */
5851 
SUMA_UpdateViewerTitle_old(SUMA_SurfaceViewer * sv)5852 void SUMA_UpdateViewerTitle_old(SUMA_SurfaceViewer *sv)
5853 {
5854    static char FuncName[]={"SUMA_UpdateViewerTitle_old"};
5855    int isv, i, N_SOlist, nalloc;
5856    char slabel[30], sside[30], srec[10], cl='\0', cr='\0', smoment[30];
5857    SUMA_SurfaceObject *SO = NULL;
5858    int SOlist[SUMA_MAX_DISPLAYABLE_OBJECTS];
5859    SUMA_Boolean LeftSide, RightSide, RightShown, LeftShown;
5860    SUMA_Boolean LocalHead = NOPE;
5861 
5862    SUMA_ENTRY;
5863 
5864    if (!sv->X) SUMA_RETURNe;
5865    if (!sv->X->TOPLEVEL) SUMA_RETURNe;
5866 
5867    isv = SUMA_WhichSV (sv, SUMAg_SVv, SUMAg_N_SVv);
5868 
5869    if (sv->X->Title) SUMA_free(sv->X->Title);
5870    sv->X->Title = NULL;
5871 
5872    if (isv >= 0) sprintf(slabel,"[%c] SUMA", 65+isv);
5873    else sprintf(slabel,"[DOH] SUMA");
5874 
5875    N_SOlist = SUMA_RegisteredSOs(sv, SUMAg_DOv, SOlist);
5876 
5877    i = 0;
5878    nalloc = 0;
5879    LeftSide = NOPE;
5880    LeftShown = NOPE;
5881    RightSide = NOPE;
5882    RightShown = NOPE;
5883    while (i < N_SOlist) {
5884       SO = (SUMA_SurfaceObject *)(SUMAg_DOv[SOlist[i]].OP);
5885       if (SO->Label) {
5886          nalloc +=  (strlen(SO->Label)+5);
5887       }
5888       if (SO->Side == SUMA_LEFT) {
5889          SUMA_LH("Left found");
5890          LeftSide = YUP;
5891          if (sv->ShowLeft) LeftShown = YUP;
5892       } else if (SO->Side == SUMA_RIGHT) {
5893          SUMA_LH("Right found");
5894          RightSide = YUP;
5895          if (sv->ShowRight) RightShown = YUP;
5896       }
5897 
5898       ++i;
5899    }
5900    if (LeftSide && LeftShown) cl = 'L';
5901    else if (LeftSide && !LeftShown) cl = 'h';
5902    else cl = 'x';
5903    if (RightSide && RightShown) cr = 'R';
5904    else if (RightSide && !RightShown) cr = 'h';
5905    else cr = 'x';
5906 
5907 
5908    sprintf(sside, ":%c%c:", cl, cr);
5909 
5910    if (sv->Record==1) sprintf(srec,":Rec");
5911    else if (sv->Record==2) sprintf(srec,":REC");
5912    else srec[0] = '\0';
5913 
5914    if (sv->GVS[sv->StdView].ApplyMomentum) sprintf(smoment,":M");
5915    else smoment[0] = '\0';
5916 
5917    if (LocalHead)
5918       fprintf (SUMA_STDERR,
5919                "%s: Found %d surface models.\n", FuncName, N_SOlist);
5920 
5921    i = 0;
5922    if (N_SOlist >= 0) {
5923       SUMA_LH("title surfaces found");
5924       sv->X->Title =
5925          (char *)SUMA_calloc(nalloc + strlen(slabel)+ 130, sizeof(char));
5926       sv->X->Title[0] = '\0';
5927       while (i < N_SOlist) {
5928          SO = (SUMA_SurfaceObject *)(SUMAg_DOv[SOlist[i]].OP);
5929          SUMA_LHv("sv->Focus_DO_ID = %d,  SOlist[%d] = %d\n",
5930                   sv->Focus_DO_ID, i, SOlist[i]);
5931          if (!i)  {
5932             if (sv->Focus_DO_ID == SOlist[i]) {
5933                sprintf (sv->X->Title,"%s%s%s%s [%s]",
5934                         slabel, srec, smoment, sside, SO->Label);
5935             } else {
5936                sprintf (sv->X->Title,"%s%s%s%s %s",
5937                         slabel, srec, smoment, sside, SO->Label);
5938             }
5939          } else {
5940             sv->X->Title = strcat (sv->X->Title, " & ");
5941             if (sv->Focus_DO_ID == SOlist[i]) {
5942                sv->X->Title = strcat (sv->X->Title, " [");
5943                sv->X->Title = strcat (sv->X->Title, SO->Label);
5944                sv->X->Title = strcat (sv->X->Title, "] ");
5945             } else  {
5946                sv->X->Title = strcat (sv->X->Title, SO->Label);
5947             }
5948          }
5949          ++i;
5950       }
5951    } else {
5952       SUMA_LH("No title could be made up");
5953       sv->X->Title = (char *)SUMA_calloc(strlen(slabel)+3, sizeof(char));
5954       sprintf (sv->X->Title,"%s:-", slabel);
5955    }
5956 
5957    XtVaSetValues(sv->X->TOPLEVEL,
5958             XmNtitle, sv->X->Title,
5959             NULL);
5960 
5961    SUMA_RETURNe;
5962 }
5963 /*!
5964    \brief updates the title string of a viewer window
5965 */
5966 
SUMA_UpdateViewerTitle(SUMA_SurfaceViewer * sv)5967 void SUMA_UpdateViewerTitle(SUMA_SurfaceViewer *sv)
5968 {
5969    static char FuncName[]={"SUMA_UpdateViewerTitle"};
5970    int isv, i, N_SOlist;
5971    char cl='\0', cr='\0', *s=NULL;
5972    SUMA_SurfaceObject *SO = NULL;
5973    int SOlist[SUMA_MAX_DISPLAYABLE_OBJECTS];
5974    SUMA_STRING *SS = NULL;
5975    SUMA_Boolean LeftSide, RightSide, RightShown, LeftShown;
5976    SUMA_Boolean LocalHead = NOPE;
5977 
5978    SUMA_ENTRY;
5979 
5980    if (!sv->X) SUMA_RETURNe;
5981    if (!sv->X->TOPLEVEL) SUMA_RETURNe;
5982 
5983    SUMA_LH("Finding SV");
5984    isv = SUMA_WhichSV (sv, SUMAg_SVv, SUMAg_N_SVv);
5985 
5986    if (sv->X->Title) SUMA_free(sv->X->Title);
5987    sv->X->Title = NULL;
5988 
5989    SS = SUMA_StringAppend_va(NULL, NULL);
5990 
5991    SUMA_LH("Number");
5992    if (isv >= 0) {
5993       if ((i = get_user_np_bloc())>-1) {
5994          SS = SUMA_StringAppend_va(SS, "[%c%d] SUMA", 65+isv, i);
5995       } else {
5996          SS = SUMA_StringAppend_va(SS, "[%c] SUMA", 65+isv);
5997       }
5998    } else SS = SUMA_StringAppend_va(SS,"[DOH] SUMA");
5999 
6000    SUMA_LH("Rec");
6001    if (sv->Record == 1) SS = SUMA_StringAppend_va(SS,":Rec");
6002    else if (sv->Record == 2) SS = SUMA_StringAppend_va(SS,":REC");
6003 
6004    SUMA_LH("Momentum");
6005    if (sv->GVS[sv->StdView].ApplyMomentum) SS = SUMA_StringAppend_va(SS,":M");
6006 
6007    SUMA_LH("ClippingPlane");
6008    // if (sv->GVS[sv->StdView].ClippingPlane) SS = SUMA_StringAppend_va(SS,":C");
6009    if (sv->GVS[sv->StdView].ClippingPlane){
6010     char strTmp[32];
6011     sprintf(strTmp, ":C:Inc=%.4f", sv->clippingPlaneIncrement);
6012     SS = SUMA_StringAppend_va(SS,strTmp);
6013    }
6014 
6015    SUMA_LH("Surf List");
6016    N_SOlist = SUMA_RegisteredSOs(sv, SUMAg_DOv, SOlist);
6017 
6018    i = 0;
6019    LeftSide = NOPE;
6020    LeftShown = NOPE;
6021    RightSide = NOPE;
6022    RightShown = NOPE;
6023    while (i < N_SOlist) {
6024       SUMA_LH("   + +");
6025       SO = (SUMA_SurfaceObject *)(SUMAg_DOv[SOlist[i]].OP);
6026       if (SO->Side == SUMA_LEFT) {
6027          SUMA_LH("Left found");
6028          LeftSide = YUP;
6029          if (sv->ShowLeft) LeftShown = YUP;
6030       } else if (SO->Side == SUMA_RIGHT) {
6031          SUMA_LH("Right found");
6032          RightSide = YUP;
6033          if (sv->ShowRight) RightShown = YUP;
6034       }
6035 
6036       ++i;
6037    }
6038 
6039    if (LeftSide && LeftShown) cl = 'L';
6040    else if (LeftSide && !LeftShown) cl = 'h';
6041    else cl = 'x';
6042    if (RightSide && RightShown) cr = 'R';
6043    else if (RightSide && !RightShown) cr = 'h';
6044    else cr = 'x';
6045 
6046    SUMA_LH("Sides");
6047 
6048    SS = SUMA_StringAppend_va(SS, ":%c%c:", cl, cr);
6049 
6050    SUMA_LHv("Found %d surface models.\n", N_SOlist);
6051 
6052    /* add the group's name */
6053    if (LocalHead) {
6054       if (sv->CurGroupName) {
6055          SUMA_S_Notev("Calling with sv->CurGroupName = %p\n", sv->CurGroupName);
6056       } else {
6057          SUMA_S_Note("Calling with NULL sv->CurGroupName\n");
6058       }
6059    }
6060 
6061    if (sv->CurGroupName) SS = SUMA_StringAppend_va(SS," %s:", sv->CurGroupName);
6062    else SS = SUMA_StringAppend_va(SS," xx:");
6063 
6064    i = 0;
6065    if (N_SOlist >= 0) {
6066       SUMA_LH("title surfaces found");
6067       while (i < N_SOlist) {
6068          SO = (SUMA_SurfaceObject *)(SUMAg_DOv[SOlist[i]].OP);
6069          SUMA_LHv("sv->Focus_DO_ID = %d,  SOlist[%d] = %d\n",
6070                   sv->Focus_DO_ID, i, SOlist[i]);
6071          if (!i)  {
6072             if (sv->Focus_DO_ID == SOlist[i]) {
6073                SS = SUMA_StringAppend_va(SS," [%s]",  SO->Label);
6074             } else {
6075                SS = SUMA_StringAppend_va(SS," %s",  SO->Label);
6076             }
6077          } else {
6078             SS = SUMA_StringAppend_va(SS," & ");
6079             if (sv->Focus_DO_ID == SOlist[i]) {
6080                SS = SUMA_StringAppend_va(SS, " [");
6081                SS = SUMA_StringAppend_va(SS, "%s", SO->Label);
6082                SS = SUMA_StringAppend_va(SS, "] ");
6083             } else  {
6084                SS = SUMA_StringAppend_va(SS, "%s", SO->Label);
6085             }
6086          }
6087          ++i;
6088       }
6089    } else {
6090       SUMA_LH("No title could be made up");
6091       SS = SUMA_StringAppend_va(SS,":-");
6092    }
6093 
6094    /* compact SS */
6095    SS = SUMA_StringAppend_va(SS, NULL);
6096 
6097    sv->X->Title = SS->s;
6098 
6099    SUMA_free(SS); SS= NULL;
6100 
6101    XtVaSetValues(sv->X->TOPLEVEL,
6102             XmNtitle, sv->X->Title,
6103             NULL);
6104 
6105    SUMA_RETURNe;
6106 }
6107 
6108 /*!
6109    \brief finds the index into the grouplist of a certain group
6110 */
SUMA_WhichGroup(SUMA_CommonFields * cf,char * nm)6111 int SUMA_WhichGroup (SUMA_CommonFields *cf, char *nm)
6112 {
6113    static char FuncName[]={"SUMA_WhichGroup"};
6114    int i = -1;
6115 
6116    SUMA_ENTRY;
6117 
6118    if (!cf) {
6119       SUMA_SL_Err("Null nm");
6120       SUMA_RETURN(i);
6121    }
6122    if (!nm) nm = "ANY";
6123 
6124    if (cf->N_Group <=0) { SUMA_RETURN(i); }
6125 
6126    for (i=0; i<cf->N_Group; ++i) {
6127       if (!strcmp(cf->GroupList[i], nm)) SUMA_RETURN(i);
6128    }
6129 
6130    SUMA_RETURN(-1);
6131 }
6132 
SUMA_RegisterSpecGroup(SUMA_CommonFields * cf,SUMA_SurfSpecFile * spec)6133 SUMA_Boolean SUMA_RegisterSpecGroup (SUMA_CommonFields *cf,
6134                                      SUMA_SurfSpecFile *spec)
6135 {
6136    static char FuncName[]={"SUMA_RegisterSpecGroup"};
6137 
6138    SUMA_ENTRY;
6139 
6140    if (!spec || spec->N_Groups != 1) {
6141       SUMA_SL_Err("!Spec || Spec->N_Groups != 1. This is unacceptable.\n");
6142       SUMA_RETURN(NOPE);
6143    }
6144 
6145    SUMA_RETURN(SUMA_RegisterGroup(cf, spec->Group[0]));
6146 }
6147 /*!
6148    \brief Register a new group with SUMA
6149 */
SUMA_RegisterGroup(SUMA_CommonFields * cf,char * gname)6150 SUMA_Boolean SUMA_RegisterGroup (SUMA_CommonFields *cf, char *gname)
6151 {
6152    static char FuncName[]={"SUMA_RegisterGroup"};
6153    int n=0;
6154    SUMA_Boolean LocalHead = NOPE;
6155 
6156    SUMA_ENTRY;
6157 
6158    if (!gname || !cf) {
6159       SUMA_S_Err("NULL gname or !cf")
6160       SUMA_RETURN(NOPE);
6161    }
6162 
6163    if (!cf->GroupList){
6164       cf->GroupList = (char **) SUMA_malloc(sizeof(char*)*SUMA_MAX_N_GROUPS);
6165       for (n=0; n<SUMA_MAX_N_GROUPS; ++n) cf->GroupList[n]=NULL;
6166       cf->N_Group = 0;
6167    }
6168 
6169    /* does the group exist already ? */
6170    if (SUMA_WhichGroup (cf, gname) < 0) {
6171       /* new group */
6172       SUMA_LH("Adding group");
6173       if (cf->N_Group >=  SUMA_MAX_N_GROUPS) {
6174          SUMA_SL_Err("Exceeding maximum number of groups allowed.\n");
6175          SUMA_RETURN(NOPE);
6176       }
6177       cf->GroupList[cf->N_Group] = SUMA_copy_string(gname);
6178       ++cf->N_Group;
6179    } else{
6180       /* an old group */
6181       SUMA_LH("Group exists already");
6182    }
6183    SUMA_RETURN(YUP);
6184 
6185 }
6186 
6187 /*!
6188    \brief Returns a list of the Groups available to a viewer.
6189 
6190    \param sv (SUMA_SurfaceViewer *) pointer to surface viewer
6191 
6192    \return clist (SUMA_ASSEMBLE_LIST_STRUCT *) pointer to structure containing results
6193 
6194    \sa SUMA_FreeAssembleListStruct
6195    \sa SUMA_CreateAssembleListStruct
6196 
6197 */
SUMA_AssembleGroupList(SUMA_SurfaceViewer * sv)6198 SUMA_ASSEMBLE_LIST_STRUCT * SUMA_AssembleGroupList (SUMA_SurfaceViewer *sv)
6199 {
6200    static char FuncName[]={"SUMA_AssembleGroupList"};
6201    SUMA_ASSEMBLE_LIST_STRUCT *clist_str = NULL;
6202    int i=-1, N_clist=-1;
6203    char *store=NULL;
6204    char **clist=NULL;
6205    void **oplist=NULL;
6206    DList *list=NULL, *listop = NULL;
6207    DListElmt *Elm = NULL, *Elmop = NULL;
6208    SUMA_Boolean Found = NOPE;
6209    SUMA_Boolean LocalHead = NOPE;
6210 
6211    SUMA_ENTRY;
6212 
6213    list = (DList *)SUMA_malloc(sizeof(DList));
6214    listop = (DList *)SUMA_malloc(sizeof(DList));
6215 
6216    clist = NULL;
6217    N_clist = -1;
6218 
6219    dlist_init(list, NULL);
6220    dlist_init(listop, NULL);
6221 
6222    for (i=0; i< SUMAg_CF->N_Group; ++i) {
6223       store = SUMA_copy_string(SUMAg_CF->GroupList[i]);
6224       if (!list->size) {
6225          dlist_ins_next(list, dlist_tail(list), (void*)store);
6226          dlist_ins_next(listop, dlist_tail(listop), NULL);
6227       } else { /* must sort first */
6228          Elm = NULL;
6229          Elmop = NULL;
6230          do {
6231             Found = NOPE;
6232             if (!Elm) {
6233                Elm = dlist_head(list);
6234                Elmop = dlist_head(listop);
6235             } else {
6236                Elm = dlist_next(Elm);
6237                Elmop = dlist_next(Elmop);
6238             }
6239 
6240             if (strcmp(store, (char*)Elm->data) <= 0) {
6241                dlist_ins_prev(list, Elm, (void *)store);
6242                dlist_ins_prev(listop, Elmop, NULL);
6243                Found = YUP;
6244             } else if (Elm == dlist_tail(list)) {
6245                /* reached the end, append */
6246                dlist_ins_next(list, Elm, (void *)store);
6247                dlist_ins_next(listop, Elmop, NULL);
6248                Found = YUP;
6249             }
6250          } while (!Found);
6251       }
6252    }
6253 
6254    if (!list->size) { /* Nothing found */
6255       N_clist = 0;
6256 
6257    }else {
6258 
6259       Elm = NULL;
6260       Elmop = NULL;
6261       clist = (char **)SUMA_calloc(list->size, sizeof(char *));
6262       oplist = (void **)SUMA_calloc(list->size, sizeof(void*));
6263       for (i=0; i< list->size; ++i) {
6264          if (!Elm) {
6265             Elm = dlist_head(list);
6266             Elmop = dlist_head(listop);
6267          } else {
6268             Elm = dlist_next(Elm);
6269             Elmop = dlist_next(Elmop);
6270          }
6271          clist[i] = (char*)Elm->data;
6272          oplist[i] = Elmop->data;
6273       }
6274 
6275       N_clist = list->size;
6276       /* destroy list */
6277       dlist_destroy(list);SUMA_free(list);
6278       dlist_destroy(listop);SUMA_free(listop);
6279 
6280 
6281    }
6282 
6283    clist_str = SUMA_CreateAssembleListStruct();
6284    clist_str->clist = clist;
6285    clist_str->oplist = oplist;
6286    clist_str->N_clist = N_clist;
6287 
6288    /* return */
6289    SUMA_RETURN (clist_str);
6290 }
6291 
6292 /*!
6293    \brief   Switch viewer between two groups
6294 */
SUMA_SwitchGroups(SUMA_SurfaceViewer * sv,char * group)6295 SUMA_Boolean SUMA_SwitchGroups (SUMA_SurfaceViewer *sv, char *group)
6296 {
6297    static char FuncName[]={"SUMA_SwitchGroups"};
6298    int ig, i, nxtstateID;
6299    SUMA_SurfaceObject *SO = NULL;
6300    DList *list = NULL;
6301    SUMA_Boolean LocalHead = NOPE;
6302 
6303    SUMA_ENTRY;
6304 
6305    if (!group) {
6306       SUMA_SL_Err("NULL group");
6307       SUMA_RETURN(NOPE);
6308    }
6309 
6310    if (!strcmp(group, sv->CurGroupName)) {
6311       SUMA_LH("Same group, nothing to do.");
6312       SUMA_RETURN(YUP);
6313    }
6314 
6315    if (SUMAg_CF->N_Group == 1) {
6316       SUMA_LH("One group, nothing to do.");
6317       SUMA_RETURN(YUP);
6318    }
6319 
6320    /* which group are we going to ? */
6321    ig = SUMA_WhichGroup (SUMAg_CF, group);
6322 
6323    if (ig < 0) {
6324       SUMA_SL_Err("No such group");
6325       SUMA_RETURN(NOPE);
6326    }
6327 
6328    /* It does not seem necessary to close surface controllers or ROI controllers*/
6329 
6330    /* find me a surface in that new group  */
6331    SO = NULL;
6332    i = 0;
6333    while (!SUMA_isSO_G(SUMAg_DOv[i], group) && i < SUMAg_N_DOv) {
6334       ++i;
6335    }
6336    if (i < SUMAg_N_DOv) { /* found a surface */
6337       SO = (SUMA_SurfaceObject *)SUMAg_DOv[i].OP;
6338    } else {
6339       SUMA_SL_Err("No candidate surface");
6340       SUMA_RETURN(NOPE);
6341    }
6342 
6343    /* what is the state ID of that surface ? */
6344    nxtstateID = SUMA_WhichState(SO->State, sv, SO->Group);
6345    if (nxtstateID < 0) {
6346       SUMA_SL_Err("Bad! State not found.");
6347       SUMA_RETURN(NOPE);
6348    }
6349 
6350    if (!SUMA_SwitchState (SUMAg_DOv, SUMAg_N_DOv, sv,  nxtstateID, group)) {
6351       SUMA_SL_Err("Failed to switch states");
6352       SUMA_RETURN(NOPE);
6353    }
6354 
6355    /* home call */
6356 
6357    #if 0
6358       /* now redisplay (won't work alone with multiple viewers, GL state problems) */
6359       if (!list) list = SUMA_CreateList();
6360       /* SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_Home, SES_Suma, sv); */
6361       SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_Redisplay, SES_Suma, sv);
6362 
6363       if (!SUMA_Engine (&list)) {
6364          fprintf(stderr, "Error %s: SUMA_Engine call failed.\n", FuncName);
6365       }
6366    #elif 0
6367                   /* redisplay all others (won't work alone with multiple viewers, GL state problems) */
6368                   if (!list) list = SUMA_CreateList ();
6369                   SUMA_REGISTER_TAIL_COMMAND_NO_DATA(list,
6370                         SE_RedisplayNow_AllOtherVisible, SES_SumaWidget, sv);
6371                   SUMA_Engine (&list);
6372 
6373                   /* redisplay . DO NOT REDISPLAY WITH SE_Redisplay_AllVisible
6374                      or you will have GL state synchronization problems */
6375                   sv->ResetGLStateVariables = YUP;
6376                   SUMA_handleRedisplay((XtPointer)sv->X->GLXAREA);
6377    #elif 1
6378 
6379             /* got to do this, in addition to SE_Redisplay_AllVisible
6380             to get the views to look good. I don't know why that is yet */
6381             for (i=0; i < SUMAg_N_SVv; ++i) {
6382                SUMA_SurfaceViewer *svtmp= &(SUMAg_SVv[i]);
6383                if (!svtmp->isShaded && svtmp->X->TOPLEVEL) {
6384                   if (!list) list = SUMA_CreateList();
6385                   SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_Home,
6386                                                       SES_Suma, svtmp);
6387                   SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_RedisplayNow,
6388                                                       SES_Suma, svtmp);
6389                   if (!SUMA_Engine (&list)) {
6390                         SUMA_S_Err("SUMA_Engine call failed.");
6391                   }
6392                }
6393             }
6394 
6395             if (!list) list = SUMA_CreateList();
6396             SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_Redisplay_AllVisible,
6397                                                SES_Suma, sv);
6398             if (!SUMA_Engine (&list)) {
6399                SUMA_S_Err("SUMA_Engine call failed.");
6400             }
6401 
6402    #endif
6403 
6404    /* update titles */
6405    SUMA_UpdateViewerTitle(sv);
6406 
6407 
6408    SUMA_RETURN(YUP);
6409 }
6410 
6411 /* Return a viewer's surface in focus, if there is a surface and it is
6412    in focus */
SUMA_SV_Focus_SO(SUMA_SurfaceViewer * sv)6413 SUMA_SurfaceObject *SUMA_SV_Focus_SO(SUMA_SurfaceViewer *sv)
6414 {
6415    static char FuncName[]={"SUMA_SV_Focus_SO"};
6416    if (!sv || sv->Focus_DO_ID < 0) return(NULL);
6417    if (SUMAg_DOv[sv->Focus_DO_ID].ObjectType == SO_type) {
6418       return((SUMA_SurfaceObject *)(SUMAg_DOv[sv->Focus_DO_ID].OP));
6419    }
6420    return(NULL);
6421 }
6422 
SUMA_SV_Focus_any_SO(SUMA_SurfaceViewer * sv,int * dov_id)6423 SUMA_SurfaceObject *SUMA_SV_Focus_any_SO(SUMA_SurfaceViewer *sv, int *dov_id)
6424 {
6425    static char FuncName[]={"SUMA_SV_Focus_any_SO"};
6426    SUMA_SurfaceObject *SO=NULL;
6427    int ii;
6428 
6429    if (dov_id) *dov_id = -1;
6430 
6431    if (sv && sv->Focus_DO_ID >= 0 &&
6432        SUMAg_DOv[sv->Focus_DO_ID].ObjectType == SO_type) {
6433       if (dov_id) *dov_id = sv->Focus_DO_ID;
6434       return((SUMA_SurfaceObject *)(SUMAg_DOv[sv->Focus_DO_ID].OP));
6435    }
6436 
6437    /* give me anything */
6438    SO = SUMA_findanySOp_inDOv(SUMAg_DOv, SUMAg_N_DOv, dov_id);
6439    return(SO);
6440 }
6441 
SUMA_SV_Focus_ADO(SUMA_SurfaceViewer * sv)6442 SUMA_ALL_DO *SUMA_SV_Focus_ADO(SUMA_SurfaceViewer *sv)
6443 {
6444    static char FuncName[]={"SUMA_SV_Focus_ADO"};
6445    if (!sv || sv->Focus_DO_ID < 0) return(NULL);
6446    return((SUMA_ALL_DO *)(SUMAg_DOv[sv->Focus_DO_ID].OP));
6447    return(NULL);
6448 }
6449 
SUMA_findanyFocusable_ADO(int * dov_id)6450 SUMA_ALL_DO *SUMA_findanyFocusable_ADO(int *dov_id)
6451 {
6452    static char FuncName[]={"SUMA_findanyFocusable_ADO"};
6453    SUMA_ALL_DO *ado=NULL;
6454    int ii;
6455    void *pp;
6456 
6457    if (dov_id) *dov_id = -1;
6458    if ((ado = (SUMA_ALL_DO *)SUMA_findanySOp_inDOv(
6459                         SUMAg_DOv, SUMAg_N_DOv, dov_id))) return(ado);
6460    if ((ado = (SUMA_ALL_DO *)SUMA_FindDset_eng("NA",
6461                         SUMAg_CF->DsetList, NULL, "isGraphDset"))) return(ado);
6462    if ((ado = (SUMA_ALL_DO *)SUMA_findanyVOp_inDOv(
6463                         SUMAg_DOv, SUMAg_N_DOv, dov_id))) return(ado);
6464    if ((ado = (SUMA_ALL_DO *)SUMA_findanyTDOp_inDOv(
6465                         SUMAg_DOv, SUMAg_N_DOv, dov_id))) return(ado);
6466    return(NULL);
6467 }
6468 
SUMA_SV_Focus_any_ADO(SUMA_SurfaceViewer * sv,int * dov_id)6469 SUMA_ALL_DO *SUMA_SV_Focus_any_ADO(SUMA_SurfaceViewer *sv, int *dov_id)
6470 {
6471    static char FuncName[]={"SUMA_SV_Focus_any_ADO"};
6472    SUMA_ALL_DO *ado=NULL;
6473    int ii;
6474 
6475    if (dov_id) *dov_id = -1;
6476 
6477    if (sv && sv->Focus_DO_ID >= 0) {
6478       if (dov_id) *dov_id = sv->Focus_DO_ID;
6479       return((SUMA_ALL_DO *)(SUMAg_DOv[sv->Focus_DO_ID].OP));
6480    }
6481 
6482    /* give me anything */
6483    ado = SUMA_findanyFocusable_ADO(dov_id);
6484    return(ado);
6485 }
6486 
SUMA_SV_any_ADO_WithSurfContWidget(SUMA_SurfaceViewer * sv,int * dov_id,SUMA_DO_Types thisdotp)6487 SUMA_ALL_DO *SUMA_SV_any_ADO_WithSurfContWidget(SUMA_SurfaceViewer *sv,
6488                                          int *dov_id, SUMA_DO_Types thisdotp)
6489 {
6490    static char FuncName[]={"SUMA_SV_any_ADO_WithSurfContWidget"};
6491    SUMA_ALL_DO *ado=NULL;
6492    SUMA_X_SurfCont *SurfCont=NULL;
6493    int ii;
6494 
6495    if (dov_id) *dov_id = -1;
6496 
6497    if (sv && sv->Focus_DO_ID >= 0 &&
6498        (SurfCont = SUMA_ADO_Cont(
6499                         (SUMA_ALL_DO *)(SUMAg_DOv[sv->Focus_DO_ID].OP))) &&
6500        SurfCont->TLS) {
6501       if (dov_id) *dov_id = sv->Focus_DO_ID;
6502       return((SUMA_ALL_DO *)(SUMAg_DOv[sv->Focus_DO_ID].OP));
6503    }
6504 
6505    /* give me anything */
6506    ado = SUMA_findany_ADO_WithSurfContWidget(dov_id, thisdotp);
6507    return(ado);
6508 }
6509 
SUMA_findany_ADO_WithSurfContWidget(int * dov_id,SUMA_DO_Types thisdotp)6510 SUMA_ALL_DO *SUMA_findany_ADO_WithSurfContWidget(int *dov_id,
6511                                                  SUMA_DO_Types thisdotp)
6512 {
6513    static char FuncName[]={"SUMA_findany_ADO_WithSurfContWidget"};
6514    SUMA_ALL_DO *ado=NULL;
6515    SUMA_DO_Types ttv[N_DO_TYPES] = { SO_type, GRAPH_LINK_type,
6516                                      VO_type, TRACT_type, CDOM_type,
6517                                      NOT_SET_type };
6518    int ii, tt;
6519    void *pp;
6520    SUMA_X_SurfCont *SurfCont=NULL;
6521 
6522    if (dov_id) *dov_id = -1;
6523    if (thisdotp != NOT_SET_type) {
6524       ttv[0] = thisdotp;
6525       ttv[1] = NOT_SET_type;
6526    }
6527 
6528    tt = 0;
6529    while (ttv[tt] != NOT_SET_type) {
6530       for (ii=0; ii<SUMAg_N_DOv; ++ii) {
6531          if (iDO_type(ii) == ttv[tt]) {
6532             ado = iDO_ADO(ii);
6533             if ((SurfCont = SUMA_ADO_Cont(ado)) &&
6534                 SurfCont->TLS) {
6535                 if (dov_id) *dov_id = ii;
6536                 return(ado);
6537             }
6538          }
6539       }
6540       ++tt;
6541    }
6542    return(NULL);
6543 }
6544 
SUMA_SurfCont_GetcurDOp(SUMA_X_SurfCont * SurfCont)6545 SUMA_ALL_DO *SUMA_SurfCont_GetcurDOp(SUMA_X_SurfCont *SurfCont)
6546 {
6547    static char FuncName[]={"SUMA_SurfCont_GetcurDOp"};
6548    SUMA_Boolean LocalHead = NOPE;
6549 
6550    if (SurfCont && SurfCont->prv_curDOp) {
6551       SUMA_ALL_DO *ado = (SUMA_ALL_DO *)*(SurfCont->prv_curDOp);
6552       if (!ado) return(NULL); /* This will happen if controller not yet open */
6553       SUMA_LHv("ADO Type name %s, variant %s\n",
6554                ADO_TNAME(ado), SurfCont->prv_variant);
6555       switch (ado->do_type) {
6556          case GRAPH_LINK_type:
6557             SUMA_S_Err("This should not be, See SUMA_SurfCont_SetcurDOp");
6558             return(NULL);
6559             break;
6560          case GDSET_type:
6561             return((SUMA_ALL_DO *)SUMA_find_Dset_GLDO((SUMA_DSET *)ado,
6562                                                  SurfCont->prv_variant,NULL));
6563             break;
6564          default:
6565             return(ado);
6566             break;
6567       }
6568    }
6569    return(NULL);
6570 }
6571 
SUMA_SurfCont_SetcurDOp(SUMA_X_SurfCont * SurfCont,SUMA_ALL_DO * ado)6572 SUMA_Boolean SUMA_SurfCont_SetcurDOp(SUMA_X_SurfCont *SurfCont, SUMA_ALL_DO *ado)
6573 {
6574    static char FuncName[]={"SUMA_SurfCont_SetcurDOp"};
6575    SUMA_Boolean LocalHead = NOPE;
6576 
6577    if (!(SurfCont && SurfCont->prv_curDOp && ado)) return(NOPE);
6578 
6579    switch(ado->do_type) {
6580       case SO_type:
6581          *(SurfCont->prv_curDOp) = (void *)ado;
6582          return(YUP);
6583          break;
6584       case GRAPH_LINK_type: /* Store the GDSET, a pointer of some permanence,
6585                                NOT gldo which has no right to property*/
6586          *(SurfCont->prv_curDOp) =
6587                (void *)SUMA_find_GLDO_Dset((SUMA_GraphLinkDO*)ado);
6588          SurfCont->prv_variant = SUMA_replace_string(SurfCont->prv_variant,
6589                                                    SUMA_ADO_variant(ado));
6590          SUMA_LHv("Now have %p, %s\n",
6591                   *(SurfCont->prv_curDOp), SurfCont->prv_variant);
6592          return(YUP);
6593          break;
6594       case GDSET_type:
6595          SUMA_S_Err( "You should not set the current DOp to a DO that has\n"
6596                      "ambiguous rendering\n");
6597          return(NOPE);
6598          break;
6599          SUMA_S_Err("Have to figure out this machinery");
6600          return(NOPE);
6601          break;
6602       case CDOM_type:
6603       case TRACT_type:
6604          *(SurfCont->prv_curDOp) = (void *)ado;
6605          return(YUP);
6606          break;
6607       case MASK_type:
6608       case VO_type:
6609          *(SurfCont->prv_curDOp) = (void *)ado;
6610          return(YUP);
6611          break;
6612       default:
6613          SUMA_S_Warnv("Not ready for the likes of %s\n",
6614                      SUMA_ObjectTypeCode2ObjectTypeName(ado->do_type));
6615          return(NOPE);
6616          break;
6617    }
6618    return(NOPE);
6619 
6620 }
6621 
6622 
SUMA_SetMouseMode(SUMA_SurfaceViewer * sv,SUMA_MOUSE_MODES mmode,void * val)6623 SUMA_Boolean SUMA_SetMouseMode(SUMA_SurfaceViewer *sv,
6624                                SUMA_MOUSE_MODES mmode, void *val)
6625 {
6626    static char FuncName[]={"SUMA_SetMouseMode"};
6627    int ival;
6628    SUMA_ALL_DO *ado;
6629    SUMA_Boolean LocalHead = NOPE;
6630 
6631    SUMA_ENTRY;
6632 
6633    if (!sv) SUMA_RETURN(NOPE);
6634 
6635    SUMA_LH("Should this function handle cross hair modification?");
6636 
6637    switch (mmode) {
6638       case SUMA_ROI_MMODE:
6639          ival = (int)(long int)val; /* Double cast to quiet compiler warning */
6640          if (ival) {
6641             if (SUMAg_CF->ROI_mode==YUP) { /* nothing to do */
6642                SUMA_RETURN(YUP);
6643             } else {
6644                /* Need to turn on ROI_mode, and kill other modes */
6645                SUMAg_CF->ROI_mode = YUP;  // [PT: Feb 22, 2021] fix '='
6646                sv->MouseMode = SUMA_DEF_MMODE;
6647                SUMA_RETURN(YUP);
6648             }
6649          } else {
6650             if (SUMAg_CF->ROI_mode==NOPE) { /* nothing to do */
6651                SUMA_RETURN(YUP);
6652             } else {
6653                /* Need to turn off ROI_mode */
6654                SUMAg_CF->ROI_mode = NOPE; // [PT: Feb 22, 2021] fix '='
6655                SUMA_RETURN(YUP);
6656             }
6657          }
6658          break;
6659       case SUMA_MASK_MANIP_MMODE:
6660          if (val) {
6661             if (SUMAg_CF->ROI_mode == YUP) SUMAg_CF->ROI_mode = NOPE;
6662             sv->MouseMode = SUMA_MASK_MANIP_MMODE;
6663             if ((ado=SUMA_whichADOg(sv->MouseMode_ado_idcode_str)) &&
6664                  ado->do_type == MASK_type) {
6665                SUMA_MDO_New_parent((SUMA_MaskDO*)ado, val, -1);
6666             }
6667             SUMA_ifree(sv->MouseMode_ado_idcode_str);
6668             sv->MouseMode_ado_idcode_str = SUMA_copy_string((char*)val);
6669          } else if (sv->MouseMode == SUMA_MASK_MANIP_MMODE) {
6670                                  sv->MouseMode = SUMA_DEF_MMODE;
6671             SUMA_ifree(sv->MouseMode_ado_idcode_str);
6672             if ((ado=SUMA_whichADOg(sv->MouseMode_ado_idcode_str)) &&
6673                  ado->do_type == MASK_type) {
6674                SUMA_MDO_New_parent((SUMA_MaskDO*)ado, NULL, -1);
6675             }
6676          }
6677          SUMA_RETURN(YUP);
6678          break;
6679       case SUMA_DEF_MMODE:
6680          sv->MouseMode = SUMA_DEF_MMODE;
6681          SUMA_RETURN(YUP);
6682          break;
6683       default:
6684          SUMA_S_Err("Not ready for %d", mmode);
6685          break;
6686    }
6687    SUMA_RETURN(NOPE);
6688 }
6689 
SUMA_ADO_ContName(SUMA_ALL_DO * ado)6690 char *SUMA_ADO_ContName(SUMA_ALL_DO *ado)
6691 {
6692    if (!ado) return("NULL");
6693    switch(ado->do_type) {
6694       case MASK_type:
6695          return ("Mask");
6696       case GRAPH_LINK_type:
6697          return ("Graph");
6698       case TRACT_type:
6699          return ("Network");
6700       case VO_type:
6701          return ("Volume");
6702       case SO_type:
6703          return ("Surface");
6704       default:
6705          return ("Not set");
6706    }
6707    return("Should not get here");
6708 }
6709 
6710