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