1 /* -*- tab-width: 4 -*-
2  *
3  * Electric(tm) VLSI Design System
4  *
5  * File: ioquickdraw.c
6  * Input/output analysis tool: plotter output on Macintosh
7  * Written by: Steven M. Rubin, Static Free Software
8  *
9  * Copyright (c) 2000 Static Free Software.
10  *
11  * Electric(tm) is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * Electric(tm) is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with Electric(tm); see the file COPYING.  If not, write to
23  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
24  * Boston, Mass 02111-1307, USA.
25  *
26  * Static Free Software
27  * 4119 Alpine Road
28  * Portola Valley, California 94028
29  * info@staticfreesoft.com
30  */
31 
32 #include "config.h"
33 #ifdef MACOS
34 
35 #include "global.h"
36 #include "egraphics.h"
37 #include "eio.h"
38 #include "usr.h"
39 #include "efunction.h"
40 
41 #include <Fonts.h>
42 #include <Printing.h>
43 #include <Scrap.h>
44 #include <QDOffscreen.h>
45 
46 #define THRESH	         2000000
47 #ifdef __MWERKS__
48 #  if __MWERKS__ >= 0x2300
49 #    define NEWCODEWARRIOR    1
50 #  endif
51 #endif
52 #ifdef NEWCODEWARRIOR
53 #  define EFONT            kFontIDTimes
54 #  define HFONT            kFontIDHelvetica
55 #else
56 #  define EFONT            times
57 #  define HFONT            helvetica
58 #endif
59 
60 GRAPHICS io_black = {LAYERO, BLACK, SOLIDC, SOLIDC,
61 	{0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF}, NOVARIABLE, 0};
62 static WINDOWPART *io_plotwindow;
63 static INTBIG      io_plotrevy;
64 static INTBIG      io_slx, io_shx, io_sly, io_shy;
65 static INTBIG      io_ulx, io_uhx, io_uly, io_uhy;
66 static WindowPtr   io_plotwin;
67 static INTBIG      io_thislayer, io_maxlayer;
68 
69 void io_setplotlayer(INTBIG);
70 void io_setbounds(INTBIG, INTBIG, INTBIG, INTBIG, INTBIG, INTBIG, INTBIG, INTBIG, INTBIG, WindowPtr);
71 void io_plotpoly(POLYGON*, WINDOWPART*);
72 void io_plotdot(INTBIG, INTBIG);
73 void io_plotline(INTBIG, INTBIG, INTBIG, INTBIG, INTBIG);
74 void io_plotpolygon(INTBIG*, INTBIG*, INTBIG, INTBIG, GRAPHICS*);
75 void io_plottext(INTBIG, INTBIG, INTBIG, INTBIG, INTBIG, INTBIG, CHAR*);
76 void io_xform(INTBIG*, INTBIG*);
77 void io_maccopyhighlighted(void);
78 
79 /*
80  * routine to write out a file to the Macintosh/Quickdraw system
81  */
io_writequickdrawlibrary(LIBRARY * lib)82 BOOLEAN io_writequickdrawlibrary(LIBRARY *lib)
83 {
84 	REGISTER NODEPROTO *np;
85 	INTBIG err, ix, swid, shei;
86 	INTBIG hlx, hhx, hly, hhy, gridlx, gridly, gridx, gridy, cx, cy, prod1, prod2, i,
87 		revy, slx, shx, sly, shy, ulx, uhx, uly, uhy, sxs, sys, dxs, dys, saver, saveg,
88 		saveb, white, *curstate, lambda;
89 	VARIABLE *var;
90 	REGISTER VARIABLE *varred, *vargreen, *varblue;
91 	static POLYGON *poly = NOPOLYGON;
92 	static THPrint hPrint = 0;
93 	TPPrPort plotwin;
94 	TPrStatus prstat;
95 	Rect sr, dr;
96 	CGrafPtr window, gra_getoffscreen(WINDOWPART *);
97 	REGISTER void *infstr;
98 
99 	np = lib->curnodeproto;
100 	if (np == NONODEPROTO)
101 	{
102 		if ((el_curwindowpart->state&WINDOWTYPE) == EXPLORERWINDOW)
103 		{
104 			ttyputmsg(_("Cannot convert Explorer window to Quickdraw.  Export PostScript instead"));
105 			return(TRUE);
106 		}
107 		ttyputerr(_("No current cell to plot"));
108 		return(TRUE);
109 	}
110 
111 	/* cannot write text-only cells */
112 	if ((np->cellview->viewstate&TEXTVIEW) != 0)
113 	{
114 		ttyputerr(_("Cannot write textual cells"));
115 		return(TRUE);
116 	}
117 
118 	/* get printing control bits */
119 	curstate = io_getstatebits();
120 
121 	/* determine area to plot */
122 	if (io_getareatoprint(np, &slx, &shx, &sly, &shy, TRUE)) return(TRUE);
123 
124 	/* open the window (to the printer) */
125 	PrOpen();
126 	if ((err = PrError()) != noErr)
127 	{
128 		ttyputerr(_("Printer error %ld"), err);
129 		return(TRUE);
130 	}
131 
132 	/* see if any printing has already been done */
133 	if (hPrint == 0)
134 	{
135 		/* this is the first print: create print record and do "Page Setup" dialog */
136 		hPrint = (THPrint)NewHandle(sizeof (TPrint));
137 		if (hPrint == 0)
138 		{
139 			ttyputerr(_("Cannot allocate print record"));
140 			return(TRUE);
141 		}
142 		PrintDefault(hPrint);
143 		if ((err = PrError()) != noErr)
144 		{
145 			ttyputerr(_("Printer error %ld"), err);
146 			return(TRUE);
147 		}
148 		if (!PrStlDialog(hPrint)) return(TRUE);
149 	} else
150 	{
151 		/* have already printed: validate print record */
152 		PrValidate(hPrint);
153 		if ((err = PrError()) != noErr)
154 		{
155 			ttyputerr(_("Printer error %ld"), err);
156 			return(TRUE);
157 		}
158 	}
159 
160 	/* do the "Print..." dialog */
161 	if (!PrJobDialog(hPrint)) return(TRUE);
162 
163 	/* open the pseudo-window to the printer */
164 	plotwin = PrOpenDoc(hPrint, 0, 0);
165 	PrOpenPage(plotwin, 0);
166 	if (PrError())
167 	{
168 		ttyputerr(_("Error opening print page"));
169 		return(TRUE);
170 	}
171 	SetPort((WindowPtr)plotwin);
172 
173 	/* save background color and make it white */
174 	varred = getvalkey((INTBIG)us_tool, VTOOL, VINTEGER|VISARRAY, us_colormap_red_key);
175 	vargreen = getvalkey((INTBIG)us_tool, VTOOL, VINTEGER|VISARRAY, us_colormap_green_key);
176 	varblue = getvalkey((INTBIG)us_tool, VTOOL, VINTEGER|VISARRAY, us_colormap_blue_key);
177 	if (varred == NOVARIABLE || vargreen == NOVARIABLE || varblue == NOVARIABLE) return(TRUE);
178 	saver = ((INTBIG *)varred->addr)[0];
179 	saveg = ((INTBIG *)vargreen->addr)[0];
180 	saveb = ((INTBIG *)varblue->addr)[0];
181 	white = 0xFF;
182 	colormapload(&white, &white, &white, 0, 0);
183 
184 	/* see if the printer is color */
185 	if ((plotwin->gPort.portBits.rowBytes & 0xC000) == 0xC000)
186 	{
187 		/* special case for color printing */
188 		hlx = slx;   hhx = shx;
189 		hly = sly;   hhy = shy;
190 		(void)us_makescreen(&hlx, &hly, &hhx, &hhy, el_curwindowpart);
191 		sr.left = hlx;   sr.right = hhx;
192 
193 		getwindowframesize(el_curwindowpart->frame, &swid, &shei);
194 		revy = shei - 1;
195 
196 		sr.top = revy - hhy;    sr.bottom = revy - hly;
197 		sr.bottom++;
198 		dr = plotwin->gPort.portRect;
199 
200 		/* ensure that the destination has the same aspect ratio as the source */
201 		sxs = hhx - hlx;   sys = hhy - hly;
202 		dxs = dr.right - dr.left;   dys = dr.bottom - dr.top;
203 		if (dxs*sys > dys*sxs)
204 		{
205 			i = dys * sxs / sys;
206 			dr.left += (dxs-i) / 2;
207 			dr.right = dr.left + i;
208 		} else
209 		{
210 			i = dxs * sys / sxs;
211 			dr.top += (dys-i) / 2;
212 			dr.bottom = dr.top + i;
213 		}
214 
215 		/* now copy the offscreen bits at "sr" to the print port at "dr" */
216 		window = gra_getoffscreen(el_curwindowpart);
217 		(void)LockPixels(window->portPixMap);
218 		CopyBits((BitMap *)*(window->portPixMap), &plotwin->gPort.portBits,
219 			&sr, &dr, srcCopy, 0L);
220 		UnlockPixels(window->portPixMap);
221 
222 		PrClosePage(plotwin);
223 		PrCloseDoc(plotwin);
224 
225 		/* print if spooled */
226 		if ((*hPrint)->prJob.bJDocLoop == bSpoolLoop)
227 		{
228 			PrPicFile(hPrint, 0, 0, 0, &prstat);
229 			if (PrError())
230 				ttyputerr(_("Error queuing print page"));
231 		}
232 		PrClose();
233 
234 		/* restore background color */
235 		colormapload(&saver, &saveg, &saveb, 0, 0);
236 		return(FALSE);
237 	}
238 
239 	TextFont(EFONT);
240 
241 	/* establish order of plotting layers */
242 	io_maxlayer = io_setuptechorder(el_curtech);
243 
244 	/* determine scaling */
245 	ulx = plotwin->gPort.portRect.left;
246 	uly = plotwin->gPort.portRect.top;
247 	uhx = plotwin->gPort.portRect.right;
248 	uhy = plotwin->gPort.portRect.bottom;
249 	revy = plotwin->gPort.portRect.bottom - plotwin->gPort.portRect.top;
250 
251 	prod1 = shx - slx;
252 	prod2 = shy - sly;
253 	if (prod1 > THRESH || prod2 > THRESH)
254 	{
255 		/* screen extents too large: scale them down please */
256 		prod1 /= 1000;   prod2 /= 1000;
257 	}
258 	prod1 *= uhy - uly;
259 	prod2 *= uhx - ulx;
260 	if (prod1 != prod2)
261 	{
262 		/* adjust the scale */
263 		if (prod1 > prod2)
264 		{
265 			/* screen extent is too wide for window */
266 			i = (shx - slx) / 20;
267 			if (i == 0) i++;
268 			shx += i;   slx -= i;
269 			i = muldiv(shx - slx, uhy - uly, uhx - ulx) - (shy - sly);
270 			sly -= i/2;
271 			shy += i/2;
272 		} else
273 		{
274 			/* screen extent is too tall for window */
275 			i = (shy - sly) / 20;
276 			if (i == 0) i++;
277 			shy += i;   sly -= i;
278 			i = muldiv(shy - sly, uhx - ulx, uhy - uly) - (shx - slx);
279 			slx -= i/2;
280 			shx += i/2;
281 		}
282 	}
283 	io_setbounds(slx, shx, sly, shy, ulx, uhx, uly, uhy, revy, (WindowPtr)plotwin);
284 
285 	/* draw the grid if requested */
286 	if ((el_curwindowpart->state&(GRIDON|GRIDTOOSMALL)) == GRIDON)
287 	{
288 		lambda = lib->lambda[np->tech->techindex];
289 		gridx = muldiv(el_curwindowpart->gridx, lambda, WHOLE);
290 		gridy = muldiv(el_curwindowpart->gridy, lambda, WHOLE);
291 		var = getvalkey((INTBIG)us_tool, VTOOL, VINTEGER, us_gridfloatskey);
292 		if (var == NOVARIABLE || var->addr == 0)
293 		{
294 			gridlx = np->lowx  / gridx * gridx;
295 			gridly = np->lowy  / gridy * gridy;
296 		} else
297 		{
298 			grabpoint(np, &gridlx, &gridly);
299 			gridalign(&gridlx, &gridly, 1, np);
300 			gridlx += gridlx / gridx * gridx;
301 			gridly += gridly / gridy * gridy;
302 		}
303 
304 		/* adjust to ensure that the first point is inside the range */
305 		while (gridlx < slx) gridlx += gridx;
306 		while (gridly < sly) gridly += gridy;
307 
308 		/* plot the loop to the printer */
309 		for(cx = gridlx; cx <= shx; cx += gridx)
310 			for(cy = gridly; cy <= shy; cy += gridy)
311 				io_plotdot(cx, cy);
312 	}
313 
314 	/* plot layers in this technology in proper order */
315 	for(ix=0; ix<io_maxlayer; ix++)
316 	{
317 		/* first plot outlines around stipple layers */
318 		io_setplotlayer(-(io_nextplotlayer(ix) + 1));
319 		(void)asktool(us_tool, x_("display-to-routine"), io_plotpoly);
320 
321 		/* next plot layers */
322 		io_setplotlayer(io_nextplotlayer(ix) + 1);
323 		(void)asktool(us_tool, x_("display-to-routine"), io_plotpoly);
324 	}
325 
326 	/* finally plot layers not in the technology */
327 	io_setplotlayer(0);
328 	(void)asktool(us_tool, x_("display-to-routine"), io_plotpoly);
329 
330 	/* put out dates if requested */
331 	if ((curstate[0]&PLOTDATES) != 0)
332 	{
333 		/* create the polygon if it doesn't exist */
334 		(void)needstaticpolygon(&poly, 1, io_tool->cluster);
335 
336 		/* plot cell name */
337 		infstr = initinfstr();
338 		formatinfstr(infstr, _("Cell: %s"), describenodeproto(np));
339 		poly->string = returninfstr(infstr);
340 		poly->xv[0] = np->highx;
341 		poly->yv[0] = np->lowy;
342 		poly->count = 1;
343 		poly->style = TEXTBOTRIGHT;
344 		TDCLEAR(poly->textdescript);
345 		TDSETSIZE(poly->textdescript, TXTSETQLAMBDA(4));
346 		poly->tech = el_curtech;
347 		poly->desc = &io_black;
348 		(void)io_plotpoly(poly, el_curwindowpart);
349 
350 		/* plot creation date */
351 		infstr = initinfstr();
352 		formatinfstr(infstr, _("Created: %s"), timetostring((time_t)np->creationdate));
353 		poly->string = returninfstr(infstr);
354 		poly->yv[0] = np->lowy + (np->highy-np->lowy) / 20;
355 		(void)io_plotpoly(poly, el_curwindowpart);
356 
357 		/* plot revision date */
358 		infstr = initinfstr();
359 		formatinfstr(infstr, _("Revised: %s"), timetostring((time_t)np->revisiondate));
360 		poly->string = returninfstr(infstr);
361 		poly->yv[0] = np->lowy + (np->highy-np->lowy) / 10;
362 		(void)io_plotpoly(poly, el_curwindowpart);
363 	}
364 
365 	/* clean up */
366 	PrClosePage(plotwin);
367 	PrCloseDoc(plotwin);
368 
369 	/* print if spooled */
370 	if ((*hPrint)->prJob.bJDocLoop == bSpoolLoop)
371 	{
372 		PrPicFile(hPrint, 0, 0, 0, &prstat);
373 	}
374 	PrClose();
375 
376 	/* restore background color */
377 	colormapload(&saver, &saveg, &saveb, 0, 0);
378 	return(FALSE);
379 }
380 
381 /******************** LAYER ORDERING FOR GRAPHIC COPY/PRINT ********************/
382 
383 /*
384  * Routine to set the current plotting layer to "i".
385  */
io_setplotlayer(INTBIG i)386 void io_setplotlayer(INTBIG i)
387 {
388 	io_thislayer = i;
389 }
390 
391 /******************** POLYGON DISPLAY FOR GRAPHIC COPY/PRINT ********************/
392 
io_setbounds(INTBIG slx,INTBIG shx,INTBIG sly,INTBIG shy,INTBIG ulx,INTBIG uhx,INTBIG uly,INTBIG uhy,INTBIG revy,WindowPtr window)393 void io_setbounds(INTBIG slx, INTBIG shx, INTBIG sly, INTBIG shy, INTBIG ulx, INTBIG uhx,
394 	INTBIG uly, INTBIG uhy, INTBIG revy, WindowPtr window)
395 {
396 	static WINDOWPART plotwindow;
397 
398 	io_plotwindow = &plotwindow;
399 	io_plotrevy = revy;
400 	io_plotwin = window;
401 	plotwindow.screenlx = io_slx = slx;
402 	plotwindow.screenhx = io_shx = shx;
403 	plotwindow.screenly = io_sly = sly;
404 	plotwindow.screenhy = io_shy = shy;
405 	plotwindow.uselx = io_ulx = ulx;
406 	plotwindow.usehx = io_uhx = uhx;
407 	plotwindow.usely = io_uly = uly;
408 	plotwindow.usehy = io_uhy = uhy;
409 	plotwindow.state = DISPWINDOW;
410 	computewindowscale(&plotwindow);
411 }
412 
413 /*
414  * routine to plot the polygon "poly"
415  */
io_plotpoly(POLYGON * poly,WINDOWPART * win)416 void io_plotpoly(POLYGON *poly, WINDOWPART *win)
417 {
418 	REGISTER INTBIG k, type;
419 	INTBIG xl, xh, yl, yh, x, y, listx[4], listy[4], size,
420 		centerx, centery, x1p, y1p, x2p, y2p, xa, ya, xb, yb, radius;
421 	INTBIG startangle, endangle, amt, style;
422 	UCHAR1 pat[8];
423 	Rect r;
424 	static POLYGON *polyspline = NOPOLYGON;
425 	REGISTER TECHNOLOGY *tech;
426 
427 	/* ignore null layers */
428 	if (poly->desc->bits == LAYERN || poly->desc->col == ALLOFF) return;
429 
430 	/* only plot the desired layer */
431 	if (io_thislayer < 0)
432 	{
433 		/* first outline filled areas in proper order */
434 		if (poly->layer != -io_thislayer-1) return;
435 		if (poly->style != FILLED && poly->style != FILLEDRECT) return;
436 		if (isbox(poly, &xl, &xh, &yl, &yh))
437 		{
438 			if (xl == xh || yl == yh) return;
439 			io_xform(&xl, &yl);
440 			io_xform(&xh, &yh);
441 			xl--;   yh++;
442 			SetPort(io_plotwin);
443 			PenMode(patCopy);
444 			PenPat(&qd.black);
445 			MoveTo(xl, io_plotrevy-yl);
446 			LineTo(xl, io_plotrevy-yh);
447 			LineTo(xh, io_plotrevy-yh);
448 			LineTo(xh, io_plotrevy-yl);
449 			LineTo(xl, io_plotrevy-yl);
450 		} else
451 		{
452 			/* outlining stipple: expand polygon */
453 			if (poly->count <= 2) return;
454 			centerx = centery = 0;
455 			for(k=0; k<poly->count; k++)
456 			{
457 				centerx += poly->xv[k];   centery += poly->yv[k];
458 			}
459 			centerx /= poly->count;   centery /= poly->count;
460 			io_xform(&centerx, &centery);
461 			for(k=0; k<poly->count; k++)
462 			{
463 				if (k == 0)
464 				{
465 					x1p = poly->xv[poly->count-1];   y1p = poly->yv[poly->count-1];
466 				} else
467 				{
468 					x1p = poly->xv[k-1];   y1p = poly->yv[k-1];
469 				}
470 				x2p = poly->xv[k];     y2p = poly->yv[k];
471 				io_xform(&x1p, &y1p);
472 				io_xform(&x2p, &y2p);
473 				if (x1p < centerx) x1p--;
474 				if (y1p > centery) y1p++;
475 				if (x2p < centerx) x2p--;
476 				if (y2p > centery) y2p++;
477 				SetPort(io_plotwin);
478 				PenMode(patCopy);
479 				PenPat(&qd.black);
480 				MoveTo(x1p, io_plotrevy-y1p);
481 				LineTo(x2p, io_plotrevy-y2p);
482 			}
483 		}
484 		return;
485 	}
486 
487 	if (io_thislayer > 0)
488 	{
489 		/* then draw layers in proper order */
490 		if (poly->layer != io_thislayer-1) return;
491 	} else
492 	{
493 		/* final pass: draw layers not in the technology */
494 		for(k=0; k<io_maxlayer; k++) if (io_nextplotlayer(k) == poly->layer) return;
495 	}
496 
497 	/* ignore grids */
498 	if (poly->style == GRIDDOTS) return;
499 	style = poly->desc->bwstyle;
500 
501 	switch (poly->style)
502 	{
503 		case FILLED:
504 		case FILLEDRECT:
505 			if (isbox(poly, &xl, &xh, &yl, &yh))
506 			{
507 				if (xl == xh)
508 				{
509 					if (yl == yh) io_plotdot(xl, yl); else
510 						io_plotline(xl, yl, xl, yh, 0);
511 					break;
512 				} else if (yl == yh)
513 				{
514 					io_plotline(xl, yl, xh, yl, 0);
515 					break;
516 				}
517 				listx[0] = xl;   listy[0] = yl;
518 				listx[1] = xl;   listy[1] = yh;
519 				listx[2] = xh;   listy[2] = yh;
520 				listx[3] = xh;   listy[3] = yl;
521 				io_plotpolygon(listx, listy, 4, style, poly->desc);
522 			} else
523 			{
524 				if (poly->count == 1)
525 				{
526 					io_plotdot(poly->xv[0], poly->yv[0]);
527 					break;
528 				}
529 				if (poly->count == 2)
530 				{
531 					io_plotline(poly->xv[0], poly->yv[0], poly->xv[1], poly->yv[1], 0);
532 					break;
533 				}
534 				io_plotpolygon(poly->xv, poly->yv, poly->count, style, poly->desc);
535 			}
536 			break;
537 
538 		case CLOSED:
539 		case CLOSEDRECT:
540 		case OPENED:
541 		case OPENEDT1:
542 		case OPENEDT2:
543 		case OPENEDT3:
544 			switch (poly->style)
545 			{
546 				case OPENEDT1: type = 1; break;
547 				case OPENEDT2: type = 2; break;
548 				case OPENEDT3: type = 3; break;
549 				default:       type = 0; break;
550 			}
551 			if (isbox(poly, &xl, &xh, &yl, &yh))
552 			{
553 				io_plotline(xl, yl, xl, yh, type);
554 				io_plotline(xl, yh, xh, yh, type);
555 				io_plotline(xh, yh, xh, yl, type);
556 				if (poly->style == CLOSED || poly->style == CLOSEDRECT)
557 					io_plotline(xh, yl, xl, yl, type);
558 				break;
559 			}
560 			for (k = 1; k < poly->count; k++)
561 				io_plotline(poly->xv[k-1], poly->yv[k-1], poly->xv[k], poly->yv[k], type);
562 			if (poly->style == CLOSED || poly->style == CLOSEDRECT)
563 			{
564 				k = poly->count - 1;
565 				io_plotline(poly->xv[k], poly->yv[k], poly->xv[0], poly->yv[0], type);
566 			}
567 			break;
568 
569 		case VECTORS:
570 			for(k=0; k<poly->count; k += 2)
571 				io_plotline(poly->xv[k], poly->yv[k], poly->xv[k+1], poly->yv[k+1], 0);
572 			break;
573 
574 		case CROSS:
575 		case BIGCROSS:
576 			getcenter(poly, &x, &y);
577 			io_plotline(x-5, y, x+5, y, 0);
578 			io_plotline(x, y+5, x, y-5, 0);
579 			break;
580 
581 		case CROSSED:
582 			getbbox(poly, &xl, &xh, &yl, &yh);
583 			io_plotline(xl, yl, xl, yh, 0);
584 			io_plotline(xl, yh, xh, yh, 0);
585 			io_plotline(xh, yh, xh, yl, 0);
586 			io_plotline(xh, yl, xl, yl, 0);
587 			io_plotline(xh, yh, xl, yl, 0);
588 			io_plotline(xh, yl, xl, yh, 0);
589 			break;
590 
591 		case DISC:
592 			/* filled disc: plot it and its outline (B&W) */
593 			centerx = poly->xv[0];   centery = poly->yv[0];
594 			xa = poly->xv[1];        ya = poly->yv[1];
595 			io_xform(&centerx, &centery);
596 			io_xform(&xa, &ya);
597 			for(k=0; k<8; k++)
598 				pat[k] = (style != PATTERNED ? 0xFF : poly->desc->raster[k]);
599 			radius = computedistance(centerx, centery, xa, ya);
600 			r.left = centerx - radius;
601 			r.right = centerx + radius + 1;
602 			r.top = io_plotrevy - centery - radius;
603 			r.bottom = io_plotrevy - centery + radius + 1;
604 			SetPort(io_plotwin);
605 			PenMode(patCopy);
606 			PenPat((PatPtr)pat);
607 			PaintOval(&r);
608 
609 		case CIRCLE: case THICKCIRCLE:
610 			centerx = poly->xv[0];   centery = poly->yv[0];
611 			xa = poly->xv[1];        ya = poly->yv[1];
612 			io_xform(&centerx, &centery);
613 			io_xform(&xa, &ya);
614 			radius = computedistance(centerx, centery, xa, ya);
615 			r.left = centerx - radius;
616 			r.right = centerx + radius + 1;
617 			r.top = io_plotrevy - centery - radius;
618 			r.bottom = io_plotrevy - centery + radius + 1;
619 			SetPort(io_plotwin);
620 			PenMode(patCopy);
621 			PenPat(&qd.black);
622 			FrameOval(&r);
623 			break;
624 
625 		case CIRCLEARC: case THICKCIRCLEARC:
626 			centerx = poly->xv[0];   centery = poly->yv[0];
627 			xa = poly->xv[1];        ya = poly->yv[1];
628 			xb = poly->xv[2];        yb = poly->yv[2];
629 			io_xform(&centerx, &centery);
630 			io_xform(&xa, &ya);
631 			io_xform(&xb, &yb);
632 
633 			radius = computedistance(centerx, centery, xa, ya);
634 			startangle = figureangle(centerx, centery, xa, ya);
635 			endangle = figureangle(centerx, centery, xb, yb);
636 			if (startangle > endangle) amt = (startangle - endangle + 5) / 10; else
637 				amt = (startangle - endangle + 3600 + 5) / 10;
638 			startangle = ((4500-startangle) % 3600 + 5) / 10;
639 			r.left = centerx - radius;
640 			r.right = centerx + radius + 1;
641 			centery = io_plotrevy - centery;
642 			r.top = centery - radius;
643 			r.bottom = centery + radius + 1;
644 			ya = io_plotrevy - ya;   yb = io_plotrevy - yb;
645 			if (centerx == xa)
646 			{
647 				if (abs(r.top-ya) < abs(r.bottom-ya)) r.top = ya; else r.bottom = ya+1;
648 			}
649 			if (centerx == xb)
650 			{
651 				if (abs(r.top-yb) < abs(r.bottom-yb)) r.top = yb; else r.bottom = yb+1;
652 			}
653 			if (centery == ya)
654 			{
655 				if (abs(r.left-xa) < abs(r.right-xa)) r.left = xa; else r.right = xa+1;
656 			}
657 			if (centery == yb)
658 			{
659 				if (abs(r.left-xb) < abs(r.right-xb)) r.left = xb; else r.right = xb+1;
660 			}
661 			SetPort(io_plotwin);
662 			PenMode(patCopy);
663 			PenPat(&qd.black);
664 			FrameArc(&r, startangle, amt);
665 			break;
666 
667 		case TEXTCENT:
668 		case TEXTTOP:
669 		case TEXTBOT:
670 		case TEXTLEFT:
671 		case TEXTRIGHT:
672 		case TEXTTOPLEFT:
673 		case TEXTBOTLEFT:
674 		case TEXTTOPRIGHT:
675 		case TEXTBOTRIGHT:
676 		case TEXTBOX:
677 			tech = win->curnodeproto->tech;
678 			size = truefontsize(TDGETSIZE(poly->textdescript), io_plotwindow, tech);
679 			getbbox(poly, &xl, &xh, &yl, &yh);
680 			io_plottext(poly->style, xl, xh, yl, yh, size, poly->string);
681 			break;
682 	}
683 }
684 
io_plotdot(INTBIG x,INTBIG y)685 void io_plotdot(INTBIG x, INTBIG y)
686 {
687 	Rect r;
688 
689 	io_xform(&x, &y);
690 
691 	r.left = x;          r.right = x+1;
692 	r.top = io_plotrevy-y;   r.bottom = io_plotrevy-y+1;
693 	SetPort(io_plotwin);
694 	FillRect(&r, &qd.black);
695 }
696 
697 /* draw a line */
io_plotline(INTBIG x1,INTBIG y1,INTBIG x2,INTBIG y2,INTBIG pattern)698 void io_plotline(INTBIG x1, INTBIG y1, INTBIG x2, INTBIG y2, INTBIG pattern)
699 {
700 	static UCHAR1 pat0[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
701 	static UCHAR1 pat1h[] = {0xFF, 0, 0, 0, 0xFF, 0, 0, 0};
702 	static UCHAR1 pat1v[] = {0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88};
703 	static UCHAR1 pat2h[] = {0xFF, 0xFF, 0xFF, 0, 0, 0xFF, 0xFF, 0xFF};
704 	static UCHAR1 pat2v[] = {0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7};
705 	static UCHAR1 *patlisth[] = {pat0, pat1h, pat2h, pat0};
706 	static UCHAR1 *patlistv[] = {pat0, pat1v, pat2v, pat0};
707 
708 	io_xform(&x1, &y1);
709 	io_xform(&x2, &y2);
710 
711 	/* do it on the printer */
712 	SetPort(io_plotwin);
713 	PenMode(patCopy);
714 	if (abs(x1-x2) > abs(y1-y2)) PenPat((PatPtr)patlistv[pattern]); else
715 		PenPat((PatPtr)patlisth[pattern]);
716 	if (pattern == 3) PenSize(3, 3);
717 	MoveTo(x1, io_plotrevy-y1);
718 	LineTo(x2, io_plotrevy-y2);
719 	if (pattern == 3) PenSize(1, 1);
720 }
721 
io_plotpolygon(INTBIG * x,INTBIG * y,INTBIG count,INTBIG style,GRAPHICS * desc)722 void io_plotpolygon(INTBIG *x, INTBIG *y, INTBIG count, INTBIG style, GRAPHICS *desc)
723 {
724 	INTBIG i;
725 	UCHAR1 pat[8];
726 	PolyHandle polyhandle;
727 	static INTBIG *myx, *myy;
728 	static INTBIG len = 0;
729 
730 	if (count == 0) return;
731 	if (count > len)
732 	{
733 		if (len != 0)
734 		{
735 			DisposePtr((Ptr)myx);   DisposePtr((Ptr)myy);
736 		}
737 		len = 0;
738 		myx = (INTBIG *)NewPtr(count * SIZEOFINTBIG);
739 		myy = (INTBIG *)NewPtr(count * SIZEOFINTBIG);
740 		if (myx == 0 || myy == 0) return;
741 		len = count;
742 	}
743 	for(i=0; i<count; i++)
744 	{
745 		myx[i] = x[i];
746 		myy[i] = y[i];
747 		io_xform(&myx[i], &myy[i]);
748 	}
749 
750 	for(i=0; i<8; i++)
751 		pat[i] = (style != PATTERNED ? 0xFF : desc->raster[i]);
752 	SetPort(io_plotwin);
753 	polyhandle = OpenPoly();
754 	MoveTo(myx[count-1], io_plotrevy-myy[count-1]);
755 	for(i=0; i<count; i++) LineTo(myx[i], io_plotrevy-myy[i]);
756 	ClosePoly();
757 	PenMode(patOr);
758 	PenPat((PatPtr)pat);
759 	PaintPoly(polyhandle);
760 	KillPoly(polyhandle);
761 }
762 
io_plottext(INTBIG type,INTBIG lx,INTBIG ux,INTBIG ly,INTBIG uy,INTBIG size,CHAR * text)763 void io_plottext(INTBIG type, INTBIG lx, INTBIG ux, INTBIG ly, INTBIG uy, INTBIG size,
764 	CHAR *text)
765 {
766 	CHAR localstring[256];
767 	INTBIG len, i, tsx, tsy, px, py, truesize;
768 	FontInfo fontinfo;
769 
770 	io_xform(&lx, &ly);
771 	io_xform(&ux, &uy);
772 
773 	len = estrlen(text);
774 	for(i=0; i<len; i++) localstring[i] = text[i];
775 	TextFont(HFONT);
776 	if (type == TEXTBOX)
777 	{
778 		/* scan for a font that fits */
779 		for(truesize = size; truesize >= 4; truesize--)
780 		{
781 			TextSize(truesize);
782 			GetFontInfo(&fontinfo);
783 			tsx = TextWidth(localstring, 0, len);
784 			tsy = fontinfo.ascent + fontinfo.descent + fontinfo.leading;
785 			if (tsx <= ux-lx && tsy <= uy-ly) break;
786 		}
787 
788 		/* continue only if text fits in Y */
789 		if (tsy <= uy-ly)
790 		{
791 			/* truncate in X if necessary */
792 			while (len > 1 && tsx > ux-lx)
793 			{
794 				len--;
795 				tsx = TextWidth(localstring, 0, len);
796 			}
797 
798 			/* continue only if text fits */
799 			if (tsx <= ux-lx)
800 			{
801 				/* draw the text */
802 				MoveTo(lx+(ux-lx-tsx)/2, io_plotrevy-(ly+(uy-ly-tsy)/2)-fontinfo.descent);
803 				TextMode(srcOr+64);
804 				DrawText(localstring, 0, len);
805 			}
806 		}
807 	} else
808 	{
809 		TextSize(size);
810 		GetFontInfo(&fontinfo);
811 		tsx = TextWidth(localstring, 0, len);
812 		tsy = fontinfo.ascent + fontinfo.descent + fontinfo.leading;
813 		switch (type)
814 		{
815 			case TEXTCENT:
816 				px = maxi(io_ulx,(lx+ux-tsx)/2);
817 				py = maxi(io_uly,(ly+uy-tsy)/2);
818 				break;
819 			case TEXTTOP:
820 				px = maxi(io_ulx,(lx+ux-tsx)/2);
821 				py = maxi(io_uly,uy-tsy);
822 				break;
823 			case TEXTBOT:
824 				px = maxi(io_ulx,(lx+ux-tsx)/2);
825 				py = ly;
826 				break;
827 			case TEXTLEFT:
828 				px = lx;
829 				py = maxi(io_uly,(ly+uy-tsy)/2);
830 				break;
831 			case TEXTRIGHT:
832 				px = maxi(io_ulx,ux-tsx);
833 				py = maxi(io_uly,(ly+uy-tsy)/2);
834 				break;
835 			case TEXTTOPLEFT:
836 				px = lx;
837 				py = maxi(io_uly,uy-tsy);
838 				break;
839 			case TEXTBOTLEFT:
840 				px = lx;
841 				py = ly;
842 				break;
843 			case TEXTTOPRIGHT:
844 				px = maxi(io_ulx,ux-tsx);
845 				py = maxi(io_uly,uy-tsy);
846 				break;
847 			case TEXTBOTRIGHT:
848 				px = maxi(io_ulx,ux-tsx);
849 				py = ly;
850 				break;
851 		}
852 		MoveTo(px, io_plotrevy-py-fontinfo.descent);
853 		TextMode(srcOr+64);
854 		DrawText(localstring, 0, len);
855 	}
856 }
857 
858 /*
859  * Routine to convert the coordinates (x,y) for display.  The coordinates for
860  * printing are placed back into (x,y) and the PostScript coordinates are placed
861  * in (psx,psy).
862  */
io_xform(INTBIG * x,INTBIG * y)863 void io_xform(INTBIG *x, INTBIG *y)
864 {
865 	*x = muldiv(*x-io_slx, io_uhx-io_ulx, io_shx-io_slx) + io_ulx;
866 	*y = muldiv(*y-io_sly, io_uhy-io_uly, io_shy-io_sly) + io_uly;
867 }
868 
869 /******************** GRAPHIC COPY ********************/
870 
871 /*
872  * routine to copy the highlighted graphics to the clipboard.  Called from
873  * "usrcomtv.c:us_text()"
874  */
io_maccopyhighlighted(void)875 void io_maccopyhighlighted(void)
876 {
877 	PicHandle picture;
878 	INTBIG len, slx, shx, sly, shy, ulx, uhx, uly, uhy, revy;
879 	INTBIG ix;
880 	CGrafPtr realwindow;
881 	extern CGrafPtr gra_getwindow(WINDOWPART *win);
882 
883 	/* initialize for copying */
884 	ZeroScrap();
885 	realwindow = gra_getwindow(el_curwindowpart);
886 	SetPort((WindowPtr)realwindow);
887 	ClipRect(&qd.thePort->portRect);
888 	picture = OpenPicture(&realwindow->portRect);
889 
890 	/* establish order of plotting layers */
891 	io_maxlayer = io_setuptechorder(el_curtech);
892 
893 	/* setup window for copy */
894 	(void)us_getareabounds(&slx, &shx, &sly, &shy);
895 	ulx = slx;   uhx = shx;
896 	uly = sly;   uhy = shy;
897 	(void)us_makescreen(&ulx, &uly, &uhx, &uhy, el_curwindowpart);
898 
899 #if 0		/* this will make a color copy in the clipboard */
900 	{
901 		Rect sr;
902 		CGrafPtr window;
903 		INTBIG revy, swid, shei;
904 
905 		window = gra_getoffscreen(el_curwindowpart);
906 		getwindowframesize(el_curwindowpart->frame, &swid, &shei);
907 		revy = shei - 1;
908 
909 		sr.left = ulx;   sr.right = uhx;
910 		sr.top = revy - uhy;    sr.bottom = revy - uly;
911 
912 		/* now copy the offscreen bits at "sr" to the print port at "dr" */
913 		(void)LockPixels(window->portPixMap);
914 		CopyBits((BitMap *)*(window->portPixMap), (BitMap *)*(realwindow->portPixMap),
915 			&sr, &sr, srcCopy, 0L);
916 		UnlockPixels(window->portPixMap);
917 
918 		ClosePicture();
919 		HLock((Handle)picture);
920 		len = (*picture)->picSize;
921 		PutScrap(len, 'PICT', (Ptr)(*picture));
922 		HUnlock((Handle)picture);
923 		KillPicture(picture);
924 		return(0);
925 	}
926 #endif
927 
928 	uhx -= ulx;   uhy -= uly;   ulx = uly = 0;
929 	revy = uhy;
930 	io_setbounds(slx, shx, sly, shy, ulx, uhx, uly, uhy, revy, (WindowPtr)realwindow);
931 	io_plotwindow = el_curwindowpart;
932 
933 	/* plot layers in this technology in proper order */
934 	for(ix=0; ix<io_maxlayer; ix++)
935 	{
936 		/* first plot outlines around stipple layers */
937 		io_setplotlayer(-(io_nextplotlayer(ix) + 1));
938 		(void)asktool(us_tool, x_("display-highlighted-to-routine"), io_plotpoly);
939 
940 		/* next plot layers */
941 		io_setplotlayer(io_nextplotlayer(ix) + 1);
942 		(void)asktool(us_tool, x_("display-highlighted-to-routine"), io_plotpoly);
943 	}
944 
945 	/* finally plot layers not in the technology */
946 	io_setplotlayer(0);
947 	(void)asktool(us_tool, x_("display-highlighted-to-routine"), io_plotpoly);
948 
949 	ClosePicture();
950 	HLock((Handle)picture);
951 	len = (*picture)->picSize;
952 	PutScrap(len, 'PICT', (Ptr)(*picture));
953 	HUnlock((Handle)picture);
954 	KillPicture(picture);
955 }
956 
957 #endif  /* MACOS - at top */
958