1 /*
2 * tile.c --
3 *
4 * Basic tile manipulation
5 *
6 * *********************************************************************
7 * * Copyright (C) 1985, 1990 Regents of the University of California. *
8 * * Permission to use, copy, modify, and distribute this *
9 * * software and its documentation for any purpose and without *
10 * * fee is hereby granted, provided that the above copyright *
11 * * notice appear in all copies. The University of California *
12 * * makes no representations about the suitability of this *
13 * * software for any purpose. It is provided "as is" without *
14 * * express or implied warranty. Export of this software outside *
15 * * of the United States of America may require an export license. *
16 * *********************************************************************
17 */
18
19 #ifndef lint
20 static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/tiles/tile.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
21 #endif /* not lint */
22
23 #include <stdio.h>
24 #include <unistd.h>
25 #include <stdlib.h>
26
27 #include "utils/magic.h"
28 #include "utils/malloc.h"
29 #include "utils/geometry.h"
30 #include "tiles/tile.h"
31
32 /*
33 * Debugging version of TiSetBody() macro in tile.h
34 * Includes sanity check that a tile at "infinity"
35 * is not being set to a type other than space.
36 */
37 /*
38 void
39 TiSetBody(tp, b)
40 Tile *tp;
41 ClientData b;
42 {
43 if (b != (ClientData)0 && b != (ClientData)(-1))
44 if (RIGHT(tp) == INFINITY || TOP(tp) == INFINITY ||
45 LEFT(tp) == MINFINITY || BOTTOM(tp) == MINFINITY)
46 TxError("Error: Tile at infinity set to non-space value %d\n", (int)b);
47 tp->ti_body = b;
48 }
49 */
50
51 /*
52 * Rectangle that defines the maximum extent of any plane.
53 * No tile created by the user should ever extend outside of
54 * this area.
55 */
56
57 global Rect TiPlaneRect = { MINFINITY+2, MINFINITY+2, INFINITY-2, INFINITY-2 };
58
59 #ifdef HAVE_SYS_MMAN_H
60
61 global Tile *TileStoreFreeList = NULL;
62 global Tile *TileStoreFreeList_end = NULL;
63
64 /* The new Tile Allocation scheme (Magic 8.0) */
65
66 static void *_block_begin = NULL;
67 static void *_current_ptr = NULL;
68 static void *_block_end = NULL;
69
70 #endif /* HAVE_SYS_MMAN_H */
71
72
73 /*
74 * --------------------------------------------------------------------
75 *
76 * TiNewPlane --
77 *
78 * Allocate and initialize a new tile plane.
79 *
80 * Results:
81 * A newly allocated Plane with all corner stitches set
82 * appropriately.
83 *
84 * Side effects:
85 * Adjusts the corner stitches of the Tile supplied to
86 * point to the appropriate bounding tile in the newly
87 * created Plane.
88 *
89 * --------------------------------------------------------------------
90 */
91
92 Plane *
TiNewPlane(tile)93 TiNewPlane(tile)
94 Tile *tile;/* Tile to become initial tile of plane.
95 * May be NULL.
96 */
97 {
98 Plane *newplane;
99 static Tile *infinityTile = (Tile *) NULL;
100
101 newplane = (Plane *) mallocMagic((unsigned) (sizeof (Plane)));
102 newplane->pl_top = TiAlloc();
103 newplane->pl_right = TiAlloc();
104 newplane->pl_bottom = TiAlloc();
105 newplane->pl_left = TiAlloc();
106
107 /*
108 * Since the lower left coordinates of the TR and RT
109 * stitches of a tile are used to determine its upper right,
110 * we must give the boundary tiles a meaningful TR and RT.
111 * To make certain that these tiles don't have zero width
112 * or height, we use a dummy tile at (INFINITY+1,INFINITY+1).
113 */
114
115 if (infinityTile == (Tile *) NULL)
116 {
117 infinityTile = TiAlloc();
118 LEFT(infinityTile) = INFINITY+1;
119 BOTTOM(infinityTile) = INFINITY+1;
120 }
121
122 if (tile)
123 {
124 RT(tile) = newplane->pl_top;
125 TR(tile) = newplane->pl_right;
126 LB(tile) = newplane->pl_bottom;
127 BL(tile) = newplane->pl_left;
128 }
129
130 LEFT(newplane->pl_bottom) = MINFINITY;
131 BOTTOM(newplane->pl_bottom) = MINFINITY;
132 RT(newplane->pl_bottom) = tile;
133 TR(newplane->pl_bottom) = newplane->pl_right;
134 LB(newplane->pl_bottom) = BADTILE;
135 BL(newplane->pl_bottom) = newplane->pl_left;
136 TiSetBody(newplane->pl_bottom, -1);
137
138 LEFT(newplane->pl_top) = MINFINITY;
139 BOTTOM(newplane->pl_top) = INFINITY;
140 RT(newplane->pl_top) = infinityTile;
141 TR(newplane->pl_top) = newplane->pl_right;
142 LB(newplane->pl_top) = tile;
143 BL(newplane->pl_top) = newplane->pl_left;
144 TiSetBody(newplane->pl_top, -1);
145
146 LEFT(newplane->pl_left) = MINFINITY;
147 BOTTOM(newplane->pl_left) = MINFINITY;
148 RT(newplane->pl_left) = newplane->pl_top;
149 TR(newplane->pl_left) = tile;
150 LB(newplane->pl_left) = newplane->pl_bottom;
151 BL(newplane->pl_left) = BADTILE;
152 TiSetBody(newplane->pl_left, -1);
153
154 LEFT(newplane->pl_right) = INFINITY;
155 BOTTOM(newplane->pl_right) = MINFINITY;
156 RT(newplane->pl_right) = newplane->pl_top;
157 TR(newplane->pl_right) = infinityTile;
158 LB(newplane->pl_right) = newplane->pl_bottom;
159 BL(newplane->pl_right) = tile;
160 TiSetBody(newplane->pl_right, -1);
161
162 newplane->pl_hint = tile;
163 return (newplane);
164 }
165
166 /*
167 * --------------------------------------------------------------------
168 *
169 * TiFreePlane --
170 *
171 * Free the storage associated with a tile plane.
172 * Only the plane itself and its four border tiles are deallocated.
173 *
174 * Results:
175 * None.
176 *
177 * Side effects:
178 * Frees memory.
179 *
180 * --------------------------------------------------------------------
181 */
182
183 void
TiFreePlane(plane)184 TiFreePlane(plane)
185 Plane *plane; /* Plane to be freed */
186 {
187 TiFree(plane->pl_left);
188 TiFree(plane->pl_right);
189 TiFree(plane->pl_top);
190 TiFree(plane->pl_bottom);
191 freeMagic((char *) plane);
192 }
193
194 /*
195 * --------------------------------------------------------------------
196 *
197 * TiToRect --
198 *
199 * Convert a tile to a rectangle.
200 *
201 * Results:
202 * None.
203 *
204 * Side effects:
205 * Sets *rect to the bounding box for the supplied tile.
206 *
207 * --------------------------------------------------------------------
208 */
209
210 void
TiToRect(tile,rect)211 TiToRect(tile, rect)
212 Tile *tile; /* Tile whose bounding box is to be stored in *rect */
213 Rect *rect; /* Pointer to rect to be set to bounding box */
214 {
215 rect->r_xbot = LEFT(tile);
216 rect->r_xtop = RIGHT(tile);
217 rect->r_ybot = BOTTOM(tile);
218 rect->r_ytop = TOP(tile);
219 }
220
221 /*
222 * --------------------------------------------------------------------
223 *
224 * TiSplitX --
225 *
226 * Given a tile and an X coordinate, split the tile into two
227 * along a line running vertically through the given coordinate.
228 *
229 * Results:
230 * Returns the new tile resulting from the splitting, which
231 * is the tile occupying the right-hand half of the original
232 * tile.
233 *
234 * Side effects:
235 * Modifies the corner stitches in the database to reflect
236 * the presence of two tiles in place of the original one.
237 *
238 * --------------------------------------------------------------------
239 */
240
241 Tile *
TiSplitX(tile,x)242 TiSplitX(tile, x)
243 Tile *tile; /* Tile to be split */
244 int x; /* X coordinate of split */
245 {
246 Tile *newtile;
247 Tile *tp;
248
249 ASSERT(x > LEFT(tile) && x < RIGHT(tile), "TiSplitX");
250
251 newtile = TiAlloc();
252 TiSetClient(newtile, CLIENTDEFAULT);
253 TiSetBody(newtile, 0);
254
255 LEFT(newtile) = x;
256 BOTTOM(newtile) = BOTTOM(tile);
257 BL(newtile) = tile;
258 TR(newtile) = TR(tile);
259 RT(newtile) = RT(tile);
260
261 /*
262 * Adjust corner stitches along the right edge
263 */
264
265 for (tp = TR(tile); BL(tp) == tile; tp = LB(tp))
266 BL(tp) = newtile;
267 TR(tile) = newtile;
268
269 /*
270 * Adjust corner stitches along the top edge
271 */
272
273 for (tp = RT(tile); LEFT(tp) >= x; tp = BL(tp))
274 LB(tp) = newtile;
275 RT(tile) = tp;
276
277 /*
278 * Adjust corner stitches along the bottom edge
279 */
280
281 for (tp = LB(tile); RIGHT(tp) <= x; tp = TR(tp))
282 /* nothing */;
283 LB(newtile) = tp;
284 while (RT(tp) == tile)
285 {
286 RT(tp) = newtile;
287 tp = TR(tp);
288 }
289
290 return (newtile);
291 }
292
293 /*
294 * --------------------------------------------------------------------
295 *
296 * TiSplitY --
297 *
298 * Given a tile and a Y coordinate, split the tile into two
299 * along a horizontal line running through the given coordinate.
300 *
301 * Results:
302 * Returns the new tile resulting from the splitting, which
303 * is the tile occupying the top half of the original
304 * tile.
305 *
306 * Side effects:
307 * Modifies the corner stitches in the database to reflect
308 * the presence of two tiles in place of the original one.
309 *
310 * --------------------------------------------------------------------
311 */
312
313 Tile *
TiSplitY(tile,y)314 TiSplitY(tile, y)
315 Tile *tile; /* Tile to be split */
316 int y; /* Y coordinate of split */
317 {
318 Tile *newtile;
319 Tile *tp;
320
321 ASSERT(y > BOTTOM(tile) && y < TOP(tile), "TiSplitY");
322
323 newtile = TiAlloc();
324 TiSetClient(newtile, CLIENTDEFAULT);
325 TiSetBody(newtile, 0);
326
327 LEFT(newtile) = LEFT(tile);
328 BOTTOM(newtile) = y;
329 LB(newtile) = tile;
330 RT(newtile) = RT(tile);
331 TR(newtile) = TR(tile);
332
333 /*
334 * Adjust corner stitches along top edge
335 */
336
337 for (tp = RT(tile); LB(tp) == tile; tp = BL(tp))
338 LB(tp) = newtile;
339 RT(tile) = newtile;
340
341 /*
342 * Adjust corner stitches along right edge
343 */
344
345 for (tp = TR(tile); BOTTOM(tp) >= y; tp = LB(tp))
346 BL(tp) = newtile;
347 TR(tile) = tp;
348
349 /*
350 * Adjust corner stitches along left edge
351 */
352
353 for (tp = BL(tile); TOP(tp) <= y; tp = RT(tp))
354 /* nothing */;
355 BL(newtile) = tp;
356 while (TR(tp) == tile)
357 {
358 TR(tp) = newtile;
359 tp = RT(tp);
360 }
361
362 return (newtile);
363 }
364
365 /*
366 * --------------------------------------------------------------------
367 *
368 * TiSplitX_Left --
369 *
370 * Given a tile and an X coordinate, split the tile into two
371 * along a line running vertically through the given coordinate.
372 * Intended for use when plowing to the left.
373 *
374 * Results:
375 * Returns the new tile resulting from the splitting, which
376 * is the tile occupying the left-hand half of the original
377 * tile.
378 *
379 * Side effects:
380 * Modifies the corner stitches in the database to reflect
381 * the presence of two tiles in place of the original one.
382 *
383 * --------------------------------------------------------------------
384 */
385
386 Tile *
TiSplitX_Left(tile,x)387 TiSplitX_Left(tile, x)
388 Tile *tile; /* Tile to be split */
389 int x; /* X coordinate of split */
390 {
391 Tile *newtile;
392 Tile *tp;
393
394 ASSERT(x > LEFT(tile) && x < RIGHT(tile), "TiSplitX");
395
396 newtile = TiAlloc();
397 TiSetClient(newtile, CLIENTDEFAULT);
398 TiSetBody(newtile, 0);
399
400 LEFT(newtile) = LEFT(tile);
401 LEFT(tile) = x;
402 BOTTOM(newtile) = BOTTOM(tile);
403
404 BL(newtile) = BL(tile);
405 LB(newtile) = LB(tile);
406 TR(newtile) = tile;
407 BL(tile) = newtile;
408
409 /* Adjust corner stitches along the left edge */
410 for (tp = BL(newtile); TR(tp) == tile; tp = RT(tp))
411 TR(tp) = newtile;
412
413 /* Adjust corner stitches along the top edge */
414 for (tp = RT(tile); LEFT(tp) >= x; tp = BL(tp))
415 /* nothing */;
416 RT(newtile) = tp;
417 for ( ; LB(tp) == tile; tp = BL(tp))
418 LB(tp) = newtile;
419
420 /* Adjust corner stitches along the bottom edge */
421 for (tp = LB(tile); RIGHT(tp) <= x; tp = TR(tp))
422 RT(tp) = newtile;
423 LB(tile) = tp;
424
425 return (newtile);
426 }
427
428 /*
429 * --------------------------------------------------------------------
430 *
431 * TiSplitY_Bottom --
432 *
433 * Given a tile and a Y coordinate, split the tile into two
434 * along a horizontal line running through the given coordinate.
435 * Used when plowing down.
436 *
437 * Results:
438 * Returns the new tile resulting from the splitting, which
439 * is the tile occupying the bottom half of the original
440 * tile.
441 *
442 * Side effects:
443 * Modifies the corner stitches in the database to reflect
444 * the presence of two tiles in place of the original one.
445 *
446 * --------------------------------------------------------------------
447 */
448
449 Tile *
TiSplitY_Bottom(tile,y)450 TiSplitY_Bottom(tile, y)
451 Tile *tile; /* Tile to be split */
452 int y; /* Y coordinate of split */
453 {
454 Tile *newtile;
455 Tile *tp;
456
457 ASSERT(y > BOTTOM(tile) && y < TOP(tile), "TiSplitY");
458
459 newtile = TiAlloc();
460 TiSetClient(newtile, CLIENTDEFAULT);
461 TiSetBody(newtile, 0);
462
463 LEFT(newtile) = LEFT(tile);
464 BOTTOM(newtile) = BOTTOM(tile);
465 BOTTOM(tile) = y;
466
467 RT(newtile) = tile;
468 LB(newtile) = LB(tile);
469 BL(newtile) = BL(tile);
470 LB(tile) = newtile;
471
472 /* Adjust corner stitches along bottom edge */
473 for (tp = LB(newtile); RT(tp) == tile; tp = TR(tp))
474 RT(tp) = newtile;
475
476 /* Adjust corner stitches along right edge */
477 for (tp = TR(tile); BOTTOM(tp) >= y; tp = LB(tp))
478 /* nothing */;
479 TR(newtile) = tp;
480 for ( ; BL(tp) == tile; tp = LB(tp))
481 BL(tp) = newtile;
482
483 /* Adjust corner stitches along left edge */
484 for (tp = BL(tile); TOP(tp) <= y; tp = RT(tp))
485 TR(tp) = newtile;
486 BL(tile) = tp;
487
488 return (newtile);
489 }
490
491 /*
492 * --------------------------------------------------------------------
493 *
494 * TiJoinX --
495 *
496 * Given two tiles sharing an entire common vertical edge, replace
497 * them with a single tile occupying the union of their areas.
498 *
499 * Results:
500 * None.
501 *
502 * Side effects:
503 * The first tile is simply relinked to reflect its new size.
504 * The second tile is deallocated. Corner stitches in the
505 * neighboring tiles are updated to reflect the new structure.
506 * If the hint tile pointer in the supplied plane pointed to
507 * the second tile, it is adjusted to point instead to the
508 * first.
509 *
510 * --------------------------------------------------------------------
511 */
512
513 void
TiJoinX(tile1,tile2,plane)514 TiJoinX(tile1, tile2, plane)
515 Tile *tile1; /* First tile, remains allocated after call */
516 Tile *tile2; /* Second tile, deallocated by call */
517 Plane *plane; /* Plane in which hint tile is updated */
518 {
519 Tile *tp;
520
521 /*
522 * Basic algorithm:
523 *
524 * Update all the corner stitches in the neighbors of tile2
525 * to point to tile1.
526 * Update the corner stitches of tile1 along the shared edge
527 * to be those of tile2.
528 * Change the bottom or left coordinate of tile1 if appropriate.
529 * Deallocate tile2.
530 */
531
532 ASSERT(BOTTOM(tile1)==BOTTOM(tile2) && TOP(tile1)==TOP(tile2), "TiJoinX");
533 ASSERT(LEFT(tile1)==RIGHT(tile2) || RIGHT(tile1)==LEFT(tile2), "TiJoinX");
534
535 /*
536 * Update stitches along top of tile
537 */
538
539 for (tp = RT(tile2); LB(tp) == tile2; tp = BL(tp))
540 LB(tp) = tile1;
541
542 /*
543 * Update stitches along bottom of tile
544 */
545
546 for (tp = LB(tile2); RT(tp) == tile2; tp = TR(tp))
547 RT(tp) = tile1;
548
549 /*
550 * Update stitches along either left or right, depending
551 * on relative position of the two tiles.
552 */
553
554 ASSERT(LEFT(tile1) != LEFT(tile2), "TiJoinX");
555 if (LEFT(tile1) < LEFT(tile2))
556 {
557 for (tp = TR(tile2); BL(tp) == tile2; tp = LB(tp))
558 BL(tp) = tile1;
559 TR(tile1) = TR(tile2);
560 RT(tile1) = RT(tile2);
561 }
562 else
563 {
564 for (tp = BL(tile2); TR(tp) == tile2; tp = RT(tp))
565 TR(tp) = tile1;
566 BL(tile1) = BL(tile2);
567 LB(tile1) = LB(tile2);
568 LEFT(tile1) = LEFT(tile2);
569 }
570
571 if (plane->pl_hint == tile2)
572 plane->pl_hint = tile1;
573 TiFree(tile2);
574 }
575
576 /*
577 * --------------------------------------------------------------------
578 *
579 * TiJoinY --
580 *
581 * Given two tiles sharing an entire common horizontal edge, replace
582 * them with a single tile occupying the union of their areas.
583 *
584 * Results:
585 * None.
586 *
587 * Side effects:
588 * The first tile is simply relinked to reflect its new size.
589 * The second tile is deallocated. Corner stitches in the
590 * neighboring tiles are updated to reflect the new structure.
591 * If the hint tile pointer in the supplied plane pointed to
592 * the second tile, it is adjusted to point instead to the
593 * first.
594 *
595 * --------------------------------------------------------------------
596 */
597
598 void
TiJoinY(tile1,tile2,plane)599 TiJoinY(tile1, tile2, plane)
600 Tile *tile1; /* First tile, remains allocated after call */
601 Tile *tile2; /* Second tile, deallocated by call */
602 Plane *plane; /* Plane in which hint tile is updated */
603 {
604 Tile *tp;
605
606 /*
607 * Basic algorithm:
608 *
609 * Update all the corner stitches in the neighbors of tile2
610 * to point to tile1.
611 * Update the corner stitches of tile1 along the shared edge
612 * to be those of tile2.
613 * Change the bottom or left coordinate of tile1 if appropriate.
614 * Deallocate tile2.
615 */
616
617 ASSERT(LEFT(tile1)==LEFT(tile2) && RIGHT(tile1)==RIGHT(tile2), "TiJoinY");
618 ASSERT(TOP(tile1)==BOTTOM(tile2) || BOTTOM(tile1)==TOP(tile2), "TiJoinY");
619
620 /*
621 * Update stitches along right of tile.
622 */
623
624 for (tp = TR(tile2); BL(tp) == tile2; tp = LB(tp))
625 BL(tp) = tile1;
626
627 /*
628 * Update stitches along left of tile.
629 */
630
631 for (tp = BL(tile2); TR(tp) == tile2; tp = RT(tp))
632 TR(tp) = tile1;
633
634 /*
635 * Update stitches along either top or bottom, depending
636 * on relative position of the two tiles.
637 */
638
639 ASSERT(BOTTOM(tile1) != BOTTOM(tile2), "TiJoinY");
640 if (BOTTOM(tile1) < BOTTOM(tile2))
641 {
642 for (tp = RT(tile2); LB(tp) == tile2; tp = BL(tp))
643 LB(tp) = tile1;
644 RT(tile1) = RT(tile2);
645 TR(tile1) = TR(tile2);
646 }
647 else
648 {
649 for (tp = LB(tile2); RT(tp) == tile2; tp = TR(tp))
650 RT(tp) = tile1;
651 LB(tile1) = LB(tile2);
652 BL(tile1) = BL(tile2);
653 BOTTOM(tile1) = BOTTOM(tile2);
654 }
655
656 if (plane->pl_hint == tile2)
657 plane->pl_hint = tile1;
658 TiFree(tile2);
659 }
660
661 #ifdef HAVE_SYS_MMAN_H
662
663 /* MMAP the tile store */
664 static signed char
mmapTileStore()665 mmapTileStore()
666 {
667 int prot = PROT_READ | PROT_WRITE;
668 int flags = MAP_ANON | MAP_PRIVATE;
669 unsigned long map_len = TILE_STORE_BLOCK_SIZE;
670
671 _block_begin = mmap(NULL, map_len, prot, flags, -1, 0);
672 if (_block_begin == MAP_FAILED)
673 {
674 TxError("TileStore: Unable to mmap ANON SEGMENT\n");
675 _exit(1);
676 }
677 _block_end = (void *) ((unsigned long) _block_begin + map_len);
678 _current_ptr = _block_begin;
679 return 0;
680 }
681
682 Tile *
getTileFromTileStore()683 getTileFromTileStore()
684 {
685 Tile *_return_tile = NULL;
686
687 if (!_block_begin && !_block_end)
688 {
689 mmapTileStore();
690 }
691
692 /* Check if we can get the tile from the
693 * Free list
694 */
695
696 if (TileStoreFreeList)
697 {
698 _return_tile = TileStoreFreeList;
699 TileStoreFreeList = (Tile *)TileStoreFreeList->ti_client;
700 return _return_tile;
701 }
702
703 /* Get it from the mmap */
704
705 if (((unsigned long)_current_ptr + sizeof(Tile))
706 > (unsigned long)_block_end)
707 {
708 mmapTileStore();
709 }
710 _current_ptr = (void *)((unsigned long)_current_ptr + sizeof(Tile));
711
712 if ((unsigned long)_current_ptr > (unsigned long) _block_end)
713 {
714 fprintf(stderr,"TileStore: internal assertion failure...");
715 _exit(1);
716 }
717 return (Tile *)((unsigned long)_current_ptr - sizeof(Tile));
718 }
719
720 static void
TileStoreFree(ptr)721 TileStoreFree(ptr)
722 Tile *ptr;
723 {
724 if (!TileStoreFreeList_end || !TileStoreFreeList)
725 {
726 TileStoreFreeList_end = ptr;
727 ptr->ti_client = (unsigned long)0;
728 TileStoreFreeList = TileStoreFreeList_end;
729 }
730 else
731 {
732 TileStoreFreeList_end->ti_client = (unsigned long)ptr;
733 TileStoreFreeList_end = ptr;
734 TileStoreFreeList_end->ti_client = (unsigned long) 0;
735 }
736 }
737
738 Tile *
TiAlloc()739 TiAlloc()
740 {
741 Tile *newtile;
742
743 newtile = getTileFromTileStore();
744 TiSetClient(newtile, CLIENTDEFAULT);
745 TiSetBody(newtile, 0);
746 return (newtile);
747 }
748
749 void
TiFree(tp)750 TiFree(tp)
751 Tile *tp;
752 {
753 TileStoreFree(tp);
754 }
755
756 #else
757
758 /*
759 * --------------------------------------------------------------------
760 *
761 * TiAlloc ---
762 *
763 * Memory allocation for tiles
764 *
765 * Results:
766 * Pointer to an initialized memory location for a tile.
767 *
768 * --------------------------------------------------------------------
769 */
770
771 Tile *
TiAlloc()772 TiAlloc()
773 {
774 Tile *newtile;
775
776 newtile = (Tile *) mallocMagic((unsigned) (sizeof (Tile)));
777 TiSetClient(newtile, CLIENTDEFAULT);
778 TiSetBody(newtile, 0);
779 return (newtile);
780 }
781
782 /*
783 * --------------------------------------------------------------------
784 *
785 * TiFree ---
786 *
787 * Release memory allocation for tiles
788 *
789 * Results:
790 * None.
791 *
792 * --------------------------------------------------------------------
793 */
794
795 void
TiFree(tp)796 TiFree(tp)
797 Tile *tp;
798 {
799 freeMagic((char *)tp);
800 }
801
802 #endif /* !HAVE_SYS_MMAN_H */
803
804 /* ==================================================================== */
805 /* */
806 /* DEBUGGING PROCEDURES */
807 /* */
808 /* ==================================================================== */
809
810 void
tiPrint(tp)811 tiPrint(tp)
812 Tile *tp;
813 {
814 printf("tp=%p LL=(%d,%d) body=0x%"DLONG_PREFIX"x\n",
815 tp, LEFT(tp), BOTTOM(tp), (dlong) tp->ti_body);
816 printf("BL=%p LB=%p RT=%p TR=%p\n", BL(tp), LB(tp), RT(tp), TR(tp));
817 }
818
819 void
tiPrintAll(tp)820 tiPrintAll(tp)
821 Tile *tp;
822 {
823 tiPrint(tp);
824 printf("UR=(%d,%d)\n", RIGHT(tp), TOP(tp));
825
826 /* The following is for plowing debugging */
827 printf("LEAD=%d\n", (int) tp->ti_client);
828 }
829