argv@island.uu.net (Dan Heller) (04/11/89)
Submitted-by: David Harrison <davidh@ic.berkeley.edu> Posting-number: Volume 3, Issue 75 Archive-name: xgraph/part06 #!/bin/sh # to extract, remove the header and type "sh filename" if `test ! -d ./xgraph-11` then mkdir ./xgraph-11 echo "mkdir ./xgraph-11" fi if `test ! -s ./xgraph-11/Makefile` then echo "writing ./xgraph-11/Makefile" cat > ./xgraph-11/Makefile << '\End\Of\Shar\' # # Makefile for the xgraph program # # David Harrison # University of California, Berkeley # 1987 # # NOTE: the libCreate library is a library I wrote to replace XCreate # and XCreateTerm with ones I think provide a better interface. # If you do not have this library, you can get it from hoser. # If you don't want to use it, just take it out of the LIBS # line below. # CLEVEL = CFLAGS = $(CLEVEL) -Ixtb -Iux11 CC = cc SRC = xgraph.c xgX.c hard_devices.c dialog.c hpgl.c new_ps.c OBJ = xgraph.o xgX.o hard_devices.o dialog.o hpgl.o new_ps.o UX11 = libux11.a XTB = libxtb.a LIBS = xtb/$(XTB) ux11/$(UX11) -lX11 -lm TARGET = xgraph #-------- $(TARGET): $(OBJ) xtb_m ux11_m $(CC) $(CFLAGS) -o $(TARGET) $(OBJ) $(LIBS) xg11: $(TOBJ) xtb_m ux11_m $(CC) $(CFLAGS) -o xg11 $(TOBJ) $(LIBS) xtb_m: cd xtb; make CLEVEL=$(CLEVEL) $(XTB) ux11_m: cd ux11; make CLEVEL=$(CLEVEL) $(UX11) xgtest: xgtest.o cc $(CFLAGS) -o xgtest xgtest.o -lm clean: rm -f $(OBJ) $(TARGET) xgtest.o xgtest #* *~ cd xtb; make clean cd ux11; make clean \End\Of\Shar\ else echo "will not over write ./xgraph-11/Makefile" fi if `test ! -s ./xgraph-11/README.ANNOUNCE` then echo "writing ./xgraph-11/README.ANNOUNCE" cat > ./xgraph-11/README.ANNOUNCE << '\End\Of\Shar\' Xgraph for X11 is now available. This program is a port of the popular 2-dimensional plotting program orginally developed under X10. In almost all respects, this program is compatible with the older xgraph. This program is NOT a widget. Like its predecessor, it is a stand-alone program that accepts input in a graph-like format and plots the data on an X11 screen. Scatter plots and a limited form of bar graph plotting is also possible. Zooming in on regions of a graph is supported. This version also includes much improved support for generating hardcopy graphs to Postscript printers and HPGL plotters. The source for the program is available through anonymous ftp to shambhala.Berkeley.EDU (128.32.132.54): % ftp shambhala.Berkeley.EDU Name: anonymous Password: <your login> ftp> cd pub ftp> binary ftp> get xgraph-11.tar.Z ftp> quit % uncompress xgraph-11.tar.Z % tar xf xgraph-11.tar This will create a directory called xgraph-11. In that directory you will find a file called README.INSTALL that contains directions for building the program. The source has also been submitted to the moderator of comp.sources.x in shar format. Please send all bug reports, questions, comments or suggestions to the electronic address below. David Harrison UC Berkeley Electronics Research Lab (davidh@ic.Berkeley.EDU, ...!ucbvax!ucbcad!davidh) \End\Of\Shar\ else echo "will not over write ./xgraph-11/README.ANNOUNCE" fi if `test ! -s ./xgraph-11/README.GENERAL` then echo "writing ./xgraph-11/README.GENERAL" cat > ./xgraph-11/README.GENERAL << '\End\Of\Shar\' This directory contains source for the X11 version of xgraph, a two-dimensional data plotting program. Those familar with the X10 version of this program will find that is completely compatible. However, there are a few important notes and changes you should be aware of: 1. The program was developed and tested on X11 release 3 on a color VAXstation GPX. It should work on most other servers without change but has not been tested on these other configurations. If you have problems, please send a note to davidh@ic.Berkeley.EDU or ...!ucbvax!ucbcad!davidh 2. This version includes an improved hardcopy facility. See the manual page for details about the hardcopy dialog. 3. In some cases, xgraph uses dashed lines to distinguish different data sets. Some servers are notoriously slow at rendering dashed lines. Be prepared for a significantly reduced performance on those servers. 4. Xgraph now uses software clipping to clip data to its display windows. This means you should be able to zoom in much farther on large data sets than was possible under the X10 version. 5. Xgraph tries to handle visuals and colormaps in a correct manner. However, you may have to make changes if your window manager does not install colormaps for applications requesting such installations. 6. This program was constructed before the release of the ICCCM of February, 1989. Since it is not a X toolkit based program, it may not conform to all of the conventions laid out in that document. 7. As a follow-on to (6), note that the operation of the program is heavily influenced by your choice of window managers. Focus based window managers (like dxwm from Digital) will require you to set focus in the text input slots of the hardcopy dialog box. 8. Since xgraph has become quite popular, those in positions of power have recommended I add the standard UC Berkeley copyright notice to this software. See copyright.h for details. David Harrison UC Berkeley Electronics Research Lab (davidh@ic.Berkeley.EDU, ...!ucbvax!ucbcad!davidh) \End\Of\Shar\ else echo "will not over write ./xgraph-11/README.GENERAL" fi if `test ! -s ./xgraph-11/README.HARDCOPY` then echo "writing ./xgraph-11/README.HARDCOPY" cat > ./xgraph-11/README.HARDCOPY << '\End\Of\Shar\' /* * Hardcopy Interface for Xgraph * * Major differences from first version: * Four new parameters are passed to the device initialization routine: * title_family, title_size, axis_family, and axis_size. See the * description of xg_init() for details. * * Clipping is done automatically by xgraph. The xg_clip() routine * is obsolete. * * The xg_line() routine has become the xg_seg() routine. It now * draws segments rather than a series of lines. * * A new field (max_segs) in the device structure now specifies * the maximum number of segments the device can handle in a group. */ /* * Adding an output device to xgraph * * Step 1 * Write versions of the following routines for your device: * xg_init(), xg_text(), xg_seg(), xg_dot(), and xg_end(). * The interface and function of these routines are described * in detail below. These routines should be named according * to your device. For example, the initialization routine * for the Postscript output device is psInit(). Also, name * your source file after your device (e.g. the postscript * routines are in the file ps.c). Instructions continue * after the description of the interface routines. */ #define D_COLOR 0x01 #define ERRBUFSIZE 2048 typedef struct xg_out { int dev_flags; /* Device characteristic flags */ int area_w, area_h; /* Width and height in pixels */ int bdr_pad; /* Padding from border */ int axis_pad; /* Extra space around axis labels */ int tick_len; /* Length of a tick mark */ int legend_pad; /* Top of legend text to legend line */ int axis_width; /* Width of big character of axis font */ int axis_height; /* Height of big character of axis font */ int title_width; /* Width of big character of title font */ int title_height; /* Height of big character of title font */ int max_segs; /* Maximum number of segments in group */ void (*xg_text)(); /* Draws text at a location */ void (*xg_seg)(); /* Draws a series of segments */ void (*xg_dot)(); /* Draws a dot or marker at a location */ void (*xg_end)(); /* Stops the drawing sequence */ char *user_state; /* User supplied state information */ } xgOut; int xg_init(strm, width, height, title_family, title_size, axis_family, axis_size, out_info, errmsg) FILE *strm; /* Output stream */ int width, height; /* Size of space (microns) */ char *title_family; /* Name of title font family */ double title_size; /* Title font height (points) */ char *axis_family; /* Name of axis font family */ double axis_size; /* Axis font height (points) */ xgOut *out_info; /* Device info (RETURN) */ char errmsg[ERRBUFSIZE]; /* Error message area */ /* * This routine is called by xgraph just before drawing is to * begin. The desired size of the plot is given by `width' * and `height'. The parameters `title_family', `title_size', * `axis_family', and `axis_size' specify the names of the * title and axis fonts and their vertical sizes (in points). * These parameters can be ignored if your device does not * support multiple fonts. The routine should fill in all of * the fields of `out_info' with appropriate values. The values * are described below: * area_w, area_h: * Size of the drawing space in device coordinates. * This should take in account the requested area * given by `width', and `height'. * bdr_pad: * Xgraph will leave this number of device coordinates around * all of the outer edges of the graph. * axis_pad: * Additional space around axis labels (in devcoords) * so that the labels do not appear crowded. * legend_pad: * Space (in devcoords) from the top of legend text to * the representative line drawn above the legend text. * tick_len: * Size of a tick mark placed on axis (in devcoords) * axis_width: * An estimate of the width of a large character in * the axis font (in devcoords). This can be an overestimate. An * underestimate may produce bad results. * axis_height: * An estimate of the height of a large character in * the axis labeling font (in devcoords). * title_width, title_height: * Same as above except for the title font. * max_segs: * Due to buffering constraints, some devices may not be able to * handle massive segment lists. This parameter tells xgraph not * to send more than `max_segs' segments in one request. * Output to the device should be written to the stream `strm'. * The functions are described individually below. After filling * in the parameters and setting the function pointers, the routine * should initialize its drawing state and store any extra needed * information in `user_state'. This value will be passed to all * other routines during the drawing sequence. If the device * cannot initialize, it should return a zero status and fill * `errmsg' with an informative error message. */ /* Text justifications */ #define T_CENTER 0 #define T_LEFT 1 #define T_UPPERLEFT 2 #define T_TOP 3 #define T_UPPERRIGHT 4 #define T_RIGHT 5 #define T_LOWERRIGHT 6 #define T_BOTTOM 7 #define T_LOWERLEFT 8 /* Text styles */ #define T_AXIS 0 #define T_TITLE 1 void xg_text(user_state, x, y, text, just, style) char *user_state; /* Value set in xg_init */ int x, y; /* Text position (pixels) */ char *text; /* Null terminated text */ int just; /* Justification (above) */ int style; /* Text style (above) */ /* * This routine should draw text at the indicated position using * the indicated justification and style. The justification refers * to the location of the point in reference to the text. For example, * if just is T_LOWERLEFT, (x,y) should be located at the lower left * edge of the text string. */ /* Line Styles */ #define L_AXIS 0 #define L_ZERO 1 #define L_VAR 2 void xg_seg(user_state, ns, seglist, width, style, lappr, color) char *user_state; /* Value set in xg_init */ int ns; /* Number of segments */ XSegment *seglist; /* X array of segments */ int width; /* Width of lines */ int style; /* See above */ int lappr; /* Line appearence */ int color; /* Line color (if any) */ /* * This routine draws a number of line segments at the points * given in `seglist'. Note that contiguous segments need not share * endpoints but often do. All segments should be `width' devcoords wide * and drawn in style `style'. If `style' is L_VAR, the parameters * `color' and `lappr' should be used to draw the line. Both * parameters vary from 0 to 7. If the device is capable of * color, `color' varies faster than `style'. If the device * has no color, `style' will vary faster than `color' and * `color' can be safely ignored. However, if the * the device has more than 8 line appearences, the two can * be combined to specify 64 line style variations. * Xgraph promises not to send more than the `max_segs' in the * xgOut structure passed back from xg_init(). */ /* Marker styles */ #define P_PIXEL 0 #define P_DOT 1 #define P_MARK 2 void xg_dot(user_state, x, y, style, type, color) char *user_state; /* Value set in xg_init */ int x, y; /* Location in pixel units */ int style; /* Dot style */ int type; /* Type of marker */ int color; /* Marker color (if any) */ /* * This routine should draw a marker at location `x,y'. If the * style is P_PIXEL, the dot should be a single pixel. If * the style is P_DOT, the dot should be a reasonably large * dot. If the style is P_MARK, it should be a distinguished * mark which is specified by `type' (0-7). If the output * device is capable of color, the marker should be drawn in * `color' (0-7) which corresponds with the color for xg_line. */ void xg_end(user_state) char *user_state; /* * This routine is called after a drawing sequence is complete. * It can be used to clean up the user state and set the device * state appropriately. This routine is optional in the structure. */ /* * Adding an output device to xgraph * * Step 2 * Edit the file hard_devices.c. Declare your initialization * function and add your device to the list of devices, * hard_devices[]. The structure hard_dev is described below: */ typedef struct hard_dev { char *dev_name; /* Device name */ int (*dev_init)(); /* Initialization function */ char *dev_spec; /* Default pipe program */ char dev_file[MFNAME]; /* Default file name */ char dev_printer[MFNAME]; /* Default printer name */ double dev_max_dim; /* Default maximum dimension (cm) */ char dev_title_font[MFNAME];/* Default name of title font */ double dev_title_size; /* Default size of title font (pnts) */ char dev_axis_font[MFNAME]; /* Default name of axis font */ double dev_axis_size; /* Default size of axis font (pnts) */ }; /* * dev_spec: * The dev_spec field should be a command that directly outputs to * your device. The command should contain one %s directive that * will be filled in with the name of the device from the hardcopy * dialog. * dev_file: * The default file to write output to if the user selects `To File'. * dev_printer: * The default printer to write output to if the user selects * `To Device'. * dev_max_dim: * The default maximum dimension for the device in centimeters. * dev_title_font, dev_title_size: * The default title font and size. Sizes are specified in * points (1/72 inch). * dev_axis_font, dev_axis_size: * The default axis font and size. */ /* * Adding an output device to xgraph * * Step 3 * Edit the file Makefile. Add your source file to the SRC variable * and the corresponding object file to the OBJ variable. Finally, * remake xgraph. Your device should now be available in the * hardcopy dialog. */ \End\Of\Shar\ else echo "will not over write ./xgraph-11/README.HARDCOPY" fi if `test ! -s ./xgraph-11/README.INSTALL` then echo "writing ./xgraph-11/README.INSTALL" cat > ./xgraph-11/README.INSTALL << '\End\Of\Shar\' This file contains instructions for building the X11 version of xgraph. When unpacked, the source is distributed into three directories: xgraph-11 Top level source for the main program xgraph-11/xtb A mini-toolbox for constructing the hardcopy dialog xgraph-11/ux11 A library of useful X11 programming utilities A Makefile is provided in each directory. Type "make" in the top level directory to build the system. The program assumes the machine already has X11 libraries and include files installed in standard locations. After a binary has been built, you can move it to a standard location and type "make clean" to remove object files and library archives. The manual page is in the file xgraph-11/xgraph.1. This file can be moved into standard manual page locations if desired. A test program for xgraph is included. To make this test program, type "make xgtest" in the top level directory. Try the following command to check out xgraph: % xgtest 7 -5.0 5.0 0.1 | xgraph This should produce a graph with a series of parabolic curves. Normally, the program is compiled without debugging, profiling, or optimization flags. You can change this by declaring the appropriate flags in the Makefile variable CLEVEL in the top level Makefile. Other documentation files are included. A summary of these files is given below: README.ANNOUNCE Message submitted to comp.windows.x announcing the program and how to obtain it. README.GENERAL Important notes about differences and quirks of the program. README.HARDCOPY Documenation for writing your own hardcopy driver library. README.INSTALL This file. David Harrison UC Berkeley Electronics Research Lab (davidh@ic.Berkeley.EDU, ...!ucbvax!ucbcad!davidh) \End\Of\Shar\ else echo "will not over write ./xgraph-11/README.INSTALL" fi if `test ! -s ./xgraph-11/TAGS` then echo "writing ./xgraph-11/TAGS" cat > ./xgraph-11/TAGS << '\End\Of\Shar\' dialog.c,325 static int can_fun(129,3306 static void del_err_box(561,16026 static int df_fun(55,1154 void do_error(380,11494 static int err_func(439,12899 int getline(539,15726 void ho_dialog(320,9553 static Window make_dialog(144,3705 static Window make_err_box(453,13225 Window make_shadow(295,9010 static int ok_fun(80,1842 dummy.c,39 int hpglInit(9,116 int psInit(21,330 format.c,211 #define ERROR(10,84 cwtype *a_cwclist(63,1001 struct llist *a_llist(51,788 void c_hort(199,4047 void do_hort(127,2429 char *f_alloc(45,723 cwtype *hort(103,1917 void s_hort(161,3052 cwtype *wls(77,1267 format2.c,339 #define ERROR(7,101 void fill_widget(295,6010 static void fmt_addpos(112,1959 static char *fmt_alloc(11,184 void fmt_do(241,5081 static void fmt_hort(136,2354 void fmt_print(257,5301 static void fmt_setpos(87,1582 static void fmt_top(201,4238 static void fmt_vert(169,3299 fmt *fmt_w(17,258 fmt *hort(32,489 fmt *vert(60,1042 hard_devices.c,32 int hard_count = sizeof(18,345 hpgl.c,145 #define MAX(7,79 #define MIN(8,122 hpglClip(79,2036 hpglDot(254,7823 hpglEnd(286,8926 hpglInit(47,1111 hpglSeg(170,4598 hpglText(95,2433 ps.c,169 #define MAX(40,616 #define MIN(39,572 #define XSUCKSY(69,1339 psClip(163,4980 psDot(333,9323 psEnd(374,10356 int psInit(72,1396 psLine(266,7394 psText(180,5571 toolbox.c,823 #define STRDUP(32,827 void br_del(433,11125 int br_get(420,10813 static int br_h(347,8441 Window br_new(373,9094 void bt_del(316,7871 static void bt_draw(170,4157 int bt_get(281,7030 static int bt_h(204,4933 static void bt_line(190,4607 int bt_set(295,7318 static GC set_gc(55,1397 static int text_width(563,13940 int ti_dch(777,20362 void ti_del(807,21337 static void ti_draw(578,14289 void ti_get(700,17954 static int ti_h(616,15350 int ti_ins(747,19392 static void ti_line(602,15002 Window ti_new(654,16194 int ti_set(717,18479 void to_del(527,13227 static void to_draw(464,11660 static int to_h(477,11927 Window to_new(496,12231 Window xtb_bt_init(237,5563 int xtb_dispatch(121,2967 void xtb_init(38,946 xtb_data xtb_lookup(106,2711 void xtb_register(85,2140 int xtb_unregister(136,3359 xawdialog.c,49 make_dialog(10,175 Widget make_whichone(34,861 xawtest.c,82 void dump_core(28,540 int dump_x11(35,652 main(51,907 void push_button(43,773 xgX.c,182 static GC dotGC(132,3501 void dot_X(279,7784 void init_X(68,1829 static GC segGC(101,2592 void seg_X(231,5930 void set_X(31,641 static GC textGC(77,1987 void text_X(161,4301 xgraph.c,1320 #define ABS(48,1208 #define ADD_GRID(1761,51835 #define BWMARK(67,1647 #define COLMARK(64,1605 #define C_CODE(1905,55145 DelWindow(589,16761 int DrawData(1912,55382 int DrawGridAndAxis(1568,45569 int DrawLegend(2053,59591 DrawTitle(1460,41887 int DrawWindow(1430,41176 unsigned long GetColor(748,20444 int HandleZoom(654,18175 int InitSets(787,21408 #define LINESTYLE(58,1463 #define MARKSTYLE(61,1538 #define MAX(46,1126 #define MIN(47,1167 Window NewWindow(441,12439 #define PIXVALUE(56,1421 int ParseArgs(1112,31201 PrintWindow(610,17212 int ProcessStyle(953,26520 #define RDDBL(938,26090 #define RDFLG(929,25863 #define RDFONT(923,25640 #define RDINT(913,25326 #define RDPIX(909,25205 #define RDSTR(920,25557 #define RND(2107,61175 int ReadData(1310,37455 int ReadDefaults(981,27241 int ReversePixel(944,26305 double RoundUp(1828,53470 #define SCREENX(106,2908 #define SCREENY(108,3011 #define TRANX(647,17977 #define TRANY(650,18069 int TransformCompute(1479,42344 int WriteValue(1864,54231 static int XErrHandler(2231,64684 int argerror(1082,29670 int del_func(394,11322 void do_hardcopy(2111,61243 int hcpy_func(414,11837 if 629,17601 double initGrid(1763,51895 main(250,7518 #define nlog10(52,1313 double stepGrid(1819,53315 static char *tildeExpand(2192,63677 xgtest.c,33 double func(16,380 main(24,523 \End\Of\Shar\ else echo "will not over write ./xgraph-11/TAGS" fi if `test ! -s ./xgraph-11/copyright.h` then echo "writing ./xgraph-11/copyright.h" cat > ./xgraph-11/copyright.h << '\End\Of\Shar\' /* * xgraph - program to graphically display numerical data * * David Harrison * University of California, Berkeley * 1989 * * Copyright (c) 1988, 1989, Regents of the University of California. * All rights reserved. * * Use and copying of this software and preparation of derivative works * based upon this software are permitted. However, any distribution of * this software or derivative works must include the above copyright * notice. * * This software is made available AS IS, and neither the Electronics * Research Laboratory or the University of California make any * warranty about the software, its performance or its conformity to * any specification. */ #ifndef _RIGHTS_ #define _RIGHTS_ static char copyright[] = "Copyright (c) 1989, Regents of the University of California. All rights reserved."; #endif /* _RIGHTS_ */ \End\Of\Shar\ else echo "will not over write ./xgraph-11/copyright.h" fi if `test ! -s ./xgraph-11/dialog.c` then echo "writing ./xgraph-11/dialog.c" cat > ./xgraph-11/dialog.c << '\End\Of\Shar\' /* * Xgraph Dialog Boxes * * This file constructs the hardcopy and error dialog * boxes used by xgraph. It uses the mini-toolbox given * in toolbox.c. */ #include "copyright.h" #include "xgout.h" #include "xgraph.h" #include "hard_devices.h" #include "xtb.h" #include <X11/Xutil.h> void do_error(); #define MAXCHBUF 1024 #ifdef SHADOW #define gray_width 16 #define gray_height 16 static short gray_bits[] = { 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa}; #endif static void make_err_box(); static void del_err_box(); #define D_VPAD 2 #define D_HPAD 2 #define D_INT 4 #define D_BRDR 2 #define D_INP 35 #define D_DSP 10 #define D_FS 10 typedef struct d_info { char *prog; /* Program name */ xtb_data cookie; /* Info used by do_harcopy */ Window choices; /* Output device choices */ Window fod; /* File or device flag */ Window fodspec; /* File or device spec */ Window dimspec; /* Maximum dimension spec */ Window tf_family; /* Title font family spec */ Window tf_size; /* Title font size spec */ Window af_family; /* Axis font family spec */ Window af_size; /* Axis font size spec */ }; #define BACKSPACE 0010 #define DELETE 0177 #define CONTROL_U 0025 #define CONTROL_X 0030 /*ARGSUSED*/ static xtb_hret df_fun(win, ch, text, val) Window win; /* Widget window */ int ch; /* Typed character */ char *text; /* Copy of text */ xtb_data val; /* User info */ /* * This is the handler function for the text widget for * specifing the file or device name. It supports simple * line editing operations. */ { if ((ch == BACKSPACE) || (ch == DELETE)) { if (!xtb_ti_dch(win)) XBell(disp, 0); } else if ((ch == CONTROL_U) || (ch == CONTROL_X)) { (void) xtb_ti_set(win, "", (xtb_data) 0); } else { /* Insert if printable - ascii dependent */ if ((ch < ' ') || (ch >= DELETE) || !xtb_ti_ins(win, ch)) { XBell(disp, 0); } } return XTB_HANDLED; } /*ARGSUSED*/ static xtb_hret ok_fun(win, bval, info) Window win; /* Button window */ int bval; /* Button value */ xtb_data info; /* Local button info */ /* * This is the handler function for when the `Ok' button * is hit. It sets the button, does the hardcopy output, * and turns the button off. It returns a status which * deactivates the dialog. */ { struct d_info *real_info = (struct d_info *) info; int val, dev_p; char file_or_dev[MAXCHBUF], dim_spec[MAXCHBUF], *dev_spec; char tfam[MAXCHBUF], afam[MAXCHBUF]; char tsizstr[MAXCHBUF], asizstr[MAXCHBUF]; double centimeters, tsize, asize; xtb_hret rtn; (void) xtb_bt_set(win, 1, (xtb_data) 0); val = xtb_br_get(real_info->choices); if ((val >= 0) && (val < hard_count)) { dev_p = xtb_br_get(real_info->fod); if ((dev_p == 0) || (dev_p == 1)) { xtb_ti_get(real_info->fodspec, file_or_dev, (xtb_data *) 0); xtb_ti_get(real_info->dimspec, dim_spec, (xtb_data *) 0); if (sscanf(dim_spec, "%lf", ¢imeters) == 1) { xtb_ti_get(real_info->tf_family, tfam, (xtb_data *) 0); xtb_ti_get(real_info->af_family, afam, (xtb_data *) 0); xtb_ti_get(real_info->tf_size, tsizstr, (xtb_data *) 0); if (sscanf(tsizstr, "%lf", &tsize) == 1) { xtb_ti_get(real_info->af_size, asizstr, (xtb_data *) 0); if (sscanf(asizstr, "%lf", &asize) == 1) { /* Got all the info */ if (dev_p) { dev_spec = (char *) 0; } else { dev_spec = hard_devices[val].dev_spec; } do_hardcopy(real_info->prog, real_info->cookie, hard_devices[val].dev_init, dev_spec, file_or_dev, centimeters, tfam, tsize, afam, asize); rtn = XTB_STOP; } else { /* Bad axis size */ do_error("Bad axis font size\n"); rtn = XTB_HANDLED; } } else { /* Bad title size */ do_error("Bad title font size\n"); rtn = XTB_HANDLED; } } else { /* Bad max dimension */ do_error("Bad maximum dimension\n"); rtn = XTB_HANDLED; } } else { /* Bad device spec */ do_error("Must specify `To File' or `To Device'\n"); rtn = XTB_HANDLED; } } else { /* Bad value spec */ do_error("Must specify an output device\n"); rtn = XTB_HANDLED; } (void) xtb_bt_set(win, 0, (xtb_data) 0); return rtn; } /*ARGSUSED*/ static xtb_hret can_fun(win, val, info) Window win; /* Button window */ int val; /* Button value */ xtb_data info; /* Local button info */ /* * This is the handler function for the cancel button. It * turns itself on and off and then exits with a status * which kills the dialog. */ { (void) xtb_bt_set(win, 1, (xtb_data) 0); (void) xtb_bt_set(win, 0, (xtb_data) 0); return XTB_STOP; } static xtb_hret dev_fun(win, old, new, info) Window win; /* Button row window */ int old; /* Previous button */ int new; /* Current button */ xtb_data info; /* User data */ /* * This routine swaps the device specific information * in the dialog based on what device is selected. The * information passed is the information for the whole * dialog. */ { struct d_info *data = (struct d_info *) info; char text[MAXCHBUF]; int fod_spot; fod_spot = xtb_br_get(data->fod); if ((old >= 0) && (old < hard_count)) { /* Save old info */ xtb_ti_get(data->fodspec, text, (xtb_data *) 0); if (fod_spot == 1) { strncpy(hard_devices[old].dev_file, text, MFNAME-1); } else if (fod_spot == 0) { strncpy(hard_devices[old].dev_printer, text, MFNAME-1); } xtb_ti_get(data->dimspec, text, (xtb_data *) 0); if (sscanf(text, "%lf", &hard_devices[old].dev_max_dim) != 1) { do_error("Warning: can't read maximum dimension"); } xtb_ti_get(data->tf_family, text, (xtb_data *) 0); strncpy(hard_devices[old].dev_title_font, text, MFNAME-1); xtb_ti_get(data->tf_size, text, (xtb_data *) 0); if (sscanf(text, "%lf", &hard_devices[old].dev_title_size) != 1) { do_error("Warning: can't read title font size"); } xtb_ti_get(data->af_family, text, (xtb_data *) 0); strncpy(hard_devices[old].dev_axis_font, text, MFNAME-1); xtb_ti_get(data->af_size, text, (xtb_data *) 0); if (sscanf(text, "%lf", &hard_devices[old].dev_axis_size) != 1) { do_error("Warning: can't read axis font size"); } } /* Insert new info */ if ((new >= 0) && (new < hard_count)) { if (fod_spot == 1) { xtb_ti_set(data->fodspec, hard_devices[new].dev_file, (xtb_data) 0); } else if (fod_spot == 0) { xtb_ti_set(data->fodspec, hard_devices[new].dev_printer, (xtb_data) 0); } else { xtb_ti_set(data->fodspec, "", (xtb_data) 0); } (void) sprintf(text, "%lg", hard_devices[new].dev_max_dim); xtb_ti_set(data->dimspec, text, (xtb_data) 0); xtb_ti_set(data->tf_family, hard_devices[new].dev_title_font, (xtb_data) 0); (void) sprintf(text, "%lg", hard_devices[new].dev_title_size); xtb_ti_set(data->tf_size, text, (xtb_data) 0); xtb_ti_set(data->af_family, hard_devices[new].dev_axis_font, (xtb_data) 0); (void) sprintf(text, "%lg", hard_devices[new].dev_axis_size); xtb_ti_set(data->af_size, text, (xtb_data) 0); } return XTB_HANDLED; } static xtb_hret fd_fun(win, old, new, info) Window win; /* Button row window */ int old; /* Previous button */ int new; /* Current button */ xtb_data info; /* User data */ /* * This routine swaps the default file or device names * based on the state of the file or device buttons. * The information passed is the information for the whole * dialog. */ { struct d_info *data = (struct d_info *) info; char text[MAXCHBUF]; int which_one; which_one = xtb_br_get(data->choices); if ((which_one >= 0) && (which_one < hard_count)) { if (old == 0) { /* Save into device space */ xtb_ti_get(data->fodspec, text, (xtb_data *) 0); strncpy(hard_devices[which_one].dev_printer, text, MFNAME-1); } else if (old == 1) { /* Save into file space */ xtb_ti_get(data->fodspec, text, (xtb_data *) 0); which_one = xtb_br_get(data->choices); strncpy(hard_devices[which_one].dev_file, text, MFNAME-1); } if (new == 0) { /* Restore into device */ xtb_ti_set(data->fodspec, hard_devices[which_one].dev_printer, (xtb_data *) 0); } else if (new == 1) { xtb_ti_set(data->fodspec, hard_devices[which_one].dev_file, (xtb_data *) 0); } } return XTB_HANDLED; } /* Indices for frames made in make_dialog */ enum d_frames_defn { TITLE_F, ODEVLBL_F, ODEVROW_F, DISPLBL_F, DISPROW_F, FDLBL_F, FDINP_F, OPTLBL_F, MDIMLBL_F, MDIMI_F, TFLBL_F, TFFAMLBL_F, TFFAM_F, TFSIZLBL_F, TFSIZ_F, AFLBL_F, AFFAMLBL_F, AFFAM_F, AFSIZLBL_F, AFSIZ_F, OK_F, CAN_F, BAR_F, LAST_F } d_frames; #define AF(ix) af[(int) (ix)] #define BAR_SLACK 10 static void make_dialog(win, spawned, prog, cookie, okbtn, frame) Window win; /* Parent window */ Window spawned; /* Spawned from window */ char *prog; /* Program name */ xtb_data cookie; /* Info for do_hardcopy */ xtb_frame *okbtn; /* Frame for OK button */ xtb_frame *frame; /* Returned window/size */ /* * This routine constructs a new dialog for asking the user about * hardcopy devices. The dialog and its size is returned in * `frame'. The window of the `ok' button is returned in `btnwin'. * This can be used to reset some of the button state to reuse the dialog. */ { Window overall; xtb_frame AF(LAST_F); xtb_fmt *def, *cntrl, *mindim, *tfarea, *afarea; Cursor diag_cursor; XColor fg_color, bg_color; XSizeHints hints; unsigned long wamask; XSetWindowAttributes wattr; struct d_info *info; int i, found, max_width; char **names; static char *fodstrs[] = { "To Device", "To File" }; wamask = ux11_fill_wattr(&wattr, CWBackPixel, bgPixel, CWBorderPixel, bdrPixel, CWOverrideRedirect, True, CWSaveUnder, True, CWColormap, cmap, UX11_END); overall = XCreateWindow(disp, win, 0, 0, 1, 1, D_BRDR, depth, InputOutput, vis, wamask, &wattr); frame->win = overall; frame->width = frame->height = frame->x_loc = frame->y_loc = 0; XStoreName(disp, overall, "Hardcopy Dialog"); XSetTransientForHint(disp, spawned, overall); info = (struct d_info *) malloc(sizeof(struct d_info)); info->prog = prog; info->cookie = cookie; /* Make all frames */ xtb_to_new(overall, "Hardcopy Options", titleFont, &AF(TITLE_F)); xtb_to_new(overall, "Output device:", axisFont, &AF(ODEVLBL_F)); found = -1; names = (char **) malloc((unsigned) (sizeof(char *) * hard_count)); for (i = 0; i < hard_count; i++) { names[i] = hard_devices[i].dev_name; if (strcmp(Odevice, names[i]) == 0) { found = i; } } xtb_br_new(overall, hard_count, names, found, dev_fun, (xtb_data) info, &AF(ODEVROW_F)); info->choices = AF(ODEVROW_F).win; xtb_to_new(overall, "Disposition:", axisFont, &AF(DISPLBL_F)); found = -1; for (i = 0; i < 2; i++) { if (strcmp(Odisp, fodstrs[i]) == 0) { found = i; } } xtb_br_new(overall, 2, fodstrs, found, fd_fun, (xtb_data) info, &AF(DISPROW_F)); info->fod = AF(DISPROW_F).win; xtb_to_new(overall, "File or Device Name:", axisFont, &AF(FDLBL_F)); xtb_ti_new(overall, OfileDev, D_INP, df_fun, (xtb_data) 0, &AF(FDINP_F)); info->fodspec = AF(FDINP_F).win; xtb_to_new(overall, "Optional Parameters", titleFont, &AF(OPTLBL_F)); xtb_to_new(overall, "Maximum Dimension (cm):", axisFont, &AF(MDIMLBL_F)); xtb_ti_new(overall, "", D_DSP, df_fun, (xtb_data) 0, &AF(MDIMI_F)); info->dimspec = AF(MDIMI_F).win; xtb_to_new(overall, "Title Font", axisFont, &AF(TFLBL_F)); xtb_to_new(overall, "Family:", axisFont, &AF(TFFAMLBL_F)); xtb_ti_new(overall, "", MFNAME, df_fun, (xtb_data) 0, &AF(TFFAM_F)); info->tf_family = AF(TFFAM_F).win; xtb_to_new(overall, "Size (pnts):", axisFont, &AF(TFSIZLBL_F)); xtb_ti_new(overall, "", D_FS, df_fun, (xtb_data) 0, &AF(TFSIZ_F)); info->tf_size = AF(TFSIZ_F).win; xtb_to_new(overall, "Axis Font", axisFont, &AF(AFLBL_F)); xtb_to_new(overall, "Family:", axisFont, &AF(AFFAMLBL_F)); xtb_ti_new(overall, "", MFNAME, df_fun, (xtb_data) 0, &AF(AFFAM_F)); info->af_family = AF(AFFAM_F).win; xtb_to_new(overall, "Size (pnts):", axisFont, &AF(AFSIZLBL_F)); xtb_ti_new(overall, "", D_FS, df_fun, (xtb_data) 0, &AF(AFSIZ_F)); info->af_size = AF(AFSIZ_F).win; xtb_bt_new(overall, " Ok ", ok_fun, (xtb_data) info, &AF(OK_F)); xtb_bt_new(overall, "Cancel", can_fun, (xtb_data) 0, &AF(CAN_F)); /* Dividing bar */ max_width = 0; for (i = 0; i < ((int) BAR_F); i++) { if (AF(i).width > max_width) max_width = AF(i).width; } xtb_bk_new(overall, max_width - BAR_SLACK, 1, &AF(BAR_F)); /* Set device specific info */ (void) dev_fun(info->choices, -1,xtb_br_get(info->choices),(xtb_data) info); (void) fd_fun(info->fod, -1, xtb_br_get(info->fod), (xtb_data) info); /* * Now place elements - could make this one expression but pcc * is too wimpy. */ cntrl = xtb_vert(XTB_LEFT, D_VPAD, D_INT, xtb_hort(XTB_CENTER, D_HPAD, D_INT, xtb_w(&AF(ODEVLBL_F)), xtb_w(&AF(ODEVROW_F)), NE), xtb_hort(XTB_CENTER, D_HPAD, D_INT, xtb_w(&AF(DISPLBL_F)), xtb_w(&AF(DISPROW_F)), NE), xtb_hort(XTB_CENTER, D_HPAD, D_INT, xtb_w(&AF(FDLBL_F)), xtb_w(&AF(FDINP_F)), NE), NE); mindim = xtb_vert(XTB_LEFT, D_VPAD, D_INT, xtb_hort(XTB_CENTER, D_HPAD, D_INT, xtb_w(&AF(MDIMLBL_F)), xtb_w(&AF(MDIMI_F)), NE), NE); tfarea = xtb_vert(XTB_LEFT, D_VPAD, D_INT, xtb_hort(XTB_CENTER, D_HPAD, D_INT, xtb_w(&AF(TFFAMLBL_F)), xtb_w(&AF(TFFAM_F)), xtb_w(&AF(TFSIZLBL_F)), xtb_w(&AF(TFSIZ_F)), NE), NE); afarea = xtb_vert(XTB_LEFT, D_VPAD, D_INT, xtb_hort(XTB_CENTER, D_HPAD, D_INT, xtb_w(&AF(AFFAMLBL_F)), xtb_w(&AF(AFFAM_F)), xtb_w(&AF(AFSIZLBL_F)), xtb_w(&AF(AFSIZ_F)), NE), NE); def = xtb_fmt_do (xtb_vert(XTB_CENTER, D_VPAD, D_INT, xtb_w(&AF(TITLE_F)), cntrl, xtb_w(&AF(BAR_F)), xtb_w(&AF(OPTLBL_F)), mindim, xtb_w(&AF(TFLBL_F)), tfarea, xtb_w(&AF(AFLBL_F)), afarea, xtb_hort(XTB_CENTER, D_HPAD, D_INT, xtb_w(&AF(OK_F)), xtb_w(&AF(CAN_F)), NE), NE), &frame->width, &frame->height); xtb_mv_frames(LAST_F, af); xtb_fmt_free(def); /* Make window large enough to contain the info */ XResizeWindow(disp, overall, frame->width, frame->height); hints.flags = PSize; hints.width = frame->width; hints.height = frame->height; XSetNormalHints(disp, overall, &hints); diag_cursor = XCreateFontCursor(disp, XC_dotbox); fg_color.pixel = normPixel; XQueryColor(disp, cmap, &fg_color); bg_color.pixel = bgPixel; XQueryColor(disp, cmap, &bg_color); XRecolorCursor(disp, diag_cursor, &fg_color, &bg_color); XDefineCursor(disp, overall, diag_cursor); frame->width += (2 * D_BRDR); frame->height += (2 * D_BRDR); *okbtn = AF(OK_F); } #ifdef SHADOW Window make_shadow(w, h) int w, h; /* * Makes a shadow window for a pop-up window of the specified size. * Needs hint work as well. Try no background window. */ { Window shadow; Bitmap gray_bm; Pixmap gray_pm; gray_bm = XStoreBitmap(gray_width, gray_height, gray_bits); gray_pm = XMakePixmap(gray_bm, normPixel, bgPixel); shadow = XCreateWindow(RootWindow, 0, 0, w, h, 0, BlackPixmap, gray_pm); XFreePixmap(gray_pm); XFreeBitmap(gray_bm); return shadow; } #endif #define SH_W 5 #define SH_H 5 void ho_dialog(parent, prog, cookie) Window parent; /* Parent window */ char *prog; /* Program name */ xtb_data cookie; /* Info passed to do_hardcopy */ /* * Asks the user about hardcopy devices. A table of hardcopy * device names and function pointers to their initialization * functions is assumed to be in the global `hard_devices' and * `hard_count'. Returns a non-zero status if the dialog was * sucessfully posted. Calls do_hardcopy in xgraph to actually * output information. */ { static Window shadow, dummy; static xtb_frame overall = { (Window) 0, 0, 0, 0, 0 }; static xtb_frame okbtn; XEvent evt; XWindowAttributes winInfo; XSizeHints hints; struct d_info *info; if (!overall.win) { make_dialog(RootWindow(disp, screen), parent, prog, cookie, &okbtn, &overall); #ifdef SHADOW shadow = make_shadow(d_w, d_h); #endif } else { /* Change the button information */ (void) xtb_bt_get(okbtn.win, (xtb_data *) &info); info->prog = prog; info->cookie = cookie; } XGetWindowAttributes(disp, parent, &winInfo); XTranslateCoordinates(disp, parent, RootWindow(disp, screen), 0, 0, &winInfo.x, &winInfo.y, &dummy); XMoveWindow(disp, overall.win, (int) (winInfo.x + winInfo.width/2 - overall.width/2), (int) (winInfo.y + winInfo.height/2 - overall.height/2)); hints.flags = PPosition; hints.x = winInfo.x + winInfo.width/2 - overall.width/2; hints.y = winInfo.y + winInfo.height/2 - overall.height/2; XSetNormalHints(disp, overall.win, &hints); #ifdef SHADOW XMoveWindow(disp, shadow, winInfo.x + winInfo.width/2 - d_w/2 + SH_W, winInfo.y + winInfo.height/2 - d_h/2 + SH_H); hints.flags = PPosition; hints.x = winInfo.x + winInfo.width/2 - d_w/2 + SH_W; hints.y = winInfo.y + winInfo.height/2 - d_h/2 + SH_H; XSetNormalHints(disp, shadow, &hints); XRaiseWindow(disp, shadow); XMapWindow(disp, shadow); #endif XRaiseWindow(disp, overall.win); XMapWindow(disp, overall.win); do { XNextEvent(disp, &evt); } while (xtb_dispatch(&evt) != XTB_STOP); XUnmapWindow(disp, overall.win); #ifdef SHADOW XUnmapWindow(disp, shadow); #endif } /*ARGSUSED*/ static xtb_hret err_func(win, bval, info) Window win; /* Button window */ int bval; /* Button value */ xtb_data info; /* Local button info */ /* * Handler function for button in error box. Simply stops dialog. */ { (void) xtb_bt_set(win, 1, (xtb_data) 0); (void) xtb_bt_set(win, 0, (xtb_data) 0); return XTB_STOP; } typedef struct err_info { Window title; Window contbtn; int num_lines; int alloc_lines; Window *lines; }; #define E_LINES 2 #define E_VPAD 3 #define E_HPAD 3 #define E_INTER 1 static void make_err_box(text, title, frame) char *text; /* Error text */ char *title; /* Title text */ xtb_frame *frame; /* Returned frame */ /* * Makes an error box with a title. */ { XSizeHints hints; struct err_info *new_info; xtb_frame tf, cf, lf; char *lineptr, *line; int y, i; unsigned long wamask; XSetWindowAttributes wattr; wamask = ux11_fill_wattr(&wattr, CWBackPixel, bgPixel, CWBorderPixel, bdrPixel, CWOverrideRedirect, True, CWSaveUnder, True, CWColormap, cmap, UX11_END); frame->win = XCreateWindow(disp, RootWindow(disp, screen), 0, 0, 1, 1, D_BRDR, depth, InputOutput, vis, wamask, &wattr); frame->x_loc = frame->y_loc = frame->width = frame->height = 0; XStoreName(disp, frame->win, "Error Dialog"); XSetTransientForHint(disp, RootWindow(disp, screen), frame->win); new_info = (struct err_info *) malloc((unsigned) sizeof(struct err_info)); xtb_to_new(frame->win, title, titleFont, &tf); new_info->title = tf.win; if (tf.width > frame->width) frame->width = tf.width; xtb_bt_new(frame->win, "Continue", err_func, (xtb_data) 0, &cf); new_info->contbtn = cf.win; if (cf.width > frame->width) frame->width = cf.width; new_info->alloc_lines = E_LINES; new_info->num_lines = 0; new_info->lines = (Window *) malloc((unsigned) (sizeof(Window) * E_LINES)); lineptr = text; while (getline(&lineptr, &line)) { if (new_info->num_lines >= new_info->alloc_lines) { new_info->alloc_lines *= 2; new_info->lines = (Window *) realloc((char *) new_info->lines, (unsigned) new_info->alloc_lines); } xtb_to_new(frame->win, line, axisFont, &lf); new_info->lines[new_info->num_lines] = lf.win; new_info->num_lines += 1; if (lf.width > frame->width) frame->width = lf.width; } /* Placement */ frame->width += (2 * E_HPAD); y = E_VPAD; /* Title */ XMoveWindow(disp, new_info->title, (int) (frame->width/2 - tf.width/2), y); y += (tf.height + E_INTER); /* All lines */ for (i = 0; i < new_info->num_lines; i++) { XMoveWindow(disp, new_info->lines[i], E_HPAD, y); y += (lf.height + E_INTER); } /* Button */ XMoveWindow(disp, new_info->contbtn, (int) (frame->width/2 - cf.width/2), y); y += (cf.height + E_INTER); /* Make dialog the right size */ y += (E_VPAD - E_INTER); XResizeWindow(disp, frame->win, frame->width, (unsigned int) y); hints.flags = PSize; hints.width = frame->width; hints.height = (unsigned int) y; XSetNormalHints(disp, frame->win, &hints); frame->width += (2 * D_BRDR); frame->height = y + (2 * D_BRDR); xtb_register(frame->win, (xtb_hret (*)()) 0, (xtb_data) new_info); } void do_error(err) char *err; /* * This posts a dialog that contains lines of text and a continue * button. The text may be multiple lines. The dialog is remade * each time. */ { Window shadow; XWindowAttributes info; XEvent evt; XSizeHints hints; xtb_frame err_frame; make_err_box(err, "XGraph Error", &err_frame); #ifdef SHADOW shadow = make_shadow(w, h); #endif XGetWindowAttributes(disp, RootWindow(disp, screen), &info); XMoveWindow(disp, err_frame.win, (int) (info.width/2 - err_frame.width/2), (int) (info.height/2 - err_frame.height/2)); hints.flags = PPosition; hints.x = info.width/2 - err_frame.width/2; hints.y = info.height/2 - err_frame.height/2; XSetNormalHints(disp, err_frame.win, &hints); #ifdef SHADOW XMoveWindow(disp, shadow, info.width/2 - w/2 + SH_W, info.height/2 - h/2 + SH_H); hints.flags = PPosition; hints.x = info.width/2 - w/2 + SH_W; hints.y = info.height/2 - h/2 + SH_H; XSetNormalHints(disp, err_frame.win, &hints); XRaiseWindow(disp, shadow); XMapWindow(disp, shadow); #endif XRaiseWindow(disp, err_frame.win); XMapWindow(disp, err_frame.win); do { XNextEvent(disp, &evt); } while (xtb_dispatch(&evt) != XTB_STOP); #ifdef SHADOW XDestroyWindow(disp, shadow); #endif del_err_box(err_frame.win); } int getline(tptr, lptr) char **tptr; char **lptr; /* * Returns next line from tptr. The text of tptr is changed! */ { *lptr = *tptr; while (**tptr && (**tptr != '\n')) { (*tptr)++; } if (**tptr == '\n') { **tptr = '\0'; (*tptr)++; return 1; } else { return 0; } } static void del_err_box(err) Window err; /* * Deletes all components of an error */ { struct err_info *info; char *dummy; int i; if (xtb_unregister(err, (xtb_data *) &info)) { xtb_to_del(info->title); xtb_bt_del(info->contbtn, (xtb_data *) &dummy); for (i = 0; i < info->num_lines; i++) { xtb_to_del(info->lines[i]); } free((char *) info->lines); free((char *) info); XDestroyWindow(disp, err); } } \End\Of\Shar\ else echo "will not over write ./xgraph-11/dialog.c" fi echo "Finished archive 6 of 6"