1 #include "coxplot.h"
2 #include <Xm/XmAll.h>
3 #include <ctype.h>
4 #include "mcw_malloc.h" /* ZSS: Needed because SUMA_plot.c does
5 allocate some pointers freed here Jan 09 */
6 #include "Amalloc.h"
7
8 /*****************************************************************************
9 This software is copyrighted and owned by the Medical College of Wisconsin.
10 See the file README.Copyright for details.
11 ******************************************************************************/
12
13 static char print_command[256] = "\0" ;
14 static char *redcolor = NULL ;
15 static char wintitle[128] = {"AFNI"}; /* ZSS Oct 7 2009 */
16
set_wintitle_memplot(char * s)17 void set_wintitle_memplot( char *s ) /* ZSS Oct 7 2009 */
18 {
19 if (s) {
20 snprintf(wintitle, 125*sizeof(char), "%s", s);
21 } else {
22 sprintf(wintitle,"AFNI");
23 }
24 return;
25 }
26
27 #ifndef LABEL_ARG
28 #define LABEL_ARG(str) \
29 XtVaTypedArg , XmNlabelString , XmRString , (str) , strlen(str)+1
30 #endif
31
32
33
34 /*--------------------------------------------------------------------------*/
35 #undef STRING_HAS_SUFFIX
36 #define STRING_HAS_SUFFIX(ss,suf) \
37 ((ss != NULL) && (suf != NULL) && \
38 (strlen(ss) >= strlen(suf)) && \
39 (strcmp(ss+strlen(ss)-strlen(suf),suf) == 0))
40
41 typedef void vpfunc(char *,MEM_plotdata *) ;
42 typedef struct { char *suf ; vpfunc *fun ; } saver_pair ;
43 static int num_spair = 0 ;
44 static saver_pair *spair = NULL ;
45
memplot_topshell_setsaver(char * suf,void (* fun)(char *,MEM_plotdata *))46 void memplot_topshell_setsaver( char *suf, void (*fun)(char *,MEM_plotdata *) )
47 {
48 int nn ;
49
50 if( suf == NULL || *suf == '\0' || fun == NULL ) return ;
51 for( nn=0 ; nn < num_spair ; nn++ )
52 if( strcmp(suf,spair[nn].suf) == 0 ) return ;
53
54 nn = num_spair + 1 ;
55 spair = (saver_pair *)realloc( (void *)spair , sizeof(saver_pair)*nn ) ;
56 spair[num_spair].suf = strdup(suf) ;
57 spair[num_spair].fun = fun ;
58 num_spair = nn ;
59 return ;
60 }
61
62 /*==========================================================================
63 Callback routines for memplot_to_topshell
64 ============================================================================*/
65
66 /*--------------------------------------------------------------------------*/
67
beep_CB(Widget w,XtPointer cd,XtPointer cb)68 static void beep_CB( Widget w , XtPointer cd , XtPointer cb )
69 {
70 char * str = (char *) cd ;
71
72 if( w != NULL ) XBell(XtDisplay(w),100) ;
73 if( str != NULL && str[0] != '\0' ) fprintf(stderr,"%s\a\n",str) ;
74 return ;
75 }
76
77 /*--------------------------------------------------------------------------
78 Save plot to a PostScript file
79 ----------------------------------------------------------------------------*/
80
81 /****** cancellation of a print request ******/
82
pscancel_CB(Widget w,XtPointer cd,XtPointer cb)83 static void pscancel_CB( Widget w , XtPointer cd , XtPointer cb )
84 {
85 MEM_topshell_data *mpcb = (MEM_topshell_data *) cd ;
86
87 if( mpcb == NULL || ! MTD_VALID(mpcb) ) return ;
88
89 if( mpcb->dial != NULL ) XtDestroyWidget( mpcb->dial ) ;
90 mpcb->dial = mpcb->wtf = NULL ;
91 return ;
92 }
93
94 /****** finalization of a print request ******/
95
psfinalize_CB(Widget w,XtPointer cd,XtPointer cb)96 static void psfinalize_CB( Widget w , XtPointer cd , XtPointer cb )
97 {
98 MEM_topshell_data *mpcb = (MEM_topshell_data *) cd ;
99 char *text , fname[128] ;
100 int ii , ll ;
101
102 if( mpcb == NULL || ! MTD_VALID(mpcb) ) return ;
103
104 if( mpcb->dial == NULL ){ XBell(XtDisplay(w),100) ; return ; }
105
106 text = XmTextFieldGetString( mpcb->wtf ) ;
107 if( text == NULL || text[0] == '\0' ){ XBell(XtDisplay(w),100) ; return ; }
108
109 ll = strlen(text) ;
110 for( ii=0 ; ii < ll ; ii++ ){
111 if( iscntrl(text[ii]) || isspace(text[ii]) ||
112 text[ii] == '/' || text[ii] == ';' ||
113 text[ii] == '*' || text[ii] == '?' ||
114 text[ii] == '&' || text[ii] == '|' ||
115 text[ii] == '"' || text[ii] == '>' ||
116 text[ii] == '<' || text[ii] == '\'' ||
117 text[ii] == '[' || text[ii] == ']' ){
118
119 XBell(XtDisplay(w),100) ; return ;
120 }
121 }
122
123 strcpy(fname,text) ;
124
125 for( ii=0 ; ii < num_spair ; ii++ ){ /* 05 Dec 2007 */
126 if( STRING_HAS_SUFFIX(fname,spair[ii].suf) ){
127 spair[ii].fun( fname , mpcb->mp ) ;
128 XtDestroyWidget( mpcb->dial ) ; mpcb->dial = mpcb->wtf = NULL ;
129 return ;
130 }
131 }
132
133 if( !STRING_HAS_SUFFIX(text,"ps") ) strcat(fname,".ps") ;
134
135 memplot_to_postscript( fname , mpcb->mp ) ;
136
137 XtDestroyWidget( mpcb->dial ) ;
138 mpcb->dial = mpcb->wtf = NULL ;
139 return ;
140 }
141
142 /****** initiation of a print request ******/
143
pm_psfile_CB(Widget w,XtPointer cd,XtPointer cb)144 void pm_psfile_CB( Widget w , XtPointer cd , XtPointer cb )
145 {
146 MEM_topshell_data * mpcb = (MEM_topshell_data *) cd ;
147 Widget wpop , wrc , wlab , wtf , form , but0 , but1 ;
148 int ibut = 0 ;
149 Position xx,yy ;
150
151 if( mpcb == NULL || ! MTD_VALID(mpcb) ) return ;
152
153 if( mpcb->dial != NULL ){ XBell(XtDisplay(w),100) ; return ; }
154
155 mpcb->dial = wpop = XtVaCreatePopupShell(
156 "AFNI" , xmDialogShellWidgetClass , mpcb->top ,
157 XmNtraversalOn , False ,
158 XmNinitialResourcesPersistent , False ,
159 NULL ) ;
160
161 XtVaSetValues( wpop ,
162 XmNmwmDecorations , MWM_DECOR_BORDER ,
163 XmNmwmFunctions , MWM_FUNC_MOVE ,
164 NULL ) ;
165
166 wrc = XtVaCreateWidget(
167 "menu" , xmRowColumnWidgetClass , wpop ,
168 XmNpacking , XmPACK_TIGHT ,
169 XmNorientation , XmVERTICAL ,
170 XmNtraversalOn , False ,
171 XmNinitialResourcesPersistent , False ,
172 NULL ) ;
173
174 wlab = XtVaCreateManagedWidget(
175 "menu" , xmLabelWidgetClass , wrc ,
176 LABEL_ARG("PostScript filename:\n[[or .jpg or .png ]]") ,
177 XmNinitialResourcesPersistent , False ,
178 NULL ) ;
179
180 mpcb->wtf = wtf = XtVaCreateManagedWidget(
181 "menu" , xmTextFieldWidgetClass , wrc ,
182 XmNcolumns , 20 ,
183 XmNeditable , True ,
184 XmNmaxLength , 32 ,
185 XmNresizeWidth , False ,
186 XmNmarginHeight , 1 ,
187 XmNmarginWidth , 1 ,
188 XmNcursorPositionVisible , True ,
189 XmNblinkRate , 0 ,
190 XmNautoShowCursorPosition , True ,
191 XmNinitialResourcesPersistent , False ,
192 XmNtraversalOn , False ,
193 NULL ) ;
194 XtAddCallback( wtf, XmNactivateCallback, psfinalize_CB, cd ) ; /* return key */
195
196 #undef TIG
197 #undef NBUT
198 #define TIG 20
199 #define NBUT 2
200
201 form = XtVaCreateWidget( "menu" , xmFormWidgetClass , wrc ,
202 XmNborderWidth , 0 ,
203 XmNfractionBase , TIG*NBUT - 1 ,
204 XmNinitialResourcesPersistent , False ,
205 NULL ) ;
206
207 ibut = 0 ;
208 but0 = XtVaCreateManagedWidget(
209 "menu" , xmPushButtonWidgetClass , form ,
210 LABEL_ARG("Cancel") ,
211 XmNtopAttachment , XmATTACH_FORM ,
212
213 XmNleftAttachment ,
214 (ibut!=0) ? XmATTACH_POSITION : XmATTACH_FORM ,
215 XmNleftPosition , ibut*TIG ,
216
217 XmNrightAttachment ,
218 (ibut==NBUT-1) ? XmATTACH_FORM : XmATTACH_POSITION ,
219 XmNrightPosition , ibut*TIG + (TIG-1) ,
220
221 XmNrecomputeSize , False ,
222 XmNtraversalOn , False ,
223 XmNinitialResourcesPersistent , False ,
224 NULL ) ;
225 XtAddCallback( but0 , XmNactivateCallback , pscancel_CB , cd ) ;
226
227
228 if( redcolor == NULL ){ HOTCOLOR(form,redcolor) ; }
229 ibut++ ;
230 but1 = XtVaCreateManagedWidget(
231 "menu" , xmPushButtonWidgetClass , form ,
232 LABEL_ARG("Save") ,
233 #if 1
234 BGCOLOR_ARG(redcolor) ,
235 #endif
236
237 XmNtopAttachment , XmATTACH_FORM ,
238
239 XmNleftAttachment ,
240 (ibut!=0) ? XmATTACH_POSITION : XmATTACH_FORM ,
241 XmNleftPosition , ibut*TIG ,
242
243 XmNrightAttachment ,
244 (ibut==NBUT-1) ? XmATTACH_FORM : XmATTACH_POSITION ,
245 XmNrightPosition , ibut*TIG + (TIG-1) ,
246
247 XmNrecomputeSize , False ,
248 XmNtraversalOn , False ,
249 XmNinitialResourcesPersistent , False ,
250 NULL ) ;
251 XtAddCallback( but1 , XmNactivateCallback , psfinalize_CB , cd ) ;
252
253 XtTranslateCoords( mpcb->top , 15,15 , &xx , &yy ) ;
254 XtVaSetValues( wpop , XmNx , (int) xx , XmNy , (int) yy , NULL ) ;
255
256 XtManageChild( form ) ;
257 XtManageChild( wrc ) ;
258 XtPopup( wpop , XtGrabNone ) ;
259 return ;
260 }
261
262 /*--------------------------------------------------------------------------
263 Print plot to a PostScript printer (if possible)
264 ----------------------------------------------------------------------------*/
265
pm_psprint_CB(Widget w,XtPointer cd,XtPointer cb)266 void pm_psprint_CB( Widget w , XtPointer cd , XtPointer cb )
267 {
268 MEM_topshell_data *mpcb = (MEM_topshell_data *) cd ;
269 MEM_plotdata *mp ;
270
271 if( mpcb == NULL ) return ;
272 mp = mpcb->mp ; if( mp == NULL ) return ;
273 memplot_to_postscript( print_command , mp ) ;
274 return ;
275 }
276
277 /*--------------------------------------------------------------------------
278 Close plot window
279 ----------------------------------------------------------------------------*/
280
pm_donebut_CB(Widget w,XtPointer cd,XtPointer cb)281 void pm_donebut_CB( Widget w , XtPointer cd , XtPointer cb )
282 {
283 MEM_topshell_data * mpcb = (MEM_topshell_data *) cd ;
284 if( mpcb == NULL || ! MTD_VALID(mpcb) ) return ;
285
286 mpcb->valid = 0 ;
287
288 if( mpcb->killfunc != NULL )
289 #if 0
290 mpcb->killfunc( mpcb ) ;
291 #else
292 AFNI_CALL_VOID_1ARG( mpcb->killfunc , MEM_topshell_data * , mpcb ) ;
293 #endif
294 if( mpcb->dial != NULL ) XtDestroyWidget( mpcb->dial ) ;
295 #ifdef HAVE_XDBE
296 if( mpcb->have_xdbe )
297 XdbeDeallocateBackBufferName( XtDisplay(mpcb->top) , mpcb->buf_xdbe ) ;
298 #endif
299 XtDestroyWidget( mpcb->top ) ;
300 delete_memplot( mpcb->mp ) ;
301 free(mpcb) ;
302
303 return ;
304 }
305
306 /*--------------------------------------------------------------------------
307 Draw plot window
308 ----------------------------------------------------------------------------*/
309
pm_expose_CB(Widget w,XtPointer cd,XtPointer cb)310 void pm_expose_CB( Widget w , XtPointer cd , XtPointer cb )
311 {
312 XmDrawingAreaCallbackStruct * cbs = (XmDrawingAreaCallbackStruct *) cb ;
313 MEM_topshell_data * mpcb = (MEM_topshell_data *) cd ;
314 MEM_plotdata * mp ;
315 XEvent evjunk ;
316 Display * dpy = XtDisplay(w) ;
317 Window win = XtWindow(w) ;
318 Drawable dw = win ; /* draw into this */
319
320 if( win == (Window) 0 ) return ; /* no window yet? */
321 if( mpcb == NULL ) return ;
322 mp = mpcb->mp ; if( mp == NULL ) return ;
323
324 if( cbs != NULL ){
325 XExposeEvent * ev = (XExposeEvent *) cbs->event ;
326 if( ev->count > 0 ) return ;
327 }
328
329 #ifdef HAVE_XDBE
330 if( use_xdbe > 0 && mpcb->have_xdbe == 0 && get_XDBE_suspension(0)==0 ){
331 XdbeSwapInfo info_xdbe ;
332
333 mpcb->buf_xdbe = XdbeAllocateBackBufferName( dpy,win,XdbeBackground );
334 mpcb->have_xdbe = 1 ;
335
336 set_X11_background( dpy , win , 255,255,255 ) ;
337 info_xdbe.swap_window = win ;
338 info_xdbe.swap_action = XdbeBackground ;
339 XdbeSwapBuffers( dpy , &info_xdbe , 1 ) ;
340 }
341
342 if( mpcb->have_xdbe ) dw = mpcb->buf_xdbe ; /* draw into this */
343 #endif
344
345 set_X11_background( dpy , win , 255,255,255 ) ;
346 if( dw == win ) XClearWindow( dpy , win ) ;
347 memplot_to_X11_sef( dpy , dw , mp , 0,0,MEMPLOT_FREE_ASPECT ) ;
348
349 #ifdef HAVE_XDBE
350 if( mpcb->have_xdbe ){
351 XdbeSwapInfo info_xdbe ;
352 info_xdbe.swap_window = win ;
353 info_xdbe.swap_action = XdbeBackground ;
354 XdbeSwapBuffers( dpy , &info_xdbe , 1 ) ;
355 }
356 #endif
357
358 /* skip any future pending Expose events */
359
360 while( XCheckWindowEvent(dpy, win ,
361 ExposureMask|StructureNotifyMask,&evjunk) ) ;
362 return ;
363 }
364
redraw_topshell(MEM_topshell_data * mpcb)365 void redraw_topshell( MEM_topshell_data * mpcb )
366 {
367 if( mpcb == NULL ) return ;
368 pm_expose_CB( mpcb->drawing , mpcb , NULL ) ;
369 return ;
370 }
371
372 /*--------------------------------------------------------------------------
373 Redraw plot window after a resize notice
374 ----------------------------------------------------------------------------*/
375
pm_resize_CB(Widget w,XtPointer cd,XtPointer cb)376 void pm_resize_CB( Widget w , XtPointer cd , XtPointer cb )
377 {
378 pm_expose_CB( w , cd , NULL ) ;
379 return ;
380 }
381
382 /*--------------------------------------------------------------------------
383 Handle input to the drawing area (key or button press) - 06 Aug 2001
384 ----------------------------------------------------------------------------*/
385
pm_input_CB(Widget w,XtPointer cd,XtPointer cb)386 void pm_input_CB( Widget w , XtPointer cd , XtPointer cb )
387 {
388 MEM_topshell_data * mpcb = (MEM_topshell_data *) cd ;
389 XmDrawingAreaCallbackStruct * cbs = (XmDrawingAreaCallbackStruct *) cb ;
390
391 if( mpcb == NULL || ! MTD_VALID(mpcb) ) return ; /* bad */
392 if( cbs == NULL || cbs->reason != XmCR_INPUT ) return ; /* real bad */
393
394 switch( cbs->event->type ){
395
396 default: break ;
397
398 /*----- take key press -----*/
399
400 case KeyPress:{
401 XKeyEvent * event = (XKeyEvent *) cbs->event ;
402 char buf[32] ;
403 KeySym ks ;
404
405 buf[0] = '\0' ;
406 XLookupString( event , buf , 32 , &ks , NULL ) ;
407
408 switch( buf[0] ){
409 default: break;
410 case 'Q':
411 case 'q':
412 pm_donebut_CB( NULL , (XtPointer) mpcb , NULL ) ;
413 break ;
414 }
415 break ;
416 }
417 break ;
418 }
419
420 return ;
421 }
422
423 /*------------------------------------------------------------------
424 External killer, for use by user routines
425 --------------------------------------------------------------------*/
426
plotkill_topshell(MEM_topshell_data * mpcb)427 void plotkill_topshell( MEM_topshell_data * mpcb )
428 {
429 if( mpcb == NULL || ! MTD_VALID(mpcb) ) return ;
430
431 pm_donebut_CB( NULL , (XtPointer) mpcb , NULL ) ;
432 return ;
433 }
434
435 /*---------------------------------------------------------------------------*/
436
pm_decode_geom(char * geom,int * ww,int * hh,int * xx,int * yy)437 void pm_decode_geom( char * geom , int *ww, int *hh , int *xx, int *yy )
438 {
439 int has_x , has_plus ;
440
441 *ww = *hh = *xx = *yy = -1 ;
442 if( geom == NULL || geom[0] == '\0' ) return ;
443
444 has_x = strstr(geom,"x") != NULL ;
445 has_plus = strstr(geom,"+") != NULL ;
446
447 if( has_x && has_plus )
448 sscanf(geom,"%dx%d+%d+%d",ww,hh,xx,yy) ;
449 else if( has_x )
450 sscanf(geom,"%dx%d",ww,hh) ;
451 else if( has_plus )
452 sscanf(geom,"+%d+%d",xx,yy) ;
453
454 return ;
455 }
456
457 /*------------------------------------------------------------------
458 Make a toplevel widget and put an existing plot into it.
459
460 If kfun is not NULL, when the user closes the window, it
461 will be called as in
462 kfun(mpcb) ;
463 where mpcb is the pointer returned by this function.
464 After this has been done, the memory used will be destroyed,
465 including all the contents of mp and mpcb.
466
467 The user may attach extra data to the void * pointer
468 mpcb->userdata after this function returns mpcb. If this
469 data involves the use of malloc, it is the user's responsibility
470 to free it in the call to kfun.
471 --------------------------------------------------------------------*/
472
memplot_to_topshell(Display * dpy,MEM_plotdata * mp,void_func * kfun)473 MEM_topshell_data * memplot_to_topshell( Display *dpy,
474 MEM_plotdata *mp, void_func *kfun )
475 {
476 Widget topshell , drawing , donebut , form , psfilebut ,
477 psprintbut ;
478 MEM_topshell_data *mpcb ;
479 int hmin=400 , wmin , ibut=0 , hh,ww,xx,yy ;
480 char *prc , *ept ;
481
482 /* sanity check */
483
484 if( dpy == NULL || mp == NULL ) return NULL ;
485
486 mpcb = (MEM_topshell_data *) malloc( sizeof(MEM_topshell_data) ) ;
487 memset((void*)mpcb, 0, sizeof(MEM_topshell_data));
488 mpcb->valid = 0 ;
489
490 #ifdef HAVE_XDBE
491 init_XDBE(dpy) ; mpcb->have_xdbe = 0 ;
492 #endif
493
494 wmin = MEMPLOT_ASPECT(mp) * hmin ;
495
496 /* 12 Oct 2000: a crude way to set the geometry of the popup */
497
498 pm_decode_geom( getenv("AFNI_tsplotgeom") , &ww,&hh,&xx,&yy ) ;
499 if( ww < wmin ) ww = wmin ;
500 if( hh < hmin ) hh = hmin ;
501
502 /* shell to hold it all */
503
504 topshell = XtVaAppCreateShell(
505 "AFNI" , "AFNI" , topLevelShellWidgetClass , dpy ,
506 XmNborderWidth , 0 ,
507 XmNminHeight , hmin , XmNheight , hh ,
508 XmNminWidth , wmin , XmNwidth , ww ,
509 XmNallowShellResize , False ,
510 XmNinitialResourcesPersistent , False ,
511 XmNdeleteResponse , XmDO_NOTHING , /* deletion handled
512 below */
513 NULL ) ;
514 XtVaSetValues(topshell, XmNtitle, wintitle, NULL); /* ZSS Oct 7 2009 */
515
516 XmAddWMProtocolCallback(
517 topshell , XmInternAtom(dpy,"WM_DELETE_WINDOW",False) ,
518 pm_donebut_CB , (XtPointer) mpcb ) ;
519
520 mpcb->top = topshell ;
521 mpcb->mp = mp ;
522 mpcb->dial= NULL ;
523 mpcb->wtf = NULL ;
524
525 mpcb->killfunc = kfun ;
526
527 /* form to manage it all */
528
529 #undef TIG
530 #undef NBUT
531 #define TIG 20
532 #define NBUT 3
533
534 mpcb->form = form =
535 XtVaCreateWidget( "dialog" , xmFormWidgetClass , topshell ,
536 XmNborderWidth , 0 ,
537 XmNfractionBase , TIG*NBUT - 1 ,
538 XmNinitialResourcesPersistent , False ,
539 NULL ) ;
540
541 /* buttons across the top */
542
543 if( redcolor == NULL ){ HOTCOLOR(form,redcolor) ; }
544
545 ibut = 0 ;
546 psfilebut = XtVaCreateManagedWidget(
547 "dialog" , xmPushButtonWidgetClass , form ,
548 LABEL_ARG("save image to file") ,
549 XmNtopAttachment , XmATTACH_FORM ,
550
551 XmNleftAttachment ,
552 (ibut!=0) ? XmATTACH_POSITION : XmATTACH_FORM ,
553 XmNleftPosition , ibut*TIG ,
554
555 XmNrightAttachment ,
556 (ibut==NBUT-1) ? XmATTACH_FORM : XmATTACH_POSITION ,
557 XmNrightPosition , ibut*TIG + (TIG-1) ,
558
559 XmNrecomputeSize , False ,
560 XmNtraversalOn , False ,
561 XmNinitialResourcesPersistent , False ,
562 NULL ) ;
563 XtAddCallback( psfilebut , XmNactivateCallback , pm_psfile_CB , (XtPointer) mpcb ) ;
564
565 ibut++ ;
566 psprintbut = XtVaCreateManagedWidget(
567 "dialog" , xmPushButtonWidgetClass , form ,
568 LABEL_ARG("to printer") ,
569 XmNtopAttachment , XmATTACH_FORM ,
570
571 XmNleftAttachment ,
572 (ibut!=0) ? XmATTACH_POSITION : XmATTACH_FORM ,
573 XmNleftPosition , ibut*TIG ,
574
575 XmNrightAttachment ,
576 (ibut==NBUT-1) ? XmATTACH_FORM : XmATTACH_POSITION ,
577 XmNrightPosition , ibut*TIG + (TIG-1) ,
578
579 XmNrecomputeSize , False ,
580 XmNtraversalOn , False ,
581 XmNinitialResourcesPersistent , False ,
582 NULL ) ;
583 prc = getenv( "AFNI_PSPRINT" ) ;
584 if( prc != NULL ){
585 sprintf( print_command , "|%.250s" , prc ) ;
586 XtAddCallback( psprintbut , XmNactivateCallback , pm_psprint_CB , (XtPointer) mpcb ) ;
587 } else {
588 #if 0
589 XtAddCallback( psprintbut , XmNactivateCallback , beep_CB ,
590 (XtPointer)"*** AFNI_PSPRINT not defined - see README.environment" );
591 #elif 0
592 XtSetSensitive( psprintbut , False ) ; /* 05 Nov 2001 */
593 #else
594 XtUnmanageChild( psprintbut ) ;
595 #endif
596 }
597
598 ibut++ ;
599 donebut = XtVaCreateManagedWidget(
600 "dialog" , xmPushButtonWidgetClass , form ,
601 LABEL_ARG("Done") ,
602 #if 1
603 BGCOLOR_ARG(redcolor) ,
604 #endif
605
606 XmNtopAttachment , XmATTACH_FORM ,
607
608 XmNleftAttachment ,
609 (ibut!=0) ? XmATTACH_POSITION : XmATTACH_FORM ,
610 XmNleftPosition , ibut*TIG ,
611
612 XmNrightAttachment ,
613 (ibut==NBUT-1) ? XmATTACH_FORM : XmATTACH_POSITION ,
614 XmNrightPosition , ibut*TIG + (TIG-1) ,
615
616 XmNrecomputeSize , False ,
617 XmNtraversalOn , False ,
618 XmNinitialResourcesPersistent , False ,
619 NULL ) ;
620 XtAddCallback( donebut , XmNactivateCallback , pm_donebut_CB , (XtPointer) mpcb ) ;
621
622 /* drawing area to receive the picture */
623
624 drawing = XtVaCreateManagedWidget( "dialog" , xmDrawingAreaWidgetClass , form ,
625 XmNtopAttachment , XmATTACH_WIDGET ,
626 XmNtopWidget , donebut ,
627 XmNleftAttachment , XmATTACH_FORM ,
628 XmNrightAttachment , XmATTACH_FORM ,
629 XmNbottomAttachment , XmATTACH_FORM ,
630 XmNinitialResourcesPersistent , False ,
631 NULL ) ;
632
633 XtAddCallback( drawing , XmNexposeCallback , pm_expose_CB , (XtPointer) mpcb ) ;
634 XtAddCallback( drawing , XmNresizeCallback , pm_resize_CB , (XtPointer) mpcb ) ;
635 XtAddCallback( drawing , XmNinputCallback , pm_input_CB , (XtPointer) mpcb ) ;
636
637 /* finish the job */
638
639 XtVaSetValues( form , BGCOLOR_ARG("white") , NULL ) ;
640
641 if( xx >= 0 && yy >= 0 )
642 XtVaSetValues( topshell , XmNx,xx , XmNy,yy , NULL ) ;
643
644 XtManageChild(form) ;
645 XtRealizeWidget(topshell);
646
647 mpcb->valid = 1 ; mpcb->userdata = NULL ; mpcb->drawing = drawing ;
648 return mpcb ;
649 }
650