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