1 #define DEBUG_1
2 #ifdef DEBUG_1
3 #define DEBUG_2
4 #define DEBUG_3
5 #endif
6
7 /* Need to figure out what to do with talking to multiple sockets (MATLAB and AFNI, for example).
8 So far, it looks like:
9 *- toggling should be separate. Maybe use Y key for matlab
10 Not sure if SUMA_Engine talk toggling targets need to be separate
11 for the various stream. Me thinks that should not be the case.
12 *- Talk_mode should be a part of the SUMAg_CF structure and should be set
13 for each stream. You'll also need to make sure relevant NI_write calls
14 abide by the settings. You should remove reliance on NI_TALK_MODE
15 and the current env used to control it.
16 *- Everytime one deals with SUMA_AFNI_STREAM_INDEX, one should have
17 a case for SUMA_TO_MATLAB_STREAM_INDEX . However, one does not
18 want to call SE_SendColorMapToAfni twice, once for AFNI and another
19 time for matlab. You want to send, not generate, the nel in question twice. */
20 /* Header FILES */
21
22 #include "SUMA_suma.h"
23
24 extern int selenium_close(void) ;
25
26 static FILE *sumaout = NULL; /* no default output stream */
27 static int SUMA_drive_set_outstream(char *outfile);
28 static FILE *SUMA_drive_get_outstream(void);
29
30 /* Make suma call itself with DriveSuma command in scom */
SUMA_MakeMeDo(char * scom,int method)31 SUMA_Boolean SUMA_MakeMeDo (char *scom, int method)
32 {
33 static char FuncName[]={"SUMA_MakeMeDo"};
34 SUMA_Boolean res = NOPE;
35 int i, exflag, margc;
36 char **margv=NULL;
37 SUMA_GENERIC_PROG_OPTIONS_STRUCT *Opt = NULL;
38 SUMA_Boolean LocalHead = NOPE;
39
40 SUMA_ENTRY;
41
42 if (!scom) SUMA_RETURN(YUP);
43
44 SUMA_LH("Talking to self");
45 /* The shortcut, proper way (below, method = 0) needs fixing.
46 SUMA does not seem to get command it sends itself. Check later */
47 if (method==1) {
48 char *ssys=(char *)SUMA_calloc(strlen(scom)+100, sizeof(char));
49 SUMA_LH("Clumsy system call");
50 sprintf(ssys,"\\DriveSuma %s &", scom);
51 if (system(ssys)) {
52 SUMA_S_Err("Failed to execute %s ssys\n", ssys);
53 SUMA_ifree(ssys);
54 SUMA_RETURN(NOPE);
55 }
56 SUMA_RETURN(YUP);
57 }
58
59 margv = SUMA_com2argv(scom, &margc);
60
61 if (!(Opt = SUMA_DriveSuma_ParseInput (margv, margc, NULL))) {
62 goto CLEANOUT;
63 }
64
65 for (i=0; i<Opt->N_com; ++i) {
66 if (LocalHead) {
67 SUMA_LH("Have the following commands");
68 fprintf(SUMA_STDERR,"Command %d: %s\n", i, Opt->com[i]);
69 }
70 if (!(exflag = SUMA_ProcessCommand(Opt->com[i], NULL, Opt->s))) {
71 SUMA_S_Errv("Failed in processing command\n%s\n", Opt->com[i]);
72 goto CLEANOUT;
73 }
74 if (exflag == -1) { /*gone daddy gone */
75 SUMA_S_Note("There's no more reason to exist.\n"
76 "Farewell dear friends.\n");
77 goto CLEANOUT;
78 }
79 }
80
81 res = YUP;
82
83 CLEANOUT:
84 if (Opt) Opt = SUMA_Free_Generic_Prog_Options_Struct(Opt);
85 margv = SUMA_free_com_argv(margv, &margc);
86
87 SUMA_RETURN(res);
88 }
89
90
91
92 /*!
93 \brief This is the function that runs the viewers.
94 success = SUMA_Engine (listp);
95
96 \param listp (DList **) pointer to doubly linked list pointer containing Engine commands
97
98 \return success (YUP/NOPE)
99
100 - *listp is destroyed just before SUMA_Engine returns and *listp is set to null
101 - To add a new command:
102 include it SUMA_define.h in SUMA_ENGINE_CODE's typedef
103 include it in SUMA_ParseCommands.c, SUMA_CommandCode, SUMA_CommandString functions
104 - OLD Format: SUMA_Boolean SUMA_Engine (char *Command, SUMA_EngineData *EngineData, SUMA_SurfaceViewer *sv)
105
106 */
107
SUMA_Engine(DList ** listp)108 SUMA_Boolean SUMA_Engine (DList **listp)
109 {
110 static char FuncName[]={"SUMA_Engine"};
111 char tmpstr[128], sfield[100], sdestination[100];
112 const char *NextCom;
113 int NextComCode, ii, i, id, ND, ip, NP, itmp=-1;
114 SUMA_SurfaceObject *SO = NULL;
115 SUMA_ALL_DO *ado = NULL;
116 SUMA_X_SurfCont *SurfCont=NULL;
117 SUMA_OVERLAYS *curColPlane=NULL;
118 float delta_t, ftmp = -1.0;
119 struct timeval tt;
120 int it, Wait_tot, nn=0, N_SOlist,
121 SOlist[SUMA_MAX_DISPLAYABLE_OBJECTS], iv200[200];
122 float ft, **fm, fv15[15];
123 double dv15[15];
124 XtPointer elvis=NULL;
125 NI_element *nel;
126 char *cbuf=NULL;
127 SUMA_Boolean Found;
128 SUMA_SurfaceViewer *svi;
129 SUMA_SurfaceViewer *sv = NULL;
130 static char Command[]={"OBSOLETE-since:Thu Jan 23 16:55:03 EST 2003"};
131 SUMA_EngineData *EngineData=NULL, *ED = NULL;
132 /* EngineData is what get passed from a list element,
133 ED is what gets added to the list inside SUMA_Engine */
134 DListElmt *NextElem_CANT_TOUCH_THIS, *LocElm=NULL;
135 DList *list= NULL;
136 SUMA_CREATE_TEXT_SHELL_STRUCT *TextShell = NULL, *LogShell=NULL;
137 SUMA_PARSED_NAME *fn = NULL;
138 static int NI_TALK_MODE = -1; /* Choose from:
139 NI_TEXT_MODE or NI_BINARY_MODE
140 Note cross-hair communication
141 is now always in NI_TEXT_MODE,
142 verify that AFNI handles either well
143 THIS handling here is TEMPORARY */
144 SUMA_Boolean LocalHead = NOPE;
145
146
147 SUMA_ENTRY;
148
149 if (NI_TALK_MODE < 0) {
150 if (AFNI_yesenv("SUMA_NI_TEXT_TALK_MODE")) {
151 SUMA_S_Note("Talking in text mode");
152 NI_TALK_MODE = NI_TEXT_MODE;
153 } else NI_TALK_MODE = NI_BINARY_MODE;
154 }
155
156 list = *listp; /* listp is now passed instead of list so that I can
157 set list to NULL from within this function */
158
159 if (!list) {
160 fprintf (SUMA_STDERR, "Error %s: Nothing to do.\n", FuncName);
161 SUMA_RETURN (NOPE);
162 }
163
164 SUMA_LH("Cycling through %d list elements", list->size);
165 while (list->size) {/* cycle through NextComs */
166 SUMA_LH("Fetching next element\n");
167 /* get the next command from the head of the list */
168 NextElem_CANT_TOUCH_THIS = dlist_head(list);
169 EngineData = (SUMA_EngineData *)NextElem_CANT_TOUCH_THIS->data;
170
171 /* decide on what Srcp might be. Currently only sv is passed
172 when the source is Suma*/
173 sv = NULL;
174 switch (EngineData->Src) {
175 case SES_Suma:
176 case SES_SumaFromAfni:
177 case SES_SumaWidget:
178 case SES_SumaFromAny:
179 sv = (SUMA_SurfaceViewer *)EngineData->Srcp;
180 case SES_Afni:
181 break;
182 default:
183 break;
184 }
185
186 NextComCode = EngineData->CommandCode;
187 if (!NextComCode) {
188 fprintf (stderr, "%s Error: Bad next element code\n", FuncName);
189 SUMA_RETURN (NOPE);
190 }
191 NextCom = SUMA_CommandString (NextComCode);
192 SUMA_LH("->%s<-\t", NextCom);
193 switch (NextComCode) {/* switch NextComCode */
194 case SE_SendColorMapToAfni:
195 /* expects in i the code of one of SUMA's standard colormaps */
196 {
197 SUMA_COLOR_MAP *cmap;
198 NI_element *nel=NULL;
199 int i;
200 char sbuf[50], *stmp=NULL;
201
202 if (EngineData->i_Dest != NextComCode ) {
203 fprintf (
204 SUMA_STDERR,
205 "Error %s: Data not destined correctly for %s (%d).\n", \
206 FuncName, NextCom, NextComCode);
207 break;
208 }
209
210 /* get the CMAP */
211 if (!(cmap = SUMA_FindCodedColMap(EngineData->i))) {
212 SUMA_SLP_Err("Failed to get colormap");
213 break;
214 }
215
216 if (cmap->N_M[0] > 256) {
217 SUMA_SLP_Err( "Cannot send more\n"
218 "than 256 colors to\n"
219 "AFNI.");
220 cmap = NULL;
221 break;
222 }
223
224 /* send AFNI the color map */
225 nel = NI_new_data_element("ni_do", 0);
226 NI_set_attribute ( nel, "ni_verb", "DRIVE_AFNI");
227 stmp = SUMA_append_string("DEFINE_COLORSCALE ", cmap->Name);
228 /* SEND COLORMAP In REVERSE ORDER TO AFNI,
229 C'est la vie */
230 for (i=cmap->N_M[0]-1; i >= 0; --i) {
231 sprintf(sbuf,"rgbi:%f/%f/%f",
232 cmap->M[i][0], cmap->M[i][1], cmap->M[i][2]);
233 stmp = SUMA_append_replace_string(stmp, sbuf, " ", 1);
234 }
235 SUMA_LH("%s",stmp);
236 NI_set_attribute ( nel, "ni_object", stmp);
237
238 /* SUMA_ShowNel((void*)nel); */
239
240 if (NI_write_element( SUMAg_CF->ns_v[SUMA_AFNI_STREAM_INDEX] ,
241 nel, NI_TALK_MODE ) < 0) {
242 SUMA_SLP_Err("Failed to send CMAP to afni");
243 NI_free_element(nel) ; nel = NULL;
244 if (stmp) SUMA_free(stmp); stmp = NULL;
245 cmap = NULL;
246 break;
247 }
248
249 NI_free_element(nel) ; nel = NULL;
250 if (stmp) SUMA_free(stmp); stmp = NULL;
251
252 /* Now set the colormap in AFNI */
253 nel = NI_new_data_element("ni_do", 0);
254 NI_set_attribute ( nel, "ni_verb", "DRIVE_AFNI");
255 stmp = SUMA_append_string("SET_PBAR_ALL ", "A.+99");
256 sprintf(sbuf, " 1 %s", cmap->Name);
257 stmp = SUMA_append_replace_string(stmp, sbuf, "", 1);
258 NI_set_attribute ( nel, "ni_object", stmp);
259
260 /* SUMA_ShowNel((void*)nel); */
261
262 if (NI_write_element( SUMAg_CF->ns_v[SUMA_AFNI_STREAM_INDEX] ,
263 nel, NI_TALK_MODE ) < 0) {
264 SUMA_SLP_Err("Failed to send CMAP to afni");
265 NI_free_element(nel) ; nel = NULL;
266 if (stmp) SUMA_free(stmp); stmp = NULL;
267 cmap = NULL;
268 break;
269 }
270
271 NI_free_element(nel) ; nel = NULL;
272 if (stmp) SUMA_free(stmp); stmp = NULL;
273
274 /* set the autorange off */
275 nel = NI_new_data_element("ni_do", 0);
276 NI_set_attribute ( nel, "ni_verb", "DRIVE_AFNI");
277 NI_set_attribute ( nel, "ni_object", "SET_FUNC_AUTORANGE A.-");
278 if (NI_write_element( SUMAg_CF->ns_v[SUMA_AFNI_STREAM_INDEX] ,
279 nel, NI_TALK_MODE ) < 0) {
280 SUMA_SLP_Err("Failed to send CMAP to afni");
281 NI_free_element(nel) ; nel = NULL;
282 cmap = NULL;
283 break;
284 }
285
286 NI_free_element(nel) ; nel = NULL;
287
288 /* set the range of the colorbar */
289 nel = NI_new_data_element("ni_do", 0);
290 NI_set_attribute ( nel, "ni_verb", "DRIVE_AFNI");
291 sprintf(sbuf," %d", cmap->N_M[0]);
292 stmp = SUMA_append_string("SET_FUNC_RANGE A.", sbuf);
293 NI_set_attribute ( nel, "ni_object", stmp);
294 if (NI_write_element( SUMAg_CF->ns_v[SUMA_AFNI_STREAM_INDEX] ,
295 nel, NI_TALK_MODE ) < 0) {
296 SUMA_SLP_Err("Failed to send CMAP to afni");
297 NI_free_element(nel) ; nel = NULL;
298 if (stmp) SUMA_free(stmp); stmp = NULL;
299 cmap = NULL;
300 break;
301 }
302 NI_free_element(nel) ; nel = NULL;
303 if (stmp) SUMA_free(stmp); stmp = NULL;
304
305 cmap = NULL;
306 }
307 break;
308 case SE_OpenDrawnROIFileSelection:
309 /* opens the open ROI file selection window.
310 Expects sv in vp, NULL is OK, and a position
311 reference widget typecast to ip, the latter can also be null.*/
312 {
313 char sbuf[128];
314 if ( EngineData->vp_Dest != NextComCode ||
315 EngineData->ip_Dest != NextComCode ) {
316 fprintf (SUMA_STDERR,
317 "Error %s: "
318 "Data not destined correctly for %s (%d).\n",
319 FuncName, NextCom, NextComCode);
320 break;
321 }
322 /* open the ROI file */
323 if (!sv) sv = SUMA_LAST_VIEWER;
324 /* wildcard selection
325 for a surface, just use the one in focus
326 But it is only to select the wildcard
327 SO assignment to an ROI is done in the ROI
328 reading function*/
329 SO = SUMA_SV_Focus_SO(sv);
330 if (SO && !SUMA_WildcardChoice(2, SO, sbuf)) {
331 sprintf(sbuf, "*.roi");
332 } else sprintf(sbuf, "*.roi");
333 if (!EngineData->vp) EngineData->vp = sv;
334 if (!EngineData->ip) {
335 SUMAg_CF->X->FileSelectDlg =
336 SUMA_CreateFileSelectionDialogStruct (
337 sv->X->TOPLEVEL, SUMA_FILE_OPEN, YUP,
338 SUMA_OpenDrawnROI, (void *)EngineData->vp,
339 NULL, NULL,
340 sbuf,
341 SUMAg_CF->X->FileSelectDlg);
342 } else {
343 SUMAg_CF->X->FileSelectDlg =
344 SUMA_CreateFileSelectionDialogStruct (
345 (Widget) EngineData->ip, SUMA_FILE_OPEN, YUP,
346 SUMA_OpenDrawnROI, (void *)EngineData->vp,
347 NULL, NULL,
348 sbuf,
349 SUMAg_CF->X->FileSelectDlg);
350 }
351 if (SO && SO->Side == SUMA_RIGHT) {
352 sprintf(sbuf,"Select RH ROI File to Open");
353 } else if (SO && SO->Side == SUMA_LEFT) {
354 sprintf(sbuf,"Select LH ROI File to Open");
355 } else sprintf(sbuf,"Select ROI File to Open");
356 SUMAg_CF->X->FileSelectDlg =
357 SUMA_CreateFileSelectionDialog ( sbuf,
358 &SUMAg_CF->X->FileSelectDlg);
359 }
360 break;
361
362 case SE_OpenXformOrtFileFileSelection:
363 /* opens the open ort file selection window.
364 Expects SUMA_XFORM in vp (to be used later and a position
365 reference widget typecast to ip, the latter can be null.*/
366 if ( EngineData->vp_Dest != NextComCode ||
367 EngineData->ip_Dest != NextComCode ) {
368 fprintf (SUMA_STDERR,
369 "Error %s: Data not destined correctly for %s (%d).\n",
370 FuncName, NextCom, NextComCode);
371 break;
372 }
373 if (!EngineData->ip) {
374 SUMAg_CF->X->FileSelectDlg =
375 SUMA_CreateFileSelectionDialogStruct (
376 sv->X->TOPLEVEL, SUMA_FILE_OPEN, YUP,
377 SUMA_OpenXformOrtFile, (void *)EngineData->vp,
378 NULL, NULL,
379 "*.1D",
380 SUMAg_CF->X->FileSelectDlg);
381 } else {
382 SUMAg_CF->X->FileSelectDlg =
383 SUMA_CreateFileSelectionDialogStruct (
384 (Widget) EngineData->ip, SUMA_FILE_OPEN, YUP,
385 SUMA_OpenXformOrtFile, (void *)EngineData->vp,
386 NULL, NULL,
387 "*.1D",
388 SUMAg_CF->X->FileSelectDlg);
389 }
390 SUMAg_CF->X->FileSelectDlg =
391 SUMA_CreateFileSelectionDialog ( "Select Ort File to Open",
392 &SUMAg_CF->X->FileSelectDlg);
393 break;
394
395 case SE_SaveDrawnROIFileSelection:
396 /* opens the save roi file selection window.
397 Expects NULL in vp (to be used later and a position reference
398 widget typecast to ip, the latter can be null.*/
399 if ( EngineData->vp_Dest != NextComCode ||
400 EngineData->ip_Dest != NextComCode ) {
401 fprintf (SUMA_STDERR,
402 "Error %s: Data not destined correctly for %s (%d).\n",
403 FuncName, NextCom, NextComCode);
404 break;
405 }
406
407 /* save ROI to file */
408 if (!sv) sv = &(SUMAg_SVv[0]);
409 if (!EngineData->ip) {
410 SUMAg_CF->X->FileSelectDlg =
411 SUMA_CreateFileSelectionDialogStruct ( sv->X->TOPLEVEL,
412 SUMA_FILE_SAVE, YUP,
413 SUMA_SaveDrawnROI,
414 (void *)EngineData->vp,
415 NULL, NULL,
416 "*.roi",
417 SUMAg_CF->X->FileSelectDlg);
418 } else {
419 SUMAg_CF->X->FileSelectDlg =
420 SUMA_CreateFileSelectionDialogStruct ((Widget) EngineData->ip,
421 SUMA_FILE_SAVE, YUP,
422 SUMA_SaveDrawnROI,
423 (void *)EngineData->vp,
424 NULL, NULL,
425 "*.roi",
426 SUMAg_CF->X->FileSelectDlg);
427 }
428
429 SUMAg_CF->X->FileSelectDlg =
430 SUMA_CreateFileSelectionDialog ( "Select ROI Filename",
431 &SUMAg_CF->X->FileSelectDlg);
432
433 break;
434 case SE_SaveXformOptsFileSelection:
435 /* opens the save Xform Opts file selection window.
436 Expects SUMA_XFORM* in vp and a position reference
437 widget typecast to ip, the latter can be null.*/
438 if ( EngineData->vp_Dest != NextComCode ||
439 EngineData->ip_Dest != NextComCode ) {
440 fprintf (SUMA_STDERR,
441 "Error %s: Data not destined correctly for %s (%d).\n",
442 FuncName, NextCom, NextComCode);
443 break;
444 }
445
446 /* save Xform opts to file */
447 if (!sv) sv = &(SUMAg_SVv[0]);
448 if (!EngineData->ip) {
449 SUMAg_CF->X->FileSelectDlg =
450 SUMA_CreateFileSelectionDialogStruct ( sv->X->TOPLEVEL,
451 SUMA_FILE_SAVE, YUP,
452 SUMA_SaveXformOpts,
453 (void *)EngineData->vp,
454 NULL, NULL,
455 "*.xfopts",
456 SUMAg_CF->X->FileSelectDlg);
457 } else {
458 SUMAg_CF->X->FileSelectDlg =
459 SUMA_CreateFileSelectionDialogStruct ((Widget) EngineData->ip,
460 SUMA_FILE_SAVE, YUP,
461 SUMA_SaveXformOpts,
462 (void *)EngineData->vp,
463 NULL, NULL,
464 "*.xfopts",
465 SUMAg_CF->X->FileSelectDlg);
466 }
467
468 SUMAg_CF->X->FileSelectDlg =
469 SUMA_CreateFileSelectionDialog ( "Select Opts Filename",
470 &SUMAg_CF->X->FileSelectDlg);
471
472 break;
473
474 case SE_SaveSOFileSelection:
475 /* saves a surface and its node colors to ascii files */
476 /* expects SO in vp and a position reference widget typecast
477 to ip, the latter can be null.*/
478 if (EngineData->vp_Dest != NextComCode ||
479 EngineData->ip_Dest != NextComCode ) {
480 fprintf (SUMA_STDERR,
481 "Error %s: Data not destined correctly for %s (%d).\n",
482 FuncName, NextCom, NextComCode);
483 break;
484 }
485 if (!sv) sv = &(SUMAg_SVv[0]);
486
487 {
488 SUMA_SAVESO_STRUCT *SaveSO_data = NULL;
489
490 SaveSO_data = (SUMA_SAVESO_STRUCT *)
491 SUMA_calloc(1,sizeof(SUMA_SAVESO_STRUCT));
492 /* DO NOT FREE THIS POINTER,
493 It is freed by the function
494 SUMA_SaveSOascii */
495 SaveSO_data->SO = (SUMA_SurfaceObject *)EngineData->vp;
496 SaveSO_data->sv = sv;
497
498 if (!EngineData->ip) {
499 SUMAg_CF->X->FileSelectDlg =
500 SUMA_CreateFileSelectionDialogStruct (
501 sv->X->TOPLEVEL, SUMA_FILE_SAVE, YUP,
502 SUMA_SaveSOascii, (void *)SaveSO_data,
503 NULL, NULL,
504 "*.1D.xyz",
505 SUMAg_CF->X->FileSelectDlg);
506 } else {
507 SUMAg_CF->X->FileSelectDlg =
508 SUMA_CreateFileSelectionDialogStruct (
509 (Widget) EngineData->ip, SUMA_FILE_SAVE, YUP,
510 SUMA_SaveSOascii, (void *)SaveSO_data,
511 NULL, NULL, "*.1D.xyz", SUMAg_CF->X->FileSelectDlg);
512 }
513
514 SUMAg_CF->X->FileSelectDlg =
515 SUMA_CreateFileSelectionDialog (
516 "Select SO file prefix.", &SUMAg_CF->X->FileSelectDlg);
517 }
518 break;
519
520 case SE_LoadSegDO:
521 if (EngineData->ip_Dest != NextComCode ) {
522 fprintf (SUMA_STDERR,
523 "Error %s: Data not destined correctly for %s (%d).\n",
524 FuncName, NextCom, NextComCode);
525 break;
526 }
527 if (!sv) sv = &(SUMAg_SVv[0]);
528 if (!EngineData->ip) {
529 SUMAg_CF->X->FileSelectDlg =
530 SUMA_CreateFileSelectionDialogStruct (
531 sv->X->TOPLEVEL, SUMA_FILE_OPEN, YUP,
532 SUMA_LoadSegDO, (void *)sv,
533 NULL, NULL,
534 "*.*",
535 SUMAg_CF->X->FileSelectDlg);
536 } else {
537 SUMAg_CF->X->FileSelectDlg =
538 SUMA_CreateFileSelectionDialogStruct (
539 (Widget) EngineData->ip, SUMA_FILE_OPEN, YUP,
540 SUMA_LoadSegDO, (void *)sv,
541 NULL, NULL,
542 "*.*",
543 SUMAg_CF->X->FileSelectDlg);
544 }
545 SUMAg_CF->X->FileSelectDlg =
546 SUMA_CreateFileSelectionDialog (
547 "Select Displayable Objects File",
548 &SUMAg_CF->X->FileSelectDlg);
549 break;
550
551 case SE_LoadViewFileSelection:
552 /* opens the view file selection window.
553 Expects a position reference widget typecast to ip,
554 the latter can be null.*/
555
556 if (EngineData->ip_Dest != NextComCode ) {
557 fprintf (SUMA_STDERR,
558 "Error %s: Data not destined correctly for %s (%d).\n",
559 FuncName, NextCom, NextComCode);
560 break;
561 }
562 if (!sv) sv = &(SUMAg_SVv[0]);
563 if (!EngineData->ip) {
564 SUMAg_CF->X->FileSelectDlg =
565 SUMA_CreateFileSelectionDialogStruct (
566 sv->X->TOPLEVEL, SUMA_FILE_OPEN, YUP,
567 SUMA_LoadVisualState, (void *)sv,
568 NULL, NULL,
569 "*.vvs",
570 SUMAg_CF->X->FileSelectDlg);
571 } else {
572 SUMAg_CF->X->FileSelectDlg =
573 SUMA_CreateFileSelectionDialogStruct (
574 (Widget) EngineData->ip, SUMA_FILE_OPEN, YUP,
575 SUMA_LoadVisualState, (void *)sv,
576 NULL, NULL,
577 "*.vvs",
578 SUMAg_CF->X->FileSelectDlg);
579 }
580 SUMAg_CF->X->FileSelectDlg =
581 SUMA_CreateFileSelectionDialog (
582 "Select Viewer Settings File", &SUMAg_CF->X->FileSelectDlg);
583 break;
584
585 case SE_SaveViewFileSelection:
586 /* opens the view file selection window.
587 Expects a position reference widget typecast to ip,
588 the latter can be null.*/
589
590 if (EngineData->ip_Dest != NextComCode ) {
591 fprintf (SUMA_STDERR,
592 "Error %s: Data not destined correctly for %s (%d).\n",
593 FuncName, NextCom, NextComCode);
594 break;
595 }
596 if (!sv) sv = &(SUMAg_SVv[0]);
597 if (!EngineData->ip) {
598 SUMAg_CF->X->FileSelectDlg =
599 SUMA_CreateFileSelectionDialogStruct (
600 sv->X->TOPLEVEL, SUMA_FILE_SAVE, YUP,
601 SUMA_SaveVisualState, (void *)sv,
602 NULL, NULL,
603 "*.vvs",
604 SUMAg_CF->X->FileSelectDlg);
605 } else {
606 SUMAg_CF->X->FileSelectDlg =
607 SUMA_CreateFileSelectionDialogStruct (
608 (Widget) EngineData->ip, SUMA_FILE_SAVE, YUP,
609 SUMA_SaveVisualState, (void *)sv,
610 NULL, NULL,
611 "*.vvs",
612 SUMAg_CF->X->FileSelectDlg);
613 }
614 SUMAg_CF->X->FileSelectDlg =
615 SUMA_CreateFileSelectionDialog ("Select Viewer Settings File",
616 &SUMAg_CF->X->FileSelectDlg);
617 break;
618
619 case SE_OpenSurfCont:
620 /* opens the surface controller
621 Expects SO in vp */
622 if (EngineData->vp_Dest != NextComCode ) {
623 fprintf (SUMA_STDERR,
624 "Error %s: Data not destined correctly for %s (%d).\n",
625 FuncName, NextCom, NextComCode);
626 break;
627 }
628 if (!sv) sv = &(SUMAg_SVv[0]);
629 ado = (SUMA_ALL_DO *)EngineData->vp;
630 if (!SUMA_viewSurfaceCont(NULL, ado, sv)) {
631 SUMA_S_Err("Failed open surfcont");
632 break;
633 }
634 break;
635
636 case SE_OneOnly:
637 if (EngineData->vp_Dest != NextComCode ) {
638 fprintf (SUMA_STDERR,
639 "Error %s: Data not destined correctly for %s (%d).\n",
640 FuncName, NextCom, NextComCode);
641 break;
642 }
643 if (!sv) sv = &(SUMAg_SVv[0]);
644 ado = (SUMA_ALL_DO *)EngineData->vp;
645 if (!SUMA_ColPlaneShowOneFore_Set (ado, YUP,
646 EngineData->Src == SES_SumaWidget)) {
647 SUMA_S_Err("Failed to set one only");
648 break;
649 }
650 break;
651
652 case SE_OpenDsetFileSelection:
653 {
654 char sbuf[128];
655 /* opens the dataset file selection window.
656 Expects SO in vp and a position reference
657 widget typecast to ip, the latter can be null.*/
658
659 if ( EngineData->vp_Dest != NextComCode ||
660 EngineData->ip_Dest != NextComCode ) {
661 fprintf (SUMA_STDERR,
662 "Error %s: Data not destined correctly for %s (%d).\n",
663 FuncName, NextCom, NextComCode);
664 break;
665 }
666
667 /* wildcard selection */
668 SO = (SUMA_SurfaceObject *)EngineData->vp;
669 if (!SUMA_WildcardChoice(1, SO, sbuf)) {
670 sprintf(sbuf, "*.dset");
671 }
672
673 /*Load data from file */
674 if (!sv) sv = &(SUMAg_SVv[0]);
675 if (!EngineData->ip) {
676 SUMAg_CF->X->FileSelectDlg =
677 SUMA_CreateFileSelectionDialogStruct (
678 sv->X->TOPLEVEL,
679 SUMA_FILE_OPEN, YUP,
680 SUMA_LoadDsetOntoSO,
681 (void *)EngineData->vp,
682 NULL, NULL,
683 sbuf,
684 SUMAg_CF->X->FileSelectDlg);
685 } else {
686 SUMAg_CF->X->FileSelectDlg =
687 SUMA_CreateFileSelectionDialogStruct (
688 (Widget) EngineData->ip,
689 SUMA_FILE_OPEN, YUP,
690 SUMA_LoadDsetOntoSO,
691 (void *)EngineData->vp,
692 NULL, NULL,
693 sbuf,
694 SUMAg_CF->X->FileSelectDlg);
695 }
696 if (SO && SO->Side == SUMA_RIGHT) {
697 sprintf(sbuf,"Select RH Dset File");
698 } else if (SO && SO->Side == SUMA_LEFT) {
699 sprintf(sbuf,"Select LH Dset File");
700 } else sprintf(sbuf,"Select Dset File");
701
702 SUMAg_CF->X->FileSelectDlg =
703 SUMA_CreateFileSelectionDialog (
704 sbuf,
705 &SUMAg_CF->X->FileSelectDlg);
706 }
707 break;
708
709 case SE_OpenDsetFile:
710 /* opens the dataset file, Expects SO in vp and a name in cp*/
711 if ( EngineData->vp_Dest != NextComCode ||
712 EngineData->cp_Dest != NextComCode ) {
713 fprintf (SUMA_STDERR,
714 "Error %s: Data not destined correctly for %s (%d).\n",
715 FuncName, NextCom, NextComCode);
716 break;
717 }
718 SUMA_LoadDsetOntoSO(EngineData->cp, EngineData->vp);
719 break;
720
721 case SE_SaveMaskFileSelection:
722 {
723 char sbuf[128];
724 /* save the mask file selection window.
725 Expects NULL in vp for now. Kept vp here
726 in case I need it in the future.
727 Also needs a position reference
728 widget typecast to ip, the latter can be null.*/
729
730 if ( EngineData->vp_Dest != NextComCode ||
731 EngineData->ip_Dest != NextComCode ) {
732 fprintf (SUMA_STDERR,
733 "Error %s: Data not destined correctly for %s (%d).\n",
734 FuncName, NextCom, NextComCode);
735 break;
736 }
737
738 /* wildcard selection */
739 sprintf(sbuf, "*.*.mo");
740
741 /*Load data from file */
742 if (!sv) sv = &(SUMAg_SVv[0]);
743 if (!EngineData->ip) {
744 SUMAg_CF->X->FileSelectDlg =
745 SUMA_CreateFileSelectionDialogStruct (
746 sv->X->TOPLEVEL,
747 SUMA_FILE_SAVE, YUP,
748 SUMA_SaveMultiMasks,
749 (void *)EngineData->vp,
750 NULL, NULL,
751 sbuf,
752 SUMAg_CF->X->FileSelectDlg);
753 } else {
754 SUMAg_CF->X->FileSelectDlg =
755 SUMA_CreateFileSelectionDialogStruct (
756 (Widget) EngineData->ip,
757 SUMA_FILE_SAVE, YUP,
758 SUMA_SaveMultiMasks,
759 (void *)EngineData->vp,
760 NULL, NULL,
761 sbuf,
762 SUMAg_CF->X->FileSelectDlg);
763 }
764
765 sprintf(sbuf,"Enter Masks Filename");
766 SUMAg_CF->X->FileSelectDlg =
767 SUMA_CreateFileSelectionDialog (
768 sbuf,
769 &SUMAg_CF->X->FileSelectDlg);
770 }
771 break;
772
773 case SE_OpenMaskFileSelection:
774 {
775 char sbuf[128];
776 /* opens the mask file selection window.
777 Expects NULL in vp for now. Kept vp here
778 in case I need it in the future.
779 Also needs a position reference
780 widget typecast to ip, the latter can be null.*/
781
782 if ( EngineData->vp_Dest != NextComCode ||
783 EngineData->ip_Dest != NextComCode ) {
784 fprintf (SUMA_STDERR,
785 "Error %s: Data not destined correctly for %s (%d).\n",
786 FuncName, NextCom, NextComCode);
787 break;
788 }
789
790 /* wildcard selection */
791 sprintf(sbuf, "*.*.mo");
792
793 /*Load data from file */
794 if (!sv) sv = &(SUMAg_SVv[0]);
795 if (!EngineData->ip) {
796 SUMAg_CF->X->FileSelectDlg =
797 SUMA_CreateFileSelectionDialogStruct (
798 sv->X->TOPLEVEL,
799 SUMA_FILE_OPEN, YUP,
800 SUMA_LoadMultiMasks,
801 (void *)EngineData->vp,
802 NULL, NULL,
803 sbuf,
804 SUMAg_CF->X->FileSelectDlg);
805 } else {
806 SUMAg_CF->X->FileSelectDlg =
807 SUMA_CreateFileSelectionDialogStruct (
808 (Widget) EngineData->ip,
809 SUMA_FILE_OPEN, YUP,
810 SUMA_LoadMultiMasks,
811 (void *)EngineData->vp,
812 NULL, NULL,
813 sbuf,
814 SUMAg_CF->X->FileSelectDlg);
815 }
816
817 sprintf(sbuf,"Select Masks File");
818 SUMAg_CF->X->FileSelectDlg =
819 SUMA_CreateFileSelectionDialog (
820 sbuf,
821 &SUMAg_CF->X->FileSelectDlg);
822 }
823 break;
824
825 case SE_OpenMaskFile:
826 /* opens the dataset file, Expects nothing in vp and a name in cp*/
827 if ( EngineData->vp_Dest != NextComCode ||
828 EngineData->cp_Dest != NextComCode ) {
829 fprintf (SUMA_STDERR,
830 "Error %s: Data not destined correctly for %s (%d).\n",
831 FuncName, NextCom, NextComCode);
832 break;
833 }
834 SUMA_LoadMultiMasks(EngineData->cp, EngineData->vp);
835 break;
836
837 case SE_OpenColFile:
838 /* opens the color file, Expects SO in vp and a name in cp*/
839 if ( EngineData->vp_Dest != NextComCode ||
840 EngineData->cp_Dest != NextComCode ) {
841 fprintf (SUMA_STDERR,
842 "Error %s: Data not destined correctly for %s (%d).\n",
843 FuncName, NextCom, NextComCode);
844 break;
845 }
846 SUMA_LoadColorPlaneFile(EngineData->cp, EngineData->vp);
847 break;
848
849 case SE_OpenCmapFileSelection:
850 /* opens the Cmap file selection window.
851 Expects ADO in vp and a position reference widget
852 typecast to ip, the latter can be null.*/
853
854 if ( EngineData->vp_Dest != NextComCode ||
855 EngineData->ip_Dest != NextComCode ) {
856 fprintf (SUMA_STDERR,
857 "Error %s: Data not destined correctly for %s (%d).\n",
858 FuncName, NextCom, NextComCode);
859 break;
860 }
861
862 /*Load colors from file */
863 if (!sv) sv = &(SUMAg_SVv[0]);
864 if (!EngineData->ip) {
865 SUMAg_CF->X->FileSelectDlg =
866 SUMA_CreateFileSelectionDialogStruct (
867 sv->X->TOPLEVEL, SUMA_FILE_OPEN, YUP,
868 SUMA_LoadCmapFile, (void *)EngineData->vp,
869 NULL, NULL,
870 "*.cmap",
871 SUMAg_CF->X->FileSelectDlg);
872 } else {
873 SUMAg_CF->X->FileSelectDlg =
874 SUMA_CreateFileSelectionDialogStruct (
875 (Widget) EngineData->ip, SUMA_FILE_OPEN, YUP,
876 SUMA_LoadCmapFile, (void *)EngineData->vp,
877 NULL, NULL,
878 "*.cmap",
879 SUMAg_CF->X->FileSelectDlg);
880 }
881
882 SUMAg_CF->X->FileSelectDlg =
883 SUMA_CreateFileSelectionDialog (
884 "Select Cmap File", &SUMAg_CF->X->FileSelectDlg);
885
886 break;
887 case SE_OpenColFileSelection:
888 /* opens the color file selection window.
889 Expects SO in vp and a position reference widget typecast to ip,
890 the latter can be null.*/
891
892 if (EngineData->vp_Dest != NextComCode ||
893 EngineData->ip_Dest != NextComCode ) {
894 fprintf (SUMA_STDERR,
895 "Error %s: Data not destined correctly for %s (%d).\n",
896 FuncName, NextCom, NextComCode);
897 break;
898 }
899
900 /*Load colors from file */
901 if (!sv) sv = &(SUMAg_SVv[0]);
902 if (!EngineData->ip) {
903 SUMAg_CF->X->FileSelectDlg =
904 SUMA_CreateFileSelectionDialogStruct (
905 sv->X->TOPLEVEL, SUMA_FILE_OPEN, YUP,
906 SUMA_LoadColorPlaneFile, (void *)EngineData->vp,
907 NULL, NULL,
908 "*.col",
909 SUMAg_CF->X->FileSelectDlg);
910 } else {
911 SUMAg_CF->X->FileSelectDlg =
912 SUMA_CreateFileSelectionDialogStruct (
913 (Widget) EngineData->ip, SUMA_FILE_OPEN, YUP,
914 SUMA_LoadColorPlaneFile, (void *)EngineData->vp,
915 NULL, NULL,
916 "*.col",
917 SUMAg_CF->X->FileSelectDlg);
918 }
919
920 SUMAg_CF->X->FileSelectDlg =
921 SUMA_CreateFileSelectionDialog (
922 "Select Node Color File", &SUMAg_CF->X->FileSelectDlg);
923
924 break;
925
926
927 case SE_OpenDrawROI:
928 /* opens the DrawROI window, expects a surface viewer
929 pointer in EngineData->Srcp*/
930 {
931 SUMA_DRAWN_ROI *DrawnROI=NULL;
932
933 if (!sv) {
934 fprintf (SUMA_STDERR, "Error %s: Null sv.\n", FuncName);
935 SUMA_RETURN(NOPE);
936 }
937
938 /* determine if there are ROIs being drawn on surfaces
939 displayed here */
940 DrawnROI = NULL;
941 /* start with the Focus_SO */
942 if ((SO = SUMA_SV_Focus_SO(sv))) {
943 DrawnROI = SUMA_FetchROI_InCreation (SO, SUMAg_DOv,
944 SUMAg_N_DOv);
945 }
946 if (!DrawnROI) { /* none found on focus surface, check
947 other surfaces in this viewer */
948 N_SOlist = SUMA_RegisteredSOs(sv, SUMAg_DOv, SOlist);
949 if (N_SOlist) {
950 it = 0;
951 do {
952 DrawnROI = SUMA_FetchROI_InCreation (SO, SUMAg_DOv,
953 SUMAg_N_DOv);
954 ++it;
955 } while (!DrawnROI && it < N_SOlist);
956 }
957 }
958
959 /* call function to create ROI window */
960 if (!SUMA_OpenDrawROIWindow (DrawnROI)) {
961 SUMA_RegisterMessage (SUMAg_CF->MessageList,
962 "Failed to open Draw ROI window",
963 FuncName,
964 SMT_Error, SMA_LogAndPopup);
965
966 }
967 break;
968
969 }
970 case SE_SetRenderMode:
971 { /* sets the rendering mode of a surface,
972 expects SO in vp and rendering mode in i*/
973 SO = (SUMA_SurfaceObject *)EngineData->vp;
974 SUMA_SET_SO_POLYMODE(SO,EngineData->i);
975 }
976 break;
977
978 case SE_SetTransMode:
979 { /* sets the transparency value of a surface,
980 expects SO in vp and TransMode in i*/
981 SO = (SUMA_SurfaceObject *)EngineData->vp;
982 SUMA_Set_ADO_TransMode((SUMA_ALL_DO *)SO,EngineData->i, 0, 0);
983 }
984 break;
985
986 case SE_SetATransMode:
987 { /* sets the transparency value of a surface,
988 expects SO in vp and TransMode in i*/
989 ado = (SUMA_ALL_DO *)EngineData->vp;
990 SUMA_Set_ADO_TransMode(ado,EngineData->i, 0, 0);
991 }
992 break;
993
994 case SE_SetDsetViewMode:
995 { /* sets the viewing mode of a dset,
996 expects ADO in vp and rendering mode in i*/
997 SUMA_COLOR_MAP *cmp=NULL;
998 static int nwarn=0, nwarn2=0;
999
1000 ado = (SUMA_ALL_DO *)EngineData->vp;
1001 if (!(curColPlane = SUMA_ADO_CurColPlane(ado)) ||
1002 !(SurfCont = SUMA_ADO_Cont(ado))) {
1003 SUMA_S_Err("No cur plane");
1004 break;
1005 }
1006 it = SUMA_ABS(curColPlane->ShowMode);
1007 if (EngineData->i == SW_SurfCont_DsetViewXXX) {
1008 curColPlane->ShowMode =
1009 -SUMA_ABS(curColPlane->ShowMode);
1010 } else {
1011 curColPlane->ShowMode = EngineData->i ;
1012 }
1013 if (strcmp(curColPlane->cmapname,"explicit")) {
1014 /* Can we do contours? */
1015 cmp = SUMA_FindNamedColMap(
1016 curColPlane->cmapname);
1017 if (!cmp) { SUMA_S_Err("Unexpected null colormap"); break;}
1018 if (SUMA_NeedsLinearizing(cmp)) {
1019 if (EngineData->i == SW_SurfCont_DsetViewCon ||
1020 EngineData->i == SW_SurfCont_DsetViewCaC ) {
1021 if (!nwarn) {
1022 SUMA_SLP_Note("Cannot do contouring with colormaps\n"
1023 "that panes of unequal sizes.\n"
1024 "Contouring turned off.\n"
1025 "Notice shown once per session.");
1026 ++nwarn;
1027 }
1028 curColPlane->ShowMode = it; /* get back */
1029 SUMA_Set_Menu_Widget( SurfCont->DsetViewModeMenu,
1030 SUMA_ShowMode2ShowModeMenuItem(it));
1031 /* kill current contours, if any */
1032 SUMA_KillOverlayContours(curColPlane);
1033 }
1034 }
1035 /* if new mode require contours, better regenerate them */
1036 if ( (it != SW_SurfCont_DsetViewCon &&
1037 it != SW_SurfCont_DsetViewCaC ) &&
1038 (curColPlane->ShowMode ==
1039 SW_SurfCont_DsetViewCon ||
1040 curColPlane->ShowMode ==
1041 SW_SurfCont_DsetViewCaC) ) {
1042 if (!SUMA_ColorizePlane(curColPlane)) {
1043 SUMA_S_Err( "Police at the station - "
1044 "and they don't look friendly.");
1045 }
1046 }
1047 } else {
1048 SUMA_LH("lam");
1049 /* explicit colormap no need for all the complications above*/
1050 if (EngineData->i == SW_SurfCont_DsetViewCon ||
1051 EngineData->i == SW_SurfCont_DsetViewCaC ) {
1052 if (!nwarn2) {
1053 SUMA_SLP_Note("Cannot do contouring with explicitly\n"
1054 "colored datasets. \n"
1055 "Notice shown once per session.");
1056 ++nwarn2;
1057 }
1058 curColPlane->ShowMode = it; /* get back */
1059 SUMA_Set_Menu_Widget( SurfCont->DsetViewModeMenu,
1060 SUMA_ShowMode2ShowModeMenuItem(it));
1061 /* kill current contours, if any . There should be none
1062 here but there is no harm */
1063 SUMA_KillOverlayContours(curColPlane);
1064 }
1065 }
1066 if (!SUMA_Remixedisplay (ado)) {
1067 SUMA_S_Err("Dunno what happened here");
1068 }
1069 }
1070 break;
1071
1072 case SE_SetDsetFont:
1073 { /* sets the Font for nodes of a (graph) dset,
1074 expects ADO in vp and rendering mode in i*/
1075 ado = (SUMA_ALL_DO *)EngineData->vp;
1076 if (!(curColPlane = SUMA_ADO_CurColPlane(ado)) ||
1077 !(SurfCont = SUMA_ADO_Cont(ado))) {
1078 SUMA_S_Err("No cur plane");
1079 break;
1080 }
1081
1082 if (EngineData->i == SW_SurfCont_DsetFontXXX) {
1083 curColPlane->Font =
1084 -SUMA_ABS(curColPlane->Font);
1085 } else {
1086 curColPlane->Font = EngineData->i;
1087 }
1088 SUMA_ADO_Flush_Pick_Buffer(ado, sv);
1089 if (!SUMA_Remixedisplay (ado)) {
1090 SUMA_S_Err("Dunno what happened here");
1091 }
1092 }
1093 break;
1094
1095 case SE_SetDsetThrough:
1096 { /* sets the sphere radius for nodes of a (graph) dset,
1097 expects ADO in vp and rendering mode in i*/
1098 ado = (SUMA_ALL_DO *)EngineData->vp;
1099 if (!(curColPlane = SUMA_ADO_CurColPlane(ado)) ||
1100 !(SurfCont = SUMA_ADO_Cont(ado))) {
1101 SUMA_S_Err("No cur plane");
1102 break;
1103 }
1104
1105 if (EngineData->i == SW_SurfCont_DsetThroughXXX) {
1106 curColPlane->Through =
1107 -SUMA_ABS(curColPlane->Through);
1108 } else {
1109 curColPlane->Through = EngineData->i;
1110 }
1111 SUMA_ADO_Flush_Pick_Buffer(ado, sv);
1112 if (!SUMA_Remixedisplay (ado)) {
1113 SUMA_S_Err("Dunno what happened here");
1114 }
1115 }
1116 break;
1117
1118 case SE_SetDsetNodeRad:
1119 { /* sets the sphere radius for nodes of a (graph) dset,
1120 expects ADO in vp and rendering mode in i*/
1121 ado = (SUMA_ALL_DO *)EngineData->vp;
1122 if (!(curColPlane = SUMA_ADO_CurColPlane(ado)) ||
1123 !(SurfCont = SUMA_ADO_Cont(ado))) {
1124 SUMA_S_Err("No cur plane");
1125 break;
1126 }
1127
1128 if (EngineData->i == SW_SurfCont_DsetNodeRadXXX) {
1129 curColPlane->NodeRad =
1130 -SUMA_ABS(curColPlane->NodeRad);
1131 } else {
1132 curColPlane->NodeRad = EngineData->i;
1133 }
1134 SUMA_ADO_Flush_Pick_Buffer(ado, sv);
1135 if (!SUMA_Remixedisplay (ado)) {
1136 SUMA_S_Err("Dunno what happened here");
1137 }
1138 }
1139 break;
1140
1141 case SE_SetDsetEdgeThick:
1142 { /* sets the thickness of a (graph's) edges,
1143 expects ADO in vp and rendering mode in i*/
1144 ado = (SUMA_ALL_DO *)EngineData->vp;
1145 if (!(curColPlane = SUMA_ADO_CurColPlane(ado)) ||
1146 !(SurfCont = SUMA_ADO_Cont(ado))) {
1147 SUMA_S_Err("No cur plane");
1148 break;
1149 }
1150
1151 curColPlane->EdgeThick = EngineData->i;
1152 SUMA_ADO_Flush_Pick_Buffer(ado, sv);
1153 if (!SUMA_Remixedisplay (ado)) {
1154 SUMA_S_Err("Dunno what happened here");
1155 }
1156 }
1157 break;
1158
1159 case SE_SetDsetEdgeStip:
1160 { /* sets the stippling of a (graph's) edges,
1161 expects ADO in vp and rendering mode in i*/
1162 ado = (SUMA_ALL_DO *)EngineData->vp;
1163 if (!(curColPlane = SUMA_ADO_CurColPlane(ado)) ||
1164 !(SurfCont = SUMA_ADO_Cont(ado))) {
1165 SUMA_S_Err("No cur plane");
1166 break;
1167 }
1168
1169 if (EngineData->i == SW_SurfCont_DsetEdgeStipXXX) {
1170 curColPlane->EdgeStip =
1171 -SUMA_ABS(curColPlane->EdgeStip);
1172 } else {
1173 curColPlane->EdgeStip = EngineData->i;
1174 }
1175
1176 if (!SUMA_Remixedisplay (ado)) {
1177 SUMA_S_Err("Dunno what happened here");
1178 }
1179 }
1180 break;
1181
1182 case SE_SetTractStyle:
1183 { /* sets the stippling of a (graph's) edges,
1184 expects ADO in vp and rendering mode in i*/
1185 ado = (SUMA_ALL_DO *)EngineData->vp;
1186 if (!(curColPlane = SUMA_ADO_CurColPlane(ado)) ||
1187 !(SurfCont = SUMA_ADO_Cont(ado))) {
1188 SUMA_S_Err("No cur plane");
1189 break;
1190 }
1191
1192 if (EngineData->i == SW_SurfCont_TractStyleSOLID) {
1193 curColPlane->EdgeStip =
1194 -SUMA_ABS(curColPlane->EdgeStip);
1195 } else {
1196 curColPlane->EdgeStip = EngineData->i;
1197 }
1198
1199 if (!SUMA_Remixedisplay (ado)) {
1200 SUMA_S_Err("Dunno what happened here");
1201 }
1202 }
1203 break;
1204
1205 case SE_SetDsetAlphaVal:
1206 { /* sets the stippling of a (graph's) edges,
1207 expects ADO in vp and rendering mode in i*/
1208 ado = (SUMA_ALL_DO *)EngineData->vp;
1209 if (!(curColPlane = SUMA_ADO_CurColPlane(ado)) ||
1210 !(SurfCont = SUMA_ADO_Cont(ado))) {
1211 SUMA_S_Err("No cur plane");
1212 break;
1213 }
1214
1215 SUMA_LH("Setting AlphaVal = %d", EngineData->i);
1216 if (curColPlane->AlphaVal != EngineData->i) {
1217 curColPlane->AlphaVal = EngineData->i;
1218 /* This requires recoloring because the alpha values may
1219 depend on the data */
1220 if (!SUMA_ColorizePlane (curColPlane)) {
1221 SUMA_SLP_Err("Failed to colorize plane.\n");
1222 SUMA_RETURN(0);
1223 }
1224
1225 if (!SUMA_Remixedisplay (ado)) {
1226 SUMA_S_Err("Dunno what happened here");
1227 }
1228 }
1229 }
1230 break;
1231
1232 case SE_SetDsetNodeCol:
1233 { /* sets the node coloring mode of a (graph) dset,
1234 expects ADO in vp and rendering mode in i*/
1235 ado = (SUMA_ALL_DO *)EngineData->vp;
1236 if (!(curColPlane = SUMA_ADO_CurColPlane(ado)) ||
1237 !(SurfCont = SUMA_ADO_Cont(ado))) {
1238 SUMA_S_Err("No cur plane");
1239 break;
1240 }
1241
1242 curColPlane->NodeCol = EngineData->i;
1243 if (!SUMA_Remixedisplay (ado)) {
1244 SUMA_S_Err("Dunno what happened here");
1245 }
1246 }
1247 break;
1248
1249 case SE_SetDsetTxtShad:
1250 { /* sets the text shading for nodes of a (graph) dset,
1251 expects ADO in vp and rendering mode in i*/
1252 ado = (SUMA_ALL_DO *)EngineData->vp;
1253 if (!(curColPlane = SUMA_ADO_CurColPlane(ado)) ||
1254 !(SurfCont = SUMA_ADO_Cont(ado))) {
1255 SUMA_S_Err("No cur plane");
1256 break;
1257 }
1258
1259 curColPlane->TxtShad = EngineData->i;
1260 if (!SUMA_Remixedisplay (ado)) {
1261 SUMA_S_Err("Dunno what happened here");
1262 }
1263 }
1264 break;
1265
1266 case SE_SetDsetGmatBord:
1267 { /* sets the border width of a (graph) dset matrix,
1268 expects ADO in vp and rendering mode in i*/
1269 ado = (SUMA_ALL_DO *)EngineData->vp;
1270 if (!(curColPlane = SUMA_ADO_CurColPlane(ado)) ||
1271 !(SurfCont = SUMA_ADO_Cont(ado))) {
1272 SUMA_S_Err("No cur plane");
1273 break;
1274 }
1275
1276 /* Get rid of matrix */
1277 curColPlane->BordFrac = EngineData->i;
1278 SUMA_GDSET_refresh_matrix_nido(SUMA_ADO_Dset(ado), 1);
1279 /* Update all viewers showing ado */
1280 SUMA_UpdateViewPoint_RegisteredADO(ado, 1);
1281 if (!SUMA_Remixedisplay (ado)) {
1282 SUMA_S_Err("Dunno what happened here");
1283 }
1284 }
1285 break;
1286
1287 case SE_SetTractMask:
1288 { /* sets the masking mode for tracts,
1289 expects ADO in vp and masking mode in i*/
1290 SUMA_TRACT_SAUX *TSaux;
1291 ado = (SUMA_ALL_DO *)EngineData->vp;
1292 if (!(TSaux = SUMA_ADO_TSaux(ado))) {
1293 SUMA_S_Err("No valid pointers");
1294 break;
1295 }
1296
1297 TSaux->TractMask = EngineData->i;
1298
1299 SUMA_ADO_Flush_Pick_Buffer(ado, sv);
1300 if (!SUMA_Remixedisplay (ado)) {
1301 SUMA_S_Err("Dunno what happened here");
1302 }
1303 }
1304 break;
1305
1306 case SE_UpdateLog:
1307 /* Updates the Log window if it is open */
1308 {
1309 if (SUMAg_CF->X->Log_TextShell) {
1310 char *s = NULL;
1311 s = SUMA_BuildMessageLog (SUMAg_CF->MessageList);
1312 SUMAg_CF->X->Log_TextShell->CursorAtBottom = YUP;
1313 (void) SUMA_CreateTextShell (s,
1314 "Message Log", SUMAg_CF->X->Log_TextShell);
1315 XRaiseWindow(SUMAg_CF->X->DPY_controller1,
1316 XtWindow(SUMAg_CF->X->Log_TextShell->toplevel));
1317 if (s) SUMA_free(s);
1318 }
1319 }
1320 break;
1321
1322 case SE_Log:
1323 /* opens log window, needs nothing for the moment*/
1324 {
1325 char *s = NULL;
1326 if (SUMAg_CF->X->Log_TextShell) { /* just raise it */
1327 XRaiseWindow( SUMAg_CF->X->DPY_controller1,
1328 XtWindow(SUMAg_CF->X->Log_TextShell->toplevel));
1329 break;
1330 }else { /* create it */
1331 s = SUMA_BuildMessageLog (SUMAg_CF->MessageList);
1332 if (LocalHead)
1333 fprintf (SUMA_STDERR,
1334 "%s: Message string:\n%s\n", FuncName, s);
1335 LogShell = SUMA_CreateTextShellStruct (
1336 SUMA_Message_open, NULL, NULL,
1337 SUMA_Message_destroyed, NULL, NULL);
1338 if (!LogShell) {
1339 fprintf (SUMA_STDERR,
1340 "Error %s: Failed in SUMA_CreateTextShellStruct.\n",
1341 FuncName);
1342 break;
1343 }
1344 SUMAg_CF->X->Log_TextShell =
1345 SUMA_CreateTextShell(s, "SUMA log", LogShell);
1346 SUMA_free(s);
1347 }
1348 }
1349 break;
1350
1351 case SE_Help:
1352 /* opens help window, needs nothing for the moment*/
1353 {
1354 char *s = NULL;
1355 if (SUMAg_CF->X->Help_TextShell) { /* just raise it */
1356 XRaiseWindow(SUMAg_CF->X->DPY_controller1,
1357 XtWindow(SUMAg_CF->X->Help_TextShell->toplevel));
1358 } else {
1359 SUMAg_CF->X->Help_TextShell = SUMA_CreateTextShellStruct (
1360 SUMA_Help_open, NULL, NULL,
1361 SUMA_Help_destroyed, NULL,
1362 "https://afni.nimh.nih.gov/pub/dist/doc/htmldoc/"
1363 "SUMA/Viewer.html#mouse-keyboard");
1364 if (!SUMAg_CF->X->Help_TextShell) {
1365 fprintf (SUMA_STDERR,
1366 "Error %s: Failed in SUMA_CreateTextShellStruct.\n",
1367 FuncName);
1368 break;
1369 }
1370 }
1371
1372 s = SUMA_help_message_Info(TXT);
1373 if (!s) {
1374 fprintf (SUMA_STDERR,
1375 "Error %s: Failed in SUMA_help_message_Info.\n",
1376 FuncName);
1377 break;
1378 }else {
1379 SUMAg_CF->X->Help_TextShell =
1380 SUMA_CreateTextShell(
1381 s, "SUMA help", SUMAg_CF->X->Help_TextShell);
1382 SUMA_free(s);
1383 }
1384 }
1385 break;
1386
1387 case SE_Help_Xform: /* use same window as SUMA's help */
1388 /* opens help window, needs xform struct in vp */
1389 {
1390 SUMA_XFORM *xf=NULL;
1391 char *s = NULL;
1392 if (EngineData->vp_Dest != NextComCode) {
1393 fprintf (SUMA_STDERR,
1394 "Error %s: "
1395 "Data not destined correctly for %s (%d).\n",
1396 FuncName, NextCom, NextComCode);
1397 break;
1398 }
1399 if (!(xf = (SUMA_XFORM *)EngineData->vp)) {
1400 SUMA_S_Err("NULL input");
1401 break;
1402 }
1403 if (SUMAg_CF->X->Help_TextShell) { /* just raise it */
1404 XRaiseWindow(SUMAg_CF->X->DPY_controller1,
1405 XtWindow(SUMAg_CF->X->Help_TextShell->toplevel));
1406 } else { /* make one */
1407 SUMAg_CF->X->Help_TextShell = SUMA_CreateTextShellStruct (
1408 SUMA_Help_open, NULL, NULL,
1409 SUMA_Help_destroyed, NULL, NULL);
1410 if (!SUMAg_CF->X->Help_TextShell) {
1411 fprintf (SUMA_STDERR,
1412 "Error %s: Failed in SUMA_CreateTextShellStruct.\n",
1413 FuncName);
1414 break;
1415 }
1416 }
1417
1418 if (!strcmp(xf->name,"Dot")) {
1419 s = SUMA_help_xform_dot_message_Info();
1420 } else {
1421 s = SUMA_copy_string("aint no help for this xform honey");
1422 }
1423
1424 if (!s) {
1425 fprintf (SUMA_STDERR,
1426 "Error %s: Failed somehow.\n",
1427 FuncName);
1428 break;
1429 }else {
1430 SUMAg_CF->X->Help_TextShell =
1431 SUMA_CreateTextShell(
1432 s, "SUMA Xform help",
1433 SUMAg_CF->X->Help_TextShell);
1434 SUMA_free(s);
1435 }
1436 }
1437 break;
1438
1439 case SE_Help_Cmap:
1440 /* opens Cmap help window, needs Cmap in vp*/
1441 {
1442 char *s = NULL;
1443 SUMA_COLOR_MAP *Cmp;
1444 if (EngineData->vp_Dest != NextComCode) {
1445 fprintf (SUMA_STDERR,
1446 "Error %s: "
1447 "Data not destined correctly for %s (%d).\n",
1448 FuncName, NextCom, NextComCode);
1449 break;
1450 }
1451 Cmp = (SUMA_COLOR_MAP *)EngineData->vp;
1452 if (SUMAg_CF->X->Help_Cmap_TextShell) { /* just raise it */
1453 XRaiseWindow(
1454 SUMAg_CF->X->DPY_controller1,
1455 XtWindow(SUMAg_CF->X->Help_Cmap_TextShell->toplevel));
1456 break;
1457 }
1458
1459 s = SUMA_help_Cmap_message_Info(Cmp, 0);
1460 if (!s) {
1461 fprintf (SUMA_STDERR,
1462 "Error %s: Failed in SUMA_help_Cmap_message_Info.\n", FuncName);
1463 break;
1464 }else {
1465 TextShell =
1466 SUMA_CreateTextShellStruct ( SUMA_Help_Cmap_open,
1467 NULL, NULL,
1468 SUMA_Help_Cmap_destroyed,
1469 NULL,
1470 "https://afni.nimh.nih.gov/pub/dist/doc/htmldoc/"
1471 "SUMA/Viewer.html#colormap-keyboard-controls");
1472 if (!TextShell) {
1473 fprintf (SUMA_STDERR,
1474 "Error %s: "
1475 "Failed in SUMA_CreateTextShellStruct.\n",
1476 FuncName);
1477 break;
1478 }
1479 SUMAg_CF->X->Help_Cmap_TextShell =
1480 SUMA_CreateTextShell(s, "SUMA Colormap help", TextShell);
1481 SUMA_free(s);
1482 }
1483 }
1484 break;
1485 case SE_Help_Plot:
1486 /* opens Plot help window, needs nothing in vp*/
1487 {
1488 char *s = NULL;
1489
1490 if (SUMAg_CF->X->Help_Plot_TextShell) { /* just raise it */
1491 XRaiseWindow(
1492 SUMAg_CF->X->DPY_controller1,
1493 XtWindow(SUMAg_CF->X->Help_Plot_TextShell->toplevel));
1494 break;
1495 }
1496
1497 s = SUMA_help_Plot_message_Info();
1498 if (!s) {
1499 fprintf (SUMA_STDERR,
1500 "Error %s: Failed in SUMA_help_Plot_message_Info.\n", FuncName);
1501 break;
1502 }else {
1503 TextShell =
1504 SUMA_CreateTextShellStruct ( SUMA_Help_Plot_open,
1505 NULL, NULL,
1506 SUMA_Help_Plot_destroyed,
1507 NULL, NULL);
1508 if (!TextShell) {
1509 fprintf (SUMA_STDERR,
1510 "Error %s: "
1511 "Failed in SUMA_CreateTextShellStruct.\n",
1512 FuncName);
1513 break;
1514 }
1515 SUMAg_CF->X->Help_Plot_TextShell =
1516 SUMA_CreateTextShell(s, "SUMA Plot help", TextShell);
1517 SUMA_free(s);
1518 }
1519 }
1520 break;
1521
1522 case SE_Whereami:
1523 /* opens wheremi text window,
1524 Expects SO in vp, and a string for the whereami data
1525 In the future, it should expect a list of whereami
1526 data and it should build the report on its own.
1527 Each whereami datum should contain atlas info, space, coordinate,
1528 label, etc. */
1529 {
1530 char *s = NULL;
1531
1532 if (EngineData->vp_Dest != NextComCode ||
1533 EngineData->s_Dest != NextComCode) {
1534 fprintf (SUMA_STDERR,
1535 "Error %s: Data not destined correctly for %s (%d).\n",
1536 FuncName, NextCom, NextComCode);
1537 break;
1538 }
1539 if (!sv) sv = &(SUMAg_SVv[0]);
1540 if (!(SO = (SUMA_SurfaceObject *)EngineData->vp)) break;
1541 if (!(s = (char*)EngineData->s)) break;
1542
1543 if (!SUMAg_CF->X->Whereami_TextShell) {
1544 if (!(SUMAg_CF->X->Whereami_TextShell =
1545 SUMA_CreateTextShellStruct ( SUMA_Whereami_open,
1546 NULL, NULL,
1547 SUMA_Whereami_destroyed,
1548 NULL, NULL))) {
1549 SUMA_S_Err("Failed to create TextShellStruct.");
1550 break;
1551 }
1552 }
1553
1554 if (SUMAg_CF->X->Whereami_TextShell) { /* update */
1555 SUMAg_CF->X->Whereami_TextShell->CursorAtBottom = YUP;
1556 (void) SUMA_CreateTextShell (s,
1557 "Where Thou Layeth",
1558 SUMAg_CF->X->Whereami_TextShell);
1559 XRaiseWindow(
1560 SUMAg_CF->X->DPY_controller1,
1561 XtWindow(SUMAg_CF->X->Whereami_TextShell->toplevel));
1562
1563 }
1564 }
1565 break;
1566 case SE_Load_Group:
1567 /* Does not need a sv
1568 expects a pointer to .spec filename in cp,
1569 if cp is NULL then it will look for a spec structure
1570 pointer in ip (sorry, ran out of places...)
1571 it will also determine if surfaces in a spec structure
1572 pointer have already been loaded from f (really, ran out
1573 of places...) a VolumeParent name in vp,
1574 the indices of the viewers to register the surfaces with
1575 in iv15.
1576 and the number of viewers specified in iv15 in i.
1577 Surfaces are registered with all i viewers in iv15*/
1578
1579 if ( EngineData->cp_Dest != NextComCode ||
1580 EngineData->vp_Dest != NextComCode
1581 || EngineData->iv15_Dest != NextComCode ||
1582 EngineData->i_Dest != NextComCode
1583 || EngineData->ip_Dest != NextComCode ||
1584 EngineData->f_Dest != NextComCode) {
1585 fprintf (SUMA_STDERR,
1586 "Error %s: Data not destined correctly for %s (%d).\n"
1587 "%d %d %d %d %d %d\n",
1588 FuncName, NextCom, NextComCode, EngineData->cp_Dest,
1589 EngineData->vp_Dest,
1590 EngineData->iv15_Dest, EngineData->i_Dest ,
1591 EngineData->ip_Dest, EngineData->f_Dest);
1592 break;
1593 }
1594 {
1595 SUMA_SurfSpecFile Spec;
1596 char *VolParName = NULL, *specfilename = NULL;
1597
1598 VolParName = (char *)EngineData->vp;
1599 specfilename = EngineData->cp;
1600 if (specfilename) {
1601 /* Load The spec file */
1602 if (LocalHead)
1603 fprintf (SUMA_STDERR,
1604 "%s: Reading Spec File %s...\n",
1605 FuncName, specfilename);
1606 if (!SUMA_AllocSpecFields(&Spec)) {
1607 SUMA_S_Err("Failed to initialize spec fields.");
1608 exit(1);
1609 }
1610 if (!SUMA_Read_SpecFile (specfilename, &Spec)) {
1611 fprintf( SUMA_STDERR,
1612 "Error %s: Error in SUMA_Read_SpecFile.\n",
1613 FuncName);
1614 exit(1);
1615 }
1616 } else {
1617 if (!EngineData->ip) {
1618 fprintf( SUMA_STDERR,
1619 "Error %s: Nothing in ip, nothing to do !\n",
1620 FuncName);
1621 exit(1);
1622 }
1623 Spec = *((SUMA_SurfSpecFile *)EngineData->ip);
1624 }
1625
1626 /* make sure only one group was read in */
1627 if (Spec.N_Groups != 1) {
1628 if (Spec.N_Groups > 1) {
1629 fprintf( SUMA_STDERR,
1630 "Error %s: "
1631 "One and only one group of surfaces is allowed "
1632 "at the moment (%d found).\n",
1633 FuncName, Spec.N_Groups);
1634 exit(1);
1635 }
1636 /* We hope some DOs are visible, proceed */
1637 } else {
1638 if (!EngineData->f) {
1639 /* load one by one surfs specified in the specs file */
1640 if (LocalHead)
1641 fprintf (SUMA_STDERR,
1642 "%s: Loading Surfaces in Spec File ...\n",
1643 FuncName);
1644 if (!SUMA_LoadSpec_eng (&Spec, SUMAg_DOv, &SUMAg_N_DOv,
1645 VolParName, 0, SUMAg_CF->DsetList)){
1646 SUMA_LH("Failed in SUMA_LoadSpec.");
1647 exit(1);
1648 }
1649 }
1650
1651
1652 /* register the new group with SUMA */
1653 if (!SUMA_RegisterSpecGroup(SUMAg_CF, &Spec)) {
1654 SUMA_SL_Err("Failed to register group");
1655 break;
1656 }
1657
1658 }
1659 /* Register surfaces in Spec file or other DOs with the
1660 surface viewer and perform setups */
1661 for (ii = 0; ii < EngineData->i; ++ii) {
1662 SUMA_LHv("%s: Registering surfaces with surface viewer "
1663 "%d/%d ...\n", FuncName, ii, EngineData->i);
1664 if (!SUMA_SetupSVforDOs (&Spec, SUMAg_DOv, SUMAg_N_DOv,
1665 &(SUMAg_SVv[EngineData->iv15[ii]]), 0)) {
1666 fprintf (SUMA_STDERR,
1667 "Error %s: "
1668 "Failed in SUMA_SetupSVforDOs function.\n",
1669 FuncName);
1670 exit(1);
1671 }
1672 }
1673
1674 if (LocalHead)
1675 fprintf (SUMA_STDERR,
1676 "%s: Adding call to Home and Redisplay \n", FuncName);
1677 /* add a call to Home and a redisplay */
1678 if (!list) {
1679 fprintf (SUMA_STDERR,
1680 "Error %s: Should not be inside "
1681 "SUMA_Engine: ZSS Feb 02 05.\n", FuncName);
1682 /* list = SUMA_CreateList();*/
1683 break;
1684 }else {
1685 SUMA_LH("Appending to list ");
1686 }
1687 ED = SUMA_InitializeEngineListData (SE_Home_AllVisible);
1688 if (!SUMA_RegisterEngineListCommand ( list, ED,
1689 SEF_Empty, NULL,
1690 SES_Afni, NULL, NOPE,
1691 SEI_Tail, NULL )) {
1692 fprintf( SUMA_STDERR,
1693 "Error %s: Failed to register command\n", FuncName);
1694 break;
1695 }
1696 ED = SUMA_InitializeEngineListData (SE_Redisplay_AllVisible);
1697 if (!SUMA_RegisterEngineListCommand ( list, ED,
1698 SEF_Empty, NULL,
1699 SES_Afni, NULL, NOPE,
1700 SEI_Tail, NULL )) {
1701 fprintf( SUMA_STDERR,
1702 "Error %s: Failed to register command\n", FuncName);
1703 break;
1704 }
1705
1706 if (specfilename) {
1707 /* locally created spec, free contents */
1708 if (!SUMA_FreeSpecFields(&Spec)) {
1709 SUMA_S_Err("Failed to free spec fields");
1710 break;
1711 }
1712
1713 }
1714
1715
1716 }
1717 if (LocalHead)
1718 fprintf (SUMA_STDERR, "%s: Done in SE_Load_Spec.\n", FuncName);
1719 break;
1720
1721 case SE_SetClip:
1722 {
1723 int iplane = -1, Delete = 0;
1724 /* expects a clipping plane name in EngineData->s,
1725 equation in fv15 and type in i*/
1726 if (EngineData->fv15_Dest != NextComCode ||
1727 EngineData->s_Dest != NextComCode ||
1728 EngineData->i_Dest != NextComCode ) {
1729 SUMA_S_Errv("Data not destined correctly for %s (%d).\n"
1730 , NextCom, NextComCode);
1731 break;
1732 }
1733
1734 /* find plane in question */
1735 iplane = -1;
1736 for (ii=0; ii<SUMAg_CF->N_ClipPlanes; ++ii) {
1737 if ( strcmp(SUMAg_CF->ClipPlanesLabels[ii],
1738 EngineData->s) == 0
1739 && SUMAg_CF->ClipPlaneType[ii] ==
1740 (SUMA_CLIP_PLANE_TYPES)EngineData->i) {
1741 iplane = ii; break;
1742 }
1743 }
1744
1745 // Added by PDL to prevent extra clip plane being partially generated
1746 // when user maniulates default plane when first enetering clipping plane
1747 // mode or using the zero key
1748 if (strlen(EngineData->s)<1) iplane = 0;
1749
1750 /* stick equation where it belongs */
1751 if (EngineData->fv15[0] == 0.0 && EngineData->fv15[1] == 0.0 &&
1752 EngineData->fv15[2] == 0.0 && EngineData->fv15[3] == 0.0) {
1753 Delete = 1; /* no more clipping */
1754 } else {
1755 Delete = 0; /* a plane to add, modify */
1756 }
1757
1758 /* what to do? */
1759 if (Delete && iplane >=0) {
1760 /* delete */
1761 SUMAg_CF->ClipPlaneType[iplane] = SUMA_NO_CLIP_PLANE_TYPE;
1762 SUMAg_CF->ClipPlanesLabels[iplane][0]='\0';
1763 SUMAg_CF->ClipPlanes[4*iplane] =
1764 SUMAg_CF->ClipPlanes[4*iplane+1] =
1765 SUMAg_CF->ClipPlanes[4*iplane+2] =
1766 SUMAg_CF->ClipPlanes[4*iplane+3]= 0.0;
1767 --SUMAg_CF->N_ClipPlanes;
1768 glDisable(SUMA_index_to_clip_plane(iplane));
1769 } else if (Delete) {
1770 /* delete what ? */
1771 SUMA_SL_Warn("No plane to delete");
1772 break;
1773 } else if (!Delete && iplane < 0) {
1774 /* add a new one */
1775 if (SUMAg_CF->N_ClipPlanes == SUMA_MAX_N_CLIP_PLANES) {
1776 SUMA_SLP_Err("No more clipping planes available.");
1777 break;
1778 }
1779 SUMAg_CF->ClipPlaneType[SUMAg_CF->N_ClipPlanes] =
1780 (SUMA_CLIP_PLANE_TYPES)EngineData->i;
1781 snprintf(SUMAg_CF->ClipPlanesLabels[SUMAg_CF->N_ClipPlanes],
1782 8*sizeof(char), "%s", EngineData->s);
1783 SUMAg_CF->ClipPlanes[4*SUMAg_CF->N_ClipPlanes ] =
1784 (GLdouble)EngineData->fv15[0];
1785 SUMAg_CF->ClipPlanes[4*SUMAg_CF->N_ClipPlanes+1] =
1786 (GLdouble)EngineData->fv15[1];
1787 SUMAg_CF->ClipPlanes[4*SUMAg_CF->N_ClipPlanes+2] =
1788 (GLdouble)EngineData->fv15[2];
1789 SUMAg_CF->ClipPlanes[4*SUMAg_CF->N_ClipPlanes+3] =
1790 (GLdouble)EngineData->fv15[3];
1791 ++SUMAg_CF->N_ClipPlanes;
1792 } else {
1793 /* Replace an existing one */
1794 SUMAg_CF->ClipPlaneType[iplane] =
1795 (SUMA_CLIP_PLANE_TYPES)EngineData->i;
1796 snprintf(SUMAg_CF->ClipPlanesLabels[iplane],
1797 8*sizeof(char), "%s", EngineData->s);
1798 SUMAg_CF->ClipPlanes[4*iplane ] =
1799 (GLdouble)EngineData->fv15[0];
1800 SUMAg_CF->ClipPlanes[4*iplane+1] =
1801 (GLdouble)EngineData->fv15[1];
1802 SUMAg_CF->ClipPlanes[4*iplane+2] =
1803 (GLdouble)EngineData->fv15[2];
1804 SUMAg_CF->ClipPlanes[4*iplane+3] =
1805 (GLdouble)EngineData->fv15[3];
1806 }
1807 ED = SUMA_InitializeEngineListData (SE_Redisplay_AllVisible);
1808 if (!SUMA_RegisterEngineListCommand ( list, ED,
1809 SEF_Empty, NULL,
1810 SES_Afni, NULL, NOPE,
1811 SEI_Tail, NULL )) {
1812 SUMA_S_Err("Failed to register command");
1813 break;
1814 }
1815
1816 /* Show the clip planes */
1817 SUMA_Show_Clip_Planes(SUMAg_CF, NULL);
1818 }
1819 break;
1820
1821 case SE_SetLookAt:
1822 /* expects a center XYZ in EngineData->fv3[0 .. 2] */
1823 if (EngineData->fv3_Dest != NextComCode) {
1824 SUMA_S_Err("Data not destined correctly for %s (%d).\n",
1825 NextCom, NextComCode);
1826 break;
1827 }
1828 /* calculate the transform required to bring the new look at
1829 location to the current one */
1830 {
1831 float ulook_old[3], ulook_new[3];
1832 int Step = 10, iStep;
1833 float fracUp, fracDown;
1834
1835 ulook_old[0] = sv->GVS[sv->StdView].ViewFrom[0] -
1836 sv->GVS[sv->StdView].ViewCenter[0];
1837 ulook_old[1] = sv->GVS[sv->StdView].ViewFrom[1] -
1838 sv->GVS[sv->StdView].ViewCenter[1];
1839 ulook_old[2] = sv->GVS[sv->StdView].ViewFrom[2] -
1840 sv->GVS[sv->StdView].ViewCenter[2];
1841 ulook_new[0] = ulook_new[1] = ulook_new[2] = 0.0;
1842 fm = (float **)SUMA_allocate2D(4,4,sizeof(float));
1843
1844 for (iStep = Step; iStep >= 1; --iStep) {
1845 fracUp = (float)(iStep)/(float)Step;
1846 fracDown = (float)(Step - iStep)/(float)Step;
1847 SUMA_LH("%d, fracUp %f, fracDown %f, fv3[%f %f %f]\n",
1848 iStep, fracUp, fracDown, EngineData->fv3[0],
1849 EngineData->fv3[1], EngineData->fv3[2]);
1850 ulook_new[0] = (EngineData->fv3[0] * fracUp +
1851 sv->GVS[sv->StdView].ViewFrom[0] * fracDown)
1852 - sv->GVS[sv->StdView].ViewCenter[0];
1853 ulook_new[1] = (EngineData->fv3[1] * fracUp +
1854 sv->GVS[sv->StdView].ViewFrom[1] * fracDown)
1855 - sv->GVS[sv->StdView].ViewCenter[1];
1856 ulook_new[2] = (EngineData->fv3[2] * fracUp +
1857 sv->GVS[sv->StdView].ViewFrom[2] * fracDown)
1858 - sv->GVS[sv->StdView].ViewCenter[2];
1859 if (fm == NULL) {
1860 SUMA_S_Err("Failed to allocate fm.");
1861 break;
1862 }
1863 if (!SUMA_FromToRotation (ulook_new, ulook_old, fm)) {
1864 SUMA_S_Err("Failed in SUMA_FromToRotation.");
1865 break;
1866 }
1867
1868 /* add a SetRotMatrix to list*/
1869 ED = SUMA_InitializeEngineListData (SE_SetRotMatrix);
1870 ED->N_cols = 4;
1871 ED->N_rows = 4;
1872 if (!(LocElm = SUMA_RegisterEngineListCommand ( list, ED,
1873 SEF_fm, (void *)fm,
1874 EngineData->Src, EngineData->Srcp, NOPE,
1875 SEI_Head, NULL ))) {
1876 SUMA_S_Err("Failed to register command");
1877 break;
1878 }
1879
1880 /* add a redisplay call */
1881 ED = SUMA_InitializeEngineListData (SE_RedisplayNow);
1882 if (!SUMA_RegisterEngineListCommand ( list, ED,
1883 SEF_Empty, NULL,
1884 EngineData->Src, EngineData->Srcp, NOPE,
1885 SEI_After, LocElm )) {
1886 SUMA_S_Err("Failed to register command");
1887 break;
1888 }
1889
1890 }
1891 /* fm was copied into engine data, free it */
1892 SUMA_free2D((char **)fm, 4);
1893 }
1894 break;
1895
1896 case SE_StartListening:
1897 /* expects nothing in EngineData */
1898 if (!SUMAg_CF->Listening) {
1899 SUMAg_CF->Listening = !SUMAg_CF->Listening;
1900 fprintf(SUMA_STDERR,"%s: Starting to listen ...\n", FuncName);
1901 /* Make sure special NIML rowtypes are defined before */
1902 get_NI_tract_type();
1903 /* start the listening WorkProcess */
1904 if (!SUMAg_CF->niml_work_on) {
1905 SUMA_LH("registering SUMA_niml_workproc...");
1906 SUMA_register_workproc(SUMA_niml_workproc, (XtPointer)sv);
1907 } else {
1908 SUMA_LH("SUMA_niml_workproc Already on.");
1909 }
1910 } else {
1911 /* if already on, just close streams */
1912 /* closing the streams */
1913 SUMA_S_Text("Closing streams, but still listening ...");
1914 /* kill the streams */
1915 for (ii=0; ii< SUMA_MAX_STREAMS; ++ii) {
1916 if (ii != SUMA_AFNI_STREAM_INDEX) {
1917 /* leave AFNI connection separate */
1918 NI_stream_close( SUMAg_CF->ns_v[ii] ) ;
1919 SUMAg_CF->ns_v[ii] = NULL ;
1920 SUMAg_CF->ns_flags_v[ii] = 0;
1921 SUMAg_CF->TrackingId_v[ii] = 0;
1922 }
1923 }
1924 }
1925 break;
1926
1927 case SE_ToggleConnected:
1928 /* expects nothing in EngineData */
1929 if (!SUMA_CanTalkToAfni (SUMAg_DOv, SUMAg_N_DOv)) {
1930 fprintf(SUMA_STDOUT,
1931 "%s: Cannot connect to AFNI.\n"
1932 "\tNot one of the surfaces is mappable "
1933 "and has a Surface Volume.\n"
1934 "\tDid you use the -sv option when launching SUMA ?\n",
1935 FuncName);
1936 break;
1937 }
1938
1939 SUMAg_CF->Connected_v[SUMA_AFNI_STREAM_INDEX] =
1940 !SUMAg_CF->Connected_v[SUMA_AFNI_STREAM_INDEX];
1941 if (SUMAg_CF->Connected_v[SUMA_AFNI_STREAM_INDEX]) {
1942 if (!SUMA_niml_call (SUMAg_CF, SUMA_AFNI_STREAM_INDEX, YUP)) {
1943 /* conection flag is reset in SUMA_niml_call */
1944 break;
1945 }
1946
1947 /* start the listening WorkProcess */
1948 if (!SUMAg_CF->niml_work_on) {
1949 SUMA_LH("registering SUMA_niml_workproc...");
1950 SUMA_register_workproc(SUMA_niml_workproc, (XtPointer)sv);
1951 } else {
1952 SUMA_LH("SUMA_niml_workproc Already on.");
1953 }
1954
1955 /* register a call for sending the surface to afni (SetAfniSurf)*/
1956 if (LocalHead)
1957 fprintf(SUMA_STDERR,"Notifying Afni of New surface...\n");
1958 ED = SUMA_InitializeEngineListData (SE_SetAfniSurf);
1959 SUMA_RegisterEngineListCommand (list, ED,
1960 SEF_Empty, NULL,
1961 SES_Suma, (void *)sv, NOPE,
1962 SEI_Head, NULL);
1963 break;
1964 } else {
1965 fprintf(SUMA_STDOUT,"%s: Disconnecting from afni.\n", FuncName);
1966
1967 if (!SUMAg_CF->ns_v[SUMA_AFNI_STREAM_INDEX]) {
1968 /* It looks like the stream was closed, do the clean up */
1969 SUMA_S_Warn("sv->ns is null, stream must have gotten closed.\n"
1970 "Cleaning up ...\n");
1971 ED = SUMA_InitializeEngineListData (SE_CloseStream4All);
1972 ii = SUMA_AFNI_STREAM_INDEX;
1973 SUMA_RegisterEngineListCommand (list, ED,
1974 SEF_i, (void*)&ii,
1975 SES_Suma, (void *)sv, NOPE,
1976 SEI_Head, NULL);
1977
1978 break;
1979 }
1980
1981
1982 /* Close the stream if nobody else wants it.
1983 This is not a great condition, one should be able to leave the
1984 stream open
1985 even if no viewer, for the moment, does not want to talk to AFNI.
1986 Perhaps in the future. */
1987 if (SUMAg_N_SVv == 1) {
1988 SUMA_S_Note("Nobody wants to talk to AFNI anymore\n"
1989 "closing stream ...\n");
1990 NI_stream_close(SUMAg_CF->ns_v[SUMA_AFNI_STREAM_INDEX]);
1991 SUMAg_CF->ns_v[SUMA_AFNI_STREAM_INDEX] = NULL;
1992 SUMAg_CF->ns_flags_v[SUMA_AFNI_STREAM_INDEX] = 0;
1993 SUMAg_CF->TrackingId_v[SUMA_AFNI_STREAM_INDEX] = 0;
1994 }
1995 break;
1996 }
1997
1998 case SE_CloseStream4All:
1999 /* expects the stream index in i in EngineData */
2000 if (EngineData->i_Dest != NextComCode) {
2001 fprintf (SUMA_STDERR,
2002 "Error %s: Data not destined correctly for %s (%d).\n",
2003 FuncName, NextCom, NextComCode);
2004 break;
2005 }
2006 /* odds are communicating program died or closed stream,
2007 mark all surfaces as unsent */
2008 if (EngineData->i == SUMA_AFNI_STREAM_INDEX) {
2009 for (ii=0; ii<SUMAg_N_DOv; ++ii) {
2010 if (SUMA_isSO(SUMAg_DOv[ii])) {
2011 SO = (SUMA_SurfaceObject *)(SUMAg_DOv[ii].OP);
2012 if (SO->SentToAfni) SO->SentToAfni = NOPE;
2013 }
2014 }
2015 }
2016
2017 /* same for parent fields */
2018 /* check first if stream in SUMAg_CF still good by any chance */
2019 nn = NI_stream_goodcheck(SUMAg_CF->ns_v[EngineData->i] , 1 ) ;
2020
2021 if( nn >= 0 ){
2022 SUMA_S_Err("Stream still alive, this should not be. "
2023 "Closing anyway.");
2024 NI_stream_close(SUMAg_CF->ns_v[EngineData->i]);
2025 }
2026
2027 /* clean up and get out of here*/
2028 SUMAg_CF->ns_v[EngineData->i] = NULL;
2029 SUMAg_CF->ns_flags_v[EngineData->i] = 0;
2030 SUMAg_CF->TrackingId_v[EngineData->i] = 0;
2031 if (EngineData->i != SUMA_AFNI_STREAM_INDEX) {
2032 /* Connected for AFNI line handled elsewhere */
2033 SUMAg_CF->Connected_v[EngineData->i] = NOPE;
2034 }
2035 break;
2036
2037 case SE_SetForceAfniSurf:
2038 /* expects nothing in EngineData */
2039 /* send to afni surfaces that can be sent even if they
2040 have been sent already */
2041 #if 0 /* pre Oct 26 */
2042 for (ii=0; ii<sv->N_DO; ++ii) {
2043 if (SUMA_isSO(SUMAg_DOv[sv->RegisteredDO[ii]])) {
2044 SO = (SUMA_SurfaceObject *)
2045 (SUMAg_DOv[sv->RegisteredDO[ii]].OP);
2046 if (SO->SentToAfni) SO->SentToAfni = NOPE;
2047 }
2048 }
2049 #else
2050 /* send all geometrically correct surfaces */
2051 for (ii=0; ii<SUMAg_N_DOv; ++ii) {
2052 if (SUMA_isSO(SUMAg_DOv[ii])) {
2053 SO = (SUMA_SurfaceObject *)(SUMAg_DOv[ii].OP);
2054 if (SO->AnatCorrect && SO->SentToAfni)
2055 SO->SentToAfni = NOPE;
2056 }
2057 }
2058 #endif
2059 /* proceed to SE_SetAfniSurf: */
2060 ED = SUMA_InitializeEngineListData (SE_SetAfniSurf);
2061 SUMA_RegisterEngineListCommand (list, ED,
2062 SEF_Empty, NULL,
2063 SES_Suma, (void *)sv, NOPE,
2064 SEI_Head, NULL);
2065 break;
2066
2067 case SE_SetAfniMask:
2068 if (SUMAg_CF->Dev) { /* Send a mask surface to AFNI */
2069 int nels_sent=0;
2070 SUMA_ALL_DO *ado = NULL;
2071 SUMA_MaskDO *mdo = NULL;
2072 if ( EngineData->s_Dest != NextComCode ||
2073 EngineData->fv3_Dest != NextComCode) {
2074 fprintf (SUMA_STDERR,
2075 "Error %s: Data not destined correctly for %s (%d).\n",
2076 FuncName, NextCom, NextComCode);
2077 break;
2078 }
2079 ado = SUMA_whichADOg(EngineData->s);
2080 if (!ado || ado->do_type != MASK_type) {
2081 SUMA_S_Warn("Mask not found or ado of wrong type");
2082 break;
2083 }
2084 mdo = (SUMA_MaskDO*)ado;
2085 if (!(SO = mdo->SO)) {
2086 SUMA_S_Warn("No mask SO");
2087 break;
2088 }
2089 SUMA_LH("Sending mask %s's surface, SO = %p...",
2090 ADO_LABEL(ado), SO);
2091 if (!SO->SentToAfni) {
2092 SUMA_LH("Sending the whole thing, SO = %p", SO);
2093 nel = NI_new_data_element("SUMA_mask", 0);
2094 NI_set_attribute(nel, "idcode", ADO_ID(ado));
2095 NI_SET_FLOATv(nel, "init_cen", mdo->init_cen, 3);
2096 NI_SET_FLOATv(nel, "new_cen", EngineData->fv3, 3);
2097 if ((nn = NI_write_element(
2098 SUMAg_CF->ns_v[SUMA_AFNI_STREAM_INDEX] , nel ,
2099 NI_TALK_MODE ))<0) {
2100 SUMA_S_Err("NI_write_element failed\n");
2101 }
2102 if (LocalHead) SUMA_ShowNel(nel);
2103 NI_free_element(nel);
2104 nel = NULL;
2105 ++nels_sent;
2106 if (1) {
2107 float delta[3] = {0, 0, 0};
2108 delta[0] = mdo->init_cen[0] - EngineData->fv3[0];
2109 delta[1] = mdo->init_cen[1] - EngineData->fv3[1];
2110 delta[2] = mdo->init_cen[2] - EngineData->fv3[2];
2111 nel = SUMA_makeNI_SurfIXYZ (SO);
2112 /* Undo the offset in the surface coords ... */
2113 SUMA_offset_NI_SurfIXYZ(nel, delta);
2114 /* label this object as being the surface of a mask */
2115 if (!nel) {
2116 fprintf(SUMA_STDERR,
2117 "Error %s: SUMA_makeNI_SurfIXYZ failed\n",
2118 FuncName);
2119 break;
2120 }
2121 NI_set_attribute(nel,"parent_type", "SUMA_mask");
2122 NI_set_attribute(nel,"parent_idcode", ADO_ID(ado));
2123 /* set up some defaults color
2124 (see matlab's rgbdectohex for visual aid)
2125 info for AFNI interface */
2126 NI_set_attribute(nel,
2127 "afni_surface_controls_toggle", "on");
2128 NI_set_attribute(nel,
2129 "afni_surface_controls_nodes","none");
2130 NI_set_attribute(nel,
2131 "afni_surface_controls_lines",
2132 SUMA_RGB_to_hex(mdo->init_col, NULL));
2133 NI_set_attribute(nel,
2134 "afni_surface_controls_plusminus","none");
2135 NI_SET_INT(nel,
2136 "afni_surface_controls_linewidth", 10 );
2137
2138 /* send surface nel */
2139 if (LocalHead)
2140 fprintf(SUMA_STDERR,"%s: Sending SURF_iXYZ nel...\n ", FuncName) ;
2141 nn = NI_write_element(
2142 SUMAg_CF->ns_v[SUMA_AFNI_STREAM_INDEX] , nel ,
2143 NI_TALK_MODE ) ;
2144
2145 if( nn < 0 ){
2146 SUMA_S_Err("NI_write_element failed\n");
2147 }
2148
2149 if (LocalHead) SUMA_ShowNel(nel);
2150 NI_free_element(nel);
2151 nel = NULL;
2152 ++nels_sent;
2153 }
2154 if (1) {
2155 /* send node normals ZSS Oct 05 04 */
2156 nel = SUMA_makeNI_SurfINORM (SO);
2157 if (!nel) {
2158 SUMA_S_Err("SUMA_makeNI_SurfINORM failed");
2159 break;
2160 }
2161 NI_set_attribute(nel,"parent_type", "SUMA_mask");
2162 NI_set_attribute(nel,"parent_idcode", ADO_ID(ado));
2163 /* send surface nel */
2164 if (LocalHead)
2165 fprintf(SUMA_STDERR,
2166 "%s: Sending SURF_NORM nel ...\n", FuncName) ;
2167 nn = NI_write_element(
2168 SUMAg_CF->ns_v[SUMA_AFNI_STREAM_INDEX] , nel ,
2169 NI_TALK_MODE ) ;
2170 if( nn < 0 ){
2171 SUMA_S_Err("NI_write_element failed");
2172 }
2173 NI_free_element(nel);
2174 nel = NULL;
2175 ++nels_sent;
2176 }
2177
2178 if (1) {
2179 /* send triangles */
2180 nel = SUMA_makeNI_SurfIJK (SO);
2181 if (!nel) {
2182 SUMA_S_Err("SUMA_makeNI_SurfIJK failed");
2183 break;
2184 }
2185 NI_set_attribute(nel,"parent_type", "SUMA_mask");
2186 NI_set_attribute(nel,"parent_idcode", ADO_ID(ado));
2187 /* send surface nel */
2188 if (LocalHead)
2189 fprintf(SUMA_STDERR,"%s: Sending SURF_IJK nel ...\n",
2190 FuncName) ;
2191 nn = NI_write_element(
2192 SUMAg_CF->ns_v[SUMA_AFNI_STREAM_INDEX] , nel ,
2193 NI_TALK_MODE ) ;
2194
2195 if( nn < 0 ){
2196 SUMA_S_Err("NI_write_element failed");
2197 }
2198 NI_free_element(nel);
2199 nel = NULL;
2200 ++nels_sent;
2201 }
2202 if (nels_sent) {
2203 /* mark surface as sent to afni */
2204 SO->SentToAfni = YUP;
2205 } else {
2206 SUMA_SL_Warn("Nothing sent dude, what's happening?");
2207 }
2208 }
2209
2210 if (1) {
2211 SUMA_LH("Sending new center, SO = %p", SO);
2212 nel = NI_new_data_element("SUMA_mask", 0);
2213 NI_set_attribute(nel, "idcode", ADO_ID(ado));
2214 NI_SET_FLOATv(nel, "new_cen", EngineData->fv3, 3);
2215 if ((nn = NI_write_element(
2216 SUMAg_CF->ns_v[SUMA_AFNI_STREAM_INDEX] , nel ,
2217 NI_TALK_MODE ))<0) {
2218 SUMA_S_Err("NI_write_element failed\n");
2219 }
2220 if (LocalHead) SUMA_ShowNel(nel);
2221 NI_free_element(nel);
2222 nel = NULL;
2223 ++nels_sent;
2224 }
2225
2226 } break;
2227
2228 case SE_SetAfniSurfList:
2229 /* expects ivec in EngineData and a string in s saying what is to be
2230 sent, a flag in i 1=report transmission, 0 = be quiet*/
2231 { int nels_sent, N_Send, *SendList;
2232 char *stmp = NULL;
2233 static char LastPrefix[THD_MAX_PREFIX+1] = {"nuda"};
2234 if (EngineData->ivec_Dest != NextComCode ||
2235 EngineData->s_Dest != NextComCode ||
2236 EngineData->i_Dest != NextComCode) {
2237 fprintf (SUMA_STDERR,
2238 "Error %s: Data not destined correctly for %s (%d).\n",
2239 FuncName, NextCom, NextComCode);
2240 break;
2241 }
2242 N_Send = EngineData->ivec->n;
2243 SendList = EngineData->ivec->v;
2244 /* send to afni the list of surfaces in SendList*/
2245 if (N_Send) {
2246 for (ii=0; ii<N_Send; ++ii) {
2247 nels_sent = 0;
2248 SO = (SUMA_SurfaceObject *)(SUMAg_DOv[SendList[ii]].OP);
2249 if (EngineData->i && SO->Label)
2250 fprintf(SUMA_STDERR,"%s: Sending surface %s (%s)...\n",
2251 FuncName, SO->Label, EngineData->s);
2252 if (SUMA_iswordin(EngineData->s,"NodeList") == 1) {
2253 nel = SUMA_makeNI_SurfIXYZ (SO);
2254 if (!nel) {
2255 fprintf(SUMA_STDERR,
2256 "Error %s: SUMA_makeNI_SurfIXYZ failed\n",
2257 FuncName);
2258 break;
2259 }
2260 /* set up some defaults color
2261 (see matlab's rgbdectohex for visual aid)
2262 info for AFNI interface */
2263 switch(ii) {
2264 case 0: /* typically wm left*/
2265 NI_set_attribute(nel,
2266 "afni_surface_controls_toggle", "on");
2267 NI_set_attribute(nel,
2268 "afni_surface_controls_nodes","none");
2269 NI_set_attribute(nel,
2270 "afni_surface_controls_lines","#00ff00");
2271 /* green 0 255 0 */
2272 NI_set_attribute(nel,
2273 "afni_surface_controls_plusminus","none");
2274 break;
2275 case 1: /* typically pial left */
2276 NI_set_attribute(nel,
2277 "afni_surface_controls_toggle", "on");
2278 NI_set_attribute(nel,
2279 "afni_surface_controls_nodes","none");
2280 NI_set_attribute(nel,
2281 "afni_surface_controls_lines","#0000ff");
2282 /* 0 0 225 blue */
2283 NI_set_attribute(nel,
2284 "afni_surface_controls_plusminus","none");
2285 break;
2286 case 2: /* typically wm right */
2287 NI_set_attribute(nel,
2288 "afni_surface_controls_toggle", "on");
2289 NI_set_attribute(nel,
2290 "afni_surface_controls_nodes","none");
2291 NI_set_attribute(nel,
2292 "afni_surface_controls_lines","#ffff00");
2293 /* green 0 255 0*/
2294 NI_set_attribute(nel,
2295 "afni_surface_controls_plusminus","none");
2296 break;
2297 case 4: /* typically pial right */
2298 NI_set_attribute(nel,
2299 "afni_surface_controls_toggle", "on");
2300 NI_set_attribute(nel,
2301 "afni_surface_controls_nodes","none");
2302 NI_set_attribute(nel,
2303 "afni_surface_controls_lines","#ff0000");
2304 /* red 255 0 0 */
2305 NI_set_attribute(nel,
2306 "afni_surface_controls_plusminus","none");
2307 break;
2308 default: /* hot pink */
2309 NI_set_attribute(nel,
2310 "afni_surface_controls_toggle", "on");
2311 NI_set_attribute(nel,
2312 "afni_surface_controls_nodes","none");
2313 NI_set_attribute(nel,
2314 "afni_surface_controls_lines","#ff69b4");
2315 /* hot pink 255 105 180 */
2316 NI_set_attribute(nel,
2317 "afni_surface_controls_plusminus","none");
2318 break;
2319 }
2320 /* send surface nel */
2321 if (LocalHead)
2322 fprintf(SUMA_STDERR,"%s: Sending SURF_iXYZ nel...\n ", FuncName) ;
2323 nn = NI_write_element(
2324 SUMAg_CF->ns_v[SUMA_AFNI_STREAM_INDEX] , nel ,
2325 NI_TALK_MODE ) ;
2326
2327 if( nn < 0 ){
2328 SUMA_S_Err("NI_write_element failed\n");
2329 }
2330
2331 #if 0
2332 {
2333 NI_stream nstdout;
2334 nstdout = NI_stream_open( "fd:1","w");
2335 if( nstdout == NULL ){
2336 fprintf(SUMA_STDERR,"Can't open fd:1\n");
2337 break;
2338 }
2339 NI_write_element( nstdout , nel , NI_TEXT_MODE ) ;
2340 NI_stream_close(nstdout);
2341 }
2342 #endif
2343
2344 NI_free_element(nel);
2345 nel = NULL;
2346 ++nels_sent;
2347 }
2348 if (SUMA_iswordin(EngineData->s,"NodeNormList") == 1) {
2349 /* send node normals ZSS Oct 05 04 */
2350 nel = SUMA_makeNI_SurfINORM (SO);
2351 if (!nel) {
2352 SUMA_S_Err("SUMA_makeNI_SurfINORM failed");
2353 break;
2354 }
2355 /* send surface nel */
2356 if (LocalHead)
2357 fprintf(SUMA_STDERR,
2358 "%s: Sending SURF_NORM nel ...\n", FuncName) ;
2359 nn = NI_write_element(
2360 SUMAg_CF->ns_v[SUMA_AFNI_STREAM_INDEX] , nel ,
2361 NI_TALK_MODE ) ;
2362 if( nn < 0 ){
2363 SUMA_S_Err("NI_write_element failed");
2364 }
2365 NI_free_element(nel);
2366 nel = NULL;
2367 ++nels_sent;
2368 }
2369
2370 if (SUMA_iswordin(EngineData->s,"FaceSetList") == 1) {
2371 /* send triangles */
2372 nel = SUMA_makeNI_SurfIJK (SO);
2373 if (!nel) {
2374 SUMA_S_Err("SUMA_makeNI_SurfIJK failed");
2375 break;
2376 }
2377 /* send surface nel */
2378 if (LocalHead)
2379 fprintf(SUMA_STDERR,"%s: Sending SURF_IJK nel ...\n",
2380 FuncName) ;
2381 nn = NI_write_element(
2382 SUMAg_CF->ns_v[SUMA_AFNI_STREAM_INDEX] , nel ,
2383 NI_TALK_MODE ) ;
2384
2385 if( nn < 0 ){
2386 SUMA_S_Err("NI_write_element failed");
2387 }
2388 NI_free_element(nel);
2389 nel = NULL;
2390 ++nels_sent;
2391 }
2392 if (nels_sent) {
2393 /* mark surface as sent to afni */
2394 SO->SentToAfni = YUP;
2395 } else {
2396 SUMA_SL_Warn("Nothing sent dude, what's happening?");
2397 }
2398 }
2399 /* Now make afni switch to the surface volume of the
2400 last surface
2401 ZSS Sept 28 06: To avoid the jamming of
2402 AFNI and SUMA's write buffers. It used to be
2403 That AFNI switched automatically at the first surface
2404 and started writing colored data while suma was still
2405 writing surfaces. As a result, both programs got stuck
2406 waiting for the write operation to finish and it never
2407 did because buffers got full and no one was busy listening
2408 Kudos to Rick R. for having figured the Ladies' bug source */
2409 SO = (SUMA_SurfaceObject *)(SUMAg_DOv[SendList[N_Send-1]].OP);
2410 if (SO->VolPar && SO->VolPar->filecode) {
2411 if (strcmp(LastPrefix, SO->VolPar->prefix)) {
2412 nel = NI_new_data_element("ni_do", 0);
2413 NI_set_attribute ( nel, "ni_verb", "DRIVE_AFNI");
2414 stmp = SUMA_append_string("SWITCH_UNDERLAY A.",
2415 SO->VolPar->prefix);
2416 stmp = SUMA_append_replace_string(stmp, "0", " ", 1);
2417 NI_set_attribute ( nel, "ni_object", stmp);
2418 fprintf(SUMA_STDERR,
2419 "%s: Sending switch underlay command to (%s)...\n", FuncName, stmp);
2420 if (NI_write_element(
2421 SUMAg_CF->ns_v[SUMA_AFNI_STREAM_INDEX] , nel,
2422 NI_TALK_MODE ) < 0) {
2423 SUMA_SLP_Err("Failed to send SWITCH_ANATOMY to afni");
2424 }
2425 NI_free_element(nel) ; nel = NULL;
2426 if (stmp) SUMA_free(stmp); stmp = NULL;
2427 snprintf(LastPrefix, THD_MAX_PREFIX, "%s",
2428 SO->VolPar->prefix);
2429 }
2430 }
2431
2432 }
2433
2434 break;
2435 }
2436
2437 case SE_SetAfniSurf:
2438 /* expects nothing in EngineData */
2439 { int N_Send, *SendList, ti=1;
2440 SUMA_IVEC ivec;
2441 /* send to afni the list of anatomically correct surfaces
2442 and with a surface volume*/
2443 /* No surfaces are sent twice because there should not be
2444 duplicate local domain parent surfaces in SUMAg_DOv */
2445 /* prior to Wed Nov 6 17:47:20 EST 2002, only mappable surfaces
2446 that are related to the ones shown in the viewer
2447 were being sent to AFNI. Now all mappable surfaces loaded are
2448 sent regardless of what is shown */
2449 /* Jan. 08 04:
2450 All anatomically correct surfaces are now sent to AFNI */
2451 SendList =
2452 SUMA_FormSOListToSendToAFNI(SUMAg_DOv , SUMAg_N_DOv, &N_Send);
2453 if (N_Send > 0) {
2454 ivec.v = SendList;
2455 ivec.n = N_Send;
2456 ED = SUMA_InitializeEngineListData (SE_SetAfniSurfList);
2457 if (!(LocElm = SUMA_RegisterEngineListCommand ( list, ED,
2458 SEF_ivec, (void *)(&ivec),
2459 SES_Suma, (void *)sv,
2460 NOPE,
2461 SEI_Tail, NULL))) {
2462 fprintf(SUMA_STDERR,
2463 "Error %s: Failed to register element\n", FuncName);
2464 break;
2465 }
2466 if (!(LocElm = SUMA_RegisterEngineListCommand (
2467 list, ED,
2468 SEF_s, (void *)("NodeList, FaceSetList, NodeNormList"),
2469 SES_Suma, (void *)sv, NOPE,
2470 SEI_In, LocElm))) {
2471 fprintf(SUMA_STDERR,
2472 "Error %s: Failed to register element\n", FuncName);
2473 break;
2474 }
2475 if (!(LocElm = SUMA_RegisterEngineListCommand ( list, ED,
2476 SEF_i, (void *)&ti,
2477 SES_Suma, (void *)sv, NOPE,
2478 SEI_In, LocElm))) {
2479 fprintf(SUMA_STDERR,
2480 "Error %s: Failed to register element\n", FuncName);
2481 break;
2482 }
2483 if (SendList) SUMA_free(SendList); SendList = NULL;
2484 }else {
2485 if (N_Send < 0 &&
2486 !SUMA_Anatomical_DOs(SUMAg_DOv , SUMAg_N_DOv, NULL)) {
2487 SUMA_SLP_Warn(
2488 "None of the surfaces were marked as 'Anatomical'\n"
2489 "So none were sent to AFNI. You can label a surface\n"
2490 "as Anatomical by adding 'Anatomical = Y' where the \n"
2491 "surface is declared in the .spec file.");
2492 }
2493 }
2494
2495 break;
2496 }
2497
2498 case SE_SetAfniThisSurf:
2499 /* expects an idcode_str in EngineData->cp and what needs to be sent
2500 in EngineData->s for surface to be sent to AFNI */
2501 {
2502 SUMA_IVEC ivec;
2503 if (EngineData->s_Dest != NextComCode ||
2504 EngineData->cp_Dest != NextComCode ||
2505 EngineData->i_Dest != NextComCode) {
2506 fprintf (SUMA_STDERR,
2507 "Error %s: Data not destined correctly for %s \n"
2508 "((%d %d %d) %d).\n",
2509 FuncName, NextCom,
2510 EngineData->s_Dest, EngineData->cp_Dest,
2511 EngineData->i_Dest, NextComCode);
2512 break;
2513 }
2514 i = SUMA_findSO_inDOv(EngineData->cp, SUMAg_DOv, SUMAg_N_DOv);
2515 if (i<0) {
2516 SUMA_SL_Err("Surface Not Found!");
2517 break;
2518 }
2519 ivec.n = 1;
2520 ivec.v = (int*)SUMA_malloc(ivec.n*sizeof(int));
2521 ivec.v[0] = i;
2522 ED = SUMA_InitializeEngineListData (SE_SetAfniSurfList);
2523 if (!(LocElm = SUMA_RegisterEngineListCommand ( list, ED,
2524 SEF_ivec, (void *)(&ivec),
2525 SES_Suma, (void *)sv, NOPE,
2526 SEI_Tail, NULL))) {
2527 fprintf( SUMA_STDERR,
2528 "Error %s: Failed to register element\n", FuncName);
2529 break;
2530 }
2531 if (!(LocElm = SUMA_RegisterEngineListCommand ( list, ED,
2532 SEF_s, (void *)(EngineData->s),
2533 SES_Suma, (void *)sv, NOPE,
2534 SEI_In, LocElm))) {
2535 fprintf( SUMA_STDERR,
2536 "Error %s: Failed to register element\n", FuncName);
2537 break;
2538 }
2539 if (!(LocElm = SUMA_RegisterEngineListCommand ( list, ED,
2540 SEF_i, (void *)&(EngineData->i),
2541 SES_Suma, (void *)sv, NOPE,
2542 SEI_In, LocElm))) {
2543 fprintf(SUMA_STDERR,
2544 "Error %s: Failed to register element\n", FuncName);
2545 break;
2546 }
2547 SUMA_free(ivec.v);
2548 break;
2549 }
2550
2551 case SE_ToggleShowSelectedNode:
2552 /* expects nothing in EngineData */
2553 {
2554 int st = SUMA_SV_GetShowSelectedDatum(sv);
2555 SUMA_SV_SetShowSelectedDatum(sv, !st,NOPE);
2556 }
2557 break;
2558
2559 case SE_SetSelectedNode: {
2560 SUMA_ALL_DO *adodat=NULL;
2561 char *idcode=NULL, *eee=NULL;
2562 NI_element *nel=NULL;
2563
2564 /* expects a node (datum) index in i and maybe a ngr in ngr
2565 ngr is only being used when AFNI is the src of the call*/
2566 if (EngineData->i_Dest != NextComCode ||
2567 EngineData->ngr_Dest != NextComCode) {
2568 fprintf (SUMA_STDERR,
2569 "Error %s: Data not destined correctly for %s (%d).\n",
2570 FuncName, NextCom, NextComCode);
2571 break;
2572 }
2573 if (!(ado = SUMA_SV_Focus_ADO(sv))) {
2574 /* No so in focus */
2575 SUMA_S_Err("No SO/DO in focus");
2576 break;
2577 }
2578
2579 if ( EngineData->ngr &&
2580 (nel = SUMA_FindNgrNamedElement(EngineData->ngr,
2581 "SUMA_crosshair_xyz"))) {
2582 if ((idcode = NI_get_attribute(nel, "surface_idcode")) &&
2583 (adodat = iDO_ADO(SUMA_whichDOg(idcode)))) {
2584 /* Make sure datum can be related to the DO in Focus
2585 For now, all one gets is surfaces, but volume id will
2586 come next. Then you'll need to check for grid match perhaps
2587 before proceeding*/
2588 if (!SUMA_isRelated(adodat, ado,2)) {
2589 SUMA_LH("No relative of mine");
2590 break;
2591 }
2592 }
2593 }
2594
2595 if (EngineData->i >= 0 &&
2596 EngineData->i <= SUMA_ADO_Max_Datum_Index(ado)) {
2597 switch (ado->do_type) {
2598 case VO_type:
2599 if ( EngineData->iv15_Dest != NextComCode ||
2600 EngineData->fv15_Dest != NextComCode ) {
2601 SUMA_S_Err(
2602 "Data not destined correctly for VOtype %s (%d).\n",
2603 NextCom, NextComCode);
2604 break;
2605 }
2606 SUMA_ADO_Set_SelectedDatum(ado, EngineData->i,
2607 (void *)EngineData->iv15,
2608 (void *)EngineData->fv15);
2609 break;
2610 case TRACT_type:
2611 if ( EngineData->iv15_Dest != NextComCode ) {
2612 SUMA_S_Err(
2613 "Data not destined correctly for VOtype %s (%d).\n",
2614 NextCom, NextComCode);
2615 break;
2616 }
2617 SUMA_ADO_Set_SelectedDatum(ado,
2618 EngineData->i, (void *)EngineData->iv15, NULL);
2619 break;
2620 default:
2621 SUMA_ADO_Set_SelectedDatum(ado, EngineData->i, NULL, NULL);
2622 break;
2623 }
2624 } else {
2625 /* ignore -1, used in initializations */
2626 if (EngineData->i != -1) {
2627 SUMA_SLP_Err(
2628 "Datum index (%d) < 0 || >= Number of data nodes (%d)",
2629 EngineData->i, SUMA_ADO_Max_Datum_Index(ado)+1);
2630 SUMA_DUMP_TRACE("Whence the bad index");
2631 }
2632 break;
2633 }
2634 /* Nick's options. Jump to the sub-brick index corresponding
2635 to node */
2636 if (!(curColPlane = SUMA_ADO_CurColPlane(ado))) {
2637 SUMA_S_Err("No cur plane");
2638 break;
2639 }
2640 SUMA_LHv("Have %d, %d and %d\n",
2641 SUMAg_CF->YokeIntToNode,
2642 SDSET_VECNUM(curColPlane->dset_link),
2643 SUMA_ADO_N_Datum(ado));
2644 if (SUMAg_CF->YokeIntToNode &&
2645 !(SDSET_VECNUM(curColPlane->dset_link) %
2646 SUMA_ADO_N_Datum(ado))) {
2647 itmp = SDSET_VECNUM(curColPlane->dset_link) /
2648 SUMA_ADO_N_Datum(ado);
2649 if (!SUMA_SwitchColPlaneIntensity(ado, curColPlane,
2650 EngineData->i*itmp, 1)) {
2651 SUMA_S_Err("Failed to yoke intensity to node index");
2652 }
2653 }
2654 SUMAg_CF->YokeIntToNode = 0;
2655
2656 /* NB: I find it strange that there is this block here
2657 followed by a similar one in SUMA_UpdateNodeField
2658 Check for possible duplications ... */
2659 if (SUMAg_CF->callbacks && !SUMAg_CF->HoldClickCallbacks) {
2660 SUMA_LH("Activating callbacks");
2661 if (!SUMA_Selected_Node_Activate_Callbacks (
2662 ado, curColPlane,
2663 EngineData->Src, EngineData->ngr)) {
2664 SUMA_S_Err("Failed to activate callbacks");
2665 }
2666 }
2667
2668 /* get the controller up if it is not, and the mood is right*/
2669 SUMA_LH("Get controller up");
2670 SUMA_OpenSurfCont_if_other(sv->X->TOPLEVEL, ado, sv);
2671
2672 SUMA_LH("Update node field");
2673 SUMA_UpdateNodeField(ado);
2674 SUMA_LH("Done with SE_SetSelectedNode");
2675
2676 /* Might need to update nodemask -- experimental, need much love
2677 and cleanup
2678 Limitations: 1- constant cmask operation
2679 2- reloads all data for mask expression!
2680 3- will not work without controller
2681 4- Works only with integers */
2682 if (SUMAg_CF->Dev && ado->do_type == SO_type &&
2683 (eee = SUMA_EnvVal("SUMA_TEMP_NODE_CMASK_EXPR"))){
2684 SUMA_SurfaceObject *SO=(SUMA_SurfaceObject *)ado;
2685 SUMA_DRAW_MASKS *DW = SO->DW;
2686 char *etmp=NULL, stmp[32];
2687 int nxyz;
2688 float val;
2689
2690 /*
2691 Toy example for expression:
2692 setenv SUMA_TEMP_NODE_CMASK_EXPR '-a labels.niml.dset -expr equals(a,$SEL)'
2693 Or better yet, for the TT atlas isosurfaces
2694 setenv SUMA_TEMP_NODE_CMASK_EXPR '-a labels.niml.dset -expr equals(a,mod($SEL,200))+equals(a,mod($SEL,200)+200)'
2695 */
2696 TLH(1);
2697 DW->user_exp =
2698 SUMA_copy_string(eee);
2699 DW->cmask_exp = SUMA_copy_string(DW->user_exp);
2700 if (SUMA_GetValuesAtSelection(ado, 1, &val, NULL, NULL)) {
2701 sprintf(stmp,"%d", (int)val);
2702 SUMA_Swap_String(&(DW->cmask_exp), "$SEL", stmp);
2703 if (!DW->last_cmask_exp ||
2704 strcmp(DW->last_cmask_exp, DW->cmask_exp)) {
2705 /* This is a brute force regen, just for testing */
2706 SUMA_LH("Evaluating %s", DW->cmask_exp);
2707 SUMA_ifree(DW->nodemask);
2708 etmp = SUMA_copy_string(DW->cmask_exp); /* EDT_calcmask
2709 modifies the string */
2710 DW->nodemask = EDT_calcmask(etmp, &nxyz, SO->N_Node );
2711 SUMA_ifree(etmp);
2712 if (!DW->nodemask) {
2713 SUMA_S_Err("Failed to setup mask with %s",
2714 DW->cmask_exp);
2715 } else {
2716 if (nxyz != SO->N_Node) {
2717 SUMA_S_Err("Bigus calamitous!\n"
2718 "length of mask (%d) != SO->N_Node (%d).\n",
2719 nxyz, SO->N_Node);
2720 SUMA_ifree(DW->nodemask);
2721 } else {
2722 DW->last_cmask_exp = SUMA_copy_string(DW->cmask_exp);
2723 for (i=0, DW->N_nz_nodemask=0; i<SO->N_Node; ++i)
2724 if (DW->nodemask[i]) ++DW->N_nz_nodemask;
2725 ++DW->PatchRegenID;
2726 SUMA_LH("OK, %d non zeros, regenID %d",
2727 DW->N_nz_nodemask, DW->PatchRegenID);
2728 }
2729 }
2730
2731 } else {
2732 SUMA_LH("No re-eval last_cmask_exp: %s",
2733 DW->last_cmask_exp);
2734 }
2735 } else {
2736 SUMA_LH("Failed to get selection!");
2737 }
2738 TLH(0);
2739 }
2740
2741 break; }
2742 case SE_ToggleShowSelectedFaceSet:
2743 /* expects nothing ! */
2744 {
2745 int st = SUMA_SV_GetShowSelectedFaceSet(sv);
2746 SUMA_SV_SetShowSelectedFaceSet(sv,!st,NOPE);
2747 }
2748 break;
2749
2750 case SE_SetSelectedFaceSet:
2751 /* expects the index for the selected FaceSet */
2752 if (EngineData->i_Dest != NextComCode) {
2753 fprintf (SUMA_STDERR,
2754 "Error %s: Data not destined correctly for %s (%d).\n",
2755 FuncName, NextCom, NextComCode);
2756 break;
2757 }
2758 if (!(ado = SUMA_SV_Focus_ADO(sv))) {
2759 SUMA_S_Err("No SO/ADO in focus");
2760 break;
2761 }
2762 switch(ado->do_type) {
2763 case SO_type: {
2764 SUMA_SurfaceObject *SO=(SUMA_SurfaceObject *)ado;
2765 SUMA_VisX_Pointers4Display(SO, 1);/*coordinates as displayed*/
2766 if (EngineData->i < 0 || EngineData->i >= SO->N_FaceSet) {
2767 if (EngineData->i != -1){
2768 SUMA_SLP_Err("Node index < 0 || "
2769 "> Number of FaceSets in surface");
2770 }
2771 break;
2772 }
2773 ND = SO->NodeDim;
2774 NP = SO->FaceSetDim;
2775 ip = NP * EngineData->i;
2776 id = ND * SO->FaceSetList[ip];
2777 SO->FaceSetMarker->n0[0] = SO->NodeList[id];
2778 SO->FaceSetMarker->n0[1] = SO->NodeList[id+1];
2779 SO->FaceSetMarker->n0[2] = SO->NodeList[id+2];
2780 id = ND * SO->FaceSetList[ip+1];
2781 SO->FaceSetMarker->n1[0] = SO->NodeList[id];
2782 SO->FaceSetMarker->n1[1] = SO->NodeList[id+1];
2783 SO->FaceSetMarker->n1[2] = SO->NodeList[id+2];
2784 id = ND * SO->FaceSetList[ip+2];
2785 SO->FaceSetMarker->n2[0] = SO->NodeList[id];
2786 SO->FaceSetMarker->n2[1] = SO->NodeList[id+1];
2787 SO->FaceSetMarker->n2[2] = SO->NodeList[id+2];
2788 SO->FaceSetMarker->NormVect[0] = SO->FaceNormList[ip];
2789 SO->FaceSetMarker->NormVect[1] = SO->FaceNormList[ip+1];
2790 SO->FaceSetMarker->NormVect[2] = SO->FaceNormList[ip+2];
2791
2792 SO->SelectedFaceSet = EngineData->i;
2793 SUMA_VisX_Pointers4Display(SO, 0);/* revert to surf cooords. */
2794 SUMA_UpdateTriField(SO);
2795 break; }
2796 case GDSET_type:
2797 SUMA_S_Err("ambigous display method without variant");
2798 break;
2799 case CDOM_type:
2800 SUMA_S_Err("Help me please");
2801 break;
2802 case GRAPH_LINK_type: {
2803 SUMA_DSET *dset = SUMA_find_GLDO_Dset((SUMA_GraphLinkDO*)ado);
2804 SUMA_GRAPH_SAUX *Saux = SDSET_GSAUX(dset);
2805 if (EngineData->i < dset->Aux->range_node_index[0] ||
2806 EngineData->i > dset->Aux->range_node_index[1]) {
2807 if (EngineData->i != -1){
2808 SUMA_SLP_Err("Node index < 0 || "
2809 "> Number of nodes in graph dataset");
2810 SUMA_S_Errv("Index is %d, current range is: %ld %ld\n",
2811 EngineData->i,
2812 dset->Aux->range_node_index[0],
2813 dset->Aux->range_node_index[1]);
2814 SUMA_DUMP_TRACE("WEIRD 3");
2815 }
2816 break;
2817 }
2818 Saux->PR->iAltSel[SUMA_ENODE_0] = EngineData->i;
2819 Saux->PR->datum_index = -1;
2820 SUMA_UpdatePointField((SUMA_ALL_DO*)ado);
2821 break;}
2822 case TRACT_type: {
2823 SUMA_TractDO *tdo = (SUMA_TractDO *)ado;
2824 SUMA_TRACT_SAUX *Saux = TDO_TSAUX(tdo);
2825 SUMA_LH("No alternate selection for tracts");
2826 break;}
2827 case MASK_type: {
2828 SUMA_S_Err("What would that be for a mask?");
2829 break; }
2830 case VO_type: {
2831 SUMA_S_Err("Nothing done for volumes here yet");
2832 break; }
2833 default:
2834 SUMA_S_Errv("Not ready for %s\n", ADO_TNAME(ado));
2835 break;
2836 }
2837 break;
2838 case SE_ToggleCrossHair:
2839 /* expects nothing in EngineData */
2840 sv->ShowCrossHair = !sv->ShowCrossHair;
2841 XmToggleButtonSetState (sv->X->ViewMenu->mw[SW_ViewCrossHair],
2842 sv->ShowCrossHair, NOPE);
2843 break;
2844
2845 case SE_SetCrossHair:
2846 /* Expects Cross Hair coordinates in fv3, and ADO in vp */
2847 if (EngineData->fv3_Dest != NextComCode ||
2848 EngineData->vp_Dest != NextComCode) {
2849 fprintf (SUMA_STDERR,
2850 "Error %s: Data not destined correctly for %s (%d).\n",
2851 FuncName, NextCom, NextComCode);
2852 break;
2853 }
2854 ado = (SUMA_ALL_DO *)EngineData->vp;
2855 if (LocalHead)
2856 fprintf(SUMA_STDERR,"%s: Setting cross hair at %f %f %f\n",
2857 FuncName, EngineData->fv3[0],
2858 EngineData->fv3[1],
2859 EngineData-> fv3[2]);
2860 sv->Ch->c[0]= EngineData->fv3[0];
2861 sv->Ch->c[1]= EngineData->fv3[1];
2862 sv->Ch->c[2]= EngineData->fv3[2];
2863
2864 /* are we in VisX mode? */
2865 if (ado && ado->do_type == SO_type &&
2866 (SO = (SUMA_SurfaceObject *)ado) && SO->VisX.Applied) {
2867 /* undo the VisX */
2868 SUMA_Apply_VisX_Chain(EngineData->fv3, 1, SO->VisX.Xchain, 1);
2869 sv->Ch->c_noVisX[0]= EngineData->fv3[0];
2870 sv->Ch->c_noVisX[1]= EngineData->fv3[1];
2871 sv->Ch->c_noVisX[2]= EngineData->fv3[2];
2872 } else {
2873 sv->Ch->c_noVisX[0]=sv->Ch->c[0];
2874 sv->Ch->c_noVisX[1]=sv->Ch->c[1];
2875 sv->Ch->c_noVisX[2]=sv->Ch->c[2];
2876 }
2877
2878 /* Make slices go to same location */
2879 SUMA_VO_set_slices_XYZ(NULL, sv->Ch->c_noVisX);
2880
2881 /* Attempt to update crosshair corrdinates
2882 in open surface controllers */
2883 SUMA_UpdateXhairField(sv);
2884 break;
2885
2886 case SE_BindCrossHair:
2887 /* expects adoID to bind cross hair to*/
2888 if (EngineData->iv3_Dest != NextComCode) {
2889 fprintf (SUMA_STDERR,
2890 "Error %s: Data not destined correctly for %s (%d).\n",
2891 FuncName, NextCom, NextComCode);
2892 break;
2893 }
2894 sv->Ch->adoID = EngineData->iv3[0];
2895 sv->Ch->datumID = EngineData->iv3[1];
2896 sv->Ch->secID = EngineData->iv3[2];
2897 SUMA_UpdateCrossHairNodeLabelField(sv);
2898 break;
2899
2900 case SE_SetSOinFocus:
2901 /* expects surface ID in i */
2902 if (EngineData->i_Dest != NextComCode) {
2903 fprintf (SUMA_STDERR,
2904 "Error %s: Data not destined correctly for %s (%d).\n",
2905 FuncName, NextCom, NextComCode);
2906 break;
2907 }
2908 if (sv->Focus_DO_ID != EngineData->i) {
2909 /* a new one, update */
2910 sv->Focus_DO_ID = EngineData->i;
2911 SUMA_UpdateViewerTitle(sv);
2912 }
2913 break;
2914
2915 case SE_ToggleLockView:
2916 /* expects index of viewer in i to toggle its lock view */
2917 /* toggles the lock view button */
2918 if (EngineData->i_Dest != NextComCode) {
2919 fprintf (SUMA_STDERR,
2920 "Error %s: Data not destined correctly for %s (%d).\n",
2921 FuncName, NextCom, NextComCode);
2922 break;
2923 }
2924 SUMAg_CF->ViewLocked[EngineData->i] =
2925 !SUMAg_CF->ViewLocked[EngineData->i];
2926 /* update button if needed*/
2927 if (EngineData->Src != SES_SumaWidget) {
2928 XmToggleButtonSetState (
2929 SUMAg_CF->X->SumaCont->LockView_tbg[EngineData->i],
2930 SUMAg_CF->ViewLocked[EngineData->i], NOPE);
2931 }
2932
2933 /* call function to update the AllLock button */
2934 SUMA_set_LockView_atb ();
2935
2936 break;
2937
2938 case SE_ToggleLockAllViews:
2939 /* expects nothing, toggles all locked view buttons */
2940
2941 /* get the current value of the button */
2942 {
2943 SUMA_Boolean CurState;
2944 CurState =
2945 XmToggleButtonGetState (SUMAg_CF->X->SumaCont->LockAllView_tb);
2946 for (ii=0; ii< SUMA_MAX_SURF_VIEWERS; ++ii) {
2947 /* set all buttons accrodingly */
2948 XmToggleButtonSetState (
2949 SUMAg_CF->X->SumaCont->LockView_tbg[ii], CurState, NOPE);
2950 SUMAg_CF->ViewLocked[ii] = CurState;
2951 }
2952 }
2953 break;
2954
2955 case SE_ToggleLockAllCrossHair:
2956 /* expects nothing, toggles cross hair lock for all viewers */
2957 {
2958 char LockName[100];
2959 SUMA_LockEnum_LockType (SUMAg_CF->Locked[0], LockName);
2960 fprintf (SUMA_STDERR,
2961 "%s: Switching Locktype from %s", FuncName, LockName);
2962 /* change the locking type of viewer 0 */
2963 SUMAg_CF->Locked[0] = (int)fmod(SUMAg_CF->Locked[0]+1,
2964 SUMA_N_Lock_Types);
2965 SUMA_LockEnum_LockType (SUMAg_CF->Locked[0], LockName);
2966 fprintf (SUMA_STDERR," %s\n", LockName);
2967 /* update the widget*/
2968 SUMA_set_Lock_rb (SUMAg_CF->X->SumaCont->Lock_rbg, 0,
2969 SUMAg_CF->Locked[0]);
2970 /* Change the locking type of all remaining viewers,
2971 including unopen ones */
2972 for (ii=1; ii< SUMA_MAX_SURF_VIEWERS; ++ii) {
2973 SUMAg_CF->Locked[ii] = SUMAg_CF->Locked[0];
2974 SUMA_set_Lock_rb (SUMAg_CF->X->SumaCont->Lock_rbg, ii,
2975 SUMAg_CF->Locked[ii]);
2976 }
2977
2978 /* now update the all lock keys */
2979 SUMA_set_Lock_arb (SUMAg_CF->X->SumaCont->Lock_rbg);
2980
2981 }
2982 break;
2983
2984 case SE_SetLockAllCrossHair:
2985 /* expects a Lock value in i , sets the lock of all viewers */
2986 if (EngineData->i_Dest != NextComCode) {
2987 fprintf (SUMA_STDERR,
2988 "Error %s: Data not destined correctly for %s (%d).\n",
2989 FuncName, NextCom, NextComCode);
2990 break;
2991 }
2992 {
2993
2994 /* Change the locking type of all remaining viewers,
2995 including unopen ones */
2996 for (ii=0; ii< SUMA_MAX_SURF_VIEWERS; ++ii) {
2997 SUMAg_CF->Locked[ii] = EngineData->i;
2998 SUMA_set_Lock_rb (SUMAg_CF->X->SumaCont->Lock_rbg, ii,
2999 SUMAg_CF->Locked[ii]);
3000 }
3001
3002 /* now update the all lock keys */
3003 SUMA_set_Lock_arb (SUMAg_CF->X->SumaCont->Lock_rbg);
3004 }
3005 break;
3006
3007 case SE_LockCrossHair:
3008 /* expects nothing in EngineData */
3009 /* calls other viewers and determine if the cross hair
3010 needs to be locked to the calling sv */
3011
3012 /* check to see if other viewers need to share the fate */
3013 ii = SUMA_WhichSV(sv, SUMAg_SVv, SUMAg_N_SVv);
3014 if (ii < 0) {
3015 fprintf (SUMA_STDERR,
3016 "Error %s: Failed to find index of sv.\n", FuncName);
3017 break;
3018 }
3019 if (SUMAg_CF->Locked[ii]) { /* This one's locked, find out which
3020 other viewers are locked to this one */
3021 SUMA_LH("SV %d locked to something, maybe", ii);
3022 for (i=0; i < SUMAg_N_SVv; ++i) {
3023 svi = &SUMAg_SVv[i];
3024 if (i != ii) {
3025 SUMA_LH("Tiz locked %d to sv %d", SUMAg_CF->Locked[i], i);
3026 switch (SUMAg_CF->Locked[i]) {
3027 case SUMA_No_Lock:
3028 if (LocalHead)
3029 fprintf (SUMA_STDERR,
3030 "%s: No lock for viewer %d.\n",
3031 FuncName, i);
3032 break;
3033 case SUMA_XYZ_Lock:
3034 if (LocalHead)
3035 fprintf (SUMA_STDERR,
3036 "%s: Try to XYZ lock viewer %d.\n",
3037 FuncName, i);
3038 /* just set the XYZ, and free the binding
3039 to the surfaces */
3040 svi->Ch->c[0] = sv->Ch->c[0];
3041 svi->Ch->c[1] = sv->Ch->c[1];
3042 svi->Ch->c[2] = sv->Ch->c[2];
3043 svi->Ch->datumID = -1;
3044 svi->Ch->adoID = -1;
3045 /* FORCE a redisplay */
3046 svi->ResetGLStateVariables = YUP;
3047 SUMA_handleRedisplay((XtPointer)svi->X->GLXAREA);
3048 break;
3049 case SUMA_I_Lock:
3050 Found = NOPE;
3051 if (iDO_isSO(sv->Ch->adoID)) { /* Surface click */
3052 SUMA_SurfaceObject *SO1 = NULL, *SO2 = NULL;
3053
3054 SUMA_LHv("Try to I lock viewer %d to node"
3055 " %d.\n", i, sv->Ch->datumID);
3056
3057 /* determine the list of shown surfaces */
3058 N_SOlist = SUMA_RegisteredSOs(svi, SUMAg_DOv,
3059 SOlist);
3060
3061 /* first find the surface that the cross hair
3062 is bound to */
3063 if (sv->Ch->adoID < 0) {
3064 fprintf (SUMA_STDERR,
3065 "%s: Cannot link from this viewer's "
3066 "cross hair. No bound surface.\n",
3067 FuncName);
3068 break;
3069 }
3070 if (sv->Ch->datumID < 0) {
3071 SUMA_S_Errv("Cannot link from this viewer's"
3072 " cross hair. No datumID for DO %s\n",
3073 iDO_label(sv->Ch->adoID));
3074 break;
3075 }
3076
3077 SO1 = (SUMA_SurfaceObject *)
3078 SUMAg_DOv[sv->Ch->adoID].OP;
3079 Found = NOPE;
3080 it = 0;
3081 while (it < N_SOlist && !Found) {
3082 SO2 = (SUMA_SurfaceObject *)
3083 SUMAg_DOv[SOlist[it]].OP;
3084 if (SUMA_isRelated_SO(SO1, SO2, 2)) {
3085 /* high level relationship is allowed,
3086 but with same-side enforcement.
3087 A level 3 returns a match based on
3088 the number of nodes only, but that
3089 can cause trouble between left and
3090 right hemisphere surfaces where the
3091 same node index does not refer
3092 necessarily to the same anatomical
3093 areas. */
3094 svi->Ch->adoID = SOlist[it];
3095 if (sv->Ch->datumID > SO2->N_Node) {
3096 SUMA_S_Err("datumID is larger than"
3097 " N_Node. Setting datumID to 0.\n");
3098 svi->Ch->datumID = 0;
3099 }else{
3100 svi->Ch->datumID = sv->Ch->datumID;
3101 }
3102 /* set the XYZ */
3103 svi->Ch->c_noVisX[0] =
3104 SO2->NodeList[SO2->NodeDim*
3105 svi->Ch->datumID];
3106 svi->Ch->c_noVisX[1] =
3107 SO2->NodeList[SO2->NodeDim*
3108 svi->Ch->datumID+1];
3109 svi->Ch->c_noVisX[2] =
3110 SO2->NodeList[SO2->NodeDim*
3111 svi->Ch->datumID+2];
3112 svi->Ch->c[0]=svi->Ch->c_noVisX[0];
3113 svi->Ch->c[1]=svi->Ch->c_noVisX[1];
3114 svi->Ch->c[2]=svi->Ch->c_noVisX[2];
3115 if (SO2->VisX.Applied) { /* Apply the VisX */
3116 SUMA_Apply_VisX_Chain(svi->Ch->c, 1,
3117 SO2->VisX.Xchain, 0);
3118 }
3119 if (LocalHead)
3120 fprintf (SUMA_STDERR,
3121 "%s: new XYZ %f %f %f\n",
3122 FuncName,
3123 svi->Ch->c[0], svi->Ch->c[1],
3124 svi->Ch->c[2]);
3125 Found = YUP;
3126 }
3127 ++it;
3128 }
3129 } else if (iDO_isGLDO(sv->Ch->adoID)){
3130 SUMA_GraphLinkDO *gldo1, *gldo2=NULL;
3131 SUMA_DSET *dset=NULL;
3132 char *variant=NULL;
3133 int ido2;
3134 float fv6[6];
3135 SUMA_LHv("Try to I lock viewer %d to edge"
3136 " %d.\n", i, sv->Ch->datumID);
3137
3138 if (sv->Ch->adoID < 0) {
3139 fprintf (SUMA_STDERR,
3140 "%s: Cannot link from this viewer's "
3141 "cross hair. No bound graph.\n",
3142 FuncName);
3143 break;
3144 }
3145 if (sv->Ch->datumID < 0) {
3146 SUMA_LHv("No datumID for DO %s\n",
3147 iDO_label(sv->Ch->adoID));
3148 /* Don't exit here, because sometimes users
3149 select and entire set of edes, when they
3150 click on the nodes of a graph, you still
3151 want to refresh the other representations
3152 of that graph*/
3153 }
3154 gldo1 = (SUMA_GraphLinkDO *)
3155 SUMAg_DOv[sv->Ch->adoID].OP;
3156 if (!(dset = SUMA_find_GLDO_Dset(gldo1))) {
3157 SUMA_S_Err("Seal Attack!");
3158 break;
3159 }
3160 Found = NOPE;
3161 it = 0;
3162 while (it < svi->N_DO && !Found) {
3163 ido2 = svi->RegistDO[it].dov_ind;
3164 if (iDO_isGLDO(ido2)) {
3165 gldo2 = (SUMA_GraphLinkDO *)SUMAg_DOv[ido2].OP;
3166 variant = iDO_variant(ido2);
3167 } else {
3168 gldo2 = NULL;
3169 variant = NULL;
3170 }
3171 if ((SUMA_find_GLDO_Dset(gldo2) == dset)&&
3172 SUMA_IS_REAL_VARIANT(variant)) {
3173 svi->Ch->adoID = ido2;
3174 svi->Ch->datumID = sv->Ch->datumID;
3175
3176 /* set the XYZ */
3177 if (svi->Ch->datumID >= 0 &&
3178 (SUMA_GDSET_EdgeXYZ_eng(dset,
3179 svi->Ch->datumID,
3180 iDO_variant(ido2), fv6))){
3181 svi->Ch->c[0] = (fv6[0]+fv6[3])/2.0;
3182 svi->Ch->c[1] = (fv6[1]+fv6[4])/2.0;
3183 svi->Ch->c[2] = (fv6[2]+fv6[5])/2.0;
3184 if (LocalHead)
3185 fprintf (SUMA_STDERR,
3186 "%s: new XYZ %f %f %f\n",
3187 FuncName,
3188 svi->Ch->c[0], svi->Ch->c[1],
3189 svi->Ch->c[2]);
3190 Found = YUP;
3191 } else {
3192 /* Still declare it found, even if coords
3193 are not set because datum index is < 0
3194 This is for updating when you select
3195 and edge's point/node */
3196 Found = YUP;
3197 }
3198 }
3199 ++it;
3200 }
3201
3202 } else {
3203 SUMA_LHv(
3204 "No linkage for clicks on objects like %s\n",
3205 iDO_label(sv->Ch->adoID));
3206 }
3207 if (!Found) {
3208 if (LocalHead)
3209 fprintf (SUMA_STDERR,
3210 "%s: No related DOs found in"
3211 " viewer, cross hair will not be"
3212 "touched .\n", FuncName);
3213 break;
3214 } else {
3215 /* FORCE a redisplay */
3216 svi->ResetGLStateVariables = YUP;
3217 SUMA_handleRedisplay(
3218 (XtPointer)svi->X->GLXAREA);
3219 }
3220 break;
3221 default:
3222 fprintf(SUMA_STDERR,
3223 "Error %s: Lock type (%d) undefined.\n",
3224 FuncName, SUMAg_CF->Locked[ii]);
3225 break;
3226 }
3227 }
3228 }
3229 }else{
3230 /* not locked to anything */
3231 SUMA_LH("SV %d not locked to anything", ii);
3232 }
3233 break;
3234
3235 case SE_SetAfniCrossHair:
3236 /* expects a Do_icor flag in i */
3237 if (EngineData->i_Dest != NextComCode) {
3238 fprintf (SUMA_STDERR,
3239 "Error %s: Data not destined correctly for %s (%d).\n",
3240 FuncName, NextCom, NextComCode);
3241 break;
3242 }
3243 if ( SUMAg_CF->Connected_v[SUMA_AFNI_STREAM_INDEX] &&
3244 sv->LinkAfniCrossHair) {
3245 SUMA_LH("Sending cross hair nel: SUMA_crosshair_xyz") ;
3246 if (!(nel = SUMA_makeNI_CrossHair (sv))) {
3247 SUMA_S_Err("SUMA_makeNI_CrossHair failed");
3248 break;
3249 }
3250 if (EngineData->i) NI_set_attribute(nel,"Do_icor", "y");
3251 if ( (nn = NI_write_element(
3252 SUMAg_CF->ns_v[SUMA_AFNI_STREAM_INDEX] ,
3253 nel , NI_TEXT_MODE)) < 0) {
3254 SUMA_S_Err("NI_write_element failed");
3255 }
3256 NI_free_element(nel); nel = NULL;
3257 }
3258
3259 if ( SUMAg_CF->Connected_v[SUMA_HALLO_SUMA_LINE] ) {
3260 SUMA_LH("Sending cross hair nel: SUMA_crosshair_xyz") ;
3261 if (!(nel = SUMA_makeNI_CrossHair (sv))) {
3262 SUMA_S_Err("SUMA_makeNI_CrossHair failed");
3263 break;
3264 }
3265 if ( (nn = NI_write_element(
3266 SUMAg_CF->ns_v[SUMA_HALLO_SUMA_LINE] ,
3267 nel , NI_TEXT_MODE)) < 0) {
3268 SUMA_S_Err("NI_write_element failed");
3269 }
3270 NI_free_element(nel); nel = NULL;
3271 }
3272
3273 if ( SUMAg_CF->Connected_v[SUMA_INSTA_TRACT_LINE] ) {
3274 NI_group *ngr=NULL;
3275 if (!(ngr = SUMA_makeNI_InstaTract_Query (sv))) {
3276 SUMA_LH("SUMA_makeNI_InstaTract_Query failed, or "
3277 "nothing found");
3278 break;
3279 }
3280 if ( (nn = NI_write_element(
3281 SUMAg_CF->ns_v[SUMA_INSTA_TRACT_LINE] ,
3282 ngr , NI_BINARY_MODE)) < 0) {
3283 SUMA_S_Err("NI_write_element failed");
3284 }
3285 if (LocalHead) SUMA_ShowNel(ngr);
3286 NI_free_element(ngr); ngr = NULL;
3287 }
3288 break;
3289
3290 case SE_SetGICORnode:
3291 /* expects nothing in EngineData */
3292 /* sends the current node to Group Icor */
3293 if (SUMAg_CF->giset && SUMAg_CF->Connected_v[SUMA_GICORR_LINE]
3294 && !SUMAg_CF->HoldClickCallbacks &&
3295 (SO = SUMA_SV_Focus_SO(sv))) {
3296 SUMA_LHv("Sending notice to GICOR, SO_ID: %d\n",
3297 sv->Focus_DO_ID);
3298 if (SUMA_AFNI_gicor_setref(SO, SO->SelectedNode) < 0) {
3299 SUMA_S_Err("Failed in SUMA_AFNI_gicor_setref");
3300 }
3301 }
3302
3303 break;
3304
3305 case SE_SetLookAtNode:
3306 /* expects a center XYZ in EngineData->fv15[0 .. 2]
3307 expects a normal vector in EngineData->fv15[3 .. 5] */
3308 if (EngineData->fv15_Dest != NextComCode) {
3309 fprintf (SUMA_STDERR,
3310 "Error %s: Data not destined correctly for %s (%d).\n",
3311 FuncName, NextCom, NextComCode);
3312 break;
3313 }
3314
3315 { float CurrentDistance;
3316 float fm2_3[2][3]={ {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0} }, *dir;
3317
3318 /* modify the ViewFrom Value such that the viewing distance
3319 remains the same */
3320 CurrentDistance = sqrt((sv->GVS[sv->StdView].ViewFrom[0] -
3321 sv->GVS[sv->StdView].ViewCenter[0]) *
3322 (sv->GVS[sv->StdView].ViewFrom[0] -
3323 sv->GVS[sv->StdView].ViewCenter[0]) +
3324 (sv->GVS[sv->StdView].ViewFrom[1] -
3325 sv->GVS[sv->StdView].ViewCenter[1]) *
3326 (sv->GVS[sv->StdView].ViewFrom[1] -
3327 sv->GVS[sv->StdView].ViewCenter[1]) +
3328 (sv->GVS[sv->StdView].ViewFrom[2] -
3329 sv->GVS[sv->StdView].ViewCenter[2]) *
3330 (sv->GVS[sv->StdView].ViewFrom[2] -
3331 sv->GVS[sv->StdView].ViewCenter[2]));
3332
3333 /* set the ViewCenter Value to that of the node's XYZ*/
3334 sv->GVS[sv->StdView].ViewCenter[0] = EngineData->fv15[0];
3335 sv->GVS[sv->StdView].ViewCenter[1] = EngineData->fv15[1];
3336 sv->GVS[sv->StdView].ViewCenter[2] = EngineData->fv15[2];
3337
3338 /* obtain the LookFrom point based on CurrentDistance and
3339 the normal vector */
3340 dir = &(EngineData->fv15[3]);
3341 SUMA_POINT_AT_DISTANCE(dir,
3342 sv->GVS[sv->StdView].ViewCenter, CurrentDistance, fm2_3);
3343
3344 fprintf(SUMA_STDOUT,"\nPoints: %f %f %f\n%f %f %f\n",
3345 fm2_3[0][0], fm2_3[0][1], fm2_3[0][2],
3346 fm2_3[1][0], fm2_3[1][1], fm2_3[1][2]);
3347
3348 sv->GVS[sv->StdView].ViewFrom[0] = fm2_3[0][0];
3349 sv->GVS[sv->StdView].ViewFrom[1] = fm2_3[0][1];
3350 sv->GVS[sv->StdView].ViewFrom[2] = fm2_3[0][2];
3351
3352 gluLookAt ( sv->GVS[sv->StdView].ViewFrom[0],
3353 sv->GVS[sv->StdView].ViewFrom[1],
3354 sv->GVS[sv->StdView].ViewFrom[2],
3355 sv->GVS[sv->StdView].ViewCenter[0],
3356 sv->GVS[sv->StdView].ViewCenter[1],
3357 sv->GVS[sv->StdView].ViewCenter[2],
3358 sv->GVS[sv->StdView].ViewCamUp[0],
3359 sv->GVS[sv->StdView].ViewCamUp[1],
3360 sv->GVS[sv->StdView].ViewCamUp[2]);
3361 }
3362
3363 break;
3364 case SE_SetLookFrom:
3365 /* expects a center XYZ in EngineData->fv3[0 .. 2] */
3366 if (EngineData->fv3_Dest != NextComCode) {
3367 fprintf (SUMA_STDERR,
3368 "Error %s:\n"
3369 " Data not destined correctly for %s (%d).\n",
3370 FuncName, NextCom, NextComCode);
3371 break;
3372 }
3373 /* set the LookFrom option */
3374 sv->GVS[sv->StdView].ViewFrom[0] = EngineData->fv3[0];
3375 sv->GVS[sv->StdView].ViewFrom[1] = EngineData->fv3[1];
3376 sv->GVS[sv->StdView].ViewFrom[2] = EngineData->fv3[2];
3377 gluLookAt ( sv->GVS[sv->StdView].ViewFrom[0],
3378 sv->GVS[sv->StdView].ViewFrom[1],
3379 sv->GVS[sv->StdView].ViewFrom[2],
3380 sv->GVS[sv->StdView].ViewCenter[0],
3381 sv->GVS[sv->StdView].ViewCenter[1],
3382 sv->GVS[sv->StdView].ViewCenter[2],
3383 sv->GVS[sv->StdView].ViewCamUp[0],
3384 sv->GVS[sv->StdView].ViewCamUp[1],
3385 sv->GVS[sv->StdView].ViewCamUp[2]);
3386 break;
3387
3388 case SE_Redisplay_AllVisible:
3389 /* expects nothing in EngineData */
3390 /* post a redisplay to all visible viewers,
3391 Do the one where pointer is last */
3392 {
3393 int viewerorder[SUMA_MAX_SURF_VIEWERS], np = 0;
3394 /* set viewer order so that the one that
3395 last had the pointer gets displayed last */
3396 for (ii=0; ii<SUMAg_N_SVv; ++ii) {
3397 if (ii != SUMAg_CF->PointerLastInViewer) {
3398 viewerorder[np] = ii; ++np;
3399 }
3400 }
3401 if (np < SUMAg_N_SVv) {
3402 viewerorder[np] = SUMAg_CF->PointerLastInViewer;
3403 ++np;
3404 }
3405 if (np != SUMAg_N_SVv) {
3406 SUMA_S_Err("WTH?");
3407 }
3408 for (np=0; np<SUMAg_N_SVv; ++np) {
3409 ii = viewerorder[np];
3410 if (LocalHead)
3411 fprintf (SUMA_STDERR,
3412 "%s: Checking viewer %d.\n", FuncName, ii);
3413 if (!SUMAg_SVv[ii].isShaded && SUMAg_SVv[ii].X->TOPLEVEL) {
3414 /* you must check for both conditions because by default
3415 all viewers are initialized to isShaded = NOPE, even before
3416 they are ever opened */
3417 if (LocalHead)
3418 fprintf (SUMA_STDERR,
3419 "%s: Redisplaying viewer %d.\n", FuncName, ii);
3420 SUMAg_SVv[ii].ResetGLStateVariables = YUP;
3421 SUMA_postRedisplay(SUMAg_SVv[ii].X->GLXAREA, NULL, NULL);
3422 }
3423 }
3424 }
3425 break;
3426
3427
3428 case SE_Redisplay:
3429 /* expects nothing in EngineData */
3430 /*post a redisplay to one specific viewer*/
3431 if (LocalHead) fprintf (SUMA_STDOUT,"%s: Redisplay ...", FuncName);
3432 SUMA_postRedisplay(sv->X->GLXAREA, NULL, NULL);
3433 if (LocalHead) fprintf (SUMA_STDOUT," Done\n");
3434 break;
3435
3436 case SE_RedisplayNow:
3437 /* expects nothing in EngineData */
3438 /*call handle redisplay immediately to one specific viewer*/
3439 if (LocalHead)
3440 fprintf (SUMA_STDOUT,"%s: Redisplaying NOW ...", FuncName);
3441 sv->ResetGLStateVariables = YUP;
3442 SUMA_handleRedisplay((XtPointer)sv->X->GLXAREA);
3443 if (LocalHead) fprintf (SUMA_STDOUT," Done\n");
3444 break;
3445
3446 case SE_RedisplayNow_AllVisible:
3447 /* expects nothing in EngineData */
3448 /* causes an immediate redisplay to all visible viewers
3449 The viewer that had the pointer last gets
3450 displayed last. This is similar in concept
3451 to SE_RedisplayNow_AllOtherVisible */
3452 {
3453 int viewerorder[SUMA_MAX_SURF_VIEWERS], np = 0;
3454 /* set viewer order so that the one that
3455 last had the pointer gets displayed last */
3456 for (ii=0; ii<SUMAg_N_SVv; ++ii) {
3457 if (ii != SUMAg_CF->PointerLastInViewer) {
3458 viewerorder[np] = ii; ++np;
3459 }
3460 }
3461 if (np < SUMAg_N_SVv) {
3462 viewerorder[np] = SUMAg_CF->PointerLastInViewer;
3463 ++np;
3464 }
3465 if (np != SUMAg_N_SVv) {
3466 SUMA_S_Err("WTH?");
3467 }
3468 for (np=0; np<SUMAg_N_SVv; ++np) {
3469 ii = viewerorder[np];
3470 if (LocalHead)
3471 fprintf (SUMA_STDERR,
3472 "%s: Checking viewer %d.\n", FuncName, ii);
3473 if (!SUMAg_SVv[ii].isShaded && SUMAg_SVv[ii].X->TOPLEVEL) {
3474 /* you must check for both conditions because by default
3475 all viewers are initialized to isShaded = NOPE, even before
3476 they are ever opened */
3477 if (LocalHead)
3478 fprintf (SUMA_STDERR,
3479 "%s: Redisplaying viewer %d.\n", FuncName, ii);
3480 SUMAg_SVv[ii].ResetGLStateVariables = YUP;
3481 SUMA_handleRedisplay((XtPointer)SUMAg_SVv[ii].X->GLXAREA);
3482 SUMA_LHv("Returned redisplaying viewer %d.\n", ii);
3483 }
3484 }
3485 }
3486 break;
3487
3488 case SE_RedisplayNow_AllOtherVisible:
3489 /* expects nothing in EngineData, expects sv in srcp*/
3490 /* causes an immediate redisplay to all visible viewers
3491 other than sv*/
3492 for (ii=0; ii<SUMAg_N_SVv; ++ii) {
3493 if (LocalHead)
3494 fprintf (SUMA_STDERR,"%s: Checking viewer %d.\n",
3495 FuncName, ii);
3496 if (!SUMAg_SVv[ii].isShaded && SUMAg_SVv[ii].X->TOPLEVEL &&
3497 &(SUMAg_SVv[ii]) != sv) {
3498 /* you must check for both conditions because by default
3499 all viewers are initialized to isShaded = NOPE, even before
3500 they are ever opened */
3501 if (LocalHead)
3502 fprintf (SUMA_STDERR,"%s: Redisplaying viewer %d.\n",
3503 FuncName, ii);
3504 SUMAg_SVv[ii].ResetGLStateVariables = YUP;
3505 SUMA_handleRedisplay((XtPointer)SUMAg_SVv[ii].X->GLXAREA);
3506 }
3507 }
3508 break;
3509
3510 case SE_ResetOpenGLState:
3511 /* reset OPEN GL's state variables */
3512 /* expects the surface viewer pointer in vp */
3513 if (EngineData->vp_Dest != NextComCode) {
3514 SUMA_S_Err("Data not destined correctly for %s (%d).\n",
3515 NextCom, NextComCode);
3516 break;
3517 }
3518 SUMA_LH("Resetting OpenGL state variables.\n");
3519
3520 /* No need to call SUMA_OpenGLStateReset,
3521 that is now done in SUMA_display */
3522 svi = (SUMA_SurfaceViewer *)EngineData->vp;
3523 svi->ResetGLStateVariables = YUP;
3524 break;
3525
3526 case SE_ToggleForeground:
3527 /* expects nothing in EngineData */
3528 /* Show/hide the foreground */
3529 sv->ShowForeground = !sv->ShowForeground;
3530 if (!sv->ShowForeground) {
3531 fprintf(SUMA_STDOUT,"%s: Foreground Colors Off.\n", FuncName);
3532 } else {
3533 fprintf(SUMA_STDOUT,"%s: Foreground Colors ON.\n", FuncName);
3534 }
3535 /* set the color remix flag */
3536 if (!SUMA_SetShownLocalRemixFlag (sv)) {
3537 fprintf (SUMA_STDERR,
3538 "Error %s: Failed in SUMA_SetShownLocalRemixFlag.\n",
3539 FuncName);
3540 break;
3541 }
3542 break;
3543
3544 case SE_ToggleBackground:
3545 /* expects nothing in EngineData */
3546 /* Show/hide the background */
3547 sv->ShowBackground = !sv->ShowBackground;
3548 if (!sv->ShowBackground) {
3549 fprintf(SUMA_STDOUT,"%s: Background Colors OFF.\n", FuncName);
3550 } else {
3551 fprintf(SUMA_STDOUT,"%s: Background Colors ON.\n", FuncName);
3552 }
3553 /* set the color remix flag */
3554 if (!SUMA_SetShownLocalRemixFlag (sv)) {
3555 fprintf (SUMA_STDERR,
3556 "Error %s: Failed in SUMA_SetShownLocalRemixFlag.\n",
3557 FuncName);
3558 break;
3559 }
3560 break;
3561
3562 case SE_Home:
3563 /* expects nothing in EngineData, needs sv */
3564 SUMA_SetGLHome(sv);
3565 break;
3566
3567 case SE_Home_AllVisible:
3568 /* expects nothing in EngineData, needs no sv */
3569 {
3570 for (ii=0; ii<SUMAg_N_SVv; ++ii) {
3571 SUMA_LHv("Checking viewer %d.\n", ii);
3572 if (!SUMAg_SVv[ii].isShaded && SUMAg_SVv[ii].X->TOPLEVEL) {
3573 /* you must check for both conditions because by default
3574 all viewers are initialized to isShaded = NOPE,
3575 even before they are ever opened */
3576 SUMA_LHv("Home call viewer %d.\n", ii);
3577 if (!list) {
3578 SUMA_S_Err(
3579 "Should not be inside SUMA_Engine: ZSS Feb 02 05.\n");
3580 /* list = SUMA_CreateList();*/
3581 break;
3582 }
3583 SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_Home,
3584 SES_Suma, &SUMAg_SVv[ii]);
3585 }
3586 }
3587 }
3588 break;
3589
3590 case SE_FOVreset:
3591 /* expects nothing in EngineData */
3592 sv->FOV[sv->iState] = SUMA_sv_auto_fov(sv);
3593 /* reset the zooming */
3594 /* Now update the zoom compensation variable */
3595 if (sv->ZoomCompensate) {
3596 sv->ZoomCompensate = sv->FOV[sv->iState] /
3597 SUMA_sv_auto_fov(sv);
3598 if (sv->ZoomCompensate > 1) sv->ZoomCompensate = 1.0;
3599 /* weird stuff at zc_fac higher that 1.5 */
3600 else if (sv->ZoomCompensate < 0.005) sv->ZoomCompensate = 0.005;
3601 }
3602
3603 break;
3604
3605 case SE_SetNodeColor:
3606 /* expects a four-columned fm in EngineData->fm[0 .. N][0..3]
3607 [Node Index] [R] [G] [B] RGB between 0 and 1*/
3608 if (EngineData->fm_Dest != NextComCode) {
3609 fprintf (SUMA_STDERR,
3610 "Error %s: Data not destined correctly for %s (%d).\n",
3611 FuncName, NextCom, NextComCode);
3612 break;
3613 }
3614
3615 if ((SO = SUMA_SV_Focus_SO(sv))) {
3616 GLfloat *glar_ColorList;
3617 glar_ColorList = SUMA_GetColorList(sv, SO->idcode_str);
3618 if (!glar_ColorList) {
3619 SUMA_S_Err("NULL color list array. Trouble.");
3620 break;
3621 }
3622 for (i=0; i < EngineData->N_rows; ++i){
3623 ii = (int)(EngineData->fm[i][0]);
3624 glar_ColorList[4*ii] = EngineData->fm[i][1];
3625 glar_ColorList[4*ii+1] = EngineData->fm[i][2];
3626 glar_ColorList[4*ii+2] = EngineData->fm[i][3];
3627 glar_ColorList[4*ii+3] = 0.5;
3628 }
3629 }
3630 break;
3631
3632 case SE_FlipLight0Pos:
3633 /* expects nothing in EngineData */
3634 sv->light0_position[0] *= -1;
3635 sv->light0_position[1] *= -1;
3636 sv->light0_position[2] *= -1;
3637 sv->lit_for *= -1;
3638 glLightfv(GL_LIGHT0, GL_POSITION, sv->light0_position);
3639 break;
3640
3641 case SE_SetLight0Pos:
3642 /* expects light XYZ position in fv[3] */
3643 if (EngineData->fv3_Dest != NextComCode) {
3644 fprintf (SUMA_STDERR,
3645 "Error %s: Data not destined correctly for %s (%d).\n",
3646 FuncName, NextCom, NextComCode);
3647 break;
3648 }
3649 sv->light0_position[0] = EngineData->fv3[0];
3650 sv->light0_position[1] = EngineData->fv3[1];
3651 sv->light0_position[2] = EngineData->fv3[2];
3652 glLightfv(GL_LIGHT0, GL_POSITION, sv->light0_position);
3653 break;
3654
3655 case SE_HighlightNodes:
3656 /* highlight nodes inside the search box */
3657 /* expects Node XYZ in EngineData->fv15[0..2]
3658 Box dimensions in EngineData->fv15[3..5] */
3659 if (EngineData->fv15_Dest != NextComCode) {
3660 SUMA_S_Errv("Data not destined correctly for %s (%d).\n",
3661 NextCom, NextComCode);
3662 break;
3663 }
3664 if ((SO = SUMA_SV_Focus_SO(sv))) {
3665 SUMA_ISINBOX IB;
3666
3667 ND = SO->NodeDim;
3668
3669 SUMA_etime (&tt, 0);
3670 IB = SUMA_isinbox (SO->NodeList, SO->N_Node,
3671 &(EngineData->fv15[0]), &(EngineData->fv15[3]), YUP);
3672 delta_t = SUMA_etime (&tt, 1);
3673 fprintf (SUMA_STDOUT,"Elapsed time for isinbox operation: %f\n",
3674 delta_t);
3675 fprintf (SUMA_STDOUT,"\t%d nodes (out of %d) found in box\n",
3676 IB.nIsIn, SO->N_Node);
3677
3678 if (IB.nIsIn) { /* found some, find the closest node */
3679 /* locate the closest node and store it's id in EngineData*/
3680 SUMA_MIN_LOC_VEC (IB.d, IB.nIsIn, ft, it);
3681
3682 /* XYZ and normal of the closest to the center */
3683 /* Color the nodes*/
3684 fm = (float **)SUMA_allocate2D(IB.nIsIn, 4, sizeof(float));
3685 if (fm == NULL) {
3686 fprintf(SUMA_STDERR,
3687 "Error %s: Could not allocate for fm.\n", FuncName);
3688 break;
3689 }
3690 for (i=0; i < IB.nIsIn; ++i) {
3691 /* id = ND * IB.IsIn[i]; */
3692 /*fprintf (SUMA_STDOUT,"\t[%d] %f %f %f\n", IB.IsIn[i] ,\
3693 SO->NodeList[id], SO->NodeList[id+1],
3694 SO->NodeList[id+2]);*/
3695 /* color those nodes in yellow, just for kicks */
3696 fm[i][0] = (float)IB.IsIn[i];
3697 fm[i][1] = 0;
3698 fm[i][2] = 0.4;
3699 fm[i][3] = 0.4;
3700 }
3701
3702 /* Place a call to Redisplay and SetNodeColor */
3703 ED = SUMA_InitializeEngineListData (SE_SetNodeColor);
3704 ED->N_cols = 4;
3705 ED->N_rows = IB.nIsIn;
3706 if (!SUMA_RegisterEngineListCommand ( list, ED,
3707 SEF_fm, (void*)fm,
3708 SES_Suma, (void *)sv,
3709 NOPE,
3710 SEI_Head, NULL)) {
3711 fprintf(SUMA_STDERR,
3712 "Error %s: Failed to register element\n", FuncName);
3713 break;
3714 }
3715 ED = SUMA_InitializeEngineListData (SE_Redisplay);
3716 SUMA_RegisterEngineListCommand ( list, ED,
3717 SEF_Empty, NULL,
3718 SES_Suma, (void *)sv, NOPE,
3719 SEI_Head, NULL);
3720
3721 /* free fm since it was copied to EngineData*/
3722 if (fm) SUMA_free2D ((char **)fm, IB.nIsIn);
3723
3724 /* get ridd of IB's vectors */
3725 if (!SUMA_Free_IsInBox (&IB)) {
3726 fprintf( SUMA_STDERR,
3727 "Error %s: Failed to free IB\n", FuncName);
3728 }
3729 } else { /* no node is close enough */
3730 /* Do nothing yet */
3731 fprintf (SUMA_STDOUT,
3732 "\nNo nodes found inside the specified box.\n");
3733 }
3734 }
3735 break;
3736
3737 case SE_GetNearestNode:
3738 /* lookfor nodes inside the search box */
3739 /* expects Node XYZ in EngineData->fv15[0..2]
3740 Box dimensions in EngineData->fv15[3..5] */
3741 if (EngineData->fv15_Dest != NextComCode) {
3742 fprintf (SUMA_STDERR,
3743 "Error %s: Data not destined correctly for %s (%d).\n",
3744 FuncName, NextCom, NextComCode);
3745 break;
3746 }
3747 if ((SO = SUMA_SV_Focus_SO(sv))){
3748 SUMA_ISINBOX IB;
3749
3750 ND = SO->NodeDim;
3751 SUMA_etime (&tt, 0);
3752 IB = SUMA_isinbox (SO->NodeList, SO->N_Node,
3753 &(EngineData->fv15[0]), &(EngineData->fv15[3]),
3754 YUP);
3755 delta_t = SUMA_etime (&tt, 1);
3756 fprintf (SUMA_STDOUT,
3757 "Elapsed time for isinbox operation: %f\n", delta_t);
3758 fprintf (SUMA_STDOUT,
3759 "\t%d nodes (out of %d) found in box\n",
3760 IB.nIsIn, SO->N_Node);
3761
3762 if (IB.nIsIn) { /* found some, find the closest node */
3763 /* locate the closest node and store it's id in EngineData*/
3764 SUMA_MIN_LOC_VEC (IB.d, IB.nIsIn, ft, it);
3765
3766 /* get the XYZ and normal of that node */
3767 id = ND * IB.IsIn[it];
3768 fv15[0] = SO->NodeList[id];
3769 fv15[1] = SO->NodeList[id+1];
3770 fv15[2] = SO->NodeList[id+2];
3771 fv15[3] = SO->NodeNormList[id];
3772 fv15[4] = SO->NodeNormList[id+1];
3773 fv15[5] = SO->NodeNormList[id+2];
3774
3775 ED = SUMA_InitializeEngineListData (SE_SetLookAtNode);
3776 if (!SUMA_RegisterEngineListCommand ( list, ED,
3777 SEF_fv15, (void *)fv15,
3778 SES_Suma, (void *)sv,
3779 NOPE,
3780 SEI_Head, NULL)) {
3781 fprintf( SUMA_STDERR,
3782 "Error %s: Failed to register element\n",
3783 FuncName);
3784 break;
3785 }
3786
3787 /* get ridd of IB's vectors */
3788 if (!SUMA_Free_IsInBox (&IB)) {
3789 fprintf( SUMA_STDERR,
3790 "Error %s: Failed to free IB\n", FuncName);
3791 }
3792 } else { /* no node is close enough */
3793 /* Do nothing yet */
3794 }
3795 }
3796 break;
3797
3798 case SE_SetRotMatrix:
3799 /* expects a rotation matrix in fm, 4x4 */
3800 /* takes the rotation matrix 3x3 with 0 in 4th row and column
3801 and 1.0 at 4,4
3802 makes a quaternion from it and sets csv->currentQuat
3803 and posts redisplay */
3804 if (EngineData->fm_Dest != NextComCode) {
3805 fprintf (SUMA_STDERR,
3806 "Error %s: "
3807 "Data not destined correctly for %s (%d).\n",
3808 FuncName, NextCom, NextComCode);
3809 break;
3810 }
3811 if (EngineData->N_rows != 4 || EngineData->N_cols != 4) {
3812 fprintf( SUMA_STDERR,
3813 "Error %s: "
3814 "fm must have 4 cols and 4 rows in SetRotMatrix\n",
3815 FuncName);
3816 break;
3817 }
3818 if (!SUMA_mattoquat (EngineData->fm,
3819 sv->GVS[sv->StdView].currentQuat))
3820 {
3821 fprintf( SUMA_STDERR,
3822 "Error %s: Failed in SUMA_mattoquat\n", FuncName);
3823 break;
3824 }
3825 break;
3826
3827 case SE_SetObjectCont:
3828 case SE_SetSurfCont:
3829 /* expects a ngr and ADO in vp */
3830 if ( EngineData->ngr_Dest != NextComCode ||
3831 EngineData->vp_Dest != NextComCode) {
3832 fprintf (SUMA_STDERR,
3833 "Error %s: Data not destined correctly for %s (%d).\n"
3834 "Have %d and %d\n",
3835 FuncName, NextCom, NextComCode,
3836 EngineData->ngr_Dest, EngineData->vp_Dest);
3837 break;
3838 }
3839 ado = (SUMA_ALL_DO *)EngineData->vp;
3840 if (!(SurfCont = SUMA_ADO_Cont(ado))) {
3841 SUMA_S_Err("Need SurfCont for %s", ADO_LABEL(ado));
3842 break;
3843 }
3844
3845 if (NI_get_attribute(EngineData->ngr, "switch_surf")) {
3846 int is;
3847
3848 if (SUMA_iswordsame(ADO_GROUP(ado), sv->CurGroupName) != 1) {
3849 SUMA_S_Errv(
3850 "ADO %s is of group %s while viewer is of group %s.\n"
3851 "Need to switch group before switch_surf\n",
3852 ADO_LABEL(ado), ADO_GROUP(ado), sv->CurGroupName);
3853 break;
3854 }
3855 is = SUMA_WhichState(ADO_STATE(ado), sv, sv->CurGroupName);
3856 if (is < 0) {
3857 SUMA_S_Errv("Surface %s of group %s, viewer in group %s\n"
3858 "No surface of state %s found.\n",
3859 ADO_LABEL(ado), ADO_GROUP(ado), sv->CurGroupName ,
3860 ADO_STATE(ado));
3861 break;
3862 }
3863 if (!SUMA_SwitchState ( SUMAg_DOv, SUMAg_N_DOv, sv,
3864 is, sv->CurGroupName)) {
3865 SUMA_S_Err("Failed to switch state"); break;
3866 } else {
3867 sv->Focus_DO_ID = ADO_iDO(ado);
3868 sv->NewGeom = YUP; /* sv->ResetGLStateVariables
3869 was not enough */
3870 /* remove this attribute and call engine again
3871 for redisplay */
3872 NI_set_attribute(EngineData->ngr, "switch_surf", NULL);
3873 {
3874 DList *llist = SUMA_CreateList();
3875 SUMA_REGISTER_HEAD_COMMAND_NO_DATA(llist, SE_Redisplay,
3876 SES_SumaFromAny, sv);
3877 if (!SUMA_Engine (&llist)) {
3878 fprintf( stderr,
3879 "Error %s: SUMA_Engine call failed.\n",
3880 FuncName);
3881 }
3882 /* update titles */
3883 SUMA_UpdateViewerTitle(sv);
3884 }
3885 }
3886 }
3887
3888 if (NI_get_attribute(EngineData->ngr, "switch_dset")) {
3889 SUMA_OVERLAYS *ColPlane = SUMA_Fetch_OverlayPointer(
3890 ado,
3891 NI_get_attribute(EngineData->ngr, "switch_dset"),
3892 &itmp);
3893
3894 if (!ColPlane) {
3895 SUMA_S_Errv("Failed to find dset %s\n",
3896 NI_get_attribute(EngineData->ngr, "switch_dset"));
3897 break;
3898 } else {
3899 if (LocalHead)
3900 fprintf (SUMA_STDERR,
3901 "%s: Retrieved ColPlane named %s\n",
3902 FuncName, ColPlane->Name);
3903 SUMA_InitializeColPlaneShell(ado, ColPlane);
3904 SUMA_UpdateColPlaneShellAsNeeded(ado);
3905 /* update other open ColPlaneShells */
3906 /* If you're viewing one plane at a time, do a remix */
3907 if (SurfCont->ShowCurForeOnly)
3908 SUMA_Remixedisplay(ado);
3909 }
3910 }
3911
3912 if (NI_get_attribute(EngineData->ngr, "switch_cmap")) {
3913 /* find the colormap */
3914 if ((itmp = SUMA_Find_ColorMap(
3915 NI_get_attribute( EngineData->ngr, "switch_cmap"),
3916 SUMAg_CF->scm->CMv,
3917 SUMAg_CF->scm->N_maps, -2 )) < 0)
3918 {
3919 SUMA_S_Err("Failed to find color map"); break;
3920 } else {
3921 SUMA_COLOR_MAP *ColMap = SUMAg_CF->scm->CMv[itmp];
3922
3923 #if 0
3924 /* Set the menu button to the current choice */
3925 if (!SUMA_SetCmapMenuChoice(ado, ColMap->Name)) {
3926 SUMA_SL_Err("Failed in SUMA_SetCmapMenuChoice");
3927 }
3928
3929 /* switch to the recently loaded cmap */
3930 if (!SUMA_SwitchColPlaneCmap(ado, ColMap)) {
3931 SUMA_SL_Err("Failed in SUMA_SwitchColPlaneCmap");
3932 }
3933
3934 /* update Lbl fields */
3935 SUMA_UpdateNodeLblField(ado);
3936 #else
3937 SUMA_SwitchCmap(ado, ColMap, 1);
3938 #endif
3939 }
3940 }
3941
3942 if (NI_get_attribute(EngineData->ngr, "switch_cmode")) {
3943 /* Set the menu button to the current choice */
3944 if (!SUMA_SetCmodeMenuChoice (ado,
3945 NI_get_attribute(EngineData->ngr, "switch_cmode"))) {
3946 SUMA_SL_Err("Failed in SUMA_SetCmodeMenuChoice");
3947 }
3948
3949 /* update Lbl fields */
3950 SUMA_UpdateNodeLblField(ado);
3951 }
3952
3953 if (NI_get_attribute(EngineData->ngr, "load_cmap")) {
3954 SUMA_LoadCmapFile (NI_get_attribute(EngineData->ngr, "load_cmap"), (void *)ado);
3955 }
3956
3957 if (NI_get_attribute(EngineData->ngr, "I_sb")) {
3958 NI_GET_INT(EngineData->ngr, "I_sb", itmp);
3959 /* inefficient implementation, but avoids duplicate code... */
3960 if (!SUMA_SwitchColPlaneIntensity(ado,
3961 SurfCont->curColPlane, itmp, 1)) {
3962 SUMA_S_Err("Failed in I_sb"); break;
3963 }
3964 }
3965 if ((cbuf = NI_get_attribute(EngineData->ngr, "Dsp"))) {
3966
3967 /* inefficient implementation (causes redisplay,
3968 but avoids duplicating code... */
3969 if (!SUMA_SetDsetViewMode(ado,
3970 SUMA_ShowModeStr2ShowModeMenuItem(cbuf), 1)) {
3971 SUMA_S_Err("Failed in Dsp"); break;
3972 }
3973 }
3974
3975 /* Should you decide to fix/improve this block,
3976 You should call on function SUMA_SetRangeNew
3977 to set the values, that function will handle
3978 contralateral parallelization, but it does not
3979 seem to use the ShowMode variable so might want
3980 that added to SUMA_SetRangeNew_one ...
3981 Same for B_range and B_scale ZSS July 2012 */
3982 if (NI_get_attribute(EngineData->ngr, "I_range")) {
3983 char *stmp = NULL;
3984
3985 NI_GET_STR_CP(EngineData->ngr, "I_range", stmp);
3986 if (!stmp) {
3987 SUMA_S_Err("Bad I_range");
3988 } else {
3989 nn = SUMA_StringToNum(stmp, (void*)dv15, 3,2);
3990 if (nn < 1 || nn > 2) {
3991 SUMA_S_Err("Bad range string.");
3992 }else {
3993 if (nn == 1) {
3994 dv15[0] = -SUMA_ABS(dv15[0]); dv15[1] = -dv15[0]; }
3995 else if (dv15[0] > dv15[1]) {
3996 ftmp = dv15[0]; dv15[0] = dv15[1]; dv15[1] = ftmp; }
3997 /* have range, set it please */
3998 SUMA_LHv("Have range of %f, %f\n", dv15[0], dv15[1]);
3999 SurfCont->curColPlane->OptScl->IntRange[0] = dv15[0];
4000 SurfCont->curColPlane->OptScl->IntRange[1] = dv15[1];
4001 SUMA_INSERT_CELL_VALUE(SurfCont->SetRangeTable, 1, 1,
4002 SurfCont->curColPlane->OptScl->IntRange[0]);
4003 SUMA_INSERT_CELL_VALUE(SurfCont->SetRangeTable, 1, 2,
4004 SurfCont->curColPlane->OptScl->IntRange[1]);
4005 if (SurfCont->curColPlane->ShowMode > 0 &&
4006 SurfCont->curColPlane->ShowMode <
4007 SW_SurfCont_DsetViewXXX ) {
4008 if (!SUMA_ColorizePlane (SurfCont->curColPlane)) {
4009 SUMA_SLP_Err("Failed to colorize plane.\n");
4010 } else {
4011 SUMA_Remixedisplay(ado);
4012 SUMA_UpdateNodeValField(ado);
4013 SUMA_UpdateNodeLblField(ado);
4014 }
4015 }
4016 }
4017 SUMA_free(stmp); stmp = NULL;
4018 }
4019 }
4020
4021 if (NI_get_attribute(EngineData->ngr, "Clst")) {
4022 char *stmp = NULL;
4023 int an;
4024 float reset;
4025 NI_GET_STR_CP(EngineData->ngr, "Clst", stmp);
4026 if (!stmp) {
4027 SUMA_S_Err("Bad Clst");
4028 } else {
4029 nn = SUMA_StringToNum(stmp, (void*)dv15, 3,2);
4030 if (nn != 2) {
4031 SUMA_S_Err("Bad Clst string.");
4032 } else {
4033 /* set radius */
4034 an = SUMA_SetClustValue(ado, SurfCont->curColPlane, 1, 1,
4035 dv15[0], 0.0,
4036 1, 0, &reset); /* don't redisp. yet */
4037 if (an < 0) {
4038 SUMA_S_Err("An error occurred setting radius");
4039 } else {
4040 /* set area */
4041 an = SUMA_SetClustValue(ado, SurfCont->curColPlane, 1, 2,
4042 dv15[1], 0.0,
4043 1, 1, &reset); /* Now redisp. */
4044 if (an < 0) {
4045 SUMA_S_Err("An error occurred setting area");
4046 }
4047 }
4048 }
4049 }
4050 }
4051
4052 if (NI_get_attribute(EngineData->ngr, "UseClst")) {
4053 int tog = 0;
4054 if (NI_IS_STR_ATTR_EQUAL(EngineData->ngr, "UseClst", "y")) {
4055 if (!SurfCont->curColPlane->OptScl->Clusterize) tog = 1;
4056 } else if (NI_IS_STR_ATTR_EQUAL(EngineData->ngr, "UseClst", "n")){
4057 if (SurfCont->curColPlane->OptScl->Clusterize) tog = 1;
4058 } else {
4059 SUMA_S_Errv("Bad value of %s for UseClst. Nothing done.\n",
4060 NI_get_attribute(EngineData->ngr, "UseClst"));
4061 }
4062 if (tog) SUMA_SetClustTableTit(ado, SurfCont->curColPlane,
4063 1, 0, Button1);
4064 }
4065
4066 if (NI_get_attribute(EngineData->ngr, "shw_0")) {
4067 if (NI_IS_STR_ATTR_EQUAL(EngineData->ngr, "shw_0", "y"))
4068 SurfCont->curColPlane->OptScl->MaskZero = NOPE;
4069 else if (NI_IS_STR_ATTR_EQUAL(EngineData->ngr, "shw_0", "n"))
4070 SurfCont->curColPlane->OptScl->MaskZero = YUP;
4071 else {
4072 SUMA_S_Errv("Bad value of %s for shw_0, setting to 'y'\n",
4073 NI_get_attribute(EngineData->ngr, "shw_0"));
4074 SurfCont->curColPlane->OptScl->MaskZero = NOPE;
4075 }
4076 XmToggleButtonSetState ( SurfCont->ShowZero_tb,
4077 SurfCont->curColPlane->OptScl->MaskZero, YUP);
4078 }
4079
4080 if (NI_get_attribute(EngineData->ngr, "B_sb")) {
4081 NI_GET_INT(EngineData->ngr, "B_sb", itmp);
4082 /* inefficient implementation, but avoids duplicate code... */
4083 if (!SUMA_SwitchColPlaneBrightness(ado,
4084 SurfCont->curColPlane, itmp, 1)) {
4085 SUMA_S_Err("Failed in T_sb"); break;
4086 }
4087 }
4088
4089 /* See comment for "I_range" above before making further
4090 changes here */
4091 if (NI_get_attribute(EngineData->ngr, "B_range")) {
4092 char *stmp = NULL;
4093 NI_GET_STR_CP(EngineData->ngr, "B_range", stmp);
4094 if (!stmp) {
4095 SUMA_S_Err("Bad B_range");
4096 } else {
4097 nn = SUMA_StringToNum(stmp, (void*)dv15, 3,2);
4098 if (nn < 1 || nn > 2) {
4099 SUMA_S_Err("Bad range string.");
4100 }else {
4101 if (nn == 1) {
4102 dv15[0] = -SUMA_ABS(dv15[0]); dv15[1] = -dv15[0]; }
4103 else if (dv15[0] > dv15[1]) {
4104 ftmp = dv15[0]; dv15[0] = dv15[1]; dv15[1] = ftmp; }
4105 /* have range, set it please */
4106 SUMA_LHv("Have range of %f, %f\n", dv15[0], dv15[1]);
4107 SurfCont->curColPlane->OptScl->BrightRange[0] = dv15[0];
4108 SurfCont->curColPlane->OptScl->BrightRange[1] = dv15[1];
4109 SUMA_INSERT_CELL_VALUE(SurfCont->SetRangeTable, 2, 1,
4110 SurfCont->curColPlane->OptScl->BrightRange[0]);
4111 SUMA_INSERT_CELL_VALUE(SurfCont->SetRangeTable, 2, 2,
4112 SurfCont->curColPlane->OptScl->BrightRange[1]);
4113 if (SurfCont->curColPlane->ShowMode > 0 &&
4114 SurfCont->curColPlane->ShowMode <
4115 SW_SurfCont_DsetViewXXX) {
4116 if (!SUMA_ColorizePlane (SurfCont->curColPlane)) {
4117 SUMA_SLP_Err("Failed to colorize plane.\n");
4118 } else {
4119 SUMA_Remixedisplay(ado);
4120 SUMA_UpdateNodeValField(ado);
4121 SUMA_UpdateNodeLblField(ado);
4122 }
4123 }
4124 }
4125 SUMA_free(stmp); stmp = NULL;
4126 }
4127 }
4128 /* See comment for "I_range" above before making further
4129 changes here */
4130 if (NI_get_attribute(EngineData->ngr, "B_scale")) {
4131 char *stmp = NULL;
4132 NI_GET_STR_CP(EngineData->ngr, "B_scale", stmp);
4133 if (!stmp) {
4134 SUMA_S_Err("Bad B_scale");
4135 } else {
4136 nn = SUMA_StringToNum(stmp, (void*)dv15, 3,2);
4137 if (nn != 2) {
4138 SUMA_S_Err("Bad scale string.");
4139 }else {
4140 if (nn == 1) {
4141 dv15[0] = -SUMA_ABS(dv15[0]); dv15[1] = -dv15[0]; }
4142 else if (dv15[0] > dv15[1]) {
4143 ftmp = dv15[0]; dv15[0] = dv15[1]; dv15[1] = ftmp; }
4144 /* have range, set it please */
4145 SUMA_LHv("Have scale range of %f, %f\n",dv15[0], dv15[1]);
4146 SurfCont->curColPlane->OptScl->BrightMap[0] = dv15[0];
4147 SurfCont->curColPlane->OptScl->BrightMap[1] = dv15[1];
4148 SUMA_INSERT_CELL_VALUE(SurfCont->SetRangeTable, 3, 1,
4149 SurfCont->curColPlane->OptScl->BrightMap[0]);
4150 SUMA_INSERT_CELL_VALUE(SurfCont->SetRangeTable, 3, 2,
4151 SurfCont->curColPlane->OptScl->BrightMap[1]);
4152 if (SurfCont->curColPlane->ShowMode > 0 &&
4153 SurfCont->curColPlane->ShowMode <
4154 SW_SurfCont_DsetViewXXX) {
4155 if (!SUMA_ColorizePlane (SurfCont->curColPlane)) {
4156 SUMA_SLP_Err("Failed to colorize plane.\n");
4157 } else {
4158 SUMA_Remixedisplay(ado);
4159 SUMA_UpdateNodeValField(ado);
4160 SUMA_UpdateNodeLblField(ado);
4161 }
4162 }
4163 }
4164 SUMA_free(stmp); stmp = NULL;
4165 }
4166 }
4167
4168 if (NI_get_attribute(EngineData->ngr, "T_sb")) {
4169 NI_GET_INT(EngineData->ngr, "T_sb", itmp);
4170 /* inefficient implementation, but avoids duplicate code... */
4171 if (!SUMA_SwitchColPlaneThreshold(ado,
4172 SurfCont->curColPlane, itmp, 1)) {
4173 SUMA_S_Err("Failed in T_sb"); break;
4174 }
4175 }
4176 if (NI_get_attribute(EngineData->ngr, "T_val")) {
4177 int unt;
4178 char *stmp=NULL;
4179 float val=0.0;
4180 stmp = SUMA_copy_string(NI_get_attribute(
4181 EngineData->ngr, "T_val"));
4182 SUMA_LHv("Tval %s\n", stmp);
4183 unt = SUMA_NumStringUnits(stmp, 1);
4184 SUMA_LHv("Tval %s\n", stmp);
4185 if (SUMA_StringToNum(stmp, (void *)&val, 1, 1) != 1) {
4186 SUMA_BEEP;
4187 /* bad syntax, reset value*/
4188 if (LocalHead) fprintf (SUMA_STDERR, "%s: Bad syntax.\n", FuncName);
4189 } else {
4190 switch (unt) {
4191 case SUMA_P_VALUE_UNITS:
4192 if (LocalHead)
4193 fprintf( SUMA_STDERR,
4194 "%s:\nUnits in p value, transforming %f\n",
4195 FuncName, val);
4196 /* transform value from P to threshold value */
4197 val = (float)SUMA_Pval2ThreshVal (ado, (double)val);
4198 if (LocalHead)
4199 fprintf( SUMA_STDERR, " to %f\n", val);
4200 break;
4201 case SUMA_PERC_VALUE_UNITS:
4202 SUMA_LH("Units in percentile value, transforming %f\n", val);
4203 val = SUMA_OverlayPercentile(SurfCont->curColPlane, 'T', val);
4204 break;
4205 default:
4206 break;
4207 }
4208 }
4209 SUMA_MODIFY_CELL_VALUE(SurfCont->SetThrScaleTable, 0,0, val);
4210
4211 /* inefficient implementation, but avoids duplicate code... */
4212 SUMA_cb_SetScaleThr(EngineData->vp);
4213 SUMA_free(stmp);
4214 }
4215
4216 if (NI_get_attribute(EngineData->ngr, "Dim")) {
4217 char stmp[50];
4218 NI_GET_FLOAT(EngineData->ngr, "Dim", ftmp);
4219 SUMA_ColPlane_NewDimFact(ado, NULL, ftmp, 0);
4220 }
4221 if (NI_get_attribute(EngineData->ngr, "Alf")) {
4222 char stmp[50];
4223 NI_GET_FLOAT(EngineData->ngr, "Alf", ftmp);
4224 SUMA_ColPlane_NewAlphaThresh(ado, NULL, ftmp, 0);
4225 }
4226 if (NI_get_attribute(EngineData->ngr, "Opa")) {
4227 char stmp[50];
4228 NI_GET_FLOAT(EngineData->ngr, "Opa", ftmp);
4229
4230 #if 0 /* should be handled in new call format below */
4231 if (SurfCont && SurfCont->ColPlaneOpacity) {
4232 SurfCont->ColPlaneOpacity->value = ftmp;
4233 sprintf(stmp,"%.1f", ftmp);
4234 SUMA_SET_TEXT_FIELD( SurfCont->ColPlaneOpacity->textfield,
4235 stmp);
4236 }
4237 #endif
4238 /* inefficient implementation, but avoids duplicate code... */
4239 SUMA_ColPlane_NewOpacity(ado, NULL, ftmp, 0);
4240 }
4241 if (NI_get_attribute(EngineData->ngr, "view_dset")) {
4242 if (NI_IS_STR_ATTR_EQUAL(EngineData->ngr, "view_dset", "y")) {
4243 if (SurfCont->curColPlane->ShowMode < 0)
4244 SurfCont->curColPlane->ShowMode =
4245 -SurfCont->curColPlane->ShowMode;
4246 } else if (NI_IS_STR_ATTR_EQUAL(EngineData->ngr,
4247 "view_dset", "n")) {
4248 if (SurfCont->curColPlane->ShowMode > 0)
4249 SurfCont->curColPlane->ShowMode =
4250 -SurfCont->curColPlane->ShowMode;
4251 } else {
4252 SUMA_S_Errv("Bad value of %s for view_dset, setting to 'y'\n",
4253 NI_get_attribute(EngineData->ngr, "view_dset"));
4254 SurfCont->curColPlane->ShowMode = SW_SurfCont_DsetViewCol;
4255 }
4256 SUMA_Set_Menu_Widget( SurfCont->DsetViewModeMenu,
4257 SUMA_ShowMode2ShowModeMenuItem(
4258 SurfCont->curColPlane->ShowMode));
4259 }
4260 if (NI_get_attribute(EngineData->ngr, "do_draw_mask")) {
4261 if (NI_IS_STR_ATTR_EQUAL(EngineData->ngr,
4262 "do_draw_mask", "All")) {
4263 sv->DO_DrawMask = SDODM_All;
4264 } else if (NI_IS_STR_ATTR_EQUAL(EngineData->ngr,
4265 "do_draw_mask", "CrossHair") ||
4266 NI_IS_STR_ATTR_EQUAL(EngineData->ngr,
4267 "do_draw_mask", "n0CrossHair") ) {
4268 sv->DO_DrawMask = SDODM_n0CrossHair;
4269 } else if (NI_IS_STR_ATTR_EQUAL(EngineData->ngr,
4270 "do_draw_mask", "n1CrossHair") ) {
4271 sv->DO_DrawMask = SDODM_n1CrossHair;
4272 } else if (NI_IS_STR_ATTR_EQUAL(EngineData->ngr,
4273 "do_draw_mask", "n2CrossHair") ) {
4274 sv->DO_DrawMask = SDODM_n2CrossHair;
4275 } else if (NI_IS_STR_ATTR_EQUAL(EngineData->ngr,
4276 "do_draw_mask", "n3CrossHair") ) {
4277 sv->DO_DrawMask = SDODM_n3CrossHair;
4278 } else if (NI_IS_STR_ATTR_EQUAL(EngineData->ngr,
4279 "do_draw_mask", "Hide")) {
4280 sv->DO_DrawMask = SDODM_Hide;
4281 }
4282 /* redisplay */
4283 SUMA_postRedisplay(sv->X->GLXAREA, NULL, NULL);
4284 }
4285 if (NI_get_attribute(EngineData->ngr, "view_surf")) {
4286 switch (ado->do_type) {
4287 case SO_type:
4288 SO = (SUMA_SurfaceObject *)ado;
4289 if (NI_IS_STR_ATTR_EQUAL(EngineData->ngr, "view_surf", "y")) {
4290 SO->Show = YUP;
4291 } else if (NI_IS_STR_ATTR_EQUAL(EngineData->ngr,"view_surf","n")){
4292 SO->Show = NOPE;
4293 } else if (NI_IS_STR_ATTR_EQUAL(EngineData->ngr,
4294 "view_surf", "Viewer")) {
4295 SUMA_SET_SO_POLYMODE(SO,SRM_ViewerDefault);
4296 SUMA_Set_Menu_Widget( SurfCont->RenderModeMenu,
4297 SUMA_RenderMode2RenderModeMenuItem(SO->PolyMode+1));
4298 } else if (NI_IS_STR_ATTR_EQUAL(EngineData->ngr,
4299 "view_surf", "Fill")) {
4300 SUMA_SET_SO_POLYMODE(SO,SRM_Fill);
4301 SUMA_Set_Menu_Widget( SurfCont->RenderModeMenu,
4302 SUMA_RenderMode2RenderModeMenuItem(SO->PolyMode+1));
4303 } else if (NI_IS_STR_ATTR_EQUAL(EngineData->ngr,
4304 "view_surf", "Line")) {
4305 SUMA_SET_SO_POLYMODE( SO, SRM_Line );
4306 SUMA_Set_Menu_Widget( SurfCont->RenderModeMenu,
4307 SUMA_RenderMode2RenderModeMenuItem(SO->PolyMode+1));
4308 } else if (NI_IS_STR_ATTR_EQUAL(EngineData->ngr,
4309 "view_surf", "Points")) {
4310 SUMA_SET_SO_POLYMODE(SO,SRM_Points);
4311 SUMA_Set_Menu_Widget( SurfCont->RenderModeMenu,
4312 SUMA_RenderMode2RenderModeMenuItem(SO->PolyMode+1));
4313 } else if (NI_IS_STR_ATTR_EQUAL(EngineData->ngr,
4314 "view_surf", "Hide")) {
4315 SUMA_SET_SO_POLYMODE(SO,SRM_Hide);
4316 SUMA_Set_Menu_Widget( SurfCont->RenderModeMenu,
4317 SUMA_RenderMode2RenderModeMenuItem(SO->PolyMode+1));
4318 } else {
4319 SUMA_S_Errv("Bad value of %s for view_surf, setting to 'y'\n",
4320 NI_get_attribute(EngineData->ngr, "view_surf"));
4321 SO->Show = YUP; SUMA_SET_SO_POLYMODE(SO,SRM_Fill);
4322 }
4323 /* redisplay */
4324 SUMA_SiSi_I_Insist(); /* did not think that was necessary...
4325 But DriveSuma's -view_surf failed
4326 to redisplay properly unless you
4327 called the command twice or
4328 move the cursor into the GLXAREA.
4329 This line appears to fix the
4330 problem... */
4331 SUMA_postRedisplay(sv->X->GLXAREA, NULL, NULL);
4332 break;
4333 default:
4334 SUMA_S_Err("Not ready with view_surf for type %s",
4335 ADO_TNAME(ado));
4336 break;
4337 }
4338 }
4339 if (NI_get_attribute(EngineData->ngr, "trans_surf")) {
4340 switch (ado->do_type) {
4341 case SO_type:
4342 SO = (SUMA_SurfaceObject *)ado;
4343 if (NI_IS_STR_ATTR_EQUAL(EngineData->ngr,
4344 "trans_surf", "Viewer")) {
4345 SUMA_Set_ADO_TransMode(ado,STM_ViewerDefault,
4346 0, 1);
4347 } else {
4348 int N=0;
4349 NI_GET_INT(EngineData->ngr, "trans_surf", N);
4350 if (N < 0 || N > 16) {
4351 SUMA_S_Errv("Bad value for trans_surf of %s\n",
4352 NI_get_attribute(EngineData->ngr, "trans_surf"));
4353 } else {
4354 SUMA_Set_ADO_TransMode(ado,(N+STM_0), 0, 1);
4355 }
4356 }
4357 /* redisplay */
4358 SUMA_SiSi_I_Insist(); /* did not think that was necessary...
4359 But DriveSuma's -view_surf failed
4360 to redisplay properly unless you
4361 called the command twice or
4362 move the cursor into the GLXAREA.
4363 This line appears to fix the
4364 problem... */
4365 SUMA_postRedisplay(sv->X->GLXAREA, NULL, NULL);
4366 break;
4367 #if 0 /* UNTESTED, don't uncomment until you test*/
4368 case VolumeObject_type:{
4369 SUMA_VolumeObject *VO = (SUMA_VolumeObject *)ado;
4370 SUMA_VOL_SAUX *VSaux;
4371 if (!(VSaux = ADO_VSaux(ado))) {
4372 SUMA_S_Warn("No VSaux"); break;
4373 }
4374 if (NI_IS_STR_ATTR_EQUAL(EngineData->ngr,
4375 "trans_surf", "Viewer")) {
4376 SUMA_Set_ADO_TransMode(ado,SATM_ViewerDefault,
4377 0, 1);
4378 } else {
4379 int N=0;
4380 NI_GET_INT(EngineData->ngr, "trans_surf", N);
4381 if (N < 0 || N > 16) {
4382 SUMA_S_Errv("Bad value for trans_surf of %s\n",
4383 NI_get_attribute(EngineData->ngr, "trans_surf"));
4384 } else {
4385 SUMA_Set_ADO_TransMode(ado,(N+SATM_0), 0, 1);
4386 }
4387 }
4388 /* redisplay */
4389 SUMA_SiSi_I_Insist(); /* did not think that was necessary...
4390 But DriveSuma's -view_surf failed
4391 to redisplay properly unless you
4392 called the command twice or
4393 move the cursor into the GLXAREA.
4394 This line appears to fix the
4395 problem... */
4396 SUMA_postRedisplay(sv->X->GLXAREA, NULL, NULL);
4397 break; }
4398 #endif
4399 default:
4400 SUMA_S_Err("Not ready with trans_surf for type %s",
4401 ADO_TNAME(ado));
4402 break;
4403 }
4404 }
4405
4406 if (NI_get_attribute(EngineData->ngr, "1_only")) {
4407 if (NI_IS_STR_ATTR_EQUAL(EngineData->ngr, "1_only", "y")) {
4408 itmp = YUP;
4409 } else if (NI_IS_STR_ATTR_EQUAL(EngineData->ngr, "1_only", "n")) {
4410 itmp = NOPE;
4411 } else {
4412 SUMA_S_Errv("Bad value of %s for 1_only, setting to 'y'\n",
4413 NI_get_attribute(EngineData->ngr, "1_only"));
4414 itmp = YUP;
4415 }
4416 if (!SUMA_ColPlaneShowOneFore_Set(ado, itmp, 0)) {
4417 SUMA_S_Err("Failed to set one only");
4418 break;
4419 }
4420 }
4421
4422 if (NI_get_attribute(EngineData->ngr, "View_Surf_Cont")) {
4423 if (NI_IS_STR_ATTR_EQUAL(EngineData->ngr,
4424 "View_Surf_Cont", "y")) {
4425 if (!SUMA_viewSurfaceCont(NULL, ado, sv)) {
4426 SUMA_S_Err("Failed open surfcont");
4427 break;
4428 }
4429 } else if (NI_IS_STR_ATTR_EQUAL(EngineData->ngr,
4430 "View_Surf_Cont", "n")) {
4431 SUMA_LH("Closing surface controller");
4432 SUMA_cb_closeSurfaceCont(NULL, (XtPointer)ado, NULL);
4433 }
4434 }
4435
4436 if (NI_get_attribute(EngineData->ngr,"Masks")) {
4437 SUMA_cb_Mask(NULL, ado, sv);
4438 }
4439
4440 if (NI_get_attribute(EngineData->ngr,"2xMasks")) {
4441 SUMA_cb_Mask(NULL, ado, sv);
4442 SUMA_cb_Mask(NULL, ado, sv);
4443 }
4444
4445 if ((cbuf = NI_get_attribute(EngineData->ngr,
4446 "Write_Surf_Cont_Help"))) {
4447 if (!SUMA_WriteCont_Help(SO_type, TXT, cbuf)) {
4448 SUMA_S_Err("Failed to write SurfCont help to %s", cbuf);
4449 }
4450 }
4451
4452 if ((cbuf = NI_get_attribute(EngineData->ngr,
4453 "Snap_Surf_Cont_Widgets"))) {
4454 if (!SUMA_Snap_AllCont(SO_type, cbuf)) {
4455 SUMA_S_Err("Failed to write SurfCont widgets to %s", cbuf);
4456 }
4457 }
4458
4459 if ((cbuf = NI_get_attribute(EngineData->ngr,
4460 "Write_Surf_Cont_Sphinx_Help"))) {
4461 if (!SUMA_WriteCont_Help(SO_type, SPX, cbuf)) {
4462 SUMA_S_Err("Failed to write SurfCont help to %s", cbuf);
4463 }
4464 }
4465
4466 if ((cbuf = NI_get_attribute(EngineData->ngr,
4467 "Write_Suma_Cont_Help"))) {
4468 if (!SUMA_WriteCont_Help(not_DO_type, TXT, cbuf)) {
4469 SUMA_S_Err("Failed to write SumaCont help to %s", cbuf);
4470 }
4471 }
4472
4473 if ((cbuf = NI_get_attribute(EngineData->ngr,
4474 "Snap_Suma_Cont_Widgets"))) {
4475 if (!SUMA_Snap_AllCont(not_DO_type, cbuf)) {
4476 SUMA_S_Err("Failed to write SumaCont widgets to %s", cbuf);
4477 }
4478 }
4479
4480 if ((cbuf = NI_get_attribute(EngineData->ngr,
4481 "Write_Suma_Cont_Sphinx_Help"))) {
4482 if (!SUMA_WriteCont_Help(not_DO_type, SPX, cbuf)) {
4483 SUMA_S_Err("Failed to write SumaCont help to %s", cbuf);
4484 }
4485 }
4486
4487 if ((cbuf = NI_get_attribute(EngineData->ngr,
4488 "Write_Tract_Cont_Help"))) {
4489 if (!SUMA_WriteCont_Help(TRACT_type, TXT, cbuf)) {
4490 SUMA_S_Err("Failed to write TractCont help to %s", cbuf);
4491 }
4492 }
4493
4494 if ((cbuf = NI_get_attribute(EngineData->ngr,
4495 "Snap_Tract_Cont_Widgets"))) {
4496 if (!SUMA_Snap_AllCont(TRACT_type, cbuf)) {
4497 SUMA_S_Err("Failed to write TractCont widgets to %s", cbuf);
4498 }
4499 }
4500
4501 if ((cbuf = NI_get_attribute(EngineData->ngr,
4502 "Write_Tract_Cont_Sphinx_Help"))) {
4503 if (!SUMA_WriteCont_Help(TRACT_type, SPX, cbuf)) {
4504 SUMA_S_Err("Failed to write TractCont help to %s", cbuf);
4505 }
4506 }
4507
4508 if ((cbuf = NI_get_attribute(EngineData->ngr,
4509 "Write_Mask_Cont_Help"))) {
4510 if (!SUMA_WriteCont_Help(MASK_type, TXT, cbuf)) {
4511 SUMA_S_Err("Failed to write MaskCont help to %s", cbuf);
4512 }
4513 }
4514
4515 if ((cbuf = NI_get_attribute(EngineData->ngr,
4516 "Snap_Mask_Cont_Widgets"))) {
4517 if (!SUMA_Snap_AllCont(MASK_type, cbuf)) {
4518 SUMA_S_Err("Failed to write MaskCont widgets to %s", cbuf);
4519 }
4520 }
4521
4522 if ((cbuf = NI_get_attribute(EngineData->ngr,
4523 "Write_Mask_Cont_Sphinx_Help"))) {
4524 if (!SUMA_WriteCont_Help(MASK_type, SPX, cbuf)) {
4525 SUMA_S_Err("Failed to write MaskCont help to %s", cbuf);
4526 }
4527 }
4528
4529
4530 if ((cbuf = NI_get_attribute(EngineData->ngr,
4531 "Write_Vol_Cont_Help"))) {
4532 if (!SUMA_WriteCont_Help(VO_type, TXT, cbuf)) {
4533 SUMA_S_Err("Failed to write TractCont help to %s", cbuf);
4534 }
4535 }
4536
4537 if ((cbuf = NI_get_attribute(EngineData->ngr,
4538 "Snap_Vol_Cont_Widgets"))) {
4539 if (!SUMA_Snap_AllCont(VO_type, cbuf)) {
4540 SUMA_S_Err("Failed to write VolCont widgets to %s", cbuf);
4541 }
4542 }
4543
4544 if ((cbuf = NI_get_attribute(EngineData->ngr,
4545 "Write_Vol_Cont_Sphinx_Help"))) {
4546 if (!SUMA_WriteCont_Help(VO_type, SPX, cbuf)) {
4547 SUMA_S_Err("Failed to write TractCont help to %s", cbuf);
4548 }
4549 }
4550
4551 if ((cbuf = NI_get_attribute(EngineData->ngr,
4552 "Write_Graph_Cont_Help"))) {
4553 if (!SUMA_WriteCont_Help(GRAPH_LINK_type, TXT, cbuf)) {
4554 SUMA_S_Err("Failed to write GraphCont help to %s", cbuf);
4555 }
4556 }
4557
4558 if ((cbuf = NI_get_attribute(EngineData->ngr,
4559 "Snap_Graph_Cont_Widgets"))) {
4560 if (!SUMA_Snap_AllCont(GRAPH_LINK_type, cbuf)) {
4561 SUMA_S_Err("Failed to write GraphCont widgets to %s", cbuf);
4562 }
4563 }
4564
4565 if ((cbuf = NI_get_attribute(EngineData->ngr,
4566 "Write_Graph_Cont_Sphinx_Help"))) {
4567 if (!SUMA_WriteCont_Help(GRAPH_LINK_type, SPX, cbuf)) {
4568 SUMA_S_Err("Failed to write GraphCont help to %s", cbuf);
4569 }
4570 }
4571
4572 if ((cbuf = NI_get_attribute(EngineData->ngr,
4573 "Write_ROI_Cont_Help"))) {
4574 if (!SUMA_WriteCont_Help(ROIdO_type, TXT, cbuf)) {
4575 SUMA_S_Err("Failed to write ROICont help to %s", cbuf);
4576 }
4577 }
4578
4579 if ((cbuf = NI_get_attribute(EngineData->ngr,
4580 "Snap_ROI_Cont_Widgets"))) {
4581 if (!SUMA_Snap_AllCont(ROIdO_type, cbuf)) {
4582 SUMA_S_Err("Failed to write ROICont widgets to %s", cbuf);
4583 }
4584 }
4585
4586 if ((cbuf = NI_get_attribute(EngineData->ngr,
4587 "Write_ROI_Cont_Sphinx_Help"))) {
4588 if (!SUMA_WriteCont_Help(ROIdO_type, SPX, cbuf)) {
4589 SUMA_S_Err("Failed to write ROICont help to %s", cbuf);
4590 }
4591 }
4592
4593 if ((cbuf = NI_get_attribute(EngineData->ngr,
4594 "Write_Mouse_Keyb_Help"))) {
4595 FILE *fout = fopen(cbuf,"w");
4596 if (!fout) {
4597 SUMA_S_Err("Failed to open %s for writing", cbuf);
4598 } else {
4599 SUMA_help_message(fout, TXT);
4600 fclose(fout); fout = NULL;
4601 }
4602 }
4603
4604 if ((cbuf = NI_get_attribute(EngineData->ngr,
4605 "Write_Mouse_Keyb_Sphinx_Help"))) {
4606 FILE *fout = fopen(cbuf,"w");
4607 if (!fout) {
4608 SUMA_S_Err("Failed to open %s for writing", cbuf);
4609 } else {
4610 SUMA_help_message(fout, SPX);
4611 fclose(fout); fout = NULL;
4612 }
4613 }
4614
4615 if ((cbuf = NI_get_attribute(EngineData->ngr,
4616 "Write_Mouse_Cmap_Keyb_Help"))) {
4617 FILE *fout = fopen(cbuf,"w");
4618 if (!fout) {
4619 SUMA_S_Err("Failed to open %s for writing", cbuf);
4620 } else {
4621 SUMA_cmap_help_message(fout, TXT);
4622 fclose(fout); fout = NULL;
4623 }
4624 }
4625
4626 if ((cbuf = NI_get_attribute(EngineData->ngr,
4627 "Write_Mouse_Cmap_Keyb_Sphinx_Help"))) {
4628 FILE *fout = fopen(cbuf,"w");
4629 if (!fout) {
4630 SUMA_S_Err("Failed to open %s for writing", cbuf);
4631 } else {
4632 SUMA_cmap_help_message(fout, SPX);
4633 fclose(fout); fout = NULL;
4634 }
4635 }
4636
4637 if ((cbuf = NI_get_attribute(EngineData->ngr,
4638 "Delete_All_Masks"))) {
4639 SUMA_DeleteAllMasks(NULL, NULL, 0);
4640 }
4641
4642 if ((cbuf = NI_get_attribute(EngineData->ngr,
4643 "Load_Masks"))) {
4644 SUMA_LoadMultiMasks(cbuf, NULL);
4645 }
4646
4647 if ((cbuf = NI_get_attribute(EngineData->ngr,
4648 "Save_Masks"))) {
4649 SUMA_SaveMultiMasks(cbuf, NULL);
4650 }
4651
4652 break;
4653
4654 case SE_SetViewerCont:
4655 /* expects a ngr and ADO in vp */
4656 if ( EngineData->ngr_Dest != NextComCode ||
4657 EngineData->vp_Dest != NextComCode) {
4658 fprintf (SUMA_STDERR,
4659 "Error %s: Data not destined correctly for %s (%d).\n"
4660 "Have %d and %d\n",
4661 FuncName, NextCom, NextComCode,
4662 EngineData->ngr_Dest, EngineData->vp_Dest);
4663 break;
4664 }
4665 ado = (SUMA_ALL_DO *)EngineData->vp;
4666 if (NI_get_attribute(EngineData->ngr, "inout_notify")) {
4667 if (NI_IS_STR_ATTR_EQUAL(EngineData->ngr, "inout_notify", "y"))
4668 SUMA_setIO_notify(1);
4669 else if (NI_IS_STR_ATTR_EQUAL(EngineData->ngr,
4670 "inout_notify", "n"))
4671 SUMA_setIO_notify(0);
4672 else {
4673 SUMA_S_Errv("Bad value of %s for inout_notify, "
4674 "setting to 'n'\n",
4675 NI_get_attribute(EngineData->ngr, "inout_notify"));
4676 SUMA_setIO_notify(0);
4677 }
4678
4679 }
4680
4681 if (NI_get_attribute(EngineData->ngr, "bkg_col")) {
4682 char *stmp = NULL;
4683 NI_GET_STR_CP(EngineData->ngr, "bkg_col", stmp);
4684 if (!stmp) {
4685 SUMA_S_Err("Bad bkg_col");
4686 } else {
4687 nn = SUMA_StringToNum(stmp, (void*)dv15, 4,4);
4688 if (nn != 4) {
4689 SUMA_S_Err("Bad bkg_col string.");
4690 } else {
4691 /* have bkg_col, set it please */
4692 SUMA_LHv("Have bkg_col of %f, %f, %f, %f\n",
4693 dv15[0], dv15[1], dv15[2], dv15[3]);
4694 sv->clear_color[0] = dv15[0];
4695 sv->clear_color[1] = dv15[1];
4696 sv->clear_color[2] = dv15[2];
4697 sv->clear_color[3] = dv15[3];
4698 {
4699 DList *llist = SUMA_CreateList();
4700 SUMA_REGISTER_HEAD_COMMAND_NO_DATA(llist, SE_Redisplay,
4701 SES_SumaFromAny, sv);
4702 if (!SUMA_Engine (&llist)) {
4703 fprintf( stderr,
4704 "Error %s: SUMA_Engine call failed.\n",
4705 FuncName);
4706 }
4707 }
4708 }
4709 SUMA_free(stmp); stmp = NULL;
4710 }
4711 }
4712 /* autorecord prefix? */
4713 if (NI_get_attribute(EngineData->ngr, "autorecord")) {
4714 if (SUMAg_CF->autorecord) SUMA_free(SUMAg_CF->autorecord);
4715 SUMAg_CF->autorecord = SUMA_SetAutoRecord(
4716 NI_get_attribute(EngineData->ngr, "autorecord"));
4717 }
4718
4719 /* search for the keys */
4720 if (NI_get_attribute(EngineData->ngr,"N_Key")) {
4721 char *stmp=NULL, nc, *vbuf=NULL, *strgval=NULL;
4722 int k, rep, N_rep = 1, redisp=0;
4723 float pauz=0.0, delta_t=0.0;
4724 struct timeval tt;
4725 DList *llist = NULL;
4726 LocalHead = NOPE;
4727 NI_GET_INT(EngineData->ngr,"N_Key", itmp);
4728 for (ii=0; ii<itmp; ++ii) {
4729 sprintf(tmpstr, "Key_%d", ii);
4730 NI_GET_STR_CP(EngineData->ngr,tmpstr, stmp);
4731 sprintf(tmpstr, "Key_rep_%d", ii);
4732 NI_GET_INT(EngineData->ngr,tmpstr, N_rep);
4733 sprintf(tmpstr, "Key_pause_%d", ii);
4734 NI_GET_FLOAT(EngineData->ngr,tmpstr, pauz);
4735 sprintf(tmpstr, "Key_redis_%d", ii);
4736 NI_GET_INT(EngineData->ngr,tmpstr, redisp);
4737 sprintf(tmpstr, "Key_strval_%d", ii);
4738 strgval = NI_get_attribute(EngineData->ngr, tmpstr);
4739 SUMA_LHv("Rep=%d, Pause=%f, Redis=%d\n, Strgval=%s",
4740 N_rep, pauz, redisp, CHECK_NULL_STR(strgval));
4741 if (stmp && (nc = strlen(stmp))) {
4742 k = SUMA_KeyPress(stmp, NULL);
4743 if (strstr(stmp, "Shift")) stmp[strlen(stmp)-1] =
4744 toupper(stmp[strlen(stmp)-1]);
4745 for (rep=0; rep<N_rep; ++rep) {
4746 SUMA_LHv(".............rep %d\n", rep);
4747 SUMA_etime(&tt, 0);
4748 switch (k) {
4749 case XK_bracketleft:
4750 if (!SUMA_bracketleft_Key(sv, stmp, "drivesuma")) {
4751 SUMA_S_Err("Failed in Key function.");
4752 }
4753 break;
4754 case XK_bracketright:
4755 if (!SUMA_bracketright_Key(sv, stmp,"drivesuma")) {
4756 SUMA_S_Err("Failed in Key function.");
4757 }
4758 break;
4759 case XK_0:
4760 case XK_1:
4761 case XK_2:
4762 case XK_3:
4763 case XK_4:
4764 case XK_5:
4765 case XK_6:
4766 case XK_7:
4767 case XK_8:
4768 case XK_9:
4769 // sprintf(stmp, "%d", k); // DO NOT DELETE
4770 if (!SUMA_Numeral_Key(sv, stmp, "drivesuma")) {
4771 SUMA_S_Err("Failed in Key function.");
4772 }
4773 break;
4774 case XK_a:
4775 case XK_A:
4776 // if (strstr(stmp, "Shift")) stmp[strlen(stmp)-1] = 'A';
4777 if (!SUMA_A_Key(sv, stmp, "drivesuma")) {
4778 SUMA_S_Err("Failed in Key function.");
4779 }
4780 break;
4781 case XK_b:
4782 case XK_B:
4783 // if (strstr(stmp, "Shift")) stmp[strlen(stmp)-1] = 'B';
4784 if (!SUMA_B_Key(sv, stmp, "drivesuma")) {
4785 SUMA_S_Err("Failed in Key function.");
4786 }
4787 break;
4788 case XK_c:
4789 case XK_C:
4790 // // if (strstr(stmp, "Shift")) stmp[strlen(stmp)-1] = 'C';
4791 if (!SUMA_C_Key(sv, stmp, "drivesuma")) {
4792 SUMA_S_Err("Failed in Key function.");
4793 }
4794 break;
4795 case XK_d:
4796 case XK_D:
4797 // if (strstr(stmp, "Shift")) stmp[strlen(stmp)-1] = 'D';
4798 if (!SUMA_D_Key(sv, stmp, "drivesuma")) {
4799 SUMA_S_Err("Failed in Key function.");
4800 }
4801 break;
4802 case XK_f:
4803 case XK_F:
4804 if (!SUMA_F_Key(sv, stmp, "drivesuma")) {
4805 SUMA_S_Err("Failed in Key function.");
4806 }
4807 break;
4808 case XK_g:
4809 case XK_G:
4810 if (!SUMA_G_Key(sv, stmp, "drivesuma")) {
4811 SUMA_S_Err("Failed in Key function.");
4812 }
4813 break;
4814 case XK_h:
4815 case XK_H:
4816 if (!SUMA_H_Key(sv, stmp, "drivesuma")) {
4817 SUMA_S_Err("Failed in Key function.");
4818 }
4819 break;
4820 case XK_j:
4821 case XK_J:
4822 // if (strstr(stmp, "Shift")) stmp[strlen(stmp)-1] = 'J';
4823 if (!SUMA_J_Key(sv, stmp, "drivesuma", strgval)) {
4824 SUMA_S_Err("Failed in Key function.");
4825 }
4826 break;
4827 case XK_l:
4828 case XK_L:
4829 // if (strstr(stmp, "Shift")) stmp[strlen(stmp)-1] = 'L';
4830 if (!SUMA_L_Key(sv, stmp, "drivesuma", strgval)) {
4831 SUMA_S_Err("Failed in Key function.");
4832 }
4833 break;
4834 case XK_m:
4835 case XK_M:
4836 // if (strstr(stmp, "Shift")) stmp[strlen(stmp)-1] = 'M';
4837 if (!SUMA_M_Key(sv, stmp, "drivesuma")) {
4838 SUMA_S_Err("Failed in Key function.");
4839 }
4840 break;
4841 case XK_n:
4842 case XK_N:
4843 // if (strstr(stmp, "Shift")) stmp[strlen(stmp)-1] = 'N';
4844 if (!SUMA_N_Key(sv, stmp, "drivesuma")) {
4845 SUMA_S_Err("Failed in Key function.");
4846 }
4847 break;
4848 case XK_o:
4849 case XK_O:
4850 // if (strstr(stmp, "Shift")) stmp[strlen(stmp)-1] = 'O';
4851 if (!SUMA_O_Key(sv, stmp, "drivesuma")) {
4852 SUMA_S_Err("Failed in Key function.");
4853 }
4854 break;
4855 case XK_p:
4856 case XK_P:
4857 // if (strstr(stmp, "Shift")) stmp[strlen(stmp)-1] = 'P';
4858 if (!SUMA_P_Key(sv, stmp, "drivesuma")) {
4859 SUMA_S_Err("Failed in Key function.");
4860 }
4861 break;
4862 case XK_r:
4863 case XK_R:
4864 // if (strstr(stmp, "Shift")) stmp[strlen(stmp)-1] = 'R';
4865 if (!SUMA_R_Key(sv, stmp, "drivesuma")) {
4866 SUMA_S_Err("Failed in Key function.");
4867 }
4868 break;
4869 case XK_s:
4870 case XK_S:
4871 if (!SUMA_S_Key(sv, stmp, "drivesuma")) {
4872 SUMA_S_Err("Failed in Key function.");
4873 }
4874 break;
4875 case XK_t:
4876 case XK_T:
4877 // if (strstr(stmp, "Shift")) stmp[strlen(stmp)-1] = 'T';
4878 if (!SUMA_T_Key(sv, stmp, "drivesuma")) {
4879 SUMA_S_Err("Failed in Key function.");
4880 }
4881 break;
4882 case XK_u:
4883 case XK_U:
4884 // if (strstr(stmp, "Shift")) stmp[strlen(stmp)-1] = 'U';
4885 if (!SUMA_U_Key(sv, stmp, "drivesuma")) {
4886 SUMA_S_Err("Failed in Key function.");
4887 }
4888 break;
4889 case XK_w:
4890 case XK_W:
4891 // if (strstr(stmp, "Shift")) stmp[strlen(stmp)-1] = 'W';
4892 if (!SUMA_W_Key(sv, stmp, "drivesuma")) {
4893 SUMA_S_Err("Failed in Key function.");
4894 }
4895 break;
4896 case XK_z:
4897 case XK_Z:
4898 // if (strstr(stmp, "Shift")) stmp[strlen(stmp)-1] = 'Z';
4899 if (!SUMA_Z_Key(sv, stmp, "drivesuma")) {
4900 SUMA_S_Err("Failed in Key function.");
4901 }
4902 break;
4903 case XK_Up:
4904 if (!SUMA_Up_Key(sv, stmp, "drivesuma")) {
4905 SUMA_S_Err("Failed in Key function.");
4906 }
4907 break;
4908 case XK_Down:
4909 if (!SUMA_Down_Key(sv, stmp, "drivesuma")) {
4910 SUMA_S_Err("Failed in Key function.");
4911 }
4912 break;
4913 case XK_Left:
4914 if (!SUMA_Left_Key(sv, stmp, "drivesuma")) {
4915 SUMA_S_Err("Failed in Key function.");
4916 }
4917 break;
4918 case XK_Right:
4919 if (!SUMA_Right_Key(sv, stmp, "drivesuma")) {
4920 SUMA_S_Err("Failed in Key function.");
4921 }
4922 break;
4923 case XK_space:
4924 if (!SUMA_space_Key(sv, stmp, "drivesuma")) {
4925 SUMA_S_Err("Failed in Key function.");
4926 }
4927 break;
4928 case XK_slash:
4929 if (!SUMA_slash_Key(sv, stmp, "drivesuma")) {
4930 SUMA_S_Err("Failed in Key function.");
4931 }
4932 break;
4933 case XK_period:
4934 if (!SUMA_period_Key(sv, stmp, "drivesuma")) {
4935 SUMA_S_Err("Failed in Key function.");
4936 }
4937 break;
4938 case XK_comma:
4939 if (!SUMA_comma_Key(sv, stmp, "drivesuma")) {
4940 SUMA_S_Err("Failed in Key function.");
4941 }
4942 break;
4943 case XK_plus:
4944 if (!SUMA_plus_Key(sv, stmp, "drivesuma")) {
4945 SUMA_S_Err("Failed in Key function.");
4946 }
4947 break;
4948 case XK_minus:
4949 if (!SUMA_minus_Key(sv, stmp, "drivesuma")) {
4950 SUMA_S_Err("Failed in Key function.");
4951 }
4952 break;
4953 case XK_equal:
4954 if (!SUMA_equal_Key(sv, stmp, "drivesuma")) {
4955 SUMA_S_Err("Failed in Key function.");
4956 }
4957 break;
4958 case XK_F1:
4959 if (!SUMA_F1_Key(sv, stmp, "drivesuma")) {
4960 SUMA_S_Err("Failed in Key function.");
4961 }
4962 break;
4963 case XK_F2:
4964 if (!SUMA_F2_Key(sv, stmp, "drivesuma")) {
4965 SUMA_S_Err("Failed in Key function.");
4966 }
4967 break;
4968 case XK_F3:
4969 if (!SUMA_F3_Key(sv, stmp, "drivesuma")) {
4970 SUMA_S_Err("Failed in Key function.");
4971 }
4972 break;
4973 case XK_F4:
4974 if (!SUMA_F4_Key(sv, stmp, "drivesuma")) {
4975 SUMA_S_Err("Failed in Key function.");
4976 }
4977 break;
4978 case XK_F5:
4979 if (!SUMA_F5_Key(sv, stmp, "drivesuma")) {
4980 SUMA_S_Err("Failed in Key function.");
4981 }
4982 break;
4983 case XK_F6:
4984 if (!SUMA_F6_Key(sv, stmp, "drivesuma")) {
4985 SUMA_S_Err("Failed in Key function.");
4986 }
4987 break;
4988 case XK_F7:
4989 if (!SUMA_F7_Key(sv, stmp, "drivesuma")) {
4990 SUMA_S_Err("Failed in Key function.");
4991 }
4992 break;
4993 case XK_F8:
4994 if (!SUMA_F8_Key(sv, stmp, "drivesuma")) {
4995 SUMA_S_Err("Failed in Key function.");
4996 }
4997 break;
4998 case XK_F9:
4999 if (!SUMA_F9_Key(sv, stmp, "drivesuma")) {
5000 SUMA_S_Err("Failed in Key function.");
5001 }
5002 break;
5003 case XK_F10:
5004 /* strgval can be used to set the value directly
5005 in the future. But it is not implemented
5006 in SUMA_F10_Key yet ... */
5007 if (!SUMA_F10_Key(sv,stmp, "drivesuma", strgval)) {
5008 SUMA_S_Err("Failed in Key function.");
5009 }
5010 break;
5011 case XK_F11:
5012 if (!SUMA_F11_Key(sv, stmp,"drivesuma", strgval)) {
5013 SUMA_S_Err("Failed in Key function.");
5014 }
5015 break;
5016 case XK_F12:
5017 if (!SUMA_F12_Key(sv, stmp, "drivesuma")) {
5018 SUMA_S_Err("Failed in Key function.");
5019 }
5020 break;
5021 case XK_VoidSymbol:
5022 SUMA_S_Errv("No good key for %s\n", stmp);
5023 break;
5024 default:
5025 SUMA_S_Errv("Don't know how to deal with %s "
5026 "in drive mode\n", stmp);
5027 break;
5028 } /* end switch k */
5029 /* do we need a call for redisplay now? */
5030 if ((redisp || pauz != 0.0f )) {
5031 /* a redisplay is already pending
5032 (from the key functions), kill it or it will get
5033 executed later*/
5034 SUMA_remove_workproc2( SUMA_handleRedisplay,
5035 sv->X->GLXAREA );
5036 llist = SUMA_CreateList ();
5037 SUMA_REGISTER_TAIL_COMMAND_NO_DATA(llist,
5038 SE_RedisplayNow, SES_SumaFromAny, sv);
5039 SUMA_LH("Forcing redisplay");
5040 SUMA_Engine (&llist);
5041 }
5042
5043 /* check on delay */
5044 if (pauz < 0) {
5045 char buf[100];
5046 sprintf( buf,
5047 "Pausing DriveSuma at Key %s, rep=%d, N_rep=%d",
5048 stmp, rep, N_rep);
5049 SUMA_LH("Calling user pause...");
5050 #if 1
5051 SUMA_PauseForUser(sv->X->TOPLEVEL, buf,
5052 SWP_POINTER_OFF, NULL, 0, -1.0);
5053 #else /* kept here to illustrate bug */
5054 /* very slow when called repeatedly except when you open the
5055 'Close All Viewers' thing by hand with SHFTESC then press No.
5056 In that case, repeated calls to SUMA_ForceUser_YesNo are quite fast.
5057 The problem in the XtManage call once the dialog is created. It takes
5058 forever to return. One solution, implemented in PauseForUser, is
5059 to destroy the widget each time and recreate it anew. Not a big deal.*/
5060 SUMA_ForceUser_YesNo(sv->X->TOPLEVEL,
5061 "Close All Viewers?",
5062 SUMA_YES, SWP_DONT_CARE);
5063 #endif
5064 } else if (pauz > 0.0f) {
5065 SUMA_LHv("Sleeping for %dms\n",
5066 (int) ((pauz-delta_t)*1000));
5067 delta_t = SUMA_etime(&tt, 1);
5068 if (delta_t < pauz) {
5069 NI_sleep((int) ((pauz-delta_t)*1000));
5070 }
5071 }
5072 } /* end of rep */
5073 SUMA_free(stmp); stmp = NULL;
5074 } /* end have iith key */
5075 } /* end loop all keys */
5076 }
5077 break;
5078
5079 case SE_SetRecorderCont:
5080 /* expects a ngr */
5081 if (EngineData->ngr_Dest != NextComCode ) {
5082 fprintf (SUMA_STDERR,
5083 "Error %s: Data not destined correctly for %s (%d).\n"
5084 "Have %d \n",
5085 FuncName, NextCom, NextComCode, EngineData->ngr_Dest);
5086 break;
5087 }
5088 {
5089 char *stmp=NULL, *sname=NULL;
5090 int ifrom = -1, ito = -1, NoTsEt = -999999;
5091 if (NI_get_attribute(EngineData->ngr, "Anim_Dup")) {
5092 NI_GET_INT(EngineData->ngr,"Anim_Dup", itmp);
5093 if (!NI_GOT || itmp < 0) {
5094 itmp = 0;
5095 }
5096 SUMA_LHv("Going for %d\n", itmp);
5097 ISQ_set_anim_dup(itmp);
5098 }
5099 if (NI_get_attribute(EngineData->ngr, "Save_As")) {
5100
5101 #if 1
5102 ifrom = ito = NoTsEt;
5103 NI_GET_INT(EngineData->ngr, "Save_From", itmp);
5104 if (!NI_GOT) {
5105 itmp = -1;
5106 } else {
5107 ifrom = itmp;
5108 }
5109 NI_GET_INT(EngineData->ngr, "Save_To", itmp);
5110 if (!NI_GOT) {
5111 itmp = -1;
5112 }else {
5113 ito = itmp;
5114 }
5115
5116 NI_GET_STR_CP(EngineData->ngr, "Save_As", stmp);
5117 if (!stmp) {
5118 SUMA_S_Err("Empty Save_As");
5119 goto CLEAN_RECORDER_CONT;
5120 }
5121 fn = SUMA_ParseFname(stmp,
5122 NI_get_attribute(EngineData->ngr,
5123 "Caller_Working_Dir"));
5124 if (!(sname = SUMA_copy_string(fn->FileName_NoExt))) {
5125 sname = SUMA_copy_string("no_name");
5126 }
5127 sname = SUMA_append_replace_string(fn->AbsPath, sname, "", 2);
5128 if (ito == NoTsEt && ifrom == NoTsEt) {
5129 if (SUMA_IMG_EXT(fn->Ext)) {
5130 ifrom = -1; ito = 0;/* nothing set, save last one */
5131 } else if (SUMA_ANIM_EXT(fn->Ext)) {
5132 ifrom = 0; ito = 0;
5133 /* nothing set, save all in animation */
5134 } else {
5135 SUMA_S_Errv("No support for extension %s\n", fn->Ext);
5136 goto CLEAN_RECORDER_CONT;
5137 }
5138 }
5139 if (ito == NoTsEt || ifrom == NoTsEt) {
5140 SUMA_S_Errv("Erreur! Horreur! ito=%d, ifrom=%d"
5141 " (NotSet=%d)\n", ito, ifrom , NoTsEt);
5142 goto CLEAN_RECORDER_CONT;
5143 }
5144 #else
5145 NI_GET_INT(EngineData->ngr, "Save_One", itmp);
5146 if (NI_GOT) {
5147 if (itmp == -1) { ifrom = -1; ito = 0; }
5148 else if (itmp >= 0) { ifrom = itmp; ito = ifrom; }
5149 else {
5150 SUMA_S_Errv("Bad value for -save_one (%d)\n", itmp);
5151 break;
5152 }
5153 }
5154
5155 NI_GET_STR_CP(EngineData->ngr, "Save_As", stmp);
5156 if (!stmp) {
5157 SUMA_S_Err("Empty Save_As");
5158 goto CLEAN_RECORDER_CONT;
5159 }
5160 fn = SUMA_ParseFname(stmp,
5161 NI_get_attribute( EngineData->ngr,
5162 "Caller_Working_Dir"));
5163 if (!(sname = SUMA_copy_string(fn->FileName_NoExt))) {
5164 sname = SUMA_copy_string("no_name");
5165 }
5166 sname = SUMA_append_replace_string(fn->AbsPath, sname, "", 2);
5167
5168 /* more checking */
5169 if (ito < 0 && ifrom < 0) {
5170 if (SUMA_IMG_EXT(fn->Ext)) {
5171 ifrom = -1; ito = 0;/* nothing set, save last one */
5172 } else if (SUMA_ANIM_EXT(fn->Ext)) {
5173 ifrom = 0; ito = 0;/* nothing set, save all in animation */
5174 } else {
5175 SUMA_S_Errv("No support for extension %s\n", fn->Ext);
5176 goto CLEAN_RECORDER_CONT;
5177 }
5178 }
5179 #endif
5180 if (ifrom > ito && ito > 0) {
5181 /* note that negative indices are OK, see ISQ_save_anim */
5182 SUMA_S_Errv("Error: ifrom=%d > ito=%d\n", ifrom, ito);
5183 goto CLEAN_RECORDER_CONT;
5184 }
5185 if ( SUMA_iswordsame_ci(fn->Ext,".agif") ||
5186 SUMA_iswordsame_ci(fn->Ext,".gif")) {
5187 ISQ_snap_agif_rng(sname, ifrom, ito);
5188 } else if ( SUMA_iswordsame_ci(fn->Ext,".mpeg") ||
5189 SUMA_iswordsame_ci(fn->Ext,".mpg")) {
5190 ISQ_snap_mpeg_rng(sname, ifrom, ito);
5191 } else if ( SUMA_iswordsame_ci(fn->Ext,".jpeg") ||
5192 SUMA_iswordsame_ci(fn->Ext,".jpg")) {
5193 ISQ_snap_jpeg_rng(sname, ifrom, ito);
5194 } else if (SUMA_iswordsame_ci(fn->Ext,".png") ) {
5195 ISQ_snap_png_rng(sname, ifrom, ito);
5196 } else {
5197 SUMA_S_Errv("Not ready to deal with format %s\n", tmpstr);
5198 goto CLEAN_RECORDER_CONT;
5199 }
5200 }
5201 CLEAN_RECORDER_CONT:
5202 if (stmp) SUMA_free(stmp); stmp = NULL;
5203 if (sname) SUMA_free(sname); sname = NULL;
5204 if (fn) fn = SUMA_Free_Parsed_Name(fn);
5205 }
5206 break;
5207 /*case SE_Something:
5208 break;*/
5209
5210 case SE_BadCode:
5211 fprintf(SUMA_STDERR,"Error SUMA_Engine: Command ->%s<- Not understood. Perhaps Code is not defined in SUMA_CommandCode\n", NextCom);
5212 break;
5213
5214 } /* switch NextComCode */
5215
5216 /* release used Element */
5217 if (LocalHead) fprintf (SUMA_STDERR, "\n%s: Releasing Engine Element.\n", FuncName);
5218 if (!SUMA_ReleaseEngineListElement (list, NextElem_CANT_TOUCH_THIS)) {
5219 fprintf(SUMA_STDERR,"Error SUMA_Engine: Failed to Release element \n");
5220 }
5221
5222 } /* cycle through NextCom */
5223
5224 if (LocalHead) fprintf (SUMA_STDERR, "\n%s: Destroying List.\n", FuncName);
5225 /* If you get here, all is well, destroy the list since it is empty*/
5226 list = SUMA_DestroyList (list);
5227 *listp = NULL;
5228
5229 SUMA_RETURN (YUP);
5230 }
5231
SUMA_nimlEngine2Engine(NI_group * ngr)5232 void *SUMA_nimlEngine2Engine(NI_group *ngr)
5233 {
5234 static char FuncName[]={"SUMA_nimlEngine2Engine"};
5235 DList *list = NULL;
5236 int isv, itmp;
5237 SUMA_NI_COMMAND_CODE cc;
5238 SUMA_EngineData *ED = NULL;
5239 DListElmt *el=NULL;
5240 void *Ret = NULL;
5241 char *adoid=NULL, *svid=NULL, *name=NULL, *adolabel=NULL,
5242 ename[32], lhs[64], rhs[256], *enveqn=NULL, *attr=NULL;
5243 SUMA_ALL_DO *ado = NULL;
5244 SUMA_SurfaceViewer *sv = NULL;
5245 SUMA_X_SurfCont *SurfCont=NULL;
5246 SUMA_PARSED_NAME *fn = NULL;
5247 SUMA_Boolean LocalHead = NOPE;
5248
5249 SUMA_ENTRY;
5250
5251 if (!ngr) { SUMA_S_Err("NULL input"); SUMA_RETURN(Ret); }
5252 if (LocalHead) SUMA_ShowNel(ngr);
5253 if (strcmp(ngr->name, "EngineCommand")) {
5254 fprintf (SUMA_STDERR,
5255 "Error %s: group name (%s) is not (EngineCommand)\n",
5256 FuncName, ngr->name);
5257 SUMA_RETURN(Ret);
5258 }
5259
5260 /* Is this a valid command? */
5261 cc = SUMA_niCommandCode(NI_get_attribute(ngr,"Command"));
5262 if (cc == SE_Empty || cc == SE_BadCode) {
5263 SUMA_S_Errv("Bad command code %s",
5264 SUMA_CHECK_NULL_STR(NI_get_attribute(ngr,"Command")));
5265 SUMA_RETURN(Ret);
5266 }
5267
5268 /* do we have the classics? */
5269 itmp = 0;
5270 sprintf(ename,"ENV.%d", itmp);
5271 while ((attr=NI_get_attribute(ngr, ename))) {
5272 SUMA_LHv("Have %s:>%s<\n", ename, attr);
5273 lhs[0] = '\0'; rhs[0]='\0';
5274 if (SUMA_ParseLHS_RHS (attr, lhs, rhs)) {
5275 enveqn = (char *) malloc(strlen(lhs)+strlen(rhs)+4) ;
5276 sprintf(enveqn,"%s=%s", lhs, rhs);
5277 putenv(enveqn);
5278 SUMA_LHv("Got %s\n", enveqn);
5279 } else {
5280 SUMA_S_Errv("Failed to parse %s: %s\n",
5281 ename, attr);
5282 }
5283 sprintf(ename,"ENV.%d", ++itmp);
5284 }
5285
5286 sv = NULL;
5287 svid = NI_get_attribute(ngr,"SV_id");
5288 if (svid) {
5289 isv = SUMA_TO_LOWER_C(svid[0])-'a';
5290 if (isv < 0 || isv > SUMAg_N_SVv) {
5291 /* try in case it was an int */
5292 isv = atoi(svid);
5293 }
5294 if (isv < 0 || isv > SUMAg_N_SVv) {
5295 SUMA_S_Errv("Bad SV_id of %s\n", svid);
5296 SUMA_RETURN(Ret);
5297 }
5298 sv = &(SUMAg_SVv[isv]);
5299 if (!sv->X->TOPLEVEL) {
5300 SUMA_S_Errv("Viewer %s must first be created "
5301 "with a separate -com command.\n", svid);
5302 SUMA_RETURN(Ret);
5303 }
5304 }
5305 if (!sv) {
5306 sv = &(SUMAg_SVv[0]);
5307 }
5308 SUMA_LH("Viewer id %s, isv=%d sv=%p",svid?svid:"NULL", isv, sv);
5309
5310 ado = NULL;
5311 if (!(adoid = NI_get_attribute(ngr,"SO_idcode")) &&
5312 !(adoid = NI_get_attribute(ngr,"DO_idcode")))
5313 adoid = NI_get_attribute(ngr,"ADO_idcode");
5314
5315 if (adoid) {
5316 ado = SUMA_whichADO(adoid, SUMAg_DOv, SUMAg_N_DOv);
5317 if (!ado) {
5318 SUMA_S_Errv("DO with id %s not found.\n", adoid);
5319 SUMA_RETURN(Ret);
5320 }
5321 }
5322 if (!(adolabel = NI_get_attribute(ngr,"SO_label")) &&
5323 !(adolabel = NI_get_attribute(ngr,"DO_label")))
5324 adolabel = NI_get_attribute(ngr,"ADO_label");;
5325 if (adolabel) {
5326 if (ado && strcmp(adolabel, ADO_LABEL(ado))) {
5327 SUMA_S_Errv("Conflict between id %s (%s) and label (%s)",
5328 ADO_ID(ado), ADO_LABEL(ado), adolabel);
5329 SUMA_RETURN(Ret);
5330 }
5331 if (!ado) { /* find ado based on label! */
5332 if ((adoid = SUMA_find_ADOidcode_from_label(adolabel,
5333 SUMAg_DOv, SUMAg_N_DOv))) {
5334 ado = SUMA_whichADO(adoid, SUMAg_DOv, SUMAg_N_DOv);
5335 if (!ado) {
5336 SUMA_S_Errv("ADO with id %s not found.\n", adoid);
5337 SUMA_RETURN(Ret);
5338 }
5339 }else {
5340 SUMA_S_Errv("ADO id from label %s not found.\n", adolabel);
5341 SUMA_RETURN(Ret);
5342 }
5343 }
5344 }
5345 if (!ado) ado = SUMA_SV_Focus_ADO(sv);
5346 if (!ado) {
5347 ado = SUMA_findanyFocusable_ADO(NULL);/* last resort */
5348 }
5349 if (!ado) {
5350 SUMA_S_Err("Have no ADOs to work with at all.\n");
5351 SUMA_RETURN(Ret);
5352 } else {
5353 if (LocalHead) {
5354 SUMA_LHv("Have ADO %s to work with\n", ADO_LABEL(ado));
5355 }
5356 }
5357 /* Create da list */
5358 if (!list) list = SUMA_CreateList ();
5359
5360
5361
5362 SurfCont = SUMA_ADO_Cont(ado);
5363 /* OK, now, switch on that command and create the Engine structure */
5364 switch (cc) {
5365 case SE_niSetObjectCont:
5366 case SE_niSetSurfCont:
5367 if (!SurfCont) {
5368 SUMA_S_Err( "Unexpected NULL SurfCont\n"
5369 "Please report error to author.");
5370 SUMA_RETURN(Ret);
5371 }
5372 if (!SUMA_isADO_Cont_Realized(ado)){
5373 /* better have a controller
5374 before going crazy */
5375 if (0) { /* this option or the next behave in the same way */
5376 if (!SUMA_viewSurfaceCont(NULL, ado, sv)) {
5377 SUMA_S_Err("Failed open surfcont");
5378 break;
5379 }
5380 } else {
5381 ED = SUMA_InitializeEngineListData (SE_OpenSurfCont);
5382 if (!SUMA_RegisterEngineListCommand (
5383 list, ED,
5384 SEF_vp, (void *)ado,
5385 SES_SumaFromAny, (void *)sv,
5386 NOPE,
5387 SEI_Head, NULL)) {
5388 fprintf (SUMA_STDERR,
5389 "Error %s: Failed to register command.\n", FuncName);
5390 }
5391 }
5392
5393 /* make sure that business is closed if user does not control it */
5394 /* IF you close the window quickly, the colormap does not render
5395 and you can get into trouble then, this also happens if
5396 Drive SUMA orders an immediate surface controller closing after
5397 a dset load ... */
5398
5399 if (!NI_get_attribute(ngr, "View_Surf_Cont"))
5400 NI_set_attribute(ngr, "View_Surf_Cont", "n");
5401 }
5402
5403 if ((name = NI_get_attribute(ngr,"Dset_FileName"))) {
5404 /* Have a dset to load */
5405 ED = SUMA_InitializeEngineListData (SE_OpenDsetFile);
5406 if (!(el = SUMA_RegisterEngineListCommand ( list, ED,
5407 SEF_vp, (void *)ado,
5408 SES_SumaFromAny,
5409 (void *)sv, NOPE,
5410 SEI_Tail, NULL))) {
5411 fprintf (SUMA_STDERR,
5412 "Error %s: Failed to register command.\n", FuncName);
5413 }
5414 if (!SUMA_RegisterEngineListCommand ( list, ED,
5415 SEF_cp, (void *)name,
5416 SES_SumaFromAny,
5417 (void *)sv, NOPE,
5418 SEI_In, el)) {
5419 fprintf (SUMA_STDERR,
5420 "Error %s: Failed to register command.\n", FuncName);
5421 }
5422 }
5423
5424 if ((name = NI_get_attribute(ngr,"Mask_FileName"))) {
5425 /* Have a Mask to load */
5426 ED = SUMA_InitializeEngineListData (SE_OpenMaskFile);
5427 if (!(el = SUMA_RegisterEngineListCommand ( list, ED,
5428 SEF_vp, (void *)ado,
5429 SES_SumaFromAny,
5430 (void *)sv, NOPE,
5431 SEI_Tail, NULL))) {
5432 fprintf (SUMA_STDERR,
5433 "Error %s: Failed to register command.\n", FuncName);
5434 }
5435 if (!SUMA_RegisterEngineListCommand ( list, ED,
5436 SEF_cp, (void *)name,
5437 SES_SumaFromAny,
5438 (void *)sv, NOPE,
5439 SEI_In, el)) {
5440 fprintf (SUMA_STDERR,
5441 "Error %s: Failed to register command.\n", FuncName);
5442 }
5443 }
5444
5445 if ((name = NI_get_attribute(ngr,"Col_FileName"))) {
5446 /* Have a color file to load */
5447 ED = SUMA_InitializeEngineListData (SE_OpenColFile);
5448 if (!(el = SUMA_RegisterEngineListCommand ( list, ED,
5449 SEF_vp, (void *)ado,
5450 SES_SumaFromAny,
5451 (void *)sv, NOPE,
5452 SEI_Tail, NULL))) {
5453 fprintf (SUMA_STDERR,
5454 "Error %s: Failed to register command.\n", FuncName);
5455 }
5456 if (!SUMA_RegisterEngineListCommand ( list, ED,
5457 SEF_cp, (void *)name,
5458 SES_SumaFromAny,
5459 (void *)sv, NOPE,
5460 SEI_In, el)) {
5461 fprintf (SUMA_STDERR,
5462 "Error %s: Failed to register command.\n", FuncName);
5463 }
5464 }
5465 /* all the rest can be handled in one engine call */
5466 ED = SUMA_InitializeEngineListData (SE_SetSurfCont);
5467 if (!(el = SUMA_RegisterEngineListCommand ( list, ED,
5468 SEF_ngr, (void *)ngr,
5469 SES_SumaFromAny, (void *)sv,
5470 NOPE,
5471 SEI_Tail, NULL))) {
5472 fprintf (SUMA_STDERR,
5473 "Error %s: Failed to register command.\n", FuncName);
5474 }
5475 if (!SUMA_RegisterEngineListCommand ( list, ED,
5476 SEF_vp, (void *)ado,
5477 SES_SumaFromAny, (void *)sv,
5478 NOPE,
5479 SEI_In, el)) {
5480 fprintf (SUMA_STDERR,
5481 "Error %s: Failed to register command.\n", FuncName);
5482 }
5483 break;
5484 case SE_niSetViewerCont:
5485 if ((name = NI_get_attribute(ngr,"N_foreg_smooth"))) {
5486 SUMA_SetNumForeSmoothing(name, (void *)sv);
5487 }
5488 if ((name = NI_get_attribute(ngr,"N_final_smooth"))) {
5489 SUMA_SetNumFinalSmoothing(name, (void *)sv);
5490 }
5491 if ((name = NI_get_attribute(ngr,"VVS_FileName"))) {
5492 /* Have a vvs to load, do it straight up,
5493 no need to call some SE_SetViewerCont, a la SE_SetSurfCont yet */
5494 if ((fn = SUMA_ParseFname(name,
5495 NI_get_attribute(ngr,
5496 "Caller_Working_Dir")))) {
5497 SUMA_LoadVisualState(fn->FullName, (void *)sv);
5498 }
5499 if (fn) fn = SUMA_Free_Parsed_Name(fn);
5500 }
5501 if ((name = NI_get_attribute(ngr,"DO_FileName"))) {
5502 /* Have a DO to load, straight up too*/
5503 if ((fn = SUMA_ParseFname(name,
5504 NI_get_attribute(ngr,
5505 "Caller_Working_Dir")))) {
5506 SUMA_LoadSegDO(fn->FullName, (void *)sv);
5507 }
5508 if (fn) fn = SUMA_Free_Parsed_Name(fn);
5509 }
5510 if ((name = NI_get_attribute(ngr,"DoViewerSetup"))) {
5511 /* have something to do with viewer setup */
5512 if (!SUMA_ApplyVisualState((NI_element *)ngr, sv)) {
5513 SUMA_S_Err("Failed to apply state");
5514 SUMA_RETURN(Ret);
5515 }
5516 }
5517 /* all the rest can be handled in one engine call */
5518 ED = SUMA_InitializeEngineListData (SE_SetViewerCont);
5519 if (!(el = SUMA_RegisterEngineListCommand ( list, ED,
5520 SEF_ngr, (void *)ngr,
5521 SES_SumaFromAny, (void *)sv,
5522 NOPE,
5523 SEI_Tail, NULL))) {
5524 fprintf (SUMA_STDERR,
5525 "Error %s: Failed to register command.\n", FuncName);
5526 }
5527 if (!SUMA_RegisterEngineListCommand ( list, ED,
5528 SEF_vp, (void *)ado,
5529 SES_SumaFromAny, (void *)sv,
5530 NOPE,
5531 SEI_In, el)) {
5532 fprintf (SUMA_STDERR,
5533 "Error %s: Failed to register command.\n", FuncName);
5534 }
5535 break;
5536 case SE_niSetRecorderCont:
5537 ED = SUMA_InitializeEngineListData (SE_SetRecorderCont);
5538 if (!(el = SUMA_RegisterEngineListCommand ( list, ED,
5539 SEF_ngr, (void *)ngr,
5540 SES_SumaFromAny, (void *)sv,
5541 NOPE,
5542 SEI_Tail, NULL))) {
5543 fprintf (SUMA_STDERR,
5544 "Error %s: Failed to register command.\n", FuncName);
5545 }
5546
5547 break;
5548 case SE_niKillSuma:
5549 XtCloseDisplay( SUMAg_CF->X->DPY_controller1 ) ;
5550 selenium_close();/* close selenium opened browser windows if open */
5551 exit(0);
5552 break;
5553 case SE_GetLabel:
5554 {
5555 /* show the current surface label */
5556 SUMA_SurfaceObject *SO=NULL;
5557 char *lbls;
5558 // lbls = ADO_LABEL(ado);
5559 SO = (SUMA_SurfaceObject *)ado;
5560 lbls = SUMA_GetLabelsAtSelection(ado,
5561 SO->SelectedNode, -1);
5562 sumaout = SUMA_drive_get_outstream();
5563 fprintf(sumaout,"%s\n",lbls);
5564 fflush(sumaout);
5565 }
5566 break;
5567
5568 default:
5569 SUMA_S_Errv("Cannot deal with command %s yet.\n",
5570 NI_get_attribute(ngr,"command"));
5571 SUMA_RETURN(Ret);
5572 break;
5573
5574 }
5575
5576 if (!SUMA_Engine(&list)) {
5577 SUMA_SLP_Err("Failed to execute command.");
5578 SUMA_RETURN(Ret);
5579 }
5580
5581
5582 SUMA_RETURN(Ret);
5583 }
5584
5585 /*!
5586 ans = SUMA_RegisteredSOs (sv, dov, SO_IDs);
5587 gets the IDs (indices into dov) and number of the Surface Objects shown in sv
5588 \param sv (SUMA_SurfaceViewer *) the surface viewer structure
5589 \param dov (SUMA_DO *) the Displayable Objects vector (accessible to sv)
5590 \param SO_IDs (int *) pre-allocated integer vector that will contain the IDs of the SO shown in sv
5591 send NULL if you do not care for it and all you'll get is ans
5592 \ret ans (int) the number of SOs shown in SV
5593 Still confused ? read the code for the function, it is shorter than the documentation.
5594 */
SUMA_RegisteredSOs(SUMA_SurfaceViewer * sv,SUMA_DO * dov,int * SO_IDs)5595 int SUMA_RegisteredSOs (SUMA_SurfaceViewer *sv, SUMA_DO *dov, int *SO_IDs)
5596 {
5597 static char FuncName[]={"SUMA_RegisteredSOs"};
5598 int i, k = 0;
5599
5600 SUMA_ENTRY;
5601
5602 for (i=0; i< sv->N_DO; ++i) {
5603 if (SUMA_isSO_G(dov[sv->RegistDO[i].dov_ind], sv->CurGroupName)) {
5604 if (SO_IDs != NULL) SO_IDs[k] = sv->RegistDO[i].dov_ind;
5605 ++k;
5606 }
5607 }
5608
5609 SUMA_RETURN (k);
5610 }
5611 /*!
5612 ans = SUMA_VisibleSOs (sv, dov, SO_IDs);
5613 gets the IDs (indices into dov) and number of the Surface Objects
5614 registered with sv and with the SO->Side matching sv->ShowRight/
5615 sv->ShowLeft and with SO->Show set to YUP
5616 \param sv (SUMA_SurfaceViewer *) the surface viewer structure
5617 \param dov (SUMA_DO *) the Displayable Objects vector (accessible to sv)
5618 \param SO_IDs (int *) pre-allocated integer vector that will contain the
5619 IDs of the SO shown in sv
5620 send NULL if you do not care for it and all you'll get is ans
5621 \param forpicking (int) 1 --> surface rendered as points will be
5622 considered invisible
5623
5624 \ret ans (int) the number of SOs shown in SV
5625 Still confused ? read the code for the function, it is shorter
5626 than the documentation.
5627
5628 \sa SUMA_isVisibleSO, SUMA_Selectable_ADOs
5629 */
5630
SUMA_VisibleSOs(SUMA_SurfaceViewer * sv,SUMA_DO * dov,int * SO_IDs,int forpicking)5631 int SUMA_VisibleSOs (SUMA_SurfaceViewer *sv, SUMA_DO *dov, int *SO_IDs,
5632 int forpicking)
5633 {
5634 static char FuncName[]={"SUMA_VisibleSOs"};
5635 SUMA_SurfaceObject *SO=NULL;
5636 int i, k = 0;
5637 SUMA_Boolean LocalHead = NOPE;
5638
5639 SUMA_ENTRY;
5640
5641 for (i=0; i< sv->N_DO; ++i) {
5642 if (SUMA_isSO_G(dov[sv->RegistDO[i].dov_ind], sv->CurGroupName)) {
5643 SO = (SUMA_SurfaceObject *)dov[sv->RegistDO[i].dov_ind].OP;
5644 if (SO_SHOWING(SO, sv) && (!forpicking || SO->PolyMode != SRM_Points)) {
5645 if ( SO->Side == SUMA_NO_SIDE ||
5646 SO->Side == SUMA_SIDE_ERROR ||
5647 SO->Side == SUMA_LR) {
5648 if (SO_IDs) {
5649 SO_IDs[k] = sv->RegistDO[i].dov_ind;
5650 }
5651 ++k;
5652 } else if ( (SO->Side == SUMA_RIGHT && sv->ShowRight) ||
5653 (SO->Side == SUMA_LEFT && sv->ShowLeft) ) {
5654 if (SO_IDs) {
5655 SO_IDs[k] = sv->RegistDO[i].dov_ind;
5656 }
5657 ++k;
5658 }
5659 }
5660 } else {
5661 switch (dov[sv->RegistDO[i].dov_ind].ObjectType) {
5662 case CDOM_type:
5663 SUMA_LH("So how do we handle the visibility of surfaces "
5664 "within a CIFTI object? Is this the place for it?");
5665 break;
5666 }
5667 }
5668 }
5669
5670 SUMA_RETURN (k);
5671 }
5672
SUMA_VisibleMDOs(SUMA_SurfaceViewer * sv,SUMA_DO * dov,int * MDO_IDs)5673 int SUMA_VisibleMDOs (SUMA_SurfaceViewer *sv, SUMA_DO *dov, int *MDO_IDs)
5674 {
5675 static char FuncName[]={"SUMA_VisibleMDOs"};
5676 SUMA_MaskDO *MDO=NULL;
5677 int i, k = 0;
5678 SUMA_Boolean LocalHead = NOPE;
5679
5680 SUMA_ENTRY;
5681
5682 for (i=0; i< sv->N_DO; ++i) {
5683 if (dov[sv->RegistDO[i].dov_ind].ObjectType != MASK_type) continue;
5684 MDO = (SUMA_MaskDO *)dov[sv->RegistDO[i].dov_ind].OP;
5685 if (!MDO_IS_SHADOW(MDO) && MDO_SHOWING(MDO, sv)) {
5686 if ( MDO->SO->Side == SUMA_NO_SIDE ||
5687 MDO->SO->Side == SUMA_SIDE_ERROR ||
5688 MDO->SO->Side == SUMA_LR) {
5689 if (MDO_IDs) {
5690 MDO_IDs[k] = sv->RegistDO[i].dov_ind;
5691 }
5692 ++k;
5693 } else if ( (MDO->SO->Side == SUMA_RIGHT && sv->ShowRight) ||
5694 (MDO->SO->Side == SUMA_LEFT && sv->ShowLeft) ) {
5695 if (MDO_IDs) {
5696 MDO_IDs[k] = sv->RegistDO[i].dov_ind;
5697 }
5698 ++k;
5699 }
5700 }
5701 }
5702
5703 SUMA_RETURN (k);
5704 }
5705
5706 /*
5707 Is this the kind of DO that can be selected in SUMA
5708 In other terms, can it be loaded and viewed with nothing
5709 else?
5710 */
SUMA_is_iDO_Selectable(int dov_id)5711 int SUMA_is_iDO_Selectable(int dov_id)
5712 {
5713 static char FuncName[]={"SUMA_is_iDO_Selectable"};
5714
5715 switch (iDO_type(dov_id)){
5716 case SO_type:
5717 case TRACT_type:
5718 case GRAPH_LINK_type:
5719 case MASK_type:
5720 case VO_type:
5721 case CDOM_type:
5722 return(1);
5723 default:
5724 return(0);
5725 }
5726 }
5727
SUMA_Selectable_ADOs(SUMA_SurfaceViewer * sv,SUMA_DO * dov,int * SO_IDs)5728 int SUMA_Selectable_ADOs (SUMA_SurfaceViewer *sv, SUMA_DO *dov, int *SO_IDs)
5729 {
5730 static char FuncName[]={"SUMA_Selectable_ADOs"};
5731 SUMA_SurfaceObject *SO=NULL;
5732 int i, k = 0;
5733 SUMA_NIDO *SDO=NULL;
5734 SUMA_Boolean LocalHead = NOPE;
5735
5736 SUMA_ENTRY;
5737
5738 for (i=0; i< sv->N_DO; ++i) {
5739 SUMA_LHv("Checking on %s\n", iDO_label(sv->RegistDO[i].dov_ind));
5740 if (SUMA_isSO_G(dov[sv->RegistDO[i].dov_ind], sv->CurGroupName)) {
5741 SO = (SUMA_SurfaceObject *)dov[sv->RegistDO[i].dov_ind].OP;
5742 if (SO_SHOWING(SO, sv)) {
5743 if ( SO->Side == SUMA_NO_SIDE ||
5744 SO->Side == SUMA_SIDE_ERROR ||
5745 SO->Side == SUMA_LR) {
5746 if (SO_IDs) {
5747 SO_IDs[k] = sv->RegistDO[i].dov_ind;
5748 }
5749 ++k;
5750 } else if ( (SO->Side == SUMA_RIGHT && sv->ShowRight) ||
5751 (SO->Side == SUMA_LEFT && sv->ShowLeft) ) {
5752 if (SO_IDs) {
5753 SO_IDs[k] = sv->RegistDO[i].dov_ind;
5754 }
5755 ++k;
5756 }
5757 }
5758 } else {
5759 switch (dov[sv->RegistDO[i].dov_ind].ObjectType) {
5760 case SO_type:
5761 /* ignore, escaped from above isSO_G */
5762 break;
5763 case GRAPH_LINK_type:
5764 /* avoid the shadow ... */
5765 if (!SUMA_IS_GOOD_STATE(
5766 iDO_state(sv->RegistDO[i].dov_ind))) break;
5767 /* OK, keep */
5768 if (SO_IDs) {
5769 SO_IDs[k] = sv->RegistDO[i].dov_ind;
5770 }
5771 ++k;
5772 break;
5773 case TRACT_type:
5774 case MASK_type:
5775 case CDOM_type:
5776 case VO_type:
5777 if (SO_IDs) {
5778 SO_IDs[k] = sv->RegistDO[i].dov_ind;
5779 }
5780 ++k;
5781 break;
5782 default:
5783 SUMA_LHv("Ignoring %s\n", iDO_label(sv->RegistDO[i].dov_ind));
5784 break;
5785 }
5786 }
5787 }
5788
5789 SUMA_RETURN (k);
5790 }
5791
SUMA_ADOs_WithSurfCont(SUMA_DO * dov,int N_dov,int * dov_IDs)5792 int SUMA_ADOs_WithSurfCont (SUMA_DO *dov, int N_dov, int *dov_IDs)
5793 {
5794 static char FuncName[]={"SUMA_ADOs_WithSurfCont"};
5795 SUMA_SurfaceObject *SO=NULL;
5796 int i, k = 0;
5797 SUMA_NIDO *SDO=NULL;
5798 SUMA_Boolean LocalHead = NOPE;
5799
5800 SUMA_ENTRY;
5801
5802 for (i=0; i< N_dov; ++i) {
5803 if (SUMA_ADO_Cont((SUMA_ALL_DO*)SUMAg_DOv[i].OP)) {
5804 dov_IDs[k] = i;
5805 ++k;
5806 }
5807 }
5808
5809 SUMA_RETURN (k);
5810 }
5811
5812
5813 /*!
5814 \brief YUP if surface is visible in a viewer
5815 \sa SUMA_VisibleSOs
5816 */
SUMA_isVisibleDO(SUMA_SurfaceViewer * sv,SUMA_DO * dov,SUMA_ALL_DO * ado)5817 SUMA_Boolean SUMA_isVisibleDO (SUMA_SurfaceViewer *sv,
5818 SUMA_DO *dov, SUMA_ALL_DO *ado)
5819 {
5820 static char FuncName[]={"SUMA_isVisibleDO"};
5821 SUMA_SurfaceObject *SO=NULL;
5822 SUMA_SurfaceObject *curSO=NULL;
5823 int i, k = 0;
5824 SUMA_Boolean LocalHead = NOPE;
5825
5826 SUMA_ENTRY;
5827 switch(ado->do_type) {
5828 case SO_type:
5829 curSO = (SUMA_SurfaceObject *)ado;
5830 for (i=0; i< sv->N_DO; ++i) {
5831 if (SUMA_isSO_G(dov[sv->RegistDO[i].dov_ind], sv->CurGroupName)) {
5832 SO = (SUMA_SurfaceObject *)dov[sv->RegistDO[i].dov_ind].OP;
5833 if (curSO == SO) {
5834 if (SO_SHOWING(SO, sv)) {
5835 if ( SO->Side == SUMA_NO_SIDE ||
5836 SO->Side == SUMA_SIDE_ERROR ) {
5837 SUMA_RETURN(YUP);
5838 ++k;
5839 } else if ( (SO->Side == SUMA_RIGHT && sv->ShowRight) ||
5840 (SO->Side == SUMA_LEFT && sv->ShowLeft) ) {
5841 SUMA_RETURN(YUP);
5842 ++k;
5843 }
5844 }
5845 }
5846 }
5847 }
5848 break;
5849 case GDSET_type:
5850 SUMA_S_Err("Can't judge this without variant");
5851 SUMA_RETURN(NOPE);
5852 break;
5853 case CDOM_type:
5854 case VO_type:
5855 case MASK_type:
5856 case TRACT_type:
5857 case GRAPH_LINK_type:
5858 for (i=0; i< sv->N_DO; ++i) {
5859 if (dov[sv->RegistDO[i].dov_ind].OP == ado) SUMA_RETURN(YUP);
5860 }
5861 SUMA_RETURN(YUP);
5862 break;
5863 default:
5864 SUMA_S_Errv("Nothing to do with %s\n",
5865 SUMA_ObjectTypeCode2ObjectTypeName(ado->do_type));
5866 SUMA_RETURN(NOPE);
5867 }
5868
5869 SUMA_RETURN(NOPE);
5870
5871 }
SUMA_isRegisteredSO(SUMA_SurfaceViewer * sv,SUMA_DO * dov,SUMA_SurfaceObject * curSO)5872 SUMA_Boolean SUMA_isRegisteredSO (SUMA_SurfaceViewer *sv,
5873 SUMA_DO *dov, SUMA_SurfaceObject *curSO)
5874 {
5875 static char FuncName[]={"SUMA_isRegisteredSO"};
5876 SUMA_SurfaceObject *SO=NULL;
5877 int i, k = 0;
5878
5879 SUMA_ENTRY;
5880
5881 for (i=0; i< sv->N_DO; ++i) {
5882 if (1) {
5883 SO = (SUMA_SurfaceObject *)dov[sv->RegistDO[i].dov_ind].OP;
5884 if (curSO == SO) {
5885 SUMA_RETURN(YUP);
5886 }
5887 }
5888 }
5889
5890 SUMA_RETURN(NOPE);
5891 }
5892
SUMA_ADO_isRegistered(SUMA_SurfaceViewer * sv,SUMA_ALL_DO * ado)5893 SUMA_Boolean SUMA_ADO_isRegistered(SUMA_SurfaceViewer *sv, SUMA_ALL_DO *ado)
5894 {
5895 static char FuncName[]={"SUMA_ADO_isRegistered"};
5896 return(SUMA_isRegisteredDO(sv, SUMAg_DOv, ado));
5897 }
5898
SUMA_isRegisteredDO(SUMA_SurfaceViewer * sv,SUMA_DO * dov,SUMA_ALL_DO * curDO)5899 SUMA_Boolean SUMA_isRegisteredDO (SUMA_SurfaceViewer *sv,
5900 SUMA_DO *dov, SUMA_ALL_DO *curDO)
5901 {
5902 static char FuncName[]={"SUMA_isRegisteredDO"};
5903 SUMA_ALL_DO *DO=NULL;
5904 int i, k = 0;
5905
5906 SUMA_ENTRY;
5907
5908 for (i=0; i< sv->N_DO; ++i) {
5909 if (1) {
5910 DO = (SUMA_ALL_DO *)dov[sv->RegistDO[i].dov_ind].OP;
5911 if (curDO == DO) {
5912 SUMA_RETURN(YUP);
5913 }
5914 }
5915 }
5916
5917 SUMA_RETURN(NOPE);
5918 }
5919
5920
5921 /*!
5922 Return 1st decent, preferably anat correct state(i.e. not shadown state)
5923 */
SUMA_FirstGoodState(SUMA_SurfaceViewer * sv)5924 int SUMA_FirstGoodState(SUMA_SurfaceViewer *sv)
5925 {
5926 static char FuncName[] = {"SUMA_FirstGoodState"};
5927 int inxt, iok;
5928
5929 SUMA_ENTRY;
5930
5931 inxt = 0; iok = -1;
5932 while (inxt < sv->N_VSv) {
5933 if (SUMA_IS_GOOD_STATE(sv->VSv[inxt].Name)) {
5934 if (sv->VSv[inxt].AnatCorrect) {
5935 SUMA_RETURN(inxt);
5936 } else {
5937 if (iok < 0) iok = inxt;
5938 }
5939 }
5940 ++inxt;
5941 }
5942
5943 SUMA_RETURN(iok);
5944 }
SUMA_FirstGoodAnatCorrState(SUMA_SurfaceViewer * sv)5945 int SUMA_FirstGoodAnatCorrState(SUMA_SurfaceViewer *sv)
5946 {
5947 static char FuncName[] = {"SUMA_FirstGoodAnatCorrState"};
5948 int inxt, iok;
5949
5950 SUMA_ENTRY;
5951
5952 inxt = 0; iok = -1;
5953 while (inxt < sv->N_VSv) {
5954 if (SUMA_IS_GOOD_STATE(sv->VSv[inxt].Name)) {
5955 if (sv->VSv[inxt].AnatCorrect) {
5956 SUMA_RETURN(inxt);
5957 }
5958 }
5959 ++inxt;
5960 }
5961
5962 SUMA_RETURN(iok);
5963 }
5964
5965
5966 /*!
5967 nxtState = SUMA_NextState(sv);
5968
5969 get the next Viewing State available in sv
5970 \param sv (SUMA_SurfaceViewer *) pointer to surface viewer structure
5971 \ret nxtState (int) the index into sv->VSv of the next state
5972 -1 if there is trouble
5973 icur is returned if there is no next state of the group sv->CurGroupName
5974 \sa SUMA_PrevState
5975 */
SUMA_NextState(SUMA_SurfaceViewer * sv)5976 int SUMA_NextState(SUMA_SurfaceViewer *sv)
5977 {
5978 static char FuncName[] = {"SUMA_NextState"};
5979 int inxt, icur;
5980 SUMA_Boolean LocalHead = NOPE;
5981
5982 SUMA_ENTRY;
5983
5984 icur = SUMA_WhichState (sv->State, sv, sv->CurGroupName);
5985 if (icur < 0) {
5986 SUMA_S_Err("SUMA_WhichState failed.");
5987 SUMA_RETURN (-1);
5988 } else {
5989 inxt = (icur + 1) % sv->N_VSv;
5990 do {
5991 /* Now see if the upcoming one is of the same group */
5992 if (inxt == icur) {
5993 /* back where we started */
5994 SUMA_RETURN(inxt);
5995 } else if (strncmp(sv->VSv[inxt].Name,"TheShadow",9)) {
5996 if (!strcmp(sv->VSv[inxt].Group, sv->CurGroupName) ||
5997 (!strcmp(sv->VSv[inxt].Group, "ANY"))) {
5998 /* group match, good, go back */
5999 SUMA_RETURN(inxt);
6000 }
6001 } else {
6002 /* Skip the shadow state */
6003 }
6004 inxt = (inxt + 1) % sv->N_VSv;
6005 } while (1);
6006 }
6007
6008 /* should not get here */
6009 SUMA_SL_Err("Flow error");
6010 SUMA_RETURN (-1);
6011 }
6012
6013 /*!
6014 precState = SUMA_PreviState (sv);
6015 get the previous Viewing State available in sv
6016 \sa SUMA_NextState
6017 */
SUMA_PrevState(SUMA_SurfaceViewer * sv)6018 int SUMA_PrevState(SUMA_SurfaceViewer *sv)
6019 {
6020 static char FuncName[] = {"SUMA_PrevState"};
6021 int inxt, icur;
6022 SUMA_Boolean LocalHead = NOPE;
6023
6024 SUMA_ENTRY;
6025
6026 icur = SUMA_WhichState (sv->State, sv, sv->CurGroupName);
6027 if (icur < 0) {
6028 fprintf(SUMA_STDERR,"Error %s: SUMA_WhichState failed.\n", FuncName);
6029 SUMA_RETURN (-1);
6030 } else {
6031 inxt = icur -1; if (inxt < 0) inxt = sv->N_VSv + inxt;
6032 do {
6033 /* Now see if the upcoming one is of the same group */
6034 if (inxt == icur) {
6035 /* back where we started */
6036 SUMA_RETURN(inxt);
6037 } else if (strncmp(sv->VSv[inxt].Name,"TheShadow",9)) {
6038 if (!strcmp(sv->VSv[inxt].Group, sv->CurGroupName) ||
6039 (!strcmp(sv->VSv[inxt].Group, "ANY"))) {
6040 /* group match, good, go back */
6041 SUMA_RETURN(inxt);
6042 }
6043 } else {
6044 /* Skip the shadow state */
6045 }
6046 inxt = inxt -1; if (inxt < 0) inxt = sv->N_VSv + inxt;
6047 } while (1);
6048 }
6049
6050 SUMA_RETURN (-1);
6051 }
6052
6053
6054
6055 /*!
6056 SOnxtID = SUMA_NextSO (dov, n_dov, CurrentIDcode, SOnxt);
6057 Get the next Surface Object in DOv
6058 \param dov (SUMA_DO *) vector containing all displayable objects
6059 \param n_dov (int) number of elements in dov
6060 \param CurrentIDcode (char *) idcode of current surface
6061 \param SOnxt (SUMA_SurfaceObject *) pointer to next surface object
6062 \ret SOnxtID (int) index into dov of SOnxt (-1) if there's an error
6063 */
6064
SUMA_NextSO(SUMA_DO * dov,int n_dov,char * idcode,SUMA_SurfaceObject * SOnxt)6065 int SUMA_NextSO (SUMA_DO *dov, int n_dov, char *idcode, SUMA_SurfaceObject *SOnxt)
6066 {
6067 static char FuncName[] = {"SUMA_NextSO"};
6068 int icur, icheck, ncheck;
6069
6070 SUMA_ENTRY;
6071
6072 if (SOnxt != NULL) {
6073 fprintf(SUMA_STDERR,"Error %s: SOnxt should be null when you call this function.\n", FuncName);
6074 SUMA_RETURN (-1);
6075 }
6076 if (n_dov < 1) {
6077 fprintf(SUMA_STDERR,"Error %s: dov contains no elements.\n", FuncName);
6078 SUMA_RETURN (-1);
6079 }
6080 icur = SUMA_findSO_inDOv (idcode, dov, n_dov);
6081 if (icur < 0) {
6082 fprintf (SUMA_STDERR,"Error %s: idcode not found in dov.\n", FuncName);
6083 SUMA_RETURN (-1);
6084 }
6085
6086 ncheck = 0;
6087 icheck = icur;
6088 while (ncheck < n_dov) {
6089 icheck = (icheck + 1) % n_dov;
6090 /*fprintf(SUMA_STDERR,"%s: Checking %d\n", FuncName, icheck);*/
6091 if (SUMA_isSO(dov[icheck])) {
6092 /*fprintf(SUMA_STDERR,"%s: Settling on %d\n", FuncName, icheck);*/
6093 SOnxt = (SUMA_SurfaceObject *)dov[icheck].OP;
6094 SUMA_RETURN (icheck);
6095 }
6096 ++ncheck;
6097 }
6098 /* should not get here */
6099 SUMA_RETURN (-1);
6100 }
6101
6102 /*!
6103 Replaces one surface in RegisteredDO with another
6104 */
SUMA_SwitchSO(SUMA_DO * dov,int N_dov,int SOcurID,int SOnxtID,SUMA_SurfaceViewer * sv)6105 SUMA_Boolean SUMA_SwitchSO (SUMA_DO *dov, int N_dov,
6106 int SOcurID, int SOnxtID, SUMA_SurfaceViewer *sv)
6107 {
6108 static char FuncName[]={"SUMA_SwitchSO"};
6109 SUMA_Axis *EyeAxis;
6110 int EyeAxis_ID;
6111 char CommString[100];
6112 SUMA_EngineData ED;
6113 DList *list = NULL;
6114
6115 SUMA_ENTRY;
6116
6117 /* unregister the current surface from RegisteredDO */
6118 /*fprintf(SUMA_STDERR,"%s: Unregistering DOv[%d]...\n", FuncName, SOcurID);*/
6119 if (!SUMA_UnRegisterDO(SOcurID, sv)) {
6120 fprintf(SUMA_STDERR,"Error %s: Failed to UnRegisterDO.\n", FuncName);
6121 SUMA_RETURN (NOPE);
6122 }
6123
6124 /* set the focus ID to the current surface */
6125 sv->Focus_DO_ID = SOnxtID;
6126
6127 /* register the new surface in RegisteredDO */
6128 /*fprintf(SUMA_STDERR,"%s: Registering DOv[%d]...\n",
6129 FuncName, sv->Focus_DO_ID); */
6130 if (!SUMA_RegisterDO(sv->Focus_DO_ID, sv)) {
6131 fprintf(SUMA_STDERR,"Error %s: Failed to RegisterDO.\n", FuncName);
6132 SUMA_RETURN (NOPE);
6133 }
6134
6135 /* modify the rotation center */
6136 if (!SUMA_UpdateRotaCenter(sv, dov, N_dov)) {
6137 fprintf (SUMA_STDERR,
6138 "Error %s: Failed to update center of rotation", FuncName);
6139 SUMA_RETURN (NOPE);
6140 }
6141
6142 /* set the viewing points */
6143 if (!SUMA_UpdateViewPoint(sv, dov, N_dov, 0)) {
6144 fprintf (SUMA_STDERR,"Error %s: Failed to update view point", FuncName);
6145 SUMA_RETURN (NOPE);
6146 }
6147
6148 /* Change the defaults of the eye axis to fit standard EyeAxis */
6149 EyeAxis_ID = SUMA_GetEyeAxis (sv, dov);
6150
6151 if (EyeAxis_ID < 0) {
6152 fprintf(SUMA_STDERR,"Error %s: No Eye Axis. %d\n", FuncName, EyeAxis_ID);
6153 } else {
6154 EyeAxis = (SUMA_Axis *)(dov[EyeAxis_ID].OP);
6155 SUMA_EyeAxisStandard (EyeAxis, sv);
6156 }
6157
6158 /* do the light business */
6159 if (dov[sv->Focus_DO_ID].ObjectType == SO_type &&
6160 !SUMA_SetViewerLightsForSO(sv,
6161 (SUMA_SurfaceObject *)(dov[sv->Focus_DO_ID].OP))) {
6162 SUMA_S_Warn("Failed to set viewer lights.\n"
6163 "Use 'F' key to flip lights in SUMA\n"
6164 "if necessary.");
6165 }
6166
6167 /* do the axis setup */
6168 SUMA_WorldAxisStandard (sv->WAx, sv);
6169
6170
6171 /* Home call baby */
6172 if (!list) list = SUMA_CreateList();
6173 SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_Home, SES_Suma, sv);
6174
6175 if (!SUMA_Engine (&list)) {
6176 fprintf(stderr, "Error SUMA_input: SUMA_Engine call failed.\n");
6177 }
6178
6179
6180 /* take care of the cross hair's XYZ */
6181
6182 /* to do elsewhere */
6183 /* when a cross hair needs to be communicated, you must use
6184 the LocalDomainParentID surface and not the Focus_Surface */
6185 SUMA_RETURN (YUP);
6186 }
6187
6188 /*!
6189 \brief gets overlays from parent surface SO_prec to child surface SO_nxt
6190
6191 */
SUMA_GetOverlaysFromParent(SUMA_SurfaceObject * SO_nxt,SUMA_SurfaceObject * SO_prec)6192 SUMA_Boolean SUMA_GetOverlaysFromParent(SUMA_SurfaceObject *SO_nxt,
6193 SUMA_SurfaceObject *SO_prec)
6194 {
6195 static char FuncName[]={"SUMA_GetOverlaysFromParent"};
6196 int j, OverInd=-1;
6197 SUMA_Boolean LocalHead = NOPE;
6198
6199 SUMA_ENTRY;
6200
6201 if (!SO_nxt || !SO_prec) {
6202 SUMA_SL_Err("Null input");
6203 SUMA_RETURN(NOPE);
6204 }
6205 if (!SUMA_isRelated_SO(SO_prec, SO_nxt, 1)) {
6206 SUMA_SL_Err("Surfaces are not level 1 related");
6207 SUMA_RETURN(NOPE);
6208 }
6209
6210 /* Create a link to each overlay plane in the precursor unless
6211 such a plane exists already */
6212 for (j=0; j < SO_prec->N_Overlays; ++j) {
6213 if (!SUMA_Fetch_OverlayPointer ((SUMA_ALL_DO *)SO_nxt,
6214 SO_prec->Overlays[j]->Name, &OverInd)) {
6215 /* plane not found, create a link to it */
6216 SUMA_LHv("Overlay plane %s not found, creating the link.\n",
6217 SO_prec->Overlays[j]->Name);
6218 SO_nxt->Overlays[SO_nxt->N_Overlays] =
6219 (SUMA_OVERLAYS *)SUMA_LinkToPointer((void*)SO_prec->Overlays[j]);
6220 /* it happens at times, that an overlay carries coordinate bias with it.
6221 When that happens, the bias should be added immediately */
6222 if (SO_nxt->Overlays[SO_nxt->N_Overlays]->OptScl) {
6223 if (SO_nxt->Overlays[SO_nxt->N_Overlays]->OptScl->BiasVect) {
6224 SUMA_LH("Adding coordbias");
6225 SUMA_AddVisX_CoordBias( SO_nxt,
6226 SO_nxt->Overlays[SO_nxt->N_Overlays],
6227 SO_nxt->Overlays[SO_nxt->N_Overlays]->OptScl->DoBias,
6228 SO_nxt->Overlays[SO_nxt->N_Overlays]->OptScl->BiasVect);
6229 /* Apply the business */
6230 if (!SUMA_ApplyVisXform(SO_nxt, "VisX",
6231 FORWARD_XFORM, 1)) {
6232 SUMA_S_Warn("Failed to apply VisX transform");
6233 }
6234 }
6235 }
6236 /*increment the number of overlay planes */
6237 ++SO_nxt->N_Overlays;
6238 } else {
6239 /* plane found, do nothing */
6240 SUMA_LHv("Overlay plane %s found. Index#%d\n.",
6241 SO_prec->Overlays[j]->Name, OverInd);
6242 }
6243 }
6244
6245 SUMA_RETURN(YUP);
6246 }
6247
6248 /*!
6249 ans = SUMA_SwitchState (dov, N_dov, sv, nxtstateID, nxtgroup);
6250
6251 Replaces one viewing state with another
6252
6253 */
SUMA_SwitchState(SUMA_DO * dov,int N_dov,SUMA_SurfaceViewer * sv,int nxtstateID,char * nxtgroup)6254 SUMA_Boolean SUMA_SwitchState ( SUMA_DO *dov, int N_dov,
6255 SUMA_SurfaceViewer *sv,
6256 int nxtstateID, char *nxtgroup)
6257 {
6258 static char FuncName[]={"SUMA_SwitchState"};
6259 SUMA_Axis *EyeAxis;
6260 int EyeAxis_ID, I_C, ND, id;
6261 char CommString[100];
6262 SUMA_EngineData ED;
6263 int curstateID, i, j, jmax, prec_ID, *MembSOs=NULL, N_MembSOs=0;
6264 int RegSO[SUMA_MAX_DISPLAYABLE_OBJECTS], N_RegSO;
6265 SUMA_SurfaceObject *SO_nxt, *SO_prec, *SO1, *SO2, *SOtmp=NULL;
6266 SUMA_DO_Types ttv[10]={SO_type, GRAPH_LINK_type, NOT_SET_type};
6267 float *XYZ, *XYZmap, zfac = 0.0;
6268 DList *list = NULL;
6269 SUMA_Boolean LocalHead = NOPE;
6270
6271 SUMA_ENTRY;
6272
6273 XYZ = NULL;
6274 XYZmap = NULL;
6275
6276 curstateID = SUMA_WhichState(sv->State, sv, sv->CurGroupName);
6277 zfac = sv->FOV[curstateID]/SUMA_sv_auto_fov(sv);
6278 if (zfac > 10) zfac = 10.0;
6279 if (zfac < 0.005) zfac = 0.005;
6280
6281 /* unregister all the surfaces for the current view */
6282 if (LocalHead)
6283 fprintf( SUMA_STDERR,
6284 "%s: Request to change to id %d\n"
6285 "Unregistering state %d (%s), sv(%p)->State = %s\n",
6286 FuncName, nxtstateID, curstateID, sv->VSv[curstateID].Name,
6287 sv, sv->State);
6288 for (i=0; i<sv->VSv[curstateID].N_MembDO; ++i) {
6289 if (!SUMA_UnRegisterDO(sv->VSv[curstateID].MembDO[i].dov_ind, sv)) {
6290 fprintf(SUMA_STDERR,"Error %s: Failed to UnRegisterDO.\n", FuncName);
6291 SUMA_RETURN (NOPE);
6292 }
6293 }
6294
6295 /* adopt the new group */
6296 if (strcmp(sv->CurGroupName, nxtgroup)) {
6297 SUMA_LH("Changing group...");
6298 if (!SUMA_AdoptGroup(sv, nxtgroup)) {
6299 SUMA_SLP_Err("Failed to adopt new group");
6300 SUMA_RETURN(NOPE);
6301 }
6302 } else {
6303 SUMA_LH("No group change...");
6304 }
6305
6306 /* register all the surfaces/DOs from the next view */
6307
6308 /* Need to set the state before you go into Registering DOs May 2013 */
6309 sv->State = sv->VSv[nxtstateID].Name;
6310 sv->iState = nxtstateID;
6311
6312 SUMA_LHv("Registering %d DOs of state %d (%s)...\n",
6313 sv->VSv[nxtstateID].N_MembDO, nxtstateID,
6314 sv->VSv[nxtstateID].Name);
6315 for (i=0; i<sv->VSv[nxtstateID].N_MembDO; ++i) {
6316 if (!SUMA_RegisterDO(sv->VSv[nxtstateID].MembDO[i].dov_ind, sv)) {
6317 fprintf(SUMA_STDERR,"Error %s: Failed to RegisterDO.\n", FuncName);
6318 SUMA_RETURN (NOPE);
6319 }
6320 }
6321
6322 /* if have two surfaces, keep them from overlapping */
6323 N_RegSO = SUMA_RegisteredSOs (sv, dov, RegSO);
6324 if (N_RegSO > 2) {
6325 SUMA_LH( "Will not attempt\n"
6326 "to separate more than\n"
6327 "2 surfaces.\n");
6328 } else if (N_RegSO == 2) {
6329 SO1 = (SUMA_SurfaceObject *)dov[RegSO[0]].OP;
6330 SO2 = (SUMA_SurfaceObject *)dov[RegSO[1]].OP;
6331 SUMA_LHv("Computing separation for %s and %s\n",
6332 SO1->Label, SO2->Label);
6333 if (!SO1->VisX0.Applied || !SO2->VisX0.Applied) {
6334 if (!SUMA_ComputeVisX(SO1, SO2, sv, "VisX0",1)) {
6335 SUMA_S_Err("Failed to compute or apply overlap avoidance xform");
6336 SUMA_RETURN(NOPE);
6337 }
6338 }
6339 }
6340
6341 SUMA_LH("Setting remix flag");
6342 /*set the Color Remix flag */
6343 if (!SUMA_SetShownLocalRemixFlag (sv)) {
6344 fprintf (SUMA_STDERR,
6345 "Error %s: Failed in SUMA_SetShownLocalRemixFlag.\n", FuncName);
6346 SUMA_RETURN (NOPE);
6347 }
6348
6349 /* Get those DOs that are surfaces or graphs*/
6350 MembSOs = SUMA_ViewState_Membs(&(sv->VSv[nxtstateID]), ttv, &N_MembSOs);
6351
6352 if (!MembSOs || N_MembSOs==0) {
6353 SUMA_S_Errv("No members found for state %s, what gives?\n",
6354 sv->VSv[nxtstateID].Name);
6355 SUMA_RETURN(NOPE);
6356 }
6357 /* if no coloroverlay exists, link to MapReference surface, if possible */
6358 SUMA_LHv("Have %d memb[SD]Os\n", N_MembSOs);
6359 for (i=0; i<N_MembSOs; ++i) {
6360 switch (dov[MembSOs[i]].ObjectType) {
6361 case SO_type:
6362 /* next surface being checked */
6363 SO_nxt = (SUMA_SurfaceObject *)(dov[MembSOs[i]].OP);
6364
6365 /* Get the Mapping Reference surface, that's the precursor*/
6366 if (!SO_nxt->LocalDomainParentID) {
6367 prec_ID = -1;
6368 }else {
6369 prec_ID = SUMA_findSO_inDOv( SO_nxt->LocalDomainParentID,
6370 SUMAg_DOv, SUMAg_N_DOv);
6371 }
6372 if (prec_ID < 0) {
6373 /* no precursors found, notify user */
6374 fprintf(SUMA_STDERR,
6375 "\n\aWarning %s: "
6376 "No precursors found for surface %d.\n"
6377 "Colors, selected nodes and facesets will "
6378 "not reflect those in previous state.\n.",
6379 FuncName, MembSOs[i]);
6380 continue;
6381 }
6382
6383 SO_prec = (SUMA_SurfaceObject *)(dov[prec_ID].OP);
6384
6385 /* check for risk of node inconsistencies */
6386
6387 if (SO_prec->N_Node >= SO_nxt->N_Node ) {/* > or equal number of nodes*/
6388 /* matching number of nodes */
6389 if (!SUMA_GetOverlaysFromParent(SO_nxt,SO_prec)) {
6390 SUMA_SL_Err("Failed to get overlays from parents");
6391 SUMA_RETURN(NOPE);
6392 }
6393
6394 if (SO_prec->N_Node > SO_nxt->N_Node) {/* More in prec */
6395 /* just warn */
6396 fprintf(SUMA_STDERR,
6397 "Warning %s: More nodes (%d) in precursor surface. \n"
6398 "Assuming upcoming surface is a subset of precursor.\n",
6399 FuncName, SO_prec->N_Node - SO_nxt->N_Node);
6400 }/* More in prec */
6401
6402 /* link the selected nodes and facesets, if possible */
6403 /*fprintf(SUMA_STDERR,
6404 "%s: Linking selected nodes ...\n",
6405 FuncName);*/
6406 /* check for risk of node inconsistencies */
6407 if (SO_prec->N_Node == SO_nxt->N_Node) {
6408 SO_nxt->SelectedNode = SO_prec->SelectedNode;
6409 } else { /*more nodes in precursor, make sure selected node is OK */
6410 if (SO_prec->SelectedNode < SO_nxt->N_Node) {
6411 SO_nxt->SelectedNode = SO_prec->SelectedNode;
6412 } else { /* this node does not exist in the upcoming thing */
6413 fprintf(SUMA_STDERR,
6414 "\n\aWarning %s: "
6415 "Slected node in precursor state does not exist "
6416 "in current state.\n"
6417 "Selected Node is left at previous setting in "
6418 "this view state.\n", FuncName);
6419 }
6420 }
6421
6422 } /* > or equal number of nodes */ else { /* less in prec */
6423 fprintf(SUMA_STDERR,
6424 "\n\aWarning %s: More nodes (%d) in upcoming surface. "
6425 "Colors, selected nodes and facesets are not carried "
6426 "through from precursor.\n",
6427 FuncName, SO_nxt->N_Node - SO_prec->N_Node);
6428 }
6429
6430 break;
6431 case GRAPH_LINK_type:
6432 /* nothing needed */
6433 break;
6434 default:
6435 SUMA_S_Err("Should not be here");
6436 break;
6437 }
6438
6439 }
6440
6441
6442 /* Bind the cross hair to a reasonable surface, if possible */
6443 if (iDO_isSO(sv->Ch->adoID)) {
6444 if (LocalHead)
6445 fprintf( SUMA_STDERR,
6446 "Local Debug %s: Linking Cross Hair via adoID...\n",
6447 FuncName);
6448 j = SUMA_MapRefRelative (sv->Ch->adoID,
6449 MembSOs,
6450 N_MembSOs, dov);
6451 if (LocalHead) fprintf( SUMA_STDERR,
6452 "Local Debug %s: "
6453 "Cross Hair's New adoID = %d\n",
6454 FuncName, j );
6455
6456 /* set the XYZ of the cross hair based on the
6457 coordinates of the upcoming surface, if possible */
6458 if (j >= 0) {
6459 SO_nxt = (SUMA_SurfaceObject *)(dov[j].OP);
6460 ND = SO_nxt->NodeDim;
6461 id = ND * sv->Ch->datumID;
6462 if (sv->Ch->datumID >= 0) {
6463 if (LocalHead) fprintf( SUMA_STDERR,
6464 "Local Debug %s: Using datumID for link.\n",
6465 FuncName);
6466 sv->Ch->c[0] = SO_nxt->NodeList[id];
6467 sv->Ch->c[1] = SO_nxt->NodeList[id+1];
6468 sv->Ch->c[2] = SO_nxt->NodeList[id+2];
6469 } else {
6470 /* no node associated with cross hair, use XYZ */
6471 if (LocalHead) fprintf( SUMA_STDERR,
6472 "Local Debug %s: Using XYZ for link.\n",
6473 FuncName);
6474 SO_prec = (SUMA_SurfaceObject *)(dov[sv->Ch->adoID].OP);
6475 /* go from XYZ to XYZmap on current surface
6476 then from XYZmap to XYZ on new surface */
6477 I_C = -1;
6478 XYZmap = SUMA_XYZ_XYZmap (sv->Ch->c, SO_prec, dov, N_dov, &I_C, 1);
6479 if (XYZmap == NULL) {
6480 fprintf( SUMA_STDERR,
6481 "Error %s: Failed in SUMA_XYZ_XYZmap\n",
6482 FuncName);
6483 }else {
6484 XYZ = SUMA_XYZmap_XYZ (XYZmap, SO_nxt, dov, N_dov, &I_C, 1);
6485 if (XYZ == NULL) {
6486 fprintf( SUMA_STDERR,
6487 "Error %s: Failed in SUMA_XYZmap_XYZ\n",
6488 FuncName);
6489 } else {
6490 sv->Ch->c[0] = XYZ[0];
6491 sv->Ch->c[1] = XYZ[1];
6492 sv->Ch->c[2] = XYZ[2];
6493 }
6494
6495 }
6496 if (XYZ) SUMA_free(XYZ);
6497 if (XYZmap) SUMA_free(XYZmap);
6498 }
6499
6500 /* if the surface controller is open, update it */
6501 if (SUMA_isADO_Cont_Realized((SUMA_ALL_DO *)SO_nxt)) {
6502 SUMA_Init_SurfCont_SurfParam((SUMA_ALL_DO *)SO_nxt);
6503 }
6504
6505 } else {
6506 fprintf( SUMA_STDERR,
6507 "%s: No relatives between states. "
6508 "CrossHair location will not correspond between states\n",
6509 FuncName);
6510 }
6511 sv->Ch->adoID = j;
6512 if (LocalHead)
6513 fprintf(SUMA_STDERR,
6514 "Local Debug %s: Linking Cross Hair Via datumID Done.\n",
6515 FuncName);
6516 }
6517
6518
6519
6520 if (sv->FOV[sv->iState] == sv->FOV_original || sv->FOV[sv->iState] < 0) {
6521 sv->FOV[sv->iState] = SUMA_sv_auto_fov(sv);
6522 }
6523 if (sv->FreezeZoomXstates)
6524 sv->FOV[sv->iState] = SUMA_sv_auto_fov(sv)*zfac;
6525
6526 /* set the focus ID to the first surface/object in the next view */
6527 sv->Focus_DO_ID = MembSOs[0];
6528
6529 SUMA_ifree(MembSOs);
6530
6531 /* Now update the cross hair info if needed for the surface in focus */
6532 if (sv->Ch->adoID >= 0 && (SOtmp = SUMA_SV_Focus_SO(sv))) {
6533 if (SUMA_isADO_Cont_Realized((SUMA_ALL_DO *)SOtmp)) {
6534 SUMA_Init_SurfCont_CrossHair((SUMA_ALL_DO *)SOtmp);
6535 }
6536 }
6537
6538 if ((SOtmp = SUMA_SV_Focus_SO(sv)) && LocalHead) {
6539 fprintf( SUMA_STDERR,
6540 "%s: Setting new Focus ID to surface %s\n",
6541 FuncName, SOtmp->Label);
6542 }
6543
6544 /* decide what the best state is */
6545 sv->StdView = SUMA_BestStandardView (sv,dov, N_dov);
6546 if (LocalHead) fprintf( SUMA_STDOUT,
6547 "%s: Standard View Now %d\n",
6548 FuncName, sv->StdView);
6549 if (sv->StdView == SUMA_N_STANDARD_VIEWS) {
6550 fprintf( SUMA_STDERR,
6551 "Error %s: Could not determine the best standard view. "
6552 "Choosing default SUMA_3D\n",
6553 FuncName);
6554 sv->StdView = SUMA_3D;
6555 }
6556
6557 /* modify the rotation center */
6558 if (!SUMA_UpdateRotaCenter(sv, dov, N_dov)) {
6559 fprintf (SUMA_STDERR,
6560 "Error %s: Failed to update center of rotation",
6561 FuncName);
6562 SUMA_RETURN (NOPE);
6563 }
6564
6565 /* set the viewing points */
6566 if (!SUMA_UpdateViewPoint(sv, dov, N_dov, 0)) {
6567 fprintf (SUMA_STDERR,"Error %s: Failed to update view point", FuncName);
6568 SUMA_RETURN (NOPE);
6569 }
6570
6571 /* Change the defaults of the eye axis to fit standard EyeAxis */
6572 EyeAxis_ID = SUMA_GetEyeAxis (sv, dov);
6573
6574 if (EyeAxis_ID < 0) {
6575 fprintf(SUMA_STDERR,"Error %s: No Eye Axis. %d\n", FuncName, EyeAxis_ID);
6576 } else {
6577 EyeAxis = (SUMA_Axis *)(dov[EyeAxis_ID].OP);
6578 SUMA_EyeAxisStandard (EyeAxis, sv);
6579 }
6580
6581 /* do the axis setup */
6582 SUMA_WorldAxisStandard (sv->WAx, sv);
6583
6584 /* do the light business */
6585 if (SOtmp && !SUMA_SetViewerLightsForSO( sv, SOtmp )) {
6586 SUMA_S_Warn("Failed to set viewer lights.\n"
6587 "Use 'F' key to flip lights in SUMA if necessary.");
6588 }
6589
6590 /* Home call baby */
6591 if (!list) list = SUMA_CreateList();
6592 SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_Home, SES_Suma, sv);
6593 if (!SUMA_Engine (&list)) {
6594 fprintf(stderr, "Error SUMA_input: SUMA_Engine call failed.\n");
6595 }
6596
6597 SUMA_RETURN (YUP);
6598 }
6599
6600 /*!
6601 Call this function whenever you have new geometry in the viewer
6602 This happens when you switch states or when you modify the coordinates
6603 of a surface
6604 The succession of function calls is replicated in parts elsewhere in the code
6605 like in the SwitchState function
6606 */
SUMA_NewGeometryInViewer(SUMA_DO * dov,int N_dov,SUMA_SurfaceViewer * sv)6607 SUMA_Boolean SUMA_NewGeometryInViewer (SUMA_DO *dov, int N_dov,
6608 SUMA_SurfaceViewer *sv)
6609 {
6610 static char FuncName[]={"SUMA_NewGeometryInViewer"};
6611 SUMA_Axis *EyeAxis;
6612 int EyeAxis_ID, I_C, OverInd, ND, id;
6613 char CommString[100];
6614 SUMA_EngineData ED;
6615 int i, j, jmax, prec_ID;
6616 SUMA_SurfaceObject *SO_nxt, *SO_prec;
6617 SUMA_Boolean LocalHead = NOPE;
6618
6619 SUMA_ENTRY;
6620
6621 /* decide what the best std view is */
6622 sv->StdView = SUMA_BestStandardView (sv,dov, N_dov);
6623 if (LocalHead)
6624 fprintf(SUMA_STDOUT,"%s: Standard View Now %d\n", FuncName, sv->StdView);
6625 if (sv->StdView == SUMA_N_STANDARD_VIEWS) {
6626 fprintf(SUMA_STDERR,
6627 "Error %s: Could not determine the best standard view."
6628 " Choosing default SUMA_3D\n", FuncName);
6629 sv->StdView = SUMA_3D;
6630 }
6631
6632 /* modify the rotation center */
6633 if (!SUMA_UpdateRotaCenter(sv, dov, N_dov)) {
6634 SUMA_S_Err("Failed to update center of rotation");
6635 SUMA_RETURN (NOPE);
6636 }
6637
6638 /* set the viewing points */
6639 if (!SUMA_UpdateViewPoint(sv, dov, N_dov, 0)) {
6640 fprintf (SUMA_STDERR,"Error %s: Failed to update view point", FuncName);
6641 SUMA_RETURN (NOPE);
6642 }
6643
6644
6645 /* Change the defaults of the eye axis to fit standard EyeAxis */
6646 EyeAxis_ID = SUMA_GetEyeAxis (sv, dov);
6647
6648 if (EyeAxis_ID < 0) {
6649 fprintf(SUMA_STDERR,"Error %s: No Eye Axis. %d\n", FuncName, EyeAxis_ID);
6650 } else {
6651 EyeAxis = (SUMA_Axis *)(dov[EyeAxis_ID].OP);
6652 SUMA_EyeAxisStandard (EyeAxis, sv);
6653 }
6654
6655 /* Need to update where you're looking at*/
6656 glMatrixMode(GL_MODELVIEW);
6657 glLoadIdentity();
6658 gluLookAt ( sv->GVS[sv->StdView].ViewFrom[0],
6659 sv->GVS[sv->StdView].ViewFrom[1],
6660 sv->GVS[sv->StdView].ViewFrom[2],
6661 sv->GVS[sv->StdView].ViewCenter[0],
6662 sv->GVS[sv->StdView].ViewCenter[1],
6663 sv->GVS[sv->StdView].ViewCenter[2],
6664 sv->GVS[sv->StdView].ViewCamUp[0],
6665 sv->GVS[sv->StdView].ViewCamUp[1],
6666 sv->GVS[sv->StdView].ViewCamUp[2]);
6667
6668 /* do the axis setup */
6669 SUMA_WorldAxisStandard (sv->WAx, sv);
6670
6671 /* You still need to call SUMA_display via SUMA_postRedisplay but that is done after this function returns */
6672
6673 SUMA_RETURN (YUP);
6674 }
6675
6676 /*!
6677 \brief ans = SUMA_OpenGLStateReset (dov, N_dov, sv);
6678 Used when going from one surface viewer to another. The OpenGL state variables
6679 need to be reset when moving from one viewer to the next. Otherwise you risk having
6680 unpredictable results the first time you do something in one viewer after you'd been
6681 in another.
6682 This function is a stripped down version of SUMA_SwitchState and should
6683 be followed by a call to SUMA_postRedisplay for all the changes to take effect.
6684
6685 Note that SUMA_postRedisplay may not be good enough because it posts a display request which may not execute immediately. SUMA_handleRedisplay would be the harsher, but more effective method.
6686
6687 Do not try executing all the commands in SUMA_display that affect the modelview
6688 matrix and the projection matrix without calling for a display the changes will not take effect.
6689
6690 \param dov (SUMA_DO *) Pointer to vector of displayable objects, typically SUMAg_DOv
6691 \param N_dov (int) number of elements in dov, typically SUMAg_N_DOv
6692 \param sv (SUMA_SurfaceViewer *) viewer making the request.
6693 \return YUP/NOPE Good/Bad
6694 \sa SUMA_NewGeometryInViewer
6695
6696 */
SUMA_OpenGLStateReset(SUMA_DO * dov,int N_dov,SUMA_SurfaceViewer * sv)6697 SUMA_Boolean SUMA_OpenGLStateReset (SUMA_DO *dov, int N_dov,
6698 SUMA_SurfaceViewer *sv)
6699 {
6700 static char FuncName[]={"SUMA_OpenGLStateReset"};
6701 SUMA_Axis *EyeAxis;
6702 int EyeAxis_ID, I_C, OverInd, ND, id;
6703 char CommString[100];
6704 SUMA_EngineData ED;
6705 int i, j, jmax, prec_ID;
6706 SUMA_SurfaceObject *SO_nxt, *SO_prec;
6707 SUMA_Boolean LocalHead = NOPE;
6708
6709 SUMA_ENTRY;
6710
6711 #if 0
6712 /* modify the rotation center */
6713 if (!SUMA_UpdateRotaCenter(sv, dov, N_dov)) {
6714 fprintf (SUMA_STDERR,
6715 "Error %s: Failed to update center of rotation", FuncName);
6716 SUMA_RETURN (NOPE);
6717 }
6718
6719 /* set the viewing points */
6720 if (!SUMA_UpdateViewPoint(sv, dov, N_dov, 0)) {
6721 fprintf (SUMA_STDERR,"Error %s: Failed to update view point", FuncName);
6722 SUMA_RETURN (NOPE);
6723 }
6724 #endif
6725
6726 /* This is all that is needed, the others above do not need to
6727 be updated at this stage*/
6728
6729 /* Change the defaults of the eye axis to fit standard EyeAxis */
6730 EyeAxis_ID = SUMA_GetEyeAxis (sv, dov);
6731
6732 if (EyeAxis_ID < 0) {
6733 /* This happens when only loading objects that are not surfaces.
6734 the eye axis for such monsters is created later, so return
6735 quietly */
6736 SUMA_LH("No Eye Axis. dealing with non SOs I take it?");
6737 } else {
6738 EyeAxis = (SUMA_Axis *)(dov[EyeAxis_ID].OP);
6739 SUMA_EyeAxisStandard (EyeAxis, sv);
6740 }
6741
6742
6743 #if 0
6744 /* force an axis drawing to set the projection matrix correctly */
6745 SUMA_SET_GL_PROJECTION(sv, sv->ortho);
6746 #endif
6747
6748 /* You still need to call SUMA_display via SUMA_postRedisplay but that is done after this function returns */
6749
6750 SUMA_RETURN (YUP);
6751 }
6752
6753
6754 /*!
6755 EyeAxisID = SUMA_GetEyeAxis (sv, dov);
6756 gets the ID (indices into dov) of the Eye Axis in sv
6757 \param sv (SUMA_SurfaceViewer *) the surface viewer structure
6758 \param dov (SUMA_DO *) the Displayable Objects vector (accessible to sv)
6759 \param Ax (SUMA_Axis *) a pointer to the Eye Axis structure (NULL if error )
6760 \ret EyeAxisID (int) the index into dov of the Eye Axis
6761 if an error is encountered, including more than one Eye Axis, a -1 is returned
6762 */
SUMA_GetEyeAxis(SUMA_SurfaceViewer * sv,SUMA_DO * dov)6763 int SUMA_GetEyeAxis (SUMA_SurfaceViewer *sv, SUMA_DO *dov)
6764 {
6765 static char FuncName[]={"SUMA_GetEyeAxis"};
6766 int i, k = -1, cnt = 0;
6767 SUMA_Axis *AO;
6768
6769 SUMA_ENTRY;
6770
6771 for (i=0; i< sv->N_DO; ++i) {
6772 if (dov[sv->RegistDO[i].dov_ind].ObjectType == AO_type) {
6773 AO = (SUMA_Axis *)(dov[sv->RegistDO[i].dov_ind].OP);
6774 if (strcmp(AO->Label, "Eye Axis") == 0) {
6775 k = sv->RegistDO[i].dov_ind;
6776 ++cnt;
6777 }
6778 }
6779 }
6780 if (cnt > 1) {
6781 fprintf (SUMA_STDERR,
6782 "Error %s: Found more than one Eye Axis. \n", FuncName);
6783 SUMA_RETURN (-1);
6784 }
6785
6786 SUMA_RETURN (k);
6787 }
6788
6789 /*!
6790 transform current XYZ to XYZmap
6791 The XYZ on an auxilliary surface are of no relevance to the volume.
6792 They must be transformed to mappable XYZ (in mm, RAI, in alignment
6793 with the Parent Volume)
6794 XYZmap = SUMA_XYZ_XYZmap (XYZ, SO, dov, N_dov, I_C, LDP_only);
6795
6796 \param XYZ (float *) XYZ triplet in SO's native coordinate space
6797 \param SO (SUMA_SurfaceObject *SO) obvious, ain't it
6798 \param dov (SUMA_DO*) vector containing all displayable objects
6799 \param N_dov (int) number of elements in dov
6800 \param I_C (int *) (pre allocated) pointer to the index of the closest
6801 (or representative) node in SO to the XYZ location.
6802 If you do not have it, make sure *I_C = -1.
6803 If you do so, the function will search for nodes contained in
6804 a box mm wide and centered on XYZ.
6805 If nodes are found in the box the I_C is set to the
6806 index of the closest node and XYZmap contains the coordinates
6807 of I_C in the SO->LocalDomainParentID surface.
6808 \param LDP_only (int) if 1, then XYZmap is only the same as XYZ when SO
6809 is itself the LDP.
6810 if 0, XYZmap = XYZ is SO is LDP, or if SO is
6811 anatomically correct.
6812 \ret XYZmap (float *) Mappable XYZ coordinates. NULL in case of trouble.
6813
6814 */
6815
SUMA_XYZ_XYZmap(float * XYZ,SUMA_SurfaceObject * SO,SUMA_DO * dov,int N_dov,int * I_C,int LDP_only)6816 float * SUMA_XYZ_XYZmap (float *XYZ, SUMA_SurfaceObject *SO,
6817 SUMA_DO* dov, int N_dov, int *I_C, int LDP_only)
6818 {/* SUMA_XYZ_XYZmap */
6819 static char FuncName[]={"SUMA_XYZ_XYZmap"};
6820 float *XYZmap;
6821 int iclosest, id, ND;
6822 SUMA_SurfaceObject *SOmap;
6823 int SOmapID;
6824 SUMA_Boolean LocalHead = NOPE;
6825
6826 SUMA_ENTRY;
6827
6828 /* allocate for return */
6829 XYZmap = (float *)SUMA_calloc (3, sizeof(float));
6830 if (XYZmap == NULL) {
6831 fprintf(SUMA_STDERR,
6832 "Error %s: Could not allocate for XYZmap.\n", FuncName);
6833 SUMA_RETURN (NULL);
6834 }
6835
6836 /* if surface is a local domain parent, do the obivious */
6837 if (SUMA_isLocalDomainParent(SO)){
6838 /*SUMA_LH("Surface is a local domain parent. XYZmap = XYZ.\n"); */
6839 SUMA_COPY_VEC (XYZ, XYZmap, 3, float, float);
6840 SUMA_RETURN (XYZmap);
6841 }
6842
6843 if (!LDP_only && SO->AnatCorrect){ /* Aug. 22 2012 */
6844 /*SUMA_LH("Surface is anatomocally correct. XYZmap = XYZ.\n"); */
6845 SUMA_COPY_VEC (XYZ, XYZmap, 3, float, float);
6846 SUMA_RETURN (XYZmap);
6847 }
6848
6849 /* if surface is not a local domain parent and not anatomically correct,
6850 do the deed */
6851 if (!SUMA_ismappable(SO)){
6852 SUMA_S_Warn("Surface is NOT mappable, returning NULL.");
6853 SUMA_free(XYZmap);
6854 SUMA_RETURN (NULL);
6855 }
6856
6857 /* surface is mappable, things will get more complicated */
6858
6859 /* find the closest node in SO */
6860 if (*I_C < 0) { /* user has not specified closest node ID*/
6861 /* must find closest node on my own */
6862 {
6863 SUMA_ISINBOX IB;
6864 float Bd[3], distance;
6865 int ii;
6866
6867 /* set the search box dimensions */
6868 Bd[0] = Bd[1] = Bd[2] = SUMA_XYZ_XFORM_BOXDIM_MM;
6869 IB = SUMA_isinbox (SO->NodeList, SO->N_Node, XYZ, Bd, YUP);
6870 SUMA_S_Notev("%d nodes (out of %d) found in box\n",
6871 IB.nIsIn, SO->N_Node);
6872
6873 if (IB.nIsIn) { /* found some, find the closest node */
6874 /* locate the closest node and store it's id in EngineData*/
6875 /*for (ii=0; ii<IB.nIsIn; ++ii) {
6876 fprintf (SUMA_STDERR,"%d\t%.3f\t\t", IB.IsIn[ii], IB.d[ii]);
6877 }*/
6878 SUMA_MIN_LOC_VEC (IB.d, IB.nIsIn, distance, iclosest);
6879 iclosest = IB.IsIn[iclosest];
6880 /* get ridd of IB's vectors */
6881 if (!SUMA_Free_IsInBox (&IB)) {
6882 fprintf(SUMA_STDERR,"Error %s: Failed to free IB\n", FuncName);
6883 }
6884
6885 } else { /* no node is close enough */
6886 SUMA_S_Errv("No node was close enough to XYZ=[%f %f %f],"
6887 " no linkage possible\n",
6888 XYZ[0], XYZ[1], XYZ[2]);
6889 SUMA_free(XYZmap);
6890 SUMA_RETURN (NULL);
6891 }
6892 /* store iclosest for lazy user */
6893 *I_C = iclosest;
6894 }
6895 } else {
6896 iclosest = *I_C;
6897 }
6898
6899 SUMA_LHv("Node identified for linking purposes is %d\n", *I_C);
6900 /* find the SO that is the Mappable cahuna */
6901 SOmapID = SUMA_findSO_inDOv(SO->LocalDomainParentID, dov, N_dov);
6902 if (SOmapID < 0) {
6903 SUMA_S_Err("Failed in SUMA_findSO_inDOv This should not happen.");
6904 SUMA_free(XYZmap);
6905 SUMA_RETURN (NULL);
6906 }
6907
6908 SOmap = (SUMA_SurfaceObject *)(dov[SOmapID].OP);
6909 ND = SOmap->NodeDim;
6910 id = ND * iclosest;
6911 XYZmap[0]=SOmap->NodeList[id];
6912 XYZmap[1]=SOmap->NodeList[id+1];
6913 XYZmap[2]=SOmap->NodeList[id+2];
6914
6915 /* all is done */
6916
6917 SUMA_RETURN (XYZmap);
6918 }/* SUMA_XYZ_XYZmap */
6919
6920 /*!
6921 transform XYZmap to XYZ on current surface
6922
6923 XYZ = SUMA_XYZmap_XYZ (XYZmap, SO, dov, N_dov, I_C, LDP_only);
6924
6925 \param XYZmap (float *) XYZmap triplet in SO's MapRef coordinate space
6926 \param SO (SUMA_SurfaceObject *SO) obvious, ain't it
6927 \param dov (SUMA_DO*) vector containing all displayable objects
6928 \param N_dov (int) number of elements in dov
6929 \param I_C (int *) (pre allocated) pointer to the index of the closest
6930 (or representative) node in SO's MapRef to the XYZmap location.
6931 If you do not have it, make sure *I_C = -1.
6932 If you do so, the function will search for nodes contained in
6933 a box mm wide and centered on XYZmap.
6934 If nodes are found in the box the I_C is set to the index of
6935 the closest node and XYZ contains the coordinates of I_C in the
6936 SO surface.
6937 \param LDP_only (int) if 1, XYZmap is set to XYZ only if SO is the LDP
6938 0, XYZmap is set to XYZ is SO is LDP or AnatCorrect
6939 \ret XYZ (float *) Equivalent of XYZmap on the auxilliary surface SO.
6940 NULL in case of trouble.
6941
6942 \sa SUMA_XYZ_XYZmap
6943 */
6944
SUMA_XYZmap_XYZ(float * XYZmap,SUMA_SurfaceObject * SO,SUMA_DO * dov,int N_dov,int * I_C,int LDP_only)6945 float * SUMA_XYZmap_XYZ (float *XYZmap, SUMA_SurfaceObject *SO, SUMA_DO* dov,
6946 int N_dov, int *I_C, int LDP_only)
6947 {/* SUMA_XYZmap_XYZ */
6948 static char FuncName[]={"SUMA_XYZmap_XYZ"};
6949 float *XYZ;
6950 int iclosest, id, ND;
6951 SUMA_SurfaceObject *SOmap;
6952 int SOmapID;
6953 SUMA_Boolean LocalHead = NOPE;
6954
6955 SUMA_ENTRY;
6956
6957 /* allocate for return */
6958 XYZ = (float *)SUMA_calloc (3, sizeof(float));
6959 if (XYZ == NULL) {
6960 fprintf(SUMA_STDERR,"Error %s: Could not allocate for XYZ.\n", FuncName);
6961 SUMA_RETURN (NULL);
6962 }
6963
6964 /* if surface is not mappable, do the deed */
6965 if (!SUMA_ismappable(SO)){
6966 fprintf(SUMA_STDERR,"%s: Surface is NOT mappable, returning NULL.\n", FuncName);
6967 SUMA_free(XYZ);
6968 SUMA_RETURN (NULL);
6969 }
6970
6971 /* if surface is a local domain parent, do the obivious */
6972 if (SUMA_isLocalDomainParent(SO)){
6973 SUMA_LH("Surface is a local domain parent. XYZ = XYZmap.\n");
6974 SUMA_COPY_VEC (XYZmap, XYZ, 3, float, float);
6975 SOmap = SO;
6976 /* do not return yet, must fix the node id too */
6977 } else if (!LDP_only && SO->AnatCorrect) {
6978 /* surface is anatomicall correct, use it */
6979 SUMA_LH("Surface is anatomically correct. XYZ = XYZmap.\n");
6980 SUMA_COPY_VEC (XYZmap, XYZ, 3, float, float);
6981 SOmap = SO;
6982 /* do not return yet, must fix the node id too */
6983 } else {
6984 /* surface is mappable, things will get more complicated */
6985 /* find the SO that is the Mappable cahuna */
6986 SOmapID = SUMA_findSO_inDOv(SO->LocalDomainParentID, dov, N_dov);
6987 if (SOmapID < 0) {
6988 SUMA_S_Err("Failed in SUMA_findSO_inDOv This should not happen.");
6989 SUMA_free(XYZ);
6990 SUMA_RETURN (NULL);
6991 }
6992 SOmap = (SUMA_SurfaceObject *)(dov[SOmapID].OP);
6993 }
6994 /* find the closest node in SO */
6995 if (*I_C < 0) { /* user has not specified closest node ID*/
6996 /* must find closest node on my own */
6997 {
6998 SUMA_ISINBOX IB;
6999 float Bd[3], distance;
7000 int ii;
7001
7002 /* set the search box dimensions */
7003 Bd[0] = Bd[1] = Bd[2] = SUMA_XYZ_XFORM_BOXDIM_MM;
7004 IB = SUMA_isinbox (SOmap->NodeList, SOmap->N_Node, XYZmap, Bd, YUP);
7005 SUMA_LHv("%d nodes (out of %d) found in box\n",
7006 IB.nIsIn, SOmap->N_Node);
7007
7008 if (IB.nIsIn) { /* found some, find the closest node */
7009 /* locate the closest node and store it's id in EngineData*/
7010 /*for (ii=0; ii<IB.nIsIn; ++ii) {
7011 fprintf (SUMA_STDERR,"%d\t%.3f\t\t", IB.IsIn[ii], IB.d[ii]);
7012 }*/
7013 SUMA_MIN_LOC_VEC (IB.d, IB.nIsIn, distance, iclosest);
7014 iclosest = IB.IsIn[iclosest];
7015 /* get ridd of IB's vectors */
7016 if (!SUMA_Free_IsInBox (&IB)) {
7017 fprintf(SUMA_STDERR,"Error %s: Failed to free IB\n", FuncName);
7018 }
7019
7020 } else { /* no node is close enough */
7021 if (SO->AnatCorrect == NOPE && SO != SOmap) {
7022 /* used to be if (SO != SOmap) only */
7023 SUMA_SL_Warn( "No node was close enough\n"
7024 "to XYZmap, no linkage possible." );
7025 SUMA_free(XYZ);
7026 SUMA_RETURN (NULL);
7027 } else {
7028 /* comes from inherrently mappable stuff, makes sense to
7029 leave XYZ */
7030 SUMA_SL_Warn( "No node was close enough\n"
7031 "to XYZmap, linking by coordinate." );
7032 SUMA_COPY_VEC (XYZmap, XYZ, 3, float, float);
7033 SUMA_RETURN (XYZ);
7034 }
7035 }
7036 /* store iclosest for lazy user */
7037 *I_C = iclosest;
7038 }
7039 } else {
7040 iclosest = *I_C;
7041 }
7042 SUMA_LHv("Node identified for linking purposes is %d\n", *I_C);
7043 ND = SO->NodeDim;
7044 id = ND * iclosest;
7045 XYZ[0]=SO->NodeList[id];
7046 XYZ[1]=SO->NodeList[id+1];
7047 XYZ[2]=SO->NodeList[id+2];
7048
7049 /* all is done */
7050 SUMA_RETURN (XYZ);
7051 }/* SUMA_XYZmap_XYZ */
7052
7053 /*!
7054 Prec_ID = SUMA_MapRefRelative (Cur_ID, Prec_List, N_Prec_List, dov);
7055 Returns the ID (index into dov) of the surface object in Prec_List that
7056 is related (via MapRef) to the surface object Cur_ID.
7057 This means that SOcur.LocalDomainParentID = SOprec.MapRef_icode_str or SOprec.idcode_str
7058
7059 \param Cur_ID (int) index into dov of the current surface object
7060 \param Prec_List (int *) indices into dov of the precursor surface objects
7061 \param N_Prec_List (int) number of indices in Prec_List
7062 \param dov (SUMA_DO *) the vector of Displayable Object Structures
7063 \ret Prec_ID (int) index into dov of the surface object that is related
7064 to Cur_ID
7065
7066 */
SUMA_MapRefRelative(int cur_id,int * prec_list,int N_prec_list,SUMA_DO * dov)7067 int SUMA_MapRefRelative (int cur_id, int *prec_list, int N_prec_list,
7068 SUMA_DO *dov)
7069 {
7070 int i, rel_id = -1;
7071 static char FuncName[]={"SUMA_MapRefRelative"};
7072 SUMA_SurfaceObject *SOcur, *SO_prec;
7073
7074 SUMA_ENTRY;
7075
7076 if (!iDO_isSO(cur_id)) { /* not a surface, return */
7077 SUMA_RETURN(-1);
7078 }
7079
7080 SOcur = (SUMA_SurfaceObject *)(dov[cur_id].OP);
7081 /* if surface has no MapRef then it cannot receive colors from precursors */
7082 if (!SUMA_ismappable(SOcur)) {
7083 SUMA_RETURN (-1);
7084 }
7085
7086 for (i=0; i<N_prec_list; ++i) {
7087 if (iDO_isSO(prec_list[i])) {
7088 SO_prec = (SUMA_SurfaceObject *)(dov[prec_list[i]].OP);
7089
7090 if ( SO_prec == SOcur ||
7091 strcmp(SOcur->idcode_str, SO_prec->idcode_str) == 0 ) {
7092 if (N_prec_list == 1) {
7093 /* if all you have is one surface in one state in SUMA
7094 then you need not worry about the rest */
7095 } else {
7096 /* this can happen if you have multiple surfaces with each being
7097 their own mappable surfaces., so it is OK too */
7098 /*
7099 fprintf(SUMA_STDERR, "\nError %s: Flow problem.\n"
7100 "Did not expect identical surfaces \n"
7101 "in this condition (N_prec_list = %d)\n",
7102 FuncName, N_prec_list);
7103 SUMA_BEEP;
7104 */
7105 }
7106 /*
7107 I changed the next condition:
7108 if ( strcmp(SOcur->LocalDomainParentID,
7109 SO_prec->LocalDomainParentID) == 0 ||
7110 strcmp(SOcur->LocalDomainParentID, SO_prec->idcode_str) == 0 )
7111 to
7112 if ( SUMA_isRelated_SO(SOcur, SO_prec, 1) )
7113 The two are the same except for the condition when the two surfaces
7114 are identical. So I put in a error message when that would happen and
7115 I'll deal with it then.
7116 ZSS Jan 08 04
7117 */
7118
7119 }
7120
7121 if ( SUMA_isRelated_SO(SOcur, SO_prec, 1) ) {
7122 /* Change made Jan 08 04, see note above */
7123 /* there's some relationship here, save it for return */
7124 if (rel_id < 0) {
7125 rel_id = prec_list[i];
7126 } else {
7127 fprintf (SUMA_STDERR,
7128 "Error %s: I did not think that would occur!"
7129 " Ignoring other relatives for now.\n", FuncName);
7130 }
7131
7132 }
7133 }
7134 }
7135
7136 SUMA_RETURN (rel_id);
7137
7138 }
7139
7140 /*!
7141 \brief creates a list of surfaces that are to be sent to AFNI
7142 */
SUMA_FormSOListToSendToAFNI(SUMA_DO * dov,int N_dov,int * N_Send)7143 int *SUMA_FormSOListToSendToAFNI(SUMA_DO *dov, int N_dov, int *N_Send)
7144 {
7145 static char FuncName[]={"SUMA_FormSOListToSendToAFNI"};
7146 int *SendList = NULL, ii, j, s, *is_listed=NULL;
7147 SUMA_SurfaceObject *SO=NULL;
7148 int no_need = 0;
7149 SUMA_SO_SIDE side=SUMA_NO_SIDE;
7150 SUMA_Boolean LocalHead = NOPE;
7151
7152 SUMA_ENTRY;
7153
7154 *N_Send = 0;
7155 SendList = (int *)SUMA_malloc(N_dov * sizeof(int));
7156 is_listed = (int *)SUMA_calloc(N_dov, sizeof(int));
7157 if (!SendList || !is_listed) {
7158 SUMA_SL_Crit("Failed to allocate");
7159 SUMA_RETURN(SendList);
7160 }
7161
7162
7163 for (s=0;s<5; ++s) {
7164 for (ii=0; ii<N_dov; ++ii) {
7165 if (SUMA_isSO(dov[ii])) {
7166 SO = (SUMA_SurfaceObject *)(dov[ii].OP);
7167 if (SO->SentToAfni) { no_need = 1; }
7168 if ( SO->AnatCorrect && !SO->SentToAfni
7169 && SO->VolPar ) {
7170 if (!SUMA_ExcludeFromSendToAfni(SO)) {
7171 switch (s) {
7172 case 0:
7173 if ( !is_listed[ii] &&
7174 SO->Side == SUMA_LEFT &&
7175 SUMA_isTypicalSOforVolSurf(SO) == -1) {
7176 SendList[*N_Send] = ii;
7177 *N_Send = *N_Send + 1;
7178 is_listed[ii] = 1;}
7179 break;
7180 case 1:
7181 if ( !is_listed[ii] &&
7182 SO->Side == SUMA_LEFT &&
7183 SUMA_isTypicalSOforVolSurf(SO) == 1) {
7184 SendList[*N_Send] = ii;
7185 *N_Send = *N_Send + 1;
7186 is_listed[ii] = 1;}
7187 break;
7188 case 2:
7189 if ( !is_listed[ii] &&
7190 SO->Side == SUMA_RIGHT &&
7191 SUMA_isTypicalSOforVolSurf(SO) == -1) {
7192 SendList[*N_Send] = ii;
7193 *N_Send = *N_Send + 1;
7194 is_listed[ii] = 1;}
7195 break;
7196 case 3:
7197 if ( !is_listed[ii] &&
7198 SO->Side == SUMA_RIGHT &&
7199 SUMA_isTypicalSOforVolSurf(SO) == 1) {
7200 SendList[*N_Send] = ii;
7201 *N_Send = *N_Send + 1;
7202 is_listed[ii] = 1;}
7203 break;
7204 default:
7205 if ( !is_listed[ii]) {
7206 SendList[*N_Send] = ii;
7207 *N_Send = *N_Send + 1;
7208 is_listed[ii] = 1;}
7209 break;
7210 }
7211 } else {
7212 if (s == 0) {
7213 SUMA_S_Notev(
7214 "State %s not sent to AFNI per exclusion in env %s\n",
7215 SO->State, "SUMA_DoNotSendStates");
7216 }
7217 }
7218 }
7219 }
7220 }
7221 }
7222
7223 if (*N_Send == 0 && !no_need) {
7224 /* an indication that nothing can be sent,
7225 as opposed things have been sent already
7226 and need not be resent */
7227 *N_Send = -1;
7228 }
7229 SUMA_RETURN(SendList);
7230
7231 }
7232
7233
7234
7235 /* get the output file for plugout info */
7236 static FILE *
SUMA_drive_get_outstream()7237 SUMA_drive_get_outstream()
7238 {
7239 char *suma_outfile;
7240
7241 /* first time in set the output stream to stdout or environment variable */
7242 if(sumaout==NULL){
7243 /* get from environment variable if set */
7244 suma_outfile = my_getenv("SUMA_OUTPLUG");
7245 if(suma_outfile!=NULL) {
7246 SUMA_drive_set_outstream(suma_outfile);
7247 }
7248 }
7249
7250 /* if still NULL output stream, set to default of stdout */
7251 if(sumaout==NULL) sumaout = stdout;
7252
7253 return(sumaout);
7254 }
7255
7256 /* set the output stream to a file rather than stdout*/
7257 static int
SUMA_drive_set_outstream(char * outfile)7258 SUMA_drive_set_outstream(char *outfile)
7259 {
7260 /* if just passed a NULL, reset output to stdout */
7261 if(outfile==NULL){
7262 sumaout = stdout;
7263 return(-1);
7264 }
7265
7266 /* check if resetting to stdout by string from plugout command */
7267 if(strcmp(outfile, "stdout")==0) {
7268 sumaout = stdout;
7269 return 0;
7270 }
7271
7272 /* make sure this file name is a good one, and open it for append */
7273 if( THD_filename_ok(outfile) )
7274 sumaout = fopen(outfile, "a");
7275
7276 /* something went wrong, so tell user and reset to stdout */
7277 if(sumaout==NULL){
7278 fprintf(stderr, "**** couldn't open outfile, resetting to stdout\n");
7279 sumaout = stdout;
7280 return(-1);
7281 }
7282 else {
7283 return 0;
7284 }
7285 }
7286
7287
7288