1
2 #ifndef lint
3 static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/resis/ResUtils.c,v 1.3 2010/06/24 12:37:56 tim Exp $";
4 #endif /* not lint */
5
6 #include <stdio.h>
7 #include <string.h>
8 #include <ctype.h>
9 #include <math.h>
10
11 #include "utils/magic.h"
12 #include "utils/geometry.h"
13 #include "utils/geofast.h"
14 #include "tiles/tile.h"
15 #include "utils/hash.h"
16 #include "database/database.h"
17 #include "utils/malloc.h"
18 #include "textio/textio.h"
19 #include "extract/extract.h"
20 #include "extract/extractInt.h"
21 #include "windows/windows.h"
22 #include "dbwind/dbwind.h"
23 #include "utils/stack.h"
24 #include "utils/tech.h"
25 #include "textio/txcommands.h"
26 #include "resis/resis.h"
27
28
29 /*
30 * ---------------------------------------------------------------------------
31 *
32 * ResFirst -- Checks to see if tile is a contact. If it is, allocate a
33 * contact structure.
34 *
35 *
36 * Results: Always returns NULL (in the form of a Region pointer)
37 *
38 * Side effects:
39 * Memory is allocated by ResFirst.
40 * We cons the newly allocated region onto the front of the existing
41 * region list.
42 *
43 *
44 * -------------------------------------------------------------------------
45 */
46
47 Region *
ResFirst(tile,arg)48 ResFirst(tile, arg)
49 Tile *tile;
50 FindRegion *arg;
51 {
52 ResContactPoint *reg;
53 TileType t;
54 int i;
55
56 if (IsSplit(tile))
57 {
58 t = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
59 }
60 else
61 t = TiGetType(tile);
62
63 if (DBIsContact(t))
64 {
65 reg = (ResContactPoint *) mallocMagic((unsigned) (sizeof(ResContactPoint)));
66 reg->cp_center.p_x = (LEFT(tile) + RIGHT(tile)) >> 1;
67 reg->cp_center.p_y = (TOP(tile) + BOTTOM(tile)) >> 1;
68 reg->cp_status = FALSE;
69 reg->cp_type = t;
70 reg->cp_width = RIGHT(tile) - LEFT(tile);
71 reg->cp_height = TOP(tile) - BOTTOM(tile);
72 for (i = 0; i < LAYERS_PER_CONTACT; i++)
73 {
74 reg->cp_tile[i] = (Tile *) NULL;
75 reg->cp_cnode[i] = (resNode *) NULL;
76 }
77 reg->cp_currentcontact = 0;
78 reg->cp_rect.r_ll.p_x = tile->ti_ll.p_x;
79 reg->cp_rect.r_ll.p_y = tile->ti_ll.p_y;
80 reg->cp_rect.r_ur.p_x = RIGHT(tile);
81 reg->cp_rect.r_ur.p_y = TOP(tile);
82 reg->cp_contactTile = tile;
83 /* Prepend it to the region list */
84 reg->cp_nextcontact = (ResContactPoint *) arg->fra_region;
85 arg->fra_region = (Region *) reg;
86 }
87 return((Region *) NULL);
88 }
89
90 /*
91 *--------------------------------------------------------------------------
92 *
93 * resMultiPlaneTerm --
94 *
95 * Callback function to set a junk field
96 *
97 *--------------------------------------------------------------------------
98 */
99
100 int
resMultiPlaneTerm(Tile * tile,tileJunk * junk2)101 resMultiPlaneTerm(Tile *tile, tileJunk *junk2)
102 {
103 tileJunk *Junk;
104
105 Junk = resAddField(tile);
106 Junk->tj_status |= RES_TILE_SD;
107 junk2->sourceEdge |= OTHERPLANE;
108 return 0;
109 }
110
111 /*
112 *--------------------------------------------------------------------------
113 *
114 * resSubstrateTerm --
115 *
116 * Callback function to set a junk field
117 *
118 *--------------------------------------------------------------------------
119 */
120
121 int
resSubstrateTerm(Tile * tile)122 resSubstrateTerm(Tile *tile)
123 {
124 tileJunk *Junk;
125
126 Junk = resAddField(tile);
127 Junk->tj_status |= RES_TILE_SUBS;
128 return 0;
129 }
130
131 /*
132 *--------------------------------------------------------------------------
133 *
134 * ResEach--
135 *
136 * ResEach calls ResFirst unless this is the first contact, in which case it
137 * has alreay been processed
138 *
139 * results: returns 0
140 *
141 * Side Effects: see ResFirst
142 *
143 * -------------------------------------------------------------------------
144 */
145
146 int
ResEach(tile,pNum,arg)147 ResEach(tile, pNum, arg)
148 Tile *tile;
149 int pNum;
150 FindRegion *arg;
151 {
152
153 if (((ResContactPoint *)(arg->fra_region))->cp_contactTile != tile)
154 {
155 ResFirst(tile, arg);
156 }
157 return(0);
158 }
159
160 /*
161 *-------------------------------------------------------------------------
162 *
163 * ResAddPlumbing-- Each tile is a tileJunk structure associated with it
164 * to keep track of various things used by the extractor. ResAddPlumbing
165 * adds this structure and sets the tile's ClientData field to point to it.
166 * If the tile is a device, then a device structure is also added;
167 * all connected device tiles are enumerated and their deviceList
168 * fields set to the new structure.
169 *
170 * Results: always returns 0
171 *
172 * Side Effects:see above
173 *
174 *-------------------------------------------------------------------------
175 */
176
177 int
ResAddPlumbing(tile,arg)178 ResAddPlumbing(tile, arg)
179 Tile *tile;
180 ClientData *arg;
181 {
182 tileJunk *Junk, *junk2;
183 static Stack *resDevStack = NULL;
184 TileType loctype, t1;
185 Tile *tp1, *tp2, *source;
186 resDevice *resDev;
187 ExtDevice *devptr;
188 TileTypeBitMask locDevSubsMask;
189
190 if (resDevStack == NULL)
191 resDevStack = StackNew(64);
192
193 if (tile->ti_client == (ClientData) CLIENTDEFAULT)
194 {
195 if (IsSplit(tile))
196 loctype = (SplitSide(tile)) ? SplitRightType(tile) :
197 SplitLeftType(tile);
198 else
199 loctype = TiGetTypeExact(tile);
200
201 devptr = ExtCurStyle->exts_device[loctype];
202 junk2 = resAddField(tile);
203 if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask), loctype))
204 {
205 int i, nterms, pNum;
206 Rect r;
207
208 /* Count SD terminals of the device */
209 nterms = 0;
210 for (i = 0;; i++)
211 {
212 if (TTMaskIsZero(&(devptr->exts_deviceSDTypes[i]))) break;
213 nterms++;
214 }
215 if (nterms < devptr->exts_deviceSDCount)
216 nterms = devptr->exts_deviceSDCount;
217
218 /* resDev terminals includes device identifier (e.g., gate) and
219 * substrate, so add two to nterms.
220 */
221 nterms += 2;
222
223 resDev = (resDevice *) mallocMagic((unsigned)(sizeof(resDevice)));
224 resDev->rd_nterms = nterms;
225 resDev->rd_terminals = (resNode **) mallocMagic(nterms * sizeof(resNode *));
226 for (i = 0; i != nterms; i++)
227 resDev->rd_terminals[i] = (resNode *) NULL;
228
229 resDev->rd_tile = tile;
230 resDev->rd_inside.r_ll.p_x = LEFT(tile);
231 resDev->rd_inside.r_ll.p_y = BOTTOM(tile);
232 resDev->rd_inside.r_ur.p_x = RIGHT(tile);
233 resDev->rd_inside.r_ur.p_y = TOP(tile);
234 resDev->rd_devtype = loctype;
235 resDev->rd_tiles = 0;
236 resDev->rd_length = 0;
237 resDev->rd_width = 0;
238 resDev->rd_perim = 0;
239 resDev->rd_area = 0;
240 resDev->rd_status = 0;
241 resDev->rd_nextDev = (resDevice *) *arg;
242 *arg = (ClientData)resDev;
243 junk2->deviceList = resDev;
244 junk2->tj_status |= RES_TILE_DEV;
245
246 for (i = 0; i < nterms - 2; i++)
247 {
248 source = NULL;
249 /* find diffusion (if present) to be source contact */
250
251 /* top */
252 for (tp2 = RT(tile); RIGHT(tp2) > LEFT(tile); tp2 = BL(tp2))
253 {
254 if TTMaskHasType(&(devptr->exts_deviceSDTypes[i]),
255 TiGetBottomType(tp2))
256 {
257 junk2->sourceEdge |= TOPEDGE;
258 source = tp2;
259 Junk = resAddField(source);
260 Junk->tj_status |= RES_TILE_SD;
261 break;
262 }
263 }
264
265 /* bottom */
266 if (source == NULL)
267 for (tp2 = LB(tile); LEFT(tp2) < RIGHT(tile); tp2 = TR(tp2))
268 {
269 if TTMaskHasType(&(devptr->exts_deviceSDTypes[i]),
270 TiGetTopType(tp2))
271 {
272 junk2->sourceEdge |= BOTTOMEDGE;
273 source = tp2;
274 Junk = resAddField(source);
275 Junk->tj_status |= RES_TILE_SD;
276 break;
277 }
278 }
279
280 /* right */
281 if (source == NULL)
282 for (tp2 = TR(tile); TOP(tp2) > BOTTOM(tile); tp2 = LB(tp2))
283 {
284 if TTMaskHasType(&(devptr->exts_deviceSDTypes[i]),
285 TiGetLeftType(tp2))
286 {
287 junk2->sourceEdge |= RIGHTEDGE;
288 source = tp2;
289 Junk = resAddField(source);
290 Junk->tj_status |= RES_TILE_SD;
291 break;
292 }
293 }
294
295 /* left */
296 if (source == NULL)
297 for (tp2 = BL(tile); BOTTOM(tp2) < TOP(tile); tp2 = RT(tp2))
298 {
299 if TTMaskHasType(&(devptr->exts_deviceSDTypes[i]),
300 TiGetRightType(tp2))
301 {
302 source = tp2;
303 Junk = resAddField(source);
304 Junk->tj_status |= RES_TILE_SD;
305 junk2->sourceEdge |= LEFTEDGE;
306 break;
307 }
308 }
309
310 /* other plane (in ResUse) */
311 if (source == NULL)
312 {
313 TiToRect(tile, &r);
314 for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
315 {
316 if (TTMaskIntersect(&DBPlaneTypes[pNum],
317 &(devptr->exts_deviceSDTypes[i])))
318 DBSrPaintArea((Tile *)NULL,
319 ResUse->cu_def->cd_planes[pNum],
320 &r, &(devptr->exts_deviceSDTypes[i]),
321 resMultiPlaneTerm, (ClientData)junk2);
322 }
323 }
324
325 /* We need to know whether a given diffusion tile connects to
326 * the source or to the drain of a device. A single
327 * diffusion tile is marked, and all connecting diffusion tiles
328 * are enumerated and called the source. Any other SD tiles
329 * are assumed to be the drain. BUG: this does not work
330 * correctly with multi SD structures.
331 */
332
333 if (source != (Tile *) NULL)
334 {
335 STACKPUSH((ClientData)source, resDevStack);
336 }
337 }
338 while (!StackEmpty(resDevStack))
339 {
340 tp1 = (Tile *) STACKPOP(resDevStack);
341 if (IsSplit(tp1))
342 {
343 t1 = (SplitSide(tp1)) ? SplitRightType(tp1) :
344 SplitLeftType(tp1);
345 }
346 else
347 t1 = TiGetTypeExact(tp1);
348
349 /* top */
350 for (tp2 = RT(tp1); RIGHT(tp2) > LEFT(tp1); tp2 = BL(tp2))
351 {
352 if (TiGetBottomType(tp2) == t1)
353 {
354 tileJunk *j = resAddField(tp2);
355 if ((j->tj_status & RES_TILE_SD) == 0)
356 {
357 j->tj_status |= RES_TILE_SD;
358 STACKPUSH((ClientData)tp2, resDevStack);
359 }
360 }
361 }
362 /* bottom */
363 for (tp2 = LB(tp1); LEFT(tp2) < RIGHT(tp1); tp2 = TR(tp2))
364 {
365 if (TiGetTopType(tp2) == t1)
366 {
367 tileJunk *j = resAddField(tp2);
368 if ((j->tj_status & RES_TILE_SD) == 0)
369 {
370 j->tj_status |= RES_TILE_SD;
371 STACKPUSH((ClientData)tp2, resDevStack);
372 }
373 }
374 }
375 /* right */
376 for (tp2 = TR(tp1); TOP(tp2) > BOTTOM(tp1); tp2 = LB(tp2))
377 {
378 if (TiGetLeftType(tp2) == t1)
379 {
380 tileJunk *j = resAddField(tp2);
381 if ((j->tj_status & RES_TILE_SD) == 0)
382 {
383 j->tj_status |= RES_TILE_SD;
384 STACKPUSH((ClientData)tp2, resDevStack);
385 }
386 }
387 }
388 /* left */
389 for (tp2 = BL(tp1); BOTTOM(tp2) < TOP(tp1); tp2 = RT(tp2))
390 {
391 if (TiGetRightType(tp2) == t1)
392 {
393 tileJunk *j = resAddField(tp2);
394 if ((j->tj_status & RES_TILE_SD) == 0)
395 {
396 j->tj_status |= RES_TILE_SD;
397 STACKPUSH((ClientData)tp2, resDevStack);
398 }
399 }
400 }
401 }
402
403 /* Find device substrate */
404
405 TTMaskZero(&locDevSubsMask);
406 TTMaskSetMask(&locDevSubsMask, &(devptr->exts_deviceSubstrateTypes));
407 TTMaskClearType(&locDevSubsMask, TT_SPACE);
408
409 TiToRect(tile, &r);
410 for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
411 {
412 if (TTMaskIntersect(&DBPlaneTypes[pNum], &locDevSubsMask))
413 DBSrPaintArea((Tile *)NULL,
414 ResUse->cu_def->cd_planes[pNum],
415 &r, &locDevSubsMask,
416 resSubstrateTerm, (ClientData)NULL);
417 }
418
419 /* find rest of device; search for source edges */
420
421 STACKPUSH((ClientData)tile, resDevStack);
422 while (!StackEmpty(resDevStack))
423 {
424 tileJunk *j0;
425
426 tp1 = (Tile *) STACKPOP(resDevStack);
427 if (IsSplit(tp1))
428 {
429 t1 = (SplitSide(tp1)) ? SplitRightType(tp1) :
430 SplitLeftType(tp1);
431 }
432 else
433 t1 = TiGetTypeExact(tp1);
434
435 devptr = ExtCurStyle->exts_device[t1];
436 j0 = (tileJunk *) tp1->ti_client;
437 /* top */
438 for (tp2 = RT(tp1); RIGHT(tp2) > LEFT(tp1); tp2 = BL(tp2))
439 {
440 if ((TiGetBottomType(tp2) == t1) &&
441 (tp2->ti_client == (ClientData) CLIENTDEFAULT))
442 {
443 Junk = resAddField(tp2);
444 STACKPUSH((ClientData)tp2, resDevStack);
445 Junk->deviceList = resDev;
446 Junk->tj_status |= RES_TILE_DEV;
447
448 }
449 else if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),
450 TiGetBottomType(tp2))
451 {
452 Junk = resAddField(tp2);
453 if (Junk->tj_status & RES_TILE_SD)
454 j0->sourceEdge |= TOPEDGE;
455 }
456 }
457 /* bottom */
458 for (tp2 = LB(tp1); LEFT(tp2) < RIGHT(tp1); tp2 = TR(tp2))
459 {
460 if ((TiGetTopType(tp2) == t1) &&
461 (tp2->ti_client == (ClientData) CLIENTDEFAULT))
462 {
463 Junk = resAddField(tp2);
464 STACKPUSH((ClientData)tp2, resDevStack);
465 Junk->deviceList = resDev;
466 Junk->tj_status |= RES_TILE_DEV;
467 }
468 else if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),
469 TiGetTopType(tp2))
470 {
471 Junk = resAddField(tp2);
472 if (Junk->tj_status & RES_TILE_SD)
473 j0->sourceEdge |= BOTTOMEDGE;
474 }
475 }
476 /* right */
477 for (tp2 = TR(tp1); TOP(tp2) > BOTTOM(tp1); tp2 = LB(tp2))
478 {
479 if ((TiGetLeftType(tp2) == t1) &&
480 (tp2->ti_client == (ClientData) CLIENTDEFAULT))
481 {
482 Junk = resAddField(tp2);
483 STACKPUSH((ClientData)tp2, resDevStack);
484 Junk->deviceList = resDev;
485 Junk->tj_status |= RES_TILE_DEV;
486 }
487 else if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),
488 TiGetLeftType(tp2))
489 {
490 Junk = resAddField(tp2);
491 if (Junk->tj_status & RES_TILE_SD)
492 j0->sourceEdge |= RIGHTEDGE;
493 }
494 }
495 /* left */
496 for (tp2 = BL(tp1); BOTTOM(tp2) < TOP(tp1); tp2 = RT(tp2))
497 {
498 if ((TiGetRightType(tp2) == t1) &&
499 (tp2->ti_client == (ClientData) CLIENTDEFAULT))
500 {
501 Junk = resAddField(tp2);
502 STACKPUSH((ClientData)tp2, resDevStack);
503 Junk->deviceList = resDev;
504 Junk->tj_status |= RES_TILE_DEV;
505 }
506 else if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),
507 TiGetRightType(tp2))
508 {
509 Junk = resAddField(tp2);
510 if (Junk->tj_status & RES_TILE_SD)
511 j0->sourceEdge |= LEFTEDGE;
512 }
513 }
514 }
515
516 /* unmark all tiles marked as being part of source */
517
518 if (source != (Tile *) NULL)
519 {
520 tileJunk *j = (tileJunk *) source->ti_client;
521
522 STACKPUSH((ClientData)source, resDevStack);
523 j->tj_status &= ~RES_TILE_SD;
524 }
525 while (!StackEmpty(resDevStack))
526 {
527 tp1 = (Tile *) STACKPOP(resDevStack);
528 if (IsSplit(tp1))
529 {
530 t1 = (SplitSide(tp1)) ? SplitRightType(tp1) :
531 SplitLeftType(tp1);
532 }
533 else
534 t1 = TiGetTypeExact(tp1);
535
536 /* top */
537 for (tp2 = RT(tp1); RIGHT(tp2) > LEFT(tp1); tp2 = BL(tp2))
538 {
539 tileJunk *j2 = (tileJunk *) tp2->ti_client;
540 if (TiGetBottomType(tp2) == t1)
541 {
542 if (j2->tj_status & RES_TILE_SD)
543 {
544 j2->tj_status &= ~RES_TILE_SD;
545 STACKPUSH((ClientData)tp2, resDevStack);
546 }
547 }
548 }
549 /* bottom */
550 for(tp2 = LB(tp1); LEFT(tp2) < RIGHT(tp1); tp2 = TR(tp2))
551 {
552 tileJunk *j2 = (tileJunk *) tp2->ti_client;
553 if (TiGetTopType(tp2) == t1)
554 {
555 if (j2->tj_status & RES_TILE_SD)
556 {
557 j2->tj_status &= ~RES_TILE_SD;
558 STACKPUSH((ClientData)tp2, resDevStack);
559 }
560 }
561 }
562 /* right */
563 for (tp2 = TR(tp1); TOP(tp2) > BOTTOM(tp1); tp2 = LB(tp2))
564 {
565 tileJunk *j2 = (tileJunk *) tp2->ti_client;
566 if (TiGetLeftType(tp2) == t1)
567 {
568 if (j2->tj_status & RES_TILE_SD)
569 {
570 j2->tj_status &= ~RES_TILE_SD;
571 STACKPUSH((ClientData)tp2, resDevStack);
572 }
573 }
574 }
575 /* left */
576 for (tp2 = BL(tp1); BOTTOM(tp2) < TOP(tp1); tp2 = RT(tp2))
577 {
578 tileJunk *j2 = (tileJunk *) tp2->ti_client;
579 if (TiGetRightType(tp2) == t1)
580 {
581 if (j2->tj_status & RES_TILE_SD)
582 {
583 j2->tj_status &= ~RES_TILE_SD;
584 STACKPUSH((ClientData)tp2, resDevStack);
585 }
586 }
587 }
588 }
589 }
590 }
591 return(0);
592 }
593
594 /*
595 *-------------------------------------------------------------------------
596 *
597 * ResRemovePlumbing-- Removes and deallocates all the tileJunk fields.
598 *
599 * Results: returns 0
600 *
601 * Side Effects: frees up memory; resets tile->ti_client fields to CLIENTDEFAULT
602 *
603 *-------------------------------------------------------------------------
604 */
605
606 int
ResRemovePlumbing(tile,arg)607 ResRemovePlumbing(tile, arg)
608 Tile *tile;
609 ClientData *arg;
610
611 {
612
613 if (tile->ti_client != (ClientData) CLIENTDEFAULT)
614 {
615 freeMagic(((char *)(tile->ti_client)));
616 tile->ti_client = (ClientData) CLIENTDEFAULT;
617 }
618 return(0);
619 }
620
621
622 /*
623 *-------------------------------------------------------------------------
624 *
625 * ResPreProcessDevices-- Given a list of all the device tiles and
626 * a list of all the devices, this procedure calculates the width and
627 * length. The width is set equal to the sum of all edges that touch
628 * diffusion divided by 2. The length is the remaining perimeter divided by
629 * 2*tiles. The perimeter and area fields of device structures are also
630 * fixed.
631 *
632 * Results: none
633 *
634 * Side Effects: sets length and width of devices. "ResDevTile"
635 * structures are freed.
636 *
637 *-------------------------------------------------------------------------
638 */
639
640 void
ResPreProcessDevices(TileList,DeviceList,Def)641 ResPreProcessDevices(TileList, DeviceList, Def)
642 ResDevTile *TileList;
643 resDevice *DeviceList;
644 CellDef *Def;
645 {
646 Tile *tile;
647 ResDevTile *oldTile;
648 tileJunk *tstruct;
649 TileType tt, residue;
650 int pNum;
651
652 while (TileList != (ResDevTile *) NULL)
653 {
654 tt = TileList->type;
655 if (DBIsContact(tt))
656 {
657 /* Find which residue of the contact is a device. */
658 TileTypeBitMask ttresidues;
659
660 DBFullResidueMask(tt, &ttresidues);
661
662 for (residue = TT_TECHDEPBASE; residue < DBNumUserLayers; residue++)
663 {
664 if (TTMaskHasType(&ttresidues, residue))
665 {
666 if (TTMaskHasType(&ExtCurStyle->exts_deviceMask, residue))
667 {
668 pNum = DBPlane(residue);
669 break;
670 }
671 }
672 }
673 }
674 else
675 pNum = DBPlane(tt); /* always correct for non-contact types */
676
677 tile = (Def->cd_planes[pNum])->pl_hint;
678 GOTOPOINT(tile, &(TileList->area.r_ll));
679
680 tt = TiGetType(tile);
681 tstruct = (tileJunk *) tile->ti_client;
682
683 if ((tstruct == (tileJunk *)CLIENTDEFAULT) ||
684 (tstruct->deviceList == NULL) ||
685 !TTMaskHasType(&ExtCurStyle->exts_deviceMask, tt))
686 {
687 TxError("Bad Device Location at %d,%d\n",
688 TileList->area.r_ll.p_x,
689 TileList->area.r_ll.p_y);
690 }
691 else if ((tstruct->tj_status & RES_TILE_MARK) == 0)
692 {
693 resDevice *rd = tstruct->deviceList;
694
695 tstruct->tj_status |= RES_TILE_MARK;
696 rd->rd_perim += TileList->perim;
697 rd->rd_length += TileList->overlap;
698 rd->rd_area += (TileList->area.r_xtop - TileList->area.r_xbot)
699 * (TileList->area.r_ytop - TileList->area.r_ybot);
700 rd->rd_tiles++;
701 }
702 oldTile = TileList;
703 TileList = TileList->nextDev;
704 freeMagic((char *)oldTile);
705 }
706
707 for (; DeviceList != NULL; DeviceList = DeviceList->rd_nextDev)
708 {
709 int width = DeviceList->rd_perim;
710 int length = DeviceList->rd_length;
711 if (DeviceList->rd_tiles != 0)
712 {
713 if (length)
714 {
715 DeviceList->rd_length = (float) length /
716 ((float)((DeviceList->rd_tiles) << 1));
717 DeviceList->rd_width = (width-length) >> 1;
718 }
719 else
720 {
721 double perimeter = DeviceList->rd_perim;
722 double area = DeviceList->rd_area;
723
724 perimeter /= 4.0;
725
726 DeviceList->rd_width = perimeter +
727 sqrt(perimeter * perimeter-area);
728 DeviceList->rd_length = (DeviceList->rd_perim
729 - 2 * DeviceList->rd_width) >> 1;
730 }
731 }
732 }
733 }
734
735
736 /*
737 *-------------------------------------------------------------------------
738 *
739 * ResAddToQueue-- adds new nodes to list of nodes requiring processing.
740 *
741 * Side Effects: nodes are added to list (i.e they have their linked list
742 * pointers modified.)
743 *
744 *-------------------------------------------------------------------------
745 */
746
747 void
ResAddToQueue(node,list)748 ResAddToQueue(node, list)
749 resNode *node, **list;
750 {
751 node->rn_more = *list;
752 node->rn_less = NULL;
753 if (*list) (*list)->rn_less = node;
754 *list = node;
755 }
756
757 /*
758 *-------------------------------------------------------------------------
759 *
760 * ResRemoveFromQueue-- removes node from queue. Complains if it notices
761 * that the node isn't in the supplied list.
762 *
763 * Results: none
764 *
765 * Side Effects: modifies nodelist
766 *
767 *-------------------------------------------------------------------------
768 */
769
770 void
ResRemoveFromQueue(node,list)771 ResRemoveFromQueue(node, list)
772 resNode *node, **list;
773 {
774 if (node->rn_less != NULL)
775 {
776 node->rn_less->rn_more = node->rn_more;
777 }
778 else
779 {
780 if (node != (*list))
781 {
782 TxError("Error: Attempt to remove node from wrong list\n");
783 }
784 else
785 {
786 *list = node->rn_more;
787 }
788 }
789 if (node->rn_more != NULL)
790 {
791 node->rn_more->rn_less = node->rn_less;
792 }
793 node->rn_more = NULL;
794 node->rn_less = NULL;
795 }
796
797 tileJunk *
resAddField(tile)798 resAddField(tile)
799 Tile *tile;
800 {
801 tileJunk *Junk;
802 if ((Junk = (tileJunk *)tile->ti_client) == (tileJunk *) CLIENTDEFAULT)
803 {
804 Junk = (tileJunk *) mallocMagic((unsigned) (sizeof(tileJunk)));
805 ResJunkInit(Junk);
806 tile->ti_client = (ClientData) Junk;
807 }
808 return Junk;
809 }
810