00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055 #include <stdio.h>
00056 #include <X11/IntrinsicP.h>
00057 #include <X11/StringDefs.h>
00058 #include <X11/Xfuncs.h>
00059
00060 #include "UnitStripCharP.h"
00061 #include <X11/Xaw/XawInit.h>
00062 #include "Private.h"
00063 #include "assert.h"
00064 #include "error.h"
00065
00066 #define MS_PER_SEC 1000
00067
00068 #define streq(a, b) (strcmp((a),(b)) == 0)
00069
00070 #ifdef CRAY
00071 #define WORD64
00072 #endif
00073
00074
00075
00076
00077 static void XawUnitStripChartInitialize(Widget, Widget, ArgList, Cardinal*);
00078 static void XawUnitStripChartDestroy(Widget);
00079 static void XawUnitStripChartRedisplay(Widget, XEvent*, Region);
00080 static void XawUnitStripChartResize(Widget);
00081 static Boolean XawUnitStripChartSetValues(Widget, Widget, Widget,
00082 ArgList, Cardinal*);
00083
00084
00085
00086
00087 static void CreateGC(UnitStripChartWidget, unsigned int);
00088 static void DestroyGC(UnitStripChartWidget, unsigned int);
00089 static void draw_it(XtPointer, XtIntervalId*);
00090 static void MoveChart(UnitStripChartWidget);
00091 static void repaint_window(UnitStripChartWidget);
00092
00093
00094
00095
00096 #define offset(field) XtOffsetOf(UnitStripChartRec, field)
00097 static XtResource resources[] = {
00098 {
00099 XtNwidth,
00100 XtCWidth,
00101 XtRDimension,
00102 sizeof(Dimension),
00103 offset(core.width),
00104 XtRImmediate,
00105 (XtPointer)
00106 120
00107 },
00108 {
00109 XtNheight,
00110 XtCHeight,
00111 XtRDimension,
00112 sizeof(Dimension),
00113 offset(core.height),
00114 XtRImmediate,
00115 (XtPointer)120
00116 },
00117 {
00118 XtNupdate,
00119 XtCInterval,
00120 XtRInt,
00121 sizeof(int),
00122 offset(unit_strip_chart.update),
00123 XtRImmediate,
00124 (XtPointer)10
00125 },
00126 {
00127 XtNminScale,
00128 XtCScale,
00129 XtRInt,
00130 sizeof(int),
00131 offset(unit_strip_chart.min_scale),
00132 XtRImmediate,
00133 (XtPointer)1
00134 },
00135 {
00136 XtNforeground,
00137 XtCForeground,
00138 XtRPixel,
00139 sizeof(Pixel),
00140 offset(unit_strip_chart.fgpixel),
00141 XtRString,
00142 XtDefaultForeground
00143 },
00144 {
00145 XtNhighlight,
00146 XtCForeground,
00147 XtRPixel,
00148 sizeof(Pixel),
00149 offset(unit_strip_chart.hipixel),
00150 XtRString,
00151 XtDefaultForeground
00152 },
00153 {
00154 XtNhighlight,
00155 XtCBackground,
00156 XtRPixel,
00157 sizeof(Pixel),
00158 offset(unit_strip_chart.bgpixel),
00159 XtRString,
00160 XtDefaultBackground
00161 },
00162 {
00163 XtNgetValue,
00164 XtCCallback,
00165 XtRCallback,
00166 sizeof(XtPointer),
00167 offset(unit_strip_chart.get_value),
00168 XtRImmediate,
00169 NULL
00170 },
00171 {
00172 XtNjumpScroll,
00173 XtCJumpScroll,
00174 XtRInt,
00175 sizeof(int),
00176 offset(unit_strip_chart.jump_val),
00177 XtRImmediate,
00178 (XtPointer)DEFAULT_JUMP
00179 },
00180 {
00181 XtNfont,
00182 XtCFont,
00183 XtRFontStruct,
00184 sizeof(XFontStruct*),
00185 offset(unit_strip_chart.font),
00186 XtRString,
00187 XtDefaultFont
00188 },
00189 {
00190 XtNfontSet,
00191 XtCFontSet,
00192 XtRFontSet,
00193 sizeof(XFontSet),
00194 offset(unit_strip_chart.fontset),
00195 XtRString,
00196 XtDefaultFontSet
00197 },
00198 {
00199 XtNlabel,
00200 XtCLabel,
00201 XtRString,
00202 sizeof(String),
00203 offset(unit_strip_chart.label),
00204 XtRString,
00205 ""
00206 },
00207 {
00208 XtNunits,
00209 XtCUnits,
00210 XtRString,
00211 sizeof(String),
00212 offset(unit_strip_chart.units),
00213 XtRString,
00214 ""
00215 },
00216 {
00217 XtNencoding,
00218 XtCEncoding,
00219 XtRUnsignedChar,
00220 sizeof(unsigned char),
00221 offset(unit_strip_chart.encoding),
00222 XtRImmediate,
00223 (XtPointer)XawTextEncoding8bit
00224 },
00225 {
00226 XtNjustify,
00227 XtCJustify,
00228 XtRJustify,
00229 sizeof(XtJustify),
00230 offset(unit_strip_chart.justify),
00231 XtRImmediate,
00232 (XtPointer)XtJustifyCenter
00233 },
00234 };
00235 #undef offset
00236
00237 UnitStripChartClassRec unitStripChartClassRec = {
00238
00239 {
00240 (WidgetClass)&simpleClassRec,
00241 "UnitStripChart",
00242 sizeof(UnitStripChartRec),
00243 XawInitializeWidgetSet,
00244 NULL,
00245 False,
00246 XawUnitStripChartInitialize,
00247 NULL,
00248 XtInheritRealize,
00249 NULL,
00250 0,
00251 resources,
00252 XtNumber(resources),
00253 NULLQUARK,
00254 True,
00255 XtExposeCompressMultiple
00256 | XtExposeGraphicsExposeMerged,
00257 True,
00258 False,
00259 XawUnitStripChartDestroy,
00260 XawUnitStripChartResize,
00261 XawUnitStripChartRedisplay,
00262 XawUnitStripChartSetValues,
00263 NULL,
00264 NULL,
00265 NULL,
00266 NULL,
00267 XtVersion,
00268 NULL,
00269 NULL,
00270 XtInheritQueryGeometry,
00271 XtInheritDisplayAccelerator,
00272 NULL,
00273 },
00274
00275 {
00276 XtInheritChangeSensitive,
00277 }
00278 };
00279
00280 WidgetClass unitStripChartWidgetClass = (WidgetClass)&unitStripChartClassRec;
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296 static void
00297 CreateGC(UnitStripChartWidget w, unsigned int which)
00298 {
00299 XGCValues myXGCV;
00300
00301 ASSERT(w != NULL);
00302
00303 if (which & FOREGROUND) {
00304 myXGCV.foreground = w->unit_strip_chart.fgpixel;
00305 w->unit_strip_chart.fgGC = XtGetGC((Widget)w, GCForeground, &myXGCV);
00306 }
00307
00308 if (which & HIGHLIGHT) {
00309 myXGCV.foreground = w->unit_strip_chart.hipixel;
00310 w->unit_strip_chart.hiGC = XtGetGC((Widget)w, GCForeground, &myXGCV);
00311 }
00312
00313 if (which & BACKGROUND) {
00314 myXGCV.foreground = w->core.background_pixel;
00315 w->unit_strip_chart.bgGC = XtGetGC((Widget)w, GCForeground, &myXGCV);
00316 }
00317 }
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330 static void
00331 DestroyGC(UnitStripChartWidget w, unsigned int which)
00332 {
00333 ASSERT(w != NULL);
00334
00335 if (which & FOREGROUND)
00336 XtReleaseGC((Widget)w, w->unit_strip_chart.fgGC);
00337
00338 if (which & HIGHLIGHT)
00339 XtReleaseGC((Widget)w, w->unit_strip_chart.hiGC);
00340
00341 if (which & BACKGROUND)
00342 XtReleaseGC((Widget)w, w->unit_strip_chart.bgGC);
00343 }
00344
00345
00346 static void
00347 XawUnitStripChartInitialize(Widget greq, Widget gnew,
00348 ArgList args, Cardinal *num_args)
00349 {
00350 UnitStripChartWidget w;
00351
00352 ASSERT(gnew != NULL);
00353 ASSERT(num_args != NULL);
00354
00355 w = (UnitStripChartWidget)gnew;
00356
00357 if (w->unit_strip_chart.update > 0)
00358 w->unit_strip_chart.interval_id =
00359 XtAppAddTimeOut(XtWidgetToApplicationContext(gnew),
00360 w->unit_strip_chart.update * MS_PER_SEC,
00361 draw_it, (XtPointer)gnew);
00362 CreateGC(w, ALL_GCS);
00363
00364 w->unit_strip_chart.scale = w->unit_strip_chart.min_scale;
00365 w->unit_strip_chart.interval = 0;
00366 w->unit_strip_chart.max_value = 0.0;
00367 w->unit_strip_chart.points = NULL;
00368 if (w->unit_strip_chart.label == NULL)
00369 w->unit_strip_chart.label = XtNewString("");
00370 else
00371 w->unit_strip_chart.label = XtNewString(w->unit_strip_chart.label);
00372 if (w->unit_strip_chart.units == NULL)
00373 w->unit_strip_chart.units = XtNewString("");
00374 else
00375 w->unit_strip_chart.units = XtNewString(w->unit_strip_chart.units);
00376 XawUnitStripChartResize(gnew);
00377 }
00378
00379 static void
00380 XawUnitStripChartDestroy(Widget gw)
00381 {
00382 UnitStripChartWidget w;
00383
00384 ASSERT(gw != NULL);
00385
00386 w = (UnitStripChartWidget)gw;
00387
00388 XtFree(w->unit_strip_chart.label);
00389 XtFree(w->unit_strip_chart.units);
00390 if (w->unit_strip_chart.update > 0)
00391 XtRemoveTimeOut(w->unit_strip_chart.interval_id);
00392 if (w->unit_strip_chart.points)
00393 XtFree((char *)w->unit_strip_chart.points);
00394 DestroyGC(w, ALL_GCS);
00395 }
00396
00397
00398
00399
00400
00401
00402
00403 static void
00404 XawUnitStripChartRedisplay(Widget w, XEvent *event, Region region)
00405 {
00406 ASSERT(event != NULL);
00407
00408 repaint_window((UnitStripChartWidget)w);
00409 }
00410
00411 static void
00412 MoveChart(UnitStripChartWidget w)
00413 {
00414 int old_max;
00415 int left, i, j;
00416 int next;
00417
00418 ASSERT(w != NULL);
00419
00420 next = w->unit_strip_chart.interval;
00421
00422 if (!XtIsRealized((Widget)w))
00423 return;
00424
00425 if (w->unit_strip_chart.jump_val < 0)
00426 w->unit_strip_chart.jump_val = DEFAULT_JUMP;
00427 if (w->unit_strip_chart.jump_val == DEFAULT_JUMP)
00428 j = XtWidth(w) >> 1;
00429 else {
00430 j = (int)XtWidth(w) - w->unit_strip_chart.jump_val;
00431 if (j < 0)
00432 j = 0;
00433 }
00434
00435 ASSERT(next - j < NUM_DATA_POINTS);
00436 (void)memmove(
00437 (char *)w->unit_strip_chart.valuedata,
00438 (char *)(w->unit_strip_chart.valuedata + next - j),
00439 j * sizeof(int)
00440 );
00441 next = w->unit_strip_chart.interval = j;
00442
00443
00444
00445
00446
00447 old_max = w->unit_strip_chart.max_value;
00448 w->unit_strip_chart.max_value = 0.0;
00449 ASSERT(next < NUM_DATA_POINTS);
00450 for (i = 0; i < next; i++) {
00451 if (w->unit_strip_chart.valuedata[i] > w->unit_strip_chart.max_value)
00452 w->unit_strip_chart.max_value = w->unit_strip_chart.valuedata[i];
00453 }
00454 }
00455
00456
00457 static void
00458 draw_it(XtPointer client_data, XtIntervalId *id)
00459 {
00460 UnitStripChartWidget w;
00461 int value;
00462
00463 ASSERT(client_data != NULL);
00464
00465 w = (UnitStripChartWidget)client_data;
00466
00467 ASSERT(w != NULL);
00468
00469 if (w->unit_strip_chart.update > 0)
00470 w->unit_strip_chart.interval_id =
00471 XtAppAddTimeOut(
00472 XtWidgetToApplicationContext((Widget)w),
00473 w->unit_strip_chart.update * MS_PER_SEC,draw_it,
00474 client_data
00475 );
00476
00477 if (w->unit_strip_chart.interval >= XtWidth(w)) {
00478 MoveChart((UnitStripChartWidget)w);
00479 XClearWindow(XtDisplay(w), XtWindow(w));
00480 repaint_window(w);
00481 }
00482
00483
00484 if (w->unit_strip_chart.get_value == NULL)
00485 return;
00486
00487 ASSERT(w != NULL);
00488
00489 XtCallCallbacks((Widget)w, XtNgetValue, (XtPointer)&value);
00490
00491 if (w == NULL) {
00492 if (client_data != NULL) {
00493 w = (UnitStripChartWidget)client_data;
00494 }
00495 else {
00496 INTERNAL_ERROR("w == NULL");
00497 return;
00498 }
00499 }
00500 ASSERT(w != NULL);
00501
00502 ASSERT(w->unit_strip_chart.interval < NUM_DATA_POINTS);
00503
00504 w->unit_strip_chart.valuedata[w->unit_strip_chart.interval] = value;
00505 if (value > w->unit_strip_chart.max_value)
00506 w->unit_strip_chart.max_value = value;
00507
00508 repaint_window(w);
00509 XFlush(XtDisplay(w));
00510 w->unit_strip_chart.interval++;
00511 }
00512
00513 static void
00514 repaint_window(UnitStripChartWidget w)
00515 {
00516 int i, j;
00517 double scale = w->unit_strip_chart.scale;
00518 int scalewidth = 0;
00519 int multiplier;
00520
00521 ASSERT(w != NULL);
00522
00523
00524
00525 if (w->unit_strip_chart.interval != 0 || scale <= w->unit_strip_chart.max_value)
00526 scale = w->unit_strip_chart.max_value + 1;
00527 multiplier = 1;
00528 while (scale > 100) {
00529 scale /= 10;
00530 multiplier *= 10;
00531 }
00532 while (scale > 10) {
00533 scale /= 2;
00534 multiplier *= 2;
00535 }
00536 if (scale < w->unit_strip_chart.min_scale)
00537 scale = w->unit_strip_chart.min_scale;
00538
00539 if (scale != w->unit_strip_chart.scale) {
00540 w->unit_strip_chart.scale = scale;
00541
00542 XawUnitStripChartResize((Widget)w);
00543
00544 if (XtIsRealized((Widget)w))
00545 XClearWindow(XtDisplay(w), XtWindow(w));
00546 }
00547
00548 if (XtIsRealized((Widget)w)) {
00549 Display *dpy = XtDisplay(w);
00550 Window win = XtWindow(w);
00551 static char text[1025] = { 0 };
00552 int multiplier_units = 0;
00553 char *multiplier_units_chars = " KMGTPE\0";
00554 char units_char;
00555 static char numstr[10] = { 0 };
00556 int cx, cy;
00557
00558
00559 ASSERT(XtWidth(w) < NUM_DATA_POINTS);
00560 for (i = 0; i < XtWidth(w); i++) {
00561 int widget_height = XtHeight(w);
00562 int y;
00563 int div;
00564
00565 y = widget_height * w->unit_strip_chart.valuedata[i];
00566 div = multiplier * scale;
00567 y /= div;
00568
00569 ASSERT(y <= widget_height);
00570
00571 XFillRectangle(dpy, win, w->unit_strip_chart.fgGC,
00572 i, XtHeight(w)-y, 1, XtHeight(w));
00573 }
00574
00575
00576 for (i = 1; i < w->unit_strip_chart.scale; i++) {
00577 j = i * ((int)XtHeight(w) / w->unit_strip_chart.scale);
00578 XDrawLine(dpy, win, w->unit_strip_chart.hiGC, 0, j, XtWidth(w), j);
00579 }
00580
00581
00582 if (strlen(w->unit_strip_chart.units)) {
00583 while (multiplier > 1000) {
00584 multiplier /= 1000;
00585 multiplier_units++;
00586 }
00587 if (multiplier_units <= strlen(multiplier_units_chars))
00588 units_char = multiplier_units_chars[multiplier_units];
00589 else
00590 units_char = '?';
00591 snprintf(numstr, 9, "%d", multiplier);
00592 snprintf(text, 1024, "%3.3s%c%s",
00593 numstr, units_char, w->unit_strip_chart.units);
00594
00595 for (cy = -3; cy < 4; cy++) {
00596 for (cx = -3; cx < 4; cx++) {
00597 XmbDrawString(XtDisplay(w), XtWindow(w),
00598 w->unit_strip_chart.fontset,
00599 w->unit_strip_chart.bgGC,
00600 5+cx, XtHeight(w)-5+cy,
00601 text, strlen(text));
00602 }
00603 }
00604
00605 XmbDrawString(XtDisplay(w), XtWindow(w),
00606 w->unit_strip_chart.fontset,
00607 w->unit_strip_chart.hiGC,
00608 5, XtHeight(w)-5,
00609 text, strlen(text));
00610 }
00611 }
00612 }
00613
00614
00615 static Boolean
00616 XawUnitStripChartSetValues(Widget current, Widget request, Widget cnew,
00617 ArgList args, Cardinal *num_args)
00618 {
00619 UnitStripChartWidget old = (UnitStripChartWidget)current;
00620 UnitStripChartWidget w = (UnitStripChartWidget)cnew;
00621 Bool ret_val = False;
00622 unsigned int new_gc = NO_GCS;
00623
00624 ASSERT(current != NULL);
00625 ASSERT(cnew != NULL);
00626
00627 old = (UnitStripChartWidget)current;
00628 w = (UnitStripChartWidget)cnew;
00629
00630 ASSERT(old != NULL);
00631 ASSERT(w != NULL);
00632
00633 if (w->unit_strip_chart.update != old->unit_strip_chart.update) {
00634 if (old->unit_strip_chart.update > 0)
00635 XtRemoveTimeOut(old->unit_strip_chart.interval_id);
00636 if (w->unit_strip_chart.update > 0)
00637 w->unit_strip_chart.interval_id =
00638 XtAppAddTimeOut(
00639 XtWidgetToApplicationContext(cnew),
00640 w->unit_strip_chart.update * MS_PER_SEC,
00641 draw_it, (XtPointer)w
00642 );
00643 }
00644
00645 if (w->unit_strip_chart.min_scale > w->unit_strip_chart.max_value + 1)
00646 ret_val = True;
00647
00648 if (w->unit_strip_chart.fgpixel != old->unit_strip_chart.fgpixel) {
00649 new_gc |= FOREGROUND;
00650 ret_val = True;
00651 }
00652
00653 if (w->unit_strip_chart.hipixel != old->unit_strip_chart.hipixel) {
00654 new_gc |= HIGHLIGHT;
00655 ret_val = True;
00656 }
00657
00658 if (w->unit_strip_chart.bgpixel != old->unit_strip_chart.bgpixel) {
00659 new_gc |= BACKGROUND;
00660 ret_val = True;
00661 }
00662
00663 DestroyGC(old, new_gc);
00664 CreateGC(w, new_gc);
00665
00666 return (ret_val);
00667 }
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679 static void
00680 XawUnitStripChartResize(Widget widget)
00681 {
00682 UnitStripChartWidget w;
00683 XPoint *points;
00684 Cardinal size;
00685 int i;
00686 static int old_width = 0;
00687
00688 ASSERT(widget != NULL);
00689
00690 w = (UnitStripChartWidget)widget;
00691
00692 ASSERT(w != NULL);
00693
00694 if (w->unit_strip_chart.scale <= 1) {
00695 XtFree((char *)w->unit_strip_chart.points);
00696 w->unit_strip_chart.points = NULL;
00697 return;
00698 }
00699
00700 size = sizeof(XPoint) * (w->unit_strip_chart.scale - 1);
00701
00702 points = (XPoint *)XtRealloc((XtPointer)w->unit_strip_chart.points, size);
00703
00704 ASSERT(points != NULL);
00705
00706 w->unit_strip_chart.points = points;
00707
00708
00709
00710 for (i = 1; i < w->unit_strip_chart.scale; i++) {
00711 points[i - 1].x = 0;
00712 points[i - 1].y = XtHeight(w) / w->unit_strip_chart.scale;
00713 }
00714
00715 if (old_width != XtWidth(w)) {
00716 for (i = w->unit_strip_chart.interval+1; i < NUM_DATA_POINTS; i++) {
00717 w->unit_strip_chart.valuedata[i] = 0;
00718 }
00719 old_width = XtWidth(w);
00720 }
00721 }