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