1 /* -*- tab-width: 4 -*-
2  *
3  * Electric(tm) VLSI Design Systems
4  *
5  * File: graphcommon.cpp
6  * Drawing graphics primitives into off-screen buffer
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 "global.h"
33 #include "edialogs.h"
34 #include "egraphics.h"
35 #include "usr.h"
36 #include <errno.h>
37 
38 #define USE_MEMMOVE						/* use memmove & memcpy */
39 
40 #if 0		/* for checking display coordinates */
41 #  define CHECKCOORD(wf, x, y, where)
42 #else
43 #  define CHECKCOORD(wf, x, y, where) if (gra_badcoord(wf, x, y, where)) return
44 #endif
45 static INTBIG  gra_badcoord(WINDOWFRAME *wf, INTBIG x, INTBIG y, CHAR *where);
46 
47 /****** line drawing ******/
48 static void    gra_drawsolidline(WINDOWFRAME *wf, INTBIG x1, INTBIG y1, INTBIG x2, INTBIG y2, INTBIG col, INTBIG mask);
49 static void    gra_drawpatline(WINDOWFRAME *wf, INTBIG x1, INTBIG y1, INTBIG x2, INTBIG y2, INTBIG col,
50                            INTBIG mask, INTBIG pattern);
51 static void    gra_drawthickline(WINDOWFRAME *wf, INTBIG x1, INTBIG y1, INTBIG x2, INTBIG y2, INTBIG col, INTBIG mask);
52 static void    gra_drawthickpoint(WINDOWFRAME *wf, INTBIG x, INTBIG y, INTBIG mask, INTBIG col);
53 
54 /****** rectangle saving ******/
55 #define NOSAVEDBOX ((SAVEDBOX *)-1)
56 typedef struct Isavedbox
57 {
58 	UCHAR1      *pix;
59 	WINDOWFRAME *wf;
60 	INTBIG      lx, hx, ly, hy;
61 } SAVEDBOX;
62 
63 /****** polygon decomposition ******/
64 #define NOPOLYSEG ((POLYSEG *)-1)
65 
66 typedef struct Isegment
67 {
68 	INTBIG fx,fy, tx,ty, direction, increment;
69 	struct Isegment *nextedge;
70 	struct Isegment *nextactive;
71 } POLYSEG;
72 
73 static POLYSEG    *gra_polysegs;
74 static INTBIG     gra_polysegcount = 0;
75 
76 /****** curve drawing ******/
77 #define MODM(x) ((x<1) ? x+8 : x)
78 #define MODP(x) ((x>8) ? x-8 : x)
79 #define ODD(x)  (x&1)
80 
81 static INTBIG        gra_arcocttable[] = {0,0,0,0,0,0,0,0,0};
82 static INTBIG        gra_arccenterx, gra_arccentery;
83 static INTBIG        gra_arcradius, gra_curveminx, gra_curveminy, gra_curvemaxx, gra_curvemaxy;
84 static INTBIG        gra_arclx, gra_archx, gra_arcly, gra_archy;
85 static INTBIG        gra_curvecol, gra_curvemask, gra_curvestyle, gra_arcfirst;
86 static BOOLEAN       gra_arcthick;
87 
88 static INTBIG  gra_arcfindoctant(INTBIG x, INTBIG y);
89 static void    gra_arcxformoctant(INTBIG x, INTBIG y, INTBIG oct, INTBIG *ox, INTBIG *oy);
90 static void    gra_arcdopixel(WINDOWFRAME *wf, INTBIG x, INTBIG y);
91 static void    gra_arcoutxform(WINDOWFRAME *wf, INTBIG x, INTBIG y);
92 static void    gra_arcbrescw(WINDOWFRAME *wf, INTBIG x, INTBIG y, INTBIG x1, INTBIG y1);
93 static void    gra_arcbresmidcw(WINDOWFRAME *wf, INTBIG x, INTBIG y);
94 static void    gra_arcbresmidccw(WINDOWFRAME *wf, INTBIG x, INTBIG y);
95 static void    gra_arcbresccw(WINDOWFRAME *wf, INTBIG x, INTBIG y, INTBIG x1, INTBIG y1);
96 static void    gra_drawdiscrow(WINDOWFRAME *wf, INTBIG thisy, INTBIG startx, INTBIG endx, GRAPHICS *desc);
97 
gra_termgraph(void)98 void gra_termgraph(void)
99 {
100 	if (gra_polysegcount > 0) efree((CHAR *)gra_polysegs);
101 }
102 
gra_badcoord(WINDOWFRAME * wf,INTBIG x,INTBIG y,CHAR * where)103 static INTBIG gra_badcoord(WINDOWFRAME *wf, INTBIG x, INTBIG y, CHAR *where )
104 {
105 	INTBIG height;
106 
107 #if !defined(USEQT) && defined(ONUNIX)
108 	height = wf->trueheight;
109 #else
110 	height = wf->shei;
111 #endif
112 
113 	if (x < 0 || x >= wf->swid || y < 0 || y >= height)
114 	{
115 		Q_UNUSED( where );
116 		return(1);
117 	}
118 	return(0);
119 }
120 
121 /******************** GRAPHICS LINES ********************/
122 
123 /*
124  * Routine to draw a line on the off-screen buffer.
125  */
gra_drawline(WINDOWPART * win,INTBIG x1,INTBIG y1,INTBIG x2,INTBIG y2,GRAPHICS * desc,INTBIG texture)126 void gra_drawline(WINDOWPART *win, INTBIG x1, INTBIG y1, INTBIG x2, INTBIG y2, GRAPHICS *desc,
127 	INTBIG texture)
128 {
129 	REGISTER INTBIG col, mask, lx, hx, ly, hy;
130 	REGISTER WINDOWFRAME *wf;
131 
132 	/* get line type parameters */
133 	wf = win->frame;
134 	col = desc->col;      mask = ~desc->bits;
135 	y1 = wf->revy - y1;   y2 = wf->revy - y2;
136 	CHECKCOORD(wf, x1, y1, x_("line"));
137 	CHECKCOORD(wf, x2, y2, x_("line"));
138 
139 	switch (texture)
140 	{
141 		case 0: gra_drawsolidline(wf, x1, y1, x2, y2, col, mask);       break;
142 		case 1: gra_drawpatline(wf, x1, y1, x2, y2, col, mask, 0x88);   break;
143 		case 2: gra_drawpatline(wf, x1, y1, x2, y2, col, mask, 0xE7);   break;
144 		case 3: gra_drawthickline(wf, x1, y1, x2, y2, col, mask);       break;
145 	}
146 	if (x1 < x2) { lx = x1;   hx = x2; } else { lx = x2;   hx = x1; }
147 	if (y1 < y2) { ly = y1;   hy = y2; } else { ly = y2;   hy = y1; }
148 	if (texture == 3)
149 	{
150 		lx--;   hx++;
151 		ly--;   hy++;
152 	}
153 	gra_setrect(wf, lx, hx+1, ly, hy+1);
154 }
155 
156 /*
157  * Routine to invert bits of the line on the off-screen buffer
158  */
gra_invertline(WINDOWPART * win,INTBIG x1,INTBIG y1,INTBIG x2,INTBIG y2)159 void gra_invertline(WINDOWPART *win, INTBIG x1, INTBIG y1, INTBIG x2, INTBIG y2)
160 {
161 	REGISTER WINDOWFRAME *wf;
162 	REGISTER INTBIG lx, hx, ly, hy, dx, dy, d, incr1, incr2, x, y, xend, yend, yincr, xincr;
163 
164 	/* get line type parameters */
165 	wf = win->frame;
166 	y1 = wf->revy - y1;   y2 = wf->revy - y2;
167 	CHECKCOORD(wf, x1, y1, x_("invline"));
168 	CHECKCOORD(wf, x2, y2, x_("invline"));
169 
170 	/* initialize the Bresenham algorithm */
171 	dx = abs(x2-x1);
172 	dy = abs(y2-y1);
173 	if (dx > dy)
174 	{
175 		/* initialize for lines that increment along X */
176 		incr1 = 2 * dy;
177 		d = incr2 = 2 * (dy - dx);
178 		if (x1 > x2)
179 		{
180 			x = x2;   y = y2;   xend = x1;   yend = y1;
181 		} else
182 		{
183 			x = x1;   y = y1;   xend = x2;   yend = y2;
184 		}
185 		if (yend < y) yincr = -1; else yincr = 1;
186 		wf->rowstart[y][x] = ~wf->rowstart[y][x];
187 
188 		/* draw line that increments along X */
189 		while (x < xend)
190 		{
191 			x++;
192 			if (d < 0) d += incr1; else
193 			{
194 				y += yincr;   d += incr2;
195 			}
196 			wf->rowstart[y][x] = ~wf->rowstart[y][x];
197 		}
198 	} else
199 	{
200 		/* initialize for lines that increment along Y */
201 		incr1 = 2 * dx;
202 		d = incr2 = 2 * (dx - dy);
203 		if (y1 > y2)
204 		{
205 			x = x2;   y = y2;   xend = x1;   yend = y1;
206 		} else
207 		{
208 			x = x1;   y = y1;   xend = x2;   yend = y2;
209 		}
210 		if (xend < x) xincr = -1; else xincr = 1;
211 		wf->rowstart[y][x] = ~wf->rowstart[y][x];
212 
213 		/* draw line that increments along X */
214 		while (y < yend)
215 		{
216 			y++;
217 			if (d < 0) d += incr1; else
218 			{
219 				x += xincr;   d += incr2;
220 			}
221 			wf->rowstart[y][x] = ~wf->rowstart[y][x];
222 		}
223 	}
224 	if (x1 < x2) { lx = x1;   hx = x2; } else { lx = x2;   hx = x1; }
225 	if (y1 < y2) { ly = y1;   hy = y2; } else { ly = y2;   hy = y1; }
226 	gra_setrect(wf, lx, hx+1, ly, hy+1);
227 }
228 
gra_drawpatline(WINDOWFRAME * wf,INTBIG x1,INTBIG y1,INTBIG x2,INTBIG y2,INTBIG col,INTBIG mask,INTBIG pattern)229 static void gra_drawpatline(WINDOWFRAME *wf, INTBIG x1, INTBIG y1, INTBIG x2, INTBIG y2, INTBIG col,
230 	INTBIG mask, INTBIG pattern)
231 {
232 	INTBIG dx, dy, d, incr1, incr2, x, y, xend, yend, yincr, xincr, i;
233 
234 	/* initialize counter for line style */
235 	i = 0;
236 
237 	/* initialize the Bresenham algorithm */
238 	dx = abs(x2-x1);
239 	dy = abs(y2-y1);
240 	if (dx > dy)
241 	{
242 		/* initialize for lines that increment along X */
243 		incr1 = 2 * dy;
244 		d = incr2 = 2 * (dy - dx);
245 		if (x1 > x2)
246 		{
247 			x = x2;   y = y2;   xend = x1;   yend = y1;
248 		} else
249 		{
250 			x = x1;   y = y1;   xend = x2;   yend = y2;
251 		}
252 		if (yend < y) yincr = -1; else yincr = 1;
253 		wf->rowstart[y][x] = (UCHAR1)((wf->rowstart[y][x]&mask) | col);
254 
255 		/* draw line that increments along X */
256 		while (x < xend)
257 		{
258 			x++;
259 			if (d < 0) d += incr1; else
260 			{
261 				y += yincr;   d += incr2;
262 			}
263 			if (i == 7) i = 0; else i++;
264 			if ((pattern & (1 << i)) == 0) continue;
265 			wf->rowstart[y][x] = (UCHAR1)((wf->rowstart[y][x]&mask) | col);
266 		}
267 	} else
268 	{
269 		/* initialize for lines that increment along Y */
270 		incr1 = 2 * dx;
271 		d = incr2 = 2 * (dx - dy);
272 		if (y1 > y2)
273 		{
274 			x = x2;   y = y2;   xend = x1;   yend = y1;
275 		} else
276 		{
277 			x = x1;   y = y1;   xend = x2;   yend = y2;
278 		}
279 		if (xend < x) xincr = -1; else xincr = 1;
280 		wf->rowstart[y][x] = (UCHAR1)((wf->rowstart[y][x]&mask) | col);
281 
282 		/* draw line that increments along X */
283 		while (y < yend)
284 		{
285 			y++;
286 			if (d < 0) d += incr1; else
287 			{
288 				x += xincr;   d += incr2;
289 			}
290 			if (i == 7) i = 0; else i++;
291 			if ((pattern & (1 << i)) == 0) continue;
292 			wf->rowstart[y][x] = (UCHAR1)((wf->rowstart[y][x]&mask) | col);
293 		}
294 	}
295 }
296 
gra_drawsolidline(WINDOWFRAME * wf,INTBIG x1,INTBIG y1,INTBIG x2,INTBIG y2,INTBIG col,INTBIG mask)297 static void gra_drawsolidline(WINDOWFRAME *wf, INTBIG x1, INTBIG y1, INTBIG x2, INTBIG y2, INTBIG col, INTBIG mask)
298 {
299 	INTBIG dx, dy, d, incr1, incr2, x, y, xend, yend, yincr, xincr;
300 
301 	/* initialize the Bresenham algorithm */
302 	dx = abs(x2-x1);
303 	dy = abs(y2-y1);
304 	if (dx > dy)
305 	{
306 		/* initialize for lines that increment along X */
307 		incr1 = 2 * dy;
308 		d = incr2 = 2 * (dy - dx);
309 		if (x1 > x2)
310 		{
311 			x = x2;   y = y2;   xend = x1;   yend = y1;
312 		} else
313 		{
314 			x = x1;   y = y1;   xend = x2;   yend = y2;
315 		}
316 		if (yend < y) yincr = -1; else yincr = 1;
317 		wf->rowstart[y][x] = (UCHAR1)((wf->rowstart[y][x]&mask) | col);
318 
319 		/* draw line that increments along X */
320 		while (x < xend)
321 		{
322 			x++;
323 			if (d < 0) d += incr1; else
324 			{
325 				y += yincr;   d += incr2;
326 			}
327 			wf->rowstart[y][x] = (UCHAR1)((wf->rowstart[y][x]&mask) | col);
328 		}
329 	} else
330 	{
331 		/* initialize for lines that increment along Y */
332 		incr1 = 2 * dx;
333 		d = incr2 = 2 * (dx - dy);
334 		if (y1 > y2)
335 		{
336 			x = x2;   y = y2;   xend = x1;   yend = y1;
337 		} else
338 		{
339 			x = x1;   y = y1;   xend = x2;   yend = y2;
340 		}
341 		if (xend < x) xincr = -1; else xincr = 1;
342 		wf->rowstart[y][x] = (UCHAR1)((wf->rowstart[y][x]&mask) | col);
343 
344 		/* draw line that increments along X */
345 		while (y < yend)
346 		{
347 			y++;
348 			if (d < 0) d += incr1; else
349 			{
350 				x += xincr;   d += incr2;
351 			}
352 			wf->rowstart[y][x] = (UCHAR1)((wf->rowstart[y][x]&mask) | col);
353 		}
354 	}
355 }
356 
gra_drawthickline(WINDOWFRAME * wf,INTBIG x1,INTBIG y1,INTBIG x2,INTBIG y2,INTBIG col,INTBIG mask)357 static void gra_drawthickline(WINDOWFRAME *wf, INTBIG x1, INTBIG y1, INTBIG x2, INTBIG y2, INTBIG col, INTBIG mask)
358 {
359 	INTBIG dx, dy, d, incr1, incr2, x, y, xend, yend, yincr, xincr;
360 
361 	/* initialize the Bresenham algorithm */
362 	dx = abs(x2-x1);
363 	dy = abs(y2-y1);
364 	if (dx > dy)
365 	{
366 		/* initialize for lines that increment along X */
367 		incr1 = 2 * dy;
368 		d = incr2 = 2 * (dy - dx);
369 		if (x1 > x2)
370 		{
371 			x = x2;   y = y2;   xend = x1;   yend = y1;
372 		} else
373 		{
374 			x = x1;   y = y1;   xend = x2;   yend = y2;
375 		}
376 		if (yend < y) yincr = -1; else yincr = 1;
377 		gra_drawthickpoint(wf, x, y, mask, col);
378 
379 		/* draw line that increments along X */
380 		while (x < xend)
381 		{
382 			x++;
383 			if (d < 0) d += incr1; else
384 			{
385 				y += yincr;
386 				d += incr2;
387 			}
388 			gra_drawthickpoint(wf, x, y, mask, col);
389 		}
390 	} else
391 	{
392 		/* initialize for lines that increment along Y */
393 		incr1 = 2 * dx;
394 		d = incr2 = 2 * (dx - dy);
395 		if (y1 > y2)
396 		{
397 			x = x2;   y = y2;   xend = x1;   yend = y1;
398 		} else
399 		{
400 			x = x1;   y = y1;   xend = x2;   yend = y2;
401 		}
402 		if (xend < x) xincr = -1; else xincr = 1;
403 		gra_drawthickpoint(wf, x, y, mask, col);
404 
405 		/* draw line that increments along X */
406 		while (y < yend)
407 		{
408 			y++;
409 			if (d < 0) d += incr1; else
410 			{
411 				x += xincr;
412 				d += incr2;
413 			}
414 			gra_drawthickpoint(wf, x, y, mask, col);
415 		}
416 	}
417 }
418 
gra_drawthickpoint(WINDOWFRAME * wf,INTBIG x,INTBIG y,INTBIG mask,INTBIG col)419 static void gra_drawthickpoint(WINDOWFRAME *wf, INTBIG x, INTBIG y, INTBIG mask, INTBIG col)
420 {
421 	wf->rowstart[y][x] = (UCHAR1)((wf->rowstart[y][x]&mask) | col);
422 	if (x > 0)
423 		wf->rowstart[y][x-1] = (UCHAR1)((wf->rowstart[y][x-1]&mask) | col);
424 	if (x < wf->swid-1)
425 		wf->rowstart[y][x+1] = (UCHAR1)((wf->rowstart[y][x+1]&mask) | col);
426 	if (y > 0)
427 		wf->rowstart[y-1][x] = (UCHAR1)((wf->rowstart[y-1][x]&mask) | col);
428 	if (y < wf->shei-1)
429 		wf->rowstart[y+1][x] = (UCHAR1)((wf->rowstart[y+1][x]&mask) | col);
430 }
431 
432 /******************** GRAPHICS POLYGONS ********************/
433 
434 /*
435  * Routine to draw a polygon on the off-screen buffer.
436  */
gra_drawpolygon(WINDOWPART * win,INTBIG * x,INTBIG * y,INTBIG count,GRAPHICS * desc)437 void gra_drawpolygon(WINDOWPART *win, INTBIG *x, INTBIG *y, INTBIG count, GRAPHICS *desc)
438 {
439 	REGISTER INTBIG i, j, k, l, ycur=0, yrev, wrap, lx=0, hx=0, ly=0, hy=0;
440 	REGISTER UCHAR1 *row;
441 	REGISTER INTBIG col, mask, style, pat;
442 	REGISTER POLYSEG *a, *active, *edge, *lastedge, *left, *edgelist;
443 	REGISTER WINDOWFRAME *wf;
444 
445 	/* get parameters */
446 	wf = win->frame;
447 	col = desc->col;   mask = ~desc->bits;
448 	style = desc->colstyle & NATURE;
449 
450 	/* set redraw area */
451 	for(i=0; i<count; i++)
452 	{
453 		CHECKCOORD(wf, x[i], y[i], x_("polygon"));
454 		if (i == 0)
455 		{
456 			lx = hx = x[i];
457 			ly = hy = y[i];
458 		} else
459 		{
460 			lx = mini(lx, x[i]);
461 			hx = maxi(hx, x[i]);
462 			ly = mini(ly, y[i]);
463 			hy = maxi(hy, y[i]);
464 		}
465 	}
466 	gra_setrect(wf, lx, hx + 1, wf->revy-hy, wf->revy-ly + 1);
467 
468 	/* make sure there is room in internal structures */
469 	if (count > gra_polysegcount)
470 	{
471 		if (gra_polysegcount > 0) efree((CHAR *)gra_polysegs);
472 		gra_polysegcount = 0;
473 		gra_polysegs = (POLYSEG *)emalloc(count * (sizeof (POLYSEG)), us_tool->cluster);
474 		if (gra_polysegs == 0) return;
475 		gra_polysegcount = count;
476 	}
477 
478 	/* fill in internal structures */
479 	edgelist = NOPOLYSEG;
480 	for(i=0; i<count; i++)
481 	{
482 		if (i == 0)
483 		{
484 			gra_polysegs[i].fx = x[count-1];
485 			gra_polysegs[i].fy = y[count-1];
486 		} else
487 		{
488 			gra_polysegs[i].fx = x[i-1];
489 			gra_polysegs[i].fy = y[i-1];
490 		}
491 		gra_polysegs[i].tx = x[i];   gra_polysegs[i].ty = y[i];
492 
493 		/* draw the edge lines to make the polygon clean */
494 		if ((desc->colstyle&(NATURE|OUTLINEPAT)) != PATTERNED)
495 			gra_drawsolidline(wf, gra_polysegs[i].fx, (wf->revy - gra_polysegs[i].fy),
496 				gra_polysegs[i].tx, (wf->revy - gra_polysegs[i].ty), col, mask);
497 
498 		/* compute the direction of this edge */
499 		j = gra_polysegs[i].ty - gra_polysegs[i].fy;
500 		if (j > 0) gra_polysegs[i].direction = 1; else
501 			if (j < 0) gra_polysegs[i].direction = -1; else
502 				gra_polysegs[i].direction = 0;
503 
504 		/* compute the X increment of this edge */
505 		if (j == 0) gra_polysegs[i].increment = 0; else
506 		{
507 			gra_polysegs[i].increment = gra_polysegs[i].tx - gra_polysegs[i].fx;
508 			if (gra_polysegs[i].increment != 0) gra_polysegs[i].increment =
509 				(gra_polysegs[i].increment * 65536 - j + 1) / j;
510 		}
511 		gra_polysegs[i].tx <<= 16;   gra_polysegs[i].fx <<= 16;
512 
513 		/* make sure "from" is above "to" */
514 		if (gra_polysegs[i].fy > gra_polysegs[i].ty)
515 		{
516 			j = gra_polysegs[i].tx;
517 			gra_polysegs[i].tx = gra_polysegs[i].fx;
518 			gra_polysegs[i].fx = j;
519 			j = gra_polysegs[i].ty;
520 			gra_polysegs[i].ty = gra_polysegs[i].fy;
521 			gra_polysegs[i].fy = j;
522 		}
523 
524 		/* insert this edge into the edgelist, sorted by ascending "fy" */
525 		if (edgelist == NOPOLYSEG)
526 		{
527 			edgelist = &gra_polysegs[i];
528 			gra_polysegs[i].nextedge = NOPOLYSEG;
529 		} else
530 		{
531 			/* insert by ascending "fy" */
532 			if (edgelist->fy > gra_polysegs[i].fy)
533 			{
534 				gra_polysegs[i].nextedge = edgelist;
535 				edgelist = &gra_polysegs[i];
536 			} else for(a = edgelist; a != NOPOLYSEG; a = a->nextedge)
537 			{
538 				if (a->nextedge == NOPOLYSEG ||
539 					a->nextedge->fy > gra_polysegs[i].fy)
540 				{
541 					/* insert after this */
542 					gra_polysegs[i].nextedge = a->nextedge;
543 					a->nextedge = &gra_polysegs[i];
544 					break;
545 				}
546 			}
547 		}
548 	}
549 
550 	/* scan polygon and render */
551 	active = NOPOLYSEG;
552 	while (active != NOPOLYSEG || edgelist != NOPOLYSEG)
553 	{
554 		if (active == NOPOLYSEG)
555 		{
556 			active = edgelist;
557 			active->nextactive = NOPOLYSEG;
558 			edgelist = edgelist->nextedge;
559 			ycur = active->fy;
560 		}
561 
562 		/* introduce edges from edge list into active list */
563 		while (edgelist != NOPOLYSEG && edgelist->fy <= ycur)
564 		{
565 			/* insert "edgelist" into active list, sorted by "fx" coordinate */
566 			if (active->fx > edgelist->fx ||
567 				(active->fx == edgelist->fx && active->increment > edgelist->increment))
568 			{
569 				edgelist->nextactive = active;
570 				active = edgelist;
571 				edgelist = edgelist->nextedge;
572 			} else for(a = active; a != NOPOLYSEG; a = a->nextactive)
573 			{
574 				if (a->nextactive == NOPOLYSEG ||
575 					a->nextactive->fx > edgelist->fx ||
576 						(a->nextactive->fx == edgelist->fx &&
577 							a->nextactive->increment > edgelist->increment))
578 				{
579 					/* insert after this */
580 					edgelist->nextactive = a->nextactive;
581 					a->nextactive = edgelist;
582 					edgelist = edgelist->nextedge;
583 					break;
584 				}
585 			}
586 		}
587 
588 		/* generate regions to be filled in on current scan line */
589 		wrap = 0;
590 		left = active;
591 		for(edge = active; edge != NOPOLYSEG; edge = edge->nextactive)
592 		{
593 			wrap = wrap + edge->direction;
594 			if (wrap == 0)
595 			{
596 				j = (left->fx + 32768) >> 16;
597 				k = (edge->fx + 32768) >> 16;
598 				yrev = wf->revy - ycur;
599 				row = wf->rowstart[yrev];
600 				if (style == PATTERNED)
601 				{
602 					/* patterned fill */
603 					pat = desc->raster[yrev&15];
604 					if (pat != 0)
605 					{
606 						for(l=j; l<=k; l++)
607 						{
608 							if ((pat & (1 << (15-(l&15)))) != 0)
609 								row[l] = (UCHAR1)((row[l] & mask) | col);
610 						}
611 					}
612 				} else
613 				{
614 					/* solid fill */
615 					for(l=j; l<=k; l++)
616 						row[l] = (UCHAR1)((row[l] & mask) | col);
617 				}
618 				left = edge->nextactive;
619 			}
620 		}
621 		ycur++;
622 
623 		/* update edges in active list */
624 		lastedge = NOPOLYSEG;
625 		for(edge = active; edge != NOPOLYSEG; edge = edge->nextactive)
626 		{
627 			if (ycur >= edge->ty)
628 			{
629 				if (lastedge == NOPOLYSEG) active = edge->nextactive;
630 					else lastedge->nextactive = edge->nextactive;
631 			} else
632 			{
633 				edge->fx += edge->increment;
634 				lastedge = edge;
635 			}
636 		}
637 	}
638 }
639 
640 /******************** GRAPHICS BOXES ********************/
641 
642 /*
643  * Routine to draw a box on the off-screen buffer.
644  */
gra_drawbox(WINDOWPART * win,INTBIG lowx,INTBIG highx,INTBIG lowy,INTBIG highy,GRAPHICS * desc)645 void gra_drawbox(WINDOWPART *win, INTBIG lowx, INTBIG highx, INTBIG lowy, INTBIG highy,
646 	GRAPHICS *desc)
647 {
648 	REGISTER WINDOWFRAME *wf;
649 	REGISTER INTBIG style, x, y, left, right, bottom, top, pat;
650 	REGISTER UCHAR1 *thisrow, mask, col;
651 
652 	/* get graphics parameters */
653 	wf = win->frame;
654 	col = (UCHAR1)desc->col;   mask = (UCHAR1)(~desc->bits);
655 	style = desc->colstyle & NATURE;
656 	left = lowx;                  right = highx + 1;
657 	bottom = wf->revy-lowy + 1;   top = wf->revy-highy;
658 	CHECKCOORD(wf, left, top, x_("box"));
659 	CHECKCOORD(wf, right-1, bottom-1, x_("box"));
660 
661 	/* handle color drawing */
662 	if (style == PATTERNED)
663 	{
664 		/* special case the patterned fill */
665 		for(y=top; y<bottom; y++)
666 		{
667 			pat = desc->raster[y&15];
668 			if (pat == 0) continue;
669 			thisrow = &wf->rowstart[y][left];
670 			for(x=left; x<right; x++)
671 			{
672 				if ((pat & (1 << (15-(x&15)))) != 0)
673 					*thisrow = (*thisrow & mask) | col;
674 				thisrow++;
675 			}
676 		}
677 	} else
678 	{
679 		for(y=top; y<bottom; y++)
680 		{
681 			thisrow = &wf->rowstart[y][left];
682 			for(x=left; x<right; x++)
683 			{
684 				*thisrow = (*thisrow & mask) | col;
685 				thisrow++;
686 			}
687 		}
688 	}
689 	gra_setrect(wf, left, right, top, bottom);
690 }
691 
692 /*
693  * Routine to invert the bits in the box from (lowx, lowy) to (highx, highy) on the off-screen buffer
694  */
gra_invertbox(WINDOWPART * win,INTBIG lowx,INTBIG highx,INTBIG lowy,INTBIG highy)695 void gra_invertbox(WINDOWPART *win, INTBIG lowx, INTBIG highx, INTBIG lowy, INTBIG highy)
696 {
697 	REGISTER WINDOWFRAME *wf;
698 	REGISTER INTBIG top, bottom, left, right, x, y;
699 	REGISTER UCHAR1 *thisrow;
700 
701 	wf = win->frame;
702 	left = lowx;
703 	right = highx + 1;
704 	bottom = wf->revy - lowy + 1;
705 	top = wf->revy - highy;
706 	if (top < 0) top = 0;
707 	CHECKCOORD(wf, left, top, x_("invbox"));
708 	CHECKCOORD(wf, right-1, bottom-1, x_("invbox"));
709 
710 	for(y=top; y<bottom; y++)
711 	{
712 		thisrow = wf->rowstart[y];
713 		for(x=left; x<right; x++) thisrow[x] = ~thisrow[x];
714 	}
715 
716 	gra_setrect(wf, left, right, top, bottom);
717 }
718 
719 /*
720  * Routine to move bits on the off-screen buffer starting with the area at
721  * (sx,sy) and ending at (dx,dy).  The size of the area to be
722  * moved is "wid" by "hei".
723  */
gra_movebox(WINDOWPART * win,INTBIG sx,INTBIG sy,INTBIG wid,INTBIG hei,INTBIG dx,INTBIG dy)724 void gra_movebox(WINDOWPART *win, INTBIG sx, INTBIG sy, INTBIG wid, INTBIG hei,
725 	INTBIG dx, INTBIG dy)
726 {
727 	REGISTER WINDOWFRAME *wf;
728 	INTBIG fleft, fright, ftop, fbottom, tleft, tright, ttop, tbottom;
729 #ifdef USE_MEMMOVE
730 	INTBIG i;
731 #else
732 	INTBIG xsize, ysize, x, y, dir, fromstart, frominc, tostart, toinc;
733 	REGISTER UCHAR1 *frombase, *tobase;
734 #endif
735 
736 	/* setup source rectangle */
737 	wf = win->frame;
738 	fleft = sx;
739 	fright = fleft + wid;
740 	ftop = wf->revy + 1 - sy - hei;
741 	fbottom = ftop + hei;
742 	CHECKCOORD(wf, fleft, ftop, x_("movebox"));
743 	CHECKCOORD(wf, fright-1, fbottom-1, x_("movebox"));
744 
745 	/* setup destination rectangle */
746 	tleft = dx;
747 	tright = tleft + wid;
748 	ttop = wf->revy + 1 - dy - hei;
749 	tbottom = ttop + hei;
750 	CHECKCOORD(wf, tleft, ttop, x_("movebox"));
751 	CHECKCOORD(wf, tright-1, tbottom-1, x_("movebox"));
752 
753 #ifdef USE_MEMMOVE
754 	/* move the rows */
755 	if (ttop < ftop)
756 	{
757 		for (i = 0; i < hei; i++)
758 			memcpy(wf->rowstart[ttop + i] + tleft, wf->rowstart[ftop + i] + fleft, wid);
759 	} else if (ttop > ftop)
760 	{
761 		for (i = hei - 1; i >= 0; i--)
762 			memcpy(wf->rowstart[ttop + i] + tleft, wf->rowstart[ftop + i] + fleft, wid);
763 	} else
764 	{
765 		for (i = 0; i < hei; i++)
766 			memmove(wf->rowstart[ttop + i] + tleft, wf->rowstart[ftop + i] + fleft, wid);
767 	}
768 #else
769 	/* determine size of bits to move */
770 	xsize = wid;   ysize = hei;
771 
772 	/* determine direction of bit copy */
773 	if (fleft < tleft) dir = 1; else dir = 0;
774 	if (ftop < ttop)
775 	{
776 		fromstart = fbottom-1;   frominc = -1;
777 		tostart = tbottom-1;       toinc = -1;
778 	} else
779 	{
780 		fromstart = ftop;   frominc = 1;
781 		tostart = ttop;       toinc = 1;
782 	}
783 
784 	/* move the bits */
785 	if (dir == 0)
786 	{
787 		/* normal forward copy in X */
788 		for(y = 0; y < ysize; y++)
789 		{
790 			frombase = wf->rowstart[fromstart] + fleft;
791 			fromstart += frominc;
792 			tobase = wf->rowstart[tostart] + tleft;
793 			tostart += toinc;
794 			for(x = 0; x < xsize; x++) *tobase++ = *frombase++;
795 		}
796 	} else
797 	{
798 		/* reverse copy in X */
799 		for(y = 0; y < ysize; y++)
800 		{
801 			frombase = wf->rowstart[fromstart] + fright;
802 			fromstart += frominc;
803 			tobase = wf->rowstart[tostart] + tright;
804 			tostart += toinc;
805 			for(x = 0; x < xsize; x++) *tobase-- = *frombase--;
806 		}
807 	}
808 #endif
809 	gra_setrect(wf, tleft, tright, ttop, tbottom);
810 }
811 
812 /*
813  * routine to save the contents of the box from "lx" to "hx" in X and from
814  * "ly" to "hy" in Y.  A code is returned that identifies this box for
815  * overwriting and restoring.  The routine returns negative if there is a error.
816  */
gra_savebox(WINDOWPART * win,INTBIG lx,INTBIG hx,INTBIG ly,INTBIG hy)817 INTBIG gra_savebox(WINDOWPART *win, INTBIG lx, INTBIG hx, INTBIG ly, INTBIG hy)
818 {
819 	REGISTER WINDOWFRAME *wf;
820 	SAVEDBOX *box;
821 #ifdef USE_MEMMOVE
822 	REGISTER INTBIG i, y;
823 #else
824 	REGISTER INTBIG i, x, y;
825 #endif
826 	REGISTER INTBIG xsize, ysize, toindex;
827 
828 	wf = win->frame;
829 	i = ly;   ly = wf->revy-hy;   hy = wf->revy-i;
830 	xsize = hx-lx+1;
831 	ysize = hy-ly+1;
832 
833 	box = (SAVEDBOX *)emalloc((sizeof (SAVEDBOX)), us_tool->cluster);
834 	if (box == 0) return(-1);
835 	box->wf = win->frame;
836 	box->pix = (UCHAR1 *)emalloc(xsize * ysize, us_tool->cluster);
837 	if (box->pix == 0) return(-1);
838 	box->lx = lx;           box->hx = hx;
839 	box->ly = ly;           box->hy = hy;
840 
841 	/* move the bits */
842 	toindex = 0;
843 	for(y = ly; y <= hy; y++)
844 	{
845 #ifdef USE_MEMMOVE
846 		memcpy(box->pix + toindex, wf->rowstart[y] + lx, xsize);
847 		toindex += xsize;
848 #else
849 		for(x = lx; x <= hx; x++)
850 			box->pix[toindex++] = wf->rowstart[y][x];
851 #endif
852 	}
853 
854 	return((INTBIG)box);
855 }
856 
857 /*
858  * routine to shift the saved box "code" so that it is restored in a different
859  * lcoation, offset by (dx,dy)
860  */
gra_movesavedbox(INTBIG code,INTBIG dx,INTBIG dy)861 void gra_movesavedbox(INTBIG code, INTBIG dx, INTBIG dy)
862 {
863 	REGISTER SAVEDBOX *box;
864 
865 	if (code == -1) return;
866 	box = (SAVEDBOX *)code;
867 	box->lx += dx;       box->hx += dx;
868 	box->ly -= dy;       box->hy -= dy;
869 }
870 
871 /*
872  * routine to restore saved box "code" to the screen.  "destroy" is:
873  *  0   restore box, do not free memory
874  *  1   restore box, free memory
875  * -1   free memory
876  * Returns true if there is an error.
877  */
gra_restorebox(INTBIG code,INTBIG destroy)878 BOOLEAN gra_restorebox(INTBIG code, INTBIG destroy)
879 {
880 	REGISTER WINDOWFRAME *wf;
881 	REGISTER SAVEDBOX *box;
882 	REGISTER INTBIG fromindex;
883 #ifdef USE_MEMMOVE
884 	REGISTER INTBIG xsize, y;
885 #else
886 	REGISTER INTBIG x, y;
887 #endif
888 
889 	/* get the box */
890 	if (code == -1) return(TRUE);
891 	box = (SAVEDBOX *)code;
892 	wf = box->wf;
893 
894 	/* move the bits */
895 	if (destroy >= 0)
896 	{
897 		fromindex = 0;
898 #ifdef USE_MEMMOVE
899 		xsize = box->hx - box->lx + 1;
900 		for(y = box->ly; y <= box->hy; y++) {
901 			memcpy(wf->rowstart[y] + box->lx, box->pix + fromindex, xsize);
902 			fromindex += xsize;
903 		}
904 #else
905 		for(y = box->ly; y <= box->hy; y++)
906 			for(x = box->lx; x <= box->hx; x++)
907 				wf->rowstart[y][x] = box->pix[fromindex++];
908 #endif
909 		gra_setrect(wf, box->lx, box->hx+1, box->ly, box->hy+1);
910 	}
911 
912 	/* destroy this box's memory if requested */
913 	if (destroy != 0)
914 	{
915 		efree((CHAR *)box->pix);
916 		efree((CHAR *)box);
917 	}
918 	return(FALSE);
919 }
920 
921 /******************** GRAPHICS TEXT ********************/
922 
923 /*
924  * Routine to draw a text on the off-screen buffer
925  */
gra_drawtext(WINDOWPART * win,INTBIG atx,INTBIG aty,INTBIG rotation,CHAR * s,GRAPHICS * desc)926 void gra_drawtext(WINDOWPART *win, INTBIG atx, INTBIG aty, INTBIG rotation, CHAR *s, GRAPHICS *desc)
927 {
928 	REGISTER INTBIG len, col, top, bottom, left, right, mask, pos,
929 		lx, hx, ly, hy, sx, ex, i, j, dpos, desti;
930 	REGISTER UCHAR1 *dest, *ptr;
931 	UCHAR1 **rowstart;
932 	INTBIG wid, hei;
933 	REGISTER WINDOWFRAME *wf;
934 
935 	/* get parameters */
936 	/* quit if string is null */
937 	len = estrlen(s);
938 	if (len == 0) return;
939 
940 	/* get parameters */
941 	wf = win->frame;
942 	col = desc->col;   mask = ~desc->bits;
943 	aty = wf->revy - aty;
944 	lx = win->uselx;   hx = win->usehx;
945 	ly = wf->revy - win->usehy;
946 	hy = wf->revy - win->usely;
947 
948 	/* clip to window frame area */
949 	if (lx < 0) lx = 0;
950 	if (hx >= wf->swid) hx = wf->swid - 1;
951 	if (ly < 0) ly = 0;
952 #if !defined(USEQT) && defined(ONUNIX)
953 	if (hy >= wf->trueheight) hy = wf->trueheight - 1;
954 #else
955 	if (hy >= wf->shei) hy = wf->shei - 1;
956 #endif
957 
958 	/* get text description */
959 	if (gettextbits(win, s, &wid, &hei, &rowstart)) return;
960 
961 	switch (rotation)
962 	{
963 		case 0:			/* no rotation */
964 			/* copy text buffer to the main offscreen buffer */
965 			if (atx < lx) sx = lx-atx; else sx = 0;
966 			if (atx+wid >= hx) ex = hx - atx; else ex = wid;
967 			pos = aty - hei;
968 			for(i=0; i<hei; i++)
969 			{
970 				desti = pos + i;
971 				if (desti < ly || desti > hy) continue;
972 				ptr = rowstart[i];
973 				dest = wf->rowstart[desti];
974 				for(j=sx; j<ex; j++)
975 				{
976 					if (ptr[j] == 0) continue;
977 					dpos = atx + j;
978 					dest[dpos] = (UCHAR1)((dest[dpos] & mask) | col);
979 				}
980 			}
981 			left = atx;     right = atx + wid;
982 			bottom = aty;   top = aty - hei;
983 			break;
984 		case 1:			/* 90 degrees counterclockwise */
985 			if (atx-hei < lx) sx = lx+hei-atx; else sx = 0;
986 			if (atx >= hx) ex = hx - atx; else ex = hei;
987 			pos = aty - wid;
988 			for(i=0; i<wid; i++)
989 			{
990 				desti = pos + i;
991 				if (desti < ly || desti > hy) continue;
992 				dest = wf->rowstart[desti];
993 				for(j=sx; j<ex; j++)
994 				{
995 					ptr = rowstart[hei-1-j];
996 					if (ptr[wid-1-i] == 0) continue;
997 					dpos = atx - j;
998 					dest[dpos] = (UCHAR1)((dest[dpos] & mask) | col);
999 				}
1000 			}
1001 			left = atx - hei;   right = atx;
1002 			bottom = aty;       top = aty - wid;
1003 			break;
1004 		case 2:			/* 180 degrees */
1005 			if (atx-wid < lx) sx = lx+wid-atx; else sx = 0;
1006 			if (atx >= hx) ex = hx - atx; else ex = wid;
1007 			pos = aty;
1008 			for(i=0; i<hei; i++)
1009 			{
1010 				desti = pos + hei - i;
1011 				if (desti < ly || desti > hy) continue;
1012 				ptr = rowstart[i];
1013 				dest = wf->rowstart[desti];
1014 				for(j=sx; j<ex; j++)
1015 				{
1016 					if (ptr[j] == 0) continue;
1017 					dpos = atx - j;
1018 					dest[dpos] = (UCHAR1)((dest[dpos] & mask) | col);
1019 				}
1020 			}
1021 			left = atx - wid;     right = atx;
1022 			bottom = aty + hei;   top = aty;
1023 			break;
1024 		case 3:			/* 90 degrees clockwise */
1025 			if (atx < lx) sx = lx-atx; else sx = 0;
1026 			if (atx+hei >= hx) ex = hx - atx; else ex = hei;
1027 			pos = aty;
1028 			for(i=0; i<wid; i++)
1029 			{
1030 				desti = pos + i;
1031 				if (desti < ly || desti > hy) continue;
1032 				dest = wf->rowstart[desti];
1033 				for(j=sx; j<ex; j++)
1034 				{
1035 					ptr = rowstart[hei-1-j];
1036 					if (ptr[i] == 0) continue;
1037 					dpos = atx + j;
1038 					dest[dpos] = (UCHAR1)((dest[dpos] & mask) | col);
1039 				}
1040 			}
1041 			left = atx;           right = atx + hei;
1042 			bottom = aty - wid;   top = aty;
1043 			break;
1044 		default:
1045 			return;
1046 	}
1047 
1048 	/* set redraw area */
1049 	gra_setrect(wf, left, right, top, bottom);
1050 }
1051 
1052 /******************** CIRCLE DRAWING ********************/
1053 
1054 /*
1055  * Routine to draw a circle on the off-screen buffer
1056  */
gra_drawcircle(WINDOWPART * win,INTBIG atx,INTBIG aty,INTBIG radius,GRAPHICS * desc)1057 void gra_drawcircle(WINDOWPART *win, INTBIG atx, INTBIG aty, INTBIG radius, GRAPHICS *desc)
1058 {
1059 	REGISTER WINDOWFRAME *wf;
1060 	REGISTER INTBIG col, mask, top, bottom, left, right;
1061 	REGISTER INTBIG x, y, d, maxx, maxy, thisx, thisy;
1062 	REGISTER UCHAR1 *thisrow;
1063 
1064 	/* get parameters */
1065 	wf = win->frame;
1066 	col = desc->col;   mask = ~desc->bits;
1067 	aty = wf->revy - aty;
1068 
1069 	/* set redraw area */
1070 	left = atx - radius;
1071 	right = atx + radius + 1;
1072 	top = aty - radius;
1073 	bottom = aty + radius + 1;
1074 	CHECKCOORD(wf, left, top, x_("circle"));
1075 	CHECKCOORD(wf, right, bottom, x_("circle"));
1076 	gra_setrect(wf, left, right, top, bottom);
1077 
1078 	maxx = wf->swid;
1079 	maxy = wf->shei;
1080 	x = 0;   y = radius;
1081 	d = 3 - 2 * radius;
1082 	if (left >= 0 && right < maxx && top >= 0 && bottom < maxy)
1083 	{
1084 		/* no clip version is faster */
1085 		while (x <= y)
1086 		{
1087 			thisrow = wf->rowstart[aty + y];
1088 			thisrow[atx + x] = (UCHAR1)((thisrow[atx + x] & mask) | col);
1089 			thisrow[atx - x] = (UCHAR1)((thisrow[atx - x] & mask) | col);
1090 
1091 			thisrow = wf->rowstart[aty - y];
1092 			thisrow[atx + x] = (UCHAR1)((thisrow[atx + x] & mask) | col);
1093 			thisrow[atx - x] = (UCHAR1)((thisrow[atx - x] & mask) | col);
1094 
1095 			thisrow = wf->rowstart[aty + x];
1096 			thisrow[atx + y] = (UCHAR1)((thisrow[atx + y] & mask) | col);
1097 			thisrow[atx - y] = (UCHAR1)((thisrow[atx - y] & mask) | col);
1098 
1099 			thisrow = wf->rowstart[aty - x];
1100 			thisrow[atx + y] = (UCHAR1)((thisrow[atx + y] & mask) | col);
1101 			thisrow[atx - y] = (UCHAR1)((thisrow[atx - y] & mask) | col);
1102 
1103 			if (d < 0) d += 4*x + 6; else
1104 			{
1105 				d += 4 * (x-y) + 10;
1106 				y--;
1107 			}
1108 			x++;
1109 		}
1110 	} else
1111 	{
1112 		/* clip version */
1113 		while (x <= y)
1114 		{
1115 			thisy = aty + y;
1116 			if (thisy >= 0 && thisy < maxy)
1117 			{
1118 				thisrow = wf->rowstart[thisy];
1119 				thisx = atx + x;
1120 				if (thisx >= 0 && thisx < maxx)
1121 					thisrow[thisx] = (UCHAR1)((thisrow[thisx] & mask) | col);
1122 				thisx = atx - x;
1123 				if (thisx >= 0 && thisx < maxx)
1124 					thisrow[thisx] = (UCHAR1)((thisrow[thisx] & mask) | col);
1125 			}
1126 
1127 			thisy = aty - y;
1128 			if (thisy >= 0 && thisy < maxy)
1129 			{
1130 				thisrow = wf->rowstart[thisy];
1131 				thisx = atx + x;
1132 				if (thisx >= 0 && thisx < maxx)
1133 					thisrow[thisx] = (UCHAR1)((thisrow[thisx] & mask) | col);
1134 				thisx = atx - x;
1135 				if (thisx >= 0 && thisx < maxx)
1136 					thisrow[thisx] = (UCHAR1)((thisrow[thisx] & mask) | col);
1137 			}
1138 
1139 			thisy = aty + x;
1140 			if (thisy >= 0 && thisy < maxy)
1141 			{
1142 				thisrow = wf->rowstart[thisy];
1143 				thisx = atx + y;
1144 				if (thisx >= 0 && thisx < maxx)
1145 					thisrow[thisx] = (UCHAR1)((thisrow[thisx] & mask) | col);
1146 				thisx = atx - y;
1147 				if (thisx >= 0 && thisx < maxx)
1148 					thisrow[thisx] = (UCHAR1)((thisrow[thisx] & mask) | col);
1149 			}
1150 
1151 			thisy = aty - x;
1152 			if (thisy >= 0 && thisy < maxy)
1153 			{
1154 				thisrow = wf->rowstart[thisy];
1155 				thisx = atx + y;
1156 				if (thisx >= 0 && thisx < maxx)
1157 					thisrow[thisx] = (UCHAR1)((thisrow[thisx] & mask) | col);
1158 				thisx = atx - y;
1159 				if (thisx >= 0 && thisx < maxx)
1160 					thisrow[thisx] = (UCHAR1)((thisrow[thisx] & mask) | col);
1161 			}
1162 
1163 			if (d < 0) d += 4*x + 6; else
1164 			{
1165 				d += 4 * (x-y) + 10;
1166 				y--;
1167 			}
1168 			x++;
1169 		}
1170 	}
1171 }
1172 
1173 /*
1174  * Routine to draw a thick circle on the off-screen buffer
1175  */
gra_drawthickcircle(WINDOWPART * win,INTBIG atx,INTBIG aty,INTBIG radius,GRAPHICS * desc)1176 void gra_drawthickcircle(WINDOWPART *win, INTBIG atx, INTBIG aty, INTBIG radius,
1177 	GRAPHICS *desc)
1178 {
1179 	REGISTER INTBIG col, mask, top, bottom, left, right;
1180 	REGISTER INTBIG x, y, d, maxx, maxy, thisx, thisy;
1181 	REGISTER WINDOWFRAME *wf;
1182 	REGISTER UCHAR1 *thisrow1, *thisrow2, *thisrow3, *thisrow4,
1183 		*thisrow1m, *thisrow2m, *thisrow3m, *thisrow4m,
1184 		*thisrow1p, *thisrow2p, *thisrow3p, *thisrow4p;
1185 
1186 	/* get parameters */
1187 	wf = win->frame;
1188 	col = desc->col;   mask = ~desc->bits;
1189 	aty = wf->revy - aty;
1190 
1191 	/* set redraw area */
1192 	left = atx - radius - 1;
1193 	right = atx + radius + 2;
1194 	top = aty - radius - 1;
1195 	bottom = aty + radius + 2;
1196 	gra_setrect(wf, left, right, top, bottom);
1197 
1198 	maxx = wf->swid;
1199 	maxy = wf->shei;
1200 	x = 0;   y = radius;
1201 	d = 3 - 2 * radius;
1202 	if (left >= 0 && right < maxx && top >= 0 && bottom < maxy)
1203 	{
1204 		/* no clip version is faster */
1205 		while (x <= y)
1206 		{
1207 			/* draw basic circle */
1208 			thisrow1 = wf->rowstart[aty + y];
1209 			thisrow2 = wf->rowstart[aty - y];
1210 			thisrow3 = wf->rowstart[aty + x];
1211 			thisrow4 = wf->rowstart[aty - x];
1212 			thisrow1[atx + x] = (UCHAR1)((thisrow1[atx + x] & mask) | col);
1213 			thisrow1[atx - x] = (UCHAR1)((thisrow1[atx - x] & mask) | col);
1214 
1215 			thisrow2[atx + x] = (UCHAR1)((thisrow2[atx + x] & mask) | col);
1216 			thisrow2[atx - x] = (UCHAR1)((thisrow2[atx - x] & mask) | col);
1217 
1218 			thisrow3[atx + y] = (UCHAR1)((thisrow3[atx + y] & mask) | col);
1219 			thisrow3[atx - y] = (UCHAR1)((thisrow3[atx - y] & mask) | col);
1220 
1221 			thisrow4[atx + y] = (UCHAR1)((thisrow4[atx + y] & mask) | col);
1222 			thisrow4[atx - y] = (UCHAR1)((thisrow4[atx - y] & mask) | col);
1223 
1224 			/* draw 1 pixel around it to make it thick */
1225 			thisrow1m = wf->rowstart[aty + y - 1];
1226 			thisrow2m = wf->rowstart[aty - y - 1];
1227 			thisrow3m = wf->rowstart[aty + x - 1];
1228 			thisrow4m = wf->rowstart[aty - x - 1];
1229 			thisrow1p = wf->rowstart[aty + y + 1];
1230 			thisrow2p = wf->rowstart[aty - y + 1];
1231 			thisrow3p = wf->rowstart[aty + x + 1];
1232 			thisrow4p = wf->rowstart[aty - x + 1];
1233 
1234 			thisrow1[atx + x + 1] = (UCHAR1)((thisrow1[atx + x + 1] & mask) | col);
1235 			thisrow1[atx + x - 1] = (UCHAR1)((thisrow1[atx + x - 1] & mask) | col);
1236 			thisrow1[atx - x + 1] = (UCHAR1)((thisrow1[atx - x + 1] & mask) | col);
1237 			thisrow1[atx - x - 1] = (UCHAR1)((thisrow1[atx - x - 1] & mask) | col);
1238 			thisrow1m[atx + x] = (UCHAR1)((thisrow1m[atx + x] & mask) | col);
1239 			thisrow1m[atx - x] = (UCHAR1)((thisrow1m[atx - x] & mask) | col);
1240 			thisrow1p[atx + x] = (UCHAR1)((thisrow1p[atx + x] & mask) | col);
1241 			thisrow1p[atx - x] = (UCHAR1)((thisrow1p[atx - x] & mask) | col);
1242 
1243 			thisrow2[atx + x + 1] = (UCHAR1)((thisrow2[atx + x + 1] & mask) | col);
1244 			thisrow2[atx + x - 1] = (UCHAR1)((thisrow2[atx + x - 1] & mask) | col);
1245 			thisrow2[atx - x + 1] = (UCHAR1)((thisrow2[atx - x + 1] & mask) | col);
1246 			thisrow2[atx - x - 1] = (UCHAR1)((thisrow2[atx - x - 1] & mask) | col);
1247 			thisrow2m[atx + x] = (UCHAR1)((thisrow2m[atx + x] & mask) | col);
1248 			thisrow2m[atx - x] = (UCHAR1)((thisrow2m[atx - x] & mask) | col);
1249 			thisrow2p[atx + x] = (UCHAR1)((thisrow2p[atx + x] & mask) | col);
1250 			thisrow2p[atx - x] = (UCHAR1)((thisrow2p[atx - x] & mask) | col);
1251 
1252 			thisrow3[atx + y + 1] = (UCHAR1)((thisrow3[atx + y + 1] & mask) | col);
1253 			thisrow3[atx + y - 1] = (UCHAR1)((thisrow3[atx + y - 1] & mask) | col);
1254 			thisrow3[atx - y + 1] = (UCHAR1)((thisrow3[atx - y + 1] & mask) | col);
1255 			thisrow3[atx - y - 1] = (UCHAR1)((thisrow3[atx - y - 1] & mask) | col);
1256 			thisrow3m[atx + y] = (UCHAR1)((thisrow3m[atx + y] & mask) | col);
1257 			thisrow3m[atx - y] = (UCHAR1)((thisrow3m[atx - y] & mask) | col);
1258 			thisrow3p[atx + y] = (UCHAR1)((thisrow3p[atx + y] & mask) | col);
1259 			thisrow3p[atx - y] = (UCHAR1)((thisrow3p[atx - y] & mask) | col);
1260 
1261 			thisrow4[atx + y + 1] = (UCHAR1)((thisrow4[atx + y + 1] & mask) | col);
1262 			thisrow4[atx + y - 1] = (UCHAR1)((thisrow4[atx + y - 1] & mask) | col);
1263 			thisrow4[atx - y + 1] = (UCHAR1)((thisrow4[atx - y + 1] & mask) | col);
1264 			thisrow4[atx - y - 1] = (UCHAR1)((thisrow4[atx - y - 1] & mask) | col);
1265 			thisrow4m[atx + y] = (UCHAR1)((thisrow4m[atx + y] & mask) | col);
1266 			thisrow4m[atx - y] = (UCHAR1)((thisrow4m[atx - y] & mask) | col);
1267 			thisrow4p[atx + y] = (UCHAR1)((thisrow4p[atx + y] & mask) | col);
1268 			thisrow4p[atx - y] = (UCHAR1)((thisrow4p[atx - y] & mask) | col);
1269 
1270 			if (d < 0) d += 4*x + 6; else
1271 			{
1272 				d += 4 * (x-y) + 10;
1273 				y--;
1274 			}
1275 			x++;
1276 		}
1277 	} else
1278 	{
1279 		/* clip version */
1280 		while (x <= y)
1281 		{
1282 			thisy = aty + y;
1283 			if (thisy >= 0 && thisy < maxy)
1284 			{
1285 				thisx = atx + x;
1286 				if (thisx >= 0 && thisx < maxx)
1287 					gra_drawthickpoint(wf, thisx, thisy, mask, col);
1288 				thisx = atx - x;
1289 				if (thisx >= 0 && thisx < maxx)
1290 					gra_drawthickpoint(wf, thisx, thisy, mask, col);
1291 			}
1292 
1293 			thisy = aty - y;
1294 			if (thisy >= 0 && thisy < maxy)
1295 			{
1296 				thisx = atx + x;
1297 				if (thisx >= 0 && thisx < maxx)
1298 					gra_drawthickpoint(wf, thisx, thisy, mask, col);
1299 				thisx = atx - x;
1300 				if (thisx >= 0 && thisx < maxx)
1301 					gra_drawthickpoint(wf, thisx, thisy, mask, col);
1302 			}
1303 
1304 			thisy = aty + x;
1305 			if (thisy >= 0 && thisy < maxy)
1306 			{
1307 				thisx = atx + y;
1308 				if (thisx >= 0 && thisx < maxx)
1309 					gra_drawthickpoint(wf, thisx, thisy, mask, col);
1310 				thisx = atx - y;
1311 				if (thisx >= 0 && thisx < maxx)
1312 					gra_drawthickpoint(wf, thisx, thisy, mask, col);
1313 			}
1314 
1315 			thisy = aty - x;
1316 			if (thisy >= 0 && thisy < maxy)
1317 			{
1318 				thisx = atx + y;
1319 				if (thisx >= 0 && thisx < maxx)
1320 					gra_drawthickpoint(wf, thisx, thisy, mask, col);
1321 				thisx = atx - y;
1322 				if (thisx >= 0 && thisx < maxx)
1323 					gra_drawthickpoint(wf, thisx, thisy, mask, col);
1324 			}
1325 
1326 			if (d < 0) d += 4*x + 6; else
1327 			{
1328 				d += 4 * (x-y) + 10;
1329 				y--;
1330 			}
1331 			x++;
1332 		}
1333 	}
1334 }
1335 
1336 /******************** DISC DRAWING ********************/
1337 
1338 /*
1339  * routine to draw a scan line of the filled-in circle of radius "radius"
1340  */
gra_drawdiscrow(WINDOWFRAME * wf,INTBIG thisy,INTBIG startx,INTBIG endx,GRAPHICS * desc)1341 static void gra_drawdiscrow(WINDOWFRAME *wf, INTBIG thisy, INTBIG startx, INTBIG endx, GRAPHICS *desc)
1342 {
1343 	REGISTER UCHAR1 *thisrow;
1344 	REGISTER INTBIG x;
1345 	REGISTER INTBIG pat;
1346 
1347 	if (thisy < gra_curveminy || thisy >= gra_curvemaxy) return;
1348 	thisrow = wf->rowstart[thisy];
1349 	if (startx < gra_curveminx) startx = gra_curveminx;
1350 	if (endx >= gra_curvemaxx) endx = gra_curvemaxx - 1;
1351 	if (gra_curvestyle == PATTERNED)
1352 	{
1353 		pat = desc->raster[thisy&15];
1354 		if (pat != 0)
1355 		{
1356 			for(x=startx; x<=endx; x++)
1357 				if ((pat & (1 << (15-(x&15)))) != 0)
1358 					thisrow[x] = (UCHAR1)((thisrow[x] & gra_curvemask) | gra_curvecol);
1359 		}
1360 	} else
1361 	{
1362 		for(x=startx; x<=endx; x++)
1363 			thisrow[x] = (UCHAR1)((thisrow[x] & gra_curvemask) | gra_curvecol);
1364 	}
1365 }
1366 
1367 /*
1368  * routine to draw a filled-in circle of radius "radius" on the off-screen buffer
1369  */
gra_drawdisc(WINDOWPART * win,INTBIG atx,INTBIG aty,INTBIG radius,GRAPHICS * desc)1370 void gra_drawdisc(WINDOWPART *win, INTBIG atx, INTBIG aty, INTBIG radius, GRAPHICS *desc)
1371 {
1372 	REGISTER WINDOWFRAME *wf;
1373 	REGISTER INTBIG x, y, d;
1374 	REGISTER INTBIG top, bottom, left, right;
1375 	REGISTER UCHAR1 *thisrow;
1376 
1377 	/* get parameters */
1378 	wf = win->frame;
1379 	gra_curvestyle = desc->colstyle & NATURE;
1380 	gra_curvecol = desc->col;   gra_curvemask = ~desc->bits;
1381 
1382 	/* set redraw area */
1383 	aty = wf->revy - aty;
1384 	left = atx - radius;
1385 	right = atx + radius + 1;
1386 	top = aty - radius;
1387 	bottom = aty + radius + 1;
1388 	gra_setrect(wf, left, right, top, bottom);
1389 
1390 	/* draw a more general disc */
1391 	gra_curveminx = maxi(win->uselx, 0);
1392 	gra_curvemaxx = mini(win->usehx, wf->swid);
1393 	gra_curveminy = maxi(wf->revy - win->usehy, 0);
1394 	gra_curvemaxy = mini(wf->revy - win->usely, wf->shei);
1395 
1396 	if (radius == 1)
1397 	{
1398 		/* just fill the area for discs this small */
1399 		if (left < gra_curveminx) left = gra_curveminx;
1400 		if (right >= gra_curvemaxx) right = gra_curvemaxx - 1;
1401 		for(y=top; y<bottom; y++)
1402 		{
1403 			if (y < gra_curveminy || y >= gra_curvemaxy) continue;
1404 			thisrow = wf->rowstart[y];
1405 			for(x=left; x<right; x++)
1406 				thisrow[x] = (UCHAR1)((thisrow[x] & gra_curvemask) | gra_curvecol);
1407 		}
1408 		return;
1409 	}
1410 
1411 	x = 0;   y = radius;
1412 	d = 3 - 2 * radius;
1413 	while (x <= y)
1414 	{
1415 		gra_drawdiscrow(wf, aty+y, atx-x, atx+x, desc);
1416 		gra_drawdiscrow(wf, aty-y, atx-x, atx+x, desc);
1417 		gra_drawdiscrow(wf, aty+x, atx-y, atx+y, desc);
1418 		gra_drawdiscrow(wf, aty-x, atx-y, atx+y, desc);
1419 
1420 		if (d < 0) d += 4*x + 6; else
1421 		{
1422 			d += 4 * (x-y) + 10;
1423 			y--;
1424 		}
1425 		x++;
1426 	}
1427 }
1428 
1429 /******************** ARC DRAWING ********************/
1430 
gra_arcfindoctant(INTBIG x,INTBIG y)1431 static INTBIG gra_arcfindoctant(INTBIG x, INTBIG y)
1432 {
1433 	if (x > 0)
1434 		if (y >= 0)
1435 			if (y >= x)	 return 7;
1436 			else         return 8;
1437 		else
1438 			if (x >= -y) return 1;
1439 			else         return 2;
1440 	else
1441 		if (y > 0)
1442 			if (y > -x)  return 6;
1443 			else         return 5;
1444 		else
1445 			if (y > x)   return 4;
1446 			else         return 3;
1447 }
1448 
gra_arcxformoctant(INTBIG x,INTBIG y,INTBIG oct,INTBIG * ox,INTBIG * oy)1449 static void gra_arcxformoctant(INTBIG x, INTBIG y, INTBIG oct, INTBIG *ox, INTBIG *oy)
1450 {
1451 	switch (oct)
1452 	{
1453 		case 1 : *ox = -y;   *oy = x;   break;
1454 		case 2 : *ox = x;    *oy = -y;  break;
1455 		case 3 : *ox = -x;   *oy = -y;  break;
1456 		case 4 : *ox = -y;   *oy = -x;  break;
1457 		case 5 : *ox = y;    *oy = -x;  break;
1458 		case 6 : *ox = -x;   *oy = y;   break;
1459 		case 7 : *ox = x;    *oy = y;   break;
1460 		case 8 : *ox = y;    *oy = x;   break;
1461 	}
1462 }
1463 
gra_arcdopixel(WINDOWFRAME * wf,INTBIG x,INTBIG y)1464 static void gra_arcdopixel(WINDOWFRAME *wf, INTBIG x, INTBIG y)
1465 {
1466 	if (x < 0 || x >= gra_curvemaxx || y < 0 || y >= gra_curvemaxy) return;
1467 	if (gra_arcfirst != 0)
1468 	{
1469 		gra_arcfirst = 0;
1470 		gra_arclx = gra_archx = x;
1471 		gra_arcly = gra_archy = y;
1472 	} else
1473 	{
1474 		if (x < gra_arclx) gra_arclx = x;
1475 		if (x > gra_archx) gra_archx = x;
1476 		if (y < gra_arcly) gra_arcly = y;
1477 		if (y > gra_archy) gra_archy = y;
1478 	}
1479 	CHECKCOORD(wf, x, y, x_("arc"));
1480 	if (gra_arcthick)
1481 	{
1482 		gra_drawthickpoint(wf, x, y, gra_curvemask, gra_curvecol);
1483 	} else
1484 	{
1485 		wf->rowstart[y][x] = (UCHAR1)((wf->rowstart[y][x] & gra_curvemask) | gra_curvecol);
1486 	}
1487 }
1488 
gra_arcoutxform(WINDOWFRAME * wf,INTBIG x,INTBIG y)1489 static void gra_arcoutxform(WINDOWFRAME *wf, INTBIG x, INTBIG y)
1490 {
1491 	if (gra_arcocttable[1]) gra_arcdopixel(wf,  y + gra_arccenterx, -x + gra_arccentery);
1492 	if (gra_arcocttable[2]) gra_arcdopixel(wf,  x + gra_arccenterx, -y + gra_arccentery);
1493 	if (gra_arcocttable[3]) gra_arcdopixel(wf, -x + gra_arccenterx, -y + gra_arccentery);
1494 	if (gra_arcocttable[4]) gra_arcdopixel(wf, -y + gra_arccenterx, -x + gra_arccentery);
1495 	if (gra_arcocttable[5]) gra_arcdopixel(wf, -y + gra_arccenterx,  x + gra_arccentery);
1496 	if (gra_arcocttable[6]) gra_arcdopixel(wf, -x + gra_arccenterx,  y + gra_arccentery);
1497 	if (gra_arcocttable[7]) gra_arcdopixel(wf,  x + gra_arccenterx,  y + gra_arccentery);
1498 	if (gra_arcocttable[8]) gra_arcdopixel(wf,  y + gra_arccenterx,  x + gra_arccentery);
1499 }
1500 
gra_arcbrescw(WINDOWFRAME * wf,INTBIG x,INTBIG y,INTBIG x1,INTBIG y1)1501 static void gra_arcbrescw(WINDOWFRAME *wf, INTBIG x, INTBIG y, INTBIG x1, INTBIG y1)
1502 {
1503 	REGISTER INTBIG d;
1504 
1505 	d = 3 - 2 * y + 4 * x;
1506 	while (x < x1 && y > y1)
1507 	{
1508 		gra_arcoutxform(wf, x, y);
1509 		if (d < 0) d += 4*x+6; else
1510 		{
1511 			d += 4*(x-y)+10;
1512 			y--;
1513 		}
1514 		x++;
1515 	}
1516 
1517 	/* get to the end */
1518 	for ( ; x < x1; x++) gra_arcoutxform(wf, x, y);
1519 	for ( ; y > y1; y--) gra_arcoutxform(wf, x, y);
1520    gra_arcoutxform(wf, x1, y1);
1521 }
1522 
gra_arcbresmidcw(WINDOWFRAME * wf,INTBIG x,INTBIG y)1523 static void gra_arcbresmidcw(WINDOWFRAME *wf, INTBIG x, INTBIG y)
1524 {
1525 	REGISTER INTBIG d;
1526 
1527 	d = 3 - 2 * y + 4 * x;
1528 	while (x < y)
1529 	{
1530 		gra_arcoutxform(wf, x, y);
1531 		if (d < 0) d += 4*x+6; else
1532 		{
1533 			d += 4*(x-y)+10;
1534 			y--;
1535 		}
1536 		x++;
1537    }
1538    if (x == y) gra_arcoutxform(wf, x, y);
1539 }
1540 
gra_arcbresmidccw(WINDOWFRAME * wf,INTBIG x,INTBIG y)1541 static void gra_arcbresmidccw(WINDOWFRAME *wf, INTBIG x, INTBIG y)
1542 {
1543 	REGISTER INTBIG d;
1544 
1545 	d = 3 + 2 * y - 4 * x;
1546 	while (x > 0)
1547 	{
1548 		gra_arcoutxform(wf, x, y);
1549 		if (d > 0) d += 6-4*x; else
1550 		{
1551 			d += 4*(y-x)+10;
1552 			y++;
1553 		}
1554 		x--;
1555    }
1556    gra_arcoutxform(wf, 0, gra_arcradius);
1557 }
1558 
gra_arcbresccw(WINDOWFRAME * wf,INTBIG x,INTBIG y,INTBIG x1,INTBIG y1)1559 static void gra_arcbresccw(WINDOWFRAME *wf, INTBIG x, INTBIG y, INTBIG x1, INTBIG y1)
1560 {
1561 	REGISTER INTBIG d;
1562 
1563 	d = 3 + 2 * y + 4 * x;
1564 	while(x > x1 && y < y1)
1565 	{
1566 		/* not always correct */
1567 		gra_arcoutxform(wf, x, y);
1568 		if (d > 0) d += 6 - 4*x; else
1569 		{
1570 			d += 4*(y-x)+10;
1571 			y++;
1572 		}
1573 		x--;
1574 	}
1575 
1576 	/* get to the end */
1577 	for ( ; x > x1; x--) gra_arcoutxform(wf, x, y);
1578 	for ( ; y < y1; y++) gra_arcoutxform(wf, x, y);
1579 	gra_arcoutxform(wf, x1, y1);
1580 }
1581 
1582 /*
1583  * draws an arc centered at (centerx, centery), clockwise,
1584  * passing by (x1,y1) and (x2,y2)
1585  */
gra_drawcirclearc(WINDOWPART * win,INTBIG centerx,INTBIG centery,INTBIG x1,INTBIG y1,INTBIG x2,INTBIG y2,BOOLEAN thick,GRAPHICS * desc)1586 void gra_drawcirclearc(WINDOWPART *win, INTBIG centerx, INTBIG centery, INTBIG x1, INTBIG y1,
1587 	INTBIG x2, INTBIG y2, BOOLEAN thick, GRAPHICS *desc)
1588 {
1589 	REGISTER WINDOWFRAME *wf;
1590 	REGISTER INTBIG alternate, pa_x, pa_y, pb_x, pb_y, i, diff;
1591 	INTBIG x, y;
1592 	REGISTER INTBIG start_oct, end_oct;
1593 
1594 	/* ignore tiny arcs */
1595 	if (x1 == x2 && y1 == y2) return;
1596 
1597 	/* get parameters */
1598 	wf = win->frame;
1599 	gra_curvecol = desc->col;   gra_curvemask = ~desc->bits;
1600 	gra_curvemaxx = wf->swid;
1601 	gra_curvemaxy = wf->shei;
1602 	y1 = wf->revy - y1;
1603 	y2 = wf->revy - y2;
1604 	gra_arccentery = wf->revy - centery;
1605 	gra_arccenterx = centerx;
1606 	pa_x = x2 - gra_arccenterx;
1607 	pa_y = y2 - gra_arccentery;
1608 	pb_x = x1 - gra_arccenterx;
1609 	pb_y = y1 - gra_arccentery;
1610 	gra_arcradius = computedistance(gra_arccenterx, gra_arccentery, x2, y2);
1611 	alternate = computedistance(gra_arccenterx, gra_arccentery, x1, y1);
1612 	start_oct = gra_arcfindoctant(pa_x, pa_y);
1613 	end_oct   = gra_arcfindoctant(pb_x, pb_y);
1614 	gra_arcfirst = 1;
1615 	gra_arcthick = thick;
1616 
1617 	/* move the point */
1618 	if (gra_arcradius != alternate)
1619 	{
1620 		diff = gra_arcradius-alternate;
1621 		switch (end_oct)
1622 		{
1623 			case 6:
1624 			case 7: /*  y >  x */ pb_y += diff;  break;
1625 			case 8: /*  x >  y */
1626 			case 1: /*  x > -y */ pb_x += diff;  break;
1627 			case 2: /* -y >  x */
1628 			case 3: /* -y > -x */ pb_y -= diff;  break;
1629 			case 4: /* -y < -x */
1630 			case 5: /*  y < -x */ pb_x -= diff;  break;
1631 		}
1632 	}
1633 
1634 	for(i=1; i<9; i++) gra_arcocttable[i] = 0;
1635 
1636 	if (start_oct == end_oct)
1637 	{
1638 		INTBIG x1, y1, x2, y2;
1639 
1640 		gra_arcocttable[start_oct] = 1;
1641 		gra_arcxformoctant(pa_x, pa_y, start_oct, &x1, &y1);
1642 		gra_arcxformoctant(pb_x, pb_y, start_oct, &x2 ,&y2);
1643 
1644 		if (ODD(start_oct)) gra_arcbrescw(wf, x1, y1, x2, y2);
1645 		else				gra_arcbresccw(wf, x1 ,y1, x2, y2);
1646 		gra_arcocttable[start_oct] = 0;
1647 	} else
1648 	{
1649 		gra_arcocttable[start_oct] = 1;
1650 		gra_arcxformoctant(pa_x, pa_y, start_oct, &x, &y);
1651 		if (ODD(start_oct)) gra_arcbresmidcw(wf, x, y);
1652 		else				gra_arcbresmidccw(wf, x, y);
1653 		gra_arcocttable[start_oct] = 0;
1654 
1655 		gra_arcocttable[end_oct] = 1;
1656 		gra_arcxformoctant(pb_x, pb_y, end_oct, &x, &y);
1657 		if (ODD(end_oct)) gra_arcbresmidccw(wf, x, y);
1658 		else			  gra_arcbresmidcw(wf, x, y);
1659 		gra_arcocttable[end_oct] = 0;
1660 
1661 		if (MODP(start_oct+1) != end_oct)
1662 		{
1663 			if (MODP(start_oct+1) == MODM(end_oct-1))
1664 				gra_arcocttable[MODP(start_oct+1)] = 1; else
1665 					for(i = MODP(start_oct+1); i != end_oct; i = MODP(i+1))
1666 						gra_arcocttable[i] = 1;
1667 			gra_arcbresmidcw(wf, 0, gra_arcradius);
1668 		}
1669 	}
1670 
1671 	/* set redraw area */
1672 	if (gra_arcfirst == 0)
1673 		gra_setrect(wf, gra_arclx, gra_archx+1, gra_arcly, gra_archy+1);
1674 }
1675 
1676 /******************** GRID CONTROL ********************/
1677 
1678 /*
1679  * fast grid drawing routine
1680  */
gra_drawgrid(WINDOWPART * win,POLYGON * obj)1681 void gra_drawgrid(WINDOWPART *win, POLYGON *obj)
1682 {
1683 	REGISTER WINDOWFRAME *wf;
1684 	REGISTER INTBIG i, j, xnum, xden, ynum, yden, x0,y0, x1,y1, x2,y2, x3,y3,
1685 		x4,y4, x5,y5, x10, y10, y10mod, xspacing, yspacing, y1base, x1base;
1686 	REGISTER INTBIG x, y, fatdots;
1687 	REGISTER VARIABLE *var;
1688 
1689 	wf = win->frame;
1690 	x0 = obj->xv[0];   y0 = obj->yv[0];		/* screen space grid spacing */
1691 	x1 = obj->xv[1];   y1 = obj->yv[1];		/* screen space grid start */
1692 	x2 = obj->xv[2];   y2 = obj->yv[2];		/* display space low */
1693 	x3 = obj->xv[3];   y3 = obj->yv[3];		/* display space high */
1694 	x4 = obj->xv[4];   y4 = obj->yv[4];		/* screen space low */
1695 	x5 = obj->xv[5];   y5 = obj->yv[5];		/* screen space high */
1696 	CHECKCOORD(wf, x2, y2, x_("grid"));
1697 	CHECKCOORD(wf, x3, y3, x_("grid"));
1698 
1699 	var = getvalkey((INTBIG)us_tool, VTOOL, -1, us_gridboldspacingkey);
1700 	if (var == NOVARIABLE) xspacing = yspacing = 10; else
1701 	{
1702 		if ((var->type&VISARRAY) == 0)
1703 			xspacing = yspacing = var->addr; else
1704 		{
1705 			xspacing = ((INTBIG *)var->addr)[0];
1706 			yspacing = ((INTBIG *)var->addr)[1];
1707 		}
1708 	}
1709 
1710 	xnum = x3 - x2;
1711 	xden = x5 - x4;
1712 	ynum = y3 - y2;
1713 	yden = y5 - y4;
1714 	x10 = x0*xspacing;       y10 = y0*yspacing;
1715 	y1base = y1 - (y1 / y0 * y0);
1716 	x1base = x1 - (x1 / x0 * x0);
1717 
1718 	/* adjust grid placement according to scale */
1719 	fatdots = 0;
1720 	if (muldiv(x0, xnum, xden) < 5 || muldiv(y0, ynum, yden) < 5)
1721 	{
1722 		x1 = x1base - (x1base - x1) / x10 * x10;   x0 = x10;
1723 		y1 = y1base - (y1base - y1) / y10 * y10;   y0 = y10;
1724 	} else if (muldiv(x0, xnum, xden) > 75 && muldiv(y0, ynum, yden) > 75)
1725 	{
1726 		fatdots = 1;
1727 	}
1728 
1729 	/* draw the grid to the offscreen buffer */
1730 	for(i = y1; i < y5; i += y0)
1731 	{
1732 		y = muldiv(i-y4, ynum, yden) + y2;
1733 		if (y < y2 || y > y3) continue;
1734 		y = wf->revy - y;
1735 		y10mod = (i-y1base) % y10;
1736 		for(j = x1; j < x5; j += x0)
1737 		{
1738 			x = muldiv(j-x4, xnum, xden) + x2;
1739 			if (x >= x2 && x <= x3) wf->rowstart[y][x] |= GRID;
1740 
1741 			/* special case every 10 grid points in each direction */
1742 			if (fatdots != 0 || ((j-x1base)%x10) == 0 && y10mod == 0)
1743 			{
1744 				if (x > x2) wf->rowstart[y][x-1] |= GRID;
1745 				if (x < x3) wf->rowstart[y][x+1] |= GRID;
1746 				if (y > y2) wf->rowstart[y-1][x] |= GRID;
1747 				if (y < y3) wf->rowstart[y+1][x] |= GRID;
1748 				if (fatdots != 0 && ((j-x1base)%x10) == 0 && y10mod == 0)
1749 				{
1750 					if (x-1 > x2) wf->rowstart[y][x-2] |= GRID;
1751 					if (x+1 < x3) wf->rowstart[y][x+2] |= GRID;
1752 					if (y-1 > y2) wf->rowstart[y-2][x] |= GRID;
1753 					if (y+1 < y3) wf->rowstart[y+2][x] |= GRID;
1754 					if (x > x2 && y > y2) wf->rowstart[y-1][x-1] |= GRID;
1755 					if (x > x2 && y < y3) wf->rowstart[y+1][x-1] |= GRID;
1756 					if (x < x3 && y > y2) wf->rowstart[y-1][x+1] |= GRID;
1757 					if (x < x3 && y < y3) wf->rowstart[y+1][x+1] |= GRID;
1758 				}
1759 			}
1760 		}
1761 	}
1762 
1763 	/* copy it back to the screen */
1764 	gra_setrect(wf, x2, x3, wf->revy-y3, wf->revy-y2);
1765 }
1766 
DiaNullDlogList(CHAR ** c)1767 BOOLEAN DiaNullDlogList(CHAR **c) { Q_UNUSED( c ); return(FALSE); }
1768 
DiaNullDlogItem(void)1769 CHAR *DiaNullDlogItem(void) { return(0); }
1770 
DiaNullDlogDone(void)1771 void DiaNullDlogDone(void) {}
1772 
1773 #ifndef USEQT
1774 
1775 /******* C++ Dialog API: EDialog class on non-QT platforms *************/
1776 
1777 class EDialogPrivate
1778 {
1779 public:
1780 	EDialogPrivate( EDialog *dia );
1781 	~EDialogPrivate();
1782 	static EDialogPrivate *find( void *vdia );
1783 	static void itemHitActionCaller(void *vdia, INTBIG item);
1784 	static void redispCaller(RECTAREA *rect, void *vdia);
1785 
1786 	EDialog *dia;
1787     BOOLEAN modal;
1788 	void *vdia;
1789 	void (*redisp)(RECTAREA *rect, void *dia);
1790 	EDialogPrivate *nextActive;
1791 	static EDialogPrivate *firstActive;
1792 };
1793 
1794 EDialogPrivate *EDialogPrivate::firstActive = 0;
1795 
EDialogPrivate(EDialog * dia)1796 EDialogPrivate::EDialogPrivate(EDialog *dia )
1797 	: dia(dia), vdia(0), redisp(0)
1798 {
1799 	nextActive = firstActive;
1800 	firstActive = this;
1801 }
1802 
~EDialogPrivate()1803 EDialogPrivate::~EDialogPrivate()
1804 {
1805 	EDialogPrivate **p = &firstActive;
1806 
1807 	/* remove from active list */
1808 	for (p = &firstActive; *p && *p != this; p = &(*p)->nextActive);
1809 	if (*p) *p = nextActive;
1810 	if (vdia) DiaDoneDialog(vdia);
1811 }
1812 
find(void * vdia)1813 EDialogPrivate *EDialogPrivate::find(void *vdia)
1814 {
1815 	EDialogPrivate *p;
1816 	for (p = firstActive; p != 0 && p->vdia != vdia; p = p->nextActive);
1817 	return p;
1818 }
1819 
DiaCloseAllModeless()1820 void DiaCloseAllModeless()
1821 {
1822     EDialogPrivate *p;
1823 
1824     for (p = EDialogPrivate::firstActive; p != 0; p = p->nextActive)
1825     {
1826         if (p->modal) continue;
1827         EDialogModeless *dia = (EDialogModeless*)p->dia;
1828         dia->hide();
1829         dia->reset();
1830     }
1831 }
1832 
itemHitActionCaller(void * vdia,INTBIG item)1833 void EDialogPrivate::itemHitActionCaller(void *vdia, INTBIG item)
1834 {
1835 	EDialogPrivate *p = find(vdia);
1836 	if (!p) return;
1837 
1838 	EDialog *dia = p->dia;
1839 	INTBIG itemtypeext = dia->itemDesc()->list[item - 1].type&ITEMTYPEEXT;
1840 	switch(itemtypeext&ITEMTYPE)
1841 	{
1842 		case CHECK:
1843 			if (itemtypeext == AUTOCHECK)
1844 				dia->setControl( item, !dia->getControl( item ) );
1845 			break;
1846 		case RADIO:
1847 			if (itemtypeext != RADIO)
1848 			{
1849 				DIALOG *dialog = dia->itemDesc();
1850 				for (int i = 0; i < dialog->items; i++)
1851 					if ((dialog->list[i].type&ITEMTYPEEXT) == itemtypeext)
1852 				{
1853 					dia->setControl( i + 1, (i + 1) == item );
1854 				}
1855 			}
1856 			break;
1857 	}
1858 	dia->itemHitAction( item );
1859 }
1860 
redispCaller(RECTAREA * rect,void * vdia)1861 void EDialogPrivate::redispCaller(RECTAREA *rect, void *vdia)
1862 {
1863 	EDialogPrivate *p = find(vdia);
1864 	if (!p) return;
1865 	(*p->redisp)( rect, p->dia );
1866 }
1867 
EDialog(DIALOG * dialog)1868 EDialog::EDialog( DIALOG *dialog )
1869 	: itemdesc( dialog ), isExtended( FALSE )
1870 {
1871 	d = new EDialogPrivate( this );
1872 	if (!d) ttyputnomemory();
1873 }
1874 
~EDialog()1875 EDialog::~EDialog()
1876 {
1877     /* if (in_loop) ttyputerr(_("Dialog shuuld be closed by accept() or reject()")); */
1878     delete d;
1879 }
1880 
reset()1881 void EDialog::reset()
1882 {
1883 }
1884 
nextHit(void)1885 INTBIG EDialog::nextHit(void)
1886 {
1887     ttyputerr(_("nextHit() called in class dialog"));
1888     return 0;
1889 }
1890 
itemHitAction(INTBIG itemHit)1891 void EDialog::itemHitAction(INTBIG itemHit)
1892 {
1893     ttyputerr(_("EDialog::itemHisAction should be redefined"));
1894 }
1895 
showExtension(BOOLEAN showIt)1896 void EDialog::showExtension( BOOLEAN showIt )
1897 {
1898     if (itemdesc->briefHeight == 0) return;
1899     if (isExtended == showIt) return;
1900     isExtended = showIt;
1901     RECTAREA& r = itemdesc->windowRect;
1902     if (d->vdia)
1903         DiaResizeDialog( d->vdia, r.right - r.left, (isExtended ? r.bottom  - r.top : itemdesc->briefHeight ) );
1904 }
1905 
extension()1906 BOOLEAN EDialog::extension()
1907 {
1908     return isExtended;
1909 }
1910 
initTextDialog(INTBIG item,BOOLEAN (* toplist)(CHAR **),CHAR * (* nextinlist)(void),void (* donelist)(void),INTBIG sortpos,INTBIG flags)1911 void EDialog::initTextDialog(INTBIG item, BOOLEAN (*toplist)(CHAR **), CHAR *(*nextinlist)(void),
1912 			void (*donelist)(void), INTBIG sortpos, INTBIG flags)
1913 {
1914     DiaInitTextDialog( d->vdia, item, toplist, nextinlist, donelist, sortpos, flags);
1915 }
1916 
loadTextDialog(INTBIG item,BOOLEAN (* toplist)(CHAR **),CHAR * (* nextinlist)(void),void (* donelist)(void),INTBIG sortpos)1917 void EDialog::loadTextDialog(INTBIG item, BOOLEAN (*toplist)(CHAR **), CHAR *(*nextinlist)(void),
1918 			void (*donelist)(void), INTBIG sortpos)
1919 {
1920     DiaLoadTextDialog( d->vdia, item, toplist, nextinlist, donelist, sortpos );
1921 }
1922 
redispRoutine(INTBIG item,void (* routine)(RECTAREA * rect,void * dia))1923 void EDialog::redispRoutine(INTBIG item, void (*routine)(RECTAREA *rect, void *dia))
1924 {
1925     d->redisp = routine;
1926     DiaRedispRoutine ( d->vdia, item, EDialogPrivate::redispCaller );
1927 }
1928 
setControl(INTBIG item,INTBIG value)1929 void EDialog::setControl(INTBIG item, INTBIG value)
1930 {
1931     INTBIG itemtypeext = itemdesc->list[item - 1].type&ITEMTYPEEXT;
1932     /* emulate grouped radio-buttones */
1933     if ((itemtypeext&ITEMTYPE) == RADIO && itemtypeext != RADIO && value != 0)
1934     {
1935         for (int i = 0; i < itemdesc->items; i++)
1936         {
1937             if ((itemdesc->list[i].type&ITEMTYPEEXT) == itemtypeext && i != item - 1)
1938                 DiaSetControl( d->vdia, item, 0 );
1939         }
1940     }
1941     DiaSetControl( d->vdia, item, value );
1942 }
1943 
setText(INTBIG item,CHAR * msg)1944 void EDialog::setText(INTBIG item, CHAR *msg)
1945 {
1946     if (d->vdia)
1947         DiaSetText( d->vdia, item, msg );
1948 }
1949 
resizeDialog(INTBIG wid,INTBIG hei)1950 void EDialog::resizeDialog(INTBIG wid, INTBIG hei) { DiaResizeDialog( d->vdia, wid, hei ); }
bringToTop()1951 void EDialog::bringToTop() { DiaBringToTop(d->vdia); };
getText(INTBIG item)1952 CHAR *EDialog::getText(INTBIG item) { return DiaGetText( d->vdia, item ); }
getControl(INTBIG item)1953 INTBIG EDialog::getControl(INTBIG item) { return DiaGetControl( d->vdia, item ); }
validEntry(INTBIG item)1954 BOOLEAN EDialog::validEntry(INTBIG item) { return DiaValidEntry( d->vdia, item ); }
dimItem(INTBIG item)1955 void EDialog::dimItem(INTBIG item) { DiaDimItem( d->vdia, item ); }
unDimItem(INTBIG item)1956 void EDialog::unDimItem(INTBIG item) { DiaUnDimItem( d->vdia, item ); }
noEditControl(INTBIG item)1957 void EDialog::noEditControl(INTBIG item) { DiaNoEditControl( d->vdia, item ); }
editControl(INTBIG item)1958 void EDialog::editControl(INTBIG item) { DiaEditControl( d->vdia, item ); }
opaqueEdit(INTBIG item)1959 void EDialog::opaqueEdit(INTBIG item) { DiaOpaqueEdit( d->vdia, item ); }
defaultButton(INTBIG item)1960 void EDialog::defaultButton(INTBIG item) { DiaDefaultButton( d->vdia, item ); }
changeIcon(INTBIG item,UCHAR1 * icon)1961 void EDialog::changeIcon(INTBIG item, UCHAR1 *icon) { DiaChangeIcon( d->vdia, item, icon ); }
setPopup(INTBIG item,INTBIG count,CHAR ** names)1962 void EDialog::setPopup(INTBIG item, INTBIG count, CHAR **names) { DiaSetPopup( d->vdia, item, count, names ); }
setPopupEntry(INTBIG item,INTBIG entry)1963 void EDialog::setPopupEntry(INTBIG item, INTBIG entry) { DiaSetPopupEntry( d->vdia, item, entry ); }
getPopupEntry(INTBIG item)1964 INTBIG EDialog::getPopupEntry(INTBIG item) { return DiaGetPopupEntry( d->vdia, item ); }
stuffLine(INTBIG item,CHAR * line)1965 void EDialog::stuffLine(INTBIG item, CHAR *line) { DiaStuffLine( d->vdia, item, line ); }
selectLine(INTBIG item,INTBIG line)1966 void EDialog::selectLine(INTBIG item, INTBIG line) { DiaSelectLine( d->vdia, item, line); }
selectLines(INTBIG item,INTBIG count,INTBIG * lines)1967 void EDialog::selectLines(INTBIG item, INTBIG count, INTBIG *lines) { DiaSelectLines( d->vdia, item, count, lines );}
getCurLine(INTBIG item)1968 INTBIG EDialog::getCurLine(INTBIG item) { return DiaGetCurLine( d->vdia, item ); }
getCurLines(INTBIG item)1969 INTBIG *EDialog::getCurLines(INTBIG item) { return DiaGetCurLines( d->vdia, item ); }
getNumScrollLines(INTBIG item)1970 INTBIG EDialog::getNumScrollLines(INTBIG item) { return DiaGetNumScrollLines( d->vdia, item ); }
getScrollLine(INTBIG item,INTBIG line)1971 CHAR *EDialog::getScrollLine(INTBIG item, INTBIG line) { return DiaGetScrollLine( d->vdia, item, line ); }
setScrollLine(INTBIG item,INTBIG line,CHAR * msg)1972 void EDialog::setScrollLine(INTBIG item, INTBIG line, CHAR *msg) { DiaSetScrollLine( d->vdia, item, line, msg ); }
synchVScrolls(INTBIG item1,INTBIG item2,INTBIG item3)1973 void EDialog::synchVScrolls(INTBIG item1, INTBIG item2, INTBIG item3) { DiaSynchVScrolls( d->vdia, item1, item2, item3 ); }
unSynchVScrolls()1974 void EDialog::unSynchVScrolls() { DiaUnSynchVScrolls( d->vdia ); }
itemRect(INTBIG item,RECTAREA * rect)1975 void EDialog::itemRect(INTBIG item, RECTAREA *rect) { DiaItemRect( d->vdia, item, rect ); }
percent(INTBIG item,INTBIG percent)1976 void EDialog::percent(INTBIG item, INTBIG percent) { DiaPercent( d->vdia, item, percent ); }
allowUserDoubleClick(void)1977 void EDialog::allowUserDoubleClick(void) { DiaAllowUserDoubleClick( d->vdia ); }
fillPoly(INTBIG item,INTBIG * xv,INTBIG * yv,INTBIG count,INTBIG r,INTBIG g,INTBIG b)1978 void EDialog::fillPoly(INTBIG item, INTBIG *xv, INTBIG *yv, INTBIG count, INTBIG r, INTBIG g, INTBIG b) { DiaFillPoly( d->vdia, item, xv, yv, count, r, g, b ); }
drawRect(INTBIG item,RECTAREA * rect,INTBIG r,INTBIG g,INTBIG b)1979 void EDialog::drawRect(INTBIG item, RECTAREA *rect, INTBIG r, INTBIG g, INTBIG b) { DiaDrawRect( d->vdia, item, rect, r, g, b ); }
frameRect(INTBIG item,RECTAREA * r)1980 void EDialog::frameRect(INTBIG item, RECTAREA *r) { DiaFrameRect( d->vdia, item, r ); }
invertRect(INTBIG item,RECTAREA * r)1981 void EDialog::invertRect(INTBIG item, RECTAREA *r) { DiaInvertRect( d->vdia, item, r); }
drawLine(INTBIG item,INTBIG fx,INTBIG fy,INTBIG tx,INTBIG ty,INTBIG mode)1982 void EDialog::drawLine(INTBIG item, INTBIG fx, INTBIG fy, INTBIG tx, INTBIG ty, INTBIG mode) { DiaDrawLine( d->vdia, item, fx, fy, tx, ty, mode ); }
setTextSize(INTBIG size)1983 void EDialog::setTextSize(INTBIG size) { DiaSetTextSize( d->vdia, size ); }
getTextInfo(CHAR * msg,INTBIG * wid,INTBIG * hei)1984 void EDialog::getTextInfo(CHAR *msg, INTBIG *wid, INTBIG *hei) { DiaGetTextInfo( d->vdia, msg, wid, hei ); }
putText(INTBIG item,CHAR * msg,INTBIG x,INTBIG y)1985 void EDialog::putText(INTBIG item, CHAR *msg, INTBIG x, INTBIG y) { DiaPutText( d->vdia, item, msg, x, y ); }
trackCursor(void (* eachdown)(INTBIG x,INTBIG y))1986 void EDialog::trackCursor(void (*eachdown)(INTBIG x, INTBIG y)) { DiaTrackCursor( d->vdia, eachdown ); }
getMouse(INTBIG * x,INTBIG * y)1987 void EDialog::getMouse(INTBIG *x, INTBIG *y) { DiaGetMouse( d->vdia, x, y ); }
1988 
EDialogModal(DIALOG * dialog)1989 EDialogModal::EDialogModal( DIALOG *dialog )
1990     : EDialog( dialog ), in_loop(FALSE), result(Rejected)
1991 {
1992     d->modal = TRUE;
1993     d->vdia = DiaInitDialog( dialog );
1994     if ( !d->vdia ) ttyputerr(_("Creation of dialog %s failed"), dialog->movable );
1995 }
1996 
exec()1997 EDialogModal::DialogCode EDialogModal::exec()
1998 {
1999     result = Rejected;
2000     for (in_loop = TRUE; in_loop;)
2001     {
2002 		INTBIG itemHit = DiaNextHit( d->vdia );
2003         EDialogPrivate::itemHitActionCaller( d->vdia, itemHit );
2004     }
2005     return(result);
2006 }
2007 
EDialogModeless(DIALOG * dialog)2008 EDialogModeless::EDialogModeless( DIALOG *dialog )
2009     : EDialog( dialog )
2010 {
2011     d->modal = FALSE;
2012 }
2013 
show()2014 void EDialogModeless::show()
2015 {
2016     if (d->vdia)
2017     {
2018         DiaBringToTop( d->vdia );
2019         return;
2020     }
2021     if (itemDesc()->briefHeight != 0 && !extension())
2022     {
2023         INTBIG saveBottom = itemDesc()->windowRect.bottom;
2024         itemDesc()->windowRect.bottom = (INTSML)(itemDesc()->windowRect.top + itemDesc()->briefHeight);
2025         d->vdia = DiaInitDialogModeless( itemDesc(), EDialogPrivate::itemHitActionCaller );
2026         itemDesc()->windowRect.bottom = (INTSML)saveBottom;
2027     } else d->vdia = DiaInitDialogModeless( itemDesc(), EDialogPrivate::itemHitActionCaller );
2028     if ( !d->vdia ) ttyputerr(_("Creation of dialog %s failed"), itemDesc()->movable );
2029 }
2030 
hide()2031 void EDialogModeless::hide()
2032 {
2033     if (!d->vdia) return;
2034     DiaDoneDialog( d->vdia );
2035     d->vdia = 0;
2036 }
2037 
isHidden()2038 BOOLEAN EDialogModeless::isHidden()
2039 {
2040     return(d->vdia == 0);
2041 }
2042 
2043 /***************** EProcess class on non-QT platforms ***********************/
2044 
2045 class EProcessPrivate
2046 {
2047 	friend class EProcess;
2048 public:
2049 	EProcessPrivate();
2050 	INTBIG process;
2051 	CHAR **arguments;
2052 	BOOLEAN _cStdin, _cStdout, _cStderr;
2053 	int ipipe[2];
2054 	int opipe[2];
2055 	UCHAR1 buf[1024];
2056 	UCHAR1 *bufp;
2057 	UINTBIG bufn;
2058 };
2059 
EProcessPrivate()2060 EProcessPrivate::EProcessPrivate()
2061 	: _cStdin( TRUE ), _cStdout( TRUE ), _cStderr( TRUE ), bufn( 0 )
2062 {
2063 	arguments = new (CHAR*[1]);
2064 	arguments[0] = 0;
2065 }
2066 
EProcess()2067 EProcess::EProcess()
2068 {
2069 	d = new EProcessPrivate();
2070 }
2071 
~EProcess()2072 EProcess::~EProcess()
2073 {
2074 	clearArguments();
2075 	delete[] d->arguments;
2076 	delete d;
2077 }
2078 
clearArguments()2079 void EProcess::clearArguments()
2080 {
2081 	for (int i = 0; d->arguments[i] != 0; i++)
2082 		delete[] d->arguments[i];
2083 	delete[] d->arguments;
2084 	d->arguments = new (CHAR*[1]);
2085 	d->arguments[0] = 0;
2086 }
2087 
addArgument(CHAR * arg)2088 void EProcess::addArgument( CHAR *arg )
2089 {
2090 	int i, n;
2091 	CHAR **newArguments;
2092 
2093 	n = 0;
2094 	while (d->arguments[n] != 0) n++;
2095 	newArguments = new (CHAR*[n + 2]);
2096 
2097 	for (i = 0; i < n; i++)
2098 		newArguments[i] = d->arguments[i];
2099 	newArguments[n] = new CHAR[estrlen(arg) + 1];
2100 	estrcpy(newArguments[n], arg);
2101 	newArguments[n + 1] = 0;
2102 	delete[] d->arguments;
2103 	d->arguments = newArguments;
2104 }
2105 
setCommunication(BOOLEAN cStdin,BOOLEAN cStdout,BOOLEAN cStderr)2106 void EProcess::setCommunication( BOOLEAN cStdin, BOOLEAN cStdout, BOOLEAN cStderr )
2107 {
2108 	d->_cStdin = cStdin;
2109 	d->_cStdout = cStdout;
2110 	d->_cStderr = cStderr;
2111 }
2112 
start(CHAR * infile)2113 BOOLEAN EProcess::start( CHAR *infile )
2114 {
2115 	d->bufn = 0;
2116 	if ( d->_cStdin ) (void)epipe(d->ipipe);
2117 	if ( d->_cStdout || d->_cStderr ) (void)epipe(d->opipe);
2118 
2119 	d->process = efork();
2120 	if (d->process == 1)
2121 	{
2122 		ttyputmsg(_("Run process directly please"));
2123 		return FALSE;
2124 	}
2125 	if (d->process == 0)
2126 	{
2127 		REGISTER INTBIG save0, save1, save2;
2128 
2129 		if (d->_cStdin ) save0 = channelreplacewithchannel(0, d->ipipe[0]);
2130 		else if (infile != 0) save0 = channelreplacewithfile(0, infile);
2131 		if ( d->_cStdout ) save1 = channelreplacewithchannel(1, d->opipe[1]);
2132 		if ( d->_cStderr ) save2 = channelreplacewithchannel(2, d->opipe[1]);
2133 		eexec( d->arguments[0], d->arguments );
2134 
2135 		if ( d->_cStdin || infile != 0) channelrestore(0, save0);
2136 		if ( d->_cStdout ) channelrestore(1, save1);
2137 		if ( d->_cStderr ) channelrestore(2, save2);
2138 		ttyputerr(_("Cannot run %s"), d->arguments[0]);
2139 		exit(1);
2140 	}
2141 
2142 	/* close the file descriptor so the pipe will terminate when done */
2143 	if ( d->_cStdin) eclose(d->ipipe[0]);
2144 	if ( d->_cStdout || d->_cStderr) eclose(d->opipe[1]);
2145 
2146 	return TRUE;
2147 }
2148 
wait()2149 void EProcess::wait()
2150 {
2151 	ewait( d->process );
2152 }
2153 
kill()2154 void EProcess::kill()
2155 {
2156 	if ( d->_cStdout || d->_cStderr) eclose(d->opipe[0]);
2157 	if (ekill(d->process) == 0)
2158 	{
2159 		ewait(d->process);
2160 		if (errno > 0)
2161 			ttyputmsg(_("%s execution reports error %d"), d->arguments[0], errno);
2162 		else ttyputmsg(_("%s execution terminated"), d->arguments[0]);
2163 	}
2164 }
2165 
getChar()2166 INTSML EProcess::getChar()
2167 {
2168 	if (d->bufn <= 0)
2169 	{
2170 		d->bufn = eread(d->opipe[0], d->buf, sizeof(d->buf)/sizeof(d->buf[0]));
2171 		d->bufp=d->buf;
2172 	}
2173 	if (d->bufn <= 0) return EOF;
2174 	d->bufn--;
2175 	return *d->bufp++;
2176 }
2177 
putChar(UCHAR1 ch)2178 void EProcess::putChar( UCHAR1 ch )
2179 {
2180 	ewrite(d->ipipe[1], &ch, 1 );
2181 }
2182 
2183 #endif /* USEQT */
2184 
2185 
2186