tomwalters@0: /* tomwalters@0: Still to consider: tomwalters@0: tomwalters@0: A structure for a box-object, containing a complete set of internal tomwalters@0: variables for one box. A routine could allocate a structure, call the tomwalters@0: routines set_box_parameters() and set_data_parameters(), and return a ptr tomwalters@0: to the structure. Now a set of #defines could take a structure pointer tomwalters@0: (just as they currently often take a window ptr), and could call the tomwalters@0: appropriate sub-routines using the internal variables for that box. tomwalters@0: (The window could be a member of the structute too). tomwalters@0: tomwalters@0: With this, you could easily maintain a set of boxes, and plot anything tomwalters@0: in any of them. But if you need ore than one window, then you'll need a tomwalters@0: window structure too, (to hold window parameters for each window). tomwalters@0: For example: tomwalters@0: tomwalters@0: struct st_window { tomwalters@0: Window w; tomwalters@0: int x,y; window origin wrt display tomwalters@0: unsigned int width,height; window size tomwalters@0: GC gc; tomwalters@0: }; tomwalters@0: tomwalters@0: struct st_box { tomwalters@0: struct st_window * pt; parent window tomwalters@0: char *fname; file name for data tomwalters@0: int n, s; num points and start point in file tomwalters@0: ...all system variables... tomwalters@0: }; tomwalters@0: tomwalters@0: */ tomwalters@0: tomwalters@0: tomwalters@0: /**************************************************************************** tomwalters@0: tomwalters@0: x11coord.h A file for inclusion into X11 plotting programs. tomwalters@0: ---------- (See x11test.c for example). tomwalters@0: tomwalters@0: **************************************************************************** tomwalters@0: tomwalters@0: User parameters: tomwalters@0: ================ tomwalters@0: 1. Window parameters - Set size and position of a window on the display. tomwalters@0: set_window_parameters(xorg,yorg, width,height) tomwalters@0: int xorg,yorg Window origin (pixel coords of top-left wrt Display). tomwalters@0: int width,height Window size (pixels). tomwalters@0: tomwalters@0: 2. Box parameters - Set size and position of a box in a preset window. tomwalters@0: a) set_box_parameters(xorg,yorg, width,height) tomwalters@0: int xorg,yorg Box origin (pixel coords of bottom-left wrt window). tomwalters@0: int width,height Box size (pixels). tomwalters@0: b) set_bordered_box(bpc) tomwalters@0: int bpc Box border (constant width) as %age of window size. tomwalters@0: tomwalters@0: 3. Data parameters - Set 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 Plot origin (as a %age of box size from box origin). tomwalters@0: float xd0,yd0 Data origin (data coords to appear under plot origin). tomwalters@0: float xrange,yrange Data ranges (area of data space to appear under plot). tomwalters@0: tomwalters@0: Notes: tomwalters@0: 1. Pixel coordinates and sizes are ints. Data coordinates and sizes are floats. tomwalters@0: 2. Pixel coords refer to the X11 coord system which has origin (0,0) in the tomwalters@0: top-left of each window. Data coords refer to the user coord system which tomwalters@0: has its origin (0,0) in the bottom-left of each box. tomwalters@0: 3. The parameter initialization routines must be called in order, (window, tomwalters@0: box, data), and must be done first, otherwise macros which use the system tomwalters@0: variables will not work. As a minimum, you MUST do set_window_parameters(), tomwalters@0: and this will give you a box the same size as the window, with origin in tomwalters@0: the bottom-left, with data origin at the box origin, and data ranges the tomwalters@0: same as pixels. tomwalters@0: 4. Although its true that set_window_parameters only sets window pixel sizes, tomwalters@0: set_box_parameters only sets box pixel sizes, and set_data_parameters only tomwalters@0: sets data sizes, the data sizes are somewhat dependent upon the pixel tomwalters@0: sizes, and so if you change the window or box parameters during a program, tomwalters@0: (eg, to resize a box), then you must re-initialize set_data_parameters at tomwalters@0: the same time. (Call it again with the same initial arguments; it will tomwalters@0: re-initialize internal parameters). tomwalters@0: tomwalters@0: User routines and macros: tomwalters@0: ========================= tomwalters@0: Set system private parameters. tomwalters@0: ----------------------------- tomwalters@0: set_window_parameters(xorg,yorg, width,height) tomwalters@0: set_box_parameters(xorg,yorg, width,height) tomwalters@0: set_bordered_box(bpc) tomwalters@0: set_data_parameters(xp0,yp0, xd0,yd0, xrange,yrange) tomwalters@0: Open connection and create window. tomwalters@0: --------------------------------- tomwalters@0: xopen() tomwalters@0: Window xcreate(name, event_mask) tomwalters@0: Convert coordinates. tomwalters@0: ------------------- tomwalters@0: int px(x) tomwalters@0: int py(y) tomwalters@0: float xp(p) tomwalters@0: float yp(p) tomwalters@0: float xpc(pc) tomwalters@0: float ypc(pc) tomwalters@0: Return pixel coordinates. tomwalters@0: ----------------------- tomwalters@0: int pleft() tomwalters@0: int pright() tomwalters@0: int pbottom() tomwalters@0: int ptop() tomwalters@0: int pwidth() tomwalters@0: int pheight() tomwalters@0: Return data coordinates. tomwalters@0: ----------------------- tomwalters@0: float xleft() tomwalters@0: float xright() tomwalters@0: float ybottom() tomwalters@0: float ytop() tomwalters@0: float xwidth() tomwalters@0: float yheight() tomwalters@0: float xcentre() tomwalters@0: float ycentre() tomwalters@0: float Xjitter(x,p) tomwalters@0: float Yjitter(y,p) tomwalters@0: Test data coordinates. tomwalters@0: --------------------- tomwalters@0: bool Xinbox(x) tomwalters@0: bool Yinbox(y) tomwalters@0: bool inbox(x,y) tomwalters@0: Draw and calibrate boxes and axes. tomwalters@0: --------------------------------- tomwalters@0: draw_Xaxis(w,yval) tomwalters@0: calibrate_Xaxis(w,yval) tomwalters@0: draw_Yaxis(w,xval) tomwalters@0: calibrate_Yaxis(w,xval) tomwalters@0: draw_box(w) tomwalters@0: calibrate_box(w) tomwalters@0: draw_calibrated_box(w) tomwalters@0: Draw points, lines, and strings, etc.. tomwalters@0: ------------------------------------- tomwalters@0: setLinewidth(width) tomwalters@0: Point(w,x,y) tomwalters@0: xPoint(w,x,y) tomwalters@0: Line(w,x1,y1,x2,y2) tomwalters@0: xLine(w,x1,y1,x2,y2) tomwalters@0: String(w,x,y,string) tomwalters@0: xString(w,x,y,string) tomwalters@0: Cross(w,x,y) tomwalters@0: xCross(w,x,y) tomwalters@0: Dot(w,x,y,dotsize) tomwalters@0: xDot(w,x,y,dotsize) tomwalters@0: Text string parameters. tomwalters@0: ----------------------- tomwalters@0: setFont("fontname") tomwalters@0: int nlines() tomwalters@0: int ncols() tomwalters@0: Return pixel sizes based on current "theFont". tomwalters@0: ---------------------------------------------- tomwalters@0: int max_charwidth() tomwalters@0: int max_charheight() tomwalters@0: int stringwidth(string) tomwalters@0: int stringheight(string) tomwalters@0: int linespacing() white space between lines. tomwalters@0: int lineheight() total line (y-value) increment. tomwalters@0: int colwidth() total character (x-value) increment. tomwalters@0: int margin() white space at sides of page. tomwalters@0: int headroom() white space at head and foot of page. tomwalters@0: Return pixel coordinates. tomwalters@0: ------------------------- tomwalters@0: int leftmargin() tomwalters@0: int rightmargin() tomwalters@0: int topmargin() tomwalters@0: int bottommargin() tomwalters@0: int line(i) tomwalters@0: int col(j) tomwalters@0: Draw text strings. tomwalters@0: ------------------ tomwalters@0: topline(w,string) tomwalters@0: bottomline(w,string) tomwalters@0: lineString(w,string,i,j) tomwalters@0: leftString(w,string,i) tomwalters@0: rightString(w,string,i) tomwalters@0: centreString(w,string,i) tomwalters@0: supertopline(w,string) tomwalters@0: tomwalters@0: tomwalters@0: Notes: tomwalters@0: 1. The user routines conventionally take data coordinate arguments. tomwalters@0: To convert pixel coordinates to data, use the xp,yp macros. tomwalters@0: tomwalters@0: Development of coord system scaling transformations: tomwalters@0: ==================================================== tomwalters@0: Internal variables (initialized by the `set' routines and used by the `px' tomwalters@0: macros) are pixel coords and sizes, and refer to the X11 coord system: tomwalters@0: tomwalters@0: | _Xp0 | tomwalters@0: +---------------+ tomwalters@0: | | tomwalters@0: tomwalters@0: | _Xp1 | tomwalters@0: +---------------------------+ tomwalters@0: | | tomwalters@0: (0,0) tomwalters@0: -+- -+- +-------------------------------------------+ tomwalters@0: | | |Window | tomwalters@0: | _Yp1| | | tomwalters@0: | | | _Wb | tomwalters@0: _Yp0| -+- | (_Xp0,_Yp1) +-----------+ (_Xp1,_Yp1) | tomwalters@0: | | |Box | | tomwalters@0: | | | |_Hb | tomwalters@0: | | | | | tomwalters@0: -+- | (_Xp0,_Yp0) +-----------+ (_Xp1,_Yp0) | tomwalters@0: | | tomwalters@0: | | tomwalters@0: | | tomwalters@0: +-------------------------------------------+ tomwalters@0: tomwalters@0: Consider a box of width Wb pixels (on horizontal axis) and height Hb pixels tomwalters@0: (on vertical axis). Let this box size represent data ranges xrange and yrange, tomwalters@0: (corresponding to Wb and Hb respectively). Let the pixel origin and the data tomwalters@0: origin be superimposed at (0,0) in the bottom-left corner. Then a data coord tomwalters@0: (x,y) is transformed into a pixel coord by the scaling: tomwalters@0: px(x) = x * Wb/xrange tomwalters@0: py(y) = y * Hb/yrange tomwalters@0: tomwalters@0: If the data coordinate which we wish to appear at the plot origin is actually tomwalters@0: (xd0,yd0), then the data origin must be shifted off the pixel origin, so that tomwalters@0: the data coord (xd0,yd0) is represented by pixel coord (0,0). Hence: tomwalters@0: px(x) = (x-xd0) * Wb/xrange tomwalters@0: py(y) = (y-yd0) * Hb/yrange tomwalters@0: tomwalters@0: It is necessary to invert the y-axis so that pixel coords are consistent with tomwalters@0: the X11 coord system, (with pixel origin in the top-left of a window and pixel tomwalters@0: y-values which increase down the window). Let the box be positioned in the tomwalters@0: top-left corner of its parent window, so that the X11 origin corresponds with tomwalters@0: the top-left corner of the box. Then the y-axis is inverted by: tomwalters@0: px(x) = (x-xd0) * Wb/xrange tomwalters@0: py(y) = Hb - (y-yd0) * Hb/yrange tomwalters@0: tomwalters@0: In general, the box will be positioned within its parent window as in the tomwalters@0: diagram above. The box is shifted into the window by an x-value Xp0 and a tomwalters@0: y-value Yp1, and these must be added to any pixel coordinate: tomwalters@0: px(x) = Xp0 + (x-xd0) * Wb/xrange tomwalters@0: py(y) = Yp1 + Hb - (y-yd0) * Hb/yrange tomwalters@0: tomwalters@0: Although Yp0 is the y-value at the bottom of the box, at its default origin, tomwalters@0: note that Yp0>Yp1, since y-values increase down the window in the X11 pixel tomwalters@0: coordinate system. tomwalters@0: Finally, we may want the user origin of the box to be somewhere other than the tomwalters@0: bottom-left corner, (Eg, scatter plots often have the user origin in the tomwalters@0: centre of the plot; time-waveform plot often have the origin half-way up the tomwalters@0: left side of the plot). To place the user origin at a pixel coordinate of tomwalters@0: (xshift,yshift), we add xshift and subtract yshift from the transformed pixel tomwalters@0: coordinates. (We subtract yshift since the transformed pixel coord is in the tomwalters@0: X11 coord system). So we have: tomwalters@0: px(x) = Xp0 + xshift + (x-xd0) * Wb/xrange tomwalters@0: py(y) = Yp1 + Hb - yshift - (y-yd0) * Hb/yrange tomwalters@0: tomwalters@0: Grouping terms we have: tomwalters@0: px(x) = Xp0 + xshift - xd0*Wb/xrange + x*Wb/xrange tomwalters@0: py(y) = Yp1 + Hb - yshift + yd0*Hb/yrange - y*Hb/yrange tomwalters@0: tomwalters@0: Now substituting: tomwalters@0: xoffset = Xp0 + xshift - xd0*Wb/xrange ; xscale = Wb/xrange tomwalters@0: yoffset = Yp1 + Hb - yshift + yd0*Hb/yrange ; yscale = Hb/yrange tomwalters@0: We have: tomwalters@0: px(x) = xoffset + x * xscale tomwalters@0: py(y) = yoffset - y * yscale tomwalters@0: tomwalters@0: The inverse transformations xp(p) and yp(p) are just the inverse of these. tomwalters@0: tomwalters@0: A typical program might be as follows: tomwalters@0: ------------------------------------- tomwalters@0: ------------------------------------------------------------------ tomwalters@0: |#include | tomwalters@0: |#include | tomwalters@0: | | tomwalters@0: |#include "x11coord.h" | tomwalters@0: | | tomwalters@0: | | tomwalters@0: |main() | tomwalters@0: |{ | tomwalters@0: | Window w; | tomwalters@0: | ..... | tomwalters@0: | | tomwalters@0: | set_window_parameters(100,85, 775,775); | tomwalters@0: | set_bordered_box(10); | tomwalters@0: | set_data_parameters(50,50, 0,0, 2.0,2.0); | tomwalters@0: | | tomwalters@0: | xopen(); | tomwalters@0: | w = xcreate("test", ButtonPressMask | ExposureMask); | tomwalters@0: | xevent_monitor(w); | tomwalters@0: |} | tomwalters@0: | | tomwalters@0: | | tomwalters@0: |xevent_monitor(w) | tomwalters@0: |Window w; | tomwalters@0: |{ | tomwalters@0: | XEvent event; | tomwalters@0: | | tomwalters@0: | for ( ; ; ) { | tomwalters@0: | XNextEvent(theDisplay,&event); | tomwalters@0: | switch (event.type) { | tomwalters@0: | .... | tomwalters@0: | case ButtonPress: | tomwalters@0: | switch(event.xbutton.button) { | tomwalters@0: | case Button1: | tomwalters@0: | XDestroyWindow(theDisplay,w); | tomwalters@0: | return; | tomwalters@0: | case Button2: | tomwalters@0: | .... | tomwalters@0: | } | tomwalters@0: | break; | tomwalters@0: | case Expose: | tomwalters@0: | if (event.xexpose.count == 0) { | tomwalters@0: | draw_calibrated_box(w); | tomwalters@0: | plot(w); | tomwalters@0: | } | tomwalters@0: | break; | tomwalters@0: | .... | tomwalters@0: | } | tomwalters@0: | } | tomwalters@0: |} | tomwalters@0: | | tomwalters@0: ------------------------------------------------------------------ tomwalters@0: The purpose of the xevent_monitor is to loop endlessly and keep the program tomwalters@0: running while the window is displayed. The window vanishes when the monitor tomwalters@0: is quit using (in this example) the left mouse button. tomwalters@0: Note that you let all plotting routines be called when an expose-event has tomwalters@0: been caught. This is not just so that the screen re-draws itself when exposed, tomwalters@0: but also to avoid data at the start of the plot going missing. tomwalters@0: If you don't set up for expose-events, but try to plot data as soon as the tomwalters@0: window is created, then it turns out that you tend to lose the first few bytes tomwalters@0: of plot data. The correct way is to plot data when the window is exposed. tomwalters@0: The window-creation and mapping process generates an expose event tomwalters@0: automatically and, when caught by the event monitor, this causes the window to tomwalters@0: be first plotted. tomwalters@0: tomwalters@0: tomwalters@0: *****************************************************************************/ tomwalters@0: #include /* /usr/include/X11/X.h */ tomwalters@0: #include /* /usr/include/X11/Xlib.h */ tomwalters@0: tomwalters@0: tomwalters@0: static char defFontString[] = "fixed" , *theFontString = defFontString ; tomwalters@0: tomwalters@0: tomwalters@0: /**************************************************************************** tomwalters@0: * Defaults for some standard window sizes tomwalters@0: ****************************************************************************/ tomwalters@0: #define FULLXORG 5 /* Full screen size */ tomwalters@0: #define FULLYORG 90 tomwalters@0: #define FULLWIDTH 1000 tomwalters@0: #define FULLHEIGHT 750 tomwalters@0: tomwalters@0: #define A4XORG 190 /* A4 size */ tomwalters@0: #define A4YORG 85 tomwalters@0: #define A4WIDTH 620 tomwalters@0: #define A4HEIGHT 760 tomwalters@0: tomwalters@0: #define PLOTXORG 100 /* Rectangular plotting area */ tomwalters@0: #define PLOTYORG 155 tomwalters@0: #define PLOTWIDTH 800 tomwalters@0: #define PLOTHEIGHT 600 tomwalters@0: tomwalters@0: #define BOXXORG 100 /* Square box */ tomwalters@0: #define BOXYORG 85 tomwalters@0: #define BOXWIDTH 775 tomwalters@0: #define BOXHEIGHT 775 tomwalters@0: tomwalters@0: /**************************************************************************** tomwalters@0: * Macros for pixel-data transformation tomwalters@0: ****************************************************************************/ tomwalters@0: /* pixel coord from data coord */ tomwalters@0: #define px(x) ( (int)(_xoffset + (x) * _xscale) ) tomwalters@0: #define py(y) ( (int)(_yoffset - (y) * _yscale) ) tomwalters@0: /* data coord from pixel coord */ tomwalters@0: #define xp(p) ( (float)(((p) - _xoffset) / _xscale) ) tomwalters@0: #define yp(p) ( (float)((_yoffset - (p)) / _yscale) ) tomwalters@0: /* data coord from a %age of data range */ tomwalters@0: #define xpc(pc) ( ((xleft()+xright())*pc) / 100 ) tomwalters@0: #define ypc(pc) ( ((ybottom()+ytop())*pc) / 100 ) tomwalters@0: /* data coord of box centre */ tomwalters@0: #define xcentre() xpc(50) tomwalters@0: #define ycentre() ypc(50) tomwalters@0: /* pixel limits of box (note that ptop() < pbottom() ). */ tomwalters@0: #define pleft() (_Xp0) tomwalters@0: #define pright() (_Xp1) tomwalters@0: #define pbottom() (_Yp0) tomwalters@0: #define ptop() (_Yp1) tomwalters@0: #define pwidth() (_Wb) tomwalters@0: #define pheight() (_Hb) tomwalters@0: /* data limits of box */ tomwalters@0: #define xleft() xp(_Xp0) tomwalters@0: #define xright() xp(_Xp1) tomwalters@0: #define ybottom() yp(_Yp0) tomwalters@0: #define ytop() yp(_Yp1) tomwalters@0: #define xwidth() xp(_Wb) tomwalters@0: #define yheight() yp(_Hb) tomwalters@0: /* test if data argument is in box */ tomwalters@0: #define Xinbox(x) ( (xleft()<=x && x<=xright()) ? 1 : 0 ) tomwalters@0: #define Yinbox(y) ( (ybottom()<=y && y<=ytop()) ? 1 : 0 ) tomwalters@0: #define inbox(x,y) ( (Xinbox(x) && Yinbox(y)) ? 1 : 0 ) tomwalters@0: /* jitter data value (ie move by a given pixel distance) */ tomwalters@0: #define Xjitter(x,p) ( xp(px(x)+(p)) ) tomwalters@0: #define Yjitter(y,p) ( yp(py(y)+(p)) ) tomwalters@0: tomwalters@0: /**************************************************************************** tomwalters@0: * Macros for routines (using preset system parameters) tomwalters@0: ****************************************************************************/ tomwalters@0: /* Xaxes: yval is a data value at which to place a horizontal axis. */ tomwalters@0: /* For example: 0 (zero line), ybottom() (box-bottom), ytop() (box-top). */ tomwalters@0: #define draw_Xaxis(w,yval) if (Yinbox(yval)) axis(w, _Xp0,_Xp1, py(yval),'x') tomwalters@0: #define calibrate_Xaxis(w,yval) calibrate_Axis(w, _Xp0,_Xp1, _Xd0,_Xd1, py(yval),'x') tomwalters@0: tomwalters@0: /* Yaxes: xval is a data value at which to place a vertical axis. */ tomwalters@0: /* For example: 0 (zero line), xleft() (box-left), xright() (box-right). */ tomwalters@0: #define draw_Yaxis(w,xval) if (Xinbox(xval)) axis(w, _Yp0,_Yp1, px(xval),'y') tomwalters@0: #define calibrate_Yaxis(w,xval) calibrate_Axis(w, _Yp0,_Yp1, _Yd0,_Yd1, px(xval),'y') tomwalters@0: tomwalters@0: #define draw_box(w) box(w, _Xp0,_Yp0, _Xp1,_Yp1) tomwalters@0: #define calibrate_box(w) calibrate_Box(w, _Xp0,_Yp0, _Xp1,_Yp1, _Xd0,_Yd0, _Xd1,_Yd1) tomwalters@0: #define draw_calibrated_box(w) draw_box(w); calibrate_box(w) tomwalters@0: tomwalters@0: #define xcreate(name,mask) xCreate(name,mask, _xorg,_yorg, _width,_height) tomwalters@0: tomwalters@0: /**************************************************************************** tomwalters@0: * Macros for standard X11 commands tomwalters@0: ****************************************************************************/ tomwalters@0: #define Point(w,x,y) XDrawPoint(theDisplay,w,theGC,px(x),py(y)) tomwalters@0: #define Line(w,x1,y1,x2,y2) XDrawLine(theDisplay,w,theGC,px(x1),py(y1),px(x2),py(y2)) tomwalters@0: #define String(w,x,y,string) XDrawString(theDisplay, w, theGC, px(x),py(y), string, strlen(string)) tomwalters@0: tomwalters@0: #define Cross(w,x,y) XDrawLine(theDisplay,w,theGC,px(x)-10,py(y),px(x)+10,py(y)); XDrawLine(theDisplay,w,theGC,px(x),py(y)-10,px(x),py(y)+10) tomwalters@0: tomwalters@0: #define xPoint(w,x,y) if (inbox(x,y)) Point(w,x,y) tomwalters@0: #define xLine(w,x1,y1,x2,y2) if (inbox(x1,y1) && inbox(x2,y2)) Line(w,x1,y1,x2,y2) tomwalters@0: #define xString(w,x,y,string) if (inbox(x,y)) String(w,x,y,string) tomwalters@0: tomwalters@0: #define xCross(w,x,y) if (inbox(x,y)) Cross(w,x,y) tomwalters@0: #define xDot(w,x,y,dotsize) if (inbox(x,y)) Dot(w,x,y,dotsize) tomwalters@0: tomwalters@0: /* Max width and height (pixels) of chars in current font, (ref 6-17, 6-19) */ tomwalters@0: #define max_charwidth() ( theFont->max_bounds.rbearing - theFont->min_bounds.lbearing ) tomwalters@0: #define max_charheight() ( theFont->max_bounds.ascent + theFont->max_bounds.descent ) tomwalters@0: /* Number of lines and cols (chars) of current font which fit into box */ tomwalters@0: #define linespacing() ( (theFont->max_bounds.descent)>>1 ) tomwalters@0: #define lineheight() ( max_charheight()+linespacing() ) tomwalters@0: #define colwidth() ( max_charwidth() ) tomwalters@0: #define nlines() ( pheight() / lineheight() ) tomwalters@0: #define ncols() ( pwidth() / colwidth() ) tomwalters@0: #define topline(w,string) lineString(w,string,1,1) tomwalters@0: #define bottomline(w,string) lineString(w,string,nlines(),1) tomwalters@0: #define margin() ( theFont->max_bounds.lbearing + theFont->max_bounds.rbearing ) tomwalters@0: #define headroom() ( theFont->max_bounds.ascent ) tomwalters@0: #define leftmargin() ( pleft() + margin() ) tomwalters@0: #define rightmargin() ( pright() - margin() ) tomwalters@0: #define topmargin() ( ptop() + headroom() ) tomwalters@0: #define bottommargin() ( pbottom() - headroom() ) tomwalters@0: #define line(i) ( topmargin() + (i-1)*lineheight() ) tomwalters@0: #define col(j) ( leftmargin() + (j-1)*colwidth() ) tomwalters@0: #define lineString(w,string,i,j) ( XDrawString(theDisplay,w,theGC,col(j),line(i),string,strlen(string)) ) tomwalters@0: #define leftString(w,string,i) ( XDrawString(theDisplay,w,theGC,leftmargin(),line(i),string,strlen(string)) ) tomwalters@0: #define rightString(w,string,i) ( XDrawString(theDisplay,w,theGC,rightmargin()-stringwidth(string),line(i),string,strlen(string)) ) tomwalters@0: #define centreString(w,string,i) ( XDrawString(theDisplay,w,theGC,(pwidth()-stringwidth(string))>>1,line(i),string,strlen(string)) ) tomwalters@0: #define supertopline(w,string) ( XDrawString(theDisplay,w,theGC,col(1),ptop()-max_charheight()-headroom(),string,strlen(string)) ) tomwalters@0: tomwalters@0: tomwalters@0: /**************************************************************************** tomwalters@0: * Window parameters (X11-specific). tomwalters@0: ****************************************************************************/ tomwalters@0: Display *theDisplay; tomwalters@0: int theScreen; /* screen_number */ tomwalters@0: int theWidth; /* horizontal size, in pixels */ tomwalters@0: int theHeight; /* vertical size, in pixels */ tomwalters@0: unsigned long theForeground; /* lines, text, and border pixel value */ tomwalters@0: unsigned long theBackground; /* background pixel value */ tomwalters@0: GC theGC; /* graphics context */ tomwalters@0: XFontStruct *theFont; /* current font used to print text */ tomwalters@0: unsigned long theBlack; /* pixel value for black */ tomwalters@0: unsigned long theWhite; /* pixel value for white */ tomwalters@0: tomwalters@0: /**************************************************************************** tomwalters@0: * System (global) variables tomwalters@0: *****************************************************************************/ tomwalters@0: int _xorg, _yorg; /* Window origin (pixel coords top-left wrt Display)*/ tomwalters@0: int _width, _height;/* Window size (pixels). */ tomwalters@0: tomwalters@0: int _Xp0, _Yp0; /* Box origin (pixel coords at bottom-left) */ tomwalters@0: int _Xp1, _Yp1; /* Box limits (pixel coords at top-right) */ tomwalters@0: int _Wb, _Hb; /* Box size (pixels). */ tomwalters@0: tomwalters@0: float _Xd0, _Yd0; /* Box origin (data coords at bottom-left) */ tomwalters@0: float _Xd1, _Yd1; /* Box limits (data coords at top-right) */ tomwalters@0: float _xrange,_yrange;/* Box size (data ranges). */ tomwalters@0: tomwalters@0: int _xshift,_yshift;/* Plot origin (pixel coords from box origin) */ tomwalters@0: float _xd0, _yd0; /* Data coords fixed at plot origin */ tomwalters@0: tomwalters@0: float _xoffset,_yoffset; tomwalters@0: float _xscale, _yscale; tomwalters@0: tomwalters@0: /**************************************************************************** tomwalters@0: * Functions (in x11coord.c) tomwalters@0: *****************************************************************************/ tomwalters@0: extern set_window_parameters(); tomwalters@0: extern set_box_parameters(); tomwalters@0: extern set_bordered_box(); tomwalters@0: extern set_data_parameters(); tomwalters@0: extern xopen(); tomwalters@0: extern GC initGC(); tomwalters@0: extern setLinewidth(); tomwalters@0: extern setFont(); tomwalters@0: extern Window xCreate(); tomwalters@0: extern axis(); tomwalters@0: extern box(); tomwalters@0: extern calibrate_Axis(); tomwalters@0: extern calibrate_Box(); tomwalters@0: extern plotX(); tomwalters@0: extern plotY(); tomwalters@0: extern int stringwidth(); tomwalters@0: extern int stringheight(); tomwalters@0: extern calibrate(); tomwalters@0: extern Dot(); tomwalters@0: