This is Chart.c in view mode; [Download] [Up]
#if ( !defined(lint) && !defined(SABER)) static char PCN_rcsid[] = "$Header: /ufs/comp/mei/PROJ_PCN/onprofile/IFModel/Xsw/RCS/Chart.c,v 1.1 1992/04/17 18:21:53 mei Exp $"; #endif /****************************************************************************** * * * Copyright (C) The Aerospace Corporation 1991 * * * * This software was developed by The Aerospace Corporation as a * * research endeavor for the United States Air Force * * Space Systems Division. The current version of the Gauge * * computer program is available for release to you for * * educational and research purposes only. It is not * * to be used for commercial purposes. * * * * In addition, the following conditions shall apply. * * * * 1) The computer software and documentation were designed to * * satisfy internal Aerospace requirements only. * * The software is provided ``as is,'' and The Aerospace Corporation * * makes no warranty, expressed or implied, as to it accuracy, * * functioning, or fitness for a particular purpose. * * * * 2) The Aerospace Corporation and its personnel are not * * responsible for providing technical support or general assistance * * with respect to the software. * * * * 3) Neither The Aerospace Corporation nor its personnel shall be * * liable for claims, losses, or damages arising out of or connected * * with the use of this software. * * Your sole and exclusive remedy shall be to request a replacement * * copy of the program. * * * ******************************************************************************/ /* * Chart.c - chart widget. */ #include <X11/IntrinsicP.h> #include "Xsw.h" #include <string.h> #include "ChartP.h" #include "Patterns.h" #define DEFAULT_CHART_WIDTH 32 /* in cells */ #define DEFAULT_CHART_HEIGHT 32 /* in cells */ #define DEFAULT_CELL_SIZE 16 /* in pixels */ static XtResource resources[] = { #define offset(field) XtOffset(ChartWidget, chart.field) { XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel), offset(foreground), XtRString, XtDefaultForeground }, { XtNhighlight, XtCForeground, XtRPixel, sizeof(Pixel), offset(highlight), XtRString, XtDefaultForeground }, { XtNcellWidth, XtCCellSize, XtRInt, sizeof(int), offset(cell_width), XtRImmediate, (XtPointer)DEFAULT_CELL_SIZE }, { XtNcellHeight, XtCCellSize, XtRInt, sizeof(int), offset(cell_height), XtRImmediate, (XtPointer)DEFAULT_CELL_SIZE }, { XtNcellSeparation, XtCCellSeparation, XtRInt, sizeof(int), offset(border), XtRImmediate, (XtPointer) 1 }, { XtNboxThickness, XtCBoxThickness, XtRInt, sizeof(int), offset(frame), XtRImmediate, (XtPointer) 3 }, { XtNbox, XtCBox, XtRBoolean, sizeof(Boolean), offset(box), XtRString, "True" }, { XtNrigidZoom, XtCRigidZoom, XtRBoolean, sizeof(Boolean), offset(rigid_zoom), XtRString, "True" }, { XtNcolors, XtCColors, XtRPixelList, sizeof(PixelList), offset(colors), XtRString, "black" }, { XtNpatterns, XtCPatterns, XtRPatternList, sizeof(PatternList), offset(patterns), XtRString, "solid" }, { XtNpalette, XtCPalette, XtRString, sizeof(String), offset(palette), XtRString, "Palette" }, { XtNwidthInCells, XtCNumberCells, XtRDimension, sizeof(Dimension), offset(width), XtRImmediate, (XtPointer)DEFAULT_CHART_WIDTH }, { XtNheightInCells, XtCNumberCells, XtRDimension, sizeof(Dimension), offset(height), XtRImmediate, (XtPointer)DEFAULT_CHART_HEIGHT }, { XtNcurX, XtCCurX, XtRInt, sizeof(int), offset(cur_x), XtRImmediate, (XtPointer) 0 }, { XtNcurY, XtCCurY, XtRInt, sizeof(int), offset(cur_y), XtRImmediate, (XtPointer) 0 }, { XtNcellArray, XtCCellArray, XtRPointer, sizeof(double *), offset(cell), XtRImmediate, (XtPointer)NULL }, { XtNstateArray, XtCStateArray, XtRPointer, sizeof(Boolean *), offset(state), XtRImmediate, (XtPointer)NULL }, { XtNtwoD, XtCTwoD, XtRBoolean, sizeof(Boolean), offset(twoD), XtRString, "True" }, { XtNzoom, XtCZoom, XtRBoolean, sizeof(Boolean), offset(zoom), XtRString, "True" }, { XtNcallback, XtCCallback, XtRCallback, sizeof(XPointer), offset(callback), XtRCallback, NULL }, { XtNchartResize, XtCCallback, XtRCallback, sizeof(XPointer), offset(chart_resize), XtRCallback, NULL }, }; static void Initialize(); static void ClassPartInitialize(); static void Redisplay(); static void Destroy(); static void Resize(); static Boolean SetValues(); /* the following are private functions unique to Chart */ static void DoCell(), DrawIntoBigPixmap(); /* the following are actions of Chart */ static void SelectCell(), ManyCells(); static char defaultTranslations[] = "<Btn1Down>: SelectCell() \n\ <Btn1Motion>: ManyCells()"; static XtActionsRec actions[] = { {"SelectCell", SelectCell}, {"ManyCells", ManyCells}, }; ChartClassRec chartClassRec = { { /* core_class fields */ /* superclass */ (WidgetClass) &coreClassRec, /* class_name */ "Chart", /* widget_size */ sizeof(ChartRec), /* class_initialize */ NULL, /* class_part_initialize */ ClassPartInitialize, /* class_inited */ FALSE, /* initialize */ Initialize, /* initialize_hook */ NULL, /* realize */ XtInheritRealize, /* actions */ actions, /* num_actions */ XtNumber(actions), /* resources */ resources, /* num_resources */ XtNumber(resources), /* xrm_class */ NULLQUARK, /* compress_motion */ TRUE, /* compress_exposure */ TRUE, /* compress_enterleave */ TRUE, /* visible_interest */ FALSE, /* destroy */ Destroy, /* resize */ Resize, /* expose */ Redisplay, /* set_values */ SetValues, /* set_values_hook */ NULL, /* set_values_almost */ XtInheritSetValuesAlmost, /* get_values_hook */ NULL, /* accept_focus */ NULL, /* version */ XtVersion, /* callback_private */ NULL, /* tm_table */ defaultTranslations, /* query_geometry */ NULL, /* display_accelerator */ XtInheritDisplayAccelerator, /* extension */ NULL }, { /* dummy_field */ 0, }, }; WidgetClass chartWidgetClass = (WidgetClass) & chartClassRec; /* CoreClassPart SuperClass; #define Superclass (&(chartClassRec.core_class.superclass)) */ /* ARGSUSED */ Boolean CvtStringToPattern(display, args, nargs, fromVal, toVal, converter_data) Display* display; XrmValuePtr args, fromVal, toVal; int *nargs; XtPointer* converter_data; { static int result; if (XswStrCmp((char *)fromVal->addr, "solid")) result = 0; else if (XswStrCmp((char *)fromVal->addr, "checkered")) result = 1; else if (XswStrCmp((char *)fromVal->addr, "slantleft")) result = 2; else if (XswStrCmp((char *)fromVal->addr, "slantright")) result = 3; else if (XswStrCmp((char *)fromVal->addr, "vertical")) result = 4; else if (XswStrCmp((char *)fromVal->addr, "horizontal")) result = 5; else XtStringConversionWarning((char *) fromVal->addr, "Pattern"); DONE(Pattern, result); } CVT_STRING_TO_LIST(CvtStringToPatternList, Pattern, XtRPattern, (Pattern)END_OF_LIST) static void GetAllGC(cw) ChartWidget cw; { XGCValues values; XtGCMask mask = GCForeground | GCBackground | GCFillStyle | GCLineWidth; int i, n_clrs, n_pats; unsigned int colors[300]; Boolean bw = False; String file_name; /* This GC used to erase areas */ values.background = cw->core.background_pixel; values.fill_style = FillSolid; values.foreground = cw->core.background_pixel; values.line_width = cw->chart.frame; cw->chart.cleargc = XtGetGC((Widget)cw, mask, &values); /* This GC used for drawing the box to indicate selections */ values.foreground = cw->chart.highlight; cw->chart.boxgc = XtGetGC((Widget)cw, mask, &values); /* Get GCs for multiple bars in 2D chart */ mask = mask | GCStipple; values.fill_style = FillOpaqueStippled; n_pats = 0; while (cw->chart.patterns[n_pats] != END_OF_LIST) n_pats++; n_clrs = 0; while(cw->chart.colors[n_clrs] != END_OF_LIST) n_clrs++; cw->chart.styles = MIN(n_pats, n_clrs); cw->chart.style_gc = (GC *)XtMalloc((cw->chart.styles+1) * sizeof(GC)); for(i=0; i < cw->chart.styles; i++) { if (i < n_pats) { values.stipple = XCreateBitmapFromData(XtDisplay(cw), ROOTWINDOW(cw), &patterns[cw->chart.patterns[i]* PAT_WIDTH*PAT_HEIGHT/8], PAT_WIDTH, PAT_HEIGHT); } else { values.stipple = XCreateBitmapFromData(XtDisplay(cw), ROOTWINDOW(cw), hundred, PAT_WIDTH, PAT_HEIGHT); } if (i < n_clrs) { values.foreground = cw->chart.colors[i]; } else { values.foreground = cw->chart.foreground; } cw->chart.style_gc[i] = XtGetGC((Widget)cw, mask, &values); } /* Now get GCs to use to indicate values in 3D chart */ /* load in selected palette */ file_name = XswGetLibName(cw->chart.palette); if (file_name != NULL) { cw->chart.values = load_color_palette(XtDisplay(cw),DefaultScreen(XtDisplay(cw)), file_name, colors); } else { cw->chart.values = -1; } if (cw->chart.values < 0) /* if no palette then use greyscale */ cw->chart.values = load_color_palette(XtDisplay(cw),DefaultScreen(XtDisplay(cw)), "Greyscale64", colors); if (cw->chart.values <= 0) { /* if one-bit pixel display */ cw->chart.values = NUM_PERCENTS; bw = True; } cw->chart.value_gc = (GC *)XtMalloc((cw->chart.values+1) * sizeof(GC)); values.stipple = XCreateBitmapFromData(XtDisplay(cw), ROOTWINDOW(cw), hundred, PAT_WIDTH, PAT_HEIGHT); for (i = 0; i < cw->chart.values; i++) { if (bw) { values.stipple = XCreateBitmapFromData(XtDisplay(cw), ROOTWINDOW(cw), &percents[i*PAT_WIDTH*PAT_HEIGHT/8], PAT_WIDTH, PAT_HEIGHT); values.foreground = cw->chart.foreground; } else { values.foreground = colors[i]; } cw->chart.value_gc[i] = XtGetGC((Widget)cw, mask, &values); } /* get highlight GC to use is box is turned off*/ values.foreground = cw->chart.highlight; values.stipple = XCreateBitmapFromData(XtDisplay(cw), ROOTWINDOW(cw), hundred, PAT_WIDTH, PAT_HEIGHT); cw->chart.value_gc[cw->chart.values] = XtGetGC((Widget)cw, mask, &values); cw->chart.style_gc[cw->chart.styles] = XtGetGC((Widget)cw, mask, &values); } /* ARGSUSED */ static void ClassPartInitialize(class) WidgetClass class; { XtSetTypeConverter(XtRString, XtRPattern, CvtStringToPattern, NULL, 0, XtCacheAll, NULL); XtSetTypeConverter(XtRString, XtRPatternList, CvtStringToPatternList, NULL, 0, XtCacheAll, NULL); } /* ARGSUSED */ static void Initialize(request, new) ChartWidget request, new; { /* * Check instance values set by resources that may be invalid. */ if (new->chart.twoD) new->chart.width = 1; if ((new->chart.width < 1) || (new->chart.height < 1)) { XtWarning("Chart: pixmapWidth and/or pixmapHeight is too small (using 10 x 10)."); new->chart.width = 10; new->chart.height = 10; } if (new->chart.cell_width < (2*new->chart.border + 1)) { XtWarning("Chart: cellWidth is too small."); new->chart.cell_width = (2*new->chart.border + 1); } if (new->chart.cell_height < (2*new->chart.border + 1)) { XtWarning("Chart: cellHeight is too small."); new->chart.cell_height = (2*new->chart.border + 1); } new->chart.save_width = new->chart.cell_width; new->chart.save_height = new->chart.cell_height; if ((new->chart.cur_x < 0) || (new->chart.cur_y < 0)) { XtWarning("Chart: cur_x and cur_y must be non-negative (using 0, 0)."); new->chart.cur_x = 0; new->chart.cur_y = 0; } new->chart.save_y = new->chart.cur_y; new->chart.save_x = new->chart.cur_x; new->chart.save_border = new->chart.border; new->chart.save_frame = new->chart.frame; if (new->chart.cell == NULL) new->chart.cell = (double *)XtCalloc(new->chart.width * new->chart.height, sizeof(double)); if (new->chart.state == NULL) new->chart.state = (Boolean *)XtCalloc(new->chart.width * new->chart.height, sizeof(Boolean)); if (new->core.width == 0) { if (new->chart.twoD) { new->core.width = 200; } else new->core.width = new->chart.width * new->chart.cell_width + new->chart.border; } if (new->core.height == 0) { new->core.height = new->chart.height * new->chart.cell_height + new->chart.border; } new->core.height = MIN(new->core.height, 1000); new->core.width = MIN(new->core.width, 1000); GetAllGC(new); if (new->chart.zoom) { Resize(new); } } /* ARGSUSED */ static void Redisplay(cw, event) ChartWidget cw; XExposeEvent *event; { register int x, y; int maxX, maxY; if (!XtIsRealized((Widget) cw)) return; if (event) { /* called from btn-event or expose */ if (cw->chart.zoom && !cw->chart.rigid_zoom) { x = event->x / (double)((double)cw->core.width/(double)cw->chart.width); y = event->y / (double)((double)cw->core.height/(double)cw->chart.height); maxX = (event->x + event->width) / (double)((double)cw->core.width/(double)cw->chart.width); maxY = (event->y + event->height) / (double)((double)cw->core.height/(double)cw->chart.height); } else { x = cw->chart.cur_x + event->x / cw->chart.cell_width; y = cw->chart.cur_y + event->y / cw->chart.cell_height; maxX = cw->chart.cur_x + (event->width+event->x)/cw->chart.cell_width + 1; maxY = cw->chart.cur_y + (event->height+event->y)/cw->chart.cell_height + 1; } if (cw->chart.twoD) x = 0; maxX = MIN(maxX, cw->chart.width); maxY = MIN(maxY, cw->chart.height); x = MIN(x, cw->chart.width); y = MIN(y, cw->chart.height); /* draw current chart */ DoCell(cw, x, y, maxX, maxY); } else { /* called because complete redraw */ DrawIntoBigPixmap(cw); } } static void ScrollChart(cw, x0, y0, x1, y1) ChartWidget cw; int x0, y0, x1, y1; { int y, x; unsigned int height, width, excess; XExposeEvent fake_event; unsigned int event_x, event_y, event_width, event_height; y = (y1 - y0) * cw->chart.cell_height; x = (x1 - x0) * cw->chart.cell_width; if (y != 0) { if (cw->chart.zoom && !cw->chart.rigid_zoom) { excess = 0; } else { excess = cw->core.height % cw->chart.cell_height; } if (y > 0) { y0 = y; y1 = 0; height = cw->core.height - y - excess; fake_event.y = height; fake_event.height = y0; event_y = y0; event_height = cw->core.height - y0; } else { y0 = 0; y1 = -y; height = cw->core.height + y - excess; fake_event.y = 0; fake_event.height = y1; event_y = 0; event_height = cw->core.height - y1; } } else { y0 = 0; y1 = 0; if (cw->chart.zoom && !cw->chart.rigid_zoom) { height = cw->core.height; } else { if (cw->core.height < cw->chart.height*cw->chart.cell_height) height = cw->core.height; else height = cw->chart.height*cw->chart.cell_height; } event_y = 0; event_height = cw->core.height; } if (x != 0) { if (cw->chart.zoom && !cw->chart.rigid_zoom) { excess = 0; } else { excess = cw->core.width % cw->chart.cell_width; } if (x > 0) { x0 = x; x1 = 0; width = cw->core.width - x - excess; event_x = width; event_width = x0; } else { x0 = 0; x1 = -x; width = cw->core.width + x - excess; event_x = 0; event_width = x1; } } else { x0 = 0; x1 = 0; if (cw->chart.zoom && !cw->chart.rigid_zoom) { width = cw->core.width; } else { if (cw->core.width < cw->chart.width*cw->chart.cell_width) width = cw->core.width; else { if (cw->chart.twoD) width = cw->core.width; else width = cw->chart.width*cw->chart.cell_width; } } } XCopyArea(XtDisplay(cw), XtWindow(cw), XtWindow(cw), cw->chart.boxgc, x0, y0, width, height, x1, y1); if (y != 0) { fake_event.x = 0; fake_event.width = width; Redisplay(cw, &fake_event); } if (x != 0) { fake_event.y = event_y; fake_event.height = event_height; fake_event.x = event_x; fake_event.width = event_width; Redisplay(cw, &fake_event); } } static void CalibrateXY(cw) ChartWidget cw; { while ((cw->chart.cur_y > 0) && (cw->chart.cell_height* (cw->chart.height-(cw->chart.cur_y-1)) < cw->core.height)) cw->chart.cur_y--; if (!cw->chart.twoD) while ((cw->chart.cur_x > 0) && (cw->chart.cell_width* (cw->chart.width-(cw->chart.cur_x-1)) < cw->core.width)) cw->chart.cur_x--; } static void CalibrateSpace(cw) ChartWidget cw; { int i; int original_frame = cw->chart.frame; unsigned int smallest; if ((cw->chart.zoom) && (!cw->chart.rigid_zoom)) { smallest = MIN(cw->core.height/cw->chart.height, cw->core.width/cw->chart.width); } else { smallest = MIN(cw->chart.cell_height, cw->chart.cell_width); } cw->chart.border = cw->chart.save_border; cw->chart.frame = cw->chart.save_frame; if (smallest > 1) { while (smallest <= cw->chart.border+2*cw->chart.frame + 1) { cw->chart.border > cw->chart.frame ? cw->chart.border-- : cw->chart.frame--; } } else { cw->chart.border = 0; cw->chart.frame = 0; } if (cw->chart.frame != original_frame) { if (cw->chart.boxgc) XtReleaseGC((Widget) cw, cw->chart.boxgc); if (cw->chart.cleargc) XtReleaseGC((Widget) cw, cw->chart.cleargc); for(i = 0; i <= cw->chart.values; i++) if (cw->chart.value_gc[i]) XtReleaseGC((Widget) cw, cw->chart.value_gc[i]); for(i = 0; i <= cw->chart.styles; i++) if (cw->chart.style_gc[i]) XtReleaseGC((Widget) cw, cw->chart.style_gc[i]); GetAllGC((Widget) cw); } } /* ARGSUSED */ static Boolean SetValues(current, request, new) Widget current, request, new; { ChartWidget curcw = (ChartWidget) current; ChartWidget newcw = (ChartWidget) new; Boolean do_redisplay = False; int i; if ((curcw->chart.foreground != newcw->chart.foreground) || (curcw->chart.colors != newcw->chart.colors) || (curcw->chart.patterns != newcw->chart.patterns)) { if (newcw->chart.boxgc) XtReleaseGC((Widget) newcw, newcw->chart.boxgc); if (newcw->chart.cleargc) XtReleaseGC((Widget) newcw, newcw->chart.cleargc); for(i = 0; i <= newcw->chart.values; i++) if (newcw->chart.value_gc[i]) XtReleaseGC((Widget) newcw, newcw->chart.value_gc[i]); for(i = 0; i <= newcw->chart.styles; i++) if (newcw->chart.style_gc[i]) XtReleaseGC((Widget) newcw, newcw->chart.style_gc[i]); GetAllGC((Widget) newcw); do_redisplay = True; } if ((curcw->chart.cur_x != newcw->chart.cur_x) || (curcw->chart.cur_y != newcw->chart.cur_y)) { CalibrateXY(newcw); if (newcw->chart.cur_x < 0) newcw->chart.cur_x = 0; if (newcw->chart.cur_y < 0) newcw->chart.cur_y = 0; ScrollChart(newcw, curcw->chart.cur_x, curcw->chart.cur_y, newcw->chart.cur_x, newcw->chart.cur_y); } if (curcw->chart.log != newcw->chart.log) do_redisplay = True; if ((curcw->chart.width != newcw->chart.width) || (curcw->core.width != newcw->core.width) || (curcw->chart.height != newcw->chart.height) || (curcw->core.height != newcw->core.height)) { if(newcw->core.height <= 0) { newcw->core.height = newcw->chart.height * newcw->chart.cell_height + newcw->chart.border; XtWarning("Correct the Chart height (0)"); } /* 4/1992 found redundant hui when debugging from R4->R5 Resize(newcw); */ do_redisplay = True; } if (curcw->chart.twoD != newcw->chart.twoD) { if (newcw->chart.twoD) { if (!curcw->chart.zoom) newcw->chart.save_x = newcw->chart.cur_x; newcw->chart.cur_x = 0; } else { if (!curcw->chart.zoom) newcw->chart.cur_x = newcw->chart.save_x; } } if (curcw->chart.zoom != newcw->chart.zoom) { if (newcw->chart.zoom) { newcw->chart.save_y = newcw->chart.cur_y; newcw->chart.cur_y = 0; if (!newcw->chart.twoD) { newcw->chart.save_x = newcw->chart.cur_x; newcw->chart.cur_x = 0; } } else { newcw->chart.cur_y = newcw->chart.save_y; if (!newcw->chart.twoD) newcw->chart.cur_x = newcw->chart.save_x; } } if ((curcw->chart.zoom != newcw->chart.zoom) || (curcw->chart.twoD != newcw->chart.twoD)){ newcw->chart.cell_height = newcw->chart.save_height; newcw->chart.cell_width = newcw->chart.save_width; Resize(newcw); if (!newcw->chart.zoom) CalibrateSpace(newcw); do_redisplay = True; } return do_redisplay; } static void Destroy(cw) ChartWidget cw; { int i; if (cw->chart.boxgc) XtReleaseGC((Widget) cw, cw->chart.boxgc); if (cw->chart.cleargc) XtReleaseGC((Widget) cw, cw->chart.cleargc); for(i = 0; i <= cw->chart.values; i++) if (cw->chart.value_gc[i]) XtReleaseGC((Widget) cw, cw->chart.value_gc[i]); XtFree((char *)cw->chart.value_gc); for(i = 0; i <= cw->chart.styles; i++) if (cw->chart.style_gc[i]) XtReleaseGC((Widget) cw, cw->chart.style_gc[i]); XtFree((char *)cw->chart.style_gc); } static Boolean GetCoord(w, event, xPtr, yPtr) ChartWidget w; XButtonEvent *event; int * xPtr, * yPtr; { if (w->chart.zoom && !w->chart.rigid_zoom) { *xPtr = event->x / (double)((double)w->core.width/(double)w->chart.width); *yPtr = event->y / (double)((double)w->core.height/(double)w->chart.height); if (w->chart.twoD) *xPtr = 0; if (*xPtr >= w->chart.width) *xPtr = w->chart.width-1; if (*yPtr >= w->chart.height) *yPtr = w->chart.height-1; } else { *xPtr = w->chart.cur_x + event->x / w->chart.cell_width; *yPtr = w->chart.cur_y + event->y / w->chart.cell_height; if (w->chart.twoD) *xPtr = 0; if ((*xPtr >= (w->core.width/w->chart.cell_width)+w->chart.cur_x) || (*yPtr >= (w->core.height/w->chart.cell_height)+w->chart.cur_y) || (*xPtr < w->chart.cur_x) || (*yPtr < w->chart.cur_y) || (*xPtr >= w->chart.width) || (*yPtr >= w->chart.height)) return False; } return True; } static void SelectCell(w, event) ChartWidget w; XButtonEvent *event; { int newx; int newy; if (!GetCoord(w, event, &newx, &newy)) return; w->chart.state[newx + newy * w->chart.width] = !w->chart.state[newx + newy * w->chart.width]; w->chart.tog_state = w->chart.state[newx + newy * w->chart.width]; w->chart.info.state = w->chart.tog_state; w->chart.info.x = newx; w->chart.info.y = newy; XtCallCallbacks((Widget) w, XtNcallback, (XtPointer)&(w->chart.info)); DoCell(w, newx, newy, (int)(w->chart.twoD ? w->chart.width : newx+1), newy+1); } static void ManyCells(w, event) ChartWidget w; XButtonEvent *event; { int newx; int newy; if (!GetCoord(w, event, &newx, &newy)) return; if (w->chart.state[newx + newy * w->chart.width] != w->chart.tog_state) { w->chart.state[newx + newy * w->chart.width] = w->chart.tog_state; w->chart.info.state = w->chart.tog_state; w->chart.info.x = newx; w->chart.info.y = newy; XtCallCallbacks((Widget) w, XtNcallback, (XtPointer)&(w->chart.info)); DoCell(w, newx, newy, (int)(w->chart.twoD ? w->chart.width : newx+1), newy+1); } } static void DrawIntoBigPixmap(cw) ChartWidget cw; { int maxX, maxY; if (cw->chart.zoom) { DoCell(cw, 0, 0, (int)cw->chart.width, (int)cw->chart.height); } else { maxX = cw->chart.cur_x + cw->core.width/cw->chart.cell_width; maxY = cw->chart.cur_y + cw->core.height/cw->chart.cell_height; if (maxX > cw->chart.width) maxX = cw->chart.width; if (maxY > cw->chart.height) maxY = cw->chart.height; DoCell(cw, cw->chart.cur_x, cw->chart.cur_y, maxX, maxY); } } /* A Public function, not static */ double * ChartGetArrayString(w) ChartWidget w; { return (w->chart.cell); } static void Resize(cw) ChartWidget cw; { if (cw->chart.zoom) { /* * Calculate the maximum cell size that will allow the * entire chart to be displayed. */ cw->chart.cell_width = MAX(cw->core.width / cw->chart.width, 1); cw->chart.cell_height = MAX(cw->core.height / cw->chart.height, 1); CalibrateSpace(cw); } else { CalibrateXY(cw); } XtCallCallbacks((Widget) cw, XtNchartResize, (XtPointer)NULL); } static void GetRectangle(w, x, y, pIndex, pRectangle) ChartWidget w; int x, y; int * pIndex; XRectangle * pRectangle; { double percent; if (w->chart.zoom && !w->chart.rigid_zoom) { pRectangle->y = (int)((double)y*(double)w->core.height/(double)w->chart.height) + w->chart.border; pRectangle->height = (int)((double)(y+1)*(double)w->core.height/(double)w->chart.height) + w->chart.border - pRectangle->y; } else { pRectangle->y = w->chart.cell_height * (y - w->chart.cur_y) + w->chart.border; pRectangle->height = (unsigned int)w->chart.cell_height; } percent = w->chart.cell[x + y*w->chart.width]; if (w->chart.twoD) { *pIndex = w->chart.values-1; pRectangle->x = w->chart.border; pRectangle->width = percent*w->core.width; } else { *pIndex = percent*(double)w->chart.values; if (*pIndex >= w->chart.values) *pIndex = w->chart.values-1; if (w->chart.zoom && !w->chart.rigid_zoom) { pRectangle->x = (int)((double)x*(double)w->core.width/(double)w->chart.width) + w->chart.border; pRectangle->width = (int)((double)(x+1)*(double)w->core.width/(double)w->chart.width) + w->chart.border - pRectangle->x; } else { pRectangle->x = w->chart.cell_width * (x - w->chart.cur_x) + w->chart.border; pRectangle->width = (unsigned int)w->chart.cell_width; } } /* if (pRectangle->width < w->chart.border+2*w->chart.frame) pRectangle->width = w->chart.border+2*w->chart.frame; */ if (pRectangle->height < w->chart.border+2*w->chart.frame) pRectangle->height = w->chart.border+2*w->chart.frame; } static void DoCell(w, x0, y0, x1, y1) ChartWidget w; int x0, y0, x1, y1; { int x, y; int fill_types; int next_x; int frame, index; XRectangle rectangle; XRectangle * drawRect; int drawRects = 0; XRectangle ** fillRect; int * fillRects; XRectangle * clearRect; int clearRects = 0; int i, nRects; Display * disp; Window win; nRects = (x1-x0)*(y1-y0); drawRect = (XRectangle *)XtMalloc(nRects * sizeof(XRectangle)); clearRect = (XRectangle *)XtMalloc(nRects * sizeof(XRectangle)); fill_types = (w->chart.twoD ? w->chart.styles : w->chart.values)+1; fillRect = (XRectangle **)XtMalloc(fill_types * sizeof(XRectangle *)); fillRects = (int *)XtMalloc(fill_types * sizeof(int)); for(i = 0; i < fill_types; i++) { fillRect[i] = (XRectangle *)XtMalloc(nRects * sizeof(XRectangle)); fillRects[i] = 0; } for (y = y0; y < y1; y++) { for(x = x0; x < x1; x++) { GetRectangle(w, x, y, &index, &rectangle); if ((rectangle.y+rectangle.height-1 <= w->core.height) && (rectangle.x+rectangle.width-1 <= w->core.width)) { if (w->chart.twoD) { if (w->chart.state[x0 + y * w->chart.width]) frame = w->chart.frame; else frame = 0; index = x - x0; if (x > x0) rectangle.x = next_x; else rectangle.width -= w->chart.border+frame; next_x = rectangle.x+rectangle.width; } if (!w->chart.twoD || (x == x1-1)) { if (w->chart.box && (w->chart.frame > 0)) { if (w->chart.state[(w->chart.twoD ? x0 : x) + y * w->chart.width]) { frame = w->chart.frame; if (w->chart.twoD) { drawRect[drawRects].x = w->chart.border+frame/2; drawRect[drawRects].width = next_x-w->chart.border; } else { drawRect[drawRects].x = rectangle.x+frame/2; drawRect[drawRects].width = rectangle.width-w->chart.border-frame; } drawRect[drawRects].y = rectangle.y+frame/2; drawRect[drawRects].height = rectangle.height-w->chart.border-frame; drawRects++; } else { frame = 0; } } else { frame = 0; if (w->chart.state[(w->chart.twoD ? x0 : x) + y * w->chart.width]) index = w->chart.twoD ? w->chart.styles : w->chart.values; } } if (w->chart.twoD) if (x != x1-1) { fillRect[index][fillRects[index]].width = rectangle.width; } else { fillRect[index][fillRects[index]].width = rectangle.width - frame; } else fillRect[index][fillRects[index]].width = rectangle.width-w->chart.border-2*frame; fillRect[index][fillRects[index]].x = rectangle.x+frame; fillRect[index][fillRects[index]].y = rectangle.y+frame; fillRect[index][fillRects[index]].height = rectangle.height-w->chart.border-2*frame; fillRects[index]++; if (w->chart.twoD && (x == x1-1)) { clearRect[clearRects].x = next_x+frame; clearRect[clearRects].y = rectangle.y; clearRect[clearRects].width = w->core.width-next_x-frame; clearRect[clearRects].height = rectangle.height; clearRects++; } } } } if (drawRects > 0) { disp = XtDisplay(w); win = XtWindow(w); XDrawRectangles(disp, win, w->chart.boxgc, drawRect, drawRects); } XtFree((char *)drawRect); for (i=0; i < fill_types; i++) { if (fillRects[i] >0) XFillRectangles(XtDisplay(w), XtWindow(w), w->chart.twoD ? w->chart.style_gc[i] : w->chart.value_gc[i], fillRect[i], fillRects[i]); XtFree((char *)fillRect[i]); } XtFree((char *)fillRect); if (clearRects > 0) XFillRectangles(XtDisplay(w), XtWindow(w), w->chart.cleargc, clearRect, clearRects); XtFree((char *)clearRect); } int XswChartNumValues(w) ChartWidget w; { return w->chart.values; } void XswChartSetRow(w, row, state) ChartWidget w; int row; Boolean state; { int j; for(j = 0; j < w->chart.width; j++) { if (w->chart.state[j + row * w->chart.width] != state) { w->chart.state[j + row * w->chart.width] = state; w->chart.info.state = state; w->chart.info.x = j; w->chart.info.y = row; XtCallCallbacks((Widget) w, XtNcallback, &(w->chart.info)); } } if (w->chart.zoom) { DoCell(w, 0, row, (int)w->chart.width, row + 1); } else { DoCell(w, w->chart.cur_x, row, (int)MIN(w->core.width/w->chart.cell_width + w->chart.cur_x, (int)w->chart.width), row + 1); } } void XswChartSetCol(w, col, state) ChartWidget w; int col; Boolean state; { int j; for(j = 0; j < w->chart.height; j++) { if (w->chart.state[col + j * w->chart.width] != state) { w->chart.state[col + j * w->chart.width] = state; w->chart.info.state = state; w->chart.info.x = col; w->chart.info.y = j; XtCallCallbacks((Widget) w, XtNcallback, &(w->chart.info)); } } if (w->chart.zoom) { DoCell(w, col, 0, col + 1, (int)w->chart.height); } else { DoCell(w, col, w->chart.cur_y, col + 1, (int)MIN(w->core.height/w->chart.cell_height + w->chart.cur_y, w->chart.height)); } } void XswChartRedisplay(w) ChartWidget w; { if (!XtIsRealized((Widget) w)) return; else DrawIntoBigPixmap(w); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.