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