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