No restriction on number of resources but a warning message if numRes > 15.
[dyninst.git] / visiClients / terrain / src / terrain.c
1 /*-----------------------------------------------------------------------------
2  *   gnuplot_x11 - X11 outboard terminal driver for gnuplot 2
3  *
4  *   Requires installation of companion inboard x11 driver in gnuplot/term.c
5  *
6  *   Acknowledgements: 
7  *      Chris Peterson (MIT) - original Xlib gnuplot support (and Xaw examples)
8  *      Dana Chee (Bellcore)  - mods to original support for gnuplot 2.0
9  *      Arthur Smith (Cornell) - graphical-label-widget idea (xplot)
10  *      Hendri Hondorp (University of Twente, The Netherlands) - Motif xgnuplot
11  *
12  *   This code is provided as is and with no warranties of any kind.
13  *       
14  *   Ed Kubaitis - Computing Services Office -  University of Illinois, Urbana
15  *---------------------------------------------------------------------------*/
16
17 /*
18  * Modified for terrain plot:
19  *      Chi-Ting Lam
20  *
21  */
22
23 #ifndef lint
24 static char rcsid[] = "@(#) $Header: /home/jaw/CVSROOT_20081103/CVSROOT/core/visiClients/terrain/src/terrain.c,v 1.8 1997/05/21 21:14:33 tung Exp $";
25 #endif
26
27 /*
28  * terrain.c - main entry point and x driver.
29  *
30  * $Log: terrain.c,v $
31  * Revision 1.8  1997/05/21 21:14:33  tung
32  * No restriction on number of resources but a warning message if numRes > 15.
33  *
34  * Revision 1.6  1997/05/21 02:27:30  tung
35  * Revised.
36  *
37  * Revision 1.5  1997/05/20 08:29:20  tung
38  * Revised on resizing the maxZ, change the xlabel and zlabel format.
39  *
40  * Revision 1.4  1997/05/20 01:29:25  tung
41  * put up the paradyn logo.
42  *
43  * Revision 1.3  1997/05/19 19:43:07  tung
44  * Make the axis appears before the curve surface shows up.
45  *
46  * Revision 1.2  1997/05/18 22:50:11  tung
47  * Eliminate ips dependent library files.
48  *
49  * Revision 1.1  1997/05/12 20:15:44  naim
50  * Adding "Terrain" visualization to paradyn (commited by naim, done by tung).
51  *
52  * Revision 1.2  1992/05/19  17:37:04  lam
53  * Added call to initialize pop up message windows.
54  *
55  * Revision 1.1  1992/05/19  06:30:55  lam
56  * Initial revision
57  *
58  *
59  */
60
61 #include <stdio.h>
62 #include <stdlib.h>
63 #include <signal.h>
64 #include <math.h>
65 #include <assert.h>
66 #include <string.h>
67
68
69 #define Ncolors 11              /* Number of colors for GNUPlot part */
70
71 #include "terrain.h"
72 #include "term.h"
73 #include "form.h"
74 #include "command.h"
75 #include "misc.h"
76 #include "visi/h/visualization.h" 
77
78 unsigned long colors[Ncolors];  /* Colors for GNUPlot part */
79 char color_keys[Ncolors][30] =   { "text", "border", "axis", 
80    "line1", "line2", "line3", "line4", "line5", "line6", "line7", "line8" };
81 char color_values[Ncolors][30] = { "black", "black", "black", 
82    "red",  "black", "blue",  "magenta", "cyan", "sienna", "orange", "coral" };
83
84 int color_disp = 0;             /* Do we have a color display? */
85 int Ntcolors=25;                /* Number of color used by terrain */
86 unsigned long *tcolors;         /* The colors used by terrain */
87
88 /* Line stypes */
89
90 char dashes[10][5] = { {0}, {1,6,0}, 
91    {0}, {4,2,0}, {1,3,0}, {4,4,0}, {1,5,0}, {4,4,4,1,0}, {4,2,0}, {1,3,0}
92    };
93
94 Widget w_top,                   /* Top level application widget */
95        w_label;                 /* The main viewer window */
96 Window win;                     /* Which window we are in */
97 Display *dpy;                   /* Which display we are in */
98 Pixmap pixmap;                  /* The drawing area in the main viewer */
99 GC gc = (GC)NULL;
100 Dimension W = 700, H = 450, D = 0; /* Initial dimension of terrain window */
101 Arg args[5];
102
103 static void resize();
104
105 int cx=0, cy=0, vchar, nc = 0;  /* Char location, size, length, etc */
106
107 int cur_lt;                     /* What kind of line we are using */
108
109 float xscale, yscale;           /* GNUPlot rescale the plot to fit the */
110                                 /* window before actually drawing      */
111 enum JUSTIFY { LEFT, CENTRE, RIGHT } jmode; /* How texts are drawn */
112
113 RValues rv;
114
115 XtResource resources[] = {
116    { XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *), 
117      XtOffset(RVptr, font), XtRString, "fixed" },
118    { XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel), 
119      XtOffset(RVptr, fg), XtRString, "black" },
120    { XtNbackground, XtCBackground, XtRPixel, sizeof(Pixel), 
121      XtOffset(RVptr, bg), XtRString, "white" },
122    };
123
124 /* New action to tell terrain to draw shadow plot when rotating */
125 XtActionProc NotifyEndThumb();
126
127 XtActionsRec actionTable[] = {
128    { "NotifyEndThumb", NotifyEndThumb }
129 };
130  
131
132
133 /***********************************************************************************
134  ************************* modified section starts *********************************/
135
136 /*
137  * default resources
138  */
139
140 String fallback_resources[] = { 
141  "*background: Grey",
142  "*foreground: Black",
143  "*font: *-Helvetica-*-r-*-12-*",
144  "*titlebar*font: *-New*Century*Schoolbook-Bold-R-*-18-*",
145  "*titlebar*background: Red",
146  "*titlebar*foreground: White",
147  "*logo*background: White",
148  "*logo*foreground: #c06077",
149  "*title*font: *-New*Century*Schoolbook-*-R-*-14-*",
150  NULL,
151 };
152
153 static int numGroups;
154 static int phase_displayed;
155 static Widget input;
156 static int numRes;
157
158 struct HistData {
159     int      curve_id;
160     unsigned prev_last;
161     char*    title;
162     unsigned metric;
163     unsigned resource;
164     int      groupId;
165 };
166
167 static int get_groupId(const char *axis_label){
168
169   int id = -1;
170   struct HistData* hdp = 0;
171   const char *temp;
172   int m, r;
173
174   for (m = 0; m < 1; m++) {
175      temp = visi_MetricLabel(m);
176      for (r = 0; r < numRes; r++) {
177         if(visi_Enabled(m,r)){
178            if(strcmp(temp,axis_label) == 0){
179               hdp = (struct HistData *)visi_GetUserData(m,r);
180               if(hdp){
181                 id =  hdp->groupId;
182                 break;
183               }
184            }
185         }
186   }}
187
188   if(id == -1){  // create a new group number
189     id = numGroups++;
190   }
191
192   return(id);
193
194 }
195
196
197 static int add_new_curve(unsigned m, unsigned r)
198 {
199   struct HistData* hdp = 0;
200 //  float* data;
201 //  float zero;
202   char* m_name;
203   char* r_name;
204   char* p_name;
205
206     if (visi_Enabled((signed)m,(signed)r) &&
207        (hdp = (struct HistData *) visi_GetUserData((signed)m,(signed)r)) == 0) {
208
209         hdp = (struct HistData *) malloc(sizeof(struct HistData));
210         assert(hdp);
211
212         hdp->curve_id  = -1;
213         hdp->groupId  = -1;
214         hdp->prev_last = 0;
215         hdp->metric    = m;
216         hdp->resource  = r;
217
218         m_name = visi_MetricName((signed)m);
219         r_name = visi_ResourceName((signed)r);
220         p_name = visi_GetMyPhaseName();
221
222         m_name = (m_name) ? (m_name) : "";
223         r_name = (r_name) ? (r_name) : "";
224
225         hdp->title   = (char *) malloc(strlen(m_name)+strlen(r_name)+4);
226         assert(hdp->title);
227         sprintf(hdp->title, "%s <%s>", m_name, r_name);
228
229
230         hdp->groupId = get_groupId(visi_MetricLabel((signed)m));
231
232         hdp->curve_id = Graph3DAddNewCurve(m_name, r_name, p_name, 
233                                            visi_MetricLabel((signed)m),  
234                                            visi_NumBuckets(), numRes);
235
236         visi_SetUserData((signed)m,(signed)r,(void *) hdp);
237
238    }
239     
240    return 0;
241
242
243
244 }
245
246
247
248
249
250 static void drawData(int is_fold)
251 {
252     struct HistData* hdp;
253     int m, r;
254     float *data;
255
256     for (m = 0; m < 1; m++) {
257 //       if (visi_NumResources() > 15)
258 //        numRes = 11;
259 //       else
260           numRes = visi_NumResources();
261
262         for (r = 0; r < numRes; r++) {
263          if (!visi_Valid(m,r)) {  // invalid histo-cell
264                 continue;
265          }
266             // this curve was previously deleted and now has new data
267             // need to add new curve to histogram widget
268          if((hdp = (struct HistData *) visi_GetUserData((signed)m,(signed)r)) == 0){
269                 add_new_curve((unsigned)m, (unsigned)r);
270                 hdp = (struct HistData *) visi_GetUserData((signed)m,(signed)r);
271                 assert(hdp);
272          }
273          
274          data = visi_DataValues(m,r);
275
276             //
277             // why is this being set everytime not just outside the loop ???
278             // jkh 5/2/94
279
280             // TODO: set start time to real start time rather that 0.0
281             // HistSampleInfo(hw, BucketWidth(), NumBuckets(),
282             // 0.0, FALSE);
283
284          if (is_fold) {
285                 Graph3DSetCurveData(hdp->curve_id,0,
286                                  visi_LastBucketFilled(m,r),data, visi_GetStartTime(), 
287                                  visi_BucketWidth(), is_fold,
288                                  color_disp, dpy, gc, rv, pixmap, W, H, win);
289          } 
290          else {
291
292                 Graph3DSetCurveData(hdp->curve_id, 
293                                     hdp->prev_last,
294                                     visi_LastBucketFilled(m,r) - hdp->prev_last,
295                                     &(data[hdp->prev_last]), visi_GetStartTime(), 
296                                     visi_BucketWidth(), is_fold,
297                                     color_disp, dpy, gc, rv, pixmap, W, H, win);
298         
299          }
300          hdp->prev_last = visi_LastBucketFilled(m,r);
301        }
302      }
303
304       
305    return;
306
307
308
309   
310 }
311
312
313 /* Event Handler to process new values from the visilib */
314 static int process_datavalues(int parameter)
315 {
316   static int checkError = 1;
317   
318   /* check for errors for datas come in at the first time */
319   if (checkError == 1)  
320   {
321      if (visi_NumMetrics() != 1)
322         visi_showErrorVisiCallback("Please select only one metric for the 3D Histogram.\nOnly one of the metrics selected will be shown.");
323
324      if (visi_NumResources() < 2)
325          visi_showErrorVisiCallback("Please select more than one resource for the 3D Histogram.\nNo curve will be shown.");
326
327      if (visi_NumResources() > 15)
328         visi_showErrorVisiCallback("It's advised to have fewer than 15 curves.");
329
330      checkError = 0;
331   }
332
333   /* get and draw the graph */
334   drawData(0);
335
336   return 0;
337
338 }
339
340
341
342 /* Event Handler to process new values from the visilib */
343 static int process_fold(int parameter)
344 {
345
346    /* get and draw the graph */
347    drawData(1);
348
349    
350    return 0;
351
352 }
353
354 /**************************modified section ends ************************************
355  ************************************************************************************/
356
357 /*-----------------------------------------------------------------------------
358  *   display - display accumulated commands from inboard driver
359  *---------------------------------------------------------------------------*/
360 void displayScreen(int action)
361 {
362     display(action);
363 }
364
365
366 int display(int action)
367 {
368    /* clean the screen when ReDisplay the Graph is needed */
369    #ifndef MOTIF
370    if (color_disp) { /* Athena needs different erase for color and mono */
371    #endif
372       XSetForeground(dpy, gc, rv.bg);
373       XFillRectangle(dpy, win, gc, 0, 0, W, H);
374       XFillRectangle(dpy, pixmap, gc, 0, 0, W, H);
375       XSetForeground(dpy, gc, rv.fg);
376       XSetBackground(dpy, gc, rv.bg);
377    #ifndef MOTIF
378    }
379    else {
380       XSetFunction(dpy, gc, GXxor);
381       XCopyArea(dpy, win, win, gc, 0, 0, W, H, 0, 0);
382       XSetFunction(dpy, gc, GXcopyInverted);
383    }
384    #endif
385
386
387    /* get and draw the graph */
388    plot3drequest(action); 
389
390    /* trigger expose events to display pixmap */
391    XClearArea(dpy, win, 0, 0, 0, 0, True);
392
393    return 0;
394 }
395
396
397
398 /*************************************************************************
399 * resize - Called by X when the window got resized.  It make a new pixmap
400 *          according to the new size of the main viewer, and redraw the
401 *          terrain in it.
402 *
403 *************************************************************************/
404
405
406 static void
407 resize(w, cd, e) 
408 Widget w;
409 char *cd;
410 XConfigureEvent *e; {
411    if (e->type != ConfigureNotify) return;
412    W = e->width; H = e->height;
413
414    init_pixmap();
415
416    display(SA_RESIZE); 
417
418
419 }
420
421
422 /*************************************************************************
423 *
424 * init_pixmap - Create a pixmap corresponding to the current size of the
425 *               main viewer.
426 *
427 *************************************************************************/
428
429 int init_pixmap()
430 {
431    /* set scaling factor between internal driver & window geometry */
432    xscale = (float)W / 4096.;  yscale = (float)H / 4096.;  
433
434    /* create new pixmap & GC */
435    if (gc) { XFreeGC(dpy, gc); XFreePixmap(dpy, pixmap); }
436    pixmap = XCreatePixmap(dpy, RootWindow(dpy,DefaultScreen(dpy)), W, H, D);
437    gc = XCreateGC(dpy, win, 0, NULL);
438    XSetFont(dpy, gc, rv.font->fid);
439
440    /* the display belongs to w_label */
441    XtSetArg(args[0], XtNbitmap, pixmap);
442    XtSetValues(w_label, args, (Cardinal)1);
443
444
445    return 0;
446 }
447
448
449
450
451 /*************************************************************************
452 *
453 * X11_vector - used by GNUPlot to draw axis and the base lines.
454 *
455 *************************************************************************/
456
457 int X11_vector(unsigned int x, unsigned int y)
458 {
459       XDrawLine(dpy, win, gc, X(cx), Y(cy), X(x), Y(y));
460
461    XDrawLine(dpy, pixmap, gc, X(cx), Y(cy), X(x), Y(y));
462    cx = x; cy = y;
463
464   return 0;
465 }
466
467
468 /*************************************************************************
469 *
470 * X11_move - used by GNUPlot to draw axis and the base lines.
471 *
472 *************************************************************************/
473
474 int X11_move(unsigned int x, unsigned int y)
475 {
476    cx = x; cy = y;
477
478    return 0;
479 }
480
481
482
483 /*************************************************************************
484 *
485 * X11_put_text - put a string to the specified location in the main viewer
486 *
487 *************************************************************************/
488
489 int X11_put_text(unsigned int x, unsigned int y, char *str)
490 {
491    int sw, sl;
492    sl = strlen(str);
493    sw = XTextWidth(rv.font, str, sl);
494
495    switch(jmode) {
496       case LEFT:   sw = 0;     break;
497       case CENTRE: sw = -sw/2; break;
498       case RIGHT:  sw = -sw;   break;
499    }
500
501    if (!color_disp) 
502    {
503          XDrawString(dpy, win, gc, X(x)+sw, Y(y)+vchar/3, str, sl);
504
505       XDrawString(dpy, pixmap, gc, X(x)+sw, Y(y)+vchar/3, str, sl);
506    }
507    else { 
508       XSetForeground(dpy, gc, colors[0]);
509          XDrawString(dpy, win, gc, X(x)+sw, Y(y)+vchar/3, str, sl);
510
511       XDrawString(dpy, pixmap, gc, X(x)+sw, Y(y)+vchar/3, str, sl);
512       XSetForeground(dpy, gc, colors[cur_lt+1]);
513    }
514
515    return 0;
516 }
517
518
519
520 /*************************************************************************
521 *
522 * X11_justify_text - Set the justify (left, right, middle) mode when
523 *                    drawing text.
524 *
525 *************************************************************************/
526
527 int X11_justify_text(enum JUSTIFY mode)
528 {
529    jmode = mode;
530    return 1;
531 }
532
533
534
535
536 /*************************************************************************
537 *
538 * X11_linetype - Set the current line type.
539 *
540 *************************************************************************/
541
542 int X11_linetype(int lt)
543
544    int width, type;
545
546     lt = (lt+2)%10;
547     width = (lt == 0) ? 2 : 0;
548     if (color_disp) {
549         if (lt != 1) 
550             type = LineSolid;
551         else {
552             type = LineOnOffDash;
553             XSetDashes(dpy, gc, 0, dashes[lt], (signed)strlen(dashes[lt]));
554         }
555         XSetForeground(dpy, gc, colors[lt+1]);
556     } else {
557         type  = (lt == 0 || lt == 2) ? LineSolid : LineOnOffDash;
558         if (dashes[lt][0])
559             XSetDashes(dpy, gc, 0, dashes[lt], (signed)strlen(dashes[lt]));
560     }
561     XSetLineAttributes( dpy,gc, (unsigned)width, type, CapButt, JoinBevel);
562
563     cur_lt = lt;
564
565     return 0;
566 }
567
568
569
570
571
572 /*************************************************************************
573 *
574 * hsv2Rgb - convert a color in HSV system into RGB system.
575 *           X11R5 should do a better job than this, but R4 does not even
576 *           have this kind of functions.
577 *           The algorithm can be found in many graphic text books.
578 *
579 *************************************************************************/
580
581
582 int hsv2Rgb(hue, val, sat, rgb)
583 float hue, val, sat;
584 XColor *rgb;
585 {
586    float minCol;
587
588    hue = (hue/360.0 - ((int)hue)/360)*360.0;
589    minCol = val * (1.0 - sat);
590    if (hue <= 120.0) {
591       rgb->green = minCol;
592       if (hue <= 60.0) {
593          rgb->red = val;
594          rgb->blue = minCol + hue * (val - minCol)/(120.0 - hue);
595       } else {
596          rgb->blue = val;
597          rgb->red = minCol + (120.0 - hue) * (val - minCol)/hue;
598       }
599    } else if (hue <= 240.0) {
600       rgb->red = minCol;
601       if (hue <= 180.0) {
602          rgb->blue = val;
603          rgb->green = minCol + (hue - 120.0) * (val - minCol)/(240 - hue);
604       } else {
605          rgb->green = val;
606          rgb->blue = minCol + (240.0 - hue) * (val - minCol)/(hue - 120.0);
607       }
608    } else {
609       rgb->blue = minCol;
610       if (hue <= 300.0) {
611          rgb->green = val;
612          rgb->red = minCol + (hue - 240.0) * (val - minCol)/(360.0 - hue);
613       } else {
614          rgb->red = val;
615          rgb->green = minCol + (360.0 - hue) * (val - minCol)/(hue - 240.0);
616       }
617    }
618
619    return 0;
620
621 }
622
623
624
625
626 /*************************************************************************
627 *
628 * NotifyEndThumb - An application action which enable terrain to tell the
629 *                  difference between jumping and smooth rotating.
630 *                  (Xaw does not have enough action to do this)
631 *
632 *************************************************************************/
633
634
635 XtActionProc
636 NotifyEndThumb(w, event, params, num_params)
637 Widget w;
638 XEvent *event;
639 String *params;
640 Cardinal *num_params;
641 {
642    display(SA_JUMP);
643 }
644
645
646 /*************************************************************************
647 * The following dummy rotines keeps GNUPlot happy
648 *************************************************************************/
649
650 int X11_init()
651 {
652   return 0;
653 }
654
655 int X11_reset()
656 {
657   return 0;
658 }
659
660 int X11_graphics()
661 {
662   return 0;
663 }
664
665 int X11_text()
666 {
667   return 0;
668 }
669
670
671
672
673 /*-----------------------------------------------------------------------------
674  *   main program - fire up application and callbacks
675  *---------------------------------------------------------------------------*/
676
677 int main(int argc, char *argv[])
678 {
679    float colStep;
680
681    XtAppContext app_con;        /* Application context */ 
682
683 /***********************************************************************************
684  ************************* modified section starts *********************************/
685  
686 //   int l, r;
687    int fd;
688
689    fd = visi_Init();
690    if (fd < 0)
691    {
692       fprintf(stderr, "error initializing Visi library\n");
693       exit(-1);
694    }
695    
696    phase_displayed = 0;
697    numGroups = 0;
698
699 /**************************modified section ends ************************************
700  ************************************************************************************/
701
702    signal(SIGINT, SIG_IGN);
703    signal(SIGTSTP, SIG_IGN);
704
705
706
707    /* initialize application */
708    w_top = XtAppInitialize(&app_con, "Terrain", NULL, ZERO, &argc, argv,
709                            fallback_resources, NULL, ZERO);
710
711    /* Initialize application action for scroll bar jump clean-ups */
712    XtAppAddActions(app_con, actionTable, ONE);
713
714    /* Initialize the frame */
715    w_label = (Widget) createForm(w_top, H, W);
716
717    tcolors = (unsigned long*)terrain_alloc(sizeof(unsigned long) * Ntcolors);
718
719    /* Don't display the window until it is ready */
720    XtSetMappedWhenManaged(w_top, False);
721    XtRealizeWidget(w_top);
722
723
724    /* extract needed information */
725    dpy = XtDisplay(w_top); win = XtWindow(w_label);
726
727    /* Do we have enough colors? */
728    color_disp = (XDisplayCells(dpy, DefaultScreen(dpy)) > 40);
729    if (color_disp)
730        D = DefaultDepth(dpy, DefaultScreen(dpy));
731    else
732        D = 1;
733
734    if (color_disp) {
735       char option[20], *value; 
736       XColor used, exact; 
737       int n;
738
739       /* Allocate colors for old GNUPlot stuffs */
740       for(n=0; n<Ncolors; n++) {
741          strcpy(option, color_keys[n]);
742          strcat(option, "Color");
743          value = XGetDefault(dpy, "terrain", option);
744          if (!value) { value = color_values[n]; }
745          if (XAllocNamedColor(dpy, DefaultColormap(dpy,0), value, &used,&exact))
746             colors[n] = used.pixel; 
747          else {
748             fprintf(stderr, "terrain: cannot allocate %s:%s\n", option, value);
749             fprintf(stderr, "terrain: assuming %s:black\n", option);
750             colors[n] = BlackPixel(dpy,0);
751          }
752       }
753
754       /* Allocate a spectum of colors for Terrain Plot */
755
756       colStep = 330.0/(float) Ntcolors;
757
758       for(n=0; n<Ntcolors; n++) {
759         hsv2Rgb(((float) n)*colStep+75.0, 65535.0, 0.75, &used);
760
761         if (XAllocColor(dpy, DefaultColormap(dpy,0), &used)) {
762            tcolors[n] = used.pixel;
763 /*
764            fprintf(stderr, "R=%u, G=%u, B=%u\n", used.red, used.green, used.blue);
765 */
766         } else {
767            fprintf(stderr, "Warning: cannot allocate color R=%u, B=%u\n", used.red, used.blue);
768            tcolors[n] = WhitePixel(dpy,0);
769         }
770       }
771    }
772
773    XtSetArg(args[0], XtNwidth, &W);
774    XtSetArg(args[1], XtNheight,&H);
775    XtGetValues(w_label, args, (Cardinal)2);
776    XtGetApplicationResources(w_top, &rv, resources, XtNumber(resources),NULL,0);
777    vchar = (rv.font->ascent + rv.font->descent);
778
779    /* add callbacks on window-resized */
780    XtAddEventHandler(w_label, StructureNotifyMask, FALSE, resize, NULL);
781    
782
783
784 /***********************************************************************************
785  ************************* modified section starts *********************************/
786   
787   (void) visi_RegistrationCallback(DATAVALUES, process_datavalues);
788   (void) visi_RegistrationCallback(FOLD,       process_fold);
789
790   XtAppAddInput(app_con, fd, XtInputReadMask, visi_callback, input);
791
792
793 /**************************modified section ends ************************************
794  ************************************************************************************/
795
796    /* Initialize terminal */
797    change_term("x11", 3);
798
799    /* PopUpInit(); */
800    
801
802    /* Create and display the graph */
803    init_pixmap();
804
805    /* Clean the screen when starts up */
806    #ifndef MOTIF
807    if (color_disp) { /* Athena needs different erase for color and mono */
808    #endif
809       XSetForeground(dpy, gc, rv.bg);
810       XFillRectangle(dpy, win, gc, 0, 0, W, H);
811       XFillRectangle(dpy, pixmap, gc, 0, 0, W, H);
812       XSetForeground(dpy, gc, rv.fg);
813       XSetBackground(dpy, gc, rv.bg);
814    #ifndef MOTIF  
815       }
816    else {
817       XSetFunction(dpy, gc, GXxor);
818       XCopyArea(dpy, win, win, gc, 0, 0, W, H, 0, 0);
819       XCopyArea(dpy, pixmap, pixmap, gc, 0, 0, W, H, 0, 0);
820       XSetFunction(dpy, gc, GXcopyInverted);
821       }
822    #endif
823
824    XtMapWidget(w_top);
825
826    XtAppMainLoop(app_con);
827
828    return 0;
829 }
830