tomwalters@0: /**************************************************************************** tomwalters@0: * Routines for x11coord package. tomwalters@0: ****************************************************************************/ tomwalters@0: tomwalters@0: #include tomwalters@0: #include tomwalters@0: #include "x11coord.h" tomwalters@0: tomwalters@0: /**************************************************************************** tomwalters@0: * Set parameters for data-pixel conversion macros tomwalters@0: ****************************************************************************/ tomwalters@0: /* Initialize parameters for size and position of window on screen */ tomwalters@0: set_window_parameters(xorg,yorg, width,height) tomwalters@0: int xorg,yorg; /* Pixel coords of window origin wrt theDisplay origin */ tomwalters@0: int width,height; /* Size of window (in pixels) */ tomwalters@0: { tomwalters@0: _xorg = xorg; tomwalters@0: _yorg = yorg; tomwalters@0: _width = width; tomwalters@0: _height = height; tomwalters@0: set_bordered_box((int)0); /* defaults */ tomwalters@0: set_data_parameters((int)0,(int)0, (float)0,(float)0, (float)width,(float)height); tomwalters@0: } tomwalters@0: tomwalters@0: /* Initialize parameters for size and position of box in preset window */ tomwalters@0: set_box_parameters(xorg,yorg, width,height) tomwalters@0: int xorg,yorg; /* Pixel coords of box origin wrt bottom-left of window */ tomwalters@0: int width,height; /* Size of window (in pixels) */ tomwalters@0: { tomwalters@0: _Xp0 = xorg; tomwalters@0: _Yp0 = _height - yorg; tomwalters@0: _Xp1 = xorg + width; tomwalters@0: _Yp1 = _height - (yorg + height); tomwalters@0: _Wb = _Xp1 - _Xp0; tomwalters@0: _Hb = _Yp0 - _Yp1; tomwalters@0: set_data_parameters((int)0,(int)0, (float)0,(float)0, (float)width,(float)height); tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: /* Initialize parameters for size and position of box in preset window, */ tomwalters@0: /* given the width of the border as a %age of the window size on any side */ tomwalters@0: set_bordered_box(bpc) tomwalters@0: int bpc; tomwalters@0: { tomwalters@0: int xborder, yborder, Wb, Hb; tomwalters@0: tomwalters@0: xborder = (_width * bpc) / 100; tomwalters@0: yborder = (_height * bpc) / 100; tomwalters@0: Wb = _width - 2*xborder; tomwalters@0: Hb = _height - 2*yborder; tomwalters@0: set_box_parameters(xborder,yborder, Wb,Hb); tomwalters@0: } tomwalters@0: tomwalters@0: /* Initialize parameters for area and location of data-space to appear in box */ tomwalters@0: set_data_parameters(xp0,yp0, xd0,yd0, xrange,yrange) tomwalters@0: int xp0,yp0; /* Box origin shift as a percentage of box width,height */ tomwalters@0: float xd0,yd0; /* Data coord to appear under box origin. */ tomwalters@0: float xrange,yrange;/* Data ranges (corresponding to box width and height). */ tomwalters@0: { tomwalters@0: _xrange = xrange; tomwalters@0: _yrange = yrange; tomwalters@0: _xshift = (_Wb * xp0)/100; tomwalters@0: _yshift = (_Hb * yp0)/100; tomwalters@0: _xd0 = xd0; tomwalters@0: _yd0 = yd0; tomwalters@0: _Xd0 = xd0 - _xrange*((float)_xshift/_Wb); tomwalters@0: _Yd0 = yd0 - _yrange*((float)_yshift/_Hb); tomwalters@0: _Xd1 = xd0 + (_xrange - _xrange*((float)_xshift/_Wb)); tomwalters@0: _Yd1 = yd0 + (_yrange - _yrange*((float)_yshift/_Hb)); tomwalters@0: tomwalters@0: _xoffset = _Xp0 + _xshift - _xd0*_Wb/_xrange ; tomwalters@0: _yoffset = _Yp1 + _Hb - _yshift + _yd0*_Hb/_yrange ; tomwalters@0: _xscale = _Wb/_xrange; tomwalters@0: _yscale = _Hb/_yrange; tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: /**************************************************************************** tomwalters@0: * Creating windows, initializing GC and Font, etc.. (X11 specific) tomwalters@0: ****************************************************************************/ tomwalters@0: xopen() tomwalters@0: { tomwalters@0: tomwalters@0: if ((char *)getenv("DISPLAY") == (char *)0 ) { tomwalters@0: fprintf(stderr,"DISPLAY not set\n"); tomwalters@0: exit(1); tomwalters@0: } tomwalters@0: if ((theDisplay = XOpenDisplay(NULL)) == NULL) { tomwalters@0: fprintf(stderr,"Can't open display %s\n", getenv("DISPLAY")); tomwalters@0: exit(1); tomwalters@0: } tomwalters@0: theScreen = XDefaultScreen(theDisplay); tomwalters@0: theForeground = theBlack = XBlackPixel(theDisplay,theScreen); /* Black lines, text, and borders */ tomwalters@0: theBackground = theWhite = XWhitePixel(theDisplay,theScreen); /* White background */ tomwalters@0: theWidth = XDisplayWidth(theDisplay,theScreen); tomwalters@0: theHeight = XDisplayHeight(theDisplay,theScreen); tomwalters@0: theGC = initGC() ; tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: /* tomwalters@0: eg: xgc( 1, "times_roman14" ) ; tomwalters@0: */ tomwalters@0: tomwalters@0: xgc( linewidth, fontstr ) tomwalters@0: int linewidth ; tomwalters@0: char *fontstr ; tomwalters@0: { tomwalters@0: setLinewidth( linewidth ) ; tomwalters@0: theFont = (XFontStruct *)0; tomwalters@0: if ( setFont( fontstr ) == NULL ) { tomwalters@0: fprintf( stderr,"can't load font %s\n", fontstr ) ; tomwalters@0: exit( 1 ) ; tomwalters@0: } tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: GC initGC() tomwalters@0: { tomwalters@0: GC gc; tomwalters@0: tomwalters@0: gc = XDefaultGC(theDisplay, theScreen); tomwalters@0: /* Set foreground and background pixel values (ie colours) */ tomwalters@0: XSetState(theDisplay, gc, theForeground, theBackground, GXcopy, AllPlanes); tomwalters@0: return gc; tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: tomwalters@0: setLinewidth(width) /* Set line width, used by XDrawLine commands */ tomwalters@0: int width; tomwalters@0: { tomwalters@0: XGCValues gcvalues; tomwalters@0: tomwalters@0: gcvalues.line_width = width; tomwalters@0: XChangeGC(theDisplay, theGC, GCLineWidth, &gcvalues); tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: setFont(fontname) /* Free last theFont (unless null) and load new font */ tomwalters@0: char *fontname; /* return null if can't load font */ tomwalters@0: { tomwalters@0: if (theFont != (XFontStruct *)0) XFreeFont(theDisplay,theFont); tomwalters@0: if ((theFont = XLoadQueryFont(theDisplay, fontname)) == NULL) tomwalters@0: return 0 ; tomwalters@0: XSetFont(theDisplay, theGC, theFont->fid); tomwalters@0: return 1 ; tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: Window xCreate(name, event_mask, xorg,yorg, width,height) tomwalters@0: char *name; tomwalters@0: long event_mask; tomwalters@0: int xorg,yorg, width,height; tomwalters@0: { tomwalters@0: Window w; tomwalters@0: tomwalters@0: if ((w = XCreateSimpleWindow(theDisplay, XDefaultRootWindow(theDisplay), tomwalters@0: xorg, yorg, (unsigned)width, (unsigned)height, 1, tomwalters@0: theForeground, theBackground)) == (Window)0 ) { tomwalters@0: fprintf(stderr,"can't create window\n"); tomwalters@0: exit(1); tomwalters@0: } tomwalters@0: XStoreName(theDisplay, w, name); tomwalters@0: XSelectInput(theDisplay, w, event_mask); tomwalters@0: XMapWindow(theDisplay, w); tomwalters@0: XFlush(theDisplay); tomwalters@0: return w; tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: /**************************************************************************** tomwalters@0: * Drawing axes and boxes in a given window w. tomwalters@0: ****************************************************************************/ tomwalters@0: axis(w, p0,p1, ploc,axis) tomwalters@0: Window w; tomwalters@0: int p0,p1; /* First and last axis pixel distances, relative to parent */ tomwalters@0: int ploc; /* Location of axis (orthogonal pixel dist from parent org) */ tomwalters@0: char axis; /* Orientation of axis ('x' or 'y') */ tomwalters@0: { tomwalters@0: if (axis=='x') XDrawLine(theDisplay, w, theGC, p0,ploc, p1,ploc); tomwalters@0: if (axis=='y') XDrawLine(theDisplay, w, theGC, ploc,p0, ploc,p1); tomwalters@0: } tomwalters@0: tomwalters@0: box(w, x0,y0, x1,y1) /* draw rectangular box */ tomwalters@0: Window w; tomwalters@0: int x0,y0, x1,y1; tomwalters@0: { tomwalters@0: axis(w, y0,y1, x0,'y'); tomwalters@0: axis(w, y0,y1, x1,'y'); tomwalters@0: axis(w, x0,x1, y0,'x'); tomwalters@0: axis(w, x0,x1, y1,'x'); tomwalters@0: } tomwalters@0: tomwalters@0: /**************************************************************************** tomwalters@0: * Calibrating axes and boxes in a given window w. tomwalters@0: ****************************************************************************/ tomwalters@0: struct mark_struct { tomwalters@0: int type; /* type= HALFMARK or FULLMARK */ tomwalters@0: int position; /* mark position on screen relative to the parent system */ tomwalters@0: char label[16]; /* ASCII label of real plot value (FULLMARK only) */ tomwalters@0: }; tomwalters@0: tomwalters@0: #define NMARKS 150 /* size of array of calibration marks */ tomwalters@0: #define FULLMARK 10 /* Box calibration marks */ tomwalters@0: #define HALFMARK 5 tomwalters@0: tomwalters@0: calibrate_Axis(w, p0,p1, d0,d1, ploc,axis) tomwalters@0: Window w; tomwalters@0: int p0,p1; /* First and last axis pixel distances, relative to parent */ tomwalters@0: float d0,d1; /* First and last axis data values */ tomwalters@0: int ploc; /* Location of axis (orthogonal pixel dist from parent org) */ tomwalters@0: char axis; /* Orientation of axis ('x' or 'y') */ tomwalters@0: { tomwalters@0: int n; tomwalters@0: struct mark_struct mark[NMARKS]; tomwalters@0: tomwalters@0: if ((n = calibrate(mark, p0,p1, d0,d1)) < 0) { tomwalters@0: fprintf(stderr,"mark array out of space, increase NMARKS\n"); tomwalters@0: exit(1); tomwalters@0: } tomwalters@0: if (axis=='x') plotX(w, ploc, mark, n); tomwalters@0: if (axis=='y') plotY(w, ploc, mark, n); tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: calibrate_Box(w, xp0,yp0, xp1,yp1, xd0,yd0, xd1,yd1) tomwalters@0: Window w; tomwalters@0: int xp0,yp0, xp1,yp1; tomwalters@0: float xd0,yd0, xd1,yd1; tomwalters@0: { tomwalters@0: calibrate_Axis(w, xp0,xp1, xd0,xd1, yp0,'x'); tomwalters@0: calibrate_Axis(w, yp0,yp1, yd0,yd1, xp0,'y'); tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: plotX(w, Y, mark, n) /* Plot calibration marks along an X axis */ tomwalters@0: Window w; tomwalters@0: int Y; tomwalters@0: struct mark_struct mark[]; tomwalters@0: int n; tomwalters@0: { tomwalters@0: int i, H, W; tomwalters@0: int X; tomwalters@0: tomwalters@0: for (i = 0 ; i < n ; i++) { tomwalters@0: X = mark[i].position; tomwalters@0: XDrawLine(theDisplay, w, theGC, X, Y, X, Y+mark[i].type); tomwalters@0: if (mark[i].type == FULLMARK) /* Label calibration value */ tomwalters@0: { tomwalters@0: W = stringwidth(mark[i].label) / 2; /* Shift label left by half width */ tomwalters@0: H=20; /* Shift label down a bit */ tomwalters@0: XDrawString(theDisplay, w, theGC, X-W, Y+H, mark[i].label, strlen(mark[i].label)); tomwalters@0: } tomwalters@0: } tomwalters@0: } tomwalters@0: tomwalters@0: plotY(w, X, mark, n) /* Plot calibration marks along a Y axis */ tomwalters@0: Window w; tomwalters@0: int X; tomwalters@0: struct mark_struct mark[]; tomwalters@0: int n; tomwalters@0: { tomwalters@0: int i, H, W; tomwalters@0: int Y; tomwalters@0: tomwalters@0: for (i = 0 ; i < n ; i++) { tomwalters@0: Y = mark[i].position; tomwalters@0: XDrawLine(theDisplay, w, theGC, X, Y, X-mark[i].type, Y); tomwalters@0: if (mark[i].type == FULLMARK) { /* Label calibration value */ tomwalters@0: W = stringwidth(mark[i].label) + 10;/* Shift label left by width */ tomwalters@0: H=5; /* Shift label down a bit */ tomwalters@0: XDrawString(theDisplay, w, theGC, X-W, Y+H, mark[i].label, strlen(mark[i].label)); tomwalters@0: } tomwalters@0: } tomwalters@0: } tomwalters@0: tomwalters@0: /**************************************************************************** tomwalters@0: * Macros used by calibration routines tomwalters@0: ****************************************************************************/ tomwalters@0: #define rem(x,y) fabs((x) - (y)*(int)((x)/(y))) /* real remainder */ tomwalters@0: #define rem2(x,y) fabs((x) - (y)*(int)((x)/(y)-0.5)) /* real remainder for -ve x */ tomwalters@0: #define round(x) ((x >= 0) ? ((int)(x+0.5)) : ((int)(x-0.5))) tomwalters@0: #define min(x,y) ((x < y) ? x : y) tomwalters@0: #define EPS 1.0e-5 tomwalters@0: tomwalters@0: /**************************************************************************** tomwalters@0: * Calibrate one axis. tomwalters@0: * Fill the given array "mark" with mark structs, and return the number of tomwalters@0: * marks, or -1 indicating that the mark array is full, (and NMARKS should tomwalters@0: * be increased). tomwalters@0: * Each mark struct in the array gives the mark position (in pixels relative tomwalters@0: * to the given first and last mark positions), the mark type (being HALFMARK tomwalters@0: * or FULLMARK), and a label string (for each FULLMARK only). tomwalters@0: * Arguments are as follows: tomwalters@0: * p0,p1 first and last screen positions in pixels, relative to the parent tomwalters@0: * window, (used to calculate mark positions on the screen). tomwalters@0: * d0,d1 first and last data values (used to calculate axis labels). tomwalters@0: *****************************************************************************/ tomwalters@0: calibrate(mark, p0, p1, d0, d1) tomwalters@0: struct mark_struct mark[]; tomwalters@0: int p0,p1; /* first and last axis pixel distances, relative to parent */ tomwalters@0: float d0,d1; /* first and last axis data values */ tomwalters@0: { tomwalters@0: int position, plotsize, nmarks=0; tomwalters@0: float div, hdiv, offset, hoffset, value, hvalue; tomwalters@0: float range, scalefactor, maxerror, nextvalue, lastvalue; tomwalters@0: float label, real_division (), sig_figs (); tomwalters@0: float tmp; tomwalters@0: tomwalters@0: if (d0 > d1) { /* swap to get +ve range */ tomwalters@0: tmp = d1; d1 = d0; d0 = tmp; tomwalters@0: tmp = p1; p1 = p0; p0 = tmp; tomwalters@0: } tomwalters@0: tomwalters@0: plotsize = p1-p0; /* screen size */ tomwalters@0: range = d1-d0; /* real plot range */ tomwalters@0: tomwalters@0: div = real_division (range); tomwalters@0: hdiv = div/10; /* Halfmarks every 10th labelled division (fullmark) */ tomwalters@0: tomwalters@0: /* calculate real offset and hoffset of 1st fullmark and halfmark */ tomwalters@0: /* respectively, from first (ie min) real value d0. */ tomwalters@0: if (d0 == 0) tomwalters@0: { tomwalters@0: offset = hoffset = 0; tomwalters@0: } tomwalters@0: else tomwalters@0: { tomwalters@0: if (d0 > 0) tomwalters@0: { tomwalters@0: offset = div - rem(d0,div); tomwalters@0: hoffset = hdiv - rem(d0,hdiv); tomwalters@0: } tomwalters@0: else /* (d0 < 0) */ tomwalters@0: { tomwalters@0: offset = rem2(d0,div); tomwalters@0: hoffset = rem2(d0,hdiv); tomwalters@0: } tomwalters@0: } tomwalters@0: tomwalters@0: value = d0 + offset; /* real value of 1st fullmark */ tomwalters@0: hvalue = d0 + hoffset; /* real value of 1st halfmark */ tomwalters@0: tomwalters@0: scalefactor = (float)plotsize/range; /* scale factor between real range and plotted range */ tomwalters@0: maxerror = hdiv/2; tomwalters@0: lastvalue = d0+range+maxerror; tomwalters@0: nextvalue = value-maxerror; tomwalters@0: tomwalters@0: /* Plot halfmarks up to 1st fullmark */ tomwalters@0: tomwalters@0: for ( ; hvalue < nextvalue ; hvalue += hdiv) tomwalters@0: { tomwalters@0: position = (int)((hvalue-d0) * scalefactor); /* actual plotted position (in plot range) */ tomwalters@0: setmark (&mark[nmarks], HALFMARK, p0+position, NULL); tomwalters@0: if (++nmarks >= NMARKS) return -1; tomwalters@0: } tomwalters@0: tomwalters@0: /* Loop plotting fullmarks, with halfmarks between each */ tomwalters@0: tomwalters@0: for ( ; value < lastvalue ; value += div) tomwalters@0: { tomwalters@0: position = (int)((value-d0) * scalefactor); /* actual plotted position */ tomwalters@0: label = sig_figs (value, range); tomwalters@0: setmark (&mark[nmarks], FULLMARK, p0+position, label); tomwalters@0: if (++nmarks >= NMARKS) return -1; tomwalters@0: tomwalters@0: /* Loop plotting halfmarks between each fullmark */ tomwalters@0: tomwalters@0: nextvalue = value+div-maxerror; tomwalters@0: if (nextvalue > lastvalue) nextvalue = lastvalue; tomwalters@0: for (hvalue = value+hdiv ; hvalue < nextvalue ; hvalue += hdiv) tomwalters@0: { tomwalters@0: position = (int)((hvalue-d0) * scalefactor); /* actual plotted position */ tomwalters@0: setmark (&mark[nmarks], HALFMARK, p0+position, NULL); tomwalters@0: if (++nmarks >= NMARKS) return -1; tomwalters@0: } tomwalters@0: } tomwalters@0: return nmarks; tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: float tomwalters@0: real_division (range) /* Return recomended division between fullmarks on real scale */ tomwalters@0: float range; tomwalters@0: { tomwalters@0: int power; tomwalters@0: float scalefactor, scaled_range, div; tomwalters@0: tomwalters@0: if (range <= 0) { tomwalters@0: fprintf(stderr,"range must be positive\n"); tomwalters@0: exit(1); tomwalters@0: } tomwalters@0: tomwalters@0: if (range >= 1.0) tomwalters@0: power = -(int)(log10(range) + EPS); tomwalters@0: else tomwalters@0: power = -(int)(log10(range) - 1 + EPS); tomwalters@0: scalefactor = pow (10.0, (float)power); tomwalters@0: tomwalters@0: scaled_range = range * scalefactor; /* scaled_range is (1 <= range <= 9.9999) */ tomwalters@0: tomwalters@0: /* Set division size (in scaled_range) between given breaks in the scale */ tomwalters@0: tomwalters@0: if (scaled_range < 1.5) div = 0.1; tomwalters@0: else if (scaled_range < 2.5) div = 0.2; tomwalters@0: else if (scaled_range < 5.0) div = 0.5; tomwalters@0: else div = 1.0; tomwalters@0: tomwalters@0: return (div/scalefactor); /* return div scaled down to real range */ tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: float tomwalters@0: sig_figs (value, range) /* Round value to 2 sig figs on the scale of the range */ tomwalters@0: float value, range; tomwalters@0: { tomwalters@0: int power; tomwalters@0: float scalefactor, scaled_value; tomwalters@0: tomwalters@0: if (range >= 1.0) tomwalters@0: power = 1-(int)(log10(range) + EPS); tomwalters@0: else tomwalters@0: power = 1-(int)(log10(range) - 1 + EPS); tomwalters@0: scalefactor = pow (10.0, (float)power); tomwalters@0: tomwalters@0: scaled_value = value * scalefactor; /* scaled_value is in range (10 <= range <= 99.999) */ tomwalters@0: value = round(scaled_value); tomwalters@0: tomwalters@0: return (value/scalefactor); tomwalters@0: } tomwalters@0: tomwalters@0: /* Fill one mark struct with the mark position, type, and label */ tomwalters@0: setmark (mark, mark_type, x, x1) tomwalters@0: struct mark_struct *mark; tomwalters@0: int mark_type; tomwalters@0: int x; /* position */ tomwalters@0: float x1; /* value of label */ tomwalters@0: { tomwalters@0: if ((mark->type = mark_type) == FULLMARK) tomwalters@0: labelstring(mark->label, x1); tomwalters@0: mark->position = x; tomwalters@0: } tomwalters@0: tomwalters@0: /* Return with str containing an appropriate ASCII string of the given value */ tomwalters@0: labelstring(str, value) tomwalters@0: char *str; tomwalters@0: float value; tomwalters@0: { tomwalters@0: float decval; /* decimal part of a number */ tomwalters@0: tomwalters@0: decval = value - (int)value; tomwalters@0: if (value < 0) decval = -decval; tomwalters@0: if (value > -EPS && value < EPS) sprintf(str,"0" ); tomwalters@0: else if (fabs(value) >= 10000) sprintf(str,"%g", value); tomwalters@0: else if (decval <= EPS) sprintf(str,"%d", (int)value); tomwalters@0: else if (decval <= 0.001) sprintf(str,"%.4f", value); tomwalters@0: else if (decval <= 0.01) sprintf(str,"%.3f", value); tomwalters@0: else if (decval <= 0.1) sprintf(str,"%.2f", value); tomwalters@0: else sprintf(str,"%.1f", value); tomwalters@0: } tomwalters@0: tomwalters@0: /**************************************************************************** tomwalters@0: Text printing routines. tomwalters@0: ****************************************************************************/ tomwalters@0: /* The origin for a char is an x-value of `lbearing' to the left of the */ tomwalters@0: /* left-most char ink, and a y-value between the `ascent' and the */ tomwalters@0: /* `descent', (ie along an underline), (ref 6-20). */ tomwalters@0: /* The `margin' is an ad-hoc idea. */ tomwalters@0: tomwalters@0: /* Return the width in pixels of the given string, using the current font */ tomwalters@0: stringwidth(str) tomwalters@0: char *str; tomwalters@0: { tomwalters@0: int width; tomwalters@0: tomwalters@0: width = XTextWidth(theFont, str, strlen(str)); tomwalters@0: return width; tomwalters@0: } tomwalters@0: tomwalters@0: /* Return the height in pixels of the given string, using the current font */ tomwalters@0: stringheight(str) tomwalters@0: char *str; tomwalters@0: { tomwalters@0: XCharStruct stringinfo; /* ref Xlib 6-17 */ tomwalters@0: int dr, fa, fd; tomwalters@0: short asc, desc, width; tomwalters@0: int height; tomwalters@0: tomwalters@0: XTextExtents(theFont, str, strlen(str), &dr,&fa,&fd, &stringinfo); tomwalters@0: asc = stringinfo.ascent; /* max of char ascents in string */ tomwalters@0: desc = stringinfo.descent; /* max of char descents in string */ tomwalters@0: width = stringinfo.width; /* sum of char widths across string */ tomwalters@0: height = asc+desc; /* max height over all chars */ tomwalters@0: return height; tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: /**************************************************************************** tomwalters@0: Misc routines. tomwalters@0: ****************************************************************************/ tomwalters@0: /* Plot a dot at data coord (x,y). Dotsize=0,1,2,3,.., and size 0 is empty */ tomwalters@0: Dot(w,x,y,dotsize) tomwalters@0: Window w; tomwalters@0: float x,y; tomwalters@0: int dotsize; tomwalters@0: { tomwalters@0: int d, X,Y; tomwalters@0: tomwalters@0: if ((d=dotsize-1) >= 0) { tomwalters@0: if (d==0) /* dotsize = 1 */ tomwalters@0: Point(w, x,y); tomwalters@0: else { /* dotsize > 1 */ tomwalters@0: for (X=(-d) ; X<=d ; X++) tomwalters@0: for (Y=(-d) ; Y<=d ; Y++) tomwalters@0: XDrawPoint(theDisplay,w,theGC,px(x)+X,py(y)+Y); tomwalters@0: } tomwalters@0: } tomwalters@0: }