1 /*
2  *   Copyright (C) 1989-1992 Yale University
3  *
4  *   This work is distributed in the hope that it will be useful; you can
5  *   redistribute it and/or modify it under the terms of the
6  *   GNU General Public License as published by the Free Software Foundation;
7  *   either version 2 of the License,
8  *   or any later version, on the following conditions:
9  *
10  *   (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS
11  *   ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE,
12  *   SALE OR
13  *   OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY
14  *   PATENT OR
15  *   OTHER RIGHTS NOT VESTED IN YALE.
16  *
17  *   (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND
18  *   WARRANTIES
19  *   WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED,
20  *   INCLUDING,
21  *   BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
22  *   PARTICULAR
23  *   PURPOSE.
24  *
25  *   (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES
26  *   WHATSOEVER TO
27  *   ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN
28  *   ARTICLE
29  *   (a) AND (b) above.
30  *
31  *   (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS,
32  *   EMPLOYEES AND
33  *   AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR
34  *   INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE
35  *   ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE
36  *   POSSIBILITY OF THE FOREGOING.
37  *
38  */
39 
40 /* -----------------------------------------------------------------
41 FILE:	    draw.c
42 DESCRIPTION:graphic drawing routine both screen and file.
43     ********************************************************
44     THERE ARE TWO FAMILIES OF ROUTINES IN THIS MODULE
45     1) Graphic routines that write to the CRT screen
46     2) Routines which write to a set of binary file later
47 	to be drawn by an independent program.
48     The user can select whether he wants either of the routines
49 	or both.
50     ********************************************************
51 DATE:	    Jan 25, 1989 - major rewrite of version 1.0
52 CONTENTS:   BOOL TWcheckServer()
53 	    TWsetMode( mode )
54 		INT mode ;
55 	    BOOL TWinitGraphics(argc,argv,numC,colors,dumpOnly,menu,refresh_func)
56 		INT  argc, numC, (*refresh_func)() ;
57 		char *argv[], **colors ;
58 		BOOL dumpOnly ;
59 		TWMENUPTR menu ;
60 	    BOOL TWinitParasite(argc,argv,numC,colors,dumpOnly,menu,refresh_func,w)
61 		INT  argc, numC, (*refresh_func)() ;
62 		char *argv[], **colors ;
63 		BOOL dumpOnly ;
64 		TWMENUPTR menu ;
65 		Window w ;
66 	    static BOOL TWinit(argc,argv,numC,desiredColors,dumpOnly,
67 		menu,refresh_func)
68 		INT  argc, numC, (*refresh_func)() ;
69 		char *argv[], **colors ;
70 		BOOL dumpOnly ;
71 		TWMENUPTR menu ;
72 	    TWINFOPTR TWgetDrawInfo()
73 	    TWsetDrawInfo( winheight, winwidth )
74 		INT winheight, winwidth ;
75 	    TWcloseGraphics()
76 	    TWzoom()
77 	    TWfullView()
78 	    TWsetwindow( left, bottom, right, top )
79 		INT left, bottom, right, top ;
80 	    TWtranslate()
81 	    TWflushFrame()
82 	    TWsync()
83 	    static void initcolors( desiredColorArray, numC )
84 		char **desiredColorArray ;
85 		INT  numC ;
86 	    static startDFrame()
87 	    static VOID drawDLine(ref,x1,y1,x2,y2,color,label)
88 		INT	ref, color ;
89 		register INT	x1,y1,x2,y2 ;
90 		char	*label ;
91 	    static VOID drawDRect(ref,x1,y1,x2,y2,color,label)
92 		INT	ref, color ;
93 		register INT	x1,y1,x2,y2 ;
94 		char	*label ;
95 	    TWarb_init()
96 	    TWarb_addpt( xpos, ypos )
97 		INT xpos, ypos ;
98 	    static VOID drawDArb( ref, color, label )
99 		INT	ref, color ;
100 		char	*label ;
101 	    TWhighLightRect( x1,y1,x2,y2 )
102 		register INT	x1,y1,x2,y2 ;
103 	    TWmoveRect( x1, y1, x2, y2, ptx, pty )
104 		INT *x1, *y1, *x2, *y2, ptx, pty ;
105 	    static XFontStruct *TWgetfont( fname, font )
106 		Font *font ;
107 	    TWstartFrame()
108 	    static closeFrame()
109 	    TWsetFrame( number )
110 		INT number ;
111 	    static drawWLine( ref_num,x1,y1,x2,y2,color,label)
112 		INT     ref_num ;
113 		INT	x1,y1,x2,y2,color ;
114 		char	*label;
115 	    static drawWRect( ref_num, x1,y1,x2,y2,color,label)
116 		INT     ref_num ;
117 		INT	x1,y1,x2,y2, color;
118 		char	*label;
119 	    static drawWArb( ref, color, label )
120 		INT	ref, color ;
121 		char	*label ;
122 REVISIONS:  Jan 31, 1989 - added screen routines.
123 	    Feb 21, 1989 - initial graphic routines.
124 	    Feb 27, 1989 - added no graphics conditional compile.
125 	    Mar 22, 1989 - made TWdrawCell and TWdrawRect separate
126 		routines.  Added info.h TWinitGraphics now returns
127 		a BOOLEAN value on whether it was successful.
128 	    Mar 23, 1989 - made program exit if problem.  Also fixed
129 		pointer problem on foreign machines.
130 	    Apr  1, 1989 - fixed black/white stipple pattern problem.
131 		Added parasite mechanism which allows another program
132 		to access main window.
133 	    Apr  9, 1989 - handle change of mode correctly now.
134 	    Apr 16, 1989 - added XGetDefaults to get user defined
135 		screen position.
136 	    Apr 27, 1989 - update for Y routines.
137 	    May 11, 1989 - fixed parasite problem.
138 	    Sep 23, 1989 - added color switch for TWtoggleColor()
139 	    Oct  2, 1989 - menus now can be compiled into program.
140 	    Nov 15, 1989 - TWsetFrame now can reset to last frame.
141 	    Mar  3, 1990 - added zoom out and removed clear screen
142 		in parasite mode.
143 	    Aug  1, 1990 - rewrote to be MOTIF compatible.
144 	    Sep 25, 1990 - fixed B&W mode. Made 9x15 default font.
145 	    Oct  5, 1990 - rewrote using prototypes.  Added
146 		TWcolorXOR.  Fixed problem with TWfullview.
147 		Also added dumpOnly mode.  Added arbitrary rectangle
148 		drawing.
149 	    Oct 12, 1990 - rewrote draw routines to use 4 windows
150 		and added pixmap for fast redraws.  Also added
151 		TWforceRedraw.
152 	    Oct 14, 1990 - fixed parasite and dump arbitrary figures.
153 	    Oct 21, 1990 - fixed parasite resizing.
154 	    Nov  4, 1990 - added Xdefault bw.
155 	    Dec  5, 1990 - added stipple to info record.
156 	    Mon Jan  7 18:17:44 CST 1991 - made SAFE_WAIT_TIME
157 		user programmable for slow machines.
158 	    Sun Feb 17 17:12:39 EST 1991 - added 3D graphics functions.
159 	    Fri Feb 22 23:38:02 EST 1991 - fixed sensitivity of
160 		3D camera.
161 	    Sat Feb 23 04:57:21 EST 1991 - fixed a very pesky bug with
162 		the pixmap.
163 	    Thu Mar  7 01:26:04 EST 1991 - now store the refresh function.
164 	    Thu Apr 18 00:36:25 EDT 1991 - fixed argument to refresh
165 		function and fixed sun XOR.
166 	    Sun Apr 28 22:06:15 EDT 1991 - set colors right for
167 		reverse video.
168 	    Wed May  1 18:55:13 EDT 1991 - added TWget_arb_fill.
169 	    Mon Aug 12 15:52:55 CDT 1991 - added rectangular
170 		fill switch.
171 	    Sun Nov  3 12:51:46 EST 1991 - fixed gcc complaints.
172 	    Sun Jan 26 03:38:49 EST 1992 - fixed window manager hint problem.
173 	    Thu Mar  5 17:01:09 EST 1992 - added clipping for faster draw
174 		during zoom.
175 ----------------------------------------------------------------- */
176 
177 #ifndef NOGRAPHICS
178 
179 #include <stdio.h>
180 #include <string.h>
181 #include <X11/Xlib.h>
182 #include <X11/Xatom.h>
183 #include <X11/Xutil.h>
184 
185 #include <yalecad/base.h>
186 #include <yalecad/file.h>
187 #include <yalecad/message.h>
188 #include <yalecad/hash.h>
189 #include <yalecad/string.h>
190 #include <yalecad/draw.h>
191 #include <yalecad/debug.h>
192 #include <yalecad/buster.h>
193 #include <yalecad/dbinary.h>
194 #include <yalecad/project.h>
195 #include <yalecad/program.h>
196 #include <yalecad/menus.h>
197 
198 #define YDRAW_VARS
199 #include "info.h"
200 
201 #define EXPECTEDCOLORS  201  /* expected number of colors in table */
202 #define NODIRECTORY     1
203 #define NOINIT          2
204 
205 #define OBSCURED	(1)
206 #define UNOBSCURED	(0)
207 
208 /* the place where these graphic contexts are stored */
209 #define HIGHLITE   	(0)
210 #define WHITE    	(1)
211 #define BLACK   	(2)
212 
213 #define DIV_2           >> 1
214 
215 /****  THE MODES AND CHOICES *******/
216 static  INT        modeS ; /* determines which mode we are in */
217 
218 /* the global routines - seen by outside world */
219 VOID (*_TWdrawRect)(P7( INT ref_num, INT x1, INT y1, INT x2, INT y2, INT color,
220 		    char *label )) ;
221 VOID (*_TWdrawLine)(P7( INT ref_num, INT x1, INT y1, INT x2, INT y2, INT color,
222 		    char *label )) ;
223 VOID (*_TWdrawArb)(P3( INT ref_num, INT color, char *label )) ;
224 
225 
226 /* the local routines seen by the routines in this file only */
227 static VOID drawDRect() ;
228 static VOID drawWRect() ;
229 static VOID drawDArb() ;
230 static VOID drawWArb() ;
231 static VOID drawDLine() ;
232 static VOID drawWLine() ;
233 static VOID initcolors( P2(char **desiredColorArray,INT  numC ) ) ;
234 static void closeFrame(P1(void)) ;
235 static VOID set_viewing_transformation() ;
236 extern VOID TW3Dperspective( P5(DOUBLE x, DOUBLE y, DOUBLE z,
237     DOUBLE *pX, DOUBLE *pY ) ) ;
238 static BOOL TWinit( P7(INT argc,char *argv[],INT numC,char **desiredColors,
239 		    BOOL dumpOnly, TWMENUPTR menu, INT (*refresh_func)() ) ) ;
240 static VOID set_clip_window( P4(INT l, INT r, INT b, INT t) ) ;
241 
242 /********** THE CRT ROUTINE STATIC DEFINITIONS *************/
243 static TWINFO      infoBoxS ;          /* information for other modules*/
244 static XColor      *colorArrayS ;      /* array of color available */
245 static GC          *graphicContextS ;  /* array of color contexts */
246 static INT         numColorS;          /* the number of colors in table */
247 static INT         borderColorS=BLACK; /* the default border color */
248 static Display     *dpyS;              /* the display connection */
249 static Window      backS;              /* the back window */
250 static Window      drawS;              /* the current window */
251 static Window      parentS;            /* the parent window */
252 static Colormap    cmapS ;             /* default color map */
253 static Pixmap      pixmapS ;           /* offscreen copy of data */
254 static INT         screenS;            /* the current screen */
255 static Font        fontS ;             /* selected font */
256 static XFontStruct *fontinfoS ;        /* font information */
257 static BOOL        fullViewS ;         /* used for zoom window */
258 static BOOL        dumpOnlyS ;         /* if TRUE only dump to file */
259 static BOOL        reverseS = FALSE;   /* reverse video */
260 static BOOL        parasiteS ;          /* this process is a parasite? */
261 static BOOL        colorS ;            /* color display ??? */
262 static BOOL        stippleS = FALSE ;  /* stipple pattern on */
263 static BOOL        displayOpenS=FALSE; /* display has been opened ??? */
264 static BOOL        *colorOnS ;         /* is color turned on ??? */
265 static BOOL        fillArbS = TRUE ;   /* whether to fill arbitrary figures */
266 static BOOL        rect_fillS = TRUE ; /* whether to fill rectangle */
267 static char        **userColorS ;      /* colors user gave us */
268 
269 /* FOR 3D perspective routines */
270 static BOOL	   perspectiveS;    	/* perspective toggle flag */
271 static DOUBLE      phiS, thetaS, rhoS;  /* 3D view point parameters */
272 static DOUBLE      radiansPerDegreeS;
273 static DOUBLE      v11S, v12S, v13S,
274                    v21S, v22S, v23S,
275                          v32S, v33S,
276 		               v43S;
277 
278 /*
279  * Initial Window Postion & Dimensions for half screen.
280  */
281 #define INT_WIDTH	(500)
282 #define INT_HEIGHT	(500)
283 #define INT_X		(1)
284 #define INT_Y		(1)
285 static DOUBLE      scaleFactorS = 1.0 ;/* scale data to screen dim.*/
286 static INT         xoffsetS ;          /* data offset to x screen dim.*/
287 static INT         yoffsetS ;          /* data offset to y screen dim.*/
288 static DOUBLE      oldscaleFactorS ;   /* remember old for zoom */
289 static INT         oldxoffsetS ;       /* remember x for zoom return */
290 static INT         oldyoffsetS ;       /* remember y for zoom return */
291 static unsigned int winwidthS ;        /* draw window width in pixels */
292 static unsigned int winheightS ;       /* draw window height in pixels */
293 static int 	   winxS ;             /* window origin x from ul */
294 static int         winyS ;             /* window origin y from ul */
295 static INT         leftS ;             /* left of user data */
296 static INT         rightS ;            /* right of user data */
297 static INT         topS ;              /* top of user data */
298 static INT         bottomS ;           /* bottom of user data */
299 static INT lS, rS, bS, tS ;            /* current user data */
300 static INT arblS, arbrS, arbbS, arbtS ;/* current user data */
301 /* used to draw arbitrary rectilinear shapes */
302 #define EXPECTEDPTS 12
303 static INT numptS ;          /* current number of points */
304 static INT ptAllocS = 0 ;    /* size of point array */
305 static XPoint *ptS = NIL(XPoint *) ; /* array of pts for arb figure */
306 
307 
308 
309 /********** STATIC DEFINITIONS FOR MIXED FUNCTIONS *************/
310 static  char *dirNameS ;      /* pathname including DATA directory */
311 static  BOOL initS = FALSE ;  /* tells whether initialization performed */
312 static  INT  frameCountS ;    /* current number of display frames */
313 static  BOOL frameOpenS ;     /* tells whether frame files are open */
314 
TWcheckServer()315 BOOL TWcheckServer()
316 {
317     char *hostmon ;
318     char *Ygetenv() ;
319 
320     /* get host name from environment variable */
321     if(!(hostmon = Ygetenv("DISPLAY"))) {
322 	M( WARNMSG,"TWcheckServer","Cannot get DISPLAY environment variable\n");
323 	return( FALSE ) ;
324     }
325     /* open display */
326     if(!(dpyS = XOpenDisplay(hostmon))) {
327 	M( WARNMSG,"TWcheckServer","Cannot connect to X server\n");
328 	return( FALSE ) ;
329     } else {
330 	XCloseDisplay( dpyS ) ;
331     }
332     return( TRUE ) ;
333 } /* end TWcheckServer */
334 
TWsetMode(mode)335 void TWsetMode( mode )
336 INT mode ;
337 {
338     if( dumpOnlyS && mode != TWWRITEONLY ){
339 	D( "TWsetMode",
340 	    fprintf( stderr,
341 	    "Drawing mode should not be changed in dumpOnly operation\n");
342 	) ;
343 	return ;
344     }
345     modeS = mode ;
346     /* select routines */
347     /* ------------------------------------------------------
348        NOTE THAT WRITE ROUTINES ALL CHECK MODE FOR TWWRITENDRAW
349        CASE AND CALL THE DRAW ROUTINES. It is done this way
350        since write routines take alot of time anyway.
351        ALSO note that TWinitGraphic and TWcloseGraphics are
352        implemented as mixed families, since they are only called
353        once each during a run.
354        ------------------------------------------------------ */
355     switch( mode ){
356 	case TWDRAWONLY:
357 	    /* pick from the D routines */
358 	    _TWdrawRect   = drawDRect ;
359 	    _TWdrawLine   = drawDLine ;
360 	    _TWdrawArb    = drawDArb ;
361 	    break ;
362 	case TWWRITEONLY:
363 	case TWWRITENDRAW:
364 	    /* pick from the W routines */
365 	    _TWdrawRect   = drawWRect ;
366 	    _TWdrawLine   = drawWLine ;
367 	    _TWdrawArb    = drawWArb ;
368 	    break ;
369     }
370 
371 } /* end TWsetMode */
372 
373 /* start a new window system */
TWinitGraphics(argc,argv,numC,colors,dumpOnly,menu,refresh_func)374 BOOL TWinitGraphics(argc,argv,numC,colors,dumpOnly,menu,refresh_func)
375 INT argc;
376 char *argv[];
377 char **colors ;
378 BOOL dumpOnly ;
379 INT  numC ;
380 TWMENUPTR menu ;
381 INT (*refresh_func)() ;
382 {
383     parasiteS = FALSE ;
384 
385     radiansPerDegreeS = acos( (double) 0.0 ) / (double) 90.0 ;
386 
387     return(TWinit(argc,argv,numC,colors,dumpOnly,menu,refresh_func));
388 } /* end TWinitGraphics */
389 
390 /* TWinitParasite takes over windows that were already opened */
TWinitParasite(argc,argv,numC,colors,dumpOnly,menu,refresh_func,w)391 BOOL TWinitParasite(argc,argv,numC,colors,dumpOnly,menu,refresh_func,w)
392 INT argc;
393 char *argv[];
394 INT  numC ;
395 char **colors ;
396 BOOL dumpOnly ;
397 TWMENUPTR menu ;
398 INT (*refresh_func)() ;
399 INT w ;
400 {
401     parasiteS = TRUE ;
402     backS = (Window) w ;
403     return(TWinit(argc,argv,numC,colors,dumpOnly,menu,refresh_func));
404 } /* end TWinitParasite */
405 
TWinit(argc,argv,numC,desiredColors,dumpOnly,menu,refresh_func)406 static BOOL TWinit(argc,argv,numC,desiredColors,dumpOnly,menu,refresh_func)
407 INT argc;
408 char *argv[];
409 INT  numC ;
410 char **desiredColors ;
411 BOOL dumpOnly ;
412 TWMENUPTR menu ;
413 INT (*refresh_func)() ;
414 {
415 
416     XSetWindowAttributes attr;
417     XWindowAttributes wattr;
418     XEvent event ;            /* describes event */
419     char *font ;              /* user font request */
420     char *hostmon ;           /* the host name of display */
421     char *Ygetenv() ;         /* get the environment variables */
422     char *reply ;             /* get xdefaults */
423     INT depth;
424     BOOL saveflag ;
425     Window root;
426     XSizeHints hints ;	      /* setup hints for window manager */
427     char *Yfixpath() ;
428     char *winstr ; /* position of Xdefault window */
429     long event_mask ;  /* used to set input selection to window */
430     INT  m ;       /* mask for determining window position*/
431 
432     dumpOnlyS = dumpOnly ; /* save for rest of execution */
433     if(!(dirNameS = Ygetenv( "DATADIR" ))){
434 	/* find fullpathname of data directory */
435 	/* dirNameS = Yfixpath( "./DATA", FALSE ) ; */
436 	/* Continue with no data dumps;  this is okay! */
437 	dirNameS = NULL;
438     }
439 
440     /* first look for data directory */
441     if((dirNameS != NULL) && !(YdirectoryExists(dirNameS)) ){
442 	/* always send this message to the screen */
443 	saveflag = Ymessage_get_mode() ;
444 	Ymessage_mode( M_VERBOSE ) ;
445 	M(MSG, NULL,"\n\n" ) ;
446 	sprintf( YmsgG,"Not Fatal:can't find data directory:%s\n", dirNameS );
447 	M(ERRMSG,"TWinitGraphics",YmsgG ) ;
448 	M(MSG,NULL, "\tKill program and use \"setenv DATADIR <directoryPath>\" ");
449 	M(MSG,NULL, "to set data directory\n");
450 	M(MSG,NULL, "\tor allow program to continue with the inability to " ) ;
451 	M(MSG,NULL, "perform screen dumps\n");
452 	Ymessage_mode( saveflag ) ;
453 	dirNameS = NULL ;
454     }
455 
456     /* set count to zero */
457     frameCountS = 0 ;
458 
459     frameOpenS = FALSE ;
460 
461     /* -------------------------------------------------------
462 	Set the mode of the graphic routines.
463 	mode                      Function
464 	0 TWDRAWONLY      Draw graphics to screen.
465 	1 TWWRITEONLY     Write graphics to draw program binary files.
466 	2 TWWRITENDRAW    Draw graphics to screen and write draw files.
467     For mode 0 hostmon must be valid.
468     For mode 1 dataDir (path of data directory) must be valid.
469     For all modes desiredColors must be valid.
470     --------------------------------------------------------- */
471     if( dumpOnlyS ){
472 	/* we are done for the dump_graphics mode */
473 	initS = TRUE ;
474 	TWsetMode( TWWRITEONLY ) ;  /* always enable both modes */
475 	return initS;
476     } else {
477 	/* OTHERWISE INITIALIZE BOTH MODES */
478 	TWsetMode( TWWRITENDRAW ) ;  /* always enable both modes */
479     }
480     /*****  BEGIN SCREEN GRAPHICS IN THIS ROUTINE **** */
481 
482     /* get host name from environment variable */
483     if(!(hostmon = Ygetenv("DISPLAY"))) {
484 	M(ERRMSG,"TWinitGraphics","Could not get DISPLAY environment variable.\n");
485 	YexitPgm(NOINIT) ;
486     }
487     /* open display */
488     if(!(dpyS = XOpenDisplay(hostmon))) {
489 	M(ERRMSG,"TWinitGraphics","Could not connect to X server.\n");
490 	YexitPgm(NOINIT) ;
491     }
492     /* get various information about display */
493     screenS = DefaultScreen(dpyS);
494     cmapS = DefaultColormap(dpyS,screenS);
495     parentS = root = RootWindow(dpyS,screenS);
496     depth = DefaultDepth(dpyS,screenS);
497 
498     /* check whether machine is color or not */
499     if( (colorS = XDisplayCells( dpyS, screenS )) > 2 ){
500 	/* if color number of display cells > 0 */
501 	colorS = TRUE ;
502 	if( reply = XGetDefault( dpyS, GRAPHICS, "bw" )){
503 	    if( strcmp( reply, "on" ) == STRINGEQ ){
504 		colorS = FALSE ;
505 	    }
506 	}
507     } else {
508 	colorS = FALSE ;
509     }
510 
511 
512     /* set font and get font info */
513     if(font = XGetDefault( dpyS, GRAPHICS, "font" )){
514         fontinfoS = TWgetfont( font, &fontS ) ;
515 	infoBoxS.fontname = font ;
516     } else {
517 	/* we perfer our default to be 9x15 */
518         fontinfoS = TWgetfont( "9x15", &fontS ) ;
519 	if(!(fontinfoS )){
520 	    fontinfoS = TWgetfont( "fixed", &fontS ) ;
521 	    infoBoxS.fontname = "fixed" ;
522 	} else {
523 	    infoBoxS.fontname = "9x15" ;
524 	}
525     }
526     /* see if we should turn on the stipple pattern */
527     if( reply = XGetDefault( dpyS, GRAPHICS, "stipple" )){
528 	if( strcmp( reply, "on" ) == STRINGEQ ){
529 	    stippleS = TRUE ;
530 	}
531     }
532     /* see if we should turn on/off the rectangular fill */
533     if( reply = XGetDefault( dpyS, GRAPHICS, "rectangle_fill" )){
534 	if( strcmp( reply, "off" ) == STRINGEQ ){
535 	    rect_fillS = FALSE ; /* dont fill rectangles - default on */
536 	}
537     }
538     /* see if we should turn on/off the arbitrary fill */
539     if( reply = XGetDefault( dpyS, GRAPHICS, "arbitrary_fill" )){
540 	if( strcmp( reply, "off" ) == STRINGEQ ){
541 	    fillArbS = FALSE ; /* dont fill arbs - default on */
542 	}
543     }
544     /* see if we should turn off the reverse video */
545     if( reply = XGetDefault( dpyS, GRAPHICS, "reverse" )){
546 	if( strcmp( reply, "on" ) == STRINGEQ ){
547 	    reverseS = TRUE ;
548 	}
549     }
550 
551     /* see if we need to reset the wait time to redraw */
552     if( reply = XGetDefault( dpyS, GRAPHICS, "wait_time" )){
553 	TWsafe_wait_timeG = atoi( reply ) ;
554     } else {
555 	TWsafe_wait_timeG = 2 ;
556     }
557 
558 
559     /* initialize position */
560     if( winstr = XGetDefault( dpyS, GRAPHICS, "geometry" )){
561 	m = XParseGeometry( winstr,&winxS,&winyS,&winwidthS,&winheightS) ;
562 	if( m & XNegative ){
563 	    winxS = XDisplayWidth( dpyS, screenS ) + winxS ;
564 	}
565 	if( m & YNegative ){
566 	    winyS = XDisplayHeight( dpyS, screenS ) + winyS ;
567 	}
568 	/* these two lines insure that uses doesn't have to press */
569 	/* button using twm window manager */
570 	if( winxS == 0 ) winxS++ ;
571 	if( winyS == 0 ) winyS++ ;
572 	hints.flags = USPosition | USSize ;
573     } else {
574 	winwidthS = INT_WIDTH;
575 	winheightS = INT_HEIGHT;
576 	winxS = INT_X;
577 	winyS = INT_Y;
578 	hints.flags = PPosition | PSize ;
579     }
580     /* end initializing position of window */
581 
582     XSelectInput(dpyS,root,SubstructureNotifyMask );
583 
584     attr.event_mask = StructureNotifyMask
585 		    | SubstructureNotifyMask
586 		    | VisibilityChangeMask
587 		    | ExposureMask;
588 
589     attr.override_redirect = FALSE ;
590     attr.save_under = FALSE ;
591     attr.backing_store = NotUseful ;
592 
593     if(reverseS == TRUE){
594 	attr.background_pixel = BlackPixel(dpyS,screenS);
595     } else {
596 	attr.background_pixel = WhitePixel(dpyS,screenS);
597     }
598 
599     if(!(parasiteS)){
600 	backS = XCreateWindow(dpyS,root,winxS,winyS,winwidthS,
601 		winheightS,
602 		0,depth,InputOutput,DefaultVisual(dpyS,screenS),
603 		CWEventMask|CWBackPixel|CWOverrideRedirect|
604 		CWSaveUnder | CWBackingStore,&attr);
605 
606 	drawS = XCreateSimpleWindow( dpyS, backS,
607 	    0, MENUHEIGHT, winwidthS, winheightS - 2*MENUHEIGHT,
608 		0L, BlackPixel(dpyS,screenS), attr.background_pixel ) ;
609 
610 	event_mask = ExposureMask | ButtonPressMask ;
611 	XSelectInput(dpyS,drawS,event_mask);
612 
613 	/* initialize colors and/or stipple patterns */
614 	initcolors( desiredColors, numC ) ;
615 
616 	/* set the window manager hints */
617 	hints.x = winxS ;
618 	hints.y = winyS ;
619 	hints.width = winwidthS ;
620 	hints.height = winheightS ;
621 	XSetStandardProperties( dpyS,backS,GRAPHICS,GRAPHICS,None,argv,argc,&hints);
622 
623 	XMapWindow(dpyS,backS);
624 	XMapRaised(dpyS,drawS);
625 
626 	/* wait to get window */
627 	XSync(dpyS, FALSE );
628 	/* -------------------------------------------------------------
629 	   Now wait to window to become visible.  This code is necessary
630 	   since some window managers (uwm) map the window as a ghost
631 	   image and wait for user to resize window.  Other window
632 	   managers (twm) map window as requested.  Need to accomodate
633 	   both.
634 	-------------------------------------------------------------- */
635 	while( TRUE ){
636 	    if( XCheckTypedWindowEvent(dpyS,backS,VisibilityNotify,&event)){
637 		if( event.xvisibility.state == VisibilityUnobscured ){
638 		    break ;
639 		}
640 	    }
641 	}
642 
643     } else { /* for a parasite case */
644 	/* retrieve the window information */
645 	drawS = TWgetWindowId( dpyS, backS ) ;
646 	/* set the event mask for the windows */
647 	event_mask = StructureNotifyMask |
648 	    SubstructureNotifyMask | VisibilityChangeMask ;
649 	XSelectInput(dpyS,backS,event_mask);
650 	event_mask = ExposureMask | ButtonPressMask ;
651 	XSelectInput(dpyS,drawS,event_mask);
652 	/* initialize colors and/or stipple patterns */
653 	initcolors( desiredColors, numC ) ;
654     }
655 
656     /* if the window manager added border around window we */
657     /* need to save new origin of window */
658     /* also if user changed size we need to get it */
659     XGetWindowAttributes( dpyS, backS, &wattr ) ;
660     winxS = infoBoxS.winx = wattr.x ;
661     winyS = infoBoxS.winy = wattr.y ;
662     winwidthS = infoBoxS.winwidth = wattr.width ;
663     winheightS = infoBoxS.winheight = wattr.height - 2 * MENUHEIGHT ;
664     /* default user data boarder to size of window */
665     leftS = 0 ;
666     bottomS = MENUHEIGHT ;
667     rightS = winwidthS ;
668     topS = winheightS ;
669     fullViewS = TRUE ;
670 
671     /* save the refresh function */
672     infoBoxS.refresh_func = refresh_func ;
673 
674     TW3Dnormal_view() ;
675 
676     if(!(parasiteS)){
677 	XClearWindow(dpyS,drawS);
678     }
679 
680     /* off screen copy of the data */
681     pixmapS = XCreatePixmap( dpyS, drawS,
682 	(unsigned)winwidthS, (unsigned)winheightS,
683 	XDefaultDepth(dpyS,screenS) ) ;
684 
685     if(!(TWinitMenuWindow( menu ))){
686 	initS = TRUE ; /* fake out TWcloseGraphics */
687 	TWcloseGraphics() ;
688 	YexitPgm(NOINIT) ;
689     }
690 
691 
692     TWdrawMenus() ;
693     XFlush( dpyS ) ;
694 
695     /* initialization has been done sucessfully */
696     displayOpenS = TRUE; /* display is open for business */
697     initS = TRUE ;
698     TWsetMode( TWDRAWONLY ) ;
699     return( initS ) ;
700 
701 } /* end function TWinitGraphics */
702 
TWgetDrawInfo()703 TWINFOPTR TWgetDrawInfo()
704 {
705     TWINFOPTR info ;
706 
707     /* put all information in record for other modules use */
708     /* a inefficient attempt at object orient programming */
709     info = &infoBoxS ;
710     info->graphicContext = graphicContextS ;
711     info->dpy = dpyS ;
712     info->drawWindow = drawS ;
713     info->backWindow = backS ;
714     info->rootWindow = parentS ;
715     info->screen = screenS ;
716     info->fontinfo = fontinfoS ;
717     info->scaleFactor = scaleFactorS ;
718     info->xoffset = xoffsetS ;
719     info->yoffset = yoffsetS ;
720     info->winwidth = winwidthS ;
721     info->winheight = winheightS ;
722     info->winx = winxS ;
723     info->winy = winyS ;
724     info->colorOn = colorOnS ;
725     info->numColors = numColorS ;
726     info->colors = userColorS ;
727     info->pixmap = pixmapS ;
728     info->stipple = stippleS ;
729     return( info ) ;
730 } /* end TWgetDrawInfo */
731 
732 
TWsetDrawInfo(winheight,winwidth,pixmap)733 void TWsetDrawInfo( winheight, winwidth, pixmap )
734 INT winheight, winwidth ;
735 Pixmap pixmap ;
736 {
737     infoBoxS.winwidth = winwidthS = winwidth ;
738     infoBoxS.winheight = winheightS = winheight ;
739     infoBoxS.pixmap = pixmapS = pixmap ;
740     fullViewS = TRUE ;
741     TWsetwindow( leftS, bottomS, rightS, topS ) ;
742 
743 } /* end TWsetDrawInfo */
744 
TWforceRedraw()745 void TWforceRedraw()
746 {
747     XEvent event ;          /* describes configuration event */
748 
749     /* set a redraw command for a zoom */
750     event.xexpose.type = Expose ;
751     event.xexpose.display = dpyS ;
752     event.xexpose.window = drawS ;
753     event.xexpose.x = 0 ;
754     event.xexpose.y = 0 ;
755     event.xexpose.count = 0 ;
756     XSendEvent( dpyS, drawS, TRUE, ExposureMask, &event ) ;
757 } /* end TWforceRedraw */
758 
TWcloseGraphics()759 void TWcloseGraphics()
760 {
761 
762     if(!(initS )){
763 	fprintf(stderr,"ERROR[closeGraphics]:initialization was not" ) ;
764 	fprintf(stderr,"performed\n  before calling closeGraphics\n" ) ;
765 	YexitPgm( NOINIT ) ;
766     }
767 
768     /* check to see if other files are open */
769     if( frameOpenS ){
770 	closeFrame() ;
771     }
772     if( displayOpenS ){
773 	TWfreeMenuWindows() ;
774 	XCloseDisplay( dpyS ) ;
775 	displayOpenS = FALSE ;
776     }
777 
778 } /* end TWcloseGraphics */
779 
780 /***********  BEGIN STRICT GRAPHICS ROUTINES ************* */
781 /* perform a zoom in main graphics window */
TWzoom()782 void TWzoom()
783 {
784     INT x1, y1 ; /* first point of user zoom */
785     INT x2, y2 ; /* second point of user zoom */
786     INT left, right, bottom, top ; /* for calculating window */
787     INT span ;   /* span of design */
788 
789     TWmessage( "[ZOOM]:Pick or enter first point of bounding box:" ) ;
790     TWgetPt2( &x1, &y1 ) ;
791     TWmessage( "[ZOOM]:Pick or enter second point of bounding box:" ) ;
792     TWgetPt2( &x2, &y2 ) ;
793 
794     if( fullViewS ){
795 	/* only save full view window size */
796 	oldxoffsetS = xoffsetS ;
797 	oldyoffsetS = yoffsetS ;
798 	oldscaleFactorS = scaleFactorS ;
799 	fullViewS = FALSE ;
800     }
801 
802     if( x1 >= x2 && y1 >= y2 ){
803 	/* zoom out */
804 	span = rightS - leftS ;
805 	span *= 2 ;
806 	left = leftS = ( (x1 + x2 ) / 2 ) - span / 2 ;
807 	right = rightS = ( (x1 + x2 ) / 2 ) + span / 2 ;
808 	span = topS - bottomS ;
809 	span *= 2 ;
810 	bottom = bottomS = ( (y1 + y2 ) / 2 ) - span / 2 ;
811 	top = topS = ( (y1 + y2 ) / 2 ) + span / 2 ;
812 
813     } else {
814 	/* zoom in */
815 	left = MIN( x1, x2 ) ;
816 	right = MAX( x1, x2 ) ;
817 	bottom = MIN( y1, y2 ) ;
818 	top = MAX( y1, y2 ) ;
819     }
820 
821     /* set new window */
822     TWsetwindow( left, bottom, right, top ) ;
823     /* important that we reset full view to FALSE at this point */
824     /* since TWsetwindow always sets it to TRUE */
825     fullViewS = FALSE ;
826     TWmessage( " " ) ;
827 
828     TWforceRedraw() ;
829 
830 }
831 
832 /* returns to full screen after zoom */
TWfullView()833 void TWfullView()
834 {
835     if( fullViewS ){
836 	return ;
837     }
838     TWmessage( "[FULLSCREEN]: Returning to original size" ) ;
839     fullViewS = TRUE ;
840     infoBoxS.xoffset = xoffsetS = oldxoffsetS ;
841     infoBoxS.yoffset = yoffsetS = oldyoffsetS ;
842     infoBoxS.scaleFactor = scaleFactorS = oldscaleFactorS ;
843     TWforceRedraw() ;
844 
845 } /* end TWfullScreen */
846 
847 /* set the window area for bar */
TWsetwindow(left,bottom,right,top)848 void TWsetwindow( left, bottom, right, top )
849 INT left, bottom, right, top ;
850 {
851     INT xspan, yspan ; /* span of data */
852     DOUBLE xscaleF, yscaleF ;  /* scale data to window span */
853 
854     if( modeS == TWWRITEONLY ){
855 	return ;
856     }
857     /* save what the user gave us in case we need to use it */
858     /* for a reconfiguration request - ie, resize window */
859     if( fullViewS ){
860 	leftS = left ; rightS = right ; bottomS = bottom ; topS = top ;
861     }
862 
863     xspan = ABS( right - left ) ;
864     if( xspan == 0 ){
865 	if( initS ){
866 	    TWmessage( "ERROR: xspan is zero. Aborting zoom..." ) ;
867 	    return ;
868 	} else {
869 	    M(ERRMSG,"TWsetwindow", "xspan is zero" ) ;
870 	    return ;
871 	}
872     }
873     yspan = ABS( top - bottom ) ;
874     if( yspan == 0 ){
875 	if( initS ){
876 	    TWmessage( "ERROR: yspan is zero. Aborting zoom..." ) ;
877 	    return ;
878 	} else {
879 	    M(ERRMSG,"TWsetwindow", "yspan is zero" ) ;
880 	    return ;
881 	}
882     }
883     /* scale data to fit to window */
884     xscaleF = (DOUBLE) winwidthS / (DOUBLE) xspan ;
885     yscaleF = (DOUBLE) winheightS / (DOUBLE) yspan ;
886     /* pick smallest of factors for scale factor */
887     scaleFactorS = MIN( xscaleF, yscaleF) ;
888 
889     /* offset from beginning of data */
890     xoffsetS = - left ;
891     yoffsetS = - bottom ;
892 
893     if(!(fullViewS)){
894 	set_clip_window( left, right, bottom, top ) ;
895 	lS = left ; bS = bottom ;
896 	if( xspan > yspan ){
897 	    rS = right ;
898 	    tS = bottom + xspan ;
899 	} else if( xspan < yspan ){
900 	    rS = left + yspan ;
901 	    tS = top ;
902 	} else {
903 	    rS = right ;
904 	    tS = top ;
905 	}
906     }
907 
908     TWinforMenus() ;
909     fullViewS = TRUE ;
910 
911 } /* end TWsetwindow */
912 
set_clip_window(left,right,bottom,top)913 static VOID set_clip_window( left, right, bottom, top )
914 INT left, right, bottom, top ;
915 {
916     INT xspan, yspan ;
917 
918     lS = left ; bS = bottom ;
919     xspan = ABS( right - left ) ;
920     yspan = ABS( top - bottom ) ;
921     if( xspan > yspan ){
922 	rS = right ;
923 	tS = bottom + xspan ;
924     } else if( xspan < yspan ){
925 	rS = left + yspan ;
926 	tS = top ;
927     } else {
928 	rS = right ;
929 	tS = top ;
930     }
931 } /* end set_clip_window() */
932 
TWtranslate()933 void TWtranslate()
934 {
935     INT x1, y1 ;
936     INT last_xoff, last_yoff ;
937 
938     if( fullViewS ){
939 	/* only save full view window size */
940 	oldxoffsetS = xoffsetS ;
941 	oldyoffsetS = yoffsetS ;
942 	oldscaleFactorS = scaleFactorS ;
943 	fullViewS = FALSE ;
944 	set_clip_window( leftS, rightS, bottomS, topS ) ;
945     }
946     last_xoff = xoffsetS ; last_yoff = yoffsetS ;
947     TWmessage( "[TRANSLATE]:Pick or enter center of view:" ) ;
948     TWgetPt2( &x1, &y1 ) ;
949     sprintf( YmsgG, "new center - %d,%d", x1, y1 ) ;
950     TWmessage( YmsgG ) ;
951     /* translate to origin first */
952     xoffsetS = - x1 ;
953     yoffsetS = - y1 ;
954     /* now center in screen - half of xspan */
955     xoffsetS += (INT) ( (DOUBLE) winwidthS / scaleFactorS / 2.0 ) ;
956     yoffsetS += (INT) ( (DOUBLE) winheightS / scaleFactorS / 2.0 );
957     TWinforMenus() ; /* tell other module about info */
958     TWforceRedraw() ;
959     /* update clipping window */
960     lS -= (xoffsetS - last_xoff) ;
961     rS -= (xoffsetS - last_xoff) ;
962     bS -= (yoffsetS - last_yoff) ;
963     tS -= (yoffsetS - last_yoff) ;
964     D( "TWtranslate",
965 	fprintf( stderr, "l:%d r:%d b:%d t:%d\n", lS, rS, bS, tS ) ;
966     ) ;
967 
968 } /* end TWtranslate */
969 
970 /* copy pixmap to screen and flush screen output buffer */
971 /* flush screen output buffer */
TWflushFrame()972 void TWflushFrame()
973 {
974     if( modeS == TWWRITEONLY ){
975 	return ;
976     }
977     XFlush( dpyS ) ;
978     TWcheckExposure() ;
979 } /* end TWflushFrame */
980 
981 /* process everything in buffer */
TWsync()982 void TWsync()
983 {
984     if( modeS == TWWRITEONLY ){
985 	return ;
986     }
987     XFlush( dpyS ) ;
988     XSync( dpyS, 0 ) ;
989 } /* end TWsync */
990 
initcolors(desiredColorArray,numC)991 static VOID initcolors( desiredColorArray, numC )
992 char **desiredColorArray ;
993 INT  numC ;
994 {
995     unsigned long backgrd;
996     unsigned long foregrd;
997     unsigned long whitepix ;
998     unsigned long blackpix ;
999     GC       gc ;      /* temp for graphics context */
1000     char     *color ;
1001     XColor   ecolor ;  /* exact color - do need to use it */
1002     INT      i, j, k ;
1003     INT      pattern ;
1004     char     *stipple ;
1005     char     *TWstdStipple() ;
1006     char     row, bit ;
1007     Pixmap   *stipplePix ;  /* array of pixmaps for stipple */
1008 
1009     /* make copy of the users colors */
1010     userColorS = YMALLOC( numC+1, char * ) ;
1011     for( i=0; i <= numC; i++ ){
1012 	if( desiredColorArray[i] ){
1013 	    userColorS[i] = Ystrclone( desiredColorArray[i] ) ;
1014 	} else {
1015 	    userColorS[i] = NULL ;
1016 	}
1017     }
1018 
1019 
1020     /* get default backgrounds white and black */
1021     whitepix = WhitePixel(dpyS,screenS);
1022     blackpix = BlackPixel(dpyS,screenS);
1023     if( reverseS == TRUE ){
1024 	backgrd = blackpix ;
1025 	foregrd = whitepix ;
1026     } else {
1027 	backgrd = whitepix ;
1028 	foregrd = blackpix ;
1029     }
1030     if( !(colorS) || stippleS ){
1031 	stippleS = TRUE ;
1032 	stipple = TWstdStipple() ;
1033 	stipplePix = YMALLOC( numC+1, Pixmap ) ;
1034 	{
1035 	unsigned int x, y, xret, yret  ;
1036 	x = 8 ;
1037 	y = 8 ;
1038 	XQueryBestSize( dpyS, StippleShape, drawS, x,y, &xret, &yret ) ;
1039 	}
1040     }
1041 
1042     /* allocate size of colorArrayS */
1043     colorArrayS = YMALLOC( numC+1, XColor ) ;
1044     /* allocate array for whether color is turned on or off */
1045     colorOnS = YMALLOC( numC+1, BOOL ) ;
1046     /* allocate initial size of graphic context one for each color */
1047     graphicContextS = YMALLOC( numC+1, GC ) ;
1048 
1049     /* initialize color on array */
1050     for( i = 0; i <= numC; i++ ){
1051 	colorOnS[i] = TRUE ;
1052     }
1053 
1054     /**** now create GRAPHIC CONTEXT for highlighting data **** */
1055     gc = graphicContextS[0] = XCreateGC( dpyS,drawS,0L,NULL ) ;
1056     XSetFont( dpyS, gc, fontS ) ;
1057     XSetFunction( dpyS, gc, GXxor ) ;
1058 #ifdef sun
1059     XSetForeground( dpyS, gc, foregrd ) ;
1060     XSetBackground( dpyS, gc, backgrd ) ;
1061 #else
1062     XSetForeground( dpyS, gc, backgrd ) ;
1063     XSetBackground( dpyS, gc, foregrd ) ;
1064 #endif
1065     XSetFillStyle( dpyS, gc, FillSolid ) ;
1066     XSetLineAttributes( dpyS,gc,1,LineSolid,CapButt,JoinBevel ) ;
1067     /**** end create GRAPHIC CONTEXT for highlighting data **** */
1068 
1069     /* lookup color in color table */
1070     for( i=1; i<= numC;  i++ ){
1071 
1072 	/* take user given colors and look them up in color table */
1073 	if( !(color = desiredColorArray[i] ) ){
1074 	    fprintf( stderr, "ERROR:Color is NULL\n" ) ;
1075 	    break ;
1076 	    /* avoid nulls */
1077 	}
1078 	/* check to make sure first two entries are */
1079 	if( i == 1 ){  /* user must give white */
1080 	    if( strcmp( desiredColorArray[i], "white" ) != STRINGEQ ){
1081 		fprintf( stderr,
1082 		    "ERROR:Element 1 must be white in color array.\n") ;
1083 	    }
1084 	} else if( i == 2 ){  /* user must give black */
1085 	    if( strcmp( desiredColorArray[i], "black" ) != STRINGEQ ){
1086 		fprintf( stderr,
1087 		    "ERROR:Element 2 must be black in color array.\n") ;
1088 	    }
1089 	}
1090 
1091 	if( colorS ){
1092 	    /* now fill up this element of the color array */
1093 	    if( XAllocNamedColor(dpyS,cmapS,color,&(colorArrayS[i]),
1094 		&ecolor) <= 0){
1095 
1096 		/* default to white if call is unsucessful <= 0 */
1097 		fprintf( stderr,"Can't find color:%s ", color ) ;
1098 		fprintf( stderr,"in color table. Defaulting to white.\n");
1099 		colorArrayS[i].pixel = whitepix ;
1100 	    }
1101 	}
1102 
1103 	/* now create GRAPHIC CONTEXT */
1104 	graphicContextS[i] =XCreateGC( dpyS,drawS,0L,NULL ) ;
1105 
1106 	/* set font */
1107 	XSetFont( dpyS, graphicContextS[i], fontS ) ;
1108 
1109 	XSetFunction( dpyS, graphicContextS[i], GXcopy ) ;
1110 	XSetBackground( dpyS, graphicContextS[i], backgrd ) ;
1111 	if( i == 1 ){
1112 	    XSetForeground( dpyS, graphicContextS[i], whitepix ) ;
1113 	    XSetBackground( dpyS, graphicContextS[i], blackpix ) ;
1114 	} else if( i == 2 ){
1115 	    XSetForeground( dpyS, graphicContextS[i], blackpix ) ;
1116 	    XSetBackground( dpyS, graphicContextS[i], whitepix ) ;
1117 	} else if( colorS ){
1118 	    XSetForeground( dpyS, graphicContextS[i],
1119 		colorArrayS[i].pixel ) ;
1120 	}
1121 	if( colorS || i <= 2 ){
1122 	    XSetFillStyle( dpyS, graphicContextS[i], FillSolid ) ;
1123 	    XSetLineAttributes( dpyS,graphicContextS[i],1,LineSolid,
1124 		CapRound, JoinBevel ) ;
1125 	}
1126 	if( i >= 3 && stippleS ){ /* i > 2 and black and white */
1127 	    if( !(colorS)){
1128 		if( reverseS ){
1129 		    XSetForeground( dpyS, graphicContextS[i], backgrd ) ;
1130 		} else {
1131 		    XSetForeground( dpyS, graphicContextS[i], foregrd ) ;
1132 		}
1133 	    }
1134 	    XSetLineAttributes( dpyS,graphicContextS[i],1,LineSolid,
1135 		CapRound, JoinBevel ) ;
1136 	    /* set stipple patterns for black and white */
1137 	    XSetFillStyle( dpyS, graphicContextS[i], FillTiled );
1138 	    /* now create an 8 x 8 pixmap for the stipple pattern */
1139 	    stipplePix[i] = XCreatePixmap( dpyS,drawS,
1140 		(unsigned)8, (unsigned)8, XDefaultDepth(dpyS,screenS) ) ;
1141 	    /* Clear the pixmap - this is very subtle. Use */
1142 	    /* XFillRectangle to insure pixmap doesn't have junk in it */
1143 	    if( reverseS ){
1144 		XFillRectangle( dpyS, stipplePix[i],
1145 		    graphicContextS[BLACK], 0, 0, 8, 8 ) ;
1146 	    } else {
1147 		XFillRectangle( dpyS, stipplePix[i],
1148 		    graphicContextS[WHITE], 0, 0, 8, 8 ) ;
1149 	    }
1150 	    /* pick ith stipple pattern fill in TWstdStipple array */
1151 	    /* pattern is offset into array */
1152 	    pattern = 8 * (i - 3) ;
1153 	    for( j = 0; j < 8 ; j++ ){
1154 		row = stipple[pattern+j] ;
1155 		for( k = 0; k < 8 ; k++ ){
1156 		    bit = row >> k ;
1157 		    /* now get low order bit */
1158 		    bit &= 0x01 ;
1159 		    if( bit ){
1160 			if( reverseS ){
1161 			    XDrawPoint( dpyS, stipplePix[i],
1162 				graphicContextS[WHITE], j, k ) ;
1163 			} else {
1164 			    if( colorS ){
1165 				XDrawPoint( dpyS, stipplePix[i],
1166 				    graphicContextS[i], j, k ) ;
1167 			    } else {
1168 				XDrawPoint( dpyS, stipplePix[i],
1169 				    graphicContextS[BLACK], j, k ) ;
1170 			    }
1171 			}
1172 		    }
1173 		}
1174 	    } /* at this point we are done building pixmap */
1175 	    /* apply stipple to graphic context */
1176 	    XSetTile( dpyS, graphicContextS[i], stipplePix[i] ) ;
1177 	    XSetFillRule( dpyS, graphicContextS[i], WindingRule ) ;
1178 	    XSetTSOrigin( dpyS, graphicContextS[i], 0, 0 ) ;
1179 
1180 	} /* end building stipple pattern */
1181 
1182     }
1183 
1184     numColorS = numC ;
1185 
1186     ASSERT( numC != 0, "initcolor",
1187 	"User didn't give any color data" ) ;
1188 
1189 } /* end initcolor */
1190 
TWcolorXOR(color,exorFlag)1191 void TWcolorXOR( color, exorFlag )
1192 INT color ;
1193 BOOL exorFlag ;
1194 {
1195     /* check to make sure color is valid */
1196     if( color <= 0 || color > numColorS ){
1197 	if( initS ){ /* graphics are available */
1198 	    sprintf( YmsgG, "Color number:%d is out of range", color ) ;
1199 	    TWmessage( YmsgG ) ;
1200 	} else {
1201 	    fprintf( stderr,"Color number:%d is out of range", color ) ;
1202 	}
1203 	return ;
1204     }
1205     if( exorFlag ){
1206 	XSetFunction( dpyS, graphicContextS[color], GXxor ) ;
1207     } else {
1208 	XSetFunction( dpyS, graphicContextS[color], GXcopy ) ;
1209     }
1210 } /* end TWcolorXOR */
1211 
1212 
1213 /* start a new slate */
startDFrame()1214 static void startDFrame()
1215 {
1216     XClearWindow( dpyS, drawS ) ;
1217     if( reverseS ){
1218 	XFillRectangle( dpyS, pixmapS,
1219 	    graphicContextS[BLACK], 0, 0, winwidthS, winheightS ) ;
1220     } else {
1221 	XFillRectangle( dpyS, pixmapS,
1222 	    graphicContextS[WHITE], 0, 0, winwidthS, winheightS ) ;
1223     }
1224     TWdrawMenus() ;
1225     XFlush( dpyS ) ;
1226 } /* end startDFrame */
1227 
drawDLine(ref,x1,y1,x2,y2,color,label)1228 static VOID drawDLine(ref,x1,y1,x2,y2,color,label)
1229 /* draw a one pixel tall line segment from x1,y1 to x2,y2 */
1230 INT	ref, color ;
1231 register INT	x1,y1,x2,y2 ;
1232 char	*label ;
1233 {
1234 
1235     /* check to make sure color is valid */
1236     if( color <= 0 || color > numColorS ){
1237 	if( initS ){ /* graphics are available */
1238 	    sprintf( YmsgG, "Color number:%d is out of range", color ) ;
1239 	    TWmessage( YmsgG ) ;
1240 	} else {
1241 	    fprintf( stderr,"Color number:%d is out of range", color ) ;
1242 	}
1243 	return ;
1244     } else if(!(colorOnS[color])){
1245 	return ;
1246     }
1247     if(!(colorS )){
1248 	/* set all lines to black in B&W mode */
1249 	color = BLACK ;
1250     }
1251     /* see if we need to clip line. We use to let Xserver do this */
1252     /* but we can avoid an interprocess communication if we do it ourself */
1253     if(!(fullViewS)){
1254 	if(!(Yproject_intersect( x1, x2, y1, y2, lS, rS, bS, tS ) )){
1255 	    return ;
1256 	}
1257     }
1258 
1259     /* add users data offset */
1260     /* next scale coordinates to window */
1261     /* account for inversion of y axis */
1262     x1 = (INT) ( (DOUBLE) (x1 + xoffsetS) * scaleFactorS ) ;
1263     x2 = (INT) ( (DOUBLE) (x2 + xoffsetS) * scaleFactorS ) ;
1264     y1 = winheightS - (INT) ( (DOUBLE) (y1 + yoffsetS) * scaleFactorS ) ;
1265     y2 = winheightS - (INT) ( (DOUBLE) (y2 + yoffsetS) * scaleFactorS ) ;
1266     /* now draw line */
1267     XDrawLine( dpyS,drawS,graphicContextS[color],
1268 	x1,y1,x2,y2 ) ;
1269     XDrawLine( dpyS,pixmapS,graphicContextS[color],
1270 	x1,y1,x2,y2 ) ;
1271     if( label ){
1272 	if( *label != EOS ){
1273 	    XDrawImageString( dpyS, drawS, graphicContextS[color],
1274 		(x1+x2)/2, (y1+y2)/2, label, strlen(label) ) ;
1275 	    XDrawImageString( dpyS, pixmapS, graphicContextS[color],
1276 		(x1+x2)/2, (y1+y2)/2, label, strlen(label) ) ;
1277 	}
1278     }
1279 } /* end drawDLine */
1280 
drawDRect(ref,x1,y1,x2,y2,color,label)1281 static VOID drawDRect(ref,x1,y1,x2,y2,color,label)
1282 /* draw a rectangle whose diagonals are (x1,y1) and (x2,y2) */
1283 /* 	if the specified color is default or invalid, use default color */
1284 /* A border will be draw around the cell if specified black (default). */
1285 INT	ref, color ;
1286 register INT	x1,y1,x2,y2 ;
1287 char	*label ;
1288 {
1289     UNSIGNED_INT width, height ;
1290     INT len ;
1291 
1292     /* check to make sure color is valid */
1293     if( color <= 0 || color > numColorS ){
1294 	if( initS ){ /* graphics are available */
1295 	    sprintf( YmsgG, "Color number:%d is out of range", color ) ;
1296 	    TWmessage( YmsgG ) ;
1297 	} else {
1298 	    fprintf( stderr,"Color number:%d is out of range", color ) ;
1299 	}
1300 	return ;
1301     } else if(!(colorOnS[color])){
1302 	return ;
1303     }
1304     if(!(fullViewS)){
1305 	/* clip if necessary for speed. Avoid interprocess communication */
1306 	if(!(Yproject_intersect( x1, x2, y1, y2, lS, rS, bS, tS ) )){
1307 	    return ;
1308 	}
1309     }
1310 
1311     /* first add data offset to move to relative to 0,0 */
1312     x1 += xoffsetS ;
1313     x2 += xoffsetS ;
1314     y1 += yoffsetS ;
1315     y2 += yoffsetS ;
1316     /* next scale coordinates to window */
1317     x1 = (INT) ( (DOUBLE) x1 * scaleFactorS ) ;
1318     x2 = (INT) ( (DOUBLE) x2 * scaleFactorS ) ;
1319     y1 = (INT) ( (DOUBLE) y1 * scaleFactorS ) ;
1320     y2 = (INT) ( (DOUBLE) y2 * scaleFactorS ) ;
1321     width = x2 - x1 ;
1322     height = y2 - y1 ;
1323     /* account for inversion of y axis */
1324     y1 = winheightS - y1 ;
1325     y2 = winheightS - y2 ;
1326     if( rect_fillS ){
1327 	XFillRectangle( dpyS,drawS,graphicContextS[color],
1328 	    x1,y2,width,height ) ;
1329 	XFillRectangle( dpyS,pixmapS,graphicContextS[color],
1330 	    x1,y2,width,height ) ;
1331 	if( borderColorS ){
1332 	    XDrawRectangle( dpyS,drawS,graphicContextS[borderColorS],
1333 		x1,y2,width,height ) ;
1334 	    XDrawRectangle( dpyS,pixmapS,graphicContextS[borderColorS],
1335 		x1,y2,width,height ) ;
1336 	}
1337     } else {
1338 	XDrawRectangle( dpyS,drawS,graphicContextS[color],
1339 	    x1,y2,width,height ) ;
1340 	XDrawRectangle( dpyS,pixmapS,graphicContextS[color],
1341 	    x1,y2,width,height ) ;
1342     }
1343     if( label ){
1344 	if( *label != EOS ){
1345 	    len = strlen(label) ;
1346 	    /* now find width of string as offset */
1347 	    width = XTextWidth( fontinfoS, label, len ) ;
1348 	    /* need image string so you can write on top of fill */
1349 	    XDrawImageString( dpyS, drawS, graphicContextS[color],
1350 		(x1+x2-width)/2, (y1+y2)/2, label, strlen(label) ) ;
1351 	    XDrawImageString( dpyS, pixmapS, graphicContextS[color],
1352 		(x1+x2-width)/2, (y1+y2)/2, label, strlen(label) ) ;
1353 	}
1354     }
1355 } /* end drawDCell */
1356 
TWarb_init()1357 void TWarb_init()
1358 {
1359     /* allocate memory if needed */
1360     if(!(ptS)){
1361 	ptAllocS = EXPECTEDPTS ;
1362 	ptS = YMALLOC( ptAllocS, XPoint );
1363     }
1364     if( modeS == TWWRITEONLY || modeS == TWWRITENDRAW ){
1365 	Ybuster_init() ;
1366     }
1367     /* make sure we cannot match the 0 record in the redundancy */
1368 #if 0
1369     /* Yikes! XPoint x and y records are defined as type short. . . */
1370     ptS[0].x = INT_MIN ;
1371     ptS[0].y = INT_MIN ;
1372 #else
1373     ptS[0].x = SHRT_MIN ;
1374     ptS[0].y = SHRT_MIN ;
1375 #endif
1376     numptS = 0 ;
1377     if( !(fullViewS)){
1378 	arblS = INT_MAX ; arbrS = INT_MIN ; arbbS = INT_MAX ; arbtS = INT_MIN ;
1379     }
1380 } /* end TWarb_init */
1381 /* ***************************************************************** */
1382 
TWarb_addpt(xpos,ypos)1383 void TWarb_addpt( xpos, ypos )
1384 INT xpos, ypos ;
1385 {
1386 
1387     if( modeS == TWWRITEONLY || modeS == TWWRITENDRAW ){
1388 	Ybuster_addpt( xpos, ypos ) ;
1389     }
1390     if(!(fullViewS)){
1391 	arblS = MIN( arblS, xpos ) ;
1392 	arbbS = MIN( arbbS, ypos ) ;
1393 	arbrS = MAX( arbrS, xpos ) ;
1394 	arbtS = MAX( arbtS, ypos ) ;
1395     }
1396     /* first add data offset to move to relative to 0,0 */
1397     xpos += xoffsetS ;
1398     ypos += yoffsetS ;
1399     /* next scale coordinates to window */
1400     xpos = (INT) ( (DOUBLE) xpos * scaleFactorS ) ;
1401     ypos = (INT) ( (DOUBLE) ypos * scaleFactorS ) ;
1402     /* account for inversion of y axis */
1403     ypos = winheightS - ypos ;
1404     /* now points are in X coordinates */
1405     if( xpos == (INT) ptS[numptS].x && ypos == (INT) ptS[numptS].y ){
1406 	/* avoid redundant points */
1407 	return ;
1408     }
1409     /* increase the space if necessary */
1410     if( ++numptS >= ptAllocS ){
1411 	ptAllocS += EXPECTEDPTS ;
1412 	ptS = YREALLOC( ptS,  ptAllocS, XPoint ) ;
1413     }
1414     ptS[numptS].x = (SHORT) xpos ;
1415     ptS[numptS].y = (SHORT) ypos ;
1416 } /* end TWarb_addpt */
1417 /* ***************************************************************** */
1418 
1419 
drawDArb(ref,color,label)1420 static VOID drawDArb( ref, color, label )
1421 INT	ref, color ;
1422 char	*label ;
1423 {
1424     INT    i ;           /* counter */
1425     INT    len ;         /* length of string if given */
1426     INT x1, y1, x2, y2 ; /* bounding box of figure */
1427     UNSIGNED_INT width ; /* width of font */
1428     XPoint *points ;     /* array starts from 1 not zero */
1429 
1430     if( color <= 0 || color > numColorS ){
1431 	if( initS ){ /* graphics are available */
1432 	    sprintf( YmsgG, "Color number:%d is out of range", color ) ;
1433 	    TWmessage( YmsgG ) ;
1434 	} else {
1435 	    fprintf( stderr,"Color number:%d is out of range", color ) ;
1436 	}
1437 	return ;
1438     } else if(!(colorOnS[color])){
1439 	return ;
1440     }
1441     points = &(ptS[1]) ;
1442 
1443     /* close the figure if it is not already closed */
1444     if( ptS[numptS].x != ptS[1].x || ptS[numptS].y != ptS[1].y ){
1445 	/* increase the space if necessary */
1446 	if( ++numptS >= ptAllocS ){
1447 	    ptAllocS += EXPECTEDPTS ;
1448 	    ptS = YREALLOC( ptS,  ptAllocS, XPoint ) ;
1449 	}
1450 	ptS[numptS].x = ptS[1].x ;
1451 	ptS[numptS].y = ptS[1].y ;
1452     }
1453     x1 = x2 = (INT) ptS[1].x ;
1454     y1 = y2 = (INT) ptS[1].y ;
1455     for( i = 2; i <= numptS; i++ ){
1456 	x1 = MIN( x1, (INT) ptS[i].x ) ;
1457 	x2 = MAX( x2, (INT) ptS[i].x ) ;
1458 	y1 = MIN( y1, (INT) ptS[i].y ) ;
1459 	y2 = MAX( y2, (INT) ptS[i].y ) ;
1460     }
1461     if(!(fullViewS)){
1462 	/* clip if necessary for speed. Avoid interprocess communication */
1463 	if(!(Yproject_intersect( arblS, arbrS, arbbS, arbtS, lS, rS, bS, tS ) )){
1464 	    return ;
1465 	}
1466     }
1467 
1468     if( fillArbS ){
1469 	/* the fill automatically closed the region. if we don't */
1470 	/* let it close the region, we have problems - bug in XFillPolygon */
1471 	XFillPolygon( dpyS, drawS, graphicContextS[color], points, numptS,
1472 	    Complex, CoordModeOrigin ) ;
1473 	XFillPolygon( dpyS, pixmapS, graphicContextS[color], points, numptS,
1474 	    Complex, CoordModeOrigin ) ;
1475     }
1476 
1477     if( label ){
1478 	if( *label != EOS ){
1479 	    len = strlen(label) ;
1480 	    /* now find width of string as offset */
1481 	    width = XTextWidth( fontinfoS, label, len ) ;
1482 	    /* need image string so you can write on top of fill */
1483 	    /* calculate where we need to put the label */
1484 	    x1 = x2 = (INT) ptS[1].x ;
1485 	    y1 = y2 = (INT) ptS[1].y ;
1486 	    for( i = 2; i <= numptS; i++ ){
1487 		x1 = MIN( x1, (INT) ptS[i].x ) ;
1488 		x2 = MAX( x2, (INT) ptS[i].x ) ;
1489 		y1 = MIN( y1, (INT) ptS[i].y ) ;
1490 		y2 = MAX( y2, (INT) ptS[i].y ) ;
1491 	    }
1492 	    XDrawImageString( dpyS, drawS, graphicContextS[color],
1493 		(x1+x2-width)/2, (y1+y2)/2, label, strlen(label) ) ;
1494 	    XDrawImageString( dpyS, pixmapS, graphicContextS[color],
1495 		(x1+x2-width)/2, (y1+y2)/2, label, strlen(label) ) ;
1496 	}
1497     }
1498     if( fillArbS ){
1499 	if( borderColorS ){
1500 	    XDrawLines( dpyS, drawS, graphicContextS[borderColorS],
1501 		points, numptS, CoordModeOrigin ) ;
1502 	    XDrawLines( dpyS, pixmapS, graphicContextS[borderColorS],
1503 		points, numptS, CoordModeOrigin ) ;
1504 	}
1505     } else {
1506 	XDrawLines( dpyS, drawS, graphicContextS[color],
1507 	    points, numptS, CoordModeOrigin ) ;
1508 	XDrawLines( dpyS, pixmapS, graphicContextS[color],
1509 	    points, numptS, CoordModeOrigin ) ;
1510     }
1511 } /* end drawDArb */
1512 
TWarb_fill(flag)1513 void TWarb_fill( flag )
1514 BOOL flag ;
1515 {
1516     fillArbS = flag ;
1517 } /* end TWarb_fill */
1518 
TWget_arb_fill()1519 BOOL TWget_arb_fill()
1520 {
1521     return( fillArbS ) ;
1522 } /* end TWget_arb_fill */
1523 
TWrect_fill(flag)1524 void TWrect_fill( flag )
1525 BOOL flag ;
1526 {
1527     rect_fillS = flag ;
1528 } /* end TWrect_fill */
1529 
TWget_rect_fill()1530 BOOL TWget_rect_fill()
1531 {
1532     return( rect_fillS ) ;
1533 } /* end TWget_rect_fill */
1534 
TWhighLightRect(x1,y1,x2,y2)1535 void TWhighLightRect( x1,y1,x2,y2 )
1536 /* draw a rectangle whose diagonals are (x1,y1) and (x2,y2) */
1537 register INT	x1,y1,x2,y2 ;
1538 {
1539     UNSIGNED_INT width, height ;
1540 
1541     /* first add data offset to move to relative to 0,0 */
1542     x1 += xoffsetS ;
1543     x2 += xoffsetS ;
1544     y1 += yoffsetS ;
1545     y2 += yoffsetS ;
1546     /* next scale coordinates to window */
1547     x1 = (INT) ( (DOUBLE) x1 * scaleFactorS ) ;
1548     x2 = (INT) ( (DOUBLE) x2 * scaleFactorS ) ;
1549     y1 = (INT) ( (DOUBLE) y1 * scaleFactorS ) ;
1550     y2 = (INT) ( (DOUBLE) y2 * scaleFactorS ) ;
1551     width = x2 - x1 ;
1552     height = y2 - y1 ;
1553     /* account for inversion of y axis */
1554     y2 = winheightS - y2 ;
1555     XFillRectangle( dpyS,drawS,graphicContextS[HIGHLITE],
1556 	x1,y2,width,height ) ;
1557     XFillRectangle( dpyS,pixmapS,graphicContextS[HIGHLITE],
1558 	x1,y2,width,height ) ;
1559 } /* end TWhighLightRect */
1560 
TWmoveRect(x1,y1,x2,y2,ptx,pty)1561 void TWmoveRect( x1, y1, x2, y2, ptx, pty )
1562 INT *x1, *y1, *x2, *y2, ptx, pty ;
1563 /* x1, y1, x2, y2 are all user data absolute coordinates */
1564 /* ptx and pty are the value of the pointer from TWgetPt */
1565 {
1566     BOOL press ;              /* tells whether button has been released */
1567     XEvent event ;            /* describes event */
1568     long event_mask ;         /* set events */
1569     INT x, y ;                /* current position of pointer */
1570     INT last_time ;           /* last time rectangle was moved */
1571     INT dx_user, dy_user ;    /* rect pos rel to pointer in user scale */
1572     INT dx_pix, dy_pix ;      /* rect pos rel to pointer in pixels */
1573     INT oldx, oldy ;          /* rect pos rel to pointer in pixels */
1574     UNSIGNED_INT width_user ; /* width of rectangle user coordinates */
1575     UNSIGNED_INT height_user; /* height of rectangle user coordinates */
1576     UNSIGNED_INT width_pix ; /* width of rectangle pixel coordinates */
1577     UNSIGNED_INT height_pix; /* height of rectangle pixel coordinates */
1578 
1579     width_user = *x2 - *x1 ;
1580     dx_user = *x1 - ptx ;
1581     height_user = *y2 - *y1 ;
1582     dy_user = pty - *y2 ; /* note that y - axis is inverted */
1583     ptx += xoffsetS ;
1584     pty += yoffsetS ;
1585     /* next scale coordinates to window */
1586     ptx  =       (INT) ( (DOUBLE) ptx * scaleFactorS ) ;
1587     pty  =       (INT) ( (DOUBLE) pty * scaleFactorS ) ;
1588     width_pix  = (INT) ( (DOUBLE) width_user * scaleFactorS ) ;
1589     height_pix = (INT) ( (DOUBLE) height_user * scaleFactorS ) ;
1590     dx_pix     = (INT) ( (DOUBLE) dx_user * scaleFactorS ) ;
1591     dy_pix     = (INT) ( (DOUBLE) dy_user * scaleFactorS ) ;
1592 
1593     /* account for inversion of y axis */
1594     pty = winheightS - pty ;
1595 
1596     /* turn on event mask for main drawing window - known as wS */
1597     event_mask = StructureNotifyMask | SubstructureNotifyMask
1598 	    | VisibilityChangeMask | ExposureMask | ButtonPressMask |
1599 	    PointerMotionMask ;
1600     XSelectInput(dpyS,drawS,event_mask);
1601 
1602     oldx = ptx ;
1603     oldy = pty ;
1604     /* draw rectangle at absolute coordinates */
1605     XDrawRectangle( dpyS,drawS,graphicContextS[HIGHLITE],
1606 	ptx+dx_pix,pty+dy_pix,width_pix,height_pix ) ;
1607 
1608     /* now look for either event - button press or keyboard */
1609     press = FALSE ;
1610     last_time = 0 ;
1611     while(!(press )){
1612 	/* check for user input from mouse */
1613 	if( press = XCheckTypedWindowEvent( dpyS,drawS,
1614 		ButtonPress,&event ) ){
1615 	    /* we have an event from the pointer */
1616 	    /* put event back on queue  and call TWgetPt */
1617 	    XPutBackEvent( dpyS, &event ) ;
1618 	    TWgetPt( &x, &y ) ;
1619 	    *x1 = x + dx_user ;
1620 	    *x2 = *x1 + width_user ;
1621 	    *y2 = y - dy_user ; /* - because of y axis inversion */
1622 	    *y1 = *y2 - height_user ;
1623 	} /* otherwise continue to loop */
1624 	/* move rectangle */
1625 	if( XCheckTypedWindowEvent( dpyS,drawS,
1626 		MotionNotify,&event ) ){
1627 	    /* avoid to many events to screen wait 50 msec.*/
1628 	    if( event.xmotion.time - last_time < 50 ){
1629 		continue ;
1630 	    }
1631 	    last_time = event.xmotion.time ;
1632 	    x = event.xmotion.x ;
1633 	    y = event.xmotion.y ;
1634 	    /* draw rectangle at old position absolute coordinates */
1635 	    XDrawRectangle( dpyS,drawS,graphicContextS[HIGHLITE],
1636 		oldx+dx_pix,oldy+dy_pix,width_pix,height_pix ) ;
1637 	    XFillRectangle( dpyS,drawS,graphicContextS[HIGHLITE],
1638 		oldx+dx_pix,oldy+dy_pix,width_pix,height_pix ) ;
1639 	    XDrawRectangle( dpyS,drawS,graphicContextS[HIGHLITE],
1640 		x+dx_pix,y+dy_pix,width_pix,height_pix ) ;
1641 	    XFillRectangle( dpyS,drawS,graphicContextS[HIGHLITE],
1642 		x+dx_pix,y+dy_pix,width_pix,height_pix ) ;
1643 	    oldx = x ; oldy = y ;
1644 	    XFlush( dpyS ) ;
1645 	}
1646     } /* end while loop */
1647 
1648 } /* end TWmoveRect */
1649 
TWgetfont(fname,font)1650 XFontStruct *TWgetfont( fname, font )
1651 char *fname ;
1652 Font *font ;
1653 {
1654     XFontStruct *fontinfo ;
1655 
1656     /* set font and get font info */
1657     /* this is a safe test to see if font exists */
1658     if(!(fontinfo = XLoadQueryFont( dpyS, fname ))){
1659 	sprintf( YmsgG, "font:%s not available - using default:fixed\n", fname ) ;
1660 	M( ERRMSG,"TWgetfont", YmsgG ) ;
1661 	fontinfo = XLoadQueryFont( dpyS, "fixed" ) ;
1662     }
1663     *font = fontinfo->fid ;
1664     return( fontinfo ) ;
1665 } /* end TWgetfont */
1666 
_TW3DdrawAxis(drawNotErase)1667 void _TW3DdrawAxis( drawNotErase )
1668 BOOL drawNotErase ;
1669 {
1670     INT xspan, yspan, zspan ;
1671     INT c ;      /* string color */
1672     INT xstring, ystring ;
1673     DOUBLE X0, Y0, X, Y ;
1674 
1675     xspan = rightS - leftS ;
1676     yspan = topS - bottomS ;
1677     zspan = MAX( xspan, yspan ) ;
1678 
1679     if( reverseS ){
1680 	if( drawNotErase ){
1681 	    c = 1 ;  /* white characters */
1682 	} else {
1683 	    /* erase */
1684 	    c = 2 ;  /* black background */
1685 	}
1686     } else {
1687 	if( drawNotErase ){
1688 	    c = 2 ;  /* black characters */
1689 	} else {
1690 	    /* erase */
1691 	    c = 1 ;  /* white background */
1692 	}
1693     }
1694 
1695     /* there are 4 points of interest */
1696     /* (0,0,0),  (xspan,0,0), (0,yspan,0),  (0,0,zspan) */
1697 
1698     /* first (0,0,0) */
1699     TW3Dperspective( (DOUBLE)0, (DOUBLE)0, (DOUBLE)0, &X0, &Y0 );
1700 
1701     /* next  (xspan,0,0) */
1702     TW3Dperspective( (DOUBLE)xspan, (DOUBLE)0, (DOUBLE)0, &X, &Y );
1703     /* draw X axis */
1704     TWdrawLine(0, (INT)X0, (INT)Y0, (INT)X, (INT)Y, 3, NIL(char *) ) ;
1705     /* draw label - find label coordinates */
1706     xstring = ( (INT) X0 + (INT) X ) DIV_2 ;
1707     ystring = ( (INT) Y0 + (INT) Y ) DIV_2 ;
1708     TWdrawString( xstring, ystring, c, "x" ) ;
1709 
1710     /* next  (0,yspan,0) */
1711     TW3Dperspective( (DOUBLE)0, (DOUBLE)yspan, (DOUBLE)0, &X, &Y );
1712     /* draw X axis */
1713     TWdrawLine(0, (INT)X0, (INT)Y0, (INT)X, (INT)Y, 3, NIL(char *) ) ;
1714     /* draw label - find label coordinates */
1715     xstring = ( (INT) X0 + (INT) X ) DIV_2 ;
1716     ystring = ( (INT) Y0 + (INT) Y ) DIV_2 ;
1717     TWdrawString( xstring, ystring, c, "y" ) ;
1718 
1719     /* next  (0,0,zspan) */
1720     TW3Dperspective( (DOUBLE)0, (DOUBLE)0, (DOUBLE)zspan, &X, &Y );
1721     /* draw X axis */
1722     TWdrawLine(0, (INT)X0, (INT)Y0, (INT)X, (INT)Y, 3, NIL(char *) ) ;
1723     /* draw label - find label coordinates */
1724     xstring = ( (INT) X0 + (INT) X ) DIV_2 ;
1725     ystring = ( (INT) Y0 + (INT) Y ) DIV_2 ;
1726     TWdrawString( xstring, ystring, c, "z" ) ;
1727 } /* end _TW3DdrawAxis */
1728 
TW3DsetCamera()1729 VOID TW3DsetCamera()
1730 {
1731   INT x, y ;
1732   INT oldx, oldy ;
1733   BOOL first_time = TRUE ;
1734   DOUBLE FOURPI = 720;
1735   DOUBLE mouseScaleX ;
1736   DOUBLE mouseScaleY ;
1737 
1738   TWmouse_tracking_start() ;
1739   TWcolorXOR( 3, TRUE ) ;
1740   _TW3DdrawAxis( TRUE ) ;
1741 
1742   /* once across window scales to four pi radians */
1743   mouseScaleX = FOURPI / (DOUBLE) (rightS - leftS) ;
1744   mouseScaleY = FOURPI / (DOUBLE) (topS - bottomS) ;
1745 
1746   while( !(TWmouse_tracking_end() )){
1747       if( TWmouse_tracking_pt( &x, &y ) ){
1748 	  /* draw the old one first */
1749 	  _TW3DdrawAxis( FALSE ) ;
1750 	  if( first_time ){
1751 	      oldx = x ;
1752 	      oldy = x ;
1753 	      first_time = FALSE ;
1754 	      continue ;
1755 	  }
1756 	  thetaS +=  ( x - oldx ) * radiansPerDegreeS * mouseScaleX;
1757 	  phiS += ( y - oldy ) * radiansPerDegreeS *mouseScaleY;
1758 	  /*
1759 	  sprintf(YmsgG, "Current settings: theta:%3d phi:%3d",
1760 	    (INT) (thetaS / radiansPerDegreeS),
1761 	    (INT) (phiS / radiansPerDegreeS) ) ;
1762 	  TWmessage(YmsgG) ;
1763 	  */
1764 	  oldx = x ; oldy = y ;
1765 	  set_viewing_transformation();
1766 	  /* now draw the new one */
1767 	  _TW3DdrawAxis( TRUE ) ;
1768 
1769 	} /* end check on whether coordinate changed */
1770     } /* end mouse tracking loop */
1771 
1772     TWcolorXOR( 3, FALSE ) ;
1773 
1774     /* translate to origin */
1775     xoffsetS = 0 ;
1776     yoffsetS = 0 ;
1777     /* now center in screen - half of xspan */
1778     xoffsetS += (INT) ( (DOUBLE) winwidthS / scaleFactorS / 2.0 ) ;
1779     yoffsetS += (INT) ( (DOUBLE) winheightS / scaleFactorS / 2.0 );
1780     TWinforMenus() ; /* tell other module about info */
1781     TWforceRedraw() ;
1782     _TW3DdrawAxis( TRUE ) ;
1783 } /* end TW3DsetCamera */
1784 
1785 /*--------------------
1786   --------------------*/
TW3DperspectiveOn()1787 VOID TW3DperspectiveOn()
1788 {
1789     perspectiveS = TRUE;
1790 } /* end TW3DperspectiveOn */
1791 
1792 /*--------------------
1793   --------------------*/
TW3DperspectiveOff()1794 VOID TW3DperspectiveOff()
1795 {
1796     perspectiveS = FALSE;
1797 } /* end TW3DperspectiveOff */
1798 
1799 /*------------------
1800   Initialize the transformation matrices
1801   ------------------*/
set_viewing_transformation()1802 static VOID set_viewing_transformation()
1803 {
1804   DOUBLE cosine_of_theta;
1805   DOUBLE sine_of_theta;
1806   DOUBLE  cosine_of_phi;
1807   DOUBLE  sine_of_phi;
1808 
1809   if ( thetaS == acos( (double)0.0 ) && phiS == 0.0 ) {
1810     cosine_of_theta = 0.0;
1811     cosine_of_phi   = 1.0;
1812     sine_of_theta   = 1.0;
1813     sine_of_phi     = 0.0;
1814   } else {
1815     cosine_of_theta = cos (thetaS);
1816     cosine_of_phi   = cos (phiS);
1817     sine_of_theta   = sin (thetaS);
1818     sine_of_phi     = sin (phiS);
1819   }
1820 
1821   v11S = -sine_of_theta;
1822   v12S = -cosine_of_phi   *  cosine_of_theta;
1823   v13S = -sine_of_phi     *  cosine_of_theta;
1824 
1825   v21S =  cosine_of_theta;
1826   v22S = -cosine_of_phi   * sine_of_theta;
1827   v23S = -sine_of_phi     * sine_of_theta;
1828 
1829   v32S =  sine_of_phi;
1830   v33S = -cosine_of_phi;
1831 
1832   v43S =  rhoS;
1833 
1834 } /* end set_viewing_transformation */
1835 
1836 /*------------------
1837   Perform a 3D transformation.
1838   ------------------*/
TW3Dperspective(x,y,z,pX,pY)1839 VOID TW3Dperspective(x, y, z, pX, pY)
1840 DOUBLE    x, y, z;
1841 DOUBLE    *pX, *pY;
1842 
1843 {
1844   DOUBLE x_eye, y_eye, z_eye;
1845 
1846   x = -x; y = -y; z = -z;
1847 
1848   x_eye = v11S * x + v21S * y;
1849   y_eye = v12S * x + v22S * y + v32S * z;
1850   z_eye = v13S * x + v23S * y + v33S * z + v43S;
1851 
1852   /* screen coordinates */
1853   if (perspectiveS) {
1854     *pX = x_eye/z_eye;
1855     *pY = y_eye/z_eye;
1856   }
1857   else {
1858     *pX = x_eye / v43S;
1859     *pY = y_eye / v43S;
1860   }
1861 
1862   D("perspective",
1863     fprintf(stderr,
1864 	"IN x:%-9.1f y:%-9.1f z:%-9.1f  OUT x:%-9.1f y:%-9.1f\n",
1865 	x,y,z,*pX,*pY ) ;
1866     );
1867 } /* end perspective */
1868 
1869 /* set the 3D translations to normal view */
TW3Dnormal_view()1870 VOID TW3Dnormal_view()
1871 {
1872     /* Sperical coordinates ?                                 */
1873     /* rho   = distance to point                              */
1874     /* theta = angle from x-axis on xy plane                  */
1875     /* phi   = angle from z-axis to line from point to origin */
1876     /* the normal way to look at things from top */
1877     thetaS    =   acos( (double) 0.0 );
1878     phiS      =   0.0 ;
1879     rhoS      =   1.0 ;
1880     perspectiveS = FALSE;   /* draw in perspective */
1881     set_viewing_transformation() ;
1882     if( initS ){
1883 	TWforceRedraw() ;
1884     }
1885     /* done 3D initialization */
1886 } /* end TW3Dnormal_view */
1887 
1888 /*-------------------------
1889     Draws a 3 dimensional cube.
1890   -------------------------*/
TW3DdrawCube(ref_num,x1,y1,z1,x2,y2,z2,color,label)1891 void TW3DdrawCube(ref_num, x1, y1, z1, x2, y2, z2, color, label)
1892 INT ref_num, x1, y1, z1, x2, y2, z2 ;
1893 INT color;
1894 char *label;
1895 {
1896     /* try it as a solid */
1897     /* side face 1 */
1898     TW3Darb_init() ;
1899     TW3Darb_addpt( x1, y1, z1 ) ;
1900     TW3Darb_addpt( x1, y1, z2 ) ;
1901     TW3Darb_addpt( x1, y2, z2 ) ;
1902     TW3Darb_addpt( x1, y2, z1 ) ;
1903     TW3DdrawArb( ref_num, color, NIL(char *) ) ;
1904     /* side face 2 */
1905     TW3Darb_init() ;
1906     TW3Darb_addpt( x2, y1, z1 ) ;
1907     TW3Darb_addpt( x2, y1, z2 ) ;
1908     TW3Darb_addpt( x2, y2, z2 ) ;
1909     TW3Darb_addpt( x2, y2, z1 ) ;
1910     TW3DdrawArb( ref_num, color, NIL(char *) ) ;
1911     /* front face 3 */
1912     TW3Darb_init() ;
1913     TW3Darb_addpt( x1, y1, z1 ) ;
1914     TW3Darb_addpt( x1, y1, z2 ) ;
1915     TW3Darb_addpt( x2, y1, z2 ) ;
1916     TW3Darb_addpt( x2, y1, z1 ) ;
1917     TW3DdrawArb( ref_num, color, NIL(char *) ) ;
1918     /* front face 4 */
1919     TW3Darb_init() ;
1920     TW3Darb_addpt( x1, y2, z1 ) ;
1921     TW3Darb_addpt( x1, y2, z2 ) ;
1922     TW3Darb_addpt( x2, y2, z2 ) ;
1923     TW3Darb_addpt( x2, y2, z1 ) ;
1924     TW3DdrawArb( ref_num, color, NIL(char *) ) ;
1925     /* bottom face */
1926     TW3Darb_init() ;
1927     TW3Darb_addpt( x1, y1, z1 ) ;
1928     TW3Darb_addpt( x1, y2, z1 ) ;
1929     TW3Darb_addpt( x2, y2, z1 ) ;
1930     TW3Darb_addpt( x2, y1, z1 ) ;
1931     TW3DdrawArb( ref_num, color, NIL(char *) ) ;
1932     /* top face */
1933     TW3Darb_init() ;
1934     TW3Darb_addpt( x1, y1, z2 ) ;
1935     TW3Darb_addpt( x1, y2, z2 ) ;
1936     TW3Darb_addpt( x2, y2, z2 ) ;
1937     TW3Darb_addpt( x2, y1, z2 ) ;
1938     TW3DdrawArb( ref_num, color, label ) ;
1939 
1940     if( fillArbS ){
1941 	TW3DdrawLine(ref_num, x1, y1, z1, x2, y1, z1, 2, NIL(char *));
1942 	TW3DdrawLine(ref_num, x1, y1, z1, x1, y2, z1, 2, NIL(char *));
1943 	TW3DdrawLine(ref_num, x1, y1, z1, x1, y1, z2, 2, NIL(char *));
1944 
1945 	TW3DdrawLine(ref_num, x2, y2, z2, x1, y2, z2, 2, NIL(char *));
1946 	TW3DdrawLine(ref_num, x2, y2, z2, x2, y1, z2, 2, NIL(char *));
1947 	TW3DdrawLine(ref_num, x2, y2, z2, x2, y2, z1, 2, NIL(char *));
1948 
1949 	TW3DdrawLine(ref_num, x1, y2, z2, x1, y1, z2, 2, NIL(char *));
1950 	TW3DdrawLine(ref_num, x1, y2, z2, x1, y2, z1, 2, NIL(char *));
1951 	TW3DdrawLine(ref_num, x2, y2, z1, x1, y2, z1, 2, NIL(char *));
1952 
1953 	TW3DdrawLine(ref_num, x2, y1, z1, x2, y2, z1, 2, NIL(char *));
1954 	TW3DdrawLine(ref_num, x2, y1, z1, x2, y1, z2, 2, NIL(char *));
1955 	TW3DdrawLine(ref_num, x1, y1, z2, x2, y1, z2, 2, NIL(char *));
1956     }
1957 
1958 } /* end TW3DdrawCube */
1959 
1960 /* returns string size in user coordinate system */
TWstringSize(string,width,height)1961 void TWstringSize( string, width, height )
1962 char *string ;
1963 INT *width, *height ;
1964 {
1965     INT len ;        /* length of string in characters */
1966     INT pix_width ;  /* width of string in pixels */
1967     INT pix_height ; /* height of string in pixels */
1968     len = strlen( string ) ;
1969     pix_width = XTextWidth( fontinfoS, string, len ) ;
1970     pix_height = fontinfoS->ascent + fontinfoS->descent ;
1971     /* now reverse scale of coordinates */
1972     *width  = (INT) ( (DOUBLE) pix_width / scaleFactorS ) ;
1973     *height = (INT) ( (DOUBLE) pix_height / scaleFactorS ) ;
1974 
1975 }
1976 
TWdrawString(x,y,color,label)1977 void TWdrawString( x, y, color, label )
1978 INT x, y, color ;
1979 char *label ;
1980 {
1981     if( color <= 0 || color > numColorS ){
1982 	if( initS ){ /* graphics are available */
1983 	    sprintf( YmsgG, "Color number:%d is out of range", color ) ;
1984 	    TWmessage( YmsgG ) ;
1985 	} else {
1986 	    fprintf( stderr,"Color number:%d is out of range", color ) ;
1987 	}
1988 	return ;
1989     } else if(!(colorOnS[color])){
1990 	return ;
1991     }
1992     if(!(fullViewS)){
1993 	if(!(Yproject_intersect( x, x, y, y, lS, rS, bS, tS ) )){
1994 	    return ;
1995 	}
1996     }
1997     /* add users data offset */
1998     /* next scale coordinates to window */
1999     /* account for inversion of y axis */
2000     x = (INT) ( (DOUBLE) (x + xoffsetS) * scaleFactorS ) ;
2001     y = winheightS - (INT) ( (DOUBLE) (y + yoffsetS) * scaleFactorS ) ;
2002     if( label ){
2003 	if( *label != EOS ){
2004 	    XDrawImageString( dpyS, drawS, graphicContextS[color],
2005 		x, y, label, strlen(label) ) ;
2006 	    XDrawImageString( dpyS, pixmapS, graphicContextS[color],
2007 		x, y, label, strlen(label) ) ;
2008 	}
2009     }
2010 } /* end TWdrawString */
2011 
2012 
2013 /******************************************************************
2014     END SCREEN GRAPHIC ROUTINES
2015 ******************************************************************* */
2016 
2017 
2018 /***  STATIC DEFINIONS FOR WRITE ROUTINES ONLY ****/
2019 static  FILE *cellFileS = NULL ; /* cellfile pointer */
2020 static  FILE *netFileS = NULL ;  /* net file pointer */
2021 static  FILE *symbFileS = NULL ; /* symbfile pointer */
2022 static  INT  numCellS = 0 ; /* cell counter */
2023 static  INT  numNetS = 0 ;  /* net counter */
2024 static  INT  numPinS = 0 ;  /* pin counter */
2025 static  INT  numCharS = 0 ; /* symbol table counter */
2026 
2027 
TWstartFrame()2028 void TWstartFrame()
2029 {
2030     char filename[LRECL] ;
2031     char dummy[5] ;
2032     UNSIGNED_INT nitems ;
2033 
2034 
2035     if(!(initS )){
2036 	fprintf(stderr,"ERROR[startNewFrame]:initialization was not" ) ;
2037 	fprintf(stderr,"performed\n  before calling startNewFrame\n" ) ;
2038 	YexitPgm( NOINIT ) ;
2039     }
2040 
2041     switch( modeS ){
2042 	case TWDRAWONLY:
2043 	    startDFrame() ;
2044 	    return ;
2045 	case TWWRITEONLY:
2046 	    break ;
2047 	case TWWRITENDRAW:
2048 	    startDFrame() ;
2049 	    break ;
2050     }
2051 
2052     if(!dirNameS){
2053 	return ;
2054     }
2055 
2056     if( frameOpenS ){
2057 	closeFrame() ;
2058     }
2059     /* signal that frame is now open */
2060     frameOpenS = TRUE ;
2061 
2062     /* now open next frame files */
2063     /* increment frame count */
2064     frameCountS++ ;
2065 
2066     /* first cell file */
2067     sprintf( filename, "%s/cell.bin.%d", dirNameS, frameCountS ) ;
2068     cellFileS = TWOPEN( filename, "w", ABORT ) ;
2069     numCellS = 0 ; /* reset cell counter */
2070 
2071     /* next net file */
2072     sprintf( filename, "%s/net.bin.%d", dirNameS, frameCountS ) ;
2073     netFileS = TWOPEN( filename, "w", ABORT ) ;
2074     numNetS = 0 ; /* reset net counter */
2075 
2076     /* next symb file */
2077     sprintf( filename, "%s/symb.bin.%d", dirNameS, frameCountS ) ;
2078     symbFileS = TWOPEN( filename, "w", ABORT ) ;
2079     /* write a dummy character at start file makes test for label */
2080     /* index easier since symbtable[0] is meaningless now. */
2081     /* All indexes into symbol table which are valid must be positive */
2082     dummy[0] = EOS ;
2083     nitems = (UNSIGNED_INT) 1 ;
2084     fwrite( dummy, sizeof(char), nitems, symbFileS ) ;
2085     numCharS = 1 ; /* reset symbol table counter */
2086 
2087 } /* end startNewFrame */
2088 
2089 /* write size of data at end of files and close them if frames are open */
closeFrame()2090 static void closeFrame()
2091 {
2092     char dummy[5] ;
2093     UNSIGNED_INT nitems ;
2094     INT numw ;
2095     INT excess ;
2096 
2097     if(!dirNameS){
2098 	return ;
2099     }
2100     /* check to see if other files are open */
2101     if( frameOpenS ){
2102 	nitems = (UNSIGNED_INT) 1 ;
2103 	/* terminate the file with number of records in each file */
2104 	numw = fwrite( &numCellS,sizeof(UNSIGNED_INT),nitems,cellFileS ) ;
2105 	ASSERT( numw == 1, "startNewFrame", "Number written zero" ) ;
2106 	numw = fwrite( &numNetS, sizeof(UNSIGNED_INT),nitems,netFileS ) ;
2107 	ASSERT( numw == 1, "startNewFrame", "Number written zero" ) ;
2108 	/* need to put on integer boundary */
2109 	if( excess = numCharS % 4 ){
2110 	    /* pad the remainder with dummy */
2111 	    nitems = (UNSIGNED_INT) (4 - excess ) ;
2112 	    numw = fwrite( dummy, sizeof(char), nitems, symbFileS ) ;
2113 	    ASSERT( numw == nitems,"startNewFrame","Number written zero");
2114 	}
2115 	nitems = (UNSIGNED_INT) 1 ;
2116 	numw = fwrite( &numCharS,sizeof(UNSIGNED_INT),nitems,symbFileS ) ;
2117 	ASSERT( numw == 1, "startNewFrame", "Number written zero" ) ;
2118 
2119 	/* files are open close them */
2120 	ASSERT( cellFileS, "startNewFrame", "cell file should be open" ) ;
2121 	TWCLOSE( cellFileS ) ;
2122 	ASSERT( netFileS, "startNewFrame", "net file should be open" ) ;
2123 	TWCLOSE( netFileS ) ;
2124 	ASSERT( symbFileS, "startNewFrame", "symb file should be open" ) ;
2125 	TWCLOSE( symbFileS ) ;
2126 	/* signal that frame has been closed */
2127 	frameOpenS = FALSE ;
2128     }
2129 
2130 } /* closeFrame */
2131 
TWsetFrame(number)2132 void TWsetFrame( number )
2133 INT number ;
2134 {
2135     char fileName[LRECL] ;
2136 
2137     if(!dirNameS){
2138 	return ;
2139     }
2140     if( number <= 0 ){
2141 	/* search for the first valid file */
2142 	/* find max number of frames of data */
2143 	for( frameCountS=1;;frameCountS++ ){
2144 
2145 	    sprintf( fileName,"%s/cell.bin.%d",dirNameS,frameCountS ) ;
2146 	    if(! (YfileExists(fileName) )){
2147 		/* last file successfully read is one less */
2148 		frameCountS-- ;
2149 		break ;
2150 	    }
2151 	}
2152     } else {
2153 	frameCountS = number ;
2154     }
2155 }
2156 
2157 /*   THE SPECIALIZED ROUTINES */
2158 /* *********  GENERIC WRITE ROUTINES **************  */
2159 /* draw a one pixel tall line segment from x1,y1 to x2,y2 */
drawWLine(ref_num,x1,y1,x2,y2,color,label)2160 static VOID drawWLine( ref_num,x1,y1,x2,y2,color,label)
2161 INT     ref_num ; /* reference number */
2162 INT	x1,y1,x2,y2,color ;
2163 char	*label;
2164 {
2165     DATABOX record ;
2166     UNSIGNED_INT nitems ;
2167     INT numw ; /* number written */
2168 
2169     if(!(colorOnS[color]) || !dirNameS ){
2170 	return ;
2171     }
2172     /* check modes call draw functions if necessary */
2173     switch( modeS ){
2174 	case TWDRAWONLY:
2175 	    /* this is an error should never call this */
2176 	    fprintf( stderr,"ERROR[drawWPin]:problem with mode\n" ) ;
2177 	    return ;
2178 	case TWWRITEONLY:
2179 	    break ;
2180 	case TWWRITENDRAW:
2181 	    drawDLine( ref_num,x1,y1,x2,y2,color,label) ;
2182 	    break ;
2183     }
2184     /* fill up data record  file destination net file */
2185     record.ref = (UNSIGNED_INT) ref_num ;
2186     record.x1 = x1 ;
2187     record.x2 = x2 ;
2188     record.y1 = y1 ;
2189     record.y2 = y2 ;
2190     /* now take care of color */
2191     record.color = color ;
2192     /* now store string in symbol table if given */
2193     if( label ){
2194 	/* write string to symbol table file */
2195 	nitems = (UNSIGNED_INT) ( strlen( label ) + 1 ) ;
2196 	numw = fwrite( label, sizeof(char), nitems, symbFileS ) ;
2197 	ASSERT( numw == nitems, "drawLine",
2198 	    "Couldnt write to string table" );
2199 	/* now store in net file offset in table */
2200 	record.label = numCharS ;
2201 	/* now update offset to include this string */
2202 	numCharS += (INT) nitems ;
2203 
2204     } else {
2205 	record.label = 0 ;
2206     }
2207     /* now write record */
2208     nitems = (UNSIGNED_INT) 1 ;
2209     numw = fwrite( &record, sizeof(DATABOX),nitems,netFileS ) ;
2210     ASSERT( numw == 1, "drawLine", "Record not written..." ) ;
2211     numNetS++ ;
2212 
2213 } /* end drawWLine */
2214 
2215 /* draw a rectangle whose diagonals are (x1,y1) and (x2,y2) */
2216 /* 	if the specified color is default or invalid, use default color */
drawWRect(ref_num,x1,y1,x2,y2,color,label)2217 static VOID drawWRect( ref_num, x1,y1,x2,y2,color,label)
2218 INT     ref_num ; /* reference number */
2219 INT	x1,y1,x2,y2, color;
2220 char	*label;
2221 {
2222     DATABOX record ;
2223     UNSIGNED_INT nitems ;
2224     INT numw ; /* number of records written */
2225 
2226     if(!(colorOnS[color]) || !dirNameS ){
2227 	return ;
2228     }
2229     /* check modes call draw functions if necessary */
2230     switch( modeS ){
2231 	case TWDRAWONLY:
2232 	    /* this is an error should never call this */
2233 	    fprintf( stderr,"ERROR[drawWRect]:problem with mode\n" ) ;
2234 	    return ;
2235 	case TWWRITEONLY:
2236 	    break ;
2237 	case TWWRITENDRAW:
2238 	    drawDRect( ref_num,x1,y1,x2,y2,color,label) ;
2239 	    break ;
2240     }
2241     /* fill up data record  file destination net file */
2242     record.ref = (UNSIGNED_INT) ref_num ;
2243     record.x1 = x1 ;
2244     record.x2 = x2 ;
2245     record.y1 = y1 ;
2246     record.y2 = y2 ;
2247     record.color = color ;
2248     /* now store string in symbol table if given */
2249     if( label ){
2250 	/* write string to symbol table file */
2251 	nitems = (UNSIGNED_INT) ( strlen( label ) + 1 ) ;
2252 	numw = fwrite( label, sizeof(char), nitems, symbFileS ) ;
2253 	ASSERT( numw == nitems, "drawWRect",
2254 	    "Couldn't write to string table" );
2255 	/* now store in net file offset in table */
2256 	record.label = numCharS ;
2257 	/* now update offset to include this string */
2258 	numCharS += (INT) nitems ;
2259 
2260     } else {
2261 	record.label = 0 ;
2262     }
2263     /* now write record */
2264     nitems = (UNSIGNED_INT) 1 ;
2265     numw = fwrite( &record, sizeof(DATABOX),nitems,cellFileS ) ;
2266     numCellS++ ;
2267     ASSERT( numw == 1, "drawWRect", "Record not written..." ) ;
2268 
2269 } /* end drawWRect */
2270 
drawWArb(ref,color,label)2271 static VOID drawWArb( ref, color, label )
2272 INT	ref, color ;
2273 char	*label ;
2274 {
2275     YBUSTBOXPTR bustptr ;
2276 
2277     if(!(colorOnS[color]) || !dirNameS ){
2278 	return ;
2279     }
2280     /* check modes call draw functions if necessary */
2281     switch( modeS ){
2282 	case TWDRAWONLY:
2283 	    /* this is an error should never call this */
2284 	    fprintf( stderr,"ERROR[drawWArb]:problem with mode\n" ) ;
2285 	    return ;
2286 	case TWWRITEONLY:
2287 	    break ;
2288 	case TWWRITENDRAW:
2289 	    drawDArb( ref, color, label ) ;
2290 	    break ;
2291     }
2292     while( bustptr = Ybuster() ){
2293 	/* l = bustptr[1].x ; */
2294 	/* r = bustptr[4].x ; */
2295 	/* b = bustptr[1].y ; */
2296 	/* t = bustptr[2].y ; */
2297 	TWdrawCell( ref, bustptr[1].x, bustptr[1].y,
2298 	    bustptr[4].x, bustptr[2].y, color, label ) ;
2299     }
2300 } /* end drawDArb */
2301 
2302 #endif /* NOGRAPHICS */
2303 /* ************************************************************** */
2304