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