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