1 #include <math.h>
2 #include "mpe_graphics_conf.h"
3 #include "mpetools.h"
4 #include "basex11.h"
5 
6 #ifdef MPE_NOMPI
7 #define MPI_MAX_PROCESSOR_NAME 256
8 #include "mpe_misc.h"
9 #else
10 #include "mpi.h"
11 #endif
12 
13 #ifdef HAVE_UNISTD_H
14 #include <unistd.h>
15 #else
16 extern char *getenv();
17 #endif
18 
19 #if defined(HAVE_STRING_H) || defined(STDC_HEADERS)
20 #include <string.h>
21 #endif
22 
23 #define MPE_INTERNAL
24 #include "mpe_graphics.h"        /*I "mpe.h" I*/
25 
26 #define DEBUG 0
27 
28 typedef struct xpand_list_Int_ {
29   int *list;
30   int nused;
31   int size;
32 } xpand_list_Int;
33 
34 #define ListHeadPtr( listPtr ) ( (listPtr)->list )
35 
36 #define ListSize( listPtr ) ( (listPtr)->nused )
37 
38 #define ListClose( listPtr, headPtr, nitems ) { \
39   headPtr = ListHeadPtr( listPtr ); \
40   nitems = ListSize( listPtr ); \
41   free( listPtr ); \
42 }
43 
44 static xpand_list_Int *Int_CreateList(int initialLen);
45 
46 /* Forward refs */
47 static void SortPoints ( MPE_Point *, int, XPoint **, MPE_Color **,
48 				   int **, int * );
49 static int Int_AddItem ( xpand_list_Int *, int );
50 
51 int MPE_buttonArray[] = {
52   Button1,
53   Button2,
54   Button3,
55   Button4,
56   Button5
57 };
58 
59 int MPE_logicArray[] = {
60   GXclear,			/* 0 */
61   GXand,			/* src && dst */
62   GXandReverse,			/* src && !dst */
63   GXcopy,			/* src */
64   GXandInverted,		/* !src && dst */
65   GXnoop,			/* dst */
66   GXxor,			/* src XOR dst */
67   GXor,				/* src || !dst */
68   GXnor,			/* !src && !dst */
69   GXequiv,			/* !src XOR dst */
70   GXinvert,			/* !dst */
71   GXorReverse,			/* !src || dst */
72   GXcopyInverted,		/* !src */
73   GXorInverted,			/* !src || dst */
74   GXnand,			/* !src || !dst */
75   GXset				/* 1 */
76 };
77 
78 static void SetBackingStoreBitGrav (MPE_XGraph);
79 
80 #ifdef POINTER_64_BITS
81 static int fort_index = 0;
82 MPE_XGraph MPE_fort_head = 0;
83 #endif
84 
85 /*N XGRAPHICS_FORTRAN
86 
87     Notes For Fortran Interface :
88     The Fortran interface to this routine is different from its C
89     counterpart and it has an additional argument, ierr, at the end
90     of the argument list, i.e. the returned function value (the error
91     code) in C interface is returned as the additional argument in
92     Fortran interface.  The Fortran interface is invoked with the
93     CALL statement.
94 
95     All MPI and MPE objects, MPI_Comm, MPE_XGraph and MPE_Color, are
96     of type INTEGER in Fortran.
97 N*/
98 
99 /*@
100     MPE_Open_graphics - (collectively) opens an X Windows display
101 
102     Input Parameters:
103 +   comm - Communicator of participating processes
104 
105 .   display - Name of X window display.  If NULL, display will be taken
106     from the local DISPLAY variable on each process. If the local DISPLAY is
107     undefined, the DISPLAY variable of the process with rank 0 in 'comm'
108     will be used.  If that is either undefined then the value of display is
109     ``hostname``:0, or if it starts with w ":xy", then the value of
110     display is ``hostname``:xy.
111 
112 .   x,y - position of the window.  If '(-1,-1)', then the user should be
113     asked to position the window (this is a window manager issue).
114 .   w,h - width and height of the window, in pixels.
115 -   is_collective - true if the graphics operations are collective; this
116     allows the MPE graphics operations to make fewer connections to the
117     display.  If false, then all processes in the communicator comm will
118     open the display; this could exceed the number of connections that your
119     X window server allows.  Not yet implemented.
120 
121     Output Parameter:
122 .   handle - Graphics handle to be given to other MPE graphics routines.
123 
124     Notes:
125     This is a collective routine.  All processes in the given communicator
126     must call it, and it has the same semantics as 'MPI_Barrier' (that is,
127     other collective operations can not cross this routine).
128 
129 .N XGRAPHICS_FORTRAN
130 
131     Additional Notes for Fortran Interface :
132     If Fortran 'display' argument is an empty string, "", display will be
133     taken from the DISPLAY variable on the process with rank 0 in 'comm'.
134     The trailing blanks in Fortran CHARACTER string argument will be
135     ignored.
136 @*/
MPE_Open_graphics(handle,comm,display,x,y,w,h,is_collective)137 int MPE_Open_graphics( handle, comm, display, x, y, w, h, is_collective )
138 MPE_XGraph *handle;
139 MPI_Comm   comm;
140 char       display[MPI_MAX_PROCESSOR_NAME+4];
141 int        x, y;
142 int        w, h;
143 int        is_collective;
144 {
145 
146 #ifndef MPE_NOMPI
147   Window     win;
148 #endif
149   MPE_XGraph new;
150   char       *local_display;
151 #ifdef FOO
152   XFontStruct **font_info;
153   XGCValues  values;
154   char       fontname[128];
155 #endif
156 #ifndef MPE_NOMPI
157   int        numprocs, namelen;
158 #endif
159   int        myid, successful=0;
160 
161   myid = 0;		     /* for the single processor version */
162   *handle            = 0;    /* In case of errors */
163   new		     = NEW(struct MPE_XGraph_s);    /* CHKPTRN(new); */
164   new->Cookie        = MPE_G_COOKIE;
165   new->xwin          = NEW(XBWindow);      /* CHKPTRN(new->xwin); */
166 
167   /* These are used to capture the images into xwd files */
168   new->capture_file  = 0;
169   new->capture_freq  = 1;
170   new->capture_num   = 0;
171   new->capture_cnt   = 0;
172   new->input_mask    = 0;
173   new->event_routine = 0;
174 
175 #ifdef POINTER_64_BITS
176   /* In case we need to support fortran */
177   new->fort_index = fort_index++;
178   new->next       = MPE_fort_head;
179   MPE_fort_head   = new;
180 #endif
181 
182 #ifndef MPE_NOMPI
183   if (is_collective) {
184     /* Not supported; just use individual connections */
185     is_collective = 0;
186   }
187 
188   new->comm	     = comm;
189   new->is_collective = is_collective;
190 
191   MPI_Comm_size(comm,&numprocs);
192   MPI_Comm_rank(comm,&myid);
193 #endif
194 
195   local_display = getenv( "DISPLAY" );
196 
197   if (!display) {
198 #ifndef MPE_NOMPI
199     int str_len;
200 #endif
201 
202 #if DEBUG
203     fprintf( stderr, "[%d] Guessing at display name.\n", myid );
204     fprintf( stderr, "[%d] DISPLAY = %s\n", myid, local_display );
205     fflush( stderr );
206 #endif
207 
208     if (myid == 0) {
209 
210       if (!local_display || local_display[0] == ':') {
211 	/*
212            Replace display with hostname:xy if undefined for the remote
213 	   nodes.  Do not modify on the master node because X11 may work
214 	   with an Unix socket and not INET one for security reason.
215         */
216 
217 #ifdef MPE_NOMPI
218 	display = (char *)malloc( 257 );
219 	MPE_GetHostName( display, 257 );
220 #else
221 	/* This is not correct, since there is no guarentee that this
222 	   is the "correct" network name */
223 	display = (char *)malloc( MPI_MAX_PROCESSOR_NAME );
224 	MPI_Get_processor_name( display, &namelen );
225 #endif
226 
227 #if DEBUG
228 	fprintf( stderr, "Process 0 is: %s\n", display );
229 	fflush( stderr );
230 #endif
231 	if (local_display)
232 	  /* Add the X11 screen number: */
233 	  strcat( display, local_display);
234 	else
235 	  /* Assume screen 0 by default: */
236 	  strcat( display, ":0" );
237 
238 #if DEBUG
239 	fprintf( stderr, "Process 0 is: %s\n", display );
240 	fflush( stderr );
241 #endif
242 
243       }
244       else
245 	/* Trust the DISPLAY environment variable: */
246 	display = local_display;
247 
248 #ifndef MPE_NOMPI
249       str_len = strlen( display ) + 1;
250       MPI_Bcast( &str_len, 1, MPI_INT, 0, comm );
251 #endif
252 
253     }
254 
255 #ifndef MPE_NOMPI
256     else {
257       MPI_Bcast( &str_len, 1, MPI_INT, 0, comm );
258       display = (char *) malloc( sizeof( char ) * str_len );
259     }
260     MPI_Bcast( display, str_len, MPI_CHAR, 0, comm );
261 #endif
262 
263     if (local_display)
264       /*
265          If the DISPLAY environment variable is set externally, trust this
266 	 value because it may be set by ssh or specifically set on the
267 	 master node to use a Unix socket instead of an IFNET one for
268 	 efficiency or security reason:
269       */
270       display = local_display;
271   }
272 
273   new->display_name = (char *)malloc( strlen(display) + 1 );
274   if (!new->display_name)
275       return MPE_ERR_LOW_MEM;
276   strcpy( new->display_name, display );
277 
278 #if DEBUG
279   fprintf( stderr, "[%d] trying to open %s\n", myid, display );
280   fflush( stderr );
281 #endif
282 
283   if (0 == myid) {
284     successful = !XBQuickWindow( new->xwin, display, (char *)"MPE", x, y, w, h );
285     /* ALWAYS send the local host */
286     if (successful) {
287 
288 #ifndef MPE_NOMPI
289       win = new->xwin->win;
290       MPI_Bcast( &win, 1, MPI_UNSIGNED_LONG, 0, comm );
291 #endif /* ifndef MPE_NOMPI */
292 
293     } else {
294 
295 #ifndef MPE_NOMPI
296       win = 0;
297       MPI_Bcast( &win, 1, MPI_UNSIGNED_LONG, 0, comm );
298 #endif /* ifndef MPE_NOMPI */
299 
300     }
301   }
302 #ifndef MPE_NOMPI
303   else {
304     MPI_Bcast( &win, 1, MPI_UNSIGNED_LONG, 0, comm );
305     if (win) {  /* if process 0 connected */
306       successful = !XBQuickWindowFromWindow( new->xwin, display, win );
307     }
308   }
309 #endif /* ifndef MPE_NOMPI */
310 
311 #if DEBUG
312   fprintf( stderr, "%s to %s from process %d.\n",
313 	   successful ? "Successfully connected" : "Failed to connect",
314 	   display, myid );
315   fflush( stderr );
316 #endif
317 
318 #ifdef FOO
319   /* set a default font */
320   strcpy(fontname,"fixed");
321   if ((*font_info = XLoadQueryFont( new->xwin->disp, fontname )) == NULL)
322   {
323       fprintf( stderr, "Could not open %s font\n", fontname );
324       exit(1);
325   }
326   values.font = (*font_info)->fid;
327   XChangeGC( new->xwin->disp, new->xwin->gc.set, GCFont, &values );
328   fprintf("successfully set default font\n");
329 #endif
330 
331   if (!successful) {
332 #ifndef MPE_NOMPI
333     char myname[MPI_MAX_PROCESSOR_NAME];
334     int mynamelen;
335     MPI_Get_processor_name( myname, &mynamelen );
336     fprintf( stderr, "Failed to connect to %s from %s\n",
337 	     display, myname );
338 #endif
339     *handle = (MPE_XGraph) 0;
340     return MPE_ERR_NOXCONNECT;
341   } else {
342     SetBackingStoreBitGrav( new );
343     *handle = new;
344     return MPE_SUCCESS;
345   }
346 }
347 
348 
SetBackingStoreBitGrav(MPE_XGraph graph)349 static void SetBackingStoreBitGrav( MPE_XGraph graph )
350 {
351   XSetWindowAttributes attrib;
352 
353   graph->backingStore = DoesBackingStore(
354 	ScreenOfDisplay( graph->xwin->disp, graph->xwin->screen ) );
355 #if DEBUG
356   fprintf( stderr, "Screen's backing store support is %s.\n",
357 	  graph->backingStore==NotUseful ? "NotUseful" :
358 	  graph->backingStore==WhenMapped ? "WhenMapped" :
359 	  graph->backingStore==Always ? "Always" : "dunno" );
360   fflush( stderr );
361 #endif
362   attrib.bit_gravity = NorthWestGravity;
363   attrib.backing_store = graph->backingStore;
364   XChangeWindowAttributes( graph->xwin->disp, graph->xwin->win,
365 			   CWBitGravity | CWBackingStore,
366 			   &attrib );
367 }
368 
369 /*@
370   MPE_CaptureFile - Sets the base filename used to capture output from updates
371 
372   Input Parameters:
373 + handle - MPE graphics handle
374 . fname  - base file name (see below)
375 - freq   - Frequency of updates
376 
377   Return Values:
378 + MPE_ERR_LOW_MEM - malloc for copy of the filename (fname) failed
379 . MPE_ERR_BAD_ARGS - 'handle' parameter is bad
380 - MPE_SUCCESS - success
381 
382   Notes:
383   The output is written in xwd format to 'fname%d', where '%d' is the number
384   of the file (starting from zero).
385 
386 .N XGRAPHICS_FORTRAN
387 
388     Additional Notes for Fortran Interface :
389     The trailing blanks in Fortran 'CHARACTER' string argument will be
390     ignored.
391 @*/
MPE_CaptureFile(handle,fname,freq)392 int MPE_CaptureFile( handle, fname, freq )
393 MPE_XGraph handle;
394 char       *fname;
395 int        freq;
396 {
397   if (handle->Cookie != MPE_G_COOKIE) {
398     fprintf( stderr, "Handle argument is incorrect or corrupted\n" );
399     return MPE_ERR_BAD_ARGS;
400   }
401 
402   handle->capture_file = (char *)malloc( strlen( fname ) + 1 );
403   if (!handle->capture_file) {
404       fprintf( stderr, "Could not allocate memory for filename\n" );
405       return MPE_ERR_LOW_MEM;
406       }
407   strcpy( handle->capture_file, fname );
408   handle->capture_num  = 0;
409   handle->capture_freq = freq;
410   handle->capture_cnt  = 0;
411 
412   return MPE_SUCCESS;
413 }
414 
415 
416 /*@
417     MPE_Draw_point - Draws a point on an X Windows display
418 
419     Input Parameters:
420 +   handle - MPE graphics handle
421 .   x,y - pixel position to draw.  Coordinates are upper-left origin (standard
422     X11)
423 -   color - Color `index` value.  See 'MPE_MakeColorArray'.
424     By default, the colors
425     'MPE_WHITE', 'MPE_BLACK', 'MPE_RED', 'MPE_YELLOW', 'MPE_GREEN', 'MPE_CYAN',
426     'MPE_BLUE',  'MPE_MAGENTA', 'MPE_AQUAMARINE',
427             'MPE_FORESTGREEN', 'MPE_ORANGE', 'MPE_VIOLET', 'MPE_BROWN',
428             'MPE_PINK', 'MPE_CORAL' and 'MPE_GRAY' are defined.
429 
430 .N XGRAPHICS_FORTRAN
431 @*/
MPE_Draw_point(handle,x,y,color)432 int MPE_Draw_point( handle, x, y, color )
433 MPE_XGraph handle;
434 int        x, y;
435 MPE_Color  color;
436 {
437   if (handle->Cookie != MPE_G_COOKIE) {
438     fprintf( stderr, "Handle argument is incorrect or corrupted\n" );
439     return MPE_ERR_BAD_ARGS;
440   }
441 
442 #ifndef MPE_NOMPI
443   if (handle->is_collective) {
444   } else
445 #endif
446 
447   {
448     XBSetPixVal( handle->xwin, handle->xwin->cmapping[color] );
449     XDrawPoint( handle->xwin->disp, handle->xwin->win,
450 	       handle->xwin->gc.set, x, y );
451   }
452   return MPE_SUCCESS;
453 }
454 
455 
456 /*@
457     MPE_Draw_points - Draws points on an X Windows display
458 
459     Input Parameters:
460 +   handle - MPE graphics handle
461 .   points - list of points to draw
462 -   npoints - number of points to draw
463 
464 .N XGRAPHICS_FORTRAN
465 @*/
MPE_Draw_points(handle,points,npoints)466 int MPE_Draw_points( handle, points, npoints )
467 MPE_XGraph handle;
468 MPE_Point *points;
469 int npoints;
470 {
471   XPoint *sortedPoints;
472   int *colorRanges, ncolors, colorNum, n;
473   MPE_Color *colorList;
474 
475   if (handle->Cookie != MPE_G_COOKIE) {
476     fprintf( stderr, "Handle argument is incorrect or corrupted\n" );
477     return MPE_ERR_BAD_ARGS;
478   }
479 
480 #if 0
481   /* temporary debug */
482   {int i;
483   fprintf( stderr, "MPE_Draw_points\n" );
484   for (i=0; i<npoints; i++) {
485     fprintf( stderr, "%d. (%d %d) %d\n", i, points[i].x, points[i].y,
486 	     points[i].c );
487   }}
488 #endif
489 
490 
491   SortPoints( points, npoints, &sortedPoints, &colorList, &colorRanges,
492 	      &ncolors );
493 
494 #if 0
495   /* another temporary debug */
496   fprintf( stderr, "Sorted points.  %d colors\n", ncolors );
497   for (i=0; i<ncolors; i++) {
498     fprintf( stderr, "%d %d's.\n", colorRanges[i], colorList[i] );
499   }
500 #endif
501 
502   for (colorNum = 0; colorNum < ncolors; colorNum++) {
503     n = (colorNum < ncolors-1)
504       ? colorRanges[colorNum+1] - colorRanges[colorNum]
505       : npoints - colorRanges[colorNum];
506 
507 /*
508     printf( "xxx: %d %d %d %d\n", (colorNum < ncolors-1),
509 	   colorRanges[colorNum+1] - colorRanges[colorNum],
510 	   ncolors - colorNum,
511 	   (colorNum < ncolors-1)
512       ? colorRanges[colorNum+1] - colorRanges[colorNum]
513       : npoints - colorRanges[colorNum] );
514 
515     printf( "Sending %d points of color %d starting at %d\n", n,
516 	    colorList[colorNum],
517 	    colorRanges[colorNum] );
518 
519 
520     for (i = 0; i<n; i++) {
521       printf( "sending (%hd %hd)\n",
522 	      sortedPoints[colorRanges[colorNum]+i].x,
523 	      sortedPoints[colorRanges[colorNum]+i].y );
524     }
525 */
526 
527     XBSetPixVal( handle->xwin, handle->xwin->cmapping[colorList[colorNum]] );
528     XDrawPoints( handle->xwin->disp, handle->xwin->win,
529 		 handle->xwin->gc.set,
530 		 sortedPoints + colorRanges[colorNum],
531 		 n, CoordModeOrigin );
532   }
533   free( sortedPoints );
534   free( colorList );
535   free( colorRanges );
536   return MPE_SUCCESS;
537 }
538 
539 
540 
SortPoints(lista,a,listb,colorList,boundaryPoints,ncolors)541 static void SortPoints( lista, a, listb, colorList, boundaryPoints, ncolors )
542 MPE_Point *lista;
543 XPoint **listb;
544 MPE_Color **colorList;
545 int a, **boundaryPoints, *ncolors;
546 {
547   int top, bottom, outoforder;
548   MPE_Color thisColor, tempColor, *keyList;
549 
550   XPoint *list, tempPt;
551   xpand_list_Int *boundaryList;
552 
553   boundaryList = Int_CreateList( 20 );
554   list = *listb = (XPoint *) malloc( sizeof( XPoint ) * a );
555   keyList = (MPE_Color *) malloc( sizeof( MPE_Color ) * a );
556   for (top = 0; top < a; top++) {
557     list[top].x = lista[top].x;
558     list[top].y = lista[top].y;
559     keyList[top] = lista[top].c;
560 /*
561     fprintf( stderr, "unsorted %d = %d %d %d\n", top, lista[top].x,
562 	     lista[top].y,
563 	     lista[top].c );
564 */
565   }
566   /* copy the list over */
567 
568   top = 0;
569   outoforder = 1;
570 
571   while (top < a && outoforder) {
572     Int_AddItem( boundaryList, top );
573     /* keep a list of the start of each different color */
574 
575     /* temp. debugging */
576     /* fprintf( */
577 
578     thisColor = keyList[top];
579     bottom = a-1;
580     outoforder = 0;
581 
582     while (top < bottom) {
583       if (keyList[top] != thisColor) {
584 	outoforder = 1;
585 	while (bottom>top && keyList[bottom] != thisColor) bottom--;
586 	if (bottom>top) {
587 	  tempPt = list[bottom];
588 	  list[bottom] = list[top];
589 	  list[top] = tempPt;
590 	  tempColor = keyList[bottom];
591 	  keyList[bottom] = keyList[top];
592 	  keyList[top] = tempColor;
593 	  top++;
594 	}
595       } else {
596 	top++;
597       }
598     }
599   }
600 
601   ListClose( boundaryList, *boundaryPoints, *ncolors );
602 
603   *colorList = (MPE_Color *) malloc( sizeof( MPE_Color ) * *ncolors );
604   for (top=0; top < *ncolors; top++) {
605     (*colorList)[top] = keyList[(*boundaryPoints)[top]];
606 /*
607     printf( "color %d = %d\n", top, (*colorList)[top] );
608 */
609   }
610 
611 /*
612   bottom = 0;
613   for (top = 0; top < a; top++) {
614     if ((*boundaryPoints)[bottom] == top) {
615       fprintf( stderr, "color = %d\n", (*colorList)[bottom] );
616       bottom++;
617     }
618     fprintf( stderr, "sorted %d = %hu %hu\n", top, list[top].x, list[top].y );
619   }
620 */
621 
622   free( keyList );
623 }
624 
625 
626 
627 /*@
628     MPE_Draw_line - Draws a line on an X11 display
629 
630     Input Parameters:
631 +   handle - MPE graphics handle
632 .   x1,y_1 - pixel position of one end of the line to draw.  Coordinates are
633             upper-left origin (standard X11)
634 .   x2,y_2 - pixel position of the other end of the line to draw.  Coordinates
635             are upper-left origin (standard X11)
636 -   color - Color `index` value.  See 'MPE_MakeColorArray'.
637     By default, the colors
638     'MPE_WHITE', 'MPE_BLACK', 'MPE_RED', 'MPE_YELLOW', 'MPE_GREEN', 'MPE_CYAN',
639     'MPE_BLUE',  'MPE_MAGENTA', 'MPE_AQUAMARINE',
640             'MPE_FORESTGREEN', 'MPE_ORANGE', 'MPE_VIOLET', 'MPE_BROWN',
641             'MPE_PINK', 'MPE_CORAL' and 'MPE_GRAY' are defined.
642 
643 .N XGRAPHICS_FORTRAN
644 @*/
MPE_Draw_line(handle,x1,y_1,x2,y_2,color)645 int MPE_Draw_line( handle, x1, y_1, x2, y_2, color )
646 MPE_XGraph handle;
647 int        x1, y_1, x2, y_2;
648 MPE_Color  color;
649 {
650   if (handle->Cookie != MPE_G_COOKIE) {
651     fprintf( stderr, "Handle argument is incorrect or corrupted\n" );
652     return MPE_ERR_BAD_ARGS;
653   }
654 
655 #ifndef MPE_NOMPI
656   if (handle->is_collective) {
657   } else
658 #endif
659 
660   {
661     XBSetPixVal( handle->xwin, handle->xwin->cmapping[color] );
662     XDrawLine( handle->xwin->disp, handle->xwin->win,
663 	      handle->xwin->gc.set, x1, y_1, x2, y_2 );
664   }
665   return MPE_SUCCESS;
666 }
667 
668 /*@
669     MPE_Fill_rectangle - Draws a filled rectangle on an X11 display
670 
671     Input Parameters:
672 +   handle - MPE graphics handle
673 .   x,y - pixel position of the upper left (low coordinate) corner of the
674             rectangle to draw.
675 .   w,h - width and height of the rectangle
676 -   color - Color `index` value.  See 'MPE_MakeColorArray'.
677     By default, the colors
678     'MPE_WHITE', 'MPE_BLACK', 'MPE_RED', 'MPE_YELLOW', 'MPE_GREEN', 'MPE_CYAN',
679     'MPE_BLUE',  'MPE_MAGENTA', 'MPE_AQUAMARINE',
680             'MPE_FORESTGREEN', 'MPE_ORANGE', 'MPE_VIOLET', 'MPE_BROWN',
681             'MPE_PINK', 'MPE_CORAL' and 'MPE_GRAY' are defined.
682 
683     Notes:
684     This uses the X11 definition of width and height, so you may want to
685     add 1 to both of them.
686 
687 .N XGRAPHICS_FORTRAN
688 @*/
MPE_Fill_rectangle(handle,x,y,w,h,color)689 int MPE_Fill_rectangle( handle, x, y, w, h, color )
690 MPE_XGraph handle;
691 int        x, y, w, h;
692 MPE_Color  color;
693 {
694   if (handle->Cookie != MPE_G_COOKIE) {
695     fprintf( stderr, "Handle argument is incorrect or corrupted\n" );
696     return MPE_ERR_BAD_ARGS;
697   }
698 
699 #ifndef MPE_NOMPI
700   if (handle->is_collective) {
701   } else
702 #endif
703 
704   {
705     XBSetPixVal( handle->xwin, handle->xwin->cmapping[color] );
706     XFillRectangle( handle->xwin->disp, handle->xwin->win,
707 		   handle->xwin->gc.set, x, y, w, h );
708   }
709   return MPE_SUCCESS;
710 }
711 
712 
713 
714 /*@
715     MPE_Update - Updates an X11 display
716 
717     Input Parameter:
718 .   handle - MPE graphics handle.
719 
720     Note:
721     Only after an 'MPE_Update' can you count on seeing the results of MPE
722     drawing routines.  This is caused by the buffering of graphics requests
723     for improved performance.
724 
725 .N XGRAPHICS_FORTRAN
726 @*/
MPE_Update(handle)727 int MPE_Update( handle )
728 MPE_XGraph handle;
729 {
730   if (handle->Cookie != MPE_G_COOKIE) {
731     fprintf( stderr, "Handle argument is incorrect or corrupted\n" );
732     return MPE_ERR_BAD_ARGS;
733   }
734 
735 #ifndef MPE_NOMPI
736   if (handle->is_collective) {
737   } else
738 #endif
739 
740   {
741     XFlush( handle->xwin->disp );
742   }
743 
744   if (handle->capture_file) {
745 #ifdef HAVE_SYSTEM
746       /* Place into a file */
747       char cmdbuf[1024];
748       if ((handle->capture_num % handle->capture_freq) == 0) {
749 	  /* Assume xwd is in user's PATH... */
750 	  sprintf( cmdbuf, "xwd -display %s -id %ld > %s%.3d.xwd\n",
751 		   handle->display_name,
752 		   (long) handle->xwin->win, handle->capture_file,
753 		   handle->capture_cnt++ );
754 	  system( cmdbuf );
755 	  }
756       handle->capture_num++;
757 #else
758       fprintf( stderr, "Could not call system routine for file capture\n" );
759 #endif
760       }
761   return MPE_SUCCESS;
762 }
763 
764 /*
765     MPE_Create_contour -
766  */
767 
768 /*
769     MPE_Draw_contour -
770  */
771 
772 
773 
774 
775 /*@
776     MPE_Close_graphics - Closes an X11 graphics device
777 
778     Input Parameter:
779 .   handle - MPE graphics handle.
780 
781     Return Values:
782 +   MPE_ERR_BAD_ARGS - 'handle' parameter is bad
783 -   MPE_SUCCESS - success
784 
785 .N XGRAPHICS_FORTRAN
786 @*/
MPE_Close_graphics(handle)787 int MPE_Close_graphics( handle )
788 MPE_XGraph *handle;
789 {
790   if (!handle || !*handle || (*handle)->Cookie != MPE_G_COOKIE) {
791     fprintf( stderr, "Handle argument is incorrect or corrupted\n" );
792     return MPE_ERR_BAD_ARGS;
793   }
794   XBWinDestroy( (*handle)->xwin );
795   FREE( *handle );
796   *handle = 0;
797   return MPE_SUCCESS;
798 }
799 
800 
801 
802 
803 /*@
804     MPE_Make_color_array - Makes an array of color indices
805 
806     Input Parameters:
807 +   handle - MPE graphics handle
808 .   nc     - Number of colors
809 
810     Output Parameter:
811 -   array - Array of color indices
812 
813     Notes:
814     The new colors for a uniform distribution in hue space and replace the
815     existing colors `except` for 'MPE_WHITE' and 'MPE_BLACK'.
816 
817 .N XGRAPHICS_FORTRAN
818 @*/
MPE_Make_color_array(handle,ncolors,array)819 int MPE_Make_color_array( handle, ncolors, array )
820 MPE_XGraph handle;
821 int        ncolors;
822 MPE_Color  array[];
823 {
824   int    i;
825   PixVal white;
826 
827   if (handle->Cookie != MPE_G_COOKIE) {
828     fprintf( stderr, "Handle argument is incorrect or corrupted\n" );
829     return MPE_ERR_BAD_ARGS;
830   }
831   XBUniformHues( handle->xwin, ncolors + 2 );
832 
833   /* XBUniformHues creates a spectrum like:
834      BLACK red->yellow->blue->purple WHITE
835      We want something like:
836      WHITE BLACK red->yellow->blue->purple
837 
838      So I shifted things around a little.
839      */
840 
841   /* here's the original code: */
842   /*
843      for (i=0; i<ncolors; i++)
844      array[i] = handle->xwin->cmapping[i + 2];
845      */
846 
847   /* here's something that works: */
848   white = handle->xwin->cmapping[ncolors+1];
849   for (i=0; i<ncolors; i++) {
850     array[i] = (MPE_Color)(i+2);
851     handle->xwin->cmapping[ncolors+1-i] = handle->xwin->cmapping[ncolors-i];
852   }
853   handle->xwin->cmapping[MPE_BLACK] = handle->xwin->cmapping[0];
854   handle->xwin->cmapping[MPE_WHITE] = white;
855 
856   return MPE_SUCCESS;
857 }
858 
859 
860 
861 /*@
862   MPE_Num_colors - Gets the number of available colors
863 
864   Input Parameter:
865 . handle - MPE graphics handle
866 
867   Output Parameter:
868 . nc - Number of colors available on the display.
869 
870 .N XGRAPHICS_FORTRAN
871 @*/
MPE_Num_colors(handle,nc)872 int MPE_Num_colors( handle, nc )
873 MPE_XGraph handle;
874 int        *nc;
875 {
876   if (handle->Cookie != MPE_G_COOKIE) {
877     fprintf( stderr, "Handle argument is incorrect or corrupted\n" );
878     return MPE_ERR_BAD_ARGS;
879   }
880   *nc = handle->xwin->maxcolors;
881   return MPE_SUCCESS;
882 }
883 
884 /*@
885    MPE_Draw_circle - Draws a circle
886 
887   Input Parameters:
888 + graph - MPE graphics handle
889 . centerx - horizontal center point of the circle
890 . centery - vertical center point of the circle
891 . radius - radius of the circle
892 - color - color of the circle
893 
894 .N XGRAPHICS_FORTRAN
895 @*/
MPE_Draw_circle(graph,centerx,centery,radius,color)896 int MPE_Draw_circle( graph, centerx, centery, radius, color )
897 MPE_XGraph graph;
898 int centerx, centery, radius;
899 MPE_Color color;
900 {
901   int returnVal;
902 
903   if (graph->Cookie != MPE_G_COOKIE) {
904     fprintf( stderr, "Handle argument is incorrect or corrupted\n" );
905     return MPE_ERR_BAD_ARGS;
906   }
907 
908 #if DEBUG
909   fprintf( stdout, "Drawing at (%d,%d) with radius %d and color %d\n",
910 	   centerx, centery, radius, color );
911   fflush( stdout );
912 #endif
913   XBSetPixVal( graph->xwin, graph->xwin->cmapping[color] );
914   XDrawArc( graph->xwin->disp, XBDrawable(graph->xwin),
915 		        graph->xwin->gc.set, centerx-radius, centery-radius,
916 		        radius*2, radius*2, 0, 360*64 );
917   returnVal = 0;
918   return MPE_Xerror( returnVal, "MPE_DrawCircle" );
919 }
920 
921 
922 
923 /*@
924    MPE_Fill_circle - Fills a circle
925 
926   Input Parameters:
927 + graph - MPE graphics handle
928 . centerx - horizontal center point of the circle
929 . centery - vertical center point of the circle
930 . radius - radius of the circle
931 - color - color of the circle
932 
933 .N XGRAPHICS_FORTRAN
934 @*/
MPE_Fill_circle(graph,centerx,centery,radius,color)935 int MPE_Fill_circle( graph, centerx, centery, radius, color )
936 MPE_XGraph graph;
937 int centerx, centery, radius;
938 MPE_Color color;
939 {
940   int returnVal;
941 
942   if (graph->Cookie != MPE_G_COOKIE) {
943     fprintf( stderr, "Handle argument is incorrect or corrupted\n" );
944     return MPE_ERR_BAD_ARGS;
945   }
946 
947   XBSetPixVal( graph->xwin, graph->xwin->cmapping[color] );
948   XFillArc( graph->xwin->disp, XBDrawable(graph->xwin),
949 		        graph->xwin->gc.set, centerx-radius, centery-radius,
950 		        radius*2, radius*2, 0, 360*64 );
951   returnVal = 0;
952   return MPE_Xerror( returnVal, "MPE_FillCircle" );
953 }
954 
955 /*@
956    MPE_Draw_string - Draw a text string
957 
958   Input Parameters:
959 + graph - MPE graphics handle
960 . x - x-coordinate of the origin of the string
961 . y - y-coordinate of the origin of the string
962 . color - color of the text
963 - string - text string to be drawn
964 
965 .N XGRAPHICS_FORTRAN
966 
967     Additional Notes for Fortran Interface :
968     The trailing blanks in Fortran CHARACTER string argument will be
969     ignored.
970 @*/
MPE_Draw_string(graph,x,y,color,string)971 int MPE_Draw_string( graph, x, y, color, string )
972 MPE_XGraph graph;
973 int x, y;
974 MPE_Color color;
975 char *string;
976 {
977   int returnVal;
978 
979   if (graph->Cookie != MPE_G_COOKIE) {
980     fprintf( stderr, "Handle argument is incorrect or corrupted\n" );
981     return MPE_ERR_BAD_ARGS;
982   }
983 
984   printf("color = %d, string = %s\n",(int) color, string);
985 
986   XBSetPixVal( graph->xwin, graph->xwin->cmapping[color] );
987   returnVal = XDrawString( graph->xwin->disp, XBDrawable(graph->xwin),
988 		        graph->xwin->gc.set, x, y, string, strlen(string) );
989 /* from mail
990   returnVal = XDrawString( graph->xwin->disp, graph->xwin->win,
991 		        graph->xwin->gc.set, x, y, string, strlen(string) );
992 */
993   return MPE_Xerror( returnVal, "MPE_DrawString" );
994 }
995 
996 
997 /*@
998    MPE_Draw_logic - Sets logical operation for laying down new pixels
999 
1000   Input Parameters:
1001 + graph - MPE graphics handle
1002 - function - integer specifying one of the following:
1003 .n            'MPE_LOGIC_COPY' - no logic, just copy the pixel
1004 .n	    'MPE_LOGIC_XOR'  - xor the new pixel with the existing one
1005 	     and many more... see 'mpe_graphics.h'
1006 
1007 .N XGRAPHICS_FORTRAN
1008 @*/
MPE_Draw_logic(graph,function)1009 int MPE_Draw_logic( graph, function )
1010 MPE_XGraph graph;
1011 int function;
1012 {
1013   int returnVal;
1014   if (graph->Cookie != MPE_G_COOKIE) {
1015     fprintf( stderr, "Handle argument is incorrect or corrupted\n" );
1016     return MPE_ERR_BAD_ARGS;
1017   }
1018   XSetFunction( graph->xwin->disp,
1019 			    graph->xwin->gc.set, function );
1020   returnVal = 0;
1021   MPE_Xerror( returnVal, "MPE_DrawLogic" );
1022   return returnVal;
1023 }
1024 
1025 
1026 
1027 /*@
1028    MPE_Line_thickness - Sets thickness of lines
1029 
1030   Input Parameters:
1031 + graph - MPE graphics handle
1032 - thickness - integer specifying how many pixels wide lines should be
1033 
1034 .N XGRAPHICS_FORTRAN
1035 @*/
MPE_Line_thickness(graph,thickness)1036 int MPE_Line_thickness( graph, thickness )
1037 MPE_XGraph graph;
1038 int thickness;
1039 {
1040   XGCValues gcChanges;
1041 
1042   gcChanges.line_width = thickness;
1043   XChangeGC( graph->xwin->disp, graph->xwin->gc.set,
1044 	     GCLineWidth, &gcChanges );
1045 
1046   return MPE_SUCCESS;
1047 }
1048 
1049 
1050 
MPE_Draw_dashes(graph,dashlen)1051 int MPE_Draw_dashes( graph, dashlen )
1052 MPE_XGraph graph;
1053 int dashlen;
1054 {
1055   XGCValues gcChanges;
1056 
1057   if (dashlen) {
1058     gcChanges.line_style = LineDoubleDash;
1059     gcChanges.dashes = dashlen;
1060     gcChanges.dash_offset = 0;
1061     XChangeGC( graph->xwin->disp, graph->xwin->gc.set,
1062 	       GCDashOffset | GCDashList | GCLineStyle, &gcChanges );
1063   } else {
1064     gcChanges.line_style = 0;
1065     XChangeGC( graph->xwin->disp, graph->xwin->gc.set,
1066 	       GCLineStyle, &gcChanges );
1067   }
1068 
1069   return 0;
1070 }
1071 
1072 
MPE_Dash_offset(graph,offset)1073 int MPE_Dash_offset( graph, offset )
1074 MPE_XGraph graph;
1075 int offset;
1076 {
1077   XGCValues gcChanges;
1078 
1079   gcChanges.dash_offset = offset;
1080   XChangeGC( graph->xwin->disp, graph->xwin->gc.set,
1081 	     GCDashOffset, &gcChanges );
1082   return 0;
1083 }
1084 
1085 
1086 
1087 
1088 
1089 /*@
1090    MPE_Add_RGB_color - Adds a color to the colormap given its RGB values
1091 
1092   Input Parameters:
1093 + graph - MPE graphics handle
1094 - red, green, blue - color levels from 0 to 65535
1095 
1096   Output Parameter:
1097 . mapping - index of the new color
1098 
1099   Return Values:
1100 + -1 - maxcolors too large (equal to numcolors)
1101 . MPE_SUCCESS - successful
1102 - mapping - index of the new color
1103 
1104   Notes:
1105   This call adds a color cell to X11''s color table, increments maxcolors
1106   (the index), and writes it to the mapping parameter.
1107 
1108 .N XGRAPHICS_FORTRAN
1109 @*/
MPE_Add_RGB_color(graph,red,green,blue,mapping)1110 int MPE_Add_RGB_color( graph, red, green, blue, mapping )
1111 MPE_XGraph graph;
1112 int red, green, blue;
1113 MPE_Color *mapping;
1114 {
1115   XColor colordef;
1116 
1117   if (graph->Cookie != MPE_G_COOKIE) {
1118     fprintf( stderr, "Handle argument is incorrect or corrupted\n" );
1119     return MPE_ERR_BAD_ARGS;
1120   }
1121 
1122   if (graph->xwin->maxcolors == graph->xwin->numcolors)
1123     return -1;
1124 
1125   colordef.red   = red;
1126   colordef.green = green;
1127   colordef.blue  = blue;
1128   colordef.flags = DoRed | DoGreen | DoBlue;
1129   if (!XAllocColor( graph->xwin->disp, graph->xwin->cmap, &colordef ))
1130     return -1;
1131   graph->xwin->cmapping[graph->xwin->maxcolors] = colordef.pixel;
1132   *mapping = (MPE_Color) (graph->xwin->maxcolors++);
1133   if (graph->xwin->maxcolors == 256)
1134     graph->xwin->maxcolors = 255;
1135   return MPE_SUCCESS;
1136 }
1137 
1138 
1139 
MPE_Xerror(int returnVal,const char * functionName)1140 int MPE_Xerror( int returnVal, const char *functionName )
1141 {
1142   if (returnVal) {
1143     switch (returnVal) {
1144     case BadAccess:
1145       fprintf( stderr, "'BadAccess' error in call to %s\n", functionName );
1146       return returnVal;
1147     case BadAlloc:
1148       fprintf( stderr, "'BadAlloc' error in call to %s\n", functionName );
1149       return returnVal;
1150     case BadColor:
1151       fprintf( stderr, "'BadColor' error in call to %s\n", functionName );
1152       return returnVal;
1153     case BadDrawable:
1154       fprintf( stderr, "'BadDrawable' error in call to %s\n", functionName );
1155       return returnVal;
1156     case BadGC:
1157       fprintf( stderr, "'BadGC' error in call to %s\n", functionName );
1158       return returnVal;
1159     case BadMatch:
1160       fprintf( stderr, "'BadMatch' error in call to %s\n", functionName );
1161       return returnVal;
1162     case BadValue:
1163       fprintf( stderr, "'BadValue' error in call to %s\n", functionName );
1164       return returnVal;
1165     default:
1166 /*
1167       fprintf( stderr, "Unknown error %d in call to %s\n",
1168 	       returnVal, functionName );
1169 */
1170       return returnVal;
1171     }
1172   } else {
1173     return MPE_SUCCESS;
1174   }
1175 }
1176 
1177 
Int_CreateList(initialLen)1178 static xpand_list_Int *Int_CreateList(initialLen)
1179 int initialLen;
1180 {
1181   xpand_list_Int *tempPtr;
1182 
1183   if (initialLen < 1) {
1184     initialLen = 10;
1185   }
1186   tempPtr = (xpand_list_Int *) malloc(sizeof(xpand_list_Int));
1187   if (tempPtr) {
1188     tempPtr->list = (int *) malloc(sizeof(int) * initialLen);
1189     if (!tempPtr->list) {
1190       return 0;
1191     }
1192     tempPtr->nused = 0;
1193     tempPtr->size = initialLen;
1194   } else {
1195     fprintf( stderr, "Could not allocate memory for expanding list\n");
1196   }
1197   return tempPtr;
1198 }
1199 
1200 
Int_AddItem(listPtr,newItem)1201 static int Int_AddItem(listPtr, newItem)
1202 xpand_list_Int *listPtr;
1203 int newItem;
1204 {
1205   int *tmp;
1206   if (listPtr->nused == listPtr->size) {
1207     if (listPtr->size < 1)
1208       listPtr->size = 1;
1209     listPtr->size *= 2;
1210     tmp = (int *) malloc( sizeof(int) * listPtr->size);
1211 
1212     if (!tmp) {
1213       fprintf( stderr, "Ran out of memory packing pixels.\n" );
1214       return 1;
1215     } else {
1216       memcpy( tmp, listPtr->list, sizeof(int) * listPtr->size / 2 );
1217       free( listPtr->list );
1218       listPtr->list = tmp;
1219     }
1220   }
1221   listPtr->list[(listPtr->nused)++] = newItem;
1222   return 0;
1223 }
1224