1 #include "SUMA_suma.h"
2 #include "coxplot.h"
3 #include "SUMA_plot.h"
4 
5 extern int selenium_close(void) ;
6 
7 /*! Parts of the code in this file are based on code from the motif programming manual.
8     This fact is mentioned at relevant spots in the code but the complete copyright
9     notice is only copied here for brevity:
10        * Written by Dan Heller and Paula Ferguson.
11        * Copyright 1994, O'Reilly & Associates, Inc.
12        * Permission to use, copy, and modify this program without
13        * restriction is hereby granted, as long as this copyright
14        * notice appears in each copy of the program source code.
15        * This program is freely distributable without licensing fees and
16        * is provided without guarantee or warrantee expressed or implied.
17        * This program is -not- in the public domain.
18 */
19 
20 /*! Widget initialization */
21 static int snglBuf[] = {GLX_RGBA, GLX_DEPTH_SIZE, 16,
22    GLX_RED_SIZE, 1, GLX_BLUE_SIZE, 1, GLX_GREEN_SIZE, 1,  None};
23 /* May 2013: Added GLX_ALPHA_SIZE, 1 for visual to get color picking to work.
24              Without it, there was always what looked like antialiasing that
25              resulted in more colors rendered than specified, no matter
26              what I disabled                                            */
27 
28 #define MULTICONV 0        /* Obsolete */
29 #define MULTISAMPLE 0      /* Does not make any difference relative to
30                               current defaults */
31 
32 #if MULTICONV
33 /* No more GLX_ACCUM business, no longer supported GL3.0+  */
34 static int dblBuf[] = {GLX_RGBA, GLX_DEPTH_SIZE, 16,
35   GLX_RED_SIZE, 1, GLX_BLUE_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_ALPHA_SIZE, 1,
36   GLX_DOUBLEBUFFER, GLX_STENCIL_SIZE, 1,
37   GLX_ACCUM_RED_SIZE, 1,   GLX_ACCUM_GREEN_SIZE, 1,
38   GLX_ACCUM_BLUE_SIZE, 1,   GLX_ACCUM_ALPHA_SIZE, 1,
39   None};
40 #elif MULTISAMPLE
41 /* Makes no difference to regular situation. I need blurring, not
42    just multisampling. For that, I'll need to use GLSL */
43 static int dblBuf[] = {GLX_RGBA, GLX_DEPTH_SIZE, 16,
44   GLX_RED_SIZE, 1, GLX_BLUE_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_ALPHA_SIZE, 1,
45   GLX_DOUBLEBUFFER, GLX_STENCIL_SIZE, 1,
46   GLX_SAMPLE_BUFFERS, 1, GLX_SAMPLES, 8,
47   None};
48 #else
49 static int dblBuf[] = {GLX_RGBA, GLX_DEPTH_SIZE, 16,
50   GLX_RED_SIZE, 1, GLX_BLUE_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_ALPHA_SIZE, 1,
51   GLX_DOUBLEBUFFER, GLX_STENCIL_SIZE, 1,
52   None};
53 #endif
54 
55 static String fallbackResources_default[] = {
56    "*glxarea*width: 300", "*glxarea*height: 300",
57    "*frame*x: 20", "*frame*y: 20",
58    "*frame*topOffset: 20", "*frame*bottomOffset: 20",
59    "*frame*rightOffset: 20", "*frame*leftOffset: 20",
60    "*frame*shadowType: SHADOW_IN",
61    "*fontList:              9x15bold=charset1"    ,
62    "*pbar*fontList:         6x10=charset1"        ,
63    "*imseq*fontList:        7x13=charset1"        ,
64    "*font8*fontList:        8x13=charset1"        ,
65    "*font7*fontList:        7x13=charset1"        ,
66    "*font6*fontList:        6x10=charset1"        ,
67    "*table*fontList:        9x15bold=charset1"    ,
68    "*background:            gray50"               ,
69    "*menu*background:       gray30"               ,
70    "*borderColor:           gray30"               ,
71    "*foreground:            black"               ,
72    "*borderWidth:           0"                    ,
73    "*troughColor:           green"                ,
74    "*XmLabel.translations:  #override<Btn2Down>:" , /* Motif 2.0 bug */
75    "*help*background:       black"                ,
76    "*help*foreground:       yellow"               ,
77    "*help*helpborder:       False"                ,
78    "*help*waitPeriod:       1066"                 ,
79    "*help*fontList:         9x15bold=charset1"    ,
80    "*cluefont:              9x15bold"             ,
81    "*help*cancelWaitPeriod: 50"                   ,
82    "*hotcolor:              blue2"               ,
83    "*buthighlight:          gray60"               ,
84    "*XmList.translations: #override"                /* 24 Feb 2007 */
85         "<Btn4Down>: ListPrevItem()\\n"
86         "<Btn5Down>: ListNextItem()"                  ,
87    "*XmText.translations: #override"
88         "<Btn4Down>: previous-line()\\n"
89         "<Btn5Down>: next-line()"                     ,
90    "*XmScrollBar.translations: #override"
91         "<Btn4Down>: IncrementUpOrLeft(0) IncrementUpOrLeft(1)\\n"
92         "<Btn5Down>: IncrementDownOrRight(1) IncrementDownOrRight(0)" ,
93   NULL
94 }; /* if you change default width and height, make sure you change SV->X->aWIDTH & SV->X->aHEIGHT in SUMA_SVmanip */
95 
96 static String fallbackResources_AFNI[] = {
97    "*glxarea*width: 300", "*glxarea*height: 300",
98    "*frame*x: 20", "*frame*y: 20",
99    "*frame*topOffset: 20", "*frame*bottomOffset: 20",
100    "*frame*rightOffset: 20", "*frame*leftOffset: 20",
101    "*frame*shadowType: SHADOW_IN",
102    "*fontList:              9x15bold=charset1"    ,
103    "*pbar*fontList:         6x10=charset1"        ,
104    "*imseq*fontList:        7x13=charset1"        ,
105    "*font8*fontList:        8x13=charset1"        ,
106    "*font7*fontList:        7x13=charset1"        ,
107    "*font6*fontList:        6x10=charset1"        ,
108    "*background:            gray30"               ,
109    "*menu*background:       gray30"               ,
110    "*borderColor:           gray30"               ,
111    "*foreground:            yellow"               ,
112    "*borderWidth:           0"                    ,
113    "*troughColor:           green"                ,
114    "*XmLabel.translations:  #override<Btn2Down>:" , /* Motif 2.0 bug */
115    "*help*background:       black"                ,
116    "*help*foreground:       yellow"               ,
117    "*help*helpborder:       False"                ,
118    "*help*waitPeriod:       1066"                 ,
119    "*help*fontList:         9x15bold=charset1"    ,
120    "*cluefont:              9x15bold"             ,
121    "*help*cancelWaitPeriod: 50"                   ,
122    "*hotcolor:              blue2"               ,
123    "*buthighlight:          gray60"               ,
124    "*XmList.translations: #override"                /* 24 Feb 2007 */
125         "<Btn4Down>: ListPrevItem()\\n"
126         "<Btn5Down>: ListNextItem()"                  ,
127    "*XmText.translations: #override"
128         "<Btn4Down>: previous-line()\\n"
129         "<Btn5Down>: next-line()"                     ,
130    "*XmScrollBar.translations: #override"
131         "<Btn4Down>: IncrementUpOrLeft(0) IncrementUpOrLeft(1)\\n"
132         "<Btn5Down>: IncrementDownOrRight(1) IncrementDownOrRight(0)" ,
133   NULL
134 }; /* if you change default width and height, make sure you change SV->X->aWIDTH & SV->X->aHEIGHT in SUMA_SVmanip */
135 
136 static String fallbackResources_EURO[] = {
137    "*glxarea*width: 300", "*glxarea*height: 300",
138    "*frame*x: 20", "*frame*y: 20",
139    "*frame*topOffset: 20", "*frame*bottomOffset: 20",
140    "*frame*rightOffset: 20", "*frame*leftOffset: 20",
141    "*frame*shadowType: SHADOW_IN",
142    "*fontList:              9x15=charset1"    ,
143    "*font8*fontList:        8x13=charset1"        ,
144    "*font7*fontList:        7x13=charset1"        ,
145    "*font6*fontList:        6x10=charset1"        ,
146    "*table*fontList:        9x15bold=charset1"    ,
147    "*pbar*fontList:         6x10=charset1"        ,
148    "*imseq*fontList:        7x13=charset1"        ,
149    "*background:            black"               ,
150    "*menu*background:       gray70"               ,
151    "*borderColor:           gray70"               ,
152    "*foreground:            white"               ,
153    "*borderWidth:           0"                    ,
154    "*troughColor:           LightCyan2"                ,
155    "*XmLabel.translations:  #override<Btn2Down>:" , /* Motif 2.0 bug */
156    "*help*background:       black"                ,
157    "*help*foreground:       yellow"               ,
158    "*help*helpborder:       False"                ,
159    "*help*waitPeriod:       1066"                 ,
160    "*help*fontList:         9x15=charset1"    ,
161    "*cluefont:              9x15"             ,
162    "*help*cancelWaitPeriod: 50"                   ,
163    "*hotcolor:              blue2"               ,
164    "*buthighlight:          gray60"               ,
165    "*XmList.translations: #override"                /* 24 Feb 2007 */
166         "<Btn4Down>: ListPrevItem()\\n"
167         "<Btn5Down>: ListNextItem()"                  ,
168    "*XmText.translations: #override"
169         "<Btn4Down>: previous-line()\\n"
170         "<Btn5Down>: next-line()"                     ,
171    "*XmScrollBar.translations: #override"
172         "<Btn4Down>: IncrementUpOrLeft(0) IncrementUpOrLeft(1)\\n"
173         "<Btn5Down>: IncrementDownOrRight(1) IncrementDownOrRight(0)" ,
174   NULL
175 }; /* if you change default width and height, make sure you change SV->X->aWIDTH & SV->X->aHEIGHT in SUMA_SVmanip */
176 
177 static String fallbackResources_PRINT[] = {
178    "*glxarea*width: 300", "*glxarea*height: 300",
179    "*frame*x: 20", "*frame*y: 20",
180    "*frame*topOffset: 20", "*frame*bottomOffset: 20",
181    "*frame*rightOffset: 20", "*frame*leftOffset: 20",
182    "*frame*shadowType: SHADOW_IN",
183    "*fontList:              9x15=charset1"    ,
184    "*font8*fontList:        8x13=charset1"        ,
185    "*font7*fontList:        7x13=charset1"        ,
186    "*font6*fontList:        6x10=charset1"        ,
187    "*table*fontList:        9x15bold=charset1"    ,
188    "*pbar*fontList:         6x10=charset1"        ,
189    "*imseq*fontList:        7x13=charset1"        ,
190    "*background:            white"               ,
191    "*menu*background:       gray10"               ,
192    "*borderColor:           gray10"               ,
193    "*foreground:            black"               ,
194    "*borderWidth:           0"                    ,
195    "*troughColor:           LightCyan2"                ,
196    "*XmLabel.translations:  #override<Btn2Down>:" , /* Motif 2.0 bug */
197    "*help*background:       white"                ,
198    "*help*foreground:       gray70"               ,
199    "*help*helpborder:       False"                ,
200    "*help*waitPeriod:       1066"                 ,
201    "*help*fontList:         9x15=charset1"    ,
202    "*cluefont:              9x15"             ,
203    "*help*cancelWaitPeriod: 50"                   ,
204    "*hotcolor:              blue2"               ,
205    "*buthighlight:          gray20"               ,
206    "*XmList.translations: #override"                /* 24 Feb 2007 */
207         "<Btn4Down>: ListPrevItem()\\n"
208         "<Btn5Down>: ListNextItem()"                  ,
209    "*XmText.translations: #override"
210         "<Btn4Down>: previous-line()\\n"
211         "<Btn5Down>: next-line()"                     ,
212    "*XmScrollBar.translations: #override"
213         "<Btn4Down>: IncrementUpOrLeft(0) IncrementUpOrLeft(1)\\n"
214         "<Btn5Down>: IncrementDownOrRight(1) IncrementDownOrRight(0)" ,
215   NULL
216 }; /* if you change default width and height, make sure you change SV->X->aWIDTH & SV->X->aHEIGHT in SUMA_SVmanip */
217 
218 static String fallbackResources_Bonaire[] = {
219    "*glxarea*width: 300", "*glxarea*height: 300",
220    "*frame*x: 20", "*frame*y: 20",
221    "*frame*topOffset: 20", "*frame*bottomOffset: 20",
222    "*frame*rightOffset: 20", "*frame*leftOffset: 20",
223    "*frame*shadowType: SHADOW_IN",
224    "*fontList:              9x15bold=charset1"    ,
225    "*font8*fontList:        8x13=charset1"        ,
226    "*font7*fontList:        7x13=charset1"        ,
227    "*font6*fontList:        6x10=charset1"        ,
228    "*table*fontList:        9x15bold=charset1"    ,
229    "*pbar*fontList:         6x10=charset1"        ,
230    "*imseq*fontList:        7x13=charset1"        ,
231    "*background:            navy"               ,
232    "*menu*background:       gray30"               ,
233    "*borderColor:           gray30"               ,
234    "*foreground:            LightCyan2"               ,
235    "*borderWidth:           0"                    ,
236    "*troughColor:           green"                ,
237    "*XmLabel.translations:  #override<Btn2Down>:" , /* Motif 2.0 bug */
238    "*help*background:       black"                ,
239    "*help*foreground:       yellow"               ,
240    "*help*helpborder:       False"                ,
241    "*help*waitPeriod:       1066"                 ,
242    "*help*fontList:         9x15bold=charset1"    ,
243    "*cluefont:              9x15bold"             ,
244    "*help*cancelWaitPeriod: 50"                   ,
245    "*hotcolor:              azure"               ,
246    "*buthighlight:          gray20"               ,
247    "*XmList.translations: #override"                /* 24 Feb 2007 */
248         "<Btn4Down>: ListPrevItem()\\n"
249         "<Btn5Down>: ListNextItem()"                  ,
250    "*XmText.translations: #override"
251         "<Btn4Down>: previous-line()\\n"
252         "<Btn5Down>: next-line()"                     ,
253    "*XmScrollBar.translations: #override"
254         "<Btn4Down>: IncrementUpOrLeft(0) IncrementUpOrLeft(1)\\n"
255         "<Btn5Down>: IncrementDownOrRight(1) IncrementDownOrRight(0)" ,
256   NULL
257 }; /* if you change default width and height, make sure you change SV->X->aWIDTH & SV->X->aHEIGHT in SUMA_SVmanip */
258 
259 /* DO NOT USE THESE, keep here for record */
260 static char SUMA_TEXT_WIDGET_TRANSLATIONS[] =
261    "  <Btn4Down>: previous-line()   \n\
262       <Btn5Down>: next-line()       ";
263 static char SUMA_SCR_LIST_WIDGET_TRANSLATIONS[] =
264    "  <Btn4Down>: ListPrevItem() \n\
265       <Btn5Down>: ListNextItem() ";
266 
267 
268 
269 /*!
270 
271 - use matlab script readXcol to choose different color settings
272 */
273 
SUMA_get_fallbackResources()274 String *SUMA_get_fallbackResources ()
275 {
276    static char FuncName[]={"SUMA_get_fallbackResources"};
277 
278    SUMA_ENTRY;
279 
280    switch (SUMAg_CF->X->X_Resources) {
281       case SXR_Afni:
282          SUMA_RETURN (fallbackResources_AFNI);
283          break;
284       case SXR_Euro:
285          SUMA_RETURN (fallbackResources_EURO);
286          break;
287       case SXR_Bonaire:
288          SUMA_RETURN (fallbackResources_Bonaire);
289          break;
290       case SXR_Print:
291          SUMA_RETURN (fallbackResources_PRINT);
292          break;
293       case SXR_default:
294       default:
295          SUMA_RETURN (fallbackResources_default);
296    }
297 
298 }
299 
300 static SUMA_Boolean PleaseDoMakeCurrent;
301 
SUMA_SiSi_I_Insist(void)302 void SUMA_SiSi_I_Insist(void)
303 {
304    PleaseDoMakeCurrent = YUP;
305 }
306 
307 /* A function that can guess at to whether or not a call to
308 glXMakeCurrent is needed. Eventually, I should no longer use
309 SUMA_SiSi_I_Insist() */
SUMA_glXMakeCurrent(Display * dpy,Window wdw,GLXContext cont,char * fname,char * wlab,int force)310 SUMA_Boolean SUMA_glXMakeCurrent(Display *dpy, Window wdw, GLXContext cont,
311       char *fname, char *wlab, int force)
312 {
313    static char FuncName[]={"SUMA_glXMakeCurrent"};
314    SUMA_Boolean LocalHead = NOPE;
315 
316    SUMA_ENTRY;
317 
318       /* An OpenGL rendering context is a port through which all OpenGL
319          commands pass. */
320       /* Before rendering, a rendering context must be bound to the desired
321       drawable using glXMakeCurrent. OpenGL rendering commands implicitly use the
322       current bound rendering context and one drawable. Just as a
323       program can create multiple windows, a program can create multiple OpenGL
324       rendering contexts. But a thread can only be bound to one rendering context
325       and drawable at a time. Once bound, OpenGL rendering can begin.
326       glXMakeCurrent can be called again to bind to a different window and/or
327       rendering context. */
328 
329    if (force || cont != SUMAg_CF->X->Cr->last_context ||
330                 dpy != SUMAg_CF->X->Cr->last_context_DPY ||
331                 wdw != SUMAg_CF->X->Cr->last_context_WDW ) {
332 
333       SUMAg_CF->X->Cr->last_context_DPY = NULL; /* This will be a clear
334                                                  record of failure to
335                                                  set last context */
336       snprintf(SUMAg_CF->X->Cr->setting_function, 62,"%s",
337                fname ? fname : "NOT_SET");
338       snprintf(SUMAg_CF->X->Cr->widget_label, 62,"%s",
339                wlab ? wlab : "NOT_SET");
340       SUMA_LH("About to make current %s, %s (dpy %p %ld %ld, force %d)",
341                fname, wlab, dpy, (long int)wdw, (long int)cont, force);
342       if (!glXMakeCurrent (dpy, wdw, cont)) {
343          SUMA_S_Err("Failed in glXMakeCurrent.\n");
344          SUMA_GL_ERRS;
345          SUMA_EDUMP_TRACE("Called from %s", FuncName);
346          SUMA_RETURN(NOPE);
347       }
348 
349       SUMAg_CF->X->Cr->last_context = cont;
350       SUMAg_CF->X->Cr->last_context_DPY = dpy;
351       SUMAg_CF->X->Cr->last_context_WDW = wdw;
352    } else {
353       SUMA_LHv("No current making needed from %s, label %s\n",
354                fname?fname:"NULL", wlab?wlab:"NULL");
355    }
356    SUMA_RETURN(YUP);
357 }
358 
SUMA_handleRedisplay(XtPointer closure)359 Boolean SUMA_handleRedisplay(XtPointer closure)
360 {
361    static char FuncName[]={"SUMA_handleRedisplay"};
362    static int Last_isv = -1;
363    int isv;
364    char buf[32];
365    SUMA_SurfaceViewer *sv;
366    SUMA_Boolean LocalHead = NOPE;
367 
368    SUMA_ENTRY;
369 
370 
371    if (LocalHead) {
372       SUMA_REPORT_WICH_WIDGET_SV ((Widget)closure);
373    }
374 
375    /* determine the surface viewer that the widget belongs to */
376    SUMA_ANY_WIDGET2SV((Widget)closure, sv, isv);
377    if (isv < 0) {
378       fprintf (SUMA_STDERR,
379                "Error %s: Failed in macro SUMA_ANY_WIDGET2SV.\n", FuncName);
380       SUMA_RETURN(NOPE);
381    }
382 
383    /* NEED TO DO WITHOUT THIS SILLY LOGIC HERE.
384       SUMA_glXMakeCurrent() below should be able to figure out
385       on its own if a call to glXMakeCurrent is needed... */
386    if (Last_isv >= 0) {    /* first time function is called,
387                               no use for this variable yet */
388       if (isv != Last_isv) {/* need to call glXMakeCurrent */
389          if (!sv->Open) {
390             if (LocalHead)
391                fprintf (SUMA_STDERR,
392                         "%s: Redisplay request for a closed window. Skipping.\n",
393                         FuncName);
394             SUMA_RETURN(NOPE);
395          }else {
396             PleaseDoMakeCurrent = YUP;
397          }
398       }
399    } else {
400       if (!sv->Open) {
401             if (LocalHead)
402                fprintf (SUMA_STDERR,
403                         "%s: Redisplay request for a closed window. \n"
404                         "Not sure that is ever needed. Skipping.\n",
405                         FuncName);
406             SUMA_RETURN(NOPE);
407       }
408    }
409    #if 0 /* trying to fix horrible freeze on 10.5
410             Actually this is also needed on 10.7, turning this option
411             on fixes a crash which happens under the following scenario:
412             from suma_demo/afni, launch afni and run_suma with both hemis.,
413             't', the switch to inflated view, rotate colormap in AFNI,
414             'ctrl+s', load dset v2s.TS.lh.niml.dset, CRASH
415             For the crash to happen the surface controller, when first
416             opened needed to be initialized for FuncAfni dataset, that
417             is why I did the switching to the inflated view and did
418             one colormap rotation in AFNI. Otherwise it would initialize
419             with the convexity dset and it won't crash.
420             In the end I put in a judicious call to SUMA_SiSi_I_Insist()
421             in SUMA_LoadDsetOntoSO() to selectively set the rendering
422             context instead of doing it at each redraw.*/
423    SUMA_S_Note("Forcing Current Making");
424    PleaseDoMakeCurrent = YUP;
425    #endif
426 
427    sprintf(buf,"GLXAREA of sv %d", isv);
428    if (!SUMA_glXMakeCurrent (sv->X->DPY, XtWindow((Widget)closure),
429                         sv->X->GLXCONTEXT, FuncName, buf, PleaseDoMakeCurrent)) {
430       SUMA_S_Err("Failed in SUMA_glXMakeCurrent.\n");
431       SUMA_RETURN(NOPE);
432    }
433    PleaseDoMakeCurrent = NOPE;
434 
435    Last_isv = isv; /* store last surface viewer to call display */
436    /* call display for the proper surface viewer*/
437    if (LocalHead)
438       fprintf (SUMA_STDERR,
439                "%s: Calling SUMA_display with SV[%d], Pointer %p.\n",
440                FuncName, isv, sv);
441    SUMA_display(sv, SUMAg_DOv);
442    sv->X->REDISPLAYPENDING = 0;
443 
444    if (SUMAg_N_SVv > 1) {
445       if (LocalHead)
446          fprintf (SUMA_STDERR, "%s: Forcing display to finish.\n", FuncName);
447       /* When multiple viewers are open, the picking does not work at times
448          if you click around rapidly.
449          The problem seems to be caused by OpenGL being in a state corresponding
450          to that of the last viewer visited before coming to the current viewer.
451          Forcing gl to render after a redisplay pending for a
452          certain viewer is placed seems to reduce this problem significantly so
453          this fix will be adopted until a better one comes along.
454          This call does reduce the apparent speed of the display and might
455          cause momentum motion to be more blocky but the overload is minimal for
456          regular use.*/
457       glFinish();
458    }
459 
460    SUMA_RETURN(YUP);
461 }
462 
463 /*!
464    \brief, set culling for viewer:
465    action takes one of: "Apply" or "Restore": Settings based on sv->BF_Cull
466                                              With Apply, you get a notice on the screen,
467                                              use it sparingly
468                         "Off" or "Hold": Turn off culling, regardless of sv->BF_Cull
469                         "Front": Turn on front face culling, regardless of sv->BF_Cull
470                         "Back": Turn on back face culling, regardless of sv->BF_Cull
471 */
SUMA_CullOption(SUMA_SurfaceViewer * sv,const char * action)472 void SUMA_CullOption(SUMA_SurfaceViewer *sv, const char *action)
473 {
474    static char FuncName[]={"SUMA_CullOption"};
475    char ac;
476 
477    SUMA_ENTRY;
478 
479    if (!action) {
480       SUMA_S_Err("NULL action!");
481       SUMA_RETURNe;
482    }
483 
484    ac = SUMA_TO_LOWER_C(action[0]);
485 
486    if (ac == 'o' || ac == 'h') {
487       glDisable(GL_CULL_FACE);
488    } else if ( ac == 'b') {
489       glCullFace (GL_BACK);
490       glEnable (GL_CULL_FACE);
491    } else if ( ac == 'f') {
492       glCullFace (GL_FRONT);
493       glEnable (GL_CULL_FACE);
494    } else if ( ac == 'a' || ac == 'r') {
495       switch (sv->BF_Cull) {
496          case 0:
497             glDisable(GL_CULL_FACE);
498             if (ac == 'a') { SUMA_SLP_Note ("Culling disabled."); }
499             break;
500          case 1:
501             glCullFace (GL_BACK);
502             glEnable (GL_CULL_FACE);
503             if (ac == 'a') { SUMA_SLP_Note ("BackFace Culling enabled."); }
504             break;
505          case 2:
506             glCullFace (GL_FRONT);
507             glEnable (GL_CULL_FACE);
508             if (ac == 'a') { SUMA_SLP_Note ("FrontFace Culling enabled."); }
509             break;
510       }
511    }
512 
513    SUMA_RETURNe;
514 }
515 /*!
516 
517 Only w is used consistently, the other input varaibles may be null at times
518 always send GLXAREA widget in w otherwise you won't know what pointer to use with
519 SUMA_remove_workproc2's data
520 \sa SUMA_remove_workproc2
521 */
522 void
SUMA_postRedisplay(Widget w,XtPointer clientData,XtPointer call)523 SUMA_postRedisplay(Widget w,
524   XtPointer clientData, XtPointer call)
525 {
526    static char FuncName[]={"SUMA_postRedisplay"};
527    static XtPointer elvis;
528    int isv;
529    SUMA_SurfaceViewer *sv;
530    SUMA_Boolean LocalHead = NOPE;
531 
532    SUMA_ENTRY;
533 
534    /* determine the surface viewer that the widget belongs to */
535    SUMA_ANY_WIDGET2SV(w, sv, isv);
536    if (isv < 0) {
537       fprintf (SUMA_STDERR,
538                "Error %s: Failed in macro SUMA_ANY_WIDGET2SV.\n", FuncName);
539       SUMA_RETURNe;
540    } else {
541       if (LocalHead) {
542          if (sv->X->REDISPLAYPENDING) {
543             fprintf (SUMA_STDERR,
544                      "%s: Redisplay Pending. "
545                      "No new request registered for viewer %d.\n",
546                      FuncName, isv);
547          } else {
548             fprintf (SUMA_STDERR,
549                      "%s: Redisplay Pending registered for viewer %d.\n",
550                      FuncName, isv);
551          }
552       }
553    }
554 
555    if(!sv->X->REDISPLAYPENDING) {
556     /*sv->X->REDISPLAYID = XtAppAddWorkProc(sv->X->APP, handleRedisplay, 0);*/
557     SUMA_register_workproc( SUMA_handleRedisplay , (XtPointer)sv->X->GLXAREA );
558     sv->X->REDISPLAYPENDING = 1;
559    }
560 
561    SUMA_RETURNe;
562 }
563 
564 /*!
565    A function for displaying the results from a plane/surface intersection after it has been rendered into a list of connected
566    strips.
567   A sequence would be:
568     Eq = SUMA_Plane_Equation (...);
569     SPI = SUMA_Surf_Plane_Intersect (SO, Eq);
570     striplist = SUMA_SPI_to_EdgeStrips(SO, SPI);
571     SUMA_display_edge_striplist(striplist, &(SUMAg_SVv[0]), SO, "ShowEdges, ShowConnectedPoints, ShowPoints");
572 
573    "ShowEdges" Means to show the intersected edges
574    "ShowConnectedPoints" Means to show the intersection points with a segment joining them. These segments are
575                          not edges. They are meant to show how the intersected points form a strip(s)
576    "ShowPoints" Just show the intersection points (which lie on intersected edges).
577 */
SUMA_display_edge_striplist(DList * striplist,SUMA_SurfaceViewer * sv,SUMA_SurfaceObject * SO,char * DispOptions)578 SUMA_Boolean SUMA_display_edge_striplist(DList *striplist,
579                SUMA_SurfaceViewer *sv, SUMA_SurfaceObject *SO, char *DispOptions)
580 {
581    static char FuncName[]={"SUMA_display_edge_striplist"};
582    /* no need to worry about freeing the DOs. They go in SUMAg_DOv */
583    SUMA_SegmentDO *SDO = NULL, *SEDO=NULL;
584    SUMA_SphereDO *SPDO = NULL;
585    DListElmt *elm = NULL, *elmlist=NULL, *elmn=NULL;
586    SUMA_STRIP *strip=NULL;
587    int N_allEpath=0, N_allPpath=0, kstrip, ke=0, j, N_Epath, N_Ppath, isclosed;
588    float col_first[4], col_last[4], col_middle[4];
589    SUMA_Boolean LocalHead = NOPE;
590 
591    SUMA_ENTRY;
592 
593    if (dlist_size(striplist)) {
594       do {
595          if (!elm) elm = dlist_head(striplist);
596          else elm  = dlist_next(elm);
597          strip = (SUMA_STRIP *)elm->data;
598          N_allEpath += dlist_size(strip->Edges);
599          N_allPpath += dlist_size(strip->Points);
600       } while (elm != dlist_tail(striplist));
601    }
602 
603 
604    if (SUMA_iswordin_ci(DispOptions, "ShowEdges") == 1) {
605       if (N_allEpath) {
606          SUMA_LHv("Building SDO of %d edges from %d strips\n",
607                   N_allEpath, dlist_size(striplist));
608          if ((SDO = SUMA_Alloc_SegmentDO (N_allEpath,
609                         "SUMA_SPI_to_EdgeStrips_segs", 0,
610                         SO->idcode_str, 0, LS_type, SO_type, NULL))) {
611             SDO->do_type = LS_type;
612             SDO->colv = (GLfloat *)SUMA_malloc(4*sizeof(GLfloat)*SDO->N_n);
613             SDO->LineWidth = 4;
614             elmlist=NULL; kstrip = 0;
615             ke = 0;
616             do {
617                if (!elmlist) elmlist = dlist_head(striplist);
618                else elmlist  = dlist_next(elmlist);
619                strip = (SUMA_STRIP *)elmlist->data;
620                N_Epath = dlist_size(strip->Edges);
621                isclosed = SUMA_isEdgeStripClosed(strip->Edges, SO);
622                if (isclosed) {
623                   col_first[0] = col_first[3] = 1.0;
624                      col_first[1] = col_first[2] = 0.0;
625                   col_middle[1] = col_middle[3] = 1.0;
626                      col_middle[0] = col_middle[2] = 0.0;
627                   col_last[0] = col_last[1] = 0.0;
628                      col_last[2] = col_last[3] = 1.0;
629                } else {
630                   col_first[0] = col_first[3] = 1.0;
631                      col_first[1] = col_first[2] = 0.0;
632                   col_middle[0] = col_middle[1] = col_middle[3] = 1.0;
633                      col_middle[2] = 0.0;
634                   col_last[0] = col_last[1] = 0.0;
635                      col_last[2] = col_last[3] = 1.0;
636                }
637                SUMA_LHv("   SDO's strip #%d of %d edges (isclosed = %d)\n",
638                         kstrip, N_Epath, isclosed);
639                elm=NULL;
640                do{
641                   if (!elm) elm = dlist_head(strip->Edges);
642                   else elm = dlist_next(elm);
643                   if (elm==dlist_head(strip->Edges)) {
644                      SUMA_COPY_VEC( col_first,
645                                     &(SDO->colv[4*ke]), 4, float, GLfloat);
646                   } else if (elm==dlist_tail(strip->Edges)) {
647                      SUMA_COPY_VEC( col_last,
648                                     &(SDO->colv[4*ke]), 4, float, GLfloat);
649                   } else {
650                      SUMA_COPY_VEC( col_middle,
651                                     &(SDO->colv[4*ke]), 4, float, GLfloat); }
652                   for (j=0; j<3;++j) {
653                      SDO->n0[3*ke+j] =
654                            SO->NodeList[3*SO->EL->EL[(INT_CAST)elm->data][0]+j];
655                      SDO->n1[3*ke+j] =
656                            SO->NodeList[3*SO->EL->EL[(INT_CAST)elm->data][1]+j];
657                   }
658                   ++ke;
659                } while (elm != dlist_tail(strip->Edges));
660                ++kstrip;
661             }  while (elmlist != dlist_tail(striplist));
662             /* addDO */
663             if (!SUMA_AddDO(  SUMAg_DOv, &SUMAg_N_DOv,
664                               (void *)SDO, LS_type, SUMA_WORLD)) {
665                fprintf(SUMA_STDERR,
666                         "Error %s: Failed in SUMA_AddDO.\n", FuncName);
667                SUMA_RETURN(NOPE);
668             }
669             /* register DO with viewer */
670             if (!SUMA_RegisterDO(SUMAg_N_DOv-1, sv)) {
671                fprintf(SUMA_STDERR,
672                         "Error %s: Failed in SUMA_RegisterDO.\n", FuncName);
673                SUMA_RETURN(NOPE);
674             }
675          }
676       }
677    }
678 
679    if (SUMA_iswordin_ci(DispOptions, "ShowConnectedPoints") == 1) {
680       if (N_allEpath) {
681          SUMA_LHv("Building SPDO of %d points from %d strips\n",
682                   N_allEpath, dlist_size(striplist));
683          if ((SEDO = SUMA_Alloc_SegmentDO (N_allEpath,
684                         "SUMA_SPI_to_EdgeStrips_pointsegs", 1,
685                         SO->idcode_str, 0, OLS_type, SO_type, NULL))) {
686             SEDO->do_type = LS_type;
687             SEDO->colv = (GLfloat *)SUMA_malloc(4*sizeof(GLfloat)*SEDO->N_n);
688             SEDO->LineWidth = 2;
689             elmlist=NULL; kstrip = 0;
690             ke = 0;
691             do {
692                if (!elmlist) elmlist = dlist_head(striplist);
693                else elmlist  = dlist_next(elmlist);
694                strip = (SUMA_STRIP *)elmlist->data;
695                N_Ppath = dlist_size(strip->Points);
696                isclosed = SUMA_isEdgeStripClosed(strip->Edges, SO);
697                if (isclosed) {
698                   col_first[0] = col_first[3] = 1.0;
699                   col_first[1] = col_first[2] = 0.0;
700                   col_middle[1] = col_middle[3] = 1.0;
701                   col_middle[0] = col_middle[2] = 0.0;
702                   col_last[0] = col_last[1] = 0.0;
703                   col_last[2] = col_last[3] = 1.0;
704                } else {
705                   col_first[0] = col_first[3] = 1.0;
706                   col_first[1] = col_first[2] = 0.0;
707                   col_middle[0] = col_middle[1] =
708                   col_middle[3] = 1.0; col_middle[2] = 0.0;
709                   col_last[0] = col_last[1] = 0.0;
710                   col_last[2] = col_last[3] = 1.0;
711                }
712                SUMA_LHv("   SEDO's strip #%d of %d edges (isclosed = %d)\n",
713                            kstrip, N_Ppath, isclosed);
714                elm=NULL;
715                do{
716                   if (!elm) elm = dlist_head(strip->Points);
717                   else elm = dlist_next(elm);
718                   if (elm==dlist_head(strip->Points)) {
719                      SUMA_COPY_VEC(col_first, &(SEDO->colv[4*ke]),
720                                     4, float, GLfloat);
721                   } else if (elm==dlist_tail(strip->Points)) {
722                         SUMA_COPY_VEC(col_last, &(SEDO->colv[4*ke]),
723                                        4, float, GLfloat);
724                   } else { SUMA_COPY_VEC(col_middle, &(SEDO->colv[4*ke]),
725                                        4, float, GLfloat); }
726                   if (elm != dlist_tail(strip->Points)) {
727                      elmn = dlist_next(elm);
728                   } else {
729                      if (isclosed) elmn = dlist_head(strip->Points);
730                      else elmn = elm;
731                   }
732                   for (j=0; j<3;++j) {
733                      SEDO->n0[3*ke+j] = ((float*)elm->data)[j];
734                      SEDO->n1[3*ke+j] = ((float*)elmn->data)[j];
735                   }
736                   ++ke;
737                } while (elm != dlist_tail(strip->Points));
738                ++kstrip;
739             }  while (elmlist != dlist_tail(striplist));
740             /* addDO */
741             if (!SUMA_AddDO(SUMAg_DOv, &SUMAg_N_DOv,
742                             (void *)SEDO, OLS_type, SUMA_WORLD)) {
743                fprintf(SUMA_STDERR,
744                         "Error %s: Failed in SUMA_AddDO.\n", FuncName);
745                SUMA_RETURN(NOPE);
746             }
747             /* register DO with viewer */
748             if (!SUMA_RegisterDO(SUMAg_N_DOv-1, sv)) {
749                fprintf(SUMA_STDERR,
750                         "Error %s: Failed in SUMA_RegisterDO.\n", FuncName);
751                SUMA_RETURN(NOPE);
752             }
753          }
754       }
755    }
756 
757    if (SUMA_iswordin_ci(DispOptions, "ShowPoints") == 1) {
758       if (N_allPpath) {
759          SUMA_LHv("Building SPDO of %d points from %d strips\n",
760                   N_allPpath, dlist_size(striplist));
761          if ((SPDO = SUMA_Alloc_SphereDO (N_allPpath,
762                         "SUMA_SPI_to_EdgeStrips_points", NULL, SP_type))) {
763             SPDO->do_type = SP_type;
764             SPDO->CommonRad = SO->EL->AvgLe/6.0;
765             SPDO->colv = (GLfloat *)SUMA_malloc(4*sizeof(GLfloat)*SPDO->N_n);
766 
767             elmlist=NULL; kstrip = 0;
768             ke = 0;
769             do {
770                if (!elmlist) elmlist = dlist_head(striplist);
771                else elmlist  = dlist_next(elmlist);
772                strip = (SUMA_STRIP *)elmlist->data;
773                N_Ppath = dlist_size(strip->Points);
774                isclosed = SUMA_isEdgeStripClosed(strip->Edges, SO);
775                if (isclosed) {
776                   col_first[0] = col_first[3] = 1.0;
777                   col_first[1] = col_first[2] = 0.0;
778                   col_middle[0] = col_middle[1] =
779                      col_middle[2] = col_middle[3] = 1.0;
780                   col_last[0] = col_last[1] = 0.0;
781                   col_last[2] = col_last[3] = 1.0;
782                } else {
783                   col_first[0] = col_first[3] = 1.0;
784                   col_first[1] = col_first[2] = 0.0;
785                   col_middle[0] = col_middle[2] =
786                      col_middle[3] = 1.0; col_middle[1] = 0.0;
787                   col_last[0] = col_last[1] = 0.0;
788                   col_last[2] = col_last[3] = 1.0;
789                }
790                SUMA_LHv("   SPDO's strip #%d of %d points (isclosed=%d)\n",
791                         kstrip, N_Ppath, isclosed);
792                elm=NULL;
793                do{
794                   if (!elm) elm = dlist_head(strip->Points);
795                   else elm = dlist_next(elm);
796                   if (elm==dlist_head(strip->Points)) {
797                      SUMA_COPY_VEC(col_first, &(SPDO->colv[4*ke]),
798                                     4, float, GLfloat);
799                   } else if (elm==dlist_tail(strip->Points)) {
800                      SUMA_COPY_VEC(col_last, &(SPDO->colv[4*ke]),
801                                     4, float, GLfloat);
802                   } else {
803                      SUMA_COPY_VEC(col_middle, &(SPDO->colv[4*ke]),
804                                     4, float, GLfloat);  }
805                   SPDO->cxyz[3*ke  ] = ((float*)elm->data)[0];
806                   SPDO->cxyz[3*ke+1] = ((float*)elm->data)[1];
807                   SPDO->cxyz[3*ke+2] = ((float*)elm->data)[2];
808                   ++ke;
809                } while(elm != dlist_tail(strip->Points));
810                ++kstrip;
811             } while (elmlist != dlist_tail(striplist));
812             /* addDO */
813             if (!SUMA_AddDO(SUMAg_DOv, &SUMAg_N_DOv,
814                            (void *)SPDO, SP_type, SUMA_WORLD)) {
815                fprintf(SUMA_STDERR,
816                         "Error %s: Failed in SUMA_AddDO.\n", FuncName);
817                SUMA_RETURN(NOPE);
818             }
819 
820             /* register DO with viewer */
821             if (!SUMA_RegisterDO(SUMAg_N_DOv-1, sv)) {
822                fprintf(SUMA_STDERR,
823                         "Error %s: Failed in SUMA_RegisterDO.\n", FuncName);
824                SUMA_RETURN(NOPE);
825             }
826 
827          }
828 
829       }
830    }
831 
832 
833 
834    if (SDO || SPDO || SEDO) {
835       /* redisplay curent only*/
836       sv->ResetGLStateVariables = YUP;
837       SUMA_handleRedisplay((XtPointer)sv->X->GLXAREA);
838    }
839    SUMA_RETURN(YUP);
840 }
841 
SUMA_LoadMaskDO(char * s,void * csvp)842 void SUMA_LoadMaskDO (char *s, void *csvp )
843 {
844    static char FuncName[]={"SUMA_LoadMaskDO"};
845    SUMA_MaskDO *MDO = NULL;
846    SUMA_SurfaceViewer *sv;
847    SUMA_DO_Types dotp=not_DO_type;
848    SUMA_DO_CoordType coord_type=SUMA_WORLD;
849    void *VDO = NULL;
850    SUMA_Boolean LocalHead = NOPE;
851 
852    SUMA_ENTRY;
853 
854    SUMA_LH("Loading %s", s);
855    sv = (SUMA_SurfaceViewer *)csvp;
856 
857    if (!s) { SUMA_RETURNe; }
858 
859    /* what type are we dealing with ? */
860    dotp = SUMA_Guess_DO_Type(s);
861    if (dotp == not_DO_type) {
862       SUMA_S_Warnv("Could not determine DO type of %s, assuming MASK.",
863                      s);
864       /* assume mask */
865       dotp = MASK_type;
866    }
867    coord_type = SUMA_WORLD;
868    switch (dotp) {
869       case MASK_type: {
870          SUMA_MaskDO *MDO = NULL;
871          if (!(VDO = (void *)SUMA_ReadMaskDO(s, NULL))) {
872             SUMA_SL_Err("Failed to read tracts file.\n");
873             SUMA_RETURNe;
874          }
875          SUMA_NEW_MASKSTATE();
876          SUMA_LH("Mask read");
877          ((SUMA_MaskDO*)VDO)->do_type = dotp;
878          MDO = (SUMA_MaskDO *)VDO;
879          if (!SUMA_AccessorizeMDO(MDO)) {
880             SUMA_SL_Err("Failed to get lipstick on that pig.\n");
881             SUMA_RETURNe;
882          }
883          break; }
884       case NIDO_type:
885          if (!(VDO = (void *)SUMA_ReadNIDO(s, NULL))) {
886             SUMA_SL_Err("Failed to read spheres file.\n");
887             SUMA_RETURNe;
888          }
889          ((SUMA_NIDO * )VDO)->do_type = dotp;
890          coord_type = SUMA_CoordType(
891                   NI_get_attribute(((SUMA_NIDO * )VDO)->ngr,
892                                     "coord_type"));
893          if (!coord_type) {
894             SUMA_SL_Err("Bad coord_type");
895             SUMA_RETURNe;
896          }
897          break;
898       default:
899          SUMA_SL_Err("Should not get here");
900          SUMA_RETURNe;
901          break;
902    }
903 
904    /* addDO */
905    SUMA_LH("Adding DO");
906    if (!SUMA_AddDO(SUMAg_DOv, &SUMAg_N_DOv, VDO, dotp, coord_type)) {
907       fprintf(SUMA_STDERR,"Error %s: Failed in SUMA_AddDO.\n", FuncName);
908       SUMA_RETURNe;
909    }
910 
911    /* register DO with viewer */
912    SUMA_LH("Registrar");
913    if (!SUMA_RegisterDO(SUMAg_N_DOv-1, sv)) {
914       fprintf(SUMA_STDERR,"Error %s: Failed in SUMA_RegisterDO.\n", FuncName);
915       SUMA_RETURNe;
916    }
917 
918    SUMA_LH("Outa here");
919    /* redisplay curent only*/
920    if (sv) {
921       sv->ResetGLStateVariables = YUP;
922       SUMA_handleRedisplay((XtPointer)sv->X->GLXAREA);
923    }
924 
925    SUMA_RETURNe;
926 }
927 
SUMA_LoadSegDO(char * s,void * csvp)928 void SUMA_LoadSegDO (char *s, void *csvp )
929 {
930    static char FuncName[]={"SUMA_LoadSegDO"};
931    SUMA_SegmentDO *SDO = NULL;
932    SUMA_SurfaceViewer *sv;
933    SUMA_SurfaceObject *SO=NULL;
934    SUMA_DO_Types dotp=not_DO_type;
935    SUMA_MaskDO *MDO = NULL;
936    SUMA_DO_CoordType coord_type=SUMA_WORLD;
937    void *VDO = NULL;
938    SUMA_Boolean LocalHead = NOPE;
939 
940    SUMA_ENTRY;
941 
942    SUMA_LH("Loading %s", s);
943    sv = (SUMA_SurfaceViewer *)csvp;
944 
945    if (!s) { SUMA_RETURNe; }
946 
947    /* what type are we dealing with ? */
948    dotp = SUMA_Guess_DO_Type(s);
949    if (dotp == not_DO_type) {
950       SUMA_S_Warnv("Could not determine DO type of %s, assuming segments.",
951                      s);
952       /* assume segments */
953       dotp = LS_type;
954    }
955    coord_type = SUMA_WORLD;
956    switch (dotp) {
957       case TRACT_type:
958          if (!sv || !(SO = SUMA_SV_Focus_SO(sv))) {
959             SUMA_LH("No surface in focus to which the tracts "
960                         "would be attached. That's OK.\n");
961          }
962          if (!(VDO = (void *)SUMA_ReadTractDO(s, SO?SO->idcode_str:NULL))) {
963                SUMA_SL_Err("Failed to read tracts file.\n");
964                SUMA_RETURNe;
965          }
966          SUMA_LH("Tract read");
967          ((SUMA_TractDO*)VDO)->do_type = dotp;
968          break;
969       case ONBV_type:
970       case NBV_type:
971          if (!(SO = SUMA_SV_Focus_SO(sv))) {
972             SUMA_SL_Err("No surface in focus to which the vector "
973                         "would be attached.\n");
974             SUMA_RETURNe;
975          }
976          if (dotp == NBV_type) {
977             if (!(SDO = SUMA_ReadNBVecDO(s, 0, SO->idcode_str))) {
978                SUMA_SL_Err("Failed to read segments file.\n");
979                SUMA_RETURNe;
980             }
981          } else {
982             if (!(SDO = SUMA_ReadNBVecDO(s, 1, SO->idcode_str))) {
983                SUMA_SL_Err("Failed to read segments file.\n");
984                SUMA_RETURNe;
985             }
986          }
987          SDO->do_type = dotp;
988          VDO = (void *)SDO;
989          break;
990       case NBSP_type:
991          if (!(SO = SUMA_SV_Focus_SO(sv))) {
992             SUMA_SL_Err("No surface in focus to which "
993                         "the spheres would be attached.\n");
994             SUMA_RETURNe;
995          }
996          if (!(VDO = (void*)SUMA_ReadNBSphDO(s, SO->idcode_str))) {
997             SUMA_SL_Err("Failed to read spheres file.\n");
998             SUMA_RETURNe;
999          }
1000          ((SUMA_SphereDO * )VDO)->do_type = dotp;
1001          break;
1002       case OLS_type:
1003          if (!(SDO = SUMA_ReadSegDO(s, 1, NULL))) {
1004             SUMA_SL_Err("Failed to read segments file.\n");
1005             SUMA_RETURNe;
1006          }
1007          SDO->do_type = dotp;
1008          VDO = (void *)SDO;
1009          break;
1010       case LS_type:
1011          if (!(SDO = SUMA_ReadSegDO(s, 0, NULL))) {
1012             SUMA_SL_Err("Failed to read segments file.\n");
1013             SUMA_RETURNe;
1014          }
1015          SDO->do_type = dotp;
1016          VDO = (void *)SDO;
1017          break;
1018      case ODIR_type:
1019          if (!(SDO = SUMA_ReadDirDO(s, 1, NULL))) {
1020             SUMA_SL_Err("Failed to read directions file.\n");
1021             SUMA_RETURNe;
1022          }
1023          SDO->do_type = dotp;
1024          VDO = (void *)SDO;
1025          break;
1026      case DIR_type:
1027          if (!(SDO = SUMA_ReadDirDO(s, 0, NULL))) {
1028             SUMA_SL_Err("Failed to read directions file.\n");
1029             SUMA_RETURNe;
1030          }
1031          SDO->do_type = dotp;
1032          VDO = (void *)SDO;
1033          break;
1034       case NBOLS_type:
1035          if (!(SO = SUMA_SV_Focus_SO(sv))) {
1036             SUMA_SL_Err("No surface in focus to which "
1037                         "the spheres would be attached.\n");
1038             SUMA_RETURNe;
1039          }
1040          if (!(SDO = SUMA_ReadNBSegDO(s, 1, SO->idcode_str))) {
1041             SUMA_SL_Err("Failed to read segments file.\n");
1042             SUMA_RETURNe;
1043          }
1044          SDO->do_type = dotp;
1045          VDO = (void *)SDO;
1046          break;
1047       case NBLS_type:
1048          if (!(SO = SUMA_SV_Focus_SO(sv))) {
1049             SUMA_SL_Err("No surface in focus to which "
1050                         "the spheres would be attached.\n");
1051             SUMA_RETURNe;
1052          }
1053          if (!(SDO = SUMA_ReadNBSegDO(s, 0, SO->idcode_str))) {
1054             SUMA_SL_Err("Failed to read segments file.\n");
1055             SUMA_RETURNe;
1056          }
1057          SDO->do_type = dotp;
1058          VDO = (void *)SDO;
1059          break;
1060       case PNT_type:
1061          if (!(VDO = (void *)SUMA_ReadPntDO(s))) {
1062             SUMA_SL_Err("Failed to read points file.\n");
1063             SUMA_RETURNe;
1064          }
1065          ((SUMA_SphereDO * )VDO)->do_type = dotp;
1066          break;
1067       case SP_type:
1068          if (!(VDO = (void *)SUMA_ReadSphDO(s))) {
1069             SUMA_SL_Err("Failed to read spheres file.\n");
1070             SUMA_RETURNe;
1071          }
1072          ((SUMA_SphereDO * )VDO)->do_type = dotp;
1073          break;
1074       case PL_type:
1075          if (!(VDO = (void *)SUMA_ReadPlaneDO(s))) {
1076             SUMA_SL_Err("Failed to read spheres file.\n");
1077             SUMA_RETURNe;
1078          }
1079          ((SUMA_SphereDO * )VDO)->do_type = dotp;
1080          break;
1081       case NIDO_type:
1082          SO = SUMA_SV_Focus_SO(sv);
1083          if (!(VDO = (void *)SUMA_ReadNIDO(s, SO ? SO->idcode_str:NULL))) {
1084             SUMA_SL_Err("Failed to read spheres file.\n");
1085             SUMA_RETURNe;
1086          }
1087          ((SUMA_NIDO * )VDO)->do_type = dotp;
1088          coord_type = SUMA_CoordType(
1089                   NI_get_attribute(((SUMA_NIDO * )VDO)->ngr,
1090                                     "coord_type"));
1091          if (!coord_type) {
1092             SUMA_SL_Err("Bad coord_type");
1093             SUMA_RETURNe;
1094          }
1095          break;
1096       case MASK_type: {
1097          SUMA_S_Warn("Why the duplication with SUMA_LoadMaskDO?...");
1098          if (!(VDO = (void *)SUMA_ReadMaskDO(s, NULL))) {
1099             SUMA_SL_Err("Failed to read masks file.\n");
1100             SUMA_RETURNe;
1101          }
1102          SUMA_LH("Mask read");
1103          ((SUMA_MaskDO*)VDO)->do_type = dotp;
1104          MDO = (SUMA_MaskDO *)VDO;
1105          if (MDO_IS_BOX(MDO)) {
1106             SUMA_LH("Forming SO for box");
1107             if (!(MDO->SO = SUMA_box_surface(MDO->hdim, MDO->cen,
1108                                              MDO->dcolv, MDO->N_obj))) {
1109                SUMA_S_Err("Failed to create box SO!");
1110                SUMA_RETURNe;
1111             }
1112          } else if (MDO_IS_SPH(MDO)) {
1113             SUMA_S_Warn("Not ready for multi obj, or spheroidal objects");
1114             if (!(MDO->SO = SUMA_CreateIcosahedron(MDO->hdim[0], 2,
1115                      MDO->cen, "n", 1))) {
1116                SUMA_S_Err("Failed to create sphere SO!");
1117                SUMA_RETURNe;
1118             }
1119          } else {
1120             SUMA_S_Err("Not ready for prime time");
1121             SUMA_RETURNe;
1122          }
1123          break; }
1124       default:
1125          SUMA_EDUMP_TRACE("Should not get here, type %d", dotp);
1126          SUMA_RETURNe;
1127          break;
1128    }
1129 
1130    #if 0
1131    { /* a test for changing SDO formats */
1132       if (SDO) {
1133          NI_group *ngr = SUMA_SDO2niSDO(SDO);
1134          int suc;
1135          NEL_WRITE_TX(ngr, "file:mess.niml.SDO", suc);
1136          SUMA_S_Note("Wrote mess to disk");
1137          /* Now free SDO and reload from disk */
1138          SUMA_free_SegmentDO(SDO);
1139          SDO = SUMA_niSDO2SDO(ngr);
1140          NI_free_element(ngr); ngr = NULL;
1141          /* now repeat xformation and see what you get */
1142          ngr = SUMA_SDO2niSDO(SDO);
1143          NEL_WRITE_TX(ngr, "file:mess2.niml.SDO", suc);
1144          SUMA_S_Note("Wrote mess2 to disk");
1145          NI_free_element(ngr); ngr = NULL;
1146          VDO = (void *)SDO;
1147       }
1148    }
1149    #endif
1150 
1151    /* addDO */
1152    SUMA_LH("Adding DO");
1153    if (!SUMA_AddDO(SUMAg_DOv, &SUMAg_N_DOv, VDO, dotp, coord_type)) {
1154       fprintf(SUMA_STDERR,"Error %s: Failed in SUMA_AddDO.\n", FuncName);
1155       SUMA_RETURNe;
1156    }
1157 
1158    /* register DO with viewer */
1159    SUMA_LH("Registrar");
1160    if (!SUMA_RegisterDO(SUMAg_N_DOv-1, sv)) {
1161       fprintf(SUMA_STDERR,"Error %s: Failed in SUMA_RegisterDO.\n", FuncName);
1162       SUMA_RETURNe;
1163    }
1164 
1165    SUMA_LH("Outa here");
1166    /* redisplay curent only*/
1167    if (sv) {
1168       sv->ResetGLStateVariables = YUP;
1169       SUMA_handleRedisplay((XtPointer)sv->X->GLXAREA);
1170    }
1171 
1172    SUMA_RETURNe;
1173 }
1174 
1175 
1176 /*!
1177    \brief, retrieves an vector attribute
1178    and decodes it into m_fv (or m_dv for double). It is your
1179    job to make sure m_fv (or m_dv) is big enough
1180    for the endeavour
1181    m_fail is 1 if no such attribute is found
1182             2 if the number of values read is not = m_n
1183 */
1184 static int shutup;
1185 
1186 #define SUMA_S2FV_ATTR(m_nel, m_attr, m_fv, m_n, m_fail) {\
1187    char *m_atmp = NULL; \
1188    int m_nr = 0; \
1189    m_fail = 0; \
1190    m_atmp = NI_get_attribute(m_nel, m_attr); \
1191    if (!m_atmp) {   \
1192       if (LocalHead) \
1193          fprintf( SUMA_STDERR,\
1194                   "Error %s:\nNo such attribute (%s).", FuncName, m_attr);  \
1195       m_fail = 1; \
1196    }  \
1197    m_nr = SUMA_StringToNum(m_atmp, (void*)m_fv, m_n,1);  \
1198    if (m_nr != m_n) {  \
1199       if (LocalHead) \
1200          fprintf( SUMA_STDERR,\
1201                   "Error %s:\nBad attribute (%s) length.\n"\
1202                   "Expected %d, found %d\n",   \
1203                            FuncName, m_attr, m_n, m_nr);  \
1204       m_fail = 2; \
1205    }  \
1206 }
1207 
1208 #define SUMA_S2DV_ATTR(m_nel, m_attr, m_dv, m_n, m_fail) {\
1209    char *m_atmp = NULL; \
1210    int m_nr = 0; \
1211    m_fail = 0; \
1212    m_atmp = NI_get_attribute(m_nel, m_attr); \
1213    if (!m_atmp) {   \
1214       if (LocalHead) \
1215          fprintf( SUMA_STDERR,\
1216                   "Error %s:\nNo such attribute (%s).", FuncName, m_attr);  \
1217       m_fail = 1; \
1218    }  \
1219    m_nr = SUMA_StringToNum(m_atmp, (void*)m_dv, m_n,2);  \
1220    if (m_nr != m_n) {  \
1221       if (LocalHead) \
1222          fprintf( SUMA_STDERR,\
1223                   "Error %s:\nBad attribute (%s) length.\n"\
1224                   "Expected %d, found %d\n",   \
1225                            FuncName, m_attr, m_n, m_nr);  \
1226       m_fail = 2; \
1227    }  \
1228 }
1229 
1230 #define SUMA_FV2S_ATTR_TMP_STR   3000
1231 /*!
1232    \brief turns a vector into a string of floats
1233    The macro will fail if your vector ends up
1234    being more than SUMA_FV2S_ATTR_TMP_STR characters long.
1235    This macro is slow and stupid, don't use it for
1236    long vectors.
1237 */
1238 #define SUMA_FV2S_ATTR(m_nel, m_attr, m_fv, m_n, m_fail) {\
1239    int m_i; \
1240    char m_stmp[SUMA_FV2S_ATTR_TMP_STR], m_val[50];   \
1241    m_fail = 0; \
1242    m_i = 0; \
1243    m_stmp[0] = '\0'; \
1244    while (m_i < m_n && !(m_fail)) { \
1245       sprintf(m_val,"%f ", m_fv[m_i]); \
1246       if (strlen(m_stmp) + strlen(m_val) >= SUMA_FV2S_ATTR_TMP_STR -1) {   \
1247          fprintf(SUMA_STDERR,"Error %s\nVector exceeded buffer length.\n", FuncName);  \
1248          m_fail = 1; \
1249       } else { \
1250          SUMA_strncat (m_stmp, m_val, SUMA_FV2S_ATTR_TMP_STR-1); \
1251          ++ m_i;  \
1252       }\
1253    }  \
1254    NI_set_attribute (m_nel, m_attr, m_stmp);      \
1255 }
1256 
1257 #define SUMA_DV2S_ATTR(m_nel, m_attr, m_dv, m_n, m_fail) {\
1258    int m_i; \
1259    char m_stmp[SUMA_FV2S_ATTR_TMP_STR], m_val[50];   \
1260    m_fail = 0; \
1261    m_i = 0; \
1262    m_stmp[0] = '\0'; \
1263    while (m_i < m_n && !(m_fail)) { \
1264       sprintf(m_val,"%f ", m_dv[m_i]); \
1265       if (strlen(m_stmp) + strlen(m_val) >= SUMA_FV2S_ATTR_TMP_STR -1) {   \
1266          fprintf(SUMA_STDERR,"Error %s\nVector exceeded buffer length.\n", FuncName);  \
1267          m_fail = 1; \
1268       } else { \
1269          SUMA_strncat (m_stmp, m_val, SUMA_FV2S_ATTR_TMP_STR-1); \
1270          ++ m_i;  \
1271       }\
1272    }  \
1273    NI_set_attribute (m_nel, m_attr, m_stmp);      \
1274 }
1275 
1276 /*!
1277    \brief   A function to save the settings of a surface viewer
1278             for later recall
1279 */
SUMA_SaveVisualState(char * fname,void * csvp)1280 void SUMA_SaveVisualState(char *fname, void *csvp )
1281 {
1282    static char FuncName[]={"SUMA_SaveVisualState"};
1283    NI_element *nel = NULL;
1284    NI_stream nstdout;
1285    char stmp[500];
1286    char *fnamestmp=NULL, *fnamestmp2=NULL;
1287    int feyl;
1288    SUMA_SurfaceViewer *csv;
1289    Position X=0, Y=0;
1290    Dimension ScrW, ScrH;
1291    SUMA_Boolean LocalHead = NOPE;
1292 
1293    SUMA_ENTRY;
1294 
1295    csv = (SUMA_SurfaceViewer *)csvp;
1296 
1297    if (!csv) { SUMA_RETURNe; }
1298 
1299    if (csv->StdView < 0 || csv->iState < 0 ) { SUMA_RETURNe; }
1300 
1301    SUMA_allow_nel_use(1);
1302    nel = SUMA_NewNel (  SUMA_VIEWER_SETTING, /* one of SUMA_DSET_TYPE */
1303                         NULL, /* idcode of Domain Parent */
1304                         NULL, /* idcode of geometry parent, not useful here*/
1305                         0,
1306                         NULL,
1307                         NULL); /* Number of elements */
1308    if (!nel) {
1309       SUMA_SL_Err("Failed to create nel.");
1310       SUMA_RETURNe;
1311    }
1312 
1313    /* Save the relevant parameters */
1314    SUMA_FV2S_ATTR(nel, "currentQuat",
1315                   csv->GVS[csv->StdView].currentQuat, 4, feyl);
1316       if (feyl) { SUMA_RETURNe; }
1317    SUMA_FV2S_ATTR(nel, "translateVec",
1318                   csv->GVS[csv->StdView].translateVec, 2, feyl);
1319       if (feyl) { SUMA_RETURNe; }
1320    SUMA_FV2S_ATTR(nel, "clear_color", csv->clear_color, 4, feyl);
1321       if (feyl) { SUMA_RETURNe; }
1322    sprintf(stmp, "%f", csv->FOV[csv->iState]);
1323    NI_set_attribute (nel, "FOV", stmp);
1324    sprintf(stmp, "%f", csv->Aspect);
1325    NI_set_attribute (nel, "Aspect", stmp);
1326    sprintf(stmp, "%d", csv->wWindWidth);
1327    NI_set_attribute (nel, "WindWidth", stmp);
1328    sprintf(stmp, "%d", csv->wWindHeight);
1329    NI_set_attribute (nel, "WindHeight", stmp);
1330    if (csv->X && csv->X->TOPLEVEL) {
1331       SUMA_ALL_DO *ado=NULL;
1332       SUMA_X_SurfCont *SurfCont=NULL;
1333       ScrW = WidthOfScreen (XtScreen(csv->X->TOPLEVEL));
1334       ScrH = HeightOfScreen (XtScreen(csv->X->TOPLEVEL));
1335       XtVaGetValues (csv->X->TOPLEVEL, /* Get the positions of New */
1336          XmNx, &X,
1337          XmNy, &Y,
1338          NULL);
1339       if ((int)X >= 0 && (int)X < ScrW ) {
1340          NI_SET_INT (nel, "WindX", (int)X);
1341       } else {
1342          SUMA_S_Warnv("X position is %d, outside of [0,%d[\n",
1343                       X, ScrW);
1344       }
1345       if ((int)Y >= 0 && (int)Y < ScrH ) {
1346          NI_SET_INT (nel, "WindY", (int)Y);
1347       } else {
1348          SUMA_S_Warnv("Y position is %d, outside of [0,%d[\n",
1349                       Y, ScrH);
1350       }
1351       if ((ado = SUMA_SV_any_ADO_WithSurfContWidget(csv,NULL,NOT_SET_type))) {
1352          SurfCont = SUMA_ADO_Cont(ado);
1353          XtVaGetValues (SurfCont->TLS, /* Get the positions of New */
1354             XmNx, &X,
1355             XmNy, &Y,
1356             NULL);
1357          if ((int)X >= 0 && (int)X < ScrW ) {
1358             NI_SET_INT (nel, "ContX", (int)X);
1359          } else {
1360             SUMA_S_Warnv("X position is %d, outside of [0,%d[\n",
1361                          X, ScrW);
1362          }
1363          if ((int)Y >= 0 && (int)Y < ScrH ) {
1364             NI_SET_INT (nel, "ContY", (int)Y);
1365          } else {
1366             SUMA_S_Warnv("Y position is %d, outside of [0,%d[\n",
1367                          Y, ScrH);
1368          }
1369       }
1370    }
1371    sprintf(stmp, "%d", (int)csv->BF_Cull);
1372    NI_set_attribute (nel, "BF_Cull", stmp);
1373    sprintf(stmp, "%f", csv->Back_Modfact);
1374    NI_set_attribute (nel, "Back_Modfact", stmp);
1375    sprintf(stmp, "%d", (int)csv->PolyMode);
1376    NI_set_attribute (nel, "PolyMode", stmp);
1377    sprintf(stmp, "%d", (int)csv->DO_DrawMask);
1378    NI_set_attribute (nel, "DO_DrawMask", stmp);
1379    sprintf(stmp, "%d", csv->ShowEyeAxis);
1380    NI_set_attribute (nel, "ShowEyeAxis", stmp);
1381    sprintf(stmp, "%d", csv->ShowMeshAxis);
1382    NI_set_attribute (nel, "ShowMeshAxis", stmp);
1383    sprintf(stmp, "%d", csv->ShowWorldAxis);
1384    NI_set_attribute (nel, "ShowWorldAxis", stmp);
1385    sprintf(stmp, "%d", csv->ShowCrossHair);
1386    NI_set_attribute (nel, "ShowCrossHair", stmp);
1387    sprintf(stmp, "%d", (int)csv->ShowForeground);
1388    NI_set_attribute (nel, "ShowForeground", stmp);
1389    sprintf(stmp, "%d", (int)csv->ShowBackground);
1390    NI_set_attribute (nel, "ShowBackground", stmp);
1391 
1392    /* write element */
1393    if (!fname) {
1394       nstdout = NI_stream_open( "file:test.niml.vvs","w");
1395    } else {
1396       fnamestmp = SUMA_append_string("file:", fname);
1397       fnamestmp2 = SUMA_Extension(fnamestmp, ".niml.vvs", NOPE);
1398       nstdout = NI_stream_open( fnamestmp2,"w");
1399       SUMA_free(fnamestmp); fnamestmp = NULL;
1400       SUMA_free(fnamestmp2); fnamestmp2 = NULL;
1401    }
1402    if( nstdout == NULL ){
1403       fprintf(stderr,"%s: Can't open file\n", FuncName);
1404       SUMA_RETURNe;
1405    }
1406    NI_write_element( nstdout , nel , NI_TEXT_MODE | NI_HEADERSHARP_FLAG) ;
1407    NI_stream_close(nstdout);
1408    NI_free_element(nel) ; nel = NULL;
1409 
1410    SUMA_RETURNe;
1411 }
1412 
SUMA_ApplyVisualState(NI_element * nel,SUMA_SurfaceViewer * csv)1413 int SUMA_ApplyVisualState(NI_element *nel, SUMA_SurfaceViewer *csv)
1414 {
1415    static char FuncName[]={"SUMA_ApplyVisualState"};
1416    int feyl;
1417    char *fnamestmp=NULL, *fnamestmp2=NULL;
1418    float quat[4], Aspect[1], FOV[1], tran[2],
1419          WindWidth[1], WindHeight[1], clear_color[4],
1420          BF_Cull[1], Back_Modfact[1], PolyMode[1], ShowEyeAxis[1],
1421          ShowWorldAxis[1], DO_DrawMask[1],
1422          ShowMeshAxis[1], ShowCrossHair[1], ShowForeground[1],
1423          ShowBackground[1], WindX[1], WindY[1], ContX[1], ContY[1];
1424    Dimension ScrW, ScrH;
1425    char *atmp;
1426    SUMA_Boolean LocalHead = NOPE;
1427 
1428    SUMA_ENTRY;
1429 
1430    if (!nel || !csv) {
1431       SUMA_S_Err("NULL input");
1432       SUMA_RETURN(0);
1433    }
1434 
1435    /* don't crash if you fail here and there, try your best ...*/
1436    SUMA_S2FV_ATTR(nel, "currentQuat", quat, 4, feyl);
1437       if (!feyl) {
1438          SUMA_COPY_VEC( quat, csv->GVS[csv->StdView].currentQuat, 4,
1439                         float, float);
1440       }
1441    SUMA_S2FV_ATTR(nel, "translateVec", tran, 2, feyl);
1442       if (!feyl) {
1443          SUMA_COPY_VEC( tran, csv->GVS[csv->StdView].translateVec, 2,
1444                         float, float);
1445       }
1446    SUMA_S2FV_ATTR(nel, "FOV", FOV, 1, feyl);
1447       if (!feyl) {
1448          csv->FOV[csv->iState] = FOV[0];
1449       }
1450    SUMA_S2FV_ATTR(nel, "Aspect", Aspect, 1, feyl);
1451       if (!feyl) {
1452          csv->Aspect = Aspect[0]; /* gets set when SUMA_resize is called */
1453       }
1454    SUMA_S2FV_ATTR(nel, "WindWidth", WindWidth, 1, feyl);
1455       if (!feyl) {
1456          csv->wWindWidth = (int)WindWidth[0];
1457             /* gets set when SUMA_resize is called */
1458       }
1459    SUMA_S2FV_ATTR(nel, "WindHeight", WindHeight, 1, feyl);
1460       if (!feyl) {
1461          csv->wWindHeight = (int)WindHeight[0];
1462             /* That gets recalculated when SUMA_resize is called */
1463       }
1464    if (csv->X && csv->X->TOPLEVEL) {
1465       SUMA_ALL_DO *ado=NULL;
1466       SUMA_X_SurfCont *SurfCont=NULL;
1467       Position Xi, Yi;
1468       ScrW = WidthOfScreen (XtScreen(csv->X->TOPLEVEL));
1469       ScrH = HeightOfScreen (XtScreen(csv->X->TOPLEVEL));
1470       SUMA_S2FV_ATTR(nel, "WindX", WindX, 1, feyl);
1471       if (!feyl) {
1472          if ((int)WindX[0] < 0 && (int)WindX[0] >= ScrW ) {
1473             SUMA_S_Warnv("X position is %d, outside of [0,%d[\n",
1474                    (int)WindX[0], ScrW);
1475             WindX[0] = -1.0;
1476          }
1477       } else WindX[0] = -1.0;
1478       SUMA_S2FV_ATTR(nel, "WindY", WindY, 1, feyl);
1479       if (!feyl) {
1480          if ((int)WindY[0] < 0 && (int)WindY[0] >= ScrW ) {
1481             SUMA_S_Warnv("Y position is %d, outside of [0,%d[\n",
1482                    (int)WindY[0], ScrW);
1483             WindY[0] = -1.0;
1484          }
1485       } else WindY[0] = -1.0;
1486 
1487       if (WindX[0] >= 0 && WindY[0] >= 0) {
1488          SUMA_LH("Setting viewer window at positions %d %d",
1489                  (int)WindX[0], (int)WindY[0]);
1490          XtVaSetValues (csv->X->TOPLEVEL, /* Set the positions of New */
1491             XmNx, (Position)((int)WindX[0]),
1492             XmNy, (Position)((int)WindY[0]),
1493             NULL);
1494        }
1495       if ((ado = SUMA_SV_Focus_any_ADO(csv, NULL))) {
1496          /* possible to set things for controller */
1497          SUMA_S2FV_ATTR(nel, "ContX", ContX, 1, feyl);
1498          if (!feyl) {
1499             if ((int)ContX[0] < 0 && (int)ContX[0] >= ScrW ) {
1500                SUMA_S_Warnv("X position is %d, outside of [0,%d[\n",
1501                       (int)ContX[0], ScrW);
1502                ContX[0] = -1.0;
1503             }
1504          } else ContX[0] = -1.0;
1505          SUMA_S2FV_ATTR(nel, "ContY", ContY, 1, feyl);
1506          if (!feyl) {
1507             if ((int)ContY[0] < 0 && (int)ContY[0] >= ScrW ) {
1508                SUMA_S_Warnv("Y position is %d, outside of [0,%d[\n",
1509                       (int)ContY[0], ScrW);
1510                ContY[0] = -1.0;
1511             }
1512          } else ContY[0] = -1.0;
1513 
1514          if (ContX[0] >= 0 && ContY[0] >= 0 &&
1515              (SurfCont = SUMA_ADO_Cont(ado))&&
1516              SUMA_viewSurfaceCont(NULL, ado, csv)) {
1517             SUMA_LH("Setting controller window at positions %d %d",
1518                  (int)ContX[0], (int)ContY[0]);
1519             XtVaSetValues (SurfCont->TLS, /* Set the positions of New */
1520                XmNx, (Position)((int)ContX[0]),
1521                XmNy, (Position)((int)ContY[0]),
1522                NULL);
1523           }
1524       }
1525    }
1526 
1527 
1528 
1529    SUMA_S2FV_ATTR(nel, "clear_color", clear_color, 4, feyl);
1530       if (!feyl) {
1531          SUMA_COPY_VEC(clear_color, csv->clear_color, 4, float, float);
1532       }
1533    SUMA_S2FV_ATTR(nel, "BF_Cull", BF_Cull, 1, feyl);
1534       if (!feyl) {
1535          csv->BF_Cull = (SUMA_Boolean)BF_Cull[0];
1536       }
1537    SUMA_S2FV_ATTR(nel, "Back_Modfact", Back_Modfact, 1, feyl);
1538       if (!feyl) {
1539          csv->Back_Modfact = Back_Modfact[0];
1540       }
1541    SUMA_S2FV_ATTR(nel, "PolyMode", PolyMode, 1, feyl);
1542       if (!feyl) {
1543          csv->PolyMode = (SUMA_RENDER_MODES)PolyMode[0];
1544       }
1545    SUMA_S2FV_ATTR(nel, "DO_DrawMask", DO_DrawMask, 1, feyl);
1546       if (!feyl) {
1547          csv->DO_DrawMask = (SUMA_DO_DRAW_MASK)DO_DrawMask[0];
1548       }
1549    SUMA_S2FV_ATTR(nel, "ShowEyeAxis", ShowEyeAxis, 1, feyl);
1550       if (!feyl) {
1551          csv->ShowEyeAxis = (int)ShowEyeAxis[0];
1552       }
1553    SUMA_S2FV_ATTR(nel, "ShowMeshAxis", ShowMeshAxis, 1, feyl);
1554       if (!feyl) {
1555          csv->ShowMeshAxis = (int)ShowMeshAxis[0];
1556       }
1557    SUMA_S2FV_ATTR(nel, "ShowWorldAxis", ShowWorldAxis, 1, feyl);
1558       if (!feyl) {
1559          csv->ShowWorldAxis = (int)ShowWorldAxis[0];
1560       }
1561    SUMA_S2FV_ATTR(nel, "ShowCrossHair", ShowCrossHair, 1, feyl);
1562       if (!feyl) {
1563          csv->ShowCrossHair = (int)ShowCrossHair[0];
1564       }
1565    SUMA_S2FV_ATTR(nel, "ShowForeground", ShowForeground, 1, feyl);
1566       if (!feyl) {
1567          csv->ShowForeground = (SUMA_Boolean)ShowForeground[0];
1568       }
1569    SUMA_S2FV_ATTR(nel, "ShowBackground", ShowBackground, 1, feyl);
1570       if (!feyl) {
1571          csv->ShowForeground = (SUMA_Boolean)ShowForeground[0];
1572       }
1573 
1574    /* do a resize (does not matter if dimensions did not change, call is simple.
1575    This call will also generate a SUMA_resize call, which will provide adjusted
1576    values to reflect size of the GLXAREA */
1577    SUMA_S_Note("Resizing main window to %d x %d",
1578             csv->wWindWidth, csv->wWindHeight);
1579    SUMA_WidgetResize (csv->X->TOPLEVEL , csv->wWindWidth, csv->wWindHeight);
1580 
1581    SUMA_RETURN(1);
1582 }
1583 /*!
1584    \brief function to load a viewer's visual state
1585 */
SUMA_LoadVisualState(char * fname,void * csvp)1586 void SUMA_LoadVisualState(char *fname, void *csvp)
1587 {
1588    static char FuncName[]={"SUMA_LoadVisualState"};
1589    NI_element *nel = NULL;
1590    int feyl;
1591    char *fnamestmp=NULL, *fnamestmp2=NULL;
1592    float quat[4], Aspect[1], FOV[1], tran[2],
1593          WindWidth[1], WindHeight[1], clear_color[4],
1594          BF_Cull[1], Back_Modfact[1], PolyMode[1],
1595          ShowEyeAxis[1], ShowWorldAxis[1], DO_DrawMask[1],
1596          ShowMeshAxis[1], ShowCrossHair[1], ShowForeground[1],
1597          ShowBackground[1];   char *atmp;
1598    NI_stream nstdin;
1599    SUMA_SurfaceViewer *csv;
1600    SUMA_Boolean LocalHead = NOPE;
1601 
1602    SUMA_ENTRY;
1603 
1604    csv = (SUMA_SurfaceViewer *)csvp;
1605    if (!csv) { SUMA_RETURNe; }
1606 
1607    if (!fname) {
1608       nstdin = NI_stream_open( "file:test.niml.vvs","r");
1609    } else {
1610       fnamestmp = SUMA_append_string("file:", fname);
1611       fnamestmp2 = SUMA_Extension(fnamestmp, ".niml.vvs", NOPE);
1612       nstdin = NI_stream_open( fnamestmp2,"r");
1613       SUMA_free(fnamestmp); fnamestmp = NULL;
1614       SUMA_free(fnamestmp2); fnamestmp2 = NULL;
1615    }
1616    if( nstdin == NULL ){
1617       fprintf(stderr,"%s: Can't open file\n", FuncName);
1618       SUMA_RETURNe;
1619    }
1620    nel = NI_read_element (nstdin, 1);
1621    if (!nel) {
1622       SUMA_SL_Err("Failed to read nel.\n");
1623       SUMA_RETURNe;
1624    }
1625 
1626    if (!SUMA_ApplyVisualState(nel, csv)) {
1627       SUMA_S_Err("Failed to apply state");
1628       SUMA_RETURNe;
1629    }
1630 
1631    NI_free_element(nel); nel = NULL;
1632    NI_stream_close(nstdin);
1633 
1634    SUMA_RETURNe;
1635 }
1636 
SUMA_index_to_clip_plane(int iplane)1637 GLenum SUMA_index_to_clip_plane(int iplane)
1638 {
1639    static char FuncName[]={"SUMA_index_to_clip_plane"};
1640 
1641    switch(iplane) {
1642       case 0:
1643          return(GL_CLIP_PLANE0);
1644          break;
1645       case 1:
1646          return(GL_CLIP_PLANE1);
1647          break;
1648       case 2:
1649          return(GL_CLIP_PLANE2);
1650          break;
1651       case 3:
1652          return(GL_CLIP_PLANE3);
1653          break;
1654       case 4:
1655          return(GL_CLIP_PLANE4);
1656          break;
1657       case 5:
1658          return(GL_CLIP_PLANE5);
1659          break;
1660       default:
1661          SUMA_SLP_Err("You are not to have more than 6 planes!!!");
1662          return(GL_CLIP_PLANE0);
1663          break;
1664    }
1665 }
1666 
SUMA_PixelsToDisk(SUMA_SurfaceViewer * csv,int w,int h,GLvoid * vpixels,int colordepth,int verb,char * ufname,int autoname,int overwrite)1667 int SUMA_PixelsToDisk(SUMA_SurfaceViewer *csv, int w, int h, GLvoid *vpixels,
1668                       int colordepth, int verb, char *ufname, int autoname,
1669                       int overwrite)
1670 {
1671    static char FuncName[]={"SUMA_PixelsToDisk"};
1672    MRI_IMAGE *tim=NULL;
1673    static char fname[512];
1674    int undoover=0;
1675    GLubyte *pixels=NULL;
1676    GLfloat *fpixels=NULL;
1677    SUMA_PARSED_NAME *pn=NULL;
1678 
1679    SUMA_ENTRY;
1680 
1681    if (!vpixels || w < 1 || SUMA_ABS(h) < 1) SUMA_RETURN(0);
1682 
1683    switch (colordepth) {
1684       case SUMA_b:
1685       case 1: {
1686          unsigned char *pp3=NULL;
1687          int ii, ii3;
1688          pixels = (GLubyte *)vpixels;
1689          if (!(pp3=(unsigned char *)SUMA_malloc(3*w*h*sizeof(unsigned char)))) {
1690             SUMA_S_Crit("malloc failed"); SUMA_RETURN(0);
1691          }
1692          ii3 = 0;
1693          for (ii=0; ii<w*h; ++ii) {
1694             pp3[ii3++] = pixels[ii];
1695             pp3[ii3++] = pixels[ii];
1696             pp3[ii3++] = pixels[ii];
1697          }
1698          tim = ISQ_snap_to_mri_image (w, h, (unsigned char *)pp3 );
1699          SUMA_free(pp3);
1700          break; }
1701       case SUMA_F:
1702       case 5: {
1703          unsigned char *pp3=NULL, pt;
1704          float fmax = 1.0;
1705          int ii, ii3;
1706          fpixels = (GLfloat *)vpixels;
1707          if (!(pp3=(unsigned char *)SUMA_malloc(3*w*h*sizeof(unsigned char)))) {
1708             SUMA_S_Crit("malloc failed"); SUMA_RETURN(0);
1709          }
1710          fmax = fpixels[0];
1711          for (ii=1; ii<w*h; ++ii) {
1712             if (fmax < fpixels[ii]) fmax = fpixels[ii];
1713          }
1714          if (fmax == 0.0f) fmax = 1.0;
1715          if (verb) {
1716             SUMA_S_Note("Buffer float max of %f", fmax);
1717          }
1718          ii3 = 0;
1719          for (ii=0; ii<w*h; ++ii) {
1720             pt = (unsigned char)((fpixels[ii]/fmax)*255);
1721             pp3[ii3++] = pt;
1722             pp3[ii3++] = pt;
1723             pp3[ii3++] = pt;
1724          }
1725          tim = ISQ_snap_to_mri_image (w, h, (unsigned char *)pp3 );
1726          SUMA_free(pp3);
1727          break; }
1728       case SUMA_bbb:
1729       case 3:
1730          pixels = (GLubyte *)vpixels;
1731          tim = ISQ_snap_to_mri_image (w, h, (unsigned char *)pixels );
1732          break;
1733       case SUMA_bbbb:
1734       case 4:
1735          pixels = (GLubyte *)vpixels;
1736          tim = ISQ_snap4_to_mri_image (w, h, (unsigned char *)pixels );
1737          break;
1738       default:
1739          SUMA_S_Errv("Bad color depth or GL tuple of %d\n", colordepth);
1740          SUMA_RETURN(0);
1741          break;
1742    }
1743 
1744    if (!tim) {
1745       SUMA_S_Err("Failed to get image");
1746       SUMA_RETURN(0);
1747    }
1748 
1749    if (!ufname) {
1750       SUMA_VALIDATE_RECORD_PATH(SUMAg_CF->autorecord);
1751       pn = SUMAg_CF->autorecord;
1752       autoname = 1;
1753    } else {
1754       if (!(pn = SUMA_ParseFname(ufname, NULL))) {
1755          SUMA_S_Errv("Failed to parse %s\n", ufname);
1756          SUMA_RETURN(0);
1757       }
1758    }
1759    if (autoname) {
1760       if (!strcasecmp(pn->Ext,".jpg") ||
1761           !strcasecmp(pn->Ext,".ppm") ||
1762           !strcasecmp(pn->Ext,".1D") ){
1763             snprintf(fname,510*sizeof(char),
1764                      "%s/%s.%c.%s%s",
1765                      pn->Path,
1766                      pn->FileName_NoExt,
1767                      SUMA_SV_CHAR(csv),
1768                      SUMA_time_stamp(),
1769                      pn->Ext);
1770       } else {
1771             snprintf(fname,510*sizeof(char),
1772                      "%s/%s.%c.%s%s",
1773                      pn->Path,
1774                      pn->FileName,
1775                      SUMA_SV_CHAR(csv),
1776                      SUMA_time_stamp(),
1777                      ".jpg");
1778       }
1779    } else {
1780       if (!strcasecmp(pn->Ext,".jpg") ||
1781           !strcasecmp(pn->Ext,".ppm") ||
1782           !strcasecmp(pn->Ext,".1D") ){
1783             snprintf(fname,510*sizeof(char),
1784                      "%s/%s%s",
1785                      pn->Path,
1786                      pn->FileName_NoExt,
1787                      pn->Ext);
1788       } else {
1789             snprintf(fname,510*sizeof(char),
1790                      "%s/%s%s",
1791                      pn->Path,
1792                      pn->FileName,
1793                      ".jpg");
1794       }
1795    }
1796 
1797    if (overwrite && !THD_ok_overwrite()) {
1798       THD_force_ok_overwrite(1);
1799       undoover=1;
1800    }
1801    if (strcasecmp(pn->Ext,".1D")) mri_write(fname,tim);
1802    else mri_write_1D(fname,tim);
1803    mri_free(tim); tim=NULL;
1804    if (verb) SUMA_S_Notev("Wrote image to %s\n",fname);
1805    if (ufname) pn = SUMA_Free_Parsed_Name(pn);
1806    if (undoover) THD_force_ok_overwrite(0);
1807    SUMA_RETURN(1);
1808 }
1809 
SUMA_SnapToDisk(SUMA_SurfaceViewer * csv,int verb,int getback)1810 int SUMA_SnapToDisk(SUMA_SurfaceViewer *csv, int verb, int getback)
1811 {
1812    static char FuncName[]={"SUMA_SnapToDisk"};
1813    GLvoid *pixels=NULL;
1814    int holdrdc = 0;
1815 
1816    SUMA_ENTRY;
1817 
1818    if (!csv) SUMA_RETURN(0);
1819 
1820    holdrdc = csv->rdc;
1821    #if 0  /* problem should be fixed by SUMA_grabRenderedPixels
1822                               Throw section out if no new problems arise.
1823                               Search for KILL_DOUBLE_RENDERING to locate
1824                               other chunks for removal
1825                                        ZSS Feb 2012 */
1826       glFinish();
1827       glXWaitX();
1828       #ifdef DARWIN
1829          csv->rdc = SUMA_RDC_X_EXPOSE; /* any thing that avoids a record
1830                                          operation ... */
1831          SUMA_handleRedisplay((XtPointer)csv->X->GLXAREA);
1832          csv->rdc=holdrdc;
1833       #endif
1834    #endif
1835    glXWaitX();
1836    pixels = SUMA_grabRenderedPixels(csv, 3, csv->X->aWIDTH, csv->X->aHEIGHT,
1837                                     getback);
1838    if (pixels) {
1839       if (!SUMA_PixelsToDisk(csv, csv->X->aWIDTH, -csv->X->aHEIGHT,
1840                              pixels, 3, verb, NULL, 1, 0)) {
1841          SUMA_S_Err("Failed to write pix to disk");
1842          SUMA_free(pixels);
1843          SUMA_RETURN(0);
1844       }
1845       SUMA_free(pixels);
1846    }
1847 
1848    SUMA_RETURN(1);
1849 }
1850 
1851 /* Some of these constants may not be defined in older openGLs */
1852 #define NO_GL_CHECK_FRAME_BUFFER 0 /* expect glCheckFramebufferStatus() */
1853 
1854 #ifndef  GL_FRAMEBUFFER
1855    #define GL_FRAMEBUFFER 0
1856    #define NO_GL_CHECK_FRAME_BUFFER 1/* No glCheckFramebufferStatus() */
1857 #endif
1858 
1859 #ifndef  GL_FRAMEBUFFER_COMPLETE
1860    #define GL_FRAMEBUFFER_COMPLETE -1
1861    #define NO_GL_CHECK_FRAME_BUFFER 1
1862 #endif
1863 
1864 #ifndef  GL_FRAMEBUFFER_UNDEFINED
1865    #define GL_FRAMEBUFFER_UNDEFINED -2
1866    #define NO_GL_CHECK_FRAME_BUFFER 1
1867 #endif
1868 
1869 #ifndef  GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE
1870    #define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE -3
1871 #endif
1872 
1873 #ifndef  GL_FRAMEBUFFER_UNSUPPORTED
1874    #define GL_FRAMEBUFFER_UNSUPPORTED -4
1875 #endif
1876 
1877 #ifndef GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT
1878    #define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT -5
1879 #endif
1880 
1881 #ifndef GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS
1882    #define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS -6
1883 #endif
1884 
1885 #if NO_GL_CHECK_FRAME_BUFFER
1886    #define glCheckFramebufferStatus DUMMY_glCheckFramebufferStatus
1887 #endif
1888 #ifdef SUMA_GL_NO_CHECK_FRAME_BUFFER
1889    #define glCheckFramebufferStatus DUMMY_glCheckFramebufferStatus
1890 #endif
1891 
1892 /* For older openGL libs */
DUMMY_glCheckFramebufferStatus(GLenum dumdum)1893 GLenum DUMMY_glCheckFramebufferStatus(GLenum dumdum) {
1894    return(GL_FRAMEBUFFER_COMPLETE);
1895 }
1896 
SUMA_SV_SortedRegistDO(SUMA_SurfaceViewer * csv,int * N_regs,SUMA_DO * dov)1897 SUMA_DO_LOCATOR *SUMA_SV_SortedRegistDO(SUMA_SurfaceViewer *csv, int *N_regs,
1898                                         SUMA_DO *dov)
1899 {
1900    static char FuncName[]={"SUMA_SV_SortedRegistDO"};
1901    SUMA_DO_LOCATOR *sRegistDO=NULL;
1902    int i, j, k, ct, ot, ctseq[2],
1903        ncheck=0, N_ctseq=-1, iotseq=-1;
1904 
1905    SUMA_ENTRY;
1906 
1907    *N_regs = -1;
1908    if (!csv || csv->N_DO <= 0 || !csv->RegistDO || !N_regs || !dov) {
1909       SUMA_S_Err("NULL or no DOs in input");
1910       SUMA_RETURN(sRegistDO);
1911    }
1912 
1913    /* count number of total objects.
1914       For now it will be the same, as N_DO, but this
1915       might allow me to render something twice, perhaps,
1916       in the future, if I allow special directives to go
1917       back with the DO_LOCATOR...
1918       For now, same as csv->N_DO*/
1919 
1920    *N_regs = csv->N_DO;
1921    sRegistDO = (SUMA_DO_LOCATOR *)
1922                   SUMA_calloc(*N_regs, sizeof(SUMA_DO_LOCATOR));
1923 
1924 
1925    /* Sequence of coordinate types */
1926    ctseq[0] = SUMA_SCREEN;
1927    ctseq[1] = SUMA_WORLD;
1928    N_ctseq = 2;
1929 
1930    ncheck=0;
1931    for (j=0; j<N_ctseq; ++j) {
1932       i = 0;
1933       while (i < csv->N_DO) {
1934          ct = dov[csv->RegistDO[i].dov_ind].CoordType;
1935          if (ct == ctseq[j]) {
1936             ot = dov[csv->RegistDO[i].dov_ind].ObjectType;
1937             iotseq =
1938                SUMA_FindFirst_inIntVect(csv->otseq, csv->otseq+csv->N_otseq, ot);
1939             if (iotseq < 0) { /* not found, take it */
1940                sRegistDO[ncheck].dov_ind = csv->RegistDO[i].dov_ind;
1941                strcpy(sRegistDO[ncheck].idcode_str,
1942                       csv->RegistDO[i].idcode_str);
1943                ++ncheck;
1944             }
1945          }
1946          ++i;
1947       }
1948       /* Now get those in csv->otseq, in order */
1949       for (k=0; k<csv->N_otseq; ++k) {
1950          i = 0;
1951          while (i < csv->N_DO) {
1952             ct = dov[csv->RegistDO[i].dov_ind].CoordType;
1953             if (ct == ctseq[j]) {
1954                ot = dov[csv->RegistDO[i].dov_ind].ObjectType;
1955                if (ot == csv->otseq[k]) { /* its time has come */
1956                   sRegistDO[ncheck].dov_ind = csv->RegistDO[i].dov_ind;
1957                   strcpy(sRegistDO[ncheck].idcode_str,
1958                          csv->RegistDO[i].idcode_str);
1959                   ++ncheck;
1960                }
1961             }
1962             ++i;
1963          }
1964       }
1965    }
1966    if (ncheck != *N_regs) {
1967       SUMA_S_Err("Mismatch, %d and %d. Adopting smaller number",
1968                   ncheck, *N_regs);
1969       if (ncheck < *N_regs) *N_regs=ncheck;
1970    }
1971    SUMA_RETURN(sRegistDO);
1972 }
1973 
SUMA_display(SUMA_SurfaceViewer * csv,SUMA_DO * dov)1974 void SUMA_display(SUMA_SurfaceViewer *csv, SUMA_DO *dov)
1975 {
1976    static char FuncName[]={"SUMA_display"};
1977    static SUMA_CONV_MODES l_C_mode=SUMA_CONV_NONE;
1978    SUMA_Boolean LocalHead = NOPE; /* local headline debugging messages */
1979 
1980    SUMA_ENTRY;
1981 
1982    if (LocalHead) {
1983       SUMA_DUMP_TRACE("Trace At display call");
1984    }
1985 
1986    if (!csv->Open) {
1987       SUMA_S_Errv("Very weird to be here with Open flag = %d\n", csv->Open);
1988       SUMA_RETURNe;
1989    }
1990 
1991    if (SUMAg_CF->Dev) {
1992       #if MULTICONV
1993          /* Obsolete! No longer works on newer machines. Need to use GLSL
1994             to do perform such trickery. This is here for historical reasons */
1995       csv->C_mode = SUMA_CONV_BOX_5X5;
1996       if (l_C_mode != csv->C_mode) {
1997          switch(csv->C_mode) {
1998           case SUMA_CONV_NONE:
1999             SUMA_C_resize(csv->C_filter, 1,1);
2000             SUMA_C_identity(csv->C_filter);
2001             break;
2002           case SUMA_CONV_BOX_3X3:
2003             SUMA_C_resize(csv->C_filter, 3, 3);
2004             SUMA_C_box(csv->C_filter);
2005             break;
2006           case SUMA_CONV_BOX_5X5:
2007             SUMA_C_resize(csv->C_filter, 5, 5);
2008             SUMA_C_box(csv->C_filter);
2009             break;
2010           case SUMA_CONV_SOBEL_X:
2011             SUMA_C_sobel(csv->C_filter);
2012             break;
2013           case SUMA_CONV_LAPLACE:
2014             SUMA_C_laplace(csv->C_filter);
2015             break;
2016          }
2017          l_C_mode = csv->C_mode;
2018       }
2019       switch (csv->C_mode) {
2020          case SUMA_CONV_NONE:
2021             SUMA_display_one(csv, dov);
2022             break;
2023          default:
2024             glClearAccum(csv->C_filter->bias,
2025                     csv->C_filter->bias,
2026                     csv->C_filter->bias,
2027                     1.0);
2028 
2029             glClear(GL_ACCUM_BUFFER_BIT);
2030 
2031             SUMA_C_convolve(csv, dov, csv->C_filter);
2032 
2033             glAccum(GL_RETURN, csv->C_filter->scale);
2034             break;
2035       }
2036       #elif MULTISAMPLE
2037       /* Does not do much, left here to prove it does
2038       not do much at all. */
2039       glEnable(GL_MULTISAMPLE);
2040       glHint(GL_MULTISAMPLE_FILTER_HINT_NV, GL_NICEST);
2041       if (0) {
2042          GLint iMultiSample=0;
2043          GLint iNumSamples = 0;
2044          glGetIntegerv(GL_SAMPLE_BUFFERS, &iMultiSample);
2045          glGetIntegerv(GL_SAMPLES, &iNumSamples);
2046          SUMA_LH("HERE %d %d", iMultiSample, iNumSamples);
2047       }
2048       SUMA_display_one(csv, dov);
2049       #else
2050       SUMA_display_one(csv, dov);
2051       #endif
2052    } else {
2053       SUMA_display_one(csv, dov);
2054    }
2055    /* FLUSH_AND_OUT: */
2056    SUMA_LHv("Flushing or swapping on %p\n", csv->X->GLXAREA);
2057    /* SUMA_HOLD_IT; Not used anymore */
2058 
2059    SUMA_GLX_BUF_SWAP(csv);
2060    SUMA_LHv("Done Flushing or swapping on %p\n", csv->X->GLXAREA);
2061 
2062   /* Avoid indirect rendering latency from queuing. */
2063   if (!glXIsDirect(csv->X->DPY, csv->X->GLXCONTEXT))
2064     glFinish();
2065 
2066   /*  if recording, take a snap
2067       Note that the buffer swap has been done, it might have
2068       been better to snap before then.
2069       This way I could have used SUMA_grabPixels
2070       instead of SUMA_grabRenderedPixels.
2071       Consider this in the future. ZSS Feb 2012*/
2072   if (csv->Record == 1 && !csv->DO_PickMode) {
2073       if (csv->rdc < SUMA_RDC_X_START || csv->rdc > SUMA_RDC_X_END) {
2074          if (0) {/* problem should be fixed by SUMA_grabRenderedPixels
2075                               Throw section out if no new problems arise.
2076                               Search for KILL_DOUBLE_RENDERING to locate
2077                               other chunks for removal
2078                                        ZSS Feb 2012 */
2079            /*
2080             Combination below helps partial coverage
2081             problem under linux when recording.
2082             But it does not fix the coverage problem
2083             entirely.
2084 
2085             SUMA_S_Note("Raising the dead");
2086             XtPopup (csv->X->TOPLEVEL, XtGrabExclusive);
2087             XRaiseWindow(XtDisplay(csv->X->TOPLEVEL),
2088                         XtWindow(csv->X->TOPLEVEL));
2089           */
2090             glFinish();
2091             glXWaitX();
2092          #ifdef DARWIN
2093 
2094             { GLvoid *pixels;
2095               int holdrdc = csv->rdc;
2096               /* see justification for this SUMA_handleRedisplay in function
2097                   SUMA_R_Key(). You need to change rdc to avoid getting into
2098                   recorder when SUMA_handleRedisplay ends up calling this
2099                   function again. */
2100               csv->rdc = SUMA_RDC_X_EXPOSE; /* any thing that avoids a record
2101                                                operation ... */
2102               SUMA_handleRedisplay((XtPointer)csv->X->GLXAREA);
2103               csv->rdc=holdrdc;
2104               pixels = SUMA_grabPixels(3, csv->X->aWIDTH, csv->X->aHEIGHT);
2105               if (pixels) {
2106                 ISQ_snapsave( csv->X->aWIDTH, -csv->X->aHEIGHT,
2107                               (unsigned char *)pixels, csv->X->GLXAREA );
2108                 SUMA_free(pixels);
2109               }
2110             }
2111          #else
2112             ISQ_snapshot ( csv->X->GLXAREA );
2113          #endif
2114          } else { /* better approach after fixing buffer swaping bug Feb 2012*/
2115             GLvoid *pixels=NULL;
2116             pixels = SUMA_grabRenderedPixels(csv, 3,
2117                                           csv->X->aWIDTH, csv->X->aHEIGHT, 0);
2118             if (pixels) {
2119               ISQ_snapsave( csv->X->aWIDTH, -csv->X->aHEIGHT,
2120                            (unsigned char *)pixels, csv->X->GLXAREA );
2121               SUMA_free(pixels);
2122             }
2123          }
2124       }
2125    } else if (csv->Record == 2 && !csv->DO_PickMode) {
2126       if (csv->rdc < SUMA_RDC_X_START || csv->rdc > SUMA_RDC_X_END) {
2127          SUMA_SnapToDisk(csv,0,0);
2128       }
2129    }
2130    /* reset rdc, if it is the last thing you'll ever do */
2131    csv->rdc = SUMA_RDC_NOT_SET;
2132 
2133    if (SUMAg_CF->Dev) {
2134       #ifdef MULTISAMP
2135       glDisable(GL_MULTISAMPLE);
2136       #endif
2137    }
2138    SUMA_RETURNe;
2139 }
2140 
SUMA_display_one(SUMA_SurfaceViewer * csv,SUMA_DO * dov)2141 void SUMA_display_one(SUMA_SurfaceViewer *csv, SUMA_DO *dov)
2142 {
2143    static char FuncName[]={"SUMA_display_one"};
2144    SUMA_DO_LOCATOR *sRegistDO = NULL;
2145    int i, N_sReg, iflush=1000;
2146    static int xList[1], yList[1];
2147    SUMA_SurfaceObject *SO=NULL;
2148    SUMA_VolumeObject *VO=NULL;
2149    GLenum fbs;
2150    GLfloat rotationMatrix[4][4];
2151    SUMA_Boolean LocalHead = NOPE; /* local headline debugging messages */
2152    int  N_dov = 1;
2153 
2154    SUMA_ENTRY;
2155 
2156    if (LocalHead) {
2157       SUMA_DUMP_TRACE("Trace At display_one call");
2158    }
2159    if (csv->iState < 0 || !csv->FOV) {
2160       /* This can happen when loading multiple surfaces
2161          at the command line such as with -i -i -i ...*/
2162       SUMA_LH("Negative state and/or NULL FOV? (%d,%p)\n",
2163                   csv->iState, csv->FOV);
2164       if (LocalHead) SUMA_DUMP_TRACE("Weird state/FOV");
2165       SUMA_RETURNe;
2166    }
2167 
2168    if (!csv->Open) {
2169       SUMA_S_Errv("Very weird to be here with Open flag = %d\n", csv->Open);
2170       SUMA_RETURNe;
2171    }
2172 
2173    if (csv->DO_PickMode && !csv->pick_colid_list) { /* get ready */
2174       csv->pick_colid_list = (DList *)SUMA_calloc(1,sizeof(DList));
2175       dlist_init(csv->pick_colid_list, SUMA_free_colid_offset_datum);
2176    }
2177 
2178    /* reset stippling masks */
2179    SUMA_StippleMaskResest();
2180 
2181 
2182    /* now you need to set the clear_color since
2183       it can be changed per viewer Thu Dec 12 2002 */
2184    glClearColor ( csv->clear_color[0], csv->clear_color[1],
2185                   csv->clear_color[2], csv->clear_color[3]);
2186 
2187    if (csv->NewGeom) {
2188       /* This function makes calls that are repeated in SUMA_OpenGLStateReset */
2189       SUMA_NewGeometryInViewer(SUMAg_DOv, SUMAg_N_DOv, csv);
2190       csv->NewGeom = NOPE;
2191       csv->ResetGLStateVariables = NOPE; /*  SUMA_NewGeometryInViewer contains
2192                                              SUMA_OpenGLStateReset
2193                                              stuff and lots more ...*/
2194    } else {
2195       /* You cannot just rely on csv->ResetGLStateVariables because
2196          it is hard to set for all conditions.
2197          For example, if you have multiple viewers open and you have surfaces
2198          moving on momentum in all viewers, then you will have to call
2199          SUMA_OpenGLStateReset before each display otherwise the openGL
2200          settings for one of them will affect the others.
2201          At any rate, that function is not costly to run so there's no harm in
2202          running it anytime you have a display call and more than one viewer
2203          open */
2204 
2205       if (SUMAg_N_SVv > 1 || csv->ResetGLStateVariables) {
2206          if (LocalHead)
2207             fprintf( SUMA_STDERR,
2208                      "%s: Calling SUMA_OpenGLStateReset.\n", FuncName);
2209          SUMA_OpenGLStateReset (SUMAg_DOv, SUMAg_N_DOv, csv);
2210          csv->ResetGLStateVariables = NOPE;
2211       }
2212    }
2213 
2214    /* calculate Pcenter_close for the axis positioning */
2215    if (csv->ShowMeshAxis || csv->ShowWorldAxis) {
2216       yList[0] = csv->X->aHEIGHT;
2217       xList[0] = 0;
2218       SUMA_GetSelectionLine ( csv, csv->X->aWIDTH/2, csv->X->aHEIGHT/2,
2219                               csv->Pcenter_close, csv->Pcenter_far, 1,
2220                               xList, yList, csv->Plist_close);
2221    }
2222    /* decide on color mixing needs */
2223    if (!csv->DO_PickMode && !SUMA_MixColors (csv)) {
2224       fprintf( SUMA_STDERR,
2225                "Error %s: Failed in SUMA_MixColors. Aborting.\n", FuncName);
2226       SUMA_RETURNe;
2227    }
2228 
2229    if (LocalHead)
2230       fprintf (SUMA_STDOUT,"%s: Building Rotation matrix ...\n", FuncName);
2231    SUMA_build_rotmatrix(rotationMatrix, csv->GVS[csv->StdView].currentQuat);
2232 
2233    if (LocalHead) {
2234       SUMA_LH("performing glClear ...");
2235       SUMA_CHECK_GL_ERROR("OpenGL Error Pre clear");
2236    }
2237    fbs = glCheckFramebufferStatus(GL_FRAMEBUFFER);
2238    switch (fbs) {
2239       case 0:
2240          SUMA_CHECK_GL_ERROR("OpenGL Error glCheckFramebufferStatus");
2241          SUMA_RETURNe;
2242       case GL_FRAMEBUFFER_COMPLETE:
2243          SUMA_LH("Frame buffer complete (%d)", fbs);
2244          break;
2245       case GL_FRAMEBUFFER_UNDEFINED:
2246          SUMA_S_Err("Frame buffer undefined(%d)", fbs);
2247          SUMA_RETURNe;
2248       case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
2249          SUMA_S_Err("Frame buffer incomplete attachment(%d)", fbs);
2250          SUMA_RETURNe;
2251       case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS:
2252          SUMA_S_Err("Frame buffer incomplete layer targets(%d)", fbs);
2253          SUMA_RETURNe;
2254       case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
2255          SUMA_S_Err("Frame buffer incomplete multisample(%d)", fbs);
2256          SUMA_RETURNe;
2257       case GL_FRAMEBUFFER_UNSUPPORTED:
2258          SUMA_S_Err("Frame buffer unsupported(%d)", fbs);
2259          SUMA_RETURNe;
2260       default:
2261          SUMA_S_Err("Frame buffer %d?", fbs);
2262          SUMA_RETURNe;
2263    }
2264    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /* clear the Color Buffer
2265                                                          and the depth buffer */
2266    if (LocalHead) {
2267       SUMA_CHECK_GL_ERROR("OpenGL Error Post clear");
2268       SUMA_LH("Clearing done ...");
2269    }
2270 
2271    SUMA_SET_GL_PROJECTION(csv, csv->ortho);
2272 
2273    if (SUMAg_CF->N_ClipPlanes) { /* clipping parts in fixed (screen)
2274                                     coordinate space */
2275       for (i=0; i<SUMAg_CF->N_ClipPlanes; ++i) {
2276          if (SUMAg_CF->ClipPlaneType[i] == SUMA_SCREEN_CLIP) {
2277             glClipPlane(SUMA_index_to_clip_plane(i),
2278                         &(SUMAg_CF->ClipPlanes[4*i]));
2279             glEnable(SUMA_index_to_clip_plane(i));
2280          }
2281       }
2282    }
2283 
2284    #if 1
2285    SUMA_LH("Sorting DOs");
2286    if (!(sRegistDO = SUMA_SV_SortedRegistDO(csv, &N_sReg, dov))) {
2287       SUMA_S_Err("Failed to create sorted registered DO.\n"
2288                  "Falling back on default");
2289       sRegistDO = csv->RegistDO;
2290       N_sReg = csv->N_DO;
2291    }
2292    #else
2293       SUMA_S_Warn("No sorting!");
2294       sRegistDO = csv->RegistDO;
2295       N_sReg = csv->N_DO;
2296    #endif
2297 
2298    /* cycle through csv->RegisteredDO and display
2299       those things that have a fixed CoordType*/
2300    if (LocalHead)
2301       fprintf (SUMA_STDOUT,
2302                "%s: Creating objects with fixed coordinates ...\n",
2303                FuncName);
2304    i = 0;
2305    while (i < N_sReg) {
2306       if (dov[sRegistDO[i].dov_ind].CoordType == SUMA_SCREEN) {
2307          switch (dov[sRegistDO[i].dov_ind].ObjectType) {
2308             case N_DO_TYPES:
2309                SUMA_S_Err("This is reserved for the number of types");
2310                break;
2311             case NOT_SET_type:
2312                SUMA_SL_Err("Should not be doing this buidness");
2313                break;
2314             case not_DO_type: /* nothing to see here */
2315                break;
2316             case NBSP_type:
2317             case SP_type:
2318             case PNT_type:
2319                SUMA_SL_Warn("Not ready yet!");
2320                break;
2321             case SO_type:
2322                break;
2323             case ANY_DSET_type:
2324             case MD_DSET_type:
2325             case GDSET_type: /* Should not be in DO list */
2326                SUMA_S_Warn("Should not have such objects as registrered DOs");
2327                break;
2328             case CDOM_type:
2329                SUMA_S_Err("Needs implementation");
2330                break;
2331             case AO_type:
2332                if (csv->ShowEyeAxis){
2333                   if (!SUMA_DrawAxis (
2334                         (SUMA_Axis*)dov[sRegistDO[i].dov_ind].OP, csv)) {
2335                      fprintf( SUMA_STDERR,
2336                               "Error %s: Could not display EYE AXIS\n",
2337                               FuncName);
2338                   }
2339                }
2340                break;
2341             case GO_type:
2342                break;
2343             case ROIdO_type:
2344                /* those are drawn by SUMA_DrawMesh */
2345                break;
2346             case ROIO_type:
2347                /* those are drawn by SUMA_DrawMesh */
2348                break;
2349             case NBT_type:
2350             case SBT_type:
2351             case DBT_type:
2352                /*  those types are not used  */
2353                break;
2354             case ONBV_type:
2355             case NBV_type:
2356             case OLS_type:
2357             case LS_type:
2358             case DIR_type:
2359             case ODIR_type:
2360             case NBOLS_type:
2361             case NBLS_type:
2362                if (!SUMA_DrawSegmentDO (
2363                      (SUMA_SegmentDO *)dov[sRegistDO[i].dov_ind].OP,
2364                      csv)) {
2365                   fprintf( SUMA_STDERR,
2366                            "Error %s: Failed in SUMA_DrawSegmentDO.\n",
2367                            FuncName);
2368                }
2369                break;
2370             case PL_type:
2371                SUMA_SL_Warn("Not ready yet!");
2372                break;
2373             case VO_type:
2374                if (!SUMA_DrawVolumeDO (
2375                      (SUMA_VolumeObject *)dov[sRegistDO[i].dov_ind].OP,
2376                         csv)) {
2377                   fprintf( SUMA_STDERR,
2378                            "Error %s: Failed in SUMA_DrawVolumeDO.\n",
2379                            FuncName);
2380                }
2381                break;
2382             case NIDO_type:
2383                SUMA_LH("Doing Screen NIDO");
2384                if (!SUMA_DrawNIDO ((SUMA_NIDO*)dov[sRegistDO[i].dov_ind].OP,
2385                      csv)) {
2386                   fprintf( SUMA_STDERR,
2387                            "Error %s: Failed in SUMA_DrawNIDO.\n",
2388                            FuncName);
2389                }
2390                break;
2391             case TRACT_type: /* should not be fixed */
2392                break;
2393             case MASK_type: /* Would we ever need this to be fixed? */
2394                break;
2395             case GRAPH_LINK_type: /* don't think we have these fixed either */
2396                break;
2397          }
2398       }
2399       ++i;
2400    }
2401 
2402    SUMA_SET_GL_MODELVIEW(csv);
2403 
2404    /* cycle through sRegistDO and display
2405       those things that have a Local CoordType*/
2406    if (LocalHead)
2407       fprintf (SUMA_STDERR,
2408                "%s: Creating objects with local coordinates ...\n", FuncName);
2409 
2410    /* cuting plane for all? */
2411    if (SUMAg_CF->N_ClipPlanes) { /* clipping parts in object coordinate space */
2412       for (i=0; i<SUMAg_CF->N_ClipPlanes; ++i) {
2413          if (SUMAg_CF->ClipPlaneType[i] == SUMA_ALL_OBJECT_CLIP) {
2414             glClipPlane(SUMA_index_to_clip_plane(i),
2415                         &(SUMAg_CF->ClipPlanes[4*i]));
2416             glEnable(SUMA_index_to_clip_plane(i));
2417          }
2418       }
2419    }
2420 
2421    /* Show the World Axis if required,
2422    Do this before DOs because with Depth test enabled (as it should
2423    for axis drawing, you can have a large texture volume, with many outer voxels
2424    of zeros obscuring the axis because of the depth test.
2425    One could deactivate the
2426    depth test and play with color blending but that is a pain. */
2427    if (csv->ShowWorldAxis) {
2428       /* fprintf(SUMA_STDOUT,"Showing World Axis \n");  */
2429       if (!SUMA_DrawAxis (csv->WAx, csv)) {
2430          fprintf(stderr,"display error: Failed to Create WAx\n");
2431       }
2432    }
2433 
2434 
2435    i = 0; iflush = N_sReg;
2436    while (i < N_sReg) {
2437       if (dov[sRegistDO[i].dov_ind].CoordType == SUMA_WORLD) {
2438          switch (dov[sRegistDO[i].dov_ind].ObjectType) {
2439             case N_DO_TYPES:
2440                SUMA_S_Err("N_DO_TYPES should not come up here");
2441                break;
2442             case SO_type:
2443                SO = (SUMA_SurfaceObject *)dov[sRegistDO[i].dov_ind].OP;
2444                if (SO->Show && SO->PolyMode != SRM_Hide) {
2445                   if (  (SO->Side == SUMA_LEFT && csv->ShowLeft) ||
2446                         (SO->Side == SUMA_RIGHT && csv->ShowRight) ||
2447                         SO->Side == SUMA_NO_SIDE || SO->Side == SUMA_LR) {
2448                         if (SUMAg_CF->Dev &&
2449                             (SUMA_EnvVal("SUMA_TEMP_NODE_CMASK_EXPR"))) {
2450                            /* Secret option, for testing only, search for
2451                            env above for example */
2452                            SUMA_DrawMesh_mask(SO, csv); /* create the surface */
2453                         } else {
2454                            SUMA_DrawMesh(SO, csv); /* create the surface */
2455                         }
2456                   }
2457                }
2458                break;
2459             case VO_type:
2460                VO = (SUMA_VolumeObject *)dov[sRegistDO[i].dov_ind].OP;
2461                if (VO->Show) {
2462                   if (!SUMA_DrawVolumeDO (VO, csv)) {
2463                      SUMA_S_Err("Failed in SUMA_DrawVolumeDO.");
2464                   }
2465                }
2466                break;
2467             case AO_type:
2468                if (csv->ShowMeshAxis) {
2469                   if (!SUMA_DrawAxis (
2470                                  (SUMA_Axis*)dov[sRegistDO[i].dov_ind].OP,
2471                                        csv)) {
2472                      fprintf( stderr,
2473                               "display error: Could not display Mesh AXIS\n");
2474                   }
2475                }
2476                break;
2477             case GO_type:
2478                break;
2479             case ROIdO_type:
2480                /* those are drawn by SUMA_DrawMesh */
2481                break;
2482             case ROIO_type:
2483                /* those are drawn by SUMA_DrawMesh */
2484                break;
2485             case ONBV_type:
2486             case NBV_type:
2487             case NBLS_type:
2488             case NBOLS_type:
2489                /* those are drawn by SUMA_DrawMesh */
2490                break;
2491             case NBT_type:
2492             case SBT_type:
2493             case DBT_type:
2494                /* those types are not used */
2495                break;
2496             case ANY_DSET_type:
2497             case MD_DSET_type:
2498             case GDSET_type:
2499                SUMA_S_Warn("Should not have type in DO list to be rendered");
2500                break;
2501             case CDOM_type:
2502                #if 0
2503                   /* A CIFTI DO is not drawn directly, not any more */
2504                if (!SUMA_Draw_CIFTI_DO (
2505                      (SUMA_CIFTI_DO *)dov[sRegistDO[i].dov_ind].OP, csv)) {
2506                   fprintf( SUMA_STDERR,
2507                            "Error %s: Failed in SUMA_Draw_CIFTI_DO.\n",
2508                            FuncName);
2509                }
2510                #endif
2511                break;
2512             case MASK_type:
2513                if (!SUMA_DrawMaskDO (
2514                      (SUMA_MaskDO *)dov[sRegistDO[i].dov_ind].OP, csv)) {
2515                   fprintf( SUMA_STDERR,
2516                            "Error %s: Failed in SUMA_DrawMaskDO.\n",
2517                            FuncName);
2518                }
2519                break;
2520             case TRACT_type:
2521                if (!SUMA_DrawTractDO (
2522                      (SUMA_TractDO *)dov[sRegistDO[i].dov_ind].OP, csv)) {
2523                   fprintf( SUMA_STDERR,
2524                            "Error %s: Failed in SUMA_DrawTractDO.\n",
2525                            FuncName);
2526                }
2527                break;
2528             case OLS_type:
2529             case LS_type:
2530             case DIR_type:
2531             case ODIR_type:
2532                if (!SUMA_DrawSegmentDO (
2533                      (SUMA_SegmentDO *)dov[sRegistDO[i].dov_ind].OP, csv)) {
2534                   fprintf( SUMA_STDERR,
2535                            "Error %s: Failed in SUMA_DrawSegmentDO.\n",
2536                            FuncName);
2537                }
2538                break;
2539             case NBSP_type:
2540                /* those are drawn by SUMA_DrawMesh */
2541                break;
2542             case PNT_type:
2543                if (!SUMA_DrawPointDO (
2544                      (SUMA_SphereDO *)dov[sRegistDO[i].dov_ind].OP, csv)) {
2545                   fprintf( SUMA_STDERR,
2546                            "Error %s: Failed in SUMA_DrawPntDO.\n", FuncName);
2547                }
2548                break;
2549             case SP_type:
2550                if (!SUMA_DrawSphereDO (
2551                      (SUMA_SphereDO *)dov[sRegistDO[i].dov_ind].OP, csv)) {
2552                   fprintf( SUMA_STDERR,
2553                            "Error %s: Failed in SUMA_DrawSphereDO.\n", FuncName);
2554                }
2555                break;
2556             case PL_type:
2557                if (!SUMA_DrawPlaneDO (
2558                      (SUMA_PlaneDO *)dov[sRegistDO[i].dov_ind].OP, csv)) {
2559                   fprintf(SUMA_STDERR,
2560                            "Error %s: Failed in SUMA_DrawPlaneDO.\n", FuncName);
2561                }
2562                break;
2563             case NIDO_type:
2564                if (SUMA_isNIDO_SurfBased(
2565                      (SUMA_NIDO *)dov[sRegistDO[i].dov_ind].OP)) {
2566                   /* this is done in SUMA_DrawMesh */
2567                } else {
2568                   if (!SUMA_DrawNIDO (
2569                         (SUMA_NIDO *)dov[sRegistDO[i].dov_ind].OP, csv)) {
2570                      fprintf(SUMA_STDERR,
2571                               "Error %s: Failed in SUMA_DrawNIDO.\n", FuncName);
2572                   }
2573                }
2574                break;
2575             case GRAPH_LINK_type:
2576                if (SUMAg_CF->Dev && SUMA_isEnv("JAVIER_DEPTH_SPECIAL","YES") &&
2577                    i < iflush) {
2578                   SUMA_LH("Flushing depth buffer");
2579                   /* This trick, and a dirty one it is, allows Javier to see
2580                   all the connections, unimpeded by any other objects that might
2581                   obscure it. This simple trick will only work if graphs
2582                   are rendered at the very end of all other objects.
2583                   Not sure what the implications, if any, will be for
2584                   the matrix display...*/
2585                   glClear(GL_DEPTH_BUFFER_BIT);
2586                   iflush = i;
2587                }
2588                /* find the real DO this baby points to and render that */
2589                if (!SUMA_DrawGraphLinkDO (
2590                     (SUMA_GraphLinkDO *)dov[sRegistDO[i].dov_ind].OP, csv)) {
2591                      fprintf(SUMA_STDERR,
2592                               "Error %s: Failed in SUMA_DrawGraphLinkDO.\n",
2593                               FuncName);
2594                }
2595                break;
2596             case NOT_SET_type:
2597             case not_DO_type:
2598                SUMA_SL_Err("What's cracking?");
2599                break;
2600          }
2601       }
2602       ++i;
2603    }
2604 
2605    /* Show the Cross Hair, if required leave this at the end because
2606    it does not care about depth tests which could be a problem when doing
2607    texture volumes*/
2608    if (csv->ShowCrossHair) {
2609       SUMA_LH("Showing Cross Hair");
2610       if (!SUMA_DrawCrossHair (csv)) {
2611          fprintf(stderr,"display error: Failed to Create Cross Hair\n");
2612       }
2613    }
2614 
2615 
2616    #if 0
2617    /* Show the pick line, you may want place this as a DO later on */
2618     {
2619       static GLfloat NoColor[] = {0.0, 0.0, 0.0, 0.0};
2620       static GLfloat LineColor[] = {1.0, 0.0, 1.0, 0.0};
2621       glLineWidth(1.0);
2622       glDisable(GL_DEPTH_TEST);
2623       glEnable(GL_LINE_STIPPLE);
2624       glLineStipple (1, 0x1C47); /* dashed, see OpenGL Prog guide, page 55 */
2625       glBegin(GL_LINES);
2626       glMaterialfv(GL_FRONT, GL_EMISSION, LineColor);
2627          /*turn on emissivity for axis*/
2628       glVertex3f(csv->Pick0[0], csv->Pick0[1], csv->Pick0[2]);
2629       glVertex3f(csv->Pick1[0], csv->Pick1[1], csv->Pick1[2]);
2630       glMaterialfv(GL_FRONT, GL_EMISSION, NoColor);
2631          /*turn off emissivity for axis*/
2632       glEnd();
2633       glDisable(GL_LINE_STIPPLE);
2634    }
2635    #endif
2636 
2637    /* Pop matrix and scrimooche */
2638    glPopMatrix();
2639 
2640    if (sRegistDO && sRegistDO != csv->RegistDO) {
2641      SUMA_free(sRegistDO);
2642    }
2643    sRegistDO = NULL;
2644 
2645    SUMA_RETURNe;
2646 }
2647 
2648 void
SUMA_graphicsInit(Widget w,XtPointer clientData,XtPointer call)2649 SUMA_graphicsInit(Widget w, XtPointer clientData, XtPointer call)
2650 {
2651 
2652    XVisualInfo *SUMAg_cVISINFO=NULL;
2653    static char FuncName[]={"SUMA_graphicsInit"};
2654    int isv;
2655    char buf[32];
2656    SUMA_SurfaceViewer *sv;
2657 
2658    SUMA_ENTRY;
2659 
2660    /* determine the surface viewer that the widget belongs to */
2661    SUMA_ANY_WIDGET2SV((Widget)w, sv, isv);
2662    if (isv < 0) {
2663       fprintf (SUMA_STDERR,
2664                "Error %s: Failed in macro SUMA_ANY_WIDGET2SV.\n", FuncName);
2665       SUMA_RETURNe;
2666    }
2667 
2668    /* Create OpenGL rendering context. */
2669    XtVaGetValues(w, GLwNvisualInfo, &SUMAg_cVISINFO, NULL);
2670    sv->X->GLXCONTEXT =
2671       glXCreateContext(XtDisplay(w), SUMAg_cVISINFO,
2672                0,                  /* No sharing. */
2673                True);              /* Direct rendering if possible. */
2674 
2675    /* Setup OpenGL state. */
2676    /* SUMA_HOLD_IT; Not used anymore */
2677    sprintf(buf,"Init of sv %d", isv);
2678    if (!SUMA_glXMakeCurrent(XtDisplay(w), XtWindow(w), sv->X->GLXCONTEXT,
2679                   FuncName, buf, 1)) {
2680       fprintf (SUMA_STDERR,
2681                "Error %s: Failed in SUMA_glXMakeCurrent.\n \tContinuing ...\n",
2682                FuncName);
2683       SUMA_RETURNe;
2684    }
2685 
2686    /* call context_Init to setup colors and lighting */
2687    SUMA_context_Init(sv);
2688 
2689    SUMA_RETURNe;
2690 }
2691 
2692 void
SUMA_context_Init(SUMA_SurfaceViewer * sv)2693 SUMA_context_Init(SUMA_SurfaceViewer *sv)
2694 {
2695    static char FuncName[]={"SUMA_context_Init"};
2696    GLfloat mat_specular[] = { SUMA_MAT_SPECULAR_INIT};
2697    GLfloat mat_shininess[] = { SUMA_MAT_SHININESS_INIT };
2698    GLfloat mat_ambient[] = { SUMA_MAT_AMBIENT_INIT};
2699    GLfloat mat_diffuse[] = { SUMA_MAT_DIFFUSE_INIT };
2700    GLfloat mat_emission[] = { SUMA_MAT_EMISSION_INIT  };
2701 
2702    /*GLfloat green_light[] = { 0.0, 1.0, 0.0, 1.0};*/
2703 
2704    SUMA_ENTRY;
2705    if (sv->PolyMode == SRM_Hide) {
2706       SUMA_SL_Note("sv->PolyMode reset to SRM_Fill");
2707       sv->PolyMode = SRM_Fill;
2708    }
2709    glClearColor (sv->clear_color[0], sv->clear_color[1],
2710                  sv->clear_color[2], sv->clear_color[3]);
2711    glShadeModel (GL_SMOOTH);
2712 
2713    SUMA_SET_GL_RENDER_MODE(sv->PolyMode);
2714 
2715 
2716    /* Set the material properties*/
2717    glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
2718    glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
2719    glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
2720    glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
2721    glMaterialfv(GL_FRONT, GL_EMISSION, mat_emission);
2722 
2723    /* set the directional light properties */
2724    glLightfv(GL_LIGHT0, GL_POSITION, sv->light0_position);
2725    glLightfv(GL_LIGHT0, GL_DIFFUSE, sv->light0_color);
2726    glLightfv(GL_LIGHT0, GL_SPECULAR, sv->light0_color);
2727 
2728    /*glLightfv(GL_LIGHT1, GL_POSITION, sv->light1_position);
2729    glLightfv(GL_LIGHT1, GL_DIFFUSE, green_light);
2730    glLightfv(GL_LIGHT1, GL_SPECULAR, green_light);*/
2731 
2732    /* set the ambient light */
2733    glLightModelfv(GL_LIGHT_MODEL_AMBIENT, sv->lmodel_ambient);
2734 
2735    glEnable(GL_LIGHTING); /* prepare GL to perform lighting calculations */
2736    glEnable(GL_LIGHT0); /*Turn lights ON */
2737    /*glEnable(GL_LIGHT1); */
2738    glEnable(GL_DEPTH_TEST);
2739    /* back face culling does not work with SureFit surfaces since facesets are not all defined clockwise or counter clockwise */
2740    /* also back face culling won't light up the interior of a surface, which is nice to have at times. Like occip patches for example */
2741    if (sv->BF_Cull) {
2742       glCullFace (GL_BACK);
2743       glEnable (GL_CULL_FACE);
2744    }
2745 
2746    /*setup the view point and then setup the lights. Those lights will remain in place regardless of the rotations/translations
2747    done on the surface */
2748    glMatrixMode(GL_MODELVIEW);
2749    glLoadIdentity();
2750    gluLookAt (   sv->GVS[sv->StdView].ViewFrom[0], sv->GVS[sv->StdView].ViewFrom[1],
2751                sv->GVS[sv->StdView].ViewFrom[2], sv->GVS[sv->StdView].ViewCenter[0],
2752                sv->GVS[sv->StdView].ViewCenter[1], sv->GVS[sv->StdView].ViewCenter[2],
2753                sv->GVS[sv->StdView].ViewCamUp[0], sv->GVS[sv->StdView].ViewCamUp[1],
2754                sv->GVS[sv->StdView].ViewCamUp[2] );
2755 
2756    /*glLightfv(GL_LIGHT0, GL_POSITION, sv->light0_position);*/
2757    /*glLightfv(GL_LIGHT1, GL_POSITION, sv->light1_position);*/
2758 
2759    SUMA_RETURNe;
2760 
2761 }
2762 
SUMA_SV_WindDims_From_DrawAreaDims(SUMA_SurfaceViewer * sv)2763 SUMA_Boolean SUMA_SV_WindDims_From_DrawAreaDims(SUMA_SurfaceViewer *sv)
2764 {
2765    static char FuncName[]={"SUMA_SV_WindDims_From_DrawAreaDims"};
2766 
2767    SUMA_ENTRY;
2768 
2769    if (!sv || !sv->X) {
2770       SUMA_S_Err("sv or sv->X is NULL");
2771       SUMA_RETURN(NOPE);
2772    }
2773 
2774    if (sv->DrawAreaWidthOffset < 0 || sv->DrawAreaHeightOffset < 0) {
2775       if (!(SUMA_SV_InitDrawAreaOffset(sv))) {
2776          SUMA_S_Err("Offset not initialized (%d %d)!\n",
2777                    sv->DrawAreaWidthOffset, sv->DrawAreaHeightOffset);
2778          SUMA_RETURN(NOPE);
2779       }
2780    }
2781    sv->wWindWidth = sv->DrawAreaWidthOffset+sv->X->aWIDTH;
2782    sv->wWindHeight = sv->DrawAreaHeightOffset+sv->X->aHEIGHT;
2783    SUMA_RETURN(YUP);
2784 }
2785 
SUMA_SV_InitDrawAreaOffset(SUMA_SurfaceViewer * sv)2786 SUMA_Boolean SUMA_SV_InitDrawAreaOffset(SUMA_SurfaceViewer *sv)
2787 {
2788    static char FuncName[]={"SUMA_SV_WindDims_From_DrawAreaDims"};
2789    Dimension awidth, aheight;
2790    Dimension wwidth, wheight;
2791    int dd;
2792    SUMA_Boolean LocalHead = NOPE;
2793 
2794    SUMA_ENTRY;
2795 
2796    if (!sv || !sv->X || !sv->X->TOPLEVEL || !sv->X->GLXAREA) {
2797       SUMA_S_Err("sv or sv->X or widgets is/are NULL");
2798       SUMA_RETURN(NOPE);
2799    }
2800 
2801    XtVaGetValues (sv->X->GLXAREA,
2802       XmNwidth, &awidth,
2803       XmNheight, &aheight,
2804       NULL);
2805    SUMA_LH("GLXAREA dims: %d %d", awidth, aheight);
2806    XtVaGetValues (sv->X->TOPLEVEL,
2807       XmNwidth, &wwidth,
2808       XmNheight, &wheight,
2809       NULL);
2810    SUMA_LH("Window dims: %d %d", wwidth, wheight);
2811    dd = (wwidth - awidth);
2812    if (dd > 0 && dd < 100) { /* sometimes values returned are crraazy,
2813                                 so just to be sure */
2814       sv->DrawAreaWidthOffset = dd;
2815    }
2816    dd = (wheight - aheight);
2817    if (dd > 0 && dd < 100) { /* sometimes values returned are crraazy,
2818                                 so just to be sure */
2819       sv->DrawAreaHeightOffset = dd;
2820    }
2821    if (sv->DrawAreaWidthOffset > 0 && sv->DrawAreaHeightOffset > 0) {
2822       SUMA_RETURN(YUP);
2823    } else {
2824       SUMA_RETURN(NOPE);
2825    }
2826 }
2827 
SUMA_SV_DrawAreaDims_From_WindDims(SUMA_SurfaceViewer * sv)2828 SUMA_Boolean SUMA_SV_DrawAreaDims_From_WindDims(SUMA_SurfaceViewer *sv)
2829 {
2830    static char FuncName[]={"SUMA_SV_DrawAreaDims_From_WindDims"};
2831 
2832    SUMA_ENTRY;
2833 
2834    if (!sv || !sv->X) {
2835       SUMA_S_Err("sv or sv->X is NULL");
2836       SUMA_RETURN(NOPE);
2837    }
2838    if (sv->DrawAreaWidthOffset < 0 || sv->DrawAreaHeightOffset < 0) {
2839       if (!(SUMA_SV_InitDrawAreaOffset(sv))) {
2840          SUMA_S_Err("Offset not initialized (%d %d)!\n",
2841                      sv->DrawAreaWidthOffset, sv->DrawAreaHeightOffset);
2842          SUMA_RETURN(NOPE);
2843       }
2844    }
2845    sv->X->aWIDTH  = sv->wWindWidth - sv->DrawAreaWidthOffset;
2846    sv->X->aHEIGHT = sv->wWindHeight - sv->DrawAreaHeightOffset;
2847    SUMA_RETURN(YUP);
2848 }
2849 
2850 void
SUMA_resize(Widget w,XtPointer clientData,XtPointer call)2851 SUMA_resize(Widget w,
2852   XtPointer clientData, XtPointer call)
2853 {
2854    static char FuncName[]={"SUMA_resize"};
2855    GLwDrawingAreaCallbackStruct *callData;
2856    SUMA_SurfaceViewer *sv;
2857    char buf[32];
2858    int isv;
2859    SUMA_Boolean LocalHead = NOPE;
2860 
2861    SUMA_ENTRY;
2862 
2863    /* determine the surface viewer that the widget belongs to */
2864    SUMA_ANY_WIDGET2SV(w, sv, isv);
2865    if (isv < 0) {
2866       fprintf (SUMA_STDERR,
2867                "Error %s: Failed in macro SUMA_ANY_WIDGET2SV.\n", FuncName);
2868       SUMA_RETURNe;
2869    }
2870 
2871    callData = (GLwDrawingAreaCallbackStruct *) call;
2872    SUMA_LH("Resizing sv %d to %dx%d from %dx%d", isv,
2873                   callData->width, callData->height,
2874                sv->X->aWIDTH, sv->X->aHEIGHT);
2875    /* SUMA_HOLD_IT; Not used anymore */
2876    sprintf(buf,"Resize sv %d", isv);
2877    if (!SUMA_glXMakeCurrent(XtDisplay(w), XtWindow(w), sv->X->GLXCONTEXT,
2878                            FuncName, buf, 1)) {
2879       fprintf (SUMA_STDERR,
2880                "Error %s: Failed in SUMA_glXMakeCurrent.\n \tContinuing ...\n",
2881                FuncName);
2882       SUMA_GL_ERRS;
2883 
2884       SUMA_RETURNe;
2885    }
2886    SUMA_LH("Context made current");
2887    /* SUMA_HOLD_IT; Not used anymore */
2888 
2889    glXWaitX();
2890    sv->X->aWIDTH = callData->width;
2891    sv->X->aHEIGHT = callData->height;
2892    glViewport(0, 0, callData->width, callData->height);
2893 
2894    glMatrixMode(GL_MODELVIEW);
2895    glLoadIdentity();
2896    gluLookAt ( sv->GVS[sv->StdView].ViewFrom[0],
2897                sv->GVS[sv->StdView].ViewFrom[1],
2898                sv->GVS[sv->StdView].ViewFrom[2],
2899                sv->GVS[sv->StdView].ViewCenter[0],
2900                sv->GVS[sv->StdView].ViewCenter[1],
2901                sv->GVS[sv->StdView].ViewCenter[2],
2902                sv->GVS[sv->StdView].ViewCamUp[0],
2903                sv->GVS[sv->StdView].ViewCamUp[1],
2904                sv->GVS[sv->StdView].ViewCamUp[2]);
2905    sv->Aspect = (GLfloat) callData->width/(GLfloat) callData->height;
2906    if (!(SUMA_SV_WindDims_From_DrawAreaDims(sv))) {
2907       SUMA_S_Err("Failed to set window dims. This should not happen");
2908       SUMA_DUMP_TRACE("How did you get here?");
2909       SUMA_S_Warn("Assuming offset is 0, but that's not cool");
2910       sv->wWindWidth = sv->X->aWIDTH;
2911       sv->wWindHeight = sv->X->aHEIGHT;
2912    }
2913 
2914    sv->rdc = SUMA_RDC_X_RESIZE;
2915    SUMA_postRedisplay(w, clientData, call);
2916    /* flush pick buffer */
2917    SUMA_PickBuffer(sv, 0, NULL);
2918 
2919    SUMA_RETURNe;
2920 }
2921 
2922 
2923 void
SUMA_expose(Widget w,XtPointer clientData,XtPointer call)2924 SUMA_expose(Widget w,
2925   XtPointer clientData, XtPointer call)
2926 {
2927   static char FuncName[]={"SUMA_expose"};
2928   int isv;
2929   SUMA_SurfaceViewer *sv;
2930   SUMA_Boolean LocalHead = NOPE;
2931 
2932   SUMA_ENTRY;
2933 
2934    SUMA_LH("Called");
2935   /*glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);*/
2936                               /* No need for that, done in display */
2937 
2938 
2939    /* get the viewer just entered. */
2940    SUMA_ANY_WIDGET2SV(w, sv, isv);
2941    if (isv < 0) {
2942       SUMA_S_Err("Failed in macro SUMA_ANY_WIDGET2SV.");
2943       SUMA_RETURNe;
2944    }
2945 
2946    sv->rdc = SUMA_RDC_X_EXPOSE;
2947 
2948    /* When using multiple viewers, you must reset the OpenGL state
2949       variables or risk having abrupt changes with the first click */
2950    sv->ResetGLStateVariables = YUP;
2951    SUMA_postRedisplay(w, NULL, NULL);
2952 
2953    if (SUMAg_CF->N_dcom) {
2954       for (isv = 0; isv < SUMAg_CF->N_dcom; ++isv) {
2955          SUMA_S_Note("Executing driver command %d: %s\n",
2956                      isv, SUMAg_CF->dcom[isv]);
2957          SUMA_MakeMeDo(SUMAg_CF->dcom[isv], 0);
2958          SUMA_ifree(SUMAg_CF->dcom[isv]);
2959       }
2960       SUMA_ifree(SUMAg_CF->dcom); SUMAg_CF->N_dcom = 0;
2961    }
2962 
2963 
2964 
2965    SUMA_RETURNe;
2966 }
2967 
2968 void
SUMA_mapStateChanged(Widget w,XtPointer clientData,XEvent * event,Boolean * cont)2969 SUMA_mapStateChanged(Widget w, XtPointer clientData,
2970   XEvent * event, Boolean * cont)
2971 {
2972 
2973    static char FuncName[]={"SUMA_mapStateChanged"};
2974    int isv;
2975    SUMA_SurfaceViewer *sv;
2976    SUMA_Boolean LocalHead = NOPE;
2977 
2978    SUMA_ENTRY;
2979 
2980    SUMA_LH("Called");
2981 
2982    /* determine the surface viewer that the widget belongs to */
2983    SUMA_ANY_WIDGET2SV(w, sv, isv);
2984    if (isv < 0) {
2985       fprintf (SUMA_STDERR, "Error %s: Failed in macro SUMA_ANY_WIDGET2SV.\n", FuncName);
2986       SUMA_RETURNe;
2987    }
2988 
2989    sv->rdc = SUMA_RDC_X_MAPSTATE;
2990 
2991    /* When using multiple viewers, you must reset the OpenGL state variables or risk having abrupt changes with the first click */
2992    sv->ResetGLStateVariables = YUP;
2993 
2994    /*fprintf(stdout, "widget window being mapped/unmapped\n");*/
2995    switch (event->type) {
2996    case MapNotify:
2997       sv->isShaded = NOPE;
2998       if (sv->GVS[sv->StdView].ApplyMomentum)
2999          sv->X->MOMENTUMID = XtAppAddTimeOut(SUMAg_CF->X->App, 1, SUMA_momentum, (XtPointer)w);
3000       break;
3001    case UnmapNotify:
3002       sv->isShaded = YUP;
3003       if (sv->GVS[sv->StdView].ApplyMomentum) {
3004          if (sv->X->MOMENTUMID) XtRemoveTimeOut(sv->X->MOMENTUMID);
3005          sv->X->MOMENTUMID = 0;
3006       }
3007       break;
3008    }
3009 
3010   SUMA_postRedisplay(w, clientData, NULL);
3011 
3012   SUMA_RETURNe;
3013 }
3014 
3015 /*!
3016 
3017    \param ContID (void *) This parameters is stored in the callback structure that the menu items
3018                         send to the callback. You can pass an integer for a controller's index or
3019                         any other structure like a surface object's ID for example.
3020    The callback structure value associated with each menu widget (cv) is:
3021    CBp->ContID = ContID;
3022    CBp->callback_data = callback_data (that is passed in items);
3023    This allows you to create multiple versions
3024    of the same menu and still be able to dissociate between them.
3025    \param hint, help (char *) strings for hints and bhelps...(NULL for nothing)
3026    \param MenuWidgets (Widget *) pointer to a vector that will contain widgets created.
3027          MenuWidgets[0] is the menu or cascade widgets, MenuWidgets[1]..MenuWidgets[N_wid-1]
3028          would contain the button and separator widgets specified in items
3029    \return N_wid (int) number of widgets in MenuWidgets. Obviously you'll need
3030          to know that ahead of time to allocate for MenuWidgets ...
3031 
3032 -  This function is largely based on BuildMenu in the "Motif Programming Manual"
3033   Build popup, option and pulldown menus, depending on the menu_type.
3034   It may be XmMENU_PULLDOWN, XmMENU_OPTION or  XmMENU_POPUP.  Pulldowns
3035   return the CascadeButton that pops up the menu.  Popups return the menu.
3036   Option menus are created, but the RowColumn that acts as the option
3037   "area" is returned unmanaged. (The user must manage it.)
3038   Pulldown menus are built from cascade buttons, so this function
3039   also builds pullright menus.  The function also adds the right
3040   callback for PushButton or ToggleButton menu items.
3041 
3042  *** SIGNIFICANT CHANGE to BuildMenu ZSS Apr 23 04
3043  *** MUST CALL SUMA_BuildMenuReset BEFORE calling SUMA_BuildMenu
3044  */
3045 static int i_wid = 0;
3046 static int N_wid = 0;
3047 static int nchar = 0;
3048 
SUMA_BuildMenuReset(int n_max)3049 void SUMA_BuildMenuReset(int n_max)
3050 {
3051    static char FuncName[]={"SUMA_BuildMenuReset"};
3052    SUMA_ENTRY;
3053    i_wid = 0;
3054    N_wid = 0;
3055    nchar = n_max;
3056    SUMA_RETURNe;
3057 }
3058 
3059 /* can't allow any menu to do arrow fields. For example
3060 Cmp will choke in function SUMA_SetCmapMenuChoice so you'll
3061 have to fix that case if you want to allow arrow fields for
3062 colormaps. But why on earth would that be needed?
3063 Only allow arrow fields for I, T, and B
3064 */
SUMA_AllowArrowFieldMenus(int N_items,char * menu_title)3065 int SUMA_AllowArrowFieldMenus(int N_items, char *menu_title)
3066 {
3067    if (!menu_title ||
3068         N_items < SUMA_floatEnv("SUMA_ArrowFieldSelectorTrigger", 200)) {
3069       return(0);
3070    }
3071    if (  !strcmp(menu_title,"I") ||
3072          !strcmp(menu_title,"T") ||
3073          !strcmp(menu_title,"B") ) return(1);
3074    return(0);
3075 }
3076 
SUMA_BuildMenu(Widget parent,int menu_type,char * menu_title,char menu_mnemonic,SUMA_Boolean tear_off,SUMA_MenuItem * items,void * ContID,char * wname,char * hint,char * help,SUMA_MENU_WIDGET * SMW)3077 int SUMA_BuildMenu(  Widget parent, int menu_type, char *menu_title,
3078                      char menu_mnemonic, SUMA_Boolean tear_off,
3079                      SUMA_MenuItem *items,
3080                      void *ContID,
3081                      char *wname, char *hint, char *help,
3082                      SUMA_MENU_WIDGET *SMW )
3083 {
3084    static char FuncName[]={"SUMA_BuildMenu"};
3085    char nlabel[300]="\0";
3086    Widget menu = NULL, cascade = NULL;
3087    XmString str=NULL;
3088    int i=-1; int N_items=0, ok_tear_off=1;
3089    SUMA_Boolean LocalHead = NOPE;
3090 
3091    SUMA_ENTRY;
3092 
3093    if (!menu_title) {
3094       SUMA_S_Warn("menu_title is NULL, alert Rick Reynolds!");
3095       menu_title = "";
3096    }
3097 
3098    if (items) {
3099       while(items[N_items].label) {
3100          if (N_items < 4) {
3101             SUMA_LHv("item %d %s callback %p\n",
3102                N_items, items[N_items].label, items[N_items].callback);
3103          } else {
3104             if (LocalHead) {fprintf(stderr,".");}
3105          }
3106          ++N_items;
3107      }
3108      if (LocalHead && N_items > 4) {fprintf(stderr,"\n");}
3109    }
3110    SUMA_LHv("Entered. menu_title %s, type %d, %d items.\n",
3111                menu_title, menu_type, N_items);
3112 
3113    if (SUMA_AllowArrowFieldMenus(N_items, menu_title)) {
3114       menu_type = SUMA_XmArrowFieldMenu;
3115       SUMA_LHv("Arrow field triggered menu_title %s, type %d, %d items.\n",
3116                menu_title, menu_type, N_items);
3117    }
3118    if (menu_type == XmMENU_PULLDOWN || menu_type == XmMENU_OPTION)
3119      menu = XmCreatePulldownMenu (parent, "_pulldown", NULL, 0);
3120    else if (menu_type == XmMENU_POPUP)
3121      menu = XmCreatePopupMenu (parent, "_popup", NULL, 0);
3122    else if (menu_type == SUMA_XmArrowFieldMenu) { /* an arrow field */
3123      menu = XtVaCreateWidget ("rowcolumn",
3124                   xmRowColumnWidgetClass, parent,
3125                   XmNpacking, XmPACK_TIGHT,
3126                   XmNleftAttachment,XmATTACH_FORM ,
3127                   XmNorientation , XmHORIZONTAL ,
3128                   XmNmarginHeight , 0 ,
3129                   XmNmarginWidth  , 0 ,
3130                      NULL);
3131       ok_tear_off = 0;
3132    }
3133    else {
3134      XtWarning ("Invalid menu type passed to BuildMenu()");
3135      SUMA_RETURN(-1);
3136    }
3137 
3138 
3139    if (tear_off && ok_tear_off)
3140      XtVaSetValues (menu, XmNtearOffModel, XmTEAR_OFF_ENABLED, NULL);
3141 
3142    /* Pulldown menus require a cascade button to be made */
3143    if (menu_type == XmMENU_PULLDOWN) {
3144      str = XmStringCreateLocalized (menu_title);
3145      cascade = XtVaCreateManagedWidget (menu_title,
3146          xmCascadeButtonWidgetClass, parent,
3147          XmNlabelString, str,
3148      /*     XmNmnemonic,    menu_mnemonic, this line causes a warning on
3149                                           OS X 10.6. Can't tell why...
3150                            It also causes plenty of valgrind conditional
3151                            jumps warnings.
3152                            To hell with it.*/
3153          XmNsubMenuId,   menu,
3154          XmNmarginHeight, 0,
3155          XmNmarginTop, 0,
3156          XmNmarginBottom, 0,
3157          NULL);
3158      XmStringFree (str);
3159    }
3160    else if (menu_type == XmMENU_OPTION) {
3161      /* Option menus are a special case, but not hard to handle */
3162      Arg args[10];
3163      int n = 0;
3164      SUMA_LHv("XmMENU_OPTION %s\n", menu_title);
3165      str = XmStringCreateLocalized (menu_title);
3166      XtSetArg (args[n], XmNsubMenuId, menu); n++;
3167      XtSetArg (args[n], XmNlabelString, str); n++;
3168      XtSetArg (args[n], XmNmarginHeight, 0); n++;
3169      XtSetArg (args[n], XmNmarginTop, 0 ); n++;
3170      XtSetArg (args[n], XmNmarginBottom, 0 ); n++;
3171      /* Following three settings have no effect ...
3172      XtSetArg (args[n], XmNpacking, XmPACK_COLUMN); n++;
3173      XtSetArg (args[n], XmNnumColumns, 2); n++;
3174      XtSetArg (args[n], XmNorientation, XmHORIZONTAL); n++;*/
3175 
3176      /* This really isn't a cascade, but this is the widget handle
3177       * we're going to return at the end of the function.
3178       */
3179      cascade = XmCreateOptionMenu (parent, menu_title, args, n);
3180      XmStringFree (str);
3181    }
3182    else if (menu_type == SUMA_XmArrowFieldMenu) {
3183       SUMA_LHv("XmMENU_OPTION %s\n", "ArrowFieldMode");
3184    }
3185 
3186    /* save the type */
3187    SMW->menu_type = menu_type;
3188 
3189    /* hide your jewel */
3190    if (menu_type == XmMENU_POPUP || menu_type == SUMA_XmArrowFieldMenu) {
3191       SMW->mw[i_wid] = menu; }
3192    else { SMW->mw[i_wid] = cascade; }
3193 
3194    if (hint || help) {
3195       SUMA_LH("Registering %s with \n%s\n and \n%s\n\n", wname, hint, help);
3196       SUMA_Register_Widget_Children_Help(SMW->mw[i_wid], 1, wname,
3197                                 hint, help);
3198    }
3199 
3200    ++i_wid;
3201 
3202    if (menu_type != SUMA_XmArrowFieldMenu) {
3203       /* Now add the menu items */
3204       for (i = 0; items[i].label != NULL; i++) {
3205          if (LocalHead)
3206             fprintf (SUMA_STDERR,
3207                      "%s: Adding label # %d - %s (CB: %p)\n",
3208                      FuncName, i, items[i].label, items[i].callback);
3209         /* If subitems exist, create the pull-right menu by calling this
3210          * function recursively.  Since the function returns a cascade
3211          * button, the widget returned is used..
3212          */
3213         if (items[i].subitems)
3214             if (menu_type == XmMENU_OPTION) {
3215                 XtWarning ("You can't have submenus from option menu items.");
3216                 continue;
3217             }
3218             else {
3219                 if (LocalHead)
3220                   fprintf (SUMA_STDERR, "%s: Going for sub-menu.\n", FuncName);
3221                 SUMA_BuildMenu ( menu, XmMENU_PULLDOWN, items[i].label,
3222                                  items[i].mnemonic, tear_off,
3223                                  items[i].subitems, ContID,
3224                                  wname, hint, help, SMW);
3225             }
3226         else {
3227             if (LocalHead)
3228                fprintf (SUMA_STDERR,
3229                         "%s: Creating widgets MenuWidgets[%d]\n",
3230                         FuncName, (INT_CAST)items[i].callback_data);
3231             if (nchar > 0) {
3232                snprintf(nlabel, nchar*sizeof(char), "%s", items[i].label);
3233                SMW->mw[i_wid] = XtVaCreateManagedWidget (nlabel,
3234                    *items[i].class, menu,
3235                    NULL);
3236             } else {
3237                SMW->mw[i_wid] =
3238                   XtVaCreateManagedWidget (items[i].label,
3239                    *items[i].class, menu,
3240                    NULL);
3241             }
3242          }
3243 
3244 
3245          /* Whether the item is a real item or a cascade button with a
3246          * menu, it can still have a mnemonic.
3247          */
3248          if (LocalHead)
3249             fprintf (SUMA_STDERR, "%s: Setting Mnemonic ...\n", FuncName);
3250          if (items[i].mnemonic)
3251             XtVaSetValues (SMW->mw[i_wid], XmNmnemonic,
3252                            items[i].mnemonic, NULL);
3253 
3254          /* any item can have an accelerator, except cascade menus. But,
3255          * we don't worry about that; we know better in our declarations.
3256          */
3257 
3258          if (LocalHead)
3259             fprintf (SUMA_STDERR, "%s: Setting accelerator ...\n", FuncName);
3260          if (items[i].accelerator) {
3261             str = XmStringCreateLocalized (items[i].accel_text);
3262             XtVaSetValues (SMW->mw[i_wid],
3263                 XmNaccelerator, items[i].accelerator,
3264                 XmNacceleratorText, str,
3265                 NULL);
3266             XmStringFree (str);
3267          }
3268 
3269          if (items[i].class == &xmToggleButtonWidgetClass ||
3270                  items[i].class == &xmToggleButtonWidgetClass) {
3271             Pixel fg_pix=0;
3272             XtVaGetValues (SMW->mw[i_wid],
3273                               XmNforeground, &fg_pix, NULL);
3274             XtVaSetValues (SMW->mw[i_wid],
3275                               XmNselectColor, fg_pix, NULL);
3276 
3277          }
3278 
3279          if (LocalHead)
3280             fprintf (SUMA_STDERR, "%s: Setting callback ...\n", FuncName);
3281          if (items[i].callback) {
3282             SUMA_MenuCallBackData *CBp=NULL;
3283             CBp = (SUMA_MenuCallBackData *)
3284                         calloc(1,sizeof(SUMA_MenuCallBackData));
3285             /* There is no freeing of this pointer in SUMA.
3286                         Once created, a widget is only destroyed when
3287                         SUMA is killed */
3288             /* prepare the callback pointer */
3289             CBp->callback_data = (XtPointer) items[i].callback_data;
3290             CBp->ContID = ContID;
3291             XtAddCallback (SMW->mw[i_wid],
3292                 (items[i].class == &xmToggleButtonWidgetClass ||
3293                  items[i].class == &xmToggleButtonWidgetClass) ?
3294                     XmNvalueChangedCallback : /* ToggleButton class */
3295                     XmNactivateCallback,      /* PushButton class */
3296                 items[i].callback, (XtPointer)CBp);
3297          }
3298          ++i_wid;
3299       }
3300    } else { /* special arrow field case */
3301       SUMA_MenuCallBackData *CBp=NULL;
3302       i = 0; /* all callbacks will be the same */
3303       /* An arrow field */
3304       if (!SMW->af) {
3305          SMW->af = (SUMA_ARROW_TEXT_FIELD*)
3306                            calloc(1,sizeof(SUMA_ARROW_TEXT_FIELD));
3307       }
3308       CBp = (SUMA_MenuCallBackData *)
3309                   calloc(1,sizeof(SUMA_MenuCallBackData));
3310       CBp->SMW = SMW;
3311       CBp->callback = items[i].callback;
3312       CBp->callback_data = NULL; /* this will be set in
3313                                   SUMA_MenuArrowFieldCallback*/
3314       CBp->ContID = ContID;
3315       SUMA_LHv("Building an arrow field, i=%d\n", i);
3316       SUMA_LHv("callback %p data %p\n",
3317                    items[i].callback, items[i].callback_data);
3318       SUMA_CreateArrowField ( menu, menu_title,
3319                      0, 0, N_items-1, 1,
3320                      8, SUMA_int,
3321                      YUP,
3322                      SUMA_MenuArrowFieldCallback, (void *)CBp,
3323                      wname,
3324                      "A way to switch sub-bricks in dsets with lots of them.",
3325                      SUMA_SurfContHelp_ArrowFieldMenu,
3326                      SMW->af);
3327    }
3328 
3329    #if 0
3330     {
3331       SUMA_LH( "Adding event handler."
3332                "Crashes when dealing with File: cascade buttons ....");
3333       if (menu_type == XmMENU_POPUP) {
3334          SUMA_ShowMeTheChildren(menu);
3335       } else {
3336          SUMA_ShowMeTheChildren(cascade);
3337       }
3338       /* add yourself an even handler to deal with long menus a la AFNI
3339       see bbox.c */
3340       if (0) {
3341       SUMA_ShowMeTheChildren(menu);
3342       XtInsertEventHandler(   cascade ,      /* handle events in optmenu */
3343                            ButtonPressMask ,  /* button presses */
3344                            FALSE ,            /* nonmaskable events? */
3345                            SUMA_optmenu_EV ,  /* handler */
3346                            (XtPointer) cascade ,   /* client data */
3347                            XtListTail ) ;     /* last in queue */
3348      }
3349 
3350    }
3351    #endif
3352    /* for popup menus, just return the menu; pulldown menus, return
3353    * the cascade button; option menus, return the thing returned
3354    * from XmCreateOptionMenu().  This isn't a menu, or a cascade button!
3355    */
3356    if (LocalHead)
3357       fprintf (SUMA_STDERR,
3358                "%s: Returning %d widgets created.\n", FuncName, i_wid);
3359    SUMA_RETURN (i_wid);
3360 }
3361 
3362 /* This function is a wrapper for calling menu callbacks when the
3363 Arrow field is used to setup the menu */
SUMA_MenuArrowFieldCallback(void * CB)3364 void SUMA_MenuArrowFieldCallback (void *CB)
3365 {
3366    static char FuncName[]={"SUMA_MenuArrowFieldCallback"};
3367    SUMA_MenuCallBackData *CBp = (SUMA_MenuCallBackData *)CB;
3368 
3369    SUMA_ENTRY;
3370 
3371    if (!CBp) {
3372       SUMA_S_Err("Bad setup, NULL CB"); SUMA_RETURNe;
3373    }
3374    if (!CBp->callback) {
3375       SUMA_S_Err("Bad setup, NULL CB->callback"); SUMA_RETURNe;
3376    }
3377    if (!CBp->SMW) {
3378       SUMA_S_Err("Need menu structure for arrofields"); SUMA_RETURNe;
3379    }
3380 
3381    CBp->callback_data = (XTP_CAST)((int)CBp->SMW->af->value+1);
3382    CBp->callback(NULL, (XtPointer)CBp, NULL);
3383    SUMA_RETURNe;
3384 }
3385 
3386 
3387 Widget Gmainw, Gmenubar;
3388 
3389 SUMA_MenuItem FileOpen_menu[] = {
3390    {  "OpenSpec", &xmPushButtonWidgetClass, \
3391       'p', "Ctrl<Key>p", "Ctrl+p", \
3392       SUMA_cb_FileOpenSpec, (XtPointer) SW_FileOpenSpec, NULL},
3393 
3394    {  "OpenSurf", &xmPushButtonWidgetClass, \
3395       'o', "Ctrl<Key>o", "Ctrl+o", \
3396       SUMA_cb_FileOpenSurf, (XtPointer) SW_FileOpenSurf, NULL},
3397 
3398    {NULL} ,
3399 };
3400 
3401 SUMA_MenuItem File_menu[] = {
3402    /*{  "Open", &xmPushButtonWidgetClass, \
3403       '\0', NULL, NULL, \
3404       NULL,  (XtPointer) SW_FileOpen, (SUMA_MenuItem *) FileOpen_menu },
3405    */
3406    {  "Save View", &xmPushButtonWidgetClass, \
3407       '\0', NULL, NULL, \
3408       SUMA_cb_FileSaveView, (XtPointer) SW_FileSaveView, NULL},
3409 
3410    {  "Load View", &xmPushButtonWidgetClass, \
3411       '\0', NULL, NULL, \
3412       SUMA_cb_FileLoadView, (XtPointer) SW_FileLoadView, NULL},
3413 
3414 
3415    {  "Close", &xmPushButtonWidgetClass, \
3416       'C', NULL, "Esc", \
3417       SUMA_cb_FileClose, (XtPointer) SW_FileClose, NULL},
3418 
3419    {NULL},
3420 };
3421 
3422 
3423 /*
3424 SUMA_MenuItem Edit_menu[] = {
3425    {  "Draw ROI", &xmPushButtonWidgetClass, \
3426       'D', "Ctrl <Key>d", "Ctrl+D", \
3427       SUMA_cb_ToolsDrawROI, (XtPointer) SW_ToolsDrawROI, NULL },
3428 
3429    {NULL},
3430 
3431 };
3432 */
3433 
3434 /* can use combo like: "Ctrl Shift<Key>d", "Ctrl+D"*/
3435 SUMA_MenuItem View_menu[] = {
3436    {  "SUMA Controller", &xmPushButtonWidgetClass, \
3437       'U', "Ctrl<Key>u", "Ctrl+u", \
3438       SUMA_cb_viewSumaCont, (XtPointer) SW_ViewSumaCont, NULL },
3439 
3440    {  "Object Controller", &xmPushButtonWidgetClass, \
3441       'S', "Ctrl<Key>s", "Ctrl+s", \
3442       SUMA_cb_viewSurfaceCont, (XtPointer) SW_ViewSurfCont, NULL },
3443 
3444    {  "Viewer Controller", &xmPushButtonWidgetClass, \
3445       'V', "Ctrl<Key>v", "Ctrl+v", \
3446       SUMA_cb_viewViewerCont, (XtPointer) SW_ViewViewCont, NULL },
3447 
3448    {  "Separator 1", &xmSeparatorWidgetClass, \
3449       '\0', NULL, NULL, \
3450       NULL, (XtPointer) SW_ViewSep1, NULL },
3451 
3452    {  "Cross Hair", &xmToggleButtonWidgetClass, \
3453       'C', "<Key>F3", "F3",  \
3454       SUMA_cb_toggle_crosshair, (XtPointer) SW_ViewCrossHair, NULL },
3455 
3456    {  "Node in Focus", &xmToggleButtonWidgetClass, \
3457       'N', "<Key>F4", "F4", \
3458       SUMA_cb_toggle_node_in_focus, (XtPointer) SW_ViewNodeInFocus, NULL },
3459 
3460    {  "Selected Faceset", &xmToggleButtonWidgetClass, \
3461       'F', "<Key>F5", "F5", \
3462       SUMA_cb_toggle_selected_faceset, (XtPointer) SW_ViewSelectedFaceset, NULL },
3463 
3464    {NULL},
3465 };
3466 
3467 SUMA_MenuItem Tools_menu[] = {
3468    {  "Draw ROI", &xmPushButtonWidgetClass, \
3469       'D', "Ctrl <Key>d", "Ctrl+d", \
3470       SUMA_cb_ToolsDrawROI, (XtPointer) SW_ToolsDrawROI, NULL },
3471 
3472    {NULL},
3473 
3474 };
3475 
3476 
3477 SUMA_MenuItem Help_menu[] = {
3478    {  "Web help", &xmPushButtonWidgetClass, \
3479       'W', NULL, NULL, \
3480       SUMA_cb_helpWeb, (XtPointer) SW_HelpWeb, NULL},
3481 
3482    {  "Usage", &xmPushButtonWidgetClass, \
3483       'U', "Ctrl <Key>h", "Ctrl+h", \
3484       SUMA_cb_helpUsage, (XtPointer) SW_HelpUsage, NULL},
3485 
3486    {  "Message Log", &xmPushButtonWidgetClass, \
3487       'L', NULL, NULL, \
3488       SUMA_cb_helpMessageLog, (XtPointer) SW_HelpMessageLog, NULL},
3489 
3490    {  "Separator 1", &xmSeparatorWidgetClass, \
3491       '\0', NULL, NULL, \
3492       NULL, (XtPointer) SW_HelpSep1, NULL },
3493 
3494    {  "SUMA Global", &xmPushButtonWidgetClass, \
3495       'G', NULL, NULL, \
3496       SUMA_cb_helpSUMAGlobal, (XtPointer) SW_HelpSUMAGlobal, NULL},
3497 
3498    {  "Viewer struct", &xmPushButtonWidgetClass, \
3499       'V', NULL, NULL, \
3500       SUMA_cb_helpViewerStruct, (XtPointer) SW_HelpViewerStruct, NULL},
3501 
3502    {  "Surface struct", &xmPushButtonWidgetClass, \
3503       'S', NULL, NULL, \
3504       SUMA_cb_helpSurfaceStruct, (XtPointer) SW_HelpSurfaceStruct, NULL},
3505 
3506    {  "Separator 2", &xmSeparatorWidgetClass, \
3507       '\0', NULL, NULL, \
3508       NULL, (XtPointer) SW_HelpSep2, NULL },
3509 
3510    {  "InOut Notify", &xmToggleButtonWidgetClass, \
3511       'I', NULL, NULL, \
3512       SUMA_cb_helpIO_notify, (XtPointer) SW_HelpIONotify, NULL},
3513 
3514    {  "Echo Keypresses", &xmToggleButtonWidgetClass, \
3515       'K', NULL, NULL, \
3516       SUMA_cb_helpEchoKeyPress, (XtPointer) SW_HelpEchoKeyPress, NULL},
3517 
3518    {  "MemTrace", &xmToggleButtonWidgetClass, \
3519       'M', NULL, NULL, \
3520       SUMA_cb_helpMemTrace, (XtPointer) SW_HelpMemTrace, NULL},
3521    {NULL},
3522 };
3523 
3524 SUMA_MenuItem RenderMode_Menu[] = {
3525    {  "Viewer", &xmPushButtonWidgetClass,
3526       '\0', NULL, NULL,
3527       SUMA_cb_SetRenderMode, (XtPointer) SW_SurfCont_RenderViewerDefault, NULL},
3528 
3529    {  "Fill", &xmPushButtonWidgetClass,
3530       '\0', NULL, NULL,
3531       SUMA_cb_SetRenderMode, (XtPointer) SW_SurfCont_RenderFill, NULL},
3532 
3533    {  "Line", &xmPushButtonWidgetClass,
3534       '\0', NULL, NULL,
3535       SUMA_cb_SetRenderMode, (XtPointer) SW_SurfCont_RenderLine, NULL},
3536 
3537    {  "Points", &xmPushButtonWidgetClass,
3538       '\0', NULL, NULL,
3539       SUMA_cb_SetRenderMode, (XtPointer) SW_SurfCont_RenderPoints, NULL},
3540 
3541    {  "Hide", &xmPushButtonWidgetClass,
3542       '\0', NULL, NULL,
3543       SUMA_cb_SetRenderMode, (XtPointer) SW_SurfCont_RenderHide, NULL},
3544 
3545    {NULL},
3546 };
3547 
3548 SUMA_MenuItem TransMode_Menu[] = {
3549    {  "Vwr", &xmPushButtonWidgetClass,
3550       '\0', NULL, NULL,
3551       SUMA_cb_SetTransMode, (XtPointer) SW_SurfCont_TransViewerDefault, NULL},
3552 
3553    {  "0", &xmPushButtonWidgetClass,
3554       '\0', NULL, NULL,
3555       SUMA_cb_SetTransMode, (XtPointer) SW_SurfCont_Trans0, NULL},
3556 
3557    {  "1", &xmPushButtonWidgetClass,
3558       '\0', NULL, NULL,
3559       SUMA_cb_SetTransMode, (XtPointer) SW_SurfCont_Trans1, NULL},
3560 
3561    {  "2", &xmPushButtonWidgetClass,
3562       '\0', NULL, NULL,
3563       SUMA_cb_SetTransMode, (XtPointer) SW_SurfCont_Trans2, NULL},
3564 
3565    {  "3", &xmPushButtonWidgetClass,
3566       '\0', NULL, NULL,
3567       SUMA_cb_SetTransMode, (XtPointer) SW_SurfCont_Trans3, NULL},
3568 
3569    {  "4", &xmPushButtonWidgetClass,
3570       '\0', NULL, NULL,
3571       SUMA_cb_SetTransMode, (XtPointer) SW_SurfCont_Trans4, NULL},
3572 
3573    {  "5", &xmPushButtonWidgetClass,
3574       '\0', NULL, NULL,
3575       SUMA_cb_SetTransMode, (XtPointer) SW_SurfCont_Trans5, NULL},
3576 
3577    {  "6", &xmPushButtonWidgetClass,
3578       '\0', NULL, NULL,
3579       SUMA_cb_SetTransMode, (XtPointer) SW_SurfCont_Trans6, NULL},
3580 
3581    {  "7", &xmPushButtonWidgetClass,
3582       '\0', NULL, NULL,
3583       SUMA_cb_SetTransMode, (XtPointer) SW_SurfCont_Trans7, NULL},
3584 
3585    {  "8", &xmPushButtonWidgetClass,
3586       '\0', NULL, NULL,
3587       SUMA_cb_SetTransMode, (XtPointer) SW_SurfCont_Trans8, NULL},
3588 
3589    {  "9", &xmPushButtonWidgetClass,
3590       '\0', NULL, NULL,
3591       SUMA_cb_SetTransMode, (XtPointer) SW_SurfCont_Trans9, NULL},
3592 
3593    {  "10", &xmPushButtonWidgetClass,
3594       '\0', NULL, NULL,
3595       SUMA_cb_SetTransMode, (XtPointer) SW_SurfCont_Trans10, NULL},
3596 
3597    {  "11", &xmPushButtonWidgetClass,
3598       '\0', NULL, NULL,
3599       SUMA_cb_SetTransMode, (XtPointer) SW_SurfCont_Trans11, NULL},
3600 
3601    {  "12", &xmPushButtonWidgetClass,
3602       '\0', NULL, NULL,
3603       SUMA_cb_SetTransMode, (XtPointer) SW_SurfCont_Trans12, NULL},
3604 
3605    {  "13", &xmPushButtonWidgetClass,
3606       '\0', NULL, NULL,
3607       SUMA_cb_SetTransMode, (XtPointer) SW_SurfCont_Trans13, NULL},
3608 
3609    {  "14", &xmPushButtonWidgetClass,
3610       '\0', NULL, NULL,
3611       SUMA_cb_SetTransMode, (XtPointer) SW_SurfCont_Trans14, NULL},
3612 
3613    {  "15", &xmPushButtonWidgetClass,
3614       '\0', NULL, NULL,
3615       SUMA_cb_SetTransMode, (XtPointer) SW_SurfCont_Trans15, NULL},
3616 
3617    {  "16", &xmPushButtonWidgetClass,
3618       '\0', NULL, NULL,
3619       SUMA_cb_SetTransMode, (XtPointer) SW_SurfCont_Trans16, NULL},
3620 
3621    {NULL},
3622 };
3623 
3624 SUMA_MenuItem VTransMode_Menu[] = {
3625    {  "Vwr", &xmPushButtonWidgetClass,
3626       '\0', NULL, NULL,
3627       SUMA_cb_SetATransMode, (XtPointer) SW_SurfCont_ATransViewerDefault, NULL},
3628 
3629    {  "A", &xmPushButtonWidgetClass,
3630       'A', NULL, NULL,
3631       SUMA_cb_SetATransMode, (XtPointer) SW_SurfCont_Alpha, NULL},
3632 
3633    {  "0", &xmPushButtonWidgetClass,
3634       '\0', NULL, NULL,
3635       SUMA_cb_SetATransMode, (XtPointer) SW_SurfCont_ATrans0, NULL},
3636 
3637    {  "1", &xmPushButtonWidgetClass,
3638       '\0', NULL, NULL,
3639       SUMA_cb_SetATransMode, (XtPointer) SW_SurfCont_ATrans1, NULL},
3640 
3641    {  "2", &xmPushButtonWidgetClass,
3642       '\0', NULL, NULL,
3643       SUMA_cb_SetATransMode, (XtPointer) SW_SurfCont_ATrans2, NULL},
3644 
3645    {  "3", &xmPushButtonWidgetClass,
3646       '\0', NULL, NULL,
3647       SUMA_cb_SetATransMode, (XtPointer) SW_SurfCont_ATrans3, NULL},
3648 
3649    {  "4", &xmPushButtonWidgetClass,
3650       '\0', NULL, NULL,
3651       SUMA_cb_SetATransMode, (XtPointer) SW_SurfCont_ATrans4, NULL},
3652 
3653    {  "5", &xmPushButtonWidgetClass,
3654       '\0', NULL, NULL,
3655       SUMA_cb_SetATransMode, (XtPointer) SW_SurfCont_ATrans5, NULL},
3656 
3657    {  "6", &xmPushButtonWidgetClass,
3658       '\0', NULL, NULL,
3659       SUMA_cb_SetATransMode, (XtPointer) SW_SurfCont_ATrans6, NULL},
3660 
3661    {  "7", &xmPushButtonWidgetClass,
3662       '\0', NULL, NULL,
3663       SUMA_cb_SetTransMode, (XtPointer) SW_SurfCont_ATrans7, NULL},
3664 
3665    {  "8", &xmPushButtonWidgetClass,
3666       '\0', NULL, NULL,
3667       SUMA_cb_SetATransMode, (XtPointer) SW_SurfCont_ATrans8, NULL},
3668 
3669    {  "9", &xmPushButtonWidgetClass,
3670       '\0', NULL, NULL,
3671       SUMA_cb_SetTransMode, (XtPointer) SW_SurfCont_ATrans9, NULL},
3672 
3673    {  "10", &xmPushButtonWidgetClass,
3674       '\0', NULL, NULL,
3675       SUMA_cb_SetATransMode, (XtPointer) SW_SurfCont_ATrans10, NULL},
3676 
3677    {  "11", &xmPushButtonWidgetClass,
3678       '\0', NULL, NULL,
3679       SUMA_cb_SetATransMode, (XtPointer) SW_SurfCont_ATrans11, NULL},
3680 
3681    {  "12", &xmPushButtonWidgetClass,
3682       '\0', NULL, NULL,
3683       SUMA_cb_SetATransMode, (XtPointer) SW_SurfCont_ATrans12, NULL},
3684 
3685    {  "13", &xmPushButtonWidgetClass,
3686       '\0', NULL, NULL,
3687       SUMA_cb_SetATransMode, (XtPointer) SW_SurfCont_ATrans13, NULL},
3688 
3689    {  "14", &xmPushButtonWidgetClass,
3690       '\0', NULL, NULL,
3691       SUMA_cb_SetTransMode, (XtPointer) SW_SurfCont_ATrans14, NULL},
3692 
3693    {  "15", &xmPushButtonWidgetClass,
3694       '\0', NULL, NULL,
3695       SUMA_cb_SetTransMode, (XtPointer) SW_SurfCont_ATrans15, NULL},
3696 
3697    {  "16", &xmPushButtonWidgetClass,
3698       '\0', NULL, NULL,
3699       SUMA_cb_SetATransMode, (XtPointer) SW_SurfCont_ATrans16, NULL},
3700 
3701    {NULL},
3702 };
3703 
3704 
3705 SUMA_MenuItem DsetViewMode_Menu[] = {
3706    {  "Col", &xmPushButtonWidgetClass,
3707       '\0', NULL, NULL,
3708       SUMA_cb_SetDsetViewMode,
3709       (XtPointer) SW_SurfCont_DsetViewCol, NULL},
3710 
3711    {  "Con", &xmPushButtonWidgetClass,
3712       '\0', NULL, NULL,
3713       SUMA_cb_SetDsetViewMode, (XtPointer) SW_SurfCont_DsetViewCon, NULL},
3714 
3715    {  "C&C", &xmPushButtonWidgetClass,
3716       '\0', NULL, NULL,
3717       SUMA_cb_SetDsetViewMode, (XtPointer) SW_SurfCont_DsetViewCaC, NULL},
3718 
3719    {  "XXX", &xmPushButtonWidgetClass,
3720       '\0', NULL, NULL,
3721       SUMA_cb_SetDsetViewMode, (XtPointer) SW_SurfCont_DsetViewXXX, NULL},
3722 
3723    {NULL},
3724 };
3725 
3726 SUMA_MenuItem DsetFont_Menu[] = {
3727    {  "8", &xmPushButtonWidgetClass,
3728       '8', NULL, NULL,
3729       SUMA_cb_SetDsetFont,
3730       (XtPointer) SW_SurfCont_DsetFont8, NULL},
3731 
3732    {  "9", &xmPushButtonWidgetClass,
3733       '9', NULL, NULL,
3734       SUMA_cb_SetDsetFont, (XtPointer) SW_SurfCont_DsetFont9, NULL},
3735 
3736    {  "T10", &xmPushButtonWidgetClass,
3737       't', NULL, NULL,
3738       SUMA_cb_SetDsetFont, (XtPointer) SW_SurfCont_DsetFontTR10, NULL},
3739 
3740    {  "H10", &xmPushButtonWidgetClass,
3741       '\0', NULL, NULL,
3742       SUMA_cb_SetDsetFont, (XtPointer) SW_SurfCont_DsetFontHE10, NULL},
3743 
3744    {  "H12", &xmPushButtonWidgetClass,
3745       'h', NULL, NULL,
3746       SUMA_cb_SetDsetFont, (XtPointer) SW_SurfCont_DsetFontHE12, NULL},
3747 
3748    {  "H18", &xmPushButtonWidgetClass,
3749       '\0', NULL, NULL,
3750       SUMA_cb_SetDsetFont, (XtPointer) SW_SurfCont_DsetFontHE18, NULL},
3751 
3752    {  "T24", &xmPushButtonWidgetClass,
3753       'T', NULL, NULL,
3754       SUMA_cb_SetDsetFont, (XtPointer) SW_SurfCont_DsetFontTR24, NULL},
3755 
3756    {  "XXX", &xmPushButtonWidgetClass,
3757       'x', NULL, NULL,
3758       SUMA_cb_SetDsetFont, (XtPointer) SW_SurfCont_DsetFontXXX, NULL},
3759 
3760    {NULL},
3761 };
3762 
3763 SUMA_MenuItem DsetNodeCol_Menu[] = {
3764    {  "Wht", &xmPushButtonWidgetClass,
3765       'W', NULL, NULL,
3766       SUMA_cb_SetDsetNodeCol,
3767       (XtPointer) SW_SurfCont_DsetNodeColWhite, NULL},
3768 
3769    {  "Blk", &xmPushButtonWidgetClass,
3770       'B', NULL, NULL,
3771       SUMA_cb_SetDsetNodeCol, (XtPointer) SW_SurfCont_DsetNodeColBlack, NULL},
3772 
3773    {  "Red", &xmPushButtonWidgetClass,
3774       'R', NULL, NULL,
3775       SUMA_cb_SetDsetNodeCol, (XtPointer) SW_SurfCont_DsetNodeColRed, NULL},
3776 
3777    {  "Grn", &xmPushButtonWidgetClass,
3778       'G', NULL, NULL,
3779       SUMA_cb_SetDsetNodeCol, (XtPointer) SW_SurfCont_DsetNodeColGreen, NULL},
3780 
3781    {  "Blu", &xmPushButtonWidgetClass,
3782       'B', NULL, NULL,
3783       SUMA_cb_SetDsetNodeCol, (XtPointer) SW_SurfCont_DsetNodeColBlue, NULL},
3784 
3785    {  "Yel", &xmPushButtonWidgetClass,
3786       'Y', NULL, NULL,
3787       SUMA_cb_SetDsetNodeCol, (XtPointer) SW_SurfCont_DsetNodeColYellow, NULL},
3788 
3789    {  "G50", &xmPushButtonWidgetClass,
3790       '5', NULL, NULL,
3791       SUMA_cb_SetDsetNodeCol, (XtPointer) SW_SurfCont_DsetNodeColGray50, NULL},
3792 
3793    {  "Val", &xmPushButtonWidgetClass,
3794       'V', NULL, NULL,
3795       SUMA_cb_SetDsetNodeCol, (XtPointer) SW_SurfCont_DsetNodeColVal, NULL},
3796 
3797    {  "Grp", &xmPushButtonWidgetClass,
3798       'G', NULL, NULL,
3799       SUMA_cb_SetDsetNodeCol, (XtPointer) SW_SurfCont_DsetNodeColGrp, NULL},
3800 
3801    {NULL},
3802 };
3803 
3804 SUMA_MenuItem DsetTxtShad_Menu[] = {
3805    {  "T", &xmPushButtonWidgetClass,
3806       '1', NULL, NULL,
3807       SUMA_cb_SetDsetTxtShad,
3808       (XtPointer) SW_SurfCont_DsetTxtShad1, NULL},
3809 
3810    {  "Ts", &xmPushButtonWidgetClass,
3811       '2', NULL, NULL,
3812       SUMA_cb_SetDsetTxtShad,
3813       (XtPointer) SW_SurfCont_DsetTxtShad2, NULL},
3814 
3815    {  "B", &xmPushButtonWidgetClass,
3816       '3', NULL, NULL,
3817       SUMA_cb_SetDsetTxtShad, (XtPointer) SW_SurfCont_DsetTxtShad3, NULL},
3818 
3819    {  "Bs", &xmPushButtonWidgetClass,
3820       '4', NULL, NULL,
3821       SUMA_cb_SetDsetTxtShad, (XtPointer) SW_SurfCont_DsetTxtShad4, NULL},
3822 
3823    {  "Ta", &xmPushButtonWidgetClass,
3824       '5', NULL, NULL,
3825       SUMA_cb_SetDsetTxtShad, (XtPointer) SW_SurfCont_DsetTxtShad5, NULL},
3826 
3827    {  "Ba", &xmPushButtonWidgetClass,
3828       '6', NULL, NULL,
3829       SUMA_cb_SetDsetTxtShad, (XtPointer) SW_SurfCont_DsetTxtShad6, NULL},
3830 
3831    {NULL},
3832 };
3833 
3834 SUMA_MenuItem DsetGmatBord_Menu[] = {
3835    {  "XX", &xmPushButtonWidgetClass,
3836       'X', NULL, NULL,
3837       SUMA_cb_SetDsetGmatBord,
3838       (XtPointer) SW_SurfCont_DsetGmatBord0, NULL},
3839 
3840    {  "5", &xmPushButtonWidgetClass,
3841       '5', NULL, NULL,
3842       SUMA_cb_SetDsetGmatBord, (XtPointer) SW_SurfCont_DsetGmatBord5, NULL},
3843 
3844    {  "10", &xmPushButtonWidgetClass,
3845       '1', NULL, NULL,
3846       SUMA_cb_SetDsetGmatBord, (XtPointer) SW_SurfCont_DsetGmatBord10, NULL},
3847 
3848    {  "20", &xmPushButtonWidgetClass,
3849       '2', NULL, NULL,
3850       SUMA_cb_SetDsetGmatBord, (XtPointer) SW_SurfCont_DsetGmatBord20, NULL},
3851 
3852    {  "40", &xmPushButtonWidgetClass,
3853       'B', NULL, NULL,
3854       SUMA_cb_SetDsetGmatBord, (XtPointer) SW_SurfCont_DsetGmatBord40, NULL},
3855 
3856    {NULL},
3857 };
3858 
3859 SUMA_MenuItem DsetNodeRad_Menu[] = {
3860    { "Cst", &xmPushButtonWidgetClass,
3861       'C', NULL, NULL,
3862       SUMA_cb_SetDsetNodeRad, (XtPointer) SW_SurfCont_DsetNodeRadConst, NULL},
3863    {  "Val", &xmPushButtonWidgetClass,
3864       'V', NULL, NULL,
3865       SUMA_cb_SetDsetNodeRad, (XtPointer) SW_SurfCont_DsetNodeRadVal, NULL},
3866    { "XXX", &xmPushButtonWidgetClass,
3867       'X', NULL, NULL,
3868       SUMA_cb_SetDsetNodeRad, (XtPointer) SW_SurfCont_DsetNodeRadXXX, NULL},
3869    {NULL},
3870 };
3871 
3872 SUMA_MenuItem DsetThrough_Menu[] = {
3873    { "Edg", &xmPushButtonWidgetClass,
3874       'E', NULL, NULL,
3875       SUMA_cb_SetDsetThrough, (XtPointer) SW_SurfCont_DsetThroughEdge, NULL},
3876    {  "Col", &xmPushButtonWidgetClass,
3877       'C', NULL, NULL,
3878       SUMA_cb_SetDsetThrough, (XtPointer) SW_SurfCont_DsetThroughCol, NULL},
3879    { "Rad", &xmPushButtonWidgetClass,
3880       'R', NULL, NULL,
3881       SUMA_cb_SetDsetThrough, (XtPointer) SW_SurfCont_DsetThroughRad, NULL},
3882    { "C&R", &xmPushButtonWidgetClass,
3883       'B', NULL, NULL,
3884       SUMA_cb_SetDsetThrough, (XtPointer) SW_SurfCont_DsetThroughCaR, NULL},
3885    { "XXX", &xmPushButtonWidgetClass,
3886       'X', NULL, NULL,
3887       SUMA_cb_SetDsetThrough, (XtPointer) SW_SurfCont_DsetThroughXXX, NULL},
3888 
3889    {NULL},
3890 };
3891 
3892 SUMA_MenuItem DsetEdgeThick_Menu[] = {
3893    { "Cst", &xmPushButtonWidgetClass,
3894       'C', NULL, NULL,
3895       SUMA_cb_SetDsetEdgeThick, (XtPointer)SW_SurfCont_DsetEdgeThickConst, NULL},
3896    {  "Val", &xmPushButtonWidgetClass,
3897       'V', NULL, NULL,
3898       SUMA_cb_SetDsetEdgeThick, (XtPointer) SW_SurfCont_DsetEdgeThickVal, NULL},
3899    {NULL},
3900 };
3901 
3902 SUMA_MenuItem DsetEdgeStip_Menu[] = {
3903    { "XXX", &xmPushButtonWidgetClass,
3904       'X', NULL, NULL,
3905       SUMA_cb_SetDsetEdgeStip, (XtPointer) SW_SurfCont_DsetEdgeStipXXX, NULL},
3906    {  "Val", &xmPushButtonWidgetClass,
3907       'V', NULL, NULL,
3908       SUMA_cb_SetDsetEdgeStip, (XtPointer) SW_SurfCont_DsetEdgeStipVal, NULL},
3909    { "s01", &xmPushButtonWidgetClass,
3910       '1', NULL, NULL,
3911       SUMA_cb_SetDsetEdgeStip, (XtPointer) SW_SurfCont_DsetEdgeStip1, NULL},
3912    { "s02", &xmPushButtonWidgetClass,
3913       '2', NULL, NULL,
3914       SUMA_cb_SetDsetEdgeStip, (XtPointer) SW_SurfCont_DsetEdgeStip2, NULL},
3915    { "s03", &xmPushButtonWidgetClass,
3916       '3', NULL, NULL,
3917       SUMA_cb_SetDsetEdgeStip, (XtPointer) SW_SurfCont_DsetEdgeStip3, NULL},
3918    { "s04", &xmPushButtonWidgetClass,
3919       '4', NULL, NULL,
3920       SUMA_cb_SetDsetEdgeStip, (XtPointer) SW_SurfCont_DsetEdgeStip4, NULL},
3921    { "s05", &xmPushButtonWidgetClass,
3922       '5', NULL, NULL,
3923       SUMA_cb_SetDsetEdgeStip, (XtPointer) SW_SurfCont_DsetEdgeStip5, NULL},
3924    { "s06", &xmPushButtonWidgetClass,
3925       '6', NULL, NULL,
3926       SUMA_cb_SetDsetEdgeStip, (XtPointer) SW_SurfCont_DsetEdgeStip6, NULL},
3927    { "s07", &xmPushButtonWidgetClass,
3928       '7', NULL, NULL,
3929       SUMA_cb_SetDsetEdgeStip, (XtPointer) SW_SurfCont_DsetEdgeStip7, NULL},
3930    { "s08", &xmPushButtonWidgetClass,
3931       '8', NULL, NULL,
3932       SUMA_cb_SetDsetEdgeStip, (XtPointer) SW_SurfCont_DsetEdgeStip8, NULL},
3933    { "s09", &xmPushButtonWidgetClass,
3934       '9', NULL, NULL,
3935       SUMA_cb_SetDsetEdgeStip, (XtPointer) SW_SurfCont_DsetEdgeStip9, NULL},
3936    { "s10", &xmPushButtonWidgetClass,
3937       '\0', NULL, NULL,
3938       SUMA_cb_SetDsetEdgeStip, (XtPointer) SW_SurfCont_DsetEdgeStip10, NULL},
3939    { "s11", &xmPushButtonWidgetClass,
3940       '\0', NULL, NULL,
3941       SUMA_cb_SetDsetEdgeStip, (XtPointer) SW_SurfCont_DsetEdgeStip11, NULL},
3942    { "s12", &xmPushButtonWidgetClass,
3943       '\0', NULL, NULL,
3944       SUMA_cb_SetDsetEdgeStip, (XtPointer) SW_SurfCont_DsetEdgeStip12, NULL},
3945    { "s13", &xmPushButtonWidgetClass,
3946       '\0', NULL, NULL,
3947       SUMA_cb_SetDsetEdgeStip, (XtPointer) SW_SurfCont_DsetEdgeStip13, NULL},
3948    { "s14", &xmPushButtonWidgetClass,
3949       '\0', NULL, NULL,
3950       SUMA_cb_SetDsetEdgeStip, (XtPointer) SW_SurfCont_DsetEdgeStip14, NULL},
3951    { "s15", &xmPushButtonWidgetClass,
3952       '\0', NULL, NULL,
3953       SUMA_cb_SetDsetEdgeStip, (XtPointer) SW_SurfCont_DsetEdgeStip15, NULL},
3954    {NULL},
3955 };
3956 
3957 SUMA_MenuItem TractStyle_Menu[] = {
3958    { "SLD", &xmPushButtonWidgetClass,
3959       'X', NULL, NULL,
3960       SUMA_cb_SetTractStyle, (XtPointer) SW_SurfCont_TractStyleSOLID, NULL},
3961    {  "HDE", &xmPushButtonWidgetClass,
3962       'V', NULL, NULL,
3963       SUMA_cb_SetTractStyle, (XtPointer) SW_SurfCont_TractStyleHIDE, NULL},
3964    { "s01", &xmPushButtonWidgetClass,
3965       '1', NULL, NULL,
3966       SUMA_cb_SetTractStyle, (XtPointer) SW_SurfCont_TractStyleST1, NULL},
3967    { "s02", &xmPushButtonWidgetClass,
3968       '2', NULL, NULL,
3969       SUMA_cb_SetTractStyle, (XtPointer) SW_SurfCont_TractStyleST2, NULL},
3970    { "s03", &xmPushButtonWidgetClass,
3971       '3', NULL, NULL,
3972       SUMA_cb_SetTractStyle, (XtPointer) SW_SurfCont_TractStyleST3, NULL},
3973    { "s04", &xmPushButtonWidgetClass,
3974       '4', NULL, NULL,
3975       SUMA_cb_SetTractStyle, (XtPointer) SW_SurfCont_TractStyleST4, NULL},
3976    { "s05", &xmPushButtonWidgetClass,
3977       '5', NULL, NULL,
3978       SUMA_cb_SetTractStyle, (XtPointer) SW_SurfCont_TractStyleST5, NULL},
3979    { "s06", &xmPushButtonWidgetClass,
3980       '6', NULL, NULL,
3981       SUMA_cb_SetTractStyle, (XtPointer) SW_SurfCont_TractStyleST6, NULL},
3982    { "s07", &xmPushButtonWidgetClass,
3983       '7', NULL, NULL,
3984       SUMA_cb_SetTractStyle, (XtPointer) SW_SurfCont_TractStyleST7, NULL},
3985    { "s08", &xmPushButtonWidgetClass,
3986       '8', NULL, NULL,
3987       SUMA_cb_SetTractStyle, (XtPointer) SW_SurfCont_TractStyleST8, NULL},
3988    { "s09", &xmPushButtonWidgetClass,
3989       '9', NULL, NULL,
3990       SUMA_cb_SetTractStyle, (XtPointer) SW_SurfCont_TractStyleST9, NULL},
3991    { "s10", &xmPushButtonWidgetClass,
3992       '\0', NULL, NULL,
3993       SUMA_cb_SetTractStyle, (XtPointer) SW_SurfCont_TractStyleST10, NULL},
3994    { "s11", &xmPushButtonWidgetClass,
3995       '\0', NULL, NULL,
3996       SUMA_cb_SetTractStyle, (XtPointer) SW_SurfCont_TractStyleST11, NULL},
3997    { "s12", &xmPushButtonWidgetClass,
3998       '\0', NULL, NULL,
3999       SUMA_cb_SetTractStyle, (XtPointer) SW_SurfCont_TractStyleST12, NULL},
4000    { "s13", &xmPushButtonWidgetClass,
4001       '\0', NULL, NULL,
4002       SUMA_cb_SetTractStyle, (XtPointer) SW_SurfCont_TractStyleST13, NULL},
4003    { "s14", &xmPushButtonWidgetClass,
4004       '\0', NULL, NULL,
4005       SUMA_cb_SetTractStyle, (XtPointer) SW_SurfCont_TractStyleST14, NULL},
4006    { "s15", &xmPushButtonWidgetClass,
4007       '\0', NULL, NULL,
4008       SUMA_cb_SetTractStyle, (XtPointer) SW_SurfCont_TractStyleST15, NULL},
4009    {NULL},
4010 };
4011 
4012 SUMA_MenuItem DsetAlphaVal_Menu[] = {
4013    { "Max", &xmPushButtonWidgetClass,
4014       'M', NULL, NULL,
4015       SUMA_cb_SetDsetAlphaVal, (XtPointer) SW_SurfCont_DsetAlphaVal_Max, NULL},
4016    {  "Avg", &xmPushButtonWidgetClass,
4017       'A', NULL, NULL,
4018       SUMA_cb_SetDsetAlphaVal, (XtPointer) SW_SurfCont_DsetAlphaVal_Avg, NULL},
4019    { "Min", &xmPushButtonWidgetClass,
4020       'm', NULL, NULL,
4021       SUMA_cb_SetDsetAlphaVal, (XtPointer) SW_SurfCont_DsetAlphaVal_Min, NULL},
4022    { "I", &xmPushButtonWidgetClass,
4023       'I', NULL, NULL,
4024       SUMA_cb_SetDsetAlphaVal, (XtPointer) SW_SurfCont_DsetAlphaVal_I, NULL},
4025    { "T", &xmPushButtonWidgetClass,
4026       'T', NULL, NULL,
4027       SUMA_cb_SetDsetAlphaVal, (XtPointer) SW_SurfCont_DsetAlphaVal_T, NULL},
4028    { "B", &xmPushButtonWidgetClass,
4029       'B', NULL, NULL,
4030       SUMA_cb_SetDsetAlphaVal, (XtPointer) SW_SurfCont_DsetAlphaVal_B, NULL},
4031    { "XXX", &xmPushButtonWidgetClass,
4032       'X', NULL, NULL,
4033       SUMA_cb_SetDsetAlphaVal, (XtPointer) SW_SurfCont_DsetAlphaVal_XXX, NULL},
4034    {NULL},
4035 };
4036 
4037 SUMA_MenuItem TractMask_Menu[] = {
4038    {  "Hde", &xmPushButtonWidgetClass,
4039       'H', NULL, NULL,
4040       SUMA_cb_SetTractMask, (XtPointer)SW_SurfCont_TractMaskHide, NULL},
4041    {  "Gry", &xmPushButtonWidgetClass,
4042       'G', NULL, NULL,
4043       SUMA_cb_SetTractMask, (XtPointer) SW_SurfCont_TractMaskGray, NULL},
4044    {  "Dim", &xmPushButtonWidgetClass,
4045       'D', NULL, NULL,
4046       SUMA_cb_SetTractMask, (XtPointer) SW_SurfCont_TractMaskDim, NULL},
4047    {  "One", &xmPushButtonWidgetClass,
4048       'O', NULL, NULL,
4049       SUMA_cb_SetTractMask, (XtPointer) SW_SurfCont_TractMaskHair, NULL},
4050    {  "Ign", &xmPushButtonWidgetClass,
4051       'I', NULL, NULL,
4052       SUMA_cb_SetTractMask, (XtPointer) SW_SurfCont_TractMaskIgnore, NULL},
4053   {NULL},
4054 };
4055 
4056 
4057 SUMA_MenuItem DrawROI_SaveMode_Menu[]= {
4058    {  "NIML", &xmPushButtonWidgetClass,
4059       '\0', NULL, NULL,
4060       SUMA_cb_SetDrawROI_SaveMode, (XtPointer) SW_DrawROI_SaveModeNIML, NULL},
4061 
4062    {  "1D", &xmPushButtonWidgetClass,
4063       '\0', NULL, NULL,
4064       SUMA_cb_SetDrawROI_SaveMode, (XtPointer) SW_DrawROI_SaveMode1D, NULL},
4065 
4066    {NULL},
4067 };
4068 
4069 SUMA_MenuItem DrawROI_SaveWhat_Menu[]= {
4070    {  "All", &xmPushButtonWidgetClass,
4071       '\0', NULL, NULL,
4072       SUMA_cb_SetDrawROI_SaveWhat, (XtPointer) SW_DrawROI_SaveWhatRelated, NULL},
4073 
4074    {  "This", &xmPushButtonWidgetClass,
4075       '\0', NULL, NULL,
4076       SUMA_cb_SetDrawROI_SaveWhat, (XtPointer) SW_DrawROI_SaveWhatThis, NULL},
4077 
4078    {NULL},
4079 };
4080 
4081 SUMA_MenuItem DrawROI_WhatDist_Menu[]= {
4082    {  "----", &xmPushButtonWidgetClass,
4083       '\0', NULL, NULL,
4084       SUMA_cb_SetDrawROI_WhatDist, (XtPointer) SW_DrawROI_WhatDistNothing, NULL},
4085 
4086    {  "trace", &xmPushButtonWidgetClass,
4087       '\0', NULL, NULL,
4088       SUMA_cb_SetDrawROI_WhatDist, (XtPointer) SW_DrawROI_WhatDistTrace, NULL},
4089 
4090    {  "all", &xmPushButtonWidgetClass,
4091       '\0', NULL, NULL,
4092       SUMA_cb_SetDrawROI_WhatDist, (XtPointer) SW_DrawROI_WhatDistAll, NULL},
4093 
4094    {NULL},
4095 };
4096 
4097 /* capture warnings from X and save them in Log
4098 Had to add it to deal with the stupid
4099    Illegal mnemonic character;  Could not convert X KEYSYM to a keycode
4100 that seem to have no effect...
4101 */
SUMA_XtWarn_handler(char * msg)4102 void SUMA_XtWarn_handler(char *msg){
4103    static char FuncName[]={"SUMA_XtWarn_handler"};
4104    static long unsigned int warn_count=0;
4105    static int wrnstep=10;
4106    char *wrn=NULL;
4107    static char ibuf[256]={""};
4108    sprintf(ibuf,"  X11 Warning %ld:", warn_count+1);
4109    wrn = SUMA_append_string(ibuf,msg);
4110    if (! ((warn_count) % wrnstep) ) {
4111       SUMA_S_Notev("%s\n"
4112                    "  Have %ld X11 warnings so far, "
4113                    "see Help-->Message Log if curious.\n"
4114                    "  This notice is shown once for each additional "
4115                    "%d warnings.\n"
4116                    "\n",
4117                    wrn, warn_count+1, wrnstep);
4118    }
4119    SUMA_L_Warn("%s",wrn);
4120    SUMA_free(wrn); wrn = NULL;
4121    ++warn_count;
4122    return ;
4123 }
4124 
4125 /* deal with fatal errors. Not used yet. */
SUMA_XtErr_handler(Display * d,XErrorEvent * x)4126 int SUMA_XtErr_handler( Display *d , XErrorEvent *x ){
4127     static char FuncName[]={"SUMA_XtErr_handler"};
4128     char buf[256] = "(null)" ;
4129 
4130     if( x != NULL && d != NULL ) {
4131       XGetErrorText( d,x->error_code , buf,255 ) ;
4132     }
4133     SUMA_S_Errv( "Intercepted fatal X11 error: %s\n",buf) ;
4134 
4135    if( x != NULL) return (x->error_code);
4136    else return (-1);
4137 }
4138 
4139 
4140 /* Report error but don't die */
SUMA_XErrHandler(Display * d,XErrorEvent * x)4141 int SUMA_XErrHandler( Display *d , XErrorEvent *x )
4142 {
4143    static char FuncName[]={"SUMA_XErrHandler"};
4144    char buf[256] = "(null)" ;
4145 
4146    SUMA_ENTRY;
4147 
4148    if( x != NULL && d != NULL ) XGetErrorText( d,x->error_code , buf,255 ) ;
4149    SUMA_S_Warn( "Intercepted X11 error: %s\n"
4150                 "Will attempt to proceed but trouble might ensue.",buf) ;
4151    SUMA_DUMP_TRACE("Trace At Xerr");
4152 
4153    SUMA_RETURN(0) ;
4154 }
4155 
4156 
SUMA_X_SurfaceViewer_Create(void)4157 SUMA_Boolean SUMA_X_SurfaceViewer_Create (void)
4158 {
4159    static char FuncName[]={"SUMA_X_SurfaceViewer_Create"};
4160    static int CallNum = 0;
4161    int ic = 0, icr=0;
4162    char *vargv[1]={ "[A] SUMA" };
4163    int cargc = 1, repos[5]={0,0,0,0,0};
4164    SUMA_Boolean NewCreation = NOPE, Found=NOPE, Inherit = NOPE;
4165    char slabel[20]="\0", *eee=NULL;
4166    SUMA_Boolean LocalHead = NOPE;
4167 
4168    SUMA_ENTRY;
4169    /* Step 1. */
4170    if (CallNum == 0) { /* first call, initialize App */
4171       SUMA_LH("Entered 1st viewer creation");
4172       SUMAg_CF->N_OpenSV = 0;
4173       /*
4174          SUMAg_SVv[ic].X->TOPLEVEL = XtAppInitialize(&SUMAg_CF->X->App, "SUMA",
4175                                                       NULL, 0, &cargc, vargv,
4176        SUMA_get_fallbackResources(), NULL, 0); Superseded by XtOpenApplication
4177       */
4178       SUMAg_SVv[ic].X->TOPLEVEL =
4179          XtOpenApplication(&(SUMAg_CF->X->App), "SUMA",
4180                            NULL, 0, &cargc, vargv,
4181                            SUMA_get_fallbackResources(),
4182                            topLevelShellWidgetClass, NULL, 0);
4183       SUMAg_SVv[ic].X->DPY = XtDisplay(SUMAg_SVv[ic].X->TOPLEVEL);
4184 
4185       if (!ic && (eee=SUMA_EnvVal("SUMA_Position_Original"))
4186               && strcmp(eee, "TopLeft")) {
4187          int nv=0;
4188          double dv[6];
4189          if (SUMA_EnvEquals("SUMA_Position_Original", "RightOffset",1,NULL)){
4190             repos[0]=2; repos[1]=437; repos[2]=44;
4191          } else if ((nv = SUMA_StringToNum(eee,
4192                                      (void *)dv, 4, 2))==2 || nv == 4) {
4193             if (nv == 2) {
4194                repos[0]=2; repos[1]=(int)dv[0]; repos[2]=(int)dv[1];
4195             } else if (nv == 4) {
4196                repos[0]=4; repos[1]=(int)dv[0]; repos[2]=(int)dv[1];
4197                            repos[3]=(int)dv[2]; repos[4]=(int)dv[3];
4198             }
4199          } else {
4200             SUMA_S_Warnv(
4201                "Ignored ill formatted env 'SUMA_Position_Original=%s'\n",
4202                   eee);
4203          }
4204          if (repos[1] < 0) repos[1] = 0;
4205          if (repos[2] < 0) repos[2] = 0;
4206       }
4207       /* catch some warnings that are not important */
4208       XtAppSetWarningHandler(SUMAg_CF->X->App,SUMA_XtWarn_handler) ;
4209 
4210       /* save DPY for first controller opened */
4211       SUMAg_CF->X->DPY_controller1 = SUMAg_SVv[ic].X->DPY;
4212       NewCreation = YUP;
4213       Inherit = NOPE;
4214 
4215       (void)XSetErrorHandler(SUMA_XErrHandler);
4216 
4217    } else {/* not the first call, new controller is required */
4218       SUMA_LH("Entered subsequent viewers creation");
4219       ic = 0;
4220       Found = NOPE;
4221       while (ic < SUMA_MAX_SURF_VIEWERS && !Found) {
4222          if (!SUMAg_SVv[ic].Open) {
4223             Found = YUP;
4224          } else {
4225             ++ic;
4226          }
4227       }
4228       if (!Found) { /* no unopen windows left to open */
4229          fprintf (SUMA_STDERR,
4230                   "Error %s: Cannot open more than %d viewers.\n",
4231                   FuncName, SUMA_MAX_SURF_VIEWERS);
4232          SUMA_RETURN (NOPE);
4233       }
4234 
4235       /* an unopen window was found, check its top level widget */
4236       if (SUMAg_SVv[ic].X->TOPLEVEL == NULL) {
4237          /* Unopen window found, needs a shell */
4238          SUMAg_SVv[ic].X->DPY = SUMAg_CF->X->DPY_controller1;
4239          SUMAg_SVv[ic].X->TOPLEVEL = XtVaAppCreateShell("SUMA" , "Suma" ,
4240                    topLevelShellWidgetClass , SUMAg_SVv[ic].X->DPY ,
4241                    XmNinitialResourcesPersistent , False ,
4242                    NULL ) ;
4243          NewCreation = YUP;
4244          Inherit = YUP;
4245       } else { /* Unopen window found, has a shell already. */
4246          NewCreation = NOPE;
4247       }
4248    }
4249 
4250    if (NewCreation) { /* create widgets, add call backs etc ,,, */
4251       SUMA_LH("New creation, Inherit=%d", Inherit);
4252       /* Step 2. */
4253       XtAddEventHandler(SUMAg_SVv[ic].X->TOPLEVEL, StructureNotifyMask,
4254        False, SUMA_mapStateChanged, NULL);
4255       XtAddEventHandler(SUMAg_SVv[ic].X->TOPLEVEL, EnterWindowMask,
4256        False, SUMA_SetcSV, NULL);
4257       XtAddEventHandler(SUMAg_SVv[ic].X->TOPLEVEL, LeaveWindowMask,
4258        False, SUMA_unSetcSV, NULL);
4259 
4260       /* Step 3 */
4261       if (!Inherit) {
4262          if (LocalHead)
4263             fprintf(stdout, "trying for cool double buffer visual\n");
4264          SUMAg_SVv[ic].X->VISINFO =
4265             glXChooseVisual(  SUMAg_SVv[ic].X->DPY,
4266                               DefaultScreen(SUMAg_SVv[ic].X->DPY), dblBuf);
4267          if (SUMAg_SVv[ic].X->VISINFO == NULL) {
4268             fprintf(stdout, "trying lame single buffer visual\n");
4269             XtAppWarning(SUMAg_CF->X->App, "trying lame single buffer visual");
4270             SUMAg_SVv[ic].X->VISINFO =
4271                glXChooseVisual(  SUMAg_SVv[ic].X->DPY,
4272                                  DefaultScreen(SUMAg_SVv[ic].X->DPY), snglBuf);
4273           if (SUMAg_SVv[ic].X->VISINFO == NULL) {
4274             XtAppError(SUMAg_CF->X->App, "no good visual");
4275             SUMA_RETURN (NOPE);
4276           }
4277           SUMAg_SVv[ic].X->DOUBLEBUFFER = False;
4278          }
4279       } else {
4280          SUMA_LH("This is new. Inheriting");
4281          SUMAg_SVv[ic].X->VISINFO = SUMAg_SVv[0].X->VISINFO;
4282          SUMAg_SVv[ic].X->DOUBLEBUFFER = SUMAg_SVv[0].X->DOUBLEBUFFER;
4283       }
4284 
4285       #ifdef USING_LESSTIF
4286          SUMA_LH("Using LessTif Libraries.");
4287       #else
4288          SUMA_LH("Using Open Motif libraries");
4289       #endif
4290 
4291       /* Step 3.5 Wed Dec 18 14:49:25 EST 2002 - The GUI*/
4292          /* see Kilgard's OpenGL Programming for the X window system */
4293          /* create main window */
4294          SUMA_LH("Creating Main Window");
4295            /* Next call Causes Seg. fault on Fedora Core 4.
4296          Not much I can do. Same happens with demo code paperplane.c
4297          by Kilgard */
4298          Gmainw = XmCreateMainWindow (  SUMAg_SVv[ic].X->TOPLEVEL,
4299                                        "mainw", NULL, 0);
4300          SUMA_LH("Managing Main Window");
4301          XtManageChild (Gmainw);
4302          /* create menu bar */
4303          Gmenubar = XmCreateMenuBar (Gmainw, "menubar", NULL, 0);
4304          XtManageChild (Gmenubar);
4305 
4306          /* create File Menu */
4307          SUMA_BuildMenuReset(0);
4308          SUMA_BuildMenu(Gmenubar, XmMENU_PULLDOWN,
4309                                  "File", 'F', YUP, File_menu,
4310                                  (VOID_CAST)ic, NULL, NULL, NULL,
4311                                  SUMAg_SVv[ic].X->FileMenu );
4312 
4313          /* create View Menu */
4314          SUMA_BuildMenuReset(0);
4315          SUMA_BuildMenu(Gmenubar, XmMENU_PULLDOWN,
4316                                  "View", 'V', YUP, View_menu,
4317                                  (VOID_CAST)ic, NULL, NULL, NULL,
4318                                  SUMAg_SVv[ic].X->ViewMenu );
4319 
4320          /* create Tools Menu */
4321          SUMA_BuildMenuReset(0);
4322          SUMA_BuildMenu(Gmenubar, XmMENU_PULLDOWN,
4323                                  "Tools", 'T', YUP, Tools_menu,
4324                                  (VOID_CAST)ic, NULL, NULL, NULL,
4325                                  SUMAg_SVv[ic].X->ToolsMenu );
4326 
4327          /* create Help Menu */
4328          SUMA_BuildMenuReset(0);
4329          SUMA_BuildMenu(Gmenubar, XmMENU_PULLDOWN,
4330                                  "Help", 'H', YUP, Help_menu,
4331                                  (VOID_CAST)ic, NULL, NULL, NULL,
4332                                  SUMAg_SVv[ic].X->HelpMenu );
4333 
4334          XtVaSetValues (Gmenubar, XmNmenuHelpWidget,
4335                         SUMAg_SVv[ic].X->HelpMenu->mw[SW_Help], NULL);
4336 
4337          /* set states of the some view menu widgets */
4338          XmToggleButtonSetState (
4339             SUMAg_SVv[ic].X->ViewMenu->mw[SW_ViewCrossHair],
4340             SUMAg_SVv[ic].ShowCrossHair, NOPE);
4341          XmToggleButtonSetState (
4342             SUMAg_SVv[ic].X->ViewMenu->mw[SW_ViewSelectedFaceset],
4343             SUMAg_SVv[ic].ShowSelectedFaceSet, NOPE);
4344          XmToggleButtonSetState (
4345             SUMAg_SVv[ic].X->ViewMenu->mw[SW_ViewNodeInFocus],
4346             SUMAg_SVv[ic].ShowSelectedDatum, NOPE);
4347 
4348          XmToggleButtonSetState (
4349             SUMAg_SVv[ic].X->HelpMenu->mw[SW_HelpMemTrace],
4350             SUMAg_CF->MemTrace, NOPE);
4351          if (SUMAg_CF->MemTrace) {
4352             XtSetSensitive(SUMAg_SVv[ic].X->HelpMenu->mw[SW_HelpMemTrace], 0); }
4353 
4354          XmToggleButtonSetState (SUMAg_SVv[ic].X->HelpMenu->mw[SW_HelpIONotify],
4355             SUMAg_CF->InOut_Notify, NOPE);
4356          XmToggleButtonSetState (
4357             SUMAg_SVv[ic].X->HelpMenu->mw[SW_HelpEchoKeyPress],
4358             SUMAg_CF->Echo_KeyPress, NOPE);
4359 
4360 
4361         SUMAg_SVv[ic].X->CMAP = SUMA_getShareableColormap(&(SUMAg_SVv[ic]));
4362 
4363         /* create a frame to put glxarea in */
4364         SUMAg_SVv[ic].X->FRAME = XmCreateFrame (Gmainw, "frame", NULL, 0);
4365         XtManageChild(SUMAg_SVv[ic].X->FRAME);
4366 
4367       #ifdef SUMA_MOTIF_GLXAREA
4368         SUMA_LH("MOTIF Drawing Area");
4369         /* Step 6. */
4370          /* glwMDrawingAreaWidgetClass requires libMesaGLwM.a */
4371 
4372         if( glwMDrawingAreaWidgetClass == NULL ) {
4373             fprintf(stderr,"** ERROR: glwMDrawingAreaWidgetClass is NULL\n"
4374             "   This might be an error in GLwDrawA.h where the class is\n"
4375             "   not referenced using 'extern'.  An alternative is to use\n"
4376             "   the local build of libGLws.a.\n");
4377             exit(1);
4378         }
4379 
4380         SUMAg_SVv[ic].X->GLXAREA = XtVaCreateManagedWidget("glxarea",
4381           glwMDrawingAreaWidgetClass, SUMAg_SVv[ic].X->FRAME,
4382           GLwNvisualInfo, SUMAg_SVv[ic].X->VISINFO,
4383           XtNcolormap, SUMAg_SVv[ic].X->CMAP,
4384           NULL);
4385       #else
4386         SUMA_LH("GL Drawing Area");
4387 
4388         /* glwDrawingAreaWidgetClass requires libMesaGLw.a */
4389 
4390         /* -------------------------------------------------------------------
4391          * check for NULL glwDrawingAreaWidgetClass        23 May 2017 [rickr]
4392          *
4393          * If glwDrawingAreaWidgetClass was declared without extern, we might
4394          * be seeing a local version of it (with a NULL value), rather than a
4395          * reference to the existing library verison (if the library is loaded
4396          * dynamically, the variable might not be seen at compile time).
4397          *
4398          * see https://www.cygwin.com/ml/cygwin-xfree/2014-10/msg00040.html
4399          * ------------------------------------------------------------------ */
4400         if( glwDrawingAreaWidgetClass == NULL ) {
4401             fprintf(stderr,"** ERROR: glwDrawingAreaWidgetClass is NULL\n"
4402             "   This might be an error in GLwDrawA.h where the class is\n"
4403             "   not referenced using 'extern'.  An alternative is to use\n"
4404             "   the local build of libGLws.a.\n");
4405             exit(1);
4406         }
4407 
4408         SUMAg_SVv[ic].X->GLXAREA = XtVaCreateManagedWidget("glxarea",
4409           glwDrawingAreaWidgetClass, SUMAg_SVv[ic].X->FRAME,
4410           GLwNvisualInfo, SUMAg_SVv[ic].X->VISINFO,
4411           XtNcolormap, SUMAg_SVv[ic].X->CMAP,
4412           NULL);
4413       #endif
4414 
4415 
4416       /* Step 7. */
4417       SUMA_LH("Callbacks");
4418       XtAddCallback( SUMAg_SVv[ic].X->GLXAREA, GLwNginitCallback,
4419                      SUMA_graphicsInit, NULL);
4420       XtAddCallback( SUMAg_SVv[ic].X->GLXAREA, GLwNexposeCallback,
4421                      SUMA_expose, NULL);
4422       XtAddCallback( SUMAg_SVv[ic].X->GLXAREA, GLwNresizeCallback,
4423                      SUMA_resize, NULL);
4424       XtAddCallback( SUMAg_SVv[ic].X->GLXAREA, GLwNinputCallback,
4425                      SUMA_input, NULL);
4426 
4427       /* trap for window kill */
4428 
4429       /* turn off default delete response. If you do not do that,
4430          you will suffer.*/
4431        XtVaSetValues( SUMAg_SVv[ic].X->TOPLEVEL,
4432            XmNdeleteResponse, XmDO_NOTHING,
4433            NULL);
4434 
4435       XmAddWMProtocolCallback(           /* make "Close" window menu work */
4436            SUMAg_SVv[ic].X->TOPLEVEL,
4437            XmInternAtom( SUMAg_SVv[ic].X->DPY , "WM_DELETE_WINDOW" , False ) ,
4438            SUMA_ButtClose_pushed , NULL ) ;
4439 
4440       /* Step 8. */
4441       XtRealizeWidget(SUMAg_SVv[ic].X->TOPLEVEL);
4442 
4443       /* I will need a Graphics Context variable to draw into the window */
4444       SUMA_LH("Getting a grahics context");
4445       if (0){ /* This has caused me lots of grief with XQuartz, on 10.8 systems
4446                  and possibly before. If this block is executed, I get undefined
4447                  buffer errors (right before glClear) and failures to set
4448                  the current graphic context with glXCreateContext().
4449                  The problems are intermittent however and at times tricky to
4450                  reproduce and they only occur whenver a new controller
4451                  is opened with 'ctrl+n' the first time. You have better odds
4452                  of causing the problem if you resize the very first window
4453                  right before opening the new controller.
4454                  In any case, this block is not needed at all anymore since
4455                  X->gc is no longer used anywhere. */
4456          XGCValues gcv; /* see program drawing.c in Motif Programming Manual,
4457                            Ch. 10 */
4458          gcv.foreground =
4459             BlackPixelOfScreen (XtScreen (SUMAg_SVv[ic].X->GLXAREA));
4460          SUMAg_SVv[ic].X->gc = XCreateGC (SUMAg_SVv[ic].X->DPY,
4461                                           XtWindow (SUMAg_SVv[ic].X->GLXAREA),
4462                                           GCForeground, &gcv);
4463          SUMA_SetSVForegroundColor (&SUMAg_SVv[ic], "Green");
4464       }
4465 
4466 
4467       /* keep track of count */
4468       SUMAg_N_SVv += 1;
4469       SUMA_LH("Repos");
4470       /* initial repositioning, just for 1st creation */
4471       if (1) {
4472       switch (repos[0]) {
4473          case 4:
4474             XtVaSetValues (SUMAg_SVv[ic].X->TOPLEVEL,
4475                XmNx, (Position)(repos[1]),
4476                XmNy, (Position)(repos[2]),
4477                XmNwidth, (repos[3]),
4478                XmNheight, (repos[4]),
4479                NULL);
4480             break;
4481          case 2:
4482             XtVaSetValues (SUMAg_SVv[ic].X->TOPLEVEL,
4483                XmNx, (Position)(repos[1]),
4484                XmNy, (Position)(repos[2]),
4485                NULL);
4486             break;
4487          default:
4488             break;
4489       }
4490       }
4491 
4492       /* position window next to the previous one open */
4493       if (1) {
4494          Found = NOPE;
4495          icr = SUMA_MAX_SURF_VIEWERS - 1;
4496          while (icr >= 0 && !Found) {
4497             if (icr != ic && SUMAg_SVv[icr].Open) {
4498                Found = YUP;
4499             } else {
4500                --icr;
4501             }
4502          }
4503          if (Found) {
4504             SUMA_PositionWindowRelative(SUMAg_SVv[ic].X->TOPLEVEL,
4505                                         SUMAg_SVv[icr].X->TOPLEVEL,
4506                                         SWP_TOP_RIGHT);
4507          } else {
4508             if (SUMA_isEnv("SUMA_StartUpLocation", "POINTER"))
4509                SUMA_PositionWindowRelative(SUMAg_SVv[ic].X->TOPLEVEL,
4510                                         NULL,
4511                                         SWP_POINTER_OFF);
4512             else {
4513                /*default, do nothing */
4514             }
4515          }
4516 
4517       }
4518       SUMA_SV_InitDrawAreaOffset(SUMAg_SVv+ic);
4519 
4520       SUMA_LH("Done with new window setup");
4521    } else {    /* widget already set up, just undo whatever
4522                   was done in SUMA_ButtClose_pushed */
4523 
4524       switch (SUMA_GL_CLOSE_MODE) {
4525          case SUMA_WITHDRAW:
4526             XMapRaised( SUMAg_SVv[ic].X->DPY,
4527                         XtWindow(SUMAg_SVv[ic].X->TOPLEVEL));
4528             break;
4529          case SUMA_UNREALIZE:
4530             SUMA_LH("Realizing");
4531             XtRealizeWidget(SUMAg_SVv[ic].X->TOPLEVEL);
4532             XSync(SUMAg_SVv[ic].X->DPY, 0);  /* Don't know if this helps for sure
4533                                                 Part of the OS X 10.5 GLX crash
4534                                                 from hell */
4535             break;
4536          default:
4537             SUMA_S_Err("Not set up for this closing mode");
4538             SUMA_RETURN(NOPE);
4539             break;
4540       }
4541       /* add the workprocess again */
4542       SUMA_register_workproc( SUMA_handleRedisplay, SUMAg_SVv[ic].X->GLXAREA );
4543       SUMAg_SVv[ic].X->REDISPLAYPENDING = 0;
4544    }
4545 
4546    SUMAg_SVv[ic].Open = YUP;
4547    ++SUMAg_CF->N_OpenSV;
4548    ++CallNum;
4549 
4550    SUMA_LH("Updates");
4551    SUMA_UpdateViewerCursor (&(SUMAg_SVv[ic]));
4552    SUMA_UpdateViewerTitle (&(SUMAg_SVv[ic]));
4553 
4554    SUMA_LH("Returning");
4555    SUMA_RETURN (YUP);
4556 }
4557 
SUMA_ButtOpen_pushed(Widget w,XtPointer cd1,XtPointer cd2)4558 void SUMA_ButtOpen_pushed (Widget w, XtPointer cd1, XtPointer cd2)
4559 {
4560    static char FuncName[]={"SUMA_ButtOpen_pushed"};
4561 
4562    SUMA_ENTRY;
4563 
4564    if (!SUMA_X_SurfaceViewer_Create ()) {
4565       fprintf (SUMA_STDERR,
4566                "Error %s: Failed in SUMA_X_SurfaceViewer_Create.\n", FuncName);
4567    }
4568    SUMA_RETURNe;
4569 }
4570 
SUMA_cb_FileOpenSpec(Widget w,XtPointer data,XtPointer calldata)4571 void SUMA_cb_FileOpenSpec (Widget w, XtPointer data, XtPointer calldata)
4572 {
4573    static char FuncName[]={"SUMA_cb_FileOpenSpec"};
4574 
4575    SUMA_ENTRY;
4576 
4577    fprintf (SUMA_STDERR, "%s: called.\n", FuncName);
4578    SUMA_RETURNe;
4579 }
4580 
SUMA_cb_FileOpenSurf(Widget w,XtPointer data,XtPointer calldata)4581 void SUMA_cb_FileOpenSurf (Widget w, XtPointer data, XtPointer calldata)
4582 {
4583    static char FuncName[]={"SUMA_cb_FileOpenSurf"};
4584 
4585    SUMA_ENTRY;
4586 
4587    fprintf (SUMA_STDERR, "%s: called.\n", FuncName);
4588    SUMA_RETURNe;
4589 }
4590 
SUMA_cb_FileSaveView(Widget w,XtPointer data,XtPointer calldata)4591 void SUMA_cb_FileSaveView (Widget w, XtPointer data, XtPointer calldata)
4592 {
4593    static char FuncName[]={"SUMA_cb_FileSaveView"};
4594    int isv, widtype;
4595    SUMA_EngineData *ED = NULL;
4596    DList *list = NULL;
4597    SUMA_SurfaceViewer *sv;
4598 
4599    SUMA_ENTRY;
4600 
4601    /* find the index of the viewer closed */
4602    SUMA_VIEWER_FROM_FILEMENU_CALLBACK(data, isv, widtype);
4603    if (widtype != SW_FileSaveView) {
4604       fprintf (SUMA_STDERR,
4605          "Error %s: Something really bad has happened.\n", FuncName);
4606       SUMA_RETURNe;
4607    }
4608 
4609    sv = &SUMAg_SVv[isv];
4610 
4611    if (!list) list = SUMA_CreateList();
4612    ED = SUMA_InitializeEngineListData (SE_SaveViewFileSelection);
4613    if (!SUMA_RegisterEngineListCommand (  list, ED,
4614                                           SEF_ip, sv->X->TOPLEVEL,
4615                                           SES_Suma, (void *)sv, NOPE,
4616                                           SEI_Head, NULL)) {
4617       fprintf (SUMA_STDERR, "Error %s: Failed to register command.\n", FuncName);
4618    }
4619    if (!SUMA_Engine (&list)) {
4620       fprintf(SUMA_STDERR, "Error %s: SUMA_Engine call failed.\n", FuncName);
4621    }
4622 
4623    /*
4624    if (!SUMA_SaveVisualState(NULL, (void*)sv)) {
4625       SUMA_SLP_Err("Failed to save view.");
4626       SUMA_RETURNe;
4627    }
4628    */
4629 
4630    SUMA_RETURNe;
4631 }
4632 
SUMA_cb_FileLoadView(Widget w,XtPointer data,XtPointer calldata)4633 void SUMA_cb_FileLoadView (Widget w, XtPointer data, XtPointer calldata)
4634 {
4635    static char FuncName[]={"SUMA_cb_FileLoadView"};
4636    int isv, widtype;
4637    SUMA_EngineData *ED = NULL;
4638    DList *list = NULL;
4639    SUMA_SurfaceViewer *sv;
4640 
4641    SUMA_ENTRY;
4642 
4643    /* find the index of the viewer closed */
4644    SUMA_VIEWER_FROM_FILEMENU_CALLBACK(data, isv, widtype);
4645    if (widtype != SW_FileLoadView) {
4646       fprintf (SUMA_STDERR, "Error %s: Something really bad has happened.\n", FuncName);
4647       SUMA_RETURNe;
4648    }
4649 
4650    sv = &SUMAg_SVv[isv];
4651 
4652    if (!list) list = SUMA_CreateList();
4653    ED = SUMA_InitializeEngineListData (SE_LoadViewFileSelection);
4654    if (!SUMA_RegisterEngineListCommand (  list, ED,
4655                                           SEF_ip, sv->X->TOPLEVEL,
4656                                           SES_Suma, (void *)sv, NOPE,
4657                                           SEI_Head, NULL)) {
4658       fprintf (SUMA_STDERR, "Error %s: Failed to register command.\n", FuncName);
4659    }
4660    if (!SUMA_Engine (&list)) {
4661       fprintf(SUMA_STDERR, "Error %s: SUMA_Engine call failed.\n", FuncName);
4662    }
4663 
4664    /*
4665    if (!SUMA_LoadVisualState(NULL, (void*)sv)) {
4666       SUMA_SLP_Err("Failed to load view.");
4667       SUMA_RETURNe;
4668    }
4669    */
4670 
4671    SUMA_RETURNe;
4672 }
4673 
4674 
SUMA_cb_FileClose(Widget w,XtPointer data,XtPointer calldata)4675 void SUMA_cb_FileClose (Widget w, XtPointer data, XtPointer calldata)
4676 {
4677    static char FuncName[]={"SUMA_cb_FileClose"};
4678    int isv, widtype;
4679    SUMA_SurfaceViewer *sv;
4680 
4681    SUMA_ENTRY;
4682 
4683    /* find the index of the viewer closed */
4684    SUMA_VIEWER_FROM_FILEMENU_CALLBACK(data, isv, widtype);
4685    if (widtype != SW_FileClose) {
4686       fprintf (SUMA_STDERR,
4687                "Error %s: Something really bad has happened.\n", FuncName);
4688       SUMA_RETURNe;
4689    }
4690 
4691    sv = &SUMAg_SVv[isv];
4692    SUMA_ButtClose_pushed (sv->X->GLXAREA, data, calldata);
4693 
4694    SUMA_RETURNe;
4695 }
4696 
4697 
4698 /*!
4699   \brief Close the viewer. Exit if it is last viewer to be closed.
4700 */
SUMA_ButtClose_pushed(Widget w,XtPointer cd1,XtPointer cd2)4701 void SUMA_ButtClose_pushed (Widget w, XtPointer cd1, XtPointer cd2)
4702 {
4703    static char FuncName[]={"SUMA_ButtClose_pushed"};
4704    int ic, Found, isv = 0;
4705    SUMA_Boolean LocalHead = NOPE;
4706 
4707    SUMA_ENTRY;
4708 
4709    SUMA_LH("Called");
4710    ic = 0;
4711    Found = 0;
4712    while (ic < SUMA_MAX_SURF_VIEWERS && !Found) {
4713       #if 0
4714       /*use once you have a close button with its widget*/
4715       if (SUMAg_SVv[ic].X->ButtClose == w) {
4716          if (LocalHead)
4717             fprintf (SUMA_STDERR,"%s: Close order from button.\n", FuncName);
4718          Found = 1;
4719       }
4720       #endif
4721       if (SUMAg_SVv[ic].X->TOPLEVEL == w) {
4722          if (LocalHead)
4723             fprintf (SUMA_STDERR,
4724                      "%s: Close order from window manager for viewer %d.\n",
4725                      FuncName, ic);
4726          Found = 1;
4727       }else if (SUMAg_SVv[ic].X->GLXAREA == w) {
4728          if (LocalHead)
4729             fprintf (SUMA_STDERR,
4730                      "%s: Close order from GLX area for viewer %d.\n",
4731                      FuncName, ic);
4732          Found = 1;
4733       }
4734 
4735       if (!Found) ++ic;
4736    }
4737 
4738    if (Found) {
4739          if (LocalHead)
4740             fprintf (SUMA_STDERR,"%s: Widget Found, ic = %d\n", FuncName, ic);
4741 
4742          /* Must turn off all workprocesses and timeouts for
4743             this surface viewer */
4744 
4745          if (!SUMAg_SVv[ic].Open) {
4746             SUMA_S_Errv("Viewer %d already closed (%d)\n",
4747                        ic, SUMAg_SVv[ic].Open);
4748          }
4749          if (LocalHead)
4750             fprintf (SUMA_STDERR,
4751                      "%s: Turning off workprocesses and timeouts ...\n",
4752                      FuncName);
4753          if (SUMAg_SVv[ic].GVS[SUMAg_SVv[ic].StdView].ApplyMomentum) {
4754             if (SUMAg_SVv[ic].X->MOMENTUMID)
4755                XtRemoveTimeOut(SUMAg_SVv[ic].X->MOMENTUMID);
4756             SUMAg_SVv[ic].X->MOMENTUMID = 0;
4757          }
4758 
4759          /* remove Redisplay workprocess*/
4760          SUMA_remove_workproc2( SUMA_handleRedisplay, SUMAg_SVv[ic].X->GLXAREA );
4761 
4762 
4763          /* done cleaning up, deal with windows ... */
4764 
4765          /**
4766             SEE UPDATED NOTE IN SUMA_display.h
4767             The comment below is obsolete.
4768             ==================================
4769          Fri Jan  3 09:51:35 EST 2003
4770              XtUnrealizeWidget is not used anymore because it destroys
4771              windows associated with a widget and its descendants.
4772             There's no need for that here.
4773             Also, destroying widgets should not be used either because that would
4774             automatically destroy the SUMA controller which is a
4775             child of one of the viewers. The code for destroy is left for
4776             historical reasons.*/
4777          switch (SUMA_GL_CLOSE_MODE) {
4778             case SUMA_WITHDRAW:
4779                if (LocalHead)
4780                   fprintf (SUMA_STDERR,"%s: Withdrawing it.\n", FuncName);
4781 
4782                XWithdrawWindow(SUMAg_SVv[ic].X->DPY,
4783                   XtWindow(SUMAg_SVv[ic].X->TOPLEVEL),
4784                   XScreenNumberOfScreen(XtScreen(SUMAg_SVv[ic].X->TOPLEVEL)));
4785                if (SUMAg_SVv[ic].X->ViewCont->TopLevelShell) {
4786                   XWithdrawWindow(SUMAg_SVv[ic].X->DPY,
4787                   XtWindow(SUMAg_SVv[ic].X->ViewCont->TopLevelShell),
4788                   XScreenNumberOfScreen(XtScreen(
4789                                     SUMAg_SVv[ic].X->ViewCont->TopLevelShell)));
4790                }
4791                break;
4792             case SUMA_UNREALIZE:
4793                SUMA_LHv("Unrealizing viewer %d\n", ic);
4794                /* Unrealizing on OS X 10.6 does not crash as it might on 10.5
4795                However, you will get something like the following messages
4796                right after unrealizing the widget.
4797                Don't know what to make of this at this time. ZSS: Oct 05 2009
4798 
4799 Mon Oct  5 17:48:12 eomer.nimh.nih.gov suma[4538] <Error>: kCGErrorIllegalArgument: CGSGetSurfaceBounds
4800 Mon Oct  5 17:48:12 eomer.nimh.nih.gov suma[4538] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xd1
4801 Mon Oct  5 17:48:12 eomer.nimh.nih.gov suma[4538] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xd1
4802 Mon Oct  5 17:48:12 eomer.nimh.nih.gov suma[4538] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xd1
4803 Mon Oct  5 17:48:12 eomer.nimh.nih.gov suma[4538] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xd1
4804 Mon Oct  5 17:48:12 eomer.nimh.nih.gov suma[4538] <Error>: unknown error code: invalid drawable
4805                */
4806                XtUnrealizeWidget(SUMAg_SVv[ic].X->TOPLEVEL);
4807                break;
4808             case SUMA_DESTROY:
4809                if (LocalHead)
4810                   fprintf (SUMA_STDERR,"%s: Destroying it.\n", FuncName);
4811                XtDestroyWidget(SUMAg_SVv[ic].X->TOPLEVEL);
4812                SUMAg_SVv[ic].X->TOPLEVEL = NULL;
4813 
4814                /* no need to destroy viewer controller */
4815                SUMAg_SVv[ic].X->ViewCont->TopLevelShell = NULL;
4816 
4817                /* update the count */
4818                SUMAg_N_SVv -= 1;
4819                break;
4820             default:
4821                SUMA_S_Err("Not set to deal with this closing mode");
4822                SUMA_RETURNe;
4823          }
4824 
4825          /* Textures displayed before closing a viewer no longer show up after
4826          the viewer is reopened. Reloading the texture with SUMA_VE_LoadTexture()
4827          brings it back, but that's a slow call that should only be done when
4828          necessary. This next call resets the records of which textures have
4829          been loaded already so that at the next drawing operation the loading
4830          is rerun and the texture marked as loaded */
4831          if (!SUMA_SV_Mark_Textures_Status(SUMAg_SVv+ic, "unloaded_all",
4832                                              NULL, 0, 0)){
4833             SUMA_S_Err("Failed to mark all textures as unloaded");
4834             SUMA_RETURNe;
4835          }
4836 
4837          SUMAg_SVv[ic].Open = NOPE;
4838          --SUMAg_CF->N_OpenSV;
4839          if (SUMAg_CF->N_OpenSV == 0) {
4840             if (LocalHead)
4841                fprintf (SUMA_STDERR,"%s: No more viewers, exiting.\n", FuncName);
4842             /* not quite necessary but for completeness */
4843             if (SUMAg_CF->X->SumaCont->AppShell) {
4844                XtDestroyWidget(SUMAg_CF->X->SumaCont->AppShell);
4845             }
4846             selenium_close();/* close selenium opened browser windows if open */
4847             exit(0);
4848          }
4849    } else {
4850       fprintf (SUMA_STDERR,"Error %s: Widget not Found!.\n", FuncName);
4851    }
4852 
4853     SUMA_RETURNe;
4854 }
4855 
SUMA_getShareableColormap_Eng(XVisualInfo * vi,Display * dpy)4856 Colormap SUMA_getShareableColormap_Eng (XVisualInfo * vi, Display *dpy)
4857 {
4858    Status status;
4859    XStandardColormap *standardCmaps;
4860    int i, numCmaps;
4861    Colormap cmap;
4862    SUMA_Boolean LocalHead = NOPE;
4863    static char FuncName[]={"SUMA_getShareableColormap_Eng"};
4864 
4865    SUMA_ENTRY;
4866 
4867    /* Be lazy; using DirectColor too involved for this example. */
4868 #if defined(__cplusplus) || defined(c_plusplus)
4869    if (vi->c_class != TrueColor) {
4870       SUMA_S_Crit("SUMA has no support for non-TrueColor visual");
4871       exit(1);
4872    }
4873 #else
4874    if (vi->class != TrueColor) {
4875       SUMA_S_Crit("SUMA has no no support for non-TrueColor visual");
4876       exit(1);
4877    }
4878 #endif
4879 
4880    /* If no standard colormap but TrueColor, just make an
4881      unshared one. */
4882    status = XmuLookupStandardColormap(dpy, vi->screen, vi->visualid,
4883     vi->depth, XA_RGB_DEFAULT_MAP,
4884     False,              /* Replace. */
4885     True);              /* Retain. */
4886    if (status == 1) {
4887     status = XGetRGBColormaps(dpy, RootWindow(dpy, vi->screen),
4888       &standardCmaps, &numCmaps, XA_RGB_DEFAULT_MAP);
4889     if (status == 1)
4890       for (i = 0; i < numCmaps; i++)
4891         if (standardCmaps[i].visualid == vi->visualid) {
4892           cmap = standardCmaps[i].colormap;
4893           XFree(standardCmaps);
4894           SUMA_RETURN(cmap);
4895         }
4896    }
4897   cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen), vi->visual, AllocNone);
4898 
4899   SUMA_RETURN(cmap);
4900 
4901 }
4902 Colormap
SUMA_getShareableColormap(SUMA_SurfaceViewer * csv)4903 SUMA_getShareableColormap(SUMA_SurfaceViewer *csv)
4904 {
4905    SUMA_Boolean LocalHead = NOPE;
4906    static char FuncName[]={"SUMA_getShareableColormap"};
4907 
4908    SUMA_ENTRY;
4909 
4910    SUMA_RETURN(SUMA_getShareableColormap_Eng(csv->X->VISINFO, csv->X->DPY));
4911 }
4912 
SUMA_SetcSV(Widget w,XtPointer clientData,XEvent * event,Boolean * cont)4913 void SUMA_SetcSV (Widget w, XtPointer clientData, XEvent * event, Boolean * cont)
4914 {
4915    static char FuncName[]={"SUMA_SetcSV"};
4916    SUMA_SurfaceViewer *sv;
4917    int isv;
4918    SUMA_Boolean LocalHead = NOPE;
4919 
4920    SUMA_ENTRY;
4921 
4922    if (LocalHead) fprintf(SUMA_STDERR,"%s:\n Called, w = %p\n", FuncName, w);
4923 
4924 
4925    /* When using multiple viewers, you must reset the
4926       OpenGL state variables or risk having abrupt changes with the
4927       first click */
4928    SUMA_ANY_WIDGET2SV(w, sv, isv);
4929    if (isv < 0) {
4930       fprintf (SUMA_STDERR,
4931                "Error %s: Failed in macro SUMA_ANY_WIDGET2SV.\n", FuncName);
4932       SUMA_RETURNe;
4933    }
4934    SUMAg_CF->PointerLastInViewer = isv;
4935 
4936    #ifdef DARWIN
4937       /* Set the focus manually.
4938       If you're not using motif widgets, window focus is not managed.
4939       You can manage it yourself with XSetInputFocus when the EnterWindowEvent is captured.
4940       You don't need to do that however if you link (for some reason) to -lXm.
4941       But on the macosx10, -lXm does not help, so we manage the foucs ourselves */
4942       /* The downside is that this call seems to be related to a crash on the mac,
4943       reported as a complaint coming from X_SetInputFocus.
4944       The crash happened when multiple viewers were open and one of them was closed
4945       AND suma was set to prompt the user with "Close this viewer?"
4946       I tried resetting the focus to a viewer that is not being closed before
4947       closing the reviewer as requested by the user but that did not help.
4948       It turns out that the problem does not occur if the prompt window does not
4949       appear on top of the viewer to be closed. More precisely, if the pointer ends
4950       up on top of the viewer just after the prompt window disapears SUMA crashes with the
4951       message: X Error of failed request: BadMatch (invalid parameter attributes) ...
4952       The solution is simple, on DARWIN, make sure prompt window appears to the right
4953       of the viewer. If the user moves it back over the viewer AND then presses YES to close
4954       the viewer then they will suffer the crash. June 15 04*/
4955 
4956       XSetInputFocus(sv->X->DPY, XtWindow(w), RevertToPointerRoot, CurrentTime);
4957    #endif
4958 
4959    sv->rdc = SUMA_RDC_X_ENTER_WINDOW;
4960 
4961    if (LocalHead)
4962       fprintf (SUMA_STDERR, "%s: in Surface Viewer #%d.\n", FuncName, isv);
4963    sv->ResetGLStateVariables = YUP;
4964 
4965    SUMA_postRedisplay(w, clientData, NULL);
4966 
4967 
4968    SUMA_RETURNe;
4969 }
4970 
SUMA_unSetcSV(Widget w,XtPointer clientData,XEvent * event,Boolean * cont)4971 void SUMA_unSetcSV (Widget w, XtPointer clientData,
4972                      XEvent * event, Boolean * cont)
4973 {
4974    static char FuncName[]={"SUMA_unSetcSV"};
4975 
4976    SUMA_ENTRY;
4977 
4978    SUMA_RETURNe;
4979 }
4980 
4981 /* ------------------------------------------------------------------------------------------------------------*/
4982 /*!
4983 
4984  functions SUMA_generateEPS, SUMA_grabPixels, SUMA_RenderToPixMap are straight from pixmap2eps.c
4985 
4986  COPYRIGHT NOTICE FROM pixmap2eps.c
4987  Copyright (c) Mark J. Kilgard, 1996.
4988 
4989  This program is freely distributable without licensing fees
4990    and is provided without guarantee or warrantee expressed or
4991    implied. This program is -not- in the public domain.
4992 
4993  \sa OpenGl, Programming for the X Window System, pp 94, 95
4994 
4995 */
4996 
4997 
4998 int
SUMA_generateEPS(char * filename,int inColor,unsigned int width,unsigned int height)4999 SUMA_generateEPS( char *filename, int inColor,
5000                   unsigned int width, unsigned int height)
5001 {
5002    FILE *fp;
5003    GLvoid *pixels;
5004    unsigned char *curpix;
5005    int components, pos, i;
5006    static char FuncName[]={"SUMA_generateEPS"};
5007 
5008    SUMA_ENTRY;
5009 
5010    pixels = SUMA_grabPixels(inColor ? 3:1, width, height);
5011 
5012    if (pixels == NULL)
5013     SUMA_RETURN (1);
5014    if (inColor)
5015     components = 3;     /* Red, green, blue. */
5016    else
5017     components = 1;     /* Luminance. */
5018 
5019    fp = fopen(filename, "w");
5020    if (fp == NULL) {
5021     SUMA_RETURN (2);
5022    }
5023    fprintf(fp, "%%!PS-Adobe-2.0 EPSF-1.2\n");
5024    fprintf(fp, "%%%%Creator: OpenGL pixmap render output\n");
5025    fprintf(fp, "%%%%BoundingBox: 0 0 %d %d\n", width, height);
5026    fprintf(fp, "%%%%EndComments\n");
5027    fprintf(fp, "gsave\n");
5028    fprintf(fp, "/bwproc {\n");
5029    fprintf(fp, "    rgbproc\n");
5030    fprintf(fp, "    dup length 3 idiv string 0 3 0\n");
5031    fprintf(fp, "    5 -1 roll {\n");
5032    fprintf(fp, "    add 2 1 roll 1 sub dup 0 eq\n");
5033    fprintf(fp, "    { pop 3 idiv 3 -1 roll dup 4 -1 roll dup\n");
5034    fprintf(fp, "        3 1 roll 5 -1 roll put 1 add 3 0 }\n");
5035    fprintf(fp, "    { 2 1 roll } ifelse\n");
5036    fprintf(fp, "    } forall\n");
5037    fprintf(fp, "    pop pop pop\n");
5038    fprintf(fp, "} def\n");
5039    fprintf(fp, "systemdict /colorimage known not {\n");
5040    fprintf(fp, "    /colorimage {\n");
5041    fprintf(fp, "        pop\n");
5042    fprintf(fp, "        pop\n");
5043    fprintf(fp, "        /rgbproc exch def\n");
5044    fprintf(fp, "        { bwproc } image\n");
5045    fprintf(fp, "    } def\n");
5046    fprintf(fp, "} if\n");
5047    fprintf(fp, "/picstr %d string def\n", width * components);
5048    fprintf(fp, "%d %d scale\n", width, height);
5049    fprintf(fp, "%d %d %d\n", width, height, 8);
5050    fprintf(fp, "[%d 0 0 %d 0 0]\n", width, height);
5051    fprintf(fp, "{currentfile picstr readhexstring pop}\n");
5052    fprintf(fp, "false %d\n", components);
5053    fprintf(fp, "colorimage\n");
5054 
5055    curpix = (unsigned char *) pixels;
5056    pos = 0;
5057    for (i = width * height * components; i > 0; i--) {
5058     fprintf(fp, "%02hx", *curpix++);
5059     if (++pos >= 32) {
5060       fprintf(fp, "\n");
5061       pos = 0;
5062     }
5063    }
5064    if (pos)
5065     fprintf(fp, "\n");
5066 
5067    fprintf(fp, "grestore\n");
5068    SUMA_free(pixels);
5069    fclose(fp);
5070    SUMA_RETURN (0);
5071 }
5072 
SUMA_grabRenderedPixels(SUMA_SurfaceViewer * sv,int ColorDepth,unsigned int width,unsigned int height,int getback)5073 GLvoid *SUMA_grabRenderedPixels(SUMA_SurfaceViewer *sv, int ColorDepth,
5074                         unsigned int width, unsigned int height, int getback)
5075 {
5076    GLvoid *buffer=NULL;
5077    if (!sv || !sv->X) return(buffer);
5078    if (!getback) SUMA_GLX_BUF_SWAP(sv); /* return to last rendered buffer */
5079    buffer = SUMA_grabPixels(ColorDepth, width, height);
5080    if (!getback) SUMA_GLX_BUF_SWAP(sv);  /* return to current buffer */
5081    return(buffer);
5082 }
5083 
SUMA_grabPixels(int ColorDepth,unsigned int width,unsigned int height)5084 GLvoid *SUMA_grabPixels(int ColorDepth,
5085                         unsigned int width, unsigned int height)
5086 {
5087    static char FuncName[]={"SUMA_grabPixels"};
5088    GLvoid *buffer;
5089    GLint swapbytes, lsbfirst, rowlength;
5090    GLint skiprows, skippixels, alignment;
5091    GLenum format;
5092    int tp, saverestore;
5093    unsigned int size;
5094 
5095    SUMA_ENTRY;
5096 
5097    if (ColorDepth == 0) ColorDepth = 1;   /* for backward compatibility */
5098 
5099    saverestore = 1;
5100    switch (ColorDepth) {
5101       case GL_LUMINANCE:
5102       case 1:
5103          format = GL_LUMINANCE;
5104          tp = GL_UNSIGNED_BYTE;
5105          size = width * height * 1;
5106          break;
5107       case GL_RGB:
5108       case 3:
5109          format = GL_RGB;
5110          tp = GL_UNSIGNED_BYTE;
5111          size = width * height * 3;
5112          break;
5113       case GL_RGBA:
5114       case 4:
5115          format = GL_RGBA;
5116          tp = GL_UNSIGNED_BYTE;
5117          size = width * height * 4;
5118          break;
5119       case GL_DEPTH_COMPONENT:
5120       case 5:
5121          saverestore = 0;
5122          format = GL_DEPTH_COMPONENT;
5123          tp = GL_FLOAT;
5124          size = width * height * 1 * sizeof(GLfloat);
5125          break;
5126       case GL_STENCIL_INDEX:
5127       case 6:
5128          saverestore = 0;
5129          format = GL_STENCIL_INDEX;
5130          tp = GL_FLOAT; /* Unsigned byte did not work */
5131          size = width * height * 1 * sizeof(GLfloat);
5132          break;
5133       default:
5134          SUMA_S_Errv("Bad ColorDepth or format of %d\n", ColorDepth);
5135          SUMA_RETURN(NULL);
5136    }
5137 
5138    buffer = (GLvoid *) SUMA_malloc(size);
5139    if (buffer == NULL)
5140     SUMA_RETURN (buffer);
5141 
5142 
5143    if (saverestore) { /* Using this makes depth and stencil index reads fail,
5144                          at least on mac os x         ZSS Dec 31 2013*/
5145       /* Save current modes. */
5146       glGetIntegerv(GL_PACK_SWAP_BYTES, &swapbytes);
5147       glGetIntegerv(GL_PACK_LSB_FIRST, &lsbfirst);
5148       glGetIntegerv(GL_PACK_ROW_LENGTH, &rowlength);
5149       glGetIntegerv(GL_PACK_SKIP_ROWS, &skiprows);
5150       glGetIntegerv(GL_PACK_SKIP_PIXELS, &skippixels);
5151       glGetIntegerv(GL_PACK_ALIGNMENT, &alignment);
5152       /* Little endian machines (DEC Alpha for example) could
5153         benefit from setting GL_PACK_LSB_FIRST to GL_TRUE
5154         instead of GL_FALSE, but this would require changing the
5155         generated bitmaps too. */
5156       glPixelStorei(GL_PACK_SWAP_BYTES, GL_TRUE);
5157       glPixelStorei(GL_PACK_LSB_FIRST, GL_TRUE);
5158       glPixelStorei(GL_PACK_ROW_LENGTH, 0);
5159       glPixelStorei(GL_PACK_SKIP_ROWS, 0);
5160       glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
5161       glPixelStorei(GL_PACK_ALIGNMENT, 1);
5162    }
5163 
5164    /* Actually read the pixels. */
5165    glReadPixels(0, 0, width, height, format,
5166                 tp, (GLvoid *) buffer);
5167 
5168    if (saverestore) {
5169       /* Restore saved modes. */
5170       glPixelStorei(GL_PACK_SWAP_BYTES, swapbytes);
5171       glPixelStorei(GL_PACK_LSB_FIRST, lsbfirst);
5172       glPixelStorei(GL_PACK_ROW_LENGTH, rowlength);
5173       glPixelStorei(GL_PACK_SKIP_ROWS, skiprows);
5174       glPixelStorei(GL_PACK_SKIP_PIXELS, skippixels);
5175       glPixelStorei(GL_PACK_ALIGNMENT, alignment);
5176    }
5177 
5178    SUMA_RETURN (buffer);
5179 }
5180 
5181 
SUMA_RenderToPixMap(SUMA_SurfaceViewer * csv,SUMA_DO * dov)5182 SUMA_Boolean SUMA_RenderToPixMap (SUMA_SurfaceViewer *csv, SUMA_DO *dov)
5183 {
5184    static int configuration[] = { GLX_DOUBLEBUFFER, GLX_RGBA, GLX_DEPTH_SIZE, 16,
5185    GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, None};
5186    Display *dpy;
5187    XVisualInfo *vi;
5188    GLXContext cx;
5189    Pixmap pmap;
5190    GLXPixmap glxpmap;
5191    int isv=-1;
5192    char buf[32];
5193    static char FuncName[]={"SUMA_RenderToPixMap"};
5194 
5195    SUMA_ENTRY;
5196    SUMA_S_Note("CALLED!");
5197    dpy = XOpenDisplay(NULL);
5198    if (dpy == NULL)
5199     fprintf(SUMA_STDERR,"Error %s: could not open display", FuncName);
5200 
5201    if (!glXQueryExtension(dpy, NULL, NULL))
5202     fprintf(SUMA_STDERR,
5203             "Error %s: X server has no OpenGL GLX extension", FuncName);
5204 
5205    /* find an OpenGL-capable RGB visual with depth buffer */
5206    #if 1  /* use screen rendering Xvisual */
5207    vi = glXChooseVisual(dpy, DefaultScreen(dpy), &configuration[1]);
5208    if (vi == NULL) {
5209    /*fprintf(SUMA_STDERR,"%s: Trying to use useless double
5210                buffering configuration.\n", FuncName);*/
5211     vi = glXChooseVisual(dpy, DefaultScreen(dpy), &configuration[0]);
5212     if (vi == NULL) {
5213       fprintf( SUMA_STDERR,
5214                "Error %s: no appropriate RGB visual with depth buffer",
5215                FuncName);
5216     }
5217    }
5218    #else
5219    vi = csv->X->VISINFO;
5220    #endif
5221 
5222 
5223    /* create an OpenGL rendering context */
5224    cx = glXCreateContext(dpy, vi,
5225     NULL,               /* no sharing of display lists */
5226     False);             /* direct rendering if possible */
5227    if (cx == NULL)
5228     fprintf(SUMA_STDERR,
5229             "Error %s: could not create rendering context", FuncName);
5230 
5231    pmap = XCreatePixmap(dpy, RootWindow(dpy, vi->screen),
5232     csv->X->aWIDTH, csv->X->aHEIGHT, vi->depth);
5233    glxpmap = glXCreateGLXPixmap(dpy, vi, pmap);
5234    isv = SUMA_WhichSV(csv, SUMAg_SVv, SUMAg_N_SVv);
5235    sprintf(buf,"pixmap of sv %d", isv);
5236    if (!SUMA_glXMakeCurrent(dpy, glxpmap, cx, FuncName, buf, 1)) {
5237       fprintf (SUMA_STDERR,
5238                "Error %s: Failed in SUMA_glXMakeCurrent.\n \tContinuing ...\n",
5239                FuncName);
5240       SUMA_GL_ERRS;
5241 
5242       SUMA_RETURN(NOPE);
5243    }
5244 
5245    SUMA_context_Init(csv);
5246    glViewport(0, 0, csv->X->aWIDTH, csv->X->aHEIGHT);
5247    SUMA_display(csv, dov);
5248 
5249    glFinish (); /* make sure you wait until rendering is over */
5250 
5251    /* find out the next best name and write it*/
5252    {
5253       char tmpprfx[100], *padprfx, *padname;
5254       int cntindx=0;
5255       SUMA_SurfaceObject *SO;
5256       SUMA_Boolean OKname = NOPE;
5257 
5258       /* get the SO in focus, use it's label for output filename */
5259       SO = SUMA_SV_Focus_SO(csv);
5260 
5261       if (!SO){
5262          padname = (char *)SUMA_calloc(100, sizeof(char));
5263       }else {
5264          if (!SO->Label) { /* nothing set, proceed with default */
5265             padname = (char *)SUMA_calloc(100, sizeof(char));
5266          } else {
5267             padname = (char *)SUMA_calloc(strlen(SO->Label)+10, sizeof(char));
5268          }
5269       }
5270       while (!OKname) {
5271          sprintf (tmpprfx, "%d", cntindx);
5272          padprfx = SUMA_pad_str (tmpprfx, '0', 4, 0);
5273          if (!SO) {
5274             sprintf(padname,"suma_img%s.eps", padprfx);
5275          }else {
5276             sprintf(padname,"%s_%s.eps", SO->Label, padprfx);
5277          }
5278          if (SUMA_filexists(padname)) {
5279             ++cntindx;
5280          } else { OKname = YUP; }
5281 
5282          SUMA_free(padprfx);
5283       }
5284 
5285      fprintf (SUMA_STDOUT,"%s: Writing image to %s ...", FuncName, padname);
5286      SUMA_generateEPS(padname, /* color */ 1, csv->X->aWIDTH, csv->X->aHEIGHT);
5287      fprintf (SUMA_STDOUT,"Done.\n");
5288      SUMA_free(padname);
5289    }
5290 
5291    /* render to original context */
5292    /* SUMA_HOLD_IT; Not used anymore */
5293    sprintf(buf,"GLXAREA of sv %d",  isv);
5294    if (!SUMA_glXMakeCurrent( XtDisplay(csv->X->GLXAREA),
5295              XtWindow(csv->X->GLXAREA),  csv->X->GLXCONTEXT,
5296              FuncName, buf, 1)) {
5297       fprintf (SUMA_STDERR,
5298                "Error %s: Failed in SUMA_glXMakeCurrent.\n \tContinuing ...\n",
5299                FuncName);
5300       SUMA_GL_ERRS;
5301 
5302       SUMA_RETURN (NOPE);
5303    }
5304 
5305    SUMA_RETURN (YUP);
5306 }
5307 
5308 /* ------------------------------------------------------------------------------------------------------------*/
5309 /*! Returns the index of the node that neighbors inode in a direction
5310 that most closely follows the direction in dd expressed in screen coordinate
5311 space
5312    \param sv
5313    \param SO
5314    \param inode (int) node in question for which we seek a neighbor along dd
5315    \param dd (2x1 double) direction in screen units along which we wish to find
5316                           a neighbor of inode. Make sure dd's norm is 1
5317    \return inodenext (int) -2 in case of error
5318                            -1 in case of no plausible move along dd.
5319                               the function allows moves as long as the
5320                               dot product is > 0
5321                            the node neighboring inode such that the screen
5322                            projection of vector inode-->inodenext is the closest
5323                            in direction to dd
5324 */
SUMA_NodeNeighborAlongScreenDirection(SUMA_SurfaceViewer * sv,SUMA_SurfaceObject * SO,int inode,double * dd)5325 int SUMA_NodeNeighborAlongScreenDirection(SUMA_SurfaceViewer *sv,
5326                                           SUMA_SurfaceObject *SO,
5327                                           int inode, double *dd)
5328 {
5329    static char FuncName[]={"SUMA_NodeNeighborAlongScreenDirection"};
5330    int ii, jj, ineighb=0, inodenext = -2, idd=-1;
5331    int lay=-1, N_neighbs=0, *neighbs=NULL;
5332    double *p=NULL;
5333    double *s=NULL, dot=0.0, dotmax=0.0;
5334    int *q=NULL;
5335    static int offset_N_Node=-1;
5336    static SUMA_GET_OFFSET_STRUCT *OffS = NULL;
5337    double dir[3]={0.0,0.0,0.0}, norm=0.0;
5338    SUMA_Boolean LocalHead=NOPE;
5339 
5340    SUMA_ENTRY;
5341 
5342    if (!SO || !sv || !dd) {
5343       SUMA_S_Err("NULL input");
5344       SUMA_RETURN(-2);
5345    }
5346 
5347    lay = sv->KeyNodeJump;
5348 
5349    if (sv->KeyNodeJump > 1) {
5350          if (offset_N_Node != SO->N_Node) {
5351             /* need to reinitialize */
5352             if (OffS) SUMA_Free_getoffsets(OffS); OffS=NULL;
5353             OffS = SUMA_Initialize_getoffsets (SO->N_Node);
5354             offset_N_Node = SO->N_Node;
5355          } else {
5356             SUMA_Recycle_getoffsets(OffS);
5357          }
5358          if (!SUMA_getoffsets2(inode, SO, -(sv->KeyNodeJump+1),
5359                                OffS, NULL, 0)) {
5360             SUMA_S_Err("Failed to get offsets");
5361             SUMA_RETURN(-2);
5362          }
5363    }
5364 
5365    do {
5366       if (lay == 1) {
5367          neighbs = SO->FN->FirstNeighb[inode];
5368          N_neighbs = SO->FN->N_Neighb[inode];
5369       } else {
5370          neighbs = OffS->layers[lay].NodesInLayer;
5371          N_neighbs = OffS->layers[lay].N_NodesInLayer;
5372       }
5373       /* Put the neighbors in p*/
5374       p = (double *)SUMA_calloc( SO->NodeDim*(N_neighbs+1),
5375                                  sizeof(double));
5376       s = (double *)SUMA_calloc( SO->NodeDim*(N_neighbs+1),
5377                                  sizeof(double));
5378       q = (int *)SUMA_calloc( N_neighbs+1, sizeof(int));
5379       for (jj=0; jj<SO->NodeDim; ++jj) {
5380          p[jj] = SO->NodeList[SO->NodeDim*inode+jj];
5381       }
5382       for (ii=0; ii<N_neighbs; ++ii) {
5383          for (jj=0; jj<SO->NodeDim; ++jj) {
5384             ineighb = neighbs[ii];
5385             p[SO->NodeDim*(ii+1)+jj] =
5386                   SO->NodeList[SO->NodeDim*ineighb+jj];
5387          }
5388       }
5389       /* find screen projection of neighbors */
5390       if (!SUMA_World2ScreenCoords( sv, N_neighbs+1,
5391                                     p , s, q, YUP, YUP)) {
5392          SUMA_S_Err("The world has failed me");                                           SUMA_RETURN(-2);
5393       }
5394 
5395       if (LocalHead) {
5396          fprintf(SUMA_STDERR," S = [\n");
5397          for (ii=0; ii<N_neighbs; ++ii) {
5398             fprintf(SUMA_STDERR, "%.3f  %.3f  %.3f\n",
5399                                  s[3*ii], s[3*ii+1], s[3*ii+2]);
5400          }
5401          fprintf(SUMA_STDERR,"];\n");
5402       }
5403 
5404       /* find closest to desired direction */
5405       for (ii=0; ii<N_neighbs; ++ii) {
5406                                  /* for each neighbor*/
5407          /* direction on screen (only x y needed)*/
5408          for (jj=0; jj<2; ++jj) {
5409             dir[jj] = s[(ii+1)*SO->NodeDim+jj] - s[jj];
5410          }
5411          SUMA_NORM_VEC(dir,2,norm);
5412          /* calculate dot product*/
5413          dot = dir[0]*dd[0]/norm + dir[1]*dd[1]/norm;
5414 
5415          if (ii==0) {
5416             dotmax = dot; idd=neighbs[ii];
5417          } else {
5418             if (dot > dotmax) {
5419                dotmax = dot; idd=neighbs[ii];
5420             }
5421          }
5422       }
5423       if (dotmax > 0) {
5424          inodenext = idd;
5425          SUMA_LHv("Next node should be %d\n", inodenext);
5426       } else {
5427          SUMA_LH("No good direction");
5428          inodenext = -1;
5429       }
5430 
5431       if (p) SUMA_free(p); p = NULL;
5432       if (q) SUMA_free(q); q = NULL;
5433       if (s) SUMA_free(s); s = NULL;
5434 
5435       lay = lay -1;
5436    } while (lay > 0 && inodenext < 0);
5437 
5438 
5439    SUMA_RETURN(inodenext);
5440 }
5441 
5442 /*!
5443    Purpose: Takes a the world x,y,z coordinates and turns them into
5444             screen coordinates
5445    Set the ApplyXform to 0 (or NOPE) if you are calling this function
5446    after the projection  and other viewing matrices have been set.
5447    This happens when this function is called as
5448    a child of SUMA_display
5449    \sa SUMA_GetSelectionLine
5450    \sa SUMA_World2ScreenCoordsF, sync modifications
5451 */
SUMA_World2ScreenCoords(SUMA_SurfaceViewer * sv,int N_List,double * WorldList,double * ScreenList,int * Quad,SUMA_Boolean ApplyXform,SUMA_Boolean ScreenY)5452 SUMA_Boolean SUMA_World2ScreenCoords (
5453                      SUMA_SurfaceViewer *sv, int N_List, double *WorldList,
5454                      double *ScreenList, int *Quad, SUMA_Boolean ApplyXform,
5455                      SUMA_Boolean ScreenY)
5456 {
5457    static char FuncName[]={"SUMA_World2ScreenCoords"};
5458    GLfloat rotationMatrix[4][4];
5459    GLint viewport[4];
5460    GLdouble mvmatrix[16], projmatrix[16];
5461    int i, i3;
5462    char CommString[100];
5463    SUMA_Boolean LocalHead = NOPE;
5464 
5465    SUMA_ENTRY;
5466 
5467    if (!sv && (Quad || ApplyXform)) {
5468       SUMA_S_Err("NULL sv with Quad or Xform. I need sv for that");
5469       SUMA_RETURN(NOPE);
5470    }
5471    if (LocalHead && sv) {
5472       fprintf (SUMA_STDERR,
5473                "%s: Current Quat: %.4f, %.4f, %.4f, %.4f.\n",
5474                FuncName, sv->GVS[sv->StdView].currentQuat[0],
5475                sv->GVS[sv->StdView].currentQuat[1],
5476                sv->GVS[sv->StdView].currentQuat[2],
5477                sv->GVS[sv->StdView].currentQuat[3]);
5478       fprintf (SUMA_STDERR,
5479                "%s: Translation Vector of view #%d: %.4f, %.4f, %.4f\n",
5480                FuncName, sv->StdView, sv->GVS[sv->StdView].translateVec[0],
5481                sv->GVS[sv->StdView].translateVec[1],
5482                sv->GVS[sv->StdView].translateVec[2]);
5483       fprintf (SUMA_STDERR,
5484                "%s: RotaCenter of view #%d: %.4f, %.4f, %.4f\n",
5485                FuncName, sv->StdView, sv->GVS[sv->StdView].RotaCenter[0],
5486                sv->GVS[sv->StdView].RotaCenter[1],
5487                sv->GVS[sv->StdView].RotaCenter[2]);
5488    }
5489 
5490 
5491    if (ApplyXform) {
5492       /* go through the ModelView transforms as you would
5493          in display since the modelview matrix is popped
5494          after each display call */
5495       SUMA_build_rotmatrix(rotationMatrix, sv->GVS[sv->StdView].currentQuat);
5496       glMatrixMode(GL_MODELVIEW);
5497       /* The next line appears to fix some bug with GL_MODELVIEW's matrix.
5498          When you clicked button3 for the first time in a viewer,
5499          the chosen point was off. The next click in the identical position would          select the correct point and subsequent clicks are OK.
5500          None of the parameters used for the selection would change between the
5501          first click and the next but it appears that going from one
5502          viewer to the next caused GL_MODELVIEW to change (sometimes) slightly.            Putting the line glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix);
5503          to check (and debug) what was happening to GL_MODELVIEW matrix between
5504          one viewer and the next fixed the clicking problem. So, we keep
5505          it here as a fix until a better one comes along. PS: This was also the
5506          source of the Z (blue) eye axis showing up when it should not. */
5507          glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix);
5508          if (LocalHead) {
5509             int itmp = 0;
5510             fprintf (SUMA_STDERR, "%s: Initial Modelview:\nMV=[ ", FuncName);
5511             while (itmp < 16) {
5512                fprintf (SUMA_STDERR, "%.4f, ", mvmatrix[itmp]); ++itmp;}
5513             fprintf (SUMA_STDERR, "]\n");
5514          }
5515       glPushMatrix();
5516       glTranslatef ( sv->GVS[sv->StdView].translateVec[0],
5517                      sv->GVS[sv->StdView].translateVec[1], 0.0);
5518       glTranslatef ( sv->GVS[sv->StdView].RotaCenter[0],
5519                      sv->GVS[sv->StdView].RotaCenter[1],
5520                      sv->GVS[sv->StdView].RotaCenter[2]);
5521       glMultMatrixf(&rotationMatrix[0][0]);
5522       glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix);
5523          if (LocalHead) {
5524             int itmp = 0;
5525             fprintf (SUMA_STDERR,
5526                      "%s: Modelview After Translation & Rotation:\nMVtr=[ ",
5527                      FuncName);
5528             while (itmp < 16) {
5529                fprintf (SUMA_STDERR, "%.4f, ", mvmatrix[itmp]); ++itmp;}
5530             fprintf (SUMA_STDERR, "]\n");
5531          }
5532       glTranslatef ( -sv->GVS[sv->StdView].RotaCenter[0],
5533                      -sv->GVS[sv->StdView].RotaCenter[1],
5534                      -sv->GVS[sv->StdView].RotaCenter[2]);
5535    }
5536    glGetIntegerv(GL_VIEWPORT, viewport);
5537    glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix);
5538    glGetDoublev(GL_PROJECTION_MATRIX, projmatrix);
5539 
5540    for (i=0;i<N_List; ++i) {
5541       i3 = 3*i;
5542       gluProject( (GLdouble)WorldList[i3],
5543                   (GLdouble)WorldList[i3+1], (GLdouble)WorldList[i3+2],
5544                   mvmatrix, projmatrix, viewport,
5545                   (GLdouble*)(&(ScreenList[i3])),
5546                   (GLdouble*)(&(ScreenList[i3+1])),
5547                   (GLdouble*)(&(ScreenList[i3+2])) );
5548       if (ScreenY) {
5549          ScreenList[i3+1] = viewport[3] - ScreenList[i3+1] - 1; /* change from
5550                                                    OpenGL's y to screen's y */
5551       }
5552 
5553       if (Quad) {
5554          if (ScreenList[i3] < sv->X->aWIDTH/2) {
5555             if (ScreenList[i3+1] > sv->X->aHEIGHT/2)
5556                Quad[i] = SUMA_LOWER_LEFT_SCREEN;
5557             else Quad[i] = SUMA_UPPER_LEFT_SCREEN;
5558          } else {
5559             if (ScreenList[i3+1] > sv->X->aHEIGHT/2)
5560                Quad[i] = SUMA_LOWER_RIGHT_SCREEN;
5561             else Quad[i] = SUMA_UPPER_RIGHT_SCREEN;
5562          }
5563       }
5564       if (LocalHead)
5565          fprintf (SUMA_STDOUT,
5566                   "%s: World: [%.2f %.2f %.2f] \t "
5567                   "Screen [%.2f %.2f %.2f] \t Quad %d\n",
5568                   FuncName,
5569                   WorldList[i3],WorldList[i3+1], WorldList[i3+2],
5570                   ScreenList[i3], ScreenList[i3+1],ScreenList[i3+2],
5571                   Quad?Quad[i]:-999);
5572    }
5573 
5574    if (ApplyXform) glPopMatrix();
5575 
5576    SUMA_RETURN (YUP);
5577 }
5578 
5579 /* Floating point precision version of SUMA_World2ScreenCoords.
5580    Keep in sync with SUMA_World2ScreenCoords */
SUMA_World2ScreenCoordsF(SUMA_SurfaceViewer * sv,int N_List,float * WorldList,float * ScreenList,int * Quad,SUMA_Boolean ApplyXform,SUMA_Boolean ScreenY)5581 SUMA_Boolean SUMA_World2ScreenCoordsF (
5582                      SUMA_SurfaceViewer *sv, int N_List, float *WorldList,
5583                      float *ScreenList, int *Quad, SUMA_Boolean ApplyXform,
5584                      SUMA_Boolean ScreenY)
5585 {
5586    static char FuncName[]={"SUMA_World2ScreenCoordsF"};
5587    GLfloat rotationMatrix[4][4];
5588    GLint viewport[4];
5589    GLdouble mvmatrix[16], projmatrix[16], scd[3];
5590    int i, i3;
5591    char CommString[100];
5592    SUMA_Boolean LocalHead = NOPE;
5593 
5594    SUMA_ENTRY;
5595    if (!sv && (Quad || ApplyXform)) {
5596       SUMA_S_Err("NULL sv with Quad or Xform. I need sv for that");
5597       SUMA_RETURN(NOPE);
5598    }
5599    if (LocalHead && sv) {
5600       fprintf (SUMA_STDERR,
5601                "%s: Current Quat: %.4f, %.4f, %.4f, %.4f.\n",
5602                FuncName, sv->GVS[sv->StdView].currentQuat[0],
5603                sv->GVS[sv->StdView].currentQuat[1],
5604                sv->GVS[sv->StdView].currentQuat[2],
5605                sv->GVS[sv->StdView].currentQuat[3]);
5606       fprintf (SUMA_STDERR,
5607                "%s: Translation Vector of view #%d: %.4f, %.4f, %.4f\n",
5608                FuncName, sv->StdView, sv->GVS[sv->StdView].translateVec[0],
5609                sv->GVS[sv->StdView].translateVec[1],
5610                sv->GVS[sv->StdView].translateVec[2]);
5611       fprintf (SUMA_STDERR,
5612                "%s: RotaCenter of view #%d: %.4f, %.4f, %.4f\n",
5613                FuncName, sv->StdView, sv->GVS[sv->StdView].RotaCenter[0],
5614                sv->GVS[sv->StdView].RotaCenter[1],
5615                sv->GVS[sv->StdView].RotaCenter[2]);
5616    }
5617 
5618 
5619    if (ApplyXform) {
5620       /* go through the ModelView transforms as you would
5621          in display since the modelview matrix is popped
5622          after each display call */
5623       SUMA_build_rotmatrix(rotationMatrix, sv->GVS[sv->StdView].currentQuat);
5624       glMatrixMode(GL_MODELVIEW);
5625       /* The next line appears to fix some bug with GL_MODELVIEW's matrix.
5626          When you clicked button3 for the first time in a viewer,
5627          the chosen point was off. The next click in the identical position would          select the correct point and subsequent clicks are OK.
5628          None of the parameters used for the selection would change between the
5629          first click and the next but it appears that going from one
5630          viewer to the next caused GL_MODELVIEW to change (sometimes) slightly.            Putting the line glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix);
5631          to check (and debug) what was happening to GL_MODELVIEW matrix between
5632          one viewer and the next fixed the clicking problem. So, we keep
5633          it here as a fix until a better one comes along. PS: This was also the
5634          source of the Z (blue) eye axis showing up when it should not. */
5635          glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix);
5636          if (LocalHead) {
5637             int itmp = 0;
5638             fprintf (SUMA_STDERR, "%s: Initial Modelview:\nMV=[ ", FuncName);
5639             while (itmp < 16) {
5640                fprintf (SUMA_STDERR, "%.4f, ", mvmatrix[itmp]); ++itmp;}
5641             fprintf (SUMA_STDERR, "]\n");
5642          }
5643       glPushMatrix();
5644       glTranslatef ( sv->GVS[sv->StdView].translateVec[0],
5645                      sv->GVS[sv->StdView].translateVec[1], 0.0);
5646       glTranslatef ( sv->GVS[sv->StdView].RotaCenter[0],
5647                      sv->GVS[sv->StdView].RotaCenter[1],
5648                      sv->GVS[sv->StdView].RotaCenter[2]);
5649       glMultMatrixf(&rotationMatrix[0][0]);
5650       glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix);
5651          if (LocalHead) {
5652             int itmp = 0;
5653             fprintf (SUMA_STDERR,
5654                      "%s: Modelview After Translation & Rotation:\nMVtr=[ ",
5655                      FuncName);
5656             while (itmp < 16) {
5657                fprintf (SUMA_STDERR, "%.4f, ", mvmatrix[itmp]); ++itmp;}
5658             fprintf (SUMA_STDERR, "]\n");
5659          }
5660       glTranslatef ( -sv->GVS[sv->StdView].RotaCenter[0],
5661                      -sv->GVS[sv->StdView].RotaCenter[1],
5662                      -sv->GVS[sv->StdView].RotaCenter[2]);
5663    }
5664    glGetIntegerv(GL_VIEWPORT, viewport);
5665    glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix);
5666    glGetDoublev(GL_PROJECTION_MATRIX, projmatrix);
5667    /* initialize because if gluProject fails without touching scd, and
5668       then copying scd's contents without any initialization causes
5669       valgrind to gripe, and rightly so. */
5670    scd[0] = scd[1] = scd[2] = 0.0;
5671    for (i=0;i<N_List; ++i) {
5672       i3 = 3*i;
5673       if (!(gluProject( (GLdouble)WorldList[i3],
5674                         (GLdouble)WorldList[i3+1], (GLdouble)WorldList[i3+2],
5675                          mvmatrix, projmatrix, viewport,
5676                         (GLdouble*)(scd  ),
5677                         (GLdouble*)(scd+1),
5678                         (GLdouble*)(scd+2) ))) {
5679          if (LocalHead) {
5680             int iim;
5681             SUMA_S_Warn(
5682                "gluProject Failed, GL_MODELVIEW_MATRIX likely all zeros."
5683                "This might happen if the rendering context is not set.");
5684             SUMA_GL_ERRS;
5685             SUMA_DUMP_TRACE("Trace at gluProject failure");
5686             fprintf(SUMA_STDERR,"ModelView Matrix: (col major)\n");
5687             iim = 0; while (iim < 16) {
5688                fprintf(SUMA_STDERR,"%.3f ", mvmatrix[iim]); ++iim;
5689             }
5690             fprintf(SUMA_STDERR,"\nProjection Matrix: (col major)\n");
5691             iim = 0; while (iim < 16) {
5692                fprintf(SUMA_STDERR,"%.3f ", projmatrix[iim]); ++iim;
5693             }
5694          }
5695          /* Set all output to zero and proceed */
5696          SUMA_LH("Failed in gluProject, skipping");
5697          memset(ScreenList, 0, 3*N_List*sizeof(float));
5698          break;
5699       }
5700       ScreenList[i3] = scd[0];
5701       if (ScreenY) {
5702          ScreenList[i3+1] = viewport[3] - scd[1] - 1; /* change from
5703                                                    OpenGL's y to screen's y */
5704       } else {
5705          ScreenList[i3+1] = scd[1];
5706       }
5707       ScreenList[i3+2] = scd[2];
5708 
5709       if (Quad) {
5710          if (ScreenList[i3] < sv->X->aWIDTH/2) {
5711             if (ScreenList[i3+1] > sv->X->aHEIGHT/2)
5712                Quad[i] = SUMA_LOWER_LEFT_SCREEN;
5713             else Quad[i] = SUMA_UPPER_LEFT_SCREEN;
5714          } else {
5715             if (ScreenList[i3+1] > sv->X->aHEIGHT/2)
5716                Quad[i] = SUMA_LOWER_RIGHT_SCREEN;
5717             else Quad[i] = SUMA_UPPER_RIGHT_SCREEN;
5718          }
5719       }
5720       if (LocalHead)
5721          fprintf (SUMA_STDOUT,
5722                   "%s: World: [%.2f %.2f %.2f] \t "
5723                   "Screen [%.2f %.2f %.2f] \t Quad %d\n",
5724                   FuncName,
5725                   WorldList[i3],WorldList[i3+1], WorldList[i3+2],
5726                   ScreenList[i3], ScreenList[i3+1],ScreenList[i3+2],
5727                   Quad?Quad[i]:-999);
5728 
5729    }
5730 
5731    if (ApplyXform) glPopMatrix();
5732 
5733    SUMA_RETURN (YUP);
5734 }
5735 
5736 /*
5737    Depth sorting of locations in NodeList
5738 
5739    All viewing matrices should be applied before this function is called
5740    Retruns sorting map, isrt (int *), such that NodeList[3*isrt[0]] is
5741    the location farthest from the eyeball.
5742 
5743    if (xform_NodeList) then NodeList's content is replaced with the
5744    screen projection coords.
5745 
5746    scrxyz (float *): Pointer to hold screen corrds version of
5747                      NodeList before any sorting. Pass NULL
5748                      to have the function use its static array.
5749 
5750 */
SUMA_DepthSort(float * NodeList,int N_Node,char ** names,int xform_NodeList,float * uscrxyz)5751 int * SUMA_DepthSort(float *NodeList, int N_Node, char **names,
5752                      int xform_NodeList, float *uscrxyz)
5753 {
5754    static char FuncName[]={"SUMA_DepthSort"};
5755    static float *scrxyz_loc=NULL;
5756    float *scrxyzR=NULL, *scrz=NULL, *scrxyz=NULL;
5757    static int N_alloc=-1;
5758    int ii, *isrt=NULL;
5759    SUMA_Boolean LocalHead = NOPE;
5760 
5761    SUMA_ENTRY;
5762 
5763    if (N_Node == -1) { /* cleanup call */
5764       SUMA_ifree(scrxyz_loc); N_alloc = -1;
5765       SUMA_RETURN(NULL);
5766    }
5767 
5768    if (!uscrxyz) {
5769       if (!scrxyz_loc || N_alloc != N_Node) {
5770          SUMA_ifree(scrxyz_loc);
5771          if (!(scrxyz_loc = (float *)SUMA_malloc(3*N_Node *sizeof(float)))) {
5772             SUMA_S_Critv("Failed to allocate for %d node XYZ vals\n", N_Node);
5773             SUMA_RETURN(NULL);
5774          }
5775          N_alloc = N_Node;
5776       }
5777       scrxyz = scrxyz_loc;
5778    } else {
5779       scrxyz = uscrxyz;
5780    }
5781 
5782    SUMA_World2ScreenCoordsF(NULL, N_Node, NodeList, scrxyz, NULL, NOPE, YUP);
5783    if (xform_NodeList) memcpy(NodeList, scrxyz, 3*N_Node*sizeof(float));
5784 
5785    if (LocalHead) { /* slower way for debugging */
5786       if (!(scrz = (float *)SUMA_malloc(N_Node *sizeof(float)))) {
5787          SUMA_S_Critv("Failed to allocate for %d node XYZ vals\n", N_Node);
5788          SUMA_RETURN(NULL);
5789       }
5790       for (ii=0; ii<N_Node; ++ii) {
5791          scrz[ii] = -scrxyz[3*ii+2];
5792       }
5793       isrt = SUMA_z_qsort (scrz, N_Node);
5794 
5795       scrxyzR = SUMA_freorder_triplets(scrxyz, isrt, N_Node);
5796 
5797       fprintf(stderr,"\nSorted %d objects, farthest first, closest last\n",
5798              N_Node);
5799       for (ii=0; ii<N_Node; ++ii) {
5800          fprintf(stderr,"Obj. %d, name %s, scr coords [%f %f %f], "
5801                         "orig coords [%f %f %f]\n",
5802                isrt[ii], names?names[isrt[ii]]:"NULL",
5803                scrxyzR[3*ii], scrxyzR[3*ii+1], scrxyzR[3*ii+2],
5804                NodeList[3*ii], NodeList[3*ii+1],NodeList[3*ii+2]);
5805       }
5806       SUMA_ifree(scrxyzR);
5807       SUMA_ifree(scrz);
5808    } else {
5809       if (uscrxyz) {/* don't ruin the screen array */
5810          if (!(scrz = (float *)SUMA_malloc(N_Node *sizeof(float)))) {
5811             SUMA_S_Critv("Failed to allocate for %d node XYZ vals\n", N_Node);
5812             SUMA_RETURN(NULL);
5813          }
5814          for (ii=0; ii<N_Node; ++ii) {
5815             scrz[ii] = -scrxyz[3*ii+2];
5816          }
5817          isrt = SUMA_z_qsort (scrz, N_Node);
5818          SUMA_ifree(scrz);
5819       } else {
5820          /* reuse scrxyz, only 1/3 will be used*/
5821          for (ii=0; ii<N_Node; ++ii) {
5822             scrxyz[ii] = -scrxyz[3*ii+2];
5823          }
5824          isrt = SUMA_z_qsort (scrxyz, N_Node);
5825       }
5826    }
5827 
5828 
5829    SUMA_RETURN(isrt);
5830 }
5831 
5832 /* Take normalized x,y screen corrdinates and turn them to world coordinates
5833 Based on code from SUMA_GetSelectionLine.
5834 If you need to set GL_MODELVIEW_MATRIX set ApplyXform to 1 and make sure
5835 sv is not NULL (otherwise sv is not needed.) See SUMA_World2ScreenCoords()
5836 for parallels.
5837 
5838 if ApplyXform = 0 function ASSUMES GL_MODELVIEW_MATRIX is current.
5839 
5840 GL_PROJECTION_MATRIX  is assumed set all the time.
5841 */
5842 
SUMA_NormScreenToWorld(SUMA_SurfaceViewer * sv,double xn,double yn,GLdouble * pfront,GLdouble * pback,int ApplyXform)5843 SUMA_Boolean SUMA_NormScreenToWorld(SUMA_SurfaceViewer *sv,
5844                                     double xn, double yn,
5845                                     GLdouble *pfront, GLdouble *pback,
5846                                     int ApplyXform)
5847 {
5848    static char FuncName[]={"SUMA_NormScreenToWorld"};
5849    GLfloat rotationMatrix[4][4];
5850    GLdouble ox, oy;
5851    GLint viewport[4];
5852    GLdouble mvmatrix[16], projmatrix[16];
5853 
5854    SUMA_Boolean LocalHead=NOPE;
5855 
5856    SUMA_ENTRY;
5857 
5858    if (ApplyXform) {
5859       if (!sv) SUMA_S_Err("Need sv with ApplyXform");
5860       SUMA_LH("Forcing setting of GL_MODELVIEW_MATRIX and GL_PROJECTION_MATRIX");
5861       /* go through the ModelView transforms as you would
5862          in display since the modelview matrix is popped
5863          after each display call */
5864       SUMA_build_rotmatrix(rotationMatrix, sv->GVS[sv->StdView].currentQuat);
5865       glMatrixMode(GL_MODELVIEW);
5866          glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix);
5867          if (LocalHead) {
5868             int itmp = 0;
5869             fprintf (SUMA_STDERR, "%s: Initial Modelview:\nMV=[ ", FuncName);
5870             while (itmp < 16) {
5871                fprintf (SUMA_STDERR, "%.4f, ", mvmatrix[itmp]); ++itmp;}
5872             fprintf (SUMA_STDERR, "]\n");
5873          }
5874       glPushMatrix();
5875       glTranslatef ( sv->GVS[sv->StdView].translateVec[0],
5876                      sv->GVS[sv->StdView].translateVec[1], 0.0);
5877       glTranslatef ( sv->GVS[sv->StdView].RotaCenter[0],
5878                      sv->GVS[sv->StdView].RotaCenter[1],
5879                      sv->GVS[sv->StdView].RotaCenter[2]);
5880       glMultMatrixf(&rotationMatrix[0][0]);
5881       glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix);
5882          if (LocalHead) {
5883             int itmp = 0;
5884             fprintf (SUMA_STDERR,
5885                      "%s: Modelview After Translation & Rotation:\nMVtr=[ ",
5886                      FuncName);
5887             while (itmp < 16) {
5888                fprintf (SUMA_STDERR, "%.4f, ", mvmatrix[itmp]); ++itmp;}
5889             fprintf (SUMA_STDERR, "]\n");
5890          }
5891       glTranslatef ( -sv->GVS[sv->StdView].RotaCenter[0],
5892                      -sv->GVS[sv->StdView].RotaCenter[1],
5893                      -sv->GVS[sv->StdView].RotaCenter[2]);
5894    }
5895 
5896    glGetIntegerv(GL_VIEWPORT, viewport);
5897    glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix);
5898    glGetDoublev(GL_PROJECTION_MATRIX, projmatrix);
5899 
5900    /* get OpenGL screen coords */
5901    ox = xn*(double)viewport[2];
5902    oy = yn*(double)viewport[3];
5903 
5904    /* unproject to world */
5905    if (pfront) {
5906       gluUnProject(  ox, oy, 0.0,
5907                      mvmatrix, projmatrix, viewport,
5908                      pfront, pfront+1, pfront+2);
5909    }
5910    if (pback) {
5911       gluUnProject(  ox, oy, 1.0,
5912                      mvmatrix, projmatrix, viewport,
5913                      pback, pback+1, pback+2);
5914    }
5915 
5916    SUMA_LHv("Normalized screen coords: [%.4f %.4f]\n"
5917             "OpenGl screen coords: [%.4f %.4f]\n"
5918             "pfront (%p): [%.4f %.4f %.4f]\n"
5919             "pback  (%p): [%.4f %.4f %.4f]\n",
5920             xn, yn, ox, oy,
5921             pfront, pfront ? pfront[0] : 0 ,
5922                     pfront ? pfront[1] : 0 ,
5923                     pfront ? pfront[2] : 0 ,
5924             pback,  pback  ? pback[0] : 0 ,
5925                     pback  ? pback[1] : 0 ,
5926                     pback  ? pback[2] : 0 );
5927 
5928    if (ApplyXform)  glPopMatrix();
5929    SUMA_RETURN(YUP);
5930 }
5931 /*!
5932    Purpose: Takes a the x,y positions of the cursor and sets
5933             the Pick0 and Pick1 values (usually sv's)
5934    \param sv (*SUMA_SurfaceViewer)
5935    \param x (int) mouse coordinate
5936    \param y (int) (y will get set to: viewport[3] - (GLint)y -1;
5937                    inside of function)
5938    \param Pick0 (GLdouble *) vector of 3 elements (usually, pass sv->Pick0)
5939    \param Pick1 (GLdouble *) vector of 3 elements (usually, pass sv->Pick1)
5940    \param N_List (int) if > 0, it indicates that there are N_list
5941                        other mouse coordinates to consider
5942                        in addition to the y and y above.
5943    \param xList (int *) a vector of N_list x values
5944    \param yList (int *) a vector of N_list y values
5945    \param PickList (Gldouble *) a N_list x 3 vector containing the equivalent
5946                                 of Pick0 for the values in xList and yList
5947    \return YUP/NOPE
5948       Also, if N_List <= 0, sv->PickPix is set before returning
5949    \sa SUMA_input, button3 pick
5950    \sa SUMA_NormScreenToWorld
5951 */
SUMA_GetSelectionLine(SUMA_SurfaceViewer * sv,int x,int y,GLdouble * Pick0,GLdouble * Pick1,int N_List,int * xList,int * yList,GLdouble * Pick0List)5952 SUMA_Boolean SUMA_GetSelectionLine (SUMA_SurfaceViewer *sv, int x, int y,
5953                                     GLdouble *Pick0, GLdouble *Pick1,
5954                                     int N_List, int *xList, int *yList,
5955                                     GLdouble *Pick0List)
5956 {
5957    static char FuncName[]={"SUMA_GetSelectionLine"};
5958    GLfloat rotationMatrix[4][4];
5959    GLint viewport[4];
5960    GLdouble mvmatrix[16], projmatrix[16];
5961    GLint realy; /* OpenGL y coordinate position */
5962    char CommString[100];
5963    int isv=-1;
5964    char buf[32];
5965    SUMA_Boolean LocalHead = NOPE;
5966 
5967    SUMA_ENTRY;
5968 
5969 
5970 
5971    if (LocalHead) {
5972       fprintf (SUMA_STDERR,
5973                "%s: Selection x, y=[%d, %d]\n",
5974                FuncName, x, y);
5975       fprintf (SUMA_STDERR,
5976                "%s: Current Quat: %.4f, %.4f, %.4f, %.4f.\n",
5977                 FuncName,
5978                 sv->GVS[sv->StdView].currentQuat[0],
5979                 sv->GVS[sv->StdView].currentQuat[1],
5980                 sv->GVS[sv->StdView].currentQuat[2],
5981                 sv->GVS[sv->StdView].currentQuat[3]);
5982       fprintf (SUMA_STDERR,
5983                "%s: Translation Vector of view #%d: %.4f, %.4f, %.4f\n",
5984                FuncName, sv->StdView, sv->GVS[sv->StdView].translateVec[0],
5985                sv->GVS[sv->StdView].translateVec[1],
5986                sv->GVS[sv->StdView].translateVec[2]);
5987       fprintf (SUMA_STDERR,
5988                "%s: RotaCenter of view #%d: %.4f, %.4f, %.4f\n",
5989                FuncName, sv->StdView, sv->GVS[sv->StdView].RotaCenter[0],
5990                sv->GVS[sv->StdView].RotaCenter[1],
5991                sv->GVS[sv->StdView].RotaCenter[2]);
5992    }
5993 
5994 
5995    /* go through the ModelView transforms as you would in
5996       display since the modelview matrix is popped
5997       after each display call */
5998    SUMA_build_rotmatrix(rotationMatrix, sv->GVS[sv->StdView].currentQuat);
5999    glMatrixMode(GL_MODELVIEW);
6000    /* BEFORE April 2013
6001       The next line (which was glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix))
6002       appears to fix some bug with GL_MODELVIEW's matrix.
6003       When you clicked button3 for the first time in a viewer,
6004       the chosen point was off. The next click in the identical position would
6005       select the correct point and subsequent clicks are OK.
6006       None of the parameters used for the selection would change between the
6007       first click and the next but it appears that going from one
6008       viewer to the next caused GL_MODELVIEW to change (sometimes) slightly.
6009       Putting the line glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix);
6010       to check (and debug) what was happening to GL_MODELVIEW matrix between one
6011       viewer and the next fixed the clicking problem. So, we keep
6012       it here as a fix until a better one comes along.
6013       PS: This was also the source of the Z (blue) eye axis showing up when
6014       it should have not.
6015          glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix);
6016 
6017       AFTER April 2013,
6018       The glGetDoublev is now replaced with the call to glXMakeCurrent
6019       I was having a similar first selection problem (the  GL_MODELVIEW)
6020       was getting screwed up as I clicked right after the surface controller
6021       notebook page was changed. For some reason, the context was no longer
6022       current or correct when the window manager had to manage widgets
6023       outside of the GLX area.
6024 
6025       AFTER Nov 2013,
6026       Now calling SUMA_glXMakeCurrent with force context setting
6027    */
6028       isv =  SUMA_WhichSV (sv, SUMAg_SVv, SUMAg_N_SVv);
6029       sprintf(buf,"GLXAREA of sv %d", isv);
6030       if (!SUMA_glXMakeCurrent (sv->X->DPY, XtWindow(sv->X->GLXAREA),
6031                            sv->X->GLXCONTEXT, FuncName, buf, 1)) {
6032                fprintf (SUMA_STDERR,
6033                         "Error %s: Failed in SUMA_glXMakeCurrent.\n"
6034                         " \tContinuing ...\n", FuncName);
6035                SUMA_GL_ERRS;
6036       }
6037       if (LocalHead) {
6038          int itmp = 0;
6039          fprintf (SUMA_STDERR,
6040                   "%s: Initial Modelview:\nMV=[ ", FuncName);
6041          while (itmp < 16) {
6042             fprintf (SUMA_STDERR, "%.4f, ", mvmatrix[itmp]); ++itmp;}
6043          fprintf (SUMA_STDERR, "]\n");
6044       }
6045    glPushMatrix();
6046    glTranslatef ( sv->GVS[sv->StdView].translateVec[0],
6047                   sv->GVS[sv->StdView].translateVec[1], 0.0);
6048    glTranslatef ( sv->GVS[sv->StdView].RotaCenter[0],
6049                   sv->GVS[sv->StdView].RotaCenter[1],
6050                   sv->GVS[sv->StdView].RotaCenter[2]);
6051    glMultMatrixf(&rotationMatrix[0][0]);
6052       glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix);
6053       if (LocalHead) {
6054          int itmp = 0;
6055          fprintf (SUMA_STDERR,
6056                   "%s: Modelview After Translation & Rotation:\nMVtr=[ ",
6057                   FuncName);
6058          while (itmp < 16) {
6059             fprintf (SUMA_STDERR, "%.4f, ", mvmatrix[itmp]); ++itmp;}
6060          fprintf (SUMA_STDERR, "]\n");
6061       }
6062    glTranslatef ( -sv->GVS[sv->StdView].RotaCenter[0],
6063                   -sv->GVS[sv->StdView].RotaCenter[1],
6064                   -sv->GVS[sv->StdView].RotaCenter[2]);
6065 
6066    glGetIntegerv(GL_VIEWPORT, viewport);
6067    glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix);
6068    glGetDoublev(GL_PROJECTION_MATRIX, projmatrix);
6069    /* viewport[3] is height of window in pixels */
6070    realy = viewport[3] - (GLint)y -1;
6071 
6072    if (N_List <=0 ) {
6073       /* store selection location in pixel indices into frame buffer */
6074       sv->PickPix[0] = (int)x; sv->PickPix[1]=(int)realy;
6075    }
6076 
6077    if (LocalHead)
6078       fprintf (SUMA_STDOUT,
6079                "%s: Coordinates at cursor are (%4d, %4d)\n"
6080                "Viewport is %d %d %d %d\n"
6081                "Normalized coords: (%.3f %.3f)\n",
6082                FuncName, x, realy,
6083                viewport[0], viewport[1], viewport[2], viewport[3],
6084                (double)x/(double)viewport[2], (double)y/viewport[3]);
6085 
6086    /* set the pick points at both ends of the clip planes */
6087    if (Pick0) {
6088       gluUnProject(  (GLdouble)x, (GLdouble)realy, 0.0,
6089                      mvmatrix, projmatrix, viewport,
6090                      &(Pick0[0]), &(Pick0[1]), &(Pick0[2]));
6091       if (LocalHead)
6092          fprintf (SUMA_STDOUT,
6093                   "World Coords at z=0.0 (near clip plane) are (%f, %f, %f)\n",
6094                  (Pick0[0]), (Pick0[1]), (Pick0[2]));
6095    }
6096    if (Pick1) {
6097       gluUnProject(  (GLdouble)x, (GLdouble)realy, 1.0,
6098                      mvmatrix, projmatrix, viewport,
6099                      &(Pick1[0]), &(Pick1[1]), &(Pick1[2]));
6100       if (LocalHead)
6101          fprintf (SUMA_STDOUT,
6102                   "World Coords at z=1.0 (far clip plane) are (%f, %f, %f)\n",
6103                   (Pick1[0]), (Pick1[1]), (Pick1[2]));
6104    }
6105 
6106    if (N_List > 0) {
6107       SUMA_LH("Doing the list thing");
6108       if (!Pick0List || !xList || !yList) {
6109          SUMA_S_Err( "Null Pick0List or xlist or ylist with non 0 N_List.\n"
6110                      "PickList ignored."); }
6111       else {
6112          int i, i3;
6113          for (i=0; i<N_List; ++i) {
6114             i3 = 3*i;
6115             realy = viewport[3] - (GLint)yList[i] -1;
6116             gluUnProject((GLdouble)xList[i], (GLdouble)realy, 0.0,
6117                            mvmatrix, projmatrix, viewport,
6118                            &(Pick0List[i3+0]), &(Pick0List[i3+1]),
6119                            &(Pick0List[i3+2]));
6120          }
6121       }
6122    }
6123    glPopMatrix();
6124 
6125    SUMA_RETURN (YUP);
6126 }
6127 
6128 /*!
6129    \brief Draws a line between screen (window) coordinates
6130 */
SUMA_DrawWindowLine(SUMA_SurfaceViewer * sv,int x0,int y0,int x1,int y1,int meth)6131 SUMA_Boolean SUMA_DrawWindowLine(SUMA_SurfaceViewer *sv,
6132                                  int x0, int y0,
6133                                  int x1, int y1, int meth)
6134 {
6135    static char FuncName[]={"SUMA_DrawWindowLine"};
6136    GLfloat rotationMatrix[4][4];
6137    static GLfloat LineCol[]={ SUMA_RED_GL };
6138    static int xlist[2], ylist[2];
6139    GLdouble Pick0[3], Pick1[3], PickList[6];
6140    static GLfloat NoColor[] = {0.0, 0.0, 0.0, 0.0};
6141    SUMA_Boolean LocalHead  = NOPE;
6142    SUMA_ENTRY;
6143 
6144    if (meth == 0) {
6145       static int nwarn=0;
6146       if (!nwarn) {
6147          SUMA_S_Warn("meth = 0 no longer allowed because of"
6148                      "troubles with X->gc, on macs.");
6149          ++nwarn;
6150       }
6151       meth = 1;
6152    }
6153    switch (meth) {
6154       case 0: /* does not work on OSX !!!*/
6155          XDrawLine (sv->X->DPY, XtWindow(sv->X->GLXAREA), sv->X->gc,
6156            (int)x0, (int)y0,
6157            (int)x1, (int)y1);
6158          break;
6159       case 1:
6160          SUMA_build_rotmatrix(rotationMatrix, sv->GVS[sv->StdView].currentQuat);
6161          xlist[0] = x0; xlist[1] = x1;
6162          ylist[0] = y0; ylist[1] = y1;
6163          SUMA_GetSelectionLine ( sv, x0, y0,
6164                                  NULL, NULL,
6165                                  2,
6166                                  xlist, ylist,
6167                                  PickList);
6168          SUMA_SET_GL_PROJECTION(sv, sv->ortho);
6169          SUMA_SET_GL_MODELVIEW(sv);
6170          glMaterialfv(GL_FRONT, GL_EMISSION, LineCol);
6171          glLineWidth(SUMA_CROSS_HAIR_LINE_WIDTH);
6172          if (LocalHead) {
6173             fprintf( SUMA_STDERR,
6174                      "%s:PickList\n"
6175                      "[%.3f %.3f %.3f\n %.3f %.3f %.3f]\n",
6176                      FuncName,
6177                      PickList[0],PickList[1],PickList[2],
6178                      PickList[3], PickList[4],PickList[5] );
6179          }
6180          glBegin(GL_LINES);
6181          glVertex3d(PickList[0], PickList[1], PickList[2]-0.001);
6182                   /* something to do with clipping ...*/
6183          glVertex3d(PickList[3], PickList[4], PickList[5]-0.001);
6184          glVertex3d(PickList[0], PickList[1], PickList[2]+0.001);
6185                   /* something to do with clipping ...*/
6186          glVertex3d(PickList[3], PickList[4], PickList[5]+0.001);
6187          glEnd();
6188          glMaterialfv(GL_FRONT, GL_EMISSION, NoColor);
6189          glPopMatrix();
6190          SUMA_GLX_BUF_SWAP(sv);
6191          break;
6192       default:
6193          break;
6194    }
6195 
6196    SUMA_RETURN(YUP);
6197 }
6198 
6199 
6200 /*!
6201    \brief A call back to open the help window
6202    No input parameters needed
6203 */
SUMA_cb_helpUsage(Widget w,XtPointer data,XtPointer callData)6204 void SUMA_cb_helpUsage (Widget w, XtPointer data, XtPointer callData)
6205 {
6206    static char FuncName[] = {"SUMA_cb_helpUsage"};
6207    DList *list = NULL;
6208 
6209    SUMA_ENTRY;
6210    if (!list) list = SUMA_CreateList();
6211    SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_Help, SES_Suma, NULL);
6212    if (!SUMA_Engine (&list)) {
6213       fprintf(stderr, "Error %s: SUMA_Engine call failed.\n", FuncName);
6214    }
6215 
6216    SUMA_RETURNe;
6217 
6218 }
6219 
SUMA_cb_helpWeb(Widget w,XtPointer data,XtPointer callData)6220 void SUMA_cb_helpWeb (Widget w, XtPointer data, XtPointer callData)
6221 {
6222    static char FuncName[] = {"SUMA_cb_helpWeb"};
6223 
6224    SUMA_ENTRY;
6225     whereami_browser("https://afni.nimh.nih.gov/pub/dist/doc/htmldoc/SUMA/Viewer.html");
6226     //whereami_browser("https://afni.nimh.nih.gov/pub/dist/doc/htmldoc/sumatoc1.html");
6227 
6228    SUMA_RETURNe;
6229 
6230 }
6231 
6232 /*!
6233    \brief A call back to open the Message Log window
6234    No input parameters needed
6235 */
SUMA_cb_helpMessageLog(Widget w,XtPointer data,XtPointer callData)6236 void SUMA_cb_helpMessageLog (Widget w, XtPointer data, XtPointer callData)
6237 {
6238    static char FuncName[] = {"SUMA_cb_helpMessageLog"};
6239    DList *list = NULL;
6240 
6241    SUMA_ENTRY;
6242    if (!list) list = SUMA_CreateList();
6243    SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_Log, SES_Suma, NULL);
6244    if (!SUMA_Engine (&list)) {
6245       fprintf(stderr, "Error %s: SUMA_Engine call failed.\n", FuncName);
6246    }
6247 
6248    SUMA_RETURNe;
6249 
6250 }
6251 
6252 /*!
6253    \brief A call back to open the viewer Info window
6254    Exepcts the index of the viewer in SUMAg_SVv in data->ContID
6255 */
SUMA_cb_helpViewerStruct(Widget w,XtPointer data,XtPointer callData)6256 void SUMA_cb_helpViewerStruct (Widget w, XtPointer data, XtPointer callData)
6257 {
6258    static char FuncName[] = {"SUMA_cb_helpViewerStruct"};
6259    SUMA_MenuCallBackData *datap=NULL;
6260    SUMA_SurfaceViewer *sv = NULL;
6261 
6262    SUMA_ENTRY;
6263 
6264    datap = (SUMA_MenuCallBackData *)data;
6265    sv = &(SUMAg_SVv[(INT_CAST)datap->ContID]);
6266 
6267    if (!sv->X->ViewCont->TopLevelShell) { /* see comments on similar section in
6268                                              SUMA_cb_helpSurfaceStruct */
6269       SUMA_cb_createViewerCont( w, (XtPointer)sv, callData);
6270       SUMA_cb_closeViewerCont ( w, (XtPointer)sv, callData);
6271    }
6272    /* Now do the info thingy */
6273    SUMA_cb_moreViewerInfo (w, (XtPointer)sv, callData);
6274 
6275 
6276    SUMA_RETURNe;
6277 
6278 }
6279 
6280 /*!
6281    \brief A call back to open the surface Info window
6282    Exepcts the index of the viewer in SUMAg_SVv in data->ContID
6283 */
SUMA_cb_helpSurfaceStruct(Widget w,XtPointer data,XtPointer callData)6284 void SUMA_cb_helpSurfaceStruct (Widget w, XtPointer data, XtPointer callData)
6285 {
6286    static char FuncName[] = {"SUMA_cb_helpSurfaceStruct"};
6287    SUMA_MenuCallBackData *datap=NULL;
6288    SUMA_SurfaceViewer *sv = NULL;
6289    SUMA_ALL_DO *ado = NULL;
6290 
6291    SUMA_ENTRY;
6292 
6293    datap = (SUMA_MenuCallBackData *)data;
6294    sv = &(SUMAg_SVv[(INT_CAST)datap->ContID]);
6295    if (!(ado = SUMA_SV_Focus_ADO(sv))) {
6296       SUMA_SLP_Err("No object in focus.\n");
6297       SUMA_RETURNe;
6298    }
6299 
6300    if (!SUMA_isADO_Cont_Realized(ado)) {
6301       SUMA_OpenCloseSurfaceCont(NULL, ado, NULL);
6302    }
6303 
6304    /* Now do the info thingy */
6305    SUMA_cb_moreSurfInfo (w,
6306          (XtPointer)SUMA_Cont_ADO(SUMA_ADO_Cont(ado)), callData);
6307 
6308    SUMA_RETURNe;
6309 
6310 }
6311 
SUMA_cb_helpSUMAGlobal(Widget w,XtPointer data,XtPointer callData)6312 void SUMA_cb_helpSUMAGlobal (Widget w, XtPointer data, XtPointer callData)
6313 {
6314    static char FuncName[] = {"SUMA_cb_helpSUMAGlobal"};
6315 
6316    SUMA_ENTRY;
6317 
6318    if (!SUMAg_CF->X->SumaCont->AppShell) { /* create */
6319       SUMA_cb_createSumaCont( w, data, callData);
6320       SUMA_cb_closeSumaCont ( w, data, callData);
6321    }
6322 
6323    /* Now open the info thingy */
6324    SUMA_cb_moreSumaInfo (w, data, callData);
6325 
6326    SUMA_RETURNe;
6327 }
6328 
6329 /*!
6330  function to toggle the IOnotify debugging flag
6331  - expects nothing
6332 */
SUMA_cb_helpIO_notify(Widget w,XtPointer data,XtPointer callData)6333 void SUMA_cb_helpIO_notify(Widget w, XtPointer data, XtPointer callData)
6334 {
6335    static char FuncName[] = {"SUMA_cb_helpIO_notify"};
6336    int ii;
6337 
6338    SUMA_ENTRY;
6339 
6340    SUMA_INOUT_NOTIFY_TOGGLE;
6341 
6342    /* must update the state of toggle buttons in otherviewers */
6343    for (ii=0; ii<SUMAg_N_SVv; ++ii) {
6344       if (!SUMAg_SVv[ii].isShaded && SUMAg_SVv[ii].X->TOPLEVEL) {
6345          /* you must check for both conditions because by default
6346          all viewers are initialized to isShaded = NOPE,
6347          even before they are ever opened */
6348          if (w != SUMAg_SVv[ii].X->HelpMenu->mw[SW_HelpIONotify]) {
6349             XmToggleButtonSetState (
6350                SUMAg_SVv[ii].X->HelpMenu->mw[SW_HelpIONotify],
6351                SUMAg_CF->InOut_Notify, NOPE);
6352          }
6353       }
6354    }
6355 
6356 
6357    SUMA_RETURNe;
6358 }
6359 
SUMA_setIO_notify(int val)6360 void SUMA_setIO_notify(int val)
6361 {
6362    static char FuncName[] = {"SUMA_setIO_notify"};
6363    int ii;
6364 
6365    SUMA_ENTRY;
6366 
6367    if (val) {SUMA_INOUT_NOTIFY_ON;}
6368    else { SUMA_INOUT_NOTIFY_OFF;}
6369 
6370    /* must update the state of toggle buttons in otherviewers */
6371    for (ii=0; ii<SUMAg_N_SVv; ++ii) {
6372       if (!SUMAg_SVv[ii].isShaded && SUMAg_SVv[ii].X->TOPLEVEL) {
6373          /* you must check for both conditions because by default
6374          all viewers are initialized to isShaded = NOPE,
6375          even before they are ever opened */
6376          {
6377             XmToggleButtonSetState (
6378                SUMAg_SVv[ii].X->HelpMenu->mw[SW_HelpIONotify],
6379                SUMAg_CF->InOut_Notify, NOPE);
6380          }
6381       }
6382    }
6383 
6384    SUMA_RETURNe;
6385 }
6386 
6387 /*!
6388  function to echo key presses that reach SUMA
6389  - expects nothing
6390 */
SUMA_cb_helpEchoKeyPress(Widget w,XtPointer data,XtPointer callData)6391 void SUMA_cb_helpEchoKeyPress(Widget w, XtPointer data, XtPointer callData)
6392 {
6393    static char FuncName[] = {"SUMA_cb_helpEchoKeyPress"};
6394    int ii;
6395 
6396    SUMA_ENTRY;
6397 
6398    SUMA_ECHO_KEYPRESS_TOGGLE;
6399 
6400    /* must update the state of toggle buttons in otherviewers */
6401    for (ii=0; ii<SUMAg_N_SVv; ++ii) {
6402       if (!SUMAg_SVv[ii].isShaded && SUMAg_SVv[ii].X->TOPLEVEL) {
6403          /* you must check for both conditions because by default
6404          all viewers are initialized to isShaded = NOPE,
6405          even before they are ever opened */
6406          if (w != SUMAg_SVv[ii].X->HelpMenu->mw[SW_HelpEchoKeyPress]) {
6407             XmToggleButtonSetState (
6408                SUMAg_SVv[ii].X->HelpMenu->mw[SW_HelpEchoKeyPress],
6409                SUMAg_CF->Echo_KeyPress, NOPE);
6410          }
6411       }
6412    }
6413 
6414 
6415    SUMA_RETURNe;
6416 }
6417 
SUMA_setEcho_KeyPress(int val)6418 void SUMA_setEcho_KeyPress(int val)
6419 {
6420    static char FuncName[] = {"SUMA_setEcho_KeyPress"};
6421    int ii;
6422 
6423    SUMA_ENTRY;
6424 
6425    if (val) {SUMA_ECHO_KEYPRESS_ON;}
6426    else { SUMA_ECHO_KEYPRESS_OFF;}
6427 
6428    /* must update the state of toggle buttons in otherviewers */
6429    for (ii=0; ii<SUMAg_N_SVv; ++ii) {
6430       if (!SUMAg_SVv[ii].isShaded && SUMAg_SVv[ii].X->TOPLEVEL) {
6431          /* you must check for both conditions because by default
6432          all viewers are initialized to isShaded = NOPE,
6433          even before they are ever opened */
6434          {
6435       XmToggleButtonSetState (
6436             SUMAg_SVv[ii].X->HelpMenu->mw[SW_HelpEchoKeyPress],
6437                SUMAg_CF->Echo_KeyPress, NOPE);
6438          }
6439       }
6440    }
6441 
6442    SUMA_RETURNe;
6443 }
6444 
6445 /*!
6446  function to toggle the Memtrace debugging flag
6447  - expects nothing
6448 */
SUMA_cb_helpMemTrace(Widget w,XtPointer data,XtPointer callData)6449 void SUMA_cb_helpMemTrace(Widget w, XtPointer data, XtPointer callData)
6450 {
6451    static char FuncName[] = {"SUMA_cb_helpIO_notify"};
6452    int ii;
6453 
6454    SUMA_ENTRY;
6455 
6456    SUMA_MEMTRACE_TOGGLE;
6457 
6458    /* must update the state of toggle buttons in otherviewers */
6459    for (ii=0; ii<SUMAg_N_SVv; ++ii) {
6460       if (!SUMAg_SVv[ii].isShaded && SUMAg_SVv[ii].X->TOPLEVEL) {
6461          /* you must check for both conditions because by default
6462          all viewers are initialized to isShaded = NOPE,
6463          even before they are ever opened */
6464          XmToggleButtonSetState (
6465             SUMAg_SVv[ii].X->HelpMenu->mw[SW_HelpMemTrace],
6466             SUMAg_CF->MemTrace, NOPE);
6467          if (SUMAg_CF->MemTrace) {
6468             /* can't turn it off */
6469              XtSetSensitive (SUMAg_SVv[ii].X->HelpMenu->mw[SW_HelpMemTrace], 0);
6470          }
6471       }
6472    }
6473 
6474    SUMA_RETURNe;
6475 }
6476 
6477 /*!
6478    \brief callback to open SUMA 's Controller
6479    No input parameters needed
6480 */
SUMA_cb_viewSumaCont(Widget w,XtPointer data,XtPointer callData)6481 void SUMA_cb_viewSumaCont(Widget w, XtPointer data, XtPointer callData)
6482 {
6483    static char FuncName[] = {"SUMA_cb_viewSumaCont"};
6484    Boolean LocalHead = NOPE;
6485 
6486    SUMA_ENTRY;
6487 
6488    SUMA_viewSumaCont(1);
6489 
6490    SUMA_RETURNe;
6491 }
6492 
SUMA_viewSumaCont(int flag)6493 int SUMA_viewSumaCont(int flag)
6494 {
6495    static char FuncName[] = {"SUMA_viewSumaCont"};
6496    Boolean LocalHead = NOPE;
6497 
6498    SUMA_ENTRY;
6499 
6500    if (flag == 1) { /* want it visible */
6501       SUMA_LH("Visibilizing");
6502       if (!SUMAg_CF->X->SumaCont->AppShell) { /* create */
6503          if (LocalHead)
6504             fprintf (SUMA_STDERR,"%s: creating controller \n", FuncName);
6505          SUMA_cb_createSumaCont( NULL, NULL, NULL);
6506       }else {
6507          /* controller already created, need to bring it up again */
6508          switch (SUMA_CLOSE_MODE)   {/* No open GL drawables in this widget*/
6509             case SUMA_WITHDRAW:
6510                if (LocalHead)
6511                   fprintf (SUMA_STDERR,
6512                            "%s: raising SUMA controller \n", FuncName);
6513                XMapRaised(SUMAg_CF->X->DPY_controller1,
6514                            XtWindow(SUMAg_CF->X->SumaCont->AppShell));
6515                break;
6516             default:
6517                SUMA_S_Err("Not ready to deal with this closing mode");
6518                SUMA_RETURN(0);
6519                break;
6520          }
6521       }
6522 
6523       SUMA_PositionWindowRelative ( SUMAg_CF->X->SumaCont->AppShell,
6524                                     SUMAg_SVv[0].X->TOPLEVEL, SWP_TOP_RIGHT);
6525    } else {
6526       /* want it minimized */
6527       SUMA_cb_closeSumaCont ( NULL, NULL, NULL);
6528    }
6529 
6530    SUMA_RETURN(1);
6531 }
6532 
6533 
SUMA_isSurfContWidgetCreated(SUMA_X_SurfCont * SurfCont)6534 SUMA_Boolean SUMA_isSurfContWidgetCreated(SUMA_X_SurfCont  *SurfCont)
6535 {
6536    static char FuncName[]={"SUMA_isSurfContWidgetCreated"};
6537    if (!SurfCont || !SurfCont->TLS) return(0);
6538    return(1);
6539 }
6540 
6541 /* Open the surface controller if other had been open already
6542    This is only for the single window mode */
SUMA_OpenSurfCont_if_other(Widget w,SUMA_ALL_DO * ado,SUMA_SurfaceViewer * sv)6543 int SUMA_OpenSurfCont_if_other(Widget w,
6544                               SUMA_ALL_DO *ado,
6545                               SUMA_SurfaceViewer *sv)
6546 {
6547    static char FuncName[]={"SUMA_OpenSurfCont_if_other"};
6548    SUMA_X_SurfCont *SurfCont=NULL;
6549    SUMA_Boolean LocalHead=NOPE;
6550 
6551    SUMA_ENTRY;
6552 
6553    if (!SUMAg_CF->X->UseSameSurfCont) { SUMA_RETURN(1); /* only in same mode */ }
6554    if (!(SurfCont=SUMA_ADO_Cont(ado))) SUMA_RETURN(0); /* bad */
6555    if (!SUMAg_CF->X->SameSurfContOpen) { /* window not on screen, do nothing */
6556       SUMA_RETURN(0);
6557    }
6558    /* OK, bring it up if needed */
6559    if (SUMA_isADO_Cont_Realized(ado)) SUMA_RETURN(1); /* nothing to do */
6560 
6561    if (0 && w) {/* no need, using  SameSurfContOpen instead*/
6562       XWindowAttributes winattr;
6563       XGetWindowAttributes(XtDisplay(w), XtWindow(w), &winattr);
6564       SUMA_LHv("Window map_state: %d\n", winattr.map_state);
6565    }
6566 
6567    if (!SUMA_viewSurfaceCont(w, ado, sv)) {
6568       SUMA_S_Err("Failed to view surface cont");
6569       SUMA_RETURN(0);
6570    }
6571 
6572    SUMA_RETURN(1);
6573 }
6574 
6575 /* Many times you need the surface controller created but not for
6576 display, create it if needed, then minimize it immediately afterwards*/
SUMA_OpenCloseSurfaceCont(Widget w,SUMA_ALL_DO * ado,SUMA_SurfaceViewer * sv)6577 int SUMA_OpenCloseSurfaceCont(Widget w,
6578                               SUMA_ALL_DO *ado,
6579                               SUMA_SurfaceViewer *sv)
6580 {
6581    static char FuncName[]={"SUMA_OpenCloseSurfaceCont"};
6582    SUMA_X_SurfCont *SurfCont=NULL;
6583    SUMA_Boolean LocalHead=NOPE;
6584 
6585    SUMA_ENTRY;
6586 
6587    if (!(SurfCont=SUMA_ADO_Cont(ado))) SUMA_RETURN(0);
6588 
6589    if (SUMA_isADO_Cont_Realized(ado)) SUMA_RETURN(1); /* nothing to do */
6590 
6591    if (w) {
6592       SUMA_LH("nism");
6593       SUMA_cb_createSurfaceCont( w, (XtPointer)ado, NULL);
6594    } else {
6595       if (!sv) {
6596          if (!(sv = SUMA_BestViewerForADO(ado)) ||
6597              !sv->X->TOPLEVEL) {
6598             SUMA_LH("NULLity");
6599             SUMA_RETURN(0);
6600          }
6601       }
6602       if (!SUMA_isADO_Cont_Created(ado)) {
6603         SUMA_LH("Creationism");
6604         SUMA_cb_createSurfaceCont( sv->X->TOPLEVEL, (XtPointer)ado, NULL);
6605       } else {
6606         /* must have been closed, open it */
6607         if (!SUMA_viewSurfaceCont( sv->X->TOPLEVEL, ado, sv)) {
6608            SUMA_S_Err("Failed to open surf cont anew");
6609            SUMA_RETURN(0);
6610         }
6611       }
6612    }
6613    SUMA_LH("Initializing ColPaneShell");
6614    SUMA_InitializeColPlaneShell(ado, SUMA_ADO_CurColPlane(ado));
6615 
6616 
6617    /* Now close it quick. Maybe should put a delayed closing for nicer effect */
6618    if (!SUMAg_CF->X->UseSameSurfCont) { /* Don't minimize when using one surfcont
6619                                           it is more annoying than useful */
6620       SUMA_LH("Closism")
6621       #if 0 /* Not a good idea to do this because widgets get unrealized and
6622            The main reason for calling this function is to be sure that
6623            the widgets are alive and well for setting and queries ZSS Nov 9 2012 */
6624       SUMA_cb_closeSurfaceCont(NULL, (XtPointer) ado, NULL);
6625       #else
6626       XIconifyWindow(SUMAg_CF->X->DPY_controller1, XtWindow(SurfCont->TLS), 0);
6627       #endif
6628    }
6629 
6630    SUMA_LH("Returnism")
6631    SUMA_RETURN(1);
6632 }
6633 
6634 /*!
6635    Get a listing of all surfaces in the surface controller notebook pages
6636    You'll have to change the returned pointer someday to allow
6637    for other objects that may have a page in Notebook...
6638 
6639    I think this function needs to be updated to include tracts, volumes, and CIFTI datasets.
6640 */
SUMA_DOsInSurfContNotebook(Widget NB)6641 SUMA_ALL_DO **SUMA_DOsInSurfContNotebook(Widget NB)
6642 {
6643    static char FuncName[]={"SUMA_DOsInSurfContNotebook"};
6644    int i, lp, j, iso;
6645    static SUMA_ALL_DO *DOv[SUMA_MAX_SURF_ON_COMMAND];
6646    SUMA_ALL_DO *DOt=NULL, *curDO=NULL;
6647    XmNotebookPageStatus ns;
6648    XmNotebookPageInfo pi;
6649    char *allids = NULL;
6650    SUMA_X_SurfCont *SurfCont=NULL, *curSurfCont=NULL;
6651    SUMA_Boolean LocalHead = NOPE;
6652 
6653    SUMA_ENTRY;
6654 
6655    iso=0;
6656    DOv[0]=NULL;
6657    if (!NB) SUMA_RETURN(DOv);
6658 
6659    XtVaGetValues(NB, XmNlastPageNumber, &lp, NULL);
6660    for (i=0; i<lp; ++i) {
6661       ns = XmNotebookGetPageInfo(NB, i+1, &pi);
6662       if (ns != XmPAGE_FOUND) {
6663          SUMA_LH("Could not find page!");
6664          SUMA_RETURN(DOv);
6665       }
6666       SUMA_LHv("Page %d, widget %p, page name=%s\n",
6667                    i+1, pi.page_widget,
6668                    XtName(pi.page_widget));
6669 
6670       for (j=0; j<SUMAg_N_DOv; ++j)
6671          if (!(strstr(((SUMA_SurfaceObject *)(SUMAg_DOv[j].OP))->Label,
6672             "clippingPlaneIdentificationSquare")))  {
6673             /*
6674             fprintf(stderr, "((SUMA_SurfaceObject *)(SUMAg_DOv[j].OP))->Label = %s\n",
6675                 ((SUMA_SurfaceObject *)(SUMAg_DOv[j].OP))->Label);
6676                 */
6677          if (SUMAg_DOv[j].ObjectType == SO_type ||
6678              SUMAg_DOv[j].ObjectType == GDSET_type ||
6679              SUMAg_DOv[j].ObjectType == TRACT_type ||
6680              SUMAg_DOv[j].ObjectType == VO_type) {
6681             DOt = (SUMA_ALL_DO *)SUMAg_DOv[j].OP;
6682             SurfCont = SUMA_ADO_Cont(DOt);
6683             if (DOt && SurfCont) {
6684                curDO = SUMA_Cont_ADO(SurfCont);
6685                if (curDO) {
6686                   if (!allids || !strstr(allids, SUMA_ADO_idcode(curDO))) {
6687                      curSurfCont = SUMA_ADO_Cont(curDO);
6688                      if (pi.page_widget == curSurfCont->Page) {
6689                         if (iso < SUMA_MAX_SURF_ON_COMMAND-1) {
6690                            DOv[iso] = curDO; ++iso; DOv[iso]=NULL;
6691                            allids = SUMA_append_replace_string(allids,
6692                                                 SUMA_ADO_idcode(curDO),"**",1);
6693                            SUMA_LHv("Got object %s\n", SUMA_ADO_Label(curDO));
6694                         } else {
6695                            SUMA_S_Errv("Too many surface controllers (%d)\n"
6696                                        "Will need to increase limit\n",
6697                                        iso);
6698                            if (allids) SUMA_free(allids); allids=NULL;
6699                            SUMA_RETURN(DOv);
6700                         }
6701                      }
6702                   } else {
6703                      /* surface sharing controller */
6704                      if (curDO != DOt) {
6705                         SUMA_LHv(
6706                        "Surface/DO %s should be sharing a controller with %s\n",
6707                            SUMA_ADO_Label(DOt), SUMA_ADO_Label(curDO));
6708                      }
6709                   }
6710                } else {
6711                   SUMA_LHv("Surface %s has no current DO set in its controller\n"
6712                         "This should mean its controller has never been open\n",
6713                          SUMA_ADO_Label(DOt));
6714                }
6715             } else {
6716                SUMA_LHv("Surface %s has no controller open yet\n",
6717                         DOt?SUMA_ADO_Label(DOt):"NULL");
6718             }
6719          } else {
6720             switch(SUMAg_DOv[j].ObjectType) {
6721                case CDOM_type:
6722                   SUMA_LH("%s objects are no longer to get their own controller",
6723                     SUMA_ObjectTypeCode2ObjectTypeName(SUMAg_DOv[j].ObjectType));
6724                   break;
6725                default:
6726                   break;
6727             }
6728          }
6729       }
6730    }
6731 
6732    if (allids) SUMA_free(allids); allids=NULL;
6733    SUMA_RETURN(DOv);
6734 }
6735 
SUMA_MarkSurfContOpen(int Open,SUMA_ALL_DO * ado)6736 SUMA_Boolean SUMA_MarkSurfContOpen(int Open, SUMA_ALL_DO *ado)
6737 {
6738    static char FuncName[]={"SUMA_MarkSurfContOpen"};
6739    int i;
6740    SUMA_ALL_DO **DOv=NULL;
6741    SUMA_X_SurfCont *SurfCont=NULL;
6742 
6743    SUMA_ENTRY;
6744 
6745    if (SUMAg_CF->X->UseSameSurfCont) {
6746       SUMAg_CF->X->SameSurfContOpen = Open;
6747       SurfCont = SUMA_ADO_Cont(ado);
6748       SurfCont->Open = Open;
6749       /* apply to all other surfaces */
6750       DOv = SUMA_DOsInSurfContNotebook(SUMAg_CF->X->SC_Notebook);
6751       i = 0;
6752       while (DOv[i]) {
6753       /*
6754         if (!(strstr(((SUMA_SurfaceObject *)(DOv[i]))->Label,
6755             "clippingPlaneIdentificationSquare_"))) {
6756             */
6757              SurfCont = SUMA_ADO_Cont(DOv[i]);
6758              SurfCont->Open=Open;
6759         // }
6760          ++i;
6761       }
6762    } else {
6763       if (ado) {
6764          SurfCont = SUMA_ADO_Cont(ado);
6765          SurfCont->Open = Open;
6766       }
6767    }
6768    SUMA_RETURN(YUP);
6769 }
6770 
SUMA_BringUpSurfContTLS(Widget TLS)6771 SUMA_Boolean SUMA_BringUpSurfContTLS(Widget TLS)
6772 {
6773    static char FuncName[]={"SUMA_BringUpSurfContTLS"};
6774    SUMA_Boolean LocalHead = NOPE;
6775 
6776    SUMA_ENTRY;
6777 
6778    if (!TLS) SUMA_RETURN(NOPE);
6779 
6780    /* controller already created, need to bring it up again */
6781    switch (SUMA_GL_CLOSE_MODE)   {/* open GL drawables in this widget*/
6782       case SUMA_WITHDRAW:
6783          if (LocalHead)
6784             fprintf (SUMA_STDERR,
6785                      "%s: Controller already created, Raising it.\n",
6786                      FuncName);
6787          XMapRaised( SUMAg_CF->X->DPY_controller1,
6788                      XtWindow(TLS));
6789          break;
6790       case SUMA_UNREALIZE:
6791          if (LocalHead)
6792             fprintf (SUMA_STDERR,
6793                      "%s: Controller already created, realizing it.\n",
6794                      FuncName);
6795          XtRealizeWidget(TLS);
6796          XSync(SUMAg_CF->X->DPY_controller1, 0);
6797          /* now do Raise, so that we can see the damned thing if it
6798             behind other windows, and hope it does not crash*/
6799          SUMA_LH("Rise and do not crash");
6800          XMapRaised( SUMAg_CF->X->DPY_controller1,
6801                      XtWindow(TLS));
6802 
6803          break;
6804       default:
6805          SUMA_S_Err("No setup for this close mode");
6806          SUMA_RETURN(NOPE);
6807          break;
6808    }
6809    SUMA_RETURN(YUP);
6810 }
6811 
6812 
6813 /*!
6814    if calling this function from outside interface, set w to NULL
6815 */
SUMA_viewSurfaceCont(Widget w,SUMA_ALL_DO * ado,SUMA_SurfaceViewer * sv)6816 int SUMA_viewSurfaceCont(Widget w, SUMA_ALL_DO *ado,
6817                          SUMA_SurfaceViewer *sv)
6818 {
6819    static char FuncName[]={"SUMA_viewSurfaceCont"};
6820    SUMA_X_SurfCont *SurfCont=NULL;
6821    SUMA_Boolean LocalHead = NOPE;
6822 
6823    SUMA_ENTRY;
6824 
6825 
6826    if (!ado || !(SurfCont=SUMA_ADO_Cont(ado))) {
6827       SUMA_RETURN(0);
6828    }
6829 
6830    if (ado->do_type == CDOM_type) {
6831       SUMA_LH("I thought we decided to not have a separate "
6832               "controller for CIFTI_DO!");
6833       SUMA_RETURN(0);
6834    }
6835    if (!sv) {
6836       SUMA_LHv("Got to get me an sv for %s\n", SUMA_ADO_Label(ado));
6837       if (!(sv = SUMA_BestViewerForADO(ado))) {
6838          SUMA_RETURN(0);
6839       }
6840    }
6841    SUMA_LHv("Working object %s,\n sv %p,\n w  %p\n",
6842             SUMA_ADO_Label(ado), w, sv);
6843 
6844    if (!SUMA_isADO_Cont_Created(ado)) {
6845       if (SUMAg_CF->X->UseSameSurfCont &&
6846           SUMAg_CF->X->CommonSurfContTLW &&
6847           !SUMAg_CF->X->SameSurfContOpen) {
6848          /* If you don't do this, then bad things will happen when:
6849          Launch SUMA with 2 types of objects (say one vol and one surf).
6850          Select the surf, open the surface controller.
6851          Close the controller.
6852          Select the vol, open the surface controller and you'll get some
6853          variant on:
6854 
6855          oo     Warning SUMA_XErrHandler (SUMA_display.c:3896):
6856          Intercepted X11 error: BadWindow (invalid Window parameter)
6857          Will attempt to proceed but trouble might ensue.
6858          ++     Notice SUMA_XErrHandler (SUMA_display.c:3897 @19:57:15):
6859          Trace At Xerr
6860                 SUMA_XErrHandler
6861                SUMA_cb_createSurfaceCont_VO
6862               SUMA_cb_createSurfaceCont
6863              SUMA_viewSurfaceCont
6864             SUMA_cb_viewSurfaceCont
6865            suma
6866           Bottom of Debug Stack
6867 
6868          The error handler catches it and you can recover from the crash,
6869          however the close (x) button no longer works on that controller
6870          and that's just not cool.
6871          The fix is in the call below. So all is well for now. Apr. 16 2014 */
6872          SUMA_LH("Must bring controller parent up first");
6873          SUMA_BringUpSurfContTLS(SUMAg_CF->X->CommonSurfContTLW);
6874       }
6875 
6876       if (LocalHead)
6877          SUMA_LH("Calling SUMA_cb_createSurfaceCont.");
6878       if (w) SUMA_cb_createSurfaceCont( w, (XtPointer)ado, NULL);
6879       else SUMA_cb_createSurfaceCont( sv->X->TOPLEVEL, (XtPointer)ado, NULL);
6880    } else {
6881       if (!SUMA_BringUpSurfContTLS(SurfCont->TLS)) {
6882          SUMA_S_Err("Failed to raise the roof");
6883          SUMA_RETURN(NOPE);
6884       }
6885    }
6886 
6887    if (!SUMA_ADO_Cont(ado)) { /* This can happen when attempting to open a
6888                                  controller for an object which should have
6889                                  none. Return without kvetching */
6890       SUMA_RETURN(YUP);
6891    }
6892 
6893    SUMA_LH("Init Position %p %p", SurfCont->PosRef, sv->X->TOPLEVEL);
6894    if (SurfCont->PosRef != sv->X->TOPLEVEL) {
6895       SurfCont->PosRef = sv->X->TOPLEVEL;
6896       if (!SUMAg_CF->X->UseSameSurfCont ||
6897           SUMA_NotebookLastPageNumber(SUMAg_CF->X->SC_Notebook) == 1) {
6898          /* Only reposition if not using same surf cont, or if
6899          using same surf cont but have only 1 page in it */
6900          SUMA_PositionWindowRelative ( SurfCont->TLS,
6901                                        SurfCont->PosRef, SWP_TOP_BEST);
6902       }
6903    }
6904 
6905    SUMA_MarkSurfContOpen(1,ado);
6906 
6907    SUMA_LH("Init SurfParam");
6908    SUMA_Init_SurfCont_SurfParam(ado);
6909    SUMA_LH("Init CrossHair");
6910    SUMA_Init_SurfCont_CrossHair(ado);
6911    SUMA_LH("Dset goodies");
6912    SUMA_InitializeColPlaneShell(ado, SurfCont->curColPlane);
6913 
6914 
6915    SUMA_LH("Returning");
6916 
6917    /* insist on a glXMakeCurrent for surface viewer,
6918    Otherwise you get a crash on OS X 10.5 if
6919    you do the following:
6920       Open the surface controller with View-->Surface Controller
6921       Close the controller
6922       Open it again in the same way and then you get one of these:
6923          X Error of failed request:  GLXBadCurrentWindow
6924          Major opcode of failed request:  149 (GLX)
6925          Minor opcode of failed request:  11 (X_GLXSwapBuffers)
6926          Serial number of failed request:  7046
6927          Current serial number in output stream:  7046
6928 
6929       */
6930    SUMA_LH("Making sv's GLXAREA current\n");
6931    SUMA_SiSi_I_Insist();
6932 
6933    #if 0
6934       SUMA_S_Warn("Block Me!");
6935       /* Toying with automated saving of controllers to help automate help
6936          The problem with simple command below is that the OpenGL parts will
6937          not get captured with XGetImage. So object controllers do not show
6938          the colormap, and the viewer windows will not show the rendering.
6939 
6940          One approach might be to grab the openGL rendered pixels, and replace
6941          the GLX areas with a widget displaying the grabbed image. I don't know
6942          ahead of time how much of a pain it will be to be sure the newly added
6943          widget does not cause resizing problems with the interface. What a pain.
6944 
6945          See functions SUMA_Snap*Widgets, for automatic widget snapping. Still
6946          need to write something to render colormaps a la PBAR_bigexpose_CB()
6947          which would then work for auto snapping of controllers.
6948       */
6949 
6950       ISQ_snapfile ( SurfCont->Mainform );
6951    #endif
6952 
6953    SUMA_RETURN(1);
6954 }
6955 
6956 /*!
6957    \brief SUMA_cb_viewSurfaceCont(Widget w, XtPointer data, XtPointer callData);
6958    opens the surface controller for the surface in focus.
6959    \param data (XtPointer) index of widget into sv->X->ViewMenu
6960    It is the controller for the surface in focus that will be open.
6961 
6962 */
SUMA_cb_viewSurfaceCont(Widget w,XtPointer data,XtPointer callData)6963 void SUMA_cb_viewSurfaceCont(Widget w, XtPointer data, XtPointer callData)
6964 {
6965    SUMA_ALL_DO *ado;
6966    SUMA_SurfaceViewer *sv;
6967    int isv, widtype;
6968    static char FuncName[] = {"SUMA_cb_viewSurfaceCont"};
6969    SUMA_Boolean LocalHead = NOPE;
6970 
6971    SUMA_ENTRY;
6972 
6973    SUMA_VIEWER_FROM_VIEWMENU_CALLBACK (data, isv, widtype);
6974 
6975    if (LocalHead)
6976       fprintf (SUMA_STDERR,
6977                "%s: A call from viewer %d, widget %d.\n",
6978                FuncName, isv, widtype);
6979 
6980    sv = &SUMAg_SVv[isv];
6981    if (sv->Focus_DO_ID >= 0) {
6982     ado = (SUMA_ALL_DO *)SUMAg_DOv[sv->Focus_DO_ID].OP;
6983    }else {
6984       fprintf (SUMA_STDERR,"%s: No displayable objects in focus.\n", FuncName);
6985       SUMA_RETURNe;
6986    }
6987 
6988    if (!SUMA_viewSurfaceCont(w, ado, sv)) {
6989       SUMA_S_Err("Failed in SUMA_viewSurfaceCont ADO %s", ADO_LABEL(ado));
6990       SUMA_RETURNe;
6991    }
6992 
6993    SUMA_RETURNe;
6994 }
6995 
6996 /*! \brief SUMA_cb_viewViewerCont(Widget w, XtPointer data, XtPointer callData)
6997       opens the viewer controller.
6998       \param data index of widget into sv->X->ViewMenu
6999 */
SUMA_cb_viewViewerCont(Widget w,XtPointer data,XtPointer callData)7000 void SUMA_cb_viewViewerCont(Widget w, XtPointer data, XtPointer callData)
7001 {
7002    int isv, widtype;
7003    SUMA_SurfaceViewer *sv;
7004    SUMA_Boolean LocalHead = NOPE;
7005    static char FuncName[] = {"SUMA_cb_viewViewerCont"};
7006 
7007    SUMA_ENTRY;
7008 
7009    SUMA_VIEWER_FROM_VIEWMENU_CALLBACK (data, isv, widtype);
7010 
7011    sv = &SUMAg_SVv[isv];
7012 
7013    if (!sv->X->ViewCont->TopLevelShell) {
7014       if (LocalHead)
7015          fprintf (SUMA_STDERR,
7016                   "%s: Calling SUMA_cb_createViewerCont.\n", FuncName);
7017       SUMA_cb_createViewerCont( w, sv, callData);
7018    }else {
7019       /* controller already created, need to bring it up again */
7020 
7021       switch (SUMA_CLOSE_MODE)   {/* No open GL drawables in this widget*/
7022          case SUMA_WITHDRAW:
7023             if (LocalHead)
7024                fprintf (SUMA_STDERR,
7025                         "%s: Controller already created, Raising it.\n",
7026                         FuncName);
7027             XMapRaised(sv->X->DPY, XtWindow(sv->X->ViewCont->TopLevelShell));                 break;
7028          default:
7029             SUMA_S_Err("Not set to deal with this close mode");
7030             SUMA_RETURNe;
7031             break;
7032       }
7033 
7034    }
7035 
7036    SUMA_RETURNe;
7037 }
7038 
7039 
7040 
7041 /*!<
7042  the function expects the index of widget into sv->X->ViewMenu in data
7043 */
SUMA_cb_toggle_crosshair(Widget w,XtPointer data,XtPointer callData)7044 void SUMA_cb_toggle_crosshair(Widget w, XtPointer data, XtPointer callData)
7045 {
7046    static char FuncName[] = {"SUMA_cb_toggle_crosshair"};
7047    int isv, widtype;
7048    DList *list = NULL;
7049    SUMA_SurfaceViewer *sv;
7050 
7051    SUMA_ENTRY;
7052 
7053    SUMA_VIEWER_FROM_VIEWMENU_CALLBACK (data, isv, widtype);
7054 
7055    sv = &SUMAg_SVv[isv];
7056 
7057    if (!list) list = SUMA_CreateList();
7058    SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_ToggleCrossHair,
7059                                        SES_SumaWidget, sv);
7060    SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_Redisplay, SES_SumaWidget, sv);
7061 
7062    if (!SUMA_Engine (&list)) {
7063       fprintf(stderr,"Error %s: Failed SUMA_Engine\n", FuncName);
7064    }
7065 
7066    SUMA_RETURNe;
7067 }
7068 
SUMA_cb_toggle_node_in_focus(Widget w,XtPointer data,XtPointer callData)7069 void SUMA_cb_toggle_node_in_focus(Widget w, XtPointer data, XtPointer callData)
7070 {
7071    static char FuncName[] = {"SUMA_cb_toggle_node_in_focus"};
7072    int isv, widtype;
7073    DList *list = NULL;
7074    SUMA_SurfaceViewer *sv;
7075 
7076    SUMA_ENTRY;
7077 
7078    SUMA_VIEWER_FROM_VIEWMENU_CALLBACK (data, isv, widtype);
7079 
7080    sv = &SUMAg_SVv[isv];
7081 
7082    if (!list) list = SUMA_CreateList();
7083    SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_ToggleShowSelectedNode,
7084                                        SES_SumaWidget, sv);
7085    SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_Redisplay, SES_SumaWidget, sv);
7086 
7087    if (!SUMA_Engine (&list)) {
7088       fprintf(stderr,"Error %s: Failed SUMA_Engine\n", FuncName);
7089    }
7090 
7091    SUMA_RETURNe;
7092 }
7093 
SUMA_cb_toggle_selected_faceset(Widget w,XtPointer data,XtPointer callData)7094 void SUMA_cb_toggle_selected_faceset(Widget w, XtPointer data,
7095                                      XtPointer callData)
7096 {
7097    static char FuncName[] = {"SUMA_cb_toggle_selected_faceset"};
7098    int isv, widtype;
7099    DList *list = NULL;
7100    SUMA_SurfaceViewer *sv;
7101 
7102    SUMA_ENTRY;
7103 
7104    SUMA_VIEWER_FROM_VIEWMENU_CALLBACK (data, isv, widtype);
7105 
7106    sv = &SUMAg_SVv[isv];
7107 
7108    if (!list) list = SUMA_CreateList();
7109    SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_ToggleShowSelectedFaceSet,
7110                                       SES_SumaWidget, sv);
7111    SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_Redisplay, SES_SumaWidget, sv);
7112 
7113    if (!SUMA_Engine (&list)) {
7114       fprintf(stderr,"Error %s: Failed SUMA_Engine\n", FuncName);
7115    }
7116 
7117    SUMA_RETURNe;
7118 }
7119 
7120 /*! Creates the dialog shell of the viewer controller.
7121 */
7122 #define SUMA_CONTROLLER_AS_DIALOG 0 /* controller widgets as dialog (1) or toplevelshells (0)
7123                                     Stick with toplevelshells or window managers might force
7124                                     you to keep them atop the surface viewers. Downside is that
7125                                     it is managed such that if the viewer is minimized, the controller is not.
7126                                     But that is not necessarily a bad thing. */
7127 /*!
7128 \brief Creates the viewer controller, expects sv in data
7129 */
SUMA_cb_createViewerCont(Widget w,XtPointer data,XtPointer callData)7130 void SUMA_cb_createViewerCont(Widget w, XtPointer data, XtPointer callData)
7131 {
7132    static char FuncName[] = {"SUMA_cb_createViewerCont"};
7133    Widget   tl, rc, pb, ViewerFrame, SwitchFrame,
7134             QuitFrame, rc_left, rc_right, rc_mamma;
7135    Display *dpy;
7136    SUMA_SurfaceViewer *sv;
7137    int isv;
7138    char slabel[100], *sss;
7139    SUMA_Boolean LocalHead = NOPE;
7140 
7141    SUMA_ENTRY;
7142 
7143    sv = (SUMA_SurfaceViewer *)data;
7144    isv = SUMA_WhichSV(sv, SUMAg_SVv, SUMAg_N_SVv);
7145 
7146    if (sv->X->ViewCont->TopLevelShell) {
7147       fprintf (SUMA_STDERR,
7148                "Error %s: sv->X->ViewCont->TopLevelShell!=NULL. \n"
7149                "Should not be here.\n", FuncName);
7150       SUMA_RETURNe;
7151    }
7152    tl = SUMA_GetTopShell(w); /* top level widget */
7153    dpy = XtDisplay(tl);
7154 
7155    sprintf(slabel,"[%c] Viewer Controller", 65+isv);
7156 
7157    if (SUMA_isEnv("SUMA_SurfContFontSize", "BIG")) {
7158       sss = "font9";
7159    } else {
7160       sss = "font8";
7161    }
7162 
7163    #if SUMA_CONTROLLER_AS_DIALOG
7164       /*xmDialogShellWidgetClass, topLevelShellWidgetClass*/
7165    SUMA_LH("Create a popup");
7166    sv->X->ViewCont->TopLevelShell = XtVaCreatePopupShell (sss,
7167       xmDialogShellWidgetClass, tl,
7168       XmNallowShellResize, True, /* let code resize shell */
7169       XmNdeleteResponse, XmDO_NOTHING,
7170       XmNtitle, slabel,
7171       NULL);
7172    #else
7173    SUMA_LH("Create an App");
7174    /** Feb 03/03: I was using XtVaCreatePopupShell to create a
7175       topLevelShellWidgetClass.
7176       XtVaCreatePopupShell is used to create dialog shells not
7177       toplevel or appshells */
7178    sv->X->ViewCont->TopLevelShell = XtVaAppCreateShell (sss, "Suma",
7179       topLevelShellWidgetClass, SUMAg_CF->X->DPY_controller1 ,
7180       XmNdeleteResponse, XmDO_NOTHING,
7181       XmNtitle, slabel,
7182       NULL);
7183    #endif
7184 
7185    /* allow for code to resize the shell */
7186    XtVaSetValues (sv->X->ViewCont->TopLevelShell,
7187          XmNresizePolicy , XmRESIZE_NONE , /* allow (?) childrent to resize */
7188          XmNallowShellResize , True ,       /* let code resize shell */
7189          NULL);
7190 
7191    /* handle the close button from window manager */
7192    XmAddWMProtocolCallback(/* make "Close" window menu work */
7193       sv->X->ViewCont->TopLevelShell,
7194       XmInternAtom( dpy , "WM_DELETE_WINDOW" , False ) ,
7195       SUMA_cb_closeViewerCont, (XtPointer) sv) ;
7196 
7197    /* create a form widget, manage it at the end ...*/
7198    sv->X->ViewCont->Mainform = XtVaCreateWidget ("dialog",
7199       xmFormWidgetClass, sv->X->ViewCont->TopLevelShell,
7200       XmNborderWidth , 0 ,
7201       XmNmarginHeight , SUMA_MARGIN ,
7202       XmNmarginWidth  , SUMA_MARGIN ,
7203       XmNshadowThickness, 2,
7204       XmNshadowType, XmSHADOW_ETCHED_IN,
7205       NULL);
7206 
7207    rc_mamma = XtVaCreateWidget ("rowcolumn",
7208             xmRowColumnWidgetClass, sv->X->ViewCont->Mainform,
7209             XmNpacking, XmPACK_TIGHT,
7210             XmNorientation , XmHORIZONTAL ,
7211             XmNmarginHeight, SUMA_MARGIN ,
7212             XmNmarginWidth , SUMA_MARGIN ,
7213             XmNleftAttachment , XmATTACH_FORM ,
7214             XmNtopAttachment  , XmATTACH_FORM ,
7215             XmNrightAttachment , XmATTACH_FORM ,
7216             NULL);
7217 
7218    rc_left = XtVaCreateWidget ("rowcolumn",
7219             xmRowColumnWidgetClass, rc_mamma,
7220             XmNpacking, XmPACK_TIGHT,
7221             XmNorientation , XmVERTICAL ,
7222             XmNmarginHeight, SUMA_MARGIN ,
7223             XmNmarginWidth , SUMA_MARGIN ,
7224             NULL);
7225 
7226    rc_right = XtVaCreateWidget ("rowcolumn",
7227             xmRowColumnWidgetClass, rc_mamma,
7228             XmNpacking, XmPACK_TIGHT,
7229             XmNorientation , XmVERTICAL ,
7230             XmNmarginHeight, SUMA_MARGIN ,
7231             XmNmarginWidth , SUMA_MARGIN ,
7232             NULL);
7233 
7234    {/*s group, state and info */
7235       Widget rc, pb, label;
7236 
7237       /* put a frame */
7238       ViewerFrame = XtVaCreateWidget ("dialog",
7239          xmFrameWidgetClass, rc_left,
7240          XmNshadowType , XmSHADOW_ETCHED_IN ,
7241          XmNshadowThickness , 5 ,
7242          XmNtraversalOn , False ,
7243          NULL);
7244 
7245       /* row column Lock rowcolumns */
7246       rc = XtVaCreateWidget ("rowcolumn",
7247             xmRowColumnWidgetClass, ViewerFrame,
7248             XmNpacking, XmPACK_TIGHT,
7249             XmNorientation , XmHORIZONTAL ,
7250             XmNmarginHeight, SUMA_MARGIN ,
7251             XmNmarginWidth , SUMA_MARGIN ,
7252             NULL);
7253 
7254       /*put a label containing the surface name,
7255          number of nodes and number of facesets */
7256       snprintf(slabel, 40*sizeof(char),
7257                "Group: %s, State: %s", sv->CurGroupName, sv->State);
7258       sv->X->ViewCont->Info_lb = XtVaCreateManagedWidget (slabel,
7259                xmLabelWidgetClass, rc,
7260                NULL);
7261 
7262       XtVaCreateManagedWidget (  "sep",
7263                                  xmSeparatorWidgetClass, rc,
7264                                  XmNorientation, XmVERTICAL,NULL);
7265 
7266       sv->X->ViewCont->ViewerInfo_pb = XtVaCreateWidget ("more",
7267          xmPushButtonWidgetClass, rc,
7268          NULL);
7269       XtAddCallback (sv->X->ViewCont->ViewerInfo_pb, XmNactivateCallback,
7270                      SUMA_cb_moreViewerInfo, (XtPointer) sv);
7271       XtVaSetValues (sv->X->ViewCont->ViewerInfo_pb,
7272                      XmNuserData, (XtPointer)sv, NULL);
7273                      /* store sv in userData
7274                      I think it is more convenient than as data
7275                      in the call back structure. This way it will
7276                      be easy to change the sv that this same button
7277                      might refer to.
7278                      This is only for testing purposes, the pb_close
7279                      button still expects sv in clientData
7280                      Feb 23 04: UserData works well, but other
7281                      functions don't use it much so also store sv in clientData*/
7282       SUMA_Register_Widget_Help(sv->X->ViewCont->ViewerInfo_pb , 1,
7283                            "ViewerCont->more",
7284                            "More info on Viewer", SUMA_moreViewerInfo_help);
7285       XtManageChild (sv->X->ViewCont->ViewerInfo_pb);
7286 
7287       XtManageChild (rc);
7288 
7289       XtManageChild (ViewerFrame);
7290 
7291    }
7292    { /* switch group and state frames */
7293       Widget rc, pb, label;/* put a frame */
7294 
7295       SwitchFrame = XtVaCreateWidget ("dialog",
7296          xmFrameWidgetClass, rc_left,
7297          XmNshadowType , XmSHADOW_ETCHED_IN ,
7298          XmNshadowThickness , 5 ,
7299          XmNtraversalOn , False ,
7300          NULL);
7301 
7302       /* row column for switching groups and state */
7303       rc = XtVaCreateWidget ("rowcolumn",
7304             xmRowColumnWidgetClass, SwitchFrame,
7305             XmNpacking, XmPACK_TIGHT,
7306             XmNorientation , XmHORIZONTAL ,
7307             XmNmarginHeight, SUMA_MARGIN ,
7308             XmNmarginWidth , SUMA_MARGIN ,
7309             NULL);
7310 
7311       /*put a label for Switch */
7312       snprintf(slabel, 40*sizeof(char), "Switch:");
7313       label = XtVaCreateManagedWidget (slabel,
7314                xmLabelWidgetClass, rc,
7315                NULL);
7316 
7317 
7318       /* put a button for swiching groups */
7319       snprintf(slabel, 40*sizeof(char), "[%c] Switch Group", 65 + isv);
7320       sv->X->ViewCont->SwitchGrouplst =
7321             SUMA_AllocateScrolledList (slabel, SUMA_LSP_SINGLE,
7322                               NOPE, YUP,
7323                               sv->X->ViewCont->TopLevelShell, SWP_TOP_LEFT,
7324                               125,
7325                               SUMA_cb_SelectSwitchGroup, (void *)sv,
7326                               SUMA_cb_SelectSwitchGroup, (void *)sv,
7327                               SUMA_cb_CloseSwitchGroup, (void *)sv);
7328 
7329 
7330       pb = XtVaCreateWidget ("Group",
7331          xmPushButtonWidgetClass, rc,
7332          NULL);
7333       XtAddCallback (pb, XmNactivateCallback,
7334                      SUMA_cb_ViewerCont_SwitchGroup, (XtPointer) sv);
7335       SUMA_Register_Widget_Help(pb , 1,
7336                            "ViewerCont->Switch->Group",
7337                            "Switch Group", "Switch Group");
7338       XtManageChild (pb);
7339 
7340       /* put a button for swiching states */
7341       pb = XtVaCreateWidget ("State",
7342          xmPushButtonWidgetClass, rc,
7343          NULL);
7344       XtAddCallback (pb, XmNactivateCallback,
7345                      SUMA_cb_ViewerCont_SwitchState, (XtPointer) sv);
7346       SUMA_Register_Widget_Help(pb , 1,
7347                            "ViewerCont->Switch->State",
7348                            "Switch State", "Switch State");
7349       XtManageChild (pb);
7350 
7351 
7352       /* now start managing the row column widget */
7353       XtManageChild (rc);
7354 
7355       /* manage the frame and the fslabelorm */
7356       XtManageChild (SwitchFrame);
7357    }
7358 
7359    { /*s close and help buttons */
7360       Widget rc, pb_close, pb_bhelp;
7361 
7362       /* put up a frame to group the display controls */
7363       QuitFrame = XtVaCreateWidget ("dialog",
7364          xmFrameWidgetClass, sv->X->ViewCont->Mainform,
7365          XmNleftAttachment , XmATTACH_FORM ,
7366          XmNtopAttachment  , XmATTACH_WIDGET ,
7367          XmNtopWidget, SwitchFrame,
7368          XmNshadowType , XmSHADOW_ETCHED_IN ,
7369          XmNshadowThickness , 5 ,
7370          XmNtraversalOn , False ,
7371          NULL);
7372 
7373 
7374       #if 0
7375       /* ugly, useless */
7376       /* this one requires Motif 1.2 or newer */
7377       XtVaCreateManagedWidget ("Disp. Cont.",
7378             xmLabelWidgetClass, QuitFrame,
7379             XmNchildType, XmFRAME_TITLE_CHILD,
7380             XmNchildHorizontalAlignment, XmALIGNMENT_BEGINNING,
7381             NULL);
7382       #endif
7383 
7384       /* row column Lock rowcolumns */
7385       rc = XtVaCreateWidget ("rowcolumn",
7386             xmRowColumnWidgetClass, QuitFrame,
7387             XmNpacking, XmPACK_TIGHT,
7388             XmNorientation , XmHORIZONTAL ,
7389             XmNmarginHeight, SUMA_MARGIN ,
7390             XmNmarginWidth , SUMA_MARGIN ,
7391             NULL);
7392 
7393       pb_close = XtVaCreateWidget ("Close",
7394          xmPushButtonWidgetClass, rc,
7395          NULL);
7396       XtAddCallback (pb_close, XmNactivateCallback,
7397                      SUMA_cb_closeViewerCont, (XtPointer) sv);
7398       SUMA_Register_Widget_Help(pb_close , 1,
7399                            "ViewerCont->Close",
7400                            "Close Viewer controller", SUMA_closeViewerCont_help);
7401       XtManageChild (pb_close);
7402 
7403       pb_bhelp = XtVaCreateWidget ("BHelp",
7404          xmPushButtonWidgetClass, rc,
7405          NULL);
7406       XtAddCallback (pb_bhelp, XmNactivateCallback, MCW_click_help_CB, NULL);
7407       SUMA_Register_Widget_Help(pb_bhelp , 1,
7408                            "ViewerCont->BHelp",
7409                            "Press this button then click on a "
7410                            "button/label/menu for more help.",
7411                            SUMA_help_help);
7412       XtManageChild (pb_bhelp);
7413 
7414 
7415       pb_bhelp = XtVaCreateWidget ("WHelp",
7416          xmPushButtonWidgetClass, rc,
7417          NULL);
7418       XtAddCallback (pb_bhelp, XmNactivateCallback,
7419                      SUMA_click_webhelp_CB, "ViewerCont->WHelp");
7420       SUMA_Register_Widget_Help(pb_bhelp , 1,
7421                            "ViewerCont->WHelp",
7422                            "Press this button then click on a "
7423                            "button/label/menu for online help.",
7424                            SUMA_webhelp_help);
7425       MCW_set_widget_bg( pb_bhelp , MCW_buthighlight(pb_bhelp) , 0 ) ;
7426       XtManageChild (pb_bhelp);
7427 
7428 
7429       /* now start managing the row column widget */
7430       XtManageChild (rc);
7431 
7432       /* manage the frame and the fslabelorm */
7433       XtManageChild (QuitFrame);
7434    }
7435 
7436    XtManageChild (rc_right);
7437    XtManageChild (rc_left);
7438    XtManageChild (rc_mamma);
7439    XtManageChild (sv->X->ViewCont->Mainform);
7440 
7441    #if SUMA_CONTROLLER_AS_DIALOG
7442    #else
7443    /** Feb 03/03: pop it up if it is a topLevelShellWidgetClass,
7444    you should do the popping after all the widgets have been created.
7445    Otherwise, the window does not size itself correctly when open */
7446    XtPopup(sv->X->ViewCont->TopLevelShell, XtGrabNone);
7447    #endif
7448 
7449    /* realize the widget */
7450    XtRealizeWidget (sv->X->ViewCont->TopLevelShell);
7451 
7452    SUMA_RETURNe;
7453 }
7454 
7455 /*!
7456    \brief Closes a viewer controller, expects sv in data
7457 */
SUMA_cb_closeViewerCont(Widget w,XtPointer data,XtPointer callData)7458 void SUMA_cb_closeViewerCont(Widget w, XtPointer data, XtPointer callData)
7459 {
7460    static char FuncName[] = {"SUMA_cb_closeViewerCont"};
7461    SUMA_SurfaceViewer *sv;
7462    SUMA_Boolean LocalHead = NOPE;
7463 
7464    SUMA_ENTRY;
7465 
7466    sv = (SUMA_SurfaceViewer *)data;
7467 
7468    if (!sv->X->ViewCont->TopLevelShell) SUMA_RETURNe;
7469 
7470    switch (SUMA_CLOSE_MODE)   {/* No open GL drawables in this widget*/
7471       case SUMA_WITHDRAW:
7472          if (LocalHead)
7473             fprintf (SUMA_STDERR,
7474                      "%s: Withdrawing Viewer Controller...\n", FuncName);
7475          XWithdrawWindow(sv->X->DPY,
7476             XtWindow(sv->X->ViewCont->TopLevelShell),
7477             XScreenNumberOfScreen(XtScreen(sv->X->ViewCont->TopLevelShell)));
7478          break;
7479       case SUMA_DESTROY:
7480          if (LocalHead)
7481             fprintf (SUMA_STDERR,
7482                      "%s: Destroying Viewer Controller...\n", FuncName);
7483          XtDestroyWidget(sv->X->ViewCont->TopLevelShell);
7484          sv->X->ViewCont->TopLevelShell = NULL;
7485          break;
7486       default:
7487          SUMA_S_Err("Not ready to deal with this closing mode\n");
7488          break;
7489          SUMA_RETURNe;
7490    }
7491 
7492    SUMA_RETURNe;
7493 
7494 }
7495 
7496 /*
7497    creates a managed widget with the common close, bhelp buttons
7498 */
SUMA_CloseBhelp_Frame(Widget parent,XtCallbackProc close_callback,XtPointer close_data,char * wname,char * close_hint,char * close_help,XtCallbackProc help_callback,XtPointer help_data,char * help_hint,char * help_help)7499 Widget SUMA_CloseBhelp_Frame( Widget parent,
7500                               XtCallbackProc close_callback,
7501                               XtPointer close_data,
7502                               char *wname,
7503                               char *close_hint,
7504                               char *close_help,
7505                               XtCallbackProc help_callback,
7506                               XtPointer help_data,
7507                               char *help_hint,
7508                               char *help_help)
7509 {
7510    static char FuncName[]={"SUMA_CloseBhelp_Frame"};
7511    Widget rc, pb_close, pb_bhelp, DispFrame, pb_help;
7512    char ss[64];
7513 
7514    SUMA_ENTRY;
7515 
7516    /* put up a frame to group the display controls */
7517    DispFrame = XtVaCreateWidget ("dialog",
7518       xmFrameWidgetClass, parent,
7519       XmNleftAttachment , XmATTACH_FORM ,
7520       XmNbottomAttachment  , XmATTACH_WIDGET ,
7521       XmNbottomWidget, parent,
7522       XmNshadowType , XmSHADOW_ETCHED_IN ,
7523       XmNshadowThickness , 5 ,
7524       XmNtraversalOn , False ,
7525       NULL);
7526 
7527 
7528    /* this one requires Motif 1.2 or newer */
7529       XtVaCreateManagedWidget ("Disp. Cont.",
7530          xmLabelWidgetClass, DispFrame,
7531          XmNchildType, XmFRAME_TITLE_CHILD,
7532          XmNchildHorizontalAlignment, XmALIGNMENT_BEGINNING,
7533          NULL);
7534 
7535    /* row column Lock rowcolumns */
7536    rc = XtVaCreateWidget ("rowcolumnCBF",
7537          xmRowColumnWidgetClass, DispFrame,
7538          XmNpacking, XmPACK_TIGHT,
7539          XmNorientation , XmHORIZONTAL ,
7540          XmNmarginHeight, SUMA_MARGIN ,
7541          XmNmarginWidth , SUMA_MARGIN ,
7542          NULL);
7543 
7544    pb_close = XtVaCreateWidget ("Close",
7545       xmPushButtonWidgetClass, rc,
7546       NULL);
7547    XtAddCallback (pb_close, XmNactivateCallback,
7548                   close_callback, close_data);
7549    snprintf(ss, 63, "%s->Close", wname);
7550    SUMA_Register_Widget_Help(pb_close , 1,
7551                         ss,
7552                         close_hint, close_help);
7553    XtManageChild (pb_close);
7554 
7555    pb_bhelp = XtVaCreateWidget ("BHelp",
7556       xmPushButtonWidgetClass, rc,
7557       NULL);
7558    XtAddCallback (pb_bhelp, XmNactivateCallback, MCW_click_help_CB, NULL);
7559    snprintf(ss, 63, "%s->BHelp", wname);
7560    SUMA_Register_Widget_Help(pb_bhelp , 1,
7561                         ss,
7562                         "Press this button then click on a "
7563                         "button/label/menu for more help.", SUMA_help_help);
7564    XtManageChild (pb_bhelp);
7565 
7566    pb_bhelp = XtVaCreateWidget ("WHelp",
7567       xmPushButtonWidgetClass, rc,
7568       NULL);
7569    snprintf(ss, 63, "%s->WHelp", wname);
7570    XtAddCallback (pb_bhelp, XmNactivateCallback, SUMA_click_webhelp_CB,
7571                   SUMA_copy_string(ss));
7572    MCW_set_widget_bg( pb_bhelp , MCW_buthighlight(pb_bhelp) , 0 ) ;
7573    SUMA_Register_Widget_Help(pb_bhelp , 1,
7574                         ss,
7575                         "Press this button then click on a "
7576                         "button/label/menu for online help.", SUMA_webhelp_help);
7577 
7578    XtManageChild (pb_bhelp);
7579 
7580 
7581    if (help_callback) {
7582       XtVaCreateManagedWidget ("sep",
7583                         xmSeparatorGadgetClass, rc,
7584                         XmNorientation, XmVERTICAL,
7585                         NULL);
7586       pb_help = XtVaCreateWidget ("Help",
7587          xmPushButtonWidgetClass, rc,
7588          NULL);
7589       XtAddCallback (pb_help, XmNactivateCallback, help_callback, help_data);
7590       snprintf(ss, 63, "%s->Help", wname);
7591       SUMA_Register_Widget_Help(pb_help, 1,ss, help_hint ?
7592             help_hint : "Press this button to get help about this interface",
7593                                              help_help ?
7594             help_help : "Help about this interface" );
7595       XtManageChild (pb_help);
7596    }
7597 
7598    /* now start managing the row column widget */
7599    XtManageChild (rc);
7600 
7601    /* manage the frame and the fslabelorm */
7602    XtManageChild (DispFrame);
7603 
7604    SUMA_RETURN(DispFrame);
7605 }
7606 
SUMA_cb_createSurfaceCont(Widget w,XtPointer data,XtPointer callData)7607 void SUMA_cb_createSurfaceCont(Widget w, XtPointer data, XtPointer callData)
7608 {
7609    static char FuncName[] = {"SUMA_cb_createSurfaceCont"};
7610    Display *dpy;
7611    SUMA_ALL_DO *ado;
7612    char *slabel, *lbl30, *sss=NULL;
7613    XmString xmstmp;
7614    SUMA_X_SurfCont *SurfCont=NULL;
7615    SUMA_OVERLAYS *curColPlane=NULL, *over0=NULL;
7616    SUMA_Boolean LocalHead = NOPE;
7617 
7618    SUMA_ENTRY;
7619 
7620    ado = (SUMA_ALL_DO *)data;
7621    if (!(SurfCont = SUMA_ADO_Cont(ado))) {
7622       SUMA_S_Errv("Failed to get Controller for ado %s\n",
7623                   SUMA_ADO_Label(ado));
7624       SUMA_RETURNe;
7625    }
7626    SUMA_LH("Creating controller for %s", ADO_LABEL(ado));
7627    switch (ado->do_type) {
7628       case SO_type:
7629          SUMA_cb_createSurfaceCont_SO(w, data, callData);
7630          break;
7631       case CDOM_type:
7632          SUMA_LH("No longer planning on separate controllers for CIFTI");
7633          #if 0
7634          SUMA_cb_createSurfaceCont_CO(w, (XtPointer)ado,  callData);
7635          #endif
7636          break;
7637       case GDSET_type:
7638          SUMA_S_Err("Cannot create a controller for a dataset"
7639                     "with no rendering variant");
7640          SUMA_RETURNe;
7641          break;
7642       case GRAPH_LINK_type: {
7643          SUMA_GraphLinkDO *gldo=(SUMA_GraphLinkDO *)ado;
7644          SUMA_cb_createSurfaceCont_GLDO(w, (XtPointer)ado,  callData);
7645          break; }
7646       case TRACT_type: {
7647          SUMA_cb_createSurfaceCont_TDO(w, (XtPointer)ado,  callData);
7648          break; }
7649       case MASK_type: {
7650          SUMA_cb_createSurfaceCont_MDO(w, (XtPointer)ado,  callData);
7651          break; }
7652       case VO_type: {
7653          SUMA_cb_createSurfaceCont_VO(w, (XtPointer)ado,  callData);
7654          break; }
7655       default:
7656          SUMA_S_Errv("No controller for type %d (%s)\n",
7657                ado->do_type, SUMA_ObjectTypeCode2ObjectTypeName(ado->do_type));
7658          SUMA_RETURNe;
7659          break;
7660    }
7661 
7662    SUMA_RETURNe;
7663 }
7664 
SUMA_WriteCont_Help(SUMA_DO_Types do_type,TFORM targ,char * fname)7665 SUMA_Boolean SUMA_WriteCont_Help(SUMA_DO_Types do_type, TFORM targ, char *fname)
7666 {
7667    static char FuncName[]={"SUMA_WriteCont_Help"};
7668    FILE *fout=NULL;
7669    char *s=NULL;
7670 
7671    SUMA_ENTRY;
7672 
7673    if (!fname) {
7674       switch (targ) {
7675          case WEB:
7676          case NO_FORMAT:
7677          case TXT:
7678             fname = "SurfCont_help.txt";
7679             break;
7680          case ASPX:
7681          case SPX:
7682             fname = "SurfCont_help.rst";
7683             break;
7684          default:
7685             SUMA_S_Warn("Unknown format of %d. Going with .txt",targ);
7686             fname = "SurfCont_help.txt";
7687             break;
7688       }
7689    }
7690 
7691    if (!(fout = fopen(fname,"w"))) {
7692       SUMA_S_Err("Failed to open help file %s in write mode", fname);
7693       SUMA_RETURN(NOPE);
7694    }
7695 
7696    switch(do_type) {
7697       case not_DO_type:
7698          s = SUMA_Help_AllSumaCont(targ);
7699          break;
7700       case SO_type:
7701          s = SUMA_Help_AllSurfCont(targ);
7702          break;
7703       case GRAPH_LINK_type:
7704          s = SUMA_Help_AllGraphCont(targ);
7705          break;
7706       case TRACT_type:
7707          s = SUMA_Help_AllTractCont(targ);
7708          break;
7709       case MASK_type:
7710          s = SUMA_Help_AllMaskCont(targ);
7711          break;
7712       case VO_type:
7713          s = SUMA_Help_AllVolCont(targ);
7714          break;
7715       case ROIdO_type:
7716          s = SUMA_Help_AllROICont(targ);
7717          break;
7718       default:
7719          SUMA_S_Err("Nothing for this controller");
7720          SUMA_RETURN(NOPE);
7721    }
7722 
7723    fprintf(fout,"%s\n", s);
7724    SUMA_ifree(s);
7725    fclose(fout); fout=NULL;
7726 
7727    SUMA_S_Note("Appended controller help to %s", fname);
7728 
7729    SUMA_RETURN(YUP);
7730 }
7731 
SUMA_Snap_AllCont(SUMA_DO_Types do_type,char * fname)7732 SUMA_Boolean SUMA_Snap_AllCont(SUMA_DO_Types do_type, char *fname)
7733 {
7734    static char FuncName[]={"SUMA_Snap_AllCont"};
7735    FILE *fout=NULL;
7736    char *s=NULL;
7737    SUMA_ALL_DO *ado=NULL;
7738 
7739    SUMA_ENTRY;
7740 
7741    if (!fname) {
7742       fname = "SurfCont";
7743    }
7744 
7745    switch(do_type) {
7746       case not_DO_type:
7747          SUMA_Snap_AllSumaCont(fname);
7748          break;
7749       case ROIdO_type:
7750          SUMA_Snap_AllROICont(fname);
7751          break;
7752       case SO_type:
7753          SUMA_Snap_AllSurfCont(fname);
7754          break;
7755       case GRAPH_LINK_type:
7756          SUMA_Snap_AllGraphCont(fname);
7757          break;
7758       case TRACT_type:
7759          if ((ado = (SUMA_ALL_DO*)SUMA_findanyTDOp_inDOv(
7760                                        SUMAg_DOv, SUMAg_N_DOv,NULL))) {
7761             SUMA_cb_SurfCont_SwitchPage(ado);
7762          }
7763          SUMA_Snap_AllTractCont(fname);
7764          break;
7765       case MASK_type:
7766          if ((ado = (SUMA_ALL_DO*)SUMA_findanyMDOp_inDOv(
7767                                        SUMAg_DOv, SUMAg_N_DOv,NULL))) {
7768             SUMA_cb_SurfCont_SwitchPage(ado);
7769          }
7770          SUMA_Snap_AllMaskCont(fname);
7771          break;
7772       case VO_type:
7773          SUMA_Snap_AllVolCont(fname);
7774          break;
7775       default:
7776          SUMA_S_Err("Nothing for this controller");
7777          SUMA_RETURN(NOPE);
7778    }
7779 
7780    SUMA_S_Note("Saved widgets for controller to root %s", fname);
7781 
7782    SUMA_RETURN(YUP);
7783 }
7784 
7785 /*!
7786    \brief SUMA_cb_createSurfaceCont_SO(Widget w, XtPointer data,
7787                                     XtPointer callData);
7788    \param data (XtPointer) to SO (NOT sv)
7789 
7790 */
SUMA_cb_createSurfaceCont_SO(Widget w,XtPointer data,XtPointer callData)7791 void SUMA_cb_createSurfaceCont_SO(Widget w, XtPointer data, XtPointer callData)
7792 {
7793    static char FuncName[] = {"SUMA_cb_createSurfaceCont_SO"};
7794    Widget tl, pb, form,
7795           rc_left, rc_right, rc_mamma, rc_gmamma, tls=NULL;
7796    Display *dpy;
7797    SUMA_ALL_DO *ado;
7798    char *slabel, *lbl30, *sss=NULL;
7799    XmString xmstmp;
7800    SUMA_X_SurfCont *SurfCont=NULL;
7801    SUMA_OVERLAYS *curColPlane=NULL, *over0=NULL;
7802    SUMA_Boolean LocalHead = NOPE;
7803 
7804    SUMA_ENTRY;
7805 
7806    ado = (SUMA_ALL_DO *)data;
7807    if (!(SurfCont = SUMA_ADO_Cont(ado))) {
7808       SUMA_S_Errv("Failed to get Controller for ado %s\n",
7809                   SUMA_ADO_Label(ado));
7810       SUMA_RETURNe;
7811    }
7812    if (!SUMA_SurfCont_SetcurDOp(SurfCont, ado)) {/* First set owner of GUI */
7813       SUMA_S_Err("Failed to set curDOp");
7814       SUMA_RETURNe;
7815    }
7816    if (!(curColPlane = SUMA_ADO_CurColPlane(ado))) {
7817       SUMA_S_Errv("Failed to get current col plane for ado %s\n",
7818                   SUMA_ADO_Label(ado));
7819       SUMA_RETURNe;
7820    }
7821    SUMA_LH("Cur Col Plane = %s", curColPlane->Name);
7822    if (SurfCont->TLS) {
7823       fprintf (SUMA_STDERR,
7824                "Error %s: SurfCont->TopLevelShell!=NULL.\n"
7825                "Should not be here.\n", FuncName);
7826       SUMA_RETURNe;
7827    }
7828 
7829    tl = SUMA_GetTopShell(w); /* top level widget */
7830    dpy = XtDisplay(tl);
7831 
7832    slabel = (char *)SUMA_malloc(sizeof(char) *
7833                                  (strlen(SUMA_ADO_Label(ado)) + 100));
7834    if (strlen(SUMA_ADO_Label(ado)) > 40) {
7835       char *tmpstr=NULL;
7836       tmpstr = SUMA_truncate_string(SUMA_ADO_Label(ado), 40);
7837       if (tmpstr) {
7838          sprintf(slabel,"[%s] Surface Controller", tmpstr);
7839          free(tmpstr); tmpstr=NULL;
7840       }
7841    } else {
7842       sprintf(slabel,"[%s] Surface Controller", SUMA_ADO_Label(ado));
7843    }
7844 
7845    /* March 12 08: Made font8 default for surface controller */
7846    if (SUMA_isEnv("SUMA_SurfContFontSize", "BIG")) {
7847       sss = "font9";
7848    } else {
7849       sss = "font8";
7850    }
7851 
7852    SUMA_LH("Creating dialog shell.");
7853    if (!SUMAg_CF->X->UseSameSurfCont ||
7854        !SUMAg_CF->X->CommonSurfContTLW) { /* need a new one */
7855       #if SUMA_CONTROLLER_AS_DIALOG /* xmDialogShellWidgetClass,
7856                                        topLevelShellWidgetClass*/
7857       tls = XtVaCreatePopupShell (sss,
7858          XmNtitle, slabel,
7859          xmDialogShellWidgetClass, tl,
7860          XmNallowShellResize, True, /* let code resize shell */
7861          XmNdeleteResponse, XmDO_NOTHING,
7862          NULL);
7863       #else
7864       SUMA_LH("Creating toplevel shell.");
7865       /** Feb 03/03:    I was using XtVaCreatePopupShell to create a
7866                         topLevelShellWidgetClass.
7867                         XtVaCreatePopupShell is used to create dialog
7868                         shells not toplevel or appshells.
7869                         Of course, it made no difference! */
7870       tls = XtVaAppCreateShell (sss, "Suma",
7871          topLevelShellWidgetClass, SUMAg_CF->X->DPY_controller1 ,
7872          XmNtitle, slabel,
7873          XmNdeleteResponse, XmDO_NOTHING,
7874          NULL);
7875       #endif
7876 
7877       /* allow for code to resize the shell */
7878       XtVaSetValues (tls,
7879             XmNresizePolicy , XmRESIZE_NONE ,
7880             XmNallowShellResize , True ,       /* let code resize shell */
7881             NULL);
7882 
7883       /* handle the close button from window manager */
7884       XmAddWMProtocolCallback(/* make "Close" window menu work */
7885          tls,
7886          XmInternAtom( dpy , "WM_DELETE_WINDOW" , False ) ,
7887          SUMA_cb_closeSurfaceCont, (XtPointer) ado) ;
7888 
7889       if (SUMAg_CF->X->UseSameSurfCont) {
7890          Widget scroller;
7891          SUMAg_CF->X->CommonSurfContTLW = tls;
7892          SUMAg_CF->X->SC_Notebook =
7893             XtVaCreateWidget("ControllerBook", xmNotebookWidgetClass,
7894                              SUMAg_CF->X->CommonSurfContTLW,
7895                              XmNbindingWidth, XmNONE,
7896                              XmNbackPageNumber, 0,
7897                              XmNmajorTabSpacing, 0,
7898                              XmNminorTabSpacing, 0,
7899                              NULL);
7900             /*XmCreateNotebook (SUMAg_CF->X->CommonSurfContTLW, "ControllerBook",
7901                               NULL, 0);
7902               XtVaSetValues(SUMAg_CF->X->SC_Notebook,
7903                           XmNbindingWidth, XmNONE,
7904                           NULL); */
7905 
7906 
7907          /* Kill the scroller from hell otherwise no keyboard input
7908             gets to the baby widgets. Better write my own scroller
7909             if need be in the future */
7910          scroller = XtNameToWidget (SUMAg_CF->X->SC_Notebook, "PageScroller");
7911          XtUnmanageChild (scroller);
7912       }
7913 
7914    }
7915 
7916    if (SUMAg_CF->X->UseSameSurfCont) {
7917       SurfCont->TLS = SUMAg_CF->X->CommonSurfContTLW;
7918    } else {
7919       SurfCont->TLS = tls;
7920    }
7921 
7922    if (!SurfCont->TLS) {
7923       SUMA_S_Err("Bad logic");
7924       SUMA_RETURNe;
7925    }
7926 
7927    SUMA_LH("Widgets...");
7928    if (SUMAg_CF->X->UseSameSurfCont) {
7929       Arg args[20];
7930       /* add the page */
7931       XtSetArg (args[0], XmNnotebookChildType, XmPAGE);
7932       SurfCont->Page =
7933          XmCreateRowColumn (SUMAg_CF->X->SC_Notebook,
7934                      SUMA_ADO_Label(ado)?SUMA_ADO_Label(ado):"page",
7935                                               args, 1);
7936    }
7937 
7938    /* create a form widget, manage it at the end ...*/
7939    SurfCont->Mainform = XtVaCreateWidget ("dialog",
7940       xmFormWidgetClass, SurfCont->Page ?
7941                               SurfCont->Page:SurfCont->TLS,
7942       XmNborderWidth , 0 ,
7943       XmNmarginHeight , SUMA_MARGIN ,
7944       XmNmarginWidth  , SUMA_MARGIN ,
7945       XmNshadowThickness, 2,
7946       XmNshadowType, XmSHADOW_ETCHED_IN,
7947       NULL);
7948 
7949    rc_gmamma = XtVaCreateWidget ("rowcolumn",
7950             xmRowColumnWidgetClass, SurfCont->Mainform,
7951             XmNpacking, XmPACK_TIGHT,
7952             XmNorientation , XmVERTICAL ,
7953             XmNmarginHeight, SUMA_MARGIN ,
7954             XmNmarginWidth , SUMA_MARGIN ,
7955             NULL);
7956 
7957 
7958    SurfCont->DispFrame = SUMA_CloseBhelp_Frame(rc_gmamma,
7959                      SUMA_cb_closeSurfaceCont, (XtPointer) ado,
7960                      "SurfCont",
7961                      "Close Surface controller", SUMA_closeSurfaceCont_help,
7962                      NULL, NULL, NULL, NULL);
7963 
7964    SUMA_Register_Widget_Help( SurfCont->DispFrame , 0,
7965                                  "SurfCont",
7966                                  "Surface Cont.",
7967 "The surface controller is for controlling the way surfaces and datasets "
7968 "defined over them are displayed. The same controller is shared by a "
7969 ":SPX::term:`family of surfaces <Family of surfaces>`:DEF:"
7970 "family of surfaces:SPX:"
7971 " and all the datasets displayed on them. Left and Right "
7972 "surfaces have separate controllers though in most cases actions on one "
7973 "hemisphere's controller are automatically mirrored on the contralateral "
7974 "side. The surface controller is initialized by the currently selected "
7975 "surface - the one said to be in focus.\n"
7976 ":SPX:"
7977 "You can launch the :ref:`Surface Controller <SurfCont>` with:"
7978 " :ref:`ctrl+s <LC_Ctrl+s>` or :menuselection:`View-->Object Controller`\n"
7979 "\n"
7980 ".. figure:: media/SurfCont.auto.ALL.jpg\n"
7981 "   :align: center\n"
7982 "   :name: media/SurfCont.auto.ALL.jpg\n"
7983 "\n"
7984 "   :ref:`(link)<media/SurfCont.auto.ALL.jpg>`\n"
7985 "\n\n"
7986 "   ..\n\n"
7987 ":DEF:"
7988 "You can launch the Surface Controller with:"
7989 "\n'ctrl+s' or 'View-->Object Controller'\n"
7990 ":SPX:"
7991 "\n") ;
7992 
7993 
7994    XtVaCreateManagedWidget ("sep", xmSeparatorWidgetClass, rc_gmamma , NULL);
7995 
7996    rc_mamma = XtVaCreateWidget ("rowcolumn",
7997             xmRowColumnWidgetClass, rc_gmamma,
7998             XmNpacking, XmPACK_TIGHT,
7999             XmNorientation , XmHORIZONTAL ,
8000             XmNmarginHeight, SUMA_MARGIN ,
8001             XmNmarginWidth , SUMA_MARGIN ,
8002             XmNleftAttachment , XmATTACH_FORM ,
8003             XmNtopAttachment  , XmATTACH_FORM ,
8004             XmNrightAttachment , XmATTACH_FORM ,
8005             NULL);
8006 
8007    rc_left = XtVaCreateWidget ("rowcolumn",
8008             xmRowColumnWidgetClass, rc_mamma,
8009             XmNpacking, XmPACK_TIGHT,
8010             XmNorientation , XmVERTICAL ,
8011             XmNmarginHeight, SUMA_MARGIN ,
8012             XmNmarginWidth , SUMA_MARGIN ,
8013 /*            XmNwidth, 317,
8014             XmNresizeWidth, False, */
8015             NULL);
8016 
8017    rc_right = XtVaCreateWidget ("rowcolumn",
8018             xmRowColumnWidgetClass, rc_mamma,
8019             XmNpacking, XmPACK_TIGHT,
8020             XmNorientation , XmVERTICAL ,
8021             XmNmarginHeight, SUMA_MARGIN ,
8022             XmNmarginWidth , SUMA_MARGIN ,
8023             NULL);
8024 
8025 
8026    {/*surface properties */
8027       Widget rc, label, rc_SurfProp, pb, www;
8028 
8029       /* put a frame */
8030       SurfCont->SurfFrame = XtVaCreateWidget ("dialog",
8031          xmFrameWidgetClass, rc_left,
8032          XmNshadowType , XmSHADOW_ETCHED_IN ,
8033          XmNshadowThickness , 5 ,
8034          XmNtraversalOn , False ,
8035          NULL);
8036 
8037       www = XtVaCreateManagedWidget ("Surface Properties",
8038             xmLabelWidgetClass, SurfCont->SurfFrame,
8039             XmNchildType, XmFRAME_TITLE_CHILD,
8040             XmNchildHorizontalAlignment, XmALIGNMENT_BEGINNING,
8041             NULL);
8042       SUMA_Register_Widget_Help( www , 0,
8043                                  "SurfCont->Surface_Properties",
8044                                  "Surface Properties",
8045             "Block providing information about selected surface."
8046             ":SPX:\n\n"
8047             ".. figure:: media/SurfCont.auto.Surface_Properties.jpg\n"
8048             "   :align: right\n"
8049             "   :name: media/SurfCont.auto.Surface_Properties.jpg\n"
8050             "\n"
8051             "   :ref:`(link)<media/SurfCont.auto.Surface_Properties.jpg>`\n"
8052             "   ..\n\n"
8053                   ":SPX:") ;
8054 
8055       rc_SurfProp = XtVaCreateWidget ("rowcolumn",
8056             xmRowColumnWidgetClass, SurfCont->SurfFrame,
8057             XmNpacking, XmPACK_TIGHT,
8058             XmNorientation , XmVERTICAL ,
8059             XmNmarginHeight, 0 ,
8060             XmNmarginWidth , 0 ,
8061             NULL);
8062 
8063       rc = XtVaCreateWidget ("rowcolumn",
8064             xmRowColumnWidgetClass, rc_SurfProp,
8065             XmNpacking, XmPACK_TIGHT,
8066             XmNorientation , XmHORIZONTAL ,
8067             XmNmarginHeight, 0 ,
8068             XmNmarginWidth , 0 ,
8069             NULL);
8070 
8071       /*put a label containing the surface name, number of nodes
8072       and number of facesets */
8073       lbl30 = SUMA_set_string_length(SUMA_ADO_Label(ado), ' ', 27);
8074       if (ado->do_type == SO_type) {
8075          SUMA_SurfaceObject *SO=(SUMA_SurfaceObject *)ado;
8076          if (lbl30) {
8077             sprintf( slabel,"%s\n%d nodes: %d tri.",
8078                      lbl30, SO->N_Node, SO->N_FaceSet);
8079             SUMA_free(lbl30); lbl30 = NULL;
8080          } else {
8081             sprintf(slabel,"???\n%d nodes: %d tri.", SO->N_Node, SO->N_FaceSet);
8082          }
8083       } else {
8084          SUMA_S_Err("This function is only for SOs");
8085          SUMA_RETURNe;
8086       }
8087       xmstmp = XmStringCreateLtoR (slabel, XmSTRING_DEFAULT_CHARSET);
8088          /* XmStringCreateLocalized(slabel) does not reliably
8089             handle newline characters q*/
8090       SurfCont->SurfInfo_label = XtVaCreateManagedWidget ("dingel-1",
8091                xmLabelWidgetClass, rc,
8092                XmNlabelString, xmstmp,
8093                NULL);
8094       XmStringFree (xmstmp);
8095       XtVaCreateManagedWidget (  "sep",
8096                                  xmSeparatorWidgetClass, rc,
8097                                  XmNorientation, XmVERTICAL, NULL );
8098       SUMA_Register_Widget_Help( SurfCont->SurfInfo_label, 1,
8099                                  "SurfCont->Surface_Properties->label",
8100                                  "Summary object information",
8101                                  "Summary object information" ) ;
8102 
8103       SurfCont->SurfInfo_pb = XtVaCreateWidget ("more",
8104          xmPushButtonWidgetClass, rc,
8105          NULL);
8106       XtAddCallback (SurfCont->SurfInfo_pb, XmNactivateCallback,
8107                      SUMA_cb_moreSurfInfo,
8108                         (XtPointer)SUMA_SurfCont_GetcurDOp(SurfCont));
8109       XtVaSetValues (SurfCont->SurfInfo_pb, XmNuserData,
8110                      (XtPointer)SUMA_SurfCont_GetcurDOp(SurfCont), NULL); /*
8111             Feb 23 04: XmNuserData is not used anymore.
8112             See notes for SUMA_cb_moreViewerInfo
8113             call for reasons why this was done...
8114 
8115             store the surface object SO/DO in userData
8116             I think it is more convenient than as data
8117             in the call back structure. This way it will
8118             be easy to change the SO that this same button
8119             might refer to.
8120             This is only for testing purposes, the pb_close
8121             button still expects SO in clientData*/
8122       SUMA_Register_Widget_Help( SurfCont->SurfInfo_pb , 1,
8123                                  "SurfCont->Surface_Properties->more",
8124                                  "More info on Surface",
8125                                  SUMA_SurfContHelp_more ) ;
8126       XtManageChild (SurfCont->SurfInfo_pb);
8127 
8128       XtManageChild (rc);
8129 
8130       XtVaCreateManagedWidget (  "sep",
8131                                  xmSeparatorWidgetClass, rc_SurfProp,
8132                                  XmNorientation, XmHORIZONTAL,NULL);
8133 
8134       rc = XtVaCreateWidget ("rowcolumn",
8135             xmRowColumnWidgetClass, rc_SurfProp,
8136             XmNpacking, XmPACK_TIGHT,
8137             XmNorientation , XmHORIZONTAL ,
8138             XmNmarginHeight, SUMA_MARGIN ,
8139             XmNmarginWidth , SUMA_MARGIN ,
8140             NULL);
8141 
8142       /* rendering menu option */
8143       SUMA_BuildMenuReset(0);
8144       SurfCont->RenderModeMenu =
8145             SUMA_Alloc_Menu_Widget(SW_N_SurfCont_Render);
8146       SUMA_BuildMenu (rc, XmMENU_OPTION,
8147                                  "Drw", '\0', YUP, RenderMode_Menu,
8148                                  (void *)SUMA_SurfCont_GetcurDOp(SurfCont),
8149                                  "SurfCont->Surface_Properties->Drw",
8150                         "Choose the rendering (drawing) mode for this surface.",
8151                                  SUMA_SurfContHelp_RenderMode,
8152                                  SurfCont->RenderModeMenu );
8153       XtManageChild (SurfCont->RenderModeMenu->mw[SW_SurfCont_Render]);
8154 
8155       SUMA_BuildMenuReset(0);
8156       SurfCont->TransModeMenu =
8157             SUMA_Alloc_Menu_Widget(SW_N_SurfCont_Trans);
8158       SUMA_BuildMenu (rc, XmMENU_OPTION,
8159                                  "Trn", '\0', YUP, TransMode_Menu,
8160                                  (void *)SUMA_SurfCont_GetcurDOp(SurfCont),
8161                                  "SurfCont->Surface_Properties->Trn",
8162                         "Choose the transparency for this surface.",
8163                                  SUMA_SurfContHelp_TransMode,
8164                                  SurfCont->TransModeMenu );
8165       XtManageChild (SurfCont->TransModeMenu->mw[SW_SurfCont_Trans]);
8166 
8167       pb = XtVaCreateWidget ("Dsets",
8168          xmPushButtonWidgetClass, rc,
8169          NULL);
8170       XtAddCallback (pb, XmNactivateCallback,
8171                      SUMA_cb_ToggleManagementColPlaneWidget,
8172                      (XtPointer)SUMA_SurfCont_GetcurDOp(SurfCont));
8173       SUMA_Register_Widget_Help( pb, 1, "SurfCont->Surface_Properties->Dsets",
8174                                   "Show/Hide Dataset (previously Color Plane) "
8175                                   "controllers",
8176                                   SUMA_SurfContHelp_Dsets ) ;
8177       XtManageChild (pb);
8178 
8179       XtManageChild (rc);
8180 
8181       XtManageChild (rc_SurfProp);
8182       XtManageChild (SurfCont->SurfFrame);
8183    }
8184 
8185    SUMA_LH("Xhair business");
8186    {  /* Xhair Controls */
8187       Widget rcv, www;
8188       /* put a frame */
8189       SurfCont->Xhair_fr = XtVaCreateWidget ("dialog",
8190          xmFrameWidgetClass, rc_left,
8191          XmNshadowType , XmSHADOW_ETCHED_IN ,
8192          XmNshadowThickness , 5 ,
8193          XmNtraversalOn , False ,
8194          NULL);
8195 
8196       www = XtVaCreateManagedWidget ("Xhair Info",
8197             xmLabelWidgetClass, SurfCont->Xhair_fr,
8198             XmNchildType, XmFRAME_TITLE_CHILD,
8199             XmNchildHorizontalAlignment, XmALIGNMENT_BEGINNING,
8200             NULL);
8201       SUMA_Register_Widget_Help( www , 0,
8202                                  "SurfCont->Xhair_Info",
8203                       "Crosshair Information",
8204                   ":SPX:\n\n"
8205                   ".. figure:: media/SurfCont.auto.Xhair_Info.jpg\n"
8206                   "   :align: right\n"
8207                   "   :name: media/SurfCont.auto.Xhair_Info.jpg\n"
8208                   "\n"
8209                   "   :ref:`(link)<media/SurfCont.auto.Xhair_Info.jpg>`\n"
8210                   "   ..\n\n"
8211                   ":SPX:") ;
8212       /* vertical row column */
8213       rcv = XtVaCreateWidget ("rowcolumn",
8214             xmRowColumnWidgetClass, SurfCont->Xhair_fr,
8215             XmNpacking, XmPACK_TIGHT,
8216             XmNorientation , XmVERTICAL ,
8217             XmNmarginHeight, 0 ,
8218             XmNmarginWidth , 0 ,
8219             NULL);
8220 
8221       /* create the widgets for the colormap stuff */
8222       SUMA_CreateXhairWidgets(rcv, ado);
8223 
8224 
8225       XtManageChild(rcv);
8226       XtManageChild(SurfCont->Xhair_fr);
8227    }  /* Xhair Controls */
8228 
8229    SUMA_LHv("\nDset Mapping, surface %s\n", SUMA_ADO_Label(ado));
8230    {  /* Dset Mapping */
8231       Widget rcv, www;
8232       /* put a frame */
8233       SurfCont->DsetMap_fr = XtVaCreateWidget ("dialog",
8234          xmFrameWidgetClass, rc_right,
8235          XmNrightAttachment , XmATTACH_FORM ,
8236          XmNleftAttachment, XmATTACH_WIDGET,
8237          XmNleftWidget, SurfCont->SurfFrame,
8238          XmNtopAttachment  , XmATTACH_FORM ,
8239          XmNshadowType , XmSHADOW_ETCHED_IN ,
8240          XmNshadowThickness , 5 ,
8241          XmNtraversalOn , False ,
8242          NULL);
8243 
8244       www = XtVaCreateManagedWidget ("Dset Mapping",
8245             xmLabelWidgetClass, SurfCont->DsetMap_fr,
8246             XmNchildType, XmFRAME_TITLE_CHILD,
8247             XmNchildHorizontalAlignment, XmALIGNMENT_BEGINNING,
8248             NULL);
8249       SUMA_Register_Widget_Help( www , 0,
8250                                  "SurfCont->Dset_Mapping",
8251                                  "Dset Color Mapping",
8252                   ":SPX:\n\n"
8253                   ".. figure:: media/SurfCont.auto.Dset_Mapping.jpg\n"
8254                   "   :align: right\n"
8255                   "   :name: media/SurfCont.auto.Dset_Mapping.jpg\n"
8256                   "\n"
8257                   "   :ref:`(link)<media/SurfCont.auto.Dset_Mapping.jpg>`\n"
8258                   "   ..\n\n"
8259                   ":SPX:") ;
8260 
8261       /* vertical row column */
8262       rcv = XtVaCreateWidget ("rowcolumn",
8263             xmRowColumnWidgetClass, SurfCont->DsetMap_fr,
8264             XmNpacking, XmPACK_TIGHT,
8265             XmNorientation , XmVERTICAL ,
8266             XmNmarginHeight, 0 ,
8267             XmNmarginWidth , 0 ,
8268             NULL);
8269 
8270       /* create the widgets for the colormap stuff */
8271       SUMA_CreateCmapWidgets(rcv, ado);
8272 
8273       XtManageChild(rcv);
8274 
8275       XtManageChild(SurfCont->DsetMap_fr);
8276    }
8277 
8278    SUMA_LH("Dset Controls");
8279    /* Dset Controls */
8280    {
8281        Widget rc, rcv, pb, www;
8282 
8283 
8284       /* put a frame */
8285       SurfCont->ColPlane_fr = XtVaCreateWidget ("dialog",
8286          xmFrameWidgetClass, rc_left,
8287          XmNshadowType , XmSHADOW_ETCHED_IN ,
8288          XmNshadowThickness , 5 ,
8289          XmNtraversalOn , False ,
8290          NULL);
8291 
8292       www = XtVaCreateManagedWidget ("Dset Controls",
8293             xmLabelWidgetClass, SurfCont->ColPlane_fr,
8294             XmNchildType, XmFRAME_TITLE_CHILD,
8295             XmNchildHorizontalAlignment, XmALIGNMENT_BEGINNING,
8296             NULL);
8297       SUMA_Register_Widget_Help( www , 0,
8298                                  "SurfCont->Dset_Controls",
8299                                  "Dset Controls",
8300                   ":SPX:\n\n"
8301                   ".. figure:: media/SurfCont.auto.Dset_Controls.jpg\n"
8302                   "   :align: right\n"
8303                   "   :name: media/SurfCont.auto.Dset_Controls.jpg\n"
8304                   "\n"
8305                   "   :ref:`(link)<media/SurfCont.auto.Dset_Controls.jpg>`\n"
8306                   "   ..\n\n"
8307                   ":SPX:") ;
8308       /* vertical row column */
8309       rcv = XtVaCreateWidget ("rowcolumn",
8310             xmRowColumnWidgetClass, SurfCont->ColPlane_fr,
8311             XmNpacking, XmPACK_TIGHT,
8312             XmNorientation , XmVERTICAL ,
8313             XmNmarginHeight, 0 ,
8314             XmNmarginWidth , 0 ,
8315             NULL);
8316 
8317       /* row column for label*/
8318       rc = XtVaCreateWidget ("rowcolumn",
8319             xmRowColumnWidgetClass, rcv,
8320             XmNpacking, XmPACK_TIGHT,
8321             XmNorientation , XmHORIZONTAL ,
8322             XmNmarginHeight, 0 ,
8323             XmNmarginWidth , 0 ,
8324             NULL);
8325 
8326       /*put a label containing the surface name,
8327          number of nodes and number of facesets */
8328       {
8329          char *Dset_tit[]  =  {  "Lbl", "Par", NULL };
8330          char *Dset_hint[] =  {  "Label of Dset",
8331                                  "Parent surface of Dset", NULL };
8332          char *Dset_help[] =  {  SUMA_SurfContHelp_DsetLblTblr0,
8333                                  SUMA_SurfContHelp_DsetLblTblr1, NULL };
8334          int colw[]={ 3, 27};
8335          SUMA_CreateTable(rc,
8336             2, 2,
8337             "SurfCont->Dset_Controls->Lbl+Par",
8338             Dset_tit, NULL,
8339             Dset_hint, NULL,
8340             Dset_help, NULL,
8341             colw, NOPE, SUMA_string,
8342             NULL, NULL,
8343             NULL, NULL,
8344             NULL, NULL,
8345             SurfCont->ColPlaneLabelTable);
8346       }
8347       XtManageChild (rc);
8348 
8349       /* add a rc for the colorplane order and opacity */
8350       rc = XtVaCreateWidget ("rowcolumn",
8351          xmRowColumnWidgetClass, rcv,
8352          XmNpacking, XmPACK_TIGHT,
8353          XmNorientation , XmHORIZONTAL ,
8354          NULL);
8355 
8356       SUMA_CreateArrowField ( rc, "Ord",
8357                            1, 0, 20, 1,
8358                            2, SUMA_int,
8359                            NOPE,
8360                            SUMA_cb_ColPlane_NewOrder, (void *)ado,
8361                            "SurfCont->Dset_Controls->Ord",
8362                            SUMA_SurfCont_ColPlaneOrder_hint,
8363                            SUMA_SurfContHelp_DsetOrd,
8364                            SurfCont->ColPlaneOrder);
8365 
8366       SUMA_CreateArrowField ( rc, "Opa",
8367                            1, 0.0, 1.0, 0.1,
8368                            3, SUMA_float,
8369                            NOPE,
8370                            SUMA_cb_ColPlane_NewOpacity, (void *)ado,
8371                            "SurfCont->Dset_Controls->Opa",
8372                            SUMA_SurfCont_ColPlaneOpacity_hint,
8373                            SUMA_SurfContHelp_DsetOpa,
8374                            SurfCont->ColPlaneOpacity);
8375 
8376       /* manage  rc */
8377       XtManageChild (rc);
8378 
8379       /* add a rc for the colorplane brightness factor and visibility */
8380       rc = XtVaCreateWidget ("rowcolumn",
8381          xmRowColumnWidgetClass, rcv,
8382          XmNpacking, XmPACK_TIGHT,
8383          XmNorientation , XmHORIZONTAL ,
8384          NULL);
8385 
8386       SUMA_CreateArrowField ( rc, "Dim",
8387                            1, 0.1, 2, 0.1,
8388                            3, SUMA_float,
8389                            YUP,
8390                            SUMA_cb_ColPlane_NewDimFact, (void *)ado,
8391                            "SurfCont->Dset_Controls->Dim",
8392                            SUMA_SurfCont_ColPlaneDim_hint,
8393                            SUMA_SurfContHelp_DsetDim,
8394                            SurfCont->ColPlaneDimFact);
8395 
8396       #if 0
8397       SurfCont->ColPlaneShow_tb = XtVaCreateManagedWidget("view",
8398             xmToggleButtonWidgetClass, rc, NULL);
8399       XmToggleButtonSetState (SurfCont->ColPlaneShow_tb, YUP, NOPE);
8400       XtAddCallback (SurfCont->ColPlaneShow_tb,
8401                   XmNvalueChangedCallback, SUMA_cb_ColPlaneShow_toggled, ado);
8402       SUMA_Register_Widget_Help(SurfCont->ColPlaneShow_tb , 1,
8403                                 "SurfCont->Dset_Controls->view",
8404                                 "Shows/Hides Dset.",
8405                                 SUMA_SurfContHelp_DsetView ) ;
8406       SUMA_SET_SELECT_COLOR(SurfCont->ColPlaneShow_tb);
8407      #else
8408       SUMA_BuildMenuReset(0);
8409       SurfCont->DsetViewModeMenu =
8410          SUMA_Alloc_Menu_Widget(SW_N_SurfCont_DsetView);
8411       SUMA_BuildMenu (rc, XmMENU_OPTION,
8412                       "Dsp", '\0', YUP, DsetViewMode_Menu,
8413                       (void *)SUMA_SurfCont_GetcurDOp(SurfCont),
8414                       "SurfCont->Dset_Controls->Dsp",
8415                       "Choose the rendering mode for this dataset.",
8416                       SUMA_SurfContHelp_DsetViewMode,
8417                       SurfCont->DsetViewModeMenu );
8418       XtManageChild (SurfCont->DsetViewModeMenu->mw[SW_SurfCont_DsetView]);
8419       SUMA_Set_Menu_Widget(SurfCont->DsetViewModeMenu,
8420                     SUMA_ShowMode2ShowModeMenuItem(
8421                                  curColPlane->ShowMode));
8422 
8423       #endif
8424       SurfCont->ColPlaneShowOneFore_tb =
8425          XtVaCreateManagedWidget("1",
8426                                  xmToggleButtonWidgetClass, rc, NULL);
8427       XmToggleButtonSetState (SurfCont->ColPlaneShowOneFore_tb,
8428                               SurfCont->ShowCurForeOnly, NOPE);
8429       XtAddCallback (SurfCont->ColPlaneShowOneFore_tb,
8430                      XmNvalueChangedCallback,
8431                      SUMA_cb_ColPlaneShowOneFore_toggled, ado);
8432 
8433       SUMA_Register_Widget_Help(SurfCont->ColPlaneShowOneFore_tb , 1,
8434                                 "SurfCont->Dset_Controls->1",
8435              "Show ONLY ONE selected Dset. Foreground only. (BHelp for more)",
8436                                  SUMA_SurfContHelp_DsetViewOne ) ;
8437       SUMA_SET_SELECT_COLOR(SurfCont->ColPlaneShowOneFore_tb);
8438 
8439       /* manage  rc */
8440       XtManageChild (rc);
8441 
8442       XtVaCreateManagedWidget (  "sep",
8443                                  xmSeparatorWidgetClass, rcv,
8444                                  XmNorientation, XmHORIZONTAL,NULL);
8445 
8446       /* row column for Switch, Load, Delete */
8447       rc = XtVaCreateWidget ("rowcolumn",
8448          xmRowColumnWidgetClass, rcv,
8449          XmNpacking, XmPACK_TIGHT,
8450          XmNorientation , XmHORIZONTAL ,
8451          NULL);
8452 
8453       /* put a push button to switch between color planes */
8454       SurfCont->SwitchDsetlst =
8455             SUMA_AllocateScrolledList ("Switch Dset",
8456                      SUMA_LSP_SINGLE,
8457                      NOPE, NOPE, /* duplicate deletion, no sorting */
8458                      SurfCont->TLS, SWP_POINTER,
8459                      125,
8460                      SUMA_cb_SelectSwitchColPlane, (void *)ado,
8461                      SUMA_cb_SelectSwitchColPlane, (void *)ado,
8462                      SUMA_cb_CloseSwitchColPlane, NULL);
8463 
8464 
8465       pb = XtVaCreateWidget ("Switch Dset",
8466          xmPushButtonWidgetClass, rc,
8467          NULL);
8468       XtAddCallback (pb, XmNactivateCallback,
8469                      SUMA_cb_SurfCont_SwitchColPlane, (XtPointer)ado);
8470       SUMA_Register_Widget_Help(pb, 1, "SurfCont->Dset_Controls->Switch_Dset",
8471                                 "Switch between datasets",
8472                                 SUMA_SurfContHelp_DsetSwitch ) ;
8473       XtManageChild (pb);
8474 
8475       pb = XtVaCreateWidget ("Load Dset",
8476             xmPushButtonWidgetClass, rc,
8477             NULL);
8478          XtAddCallback (pb, XmNactivateCallback,
8479                         SUMA_cb_Dset_Load, (XtPointer) ado);
8480          SUMA_Register_Widget_Help(pb, 1, "SurfCont->Dset_Controls->Load_Dset",
8481                                    "Load a new dataset (much more with BHelp)",
8482                                    SUMA_SurfContHelp_DsetLoad ) ;
8483          XtManageChild (pb);
8484 
8485       pb = XtVaCreateWidget ("Delete",
8486          xmPushButtonWidgetClass, rc,
8487          NULL);
8488       XtAddCallback (pb, XmNactivateCallback,
8489                      SUMA_cb_ColPlane_Delete, (XtPointer) ado);
8490       /* XtManageChild (pb); */ /* Not ready for this one yet */
8491 
8492       pb = XtVaCreateWidget ("Load Col",
8493          xmPushButtonWidgetClass, rc,
8494          NULL);
8495       XtAddCallback (pb, XmNactivateCallback,
8496                      SUMA_cb_ColPlane_Load, (XtPointer) ado);
8497       SUMA_Register_Widget_Help(pb, 1, "SurfCont->Dset_Controls->Load_Col",
8498                                 "Load a new color plane (more with BHelp)",
8499                                 SUMA_SurfContHelp_DsetLoadCol) ;
8500       XtManageChild (pb);
8501 
8502 
8503       XtManageChild (rc);
8504       /* manage vertical row column */
8505       XtManageChild (rcv);
8506 
8507       XtManageChild (SurfCont->ColPlane_fr);
8508    }
8509 
8510 
8511    if (SUMAg_CF->X->UseSameSurfCont) {
8512       Widget rc=NULL;
8513       /* put something to cycle through objects */
8514       if ((rc = SUMA_FindChildWidgetNamed(SurfCont->DispFrame, "rowcolumnCBF"))){
8515          XtVaCreateManagedWidget (  "sep",
8516                               xmSeparatorWidgetClass, rc,
8517                               XmNorientation, XmVERTICAL,NULL);
8518 
8519          pb = XtVaCreateWidget ("All Objs.",
8520                   xmPushButtonWidgetClass, rc,
8521                   NULL);
8522          XtAddCallback (pb, XmNactivateCallback,
8523                         SUMA_cb_AllConts, NULL);
8524          SUMA_Register_Widget_Help(pb, 1, "SurfCont->Disp_Cont->AllObjs",
8525                                 "Initialize Controllers for All Objects",
8526                                 SUMA_SurfContHelp_AllObjs) ;
8527          XtManageChild (pb);
8528          SUMA_CreateArrowField ( rc, "Switch",
8529                            1, 1, 20, 1,
8530                            2, SUMA_int,
8531                            YUP,
8532                            SUMA_cb_SurfCont_SwitchPage, (void *)ado,
8533                            "SurfCont->Disp_Cont->Switch",
8534                            "Switch to other object controller",
8535                            SUMA_Switch_Cont_BHelp,
8536                            SurfCont->SurfContPage);
8537          xmstmp = XmStringCreateLtoR (SUMA_ADO_CropLabel(ado,
8538                                           SUMA_SURF_CONT_SWITCH_LABEL_LENGTH),
8539                                       XmSTRING_DEFAULT_CHARSET);
8540          SurfCont->SurfContPage_label = XtVaCreateManagedWidget ("dingel-2",
8541                xmLabelWidgetClass, rc,
8542                XmNlabelString, xmstmp,
8543                NULL);
8544          XmStringFree (xmstmp);
8545       }
8546    }
8547    SUMA_LHv("Management ...%p %p %p %p %p\n",
8548             rc_right, rc_left, rc_mamma, SurfCont->Mainform, SurfCont->Page);
8549 
8550    XtManageChild (rc_right);
8551    XtManageChild (rc_left);
8552    XtManageChild (rc_mamma);
8553    XtManageChild (rc_gmamma);
8554    XtManageChild (SurfCont->Mainform);
8555    if (SUMAg_CF->X->UseSameSurfCont) XtManageChild (SurfCont->Page);
8556 
8557    #if SUMA_CONTROLLER_AS_DIALOG
8558    #else
8559    /** Feb 03/03: pop it up if it is a topLevelShellWidgetClass,
8560    you should do the popping after all the widgets have been created.
8561    Otherwise, the window does not size itself correctly when open */
8562    XtPopup(SurfCont->TLS, XtGrabNone);
8563    #endif
8564 
8565    /* realize the widget */
8566    if (SUMAg_CF->X->UseSameSurfCont) XtManageChild (SUMAg_CF->X->SC_Notebook);
8567    XtRealizeWidget (SurfCont->TLS);
8568 
8569    SUMA_LH("%s",slabel);
8570    SUMA_free (slabel);
8571 
8572    /* Mark as open */
8573    SUMA_MarkSurfContOpen(1,ado);
8574 
8575    SUMA_LHv("Marked %s's controller as open.\n", SUMA_ADO_Label(ado));
8576 
8577    /* initialize the left side
8578       (no need here, that's done in SUMA_cb_viewSurfaceCont)*/
8579    /* SUMA_Init_SurfCont_SurfParam(ado); */
8580 
8581    /* initialize the ColorPlane frame if possible
8582    Do it here rather than above because scale goes crazy
8583    when parent widgets are being resized*/
8584 
8585    if (!(over0 = SUMA_ADO_Overlay0(ado))) {
8586       SUMA_SurfaceObject *SOp=NULL, *SO=(SUMA_SurfaceObject *)ado;
8587       SUMA_LH("NO Overlays yet for this surface\n");
8588       /* happens in very few instances when both child and parent
8589       are in the first view and the child is selected before the surface
8590       controller for that family is ever opened! */
8591       SOp = SUMA_findSOp_inDOv(SO->LocalDomainParentID, SUMAg_DOv, SUMAg_N_DOv);
8592       if (!SOp) {
8593          SUMA_SL_Err("Failed to find parent, should not be.");
8594       }
8595 
8596       if (!SUMA_GetOverlaysFromParent(SO, SOp)) {
8597          SUMA_SL_Err("Failed to copy overlays!");
8598          SUMA_RETURNe;
8599       }
8600    }
8601 
8602    if (SUMA_ADO_N_Overlays(ado)>0) {
8603       SUMA_LH("Initializing ColPlaneShell");
8604       SUMA_InitializeColPlaneShell(ado, curColPlane); /* Used to use Over0,
8605                               But that is not good when Over0 is not
8606                               the current color Plane. This
8607                               function no longer gets down to here without
8608                            cutColPlane, so we should be good to go May 4th 2015*/
8609       #ifdef NONONO /* It looks like I do not need this anymore
8610                        Used to be #idef DARWIN */
8611       /* Sometimes color maps do not show up on mac when you first
8612          open the surface controller */
8613       SUMA_LH("Darwining");
8614       SUMA_SwitchColPlaneCmap(ado, SUMA_CmapOfPlane(curColPlane));
8615       #endif
8616    }
8617 
8618    #if USING_LESSTIF
8619    SUMA_LH("Less tif fix");
8620    /* A quick fix to ensure Dset_Mapping
8621       gets displayed properly the first time */
8622    SUMA_cb_ToggleManagementColPlaneWidget(NULL, (XtPointer)(&ado), NULL);
8623    SUMA_cb_ToggleManagementColPlaneWidget(NULL, (XtPointer)(&ado), NULL);
8624    #endif
8625 
8626    SUMA_LH("going home.");
8627 
8628    SUMA_MarkSurfContOpen(1, ado);
8629 
8630    SUMA_RETURNe;
8631 }
8632 
SUMA_cb_createSurfaceCont_GLDO(Widget w,XtPointer data,XtPointer callData)8633 void SUMA_cb_createSurfaceCont_GLDO(Widget w, XtPointer data,
8634                                      XtPointer callData)
8635 {
8636    static char FuncName[] = {"SUMA_cb_createSurfaceCont_GLDO"};
8637    Widget tl, pb, form,
8638           rc_left, rc_right, rc_mamma, rc_gmamma, tls=NULL;
8639    Display *dpy;
8640    SUMA_ALL_DO *ado;
8641    char *slabel, *lbl30, *sss=NULL;
8642    XmString xmstmp;
8643    SUMA_X_SurfCont *SurfCont=NULL;
8644    SUMA_OVERLAYS *curColPlane=NULL, *over0=NULL;
8645    SUMA_GRAPH_SAUX *GSaux = NULL;
8646    SUMA_Boolean LocalHead = NOPE;
8647 
8648    SUMA_ENTRY;
8649 
8650    ado = (SUMA_ALL_DO *)data;
8651    if (ado->do_type != GRAPH_LINK_type) {
8652       SUMA_S_Errv("Calling me with (%s) other than SDSET_GRAPH_Link type,\n"
8653                   "I don't like that, call me with GLDO",
8654                   SUMA_ObjectTypeCode2ObjectTypeName(ado->do_type));
8655       SUMA_RETURNe;
8656    }
8657    SUMA_LHv("Creating SurfaceCont for type %s, label %s\n",
8658             ADO_TNAME(ado), SUMA_ADO_Label(ado));
8659    if (LocalHead) {
8660       SUMA_DUMP_TRACE("Creating SurfaceCont");
8661    }
8662    if (!(SurfCont = SUMA_ADO_Cont(ado))) {
8663       SUMA_S_Errv("Failed to get Controller for ado %s\n",
8664                   SUMA_ADO_Label(ado));
8665       SUMA_RETURNe;
8666    }
8667    if (!(GSaux = SUMA_ADO_GSaux(ado))) {
8668       SUMA_S_Errv("No GSaux for ado %s\n",
8669                   SUMA_ADO_Label(ado));
8670       SUMA_RETURNe;
8671    }
8672    if (!SUMA_SurfCont_SetcurDOp(SurfCont, ado)) {
8673       SUMA_S_Errv("Failed to Set curDOp for %s\n",
8674                   SUMA_ADO_Label(ado));
8675       SUMA_RETURNe;
8676    }
8677    if (!(curColPlane = SUMA_ADO_CurColPlane(ado))) {
8678       SUMA_S_Errv("Failed to get current col plane for ado %s\n",
8679                   SUMA_ADO_Label(ado));
8680       SUMA_RETURNe;
8681    }
8682    if (SurfCont->TLS) {
8683       fprintf (SUMA_STDERR,
8684                "Error %s: SurfCont->TopLevelShell!=NULL.\n"
8685                "Should not be here.\n", FuncName);
8686       SUMA_RETURNe;
8687    }
8688 
8689    tl = SUMA_GetTopShell(w); /* top level widget */
8690    dpy = XtDisplay(tl);
8691 
8692    slabel = (char *)SUMA_malloc(sizeof(char) *
8693                                  (strlen(SUMA_ADO_Label(ado)) + 100));
8694    if (strlen(SUMA_ADO_Label(ado)) > 40) {
8695       char *tmpstr=NULL;
8696       tmpstr = SUMA_truncate_string(SUMA_ADO_Label(ado), 40);
8697       if (tmpstr) {
8698          sprintf(slabel,"[%s] %s Dset Controller",
8699                         tmpstr, SUMA_ADO_ContName(ado));
8700          free(tmpstr); tmpstr=NULL;
8701       }
8702    } else {
8703       sprintf(slabel,"[%s] %s Dset Controller",
8704                      SUMA_ADO_Label(ado), SUMA_ADO_ContName(ado));
8705    }
8706 
8707    /* March 12 08: Made font8 default for surface controller */
8708    if (SUMA_isEnv("SUMA_SurfContFontSize", "BIG")) {
8709       sss = "font9";
8710    } else {
8711       sss = "font8";
8712    }
8713 
8714    SUMA_LH("Creating dialog shell.");
8715    if (!SUMAg_CF->X->UseSameSurfCont ||
8716        !SUMAg_CF->X->CommonSurfContTLW) { /* need a new one */
8717       #if SUMA_CONTROLLER_AS_DIALOG /* xmDialogShellWidgetClass,
8718                                        topLevelShellWidgetClass*/
8719       tls = XtVaCreatePopupShell (sss,
8720          XmNtitle, slabel,
8721          xmDialogShellWidgetClass, tl,
8722          XmNallowShellResize, True, /* let code resize shell */
8723          XmNdeleteResponse, XmDO_NOTHING,
8724          NULL);
8725       #else
8726       SUMA_LH("Creating toplevel shell.");
8727       /** Feb 03/03:    I was using XtVaCreatePopupShell to create a
8728                         topLevelShellWidgetClass.
8729                         XtVaCreatePopupShell is used to create dialog
8730                         shells not toplevel or appshells.
8731                         Of course, it made no difference! */
8732       tls = XtVaAppCreateShell (sss, "Suma",
8733          topLevelShellWidgetClass, SUMAg_CF->X->DPY_controller1 ,
8734          XmNtitle, slabel,
8735          XmNdeleteResponse, XmDO_NOTHING,
8736          NULL);
8737       #endif
8738 
8739       /* allow for code to resize the shell */
8740       XtVaSetValues (tls,
8741             XmNresizePolicy , XmRESIZE_NONE ,
8742             XmNallowShellResize , True ,       /* let code resize shell */
8743             NULL);
8744 
8745       /* handle the close button from window manager */
8746       XmAddWMProtocolCallback(/* make "Close" window menu work */
8747          tls,
8748          XmInternAtom( dpy , "WM_DELETE_WINDOW" , False ) ,
8749          SUMA_cb_closeSurfaceCont, (XtPointer) ado) ;
8750 
8751       if (SUMAg_CF->X->UseSameSurfCont) {
8752          Widget scroller;
8753          SUMAg_CF->X->CommonSurfContTLW = tls;
8754          SUMAg_CF->X->SC_Notebook =
8755             XtVaCreateWidget("ControllerBook", xmNotebookWidgetClass,
8756                              SUMAg_CF->X->CommonSurfContTLW,
8757                              XmNbindingWidth, XmNONE,
8758                              XmNbackPageNumber, 0,
8759                              XmNmajorTabSpacing, 0,
8760                              XmNminorTabSpacing, 0,
8761                              NULL);
8762             /*XmCreateNotebook (SUMAg_CF->X->CommonSurfContTLW, "ControllerBook",
8763                               NULL, 0);
8764               XtVaSetValues(SUMAg_CF->X->SC_Notebook,
8765                           XmNbindingWidth, XmNONE,
8766                           NULL); */
8767 
8768 
8769          /* Kill the scroller from hell otherwise no keyboard input
8770             gets to the baby widgets. Better write my own scroller
8771             if need be in the future */
8772          scroller = XtNameToWidget (SUMAg_CF->X->SC_Notebook, "PageScroller");
8773          XtUnmanageChild (scroller);
8774       }
8775    }
8776 
8777    if (SUMAg_CF->X->UseSameSurfCont) {
8778       SurfCont->TLS = SUMAg_CF->X->CommonSurfContTLW;
8779    } else {
8780       SurfCont->TLS = tls;
8781    }
8782 
8783    if (!SurfCont->TLS) {
8784       SUMA_S_Err("Bad logic");
8785       SUMA_RETURNe;
8786    }
8787 
8788    SUMA_LH("Widgets...");
8789    if (SUMAg_CF->X->UseSameSurfCont) {
8790       Arg args[20];
8791       /* add the page */
8792       XtSetArg (args[0], XmNnotebookChildType, XmPAGE);
8793       SurfCont->Page =
8794          XmCreateRowColumn (SUMAg_CF->X->SC_Notebook,
8795                      SUMA_ADO_Label(ado)?SUMA_ADO_Label(ado):"page",
8796                                               args, 1);
8797    }
8798 
8799    /* create a form widget, manage it at the end ...*/
8800    SurfCont->Mainform = XtVaCreateWidget ("dialog",
8801       xmFormWidgetClass, SurfCont->Page ?
8802                               SurfCont->Page:SurfCont->TLS,
8803       XmNborderWidth , 0 ,
8804       XmNmarginHeight , SUMA_MARGIN ,
8805       XmNmarginWidth  , SUMA_MARGIN ,
8806       XmNshadowThickness, 2,
8807       XmNshadowType, XmSHADOW_ETCHED_IN,
8808       NULL);
8809 
8810    rc_gmamma = XtVaCreateWidget ("rowcolumn",
8811             xmRowColumnWidgetClass, SurfCont->Mainform,
8812             XmNpacking, XmPACK_TIGHT,
8813             XmNorientation , XmVERTICAL ,
8814             XmNmarginHeight, SUMA_MARGIN ,
8815             XmNmarginWidth , SUMA_MARGIN ,
8816             XmNtopAttachment  , XmATTACH_FORM ,
8817             XmNbottomAttachment  , XmATTACH_FORM ,
8818             NULL);
8819 
8820 
8821    SurfCont->DispFrame = SUMA_CloseBhelp_Frame(rc_gmamma,
8822                      SUMA_cb_closeSurfaceCont, (XtPointer) ado,
8823                      "GraphCont",
8824                      "Close Graph controller", SUMA_closeSurfaceCont_help,
8825                      NULL, NULL, NULL, NULL);
8826 
8827    SUMA_Register_Widget_Help( SurfCont->DispFrame , 0,
8828                               "GraphCont",
8829                               "Graph Cont.",
8830 "The graph controller is for controlling the way graphs (matrices) are rendered.  Each graph gets its own controller. You can use the switch button above to switch between them. The graph controller is initialized by the graph of the last selected edge/cell.\n After you have selected an edge, "
8831 ":SPX:"
8832 "you can launch the :ref:`Graph Controller <VolCont>` with:"
8833 " :ref:`ctrl+s <LC_Ctrl+s>` or :menuselection:`View-->Object Controller`\n"
8834 "\n"
8835 ".. figure:: media/GraphCont.auto.ALL.jpg\n"
8836 "   :align: center\n"
8837 "   :name: media/GraphCont.auto.ALL.jpg\n"
8838 "\n"
8839 "   :ref:`(link)<media/GraphCont.auto.ALL.jpg>`\n"
8840 "\n\n"
8841 "   ..\n\n"
8842 ":DEF:"
8843 "you can launch the Graph Controller with:"
8844 "\n'ctrl+s' or 'View-->Object Controller'\n"
8845 ":SPX:"
8846 "\n") ;
8847 
8848    XtVaCreateManagedWidget ("sep", xmSeparatorWidgetClass, rc_gmamma , NULL);
8849 
8850    rc_mamma = XtVaCreateWidget ("rowcolumn",
8851             xmRowColumnWidgetClass, rc_gmamma,
8852             XmNpacking, XmPACK_TIGHT,
8853             XmNorientation , XmHORIZONTAL ,
8854             XmNmarginHeight, SUMA_MARGIN ,
8855             XmNmarginWidth , SUMA_MARGIN ,
8856             XmNleftAttachment , XmATTACH_FORM ,
8857             XmNtopAttachment  , XmATTACH_FORM ,
8858             XmNrightAttachment , XmATTACH_FORM ,
8859             NULL);
8860 
8861    rc_left = XtVaCreateWidget ("rowcolumn",
8862             xmRowColumnWidgetClass, rc_mamma,
8863             XmNpacking, XmPACK_TIGHT,
8864             XmNorientation , XmVERTICAL ,
8865             XmNmarginHeight, SUMA_MARGIN ,
8866             XmNmarginWidth , SUMA_MARGIN ,
8867 /*            XmNwidth, 317,
8868             XmNresizeWidth, False, */
8869             NULL);
8870 
8871    rc_right = XtVaCreateWidget ("rowcolumn",
8872             xmRowColumnWidgetClass, rc_mamma,
8873             XmNpacking, XmPACK_TIGHT,
8874             XmNorientation , XmVERTICAL ,
8875             XmNmarginHeight, SUMA_MARGIN ,
8876             XmNmarginWidth , SUMA_MARGIN ,
8877             NULL);
8878 
8879 
8880    {/*surface properties */
8881       Widget rc, label, rc_SurfProp, pb, www;
8882 
8883       /* put a frame */
8884       SurfCont->SurfFrame = XtVaCreateWidget ("dialog",
8885          xmFrameWidgetClass, rc_left,
8886          XmNshadowType , XmSHADOW_ETCHED_IN ,
8887          XmNshadowThickness , 5 ,
8888          XmNtraversalOn , False ,
8889          NULL);
8890 
8891       www = XtVaCreateManagedWidget ("Graph Dset Properties",
8892             xmLabelWidgetClass, SurfCont->SurfFrame,
8893             XmNchildType, XmFRAME_TITLE_CHILD,
8894             XmNchildHorizontalAlignment, XmALIGNMENT_BEGINNING,
8895             NULL);
8896       SUMA_Register_Widget_Help( www , 0,
8897                               "GraphCont->Graph_Dset_Properties",
8898                               "Properties of graph dset",
8899             ":SPX:\n\n"
8900             ".. figure:: media/GraphCont.auto.Graph_Dset_Properties.jpg\n"
8901             "   :align: right\n"
8902             "   :name: media/GraphCont.auto.Graph_Dset_Properties.jpg\n"
8903             "\n"
8904             "   :ref:`(link)<media/GraphCont.auto.Graph_Dset_Properties.jpg>`\n"
8905             "   ..\n\n"
8906             ":SPX:") ;
8907 
8908       rc_SurfProp = XtVaCreateWidget ("rowcolumn",
8909             xmRowColumnWidgetClass, SurfCont->SurfFrame,
8910             XmNpacking, XmPACK_TIGHT,
8911             XmNorientation , XmVERTICAL ,
8912             XmNmarginHeight, 0 ,
8913             XmNmarginWidth , 0 ,
8914             NULL);
8915 
8916       rc = XtVaCreateWidget ("rowcolumn",
8917             xmRowColumnWidgetClass, rc_SurfProp,
8918             XmNpacking, XmPACK_TIGHT,
8919             XmNorientation , XmHORIZONTAL ,
8920             XmNmarginHeight, 0 ,
8921             XmNmarginWidth , 0 ,
8922             NULL);
8923 
8924       /*put a label containing the surface name, number of nodes
8925       and number of facesets */
8926       lbl30 = SUMA_set_string_length(
8927             SDSET_LABEL(SUMA_find_GLDO_Dset((SUMA_GraphLinkDO*)ado)), ' ', 27);
8928       if (lbl30) {
8929          sprintf(slabel,"%s \n%d edges, variant %s.",
8930                      lbl30, SUMA_ADO_N_Datum(ado), SUMA_ADO_variant(ado));
8931          SUMA_free(lbl30); lbl30 = NULL;
8932       } else {
8933          sprintf(slabel,"???\n%d edges.",SUMA_ADO_N_Datum(ado));
8934       }
8935 
8936       xmstmp = XmStringCreateLtoR (slabel, XmSTRING_DEFAULT_CHARSET);
8937          /* XmStringCreateLocalized(slabel) does not reliably
8938             handle newline characters q*/
8939       SurfCont->SurfInfo_label = XtVaCreateManagedWidget ("dingel-3",
8940                xmLabelWidgetClass, rc,
8941                XmNlabelString, xmstmp,
8942                NULL);
8943       XmStringFree (xmstmp);
8944       SUMA_Register_Widget_Help( SurfCont->SurfInfo_label, 1,
8945                                  "GraphCont->Graph_Dset_Properties->label",
8946                                  "Summary object information",
8947                                  "Summary object information" ) ;
8948 
8949       XtVaCreateManagedWidget (  "sep",
8950                                  xmSeparatorWidgetClass, rc,
8951                                  XmNorientation, XmVERTICAL, NULL );
8952 
8953       SurfCont->SurfInfo_pb = XtVaCreateWidget ("more",
8954          xmPushButtonWidgetClass, rc,
8955          NULL);
8956       XtAddCallback (SurfCont->SurfInfo_pb, XmNactivateCallback,
8957                      SUMA_cb_moreSurfInfo,
8958                         (XtPointer)SUMA_SurfCont_GetcurDOp(SurfCont));
8959       XtVaSetValues (SurfCont->SurfInfo_pb, XmNuserData,
8960                      (XtPointer)SUMA_SurfCont_GetcurDOp(SurfCont), NULL);
8961 
8962       SUMA_Register_Widget_Help( SurfCont->SurfInfo_pb , 1,
8963                                  "GraphCont->Graph_Dset_Properties->more",
8964                                  "More info on Graph Dset" ,
8965                                  SUMA_SurfContHelp_more ) ;
8966       XtManageChild (SurfCont->SurfInfo_pb);
8967 
8968       XtManageChild (rc);
8969 
8970       #if 0 /* This section is for widgets that have no use yet
8971                for graph dsets. If they don't get revived soon,
8972                kill them all in the future.     May 2013 */
8973       XtVaCreateManagedWidget (  "sep",
8974                                  xmSeparatorWidgetClass, rc_SurfProp,
8975                                  XmNorientation, XmHORIZONTAL,NULL);
8976 
8977       rc = XtVaCreateWidget ("rowcolumn",
8978             xmRowColumnWidgetClass, rc_SurfProp,
8979             XmNpacking, XmPACK_TIGHT,
8980             XmNorientation , XmHORIZONTAL ,
8981             XmNmarginHeight, SUMA_MARGIN ,
8982             XmNmarginWidth , SUMA_MARGIN ,
8983             NULL);
8984 
8985       /* rendering menu option */
8986       SUMA_BuildMenuReset(0);
8987       SurfCont->RenderModeMenu =
8988             SUMA_Alloc_Menu_Widget(SW_N_SurfCont_Render);
8989       SUMA_BuildMenu (rc, XmMENU_OPTION,
8990                                  "Drw", '\0', YUP, RenderMode_Menu,
8991                                  (void *)SUMA_SurfCont_GetcurDOp(SurfCont),
8992                                  "GraphCont->NOT_USED_YET->Drw",
8993                         "Choose the rendering (drawing) mode for this graph.",
8994                                  SUMA_SurfContHelp_RenderMode,
8995                                  SurfCont->RenderModeMenu );
8996       XtManageChild (SurfCont->RenderModeMenu->mw[SW_SurfCont_Render]);
8997 
8998       SUMA_BuildMenuReset(0);
8999       SurfCont->TransModeMenu =
9000             SUMA_Alloc_Menu_Widget(SW_N_SurfCont_Trans);
9001       SUMA_BuildMenu (rc, XmMENU_OPTION,
9002                                  "Trn", '\0', YUP, TransMode_Menu,
9003                                  (void *)SUMA_SurfCont_GetcurDOp(SurfCont),
9004                                  "GraphCont->NOT_USED_YET->Trn",
9005                         "Choose the transparency for this graph.",
9006                                  SUMA_SurfContHelp_TransMode,
9007                                  SurfCont->TransModeMenu );
9008       XtManageChild (SurfCont->TransModeMenu->mw[SW_SurfCont_Trans]);
9009 
9010       pb = XtVaCreateWidget ("Dsets",
9011          xmPushButtonWidgetClass, rc,
9012          NULL);
9013       XtAddCallback (pb, XmNactivateCallback,
9014                      SUMA_cb_ToggleManagementColPlaneWidget,
9015                      (XtPointer)SUMA_SurfCont_GetcurDOp(SurfCont));
9016       SUMA_Register_Widget_Help( pb, 1,
9017                                  "GraphCont->NOT_USED_YET->Dsets",
9018                                  "Show/Hide Dataset (previously Color Plane) "
9019                                  "controllers",
9020                                  SUMA_SurfContHelp_Dsets ) ;
9021       XtManageChild (pb);
9022 
9023       XtManageChild (rc);
9024       #endif
9025 
9026       XtManageChild (rc_SurfProp);
9027       XtManageChild (SurfCont->SurfFrame);
9028    }
9029 
9030    SUMA_LH("Xhair business");
9031    {  /* Xhair Controls */
9032       Widget rcv, www;
9033       /* put a frame */
9034       SurfCont->Xhair_fr = XtVaCreateWidget ("dialog",
9035          xmFrameWidgetClass, rc_left,
9036          XmNshadowType , XmSHADOW_ETCHED_IN ,
9037          XmNshadowThickness , 5 ,
9038          XmNtraversalOn , False ,
9039          NULL);
9040 
9041       www = XtVaCreateManagedWidget ("Xhair Info",
9042             xmLabelWidgetClass, SurfCont->Xhair_fr,
9043             XmNchildType, XmFRAME_TITLE_CHILD,
9044             XmNchildHorizontalAlignment, XmALIGNMENT_BEGINNING,
9045             NULL);
9046       SUMA_Register_Widget_Help( www , 0,
9047                                  "GraphCont->Xhair_Info",
9048                       "Crosshair Information",
9049                   ":SPX:\n\n"
9050                   ".. figure:: media/GraphCont.auto.Xhair_Info.jpg\n"
9051                   "   :align: right\n"
9052                   "   :name: media/GraphCont.auto.Xhair_Info.jpg\n"
9053                   "\n"
9054                   "   :ref:`(link)<media/GraphCont.auto.Xhair_Info.jpg>`\n"
9055                   "   ..\n\n"
9056                   ":SPX:") ;
9057       /* vertical row column */
9058       rcv = XtVaCreateWidget ("rowcolumn",
9059             xmRowColumnWidgetClass, SurfCont->Xhair_fr,
9060             XmNpacking, XmPACK_TIGHT,
9061             XmNorientation , XmVERTICAL ,
9062             XmNmarginHeight, 0 ,
9063             XmNmarginWidth , 0 ,
9064             NULL);
9065 
9066       /* create the widgets for the colormap stuff */
9067       SUMA_CreateXhairWidgets(rcv, ado);
9068 
9069       XtManageChild(rcv);
9070       XtManageChild(SurfCont->Xhair_fr);
9071    }  /* Xhair Controls */
9072 
9073    SUMA_LHv("\nGDset Mapping, graph %s\n", SUMA_ADO_Label(ado));
9074    {  /* Dset Mapping */
9075       Widget rcv, www;
9076       /* put a frame */
9077       SurfCont->DsetMap_fr = XtVaCreateWidget ("dialog",
9078          xmFrameWidgetClass, rc_right,
9079          XmNrightAttachment , XmATTACH_FORM ,
9080          XmNleftAttachment, XmATTACH_WIDGET,
9081          XmNleftWidget, SurfCont->SurfFrame,
9082          XmNtopAttachment  , XmATTACH_FORM ,
9083          XmNshadowType , XmSHADOW_ETCHED_IN ,
9084          XmNshadowThickness , 5 ,
9085          XmNtraversalOn , False ,
9086          NULL);
9087 
9088       www = XtVaCreateManagedWidget ("GDset Mapping",
9089             xmLabelWidgetClass, SurfCont->DsetMap_fr,
9090             XmNchildType, XmFRAME_TITLE_CHILD,
9091             XmNchildHorizontalAlignment, XmALIGNMENT_BEGINNING,
9092             NULL);
9093       SUMA_Register_Widget_Help( www , 0,
9094                               "GraphCont->GDset_Mapping",
9095                               "Control mapping of edge/cell values to color map",
9096                   ":SPX:\n\n"
9097                   ".. figure:: media/GraphCont.auto.GDset_Mapping.jpg\n"
9098                   "   :align: right\n"
9099                   "   :name: media/GraphCont.auto.GDset_Mapping.jpg\n"
9100                   "\n"
9101                   "   :ref:`(link)<media/GraphCont.auto.GDset_Mapping.jpg>`\n"
9102                   "   ..\n\n"
9103                   ":SPX:") ;
9104 
9105       /* vertical row column */
9106       rcv = XtVaCreateWidget ("rowcolumn",
9107             xmRowColumnWidgetClass, SurfCont->DsetMap_fr,
9108             XmNpacking, XmPACK_TIGHT,
9109             XmNorientation , XmVERTICAL ,
9110             XmNmarginHeight, 0 ,
9111             XmNmarginWidth , 0 ,
9112             NULL);
9113 
9114       /* create the widgets for the colormap stuff */
9115       SUMA_CreateCmapWidgets(rcv, ado);
9116 
9117       XtManageChild(rcv);
9118 
9119       XtManageChild(SurfCont->DsetMap_fr);
9120    }
9121 
9122    SUMA_LH("GDset Controls");
9123    /* Dset Controls */
9124    {
9125        Widget rc, rcv, pb, www;
9126 
9127       /* put a frame */
9128       SurfCont->ColPlane_fr = XtVaCreateWidget ("dialog",
9129          xmFrameWidgetClass, rc_left,
9130          XmNshadowType , XmSHADOW_ETCHED_IN ,
9131          XmNshadowThickness , 5 ,
9132          XmNtraversalOn , False ,
9133          NULL);
9134 
9135       www = XtVaCreateManagedWidget ("GDset Controls",
9136             xmLabelWidgetClass, SurfCont->ColPlane_fr,
9137             XmNchildType, XmFRAME_TITLE_CHILD,
9138             XmNchildHorizontalAlignment, XmALIGNMENT_BEGINNING,
9139             NULL);
9140 
9141       SUMA_Register_Widget_Help( www , 0,
9142                         "GraphCont->GDset_Controls",
9143                         "Control appearance of 3D graphs and matrices",
9144                   ":SPX:\n\n"
9145                   ".. figure:: media/GraphCont.auto.GDset_Controls.jpg\n"
9146                   "   :align: right\n"
9147                   "   :name: media/GraphCont.auto.GDset_Controls.jpg\n"
9148                   "\n"
9149                   "   :ref:`(link)<media/GraphCont.auto.GDset_Controls.jpg>`\n"
9150                   "   ..\n\n"
9151                   ":SPX:") ;
9152 
9153       /* vertical row column */
9154       rcv = XtVaCreateWidget ("rowcolumn",
9155             xmRowColumnWidgetClass, SurfCont->ColPlane_fr,
9156             XmNpacking, XmPACK_TIGHT,
9157             XmNorientation , XmVERTICAL ,
9158             XmNmarginHeight, 0 ,
9159             XmNmarginWidth , 0 ,
9160             NULL);
9161 
9162       /* row column for label*/
9163       rc = XtVaCreateWidget ("rowcolumn",
9164             xmRowColumnWidgetClass, rcv,
9165             XmNpacking, XmPACK_TIGHT,
9166             XmNorientation , XmHORIZONTAL ,
9167             XmNmarginHeight, 0 ,
9168             XmNmarginWidth , 0 ,
9169             NULL);
9170 
9171       /*put a label containing the surface name,
9172          number of nodes and number of facesets */
9173       {
9174          char *Dset_tit[]  =  {  "Lbl", NULL };
9175          char *Dset_hint[] =  {  "Label of Graph Dset",  NULL };
9176          char *Dset_help[] =  {  SUMA_SurfContHelp_DsetLblTblr0, NULL };
9177          int colw[]={ 3, 27};
9178          SUMA_CreateTable(rc,
9179             1, 2,
9180             "GraphCont->GDset_Controls->Lbl",
9181             Dset_tit, NULL,
9182             Dset_hint, NULL,
9183             Dset_help, NULL,
9184             colw, NOPE, SUMA_string,
9185             NULL, NULL,
9186             NULL, NULL,
9187             NULL, NULL,
9188             SurfCont->ColPlaneLabelTable);
9189       }
9190       XtManageChild (rc);
9191 
9192       /* add a rc for the colorplane brightness and perhaps visibility? */
9193       rc = XtVaCreateWidget ("rowcolumn",
9194          xmRowColumnWidgetClass, rcv,
9195          XmNpacking, XmPACK_TIGHT,
9196          XmNorientation , XmHORIZONTAL ,
9197          NULL);
9198 
9199       SUMA_CreateArrowField ( rc, "Dim",
9200                            1, 0.1, 2, 0.1,
9201                            3, SUMA_float,
9202                            YUP,
9203                            SUMA_cb_ColPlane_NewDimFact, (void *)ado,
9204                            "GraphCont->GDset_Controls->Dim",
9205                            SUMA_SurfCont_ColPlaneDim_hint,
9206                            SUMA_SurfContHelp_DsetDim,
9207                            SurfCont->ColPlaneDimFact);
9208 
9209 
9210 
9211       SurfCont->GDSET_ShowBundles_tb =
9212          XtVaCreateManagedWidget("Bundles",
9213                                  xmToggleButtonWidgetClass, rc, NULL);
9214       XmToggleButtonSetState (SurfCont->GDSET_ShowBundles_tb,
9215                               GSaux->ShowBundles, NOPE);
9216       XtAddCallback (SurfCont->GDSET_ShowBundles_tb,
9217                      XmNvalueChangedCallback,
9218                      SUMA_cb_GDSET_ShowBundles_toggled, ado);
9219 
9220       SUMA_Register_Widget_Help(SurfCont->GDSET_ShowBundles_tb , 1,
9221                         "GraphCont->GDset_Controls->Bundles",
9222                         "Show bundles instead of edges if possible.",
9223                         SUMA_SurfContHelp_GDSET_ViewBundles ) ;
9224       SUMA_SET_SELECT_COLOR(SurfCont->GDSET_ShowBundles_tb);
9225 
9226       SUMA_BuildMenuReset(0);
9227       SurfCont->DsetThroughMenu =
9228          SUMA_Alloc_Menu_Widget(SW_N_SurfCont_DsetThrough);
9229       SUMA_BuildMenu (rc, XmMENU_OPTION,
9230                 "CN", '\0', YUP, DsetThrough_Menu,
9231                 (void *)SUMA_SurfCont_GetcurDOp(SurfCont),
9232                 "GraphCont->GDset_Controls->CN",
9233                 "How to display connection to selected graph node.",
9234                 SUMA_SurfContHelp_DsetThrough,
9235                 SurfCont->DsetThroughMenu );
9236       XtManageChild (SurfCont->DsetThroughMenu->mw[SW_SurfCont_DsetThrough]);
9237       SUMA_Set_Menu_Widget(SurfCont->DsetThroughMenu,
9238                            SUMA_Through2ThroughMenuItem(curColPlane->Through));
9239 
9240       /* manage  rc */
9241       XtManageChild (rc);
9242 
9243       /* add a rc for the node radius, gain, and colors */
9244       rc = XtVaCreateWidget ("rowcolumn",
9245          xmRowColumnWidgetClass, rcv,
9246          XmNpacking, XmPACK_TIGHT,
9247          XmNorientation , XmHORIZONTAL ,
9248          NULL);
9249 
9250       SUMA_BuildMenuReset(0);
9251       SurfCont->DsetNodeRadMenu =
9252          SUMA_Alloc_Menu_Widget(SW_N_SurfCont_DsetNodeRad);
9253       SUMA_BuildMenu (rc, XmMENU_OPTION,
9254                 "Rd", '\0', YUP, DsetNodeRad_Menu,
9255                 (void *)SUMA_SurfCont_GetcurDOp(SurfCont),
9256                 "GraphCont->GDset_Controls->Rd",
9257                 "Choose the sizing option for graph nodes.",
9258                 SUMA_SurfContHelp_DsetNodeRad,
9259                 SurfCont->DsetNodeRadMenu );
9260       XtManageChild (SurfCont->DsetNodeRadMenu->mw[SW_SurfCont_DsetNodeRad]);
9261 
9262       SUMA_CreateArrowField ( rc, "Gn",
9263                            1.0, 0.0, 200.0, 1.0,
9264                            3, SUMA_float,
9265                            YUP,
9266                            SUMA_cb_ColPlane_NewNodeRadGain, (void *)ado,
9267                            "GraphCont->GDset_Controls->Rd->Gn",
9268                            SUMA_SurfCont_NodeRadGain_hint,
9269                            SUMA_SurfContHelp_DsetNodeRadGain,
9270                            SurfCont->NodeRadGainAF);
9271 
9272       SUMA_BuildMenuReset(0);
9273       SurfCont->DsetGmatBordMenu =
9274          SUMA_Alloc_Menu_Widget(SW_N_SurfCont_DsetGmatBord);
9275       SUMA_BuildMenu (rc, XmMENU_OPTION,
9276                 "Br", '\0', YUP, DsetGmatBord_Menu,
9277                 (void *)SUMA_SurfCont_GetcurDOp(SurfCont),
9278                 "GraphCont->GDset_Controls->Br",
9279                 "Choose the partition ratio of matrix.",
9280                 SUMA_SurfContHelp_DsetGmatBord,
9281                 SurfCont->DsetGmatBordMenu );
9282       XtManageChild (SurfCont->DsetGmatBordMenu->mw[SW_SurfCont_DsetGmatBord]);
9283 
9284       XtManageChild (rc);
9285 
9286       /* add a rc for the node font and colorization */
9287       rc = XtVaCreateWidget ("rowcolumn",
9288          xmRowColumnWidgetClass, rcv,
9289          XmNpacking, XmPACK_TIGHT,
9290          XmNorientation , XmHORIZONTAL ,
9291          NULL);
9292 
9293       SUMA_BuildMenuReset(0);
9294       SurfCont->DsetFontMenu =
9295          SUMA_Alloc_Menu_Widget(SW_N_SurfCont_DsetFont);
9296       SUMA_BuildMenu (rc, XmMENU_OPTION,
9297                 "Fo", '\0', YUP, DsetFont_Menu,
9298                 (void *)SUMA_SurfCont_GetcurDOp(SurfCont),
9299                 "GraphCont->GDset_Controls->Fo",
9300                 "Choose the font for graph node labels.",
9301                 SUMA_SurfContHelp_DsetFont,
9302                 SurfCont->DsetFontMenu );
9303       XtManageChild (SurfCont->DsetFontMenu->mw[SW_SurfCont_DsetFont]);
9304       SUMA_Set_Menu_Widget(SurfCont->DsetFontMenu,
9305                            SUMA_Font2FontMenuItem(curColPlane->Font));
9306 
9307       SUMA_BuildMenuReset(0);
9308       SurfCont->DsetNodeColMenu =
9309          SUMA_Alloc_Menu_Widget(SW_N_SurfCont_DsetNodeCol);
9310       SUMA_BuildMenu (rc, XmMENU_OPTION,
9311                 "Cl", '\0', YUP, DsetNodeCol_Menu,
9312                 (void *)SUMA_SurfCont_GetcurDOp(SurfCont),
9313                 "GraphCont->GDset_Controls->Cl",
9314                 "Choose the coloring option for graph nodes.",
9315                 SUMA_SurfContHelp_DsetNodeCol,
9316                 SurfCont->DsetNodeColMenu );
9317       XtManageChild (SurfCont->DsetNodeColMenu->mw[SW_SurfCont_DsetNodeCol]);
9318       SUMA_Set_Menu_Widget( SurfCont->DsetNodeColMenu, curColPlane->NodeCol);
9319 
9320       SUMA_BuildMenuReset(0);
9321       SurfCont->DsetTxtShadMenu =
9322          SUMA_Alloc_Menu_Widget(SW_N_SurfCont_DsetTxtShad);
9323       SUMA_BuildMenu (rc, XmMENU_OPTION,
9324                 "Sh", '\0', YUP, DsetTxtShad_Menu,
9325                 (void *)SUMA_SurfCont_GetcurDOp(SurfCont),
9326                 "GraphCont->GDset_Controls->Sh",
9327                 "Choose the shading options for node labels.",
9328                 SUMA_SurfContHelp_DsetTxtShad,
9329                 SurfCont->DsetTxtShadMenu );
9330       XtManageChild (SurfCont->DsetTxtShadMenu->mw[SW_SurfCont_DsetTxtShad]);
9331 
9332       SurfCont->GDSET_ShowUncon_tb =
9333          XtVaCreateManagedWidget("U",
9334                                  xmToggleButtonWidgetClass, rc, NULL);
9335       XmToggleButtonSetState (SurfCont->GDSET_ShowUncon_tb,
9336                               GSaux->ShowUncon, NOPE);
9337       XtAddCallback (SurfCont->GDSET_ShowUncon_tb,
9338                      XmNvalueChangedCallback,
9339                      SUMA_cb_GDSET_ShowUncon_toggled, ado);
9340       SUMA_Register_Widget_Help(SurfCont->GDSET_ShowUncon_tb , 1,
9341                         "GraphCont->GDset_Controls->U",
9342                         "Show Unconnected graph nodes.",
9343                         SUMA_SurfContHelp_GDSET_ViewUncon) ;
9344       SUMA_SET_SELECT_COLOR(SurfCont->GDSET_ShowUncon_tb);
9345 
9346 
9347 
9348       /* manage  rc */
9349       XtManageChild (rc);
9350 
9351       /* add a rc for the edge size, stippling and colorization */
9352       rc = XtVaCreateWidget ("rowcolumn",
9353          xmRowColumnWidgetClass, rcv,
9354          XmNpacking, XmPACK_TIGHT,
9355          XmNorientation , XmHORIZONTAL ,
9356          NULL);
9357 
9358       SUMA_BuildMenuReset(0);
9359       SurfCont->DsetEdgeThickMenu =
9360          SUMA_Alloc_Menu_Widget(SW_N_SurfCont_DsetEdgeThick);
9361       SUMA_BuildMenu (rc, XmMENU_OPTION,
9362                 "Th", '\0', YUP, DsetEdgeThick_Menu,
9363                 (void *)SUMA_SurfCont_GetcurDOp(SurfCont),
9364                 "GraphCont->GDset_Controls->Th",
9365                 "Choose the thickness option for graph edges.",
9366                 SUMA_SurfContHelp_DsetEdgeThick,
9367                 SurfCont->DsetEdgeThickMenu );
9368       XtManageChild (SurfCont->DsetEdgeThickMenu->mw[SW_SurfCont_DsetEdgeThick]);
9369 
9370       SUMA_CreateArrowField ( rc, "Gn",
9371                            1.0, 0.0, 200.0, 1.0,
9372                            3, SUMA_float,
9373                            YUP,
9374                            SUMA_cb_ColPlane_NewEdgeThickGain, (void *)ado,
9375                            "GraphCont->GDset_Controls->Th->Gn",
9376                            SUMA_SurfCont_EdgeThickGain_hint,
9377                            SUMA_SurfContHelp_DsetEdgeThickGain,
9378                            SurfCont->EdgeThickGainAF);
9379 
9380 
9381       SUMA_BuildMenuReset(0);
9382       SurfCont->DsetEdgeStipMenu =
9383          SUMA_Alloc_Menu_Widget(SW_N_SurfCont_DsetEdgeStip);
9384       SUMA_BuildMenu (rc, XmMENU_OPTION,
9385                 "St", '\0', YUP, DsetEdgeStip_Menu,
9386                 (void *)SUMA_SurfCont_GetcurDOp(SurfCont),
9387                 "GraphCont->GDset_Controls->St",
9388                 "Choose the stippling option for graph edges.",
9389                 SUMA_SurfContHelp_DsetEdgeStip,
9390                 SurfCont->DsetEdgeStipMenu );
9391       XtManageChild (SurfCont->DsetEdgeStipMenu->mw[SW_SurfCont_DsetEdgeStip]);
9392 
9393       XtManageChild (rc);
9394 
9395 
9396       #if 0
9397          /* Not sure this is all that useful here.
9398             Makes no sense to load a new dataset onto an existing one.
9399             Switching certainly makes no sense... */
9400       XtVaCreateManagedWidget (  "sep",
9401                                  xmSeparatorWidgetClass, rcv,
9402                                  XmNorientation, XmHORIZONTAL,NULL);
9403 
9404       /* row column for Switch, Load, Delete */
9405       rc = XtVaCreateWidget ("rowcolumn",
9406          xmRowColumnWidgetClass, rcv,
9407          XmNpacking, XmPACK_TIGHT,
9408          XmNorientation , XmHORIZONTAL ,
9409          NULL);
9410 
9411       /* put a push button to switch between color planes */
9412       SurfCont->SwitchDsetlst =
9413             SUMA_AllocateScrolledList ("Switch Dset",
9414                      SUMA_LSP_SINGLE,
9415                      NOPE, NOPE, /* duplicate deletion, no sorting */
9416                      SurfCont->TLS, SWP_POINTER,
9417                      125,
9418                      SUMA_cb_SelectSwitchColPlane, (void *)ado,
9419                      SUMA_cb_SelectSwitchColPlane, (void *)ado,
9420                      SUMA_cb_CloseSwitchColPlane, NULL);
9421 
9422 
9423       pb = XtVaCreateWidget ("Switch Dset",
9424          xmPushButtonWidgetClass, rc,
9425          NULL);
9426       XtAddCallback (pb, XmNactivateCallback,
9427                      SUMA_cb_SurfCont_SwitchColPlane, (XtPointer)ado);
9428       SUMA_Register_Widget_Help(pb, 1, "GraphCont->GDset_Controls->Switch_Dset",
9429                                 "Switch between datasets",
9430                                 SUMA_SurfContHelp_DsetSwitch ) ;
9431       XtManageChild (pb);
9432 
9433       pb = XtVaCreateWidget ("Load Dset",
9434             xmPushButtonWidgetClass, rc,
9435             NULL);
9436          XtAddCallback (pb, XmNactivateCallback,
9437                         SUMA_cb_Dset_Load, (XtPointer) ado);
9438          SUMA_Register_Widget_Help(pb, 1, "GraphCont->GDset_Controls->Load_Dset",
9439                                    "Load a new dataset (much more with BHelp)",
9440                                    SUMA_SurfContHelp_DsetLoad ) ;
9441          XtManageChild (pb);
9442 
9443       pb = XtVaCreateWidget ("Delete",
9444          xmPushButtonWidgetClass, rc,
9445          NULL);
9446       XtAddCallback (pb, XmNactivateCallback,
9447                      SUMA_cb_ColPlane_Delete, (XtPointer) ado);
9448       /* XtManageChild (pb); */ /* Not ready for this one yet */
9449 
9450 
9451 
9452       XtManageChild (rc);
9453       #endif
9454 
9455       /* manage vertical row column */
9456       XtManageChild (rcv);
9457 
9458       XtManageChild (SurfCont->ColPlane_fr);
9459    }
9460 
9461 
9462 
9463    if (SUMAg_CF->X->UseSameSurfCont) {
9464       Widget rc=NULL;
9465       /* put something to cycle through objects */
9466       if ((rc = SUMA_FindChildWidgetNamed(SurfCont->DispFrame,"rowcolumnCBF"))) {
9467          XtVaCreateManagedWidget (  "sep",
9468                               xmSeparatorWidgetClass, rc,
9469                               XmNorientation, XmVERTICAL,NULL);
9470          pb = XtVaCreateWidget ("All Objs.",
9471                   xmPushButtonWidgetClass, rc,
9472                   NULL);
9473          XtAddCallback (pb, XmNactivateCallback,
9474                         SUMA_cb_AllConts, NULL);
9475          SUMA_Register_Widget_Help(pb, 1, "GraphCont->Disp_Cont->AllObjs",
9476                                 "Initialize Controllers for All Objects",
9477                                 SUMA_SurfContHelp_AllObjs) ;
9478          XtManageChild (pb);
9479 
9480          SUMA_CreateArrowField ( rc, "Switch",
9481                            1, 1, 20, 1,
9482                            2, SUMA_int,
9483                            YUP,
9484                            SUMA_cb_SurfCont_SwitchPage, (void *)ado,
9485                            "GraphCont->Disp_Cont->Switch",
9486                            "Switch to other object controller",
9487                            SUMA_Switch_Cont_BHelp,
9488                            SurfCont->SurfContPage);
9489          xmstmp = XmStringCreateLtoR (SUMA_ADO_CropLabel(ado,
9490                                        SUMA_SURF_CONT_SWITCH_LABEL_LENGTH),
9491                                       XmSTRING_DEFAULT_CHARSET);
9492          SurfCont->SurfContPage_label = XtVaCreateManagedWidget ("dingel-4",
9493                xmLabelWidgetClass, rc,
9494                XmNlabelString, xmstmp,
9495                NULL);
9496          XmStringFree (xmstmp);
9497       }
9498    }
9499 
9500    SUMA_LHv("Management ...%p %p %p %p %p\n",
9501             rc_right, rc_left, rc_mamma, SurfCont->Mainform, SurfCont->Page);
9502 
9503    XtManageChild (rc_right);
9504    XtManageChild (rc_left);
9505    XtManageChild (rc_mamma);
9506    XtManageChild (rc_gmamma);
9507    XtManageChild (SurfCont->Mainform);
9508    if (SUMAg_CF->X->UseSameSurfCont) XtManageChild (SurfCont->Page);
9509 
9510    #if SUMA_CONTROLLER_AS_DIALOG
9511    #else
9512    /** Feb 03/03: pop it up if it is a topLevelShellWidgetClass,
9513    you should do the popping after all the widgets have been created.
9514    Otherwise, the window does not size itself correctly when open */
9515    XtPopup(SurfCont->TLS, XtGrabNone);
9516    #endif
9517 
9518    /* realize the widget */
9519    if (SUMAg_CF->X->UseSameSurfCont) XtManageChild (SUMAg_CF->X->SC_Notebook);
9520    XtRealizeWidget (SurfCont->TLS);
9521 
9522    SUMA_LH("%s",slabel);
9523    SUMA_free (slabel);
9524 
9525    /* Mark as open */
9526    SUMA_MarkSurfContOpen(1,ado);
9527 
9528    SUMA_LHv("Marked %s's controller as open.\n", SUMA_ADO_Label(ado));
9529 
9530    /* initialize the left side
9531       (no need here, that's done in SUMA_cb_viewSurfaceCont)*/
9532    /* SUMA_Init_SurfCont_SurfParam(ado); */
9533 
9534    /* initialize the ColorPlane frame if possible
9535    Do it here rather than above because scale goes crazy
9536    when parent widgets are being resized*/
9537 
9538    if (ado->do_type == SO_type && !(over0 = SUMA_ADO_Overlay0(ado))) {
9539       SUMA_SurfaceObject *SOp=NULL, *SO=(SUMA_SurfaceObject *)ado;
9540       SUMA_LH("NO Overlays yet for this surface\n");
9541       /* happens in very few instances when both child and parent
9542       are in the first view and the child is selected before the surface
9543       controller for that family is ever opened! */
9544       SOp = SUMA_findSOp_inDOv(SO->LocalDomainParentID, SUMAg_DOv, SUMAg_N_DOv);
9545       if (!SOp) {
9546          SUMA_SL_Err("Failed to find parent, should not be.");
9547       }
9548 
9549       if (!SUMA_GetOverlaysFromParent(SO, SOp)) {
9550          SUMA_SL_Err("Failed to copy overlays!");
9551          SUMA_RETURNe;
9552       }
9553    }
9554 
9555    if (SUMA_ADO_N_Overlays(ado)>0) {
9556       SUMA_LH("Initializing ColPlaneShell");
9557       SUMA_InitializeColPlaneShell(ado, curColPlane);
9558       #ifdef NONONO /* It looks like I do not need this anymore
9559                        Used to be #idef DARWIN */
9560       /* Sometimes color maps do not show up on mac when you first
9561          open the surface controller */
9562       SUMA_LH("Darwining");
9563       SUMA_SwitchColPlaneCmap(ado, SUMA_CmapOfPlane(curColPlane));
9564       #endif
9565    }
9566 
9567    #if USING_LESSTIF
9568    SUMA_LH("Less tif fix");
9569    /* A quick fix to ensure Dset_Mapping
9570       gets displayed properly the first time */
9571    SUMA_cb_ToggleManagementColPlaneWidget(NULL, (XtPointer)(&ado), NULL);
9572    SUMA_cb_ToggleManagementColPlaneWidget(NULL, (XtPointer)(&ado), NULL);
9573    #endif
9574 
9575    SUMA_LH("going home.");
9576 
9577    SUMA_MarkSurfContOpen(1, ado);
9578 
9579    SUMA_RETURNe;
9580 }
9581 
SUMA_cb_createSurfaceCont_TDO(Widget w,XtPointer data,XtPointer callData)9582 void SUMA_cb_createSurfaceCont_TDO(Widget w, XtPointer data,
9583                                      XtPointer callData)
9584 {
9585    static char FuncName[] = {"SUMA_cb_createSurfaceCont_TDO"};
9586    Widget tl, pb, form,
9587           rc_left, rc_right, rc_mamma, rc_gmamma, tls=NULL;
9588    Display *dpy;
9589    SUMA_ALL_DO *ado;
9590    SUMA_TractDO *tdo;
9591    char *slabel, *lbl30, *sss=NULL;
9592    XmString xmstmp;
9593    SUMA_X_SurfCont *SurfCont=NULL;
9594    SUMA_TRACT_SAUX *TSaux=NULL;
9595    SUMA_OVERLAYS *curColPlane=NULL, *over0=NULL;
9596    SUMA_Boolean LocalHead = NOPE;
9597 
9598    SUMA_ENTRY;
9599 
9600    ado = (SUMA_ALL_DO *)data;
9601    if (ado->do_type != TRACT_type) {
9602       SUMA_S_Errv("Calling me with (%s) other than TRACT_type type,\n"
9603                   "I don't like that, call me with TDO",
9604                   SUMA_ObjectTypeCode2ObjectTypeName(ado->do_type));
9605       SUMA_RETURNe;
9606    }
9607    tdo = (SUMA_TractDO *)ado;
9608 
9609    if (LocalHead) {
9610       SUMA_LHv("Creating SurfaceCont for type %s, label %s\n",
9611             ADO_TNAME(ado), SUMA_ADO_Label(ado));
9612       SUMA_DUMP_TRACE("Creating SurfaceCont");
9613    }
9614    if (!(SurfCont = SUMA_ADO_Cont(ado))) {
9615       SUMA_S_Errv("Failed to get Controller for ado %s\n",
9616                   SUMA_ADO_Label(ado));
9617       SUMA_RETURNe;
9618    }
9619    if (!SUMA_SurfCont_SetcurDOp(SurfCont, ado)) {
9620       SUMA_S_Errv("Failed to Set curDOp for %s\n",
9621                   SUMA_ADO_Label(ado));
9622       SUMA_RETURNe;
9623    }
9624    if (!(curColPlane = SUMA_ADO_CurColPlane(ado))) {
9625       SUMA_S_Errv("Failed to get current col plane for ado %s\n",
9626                   SUMA_ADO_Label(ado));
9627       SUMA_RETURNe;
9628    }
9629    SUMA_LH("CurColPlane %p for ado %s\n", curColPlane, SUMA_ADO_Label(ado));
9630    if (SurfCont->TLS) {
9631       fprintf (SUMA_STDERR,
9632                "Error %s: SurfCont->TopLevelShell!=NULL.\n"
9633                "Should not be here.\n", FuncName);
9634       SUMA_RETURNe;
9635    }
9636    if (!(TSaux = SUMA_ADO_TSaux(ado))) {
9637       SUMA_S_Err("Failed to get TSaux");
9638       SUMA_RETURNe;
9639    }
9640    tl = SUMA_GetTopShell(w); /* top level widget */
9641    dpy = XtDisplay(tl);
9642 
9643    slabel = (char *)SUMA_malloc(sizeof(char) *
9644                                  (strlen(SUMA_ADO_Label(ado)) + 100));
9645    if (strlen(SUMA_ADO_Label(ado)) > 40) {
9646       char *tmpstr=NULL;
9647       tmpstr = SUMA_truncate_string(SUMA_ADO_Label(ado), 40);
9648       if (tmpstr) {
9649          sprintf(slabel,"[%s] Tract Controller", tmpstr);
9650          free(tmpstr); tmpstr=NULL;
9651       }
9652    } else {
9653       sprintf(slabel,"[%s] Tract Controller", SUMA_ADO_Label(ado));
9654    }
9655 
9656    /* March 12 08: Made font8 default for surface controller */
9657    if (SUMA_isEnv("SUMA_SurfContFontSize", "BIG")) {
9658       sss = "font9";
9659    } else {
9660       sss = "font8";
9661    }
9662 
9663    SUMA_LH("Creating dialog shell.");
9664    if (!SUMAg_CF->X->UseSameSurfCont ||
9665        !SUMAg_CF->X->CommonSurfContTLW) { /* need a new one */
9666       #if SUMA_CONTROLLER_AS_DIALOG /* xmDialogShellWidgetClass,
9667                                        topLevelShellWidgetClass*/
9668       tls = XtVaCreatePopupShell (sss,
9669          XmNtitle, slabel,
9670          xmDialogShellWidgetClass, tl,
9671          XmNallowShellResize, True, /* let code resize shell */
9672          XmNdeleteResponse, XmDO_NOTHING,
9673          NULL);
9674       #else
9675       SUMA_LH("Creating toplevel shell.");
9676       /** Feb 03/03:    I was using XtVaCreatePopupShell to create a
9677                         topLevelShellWidgetClass.
9678                         XtVaCreatePopupShell is used to create dialog
9679                         shells not toplevel or appshells.
9680                         Of course, it made no difference! */
9681       tls = XtVaAppCreateShell (sss, "Suma",
9682          topLevelShellWidgetClass, SUMAg_CF->X->DPY_controller1 ,
9683          XmNtitle, slabel,
9684          XmNdeleteResponse, XmDO_NOTHING,
9685          NULL);
9686       #endif
9687 
9688       /* allow for code to resize the shell */
9689       XtVaSetValues (tls,
9690             XmNresizePolicy , XmRESIZE_NONE ,
9691             XmNallowShellResize , True ,       /* let code resize shell */
9692             NULL);
9693 
9694       /* handle the close button from window manager */
9695       XmAddWMProtocolCallback(/* make "Close" window menu work */
9696          tls,
9697          XmInternAtom( dpy , "WM_DELETE_WINDOW" , False ) ,
9698          SUMA_cb_closeSurfaceCont, (XtPointer) ado) ;
9699 
9700       if (SUMAg_CF->X->UseSameSurfCont) {
9701          Widget scroller;
9702          SUMAg_CF->X->CommonSurfContTLW = tls;
9703          SUMAg_CF->X->SC_Notebook =
9704             XtVaCreateWidget("ControllerBook", xmNotebookWidgetClass,
9705                              SUMAg_CF->X->CommonSurfContTLW,
9706                              XmNbindingWidth, XmNONE,
9707                              XmNbackPageNumber, 0,
9708                              XmNmajorTabSpacing, 0,
9709                              XmNminorTabSpacing, 0,
9710                              NULL);
9711             /*XmCreateNotebook (SUMAg_CF->X->CommonSurfContTLW, "ControllerBook",
9712                               NULL, 0);
9713               XtVaSetValues(SUMAg_CF->X->SC_Notebook,
9714                           XmNbindingWidth, XmNONE,
9715                           NULL); */
9716 
9717 
9718          /* Kill the scroller from hell otherwise no keyboard input
9719             gets to the baby widgets. Better write my own scroller
9720             if need be in the future */
9721          scroller = XtNameToWidget (SUMAg_CF->X->SC_Notebook, "PageScroller");
9722          XtUnmanageChild (scroller);
9723       }
9724 
9725    }
9726 
9727    if (SUMAg_CF->X->UseSameSurfCont) {
9728       SurfCont->TLS = SUMAg_CF->X->CommonSurfContTLW;
9729    } else {
9730       SurfCont->TLS = tls;
9731    }
9732 
9733    if (!SurfCont->TLS) {
9734       SUMA_S_Err("Bad logic");
9735       SUMA_RETURNe;
9736    }
9737 
9738    SUMA_LH("Widgets...");
9739    if (SUMAg_CF->X->UseSameSurfCont) {
9740       Arg args[20];
9741       /* add the page */
9742       XtSetArg (args[0], XmNnotebookChildType, XmPAGE);
9743       SurfCont->Page =
9744          XmCreateRowColumn (SUMAg_CF->X->SC_Notebook,
9745                      SUMA_ADO_Label(ado)?SUMA_ADO_Label(ado):"page",
9746                                               args, 1);
9747    }
9748 
9749    /* create a form widget, manage it at the end ...*/
9750    SurfCont->Mainform = XtVaCreateWidget ("dialog",
9751       xmFormWidgetClass, SurfCont->Page ?
9752                               SurfCont->Page:SurfCont->TLS,
9753       XmNborderWidth , 0 ,
9754       XmNmarginHeight , SUMA_MARGIN ,
9755       XmNmarginWidth  , SUMA_MARGIN ,
9756       XmNshadowThickness, 2,
9757       XmNshadowType, XmSHADOW_ETCHED_IN,
9758       NULL);
9759 
9760    rc_gmamma = XtVaCreateWidget ("rowcolumn",
9761             xmRowColumnWidgetClass, SurfCont->Mainform,
9762             XmNpacking, XmPACK_TIGHT,
9763             XmNorientation , XmVERTICAL ,
9764             XmNmarginHeight, SUMA_MARGIN ,
9765             XmNmarginWidth , SUMA_MARGIN ,
9766             XmNtopAttachment  , XmATTACH_FORM ,
9767             XmNbottomAttachment  , XmATTACH_FORM ,
9768             NULL);
9769 
9770 
9771    SurfCont->DispFrame = SUMA_CloseBhelp_Frame(rc_gmamma,
9772                      SUMA_cb_closeSurfaceCont, (XtPointer) ado,
9773                      "TractCont",
9774                      "Close Surface controller", SUMA_closeSurfaceCont_help,
9775                      NULL, NULL, NULL, NULL);
9776    SUMA_Register_Widget_Help( SurfCont->DispFrame , 0,
9777                               "TractCont",
9778                               "Network/Tracts Cont.",
9779 "The tract controller is for controlling the way tracts and values "
9780 "defined over them are displayed. "
9781 "Each network of tracts gets its own controller. "
9782 ":SPX:"
9783 "You can launch the :ref:`Tract Controller <TractCont>` with:"
9784 " :ref:`ctrl+s <LC_Ctrl+s>` or :menuselection:`View-->Object Controller`\n"
9785 "\n"
9786 ".. figure:: media/TractCont.auto.ALL.jpg\n"
9787 "   :align: center\n"
9788 "   :name: media/TractCont.auto.ALL.jpg\n"
9789 "\n"
9790 "   :ref:`(link)<media/TractCont.auto.ALL.jpg>`\n"
9791 "\n\n"
9792 "   ..\n\n"
9793 ":DEF:"
9794 "You can launch the Tract Controller with:"
9795 "\n'ctrl+s' or 'View-->Tract Controller'\n"
9796 ":SPX:"
9797 "\n") ;
9798 
9799    XtVaCreateManagedWidget ("sep", xmSeparatorWidgetClass, rc_gmamma , NULL);
9800 
9801    rc_mamma = XtVaCreateWidget ("rowcolumn",
9802             xmRowColumnWidgetClass, rc_gmamma,
9803             XmNpacking, XmPACK_TIGHT,
9804             XmNorientation , XmHORIZONTAL ,
9805             XmNmarginHeight, SUMA_MARGIN ,
9806             XmNmarginWidth , SUMA_MARGIN ,
9807             XmNleftAttachment , XmATTACH_FORM ,
9808             XmNtopAttachment  , XmATTACH_FORM ,
9809             XmNrightAttachment , XmATTACH_FORM ,
9810             NULL);
9811 
9812    rc_left = XtVaCreateWidget ("rowcolumn",
9813             xmRowColumnWidgetClass, rc_mamma,
9814             XmNpacking, XmPACK_TIGHT,
9815             XmNorientation , XmVERTICAL ,
9816             XmNmarginHeight, SUMA_MARGIN ,
9817             XmNmarginWidth , SUMA_MARGIN ,
9818 /*            XmNwidth, 317,
9819             XmNresizeWidth, False, */
9820             NULL);
9821 
9822    rc_right = XtVaCreateWidget ("rowcolumn",
9823             xmRowColumnWidgetClass, rc_mamma,
9824             XmNpacking, XmPACK_TIGHT,
9825             XmNorientation , XmVERTICAL ,
9826             XmNmarginHeight, SUMA_MARGIN ,
9827             XmNmarginWidth , SUMA_MARGIN ,
9828             NULL);
9829 
9830 
9831    {/*surface properties */
9832       Widget rc, label, rc_SurfProp, pb, www;
9833 
9834       /* put a frame */
9835       SurfCont->SurfFrame = XtVaCreateWidget ("dialog",
9836          xmFrameWidgetClass, rc_left,
9837          XmNshadowType , XmSHADOW_ETCHED_IN ,
9838          XmNshadowThickness , 5 ,
9839          XmNtraversalOn , False ,
9840          NULL);
9841 
9842       www = XtVaCreateManagedWidget ("Tract Properties",
9843             xmLabelWidgetClass, SurfCont->SurfFrame,
9844             XmNchildType, XmFRAME_TITLE_CHILD,
9845             XmNchildHorizontalAlignment, XmALIGNMENT_BEGINNING,
9846             NULL);
9847       SUMA_Register_Widget_Help( www , 0,
9848                                  "TractCont->Tract_Properties",
9849                                  "Tract Properties",
9850                "Name and number of bundles, tracts, and points making up the "
9851                " selected network of tracts. "
9852                   ":SPX:\n\n"
9853                   ".. figure:: media/TractCont.auto.Tract_Properties.jpg\n"
9854                   "   :align: right\n"
9855                   "   :name: media/TractCont.auto.Tract_Properties.jpg\n"
9856                   "\n"
9857                   "   :ref:`(link)<media/TractCont.auto.Tract_Properties.jpg>`\n"
9858                   "   ..\n\n"
9859                   ":SPX:") ;
9860 
9861       rc_SurfProp = XtVaCreateWidget ("rowcolumn",
9862             xmRowColumnWidgetClass, SurfCont->SurfFrame,
9863             XmNpacking, XmPACK_TIGHT,
9864             XmNorientation , XmVERTICAL ,
9865             XmNmarginHeight, 0 ,
9866             XmNmarginWidth , 0 ,
9867             NULL);
9868 
9869       rc = XtVaCreateWidget ("rowcolumn",
9870             xmRowColumnWidgetClass, rc_SurfProp,
9871             XmNpacking, XmPACK_TIGHT,
9872             XmNorientation , XmHORIZONTAL ,
9873             XmNmarginHeight, 0 ,
9874             XmNmarginWidth , 0 ,
9875             NULL);
9876 
9877       /*put a label containing the Object name, number of bundles, tracts,
9878         points */
9879       lbl30 = SUMA_set_string_length(SUMA_ADO_Label(ado), ' ', 27);
9880       if (lbl30) {
9881          sprintf(slabel,"%s \n%d bnd. %d trc. %d pts.",
9882                      lbl30, TDO_N_BUNDLES(tdo), TDO_N_TRACTS(tdo),
9883                      SUMA_ADO_N_Datum(ado));
9884          SUMA_free(lbl30); lbl30 = NULL;
9885       } else {
9886          sprintf(slabel,"???\n%d bnd. %d trc. %d pts.",
9887                      TDO_N_BUNDLES(tdo),
9888                      TDO_N_TRACTS(tdo), SUMA_ADO_N_Datum(ado));
9889       }
9890       xmstmp = XmStringCreateLtoR (slabel, XmSTRING_DEFAULT_CHARSET);
9891          /* XmStringCreateLocalized(slabel) does not reliably
9892             handle newline characters q*/
9893       SurfCont->SurfInfo_label = XtVaCreateManagedWidget ("hagel",
9894                xmLabelWidgetClass, rc,
9895                XmNlabelString, xmstmp,
9896                NULL);
9897       XmStringFree (xmstmp);
9898       SUMA_Register_Widget_Help( SurfCont->SurfInfo_label, 1,
9899                                  "TractCont->Tract_Properties->label",
9900                                  "Summary object information" ,
9901                                  "Summary object information" ) ;
9902       XtVaCreateManagedWidget (  "sep",
9903                                  xmSeparatorWidgetClass, rc,
9904                                  XmNorientation, XmVERTICAL, NULL );
9905 
9906       SurfCont->SurfInfo_pb = XtVaCreateWidget ("more",
9907          xmPushButtonWidgetClass, rc,
9908          NULL);
9909       XtAddCallback (SurfCont->SurfInfo_pb, XmNactivateCallback,
9910                      SUMA_cb_moreSurfInfo,
9911                         (XtPointer)SUMA_SurfCont_GetcurDOp(SurfCont));
9912       XtVaSetValues (SurfCont->SurfInfo_pb, XmNuserData,
9913                      (XtPointer)SUMA_SurfCont_GetcurDOp(SurfCont), NULL);
9914       SUMA_Register_Widget_Help( SurfCont->SurfInfo_pb, 1,
9915                                  "TractCont->Tract_Properties->more",
9916                                  "More info on network of tracts" ,
9917                                  SUMA_SurfContHelp_more ) ;
9918       XtManageChild (SurfCont->SurfInfo_pb);
9919 
9920       XtManageChild (rc);
9921 
9922       XtManageChild (rc_SurfProp);
9923       XtManageChild (SurfCont->SurfFrame);
9924    }
9925 
9926    SUMA_LH("Xhair business");
9927    {  /* Xhair Controls */
9928       Widget rcv, www;
9929       /* put a frame */
9930       SurfCont->Xhair_fr = XtVaCreateWidget ("dialog",
9931          xmFrameWidgetClass, rc_left,
9932          XmNshadowType , XmSHADOW_ETCHED_IN ,
9933          XmNshadowThickness , 5 ,
9934          XmNtraversalOn , False ,
9935          NULL);
9936 
9937       www = XtVaCreateManagedWidget ("Xhair Info",
9938             xmLabelWidgetClass, SurfCont->Xhair_fr,
9939             XmNchildType, XmFRAME_TITLE_CHILD,
9940             XmNchildHorizontalAlignment, XmALIGNMENT_BEGINNING,
9941             NULL);
9942       SUMA_Register_Widget_Help( www , 0,
9943                                  "TractCont->Xhair_Info",
9944                                  "Information at crosshair",
9945                   ":SPX:\n\n"
9946                   ".. figure:: media/TractCont.auto.Xhair_Info.jpg\n"
9947                   "   :align: right\n\n"
9948                   "   :name: media/TractCont.auto.Xhair_Info.jpg\n"
9949                   "\n"
9950                   "   :ref:`(link)<media/TractCont.auto.Xhair_Info.jpg>`\n"
9951                   "   ..\n\n"
9952                   ":SPX:") ;
9953       /* vertical row column */
9954       rcv = XtVaCreateWidget ("rowcolumn",
9955             xmRowColumnWidgetClass, SurfCont->Xhair_fr,
9956             XmNpacking, XmPACK_TIGHT,
9957             XmNorientation , XmVERTICAL ,
9958             XmNmarginHeight, 0 ,
9959             XmNmarginWidth , 0 ,
9960             NULL);
9961 
9962       /* create the widgets for the colormap stuff */
9963       SUMA_CreateXhairWidgets(rcv, ado);
9964 
9965       XtManageChild(rcv);
9966       XtManageChild(SurfCont->Xhair_fr);
9967    }  /* Xhair Controls */
9968 
9969    SUMA_LHv("\nDset Mapping, tract %s\n", SUMA_ADO_Label(ado));
9970    {  /* Dset Mapping */
9971       Widget rcv, www;
9972       /* put a frame */
9973       SurfCont->DsetMap_fr = XtVaCreateWidget ("dialog",
9974          xmFrameWidgetClass, rc_right,
9975          XmNrightAttachment , XmATTACH_FORM ,
9976          XmNleftAttachment, XmATTACH_WIDGET,
9977          XmNleftWidget, SurfCont->SurfFrame,
9978          XmNtopAttachment  , XmATTACH_FORM ,
9979          XmNshadowType , XmSHADOW_ETCHED_IN ,
9980          XmNshadowThickness , 5 ,
9981          XmNtraversalOn , False ,
9982          NULL);
9983 
9984       www = XtVaCreateManagedWidget ("Dset Mapping",
9985             xmLabelWidgetClass, SurfCont->DsetMap_fr,
9986             XmNchildType, XmFRAME_TITLE_CHILD,
9987             XmNchildHorizontalAlignment, XmALIGNMENT_BEGINNING,
9988             NULL);
9989       SUMA_Register_Widget_Help( www , 0,
9990                                  "TractCont->Dset_Mapping",
9991                                  "Tract Dset Color Mapping",
9992                   ":SPX:\n\n"
9993                   ".. figure:: media/TractCont.auto.Dset_Mapping.jpg\n"
9994                   "   :align: right\n"
9995                   "   :name: media/TractCont.auto.Dset_Mapping.jpg\n"
9996                   "\n"
9997                   "   :ref:`(link)<media/TractCont.auto.Dset_Mapping.jpg>`\n"
9998                   "   ..\n\n"
9999                   ":SPX:") ;
10000 
10001       /* vertical row column */
10002       rcv = XtVaCreateWidget ("rowcolumn",
10003             xmRowColumnWidgetClass, SurfCont->DsetMap_fr,
10004             XmNpacking, XmPACK_TIGHT,
10005             XmNorientation , XmVERTICAL ,
10006             XmNmarginHeight, 0 ,
10007             XmNmarginWidth , 0 ,
10008             NULL);
10009 
10010       /* create the widgets for the colormap stuff */
10011       SUMA_CreateCmapWidgets(rcv, ado);
10012 
10013       XtManageChild(rcv);
10014 
10015       XtManageChild(SurfCont->DsetMap_fr);
10016    }
10017 
10018    SUMA_LH("Dset Controls");
10019    /* Dset Controls */
10020    {
10021        Widget rc, rcv, pb, www;
10022 
10023 
10024       /* put a frame */
10025       SurfCont->ColPlane_fr = XtVaCreateWidget ("dialog",
10026          xmFrameWidgetClass, rc_left,
10027          XmNshadowType , XmSHADOW_ETCHED_IN ,
10028          XmNshadowThickness , 5 ,
10029          XmNtraversalOn , False ,
10030          NULL);
10031 
10032       www = XtVaCreateManagedWidget ("Coloring Controls",
10033             xmLabelWidgetClass, SurfCont->ColPlane_fr,
10034             XmNchildType, XmFRAME_TITLE_CHILD,
10035             XmNchildHorizontalAlignment, XmALIGNMENT_BEGINNING,
10036             NULL);
10037 
10038       SUMA_Register_Widget_Help( www , 0,
10039                                  "TractCont->Coloring_Controls",
10040                                  "Coloring Controls",
10041 "Controls the final coloration of the tracts based on the tract datasets"
10042 " available. What's a tract dataset you say? It is a dataset defined over the"
10043 " collection of points that define the tracts of a network. And where do we get"
10044 " these sets? Nowhere at the moment. For now they are generated internally and"
10045 " they are only of the RGB variety. This will change in the future, when you"
10046 " would be able to drive a flying car and have arbitrary sets much like on"
10047 " surfaces or volumes."
10048 ":SPX:\n\n"
10049 ".. figure:: media/TractCont.auto.Coloring_Controls.jpg\n"
10050 "   :align: right\n"
10051 "   :name: media/TractCont.auto.Coloring_Controls.jpg\n"
10052 "\n"
10053 "   :ref:`(link)<media/TractCont.auto.Coloring_Controls.jpg>`\n"
10054                   "   ..\n\n"
10055                   ":SPX:") ;
10056       /* vertical row column */
10057       rcv = XtVaCreateWidget ("rowcolumn",
10058             xmRowColumnWidgetClass, SurfCont->ColPlane_fr,
10059             XmNpacking, XmPACK_TIGHT,
10060             XmNorientation , XmVERTICAL ,
10061             XmNmarginHeight, 0 ,
10062             XmNmarginWidth , 0 ,
10063             NULL);
10064 
10065       /* row column for label*/
10066       rc = XtVaCreateWidget ("rowcolumn",
10067             xmRowColumnWidgetClass, rcv,
10068             XmNpacking, XmPACK_TIGHT,
10069             XmNorientation , XmHORIZONTAL ,
10070             XmNmarginHeight, 0 ,
10071             XmNmarginWidth , 0 ,
10072             NULL);
10073 
10074       /*put a label containing the surface name,
10075          number of nodes and number of facesets */
10076       {
10077          char *Dset_tit[]  =  {  "Lbl", NULL };
10078          char *Dset_hint[] =  {  "Label of dataset displayed on tracts",  NULL };
10079          char *Dset_help[] =  {  SUMA_SurfContHelp_DsetLblTblr0, NULL };
10080          int colw[]={ 3, 27};
10081          SUMA_CreateTable(rc,
10082             1, 2,
10083             "TractCont->Coloring_Controls->Lbl",
10084             Dset_tit, NULL,
10085             Dset_hint, NULL,
10086             Dset_help, NULL,
10087             colw, NOPE, SUMA_string,
10088             NULL, NULL,
10089             NULL, NULL,
10090             NULL, NULL,
10091             SurfCont->ColPlaneLabelTable);
10092       }
10093       XtManageChild (rc);
10094 
10095       /* add a rc for the colorplane brightness and perhaps visibility? */
10096       rc = XtVaCreateWidget ("rowcolumn",
10097          xmRowColumnWidgetClass, rcv,
10098          XmNpacking, XmPACK_TIGHT,
10099          XmNorientation , XmHORIZONTAL ,
10100          NULL);
10101 
10102       SUMA_CreateArrowField ( rc, "Dim",
10103                            1, 0.1, 2, 0.1,
10104                            3, SUMA_float,
10105                            YUP,
10106                            SUMA_cb_ColPlane_NewDimFact, (void *)ado,
10107                            "TractCont->Coloring_Controls->Dim",
10108                            SUMA_SurfCont_ColPlaneDim_hint,
10109                            SUMA_SurfContHelp_DsetDim,
10110                            SurfCont->ColPlaneDimFact);
10111 
10112       SUMA_CreateArrowField ( rc, "Ord",
10113                            1, 0, 20, 1,
10114                            2, SUMA_int,
10115                            NOPE,
10116                            SUMA_cb_ColPlane_NewOrder, (void *)ado,
10117                            "TractCont->Coloring_Controls->Ord",
10118                            SUMA_SurfCont_ColPlaneOrder_hint,
10119                            SUMA_TractContHelp_DsetOrd,
10120                            SurfCont->ColPlaneOrder);
10121 
10122       SurfCont->ColPlaneShowOneFore_tb =
10123          XtVaCreateManagedWidget("1",
10124                                  xmToggleButtonWidgetClass, rc, NULL);
10125       XmToggleButtonSetState (SurfCont->ColPlaneShowOneFore_tb,
10126                               SurfCont->ShowCurForeOnly, NOPE);
10127       XtAddCallback (SurfCont->ColPlaneShowOneFore_tb,
10128                      XmNvalueChangedCallback,
10129                      SUMA_cb_ColPlaneShowOneFore_toggled, ado);
10130 
10131       SUMA_Register_Widget_Help(SurfCont->ColPlaneShowOneFore_tb , 1,
10132                                 "TractCont->Coloring_Controls->1",
10133              "Show ONLY selected set. (BHelp for more)",
10134                                 SUMA_TractContHelp_DsetViewOne ) ;
10135       SUMA_SET_SELECT_COLOR(SurfCont->ColPlaneShowOneFore_tb);
10136 
10137       /* manage  rc */
10138       XtManageChild (rc);
10139 
10140       /* another row*/
10141       rc = XtVaCreateWidget ("rowcolumn",
10142          xmRowColumnWidgetClass, rcv,
10143          XmNpacking, XmPACK_TIGHT,
10144          XmNorientation , XmHORIZONTAL ,
10145          NULL);
10146 
10147       SUMA_BuildMenuReset(0);
10148 
10149       SUMA_CreateArrowField ( rc, "Opa",
10150                            1, 0.0, 1.0, 0.1,
10151                            3, SUMA_float,
10152                            NOPE,
10153                            SUMA_cb_ColPlane_NewOpacity, (void *)ado,
10154                            "TractCont->Coloring_Controls->Opa",
10155                            SUMA_SurfCont_ColPlaneOpacity_hint,
10156                            SUMA_TractContHelp_DsetOpa,
10157                            SurfCont->ColPlaneOpacity);
10158 
10159       SUMA_BuildMenuReset(0);
10160       SurfCont->TractStyleMenu =
10161          SUMA_Alloc_Menu_Widget(SW_N_SurfCont_TractStyle);
10162       SUMA_BuildMenu (rc, XmMENU_OPTION,
10163                 "Ln", '\0', YUP, TractStyle_Menu,
10164                 (void *)SUMA_SurfCont_GetcurDOp(SurfCont),
10165                 "TractCont->Coloring_Controls->Ln",
10166                 "Line drawing style",
10167                 SUMA_SurfContHelp_TractStyle,
10168                 SurfCont->TractStyleMenu );
10169       XtManageChild (SurfCont->TractStyleMenu->mw[SW_SurfCont_TractStyle]);
10170 
10171       XtManageChild (rc);
10172 
10173       /* Masking opts*/
10174       rc = XtVaCreateWidget ("rowcolumn",
10175           xmRowColumnWidgetClass, rcv,
10176           XmNpacking, XmPACK_TIGHT,
10177           XmNorientation , XmHORIZONTAL ,
10178           NULL);
10179 
10180       SurfCont->Mask_pb = XtVaCreateWidget ("Masks",
10181          xmPushButtonWidgetClass, rc,
10182          NULL);
10183       XtAddCallback (SurfCont->Mask_pb, XmNactivateCallback,
10184                      SUMA_cb_Mask,
10185                         (XtPointer)SUMA_SurfCont_GetcurDOp(SurfCont));
10186       XtVaSetValues (SurfCont->Mask_pb, XmNuserData,
10187                      (XtPointer)SUMA_SurfCont_GetcurDOp(SurfCont), NULL);
10188       SUMA_Register_Widget_Help( SurfCont->Mask_pb , 1,
10189                                  "TractCont->Coloring_Controls->Masks",
10190                                  "Create/Switch to Masks controller",
10191                                  SUMA_SurfContHelp_Mask ) ;
10192       XtManageChild (SurfCont->Mask_pb);
10193 
10194       SUMA_BuildMenuReset(0);
10195       SurfCont->TractMaskMenu =
10196           SUMA_Alloc_Menu_Widget(SW_N_SurfCont_TractMask);
10197       SUMA_BuildMenu (rc, XmMENU_OPTION,
10198                 "", '\0', YUP, TractMask_Menu,
10199                 (void *)SUMA_SurfCont_GetcurDOp(SurfCont),
10200                 "TractCont->Coloring_Controls->Hde",
10201                 "Choose how masked tracts are displayed.",
10202                 SUMA_SurfContHelp_TractMask,
10203                 SurfCont->TractMaskMenu );
10204       XtManageChild (SurfCont->TractMaskMenu->mw[SW_SurfCont_TractMask]);
10205       if (!SUMA_findanyMDOp(NULL))
10206          XtSetSensitive(SurfCont->TractMaskMenu->mw[SW_SurfCont_TractMask], 0);
10207 
10208       SUMA_BuildMenuReset(0);
10209       SUMA_CreateArrowField ( rc, "Gry",
10210                            TSaux->MaskGray, 0.0, 100, 5,
10211                            2, SUMA_int,
10212                            NOPE,
10213                            SUMA_cb_Tract_NewGray, (void *)ado,
10214                            "TractCont->Coloring_Controls->Gry",
10215                            SUMA_SurfCont_TractMask_hint,
10216                            SUMA_SurfContHelp_TractMaskGray,
10217                            SurfCont->TractMaskGray);
10218       if (!SUMA_findanyMDOp(NULL))
10219          XtSetSensitive(SurfCont->TractMaskGray->rc, 0);
10220 
10221       XtManageChild (rc);
10222 
10223       XtVaCreateManagedWidget (  "sep",
10224                                  xmSeparatorWidgetClass, rcv,
10225                                  XmNorientation, XmHORIZONTAL,NULL);
10226 
10227       /* row column for Switch, Load, Delete */
10228       rc = XtVaCreateWidget ("rowcolumn",
10229          xmRowColumnWidgetClass, rcv,
10230          XmNpacking, XmPACK_TIGHT,
10231          XmNorientation , XmHORIZONTAL ,
10232          NULL);
10233 
10234       /* put a push button to switch between color planes */
10235       SurfCont->SwitchDsetlst =
10236             SUMA_AllocateScrolledList ("Switch Coloring",
10237                      SUMA_LSP_SINGLE,
10238                      NOPE, NOPE, /* duplicate deletion, no sorting */
10239                      SurfCont->TLS, SWP_POINTER,
10240                      125,
10241                      SUMA_cb_SelectSwitchColPlane, (void *)ado,
10242                      SUMA_cb_SelectSwitchColPlane, (void *)ado,
10243                      SUMA_cb_CloseSwitchColPlane, NULL);
10244 
10245 
10246       pb = XtVaCreateWidget ("Switch Dset",
10247          xmPushButtonWidgetClass, rc,
10248          NULL);
10249       XtAddCallback (pb, XmNactivateCallback,
10250                      SUMA_cb_SurfCont_SwitchColPlane, (XtPointer)ado);
10251       SUMA_Register_Widget_Help(pb, 1,
10252                            "TractCont->Coloring_Controls->Switch_Dset",
10253                                 "Switch between datasets",
10254                                 SUMA_TractContHelp_DsetSwitch ) ;
10255       XtManageChild (pb);
10256 
10257       pb = XtVaCreateWidget ("Load Dset",
10258             xmPushButtonWidgetClass, rc,
10259             NULL);
10260       XtAddCallback (pb, XmNactivateCallback,
10261                      SUMA_cb_Dset_Load, (XtPointer) ado);
10262       SUMA_Register_Widget_Help(pb, 1,"TractCont->Coloring_Controls->Load_Dset",
10263                                 "Load a new dataset (much more with BHelp)",
10264                                 SUMA_SurfContHelp_DsetLoad ) ;
10265       /* XtManageChild (pb); Not ready just yet */
10266 
10267       pb = XtVaCreateWidget ("Delete",
10268          xmPushButtonWidgetClass, rc,
10269          NULL);
10270       XtAddCallback (pb, XmNactivateCallback,
10271                      SUMA_cb_ColPlane_Delete, (XtPointer) ado);
10272       /* XtManageChild (pb); */ /* Not ready for this one yet */
10273 
10274 
10275 
10276       XtManageChild (rc);
10277       /* manage vertical row column */
10278       XtManageChild (rcv);
10279 
10280       XtManageChild (SurfCont->ColPlane_fr);
10281    }
10282 
10283 
10284 
10285    if (SUMAg_CF->X->UseSameSurfCont) {
10286       Widget rc=NULL;
10287       /* put something to cycle through objects */
10288       if ((rc = SUMA_FindChildWidgetNamed(SurfCont->DispFrame, "rowcolumnCBF"))){
10289          XtVaCreateManagedWidget (  "sep",
10290                               xmSeparatorWidgetClass, rc,
10291                               XmNorientation, XmVERTICAL,NULL);
10292          pb = XtVaCreateWidget ("All Objs.",
10293                   xmPushButtonWidgetClass, rc,
10294                   NULL);
10295          XtAddCallback (pb, XmNactivateCallback,
10296                         SUMA_cb_AllConts, NULL);
10297          SUMA_Register_Widget_Help(pb, 1,"TractCont->Disp_Cont->AllObjs",
10298                                 "Initialize Controllers for All Objects",
10299                                 SUMA_SurfContHelp_AllObjs) ;
10300          XtManageChild (pb);
10301 
10302          SUMA_CreateArrowField ( rc, "Switch",
10303                            1, 1, 20, 1,
10304                            2, SUMA_int,
10305                            YUP,
10306                            SUMA_cb_SurfCont_SwitchPage, (void *)ado,
10307                            "TractCont->Disp_Cont->Switch",
10308                            "Switch to other object controller",
10309                            SUMA_Switch_Cont_BHelp,
10310                            SurfCont->SurfContPage);
10311          xmstmp = XmStringCreateLtoR (SUMA_ADO_CropLabel(ado,
10312                                           SUMA_SURF_CONT_SWITCH_LABEL_LENGTH),
10313                                       XmSTRING_DEFAULT_CHARSET);
10314          SurfCont->SurfContPage_label = XtVaCreateManagedWidget ("dingel-5",
10315                xmLabelWidgetClass, rc,
10316                XmNlabelString, xmstmp,
10317                NULL);
10318          XmStringFree (xmstmp);
10319       }
10320    }
10321 
10322    SUMA_LHv("Management ...%p %p %p %p %p\n",
10323             rc_right, rc_left, rc_mamma, SurfCont->Mainform, SurfCont->Page);
10324 
10325    XtManageChild (rc_right);
10326    XtManageChild (rc_left);
10327    XtManageChild (rc_mamma);
10328    XtManageChild (rc_gmamma);
10329    XtManageChild (SurfCont->Mainform);
10330    if (SUMAg_CF->X->UseSameSurfCont) XtManageChild (SurfCont->Page);
10331 
10332    #if SUMA_CONTROLLER_AS_DIALOG
10333    #else
10334    /** Feb 03/03: pop it up if it is a topLevelShellWidgetClass,
10335    you should do the popping after all the widgets have been created.
10336    Otherwise, the window does not size itself correctly when open */
10337    XtPopup(SurfCont->TLS, XtGrabNone);
10338    #endif
10339 
10340    /* realize the widget */
10341    if (SUMAg_CF->X->UseSameSurfCont) XtManageChild (SUMAg_CF->X->SC_Notebook);
10342    XtRealizeWidget (SurfCont->TLS);
10343 
10344    SUMA_LH("%s",slabel);
10345    SUMA_free (slabel);
10346 
10347    /* Mark as open */
10348    SUMA_MarkSurfContOpen(1,ado);
10349 
10350    SUMA_LHv("Marked %s's controller as open.\n", SUMA_ADO_Label(ado));
10351 
10352    /* initialize the left side
10353       (no need here, that's done in SUMA_cb_viewSurfaceCont)*/
10354    /* SUMA_Init_SurfCont_SurfParam(ado); */
10355 
10356    /* initialize the ColorPlane frame if possible
10357    Do it here rather than above because scale goes crazy
10358    when parent widgets are being resized*/
10359 
10360 
10361    if (SUMA_ADO_N_Overlays(ado)>0) {
10362       SUMA_LH("Initializing ColPlaneShell");
10363       SUMA_InitializeColPlaneShell(ado, curColPlane);
10364       #ifdef NONONO /* It looks like I do not need this anymore
10365                        Used to be #idef DARWIN */
10366       /* Sometimes color maps do not show up on mac when you first
10367          open the surface controller */
10368       SUMA_LH("Darwining");
10369       SUMA_SwitchColPlaneCmap(ado, SUMA_CmapOfPlane(curColPlane));
10370       #endif
10371    }
10372 
10373    #if USING_LESSTIF
10374    SUMA_LH("Less tif fix");
10375    /* A quick fix to ensure Dset_Mapping
10376       gets displayed properly the first time */
10377    SUMA_cb_ToggleManagementColPlaneWidget(NULL, (XtPointer)(&ado), NULL);
10378    SUMA_cb_ToggleManagementColPlaneWidget(NULL, (XtPointer)(&ado), NULL);
10379    #endif
10380 
10381    SUMA_LH("going home.");
10382 
10383    SUMA_MarkSurfContOpen(1, ado);
10384 
10385    SUMA_RETURNe;
10386 }
10387 
SUMA_cb_createSurfaceCont_CO(Widget w,XtPointer data,XtPointer callData)10388 void SUMA_cb_createSurfaceCont_CO(Widget w, XtPointer data, XtPointer callData)
10389 {
10390    static char FuncName[] = {"SUMA_cb_createSurfaceCont_CO"};
10391    Widget tl, pb, form,
10392           rc_left, rc_right, rc_mamma, rc_gmamma, tls=NULL;
10393    Display *dpy;
10394    SUMA_ALL_DO *ado;
10395    SUMA_CIFTI_DO *co;
10396    char *slabel, *lbl30, *sss=NULL;
10397    XmString xmstmp;
10398    SUMA_X_SurfCont *SurfCont=NULL;
10399    SUMA_OVERLAYS *curColPlane=NULL, *over0=NULL;
10400    SUMA_Boolean LocalHead = NOPE;
10401 
10402    SUMA_ENTRY;
10403 
10404    ado = (SUMA_ALL_DO *)data;
10405    if (ado->do_type != CDOM_type) {
10406       SUMA_S_Errv("Calling me with (%s) other than VO_type type,\n"
10407                   "I don't like that, call me with VO",
10408                   SUMA_ObjectTypeCode2ObjectTypeName(ado->do_type));
10409       SUMA_RETURNe;
10410    }
10411 
10412    SUMA_S_Err("CIFTI objects do not have their own controller");
10413 
10414    SUMA_RETURNe;
10415 }
10416 
SUMA_cb_createSurfaceCont_VO(Widget w,XtPointer data,XtPointer callData)10417 void SUMA_cb_createSurfaceCont_VO(Widget w, XtPointer data, XtPointer callData)
10418 {
10419    static char FuncName[] = {"SUMA_cb_createSurfaceCont_VO"};
10420    Widget tl, pb, form,
10421           rc_left, rc_right, rc_mamma, rc_gmamma, tls=NULL;
10422    Display *dpy;
10423    SUMA_ALL_DO *ado;
10424    SUMA_VolumeObject *vo;
10425    char *slabel, *lbl30, *sss=NULL;
10426    XmString xmstmp;
10427    SUMA_X_SurfCont *SurfCont=NULL;
10428    SUMA_OVERLAYS *curColPlane=NULL, *over0=NULL;
10429    SUMA_Boolean LocalHead = NOPE;
10430 
10431    SUMA_ENTRY;
10432 
10433    ado = (SUMA_ALL_DO *)data;
10434    if (ado->do_type != VO_type) {
10435       SUMA_S_Errv("Calling me with (%s) other than VO_type type,\n"
10436                   "I don't like that, call me with VO",
10437                   SUMA_ObjectTypeCode2ObjectTypeName(ado->do_type));
10438       SUMA_RETURNe;
10439    }
10440    vo = (SUMA_VolumeObject *)ado;
10441 
10442    SUMA_LHv("Creating SurfaceCont for type %s, label %s\n",
10443             ADO_TNAME(ado), SUMA_ADO_Label(ado));
10444 
10445    if (!(SurfCont = SUMA_ADO_Cont(ado))) {
10446       SUMA_S_Errv("Failed to get Controller for ado %s\n",
10447                   SUMA_ADO_Label(ado));
10448       SUMA_RETURNe;
10449    }
10450    SUMA_LH("SurfCont = %p, %p %p %p",
10451             SurfCont, SurfCont->Ax_slc, SurfCont->Sa_slc, SurfCont->Co_slc);
10452    if (!SUMA_SurfCont_SetcurDOp(SurfCont, ado)) {
10453       SUMA_S_Errv("Failed to Set curDOp for %s\n",
10454                   SUMA_ADO_Label(ado));
10455       SUMA_RETURNe;
10456    }
10457    if (!(curColPlane = SUMA_ADO_CurColPlane(ado))) {
10458       SUMA_S_Errv("Failed to get current col plane for ado %s\n",
10459                   SUMA_ADO_Label(ado));
10460       SUMA_RETURNe;
10461    }
10462    if (SurfCont->TLS) {
10463       fprintf (SUMA_STDERR,
10464                "Error %s: SurfCont->TopLevelShell!=NULL.\n"
10465                "Should not be here.\n", FuncName);
10466       SUMA_RETURNe;
10467    }
10468 
10469    SUMA_LH("Getting TL of %p", w);
10470    tl = SUMA_GetTopShell(w); /* top level widget */
10471    SUMA_LH("Got tl = %p", tl);
10472    dpy = XtDisplay(tl);
10473    SUMA_LH("Got dpy %p", dpy);
10474 
10475    slabel = (char *)SUMA_malloc(sizeof(char) *
10476                                  (strlen(SUMA_ADO_Label(ado)) + 100));
10477    if (strlen(SUMA_ADO_Label(ado)) > 40) {
10478       char *tmpstr=NULL;
10479       tmpstr = SUMA_truncate_string(SUMA_ADO_Label(ado), 40);
10480       if (tmpstr) {
10481          sprintf(slabel,"[%s] Volume Controller", tmpstr);
10482          free(tmpstr); tmpstr=NULL;
10483       }
10484    } else {
10485       sprintf(slabel,"[%s] Volume Controller", SUMA_ADO_Label(ado));
10486    }
10487 
10488    /* March 12 08: Made font8 default for surface controller */
10489    if (SUMA_isEnv("SUMA_SurfContFontSize", "BIG")) {
10490       sss = "font9";
10491    } else {
10492       sss = "font8";
10493    }
10494 
10495    SUMA_LH("Creating dialog shell.");
10496    if (!SUMAg_CF->X->UseSameSurfCont ||
10497        !SUMAg_CF->X->CommonSurfContTLW) { /* need a new one */
10498       #if SUMA_CONTROLLER_AS_DIALOG /* xmDialogShellWidgetClass,
10499                                        topLevelShellWidgetClass*/
10500       tls = XtVaCreatePopupShell (sss,
10501          XmNtitle, slabel,
10502          xmDialogShellWidgetClass, tl,
10503          XmNallowShellResize, True, /* let code resize shell */
10504          XmNdeleteResponse, XmDO_NOTHING,
10505          NULL);
10506       #else
10507       SUMA_LH("Creating toplevel shell.");
10508       /** Feb 03/03:    I was using XtVaCreatePopupShell to create a
10509                         topLevelShellWidgetClass.
10510                         XtVaCreatePopupShell is used to create dialog
10511                         shells not toplevel or appshells.
10512                         Of course, it made no difference! */
10513       tls = XtVaAppCreateShell (sss, "Suma",
10514          topLevelShellWidgetClass, SUMAg_CF->X->DPY_controller1 ,
10515          XmNtitle, slabel,
10516          XmNdeleteResponse, XmDO_NOTHING,
10517          NULL);
10518       #endif
10519 
10520       /* allow for code to resize the shell */
10521       XtVaSetValues (tls,
10522             XmNresizePolicy , XmRESIZE_NONE ,
10523             XmNallowShellResize , True ,       /* let code resize shell */
10524             NULL);
10525 
10526       /* handle the close button from window manager */
10527       XmAddWMProtocolCallback(/* make "Close" window menu work */
10528          tls,
10529          XmInternAtom( dpy , "WM_DELETE_WINDOW" , False ) ,
10530          SUMA_cb_closeSurfaceCont, (XtPointer) ado) ;
10531 
10532       if (SUMAg_CF->X->UseSameSurfCont) {
10533          Widget scroller;
10534          SUMAg_CF->X->CommonSurfContTLW = tls;
10535          SUMAg_CF->X->SC_Notebook =
10536             XtVaCreateWidget("ControllerBook", xmNotebookWidgetClass,
10537                              SUMAg_CF->X->CommonSurfContTLW,
10538                              XmNbindingWidth, XmNONE,
10539                              XmNbackPageNumber, 0,
10540                              XmNmajorTabSpacing, 0,
10541                              XmNminorTabSpacing, 0,
10542                              NULL);
10543             /*XmCreateNotebook (SUMAg_CF->X->CommonSurfContTLW, "ControllerBook",
10544                               NULL, 0);
10545               XtVaSetValues(SUMAg_CF->X->SC_Notebook,
10546                           XmNbindingWidth, XmNONE,
10547                           NULL); */
10548 
10549 
10550          /* Kill the scroller from hell otherwise no keyboard input
10551             gets to the baby widgets. Better write my own scroller
10552             if need be in the future */
10553          scroller = XtNameToWidget (SUMAg_CF->X->SC_Notebook, "PageScroller");
10554          XtUnmanageChild (scroller);
10555       }
10556    }
10557 
10558    if (SUMAg_CF->X->UseSameSurfCont) {
10559       SurfCont->TLS = SUMAg_CF->X->CommonSurfContTLW;
10560    } else {
10561       SurfCont->TLS = tls;
10562    }
10563 
10564    if (!SurfCont->TLS) {
10565       SUMA_S_Err("Bad logic");
10566       SUMA_RETURNe;
10567    }
10568 
10569    SUMA_LH("Widgets...");
10570    if (SUMAg_CF->X->UseSameSurfCont) {
10571       Arg args[20];
10572       /* add the page */
10573       XtSetArg (args[0], XmNnotebookChildType, XmPAGE);
10574       SurfCont->Page =
10575          XmCreateRowColumn (SUMAg_CF->X->SC_Notebook,
10576                      SUMA_ADO_Label(ado)?SUMA_ADO_Label(ado):"page",
10577                                               args, 1);
10578    }
10579 
10580    /* create a form widget, manage it at the end ...*/
10581    SurfCont->Mainform = XtVaCreateWidget ("dialog",
10582       xmFormWidgetClass, SurfCont->Page ?
10583                               SurfCont->Page:SurfCont->TLS,
10584       XmNborderWidth , 0 ,
10585       XmNmarginHeight , SUMA_MARGIN ,
10586       XmNmarginWidth  , SUMA_MARGIN ,
10587       XmNshadowThickness, 2,
10588       XmNshadowType, XmSHADOW_ETCHED_IN,
10589       NULL);
10590 
10591    rc_gmamma = XtVaCreateWidget ("rowcolumn",
10592             xmRowColumnWidgetClass, SurfCont->Mainform,
10593             XmNpacking, XmPACK_TIGHT,
10594             XmNorientation , XmVERTICAL ,
10595             XmNmarginHeight, SUMA_MARGIN ,
10596             XmNmarginWidth , SUMA_MARGIN ,
10597             XmNtopAttachment  , XmATTACH_FORM ,
10598             XmNbottomAttachment  , XmATTACH_FORM ,
10599             NULL);
10600 
10601 
10602    SurfCont->DispFrame = SUMA_CloseBhelp_Frame(rc_gmamma,
10603                      SUMA_cb_closeSurfaceCont, (XtPointer) ado,
10604                      "VolCont",
10605                      "Close Surface controller", SUMA_closeSurfaceCont_help,
10606                      NULL, NULL, NULL, NULL);
10607 
10608    SUMA_Register_Widget_Help( SurfCont->DispFrame , 0,
10609                                  "VolCont",
10610                                  "Volume Cont.",
10611 "The volume controller is for controlling the way volumes are rendered. Each volume gets its own controller. You can use the switch button above to switch between them. The volume controller is initialized by the volume of the last selected voxel.\n After you have selected a voxel, "
10612 ":SPX:"
10613 "you can launch the :ref:`Volume Controller <VolCont>` with:"
10614 " :ref:`ctrl+s <LC_Ctrl+s>` or :menuselection:`View-->Object Controller`\n"
10615 "\n"
10616 ".. figure:: media/VolCont.auto.ALL.jpg\n"
10617 "   :align: center\n"
10618 "   :name: media/VolCont.auto.ALL.jpg\n"
10619 "\n"
10620 "   :ref:`(link)<media/VolCont.auto.ALL.jpg>`\n"
10621 "   ..\n\n"
10622 ":DEF:"
10623 "you can launch the Volume Controller with:"
10624 "\n'ctrl+s' or 'View-->Object Controller'\n"
10625 ":SPX:"
10626 "\n") ;
10627 
10628    XtVaCreateManagedWidget ("sep", xmSeparatorWidgetClass, rc_gmamma , NULL);
10629 
10630    rc_mamma = XtVaCreateWidget ("rowcolumn",
10631             xmRowColumnWidgetClass, rc_gmamma,
10632             XmNpacking, XmPACK_TIGHT,
10633             XmNorientation , XmHORIZONTAL ,
10634             XmNmarginHeight, SUMA_MARGIN ,
10635             XmNmarginWidth , SUMA_MARGIN ,
10636             XmNleftAttachment , XmATTACH_FORM ,
10637             XmNtopAttachment  , XmATTACH_FORM ,
10638             XmNrightAttachment , XmATTACH_FORM ,
10639             NULL);
10640 
10641    rc_left = XtVaCreateWidget ("rowcolumn",
10642             xmRowColumnWidgetClass, rc_mamma,
10643             XmNpacking, XmPACK_TIGHT,
10644             XmNorientation , XmVERTICAL ,
10645             XmNmarginHeight, SUMA_MARGIN ,
10646             XmNmarginWidth , SUMA_MARGIN ,
10647             NULL);
10648 
10649    rc_right = XtVaCreateWidget ("rowcolumn",
10650             xmRowColumnWidgetClass, rc_mamma,
10651             XmNpacking, XmPACK_TIGHT,
10652             XmNorientation , XmVERTICAL ,
10653             XmNmarginHeight, SUMA_MARGIN ,
10654             XmNmarginWidth , SUMA_MARGIN ,
10655             NULL);
10656 
10657 
10658    {/*surface properties */
10659       Widget rc, label, rc_SurfProp, pb, www;
10660 
10661       /* put a frame */
10662       SurfCont->SurfFrame = XtVaCreateWidget ("dialog",
10663          xmFrameWidgetClass, rc_left,
10664          XmNshadowType , XmSHADOW_ETCHED_IN ,
10665          XmNshadowThickness , 5 ,
10666          XmNtraversalOn , False ,
10667          NULL);
10668 
10669       www = XtVaCreateManagedWidget ("Volume Properties",
10670             xmLabelWidgetClass, SurfCont->SurfFrame,
10671             XmNchildType, XmFRAME_TITLE_CHILD,
10672             XmNchildHorizontalAlignment, XmALIGNMENT_BEGINNING,
10673             NULL);
10674       SUMA_Register_Widget_Help( www , 0,
10675                                  "VolCont->Volume_Properties",
10676                                  "Volume Properties",
10677                   "Block providing information about selected volume."
10678                   ":SPX:\n\n"
10679                   ".. figure:: media/VolCont.auto.Volume_Properties.jpg\n"
10680                   "   :align: right\n"
10681                   "   :name: media/VolCont.auto.Volume_Properties.jpg\n"
10682                   "\n"
10683                   "   :ref:`(link)<media/VolCont.auto.Volume_Properties.jpg>`\n"
10684                   "   ..\n\n"
10685                   ":SPX:") ;
10686 
10687       rc_SurfProp = XtVaCreateWidget ("rowcolumn",
10688             xmRowColumnWidgetClass, SurfCont->SurfFrame,
10689             XmNpacking, XmPACK_TIGHT,
10690             XmNorientation , XmVERTICAL ,
10691             XmNmarginHeight, 0 ,
10692             XmNmarginWidth , 0 ,
10693             NULL);
10694 
10695       rc = XtVaCreateWidget ("rowcolumn",
10696             xmRowColumnWidgetClass, rc_SurfProp,
10697             XmNpacking, XmPACK_TIGHT,
10698             XmNorientation , XmHORIZONTAL ,
10699             XmNmarginHeight, 0 ,
10700             XmNmarginWidth , 0 ,
10701             NULL);
10702 
10703       /*put a label containing the Object name, number of bundles, tracts,
10704         points */
10705 
10706       lbl30 = SUMA_set_string_length(SUMA_ADO_Label(ado), ' ', 27);
10707       if (lbl30) {
10708          sprintf(slabel,"%s\n%d x %d x %d (%d vox)",
10709                      lbl30, VO_NI(vo), VO_NJ(vo), VO_NK(vo),
10710                      SUMA_ADO_N_Datum(ado));
10711          SUMA_free(lbl30); lbl30 = NULL;
10712       } else {
10713          sprintf(slabel,"???\n%d x %d x %d = %d voxels.",
10714                      VO_NI(vo), VO_NJ(vo), VO_NK(vo),
10715                      SUMA_ADO_N_Datum(ado));
10716       }
10717       xmstmp = XmStringCreateLtoR (slabel, XmSTRING_DEFAULT_CHARSET);
10718          /* XmStringCreateLocalized(slabel) does not reliably
10719             handle newline characters q*/
10720       SurfCont->SurfInfo_label = XtVaCreateManagedWidget ("shagel",
10721                xmLabelWidgetClass, rc,
10722                XmNlabelString, xmstmp,
10723                NULL);
10724       XmStringFree (xmstmp);
10725       SUMA_Register_Widget_Help( SurfCont->SurfInfo_label, 1,
10726                                  "VolCont->Volume_Properties->label",
10727                                  "Summary object information" ,
10728                                  "Summary object information" ) ;
10729 
10730       XtVaCreateManagedWidget (  "sep",
10731                                  xmSeparatorWidgetClass, rc,
10732                                  XmNorientation, XmVERTICAL, NULL );
10733 
10734       SurfCont->SurfInfo_pb = XtVaCreateWidget ("more",
10735          xmPushButtonWidgetClass, rc,
10736          NULL);
10737       XtAddCallback (SurfCont->SurfInfo_pb, XmNactivateCallback,
10738                      SUMA_cb_moreSurfInfo,
10739                         (XtPointer)SUMA_SurfCont_GetcurDOp(SurfCont));
10740       XtVaSetValues (SurfCont->SurfInfo_pb, XmNuserData,
10741                      (XtPointer)SUMA_SurfCont_GetcurDOp(SurfCont), NULL);
10742       SUMA_Register_Widget_Help( SurfCont->SurfInfo_pb , 1,
10743                                  "VolCont->Volume_Properties->more",
10744                                  "More info on Volume",
10745                                  SUMA_SurfContHelp_more ) ;
10746       XtManageChild (SurfCont->SurfInfo_pb);
10747 
10748       XtManageChild (rc);
10749 
10750       XtManageChild (rc_SurfProp);
10751       XtManageChild (SurfCont->SurfFrame);
10752    }
10753 
10754    SUMA_LH("Xhair business");
10755    {  /* Xhair Controls */
10756       Widget rcv, www;
10757 
10758       /* put a frame */
10759       SurfCont->Xhair_fr = XtVaCreateWidget ("dialog",
10760          xmFrameWidgetClass, rc_left,
10761          XmNshadowType , XmSHADOW_ETCHED_IN ,
10762          XmNshadowThickness , 5 ,
10763          XmNtraversalOn , False ,
10764          NULL);
10765 
10766       www = XtVaCreateManagedWidget ("Xhair Info",
10767             xmLabelWidgetClass, SurfCont->Xhair_fr,
10768             XmNchildType, XmFRAME_TITLE_CHILD,
10769             XmNchildHorizontalAlignment, XmALIGNMENT_BEGINNING,
10770             NULL);
10771       SUMA_Register_Widget_Help( www , 0,
10772                                  "VolCont->Xhair_Info",
10773                                  "Information at crosshair",
10774                                  ":SPX:\n\n"
10775                   ".. figure:: media/VolCont.auto.Xhair_Info.jpg\n"
10776                   "   :align: right\n"
10777                   "   :name: media/VolCont.auto.Xhair_Info.jpg\n"
10778                   "\n"
10779                   "   :ref:`(link)<media/VolCont.auto.Xhair_Info.jpg>`\n"
10780                   "   ..\n\n"
10781                   ":SPX:") ;
10782 
10783 
10784       /* vertical row column */
10785       rcv = XtVaCreateWidget ("rowcolumn",
10786             xmRowColumnWidgetClass, SurfCont->Xhair_fr,
10787             XmNpacking, XmPACK_TIGHT,
10788             XmNorientation , XmVERTICAL ,
10789             XmNmarginHeight, 0 ,
10790             XmNmarginWidth , 0 ,
10791             NULL);
10792 
10793       /* create the widgets for the colormap stuff */
10794       SUMA_CreateXhairWidgets(rcv, ado);
10795 
10796       XtManageChild(rcv);
10797       XtManageChild(SurfCont->Xhair_fr);
10798    }  /* Xhair Controls */
10799 
10800    SUMA_LHv("\nDset Mapping, volume %s\n", SUMA_ADO_Label(ado));
10801    {  /* Dset Mapping */
10802       Widget rcv, www;
10803       /* put a frame */
10804       SurfCont->DsetMap_fr = XtVaCreateWidget ("dialog",
10805          xmFrameWidgetClass, rc_right,
10806          XmNrightAttachment , XmATTACH_FORM ,
10807          XmNleftAttachment, XmATTACH_WIDGET,
10808          XmNleftWidget, SurfCont->SurfFrame,
10809          XmNtopAttachment  , XmATTACH_FORM ,
10810          XmNshadowType , XmSHADOW_ETCHED_IN ,
10811          XmNshadowThickness , 5 ,
10812          XmNtraversalOn , False ,
10813          NULL);
10814 
10815       www = XtVaCreateManagedWidget ("Dset Mapping",
10816             xmLabelWidgetClass, SurfCont->DsetMap_fr,
10817             XmNchildType, XmFRAME_TITLE_CHILD,
10818             XmNchildHorizontalAlignment, XmALIGNMENT_BEGINNING,
10819             NULL);
10820       SUMA_Register_Widget_Help( www , 0,
10821                                  "VolCont->Dset_Mapping",
10822                                  "Dset Color Mapping",
10823                   ":SPX:\n\n"
10824                   ".. figure:: media/VolCont.auto.Dset_Mapping.jpg\n"
10825                   "   :align: right\n"
10826                   "   :name: media/VolCont.auto.Dset_Mapping.jpg\n"
10827                   "\n"
10828                   "   :ref:`(link)<media/VolCont.auto.Dset_Mapping.jpg>`\n"
10829                   "   ..\n\n"
10830                   ":SPX:") ;
10831 
10832       /* vertical row column */
10833       rcv = XtVaCreateWidget ("rowcolumn",
10834             xmRowColumnWidgetClass, SurfCont->DsetMap_fr,
10835             XmNpacking, XmPACK_TIGHT,
10836             XmNorientation , XmVERTICAL ,
10837             XmNmarginHeight, 0 ,
10838             XmNmarginWidth , 0 ,
10839             NULL);
10840 
10841       /* create the widgets for the colormap stuff */
10842       SUMA_CreateCmapWidgets(rcv, ado);
10843 
10844       XtManageChild(rcv);
10845 
10846       XtManageChild(SurfCont->DsetMap_fr);
10847    }
10848 
10849    SUMA_LH("Slice Controls");
10850    {
10851       Widget rc, rcv, pb, rch, www;
10852 
10853       /* put a frame */
10854       SurfCont->Slice_fr = XtVaCreateWidget ("dialog",
10855          xmFrameWidgetClass, rc_left,
10856          XmNshadowType , XmSHADOW_ETCHED_IN ,
10857          XmNshadowThickness , 5 ,
10858          XmNtraversalOn , False ,
10859          NULL);
10860 
10861       www = XtVaCreateManagedWidget ("Slice Controls",
10862             xmLabelWidgetClass, SurfCont->Slice_fr,
10863             XmNchildType, XmFRAME_TITLE_CHILD,
10864             XmNchildHorizontalAlignment, XmALIGNMENT_BEGINNING,
10865             NULL);
10866       SUMA_Register_Widget_Help( www , 0,
10867                                  "VolCont->Slice_Controls",
10868                              "Set up which and how many slices are displayed",
10869                   ":SPX:\n\n"
10870                   ".. figure:: media/VolCont.auto.Slice_Controls.jpg\n"
10871                   "   :align: right\n"
10872                   "   :name: media/VolCont.auto.Slice_Controls.jpg\n"
10873                   "\n"
10874                   "   :ref:`(link)<media/VolCont.auto.Slice_Controls.jpg>`\n"
10875                   "\n"
10876                   ":SPX:") ;
10877 
10878       /* vertical row column */
10879       rcv = XtVaCreateWidget ("rowcolumn",
10880             xmRowColumnWidgetClass, SurfCont->Slice_fr,
10881             XmNpacking, XmPACK_TIGHT,
10882             XmNorientation , XmVERTICAL ,
10883             XmNmarginHeight, 0 ,
10884             XmNmarginWidth , 0 ,
10885             NULL);
10886 
10887       /* Slice toys */
10888       SUMA_CreateSliceFields( rcv, "Ax",
10889                   SUMA_SliceSelect_axial_hint, SUMA_SliceSelect_axial_help,
10890                   SUMA_VO_N_Slices((SUMA_VolumeObject *)ado, "Ax"), "Ax", ado,
10891                            NULL, (void *)ado,
10892                            SurfCont->Ax_slc);
10893       SUMA_CreateSliceFields( rcv, "Sa",
10894                   SUMA_SliceSelect_sagittal_hint, SUMA_SliceSelect_sagittal_help,
10895                   SUMA_VO_N_Slices((SUMA_VolumeObject *)ado, "Sa"), "Sa", ado,
10896                            NULL, (void *)ado,
10897                            SurfCont->Sa_slc);
10898       SUMA_CreateSliceFields( rcv, "Co",
10899                   SUMA_SliceSelect_coronal_hint, SUMA_SliceSelect_coronal_help,
10900                   SUMA_VO_N_Slices((SUMA_VolumeObject *)ado, "Co"), "Co", ado,
10901                            NULL, (void *)ado,
10902                            SurfCont->Co_slc);
10903 
10904       rch = XtVaCreateWidget ("rowcolumn",
10905             xmRowColumnWidgetClass, rcv,
10906             XmNpacking, XmPACK_TIGHT,
10907             XmNorientation , XmHORIZONTAL ,
10908             XmNmarginHeight, 0 ,
10909             XmNmarginWidth , 0 ,
10910             NULL);
10911       SUMA_BuildMenuReset(0);
10912       SurfCont->VTransModeMenu = SUMA_Alloc_Menu_Widget(SW_N_SurfCont_ATrans);
10913       SUMA_BuildMenu (  rch, XmMENU_OPTION,
10914                         "Trn", '\0', YUP, VTransMode_Menu,
10915                         (void *)SUMA_SurfCont_GetcurDOp(SurfCont),
10916                         "VolCont->Slice_Controls->Trn",
10917                         "Choose the transparency for these slices.",
10918                         SUMA_SurfContHelp_VTransMode,
10919                         SurfCont->VTransModeMenu );
10920       XtManageChild (SurfCont->VTransModeMenu->mw[SW_SurfCont_ATrans]);
10921 
10922       /* Now for the toggle button */
10923       SurfCont->VSliceAtXYZ_tb = XtVaCreateManagedWidget("Slices At +",
10924                         xmToggleButtonWidgetClass, rch, NULL);
10925       XtAddCallback (SurfCont->VSliceAtXYZ_tb,
10926                   XmNvalueChangedCallback, SUMA_cb_VSliceAtXYZ_toggled, ado);
10927       SUMA_Register_Widget_Help(SurfCont->VSliceAtXYZ_tb, 1,
10928                                 "VolCont->Slice_Controls->Slices_At_+",
10929                                 "Make slices jump to crosshair location",
10930                                 "Make slices jump to crosshair location");
10931 
10932       SUMA_SET_SELECT_COLOR(SurfCont->VSliceAtXYZ_tb);
10933       XmToggleButtonSetState (SurfCont->VSliceAtXYZ_tb,
10934                   SUMA_VO_SlicesAtCrosshair((SUMA_VolumeObject *)ado) , NOPE);
10935 
10936       XtManageChild (rch);
10937       XtManageChild (rcv);
10938       XtManageChild (SurfCont->Slice_fr);
10939    }
10940 
10941    SUMA_LH("Volume Rendering Controls");
10942    {
10943       Widget rc, rcv, pb, www;
10944 
10945       /* put a frame */
10946       SurfCont->VR_fr = XtVaCreateWidget ("dialog",
10947          xmFrameWidgetClass, rc_left,
10948          XmNshadowType , XmSHADOW_ETCHED_IN ,
10949          XmNshadowThickness , 5 ,
10950          XmNtraversalOn , False ,
10951          NULL);
10952 
10953       www = XtVaCreateManagedWidget ("Volume Rendering Controls",
10954             xmLabelWidgetClass, SurfCont->VR_fr,
10955             XmNchildType, XmFRAME_TITLE_CHILD,
10956             XmNchildHorizontalAlignment, XmALIGNMENT_BEGINNING,
10957             NULL);
10958       SUMA_Register_Widget_Help(www, 0,
10959                                 "VolCont->Volume_Rendering_Controls",
10960                                 "Set the parameters for 3D rendering",
10961          ":SPX:\n\n"
10962          ".. figure:: media/VolCont.auto.Volume_Rendering_Controls.jpg\n"
10963          "   :align: right\n"
10964          "   :name: media/VolCont.auto.Volume_Rendering_Controls.jpg\n"
10965          "\n"
10966          "   :ref:`(link)<media/VolCont.auto.Volume_Rendering_Controls.jpg>`\n"
10967          "\n"
10968                ":SPX:"      );
10969       /* vertical row column */
10970       rcv = XtVaCreateWidget ("rowcolumn",
10971             xmRowColumnWidgetClass, SurfCont->VR_fr,
10972             XmNpacking, XmPACK_TIGHT,
10973             XmNorientation , XmVERTICAL ,
10974             XmNmarginHeight, 0 ,
10975             XmNmarginWidth , 0 ,
10976             NULL);
10977 
10978       /* Slice toys */
10979       SUMA_CreateVrFields( rcv,  "Ns",
10980                   SUMA_VR_hint, SUMA_VR_help,
10981                   SUMA_VO_N_Slices((SUMA_VolumeObject *)ado, "Mx"),  ado,
10982                            NULL, (void *)ado,
10983                            SurfCont->VR_fld);
10984       XtManageChild(rcv);
10985       XtManageChild (SurfCont->VR_fr);
10986    }
10987 
10988    SUMA_LH("Dset Controls");
10989    /* Dset Controls */
10990    {
10991        Widget rc, rcv, pb, www;
10992 
10993       /* put a frame */
10994       SurfCont->ColPlane_fr = XtVaCreateWidget ("dialog",
10995          xmFrameWidgetClass, rc_left,
10996          XmNshadowType , XmSHADOW_ETCHED_IN ,
10997          XmNshadowThickness , 5 ,
10998          XmNtraversalOn , False ,
10999          NULL);
11000 
11001       www = XtVaCreateManagedWidget ("Dset Controls",
11002             xmLabelWidgetClass, SurfCont->ColPlane_fr,
11003             XmNchildType, XmFRAME_TITLE_CHILD,
11004             XmNchildHorizontalAlignment, XmALIGNMENT_BEGINNING,
11005             NULL);
11006       SUMA_Register_Widget_Help( www , 0,
11007                                  "VolCont->Dset_Controls",
11008                                  "Dset Controls",
11009                   ":SPX:\n\n"
11010                   ".. figure:: media/VolCont.auto.Dset_Controls.jpg\n"
11011                   "   :align: right\n"
11012                   "   :name: media/VolCont.auto.Dset_Controls.jpg\n"
11013                   "\n"
11014                   "   :ref:`(link)<media/VolCont.auto.Dset_Controls.jpg>`\n"
11015                   "\n"
11016                   ":SPX:") ;
11017 
11018       /* vertical row column */
11019       rcv = XtVaCreateWidget ("rowcolumn",
11020             xmRowColumnWidgetClass, SurfCont->ColPlane_fr,
11021             XmNpacking, XmPACK_TIGHT,
11022             XmNorientation , XmVERTICAL ,
11023             XmNmarginHeight, 0 ,
11024             XmNmarginWidth , 0 ,
11025             NULL);
11026 
11027       /* row column for label*/
11028       rc = XtVaCreateWidget ("rowcolumn",
11029             xmRowColumnWidgetClass, rcv,
11030             XmNpacking, XmPACK_TIGHT,
11031             XmNorientation , XmHORIZONTAL ,
11032             XmNmarginHeight, 0 ,
11033             XmNmarginWidth , 0 ,
11034             NULL);
11035 
11036       /*put a label containing the surface name,
11037          number of nodes and number of facesets */
11038       {
11039          char *Dset_tit[]  =  {  "Lbl", NULL };
11040          char *Dset_hint[] =  {  "Label of Volume Dset",  NULL };
11041          char *Dset_help[] =  {  SUMA_SurfContHelp_DsetLblTblr0, NULL };
11042          int colw[]={ 3, 27};
11043          SUMA_CreateTable(rc,
11044             1, 2,
11045             "VolCont->Dset_Controls->Lbl",
11046             Dset_tit, NULL,
11047             Dset_hint, NULL,
11048             Dset_help, NULL,
11049             colw, NOPE, SUMA_string,
11050             NULL, NULL,
11051             NULL, NULL,
11052             NULL, NULL,
11053             SurfCont->ColPlaneLabelTable);
11054       }
11055       XtManageChild (rc);
11056 
11057       /* add a rc for the colorplane brightness and perhaps visibility? */
11058       rc = XtVaCreateWidget ("rowcolumn",
11059          xmRowColumnWidgetClass, rcv,
11060          XmNpacking, XmPACK_TIGHT,
11061          XmNorientation , XmHORIZONTAL ,
11062          NULL);
11063 
11064       SUMA_CreateArrowField ( rc, "Dim",
11065                            1, 0.1, 2, 0.1,
11066                            3, SUMA_float,
11067                            YUP,
11068                            SUMA_cb_ColPlane_NewDimFact, (void *)ado,
11069                            "VolCont->Dset_Controls->Dim",
11070                            SUMA_SurfCont_ColPlaneDim_hint,
11071                            SUMA_SurfContHelp_DsetDim,
11072                            SurfCont->ColPlaneDimFact);
11073 
11074       #if 0 /* Nothing for this yet */
11075       SUMA_CreateArrowField ( rc, "Ord",
11076                            1, 0, 20, 1,
11077                            2, SUMA_int,
11078                            NOPE,
11079                            SUMA_cb_ColPlane_NewOrder, (void *)ado,
11080                            "VolCont->Dset_Controls->Ord",
11081                            SUMA_SurfCont_ColPlaneOrder_hint,
11082                            SUMA_SurfContHelp_DsetOrd,
11083                            SurfCont->ColPlaneOrder);
11084       #endif
11085 
11086       /* manage  rc */
11087       XtManageChild (rc);
11088 
11089       /* another row*/
11090       rc = XtVaCreateWidget ("rowcolumn",
11091          xmRowColumnWidgetClass, rcv,
11092          XmNpacking, XmPACK_TIGHT,
11093          XmNorientation , XmHORIZONTAL ,
11094          NULL);
11095 
11096       SUMA_BuildMenuReset(0);
11097       SurfCont->DsetAlphaValMenu =
11098          SUMA_Alloc_Menu_Widget(SW_N_SurfCont_DsetAlphaVal);
11099       SUMA_BuildMenu (rc, XmMENU_OPTION,
11100                 "Avl", '\0', YUP, DsetAlphaVal_Menu,
11101                 (void *)SUMA_SurfCont_GetcurDOp(SurfCont),
11102                 "VolCont->Dset_Controls->Avl",
11103                 "Choose method for computing color alpha value for voxels.",
11104                 SUMA_SurfContHelp_DsetAlphaVal,
11105                 SurfCont->DsetAlphaValMenu );
11106       XtManageChild (SurfCont->DsetAlphaValMenu->mw[SW_SurfCont_DsetAlphaVal]);
11107 
11108       SUMA_CreateArrowField ( rc, "Ath",
11109                            1, 0.0, 1, 0.1,
11110                            3, SUMA_float,
11111                            YUP,
11112                            SUMA_cb_ColPlane_NewAlphaThresh, (void *)ado,
11113                            "VolCont->Dset_Controls->Ath",
11114                            SUMA_SurfCont_ColPlaneAlphaThresh_hint,
11115                            SUMA_SurfContHelp_DsetAlphaThresh,
11116                            SurfCont->ColPlaneAlphaThresh);
11117 
11118 
11119       #if 0  /* Not ready for this yet, no multiple vols used */
11120       SurfCont->ColPlaneShowOneFore_tb =
11121          XtVaCreateManagedWidget("1",
11122                                  xmToggleButtonWidgetClass, rc, NULL);
11123       XmToggleButtonSetState (SurfCont->ColPlaneShowOneFore_tb,
11124                               SurfCont->ShowCurForeOnly, NOPE);
11125       XtAddCallback (SurfCont->ColPlaneShowOneFore_tb,
11126                      XmNvalueChangedCallback,
11127                      SUMA_cb_ColPlaneShowOneFore_toggled, ado);
11128 
11129       SUMA_Register_Widget_Help(SurfCont->ColPlaneShowOneFore_tb ,  1,
11130                                 "VolCont->Dset_Controls->1",
11131              "Show ONLY selected set. Foreground only. (BHelp for more)\n",
11132                                 SUMA_SurfContHelp_DsetViewOne ) ;
11133       SUMA_SET_SELECT_COLOR(SurfCont->ColPlaneShowOneFore_tb);
11134       #endif
11135 
11136       XtManageChild (rc);
11137 
11138       #if 0 /* Nothing for these yet */
11139       SUMA_BuildMenuReset(0);
11140       SUMA_CreateArrowField ( rc, "Opa",
11141                            1, 0.0, 1.0, 0.1,
11142                            3, SUMA_float,
11143                            NOPE,
11144                            SUMA_cb_ColPlane_NewOpacity, (void *)ado,
11145                            "VolCont->Dset_Controls->Opa",
11146                            SUMA_SurfCont_ColPlaneOpacity_hint,
11147                            SUMA_SurfContHelp_DsetOpa,
11148                            SurfCont->ColPlaneOpacity);
11149 
11150 
11151 
11152       XtVaCreateManagedWidget (  "sep",
11153                                  xmSeparatorWidgetClass, rcv,
11154                                  XmNorientation, XmHORIZONTAL,NULL);
11155 
11156       /* row column for Switch, Load, Delete */
11157       rc = XtVaCreateWidget ("rowcolumn",
11158          xmRowColumnWidgetClass, rcv,
11159          XmNpacking, XmPACK_TIGHT,
11160          XmNorientation , XmHORIZONTAL ,
11161          NULL);
11162 
11163       /* put a push button to switch between color planes */
11164       SurfCont->SwitchDsetlst =
11165             SUMA_AllocateScrolledList ("Switch Dset",
11166                      SUMA_LSP_SINGLE,
11167                      NOPE, NOPE, /* duplicate deletion, no sorting */
11168                      SurfCont->TLS, SWP_POINTER,
11169                      125,
11170                      SUMA_cb_SelectSwitchColPlane, (void *)ado,
11171                      SUMA_cb_SelectSwitchColPlane, (void *)ado,
11172                      SUMA_cb_CloseSwitchColPlane, NULL);
11173 
11174 
11175       pb = XtVaCreateWidget ("Switch Dset",
11176          xmPushButtonWidgetClass, rc,
11177          NULL);
11178       XtAddCallback (pb, XmNactivateCallback,
11179                      SUMA_cb_SurfCont_SwitchColPlane, (XtPointer)ado);
11180       SUMA_Register_Widget_Help(pb, 1,
11181                                 "VolCont->Dset_Controls->Switch_Dset",
11182                                 "Switch between datasets",
11183                                 SUMA_SurfContHelp_DsetSwitch ) ;
11184       XtManageChild (pb);
11185 
11186       pb = XtVaCreateWidget ("Load Dset",
11187             xmPushButtonWidgetClass, rc,
11188             NULL);
11189       XtAddCallback (pb, XmNactivateCallback,
11190                      SUMA_cb_Dset_Load, (XtPointer) ado);
11191       SUMA_Register_Widget_Help(pb, 1,
11192                                 "VolCont->Dset_Controls->Load_Dset",
11193                                 "Load a new dataset (much more with BHelp)",
11194                                 SUMA_SurfContHelp_DsetLoad ) ;
11195       XtManageChild (pb);
11196 
11197       pb = XtVaCreateWidget ("Delete",
11198          xmPushButtonWidgetClass, rc,
11199          NULL);
11200       XtAddCallback (pb, XmNactivateCallback,
11201                      SUMA_cb_ColPlane_Delete, (XtPointer) ado);
11202       /* XtManageChild (pb); */ /* Not ready for this one yet */
11203 
11204       XtManageChild (rc);
11205       #endif /* Nothing for switching or loading Dsets now ... */
11206 
11207       /* manage vertical row column */
11208       XtManageChild (rcv);
11209 
11210       XtManageChild (SurfCont->ColPlane_fr);
11211    }
11212 
11213 
11214 
11215    if (SUMAg_CF->X->UseSameSurfCont) {
11216       Widget rc=NULL;
11217       /* put something to cycle through objects */
11218       if ((rc = SUMA_FindChildWidgetNamed(SurfCont->DispFrame, "rowcolumnCBF"))){
11219          XtVaCreateManagedWidget (  "sep",
11220                               xmSeparatorWidgetClass, rc,
11221                               XmNorientation, XmVERTICAL,NULL);
11222          pb = XtVaCreateWidget ("All Objs.",
11223                   xmPushButtonWidgetClass, rc,
11224                   NULL);
11225          XtAddCallback (pb, XmNactivateCallback,
11226                         SUMA_cb_AllConts, NULL);
11227          SUMA_Register_Widget_Help(pb, 1, "VolCont->Disp_Cont->AllObjs",
11228                                 "Initialize Controllers for All Objects",
11229                                 SUMA_SurfContHelp_AllObjs) ;
11230          XtManageChild (pb);
11231 
11232          SUMA_CreateArrowField ( rc, "Switch",
11233                            1, 1, 20, 1,
11234                            2, SUMA_int,
11235                            YUP,
11236                            SUMA_cb_SurfCont_SwitchPage, (void *)ado,
11237                            "VolCont->Disp_Cont->Switch",
11238                            "Switch to other object controller",
11239                            SUMA_Switch_Cont_BHelp,
11240                            SurfCont->SurfContPage);
11241          xmstmp = XmStringCreateLtoR (SUMA_ADO_CropLabel(ado,
11242                                        SUMA_SURF_CONT_SWITCH_LABEL_LENGTH),
11243                                       XmSTRING_DEFAULT_CHARSET);
11244          SurfCont->SurfContPage_label = XtVaCreateManagedWidget ("dingel-6",
11245                xmLabelWidgetClass, rc,
11246                XmNlabelString, xmstmp,
11247                NULL);
11248          XmStringFree (xmstmp);
11249       }
11250    }
11251 
11252    SUMA_LHv("Management ...%p %p %p %p %p\n",
11253             rc_right, rc_left, rc_mamma, SurfCont->Mainform, SurfCont->Page);
11254 
11255    XtManageChild (rc_right);
11256    XtManageChild (rc_left);
11257    XtManageChild (rc_mamma);
11258    XtManageChild (rc_gmamma);
11259    XtManageChild (SurfCont->Mainform);
11260    if (SUMAg_CF->X->UseSameSurfCont) XtManageChild (SurfCont->Page);
11261 
11262 
11263    SUMA_LH("Popup maybe and Notebook management");
11264    #if SUMA_CONTROLLER_AS_DIALOG
11265    #else
11266    /** Feb 03/03: pop it up if it is a topLevelShellWidgetClass,
11267    you should do the popping after all the widgets have been created.
11268    Otherwise, the window does not size itself correctly when open */
11269    XtPopup(SurfCont->TLS, XtGrabNone);
11270    #endif
11271 
11272    /* realize the widget */
11273    if (SUMAg_CF->X->UseSameSurfCont) {
11274       XtManageChild (SUMAg_CF->X->SC_Notebook);
11275    }
11276    SUMA_LH("Realize TLS widget %p, closed %d",
11277             SurfCont->TLS, !SUMAg_CF->X->SameSurfContOpen);
11278    XtRealizeWidget (SurfCont->TLS);
11279 
11280    SUMA_LH("%s",slabel);
11281    SUMA_free (slabel);
11282 
11283 
11284    /* initialize the left side
11285       (no need here, that's done in SUMA_cb_viewSurfaceCont)*/
11286    /* SUMA_Init_SurfCont_SurfParam(ado); */
11287 
11288    /* initialize the ColorPlane frame if possible
11289    Do it here rather than above because scale goes crazy
11290    when parent widgets are being resized*/
11291 
11292    if (SUMA_ADO_N_Overlays(ado)>0) {
11293       SUMA_LH("Initializing ColPlaneShell");
11294       SUMA_InitializeColPlaneShell(ado, curColPlane);
11295       #ifdef NONONO /* It looks like I do not need this anymore
11296                        Used to be #idef DARWIN */
11297       /* Sometimes color maps do not show up on mac when you first
11298          open the surface controller */
11299       SUMA_LH("Darwining");
11300       SUMA_SwitchColPlaneCmap(ado, SUMA_CmapOfPlane(curColPlane));
11301       #endif
11302    } else {
11303       SUMA_LH("No overlays to work with");
11304    }
11305 
11306    #if USING_LESSTIF
11307    SUMA_LH("Less tif fix");
11308    /* A quick fix to ensure Dset_Mapping
11309       gets displayed properly the first time */
11310    SUMA_cb_ToggleManagementColPlaneWidget(NULL, (XtPointer)(&ado), NULL);
11311    SUMA_cb_ToggleManagementColPlaneWidget(NULL, (XtPointer)(&ado), NULL);
11312    #endif
11313 
11314    SUMA_LH("going home.");
11315 
11316    SUMA_MarkSurfContOpen(1, ado);
11317    SUMA_LHv("Marked %s's controller as open.\n", SUMA_ADO_Label(ado));
11318 
11319    SUMA_RETURNe;
11320 }
11321 
11322 /*!
11323    \brief close surface controller, expects SO in data
11324 */
SUMA_cb_closeSurfaceCont(Widget w,XtPointer data,XtPointer callData)11325 void SUMA_cb_closeSurfaceCont(Widget w, XtPointer data, XtPointer callData)
11326 {
11327    static char FuncName[] = {"SUMA_cb_closeSurfaceCont"};
11328    SUMA_ALL_DO *ado;
11329    SUMA_X_SurfCont *SurfCont=NULL;
11330    SUMA_Boolean LocalHead = NOPE;
11331 
11332    SUMA_ENTRY;
11333 
11334    ado = (SUMA_ALL_DO *)data;
11335    SurfCont = SUMA_ADO_Cont(ado);
11336    SUMA_LHv("Have TLS %p Open %d Same %d SameOpen %d\n",
11337             SurfCont->TLS, SurfCont->Open,
11338             SUMAg_CF->X->UseSameSurfCont, SUMAg_CF->X->SameSurfContOpen)
11339    if (!SurfCont->TLS || !SurfCont->Open ||
11340        (SUMAg_CF->X->UseSameSurfCont && !SUMAg_CF->X->SameSurfContOpen) )
11341       SUMA_RETURNe;
11342 
11343    switch (SUMA_GL_CLOSE_MODE)   {/* No open GL drawables in this widget*/
11344       case SUMA_WITHDRAW:
11345          if (LocalHead)
11346             fprintf (SUMA_STDERR,
11347                      "%s: Withdrawing Surface Controller...\n", FuncName);
11348          XWithdrawWindow(SUMAg_CF->X->DPY_controller1,
11349             XtWindow(SurfCont->TLS),
11350             XScreenNumberOfScreen(XtScreen(SurfCont->TLS)));
11351          break;
11352       case SUMA_DESTROY:
11353          if (LocalHead)
11354             fprintf (SUMA_STDERR,
11355                      "%s: Destroying Surface Controller...\n", FuncName);
11356          if (!SUMAg_CF->X->CommonSurfContTLW) { /* not in common mode */
11357                XtDestroyWidget(SurfCont->TLS);
11358          }
11359          SurfCont->TLS = NULL;
11360          break;
11361       case SUMA_UNREALIZE:
11362          if (LocalHead)
11363             fprintf (SUMA_STDERR,
11364                      "%s: Unrealizing Surface Controller...\n", FuncName);
11365          XtUnrealizeWidget(SurfCont->TLS);
11366          break;
11367       default:
11368          SUMA_S_Err("Not set up to deal with this closure mode");
11369          SUMA_RETURNe;
11370          break;
11371    }
11372 
11373    SUMA_MarkSurfContOpen(0,ado);
11374    SUMA_RETURNe;
11375 }
11376 
11377 /*!
11378    Find number for page widget in notebook
11379    0 for bad news
11380 */
SUMA_PageWidgetToNumber(Widget NB,Widget page)11381 int SUMA_PageWidgetToNumber(Widget NB, Widget page)
11382 {
11383    static char FuncName[]={"SUMA_PageWidgetToNumber"};
11384    int i, lp;
11385    XmNotebookPageStatus ns;
11386    XmNotebookPageInfo pi;
11387    SUMA_Boolean LocalHead = NOPE;
11388 
11389    SUMA_ENTRY;
11390 
11391    if (!NB || !page) SUMA_RETURN(0);
11392 
11393    XtVaGetValues(NB, XmNlastPageNumber, &lp, NULL);
11394    for (i=0; i<lp; ++i) {
11395       ns = XmNotebookGetPageInfo(NB, i+1, &pi);
11396       if (ns != XmPAGE_FOUND) {
11397          SUMA_LH("Could not find page!");
11398          SUMA_RETURN(0);
11399       }
11400       SUMA_LHv("Page %d, widget %p, have page %p, match=%d, "
11401                    "page name=%s\n",
11402                    i+1, pi.page_widget, page,
11403                    (pi.page_widget==page)?1:0,
11404                    XtName(pi.page_widget));
11405       if (pi.page_widget==page) SUMA_RETURN(i+1);
11406    }
11407    SUMA_RETURN(0);
11408 }
11409 
SUMA_isCurrentContPage(Widget NB,Widget page)11410 int SUMA_isCurrentContPage(Widget NB, Widget page)
11411 {
11412    static char FuncName[]={"SUMA_isCurrentContPage"};
11413    int lp;
11414    XmNotebookPageStatus ns;
11415    XmNotebookPageInfo pi;
11416    SUMA_Boolean LocalHead = NOPE;
11417 
11418    SUMA_ENTRY;
11419 
11420    if (!NB) SUMA_RETURN(0);
11421 
11422    XtVaGetValues(NB, XmNcurrentPageNumber, &lp, NULL);
11423    ns = XmNotebookGetPageInfo(NB, lp, &pi);
11424    if (ns != XmPAGE_FOUND) {
11425          SUMA_LH("Could not find current page!");
11426          SUMA_RETURN(0);
11427    }
11428    if (pi.page_widget==page) SUMA_RETURN(1);
11429    SUMA_RETURN(0);
11430 }
11431 
11432 /*!
11433    \brief updates the left side of Surface Controller
11434 */
SUMA_Init_SurfCont_SurfParam(SUMA_ALL_DO * ado)11435 SUMA_Boolean SUMA_Init_SurfCont_SurfParam(SUMA_ALL_DO *ado)
11436 {
11437    static char FuncName[]={"SUMA_Init_SurfCont_SurfParam"};
11438 
11439    SUMA_ENTRY;
11440 
11441    if (!ado) SUMA_RETURN(NOPE);
11442 
11443    switch (ado->do_type) {
11444       case SO_type:
11445          SUMA_RETURN(SUMA_Init_SurfCont_SurfParam_SO((SUMA_SurfaceObject *)ado));
11446          break;
11447       case CDOM_type:
11448          SUMA_RETURN(SUMA_Init_SurfCont_SurfParam_CO(ado));
11449          break;
11450       case GDSET_type:
11451          SUMA_S_Err("Should not send me DOs that can't be displayed \n"
11452                     "without variant info");
11453          SUMA_RETURN(NOPE);
11454          break;
11455       case GRAPH_LINK_type: {
11456          SUMA_GraphLinkDO *gldo=(SUMA_GraphLinkDO *)ado;
11457          SUMA_DSET *dset=NULL;
11458          if (!(dset=SUMA_find_GLDO_Dset(gldo))) {
11459             SUMA_S_Errv("Failed to find dset for gldo %s!!!\n",
11460                         SUMA_ADO_Label(ado));
11461             SUMA_RETURN(NOPE);
11462          }
11463          SUMA_RETURN(SUMA_Init_SurfCont_SurfParam_GLDO(ado));
11464          break; }
11465       case TRACT_type: {
11466          SUMA_RETURN(SUMA_Init_SurfCont_SurfParam_TDO(ado));
11467          break; }
11468       case MASK_type: {
11469          SUMA_RETURN(SUMA_Init_SurfCont_SurfParam_MDO(ado));
11470          break; }
11471       case VO_type: {
11472          SUMA_RETURN(SUMA_Init_SurfCont_SurfParam_VO(ado));
11473          break; }
11474       default:
11475          SUMA_S_Errv("Rien de rien for %s\n",
11476             SUMA_ObjectTypeCode2ObjectTypeName(ado->do_type));
11477          break;
11478    }
11479    SUMA_RETURN(NOPE);
11480 }
11481 
SUMA_Init_SurfCont_SurfParam_SO(SUMA_SurfaceObject * SO)11482 SUMA_Boolean SUMA_Init_SurfCont_SurfParam_SO(SUMA_SurfaceObject *SO)
11483 {
11484    static char FuncName[]={"SUMA_Init_SurfCont_SurfParam_SO"};
11485    char *slabel = NULL, *Name, *lbl30 = NULL;
11486    int i, imenu;
11487    Widget *w=NULL, whist=NULL;
11488    XmString string;
11489    SUMA_SurfaceObject *oSO;
11490    SUMA_ALL_DO *oado=NULL;
11491    SUMA_Boolean SameSurface = NOPE;
11492    SUMA_Boolean LocalHead = NOPE;
11493 
11494    SUMA_ENTRY;
11495 
11496    if (!(oado = SUMA_SurfCont_GetcurDOp(SO->SurfCont))) {
11497       SUMA_S_Err("Failed to retrieve DO");
11498       SUMA_RETURN(NOPE);
11499    }
11500    if (oado->do_type != SO_type) {
11501       SUMA_S_Err("Did not expect type mismatch here.");
11502       SUMA_RETURN(NOPE);
11503    } else {
11504       oSO = (SUMA_SurfaceObject *)oado;
11505    }
11506    if (oSO == SO) {
11507       SameSurface = YUP;
11508    } else {
11509       SameSurface = NOPE;
11510    }
11511 
11512    SUMA_LHv("Called for %s, current %s, buttdown = %d\n",
11513             SO->Label, oSO->Label, SUMAg_CF->X->ButtonDown);
11514    /* set the new current surface pointer */
11515    if (!SUMA_SurfCont_SetcurDOp(SO->SurfCont, (SUMA_ALL_DO *)SO)) {
11516       SUMA_S_Err("Failed to set current pointer");
11517       SUMA_RETURN(NOPE);
11518    }
11519    if (!SameSurface ||
11520        ( SUMAg_CF->X->UseSameSurfCont &&
11521          !SUMA_isCurrentContPage(SUMAg_CF->X->SC_Notebook,
11522                                  SO->SurfCont->Page))) {
11523       /* initialize the title of the window */
11524       slabel = (char *)SUMA_malloc (sizeof(char) * (strlen(SO->Label) + 100));
11525       if (strlen(SO->Label) > 40) {
11526          char *tmpstr=NULL;
11527          tmpstr = SUMA_truncate_string(SO->Label, 40);
11528          if (tmpstr) {
11529             sprintf(slabel,"[%s] Surface Controller", tmpstr);
11530             free(tmpstr); tmpstr=NULL;
11531          }
11532       } else {
11533          sprintf(slabel,"[%s] Surface Controller", SO->Label);
11534       }
11535       SUMA_LH("Setting title");
11536       XtVaSetValues(SO->SurfCont->TLS, XtNtitle, slabel, NULL);
11537 
11538       /* initialize the string before the more button */
11539          /*put a label containing the surface name, number of nodes
11540             and number of facesets */
11541          lbl30 = SUMA_set_string_length(SO->Label, ' ', 27);
11542          if (lbl30) {
11543             sprintf( slabel,"%s\n%d nodes: %d tri.",
11544                      lbl30, SO->N_Node, SO->N_FaceSet);
11545             SUMA_free(lbl30); lbl30 = NULL;
11546          } else {
11547             sprintf(slabel,"???\n%d nodes: %d tri.", SO->N_Node, SO->N_FaceSet);
11548          }
11549          SUMA_LHv("Setting label to\n>>%s<<\n", slabel);
11550          string = XmStringCreateLtoR (slabel, XmSTRING_DEFAULT_CHARSET);
11551          XtVaSetValues( SO->SurfCont->SurfInfo_label,
11552                         XmNlabelString, string, NULL);
11553          XmStringFree (string);
11554 
11555       if (slabel) SUMA_free(slabel); slabel = NULL;
11556       /* Can't do much with the SurfInfo button,
11557       You can only have on Info shell/LocalDomainParent
11558       at a time */
11559 
11560       SUMA_LH("Setting RenderMode");
11561       /* set the correct RenderMode for that surface */
11562       imenu = -1;
11563       switch (SO->PolyMode) {
11564          case SRM_ViewerDefault:
11565             imenu = SW_SurfCont_RenderViewerDefault;
11566             break;
11567          case SRM_Fill:
11568             imenu = SW_SurfCont_RenderFill;
11569             break;
11570          case SRM_Line:
11571             imenu = SW_SurfCont_RenderLine;
11572             break;
11573          case SRM_Points:
11574             imenu = SW_SurfCont_RenderPoints;
11575             break;
11576          case SRM_Hide:
11577             imenu = SW_SurfCont_RenderHide;
11578             break;
11579          default:
11580             fprintf (SUMA_STDERR, "Error %s: Unexpected something.\n", FuncName);
11581             break;
11582       }
11583       /* look for name of widget with imenu for call data.
11584          This is overkill but its fun */
11585       i = 0;
11586       Name = NULL;
11587       while (&(RenderMode_Menu[i])) {
11588          if ((INT_CAST)RenderMode_Menu[i].callback_data == imenu) {
11589             Name = RenderMode_Menu[i].label;
11590             if (LocalHead) fprintf (SUMA_STDERR,"Looking for %s\n", Name);
11591             /* now we know what the name of the button needed is, look for it*/
11592             w = SO->SurfCont->RenderModeMenu->mw;
11593             for (i=0; i< SW_N_SurfCont_Render; ++i) {
11594                if (LocalHead) fprintf (SUMA_STDERR,"I have %s\n", XtName(w[i]));
11595                if (strcmp(Name, XtName(w[i])) == 0) {
11596                   SUMA_LH("Match!");
11597                   XtVaSetValues(  w[0], XmNmenuHistory , w[i] , NULL ) ;
11598                   goto RAISE;
11599               }
11600             }
11601          }
11602          ++i;
11603       }
11604 
11605       SUMA_LH("Setting TransMode");
11606       /* set the transparency for that surface */
11607       imenu = -1;
11608       switch (SO->TransMode) {
11609          case STM_ViewerDefault:
11610             imenu = SW_SurfCont_TransViewerDefault;
11611             break;
11612          case STM_0:
11613             imenu = SW_SurfCont_Trans0;
11614             break;
11615          case STM_1:
11616             imenu = SW_SurfCont_Trans1;
11617             break;
11618          case STM_2:
11619             imenu = SW_SurfCont_Trans2;
11620             break;
11621          case STM_3:
11622             imenu = SW_SurfCont_Trans3;
11623             break;
11624          case STM_4:
11625             imenu = SW_SurfCont_Trans4;
11626             break;
11627          case STM_5:
11628             imenu = SW_SurfCont_Trans5;
11629             break;
11630          case STM_6:
11631             imenu = SW_SurfCont_Trans6;
11632             break;
11633          case STM_7:
11634             imenu = SW_SurfCont_Trans7;
11635             break;
11636          case STM_8:
11637             imenu = SW_SurfCont_Trans8;
11638             break;
11639          case STM_9:
11640             imenu = SW_SurfCont_Trans9;
11641             break;
11642          case STM_10:
11643             imenu = SW_SurfCont_Trans10;
11644             break;
11645          case STM_11:
11646             imenu = SW_SurfCont_Trans11;
11647             break;
11648          case STM_12:
11649             imenu = SW_SurfCont_Trans12;
11650             break;
11651          case STM_13:
11652             imenu = SW_SurfCont_Trans13;
11653             break;
11654          case STM_14:
11655             imenu = SW_SurfCont_Trans14;
11656             break;
11657          case STM_15:
11658             imenu = SW_SurfCont_Trans15;
11659             break;
11660          case STM_16:
11661             imenu = SW_SurfCont_Trans16;
11662             break;
11663          default:
11664             fprintf (SUMA_STDERR, "Error %s: Unexpected something.\n", FuncName);
11665             break;
11666       }
11667       /* look for name of widget with imenu for call data.
11668          This is overkill but its fun */
11669       i = 0;
11670       Name = NULL;
11671       while (&(TransMode_Menu[i])) {
11672          if ((INT_CAST)TransMode_Menu[i].callback_data == imenu) {
11673             Name = TransMode_Menu[i].label;
11674             if (LocalHead) fprintf (SUMA_STDERR,"Looking for %s\n", Name);
11675             /* now we know what the name of the button needed is, look for it*/
11676             w = SO->SurfCont->TransModeMenu->mw;
11677             for (i=0; i< SW_N_SurfCont_Trans; ++i) {
11678                if (LocalHead) fprintf (SUMA_STDERR,"I have %s\n", XtName(w[i]));
11679                if (strcmp(Name, XtName(w[i])) == 0) {
11680                   SUMA_LH("Match!");
11681                   XtVaSetValues(  w[0], XmNmenuHistory , w[i] , NULL ) ;
11682                   goto RAISE;
11683               }
11684             }
11685          }
11686          ++i;
11687       }
11688 
11689       RAISE:
11690       if (SUMAg_CF->X->UseSameSurfCont) {
11691          if (!(i = SUMA_PageWidgetToNumber(SUMAg_CF->X->SC_Notebook,
11692                                           SO->SurfCont->Page))) {
11693             SUMA_S_Errv("Failed to find controller page for surface %s\n",
11694                         CHECK_NULL_STR(SO->Label));
11695          } else {
11696             SUMA_LHv("Setting notebook page to page %d, button down is %d\n",
11697                      i,SUMAg_CF->X->ButtonDown);
11698             if (LocalHead) SUMA_DUMP_TRACE("You rang?");
11699             if (!SUMAg_CF->X->ButtonDown) {
11700                SUMA_SetSurfContPageNumber(SUMAg_CF->X->SC_Notebook, i);
11701             }
11702          }
11703       }
11704    }
11705 
11706    /* do even if this is the old surface */
11707 
11708    SUMA_RETURN(YUP);
11709 }
11710 
SUMA_NotebookLastPageNumber(Widget NB)11711 int SUMA_NotebookLastPageNumber(Widget NB)
11712 {
11713    static char FuncName[]={"SUMA_NotebookLastPageNumber"};
11714    int imax=0;
11715    if (NB) XtVaGetValues(NB, XmNlastPageNumber, &imax, NULL);
11716    return(imax);
11717 }
11718 
SUMA_SetSurfContPageNumber(Widget NB,int i)11719 SUMA_Boolean SUMA_SetSurfContPageNumber(Widget NB, int i)
11720 {
11721    static char FuncName[]={"SUMA_SetSurfContPageNumber"};
11722    int k, N_adolist=0, adolist[SUMA_MAX_DISPLAYABLE_OBJECTS];
11723    SUMA_X_SurfCont *SurfCont = NULL;
11724    char sbuf[SUMA_MAX_LABEL_LENGTH];
11725    XmString string;
11726    int imax;
11727    SUMA_Boolean LocalHead = NOPE;
11728 
11729    SUMA_ENTRY;
11730    if (!NB || i < 1) {
11731       SUMA_S_Errv("NULL widget or bad page number %d\n", i);
11732       SUMA_RETURN(NOPE);
11733    }
11734    XtVaGetValues(NB, XmNlastPageNumber, &imax, NULL);
11735    if (i > imax) {
11736       SUMA_S_Errv("Request to switch to page %d, but have %d pages total.\n",
11737                   i, imax);
11738       SUMA_RETURN(NOPE);
11739    }
11740    SUMA_LHv("Setting page to %d\n", i);
11741    XtVaSetValues(NB, XmNcurrentPageNumber, i, NULL);
11742 
11743    /* And force set all arrow fields, they are supposed to act like one */
11744    N_adolist = SUMA_ADOs_WithSurfCont (SUMAg_DOv, SUMAg_N_DOv, adolist);
11745    SUMA_LHv("Force setting %d surfconts to page %d, max %d\n",
11746                N_adolist, i, imax);
11747    for (k=0; k<N_adolist; ++k) {
11748       /* Note that many objects in this list maybe intimately
11749          related (they share the same parent graph link). So
11750          beware that you may be setting the same arrow head
11751          multiple times. But that is not a big deal, just redundant
11752          work */
11753       SUMA_LHv("   %d for %s\n",
11754                k, SUMA_ADO_Label((SUMA_ALL_DO *)SUMAg_DOv[adolist[k]].OP));
11755       SurfCont = SUMA_ADO_Cont((SUMA_ALL_DO *)SUMAg_DOv[adolist[k]].OP);
11756       if (SurfCont && SurfCont->SurfContPage && SurfCont->SurfContPage->rc) {
11757          SurfCont->SurfContPage->value = i;
11758          SurfCont->SurfContPage->max = (float)imax;
11759 
11760          sprintf(sbuf,"%d",(int)SurfCont->SurfContPage->value);
11761          SUMA_SET_TEXT_FIELD(SurfCont->SurfContPage->textfield, sbuf);
11762 
11763          string = XmStringCreateLtoR (
11764                SUMA_ADO_CropLabel((SUMA_ALL_DO *)SUMAg_DOv[adolist[k]].OP,
11765                                   SUMA_SURF_CONT_SWITCH_LABEL_LENGTH),
11766                      XmSTRING_DEFAULT_CHARSET);
11767          XtVaSetValues( SurfCont->SurfContPage_label,
11768                         XmNlabelString, string, NULL);
11769          XmStringFree (string);
11770       }
11771    }
11772 
11773    SUMA_RETURN(YUP);
11774 }
11775 
SUMA_Init_SurfCont_SurfParam_GLDO(SUMA_ALL_DO * ado)11776 SUMA_Boolean SUMA_Init_SurfCont_SurfParam_GLDO(SUMA_ALL_DO *ado)
11777 {
11778    static char FuncName[]={"SUMA_Init_SurfCont_SurfParam_GLDO"};
11779    return(SUMA_Init_SurfCont_SurfParam_ADO(ado));
11780 }
11781 
SUMA_Init_SurfCont_SurfParam_TDO(SUMA_ALL_DO * ado)11782 SUMA_Boolean SUMA_Init_SurfCont_SurfParam_TDO(SUMA_ALL_DO *ado)
11783 {
11784    static char FuncName[]={"SUMA_Init_SurfCont_SurfParam_TDO"};
11785    return(SUMA_Init_SurfCont_SurfParam_ADO(ado));
11786 }
11787 
SUMA_Init_SurfCont_SurfParam_VO(SUMA_ALL_DO * ado)11788 SUMA_Boolean SUMA_Init_SurfCont_SurfParam_VO(SUMA_ALL_DO *ado)
11789 {
11790    static char FuncName[]={"SUMA_Init_SurfCont_SurfParam_VO"};
11791    return(SUMA_Init_SurfCont_SurfParam_ADO(ado));
11792 }
11793 
SUMA_Init_SurfCont_SurfParam_CO(SUMA_ALL_DO * ado)11794 SUMA_Boolean SUMA_Init_SurfCont_SurfParam_CO(SUMA_ALL_DO *ado)
11795 {
11796    static char FuncName[]={"SUMA_Init_SurfCont_SurfParam_CO"};
11797    return(SUMA_Init_SurfCont_SurfParam_ADO(ado));
11798 }
11799 
SUMA_Init_SurfCont_SurfParam_MDO(SUMA_ALL_DO * ado)11800 SUMA_Boolean SUMA_Init_SurfCont_SurfParam_MDO(SUMA_ALL_DO *ado)
11801 {
11802    static char FuncName[]={"SUMA_Init_SurfCont_SurfParam_MDO"};
11803    return(SUMA_Init_SurfCont_SurfParam_ADO(ado));
11804 }
11805 
SUMA_Init_SurfCont_SurfParam_ADO(SUMA_ALL_DO * ado)11806 SUMA_Boolean SUMA_Init_SurfCont_SurfParam_ADO(SUMA_ALL_DO *ado)
11807 {
11808    static char FuncName[]={"SUMA_Init_SurfCont_SurfParam_ADO"};
11809    char *slabel = NULL, *Name, *lbl30 = NULL;
11810    int i, imenu;
11811    Widget *w=NULL, whist=NULL;
11812    XmString string;
11813    SUMA_ALL_DO *oado=NULL;
11814    SUMA_X_SurfCont *SurfCont = NULL;
11815    SUMA_OVERLAYS *curColPlane=NULL;
11816    SUMA_Boolean SameObject = NOPE;
11817    SUMA_Boolean LocalHead = NOPE;
11818 
11819    SUMA_ENTRY;
11820 
11821    if (!ado || !(SurfCont = SUMA_ADO_Cont(ado)) || !SurfCont->TLS) {
11822       SUMA_S_Err("NULL input on ADO %s type %s (%p, TLS %p)",
11823                   ADO_LABEL(ado), ADO_TNAME(ado),
11824                   SurfCont, SurfCont?SurfCont->TLS:NULL);
11825       SUMA_DUMP_TRACE("NULL input on ADO");
11826       SUMA_RETURN(NOPE);
11827    }
11828 
11829    if (!(oado = SUMA_SurfCont_GetcurDOp(SurfCont))) {
11830       SUMA_S_Err("Failed to retrieve DO"); SUMA_RETURN(NOPE);
11831    }
11832 
11833    if (oado->do_type != ado->do_type) {
11834       SUMA_S_Errv("Type mismatch: oado is %d (%s), ado is %d (%s)\n",
11835                   oado->do_type,
11836                   SUMA_ObjectTypeCode2ObjectTypeName(oado->do_type),
11837                   ado->do_type,
11838                   SUMA_ObjectTypeCode2ObjectTypeName(ado->do_type));
11839       SUMA_DUMP_TRACE("DO type mismatch");
11840       SUMA_RETURN(NOPE);
11841    }
11842    if (oado == ado) {
11843       SameObject = YUP;
11844    } else {
11845       SameObject = NOPE;
11846    }
11847 
11848    SUMA_LHv("Called for %s, current %s, buttdown = %d\n",
11849             SUMA_ADO_Label(ado), SUMA_ADO_Label(oado), SUMAg_CF->X->ButtonDown);
11850    /* set the new current surface pointer.
11851       Here you must decide whether or not to get the particular DO variant
11852       that was clicked on...  */
11853    if (!SUMA_SurfCont_SetcurDOp(SurfCont,ado)) {
11854       SUMA_S_Err("Failed to set curDOp");
11855       SUMA_RETURN(NOPE);
11856    }
11857 
11858    if (!SameObject ||
11859        ( SUMAg_CF->X->UseSameSurfCont &&
11860          !SUMA_isCurrentContPage(SUMAg_CF->X->SC_Notebook,
11861                                  SurfCont->Page))) {
11862       /* initialize the title of the window */
11863       slabel = (char *)SUMA_malloc (sizeof(char) *
11864                            (strlen(SUMA_ADO_Label(ado)) + 100));
11865 
11866       if (strlen(SUMA_ADO_Label(ado)) > 40) {
11867          char *tmpstr=NULL;
11868          tmpstr = SUMA_truncate_string(SUMA_ADO_Label(ado), 40);
11869          if (tmpstr) {
11870             sprintf(slabel,"[%s] %s Controller", tmpstr, SUMA_ADO_ContName(ado));
11871             free(tmpstr); tmpstr=NULL;
11872          }
11873       } else {
11874          sprintf(slabel,"[%s] %s Controller",
11875                         SUMA_ADO_Label(ado), SUMA_ADO_ContName(ado));
11876       }
11877       SUMA_LH("Setting title");
11878       XtVaSetValues(SurfCont->TLS, XtNtitle, slabel, NULL);
11879 
11880       /* initialize the string before the more button */
11881          /*put a label containing the surface name, number of nodes
11882             and number of facesets */
11883          lbl30 = SUMA_set_string_length(SUMA_ADO_Label(ado), ' ', 27);
11884          switch (ado->do_type) {
11885             case GRAPH_LINK_type:
11886                if (lbl30) {
11887                   sprintf(slabel,"%s\n%d edges, variant %s.",
11888                            lbl30, SUMA_ADO_N_Datum(ado), SUMA_ADO_variant(ado));
11889                   SUMA_free(lbl30); lbl30 = NULL;
11890                } else {
11891                   sprintf(slabel,"???\n%d edges.",SUMA_ADO_N_Datum(ado));
11892                }
11893                break;
11894             case TRACT_type: {
11895                SUMA_TractDO *tdo = (SUMA_TractDO *)ado;
11896                if (lbl30) {
11897                   sprintf(slabel,"%s \n%d bnd. %d trc. %d pts.",
11898                               lbl30, TDO_N_BUNDLES(tdo), TDO_N_TRACTS(tdo),
11899                               SUMA_ADO_N_Datum(ado));
11900                   SUMA_free(lbl30); lbl30 = NULL;
11901                } else {
11902                   sprintf(slabel,"???\n%d bnd. %d trc. %d pts.",
11903                               TDO_N_BUNDLES(tdo),
11904                               TDO_N_TRACTS(tdo), SUMA_ADO_N_Datum(ado));
11905                }
11906                break; }
11907             case MASK_type: { /* Won't be used anymore, see below */
11908                SUMA_MaskDO *mdo = (SUMA_MaskDO *)ado;
11909                if (lbl30) {
11910                   sprintf(slabel,"Current: %s\n ", lbl30);
11911                   SUMA_free(lbl30); lbl30 = NULL;
11912                } else {
11913                   sprintf(slabel,"Current: ???\n ");
11914                }
11915                break; }
11916             default:
11917                if (lbl30) {
11918                   sprintf(slabel,"%s\n%d data vals.",
11919                            lbl30, SUMA_ADO_N_Datum(ado));
11920                   SUMA_free(lbl30); lbl30 = NULL;
11921                } else {
11922                   sprintf(slabel,"???\n%d data vals.",SUMA_ADO_N_Datum(ado));
11923                }
11924                break;
11925          }
11926          if (SurfCont->SurfInfo_label) { /* Not used for MASK_type */
11927             SUMA_LHv("Setting label to\n>>%s<<\n", slabel);
11928             string = XmStringCreateLtoR (slabel, XmSTRING_DEFAULT_CHARSET);
11929             XtVaSetValues( SurfCont->SurfInfo_label,
11930                            XmNlabelString, string, NULL);
11931             XmStringFree (string);
11932          }
11933 
11934       if (slabel) SUMA_free(slabel); slabel = NULL;
11935       /* Can't do much with the SurfInfo button,
11936       You can only have on Info shell/LocalDomainParent
11937       at a time */
11938 
11939 
11940       /* RAISE */
11941       if (SUMAg_CF->X->UseSameSurfCont) {
11942          if (!(i = SUMA_PageWidgetToNumber(SUMAg_CF->X->SC_Notebook,
11943                                            SurfCont->Page))) {
11944             SUMA_S_Errv("Failed to find controller page for surface %s\n",
11945                         CHECK_NULL_STR(SUMA_ADO_Label(ado)));
11946          } else {
11947             SUMA_LHv("Setting notebook page to page %d, button down is %d\n",
11948                      i,SUMAg_CF->X->ButtonDown);
11949             if (LocalHead) SUMA_DUMP_TRACE("You rang?");
11950             if (!SUMAg_CF->X->ButtonDown) {
11951                SUMA_SetSurfContPageNumber(SUMAg_CF->X->SC_Notebook, i);
11952             }
11953          }
11954       }
11955    }
11956 
11957    /* do even if this is the old surface */
11958 
11959    SUMA_RETURN(YUP);
11960 }
11961 
11962 /*!
11963    \brief creates/raises the DrawROI window
11964 
11965    \param DrawnROI (SUMA_DRAWN_ROI *) a drawn ROI that is currently being drawn. NULL if there are none
11966 
11967 */
SUMA_OpenDrawROIWindow(SUMA_DRAWN_ROI * DrawnROI)11968 SUMA_Boolean SUMA_OpenDrawROIWindow (SUMA_DRAWN_ROI *DrawnROI)
11969 {
11970    static char FuncName[] = {"SUMA_OpenDrawROIWindow"};
11971    SUMA_Boolean LocalHead = NOPE;
11972 
11973    SUMA_ENTRY;
11974 
11975    if (!SUMAg_CF->X->DrawROI->AppShell) { /* need to create window */
11976       SUMA_CreateDrawROIWindow ();
11977    } else {/* just needs raising */
11978       /* controller already created, need to bring it up again */
11979       switch (SUMA_CLOSE_MODE)   {/* No open GL drawables in this widget*/
11980          case SUMA_WITHDRAW:
11981             if (LocalHead)
11982                fprintf (SUMA_STDERR,"%s: raising DrawROI window \n", FuncName);
11983             XMapRaised(SUMAg_CF->X->DPY_controller1,
11984                         XtWindow(SUMAg_CF->X->DrawROI->AppShell));
11985             break;
11986          default:
11987             SUMA_S_Err("Not setup for this close mode");
11988             SUMA_RETURN(NOPE);
11989             break;
11990       }
11991    }
11992 
11993    if (DrawnROI) {
11994       /* initialize the window */
11995       SUMA_InitializeDrawROIWindow (DrawnROI);
11996    }
11997 
11998    SUMA_RETURN(YUP);
11999 }
12000 
12001 /*!
12002    \brief Sets the widgets in the DrawROI window based on the DrawnROI structure
12003 */
SUMA_InitializeDrawROIWindow(SUMA_DRAWN_ROI * DrawnROI)12004 SUMA_Boolean SUMA_InitializeDrawROIWindow (SUMA_DRAWN_ROI *DrawnROI)
12005 {
12006    static char FuncName[] = {"SUMA_InitializeDrawROIWindow"};
12007    SUMA_SurfaceObject *SOp = NULL;
12008    char sbuf[SUMA_MAX_LABEL_LENGTH];
12009    SUMA_Boolean LocalHead = NOPE;
12010 
12011    SUMA_ENTRY;
12012 
12013    if (!DrawnROI) {
12014       if (LocalHead)
12015          fprintf (SUMA_STDERR, "%s: Initializing with NULL.\n", FuncName);
12016       SUMA_SET_LABEL(SUMAg_CF->X->DrawROI->ParentLabel_lb, "Parent: -");
12017       SUMA_SET_TEXT_FIELD(SUMAg_CF->X->DrawROI->ROIlbl->textfield, "-");
12018       SUMA_SET_TEXT_FIELD(SUMAg_CF->X->DrawROI->ROIval->textfield, "0");
12019    }else {
12020       if (LocalHead)
12021          fprintf (SUMA_STDERR,
12022                   "%s: Initializing with %p.\n", FuncName, DrawnROI);
12023       SOp = SUMA_findSOp_inDOv(DrawnROI->Parent_idcode_str,
12024                                SUMAg_DOv, SUMAg_N_DOv);
12025       if (SOp) {
12026          sprintf (sbuf, "Parent: %s", SOp->Label);
12027          SUMA_SET_LABEL(SUMAg_CF->X->DrawROI->ParentLabel_lb, sbuf);
12028       } else {
12029          SUMA_SET_LABEL(SUMAg_CF->X->DrawROI->ParentLabel_lb,
12030                         "Parent: Not Found");
12031       }
12032 
12033       SUMAg_CF->X->DrawROI->curDrawnROI = DrawnROI;
12034             /* set the currently drawnROI */
12035 
12036       SUMA_SET_TEXT_FIELD(SUMAg_CF->X->DrawROI->ROIlbl->textfield,
12037                            DrawnROI->Label);
12038 
12039       SUMAg_CF->X->DrawROI->ROIval->value = DrawnROI->iLabel;
12040       sprintf(sbuf,"%d", DrawnROI->iLabel);
12041       SUMA_SET_TEXT_FIELD(SUMAg_CF->X->DrawROI->ROIval->textfield, sbuf);
12042    }
12043    SUMA_RETURN (YUP);
12044 }
12045 
12046 /*!
12047    \brief Initializes the widgets in the color plane shell window based on the SUMA_OVERLAYS structue
12048 */
SUMA_InitializeColPlaneShell(SUMA_ALL_DO * ado,SUMA_OVERLAYS * colPlane)12049 SUMA_Boolean SUMA_InitializeColPlaneShell(
12050                   SUMA_ALL_DO *ado,
12051                   SUMA_OVERLAYS *colPlane)
12052 {
12053    static char FuncName[] = {"SUMA_InitializeColPlaneShell"};
12054    SUMA_Boolean LocalHead = NOPE;
12055 
12056    SUMA_ENTRY;
12057 
12058 
12059 
12060    if (!ado) {
12061       SUMA_S_Err("NULL input, what gives?");
12062       SUMA_RETURN(NOPE);
12063    }
12064    if (LocalHead) {
12065       SUMA_LH("Called with colPlane %p, ado %s", colPlane, ADO_LABEL(ado));
12066       SUMA_DUMP_TRACE("And who called that one?");
12067    }
12068    switch(ado->do_type) {
12069       case SO_type:
12070          SUMA_RETURN(SUMA_InitializeColPlaneShell_SO(
12071                               (SUMA_SurfaceObject *)ado, colPlane));
12072          break;
12073       case GDSET_type:
12074          SUMA_S_Err("No init for a DO that cannot be dispalyed\n"
12075                     "without variant");
12076          SUMA_RETURN(NOPE);
12077          break;
12078       case CDOM_type:
12079          SUMA_RETURN(SUMA_InitializeColPlaneShell_CO(ado, colPlane));
12080          break;
12081       case GRAPH_LINK_type: {
12082          SUMA_GraphLinkDO *gldo=(SUMA_GraphLinkDO *)ado;
12083          SUMA_DSET *dset=NULL;
12084          if (!(dset=SUMA_find_GLDO_Dset(gldo))) {
12085             SUMA_S_Errv("Failed to find dset for gldo %s!!!\n",
12086                         SUMA_ADO_Label(ado));
12087             SUMA_RETURN(NOPE);
12088          }
12089          SUMA_RETURN(SUMA_InitializeColPlaneShell_GLDO(ado, colPlane));
12090          break; }
12091       case TRACT_type: {
12092          SUMA_RETURN(SUMA_InitializeColPlaneShell_TDO(ado, colPlane));
12093          break; }
12094       case MASK_type: {
12095          SUMA_RETURN(SUMA_InitializeColPlaneShell_MDO(ado, colPlane));
12096          break; }
12097       case VO_type: {
12098          SUMA_RETURN(SUMA_InitializeColPlaneShell_VO(ado, colPlane));
12099          break; }
12100       default:
12101          SUMA_S_Errv("Not ready for %s types\n",
12102             SUMA_ObjectTypeCode2ObjectTypeName(ado->do_type));
12103          SUMA_RETURN(NOPE);
12104    }
12105 
12106    SUMA_RETURN(NOPE);
12107 }
12108 
SUMA_InitializeColPlaneShell_SO(SUMA_SurfaceObject * SO,SUMA_OVERLAYS * ColPlane)12109 SUMA_Boolean SUMA_InitializeColPlaneShell_SO (
12110                   SUMA_SurfaceObject *SO,
12111                   SUMA_OVERLAYS *ColPlane)
12112 {
12113    static char FuncName[] = {"SUMA_InitializeColPlaneShell_SO"};
12114    char sbuf[SUMA_MAX_LABEL_LENGTH];
12115    double range[2];
12116    int loc[2], i;
12117    SUMA_SurfaceObject *SOpar=NULL;
12118 
12119    SUMA_Boolean LocalHead = NOPE;
12120 
12121    SUMA_ENTRY;
12122 
12123    SUMA_LH("Called");
12124 
12125    if (!SO || !SO->SurfCont) {
12126       SUMA_S_Err("NULL input, what gives?");
12127       SUMA_RETURN(NOPE);
12128    }
12129 
12130    if (!SO->SurfCont->ColPlane_fr) {
12131       /* just set the curColPlane before returning ZSS  March 25 08*/
12132       if (ColPlane) SO->SurfCont->curColPlane = ColPlane;
12133       SUMA_RETURN(YUP);
12134    }
12135 
12136    if (!ColPlane) {
12137       SUMA_LH("Initializing with NULL");
12138       SUMA_INSERT_CELL_STRING(SO->SurfCont->ColPlaneLabelTable, 0, 1, "-");
12139       SUMA_INSERT_CELL_STRING(SO->SurfCont->ColPlaneLabelTable, 1, 1, "-");
12140       SUMA_SET_TEXT_FIELD(SO->SurfCont->SurfContPage->textfield, "-");
12141       SUMA_SET_TEXT_FIELD(SO->SurfCont->ColPlaneOrder->textfield, "-");
12142       SUMA_SET_TEXT_FIELD(SO->SurfCont->ColPlaneOpacity->textfield,"-");
12143       SUMA_SET_TEXT_FIELD(SO->SurfCont->ColPlaneDimFact->textfield,"-");
12144       SUMA_RETURN (YUP);
12145    }else {
12146       SUMA_LH("Initializing for real");
12147       if (ColPlane->dset_link) { /* get the parent surface of the colorplane */
12148          if (ColPlane->dset_link->ngr) {
12149             SOpar = SUMA_findSOp_inDOv(
12150                               NI_get_attribute(ColPlane->dset_link->ngr,
12151                                                 "domain_parent_idcode"),
12152                               SUMAg_DOv, SUMAg_N_DOv);
12153          }
12154       }
12155       if (!SOpar) {
12156          SUMA_SL_Warn(  "No domain parent for dset %s found.\n"
12157                         "Proceeding with next best option.",
12158                         SDSET_LABEL(ColPlane->dset_link));
12159          SOpar = SO;
12160       }
12161 
12162       if (  strlen(ColPlane->Label) +
12163             strlen(SOpar->Label) +  25   >
12164             SUMA_MAX_LABEL_LENGTH) {
12165          SUMA_SL_Warn("Surface Labels too long!");
12166          SUMA_INSERT_CELL_STRING(SO->SurfCont->ColPlaneLabelTable,
12167                                  0, 1, "Surface Labels too long!");
12168          SUMA_INSERT_CELL_STRING(SO->SurfCont->ColPlaneLabelTable,
12169                                  1, 1, "Surface Labels too long!");
12170       } else {
12171          if (strlen(SOpar->Label) > 40) {
12172             char *tmpstr=NULL;
12173             tmpstr = SUMA_truncate_string(SOpar->Label, 40);
12174             if (tmpstr) {
12175                sprintf (sbuf, "Label: %s\nParent: %s", ColPlane->Label, tmpstr);
12176                free(tmpstr); tmpstr = NULL;
12177             }
12178             SUMA_INSERT_CELL_STRING(SO->SurfCont->ColPlaneLabelTable,
12179                                     0, 1, ColPlane->Label);
12180             SUMA_INSERT_CELL_STRING(SO->SurfCont->ColPlaneLabelTable,
12181                                     1, 1, tmpstr);
12182          } else {
12183             sprintf (sbuf, "Label: %s\nParent: %s",
12184                      ColPlane->Label, SOpar->Label);
12185          }
12186          SUMA_INSERT_CELL_STRING(SO->SurfCont->ColPlaneLabelTable,
12187                                  0, 1, ColPlane->Label);
12188          SUMA_INSERT_CELL_STRING(SO->SurfCont->ColPlaneLabelTable,
12189                                  1, 1, SOpar->Label);
12190       }
12191 
12192       if (SUMAg_CF->X->UseSameSurfCont) {
12193          SO->SurfCont->SurfContPage->value =
12194             SUMA_PageWidgetToNumber(SUMAg_CF->X->SC_Notebook,
12195                                     SO->SurfCont->Page);
12196          SUMA_LHv("Setting PPpage to %d\n",
12197                       (int)SO->SurfCont->SurfContPage->value);
12198          sprintf(sbuf,"%d",(int)SO->SurfCont->SurfContPage->value);
12199          SUMA_SET_TEXT_FIELD(SO->SurfCont->SurfContPage->textfield, sbuf);
12200       }
12201 
12202       SO->SurfCont->ColPlaneOrder->value = ColPlane->PlaneOrder;
12203       sprintf(sbuf,"%d", ColPlane->PlaneOrder);
12204       SUMA_SET_TEXT_FIELD(SO->SurfCont->ColPlaneOrder->textfield, sbuf);
12205 
12206       SO->SurfCont->ColPlaneOpacity->value = ColPlane->GlobalOpacity;
12207       sprintf(sbuf,"%.1f", ColPlane->GlobalOpacity);
12208       SUMA_SET_TEXT_FIELD(SO->SurfCont->ColPlaneOpacity->textfield, sbuf);
12209 
12210       if (ColPlane->OptScl)
12211          SO->SurfCont->ColPlaneDimFact->value = ColPlane->OptScl->BrightFact;
12212       else SO->SurfCont->ColPlaneDimFact->value = ColPlane->DimFact;
12213       sprintf(sbuf,"%.1f", SO->SurfCont->ColPlaneDimFact->value);
12214       SUMA_SET_TEXT_FIELD(SO->SurfCont->ColPlaneDimFact->textfield, sbuf);
12215 
12216    }
12217 
12218 
12219    SO->SurfCont->curColPlane = ColPlane;
12220 
12221    SUMA_LHv("Have ShowMode for %s of %d (widget %d)\n",
12222                 SO->SurfCont->curColPlane->Label,
12223                 SO->SurfCont->curColPlane->ShowMode,
12224                 SUMA_ShowMode2ShowModeMenuItem(
12225                               SO->SurfCont->curColPlane->ShowMode));
12226    SUMA_Set_Menu_Widget(SO->SurfCont->DsetViewModeMenu,
12227                  SUMA_ShowMode2ShowModeMenuItem(
12228                               SO->SurfCont->curColPlane->ShowMode));
12229    /* obsolete
12230    XmToggleButtonSetState (SO->SurfCont->ColPlaneShow_tb, ColPlane->Show, NOPE);
12231    */
12232 
12233    /* Set 1 only sensitivity */
12234    if (SO->SurfCont->ColPlaneShowOneFore_tb) {
12235       if (SO->SurfCont->curColPlane->isBackGrnd) {
12236          XtSetSensitive (SO->SurfCont->ColPlaneShowOneFore_tb, 0);
12237       }  else {
12238          XtSetSensitive (SO->SurfCont->ColPlaneShowOneFore_tb, 1);
12239       }
12240    }
12241 
12242 
12243 
12244    /* update the cross hair group */
12245    SUMA_Init_SurfCont_CrossHair((SUMA_ALL_DO *)SO);
12246 
12247    /* set the colormap */
12248    SUMA_LH("Cmap time");
12249    if (SO->SurfCont->cmp_ren->cmap_context) {
12250       SUMA_LH("Rendering context not null");
12251       if (strcmp(SO->SurfCont->curColPlane->cmapname, "explicit") == 0 ||
12252           SUMA_is_Label_dset(SO->SurfCont->curColPlane->dset_link, NULL)) {
12253          SUMA_LH("Checking management");
12254          if (XtIsManaged(SO->SurfCont->DsetMap_fr)) {
12255             SUMA_LH("An RGB dset, or label dset no surface controls to be seen");
12256             XtUnmanageChild(SO->SurfCont->DsetMap_fr);
12257             XtUnmanageChild(XtParent(SO->SurfCont->DsetMap_fr));
12258          }else {
12259             SUMA_LH("An RGB dset, or label dset and no controls managed");
12260          }
12261       } else {
12262          if (!XtIsManaged(SO->SurfCont->DsetMap_fr)) {
12263             SUMA_LH( "A non RGB, and non label, dset \n"
12264                      "surface controls need to be seen\n"
12265                      "But only when ColPlane_fr is also shown \n"
12266                      "(frame may be hidden by Dsets button action)");
12267             if (XtIsManaged(SO->SurfCont->ColPlane_fr)) {
12268                XtManageChild(XtParent(SO->SurfCont->DsetMap_fr));
12269                XtManageChild(SO->SurfCont->DsetMap_fr);
12270             }
12271          }
12272          SUMA_LH( "Handling redisplay");
12273          SUMA_cmap_wid_handleRedisplay((XtPointer) SO);
12274 
12275          SUMA_LH( "cmap options");
12276          /* set the widgets for dems mapping options */
12277          SUMA_set_cmap_options((SUMA_ALL_DO *)SO, YUP, NOPE);
12278 
12279          SUMA_LH( "cmap menu choice");
12280          /* set the menu to show the colormap used */
12281          SUMA_SetCmapMenuChoice((SUMA_ALL_DO *)SO, ColPlane->cmapname);
12282 
12283          SUMA_LH( "Dset col range");
12284          /* set the values for the threshold bar */
12285          if (SUMA_GetDsetColRange(  SO->SurfCont->curColPlane->dset_link,
12286                                     SO->SurfCont->curColPlane->OptScl->tind,
12287                                     range, loc)) {
12288             SUMA_SetScaleRange((SUMA_ALL_DO *)SO, range );
12289          }
12290       }
12291    } else {
12292       SUMA_LH("cmap_context was NULL");
12293    }
12294 
12295    SUMA_LH("Returning");
12296    SUMA_RETURN (YUP);
12297 }
12298 
12299 /*!
12300    This function mirrors SUMA_InitializeColPlaneShell_SO
12301    but it is for graph datasets
12302 */
SUMA_InitializeColPlaneShell_GLDO(SUMA_ALL_DO * ado,SUMA_OVERLAYS * ColPlane)12303 SUMA_Boolean SUMA_InitializeColPlaneShell_GLDO (
12304                   SUMA_ALL_DO *ado,
12305                   SUMA_OVERLAYS *ColPlane)
12306 {
12307    static char FuncName[] = {"SUMA_InitializeColPlaneShell_GLDO"};
12308    char sbuf[SUMA_MAX_LABEL_LENGTH];
12309    double range[2];
12310    int loc[2], i;
12311    SUMA_OVERLAYS *curColPlane=NULL;
12312    SUMA_X_SurfCont *SurfCont=NULL;
12313    SUMA_Boolean LocalHead = NOPE;
12314 
12315    SUMA_ENTRY;
12316 
12317    SUMA_LH("Called");
12318 
12319    SurfCont = SUMA_ADO_Cont(ado);
12320    curColPlane = SUMA_ADO_CurColPlane(ado);
12321 
12322    if (!ado || !SurfCont) {
12323       SUMA_S_Err("NULL input, what gives?");
12324       SUMA_RETURN(NOPE);
12325    }
12326 
12327    if (!SurfCont->ColPlane_fr) {
12328       /* just set the curColPlane before returning ZSS  March 25 08*/
12329       if (ColPlane) SurfCont->curColPlane = ColPlane;
12330       SUMA_RETURN(YUP);
12331    }
12332 
12333    if (!ColPlane) {
12334       SUMA_LH("Initializing with NULL");
12335       SUMA_INSERT_CELL_STRING(SurfCont->ColPlaneLabelTable, 0, 1, "-");
12336       SUMA_SET_TEXT_FIELD(SurfCont->SurfContPage->textfield, "-");
12337       SUMA_SET_TEXT_FIELD(SurfCont->ColPlaneDimFact->textfield,"-");
12338       SUMA_RETURN (YUP);
12339    } else {
12340       SUMA_LH("Initializing for real");
12341 
12342       SUMA_INSERT_CELL_STRING(SurfCont->ColPlaneLabelTable,
12343                                  0, 1, ColPlane->Label);
12344    }
12345 
12346    SurfCont->curColPlane = ColPlane;
12347 
12348 
12349    /* update the cross hair group */
12350    SUMA_Init_SurfCont_CrossHair(ado);
12351 
12352    if (SUMAg_CF->X->UseSameSurfCont) {
12353       SurfCont->SurfContPage->value =
12354          SUMA_PageWidgetToNumber(SUMAg_CF->X->SC_Notebook,
12355                                  SurfCont->Page);
12356       SUMA_LHv("Setting PPpage to %d\n",
12357                     (int)SurfCont->SurfContPage->value);
12358 
12359       sprintf(sbuf,"%d",(int)SurfCont->SurfContPage->value);
12360       SUMA_SET_TEXT_FIELD(SurfCont->SurfContPage->textfield, sbuf);
12361    }
12362 
12363    /* set the colormap */
12364    SUMA_LH("Cmap time");
12365    if (SurfCont->cmp_ren->cmap_context) {
12366       SUMA_LH("Rendering context not null");
12367       if (strcmp(curColPlane->cmapname, "explicit") == 0 ||
12368           SUMA_is_Label_dset(curColPlane->dset_link, NULL)) {
12369          SUMA_LH("Checking management");
12370          if (XtIsManaged(SurfCont->DsetMap_fr)) {
12371             SUMA_LH("An RGB dset, or label dset no surface controls to be seen");
12372             XtUnmanageChild(SurfCont->DsetMap_fr);
12373             XtUnmanageChild(XtParent(SurfCont->DsetMap_fr));
12374          }else {
12375             SUMA_LH("An RGB dset, or label dset and no controls managed");
12376          }
12377       } else {
12378          if (!XtIsManaged(SurfCont->DsetMap_fr)) {
12379             SUMA_LH( "A non RGB, and non label, dset \n"
12380                      "surface controls need to be seen\n"
12381                      "But only when ColPlane_fr is also shown \n"
12382                      "(frame may be hidden by Dsets button action)");
12383             if (XtIsManaged(SurfCont->ColPlane_fr)) {
12384                XtManageChild(XtParent(SurfCont->DsetMap_fr));
12385                XtManageChild(SurfCont->DsetMap_fr);
12386             }
12387          }
12388          SUMA_LH( "Handling redisplay");
12389          SUMA_cmap_wid_handleRedisplay((XtPointer)ado);
12390 
12391          SUMA_LH( "cmap options");
12392          /* set the widgets for dems mapping options */
12393          SUMA_set_cmap_options(ado, YUP, NOPE);
12394 
12395          SUMA_LH( "cmap menu choice");
12396          /* set the menu to show the colormap used */
12397          SUMA_SetCmapMenuChoice(ado, ColPlane->cmapname);
12398 
12399          /* set the values for the threshold bar */
12400          SUMA_LH( "dset range");
12401          if (SUMA_GetDsetColRange(  curColPlane->dset_link,
12402                                     curColPlane->OptScl->tind,
12403                                     range, loc)) {
12404             SUMA_SetScaleRange(ado, range );
12405          }
12406       }
12407    } else {
12408       SUMA_LH("cmap_context was NULL");
12409    }
12410 
12411    SUMA_LH("Returning");
12412    SUMA_RETURN (YUP);
12413 }
12414 
12415 /*!
12416    This function mirrors SUMA_InitializeColPlaneShell_SO
12417    but it is for tracts
12418 */
SUMA_InitializeColPlaneShell_TDO(SUMA_ALL_DO * ado,SUMA_OVERLAYS * ColPlane)12419 SUMA_Boolean SUMA_InitializeColPlaneShell_TDO (
12420                   SUMA_ALL_DO *ado,
12421                   SUMA_OVERLAYS *ColPlane)
12422 {
12423    static char FuncName[] = {"SUMA_InitializeColPlaneShell_TDO"};
12424    char sbuf[SUMA_MAX_LABEL_LENGTH];
12425    double range[2];
12426    int loc[2], i;
12427    SUMA_OVERLAYS *curColPlane=NULL;
12428    SUMA_X_SurfCont *SurfCont=NULL;
12429    SUMA_Boolean LocalHead = NOPE;
12430 
12431    SUMA_ENTRY;
12432 
12433    if (LocalHead) {
12434       SUMA_LH("Called with ColPlane %p", ColPlane);
12435       SUMA_DUMP_TRACE("Who called this?");
12436    }
12437    SurfCont = SUMA_ADO_Cont(ado);
12438    curColPlane = SUMA_ADO_CurColPlane(ado);
12439 
12440    if (!ado || !SurfCont) {
12441       SUMA_S_Err("NULL input, what gives?");
12442       SUMA_RETURN(NOPE);
12443    }
12444 
12445    if (!SurfCont->ColPlane_fr) {
12446       /* just set the curColPlane before returning ZSS  March 25 08*/
12447       if (ColPlane) SurfCont->curColPlane = ColPlane;
12448       SUMA_RETURN(YUP);
12449    }
12450 
12451    if (!ColPlane) {
12452       SUMA_LH("Initializing with NULL");
12453       SUMA_INSERT_CELL_STRING(SurfCont->ColPlaneLabelTable, 0, 1, "-");
12454       SUMA_SET_TEXT_FIELD(SurfCont->SurfContPage->textfield, "-");
12455       SUMA_SET_TEXT_FIELD(SurfCont->ColPlaneDimFact->textfield,"-");
12456       SUMA_RETURN (YUP);
12457    } else {
12458       SUMA_LH("Initializing for real");
12459 
12460       SUMA_INSERT_CELL_STRING(SurfCont->ColPlaneLabelTable,
12461                                  0, 1, ColPlane->Label);
12462    }
12463 
12464    SurfCont->curColPlane = ColPlane;
12465 
12466 
12467    /* update the cross hair group */
12468    SUMA_Init_SurfCont_CrossHair(ado);
12469 
12470    if (SUMAg_CF->X->UseSameSurfCont) {
12471       SurfCont->SurfContPage->value =
12472          SUMA_PageWidgetToNumber(SUMAg_CF->X->SC_Notebook,
12473                                  SurfCont->Page);
12474       SUMA_LHv("Setting PPpage to %d\n",
12475                     (int)SurfCont->SurfContPage->value);
12476 
12477       sprintf(sbuf,"%d",(int)SurfCont->SurfContPage->value);
12478       SUMA_SET_TEXT_FIELD(SurfCont->SurfContPage->textfield, sbuf);
12479    }
12480 
12481    /* set the colormap */
12482    SUMA_LH("Cmap time");
12483    if (SurfCont->cmp_ren->cmap_context) {
12484       SUMA_LH("Rendering context not null");
12485       if (strcmp(curColPlane->cmapname, "explicit") == 0 ||
12486           SUMA_is_Label_dset(curColPlane->dset_link, NULL)) {
12487          SUMA_LH("Checking management");
12488          if (XtIsManaged(SurfCont->DsetMap_fr)) {
12489             SUMA_LH("An RGB dset, or label dset no surface controls to be seen");
12490             XtUnmanageChild(SurfCont->DsetMap_fr);
12491             XtUnmanageChild(XtParent(SurfCont->DsetMap_fr));
12492          }else {
12493             SUMA_LH("An RGB dset, or label dset and no controls managed");
12494          }
12495       } else {
12496          if (!XtIsManaged(SurfCont->DsetMap_fr)) {
12497             SUMA_LH( "A non RGB, and non label, dset \n"
12498                      "surface controls need to be seen\n"
12499                      "But only when ColPlane_fr is also shown \n"
12500                      "(frame may be hidden by Dsets button action)");
12501             if (XtIsManaged(SurfCont->ColPlane_fr)) {
12502                XtManageChild(XtParent(SurfCont->DsetMap_fr));
12503                XtManageChild(SurfCont->DsetMap_fr);
12504             }
12505          }
12506          SUMA_LH( "Handling redisplay");
12507          SUMA_cmap_wid_handleRedisplay((XtPointer)ado);
12508 
12509          SUMA_LH( "cmap options");
12510          /* set the widgets for dems mapping options */
12511          SUMA_set_cmap_options(ado, YUP, NOPE);
12512 
12513          SUMA_LH( "cmap menu choice");
12514          /* set the menu to show the colormap used */
12515          SUMA_SetCmapMenuChoice(ado, ColPlane->cmapname);
12516 
12517          /* set the values for the threshold bar */
12518          SUMA_LH( "dset range");
12519          if (SUMA_GetDsetColRange(  curColPlane->dset_link,
12520                                     curColPlane->OptScl->tind,
12521                                     range, loc)) {
12522             SUMA_SetScaleRange(ado, range );
12523          }
12524       }
12525    } else {
12526       SUMA_LH("cmap_context was NULL");
12527    }
12528 
12529    SUMA_LH("Returning");
12530    SUMA_RETURN (YUP);
12531 }
12532 
12533 /*!
12534    This function mirrors SUMA_InitializeColPlaneShell_SO or _VO
12535    but it is for CIFTI objects
12536 */
SUMA_InitializeColPlaneShell_CO(SUMA_ALL_DO * ado,SUMA_OVERLAYS * ColPlane)12537 SUMA_Boolean SUMA_InitializeColPlaneShell_CO (
12538                   SUMA_ALL_DO *ado,
12539                   SUMA_OVERLAYS *ColPlane)
12540 {
12541    static char FuncName[] = {"SUMA_InitializeColPlaneShell_CO"};
12542    char sbuf[SUMA_MAX_LABEL_LENGTH];
12543    double range[2];
12544    int loc[2], i;
12545    SUMA_OVERLAYS *curColPlane=NULL;
12546    SUMA_X_SurfCont *SurfCont=NULL;
12547    SUMA_Boolean LocalHead = NOPE;
12548 
12549    SUMA_ENTRY;
12550 
12551    SUMA_LH("Called with ColPlane %p", ColPlane);
12552 
12553    SurfCont = SUMA_ADO_Cont(ado);
12554    curColPlane = SUMA_ADO_CurColPlane(ado);
12555 
12556    if (!ado || !SurfCont) {
12557       SUMA_S_Err("NULL input, what gives?");
12558       SUMA_RETURN(NOPE);
12559    }
12560 
12561    SUMA_S_Err("Place Holder, nothing yet. See comparable functions for "
12562               "_VO and _SO");
12563 
12564    SUMA_RETURN(NOPE);
12565 }
12566 
12567 
12568 /*!
12569    This function mirrors SUMA_InitializeColPlaneShell_SO
12570    but it is for volume objects
12571 */
SUMA_InitializeColPlaneShell_VO(SUMA_ALL_DO * ado,SUMA_OVERLAYS * ColPlane)12572 SUMA_Boolean SUMA_InitializeColPlaneShell_VO (
12573                   SUMA_ALL_DO *ado,
12574                   SUMA_OVERLAYS *ColPlane)
12575 {
12576    static char FuncName[] = {"SUMA_InitializeColPlaneShell_VO"};
12577    char sbuf[SUMA_MAX_LABEL_LENGTH];
12578    double range[2];
12579    int loc[2], i;
12580    SUMA_OVERLAYS *curColPlane=NULL;
12581    SUMA_X_SurfCont *SurfCont=NULL;
12582    SUMA_Boolean LocalHead = NOPE;
12583 
12584    SUMA_ENTRY;
12585 
12586    SUMA_LH("Called with ColPlane %p", ColPlane);
12587 
12588    SurfCont = SUMA_ADO_Cont(ado);
12589    curColPlane = SUMA_ADO_CurColPlane(ado);
12590 
12591    if (!ado || !SurfCont) {
12592       SUMA_S_Err("NULL input, what gives?");
12593       SUMA_RETURN(NOPE);
12594    }
12595 
12596    if (!SurfCont->ColPlane_fr) {
12597       /* just set the curColPlane before returning ZSS  March 25 08*/
12598       if (ColPlane) SurfCont->curColPlane = ColPlane;
12599       SUMA_RETURN(YUP);
12600    }
12601 
12602    if (!ColPlane) {
12603       SUMA_LH("Initializing with NULL");
12604       SUMA_INSERT_CELL_STRING(SurfCont->ColPlaneLabelTable, 0, 1, "-");
12605       SUMA_SET_TEXT_FIELD(SurfCont->SurfContPage->textfield, "-");
12606       SUMA_SET_TEXT_FIELD(SurfCont->ColPlaneAlphaThresh->textfield,"-");
12607       SUMA_RETURN (YUP);
12608    } else {
12609       SUMA_LH("Initializing for real");
12610 
12611       SUMA_INSERT_CELL_STRING(SurfCont->ColPlaneLabelTable,
12612                                  0, 1, ColPlane->Label);
12613 
12614       SurfCont->ColPlaneAlphaThresh->value = ColPlane->AlphaThresh;
12615       sprintf(sbuf,"%.1f", SurfCont->ColPlaneAlphaThresh->value);
12616       SUMA_SET_TEXT_FIELD(SurfCont->ColPlaneAlphaThresh->textfield, sbuf);
12617    }
12618 
12619    SurfCont->curColPlane = ColPlane;
12620 
12621 
12622    /* update the cross hair group */
12623    SUMA_Init_SurfCont_CrossHair(ado);
12624 
12625    if (SUMAg_CF->X->UseSameSurfCont) {
12626       SurfCont->SurfContPage->value =
12627          SUMA_PageWidgetToNumber(SUMAg_CF->X->SC_Notebook,
12628                                  SurfCont->Page);
12629       SUMA_LHv("Setting PPpage to %d\n",
12630                     (int)SurfCont->SurfContPage->value);
12631 
12632       sprintf(sbuf,"%d",(int)SurfCont->SurfContPage->value);
12633       SUMA_SET_TEXT_FIELD(SurfCont->SurfContPage->textfield, sbuf);
12634    }
12635 
12636    /* set the colormap */
12637    SUMA_LH("Cmap time");
12638    if (SurfCont->cmp_ren->cmap_context) {
12639       SUMA_LH("Rendering context not null");
12640       if (strcmp(curColPlane->cmapname, "explicit") == 0 ||
12641           SUMA_is_Label_dset(curColPlane->dset_link, NULL)) {
12642          SUMA_LH("Checking management");
12643          if (XtIsManaged(SurfCont->DsetMap_fr)) {
12644             SUMA_LH("An RGB dset, or label dset no surface controls to be seen");
12645             XtUnmanageChild(SurfCont->DsetMap_fr);
12646             XtUnmanageChild(XtParent(SurfCont->DsetMap_fr));
12647          }else {
12648             SUMA_LH("An RGB dset, or label dset and no controls managed");
12649          }
12650       } else {
12651          if (!XtIsManaged(SurfCont->DsetMap_fr)) {
12652             SUMA_LH( "A non RGB, and non label, dset \n"
12653                      "surface controls need to be seen\n"
12654                      "But only when ColPlane_fr is also shown \n"
12655                      "(frame may be hidden by Dsets button action)");
12656             if (XtIsManaged(SurfCont->ColPlane_fr)) {
12657                XtManageChild(XtParent(SurfCont->DsetMap_fr));
12658                XtManageChild(SurfCont->DsetMap_fr);
12659             }
12660          }
12661          SUMA_LH( "Handling redisplay");
12662          SUMA_cmap_wid_handleRedisplay((XtPointer)ado);
12663 
12664          SUMA_LH( "cmap options");
12665          /* set the widgets for dems mapping options */
12666          SUMA_set_cmap_options(ado, YUP, NOPE);
12667 
12668          SUMA_LH( "cmap menu choice");
12669          /* set the menu to show the colormap used */
12670          SUMA_SetCmapMenuChoice(ado, ColPlane->cmapname);
12671 
12672          /* set the values for the threshold bar */
12673          SUMA_LH( "dset range");
12674          if (SUMA_GetDsetColRange(  curColPlane->dset_link,
12675                                     curColPlane->OptScl->tind,
12676                                     range, loc)) {
12677             SUMA_SetScaleRange(ado, range );
12678          }
12679       }
12680    } else {
12681       SUMA_LH("cmap_context was NULL");
12682    }
12683 
12684    SUMA_LH("Returning");
12685    SUMA_RETURN (YUP);
12686 }
12687 
12688 /*!
12689    This function mirrors SUMA_InitializeColPlaneShell_SO
12690    but it is for volume objects
12691 */
SUMA_InitializeColPlaneShell_MDO(SUMA_ALL_DO * ado,SUMA_OVERLAYS * ColPlane)12692 SUMA_Boolean SUMA_InitializeColPlaneShell_MDO (
12693                   SUMA_ALL_DO *ado,
12694                   SUMA_OVERLAYS *ColPlane)
12695 {
12696    static char FuncName[] = {"SUMA_InitializeColPlaneShell_MDO"};
12697    char sbuf[SUMA_MAX_LABEL_LENGTH];
12698    double range[2];
12699    int loc[2], i;
12700    SUMA_OVERLAYS *curColPlane=NULL;
12701    SUMA_X_SurfCont *SurfCont=NULL;
12702    SUMA_Boolean LocalHead = NOPE;
12703 
12704    SUMA_ENTRY;
12705 
12706    SUMA_LH("Called with ColPlane %p", ColPlane);
12707 
12708    SurfCont = SUMA_ADO_Cont(ado);
12709    curColPlane = SUMA_ADO_CurColPlane(ado);
12710 
12711    if (!ado || !SurfCont) {
12712       SUMA_S_Err("NULL input, what gives?");
12713       SUMA_RETURN(NOPE);
12714    }
12715 
12716    if (!SurfCont->ColPlane_fr) {
12717       /* just set the curColPlane before returning ZSS  March 25 08*/
12718       if (ColPlane) SurfCont->curColPlane = ColPlane;
12719       SUMA_RETURN(YUP);
12720    }
12721 
12722    if (!ColPlane) {
12723       SUMA_LH("Initializing with NULL");
12724       SUMA_INSERT_CELL_STRING(SurfCont->ColPlaneLabelTable, 0, 1, "-");
12725       SUMA_SET_TEXT_FIELD(SurfCont->SurfContPage->textfield, "-");
12726       SUMA_SET_TEXT_FIELD(SurfCont->ColPlaneDimFact->textfield,"-");
12727       SUMA_RETURN (YUP);
12728    } else {
12729       SUMA_LH("Initializing for real");
12730 
12731       SUMA_INSERT_CELL_STRING(SurfCont->ColPlaneLabelTable,
12732                                  0, 1, ColPlane->Label);
12733    }
12734 
12735    SurfCont->curColPlane = ColPlane;
12736 
12737 
12738    /* update the cross hair group */
12739    SUMA_Init_SurfCont_CrossHair(ado);
12740 
12741    if (SUMAg_CF->X->UseSameSurfCont) {
12742       SurfCont->SurfContPage->value =
12743          SUMA_PageWidgetToNumber(SUMAg_CF->X->SC_Notebook,
12744                                  SurfCont->Page);
12745       SUMA_LHv("Setting PPpage to %d\n",
12746                     (int)SurfCont->SurfContPage->value);
12747 
12748       sprintf(sbuf,"%d",(int)SurfCont->SurfContPage->value);
12749       SUMA_SET_TEXT_FIELD(SurfCont->SurfContPage->textfield, sbuf);
12750    }
12751 
12752    /* set the colormap */
12753    SUMA_LH("Cmap time");
12754    if (SurfCont->cmp_ren->cmap_context) {
12755       SUMA_LH("Rendering context not null");
12756       if (strcmp(curColPlane->cmapname, "explicit") == 0 ||
12757           SUMA_is_Label_dset(curColPlane->dset_link, NULL)) {
12758          SUMA_LH("Checking management");
12759          if (XtIsManaged(SurfCont->DsetMap_fr)) {
12760             SUMA_LH("An RGB dset, or label dset no surface controls to be seen");
12761             XtUnmanageChild(SurfCont->DsetMap_fr);
12762             XtUnmanageChild(XtParent(SurfCont->DsetMap_fr));
12763          }else {
12764             SUMA_LH("An RGB dset, or label dset and no controls managed");
12765          }
12766       } else {
12767          if (!XtIsManaged(SurfCont->DsetMap_fr)) {
12768             SUMA_LH( "A non RGB, and non label, dset \n"
12769                      "surface controls need to be seen\n"
12770                      "But only when ColPlane_fr is also shown \n"
12771                      "(frame may be hidden by Dsets button action)");
12772             if (XtIsManaged(SurfCont->ColPlane_fr)) {
12773                XtManageChild(XtParent(SurfCont->DsetMap_fr));
12774                XtManageChild(SurfCont->DsetMap_fr);
12775             }
12776          }
12777          SUMA_LH( "Handling redisplay");
12778          SUMA_cmap_wid_handleRedisplay((XtPointer)ado);
12779 
12780          SUMA_LH( "cmap options");
12781          /* set the widgets for dems mapping options */
12782          SUMA_set_cmap_options(ado, YUP, NOPE);
12783 
12784          SUMA_LH( "cmap menu choice");
12785          /* set the menu to show the colormap used */
12786          SUMA_SetCmapMenuChoice(ado, ColPlane->cmapname);
12787 
12788          /* set the values for the threshold bar */
12789          SUMA_LH( "dset range");
12790          if (SUMA_GetDsetColRange(  curColPlane->dset_link,
12791                                     curColPlane->OptScl->tind,
12792                                     range, loc)) {
12793             SUMA_SetScaleRange(ado, range );
12794          }
12795       }
12796    } else {
12797       SUMA_LH("cmap_context was NULL");
12798    }
12799 
12800    SUMA_LH("Returning");
12801    SUMA_RETURN (YUP);
12802 }
12803 
12804 /*!
12805    \brief Updates color plane editing windows of surfaces related to SO,
12806    if the color planes are open and displaying the same plane
12807 
12808 */
SUMA_UpdateColPlaneShellAsNeeded(SUMA_ALL_DO * ado)12809 SUMA_Boolean SUMA_UpdateColPlaneShellAsNeeded(SUMA_ALL_DO *ado)
12810 {
12811    static char FuncName[] = {"SUMA_UpdateColPlaneShellAsNeeded"};
12812    int i=-1;
12813    SUMA_SurfaceObject *SOi=NULL, *SO=NULL;
12814    SUMA_X_SurfCont *SurfCont=NULL;
12815    SUMA_Boolean LocalHead = NOPE;
12816 
12817    SUMA_ENTRY;
12818 
12819    SurfCont = SUMA_ADO_Cont(ado);
12820    if (!SurfCont) SUMA_RETURN(NOPE);
12821 
12822    SUMA_LH("Called");
12823    switch (ado->do_type) {
12824       case SO_type:
12825          /* find out which surfaces are related to SO */
12826          SO = (SUMA_SurfaceObject *)ado;
12827          for (i=0; i<SUMAg_N_DOv; ++i) {
12828             if (SUMA_isSO(SUMAg_DOv[i])) {
12829                SOi = (SUMA_SurfaceObject *)SUMAg_DOv[i].OP;
12830                if (SOi != SO && SUMA_isRelated_SO (SOi, SO, 1)) {
12831                   /* do this for kins of the 1st order */
12832                   if (SOi->SurfCont) {
12833                      if (  SOi->SurfCont != SO->SurfCont &&
12834                            SOi->SurfCont->ColPlane_fr &&
12835                            SOi->SurfCont->curColPlane ==
12836                                        SO->SurfCont->curColPlane) {
12837                         SUMA_InitializeColPlaneShell((SUMA_ALL_DO *)SOi,
12838                                                      SOi->SurfCont->curColPlane);
12839                      }
12840                   }
12841                }
12842             }
12843          }
12844          break;
12845       case GDSET_type:
12846          SUMA_S_Warn("This should not happen in this modern day and age");
12847          break;
12848       case CDOM_type:
12849       case VO_type:
12850       case TRACT_type:
12851       case MASK_type:
12852       case GRAPH_LINK_type:
12853          /* Nothing should be done here because these objects don't
12854             have the types of kinship that surfaces have. Otherwise
12855             You end up resetting things like I range when you change
12856             the Dim value of tracts, graphs, or volumes */
12857          #if 0
12858          SUMA_InitializeColPlaneShell(ado, SurfCont->curColPlane);
12859          #endif
12860          break;
12861       default:
12862          SUMA_S_Errv("Nothing to do with %s\n",
12863                SUMA_ObjectTypeCode2ObjectTypeName(ado->do_type));
12864          SUMA_RETURN(NOPE);
12865    }
12866 
12867    SUMA_RETURN(YUP);
12868 }
12869 
12870 /*!
12871    \brief Creates the widgets for the DrawROI window
12872 */
SUMA_CreateDrawROIWindow(void)12873 void SUMA_CreateDrawROIWindow(void)
12874 {
12875    static char FuncName[] = {"SUMA_CreateDrawROIWindow"};
12876    Widget rc, pb, rc_ur, rcv, rc_switch, rc_save, www;
12877    int i;
12878    char *sss, slabel[]={"Draw ROI"};
12879    SUMA_Boolean LocalHead = NOPE;
12880 
12881    SUMA_ENTRY;
12882 
12883    if (SUMAg_CF->X->DrawROI->AppShell) {
12884       SUMA_S_Err("SUMAg_CF->X->DrawROI->AppShell!=NULL. Should not be here.\n");
12885       SUMA_RETURNe;
12886    }
12887 
12888    if (SUMA_isEnv("SUMA_SurfContFontSize", "BIG")) {
12889       sss = "font9";
12890    } else {
12891       sss = "font8";
12892    }
12893 
12894    SUMA_LH("Create AppShell");
12895    /* create as a separate application shell,
12896    you do not want a parent to this controller that
12897    can be closed or withdrawn temporarily */
12898    SUMAg_CF->X->DrawROI->AppShell = XtVaAppCreateShell(sss , "Suma" ,
12899       topLevelShellWidgetClass , SUMAg_CF->X->DPY_controller1 ,
12900       XmNtitle, slabel,
12901       NULL ) ;
12902 
12903    /* turn off default delete response. If you do not do that, you will suffer.*/
12904    XtVaSetValues( SUMAg_CF->X->DrawROI->AppShell,
12905            XmNdeleteResponse, XmDO_NOTHING,
12906            NULL);
12907 
12908    /* handle the close button from window manager */
12909    XmAddWMProtocolCallback(/* make "Close" window menu work */
12910       SUMAg_CF->X->DrawROI->AppShell,
12911       XmInternAtom( SUMAg_CF->X->DPY_controller1 , "WM_DELETE_WINDOW" , False ) ,
12912       SUMA_cb_CloseDrawROIWindow, NULL) ;
12913 
12914 SUMA_Register_Widget_Help( SUMAg_CF->X->DrawROI->AppShell , 0,
12915                                  "ROICont",
12916                                  "ROI Cont.",
12917 "The ROI controller is for drawing ROIs on surfaces.:LR:\n"
12918 ":SPX:"
12919 "You can launch the :ref:`Draw ROI Controller <ROICont>` with:"
12920 " :ref:`ctrl+d <LC_Ctrl+d>` or :menuselection:`Tools-->Draw ROI`\n"
12921 "\n"
12922 ".. figure:: media/ROICont.auto.ALL.jpg\n"
12923 "   :align: center\n"
12924 "   :name: media/ROICont.auto.ALL.jpg\n"
12925 "\n"
12926 "   :ref:`(link)<media/ROICont.auto.ALL.jpg>`\n"
12927 "\n"
12928 ":DEF:"
12929 "You can launch the Draw ROI Controller with:"
12930 "\n'ctrl+d' or 'Tools-->Draw ROI'\n"
12931 ":SPX:"
12932 "\n") ;
12933 
12934    /* create a form widget, manage it at the end ...*/
12935    SUMAg_CF->X->DrawROI->form = XtVaCreateWidget ("dialog",
12936       xmFormWidgetClass, SUMAg_CF->X->DrawROI->AppShell,
12937       XmNborderWidth , 0 ,
12938       XmNmarginHeight , SUMA_MARGIN ,
12939       XmNmarginWidth  , SUMA_MARGIN ,
12940       XmNshadowThickness, 2,
12941       XmNshadowType, XmSHADOW_ETCHED_IN,
12942       NULL);
12943 
12944    /* a frame to put stuff in */
12945    SUMAg_CF->X->DrawROI->frame = XtVaCreateWidget ("dialog",
12946       xmFrameWidgetClass, SUMAg_CF->X->DrawROI->form,
12947       XmNleftAttachment , XmATTACH_FORM ,
12948       XmNtopAttachment  , XmATTACH_FORM ,
12949       XmNshadowType , XmSHADOW_ETCHED_IN ,
12950       XmNshadowThickness , 5 ,
12951       XmNtraversalOn , False ,
12952       NULL);
12953 
12954    www = XtVaCreateManagedWidget ("ROI",
12955       xmLabelWidgetClass, SUMAg_CF->X->DrawROI->frame,
12956       XmNchildType, XmFRAME_TITLE_CHILD,
12957       XmNchildHorizontalAlignment, XmALIGNMENT_BEGINNING,
12958       NULL);
12959 
12960    SUMA_Register_Widget_Help( www , 0,
12961                               "ROICont->ROI",
12962                               "ROI",
12963                   "Controls for drawing ROIs."
12964                   ":SPX:\n\n"
12965                   ".. figure:: media/ROICont.auto.ROI.jpg\n"
12966                   "   :align: right\n"
12967                   "   :name: media/ROICont.auto.ROI.jpg\n"
12968                   "\n"
12969                   "   :ref:`(link)<media/ROICont.auto.ROI.jpg>`\n"
12970                   "\n"
12971                   ":SPX:") ;
12972 
12973    /* vertical row column to stack horizontal rcs in */
12974    rcv = XtVaCreateWidget ("rowcolumn",
12975          xmRowColumnWidgetClass, SUMAg_CF->X->DrawROI->frame,
12976          XmNorientation , XmVERTICAL ,
12977          XmNmarginHeight, 0 ,
12978          XmNmarginWidth , 0 ,
12979          NULL);
12980 
12981    /* row column for the parent surface name */
12982    rc = XtVaCreateWidget ("rowcolumn",
12983          xmRowColumnWidgetClass, rcv,
12984          XmNpacking, XmPACK_TIGHT,
12985          XmNorientation , XmHORIZONTAL ,
12986          XmNmarginHeight, 0 ,
12987          XmNmarginWidth , 0 ,
12988          NULL);
12989 
12990    /*put a label containing the ROI's parent surface name */
12991    SUMAg_CF->X->DrawROI->ParentLabel_lb =
12992       XtVaCreateManagedWidget ("Parent: N/A",
12993             xmLabelWidgetClass, rc,
12994             NULL);
12995    SUMA_Register_Widget_Help(SUMAg_CF->X->DrawROI->ParentLabel_lb, 1,
12996                              "ROICont->ROI->Parent",
12997                              "Label of the ROI's parent surface",
12998                              SUMA_DrawROI_ParentLabel_help ) ;
12999    XtManageChild(rc);
13000 
13001    /* row column for the surface labels and the toggle DrawROI buttons */
13002    rc = XtVaCreateWidget ("rowcolumn",
13003          xmRowColumnWidgetClass, rcv,
13004          XmNpacking, XmPACK_TIGHT,
13005          XmNorientation , XmHORIZONTAL ,
13006          XmNmarginHeight, 0 ,
13007          XmNmarginWidth , 0 ,
13008          NULL);
13009 
13010    /*put a toggle button for the DrawROI more */
13011    /* Turn on the ROI drawing mode, since that is what
13012    the users want to do the first time they open this window */
13013    SUMAg_CF->ROI_mode = YUP; SUMA_ResetPrying(NULL);
13014    /* make a call to change the cursor */
13015    SUMA_UpdateAllViewerCursor();
13016    SUMAg_CF->X->DrawROI->DrawROImode_tb = XtVaCreateManagedWidget("Draw",
13017       xmToggleButtonWidgetClass, rc, NULL);
13018    XmToggleButtonSetState (SUMAg_CF->X->DrawROI->DrawROImode_tb,
13019                            SUMAg_CF->ROI_mode, NOPE);
13020    XtAddCallback (SUMAg_CF->X->DrawROI->DrawROImode_tb,
13021                   XmNvalueChangedCallback, SUMA_cb_DrawROImode_toggled,
13022                   NULL);
13023    SUMA_Register_Widget_Help(SUMAg_CF->X->DrawROI->DrawROImode_tb , 1,
13024                      "ROICont->ROI->Draw",
13025                      "Toggles ROI drawing mode",
13026                      SUMA_DrawROI_DrawROIMode_help ) ;
13027 
13028    /* set the toggle button's select color */
13029    SUMA_SET_SELECT_COLOR(SUMAg_CF->X->DrawROI->DrawROImode_tb);
13030 
13031 
13032    /* put a toggle button for showing/hiding contours */
13033    SUMAg_CF->X->DrawROI->ContROImode_tb =
13034                XtVaCreateManagedWidget("Cont.",
13035                                        xmToggleButtonWidgetClass, rc, NULL);
13036    XmToggleButtonSetState (SUMAg_CF->X->DrawROI->ContROImode_tb,
13037                            SUMAg_CF->ROI_contmode, NOPE);
13038    XtAddCallback (SUMAg_CF->X->DrawROI->ContROImode_tb,
13039                   XmNvalueChangedCallback, SUMA_cb_ContROImode_toggled,
13040                   NULL);
13041    SUMA_Register_Widget_Help(SUMAg_CF->X->DrawROI->ContROImode_tb , 1,
13042                      "ROICont->ROI->Cont.",
13043                      "Toggles showing ROI contours",
13044                      SUMA_DrawROI_ContROIMode_help ) ;
13045 
13046    /* set the toggle button's select color */
13047    SUMA_SET_SELECT_COLOR(SUMAg_CF->X->DrawROI->ContROImode_tb);
13048 
13049 
13050    /*put a toggle button for the Pen mode */
13051    SUMAg_CF->X->DrawROI->Penmode_tb =
13052       XtVaCreateManagedWidget("Pen",
13053                               xmToggleButtonWidgetClass, rc, NULL);
13054    XmToggleButtonSetState (SUMAg_CF->X->DrawROI->Penmode_tb,
13055                            SUMAg_CF->Pen_mode, NOPE);
13056    XtAddCallback (SUMAg_CF->X->DrawROI->Penmode_tb,
13057                   XmNvalueChangedCallback, SUMA_cb_DrawROIPen_toggled,
13058                   NULL);
13059    SUMA_Register_Widget_Help(SUMAg_CF->X->DrawROI->Penmode_tb , 1,
13060                      "ROICont->ROI->Pen",
13061                      "Toggles Pen drawing mode",
13062                      SUMA_DrawROI_PenMode_help ) ;
13063 
13064    /* set the toggle button's select color */
13065    SUMA_SET_SELECT_COLOR(SUMAg_CF->X->DrawROI->Penmode_tb);
13066 
13067    /* set sensitivity of Pen button */
13068    if (SUMAg_CF->ROI_mode) XtSetSensitive (SUMAg_CF->X->DrawROI->Penmode_tb, 1);
13069    else XtSetSensitive (SUMAg_CF->X->DrawROI->Penmode_tb, 0);
13070 
13071    /* Put a toggle button for real time communication with AFNI */
13072    SUMAg_CF->X->DrawROI->AfniLink_tb = XtVaCreateManagedWidget("Afni",
13073       xmToggleButtonWidgetClass, rc, NULL);
13074 
13075    #if 0
13076    /* can the link be on ? */
13077    if (SUMAg_CF->Connected) SUMAg_CF->ROI2afni = YUP;
13078    else SUMAg_CF->ROI2afni = NOPE;
13079    #endif
13080    SUMAg_CF->ROI2afni = NOPE; /* keep link off when starting,
13081                                  otherwise  it is confusing */
13082 
13083    XmToggleButtonSetState (SUMAg_CF->X->DrawROI->AfniLink_tb,
13084                            SUMAg_CF->ROI2afni, NOPE);
13085    XtAddCallback (SUMAg_CF->X->DrawROI->AfniLink_tb,
13086                   XmNvalueChangedCallback, SUMA_cb_AfniLink_toggled,
13087                   NULL);
13088    SUMA_Register_Widget_Help(SUMAg_CF->X->DrawROI->AfniLink_tb , 1,
13089                      "ROICont->ROI->Afni",
13090                      "Toggles Link to Afni",
13091                      SUMA_DrawROI_AfniLink_help ) ;
13092 
13093    /* set the toggle button's select color */
13094    SUMA_SET_SELECT_COLOR(SUMAg_CF->X->DrawROI->AfniLink_tb);
13095 
13096    SUMA_LH("Building menu");
13097    /* put a menu for writing distance info */
13098    SUMA_BuildMenuReset(0);
13099    SUMAg_CF->X->DrawROI->WhatDistMenu =
13100       SUMA_Alloc_Menu_Widget(SW_N_DrawROI_WhatDist);
13101    SUMA_BuildMenu (rc, XmMENU_OPTION,
13102                    "Dist", '\0', YUP, DrawROI_WhatDist_Menu,
13103                    "DoDist",
13104                    "ROICont->ROI->Dist",
13105                    "Report length of drawn segments? (BHelp for more)",
13106                    SUMA_DrawROI_WhatDist_help,
13107                    SUMAg_CF->X->DrawROI->WhatDistMenu);
13108    XtManageChild (SUMAg_CF->X->DrawROI->WhatDistMenu->mw[SW_DrawROI_WhatDist]);
13109 
13110     /* manage rc */
13111    XtManageChild (rc);
13112 
13113    /* add a rc for the ROI label and the ROI node value */
13114    rc = XtVaCreateWidget ("rowcolumn",
13115       xmRowColumnWidgetClass, rcv,
13116       XmNpacking, XmPACK_TIGHT,
13117       XmNorientation , XmHORIZONTAL ,
13118       XmNmarginHeight, 0 ,
13119       XmNmarginWidth , 0 ,
13120       NULL);
13121 
13122 
13123    SUMA_CreateTextField ( rc, "Label:",
13124                            6, SUMA_DrawROI_NewLabel,
13125                            "ROICont->ROI->Label",
13126                            "Label of ROI being drawn", SUMA_DrawROI_Label_help,
13127                            SUMAg_CF->X->DrawROI->ROIlbl);
13128 
13129    SUMA_CreateArrowField ( rc, "Value:",
13130                            1, 0, 999, 1,
13131                            3, SUMA_int,
13132                            NOPE,
13133                            SUMA_DrawROI_NewValue, NULL,
13134                            "ROICont->ROI->Value",
13135                            "Integer value associated with ROI",
13136                            SUMA_DrawROI_Value_help,
13137                            SUMAg_CF->X->DrawROI->ROIval);
13138    /* manage  rc */
13139    XtManageChild (rc);
13140 
13141 
13142    /* a separator */
13143    XtVaCreateManagedWidget ("sep", xmSeparatorWidgetClass, rcv, NULL);
13144 
13145    /* add rc for undo, redo buttons */
13146    rc_ur = XtVaCreateWidget ("rowcolumn",
13147       xmRowColumnWidgetClass, rcv,
13148       XmNpacking, XmPACK_TIGHT,
13149       XmNorientation , XmHORIZONTAL ,
13150       XmNmarginHeight, SUMA_MARGIN ,
13151       XmNmarginWidth , SUMA_MARGIN ,
13152       NULL);
13153 
13154    SUMAg_CF->X->DrawROI->Undo_pb = XtVaCreateWidget ("Undo",
13155       xmPushButtonWidgetClass, rc_ur,
13156       NULL);
13157    XtAddCallback (SUMAg_CF->X->DrawROI->Undo_pb,
13158                   XmNactivateCallback, SUMA_cb_DrawROI_Undo, NULL);
13159    SUMA_Register_Widget_Help(SUMAg_CF->X->DrawROI->Undo_pb, 1,
13160                              "ROICont->ROI->Undo",
13161                              "Undo the last action on the stack",
13162                              SUMA_DrawROI_Undo_help ) ;
13163    XtManageChild (SUMAg_CF->X->DrawROI->Undo_pb);
13164 
13165    SUMAg_CF->X->DrawROI->Redo_pb = XtVaCreateWidget ("Redo",
13166       xmPushButtonWidgetClass, rc_ur,
13167       NULL);
13168    XtAddCallback (SUMAg_CF->X->DrawROI->Redo_pb,
13169                   XmNactivateCallback, SUMA_cb_DrawROI_Redo, NULL);
13170    SUMA_Register_Widget_Help(SUMAg_CF->X->DrawROI->Redo_pb , 1,
13171                              "ROICont->ROI->Redo",
13172                              "Redo the last undone action",
13173                              SUMA_DrawROI_Redo_help ) ;
13174    XtManageChild (SUMAg_CF->X->DrawROI->Redo_pb);
13175 
13176    XtVaCreateManagedWidget (  "sep",
13177                               xmSeparatorWidgetClass, rc_ur,
13178                               XmNorientation, XmVERTICAL,NULL);
13179 
13180    SUMAg_CF->X->DrawROI->Join_pb = XtVaCreateWidget ("Join",
13181       xmPushButtonWidgetClass, rc_ur,
13182       NULL);
13183    XtAddCallback (SUMAg_CF->X->DrawROI->Join_pb,
13184                   XmNactivateCallback, SUMA_cb_DrawROI_Join, NULL);
13185    SUMA_Register_Widget_Help(SUMAg_CF->X->DrawROI->Join_pb , 1,
13186                              "ROICont->ROI->Join",
13187                              "Join the first node of the path to the last",
13188                              SUMA_DrawROI_Join_help ) ;
13189    XtManageChild (SUMAg_CF->X->DrawROI->Join_pb);
13190 
13191    SUMAg_CF->X->DrawROI->Finish_pb = XtVaCreateWidget ("Finish",
13192       xmPushButtonWidgetClass, rc_ur,
13193       NULL);
13194    XtAddCallback (SUMAg_CF->X->DrawROI->Finish_pb,
13195                   XmNactivateCallback, SUMA_cb_DrawROI_Finish, NULL);
13196    SUMA_Register_Widget_Help(SUMAg_CF->X->DrawROI->Finish_pb , 1,
13197                              "ROICont->ROI->Finish",
13198                              "Label ROI as finished.",
13199                              SUMA_DrawROI_Finish_help ) ;
13200    XtManageChild (SUMAg_CF->X->DrawROI->Finish_pb);
13201 
13202 
13203    /* a separator */
13204    XtVaCreateManagedWidget ("sep", xmSeparatorWidgetClass, rcv, NULL);
13205 
13206    /* manage rc_ur */
13207    XtManageChild (rc_ur);
13208 
13209    /* add rc for switchin */
13210    rc_switch = XtVaCreateWidget ("rowcolumn",
13211       xmRowColumnWidgetClass, rcv,
13212       XmNpacking, XmPACK_TIGHT,
13213       XmNorientation , XmHORIZONTAL ,
13214       XmNmarginHeight, SUMA_MARGIN ,
13215       XmNmarginWidth , SUMA_MARGIN ,
13216       NULL);
13217 
13218 
13219 
13220    /* put a push button to switch between ROIs */
13221    SUMAg_CF->X->DrawROI->SwitchROIlst =
13222       SUMA_AllocateScrolledList ("Switch ROI", SUMA_LSP_SINGLE,
13223                                  NOPE, YUP,
13224                                  SUMAg_CF->X->DrawROI->AppShell, SWP_TOP_LEFT,
13225                                  125,
13226                                  SUMA_cb_SelectSwitchROI, NULL,
13227                                  SUMA_cb_SelectSwitchROI, NULL,
13228                                  SUMA_cb_CloseSwitchROI, NULL);
13229 
13230    pb = XtVaCreateWidget ( "Switch ROI", xmPushButtonWidgetClass,
13231                            rc_switch, NULL);
13232    XtAddCallback (pb, XmNactivateCallback, SUMA_cb_DrawROI_SwitchROI,
13233                   SUMAg_CF->X->DrawROI->SwitchROIlst);
13234    SUMA_Register_Widget_Help(pb, 1,
13235                              "ROICont->ROI->Switch_ROI",
13236                              "Switch between ROIs.",
13237                              SUMA_DrawROI_SwitchROI_help ) ;
13238    XtManageChild (pb);
13239 
13240    SUMAg_CF->X->DrawROI->Load_pb = XtVaCreateWidget ("Load",
13241       xmPushButtonWidgetClass, rc_switch,
13242       NULL);
13243    XtAddCallback (SUMAg_CF->X->DrawROI->Load_pb,
13244                   XmNactivateCallback, SUMA_cb_DrawROI_Load, NULL);
13245    SUMA_Register_Widget_Help(SUMAg_CF->X->DrawROI->Load_pb , 1,
13246                              "ROICont->ROI->Load",
13247                              "Load a Drawn ROI",
13248                              SUMA_DrawROI_Load_help ) ;
13249    XtManageChild (SUMAg_CF->X->DrawROI->Load_pb);
13250 
13251    XtVaCreateManagedWidget (  "sep",
13252                            xmSeparatorWidgetClass, rc_switch,
13253                            XmNorientation, XmVERTICAL,NULL);
13254 
13255    SUMAg_CF->X->DrawROI->Delete_pb = XtVaCreateWidget ("delete ROI",
13256       xmPushButtonWidgetClass, rc_switch,
13257       NULL);
13258    XtAddCallback (SUMAg_CF->X->DrawROI->Delete_pb,
13259                   XmNactivateCallback, SUMA_cb_DrawROI_Delete, NULL);
13260    SUMA_Register_Widget_Help(SUMAg_CF->X->DrawROI->Delete_pb , 1,
13261                              "ROICont->ROI->delete_ROI",
13262                              "Click twice in 5 seconds to delete ROI. "
13263                              "No Undo for this action.",
13264                              SUMA_DrawROI_DeleteROI_help);
13265    MCW_set_widget_bg( SUMAg_CF->X->DrawROI->Delete_pb ,
13266                       MCW_hotcolor(SUMAg_CF->X->DrawROI->Delete_pb) , 0 ) ;
13267 
13268    XtManageChild (SUMAg_CF->X->DrawROI->Delete_pb);
13269 
13270 
13271    /* manage rc_switch */
13272    XtManageChild (rc_switch);
13273 
13274    /* a separator */
13275    XtVaCreateManagedWidget ("sep", xmSeparatorWidgetClass, rcv, NULL);
13276 
13277    /* add rc for savin */
13278    rc_save = XtVaCreateWidget ("rowcolumn",
13279       xmRowColumnWidgetClass, rcv,
13280       XmNpacking, XmPACK_TIGHT,
13281       XmNorientation , XmHORIZONTAL ,
13282       XmNmarginHeight, SUMA_MARGIN ,
13283       XmNmarginWidth , SUMA_MARGIN ,
13284       NULL);
13285 
13286    SUMAg_CF->X->DrawROI->Save_pb = XtVaCreateWidget ("Save",
13287       xmPushButtonWidgetClass, rc_save,
13288       NULL);
13289    XtAddCallback (SUMAg_CF->X->DrawROI->Save_pb,
13290                   XmNactivateCallback, SUMA_cb_DrawROI_Save, NULL);
13291    SUMA_Register_Widget_Help(SUMAg_CF->X->DrawROI->Save_pb , 1,
13292                              "ROICont->ROI->Save",
13293                              "Save the Drawn ROI to disk.",
13294                              SUMA_DrawROI_Save_help ) ;
13295    XtManageChild (SUMAg_CF->X->DrawROI->Save_pb);
13296 
13297    /* Saving Mode */
13298    SUMA_BuildMenuReset(0);
13299    SUMAg_CF->X->DrawROI->SaveModeMenu =
13300          SUMA_Alloc_Menu_Widget(SW_N_DrawROI_SaveMode);
13301    SUMA_BuildMenu (rc_save, XmMENU_OPTION,
13302                                "", '\0', YUP, DrawROI_SaveMode_Menu,
13303                                "Frm.",
13304                                "ROICont->ROI->Save->NIML",
13305                                "Format for saving ROI, "
13306                                "use NIML to preserve tracing order. "
13307                                "(BHelp or WHelp for more)",
13308                                SUMA_DrawROI_SaveFormat_help,
13309                                SUMAg_CF->X->DrawROI->SaveModeMenu);
13310    XtManageChild (SUMAg_CF->X->DrawROI->SaveModeMenu->mw[SW_DrawROI_SaveMode]);
13311 
13312    /* Saving what ? */
13313    SUMA_BuildMenuReset(0);
13314    SUMAg_CF->X->DrawROI->SaveWhatMenu =
13315           SUMA_Alloc_Menu_Widget(SW_N_DrawROI_SaveWhat);
13316    SUMA_BuildMenu (rc_save, XmMENU_OPTION,
13317                                "", '\0', YUP, DrawROI_SaveWhat_Menu,
13318                                "What",
13319                                "ROICont->ROI->Save->All",
13320                                "Which ROIs to save?",
13321                                SUMA_DrawROI_SaveWhat_help,
13322                                SUMAg_CF->X->DrawROI->SaveWhatMenu);
13323    XtManageChild (SUMAg_CF->X->DrawROI->SaveWhatMenu->mw[SW_DrawROI_SaveWhat]);
13324 
13325 
13326    XtVaCreateManagedWidget (  "sep",
13327                               xmSeparatorWidgetClass, rc_save,
13328                               XmNorientation, XmVERTICAL,NULL);
13329 
13330    pb = XtVaCreateWidget ("BHelp",
13331       xmPushButtonWidgetClass, rc_save,
13332       NULL);
13333    XtAddCallback (pb, XmNactivateCallback, MCW_click_help_CB, NULL);
13334    SUMA_Register_Widget_Help(pb, 1, "ROICont->ROI->BHelp",
13335          "Press this button then click on a button/label/menu for more help.",
13336                              SUMA_help_help ) ;
13337    XtManageChild (pb);
13338 
13339    pb = XtVaCreateWidget ("WHelp",
13340       xmPushButtonWidgetClass, rc_save,
13341       NULL);
13342    XtAddCallback (pb, XmNactivateCallback, SUMA_click_webhelp_CB,
13343                   "ROICont->ROI->WHelp");
13344    MCW_set_widget_bg( pb , MCW_buthighlight(pb) , 0 ) ;
13345    SUMA_Register_Widget_Help(pb, 1, "ROICont->ROI->WHelp",
13346          "Press this button then click on a button/label/menu for online help.",
13347                              SUMA_webhelp_help ) ;
13348    XtManageChild (pb);
13349 
13350    SUMAg_CF->X->DrawROI->Close_pb = XtVaCreateWidget ("Close",
13351       xmPushButtonWidgetClass, rc_save,
13352       NULL);
13353    XtAddCallback (SUMAg_CF->X->DrawROI->Close_pb, XmNactivateCallback,
13354                   SUMA_cb_CloseDrawROIWindow, NULL);
13355    SUMA_Register_Widget_Help(SUMAg_CF->X->DrawROI->Close_pb, 1,
13356                              "ROICont->ROI->Close",
13357                              "Close Draw ROI window",
13358                              SUMA_closeDrawROI_help ) ;
13359    XtManageChild (SUMAg_CF->X->DrawROI->Close_pb);
13360 
13361    /* manage rc_save */
13362    XtManageChild (rc_save);
13363 
13364    /* manage vertical rc */
13365    XtManageChild (rcv);
13366 
13367    /* manage frame */
13368    XtManageChild (SUMAg_CF->X->DrawROI->frame);
13369 
13370    /* manage form */
13371    XtManageChild (SUMAg_CF->X->DrawROI->form);
13372 
13373    /* position the widget relative to the first open viewer */
13374    SUMA_LHv("Position widgets (%d viewers)\n", SUMAg_N_SVv);
13375    i=0;
13376    while (i < SUMAg_N_SVv &&
13377          !SUMAg_SVv[i].X->ViewCont->TopLevelShell && SUMAg_SVv[i].isShaded) ++i;
13378 
13379    if (i < SUMAg_N_SVv) {
13380       if (LocalHead) fprintf (SUMA_STDERR, "%s: i = %d\n", FuncName, i);
13381       SUMA_PositionWindowRelative ( SUMAg_CF->X->DrawROI->AppShell,
13382                                     SUMAg_SVv[i].X->TOPLEVEL, SWP_TOP_RIGHT);
13383    }
13384 
13385    /* realize the widget */
13386    XtRealizeWidget (SUMAg_CF->X->DrawROI->AppShell);
13387 
13388    SUMA_LH("All done");
13389    SUMA_RETURNe;
13390 }
13391 
13392 /*!
13393    \brief: Creates and initializes the structure for a scrolled list
13394 
13395    \param Label (char *) Label of window containing list.
13396          Label should be freed (if necessary) after this function returns.
13397    \param SelectPolicy (SUMA_ListSelectPolicy) list selection policy
13398    \param RemoveDups (SUMA_Boolean) YUP: Allow duplicate entries, NOPE: Purge duplicate entries
13399    \param ShowSorted (SUMA_Boolean) YUP: Sort list entries
13400    \param PosRef (Widget) Widget to position list relative to
13401    \param Pos (SUMA_WINDOW_POSITION) position of list relative to PosRef
13402    \param Default_cb pointer to default selection callack function
13403    \param Default_Data (void *) pointer to default callback data, If you specify NULL then
13404          the SUMA_LIST_WIDGET * is sent in data.
13405    \param Select_cb pointer to selection callback function. That
13406          function should be ready to deal with te SelectionPolicy you have set.
13407          See Motif Programming Manual, section 12.5.
13408          Typically, you will use the same function for Select_cb and Default_cb
13409    \param Select_Data (void *) pointer to select callback data, If you specify NULL then
13410          the SUMA_LIST_WIDGET * is sent in data.
13411    \param CloseList_cb pointer to close callback function
13412    \param CloseList_Data (void *) pointer to close callback data, If you specify NULL then
13413          the SUMA_LIST_WIDGET * is sent in data.
13414    \return LW (SUMA_LIST_WIDGET *) allocate and initialized List Widget structure
13415 
13416    \sa SUMA_FreeScrolledList
13417 
13418 */
SUMA_AllocateScrolledList(char * Label,int SelectPolicy,SUMA_Boolean RemoveDups,SUMA_Boolean ShowSorted,Widget PosRef,SUMA_WINDOW_POSITION Pos,int width,void (* Default_cb)(Widget w,XtPointer data,XtPointer calldata),void * Default_Data,void (* Select_cb)(Widget w,XtPointer data,XtPointer calldata),void * Select_Data,void (* CloseList_cb)(Widget w,XtPointer data,XtPointer calldata),void * CloseList_Data)13419 SUMA_LIST_WIDGET * SUMA_AllocateScrolledList (
13420       char *Label, int SelectPolicy,
13421       SUMA_Boolean RemoveDups, SUMA_Boolean ShowSorted,
13422       Widget PosRef, SUMA_WINDOW_POSITION Pos,
13423       int width,
13424       void (*Default_cb)
13425             (Widget w, XtPointer data, XtPointer calldata),
13426       void *Default_Data,
13427       void (*Select_cb)
13428             (Widget w, XtPointer data, XtPointer calldata),
13429       void *Select_Data,
13430       void (*CloseList_cb)
13431             (Widget w, XtPointer data, XtPointer calldata),
13432       void *CloseList_Data)
13433 {
13434    static char FuncName[]={"SUMA_AllocateScrolledList"};
13435    SUMA_LIST_WIDGET *LW = NULL;
13436 
13437    SUMA_ENTRY;
13438 
13439    if (!Label) {
13440       SUMA_SLP_Err("Null Label");
13441       SUMA_RETURN(LW);
13442    }
13443 
13444    LW = (SUMA_LIST_WIDGET *) SUMA_malloc(sizeof(SUMA_LIST_WIDGET));
13445    memset(LW, 0, sizeof(SUMA_LIST_WIDGET));
13446    LW->toplevel = NULL;
13447    LW->list = NULL;
13448    LW->rc = NULL;
13449    LW->RemoveDups = RemoveDups;
13450    LW->SelectPolicy = SelectPolicy;
13451    LW->ShowSorted = ShowSorted;
13452    LW->Label = (char *)SUMA_calloc(strlen(Label)+1, sizeof(char));
13453    LW->Label = strcpy (LW->Label, Label);
13454    LW->PosRef = PosRef;
13455    LW->Pos = Pos;
13456    LW->CloseList_cb = CloseList_cb;
13457    LW->CloseList_Data = CloseList_Data;
13458    LW->Default_cb = Default_cb;
13459    LW->Default_Data = Default_Data;
13460    LW->Select_cb = Select_cb;
13461    LW->Select_Data = Select_Data;
13462    LW->ALS = NULL;
13463    LW->isShaded = YUP;
13464    LW->lastitempos = -1;
13465    if (width > 0) LW->width = width;
13466    else LW->width = 125;
13467 
13468    SUMA_RETURN(LW);
13469 
13470 }
13471 
13472 /*!
13473    \brief Frees the SUMA_LIST_WIDGET *
13474 */
SUMA_FreeScrolledList(SUMA_LIST_WIDGET * LW)13475 SUMA_LIST_WIDGET * SUMA_FreeScrolledList (SUMA_LIST_WIDGET *LW)
13476 {
13477    static char FuncName[]={"SUMA_FreeScrolledList"};
13478 
13479    SUMA_ENTRY;
13480    if (LW->Label) SUMA_free(LW->Label);
13481    if (LW->ALS) SUMA_FreeAssembleListStruct(LW->ALS);
13482    if (LW) SUMA_free(LW);
13483 
13484    SUMA_RETURN(NULL);
13485 
13486 }
13487 
13488 /*!
13489    \brief changes the Default_Data Select_Data  callback data for a list widget.
13490    Does not change callbacks although that can be arranged
13491    - Do not change callback data outside of this function
13492    - Make sure you remove callbacks properly or you'll end
13493    up with multiple callbacks
13494    \sa SUMA_CreateScrolledList
13495 */
SUMA_UpdateScrolledListData(SUMA_LIST_WIDGET * LW,void * Default_Data,void * Select_Data,void * CloseList_Data)13496 SUMA_Boolean SUMA_UpdateScrolledListData(SUMA_LIST_WIDGET *LW,
13497             void *Default_Data, void *Select_Data, void *CloseList_Data)
13498 {
13499    static char FuncName[]={"SUMA_UpdateScrolledListData"};
13500    SUMA_Boolean LocalHead = NOPE;
13501 
13502    SUMA_ENTRY;
13503 
13504    if (!LW) SUMA_RETURN(NOPE);
13505    if (!LW->toplevel) { /* no callbacks yet, just assign the data
13506                            values to their positions in LW */
13507       LW->Default_Data = Default_Data;
13508       LW->Select_Data = Select_Data;
13509       LW->CloseList_Data = CloseList_Data;
13510       SUMA_RETURN(YUP);
13511    }
13512 
13513    /* need to remove old callbacks before adding new ones
13514       SEE ALSO SUMA_CreateScrolledList*/
13515    if (LW->Default_Data !=  Default_Data) {
13516       SUMA_LH("Doing Default Data...");
13517       if (!LW->Default_Data) {
13518          XtRemoveCallback(LW->list, XmNdefaultActionCallback,
13519                            LW->Default_cb, (XtPointer)LW);
13520       } else {
13521          XtRemoveCallback (LW->list, XmNdefaultActionCallback,
13522                            LW->Default_cb, (XtPointer)LW->Default_Data);
13523       }
13524       if (!Default_Data) {
13525          XtAddCallback (LW->list, XmNdefaultActionCallback,
13526                         LW->Default_cb, (XtPointer)LW);
13527       } else {
13528          XtAddCallback (LW->list, XmNdefaultActionCallback,
13529                         LW->Default_cb, (XtPointer)Default_Data);
13530       }
13531       LW->Default_Data =  Default_Data;
13532    }
13533 
13534    if (LW->Select_Data !=  Select_Data) {
13535       SUMA_LH("Doing Select Data...");
13536       switch (LW->SelectPolicy){
13537          case SUMA_LSP_SINGLE:
13538             if (!LW->Select_Data)
13539                XtRemoveCallback (LW->list, XmNsingleSelectionCallback,
13540                                  LW->Select_cb, (XtPointer)LW);
13541             else
13542                XtRemoveCallback (LW->list, XmNsingleSelectionCallback,
13543                                  LW->Select_cb, (XtPointer)LW->Select_Data);
13544             break;
13545          case SUMA_LSP_BROWSE:
13546             if (!LW->Select_Data)
13547                XtRemoveCallback (LW->list, XmNbrowseSelectionCallback,
13548                                  LW->Select_cb, (XtPointer)LW);
13549             else
13550                XtRemoveCallback (LW->list, XmNbrowseSelectionCallback,
13551                                  LW->Select_cb, (XtPointer)LW->Select_Data);
13552 
13553             break;
13554          case SUMA_LSP_MULTIPLE:
13555             if (!LW->Select_Data)
13556                XtRemoveCallback (LW->list, XmNmultipleSelectionCallback,
13557                                  LW->Select_cb, (XtPointer)LW);
13558             else
13559                XtRemoveCallback (LW->list, XmNmultipleSelectionCallback,
13560                                  LW->Select_cb, (XtPointer)LW->Select_Data);
13561 
13562             break;
13563          case SUMA_LSP_EXTENDED:
13564             if (!LW->Select_Data)
13565                XtRemoveCallback (LW->list, XmNextendedSelectionCallback,
13566                                  LW->Select_cb, (XtPointer)LW);
13567             else
13568                XtRemoveCallback (LW->list, XmNextendedSelectionCallback,
13569                                  LW->Select_cb, (XtPointer)LW->Select_Data);
13570 
13571             break;
13572          default:
13573             SUMA_SL_Err("Bad selection policy");
13574             SUMA_RETURN(NOPE);
13575             break;
13576       }
13577 
13578       switch (LW->SelectPolicy){
13579          case SUMA_LSP_SINGLE:
13580             if (!Select_Data)
13581                XtAddCallback (LW->list, XmNsingleSelectionCallback,
13582                               LW->Select_cb, (XtPointer)LW);
13583             else
13584                XtAddCallback (LW->list, XmNsingleSelectionCallback,
13585                               LW->Select_cb, (XtPointer)Select_Data);
13586             break;
13587          case SUMA_LSP_BROWSE:
13588             if (!Select_Data)
13589                XtAddCallback (LW->list, XmNbrowseSelectionCallback,
13590                               LW->Select_cb, (XtPointer)LW);
13591             else
13592                XtAddCallback (LW->list, XmNbrowseSelectionCallback,
13593                               LW->Select_cb, (XtPointer)Select_Data);
13594 
13595             break;
13596          case SUMA_LSP_MULTIPLE:
13597             if (!Select_Data)
13598                XtAddCallback (LW->list, XmNmultipleSelectionCallback,
13599                               LW->Select_cb, (XtPointer)LW);
13600             else
13601                XtAddCallback (LW->list, XmNmultipleSelectionCallback,
13602                               LW->Select_cb, (XtPointer)Select_Data);
13603 
13604             break;
13605          case SUMA_LSP_EXTENDED:
13606             if (!Select_Data)
13607                XtAddCallback (LW->list, XmNextendedSelectionCallback,
13608                               LW->Select_cb, (XtPointer)LW);
13609             else
13610                XtAddCallback (LW->list, XmNextendedSelectionCallback,
13611                               LW->Select_cb, (XtPointer)Select_Data);
13612 
13613             break;
13614          default:
13615             SUMA_SL_Err("Bad selection policy");
13616             SUMA_RETURN(NOPE);
13617             break;
13618       }
13619 
13620       LW->Select_Data =  Select_Data;
13621 
13622    }
13623 
13624    if (LW->CloseList_Data !=  CloseList_Data) {
13625       SUMA_LH("Doing CloseList Data...");
13626       if (!LW->CloseList_Data) {
13627          XmRemoveWMProtocolCallback(/* make "Close" window menu work */
13628             LW->toplevel,
13629             XmInternAtom( SUMAg_CF->X->DPY_controller1  ,
13630                            "WM_DELETE_WINDOW" , False ) ,
13631             LW->CloseList_cb, (XtPointer)LW) ;
13632       } else {
13633          XmRemoveWMProtocolCallback(/* make "Close" window menu work */
13634             LW->toplevel,
13635             XmInternAtom( SUMAg_CF->X->DPY_controller1  ,
13636                            "WM_DELETE_WINDOW" , False ) ,
13637             LW->CloseList_cb, (XtPointer)LW->CloseList_Data) ;
13638       }
13639       if (!CloseList_Data) {
13640          XmAddWMProtocolCallback(/* make "Close" window menu work */
13641             LW->toplevel,
13642             XmInternAtom( SUMAg_CF->X->DPY_controller1  ,
13643                            "WM_DELETE_WINDOW" , False ) ,
13644             LW->CloseList_cb, (XtPointer)LW) ;
13645       } else {
13646          XmAddWMProtocolCallback(/* make "Close" window menu work */
13647             LW->toplevel,
13648             XmInternAtom( SUMAg_CF->X->DPY_controller1  ,
13649                            "WM_DELETE_WINDOW" , False ) ,
13650             LW->CloseList_cb, (XtPointer)CloseList_Data) ;
13651       }
13652 
13653       LW->CloseList_Data =  CloseList_Data;
13654    }
13655    SUMA_RETURN(YUP);
13656 }
13657 
13658 /*!
13659    \brief creates a scrolled list window
13660    SUMA_CreateScrolledList (  clist, N_clist, Partial, LW);
13661 
13662    \param clist (char **) list of strings. You should free it after you call the function
13663    \param N_clist (int) number of elements in clist
13664    \param Partial (SUMA_Boolean) YUP: add to existing list, NOPE: Replace it.
13665          If !Partial and !LW->RemoveDups then the previous selection position is lost.
13666    \param LW (SUMA_LIST_WIDGET *) initialized list widget structure.
13667 
13668    \sa SUMA_AllocateScrolledList
13669    \sa SUMA_UpdateScrolledListData
13670    - If LW->toplevel = NULL then a new widget is created, otherwise only the list is updated
13671 
13672 
13673 */
SUMA_CreateScrolledList(char ** clist,int N_clist,SUMA_Boolean Partial,SUMA_LIST_WIDGET * LW)13674 void SUMA_CreateScrolledList (
13675       char **clist, int N_clist,
13676       SUMA_Boolean Partial, SUMA_LIST_WIDGET *LW)
13677 {
13678    static char FuncName[]={"SUMA_CreateScrolledList"};
13679    XmString  str, *strlist = NULL;
13680    char *text;
13681    int i = -1, iclist, u_bound = 0, l_bound = 0, n;
13682    Arg args[20];
13683    SUMA_Boolean New = NOPE;
13684    SUMA_Boolean LocalHead = NOPE;
13685 
13686 
13687    SUMA_ENTRY;
13688 
13689    if (!LW) { /* Never been created */
13690       SUMA_SL_Err ("Null LW!");
13691       SUMA_RETURNe;
13692    }
13693 
13694    if (N_clist <= 0) {
13695       SUMA_SLP_Note ("No elements in list (such as ROIs) found");
13696       SUMA_RETURNe;
13697    }
13698 
13699    if (!LW->toplevel) {
13700       /* widget has never been created
13701          or had been destroyed, create it anew */
13702       /* create the widget */
13703       LW->toplevel = XtVaAppCreateShell(LW->Label , "Suma" ,
13704                      topLevelShellWidgetClass , SUMAg_CF->X->DPY_controller1 ,
13705                      NULL ) ;
13706 
13707       /* cancel the kill button's effect */
13708       XtVaSetValues( LW->toplevel,
13709            XmNdeleteResponse, XmDO_NOTHING,
13710            NULL);
13711 
13712       /* handle the close button from window manager
13713          SEE ALSO  SUMA_UpdateScrolledListData */
13714       if (!LW->CloseList_Data) {
13715          XmAddWMProtocolCallback(/* make "Close" window menu work */
13716             LW->toplevel,
13717             XmInternAtom(  SUMAg_CF->X->DPY_controller1  ,
13718                            "WM_DELETE_WINDOW" , False ) ,
13719             LW->CloseList_cb, (XtPointer)LW) ;
13720       } else {
13721          XmAddWMProtocolCallback(/* make "Close" window menu work */
13722             LW->toplevel,
13723             XmInternAtom(  SUMAg_CF->X->DPY_controller1  ,
13724                            "WM_DELETE_WINDOW" , False ) ,
13725             LW->CloseList_cb, (XtPointer)LW->CloseList_Data) ;
13726       }
13727 
13728 
13729       LW->rc = XtVaCreateWidget( "Tonka",
13730                                  xmRowColumnWidgetClass, LW->toplevel, NULL);
13731       n = 0;
13732       XtSetArg (args[n], XmNitemCount,      0); n++;
13733       XtSetArg (args[n], XmNlistSizePolicy,   XmCONSTANT   ); n++;
13734       XtSetArg (args[n], XmNwidth, LW->width); n++;
13735       LW->list = XmCreateScrolledList (LW->rc, "Tonka", args, n);
13736 
13737 
13738       /* add the default selection callback
13739          SEE ALSO  SUMA_UpdateScrolledListData */
13740       if (!LW->Default_Data) {
13741          XtAddCallback (LW->list,
13742                         XmNdefaultActionCallback,
13743                         LW->Default_cb, (XtPointer)LW);
13744       } else {
13745          XtAddCallback (LW->list,
13746                         XmNdefaultActionCallback,
13747                         LW->Default_cb, (XtPointer)LW->Default_Data);
13748       }
13749 
13750      /* set the selection policy SEE ALSO  SUMA_UpdateScrolledListData */
13751       switch (LW->SelectPolicy){
13752          case SUMA_LSP_SINGLE:
13753             XtVaSetValues( LW->list, XmNselectionPolicy, XmSINGLE_SELECT, NULL);
13754             if (!LW->Select_Data)
13755                XtAddCallback (LW->list,
13756                               XmNsingleSelectionCallback,
13757                               LW->Select_cb, (XtPointer)LW);
13758             else
13759                XtAddCallback (LW->list, XmNsingleSelectionCallback,
13760                               LW->Select_cb, (XtPointer)LW->Select_Data);
13761             break;
13762          case SUMA_LSP_BROWSE:
13763             XtVaSetValues( LW->list, XmNselectionPolicy, XmBROWSE_SELECT, NULL);
13764             if (!LW->Select_Data)
13765                XtAddCallback (LW->list,
13766                               XmNbrowseSelectionCallback,
13767                               LW->Select_cb, (XtPointer)LW);
13768             else
13769                XtAddCallback (LW->list,
13770                               XmNbrowseSelectionCallback,
13771                               LW->Select_cb, (XtPointer)LW->Select_Data);
13772 
13773             break;
13774          case SUMA_LSP_MULTIPLE:
13775             if (!LW->Select_Data)
13776                XtAddCallback (LW->list,
13777                               XmNmultipleSelectionCallback,
13778                               LW->Select_cb, (XtPointer)LW);
13779             else
13780                XtAddCallback (LW->list,
13781                               XmNmultipleSelectionCallback,
13782                               LW->Select_cb, (XtPointer)LW->Select_Data);
13783 
13784             XtVaSetValues( LW->list,
13785                            XmNselectionPolicy, XmMULTIPLE_SELECT, NULL);
13786             break;
13787          case SUMA_LSP_EXTENDED:
13788             if (!LW->Select_Data)
13789                XtAddCallback (LW->list,
13790                               XmNextendedSelectionCallback,
13791                               LW->Select_cb, (XtPointer)LW);
13792             else
13793                XtAddCallback (LW->list,
13794                               XmNextendedSelectionCallback,
13795                               LW->Select_cb, (XtPointer)LW->Select_Data);
13796 
13797             XtVaSetValues( LW->list,
13798                            XmNselectionPolicy, XmEXTENDED_SELECT, NULL);
13799             break;
13800          default:
13801             SUMA_SL_Err("Bad selection policy");
13802             SUMA_RETURNe;
13803             break;
13804       }
13805 
13806        /* manage it */
13807       if (LocalHead) fprintf(SUMA_STDERR, "%s: Managing ..\n", FuncName);
13808       XtManageChild (LW->list);
13809       XtManageChild (LW->rc);
13810 
13811 
13812       SUMA_PositionWindowRelative (LW->toplevel, LW->PosRef, LW->Pos);
13813 
13814       LW->isShaded = NOPE;
13815       New = YUP;
13816 
13817    } else {
13818       /*map and raise the baby */
13819       XMapRaised(SUMAg_CF->X->DPY_controller1, XtWindow(LW->toplevel));
13820       LW->isShaded = NOPE;
13821    }
13822 
13823 
13824    /* now cycle through the elements in clist and add them,
13825       if they are new, in alphabetical order */
13826    if (!Partial && !LW->RemoveDups) {
13827       if (LocalHead)
13828          fprintf (SUMA_STDERR,
13829                   "%s: New full list, deleting old entries. \n", FuncName);
13830       XmListDeleteAllItems(LW->list);
13831    }else {
13832       if (LocalHead)
13833          fprintf (SUMA_STDERR,
13834                   "%s: Partial list, will add.\n", FuncName);
13835    }
13836    for (iclist=0; iclist < N_clist; iclist++)     {
13837       SUMA_LH("%s",clist[iclist]);
13838       if (LW->ShowSorted) {
13839          l_bound = 0;
13840          /* get the current entries (and number of entries) from the List */
13841          XtVaGetValues (LW->list,
13842                         XmNitemCount, &u_bound,
13843                         XmNitems,     &strlist,
13844                         NULL);
13845          u_bound--;
13846          /* perform binary search */
13847          while (u_bound >= l_bound) {
13848             int i = l_bound + (u_bound - l_bound) / 2;
13849             /* convert the compound string into a regular C string */
13850             if (!XmStringGetLtoR (strlist[i], XmFONTLIST_DEFAULT_TAG, &text))
13851                break;
13852             if (strcmp (text, clist[iclist]) > 0)
13853                u_bound = i - 1; /* newtext comes before item */
13854             else
13855                l_bound = i + 1; /* newtext comes after item */
13856             XtFree (text); /* XmStringGetLtoR() allocates memory ... yuk */
13857          }
13858       } else { /* Not sorted, add to bottom*/
13859         l_bound = 0;
13860       }
13861 
13862       if (LocalHead)
13863          fprintf (SUMA_STDERR,"%s: Adding %s...\n", FuncName, clist[iclist]);
13864       str = XmStringCreateLocalized (clist[iclist]);
13865 
13866       /* positions indexes start at 1, so increment accordingly */
13867       if (LW->RemoveDups) {
13868          if (LocalHead)
13869             fprintf (SUMA_STDERR,"%s: removing duplicates\n", FuncName);
13870          if (!XmListItemExists(LW->list, str))
13871             XmListAddItemUnselected (LW->list, str, l_bound+1);
13872       } else {
13873          if (LocalHead) fprintf (SUMA_STDERR,"%s: with duplicates\n", FuncName);
13874          XmListAddItemUnselected (LW->list, str, l_bound+1);
13875       }
13876       XmStringFree (str);
13877 
13878    }
13879 
13880 
13881    /* set the vertical size of the list */
13882    XtVaSetValues( LW->list,
13883                   XmNvisibleItemCount, 10,
13884                   NULL);
13885 
13886 
13887    if (New) {
13888       XmListSetPos(LW->list,1);
13889       XmListSelectPos(LW->list,1, False);
13890       /* realize the widget */
13891       XtRealizeWidget (LW->toplevel);
13892       /* To allow user to adjust list height, I would have to put in a callback
13893       on the rc widget to reset XmNvisibleItemCount manually.
13894       Attempts to set  XmNresizeHeight for rc or toplevel did not work*/
13895    } else {
13896       XmListSetPos(LW->list,SUMA_MAX_PAIR(1,LW->lastitempos-3));
13897       XmListSelectPos(LW->list,SUMA_MAX_PAIR(1,LW->lastitempos), False);
13898    }
13899 
13900    SUMA_RETURNe;
13901 }
13902 
13903 
13904 
13905 /*!
13906    \brief adds arrow fields
13907    SUMA_CreateArrowField (    pw, label,
13908                               value,  vmin,  vmax,  vstep,
13909                               cwidth, type,
13910                               wrap,
13911                               NewValueCallback,
13912                               cb_data ,
13913                               AF);
13914 
13915    \param pw (Widget)   Parent widget
13916    \param label (char *) label (NULL for nothing)
13917    \param value (float) current value
13918    \param vmin (float) minimum value
13919    \param vmax (float) maximum value
13920    \param vstep (float) arrow increment
13921    \param cwidth (int) number of columns for text field
13922    \param type (SUMA_VARTYPE) SUMA_int or SUMA_float
13923    \param wrap (SUMA_Boolean) YUP=wrap values, NOPE=clip values
13924    \param NewValueCallback(void *data) (void *) Function to call when there is a new value in town.
13925    \param cb_data (void *) data to send to callback.
13926                            if NULL data is actually the AF structure pointer itself.
13927    \param hint (char *) if NULL, no hint
13928    \param help (char *) if NULL no help
13929    \param AF (SUMA_ARROW_TEXT_FIELD *) structure defining the arrow field.
13930    - AF must be pre-allocated, of course. Its fields are initialized by the values passed to the function
13931 */
SUMA_CreateArrowField(Widget pw,char * label,float value,float vmin,float vmax,float vstep,int cwidth,SUMA_VARTYPE type,SUMA_Boolean wrap,void (* NewValueCallback)(void * data),void * cb_data,char * wname,char * hint,char * help,SUMA_ARROW_TEXT_FIELD * AF)13932 void SUMA_CreateArrowField (  Widget pw, char *label,
13933                               float value, float vmin,
13934                               float vmax, float vstep,
13935                               int cwidth, SUMA_VARTYPE type,
13936                               SUMA_Boolean wrap,
13937                               void (*NewValueCallback)(void *data),
13938                               void *cb_data,
13939                               char *wname, char *hint, char *help,
13940                               SUMA_ARROW_TEXT_FIELD *AF)
13941 {
13942    static char FuncName[]={"SUMA_CreateArrowField"};
13943    char sbuf[64], sss[256]={""};
13944    char *sh=NULL;
13945 
13946    SUMA_ENTRY;
13947 
13948    if (!AF) {
13949       SUMA_RegisterMessage (SUMAg_CF->MessageList,
13950                             "Bad value in text field",
13951                             FuncName, SMT_Error, SMA_Log);
13952       SUMA_RETURNe;
13953    }
13954 
13955    AF->step = vstep;
13956    AF->value = value;
13957    AF->min = vmin;
13958    AF->max = vmax;
13959    AF->cwidth = cwidth;
13960    AF->type = type;
13961    AF->NewValueCallback = NewValueCallback;
13962    AF->NewValueCallbackData = cb_data;
13963    AF->modified = NOPE;
13964    AF->wrap = wrap;
13965    AF->rc = XtVaCreateManagedWidget ("Container",
13966       xmRowColumnWidgetClass, pw,
13967       XmNpacking, XmPACK_TIGHT,
13968       XmNorientation , XmHORIZONTAL ,
13969       NULL);
13970 
13971    if (hint || help) {
13972       SUMA_Register_Widget_Help( AF->rc , 1, wname, hint, help);
13973    }
13974 
13975    if (label) {
13976       AF->label =  XtVaCreateManagedWidget (label,
13977          xmLabelWidgetClass, AF->rc,
13978          XmNmarginHeight, 0,
13979          XmNmarginTop, 0,
13980          XmNmarginBottom, 0,
13981          NULL);
13982       if (hint || help) {
13983          snprintf(sss, 255,"%s->label", wname);
13984          if (AF->type == SUMA_int || AF->type == SUMA_float) {
13985             sh = SUMA_append_replace_string(help,
13986               "For numeric arrow fields, you can also change values by scrolling"
13987               "with the pointer over the text field.", ":LR:\n",0);
13988          } else {
13989             sh = help;
13990          }
13991          SUMA_Register_Widget_Help( AF->label , 1, sss, NULL, help?help:hint);
13992          if (sh != help) { SUMA_ifree(sh); }
13993       }
13994    }else {
13995       AF->label = NULL;
13996    }
13997 
13998    AF->up = XtVaCreateManagedWidget ("arrow_up",
13999          xmArrowButtonWidgetClass, AF->rc,
14000          XmNarrowDirection,   XmARROW_UP,
14001          XmNmarginHeight, 0,
14002          XmNmarginTop, 0,
14003          XmNmarginBottom, 0,
14004          NULL);
14005    if (hint || help) {
14006       snprintf(sss, 255,"%s->up", wname);
14007       if (AF->type == SUMA_int || AF->type == SUMA_float) {
14008          sh = SUMA_append_replace_string(help,
14009             "For numeric arrow fields, you can also change values by scrolling"
14010             "with the pointer over the text field.", ":LR:\n",0);
14011       } else {
14012          sh = help;
14013       }
14014       SUMA_Register_Widget_Help( AF->up , 1, sss, NULL, help?help:hint);
14015       if (sh != help) { SUMA_ifree(sh); }
14016    }
14017 
14018    XtVaSetValues (AF->up, XmNuserData, (XtPointer)AF, NULL);
14019    XtAddCallback (AF->up, XmNarmCallback, SUMA_ATF_start_stop, (XtPointer)1);
14020    XtAddCallback (AF->up, XmNdisarmCallback, SUMA_ATF_start_stop, (XtPointer)1);
14021 
14022    AF->down = XtVaCreateManagedWidget ("arrow_dn",
14023       xmArrowButtonWidgetClass, AF->rc,
14024       XmNarrowDirection,   XmARROW_DOWN,
14025       XmNmarginHeight, 0,
14026       XmNmarginTop, 0,
14027       XmNmarginBottom, 0,
14028       NULL);
14029    if (hint || help) {
14030       snprintf(sss, 255,"%s->down", wname);
14031       if (AF->type == SUMA_int || AF->type == SUMA_float) {
14032          sh = SUMA_append_replace_string(help,
14033             "For numeric arrow fields, you can also change values by scrolling"
14034             "with the pointer over the text field.", ":LR:\n",0);
14035       } else {
14036          sh = help;
14037       }
14038       SUMA_Register_Widget_Help( AF->down , 1, sss, NULL, help?help:hint);
14039       if (sh != help) { SUMA_ifree(sh); }
14040    }
14041    XtVaSetValues (AF->down, XmNuserData, (XtPointer)AF, NULL);
14042    XtAddCallback (AF->down, XmNarmCallback, SUMA_ATF_start_stop, (XtPointer)-1);
14043    XtAddCallback (AF->down, XmNdisarmCallback,
14044                               SUMA_ATF_start_stop, (XtPointer)-1);
14045 
14046    SUMA_ATF_GetString(AF, sbuf);
14047    AF->textfield = XtVaCreateManagedWidget ("label",
14048       xmTextFieldWidgetClass, AF->rc,
14049       XmNuserData, (XtPointer)AF,
14050       XmNvalue, sbuf,
14051       XmNcolumns, AF->cwidth,
14052       XmNmarginHeight, 0,
14053       XmNmarginTop, 0,
14054       XmNmarginBottom, 0,
14055       NULL);
14056 
14057    if (hint || help) {
14058       snprintf(sss, 255,"%s->val", wname);
14059       if (AF->type == SUMA_int || AF->type == SUMA_float) {
14060          sh = SUMA_append_replace_string(help,
14061             "For numeric arrow fields, you can also change values by scrolling"
14062             "with the pointer over the text field.", ":LR:\n",0);
14063       } else {
14064          sh = help;
14065       }
14066       SUMA_Register_Widget_Help( AF->textfield , 1, sss, NULL, sh?sh:hint);
14067       if (sh != help) { SUMA_ifree(sh); }
14068    }
14069 
14070    XtAddCallback (AF->textfield, XmNactivateCallback,
14071                                     SUMA_ATF_cb_label_change, (XtPointer)AF);
14072    XtAddCallback (AF->textfield, XmNmodifyVerifyCallback,
14073                                     SUMA_ATF_cb_label_Modify, (XtPointer)AF);
14074 
14075    /* add event handler to nitify when widget was left */
14076    XtInsertEventHandler( AF->textfield ,        /* notify when */
14077                          LeaveWindowMask ,  /* pointer leaves */
14078                          FALSE ,            /* this window */
14079                          SUMA_leave_EV,
14080                          (XtPointer) AF ,
14081                          XtListTail ) ;     /* last in queue */
14082    XtInsertEventHandler( AF->textfield  ,      /* handle events in cell */
14083                          ButtonPressMask ,  /* button presses */
14084                          FALSE ,            /* nonmaskable events? */
14085                          SUMA_press_EV,  /* handler */
14086                          (XtPointer) AF ,   /* client data */
14087                          XtListTail ) ;
14088    XtManageChild (AF->rc);
14089    SUMA_RETURNe;
14090 }
14091 
14092 
14093 /*! \brief Sets the GUI menu selection to the ith selection
14094            for a menu created by SUMA_BuildMenu. i starts at 1 */
SUMA_Set_Menu_Widget(SUMA_MENU_WIDGET * men,int i)14095 SUMA_Boolean SUMA_Set_Menu_Widget(SUMA_MENU_WIDGET *men, int i)
14096 {
14097    static char FuncName[]={"SUMA_Set_Menu_Widget"};
14098    char stmp[64]={""};
14099    SUMA_Boolean LocalHead = NOPE;
14100 
14101    SUMA_ENTRY;
14102 
14103    if (i<1) { SUMA_S_Err("i must be >=1"); SUMA_RETURN(NOPE);   }
14104    if (!men) { SUMA_DUMP_TRACE("NULL widget struct"); SUMA_RETURN(NOPE); }
14105    if(men->menu_type == SUMA_XmArrowFieldMenu) {
14106       if (!men->af || !men->af->textfield) {
14107          SUMA_S_Err("Null AF for arrow field menu!");  SUMA_RETURN(NOPE);
14108       }
14109       sprintf(stmp,"%d", i-1);
14110       SUMA_LHv("Arrows: stmp=%s, textfield=%p\n", stmp, men->af->textfield);
14111       XtVaSetValues( men->af->textfield, XmNvalue, stmp, NULL);
14112       men->af->value = i-1;
14113    } else {
14114       SUMA_LHv("Non arrows, %p, men->N_mw %d, i=%d\n", men->mw, men->N_mw, i);
14115       if (!men->mw || i>=men->N_mw || !men->mw[i]) {
14116          /* you can get here with i>=men->N_mw if controller has not been
14117            open yet, so return without complaints. */
14118          /* SUMA_S_Err("Null menu widgets or bad index for menu!");
14119          SUMA_RETURN(NOPE); */
14120          SUMA_RETURN(YUP);
14121       }
14122       XtVaSetValues(  men->mw[0], XmNmenuHistory ,  men->mw[i], NULL);
14123    }
14124 
14125    SUMA_RETURN(YUP);
14126 }
14127 
14128 /*!
14129    creates a text field.
14130 
14131    \sa SUMA_CreateArrowField
14132 */
SUMA_CreateTextField(Widget pw,char * label,int cwidth,void (* NewValueCallback)(void * data),char * wname,char * hint,char * help,SUMA_ARROW_TEXT_FIELD * AF)14133 void SUMA_CreateTextField ( Widget pw, char *label,
14134                               int cwidth,
14135                               void (*NewValueCallback)(void *data),
14136                               char *wname, char *hint, char *help,
14137                               SUMA_ARROW_TEXT_FIELD *AF)
14138 {
14139    static char FuncName[]={"SUMA_CreateTextField"};
14140 
14141    SUMA_ENTRY;
14142 
14143    /* techincally, one should have a structure that
14144       is only for text but that is not necessary, I think */
14145 
14146    AF->up = AF->down = NULL;
14147    AF->step = AF->value = AF->min = AF->max = AF->wrap = 0;
14148 
14149    AF->type = SUMA_string;
14150    AF->NewValueCallback = NewValueCallback;
14151    AF->NewValueCallbackData = NULL;
14152    AF->arrow_action = NOPE;
14153    AF->cwidth = cwidth;
14154    AF->modified = NOPE;
14155 
14156    AF->rc = XtVaCreateManagedWidget ("Container",
14157       xmRowColumnWidgetClass, pw,
14158       XmNpacking, XmPACK_TIGHT,
14159       XmNorientation , XmHORIZONTAL ,
14160       NULL);
14161 
14162    if (hint || help) {
14163       SUMA_Register_Widget_Help( AF->rc , 1, wname, hint, help);
14164    }
14165 
14166 
14167    if (label) {
14168       AF->label =  XtVaCreateManagedWidget (label,
14169          xmLabelWidgetClass, AF->rc,
14170          XmNmarginHeight, 0,
14171          XmNmarginTop, 0,
14172          XmNmarginBottom, 0,
14173          NULL);
14174       if (hint || help) {
14175          SUMA_Register_Widget_Help( AF->label , 1, wname, hint, help);
14176       }
14177    }else {
14178       AF->label = NULL;
14179    }
14180 
14181    AF->textfield = XtVaCreateManagedWidget ("label",
14182       xmTextFieldWidgetClass, AF->rc,
14183       XmNuserData, (XtPointer)AF,
14184       XmNvalue, "0",
14185       XmNcolumns, AF->cwidth,
14186       XmNmarginHeight, 0,
14187       XmNmarginTop, 0,
14188       XmNmarginBottom, 0,
14189       NULL);
14190    if (hint || help) {
14191       SUMA_Register_Widget_Help( AF->textfield , 1, wname, hint, help);
14192    }
14193 
14194    XtAddCallback (AF->textfield, XmNactivateCallback,
14195                   SUMA_ATF_cb_label_change, (XtPointer)AF);
14196    XtAddCallback (AF->textfield, XmNmodifyVerifyCallback,
14197                   SUMA_ATF_cb_label_Modify, (XtPointer)AF);
14198 
14199    /* add event handler to nitify when widget was left */
14200    XtInsertEventHandler( AF->textfield ,        /* notify when */
14201                          LeaveWindowMask ,  /* pointer leaves */
14202                          FALSE ,            /* this window */
14203                          SUMA_leave_EV,
14204                          (XtPointer) AF ,
14205                          XtListTail ) ;     /* last in queue */
14206    XtManageChild (AF->rc);
14207    SUMA_RETURNe;
14208 }
14209 
14210 /*!
14211    \brief This function is called when label field has been modified by user keyboard input.
14212    All it does is set AF->modified to YUP
14213 
14214 */
SUMA_ATF_cb_label_Modify(Widget w,XtPointer client_data,XtPointer call_data)14215 void SUMA_ATF_cb_label_Modify (Widget w, XtPointer client_data, XtPointer call_data)
14216 {
14217    static char FuncName[]={"SUMA_ATF_cb_label_Modify"};
14218    SUMA_ARROW_TEXT_FIELD *AF=NULL;
14219 
14220    SUMA_ENTRY;
14221 
14222    AF = (SUMA_ARROW_TEXT_FIELD *)client_data ;
14223    if (!AF->arrow_action) AF->modified = YUP;
14224 
14225    SUMA_RETURNe;
14226 }
14227 
14228 /*!
14229    \brief This function is called when mouse pointer leaves label field
14230    It only acts if  AF->modified
14231 */
SUMA_leave_EV(Widget w,XtPointer client_data,XEvent * ev,Boolean * continue_to_dispatch)14232 void SUMA_leave_EV( Widget w , XtPointer client_data ,
14233                   XEvent * ev , Boolean * continue_to_dispatch )
14234 {
14235    SUMA_ARROW_TEXT_FIELD *AF=NULL;
14236    XLeaveWindowEvent * lev = (XLeaveWindowEvent *) ev ;
14237    XmAnyCallbackStruct cbs ;
14238    static char FuncName[]={"SUMA_leave_EV"};
14239    SUMA_Boolean LocalHead = NOPE;
14240 
14241    SUMA_ENTRY;
14242 
14243    SUMA_LH("Called");
14244    AF = (SUMA_ARROW_TEXT_FIELD *)client_data ;
14245    if( lev->type != LeaveNotify || !AF->modified ) SUMA_RETURNe;
14246 
14247    SUMA_LH("Leave notification");
14248    SUMA_ATF_cb_label_change( AF->textfield , (XtPointer) AF , NULL ) ;
14249 
14250    SUMA_RETURNe;
14251 }
14252 
14253 /*!
14254    \brief This function is called when button presses happen in arrow text field
14255 */
SUMA_press_EV(Widget w,XtPointer client_data,XEvent * ev,Boolean * continue_to_dispatch)14256 void SUMA_press_EV( Widget w , XtPointer client_data ,
14257                     XEvent * ev , Boolean * continue_to_dispatch )
14258 {
14259    static char FuncName[]={"SUMA_press_EV"};
14260    SUMA_ARROW_TEXT_FIELD *AF=NULL;
14261    XButtonEvent * bev = (XButtonEvent *) ev ;
14262    XmAnyCallbackStruct cbs ;
14263    int incr=0, ival=0;
14264    SUMA_Boolean LocalHead = NOPE;
14265 
14266    SUMA_ENTRY;
14267 
14268    SUMA_LH("Called");
14269    AF = (SUMA_ARROW_TEXT_FIELD *)client_data ;
14270 
14271    /* see note in bbox.c optmenu_EV for the condition below*/
14272    if( bev->button == Button2 ) {
14273      XUngrabPointer( bev->display , CurrentTime ) ;
14274      SUMA_RETURNe ;
14275    }
14276 
14277    if( w == NULL || AF == NULL ) { SUMA_RETURNe ; }
14278 
14279    incr = 0;
14280    switch (bev->button) {
14281       case Button1:
14282          SUMA_LH("Button 1");
14283          break;
14284       case Button2:
14285          SUMA_LH("Button 2");
14286          break;
14287       case Button3:
14288          SUMA_LH("Button 3");
14289          break;
14290       case Button4:
14291       case 6:  /* This is shift and wheel on mac, Button6 is not in X.h ! */
14292          SUMA_LH("Button 4/6 %d", bev->button);
14293          incr = -1;
14294          break;
14295       case Button5:
14296       case 7:
14297          SUMA_LH("Button 5/7 %d", bev->button);
14298          incr = 1;
14299          break;
14300       default:
14301          SUMA_RETURNe;
14302    }
14303 
14304    if (incr) {
14305       AF->direction = incr;
14306       ival = AF->value;
14307       SUMA_ATF_change_value (AF, NULL );
14308       if (ival != AF->value) {
14309          if (!AF->NewValueCallbackData)
14310                AF->NewValueCallback((void*)AF);
14311          else
14312                AF->NewValueCallback(AF->NewValueCallbackData);
14313       }
14314    }
14315 
14316    SUMA_RETURNe;
14317 }
14318 
14319 
14320 /*!
14321    \brief This function is called when the label field is activated by the user
14322 
14323 */
SUMA_ATF_cb_label_change(Widget w,XtPointer client_data,XtPointer call_data)14324 void SUMA_ATF_cb_label_change (Widget w, XtPointer client_data,
14325                                XtPointer call_data)
14326 {
14327    static char FuncName[]={"SUMA_ATF_cb_label_change"};
14328    SUMA_ARROW_TEXT_FIELD *AF=NULL;
14329    SUMA_Boolean LocalHead = NOPE;
14330 
14331    SUMA_ENTRY;
14332 
14333    /* make call to NewValue callback */
14334    AF = (SUMA_ARROW_TEXT_FIELD *)client_data;
14335    SUMA_LHv("Type %d (%d int, %d float\n", AF->type, SUMA_int, SUMA_float);
14336    if (AF->type == SUMA_int || AF->type == SUMA_float) SUMA_ATF_SetValue (AF);
14337 
14338    if (!AF->NewValueCallbackData) {
14339       SUMA_LH("No Callback data.");
14340       AF->NewValueCallback((void*)AF);
14341    } else {
14342       SUMA_LH("Callback data.");
14343       AF->NewValueCallback(AF->NewValueCallbackData);
14344    }
14345 
14346    AF->modified = NOPE;
14347    SUMA_RETURNe;
14348 }
14349 
14350 /*!
14351    \brief function to handle the pressed buttons of the arrow keys
14352 
14353    -Based on code from Motif Programming Manual: arrow_timer.c
14354 
14355  - start_stop is used to start or stop the incremental changes to
14356  * the label's value.  When the button goes down, the reason is
14357  * XmCR_ARM and the timer starts.  XmCR_DISARM disables the timer.
14358  */
SUMA_ATF_start_stop(Widget w,XtPointer client_data,XtPointer call_data)14359 void SUMA_ATF_start_stop (Widget w, XtPointer client_data, XtPointer call_data)
14360 {
14361    static char FuncName[]={"SUMA_ATF_start_stop"};
14362    int incr = (INT_CAST) client_data;
14363    SUMA_ARROW_TEXT_FIELD *AF = NULL;
14364    void *n = NULL;
14365    XmArrowButtonCallbackStruct *cbs =
14366         (XmArrowButtonCallbackStruct *) call_data;
14367 
14368 
14369    SUMA_ENTRY;
14370 
14371    if (!w) SUMA_RETURNe;
14372 
14373    XtVaGetValues(w, XmNuserData, &n, NULL);
14374    if (!n) SUMA_RETURNe;
14375    AF = (SUMA_ARROW_TEXT_FIELD *)n;
14376    AF->direction = incr;
14377 
14378    if (cbs->reason == XmCR_ARM) {
14379      AF->arrow_action = YUP;
14380      SUMA_ATF_change_value (AF, (XtIntervalId *)1 );
14381    } else if (cbs->reason == XmCR_DISARM) {
14382      if (AF->arrow_timer_id) XtRemoveTimeOut (AF->arrow_timer_id);
14383      /* make call to NewValue callback */
14384      if (!AF->NewValueCallbackData)
14385          AF->NewValueCallback((void*)AF);
14386      else
14387          AF->NewValueCallback(AF->NewValueCallbackData);
14388 
14389      AF->arrow_action = NOPE;
14390 
14391    }
14392 
14393    SUMA_RETURNe;
14394 }
14395 
14396 /*!
14397    \brief A function that is called when the DrawROI value arrow field is set.
14398 
14399    \param data (void *) a typecast of a pointer to a SUMA_ARROW_TEXT_FIELD structure
14400 */
SUMA_DrawROI_NewValue(void * data)14401 void SUMA_DrawROI_NewValue (void *data)
14402 {
14403    static char FuncName[]={"SUMA_DrawROI_NewValue"};
14404    SUMA_ARROW_TEXT_FIELD *AF=NULL;
14405    SUMA_DRAWN_ROI *DrawnROI=NULL;
14406    static int ErrCnt=0;
14407    DList *list=NULL;
14408    SUMA_Boolean LocalHead = NOPE;
14409 
14410    SUMA_ENTRY;
14411 
14412    AF = (SUMA_ARROW_TEXT_FIELD *)data;
14413    DrawnROI = SUMAg_CF->X->DrawROI->curDrawnROI;
14414 
14415    if (!DrawnROI) SUMA_RETURNe;
14416 
14417    if (AF->value == DrawnROI->iLabel) SUMA_RETURNe;
14418 
14419    if (!DrawnROI->DrawStatus == SUMA_ROI_Finished) {
14420       if (LocalHead)
14421          fprintf (SUMA_STDERR,
14422                   "%s: Changing ROI value from %d to %d\n",
14423                   FuncName, DrawnROI->iLabel, (int)AF->value);
14424 
14425       DrawnROI->iLabel = (int)AF->value;
14426       ErrCnt = 0;
14427    } else {
14428       if (!ErrCnt)
14429          SUMA_SLP_Err ( "ROI is marked as finished.\n"
14430                         "New value will not be applied.\n");
14431       ++ErrCnt;
14432       AF->value = (float)DrawnROI->iLabel;
14433       SUMA_ATF_SetString (AF);
14434    }
14435 
14436    /* if your colors are based on the label, you've got work to do*/
14437    if (DrawnROI->ColorByLabel) {
14438       SUMA_SurfaceObject *SO=NULL;
14439       /* Now update the Paint job on the ROI plane */
14440       SO = SUMA_findSOp_inDOv (DrawnROI->Parent_idcode_str,
14441                                SUMAg_DOv, SUMAg_N_DOv);
14442       if (!SO) {
14443          SUMA_SLP_Err(  "Failed to find parent surface\n"
14444                         "No color for you!");
14445          SUMA_RETURNe;
14446       }
14447       if (!SUMA_Paint_SO_ROIplanes_w (SO, SUMAg_DOv, SUMAg_N_DOv)) {
14448          SUMA_SLP_Err("Failed in SUMA_Paint_SO_ROIplanes_w.");
14449          SUMA_RETURNe;
14450       }
14451 
14452       if (!list) list = SUMA_CreateList ();
14453       SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_Redisplay_AllVisible,
14454                                           SES_SumaWidget, NULL);
14455       if (!SUMA_Engine (&list)) {
14456          fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_Engine.\n", FuncName);
14457          SUMA_RETURNe;
14458       }
14459    }
14460    SUMA_RETURNe;
14461 }
14462 
SUMA_ColPlane_NewOrder(SUMA_ALL_DO * ado,SUMA_OVERLAYS * colp,int neworder,int cb_direct)14463 int SUMA_ColPlane_NewOrder(SUMA_ALL_DO *ado, SUMA_OVERLAYS *colp,
14464                                int neworder, int cb_direct)
14465 {
14466    static char FuncName[]={"SUMA_ColPlane_NewOrder"};
14467    SUMA_SurfaceObject *SOC=NULL, *SO=NULL;
14468    SUMA_OVERLAYS *colpC=NULL;
14469    SUMA_OVERLAYS *curColPlane=NULL;
14470    SUMA_X_SurfCont *SurfCont=NULL;
14471    SUMA_Boolean LocalHead = NOPE;
14472 
14473    SUMA_ENTRY;
14474 
14475    if (!ado || !(SurfCont = SUMA_ADO_Cont(ado))) SUMA_RETURN(0);
14476    curColPlane = SUMA_ADO_CurColPlane(ado);
14477    if (!colp) colp = curColPlane;
14478    if (!colp) SUMA_RETURN(0);
14479    if (colp != curColPlane) {
14480       SUMA_S_Err("Will need to switch current plane. Not ready for this");
14481       SUMA_RETURN(0);
14482    }
14483 
14484    if (!SUMA_ColPlane_NewOrder_one(ado, colp, neworder, cb_direct)) {
14485       SUMA_S_Err("Returning on a sad note");
14486       SUMA_RETURN(0);
14487    }
14488 
14489    if (ado->do_type == SO_type) {
14490       SO = (SUMA_SurfaceObject *)ado;
14491       colpC = SUMA_Contralateral_overlay(colp, SO, &SOC);
14492       if (colpC && SOC) {
14493          SUMA_LHv("Found contralateral equivalent to:\n"
14494                       " %s and %s in\n"
14495                       " %s and %s\n",
14496                       SO->Label, CHECK_NULL_STR(colp->Label),
14497                       SOC->Label, CHECK_NULL_STR(colpC->Label));
14498          if (SOC->SurfCont->curColPlane != colpC) {
14499             SUMA_S_Err("Don't have contralateral as cur colplane.\n"
14500                        "This should not happen under L/R yoked conditions.");
14501             SUMA_RETURN(0);
14502          }
14503          if (!SUMA_ColPlane_NewOrder_one((SUMA_ALL_DO *)SOC, colpC,
14504                                          neworder, 0)) {
14505             SUMA_S_Warn("Failed in contralateralization");
14506          }
14507       } else {
14508          SUMA_LHv("Found NO contralateral equivalent to:\n"
14509                       " %s and %s in\n",
14510                       SO->Label, CHECK_NULL_STR(colp->Label));
14511       }
14512    }
14513 
14514 
14515    SUMA_RETURN(1);
14516 }
14517 
SUMA_ColPlane_NewOrder_one(SUMA_ALL_DO * ado,SUMA_OVERLAYS * colp,int neworder,int cb_direct)14518 int SUMA_ColPlane_NewOrder_one(SUMA_ALL_DO *ado, SUMA_OVERLAYS *colp,
14519                                int neworder, int cb_direct)
14520 {
14521    static char FuncName[]={"SUMA_ColPlane_NewOrder_one"};
14522    char sbuf[SUMA_MAX_LABEL_LENGTH];
14523    int Old_Order = -1, i, iMove, NetMove;
14524    SUMA_Boolean Shaded, Decent;
14525    SUMA_X_SurfCont *SurfCont=NULL;
14526    SUMA_OVERLAYS *curColPlane=NULL;
14527    SUMA_Boolean LocalHead = NOPE;
14528 
14529    SUMA_ENTRY;
14530 
14531    if (!ado || !(SurfCont = SUMA_ADO_Cont(ado))) SUMA_RETURN(0);
14532 
14533    curColPlane = SUMA_ADO_CurColPlane(ado);
14534 
14535    if (!colp) colp = curColPlane;
14536    if (!colp) SUMA_RETURN(0);
14537    if (colp != curColPlane) {
14538       SUMA_S_Err("Will need to switch current plane. Not ready for this");
14539       SUMA_RETURN(0);
14540    }
14541 
14542    /* Now show the new order */
14543    if (LocalHead) SUMA_Print_PlaneOrder(ado, NULL);
14544 
14545 
14546    /* Now figure out the direction of the arrow presses */
14547    NetMove = (int)neworder -
14548                   curColPlane->PlaneOrder ;
14549 
14550    if (LocalHead) fprintf (SUMA_STDERR,"%s:  Net move %d\n", FuncName, NetMove);
14551    iMove = 0;
14552    Decent = YUP;
14553    if (NetMove > 0) {
14554       do {
14555          Old_Order = curColPlane->PlaneOrder;
14556          if (!SUMA_MovePlaneUp(ado, curColPlane->Name)) {
14557             SUMA_L_Err("Error in SUMA_MovePlaneUp.");
14558             SUMA_RETURN(0);
14559          }
14560 
14561          if (curColPlane->PlaneOrder == Old_Order) {
14562             SUMA_LH("Nothing can be done");
14563             Decent = NOPE;
14564          } else {
14565             ++iMove;
14566          }
14567       } while (iMove < NetMove && Decent);
14568    } else if (NetMove < 0) {
14569       do {
14570          Old_Order = curColPlane->PlaneOrder;
14571          if (!SUMA_MovePlaneDown(ado, curColPlane->Name)) {
14572             SUMA_L_Err("Error in SUMA_MovePlaneDown.");
14573             SUMA_RETURN(0);
14574          }
14575          if (curColPlane->PlaneOrder == Old_Order) {
14576             SUMA_LH("Enough");
14577             Decent = NOPE;
14578          } else {
14579             ++iMove;
14580          }
14581       } while (iMove < -NetMove && Decent);
14582    } else {
14583       Decent = NOPE;
14584    }
14585 
14586    SUMA_LH("Out");
14587    /* Now show the new order */
14588    if(LocalHead) SUMA_Print_PlaneOrder(ado, NULL);
14589 
14590    /* refresh the switch list */
14591    SUMA_IS_SWITCH_COL_PLANE_SHADED(ado, Shaded);
14592    if (!Shaded) {
14593       SUMA_LH("Refreshing Col Plane List");
14594       SUMA_RefreshDsetList (ado);
14595    }
14596 
14597    if (!Decent) {
14598       /* reset order value in widget to its last acceptable value. */
14599       sprintf(sbuf,"%d", curColPlane->PlaneOrder);
14600       neworder = curColPlane->PlaneOrder;
14601       SUMA_SET_TEXT_FIELD(SurfCont->ColPlaneOrder->textfield, sbuf);
14602    }
14603 
14604    SUMA_UpdateColPlaneShellAsNeeded(ado); /* update other open ColPlaneShells */
14605 
14606    if (iMove > 0) { /* something decent was done, act on it */
14607       /* a good remix and redisplay */
14608       SUMA_LH("Remix and redisplay");
14609       SUMA_Remixedisplay (ado);
14610    }
14611 
14612    if (!cb_direct && neworder != (int)SurfCont->ColPlaneOrder->value) {
14613       /* force gui match */
14614       sprintf(sbuf,"%d", neworder);
14615       SurfCont->ColPlaneOrder->value = neworder;
14616       SUMA_SET_TEXT_FIELD(SurfCont->ColPlaneOrder->textfield, sbuf);
14617    }
14618 
14619    SUMA_RETURN(1);
14620 }
14621 
14622 /*!
14623    \brief Function to update the order of a colorplane
14624 
14625    -expects ADO in data
14626 */
SUMA_cb_ColPlane_NewOrder(void * data)14627 void SUMA_cb_ColPlane_NewOrder (void *data)
14628 {
14629    static char FuncName[]={"SUMA_cb_ColPlane_NewOrder"};
14630    SUMA_ALL_DO *ado=NULL;
14631    SUMA_X_SurfCont *SurfCont=NULL;
14632    SUMA_OVERLAYS *curColPlane=NULL;
14633    SUMA_Boolean LocalHead = NOPE;
14634 
14635    SUMA_ENTRY;
14636 
14637    ado = (SUMA_ALL_DO *)data;
14638    if (!ado || !(SurfCont=SUMA_ADO_Cont(ado))
14639             || !SurfCont->ColPlaneOrder) SUMA_RETURNe;
14640    curColPlane = SUMA_ADO_CurColPlane(ado);
14641 
14642 
14643    /* make sure a new order is in order */
14644    if (curColPlane->PlaneOrder ==
14645          (int)SurfCont->ColPlaneOrder->value) SUMA_RETURNe;
14646 
14647    SUMA_ColPlane_NewOrder(ado, NULL,
14648                               (int)SurfCont->ColPlaneOrder->value, 1);
14649 
14650    SUMA_RETURNe;
14651 }
14652 
14653 /*!
14654    \brief Function to change pages in notebook
14655 
14656    -expects ADO in data
14657 */
SUMA_cb_SurfCont_SwitchPage(void * data)14658 void SUMA_cb_SurfCont_SwitchPage (void *data)
14659 {
14660    static char FuncName[]={"SUMA_cb_SurfCont_SwitchPage"};
14661    char sbuf[SUMA_MAX_LABEL_LENGTH];
14662    SUMA_ALL_DO *ado=NULL;
14663    SUMA_X_SurfCont *SurfCont=NULL;
14664    SUMA_OVERLAYS *curColPlane=NULL;
14665    SUMA_Boolean LocalHead = NOPE;
14666 
14667    SUMA_ENTRY;
14668 
14669    ado = (SUMA_ALL_DO *)data;
14670    if (!ado || !(SurfCont=SUMA_ADO_Cont(ado))
14671             || !SurfCont->SurfContPage) SUMA_RETURNe;
14672    curColPlane = SUMA_ADO_CurColPlane(ado);
14673 
14674    SUMA_LHv("About to change page to %d\n", (int)SurfCont->SurfContPage->value);
14675    if (!(SUMA_SetSurfContPageNumber(SUMAg_CF->X->SC_Notebook,
14676                                     SurfCont->SurfContPage->value))) {
14677       /* revert to good value */
14678       SurfCont->SurfContPage->value =
14679                SUMA_PageWidgetToNumber(SUMAg_CF->X->SC_Notebook, SurfCont->Page);
14680       sprintf(sbuf,"%d",(int)SurfCont->SurfContPage->value);
14681       SUMA_SET_TEXT_FIELD(SurfCont->SurfContPage->textfield, sbuf);
14682       SUMA_LHv("Problem, reverting to %d\n",
14683                (int)SurfCont->SurfContPage->value);
14684    }
14685 
14686    SUMA_RETURNe;
14687 }
14688 
14689 /*!
14690    \brief Initialize controllers for all objects that would have one
14691 
14692    -expects nothing
14693 */
SUMA_cb_AllConts(Widget w,XtPointer data,XtPointer client_data)14694 void SUMA_cb_AllConts(Widget w, XtPointer data, XtPointer client_data)
14695 {
14696    static char FuncName[]={"SUMA_cb_AllConts"};
14697    SUMA_ALL_DO *ado=NULL;
14698    int ido, new = 0;
14699 
14700    SUMA_ENTRY;
14701    /* For a large number of objects, say 90, this function
14702       can take a very long (2-3 mins) time to finsh. The reason
14703       for this latency is that a very large number of events end up
14704       in the queue with each new controller opened. The process takes longer
14705       and longer with each new controller opened.
14706       The best way around this is to force X11 to discard all the
14707       generated events and just refresh the display of the last
14708       controller opened. The update will then take place once
14709       you switch the the controller of interest.
14710 
14711       Note that MCW_invert_widget was also calling XSync() and XmUpdatedisplay()
14712       so I have had to call a variant that does not force these calls.
14713 
14714       Note again, the delay still increases with increasing objects but
14715       for now this remaining slowing down is not worth pursuing.
14716 
14717                                        ZSS Snowed in, Feb. 2015 */
14718    XSync( XtDisplay(w) , False ) ; /* Be nice and tidy up before plunge
14719                                       We will drop all remaining events later*/
14720    for (ido=0; ido<SUMAg_N_DOv; ++ido) {
14721       ado = (SUMA_ALL_DO *)SUMAg_DOv[ido].OP;
14722       if (SUMA_ADO_Cont(ado) && !SUMA_isADO_Cont_Realized(ado)) {
14723          ++new;
14724          SUMA_viewSurfaceCont(NULL, ado, NULL);
14725       }
14726    }
14727    if (new > 10) { /* don't bother unless we have had too many newbies */
14728       XSync( XtDisplay(w) , True ) ; /* get rid of all pending events */
14729       /* Now repeat call to last ado's viewer to update its widgets */
14730       if (new) SUMA_SetSurfContPageNumber(SUMAg_CF->X->SC_Notebook, 1);
14731    }
14732    SUMA_RETURNe;
14733 }
14734 
14735 /*!
14736    \brief Function to update the opacity of a colorplane
14737 
14738    -expects SO in data
14739 */
SUMA_cb_ColPlane_NewOpacity(void * data)14740 void SUMA_cb_ColPlane_NewOpacity(void *data)
14741 {
14742    static char FuncName[]={"SUMA_cb_ColPlane_NewOpacity"};
14743    SUMA_ALL_DO *ado=NULL;
14744    SUMA_X_SurfCont *SurfCont=NULL;
14745    SUMA_OVERLAYS *curColPlane=NULL;
14746    SUMA_Boolean LocalHead = NOPE;
14747 
14748    SUMA_ENTRY;
14749 
14750    ado = (SUMA_ALL_DO *)data;
14751    if (!ado || !(SurfCont=SUMA_ADO_Cont(ado))
14752             || !SurfCont->ColPlaneOpacity) SUMA_RETURNe;
14753    curColPlane = SUMA_ADO_CurColPlane(ado);
14754 
14755    if (SurfCont->ColPlaneOpacity->value ==
14756        curColPlane->GlobalOpacity) SUMA_RETURNe;
14757 
14758    SUMA_ColPlane_NewOpacity(ado, NULL, SurfCont->ColPlaneOpacity->value, 1);
14759 
14760    SUMA_RETURNe;
14761 }
14762 
SUMA_ColPlane_NewOpacity(SUMA_ALL_DO * ado,SUMA_OVERLAYS * colp,float newopacity,int cb_direct)14763 int SUMA_ColPlane_NewOpacity (SUMA_ALL_DO *ado, SUMA_OVERLAYS *colp,
14764                                float newopacity, int cb_direct )
14765 {
14766    static char FuncName[]={"SUMA_ColPlane_NewOpacity"};
14767    SUMA_SurfaceObject *SOC=NULL, *SO=NULL;
14768    SUMA_OVERLAYS *colpC=NULL;
14769    SUMA_X_SurfCont *SurfCont=NULL;
14770    SUMA_OVERLAYS *curColPlane=NULL;
14771    SUMA_Boolean LocalHead = NOPE;
14772 
14773    SUMA_ENTRY;
14774 
14775    SUMA_LH("Called");
14776 
14777    if (!ado || !(SurfCont = SUMA_ADO_Cont(ado))) SUMA_RETURN(0);
14778    curColPlane = SUMA_ADO_CurColPlane(ado);
14779    if (!colp) colp = curColPlane;
14780    if (!colp) SUMA_RETURN(0);
14781    if (colp != curColPlane) {
14782       SUMA_S_Err( "Will need to switch to current plane first. "
14783                   "Not ready for this");
14784       SUMA_RETURN(0);
14785    }
14786 
14787    if (!SUMA_ColPlane_NewOpacity_one(ado, colp, newopacity, cb_direct)) {
14788       SUMA_S_Err("Returning on a sad note");
14789       SUMA_RETURN(0);
14790    }
14791 
14792    if (ado->do_type == SO_type) {
14793       SO = (SUMA_SurfaceObject *)ado;
14794       colpC = SUMA_Contralateral_overlay(colp, SO, &SOC);
14795       if (colpC && SOC) {
14796          SUMA_LHv("Found contralateral equivalent to:\n"
14797                       " %s and %s in\n"
14798                       " %s and %s\n",
14799                       SO->Label, CHECK_NULL_STR(colp->Label),
14800                       SOC->Label, CHECK_NULL_STR(colpC->Label));
14801          if (SOC->SurfCont->curColPlane != colpC) {
14802             SUMA_S_Err("Don't have contralateral as cur colplane.\n"
14803                        "This should not happen under L/R yoked conditions.");
14804             SUMA_RETURN(0);
14805          }
14806          if (!SUMA_ColPlane_NewOpacity_one((SUMA_ALL_DO *)SOC, colpC,
14807                                          newopacity, 0)) {
14808             SUMA_S_Warn("Failed in contralateralization");
14809          }
14810       } else {
14811          SUMA_LHv("Found NO contralateral equivalent to:\n"
14812                       " %s and %s in\n",
14813                       SO->Label, CHECK_NULL_STR(colp->Label));
14814       }
14815    }
14816 
14817    SUMA_RETURN(1);
14818 }
14819 
SUMA_ColPlane_NewOpacity_one(SUMA_ALL_DO * ado,SUMA_OVERLAYS * colp,float newopacity,int cb_direct)14820 int SUMA_ColPlane_NewOpacity_one(SUMA_ALL_DO *ado, SUMA_OVERLAYS *colp,
14821                                  float newopacity, int cb_direct)
14822 {
14823    static char FuncName[]={"SUMA_ColPlane_NewOpacity_one"};
14824    char sbuf[SUMA_MAX_LABEL_LENGTH];
14825    SUMA_X_SurfCont *SurfCont=NULL;
14826    SUMA_OVERLAYS *curColPlane=NULL;
14827    SUMA_Boolean LocalHead = NOPE;
14828 
14829    SUMA_ENTRY;
14830 
14831    if (!ado || !(SurfCont = SUMA_ADO_Cont(ado))) SUMA_RETURN(0);
14832    curColPlane = SUMA_ADO_CurColPlane(ado);
14833    if (!colp) colp = curColPlane;
14834    if (!colp) SUMA_RETURN(0);
14835    if (colp != curColPlane) {
14836       SUMA_S_Err("Will need to switch current plane. Not ready for this");
14837       SUMA_RETURN(0);
14838    }
14839 
14840    /* change the value of the global opacity */
14841    curColPlane->GlobalOpacity = newopacity;
14842    if (LocalHead) fprintf(SUMA_STDERR,"%s: GlobalOpacity of %s set to %f.\n",
14843          FuncName, curColPlane->Name,
14844          curColPlane->GlobalOpacity);
14845 
14846    SUMA_UpdateColPlaneShellAsNeeded(ado); /* update other open ColPlaneShells */
14847 
14848    /* a good remix and redisplay */
14849    SUMA_Remixedisplay (ado);
14850 
14851    if (!cb_direct && newopacity != SurfCont->ColPlaneOpacity->value) {
14852       /* force gui match */
14853       sprintf(sbuf,"%.2f", newopacity);
14854       SurfCont->ColPlaneOpacity->value = newopacity;
14855       SUMA_SET_TEXT_FIELD(SurfCont->ColPlaneOpacity->textfield, sbuf);
14856    }
14857 
14858    SUMA_RETURN(1);
14859 }
14860 
SUMA_cb_Tract_NewGray(void * data)14861 void SUMA_cb_Tract_NewGray(void *data)
14862 {
14863    static char FuncName[]={"SUMA_cb_Tract_NewGray"};
14864    SUMA_ALL_DO *ado=NULL;
14865    SUMA_X_SurfCont *SurfCont=NULL;
14866    SUMA_TRACT_SAUX *TSaux=NULL;
14867    SUMA_Boolean LocalHead = NOPE;
14868 
14869    SUMA_ENTRY;
14870 
14871    ado = (SUMA_ALL_DO *)data;
14872    if (!ado || !(TSaux=SUMA_ADO_TSaux(ado)) ||
14873        !(SurfCont = SUMA_ADO_Cont(ado))) SUMA_RETURNe;
14874 
14875    if (SurfCont->TractMaskGray->value ==
14876        TSaux->MaskGray) SUMA_RETURNe;
14877 
14878    SUMA_Tract_NewGray(ado, SurfCont->TractMaskGray->value, 1);
14879 
14880    SUMA_RETURNe;
14881 }
14882 
SUMA_Tract_NewGray(SUMA_ALL_DO * ado,float newgray,int cb_direct)14883 int SUMA_Tract_NewGray (SUMA_ALL_DO *ado,
14884                            float newgray, int cb_direct )
14885 {
14886    static char FuncName[]={"SUMA_Tract_NewGray"};
14887    SUMA_TractDO *tdo = (SUMA_TractDO*)ado;
14888    SUMA_X_SurfCont *SurfCont=NULL;
14889    SUMA_TRACT_SAUX *TSaux=NULL;
14890    char sbuf[32];
14891    SUMA_Boolean LocalHead = NOPE;
14892 
14893    SUMA_ENTRY;
14894 
14895    SUMA_LH("Called");
14896 
14897    if (!ado || !(TSaux = SUMA_ADO_TSaux(ado)) ||
14898        !(SurfCont = SUMA_ADO_Cont(ado))) SUMA_RETURN(0);
14899 
14900    /* change the value of the masking mode */
14901    TSaux->MaskGray = newgray;
14902    if (LocalHead) fprintf(SUMA_STDERR,"%s: Newgray of %s set to %f.\n",
14903          FuncName, ADO_LABEL(ado),
14904          TSaux->MaskGray);
14905 
14906    /* a good remix and redisplay */
14907    SUMA_Remixedisplay (ado);
14908 
14909    if (!cb_direct && newgray != SurfCont->TractMaskGray->value) {
14910       /* force gui match */
14911       sprintf(sbuf,"%.2f", newgray);
14912       SurfCont->TractMaskGray->value = newgray;
14913       SUMA_SET_TEXT_FIELD(SurfCont->TractMaskGray->textfield, sbuf);
14914    }
14915 
14916    SUMA_RETURN(1);
14917 }
14918 
14919 /*!
14920    \brief Function to update the DimFact of a colorplane
14921    DimFact is the same as BrightFact which is not defined
14922    for explicitly colored planes
14923    -expects SO in data
14924 */
SUMA_cb_ColPlane_NewDimFact(void * data)14925 void SUMA_cb_ColPlane_NewDimFact (void *data)
14926 {
14927    static char FuncName[]={"SUMA_cb_ColPlane_NewDimFact"};
14928    SUMA_ALL_DO *ado=NULL;
14929    SUMA_X_SurfCont *SurfCont=NULL;
14930    SUMA_OVERLAYS *curColPlane=NULL;
14931    SUMA_Boolean LocalHead = NOPE;
14932 
14933    SUMA_ENTRY;
14934 
14935    SUMA_LH("Called");
14936 
14937    ado = (SUMA_ALL_DO *)data;
14938    if (!ado || !(SurfCont=SUMA_ADO_Cont(ado))
14939             || !SurfCont->curColPlane ) SUMA_RETURNe;
14940    curColPlane = SUMA_ADO_CurColPlane(ado);
14941    if (curColPlane->DimFact ==
14942        SurfCont->ColPlaneDimFact->value) SUMA_RETURNe;
14943 
14944    SUMA_ColPlane_NewDimFact(ado, curColPlane,
14945                             SurfCont->ColPlaneDimFact->value, 1);
14946    SUMA_RETURNe;
14947 }
14948 
SUMA_ColPlane_NewDimFact(SUMA_ALL_DO * ado,SUMA_OVERLAYS * colp,float newdimfact,int cb_direct)14949 int SUMA_ColPlane_NewDimFact (SUMA_ALL_DO *ado, SUMA_OVERLAYS *colp,
14950                               float newdimfact, int cb_direct)
14951 {
14952    static char FuncName[]={"SUMA_ColPlane_NewDimFact"};
14953    SUMA_SurfaceObject *SOC=NULL, *SO=NULL;
14954    SUMA_OVERLAYS *colpC=NULL;
14955    SUMA_X_SurfCont *SurfCont=NULL;
14956    SUMA_OVERLAYS *curColPlane=NULL;
14957    SUMA_Boolean LocalHead = NOPE;
14958 
14959    SUMA_ENTRY;
14960 
14961    SUMA_LH("Called");
14962 
14963    if (!ado || !(SurfCont=SUMA_ADO_Cont(ado))) SUMA_RETURN(0);
14964    curColPlane = SUMA_ADO_CurColPlane(ado);
14965    if (!colp) colp = curColPlane;
14966    if (!colp) SUMA_RETURN(0);
14967    if (colp != curColPlane) {
14968       SUMA_S_Err( "Will need to switch to current plane first. "
14969                   "Not ready for this");
14970       SUMA_RETURN(0);
14971    }
14972 
14973    if (!SUMA_ColPlane_NewDimFact_one(ado, colp, newdimfact, cb_direct)) {
14974       SUMA_S_Err("Non son pagliaccio");
14975       SUMA_RETURN(0);
14976    }
14977 
14978    if (ado->do_type == SO_type) {
14979       SO = (SUMA_SurfaceObject *)ado;
14980       colpC = SUMA_Contralateral_overlay(colp, SO, &SOC);
14981       if (colpC && SOC) {
14982          SUMA_LHv("Found contralateral equivalent to:\n"
14983                       " %s and %s in\n"
14984                       " %s and %s\n",
14985                       SO->Label, CHECK_NULL_STR(colp->Label),
14986                       SOC->Label, CHECK_NULL_STR(colpC->Label));
14987          if (SOC->SurfCont->curColPlane != colpC) {
14988             SUMA_S_Err("Don't have contralateral as cur colplane.\n"
14989                        "This should not happen under L/R yoked conditions.");
14990             SUMA_RETURN(0);
14991          }
14992          if (!SUMA_ColPlane_NewDimFact_one((SUMA_ALL_DO *)SOC, colpC,
14993                                            newdimfact, 0)) {
14994             SUMA_S_Warn("Failed in contralateralization");
14995          }
14996       } else {
14997          SUMA_LHv("Found NO contralateral equivalent to:\n"
14998                       " %s and %s in\n",
14999                       SO->Label, CHECK_NULL_STR(colp->Label));
15000       }
15001    }
15002    SUMA_RETURN(1);
15003 }
15004 
SUMA_ColPlane_NewDimFact_one(SUMA_ALL_DO * ado,SUMA_OVERLAYS * colp,float newdimfact,int cb_direct)15005 int SUMA_ColPlane_NewDimFact_one (SUMA_ALL_DO *ado, SUMA_OVERLAYS *colp,
15006                                   float newdimfact, int cb_direct)
15007 {
15008    static char FuncName[]={"SUMA_ColPlane_NewDimFact_one"};
15009    char sbuf[SUMA_MAX_LABEL_LENGTH];
15010    SUMA_X_SurfCont *SurfCont=NULL;
15011    SUMA_OVERLAYS *curColPlane=NULL;
15012    SUMA_Boolean LocalHead = NOPE;
15013 
15014    SUMA_ENTRY;
15015 
15016    SUMA_LH("Called");
15017 
15018    if (!ado || !(SurfCont=SUMA_ADO_Cont(ado))) SUMA_RETURN(0);
15019    curColPlane = SUMA_ADO_CurColPlane(ado);
15020    if (!colp) colp = curColPlane;
15021    if (!colp) SUMA_RETURN(0);
15022    if (colp != curColPlane) {
15023       SUMA_S_Err("Will need to switch current plane. Not ready for this");
15024       SUMA_RETURN(0);
15025    }
15026 
15027    /* change the value of the dimfact */
15028    curColPlane->DimFact = newdimfact;
15029    if (curColPlane->OptScl)
15030       curColPlane->OptScl->BrightFact =
15031                                  curColPlane->DimFact;
15032 
15033    if (LocalHead) fprintf(SUMA_STDERR,"%s: DimFact of %s set to %f.\n",
15034          FuncName, curColPlane->Name,
15035          curColPlane->DimFact);
15036 
15037    SUMA_UpdateColPlaneShellAsNeeded(ado); /* update other open ColPlaneShells */
15038 
15039    /* need to colorize plane */
15040    SUMA_ColorizePlane(curColPlane);
15041 
15042    /* a good remix and redisplay */
15043    SUMA_Remixedisplay (ado);
15044 
15045    /* update color label */
15046    SUMA_UpdateNodeLblField(ado);
15047 
15048    if (!cb_direct && newdimfact != SurfCont->ColPlaneDimFact->value) {
15049       /* force gui match */
15050       sprintf(sbuf,"%.2f", newdimfact);
15051       SurfCont->ColPlaneDimFact->value = newdimfact;
15052       SUMA_SET_TEXT_FIELD(SurfCont->ColPlaneDimFact->textfield, sbuf);
15053    }
15054 
15055    SUMA_RETURN(1);
15056 }
15057 /*!
15058    \brief Function to update the AlphaThresh of a colorplane
15059    AlphaThresh is only valued for volume objects, at the moment
15060    -expects VO in data
15061 */
SUMA_cb_ColPlane_NewAlphaThresh(void * data)15062 void SUMA_cb_ColPlane_NewAlphaThresh (void *data)
15063 {
15064    static char FuncName[]={"SUMA_cb_ColPlane_NewAlphaThresh"};
15065    SUMA_ALL_DO *ado=NULL;
15066    SUMA_X_SurfCont *SurfCont=NULL;
15067    SUMA_OVERLAYS *curColPlane=NULL;
15068    SUMA_Boolean LocalHead = NOPE;
15069 
15070    SUMA_ENTRY;
15071 
15072    SUMA_LH("Called");
15073 
15074    ado = (SUMA_ALL_DO *)data;
15075    if (!ado || !(SurfCont=SUMA_ADO_Cont(ado))
15076             || !SurfCont->curColPlane ) SUMA_RETURNe;
15077    curColPlane = SUMA_ADO_CurColPlane(ado);
15078    if (curColPlane->AlphaThresh ==
15079        SurfCont->ColPlaneAlphaThresh->value) SUMA_RETURNe;
15080 
15081    SUMA_ColPlane_NewAlphaThresh(ado, curColPlane,
15082                             SurfCont->ColPlaneAlphaThresh->value, 1);
15083    SUMA_RETURNe;
15084 }
15085 
SUMA_ColPlane_NewAlphaThresh(SUMA_ALL_DO * ado,SUMA_OVERLAYS * colp,float newAlphaThresh,int cb_direct)15086 int SUMA_ColPlane_NewAlphaThresh (SUMA_ALL_DO *ado, SUMA_OVERLAYS *colp,
15087                               float newAlphaThresh, int cb_direct)
15088 {
15089    static char FuncName[]={"SUMA_ColPlane_NewAlphaThresh"};
15090    SUMA_SurfaceObject *SOC=NULL, *SO=NULL;
15091    SUMA_OVERLAYS *colpC=NULL;
15092    SUMA_X_SurfCont *SurfCont=NULL;
15093    SUMA_OVERLAYS *curColPlane=NULL;
15094    SUMA_Boolean LocalHead = NOPE;
15095 
15096    SUMA_ENTRY;
15097 
15098    SUMA_LH("Called");
15099 
15100    if (!ado || !(SurfCont=SUMA_ADO_Cont(ado))) SUMA_RETURN(0);
15101    curColPlane = SUMA_ADO_CurColPlane(ado);
15102    if (!colp) colp = curColPlane;
15103    if (!colp) SUMA_RETURN(0);
15104    if (colp != curColPlane) {
15105       SUMA_S_Err( "Will need to switch to current plane first. "
15106                   "Not ready for this");
15107       SUMA_RETURN(0);
15108    }
15109 
15110    if (!SUMA_ColPlane_NewAlphaThresh_one(ado, colp, newAlphaThresh, cb_direct)) {
15111       SUMA_S_Err("Non son pagliaccio");
15112       SUMA_RETURN(0);
15113    }
15114 
15115    if (ado->do_type == SO_type) {
15116       SO = (SUMA_SurfaceObject *)ado;
15117       colpC = SUMA_Contralateral_overlay(colp, SO, &SOC);
15118       if (colpC && SOC) {
15119          SUMA_LHv("Found contralateral equivalent to:\n"
15120                       " %s and %s in\n"
15121                       " %s and %s\n",
15122                       SO->Label, CHECK_NULL_STR(colp->Label),
15123                       SOC->Label, CHECK_NULL_STR(colpC->Label));
15124          if (SOC->SurfCont->curColPlane != colpC) {
15125             SUMA_S_Err("Don't have contralateral as cur colplane.\n"
15126                        "This should not happen under L/R yoked conditions.");
15127             SUMA_RETURN(0);
15128          }
15129          if (!SUMA_ColPlane_NewAlphaThresh_one((SUMA_ALL_DO *)SOC, colpC,
15130                                            newAlphaThresh, 0)) {
15131             SUMA_S_Warn("Failed in contralateralization");
15132          }
15133       } else {
15134          SUMA_LHv("Found NO contralateral equivalent to:\n"
15135                       " %s and %s in\n",
15136                       SO->Label, CHECK_NULL_STR(colp->Label));
15137       }
15138    }
15139    SUMA_RETURN(1);
15140 }
15141 
SUMA_ColPlane_NewAlphaThresh_one(SUMA_ALL_DO * ado,SUMA_OVERLAYS * colp,float newAlphaThresh,int cb_direct)15142 int SUMA_ColPlane_NewAlphaThresh_one (SUMA_ALL_DO *ado, SUMA_OVERLAYS *colp,
15143                                   float newAlphaThresh, int cb_direct)
15144 {
15145    static char FuncName[]={"SUMA_ColPlane_NewAlphaThresh_one"};
15146    char sbuf[SUMA_MAX_LABEL_LENGTH];
15147    SUMA_X_SurfCont *SurfCont=NULL;
15148    SUMA_OVERLAYS *curColPlane=NULL;
15149    SUMA_Boolean LocalHead = NOPE;
15150 
15151    SUMA_ENTRY;
15152 
15153    SUMA_LH("Called");
15154 
15155    if (!ado || !(SurfCont=SUMA_ADO_Cont(ado))) SUMA_RETURN(0);
15156    curColPlane = SUMA_ADO_CurColPlane(ado);
15157    if (!colp) colp = curColPlane;
15158    if (!colp) SUMA_RETURN(0);
15159    if (colp != curColPlane) {
15160       SUMA_S_Err("Will need to switch current plane. Not ready for this");
15161       SUMA_RETURN(0);
15162    }
15163 
15164    /* change the value of the AlphaThresh */
15165    curColPlane->AlphaThresh = newAlphaThresh;
15166 
15167    if (LocalHead) fprintf(SUMA_STDERR,"%s: AlphaThresh of %s set to %f.\n",
15168          FuncName, curColPlane->Name,
15169          curColPlane->AlphaThresh);
15170 
15171    SUMA_UpdateColPlaneShellAsNeeded(ado); /* update other open ColPlaneShells */
15172 
15173    /* NO need to colorize plane. That is the whole reason for using AlphaThresh
15174       rather than the threshold slider !
15175       Colorizing the volume is taxing because one has to reload the volume
15176       into the texture memory.... */
15177    /* SUMA_ColorizePlane(curColPlane); */
15178 
15179    /* a good remix and redisplay */
15180    SUMA_Remixedisplay (ado);
15181 
15182    /* update color label */
15183    SUMA_UpdateNodeLblField(ado);
15184 
15185    if (!cb_direct && newAlphaThresh != SurfCont->ColPlaneAlphaThresh->value) {
15186       /* force gui match */
15187       sprintf(sbuf,"%.2f", newAlphaThresh);
15188       SurfCont->ColPlaneAlphaThresh->value = newAlphaThresh;
15189       SUMA_SET_TEXT_FIELD(SurfCont->ColPlaneAlphaThresh->textfield, sbuf);
15190    }
15191 
15192    SUMA_RETURN(1);
15193 }
15194 
SUMA_cb_ColPlane_NewNodeRadGain(void * data)15195 void SUMA_cb_ColPlane_NewNodeRadGain (void *data)
15196 {
15197    static char FuncName[]={"SUMA_cb_ColPlane_NewNodeRadGain"};
15198    SUMA_ALL_DO *ado=NULL;
15199    SUMA_X_SurfCont *SurfCont=NULL;
15200    SUMA_OVERLAYS *curColPlane=NULL;
15201    SUMA_Boolean LocalHead = NOPE;
15202 
15203    SUMA_ENTRY;
15204 
15205    SUMA_LH("Called");
15206 
15207    ado = (SUMA_ALL_DO *)data;
15208    if (!ado || !(SurfCont=SUMA_ADO_Cont(ado))
15209             || !SurfCont->curColPlane ) SUMA_RETURNe;
15210    curColPlane = SUMA_ADO_CurColPlane(ado);
15211    if (curColPlane->NodeRadGain ==
15212        SurfCont->NodeRadGainAF->value) SUMA_RETURNe;
15213 
15214    SUMA_ColPlane_NewNodeRadGain(ado, curColPlane,
15215                             SurfCont->NodeRadGainAF->value, 1);
15216    SUMA_RETURNe;
15217 }
15218 
SUMA_ColPlane_NewNodeRadGain(SUMA_ALL_DO * ado,SUMA_OVERLAYS * colp,float newdimfact,int cb_direct)15219 int SUMA_ColPlane_NewNodeRadGain (SUMA_ALL_DO *ado, SUMA_OVERLAYS *colp,
15220                               float newdimfact, int cb_direct)
15221 {
15222    static char FuncName[]={"SUMA_ColPlane_NewNodeRadGain"};
15223    SUMA_SurfaceObject *SOC=NULL, *SO=NULL;
15224    SUMA_OVERLAYS *colpC=NULL;
15225    SUMA_X_SurfCont *SurfCont=NULL;
15226    SUMA_OVERLAYS *curColPlane=NULL;
15227    SUMA_Boolean LocalHead = NOPE;
15228 
15229    SUMA_ENTRY;
15230 
15231    SUMA_LH("Called");
15232 
15233    if (!ado || !(SurfCont=SUMA_ADO_Cont(ado))) SUMA_RETURN(0);
15234    curColPlane = SUMA_ADO_CurColPlane(ado);
15235    if (!colp) colp = curColPlane;
15236    if (!colp) SUMA_RETURN(0);
15237    if (colp != curColPlane) {
15238       SUMA_S_Err( "Will need to switch to current plane first. "
15239                   "Not ready for this");
15240       SUMA_RETURN(0);
15241    }
15242 
15243    if (!SUMA_ColPlane_NewNodeRadGain_one(ado, colp, newdimfact, cb_direct)) {
15244       SUMA_S_Err("Non son pagliaccio");
15245       SUMA_RETURN(0);
15246    }
15247 
15248    SUMA_RETURN(1);
15249 }
15250 
SUMA_ColPlane_NewNodeRadGain_one(SUMA_ALL_DO * ado,SUMA_OVERLAYS * colp,float newdimfact,int cb_direct)15251 int SUMA_ColPlane_NewNodeRadGain_one (SUMA_ALL_DO *ado, SUMA_OVERLAYS *colp,
15252                                        float newdimfact, int cb_direct)
15253 {
15254    static char FuncName[]={"SUMA_ColPlane_NewNodeRadGain_one"};
15255    char sbuf[SUMA_MAX_LABEL_LENGTH];
15256    SUMA_X_SurfCont *SurfCont=NULL;
15257    SUMA_OVERLAYS *curColPlane=NULL;
15258    SUMA_Boolean LocalHead = NOPE;
15259 
15260    SUMA_ENTRY;
15261 
15262    SUMA_LH("Called");
15263 
15264    if (!ado || !(SurfCont=SUMA_ADO_Cont(ado))) SUMA_RETURN(0);
15265    curColPlane = SUMA_ADO_CurColPlane(ado);
15266    if (!colp) colp = curColPlane;
15267    if (!colp) SUMA_RETURN(0);
15268    if (colp != curColPlane) {
15269       SUMA_S_Err("Will need to switch current plane. Not ready for this");
15270       SUMA_RETURN(0);
15271    }
15272 
15273    /* change the value of the dimfact */
15274    curColPlane->NodeRadGain = newdimfact;
15275 
15276    if (LocalHead) fprintf(SUMA_STDERR,"%s: NodeRadGain of %s set to %f.\n",
15277          FuncName, curColPlane->Name,
15278          curColPlane->NodeRadGain);
15279 
15280    SUMA_UpdateColPlaneShellAsNeeded(ado); /* update other open ColPlaneShells */
15281 
15282    SUMA_ADO_Flush_Pick_Buffer(ado, NULL);
15283 
15284    /* need to colorize plane */
15285    SUMA_ColorizePlane(curColPlane);
15286 
15287    /* a good remix and redisplay */
15288    SUMA_Remixedisplay (ado);
15289 
15290    /* update color label */
15291    SUMA_UpdateNodeLblField(ado);
15292 
15293    if (!cb_direct && newdimfact != SurfCont->NodeRadGainAF->value) {
15294       /* force gui match */
15295       sprintf(sbuf,"%.2f", newdimfact);
15296       SurfCont->NodeRadGainAF->value = newdimfact;
15297       SUMA_SET_TEXT_FIELD(SurfCont->NodeRadGainAF->textfield, sbuf);
15298    }
15299 
15300    SUMA_RETURN(1);
15301 }
15302 
SUMA_cb_ColPlane_NewEdgeThickGain(void * data)15303 void SUMA_cb_ColPlane_NewEdgeThickGain (void *data)
15304 {
15305    static char FuncName[]={"SUMA_cb_ColPlane_NewEdgeThickGain"};
15306    SUMA_ALL_DO *ado=NULL;
15307    SUMA_X_SurfCont *SurfCont=NULL;
15308    SUMA_OVERLAYS *curColPlane=NULL;
15309    SUMA_Boolean LocalHead = NOPE;
15310 
15311    SUMA_ENTRY;
15312 
15313    SUMA_LH("Called");
15314 
15315    ado = (SUMA_ALL_DO *)data;
15316    if (!ado || !(SurfCont=SUMA_ADO_Cont(ado))
15317             || !SurfCont->curColPlane ) SUMA_RETURNe;
15318    curColPlane = SUMA_ADO_CurColPlane(ado);
15319    if (curColPlane->EdgeThickGain ==
15320        SurfCont->EdgeThickGainAF->value) SUMA_RETURNe;
15321 
15322    SUMA_ColPlane_NewEdgeThickGain(ado, curColPlane,
15323                             SurfCont->EdgeThickGainAF->value, 1);
15324    SUMA_RETURNe;
15325 }
15326 
15327 
SUMA_ColPlane_NewEdgeThickGain(SUMA_ALL_DO * ado,SUMA_OVERLAYS * colp,float newdimfact,int cb_direct)15328 int SUMA_ColPlane_NewEdgeThickGain (SUMA_ALL_DO *ado, SUMA_OVERLAYS *colp,
15329                               float newdimfact, int cb_direct)
15330 {
15331    static char FuncName[]={"SUMA_ColPlane_NewEdgeThickGain"};
15332    SUMA_SurfaceObject *SOC=NULL, *SO=NULL;
15333    SUMA_OVERLAYS *colpC=NULL;
15334    SUMA_X_SurfCont *SurfCont=NULL;
15335    SUMA_OVERLAYS *curColPlane=NULL;
15336    SUMA_Boolean LocalHead = NOPE;
15337 
15338    SUMA_ENTRY;
15339 
15340    SUMA_LH("Called");
15341 
15342    if (!ado || !(SurfCont=SUMA_ADO_Cont(ado))) SUMA_RETURN(0);
15343    curColPlane = SUMA_ADO_CurColPlane(ado);
15344    if (!colp) colp = curColPlane;
15345    if (!colp) SUMA_RETURN(0);
15346    if (colp != curColPlane) {
15347       SUMA_S_Err( "Will need to switch to current plane first. "
15348                   "Not ready for this");
15349       SUMA_RETURN(0);
15350    }
15351 
15352    if (!SUMA_ColPlane_NewEdgeThickGain_one(ado, colp, newdimfact, cb_direct)) {
15353       SUMA_S_Err("Non son pagliaccio");
15354       SUMA_RETURN(0);
15355    }
15356 
15357    SUMA_RETURN(1);
15358 }
15359 
SUMA_ColPlane_NewEdgeThickGain_one(SUMA_ALL_DO * ado,SUMA_OVERLAYS * colp,float newdimfact,int cb_direct)15360 int SUMA_ColPlane_NewEdgeThickGain_one (SUMA_ALL_DO *ado, SUMA_OVERLAYS *colp,
15361                                        float newdimfact, int cb_direct)
15362 {
15363    static char FuncName[]={"SUMA_ColPlane_NewEdgeThickGain_one"};
15364    char sbuf[SUMA_MAX_LABEL_LENGTH];
15365    SUMA_X_SurfCont *SurfCont=NULL;
15366    SUMA_OVERLAYS *curColPlane=NULL;
15367    SUMA_Boolean LocalHead = NOPE;
15368 
15369    SUMA_ENTRY;
15370 
15371    SUMA_LH("Called");
15372 
15373    if (!ado || !(SurfCont=SUMA_ADO_Cont(ado))) SUMA_RETURN(0);
15374    curColPlane = SUMA_ADO_CurColPlane(ado);
15375    if (!colp) colp = curColPlane;
15376    if (!colp) SUMA_RETURN(0);
15377    if (colp != curColPlane) {
15378       SUMA_S_Err("Will need to switch current plane. Not ready for this");
15379       SUMA_RETURN(0);
15380    }
15381 
15382    /* change the value of the dimfact */
15383    curColPlane->EdgeThickGain = newdimfact;
15384 
15385    if (LocalHead) fprintf(SUMA_STDERR,"%s: EdgeThickGain of %s set to %f.\n",
15386          FuncName, curColPlane->Name,
15387          curColPlane->EdgeThickGain);
15388 
15389    SUMA_UpdateColPlaneShellAsNeeded(ado); /* update other open ColPlaneShells */
15390 
15391    /* need to colorize plane */
15392    SUMA_ColorizePlane(curColPlane);
15393 
15394    SUMA_ADO_Flush_Pick_Buffer(ado, NULL);
15395 
15396    /* a good remix and redisplay */
15397    SUMA_Remixedisplay (ado);
15398 
15399    /* update color label */
15400    SUMA_UpdateNodeLblField(ado);
15401 
15402    if (!cb_direct && newdimfact != SurfCont->EdgeThickGainAF->value) {
15403       /* force gui match */
15404       sprintf(sbuf,"%.2f", newdimfact);
15405       SurfCont->EdgeThickGainAF->value = newdimfact;
15406       SUMA_SET_TEXT_FIELD(SurfCont->EdgeThickGainAF->textfield, sbuf);
15407    }
15408 
15409    SUMA_RETURN(1);
15410 }
15411 
15412 /*!
15413    \brief Function to set the color remix flag for DOs and call
15414       a redisplay for relevant viewers
15415 */
SUMA_Remixedisplay(SUMA_ALL_DO * ADO)15416 SUMA_Boolean SUMA_Remixedisplay (SUMA_ALL_DO *ADO)
15417 {
15418    static char FuncName[]={"SUMA_Remixedisplay"};
15419    DList *list=NULL;
15420    char *idcode=NULL;
15421    SUMA_Boolean LocalHead = NOPE;
15422 
15423    SUMA_ENTRY;
15424 
15425    SUMA_LHv("Called with ado=%p, ado->do_type=%d, ado->idcode_str=%s\n",
15426       ADO, ADO?ADO->do_type:-1, SUMA_CHECK_NULL_STR(SUMA_ADO_idcode(ADO)));
15427 
15428    /* remix colors for all viewers displaying related surfaces */
15429    switch (ADO->do_type) {
15430       case SO_type:
15431       case VO_type:
15432       case MASK_type:
15433       case TRACT_type:
15434       case CDOM_type:
15435       case GDSET_type:
15436          idcode = SUMA_ADO_idcode(ADO);
15437          break;
15438       case GRAPH_LINK_type: {
15439          SUMA_DSET *dset = SUMA_find_GLDO_Dset((SUMA_GraphLinkDO *)ADO);
15440          idcode = SUMA_ADO_idcode((SUMA_ALL_DO *)dset);
15441          break; }
15442       default:
15443          SUMA_S_Errv("Not ready for type %s\n", ADO_TNAME(ADO));
15444          SUMA_RETURN(NOPE);
15445          break;
15446    }
15447 
15448 
15449    if (!SUMA_SetRemixFlag(idcode, SUMAg_SVv, SUMAg_N_SVv)) {
15450       SUMA_SLP_Err("Failed in SUMA_SetRemixFlag.");
15451       SUMA_RETURN(NOPE);
15452    }
15453 
15454    /* redisplay */
15455    if (!list) list = SUMA_CreateList ();
15456    SUMA_REGISTER_TAIL_COMMAND_NO_DATA( list, SE_RedisplayNow_AllVisible,
15457                                        SES_Suma, NULL);
15458    if (!SUMA_Engine(&list)) {
15459       SUMA_SLP_Err("Failed to redisplay.");
15460       SUMA_RETURN(NOPE);
15461    }
15462 
15463    SUMA_RETURN(YUP);
15464 }
15465 
15466 /*!
15467    \brief callback to deal with show/hide colorplane toggle
15468 
15469    -expects SO in data
15470 */
SUMA_cb_ColPlaneShow_toggled(Widget w,XtPointer data,XtPointer client_data)15471 void SUMA_cb_ColPlaneShow_toggled ( Widget w, XtPointer data,
15472                                     XtPointer client_data)
15473 {
15474    static char FuncName[]={"SUMA_cb_ColPlaneShow_toggled"};
15475    SUMA_SurfaceObject *SO = NULL;
15476    SUMA_Boolean LocalHead = NOPE;
15477 
15478    SUMA_ENTRY;
15479 
15480    SUMA_LH("Called");
15481 
15482    SUMA_S_Warn("Obsolete, do not call me!");
15483    SUMA_RETURNe;
15484 
15485    #if 0
15486    SO = (SUMA_SurfaceObject *)data;
15487 
15488    if (!SO || !SO->SurfCont) SUMA_RETURNe;
15489    if (!SO->SurfCont->curColPlane ||
15490        !SO->SurfCont->ColPlaneShow_tb) SUMA_RETURNe;
15491 
15492    SUMA_LH("Getting State");
15493    SO->SurfCont->curColPlane->Show =
15494       XmToggleButtonGetState (SO->SurfCont->ColPlaneShow_tb);
15495    if (SO->SurfCont->Int_tb) {
15496       /* set the duplicate button next to int */
15497       SUMA_LH("Setting State of duplicate button");
15498       XmToggleButtonSetState (SO->SurfCont->Int_tb,
15499                               SO->SurfCont->curColPlane->Show, NOPE);
15500    }
15501    SUMA_LH("Updating color plane shells");
15502    SUMA_UpdateColPlaneShellAsNeeded(SO); /* update other open ColPlaneShells */
15503 
15504    SUMA_Remixedisplay((SUMA_ALL_DO*)SO);
15505    SUMA_UpdateNodeLblField(NULL,SO);
15506 
15507    SUMA_RETURNe;
15508    #endif
15509 }
15510 
15511 /*!
15512    \brief callback to deal with show only one colorplane toggle
15513 
15514    -expects SO in data
15515 */
SUMA_cb_ColPlaneShowOneFore_toggled(Widget w,XtPointer data,XtPointer client_data)15516 void SUMA_cb_ColPlaneShowOneFore_toggled (Widget w, XtPointer data,
15517                                           XtPointer client_data)
15518 {
15519    static char FuncName[]={"SUMA_cb_ColPlaneShowOneFore_toggled"};
15520    SUMA_X_SurfCont *SurfCont=NULL;
15521    SUMA_ALL_DO *ado=NULL;
15522    SUMA_OVERLAYS *curColPlane=NULL;
15523    SUMA_Boolean LocalHead = NOPE;
15524 
15525    SUMA_ENTRY;
15526 
15527    SUMA_LH("Called");
15528 
15529    ado = (SUMA_ALL_DO *)data;
15530 
15531    SurfCont = SUMA_ADO_Cont(ado);
15532    curColPlane = SUMA_ADO_CurColPlane(ado);
15533    if (!curColPlane) SUMA_RETURNe;
15534 
15535    SUMA_ColPlaneShowOneFore_Set(ado,
15536                XmToggleButtonGetState (SurfCont->ColPlaneShowOneFore_tb), 1);
15537 
15538    SUMA_RETURNe;
15539 }
15540 
SUMA_ColPlaneShowOneFore_Set_one(SUMA_ALL_DO * ado,SUMA_Boolean state,int cb_direct)15541 int SUMA_ColPlaneShowOneFore_Set_one ( SUMA_ALL_DO *ado,
15542                                        SUMA_Boolean state, int cb_direct)
15543 {
15544    static char FuncName[]={"SUMA_ColPlaneShowOneFore_Set_one"};
15545    SUMA_X_SurfCont *SurfCont=NULL;
15546    SUMA_OVERLAYS *curColPlane=NULL;
15547 
15548    SUMA_ENTRY;
15549 
15550 
15551    if (!(SurfCont=SUMA_ADO_Cont(ado))) SUMA_RETURN(0);
15552    if (!SUMA_isADO_Cont_Realized(ado)) SUMA_RETURN(0);
15553 
15554    if (SurfCont->ShowCurForeOnly == state) SUMA_RETURN(1);
15555 
15556    SurfCont->ShowCurForeOnly = state;
15557    XmToggleButtonSetState (SurfCont->ColPlaneShowOneFore_tb,
15558                            SurfCont->ShowCurForeOnly, NOPE);
15559 
15560    SUMA_UpdateColPlaneShellAsNeeded(ado); /* update other open ColPlaneShells */
15561 
15562    SUMA_Remixedisplay(ado);
15563    SUMA_UpdateNodeLblField(ado);
15564 
15565    SUMA_RETURN(1);
15566 }
15567 
SUMA_ColPlaneShowOneFore_Set(SUMA_ALL_DO * ado,SUMA_Boolean state,int cb_direct)15568 int SUMA_ColPlaneShowOneFore_Set ( SUMA_ALL_DO *ado,
15569                                    SUMA_Boolean state, int cb_direct)
15570 {
15571    static char FuncName[]={"SUMA_ColPlaneShowOneFore_Set"};
15572    SUMA_SurfaceObject *SOC=NULL, *SO=NULL;
15573    SUMA_OVERLAYS *colpC=NULL, *colp=NULL;
15574    SUMA_X_SurfCont *SurfCont=NULL;
15575    SUMA_OVERLAYS *curColPlane=NULL;
15576    SUMA_Boolean LocalHead = NOPE;
15577 
15578    SUMA_ENTRY;
15579 
15580    if (!(SurfCont=SUMA_ADO_Cont(ado))) SUMA_RETURN(0);
15581    if (!SUMA_isADO_Cont_Realized(ado)) SUMA_RETURN(0);
15582 
15583 
15584    if (!SUMA_ColPlaneShowOneFore_Set_one (ado, state, cb_direct)) {
15585       SUMA_S_Err("Returning on an angry note");
15586       SUMA_RETURN(0);
15587    }
15588 
15589    if (ado->do_type == SO_type) {
15590       SO = (SUMA_SurfaceObject *)ado;
15591       colp = SO->SurfCont->curColPlane;
15592       colpC = SUMA_Contralateral_overlay(colp, SO, &SOC);
15593       if (colpC && SOC) {
15594          SUMA_LHv("Found contralateral equivalent to:\n"
15595                       " %s and %s in\n"
15596                       " %s and %s\n",
15597                       SO->Label, CHECK_NULL_STR(colp->Label),
15598                       SOC->Label, CHECK_NULL_STR(colpC->Label));
15599          if (SOC->SurfCont->curColPlane != colpC) {
15600             SUMA_S_Err("Don't have contralateral as cur colplane.\n"
15601                        "This should not happen under L/R yoked conditions.");
15602             SUMA_RETURN(0);
15603          }
15604          if (!SUMA_ColPlaneShowOneFore_Set_one ((SUMA_ALL_DO *)SOC, state, 0)) {
15605             SUMA_S_Err("Returning on an cranky note");
15606             SUMA_RETURN(0);
15607          }
15608       } else {
15609          SUMA_LHv("Found NO contralateral equivalent to:\n"
15610                       " %s and %s in\n",
15611                       SO->Label, CHECK_NULL_STR(colp->Label));
15612       }
15613    }
15614 
15615    SUMA_RETURN(1);
15616 }
15617 
SUMA_cb_GDSET_ShowBundles_toggled(Widget w,XtPointer data,XtPointer client_data)15618 void SUMA_cb_GDSET_ShowBundles_toggled (Widget w, XtPointer data,
15619                                           XtPointer client_data)
15620 {
15621    static char FuncName[]={"SUMA_cb_GDSET_ShowBundles_toggled"};
15622    SUMA_X_SurfCont *SurfCont=NULL;
15623    SUMA_ALL_DO *ado=NULL;
15624    SUMA_Boolean LocalHead = NOPE;
15625 
15626    SUMA_ENTRY;
15627 
15628    SUMA_LH("Called");
15629 
15630    ado = (SUMA_ALL_DO *)data;
15631 
15632    SurfCont = SUMA_ADO_Cont(ado);
15633    if (!SurfCont) SUMA_RETURNe;
15634 
15635    SUMA_GDSET_ShowBundles(ado,
15636                XmToggleButtonGetState (SurfCont->GDSET_ShowBundles_tb), 1);
15637 
15638    SUMA_RETURNe;
15639 }
15640 
SUMA_cb_GDSET_ShowUncon_toggled(Widget w,XtPointer data,XtPointer client_data)15641 void SUMA_cb_GDSET_ShowUncon_toggled (Widget w, XtPointer data,
15642                                           XtPointer client_data)
15643 {
15644    static char FuncName[]={"SUMA_cb_GDSET_ShowUncon_toggled"};
15645    SUMA_X_SurfCont *SurfCont=NULL;
15646    SUMA_ALL_DO *ado=NULL;
15647    SUMA_Boolean LocalHead = NOPE;
15648 
15649    SUMA_ENTRY;
15650 
15651    SUMA_LH("Called");
15652 
15653    ado = (SUMA_ALL_DO *)data;
15654 
15655    SurfCont = SUMA_ADO_Cont(ado);
15656    if (!SurfCont) SUMA_RETURNe;
15657 
15658    SUMA_GDSET_ShowUncon(ado,
15659                XmToggleButtonGetState (SurfCont->GDSET_ShowUncon_tb), 1);
15660 
15661    SUMA_RETURNe;
15662 }
15663 
SUMA_FlushPickBufferForDO(SUMA_ALL_DO * curDO)15664 int SUMA_FlushPickBufferForDO(SUMA_ALL_DO *curDO)
15665 {
15666    static char FuncName[]={"SUMA_FlushPickBufferForDO"};
15667    int i=0, iup=0;
15668    SUMA_SurfaceViewer *sv=NULL;
15669 
15670    SUMA_ENTRY;
15671 
15672    if (!curDO) SUMA_RETURN(0);
15673 
15674    /* update any viewer that is showing this
15675       surface */
15676    for (i=0; i<SUMAg_N_SVv; ++i) {
15677       if (!SUMAg_SVv[i].isShaded && SUMAg_SVv[i].X->TOPLEVEL) {
15678          /* is this viewer showing curSO ? */
15679          if (SUMA_isRegisteredDO(&(SUMAg_SVv[i]), SUMAg_DOv, curDO)) {
15680             sv = &(SUMAg_SVv[i]);
15681             SUMA_PickBuffer(sv, 0, NULL); /* flush pick buffer */
15682             ++iup;
15683          }
15684       }
15685    }
15686 
15687    SUMA_RETURN(iup);
15688 }
15689 
15690 
SUMA_GDSET_ShowBundles(SUMA_ALL_DO * ado,SUMA_Boolean state,int cb_direct)15691 int SUMA_GDSET_ShowBundles ( SUMA_ALL_DO *ado,
15692                                 SUMA_Boolean state, int cb_direct)
15693 {
15694    static char FuncName[]={"SUMA_GDSET_ShowBundles"};
15695    SUMA_X_SurfCont *SurfCont=NULL;
15696    SUMA_GRAPH_SAUX *GSaux = NULL;
15697    SUMA_ENTRY;
15698 
15699 
15700    if (!(SurfCont=SUMA_ADO_Cont(ado))) SUMA_RETURN(0);
15701    if (!SUMA_isADO_Cont_Realized(ado)) SUMA_RETURN(0);
15702    if (!(GSaux = SUMA_ADO_GSaux(ado))) SUMA_RETURN(0);
15703 
15704    if (GSaux->ShowBundles == state) SUMA_RETURN(1);
15705 
15706    GSaux->ShowBundles = state;
15707    XmToggleButtonSetState (SurfCont->GDSET_ShowBundles_tb,
15708                            GSaux->ShowBundles, NOPE);
15709    /* flush pick buffer */
15710    SUMA_FlushPickBufferForDO(ado);
15711 
15712    SUMA_Remixedisplay(ado);
15713 
15714    SUMA_RETURN(1);
15715 }
15716 
SUMA_GDSET_ShowUncon(SUMA_ALL_DO * ado,SUMA_Boolean state,int cb_direct)15717 int SUMA_GDSET_ShowUncon ( SUMA_ALL_DO *ado,
15718                                 SUMA_Boolean state, int cb_direct)
15719 {
15720    static char FuncName[]={"SUMA_GDSET_ShowUncon"};
15721    SUMA_X_SurfCont *SurfCont=NULL;
15722    SUMA_GRAPH_SAUX *GSaux = NULL;
15723    SUMA_ENTRY;
15724 
15725 
15726    if (!(SurfCont=SUMA_ADO_Cont(ado))) SUMA_RETURN(0);
15727    if (!SUMA_isADO_Cont_Realized(ado)) SUMA_RETURN(0);
15728    if (!(GSaux = SUMA_ADO_GSaux(ado))) SUMA_RETURN(0);
15729 
15730    if (GSaux->ShowUncon == state) SUMA_RETURN(1);
15731 
15732    GSaux->ShowUncon = state;
15733    XmToggleButtonSetState (SurfCont->GDSET_ShowUncon_tb,
15734                            GSaux->ShowUncon, NOPE);
15735    /* flush pick buffer */
15736    SUMA_FlushPickBufferForDO(ado);
15737 
15738    SUMA_Remixedisplay(ado);
15739 
15740    SUMA_RETURN(1);
15741 }
15742 
15743 /*!
15744  \brief Function based on arrow_time.c program from Motif Programing Manual
15745 
15746  change_value is called each time the timer expires.  This function
15747  * is also used to initiate the timer.  The "id" represents that timer
15748  * ID returned from the last call to XtAppAddTimeOut().  If id == 1,
15749  * the function was called from start_stop(), not a timeout.  If the value
15750  * has reached its maximum or minimum, don't restart timer, just return.
15751  * If id == 1, this is the first timeout so make it be longer to allow
15752  * the user to release the button and avoid getting into the "speedy"
15753  * part of the timeouts.
15754  */
SUMA_ATF_change_value(XtPointer client_data,XtIntervalId * id)15755 void SUMA_ATF_change_value(XtPointer client_data, XtIntervalId *id)
15756 {
15757    static char FuncName[]={"SUMA_ATF_change_value"};
15758    float ArrowTolerance = 0.0001; /* roundoff and truncation headaches ... */
15759    int incr;
15760    SUMA_ARROW_TEXT_FIELD * AF= NULL;
15761    SUMA_Boolean LocalHead = NOPE;
15762 
15763    SUMA_ENTRY;
15764 
15765    AF = (SUMA_ARROW_TEXT_FIELD *)client_data;
15766 
15767    if (!AF->wrap) {
15768       if (AF->value + AF->direction * AF->step > (AF->max + ArrowTolerance) ||
15769         AF->value + AF->direction * AF->step < (AF->min - ArrowTolerance) ) {
15770            SUMA_RETURNe;
15771       }
15772    }
15773 
15774    AF->value += AF->direction * AF->step;
15775 
15776    if (AF->wrap) SUMA_WRAP_VALUE(AF->value, AF->min, AF->max);
15777 
15778    /* round to the tolerance */
15779    if (LocalHead)
15780       fprintf (SUMA_STDERR, "%s: Pre Tolerance %f\n", FuncName, AF->value);
15781    /* if no negs allowed, take absolute value.
15782       Round off errors can cause AF->value to show -0.00000001
15783       or something ugly like that*/
15784    if (AF->min >= 0.0 && AF->value < 0.0) AF->value = 0.0;
15785    if (LocalHead)
15786       fprintf (SUMA_STDERR, "%s: Post Tolerance %f\n", FuncName, AF->value);
15787 
15788    SUMA_ATF_SetString (AF);
15789 
15790    if (id) {
15791       AF->arrow_timer_id =
15792          XtAppAddTimeOut (SUMAg_CF->X->App, (INT_CAST)id==1? 500 : 100,
15793                            SUMA_ATF_change_value, (XtPointer)AF);
15794    }
15795    /* turn off the modified field because it should only be on
15796       when the user edits the field */
15797    SUMA_RETURNe;
15798 }
15799 
15800 /*!
15801    \brief updates string based on ROI value in the Arrowfield
15802 */
SUMA_ATF_SetString(SUMA_ARROW_TEXT_FIELD * AF)15803 void SUMA_ATF_SetString (SUMA_ARROW_TEXT_FIELD * AF)
15804 {
15805    static char FuncName[]={"SUMA_ATF_SetString"};
15806    char buf[36];
15807 
15808    SUMA_ENTRY;
15809 
15810    if (AF->type == SUMA_int) {
15811       sprintf (buf, "%-4d", (int)AF->value);
15812    }else if (AF->type == SUMA_float) {
15813       sprintf (buf, "%-4.4f", AF->value);
15814    }else {
15815       /* fair enough, this is a text field, nothing to be done for value*/
15816       SUMA_RETURNe;
15817    }
15818    XtVaSetValues (AF->textfield, XmNvalue, buf, NULL);
15819 
15820    SUMA_RETURNe;
15821 }
15822 
SUMA_ATF_GetString(SUMA_ARROW_TEXT_FIELD * AF,char * sbuf)15823 void SUMA_ATF_GetString (SUMA_ARROW_TEXT_FIELD * AF, char *sbuf)
15824 {
15825    static char FuncName[]={"SUMA_ATF_GetString"};
15826 
15827    SUMA_ENTRY;
15828 
15829    sbuf[0]='\0';
15830 
15831    if (AF->type == SUMA_int) {
15832       snprintf (sbuf, 62, "%-4d", (int)AF->value);
15833    }else if (AF->type == SUMA_float) {
15834       snprintf (sbuf, 62, "%-4.4f", AF->value);
15835    }else if (AF->type == SUMA_string) { /* This AF is a text field, should
15836                                            not have a 'value' */
15837       snprintf (sbuf, 62, "Text-Field");
15838    } else {
15839       snprintf(sbuf, 62, "UnGettable");
15840    }
15841 
15842    SUMA_RETURNe;
15843 }
15844 
15845 /*!
15846    \brief sets the value of Arrowfield based on string
15847 */
SUMA_ATF_SetValue(SUMA_ARROW_TEXT_FIELD * AF)15848 void SUMA_ATF_SetValue (SUMA_ARROW_TEXT_FIELD * AF)
15849 {
15850    static char FuncName[]={"SUMA_ATF_SetValue"};
15851    double val;
15852    void *n = NULL;
15853    SUMA_Boolean LocalHead = NOPE;
15854 
15855    SUMA_ENTRY;
15856 
15857 
15858    XtVaGetValues (AF->textfield, XmNvalue, &n, NULL);
15859    /* YOU DO NOT WANT TO FREE n because n is not a
15860       copy of the string in the widget!
15861       Later in time:
15862       Hmmmm, maybe you do, maybe you do. Must abide by
15863       upper case message. Must have crashed somwhere */
15864 
15865    SUMA_LHv("Read %s\n", (char *)n);
15866 
15867    if (!SUMA_strtod((char*)n, &val)){
15868       /* bad syntax, reset value*/
15869       SUMA_LHv("Bad syntax, got %f.\n", val);
15870       SUMA_RegisterMessage (SUMAg_CF->MessageList,
15871             "Bad value in text field", FuncName, SMT_Error, SMA_Log);
15872       SUMA_ATF_SetString (AF);
15873    }else {
15874       if (AF->type == SUMA_int) {
15875          AF->value = (int)val;
15876          if (AF->wrap) {
15877             SUMA_WRAP_VALUE(AF->value, AF->min, AF->max);
15878          } else {
15879             SUMA_CLIP_VALUE(AF->value, AF->min, AF->max);
15880          }
15881 
15882          /* now call set string just to be sure users did not enter floats */
15883          SUMA_ATF_SetString (AF);
15884       } else {
15885          AF->value = val;
15886          if (AF->wrap) {
15887             SUMA_WRAP_VALUE(AF->value, AF->min, AF->max);
15888          } else {
15889             SUMA_CLIP_VALUE(AF->value, AF->min, AF->max);
15890          }
15891          /* It is still nice to call SetString because it puts the
15892             cursor at the beginning of the field */
15893          SUMA_ATF_SetString (AF);
15894 
15895       }
15896    }
15897 
15898    SUMA_RETURNe;
15899 }
15900 
15901 /*!
15902    \brief Callback for Group button
15903    -Expects sv in data
15904 */
SUMA_cb_ViewerCont_SwitchGroup(Widget w,XtPointer data,XtPointer call_data)15905 void SUMA_cb_ViewerCont_SwitchGroup (  Widget w, XtPointer data,
15906                                        XtPointer call_data)
15907 {
15908    static char FuncName[]={"SUMA_cb_ViewerCont_SwitchGroup"};
15909    SUMA_SurfaceViewer *sv=NULL;
15910    SUMA_LIST_WIDGET *LW = NULL;
15911    SUMA_Boolean LocalHead = NOPE;
15912 
15913    SUMA_ENTRY;
15914 
15915    sv = (SUMA_SurfaceViewer *)data;
15916 
15917    LW = sv->X->ViewCont->SwitchGrouplst;
15918 
15919    if (LW->ALS) {
15920       /* free that old hag */
15921       if (LocalHead) SUMA_S_Err("Freeing the hag.");
15922       LW->ALS = SUMA_FreeAssembleListStruct(LW->ALS);
15923    }
15924 
15925    /* assemble the ROI list */
15926    LW->ALS = SUMA_AssembleGroupList (sv);
15927 
15928    if (!LW->ALS) {
15929       SUMA_SLP_Err("Error assembling list.");
15930       SUMA_RETURNe;
15931    }
15932 
15933    if (LW->ALS->N_clist < 0) {
15934       SUMA_SL_Err("Failed in SUMA_AssembleGroupList");
15935       SUMA_RETURNe;
15936    }
15937 
15938    if (!LW->ALS->N_clist) {
15939       SUMA_SLP_Note ("No Groups to choose from.");
15940       SUMA_RETURNe;
15941    }
15942 
15943    SUMA_CreateScrolledList ( LW->ALS->clist, LW->ALS->N_clist, NOPE,
15944                              LW);
15945 
15946    SUMA_RETURNe;
15947 }
15948 /*!
15949    \brief Callback for Group button
15950    -Expects sv in data
15951 */
SUMA_cb_ViewerCont_SwitchState(Widget w,XtPointer data,XtPointer call_data)15952 void SUMA_cb_ViewerCont_SwitchState (Widget w, XtPointer data,
15953                                      XtPointer call_data)
15954 {
15955    static char FuncName[]={"SUMA_cb_ViewerCont_SwitchState"};
15956    SUMA_SurfaceViewer *sv=NULL;
15957    SUMA_Boolean LocalHead = NOPE;
15958 
15959    SUMA_ENTRY;
15960 
15961    sv = (SUMA_SurfaceViewer *)data;
15962 
15963    SUMA_SLP_Warn( "Not implemented yet.\n"
15964                   "Use ',' and '.' keys\n");
15965 
15966    SUMA_RETURNe;
15967 }
15968 
15969 /*!
15970    \brief Callback for Switch Col Plane button
15971    -Expects SO in data
15972 */
SUMA_cb_SurfCont_SwitchColPlane(Widget w,XtPointer data,XtPointer call_data)15973 void SUMA_cb_SurfCont_SwitchColPlane (Widget w, XtPointer data,
15974                                       XtPointer call_data)
15975 {
15976    static char FuncName[]={"SUMA_cb_SurfCont_SwitchColPlane"};
15977    SUMA_Boolean LocalHead = NOPE;
15978    SUMA_ALL_DO *ado = NULL;
15979 
15980    SUMA_ENTRY;
15981 
15982    SUMA_LH("Called");
15983    ado = (SUMA_ALL_DO *)data;
15984 
15985    SUMA_RefreshDsetList (ado);
15986 
15987    SUMA_RETURNe;
15988 }
15989 /*!
15990    \brief Callback for Switch ROI button
15991 
15992    -Expects LW in data
15993 */
SUMA_cb_DrawROI_SwitchROI(Widget w,XtPointer data,XtPointer call_data)15994 void SUMA_cb_DrawROI_SwitchROI (Widget w, XtPointer data, XtPointer call_data)
15995 {
15996    static char FuncName[]={"SUMA_cb_DrawROI_SwitchROI"};
15997    SUMA_Boolean LocalHead = NOPE;
15998    SUMA_LIST_WIDGET *LW = NULL;
15999 
16000    SUMA_ENTRY;
16001 
16002    LW = (SUMA_LIST_WIDGET *)data;
16003 
16004    if (LW->ALS) {
16005       /* free that old hag */
16006       if (LocalHead) SUMA_S_Err("Freeing the hag.");
16007       LW->ALS = SUMA_FreeAssembleListStruct(LW->ALS);
16008    }
16009    /* assemble the ROI list */
16010    LW->ALS = SUMA_AssembleAllROIList (SUMAg_DOv, SUMAg_N_DOv, YUP);
16011 
16012    if (!LW->ALS) {
16013       SUMA_SLP_Err("Error assembling list.");
16014       SUMA_RETURNe;
16015    }
16016 
16017    if (LW->ALS->N_clist < 0) {
16018       SUMA_SL_Err("Failed in SUMA_AssembleAllROIList");
16019       SUMA_RETURNe;
16020    }
16021 
16022    if (!LW->ALS->N_clist) {
16023       SUMA_SLP_Note ("No ROIs to choose from.");
16024       SUMA_RETURNe;
16025    }
16026    SUMA_CreateScrolledList ( LW->ALS->clist, LW->ALS->N_clist, NOPE,
16027                              LW);
16028 
16029    SUMA_RETURNe;
16030 }
16031 
16032 /*!
16033    \brief Toggles the draw ROI mode
16034 */
SUMA_cb_DrawROImode_toggled(Widget w,XtPointer data,XtPointer call_data)16035 void SUMA_cb_DrawROImode_toggled (Widget w, XtPointer data, XtPointer call_data)
16036 {
16037    static char FuncName[] = {"SUMA_cb_DrawROImode_toggled"};
16038 
16039    SUMA_ENTRY;
16040 
16041    SUMAg_CF->ROI_mode = !SUMAg_CF->ROI_mode;
16042    if (SUMAg_CF->ROI_mode) SUMA_ResetPrying(NULL);
16043    /* take care of sensitivity of Pen button */
16044    if (!SUMAg_CF->ROI_mode) XtSetSensitive (SUMAg_CF->X->DrawROI->Penmode_tb, 0);
16045    else XtSetSensitive (SUMAg_CF->X->DrawROI->Penmode_tb, 1);
16046 
16047    SUMA_UpdateAllViewerCursor();
16048 
16049    SUMA_RETURNe;
16050 
16051 }
16052 /*!
16053    \brief Toggles the contour ROI mode
16054 */
SUMA_cb_ContROImode_toggled(Widget w,XtPointer data,XtPointer call_data)16055 void SUMA_cb_ContROImode_toggled (Widget w, XtPointer data, XtPointer call_data)
16056 {
16057    static char FuncName[] = {"SUMA_cb_ContROImode_toggled"};
16058    DList *list=NULL;
16059    SUMA_ENTRY;
16060 
16061    SUMAg_CF->ROI_contmode = !SUMAg_CF->ROI_contmode;
16062 
16063 
16064    /* redisplay */
16065    if (!list) list = SUMA_CreateList ();
16066    SUMA_REGISTER_TAIL_COMMAND_NO_DATA(list,
16067                                       SE_RedisplayNow_AllVisible,
16068                                       SES_Suma, NULL);
16069    if (!SUMA_Engine(&list)) {
16070       SUMA_SLP_Err("Failed to redisplay.");
16071       SUMA_RETURNe;
16072    }
16073 
16074    SUMA_RETURNe;
16075 
16076 }
16077 /*!
16078    \brief Toggles the pen mode
16079 */
16080 
SUMA_cb_DrawROIPen_toggled(Widget w,XtPointer data,XtPointer call_data)16081 void SUMA_cb_DrawROIPen_toggled (Widget w, XtPointer data, XtPointer call_data)
16082 {
16083    static char FuncName[] = {"SUMA_cb_DrawROIPen_toggled"};
16084 
16085    SUMA_ENTRY;
16086 
16087    SUMAg_CF->Pen_mode = !SUMAg_CF->Pen_mode;
16088 
16089    SUMA_UpdateAllViewerCursor();
16090 
16091    SUMA_RETURNe;
16092 
16093 }
16094 
16095 
16096 /*!
16097    \brief Toggles the Afni link mode
16098 */
SUMA_cb_AfniLink_toggled(Widget w,XtPointer data,XtPointer call_data)16099 void SUMA_cb_AfniLink_toggled (Widget w, XtPointer data, XtPointer call_data)
16100 {
16101    static char FuncName[] = {"SUMA_cb_AfniLink_toggled"};
16102    DList *list=NULL;
16103    SUMA_STANDARD_CMAP cmap;
16104    SUMA_EngineData *ED = NULL;
16105    SUMA_Boolean LocalHead = NOPE;
16106 
16107    SUMA_ENTRY;
16108 
16109    SUMAg_CF->ROI2afni = !SUMAg_CF->ROI2afni;
16110 
16111    /* make sure that is OK */
16112    /* Same here, need to handle SUMA_TO_MATLAB_STREAM_INDEX */
16113    if (SUMAg_CF->ROI2afni && !SUMAg_CF->Connected_v[SUMA_AFNI_STREAM_INDEX]) {
16114       SUMAg_CF->ROI2afni = NOPE;
16115 
16116       SUMA_SLP_Err(  "Cannot link to Afni.\n"
16117                      "No connection found.");
16118       XmToggleButtonSetState (SUMAg_CF->X->DrawROI->AfniLink_tb,
16119                               SUMAg_CF->ROI2afni, NOPE);
16120    }
16121 
16122    if (SUMAg_CF->ROI2afni) {
16123       if (SUMAg_CF->ROI_CM) {
16124          if (LocalHead) fprintf (SUMA_STDERR,"%s: Sending cmap (%s)\n",
16125             FuncName,  SUMAg_CF->ROI_CM->Name);
16126             SUMA_LH("Sending colormap to afni ...");
16127          /* send the color map for ROI to afni */
16128          cmap = SUMA_StandardMapIndex (SUMAg_CF->ROI_CM->Name);
16129          if (LocalHead) fprintf (SUMA_STDERR,"%s: Sending cmap %d (%s)\n",
16130             FuncName, cmap, SUMAg_CF->ROI_CM->Name);
16131          list = SUMA_CreateList();
16132          ED = SUMA_InitializeEngineListData (SE_SendColorMapToAfni);
16133          if (!SUMA_RegisterEngineListCommand (  list, ED,
16134                                                 SEF_i, (void*)&cmap,
16135                                                 SES_SumaWidget, NULL, NOPE,
16136                                                 SEI_Head, NULL )) {
16137             fprintf( SUMA_STDERR,
16138                      "Error %s: Failed to register command\n", FuncName);
16139             SUMA_RETURNe;
16140          }
16141          SUMA_LH("NOW!");
16142          if (!SUMA_Engine (&list)) {
16143             fprintf(stderr, "Error %s: SUMA_Engine call failed.\n", FuncName);
16144          }
16145       }
16146    }
16147    SUMA_RETURNe;
16148 
16149 }
16150 
SUMA_SelectSwitchColPlane_one(SUMA_ALL_DO * ado,SUMA_LIST_WIDGET * LW,int ichoice,SUMA_Boolean CloseShop,int setmen)16151 int SUMA_SelectSwitchColPlane_one(SUMA_ALL_DO *ado,
16152                                   SUMA_LIST_WIDGET *LW,
16153                                   int ichoice, SUMA_Boolean CloseShop,
16154                                   int setmen)
16155 {
16156    static char FuncName[]={"SUMA_SelectSwitchColPlane_one"};
16157    SUMA_OVERLAYS *ColPlane=NULL;
16158    SUMA_X_SurfCont *SurfCont=NULL;
16159    SUMA_OVERLAYS *curColPlane=NULL;
16160    SUMA_Boolean LocalHead = NOPE;
16161 
16162    SUMA_ENTRY;
16163 
16164    if (!ado || !LW) SUMA_RETURN(0);
16165    SurfCont = SUMA_ADO_Cont(ado);
16166 
16167    /* retrieve that choice from the SUMA_ASSEMBLE_LIST_STRUCT
16168       structure and initialize the drawing window */
16169    if (LW->ALS) {
16170       if (LocalHead)
16171          fprintf (SUMA_STDERR,"%s: N_clist = %d\n", FuncName, LW->ALS->N_clist);
16172       if (LW->ALS->N_clist > ichoice) {
16173          ColPlane = (SUMA_OVERLAYS *)LW->ALS->oplist[ichoice];
16174          if (LocalHead)
16175             fprintf (SUMA_STDERR,"%s: Retrieved ColPlane named %s\n",
16176                      FuncName, ColPlane->Name);
16177          SUMA_InitializeColPlaneShell(ado, ColPlane);
16178          SUMA_UpdateColPlaneShellAsNeeded(ado); /* update other open
16179                                                    ColPlaneShells */
16180          SUMA_UpdateNodeField(ado);
16181          SUMA_UpdateCrossHairNodeLabelFieldForDO(ado);
16182          /* If you're viewing one plane at a time, do a remix */
16183          if (SurfCont->ShowCurForeOnly)
16184             SUMA_Remixedisplay(ado);
16185       }
16186    } else {
16187       if (LocalHead) fprintf (SUMA_STDERR,"%s: NULL ALS\n", FuncName);
16188    }
16189 
16190    if (CloseShop) {
16191       SUMA_cb_CloseSwitchColPlane( NULL,
16192                         (XtPointer)SurfCont->SwitchDsetlst,  NULL);
16193    }
16194 
16195    SUMA_RETURN(1);
16196 }
16197 
SUMA_SelectSwitchColPlane(SUMA_ALL_DO * ado,SUMA_LIST_WIDGET * LW,int ichoice,SUMA_Boolean CloseShop,int setmen)16198 int SUMA_SelectSwitchColPlane(SUMA_ALL_DO *ado,
16199                                   SUMA_LIST_WIDGET *LW,
16200                                   int ichoice, SUMA_Boolean CloseShop,
16201                                   int setmen)
16202 {
16203    static char FuncName[]={"SUMA_SelectSwitchColPlane"};
16204    SUMA_Boolean LocalHead = NOPE;
16205 
16206    SUMA_ENTRY;
16207 
16208    if (!ado || !LW) SUMA_RETURN(0);
16209 
16210    if (!SUMA_SelectSwitchColPlane_one(ado, LW, ichoice, CloseShop, setmen)) {
16211       SUMA_RETURN(0);
16212    }
16213 
16214    if (ado->do_type == SO_type) {
16215       SUMA_OVERLAYS *colp=NULL, *colpC=NULL;
16216       SUMA_SurfaceObject *SOC=NULL, *SO=(SUMA_SurfaceObject *)ado;
16217       /* do we have a contralateral SO and overlay? */
16218       colp = SUMA_ADO_CurColPlane(ado);
16219       colpC = SUMA_Contralateral_overlay(colp, (SUMA_SurfaceObject *)ado, &SOC);
16220       if (colpC && SOC) {
16221          SUMA_LHv("Found contralateral equivalent to:\n"
16222                       " %s and %s in\n"
16223                       " %s and %s\n",
16224                       SO->Label, CHECK_NULL_STR(colp->Label),
16225                       SOC->Label, CHECK_NULL_STR(colpC->Label));
16226          if (!SOC->SurfCont->SwitchDsetlst->ALS)
16227                         SUMA_RefreshDsetList ((SUMA_ALL_DO *)SOC);
16228          if (!SUMA_SelectSwitchColPlane_one((SUMA_ALL_DO *)SOC,
16229                                        SOC->SurfCont->SwitchDsetlst,
16230                                             ichoice, 0, 1)) {
16231             SUMA_S_Warn("Failed in contralateralization");
16232          }
16233       }
16234    }
16235 
16236    SUMA_RETURN(1);
16237 }
16238 
16239 /*!
16240    \brief handles a selection from switch ColPlane
16241 
16242    -expect SO in data
16243 
16244 */
SUMA_cb_SelectSwitchColPlane(Widget w,XtPointer data,XtPointer call_data)16245 void SUMA_cb_SelectSwitchColPlane(Widget w, XtPointer data, XtPointer call_data)
16246 {
16247    static char FuncName[] = {"SUMA_cb_SelectSwitchColPlane"};
16248    SUMA_LIST_WIDGET *LW = NULL;
16249    XmListCallbackStruct *cbs = (XmListCallbackStruct *) call_data;
16250    SUMA_Boolean CloseShop = NOPE, Found = NOPE;
16251    int ichoice = -1;
16252    SUMA_OVERLAYS *ColPlane = NULL;
16253    SUMA_ALL_DO *ado = NULL;
16254    SUMA_X_SurfCont *SurfCont=NULL;
16255    SUMA_Boolean LocalHead=NOPE;
16256 
16257    SUMA_ENTRY;
16258 
16259    ado = (SUMA_ALL_DO *)data;
16260 
16261    SurfCont = SUMA_ADO_Cont(ado);
16262    LW = SurfCont->SwitchDsetlst;
16263 
16264    if (!LW) {
16265       SUMA_S_Err("NULL LW!");
16266       SUMA_RETURNe;
16267    }
16268 
16269    ichoice = SUMA_GetListIchoice(cbs, LW, &CloseShop);
16270 
16271    if (!SUMA_SelectSwitchColPlane(ado, LW, ichoice, CloseShop, 1)) {
16272       SUMA_S_Err("I guess failure was an option.");
16273    }
16274 
16275    SUMA_RETURNe;
16276 }
16277 
16278 /*!
16279    \brief Closes the DrawROI window
16280 
16281    -expects SUMA_LIST_WIDGET * in client_data
16282 */
SUMA_cb_CloseSwitchColPlane(Widget w,XtPointer data,XtPointer call_data)16283 void SUMA_cb_CloseSwitchColPlane(Widget w, XtPointer data, XtPointer call_data)
16284 {
16285    static char FuncName[] = {"SUMA_cb_CloseSwitchColPlane"};
16286    SUMA_Boolean LocalHead = NOPE;
16287    SUMA_LIST_WIDGET *LW = NULL;
16288 
16289    SUMA_ENTRY;
16290 
16291    LW = (SUMA_LIST_WIDGET *)data;
16292 
16293    switch (SUMA_CLOSE_MODE)   {/* No open GL drawables in this widget*/
16294       case SUMA_WITHDRAW:
16295          if (LocalHead)
16296             fprintf (SUMA_STDERR,
16297                      "%s: Withdrawing list widget %s...\n",
16298                      FuncName, LW->Label);
16299          XWithdrawWindow(SUMAg_CF->X->DPY_controller1,
16300             XtWindow(LW->toplevel),
16301             XScreenNumberOfScreen(XtScreen(LW->toplevel)));
16302          break;
16303       case SUMA_DESTROY:
16304          if (LocalHead)
16305             fprintf (SUMA_STDERR,
16306                      "%s: Destroying list widget %s...\n", FuncName, LW->Label);
16307          XtDestroyWidget(LW->toplevel);
16308          LW->toplevel = NULL;
16309          break;
16310       default:
16311          SUMA_S_Err("Not setup to deal with this closing mode");
16312          SUMA_RETURNe;
16313          break;
16314    }
16315 
16316    LW->isShaded = YUP;
16317 
16318    SUMA_RETURNe;
16319 }
16320 
16321 /*!
16322    \brief default selection action, handles single selection mode
16323    - expects sv in data
16324 */
SUMA_cb_SelectSwitchGroup(Widget w,XtPointer data,XtPointer call_data)16325 void SUMA_cb_SelectSwitchGroup(Widget w, XtPointer data, XtPointer call_data)
16326 {
16327    static char FuncName[] = {"SUMA_cb_SelectSwitchGroup"};
16328    SUMA_LIST_WIDGET *LW = NULL;
16329    XmListCallbackStruct *cbs = (XmListCallbackStruct *) call_data;
16330    char *choice=NULL;
16331    SUMA_Boolean CloseShop = NOPE, Found = NOPE;
16332    int ichoice = -1;
16333    char *strn=NULL;
16334    SUMA_SurfaceViewer *sv=NULL;
16335    SUMA_Boolean LocalHead = NOPE;
16336 
16337    SUMA_ENTRY;
16338 
16339    sv = (SUMA_SurfaceViewer *)data;
16340 
16341    LW = sv->X->ViewCont->SwitchGrouplst;
16342 
16343    if (!LW) {
16344       SUMA_S_Err("NULL LW!");
16345       SUMA_RETURNe;
16346    }
16347 
16348    ichoice = SUMA_GetListIchoice(cbs, LW, &CloseShop);
16349 
16350    /* now retrieve that choice from the SUMA_ASSEMBLE_LIST_STRUCT structure
16351       and initialize the drawing window */
16352    if (LW->ALS) {
16353       if (LocalHead) fprintf (SUMA_STDERR,"%s: N_clist = %d\n",
16354                                              FuncName, LW->ALS->N_clist);
16355       if (LW->ALS->N_clist > ichoice) {
16356          strn = (char *)LW->ALS->clist[ichoice];
16357          if (LocalHead) fprintf (SUMA_STDERR,"%s: Retrieved group labeled %s\n",
16358                                     FuncName, strn);
16359          /* Now we know what group the user wants so go switch groups */
16360          if (!SUMA_SwitchGroups(sv, strn)) {
16361             SUMA_SLP_Err("Failed to switch groups");
16362          }
16363       }
16364    } else {
16365       if (LocalHead) fprintf (SUMA_STDERR,"%s: NULL ALS\n", FuncName);
16366    }
16367 
16368    /* Now make the viewer switch group */
16369 
16370    if (CloseShop) {
16371       SUMA_LH("Closing Shop");
16372       SUMA_cb_CloseSwitchGroup( w,  data,  call_data);
16373    }
16374 
16375    SUMA_RETURNe;
16376 }
16377 
16378 /*!
16379    \brief Closes the SwitchGroup window
16380 
16381    -expects sv in client_data
16382 */
SUMA_cb_CloseSwitchGroup(Widget w,XtPointer data,XtPointer call_data)16383 void SUMA_cb_CloseSwitchGroup(Widget w, XtPointer data, XtPointer call_data)
16384 {
16385    static char FuncName[] = {"SUMA_cb_CloseSwitchGroup"};
16386    SUMA_LIST_WIDGET *LW = NULL;
16387    SUMA_SurfaceViewer *sv=NULL;
16388    SUMA_Boolean LocalHead = NOPE;
16389 
16390    SUMA_ENTRY;
16391 
16392    sv = (SUMA_SurfaceViewer *)data;
16393 
16394    LW = sv->X->ViewCont->SwitchGrouplst;
16395 
16396    switch (SUMA_CLOSE_MODE)   {/* No open GL drawables in this widget*/
16397       case SUMA_WITHDRAW:
16398          if (LocalHead)
16399             fprintf (SUMA_STDERR,
16400                      "%s: Withdrawing list widget %s...\n", FuncName, LW->Label);
16401          XWithdrawWindow(SUMAg_CF->X->DPY_controller1,
16402             XtWindow(LW->toplevel),
16403             XScreenNumberOfScreen(XtScreen(LW->toplevel)));
16404          break;
16405       case SUMA_DESTROY:
16406          if (LocalHead)
16407             fprintf (SUMA_STDERR,
16408                      "%s: Destroying list widget %s...\n", FuncName, LW->Label);
16409          XtDestroyWidget(LW->toplevel);
16410          LW->toplevel = NULL;
16411          break;
16412       default:
16413          SUMA_S_Err("Not setup to deal with this closing mode");
16414          SUMA_RETURNe;
16415          break;
16416    }
16417 
16418    LW->isShaded = YUP;
16419 
16420    SUMA_RETURNe;
16421 }
16422 
16423 /*!
16424    \brief default selection action, handles single selection mode
16425 
16426    -code snipets from Motif Programming Manual
16427 */
SUMA_cb_SelectSwitchROI(Widget w,XtPointer data,XtPointer call_data)16428 void SUMA_cb_SelectSwitchROI(Widget w, XtPointer data, XtPointer call_data)
16429 {
16430    static char FuncName[] = {"SUMA_cb_SelectSwitchROI"};
16431    SUMA_LIST_WIDGET *LW = NULL;
16432    XmListCallbackStruct *cbs = (XmListCallbackStruct *) call_data;
16433    char *choice=NULL;
16434    SUMA_Boolean CloseShop = NOPE, Found = NOPE;
16435    int ichoice = -1;
16436    SUMA_DRAWN_ROI *DrawnROI = NULL;
16437    SUMA_Boolean LocalHead = NOPE;
16438 
16439    SUMA_ENTRY;
16440 
16441    LW = (SUMA_LIST_WIDGET *)data;
16442 
16443    if (!LW) {
16444       SUMA_S_Err("NULL LW!");
16445       SUMA_RETURNe;
16446    }
16447 
16448    ichoice = SUMA_GetListIchoice(cbs, LW, &CloseShop);
16449 
16450    /* now retrieve that choice from the SUMA_ASSEMBLE_LIST_STRUCT structure and initialize the drawing window */
16451    if (LW->ALS) {
16452       if (LocalHead) fprintf (SUMA_STDERR,"%s: N_clist = %d\n", FuncName, LW->ALS->N_clist);
16453       if (LW->ALS->N_clist > ichoice) {
16454          DrawnROI = (SUMA_DRAWN_ROI *)LW->ALS->oplist[ichoice];
16455          if (LocalHead) fprintf (SUMA_STDERR,"%s: Retrieved DrawnROI labeled %s\n", FuncName, DrawnROI->Label);
16456          SUMA_InitializeDrawROIWindow(DrawnROI);
16457       }
16458    } else {
16459       if (LocalHead) fprintf (SUMA_STDERR,"%s: NULL ALS\n", FuncName);
16460    }
16461 
16462    if (CloseShop) {
16463       SUMA_cb_CloseSwitchROI( w,  data,  call_data);
16464    }
16465 
16466    SUMA_RETURNe;
16467 }
16468 
16469 /*!
16470    \brief Closes the SwitchROI window
16471 
16472    -expects SUMA_LIST_WIDGET * in client_data
16473 */
SUMA_cb_CloseSwitchROI(Widget w,XtPointer data,XtPointer call_data)16474 void SUMA_cb_CloseSwitchROI(Widget w, XtPointer data, XtPointer call_data)
16475 {
16476    static char FuncName[] = {"SUMA_cb_CloseSwitchROI"};
16477    SUMA_Boolean LocalHead = NOPE;
16478    SUMA_LIST_WIDGET *LW = NULL;
16479 
16480    SUMA_ENTRY;
16481 
16482    LW = (SUMA_LIST_WIDGET *)data;
16483 
16484    switch (SUMA_CLOSE_MODE)   {/* No open GL drawables in this widget*/
16485       case SUMA_WITHDRAW:
16486          if (LocalHead)
16487             fprintf (SUMA_STDERR,
16488                      "%s: Withdrawing list widget %s...\n", FuncName, LW->Label);
16489          XWithdrawWindow(SUMAg_CF->X->DPY_controller1,
16490             XtWindow(LW->toplevel),
16491             XScreenNumberOfScreen(XtScreen(LW->toplevel)));
16492          break;
16493       case SUMA_DESTROY:
16494          if (LocalHead)
16495             fprintf (SUMA_STDERR,
16496                      "%s: Destroying list widget %s...\n", FuncName, LW->Label);
16497          XtDestroyWidget(LW->toplevel);
16498          LW->toplevel = NULL;
16499          break;
16500       default:
16501          SUMA_S_Err("Not setup to deal with this mode");
16502          SUMA_RETURNe;
16503          break;
16504    }
16505 
16506    LW->isShaded = YUP;
16507 
16508    SUMA_RETURNe;
16509 }
16510 /*!
16511    \brief Closes the DrawROI window
16512 */
SUMA_cb_CloseDrawROIWindow(Widget w,XtPointer data,XtPointer call_data)16513 void SUMA_cb_CloseDrawROIWindow(Widget w, XtPointer data, XtPointer call_data)
16514 {
16515    static char FuncName[] = {"SUMA_cb_CloseDrawROIWindow"};
16516    SUMA_Boolean Shaded = NOPE, LocalHead = NOPE;
16517 
16518    SUMA_ENTRY;
16519 
16520    if (!SUMAg_CF->X->DrawROI->AppShell) SUMA_RETURNe;
16521 
16522    /* if the ROI selection list is open, close it */
16523    /* Close the ROIlist window if it is open */
16524    SUMA_IS_DRAW_ROI_SWITCH_ROI_SHADED(Shaded);
16525    if (!Shaded) {
16526       if (LocalHead)
16527          fprintf (SUMA_STDERR, "%s: Closing switch ROI window ...\n", FuncName);
16528       SUMA_cb_CloseSwitchROI(NULL,
16529                            (XtPointer) SUMAg_CF->X->DrawROI->SwitchROIlst, NULL);
16530    }
16531 
16532    /* Turn off Draw Mode, if it is ON */
16533    if (SUMAg_CF->ROI_mode) {
16534       XmToggleButtonSetState (SUMAg_CF->X->DrawROI->DrawROImode_tb,
16535                               NOPE, YUP);
16536    }
16537    switch (SUMA_CLOSE_MODE)   {/* No open GL drawables in this widget*/
16538       case SUMA_WITHDRAW:
16539          if (LocalHead)
16540             fprintf (SUMA_STDERR,
16541                      "%s: Withdrawing DrawROI window...\n", FuncName);
16542          XWithdrawWindow(SUMAg_CF->X->DPY_controller1,
16543             XtWindow(SUMAg_CF->X->DrawROI->AppShell),
16544             XScreenNumberOfScreen(XtScreen(SUMAg_CF->X->DrawROI->AppShell)));
16545          break;
16546       case SUMA_DESTROY :
16547          if (LocalHead)
16548             fprintf (SUMA_STDERR,"%s: Destroying DrawROI window...\n", FuncName);
16549          XtDestroyWidget(SUMAg_CF->X->DrawROI->AppShell);
16550          SUMAg_CF->X->DrawROI->AppShell = NULL;
16551          break;
16552       default:
16553          SUMA_S_Err("Not setup to deal with this mode of closure");
16554          SUMA_RETURNe;
16555          break;
16556    }
16557 
16558    SUMA_RETURNe;
16559 }
16560 /*!
16561    \brief creates the SUMA controller window. Expects nothing  in input
16562 */
SUMA_cb_createSumaCont(Widget ww,XtPointer ddata,XtPointer ccallData)16563 void SUMA_cb_createSumaCont(Widget ww, XtPointer ddata, XtPointer ccallData)
16564 {
16565    static char FuncName[] = {"SUMA_cb_createSumaCont"};
16566    Widget w, rc, pb_close, pb_new, pb_done, pb_bhelp, AppFrame,
16567           tb, rb, rc_m;
16568    int i;
16569    char *sss;
16570    SUMA_Boolean LocalHead = NOPE;
16571 
16572    SUMA_ENTRY;
16573 
16574    if (SUMAg_CF->X->SumaCont->AppShell) {
16575       SUMA_S_Err("SUMAg_CF->X->SumaCont->AppShell!=NULL. Should not be here.");
16576       SUMA_RETURNe;
16577    }
16578 
16579    if (SUMA_isEnv("SUMA_SurfContFontSize", "BIG")) {
16580       sss = "font9";
16581    } else {
16582       sss = "font8";
16583    }
16584 
16585    /* create as a separate application shell,
16586       you do not want a parent to this controller that
16587       can be closed or withdrawn temporarily */
16588    SUMAg_CF->X->SumaCont->AppShell = XtVaAppCreateShell( sss, "Suma" ,
16589       topLevelShellWidgetClass , SUMAg_CF->X->DPY_controller1 ,
16590       XmNtitle, "Suma Controller",
16591       NULL ) ;
16592 
16593 
16594    /* turn off default delete response. If you do not do that, you will suffer.*/
16595    XtVaSetValues( SUMAg_CF->X->SumaCont->AppShell,
16596            XmNdeleteResponse, XmDO_NOTHING,
16597            NULL);
16598 
16599    /* handle the close button from window manager */
16600    XmAddWMProtocolCallback(/* make "Close" window menu work */
16601       SUMAg_CF->X->SumaCont->AppShell,
16602       XmInternAtom( SUMAg_CF->X->DPY_controller1 , "WM_DELETE_WINDOW" , False ) ,
16603       SUMA_cb_closeSumaCont, NULL) ;
16604 
16605    /* create a form widget, manage it at the end ...*/
16606    SUMAg_CF->X->SumaCont->form = XtVaCreateWidget ("dialog",
16607       xmFormWidgetClass, SUMAg_CF->X->SumaCont->AppShell,
16608       XmNborderWidth , 0 ,
16609       XmNmarginHeight , SUMA_MARGIN ,
16610       XmNmarginWidth  , SUMA_MARGIN ,
16611       XmNshadowThickness, 2,
16612       XmNshadowType, XmSHADOW_ETCHED_IN,
16613       NULL);
16614 
16615    SUMA_Register_Widget_Help( SUMAg_CF->X->SumaCont->form , 0,
16616                                  "SumaCont",
16617                                  "Suma Controller",
16618 "The suma controller is for controlling parameters common to across viewers and objects."
16619 ":SPX:"
16620 "You can launch the :ref:`Suma Controller <SumaCont>` with:"
16621 " :ref:`ctrl+u <LC_Ctrl+u>` or :menuselection:`View-->Suma Controller`\n"
16622 "\n"
16623 ".. figure:: media/SumaCont.auto.ALL.jpg\n"
16624 "   :align: center\n"
16625 "   :name: media/SumaCont.auto.ALL.jpg\n"
16626 "\n"
16627 "   :ref:`(link)<media/SumaCont.auto.ALL.jpg>`\n"
16628 "\n\n"
16629 "   ..\n\n"
16630 ":DEF:"
16631 "You can launch the Suma Controller with:"
16632 "\n'ctrl+u' or 'View-->Suma Controller'\n"
16633 ":SPX:"
16634 "\n") ;
16635 
16636 
16637    /* a LockFrame to put the lockstuff in */
16638    SUMAg_CF->X->SumaCont->LockFrame = XtVaCreateWidget ("dialog",
16639       xmFrameWidgetClass, SUMAg_CF->X->SumaCont->form,
16640       XmNleftAttachment , XmATTACH_FORM ,
16641       XmNtopAttachment  , XmATTACH_FORM ,
16642       XmNshadowType , XmSHADOW_ETCHED_IN ,
16643       XmNshadowThickness , 5 ,
16644       XmNtraversalOn , False ,
16645       NULL);
16646 
16647       /* this one requires Motif 1.2 or newer */
16648       XtVaCreateManagedWidget ("Lock",
16649          xmLabelWidgetClass, SUMAg_CF->X->SumaCont->LockFrame,
16650          XmNchildType, XmFRAME_TITLE_CHILD,
16651          XmNchildHorizontalAlignment, XmALIGNMENT_BEGINNING,
16652          NULL);
16653 
16654    /* row column Lock rowcolumns */
16655    rc = XtVaCreateWidget ("rowcolumn",
16656          xmRowColumnWidgetClass, SUMAg_CF->X->SumaCont->LockFrame,
16657          XmNpacking, XmPACK_TIGHT,
16658          XmNorientation , XmHORIZONTAL ,
16659          XmNmarginHeight, SUMA_MARGIN ,
16660          XmNmarginWidth , SUMA_MARGIN ,
16661          NULL);
16662 
16663    for (i = 0; i < SUMA_MAX_SURF_VIEWERS; i++) {
16664       char stmp[3];
16665       int tmpfac;
16666 
16667       rc_m = XtVaCreateManagedWidget ("rowcolumn",
16668          xmRowColumnWidgetClass, rc,
16669          XmNpacking, XmPACK_TIGHT,
16670          XmNorientation , XmVERTICAL ,
16671          NULL);
16672 
16673       sprintf(stmp,"%c", 65+i);
16674       w = XtVaCreateManagedWidget (stmp,
16675          xmLabelWidgetClass, rc_m,
16676          NULL);
16677 
16678       SUMAg_CF->X->SumaCont->Lock_rbg->rb[i] = XtVaCreateWidget("radiobox",
16679          xmRowColumnWidgetClass, rc_m,
16680          XmNorientation , XmVERTICAL ,
16681          XmNpacking,      XmPACK_TIGHT,
16682          XmNradioBehavior, True,
16683          XmNnumColumns,   1,
16684          NULL);
16685 
16686       tmpfac = SUMAg_CF->X->SumaCont->Lock_rbg->N_but;
16687 
16688       SUMAg_CF->X->SumaCont->Lock_rbg->tb[tmpfac*i] =
16689          XtVaCreateManagedWidget("-",
16690             xmToggleButtonWidgetClass,
16691             SUMAg_CF->X->SumaCont->Lock_rbg->rb[i], NULL);
16692       XtAddCallback (SUMAg_CF->X->SumaCont->Lock_rbg->tb[tmpfac*i],
16693                      XmNvalueChangedCallback, SUMA_cb_XHlock_toggled,
16694                      (XTP_CAST)(tmpfac*i));
16695 
16696       SUMAg_CF->X->SumaCont->Lock_rbg->tb[tmpfac*i+1] =
16697          XtVaCreateManagedWidget("i",
16698             xmToggleButtonWidgetClass,
16699             SUMAg_CF->X->SumaCont->Lock_rbg->rb[i], NULL);
16700       XtAddCallback (SUMAg_CF->X->SumaCont->Lock_rbg->tb[tmpfac*i+1],
16701                      XmNvalueChangedCallback, SUMA_cb_XHlock_toggled,
16702                      (XTP_CAST)(tmpfac*i+1));
16703 
16704       SUMAg_CF->X->SumaCont->Lock_rbg->tb[tmpfac*i+2] =
16705          XtVaCreateManagedWidget("c",
16706             xmToggleButtonWidgetClass,
16707             SUMAg_CF->X->SumaCont->Lock_rbg->rb[i], NULL);
16708       XtAddCallback (SUMAg_CF->X->SumaCont->Lock_rbg->tb[tmpfac*i+2],
16709                      XmNvalueChangedCallback, SUMA_cb_XHlock_toggled,
16710                      (XTP_CAST)(tmpfac*i+2));
16711 
16712       XtManageChild (SUMAg_CF->X->SumaCont->Lock_rbg->rb[i]);
16713 
16714       /* put some help on the radiobox and its children*/
16715       SUMA_Register_Widget_Children_Help(SUMAg_CF->X->SumaCont->Lock_rbg->rb[i],
16716                            1, "SumaCont->Lock", NULL, SUMA_LockSumaCont_help );
16717 
16718       /* initialize radio button created */
16719       SUMA_set_Lock_rb (SUMAg_CF->X->SumaCont->Lock_rbg, i, SUMAg_CF->Locked[i]);
16720 
16721       XtVaCreateManagedWidget ("sep", xmSeparatorWidgetClass, rc_m, NULL);
16722 
16723       SUMAg_CF->X->SumaCont->LockView_tbg[i] = XtVaCreateManagedWidget("v",
16724          xmToggleButtonWidgetClass, rc_m, NULL);
16725       XtAddCallback (SUMAg_CF->X->SumaCont->LockView_tbg[i],
16726                      XmNvalueChangedCallback, SUMA_cb_XHviewlock_toggled,
16727                      (XTP_CAST) i);
16728       XmToggleButtonSetState (SUMAg_CF->X->SumaCont->LockView_tbg[i],
16729                               SUMAg_CF->ViewLocked[i], NOPE);
16730       /* put some help on the view lock*/
16731       SUMA_Register_Widget_Children_Help(rc_m , 1,
16732                            "SumaCont->Lock->View",
16733                            NULL, SUMA_LockViewSumaCont_help );
16734 
16735    }
16736    XtManageChild (rc);
16737    XtManageChild (SUMAg_CF->X->SumaCont->LockFrame);
16738 
16739 
16740    /* a vertical separator */
16741    XtVaCreateManagedWidget ("sep",
16742                            xmSeparatorGadgetClass, rc,
16743                            XmNorientation, XmVERTICAL,
16744                            NULL);
16745 
16746    /* a radio box for the all buttons */
16747    rc_m = XtVaCreateManagedWidget ("rowcolumn",
16748          xmRowColumnWidgetClass, rc,
16749          XmNpacking, XmPACK_TIGHT,
16750          XmNorientation , XmVERTICAL ,
16751          NULL);
16752 
16753    w = XtVaCreateManagedWidget ("All",
16754       xmLabelWidgetClass, rc_m,
16755       NULL);
16756 
16757    SUMAg_CF->X->SumaCont->Lock_rbg->arb = XtVaCreateWidget("radiobox",
16758       xmRowColumnWidgetClass, rc_m,
16759       XmNorientation , XmVERTICAL ,
16760       XmNpacking,      XmPACK_TIGHT,
16761       XmNradioBehavior, True,
16762       XmNnumColumns,   1,
16763       NULL);
16764 
16765    SUMAg_CF->X->SumaCont->Lock_rbg->atb[0] = XtVaCreateManagedWidget("-",
16766    xmToggleButtonWidgetClass, SUMAg_CF->X->SumaCont->Lock_rbg->arb, NULL);
16767    XtAddCallback (SUMAg_CF->X->SumaCont->Lock_rbg->atb[0],
16768                   XmNvalueChangedCallback, SUMA_cb_XHalock_toggled,
16769                   (XtPointer)(0));
16770 
16771    SUMAg_CF->X->SumaCont->Lock_rbg->atb[1] = XtVaCreateManagedWidget("i",
16772    xmToggleButtonWidgetClass, SUMAg_CF->X->SumaCont->Lock_rbg->arb, NULL);
16773    XtAddCallback (SUMAg_CF->X->SumaCont->Lock_rbg->atb[1],
16774                   XmNvalueChangedCallback, SUMA_cb_XHalock_toggled,
16775                   (XtPointer)(1));
16776 
16777    SUMAg_CF->X->SumaCont->Lock_rbg->atb[2] = XtVaCreateManagedWidget("c",
16778    xmToggleButtonWidgetClass, SUMAg_CF->X->SumaCont->Lock_rbg->arb, NULL);
16779    XtAddCallback (SUMAg_CF->X->SumaCont->Lock_rbg->atb[2],
16780                   XmNvalueChangedCallback, SUMA_cb_XHalock_toggled,
16781                   (XtPointer)(2));
16782 
16783    XtManageChild (SUMAg_CF->X->SumaCont->Lock_rbg->arb);
16784 
16785    /* put some help on the radiobox and its children*/
16786    SUMA_Register_Widget_Children_Help(SUMAg_CF->X->SumaCont->Lock_rbg->arb , 1,
16787                          "SumaCont->Lock->All", NULL,
16788                          SUMA_LockSumaCont_help );
16789 
16790    /* initialize radio button created */
16791    SUMA_set_Lock_arb (SUMAg_CF->X->SumaCont->Lock_rbg);
16792 
16793    XtVaCreateManagedWidget ("sep", xmSeparatorGadgetClass, rc_m, NULL);
16794 
16795    SUMAg_CF->X->SumaCont->LockAllView_tb =
16796       XtVaCreateManagedWidget("v",xmToggleButtonWidgetClass, rc_m, NULL);
16797    XtAddCallback (SUMAg_CF->X->SumaCont->LockAllView_tb,
16798                   XmNvalueChangedCallback, SUMA_cb_XHaviewlock_toggled, NULL);
16799    SUMA_set_LockView_atb();
16800 
16801    /* a frame to put the Close button in */
16802    SUMAg_CF->X->SumaCont->AppFrame = XtVaCreateWidget ("dialog",
16803       xmFrameWidgetClass, SUMAg_CF->X->SumaCont->form,
16804       XmNleftAttachment , XmATTACH_FORM ,
16805       XmNtopAttachment  , XmATTACH_WIDGET ,
16806       XmNtopWidget, SUMAg_CF->X->SumaCont->LockFrame,
16807       XmNshadowType , XmSHADOW_ETCHED_IN ,
16808       XmNshadowThickness , 5 ,
16809       XmNtraversalOn , False ,
16810       NULL);
16811 
16812 
16813    rc = XtVaCreateManagedWidget ("rowcolumn",
16814          xmRowColumnWidgetClass, SUMAg_CF->X->SumaCont->AppFrame,
16815          XmNpacking, XmPACK_COLUMN,
16816          XmNorientation , XmVERTICAL ,
16817          XmNnumColumns, 2,
16818          NULL);
16819 
16820    pb_new = XtVaCreateWidget ("Viewer",
16821       xmPushButtonWidgetClass, rc,
16822       NULL);
16823    XtAddCallback (pb_new, XmNactivateCallback, SUMA_cb_newSumaCont, NULL);
16824    SUMA_Register_Widget_Help(pb_new , 1, "SumaCont->Viewer",
16825                              "Opens a new viewer", SUMA_viewerSumaCont_help );
16826    XtManageChild (pb_new);
16827 
16828    pb_close = XtVaCreateWidget ("Close",
16829       xmPushButtonWidgetClass, rc,
16830       NULL);
16831    XtAddCallback (pb_close, XmNactivateCallback, SUMA_cb_closeSumaCont, NULL);
16832    SUMA_Register_Widget_Help(pb_close , 1, "SumaCont->Close",
16833                              "Close SUMA controller", SUMA_closeSumaCont_help ) ;
16834    XtManageChild (pb_close);
16835 
16836    pb_bhelp = XtVaCreateWidget ("BHelp",
16837       xmPushButtonWidgetClass, rc,
16838       NULL);
16839    XtAddCallback (pb_bhelp, XmNactivateCallback, MCW_click_help_CB, NULL);
16840    SUMA_Register_Widget_Help(pb_bhelp, 1, "SumaCont->BHelp",
16841            "Press this button then click on a button/label/menu for more help.",
16842                              SUMA_help_help ) ;
16843 
16844    XtManageChild (pb_bhelp);
16845 
16846    pb_bhelp = XtVaCreateWidget ("WHelp",
16847       xmPushButtonWidgetClass, rc,
16848       NULL);
16849    XtAddCallback (pb_bhelp, XmNactivateCallback, SUMA_click_webhelp_CB,
16850                   "SumaCont->WHelp");
16851    MCW_set_widget_bg( pb_bhelp , MCW_buthighlight(pb_bhelp) , 0 ) ;
16852    SUMA_Register_Widget_Help(pb_bhelp, 1, "SumaCont->WHelp",
16853           "Press this button then click on a button/label/menu for online help.",
16854                              SUMA_webhelp_help ) ;
16855 
16856    XtManageChild (pb_bhelp);
16857 
16858    SUMAg_CF->X->SumaCont->quit_pb = XtVaCreateWidget ("done",
16859       xmPushButtonWidgetClass, rc,
16860       NULL);
16861    XtAddCallback (SUMAg_CF->X->SumaCont->quit_pb, XmNactivateCallback,
16862                   SUMA_cb_doneSumaCont, NULL);
16863    SUMA_Register_Widget_Help(SUMAg_CF->X->SumaCont->quit_pb, 1,
16864                              "SumaCont->done",
16865                   "Click twice in 5 seconds to close everything and quit SUMA.",
16866                   "Click twice in 5 seconds to quit application. "
16867                   "All viewer windows will be closed, nothing is saved, "
16868                   "SUMA will terminate, and "
16869                   "there maybe no one left at this computer.");
16870    MCW_set_widget_bg( SUMAg_CF->X->SumaCont->quit_pb ,
16871                       MCW_hotcolor(SUMAg_CF->X->SumaCont->quit_pb) , 0 ) ;
16872 
16873    XtManageChild (SUMAg_CF->X->SumaCont->quit_pb);
16874 
16875    XtManageChild (SUMAg_CF->X->SumaCont->AppFrame);
16876 
16877    /* manage the remaing widgets */
16878    XtManageChild (SUMAg_CF->X->SumaCont->form);
16879 
16880    /* realize the widget */
16881    XtRealizeWidget (SUMAg_CF->X->SumaCont->AppShell);
16882 
16883    SUMA_RETURNe;
16884 }
16885 
16886 /*!
16887    \brief Close all viewers and exit SUMA
16888 
16889    based on afni's AFNI_quit_CB
16890 */
16891 
SUMA_cb_doneSumaCont(Widget wcall,XtPointer cd1,XtPointer cbs)16892 void  SUMA_cb_doneSumaCont(Widget wcall, XtPointer cd1, XtPointer cbs)
16893 {
16894    static char FuncName[] = {"SUMA_cb_doneSumaCont"};
16895    XmPushButtonCallbackStruct * pbcbs = (XmPushButtonCallbackStruct *) cbs ;
16896    SUMA_Boolean LocalHead = NOPE;
16897 
16898    SUMA_ENTRY;
16899 
16900    /* NULL widget --> reset button to lowercase */
16901    if( wcall == NULL ){
16902       if (LocalHead) fprintf (SUMA_STDERR, "%s: Resetting button.\n", FuncName);
16903       if( SUMAg_CF->X->SumaCont->quit_first == NOPE ){
16904          MCW_set_widget_label( SUMAg_CF->X->SumaCont->quit_pb , "done " ) ;
16905          SUMAg_CF->X->SumaCont->quit_first = YUP ;
16906       }
16907       SUMA_RETURNe ;
16908    }
16909 
16910    /* Press of button with Shift or Control key pressed --> Death Now */
16911    if( pbcbs != NULL                       &&
16912        pbcbs->event != NULL                &&
16913        pbcbs->event->type == ButtonRelease &&
16914        ((XButtonEvent *)(pbcbs->event))->state &  /* note single & here! */
16915        (ShiftMask|ControlMask|Button2Mask|Button3Mask) ){
16916 
16917       if (LocalHead) fprintf (SUMA_STDERR, "%s: Closing display.\n", FuncName);
16918       XtCloseDisplay( SUMAg_CF->X->DPY_controller1 ) ;
16919       exit(0) ;
16920    }
16921 
16922    /* First press --> just change button label */
16923 
16924    if( SUMAg_CF->X->SumaCont->quit_first ){
16925       MCW_set_widget_label( SUMAg_CF->X->SumaCont->quit_pb , "DONE " ) ;
16926       SUMAg_CF->X->SumaCont->quit_first = NOPE ;
16927 
16928       /* if not re-pressed in 5 seconds, will reset to lowercase */
16929       if (LocalHead) fprintf (SUMA_STDERR, "%s: First Press, adding time out.\n", FuncName);
16930       (void) XtAppAddTimeOut(
16931                XtWidgetToApplicationContext(SUMAg_CF->X->SumaCont->quit_pb) ,
16932                5000 , SUMA_quit_timeout_CB , NULL ) ;
16933 
16934        SUMA_RETURNe;
16935    }
16936 
16937    /* close up */
16938    if (LocalHead) fprintf (SUMA_STDERR, "%s: Closing shop...\n", FuncName);
16939    XtCloseDisplay( SUMAg_CF->X->DPY_controller1 ) ;
16940 
16941    selenium_close(); /* close any selenium opened browser windows if open */
16942    exit(0) ;
16943 
16944    SUMA_RETURNe;
16945 }
SUMA_quit_timeout_CB(XtPointer client_data,XtIntervalId * id)16946 void SUMA_quit_timeout_CB( XtPointer client_data , XtIntervalId * id )
16947 {
16948    static char FuncName[] = {"SUMA_quit_timeout_CB"};
16949 
16950    SUMA_ENTRY;
16951 
16952    SUMA_cb_doneSumaCont(NULL, NULL, NULL);
16953 
16954    SUMA_RETURNe;
16955 }
16956 
SUMA_cb_XHlock_toggled(Widget w,XtPointer client_data,XtPointer callData)16957 void SUMA_cb_XHlock_toggled(Widget w, XtPointer client_data, XtPointer callData)
16958 {
16959    static char FuncName[] = {"SUMA_cb_XHlock_toggled"};
16960    SUMA_Boolean LocalHead = NOPE;
16961    int cd, i, j;
16962 
16963    cd = (INT_CAST) client_data;
16964 
16965    SUMA_ENTRY;
16966 
16967    i = cd / SUMAg_CF->X->SumaCont->Lock_rbg->N_but;
16968    j = cd % SUMAg_CF->X->SumaCont->Lock_rbg->N_but;
16969    fprintf (SUMA_STDERR, "%s: Viewer %c Lock=%d.\n", FuncName, 65+i, j);
16970    SUMAg_CF->Locked[i] = j;
16971 
16972    /* now call the function to set the All lock buttons */
16973    SUMA_set_Lock_arb (SUMAg_CF->X->SumaCont->Lock_rbg);
16974 
16975    SUMA_RETURNe;
16976 }
16977 
SUMA_cb_XHalock_toggled(Widget w,XtPointer client_data,XtPointer callData)16978 void SUMA_cb_XHalock_toggled (Widget w, XtPointer client_data,
16979                               XtPointer callData)
16980 {
16981    static char FuncName[] = {"SUMA_cb_XHalock_toggled"};
16982    int i;
16983    DList *list=NULL;
16984    SUMA_EngineData *ED = NULL;
16985 
16986    SUMA_ENTRY;
16987 
16988    i = (INT_CAST) client_data;
16989 
16990 
16991    list = SUMA_CreateList();
16992    ED = SUMA_InitializeEngineListData (SE_SetLockAllCrossHair);
16993    if (!SUMA_RegisterEngineListCommand (  list, ED,
16994                                           SEF_i, (void*)&i,
16995                                           SES_SumaWidget, NULL, NOPE,
16996                                           SEI_Head, NULL )) {
16997       fprintf(SUMA_STDERR,"Error %s: Failed to register command\n", FuncName);
16998       SUMA_RETURNe;
16999    }
17000 
17001    if (!SUMA_Engine (&list)) {
17002       fprintf(stderr, "Error %s: SUMA_Engine call failed.\n", FuncName);
17003    }
17004 
17005    SUMA_RETURNe;
17006 }
17007 
SUMA_cb_XHaviewlock_toggled(Widget w,XtPointer client_data,XtPointer callData)17008 void SUMA_cb_XHaviewlock_toggled (Widget w, XtPointer client_data,
17009                                   XtPointer callData)
17010 {
17011    static char FuncName[] = {"SUMA_cb_XHaviewlock_toggled"};
17012    DList *list=NULL;
17013    SUMA_EngineData *ED = NULL;
17014 
17015    SUMA_ENTRY;
17016 
17017    list = SUMA_CreateList();
17018    ED = SUMA_InitializeEngineListData (SE_ToggleLockAllViews);
17019    if (!SUMA_RegisterEngineListCommand (  list, ED,
17020                                           SEF_Empty, NULL,
17021                                           SES_SumaWidget, NULL, NOPE,
17022                                           SEI_Head, NULL )) {
17023       fprintf(SUMA_STDERR,"Error %s: Failed to register command\n", FuncName);
17024       SUMA_RETURNe;
17025    }
17026    if (!SUMA_Engine (&list)) {
17027       fprintf(stderr, "Error %s: SUMA_Engine call failed.\n", FuncName);
17028    }
17029 
17030 
17031    SUMA_RETURNe;
17032 
17033 }
17034 
SUMA_cb_XHviewlock_toggled(Widget w,XtPointer client_data,XtPointer callData)17035 void SUMA_cb_XHviewlock_toggled(Widget w, XtPointer client_data,
17036                                  XtPointer callData)
17037 {
17038    static char FuncName[] = {"SUMA_cb_XHviewlock_toggled"};
17039    SUMA_Boolean LocalHead = NOPE;
17040    DList *list=NULL;
17041    SUMA_EngineData *ED = NULL;
17042    int i = (INT_CAST) client_data;
17043 
17044    SUMA_ENTRY;
17045 
17046    list = SUMA_CreateList ();
17047    ED = SUMA_InitializeEngineListData (SE_ToggleLockView);
17048    if (!SUMA_RegisterEngineListCommand (  list, ED,
17049                                           SEF_i, (void*)&i,
17050                                           SES_SumaWidget, NULL, NOPE,
17051                                           SEI_Head, NULL )) {
17052       fprintf(SUMA_STDERR,"Error %s: Failed to register command\n", FuncName);
17053       SUMA_RETURNe;
17054    }
17055    if (!SUMA_Engine (&list)) {
17056       fprintf(stderr, "Error %s: SUMA_Engine call failed.\n", FuncName);
17057    }
17058 
17059    SUMA_RETURNe;
17060 }
17061 
17062 /*!
17063    \brief open a new viewer, expects nothing in data
17064 */
17065 
SUMA_cb_newSumaCont(Widget w,XtPointer client_data,XtPointer callData)17066 void SUMA_cb_newSumaCont(Widget w, XtPointer client_data, XtPointer callData)
17067 {
17068    static char FuncName[] = {"SUMA_cb_newSumaCont"};
17069    SUMA_Boolean LocalHead = NOPE;
17070 
17071    SUMA_ENTRY;
17072 
17073    fprintf(SUMA_STDOUT, "%s: Opening a new controller...\n", FuncName);
17074    /* open a new controller */
17075    if (!SUMA_X_SurfaceViewer_Create ()) {
17076       SUMA_S_Err("Failed in SUMA_X_SurfaceViewer_Create.");
17077       SUMA_RETURNe;
17078    }
17079 
17080    SUMA_RETURNe;
17081 }
17082 /*!
17083    \brief Close the suma controller, expects nothing in data
17084 */
SUMA_cb_closeSumaCont(Widget w,XtPointer data,XtPointer callData)17085 void SUMA_cb_closeSumaCont(Widget w, XtPointer data, XtPointer callData)
17086 {
17087    static char FuncName[] = {"SUMA_cb_closeSumaCont"};
17088    SUMA_Boolean LocalHead = NOPE;
17089 
17090    SUMA_ENTRY;
17091 
17092    if (!SUMAg_CF->X->SumaCont->AppShell) SUMA_RETURNe;
17093 
17094    switch (SUMA_CLOSE_MODE)   {/* NO open GL drawables in this widget*/
17095       case SUMA_WITHDRAW:
17096          if (LocalHead)
17097             fprintf (SUMA_STDERR,
17098                      "%s: Withdrawing Suma Controller...\n", FuncName);
17099          XWithdrawWindow(SUMAg_CF->X->DPY_controller1,
17100             XtWindow(SUMAg_CF->X->SumaCont->AppShell),
17101             XScreenNumberOfScreen(XtScreen(SUMAg_CF->X->SumaCont->AppShell)));
17102          break;
17103       case SUMA_DESTROY:
17104          if (LocalHead)
17105             fprintf (SUMA_STDERR,
17106                      "%s: Destroying Suma Controller...\n", FuncName);
17107          XtDestroyWidget(SUMAg_CF->X->SumaCont->AppShell);
17108          SUMAg_CF->X->SumaCont->AppShell = NULL;
17109          break;
17110       default:
17111          SUMA_S_Err("Not setup to deal with this closing mode");
17112          SUMA_RETURNe;
17113          break;
17114    }
17115 
17116    SUMA_RETURNe;
17117 
17118 }
17119 
17120 /*!
17121 
17122    \brief climb widget tree until we get to the top.  Return the Shell
17123    tw = SUMA_GetTopShell(w);
17124 
17125    \param w (Widget) widget for which the top widget is sought
17126    \return tw (Widget) top widget
17127 
17128  * Written by Dan Heller and Paula Ferguson.
17129  * Copyright 1994, O'Reilly & Associates, Inc.
17130  * see full notice in the beginning of this file
17131 
17132 */
SUMA_GetTopShell(Widget w)17133 Widget SUMA_GetTopShell(Widget w)
17134 {
17135     while (w && !XtIsWMShell (w))
17136         w = XtParent (w);
17137     return w;
17138 }
17139 
17140 /*!
17141    \brief Sets a button on a radio box
17142 */
17143 
SUMA_set_Lock_rb(SUMA_rb_group * Lock_rbg,int irb,int but)17144 void SUMA_set_Lock_rb (SUMA_rb_group * Lock_rbg, int irb, int but)
17145 {
17146    static char FuncName[] = {"SUMA_set_Lock_rb"};
17147    SUMA_Boolean LocalHead = NOPE;
17148    Widget w;
17149    int i, itb, ifb;
17150 
17151    SUMA_ENTRY;
17152 
17153    ifb = irb*Lock_rbg->N_but; /* index of first button in radio box irb */
17154    itb = ifb+but; /* index of button to modify */
17155 
17156    i = 0;
17157    while (i<Lock_rbg->N_but) {
17158       /* get the widget of the button in question */
17159       w = Lock_rbg->tb[ifb+i];
17160       if (!w) SUMA_RETURNe; /* this happens before opening the SUMA controller */
17161       if ( (ifb + i) == itb) XmToggleButtonSetState (w, YUP, NOPE);
17162        else XmToggleButtonSetState (w, NOPE, NOPE);
17163       ++i;
17164    }
17165 
17166    SUMA_RETURNe;
17167 
17168 }
17169 
SUMA_set_Lock_arb(SUMA_rb_group * Lock_rbg)17170 void SUMA_set_Lock_arb (SUMA_rb_group * Lock_rbg)
17171 {
17172    static char FuncName[] = {"SUMA_set_Lock_arb"};
17173    int i, sumlock;
17174 
17175    SUMA_ENTRY;
17176 
17177    if (!Lock_rbg->atb[0]) SUMA_RETURNe;
17178    /* find out if all buttons are set to the same value */
17179    sumlock = 0;
17180    for (i=0; i < SUMA_MAX_SURF_VIEWERS; ++i) {
17181       sumlock += SUMAg_CF->Locked[i];
17182    }
17183 
17184    if (sumlock == SUMA_MAX_SURF_VIEWERS * SUMA_No_Lock) { /* all no lock */
17185          XmToggleButtonSetState (Lock_rbg->atb[0], YUP, NOPE);
17186          XmToggleButtonSetState (Lock_rbg->atb[1], NOPE, NOPE);
17187          XmToggleButtonSetState (Lock_rbg->atb[2], NOPE, NOPE);
17188    }else if (sumlock == SUMA_MAX_SURF_VIEWERS * SUMA_I_Lock) {
17189          XmToggleButtonSetState (Lock_rbg->atb[0], NOPE, NOPE);
17190          XmToggleButtonSetState (Lock_rbg->atb[1], YUP, NOPE);
17191          XmToggleButtonSetState (Lock_rbg->atb[2], NOPE, NOPE);
17192    }else if (sumlock == SUMA_MAX_SURF_VIEWERS * SUMA_XYZ_Lock) {
17193          XmToggleButtonSetState (Lock_rbg->atb[0], NOPE, NOPE);
17194          XmToggleButtonSetState (Lock_rbg->atb[1], NOPE, NOPE);
17195          XmToggleButtonSetState (Lock_rbg->atb[2], YUP, NOPE);
17196    }else {
17197          XmToggleButtonSetState (Lock_rbg->atb[0], NOPE, NOPE);
17198          XmToggleButtonSetState (Lock_rbg->atb[1], NOPE, NOPE);
17199          XmToggleButtonSetState (Lock_rbg->atb[2], NOPE, NOPE);
17200    }
17201 
17202    SUMA_RETURNe;
17203 
17204 }
17205 
SUMA_set_LockView_atb(void)17206 void SUMA_set_LockView_atb (void)
17207 {
17208    static char FuncName[] = {"SUMA_set_LockView_atb"};
17209    int i, sumlock;
17210 
17211    SUMA_ENTRY;
17212 
17213    /* find out if all buttons are set to the same value */
17214    sumlock = 0;
17215    for (i=0; i < SUMA_MAX_SURF_VIEWERS; ++i) {
17216       sumlock += SUMAg_CF->ViewLocked[i];
17217    }
17218 
17219    if (sumlock == SUMA_MAX_SURF_VIEWERS) { /* all locked */
17220       XmToggleButtonSetState (SUMAg_CF->X->SumaCont->LockAllView_tb, YUP, NOPE);
17221    }else if (sumlock == NOPE) { /* none locked */
17222       XmToggleButtonSetState (SUMAg_CF->X->SumaCont->LockAllView_tb, NOPE, NOPE);
17223    }else {/* a mix and match */
17224       /* do nothing for now */
17225    }
17226 
17227    SUMA_RETURNe;
17228 }
17229 
17230 /*!
17231    \brief opens a text window with information about the surface viewer
17232    -expects sv pointer in userdata
17233    Feb 23 04: Now requiring sv in client_data. Other widgets will be calling
17234    this function too so w should not be used
17235 */
SUMA_cb_moreViewerInfo(Widget w,XtPointer client_data,XtPointer callData)17236 void SUMA_cb_moreViewerInfo (Widget w, XtPointer client_data, XtPointer callData)
17237 {
17238    static char FuncName[] = {"SUMA_cb_moreViewerInfo"};
17239    SUMA_SurfaceViewer *sv=NULL;
17240    void *n=NULL;
17241    char *s = NULL, stmp[100];
17242    SUMA_Boolean LocalHead = NOPE;
17243    SUMA_CREATE_TEXT_SHELL_STRUCT *TextShell = NULL;
17244    int isv;
17245 
17246    SUMA_ENTRY;
17247 
17248    #if 0
17249    /* The userdata way ,
17250    not setup for all widgets calling this function .... */
17251    XtVaGetValues (w,
17252                   XmNuserData, &n,
17253                   NULL);
17254    sv = (SUMA_SurfaceViewer *)n;
17255    #else
17256    /* the good old way, Feb 23 04 */
17257    sv = (SUMA_SurfaceViewer *)client_data;
17258    #endif
17259 
17260    isv = SUMA_WhichSV(sv, SUMAg_SVv, SUMAg_N_SVv);
17261    /* form the string of the surface info */
17262    if (!(s = SUMA_SurfaceViewer_StructInfo(sv, 1))) {
17263       SUMA_S_Err("Failed in SUMA_SurfaceViewer_StructInfo.");
17264       SUMA_RETURNe;
17265    }
17266    sprintf(stmp, "[%c] Viewer Info", 65+isv);
17267 
17268    /* check to see if window is already open, if it is, just raise it */
17269    if (sv->X->ViewCont->ViewerInfo_TextShell) {
17270      sv->X->ViewCont->ViewerInfo_TextShell =
17271          SUMA_CreateTextShell(s, stmp, sv->X->ViewCont->ViewerInfo_TextShell);
17272      SUMA_ifree(s);
17273      XRaiseWindow (SUMAg_CF->X->DPY_controller1,
17274          XtWindow(sv->X->ViewCont->ViewerInfo_TextShell->toplevel));
17275      SUMA_RETURNe;
17276    }
17277 
17278 
17279    if (s) {
17280       TextShell =  SUMA_CreateTextShellStruct (
17281                                  SUMA_ViewerInfo_open,
17282                                  (void *)sv, "SurfaceViewer",
17283                                  SUMA_ViewerInfo_destroyed,
17284                                  (void *)sv, NULL);
17285       if (!TextShell) {
17286          fprintf (SUMA_STDERR,
17287                   "Error %s: Failed in SUMA_CreateTextShellStruct.\n",
17288                    FuncName);
17289          SUMA_RETURNe;
17290       }
17291       sv->X->ViewCont->ViewerInfo_TextShell =
17292             SUMA_CreateTextShell(s, stmp, TextShell);
17293       SUMA_ifree(s);
17294       /* invert the widget to indicate window is open */
17295       if (sv->X->ViewCont && sv->X->ViewCont->ViewerInfo_pb)
17296                MCW_invert_widget (sv->X->ViewCont->ViewerInfo_pb);
17297    }
17298 
17299 
17300    SUMA_RETURNe;
17301 }
17302 
17303 /*!
17304    \brief Function called when Viewer Info window is open
17305 */
SUMA_ViewerInfo_open(void * p)17306 void SUMA_ViewerInfo_open (void *p)
17307 {
17308    static char FuncName[] = {"SUMA_ViewerInfo_open"};
17309    SUMA_SurfaceViewer *sv= NULL;
17310 
17311    SUMA_ENTRY;
17312 
17313    sv = (SUMA_SurfaceViewer *)p;
17314 
17315 
17316    SUMA_RETURNe;
17317 }
17318 
17319 /*!
17320    \brief Function called when Viewer Info window is destroyed
17321 */
SUMA_ViewerInfo_destroyed(void * p)17322 void SUMA_ViewerInfo_destroyed (void *p)
17323 {
17324    static char FuncName[] = {"SUMA_ViewerInfo_destroyed"};
17325    SUMA_SurfaceViewer *sv= NULL;
17326 
17327    SUMA_ENTRY;
17328 
17329    sv = (SUMA_SurfaceViewer *)p;
17330    MCW_invert_widget (sv->X->ViewCont->ViewerInfo_pb);
17331 
17332    sv->X->ViewCont->ViewerInfo_TextShell = NULL;
17333    SUMA_RETURNe;
17334 }
17335 
17336 
17337 /*!
17338    \brief Opens a text viewer with SUMA's structure info
17339    - expects nothing for input
17340 */
SUMA_cb_moreSumaInfo(Widget w,XtPointer client_data,XtPointer callData)17341 void SUMA_cb_moreSumaInfo (Widget w, XtPointer client_data, XtPointer callData)
17342 {
17343    static char FuncName[] = {"SUMA_cb_moreSumaInfo"};
17344    SUMA_SurfaceObject *SO=NULL;
17345    void *n=NULL;
17346    char *s = NULL;
17347    SUMA_Boolean LocalHead = NOPE;
17348    SUMA_CREATE_TEXT_SHELL_STRUCT *TextShell = NULL;
17349 
17350    SUMA_ENTRY;
17351 
17352    /* form the string of the surface info */
17353    if (!(s = SUMA_CommonFieldsInfo (SUMAg_CF, 1))) {
17354       SUMA_S_Err("Failed in SUMA_CommonFieldsInfo.");
17355       SUMA_RETURNe;
17356    }
17357 
17358    /* check to see if window is already open, if it is, just raise it */
17359    if (SUMAg_CF->X->SumaCont->SumaInfo_TextShell) {
17360       SUMAg_CF->X->SumaCont->SumaInfo_TextShell =
17361                SUMA_CreateTextShell(s, "SUMA",
17362                            SUMAg_CF->X->SumaCont->SumaInfo_TextShell);
17363       SUMA_ifree(s);
17364       XRaiseWindow (SUMAg_CF->X->DPY_controller1,
17365                   XtWindow(SUMAg_CF->X->SumaCont->SumaInfo_TextShell->toplevel));
17366       SUMA_RETURNe;
17367    }
17368 
17369    if (s) {
17370       TextShell =  SUMA_CreateTextShellStruct (SUMA_SumaInfo_open, NULL, NULL,
17371                                                SUMA_SumaInfo_destroyed, NULL,
17372                                                NULL);
17373       if (!TextShell) {
17374          fprintf (SUMA_STDERR,
17375                   "Error %s: Failed in SUMA_CreateTextShellStruct.\n", FuncName);
17376          SUMA_RETURNe;
17377       }
17378       SUMAg_CF->X->SumaCont->SumaInfo_TextShell =
17379                         SUMA_CreateTextShell(s, "SUMA", TextShell);
17380       SUMA_ifree(s);
17381    }
17382 
17383 
17384    SUMA_RETURNe;
17385 }
17386 
17387 /*!
17388    \brief Function called when Suma Info window is open
17389 */
SUMA_SumaInfo_open(void * p)17390 void SUMA_SumaInfo_open (void *p)
17391 {
17392    static char FuncName[] = {"SUMA_SumaInfo_open"};
17393 
17394    SUMA_ENTRY;
17395 
17396    /* nothing to do here ... */
17397 
17398    SUMA_RETURNe;
17399 }
17400 
17401 /*!
17402    \brief Function called when Suma Info window is destroyed
17403 */
SUMA_SumaInfo_destroyed(void * p)17404 void SUMA_SumaInfo_destroyed (void *p)
17405 {
17406    static char FuncName[] = {"SUMA_SumaInfo_destroyed"};
17407    SUMA_SurfaceObject *SO= NULL;
17408 
17409    SUMA_ENTRY;
17410 
17411    SUMAg_CF->X->SumaCont->SumaInfo_TextShell = NULL;
17412    SUMA_RETURNe;
17413 }
17414 
17415 /*!
17416    \brief opens a text window with information about the surface object in focus
17417    -expects SO pointer in userdata
17418    Feb 23 04: Now requiring ado in client_data. Other widgets will be calling
17419    this function too, so w should not be used
17420 */
SUMA_cb_moreSurfInfo(Widget w,XtPointer client_data,XtPointer callData)17421 void SUMA_cb_moreSurfInfo (Widget w, XtPointer client_data, XtPointer callData)
17422 {
17423    static char FuncName[] = {"SUMA_cb_moreSurfInfo"};
17424    SUMA_ALL_DO *ado=NULL;
17425    void *n=NULL;
17426    char *s = NULL;
17427    SUMA_Boolean LocalHead = NOPE;
17428    SUMA_X_SurfCont *SurfCont=NULL;
17429    SUMA_CREATE_TEXT_SHELL_STRUCT *TextShell = NULL;
17430 
17431    SUMA_ENTRY;
17432 
17433    ado = (SUMA_ALL_DO *)client_data;
17434    SurfCont = SUMA_ADO_Cont(ado);
17435 
17436    if (!(s = SUMA_ADO_Info (ado, SUMAg_CF->DsetList, 0))) {
17437       SUMA_S_Err("Failed in SUMA_SurfaceObject_Info.");
17438       SUMA_RETURNe;
17439    }
17440 
17441    /* check to see if window is already open, if it is, just raise it */
17442    if (SurfCont->SurfInfo_TextShell) {
17443       SurfCont->SurfInfo_TextShell =
17444          SUMA_CreateTextShell(s, SUMA_ADO_Label(ado),
17445                               SurfCont->SurfInfo_TextShell);
17446       SUMA_ifree(s);
17447       XRaiseWindow (SUMAg_CF->X->DPY_controller1,
17448             XtWindow(SurfCont->SurfInfo_TextShell->toplevel));
17449       SUMA_RETURNe;
17450    }
17451 
17452    if (s) {
17453       TextShell =
17454          SUMA_CreateTextShellStruct (SUMA_SurfInfo_open, (void *)ado, "ADO",
17455                                      SUMA_SurfInfo_destroyed, (void *)ado,
17456                                      NULL);
17457       if (!TextShell) {
17458          SUMA_S_Err("Failed in SUMA_CreateTextShellStruct.");
17459          SUMA_RETURNe;
17460       }
17461       SurfCont->SurfInfo_TextShell =
17462          SUMA_CreateTextShell(s, SUMA_ADO_Label(ado), TextShell);
17463       SUMA_ifree(s);
17464       /* invert the widget to indicate window is open */
17465       MCW_invert_widget (SurfCont->SurfInfo_pb);
17466    }
17467 
17468 
17469    SUMA_RETURNe;
17470 }
17471 
17472 /*!
17473    \brief Function called when Surface Info window is open
17474 */
SUMA_SurfInfo_open(void * p)17475 void SUMA_SurfInfo_open (void *p)
17476 {
17477    static char FuncName[] = {"SUMA_SurfInfo_open"};
17478    SUMA_ALL_DO *ado= NULL;
17479 
17480    SUMA_ENTRY;
17481 
17482    ado = (SUMA_ALL_DO *)p;
17483 
17484 
17485    SUMA_RETURNe;
17486 }
17487 
17488 /*!
17489    \brief Function called when Surface Info window is destroyed
17490 */
SUMA_SurfInfo_destroyed(void * p)17491 void SUMA_SurfInfo_destroyed (void *p)
17492 {
17493    static char FuncName[] = {"SUMA_SurfInfo_destroyed"};
17494    SUMA_ALL_DO *ado= NULL;
17495    SUMA_X_SurfCont *SurfCont=NULL;
17496 
17497    SUMA_ENTRY;
17498    if (!(ado = (SUMA_ALL_DO *)p) || !(SurfCont = SUMA_ADO_Cont(ado))) {
17499       SUMA_S_Err("Real bad cheese");
17500       SUMA_RETURNe;
17501    }
17502    MCW_invert_widget (SurfCont->SurfInfo_pb);
17503 
17504    SurfCont->SurfInfo_TextShell = NULL;
17505    SUMA_RETURNe;
17506 }
17507 
17508 #define NO_SPACE(str) {\
17509    int m_i; \
17510    for (m_i=0; str[m_i]!='\0';++m_i) { \
17511       if (isspace(str[m_i])) { str[m_i]='_'; } \
17512    }  \
17513 }
17514 
17515 
SUMA_WriteStringToFile(char * fname,char * s,int over,int view)17516 char * SUMA_WriteStringToFile(char *fname, char *s, int over, int view)
17517 {
17518    static char FuncName[]={"SUMA_WriteStringToFile"};
17519    FILE *fout=NULL;
17520    char *fused=NULL, *viewer=NULL;
17521    int i=0;
17522    char sbuf[128], cmd[256];
17523 
17524    SUMA_ENTRY;
17525 
17526    if (!fname) fname = FuncName;
17527    if (!s) SUMA_RETURN(NULL);
17528 
17529    fused = SUMA_copy_string(fname);SUMA_NICEATE_FILENAME(fused, '_');
17530    if (!over) {
17531       i = 0;
17532       while (i < 10000 && SUMA_filexists(fused)) {
17533          SUMA_free(fused);fused = NULL;
17534          sprintf(sbuf,".%03d", i);
17535          fused = SUMA_append_replace_string(fname,sbuf,"", 0); NO_SPACE(fused);
17536          SUMA_NICEATE_FILENAME(fused, '_');
17537          ++i;
17538       }
17539       if (i >= 10000) {
17540          SUMA_S_Errv("Cannot find available name for %s\n"
17541                      "I am giving up.\n", fname);
17542          SUMA_free(fused); fused = NULL;
17543          SUMA_RETURN(NULL);
17544       }
17545    }
17546 
17547    if ((fout = fopen(fused,"w"))) {
17548       fprintf(fout,"%s", s);
17549       fclose(fout);
17550    } else {
17551       SUMA_S_Errv("Failed to write to %s.\n", fused);
17552       SUMA_free(fused);
17553       SUMA_RETURN(NULL);
17554    }
17555 
17556    if (view) {
17557       if (!(viewer = GetAfniTextEditor())) {
17558          SUMA_S_Err("No GUI editor defined, and guessing game failed.\n"
17559               "Set AFNI_GUI_EDITOR in your .afnirc for this option to work.\n");
17560          SUMA_free(fused);
17561          SUMA_RETURN(NULL);
17562       }
17563       snprintf(cmd,250*sizeof(char),"%s %s &", viewer, fused);
17564       system(cmd);
17565    }
17566 
17567    SUMA_RETURN(fused);
17568 }
17569 
17570 /*!
17571    View text content of shell in editor
17572 */
SUMA_ViewTextShellInEditor(Widget w,XtPointer ud,XtPointer cd)17573 void SUMA_ViewTextShellInEditor(Widget w, XtPointer ud, XtPointer cd)
17574 {
17575    static char FuncName[] = {"SUMA_ViewTextShellInEditor"};
17576    SUMA_CREATE_TEXT_SHELL_STRUCT *TextShell=NULL;
17577    char *string=NULL, *fused=NULL;
17578    char sbuf[128];
17579 
17580    SUMA_ENTRY;
17581 
17582    if (!GetAfniTextEditor()) {
17583       SUMA_SLP_Err("No GUI editor defined, and guessing game failed.\n"
17584               "Set AFNI_GUI_EDITOR in your .afnirc for this option to work.");
17585       SUMA_RETURNe;
17586    }
17587    TextShell = (SUMA_CREATE_TEXT_SHELL_STRUCT *)ud;
17588 
17589    if (!(string = XmTextGetString (TextShell->text_w)) || !*string) {
17590       SUMA_SLP_Warn("Nothing to save");
17591       SUMA_RETURNe;
17592    }
17593 
17594    snprintf(sbuf, 120*sizeof(char),"/tmp/VTSIE.%s.txt",TextShell->title);
17595    if (!(fused = SUMA_WriteStringToFile(sbuf, string, 0, 1))) {
17596       SUMA_SLP_Err("Failed to write text.");
17597    } else {
17598       SUMA_free(fused); fused=NULL;
17599    }
17600 
17601    XtFree(string); string=NULL;
17602 
17603    SUMA_RETURNe;
17604 }
17605 
17606 /*!
17607    Save text content of shell to a file
17608 */
SUMA_SaveTextShell(Widget w,XtPointer ud,XtPointer cd)17609 void SUMA_SaveTextShell(Widget w, XtPointer ud, XtPointer cd)
17610 {
17611    static char FuncName[] = {"SUMA_SaveTextShell"};
17612    SUMA_CREATE_TEXT_SHELL_STRUCT *TextShell=NULL;
17613    char *string=NULL, *fused=NULL;
17614    char sbuf[128];
17615 
17616    SUMA_ENTRY;
17617 
17618    TextShell = (SUMA_CREATE_TEXT_SHELL_STRUCT *)ud;
17619 
17620    if (!(string = XmTextGetString (TextShell->text_w)) || !*string) {
17621       SUMA_SLP_Warn("Nothing to save");
17622       SUMA_RETURNe;
17623    }
17624 
17625    if (!(fused = SUMA_WriteStringToFile(TextShell->title, string, 0, 0))) {
17626       SUMA_SLP_Err("Failed to write text.");
17627    } else {
17628       snprintf(sbuf,127*sizeof(char),
17629                    "Wrote window content to %s", fused);
17630       SUMA_free(fused); fused=NULL;
17631       SUMA_SLP_Note("%s",sbuf);
17632    }
17633 
17634    XtFree(string); string=NULL;
17635 
17636    SUMA_RETURNe;
17637 }
17638 
17639 
17640 /*!
17641    Refresh content of text shell
17642 */
SUMA_RefreshTextShell(Widget w,XtPointer ud,XtPointer cd)17643 void SUMA_RefreshTextShell(Widget w, XtPointer ud, XtPointer cd)
17644 {
17645    static char FuncName[] = {"SUMA_RefreshTextShell"};
17646    SUMA_CREATE_TEXT_SHELL_STRUCT *TextShell=NULL;
17647    char *string=NULL, *fused=NULL;
17648    char sbuf[128];
17649    SUMA_Boolean LocalHead = NOPE;
17650 
17651    SUMA_ENTRY;
17652 
17653    TextShell = (SUMA_CREATE_TEXT_SHELL_STRUCT *)ud;
17654 
17655    if (!TextShell->OpenDataType) { /* not refreshable for sure */
17656       SUMA_RETURNe;
17657    }
17658 
17659    /* find out where this text shell comes from based on the OpenDataType */
17660    if (strstr(TextShell->OpenDataType, "SurfaceViewer")) {
17661       SUMA_cb_moreViewerInfo(w, TextShell->OpenData, cd);
17662    } else if (strstr(TextShell->OpenDataType, "ADO")) {
17663       SUMA_cb_moreSurfInfo(w, TextShell->OpenData, cd);
17664    } else {
17665       /* nothing know as updatable */
17666       SUMA_LHv("Nothing done for >%s<%s>\n",
17667                   TextShell->title, TextShell->OpenDataType);
17668    }
17669 
17670    SUMA_RETURNe;
17671 }
17672 
17673 /*!
17674    Open weblink of text shell
17675 */
SUMA_WebTextShell(Widget w,XtPointer ud,XtPointer cd)17676 void SUMA_WebTextShell(Widget w, XtPointer ud, XtPointer cd)
17677 {
17678    static char FuncName[] = {"SUMA_WebTextShell"};
17679    SUMA_CREATE_TEXT_SHELL_STRUCT *TextShell=NULL;
17680    char *string=NULL, *fused=NULL;
17681    char sbuf[128];
17682    SUMA_Boolean LocalHead = NOPE;
17683 
17684    SUMA_ENTRY;
17685 
17686    TextShell = (SUMA_CREATE_TEXT_SHELL_STRUCT *)ud;
17687 
17688    if (!TextShell->weblink) { /* nothing to do for sure */
17689       SUMA_RETURNe;
17690    }
17691 
17692    SUMA_LH("Opening %s", TextShell->weblink);
17693    whereami_browser(TextShell->weblink);
17694 
17695    SUMA_RETURNe;
17696 }
17697 
17698 
17699 
17700 /*!
17701    \brief calls XtDestroyWidget on to top level shell of w and frees the TextShell pointer in clientdata.
17702 */
SUMA_DestroyTextShell(Widget w,XtPointer ud,XtPointer cd)17703 void SUMA_DestroyTextShell (Widget w, XtPointer ud, XtPointer cd)
17704 {
17705    static char FuncName[] = {"SUMA_DestroyTextShell"};
17706    SUMA_CREATE_TEXT_SHELL_STRUCT *TextShell=NULL;
17707 
17708    SUMA_ENTRY;
17709 
17710    TextShell = (SUMA_CREATE_TEXT_SHELL_STRUCT *)ud;
17711    if (TextShell) {
17712       if (TextShell->DestroyCallBack) {
17713          /* call destroy callback */
17714          TextShell->DestroyCallBack(TextShell->DestroyData);
17715       }
17716       SUMA_ifree(TextShell->title);
17717       SUMA_ifree(TextShell->OpenDataType);
17718       SUMA_ifree(TextShell->weblink);
17719       SUMA_free(TextShell);
17720    }
17721    XtDestroyWidget(SUMA_GetTopShell(w));
17722 
17723    SUMA_RETURNe;
17724 }
17725 
17726 
17727 /*!
17728    \brief Creates the structure used to pass widget and options back and forth from SUMA_CreateTextShell
17729    TextShellStruct = SUMA_CreateTextShellStruct (void (*opencallback)(void *data), void *opendata,
17730                                                             void (*closecallback)(void*data), void *closedata);
17731 
17732    - callbacks and their data are stored in their respective fields in TextShellStruct
17733    - All widgets are set to NULL
17734 
17735 */
17736 
SUMA_CreateTextShellStruct(void (* opencallback)(void * data),void * opendata,char * odtype,void (* closecallback)(void * data),void * closedata,char * weblink)17737 SUMA_CREATE_TEXT_SHELL_STRUCT * SUMA_CreateTextShellStruct (
17738                                     void (*opencallback)(void *data),
17739                                     void *opendata, char *odtype,
17740                                     void (*closecallback)(void*data),
17741                                     void *closedata,
17742                                     char *weblink)
17743 {
17744    static char FuncName[] = {"SUMA_CreateTextShellStruct"};
17745    SUMA_CREATE_TEXT_SHELL_STRUCT *TextShell=NULL;
17746 
17747    SUMA_ENTRY;
17748 
17749    TextShell = (SUMA_CREATE_TEXT_SHELL_STRUCT *)
17750                SUMA_calloc(1,sizeof(SUMA_CREATE_TEXT_SHELL_STRUCT));
17751    if (!TextShell) {
17752       fprintf (SUMA_STDERR,
17753                "Error %s: Failed to allocate for TextShell.\n",
17754                FuncName);
17755       SUMA_RETURN (NULL);
17756    }
17757    if (!odtype) odtype = "NotSet";
17758    TextShell->text_w =  TextShell->search_w =
17759                         TextShell->text_output =
17760                         TextShell->toplevel = NULL;
17761    TextShell->case_sensitive = NOPE;
17762    TextShell->allow_edit = NOPE;
17763    TextShell->OpenCallBack = opencallback;
17764    TextShell->OpenData = opendata;
17765    TextShell->OpenDataType = SUMA_copy_string(odtype);
17766    TextShell->DestroyCallBack = closecallback;
17767    TextShell->DestroyData = closedata;
17768    TextShell->CursorAtBottom = NOPE;
17769    TextShell->title = NULL;
17770    TextShell->weblink = NULL;
17771    if (weblink) TextShell->weblink = SUMA_copy_string(weblink);
17772    SUMA_RETURN (TextShell);
17773 }
17774 
17775 /*!
17776    \brief Opens a window with text information in it.
17777 
17778    \param s (char *) string to display, must be null terminated.
17779    \param title (char *) title of window
17780    \param TextShell (SUMA_CreateTextShell *) containing options
17781                                                 for SUMA_CreateTextShell
17782       if TextShell->toplevel then only the log message is updated, otherwise
17783                                                 the window is created.
17784    \return TextShell (SUMA_CreateTextShell *) same structure sent to function
17785                                               but with widgets fields filled.
17786 
17787    \sa SUMA_CreateTextShellStruct
17788 
17789    - based on example SUMA_search_text from "Motif Programming Manual"
17790    see copyright notice in beginning of SUMA_display.c
17791 */
SUMA_CreateTextShell(char * s,char * title,SUMA_CREATE_TEXT_SHELL_STRUCT * TextShell)17792 SUMA_CREATE_TEXT_SHELL_STRUCT * SUMA_CreateTextShell (
17793                                  char *s,
17794                                  char *title,
17795                                  SUMA_CREATE_TEXT_SHELL_STRUCT *TextShell)
17796 {
17797    static char FuncName[] = {"SUMA_CreateTextShell"};
17798    Widget rowcol_v, rowcol_h, close_w, save_w, view_w,
17799           form, frame, toggle_case_w, refresh_w, web_w;
17800    int n;
17801    Pixel fg_pix = 0;
17802    Arg args[30];
17803    static XmTextScanType sarray[] = {  XmSELECT_POSITION,
17804                                        XmSELECT_WORD,
17805                                        XmSELECT_LINE,
17806                                        XmSELECT_ALL };
17807    SUMA_Boolean LocalHead = NOPE;
17808 
17809    SUMA_ENTRY;
17810 
17811    if (!title) title = "NO_Title";
17812    if (!TextShell) {
17813       SUMA_S_Err("Need Text Shell first");
17814       SUMA_RETURN(TextShell);
17815    }
17816    if (TextShell->title) SUMA_free(TextShell->title);
17817    TextShell->title = SUMA_copy_string(title);
17818 
17819    if (TextShell->OpenCallBack) { /* do the opening callback */
17820       SUMA_LH("Calling OpenCallBack.\n");
17821       TextShell->OpenCallBack(TextShell->OpenData);
17822    }
17823 
17824    if (!TextShell->toplevel) { /* need to create window */
17825       SUMA_LH("Creating new text shell window.\n");
17826       TextShell->toplevel = XtVaAppCreateShell (title, "Suma",
17827          topLevelShellWidgetClass, SUMAg_CF->X->DPY_controller1 ,
17828          XmNdeleteResponse, XmDO_NOTHING,
17829          NULL);
17830 
17831       XmAddWMProtocolCallback(/* make "Close" window menu work */
17832          TextShell->toplevel,
17833          XmInternAtom(  SUMAg_CF->X->DPY_controller1 ,
17834                         "WM_DELETE_WINDOW" ,
17835                         False ) ,
17836          SUMA_DestroyTextShell, TextShell) ;
17837 
17838       form = XtVaCreateWidget ("textoutput",
17839         xmFormWidgetClass, TextShell->toplevel, NULL);
17840 
17841 
17842       rowcol_v = XtVaCreateWidget ("rowcol_v",
17843         xmRowColumnWidgetClass, form, NULL);
17844 
17845       rowcol_h = XtVaCreateWidget ("rowcol_h",
17846         xmRowColumnWidgetClass, rowcol_v,
17847         XmNorientation,  XmHORIZONTAL,
17848         NULL);
17849       XtVaCreateManagedWidget ("Search Pattern:",
17850         xmLabelWidgetClass, rowcol_h, NULL);
17851 
17852       TextShell->search_w = XtVaCreateManagedWidget ("SUMA_search_text",
17853         xmTextFieldWidgetClass, rowcol_h, NULL);
17854 
17855       XtVaGetValues (TextShell->search_w, XmNforeground, &fg_pix, NULL);
17856       toggle_case_w = XtVaCreateManagedWidget ("Case Sensitive",
17857          xmToggleButtonWidgetClass, rowcol_h,
17858          XmNset, TextShell->case_sensitive,
17859          XmNselectColor, fg_pix,
17860          NULL);
17861       XtAddCallback (toggle_case_w,
17862                      XmNvalueChangedCallback,
17863                      SUMA_cb_ToggleCaseSearch,
17864                      TextShell);
17865       refresh_w = XtVaCreateManagedWidget (
17866                      "Refresh",
17867                      xmPushButtonWidgetClass,
17868                      rowcol_h, NULL);
17869       XtAddCallback (refresh_w,
17870                      XmNactivateCallback,
17871                      SUMA_RefreshTextShell,
17872                      TextShell);
17873       save_w = XtVaCreateManagedWidget (
17874                      "Save",
17875                      xmPushButtonWidgetClass,
17876                      rowcol_h, NULL);
17877       XtAddCallback (save_w,
17878                      XmNactivateCallback,
17879                      SUMA_SaveTextShell,
17880                      TextShell);
17881       view_w = XtVaCreateManagedWidget (
17882                      "View",
17883                      xmPushButtonWidgetClass,
17884                      rowcol_h, NULL);
17885       XtAddCallback (view_w,
17886                      XmNactivateCallback,
17887                      SUMA_ViewTextShellInEditor,
17888                      TextShell);
17889       if (TextShell->weblink) {
17890          web_w = XtVaCreateManagedWidget (
17891                      "WHelp",
17892                      xmPushButtonWidgetClass,
17893                      rowcol_h, NULL);
17894          XtAddCallback (web_w,
17895                         XmNactivateCallback,
17896                         SUMA_WebTextShell,
17897                         TextShell);
17898          MCW_set_widget_bg( web_w , MCW_buthighlight(web_w) , 0 ) ;
17899       }
17900       close_w = XtVaCreateManagedWidget (
17901                      "Close",
17902                      xmPushButtonWidgetClass,
17903                      rowcol_h, NULL);
17904       XtAddCallback (close_w,
17905                      XmNactivateCallback,
17906                      SUMA_DestroyTextShell,
17907                      TextShell);
17908 
17909       XtManageChild (rowcol_h);
17910 
17911       SUMA_LH("Text output widget\n");
17912       TextShell->text_output = XtVaCreateManagedWidget ("text_output",
17913         xmTextWidgetClass, rowcol_v,
17914         XmNeditable, False,
17915         XmNcursorPositionVisible, False,
17916         XmNshadowThickness,       0,
17917         XmNhighlightThickness,    0,
17918         NULL);
17919 
17920       XtManageChild (rowcol_v);
17921 
17922       n = 0;
17923       XtSetArg (args[n], XmNrows,      10); n++;
17924       XtSetArg (args[n], XmNcolumns,   80); n++;
17925       XtSetArg (args[n], XmNeditMode,  XmMULTI_LINE_EDIT); n++;
17926       XtSetArg (args[n], XmNeditable, TextShell->allow_edit); n++;
17927       XtSetArg (args[n], XmNscrollHorizontal,  False); n++;
17928       XtSetArg (args[n], XmNwordWrap,  True); n++;
17929       XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
17930       XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
17931       XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
17932       XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
17933       XtSetArg (args[n], XmNtopWidget, rowcol_v); n++;
17934       /* XtSetArg (args[n], XmNselectionArray, sarray); n++;
17935       XtSetArg (args[n], XmNselectionArrayCount, 4); n++;
17936       XtSetArg (args[n], XmNselectThreshold, 1); n++;  leave it to defaults*/
17937 
17938       TextShell->text_w = XmCreateScrolledText (form, "text_w", args, n);
17939 
17940       SUMA_LHv("String %s\n",s?s:"NULL");
17941       if (!s) {
17942          XmTextSetString (TextShell->text_w, "No Messages.\n---------------\n");
17943       } else {
17944          XmTextSetString (TextShell->text_w, s);
17945       }
17946       XtManageChild (TextShell->text_w);
17947 
17948       SUMA_LH("Adding callback\n");
17949       XtAddCallback (TextShell->search_w,
17950                      XmNactivateCallback, SUMA_cb_search_text,
17951                      TextShell);
17952 
17953       /* Setting XmNtranslations gives warning
17954          if done inside XmCreateScrolledText ror text_w
17955 
17956       Not needed anymore, see #override in fallback resources
17957       If you keep this here, you can no longer select from the text window!
17958 
17959       XtVaSetValues  (  TextShell->text_w,
17960                         XmNtranslations,
17961                         XtParseTranslationTable(SUMA_TEXT_WIDGET_TRANSLATIONS),
17962                         NULL);
17963       */
17964 
17965       XtManageChild (form);
17966 
17967       /* pop it up if it is a topLevelShellWidgetClass */
17968       XtPopup(TextShell->toplevel, XtGrabNone);
17969 
17970       XtRealizeWidget (TextShell->toplevel);
17971    } else { /* already created, just replace text and perhaps title in title bar
17972                (in the future)*/
17973       XmTextPosition nlpos, otpos;
17974 
17975       otpos = XmTextGetInsertionPosition(TextShell->text_w);/*current position*/
17976       SUMA_LH("Setting string in previously created text shell window.\n");
17977 
17978       if (!s) XmTextSetString (TextShell->text_w,
17979                                "No Messages.\n---------------\n");
17980       else XmTextSetString (TextShell->text_w, s);
17981       nlpos = XmTextGetLastPosition (TextShell->text_w); /*new last position*/
17982       if (TextShell->CursorAtBottom) {
17983          XmTextSetInsertionPosition(TextShell->text_w, nlpos);
17984       } else {
17985          n = 1;
17986          XtVaGetValues (TextShell->text_w, XmNrows, &n, NULL);
17987          SUMA_LHv("previous pos %d, current last pos %d, num_rows %d\n",
17988                         (int)otpos, (int)nlpos, n);
17989          /* for some reason sometimes n is undefined, put restrictions */
17990          if (n<0) n = 10;  /* Bug should not happen */
17991          if (n>40) n = 40; /* Guarding for too big a shift
17992                               Might not be necessary */
17993          /* try to put the cursor in a comparable position */
17994          if ( (int)otpos < (int)nlpos ) {
17995             XmTextSetInsertionPosition(TextShell->text_w, otpos);
17996          } else {
17997             XmTextSetInsertionPosition(TextShell->text_w, nlpos);
17998          }
17999          if (n) XmTextScroll(TextShell->text_w, n/2);
18000       }
18001    }
18002    SUMA_RETURN(TextShell);
18003 }
18004 
18005 /*! \brief toggles case sensitive search
18006    - Expects a SUMA_CREATE_TEXT_SHELL_STRUCT pointer in clientdata:
18007 */
18008 
SUMA_cb_ToggleCaseSearch(Widget widget,XtPointer client_data,XtPointer call_data)18009 void SUMA_cb_ToggleCaseSearch (Widget widget, XtPointer client_data, XtPointer call_data)
18010 {
18011    static char FuncName[]={"SUMA_cb_ToggleCaseSearch"};
18012    SUMA_CREATE_TEXT_SHELL_STRUCT *TextShell;
18013 
18014    SUMA_ENTRY;
18015 
18016    TextShell = (SUMA_CREATE_TEXT_SHELL_STRUCT *)client_data;
18017    TextShell->case_sensitive = !TextShell->case_sensitive;
18018 
18019    SUMA_RETURNe;
18020 }
18021 /*!
18022     \brief searches text in a text widget for a string specified in a textfield widget and
18023     writes the results in a text_output text widget.
18024 
18025    - Expects a structure SUMA_CREATE_TEXT_SHELL_STRUCT pointer in clientdata:
18026       text_w (Widget)
18027       search_w (Widget)
18028       text_output (Widget)
18029 
18030    - Based on search_text() from "Motif Programming Manual"
18031 */
SUMA_cb_search_text(Widget widget,XtPointer client_data,XtPointer call_data)18032 void SUMA_cb_search_text(Widget widget,
18033                   XtPointer client_data, XtPointer call_data)
18034 {
18035    char *search_pat, *p, *string, buf[65];
18036    XmTextPosition pos;
18037    int len, i;
18038    Boolean found = False;
18039    SUMA_CREATE_TEXT_SHELL_STRUCT *TextShell;
18040    static char FuncName[]={"SUMA_cb_search_text"};
18041    SUMA_Boolean LocalHead = NOPE;
18042 
18043    SUMA_ENTRY;
18044 
18045 
18046    TextShell = (SUMA_CREATE_TEXT_SHELL_STRUCT *)client_data;
18047    if (!TextShell) { SUMA_SL_Err("Unexpected NULL TextShell"); SUMA_RETURNe; }
18048 
18049    /* get the text that is about to be searched */
18050    if (!(string = XmTextGetString (TextShell->text_w)) || !*string) {
18051      XmTextSetString (TextShell->text_output, "No text to search.");
18052      if (string) XtFree (string); /* may have been ""; free it */
18053      SUMA_RETURNe;
18054    }
18055    SUMA_LHv("Looking for %s\n", string);
18056    len = strlen(string);
18057    if (!TextShell->case_sensitive) {
18058       if (LocalHead)
18059          fprintf (SUMA_STDERR,"%s: Case insensitive search.\n", FuncName);
18060       /* turn string to lowercase */
18061       for (i=0; i < len; ++i) string[i] = tolower(string[i]);
18062    }
18063 
18064    /* get the pattern we're going to search for in the text. */
18065    if (!(search_pat = XmTextGetString (TextShell->search_w)) || !*search_pat) {
18066      XmTextSetString (TextShell->text_output, "Specify a search pattern.");
18067      XtFree (string); /* this we know is a string; free it */
18068      if (search_pat) XtFree (search_pat); /* this may be "", XtFree() checks.. */
18069      SUMA_RETURNe;
18070    }
18071    len = strlen (search_pat);
18072    SUMA_LHv("Pat %s\n", search_pat);
18073 
18074    if (!TextShell->case_sensitive) {
18075       /* turn search_pat to lowercase */
18076       for (i=0; i < len; ++i) search_pat[i] = tolower(search_pat[i]);
18077    }
18078    /* start searching at current cursor position + 1 to find
18079    * the -next- occurrance of string.  we may be sitting on it.
18080    */
18081    SUMA_LH("Looking down");
18082    pos = XmTextGetCursorPosition (TextShell->text_w);
18083    for (p = &string[pos+1]; (p = index (p, *search_pat)); p++)
18084      if (!strncmp (p, search_pat, len)) {
18085          found = True;
18086          break;
18087      }
18088    if (!found) { /* didn't find pattern? */
18089      /* search from beginning till we've passed "pos" */
18090       SUMA_LH("Looking from top");
18091      for (p = string;
18092              (p = index (p, *search_pat)) && p - string <= pos; p++)
18093          if (!strncmp (p, search_pat, len)) {
18094              found = True;
18095              break;
18096          }
18097    }
18098 
18099    if (!found) {
18100       SUMA_LH("Got nothing");
18101      XmTextSetString (TextShell->text_output, "Pattern not found.");
18102    } else {
18103      pos = (XmTextPosition)(p - string);
18104      snprintf (buf,sizeof(char)*64, "Pattern found at position %ld.", pos);
18105      SUMA_LH("%s",buf);
18106      XmTextSetString (TextShell->text_output, buf);
18107      SUMA_LH("insertion");
18108      XmTextSetInsertionPosition (TextShell->text_w, pos);
18109      SUMA_LH("highlight");
18110      XmTextSetHighlight(TextShell->text_w, pos, pos+len, XmHIGHLIGHT_SELECTED);
18111      SUMA_LH("freeatlast");
18112    }
18113    if (string) XtFree (string);
18114    if (search_pat) XtFree (search_pat);
18115 
18116    SUMA_RETURNe;
18117 }
18118 
18119 /*!
18120    \brief sets the saving mode
18121    - expects a SUMA_MenuCallBackData * in  client_data
18122    Nothing in client_data->ContID and Menubutton in client_data->callback_data
18123 */
SUMA_cb_SetDrawROI_SaveMode(Widget widget,XtPointer client_data,XtPointer call_data)18124 void SUMA_cb_SetDrawROI_SaveMode(Widget widget, XtPointer client_data,
18125                                  XtPointer call_data)
18126 {
18127    static char FuncName[]={"SUMA_cb_SetDrawROI_SaveMode"};
18128    SUMA_MenuCallBackData *datap=NULL;
18129    SUMA_Boolean LocalHead = NOPE;
18130 
18131    SUMA_ENTRY;
18132 
18133    datap = (SUMA_MenuCallBackData *)client_data;
18134 
18135    if (LocalHead)
18136       fprintf(SUMA_STDERR,"%s: Setting SaveMode to %d\n",
18137                FuncName, (INT_CAST)datap->callback_data);
18138    SUMAg_CF->X->DrawROI->SaveMode = (INT_CAST)datap->callback_data;
18139 
18140    SUMA_RETURNe;
18141 }
18142 
18143 
18144 /*!
18145    \brief sets the " what distance" parameter
18146    - expects a SUMA_MenuCallBackData * in  client_data
18147    Nothing in client_data->ContID and Menubutton in client_data->callback_data
18148 */
SUMA_cb_SetDrawROI_WhatDist(Widget widget,XtPointer client_data,XtPointer call_data)18149 void SUMA_cb_SetDrawROI_WhatDist(Widget widget, XtPointer client_data,
18150                                  XtPointer call_data)
18151 {
18152    static char FuncName[]={"SUMA_cb_SetDrawROI_WhatDist"};
18153    SUMA_MenuCallBackData *datap=NULL;
18154    SUMA_Boolean LocalHead = NOPE;
18155 
18156    SUMA_ENTRY;
18157 
18158    datap = (SUMA_MenuCallBackData *)client_data;
18159 
18160    if (LocalHead)
18161       fprintf(SUMA_STDERR,"%s: Setting WhatDist to %d\n",
18162                FuncName, (INT_CAST)datap->callback_data);
18163    SUMAg_CF->X->DrawROI->WhatDist = (INT_CAST)datap->callback_data;
18164 
18165    SUMA_RETURNe;
18166 }
18167 
18168 /*!
18169    \brief sets the "saving what" parameter
18170    - expects a SUMA_MenuCallBackData * in  client_data
18171    Nothing in client_data->ContID and Menubutton in client_data->callback_data
18172 */
SUMA_cb_SetDrawROI_SaveWhat(Widget widget,XtPointer client_data,XtPointer call_data)18173 void SUMA_cb_SetDrawROI_SaveWhat(Widget widget, XtPointer client_data,
18174                                     XtPointer call_data)
18175 {
18176    static char FuncName[]={"SUMA_cb_SetDrawROI_SaveWhat"};
18177    SUMA_MenuCallBackData *datap=NULL;
18178    SUMA_Boolean LocalHead = NOPE;
18179 
18180    SUMA_ENTRY;
18181 
18182    datap = (SUMA_MenuCallBackData *)client_data;
18183 
18184    if (LocalHead)
18185       fprintf(SUMA_STDERR,"%s: Setting SaveWhat to %d\n",
18186                FuncName, (INT_CAST)datap->callback_data);
18187    SUMAg_CF->X->DrawROI->SaveWhat = (INT_CAST)datap->callback_data;
18188 
18189    SUMA_RETURNe;
18190 }
18191 
18192 /*!
18193    \brief sets the rendering mode of a surface
18194 
18195    - expects a SUMA_MenuCallBackData * in  client_data
18196    with SO as client_data->ContID and Menubutton in client_data->callback_data
18197 */
SUMA_cb_SetRenderMode(Widget widget,XtPointer client_data,XtPointer call_data)18198 void SUMA_cb_SetRenderMode(Widget widget, XtPointer client_data,
18199                            XtPointer call_data)
18200 {
18201    static char FuncName[]={"SUMA_cb_SetRenderMode"};
18202    DList *list = NULL;
18203    DListElmt *Elmnt = NULL;
18204    SUMA_EngineData *ED = NULL;
18205    SUMA_MenuCallBackData *datap=NULL;
18206    SUMA_SurfaceObject *SO = NULL;
18207    int imenu = 0;
18208 
18209    SUMA_ENTRY;
18210 
18211    /* get the surface object that the setting belongs to */
18212    datap = (SUMA_MenuCallBackData *)client_data;
18213    SO = (SUMA_SurfaceObject *)datap->ContID;
18214    imenu = (INT_CAST)datap->callback_data;
18215 
18216    switch (imenu) {
18217       case SW_SurfCont_RenderViewerDefault:
18218          imenu = SRM_ViewerDefault;
18219          break;
18220       case SW_SurfCont_RenderFill:
18221          imenu = SRM_Fill;
18222          break;
18223       case SW_SurfCont_RenderLine:
18224          imenu = SRM_Line;
18225          break;
18226       case SW_SurfCont_RenderPoints:
18227          imenu = SRM_Points;
18228          break;
18229       case SW_SurfCont_RenderHide:
18230          imenu = SRM_Hide;
18231          break;
18232       default:
18233          fprintf (SUMA_STDERR, "Error %s: Unexpected widget index.\n", FuncName);
18234          break;
18235    }
18236 
18237 
18238    /* make a call to SUMA_Engine */
18239    if (!list) list = SUMA_CreateList ();
18240    SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_Redisplay_AllVisible,
18241                                        SES_SumaWidget, NULL);
18242    ED = SUMA_InitializeEngineListData (SE_SetRenderMode);
18243    Elmnt = SUMA_RegisterEngineListCommand ( list, ED,
18244                                          SEF_i, (void *)&imenu,
18245                                          SES_SumaWidget, NULL, NOPE,
18246                                          SEI_Head, NULL);
18247    if (!SUMA_RegisterEngineListCommand ( list, ED,
18248                                          SEF_vp, (void *)SO,
18249                                          SES_SumaWidget, NULL, NOPE,
18250                                          SEI_In, Elmnt)) {
18251       fprintf (SUMA_STDERR,
18252                "Error %s: Failed in SUMA_RegisterEngineListCommand.\n",
18253                FuncName);
18254       SUMA_RETURNe;
18255    }
18256 
18257 
18258    if (!SUMA_Engine (&list)) {
18259       fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_Engine.\n", FuncName);
18260       SUMA_RETURNe;
18261    }
18262 
18263    SUMA_RETURNe;
18264 }
18265 
SUMA_RenderMode2RenderModeMenuItem(int Mode)18266 int SUMA_RenderMode2RenderModeMenuItem(int Mode)
18267 {
18268    static char FuncName[]={"SUMA_RenderMode2RenderModeMenuItem"};
18269 
18270    SUMA_ENTRY;
18271 
18272    if ((Mode) >= SW_N_SurfCont_Render ||
18273        (Mode) <=  SW_SurfCont_Render) {
18274       SUMA_S_Err("Bad mode, returning FILL");
18275       SUMA_RETURN(SW_SurfCont_RenderFill);
18276    }
18277 
18278    SUMA_RETURN(Mode);
18279 }
18280 
18281 /*!
18282    \brief sets the transparency mode of a surface
18283 
18284    - expects a SUMA_MenuCallBackData * in  client_data
18285    with SO as client_data->ContID and Menubutton in client_data->callback_data
18286 */
SUMA_cb_SetTransMode(Widget widget,XtPointer client_data,XtPointer call_data)18287 void SUMA_cb_SetTransMode(Widget widget, XtPointer client_data,
18288                            XtPointer call_data)
18289 {
18290    static char FuncName[]={"SUMA_cb_SetTransMode"};
18291    DList *list = NULL;
18292    DListElmt *Elmnt = NULL;
18293    SUMA_EngineData *ED = NULL;
18294    SUMA_MenuCallBackData *datap=NULL;
18295    SUMA_SurfaceObject *SO = NULL;
18296    int imenu = 0;
18297 
18298    SUMA_ENTRY;
18299 
18300    /* get the surface object that the setting belongs to */
18301    datap = (SUMA_MenuCallBackData *)client_data;
18302    SO = (SUMA_SurfaceObject *)datap->ContID;
18303    imenu = (INT_CAST)datap->callback_data;
18304 
18305    switch (imenu) {
18306       case SW_SurfCont_TransViewerDefault:
18307          imenu = STM_ViewerDefault;
18308          break;
18309       case SW_SurfCont_Trans0:
18310          imenu = STM_0;
18311          break;
18312       case SW_SurfCont_Trans1:
18313          imenu = STM_1;
18314          break;
18315       case SW_SurfCont_Trans2:
18316          imenu = STM_2;
18317          break;
18318       case SW_SurfCont_Trans3:
18319          imenu = STM_3;
18320          break;
18321       case SW_SurfCont_Trans4:
18322          imenu = STM_4;
18323          break;
18324       case SW_SurfCont_Trans5:
18325          imenu = STM_5;
18326          break;
18327       case SW_SurfCont_Trans6:
18328          imenu = STM_6;
18329          break;
18330       case SW_SurfCont_Trans7:
18331          imenu = STM_7;
18332          break;
18333       case SW_SurfCont_Trans8:
18334          imenu = STM_8;
18335          break;
18336       case SW_SurfCont_Trans9:
18337          imenu = STM_9;
18338          break;
18339       case SW_SurfCont_Trans10:
18340          imenu = STM_10;
18341          break;
18342       case SW_SurfCont_Trans11:
18343          imenu = STM_11;
18344          break;
18345       case SW_SurfCont_Trans12:
18346          imenu = STM_12;
18347          break;
18348       case SW_SurfCont_Trans13:
18349          imenu = STM_13;
18350          break;
18351       case SW_SurfCont_Trans14:
18352          imenu = STM_14;
18353          break;
18354       case SW_SurfCont_Trans15:
18355          imenu = STM_15;
18356          break;
18357       case SW_SurfCont_Trans16:
18358          imenu = STM_16;
18359          break;
18360       default:
18361          fprintf (SUMA_STDERR, "Error %s: Unexpected widget index.\n", FuncName);
18362          break;
18363    }
18364 
18365 
18366    /* make a call to SUMA_Engine */
18367    if (!list) list = SUMA_CreateList ();
18368    SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_Redisplay_AllVisible,
18369                                        SES_SumaWidget, NULL);
18370    ED = SUMA_InitializeEngineListData (SE_SetTransMode);
18371    Elmnt = SUMA_RegisterEngineListCommand ( list, ED,
18372                                          SEF_i, (void *)&imenu,
18373                                          SES_SumaWidget, NULL, NOPE,
18374                                          SEI_Head, NULL);
18375    if (!SUMA_RegisterEngineListCommand ( list, ED,
18376                                          SEF_vp, (void *)SO,
18377                                          SES_SumaWidget, NULL, NOPE,
18378                                          SEI_In, Elmnt)) {
18379       fprintf (SUMA_STDERR,
18380                "Error %s: Failed in SUMA_RegisterEngineListCommand.\n",
18381                FuncName);
18382       SUMA_RETURNe;
18383    }
18384 
18385 
18386    if (!SUMA_Engine (&list)) {
18387       fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_Engine.\n", FuncName);
18388       SUMA_RETURNe;
18389    }
18390 
18391    SUMA_RETURNe;
18392 }
18393 
18394 /*!
18395    \brief sets the transparency mode of a volume/slices
18396 
18397    - expects a SUMA_MenuCallBackData * in  client_data
18398    with ado as client_data->ContID and Menubutton in client_data->callback_data
18399 */
SUMA_cb_SetATransMode(Widget widget,XtPointer client_data,XtPointer call_data)18400 void SUMA_cb_SetATransMode(Widget widget, XtPointer client_data,
18401                            XtPointer call_data)
18402 {
18403    static char FuncName[]={"SUMA_cb_SetATransMode"};
18404    DList *list = NULL;
18405    DListElmt *Elmnt = NULL;
18406    SUMA_EngineData *ED = NULL;
18407    SUMA_MenuCallBackData *datap=NULL;
18408    SUMA_ALL_DO *ado = NULL;
18409    int imenu = 0;
18410 
18411    SUMA_ENTRY;
18412 
18413    /* get the surface object that the setting belongs to */
18414    datap = (SUMA_MenuCallBackData *)client_data;
18415    ado = (SUMA_ALL_DO *)datap->ContID;
18416    imenu = (INT_CAST)datap->callback_data;
18417 
18418    switch (imenu) {
18419       case SW_SurfCont_ATransViewerDefault:
18420          imenu = SATM_ViewerDefault;
18421          break;
18422       case SW_SurfCont_Alpha:
18423          imenu = SATM_ALPHA;
18424          break;
18425       case SW_SurfCont_ATrans0:
18426          imenu = SATM_0;
18427          break;
18428       case SW_SurfCont_ATrans1:
18429          imenu = SATM_1;
18430          break;
18431       case SW_SurfCont_ATrans2:
18432          imenu = SATM_2;
18433          break;
18434       case SW_SurfCont_ATrans3:
18435          imenu = SATM_3;
18436          break;
18437       case SW_SurfCont_ATrans4:
18438          imenu = SATM_4;
18439          break;
18440       case SW_SurfCont_ATrans5:
18441          imenu = SATM_5;
18442          break;
18443       case SW_SurfCont_ATrans6:
18444          imenu = SATM_6;
18445          break;
18446       case SW_SurfCont_ATrans7:
18447          imenu = SATM_7;
18448          break;
18449       case SW_SurfCont_ATrans8:
18450          imenu = SATM_8;
18451          break;
18452       case SW_SurfCont_ATrans9:
18453          imenu = SATM_9;
18454          break;
18455       case SW_SurfCont_ATrans10:
18456          imenu = SATM_10;
18457          break;
18458       case SW_SurfCont_ATrans11:
18459          imenu = SATM_11;
18460          break;
18461       case SW_SurfCont_ATrans12:
18462          imenu = SATM_12;
18463          break;
18464       case SW_SurfCont_ATrans13:
18465          imenu = SATM_13;
18466          break;
18467       case SW_SurfCont_ATrans14:
18468          imenu = SATM_14;
18469          break;
18470       case SW_SurfCont_ATrans15:
18471          imenu = SATM_15;
18472          break;
18473       case SW_SurfCont_ATrans16:
18474          imenu = SATM_16;
18475          break;
18476       default:
18477          fprintf (SUMA_STDERR, "Error %s: Unexpected widget index.\n", FuncName);
18478          break;
18479    }
18480 
18481 
18482    /* make a call to SUMA_Engine */
18483    if (!list) list = SUMA_CreateList ();
18484    SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_Redisplay_AllVisible,
18485                                        SES_SumaWidget, NULL);
18486    ED = SUMA_InitializeEngineListData (SE_SetATransMode);
18487    Elmnt = SUMA_RegisterEngineListCommand ( list, ED,
18488                                          SEF_i, (void *)&imenu,
18489                                          SES_SumaWidget, NULL, NOPE,
18490                                          SEI_Head, NULL);
18491    if (!SUMA_RegisterEngineListCommand ( list, ED,
18492                                          SEF_vp, (void *)ado,
18493                                          SES_SumaWidget, NULL, NOPE,
18494                                          SEI_In, Elmnt)) {
18495       fprintf (SUMA_STDERR,
18496                "Error %s: Failed in SUMA_RegisterEngineListCommand.\n",
18497                FuncName);
18498       SUMA_RETURNe;
18499    }
18500 
18501 
18502    if (!SUMA_Engine (&list)) {
18503       fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_Engine.\n", FuncName);
18504       SUMA_RETURNe;
18505    }
18506 
18507    SUMA_RETURNe;
18508 }
18509 
SUMA_TransMode2TransModeMenuItem(int Mode)18510 int SUMA_TransMode2TransModeMenuItem(int Mode)
18511 {
18512    static char FuncName[]={"SUMA_TransMode2TransModeMenuItem"};
18513 
18514    SUMA_ENTRY;
18515 
18516    if ((Mode) >= SW_N_SurfCont_Trans ||
18517        (Mode) <=  SW_SurfCont_Trans) {
18518       SUMA_S_Err("Bad mode, returning 0");
18519       SUMA_RETURN(SW_SurfCont_Trans0);
18520    }
18521 
18522    SUMA_RETURN(Mode);
18523 }
18524 
SUMA_ATransMode2ATransModeMenuItem(int Mode)18525 int SUMA_ATransMode2ATransModeMenuItem(int Mode)
18526 {
18527    static char FuncName[]={"SUMA_ATransMode2ATransModeMenuItem"};
18528 
18529    SUMA_ENTRY;
18530 
18531    if ((Mode) >= SW_N_SurfCont_ATrans ||
18532        (Mode) <=  SW_SurfCont_ATrans) {
18533       SUMA_S_Err("Bad mode, returning 0");
18534       SUMA_RETURN(SW_SurfCont_ATrans0);
18535    }
18536 
18537    SUMA_RETURN(Mode);
18538 }
18539 
18540 
18541 
SUMA_ShowMode2ShowModeMenuItem(int Mode)18542 int SUMA_ShowMode2ShowModeMenuItem(int Mode)
18543 {
18544    static char FuncName[]={"SUMA_ShowMode2ShowModeMenuItem"};
18545 
18546    SUMA_ENTRY;
18547 
18548    if (SUMA_ABS(Mode) >= SW_N_SurfCont_DsetView ||
18549        SUMA_ABS(Mode) <= SW_SurfCont_DsetView ) {
18550       SUMA_S_Err("Bad mode, returning FULL");
18551       SUMA_RETURN(SW_SurfCont_DsetViewCol);
18552    }
18553    if (Mode < 0) {
18554       SUMA_RETURN(SW_SurfCont_DsetViewXXX);
18555    } else {
18556       SUMA_RETURN(Mode);
18557    }
18558 }
18559 
18560 
SUMA_ShowModeStr2ShowModeMenuItem(char * str)18561 int SUMA_ShowModeStr2ShowModeMenuItem(char *str)
18562 {
18563    static char FuncName[]={"SUMA_ShowModeStr2ShowModeMenuItem"};
18564 
18565    SUMA_ENTRY;
18566    if (!str) {
18567       SUMA_S_Err("NULL str, returning view color");
18568       SUMA_RETURN(SW_SurfCont_DsetViewCol);
18569    }
18570    if (!strcasecmp(str,"xxx"))
18571        SUMA_RETURN(SW_SurfCont_DsetViewXXX);
18572    else if (!strcasecmp(str,"col"))
18573        SUMA_RETURN(SW_SurfCont_DsetViewCol);
18574    else if (!strcasecmp(str,"con"))
18575        SUMA_RETURN(SW_SurfCont_DsetViewCon);
18576    else if (!strcasecmp(str,"c&c"))
18577        SUMA_RETURN(SW_SurfCont_DsetViewCaC);
18578    else {
18579       SUMA_S_Errv("'%s' is not a valid show mode, returning view col", str);
18580       SUMA_RETURN(SW_SurfCont_DsetViewCol);
18581    }
18582 
18583 }
18584 
SUMA_NodeRad2NodeRadMenuItem(int Mode)18585 int SUMA_NodeRad2NodeRadMenuItem(int Mode)
18586 {
18587    static char FuncName[]={"SUMA_NodeRad2NodeRadMenuItem"};
18588 
18589    SUMA_ENTRY;
18590 
18591    if (SUMA_ABS(Mode) >= SW_N_SurfCont_DsetNodeRad ||
18592        SUMA_ABS(Mode) <= SW_SurfCont_DsetNodeRad ) {
18593       SUMA_S_Err("Bad mode, returning Const");
18594       SUMA_RETURN(SW_SurfCont_DsetNodeRadConst);
18595    }
18596    if (Mode < 0) {
18597       SUMA_RETURN(SW_SurfCont_DsetNodeRadXXX);
18598    } else {
18599       SUMA_RETURN(Mode);
18600    }
18601 }
18602 
SUMA_NodeRadStr2NodeRadMenuItem(char * str)18603 int SUMA_NodeRadStr2NodeRadMenuItem(char *str)
18604 {
18605    static char FuncName[]={"SUMA_NodeRadStr2NodeRadMenuItem"};
18606 
18607    SUMA_ENTRY;
18608    if (!str) {
18609       SUMA_S_Err("NULL str, returning Const");
18610       SUMA_RETURN(SW_SurfCont_DsetNodeRadConst);
18611    }
18612    if (!strcasecmp(str,"xxx"))
18613        SUMA_RETURN(SW_SurfCont_DsetNodeRadXXX);
18614    else if (!strcasecmp(str,"cst") || !strcasecmp(str,"const"))
18615        SUMA_RETURN(SW_SurfCont_DsetNodeRadConst);
18616    else if (!strcasecmp(str,"val"))
18617        SUMA_RETURN(SW_SurfCont_DsetNodeRadVal);
18618    else {
18619       SUMA_S_Errv("'%s' is not a valid show mode, returning Const", str);
18620       SUMA_RETURN(SW_SurfCont_DsetNodeRadConst);
18621    }
18622 
18623 }
18624 
SUMA_Through2ThroughMenuItem(int Mode)18625 int SUMA_Through2ThroughMenuItem(int Mode)
18626 {
18627    static char FuncName[]={"SUMA_Through2ThroughMenuItem"};
18628 
18629    SUMA_ENTRY;
18630 
18631    if (SUMA_ABS(Mode) >= SW_N_SurfCont_DsetThrough ||
18632        SUMA_ABS(Mode) <= SW_SurfCont_DsetThrough ) {
18633       SUMA_S_Err("Bad mode, returning Edge");
18634       SUMA_RETURN(SW_SurfCont_DsetThroughEdge);
18635    }
18636    if (Mode < 0) {
18637       SUMA_RETURN(SW_SurfCont_DsetThroughXXX);
18638    } else {
18639       SUMA_RETURN(Mode);
18640    }
18641 }
18642 
SUMA_ThroughStr2ThroughMenuItem(char * str)18643 int SUMA_ThroughStr2ThroughMenuItem(char *str)
18644 {
18645    static char FuncName[]={"SUMA_ThroughStr2ThroughMenuItem"};
18646 
18647    SUMA_ENTRY;
18648    if (!str) {
18649       SUMA_S_Err("NULL str, returning Edge");
18650       SUMA_RETURN(SW_SurfCont_DsetThroughEdge);
18651    }
18652    if (!strcasecmp(str,"xxx"))
18653        SUMA_RETURN(SW_SurfCont_DsetThroughXXX);
18654    else if (!strcasecmp(str,"edg") || !strcasecmp(str,"edge"))
18655        SUMA_RETURN(SW_SurfCont_DsetThroughEdge);
18656    else if (!strcasecmp(str,"col") || !strcasecmp(str,"color"))
18657        SUMA_RETURN(SW_SurfCont_DsetThroughCol);
18658    else if (!strcasecmp(str,"rad") || !strcasecmp(str,"radius"))
18659        SUMA_RETURN(SW_SurfCont_DsetThroughRad);
18660    else if (!strcasecmp(str,"c&r"))
18661        SUMA_RETURN(SW_SurfCont_DsetThroughCaR);
18662    else {
18663       SUMA_S_Errv("'%s' is not a valid show mode, returning Edge", str);
18664       SUMA_RETURN(SW_SurfCont_DsetThroughEdge);
18665    }
18666 
18667 }
18668 
SUMA_NodeCol2NodeColMenuItem(int Mode)18669 int SUMA_NodeCol2NodeColMenuItem(int Mode)
18670 {
18671    static char FuncName[]={"SUMA_NodeCol2NodeColMenuItem"};
18672 
18673    SUMA_ENTRY;
18674 
18675    if (SUMA_ABS(Mode) >= SW_N_SurfCont_DsetNodeCol ||
18676        SUMA_ABS(Mode) <= SW_SurfCont_DsetNodeCol ) {
18677       SUMA_S_Err("Bad mode, returning Const");
18678       SUMA_RETURN(SW_SurfCont_DsetNodeColWhite);
18679    }
18680    if (Mode < 0) {
18681       SUMA_S_Err("No hide mode for color, returning Const");
18682       SUMA_RETURN(SW_SurfCont_DsetNodeColWhite);
18683    } else {
18684       SUMA_RETURN(Mode);
18685    }
18686 }
18687 
SUMA_NodeColStr2NodeColMenuItem(char * str)18688 int SUMA_NodeColStr2NodeColMenuItem(char *str)
18689 {
18690    static char FuncName[]={"SUMA_NodeColStr2NodeColMenuItem"};
18691 
18692    SUMA_ENTRY;
18693    if (!str) {
18694       SUMA_S_Err("NULL str, returning White");
18695       SUMA_RETURN(SW_SurfCont_DsetNodeColWhite);
18696    }
18697    if (!strcasecmp(str,"wht") || !strcasecmp(str,"white"))
18698        SUMA_RETURN(SW_SurfCont_DsetNodeColWhite);
18699    else if (!strcasecmp(str,"blk") || !strcasecmp(str,"black"))
18700        SUMA_RETURN(SW_SurfCont_DsetNodeColBlack);
18701    else if (!strcasecmp(str,"red"))
18702        SUMA_RETURN(SW_SurfCont_DsetNodeColRed);
18703    else if (!strcasecmp(str,"grn") || !strcasecmp(str,"green"))
18704        SUMA_RETURN(SW_SurfCont_DsetNodeColGreen);
18705    else if (!strcasecmp(str,"blu") || !strcasecmp(str,"blue"))
18706        SUMA_RETURN(SW_SurfCont_DsetNodeColBlue);
18707    else if (!strcasecmp(str,"yel") ||!strcasecmp(str,"yellow"))
18708        SUMA_RETURN(SW_SurfCont_DsetNodeColYellow);
18709    else if (!strcasecmp(str,"g50") || !strcasecmp(str,"gray50"))
18710        SUMA_RETURN(SW_SurfCont_DsetNodeColGray50);
18711    else if (!strcasecmp(str,"val"))
18712        SUMA_RETURN(SW_SurfCont_DsetNodeColVal);
18713    else if (!strcasecmp(str,"grp"))
18714        SUMA_RETURN(SW_SurfCont_DsetNodeColGrp);
18715    else {
18716       SUMA_S_Errv("'%s' is not a valid node color, returning White", str);
18717       SUMA_RETURN(SW_SurfCont_DsetNodeColWhite);
18718    }
18719 
18720 }
18721 
SUMA_NodeCol2Col(int Mode,float * here)18722 float * SUMA_NodeCol2Col(int Mode, float *here)
18723 {
18724    static char FuncName[]={"SUMA_NodeCol2Col"};
18725    static int ncall=0;
18726    static float fv[10][4];
18727 
18728    SUMA_ENTRY;
18729 
18730    if (!here) {
18731       ncall++; if (ncall > 9) ncall=0;
18732       here = fv[ncall];
18733    }
18734    here[3] = 1.0;
18735    switch (Mode){
18736       default:
18737       case SW_SurfCont_DsetNodeColWhite:
18738          here[0] = here[1] = here[2] = 1.0;
18739          break;
18740       case SW_SurfCont_DsetNodeColBlack:
18741          here[0] = here[1] = here[2] = 0.0;
18742          break;
18743       case SW_SurfCont_DsetNodeColRed:
18744          here[0] = 1.0; here[1] = here[2] = 0.0;
18745          break;
18746       case SW_SurfCont_DsetNodeColGreen:
18747          here[0] = 0.0; here[1] = 1.0; here[2] = 0.0;
18748          break;
18749       case SW_SurfCont_DsetNodeColBlue:
18750          here[0] = 0.0; here[1] = 0.0; here[2] = 1.0;
18751          break;
18752       case SW_SurfCont_DsetNodeColYellow:
18753          here[0] = 1.0; here[1] = 1.0; here[2] = 0.0;
18754          break;
18755       case SW_SurfCont_DsetNodeColGray50:
18756          here[0] = 0.5; here[1] = 0.5; here[2] = 0.5;
18757          break;
18758    }
18759 
18760    SUMA_RETURN(here);
18761 }
18762 
SUMA_Font2FontMenuItem(int Mode)18763 int SUMA_Font2FontMenuItem(int Mode)
18764 {
18765    static char FuncName[]={"SUMA_Font2FontMenuItem"};
18766 
18767    SUMA_ENTRY;
18768 
18769    if (SUMA_ABS(Mode) >= SW_N_SurfCont_DsetFont ||
18770        SUMA_ABS(Mode) <= SW_SurfCont_DsetFont ) {
18771       SUMA_S_Err("Bad mode, returning Font 9");
18772       SUMA_RETURN(SW_SurfCont_DsetFont9);
18773    }
18774    if (Mode < 0) {
18775       SUMA_RETURN(SW_SurfCont_DsetFontXXX);
18776    } else {
18777       SUMA_RETURN(Mode);
18778    }
18779 }
18780 
SUMA_Font2GLFont(int Mode)18781 void * SUMA_Font2GLFont(int Mode)
18782 {
18783    static char FuncName[]={"SUMA_Font2GLFont"};
18784 
18785    SUMA_ENTRY;
18786 
18787    if (SUMA_ABS(Mode) >= SW_N_SurfCont_DsetFont ||
18788        SUMA_ABS(Mode) <= SW_SurfCont_DsetFont ) {
18789       SUMA_S_Errv("Bad mode %d, returning Font 9", Mode);
18790       SUMA_RETURN(GLUT_BITMAP_9_BY_15);
18791    }
18792    if (Mode < 0) {
18793       SUMA_RETURN(NULL);
18794    } else {
18795       switch(Mode) {
18796          case SW_SurfCont_DsetFont8:
18797             SUMA_RETURN(GLUT_BITMAP_8_BY_13);
18798          case SW_SurfCont_DsetFont9:
18799             SUMA_RETURN(GLUT_BITMAP_9_BY_15);
18800          case SW_SurfCont_DsetFontTR10:
18801             SUMA_RETURN(GLUT_BITMAP_TIMES_ROMAN_10);
18802          case SW_SurfCont_DsetFontTR24:
18803             SUMA_RETURN(GLUT_BITMAP_TIMES_ROMAN_24);
18804          case SW_SurfCont_DsetFontHE10:
18805             SUMA_RETURN(GLUT_BITMAP_HELVETICA_10);
18806          case SW_SurfCont_DsetFontHE12:
18807             SUMA_RETURN(GLUT_BITMAP_HELVETICA_12);
18808          case SW_SurfCont_DsetFontHE18:
18809             SUMA_RETURN(GLUT_BITMAP_HELVETICA_18);
18810          default:
18811             SUMA_RETURN(GLUT_BITMAP_9_BY_15);
18812       }
18813    }
18814    SUMA_RETURN(NULL);
18815 }
18816 
SUMA_FontStr2FontMenuItem(char * str)18817 int SUMA_FontStr2FontMenuItem(char *str)
18818 {
18819    static char FuncName[]={"SUMA_FontStr2FontMenuItem"};
18820 
18821    SUMA_ENTRY;
18822    if (!str) {
18823       SUMA_S_Err("NULL str, returning Font 9");
18824       SUMA_RETURN(SW_SurfCont_DsetFont9);
18825    }
18826    if (!strcasecmp(str,"xxx"))
18827        SUMA_RETURN(SW_SurfCont_DsetFontXXX);
18828    else if (!strcasecmp(str,"8") || !strcasecmp(str,"f8"))
18829        SUMA_RETURN(SW_SurfCont_DsetFont8);
18830    else if (!strcasecmp(str,"9") || !strcasecmp(str,"f9"))
18831        SUMA_RETURN(SW_SurfCont_DsetFont9);
18832    else if (!strcasecmp(str,"T10") || !strcasecmp(str,"TR10") )
18833        SUMA_RETURN(SW_SurfCont_DsetFontTR10);
18834    else if (!strcasecmp(str,"T24") || !strcasecmp(str,"TR24"))
18835        SUMA_RETURN(SW_SurfCont_DsetFontTR24);
18836    else if (!strcasecmp(str,"H10") || !strcasecmp(str,"He10"))
18837        SUMA_RETURN(SW_SurfCont_DsetFontHE10);
18838    else if (!strcasecmp(str,"H12") || !strcasecmp(str,"He12"))
18839        SUMA_RETURN(SW_SurfCont_DsetFontHE12);
18840    else if (!strcasecmp(str,"H18") || !strcasecmp(str,"He18"))
18841        SUMA_RETURN(SW_SurfCont_DsetFontHE18);
18842    else {
18843       SUMA_S_Errv("'%s' is not a valid Font, returning Font 9", str);
18844       SUMA_RETURN(SW_SurfCont_DsetFont9);
18845    }
18846 }
18847 /*!
18848    \brief sets the dataset viewing mode of the current dset  on SO
18849 
18850 */
SUMA_SetDsetViewMode(SUMA_ALL_DO * ado,int imenu,int updatemenu)18851 int SUMA_SetDsetViewMode(SUMA_ALL_DO *ado, int imenu, int updatemenu)
18852 {
18853    static char FuncName[]={"SUMA_SetDsetViewMode"};
18854    DList *list = NULL;
18855    DListElmt *Elmnt = NULL;
18856    SUMA_EngineData *ED = NULL;
18857    SUMA_X_SurfCont *SurfCont=NULL;
18858    SUMA_OVERLAYS *curColPlane=NULL;
18859 
18860    SUMA_ENTRY;
18861 
18862    /* make a call to SUMA_Engine */
18863    if (!list) list = SUMA_CreateList ();
18864    ED = SUMA_InitializeEngineListData (SE_SetDsetViewMode);
18865    Elmnt = SUMA_RegisterEngineListCommand ( list, ED,
18866                                          SEF_i, (void *)&imenu,
18867                                          SES_SumaWidget, NULL, NOPE,
18868                                          SEI_Head, NULL);
18869    if (!SUMA_RegisterEngineListCommand ( list, ED,
18870                                          SEF_vp, (void *)ado,
18871                                          SES_SumaWidget, NULL, NOPE,
18872                                          SEI_In, Elmnt)) {
18873       fprintf (SUMA_STDERR,
18874                "Error %s: Failed in SUMA_RegisterEngineListCommand.\n",
18875                FuncName);
18876       SUMA_RETURN(NOPE);
18877    }
18878 
18879 
18880    if (!SUMA_Engine (&list)) {
18881       fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_Engine.\n", FuncName);
18882       SUMA_RETURN(NOPE);
18883    }
18884 
18885    if (updatemenu &&
18886        (SurfCont = SUMA_ADO_Cont(ado)) &&
18887        (curColPlane = SUMA_ADO_CurColPlane(ado))) {
18888       SUMA_Set_Menu_Widget( SurfCont->DsetViewModeMenu,
18889                             curColPlane->ShowMode);
18890    }
18891 
18892    SUMA_RETURN(YUP);
18893 }
18894 
18895 /*!
18896    \brief sets the dataset viewing mode of the current dset
18897 
18898    - expects a SUMA_MenuCallBackData * in  client_data
18899    with SO as client_data->ContID and Menubutton in client_data->callback_data
18900 */
SUMA_cb_SetDsetViewMode(Widget widget,XtPointer client_data,XtPointer call_data)18901 void SUMA_cb_SetDsetViewMode(Widget widget, XtPointer client_data,
18902                            XtPointer call_data)
18903 {
18904    static char FuncName[]={"SUMA_cb_SetDsetViewMode"};
18905    SUMA_MenuCallBackData *datap=NULL;
18906    SUMA_ALL_DO *ado = NULL;
18907    int imenu = 0;
18908 
18909    SUMA_ENTRY;
18910 
18911 
18912    /* get the surface object that the setting belongs to */
18913    datap = (SUMA_MenuCallBackData *)client_data;
18914    ado = (SUMA_ALL_DO *)datap->ContID;
18915    imenu = (INT_CAST)datap->callback_data;
18916 
18917    if (!SUMA_SetDsetViewMode(ado, imenu, 0)) {
18918       SUMA_S_Err("Failed to set view mode");
18919       SUMA_RETURNe;
18920    }
18921 
18922 
18923    SUMA_RETURNe;
18924 }
18925 
18926 /*!
18927    \brief sets the dataset viewing mode of the current dset  on SO
18928 
18929 */
SUMA_SetDsetFont(SUMA_ALL_DO * ado,int imenu,int updatemenu)18930 int SUMA_SetDsetFont(SUMA_ALL_DO *ado, int imenu, int updatemenu)
18931 {
18932    static char FuncName[]={"SUMA_SetDsetFont"};
18933    DList *list = NULL;
18934    DListElmt *Elmnt = NULL;
18935    SUMA_EngineData *ED = NULL;
18936    SUMA_X_SurfCont *SurfCont=NULL;
18937    SUMA_OVERLAYS *curColPlane=NULL;
18938 
18939    SUMA_ENTRY;
18940 
18941    /* make a call to SUMA_Engine */
18942    if (!list) list = SUMA_CreateList ();
18943    ED = SUMA_InitializeEngineListData (SE_SetDsetFont);
18944 
18945    Elmnt = SUMA_RegisterEngineListCommand ( list, ED,
18946                                          SEF_i, (void *)&imenu,
18947                                          SES_SumaWidget, NULL, NOPE,
18948                                          SEI_Head, NULL);
18949    if (!SUMA_RegisterEngineListCommand ( list, ED,
18950                                          SEF_vp, (void *)ado,
18951                                          SES_SumaWidget, NULL, NOPE,
18952                                          SEI_In, Elmnt)) {
18953       fprintf (SUMA_STDERR,
18954                "Error %s: Failed in SUMA_RegisterEngineListCommand.\n",
18955                FuncName);
18956       SUMA_RETURN(NOPE);
18957    }
18958 
18959 
18960    if (!SUMA_Engine (&list)) {
18961       fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_Engine.\n", FuncName);
18962       SUMA_RETURN(NOPE);
18963    }
18964 
18965    if (updatemenu &&
18966        (SurfCont = SUMA_ADO_Cont(ado)) &&
18967        (curColPlane = SUMA_ADO_CurColPlane(ado))) {
18968       SUMA_Set_Menu_Widget( SurfCont->DsetFontMenu,
18969                             curColPlane->Font);
18970    }
18971 
18972    SUMA_RETURN(YUP);
18973 }
18974 
SUMA_cb_SetDsetFont(Widget widget,XtPointer client_data,XtPointer call_data)18975 void SUMA_cb_SetDsetFont(Widget widget, XtPointer client_data,
18976                            XtPointer call_data)
18977 {
18978    static char FuncName[]={"SUMA_cb_SetDsetFont"};
18979    SUMA_MenuCallBackData *datap=NULL;
18980    SUMA_ALL_DO *ado = NULL;
18981    int imenu = 0;
18982 
18983    SUMA_ENTRY;
18984 
18985 
18986    /* get the surface object that the setting belongs to */
18987    datap = (SUMA_MenuCallBackData *)client_data;
18988    ado = (SUMA_ALL_DO *)datap->ContID;
18989    imenu = (INT_CAST)datap->callback_data;
18990 
18991    if (!SUMA_SetDsetFont(ado, imenu, 0)) {
18992       SUMA_S_Err("Failed to set view mode");
18993       SUMA_RETURNe;
18994    }
18995 
18996 
18997    SUMA_RETURNe;
18998 }
18999 
SUMA_SetDsetNodeRad(SUMA_ALL_DO * ado,int imenu,int updatemenu)19000 int SUMA_SetDsetNodeRad(SUMA_ALL_DO *ado, int imenu, int updatemenu)
19001 {
19002    static char FuncName[]={"SUMA_SetDsetNodeRad"};
19003    DList *list = NULL;
19004    DListElmt *Elmnt = NULL;
19005    SUMA_EngineData *ED = NULL;
19006    SUMA_X_SurfCont *SurfCont=NULL;
19007    SUMA_OVERLAYS *curColPlane=NULL;
19008 
19009    SUMA_ENTRY;
19010 
19011    /* make a call to SUMA_Engine */
19012    if (!list) list = SUMA_CreateList ();
19013    ED = SUMA_InitializeEngineListData (SE_SetDsetNodeRad);
19014 
19015    Elmnt = SUMA_RegisterEngineListCommand ( list, ED,
19016                                          SEF_i, (void *)&imenu,
19017                                          SES_SumaWidget, NULL, NOPE,
19018                                          SEI_Head, NULL);
19019    if (!SUMA_RegisterEngineListCommand ( list, ED,
19020                                          SEF_vp, (void *)ado,
19021                                          SES_SumaWidget, NULL, NOPE,
19022                                          SEI_In, Elmnt)) {
19023       fprintf (SUMA_STDERR,
19024                "Error %s: Failed in SUMA_RegisterEngineListCommand.\n",
19025                FuncName);
19026       SUMA_RETURN(NOPE);
19027    }
19028 
19029 
19030    if (!SUMA_Engine (&list)) {
19031       fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_Engine.\n", FuncName);
19032       SUMA_RETURN(NOPE);
19033    }
19034 
19035    if (updatemenu &&
19036        (SurfCont = SUMA_ADO_Cont(ado)) &&
19037        (curColPlane = SUMA_ADO_CurColPlane(ado))) {
19038       SUMA_Set_Menu_Widget( SurfCont->DsetNodeRadMenu,
19039                             curColPlane->NodeRad);
19040    }
19041 
19042    SUMA_RETURN(YUP);
19043 }
19044 
SUMA_cb_SetDsetNodeRad(Widget widget,XtPointer client_data,XtPointer call_data)19045 void SUMA_cb_SetDsetNodeRad(Widget widget, XtPointer client_data,
19046                            XtPointer call_data)
19047 {
19048    static char FuncName[]={"SUMA_cb_SetDsetNodeRad"};
19049    SUMA_MenuCallBackData *datap=NULL;
19050    SUMA_ALL_DO *ado = NULL;
19051    int imenu = 0;
19052 
19053    SUMA_ENTRY;
19054 
19055 
19056    /* get the  object that the setting belongs to */
19057    datap = (SUMA_MenuCallBackData *)client_data;
19058    ado = (SUMA_ALL_DO *)datap->ContID;
19059    imenu = (INT_CAST)datap->callback_data;
19060 
19061    if (!SUMA_SetDsetNodeRad(ado, imenu, 0)) {
19062       SUMA_S_Err("Failed to set view mode");
19063       SUMA_RETURNe;
19064    }
19065 
19066 
19067    SUMA_RETURNe;
19068 }
19069 
SUMA_SetDsetThrough(SUMA_ALL_DO * ado,int imenu,int updatemenu)19070 int SUMA_SetDsetThrough(SUMA_ALL_DO *ado, int imenu, int updatemenu)
19071 {
19072    static char FuncName[]={"SUMA_SetDsetThrough"};
19073    DList *list = NULL;
19074    DListElmt *Elmnt = NULL;
19075    SUMA_EngineData *ED = NULL;
19076    SUMA_X_SurfCont *SurfCont=NULL;
19077    SUMA_OVERLAYS *curColPlane=NULL;
19078 
19079    SUMA_ENTRY;
19080 
19081    /* make a call to SUMA_Engine */
19082    if (!list) list = SUMA_CreateList ();
19083    ED = SUMA_InitializeEngineListData (SE_SetDsetThrough);
19084 
19085    Elmnt = SUMA_RegisterEngineListCommand ( list, ED,
19086                                          SEF_i, (void *)&imenu,
19087                                          SES_SumaWidget, NULL, NOPE,
19088                                          SEI_Head, NULL);
19089    if (!SUMA_RegisterEngineListCommand ( list, ED,
19090                                          SEF_vp, (void *)ado,
19091                                          SES_SumaWidget, NULL, NOPE,
19092                                          SEI_In, Elmnt)) {
19093       fprintf (SUMA_STDERR,
19094                "Error %s: Failed in SUMA_RegisterEngineListCommand.\n",
19095                FuncName);
19096       SUMA_RETURN(NOPE);
19097    }
19098 
19099 
19100    if (!SUMA_Engine (&list)) {
19101       fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_Engine.\n", FuncName);
19102       SUMA_RETURN(NOPE);
19103    }
19104 
19105    if (updatemenu &&
19106        (SurfCont = SUMA_ADO_Cont(ado)) &&
19107        (curColPlane = SUMA_ADO_CurColPlane(ado))) {
19108       SUMA_Set_Menu_Widget( SurfCont->DsetThroughMenu,
19109                             curColPlane->Through);
19110    }
19111 
19112    SUMA_RETURN(YUP);
19113 }
19114 
SUMA_cb_SetDsetThrough(Widget widget,XtPointer client_data,XtPointer call_data)19115 void SUMA_cb_SetDsetThrough(Widget widget, XtPointer client_data,
19116                            XtPointer call_data)
19117 {
19118    static char FuncName[]={"SUMA_cb_SetDsetThrough"};
19119    SUMA_MenuCallBackData *datap=NULL;
19120    SUMA_ALL_DO *ado = NULL;
19121    int imenu = 0;
19122 
19123    SUMA_ENTRY;
19124 
19125 
19126    /* get the  object that the setting belongs to */
19127    datap = (SUMA_MenuCallBackData *)client_data;
19128    ado = (SUMA_ALL_DO *)datap->ContID;
19129    imenu = (INT_CAST)datap->callback_data;
19130 
19131    if (!SUMA_SetDsetThrough(ado, imenu, 0)) {
19132       SUMA_S_Err("Failed to set view mode");
19133       SUMA_RETURNe;
19134    }
19135 
19136 
19137    SUMA_RETURNe;
19138 }
19139 
SUMA_SetDsetEdgeThick(SUMA_ALL_DO * ado,int imenu,int updatemenu)19140 int SUMA_SetDsetEdgeThick(SUMA_ALL_DO *ado, int imenu, int updatemenu)
19141 {
19142    static char FuncName[]={"SUMA_SetDsetEdgeThick"};
19143    DList *list = NULL;
19144    DListElmt *Elmnt = NULL;
19145    SUMA_EngineData *ED = NULL;
19146    SUMA_X_SurfCont *SurfCont=NULL;
19147    SUMA_OVERLAYS *curColPlane=NULL;
19148 
19149    SUMA_ENTRY;
19150 
19151    /* make a call to SUMA_Engine */
19152    if (!list) list = SUMA_CreateList ();
19153    ED = SUMA_InitializeEngineListData (SE_SetDsetEdgeThick);
19154 
19155    Elmnt = SUMA_RegisterEngineListCommand ( list, ED,
19156                                          SEF_i, (void *)&imenu,
19157                                          SES_SumaWidget, NULL, NOPE,
19158                                          SEI_Head, NULL);
19159    if (!SUMA_RegisterEngineListCommand ( list, ED,
19160                                          SEF_vp, (void *)ado,
19161                                          SES_SumaWidget, NULL, NOPE,
19162                                          SEI_In, Elmnt)) {
19163       fprintf (SUMA_STDERR,
19164                "Error %s: Failed in SUMA_RegisterEngineListCommand.\n",
19165                FuncName);
19166       SUMA_RETURN(NOPE);
19167    }
19168 
19169 
19170    if (!SUMA_Engine (&list)) {
19171       fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_Engine.\n", FuncName);
19172       SUMA_RETURN(NOPE);
19173    }
19174 
19175    if (updatemenu &&
19176        (SurfCont = SUMA_ADO_Cont(ado)) &&
19177        (curColPlane = SUMA_ADO_CurColPlane(ado))) {
19178       SUMA_Set_Menu_Widget( SurfCont->DsetEdgeThickMenu,
19179                             curColPlane->EdgeThick);
19180    }
19181 
19182    SUMA_RETURN(YUP);
19183 }
19184 
SUMA_cb_SetDsetEdgeThick(Widget widget,XtPointer client_data,XtPointer call_data)19185 void SUMA_cb_SetDsetEdgeThick(Widget widget, XtPointer client_data,
19186                            XtPointer call_data)
19187 {
19188    static char FuncName[]={"SUMA_cb_SetDsetEdgeThick"};
19189    SUMA_MenuCallBackData *datap=NULL;
19190    SUMA_ALL_DO *ado = NULL;
19191    int imenu = 0;
19192 
19193    SUMA_ENTRY;
19194 
19195 
19196    /* get the  object that the setting belongs to */
19197    datap = (SUMA_MenuCallBackData *)client_data;
19198    ado = (SUMA_ALL_DO *)datap->ContID;
19199    imenu = (INT_CAST)datap->callback_data;
19200 
19201    if (!SUMA_SetDsetEdgeThick(ado, imenu, 0)) {
19202       SUMA_S_Err("Failed to set view mode");
19203       SUMA_RETURNe;
19204    }
19205 
19206 
19207    SUMA_RETURNe;
19208 }
19209 
SUMA_SetDsetAlphaVal(SUMA_ALL_DO * ado,int imenu,int updatemenu)19210 int SUMA_SetDsetAlphaVal(SUMA_ALL_DO *ado, int imenu, int updatemenu)
19211 {
19212    static char FuncName[]={"SUMA_SetDsetAlphaVal"};
19213    DList *list = NULL;
19214    DListElmt *Elmnt = NULL;
19215    SUMA_EngineData *ED = NULL;
19216    SUMA_X_SurfCont *SurfCont=NULL;
19217    SUMA_OVERLAYS *curColPlane=NULL;
19218 
19219    SUMA_ENTRY;
19220 
19221    /* make a call to SUMA_Engine */
19222    if (!list) list = SUMA_CreateList ();
19223    ED = SUMA_InitializeEngineListData (SE_SetDsetAlphaVal);
19224 
19225    Elmnt = SUMA_RegisterEngineListCommand ( list, ED,
19226                                          SEF_i, (void *)&imenu,
19227                                          SES_SumaWidget, NULL, NOPE,
19228                                          SEI_Head, NULL);
19229    if (!SUMA_RegisterEngineListCommand ( list, ED,
19230                                          SEF_vp, (void *)ado,
19231                                          SES_SumaWidget, NULL, NOPE,
19232                                          SEI_In, Elmnt)) {
19233       fprintf (SUMA_STDERR,
19234                "Error %s: Failed in SUMA_RegisterEngineListCommand.\n",
19235                FuncName);
19236       SUMA_RETURN(NOPE);
19237    }
19238 
19239 
19240    if (!SUMA_Engine (&list)) {
19241       fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_Engine.\n", FuncName);
19242       SUMA_RETURN(NOPE);
19243    }
19244 
19245    if (updatemenu &&
19246        (SurfCont = SUMA_ADO_Cont(ado)) &&
19247        (curColPlane = SUMA_ADO_CurColPlane(ado))) {
19248       SUMA_Set_Menu_Widget( SurfCont->DsetAlphaValMenu,
19249                             curColPlane->AlphaVal);
19250    }
19251 
19252    SUMA_RETURN(YUP);
19253 }
19254 
SUMA_cb_SetDsetAlphaVal(Widget widget,XtPointer client_data,XtPointer call_data)19255 void SUMA_cb_SetDsetAlphaVal(Widget widget, XtPointer client_data,
19256                            XtPointer call_data)
19257 {
19258    static char FuncName[]={"SUMA_cb_SetDsetAlphaVal"};
19259    SUMA_MenuCallBackData *datap=NULL;
19260    SUMA_ALL_DO *ado = NULL;
19261    int imenu = 0;
19262 
19263    SUMA_ENTRY;
19264 
19265 
19266    /* get the  object that the setting belongs to */
19267    datap = (SUMA_MenuCallBackData *)client_data;
19268    ado = (SUMA_ALL_DO *)datap->ContID;
19269    imenu = (INT_CAST)datap->callback_data;
19270 
19271    if (!SUMA_SetDsetAlphaVal(ado, imenu, 0)) {
19272       SUMA_S_Err("Failed to set view mode");
19273       SUMA_RETURNe;
19274    }
19275 
19276 
19277    SUMA_RETURNe;
19278 }
19279 
SUMA_SetDsetEdgeStip(SUMA_ALL_DO * ado,int imenu,int updatemenu)19280 int SUMA_SetDsetEdgeStip(SUMA_ALL_DO *ado, int imenu, int updatemenu)
19281 {
19282    static char FuncName[]={"SUMA_SetDsetEdgeStip"};
19283    DList *list = NULL;
19284    DListElmt *Elmnt = NULL;
19285    SUMA_EngineData *ED = NULL;
19286    SUMA_X_SurfCont *SurfCont=NULL;
19287    SUMA_OVERLAYS *curColPlane=NULL;
19288 
19289    SUMA_ENTRY;
19290 
19291    /* make a call to SUMA_Engine */
19292    if (!list) list = SUMA_CreateList ();
19293    ED = SUMA_InitializeEngineListData (SE_SetDsetEdgeStip);
19294 
19295    Elmnt = SUMA_RegisterEngineListCommand ( list, ED,
19296                                          SEF_i, (void *)&imenu,
19297                                          SES_SumaWidget, NULL, NOPE,
19298                                          SEI_Head, NULL);
19299    if (!SUMA_RegisterEngineListCommand ( list, ED,
19300                                          SEF_vp, (void *)ado,
19301                                          SES_SumaWidget, NULL, NOPE,
19302                                          SEI_In, Elmnt)) {
19303       fprintf (SUMA_STDERR,
19304                "Error %s: Failed in SUMA_RegisterEngineListCommand.\n",
19305                FuncName);
19306       SUMA_RETURN(NOPE);
19307    }
19308 
19309 
19310    if (!SUMA_Engine (&list)) {
19311       fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_Engine.\n", FuncName);
19312       SUMA_RETURN(NOPE);
19313    }
19314 
19315    if (updatemenu &&
19316        (SurfCont = SUMA_ADO_Cont(ado)) &&
19317        (curColPlane = SUMA_ADO_CurColPlane(ado))) {
19318       SUMA_Set_Menu_Widget( SurfCont->DsetEdgeStipMenu,
19319                             curColPlane->EdgeStip);
19320    }
19321 
19322    SUMA_RETURN(YUP);
19323 }
19324 
SUMA_cb_SetDsetEdgeStip(Widget widget,XtPointer client_data,XtPointer call_data)19325 void SUMA_cb_SetDsetEdgeStip(Widget widget, XtPointer client_data,
19326                            XtPointer call_data)
19327 {
19328    static char FuncName[]={"SUMA_cb_SetDsetEdgeStip"};
19329    SUMA_MenuCallBackData *datap=NULL;
19330    SUMA_ALL_DO *ado = NULL;
19331    int imenu = 0;
19332 
19333    SUMA_ENTRY;
19334 
19335 
19336    /* get the  object that the setting belongs to */
19337    datap = (SUMA_MenuCallBackData *)client_data;
19338    ado = (SUMA_ALL_DO *)datap->ContID;
19339    imenu = (INT_CAST)datap->callback_data;
19340 
19341    if (!SUMA_SetDsetEdgeStip(ado, imenu, 0)) {
19342       SUMA_S_Err("Failed to set view mode");
19343       SUMA_RETURNe;
19344    }
19345 
19346 
19347    SUMA_RETURNe;
19348 }
19349 
SUMA_SetTractStyle(SUMA_ALL_DO * ado,int imenu,int updatemenu)19350 int SUMA_SetTractStyle(SUMA_ALL_DO *ado, int imenu, int updatemenu)
19351 {
19352    static char FuncName[]={"SUMA_SetTractStyle"};
19353    DList *list = NULL;
19354    DListElmt *Elmnt = NULL;
19355    SUMA_EngineData *ED = NULL;
19356    SUMA_X_SurfCont *SurfCont=NULL;
19357    SUMA_OVERLAYS *curColPlane=NULL;
19358 
19359    SUMA_ENTRY;
19360 
19361    /* make a call to SUMA_Engine */
19362    if (!list) list = SUMA_CreateList ();
19363    ED = SUMA_InitializeEngineListData (SE_SetTractStyle);
19364 
19365    Elmnt = SUMA_RegisterEngineListCommand ( list, ED,
19366                                          SEF_i, (void *)&imenu,
19367                                          SES_SumaWidget, NULL, NOPE,
19368                                          SEI_Head, NULL);
19369    if (!SUMA_RegisterEngineListCommand ( list, ED,
19370                                          SEF_vp, (void *)ado,
19371                                          SES_SumaWidget, NULL, NOPE,
19372                                          SEI_In, Elmnt)) {
19373       fprintf (SUMA_STDERR,
19374                "Error %s: Failed in SUMA_RegisterEngineListCommand.\n",
19375                FuncName);
19376       SUMA_RETURN(NOPE);
19377    }
19378 
19379 
19380    if (!SUMA_Engine (&list)) {
19381       fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_Engine.\n", FuncName);
19382       SUMA_RETURN(NOPE);
19383    }
19384 
19385    if (updatemenu &&
19386        (SurfCont = SUMA_ADO_Cont(ado)) &&
19387        (curColPlane = SUMA_ADO_CurColPlane(ado))) {
19388       SUMA_Set_Menu_Widget( SurfCont->TractStyleMenu,
19389                             curColPlane->EdgeStip);
19390    }
19391 
19392    SUMA_RETURN(YUP);
19393 }
19394 
SUMA_cb_SetTractStyle(Widget widget,XtPointer client_data,XtPointer call_data)19395 void SUMA_cb_SetTractStyle(Widget widget, XtPointer client_data,
19396                            XtPointer call_data)
19397 {
19398    static char FuncName[]={"SUMA_cb_SetTractStyle"};
19399    SUMA_MenuCallBackData *datap=NULL;
19400    SUMA_ALL_DO *ado = NULL;
19401    int imenu = 0;
19402 
19403    SUMA_ENTRY;
19404 
19405 
19406    /* get the  object that the setting belongs to */
19407    datap = (SUMA_MenuCallBackData *)client_data;
19408    ado = (SUMA_ALL_DO *)datap->ContID;
19409    imenu = (INT_CAST)datap->callback_data;
19410 
19411    if (!SUMA_SetTractStyle(ado, imenu, 0)) {
19412       SUMA_S_Err("Failed to set view mode");
19413       SUMA_RETURNe;
19414    }
19415 
19416 
19417    SUMA_RETURNe;
19418 }
19419 
19420 
SUMA_SetTractMask(SUMA_ALL_DO * ado,int imenu,int updatemenu)19421 int SUMA_SetTractMask(SUMA_ALL_DO *ado, int imenu, int updatemenu)
19422 {
19423    static char FuncName[]={"SUMA_SetTractMask"};
19424    DList *list = NULL;
19425    DListElmt *Elmnt = NULL;
19426    SUMA_EngineData *ED = NULL;
19427    SUMA_TRACT_SAUX *TSaux=NULL;
19428    SUMA_X_SurfCont *SurfCont=NULL;
19429 
19430    SUMA_ENTRY;
19431 
19432    /* make a call to SUMA_Engine */
19433    if (!list) list = SUMA_CreateList ();
19434    ED = SUMA_InitializeEngineListData (SE_SetTractMask);
19435 
19436    Elmnt = SUMA_RegisterEngineListCommand ( list, ED,
19437                                          SEF_i, (void *)&imenu,
19438                                          SES_SumaWidget, NULL, NOPE,
19439                                          SEI_Head, NULL);
19440    if (!SUMA_RegisterEngineListCommand ( list, ED,
19441                                          SEF_vp, (void *)ado,
19442                                          SES_SumaWidget, NULL, NOPE,
19443                                          SEI_In, Elmnt)) {
19444       fprintf (SUMA_STDERR,
19445                "Error %s: Failed in SUMA_RegisterEngineListCommand.\n",
19446                FuncName);
19447       SUMA_RETURN(NOPE);
19448    }
19449 
19450 
19451    if (!SUMA_Engine (&list)) {
19452       fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_Engine.\n", FuncName);
19453       SUMA_RETURN(NOPE);
19454    }
19455 
19456    if (updatemenu &&
19457        (SurfCont = SUMA_ADO_Cont(ado)) &&
19458        (TSaux = SUMA_ADO_TSaux(ado))) {
19459       SUMA_Set_Menu_Widget( SurfCont->TractMaskMenu,
19460                             TSaux->TractMask);
19461    }
19462 
19463    SUMA_RETURN(YUP);
19464 }
19465 
SUMA_cb_SetTractMask(Widget widget,XtPointer client_data,XtPointer call_data)19466 void SUMA_cb_SetTractMask(Widget widget, XtPointer client_data,
19467                            XtPointer call_data)
19468 {
19469    static char FuncName[]={"SUMA_cb_SetTractMask"};
19470    SUMA_MenuCallBackData *datap=NULL;
19471    SUMA_ALL_DO *ado = NULL;
19472    int imenu = 0;
19473 
19474    SUMA_ENTRY;
19475 
19476 
19477    /* get the  object that the setting belongs to */
19478    datap = (SUMA_MenuCallBackData *)client_data;
19479    ado = (SUMA_ALL_DO *)datap->ContID;
19480    imenu = (INT_CAST)datap->callback_data;
19481 
19482    if (!SUMA_SetTractMask(ado, imenu, 0)) {
19483       SUMA_S_Err("Failed to set view mode");
19484       SUMA_RETURNe;
19485    }
19486 
19487 
19488    SUMA_RETURNe;
19489 }
19490 
SUMA_SetDsetNodeCol(SUMA_ALL_DO * ado,int imenu,int updatemenu)19491 int SUMA_SetDsetNodeCol(SUMA_ALL_DO *ado, int imenu, int updatemenu)
19492 {
19493    static char FuncName[]={"SUMA_SetDsetNodeCol"};
19494    DList *list = NULL;
19495    DListElmt *Elmnt = NULL;
19496    SUMA_EngineData *ED = NULL;
19497    SUMA_X_SurfCont *SurfCont=NULL;
19498    SUMA_OVERLAYS *curColPlane=NULL;
19499 
19500    SUMA_ENTRY;
19501 
19502    /* make a call to SUMA_Engine */
19503    if (!list) list = SUMA_CreateList ();
19504    ED = SUMA_InitializeEngineListData (SE_SetDsetNodeCol);
19505 
19506    Elmnt = SUMA_RegisterEngineListCommand ( list, ED,
19507                                          SEF_i, (void *)&imenu,
19508                                          SES_SumaWidget, NULL, NOPE,
19509                                          SEI_Head, NULL);
19510    if (!SUMA_RegisterEngineListCommand ( list, ED,
19511                                          SEF_vp, (void *)ado,
19512                                          SES_SumaWidget, NULL, NOPE,
19513                                          SEI_In, Elmnt)) {
19514       fprintf (SUMA_STDERR,
19515                "Error %s: Failed in SUMA_RegisterEngineListCommand.\n",
19516                FuncName);
19517       SUMA_RETURN(NOPE);
19518    }
19519 
19520 
19521    if (!SUMA_Engine (&list)) {
19522       fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_Engine.\n", FuncName);
19523       SUMA_RETURN(NOPE);
19524    }
19525 
19526    if (updatemenu &&
19527        (SurfCont = SUMA_ADO_Cont(ado)) &&
19528        (curColPlane = SUMA_ADO_CurColPlane(ado))) {
19529       SUMA_Set_Menu_Widget( SurfCont->DsetNodeColMenu,
19530                             curColPlane->NodeCol);
19531    }
19532 
19533    SUMA_RETURN(YUP);
19534 }
19535 
SUMA_cb_SetDsetNodeCol(Widget widget,XtPointer client_data,XtPointer call_data)19536 void SUMA_cb_SetDsetNodeCol(Widget widget, XtPointer client_data,
19537                            XtPointer call_data)
19538 {
19539    static char FuncName[]={"SUMA_cb_SetDsetNodeCol"};
19540    SUMA_MenuCallBackData *datap=NULL;
19541    SUMA_ALL_DO *ado = NULL;
19542    int imenu = 0;
19543 
19544    SUMA_ENTRY;
19545 
19546 
19547    /* get the  object that the setting belongs to */
19548    datap = (SUMA_MenuCallBackData *)client_data;
19549    ado = (SUMA_ALL_DO *)datap->ContID;
19550    imenu = (INT_CAST)datap->callback_data;
19551 
19552    if (!SUMA_SetDsetNodeCol(ado, imenu, 0)) {
19553       SUMA_S_Err("Failed to set view mode");
19554       SUMA_RETURNe;
19555    }
19556 
19557 
19558    SUMA_RETURNe;
19559 }
19560 
SUMA_SetDsetTxtShad(SUMA_ALL_DO * ado,int imenu,int updatemenu)19561 int SUMA_SetDsetTxtShad(SUMA_ALL_DO *ado, int imenu, int updatemenu)
19562 {
19563    static char FuncName[]={"SUMA_SetDsetTxtShad"};
19564    DList *list = NULL;
19565    DListElmt *Elmnt = NULL;
19566    SUMA_EngineData *ED = NULL;
19567    SUMA_X_SurfCont *SurfCont=NULL;
19568    SUMA_OVERLAYS *curColPlane=NULL;
19569 
19570    SUMA_ENTRY;
19571 
19572    /* make a call to SUMA_Engine */
19573    if (!list) list = SUMA_CreateList ();
19574    ED = SUMA_InitializeEngineListData (SE_SetDsetTxtShad);
19575 
19576    Elmnt = SUMA_RegisterEngineListCommand ( list, ED,
19577                                          SEF_i, (void *)&imenu,
19578                                          SES_SumaWidget, NULL, NOPE,
19579                                          SEI_Head, NULL);
19580    if (!SUMA_RegisterEngineListCommand ( list, ED,
19581                                          SEF_vp, (void *)ado,
19582                                          SES_SumaWidget, NULL, NOPE,
19583                                          SEI_In, Elmnt)) {
19584       fprintf (SUMA_STDERR,
19585                "Error %s: Failed in SUMA_RegisterEngineListCommand.\n",
19586                FuncName);
19587       SUMA_RETURN(NOPE);
19588    }
19589 
19590 
19591    if (!SUMA_Engine (&list)) {
19592       fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_Engine.\n", FuncName);
19593       SUMA_RETURN(NOPE);
19594    }
19595 
19596    if (updatemenu &&
19597        (SurfCont = SUMA_ADO_Cont(ado)) &&
19598        (curColPlane = SUMA_ADO_CurColPlane(ado))) {
19599       SUMA_Set_Menu_Widget( SurfCont->DsetTxtShadMenu,
19600                             curColPlane->TxtShad);
19601    }
19602 
19603    SUMA_RETURN(YUP);
19604 }
19605 
SUMA_cb_SetDsetTxtShad(Widget widget,XtPointer client_data,XtPointer call_data)19606 void SUMA_cb_SetDsetTxtShad(Widget widget, XtPointer client_data,
19607                            XtPointer call_data)
19608 {
19609    static char FuncName[]={"SUMA_cb_SetDsetTxtShad"};
19610    SUMA_MenuCallBackData *datap=NULL;
19611    SUMA_ALL_DO *ado = NULL;
19612    int imenu = 0;
19613 
19614    SUMA_ENTRY;
19615 
19616 
19617    /* get the  object that the setting belongs to */
19618    datap = (SUMA_MenuCallBackData *)client_data;
19619    ado = (SUMA_ALL_DO *)datap->ContID;
19620    imenu = (INT_CAST)datap->callback_data;
19621 
19622    if (!SUMA_SetDsetTxtShad(ado, imenu, 0)) {
19623       SUMA_S_Err("Failed to set view mode");
19624       SUMA_RETURNe;
19625    }
19626 
19627 
19628    SUMA_RETURNe;
19629 }
19630 
19631 
SUMA_SetDsetGmatBord(SUMA_ALL_DO * ado,int imenu,int updatemenu)19632 int SUMA_SetDsetGmatBord(SUMA_ALL_DO *ado, int imenu, int updatemenu)
19633 {
19634    static char FuncName[]={"SUMA_SetDsetGmatBord"};
19635    DList *list = NULL;
19636    DListElmt *Elmnt = NULL;
19637    SUMA_EngineData *ED = NULL;
19638    SUMA_X_SurfCont *SurfCont=NULL;
19639    SUMA_OVERLAYS *curColPlane=NULL;
19640 
19641    SUMA_ENTRY;
19642 
19643    /* make a call to SUMA_Engine */
19644    if (!list) list = SUMA_CreateList ();
19645    ED = SUMA_InitializeEngineListData (SE_SetDsetGmatBord);
19646 
19647    Elmnt = SUMA_RegisterEngineListCommand ( list, ED,
19648                                          SEF_i, (void *)&imenu,
19649                                          SES_SumaWidget, NULL, NOPE,
19650                                          SEI_Head, NULL);
19651    if (!SUMA_RegisterEngineListCommand ( list, ED,
19652                                          SEF_vp, (void *)ado,
19653                                          SES_SumaWidget, NULL, NOPE,
19654                                          SEI_In, Elmnt)) {
19655       fprintf (SUMA_STDERR,
19656                "Error %s: Failed in SUMA_RegisterEngineListCommand.\n",
19657                FuncName);
19658       SUMA_RETURN(NOPE);
19659    }
19660 
19661 
19662    if (!SUMA_Engine (&list)) {
19663       fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_Engine.\n", FuncName);
19664       SUMA_RETURN(NOPE);
19665    }
19666 
19667    if (updatemenu &&
19668        (SurfCont = SUMA_ADO_Cont(ado)) &&
19669        (curColPlane = SUMA_ADO_CurColPlane(ado))) {
19670       SUMA_Set_Menu_Widget( SurfCont->DsetGmatBordMenu,
19671                             curColPlane->BordFrac);
19672    }
19673 
19674    SUMA_RETURN(YUP);
19675 }
19676 
SUMA_cb_SetDsetGmatBord(Widget widget,XtPointer client_data,XtPointer call_data)19677 void SUMA_cb_SetDsetGmatBord(Widget widget, XtPointer client_data,
19678                            XtPointer call_data)
19679 {
19680    static char FuncName[]={"SUMA_cb_SetDsetGmatBord"};
19681    SUMA_MenuCallBackData *datap=NULL;
19682    SUMA_ALL_DO *ado = NULL;
19683    int imenu = 0;
19684 
19685    SUMA_ENTRY;
19686 
19687 
19688    /* get the  object that the setting belongs to */
19689    datap = (SUMA_MenuCallBackData *)client_data;
19690    ado = (SUMA_ALL_DO *)datap->ContID;
19691    imenu = (INT_CAST)datap->callback_data;
19692 
19693    if (!SUMA_SetDsetGmatBord(ado, imenu, 0)) {
19694       SUMA_S_Err("Failed to set view mode");
19695       SUMA_RETURNe;
19696    }
19697 
19698 
19699    SUMA_RETURNe;
19700 }
19701 
19702 
19703 /*!
19704    \brief pops a SUMA message
19705 */
SUMA_PopUpMessage(SUMA_MessageData * MD)19706 void SUMA_PopUpMessage (SUMA_MessageData *MD)
19707 {
19708    static char FuncName[]={"SUMA_PopUpMessage"};
19709    Widget Parent_w=NULL, wmsg = NULL;
19710    int ii;
19711    char *sf=NULL;
19712    SUMA_ENTRY;
19713 
19714    if (!SUMAg_N_SVv) {
19715       /* no graphics here, get out */
19716       SUMA_RETURNe;
19717    }
19718 
19719    /* find a decent popup message parent */
19720    ii=0;
19721    while (  (  SUMAg_SVv[ii].isShaded ||
19722                !SUMAg_SVv[ii].X->TOPLEVEL) &&
19723             (ii < SUMAg_N_SVv)) {
19724       ++ii;
19725    }
19726 
19727 
19728    if (ii < SUMAg_N_SVv)
19729       Parent_w = SUMAg_SVv[ii].X->TOPLEVEL;
19730    else {
19731       /* try again but with one that could be shaded */
19732       ii=0;
19733       while (!SUMAg_SVv[ii].X->TOPLEVEL && (ii < SUMAg_N_SVv)) {
19734          ++ii;
19735       }
19736       if (ii >= SUMAg_N_SVv) {
19737          fprintf (SUMA_STDERR,
19738             "Error %s: This should not be happening.\n", FuncName);
19739          SUMA_RETURNe;
19740       }else Parent_w = SUMAg_SVv[ii].X->TOPLEVEL;
19741    }
19742 
19743    if (MD->Action ==  SMA_LogAndPopup) {
19744       wmsg = NULL;
19745       sf = SUMA_FormatMessage (MD);
19746       switch (MD->Type) {
19747          case SMT_Notice:
19748             wmsg = MCW_popup_message(Parent_w, sf,
19749                                      MCW_USER_KILL | MCW_TIMER_KILL);
19750             break;
19751          case SMT_Warning:
19752             wmsg = MCW_popup_message(Parent_w, sf,
19753                                      MCW_USER_KILL | MCW_TIMER_KILL);
19754             break;
19755          case SMT_Error:
19756             wmsg = MCW_popup_message(Parent_w, sf,
19757                                      MCW_USER_KILL);
19758             break;
19759          case SMT_Critical:
19760             wmsg = MCW_popup_message(Parent_w, sf,
19761                                      MCW_CALLER_KILL);
19762             break;
19763          case SMT_Text:
19764             wmsg = MCW_popup_message(Parent_w, sf,
19765                                      MCW_CALLER_KILL | MCW_TIMER_KILL);
19766             break;
19767          default:
19768             break;
19769       }
19770       if (sf)SUMA_free(sf); sf = NULL;
19771       if (wmsg) {
19772          SUMA_PositionWindowRelative (wmsg, NULL, SWP_POINTER_OFF);
19773       }
19774    }
19775 
19776    SUMA_RETURNe;
19777 
19778 }
19779 
19780 /*!
19781    \brief forms the message string.
19782 */
SUMA_FormatMessage(SUMA_MessageData * MD)19783 char * SUMA_FormatMessage (SUMA_MessageData *MD)
19784 {
19785    static char FuncName[]={"SUMA_FormatMessage"};
19786    char *s=NULL;
19787 
19788    SUMA_ENTRY;
19789 
19790    s = (char *)SUMA_calloc (strlen(MD->Message)+strlen(MD->Source)+100,
19791                             sizeof(char));
19792    if (!s) {
19793       fprintf (SUMA_STDERR, "Error %s: Failed to allocate.\n", FuncName);
19794       SUMA_RETURN(NULL);
19795    }
19796    switch (MD->Type) {
19797       case SMT_Notice:
19798          sprintf(s,"Notice %s:\n%s\n", MD->Source, MD->Message);
19799          break;
19800       case SMT_Warning:
19801          sprintf(s,"Warning %s:\n%s\n", MD->Source, MD->Message);
19802          break;
19803       case SMT_Error:
19804          sprintf(s,"Error %s:\n%s\n", MD->Source, MD->Message);
19805          break;
19806       case SMT_Critical:
19807          sprintf(s,"Critical Error %s:\n%s\n", MD->Source, MD->Message);
19808          break;
19809       case SMT_Text:
19810          sprintf(s,"%s", MD->Message);
19811          break;
19812       default:
19813          sprintf(s,"BAD MESSAGE.\n");
19814          break;
19815    }
19816 
19817    SUMA_RETURN (s);
19818 }
19819 
SUMA_OpenDrawROIController(SUMA_SurfaceViewer * sv)19820 SUMA_Boolean SUMA_OpenDrawROIController(SUMA_SurfaceViewer *sv)
19821 {
19822    static char FuncName[]={"SUMA_OpenDrawROIController"};
19823    DList *list = NULL;
19824 
19825    SUMA_ENTRY;
19826 
19827    if (!sv) {
19828       sv = (void*)&SUMAg_SVv[0];
19829    }
19830    if (!sv) SUMA_RETURN(NOPE);
19831 
19832    /* register a call to open the ROI editor */
19833    if (!list) list = SUMA_CreateList ();
19834    SUMA_REGISTER_HEAD_COMMAND_NO_DATA( list,
19835                                        SE_OpenDrawROI, SES_SumaWidget,
19836                                        (void*)sv);
19837    if (!SUMA_Engine (&list)) {
19838       SUMA_RegisterMessage (SUMAg_CF->MessageList,
19839                             "Failed to open DrawROI",
19840                             FuncName, SMT_Error, SMA_LogAndPopup);
19841       SUMA_RETURN(NOPE);
19842    }
19843 
19844    SUMA_RETURN(YUP);
19845 }
19846 /*!
19847    \brief opens the DRAW ROI window
19848 
19849    - expects a SUMA_MenuCallBackData * in  client_data
19850    with sv index as client_data->ContID
19851 */
SUMA_cb_ToolsDrawROI(Widget w,XtPointer client_data,XtPointer call_data)19852 void SUMA_cb_ToolsDrawROI (Widget w, XtPointer client_data, XtPointer call_data)
19853 {
19854    static char FuncName[]={"SUMA_cb_ToolsDrawROI"};
19855    int isv;
19856    SUMA_MenuCallBackData * datap=NULL;
19857 
19858    SUMA_ENTRY;
19859 
19860    /* get the surface viewer that the command was made in */
19861    datap = (SUMA_MenuCallBackData *)client_data;
19862    isv = (INT_CAST)datap->ContID;
19863    if (isv < 0 || isv >= SUMAg_N_SVv) {
19864       SUMA_S_Err("Bad baby");
19865       SUMA_RETURNe;
19866    }
19867 
19868    SUMA_OpenDrawROIController((&SUMAg_SVv[isv]));
19869    /* Turn on Draw Mode, if it is OFF */
19870    if (!SUMAg_CF->ROI_mode) {
19871       XmToggleButtonSetState (SUMAg_CF->X->DrawROI->DrawROImode_tb,
19872                               YUP, YUP);
19873    }
19874 
19875    SUMA_RETURNe;
19876 }
19877 
19878 /*!
19879    \brief Undo an action on the stack
19880 
19881    - expects nothing
19882 */
SUMA_cb_DrawROI_Undo(Widget w,XtPointer data,XtPointer client_data)19883 void SUMA_cb_DrawROI_Undo (Widget w, XtPointer data, XtPointer client_data)
19884 {
19885    static char FuncName[]={"SUMA_cb_DrawROI_Undo"};
19886    DList *list = NULL;
19887    DListElmt *tmp=NULL;
19888    SUMA_Boolean LocalHead = NOPE;
19889 
19890    SUMA_ENTRY;
19891 
19892    if (!SUMAg_CF->X->DrawROI->curDrawnROI) SUMA_RETURNe;
19893 
19894    if (LocalHead)
19895       fprintf(SUMA_STDERR,"%s: Calling SUMA_UndoAction...\n", FuncName);
19896 
19897    if (!SUMAg_CF->X->DrawROI->curDrawnROI->StackPos) {
19898       SUMA_SLP_Err("Nothing to Undo.");
19899       SUMA_RETURNe;
19900    }
19901 
19902    tmp = SUMA_UndoAction (SUMAg_CF->X->DrawROI->curDrawnROI->ActionStack,
19903                            SUMAg_CF->X->DrawROI->curDrawnROI->StackPos);
19904    if (!tmp) {
19905       SUMA_S_Err("Failed to Undo.");
19906       SUMA_RETURNe;
19907    }else if (tmp == SUMAg_CF->X->DrawROI->curDrawnROI->StackPos) {
19908       /* reached bottom */
19909       SUMAg_CF->X->DrawROI->curDrawnROI->StackPos = NULL;
19910    }else {
19911       SUMAg_CF->X->DrawROI->curDrawnROI->StackPos = tmp;
19912    }
19913 
19914    if (dlist_size(SUMAg_CF->X->DrawROI->curDrawnROI->ROIstrokelist)) {
19915       SUMA_LH("Not empty ROIstrokelist");
19916    }else {
19917       SUMA_LH(" empty ROIstrokelist");
19918    }
19919 
19920    /* do the paint thing */
19921    /* Now update the Paint job on the ROI plane */
19922    if (!SUMA_Paint_SO_ROIplanes_w (
19923          SUMA_findSOp_inDOv(
19924               SUMAg_CF->X->DrawROI->curDrawnROI->Parent_idcode_str,
19925               SUMAg_DOv, SUMAg_N_DOv),
19926          SUMAg_DOv, SUMAg_N_DOv)) {
19927       SUMA_SLP_Err("Failed in SUMA_Paint_SO_ROIplanes_w.");
19928       SUMA_RETURNe;
19929    }
19930 
19931    /* place a call to redisplay */
19932    if (!list) list = SUMA_CreateList ();
19933    SUMA_REGISTER_TAIL_COMMAND_NO_DATA(list, SE_Redisplay_AllVisible,
19934                                        SES_Suma, NULL);
19935    if (!SUMA_Engine (&list)) {
19936       SUMA_SL_Err("Failed calling SUMA_Engine.");
19937    }
19938 
19939 
19940    SUMA_RETURNe;
19941 }
19942 
SUMA_cb_DrawROI_Redo(Widget w,XtPointer data,XtPointer client_data)19943 void SUMA_cb_DrawROI_Redo (Widget w, XtPointer data, XtPointer client_data)
19944 {
19945    static char FuncName[]={"SUMA_cb_DrawROI_Redo"};
19946    DList *list = NULL;
19947    DListElmt *tmp=NULL;
19948    SUMA_Boolean LocalHead = NOPE;
19949 
19950 
19951    SUMA_ENTRY;
19952 
19953    if (!SUMAg_CF->X->DrawROI->curDrawnROI) SUMA_RETURNe;
19954 
19955    if (LocalHead)
19956       fprintf(SUMA_STDERR,"%s: Calling SUMA_RedoAction...\n", FuncName);
19957 
19958    if (SUMAg_CF->X->DrawROI->curDrawnROI->StackPos ==
19959          dlist_tail(SUMAg_CF->X->DrawROI->curDrawnROI->ActionStack)) {
19960       SUMA_SLP_Err("Nothing to Redo.");
19961       SUMA_RETURNe;
19962    }
19963 
19964    tmp = SUMA_RedoAction (SUMAg_CF->X->DrawROI->curDrawnROI->ActionStack,
19965                            SUMAg_CF->X->DrawROI->curDrawnROI->StackPos);
19966    if (!tmp) {
19967       SUMA_S_Err("Failed to Redo.");
19968       SUMA_RETURNe;
19969    }else {
19970       SUMAg_CF->X->DrawROI->curDrawnROI->StackPos = tmp;
19971    }
19972 
19973 
19974    /* do the paint thing */
19975    /* Now update the Paint job on the ROI plane */
19976    if (!SUMA_Paint_SO_ROIplanes_w (
19977          SUMA_findSOp_inDOv(
19978                SUMAg_CF->X->DrawROI->curDrawnROI->Parent_idcode_str,
19979                SUMAg_DOv, SUMAg_N_DOv),
19980          SUMAg_DOv, SUMAg_N_DOv)) {
19981       SUMA_SLP_Err("Failed in SUMA_Paint_SO_ROIplanes_w.");
19982       SUMA_RETURNe;
19983    }
19984 
19985    /* place a call to redisplay */
19986    if (!list) list = SUMA_CreateList ();
19987    SUMA_REGISTER_TAIL_COMMAND_NO_DATA(list, SE_Redisplay_AllVisible,
19988                                       SES_Suma, NULL);
19989    if (!SUMA_Engine (&list)) {
19990       SUMA_SL_Err("Failed calling SUMA_Engine.");
19991    }
19992 
19993    SUMA_RETURNe;
19994 }
19995 
SUMA_cb_DrawROI_Join(Widget w,XtPointer data,XtPointer client_data)19996 void SUMA_cb_DrawROI_Join (Widget w, XtPointer data, XtPointer client_data)
19997 {
19998    static char FuncName[]={"SUMA_cb_DrawROI_Join"};
19999    SUMA_Boolean LocalHead = NOPE;
20000    int HeadNode=-1, TailNode=-1;
20001    float ThirdNode_v[3];
20002    SUMA_DRAWN_ROI *DrawnROI=NULL;
20003    SUMA_SurfaceObject *SO=NULL;
20004    SUMA_ROI_DATUM *ROIstroke = NULL;
20005    SUMA_ROI_ACTION_STRUCT *ROIA;
20006    DListElmt *tmpStackPos=NULL;
20007    DList *list=NULL;
20008 
20009    SUMA_ENTRY;
20010 
20011    DrawnROI = SUMAg_CF->X->DrawROI->curDrawnROI;
20012 
20013    if (!DrawnROI) {
20014       SUMA_SLP_Err ("NO ROI to close.");
20015       SUMA_RETURNe;
20016    }
20017 
20018    if (DrawnROI->DrawStatus == SUMA_ROI_Finished) {
20019       SUMA_SLP_Err ("Cannot edit Finished ROI.");
20020       SUMA_RETURNe;
20021    }
20022 
20023    if (DrawnROI->Type != SUMA_ROI_OpenPath) {
20024       SUMA_SLP_Err ("You can only close an open path.");
20025       SUMA_RETURNe;
20026    }
20027 
20028    SUMA_DRAWN_ROI_HEAD_NODE(DrawnROI,HeadNode);
20029    SUMA_DRAWN_ROI_TAIL_NODE(DrawnROI,TailNode);
20030 
20031    /* get the third node, assuming it is along the normal of the TailNode */
20032    SO = SUMA_findSOp_inDOv(DrawnROI->Parent_idcode_str, SUMAg_DOv, SUMAg_N_DOv);
20033    ThirdNode_v[0] = SO->NodeList[3*TailNode] + 20 *SO->NodeNormList[3*TailNode];
20034    ThirdNode_v[1] = SO->NodeList[3*TailNode+1] + 20 *SO->NodeNormList[3*TailNode+1];
20035    ThirdNode_v[2] = SO->NodeList[3*TailNode+2] + 20 *SO->NodeNormList[3*TailNode+2];
20036 
20037    /* No do the intersection */
20038    ROIstroke = SUMA_Surf_Plane_Intersect_ROI (SO, TailNode, HeadNode, ThirdNode_v);
20039 
20040    if (!ROIstroke) {
20041       SUMA_SLP_Err ("Failed to close path.\nTry closing with mouse.");
20042       SUMA_RETURNe;
20043    }
20044 
20045    /* what is the last node of ROIstroke ?
20046    It is possible that the returned ROIstroke
20047    was not a successful closure (a partial success), investigate*/
20048    if (LocalHead) fprintf(SUMA_STDERR, "%s: Last node of ROIstroke is %d\n", FuncName, ROIstroke->nPath[ROIstroke->N_n-1]);
20049    if (ROIstroke->nPath[ROIstroke->N_n-1] != HeadNode) {
20050       /* Can't accept partials */
20051       SUMA_SLP_Err ("Failed to close path.\nTry closing with mouse.");
20052       SUMA_RETURNe;
20053    }
20054 
20055    /* looking good, add the thing */
20056    ROIstroke->action = SUMA_BSA_JoinEnds;
20057    ROIA = (SUMA_ROI_ACTION_STRUCT *)
20058             SUMA_calloc(1,sizeof(SUMA_ROI_ACTION_STRUCT)); /* this structure is freed in SUMA_DestroyROIActionData */
20059    ROIA->DrawnROI = DrawnROI;
20060    ROIA->ROId = ROIstroke;
20061    tmpStackPos = SUMA_PushActionStack (DrawnROI->ActionStack, DrawnROI->StackPos, SUMA_AddToTailJunctionROIDatum, (void *)ROIA, SUMA_DestroyROIActionData);
20062    if (tmpStackPos) DrawnROI->StackPos = tmpStackPos;
20063    else {
20064       fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_PushActionStack.\n", FuncName);
20065       SUMA_RETURNe;
20066    }
20067 
20068    /* redisplay all others */
20069    if (!list) list = SUMA_CreateList ();
20070    SUMA_REGISTER_TAIL_COMMAND_NO_DATA(list, SE_RedisplayNow_AllVisible, SES_SumaWidget, NULL);
20071    SUMA_Engine (&list);
20072 
20073    SUMA_RETURNe;
20074 }
20075 
SUMA_cb_DrawROI_Finish(Widget w,XtPointer data,XtPointer client_data)20076 void SUMA_cb_DrawROI_Finish (Widget w, XtPointer data, XtPointer client_data)
20077 {
20078    static char FuncName[]={"SUMA_cb_DrawROI_Finish"};
20079    SUMA_Boolean LocalHead = NOPE;
20080    SUMA_DRAWN_ROI *DrawnROI=NULL;
20081    SUMA_ROI_ACTION_STRUCT *ROIA;
20082    SUMA_SurfaceObject *SO = NULL;
20083    DListElmt *tmpStackPos=NULL;
20084    DList *list=NULL;
20085 
20086    SUMA_ENTRY;
20087 
20088    DrawnROI = SUMAg_CF->X->DrawROI->curDrawnROI;
20089 
20090    if (!DrawnROI) {
20091       SUMA_SLP_Err ("NO ROI to finish.");
20092       SUMA_RETURNe;
20093    }
20094 
20095    if (DrawnROI->DrawStatus == SUMA_ROI_Finished) {
20096       /* nothing to do */
20097       SUMA_RETURNe;
20098    }
20099 
20100    /* looking good, add the thing */
20101    ROIA = (SUMA_ROI_ACTION_STRUCT *)
20102              SUMA_calloc(1,sizeof(SUMA_ROI_ACTION_STRUCT)); /* this structure is freed in SUMA_DestroyROIActionData */
20103    ROIA->DrawnROI = DrawnROI;
20104    ROIA->ROId = NULL;
20105    tmpStackPos = SUMA_PushActionStack (DrawnROI->ActionStack, DrawnROI->StackPos, SUMA_FinishedROI, (void *)ROIA, SUMA_DestroyROIActionData);
20106    if (tmpStackPos) DrawnROI->StackPos = tmpStackPos;
20107    else {
20108       fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_PushActionStack.\n", FuncName);
20109       SUMA_RETURNe;
20110    }
20111 
20112    SO = SUMA_findSOp_inDOv(DrawnROI->Parent_idcode_str, SUMAg_DOv, SUMAg_N_DOv);
20113 
20114    /* Now update the Paint job on the ROI plane */
20115    if (!SUMA_Paint_SO_ROIplanes_w (SO, SUMAg_DOv, SUMAg_N_DOv)) {
20116       SUMA_SLP_Err("Failed in SUMA_Paint_SO_ROIplanes_w.");
20117       SUMA_RETURNe;
20118    }
20119 
20120    /* redisplay all others */
20121    if (!list) list = SUMA_CreateList ();
20122    SUMA_REGISTER_TAIL_COMMAND_NO_DATA(list, SE_Redisplay_AllVisible, SES_SumaWidget, NULL);
20123    SUMA_Engine (&list);
20124 
20125    SUMA_RETURNe;
20126 }
20127 
20128 /*!
20129    \brief Delete a drawn ROI
20130 
20131 */
SUMA_cb_DrawROI_Delete(Widget wcall,XtPointer cd1,XtPointer cbs)20132 void SUMA_cb_DrawROI_Delete(Widget wcall, XtPointer cd1, XtPointer cbs)
20133 {
20134    static char *PlaneName=NULL, FuncName[] = {"SUMA_cb_DrawROI_Delete"};
20135    XmPushButtonCallbackStruct * pbcbs = (XmPushButtonCallbackStruct *) cbs ;
20136    static int ErrCnt =0;
20137    DList *list=NULL;
20138    SUMA_SurfaceObject *SO=NULL;
20139    SUMA_Boolean LocalHead = NOPE;
20140 
20141    SUMA_ENTRY;
20142 
20143    if (!SUMAg_CF->X->DrawROI->curDrawnROI && wcall) {
20144       /* remember, you'll always get the callback from the time out function
20145       the use of wcall in the condition above is to tell the difference between
20146       the timeout call and a delete request with a null curDrawnROI ...
20147       NULL curDrawnROI occurs normally such as when there are no ROI left */
20148       if (!ErrCnt) SUMA_SLP_Note ("No ROI to delete");
20149       wcall = NULL; /* use this to turn key back to lower case ahead */
20150       ErrCnt ++;
20151    }
20152 
20153    /* NULL widget --> reset button to lowercase */
20154    if( wcall == NULL ){
20155       if (LocalHead) fprintf (SUMA_STDERR, "%s: Resetting button.\n", FuncName);
20156       if( SUMAg_CF->X->DrawROI->Delete_first == NOPE ){
20157          MCW_set_widget_label( SUMAg_CF->X->DrawROI->Delete_pb , "delete ROI" ) ;
20158          SUMAg_CF->X->DrawROI->Delete_first = YUP ;
20159       }
20160       SUMA_RETURNe ;
20161    }
20162 
20163    /* First press --> just change button label */
20164 
20165    if( SUMAg_CF->X->DrawROI->Delete_first ){
20166       MCW_set_widget_label( SUMAg_CF->X->DrawROI->Delete_pb  , "DELETE ROI" ) ;
20167       SUMAg_CF->X->DrawROI->Delete_first = NOPE ;
20168 
20169       /* if not re-pressed in 5 seconds, will reset to lowercase */
20170       SUMA_LH("First Press, adding time out.");
20171       (void) XtAppAddTimeOut(
20172                XtWidgetToApplicationContext(SUMAg_CF->X->DrawROI->Delete_pb) ,
20173                5000 , SUMA_delete_timeout_CB , NULL ) ;
20174 
20175        SUMA_RETURNe;
20176    }
20177 
20178    /* delete ROI */
20179    ErrCnt = 0;
20180    SUMA_LHv("Should be deleting ROI %s here ...\n",
20181             SUMAg_CF->X->DrawROI->curDrawnROI->Label);
20182 
20183    /* preserve some info about ROI to be deleted */
20184    SO = SUMA_findSOp_inDOv(SUMAg_CF->X->DrawROI->curDrawnROI->Parent_idcode_str ,
20185                            SUMAg_DOv, SUMAg_N_DOv);
20186    PlaneName = SUMA_copy_string(SUMAg_CF->X->DrawROI->curDrawnROI->ColPlaneName);
20187 
20188    if (!SUMA_DeleteROI (SUMAg_CF->X->DrawROI->curDrawnROI)) {
20189       SUMA_SLP_Err("Failed to delete ROI");
20190       SUMA_RETURNe;
20191    }
20192 
20193    /* If no other ROIs remain on the same plane as the deleted ROI,
20194       flush that plane's colors */
20195    SUMA_FlushPlaneNotInUse (PlaneName, (SUMA_ALL_DO *)SO,
20196                             SUMAg_DOv, SUMAg_N_DOv);
20197    if (PlaneName) SUMA_free(PlaneName);
20198 
20199    /* Now update the Paint job on the ROI plane */
20200    if (!SUMA_Paint_SO_ROIplanes_w (
20201          SO, SUMAg_DOv, SUMAg_N_DOv)) {
20202       SUMA_SLP_Err("Failed in SUMA_Paint_SO_ROIplanes_w.");
20203       SUMA_RETURNe;
20204    }
20205 
20206    /* redisplay */
20207    if (!list) list = SUMA_CreateList ();
20208    SUMA_REGISTER_TAIL_COMMAND_NO_DATA(list, SE_Redisplay_AllVisible,
20209                                       SES_Suma, NULL);
20210    if (!SUMA_Engine(&list)) SUMA_SLP_Err("Failed to redisplay.");
20211 
20212    /* reset the Delete button settings */
20213    MCW_set_widget_label( SUMAg_CF->X->DrawROI->Delete_pb , "delete ROI" ) ;
20214    SUMA_RETURNe;
20215 }
20216 
SUMA_delete_timeout_CB(XtPointer client_data,XtIntervalId * id)20217 void SUMA_delete_timeout_CB( XtPointer client_data , XtIntervalId * id )
20218 {
20219    static char FuncName[] = {"SUMA_delete_timeout_CB"};
20220 
20221    SUMA_ENTRY;
20222 
20223    SUMA_cb_DrawROI_Delete(NULL, NULL, NULL);
20224 
20225    SUMA_RETURNe;
20226 }
20227 
20228 /*!
20229    \brief saving the current ROI (stored in SUMAg_CF->X->DrawROI->curDrawnROI) to a niml format
20230 */
SUMA_cb_DrawROI_Save(Widget w,XtPointer data,XtPointer client_data)20231 void SUMA_cb_DrawROI_Save (Widget w, XtPointer data, XtPointer client_data)
20232 {
20233    static char FuncName[]={"SUMA_cb_DrawROI_Save"};
20234    SUMA_DRAWN_ROI *dROI=NULL;
20235    DList *list = NULL;
20236    SUMA_EngineData *ED = NULL;
20237    DListElmt *NextElm = NULL;
20238    SUMA_Boolean LocalHead = NOPE;
20239 
20240    SUMA_ENTRY;
20241 
20242    SUMA_LH("Called");
20243 
20244    dROI = SUMAg_CF->X->DrawROI->curDrawnROI;
20245 
20246    if (!dROI) {
20247       SUMA_LH("NULL ROI");
20248       SUMA_RETURNe;
20249    }
20250 
20251    if (!list) list = SUMA_CreateList();
20252    ED = SUMA_InitializeEngineListData (SE_SaveDrawnROIFileSelection);
20253    if (!(NextElm = SUMA_RegisterEngineListCommand (  list, ED,
20254                                           SEF_vp, NULL,
20255                                           SES_Suma, NULL, NOPE,
20256                                           SEI_Head, NULL))) {
20257       fprintf (SUMA_STDERR, "Error %s: Failed to register command.\n", FuncName);
20258    }
20259    if (!SUMA_RegisterEngineListCommand (  list, ED,
20260                                           SEF_ip, (int *)w,
20261                                           SES_Suma, NULL, NOPE,
20262                                           SEI_In, NextElm)) {
20263       fprintf (SUMA_STDERR, "Error %s: Failed to register command.\n", FuncName);
20264    }
20265 
20266    if (!SUMA_Engine (&list)) {
20267       fprintf(SUMA_STDERR, "Error %s: SUMA_Engine call failed.\n", FuncName);
20268    }
20269 
20270    SUMA_RETURNe;
20271 }
20272 
SUMA_cb_DrawROI_Load(Widget w,XtPointer data,XtPointer client_data)20273 void SUMA_cb_DrawROI_Load (Widget w, XtPointer data, XtPointer client_data)
20274 {
20275    static char FuncName[]={"SUMA_cb_DrawROI_Load"};
20276    DList *list = NULL;
20277    SUMA_EngineData *ED = NULL;
20278    DListElmt *NextElm = NULL;
20279    SUMA_Boolean LocalHead = NOPE;
20280 
20281    SUMA_ENTRY;
20282 
20283    if (!list) list = SUMA_CreateList();
20284    ED = SUMA_InitializeEngineListData (SE_OpenDrawnROIFileSelection);
20285    if (!(NextElm = SUMA_RegisterEngineListCommand (  list, ED,
20286                                           SEF_vp, NULL,
20287                                           SES_Suma, NULL, NOPE,
20288                                           SEI_Head, NULL))) {
20289       fprintf (SUMA_STDERR,
20290                "Error %s: Failed to register command.\n", FuncName);
20291    }
20292    if (!SUMA_RegisterEngineListCommand (  list, ED,
20293                                           SEF_ip, (int *)w,
20294                                           SES_Suma, NULL, NOPE,
20295                                           SEI_In, NextElm)) {
20296       fprintf (SUMA_STDERR,
20297                "Error %s: Failed to register command.\n", FuncName);
20298    }
20299 
20300    if (!SUMA_Engine (&list)) {
20301       fprintf(SUMA_STDERR, "Error %s: SUMA_Engine call failed.\n", FuncName);
20302    }
20303 
20304    SUMA_RETURNe;
20305 }
20306 
SUMA_DrawROI_NewLabel(void * data)20307 void SUMA_DrawROI_NewLabel (void *data)
20308 {
20309    static char FuncName[]={"SUMA_DrawROI_NewLabel"};
20310    SUMA_DRAWN_ROI *DrawnROI=NULL;
20311    SUMA_ARROW_TEXT_FIELD * AF=NULL;
20312    void *n=NULL;
20313    static int ErrCnt=0;
20314    SUMA_Boolean Shaded = YUP;
20315    SUMA_Boolean LocalHead = NOPE;
20316 
20317    SUMA_ENTRY;
20318 
20319    AF = (SUMA_ARROW_TEXT_FIELD *)data;
20320    DrawnROI = SUMAg_CF->X->DrawROI->curDrawnROI;
20321    if (!DrawnROI) {
20322       SUMA_LH("Null DrawnROI");
20323       SUMA_RETURNe;
20324    }
20325 
20326    XtVaGetValues (AF->textfield, XmNvalue, &n, NULL);
20327    /* return if no change has been made */
20328    if (!strcmp((char *)n, DrawnROI->Label)) {
20329       SUMA_LH("No change");
20330       SUMA_RETURNe;
20331    }
20332 
20333    if (DrawnROI->DrawStatus != SUMA_ROI_Finished) {
20334       SUMA_LH("unFinished");
20335       /* YOU DO NOT WANT TO FREE n because n is not a copy of the string
20336          in the widget! */
20337       if (DrawnROI->Label) {
20338          SUMA_LH("Changing ROI label from %s to %s\n",
20339                  DrawnROI->Label, (char *)n);
20340          DrawnROI->Label = (char *)SUMA_realloc(DrawnROI->Label,
20341                                           sizeof(char)*(strlen((char *)n)+1));
20342       }  else {
20343          SUMA_LH("Setting ROI label to %s\n", (char *)n);
20344          DrawnROI->Label = (char *)SUMA_malloc(sizeof(char) *
20345                                                 (strlen((char *)n)+1));
20346       }
20347       DrawnROI->Label = strcpy(DrawnROI->Label, (char *)n);
20348       ErrCnt = 0;
20349 
20350       /* check if list window is open and update it if need be */
20351       SUMA_IS_DRAW_ROI_SWITCH_ROI_SHADED(Shaded);
20352       if (!Shaded) {
20353          SUMA_LH("updating switch ROI window ...\n");
20354          SUMA_cb_DrawROI_SwitchROI(NULL, (XtPointer)
20355                                  SUMAg_CF->X->DrawROI->SwitchROIlst, NULL);
20356       }
20357    } else {
20358       SUMA_LH("Finished");
20359       if (!ErrCnt) SUMA_SLP_Err("ROI maked as finished.\n"
20360                                 "New label cannot be applied.");
20361       ++ErrCnt;
20362       SUMA_SET_TEXT_FIELD(SUMAg_CF->X->DrawROI->ROIlbl->textfield,
20363                         DrawnROI->Label);
20364    }
20365 
20366    SUMA_RETURNe;
20367 }
20368 
20369 /*
20370 Children of New are always called with a resize if they want one.
20371 When  New is sv->X->TOPLEVEL a resize  callback is initiated on
20372 the GLXAREA with adjusted width and height values.
20373 */
SUMA_WidgetResize(Widget New,int width,int height)20374 void SUMA_WidgetResize (Widget New, int width, int height)
20375 {
20376    static char FuncName[]={"SUMA_WidgetResize"};
20377 
20378    SUMA_ENTRY;
20379 
20380    XtVaSetValues (New,
20381       XmNwidth, width,
20382       XmNheight, height,
20383       NULL);
20384    SUMA_RETURNe;
20385 }
20386 
20387 /*!
20388    \brief Positions a new widget relative to a reference widget
20389    SUMA_PositionWindowRelative ( New,  Ref,  Loc);
20390 
20391    \param New (Widget) the widget to place
20392    \param Ref (Widget) the widget relative to which New is placed (could pass NULL if positioning relative to pointer)
20393 
20394    \param Loc (SUMA_WINDOW_POSITION) the position of New relative to Ref
20395 
20396    This function is a working fallback function in case the mysterious
20397    <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0x2fa
20398    start coming back with the new function on DARWIN
20399 
20400    See SUMA_PositionWindowRelative_current()
20401 */
SUMA_PositionWindowRelative_orig(Widget New,Widget Ref,SUMA_WINDOW_POSITION Loc)20402 void SUMA_PositionWindowRelative_orig (  Widget New, Widget Ref,
20403                                     SUMA_WINDOW_POSITION Loc)
20404 {
20405    static char FuncName[]={"SUMA_PositionWindowRelative_orig"};
20406    Position RefX=0, RefY=0, NewX=0, NewY=0, Dx=5, RootX=0, RootY=0;
20407    Dimension RefW=0, RefH=0, ScrW=0, ScrH=0, NewW=0, NewH=0;
20408 
20409    SUMA_Boolean LocalHead=NOPE;
20410 
20411    SUMA_ENTRY;
20412 
20413    if (!New) { SUMA_RETURNe; }
20414 
20415    ScrW = WidthOfScreen (XtScreen(New));
20416    ScrH = HeightOfScreen (XtScreen(New));
20417 
20418    SUMA_LH("Getting New Positions");
20419    XtVaGetValues (New,           /* get the positions of New */
20420          XmNwidth, &NewW,
20421          XmNheight, &NewH,
20422          XmNx, &NewX,
20423          XmNy, &NewY,
20424          NULL);
20425 
20426    if (Ref) { /* get the positions of Ref */
20427       XtVaGetValues (Ref,
20428          XmNwidth, &RefW,
20429          XmNheight, &RefH,
20430          XmNx, &RefX,
20431          XmNy, &RefY,
20432          NULL);
20433       if (0) {
20434          /* stupid gig to figure out window manager position offsets,
20435          Does not work ..... */
20436          XtVaSetValues (Ref,  /* set the positions to where WM told you it is */
20437             XmNx, RefX+20,
20438             XmNy, RefY+12,
20439             NULL);
20440          /* Now query again */
20441          XtVaGetValues (Ref,   /* get the positions after you've just set them */
20442             XmNx, &RootX,
20443             XmNy, &RootY,
20444             NULL);
20445          SUMA_LHv( "Nothing changed.....:\n"
20446                   "Asked for: %d %d\n"
20447                   "Got      : %d %d\n",
20448                   RefX+20, RefY+12, RootX, RootY);
20449       }
20450 
20451    /* These positions do not seem to properly account for window positioning.
20452     According to documentation, XmNx and Xmny are the coordinates relative to
20453     the shell's parent window, usually the window manager's frame window.
20454     (tip from ftp://ftp.x.org/contrib/faqs/FAQ-Xt).
20455     Use XtTranslateCoords() to translate to root coordinate space. But that does
20456     not work on my mac (maybe two displays...) and that makes the problem
20457     worse. So I won't be using it. Other folksy remedies include setting
20458     some resource to False but that did nothing. There are also indications
20459     that this is a quartz problem... Will live with this for now...*/
20460       /* Get the root position*/
20461       XtTranslateCoords(Ref, RefX, RefY, &RootX, &RootY);
20462       SUMA_LHv("Got Ref Positions,  %d %d, %d %d\n"
20463                "    Root Positions, %d %d\n",
20464                   RefX, RefY, RefW, RefH,
20465                   RootX, RootY);
20466       /* RefX = RootX; RefY=RootY; Does not work, at least on macs... */
20467    } else {
20468       if (LocalHead) fprintf(SUMA_STDERR, "%s: NULL Ref.\n", FuncName);
20469       RefX = 10;
20470       RefY = 10;
20471       RefW = 0;
20472       RefH = 0;
20473    }
20474 
20475    switch (Loc) {
20476       case SWP_BOTTOM_RIGHT_CORNER:
20477          NewX = RefW + RefX;
20478          NewY = RefH + RefY;
20479          break;
20480       case SWP_TOP_RIGHT:
20481          NewX = RefW + RefX + Dx;
20482          NewY = RefY;
20483          break;
20484       case SWP_TOP_LEFT:
20485          NewX = RefW + Dx;
20486          NewY = RefY;
20487          break;
20488       case SWP_STEP_DOWN_RIGHT:
20489          NewY = RefY + 10;
20490          NewX = RefX + 10;
20491          break;
20492       case SWP_POINTER:
20493          {
20494             Window root, child, wind;
20495             int root_x, root_y, win_x, win_y, isv;
20496             unsigned int keys_buttons;
20497             SUMA_LH("Pointer Query 1");
20498             if (!XtIsRealized(New)) {
20499                SUMA_LH("Need new wind");
20500                isv = 0;
20501                while (isv < SUMAg_N_SVv &&
20502                       !XtIsRealized(SUMAg_SVv[isv].X->GLXAREA)) ++isv;
20503                if (isv < SUMAg_N_SVv) {
20504                   wind = XtWindow(SUMAg_SVv[isv].X->GLXAREA);
20505                } else {
20506                   SUMA_SL_Err("Nothing to work with here!");
20507                   SUMA_RETURNe;
20508                }
20509             } else {
20510                wind = XtWindow(New);
20511             }
20512             XQueryPointer( XtDisplay(New), wind, &root, &child,
20513                            &root_x, &root_y, &win_x, &win_y, &keys_buttons);
20514             NewX = root_x;
20515             NewY = root_y;
20516          }
20517          break;
20518       case SWP_POINTER_OFF:
20519          {
20520             Window root, child, wind;
20521             int root_x, root_y, win_x, win_y;
20522             unsigned int keys_buttons;
20523             SUMA_LH("Pointer Query 2");
20524             if (!XtIsRealized(New)) {
20525                SUMA_LH("Need new wind");
20526                if (!XtIsRealized(SUMAg_SVv[0].X->GLXAREA)) {
20527                   SUMA_SL_Err("Nothing to work with here!");
20528                   SUMA_RETURNe;
20529                }
20530                wind = XtWindow(SUMAg_SVv[0].X->GLXAREA);
20531             } else {
20532                wind = XtWindow(New);
20533             }
20534             XQueryPointer( XtDisplay(New), wind, &root, &child,
20535                            &root_x, &root_y, &win_x, &win_y, &keys_buttons);
20536             NewX = root_x - (int)NewW/2;
20537             NewY = root_y - (int)NewH + Dx;
20538          }
20539          break;
20540          case SWP_POINTER_LEFT_BOTTOM:
20541          {
20542             Window root, child, wind;
20543             int root_x, root_y, win_x, win_y;
20544             unsigned int keys_buttons;
20545             SUMA_LH("Pointer Query 2");
20546             if (!XtIsRealized(New)) {
20547                SUMA_LH("Need new wind");
20548                if (!XtIsRealized(SUMAg_SVv[0].X->GLXAREA)) {
20549                   SUMA_SL_Err("Nothing to work with here!");
20550                   SUMA_RETURNe;
20551                }
20552                wind = XtWindow(SUMAg_SVv[0].X->GLXAREA);
20553             } else {
20554                wind = XtWindow(New);
20555             }
20556             XQueryPointer( XtDisplay(New), wind, &root, &child,
20557                            &root_x, &root_y, &win_x, &win_y, &keys_buttons);
20558             NewX = root_x - (int)Dx*2;
20559             NewY = root_y - (int)NewH + Dx;
20560          }
20561          break;
20562 
20563       default:
20564          fprintf (SUMA_STDERR, "Error %s: Option not known.\n", FuncName);
20565          SUMA_RETURNe;
20566          break;
20567    }
20568 
20569 
20570    if (NewX >= ScrW || NewX < 0) NewX = 50;
20571    if (NewY >= ScrH || NewY < 0) NewY = 50;
20572 
20573    if (LocalHead) fprintf (SUMA_STDERR, "%s: Positioning window at %d %d\n", FuncName, NewX, NewY);
20574    XtVaSetValues (New,
20575       XmNx, NewX,
20576       XmNy, NewY,
20577       NULL);
20578 
20579    SUMA_RETURNe;
20580 }
20581 
20582 /*!
20583    \brief Positions a new widget relative to a reference widget
20584    SUMA_PositionWindowRelative ( New,  Ref,  Loc);
20585 
20586    \param New (Widget) the widget to place
20587    \param Ref (Widget) the widget relative to which New is placed (could pass NULL if positioning relative to pointer)
20588 
20589    \param Loc (SUMA_WINDOW_POSITION) the position of New relative to Ref
20590 */
SUMA_PositionWindowRelative_current(Widget New,Widget Ref,SUMA_WINDOW_POSITION Loc)20591 void SUMA_PositionWindowRelative_current (  Widget New, Widget Ref,
20592                                     SUMA_WINDOW_POSITION Loc)
20593 {
20594    static char FuncName[]={"SUMA_PositionWindowRelative_current"};
20595    Position RefX=0, RefY=0, NewX=0, NewY=0, Dx=5, RootX=0, RootY=0;
20596    Dimension RefW=0, RefH=0, ScrW=0, ScrH=0, NewW=0, NewH=0;
20597    Position MinOK=150;
20598    SUMA_Boolean LocalHead=NOPE;
20599 
20600    SUMA_ENTRY;
20601 
20602    if (LocalHead) {
20603       SUMA_DUMP_TRACE("Who Called SUMA_PositionWindowRelative_current");
20604    }
20605 
20606    if (!New) { SUMA_RETURNe; }
20607 
20608    ScrW = WidthOfScreen (XtScreen(New));
20609    ScrH = HeightOfScreen (XtScreen(New));
20610 
20611    SUMA_LH("Getting New Positions: screen w%d, h%d", ScrW, ScrH);
20612    XtVaGetValues (New,           /* get the positions of New */
20613          XmNwidth, &NewW,
20614          XmNheight, &NewH,
20615          XmNx, &NewX,
20616          XmNy, &NewY,
20617          NULL);
20618    /* For some reason, all the New parameters are 0 or close to 0
20619    when the  controller is open in the absence of surfaces. Not
20620    sure why that is the case yet, but going down that route might
20621    provide a clue */
20622    SUMA_LH("Current New Position: x%d, y%d, w%d, h%d", NewX, NewY, NewW, NewH);
20623 
20624    if (Ref) { /* get the positions of Ref */
20625       XtVaGetValues (Ref,
20626          XmNwidth, &RefW,
20627          XmNheight, &RefH,
20628          XmNx, &RefX,
20629          XmNy, &RefY,
20630          NULL);
20631       if (0) {
20632          /* stupid gig to figure out window manager position offsets,
20633          Does not work ..... */
20634          XtVaSetValues (Ref,  /* set the positions to where WM told you it is */
20635             XmNx, RefX+20,
20636             XmNy, RefY+12,
20637             NULL);
20638          /* Now query again */
20639          XtVaGetValues (Ref,   /* get the positions after you've just set them */
20640             XmNx, &RootX,
20641             XmNy, &RootY,
20642             NULL);
20643          SUMA_LHv( "Nothing changed.....:\n"
20644                   "Asked for: %d %d\n"
20645                   "Got      : %d %d\n",
20646                   RefX+20, RefY+12, RootX, RootY);
20647       }
20648 
20649    /* These positions do not seem to properly account for window positioning.
20650     According to documentation, XmNx and Xmny are the coordinates relative to
20651     the shell's parent window, usually the window manager's frame window.
20652     (tip from ftp://ftp.x.org/contrib/faqs/FAQ-Xt).
20653     Use XtTranslateCoords() to translate to root coordinate space. But that does
20654     not work on my mac (maybe two displays...) and that makes the problem
20655     worse. So I won't be using it. Other folksy remedies include setting
20656     some resource to False but that did nothing. There are also indications
20657     that this is a quartz problem... Will live with this for now...*/
20658       /* Get the root position*/
20659       XtTranslateCoords(Ref, RefX, RefY, &RootX, &RootY);
20660       SUMA_LHv("Got Ref Positions,  x%d y%d, W%d H%d\n"
20661                "    Root Positions, x%d y%d\n",
20662                   RefX, RefY, RefW, RefH,
20663                   RootX, RootY);
20664       /* RefX = RootX; RefY=RootY; Does not work, at least on macs... */
20665       #ifdef DARWIN
20666       if (SUMAg_CF->X->roffx == -1) {
20667          /* For some insane reason the block below causes weird errors
20668             on OSX 10.8 (and possibly older). Basically a call
20669             to  XGetWindowAttributes(SUMAg_CF->X->DPY_controller1,
20670                                XtWindow(SUMAg_SVv[0].X->GLXAREA), &wa);
20671             or variants on it generated a boat load of :
20672           kCGErrorIllegalArgument: CGSSetWindowSendExposed: Invalid window 0x8a0:
20673           and other variants.  The slew of errors ends with something like:
20674           error: xp_attach_gl_context returned: 2
20675           which triggers:
20676           Error SUMA_handleRedisplay: Failed in glXMakeCurrent.
20677                   Continuing ...
20678           SUMA_handleRedisplay (via SUMA_GL_ERRS): Looking for OpenGL errors ...
20679           GL error 1: invalid framebuffer operation
20680 
20681           This can result in messed up rendering buffers.
20682 
20683           Why this happens I have no idea but I have wasted enough of my life
20684           on this already and then some.
20685          */
20686          SUMAg_CF->X->roffx = 0;
20687          SUMAg_CF->X->roffy = 22;
20688       }
20689       #else
20690       if (SUMAg_CF->X->roffx == -1) {
20691          XWindowAttributes wa;
20692          Display *dd=NULL;
20693          Window ww;
20694          dd = XtDisplay(Ref);
20695          ww = XtWindow(Ref);
20696          if (dd && ww && XGetWindowAttributes(dd, ww, &wa)) {
20697             if (wa.y > 0) { /* I have had XGetWindowAttributes
20698                              fail at times and return 0 0 for offsets. */
20699                SUMA_LHv("Setting offsets to %d %d\n", wa.x, wa.y);
20700                SUMAg_CF->X->roffx = wa.x;
20701                SUMAg_CF->X->roffy = wa.y;
20702             } else {
20703                SUMA_LH("Failed to get reasonable offset.");
20704                SUMAg_CF->X->roffx = 0; SUMAg_CF->X->roffy = 0;
20705             }
20706          } else {
20707             SUMA_LH("Failed to get window attributes, approximating");
20708             SUMAg_CF->X->roffx = 0;
20709             SUMAg_CF->X->roffy = 22;
20710          }
20711       }
20712       #endif
20713    } else {
20714       if (LocalHead) fprintf(SUMA_STDERR, "%s: NULL Ref.\n", FuncName);
20715       RefX = 10;
20716       RefY = 10;
20717       RefW = 0;
20718       RefH = 0;
20719    }
20720 
20721    switch (Loc) {
20722       case SWP_BOTTOM_RIGHT_CORNER:
20723          NewX = RefW + RefX;
20724          NewY = RefH + RefY;
20725          break;
20726       case SWP_TOP_RIGHT:
20727          NewX = (Position)(RefW + RefX + Dx - SUMAg_CF->X->roffx);
20728          NewY = (Position)(RefY - SUMAg_CF->X->roffy);
20729          break;
20730       case SWP_TOP_LEFT:
20731          NewX = (Position)(RefW + Dx - SUMAg_CF->X->roffx);
20732          NewY = (Position)(RefY - SUMAg_CF->X->roffy);
20733          break;
20734       case SWP_TOP_BEST:
20735          /* aim for TOP_RIGHT */
20736          NewX = (Position)(RefW + RefX + Dx - SUMAg_CF->X->roffx);
20737          NewY = (Position)(RefY - SUMAg_CF->X->roffy);
20738          SUMA_LH("NewX  %d", NewX);
20739          if (NewX >= ScrW-NewW) { /* Try TOP_LEFT side with no overlap */
20740             NewX = (Position)(RefX + Dx - SUMAg_CF->X->roffx - NewW);
20741          }
20742          SUMA_LH("NewX now %d", NewX);
20743          if (NewX < 0) NewX = MinOK;
20744          if (NewY >= ScrH ) NewY = ScrH-MinOK;
20745          if (NewY < 0) NewY = MinOK;
20746          break;
20747       case SWP_STEP_DOWN_RIGHT:
20748          NewY = RefY + 10;
20749          NewX = RefX + 10;
20750          break;
20751       case SWP_POINTER:
20752          {
20753             Window root, child, wind;
20754             int root_x, root_y, win_x, win_y, isv;
20755             unsigned int keys_buttons;
20756             SUMA_LH("Pointer Query 1");
20757             if (!XtIsRealized(New)) {
20758                SUMA_LH("Need new wind");
20759                isv = 0;
20760                while (isv < SUMAg_N_SVv &&
20761                       !XtIsRealized(SUMAg_SVv[isv].X->GLXAREA)) ++isv;
20762                if (isv < SUMAg_N_SVv) {
20763                   wind = XtWindow(SUMAg_SVv[isv].X->GLXAREA);
20764                } else {
20765                   SUMA_SL_Err("Nothing to work with here!");
20766                   SUMA_RETURNe;
20767                }
20768             } else {
20769                wind = XtWindow(New);
20770             }
20771             XQueryPointer( XtDisplay(New), wind, &root, &child,
20772                            &root_x, &root_y, &win_x, &win_y, &keys_buttons);
20773             NewX = root_x;
20774             NewY = root_y;
20775          }
20776          break;
20777       case SWP_POINTER_OFF:
20778          {
20779             Window root, child, wind;
20780             int root_x, root_y, win_x, win_y;
20781             unsigned int keys_buttons;
20782             SUMA_LH("Pointer Query 2");
20783             if (!XtIsRealized(New)) {
20784                SUMA_LH("Need new wind");
20785                if (!XtIsRealized(SUMAg_SVv[0].X->GLXAREA)) {
20786                   SUMA_SL_Err("Nothing to work with here!");
20787                   SUMA_RETURNe;
20788                }
20789                wind = XtWindow(SUMAg_SVv[0].X->GLXAREA);
20790             } else {
20791                wind = XtWindow(New);
20792             }
20793             XQueryPointer( XtDisplay(New), wind, &root, &child,
20794                            &root_x, &root_y, &win_x, &win_y, &keys_buttons);
20795             NewX = root_x - (int)NewW/2;
20796             NewY = root_y - (int)NewH + Dx;
20797          }
20798          break;
20799          case SWP_POINTER_LEFT_BOTTOM:
20800          {
20801             Window root, child, wind;
20802             int root_x, root_y, win_x, win_y;
20803             unsigned int keys_buttons;
20804             SUMA_LH("Pointer Query 2");
20805             if (!XtIsRealized(New)) {
20806                SUMA_LH("Need new wind");
20807                if (!XtIsRealized(SUMAg_SVv[0].X->GLXAREA)) {
20808                   SUMA_SL_Err("Nothing to work with here!");
20809                   SUMA_RETURNe;
20810                }
20811                wind = XtWindow(SUMAg_SVv[0].X->GLXAREA);
20812             } else {
20813                wind = XtWindow(New);
20814             }
20815             XQueryPointer( XtDisplay(New), wind, &root, &child,
20816                            &root_x, &root_y, &win_x, &win_y, &keys_buttons);
20817             NewX = root_x - (int)Dx*13;
20818             NewY = root_y - (int)NewH + Dx;
20819          }
20820          break;
20821 
20822       default:
20823          fprintf (SUMA_STDERR, "Error %s: Option not known.\n", FuncName);
20824          SUMA_RETURNe;
20825          break;
20826    }
20827 
20828 
20829    if (NewX >= ScrW-MinOK) NewX = ScrW-MinOK;
20830    if (NewX < 0) NewX = MinOK;
20831    if (NewY >= ScrH ) NewY = ScrH-MinOK;
20832    if (NewY < 0) NewY = MinOK;
20833 
20834    SUMA_LH("Positioning window at %d %d\n", NewX, NewY);
20835    XtVaSetValues (New,
20836       XmNx, NewX,
20837       XmNy, NewY,
20838       NULL);
20839 
20840    SUMA_RETURNe;
20841 }
20842 
SUMA_PositionWindowRelative(Widget New,Widget Ref,SUMA_WINDOW_POSITION Loc)20843 void SUMA_PositionWindowRelative (  Widget New, Widget Ref,
20844                                     SUMA_WINDOW_POSITION Loc)
20845 {
20846    SUMA_PositionWindowRelative_current(New, Ref, Loc);
20847 }
20848 
20849 
20850 /*** Functions to follow taken from editor_dnd.c example code
20851  * Written by Paula Ferguson.
20852  * Copyright 1994, O'Reilly & Associates, Inc.
20853  * Permission to use, copy, and modify this program without
20854  * restriction is hereby granted, as long as this copyright
20855  * notice appears in each copy of the program source code.
20856  * This program is freely distributable without licensing fees and
20857  * is provided without guarantee or warrantee expressed or implied.
20858  * This program is -not- in the public domain.
20859  */
20860 
20861 /*!
20862    \brief function to allocate and initialize a prompt dialogue structure
20863 
20864    \param Mode (SUMA_PROMPT_MODE) type of action area buttons desired
20865    \param init_selection (char *) the original value to set the text_field to
20866    \param daddy (Widget) the parent widget of the dialog
20867    \param preserve (SUMA_Boolean) if YUP then do not destroy widget and structure after use
20868    \param Return_button (SUMA_PROMPT_BUTTONS) make return (enter) in the text field
20869       mimick button Return_button (usually SUMA_OK_BUTTON OR SUMA_APPLY_BUTTON)
20870    \param SelectCallback
20871    \param SelectData
20872    \param CancelCallback
20873    \param CancelData
20874    \param HelpCallback
20875    \param HelpData
20876    \param oprmpt (SUMA_PROMPT_DIALOG_STRUCT *) the structure to reuse.
20877                   Use in conjuction with preserve=YUP
20878 
20879    \sa warnings in SUMA_CreateFileSelectionDialogStruct
20880 */
SUMA_CreatePromptDialogStruct(SUMA_PROMPT_MODE Mode,char * TextFieldLabel,char * init_selection,Widget daddy,SUMA_Boolean preserve,SUMA_PROMPT_BUTTONS Return_button,void (* SelectCallback)(char * selection,void * data),void * SelectData,void (* CancelCallback)(void * data),void * CancelData,void (* HelpCallback)(void * data),void * HelpData,int (* VerifyFunction)(char * selection,void * data),void * VerifyData,SUMA_PROMPT_DIALOG_STRUCT * oprmpt)20881 SUMA_PROMPT_DIALOG_STRUCT *SUMA_CreatePromptDialogStruct (
20882       SUMA_PROMPT_MODE Mode, char *TextFieldLabel,
20883       char *init_selection,
20884       Widget daddy, SUMA_Boolean preserve,
20885       SUMA_PROMPT_BUTTONS Return_button,
20886       void(*SelectCallback)(char *selection, void *data), void *SelectData,
20887       void(*CancelCallback)(void *data), void *CancelData,
20888       void(*HelpCallback)(void *data), void *HelpData,
20889       int(*VerifyFunction)(char *selection, void *data), void *VerifyData,
20890       SUMA_PROMPT_DIALOG_STRUCT *oprmpt)
20891 {
20892    static char FuncName[]={"SUMA_CreatePromptDialogStruct"};
20893    SUMA_PROMPT_DIALOG_STRUCT *prmpt=NULL;
20894    SUMA_Boolean LocalHead = NOPE;
20895 
20896    SUMA_ENTRY;
20897 
20898    if (!oprmpt) {
20899       SUMA_LH ("New prompt structure");
20900       prmpt = (SUMA_PROMPT_DIALOG_STRUCT *)
20901                   SUMA_calloc(1,sizeof(SUMA_PROMPT_DIALOG_STRUCT));
20902       if (!prmpt) {
20903          SUMA_SLP_Crit("Failed to allocate for prmpt");
20904          SUMA_RETURN(prmpt);
20905       }
20906       prmpt->daddy = daddy;
20907       prmpt->dialog = NULL;
20908       prmpt->pane = NULL;
20909       prmpt->text_w = NULL;
20910       prmpt->Mode = Mode;
20911    } else {
20912       SUMA_LH("Refitting old prompt structure.");
20913       prmpt = oprmpt;
20914       if (!preserve) SUMA_SLP_Warn("You should not be reusing\na prmpt structure along with\nthe Preserve flag on.");
20915       if (Mode != prmpt->Mode) SUMA_SLP_Warn("You cannot be reusing\na prmpt structure and change its mode.");
20916       if (prmpt->selection) SUMA_free(prmpt->selection);
20917       if (prmpt->label) SUMA_free(prmpt->label);
20918    }
20919 
20920    prmpt->SelectCallback = SelectCallback;
20921    prmpt->SelectData = SelectData;
20922    prmpt->CancelCallback = CancelCallback;
20923    prmpt->CancelData = CancelData;
20924    prmpt->HelpCallback = HelpCallback;
20925    prmpt->HelpData = HelpData;
20926    prmpt->default_button = Return_button;
20927    prmpt->VerifyFunction = VerifyFunction;
20928    prmpt->VerifyData = VerifyData;
20929 
20930    if (init_selection) {
20931       prmpt->selection = (char *)SUMA_calloc(strlen(init_selection)+1, sizeof(char));
20932       prmpt->selection = strcpy(prmpt->selection, init_selection);
20933    }else {
20934       prmpt->selection = NULL;
20935    }
20936    if (TextFieldLabel) {
20937       prmpt->label = (char *)SUMA_calloc(strlen(TextFieldLabel)+1, sizeof(char));
20938       prmpt->label = strcpy(prmpt->label, TextFieldLabel);
20939    }else {
20940       prmpt->label = NULL;
20941    }
20942    prmpt->preserve = preserve;
20943 
20944    SUMA_RETURN(prmpt);
20945 }
20946 
20947 /*!
20948    \brief function to open a prompt
20949 */
SUMA_CreatePromptDialog(char * title_extension,SUMA_PROMPT_DIALOG_STRUCT * prmpt)20950 SUMA_PROMPT_DIALOG_STRUCT *SUMA_CreatePromptDialog(char *title_extension, SUMA_PROMPT_DIALOG_STRUCT *prmpt)
20951 {
20952    static char FuncName[]={"SUMA_CreatePromptDialog"};
20953    Widget rc;
20954    XmString string;
20955    SUMA_Boolean LocalHead = NOPE;
20956 
20957    SUMA_ENTRY;
20958 
20959    if (!prmpt->dialog) {
20960       SUMA_LH ("Creating new prompt dialog.");
20961       /* The DialogShell is the Shell for this dialog.  Set it up so
20962       * that the "Close" button in the window manager's system menu
20963       * destroys the shell (it only unmaps it by default).
20964       */
20965       prmpt->dialog= XtVaCreatePopupShell ("dialog",
20966         xmDialogShellWidgetClass, prmpt->daddy,
20967         XmNtitle,  title_extension,     /* give arbitrary title in wm */
20968         XmNdeleteResponse, XmDO_NOTHING,  /* Unmap is the default and it is the best,
20969                                              by I can't get an unmap callback for
20970                                              the stupid dialog shell.
20971                                           */
20972         NULL);
20973 
20974       /* handle the close button from window manager */
20975       XmAddWMProtocolCallback(/* make "Close" window menu work */
20976          prmpt->dialog,
20977          XmInternAtom( XtDisplay(prmpt->dialog) , "WM_DELETE_WINDOW" , False ) ,
20978          SUMA_PromptUnmap_cb, (XtPointer) prmpt) ;
20979 
20980 
20981       /* Create the paned window as a child of the dialog.  This will
20982       * contain the control area and the action area
20983       * (created by CreateActionArea() using the action_items above).
20984       */
20985       prmpt->pane = XtVaCreateWidget ("pane", xmPanedWindowWidgetClass,
20986                                       prmpt->dialog,
20987         XmNsashWidth,  1,
20988         XmNsashHeight, 1,
20989         NULL);
20990 
20991       /* create the control area which contains a
20992       * Label gadget and a TextField widget.
20993       */
20994       rc = XtVaCreateWidget ("control_area", xmRowColumnWidgetClass,
20995                              prmpt->pane, NULL);
20996       string = XmStringCreateLocalized (prmpt->label);
20997       XtVaCreateManagedWidget ("label", xmLabelWidgetClass, rc,
20998         XmNlabelString,    string,
20999         NULL);
21000       XmStringFree (string);
21001 
21002       prmpt->text_w = XtVaCreateManagedWidget ("text-field",
21003         xmTextFieldWidgetClass, rc,
21004         NULL);
21005 
21006       if (prmpt->selection) {
21007          XtVaSetValues(prmpt->text_w,
21008             XmNvalue, prmpt->selection,
21009             NULL);
21010       }
21011 
21012       /* add a callback for the return in the text-field widget */
21013       XtAddCallback (prmpt->text_w, XmNactivateCallback,
21014                      SUMA_PromptActivate_cb, (XtPointer)prmpt);
21015 
21016       /* RowColumn is full -- now manage */
21017       XtManageChild (rc);
21018 
21019 
21020       /* Now create the action area */
21021       if (!SUMA_CreatePromptActionArea (prmpt)){
21022          SUMA_SLP_Crit("Failed to create action area.");
21023          SUMA_RETURN(NULL);
21024       }
21025 
21026 
21027        XtManageChild (prmpt->actionarea);
21028        XtManageChild (prmpt->pane);
21029        XtPopup (prmpt->dialog, XtGrabNone);
21030    }else {
21031       SUMA_LH ("bringing back old prompt dialog.");
21032       XtManageChild (prmpt->dialog);
21033       /* make sure that dialog is raised to top of window stack */
21034       /*
21035          For some reason, the next line fails after opening the prompt more
21036          than twice!
21037 
21038          XMapRaised (XtDisplay (prmpt->dialog), XtWindow (XtParent (prmpt->dialog)));
21039 
21040          For some other reason, the following line works although it should be done by default
21041          when a widget is managed. ZSS May 14 03*/
21042       XtMapWidget (prmpt->dialog);
21043    }
21044 
21045    SUMA_RETURN(prmpt);
21046 }
21047 
21048 /*!
21049    \brief function to create the action area of the prompt
21050 */
21051 #define TIGHTNESS 20
SUMA_PromptButtonLabel(SUMA_PROMPT_BUTTONS code)21052 const char * SUMA_PromptButtonLabel(SUMA_PROMPT_BUTTONS code)
21053 {
21054    static char FuncName[]={"SUMA_CommandString"};
21055 
21056    SUMA_ENTRY;
21057 
21058    switch (code) {
21059       case SUMA_OK_BUTTON:
21060          SUMA_RETURN("OK");
21061       case SUMA_CLEAR_BUTTON:
21062          SUMA_RETURN("Clear");
21063       case SUMA_CANCEL_BUTTON:
21064          SUMA_RETURN("Cancel");
21065       case SUMA_HELP_BUTTON:
21066          SUMA_RETURN("Help");
21067       case SUMA_APPLY_BUTTON:
21068          SUMA_RETURN("Apply");
21069       default:
21070          SUMA_RETURN("BAD BAD BAD.");
21071    }
21072    SUMA_RETURN("This cannot be.");
21073 }
21074 
SUMA_CreatePromptActionArea(SUMA_PROMPT_DIALOG_STRUCT * prmpt)21075 SUMA_Boolean SUMA_CreatePromptActionArea (SUMA_PROMPT_DIALOG_STRUCT *prmpt)
21076 {
21077    static char FuncName[]={"SUMA_CreatePromptActionArea"};
21078    int i, num_actions;
21079    Widget widget=NULL;
21080    SUMA_Boolean DoButt[SUMA_N_PROMPT_BUTTONS];
21081    SUMA_Boolean LocalHead = NOPE;
21082 
21083    SUMA_ENTRY;
21084 
21085    SUMA_LH ("Called");
21086    /* initialize DoButt */
21087    for (i=0; i < SUMA_N_PROMPT_BUTTONS; ++i) DoButt[i]=NOPE;
21088 
21089    /* Now set the flags for building the action area */
21090    num_actions = 0;
21091    switch (prmpt->Mode) {
21092       case SUMA_OK:
21093          DoButt[SUMA_OK_BUTTON] = YUP;
21094          num_actions = 1;
21095          break;
21096       case SUMA_OK_HELP:
21097          DoButt[SUMA_OK_BUTTON] = DoButt[SUMA_HELP_BUTTON] = YUP;
21098          num_actions = 2;
21099          break;
21100       case SUMA_OK_CANCEL:
21101          DoButt[SUMA_OK_BUTTON] = DoButt[SUMA_CANCEL_BUTTON] = YUP;
21102          num_actions = 2;
21103          break;
21104       case SUMA_OK_CANCEL_HELP:
21105          DoButt[SUMA_OK_BUTTON] = DoButt[SUMA_CANCEL_BUTTON] =
21106          DoButt[SUMA_HELP_BUTTON] = YUP;
21107          num_actions = 3;
21108          break;
21109       case SUMA_OK_CLEAR_CANCEL:
21110          DoButt[SUMA_OK_BUTTON] = DoButt[SUMA_CANCEL_BUTTON] =
21111          DoButt[SUMA_CLEAR_BUTTON] = YUP;
21112          num_actions = 3;
21113          break;
21114       case SUMA_OK_CLEAR_CANCEL_HELP:
21115          DoButt[SUMA_OK_BUTTON] = DoButt[SUMA_CANCEL_BUTTON] =
21116          DoButt[SUMA_CLEAR_BUTTON] = DoButt[SUMA_HELP_BUTTON] = YUP;
21117          num_actions = 4;
21118          break;
21119       case SUMA_OK_APPLY_CANCEL:
21120          DoButt[SUMA_OK_BUTTON] = DoButt[SUMA_CANCEL_BUTTON] =
21121          DoButt[SUMA_APPLY_BUTTON] = YUP;
21122          num_actions = 3;
21123          break;
21124       case SUMA_OK_APPLY_CANCEL_HELP:
21125          DoButt[SUMA_OK_BUTTON] = DoButt[SUMA_CANCEL_BUTTON] =
21126          DoButt[SUMA_APPLY_BUTTON] = DoButt[SUMA_HELP_BUTTON] = YUP;
21127          num_actions = 4;
21128          break;
21129       case SUMA_OK_APPLY_CLEAR_CANCEL:
21130          DoButt[SUMA_OK_BUTTON] = DoButt[SUMA_CANCEL_BUTTON] =
21131          DoButt[SUMA_APPLY_BUTTON] = DoButt[SUMA_CLEAR_BUTTON] = YUP;
21132          num_actions = 4;
21133          break;
21134       case SUMA_OK_APPLY_CLEAR_CANCEL_HELP:
21135          DoButt[SUMA_OK_BUTTON] = DoButt[SUMA_CANCEL_BUTTON] =
21136          DoButt[SUMA_APPLY_BUTTON] = DoButt[SUMA_CLEAR_BUTTON] =
21137          DoButt[SUMA_HELP_BUTTON] = YUP;
21138          num_actions = 5;
21139          break;
21140       default:
21141          SUMA_SL_Err("Bad prompt mode.");
21142          SUMA_RETURN(NOPE);
21143          break;
21144    }
21145 
21146    prmpt->actionarea = XtVaCreateWidget ("action_area", xmFormWidgetClass, prmpt->pane,
21147         XmNfractionBase, TIGHTNESS*num_actions - 1,
21148         XmNleftOffset,   10,
21149         XmNrightOffset,  10,
21150         NULL);
21151 
21152    /* create the buttons */
21153    for (i=0; i< SUMA_N_PROMPT_BUTTONS; ++i) {
21154       if (DoButt[i]) {
21155          widget = XtVaCreateManagedWidget (SUMA_PromptButtonLabel(i),
21156             xmPushButtonWidgetClass, prmpt->actionarea,
21157             XmNleftAttachment,       i? XmATTACH_POSITION : XmATTACH_FORM,
21158             XmNleftPosition,         TIGHTNESS*i,
21159             XmNtopAttachment,        XmATTACH_FORM,
21160             XmNbottomAttachment,     XmATTACH_FORM,
21161             XmNrightAttachment,
21162                 i != num_actions - 1 ? XmATTACH_POSITION : XmATTACH_FORM,
21163             XmNrightPosition,        TIGHTNESS * i + (TIGHTNESS - 1),
21164             XmNshowAsDefault,        i == 0,
21165             XmNdefaultButtonShadowThickness, 1,
21166             NULL);
21167       }
21168       if (i == prmpt->default_button) {
21169          /* Set the action_area's default button  Also, set the
21170           * pane window constraint for max and min heights so this
21171           * particular pane in the PanedWindow is not resizable.
21172           */
21173          Dimension height=0, h=0;
21174          XtVaGetValues (prmpt->actionarea, XmNmarginHeight, &h, NULL);
21175          XtVaGetValues (widget, XmNheight, &height, NULL);
21176          height += 2 * h;
21177          XtVaSetValues (prmpt->actionarea,
21178              XmNdefaultButton, widget,
21179              XmNpaneMaximum,   height,
21180              XmNpaneMinimum,   height,
21181              NULL);
21182       }
21183 
21184       /* Now set the callbacks */
21185       switch (i) {
21186          case SUMA_OK_BUTTON:
21187             XtAddCallback (widget, XmNactivateCallback, SUMA_PromptOk_cb, (XtPointer)prmpt);
21188             break;
21189          case SUMA_CLEAR_BUTTON:
21190             XtAddCallback (widget, XmNactivateCallback, SUMA_PromptClear_cb, (XtPointer)prmpt);
21191             break;
21192          case SUMA_CANCEL_BUTTON:
21193             XtAddCallback (widget, XmNactivateCallback, SUMA_PromptCancel_cb, (XtPointer)prmpt);
21194             break;
21195          case SUMA_APPLY_BUTTON:
21196             XtAddCallback (widget, XmNactivateCallback, SUMA_PromptApply_cb, (XtPointer)prmpt);
21197             break;
21198          case SUMA_HELP_BUTTON:
21199             XtAddCallback (widget, XmNactivateCallback, SUMA_PromptHelp_cb, (XtPointer)prmpt);
21200             break;
21201          default:
21202             SUMA_SL_Err("Bad action area button label");
21203             break;
21204       }
21205    }
21206 
21207    SUMA_RETURN(YUP);
21208 }
21209 
21210 /*!
21211    \brief Called when prompt dialog is being unmapped.
21212    This happens when users enter a selection, hit cancel or hit the kill button on the window
21213 
21214    -expects a SUMA_PROMPT_DIALOG_STRUCT *in data
21215 
21216 */
SUMA_PromptUnmap_cb(Widget w,XtPointer data,XtPointer calldata)21217 void SUMA_PromptUnmap_cb (Widget w, XtPointer data, XtPointer calldata)
21218 {
21219    static char FuncName[]={"SUMA_PromptUnmap_cb"};
21220    SUMA_PROMPT_DIALOG_STRUCT *prmpt=NULL;
21221    SUMA_Boolean LocalHead = NOPE;
21222 
21223    SUMA_ENTRY;
21224 
21225    SUMA_LH("Called");
21226 
21227    prmpt = (SUMA_PROMPT_DIALOG_STRUCT *)data;
21228 
21229    /* if preservation is not required, kill the widget and free dlg */
21230    if (!prmpt->preserve) {
21231       if (prmpt->dialog) {
21232          SUMA_LH("Destroying prompt");
21233          XtDestroyWidget(prmpt->dialog);
21234       }else {
21235          SUMA_SL_Warn("prmpt->dialog is null.\nThis should not be.");
21236       }
21237 
21238       /* now free the structure */
21239       SUMA_FreePromptDialogStruct(prmpt);
21240 
21241    }else {
21242       SUMA_LH("Preserving prompt");
21243       XtUnmapWidget (prmpt->dialog);
21244    }
21245 
21246    SUMA_RETURNe;
21247 }
21248 
21249 /*!
21250    \brief Call from Activate button in prompt dialog
21251 
21252    -expects a SUMA_PROMPT_DIALOG_STRUCT *in data
21253 */
SUMA_PromptActivate_cb(Widget w,XtPointer data,XtPointer calldata)21254 void SUMA_PromptActivate_cb (Widget w, XtPointer data, XtPointer calldata)
21255 {
21256    static char FuncName[]={"SUMA_PromptActivate_cb"};
21257    XmAnyCallbackStruct *cbs = (XmAnyCallbackStruct *) calldata;
21258    Widget dflt = NULL;
21259    SUMA_PROMPT_DIALOG_STRUCT *prmpt=NULL;
21260    SUMA_Boolean LocalHead = NOPE;
21261 
21262    SUMA_ENTRY;
21263 
21264    SUMA_LH("Called");
21265 
21266    prmpt = (SUMA_PROMPT_DIALOG_STRUCT *)data;
21267 
21268    /* get the "default button" from the action area... */
21269     XtVaGetValues (prmpt->actionarea, XmNdefaultButton, &dflt, NULL);
21270     if (dflt) /* sanity check -- this better work */
21271         /* make the default button think it got pushed using
21272          * XtCallActionProc().  This function causes the button
21273          * to appear to be activated as if the user pressed it.
21274          */
21275         XtCallActionProc (dflt, "ArmAndActivate", cbs->event, NULL, 0);
21276 
21277 
21278    SUMA_RETURNe;
21279 }
21280 
21281 /*!
21282    \brief Call from Ok button in prompt dialog
21283 
21284    -expects a SUMA_PROMPT_DIALOG_STRUCT *in data
21285 */
SUMA_PromptOk_cb(Widget w,XtPointer data,XtPointer calldata)21286 void SUMA_PromptOk_cb (Widget w, XtPointer data, XtPointer calldata)
21287 {
21288    static char FuncName[]={"SUMA_PromptOk_cb"};
21289    SUMA_PROMPT_DIALOG_STRUCT *prmpt=NULL;
21290    SUMA_Boolean LocalHead = NOPE;
21291 
21292    SUMA_ENTRY;
21293 
21294    SUMA_LH("Called");
21295 
21296    prmpt = (SUMA_PROMPT_DIALOG_STRUCT *)data;
21297 
21298    /* apply first */
21299    SUMA_PromptApply_cb (w, data, calldata);
21300 
21301    /* close window */
21302    SUMA_PromptUnmap_cb (w, data, calldata);
21303 
21304    SUMA_RETURNe;
21305 }
21306 
21307 /*!
21308    \brief Call from Clear button in prompt dialog
21309 
21310    -expects a SUMA_PROMPT_DIALOG_STRUCT *in data
21311 */
SUMA_PromptClear_cb(Widget w,XtPointer data,XtPointer calldata)21312 void SUMA_PromptClear_cb (Widget w, XtPointer data, XtPointer calldata)
21313 {
21314    static char FuncName[]={"SUMA_PromptClear_cb"};
21315    SUMA_PROMPT_DIALOG_STRUCT *prmpt=NULL;
21316    SUMA_Boolean LocalHead = NOPE;
21317 
21318    SUMA_ENTRY;
21319 
21320    SUMA_LH("Called");
21321 
21322    prmpt = (SUMA_PROMPT_DIALOG_STRUCT *)data;
21323 
21324    XmTextFieldSetString (prmpt->text_w, "");
21325 
21326    SUMA_RETURNe;
21327 }
21328 
21329 /*!
21330    \brief Call from Apply button in prompt dialog
21331 
21332    -expects a SUMA_PROMPT_DIALOG_STRUCT *in data
21333 */
SUMA_PromptApply_cb(Widget w,XtPointer data,XtPointer calldata)21334 void SUMA_PromptApply_cb (Widget w, XtPointer data, XtPointer calldata)
21335 {
21336    static char FuncName[]={"SUMA_PromptApply_cb"};
21337    SUMA_PROMPT_DIALOG_STRUCT *prmpt=NULL;
21338    char *text=NULL;
21339    SUMA_Boolean LocalHead = NOPE;
21340 
21341    SUMA_ENTRY;
21342 
21343    SUMA_LH("Called");
21344 
21345    prmpt = (SUMA_PROMPT_DIALOG_STRUCT *)data;
21346 
21347    text = XmTextFieldGetString (prmpt->text_w);
21348 
21349    if (prmpt->selection) SUMA_free(prmpt->selection);
21350    if (text[0]) {
21351       prmpt->selection = (char *)SUMA_calloc(strlen(text)+1,sizeof(char));
21352       prmpt->selection = strcpy(prmpt->selection, text);
21353    }else {
21354       prmpt->selection = NULL;
21355    }
21356    XtFree (text);
21357 
21358    SUMA_LH("Read %s\n", prmpt->selection);
21359 
21360    /* verify the input */
21361    if (prmpt->VerifyFunction) {
21362       if (!prmpt->VerifyFunction(prmpt->selection, prmpt->VerifyData)) {
21363          SUMA_SLP_Err("Gibberish! try again.\n"
21364                       "Syntax error or wrong\n"
21365                       "number/type of arguments.\n"
21366                       "See command line for more specific errors.");
21367          SUMA_RETURNe;
21368       }
21369    }
21370 
21371    /* do your selectcallback */
21372    if (prmpt->SelectCallback) {
21373       prmpt->SelectCallback(prmpt->selection, prmpt->SelectData);
21374    }
21375 
21376 
21377    SUMA_RETURNe;
21378 }
21379 
21380 /*!
21381    \brief Call from Cancel button in prompt dialog
21382 
21383    -expects a SUMA_PROMPT_DIALOG_STRUCT *in data
21384 */
SUMA_PromptCancel_cb(Widget w,XtPointer data,XtPointer calldata)21385 void SUMA_PromptCancel_cb (Widget w, XtPointer data, XtPointer calldata)
21386 {
21387    static char FuncName[]={"SUMA_PromptCancel_cb"};
21388    SUMA_PROMPT_DIALOG_STRUCT *prmpt=NULL;
21389    SUMA_Boolean LocalHead = NOPE;
21390 
21391    SUMA_ENTRY;
21392 
21393    SUMA_LH("Called");
21394 
21395    prmpt = (SUMA_PROMPT_DIALOG_STRUCT *)data;
21396 
21397    /* do your cancelcallback */
21398    if (prmpt->CancelCallback) {
21399       prmpt->CancelCallback (prmpt->CancelData);
21400    }
21401 
21402    /* close window */
21403    SUMA_PromptUnmap_cb (w, data, calldata);
21404 
21405    SUMA_RETURNe;
21406 }
21407 
21408 /*!
21409    \brief Call from Help button in prompt dialog
21410 
21411    -expects a SUMA_PROMPT_DIALOG_STRUCT *in data
21412 */
SUMA_PromptHelp_cb(Widget w,XtPointer data,XtPointer calldata)21413 void SUMA_PromptHelp_cb (Widget w, XtPointer data, XtPointer calldata)
21414 {
21415    static char FuncName[]={"SUMA_PromptHelp_cb"};
21416    SUMA_PROMPT_DIALOG_STRUCT *prmpt=NULL;
21417    SUMA_Boolean LocalHead = NOPE;
21418 
21419    SUMA_ENTRY;
21420 
21421    SUMA_LH("Called");
21422 
21423    prmpt = (SUMA_PROMPT_DIALOG_STRUCT *)data;
21424 
21425    /* do your helpcallback */
21426    if (prmpt->HelpCallback) {
21427       prmpt->HelpCallback (prmpt->HelpData);
21428    }
21429 
21430    SUMA_RETURNe;
21431 }
21432 
21433 /*!
21434    \brief frees prompt dialog structure.
21435    It does not destroy the widget for the dialog, that should be done
21436    before this function is called.
21437 
21438 */
SUMA_FreePromptDialogStruct(SUMA_PROMPT_DIALOG_STRUCT * prmpt)21439 void SUMA_FreePromptDialogStruct(SUMA_PROMPT_DIALOG_STRUCT *prmpt)
21440 {
21441    static char FuncName[]={"SUMA_FreePromptDialogStruct"};
21442    SUMA_Boolean LocalHead = NOPE;
21443 
21444    SUMA_ENTRY;
21445    SUMA_LH("Called");
21446 
21447    if (!prmpt) SUMA_RETURNe;
21448 
21449    /* now free structure */
21450    if (prmpt->selection) SUMA_free(prmpt->selection);
21451    if (prmpt->label) SUMA_free(prmpt->label);
21452    SUMA_free(prmpt);
21453 
21454    SUMA_RETURNe;
21455 }
21456 
21457 /*!
21458    \brief function to allocate and initialize a file selection dialogue structure
21459 
21460    \param parent (Widget) parent widget of dialog
21461    \param Mode (SUMA_FILE_SELECT_MODE) : SUMA_OPEN_FILE, SUMA_SAVE_FILE
21462    \param preserve (SUMA_Boolean) YUP: keep dialog widget and structure after closing.
21463                                     see notes in structure's definition for more help.
21464    \param SelectCallback(char *filename, void *data) (void*): Function to call when selection is made
21465    \param SelectData (void *) data to pass SelectCallback
21466    \param CancelCallback(void *data) (void*): Function to call when cancel is pressed
21467    \param CancelData (void *) data to pass CancelCallback
21468    \param FilePattern (char *) pattern to use as initial file filter.
21469             FilePattern is copied so you should handle freeing it if necessary.
21470             If FilePattern = NULL then the one that was used last is preserved.
21471    \param odlg (SUMA_SELECTION_DIALOG_STRUCT *) if not null, then instead of
21472             creating a new structure, the function will update the fields in
21473             odlg. This is useful if you want to reuse a dialog's widget (preserve = YUP)
21474             but with different callbacks and calldata.
21475             NOTE: parent cannot be changed if you are updating odlg.
21476             NOTE: DO NOT USE preserve = YUP along with non-NULL odlg. It does not make sense
21477             and I can't easily make this fool proof.
21478    \return dlg_strct (SUMA_SELECTION_DIALOG_STRUCT *) an allocated and initialized dialogue struct
21479                or an updated odlg if specified.
21480 
21481    -You might have to add a trap for the kill button, if possible, else you need to trap for the kill with
21482    a callback to set the widget to null.
21483 
21484    See SUMA_DestroyTextShell
21485 */
SUMA_CreateFileSelectionDialogStruct(Widget daddy,SUMA_FILE_SELECT_MODE Mode,SUMA_Boolean preserve,void (* SelectCallback)(char * filename,void * data),void * SelectData,void (* CancelCallback)(void * data),void * CancelData,char * FilePattern,SUMA_SELECTION_DIALOG_STRUCT * odlg)21486 SUMA_SELECTION_DIALOG_STRUCT *SUMA_CreateFileSelectionDialogStruct (
21487    Widget daddy,
21488    SUMA_FILE_SELECT_MODE Mode,
21489    SUMA_Boolean preserve,
21490    void (*SelectCallback)(char *filename, void *data),
21491    void *SelectData,
21492    void (*CancelCallback)(void *data),
21493    void *CancelData,
21494    char *FilePattern,
21495    SUMA_SELECTION_DIALOG_STRUCT *odlg)
21496 {
21497    static char FuncName[]={"SUMA_CreateFileSelectionDialogStruct"};
21498    SUMA_SELECTION_DIALOG_STRUCT * dlg = NULL;
21499    SUMA_Boolean LocalHead = NOPE;
21500 
21501    SUMA_ENTRY;
21502 
21503    if (!odlg) { /* new structure */
21504       SUMA_LH("A new structure ");
21505       dlg = (SUMA_SELECTION_DIALOG_STRUCT *)
21506                   SUMA_calloc(1,sizeof(SUMA_SELECTION_DIALOG_STRUCT));
21507       if (!dlg) {
21508          fprintf (SUMA_STDERR,
21509                   "Error %s: Failed to allocate for TextShell.\n",
21510                   FuncName);
21511          SUMA_RETURN (NULL);
21512       }
21513       dlg->dlg_w = NULL;
21514       dlg->FilePattern = NULL;
21515    }else {
21516       SUMA_LH("Refitting old one. ");
21517       if (!preserve)
21518          SUMA_SLP_Warn( "You should not be reusing\n"
21519                         "a dlg structure along with\n"
21520                         "the Preserve flag on.");
21521       dlg = odlg;
21522       if (dlg->filename) {
21523          SUMA_LH("Freeing dlg->filename");
21524          SUMA_free(dlg->filename);
21525       }
21526    }
21527 
21528    dlg->daddy = daddy;
21529    dlg->filename = NULL;
21530    dlg->Mode = Mode;
21531    dlg->SelectCallback = SelectCallback;
21532    dlg->SelectData = SelectData;
21533    dlg->CancelCallback = CancelCallback;
21534    dlg->CancelData = CancelData;
21535    dlg->preserve = preserve;
21536 
21537    if (FilePattern) {
21538       /* new one specified, destroy the old one */
21539       if (dlg->FilePattern) {
21540          SUMA_LHv("Reseting dlg->FilePattern to %s\n", FilePattern);
21541          SUMA_free(dlg->FilePattern);
21542       }
21543       dlg->FilePattern = SUMA_copy_string (FilePattern);
21544    }
21545 
21546    SUMA_RETURN(dlg);
21547 }
21548 
21549 /*!
21550    \brief, opens a file selection dialogue
21551 
21552    \param title (char *) title of window
21553    \param dlg (SUMA_SELECTION_DIALOG_STRUCT **) pointer to structure created and initialized by SUMA_CreateFileSelectionDialogStruct
21554 */
SUMA_CreateFileSelectionDialog(char * title_extension,SUMA_SELECTION_DIALOG_STRUCT ** dlgp)21555 SUMA_SELECTION_DIALOG_STRUCT *SUMA_CreateFileSelectionDialog (
21556       char *title_extension,
21557       SUMA_SELECTION_DIALOG_STRUCT **dlgp)
21558 {
21559    static char FuncName[]={"SUMA_CreateFileSelectionDialog"};
21560    static char *last_title_extension=NULL;
21561    SUMA_Boolean LocalHead = NOPE, same;
21562    SUMA_SELECTION_DIALOG_STRUCT *dlg = NULL;
21563    XmString button, title, pattern=NULL;
21564 
21565    SUMA_ENTRY;
21566 
21567    dlg = *dlgp;
21568    if (!dlg->dlg_w) {/* need to create it for the first time */
21569       SUMA_LH ("Creating new file selection window.");
21570       dlg->dlg_w = XmCreateFileSelectionDialog (dlg->daddy, "Files", NULL, 0);
21571 
21572 
21573       XtVaSetValues (dlg->dlg_w,
21574          XmNdeleteResponse, XmUNMAP,  /* system menu "Close" action */
21575         NULL);
21576 
21577       /* you can't cancel the kill button's effect,
21578       the way you do for toplevel shells.
21579       But it does appear that the kill button is just
21580       unmanaging the widget, which is fine.
21581       see my modified action_area.c file
21582       */
21583    } else {
21584       SUMA_LH ("Updating");
21585       /* update and raise dialogue,
21586         that is done next.
21587         For the moment, remove pre-existing callbacks*/
21588       XtRemoveAllCallbacks (dlg->dlg_w, XmNcancelCallback);
21589       XtRemoveAllCallbacks (dlg->dlg_w, XmNokCallback);
21590       XtRemoveAllCallbacks (dlg->dlg_w, XmNunmapCallback);
21591    }
21592 
21593    same = NOPE;
21594    if (title_extension) {
21595       if (last_title_extension) {
21596    SUMA_LHv("last: %s, this: %s\n", last_title_extension, title_extension);
21597          if (strcmp(last_title_extension, title_extension) == 0)
21598             { same = YUP; }
21599          SUMA_free(last_title_extension); last_title_extension=NULL;
21600       }
21601       last_title_extension = SUMA_copy_string( title_extension);
21602    }
21603    if (dlg->FilePattern ) {
21604       if (!same) {
21605          pattern = XmStringCreateLocalized (dlg->FilePattern);
21606          XtVaSetValues (dlg->dlg_w,
21607             XmNpattern, pattern,
21608             NULL);
21609          XmStringFree (pattern);
21610       } else {
21611          XtVaGetValues(dlg->dlg_w, XmNpattern, &pattern, NULL);
21612          if (pattern) {
21613             XmFileSelectionDoSearch(dlg->dlg_w, pattern);
21614             XmStringFree (pattern);
21615          }
21616       }
21617    }
21618 
21619    XtAddCallback (dlg->dlg_w,
21620                   XmNcancelCallback, SUMA_FileSelection_popdown_cb,
21621                   (XtPointer)dlg);
21622    XtAddCallback (dlg->dlg_w,
21623                   XmNokCallback, SUMA_FileSelection_file_select_cb,
21624                   (XtPointer)dlg);
21625    XtAddCallback (dlg->dlg_w,
21626                   XmNunmapCallback, SUMA_FileSelection_Unmap_cb,
21627                   (XtPointer)dlgp);
21628 
21629    if (dlg->Mode == SUMA_FILE_OPEN) {
21630       button = XmStringCreateLocalized ("Open");
21631       title = XmStringCreateLocalized (title_extension);
21632    }
21633    else { /* dlg->Mode == SUMA_FILE_SAVE */
21634      button = XmStringCreateLocalized ("Save");
21635      title = XmStringCreateLocalized (title_extension);
21636    }
21637    XtVaSetValues (dlg->dlg_w,
21638      XmNokLabelString, button,
21639      XmNdialogTitle,   title,
21640      NULL);
21641 
21642    XmStringFree (button);
21643    XmStringFree (title);
21644 
21645    XtManageChild (dlg->dlg_w);
21646 
21647    /* make sure that dialog is raised to top of window stack */
21648    XMapRaised (XtDisplay (dlg->dlg_w), XtWindow (XtParent (dlg->dlg_w)));
21649 
21650    SUMA_RETURN(dlg);
21651 }
21652 /*!
21653  \brief sample callback routine for "Cancel" button in FileSelectionDialogs
21654  SUMA_SELECTION_DIALOG_STRUCT *
21655 */
SUMA_FileSelection_popdown_cb(Widget w,XtPointer client_data,XtPointer call_data)21656 void SUMA_FileSelection_popdown_cb (Widget w, XtPointer client_data, XtPointer call_data)
21657 {
21658    static char FuncName[]={"SUMA_FileSelection_popdown_cb"};
21659    SUMA_SELECTION_DIALOG_STRUCT *dlg;
21660    SUMA_Boolean LocalHead = NOPE;
21661 
21662    SUMA_ENTRY;
21663 
21664    SUMA_LH("Called");
21665 
21666    dlg = (SUMA_SELECTION_DIALOG_STRUCT *)client_data;
21667 
21668 
21669    /* do the callback for the cancel */
21670    if (dlg->CancelCallback) {
21671       dlg->CancelCallback(dlg->CancelData);
21672    }
21673 
21674    XtUnmanageChild (dlg->dlg_w);
21675 
21676    SUMA_RETURNe;
21677 }
21678 /*!
21679  \brief sample callback routine for killing window in FileSelectionDialogs.
21680  That happens when users hit the X on the dialog
21681  This function destroys the widget and frees the structure if no preservation is needed
21682 
21683  -expect SUMA_SELECTION_DIALOG_STRUCT ** in client_data
21684 */
SUMA_FileSelection_Unmap_cb(Widget w,XtPointer client_data,XtPointer call_data)21685 void SUMA_FileSelection_Unmap_cb (
21686    Widget w, XtPointer client_data, XtPointer call_data)
21687 {
21688    static char FuncName[]={"SUMA_FileSelection_Unmap_cb"};
21689    SUMA_SELECTION_DIALOG_STRUCT *dlg;
21690    SUMA_SELECTION_DIALOG_STRUCT **dlgp;
21691    SUMA_Boolean LocalHead = NOPE;
21692 
21693    SUMA_ENTRY;
21694 
21695    SUMA_LH("Called");
21696 
21697    dlgp = (SUMA_SELECTION_DIALOG_STRUCT **)client_data;
21698    dlg = *dlgp;
21699 
21700    /* if preservation is not required, kill the widget and free dlg */
21701    if (!dlg->preserve) {
21702       if (dlg->dlg_w) {
21703          SUMA_LH("Destroying dlg");
21704          XtDestroyWidget(dlg->dlg_w);
21705       }else {
21706          SUMA_SL_Warn("dlg_w is null.\nThis should not be.");
21707       }
21708 
21709       /* now free the structure */
21710       SUMA_FreeFileSelectionDialogStruct(dlg);
21711       *dlgp = NULL;
21712 
21713    }
21714 
21715    SUMA_RETURNe;
21716 }
21717 
21718 /*!
21719    \brief Free the structure for creating a file selection dialog
21720 
21721 */
SUMA_FreeFileSelectionDialogStruct(SUMA_SELECTION_DIALOG_STRUCT * dlg)21722 void SUMA_FreeFileSelectionDialogStruct(SUMA_SELECTION_DIALOG_STRUCT *dlg)
21723 {
21724    static char FuncName[]={"SUMA_FreeFileSelectionDialogStruct"};
21725    SUMA_Boolean LocalHead = NOPE;
21726 
21727    SUMA_ENTRY;
21728    SUMA_LH("Called");
21729 
21730 
21731    if (!dlg) SUMA_RETURNe;
21732 
21733    /* now free structure */
21734    if (dlg->filename) SUMA_free(dlg->filename);
21735    if (dlg->FilePattern) SUMA_free(dlg->FilePattern);
21736    SUMA_free(dlg);
21737 
21738    SUMA_RETURNe;
21739 }
21740 
21741 /*!
21742 callback routine for "OK" button in FileSelectionDialogs
21743 */
SUMA_FileSelection_file_select_cb(Widget dialog,XtPointer client_data,XtPointer call_data)21744 void SUMA_FileSelection_file_select_cb(Widget dialog, XtPointer client_data, XtPointer call_data)
21745 {
21746    static char FuncName[]={"SUMA_FileSelection_file_select_cb"};
21747    char buf[256], *filename;
21748    struct stat statb;
21749    FILE *fp=NULL;
21750    SUMA_SELECTION_DIALOG_STRUCT *dlg;
21751    XmFileSelectionBoxCallbackStruct *cbs =
21752      (XmFileSelectionBoxCallbackStruct *) call_data;
21753    SUMA_Boolean LocalHead = NOPE;
21754 
21755    SUMA_ENTRY;
21756 
21757    SUMA_LH("Called");
21758 
21759    dlg = (SUMA_SELECTION_DIALOG_STRUCT *)client_data;
21760 
21761    /* clear old filename */
21762    if (dlg->filename) {
21763       SUMA_free(dlg->filename);
21764       dlg->filename = NULL;
21765    }
21766 
21767    if (!XmStringGetLtoR (cbs->value, XmFONTLIST_DEFAULT_TAG, &filename))
21768       SUMA_RETURNe; /* must have been an internal error */
21769 
21770    if (filename[0] == '\0') {
21771       XtFree (filename);
21772       XBell (XtDisplay (dlg->daddy), 50);
21773       SUMA_RETURNe; /* nothing typed */
21774    }
21775 
21776    if (dlg->Mode == SUMA_FILE_SAVE) {
21777       /* here you could do some tests on the file given the
21778       options that would be specified in dlg */
21779       /* Do not carry out tests here as filename might change
21780          once proper extensions are added */
21781       #if 0
21782       if (!(fp = fopen (filename, "w"))) {
21783          perror (filename);
21784          sprintf (buf, "Can't save to %s.", filename);
21785          SUMA_SLP_Err(buf);
21786          XtFree(filename);
21787          SUMA_RETURNe;
21788       }
21789       #endif
21790 
21791    }
21792    else { /* reason == FILE_OPEN */
21793      /* here you could do some tests on the file given the
21794      options that would be specified in dlg */
21795      /* make sure the file is a regular text file and open it */
21796      if (stat (filename, &statb) == -1 ||
21797              (statb.st_mode & S_IFMT) != S_IFREG ||
21798              !(fp = fopen (filename, "r"))) {
21799          perror (filename);
21800          SUMA_SLP_Err("Can't read %s.", filename);
21801          XtFree(filename);
21802          SUMA_RETURNe;
21803      }
21804    }
21805 
21806    /* store the filename */
21807    if (filename) {
21808       dlg->filename = (char *)SUMA_calloc(strlen(filename)+1, sizeof(char));
21809       dlg->filename = strcpy(dlg->filename, filename);
21810    }
21811 
21812    /* free all allocated space. */
21813    XtFree (filename);
21814    if (fp) fclose (fp);
21815 
21816    /* Now do the SelectCallback */
21817    if (dlg->SelectCallback) {
21818       dlg->SelectCallback(dlg->filename, dlg->SelectData);
21819    }
21820 
21821    XtUnmanageChild (dlg->dlg_w); /* this function will call the unmap
21822                                     callback which will do the destruction
21823                                     if dialog is not to be preserved */
21824 
21825    SUMA_RETURNe;
21826 }
21827 
21828 /* This function is for hiding the color plane frame */
SUMA_cb_ToggleManagementColPlaneWidget(Widget w,XtPointer data,XtPointer client_data)21829 void  SUMA_cb_ToggleManagementColPlaneWidget(Widget w, XtPointer data,
21830                                              XtPointer client_data)
21831 {
21832    static char FuncName[]={"SUMA_cb_ToggleManagementColPlaneWidget"};
21833    static int ncall=1;
21834    SUMA_ALL_DO *ado = NULL;
21835    int xx, yy, notest = 0;
21836    SUMA_X_SurfCont *SurfCont=NULL;
21837    SUMA_OVERLAYS *curColPlane=NULL;
21838    SUMA_Boolean LocalHead = NOPE;
21839 
21840    SUMA_ENTRY;
21841 
21842    ado = (SUMA_ALL_DO *)data;
21843    SurfCont = SUMA_ADO_Cont(ado);
21844    curColPlane = SUMA_ADO_CurColPlane(ado);
21845 
21846 #ifdef USING_LESSTIF
21847       notest = 1;
21848 #endif
21849 
21850    if (ncall > 0) {
21851       if (XtIsManaged(SurfCont->ColPlane_fr)) {
21852          SUMA_LHv("UnM.ch: ColPlane_fr, ncall %d\n", ncall);
21853          XtUnmanageChild(SurfCont->ColPlane_fr);
21854       }
21855       if( notest ) {
21856          SUMA_LHv("UnM.ch: DsetMap_fr, ncall %d\n", ncall);
21857          XtUnmanageChild(SurfCont->DsetMap_fr); /* needed */
21858       }
21859       /* if nothing else remains in the parent of ColPlane,
21860          then unmanage its parent (rc_right) too.
21861          *** Parent of that frame is now rc_left    May 25 04*/
21862       /* XtUnmanageChild(XtParent(SurfCont->ColPlane_fr)); May 25 04*/
21863       if (XtIsManaged(SurfCont->DsetMap_fr)) {
21864          SUMA_LHv("UnM.ch: DsetMap_fr, par(DsetMap_fr), ncall %d\n", ncall);
21865          XtUnmanageChild(SurfCont->DsetMap_fr);
21866          XtUnmanageChild(XtParent(SurfCont->DsetMap_fr));
21867       }
21868    } else {
21869       /* XtManageChild(XtParent(SurfCont->ColPlane_fr)); May 25 04*/
21870       if ((strcmp(curColPlane->cmapname, "explicit") != 0) &&
21871           !SUMA_is_Label_dset(curColPlane->dset_link, NULL)) {
21872          SUMA_LHv("Not explicit, ncall = %d\n", ncall);
21873          /* not an RGB dset */
21874          if (!XtIsManaged(SurfCont->DsetMap_fr)) {
21875             SUMA_LHv("M.ch: par(DsetMap_fr) DsetMap_fr, ncall = %d\n", ncall);
21876             XtManageChild(XtParent(SurfCont->DsetMap_fr));
21877             XtManageChild((Widget)SurfCont->DsetMap_fr);
21878          }
21879       }
21880 
21881       SUMA_LHv("M.ch: ColPlane_fr, ncall = %d\n", ncall);
21882       XtManageChild((Widget)SurfCont->ColPlane_fr);
21883 
21884       SUMA_LHv("Map.R: ColPlane_fr, ncall = %d\n", ncall);
21885       XMapRaised (XtDisplay(SurfCont->ColPlane_fr),
21886                   XtWindow(SurfCont->TLS));
21887    }
21888 
21889    ncall *= -1;
21890    SUMA_RETURNe;
21891 }
21892 
21893 
21894 /*!
21895    Load colorplane
21896 
21897    expects SO in data and a calling widget in w
21898 */
SUMA_cb_ColPlane_Load(Widget w,XtPointer data,XtPointer client_data)21899 void SUMA_cb_ColPlane_Load(Widget w, XtPointer data, XtPointer client_data)
21900 {
21901    static char FuncName[]={"SUMA_cb_ColPlane_Load"};
21902    SUMA_LIST_WIDGET *LW=NULL;
21903    SUMA_SurfaceObject *SO=NULL;
21904    DList *list = NULL;
21905    SUMA_EngineData *ED = NULL;
21906    DListElmt *NextElm = NULL;
21907    SUMA_Boolean LocalHead = NOPE;
21908 
21909    SUMA_ENTRY;
21910 
21911    SUMA_LH("Called");
21912 
21913    SO = (SUMA_SurfaceObject *)data;
21914 
21915    if (!list) list = SUMA_CreateList();
21916    ED = SUMA_InitializeEngineListData (SE_OpenColFileSelection);
21917    if (!(NextElm = SUMA_RegisterEngineListCommand (  list, ED,
21918                                           SEF_vp, (void *)data,
21919                                           SES_Suma, NULL, NOPE,
21920                                           SEI_Head, NULL))) {
21921       fprintf (SUMA_STDERR, "Error %s: Failed to register command.\n", FuncName);
21922    }
21923    if (!SUMA_RegisterEngineListCommand (  list, ED,
21924                                           SEF_ip, (int *)w,
21925                                           SES_Suma, NULL, NOPE,
21926                                           SEI_In, NextElm)) {
21927       fprintf (SUMA_STDERR, "Error %s: Failed to register command.\n", FuncName);
21928    }
21929 
21930    if (!SUMA_Engine (&list)) {
21931       fprintf(SUMA_STDERR, "Error %s: SUMA_Engine call failed.\n", FuncName);
21932    }
21933 
21934    SUMA_RETURNe;
21935 }
21936 
21937 /*!
21938    Load Dset
21939 
21940    expects SO in data and a calling widget in w
21941 */
SUMA_cb_Dset_Load(Widget w,XtPointer data,XtPointer client_data)21942 void SUMA_cb_Dset_Load(Widget w, XtPointer data, XtPointer client_data)
21943 {
21944    static char FuncName[]={"SUMA_cb_Dset_Load"};
21945    SUMA_LIST_WIDGET *LW=NULL;
21946    SUMA_SurfaceObject *SO=NULL;
21947    DList *list = NULL;
21948    SUMA_EngineData *ED = NULL;
21949    DListElmt *NextElm = NULL;
21950    SUMA_Boolean LocalHead = NOPE;
21951 
21952    SUMA_ENTRY;
21953 
21954    SUMA_LH("Called");
21955 
21956    SO = (SUMA_SurfaceObject *)data;
21957 
21958    if (!list) list = SUMA_CreateList();
21959    ED = SUMA_InitializeEngineListData (SE_OpenDsetFileSelection);
21960    if (!(NextElm = SUMA_RegisterEngineListCommand (  list, ED,
21961                                           SEF_vp, (void *)data,
21962                                           SES_Suma, NULL, NOPE,
21963                                           SEI_Head, NULL))) {
21964       fprintf (SUMA_STDERR,
21965          "Error %s: Failed to register command.\n", FuncName);
21966    }
21967    if (!SUMA_RegisterEngineListCommand (  list, ED,
21968                                           SEF_ip, (int *)w,
21969                                           SES_Suma, NULL, NOPE,
21970                                           SEI_In, NextElm)) {
21971       fprintf (SUMA_STDERR,
21972          "Error %s: Failed to register command.\n", FuncName);
21973    }
21974 
21975    if (!SUMA_Engine (&list)) {
21976       fprintf(SUMA_STDERR,
21977          "Error %s: SUMA_Engine call failed.\n", FuncName);
21978    }
21979 
21980    SUMA_RETURNe;
21981 }
21982 
21983 /*!
21984    Delete colorplane
21985 
21986    expects SO in data
21987 */
SUMA_cb_ColPlane_Delete(Widget w,XtPointer data,XtPointer client_data)21988 void SUMA_cb_ColPlane_Delete(Widget w, XtPointer data, XtPointer client_data)
21989 {
21990    static char FuncName[]={"SUMA_cb_ColPlane_Delete"};
21991    SUMA_LIST_WIDGET *LW=NULL;
21992    SUMA_SurfaceObject *SO=NULL;
21993    SUMA_Boolean LocalHead = NOPE;
21994 
21995    SUMA_ENTRY;
21996 
21997    SUMA_LH("Called");
21998    SUMA_RETURNe;
21999 
22000    #if 0
22001    SO = (SUMA_SurfaceObject *)data;
22002 
22003    LW is not set yet ...
22004 
22005    /*close the list widget if open */
22006    if (!LW->isShaded) {
22007       if (LocalHead) fprintf (SUMA_STDERR, "%s: Closing switch Color plane window ...\n", FuncName);
22008       SUMA_cb_CloseSwitchColPlane( w,  (XtPointer)SO->SurfCont->SwitchDsetlst,  client_data);
22009    }
22010    #endif
22011    SUMA_RETURNe;
22012 }
22013 
22014 /*!
22015    \brief create a forced answer dialog for replacing files
22016    \return SUMA_YES SUMA_NO SUMA_YES_ALL or SUMA_NO_ALL
22017 
22018 */
SUMA_AskUser_File_replace(Widget parent,char * question,int default_ans)22019 int SUMA_AskUser_File_replace(Widget parent, char *question, int default_ans)
22020 {
22021     static char FuncName[]={"SUMA_AskUser_File_replace"};
22022     static Widget dialog; /* static to avoid multiple creation */
22023     Widget YesWid, NoWid, HelpWid;
22024     XmString text, yes, no;
22025     static int answer;
22026 
22027    SUMA_ENTRY;
22028 
22029    if (!dialog) {
22030      dialog = XmCreateQuestionDialog (parent, "dialog", NULL, 0);
22031      XtVaSetValues (dialog,
22032          XmNdialogStyle,        XmDIALOG_FULL_APPLICATION_MODAL,
22033          NULL);
22034      XtSetSensitive (
22035          XmMessageBoxGetChild (dialog, XmDIALOG_HELP_BUTTON),
22036          False);
22037      XtAddCallback (dialog, XmNokCallback, SUMA_response, &answer);
22038      XtAddCallback (dialog, XmNcancelCallback, SUMA_response, &answer);
22039     /* Now add a special extra cute little button */
22040     {
22041        XmString NewButt;
22042        Widget NewButt_button = NULL;
22043 
22044        NewButt= XmStringCreateLocalized ("Yes All");
22045        NewButt_button = XtVaCreateManagedWidget("Yes All",
22046          xmPushButtonWidgetClass, dialog,
22047          XmNlabelString, NewButt,
22048          NULL);
22049        XtVaSetValues(NewButt_button, XmNuserData, SUMA_YES_ALL, NULL);
22050        XtAddCallback (NewButt_button, XmNactivateCallback, SUMA_response, &answer);
22051        XmStringFree (NewButt);
22052 
22053 
22054        NewButt= XmStringCreateLocalized ("No");
22055        NewButt_button = XtVaCreateManagedWidget("No",
22056          xmPushButtonWidgetClass, dialog,
22057          XmNlabelString, NewButt,
22058          NULL);
22059        XtVaSetValues(NewButt_button, XmNuserData, SUMA_NO, NULL);
22060        XtAddCallback (NewButt_button, XmNactivateCallback, SUMA_response, &answer);
22061        XmStringFree (NewButt);
22062 
22063     }
22064 
22065     }
22066    answer = SUMA_NO_ANSWER;
22067    text = XmStringCreateLocalized (question);
22068    yes = XmStringCreateLocalized ("Yes");
22069    no = XmStringCreateLocalized ("No All");
22070    XtVaSetValues (dialog,
22071      XmNmessageString,      text,
22072      XmNokLabelString,      yes,
22073      XmNcancelLabelString,  no,
22074      XmNdefaultButtonType,  default_ans == SUMA_YES ?
22075          XmDIALOG_OK_BUTTON : XmDIALOG_CANCEL_BUTTON,
22076      NULL);
22077    XmStringFree (text);
22078    XmStringFree (yes);
22079    XmStringFree (no);
22080 
22081    /* set the values of the standrard buttons */
22082    YesWid = XmMessageBoxGetChild(dialog, XmDIALOG_OK_BUTTON);
22083    XtVaSetValues(YesWid, XmNuserData, SUMA_YES, NULL);
22084    NoWid = XmMessageBoxGetChild(dialog, XmDIALOG_CANCEL_BUTTON);
22085    XtVaSetValues(NoWid, XmNuserData, SUMA_NO_ALL, NULL);
22086    HelpWid = XmMessageBoxGetChild(dialog, XmDIALOG_HELP_BUTTON);
22087    XtVaSetValues(HelpWid, XmNuserData, SUMA_HELP, NULL);
22088 
22089    /* unmanage the Help button because I am not using it here */
22090    XtUnmanageChild(HelpWid);
22091 
22092    XtManageChild (dialog);
22093    XtPopup (XtParent (dialog), XtGrabNone);
22094 
22095    while (answer == SUMA_NO_ANSWER)
22096      XtAppProcessEvent (SUMAg_CF->X->App, XtIMAll);
22097 
22098    XtPopdown (XtParent (dialog));
22099    /* make sure the dialog goes away before returning. Sync with server
22100    * and update the display.
22101    */
22102    XSync (XtDisplay (dialog), 0);
22103    XmUpdateDisplay (parent);
22104 
22105    SUMA_RETURN(answer);
22106 }
22107 
22108 
22109 /*!
22110   Supposed to behave like ForceUser function below but only for pausing.
22111 */
SUMA_PauseForUser(Widget parent,char * question,SUMA_WINDOW_POSITION pos,XtAppContext * app,int withcancel,float timeout)22112 int SUMA_PauseForUser(  Widget parent, char *question, SUMA_WINDOW_POSITION pos,
22113                         XtAppContext *app, int withcancel, float timeout)
22114 {
22115    static char FuncName[]={"SUMA_PauseForUser"};
22116    static Widget dialog; /* static to avoid multiple creation */
22117    Widget YesWid;
22118    int ii;
22119    XmString text, yes;
22120    struct  timeval  tt;
22121    static int answer;
22122    SUMA_Boolean LocalHead = NOPE;
22123 
22124    SUMA_ENTRY;
22125    if (!parent) {
22126       /* look for the first non-null sv->X->TOPLEVEL */
22127       ii = 0;
22128       while (ii<SUMAg_N_SVv && !(parent=SUMAg_SVv[ii].X->TOPLEVEL)) {
22129          ++ii;
22130       }
22131    }
22132    if (!parent) { /* no widgets, go command line */
22133       SUMA_PAUSE_PROMPT_STDIN(question);
22134       SUMA_RETURN(SUMA_YES);
22135    }
22136 
22137    if (!dialog) {
22138      SUMA_LH("Creating Dialog");
22139      dialog = XmCreateQuestionDialog (parent, "dialog", NULL, 0);
22140      XtVaSetValues (dialog,
22141          XmNdialogStyle,        XmDIALOG_FULL_APPLICATION_MODAL,
22142          NULL);
22143      /* Don't need help and cancel buttons*/
22144      XtUnmanageChild (XmMessageBoxGetChild (dialog, XmDIALOG_HELP_BUTTON));
22145      if (!withcancel) {
22146       XtUnmanageChild (XmMessageBoxGetChild (dialog, XmDIALOG_CANCEL_BUTTON));
22147      }else {
22148       XtAddCallback (dialog, XmNcancelCallback, SUMA_response, &answer);
22149      }
22150 
22151      XtAddCallback (dialog, XmNokCallback, SUMA_response, &answer);
22152     } else {
22153       SUMA_LH("Reusing Dialog (SLOW SLOW SLOW)");
22154     }
22155 
22156    SUMA_etime(&tt, 0);
22157    answer = SUMA_NO_ANSWER;
22158    text = XmStringCreateLocalized (question);
22159    yes = XmStringCreateLocalized ("OK");
22160    XtVaSetValues (dialog,
22161      XmNmessageString,      text,
22162      XmNokLabelString,      yes,
22163      XmNdefaultButtonType,  XmDIALOG_OK_BUTTON,
22164      NULL);
22165    XmStringFree (text);
22166    XmStringFree (yes);
22167 
22168    /* set the values of the standard buttons */
22169    YesWid = XmMessageBoxGetChild(dialog, XmDIALOG_OK_BUTTON);
22170    XtVaSetValues(YesWid, XmNuserData, SUMA_YES, NULL);
22171 
22172    XtManageChild (dialog);
22173 
22174    XtPopup (XtParent (dialog), XtGrabNone);
22175 
22176    if (pos != SWP_DONT_CARE) SUMA_PositionWindowRelative(dialog, parent, pos);
22177 
22178 
22179    if (!app) app = &(SUMAg_CF->X->App);
22180    if (timeout < 0.0) { /* no timer */
22181       while ( (answer == SUMA_NO_ANSWER && XtIsManaged(dialog)) ) {
22182           XtAppProcessEvent (*app, XtIMAll);
22183       }
22184    } else {
22185       while ( (answer == SUMA_NO_ANSWER && XtIsManaged(dialog)) ) {
22186          if (timeout < 0.0 || SUMA_etime(&tt,1) < timeout) {
22187             if (XtAppPending(*app)) { XtAppProcessEvent (*app, XtIMAll); }
22188          } else {
22189             XtVaGetValues(YesWid, XmNuserData, &answer, NULL);
22190             break;
22191          }
22192       }
22193    }
22194    #if 1
22195       SUMA_LH("destroying dialog");
22196 
22197       XtDestroyWidget(dialog);   /* This won't get the widget off of the screen
22198                                     unless there is an XtAppMainLoop running.
22199                                     When that is not the case, you need to
22200                                     trigger an event processing call, see
22201                                     SUMA_prompt_user.c for an example */
22202 
22203       dialog = NULL;
22204    #else /* bad, takes for ever to come back up.
22205             Same for repeated calls of ForceUser if created for the first
22206             time from DriveSuma and not from the interface with, say 'shft+Esc'
22207             See bit of illustration code in SUMA_Engine where PauseForUser
22208             is called*/
22209       XtUnmanageChild(dialog);
22210    #endif
22211    SUMA_RETURN(answer);
22212 }
22213 
22214 /*!
22215    \brief create a forced answer dialog YES/NO
22216 
22217    set pos to SWP_DONT_CARE (recommended) if you don't want to specify where
22218    the prompt goes
22219    \return SUMA_YES SUMA_NO
22220 */
SUMA_ForceUser_YesNo(Widget parent,char * question,int default_ans,SUMA_WINDOW_POSITION pos)22221 int SUMA_ForceUser_YesNo(Widget parent, char *question, int default_ans, SUMA_WINDOW_POSITION pos)
22222 {
22223     static char FuncName[]={"SUMA_ForceUser_YesNo"};
22224     static Widget dialog; /* static to avoid multiple creation */
22225     Widget YesWid, NoWid, HelpWid;
22226     XmString text, yes, no;
22227     static int answer;
22228 
22229    SUMA_ENTRY;
22230 
22231    if (!dialog) {
22232      dialog = XmCreateQuestionDialog (parent, "dialog", NULL, 0);
22233      XtVaSetValues (dialog,
22234          XmNdialogStyle,        XmDIALOG_FULL_APPLICATION_MODAL,
22235          NULL);
22236      XtSetSensitive (
22237          XmMessageBoxGetChild (dialog, XmDIALOG_HELP_BUTTON),
22238          False);
22239      XtAddCallback (dialog, XmNokCallback, SUMA_response, &answer);
22240      XtAddCallback (dialog, XmNcancelCallback, SUMA_response, &answer);
22241 
22242     }
22243    answer = SUMA_NO_ANSWER;
22244    text = XmStringCreateLocalized (question);
22245    yes = XmStringCreateLocalized ("Yes");
22246    no = XmStringCreateLocalized ("No");
22247    XtVaSetValues (dialog,
22248      XmNmessageString,      text,
22249      XmNokLabelString,      yes,
22250      XmNcancelLabelString,  no,
22251      XmNdefaultButtonType,  default_ans == SUMA_YES ?
22252          XmDIALOG_OK_BUTTON : XmDIALOG_CANCEL_BUTTON,
22253      NULL);
22254    XmStringFree (text);
22255    XmStringFree (yes);
22256    XmStringFree (no);
22257 
22258    /* set the values of the standard buttons */
22259    YesWid = XmMessageBoxGetChild(dialog, XmDIALOG_OK_BUTTON);
22260    XtVaSetValues(YesWid, XmNuserData, SUMA_YES, NULL);
22261    NoWid = XmMessageBoxGetChild(dialog, XmDIALOG_CANCEL_BUTTON);
22262    XtVaSetValues(NoWid, XmNuserData, SUMA_NO_ALL, NULL);
22263    HelpWid = XmMessageBoxGetChild(dialog, XmDIALOG_HELP_BUTTON);
22264    XtVaSetValues(HelpWid, XmNuserData, SUMA_HELP, NULL);
22265 
22266    /* unmanage the buttons I am not using it here */
22267    XtUnmanageChild(HelpWid);
22268 
22269 
22270    XtManageChild (dialog);
22271    XtPopup (XtParent (dialog), XtGrabNone);
22272 
22273    if (pos != SWP_DONT_CARE) SUMA_PositionWindowRelative(dialog, parent, pos);
22274 
22275    while (answer == SUMA_NO_ANSWER)
22276      XtAppProcessEvent (SUMAg_CF->X->App, XtIMAll);
22277 
22278    XtPopdown (XtParent (dialog));
22279    /* make sure the dialog goes away before returning. Sync with server
22280    * and update the display.
22281    */
22282    XSync (XtDisplay (dialog), 0);
22283    XmUpdateDisplay (parent);
22284 
22285    SUMA_RETURN(answer);
22286 }
22287 
22288 
22289 /*
22290  * AskUser() -- a generalized routine that asks the user a question
22291  * and returns a response.  Parameters are: the question, the labels
22292  * for the "Yes" and "No" buttons, and the default selection to use.
22293  */
AskUser(Widget parent,char * question,char * ans1,char * ans2,int default_ans)22294 int AskUser(Widget parent, char *question, char *ans1, char *ans2, int default_ans)
22295 {
22296     static Widget dialog; /* static to avoid multiple creation */
22297     XmString text, yes, no;
22298     static int answer;
22299 
22300     if (!dialog) {
22301         dialog = XmCreateQuestionDialog (parent, "dialog", NULL, 0);
22302         XtVaSetValues (dialog,
22303             XmNdialogStyle,        XmDIALOG_FULL_APPLICATION_MODAL,
22304             NULL);
22305         XtSetSensitive (
22306             XmMessageBoxGetChild (dialog, XmDIALOG_HELP_BUTTON),
22307             False);
22308         XtAddCallback (dialog, XmNokCallback, SUMA_response, &answer);
22309         XtAddCallback (dialog, XmNcancelCallback, SUMA_response, &answer);
22310        /* Now add a special extra cute little button */
22311        {
22312           /* To do here:
22313           - Make all other buttons use UserData for uniformity
22314           - use SUMA_NO, SUMA_YES etc....
22315           - deal with recreation issues (you'll have to keep track of which new buttons are used, their new labels and whether they are to appear or not.)
22316             You'll probably want different kinds of static dialog widgets for the various types you envision using ....
22317           */
22318           XmString All = XmStringCreateLocalized ("All");
22319           Widget All_button = NULL;
22320 
22321           All_button = XtVaCreateManagedWidget("All",
22322             xmPushButtonWidgetClass, dialog,
22323             XmNlabelString, All,
22324             NULL);
22325           XtVaSetValues(All_button, XmNuserData, SUMA_YES_ALL, NULL);
22326           XtAddCallback (All_button, XmNactivateCallback, SUMA_response, &answer);
22327           XmStringFree (All);
22328        }
22329 
22330     }
22331     answer = SUMA_NO_ANSWER;
22332     text = XmStringCreateLocalized (question);
22333     yes = XmStringCreateLocalized (ans1);
22334     no = XmStringCreateLocalized (ans2);
22335     XtVaSetValues (dialog,
22336         XmNmessageString,      text,
22337         XmNokLabelString,      yes,
22338         XmNcancelLabelString,  no,
22339         XmNdefaultButtonType,  default_ans == SUMA_YES ?
22340             XmDIALOG_OK_BUTTON : XmDIALOG_CANCEL_BUTTON,
22341         NULL);
22342     XmStringFree (text);
22343     XmStringFree (yes);
22344     XmStringFree (no);
22345 
22346     XtManageChild (dialog);
22347     XtPopup (XtParent (dialog), XtGrabNone);
22348 
22349     while (answer == SUMA_NO_ANSWER)
22350         XtAppProcessEvent (SUMAg_CF->X->App, XtIMAll);
22351 
22352     XtPopdown (XtParent (dialog));
22353     /* make sure the dialog goes away before returning. Sync with server
22354      * and update the display.
22355      */
22356     XSync (XtDisplay (dialog), 0);
22357     XmUpdateDisplay (parent);
22358 
22359     return answer;
22360 }
22361 
22362 /*!
22363    \brief sets the answer value to a question dialog created by functions
22364    like SUMA_AskUser....
22365    -Based largely on example in Motif Programming Manual chapters 5 and 7
22366 
22367    - For the three standard dialog buttons:
22368    XmDIALOG_OK_BUTTON, XmDIALOG_CANCEL_BUTTON and XmDIALOG_HELP_BUTTON,
22369    the widget appears to be the dialog widget
22370    - For the other buttons (XmCR_ACTIVATE) the widget appears to be the
22371    button itself.
22372  */
SUMA_response(Widget widget,XtPointer client_data,XtPointer call_data)22373 void SUMA_response(Widget widget, XtPointer client_data, XtPointer call_data)
22374 {
22375    static char FuncName[]={"SUMA_response"};
22376    int *answer = (int *) client_data;
22377    int ud=0;
22378    Widget YesWid, NoWid, HelpWid;
22379    XmAnyCallbackStruct *cbs = (XmAnyCallbackStruct *) call_data;
22380    SUMA_Boolean LocalHead = NOPE;
22381 
22382    SUMA_ENTRY;
22383 
22384    switch (cbs->reason) {
22385    case XmCR_OK:
22386       YesWid = XmMessageBoxGetChild(widget, XmDIALOG_OK_BUTTON);
22387       XtVaGetValues(YesWid, XmNuserData, &ud, NULL);
22388       *answer = ud;
22389       break;
22390    case XmCR_CANCEL:
22391       NoWid = XmMessageBoxGetChild(widget, XmDIALOG_CANCEL_BUTTON);
22392       XtVaGetValues(NoWid, XmNuserData, &ud, NULL);
22393       *answer = ud;
22394       break;
22395    case XmCR_HELP:
22396       HelpWid = XmMessageBoxGetChild(widget, XmDIALOG_HELP_BUTTON);
22397       XtVaGetValues(HelpWid, XmNuserData, &ud, NULL);
22398       *answer = ud;
22399       break;
22400    case XmCR_ACTIVATE:
22401       XtVaGetValues(widget, XmNuserData, &ud, NULL);
22402       *answer = ud;
22403       break;
22404    default:
22405       *answer = -1;
22406       break;
22407    }
22408 
22409    if (LocalHead) fprintf (SUMA_STDERR,"%s: Answer %d\n", FuncName, *answer);
22410    SUMA_RETURNe;
22411 }
22412 /*!
22413    \brief spits out stats about available visuals
22414 
22415    - copied from program glxvisuals.c by Mark Kilgard
22416 
22417    \sa SUMA_ShowVisual
22418 */
SUMA_ShowAllVisuals(void)22419 void SUMA_ShowAllVisuals (void)
22420 {
22421    static char FuncName[]={"SUMA_ShowAllVisuals"};
22422    Display *dpy;
22423    XVisualInfo match, *visualList=NULL, *vi=NULL, *visualToTry=NULL;
22424    int errorBase, eventBase, major, minor, found, glxcapable;
22425    Widget TopLevel;
22426    XtAppContext App;
22427    char *vargv[1]={ "[A] SUMA" };
22428    int cargc = 1;
22429 
22430    SUMA_ENTRY;
22431 
22432    dpy = XOpenDisplay(NULL);
22433    if (!dpy) {
22434       fprintf( SUMA_STDERR,
22435                "Error %s: Could not connect to %s.\n",
22436                FuncName, XDisplayName(NULL));
22437       SUMA_RETURNe;
22438    }
22439    if (glXQueryExtension(dpy, &errorBase, &eventBase) == False) {
22440       fprintf(SUMA_STDERR,
22441               "Error %s: OpenGL not supported by X server.\n" ,FuncName);
22442       SUMA_RETURNe;
22443    }
22444 
22445    glXQueryVersion(dpy, &major, &minor);
22446    fprintf(SUMA_STDERR, "display: %s\n", XDisplayName(NULL));
22447    fprintf(SUMA_STDERR, "using GLX version: %d.%d\n\n", major, minor);
22448 
22449    match.screen = DefaultScreen(dpy);
22450    visualList = XGetVisualInfo(dpy, VisualScreenMask, &match, &found);
22451 
22452    visualToTry = NULL;
22453    for(vi = visualList; found > 0; found--, vi++) {
22454       if (vi == visualList) glxcapable = SUMA_ShowVisual(dpy, vi, YUP);
22455       else glxcapable = SUMA_ShowVisual(dpy, vi, NOPE);
22456 
22457       if (glxcapable) visualToTry = vi;
22458    }
22459 
22460    if (visualToTry) {
22461       GLXContext context;
22462       Window window;
22463       Colormap colormap;
22464       XSetWindowAttributes swa;
22465 
22466       context = glXCreateContext(dpy, visualToTry, 0, GL_TRUE);
22467       colormap = XCreateColormap(dpy,
22468       RootWindow(dpy, visualToTry->screen),
22469       visualToTry->visual, AllocNone);
22470       swa.colormap = colormap;
22471       swa.border_pixel = 0;
22472       window = XCreateWindow( dpy, RootWindow(dpy, visualToTry->screen),
22473                               0, 0, 100, 100, 0, visualToTry->depth,
22474                               InputOutput, visualToTry->visual,
22475                               CWBorderPixel | CWColormap, &swa);
22476       SUMA_glXMakeCurrent(dpy, window, context, FuncName, "showall", 1);
22477       fprintf(SUMA_STDERR, "\n");
22478       fprintf(SUMA_STDERR, "OpenGL vendor string: %s\n", glGetString(GL_VENDOR));
22479       fprintf(SUMA_STDERR, "OpenGL renderer string: %s\n",
22480                            glGetString(GL_RENDERER));
22481       fprintf(SUMA_STDERR, "OpenGL version string: %s\n",
22482                            glGetString(GL_VERSION));
22483       if (glXIsDirect(dpy, context))
22484          fprintf(SUMA_STDERR, "direct rendering: supported\n");
22485    } else fprintf(SUMA_STDERR, "No GLX-capable visuals!\n");
22486 
22487    if (visualList) XFree(visualList);
22488 
22489    /* which visual will be chosen by SUMA ?
22490       (based on Step 3 in SUMA_X_SurfaceViewer_Create) */
22491    /* TopLevel = XtAppInitialize(&App, "SUMA", NULL, 0, &cargc, vargv,
22492                               SUMA_get_fallbackResources(), NULL, 0);
22493                Superseded by XtOpenApplication*/
22494    TopLevel = XtOpenApplication(&App, "SUMA", NULL, 0, &cargc, vargv,
22495                                  SUMA_get_fallbackResources(),
22496                                  topLevelShellWidgetClass, NULL, 0);
22497    dpy = XtDisplay(TopLevel);
22498 
22499    vi = glXChooseVisual(dpy, DefaultScreen(dpy), dblBuf);
22500    if (vi == NULL) {
22501       fprintf(stdout, "trying lame single buffer visual\n");
22502       XtAppWarning(App, "trying lame single buffer visual");
22503       vi = glXChooseVisual(dpy, DefaultScreen(dpy), snglBuf);
22504     if (vi == NULL) {
22505       XtAppError(App, "no good visual");
22506       }
22507    }
22508    fprintf (SUMA_STDERR,"************************************\n");
22509    fprintf (SUMA_STDERR,"%s: Visual chosen by SUMA:\n", FuncName);
22510    SUMA_ShowVisual(dpy, vi, YUP);
22511    if (vi->class != TrueColor) {
22512       fprintf (SUMA_STDERR,"%s: Visual is not TrueColor.\n", FuncName);
22513       fprintf (SUMA_STDERR," SUMA NO LIKE.\n");
22514    }
22515    /* Might cause trouble on Fedora Core 4. Don't know what to do with it */
22516    XtDestroyWidget(TopLevel);
22517    XtDestroyApplicationContext(App);
22518    SUMA_RETURNe;
22519 }
22520 
22521 /*!
22522    \brief Show the properties of a visual.
22523    \sa OpenGL Programming for the X Window System by Mark J. Kilgard
22524              pp. 75..81
22525 */
SUMA_ShowVisual(Display * dpy,XVisualInfo * vi,SUMA_Boolean ShowHead)22526 int SUMA_ShowVisual (Display *dpy, XVisualInfo *vi, SUMA_Boolean ShowHead)
22527 {
22528    static char FuncName[]={"SUMA_ShowVisual"};
22529    int glxCapable, bufferSize, level, renderType, doubleBuffer, stereo,
22530       auxBuffers, redSize, greenSize, blueSize, alphaSize, depthSize,
22531       stencilSize, acRedSize, acGreenSize, acBlueSize, acAlphaSize;
22532 
22533    SUMA_ENTRY;
22534 
22535    if (ShowHead) {
22536       fprintf(SUMA_STDERR, "\n");
22537       fprintf(SUMA_STDERR, "   visual     bf lv rg d st  r  g  b a   ax dp st accum buffs\n");
22538       fprintf(SUMA_STDERR, " id dep cl    sz l  ci b ro sz sz sz sz  bf th cl  r  g  b  a\n");
22539       fprintf(SUMA_STDERR, "-------------------------------------------------------------\n");
22540    }
22541 
22542    glXGetConfig(dpy, vi, GLX_USE_GL, &glxCapable);
22543    if (glxCapable) {
22544       fprintf(SUMA_STDERR, "0x%x %2d %s",(unsigned int)vi->visualid,
22545                            vi->depth, SUMA_ClassOf(vi->class));
22546       glXGetConfig(dpy, vi, GLX_BUFFER_SIZE, &bufferSize);
22547       glXGetConfig(dpy, vi, GLX_LEVEL, &level);
22548       glXGetConfig(dpy, vi, GLX_RGBA, &renderType);
22549       glXGetConfig(dpy, vi, GLX_DOUBLEBUFFER, &doubleBuffer);
22550       glXGetConfig(dpy, vi, GLX_STEREO, &stereo);
22551       glXGetConfig(dpy, vi, GLX_AUX_BUFFERS, &auxBuffers);
22552       glXGetConfig(dpy, vi, GLX_RED_SIZE, &redSize);
22553       glXGetConfig(dpy, vi, GLX_GREEN_SIZE, &greenSize);
22554       glXGetConfig(dpy, vi, GLX_BLUE_SIZE, &blueSize);
22555       glXGetConfig(dpy, vi, GLX_ALPHA_SIZE, &alphaSize);
22556       glXGetConfig(dpy, vi, GLX_DEPTH_SIZE, &depthSize);
22557       glXGetConfig(dpy, vi, GLX_STENCIL_SIZE, &stencilSize);
22558       glXGetConfig(dpy, vi, GLX_ACCUM_RED_SIZE, &acRedSize);
22559       glXGetConfig(dpy, vi, GLX_ACCUM_GREEN_SIZE, &acGreenSize);
22560       glXGetConfig(dpy, vi, GLX_ACCUM_BLUE_SIZE, &acBlueSize);
22561       glXGetConfig(dpy, vi, GLX_ACCUM_ALPHA_SIZE, &acAlphaSize);
22562       fprintf(SUMA_STDERR, "    %2s %2s %1s  %1s  %1s ",
22563         SUMA_Format(bufferSize, 2), SUMA_Format(level, 2),
22564         renderType ? "r" : "c",
22565          doubleBuffer ? "y" : ".",
22566          stereo ? "y" : ".");
22567       fprintf(SUMA_STDERR, "%2s %2s %2s %2s ",
22568          SUMA_Format(redSize, 2), SUMA_Format(greenSize, 2),
22569          SUMA_Format(blueSize, 2), SUMA_Format(alphaSize, 2));
22570       fprintf(SUMA_STDERR, "%2s %2s %2s %2s %2s %2s %2s",
22571         SUMA_Format(auxBuffers, 2), SUMA_Format(depthSize, 2),
22572         SUMA_Format(stencilSize, 2),
22573         SUMA_Format(acRedSize, 2), SUMA_Format(acGreenSize, 2),
22574         SUMA_Format(acBlueSize, 2), SUMA_Format(acAlphaSize, 2));
22575       fprintf(SUMA_STDERR, "\n");
22576    }
22577 
22578    SUMA_RETURN(glxCapable);
22579 }
22580 
SUMA_ClassOf(int c)22581 char * SUMA_ClassOf(int c)
22582 {
22583    static char FuncName[]={"SUMA_ClassOf"};
22584 
22585    SUMA_ENTRY;
22586 
22587    switch (c) {
22588       case StaticGray:   SUMA_RETURN("sg");
22589       case GrayScale:    SUMA_RETURN("gs");
22590       case StaticColor:  SUMA_RETURN("sc");
22591       case PseudoColor:  SUMA_RETURN("pc");
22592       case TrueColor:    SUMA_RETURN("tc");
22593       case DirectColor:  SUMA_RETURN("dc");
22594       default:           SUMA_RETURN("??");
22595    }
22596 }
22597 
SUMA_Format(int n,int w)22598 char * SUMA_Format(int n, int w)
22599 {
22600    static char FuncName[]={"SUMA_Format"};
22601    static char buffer[256];
22602    static int bufptr;
22603    char *buf;
22604 
22605    SUMA_ENTRY;
22606 
22607    if (bufptr >= sizeof(buffer) - w)
22608       bufptr = 0;
22609 
22610    buf = buffer + bufptr;
22611 
22612    if (n == 0)
22613       sprintf(buf, "%*s", w, ".");
22614    else
22615       sprintf(buf, "%*d", w, n);
22616 
22617    bufptr += w + 1;
22618 
22619    SUMA_RETURN(buf);
22620 }
22621 
22622 
SUMA_cb_CloseXformInterface(Widget w,XtPointer data,XtPointer call_data)22623 void SUMA_cb_CloseXformInterface(Widget w, XtPointer data, XtPointer call_data)
22624 {
22625    static char FuncName[] = {"SUMA_cb_CloseXformInterface"};
22626    SUMA_XFORM *xf=(SUMA_XFORM *)data;
22627    SUMA_Boolean Shaded = NOPE;
22628    SUMA_Boolean LocalHead = NOPE;
22629 
22630    SUMA_ENTRY;
22631 
22632    if (!xf->gui->AppShell) SUMA_RETURNe;
22633 
22634 
22635    if (LocalHead)
22636       fprintf (SUMA_STDERR,"%s: Withdrawing xf window...\n", FuncName);
22637 
22638    XWithdrawWindow(SUMAg_CF->X->DPY_controller1,
22639       XtWindow(xf->gui->AppShell),
22640       XScreenNumberOfScreen(XtScreen(xf->gui->AppShell)));
22641 
22642    SUMA_RETURNe;
22643 }
22644 
SUMA_cb_helpXformInterface(Widget w,XtPointer data,XtPointer call_data)22645 void SUMA_cb_helpXformInterface (Widget w, XtPointer data, XtPointer call_data)
22646 {
22647    static char FuncName[] = {"SUMA_cb_helpXformInterface"};
22648    SUMA_XFORM *xf=(SUMA_XFORM *)data;
22649    SUMA_Boolean Shaded = NOPE;
22650    DList *list = NULL;
22651    SUMA_EngineData *ED = NULL;
22652    DListElmt *NextElm = NULL;
22653    SUMA_Boolean LocalHead = NOPE;
22654 
22655    SUMA_ENTRY;
22656 
22657 
22658    if (LocalHead)
22659       fprintf (SUMA_STDERR,"%s: help for xf window...\n", FuncName);
22660 
22661 
22662    if (!list) list = SUMA_CreateList();
22663    ED = SUMA_InitializeEngineListData (SE_Help_Xform);
22664    if (!(NextElm = SUMA_RegisterEngineListCommand (  list, ED,
22665                                           SEF_vp, (void *)xf,
22666                                           SES_Suma, NULL, NOPE,
22667                                           SEI_Tail, NULL))) {
22668       fprintf (SUMA_STDERR, "Error %s: Failed to register command.\n", FuncName);
22669    }
22670    if (!SUMA_Engine (&list)) {
22671       fprintf(stderr, "Error %s: SUMA_Engine call failed.\n", FuncName);
22672    }
22673 
22674    SUMA_RETURNe;
22675 }
22676 
22677 /*!
22678    \brief Sets the widgets in the DrawROI window based on the DrawnROI structure
22679 */
SUMA_InitializeXformInterface(SUMA_XFORM * xf)22680 SUMA_Boolean SUMA_InitializeXformInterface (SUMA_XFORM *xf)
22681 {
22682    static char FuncName[] = {"SUMA_InitializeXformInterface"};
22683    char sbuf[12*SUMA_MAX_LABEL_LENGTH+12];
22684    int ii=0;
22685    SUMA_DSET *in_dset=NULL;
22686    NI_element *dotopts=NULL;
22687    SUMA_Boolean LocalHead = NOPE;
22688 
22689    SUMA_ENTRY;
22690 
22691    if (LocalHead) SUMA_DUMP_TRACE("who's calling?");
22692 
22693    if (!xf) {
22694       if (LocalHead)
22695          fprintf (SUMA_STDERR, "%s: Initializing with NULL.\n", FuncName);
22696    }else {
22697       if (LocalHead)
22698          fprintf (SUMA_STDERR,
22699                   "%s: Initializing with %p.\n", FuncName, xf);
22700 
22701       /* generic stuff */
22702       XmToggleButtonSetState( xf->gui->Active_tb, xf->active, NOPE);
22703 
22704       /* particulars */
22705       if (!strcmp(xf->name, "Dot")) {
22706          for (ii=0; ii<xf->N_parents; ++ii) {
22707             if (!SUMA_is_ID_4_DSET(xf->parents[ii], &in_dset)) {
22708                SUMA_S_Err("You've really done it this time!");
22709                SUMA_RETURN(NOPE);
22710             }
22711             if (ii==0) snprintf (sbuf, sizeof(char)*3*SUMA_MAX_LABEL_LENGTH,
22712                                  "TS Parents:\n"
22713                                  "%s", SUMA_sdset_label(in_dset));
22714             else if (ii<10)      {
22715                strcat(sbuf,"\n");
22716                strcat(sbuf,SUMA_sdset_label(in_dset));
22717             }  else {
22718                SUMA_S_Err("Fatten sbuf");
22719             }
22720          }
22721          SUMA_SET_LABEL(xf->gui->ParentLabel_lb, sbuf);
22722 
22723          if (LocalHead) SUMA_ShowNel(xf->XformOpts);
22724 
22725          if ((dotopts = SUMA_FindNgrNamedElement(xf->XformOpts, "dotopts"))) {
22726             NI_GET_FLOAT(dotopts, "filter_below", (xf->gui->AF0->value));
22727             sprintf(sbuf, "%.3f", (xf->gui->AF0->value));
22728             SUMA_SET_TEXT_FIELD(xf->gui->AF0->textfield,sbuf);
22729             NI_GET_FLOAT(dotopts, "filter_above", (xf->gui->AF1->value));
22730             sprintf(sbuf, "%.3f", xf->gui->AF1->value);
22731             SUMA_SET_TEXT_FIELD(xf->gui->AF1->textfield,sbuf);
22732             NI_GET_INT(dotopts, "polort", (xf->gui->AF2->value));
22733             sprintf(sbuf, "%d", (int)(xf->gui->AF2->value));
22734             SUMA_SET_TEXT_FIELD(xf->gui->AF2->textfield,sbuf);
22735          } else {
22736             SUMA_DUMP_TRACE("No dotopts");
22737             SUMA_S_Err("No dotopts!");
22738             SUMA_RETURN(NOPE);
22739          }
22740          if (xf->gui->ShowPreProc_tb)
22741             XmToggleButtonSetState( xf->gui->ShowPreProc_tb,
22742                                     xf->ShowPreProc, NOPE);
22743       } else {
22744          SUMA_S_Errv("Don't know how to initialize %s\n", xf->name);
22745       }
22746    }
22747    SUMA_RETURN (YUP);
22748 }
22749 
SUMA_cb_XformActive_toggled(Widget w,XtPointer data,XtPointer client_data)22750 void SUMA_cb_XformActive_toggled(Widget w, XtPointer data,
22751                                  XtPointer client_data)
22752 {
22753    static char FuncName[]={"SUMA_cb_XformActive_toggled"};
22754    SUMA_XFORM *xf=(SUMA_XFORM*)data;
22755 
22756    SUMA_ENTRY;
22757 
22758    SUMA_SetXformActive(xf, !xf->active, 1);
22759 
22760    SUMA_RETURNe;
22761 }
22762 
SUMA_cb_XformShowPreProc_toggled(Widget w,XtPointer data,XtPointer client_data)22763 void SUMA_cb_XformShowPreProc_toggled( Widget w, XtPointer data,
22764                                        XtPointer client_data)
22765 {
22766    static char FuncName[]={"SUMA_cb_XformShowPreProc_toggled"};
22767    SUMA_XFORM *xf=(SUMA_XFORM*)data;
22768 
22769    SUMA_ENTRY;
22770 
22771    SUMA_SetXformShowPreProc(xf, !xf->ShowPreProc, 1);
22772 
22773    SUMA_RETURNe;
22774 }
22775 
SUMA_CreateXformXformInterface(SUMA_XFORM * xf,Widget parent_frame)22776 void SUMA_CreateXformXformInterface(SUMA_XFORM *xf, Widget parent_frame)
22777 {
22778    static char FuncName[]={"SUMA_CreateXformXformInterface"};
22779    Widget rc, rcv;
22780    SUMA_Boolean LocalHead=NOPE;
22781 
22782    SUMA_ENTRY;
22783 
22784    /* the vertical rcv */
22785    rcv = XtVaCreateWidget ("rowcolumn",
22786          xmRowColumnWidgetClass, parent_frame,
22787          XmNorientation , XmVERTICAL ,
22788          XmNmarginHeight, 0 ,
22789          XmNmarginWidth , 0 ,
22790          NULL);
22791    /* row column to hold active button and maybe more */
22792    rc = XtVaCreateWidget ("rowcolumn",
22793          xmRowColumnWidgetClass, rcv,
22794          XmNpacking, XmPACK_TIGHT,
22795          XmNorientation , XmHORIZONTAL ,
22796          XmNmarginHeight, 0 ,
22797          XmNmarginWidth , 0 ,
22798          NULL);
22799    xf->gui->Active_tb = XtVaCreateManagedWidget("Active",
22800       xmToggleButtonWidgetClass, rc, NULL);
22801    XmToggleButtonSetState (xf->gui->Active_tb, xf->active, NOPE);
22802    XtAddCallback (xf->gui->Active_tb,
22803                   XmNvalueChangedCallback, SUMA_cb_XformActive_toggled,
22804                   (XtPointer)xf);
22805    SUMA_Register_Widget_Help(xf->gui->Active_tb , 1,
22806                              "Xform->Active",
22807                              "Activate/Suspend xform",
22808                              SUMA_ActivateXform_help ) ;
22809 
22810    /* set the toggle button's select color */
22811    SUMA_SET_SELECT_COLOR(xf->gui->Active_tb);
22812 
22813    XtManageChild(rc);
22814 
22815    XtManageChild(rcv);
22816    SUMA_RETURNe;
22817 }
22818 
SUMA_CreateXformParentsInterface(SUMA_XFORM * xf,Widget parent_frame)22819 void SUMA_CreateXformParentsInterface(SUMA_XFORM *xf, Widget parent_frame)
22820 {
22821    static char FuncName[]={"SUMA_CreateXformParentsInterface"};
22822    Widget rc, rcv;
22823    SUMA_Boolean LocalHead=NOPE;
22824 
22825    SUMA_ENTRY;
22826 
22827    /* the vertical rcv */
22828    rcv = XtVaCreateWidget ("rowcolumn",
22829          xmRowColumnWidgetClass, parent_frame,
22830          XmNorientation , XmVERTICAL ,
22831          XmNmarginHeight, 0 ,
22832          XmNmarginWidth , 0 ,
22833          NULL);
22834 
22835    /* row column to hold parent name and maybe more*/
22836    rc = XtVaCreateWidget ("rowcolumn",
22837          xmRowColumnWidgetClass, rcv,
22838          XmNpacking, XmPACK_TIGHT,
22839          XmNorientation , XmHORIZONTAL ,
22840          XmNmarginHeight, 0 ,
22841          XmNmarginWidth , 0 ,
22842          NULL);
22843    if ( !strcmp(xf->name,"Dot") ) { /* Dot xform */
22844       xf->gui->ParentLabel_lb =
22845          XtVaCreateManagedWidget ("TS Parents:      N/A \n"
22846                                   "                 N/A \n",
22847             xmLabelWidgetClass, rc,
22848             NULL);
22849       SUMA_Register_Widget_Help(xf->gui->ParentLabel_lb , 1,
22850                                 "Dot->Xform->datasets->TS_Parents",
22851                                 "Label of time series dsets transformed",
22852                                 SUMA_DotXform_ParentLabel_help ) ;
22853    } else {
22854       SUMA_S_Errv("Don't know how to build xform parent interface for %s\n",
22855                   xf->name);
22856       SUMA_RETURNe;
22857    }
22858    XtManageChild(rc);
22859 
22860    if (!strcmp(xf->name,"Dot")) {
22861       /* Show intermediate dsets? */
22862       rc = XtVaCreateWidget ("rowcolumn",
22863             xmRowColumnWidgetClass, rcv,
22864             XmNpacking, XmPACK_TIGHT,
22865             XmNorientation , XmHORIZONTAL ,
22866             XmNmarginHeight, 0 ,
22867             XmNmarginWidth , 0 ,
22868             NULL);
22869 
22870       XtVaCreateManagedWidget ("Preprocessed Dsets:",
22871                xmLabelWidgetClass, rc,
22872                NULL);
22873 
22874       /* a save button for preprocessed dsets */
22875       xf->gui->SavePreProc_pb = XtVaCreateWidget ("Save",
22876                                            xmPushButtonWidgetClass, rc,
22877                                            NULL);
22878       XtAddCallback (xf->gui->SavePreProc_pb,
22879                      XmNactivateCallback,
22880                      SUMA_cb_XformPreProc_Save, (XtPointer)xf);
22881       SUMA_Register_Widget_Help(xf->gui->SavePreProc_pb ,1,
22882                                 "Dot->Xform->datasets->Save",
22883                         "Save the preprocessed dsets to disk.",
22884                                 SUMA_XformPreProc_Save_help ) ;
22885       XtManageChild (xf->gui->SavePreProc_pb);
22886 
22887       #if 0 /* complicated, see comment in SUMA_SetXformShowPreProc*/
22888       xf->gui->ShowPreProc_tb = XtVaCreateManagedWidget("Show Intermediate",
22889          xmToggleButtonWidgetClass, rc, NULL);
22890       XmToggleButtonSetState (xf->gui->ShowPreProc_tb, xf->ShowPreProc, NOPE);
22891       XtAddCallback (xf->gui->ShowPreProc_tb,
22892                      XmNvalueChangedCallback, SUMA_cb_XformShowPreProc_toggled,
22893                      (XtPointer)xf);
22894       SUMA_Register_Widget_Help(xf->gui->ShowPreProc_tb , 1,
22895                                 "Dot->Xform->UNUSED->Show_Intermediate",
22896                                 "Make visible preprocessed dsets",
22897                                 SUMA_ShowPreProcXform_help ) ;
22898 
22899       /* set the toggle button's select color */
22900       SUMA_SET_SELECT_COLOR(xf->gui->ShowPreProc_tb);
22901       #endif
22902 
22903       XtManageChild(rc);
22904 
22905    }else {
22906       SUMA_S_Errv("Don't know how to build xform parent interface for %s\n",
22907                   xf->name);
22908       SUMA_RETURNe;
22909    }
22910    XtManageChild(rc);
22911 
22912 
22913 
22914    XtManageChild(rcv);
22915    SUMA_RETURNe;
22916 }
22917 
22918 
SUMA_DotXform_NewBandPass(SUMA_XFORM * xf,float lf,float uf,int fromgui)22919 void SUMA_DotXform_NewBandPass(  SUMA_XFORM *xf,
22920                                  float lf, float uf,
22921                                  int fromgui)
22922 {
22923    static char FuncName[]={"SUMA_DotXform_NewBandPass"};
22924    NI_element *dotopts=NULL;
22925    char sbuf[256];
22926    int ii;
22927    float ouf=0.0, olf=0.0;
22928    SUMA_Boolean LocalHead = NOPE;
22929 
22930    SUMA_ENTRY;
22931 
22932    if (lf > uf) {
22933       SUMA_S_Err("Bad range");
22934       SUMA_RETURNe;
22935    }
22936 
22937    if (!(dotopts = SUMA_FindNgrNamedElement(xf->XformOpts, "dotopts"))) {
22938       SUMA_S_Err("Failed to find dotopts");
22939       SUMA_RETURNe;
22940    }
22941 
22942    NI_GET_FLOAT(dotopts,"filter_below", olf);
22943    NI_GET_FLOAT(dotopts,"filter_above", ouf);
22944 
22945    if (olf == lf && ouf == uf) {
22946       SUMA_LH("Nothing to do");
22947       SUMA_RETURNe;
22948    } else {
22949       SUMA_LHv("%f %f\n%f %f\n",
22950                      olf, lf, ouf, uf);
22951    }
22952 
22953    NI_SET_FLOAT(dotopts,"filter_below", lf);
22954    NI_SET_FLOAT(dotopts,"filter_above", uf);
22955 
22956    if (!fromgui && xf->gui) {
22957       xf->gui->AF0->value = lf;
22958       sprintf(sbuf, "%.3f", lf);
22959       SUMA_SET_TEXT_FIELD(xf->gui->AF0->textfield,sbuf);
22960       xf->gui->AF1->value = uf;
22961       sprintf(sbuf, "%.3f", uf);
22962       SUMA_SET_TEXT_FIELD(xf->gui->AF1->textfield,sbuf);
22963    }
22964 
22965    for (ii=0; ii<xf->N_parents; ++ii)
22966       SUMA_DotXform_SetPending (dotopts, 1, xf->parents[ii]);
22967 
22968 
22969    SUMA_RETURNe;
22970 }
22971 
SUMA_OpenXformOrtFile(char * filename,void * data)22972 void SUMA_OpenXformOrtFile (char *filename, void *data)
22973 {
22974    static char FuncName[]={"SUMA_OpenXformOrtFile"};
22975    SUMA_XFORM *xf=(SUMA_XFORM *)data;
22976    SUMA_Boolean LocalHead = NOPE;
22977 
22978    SUMA_ENTRY;
22979 
22980    if (!xf) {
22981       SUMA_S_Err("NULL input");
22982    }
22983    if (!strcmp(xf->name,"Dot")) {
22984       SUMA_DotXform_NewOrtName( xf,
22985                                filename,
22986                                1 );
22987    } else {
22988       SUMA_S_Err("Dunno what to do");
22989    }
22990 
22991 
22992    SUMA_RETURNe;
22993 }
22994 
SUMA_DotXform_NewPolort(SUMA_XFORM * xf,int polort,int fromgui)22995 void SUMA_DotXform_NewPolort(  SUMA_XFORM *xf,
22996                                int polort,
22997                                int fromgui)
22998 {
22999    static char FuncName[]={"SUMA_DotXform_NewPolort"};
23000    NI_element *dotopts=NULL;
23001    char sbuf[256];
23002    int ii=0, opolort=0;
23003    SUMA_DSET *in_dset=NULL;
23004    SUMA_Boolean LocalHead = NOPE;
23005 
23006    SUMA_ENTRY;
23007 
23008    if (polort < -1) {
23009       SUMA_S_Err("Bad val");
23010       SUMA_RETURNe;
23011    }
23012 
23013    if (!(dotopts = SUMA_FindNgrNamedElement(xf->XformOpts, "dotopts"))) {
23014       SUMA_S_Err("Failed to find dotopts");
23015       SUMA_RETURNe;
23016    }
23017 
23018    NI_GET_INT(dotopts,"polort", opolort);
23019    if (polort == opolort) { /* nothing to do */
23020       SUMA_LH("Nothing to do");
23021       SUMA_RETURNe;
23022    } else {
23023       SUMA_LHv("%d %d\n", opolort, polort);
23024    }
23025 
23026    NI_SET_INT(dotopts,"polort", polort);
23027 
23028    if (!fromgui && xf->gui) {
23029       xf->gui->AF2->value = polort;
23030       sprintf(sbuf, "%d", polort);
23031       SUMA_SET_TEXT_FIELD(xf->gui->AF2->textfield,sbuf);
23032    }
23033 
23034    /* recalculate polorts */
23035    if (!(SUMA_is_ID_4_DSET(xf->parents[0], &in_dset))) {
23036       SUMA_S_Err("Could not find ts dset");
23037       SUMA_RETURNe;
23038    }
23039    if (!SUMA_DotXform_MakeOrts( dotopts, SDSET_VECNUM(in_dset),
23040                                 polort, NI_get_attribute(dotopts,"ortname"))){
23041       SUMA_S_Err("Failed to make orts");
23042       SUMA_RETURNe;
23043    }
23044 
23045 
23046    for (ii=0; ii<xf->N_parents; ++ii)
23047       SUMA_DotXform_SetPending (dotopts, 1, xf->parents[ii]);
23048 
23049 
23050    SUMA_RETURNe;
23051 }
23052 
SUMA_DotXform_NewOrtName(SUMA_XFORM * xf,char * ortname,int fromgui)23053 void SUMA_DotXform_NewOrtName(  SUMA_XFORM *xf,
23054                                char * ortname,
23055                                int fromgui)
23056 {
23057    static char FuncName[]={"SUMA_DotXform_NewOrtName"};
23058    NI_element *dotopts=NULL;
23059    char sbuf[256];
23060    int ii=0, polort=-3;
23061    SUMA_DSET *in_dset=NULL;
23062    SUMA_Boolean LocalHead=NOPE;
23063 
23064    SUMA_ENTRY;
23065 
23066    if (!(dotopts = SUMA_FindNgrNamedElement(xf->XformOpts, "dotopts"))) {
23067       SUMA_S_Err("Failed to find dotopts");
23068       SUMA_RETURNe;
23069    }
23070 
23071    SUMA_LHv("Setting ortname to %s\n", ortname);
23072    NI_set_attribute(dotopts,"ortname", ortname);
23073 
23074    if (xf->gui) {
23075       if (ortname) {
23076          SUMA_PARSED_NAME *pn = SUMA_ParseFname(ortname, SUMAg_CF->cwd);
23077          SUMA_SET_LABEL(xf->gui->OrtFileLabel_lb, pn->FileName);
23078          SUMA_Free_Parsed_Name(pn); pn = NULL;
23079       } else {
23080          SUMA_SET_LABEL(xf->gui->OrtFileLabel_lb, "--");
23081       }
23082    }
23083 
23084    /* recalculate polorts */
23085    if (!(SUMA_is_ID_4_DSET(xf->parents[0], &in_dset))) {
23086       SUMA_S_Err("Could not find ts dset");
23087       SUMA_RETURNe;
23088    }
23089    NI_GET_INT(dotopts,"polort", polort);
23090    if (!SUMA_DotXform_MakeOrts( dotopts, SDSET_VECNUM(in_dset),
23091                                 polort, ortname)){
23092       SUMA_S_Err("Failed to make orts");
23093       SUMA_RETURNe;
23094    }
23095 
23096 
23097    for (ii=0; ii<xf->N_parents; ++ii)
23098       SUMA_DotXform_SetPending (dotopts, 1, xf->parents[ii]);
23099 
23100 
23101    SUMA_RETURNe;
23102 }
23103 
SUMA_Xform_NewAF0(void * data)23104 void SUMA_Xform_NewAF0 (void *data)
23105 {
23106    static char FuncName[]={"SUMA_Xform_NewAF0"};
23107    SUMA_XFORM *xf=(SUMA_XFORM *)data;
23108    char sbuf[128];
23109 
23110    SUMA_ENTRY;
23111 
23112    if (!strcmp(xf->name,"Dot")) {
23113       if (xf->gui->AF0->value > xf->gui->AF1->value) {/* bad range*/
23114          xf->gui->AF0->value = xf->gui->AF1->value;
23115          sprintf(sbuf, "%.3f", xf->gui->AF0->value);
23116          SUMA_SET_TEXT_FIELD(xf->gui->AF0->textfield,sbuf);
23117          SUMA_RETURNe;
23118       }
23119 
23120       SUMA_DotXform_NewBandPass( xf, xf->gui->AF0->value,
23121                                  xf->gui->AF1->value , 1);
23122    } else {
23123       SUMA_S_Errv("Don't know how to process xform %s\n", xf->name);
23124    }
23125 
23126    SUMA_RETURNe;
23127 }
23128 
SUMA_Xform_NewAF1(void * data)23129 void SUMA_Xform_NewAF1 (void *data)
23130 {
23131    static char FuncName[]={"SUMA_Xform_NewAF1"};
23132    SUMA_XFORM *xf=(SUMA_XFORM *)data;
23133    char sbuf[128];
23134 
23135    SUMA_ENTRY;
23136 
23137    if (!strcmp(xf->name,"Dot")) {
23138       if (xf->gui->AF1->value < xf->gui->AF0->value) {/* bad range*/
23139          xf->gui->AF1->value = xf->gui->AF0->value;
23140          sprintf(sbuf, "%.3f", xf->gui->AF1->value);
23141          SUMA_SET_TEXT_FIELD(xf->gui->AF1->textfield,sbuf);
23142          SUMA_RETURNe;
23143       }
23144       SUMA_DotXform_NewBandPass( xf, xf->gui->AF0->value,
23145                                  xf->gui->AF1->value , 1);
23146    } else {
23147       SUMA_S_Errv("Don't know how to process xform %s\n", xf->name);
23148    }
23149 
23150    SUMA_RETURNe;
23151 }
23152 
SUMA_Xform_NewAF2(void * data)23153 void SUMA_Xform_NewAF2 (void *data)
23154 {
23155    static char FuncName[]={"SUMA_Xform_NewAF2"};
23156    SUMA_XFORM *xf=(SUMA_XFORM *)data;
23157    char sbuf[128];
23158 
23159    SUMA_ENTRY;
23160 
23161    if (!strcmp(xf->name,"Dot")) {
23162       SUMA_DotXform_NewPolort( xf, xf->gui->AF2->value, 1);
23163    } else {
23164       SUMA_S_Errv("Don't know how to process xform %s\n", xf->name);
23165    }
23166 
23167    SUMA_RETURNe;
23168 }
23169 
23170 
SUMA_cb_XformOpts_Apply(Widget w,XtPointer data,XtPointer client_data)23171 void SUMA_cb_XformOpts_Apply (Widget w, XtPointer data,
23172                              XtPointer client_data)
23173 {
23174    static char FuncName[]={"SUMA_cb_XformOpts_Apply"};
23175    SUMA_XFORM *xf=(SUMA_XFORM*)data;
23176    NI_element *nelpars=NULL;
23177    SUMA_Boolean LocalHead = NOPE;
23178 
23179    SUMA_ENTRY;
23180 
23181    if (!strcmp(xf->name,"Dot")) {
23182       SUMA_CALLBACK *cb=NULL;
23183       DListElmt *el=NULL;
23184       DList *lst = SUMAg_CF->callbacks;
23185       if (!lst) SUMA_RETURNe;
23186       el = dlist_head(lst);
23187       while (el && !cb) {
23188          cb = (SUMA_CALLBACK *)el->data;
23189          if (!strcmp(cb->creator_xform, xf->idcode_str)) {
23190             SUMA_SetCallbackPending(cb, 1, SES_Suma);
23191             if (( nelpars=
23192                    SUMA_FindNgrNamedElement(
23193                      cb->FunctionInput, "event_parameters"))) {
23194                /* put the last events back in */
23195                SUMA_XFORM_RETRIEVE_LAST_EVENT(nelpars);
23196                if (!SUMA_ExecuteCallback(cb, 1, NULL, 1)) {
23197                   SUMA_S_Err("Failed executing callback");
23198                }
23199             }
23200          }
23201          el = dlist_next(el);
23202       }
23203    } else {
23204       SUMA_S_Errv("Don't know what to do for this %s xform", xf->name);
23205       SUMA_RETURNe;
23206    }
23207 
23208    SUMA_RETURNe;
23209 }
23210 
SUMA_cb_XformOpts_Save(Widget w,XtPointer data,XtPointer client_data)23211 void SUMA_cb_XformOpts_Save (Widget w, XtPointer data,
23212                              XtPointer client_data)
23213 {
23214    static char FuncName[]={"SUMA_cb_XformOpts_Save"};
23215    SUMA_XFORM *xf=(SUMA_XFORM*)data;
23216    DList *list = NULL;
23217    SUMA_EngineData *ED = NULL;
23218    DListElmt *NextElm = NULL;
23219    SUMA_Boolean LocalHead = NOPE;
23220 
23221    SUMA_ENTRY;
23222 
23223    if (!list) list = SUMA_CreateList();
23224    ED = SUMA_InitializeEngineListData (SE_SaveXformOptsFileSelection);
23225    if (!(NextElm = SUMA_RegisterEngineListCommand (  list, ED,
23226                                           SEF_vp, (void *)xf,
23227                                           SES_Suma, NULL, NOPE,
23228                                           SEI_Head, NULL))) {
23229       fprintf (SUMA_STDERR, "Error %s: Failed to register command.\n", FuncName);
23230    }
23231    if (!SUMA_RegisterEngineListCommand (  list, ED,
23232                                           SEF_ip, (int *)w,
23233                                           SES_Suma, NULL, NOPE,
23234                                           SEI_In, NextElm)) {
23235       fprintf (SUMA_STDERR, "Error %s: Failed to register command.\n", FuncName);
23236    }
23237 
23238    if (!SUMA_Engine (&list)) {
23239       fprintf(SUMA_STDERR, "Error %s: SUMA_Engine call failed.\n", FuncName);
23240    }
23241 
23242    SUMA_RETURNe;
23243 }
23244 
SUMA_SaveXformPreProcDsets(SUMA_XFORM * xf,char * prefix)23245 SUMA_Boolean SUMA_SaveXformPreProcDsets (SUMA_XFORM *xf, char *prefix)
23246 {
23247    static char FuncName[]={"SUMA_SaveXformPreProcDsets"};
23248    char *fn=NULL, *fno=NULL, *oid=NULL, *ofn=NULL;
23249    int ii;
23250    NI_element *dotopt=NULL;
23251    SUMA_DSET *in_dset=NULL, *pp_dset=NULL;
23252    SUMA_Boolean LocalHead = NOPE;
23253 
23254    SUMA_ENTRY;
23255 
23256    if (!strcmp(xf->name,"Dot")) {
23257       if (!(dotopt = SUMA_FindNgrNamedElement(xf->XformOpts, "dotopts"))) {
23258          SUMA_S_Err("dotopt not found");
23259          SUMA_RETURN(NOPE);
23260       }
23261       for (ii=0; ii<xf->N_parents; ++ii) {
23262          if (!SUMA_is_ID_4_DSET(xf->parents[ii], &in_dset)) {
23263             SUMA_S_Err("No parent");
23264             SUMA_RETURN(NOPE);
23265          }
23266          if (!(pp_dset = SUMA_GetDotPreprocessedDset(in_dset, dotopt))){
23267             SUMA_S_Err("PreProcParent not found");
23268             SUMA_RETURN(NOPE);
23269          }
23270          fn = SUMA_append_replace_string(prefix,SDSET_LABEL(in_dset),
23271                                          "", 0);
23272          fno = SUMA_WriteDset_PreserveID(fn, pp_dset, SUMA_BINARY_NIML,1,1);
23273          if (fno) fprintf(stderr,"Saved %s\n", fno);
23274          else fprintf(stderr,"Failed to save\n");
23275 
23276          SUMA_free(fn); fn=NULL;
23277          SUMA_free(fno); fno=NULL;
23278       }
23279    } else {
23280       SUMA_S_Errv("Can't do %s\n", xf->name);
23281       SUMA_RETURN(NOPE);
23282    }
23283    SUMA_RETURN(YUP);
23284 }
23285 
SUMA_cb_XformPreProc_Save(Widget w,XtPointer data,XtPointer client_data)23286 void SUMA_cb_XformPreProc_Save (Widget w, XtPointer data,
23287                              XtPointer client_data)
23288 {
23289    static char FuncName[]={"SUMA_cb_XformPreProc_Save"};
23290    SUMA_XFORM *xf=(SUMA_XFORM*)data;
23291    DList *list = NULL;
23292    SUMA_EngineData *ED = NULL;
23293    DListElmt *NextElm = NULL;
23294    SUMA_Boolean LocalHead = NOPE;
23295 
23296    SUMA_ENTRY;
23297 
23298    SUMA_SaveXformPreProcDsets(xf, "pp");
23299 
23300    SUMA_RETURNe;
23301 }
23302 
SUMA_cb_XformOrtFile_Load(Widget w,XtPointer data,XtPointer client_data)23303 void SUMA_cb_XformOrtFile_Load(Widget w, XtPointer data, XtPointer client_data)
23304 {
23305    static char FuncName[]={"SUMA_cb_XformOrtFile_Load"};
23306    DList *list = NULL;
23307    SUMA_EngineData *ED = NULL;
23308    DListElmt *NextElm = NULL;
23309    SUMA_XFORM *xf=(SUMA_XFORM*)data;
23310    SUMA_Boolean LocalHead = NOPE;
23311 
23312    SUMA_ENTRY;
23313 
23314    if (!xf) { SUMA_S_Err("what gives?"); SUMA_RETURNe;}
23315    SUMA_LHv("Loading ort for %s\n", xf->name);
23316 
23317    if (!list) list = SUMA_CreateList();
23318    ED = SUMA_InitializeEngineListData (SE_OpenXformOrtFileFileSelection);
23319    if (!(NextElm = SUMA_RegisterEngineListCommand (  list, ED,
23320                                           SEF_vp, (XtPointer)xf,
23321                                           SES_Suma, NULL, NOPE,
23322                                           SEI_Head, NULL))) {
23323       fprintf (SUMA_STDERR,
23324                "Error %s: Failed to register command.\n", FuncName);
23325    }
23326    if (!SUMA_RegisterEngineListCommand (  list, ED,
23327                                           SEF_ip, (int *)w,
23328                                           SES_Suma, NULL, NOPE,
23329                                           SEI_In, NextElm)) {
23330       fprintf (SUMA_STDERR,
23331                "Error %s: Failed to register command.\n", FuncName);
23332    }
23333 
23334    if (!SUMA_Engine (&list)) {
23335       fprintf(SUMA_STDERR, "Error %s: SUMA_Engine call failed.\n", FuncName);
23336    }
23337 
23338    SUMA_RETURNe;
23339 }
23340 
SUMA_CreateXformOptionsInterface(SUMA_XFORM * xf,Widget parent_frame)23341 void SUMA_CreateXformOptionsInterface(SUMA_XFORM *xf, Widget parent_frame)
23342 {
23343    static char FuncName[]={"SUMA_CreateXformOptionsInterface"};
23344    Widget rc, rcv;
23345    float fs, fmax, fstep;
23346    double TR;
23347    int N_TS;
23348    XmString xmstmp;
23349    SUMA_DSET *in_dset=NULL;
23350 
23351    SUMA_ENTRY;
23352 
23353    /* the vertical rcv */
23354    rcv = XtVaCreateWidget ("rowcolumn",
23355          xmRowColumnWidgetClass, parent_frame,
23356          XmNorientation , XmVERTICAL ,
23357          XmNmarginHeight, 0 ,
23358          XmNmarginWidth , 0 ,
23359          NULL);
23360 
23361    if ( !strcmp(xf->name,"Dot") ) { /* Dot xform */
23362       rc = XtVaCreateWidget ("rowcolumn",
23363             xmRowColumnWidgetClass, rcv,
23364             XmNpacking, XmPACK_TIGHT,
23365             XmNorientation , XmHORIZONTAL ,
23366             XmNmarginHeight, 0 ,
23367             XmNmarginWidth , 0 ,
23368             NULL);
23369       /* put a label in this rc*/
23370       XtVaCreateManagedWidget ("Band Pass Range (Hz.)",
23371                xmLabelWidgetClass, rc,
23372                NULL);
23373       XtManageChild(rc);
23374 
23375       /* row column to hold bandpass options  and maybe more */
23376       rc = XtVaCreateWidget ("rowcolumn",
23377             xmRowColumnWidgetClass, rcv,
23378             XmNpacking, XmPACK_TIGHT,
23379             XmNorientation , XmHORIZONTAL ,
23380             XmNmarginHeight, 0 ,
23381             XmNmarginWidth , 0 ,
23382             NULL);
23383 
23384 
23385       /* find some params from parent dsets */
23386       if (!(SUMA_is_ID_4_DSET(xf->parents[0],
23387                               &in_dset))) {
23388          SUMA_S_Err("Could not find parent dset");
23389          SUMA_RETURNe;
23390       }
23391       if (!(SUMA_is_TimeSeries_dset(in_dset, &TR))) {
23392          TR = 0.0;
23393       }
23394 
23395       SUMA_SPECT_AXIS(TR,SDSET_VECNUM(in_dset),  fs, fmax,fstep);
23396 
23397       SUMA_CreateArrowField ( rc, "LF",
23398                         0.01, 0.0, fmax, fstep,
23399                         6, SUMA_float,
23400                         NOPE,
23401                         SUMA_Xform_NewAF0, (void *)xf,
23402                         "Dot->options->LF",
23403                         SUMA_DotXform_AF0_hint,
23404                         SUMA_DotXform_AF0_help,
23405                         xf->gui->AF0);
23406       SUMA_CreateArrowField ( rc, "HF",
23407                         fmax > 0.1 ? 0.1:fmax, 0.0, 1.0, fstep,
23408                         6, SUMA_float,
23409                         NOPE,
23410                         SUMA_Xform_NewAF1, (void *)xf,
23411                         "Dot->options->HF",
23412                         SUMA_DotXform_AF1_hint,
23413                         SUMA_DotXform_AF1_help,
23414                         xf->gui->AF1);
23415 
23416       XtManageChild(rc);
23417 
23418       /* row column to hold polort options and maybe more*/
23419       rc = XtVaCreateWidget ("rowcolumn",
23420             xmRowColumnWidgetClass, rcv,
23421             XmNpacking, XmPACK_TIGHT,
23422             XmNorientation , XmHORIZONTAL ,
23423             XmNmarginHeight, 0 ,
23424             XmNmarginWidth , 0 ,
23425             NULL);
23426 
23427       SUMA_CreateArrowField ( rc, "polort",
23428                         /* 0, -1, SDSET_VECNUM(in_dset)/2,  */
23429                         2,2,2, /* for now keep it frozen, till you figure out
23430                                   how to turn off bandpassing when polort is
23431                                   used.  */
23432                         1,
23433                         3, SUMA_int,
23434                         NOPE,
23435                         SUMA_Xform_NewAF2, (void *)xf,
23436                         "Dot->options->polort",
23437                         SUMA_DotXform_AF2_hint,
23438                         SUMA_DotXform_AF2_help,
23439                         xf->gui->AF2);
23440       XtManageChild(rc);
23441       XtSetSensitive(rc, 0);
23442 
23443       rc = XtVaCreateWidget ("rowcolumn",
23444             xmRowColumnWidgetClass, rcv,
23445             XmNpacking, XmPACK_TIGHT,
23446             XmNorientation , XmHORIZONTAL ,
23447             XmNmarginHeight, 0 ,
23448             XmNmarginWidth , 0 ,
23449             NULL);
23450 
23451       xf->gui->LoadOrtFile_pb = XtVaCreateWidget ("OrtFile",
23452                                     xmPushButtonWidgetClass, rc,
23453                                     NULL);
23454       XtAddCallback (xf->gui->LoadOrtFile_pb,
23455                      XmNactivateCallback, SUMA_cb_XformOrtFile_Load,
23456                      (XtPointer)xf);
23457       SUMA_Register_Widget_Help(xf->gui->LoadOrtFile_pb , 1,
23458                                 "Dot->options->OrtFile",
23459                                 "Load an ort file",
23460                                 SUMA_XformOrtFile_Load_help ) ;
23461       XtManageChild (xf->gui->LoadOrtFile_pb);
23462 
23463       xmstmp = XmStringCreateLtoR ("no ort file loaded",
23464                                     XmSTRING_DEFAULT_CHARSET);
23465       xf->gui->OrtFileLabel_lb = XtVaCreateManagedWidget (
23466                "orti",
23467                xmLabelWidgetClass, rc,
23468                XmNlabelString, xmstmp,
23469                NULL);
23470       XmStringFree (xmstmp); xmstmp=NULL;
23471 
23472       XtManageChild(rc);
23473 
23474       rc = XtVaCreateWidget ("rowcolumn",
23475             xmRowColumnWidgetClass, rcv,
23476             XmNpacking, XmPACK_TIGHT,
23477             XmNorientation , XmHORIZONTAL ,
23478             XmNmarginHeight, 0 ,
23479             XmNmarginWidth , 0 ,
23480             NULL);
23481 
23482       XtVaCreateManagedWidget ("Options:",
23483                xmLabelWidgetClass, rc,
23484                NULL);
23485 
23486       xf->gui->SaveOpts_pb = XtVaCreateWidget ("Save",
23487                                            xmPushButtonWidgetClass, rc,
23488                                            NULL);
23489       XtAddCallback (xf->gui->SaveOpts_pb,
23490                      XmNactivateCallback,
23491                      SUMA_cb_XformOpts_Save, (XtPointer)xf);
23492       SUMA_Register_Widget_Help(xf->gui->SaveOpts_pb , 1,
23493                                 "Dot->options->Options->Save",
23494                                 "Save the options to disk.",
23495                                 SUMA_XformOpts_Save_help ) ;
23496       XtManageChild (xf->gui->SaveOpts_pb);
23497 
23498       xf->gui->ApplyOpts_pb = XtVaCreateWidget ("Apply",
23499                                        xmPushButtonWidgetClass, rc,
23500                                        NULL);
23501       XtAddCallback (xf->gui->ApplyOpts_pb,
23502                      XmNactivateCallback,
23503                      SUMA_cb_XformOpts_Apply, (XtPointer)xf);
23504       SUMA_Register_Widget_Help(xf->gui->ApplyOpts_pb, 1,
23505                                 "Dot->options->Options->Apply",
23506                                 "Apply the options immediately",
23507                                 SUMA_XformOpts_Apply_help ) ;
23508       XtManageChild (xf->gui->ApplyOpts_pb);
23509 
23510       XtManageChild(rc);
23511 
23512 
23513    } else {
23514       SUMA_S_Errv("Don't know how to build xform parent interface for %s\n",
23515                   xf->name);
23516       SUMA_RETURNe;
23517    }
23518 
23519    XtManageChild(rcv);
23520 
23521    SUMA_RETURNe;
23522 }
23523 
SUMA_CreateXformInterface(SUMA_XFORM * xf)23524 void SUMA_CreateXformInterface(SUMA_XFORM *xf)
23525 {
23526    static char FuncName[]={"SUMA_CreateXformInterface"};
23527    Widget cb_frame, opts_frame, frame_rcv, form, parent_frame, xform_frame;
23528    int i;
23529    char *sss;
23530    SUMA_Boolean LocalHead = NOPE;
23531 
23532    SUMA_ENTRY;
23533 
23534    if (xf->gui) SUMA_RETURNe;
23535 
23536    xf->gui = SUMA_NewXformInterface(NULL);
23537 
23538    if (SUMA_isEnv("SUMA_SurfContFontSize", "BIG")) {
23539       sss = "font9";
23540    } else {
23541       sss = "font8";
23542    }
23543 
23544    /* generic parts */
23545    xf->gui->AppShell = XtVaAppCreateShell(sss , "Suma" ,
23546                                           topLevelShellWidgetClass ,
23547                                           SUMAg_CF->X->DPY_controller1 ,
23548                                           XmNtitle, xf->name,
23549                                           NULL ) ;
23550 
23551    /* turn off default delete response.
23552       If you do not do that, you will suffer.*/
23553    XtVaSetValues( xf->gui->AppShell,
23554            XmNdeleteResponse, XmDO_NOTHING,
23555            NULL);
23556 
23557    /* handle the close button from window manager */
23558    XmAddWMProtocolCallback(/* make "Close" window menu work */
23559       xf->gui->AppShell,
23560       XmInternAtom( SUMAg_CF->X->DPY_controller1, "WM_DELETE_WINDOW" , False ) ,
23561       SUMA_cb_CloseXformInterface, (XtPointer)xf) ;
23562 
23563    /* create a form widget, manage it at the end ...*/
23564    form = XtVaCreateWidget ("dialog",
23565       xmFormWidgetClass, xf->gui->AppShell,
23566       XmNborderWidth , 2 ,
23567       XmNmarginHeight , SUMA_MARGIN ,
23568       XmNmarginWidth  , SUMA_MARGIN ,
23569       XmNshadowThickness, 2,
23570       XmNshadowType, XmSHADOW_ETCHED_IN,
23571       NULL);
23572 
23573    /* a vertical rc to put multiple frames in */
23574    frame_rcv = XtVaCreateWidget ("rowcolumn",
23575          xmRowColumnWidgetClass, form,
23576          XmNorientation , XmVERTICAL ,
23577          XmNmarginHeight, 0 ,
23578          XmNmarginWidth , 0 ,
23579          NULL);
23580 
23581 
23582    /* a frame for xform general buttons */
23583    xform_frame = XtVaCreateWidget ("dialog",
23584       xmFrameWidgetClass, frame_rcv,
23585       XmNleftAttachment , XmATTACH_FORM ,
23586       XmNtopAttachment  , XmATTACH_FORM ,
23587       XmNshadowType , XmSHADOW_ETCHED_IN ,
23588       XmNshadowThickness , 5 ,
23589       XmNtraversalOn , False ,
23590       NULL);
23591    XtVaCreateManagedWidget ("xform",
23592       xmLabelWidgetClass, xform_frame,
23593       XmNchildType, XmFRAME_TITLE_CHILD,
23594       XmNchildHorizontalAlignment, XmALIGNMENT_BEGINNING,
23595       NULL);
23596 
23597    /* populate the xform frame based on the type of xform */
23598    SUMA_CreateXformXformInterface(xf,xform_frame);
23599 
23600    XtManageChild (xform_frame);
23601 
23602    /* a frame to put parent datasets stuff in */
23603    parent_frame = XtVaCreateWidget ("dialog",
23604       xmFrameWidgetClass, frame_rcv,
23605       XmNleftAttachment , XmATTACH_FORM ,
23606       XmNtopAttachment  , XmATTACH_FORM ,
23607       XmNshadowType , XmSHADOW_ETCHED_IN ,
23608       XmNshadowThickness , 5 ,
23609       XmNtraversalOn , False ,
23610       NULL);
23611 
23612    XtVaCreateManagedWidget ("datasets",
23613       xmLabelWidgetClass, parent_frame,
23614       XmNchildType, XmFRAME_TITLE_CHILD,
23615       XmNchildHorizontalAlignment, XmALIGNMENT_BEGINNING,
23616       NULL);
23617 
23618    /* populate the datasets frame based on the type of xform */
23619    SUMA_CreateXformParentsInterface(xf,parent_frame);
23620 
23621    XtManageChild (parent_frame);
23622 
23623    /* a frame to put options in */
23624    opts_frame = XtVaCreateWidget ("dialog",
23625       xmFrameWidgetClass, frame_rcv,
23626       XmNleftAttachment , XmATTACH_FORM ,
23627       XmNtopAttachment  , XmATTACH_FORM ,
23628       XmNshadowType , XmSHADOW_ETCHED_IN ,
23629       XmNshadowThickness , 5 ,
23630       XmNtraversalOn , False ,
23631       NULL);
23632    XtVaCreateManagedWidget ("options",
23633       xmLabelWidgetClass, opts_frame,
23634       XmNchildType, XmFRAME_TITLE_CHILD,
23635       XmNchildHorizontalAlignment, XmALIGNMENT_BEGINNING,
23636       NULL);
23637 
23638    /* populate the opts frame based on the type of xform */
23639 
23640    SUMA_CreateXformOptionsInterface(xf,opts_frame);
23641 
23642    XtManageChild (opts_frame);
23643 
23644    /* the close, bhelp deal */
23645    cb_frame = SUMA_CloseBhelp_Frame( frame_rcv,
23646                               SUMA_cb_CloseXformInterface,
23647                               (XtPointer) xf,
23648                               "Dot",
23649                               "Close Xform controller",
23650                               SUMA_closeXformCont_help,
23651                               SUMA_cb_helpXformInterface,
23652                               (XtPointer) xf,
23653                               "Help on using this transform's interface",
23654                               SUMA_helpXformCont_help);
23655 
23656    /* manage the frame rcv */
23657    XtManageChild (frame_rcv);
23658 
23659    /* manage the form */
23660    XtManageChild (form);
23661 
23662    /* position the widget relative to the first open viewer */
23663    i=0;
23664    while (  i < SUMAg_N_SVv &&
23665             !SUMAg_SVv[i].X->ViewCont->TopLevelShell &&
23666             SUMAg_SVv[i].isShaded) ++i;
23667 
23668    if (i < SUMAg_N_SVv) {
23669       if (LocalHead) fprintf (SUMA_STDERR, "%s: i = %d\n", FuncName, i);
23670       SUMA_PositionWindowRelative ( xf->gui->AppShell,
23671                                     SUMAg_SVv[i].X->TOPLEVEL, SWP_TOP_RIGHT);
23672    }
23673 
23674    /* realize the widget */
23675    XtRealizeWidget (xf->gui->AppShell);
23676 
23677 
23678    SUMA_RETURNe;
23679 
23680 }
23681 
23682 /*!
23683    \brief Supposed to suggest a good wildcard string
23684    \param filetype: Not used now. It should be used to
23685                     tell whether the wildcard is for a dataset
23686                     or a surface, etc.
23687    \param SO
23688    \param wild[]: a char string to contain the wildcard
23689    Function needs lots of work
23690 */
SUMA_WildcardChoice(int filetype,SUMA_SurfaceObject * SO,char wild[])23691 SUMA_Boolean SUMA_WildcardChoice(int filetype,
23692                   SUMA_SurfaceObject *SO, char wild[])
23693 {
23694    static char FuncName[]={"SUMA_WildcardChoice"};
23695    char *eeel = NULL;
23696    char *eeer = NULL;
23697    SUMA_Boolean LocalHead = NOPE;
23698 
23699    SUMA_ENTRY;
23700 
23701    if (!SO) SUMA_RETURN(NOPE);
23702 
23703    /* default */
23704    switch (filetype) {
23705       case 1: /* dsets */
23706          eeel = getenv("SUMA_LEFT_FILE_DSET_IDENTIFIER");
23707          eeer = getenv("SUMA_RIGHT_FILE_DSET_IDENTIFIER");
23708          snprintf(wild, sizeof(char)*64, "*.dset");
23709          if (SO->Side == SUMA_LEFT ) {
23710             if (eeel) snprintf(wild, sizeof(char)*64,"%s", eeel);
23711          } else if (SO->Side == SUMA_RIGHT) {
23712             if (eeer) snprintf(wild, sizeof(char)*64,"%s", eeer);
23713          }
23714          break;
23715       case 2: /* rois */
23716          eeel = getenv("SUMA_LEFT_FILE_ROI_IDENTIFIER");
23717          eeer = getenv("SUMA_RIGHT_FILE_ROI_IDENTIFIER");
23718          snprintf(wild, sizeof(char)*64,"*.roi");
23719          if (SO->Side == SUMA_LEFT ) {
23720             if (eeel) snprintf(wild, sizeof(char)*64,"%s", eeel);
23721          } else if (SO->Side == SUMA_RIGHT) {
23722             if (eeer) snprintf(wild, sizeof(char)*64,"%s", eeer);
23723          }
23724          break;
23725       default: /* anything bloke */
23726          eeel = getenv("SUMA_LEFT_FILE_OTHER_IDENTIFIER");
23727          eeer = getenv("SUMA_RIGHT_FILE_OTHER_IDENTIFIER");
23728          snprintf(wild, sizeof(char)*64,"*");
23729          if (SO->Side == SUMA_LEFT ) {
23730             if (eeel) snprintf(wild, sizeof(char)*64,"%s", eeel);
23731          } else if (SO->Side == SUMA_RIGHT) {
23732             if (eeer) snprintf(wild, sizeof(char)*64,"%s", eeer);
23733          }
23734          break;
23735    }
23736 
23737    SUMA_RETURN(YUP);
23738 }
23739 
23740 
23741 /*
23742 void  (Widget w, XtPointer data, XtPointer client_data)
23743 {
23744    static char FuncName[]={""};
23745 
23746    SUMA_ENTRY;
23747 
23748    SUMA_RETURNe;
23749 }
23750 
23751 */
23752