1 /*****************************************************************************
2    Major portions of this software are copyrighted by the Medical College
3    of Wisconsin, 1994-2000, and are released under the Gnu General Public
4    License, Version 2.  See the file README.Copyright for details.
5 ******************************************************************************/
6 
7 #undef MAIN
8 
9 #include "afni.h"
10 
11 #undef  STAMPER
12 #define STAMPER(ar,ww)    \
13  do{ if( (ar) != NULL )   \
14        (ar)->last_when[(ww)-RECEIVE_BASEVAL] = NI_clock_time() ; } while(0)
15 
16 #undef  STAMPCHECK
17 #if 1
18 #define STAMPCHECK(ar,ww) \
19  ( (ar) != NULL && NI_clock_time() > (ar)->last_when[(ww)-RECEIVE_BASEVAL]+33 )
20 #else
21 #define STAMPCHECK(ar,ww) ((ar) != NULL)
22 #endif
23 
24 #undef  STAMPSHOW
25 #define STAMPSHOW(iq,ar,ww)               \
26  INFO_message("%d: last_when[%d] = %d",   \
27               (iq),(ww)-RECEIVE_BASEVAL,(ar)->last_when[(ww)-RECEIVE_BASEVAL])
28 
29 /*---------------------------------------------------------------------------*/
30 /*! Set up to have AFNI send data to a receiver (callback function):
31 
32      rmask = bitwise OR (|) mask of RECEIVE_*_MASK (cf. afni.h)
33 
34      cb    = callback function to receive data; will be called like
35                cb( int why , int np , void *vp , void *cb_data )
36              where why = a RECEIVE_* code (cf. below)
37                    np  = count of data in vp (may be 0)
38                    vp  = pointer to data being sent (may be NULL)
39                cb_data = pointer passed into this routine (may be NULL)
40 
41      cbname = string to identify callback func (for debugging)
42 
43      why = RECEIVE_VIEWPOINT --> np = 3, vp = int *, pointing to
44                                  array of dataset voxel indices just
45                                  jumped to; vp[0] = x index, etc.
46 
47      why = RECEIVE_REDISPLAY --> the user did something to cause
48                                  an image redisplay besides changing
49                                  the viewpoint. For this call, np and
50                                  vp are unused.
51 
52      why = RECEIVE_FUNCDISPLAY --> the user did something to cause
53                                    the function display to change.
54                                    For this call, np and vp are unused.
55 
56      why = RECEIVE_POINTS --> np = number of points drawn
57                               vp = int **, pointer to array of arrays
58                                    of dataset voxel indices:
59                                     vp[0][i] = x index of point i
60                                     vp[1][i] = y index of point i
61                                     vp[2][i] = z index of point i,
62                                     vp[3][0] = sending mode
63                                    for i=0..np-1
64 
65      why = RECEIVE_DRAWNOTICE --> the user drew something and that
66                                   information was sent to a receiver.
67                                   This call will occur AFTER all the
68                                   RECEIVE_POINTS calls have been done.
69                                   If no RECEIVE_POINTS calls are made,
70                                   then no RECEIVE_DRAWNOTICE calls will
71                                   be made either.  For this call,
72                                   np and vp are unused.
73 
74      why = RECEIVE_DSETCHANGE --> the user did something (like rescan
75                                   a session) that may have changed
76                                   dataset pointers.  The receiving
77                                   routine should use dataset idcodes
78                                   to re-find the correct dataset
79                                   pointers.  For this call, np and vp
80                                   are unused.
81 
82      why = RECEIVE_CLOSURE --> the user closed the controller window,
83                                which means that no more data will
84                                be coming from it -- even if it is
85                                reopened, AFNI_receive_init must be
86                                called again.  For this call, np and
87                                vp are unused.
88 
89      why = RECEIVE_ALTERATION --> the user changed something in the
90                                   controller -- the dataset, the
91                                   time index, the resampling, ....
92                                   This is basically a warning
93                                   message.  For this call, np and
94                                   vp are unused.
95 
96      why = RECEIVE_TIMEINDEX --> the time index changed in im3d;
97                                  for this call, np,vp are unused.
98                                  The new time index is in
99                                    im3d->vinfo->time_index
100 
101    This function returns a non-negative int if all is OK -- this
102    value is the "key" that is used in calls to AFNI_receive_control
103    when you want to manipulate the status of this connection.
104 
105    This function returns -1 if an error occurs.
106 
107    Modified 29 Mar 1999 to allow for multiple receivers
108    (but drawing can only be done in one mode).
109 *//*-------------------------------------------------------------------------*/
110 
AFNI_receive_init(Three_D_View * im3d,int rmask,gen_func * cb,void * cb_data,char * cbname)111 int AFNI_receive_init( Three_D_View *im3d , int rmask ,
112                        gen_func *cb , void *cb_data  , char *cbname )
113 {
114    int ir , kk ;
115 
116 ENTRY("AFNI_receive_init") ;
117 
118    /* check for invalid entries */
119 
120    if( ! IM3D_VALID(im3d)            ||               /* no good? */
121        cb == NULL                    ||               /* no receiver? */
122        (rmask & RECEIVE_ALL_MASK) == 0 ) RETURN(-1) ; /* no action? */
123 
124    for( ir=0 ; ir < im3d->vinfo->num_receiver ; ir++ )
125      if( im3d->vinfo->receiver[ir] == NULL ) break ;
126 
127    if( ir == im3d->vinfo->num_receiver ){
128 #if 0
129 fprintf(stderr,"AFNI_receive_init AFREALL() with ir=%d num_receiver=%d\n",
130         ir,im3d->vinfo->num_receiver ) ;
131 #endif
132       im3d->vinfo->receiver = AFREALL( im3d->vinfo->receiver, AFNI_receiver *, ir+1 );
133       im3d->vinfo->num_receiver ++ ;
134    }
135    im3d->vinfo->receiver[ir] = AFMALL( AFNI_receiver, sizeof(AFNI_receiver)) ;
136 
137    im3d->vinfo->receiver[ir]->receiver_func = cb ;
138    im3d->vinfo->receiver[ir]->receiver_mask = rmask ;
139    im3d->vinfo->receiver[ir]->receiver_data = cb_data ;
140    for( kk=0 ; kk < RECEIVE_NUMVAL ; kk++ )
141      im3d->vinfo->receiver[ir]->last_when[kk] = -666 ;  /* 08 Sep 2009 */
142 
143    im3d->vinfo->receiver[ir]->receiver_funcname =
144      strdup( (cbname != NULL && *cbname != '\0') ? cbname : "[unknown func]" ) ;
145 
146    AFNI_toggle_drawing( im3d ) ;
147 
148    RETURN(ir) ;  /* 15 Jun 1999: used to return 0, which is not correct! */
149 }
150 
151 /*-------------------------------------------------------------------------*/
152 /*! Turn off all reception for this viewer.
153 ---------------------------------------------------------------------------*/
154 
AFNI_receive_destroy(Three_D_View * im3d)155 void AFNI_receive_destroy( Three_D_View *im3d )
156 {
157    int ir ;
158 
159 ENTRY("AFNI_receive_destroy") ;
160 
161    if( !IM3D_VALID(im3d) ) EXRETURN ;
162 
163    if( im3d->vinfo->receiver != NULL && im3d->vinfo->num_receiver > 0 ){
164 
165       for( ir=0 ; ir < im3d->vinfo->num_receiver ; ir++ ){
166 
167          if( im3d->vinfo->receiver[ir] != NULL ){
168 #if 0
169             im3d->vinfo->receiver[ir]->receiver_func(
170                    RECEIVE_CLOSURE , 0 , NULL ,
171                    im3d->vinfo->receiver[ir]->receiver_data ) ;
172 #else
173             AFNI_CALL_VOID_4ARG( im3d->vinfo->receiver[ir]->receiver_func ,
174                                  int,RECEIVE_CLOSURE , int,0 ,
175                                  void *,NULL ,
176                                  void *,im3d->vinfo->receiver[ir]->receiver_data ) ;
177 #endif
178 
179             if( im3d->vinfo->receiver[ir]->receiver_funcname != NULL )
180               free( im3d->vinfo->receiver[ir]->receiver_funcname ) ;
181             free( im3d->vinfo->receiver[ir] ) ;
182             im3d->vinfo->receiver[ir] = NULL ;
183          }
184       }
185 
186       im3d->vinfo->num_receiver    = 0 ;
187       im3d->vinfo->drawing_enabled = 0 ;
188       im3d->vinfo->drawing_mode    = DRAWING_LINES ;  /* default */
189    }
190 
191    EXRETURN ;
192 }
193 
194 /*-------------------------------------------------------------------*/
195 /*! Control how the receiver works:
196     - code = indicates what action is
197     - arg  = extra information, if code needs it
198 
199   This function returns 0 if all is OK, and returns -1 if an error
200   occurs.
201 ---------------------------------------------------------------------*/
202 
AFNI_receive_control(Three_D_View * im3d,int key,int code,void * arg)203 int AFNI_receive_control( Three_D_View *im3d, int key, int code, void *arg )
204 {
205 ENTRY("AFNI_receive_control") ;
206 
207    /* check input for OK-osity */
208 
209    if( ! IM3D_VALID(im3d) || im3d->vinfo->receiver == NULL ) RETURN(-1) ;
210    if( key < 0 || key >= im3d->vinfo->num_receiver )         RETURN(-1) ;
211    if( im3d->vinfo->receiver[key] == NULL )                  RETURN(-1) ;
212 
213    /* take appropriate actions */
214 
215    switch( code ){
216 
217       default: RETURN(-1) ;
218 
219       case DRAWNOTICE_STARTUP:{    /* 30 Mar 1999 */
220          im3d->vinfo->receiver[key]->receiver_mask |= RECEIVE_DRAWNOTICE_MASK ;
221       }
222       break ;
223 
224       case DRAWNOTICE_SHUTDOWN:{   /* 30 Mar 1999 */
225          im3d->vinfo->receiver[key]->receiver_mask &= (RECEIVE_ALL_MASK - RECEIVE_DRAWNOTICE_MASK) ;
226       }
227       break ;
228 
229       case DSETCHANGE_STARTUP:{    /* 31 Mar 1999 */
230          im3d->vinfo->receiver[key]->receiver_mask |= RECEIVE_DSETCHANGE_MASK ;
231       }
232       break ;
233 
234       case DSETCHANGE_SHUTDOWN:{   /* 30 Mar 1999 */
235          im3d->vinfo->receiver[key]->receiver_mask &= (RECEIVE_ALL_MASK - RECEIVE_DSETCHANGE_MASK) ;
236       }
237       break ;
238 
239       case DRAWING_STARTUP:{
240          im3d->vinfo->receiver[key]->receiver_mask |= RECEIVE_DRAWING_MASK ;
241          AFNI_toggle_drawing( im3d ) ;
242       }
243       break ;
244 
245       case DRAWING_SHUTDOWN:{
246          im3d->vinfo->receiver[key]->receiver_mask &= (RECEIVE_ALL_MASK - RECEIVE_DRAWING_MASK) ;
247          AFNI_toggle_drawing( im3d ) ;
248       }
249       break ;
250 
251       case DRAWING_OVCINDEX:{
252          int ind = PTOI(arg) ;
253 
254          if( ind <= 0 || ind >= im3d->dc->ovc->ncol_ov ){
255             RETURN(-1) ;
256          } else {
257             Pixel ppp = im3d->dc->ovc->pix_ov[ind] ;
258             drive_MCW_imseq( im3d->s123, isqDR_button2_pixel, (XtPointer)ppp ) ;
259             drive_MCW_imseq( im3d->s231, isqDR_button2_pixel, (XtPointer)ppp ) ;
260             drive_MCW_imseq( im3d->s312, isqDR_button2_pixel, (XtPointer)ppp ) ;
261             im3d->vinfo->drawing_pixel = ppp ;
262          }
263       }
264       break ;
265 
266       case DRAWING_X11PIXEL:{
267          Pixel ppp = (Pixel) arg ;
268          drive_MCW_imseq( im3d->s123, isqDR_button2_pixel, (XtPointer)ppp ) ;
269          drive_MCW_imseq( im3d->s231, isqDR_button2_pixel, (XtPointer)ppp ) ;
270          drive_MCW_imseq( im3d->s312, isqDR_button2_pixel, (XtPointer)ppp ) ;
271          im3d->vinfo->drawing_pixel = ppp ;
272       }
273       break ;
274 
275       case DRAWING_LINES:
276       case DRAWING_FILL:
277       case DRAWING_POINTS:
278       case DRAWING_NODRAW:{
279          im3d->vinfo->drawing_mode = code ;
280          drive_MCW_imseq( im3d->s123, isqDR_button2_mode, (XtPointer)ITOP(code) ) ;
281          drive_MCW_imseq( im3d->s231, isqDR_button2_mode, (XtPointer)ITOP(code) ) ;
282          drive_MCW_imseq( im3d->s312, isqDR_button2_mode, (XtPointer)ITOP(code) ) ;
283       }
284       break ;
285 
286       case DRAWING_LINEWIDTH:{    /* 08 Oct 2002 */
287         int ww = PTOI(arg) ;
288         if( ww >= 0 ){
289           drive_MCW_imseq( im3d->s123, isqDR_button2_width, (XtPointer)ITOP(ww) ) ;
290           drive_MCW_imseq( im3d->s231, isqDR_button2_width, (XtPointer)ITOP(ww) ) ;
291           drive_MCW_imseq( im3d->s312, isqDR_button2_width, (XtPointer)ITOP(ww) ) ;
292         }
293       }
294       break ;
295 
296       case VIEWPOINT_STARTUP:{
297          im3d->vinfo->receiver[key]->receiver_mask |= RECEIVE_VIEWPOINT_MASK ;
298       }
299       break ;
300 
301       case VIEWPOINT_SHUTDOWN:{
302          im3d->vinfo->receiver[key]->receiver_mask &= (RECEIVE_ALL_MASK - RECEIVE_VIEWPOINT_MASK) ;
303       }
304       break ;
305 
306       case REDISPLAY_STARTUP:{
307          im3d->vinfo->receiver[key]->receiver_mask |= RECEIVE_REDISPLAY_MASK ;
308       }
309       break ;
310 
311       case REDISPLAY_SHUTDOWN:{
312          im3d->vinfo->receiver[key]->receiver_mask &= (RECEIVE_ALL_MASK - RECEIVE_REDISPLAY_MASK) ;
313       }
314       break ;
315 
316       case FUNCDISPLAY_STARTUP:{
317          im3d->vinfo->receiver[key]->receiver_mask |= RECEIVE_FUNCDISPLAY_MASK ;
318       }
319       break ;
320 
321       case FUNCDISPLAY_SHUTDOWN:{
322          im3d->vinfo->receiver[key]->receiver_mask &= (RECEIVE_ALL_MASK - RECEIVE_FUNCDISPLAY_MASK) ;
323       }
324       break ;
325 
326       case OVERLAY_STARTUP:{
327          im3d->vinfo->receiver[key]->receiver_mask |= RECEIVE_OVERLAY_MASK ;
328       }
329       break ;
330 
331       case OVERLAY_SHUTDOWN:{
332          im3d->vinfo->receiver[key]->receiver_mask &= (RECEIVE_ALL_MASK - RECEIVE_OVERLAY_MASK) ;
333       }
334       break ;
335 
336       case TIMEINDEX_STARTUP:{
337          im3d->vinfo->receiver[key]->receiver_mask |= RECEIVE_TIMEINDEX_MASK ;
338       }
339       break ;
340 
341       case TIMEINDEX_SHUTDOWN:{
342          im3d->vinfo->receiver[key]->receiver_mask &= (RECEIVE_ALL_MASK - RECEIVE_TIMEINDEX_MASK) ;
343       }
344       break ;
345 
346       case EVERYTHING_SHUTDOWN:{
347          im3d->vinfo->receiver[key]->receiver_mask = 0 ;
348          AFNI_toggle_drawing( im3d ) ;
349       }
350       break ;
351 
352    } /* end of switch on codes */
353 
354    /* possibly remove this receiver, and maybe even all receivers */
355 
356    if( im3d->vinfo->receiver[key]->receiver_mask == 0 ){   /* receiving nothing at all? */
357       int ir , nn=0 ;
358 
359       if( im3d->vinfo->receiver[key]->receiver_funcname != NULL )
360         free( im3d->vinfo->receiver[key]->receiver_funcname ) ;
361 
362       free( im3d->vinfo->receiver[key] ) ;                 /* toss this one fer shur */
363       im3d->vinfo->receiver[key] = NULL ;
364 
365       for( ir=0 ; ir < im3d->vinfo->num_receiver ; ir++ )  /* see if any are left */
366          if( im3d->vinfo->receiver[ir] != NULL ) nn++ ;
367 
368       if( nn == 0 ) im3d->vinfo->num_receiver = 0 ;        /* if not, toss them all */
369    }
370 
371    RETURN(0) ;
372 }
373 
374 /*-------------------------------------------------------------------
375    Turn the drawing on or off for the given controller
376 ---------------------------------------------------------------------*/
377 
AFNI_toggle_drawing(Three_D_View * im3d)378 void AFNI_toggle_drawing( Three_D_View *im3d )
379 {
380    int turn_on = 0 ;
381 
382 ENTRY("AFNI_toggle_drawing") ;
383 
384    if( ! IM3D_OPEN(im3d) ) EXRETURN ;
385 
386    /* count up how many receivers want the drawing */
387 
388    if( im3d->vinfo->receiver != NULL ){
389       int ir ;
390       for( ir=0 ; ir < im3d->vinfo->num_receiver ; ir++ )
391          if( im3d->vinfo->receiver[ir] != NULL &&
392              (im3d->vinfo->receiver[ir]->receiver_mask & RECEIVE_DRAWING_MASK) )
393             turn_on++ ;
394    }
395    im3d->vinfo->drawing_enabled = (turn_on != 0) ;
396 
397    if( ! im3d->vinfo->drawing_enabled ){
398 
399    /*-- quench the flames --*/
400 
401       drive_MCW_imseq( im3d->s123 , isqDR_button2_disable , NULL ) ;
402       drive_MCW_imseq( im3d->s231 , isqDR_button2_disable , NULL ) ;
403       drive_MCW_imseq( im3d->s312 , isqDR_button2_disable , NULL ) ;
404 
405       drive_MCW_grapher( im3d->g123 , graDR_button2_disable , NULL ) ;
406       drive_MCW_grapher( im3d->g231 , graDR_button2_disable , NULL ) ;
407       drive_MCW_grapher( im3d->g312 , graDR_button2_disable , NULL ) ;
408 
409    } else {
410 
411    /*-- come on baby, light my fire --*/
412 
413       drive_MCW_imseq( im3d->s123 , isqDR_button2_enable , NULL ) ;
414       drive_MCW_imseq( im3d->s231 , isqDR_button2_enable , NULL ) ;
415       drive_MCW_imseq( im3d->s312 , isqDR_button2_enable , NULL ) ;
416 
417       if( im3d->vinfo->drawing_pixel > 0 ){
418          drive_MCW_imseq( im3d->s123, isqDR_button2_pixel,
419                           (XtPointer)im3d->vinfo->drawing_pixel ) ;
420          drive_MCW_imseq( im3d->s231, isqDR_button2_pixel,
421                           (XtPointer)im3d->vinfo->drawing_pixel ) ;
422          drive_MCW_imseq( im3d->s312, isqDR_button2_pixel,
423                           (XtPointer)im3d->vinfo->drawing_pixel ) ;
424       }
425 
426       drive_MCW_imseq( im3d->s123, isqDR_button2_mode,
427                        (XtPointer)ITOP(im3d->vinfo->drawing_mode) ) ;
428       drive_MCW_imseq( im3d->s231, isqDR_button2_mode,
429                        (XtPointer)ITOP(im3d->vinfo->drawing_mode) ) ;
430       drive_MCW_imseq( im3d->s312, isqDR_button2_mode,
431                        (XtPointer)ITOP(im3d->vinfo->drawing_mode) ) ;
432 
433       drive_MCW_grapher( im3d->g123 , graDR_button2_enable , NULL ) ;
434       drive_MCW_grapher( im3d->g231 , graDR_button2_enable , NULL ) ;
435       drive_MCW_grapher( im3d->g312 , graDR_button2_enable , NULL ) ;
436 
437    }
438 
439    EXRETURN ;
440 }
441 
442 /*-------------------------------------------------------------------
443    Send alteration message to all receivers
444    (they don't have to register for this information)
445 ---------------------------------------------------------------------*/
446 
AFNI_process_alteration(Three_D_View * im3d)447 void AFNI_process_alteration( Three_D_View *im3d )
448 {
449    int ir ;
450 
451 ENTRY("AFNI_process_alteration") ;
452 
453    if( !IM3D_VALID(im3d) || im3d->vinfo->receiver == NULL  ||
454                             im3d->vinfo->num_receiver == 0   ) EXRETURN ;
455 
456    for( ir=0 ; ir < im3d->vinfo->num_receiver ; ir++ ){
457       if( STAMPCHECK(im3d->vinfo->receiver[ir],RECEIVE_ALTERATION) ){
458 STATUS(im3d->vinfo->receiver[ir]->receiver_funcname) ;
459 #if 0
460          im3d->vinfo->receiver[ir]->receiver_func(
461                    RECEIVE_ALTERATION , 0 , NULL ,
462                    im3d->vinfo->receiver[ir]->receiver_data ) ;
463 #else
464          AFNI_CALL_VOID_4ARG( im3d->vinfo->receiver[ir]->receiver_func ,
465                               int,RECEIVE_ALTERATION , int,0 ,
466                               void *,NULL ,
467                               void *,im3d->vinfo->receiver[ir]->receiver_data ) ;
468 #endif
469          STAMPER(im3d->vinfo->receiver[ir],RECEIVE_ALTERATION) ;
470       }
471    }
472 
473    EXRETURN ;
474 }
475 
476 /*-------------------------------------------------------------------
477    Send drawing notices to interested receivers.
478    Really used to indicate that the values in a dataset have changed.
479 ---------------------------------------------------------------------*/
480 
AFNI_process_drawnotice(Three_D_View * im3d)481 void AFNI_process_drawnotice( Three_D_View *im3d )
482 {
483    int ir ;
484 
485 ENTRY("AFNI_process_drawnotice") ;
486 
487    if( !IM3D_VALID(im3d) || im3d->vinfo->receiver == NULL  ||
488                             im3d->vinfo->num_receiver == 0   ) EXRETURN ;
489 
490    for( ir=0 ; ir < im3d->vinfo->num_receiver ; ir++ ){
491 
492       if( STAMPCHECK(im3d->vinfo->receiver[ir],RECEIVE_DRAWNOTICE) &&
493           (im3d->vinfo->receiver[ir]->receiver_mask & RECEIVE_DRAWNOTICE_MASK) ){
494 
495 STATUS(im3d->vinfo->receiver[ir]->receiver_funcname) ;
496 #if 0
497          im3d->vinfo->receiver[ir]->receiver_func(
498                    RECEIVE_DRAWNOTICE , 0 , NULL ,
499                    im3d->vinfo->receiver[ir]->receiver_data ) ;
500 #else
501          AFNI_CALL_VOID_4ARG( im3d->vinfo->receiver[ir]->receiver_func ,
502                               int,RECEIVE_DRAWNOTICE , int,0 ,
503                               void *,NULL ,
504                               void *,im3d->vinfo->receiver[ir]->receiver_data ) ;
505 #endif
506          STAMPER(im3d->vinfo->receiver[ir],RECEIVE_DRAWNOTICE) ;
507       }
508    }
509 
510    EXRETURN ;
511 }
512 
513 /*-------------------------------------------------------------------
514    Send dset change notices to interested receivers
515 ---------------------------------------------------------------------*/
516 
AFNI_process_dsetchange(Three_D_View * im3d)517 void AFNI_process_dsetchange( Three_D_View *im3d )
518 {
519    int ir ;
520 
521 ENTRY("AFNI_process_dsetchange") ;
522 
523    if( !IM3D_VALID(im3d) || im3d->vinfo->receiver == NULL  ||
524                             im3d->vinfo->num_receiver == 0   ) EXRETURN ;
525 
526    for( ir=0 ; ir < im3d->vinfo->num_receiver ; ir++ ){
527 
528       if( STAMPCHECK(im3d->vinfo->receiver[ir],RECEIVE_DSETCHANGE) &&
529           (im3d->vinfo->receiver[ir]->receiver_mask & RECEIVE_DSETCHANGE_MASK) ){
530 
531 STATUS(im3d->vinfo->receiver[ir]->receiver_funcname) ;
532 #if 0
533          im3d->vinfo->receiver[ir]->receiver_func(
534                    RECEIVE_DSETCHANGE , 0 , NULL ,
535                    im3d->vinfo->receiver[ir]->receiver_data ) ;
536 #else
537          AFNI_CALL_VOID_4ARG( im3d->vinfo->receiver[ir]->receiver_func ,
538                               int,RECEIVE_DSETCHANGE , int,0 ,
539                               void *,NULL ,
540                               void *,im3d->vinfo->receiver[ir]->receiver_data ) ;
541 #endif
542          STAMPER(im3d->vinfo->receiver[ir],RECEIVE_DSETCHANGE) ;
543       }
544    }
545 
546    EXRETURN ;
547 }
548 
549 /*-------------------------------------------------------------------
550    Send new (i,j,k) coordinates to all receivers that care
551 ---------------------------------------------------------------------*/
552 
AFNI_process_viewpoint(Three_D_View * im3d)553 void AFNI_process_viewpoint( Three_D_View *im3d )
554 {
555    int ir , ijk[3] ;
556 
557 ENTRY("AFNI_process_viewpoint") ;
558 
559    if( !IM3D_VALID(im3d) || im3d->vinfo->receiver == NULL  ||
560                             im3d->vinfo->num_receiver == 0   ) EXRETURN ;
561 
562 #if 0
563 if( AFNI_yesenv("BOBCOX") ){
564   INFO_message("AFNI_process_viewpoint"); DBG_traceback();
565 }
566 #endif
567 
568    ijk[0] = im3d->vinfo->i1 ;
569    ijk[1] = im3d->vinfo->j2 ;
570    ijk[2] = im3d->vinfo->k3 ;
571 
572    for( ir=0 ; ir < im3d->vinfo->num_receiver ; ir++ ){
573       if( STAMPCHECK(im3d->vinfo->receiver[ir],RECEIVE_VIEWPOINT) &&
574           (im3d->vinfo->receiver[ir]->receiver_mask & RECEIVE_VIEWPOINT_MASK) ){
575 
576 #if 0
577 if( AFNI_yesenv("BOBCOX") ) STAMPSHOW(ir,im3d->vinfo->receiver[ir],RECEIVE_FUNCDISPLAY) ;
578 #endif
579 
580 STATUS(im3d->vinfo->receiver[ir]->receiver_funcname) ;
581 #if 0
582          im3d->vinfo->receiver[ir]->receiver_func(
583                    RECEIVE_VIEWPOINT , 3 , ijk ,
584                    im3d->vinfo->receiver[ir]->receiver_data ) ;
585 #else
586          AFNI_CALL_VOID_4ARG( im3d->vinfo->receiver[ir]->receiver_func ,
587                               int,RECEIVE_VIEWPOINT , int,3 ,
588                               void *,ijk ,
589                               void *,im3d->vinfo->receiver[ir]->receiver_data ) ;
590 #endif
591          STAMPER(im3d->vinfo->receiver[ir],RECEIVE_VIEWPOINT) ;
592 
593 #if 0
594 if( AFNI_yesenv("BOBCOX") ) STAMPSHOW(ir,im3d->vinfo->receiver[ir],RECEIVE_VIEWPOINT) ;
595 #endif
596       }
597    }
598 
599    EXRETURN ;
600 }
601 
602 /*-------------------------------------------------------------------*/
603 /*! Send time index change notice to receivers that care [29 Jan 2003]
604 ---------------------------------------------------------------------*/
605 
AFNI_process_timeindex(Three_D_View * im3d)606 void AFNI_process_timeindex( Three_D_View *im3d )
607 {
608    int ir ;
609 
610 ENTRY("AFNI_process_timeindex") ;
611 
612    if( !IM3D_VALID(im3d) || im3d->vinfo->receiver == NULL  ||
613                             im3d->vinfo->num_receiver == 0   ) EXRETURN ;
614 
615    for( ir=0 ; ir < im3d->vinfo->num_receiver ; ir++ ){
616       if( STAMPCHECK(im3d->vinfo->receiver[ir],RECEIVE_TIMEINDEX) &&
617           (im3d->vinfo->receiver[ir]->receiver_mask & RECEIVE_TIMEINDEX_MASK) ){
618 
619 STATUS(im3d->vinfo->receiver[ir]->receiver_funcname) ;
620 #if 0
621          im3d->vinfo->receiver[ir]->receiver_func(
622                    RECEIVE_TIMEINDEX , 0 , NULL ,
623                    im3d->vinfo->receiver[ir]->receiver_data ) ;
624 #else
625          AFNI_CALL_VOID_4ARG( im3d->vinfo->receiver[ir]->receiver_func ,
626                               int,RECEIVE_TIMEINDEX , int,0 ,
627                               void *,NULL ,
628                               void *,im3d->vinfo->receiver[ir]->receiver_data ) ;
629 #endif
630          STAMPER(im3d->vinfo->receiver[ir],RECEIVE_TIMEINDEX) ;
631       }
632    }
633 
634    EXRETURN ;
635 }
636 
637 /*-------------------------------------------------------------------*/
638 /*! Send redisplay notification to receivers that care [04 Mar 2002].
639 ---------------------------------------------------------------------*/
640 
AFNI_process_redisplay(Three_D_View * im3d)641 void AFNI_process_redisplay( Three_D_View *im3d )
642 {
643    int ir ;
644 
645 ENTRY("AFNI_process_redisplay") ;
646 
647    if( !IM3D_VALID(im3d) || im3d->vinfo->receiver == NULL  ||
648                             im3d->vinfo->num_receiver == 0   ) EXRETURN ;
649 
650    for( ir=0 ; ir < im3d->vinfo->num_receiver ; ir++ ){
651       if( STAMPCHECK(im3d->vinfo->receiver[ir],RECEIVE_REDISPLAY) &&
652           (im3d->vinfo->receiver[ir]->receiver_mask & RECEIVE_REDISPLAY_MASK) ){
653 
654 STATUS(im3d->vinfo->receiver[ir]->receiver_funcname) ;
655 #if 0
656          im3d->vinfo->receiver[ir]->receiver_func(
657                    RECEIVE_REDISPLAY , 0 , NULL ,
658                    im3d->vinfo->receiver[ir]->receiver_data ) ;
659 #else
660          AFNI_CALL_VOID_4ARG( im3d->vinfo->receiver[ir]->receiver_func ,
661                               int,RECEIVE_REDISPLAY , int,0 ,
662                               void *,NULL ,
663                               void *,im3d->vinfo->receiver[ir]->receiver_data ) ;
664 #endif
665          STAMPER(im3d->vinfo->receiver[ir],RECEIVE_REDISPLAY) ;
666       }
667    }
668 
669    EXRETURN ;
670 }
671 
672 /*-------------------------------------------------------------------*/
673 /*! Send funcdisplay notification to receivers that care [05 Mar 2002].
674 ---------------------------------------------------------------------*/
675 
AFNI_process_funcdisplay(Three_D_View * im3d)676 void AFNI_process_funcdisplay( Three_D_View *im3d )
677 {
678    int ir ;
679 
680 ENTRY("AFNI_process_funcdisplay") ;
681 
682    if( !IM3D_VALID(im3d) || im3d->vinfo->receiver == NULL  ||
683                             im3d->vinfo->num_receiver == 0   ) EXRETURN ;
684 
685 #if 0
686 if( AFNI_yesenv("BOBCOX") ){
687   INFO_message("AFNI_process_funcdisplay"); DBG_traceback();
688 }
689 #endif
690 
691    for( ir=0 ; ir < im3d->vinfo->num_receiver ; ir++ ){
692       if( STAMPCHECK(im3d->vinfo->receiver[ir],RECEIVE_FUNCDISPLAY) &&
693           (im3d->vinfo->receiver[ir]->receiver_mask & RECEIVE_FUNCDISPLAY_MASK) ){
694 
695 #if 0
696 if( AFNI_yesenv("BOBCOX") ) STAMPSHOW(ir,im3d->vinfo->receiver[ir],RECEIVE_FUNCDISPLAY) ;
697 #endif
698 
699 STATUS(im3d->vinfo->receiver[ir]->receiver_funcname) ;
700 #if 0
701          im3d->vinfo->receiver[ir]->receiver_func(
702                    RECEIVE_FUNCDISPLAY , 0 , NULL ,
703                    im3d->vinfo->receiver[ir]->receiver_data ) ;
704 #else
705          AFNI_CALL_VOID_4ARG( im3d->vinfo->receiver[ir]->receiver_func ,
706                               int,RECEIVE_FUNCDISPLAY , int,0 ,
707                               void *,NULL ,
708                               void *,im3d->vinfo->receiver[ir]->receiver_data ) ;
709 #endif
710          STAMPER(im3d->vinfo->receiver[ir],RECEIVE_FUNCDISPLAY) ;
711 
712 #if 0
713 if( AFNI_yesenv("BOBCOX") ) STAMPSHOW(ir,im3d->vinfo->receiver[ir],RECEIVE_FUNCDISPLAY) ;
714 #endif
715       }
716    }
717 
718    EXRETURN ;
719 }
720 
721 /*-------------------------------------------------------------------*/
722 /*! Process drawn points:
723     - npts  = number of points sent in
724     - mode  = type of points to follow:
725               - PLANAR_MODE + zz ==> axis zz is fixed, for zz=1,2,3
726               - SINGLE_MODE + zz ==> one point only, clicked in a
727                                       window with zz fixed
728               - THREED_MODE      ==> points are in 3D (not planar)
729                                       (not currently possible)
730               - UNDO_MODE        ==> undo last drawing action
731               - INCVAL_MODE      ==> add 1 to drawing value
732               - DECVAL_MODE      ==> subtract 1 from drawing value
733 
734     - xd[i] = x index of point i, for i=0..npts-1
735     - yd[i] = y index of point i, for i=0..npts-1
736     - zd[i] = z index of point i, for i=0..npts-1
737 
738    These indices are with respect to the dataset brick axes.
739 ---------------------------------------------------------------------*/
740 
AFNI_process_drawing(Three_D_View * im3d,int mode,int npts,int * xd,int * yd,int * zd)741 void AFNI_process_drawing( Three_D_View *im3d , int mode ,
742                            int npts , int *xd , int *yd , int *zd )
743 {
744    int ii , nn , ir , nsent ;
745    int *vp[4] , *xn=NULL , *yn=NULL , *zn=NULL ;
746 
747 ENTRY("AFNI_process_drawing") ;
748 
749    if( !IM3D_VALID(im3d) || im3d->vinfo->receiver == NULL  ||
750                             im3d->vinfo->num_receiver == 0 ||
751        npts < 0          || im3d->vinfo->drawing_enabled == 0 ) EXRETURN ;
752 
753 if(PRINT_TRACING){
754   char str[256] ; sprintf(str,"received %d points",npts) ; STATUS(str) ;
755 }
756 
757    /*-- if no further treatment is needed,
758         just flag input data to be set to receiver --*/
759 
760    if( im3d->vinfo->drawing_mode == DRAWING_POINTS ||
761        im3d->vinfo->drawing_mode == DRAWING_NODRAW || npts <= 1 ){
762 
763       xn = xd ; yn = yd ; zn = zd ; nn = npts ;
764    }
765 
766    /*-- must fill in the lines:
767         create arrays xn, yn, zn of length nn --*/
768 
769    else if( im3d->vinfo->drawing_mode == DRAWING_LINES ){
770 
771       AFNI_3d_linefill( npts , xd,yd,zd , &nn , &xn , &yn , &zn ) ;
772    }
773 
774    /*-- must fill in the polygon --*/
775 
776    else if( im3d->vinfo->drawing_mode == DRAWING_FILL ){
777 
778       /* this just fills the lines like above --
779          need to write a real polygon filling routine? */
780 
781       AFNI_3d_linefill( npts , xd,yd,zd , &nn , &xn , &yn , &zn ) ;
782    }
783 
784    /*-- send data to receivers that want it --*/
785 
786 #if 0
787 fprintf(stderr,"Sending %d points to receiver\n",nn) ;
788 #endif
789 
790    vp[3] = &mode ;                        /* how the points are arranged */
791 
792    vp[0] = xn ; vp[1] = yn ; vp[2] = zn ;
793 
794    for( nsent=ir=0 ; ir < im3d->vinfo->num_receiver ; ir++ ){
795 
796       if( STAMPCHECK(im3d->vinfo->receiver[ir],RECEIVE_POINTS) &&
797           (im3d->vinfo->receiver[ir]->receiver_mask & RECEIVE_DRAWING_MASK) ){
798 
799 STATUS(im3d->vinfo->receiver[ir]->receiver_funcname) ;
800 #if 0
801          im3d->vinfo->receiver[ir]->receiver_func(
802                    RECEIVE_POINTS , nn ,
803                    (void *) vp , im3d->vinfo->receiver[ir]->receiver_data ) ;
804 #else
805          AFNI_CALL_VOID_4ARG( im3d->vinfo->receiver[ir]->receiver_func ,
806                               int,RECEIVE_POINTS , int,nn ,
807                               void *,vp ,
808                               void *,im3d->vinfo->receiver[ir]->receiver_data ) ;
809 #endif
810          nsent++ ;
811          STAMPER(im3d->vinfo->receiver[ir],RECEIVE_POINTS) ;
812       }
813    }
814 
815    /* 30 Mar 1999: also send DRAWNOTICE to receivers that like this stuff */
816 
817    if( nsent > 0 ) AFNI_process_drawnotice( im3d ) ;
818 
819    /*-- free any created arrays --*/
820 
821    if( xn != xd ){ free(xn); free(yn); free(zn); }
822    EXRETURN ;
823 }
824 
825 /*--------------------------------------------------------------------
826    3D line filler-inner -- quick and dirty.
827    The output arrays (*xout, *yout, *zout) should be freed when
828    their usefulness is over.
829 ----------------------------------------------------------------------*/
830 
AFNI_3d_linefill(int nin,int * xin,int * yin,int * zin,int * nout,int ** xout,int ** yout,int ** zout)831 void AFNI_3d_linefill( int   nin  , int *  xin  , int *  yin  , int *  zin ,
832                        int * nout , int ** xout , int ** yout , int ** zout )
833 {
834    int * xut , * yut , * zut ;
835    int   nut , iin , jout , nall ;
836    int   x1,y1,z1 , x2,y2,z2 , dx,dy,dz , adx,ady,adz , xlast,ylast,zlast ;
837    float fdxyz , fdx,fdy,fdz , fx,fy,fz ;
838 
839 ENTRY("AFNI_3d_linefill") ;
840 
841    /* sanity check */
842 
843    if( nin <= 0 || xin == NULL || yin == NULL || zin == NULL ){
844       *nout = 0 ; *xout = *yout = *zout = NULL ; EXRETURN ;
845    }
846 
847    /* trivial case */
848 
849    if( nin == 1 ){
850       nut = 1 ;                                             *nout = nut ;
851       xut = (int *) malloc(sizeof(int)) ; xut[0] = xin[0] ; *xout = xut ;
852       yut = (int *) malloc(sizeof(int)) ; yut[0] = yin[0] ; *yout = yut ;
853       zut = (int *) malloc(sizeof(int)) ; zut[0] = zin[0] ; *zout = zut ;
854       EXRETURN ;
855    }
856 
857    /* setup to scan through lines */
858 
859    nall = nin ;
860    xut  = (int *) malloc( sizeof(int) * nall ) ;
861    yut  = (int *) malloc( sizeof(int) * nall ) ;
862    zut  = (int *) malloc( sizeof(int) * nall ) ;
863    nut  = 0 ;
864 
865 #undef  ADDPT
866 #define ADDPT(i,j,k)                                          \
867   do{ if( nut == nall ){                                      \
868          nall += 128 ;                                        \
869          xut = (int *) realloc( xut , sizeof(int) * nall ) ;  \
870          yut = (int *) realloc( yut , sizeof(int) * nall ) ;  \
871          zut = (int *) realloc( zut , sizeof(int) * nall ) ;  \
872       }                                                       \
873       xut[nut] = xlast = (i) ;                                \
874       yut[nut] = ylast = (j) ;                                \
875       zut[nut] = zlast = (k) ; nut++ ; } while(0)
876 
877    /* draw line from point #iin to #iin+1 */
878 
879    x2 = xin[0] ; y2 = yin[0] ; z2 = zin[0] ;
880    for( iin=0 ; iin < nin-1 ; iin++ ){
881       x1  = x2         ; y1  = y2         ; z1  = z2 ;
882       x2  = xin[iin+1] ; y2  = yin[iin+1] ; z2  = zin[iin+1] ;
883       dx  = x2 - x1    ; dy  = y2 - y1    ; dz  = z2 - z1 ;
884       adx = abs(dx)    ; ady = abs(dy)    ; adz = abs(dz) ;
885 
886       /* add start point to list */
887 
888       ADDPT(x1,y1,z1) ;
889 
890       /* special case: neighbors ==> skip to next line */
891 
892       if( adx <= 1 && ady <= 1 && adz <= 1 ) continue ;
893 
894       /* OK, we have to do work (moan) */
895 
896 #define SFRAC 0.495
897 
898       fdxyz = adx + ady + adz ;                /* Manhattan distance */
899       fdx   = SFRAC * dx / fdxyz ;             /* steps */
900       fdy   = SFRAC * dy / fdxyz ;
901       fdz   = SFRAC * dz / fdxyz ;
902 
903       /* step thru in small increments,
904          adding new integer points, and stopping at line's end */
905 
906 #if 0
907 fprintf(stderr,"linefill: from %d %d %d to %d %d %d\n",
908         x1,y1,z1 , x2,y2,z2 ) ;
909 #endif
910 
911       fx = x1+fdx+0.499 ; fy = y1+fdy+0.499 ; fz = z1+fdz+0.499 ;
912       do {
913          fx = fx + fdx ; fy = fy + fdy ; fz = fz + fdz ;
914          x1 = (int) fx ; y1 = (int) fy ; z1 = (int) fz ;
915 
916 #if 0
917 fprintf(stderr,"   at %d %d %d\n",x1,y1,z1) ;
918 #endif
919 
920          if( x1 == x2    && y1 == y2    && z1 == z2    ) break ;
921 
922          if( x1 != xlast || y1 != ylast || z1 != zlast ) ADDPT(x1,y1,z1) ;
923       } while(1) ;
924 
925    } /* end of loop over lines */
926 
927    ADDPT(x2,y2,z2) ;  /* add last point */
928 
929    *nout = nut ; *xout = xut ; *yout = yut ; *zout = zut ;
930    EXRETURN ;
931 }
932 
933