diff --git a/trick_source/data_products/.gitignore b/trick_source/data_products/.gitignore index e69de29b..6b55aac5 100644 --- a/trick_source/data_products/.gitignore +++ b/trick_source/data_products/.gitignore @@ -0,0 +1 @@ +fermi-ware diff --git a/trick_source/data_products/fermi-ware/.gitignore b/trick_source/data_products/fermi-ware/.gitignore deleted file mode 100644 index 39a679d0..00000000 --- a/trick_source/data_products/fermi-ware/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -object_* - diff --git a/trick_source/data_products/fermi-ware/README.md b/trick_source/data_products/fermi-ware/README.md deleted file mode 100644 index deae0fd9..00000000 --- a/trick_source/data_products/fermi-ware/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# fermi-ware -Fermi-ware plot widgets for use with Trick - -Trick is on GitHub: https://github.com/nasa/trick diff --git a/trick_source/data_products/fermi-ware/XY.c b/trick_source/data_products/fermi-ware/XY.c deleted file mode 100644 index 2baf63ad..00000000 --- a/trick_source/data_products/fermi-ware/XY.c +++ /dev/null @@ -1,4615 +0,0 @@ -/******************************************************************************* -* * -* XY.c -- General Purpose Plot Widget * -* * -* Copyright (c) 1991 Universities Research Association, Inc. * -* All rights reserved. * -* * -* This material resulted from work developed under a Government Contract and * -* is subject to the following license: The Government retains a paid-up, * -* nonexclusive, irrevocable worldwide license to reproduce, prepare derivative * -* works, perform publicly and display publicly by or for the Government, * -* including the right to distribute to other Government contractors. Neither * -* the United States nor the United States Department of Energy, nor any of * -* their employees, makes any warrenty, express or implied, or assumes any * -* legal liability or responsibility for the accuracy, completeness, or * -* usefulness of any information, apparatus, product, or process disclosed, or * -* represents that its use would not infringe privately owned rights. * -* * -* Fermilab Nirvana GUI Library * -* May 28, 1992 * -* * -* Written by Mark Edel * -* * -*******************************************************************************/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if XmVersion == 1002 -#include -#endif -#include "psUtils.h" -#include "drawAxes.h" -#include "dragAxes.h" -#include "XYP.h" - - -#include "../EQParse/eqparse_protos.h" - -#define REDRAW_NONE 0 -#define REDRAW_H_AXIS 1 -#define REDRAW_V_AXIS 2 -#define REDRAW_CONTENTS 4 -#define REDRAW_LABELS 8 -#define REDRAW_ALL 15 - -#define ZOOM_FACTOR .25 /* (linear) fraction of currently displayed - data to place outside of current limits - when user invokes zoom command */ -#define LEFT_MARGIN 0 /* empty space to left of widget. Should be - small since v axis usually reserves more - space than it needs (for long numbers) */ -#define TOP_MARGIN 7 /* empty space at top of widget */ -#define RIGHT_MARGIN 0 /* empty space to right of widget. Should be - small because h axis reserves more room - than it needs for last label to stick out */ -#define BOTTOM_MARGIN 3 /* empty space at bottom of widget */ -#define X_LABEL_MARGIN 7 /* space between x axis label and numbers */ -#define Y_LABEL_MARGIN 15 /* space between y axis label and axis line */ -#define LEGEND_TOP_MARGIN 5 /* space between legend and y axis label */ -#define LEGEND_LEFT_MARGIN 5 /* space to the left of margin */ -#define LEGEND_RIGHT_MARGIN 5 /* space to the right of margin */ -#define LEGEND_LINE_LEN 40 /* width of example lines in plot legend */ -#define LEGEND_NAME_SPACING 5 /* space between sample line and name */ -#define LEGEND_COLUMN_MARGIN 20 /* space between columns in legend */ -#define TINY_MARK_SIZE 2 /* width/height for small marker symbols */ -#define SMALL_MARK_SIZE 4 /* width/height for small marker symbols */ -#define MED_MARK_SIZE 6 /* width/height for medium marker symbols */ -#define LARGE_MARK_SIZE 8 /* width/height for large marker symbols */ -#define ERROR_MARKER_RATIO 1.25 /* ratio of error bar end to marker size */ - -/* Set of constants for data to window coordinate transformation */ -typedef struct { - char xLogScaling, yLogScaling; - double minXData, minYData, minXLim, minYLim, maxXLim, maxYLim; - double xScale, yScale, minXPix, maxYPix; -} transform; - -/* header of a list for accumulating figures (XRectangles, XArcs, XSegments) - for drawing markers independent of their composition */ -typedef struct { - int style; - int nFigures; - char *list; - char *fillPtr; -} markStruct; - -/* header for a list for acumulating line segments in connected groups so that - they can be drawn with a continuous dash pattern, and independent of their - destination (FloatPoints for PSFloatDrawLines and XPoints for XDrawLines) */ -typedef struct { - int outDevice; - XPoint *points; - FloatPoint *floatPoints; - int *lineCounts; - int *curLineCount; - XPoint *fillPtr; - FloatPoint *fFillPtr; -} lineStruct; - -typedef struct { - XPoint dispPoint ; - XYPoint value ; -} pointStruct; - -/* JBF - added ZoomData from old version */ -typedef struct -{ - int x1, y1, x2, y2; -} ZoomData; - - -/* legend is drawn differently to save space when user doesn't have - lines and/or markers on any of the curves */ -enum legendStyles {NO_MARKERS, NO_LINES, FULL_LEGEND}; - -void GetWidgetPopupList(Widget w, WidgetList *wl, int *num) ; - -void errorEQParseDialog( Widget w, int error_code ) ; -int maxnumpts(XYCurve* curves, int numCurves) ; -XYCurve* curvemath( Widget parent_w, XYCurve* curves, - int numCurves, char *equation) ; -XYCurve* curvesub(XYCurve* c1, XYCurve* c2) ; -static void setResourceGridColor( Widget w, int offset, XrmValue *value ) ; -void label_pointer( XYWidget w, double x_data, double y_data, char* txt ) ; -void getXYMousePosition( XYWidget w, XEvent *event, double* x, double* y ) ; -int curveClosestToMouseClick( XYWidget w, XEvent *event, - double* xOnCurve, double* yOnCurve ) ; -static void motion(XYWidget w, XEvent *event, char *args, int n_args) ; -static void crossHairs(XYWidget w, XEvent *event, char *args, int n_args) ; -static void valueDisplay(XYWidget w, XEvent *event, char *args, int n_args) ; -void drawCrosshairs( Display* display, Drawable drawBuf, - XYWidget w, int x_win, int y_win ) ; -static void selectCurve(XYWidget w, XEvent *event, char *args, int n_args); -void combineCurvesDialog(XYWidget w, XEvent *event, char* args, int n_args) ; -void combineCurvesOKCB( Widget w, XtPointer client_data, - XtPointer call_data ) ; -void combineCurvesCancelCB( Widget w, XtPointer client_data, - XtPointer call_data ) ; -void combineCurvesHelpCB(Widget w, XtPointer client_data, - XtPointer call_data ) ; -void manipulateCurve(XYWidget w, XEvent *event, char* args, int n_args) ; -void manipulateCurveCB ( Widget w, XtPointer client_data, - XtPointer call_data ) ; -static void motionAP(XYWidget w, XEvent *event, char *args, int n_args); -static void btnUpAP(XYWidget w, XEvent *event, char *args, int n_args); -/** JBF removed to match old and add zoom ** -static void btn2AP(XYWidget w, XEvent *event, char *args, int n_args); -******/ -/* JBF added *_zoom from old version ***/ -static void start_zoom(XYWidget w, XEvent *event, char *args, int n_args); -static void track_zoom(XYWidget w, XEvent *event, char *args, int n_args); -static void end_zoom(XYWidget w, XEvent *event, char *args, int n_args); -/* end JBF */ - -static void btn3AP(XYWidget w, XEvent *event, char *args, int n_args); -static void initialize(XYWidget request, XYWidget new); -static void redisplay(XYWidget w, XEvent *event, Region region); -static void redisplayContents(XYWidget w, int outDevice, int redrawArea); -static void destroy(XYWidget w); -static void resize(XYWidget w); -static void resizeParts(XYWidget w); -static Boolean setValues(XYWidget current, XYWidget request,XYWidget new); -static void setContents(Widget w, XYCurve *curves, int nCurves, int rescaleMode, - int dataOnly); -static int resetDataAndViewRanges(XYWidget w, int rescaleMode); -static void drawCurve(XYWidget w, Drawable drawBuf, int outDevice, XYCurve - *curve); -static void startLineList(lineStruct *lineList, int outDevice, int maxSegs); -static void addToLineList(lineStruct *lineList, float x, float y, int restart, - int round); -static void drawLineList(Display *display, Drawable drawBuf, GC gc, - int outDevice, lineStruct *lineList, XYCurve *curve); -static void startMarkList(markStruct *markList, int markerStyle, int maxLength); -static void addToMarkList(markStruct *markList, int x, int y, int size); -static void drawMarkList(Display *display, Drawable drawBuf, GC gc, int outDevice, - markStruct *markList, XYCurve *curve); -static int tryLegendLayout(XYWidget w, int nRows, int *width, int *nColumns); -static int legendColumnStyle(XYCurve *curves, int nCurves, int colNum, - int nRows); -static void layoutLegend(XYWidget w, int *nRows, int *legendHeight, - int *columnWidth, int *leftMargin); -static void drawLegend(XYWidget w, Drawable drawBuf, int outDevice); -static void drawMarker(Display *display, Drawable drawBuf, GC gc, int outDevice, - XYCurve *curve, int x, int y); -static void drawLine(Display *display, Drawable drawBuf, GC gc, int outDevice, - XYCurve *curve, int x1, int y1, int x2, int y2); -static void updateBufferAllocation(XYWidget w); -#if XmVERSION < 2 -static XFontStruct *getFontStruct(XmFontList font); -#else -static void DefaultFont(Widget w, int offset, XrmValue *value); -#endif -static void calcDataRange(XYWidget w, double *xMin, double *xMax, double *yMin, - double *yMax); -static void oneCurveDataRange(XYWidget w, XYCurve *curve, double *xMin, - double *xMax, double *yMin, double *yMax); -static void computeTransform(XYWidget w, transform *xform); -static double dataToWindowX(transform *xform, double value); -static double dataToWindowY(transform *xform, double value); -static void copyCurveData(XYCurve *fromCurve, XYCurve *toCurve, int dataOnly); -static void copyCurveStyle(XYCurve *fromCurve, XYCurve *toCurve); -static void freeCurveData(XYCurve *curve, int dataOnly); -static double dMin(double d1, double d2); -static double dMax(double d1, double d2); -double dist_point_to_curve( XYCurve* curve, double x0, double y0, - double* x_on_curve, double* y_on_curve ) ; - -/* Line dash styles (defined as strings for convenience, but note that the - numbers are in octal) */ -static char *DashLists[] = { - "\01" /* XY_NO_LINE (not used) */, - "\01" /* XY_PLAIN_LINE (used w/dashes off) */, - "\01\01" /* XY_FINE_DASH */, - "\02\02" /* XY_MED_FINE_DASH */, - "\04\04" /* XY_DASH */, - "\06\06" /* XY_LONG_DASH */, - "\016\06" /* XY_X_LONG_DASH */, - "\020\03\02\03" /* XY_1_DOT_DASH */, - "\016\03\02\03\02\03" /* XY_2_DOT_DASH */, - "\013\03\02\03\02\03\02\03" /* XY_3_DOT_DASH */, - "\011\03\02\03\02\03\02\03\02\03" /* XY_4_DOT_DASH */, - "\01" /* XY_THICK_LINE (used w/dashes off) */, - "\01" /* XY_X_THICK_LINE (used w/dashes off) */ -}; - -/* Table to translate mark width index to actual width in pixels */ -static char MarkWidths[] = {TINY_MARK_SIZE, SMALL_MARK_SIZE, - MED_MARK_SIZE, LARGE_MARK_SIZE}; - -/* JBF - added Btn2Motion and Btn2Up from old version */ - -static char defaultTranslations[] = - "~Ctrl Shift: manipulateCurve()\n\ - ~Shift Ctrl: combineCurvesDialog()\n\ - Shift Ctrl: selectCurve()\n\ - : Motion()\n\ - : Motion()\n\ - : BtnUp()\n\ - : Btn2Down()\n\ - : Btn2Motion()\n\ - : Btn2Up()\n\ - : Btn3Press()\n\ - : motion()\n" ; - -/* JBF - added Btn2Down, Btn2Motion, and Btn2Up zoom stuff from old version, - and removed Btn2Press */ -static XtActionsRec actionsList[] = { - {"selectCurve", (XtActionProc)selectCurve}, - {"manipulateCurve", (XtActionProc)manipulateCurve}, - {"combineCurvesDialog", (XtActionProc)combineCurvesDialog}, - {"Motion", (XtActionProc)motionAP}, - {"BtnUp", (XtActionProc)btnUpAP}, - {"Btn2Down", (XtActionProc)start_zoom}, - {"Btn2Motion", (XtActionProc)track_zoom}, - {"Btn2Up", (XtActionProc)end_zoom}, - {"Btn3Press", (XtActionProc)btn3AP}, - {"motion", (XtActionProc)motion} -}; - -static XtResource resources[] = { -/* Keith added cross hairs */ - {XmNenableCrosshairs, XmCEnableCrosshairs, XmRBoolean, sizeof(Boolean), - XtOffset(XYWidget, xy.enableCrosshairs), XmRString, "False"}, - - {XmNdoubleBuffer, XmCDoubleBuffer, XmRBoolean, sizeof(Boolean), - XtOffset(XYWidget, xy.doubleBuffer), XmRString, "False"}, - {XmNshowLegend, XmCShowLegend, XmRBoolean, sizeof(Boolean), - XtOffset(XYWidget, xy.showLegend), XmRString, "True"}, -/* RCS added grid on/off stuff -*/ - {XmNshowGrid, XmCShowGrid, XmRBoolean, sizeof(Boolean), - XtOffset(XYWidget, xy.showGrid), XmRString, "True"}, - {XmNgridColor, XmCGridColor, XmRPixel, sizeof (Pixel), - XtOffset(XYWidget, xy.gridColor), XtRCallProc, - (XtPointer) setResourceGridColor}, - {XmNprintGridColor, XmCPrintGridColor, XmRPixel, sizeof (Pixel), - XtOffset(XYWidget, xy.printGridColor), XmRPixel, 0}, - {XmNxLogScaling, XmCXLogScaling, XmRBoolean, sizeof(Boolean), - XtOffset(XYWidget, xy.xLogScaling), XmRString, "False"}, - {XmNyLogScaling, XmCYLogScaling, XmRBoolean, sizeof(Boolean), - XtOffset(XYWidget, xy.yLogScaling), XmRString, "False"}, - {XmNmarginPercent, XmCMarginPercent, XmRInt, sizeof(int), - XtOffset(XYWidget, xy.marginPercent), XmRString, "4"}, - -/* JBF - added plotTitle from old version */ - {XmNplotTitle, XmCPlotTitle, XmRXmString, sizeof (XmString), - XtOffset(XYWidget, xy.plotTitle), XmRString, NULL}, - -#if XmVERSION < 2 - {XmNfontList, XmCFontList, XmRFontList, sizeof(XmFontList), - XtOffset(XYWidget, xy.render_font), XmRImmediate, NULL}, -#else - {XmNrenderTable, XmCRenderTable, XmRRenderTable, sizeof(XmRenderTable), - XtOffset(XYWidget, xy.render_font), XmRCallProc, (XtPointer)DefaultFont}, -#endif - {XmNxAxisLabel, XmCXAxisLabel, XmRXmString, sizeof (XmString), - XtOffset(XYWidget, xy.xAxisLabel), XmRString, NULL}, - {XmNyAxisLabel, XmCYAxisLabel, XmRXmString, sizeof (XmString), - XtOffset(XYWidget, xy.yAxisLabel), XmRString, NULL}, - {XmNresizeCallback, XmCCallback, XmRCallback, sizeof(caddr_t), - XtOffset (XYWidget, xy.resize), XtRCallback, NULL}, - {XmNbtn2Callback, XmCCallback, XmRCallback, sizeof(caddr_t), - XtOffset (XYWidget, xy.btn2), XtRCallback, NULL}, - {XmNbtn3Callback, XmCCallback, XmRCallback, sizeof(caddr_t), - XtOffset (XYWidget, xy.btn3), XtRCallback, NULL}, - {XmNredisplayCallback, XmCCallback, XmRCallback, sizeof(caddr_t), - XtOffset (XYWidget, xy.redisplay), XtRCallback, NULL}, - {XmNyAxisFormat, XmCYAxisFormat, XmRString, sizeof(XmString), - XtOffset(XYWidget, xy.yAxisFormat), XmRString, NULL}, - - {XmNValueDisplay, XmCValueDisplay, XmRBoolean, sizeof(Boolean), - XtOffset(XYWidget, xy.valueDisplay), XmRString, "False"}, - -}; - -XYClassRec xyClassRec = { - /* CoreClassPart */ - { - (WidgetClass) &xmPrimitiveClassRec, /* superclass */ - "XY", /* class_name */ - sizeof(XYRec), /* widget_size */ - NULL, /* class_initialize */ - NULL, /* class_part_initialize */ - FALSE, /* class_inited */ - (XtInitProc)initialize, /* initialize */ - NULL, /* initialize_hook */ - XtInheritRealize, /* realize */ - actionsList, /* actions */ - XtNumber(actionsList), /* num_actions */ - resources, /* resources */ - XtNumber(resources), /* num_resources */ - NULLQUARK, /* xrm_class */ - TRUE, /* compress_motion */ - TRUE, /* compress_exposure */ - TRUE, /* compress_enterleave */ - TRUE, /* visible_interest */ - (XtWidgetProc)destroy, /* destroy */ - (XtWidgetProc)resize, /* resize */ - (XtExposeProc)redisplay, /* expose */ - (XtSetValuesFunc)setValues, /* set_values */ - NULL, /* set_values_hook */ - XtInheritSetValuesAlmost, /* set_values_almost */ - NULL, /* get_values_hook */ - NULL, /* accept_focus */ - XtVersion, /* version */ - NULL, /* callback private */ - defaultTranslations, /* tm_table */ - NULL, /* query_geometry */ - NULL, /* display_accelerator */ - NULL, /* extension */ - }, - /* Motif primitive class fields */ - { - (XtWidgetProc)_XtInherit, /* Primitive border_highlight */ - (XtWidgetProc)_XtInherit, /* Primitive border_unhighlight */ - XtInheritTranslations, /* translations */ - (XtActionProc)motionAP, /* arm_and_activate */ - NULL, /* get resources */ - 0, /* num get_resources */ - NULL, /* extension */ - }, - /* XY class part */ - { - 0, /* ignored */ - } -}; - -/* JBF added zd from old version */ -static ZoomData zd; - - -WidgetClass xyWidgetClass = (WidgetClass)&xyClassRec; - -static void setResourceGridColor( Widget w, int offset __attribute__ ((unused)), XrmValue *value ) { - - Display *display ; - XColor xWindowsColorScreen ; - XColor xWindowsColorExact ; - Colormap colormap ; - Screen *screen ; - - display = XtDisplay(w); - screen = XtScreen(w) ; - colormap = DefaultColormapOfScreen(screen); - XAllocNamedColor(display, colormap, "gray87", - &xWindowsColorScreen, - &xWindowsColorExact ) ; - value->addr = (caddr_t) &xWindowsColorScreen.pixel ; -} - -/* -** Widget initialize method -*/ -static void initialize(XYWidget request, XYWidget new) -{ - XGCValues values; - Display *display = XtDisplay(new); -#if XmVERSION >= 2 - XFontStruct *fs; -#endif - - /* Make sure the window size is not zero. The Core - initialize() method doesn't do this. */ - if (request->core.width == 0) - new->core.width = 500; - if (request->core.height == 0) - new->core.height = 400; - - /* Make a local copy of the fontlist, - or get the default if not specified */ -#if XmVERSION < 2 - if (new->xy.render_font == NULL) - new->xy.render_font = - XmFontListCopy(_XmGetDefaultFontList( - (Widget) new, XmLABEL_FONTLIST)); - else - new->xy.render_font = XmFontListCopy(new->xy.render_font); -#else - if (new->xy.render_font == NULL) - new->xy.render_font = - XmeGetDefaultRenderTable((Widget)new,XmTEXT_RENDER_TABLE); - new->xy.render_font = XmRenderTableCopy(new->xy.render_font,NULL,0); -#endif - - /* Make local copies of the XmStrings */ -/* JBF - added plotTitle from old version */ - if (new->xy.plotTitle != NULL) - new->xy.plotTitle = XmStringCopy(new->xy.plotTitle); - - if (new->xy.xAxisLabel != NULL) - new->xy.xAxisLabel = XmStringCopy(new->xy.xAxisLabel); - if (new->xy.yAxisLabel != NULL) - new->xy.yAxisLabel = XmStringCopy(new->xy.yAxisLabel); - - /* Create graphics contexts for drawing in the widget */ -#if XmVERSION < 2 - values.font = getFontStruct(new->xy.render_font)->fid; -#else - XmeRenderTableGetDefaultFont(new->xy.render_font,&fs); - values.font = fs->fid; -#endif - values.foreground = new->primitive.foreground; - values.background = new->core.background_pixel; - new->xy.gc = XCreateGC(display, XDefaultRootWindow(display), - GCForeground|GCBackground|GCFont, &values); - new->xy.contentsGC = XCreateGC(display, XDefaultRootWindow(display), - GCForeground|GCBackground|GCFont, &values); - - /* Initialize various fields */ - ResetAxisDragging(&new->xy.dragState); - new->xy.curves = NULL; - new->xy.nCurves = 0; - new->xy.strings = NULL; - new->xy.nStrings = 0; - new->xy.drawBuffer = 0; - new->xy.valueBuffer = 0; - new->xy.xEnd = 0; - new->xy.xOrigin = 0; - new->xy.yOrigin = 0; - new->xy.yEnd = 0; - new->xy.yAxisFormat = XmStringCreateLocalized("%g"); - - /* Default plotting boundaries */ - setContents((Widget)new, NULL, 0, XY_RESCALE, False); - - /* JBF - added from previous version */ - values.foreground = new->primitive.foreground ^ new->core.background_pixel; - values.line_style = LineSolid; - values.function = GXxor ; - new->xy.zoomGC = XtGetGC((Widget)new, - GCForeground | GCBackground | GCLineStyle | GCFunction, - &values); - - /* end JBF */ - - /* Keith added cross hairs */ - new->xy.enableCrosshairs = 0 ; /* Default is not using them */ - new->xy.crosshairFirst = 1 ; - - new->xy.valueDisplay = 0 ; /* Default is not using them */ - - /* Set size dependent items */ - resize(new); -} - -/* -** Widget destroy method -*/ -static void destroy(XYWidget w) -{ - int i; - - XFreeGC(XtDisplay(w), w->xy.gc); - XFreeGC(XtDisplay(w), w->xy.contentsGC); -#if XmVERSION < 2 - if (w->xy.render_font != NULL) - XmFontListFree(w->xy.render_font); -#else - if (w->xy.render_font != NULL) - XmRenderTableFree(w->xy.render_font); -#endif - if (w->xy.drawBuffer) - XFreePixmap(XtDisplay(w), w->xy.drawBuffer); - if (w->xy.valueBuffer) - XFreePixmap(XtDisplay(w), w->xy.valueBuffer); - XtRemoveAllCallbacks ((Widget)w, XmNresizeCallback); - XtRemoveAllCallbacks ((Widget)w, XmNbtn2Callback); - XtRemoveAllCallbacks ((Widget)w, XmNbtn3Callback); - XtRemoveAllCallbacks ((Widget)w, XmNredisplayCallback); - -/* JBF - added plotTitle from old version */ - if (w->xy.plotTitle != NULL) - XmStringFree(w->xy.plotTitle); - - if (w->xy.xAxisLabel != NULL) - XmStringFree(w->xy.xAxisLabel); - if (w->xy.yAxisLabel != NULL) - XmStringFree(w->xy.yAxisLabel); - if (w->xy.curves != NULL) { - for (i=0; ixy.nCurves; i++) - freeCurveData(&w->xy.curves[i], False); - XtFree((char *) w->xy.curves); - } - for (i=0; ixy.nStrings; i++) { -#if XmVERSION < 2 - XmFontListFree(w->xy.strings[i].render_font); -#else - XmRenderTableFree(w->xy.strings[i].render_font); -#endif - XmStringFree(w->xy.strings[i].string); - } - if (w->xy.nStrings != 0) - XtFree((char *)w->xy.strings); -} - -/* -** Widget resize method. Called when the total size of the widget changes -*/ -static void resize(XYWidget w) -{ - /* resize the drawing buffer, an offscreen pixmap for smoother animation */ - updateBufferAllocation(w); - - /* change size dependent values in the widget */ - resizeParts(w); - - /* call the resize callback */ - if (XtIsRealized((Widget)w)) - XtCallCallbacks((Widget)w, XmNresizeCallback, NULL); -} - -/* -** Internal resize procedure, called when the window is resized, or when -** something within the widget changes size (such as when labels are added or -** removed, or the legend changes size). Re-calculates the sizes of the -** various part of the widget (highlights, shadows, axis labels, plot -** contents, plot legend, margins, etc.) and the size dependent elements -** in the widget instance data structure. -*/ -static void resizeParts(XYWidget w) -{ - int legendHeight, borderWidth = - w->primitive.shadow_thickness + w->primitive.highlight_thickness; - XRectangle clipRect; -#if XmVERSION < 2 - XFontStruct *fs = getFontStruct(w->xy.render_font); -#else - XFontStruct *fs; - XmeRenderTableGetDefaultFont(w->xy.render_font,&fs); -#endif - - /* calculate the area of the widget where contents can be drawn */ - w->xy.xMin = borderWidth; - w->xy.yMin = borderWidth; - w->xy.xMax = w->core.width - borderWidth; - w->xy.yMax = w->core.height - borderWidth; - - /* calculate how the space within the drawable area should be divided - horizontally (layoutLegend below uses this information) */ - w->xy.axisLeft = w->xy.xMin + LEFT_MARGIN; - w->xy.xOrigin = w->xy.axisLeft + VAxisWidth(fs, w->xy.yAxisFormat); - w->xy.axisRight = w->xy.xMax - RIGHT_MARGIN; - w->xy.xEnd = w->xy.axisRight - HAxisEndClearance(fs); - - /* find out how high the legend will need to be and how many rows it has */ - layoutLegend(w, &w->xy.legendRows, &legendHeight, - &w->xy.legendColumnSpacing, &w->xy.legendLeftMargin); - - /* calculate how the space within the drawable area should be divided - vertically, depending the sizes of the labels and plot legend */ - w->xy.legendTop = w->xy.yMax - BOTTOM_MARGIN - legendHeight; - if ((w->xy.yAxisLabel != NULL) || (w->xy.plotTitle != NULL)) - w->xy.yEnd = w->xy.yMin + 3*(fs->ascent + fs->descent) + TOP_MARGIN; - else - w->xy.yEnd = VAxisEndClearance(fs) + fs->ascent/2 + TOP_MARGIN; - w->xy.axisTop = w->xy.yEnd - VAxisEndClearance(fs); - - w->xy.axisBottom = w->xy.yMax - BOTTOM_MARGIN - legendHeight - - (legendHeight == 0 ? 0 : LEGEND_TOP_MARGIN) - - (w->xy.xAxisLabel == NULL ? fs->ascent/2 : - fs->ascent + fs->descent + X_LABEL_MARGIN); - w->xy.yOrigin = w->xy.axisBottom - HAxisHeight(fs); - - /* set plot contents gc to clip drawing at the edges */ - clipRect.x = w->xy.xOrigin; - clipRect.y = w->xy.yEnd; - clipRect.width = w->xy.xEnd - w->xy.xOrigin; - clipRect.height = w->xy.yOrigin - w->xy.yEnd; - XSetClipRectangles(XtDisplay(w), w->xy.contentsGC, 0, 0, &clipRect, - 1, Unsorted); - - /* set drawing gc to clip drawing before motif shadow and highlight */ - clipRect.x = borderWidth; - clipRect.y = borderWidth; - clipRect.width = w->core.width - 2 * borderWidth; - clipRect.height = w->core.height - 2 * borderWidth; - XSetClipRectangles(XtDisplay(w), w->xy.gc, 0, 0, &clipRect, 1, Unsorted); -} - -/* -** Widget redisplay method -*/ -static void redisplay(XYWidget w, XEvent *event __attribute__ ((unused)), Region region __attribute__ ((unused))) -{ - /* Draw the Motif required shadows and highlights */ - if (w->primitive.shadow_thickness > 0) { - _XmDrawShadow (XtDisplay(w), XtWindow(w), w->primitive.bottom_shadow_GC, - w->primitive.top_shadow_GC, w->primitive.shadow_thickness, - w->primitive.highlight_thickness, - w->primitive.highlight_thickness, - w->core.width - 2 * w->primitive.highlight_thickness, - w->core.height-2 * w->primitive.highlight_thickness); - } - if (w->primitive.highlighted) - _XmHighlightBorder((Widget)w); - else if (_XmDifferentBackground((Widget)w, XtParent((Widget)w))) - _XmUnhighlightBorder((Widget)w); - - /* Now draw the contents of the xy widget */ - redisplayContents(w, X_SCREEN, REDRAW_ALL); -} - -/* -** Widget setValues method -*/ -static Boolean setValues(XYWidget current, XYWidget request __attribute__ ((unused)), XYWidget new) -{ - Boolean redraw = False, doResize = False; - Display *display = XtDisplay(new); - - /* If the background color has changed, change the GCs */ - if (new->core.background_pixel !=current->core.background_pixel) { - XSetBackground(display, new->xy.gc, new->core.background_pixel); - XSetBackground(display,new->xy.contentsGC,new->core.background_pixel); - redraw = TRUE; - } - - /* if the foreground color has changed, redraw */ - if (new->primitive.foreground != current->primitive.foreground) - redraw = TRUE; - - /* if double buffering changes, allocate or deallocate offscreen pixmap */ - if (new->xy.doubleBuffer != current->xy.doubleBuffer) { - updateBufferAllocation(new); - redraw = TRUE; - } - - /* if legend is turned on or off, resize everything */ - if (new->xy.showLegend != current->xy.showLegend) - doResize = TRUE; - -/* RCS if turning grid on or off need to redraw -*/ - if (new->xy.showGrid != current->xy.showGrid) - redraw = TRUE; - - /* if log scaling changes, re-calculate data range if the plot has a - margin, verify data (and set back to linear if data can't handle - log scaling), reset dragging, and redraw */ - if (new->xy.xLogScaling != current->xy.xLogScaling || - new->xy.yLogScaling != current->xy.yLogScaling) { - if (new->xy.marginPercent == 0) { - if (new->xy.xLogScaling && new->xy.minXData <= 0.) - new->xy.xLogScaling = False; - if (new->xy.yLogScaling && new->xy.minYData <= 0.) - new->xy.yLogScaling = False; - } else - resetDataAndViewRanges((XYWidget)new, XY_RESCALE); - ResetAxisDragging(&new->xy.dragState); - redraw = TRUE; - } - - /* if labels are changed, free the old ones and copy the new ones */ -/* JBF - added plotTitle from old version */ - /* if labels are changed, free the old ones and copy the new ones */ - if (new->xy.plotTitle != current->xy.plotTitle) { - if (current->xy.plotTitle != NULL) - XmStringFree(current->xy.plotTitle); - new->xy.plotTitle = XmStringCopy(new->xy.plotTitle); - doResize = TRUE; - } - - if (new->xy.xAxisLabel != current->xy.xAxisLabel) { - if (current->xy.xAxisLabel != NULL) - XmStringFree(current->xy.xAxisLabel); - new->xy.xAxisLabel = XmStringCopy(new->xy.xAxisLabel); - doResize = TRUE; - } - if (new->xy.yAxisLabel != current->xy.yAxisLabel) { - if (current->xy.yAxisLabel != NULL) - XmStringFree(current->xy.yAxisLabel); - new->xy.yAxisLabel = XmStringCopy(new->xy.yAxisLabel); - doResize = TRUE; - } - - /* if highlight thickness or shadow thickness changed, resize and redraw */ - if ((new->primitive.highlight_thickness != - current->primitive.highlight_thickness) || - (new->primitive.shadow_thickness != - current->primitive.shadow_thickness)) { - doResize = TRUE; - } - if (doResize) { - resize(new); - return TRUE; - } - return redraw; -} - - -/* -** JBF - added *_zoom and set_lines from old version -** -** -** Button 2 -** Button press and button motion and button release action procs for zoom. -*/ - -/* -** support routine for button 2 *_zoom action routines. -*/ -static void set_lines(ZoomData data, XPoint *points) -{ - points[0].x = points[1].x = points[4].x = data.x1; - points[0].y = points[3].y = points[4].y = data.y1; - points[1].y = points[2].y = data.y2; - points[2].x = points[3].x = data.x2; -} - -static void start_zoom(XYWidget w, XEvent *event, char *args __attribute__ ((unused)), int n_args __attribute__ ((unused))) -{ -XPoint points[5]; - - - zd.x1 = zd.x2 = event->xbutton.x; - zd.y1 = zd.y2 = event->xbutton.y; - set_lines(zd, points); - XDrawLines(XtDisplay(w), XtWindow(w), w->xy.zoomGC, - points, 5, CoordModeOrigin); - -} -static void track_zoom(XYWidget w, XEvent *event, char *args __attribute__ ((unused)), int n_args __attribute__ ((unused))) -{ -XPoint points[5]; - - set_lines(zd, points); - XDrawLines(XtDisplay(w), XtWindow(w), w->xy.zoomGC, - points, 5, CoordModeOrigin); - - zd.x2 = event->xbutton.x; - zd.y2 = event->xbutton.y; - set_lines(zd, points); - XDrawLines(XtDisplay(w), XtWindow(w), w->xy.zoomGC, - points, 5, CoordModeOrigin); - -} -static void end_zoom(XYWidget w, XEvent *event __attribute__ ((unused)), char *args __attribute__ ((unused)), int n_args __attribute__ ((unused))) -{ -XPoint points[5]; -double minXLim, minYLim, maxXLim, maxYLim; -double xScale, yScale; -int x1, y11, x2, y2; - - - set_lines( zd, points ); - XDrawLines( XtDisplay(w), XtWindow(w), w->xy.zoomGC, - points, 5, CoordModeOrigin ); - if ( abs(zd.x2 - zd.x1) < 5 || abs(zd.y2 - zd.y1) < 5 ) - { - XBell( XtDisplay( w ), 10 ); - return; /* the magnifying glass is too small */ - } - - if (zd.x1 < zd.x2) - { - x1 = zd.x1; - x2 = zd.x2; - } - else - { - x2 = zd.x1; - x1 = zd.x2; - } - if (zd.y1 > zd.y2) - { - y11 = zd.y1; - y2 = zd.y2; - } - else - { - y2 = zd.y1; - y11 = zd.y2; - } - - minXLim = w->xy.minXLim; maxXLim = w->xy.maxXLim; - minYLim = w->xy.minYLim; maxYLim = w->xy.maxYLim; - - xScale = (maxXLim - minXLim)/(w->xy.xEnd - w->xy.xOrigin); - yScale = (maxYLim - minYLim)/(w->xy.yOrigin - w->xy.yEnd); - - /* TOP */ - w->xy.maxYLim = minYLim + (double)(w->xy.yOrigin - y2) * yScale; - - /* BOTTOM */ - w->xy.minYLim = minYLim + (double)(w->xy.yOrigin - y11) * yScale; - - /* RIGHT */ - w->xy.maxXLim = minXLim + (double)(x2 - w->xy.xOrigin) * xScale; - - /* LEFT */ - w->xy.minXLim = minXLim + (double)(x1 - w->xy.xOrigin) * xScale; - - - redisplayContents(w, X_SCREEN, REDRAW_ALL); -} - - -/* -** end Button 2 press, motion, and release action procs. -*/ - -/* -** Button press and button motion action proc. -*/ -static void motionAP(XYWidget w, XEvent *event, char *args __attribute__ ((unused)), int n_args __attribute__ ((unused))) -{ - int chgdArea, redrawArea = REDRAW_NONE; - - if (event->type == ButtonPress) - XmProcessTraversal((Widget)w, XmTRAVERSE_CURRENT); - - chgdArea = DragAxes(event, w->xy.xOrigin, w->xy.xEnd, w->xy.yOrigin, - w->xy.yEnd, w->xy.axisLeft, w->xy.axisTop, w->xy.axisBottom, - w->xy.axisRight, w->xy.minXData, w->xy.maxXData, w->xy.minYData, - w->xy.maxYData, w->xy.xLogScaling, w->xy.yLogScaling, - &w->xy.minXLim, &w->xy.maxXLim, &w->xy.minYLim, &w->xy.maxYLim, - &w->xy.dragState, &w->xy.xDragStart, &w->xy.yDragStart); - if (chgdArea & DA_REDRAW_H_AXIS) redrawArea |= REDRAW_H_AXIS; - if (chgdArea & DA_REDRAW_V_AXIS) redrawArea |= REDRAW_V_AXIS; - if (chgdArea & DA_REDRAW_CONTENTS) redrawArea |= REDRAW_CONTENTS; - - redisplayContents(w, X_SCREEN, redrawArea); -} - -/* -** Shift-Button1-Down Selects A Curve -** Keith's Addition -** 7-11-2003 -*/ -static void selectCurve(XYWidget w, XEvent *event, char *args __attribute__ ((unused)), int n_args __attribute__ ((unused))) -{ - int ii ; - char* run_id ; - int closest_curve_to_mouse ; - double xOnCurve, yOnCurve ; - Drawable drawBuf; - Display *display = XtDisplay(w); - - closest_curve_to_mouse = curveClosestToMouseClick( w, event, - &xOnCurve, &yOnCurve ) ; - - if (w->xy.doubleBuffer) { - drawBuf = w->xy.drawBuffer; - } else { - drawBuf = XtWindow(w); - } - - /* Highlight selected curve and dehighlight last selected curve */ - for ( ii = 0 ; ii < w->xy.nCurves ; ii++ ) { - if ( w->xy.curves[ii].lineStyle == XY_X_THICK_LINE ) { - w->xy.curves[ii].lineStyle = XY_PLAIN_LINE ; - drawCurve(w, drawBuf, X_SCREEN, &w->xy.curves[ii]); - } - } - w->xy.curves[closest_curve_to_mouse].lineStyle = XY_X_THICK_LINE ; - - redisplayContents((XYWidget)w, X_SCREEN, REDRAW_ALL); - drawCurve(w, drawBuf, X_SCREEN, &w->xy.curves[closest_curve_to_mouse]); - - /* Do this after redisplayContents() so it - * will be more visible on top of other the curves - */ - if (w->xy.doubleBuffer ) { - XCopyArea(display, drawBuf, XtWindow(w), w->xy.gc, 0, 0, - w->core.width, w->core.height, 0, 0); - } - - if (XtIsRealized((Widget)w)) { - XtCallCallbacks((Widget)w, XmNredisplayCallback, NULL); - } - - /* Show curve number for selected curve */ - XmStringGetLtoR( w->xy.curves[closest_curve_to_mouse].curve_id, - XmFONTLIST_DEFAULT_TAG, - &run_id ) ; - label_pointer( w, xOnCurve, yOnCurve, run_id ) ; -} - -/* -** Returns curve number closest to mouse click -** Also gives the x-y location on curve (not pixel location) -** Keith's Addition -** 7-11-2003 -*/ -int curveClosestToMouseClick( XYWidget w, XEvent *event, - double* xOnCurve, double* yOnCurve ) { - - int ii ; - double xMousePos, yMousePos ; - int closest_curve_to_mouse ; - double dist, min_dist ; - double x, y ; - - getXYMousePosition( w, event, &xMousePos, &yMousePos ) ; - - min_dist = 1.0e20 ; - closest_curve_to_mouse = 0 ; - for ( ii = 0 ; ii < w->xy.nCurves ; ii++ ) { - dist = dist_point_to_curve( &(w->xy.curves[ii]), - xMousePos, yMousePos, - &x, &y ) ; - if ( dist < min_dist ) { - min_dist = dist ; - closest_curve_to_mouse = ii ; - *xOnCurve = x ; - *yOnCurve = y ; - } - } - - return( closest_curve_to_mouse ) ; -} - - -/* -** Get Current x-y location of mouse click -** Location is not in pixel coords. It is in data coords. -** Keith's addition -** 7-11-2003 -*/ -void getXYMousePosition( XYWidget w, XEvent *event, double* x, double* y ) { - - ResetAxisDragging(&w->xy.dragState) ; - - DragAxes(event, w->xy.xOrigin, w->xy.xEnd, w->xy.yOrigin, - w->xy.yEnd, w->xy.axisLeft, w->xy.axisTop, w->xy.axisBottom, - w->xy.axisRight, w->xy.minXData, w->xy.maxXData, w->xy.minYData, - w->xy.maxYData, w->xy.xLogScaling, w->xy.yLogScaling, - &w->xy.minXLim, &w->xy.maxXLim, &w->xy.minYLim, &w->xy.maxYLim, - &w->xy.dragState, &w->xy.xDragStart, &w->xy.yDragStart); - - *x = w->xy.xDragStart ; - *y = w->xy.yDragStart ; -} - -/* -** Button up action proc. -*/ -static void btnUpAP(XYWidget w, XEvent *event __attribute__ ((unused)), char *args __attribute__ ((unused)), int n_args __attribute__ ((unused))) -{ - ResetAxisDragging(&w->xy.dragState); -} - -static void btn3AP(XYWidget w, XEvent *event __attribute__ ((unused)), char *args __attribute__ ((unused)), int n_args __attribute__ ((unused))) -{ - -#ifdef ORIGINAL - XYCallbackStruct cbStruct; - XmProcessTraversal((Widget)w, XmTRAVERSE_CURRENT); - - /* Just call the callback */ - cbStruct.reason = XmCR_INPUT; - cbStruct.event = event; - XtCallCallbacks((Widget)w, XmNbtn3Callback, (XtPointer)&cbStruct); -#endif /* ORIGINAL */ - -/* JBF - copied stuff below from old version */ - - resetDataAndViewRanges(w, XY_RESCALE); - if (XtIsRealized((Widget)w)) - redisplayContents(w, X_SCREEN, REDRAW_ALL); - -} - -/* -** XYSetContents -** -** Specify the contents of the xy widget in the form of sets of points in 2D -** space. Each set has a distinct marker and/or connecting line style, and -** possibly associated error bars (horizontal and/or vertical). The data and -** appearance information for each set is called a curve. XYSetContents -** takes an array of XYCurve data structures which contain all of this data, -** and passes it along to the XY widget to display. -** -** Parameters -** -** w An xy widget -** curves An array of curves to display -** nCurves The number of curves specified in curves -** rescaleMode One of: XY_NO_RESCALE, XY_RESCALE, or -** XY_GROW_ONLY. Tells the widget how to change -** its display to incorporate the new contents. -*/ -void XYSetContents(Widget w, XYCurve *curves, int nCurves, int rescaleMode) -{ - setContents(w, curves, nCurves, rescaleMode, False); -} - -/* -** XYUpdateStyles -** -** Update the style information (marker style, line style, color, and marker -** size) for the data currently displayed by the widget, keeping the -** existing data, and ignoring the data fields in the curves structures. -** The number of curves must be the same as the currently displayed data -** -** Parameters -** -** w An xy widget -** curves An array of curve data structures containing the -** new style information, with the same number of -** elements as were passed originally in the nCurves -** argument to XYSetContents. -*/ -void XYUpdateStyles(Widget w, XYCurve *curves) -{ - int i; - - for (i=0; i<((XYWidget)w)->xy.nCurves; i++) - copyCurveStyle(&curves[i], &((XYWidget)w)->xy.curves[i]); - if (XtIsRealized(w)) - redisplayContents((XYWidget)w, X_SCREEN, REDRAW_ALL); -} - -/* -** XYUpdateData -** -** Update the data displayed by the widget, using the new data in the -** curves structure, ignoring style, color, and name information. -** The number of curves must be the same as the currently displayed data -** -** Parameters -** -** w An xy widget -** curves An array of curve data structures containing the -** new data to display, with the same number of -** elements as were passed originally in the nCurves -** argument to XYSetContents. -** rescaleMode One of: XY_NO_RESCALE, XY_RESCALE, or -** XY_GROW_ONLY. Tells the widget how to change -** its display to incorporate the new contents. -*/ -void XYUpdateData(Widget w, XYCurve *curves, int rescaleMode) -{ - setContents(w, curves, ((XYWidget)w)->xy.nCurves, rescaleMode, True); -} - -/* - * JBF - copied from previous version of plot widgets - * -** getXYCurves -** -** get the array of points from the widget -** -** Parameters -** -** w An xy widget -** -*/ -int -getXYCurves(Widget w, XYCurve **curve) -{ - XYWidget xyW = (XYWidget)w; - - *curve = xyW->xy.curves; - return (xyW->xy.nCurves); - -} - - -/* - * JBF - copied from previous version of plot widgets - * -** addPoints -** -** Add more points to the specified curve. -** -** Parameters -** -** w An xy widget -** -** curve_num -- The curve to get the new points -** -** data -- XYPoint data -** -** num_points -- the number of points in the data array -*/ -int -addXYPoints(Widget w, int curve_num, XYPoint *data, int num_points) -{ - XYWidget xyW = (XYWidget)w; - XYPoint *newPoints; - int i, j; - int nPoints; - - /* - * make sure a valid curve number was passed in - */ - if (curve_num >= xyW->xy.nCurves) - return(-1); - - /* - * make a new array for points, copy the old points into it and then - * add in the new points - */ - nPoints = xyW->xy.curves[curve_num].nPoints; - newPoints = (XYPoint *) malloc(sizeof(XYPoint) * (nPoints + num_points)); - memcpy(newPoints, xyW->xy.curves[curve_num].points, - sizeof(XYPoint) * nPoints); - for (i=nPoints, j=0; jxy.curves[curve_num].points); - xyW->xy.curves[curve_num].nPoints = nPoints+num_points; - xyW->xy.curves[curve_num].points = (XYPoint *) malloc(i); - memcpy(xyW->xy.curves[curve_num].points, newPoints, i); - free((char *)newPoints); - - /* redraw the widget with the new data */ - resizeParts(xyW); - if (XtIsRealized(w)) - redisplayContents(xyW, X_SCREEN, REDRAW_ALL); - return(0); -} - - - -static void setContents(Widget w, XYCurve *curves, int nCurves, int rescaleMode, - int dataOnly) -{ - XYWidget xyW = (XYWidget)w; - int i, redrawArea = REDRAW_NONE; - int doResize = nCurves != xyW->xy.nCurves && xyW->xy.showLegend; - - /* Free the existing data (but preserve curve structures in dataOnly - case to save appearance information) */ - if (xyW->xy.nCurves != 0) { - if (dataOnly) { - for (i=0; ixy.nCurves; i++) - freeCurveData(&xyW->xy.curves[i], True); - } else { - for (i=0; ixy.nCurves; i++) - freeCurveData(&xyW->xy.curves[i], False); - XtFree((char *)xyW->xy.curves); - } - } - - /* Copy in the user's data */ - if (nCurves != 0) { - if (!dataOnly) { - xyW->xy.curves = (XYCurve *)XtMalloc(sizeof(XYCurve) * nCurves); - xyW->xy.nCurves = nCurves; - } - for (i=0; ixy.curves[i].flatline = 0 ; - copyCurveData(&curves[i], &xyW->xy.curves[i], dataOnly); - } - } else { - xyW->xy.nCurves = 0; - xyW->xy.curves = NULL; - } - - /* if the number of curves changed, the legend may have changed size, - so recalculate the size-dependent parts of the widget */ - if (doResize) { - resizeParts(xyW); - redrawArea |= REDRAW_ALL; - } - - /* Scan the data and calculate the new data and view ranges */ - redrawArea |= resetDataAndViewRanges(xyW, rescaleMode); - - /* redraw the widget with the new data */ - if (XtIsRealized(w)) - redisplayContents(xyW, X_SCREEN, redrawArea); -} - -/* -** Examine the data currently stored in the widget, and reset both the -** maximum viewable data range (minXData, minYData, maxXData, maxYData), -** and the current visible range (minXLim, minYLim, maxXLim, maxYLim), -** according to the specified rescale mode. Returns which areas of the -** widget have changed and must be redrawn to display the changes. -*/ -static int resetDataAndViewRanges(XYWidget w, int rescaleMode) -{ - double minX, minY, maxX, maxY; - int redrawArea = REDRAW_NONE; - - /* Examine the data to find the min and max values */ - if (w->xy.nCurves == 0) { - if (rescaleMode == XY_RESCALE) { - minX = minY = 0.; - maxX = maxY = 1.; - } else { - minX = w->xy.minXData; minY = w->xy.minYData; - maxX = w->xy.maxXData; maxY = w->xy.maxYData; - } - } else - calcDataRange(w, &minX, &maxX, &minY, &maxY); - - /* recalculate plot limits from the new data (full rescale) */ - if (rescaleMode == XY_RESCALE) { - if (maxX == minX) { - if ( maxX == 0. ) { - maxX += 1.; - minX -= 1.; - } - else if ( maxX > 0. ) { - maxX *= 1.01 ; - minX *= 0.99 ; - } - else { - maxX *= 0.99 ; - minX *= 1.01 ; - } - } - if (maxY == minY) { - if ( maxY == 0. ) { - maxY += 1.; - minY -= 1.; - } - else if ( maxY > 0. ) { - maxY *= 1.01 ; - minY *= 0.99 ; - } - else { - maxY *= 0.99 ; - minY *= 1.01 ; - } - } - w->xy.maxXData = maxX; w->xy.maxXLim = maxX; - w->xy.minXData = minX; w->xy.minXLim = minX; - w->xy.maxYData = maxY; w->xy.maxYLim = maxY; - w->xy.minYData = minY; w->xy.minYLim = minY; - redrawArea |= REDRAW_CONTENTS | REDRAW_H_AXIS | REDRAW_V_AXIS; - - /* recalculate data limits but don't change visible range (no rescale) */ - } else if (rescaleMode == XY_NO_RESCALE) { - redrawArea |= REDRAW_CONTENTS; - if (maxX > w->xy.maxXData) { - w->xy.maxXData = maxX; - redrawArea |= REDRAW_H_AXIS; - } - if (minX < w->xy.minXData) { - w->xy.minXData = minX; - redrawArea |= REDRAW_H_AXIS; - } - if (maxY > w->xy.maxYData) { - w->xy.maxYData = maxY; - redrawArea |= REDRAW_V_AXIS; - } - if (minY < w->xy.minYData) { - w->xy.minYData = minY; - redrawArea |= REDRAW_V_AXIS; - } - - /* recalculate limits for rescale-at-max (normal data-update mode) */ - } else if (rescaleMode == XY_RESCALE_AT_MAX) { - redrawArea |= REDRAW_CONTENTS; - minX = dMin(w->xy.minXData, minX); - maxX = dMax(w->xy.maxXData, maxX); - minY = dMin(w->xy.minYData, minY); - maxY = dMax(w->xy.maxYData, maxY); - if (w->xy.maxXData != maxX || w->xy.minXData != minX) - redrawArea |= REDRAW_H_AXIS; - if (w->xy.maxYData != maxY || w->xy.minYData != minY) - redrawArea |= REDRAW_V_AXIS; - if (w->xy.maxXData == w->xy.maxXLim) - w->xy.maxXLim = maxX; - if (w->xy.minXData == w->xy.minXLim) - w->xy.minXLim = minX; - if (w->xy.maxYData == w->xy.maxYLim) - w->xy.maxYLim = maxY; - if (w->xy.minYData == w->xy.minYLim) - w->xy.minYLim = minY; - w->xy.maxXData = maxX; w->xy.minXData = minX; - w->xy.maxYData = maxY; w->xy.minYData = minY; - - } - return redrawArea; -} - -/* -** XYSetStrings -** -** Display a set of text strings in the plot area of the widget. Calling this -** routine removes any strings which were displayed previously and replaces -** them with the ones passed here. The strings are in the form of XYString -** data structures, which contain position, font, color, and alignment, for -** the string, in addition to the text string itself. In the XYString -** structure, font can be passed as NULL, and will default to the widget's -** fontList resource. -** -** Parameters -** -** w An xy widget -** strings Array of XYStrings data structures containing string, -** position, font, color, and alignment information -** nStrings The number of XYString data structures contained in -** strings above -** -*/ -void XYSetStrings(Widget w, XYString *strings, int nStrings) -{ - XYWidget xyW = (XYWidget)w; - int i; - - /* free the old string data */ - for (i=0; ixy.nStrings; i++) { -#if XmVERSION < 2 - XmFontListFree(xyW->xy.strings[i].render_font); -#else - XmRenderTableFree(xyW->xy.strings[i].render_font); -#endif - XmStringFree(xyW->xy.strings[i].string); - } - if (nStrings != 0) - XtFree((char *)xyW->xy.strings); - - /* copy in the new data */ - xyW->xy.nStrings = nStrings; - if (nStrings == 0) - xyW->xy.strings = NULL; - else - xyW->xy.strings = (XYString *)XtMalloc(sizeof(XYString) * nStrings); - for (i=0; ixy.strings[i] = strings[i]; -#if XmVERSION < 2 - xyW->xy.strings[i].render_font = XmFontListCopy(strings[i].render_font); -#else - xyW->xy.strings[i].render_font = XmRenderTableCopy(xyW->xy.render_font,NULL,0); -#endif - xyW->xy.strings[i].string = XmStringCopy(strings[i].string); - } - - /* update the display */ - if (XtIsRealized(w)) - redisplayContents(xyW, X_SCREEN, REDRAW_CONTENTS); -} - -/* -** XYSetVisibleRange, XYGetVisibleRange -** -** Set (Get) the range of data that is visible. minXLim, minYLim, maxXLim, and -** maxYLim specify the endpoints of the x and y axes. XYSetVisibleRange, -** unlike the widgets interactive rescaling routines, can zoom out past the -** actual minimum and maximum data points. -*/ -void XYSetVisibleRange(Widget w, double minXLim, double minYLim, - double maxXLim, double maxYLim) -{ - XYWidget xyW = (XYWidget)w; - double minX, minY, maxX, maxY; - - /* if log scaling was requested, make sure new range is log scaleable */ - if (xyW->xy.xLogScaling && minXLim <= 0.) - minXLim = FLT_MIN; - if (xyW->xy.yLogScaling && minYLim <= 0.) - minYLim = FLT_MIN; - - /* calculate the actual range of the data */ - calcDataRange(xyW, &minX, &maxX, &minY, &maxY); - - /* allow user to zoom beyond the range of the data */ - xyW->xy.maxXData = dMax(maxXLim, maxX); - xyW->xy.minXData = dMin(minXLim, minX); - xyW->xy.maxYData = dMax(maxYLim, maxY); - xyW->xy.minYData = dMin(minYLim, minY); - - /* Set the range */ - xyW->xy.minXLim = minXLim; - xyW->xy.maxXLim = maxXLim; - xyW->xy.minYLim = minYLim; - xyW->xy.maxYLim = maxYLim; - - /* redraw if the widget is realized */ - if (XtIsRealized(w)) - redisplayContents(xyW, X_SCREEN, - REDRAW_V_AXIS | REDRAW_H_AXIS | REDRAW_CONTENTS); -} -void XYGetVisibleRange(Widget w, double *minXLim, double *minYLim, - double *maxXLim, double *maxYLim) -{ - *minXLim = ((XYWidget)w)->xy.minXLim; - *maxXLim = ((XYWidget)w)->xy.maxXLim; - *minYLim = ((XYWidget)w)->xy.minYLim; - *maxYLim = ((XYWidget)w)->xy.maxYLim; -} - -/* -** XYZoomOut, XYZoomIn, XYResetZoom -** -** Zoom in and out by ZOOM_FACTOR. Zoom in is centered on the current -** center of the plot. -*/ -void XYZoomOut(Widget w) -{ - XYWidget xyW = (XYWidget)w; - int xLogScaling = xyW->xy.xLogScaling, yLogScaling = xyW->xy.yLogScaling; - double xOffset, yOffset, newMaxXLim, newMinXLim, newMaxYLim, newMinYLim; - double minXLim, maxXLim, minYLim, maxYLim; - int redrawArea = REDRAW_NONE; - - /* if log scaling was requested, express limits in log coordinates */ - minXLim = xLogScaling ? log10(xyW->xy.minXLim) : xyW->xy.minXLim; - maxXLim = xLogScaling ? log10(xyW->xy.maxXLim) : xyW->xy.maxXLim; - minYLim = yLogScaling ? log10(xyW->xy.minYLim) : xyW->xy.minYLim; - maxYLim = yLogScaling ? log10(xyW->xy.maxYLim) : xyW->xy.maxYLim; - - /* Calculate a suitable offset to reverse a zoom in by ZOOM_FACTOR */ - xOffset = (maxXLim - minXLim) * (ZOOM_FACTOR/(1.-ZOOM_FACTOR)) / 2; - yOffset = (maxYLim - minYLim) * (ZOOM_FACTOR/(1.-ZOOM_FACTOR)) / 2; - - /* widen the plotting limits by the offsets calculated above, - stopping when the limits reach the limits of the data */ - newMaxXLim = dMin(xyW->xy.maxXData, - xLogScaling ? pow(10., maxXLim + xOffset) : maxXLim + xOffset); - newMinXLim = dMax(xyW->xy.minXData, - xLogScaling ? pow(10., minXLim - xOffset) : minXLim - xOffset); - newMaxYLim = dMin(xyW->xy.maxYData, - yLogScaling ? pow(10., maxYLim + yOffset) : maxYLim + yOffset); - newMinYLim = dMax(xyW->xy.minYData, - yLogScaling ? pow(10., minYLim - yOffset) : minYLim - yOffset); - - /* Tell widget to redraw, and what parts, if limits have changed */ - if (newMaxXLim != maxXLim || newMinXLim != minXLim) - redrawArea |= REDRAW_H_AXIS | REDRAW_CONTENTS; - if (newMaxYLim != maxYLim || newMinYLim != minYLim) - redrawArea |= REDRAW_V_AXIS | REDRAW_CONTENTS; - - /* Set the new limits */ - xyW->xy.maxXLim = newMaxXLim; - xyW->xy.minXLim = newMinXLim; - xyW->xy.maxYLim = newMaxYLim; - xyW->xy.minYLim = newMinYLim; - - /* redraw if the widget is realized */ - if (XtIsRealized(w)) - redisplayContents(xyW, X_SCREEN, redrawArea); -} -void XYZoomIn(Widget w) -{ - XYWidget xyW = (XYWidget)w; - int xLogScaling = xyW->xy.xLogScaling, yLogScaling = xyW->xy.yLogScaling; - double xOffset, yOffset; - double minXLim, maxXLim, minYLim, maxYLim; - - /* if log scaling was requested, express limits in log coordinates */ - minXLim = xLogScaling ? log10(xyW->xy.minXLim) : xyW->xy.minXLim; - maxXLim = xLogScaling ? log10(xyW->xy.maxXLim) : xyW->xy.maxXLim; - minYLim = yLogScaling ? log10(xyW->xy.minYLim) : xyW->xy.minYLim; - maxYLim = yLogScaling ? log10(xyW->xy.maxYLim) : xyW->xy.maxYLim; - - /* Calculate offsets for limits of displayed data to zoom by ZOOM_FACTOR */ - xOffset = (maxXLim - minXLim) * ZOOM_FACTOR / 2; - yOffset = (maxYLim - minYLim) * ZOOM_FACTOR / 2; - - /* Narrow the plotting limits by the offsets calculated above */ - maxXLim -= xOffset; - minXLim += xOffset; - maxYLim -= yOffset; - minYLim += yOffset; - - /* Set the new limits */ - xyW->xy.maxXLim = xLogScaling ? pow(10.,maxXLim) : maxXLim; - xyW->xy.minXLim = xLogScaling ? pow(10.,minXLim) : minXLim; - xyW->xy.maxYLim = yLogScaling ? pow(10.,maxYLim) : maxYLim; - xyW->xy.minYLim = yLogScaling ? pow(10.,minYLim) : minYLim; - - /* redraw if the widget is realized */ - if (XtIsRealized(w)) - redisplayContents(xyW, X_SCREEN, - REDRAW_V_AXIS | REDRAW_H_AXIS | REDRAW_CONTENTS); -} -void XYResetZoom(Widget w) -{ - XYWidget xyW = (XYWidget)w; - double minX, minY, maxX, maxY; - - calcDataRange(xyW, &minX, &maxX, &minY, &maxY); - xyW->xy.minXLim = xyW->xy.minXData = minX; - xyW->xy.minYLim = xyW->xy.minYData = minY; - xyW->xy.maxXLim = xyW->xy.maxXData = maxX; - xyW->xy.maxYLim = xyW->xy.maxYData = maxY; - - if (XtIsRealized(w)) - redisplayContents(xyW, X_SCREEN, - REDRAW_V_AXIS | REDRAW_H_AXIS | REDRAW_CONTENTS); -} - -/* -** XYPrintContents -** -** Prints the contents XY widget to a PostScript file. -** -** Parameters -** -** w A xy widget -** psFileName Name for the PostScript file that will be created -** -*/ -void XYPrintContents(Widget w, char *psFileName) -{ - FILE * ps; - XYWidget xyW = (XYWidget)w; - - ps = OpenPS(psFileName, xyW->core.width, xyW->core.height); - if (ps != NULL) { - redisplayContents(xyW, PS_PRINTER, REDRAW_ALL); - EndPS(); - } -} - -/* - * JBF - copied from previous version of plot widgets and modified to - * make more generic. - * -** XYPrintMultiple -** -** Prints the contents of an array of XY widgets to a PostScript file. -** -** Parameters -** -** w an array of xy widgets -** num_plots number of widgets in array -** num_rows number of rows to print on page -** num_columns number of columns to print on page -** page_title page title for postscript file -** DestroyOldFile indicates whether to append to existing file -** or to create a new one -** psFileName Name for the PostScript file that will be created -** -*/ -void XYPrintMultiple(Widget w[], - int landscape, - int num_plots, - int num_rows, - int num_columns, - char *page_title, - char *page_sub_title, - Boolean DestroyOldFile, - char *psFileName) -{ - int i; - XYWidget xyW; - FILE * ps; - float page_x, page_y; - float start_page_x, start_page_y; - float max_plot_wd_inches, max_plot_ht_inches; - float actual_plot_wd_inches, actual_plot_ht_inches; - float x_scale_to_page, y_scale_to_page; - float scale_factor = 1.0 ; - int curr_row, curr_col; - int max_wd, max_ht; - double title_y_offset ; - - xyW = (XYWidget)w[0]; - - ps = OpenPSNoClip(landscape , psFileName, DestroyOldFile, - xyW->core.width, xyW->core.height); - - if (ps == (FILE *)NULL) - return; - - - max_wd = xyW->core.width; - max_ht = xyW->core.height; - for (i=1; icore.width) - max_wd = xyW->core.width; - - if (max_ht < xyW->core.height) - max_ht = xyW->core.height; - } - - /* - * Based on an 8.5 x 11 inch page: - * Compute the page space needed for each plot widget. 1/2 inch - * is allowed for page margin in each direction. Also, 1/2 inch - * vertically is allowed for the page title. That leaves a working - * page area of 8 x 10 inches. - * - */ - if ( landscape ) { - max_plot_wd_inches = 10.0/num_columns; - max_plot_ht_inches = 8.0/num_rows; - } - else { - max_plot_wd_inches = 8.0/num_columns; - max_plot_ht_inches = 10.0/num_rows; - } - - /* - * Keep the width to height ratio of the printed plot the same as - * it is on the X interface plot. - */ - x_scale_to_page = 72.0 * max_plot_wd_inches/max_wd; - y_scale_to_page = 72.0 * max_plot_ht_inches/max_ht; - - if ( !landscape ) { - if (x_scale_to_page < y_scale_to_page) - scale_factor = x_scale_to_page; - else - scale_factor = y_scale_to_page; - } - - actual_plot_wd_inches = scale_factor * ((float)max_wd/72.0); - actual_plot_ht_inches = scale_factor * ((float)max_ht/72.0); - - /* - * The scaled plots may not take up the maximum space allowed, so adjust - * their starting positions so that they will be centered within their - * allowed space. - */ - if (max_plot_wd_inches > actual_plot_wd_inches) - start_page_x = (max_plot_wd_inches - actual_plot_wd_inches)/2.0; - else - start_page_x = 0.0; - - if ( landscape ) { - start_page_x -= 5.0 / num_columns ; - } - - if (max_plot_ht_inches > actual_plot_ht_inches) - { - start_page_y = 10.0 - ((max_plot_ht_inches - actual_plot_ht_inches)/2.0); - start_page_y -= actual_plot_ht_inches; - } - else - start_page_y = 10.0 - actual_plot_ht_inches; - - if ( landscape ) { - start_page_y -= ((4.0 / num_rows) + 2.0) ; - } - - fprintf(ps, "/inch {72 mul} def\n"); - - page_x = start_page_x; - page_y = start_page_y; - curr_row = 1; - curr_col = 1; - - for (i=0; icore.width); - fprintf(ps, "%d %d lineto\n", xyW->core.width, xyW->core.height); - fprintf(ps, "0 %d lineto\n", xyW->core.height); - fprintf(ps, "closepath clip\n"); - fprintf(ps, "newpath\n"); - - - redisplayContents(xyW, PS_PRINTER, REDRAW_ALL); - - fprintf(ps,"grestore\n"); - - /* - * Update the current row and column. - */ - curr_col++; - if (curr_col > num_columns) - { - curr_col = 1; - curr_row++; - page_x = start_page_x; - page_y -= max_plot_ht_inches; - } - else - page_x +=max_plot_wd_inches; - - } - - /* - * Draw box around page. A line between each plot will be drawn below - * in the for loops. Note that this box and lines are after the - * gsave/grestore block containing the tranlate and scale statements for - * each plot. - */ - fprintf(ps, "gsave\n"); /* corresponding grestore follows showpage and - is written by EndPS */ - fprintf(ps, "0 0 moveto\n"); - - if ( landscape ) { - fprintf(ps, "10 inch 0 lineto\n"); - fprintf(ps, "10 inch 8.25 inch lineto\n"); - fprintf(ps, "0 8.25 inch lineto\n"); - } - else { - fprintf(ps, "8.25 inch 0 lineto\n"); - fprintf(ps, "8.25 inch 10 inch lineto\n"); - fprintf(ps, "0 10 inch lineto\n"); - } - - fprintf(ps, "closepath stroke\n"); - fprintf(ps, "newpath\n"); - - for (i=1; ixy.gc; - XGCValues gcValues; - Drawable drawBuf; - int i, stringWidth, stringX, alignment; - XmFontList stringFont; - Pixel lastColor; - XYString *string; - transform xform; -#if XmVERSION < 2 - XFontStruct *fs = getFontStruct(w->xy.render_font); -#else - XFontStruct *fs; - XmeRenderTableGetDefaultFont(w->xy.render_font,&fs); -#endif - - /* Save some energy if the widget isn't visible or no drawing requested */ - if ((outDevice==X_SCREEN && !w->core.visible) || redrawArea == REDRAW_NONE) - return; - - /* Set destination for drawing commands, offscreen pixmap or window */ - if (w->xy.doubleBuffer) - drawBuf = w->xy.drawBuffer; - else - drawBuf = XtWindow(w); - - /* Clear the drawing buffer or window only in the areas that have - changed. The other parts are still redrawn, but the net effect - is that the unchanged areas do not flicker */ - if (outDevice == X_SCREEN) { - XSetForeground(display, gc, w->core.background_pixel); - if (redrawArea == REDRAW_ALL) { - XFillRectangle(display, drawBuf, gc, w->xy.xMin, w->xy.yMin, - w->xy.xMax - w->xy.xMin, w->xy.yMax - w->xy.yMin); - } else { - if (redrawArea & REDRAW_V_AXIS) - XFillRectangle(display, drawBuf, gc, w->xy.axisLeft, - w->xy.axisTop, w->xy.xOrigin - w->xy.axisLeft, - w->xy.axisBottom - w->xy.axisTop); - if (redrawArea & REDRAW_H_AXIS) - XFillRectangle(display, drawBuf, gc, w->xy.axisLeft, - w->xy.yOrigin + 1, w->xy.axisRight-w->xy.axisLeft, - w->xy.axisBottom - w->xy.yOrigin + 1); - if (redrawArea & REDRAW_CONTENTS) - XFillRectangle(display, drawBuf, gc, w->xy.xOrigin + 1, - w->xy.yEnd, w->xy.xEnd - w->xy.xOrigin, - w->xy.yOrigin - w->xy.yEnd); - } - /* clear the buffer that hold the value marker. - This will tell the routine to start over */ - if ( w->xy.valueBuffer ) { - XFreePixmap(XtDisplay(w), w->xy.valueBuffer); - w->xy.valueBuffer = 0 ; - } - } - - /* Draw the axes */ - gcValues.line_width = 0; - gcValues.line_style = LineSolid; - gcValues.foreground = w->primitive.foreground; - gcValues.font = fs->fid; - XChangeGC(display, gc, GCLineWidth|GCLineStyle|GCForeground|GCFont, &gcValues); - if (w->xy.nCurves == 0) { - /* empty of data, just draw axis lines */ - XSegment segs[2]; - segs[0].x1 = segs[0].x2 = segs[1].x1 = w->xy.xOrigin; - segs[0].y1 = segs[1].y1 = segs[1].y2 = w->xy.yOrigin; - segs[1].x2 = w->xy.xEnd; segs[0].y2 = w->xy.yEnd; - if (outDevice == X_SCREEN) - XDrawSegments(display, drawBuf, gc, segs, 2); - else /* PS_PRINTER */ - PSDrawSegments(display, drawBuf, gc, segs, 2); - } else { - - DrawHorizontalAxis(display, drawBuf, gc, fs, outDevice, - w->xy.yOrigin, w->xy.yEnd, w->xy.xOrigin, - w->xy.xEnd, w->xy.minXData, - w->xy.maxXData, w->xy.minXLim, w->xy.maxXLim, - w->xy.xLogScaling, 0, w->xy.showGrid, - w->xy.gridColor, w->xy.printGridColor); - DrawVerticalAxis(display, drawBuf, gc, fs, outDevice, - w->xy.xOrigin, w->xy.xEnd, w->xy.yEnd, - w->xy.yOrigin, w->xy.minYData, - w->xy.maxYData, w->xy.minYLim, w->xy.maxYLim, - w->xy.yLogScaling, w->xy.yAxisFormat , - w->xy.showGrid, w->xy.gridColor, - w->xy.printGridColor); - } - - - /* JBF - added plotTitle from old version, but changed XmALIGNMENT_BEGINNING - * to XmALIGNMENT_CENTER - */ - - /* Draw the plot title */ - if (w->xy.plotTitle != NULL) { - if (outDevice == X_SCREEN) { - XmStringDraw(display, drawBuf, w->xy.render_font, - w->xy.plotTitle, gc, - w->xy.xOrigin + Y_LABEL_MARGIN, - w->xy.yMin + TOP_MARGIN, - w->xy.xEnd - w->xy.xOrigin, XmALIGNMENT_CENTER, - XmSTRING_DIRECTION_L_TO_R, NULL); - } - else { - PSDrawXmString(display, drawBuf, w->xy.render_font, w->xy.plotTitle, - gc, w->xy.xOrigin + Y_LABEL_MARGIN, - w->xy.yMin + TOP_MARGIN, - w->xy.xEnd - w->xy.xOrigin, XmALIGNMENT_CENTER); - } - } - - - /* Draw the axis labels */ - if (w->xy.xAxisLabel != NULL) { - if (outDevice == X_SCREEN) { - XmStringDraw(display, drawBuf, w->xy.render_font, - w->xy.xAxisLabel, gc, - w->xy.xOrigin, - w->xy.axisBottom + X_LABEL_MARGIN, - w->xy.xEnd - w->xy.xOrigin, - XmALIGNMENT_CENTER, - XmSTRING_DIRECTION_L_TO_R, - NULL); - } - else { - PSDrawXmString(display, drawBuf, w->xy.render_font, - w->xy.xAxisLabel, - gc, - w->xy.xOrigin, - w->xy.axisBottom + X_LABEL_MARGIN, - w->xy.xEnd - w->xy.xOrigin, - XmALIGNMENT_CENTER); - } - } - - - /* JBF - changed y coordinate to reflect addition of plotTitle **/ - if (w->xy.yAxisLabel != NULL) { - if (outDevice == X_SCREEN) { - XmStringDraw(display, drawBuf, w->xy.render_font, - w->xy.yAxisLabel, gc, - Y_LABEL_MARGIN, - w->xy.yMin + 2 * TOP_MARGIN + fs->ascent + fs->descent, - w->xy.xEnd - w->xy.xOrigin, - XmALIGNMENT_BEGINNING, - XmSTRING_DIRECTION_L_TO_R, - NULL); - } - else { - PSDrawXmString(display, drawBuf, w->xy.render_font, - w->xy.yAxisLabel, - gc, - w->xy.xOrigin + Y_LABEL_MARGIN, - w->xy.yMin + 2*TOP_MARGIN + - fs->ascent + fs->descent, - w->xy.xEnd - w->xy.xOrigin, - XmALIGNMENT_BEGINNING); - } - } - - /* Draw the legend */ - if (w->xy.showLegend && redrawArea == REDRAW_ALL) - drawLegend(w, drawBuf, outDevice); - - /* Draw the contents of the plot */ - for (i=0; ixy.nCurves; i++) - drawCurve(w, drawBuf, outDevice, &w->xy.curves[i]); - - /* Draw the plotted strings */ - lastColor = w->primitive.foreground; - XSetForeground(display, w->xy.contentsGC, lastColor); - computeTransform(w, &xform); - for (i=0, string=w->xy.strings; ixy.nStrings; i++, string++) { - if (string->color != lastColor) { - XSetForeground(display, w->xy.contentsGC, string->color); - lastColor = string->color; - } - stringFont = string->render_font == NULL ? - w->xy.render_font : string->render_font ; - stringWidth = XmStringWidth(stringFont, string->string); - if (string->alignment == XY_LEFT) { - stringX = dataToWindowX(&xform, string->x); - alignment = XmALIGNMENT_BEGINNING; - } else if (string->alignment == XY_CENTER) { - stringX = dataToWindowX(&xform, string->x) - stringWidth/2; - alignment = XmALIGNMENT_CENTER; - } else { /* XY_RIGHT */ - stringX = dataToWindowX(&xform, string->x) - stringWidth; - alignment = XmALIGNMENT_END; - } - if (outDevice == X_SCREEN) - XmStringDraw(display, drawBuf, stringFont, string->string, - w->xy.contentsGC, stringX, - (int)dataToWindowY(&xform, string->y), stringWidth, - alignment, XmSTRING_DIRECTION_L_TO_R, NULL); - else - PSDrawXmString(display, drawBuf, stringFont, string->string, - w->xy.contentsGC, stringX, - (int)dataToWindowY(&xform, string->y), - stringWidth, alignment); - } - - /* After zooming, initialize cross hairs */ - w->xy.crosshairFirst = 1 ; - - /* For double buffering, now copy offscreen pixmap to screen */ - if (w->xy.doubleBuffer && outDevice == X_SCREEN) - XCopyArea(display, drawBuf, XtWindow(w), gc, 0, 0, - w->core.width, w->core.height, 0, 0); - - /* Call the redisplay callback so an application which draws on the xy - widget can refresh it's graphics */ - if (XtIsRealized((Widget)w) && outDevice == X_SCREEN) - XtCallCallbacks((Widget)w, XmNredisplayCallback, NULL); -} - -/* -** Draw one curve. Note that drawing is done using the cumbersome method -** of accumulating all of the segments and marker figures for a curve -** in a counted array of X data structures and using the multiple figure -** call, such as XDrawSegments or XDrawRectangles, rather than simply making -** the call to draw the figure on the spot. This is done because in some -** circumstances there is a 10 to 1 speed difference between these two -** methods. -** -** For the most part the coordinate system -** used for drawing in this widget is the X integer coordinate system -** of the widget's window. For PostScript output, the coordinates are -** the same, but we sometimes try to acheive higher resolution by using -** floating point numbers to place points within the grid of the 72 dpi -** screen coordinates. Here, only lines without markers are -** drawn this way. Improving the print quality of all of the widgets -** is an ongoing process. -** -** The X coordinate system, being based on 16 bit integers also causes -** trouble with clipping. If the user zooms out, it is very easy to -** exceed the limits of a short integer. This widget really needs to -** do its own clipping of lines, but at the moment, it only eliminates those -** lines which are obviously outside of the boundaries of the window. Lines -** may still have endpoints far outside of the window, and at high zoom -** factors, things happen. -*/ -static void drawCurve(XYWidget w, Drawable drawBuf, int outDevice, XYCurve - *curve) -{ - int hasLines = curve->lineStyle != XY_NO_LINE; - int hasMarkers = curve->markerStyle != XY_NO_MARK; - int hasHErrs = curve->horizBars != NULL, hasVErrs = curve->vertBars != NULL; - Display *display = XtDisplay(w); - GC gc = w->xy.contentsGC; - XGCValues gcValues; - int xMin = w->xy.xOrigin, yMin = w->xy.yEnd; - int xMax = w->xy.xEnd, yMax = w->xy.yOrigin; - int markWidth = hasMarkers ? MarkWidths[(int)curve->markerSize] : 0; - int errWidth = (hasMarkers?markWidth:MED_MARK_SIZE) * ERROR_MARKER_RATIO; - int xMarkMin = xMin - markWidth/2, yMarkMin = yMin - markWidth/2; - int xMarkMax = xMax + markWidth/2, yMarkMax = yMax + markWidth/2; - int xErrMin = xMin - errWidth/2, yErrMin = yMin - errWidth/2; - int xErrMax = xMax + errWidth/2, yErrMax = yMax + errWidth/2; - XYErrorBar *hErr, *vErr; - markStruct markList; - lineStruct lineList; - XYPoint *point; - transform xform; - XSegment *seg, *segs = NULL ; - int nSegs; - double x, y, lastX, lastY, barMin, barMax; - int i, lastPointDrawn; - - XmString s0 ; - XtPointer str ; - double startx = 0.0 ; -#if XmVERSION < 2 - XFontStruct *fs = getFontStruct(w->xy.render_font); -#else - XFontStruct *fs; - XmeRenderTableGetDefaultFont(w->xy.render_font,&fs); -#endif - - /* Compute constants for data to window coordinate transformation */ - computeTransform(w, &xform); - - /* Allocate memory for points, segments and markers */ - if (hasLines) - startLineList(&lineList, outDevice, curve->nPoints); - if (hasHErrs || hasVErrs) - segs = (XSegment *)XtMalloc(sizeof(XSegment) * curve->nPoints * - ((hasHErrs ? 4 : 0) + (hasVErrs ? 4 : 0))); - if (hasMarkers) - startMarkList(&markList, curve->markerStyle, curve->nPoints); - - /* Loop through all of the data converting the data coordinates to - X coordinates and accumulating line segments and markers to draw. */ - seg = segs; - nSegs = 0; - lastPointDrawn = False; - for (i=0, point=curve->points, hErr=curve->horizBars, vErr=curve->vertBars; - inPoints; i++, point++, hErr++, vErr++) { - x = dataToWindowX(&xform, point->x); - y = dataToWindowY(&xform, point->y); - if (hasLines) { - if (i!=0 && !((lastXxMax && x>xMax) || - (lastYyMax && y>yMax))) { - if (!lastPointDrawn) - addToLineList(&lineList, lastX, lastY, True, hasMarkers); - if (xxMax || yyMax) { - /* point was clipped */ - addToLineList(&lineList, x, y, False, hasMarkers); - lastPointDrawn = False; - } else { - addToLineList(&lineList, x, y, False, hasMarkers); - lastPointDrawn = True; - if ( startx == 0.0 ) { - startx = x; - } - } - } - lastX = x; - lastY = y; - } - if (hasHErrs && y>yErrMin && ymin); - barMax = dataToWindowX(&xform, hErr->max); - if (!((barMinxMax&&barMax>xMax))) { - seg->x1 = barMin; seg->x2 = x-markWidth/2; - seg->y1 = seg->y2 = y; - seg++; nSegs++; - seg->x1 = barMax; seg->x2 = x+markWidth/2; - seg->y1 = seg->y2 = y; - seg++; nSegs++; - seg->x1 = seg->x2 = barMin; - seg->y1 = y-errWidth/2; seg->y2 = y+errWidth/2; - seg++; nSegs++; - seg->x1 = seg->x2 = barMax; - seg->y1 = y-errWidth/2; seg->y2 = y+errWidth/2; - seg++; nSegs++; - } - } - if (hasVErrs && x>xErrMin && xmin); - barMax = dataToWindowY(&xform, vErr->max); - if (!((barMinyMax&&barMax>yMax))) { - seg->x1 = seg->x2 = x; seg->y1 = barMin; - seg->y2 = y+markWidth/2; - seg++; nSegs++; - seg->x1 = seg->x2 = x; seg->y1 = barMax; - seg->y2 = y-markWidth/2; - seg++; nSegs++; - seg->x1 = x-errWidth/2; seg->x2 = x+errWidth/2; - seg->y1 = seg->y2 = barMin; - seg++; nSegs++; - seg->x1 = x-errWidth/2; seg->x2 = x+errWidth/2; - seg->y1 = seg->y2 = barMax; - seg++; nSegs++; - } - } - if (hasMarkers && x>xMarkMin && xyMarkMin && ymarkerSize); - - } - - /* Clipping information can't be read from the GCs by the PS translation - code, so it has to be set and unset by hand before and after drawing */ - if (outDevice == PS_PRINTER) - PSSetClipRectangle(xMin, yMin, xMax, yMax); - - /* Draw the line segments for the connecting lines */ - if (hasLines) - drawLineList(display, drawBuf, gc, outDevice, &lineList, curve); - - /* write a "flatline" message if the line is truly flat */ - if (curve->flatline != 0) { - if (outDevice == X_SCREEN) { - - char temp[60] ; - char temp2[60] ; - -#if XmVERSION < 2 - str = (char *)w->xy.yAxisFormat ; -#else - str = XmStringUnparse(w->xy.yAxisFormat, NULL, 0, XmCHARSET_TEXT, NULL, 0, XmOUTPUT_ALL); -#endif - sprintf(temp,"Flatline at %s" , (char *)str) ; - sprintf(temp2, temp , curve->flatlineValue ) ; - XmStringDraw(display, drawBuf, w->xy.render_font, - s0 = XmStringCreateLocalized(temp2) , gc, - (int)startx + 5 , - /*(int)y + fs->ascent ,*/ - (int)y + 2 , - w->xy.xEnd - w->xy.xOrigin, - XmALIGNMENT_BEGINNING, - XmSTRING_DIRECTION_L_TO_R, NULL); - - XtFree(str) ; - XmStringFree(s0) ; - } - } - - /* Draw error bars */ - if (hasHErrs || hasVErrs) { - gcValues.line_width = 0; - gcValues.line_style = LineSolid; - gcValues.foreground = curve->linePixel; - XChangeGC(display, gc, GCLineWidth|GCLineStyle|GCForeground, &gcValues); - if (outDevice == X_SCREEN) - XDrawSegments(display, drawBuf, gc, segs, nSegs); - else - PSDrawSegments(display, drawBuf, gc, segs, nSegs); - XtFree((char *)segs); - } - - /* Draw markers */ - if (hasMarkers) - drawMarkList(display, drawBuf, gc, outDevice, &markList, curve); - - /* Unset temporary clipping on print output */ - if (outDevice == PS_PRINTER) - PSSetClipRectangle(xMin, yMin, xMax, yMax); -} - -/* -** Allocate memory and initialize a lineList data structure to begin -** accumulating groups of lines to draw. Lines are accumulated either -** in XPoint form, for the screen, or FloatPoint form for higher resolution -** on a PostScript printer. Used in conjunction with addToLineList and -** drawLineList. drawLineList deallocates the memory allocated here -*/ -static void startLineList(lineStruct *lineList, int outDevice, int maxSegs) -{ - if (outDevice == X_SCREEN) - lineList->fillPtr = lineList->points = - (XPoint *)XtMalloc(sizeof(XPoint) * maxSegs * 2); - else - lineList->fFillPtr = lineList->floatPoints = - (FloatPoint *)XtMalloc(sizeof(FloatPoint) * maxSegs * 2); - lineList->lineCounts = (int *)XtMalloc(sizeof(int) * maxSegs); - lineList->curLineCount = lineList->lineCounts; - *lineList->curLineCount = 0; - lineList->outDevice = outDevice; -} - -/* -** Add a new point to an accumulating line to be drawn later. See -** startLineList and drawLineList for more information. restart tells the -** function to begin a new run of connected segments (i.e. don't draw -** a line from the last point to this one). If round is true, rounds -** x and y to the nearest integer value. This is used in the case of -** printer output to reduce the resolution, since markers are not yet drawn -** at the higher resolution, and the lines don't look good if they don't -** join the markers (esp. small ones) exactly. -*/ -static void addToLineList(lineStruct *lineList, float x, float y, int restart, - int round) -{ - if (restart && *lineList->curLineCount != 0) { - lineList->curLineCount++; - *lineList->curLineCount = 0; - } - if (lineList->outDevice == X_SCREEN) { - lineList->fillPtr->x = x; - lineList->fillPtr->y = y; - lineList->fillPtr++; - } else { - lineList->fFillPtr->x = round ? (int)x : x; - lineList->fFillPtr->y = round ? (int)y : y; - lineList->fFillPtr++; - } - (*lineList->curLineCount)++; -} - -/* -** drawLineList draws the lines accumulated in lineList (see startLineList -** and addToLineList). The argument "curve" supplies style information. -** Uses repeated calls to either XDrawLines or PSFloatDrawLines. Also -** deallocates memory attached to lineList, allocated by startLineList. -*/ -static void drawLineList(Display *display, Drawable drawBuf, GC gc, - int outDevice, lineStruct *lineList, XYCurve *curve) -{ - XGCValues gcValues; - XPoint *pt; - FloatPoint *fpt; - int nLineCounts = (lineList->curLineCount - lineList->lineCounts) + 1; - int i, *count, style = curve->lineStyle; - - /* set up the graphics context. the convention for GCs in this widget - is that line style, width, and color are not preserved */ - gcValues.line_width = style == XY_THICK_LINE ? 2 : - (style == XY_X_THICK_LINE ? 3 : 0); - gcValues.foreground = curve->linePixel; - gcValues.line_style = (style==XY_PLAIN_LINE || style==XY_THICK_LINE || - style==XY_X_THICK_LINE) ? LineSolid : LineOnOffDash; - XChangeGC(display, gc, GCLineWidth|GCLineStyle|GCForeground, &gcValues); - XSetDashes(display, gc, 0, DashLists[style], strlen(DashLists[style])); - - if (outDevice == X_SCREEN) { - pt = lineList->points; - for (i=0, count=lineList->lineCounts; ipoints); - } else { /* outDevice == PS_PRINTER */ - fpt = lineList->floatPoints; - for (i=0, count=lineList->lineCounts; ifloatPoints); - } - XtFree((char *)lineList->lineCounts); -} - -/* -** allocate storage for segments, rectangles or arcs for drawing markers -*/ -static void startMarkList(markStruct *markList, int markerStyle, int maxLength) -{ - int size; - - markList->style = markerStyle; - switch (markerStyle) { - case XY_NO_MARK: - size = 0; - break; - case XY_SQUARE_MARK: case XY_SOLID_SQUARE_MARK: case XY_THICK_SQUARE_MARK: - size = sizeof(XRectangle); - break; - case XY_CIRCLE_MARK: case XY_SOLID_CIRCLE_MARK: case XY_THICK_CIRCLE_MARK: - size = sizeof(XArc); - break; - case XY_STAR_MARK: - size = sizeof(XSegment) * 4; - break; - case XY_X_MARK: - size = sizeof(XSegment) * 2; - break; - case XY_TRIANGLE_MARK: - size = sizeof(XSegment) * 3; - break; - } - markList->list = (void *)XtMalloc(size * maxLength); - markList->fillPtr = markList->list; - markList->nFigures = 0; -} - -/* -** Add the appropriate figure(s) to markList to eventually draw a marker at -** the location (x,y). The list must have been allocated with startMarkList, -** and should be drawn and disposed of with drawMarkList. -*/ -static void addToMarkList(markStruct *markList, int x, int y, int size) -{ - int markWidth = MarkWidths[size]; - - switch (markList->style) { - case XY_NO_MARK: - break; - case XY_SQUARE_MARK: case XY_SOLID_SQUARE_MARK: case XY_THICK_SQUARE_MARK: - ((XRectangle *)markList->fillPtr)->x = x - markWidth/2; - ((XRectangle *)markList->fillPtr)->y = y - markWidth/2; - ((XRectangle *)markList->fillPtr)->width = markWidth; - ((XRectangle *)markList->fillPtr)->height = markWidth; - markList->fillPtr += sizeof(XRectangle); - markList->nFigures++; - break; - case XY_CIRCLE_MARK: case XY_SOLID_CIRCLE_MARK: case XY_THICK_CIRCLE_MARK: - ((XArc *)markList->fillPtr)->x = x - markWidth/2; - ((XArc *)markList->fillPtr)->y = y - markWidth/2; - ((XArc *)markList->fillPtr)->width = markWidth; - ((XArc *)markList->fillPtr)->height = markWidth; - ((XArc *)markList->fillPtr)->angle1 = 0; - ((XArc *)markList->fillPtr)->angle2 = 360 * 64; - markList->fillPtr += sizeof(XArc); - markList->nFigures++; - break; - case XY_STAR_MARK: - ((XSegment *)markList->fillPtr)->x1 = x; - ((XSegment *)markList->fillPtr)->y1 = y - markWidth/2; - ((XSegment *)markList->fillPtr)->x2 = x; - ((XSegment *)markList->fillPtr)->y2 = y + markWidth/2; - markList->fillPtr += sizeof(XSegment); - ((XSegment *)markList->fillPtr)->x1 = x - markWidth/2; - ((XSegment *)markList->fillPtr)->y1 = y; - ((XSegment *)markList->fillPtr)->x2 = x + markWidth/2; - ((XSegment *)markList->fillPtr)->y2 = y; - markList->fillPtr += sizeof(XSegment); - markList->nFigures += 2; - /* no break, uses XY_X_MARK */ - case XY_X_MARK: - ((XSegment *)markList->fillPtr)->x1 = x - markWidth/2; - ((XSegment *)markList->fillPtr)->y1 = y - markWidth/2; - ((XSegment *)markList->fillPtr)->x2 = x + markWidth/2; - ((XSegment *)markList->fillPtr)->y2 = y + markWidth/2; - markList->fillPtr += sizeof(XSegment); - ((XSegment *)markList->fillPtr)->x1 = x + markWidth/2; - ((XSegment *)markList->fillPtr)->y1 = y - markWidth/2; - ((XSegment *)markList->fillPtr)->x2 = x - markWidth/2; - ((XSegment *)markList->fillPtr)->y2 = y + markWidth/2; - markList->fillPtr += sizeof(XSegment); - markList->nFigures += 2; - break; - case XY_TRIANGLE_MARK: - ((XSegment *)markList->fillPtr)->x1 = x; - ((XSegment *)markList->fillPtr)->y1 = y - markWidth/2; - ((XSegment *)markList->fillPtr)->x2 = x + markWidth/2; - ((XSegment *)markList->fillPtr)->y2 = y + markWidth/2; - markList->fillPtr += sizeof(XSegment); - ((XSegment *)markList->fillPtr)->x1 = x + markWidth/2; - ((XSegment *)markList->fillPtr)->y1 = y + markWidth/2; - ((XSegment *)markList->fillPtr)->x2 = x - markWidth/2; - ((XSegment *)markList->fillPtr)->y2 = y + markWidth/2; - markList->fillPtr += sizeof(XSegment); - ((XSegment *)markList->fillPtr)->x1 = x - markWidth/2; - ((XSegment *)markList->fillPtr)->y1 = y + markWidth/2; - ((XSegment *)markList->fillPtr)->x2 = x; - ((XSegment *)markList->fillPtr)->y2 = y - markWidth/2; - markList->fillPtr += sizeof(XSegment); - markList->nFigures += 3; - break; - } -} - -/* -** Draw the markers accumulated with addToMarkList and free the list -*/ -static void drawMarkList(Display *display, Drawable drawBuf, GC gc, - int outDevice, markStruct *markList, XYCurve *curve) -{ - XGCValues gcValues; - int size = curve->markerSize, style = curve->markerStyle; - - /* set up the graphics context. the convention for GCs in this widget - is that line style, width, and color are not preserved */ - if (style==XY_THICK_SQUARE_MARK || style==XY_THICK_CIRCLE_MARK) - gcValues.line_width = size==XY_SMALL ? 1 : - (size==XY_MEDIUM || size==XY_LARGE ? 2 : 0); - else - gcValues.line_width = 0; - gcValues.line_style = LineSolid; - gcValues.foreground = curve->markerPixel; - XChangeGC(display, gc, GCLineWidth|GCLineStyle|GCForeground, &gcValues); - - if (outDevice == X_SCREEN) { - switch (style) { - case XY_NO_MARK: - break; - case XY_SQUARE_MARK: case XY_THICK_SQUARE_MARK: - XDrawRectangles(display, drawBuf, gc, (XRectangle *)markList->list, - markList->nFigures); - break; - case XY_SOLID_SQUARE_MARK: - XFillRectangles(display, drawBuf, gc, (XRectangle *)markList->list, - markList->nFigures); - break; - case XY_CIRCLE_MARK: case XY_THICK_CIRCLE_MARK: - XDrawArcs(display, drawBuf, gc, (XArc *)markList->list, - markList->nFigures); - break; - case XY_SOLID_CIRCLE_MARK: - XFillArcs(display, drawBuf, gc, (XArc *)markList->list, - markList->nFigures); - break; - case XY_STAR_MARK: case XY_X_MARK: case XY_TRIANGLE_MARK: - XDrawSegments(display, drawBuf, gc, (XSegment *)markList->list, - markList->nFigures); - break; - } - } else { /* PS_PRINTER */ - switch (style) { - case XY_NO_MARK: - break; - case XY_SQUARE_MARK: case XY_THICK_SQUARE_MARK: - PSDrawRectangles(display, drawBuf, gc, (XRectangle *)markList->list, - markList->nFigures); - break; - case XY_SOLID_SQUARE_MARK: - PSFillRectangles(display, drawBuf, gc, (XRectangle *)markList->list, - markList->nFigures); - break; - case XY_CIRCLE_MARK: case XY_THICK_CIRCLE_MARK: - PSDrawArcs(display, drawBuf, gc, (XArc *)markList->list, - markList->nFigures); - break; - case XY_SOLID_CIRCLE_MARK: - PSFillArcs(display, drawBuf, gc, (XArc *)markList->list, - markList->nFigures); - break; - case XY_STAR_MARK: case XY_X_MARK: case XY_TRIANGLE_MARK: - PSDrawSegments(display, drawBuf, gc, (XSegment *)markList->list, - markList->nFigures); - break; - } - } - XtFree((char *)markList->list); -} - -/* -** Find the best layout for a legend for the current set of named curves that -** the widget contains. Returns the number of rows, height, column width, and -** left margin for the optimal layout. -*/ -static void layoutLegend(XYWidget w, int *nRows, int *legendHeight, - int *columnWidth, int *leftMargin) -{ - int xOrigin = w->xy.xOrigin, xEnd = w->xy.xEnd; - int n, row, rows, colHeight, maxColHeight, width=0, nCols=0; /* JBF - inited*/ - XYCurve *curve; - - /* If the legend is hidden */ - if (!w->xy.showLegend) { - *nRows = 0; - *legendHeight = 0; - *leftMargin = 0; - *columnWidth = 0; - return; - } - - /* Find how many rows and columns will fit all of the curve names, - and the width of that layout for centering later */ - for (rows=1; rows<=w->xy.nCurves; rows++) - if (tryLegendLayout(w, rows, &width, &nCols)) - break; - *nRows = rows; - - /* Find the height of the legend */ - maxColHeight = 0; - row = 1; - colHeight = 0; - for (curve=w->xy.curves, n=0; nxy.nCurves; curve++, n++) { - colHeight += XmStringHeight(w->xy.render_font, curve->name); - if (row >= rows) { - maxColHeight = colHeight > maxColHeight ? colHeight : maxColHeight; - row = 1; - colHeight = 0; - } else - row++; - } - *legendHeight = maxColHeight; - - /* determine a pleasant vertical spacing (column spacing and margins), - with the goal of centering the legend under the horizontal axis line - with the widest possible column spacing, but ignoring centering to - pack the legend in as few rows as possible. */ - if (width > xEnd - xOrigin + - 2 * ((w->xy.xMax - LEGEND_RIGHT_MARGIN) - w->xy.xEnd)) { - /* can't center, just move left margin */ - *columnWidth = LEGEND_COLUMN_MARGIN; - *leftMargin = w->xy.xMax - LEGEND_RIGHT_MARGIN - width; - if (*leftMargin < w->xy.xMin + LEGEND_LEFT_MARGIN) - *leftMargin = w->xy.xMin + LEGEND_LEFT_MARGIN; - } else if (width > xEnd - xOrigin || nCols <= 1) { - /* can center, but can't adjust column spacing */ - *columnWidth = LEGEND_COLUMN_MARGIN; - *leftMargin = xOrigin + ((xEnd - xOrigin) - width)/2; - } else { - /* can center and widen column spacing */ - *columnWidth = ((xEnd - xOrigin) - (width - - (LEGEND_COLUMN_MARGIN*(nCols-1)))) / (nCols-1); - *leftMargin = xOrigin; - } -} - -/* -** Draw the plot legend at the bottom of the widget -*/ -static void drawLegend(XYWidget w, Drawable drawBuf, int outDevice) -{ - Display *display = XtDisplay(w); - GC gc = w->xy.gc; - int markerWidth, lineWidth, style; - int n, top_, left, row, col, maxNameWidth, nameWidth, nameHeight; - int sampleY, sampleX1, sampleX2, nameX; - XYCurve *curve; - - top_ = w->xy.legendTop; - left = w->xy.legendLeftMargin; - row = 1; - col = 1; - maxNameWidth = 0; - style = legendColumnStyle(w->xy.curves, w->xy.nCurves, 1, w->xy.legendRows); - for (curve=w->xy.curves, n=0; nxy.nCurves; curve++, n++) { - markerWidth = (style==NO_MARKERS ? 0 : LARGE_MARK_SIZE); - lineWidth = (style==NO_LINES ? 0 : LEGEND_LINE_LEN); - nameHeight = XmStringHeight(w->xy.render_font, curve->name); - nameWidth = XmStringWidth(w->xy.render_font, curve->name); - sampleY = top_ + nameHeight/2; - sampleX1 = left + markerWidth/2; - sampleX2 = sampleX1 + lineWidth; - nameX = left + LEGEND_NAME_SPACING + markerWidth + lineWidth; - if (curve->lineStyle != XY_NO_LINE) - drawMarker(display, drawBuf, gc, outDevice, curve, - sampleX1, sampleY); - drawMarker(display, drawBuf, gc, outDevice, curve, sampleX2, sampleY); - drawLine(display, drawBuf, gc, outDevice, curve, - sampleX1, sampleY, sampleX2, sampleY); - XSetForeground(display, gc, w->primitive.foreground); - if (outDevice == X_SCREEN) - XmStringDraw(display, drawBuf, w->xy.render_font, curve->name, gc, - nameX, top_, nameWidth, XmALIGNMENT_BEGINNING, - XmSTRING_DIRECTION_L_TO_R, NULL); - else - PSDrawXmString(display, drawBuf, w->xy.render_font, curve->name, gc, - nameX, top_, nameWidth, XmALIGNMENT_BEGINNING); - maxNameWidth = nameWidth > maxNameWidth ? nameWidth : maxNameWidth; - if (row >= w->xy.legendRows) { - top_ = w->xy.legendTop; - left = nameX + maxNameWidth + w->xy.legendColumnSpacing; - row = 1; - col++; - maxNameWidth = 0; - style = legendColumnStyle(w->xy.curves, w->xy.nCurves, col, - w->xy.legendRows); - } else { - top_ += nameHeight; - row++; - } - } -} - -/* -** Find out if a layout using a given number of rows is possible, and if -** so, the minimum width and number of columns it would contain. -*/ -static int tryLegendLayout(XYWidget w, int nRows, int *width, int *nColumns) -{ - int curve, colStart, colWidth, row, fieldWidth, nCols, style; - int maxWidth = (w->xy.xMax - LEGEND_RIGHT_MARGIN) - - (w->xy.xMin + LEGEND_LEFT_MARGIN); - - curve = 0; - colStart = 0; - nCols = 0; - while (curve < w->xy.nCurves) { - nCols++; - style = legendColumnStyle(w->xy.curves, w->xy.nCurves, nCols, nRows); - colWidth = 0; - for (row=1; row<=nRows; row++) { - fieldWidth = (style==NO_LINES ? 0 : LEGEND_LINE_LEN) + - (style==NO_MARKERS ? 0 : LARGE_MARK_SIZE) + - LEGEND_NAME_SPACING + (w->xy.curves[curve].name == NULL ? - 0 : XmStringWidth(w->xy.render_font, w->xy.curves[curve].name)); - colWidth = fieldWidth > colWidth ? fieldWidth : colWidth; - if (++curve >= w->xy.nCurves) - break; - } - if (colStart + colWidth > maxWidth && nRows < w->xy.nCurves) - return False; - colStart += colWidth + LEGEND_COLUMN_MARGIN; - } - *width = colStart - LEGEND_COLUMN_MARGIN; - *nColumns = nCols; - return True; -} - -/* -** Given a column number and the number of rows in the legend, calculates -** how the column should appear: NO_LINES, NO_MARKERS, or FULL_LEGEND -*/ -static int legendColumnStyle(XYCurve *curves, int nCurves, int colNum, - int nRows) -{ - int i, hasMarkers = False, hasLines = False; - -/** JBF ** - for (i=(colNum-1)*nRows; imarkerStyle == XY_NO_MARK) - return; - startMarkList(&markList, curve->markerStyle, 1); - addToMarkList(&markList, x, y, curve->markerSize); - drawMarkList(display, drawBuf, gc, outDevice, &markList, curve); -} - -/* -** Draw a single line of style defined by curve from (x1, y1) to (x2, y2) -*/ -static void drawLine(Display *display, Drawable drawBuf, GC gc, int outDevice, - XYCurve *curve, int x1, int y11, int x2, int y2) -{ - lineStruct lineList; - - if (curve->lineStyle == XY_NO_LINE) - return; - startLineList(&lineList, outDevice, 2); - addToLineList(&lineList, x1, y11, True, False); - addToLineList(&lineList, x2, y2, False, False); - drawLineList(display, drawBuf, gc, outDevice, &lineList, curve); -} - -/* -** For smoother animation, it is possible to allocate an offscreen pixmap -** and draw to that rather than directly into the window. Unfortunately, -** it is too slow on many machines, so we have to give the user the choice -** whether to use it or not. This routine reallocates the offscreen -** pixmap buffer when the window is resized, and when the widget is created -*/ -static void updateBufferAllocation(XYWidget w) -{ - if (w->xy.drawBuffer) - XFreePixmap(XtDisplay(w), w->xy.drawBuffer); - if (w->xy.doubleBuffer) { - w->xy.drawBuffer = XCreatePixmap(XtDisplay(w), - DefaultRootWindow(XtDisplay(w)), w->core.width, w->core.height, - DefaultDepthOfScreen(XtScreen(w))); - } else { - w->xy.drawBuffer = 0; - } - -} - -#if XmVERSION >= 2 - -/* -** In Motif 2.0 and later, XmFontList is an obsolete data type. -** Use XmRenderTable instead. -*/ -static void DefaultFont( - Widget w, - int offset __attribute__ ((unused)), - XrmValue *value) -{ - static XmRenderTable rt; - - rt = XmeGetDefaultRenderTable(w,XmTEXT_RENDER_TABLE); - value->addr = (XtPointer) &rt; - value->size = sizeof(rt); - -} /* end DefaultFont */ - -#else /* Motif 1.x */ -/* -** Get the XFontStruct that corresponds to the default (first) font in -** a Motif font list. Since Motif stores this, it saves us from storing -** it or querying it from the X server. -*/ -#if ((XmVERSION >= 1) && (XmREVISION >= 2)) -/* - * JBF - updated for motif 1.2 - * XmFontListGetNextFont is obsolete in Motif 1.2 - */ - -/* Motif 1.2 or newer */ -static XFontStruct *getFontStruct(XmFontList font) -{ - XFontStruct *fs; - XmFontContext context; - XmFontListEntry entry; - XmFontType type_return; - XtPointer font_info; - int num_fs; - XFontStruct **font_struct_list_return; - char **font_name_list_return; - - XmFontListInitFontContext(&context, font); - entry = XmFontListNextEntry(context); - if (entry != (XmFontListEntry) NULL) - { - font_info = XmFontListEntryGetFont(entry,&type_return); - if (type_return == XmFONT_IS_FONT) - fs = (XFontStruct *)font_info; - else /* type_return == XmFONT_IS_FONTSET */ - { - num_fs = XFontsOfFontSet((XFontSet)font_info, - &font_struct_list_return, - &font_name_list_return); - if (num_fs > 0) - fs = font_struct_list_return[0]; - else - fs = (XFontStruct *)NULL; - } - } - else - fs = (XFontStruct *)NULL; - - XmFontListFreeFontContext(context); - return fs; -} - -#else -/* Motif 1.1 */ - -static XFontStruct *getFontStruct(XmFontList font) -{ - XFontStruct *fs; - XmFontContext context; - XmStringCharSet charset; - - XmFontListInitFontContext(&context, font); - XmFontListGetNextFont(context, &charset, &fs); - XmFontListFreeFontContext(context); - XtFree(charset); - return fs; -} -#endif /* for Motif 1.2 or greater */ -#endif /* for Motif 2 of greater */ - - -/* -** Calculate the actual extent of the data in the widget. As a side-effect, -** may reset xLogScaling or yLogScaling to false if data can not be displayed -** in log scaling mode. -*/ -static void calcDataRange(XYWidget w, double *xMin, double *xMax, double *yMin, - double *yMax) -{ - XYCurve *curve; - double minX = FLT_MAX, minY = FLT_MAX, maxX = -FLT_MAX, maxY = -FLT_MAX; - double cMinX, cMaxX, cMinY, cMaxY, logMin, logMax; - int n; - - /* combine the ranges from all of the curves */ - for (n=0, curve=w->xy.curves; nxy.nCurves; n++, curve++) { - oneCurveDataRange(w, curve, &cMinX, &cMaxX, &cMinY, &cMaxY); - minX = dMin(minX, cMinX); - maxX = dMax(maxX, cMaxX); - minY = dMin(minY, cMinY); - maxY = dMax(maxY, cMaxY); - if ( cMinY == cMaxY ) { - curve->flatline = 1 ; - curve->flatlineValue = cMinY ; - } - } - - /* Check that log scaling is possible with current data and current - settings of xLogScaling and yLogScaling. If it is not possible, - resets x or yLogScaling to False and takes no further action. */ - if (w->xy.xLogScaling && minX <= 0.) - w->xy.xLogScaling = False; - if (w->xy.yLogScaling && minY <= 0.) - w->xy.yLogScaling = False; - - /* expand the range by plot margin percentage (used mostly to make - room for markers and error bar tops) */ - if (w->xy.xLogScaling) { - logMin = log10(minX); - logMax = log10(maxX); - minX = pow(10., logMin - (logMax - logMin) * w->xy.marginPercent / 100); - maxX = pow(10., logMax + (logMax - logMin) * w->xy.marginPercent / 100); - } else { - minX -= (maxX - minX) * w->xy.marginPercent / 100; - maxX += (maxX - minX) * w->xy.marginPercent / 100; - } - if (w->xy.yLogScaling) { - logMin = log10(minY); - logMax = log10(maxY); - minY = pow(10., logMin - (logMax - logMin) * w->xy.marginPercent / 100); - maxY = pow(10., logMax + (logMax - logMin) * w->xy.marginPercent / 100); - } else { - minY -= (maxY - minY) * w->xy.marginPercent / 100; - maxY += (maxY - minY) * w->xy.marginPercent / 100; - } - - *xMin = minX; *yMin = minY; *xMax = maxX; *yMax = maxY; -} - -/* -** Find the rectangular area covered by a curve, including error bars and -** decorations (markers and error bar ends) -*/ -static void oneCurveDataRange(XYWidget w __attribute__ ((unused)), XYCurve *curve, double *xMin, - double *xMax, double *yMin, double *yMax) -{ - XYPoint *point; - XYErrorBar *vert, *hor; - double minX = FLT_MAX, minY = FLT_MAX, maxX = -FLT_MAX, maxY = -FLT_MAX; - int i; - - /* Loop through all of the data, recording minimum and maximum values */ - if (curve->vertBars != NULL && curve->horizBars != NULL) { - for (i=0, point=curve->points, vert=curve->vertBars, - hor=curve->horizBars; inPoints; - i++, point++, vert++, hor++) { - if (point->x > maxX) maxX = point->x; - if (hor->max > maxX) maxX = hor->max; - if (point->y > maxY) maxY = point->y; - if (vert->max > maxY) maxY = vert->max; - if (point->x < minX) minX = point->x; - if (hor->min < minX) minX = hor->min; - if (point->y < minY) minY = point->y; - if (vert->min < minY) minY = vert->min; - } - } else if (curve->vertBars != NULL) { - for (i=0, point=curve->points, vert=curve->vertBars; - inPoints; i++, point++, vert++) { - if (point->x > maxX) maxX = point->x; - if (point->y > maxY) maxY = point->y; - if (vert->max > maxY) maxY = vert->max; - if (point->x < minX) minX = point->x; - if (point->y < minY) minY = point->y; - if (vert->min < minY) minY = vert->min; - } - } else if (curve->horizBars != NULL) { - for (i=0, point=curve->points, hor=curve->horizBars; - inPoints; i++, point++, hor++) { - if (point->x > maxX) maxX = point->x; - if (hor->max > maxX) maxX = hor->max; - if (point->y > maxY) maxY = point->y; - if (point->x < minX) minX = point->x; - if (hor->min < minX) minX = hor->min; - if (point->y < minY) minY = point->y; - } - } else { - for (i=0, point=curve->points; inPoints; i++, point++) { - if (point->x > maxX) maxX = point->x; - if (point->y > maxY) maxY = point->y; - if (point->x < minX) minX = point->x; - if (point->y < minY) minY = point->y; - } - } - - *xMin = minX; *yMin = minY; *xMax = maxX; *yMax = maxY; -} - -/* Compute constants for data to window coordinate transformation */ -static void computeTransform(XYWidget w, transform *xform) -{ - /* If log scaling was requested, express limits in log coordinates */ - if (w->xy.xLogScaling) { - xform->minXData = log10(w->xy.minXData); - xform->minXLim = log10(w->xy.minXLim); - xform->maxXLim = log10(w->xy.maxXLim); - } else { - xform->minXData = w->xy.minXData; - xform->minXLim = w->xy.minXLim; - xform->maxXLim = w->xy.maxXLim; - } - if (w->xy.yLogScaling) { - xform->minYData = log10(w->xy.minYData); - xform->minYLim = log10(w->xy.minYLim); - xform->maxYLim = log10(w->xy.maxYLim); - } else { - xform->minYData = w->xy.minYData; - xform->minYLim = w->xy.minYLim; - xform->maxYLim = w->xy.maxYLim; - } - xform->xScale = (w->xy.xEnd - w->xy.xOrigin) / - (xform->maxXLim - xform->minXLim); - xform->yScale = (w->xy.yOrigin - w->xy.yEnd) / - (xform->maxYLim - xform->minYLim); - xform->minXPix = w->xy.xOrigin - - (xform->minXLim - xform->minXData) * xform->xScale; - xform->maxYPix = w->xy.yOrigin + - (xform->minYLim - xform->minYData) * xform->yScale; - xform->xLogScaling = w->xy.xLogScaling; - xform->yLogScaling = w->xy.yLogScaling; -} - -/* Convert X and Y values from data coordinates to window coordinates. - Requires valid transformation data from computeTransform above */ -static double dataToWindowX(transform *xform, double value) -{ - if (xform->xLogScaling) - return xform->minXPix + (log10(value)-xform->minXData) * xform->xScale; - else - return xform->minXPix + (value - xform->minXData) * xform->xScale; -} -static double dataToWindowY(transform *xform, double value) -{ - if (xform->yLogScaling) - return xform->maxYPix - (log10(value)-xform->minYData) * xform->yScale; - else - return xform->maxYPix - (value - xform->minYData) * xform->yScale; -} - -/* Copies data from one curve data structure to another */ -static void copyCurveData(XYCurve *fromCurve, XYCurve *toCurve, int dataOnly) -{ - int pointDataSize, errDataSize; - - if (!dataOnly) { - copyCurveStyle(fromCurve, toCurve); - toCurve->nPoints = fromCurve->nPoints; - } - - pointDataSize = sizeof(XYPoint) * fromCurve->nPoints; - toCurve->points = (XYPoint *)XtMalloc(pointDataSize); - - memcpy(toCurve->points, fromCurve->points, pointDataSize); - errDataSize = sizeof(XYErrorBar) * fromCurve->nPoints; - - if (fromCurve->horizBars != NULL) { - toCurve->horizBars = (XYErrorBar *)XtMalloc(errDataSize); - memcpy(toCurve->horizBars, fromCurve->horizBars, errDataSize); - } else { - toCurve->horizBars = NULL; - } - - if (fromCurve->vertBars != NULL) { - toCurve->vertBars = (XYErrorBar *)XtMalloc(errDataSize); - memcpy(toCurve->vertBars, fromCurve->vertBars, errDataSize); - } else { - toCurve->vertBars = NULL; - } - -} - -/* Copies name and style information from one curve data structure to another */ -static void copyCurveStyle(XYCurve *fromCurve, XYCurve *toCurve) -{ - toCurve->curve_id = fromCurve->curve_id == NULL ? - NULL : XmStringCopy(fromCurve->curve_id); - - toCurve->name = fromCurve->name == NULL ? - NULL : XmStringCopy(fromCurve->name); - - toCurve->markerStyle = fromCurve->markerStyle; - toCurve->markerSize = fromCurve->markerSize; - toCurve->lineStyle = fromCurve->lineStyle; - toCurve->markerPixel = fromCurve->markerPixel; - toCurve->linePixel = fromCurve->linePixel; -} - -/* Free the data WITHIN a curve data structure (not the structure itself) */ -static void freeCurveData(XYCurve *curve, int dataOnly) -{ - if (!dataOnly && curve->curve_id != NULL) - XmStringFree(curve->curve_id); - if (!dataOnly && curve->name != NULL) - XmStringFree(curve->name); - if (curve->points != NULL) - XtFree((char *)curve->points); - if (curve->horizBars != NULL) - XtFree((char *)curve->horizBars); - if (curve->vertBars != NULL) - XtFree((char *)curve->vertBars); -} - -/* minimum and maximum of two doubles */ -static double dMin(double d1, double d2) -{ - if (d2 < d1) - return d2; - return d1; -} -static double dMax(double d1, double d2) -{ - if (d2 > d1) - return d2; - return d1; -} - - -/* -** Find the distance from a point to a curve -** -** x/y_on_curve are the closest points on -** the curve from x0, y0 -** -** This was fun to write -** Keith's Addition -** 7-11-2003 -*/ -double dist_point_to_curve( - XYCurve* curve, /* input */ - double x0, double y00, /* inputs */ - double* x_on_curve, double* y_on_curve ) { /* outputs */ - - int ii ; - double m ; - double b1, b2 ; - double dist, dist2, min_dist ; - double x1, y11, x2, y2 ; - double x2_x1, y2_y1 ; - double xi, yi ; - double xi_x0, yi_y0 ; - double x1_x0, y1_y0, x2_x0, y2_y0 ; - - int onSegment ; - int inXRange ; - int inYRange ; - - min_dist = 1.0e30 ; - for ( ii = 0 ; ii < curve->nPoints-1 ; ii++ ) { - - /* Get shorthand names */ - x1 = curve->points[ii].x ; - y11 = curve->points[ii].y ; - x2 = curve->points[ii+1].x ; - y2 = curve->points[ii+1].y ; ; - x2_x1 = x2 - x1 ; - y2_y1 = y2 - y11 ; - - /* Find distance from (x0,y0) to line defined by (x1,y1) (x2,y2) */ - /* Find what point is closest from (x0,y0) to line segment - * (i.e. solve two equations where lines intersect) - * - * You could solve distance right now with the following: - * It is just a novelty, I don't use it. - * d = fabs( m*(x0 - x1) - y0 + y11 ) / sqrt( m*m + 1 ) ; - */ - if ( y2_y1 == 0.0 ) { - xi = x0 ; - yi = y11 ; - } else if ( x2_x1 == 0.0 ) { - xi = x1 ; - yi = y00 ; - } else { - m = ( y2_y1 ) / ( x2_x1 ) ; - b1 = y00 + x0/m ; - b2 = y11 - m*x1 ; - xi = (b1 - b2)*m/(m*m + 1) ; - yi = m*xi + b2 ; - } - - /* Is (xi,yi) on (x1,y11)(x2,y2) segment? */ - onSegment = 0 ; - inXRange = 0 ; - inYRange = 0 ; - if ( x1 < x2 ) { - if ( x1 <= xi && xi <= x2 ) { - inXRange = 1 ; - } - } else { - if ( x2 <= xi && xi <= x1 ) { - inXRange = 1 ; - } - } - if ( y11 < y2 ) { - if ( y11 <= yi && yi <= y2 ) { - inYRange = 1 ; - } - } else { - if ( y2 <= yi && yi <= y11 ) { - inYRange = 1 ; - } - } - if ( inXRange && inYRange ) { - onSegment = 1 ; - } - if ( onSegment ) { - xi_x0 = xi - x0 ; - yi_y0 = yi - y00 ; - dist = xi_x0*xi_x0 + yi_y0*yi_y0 ; - if ( dist < min_dist ) { - min_dist = dist ; - *x_on_curve = xi ; - *y_on_curve = yi ; - } - } else { - /* Intersection point not on segment, so - * closest point will be one of the segment's endpoints - */ - x1_x0 = x1 - x0 ; - y1_y0 = y11 - y00 ; - x2_x0 = x2 - x0 ; - y2_y0 = y2 - y00 ; - dist = x1_x0*x1_x0 + y1_y0*y1_y0 ; - dist2 = x2_x0*x2_x0 + y2_y0*y2_y0 ; - if ( dist < min_dist ) { - min_dist = dist ; - *x_on_curve = xi ; - *y_on_curve = yi ; - } - if ( dist2 < min_dist ) { - min_dist = dist2 ; - *x_on_curve = xi ; - *y_on_curve = yi ; - } - } - } - - return ( sqrt(min_dist) ) ; -} - -/* -** This routine will draw a line with connecting text -** for a given point on the widget -** The given point is designated in data coords -** Keith's Addition -** 7-11-2003 -*/ -void label_pointer( XYWidget w, double x_data, double y_data, - char* label_text ) { - - int x_rect, y_rect ; - int w_rect, h_rect ; - - int x_win, y_win ; - transform xform; - XGCValues gcValues; - XmString x_string ; - - /* For color */ - XColor xWindowsColorScreen ; - XColor xWindowsColorExact ; - Screen * screen ; - Colormap colormap ; - Pixel yellow_pixel ; - Pixel black_pixel ; - - /* For font size */ - XFontStruct *fs; - - /* For XDrawLine */ - Display *display = XtDisplay(w); - Drawable drawBuf ; - GC gc = w->xy.gc; - - if (w->xy.doubleBuffer) { - drawBuf = w->xy.drawBuffer; - } else { - drawBuf = XtWindow(w); - } - - /* Compute constants for data to window coordinate transformation */ - computeTransform(w, &xform); - - x_win = dataToWindowX(&xform, x_data); - y_win = dataToWindowY(&xform, y_data); - - /* Get font info for font size */ -#if XmVERSION < 2 - fs = getFontStruct(w->xy.render_font) ; -#else - XmeRenderTableGetDefaultFont(w->xy.render_font,&fs); -#endif - - /* Get yellow and black */ - screen = XtScreen(w) ; - colormap = DefaultColormapOfScreen(screen); - XAllocNamedColor(display, colormap, "yellow", - &xWindowsColorScreen, - &xWindowsColorExact ) ; - yellow_pixel = xWindowsColorScreen.pixel ; - XAllocNamedColor(display, colormap, "black", - &xWindowsColorScreen, - &xWindowsColorExact ) ; - black_pixel = xWindowsColorScreen.pixel ; - - if ( w->xy.axisRight > x_win + 180 ) { - - /* Draw pointer label to right of line */ - - /* Draw a little arrow to line */ - XDrawLine( display, drawBuf, gc, x_win, y_win, - x_win, y_win - 6 ) ; - XDrawLine( display, drawBuf, gc, x_win, y_win, - x_win + 6 , y_win ) ; - XDrawLine( display, drawBuf, gc, x_win, y_win, - x_win + 30 , y_win - 30 ) ; - XDrawLine( display, drawBuf, gc, x_win + 30 , y_win - 30 , - x_win + 60 , y_win - 30 ) ; - - /* Get pixel location for little box to put label in */ - x_rect = x_win + 60 ; - y_rect = y_win - 30 - fs->ascent/2 - 3 ; - - } else { - /* If box will extend outside of viewing area on right, - * then make box on left hand side of line - */ - - /* Draw a little arrow to line */ - XDrawLine( display, drawBuf, gc, x_win, y_win, - x_win, y_win - 6 ) ; - XDrawLine( display, drawBuf, gc, x_win, y_win, - x_win - 6 , y_win ) ; - XDrawLine( display, drawBuf, gc, x_win, y_win, - x_win - 30 , y_win - 30 ) ; - XDrawLine( display, drawBuf, gc, x_win - 30 , y_win - 30 , - x_win - 60 , y_win - 30 ) ; - - /* Get pixel location for little box to put label in */ - x_rect = x_win - 90 ; - y_rect = y_win - 30 - fs->ascent/2 - 3 ; - } - w_rect = fs->max_bounds.width*strlen(label_text) + 6 ; - h_rect = fs->ascent + fs->descent + 6 ; - - /* Draw a little box to put label in */ - XDrawRectangle( display, drawBuf, gc, - x_rect, y_rect, w_rect, h_rect ) ; - gcValues.foreground = (unsigned long) yellow_pixel ; - XChangeGC(display, gc, GCForeground, &gcValues); - XFillRectangle( display, drawBuf, gc, - x_rect+1, y_rect+1, w_rect-1, h_rect-1 ) ; - - /* Draw the text of the label */ - gcValues.foreground = (unsigned long) black_pixel ; - XChangeGC(display, gc, GCForeground, &gcValues); - x_string = XmStringCreateLocalized( label_text ) ; - XmStringDraw(display, drawBuf, w->xy.render_font, x_string, gc, - x_rect + 3, y_rect + h_rect/2 - fs->ascent/2 - 1, - strlen(label_text) + 6, XmALIGNMENT_BEGINNING, - XmSTRING_DIRECTION_L_TO_R, NULL); - XmStringFree( x_string ) ; - - /* For double buffering, now copy offscreen pixmap to screen */ - if (w->xy.doubleBuffer) { - XCopyArea(display, drawBuf, XtWindow(w), w->xy.gc, 0, 0, - w->core.width, w->core.height, 0, 0); - } - - /* Call the redisplay callback so an application which draws on the xy - widget can refresh it's graphics */ - if (XtIsRealized((Widget)w)) - XtCallCallbacks((Widget)w, XmNredisplayCallback, NULL); -} - - -/* - ** Keith snagged this off of the internet - ** You have to have: - ** #include - ** #include - ** #include - */ -void GetWidgetPopupList(Widget w, WidgetList *wl, int *num) { - - struct _WidgetRec *wr = (struct _WidgetRec *) w; - - *wl = wr->core.popup_list; - *num = wr->core.num_popups; -} - -/* - ** This pops up a dialog box for the user to enter formulas to - ** transform a curves x-y vectors - ** Keith's Addition - ** 7-11-2003 - */ -void manipulateCurve(XYWidget w, XEvent *event, char* args __attribute__ ((unused)), int n_args __attribute__ ((unused))) { - - double xOnCurve, yOnCurve ; - char title[128] ; - - int ii ; - int nPopupChildren ; - WidgetList popupChildren ; - - static XYManipulateCurveCBData xym ; - Widget dialog ; - Widget pane_main ; - Widget form_control ; - Widget form_action ; - Widget label_x ; - Widget label_y ; - static Widget text_x ; - static Widget text_y ; - Widget button_ok ; - Widget button_close ; - Widget button_apply ; - Dimension h ; - XmString label_string ; - - /* Get position and curve selected */ - w->xy.selectedCurve = curveClosestToMouseClick( w, event, - &xOnCurve, &yOnCurve ) ; - /* Set dialog box title */ - sprintf(title, "Manipulate Curve #%d", w->xy.selectedCurve ) ; - - /* If there is already a dialog box up, reset title and return */ - GetWidgetPopupList(XtParent(w), &popupChildren, &nPopupChildren) ; - for ( ii = 0 ; ii < nPopupChildren ; ii++ ) { - if ( ! strcmp( XtName(popupChildren[ii]), "xy_formula_dialog" ) ) { - XtVaSetValues( popupChildren[ii], - XmNtitle, title, - NULL ) ; - selectCurve(w, event, NULL, 0 ) ; - xym.w = w ; /* Switch current widget to one just clicked */ - return ; - } - } - - dialog = XtVaCreatePopupShell( "xy_formula_dialog", - xmDialogShellWidgetClass, XtParent(w), - XmNtitle, title, - XmNdeleteResponse, XmDESTROY, - NULL ) ; - - pane_main = XtVaCreateWidget( "pane_main", - xmPanedWindowWidgetClass, dialog, - XmNsashWidth, 1, - XmNsashHeight, 1, - XmNheight, 175, - XmNwidth, 400, - NULL ) ; - - /* - * The "control" area of the dialog - */ - form_control = XtVaCreateWidget( "form_control", - xmFormWidgetClass, pane_main, - NULL ) ; - - label_x = XtVaCreateManagedWidget( "x = ", - xmLabelGadgetClass, form_control, - XmNtopOffset, 15, - XmNtopAttachment, XmATTACH_POSITION, - XmNbottomAttachment, XmATTACH_NONE, - XmNleftAttachment, XmATTACH_FORM, - NULL ) ; - - text_x = XtVaCreateManagedWidget( "text_x_formula", - xmTextWidgetClass, form_control, - XmNvalue, "x", - XmNtopOffset, 10, - XmNtopAttachment, XmATTACH_FORM, - XmNbottomAttachment, XmATTACH_NONE, - XmNleftAttachment, XmATTACH_WIDGET, - XmNleftWidget, label_x, - XmNrightAttachment, XmATTACH_FORM, - NULL ) ; - - label_y = XtVaCreateManagedWidget( "y = ", - xmLabelGadgetClass, form_control, - XmNtopOffset, 25, - XmNtopAttachment, XmATTACH_WIDGET, - XmNtopWidget, text_x, - XmNbottomAttachment, XmATTACH_NONE, - XmNleftAttachment, XmATTACH_FORM, - NULL ) ; - - text_y = XtVaCreateManagedWidget( "text_y_formula", - xmTextWidgetClass, form_control, - XmNvalue, "y", - XmNtopOffset, 20, - XmNtopAttachment, XmATTACH_WIDGET, - XmNtopWidget, text_x, - XmNbottomAttachment, XmATTACH_NONE, - XmNleftAttachment, XmATTACH_WIDGET, - XmNleftWidget, label_y, - XmNrightAttachment, XmATTACH_FORM, - NULL ) ; - - /* - * The "action" area of the dialog - */ - xym.x_formula = text_x ; - xym.y_formula = text_y ; - xym.w = w ; - - form_action = XtVaCreateWidget( "form_action", - xmFormWidgetClass, pane_main, - XmNfractionBase, 7, - NULL ) ; - - /* OK */ - label_string = XmStringCreateLocalized("OK") ; - button_ok = XtVaCreateManagedWidget( "button_ok", - xmPushButtonGadgetClass, form_action, - XmNdefaultButtonShadowThickness, 1, - XmNlabelString, label_string, - XmNtopAttachment, XmATTACH_FORM, - XmNbottomAttachment, XmATTACH_FORM, - XmNleftAttachment, XmATTACH_POSITION, - XmNleftPosition, 1, - XmNrightAttachment, XmATTACH_POSITION, - XmNrightPosition, 2, - NULL ) ; - XmStringFree(label_string) ; - XtAddCallback( button_ok, - XmNactivateCallback, - manipulateCurveCB, - &xym ) ; - - /* Apply */ - label_string = XmStringCreateLocalized("Apply") ; - button_apply = XtVaCreateManagedWidget( "button_apply", - xmPushButtonGadgetClass, form_action, - XmNdefaultButtonShadowThickness, 1, - XmNlabelString, label_string, - XmNtopAttachment, XmATTACH_FORM, - XmNbottomAttachment, XmATTACH_FORM, - XmNleftAttachment, XmATTACH_POSITION, - XmNleftPosition, 3, - XmNrightAttachment, XmATTACH_POSITION, - XmNrightPosition, 4, - NULL ) ; - XmStringFree(label_string) ; - XtAddCallback( button_apply, - XmNactivateCallback, - manipulateCurveCB, - &xym ) ; - - /* Close */ - label_string = XmStringCreateLocalized("Close") ; - button_close = XtVaCreateManagedWidget( "button_close", - xmPushButtonGadgetClass, form_action, - XmNdefaultButtonShadowThickness, 1, - XmNlabelString, label_string, - XmNtopAttachment, XmATTACH_FORM, - XmNbottomAttachment, XmATTACH_FORM, - XmNleftAttachment, XmATTACH_POSITION, - XmNleftPosition, 5, - XmNrightAttachment, XmATTACH_POSITION, - XmNrightPosition, 6, - NULL ) ; - XmStringFree(label_string) ; - XtAddCallback( button_close, - XmNactivateCallback, - manipulateCurveCB, - &xym ) ; - - /* Action area sizing */ - XtVaGetValues( button_ok, XmNheight, &h, NULL ) ; - XtVaSetValues( form_action, - XmNpaneMaximum, h, - XmNpaneMinimum, h, - NULL ) ; - - XtManageChild(pane_main) ; - XtManageChild(form_action) ; - XtManageChild(form_control) ; - XtManageChild(dialog) ; - XtPopup( dialog, XtGrabNone ) ; - - selectCurve(w, event, NULL, 0 ) ; -} - -/* - ** Callback when buttons pressed on - ** manipulateCurve() dialog box - ** Keith's Addition - ** 7-11-2003 - */ -void manipulateCurveCB ( Widget widget, - XtPointer client_data, - XtPointer call_data __attribute__ ((unused))) { - int ii ; - int ret ; - XYManipulateCurveCBData* xym ; - XYCurve* curve ; - char *xEquation ; - char *yEquation ; - - double val ; - - if ( !strcmp( XtName(widget), "button_ok") || - !strcmp( XtName(widget), "button_apply") ) { - - xym = (XYManipulateCurveCBData*) client_data ; - - xEquation = XmTextGetString (xym->x_formula) ; - yEquation = XmTextGetString (xym->y_formula) ; - curve = &(xym->w->xy.curves[xym->w->xy.selectedCurve]) ; - - /* Make sure that there are no problems with curve (i.e. - * syntax errors, divide by zero, square root neg num .... ) - * We are not manipulating curve, we are just error checking - */ - for ( ii = 0 ; ii < curve->nPoints ; ii++ ) { - ret = equationparse(xEquation, - curve->points[ii].x, - &val) ; - if ( ret ) { - errorEQParseDialog( XtParent(XtParent(widget)), ret ) ; - return ; - } - - ret = equationparse(yEquation, - curve->points[ii].y, - &val ) ; - if ( ret ) { - errorEQParseDialog( XtParent(XtParent(widget)), ret ) ; - return ; - } - } - - /* Do actual curve manipulation */ - for ( ii = 0 ; ii < curve->nPoints ; ii++ ) { - ret = equationparse(xEquation, - curve->points[ii].x, - &curve->points[ii].x) ; - ret = equationparse(yEquation, - curve->points[ii].y, - &curve->points[ii].y ) ; - } - - resetDataAndViewRanges(xym->w, XY_RESCALE); - redisplayContents(xym->w, X_SCREEN, REDRAW_ALL); - } - - if ( !strcmp( XtName(widget), "button_ok") || - !strcmp( XtName(widget), "button_close") ) { - - /* Close out the dialog box */ - while ( ! XmIsDialogShell( widget ) ) { - widget = XtParent( widget ) ; - } - XtDestroyWidget(widget); - } -} - -static void motion(XYWidget w, XEvent *event, char *args, int n_args) { - - /* - if we are using crosshairs, call that first. valueDisplay - will be called inside the crossHairs routine - */ - if ( w->xy.enableCrosshairs ) { - crossHairs( w , event , args , n_args ) ; - } - else { - if ( w->xy.valueDisplay ) { - valueDisplay( w , event , args , n_args ) ; - } - } - -} - -static void valueDisplay(XYWidget w, XEvent *event, char *args __attribute__ ((unused)), int n_args __attribute__ ((unused))) { - - int ii , jj ; - XYCurve * curve ; - XYPoint * point ; - double dist ; - double min_dist ; - double min_x , min_y ; - char format[60] ; - char value[60] ; - transform xform; - int x_point, y_point ; - int x_win , y_win ; - Display *display ; - Drawable drawBuf ; - XmString s0 ; - XtPointer str ; - GC gc ; - Pixel markColor ; - XFontStruct *fs; - int y_rect ; - int w_rect , h_rect ; - int xMin = w->xy.xOrigin, yMin = w->xy.yEnd; - int xMax = w->xy.xEnd, yMax = w->xy.yOrigin; - int clear_width ; - - if (w->xy.doubleBuffer) { - drawBuf = w->xy.drawBuffer; - } else { - drawBuf = XtWindow(w); - } - - /* For XDrawLine */ - display = XtDisplay(w); - - gc = w->xy.gc; - - /* Get font info for font size */ -#if XmVERSION < 2 - fs = getFontStruct(w->xy.render_font) ; -#else - XmeRenderTableGetDefaultFont(w->xy.render_font,&fs); -#endif - - computeTransform(w, &xform); - min_dist = 1e200; - /* find the closest point to the cursor */ - for ( ii = 0 ; ii < w->xy.nCurves ; ii++ ) { - curve = &(w->xy.curves[ii]) ; - for ( jj = 0 ; jj < curve->nPoints ; jj++ ) { - point = &(curve->points[jj]) ; - - x_point = dataToWindowX(&xform, point->x); - y_point = dataToWindowY(&xform, point->y); - - /* make sure the point is on the screen */ - if (x_point >= xMin && x_point <= xMax && - y_point >= yMin && y_point <= yMax) { - - /* get magnitude of distance, no need for sqrt */ - dist = (x_point - event->xbutton.x)*(x_point - event->xbutton.x) + - (y_point - event->xbutton.y)*(y_point - event->xbutton.y) ; - - if ( dist < min_dist ) { - min_dist = dist ; - min_x = point->x ; - min_y = point->y ; - x_win = x_point ; - y_win = y_point ; - markColor = curve->linePixel; - } - } - } - } - - if ( w->xy.valueBuffer == 0 ) { - /* - valueBuffer will contain the graph before a mark is placed on it - we use it to copy back the original picture when we clear a mark - */ - w->xy.valueBuffer = XCreatePixmap(XtDisplay(w), - DefaultRootWindow(XtDisplay(w)), w->core.width, w->core.height, - DefaultDepthOfScreen(XtScreen(w))); - - /* copy the clean drawbuf to valueBuffer for saving */ - XCopyArea(display, drawBuf , w->xy.valueBuffer, gc, 0 , 0 , - w->core.width , w->core.height , 0 , 0 ); - } - else { - /* clear the last mark by copying the clean valueBuffer back to drawBuf */ - XCopyArea(display, w->xy.valueBuffer, drawBuf , gc, w->xy.valueX - LARGE_MARK_SIZE , w->xy.valueY - LARGE_MARK_SIZE , - LARGE_MARK_SIZE * 2, LARGE_MARK_SIZE * 2, w->xy.valueX - LARGE_MARK_SIZE , w->xy.valueY - LARGE_MARK_SIZE ); - /* copy to the screen too */ - XCopyArea(display, w->xy.valueBuffer, XtWindow(w) , gc, w->xy.valueX - LARGE_MARK_SIZE , w->xy.valueY - LARGE_MARK_SIZE , - LARGE_MARK_SIZE * 2, LARGE_MARK_SIZE * 2, w->xy.valueX - LARGE_MARK_SIZE , w->xy.valueY - LARGE_MARK_SIZE ); - } - - /* draw a mark on the closest point */ - XYDrawMarker(display, drawBuf, gc, XY_LARGE, - XY_SOLID_CIRCLE_MARK , markColor, x_win, y_win) ; - -#if XmVERSION < 2 - str = (char *)w->xy.yAxisFormat ; -#else - str = (XtPointer)XmStringUnparse(w->xy.yAxisFormat, NULL, 0, XmCHARSET_TEXT, NULL, 0, XmOUTPUT_ALL); -#endif - sprintf(format,"%s , %s" , (char *)str, (char *)str ) ; - sprintf(value, format , min_x , min_y ) ; - - /* calculate maximum width we need to clear 2*format max width + 3*width of char + pad(6) */ - clear_width = VAxisWidth(fs , w->xy.yAxisFormat) * 2 + fs->max_bounds.width * 3 + 6 ; - h_rect = fs->ascent + fs->descent + 6 ; - y_rect = w->xy.yMin + 2 * TOP_MARGIN + fs->ascent + fs->descent ; - - XSetForeground(display, gc, w->core.background_pixel); - XFillRectangle( display, drawBuf, gc, - w->xy.xEnd - clear_width , y_rect, clear_width, h_rect ) ; - - w_rect = fs->max_bounds.width*strlen(value) + 6 ; - - /* draw the value string */ - XSetForeground(display, gc, w->primitive.foreground); - s0 = XmStringCreateLocalized( value ) ; - XmStringDraw(display, drawBuf, w->xy.render_font, - s0, gc, - w->xy.xEnd - w_rect , - w->xy.yMin + 2 * TOP_MARGIN + fs->ascent + fs->descent, - w->xy.xEnd - w->xy.xOrigin, - XmALIGNMENT_BEGINNING, - XmSTRING_DIRECTION_L_TO_R, - NULL); - - XmStringFree( s0 ) ; - XtFree(str) ; - - /* For double buffering, now copy offscreen pixmap to screen , copy only the changed area */ - if (w->xy.doubleBuffer) { - XCopyArea(display, drawBuf , XtWindow(w), gc, w->xy.xEnd - clear_width , y_rect , - clear_width , h_rect , w->xy.xEnd - clear_width , y_rect ); - XCopyArea(display, drawBuf , XtWindow(w), gc, x_win - LARGE_MARK_SIZE , y_win - LARGE_MARK_SIZE , - LARGE_MARK_SIZE * 2 , LARGE_MARK_SIZE * 2 , x_win - LARGE_MARK_SIZE , y_win - LARGE_MARK_SIZE ); - } - - /* save the coordinates of the last mark */ - w->xy.valueX = x_win ; - w->xy.valueY = y_win ; - - return ; -} - - -static void crossHairs(XYWidget w, XEvent *event, char *args, int n_args) { - - double x, y ; - int x_win, y_win ; - Display *display ; - Drawable drawBuf ; - transform xform; - - /* If user prefers -not- to use crosshair, just return */ - if ( ! w->xy.enableCrosshairs ) { - return ; - } - - /* For XDrawLine */ - display = XtDisplay(w); - - if (w->xy.doubleBuffer) { - drawBuf = w->xy.drawBuffer; - } else { - drawBuf = XtWindow(w); - } - - /* Compute constants for data to window coordinate transformation */ - computeTransform(w, &xform); - - /* Get mouse position in pixel coords */ - getXYMousePosition( w, event, &x, &y ) ; - x_win = dataToWindowX(&xform, x); - y_win = dataToWindowY(&xform, y); - - /* Don't draw any cross hair outside the axes */ - if ( x_win < w->xy.xOrigin || x_win > w->xy.xEnd || - y_win > w->xy.yOrigin || y_win < w->xy.yEnd ) { - return ; - } - - /* Draw cross hair and data labels */ - if ( w->xy.crosshairFirst ) { - - /* call valueDisplay while the graph is clear */ - if ( w->xy.valueDisplay ) { - valueDisplay( w , event , args , n_args ) ; - } - - sprintf(w->xy.crosshairVertText, "%.6lf", x) ; - sprintf(w->xy.crosshairHoriText, "%.6lf", y) ; - - drawCrosshairs( display, drawBuf, w, x_win, y_win ) ; - - /* Save off this first state */ - w->xy.lastCrosshairX = x_win ; - w->xy.lastCrosshairY = y_win ; - w->xy.crosshairFirst = 0 ; - - } else { - - /* Clear last line and labels - * (the magic is in the GCXxor func in zoomGC -> a^b^b = a) - */ - drawCrosshairs( display, drawBuf, w, - w->xy.lastCrosshairX, w->xy.lastCrosshairY ) ; - - /* call valueDisplay while the graph is clear */ - if ( w->xy.valueDisplay ) { - valueDisplay( w , event , args , n_args ) ; - } - - /* Draw the crosshairs with current data */ - sprintf(w->xy.crosshairVertText, "%.6lf", x) ; - sprintf(w->xy.crosshairHoriText, "%.6lf", y) ; - drawCrosshairs( display, drawBuf, w, x_win, y_win ) ; - - /* Save off the last coords to clear hairs on next call */ - w->xy.lastCrosshairX = x_win ; - w->xy.lastCrosshairY = y_win ; - } - - /* For double buffering, now copy offscreen pixmap to screen */ - if (w->xy.doubleBuffer) { - XCopyArea(display, drawBuf, XtWindow(w), w->xy.gc, 0, 0, - w->core.width, w->core.height, 0, 0); - } - - /* Call the redisplay callback so an application which draws on the xy - widget can refresh it's graphics */ - if (XtIsRealized((Widget)w)) - XtCallCallbacks((Widget)w, XmNredisplayCallback, NULL); -} - -void drawCrosshairs( Display* display, Drawable drawBuf, - XYWidget w, int x_win, int y_win ) { - XmString string ; - - /* Draw the crosshair the first time */ - XDrawLine( display, drawBuf, w->xy.zoomGC, - w->xy.xOrigin, y_win, - w->xy.xEnd, y_win ) ; - XDrawLine( display, drawBuf, w->xy.zoomGC, - x_win, w->xy.yOrigin, - x_win, w->xy.yEnd ) ; - - /* Label for vertical cross hair */ - w->xy.crosshairVertXTextCoord = x_win+3 ; - w->xy.crosshairVertYTextCoord = w->xy.yOrigin - 16 ; - string = XmStringCreateLocalized( w->xy.crosshairVertText ) ; - XmStringDraw(display, drawBuf, w->xy.render_font, - string, w->xy.zoomGC, - w->xy.crosshairVertXTextCoord, - w->xy.crosshairVertYTextCoord, - 16, XmALIGNMENT_BEGINNING, - XmSTRING_DIRECTION_L_TO_R, NULL); - XmStringFree( string ) ; - - /* Label for horizontal cross hair */ - w->xy.crosshairHoriXTextCoord = w->xy.xOrigin+3 ; - w->xy.crosshairHoriYTextCoord = y_win - 16 ; - string = XmStringCreateLocalized( w->xy.crosshairHoriText ) ; - XmStringDraw(display, drawBuf, w->xy.render_font, - string, w->xy.zoomGC, - w->xy.crosshairHoriXTextCoord, - w->xy.crosshairHoriYTextCoord, - 16, XmALIGNMENT_BEGINNING, - XmSTRING_DIRECTION_L_TO_R, NULL); - XmStringFree( string ) ; -} - -/* - ** This pops up a dialog box for the user to enter a formula - ** for combining curves arithmetically - ** - ** Keith's Addition - ** 7-24-2003 - */ -void combineCurvesDialog(XYWidget w, XEvent *event __attribute__ ((unused)), char* args __attribute__ ((unused)), int n_args __attribute__ ((unused))) { - - int ii ; - int nPopupChildren ; - WidgetList popupChildren ; - - static XYManipulateCurveCBData xym ; - - Widget dialog ; - Arg wargs[5] ; - int nargs ; - XmString labelTitle ; - - /* Always pass XY widget that was clicked in to CallBack */ - xym.w = w ; - - /* If there is already a dialog box up, return */ - GetWidgetPopupList(XtParent(w), &popupChildren, &nPopupChildren) ; - for ( ii = 0 ; ii < nPopupChildren ; ii++ ) { - if ( ! strcmp( XtName(popupChildren[ii]), - "curve_formula_dialog_popup" ) ) { - return ; - } - } - - labelTitle = XmStringCreateLocalized("Formula:"); - nargs = 0 ; - XtSetArg( wargs[nargs], XmNselectionLabelString, labelTitle) ; nargs++ ; - XtSetArg( wargs[nargs], XmNautoUnmanage, False) ; nargs++ ; - XtSetArg( wargs[nargs], XmNtitle, "Curve Formula") ; nargs++ ; - dialog = XmCreatePromptDialog( XtParent(w), - "curve_formula_dialog", wargs, nargs ) ; - XmStringFree( labelTitle ) ; - - XtAddCallback( dialog, XmNokCallback, - combineCurvesOKCB, - &xym) ; - - XtAddCallback( dialog, XmNcancelCallback, combineCurvesCancelCB, NULL ) ; -/* - XtAddCallback( dialog, XmNhelpCallback, combineCurvesHelpCB, w ) ; -*/ - - XtManageChild( dialog ) ; - XtPopup( XtParent(dialog), XtGrabNone ) ; -} - -/* - ** Callback from OK button being pressed on combineCurvesDialog - ** This CB will take the formula string from the dialog - ** and call routines to actually combine the curves - ** using the formula - ** - ** Keith's Addition - ** 7-24-2003 - */ -void combineCurvesOKCB( Widget parent_w, XtPointer client_data, - XtPointer call_data ) { - int ii ; - int numCurves ; - char* formula_xm ; - char formula[512] ; - XYCurve* curve ; - XYCurve* newCurves ; - XYWidget w ; - XYManipulateCurveCBData* xym ; - - /* Get formula entered by user in dialog box */ - XmSelectionBoxCallbackStruct *cbs = - (XmSelectionBoxCallbackStruct*) call_data ; - XmStringGetLtoR( cbs->value, - XmFONTLIST_DEFAULT_TAG, - &formula_xm ) ; - strcpy( formula, formula_xm ) ; - XtFree( formula_xm ) ; - - curve = (XYCurve *) XtMalloc(sizeof(XYCurve)) ; - - /* XYWidget passed in */ - xym = (XYManipulateCurveCBData*) client_data ; - w = xym->w ; - - newCurves = (XYCurve *)malloc(sizeof(XYCurve) * (w->xy.nCurves + 1)) ; - numCurves = w->xy.nCurves + 1 ; - - for (ii = 0; ii < w->xy.nCurves; ii++) { - copyCurveData(&w->xy.curves[ii], &newCurves[ii], False) ; - } - - curve = curvemath( XtParent(parent_w), w->xy.curves, - w->xy.nCurves, formula) ; - - /* curvemath() found no common points, so it returned NULL */ - if ( curve == NULL ) { - - - for ( ii = 0 ; ii < numCurves-1 ; ii++ ) { - freeCurveData(&newCurves[ii],False) ; - } - - XtFree((char *) newCurves) ; - - return ; - } - - copyCurveData(curve,&newCurves[numCurves-1],False) ; - freeCurveData(curve,False) ; - XtFree((char *) curve) ; - - setContents((Widget)w,newCurves,numCurves,XY_RESCALE,False) ; - - for ( ii = 0 ; ii < numCurves ; ii++ ) { - freeCurveData(&newCurves[ii],False) ; - } - XtFree((char *) newCurves) ; -} - -/* - ** Callback from Cancel button being pressed on combineCurvesDialog - ** - ** Keith's Addition - ** 7-24-2003 - */ -void combineCurvesCancelCB( Widget w, XtPointer client_data __attribute__ ((unused)), - XtPointer call_data __attribute__ ((unused))) { - XtDestroyWidget( w ) ; -} - - -int maxnumpts(XYCurve* curves, int numCurves) -{ - int maxnum, i ; - maxnum = 0; - for (i = 0; i < numCurves; i++) - { - if (curves[i].nPoints > maxnum) - { - maxnum = curves[i].nPoints ; - } - } - return (maxnum) ; -} - -XYCurve* curvemath( Widget parent_w, XYCurve* curves, - int numCurves, char *equation) -{ - -#define FREE_CPI \ - for ( i = 0 ; i < maxnumcurvepts ; i++ ) { \ - free(commonPtIndex[i]) ; \ - } \ - free(commonPtIndex) ; \ - free( iindex ) ; - - /* For error dialog */ - char err_msg[32] ; - Widget dialog ; - Arg wargs[5] ; - int nargs ; - XmString msg ; - - /* Colors for curves */ - Colormap colormap ; - Display* display ; - Screen* screen ; - XColor xWindowsColorScreen ; - XColor xWindowsColorExact ; - Pixel pixel ; - #define CURVEMATH_NUM_COLORS 14 - char colors[CURVEMATH_NUM_COLORS][32] = { - "black", "red", "blue", "green", "magenta", - "yellow", "cyan", "pink", "darkgreen", "lightblue", - "purple", "orange", "maroon", "goldenrod" } ; - - XYCurve *result ; - XYCurve* tempCurves ; - char *tempeq ; - char tempbuff[512] ; - char strnum[16] ; - int* iindex ; - int maxnumcurvepts ; - int** commonPtIndex ; - int numCommonPts, i, j, k, l, m, n, o, p, q, r, s, t, u ; - int numMatches , moreMatches , cPresent , colon ; - double checkX ; - int numUsedCurves, cnum, tcnum , rrindex, pt, tpt, spt, len ; - int ret ; - result = (XYCurve *) malloc(sizeof(XYCurve)) ; - tempCurves = (XYCurve *) malloc(sizeof(XYCurve) * numCurves) ; - memset(tempbuff,0,512) ; - memset(strnum,0,16) ; - tempeq = tempbuff ; - len = strlen (equation) ; - numCommonPts = 0 ; - moreMatches = 0 ; - numUsedCurves = 0 ; - cPresent = 0 ; - colon = 0; - result->name = XmStringCreateLocalized(equation) ; - result->markerStyle = curves[0].markerStyle ; - result->markerSize = curves[0].markerSize ; - result->lineStyle = curves[0].lineStyle ; - - /* Allocations */ - iindex = (int*) calloc ( numCurves, sizeof(int) ) ; - maxnumcurvepts = maxnumpts(curves, numCurves) ; - commonPtIndex = (int**) calloc ( maxnumcurvepts, sizeof(int*) ) ; - for ( i = 0 ; i < maxnumcurvepts ; i++ ) { - commonPtIndex[i] = (int*) calloc ( numCurves, sizeof(int) ) ; - } - - /* Get new color for each new curve */ - display = XtDisplay(parent_w) ; - screen = XtScreen(parent_w) ; - colormap = DefaultColormapOfScreen(screen); - XAllocNamedColor( display, colormap, - colors[numCurves%CURVEMATH_NUM_COLORS], - &xWindowsColorScreen, - &xWindowsColorExact ) ; - pixel = xWindowsColorScreen.pixel ; - result->linePixel = pixel ; - result->markerPixel = pixel ; - - result->nPoints = 0 ; - spt = 0 ; - - /* Set defaults in result curve (valgrind) */ - result->horizBars = NULL ; - result->vertBars = NULL ; - - for (r = 0; r < numCurves; r++) - { - iindex[r] = 0 ; - } - for (s = 0; s < maxnumcurvepts; s++) - { - for (t = 0; t < numCurves; t++) - { - commonPtIndex[s][t] = 0 ; - } - } - - for (p = 0; p < (len-1); p++) - { - if ((equation[p] == 'c') && isdigit(equation[p+1]) ) - { - cPresent = 1 ; - break ; - } - } - if (cPresent != 1) - { - char *tequation ; - char teqbuff[64] ; - char prefix[64] = "c0:" ; - char *tprefix = prefix ; - memset(teqbuff,0,64) ; - tequation = teqbuff ; - tequation = strcat(tprefix,equation) ; - strcpy(equation,tequation) ; - } - len = strlen (equation) ; - for (p = 0; p < (len-1); p++) - { - if (equation[p] == ':') - { - char *curveStr ; - char csbuff[64] ; - char *curveNumStr ; - char cnsbuff[64] ; - memset(csbuff,0,64) ; - memset(cnsbuff,0,64) ; - curveStr = csbuff ; - curveNumStr = cnsbuff ; - colon = 1 ; - strncpy(curveStr,equation,p) ; - curveNumStr = &curveStr[1] ; - equation = &equation[p+1] ; - cnum = atoi(curveNumStr) ; - break ; - } - } - len = strlen (equation) ; - if (colon == 1) - { - result->points = (XYPoint *) malloc - (sizeof(XYPoint) * (curves[cnum].nPoints)) ; - numCommonPts = curves[cnum].nPoints ; - result->nPoints = curves[cnum].nPoints ; - for ( i = 0 ; i < curves[cnum].nPoints ; i++ ) { - result->points[i].x = curves[cnum].points[i].x ; - commonPtIndex[i][0] = i ; - } - for ( i = 0 ; i < curves[cnum].nPoints ; i++ ) { - ret = equationparse(equation, - result->points[i].x, - &result->points[i].y) ; - if ( ret ) { - errorEQParseDialog( parent_w, ret ) ; - XtFree((char *)tempCurves) ; - FREE_CPI - return (NULL) ; - } - } - XtFree((char *)tempCurves) ; - FREE_CPI ; - return (result) ; - } - - for (p = 0; p < (len-1); p++) - { - if ((equation[p] == 'c') && isdigit(equation[p+1])) - { - cnum = 0 ; - p++ ; - spt = 0 ; - memset(strnum,0,16) ; - while ( isdigit(equation[p]) && (p < len) ) - { - strnum[spt] = equation[p] ; - spt++ ; - p++ ; - } - cnum = atoi(strnum) ; - if (cnum >= numCurves) - { - /* Error dialog popup */ - sprintf(err_msg,"%d is not a valid curve number", cnum) ; - msg = XmStringCreateLocalized(err_msg) ; - nargs = 0 ; - XtSetArg( wargs[nargs], XmNmessageString, msg ) ; nargs++ ; - XtSetArg( wargs[nargs], XmNtitle, "Error" ) ; nargs++ ; - dialog = XmCreateErrorDialog( parent_w, - "error_message", - wargs, nargs ) ; - XtManageChild( dialog ) ; - - FREE_CPI; - return(NULL); - } - copyCurveData(&curves[cnum],&tempCurves[numUsedCurves],False) ; - numUsedCurves++ ; - } - } - - result->points = (XYPoint *) malloc - (sizeof(XYPoint) * (tempCurves[0].nPoints)) ; - - - for (i = 0; i < tempCurves[0].nPoints; i++) - { - for (m = 0; m < numUsedCurves; m++) - { - if (iindex[m] == tempCurves[m].nPoints) - { - moreMatches = 1 ; - break ; - } - } - if (moreMatches == 1) - { - break ; - } - numMatches = 0 ; - checkX = tempCurves[0].points[i].x ; - for (j = 1; j < numUsedCurves; j++) - { - for (k = 0; k < tempCurves[j].nPoints; k++) - { - if (tempCurves[j].points[iindex[j]].x > checkX) - { - break ; - } - else if (tempCurves[j].points[iindex[j]].x == checkX) - { - numMatches++ ; - break ; - } - else - { - iindex[j] = iindex[j] + 1 ; - } - } - if (numMatches < j) - { - break ; - } - else if (numMatches == (numUsedCurves - 1)) - { - /*commonPts[numCommonPts] = checkX ;*/ - for (o = 0; o < numUsedCurves; o++) - { - commonPtIndex[numCommonPts][o] = iindex[o] ; - } - result->points[result->nPoints].x = - tempCurves[0].points[i].x ; - result->nPoints++ ; - numCommonPts++ ; - for (l = 1; l < numUsedCurves; l++) - { - iindex[l] = iindex[l] + 1 ; - } - } - } - iindex[0] = iindex[0] + 1 ; - } - - if ( numUsedCurves == 1 ) { - numCommonPts = tempCurves[0].nPoints ; - result->nPoints = tempCurves[0].nPoints ; - for ( i = 0 ; i < tempCurves[0].nPoints ; i++ ) { - result->points[i].x = tempCurves[0].points[i].x ; - commonPtIndex[i][0] = i ; - } - } - - if (numCommonPts == 0) - { - free( result ) ; - XtFree((char *)tempCurves) ; - - /* Warning dialog box that says no common points */ - msg = XmStringCreateLocalized( - "When combining curves there were\n" - "no points between the curves where\n" - "the time stamp matched.\n" - "So there is nothing to display." ); - nargs = 0 ; - XtSetArg( wargs[nargs], XmNmessageString, msg ) ; nargs++ ; - XtSetArg( wargs[nargs], XmNtitle, "Warning" ) ; nargs++ ; - dialog = XmCreateWarningDialog( parent_w, "warning_message", - wargs, nargs ) ; - XtManageChild( dialog ) ; - - FREE_CPI ; - return (NULL); - } - - rrindex = 0; - while (rrindex < numCommonPts) - { - memset(tempbuff,0,512) ; - tempeq = tempbuff ; - pt = 0 ; - tpt = 0 ; - while( pt < len ) - { - if ( pt == len - 1 ) { - tempeq[tpt] = equation[pt] ; - tpt++ ; - pt++ ; - } - else if ((equation[pt] == 'c') && (equation[pt+1] >= 48) - && (equation[pt+1] <= 57)) - { - pt++ ; - n = pt ; - cnum = 0 ; - spt = 0 ; - memset(strnum,0,16) ; - while ((equation[n] >= 48) && (equation[n] <= 57) && (n < len)) - { - strnum[spt] = equation[n] ; - spt++ ; - pt++ ; - n++ ; - } - cnum = atoi(strnum) ; - tcnum = -1 ; - for (q = 0; q < numUsedCurves; q++) - { - if (XmStringCompare(curves[cnum].name, tempCurves[q].name)) - { - tcnum = q ; - break ; - } - } - if (tcnum == -1) - { - printf("\n Parse error in XY.c, no match found...") ; - exit(1) ; - } - if (curves[cnum].points[commonPtIndex[rrindex][tcnum]].y <= 0) - { - sprintf(tempeq,"%s(%.12lf)", - tempeq, - curves[cnum].points[ - commonPtIndex[rrindex][tcnum]].y) ; - } - else - { - sprintf(tempeq,"%s%.12lf", - tempeq, - curves[cnum].points[ - commonPtIndex[rrindex][tcnum]].y); - } - tpt = strlen (tempeq) ; - } - else - { - tempeq[tpt] = equation[pt] ; - tpt++ ; - pt++ ; - } - } -#if 0 - printf("\nEquation after substitution: %s",tempeq) ; -#endif - - ret = equationparse(tempeq, - result->points[rrindex].x, - &result->points[rrindex].y) ; - if ( ret ) { - errorEQParseDialog( parent_w, ret ) ; - break ; - } - - rrindex++ ; - } - - for (u = 0; u < numUsedCurves; u++) - { - freeCurveData(&tempCurves[u],False) ; - } - XtFree((char *)tempCurves) ; - - FREE_CPI ; - if ( ret ) { - /* Error has occured */ - return( NULL ) ; - } else { - return (result) ; - } -} - -XYCurve* curvesub(XYCurve* c1, XYCurve* c2) -{ - int c1index, c2index, rrindex ; - XYCurve *result ; - XmString nameSep ; - XmString tmpString ; - result = (XYCurve *) malloc(sizeof(XYCurve)) ; - nameSep = XmStringCreateLocalized (" - ") ; - c1index = 0 ; - c2index = 0 ; - rrindex = 0 ; - tmpString = XmStringConcat(c1->name, nameSep) ; - result->name = XmStringConcat(tmpString, c2->name) ; - XmStringFree(nameSep) ; - result->markerStyle = c1->markerStyle ; - result->markerSize = c1->markerSize ; - result->lineStyle = c1->lineStyle ; - result->markerPixel = c1->markerPixel ; - result->linePixel = c1->linePixel ; - result->nPoints = 0 ; - - if (c1->nPoints < c2->nPoints) - { - result->points = (XYPoint *) malloc - (sizeof(XYPoint) * (c1->nPoints)) ; - } - else - { - result->points = (XYPoint *) malloc - (sizeof(XYPoint) * (c2->nPoints)) ; - } - - while ((c1index < c1->nPoints) && (c2index < c2->nPoints)) - { - if (c1->points[c1index].x < c2->points[c2index].x) - { - c1index++ ; - } - else if (c1->points[c1index].x > c2->points[c2index].x) - { - c2index++ ; - } - else if (c1->points[c1index].x == c2->points[c2index].x) - { - result->nPoints++ ; - result->points[rrindex].x = c1->points[c1index].x ; - result->points[rrindex].y = c1->points[c1index].y - - c2->points[c2index].y ; - - rrindex++ ; - c1index++ ; - c2index++ ; - } - } - - return (result) ; -} - -void errorEQParseDialog( Widget w, int error_code ) { - - char* error_msg ; - - /* For error dialog */ - Widget dialog ; - Arg wargs[5] ; - int nargs ; - char msg1[80] ; - XmString msg ; - - error_msg = eqperror( error_code ) ; - sprintf(msg1, "%s%s", "An error was encountered while handling\n" - "the formula entry.\n\n", - error_msg) ; - free( error_msg ) ; - - /* Warning dialog box that says no common points */ - msg = XmStringCreateLocalized(msg1) ; - nargs = 0 ; - XtSetArg( wargs[nargs], XmNmessageString, msg ) ; nargs++ ; - XtSetArg( wargs[nargs], XmNtitle, "Error" ) ; nargs++ ; - dialog = XmCreateErrorDialog( w, "error_message", wargs, nargs ) ; - XtManageChild( dialog ) ; - - return; -} diff --git a/trick_source/data_products/fermi-ware/XY.h b/trick_source/data_products/fermi-ware/XY.h deleted file mode 100644 index 5b64e754..00000000 --- a/trick_source/data_products/fermi-ware/XY.h +++ /dev/null @@ -1,186 +0,0 @@ -/******************************************************************************* -* * -* XY.h - General Purpose Plot Widget, Public Header File * -* * -* Copyright (c) 1991 Universities Research Association, Inc. * -* All rights reserved. * -* * -* This material resulted from work developed under a Government Contract and * -* is subject to the following license: The Government retains a paid-up, * -* nonexclusive, irrevocable worldwide license to reproduce, prepare derivative * -* works, perform publicly and display publicly by or for the Government, * -* including the right to distribute to other Government contractors. Neither * -* the United States nor the United States Department of Energy, nor any of * -* their employees, makes any warrenty, express or implied, or assumes any * -* legal liability or responsibility for the accuracy, completeness, or * -* usefulness of any information, apparatus, product, or process disclosed, or * -* represents that its use would not infringe privately owned rights. * -* * -* Fermilab Nirvana GUI Library * -* May 28, 1992 * -* * -* Written by Mark Edel * -* * -*******************************************************************************/ - -#ifndef XY_H -#define XY_H - -enum XYRescaleModes {XY_NO_RESCALE, XY_RESCALE, XY_RESCALE_AT_MAX}; -enum XYStringAlignments {XY_LEFT, XY_CENTER, XY_RIGHT}; -#define XY_N_MARK_STYLES 10 -#define XY_N_MARK_SIZES 4 -#define XY_N_LINE_STYLES 13 - -/* JBF added if _CURVE_INFO_ define stuff to match old versions and - * to be compatible w/Data Products - */ -#ifndef _CURVE_INFO_ -#define _CURVE_INFO_ -enum XYMarkStyles {XY_NO_MARK, XY_SQUARE_MARK, XY_CIRCLE_MARK, XY_STAR_MARK, - XY_X_MARK, XY_TRIANGLE_MARK, XY_SOLID_SQUARE_MARK, XY_SOLID_CIRCLE_MARK, - XY_THICK_SQUARE_MARK, XY_THICK_CIRCLE_MARK}; -enum XYMarkSizes {XY_TINY, XY_SMALL, XY_MEDIUM, XY_LARGE}; -enum XYLineStyles {XY_NO_LINE, XY_PLAIN_LINE, XY_FINE_DASH, XY_MED_FINE_DASH, - XY_DASH, XY_LONG_DASH, XY_X_LONG_DASH, XY_1_DOT_DASH, XY_2_DOT_DASH, - XY_3_DOT_DASH, XY_4_DOT_DASH, XY_THICK_LINE, XY_X_THICK_LINE}; -#endif /* _CURVE_INFO_ */ - -/* Resource strings */ -#define XmNdoubleBuffer "doubleBuffer" -#define XmCDoubleBuffer "DoubleBuffer" -#define XmNshowLegend "showLegend" -#define XmCShowLegend "ShowLegend" -#define XmNshowGrid "showGrid" -#define XmCShowGrid "ShowGrid" -#define XmNgridColor "gridColor" -#define XmCGridColor "gridColor" -#define XmNprintGridColor "printGridColor" -#define XmCPrintGridColor "printGridColor" -#define XmNxLogScaling "xLogScaling" -#define XmCXLogScaling "XLogScaling" -#define XmNyLogScaling "yLogScaling" -#define XmCYLogScaling "YLogScaling" -#define XmNmarginPercent "marginPercent" -#define XmCMarginPercent "MarginPercent" -#define XmNbtn2Callback "btn2Callback" -#define XmCBtn2Callback "Btn2Callback" -#define XmNbtn3Callback "btn3Callback" -#define XmCBtn3Callback "Btn3Callback" - -/* JBF - added plotTitle from old version */ -#define XmNplotTitle "plotTitle" -#define XmCPlotTitle "PlotTitle" - -#define XmNxAxisLabel "xAxisLabel" -#define XmCXAxisLabel "XAxisLabel" -#define XmNyAxisLabel "yAxisLabel" -#define XmCYAxisLabel "YAxisLabel" -#define XmNredisplayCallback "redisplayCallback" -#define XmCRedisplayCallback "RedisplayCallback" - -/* Keith added the crosshairs */ -#define XmNenableCrosshairs "enableCrosshairs" -#define XmCEnableCrosshairs "EnableCrosshairs" - -#define XmNValueDisplay "valueDisplay" -#define XmCValueDisplay "ValueDisplay" - -#define XmNyAxisFormat "yAxisFormat" -#define XmCYAxisFormat "YAxisFormat" - -extern WidgetClass xyWidgetClass; - -typedef struct _XYClassRec *XYWidgetClass; -typedef struct _XYRec *XYWidget; - -/* - * It is possible that XYPoint will be defined in AppUtil.hh or somewhere else - * This is my work around... :-( - */ -#ifndef _XYPOINT_ -#define _XYPOINT_ -typedef struct _XYPoint { - double x, y; -} XYPoint; -#endif - -typedef struct _XYErrorBar { - float min, max; -} XYErrorBar; - -typedef struct _XYString { - float x, y; -#if XmVERSION < 2 - XmFontList render_font; -#else - XmRenderTable render_font; -#endif - Pixel color; - int alignment; - XmString string; -} XYString; - -typedef struct { - int reason; - XEvent *event; -} XYCallbackStruct; - -typedef struct _XYCurve { - XmString curve_id ; - XmString name; - char markerStyle; - char markerSize; - char lineStyle; - Pixel markerPixel; - Pixel linePixel; - int nPoints; - XYPoint *points; - XYErrorBar *horizBars; - XYErrorBar *vertBars; - int flatline ; - double flatlineValue ; -} XYCurve; - -typedef struct { - Widget x_formula ; - Widget y_formula ; - XYWidget w ; -} XYManipulateCurveCBData ; - -typedef struct { - Widget curves_formula ; - XYWidget w ; -} XYCombineCurvesCBData ; - -void XYSetContents(Widget w, XYCurve *curves, int nCurves, int rescaleMode); -void XYUpdateStyles(Widget w, XYCurve *curves); -void XYUpdateData(Widget w, XYCurve *curves, int rescaleMode); -void XYSetStrings(Widget w, XYString *strings, int nStrings); -void XYSetVisibleRange(Widget w, double minXLim, double minYLim, - double maxXLim, double maxYLim); -void XYGetVisibleRange(Widget w, double *minXLim, double *minYLim, - double *maxXLim, double *maxYLim); -void XYZoomOut(Widget w); -void XYZoomIn(Widget w); -void XYResetZoom(Widget w); -void XYPrintContents(Widget w, char *psFileName); -/* JBF */ -void XYPrintMultiple(Widget w[], - int landscape, - int num_plots, - int num_rows, - int num_columns, - char *page_title, - char *page_sub_title, - Boolean DestroyOldFile, - char *psFileName); - -int getXYCurves(Widget w, XYCurve **curve) ; -int addXYPoints(Widget w, int curve_num, XYPoint *data, int num_points) ; -/* end JBF */ -void XYDrawMarker(Display *display, Drawable drawBuf, GC gc, int size, - int style, Pixel color, int x, int y); -void XYDrawLine(Display *display, Drawable drawBuf, GC gc, int style, - Pixel color, int x1, int y1, int x2, int y2); -#endif diff --git a/trick_source/data_products/fermi-ware/XYP.h b/trick_source/data_products/fermi-ware/XYP.h deleted file mode 100644 index 69c6745f..00000000 --- a/trick_source/data_products/fermi-ware/XYP.h +++ /dev/null @@ -1,125 +0,0 @@ -/******************************************************************************* -* * -* XYP.h - General Purpose Plot Widget, Private Header File * -* * -* Copyright (c) 1991 Universities Research Association, Inc. * -* All rights reserved. * -* * -* This material resulted from work developed under a Government Contract and * -* is subject to the following license: The Government retains a paid-up, * -* nonexclusive, irrevocable worldwide license to reproduce, prepare derivative * -* works, perform publicly and display publicly by or for the Government, * -* including the right to distribute to other Government contractors. Neither * -* the United States nor the United States Department of Energy, nor any of * -* their employees, makes any warrenty, express or implied, or assumes any * -* legal liability or responsibility for the accuracy, completeness, or * -* usefulness of any information, apparatus, product, or process disclosed, or * -* represents that its use would not infringe privately owned rights. * -* * -* Fermilab Nirvana GUI Library * -* May 28, 1992 * -* * -* Written by Mark Edel * -* * -*******************************************************************************/ -#ifndef XYP_H -#define XYP_H - -#include "XY.h" -#include -#if XmVERSION >= 2 -#include -#endif - -typedef struct _XYClassPart{ - int ignore; -} XYClassPart; - -typedef struct _XYClassRec{ - CoreClassPart core_class; - XmPrimitiveClassPart primitive_class; - XYClassPart xy_class; -} XYClassRec; - -extern XYClassRec xyClassRec; - -typedef struct _XYPart { - /* JBF - added zoomGC from old version */ - GC zoomGC; /* Graphics context for zoom box */ - GC gc; /* Graphics context for axes & labels */ - GC contentsGC; /* Graphics context for plot contents */ - Pixmap drawBuffer; /* Double buffering for non-flashing draws */ - - Pixmap valueBuffer; /* Double buffering for value mark */ - int valueX ; /* coordinates of mark */ - int valueY ; /* coordinates of mark */ - - int xMin, yMin, xMax, yMax; /* Boundaries of the drawable area of widget */ -#if XmVERSION < 2 - XmFontList render_font; /* Motif font list associated with widget */ -#else - XmRenderTable render_font; /* Motif Render Table associated with widget */ -#endif - XtCallbackList resize; /* Callbacks */ - XtCallbackList btn2; - XtCallbackList btn3; - XtCallbackList redisplay; - Boolean doubleBuffer; /* When set, draw first to offscreen pixmap */ - Boolean xLogScaling; /* When set, plot X axis as log of X */ - Boolean yLogScaling; /* When set, plot Y axis as log of Y */ - Boolean showLegend; /* When set, show the plot legend */ - Boolean showGrid; /* When set, draw the grid lines */ - - Pixel gridColor; /* color for grid lines */ - Pixel printGridColor; /* color for grid lines */ - /* JBF - added plotTitle from old version */ - XmString plotTitle; /* Compound string for plot title */ - - - XmString xAxisLabel; /* Compound string labels for axes */ - XmString yAxisLabel; - XmString yAxisFormat; /* printf format to show on Y axis */ - int marginPercent; /* Size of plot border in % of data range */ - int xOrigin, yOrigin; /* The point where the axis lines meet */ - int xEnd, yEnd; /* The ends of the x and y axis lines */ - int legendTop; /* Y coord. of the top of the plot legend */ - int legendLeftMargin; /* left edge of legend */ - int axisLeft, axisTop; /* Along with xOrigin and yOrigin, define */ - int axisBottom, axisRight; /* the boundaries of the axis areas */ - int legendRows; /* Number of rows in the plot legend */ - int legendColumnSpacing; /* How far apart to space legend columns */ - int dragState; /* Is the user currently dragging the mouse? */ - double xDragStart; /* X (data coord) position of start of drag */ - double yDragStart; /* Y (data coord) position of start of drag */ - double minXData, maxXData; /* Minimum and maximum x data values */ - double minYData, maxYData; /* Minimum and maximum y data values */ - double minXLim, maxXLim; /* Min and max x data actually displayed */ - double minYLim, maxYLim; /* Min and max y data actually displayed */ - XYCurve *curves; /* Data to be displayed on the plot */ - int nCurves; /* Number of curves in curves above */ - XYString *strings; /* Text strings to be displayed on the plot */ - int nStrings; /* Number of text strings in strings above */ - int selectedCurve ; /* Index of curve selected by user */ - - Boolean enableCrosshairs ; /* User preference */ - int crosshairFirst ; /* First time to display crosshair */ - int lastCrosshairX ; /* Save X-Y pixel location of crosshair */ - int lastCrosshairY ; - int crosshairHoriXTextCoord ; /* X-Y pix location of value on horizontal */ - int crosshairHoriYTextCoord ; /* line in cross hair */ - int crosshairVertXTextCoord ; /* X-Y pix location of value on vertical */ - int crosshairVertYTextCoord ; /* line in cross hair */ - char crosshairHoriText[16] ; /* Numbers displayed for crosshair */ - char crosshairVertText[16] ; - - Boolean valueDisplay ; /* User preference */ - -} XYPart; - -typedef struct _XYRec { - CorePart core; - XmPrimitivePart primitive; - XYPart xy; -} XYRec; - -#endif diff --git a/trick_source/data_products/fermi-ware/dragAxes.c b/trick_source/data_products/fermi-ware/dragAxes.c deleted file mode 100644 index bcc18dcd..00000000 --- a/trick_source/data_products/fermi-ware/dragAxes.c +++ /dev/null @@ -1,221 +0,0 @@ -/******************************************************************************* -* * -* dragAxes.c - Handle axis dragging for 2D plotting widgets * -* * -* Copyright (c) 1991 Universities Research Association, Inc. * -* All rights reserved. * -* * -* This material resulted from work developed under a Government Contract and * -* is subject to the following license: The Government retains a paid-up, * -* nonexclusive, irrevocable worldwide license to reproduce, prepare derivative * -* works, perform publicly and display publicly by or for the Government, * -* including the right to distribute to other Government contractors. Neither * -* the United States nor the United States Department of Energy, nor any of * -* their employees, makes any warrenty, express or implied, or assumes any * -* legal liability or responsibility for the accuracy, completeness, or * -* usefulness of any information, apparatus, product, or process disclosed, or * -* represents that its use would not infringe privately owned rights. * -* * -* Fermilab Nirvana GUI Library * -* May 28, 1992 * -* * -* Written by Mark Edel * -* * -*******************************************************************************/ -#include -#include -#include "dragAxes.h" - -enum dragStates {NOT_DRAGGING, DRAGGING_NOTHING, DRAGGING_TOP, DRAGGING_BOTTOM, - DRAGGING_BOTTOM_AND_LEFT, DRAGGING_LEFT, DRAGGING_RIGHT, DRAGGING_DATA}; - -/* -** ResetAxisDragging -** -** Call this before calling DragAxes to initialize the drag state. Can also -** be called to stop any axis dragging currently in progress. -*/ -void ResetAxisDragging(int *dragState) -{ - *dragState = NOT_DRAGGING; -} - -/* -** DragAxes -** -** process a button motion (mouse drag) event to 1) check if it is within -** the boundaries of the axis dragging areas and 2) if so process the -** drag event to adjust the plotting limits. Requires the caller to -** maintain the dragState, xDragStart, and yDragStart variables between -** calls. Call ResetAxisDragging to initialize dragState before calling -** this routine. -*/ -int DragAxes(XEvent *event, int xOrigin, int xEnd, int yOrigin, - int yEnd, int axisLeft, int axisTop, int axisBottom, int axisRight, - double minXData, double maxXData, double minYData, double maxYData, - int xLogScaling, int yLogScaling, double *minXLimit, double *maxXLimit, - double *minYLimit, double *maxYLimit, int *dragState, - double *xDragStart, double *yDragStart) -{ - double minXLim, minYLim, maxXLim, maxYLim; - double minXDat, minYDat, maxXDat, maxYDat; - double xScale, yScale, xOffset, yOffset, newLim; - int x, y; - int redrawArea = DA_REDRAW_NONE; - - /* use log coordinates (which are linear) for log scaling on either axis */ - if (xLogScaling) { - minXLim = log10(*minXLimit); maxXLim = log10(*maxXLimit); - minXDat = log10(minXData); maxXDat = log10(maxXData); - } else { - minXLim = *minXLimit; maxXLim = *maxXLimit; - minXDat = minXData; maxXDat = maxXData; - } - if (yLogScaling) { - minYLim = log10(*minYLimit); maxYLim = log10(*maxYLimit); - minYDat = log10(minYData); maxYDat = log10(maxYData); - } else { - minYLim = *minYLimit; maxYLim = *maxYLimit; - minYDat = minYData; maxYDat = maxYData; - } - - /* calculate scale factors for translating data coords to pixel coords */ - xScale = (maxXLim - minXLim)/(xEnd - xOrigin); - yScale = (maxYLim - minYLim)/(yOrigin - yEnd); - - if (event->type == ButtonPress || event->type == MotionNotify) { - x = event->xbutton.x; - y = event->xbutton.y; - switch (*dragState) { - case NOT_DRAGGING: - if (x >= xOrigin && x <= xEnd && y <= yOrigin && y >= yEnd) - *dragState = DRAGGING_DATA; - else if (x >= axisLeft && x <= xOrigin && - y >= yOrigin && y <= axisBottom) - *dragState = DRAGGING_BOTTOM_AND_LEFT; - else if (x >= axisLeft && x <= xOrigin && - y >= axisTop && y <= axisBottom) - if (y < yEnd + (yOrigin - yEnd)/2) - *dragState = DRAGGING_TOP; - else - *dragState = DRAGGING_BOTTOM; - else if (x >= axisLeft && x <= axisRight && - y <= axisBottom && y >= yOrigin ) - if (x < xOrigin + (xEnd - xOrigin)/2) - *dragState = DRAGGING_LEFT; - else - *dragState = DRAGGING_RIGHT; - else - *dragState = DRAGGING_NOTHING; - *xDragStart = minXLim + (double)(x - xOrigin) * xScale; - *yDragStart = minYLim + (double)(yOrigin - y) * yScale; - break; - case DRAGGING_NOTHING: - break; - case DRAGGING_DATA: - xOffset = minXLim - (*xDragStart - (x - xOrigin) * xScale); - yOffset = minYLim - (*yDragStart - (yOrigin - y) * yScale); - if (maxXLim - xOffset > maxXDat) - xOffset = maxXLim - maxXDat; - else if (minXLim - xOffset < minXDat) - xOffset = minXLim - minXDat; - if (xOffset != 0.) { - *maxXLimit = xLogScaling ? pow(10., maxXLim-xOffset) : - maxXLim-xOffset; - *minXLimit = xLogScaling ? pow(10., minXLim-xOffset) : - minXLim-xOffset; - redrawArea |= DA_REDRAW_H_AXIS | DA_REDRAW_CONTENTS; - } - if (maxYLim - yOffset > maxYDat) - yOffset = maxYLim - maxYDat; - else if (minYLim - yOffset < minYDat) - yOffset = minYLim - minYDat; - if (yOffset != 0.) { - *maxYLimit = yLogScaling ? pow(10., maxYLim-yOffset) : - maxYLim-yOffset; - *minYLimit = yLogScaling ? pow(10., minYLim-yOffset) : - minYLim-yOffset; - redrawArea |= DA_REDRAW_V_AXIS | DA_REDRAW_CONTENTS; - } - break; - case DRAGGING_TOP: - if (y < yOrigin) - newLim = minYLim + (*yDragStart - minYLim) * - (double)(yOrigin-yEnd)/(double)(yOrigin-y); - if (y >= yOrigin || newLim > maxYDat) - newLim = maxYDat; - if (newLim != maxYLim) - redrawArea |= DA_REDRAW_V_AXIS | DA_REDRAW_CONTENTS; - *maxYLimit = yLogScaling ? pow(10., newLim) : newLim; - break; - case DRAGGING_BOTTOM: - if (y > yEnd) - newLim = maxYLim - (maxYLim - *yDragStart) * - (double)(yOrigin - yEnd)/(double)(y - yEnd); - if (y <= yEnd || newLim < minYDat) - newLim = minYDat; - if (newLim != minYLim) - redrawArea |= DA_REDRAW_V_AXIS | DA_REDRAW_CONTENTS; - *minYLimit = yLogScaling ? pow(10., newLim) : newLim; - break; - case DRAGGING_BOTTOM_AND_LEFT: - if (y > yEnd) - newLim = maxYLim - (maxYLim - *yDragStart) * - (double)(yOrigin - yEnd)/(double)(y - yEnd); - if (y <= yEnd || newLim < minYDat) - newLim = minYDat; - if (newLim != minYLim) - redrawArea |= DA_REDRAW_V_AXIS | DA_REDRAW_CONTENTS; - *minYLimit = yLogScaling ? pow(10., newLim) : newLim; - if (x < xEnd) - newLim = maxXLim - (maxXLim - *xDragStart) * - (double)(xEnd - xOrigin)/(double)(xEnd - x); - if (x >= xEnd || newLim < minXDat) - newLim = minXDat; - if (newLim != minXLim) - redrawArea |= DA_REDRAW_H_AXIS | DA_REDRAW_CONTENTS; - *minXLimit = xLogScaling ? pow(10., newLim) : newLim; - break; - case DRAGGING_RIGHT: - if (x > xOrigin) - newLim = minXLim + (*xDragStart - minXLim) * - (double)(xEnd - xOrigin)/(double)(x - xOrigin); - if (x <= xOrigin || newLim > maxXDat) - newLim = maxXDat; - if (newLim != maxXLim) - redrawArea |= DA_REDRAW_H_AXIS | DA_REDRAW_CONTENTS; - *maxXLimit = xLogScaling ? pow(10., newLim) : newLim; - break; - case DRAGGING_LEFT: - if (x < xEnd) - newLim = maxXLim - (maxXLim - *xDragStart) * - (double)(xEnd - xOrigin)/(double)(xEnd - x); - if (x >= xEnd || newLim < minXDat) - newLim = minXDat; - if (newLim != minXLim) - redrawArea |= DA_REDRAW_H_AXIS | DA_REDRAW_CONTENTS; - *minXLimit = xLogScaling ? pow(10., newLim) : newLim; - break; - } - } - - /* conversion back and forth to log coordinates can introduce error which - will make the plot limits not match the data limits when the user has - dragged the scale all the way back in. This code restores them */ - if (xLogScaling) { - minXLim = log10(*minXLimit); maxXLim = log10(*maxXLimit); - if (fabs(minXLim - minXDat) < (maxXLim - minXLim) / 1000.) - *minXLimit = minXData; - if (fabs(maxXLim - maxXDat) < (maxXLim - minXLim) / 1000.) - *maxXLimit = maxXData; - } - if (yLogScaling) { - minYLim = log10(*minYLimit); maxYLim = log10(*maxYLimit); - if (fabs(minYLim - minYDat) < (maxYLim - minYLim) / 1000.) - *minYLimit = minYData; - if (fabs(maxYLim - maxYDat) < (maxYLim - minYLim) / 1000.) - *maxYLimit = maxYData; - } - - return redrawArea; -} diff --git a/trick_source/data_products/fermi-ware/dragAxes.h b/trick_source/data_products/fermi-ware/dragAxes.h deleted file mode 100644 index 664e3cb6..00000000 --- a/trick_source/data_products/fermi-ware/dragAxes.h +++ /dev/null @@ -1,36 +0,0 @@ -/******************************************************************************* -* * -* dragAxes.h - Handle axis dragging for 2D plotting widgets * -* * -* Copyright (c) 1991 Universities Research Association, Inc. * -* All rights reserved. * -* * -* This material resulted from work developed under a Government Contract and * -* is subject to the following license: The Government retains a paid-up, * -* nonexclusive, irrevocable worldwide license to reproduce, prepare derivative * -* works, perform publicly and display publicly by or for the Government, * -* including the right to distribute to other Government contractors. Neither * -* the United States nor the United States Department of Energy, nor any of * -* their employees, makes any warrenty, express or implied, or assumes any * -* legal liability or responsibility for the accuracy, completeness, or * -* usefulness of any information, apparatus, product, or process disclosed, or * -* represents that its use would not infringe privately owned rights. * -* * -* Fermilab Nirvana GUI Library * -* May 28, 1992 * -* * -* Written by Mark Edel * -* * -*******************************************************************************/ -#define DA_REDRAW_NONE 0 -#define DA_REDRAW_H_AXIS 1 -#define DA_REDRAW_V_AXIS 2 -#define DA_REDRAW_CONTENTS 4 - -void ResetAxisDragging(int *dragState); -int DragAxes(XEvent *event, int xOrigin, int xEnd, int yOrigin, - int yEnd, int axisLeft, int axisTop, int axisBottom, int axisRight, - double minXData, double maxXData, double minYData, double maxYData, - int xLogScaling, int yLogScaling, double *minXLimit, double *maxXLimit, - double *minYLimit, double *maxYLimit, int *dragState, - double *xDragStart, double *yDragStart); diff --git a/trick_source/data_products/fermi-ware/drawAxes.c b/trick_source/data_products/fermi-ware/drawAxes.c deleted file mode 100644 index 2b2b6a49..00000000 --- a/trick_source/data_products/fermi-ware/drawAxes.c +++ /dev/null @@ -1,1574 +0,0 @@ -/******************************************************************************* -* * -* drawAxes.c -- Generic axis drawing routines for 2D graphs & plots * -* * -* Copyright (c) 1991 Universities Research Association, Inc. * -* All rights reserved. * -* * -* This material resulted from work developed under a Government Contract and * -* is subject to the following license: The Government retains a paid-up, * -* nonexclusive, irrevocable worldwide license to reproduce, prepare derivative * -* works, perform publicly and display publicly by or for the Government, * -* including the right to distribute to other Government contractors. Neither * -* the United States nor the United States Department of Energy, nor any of * -* their employees, makes any warrenty, express or implied, or assumes any * -* legal liability or responsibility for the accuracy, completeness, or * -* usefulness of any information, apparatus, product, or process disclosed, or * -* represents that its use would not infringe privately owned rights. * -* * -* Fermilab Nirvana GUI Library * -* May 28, 1992 * -* * -* Written by Mark Edel * -* * -*******************************************************************************/ -#include -#include -#include -#include -#include -#include -#include "psUtils.h" -#include "drawAxes.h" - -/* prototypes of system routines missing from include files */ -#ifdef VMS -#include "../util/vmsUtils.h" -#else -//double rint(double); -#endif /*VMS*/ - -#define SHORT_TIC_LEN 4 /* length in pixels for short axis tic marks */ -#define MED_TIC_LEN 6 /* length in pixels for medium axis tic marks */ -#define LONG_TIC_LEN 8 /* length in pixels for long axis tic marks. - if too short, large fonts may collide at - the intersection of the v and h axes */ -#define MIN_TIC_SPACING 4 /* minimum interval in pixels for axis tics */ -#define MIN_LOG_TIC_SPACING 2 /* min spacing for axis tics on log plots */ -#define BIN_TIC_THRESHOLD 4 /* minimum spacing of tics labeling bin edges - before ignoring bin edges in choosing tics */ -#define MIN_V_LABEL_SPACING 1 /* vertical space to leave between labels in - (font dep.) units of character height */ -#define MIN_V_LOG_LABEL_SPACING .5 /* "" for log plots */ -#define MIN_H_LABEL_SPACING 1 /* horizontal space to leave between labels - in units of maximum character width */ -#define MIN_H_LOG_LABEL_SPACING .5 /* "" for log plots */ - -/* table of multiples of 10, 2, and 5 for reference in figuring label spacing */ -#define NMULTIPLIERS 15 -static int Multipliers[NMULTIPLIERS] = { - 1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000, 50000}; - -static void drawLinearVAxis(Display *display, Drawable window, GC gc, - XFontStruct *fs, int outDevice, int x, int x2, int y11, int y2, - double minData, double maxData, double minLimit, double maxLimit, XmString yAxisFormat , - int showGrid, Pixel gridColor , Pixel printGridColor ); - -static void drawLogVAxis(Display *display, Drawable window, GC gc, - XFontStruct *fs, int outDevice, int x, int y11, int y2, - double minData, double maxData, double minLimit, double maxLimit); - -static void drawLinearHAxis(Display *display, Drawable window, GC gc, - XFontStruct *fs, int outDevice, int y, int y2, int x1, int x2, - double minData, double maxData, double minLimit, double maxLimit, - int showGrid, Pixel gridColor , Pixel printGridColor ); -static void drawDiscreteHAxis(Display *display, Drawable window, GC gc, - XFontStruct *fs, int outDevice, int y, int x1, int x2, - double minData, double maxData, double minLimit, double maxLimit, int nBins); -static void drawLogHAxis(Display *display, Drawable window, GC gc, - XFontStruct *fs, int outDevice, int y, int x1, int x2, - double minData, double maxData, double minLimit, double maxLimit); -static int calcDecimalOffset(char *labelStr, XFontStruct *fs); -static double calcLinTicInterval(double labelInterval, double scale, int factor); -static double calcLogTicInterval(int pixRange, double labelInterval, double min, - double max, int factor); -static double calcTicInterval(double labelInterval, double minTicInterval, - int factor); -static double calcLabelInterval(int pixRange, double dataRange, XFontStruct *fs, - int *factor); -static double calcLogLabelInterval(int pixRange, double min, double max, - XFontStruct *fs, int *factor); -static double calcMinLogInterval(int pixRange, double min, double max, - double narrowSpacing, double wideSpacing, int *factor); -static void drawHCenteredFloat(Display *display, Drawable window, GC gc, - XFontStruct *fs, int outDevice, double value, int x, int y); -static void drawVCenteredFloat(Display *display, Drawable window, GC gc, - XFontStruct *fs, int outDevice, double value, - int x, int y, int maxDecimalOffset, XmString yAxisFormat); -static void measureHCenteredFloat(XFontStruct *fs, double value, - int x, int *left, int *right); -static void genHAxisLineSegs(XSegment **segPtr, int *segCount, int x1, int x2, - int y, int drawAxisLine, int drawLeftArrow, int drawRightArrow); -static void genVAxisLineSegs(XSegment **segPtr, int *segCount, int x, int y11, - int y2, int drawAxisLine, int drawTopArrow, int drawBottomArrow); - -/* -** A note about rounding errors: -** -** Because this code deals with both an integer coordinate system and -** the floating point coordinate system of the data, it is sensitive -** to rounding errors. Be careful when you make changes. Think about -** how the data will be quantized. Will precision be lost? Will there -** be biases? -*/ - -/* -** HAxisHeight HAxisEndClearance VAxisWidth VAxisEndClearance -** -** Determine amount of space required to draw axes. The calls which actually -** draw the axes, DrawHorizontalAxis and DrawVerticalAxis, draw from the -** desired coordinates of the axis lines, but use space around the lines -** for tic marks and scale text. Use these routines to find out how much -** space the axis drawing routines will need. -*/ -int HAxisHeight(XFontStruct *fs) -{ - /* allow space for label below long tic separated by 2 pixels */ - return fs->ascent + LONG_TIC_LEN + 2; -} -int HAxisEndClearance(XFontStruct *fs) -{ - /* allow space for half of an 10 digit number to stick off end of axis */ - return XTextWidth(fs, "1234567890", 10) / 2; -} -int VAxisWidth(XFontStruct *fs, XmString format) -{ - char temp[40] ; - int digits ; - - char *str; - -#if XmVERSION < 2 - XmStringContext context; - XmStringCharSet charset; - XmStringDirection direction; - Boolean separator = FALSE; - String text = NULL ; - - XmStringInitContext(&context,format); - XmStringGetNextSegment(context,&text,&charset, &direction,&separator) ; - str = (char *)text ; -#else - str = XmStringUnparse(format, NULL, 0, XmCHARSET_TEXT, NULL, 0, XmOUTPUT_ALL); -#endif - sprintf(temp , str , -1.23456789012345678901234567890) ; - digits = strlen(temp) ; - XtFree(str) ; - - /* allow space for 10 character labels + axis tics (may have to change) */ - return XTextWidth(fs, "123456789012345678901234567890" , digits + 1) + LONG_TIC_LEN + 1; -} - -int VAxisEndClearance(XFontStruct *fs) -{ - /* allow space for half of a label to protrude above or below axis line */ - return fs->ascent / 2; -} - -/* -** DrawHorizontalAxis -** -** Draw a horizontal axis for a plot or histogram. For histograms, providing -** the routine with the number of bins in the histogram allows it to choose -** between labeling bin edges precisely, and drawing a general purpose -** horizontal axis ignoring bin edges. Specify the position of the axis -** by the x and y window coordinates where the actual axis line should be -** drawn. Use HAxisHeight and HAxisEndClearance to find the amount of space -** that this routine will need to accomodate the tics and labels underneath -** and to either side of the axis line. -** -** Parameters -** -** display X display to draw to. -** window X window or pixmap to draw into. -** gc X graphics context to use in drawing labels and tics -** fs X font structure for font measurements. Even though -** gc specifies the font to be used to draw the string, -** the caller has to supply this argument with the -** XFontStruct corresponding to the font in the gc. -** This avoids round trip overhead of querying the -** server for the font data -** outDevice Output device, X_SCREEN, or PS_PRINTER -** y, x1, and, x2 Where to draw the axis line itself -** in window coordinates. -** minData, Horizontal range of the data to be plotted, even -** maxData if some of it is outside the range displayed. -** minLimit, Limits in data coordinates on the data displayed. -** maxLimit The part of the axis outside of minLimit and maxLimit -** is not drawn, but arrows indicate that some data is -** not shown. -** logScaling Use log scaling, if false, use linear scaling. -** nBins For histograms, the number of bins (for labeling -** bin edges). Pass nBins = 0 for a continuous axis. -*/ -/* RCS -void DrawHorizontalAxis(Display *display, Drawable window, GC gc, - XFontStruct *fs, int outDevice, int y, int x1, int x2, - double minData, double maxData, double minLimit, double maxLimit, - int logScaling, int nBins) -*/ -void DrawHorizontalAxis(Display *display, Drawable window, GC gc, - XFontStruct *fs, int outDevice, int y, int y2, int x1, int x2, - double minData, double maxData, double minLimit, double maxLimit, - int logScaling, int nBins, - int drawGrid, Pixel gridColor , Pixel printGridColor ) -{ - double binWidth, nVisibleBins, nPixelsPerBin; - - /* reject dangerous values here (don't draw axis) rather than cause error */ - if (x2 <= x1 || maxData <= minData || maxLimit <= minLimit) - return; - - /* If log scaling is specified, use log axis routine regardless of - whether the caller wanted to draw a discrete axis */ - if (logScaling) { - drawLogHAxis(display, window, gc, fs, outDevice, y, x1, x2, - minData, maxData, minLimit, maxLimit); - return; - } - - /* Draw a discrete (edge labeled) axis if one was requested and there - are enough pixels per bin to make it worthwhile */ - if (nBins != 0) { - binWidth = (maxData - minData) / nBins; - nVisibleBins = (maxLimit - minLimit) / binWidth; - nPixelsPerBin = (x2 - x1) / nVisibleBins; - if (nPixelsPerBin > BIN_TIC_THRESHOLD) { - drawDiscreteHAxis(display, window, gc, fs, outDevice, y, x1, x2, - minData, maxData, minLimit, maxLimit, nBins); - return; - } - } - - /* Otherwise, draw a plain old linear axis */ - /* RCS - drawLinearHAxis(display, window, gc, fs, outDevice, y, x1, x2, - minData, maxData, minLimit, maxLimit); - */ - drawLinearHAxis(display, window, gc, fs, outDevice, y, y2, x1, x2, - minData, maxData, minLimit, maxLimit, drawGrid, gridColor, printGridColor ); -} - -/* -** DrawVerticalAxis -** -** Draw a vertical axis for a plot or histogram. Specify the position of -** the axis by the x and y window coordinates where the actual axis line should be -** drawn. Use VAxisWidth and VAxisEndClearance to find the amount of space -** that this routine will need to accomodate the tics and labels to the left -** and above and below the axis line. -** -** Parameters -** -** display X display to draw to. -** window X window or pixmap to draw into. -** gc X graphics context to use in drawing labels and tics -** fs X font structure for font measurements. Even though -** gc specifies the font to be used to draw the string, -** the caller has to supply this argument with the -** XFontStruct corresponding to the font in the gc. -** This avoids round trip overhead of querying the -** server for the font data -** outDevice Output device, X_SCREEN, or PS_PRINTER -** x, y1, and, y Where to draw the axis line itself -** in window coordinates. -** minData, Vertical range of the data to be plotted, even -** maxData if some of it is outside the range displayed. -** minLimit, Limits in data coordinates on the data displayed. -** maxLimit The part of the axis outside of minLimit and maxLimit -** is not drawn, but arrows indicate that some data is -** not shown. -*/ -void DrawVerticalAxis(Display *display, Drawable window, GC gc, XFontStruct *fs, - int outDevice, int x, int x2, int y11, int y2, double minData, double maxData, - double minLimit, double maxLimit, int logScaling, XmString yAxisFormat , - int drawGrid, Pixel gridColor, Pixel printGridColor ) -{ - int temp; - - /* reject bad data before it causes an error (just don't draw axis) */ - if (y11==y2 || maxData<=minData || maxLimit<=minLimit) - return; - - /* put y11 & y2 in a known order (y11 = top coord, y2 = bottom coord) */ - if (y2 < y11) { - temp = y2; y2 = y11; y11 = temp; - } - - if (logScaling) - drawLogVAxis(display, window, gc, fs, outDevice, x, y11, y2, - minData, maxData, minLimit, maxLimit); - else - drawLinearVAxis(display, window, gc, fs, outDevice, x, x2, y11, y2, - minData, maxData, minLimit, maxLimit, yAxisFormat , drawGrid, gridColor, printGridColor ); -} - -static void drawLinearVAxis(Display *display, Drawable window, GC gc, - XFontStruct *fs, int outDevice, int x, int x2, int y11, int y2, - double minData, double maxData, double minLimit, double maxLimit, XmString yAxisFormat, - int drawGrid, Pixel gridColor , Pixel printGridColor ) -{ - double dataRange = maxLimit - minLimit; - int pixRange = y2 - y11; - int maxDecimalOffset = 0; - char labelStr[40]; - double labelValue, label1Value, ticValue, tic1Value; - double interval, ticInterval; - double scale, maxTics; - double ticY; - int nSegs, nSegsGrid, nFSegs, maxSegs, factor, decimalOffset; - int tics_nFSegs; - int maxLabels, labelCenter; - int ticLen, i, ticsBetweenLabels; - XSegment *seg, *segs; - XSegment *segGrid, *segsGrid; - FloatSegment *fSeg, *fSegs; - FloatSegment *tics_fSeg, *tics_fSegs; - XGCValues gcValues, grid_gcValues; - int first_tic = 1 ; - XtPointer str ; - - /* calculate a scale to convert data coordinates to pixel coordinates */ - scale = pixRange/dataRange; - - /* determine how far apart to draw the labels and tics */ - interval = calcLabelInterval(pixRange, dataRange, fs, &factor); - ticInterval = calcLinTicInterval(interval, scale, factor); - - /* start the first label at near minLimit rounded to multiples of interval, - start the first tic one label interval before first label */ - label1Value = rint(minLimit / interval) * interval; - tic1Value = label1Value - interval; - - /* measure the length of text after the decimal point for all labels so - they can aligned, but not padded & will work with proportional fonts */ - maxLabels = (int)(dataRange/interval) + 2; - for (i=0; i<=maxLabels; i++) { -#if XmVERSION < 2 - XmStringContext context; - XmStringCharSet charset; - XmStringDirection direction; - Boolean separator = FALSE; - String text = NULL ; - - XmStringInitContext(&context,yAxisFormat); - XmStringGetNextSegment(context,&text,&charset, &direction,&separator) ; - str = (char *)text ; -#else - str = XmStringUnparse(yAxisFormat, NULL, 0, XmCHARSET_TEXT, NULL, 0, XmOUTPUT_ALL); -#endif - - labelValue = label1Value + interval*i; - sprintf(labelStr, (char *)str, labelValue); - XtFree(str) ; - decimalOffset = calcDecimalOffset(labelStr, fs); - if (decimalOffset > maxDecimalOffset) - maxDecimalOffset = decimalOffset; - } - - /* draw the labels using the interval, starting value, - and string offsets calculated above */ - for (i=0; i<=maxLabels; i++) { - labelValue = label1Value + interval*i; - if ( labelValue != 0.0 ) { - if ( fabs(label1Value/labelValue) > 1e10) { - labelValue = 0.0 ; - } - } - labelCenter = rint(y2 - (labelValue - minLimit) * scale); - if (labelCenter >= y11 && labelCenter <= y2) { - drawVCenteredFloat(display, window, gc, fs, outDevice, labelValue, - x - LONG_TIC_LEN - 1, labelCenter, maxDecimalOffset, yAxisFormat); - } - } - - /* allocate enough memory for X segments to draw axis lines and - tics at minimum tic spacing: Maximum # of tics + last tic + - axis line + 0-2 arrows of 2 segments each */ - maxSegs = (y2 - y11)/MIN_TIC_SPACING + 10; - if (outDevice == X_SCREEN) { - segs = (XSegment *)XtMalloc(sizeof(XSegment) * maxSegs); - segsGrid = (XSegment*)XtMalloc(sizeof(XSegment)*maxSegs) ; - seg = segs; - segGrid = segsGrid; - } else { - segs = (XSegment *)XtMalloc(sizeof(XSegment) * 5); - seg = segs; - fSegs = (FloatSegment *)XtMalloc(sizeof(FloatSegment) * maxSegs); - fSeg = fSegs; - tics_fSegs = (FloatSegment *)XtMalloc(sizeof(FloatSegment) * maxSegs); - tics_fSeg = tics_fSegs; - } - nSegs = 0; - nSegsGrid = 0; - nFSegs = 0; - tics_nFSegs = 0; - - /* draw the tics using interval, ticInterval, and tic1Value from above */ - ticsBetweenLabels = (int)rint(interval/ticInterval); - maxTics = dataRange/ticInterval + ticsBetweenLabels + 2; - for (i=0; i<=maxTics; i++) { - ticValue = tic1Value + ticInterval * i; - ticY = y2 - (ticValue - minLimit) * scale; - if (ticY >= y11 && ticY <= y2) { - if (i % ticsBetweenLabels == 0) - ticLen = LONG_TIC_LEN; - else if ((i*2) % ticsBetweenLabels == 0) - ticLen = MED_TIC_LEN; - else - ticLen = SHORT_TIC_LEN; - /* RCS jbf -- added to turn on and off grid lines */ - if (drawGrid) - { - if (outDevice == X_SCREEN) { - if (i % ticsBetweenLabels == 0) { - seg->x1=x; - - /* Gridline segments */ - segGrid->x1=x2 ; - segGrid->x2 = x ; - segGrid->y1 = segGrid->y2 = rint(ticY); - segGrid++; nSegsGrid++; - - } else { - seg->x1=x; - segGrid->x1=x ; - } - - seg->x2=x-ticLen; - seg->y1=seg->y2=rint(ticY); - seg++; nSegs++; - - } else { - if (i % ticsBetweenLabels == 0 && first_tic == 0 ) { - fSeg->x1=x2; - } - else { - fSeg->x1=x; - } - - fSeg->x2=x; - fSeg->y1=fSeg->y2=rint(ticY); - fSeg++; nFSegs++; - - /* Save tics and axis to be printed in black */ - tics_fSeg->x1=x; tics_fSeg->x2=x-ticLen; - tics_fSeg->y1=tics_fSeg->y2=ticY; - tics_fSeg++; tics_nFSegs++; - first_tic = 0 ; - } - } - else - { - - if (outDevice == X_SCREEN) { - seg->x1=x; seg->x2=x-ticLen; seg->y1=seg->y2=rint(ticY); - seg++; nSegs++; - } else { - fSeg->x1=x; fSeg->x2=x-ticLen; fSeg->y1=fSeg->y2=ticY; - fSeg++; nFSegs++; - } - } - } - } - - /* generate axis line and arrow heads to indicate data not shown */ - genVAxisLineSegs(&seg, &nSegs, x, y11, y2, True, - maxData > maxLimit, minData < minLimit); - - XGetGCValues(display, gc, GCForeground, &gcValues); - /* draw the axis and tic lines */ - if (outDevice == X_SCREEN) { - grid_gcValues.foreground = gridColor ; - XChangeGC(display, gc, GCForeground, &grid_gcValues); - XDrawSegments(display, window, gc, segsGrid, nSegsGrid); - XChangeGC(display, gc, GCForeground, &gcValues); - XDrawSegments(display, window, gc, segs, nSegs); - } else { /* PS_PRINTER */ - grid_gcValues.foreground = printGridColor ; - XChangeGC(display, gc, GCForeground, &grid_gcValues); - PSFloatDrawSegments(display, window, gc, fSegs, nFSegs); - XChangeGC(display, gc, GCForeground, &gcValues); - PSFloatDrawSegments(display, window, gc, tics_fSegs, tics_nFSegs); - PSDrawSegments(display, window, gc, segs, nSegs); - XtFree((char *)fSegs); - } - XtFree((char *)segs); -} - -static void drawLogVAxis(Display *display, Drawable window, GC gc, - XFontStruct *fs, int outDevice, int x, int y11, int y2, - double minData, double maxData, double minLimit, double maxLimit) -{ - double logMinLimit, logMaxLimit; - char labelStr[16]; - double label1Value, labelValue, logLabelValue, labelLimit; - double powLabelValue, logPowLabelValue, logPowLabel1Value; - double ticValue, tic1Value, ticLimit, ticY; - double powTicValue, logPowTicValue, logPowTic1Value; - double logPowInterval, logPowTicInterval; - double interval, scaledInterval, ticInterval, scaledTicInterval; - double logScale; - int nSegs, nFSegs, maxSegs, factor, powFactor; - int maxPowLabels, maxPowTics, labelCenter, powLabelCenter; - int ticLen, i, j, ticCount, ticsBetweenLabels, powTicsBetweenLabels; - int decimalOffset, maxDecimalOffset = 0; - XSegment *seg, *segs; - FloatSegment *fSeg, *fSegs; - XmString s0 ; - - /* reject dangerous values */ - if (minData <= 0. || minLimit <= 0. || (maxLimit-minLimit)/minLimit < 1e-6) - return; - - logMinLimit = log10(minLimit); logMaxLimit = log10(maxLimit); - - /* calculate a scale to convert log data coordinates to pixel coordinates */ - logScale = (y2-y11)/(logMaxLimit-logMinLimit); - - /* determine spacing for power of 10 labels and tics. Use linear - spacing algorithms, but limit to no finer than powers of 10 */ - logPowInterval = calcLabelInterval(y2-y11, logMaxLimit-logMinLimit, fs, - &powFactor); - if (logPowInterval < 1) { - logPowInterval = 1; - powFactor = 0; - } - logPowTicInterval = calcLinTicInterval(logPowInterval, logScale, powFactor); - if (logPowTicInterval < 1) - logPowTicInterval = 1; - - /* determine spacing between power of 10 labels */ - interval = calcLogLabelInterval(y2-y11, minLimit, maxLimit, fs, &factor); - ticInterval = calcLogTicInterval(y2-y11, interval, minLimit, maxLimit, - factor); - - /* loop over each power of 10 in the axis range */ - maxPowLabels = (int)((logMaxLimit-logMinLimit)/logPowInterval) + 2; - logPowLabel1Value = floor(logMinLimit / logPowInterval) * logPowInterval; - for (i=0; i<=maxPowLabels; i++) { - logPowLabelValue = logPowLabel1Value + logPowInterval*i; - powLabelValue = pow(10., logPowLabelValue); - - /* calculate the spacing of labels within the power-of-10 intervals */ - if (interval > 1.) { - /* if labels are at intervals of more than one, the log effect - strongly compresses the top of the interval, the values also - start at 1 rather than zero, so we just put labels at 2 and 5 */ - scaledInterval = 3. * powLabelValue; - labelLimit = 6. * powLabelValue; - label1Value = 2. * powLabelValue; - } else { - scaledInterval = interval * powLabelValue; - labelLimit = 10. * powLabelValue - scaledInterval/2; - if (minLimit > powLabelValue) - label1Value = rint(minLimit/scaledInterval) * scaledInterval; - else - label1Value = powLabelValue + scaledInterval; - } - - /* measure the length of text after the decimal point for all labels */ - sprintf(labelStr, "%g", powLabelValue); - maxDecimalOffset = calcDecimalOffset(labelStr, fs); - labelValue = label1Value; - for (j=1; labelValue < labelLimit; j++) { - logLabelValue = log10(labelValue); - labelCenter = (int)rint(y2 - (logLabelValue-logMinLimit)*logScale); - if (labelCenter < y11) - break; - sprintf(labelStr, "%g", labelValue); - decimalOffset = calcDecimalOffset(labelStr, fs); - if (decimalOffset > maxDecimalOffset) - maxDecimalOffset = decimalOffset; - labelValue = label1Value + j*scaledInterval; - } - - /* draw the power-of 10 label */ - powLabelCenter = rint(y2 - (logPowLabelValue - logMinLimit) * logScale); - if (powLabelCenter >= y11 && powLabelCenter <= y2) { - drawVCenteredFloat(display, window, gc, fs, outDevice,powLabelValue, - x - LONG_TIC_LEN - 1, powLabelCenter, maxDecimalOffset, s0 = XmStringCreateLocalized("%g")); - XmStringFree(s0) ; - } - - /* draw the labels within the power-of-10 intervals */ - if (interval > 2.) - continue; - labelValue = label1Value; - for (j=1; labelValue < labelLimit; j++) { - logLabelValue = log10(labelValue); - labelCenter = (int)rint(y2 - (logLabelValue-logMinLimit)*logScale); - if (labelCenter < y11) - break; - if (labelCenter <= y2) { - drawVCenteredFloat(display, window, gc, fs, outDevice, - labelValue, x - LONG_TIC_LEN - 1, - labelCenter, maxDecimalOffset, s0 = XmStringCreateLocalized("%g")); - XmStringFree(s0) ; - } - labelValue = label1Value + j*scaledInterval; - } - } - - /* allocate enough memory for X segments to draw axis lines and - tics at minimum tic spacing: Maximum # of tics + last tic + - axis line + 0-2 arrows of 2 segments each */ - maxSegs = (y2 - y11)/MIN_LOG_TIC_SPACING + 10; - if (outDevice == X_SCREEN) { - segs = (XSegment *)XtMalloc(sizeof(XSegment) * maxSegs); - seg = segs; - } else { - segs = (XSegment *)XtMalloc(sizeof(XSegment) * 5); - seg = segs; - fSegs = (FloatSegment *)XtMalloc(sizeof(FloatSegment) * maxSegs); - fSeg = fSegs; - } - nSegs = 0; - nFSegs = 0; - - /* draw the tics */ - logPowTic1Value = logPowLabel1Value - logPowInterval; - powTicsBetweenLabels = (int)rint(logPowInterval/logPowTicInterval); - maxPowTics = (logMaxLimit - logMinLimit)/logPowTicInterval + - powTicsBetweenLabels + 4; - for (i=0; i<=maxPowTics; i++) { - logPowTicValue = logPowTic1Value + logPowTicInterval * i; - powTicValue = pow(10., logPowTicValue); - ticY = y2 - (logPowTicValue - logMinLimit) * logScale; - if (ticY >= y11 && ticY <= y2) { - if (i % powTicsBetweenLabels == 0) - ticLen = LONG_TIC_LEN; - else if ((i*2) % powTicsBetweenLabels == 0) - ticLen = MED_TIC_LEN; - else - ticLen = SHORT_TIC_LEN; - if (outDevice == X_SCREEN) { - seg->x1=x; seg->x2=x-ticLen; seg->y1=seg->y2=rint(ticY); - seg++; nSegs++; - } else { - fSeg->x1=x; fSeg->x2=x-ticLen; fSeg->y1=fSeg->y2=ticY; - fSeg++; nFSegs++; - } - } - /* draw the tics within the power-of-10 intervals */ - if (ticInterval > 1.) - continue; - scaledTicInterval = ticInterval * powTicValue; - ticsBetweenLabels = interval/ticInterval; - ticLimit = pow(10., floor(logPowTicValue+1.)) - scaledTicInterval/2; - if (minLimit > powTicValue) - tic1Value = floor(minLimit/(scaledTicInterval*10)) * - scaledTicInterval*10 + scaledTicInterval; - else - tic1Value = powTicValue + scaledTicInterval; - ticValue = tic1Value; - for (j=1; ticValue < ticLimit; j++) { - ticValue = tic1Value + (j-1)*scaledTicInterval; - ticY = y2 - (log10(ticValue)-logMinLimit)*logScale; - ticCount = (minLimit<=powTicValue && ticInterval>=1.) ? j+1 : j; - if (ticY < y11) - break; - if (ticY > y2) - continue; - if (interval>1. && interval<=2. && (ticCount==2 || ticCount==5)) - ticLen = LONG_TIC_LEN; - else if (interval>1. && ticCount==5) - ticLen = MED_TIC_LEN; - else if (interval>1.) - ticLen = SHORT_TIC_LEN; - else if (ticCount % ticsBetweenLabels == 0) - ticLen = LONG_TIC_LEN; - else if ((ticCount*2) % ticsBetweenLabels == 0) - ticLen = MED_TIC_LEN; - else - ticLen = SHORT_TIC_LEN; - if (outDevice == X_SCREEN) { - seg->x1=x; seg->x2=x-ticLen; seg->y1=seg->y2=rint(ticY); - seg++; nSegs++; - } else { - fSeg->x1=x; fSeg->x2=x-ticLen; fSeg->y1=fSeg->y2=ticY; - fSeg++; nFSegs++; - } - } - } - - /* generate axis line and arrow heads to indicate data not shown */ - genVAxisLineSegs(&seg, &nSegs, x, y11, y2, True, - maxData > maxLimit, minData < minLimit); - - /* draw the axis and tic lines */ - if (outDevice == X_SCREEN) { - XDrawSegments(display, window, gc, segs, nSegs); - } else { /* PS_PRINTER */ - PSFloatDrawSegments(display, window, gc, fSegs, nFSegs); - PSDrawSegments(display, window, gc, segs, nSegs); - XtFree((char *)fSegs); - } - XtFree((char *)segs); -} - -/* RCS -static void drawLinearHAxis(Display *display, Drawable window, GC gc, - XFontStruct *fs, int outDevice, int y, int x1, int x2, - double minData, double maxData, double minLimit, double maxLimit) -*/ -static void drawLinearHAxis(Display *display, Drawable window, GC gc, - XFontStruct *fs, int outDevice, int y, int y2, int x1, int x2, - double minData, double maxData, double minLimit, double maxLimit, - int showGrid, Pixel gridColor , Pixel printGridColor ) -{ - double dataRange = maxData - minData; - double scale = (x2 - x1)/(maxLimit - minLimit); - double pixRange = dataRange * scale; - double minPix = x1 - (minLimit - minData) * scale; - double minLabelSpacing = (fs->max_bounds).width * MIN_H_LABEL_SPACING; - double labelValue, label1Value, ticValue, tic1Value; - double minInterval, interval, ticInterval, maxTics, ticX; - int consumedSpace, nSegs, nSegsGrid, nFSegs, maxSegs, multIndex; - int tics_nFSegs ; - int maxLabels, labelY, labelLeft, labelRight, labelCenter; - int ticLen, i, ticsBetweenLabels; - XSegment *seg, *segs; - XSegment *segGrid, *segsGrid; - FloatSegment *fSeg, *fSegs; - FloatSegment *tics_fSeg, *tics_fSegs; - XGCValues gcValues, grid_gcValues; - int first_tic = 1 ; - - /* find the maximum number of tics that will fit across the whole axis */ - maxTics = pixRange/MIN_TIC_SPACING; - - /* begin with the rounded factor of 10 below where - labels would be placed every MIN_TIC_SPACING */ - minInterval = pow(10., floor(log10(dataRange/(double)maxTics) - 1.)); - - /* loop, increasing the interval between until all of the labels fit */ - for (multIndex=0; multIndex minData */ - labelValue = (floor(minData / interval)) * interval; //DANNY - if (labelValue < minData) - labelValue += interval; - label1Value = labelValue; - /* loop, checking the placement of all of the labels */ - consumedSpace = INT_MIN; - while (labelValue <= maxData) { - labelCenter = (int)(minPix + (labelValue - minData) * scale); - measureHCenteredFloat(fs, labelValue, labelCenter, &labelLeft, - &labelRight); - if (labelLeft < consumedSpace) - break; /* collision with previous label */ - consumedSpace = labelRight + minLabelSpacing;; - labelValue += interval; - } - /* exit loop if all of the labels were laid out successfully */ - if (labelValue > maxData) - break; - } - if (multIndex == NMULTIPLIERS) { - fprintf(stderr, "Couldn't lay out axis labels. Font problem?"); - return; - } - - /* draw the labels using interval and label1Value calculated above */ - labelY = y + HAxisHeight(fs); - maxLabels = (int)(dataRange/interval + 1); - for (i=0; i<=maxLabels; i++) { - labelValue = label1Value + interval*i; - labelCenter = (int)(minPix + (labelValue - minData) * scale); - if (labelCenter >= x1 && labelCenter <= x2) { - drawHCenteredFloat(display, window, gc, fs, outDevice, - labelValue, labelCenter, labelY); - } - } - - /* allocate enough memory for X segments to draw axis lines and - tics at minimum tic spacing: Maximum # of tics + last tic + - axis line + 0-2 arrows of 2 segments each */ - maxSegs = (x2 - x1)/MIN_TIC_SPACING + 10; - if (outDevice == X_SCREEN) { - segs = (XSegment *)XtMalloc(sizeof(XSegment) * maxSegs); - seg = segs; - segsGrid = (XSegment *)XtMalloc(sizeof(XSegment) * maxSegs); - segGrid = segsGrid; - } else { - segs = (XSegment *)XtMalloc(sizeof(XSegment) * 5); - seg = segs; - fSegs = (FloatSegment *)XtMalloc(sizeof(FloatSegment) * maxSegs); - fSeg = fSegs; - tics_fSegs = (FloatSegment *)XtMalloc(sizeof(FloatSegment) * maxSegs); - tics_fSeg = tics_fSegs; - } - nSegs = 0; - nSegsGrid = 0; - nFSegs = 0; - tics_nFSegs = 0; - - /* determine how far apart to draw the tics */ - ticInterval = calcLinTicInterval(interval, scale, multIndex % 3); - - /* draw the tics */ - tic1Value = label1Value - interval; - ticsBetweenLabels = (int)rint(interval/ticInterval); - maxTics = dataRange/ticInterval + ticsBetweenLabels + 1; - for (i=0; i= x1 && ticX <= x2) { - if (i % ticsBetweenLabels == 0) - ticLen = LONG_TIC_LEN; - else if ((i*2) % ticsBetweenLabels == 0) - ticLen = MED_TIC_LEN; - else - ticLen = SHORT_TIC_LEN; - - /* RCS jbf -- added to turn on and off grid lines */ - if (showGrid) - { - if (outDevice == X_SCREEN) { - - if (i % ticsBetweenLabels == 0) { - seg->y1=y; - - /* Gridline segments */ - segGrid->y1 = y2 ; - segGrid->y2 = y ; - segGrid->x1 = segGrid->x2 = rint(ticX); - segGrid++; nSegsGrid++; - - } else { - seg->y1=y; - segGrid->y1=y ; - } - - seg->x1=seg->x2=(int)ticX; seg->y2=y+ticLen; - seg++; nSegs++; - } else { - if (i % ticsBetweenLabels == 0 && first_tic == 0 ) - fSeg->y1=y2; - else - fSeg->y1=y; - - fSeg->x1=fSeg->x2=ticX; - fSeg->y2=y; - fSeg++; nFSegs++; - tics_fSeg->x1=tics_fSeg->x2=ticX; tics_fSeg->y1=y; tics_fSeg->y2=y+ticLen; - tics_fSeg++; tics_nFSegs++; - first_tic = 0 ; - } - } - else - { - if (outDevice == X_SCREEN) { - seg->x1=seg->x2=(int)ticX; seg->y1=y; seg->y2=y+ticLen; - seg++; nSegs++; - } else { - fSeg->x1=fSeg->x2=ticX; fSeg->y1=y; fSeg->y2=y+ticLen; - fSeg++; nFSegs++; - } - } - } - } - - /* generate axis line and arrow heads to indicate data not shown */ - genHAxisLineSegs(&seg, &nSegs, x1, x2, y, True, - minData < minLimit, maxData > maxLimit); - - /* draw the axis and tic lines */ - XGetGCValues(display, gc, GCForeground, &gcValues); - if (outDevice == X_SCREEN) { - grid_gcValues.foreground = gridColor ; - XChangeGC(display, gc, GCForeground, &grid_gcValues); - XDrawSegments(display, window, gc, segsGrid, nSegsGrid); - XChangeGC(display, gc, GCForeground, &gcValues); - XDrawSegments(display, window, gc, segs, nSegs); - - } else { /* PS_PRINTER */ - grid_gcValues.foreground = printGridColor ; - XChangeGC(display, gc, GCForeground, &grid_gcValues); - PSFloatDrawSegments(display, window, gc, fSegs, nFSegs); - XChangeGC(display, gc, GCForeground, &gcValues); - PSFloatDrawSegments(display, window, gc, tics_fSegs, tics_nFSegs); - PSDrawSegments(display, window, gc, segs, nSegs); - XtFree((char *)fSegs); - } - XtFree((char *)segs); -} - -static void drawLogHAxis(Display *display, Drawable window, GC gc, - XFontStruct *fs, int outDevice, int y, int x1, int x2, - double minData, double maxData, double minLimit, double maxLimit) -{ - double logMaxData = log10(maxData), logMinData = log10(minData); - double logMaxLimit = log10(maxLimit), logMinLimit = log10(minLimit); - double logLimitRange = logMaxLimit - logMinLimit; - double logScale = (x2 - x1)/(logMaxLimit - logMinLimit); - double minLabelSpacing = (fs->max_bounds).width * MIN_H_LABEL_SPACING; - double min, max, logMin, logMax, logRange, pixRange, minPix; - double powLabelValue, logPowLabelValue, powLabel1Value, logPowLabel1Value; - double labelValue, label1Value, labelLimit; - double powTicValue, logPowTicValue, logPowTic1Value; - double ticValue, tic1Value, ticLimit, ticX; - double minInterval, minPowInterval, powInterval, interval; - double ticInterval, scaledTicInterval, powTicInterval; - double scaledInterval, maxPowTics, maxTics; - int consumedSpace, innerSpace, endSpace, nSegs, nFSegs, maxSegs; - int multIndex, powMultIndex; - int maxPowLabels, labelY, labelLeft, labelRight, labelCenter, ticCount; - int ticLen, i, j, powTicsBetweenLabels, ticsBetweenLabels, factor; - XSegment *seg, *segs; - FloatSegment *fSeg, *fSegs; - - /* Spacing tics and labels for the entire data range gets very slow - when the plot is zoomed way in, and spacing it using only the visible - (limit) range makes labels and tics flash on and off durring panning. - The compromise is to calculate spacing using a range - 5 plot-widths on either side of the visible range of the plot */ - logMin = logMinLimit - logLimitRange * 5; - if (logMinData > logMin) { min = minData; logMin = logMinData; } - else min = pow(10., logMin); - logMax = logMaxLimit + logLimitRange * 5; - if (logMaxData < logMax) { max = maxData; logMax = logMaxData; } - else max = pow(10., logMax); - logRange = logMax - logMin; - pixRange = logRange * logScale; - minPix = x1 - (logMinLimit - logMin) * logScale; - - /* find the maximum number of tics that will fit across the whole axis */ - maxTics = pixRange/MIN_LOG_TIC_SPACING; - - /* begin the spacing of power-of-10 labels at the rounded factor of - 10 below where labels would be placed every MIN_LOG_TIC_SPACING */ - minPowInterval = pow(10., floor(log10(logRange/(double)maxTics) - 1.)); - if (minPowInterval < 1) - minPowInterval = 1; - - /* begin the spacing of the labels within powers of 10 at the interval - where MIN_LOG_TIC_SPACING would fit at the tightest point in the data */ - minInterval = calcMinLogInterval((int)pixRange, min, max, - MIN_LOG_TIC_SPACING, MIN_TIC_SPACING, &factor); - if (factor == 1) - minInterval /= 2; - else if (factor == 2) - minInterval /= 5; - - /* loop, increasing the interval between until all of the labels fit */ - for (powMultIndex=0; powMultIndex= x1) { - measureHCenteredFloat(fs, powLabelValue, labelCenter, - &labelLeft, &labelRight); - if (labelLeft < consumedSpace) - break; /* collision with previous label */ - consumedSpace = labelRight + minLabelSpacing; - } - /* temporarily create the next power of 10 label to define the - space for the labels within the power of 10 interval */ - labelCenter = - (int)(minPix + (logPowLabelValue+1.-logMin)*logScale); - measureHCenteredFloat(fs, powLabelValue*10., labelCenter, - &endSpace, &labelRight); - /* loop trying to place the labels within the power of 10 interval */ - while (multIndex 5.) - break; /* labels don't fit within powers of 10 */ - if (interval > 1.) { - /* if labels are at intervals of more than one, just put - labels at 2 and 5 */ - scaledInterval = 3. * powLabelValue; - labelLimit = 6. * powLabelValue; - label1Value = 2. * powLabelValue; - } else { - scaledInterval = interval * powLabelValue; - if (min > powLabelValue) - label1Value = rint(min/scaledInterval) * scaledInterval; - else - label1Value = powLabelValue + scaledInterval; - if (max < powLabelValue*10) - labelLimit = max; - else - labelLimit = powLabelValue*10 - scaledInterval/2; - } - labelValue = label1Value; - innerSpace = consumedSpace; - while (labelValue <= labelLimit) { - labelCenter = (int)(minPix + - (log10(labelValue)-logMin)*logScale); - measureHCenteredFloat(fs, labelValue, labelCenter, - &labelLeft, &labelRight); - if (labelLeft < innerSpace) - break; /* collision with previous label */ - innerSpace = labelRight + minLabelSpacing; - labelValue += scaledInterval; - } - if (labelValue > labelLimit && innerSpace < endSpace) - break; /* labels laid out successfully */ - multIndex++; - } - if (multIndex == NMULTIPLIERS) { - fprintf(stderr, "Couldn't lay out axis labels. Font problem?"); - return; - } - logPowLabelValue += powInterval; - powLabelValue = pow(10., logPowLabelValue); - } - /* exit loop if all of the labels were laid out successfully */ - if (powLabelValue > max) - break; - } - if (powMultIndex == NMULTIPLIERS) { - fprintf(stderr, "Couldn't lay out axis labels. Font problem?"); - return; - } - - /* draw the labels using interval and label1Value calculated above */ - labelY = y + HAxisHeight(fs); - maxPowLabels = (int)(logRange/powInterval + 1); - for (i=0; i<=maxPowLabels; i++) { - logPowLabelValue = logPowLabel1Value + powInterval*i; - powLabelValue = pow(10., logPowLabelValue); - labelCenter = (int)(minPix + (logPowLabelValue-logMin)*logScale); - if (labelCenter >= x1 && labelCenter <= x2) - drawHCenteredFloat(display, window, gc, fs, outDevice, - powLabelValue, labelCenter, labelY); - if (interval > 5.) - continue; - if (interval > 1.) { - /* if labels are at intervals of more than one, label at 2 and 5 */ - scaledInterval = 3. * powLabelValue; - labelLimit = 6. * powLabelValue; - label1Value = 2. * powLabelValue; - } else { - scaledInterval = interval * powLabelValue; - if (min > powLabelValue) - label1Value = rint(min/scaledInterval) * scaledInterval; - else - label1Value = powLabelValue + scaledInterval; - if (max < powLabelValue*10) - labelLimit = max; - else - labelLimit = powLabelValue*10 - scaledInterval/2; - } - labelValue = label1Value; - for (j=1; labelValue <= labelLimit; j++) { - labelCenter = (int)(minPix + - (log10(labelValue)-logMin)*logScale); - if (labelCenter >= x1 && labelCenter <= x2) - drawHCenteredFloat(display, window, gc, fs, outDevice, - labelValue, labelCenter, labelY); - labelValue = label1Value + j*scaledInterval; - } - } - - /* allocate enough memory for X segments to draw axis lines and - tics at minimum tic spacing: Maximum # of tics + last tic + - axis line + 0-2 arrows of 2 segments each */ - maxSegs = (x2 - x1)*10/* /MIN_LOG_TIC_SPACING */ + 10; - if (outDevice == X_SCREEN) { - segs = (XSegment *)XtMalloc(sizeof(XSegment) * maxSegs); - seg = segs; - } else { - segs = (XSegment *)XtMalloc(sizeof(XSegment) * 5); - seg = segs; - fSegs = (FloatSegment *)XtMalloc(sizeof(FloatSegment) * maxSegs); - fSeg = fSegs; - } - nSegs = 0; - nFSegs = 0; - - /* determine how far apart to draw the tics */ - powTicInterval = calcLinTicInterval(powInterval, logScale, powMultIndex % 3); - if (powTicInterval < 1) - powTicInterval = 1; - ticInterval = calcLogTicInterval((int)pixRange, interval, min, - max, multIndex % 3); - - /* draw the tics */ - logPowTic1Value = logPowLabel1Value; - powTicsBetweenLabels = (int)rint(powInterval/powTicInterval); - maxPowTics = logRange/powTicInterval + powTicsBetweenLabels + 2; - for (i=0; i<=maxPowTics; i++) { - logPowTicValue = logPowTic1Value + powTicInterval * i; - powTicValue = pow(10., logPowTicValue); - ticX = minPix + (logPowTicValue - logMin) * logScale; - if (ticX >= x1 && ticX <= x2) { - if (i % powTicsBetweenLabels == 0) - ticLen = LONG_TIC_LEN; - else if ((i*2) % powTicsBetweenLabels == 0) - ticLen = MED_TIC_LEN; - else - ticLen = SHORT_TIC_LEN; - if (outDevice == X_SCREEN) { - seg->x1=seg->x2=(int)ticX; seg->y1=y; seg->y2=y+ticLen; - seg++; nSegs++; - } else { - fSeg->x1=fSeg->x2=ticX; fSeg->y1=y; fSeg->y2=y+ticLen; - fSeg++; nFSegs++; - } - } - /* draw the tics within the power-of-10 intervals */ - if (ticInterval > 1.) - continue; - scaledTicInterval = ticInterval * powTicValue; - ticsBetweenLabels = interval/ticInterval; - ticLimit = pow(10., floor(logPowTicValue+1.)) - scaledTicInterval/2; - if (min > powTicValue) - tic1Value = floor(min/(scaledTicInterval*10)) * - scaledTicInterval*10 + scaledTicInterval; - else - tic1Value = powTicValue + scaledTicInterval; - ticValue = tic1Value; - for (j=1; ticValue < ticLimit; j++) { - ticValue = tic1Value + (j-1)*scaledTicInterval; - ticX = minPix + (log10(ticValue)-logMin)*logScale; - ticCount = (min<=powTicValue && ticInterval>=1.) ? j+1 : j; - if (ticX < x1) - continue; - if (ticX > x2) - break; - if (interval>1. && interval<=2. && (ticCount==2 || ticCount==5)) - ticLen = LONG_TIC_LEN; - else if (interval>1. && ticCount==5) - ticLen = MED_TIC_LEN; - else if (interval>1.) - ticLen = SHORT_TIC_LEN; - else if (ticCount % ticsBetweenLabels == 0) - ticLen = LONG_TIC_LEN; - else if ((ticCount*2) % ticsBetweenLabels == 0) - ticLen = MED_TIC_LEN; - else - ticLen = SHORT_TIC_LEN; - if (outDevice == X_SCREEN) { - seg->x1=seg->x2=(int)ticX; seg->y1=y; seg->y2=y+ticLen; - seg++; nSegs++; - } else { - fSeg->x1=fSeg->x2=ticX; fSeg->y1=y; fSeg->y2=y+ticLen; - fSeg++; nFSegs++; - } - } - } - - /* generate axis line and arrow heads to indicate data not shown */ - genHAxisLineSegs(&seg, &nSegs, x1, x2, y, True, - minData < minLimit, maxData > maxLimit); - - /* draw the axis and tic lines */ - if (outDevice == X_SCREEN) { - XDrawSegments(display, window, gc, segs, nSegs); - } else { /* PS_PRINTER */ - PSFloatDrawSegments(display, window, gc, fSegs, nFSegs); - PSDrawSegments(display, window, gc, segs, nSegs); - XtFree((char *)fSegs); - } - XtFree((char *)segs); -} - -static void drawDiscreteHAxis(Display *display, Drawable window, GC gc, - XFontStruct *fs, int outDevice, int y, int x1, int x2, double minData, - double maxData, double minLimit, double maxLimit, int nBins) -{ - double dataRange = maxData - minData; - double scale = (x2 - x1)/(maxLimit - minLimit); - int pixRange = dataRange * scale; - int minPix = x1 - (minLimit - minData) * scale; - double minLabelSpacing = (fs->max_bounds).width * MIN_H_LABEL_SPACING; - int consumedSpace; - double labelValue, increment; - int i, l, nLabels, mult, labelLeft, labelRight, labelCenter, labelY, nSegs; - int ticX, ticLen; - XSegment *seg, *segs; - - /* determine the number of labels that will fit by simulating drawing - them. Iterate first trying to label every bin edge, then every other - bin, then every 5th, every tenth, etc., until the labels fit. */ - for (i=0, mult=Multipliers[0]; i= minLimit && labelValue <= maxLimit) { - labelCenter = minPix + (labelValue - minData) * scale; - drawHCenteredFloat(display, window, gc, fs, outDevice, - labelValue, labelCenter, labelY); - } - } - - /* allocate memory for segments to draw axis lines and tics, 1 tic per - bin + last tic + axis line + 0-2 arrows of 2 segments each */ - segs = (XSegment *)XtMalloc(sizeof(XSegment) * (nBins + 10)); - seg = segs; nSegs = 0; - - /* generate the tic lines */ - for (i=0; i<=nBins; i++) { - ticX = minPix + (i * pixRange)/nBins; - if (ticX >= x1 && ticX <= x2) { - if (i % mult == 0) - ticLen = LONG_TIC_LEN; - else if ((i*2) % mult == 0) - ticLen = MED_TIC_LEN; - else - ticLen = SHORT_TIC_LEN; - seg->x1=seg->x2=ticX; seg->y1=y; seg->y2=y+ticLen; seg++; nSegs++; - } - } - - /* generate axis line and arrow heads to indicate data not shown */ - genHAxisLineSegs(&seg, &nSegs, x1, x2, y, True, - minData < minLimit, maxData > maxLimit); - - /* draw the axis and tic lines */ - if (outDevice == X_SCREEN) - XDrawSegments(display, window, gc, segs, nSegs); - else /* PS_PRINTER */ - PSDrawSegments(display, window, gc, segs, nSegs); - XtFree((char *) segs); -} - -/* -** RedrawHAxisArrows, RedrawVAxisArrows -** -** Arrows on the tips of the axes are used to indicate that data which is not -** shown exists beyond the edge of the plot. These arrows protrude into -** the area where the plot is drawn, so RedrawHAxisArrows and RedrawVAxisArrows -** are provided to fix up the arrows if plot data has overwritten them. -*/ -void RedrawHAxisArrows(Display *display, Drawable window, GC gc, - int y, int x1, int x2, double minData, double maxData, - double minLimit, double maxLimit) -{ - XSegment *seg, *segs; - int nSegs = 0; - - seg = segs = (XSegment *)XtMalloc(sizeof(XSegment) * 5); - genHAxisLineSegs(&seg, &nSegs, x1, x2, y, False, - minData < minLimit, maxData > maxLimit); - XDrawSegments(display, window, gc, segs, nSegs); - XtFree((char *) segs); -} -void RedrawVAxisArrows(Display *display, Drawable window, GC gc, - int x, int y11, int y2, double minData, double maxData, - double minLimit, double maxLimit) -{ - XSegment *seg, *segs; - int nSegs = 0; - - seg = segs = (XSegment *)XtMalloc(sizeof(XSegment) * 5); - genVAxisLineSegs(&seg, &nSegs, x, y11, y2, False, - maxData > maxLimit, minData < minLimit); - XDrawSegments(display, window, gc, segs, nSegs); - XtFree((char *) segs); -} - -/* Calculate the number of pixels to the left of the decimal point, given - a string containing a number, and an x font structure for measuring */ -static int calcDecimalOffset(char *labelStr, XFontStruct *fs) -{ - char *decimalStr; - - decimalStr = strchr(labelStr, '.'); - if (decimalStr == NULL) { - decimalStr = strchr(labelStr, 'e'); - if (decimalStr == NULL) - return 0; - } - return XTextWidth(fs, decimalStr, strlen(decimalStr)); -} - -/* Calculate interval (how far apart to draw in data coordinates) between - tics given interval between labels, scale, and whether the multiplier - used was a factor of 10, 2, or 5. Parameter factor==0: 10, - factor==1: 2, factor==2: 5 */ -static double calcLinTicInterval(double labelInterval, double scale, int factor) -{ - return calcTicInterval(labelInterval, MIN_TIC_SPACING/scale, factor); -} - -static double calcLogTicInterval(int pixRange, double labelInterval, double min, - double max, int factor) -{ - double minTicInterval; - int dummyFactor; - - minTicInterval = calcMinLogInterval(pixRange, min, max, - MIN_LOG_TIC_SPACING, MIN_TIC_SPACING, &dummyFactor); - return calcTicInterval(labelInterval, minTicInterval, factor); -} - -static double calcTicInterval(double labelInterval, double minTicInterval, - int factor) -{ - switch (factor) { - case 0: /* labels placed at factors of 10 */ - if (labelInterval/10 >= minTicInterval) - return labelInterval/10; - else if (labelInterval/2 >= minTicInterval) - return labelInterval/2; - else - return labelInterval; - case 1: /* labels placed at factors of 2 */ - if (labelInterval/2 >= minTicInterval) - return labelInterval/2; - else - return labelInterval; - case 2: /* labels placed at factors of 5 */ - if (labelInterval/5 >= minTicInterval) - return labelInterval/5; - else - return labelInterval; - } - - return 0.0 ; -} - -/* -** Calculate label spacing in data coordinates, return the spacing in -** interval, and return the step factor as the function value. The -** possible values are: 0: factor of 10, 1: factor of 2, 2: factor of 5. -*/ -static double calcLabelInterval(int pixRange, double dataRange, XFontStruct *fs, - int *factor) -{ - double interval, minInterval, maxTics; - int minLabelSpacing = fs->ascent * (1 + MIN_V_LABEL_SPACING); - int multIndex; - - /* find the maximum number of tics that will fit across the visible axis */ - maxTics = pixRange/(double)MIN_TIC_SPACING; - - /* begin with the rounded factor of 10 below where - labels would be placed every MIN_TIC_SPACING */ - minInterval = pow(10., floor(log10(dataRange/maxTics) - 1.)); - - /* loop, increasing the interval between labels until they all fit */ - for (multIndex=0; multIndexascent * (1 + MIN_V_LOG_LABEL_SPACING), - fs->ascent * (1 + MIN_V_LABEL_SPACING), factor); -} - -/* -** Calculate the minimum even (power of 2, 5, or 10) interval that will -** fit within one power of 10 between min and max. The minimum spacing -** is given in pixels for both the wide and the narrow ends of the range such -** that narrowSpacing and wideSpacing pixels will fit at the narrowly spaced -** maximum end of and widely spaced minimum end of one power of 10. -*/ -static double calcMinLogInterval(int pixRange, double min, double max, - double narrowSpacing, double wideSpacing, int *factor) -{ - double interval, minInterval, minPow, maxPow, scale; - double logNarrowSpacing, logWideSpacing; - int multIndex; - double logMin = log10(min); - double logMax = log10(max); - - /* find the minimum tic & label spacing in the log coordinate system */ - scale = (logMax-logMin) / pixRange; - logNarrowSpacing = narrowSpacing * scale; - logWideSpacing = wideSpacing * scale; - - /* normalize the range to values between 1 and 10 (one power of 10) */ - minPow = (int)floor(logMin); - maxPow = (int)ceil(logMax); - if (maxPow - minPow > 1) { - min = 1.; - max = 10.; - logMin = 0.; - logMax = 1.; - } else { - logMin -= minPow; - logMax -= minPow; - min = pow(10., logMin); - max = pow(10., logMax); - } - - /* measure that distance down from the maximum range to get the minimum - spacing in data coordinates for the closest objects in the range */ - minInterval = pow(10., logMax) - pow(10., logMax - logNarrowSpacing); - - /* round the interval size down to the nearest power of 10 */ - minInterval = pow(10., floor(log10(minInterval))); - - /* loop, increasing the interval between objects until they all fit */ - for (multIndex=0; multIndex= 10.) - break; - if (logMax - log10(max-interval) >= logNarrowSpacing && - log10(min+interval) - logMin >= logWideSpacing) - break; - } - - if (multIndex == NMULTIPLIERS) { - fprintf(stderr, "Couldn't lay out V axis labels. Font problem?"); - return 0.; - } - - *factor = multIndex % 3; - return interval; -} - -static void drawHCenteredFloat(Display *display, Drawable window, GC gc, - XFontStruct *fs, int outDevice, double value, int x, int y) -{ - char valueStr[16]; - int textWidth, strLen; - - sprintf(valueStr, "%g", value); - strLen = strlen(valueStr); - textWidth = XTextWidth(fs, valueStr, strLen); - if (outDevice == X_SCREEN) - XDrawString(display, window, gc, x-textWidth/2, y, valueStr, strLen); - else - PSDrawString(display, window, gc, fs, x, y, PS_CENTER, valueStr); -} - -static void measureHCenteredFloat(XFontStruct *fs, double value, - int x, int *left, int *right) -{ - char valueStr[16]; - int textWidth, strLen; - - sprintf(valueStr, "%g", value); - strLen = strlen(valueStr); - textWidth = XTextWidth(fs, valueStr, strLen); - *left = x - textWidth/2; - *right = x + textWidth/2; -} - -static void genHAxisLineSegs(XSegment **segPtr, int *segCount, int x1, int x2, - int y, int drawAxisLine, int drawLeftArrow, int drawRightArrow) -{ - XSegment * seg = *segPtr; - int nSegs = 0; - - /* generate the axis line */ - if (drawAxisLine) { - seg->x1 = x1; seg->x2 = x2; seg->y1 = seg->y2 = y; seg++; nSegs++; - } - - /* draw arrow heads to indicate data not shown */ - if (drawLeftArrow) { - seg->x1=x1; seg->x2=x1+6; seg->y1=y; seg->y2=y+2; seg++; nSegs++; - seg->x1=x1; seg->x2=x1+6; seg->y1=y; seg->y2=y-2; seg++; nSegs++; - } - if (drawRightArrow) { - seg->x1=x2; seg->x2=x2-6; seg->y1=y; seg->y2=y+2; seg++; nSegs++; - seg->x1=x2; seg->x2=x2-6; seg->y1=y; seg->y2=y-2; seg++; nSegs++; - } - - *segPtr = seg; - *segCount += nSegs; -} - -static void genVAxisLineSegs(XSegment **segPtr, int *segCount, int x, int y11, - int y2, int drawAxisLine, int drawTopArrow, int drawBottomArrow) -{ - XSegment * seg = *segPtr; - int nSegs = 0; - - /* generate the axis line */ - if (drawAxisLine) { - seg->x1 = seg->x2 = x; seg->y1 = y11; seg->y2 = y2; seg++; nSegs++; - } - - /* draw arrow heads to indicate data not shown */ - if (drawTopArrow) { - seg->y1=y11; seg->y2=y11+6; seg->x1=x; seg->x2=x+2; seg++; nSegs++; - seg->y1=y11; seg->y2=y11+6; seg->x1=x; seg->x2=x-2; seg++; nSegs++; - } - if (drawBottomArrow) { - seg->y1=y2; seg->y2=y2-6; seg->x1=x; seg->x2=x+2; seg++; nSegs++; - seg->y1=y2; seg->y2=y2-6; seg->x1=x; seg->x2=x-2; seg++; nSegs++; - } - - *segPtr = seg; - *segCount += nSegs; -} - -static void drawVCenteredFloat(Display *display, Drawable window, GC gc, - XFontStruct *fs, int outDevice, double value, - int x, int y, int maxDecimalOffset, XmString yAxisFormat ) -{ - char valueStr[40]; - int top, width, strLen, decimalOffset; - int temp ; - XtPointer str ; - -#if XmVERSION < 2 - XmStringContext context; - XmStringCharSet charset; - XmStringDirection direction; - Boolean separator = FALSE; - String text = NULL ; - - XmStringInitContext(&context,yAxisFormat); - XmStringGetNextSegment(context,&text,&charset, &direction,&separator) ; - str = (char *)text ; -#else - str = XmStringUnparse(yAxisFormat, NULL, 0, XmCHARSET_TEXT, NULL, 0, XmOUTPUT_ALL); -#endif - sprintf(valueStr, (char *)str, value); - XtFree(str) ; - strLen = strlen(valueStr); - top = y + fs->ascent/2; - width = XTextWidth(fs, valueStr, strLen); - decimalOffset = calcDecimalOffset(valueStr, fs); - /* A.Lin - start labels at least 5 pixels into the graph */ - temp = x - width - maxDecimalOffset + decimalOffset ; - temp = (temp > 5) ? temp : 5 ; - if (outDevice == X_SCREEN) - XDrawString(display, window, gc, temp, top, valueStr, strLen); - else - PSDrawString(display, window, gc, fs, x - width - maxDecimalOffset - + decimalOffset, top, PS_LEFT, valueStr); -} diff --git a/trick_source/data_products/fermi-ware/drawAxes.h b/trick_source/data_products/fermi-ware/drawAxes.h deleted file mode 100644 index 606d5f5e..00000000 --- a/trick_source/data_products/fermi-ware/drawAxes.h +++ /dev/null @@ -1,46 +0,0 @@ -/******************************************************************************* -* * -* drawAxes.h -- Generic axis drawing routines for 2D graphs & plots * -* * -* Copyright (c) 1991 Universities Research Association, Inc. * -* All rights reserved. * -* * -* This material resulted from work developed under a Government Contract and * -* is subject to the following license: The Government retains a paid-up, * -* nonexclusive, irrevocable worldwide license to reproduce, prepare derivative * -* works, perform publicly and display publicly by or for the Government, * -* including the right to distribute to other Government contractors. Neither * -* the United States nor the United States Department of Energy, nor any of * -* their employees, makes any warrenty, express or implied, or assumes any * -* legal liability or responsibility for the accuracy, completeness, or * -* usefulness of any information, apparatus, product, or process disclosed, or * -* represents that its use would not infringe privately owned rights. * -* * -* Fermilab Nirvana GUI Library * -* May 28, 1992 * -* * -* Written by Mark Edel * -* * -*******************************************************************************/ -int HAxisHeight(XFontStruct *fs); -int HAxisEndClearance(XFontStruct *fs); -int VAxisWidth(XFontStruct *fs, XmString format); -int VAxisEndClearance(XFontStruct *fs); - -void DrawHorizontalAxis(Display *display, Drawable window, GC gc, - XFontStruct *fs, int outDevice, int y, int y2, int x1, int x2, - double minData, double maxData, double minLimit, double maxLimit, - int logScaling, int nBins, - int showGrid, Pixel gridColor, Pixel printGridColor ); - -void DrawVerticalAxis(Display *display, Drawable window, GC gc, XFontStruct *fs, - int outDevice, int x, int x2, int y1, int y2, double minData, double maxData, - double minLimit, double maxLimit, int logScaling, XmString yAxisFormat , - int showGrid, Pixel gridColor, Pixel printGridColor ); - -void RedrawHAxisArrows(Display *display, Drawable window, GC gc, - int y, int x1, int x2, double minData, double maxData, - double minLimit, double maxLimit); -void RedrawVAxisArrows(Display *display, Drawable window, GC gc, - int x, int y1, int y2, double minData, double maxData, - double minLimit, double maxLimit); diff --git a/trick_source/data_products/fermi-ware/makefile b/trick_source/data_products/fermi-ware/makefile deleted file mode 100644 index eb0fdb9e..00000000 --- a/trick_source/data_products/fermi-ware/makefile +++ /dev/null @@ -1,62 +0,0 @@ -include ${TRICK_HOME}/share/trick/makefiles/Makefile.common - -CC = cc -OBJ_DIR = object_${TRICK_HOST_CPU} -DP_CFLAGS = -g -Wall -I/usr/X11R6/include -I/usr/X11/include -I${TRICK_HOME}/trick_source - -ifeq ($(TRICK_HOST_TYPE), Darwin) - DP_CFLAGS += -I/sw/include -endif -ifeq ($(TRICK_DP_FORCE_32BIT), 1) - DP_CFLAGS += -m32 -endif - -OBJECTS= \ - ${OBJ_DIR}/XY.o \ - ${OBJ_DIR}/drawAxes.o \ - ${OBJ_DIR}/dragAxes.o \ - ${OBJ_DIR}/psUtils.o - -LIBDIR = object_${TRICK_HOST_CPU} -LIBNAME = libfermi.a - -all: $(LIBDIR)/$(LIBNAME) - @ echo "Library up to date" - -$(OBJ_DIR): - @ mkdir -p $(OBJ_DIR) - @ echo "Created $(OBJ_DIR)" - -$(LIBDIR): - - mkdir -p $(LIBDIR) - - -$(LIBDIR)/$(LIBNAME): $(OBJECTS) | $(LIBDIR) - ar cr $(LIBDIR)/$(LIBNAME) $? - -# For XY.c, disable "implicit declaration of function" warnings -# generated due to it's use of obsolete Motif functions that have no -# prototypes in Motif 2.x packages. Yes, this is a naughty thing to -# do. - -${OBJ_DIR}/XY.o : XY.c | $(OBJ_DIR) - $(CC) $(DP_CFLAGS) -c ${@F:.o=.c} -o $@ - -${OBJ_DIR}/drawAxes.o : drawAxes.c | $(OBJ_DIR) - $(CC) $(DP_CFLAGS) -c ${@F:.o=.c} -o $@ - -${OBJ_DIR}/dragAxes.o : dragAxes.c | $(OBJ_DIR) - $(CC) $(DP_CFLAGS) -c ${@F:.o=.c} -o $@ - -${OBJ_DIR}/psUtils.o : psUtils.c | $(OBJ_DIR) - $(CC) $(DP_CFLAGS) -c ${@F:.o=.c} -o $@ - -clean: - rm -rf $(LIB) $(OBJ_DIR) - @ echo "Object files successfully removed" - -real_clean: clean - -$(MODEL_BIN_DIR)/XY.o: psUtils.h drawAxes.h dragAxes.h XYP.h XY.h -$(MODEL_BIN_DIR)/dragAxes.o: dragAxes.h -$(MODEL_BIN_DIR)/drawAxes.o: psUtils.h drawAxes.h diff --git a/trick_source/data_products/fermi-ware/psUtils.c b/trick_source/data_products/fermi-ware/psUtils.c deleted file mode 100644 index 3d2446e0..00000000 --- a/trick_source/data_products/fermi-ware/psUtils.c +++ /dev/null @@ -1,864 +0,0 @@ -/******************************************************************************* -* * -* psUtils.c -- PostScript file output routines * -* * -* Copyright (c) 1991 Universities Research Association, Inc. * -* All rights reserved. * -* * -* This material resulted from work developed under a Government Contract and * -* is subject to the following license: The Government retains a paid-up, * -* nonexclusive, irrevocable worldwide license to reproduce, prepare derivative * -* works, perform publicly and display publicly by or for the Government, * -* including the right to distribute to other Government contractors. Neither * -* the United States nor the United States Department of Energy, nor any of * -* their employees, makes any warrenty, express or implied, or assumes any * -* legal liability or responsibility for the accuracy, completeness, or * -* usefulness of any information, apparatus, product, or process disclosed, or * -* represents that its use would not infringe privately owned rights. * -* * -* Fermilab Nirvana GUI Library * -* April 16, 1992 * -* * -* Written by Arnulfo Zepeda-Navratil * -* Centro de Investigacion y Estudio Avanzados ( CINVESTAV ) * -* Mexico * -* * -* With some portions from psFiles.c by Sanza T. Kazadi, Fermilab * -* * -* June 1994 : Upgrade to Encapsulated Postscript, by P. Lebrun * -* Include also a routine to draw rectangles * -* * -*******************************************************************************/ - -#include -#include /* access */ -#include -#include -#include -#include "psUtils.h" - -static void echPS(char *str, int siz, int posx, int posy, int anchor, - char *fontname, double red, double green, double blue); -static void setXGCLineParams(Display *display, GC gc); -static void getXParms(Display *display, GC gc, - unsigned short *red_ptr, unsigned short *green_ptr, - unsigned short *blue_ptr, double *lineWidth); -static XFontStruct *getFontStruct(XmFontList font); - -/* Parameters of the current open file */ -static int PSWidth = 0; -static int PSHeight = 0; -static FILE *PSFile; - -/* Maximum color component value in X Windows */ -#define COLOR_FACTOR 65535.0 - -/* Amount of space to leave on the edge of the printer page in 72nds of an - inch. If this is too big, part of the page will be wasted, too small, - and some (espescially color) printers will clip off part of the plot */ -#define PAGE_MARGIN 18 - -/* Coordinate conversion if necessary is done here */ -#define x_X2PS(x) (x) -#define y_X2PS(y) (PSHeight?PSHeight-y:(y)) - -/* -** Open a text file for one page of PostScript output, append text if -** already created. On error, return a NULL pointer. This routine -** also sets up the coordinate system and clipping for later output routines -*/ -FILE *OpenPS(char fname[], int width, int height) -{ - time_t tt; - PSFile = fopen(fname,"w"); - if (PSFile == NULL) - return NULL; - fprintf(PSFile, "%%!PS-Adobe-3.0\n"); - fprintf(PSFile, "%%%%BoundingBox: %d %d %d %d \n", PAGE_MARGIN, - PAGE_MARGIN, width*72/75 + PAGE_MARGIN, height*72/75 + PAGE_MARGIN); - fprintf(PSFile, "%%%%Title: %s \n", fname); - time(&tt); - fprintf(PSFile, "%%%%CreationDate: %s \n", ctime(&tt)); - - /* Set up the page margin. This is essential since most PostScript - printers can't print all of the way to the edge of the page. For - encapsulated PostScript, we aren't allowed to use initclip to find - out the real boundaries of the page, so this guess must suffice */ - fprintf(PSFile, "%d %d translate\n", PAGE_MARGIN, PAGE_MARGIN); - - /* Scale coordinates to 75 dpi rather than 72 because most X screens - are closer to 75, and because being an even multiple of 300, simple - line thicknesses like 1.0 and .5 will be more uniform */ - fprintf(PSFile, "72 75 div dup scale\n"); - - /* Define PostScript procedures for drawing dots and line segments: - d draws a dot using x and y coordinates from the stack, l draws - a line between arguments x1 y1 x2 y2 from the stack, rect draws - a rectangle, fillrect fills a rectangle */ - fprintf(PSFile, "%% Draw a dot. Args are x, y\n\ -/d {\n\ -currentlinewidth 2 div sub moveto\n\ -0 currentlinewidth rlineto stroke\n\ -} def\n\ -%% Draw a line. Args are x1, y1, x2, y2\n\ -/l {\n\ -moveto lineto stroke\n\ -} def\n\ -%% Draw a rectangle. Args are width, height, bottom, left\n\ -/rect {\n\ -gsave\n\ -translate\n\ -matrix currentmatrix\n\ -3 1 roll\n\ -scale\n\ -newpath\n\ -0 0 moveto\n\ -0 1 lineto\n\ -1 1 lineto\n\ -1 0 lineto\n\ -closepath\n\ -setmatrix\n\ -stroke\n\ -grestore\n\ -} def\n\ -%% Draw a filled rectangle. Args are width, height, bottom, left\n\ -/fillrect {\n\ -gsave\n\ -translate\n\ -scale\n\ -newpath\n\ -0 0 moveto\n\ -0 1 lineto\n\ -1 1 lineto\n\ -1 0 lineto\n\ -closepath\n\ -fill\n\ -grestore\n\ -} def\n\ -%% Draw an arc. Args are: x, y, radius, angle1, angle2\n\ -/xarc {\n\ -newpath\n\ -arc\n\ -stroke\n\ -} def\n\ -%% Draw a filled arc. Args are: x, y, radius, angle1, angle2\n\ -/fillarc {\n\ -newpath\n\ -arc\n\ -fill\n\ -} def\n"); - - /* Clip to the width and height of the window on the screen */ - fprintf(PSFile, "0 0 moveto\n"); - fprintf(PSFile, "%d 0 lineto\n", width); - fprintf(PSFile, "%d %d lineto\n", width, height); - fprintf(PSFile, "0 %d lineto\n", height); - fprintf(PSFile, "closepath clip\n"); - fprintf(PSFile, "newpath\n"); - - /* save the width and height */ - PSWidth = width; - PSHeight = height; - - return(PSFile); -} - -/* - * JBF - This routine copied from OpenPS and modified. - * -** Open a text file for one page of PostScript output, append text if -** already created and if desired. On error, return a NULL pointer. -** This routine also sets up the coordinate system for later output routines. -*/ -FILE *OpenPSNoClip(int landscape , char fname[], Boolean DestroyOldFile, int width, int height) -{ - time_t tt; - Boolean write_header_flag; - - /* - * Does the user wish to append to a file, if it already exists ? - * Does the file already exist ? - */ - if ((DestroyOldFile == False) && (access(fname,F_OK) == 0)) - { - /* - * Append to an existing file. - */ - PSFile = fopen(fname,"a"); - if (PSFile == NULL) - return NULL; - - fseek (PSFile, 0L, SEEK_END); - - if (ftell(PSFile) == 0l) - write_header_flag = True; - else - write_header_flag = False; - - } - else - { - /* - * Create a new file. - */ - PSFile = fopen(fname,"w"); - if (PSFile == NULL) - return NULL; - - write_header_flag = True; - } - - if (write_header_flag == True) - { - - fprintf(PSFile, "%%!PS-Adobe-3.0\n"); - /* - fprintf(PSFile, "%%%%BoundingBox: %d %d %d %d \n", PAGE_MARGIN, - PAGE_MARGIN, width*72/75 + PAGE_MARGIN, height*72/75 + PAGE_MARGIN); - */ - fprintf(PSFile, "%%%%Title: %s \n", fname); - time(&tt); - fprintf(PSFile, "%%%%CreationDate: %s \n", ctime(&tt)); - - /* Set up the page margin. This is essential since most PostScript - printers can't print all of the way to the edge of the page. For - encapsulated PostScript, we aren't allowed to use initclip to find - out the real boundaries of the page, so this guess must suffice */ - if ( landscape ) { - fprintf(PSFile, "90 rotate 0 -612 translate\n"); - } - fprintf(PSFile, "%d %d translate\n", PAGE_MARGIN, PAGE_MARGIN); - - /* Scale coordinates to 75 dpi rather than 72 because most X screens - are closer to 75, and because being an even multiple of 300, simple - line thicknesses like 1.0 and .5 will be more uniform */ - fprintf(PSFile, "72 75 div dup scale\n"); - - /* Define PostScript procedures for drawing dots and line segments: - d draws a dot using x and y coordinates from the stack, l draws - a line between arguments x1 y1 x2 y2 from the stack, rect draws - a rectangle, fillrect fills a rectangle */ - fprintf(PSFile, "%% Draw a dot. Args are x, y\n\ -/d {\n\ -currentlinewidth 2 div sub moveto\n\ -0 currentlinewidth rlineto stroke\n\ -} def\n\ -%% Draw a line. Args are x1, y1, x2, y2\n\ -/l {\n\ -moveto lineto stroke\n\ -} def\n\ -%% Draw a rectangle. Args are width, height, bottom, left\n\ -/rect {\n\ -gsave\n\ -translate\n\ -matrix currentmatrix\n\ -3 1 roll\n\ -scale\n\ -newpath\n\ -0 0 moveto\n\ -0 1 lineto\n\ -1 1 lineto\n\ -1 0 lineto\n\ -closepath\n\ -setmatrix\n\ -stroke\n\ -grestore\n\ -} def\n\ -%% Draw a filled rectangle. Args are width, height, bottom, left\n\ -/fillrect {\n\ -gsave\n\ -translate\n\ -scale\n\ -newpath\n\ -0 0 moveto\n\ -0 1 lineto\n\ -1 1 lineto\n\ -1 0 lineto\n\ -closepath\n\ -fill\n\ -grestore\n\ -} def\n\ -%% Draw an arc. Args are: x, y, radius, angle1, angle2\n\ -/xarc {\n\ -newpath\n\ -arc\n\ -stroke\n\ -} def\n\ -%% Draw a filled arc. Args are: x, y, radius, angle1, angle2\n\ -/fillarc {\n\ -newpath\n\ -arc\n\ -fill\n\ -} def\n"); - - } - - /* save the width and height */ - PSWidth = width; - PSHeight = height; - - return(PSFile); -} - -/* -** End writing to a PostScript file -*/ -void EndPS(void) -{ - fprintf(PSFile, "showpage grestore\n"); - fclose(PSFile); -} - -/* -** Draw a continuous connected line from an array of X XPoint structures -** to the PostScript file -*/ -void PSDrawLines(Display *display, Drawable w __attribute__ ((unused)), GC gc, - XPoint *points, int nPoints, int mode) -{ - int i; - XPoint *point; - - if (mode != CoordModeOrigin) { - fprintf(stderr, "PSDrawLines only does CoordModeOrigin (so far)\n"); - return; - } - - /* set line drawing parameters from contents of X graphics context */ - setXGCLineParams(display, gc); - - /* generate PostScript calls to the line drawing procedure l defined - in OpenPS above to draw each of the segments in the array */ - fprintf(PSFile, "%d %d moveto\n", x_X2PS(points->x), y_X2PS(points->y)); - for(i=1, point= &points[1]; ix), y_X2PS(point->y)); - fprintf(PSFile, "stroke\n"); -} - -/* -** Draw colored line segments from an array of X XSegment structures -** to the PostScript file -*/ -void PSDrawSegments(Display *display, Drawable w __attribute__ ((unused)), GC gc, - XSegment *segment, int nSegments) -{ - int j; - - /* set line drawing parameters from contents of X graphics context */ - setXGCLineParams(display, gc); - - /* generate PostScript calls to the line drawing procedure l defined - in OpenPS above to draw each of the segments in the array */ - for(j=0; jx1), y_X2PS(segment->y1), - x_X2PS(segment->x2), y_X2PS(segment->y2)); -} - -void PSDrawLine(Display *display, Drawable w, GC gc, int x1, int y1, - int x2, int y2) -{ - XSegment seg; - - seg.x1 = x1; seg.x2 = x2; seg.y1 = y1; seg.y2 = y2; - PSDrawSegments(display, w, gc, &seg, 1); -} - -/* -** Draw colored line segments from a floating point equivalent of the -** XSegment data structure to the PostScript File. The coordinate system -** is still assumed to be set up to be equivalent to X coordinate system, -** the floating point values just allow lines to be positioned at a greater -** precision within the 72 dpi grid of the screen coordinate system. -*/ -void PSFloatDrawSegments(Display *display, Drawable w __attribute__ ((unused)), GC gc, - FloatSegment *segment, int nSegments) -{ - int j; - - /* set line drawing parameters from contents of X graphics context */ - setXGCLineParams(display, gc); - - /* generate PostScript calls to the line drawing procedure l defined - in OpenPS above to draw each of the segments in the array */ - for(j=0; jx1), y_X2PS(segment->y1), - x_X2PS(segment->x2), y_X2PS(segment->y2)); -} - -/* -** Draw a continuous connected line from a floating point equivalent of the -** XPoint data structure to the PostScript File. The coordinate system -** is still assumed to be set up to be equivalent to X coordinate system, -** the floating point values just allow lines to be positioned at a greater -** precision within the 72 dpi grid of the screen coordinate system. -*/ -void PSFloatDrawLines(Display *display, Drawable w __attribute__ ((unused)), GC gc, - FloatPoint *points, int nPoints) -{ - int i; - FloatPoint *point; - - /* set line drawing parameters from contents of X graphics context */ - setXGCLineParams(display, gc); - - /* generate PostScript calls to the line drawing procedure l defined - in OpenPS above to draw each of the segments in the array */ - fprintf(PSFile, "%g %g moveto\n", x_X2PS(points->x), y_X2PS(points->y)); - for(i=1, point= &points[1]; ix), y_X2PS(point->y)); - fprintf(PSFile, "stroke\n"); -} - -/* -** Draw colored points from an X XPoint structure to the PostScript file -*/ -void PSDrawPoints(Display *display, Drawable w __attribute__ ((unused)), GC gc, - XPoint *point, int npoints, int mode __attribute__ ((unused))) -{ - int j; - - /* Set line drawing parameters from contents of X graphics context */ - setXGCLineParams(display, gc); - - /* generate PostScript calls to the line drawing procedure l defined - in OpenPS above to draw each of the segments in the array */ - for(j=0; jx), y_X2PS(point->y)); -} - -/* -** Display a colored Motif compound string in Times Roman at a point size -** one point smaller than the default font of the fontlist specified. -** Parameters are the same as XmStringDraw, except minus layout direction -** and clipping. The routine can't yet handle multiline strings, -** clipping, or right-to-left character sets. -*/ -void PSDrawXmString(Display *display, Drawable w, XmFontList font, XmString msg, - GC gc, int x, int y, int width, int alignment) -{ - char *ansiMsg; - XFontStruct *fs = getFontStruct(font); - int adjX, adjY, anchor; - - /* Calculate revised coordinates and anchor mode for drawing the string, - using the parameters in the form required by XmStringDraw */ - adjY = y + fs->ascent; /* change y to top left corner of string */ - if (alignment == XmALIGNMENT_BEGINNING) { - adjX = x; - anchor = PS_LEFT; - } else if (alignment == XmALIGNMENT_CENTER) { - adjX = x + width/2; - anchor = PS_CENTER; - } else /* XmALIGNMENT_END */ { - adjX = x + width; - anchor = PS_RIGHT; - } - - /* Convert the string to a C style stle string and call PSDrawString */ - XmStringGetLtoR(msg, XmSTRING_DEFAULT_CHARSET, &ansiMsg); - PSDrawString(display, w, gc, fs, adjX, adjY, anchor, ansiMsg); - XtFree(ansiMsg); -} - -/* -** Display a colored string in Times Roman at a point size -** one point smaller than the default font specified in fs -*/ -void PSDrawString(Display *display, Drawable w __attribute__ ((unused)), GC gc, XFontStruct *fs, - int x, int y, int anchor, char *msg) -{ - double lw; - unsigned short red, green, blue; - - getXParms(display, gc, &red, &green, &blue, &lw); - - echPS(msg, fs->ascent + fs->descent - 2, x_X2PS(x), y_X2PS(y), - anchor, "Times-Roman", - (float)red / COLOR_FACTOR, - (float)green / COLOR_FACTOR, - (float)blue / COLOR_FACTOR); -} - -#ifdef notdef /* paul's original */ -/* -** Draw colored rectangles from an X XRectangle structure -** to the PostScript file -*/ -void PSDrawRectangles(Display *display, Drawable w, GC gc, - XRectangle *rect, int nrects, int mode) -{ - int j; - - /* Set line drawing parameters from contents of X graphics context */ - setXGCLineParams(display, gc); - - /* generate PostScript calls to the box drawing procedure defined - here. - Note : we rely here on a non-rescaling version of X2PS */ - fprintf(PSFile,"/box{newpath \n"); - fprintf(PSFile,"0 0 moveto \n"); - fprintf(PSFile,"0 1 lineto \n"); - fprintf(PSFile,"1 1 lineto \n"); - fprintf(PSFile,"1 0 lineto \n"); - fprintf(PSFile,"closepath \n"); - fprintf(PSFile,"}def \n"); - - for(j=0; jx), - (y_X2PS(rect->y) - rect->height)); - fprintf(PSFile,"%d %d scale\n",rect->width, rect->height); - if (mode ==0) - fprintf(PSFile,"box \n"); - else - fprintf(PSFile,"box fill \n"); - fprintf(PSFile,"grestore \n"); - -/* Code for Postscript Level 2 - if (mode == 0) - fprintf(PSFile, "%d %d %d %d rectstroke\n", - x_X2PS(rect->x), y_X2PS(rect->y), rect->width, rect->height); - - else - fprintf(PSFile, "%d %d %d %d rectfill\n", - x_X2PS(rect->x), y_X2PS(rect->y), rect->width, rect->height); - */ - - } -} -#endif -/* -** Draw rectangles from an array of X XRectangle structures -*/ -void PSDrawRectangles(Display *display, Drawable w __attribute__ ((unused)), GC gc, - XRectangle *rects, int nRects) -{ - int j; - XRectangle *rect; - - /* Set line drawing parameters from contents of X graphics context */ - setXGCLineParams(display, gc); - - for(j=0, rect=rects; jwidth, rect->height, - x_X2PS(rect->x), y_X2PS(rect->y) - rect->height); -} - -/* -** Draw filled rectangles from an array of X XRectangle structures -*/ -void PSFillRectangles(Display *display, Drawable w __attribute__ ((unused)), GC gc, - XRectangle *rects, int nRects) -{ - int j; - XRectangle *rect; - - /* Set line drawing parameters from contents of X graphics context */ - setXGCLineParams(display, gc); - - for(j=0, rect=rects; jwidth, rect->height, - x_X2PS(rect->x), y_X2PS(rect->y) - rect->height); -} - -/* -** Draw arcs from an array of X XArc structures -*/ -void PSDrawArcs(Display *display, Drawable w __attribute__ ((unused)), GC gc, - XArc *arcs, int nArcs) -{ - int j; - XArc *arc; - - /* Set line drawing parameters from contents of X graphics context */ - setXGCLineParams(display, gc); - - for(j=0, arc=arcs; jwidth != arc->height) { - fprintf(stderr, "PSDrawArcs doesn't yet support eliptical arcs\n"); - return; - } - fprintf(PSFile,"%d %d %d %d %d xarc\n", x_X2PS(arc->x + arc->width/2), - y_X2PS(arc->y - arc->height/2), arc->width/2, arc->angle1/64, - arc->angle2/64); - } -} - -/* -** Draw filled arcs from an array of X XArc structures -*/ -void PSFillArcs(Display *display, Drawable w __attribute__ ((unused)), GC gc, - XArc *arcs, int nArcs) -{ - int j; - XArc *arc; - - /* Set line drawing parameters from contents of X graphics context */ - setXGCLineParams(display, gc); - - for(j=0, arc=arcs; jwidth != arc->height) { - fprintf(stderr, "PSDrawArcs doesn't yet support eliptical arcs\n"); - return; - } - fprintf(PSFile,"%d %d %d %d %d fillarc\n", - x_X2PS(arc->x + arc->width/2), y_X2PS(arc->y - arc->height/2), - arc->width/2, arc->angle1/64, arc->angle2/64); - } -} - -/* -** draw an image -*/ -void PSDrawImage( - Display *display, - Drawable w __attribute__ ((unused)), - GC gc, - int scanLength, int scanLines, int bitsPerSample, int x, int y, - unsigned char *bitmap ) -{ - int i, disp_x, disp_y ; - - /* set image drawing parameters from the contents of X graphics context */ - setXGCLineParams(display, gc); - - /* translate the origin to drawing position */ - disp_x = x; - disp_y = y ; - /* draw image */ - fprintf(PSFile, "%d %d translate\n", x_X2PS(disp_x), y_X2PS(disp_y)); - fprintf(PSFile, "%d %d %d [%d 0 0 %d 0 0] {<", scanLength, - scanLines, bitsPerSample, scanLength, scanLines); - for (i = 0; i < scanLength; i++) { - fprintf(PSFile, "%02x", bitmap[i]); - } - fprintf(PSFile, ">} image\n"); - - /* restore origin */ - fprintf(PSFile, "%d %d translate\n", -x_X2PS(disp_x), -y_X2PS(disp_y)); -} - - -/* -** Draw dashed (or solid) line segments (dashed lines can't be drawn by -** PSDrawSegments because X does not provide access to the complete dash -** information in the gc -*/ -void PSDrawDashedSegments(Display *display, Drawable w, GC gc, - XSegment *segments, int nSegments, char *dashList, int dashOffset) -{ - int i, len; - XGCValues valuesRet; - - /* if dashed lines are turned off in the GC, draw solid */ - XGetGCValues(display, gc, GCLineStyle, &valuesRet); - if (valuesRet.line_style == LineSolid) { - PSDrawSegments(display, w, gc, segments, nSegments); - return; - } - - /* transform and set dash list */ - len = strlen(dashList); - if (len != 0) { - fprintf(PSFile, "["); - for (i = 0; i < len - 1; i++) - fprintf(PSFile, "%3d ", (int)dashList[i]); - fprintf(PSFile, "%3d] %d setdash\n", (int)(dashList[len-1]), - dashOffset); - } - - /* draw the segments */ - PSDrawSegments(display, w, gc, segments, nSegments); - - /* set the line style back to solid line */ - fprintf(PSFile, "[] 0 setdash\n"); -} - -/* -** Draw continuous dashed lines from the floating point equivalent of the -** XPoint data structure -*/ -void PSFloatDrawDashedLines(Display *display, Drawable w, GC gc, - FloatPoint *points, int nPoints, char *dashList, int dashOffset) -{ - int i, len; - XGCValues valuesRet; - - /* if dashed lines are turned off in the GC, draw solid */ - XGetGCValues(display, gc, GCLineStyle, &valuesRet); - if (valuesRet.line_style == LineSolid) { - PSFloatDrawLines(display, w, gc, points, nPoints); - return; - } - - /* transform and set dash list */ - len = strlen(dashList); - if (len != 0) { - fprintf(PSFile, "["); - for (i = 0; i < len - 1; i++) - fprintf(PSFile, "%3d ", (int)dashList[i]); - fprintf(PSFile, "%3d] %d setdash\n", (int)(dashList[len-1]), - dashOffset); - } - - /* draw the lines */ - PSFloatDrawLines(display, w, gc, points, nPoints); - - /* set the line style back to solid line */ - fprintf(PSFile, "[] 0 setdash\n"); -} - -/* -** Draw a dashed line (dashed lines can't be drawn by PSDrawLine because -** X does not give access to the complete dash information in the gc -*/ -void PSDrawDashedLine(Display *display, Drawable w, GC gc, int x1, int y1, - int x2, int y2, char *dashList, int dashOffset) -{ - XSegment seg; - - seg.x1 = x1; seg.x2 = x2; seg.y1 = y1; seg.y2 = y2; - PSDrawDashedSegments(display, w, gc, &seg, 1, dashList, dashOffset); -} - -/* -** Change the current clip rectangle -*/ -void PSSetClipRectangle(int x1, int y1, int x2, int y2) -{ - fprintf(PSFile, "newpath\n"); - fprintf(PSFile, "%d %d moveto\n", x_X2PS(x1), y_X2PS(y1)); - fprintf(PSFile, "%d %d lineto\n", x_X2PS(x2), y_X2PS(y1)); - fprintf(PSFile, "%d %d lineto\n", x_X2PS(x2), y_X2PS(y2)); - fprintf(PSFile, "%d %d lineto\n", x_X2PS(x1), y_X2PS(y2)); - fprintf(PSFile, " %d %d lineto\n", x_X2PS(x1), y_X2PS(y1)); - fprintf(PSFile, "closepath clip newpath\n"); -} - -/* -** Output colored text -*/ -static void echPS(char *str, int siz, int posx, int posy, int anchor, - char *fontname, double red, double green, double blue) -{ - fprintf(PSFile, "%.2f %.2f %.2f setrgbcolor ", red, green, blue); - fprintf(PSFile, "/%s findfont %04d scalefont setfont\n", fontname, siz); - if (anchor == PS_LEFT) - fprintf(PSFile, "%d %d moveto\n", posx, posy); - else if (anchor == PS_CENTER) - fprintf(PSFile, "(%s) stringwidth pop 2 div neg %d add %d moveto\n", - str, posx, posy); - else if (anchor == PS_RIGHT) - fprintf(PSFile, "(%s) stringwidth pop neg %d add %d moveto\n", - str, posx, posy); - else { - fprintf(stderr, "Internal error: bad anchor value in echPS\n"); - return; - } - fprintf(PSFile, "(%s) show\n", str); -} - -/* -** Set a subset of GC parameters relating to line appearance for subsequent -** drawing operations -*/ -static void setXGCLineParams(Display *display, GC gc) -{ - double lineWidth; - unsigned short red, green, blue; - - /* Set line drawing parameters from contents of X graphics context */ - getXParms(display, gc, &red, &green, &blue, &lineWidth); - fprintf(PSFile, "%.2f %.2f %.2f setrgbcolor ", (float)red/COLOR_FACTOR, - (float)green/COLOR_FACTOR, (float)blue/COLOR_FACTOR); - fprintf(PSFile, "%.2f setlinewidth\n", lineWidth); -} - -/* -** Obtain X Window related drawing parameters -** and massage them for PostScript printers -*/ -static void getXParms(Display *display, GC gc, unsigned short *red_ptr, - unsigned short *green_ptr, unsigned short *blue_ptr, double *lineWidth) -{ - XGCValues valuesRet; - XColor ret_color; - - XGetGCValues(display, gc, GCForeground | GCLineWidth, &valuesRet); - /*XGetWindowAttributes(display, w, window_attributes);*/ - ret_color.pixel = valuesRet.foreground; - ret_color.flags = DoRed | DoGreen | DoBlue ; - XQueryColor(display, /*window_attributes.colormap*/ /* Get color rgb */ - DefaultColormap(display,0), &ret_color); - *red_ptr = ret_color.red; - *green_ptr = ret_color.green; - *blue_ptr = ret_color.blue; - *lineWidth = valuesRet.line_width == 0 ? 0.5 : valuesRet.line_width; -} - -/* -** Get the XFontStruct that corresponds to the default (first) font in -** a Motif font list. Since Motif stores this, it saves us from storing -** it or querying it from the X server. -*/ -#if ((XmVERSION >= 1) && (XmREVISION >= 2)) -/* - * JBF - updated for motif 1.2 - * XmFontListGetNextFont is obsolete in Motif 1.2 - */ - -/* Motif 1.2 or newer */ -static XFontStruct *getFontStruct(XmFontList font) -{ - XFontStruct *fs; - XmFontContext context; - XmFontListEntry entry; - XmFontType type_return; - XtPointer font_info; - int num_fs; - XFontStruct **font_struct_list_return; - char **font_name_list_return; - - XmFontListInitFontContext(&context, font); - entry = XmFontListNextEntry(context); - if (entry != (XmFontListEntry) NULL) - { - font_info = XmFontListEntryGetFont(entry,&type_return); - if (type_return == XmFONT_IS_FONT) - fs = (XFontStruct *)font_info; - else /* type_return == XmFONT_IS_FONTSET */ - { - num_fs = XFontsOfFontSet((XFontSet)font_info, - &font_struct_list_return, - &font_name_list_return); - if (num_fs > 0) - fs = font_struct_list_return[0]; - else - fs = (XFontStruct *)NULL; - } - } - else - fs = (XFontStruct *)NULL; - - XmFontListFreeFontContext(context); - return fs; -} - -#else -/* Motif 1.1 */ -static XFontStruct *getFontStruct(XmFontList font) -{ - XFontStruct *fs; - XmFontContext context; - XmStringCharSet charset; - - XmFontListInitFontContext(&context, font); - XmFontListGetNextFont(context, &charset, &fs); - XmFontListFreeFontContext(context); - XtFree(charset); - return fs; -} - -#endif diff --git a/trick_source/data_products/fermi-ware/psUtils.h b/trick_source/data_products/fermi-ware/psUtils.h deleted file mode 100644 index 49cfe97d..00000000 --- a/trick_source/data_products/fermi-ware/psUtils.h +++ /dev/null @@ -1,78 +0,0 @@ -/******************************************************************************* -* * -* psUtils.h -- PostScript file output routines Public Header File * -* * -* Copyright (c) 1991 Universities Research Association, Inc. * -* All rights reserved. * -* * -* This material resulted from work developed under a Government Contract and * -* is subject to the following license: The Government retains a paid-up, * -* nonexclusive, irrevocable worldwide license to reproduce, prepare derivative * -* works, perform publicly and display publicly by or for the Government, * -* including the right to distribute to other Government contractors. Neither * -* the United States nor the United States Department of Energy, nor any of * -* their employees, makes any warrenty, express or implied, or assumes any * -* legal liability or responsibility for the accuracy, completeness, or * -* usefulness of any information, apparatus, product, or process disclosed, or * -* represents that its use would not infringe privately owned rights. * -* * -* Fermilab Nirvana GUI Library * -* April 16, 1992 * -* * -* Written by Arnulfo Zepeda-Navratil * -* Centro de Investigacion y Estudio Avanzados ( CINVESTAV ) * -* Mexico * -* * -* With some portions from psFiles.c by Sanza T. Kazadi, Fermilab * -* * -*******************************************************************************/ -/* SCCS ID: psUtils.h 1.7 2/1/95 */ - -enum outdevice {X_SCREEN, PS_PRINTER}; -enum anchorModes {PS_LEFT, PS_CENTER, PS_RIGHT}; - -typedef struct { - float x1, y1, x2, y2; -} FloatSegment; - -typedef struct { - float x, y; -} FloatPoint; - -FILE *OpenPS_v2(char fname[], int width, int height); -FILE *OpenPS(char fname[], int width, int height); -FILE *OpenPSNoClip(int landscape , char fname[], Boolean DestroyOldFile, int width, int height); -void EndPS(void); -void PSDrawSegments(Display *display, Drawable w, GC gc, - XSegment *segment, int nsegments); -void PSDrawLine(Display *display, Drawable w, GC gc, int x1, int y1, - int x2, int y2); -void PSDrawLines(Display *display, Drawable w, GC gc, - XPoint *points, int nPoints, int mode); -void PSFloatDrawSegments(Display *display, Drawable w, GC gc, - FloatSegment *segment, int nSegments); -void PSFloatDrawLines(Display *display, Drawable w, GC gc, - FloatPoint *points, int nPoints); -void PSDrawPoints(Display *display, Drawable w, GC gc, - XPoint *point, int npoints, int mode); -void PSDrawRectangles(Display *display, Drawable w, GC gc, - XRectangle *rects, int nRects); -void PSFillRectangles(Display *display, Drawable w, GC gc, - XRectangle *rects, int nRects); -void PSDrawArcs(Display *display, Drawable w, GC gc, - XArc *arcs, int nArcs); -void PSFillArcs(Display *display, Drawable w, GC gc, - XArc *arcs, int nArcs); -void PSDrawString(Display *display, Drawable w, GC gc, XFontStruct *fs, - int x, int y, int anchor, char *msg); -void PSDrawXmString(Display *display, Drawable w, XmFontList font, XmString msg, - GC gc, int x, int y, int width, int alignment); -void PSDrawImage(Display *display, Drawable w, GC gc, int scanLength, - int scanLines, int bitsPerSample, int x, int y, unsigned char *bitmap); -void PSDrawDashedSegments(Display *display, Drawable w, GC gc, - XSegment *segments, int nSegments, char *dashList, int dashOffset); -void PSDrawDashedLine(Display *display, Drawable w, GC gc, int x1, int y1, - int x2, int y2, char *dashList, int dashOffset); -void PSFloatDrawDashedLines(Display *display, Drawable w, GC gc, - FloatPoint *points, int nPoints, char *dashList, int dashOffset); -void PSSetClipRectangle(int x1, int y1, int x2, int y2);