diff -rcN xconq-7.2.1/ChangeLog xconq-7.2.2/ChangeLog
*** xconq-7.2.1/ChangeLog	Tue May 26 20:19:28 1998
--- xconq-7.2.2/ChangeLog	Tue Jun 30 21:30:29 1998
***************
*** 1,3 ****
--- 1,23 ----
+ Tue Jun 30 20:48:20 1998  Stan Shebs  <shebs@andros.cygnus.com>
+ 
+ 	* Version 7.2.2 released.
+ 
+ 	* NEWS, README, xconq.spec, version.h: Bump to 7.2.2.
+ 
+ 	* xinit.c (init_unit_images): Always use silhouettes.
+ 	(init_terrain_images): Pick up solid colors correctly.
+ 
+ 	From Hans Ronne (Note extra diffs from 7.2.1, due to
+ 	other development source divergences):
+ 	* maccolors.c: Bugfix for colorschemes on m68k Macs.
+ 	* macimf.c: Heap fragmentation fix.
+ 	* macmenus.c: World map crash fix.
+ 
+ 	From Dan Croyle <croyle@gelemna.ft-wayne.in.us>:
+ 	* config.host (*-*-freebsd*): New configuration.
+ 	* config/mh-freebsd: New file.
+ 	* SelFile/Dir.c, SelFile/SelFile.c: Add FreeBSD ifdefs.
+ 	
  Tue May 26 20:05:52 1998  Stan Shebs  <shebs@andros.cygnus.com>
  
  	* Version 7.2.1 released.
diff -rcN xconq-7.2.1/NEWS xconq-7.2.2/NEWS
*** xconq-7.2.1/NEWS	Thu May 21 19:27:24 1998
--- xconq-7.2.2/NEWS	Tue Jun 30 21:35:41 1998
***************
*** 1,5 ****
--- 1,13 ----
  XCONQ RELEASE NOTES
  
+ *** 7.2.2
+ 
+ Many bug fixes in the Mac version.
+ 
+ Panner drawing fix in the X11 version.
+ 
+ Added FreeBSD configuration.
+ 
  *** 7.2.1
  
  All image scaling and default image generation now happens in
diff -rcN xconq-7.2.1/README xconq-7.2.2/README
*** xconq-7.2.1/README	Thu May 21 19:37:34 1998
--- xconq-7.2.2/README	Tue Jun 30 20:59:25 1998
***************
*** 1,4 ****
! This is the source directory for version 7.2.1 of Xconq, a graphical
  multi-player strategy game and game design system.  This distribution
  includes interfaces for X11, curses, and Macintosh(tm).
  
--- 1,4 ----
! This is the source directory for version 7.2.2 of Xconq, a graphical
  multi-player strategy game and game design system.  This distribution
  includes interfaces for X11, curses, and Macintosh(tm).
  
diff -rcN xconq-7.2.1/SelFile/Dir.c xconq-7.2.2/SelFile/Dir.c
*** xconq-7.2.1/SelFile/Dir.c	Mon May 18 19:36:06 1998
--- xconq-7.2.2/SelFile/Dir.c	Tue Jun 30 21:27:12 1998
***************
*** 33,39 ****
  #include "SFinternal.h"
  
  #if defined(SVR4) || defined(SYSV) || defined(USG) || defined(__alpha__)      \
!  || defined(__CYGWIN32__)
  #include <dirent.h>
  #else /* defined(SVR4) || defined(SYSV) || defined(USG) ... */
  #include <sys/dir.h>
--- 33,39 ----
  #include "SFinternal.h"
  
  #if defined(SVR4) || defined(SYSV) || defined(USG) || defined(__alpha__)      \
!  || defined(__CYGWIN32__) || defined(__FreeBSD__)
  #include <dirent.h>
  #else /* defined(SVR4) || defined(SYSV) || defined(USG) ... */
  #include <sys/dir.h>
diff -rcN xconq-7.2.1/SelFile/SelFile.c xconq-7.2.2/SelFile/SelFile.c
*** xconq-7.2.1/SelFile/SelFile.c	Thu Mar 26 19:46:51 1998
--- xconq-7.2.2/SelFile/SelFile.c	Tue Jun 30 21:27:39 1998
***************
*** 44,50 ****
  #include <stdio.h>
  #include <errno.h>
  
! #ifndef __GLIBC__
  /* BSD 4.3 errno.h does not declare errno */
  extern int errno;
  extern int sys_nerr;
--- 44,50 ----
  #include <stdio.h>
  #include <errno.h>
  
! #if !defined(__GLIBC__) && !defined(__FreeBSD__)
  /* BSD 4.3 errno.h does not declare errno */
  extern int errno;
  extern int sys_nerr;
diff -rcN xconq-7.2.1/config/mh-freebsd xconq-7.2.2/config/mh-freebsd
*** xconq-7.2.1/config/mh-freebsd	Wed Dec 31 16:00:00 1969
--- xconq-7.2.2/config/mh-freebsd	Tue Jun 30 21:28:35 1998
***************
*** 0 ****
--- 1,4 ----
+ X11_INCLUDE_FLAGS =	-I/usr/X11R6/include
+ X11_LIB_FLAGS =		-L/usr/X11R6/lib
+ 
+ appdefaultsdir = 	/usr/X11R6/lib/X11/app-defaults	
diff -rcN xconq-7.2.1/config.host xconq-7.2.2/config.host
*** xconq-7.2.1/config.host	Mon Jan 12 19:33:31 1998
--- xconq-7.2.2/config.host	Tue Jun 30 21:27:39 1998
***************
*** 39,44 ****
--- 39,45 ----
    *-*-lynxos*)	  	  host_makefile_frag=config/mh-lynxos ;;
    *-*-sysv4*)             host_makefile_frag=config/mh-sysv4 ;;
    *-*-sysv*)              host_makefile_frag=config/mh-sysv ;;
+   *-*-freebsd*)           host_makefile_frag=config/mh-freebsd ;;
  esac
  
  if [ x$host_makefile_frag != x ] ; then
diff -rcN xconq-7.2.1/kernel/version.h xconq-7.2.2/kernel/version.h
*** xconq-7.2.1/kernel/version.h	Thu May 21 19:34:42 1998
--- xconq-7.2.2/kernel/version.h	Tue Jun 30 21:01:09 1998
***************
*** 1,3 ****
! #define VERSION "7.2.1 (May 1998)"
  
  #define COPYRIGHT "Copyright 1986-1998 Stanley T. Shebs"
--- 1,3 ----
! #define VERSION "7.2.2 (June 1998)"
  
  #define COPYRIGHT "Copyright 1986-1998 Stanley T. Shebs"
diff -rcN xconq-7.2.1/mac/maccolors.c xconq-7.2.2/mac/maccolors.c
*** xconq-7.2.1/mac/maccolors.c	Sun May 17 22:55:57 1998
--- xconq-7.2.2/mac/maccolors.c	Mon Jun  1 14:29:31 1998
***************
*** 41,47 ****
  int default_draw_topunit = TRUE;	/* Draw unit info boxes in maps */
  int default_drawothermaps = TRUE;	/* Draw other maps as boxes */
  int default_erase_names = FALSE;	/* Draw extra rows to erase name of moving unit */
! int default_max_bufx = 400;			/* Horizontal scrolling buffers in offscreen graphics */
  int default_max_bufy = 400;			/* Vertical scrolling buffers in offscreen graphics */
  int default_optimize_fonts = TRUE;	/* Use optimized font sizes in map content */
  int default_power = 5;				/* Default power of new map */
--- 41,47 ----
  int default_draw_topunit = TRUE;	/* Draw unit info boxes in maps */
  int default_drawothermaps = TRUE;	/* Draw other maps as boxes */
  int default_erase_names = FALSE;	/* Draw extra rows to erase name of moving unit */
! int default_max_bufx = 600;			/* Horizontal scrolling buffers in offscreen graphics */
  int default_max_bufy = 400;			/* Vertical scrolling buffers in offscreen graphics */
  int default_optimize_fonts = TRUE;	/* Use optimized font sizes in map content */
  int default_power = 5;				/* Default power of new map */
***************
*** 67,73 ****
  RGBColor *sideColor;				/* sideColor[0-15][1-3] are defined by default color schemes */
  									/* sideColor[][0] is not defined, and available for future use */
  
! char **colorscheme;					/* Color schemes by name (red,pink,brown) etc */
  char **default_featColorName;		/* Default feature colors by name (black etc) */
  char **default_colorscheme;			/* Default color schemes (red,pink,brown) etc */
  
--- 67,82 ----
  RGBColor *sideColor;				/* sideColor[0-15][1-3] are defined by default color schemes */
  									/* sideColor[][0] is not defined, and available for future use */
  
! // --- 68K COLORSCHEME BUG FIX -----------------------------------------------------
! 
! extern char **current_colorscheme = 0;		/* Current color schemes by names (red,pink,blue) */
! 									/* Unlike side->colorscheme defined also for null sides */	
! 									/* Declared extern for use in macwins.c */
! 
! //	char **colorscheme; 			/* Color schemes by name (red,pink,brown) etc */
! 
! // ----------------------------------------------------------------------------
! 
  char **default_featColorName;		/* Default feature colors by name (black etc) */
  char **default_colorscheme;			/* Default color schemes (red,pink,brown) etc */
  
***************
*** 93,104 ****
  	default_featColorName = (char **) xmalloc((FEATURES+1) * sizeof(char *));
  	sideColor = (RGBColor *) xmalloc((MAXSIDES+1) * 4 * sizeof(RGBColor));
  	sideColorName = (char **) xmalloc((MAXSIDES+1) * 4 * sizeof(char *));
! 	colorscheme = (char **) xmalloc((MAXSIDES+1) * sizeof(char *));
  	default_colorscheme = (char **) xmalloc((MAXSIDES+1) * sizeof(char *));
! 	for (i = 0; i <= MAXSIDES; i++) {
! 		side_n(i)->colorscheme = (char *) xmalloc(96);
! 		strcpy(side_n(i)->colorscheme,  "");
! 	}
  	main_icon_color = (int *) xmalloc((MAXSIDES+1) * sizeof(int));
  	half_icon_color = (int *) xmalloc((MAXSIDES+1) * sizeof(int));
  	icon_mask_color = (int *) xmalloc((MAXSIDES+1) * sizeof(int));
--- 102,123 ----
  	default_featColorName = (char **) xmalloc((FEATURES+1) * sizeof(char *));
  	sideColor = (RGBColor *) xmalloc((MAXSIDES+1) * 4 * sizeof(RGBColor));
  	sideColorName = (char **) xmalloc((MAXSIDES+1) * 4 * sizeof(char *));
! 
! // --- 68K COLORSCHEME BUG FIX ----------------------------------------------------
! 
! 	current_colorscheme = (char **) xmalloc((MAXSIDES+1) * sizeof(char *)); 
! 
! //	colorscheme = (char **) xmalloc((MAXSIDES+1) * sizeof(char *)); 
! 
  	default_colorscheme = (char **) xmalloc((MAXSIDES+1) * sizeof(char *));
! 
! //	for (i = 0; i <= MAXSIDES; i++) {
! //		side_n(i)->colorscheme = (char *) xmalloc(96);
! //		strcpy(side_n(i)->colorscheme,  "");
! //	}
! 
! // ----------------------------------------------------------------------------
! 
  	main_icon_color = (int *) xmalloc((MAXSIDES+1) * sizeof(int));
  	half_icon_color = (int *) xmalloc((MAXSIDES+1) * sizeof(int));
  	icon_mask_color = (int *) xmalloc((MAXSIDES+1) * sizeof(int));
***************
*** 127,133 ****
  	default_featColorName[3] = "midnight-blue";	/* Text color */
  	default_featColorName[4] = "dark-gray";			/* Grid color */
  	default_featColorName[5] = "black";			/* Unseen color */
! 	default_featColorName[6] = "dark-gray";			/* Shorelines */
  	default_featColorName[7] = "deep-pink";		/* Feature text and borders */
  	default_featColorName[8] = "red";			/* Frontlines */
  	default_featColorName[9] = "midnight-blue";	/* Meridians */
--- 146,160 ----
  	default_featColorName[3] = "midnight-blue";	/* Text color */
  	default_featColorName[4] = "dark-gray";			/* Grid color */
  	default_featColorName[5] = "black";			/* Unseen color */
! 
! // --- DONT USE SAME DEFAULT COLORS FOR SHORELINES AND GRID ------------------------
! 
! 	default_featColorName[6] = "blue"; 		/* Shorelines */   // "mountains-3" also looks OK!
! 
! //	default_featColorName[6] = "dark-gray";	/* Shorelines */
! 
! // ---------------------------------------------------------------------
! 
  	default_featColorName[7] = "deep-pink";		/* Feature text and borders */
  	default_featColorName[8] = "red";			/* Frontlines */
  	default_featColorName[9] = "midnight-blue";	/* Meridians */
***************
*** 149,159 ****
  set_default_side_colors(int e)
  {
  	/* First reset current colors to default colors */
! 	strcpy( side_n(e)->colorscheme, default_colorscheme[e]);
  	/* Change the current colors */
  	set_side_colors(e);
  	/* Copy the result back to default colors */
  	default_colorscheme[e] = side_n(e)->colorscheme;
  	force_overall_update();
  	save_preferences();
  }
--- 176,202 ----
  set_default_side_colors(int e)
  {
  	/* First reset current colors to default colors */
! 
! // --- 68K COLORSCHEME BUG FIX ----------------------------------------------------
! 
! 	side_n(e)->colorscheme = default_colorscheme[e];
! 
! //	strcpy( side_n(e)->colorscheme, default_colorscheme[e]);
! 
! // ----------------------------------------------------------------------------
! 
  	/* Change the current colors */
  	set_side_colors(e);
  	/* Copy the result back to default colors */
+ 
+ // --- 68K COLORSCHEME BUG FIX ----------------------------------------------------
+ 
  	default_colorscheme[e] = side_n(e)->colorscheme;
+ 
+ //	strcpy(default_colorscheme[e], side_n(e)->colorscheme);
+ 
+ // ---------------------------------------------------------------------------
+ 
  	force_overall_update();
  	save_preferences();
  }
***************
*** 189,203 ****
  			set_sideColorName(i, 2, "undefined");
  			set_sideColorName(i, 3, "undefined");
  
! 			/* First load the default colorschemes */
! 			colorscheme[i] = default_colorscheme[i];
  
! 			/* Then overwrite them with schemes from game file */
! 			if (strcmp(side_n(i)->colorscheme, "") != 0) {
! 				colorscheme[i] = side_n(i)->colorscheme;
! 			}
! 			/* Dissect scheme into colors and color names */
! 			dissect_colorscheme(i, colorscheme[i]);
  
  		}
  
--- 232,257 ----
  			set_sideColorName(i, 2, "undefined");
  			set_sideColorName(i, 3, "undefined");
  
! // --- 68K COLORSCHEME BUG FIX ----------------------------------------------------
  
! 			/* Use schemes defined in game file if present or else default schemes */
! 			if (side_n(i) && side_n(i)->colorscheme)
! 				current_colorscheme[i] = copy_string(side_n(i)->colorscheme);
! 			else	current_colorscheme[i] = copy_string(default_colorscheme[i]);
! 				
! 			dissect_colorscheme(i);
! 
! //			/* First load the default colorschemes */
! //			colorscheme[i] = default_colorscheme[i];
! 
! //			/* Then overwrite them with schemes from game file */
! //			if (strcmp(side_n(i)->colorscheme, "") != 0) {
! //				colorscheme[i] = side_n(i)->colorscheme;
! //			}
! //			/* Dissect scheme into colors and color names */
! //			dissect_colorscheme(i, colorscheme[i]);
! 
! // ----------------------------------------------------------------------------
  
  		}
  
***************
*** 224,237 ****
  		featColorName[i] = default_featColorName[i];
  		featColor[i] = get_color(featColorName[i]);
  	}
  }
  
  /* This function is based on init_emblem from the X11 interface. */
  /* It also tests each name for validity and stores it in an array. */
  
  void
! dissect_colorscheme(int sidenum, char* colorscheme)
  {
  	char	 	*s, *c;
  	char		cbuf[BUFSIZE];
  	int 		i, button;
--- 278,310 ----
  		featColorName[i] = default_featColorName[i];
  		featColor[i] = get_color(featColorName[i]);
  	}
+ 
+ // --- MOVED HERE FROM INIT_TERRAIN_IMAGES -----------------------------------------
+ 
+ 	if (strcmp(gridcolor_name, unseencolor_name) == 0
+ 	    && empty_string(g_unseen_image_name()))
+ 		  grid_matches_unseen = TRUE;
+ 	blackcolor.red = blackcolor.green = blackcolor.blue = 0;
+ 
+ // ---------------------------------------------------------------------------
+ 
  }
  
  /* This function is based on init_emblem from the X11 interface. */
  /* It also tests each name for validity and stores it in an array. */
  
+ // --- 68K COLORSCHEME BUG FIX ----------------------------------------------------
+ 
  void
! dissect_colorscheme(int sidenum)
! 
! //	dissect_colorscheme(int sidenum, char* colorscheme)
! 
  {
+ 	char		*colorscheme = current_colorscheme[sidenum];
+ 	
+ // ----------------------------------------------------------------------------
+ 
  	char	 	*s, *c;
  	char		cbuf[BUFSIZE];
  	int 		i, button;
diff -rcN xconq-7.2.1/mac/macconq.c xconq-7.2.2/mac/macconq.c
*** xconq-7.2.1/mac/macconq.c	Thu May 14 22:43:08 1998
--- xconq-7.2.2/mac/macconq.c	Fri May 29 17:34:27 1998
***************
*** 277,282 ****
--- 277,294 ----
  init_toolbox()
  {
  	SysEnvRec se;
+ 	
+ // --- 68K DEFAULT STACK SIZE INCREASE ---------------------------
+ 
+ #if  __MC68K__
+ 
+ 	/* Increase stack size from default 24K (ColorQD) to 64K by adding 40K. */
+ 
+ 	SetApplLimit(GetApplLimit() - 40960);
+ 	
+ #endif
+ 
+ // --------------------------------------------------------	
  
  	MaxApplZone();
  
diff -rcN xconq-7.2.1/mac/macconq.h xconq-7.2.2/mac/macconq.h
*** xconq-7.2.1/mac/macconq.h	Sun May 17 22:58:40 1998
--- xconq-7.2.2/mac/macconq.h	Mon May 25 19:07:53 1998
***************
*** 743,751 ****
  extern void draw_related_maps(Map *map);
  extern void draw_other_map(Map *map, Map *map2);
  extern void draw_row(Map *map, int x0, int y0, int len, int clearit);
! extern int cell_update(Map *map, int x, int y);
! extern void draw_terrain_row(Map *map, int x0, int y0, int len);
! extern void draw_legend(Map *map, int x, int y);
  
  extern void draw_selections(Map *map);
  extern void draw_selections_at(Map *map, int x, int y);
--- 743,759 ----
  extern void draw_related_maps(Map *map);
  extern void draw_other_map(Map *map, Map *map2);
  extern void draw_row(Map *map, int x0, int y0, int len, int clearit);
! 
! // --- MOVED TO MACROW.C -----------------------------
! 
! //	extern int cell_update(Map *map, int x, int y);
! //	extern void draw_terrain_row(Map *map, int x0, int y0, int len);
! 
! // --- NO LONGER USED --------------------------------
! 
! //	extern void draw_legend(Map *map, int x, int y);
! 
! // ------------------------------------------------
  
  extern void draw_selections(Map *map);
  extern void draw_selections_at(Map *map, int x, int y);
***************
*** 1126,1133 ****
  extern void init_emblem_cicns(void);			/* Intitialize cicns ny a dummy PlotCIcon call */
  extern void dispose_unit_cicns(void);			/* Trash every unit cicn in use */
  extern void dispose_emblem_cicns(void);		/* Trash every emblem cicn in use */
! extern void dissect_colorscheme(int sidenum, 	/* Dissect a colorscheme into sideColorNames */
! 		 char* colorscheme);				
  
  /* Functions in maccmd.c now declared here for use elsewhere */
  
--- 1134,1148 ----
  extern void init_emblem_cicns(void);			/* Intitialize cicns ny a dummy PlotCIcon call */
  extern void dispose_unit_cicns(void);			/* Trash every unit cicn in use */
  extern void dispose_emblem_cicns(void);		/* Trash every emblem cicn in use */
! 
! // --- 68K COLORSCHEME BUG FIX -----------------------------------------------
! 
! extern void dissect_colorscheme(int e);	 	/* Dissect a colorscheme into sideColorNames */
! 
! //  extern void dissect_colorscheme(int sidenum, 	/* Dissect a colorscheme into sideColorNames */
! //		 char* colorscheme);				
! 
! // -----------------------------------------------------------------------
  
  /* Functions in maccmd.c now declared here for use elsewhere */
  
diff -rcN xconq-7.2.1/mac/macdraw.c xconq-7.2.2/mac/macdraw.c
*** xconq-7.2.1/mac/macdraw.c	Sun May 17 08:55:31 1998
--- xconq-7.2.2/mac/macdraw.c	Sun May 24 14:41:35 1998
***************
*** 658,663 ****
--- 658,766 ----
  	}
  }
  
+ // --- MOVED HERE FROM MACMAP.C ---------------------------------
+ 
+ /* Given a magnification power, compute the clipping regions to be used at
+    that power. */
+ 
+ void
+ make_cell_clip(int power)
+ {
+ 	int hw = hws[power], hh = hhs[power], delt = (hhs[power] - hcs[power]);
+ 	PolyHandle poly;
+ 	RgnHandle tmprgn;
+ 
+ 	/* Make a hexagon region by drawing a polygon and then framing it while
+ 	   a region is open. */
+ 	poly = OpenPoly();
+ 	MoveTo(hw / 2, 0);
+ 	LineTo(hw, delt);
+ 	LineTo(hw, hh - delt);
+ 	LineTo(hw / 2, hh);
+ 	LineTo(0, hh - delt);
+ 	LineTo(0, delt);
+ 	LineTo(hw / 2, 0);
+ 	ClosePoly();
+ 	cellrgns[power] = NewRgn();
+ 	OpenRgn();
+ 	FramePoly(poly);
+ 	CloseRgn(cellrgns[power]);
+ 	/* Make the grid-displaying version of the hexagon. */
+ 	gridcellrgns[power] = NewRgn();
+ 	CopyRgn(cellrgns[power], gridcellrgns[power]);
+ 	/* Cut off a one-pixel line on the side. */
+ 	tmprgn = NewRgn();
+ 	SetRectRgn(tmprgn, hw - 1, 0, hw + 1, hh); 
+ 	DiffRgn(gridcellrgns[power], tmprgn, gridcellrgns[power]);
+ 	/* Now intersect with a region shifted upwards by one, which makes
+ 	   the grid line along the bottom of the hex. */
+ 	tmprgn = NewRgn();
+ 	CopyRgn(cellrgns[power], tmprgn);
+ 	OffsetRgn(tmprgn, 0, -1);
+ 	SectRgn(gridcellrgns[power], tmprgn, gridcellrgns[power]);
+ 
+ 	/* Similarly, but for cells at an angle. */
+ 	/* (should only calc when angle view first requested) */
+ 	/* First make a region as viewed at a 30-degree angle. */
+ 	hh /= 2;  delt /= 2;
+ 	poly = OpenPoly();
+ 	MoveTo(hw / 2, 0);
+ 	LineTo(hw, delt);
+ 	LineTo(hw, hh - delt);
+ 	LineTo(hw / 2, hh);
+ 	LineTo(0, hh - delt);
+ 	LineTo(0, delt);
+ 	LineTo(hw / 2, 0);
+ 	ClosePoly();
+ 	cellrgns30[power] = NewRgn();
+ 	OpenRgn();
+ 	FramePoly(poly);
+ 	CloseRgn(cellrgns30[power]);
+ 	gridcellrgns30[power] = NewRgn();
+ 	CopyRgn(cellrgns30[power], gridcellrgns30[power]);
+ 	/* Cut off a one-pixel line on the side. */
+ 	tmprgn = NewRgn();
+ 	SetRectRgn(tmprgn, hw - 1, 0, hw + 1, hh/2); 
+ 	DiffRgn(gridcellrgns30[power], tmprgn, gridcellrgns30[power]);
+ 	/* Now intersect with a region shifted upwards by one, which makes
+ 	   the grid line along the bottom of the hex. */
+ 	tmprgn = NewRgn();
+ 	CopyRgn(cellrgns30[power], tmprgn);
+ 	OffsetRgn(tmprgn, 0, -1);
+ 	SectRgn(gridcellrgns30[power], tmprgn, gridcellrgns30[power]);
+ 
+ 	/* Now make a region as viewed at a 15-degree angle. */
+ 	hh = hhs[power] / 4;
+ 	delt = (hhs[power] - hcs[power]) / 4;
+ 	poly = OpenPoly();
+ 	MoveTo(hw / 2, 0);
+ 	LineTo(hw, delt);
+ 	LineTo(hw, hh - delt);
+ 	LineTo(hw / 2, hh);
+ 	LineTo(0, hh - delt);
+ 	LineTo(0, delt);
+ 	LineTo(hw / 2, 0);
+ 	ClosePoly();
+ 	cellrgns15[power] = NewRgn();
+ 	OpenRgn();
+ 	FramePoly(poly);
+ 	CloseRgn(cellrgns15[power]);
+ 	gridcellrgns15[power] = NewRgn();
+ 	CopyRgn(cellrgns15[power], gridcellrgns15[power]);
+ 	/* Cut off a one-pixel line on the side. */
+ 	tmprgn = NewRgn();
+ 	SetRectRgn(tmprgn, hw - 1, 0, hw + 1, hh/2); 
+ 	DiffRgn(gridcellrgns15[power], tmprgn, gridcellrgns15[power]);
+ 	/* Now intersect with a region shifted upwards by one, which makes
+ 	   the grid line along the bottom of the hex. */
+ 	tmprgn = NewRgn();
+ 	CopyRgn(cellrgns15[power], tmprgn);
+ 	OffsetRgn(tmprgn, 0, -1);
+ 	SectRgn(gridcellrgns15[power], tmprgn, gridcellrgns15[power]);
+ }
+ 
+ // --------------------------------------------------------------
+ 
  /* Draw a set of borders for the given position. */
  
  void
***************
*** 728,733 ****
--- 831,844 ----
  		}
  	}
  	for_all_directions(dir) {
+ 
+ // --- SPEEDS UP DRAWING & PREVENTS DOUBLE LINES AT CLIFF TOP & BOTTOM BUG ----------
+ 
+ 		if (dir == EAST || dir == SOUTHWEST || dir == SOUTHEAST)
+ 			continue;
+ 
+ // ----------------------------------------------------------------------
+ 
  		if (bitmask & (1 << dir)) {
  			/* Actually draw the line. */
  			sx1 = bsx[power][dir];  sy1 = bsy[power][dir];
***************
*** 756,761 ****
--- 867,880 ----
  			PenMode(notPatOr);
  		}
  		for_all_directions(dir) {
+ 
+ // --- SPEEDS UP DRAWING & PREVENTS DOUBLE LINES AT CLIFF TOP & BOTTOM BUG ----------
+ 
+ 			if (dir == EAST || dir == SOUTHWEST || dir == SOUTHEAST)
+ 				continue;
+ 
+ // ----------------------------------------------------------------------
+ 
  			if (bitmask & (1 << dir)) {
  				/* Actually draw the line. */
  				sx1 = bsx[power][dir];  sy1 = bsy[power][dir];
diff -rcN xconq-7.2.1/mac/macgworld.c xconq-7.2.2/mac/macgworld.c
*** xconq-7.2.1/mac/macgworld.c	Sat May 16 14:44:33 1998
--- xconq-7.2.2/mac/macgworld.c	Sun May 24 12:27:42 1998
***************
*** 13,23 ****
  /* Needed for changing screen depths and handling the control strip */
  
  #include <Palettes.h>
  #ifdef CONTROL_STRIP
  #include <ControlStrip.h>
! /* Apple control strip routine descriptors */
! #include "applestuff.h"
! #endif
  
  // --- USED TO DEBUG OFFSCREEN GRAPHICS ----------------------------------------
  
--- 13,77 ----
  /* Needed for changing screen depths and handling the control strip */
  
  #include <Palettes.h>
+ 
  #ifdef CONTROL_STRIP
+ 
+ // --- NEW STUFF MOVED HERE FROM APPLESTUFF.H ------------------
+ 
+ /*	Apple control strip routine descriptors follow below. */
+ /*	Must be included in PPC projects that use the control strip. *
+ /*	See http://devworld.apple.com/dev/qa/ops/ops15.html. */
+ 
+ #if GENERATINGCFM
+ 
+ /* If we're not generating CFM, then assume the
+    68K inlines in the headers apply instead. */
+ 
+ #include <MixedMode.h>
+ #include <OSUtils.h>
+ pascal Boolean SBIsControlStripVisible ( void );
+ pascal void SBShowHideControlStrip(Boolean showIt);
+ 
+ /*  SBIsControlStripVisible is a Pascal routine, */
+ /*  dispatched from the selector in D0, returning */
+ /*  a Boolean result */
+ pascal Boolean SBIsControlStripVisible ( void )
+ {
+     enum
+         {
+         uppSBIsControlStripVisibleInfo = kD0DispatchedPascalStackBased
+             | RESULT_SIZE (SIZE_CODE (sizeof(Boolean)))
+             | DISPATCHED_STACK_ROUTINE_SELECTOR_SIZE (kFourByteCode)
+             };
+ 
+             return CallUniversalProc (
+             GetToolTrapAddress (_ControlStripDispatch),
+             uppSBIsControlStripVisibleInfo, 0x00);
+ }
+ 
+ pascal void SBShowHideControlStrip(Boolean showIt)
+ {
+     enum
+         {
+         uppSBShowHideControlStripInfo =
+             kD0DispatchedPascalStackBased
+             | DISPATCHED_STACK_ROUTINE_SELECTOR_SIZE (kFourByteCode)
+             | DISPATCHED_STACK_ROUTINE_PARAMETER
+                 (1, SIZE_CODE (sizeof (showIt)))
+             };
+ 
+             CallUniversalProc (
+             GetToolTrapAddress (_ControlStripDispatch),
+             uppSBShowHideControlStripInfo, 0x01, showIt);
+ }
+ 
+ #else   /*  not GENERATINGCFM */
  #include <ControlStrip.h>
! #endif /*  GENERATINGCFM */
! 
! // --- END NEW STUFF -------------------------------------------------------
! 
! #endif /* CONTROL_STRIP */
  
  // --- USED TO DEBUG OFFSCREEN GRAPHICS ----------------------------------------
  
diff -rcN xconq-7.2.1/mac/macimf.c xconq-7.2.2/mac/macimf.c
*** xconq-7.2.1/mac/macimf.c	Thu May 21 00:08:17 1998
--- xconq-7.2.2/mac/macimf.c	Mon Jun  1 07:37:15 1998
***************
*** 266,275 ****
  			/* Mask is built in, don't need to load separately. */
  		}
  	}
! 	/* We want to unlock the cicn now, and lock it high later on;
! 	   but not if it was already processed. */
! 	if (newcicn)
! 	  HUnlock((Handle) cicnhandle);
  }
  
  void
--- 266,290 ----
  			/* Mask is built in, don't need to load separately. */
  		}
  	}
! 
! // --- HEAP FRAGMENTATION FIX -----------------------------------------
! 
! 	/* Always unlock this handle or the heap will be messed up beyond all recognition!
! 	Moreover, if get_mac_image returns an already loaded cicn, the new cicnhandle is 
! 	never used, as macimg->colricon still points to the old cicnhandle at the top of the 
! 	heap. The new cicnhandle should therefore not only be unlocked but also trashed. */	
! 
! 	HUnlock((Handle) cicnhandle);
! 	if (!newcicn)
! 		DisposeCIcon(cicnhandle);
! 
! //	/* We want to unlock the cicn now, and lock it high later on;
! //	   but not if it was already processed. */
! //	if (newcicn)
! //	  HUnlock((Handle) cicnhandle);
! 	
! // --------------------------------------------------------------
! 
  }
  
  void
diff -rcN xconq-7.2.1/mac/macinit.c xconq-7.2.2/mac/macinit.c
*** xconq-7.2.1/mac/macinit.c	Sun May 17 12:54:15 1998
--- xconq-7.2.2/mac/macinit.c	Mon Jun  1 14:06:40 1998
***************
*** 2113,2125 ****
  	}
  	/* Set up the images we'll be needing. */
  	init_terrain_images();
! 	init_unit_images();
! 	init_side_colors();
  	/* Trial side/player assignment, will create the default player if nececessary. */
  	make_trial_assignments();
  	/* Get the emblems so they can be displayed in the player dialog. */
  	init_all_emblem_images();
  	init_emblem_cicns();
  	/* Ask for modifications to the trial assignment. */
  	return player_setup_dialog();
  }
--- 2113,2141 ----
  	}
  	/* Set up the images we'll be needing. */
  	init_terrain_images();
! 
! // --- HEAP FRAGMENTATION FIX -------------------------------------
! 
! //	init_unit_images();		/* Moved below. */
! 
! // -----------------------------------------------------------
! 
! 	init_side_colors();		
  	/* Trial side/player assignment, will create the default player if nececessary. */
  	make_trial_assignments();
  	/* Get the emblems so they can be displayed in the player dialog. */
  	init_all_emblem_images();
  	init_emblem_cicns();
+ 
+ // --- HEAP FRAGMENTATION FIX -------------------------------------
+ 
+ 	/* It is important that unit cicns are loaded after the emblems since functions
+ 	that reinit cicns assume that emblems always are located above the unit cicns. */
+ 	
+ 	init_unit_images();
+ 
+ // -----------------------------------------------------------
+ 
  	/* Ask for modifications to the trial assignment. */
  	return player_setup_dialog();
  }
***************
*** 2526,2535 ****
  	Image *timg;
  	MacImage *mactimg;
  
! 	if (strcmp(gridcolor_name, unseencolor_name) == 0
! 	    && empty_string(g_unseen_image_name()))
! 	  grid_matches_unseen = TRUE;
! 	blackcolor.red = blackcolor.green = blackcolor.blue = 0;
  
  	timages = (ImageFamily **) xmalloc(numttypes * sizeof(ImageFamily *));
  
--- 2542,2555 ----
  	Image *timg;
  	MacImage *mactimg;
  
! // --- MOVED TO INIT_SIDE_COLORS -------------------------------------------------
! 
! //	if (strcmp(gridcolor_name, unseencolor_name) == 0
! //	    && empty_string(g_unseen_image_name()))
! //	  grid_matches_unseen = TRUE;
! //	blackcolor.red = blackcolor.green = blackcolor.blue = 0;
! 
! // --------------------------------------------------------------------------
  
  	timages = (ImageFamily **) xmalloc(numttypes * sizeof(ImageFamily *));
  
***************
*** 2607,2617 ****
--- 2627,2662 ----
  reinit_all_emblem_images()
  {
  	dispose_emblem_cicns();
+ 
+ // --- HEAP FRAGMENTATION FIX -----------------------------------
+ 
+ 	/* The emblem cicns are locked in place above the unit cicns, which are
+ 	also locked. To reinit the emblem cicns in their correct position we must 
+ 	therefore first dispose of the unit cicns and then reinit them after we are
+ 	done with the emblem cicns. */
+ 
+ 	/* Also free the emblem images. */
+ 	free(eimages);
+ 
+ 	/* Dispose of and free unit images. */
+ 	dispose_unit_cicns();
+ 	free(uimages);
+ 
+ // ----------------------------------------------------------
+ 
  	/* This isn't great, because all the collected data goes away, and we have to
  	   reread and reallocate everything.  It would be smarter just to reinit the
  	   Mac-specific parts alone. */
  	init_all_emblem_images();
  	init_emblem_cicns();
+ 
+ // --- HEAP FRAGMENTATION FIX -----------------------------------
+ 
+ 	/* Finally load the unit cicns again below the new emblems. */
+ 	init_unit_images();
+ 
+ // ----------------------------------------------------------
+ 
  }
  
  /* Set up the emblems for a particular side.  This is used both to do all sides
***************
*** 2644,2649 ****
--- 2689,2710 ----
  				mac_init_cicn(img);
  			}
  		}
+ 
+ // --- HEAP FRAGMENTATION FIX ---------------------------------
+ 
+ 		/* The purpose of these dummy calls is to avoid later calls to
+ 		mac_init_cicn during the game which will mess up the heap. 
+ 		In particular, calls to best_image during offscreen drawing 
+ 		will put locked cicn handles all over the heap, since the gworld 
+ 		pixmap is locked in place at drawing time. */
+ 
+ 		/* Trigger add_shrunken_image once and for all. */
+ 		img = best_image(uimages[u], 1, 1);
+ 		/* Trigger add_magnified_image once and for all. */
+ 		img = best_image(uimages[u], 128, 128);
+ 
+ // -------------------------------------------------------
+ 
  	}
  }
  
***************
*** 2688,2693 ****
--- 2749,2770 ----
  				mac_init_cicn(img);
  			}
  		}
+ 
+ // --- HEAP FRAGMENTATION FIX ---------------------------------
+ 
+ 		/* The purpose of these dummy calls is to avoid later calls to
+ 		mac_init_cicn during the game which will mess up the heap. 
+ 		In particular, calls to best_image during offscreen drawing 
+ 		will put locked cicn handles all over the heap, since the gworld 
+ 		pixmap is locked in place at drawing time. */
+ 
+ 		/* Trigger add_shrunken_image once and for all. */
+ 		img = best_image(eimages[side_number(side)], 1, 1);
+ 		/* Trigger add_magnified_image once and for all. */
+ 		img = best_image(eimages[side_number(side)], 128, 128);
+ 
+ // -------------------------------------------------------
+ 
  	}
  }
  
***************
*** 2711,2716 ****
--- 2788,2800 ----
  					DisposHandle((Handle) (*cicnhandle)->iconData);
  					DisposHandle((Handle) cicnhandle);
  					macimg->colricon = nil;
+ 
+ // --- HEAP FRAGMENTATION FIX -------------------------------------------
+ 
+ 					macimg->cicn_inited = FALSE;
+ 
+ // -----------------------------------------------------------------
+ 
  				}
  			}
  		}
diff -rcN xconq-7.2.1/mac/macmap.c xconq-7.2.2/mac/macmap.c
*** xconq-7.2.1/mac/macmap.c	Mon May 18 00:00:16 1998
--- xconq-7.2.2/mac/macmap.c	Mon Jun  1 15:55:35 1998
***************
*** 1,4 ****
--- 1,16 ----
  /* Map graphics for the Mac interface to Xconq.
+ 
+     Now contains:	1. Coordinate transforming and calculating functions.
+ 			2. Map creating, destroying and modifying functions.
+ 			3. draw_map and all the functions it calls.
+ 			4. draw_other_maps & draw_related_maps.
+ 			5. draw_unit_blast & erase_unit_blast.
+ 			6. draw_selections, erase_selections etc.
+ 			7. update_cell_display.
+ 
+    draw_row and all functions that it calls are now in the separate source macrow.c.
+    All mouse-driven user interaction code is in macmouse.c (formerly macmap2.c).
+ 
     Copyright (C) 1992-1998 Stanley T. Shebs.
  
  Xconq is free software; you can redistribute it and/or modify
***************
*** 7,34 ****
  any later version.  See the file COPYING.  */
  
  #include "conq.h"
- extern int any_thickness;
  #include "macconq.h"
  extern void xform_fractional(Map *map, int x, int y, int xf, int yf, int *sxp, int *syp);
  
! extern int contour_interval;
  
! #define GENERIC_MERIDIANS
  
! static void draw_meridians(Map *map);
! static void draw_borders(Map *map, int x, int y, int b);
! static void draw_connections(Map *map, int x, int y, int c);
! static void draw_units(Map *map, int x, int y);
! static void draw_unit_and_occs(Map *map, Unit *unit, int sx, int sy, int sw, int sh);
! static void draw_people_row(Map *map, int x0, int y0, int len);
! static void draw_feature_boundary(Map *map, int x, int y);
! static void draw_materials(Map *map, int x, int y);
! static void draw_ai_region(Map *map, int x, int y);
! static void draw_info_text(Map *map, int x, int y, int len, char *buf);
! extern void draw_gridlines(Map *map, int x0, int y, int len);
! extern void draw_simple_feature_borders(Map *map, int x0, int y0, int len);
! extern void draw_shorelines(Map *map, int x0, int y0, int len);
! extern void draw_unit_names_only(Map *map, int x, int y);
  
  /* Adjust viewport for offscreen drawing and go offscreen.
     Then call draw_other_maps to erase other-map boxes */
--- 19,52 ----
  any later version.  See the file COPYING.  */
  
  #include "conq.h"
  #include "macconq.h"
+ 
+ static void draw_meridians(Map *map);
+ static void draw_info_text(Map *map, int x, int y, int len, char *buf);
+ static void draw_unit_names_only(Map *map, int x, int y);
+ extern void draw_gridlines(Map *map, int x, int y);
+ extern void draw_shorelines(Map *map, int x, int y);
  extern void xform_fractional(Map *map, int x, int y, int xf, int yf, int *sxp, int *syp);
  
! // --- WORLD MAP CRASH FIX ----------------------------
  
! extern Map *worldmap;		/* Defined in macmenus.c. */
  
! // ------------------------------------------------
! 
! Map *frontmap;
! int conwid = 32;
! int tophgt;
! int mapnum = 1;
! int nummaps = 0;
! int lastmaph = -1;
! int lastmapv = -1;
! int animation_pattern_state;
! char *mouseover = "something";
! 
! /* Handles of the pictures that display all the map control buttons. */
! PicHandle tlcontrols = nil;
! PicHandle blcontrols = nil;
  
  /* Adjust viewport for offscreen drawing and go offscreen.
     Then call draw_other_maps to erase other-map boxes */
***************
*** 53,64 ****
    }
  
  /* These three macros are used to handle cases where an item stretches across the */
! /* edge of a wrapped world. It is then necessary to draw it twice, once at each end. */
  /* The macros should be applied to all drawing functions that take an sx value, rect */
  /* or poly as a parameter. */
  
  /* Repeat (function) once using sx shifted one area width to the right. */
! #define WRAP_SX(map, sx, function) { \
  	(function); \
  	if (area.xwrap && (sx) < 0) { \
  		(sx) += (map)->vp->sxmax; \
--- 71,82 ----
    }
  
  /* These three macros are used to handle cases where an item stretches across the */
! /* edge of a wrapped gworld. It is then necessary to draw it twice, once at each end. */
  /* The macros should be applied to all drawing functions that take an sx value, rect */
  /* or poly as a parameter. */
  
  /* Repeat (function) once using sx shifted one area width to the right. */
! #define UNWRAP_SX(map, sx, function) { \
  	(function); \
  	if (area.xwrap && (sx) < 0) { \
  		(sx) += (map)->vp->sxmax; \
***************
*** 68,74 ****
  }
  
  /* Repeat (function) once using rect offset one area width to the right. */
! #define WRAP_RECT(map, rect, function) { \
  	(function); \
  	if (area.xwrap && (rect).left < 0) { \
  		OffsetRect(&(rect), (map)->vp->sxmax, 0); \
--- 86,92 ----
  }
  
  /* Repeat (function) once using rect offset one area width to the right. */
! #define UNWRAP_RECT(map, rect, function) { \
  	(function); \
  	if (area.xwrap && (rect).left < 0) { \
  		OffsetRect(&(rect), (map)->vp->sxmax, 0); \
***************
*** 78,84 ****
  }
  
  /* Repeat (function) once using poly offset one area width to the right. */
! #define WRAP_POLY(map, poly, function) { \
  	(function); \
  	if (area.xwrap && (*(*(poly))).polyBBox.left < 0) { \
  		OffsetPoly((poly), (map)->vp->sxmax, 0); \
--- 96,102 ----
  }
  
  /* Repeat (function) once using poly offset one area width to the right. */
! #define UNWRAP_POLY(map, poly, function) { \
  	(function); \
  	if (area.xwrap && (*(*(poly))).polyBBox.left < 0) { \
  		OffsetPoly((poly), (map)->vp->sxmax, 0); \
***************
*** 87,148 ****
  	} \
  }
  
! /* For these accessors, x must already be wrapped. */
! 
! #define cell_overlay(x, y)  \
!   ((dside->designer && !map->see_all) \
!    ? ((terrain_view(dside, x, y) == UNSEEN) ? -2 : 0)  \
!    : (tmpdrawlighting  \
!       ? (night_at(x, y)  \
!          ? -2  \
!          : (tmpdrawcoverage ? (cover(dside, x, y) == 0 ? -1 : 0) : 0))  \
!       : (tmpdrawcoverage  \
!           ? (cover(dside, x, y) == 0 ? -1 : 0)  \
!           : 0)))
! 
! #define cell_terrain(map, x, y)  \
!   ((map->see_all || dside->designer) \
!    ? terrain_at(x, y)  \
!    : (terrain_visible(dside, x, y)  \
! 	  ? vterrain(terrain_view(dside, x, y))  \
! 	  : NONTTYPE))
! 
! #define cell_style(map, x, y, power)  \
!   ((map->see_all || terrain_visible(dside, x, y) || unseen_image != NULL)  \
!    ? (power >= 4 ? usepolygons : useblocks)  \
!    : dontdraw);
! 
! static void draw_cliffs(Map *map, int x, int y);
! static void draw_contours(Map *map, int x, int y);
! 
! int tmpdrawlighting;
! 
! int tmpdrawcoverage;
! 
! /* The width of the left-side control panel. */
  
! int conwid = 32;
  
! /* The height of the top line. */
  
! int tophgt;
  
! int mapnum = 1;
  
! int nummaps = 0;
  
! int lastmaph = -1, lastmapv = -1;
  
! /* Handles of the pictures that display all the map control buttons. */
  
! PicHandle tlcontrols = nil;
! PicHandle blcontrols = nil;
  
! char *mouseover = "something";
  
! int animation_pattern_state;
  
! Map *frontmap;
  
  /* This tests whether the given cell might possibly be visible on the given map.
     Not as precise as a real cliprect calculation. */
--- 105,194 ----
  	} \
  }
  
! /* Given a map and a cell, compute the pixel coords of the cell's UL corner.
!    This is the core routine that relates cells and pixels. */
  
! void
! xform(map, x, y, sxp, syp)
! Map *map;
! int x, y, *sxp, *syp;
! {
! 	xform_cell(map->vp, x, y, sxp, syp);
! 	/* Shift the basic viewport result to account for both origin-shift and map decor. */
! 	*sxp += map->osx + map->conw;  *syp += map->osy + map->toph;
! }
  
! void
! xform_fractional(map, x, y, xf, yf, sxp, syp)
! Map *map;
! int x, y, xf, yf, *sxp, *syp;
! {
! 	xform_cell_fractional(map->vp, x, y, xf, yf, sxp, syp);
! 	/* Shift the basic viewport result to account for both origin-shift and map decor. */
! 	*sxp += map->osx + map->conw;  *syp += map->osy + map->toph;
! }
  
! void
! m_xform_unit(map, unit, sxp, syp, swp, shp)
! Map *map;
! Unit *unit;
! int *sxp, *syp, *swp, *shp;
! {
! 	xform_unit(map->vp, unit, sxp, syp, swp, shp);
! 	/* Shift the basic viewport result to account for both origin-shift and map decor. */
! 	*sxp += map->osx + map->conw;  *syp += map->osy + map->toph;
! }
  
! void
! m_xform_unit_self(map, unit, sxp, syp, swp, shp)
! Map *map;
! Unit *unit;
! int *sxp, *syp, *swp, *shp;
! {
! 	xform_unit_self(map->vp, unit, sxp, syp, swp, shp);
! 	/* Shift the basic viewport result to account for both origin-shift and map decor. */
! 	*sxp += map->osx + map->conw;  *syp += map->osy + map->toph;
! }
  
! void
! m_xform_occupant(map, transport, unit, sx, sy, sw, sh, sxp, syp, swp, shp)
! Map *map;
! Unit *transport, *unit;
! int sx, sy, sw, sh, *sxp, *syp, *swp, *shp;
! {
! 	/* Transform the coordinates back to relative values. */
! 	sx -= map->osx + map->conw;  sy -= map->osy + map->toph;
! 	xform_occupant(map->vp, transport, unit, sx, sy, sw, sh, sxp, syp, swp, shp);
! 	/* Shift the basic viewport result to account for both origin-shift and map decor. */
! 	*sxp += map->osx + map->conw;  *syp += map->osy + map->toph;
! }
  
! /* Un-transform screen coordinates (as supplied by mouse perhaps) into
!    map coordinates.  */
  
! /* Note that only drawing is affected by SetOrigin - mouse locations are
!    always window-relative, and thus only need to be adjusted by map decor
!    before going to the generic routines. */
  
! int
! m_nearest_cell(Map *map, int sx, int sy, int *xp, int *yp)
! {
! 	return nearest_cell(map->vp, sx - map->conw, sy - map->toph, xp, yp, NULL, NULL);
! }
  
! /* Find the closest direction of the closest boundary */
  
! int
! m_nearest_boundary(Map *map, int sx, int sy, int *xp, int *yp, int *dirp)
! {
! 	return nearest_boundary(map->vp, sx - map->conw, sy - map->toph, xp, yp, dirp);
! }
  
! int
! m_nearest_unit(Map *map, int sx, int sy, Unit **unitp)
! {
! 	return nearest_unit(map->vp, sx - map->conw, sy - map->toph, unitp);
! }
  
  /* This tests whether the given cell might possibly be visible on the given map.
     Not as precise as a real cliprect calculation. */
***************
*** 161,302 ****
  	return cell_is_in_middle(map->vp, x, y);
  }
  
! /* Draw an individual detailed cell, as a row of one, on all maps. */
! 
! void  
! update_cell_display(Side *side, int x, int y, int rightnow)
  {
! 	int xw, leftcells = 0, cells = 1, name = FALSE, sx1, sy1, i, j;		
! 	Rect destRect;
! 	GrafPtr	oldport;
! 	Unit *unit;
! 	Map *map;
! 
! 	if (!active_display(side))
! 	  return;
! 	xw = wrapx(x);
! 	GetPort(&oldport);
! 	for_all_maps(map) {
! 
! 		/* If update was only to report changes in undrawn info, maybe don't bother. */
! 		if ((rightnow == 34 && !map->vp->draw_temperature) 
! 		    || (rightnow == 37 && !map->vp->draw_clouds)
! 		    || (rightnow == 35 && !map->vp->draw_winds)
! 		    || (rightnow == 36 && !map->vp->draw_cover))
! 		  continue;
! 
! 		/* Dont update cells outside the current gworld */
! 		if (!cell_is_in_gworld(map, x, y))
! 		  continue;
! 
! 		/* Find the max number of cells a unit name can occupy at this mag */
! 		if (map->vp->draw_names) {
! 			switch(map->vp->power) {
! 				case 7: 	cells = 2; break; 	/* 128 x 128 hexes */
! 				case 6: 	cells = 3; break;		/*      64 x 64 hexes */	
! 				case 5: 	cells = 4; break;		/*      32 x 32 hexes */
! 				case 4: 	cells = 4; break;		/*      16 x 16 hexes */
! 				case 3: 	cells = 8; break;		/*         8 x  8  hexes */
! 				default: 	cells = 1; break;
! 			}
! 		}
! 		/* Compute leftcells now in case we skip the erasing row */
! 		leftcells = cells - 1;
! 
! 		/* Skip erasing row if name erasing was not called for */
! 		if (!map->erase_names)
! 		  cells = 1;
! 
! 		/* Check if erasing row really is needed, but only if we have one */
! 		if (cells > 1) {
! 			/* First check if there is a named unit at (x, y)*/
! 			for_all_stack(xw, y, unit) 
! 				name = (unit->name != NULL);
! 			/* Check adjacent hexes. Stop as soon as a named unit is found */
! 			if (!name && inside_area(x, y + 1))
! 				for_all_stack(xw, y + 1, unit) 
! 				  name = (unit->name != NULL);	/* NE hex */
! 			if (!name && inside_area(x - 1, y + 1))	
! 				for_all_stack(wrapx(x - 1), y + 1, unit) 
! 				  name = (unit->name != NULL);	/* NW hex */
! 			if (!name && inside_area(x - 1, y))	
! 				for_all_stack(wrapx(x - 1), y, unit) 
! 				  name = (unit->name != NULL);	/* W hex */
! 			if (!name && inside_area(x + 1, y))	
! 				for_all_stack(wrapx(x + 1), y, unit) 
! 				  name = (unit->name != NULL);	/* E hex */
! 			if (!name && inside_area(x, y - 1))	
! 				for_all_stack(xw, y - 1, unit) 
! 				  name = (unit->name != NULL);	/* SW hex */
! 			if (!name && inside_area(x + 1, y - 1))	
! 				for_all_stack(wrapx(x + 1), y - 1, unit) 
! 				  name = (unit->name != NULL);	/* SE hex */
! 			/* No named units in adjacent hexes. A named unit could not */
! 			/* have left (x, y) in this step, thus we skip the erasing row */
! 			if (!name)
! 			  cells = 1;
! 		}
! 
! 		GO_OFFSCREEN(map);
! 
! 		/* First draw a row of cells starting at (x, y) in order to
! 		   erase the name of any unit that moved out of that cell */
! 		draw_row(map, x, y, cells, TRUE);
! 
! 		/* Re-draw gridlines & shorelines for the (cells + 1) hexes
! 		   below the updated row that were erased by the update */				
! 		if (map->vp->draw_grid &! grid_matches_unseen)
! 		  draw_gridlines(map, x, y - 1, cells + 1);
! 		if (map->shorelines)
! 		  draw_shorelines(map, x, y - 1, cells + 1);
! 
! 		/* Re-draw any named units in the (leftcells) hexes to the */
! 		/* left of (x, y) whose names were erased by the update */
! 		/* Note: this is done even if erase_names is not set! */
! 		if (map->vp->draw_names) {
! 			for (i = x - leftcells; i <  x; i++) {
! 				for_all_stack(wrapx(i), y, unit) {
! 					if (unit->name)	{							
! 						draw_unit_names_only(map, i, y);
! 						break;
! 					}
! 				}
! 			}
! 		}					
! 
! 		/* Re-draw any selected units within the updated row */
! 		for (i = 0; i < map->numselections; ++i) {
! 			unit = map->selections[i];
! 			for (j = 0; j < cells; j++) {
! 				if (unit && unit->x ==  wrapx(x + j) && unit->y == y) {
! 					draw_selected_unit(map, unit);
! 				}						
! 			}
! 		}
! 
! 		RETURN_ONSCREEN(map);
! 
! 		/* Find the pixel coordinates of (x, y) */
! 		xform(map, x, y, &sx1, &sy1);
! 
! 		/* Set destRect to enclose the redrawn row of cells */
! 		SetRect(&destRect, 
! 				sx1 - 2, sy1 - 2,			/* Add 2 for W & N shorelines */ 	
! 				sx1 + cells * map->vp->hw, 
! 				sy1 + map->vp->hh + 4);		/* Add 4 for SE & SW shorelines */
  
! 		/* Now copy offscreen rect to window */
! 		copy_from_gworld(map, destRect);			
  
! 		/* Update unit info line */
! 		if (map->numselections > 0) {
! 			unit = map->selections[0];
! 			if (in_play(unit) && unit->x == xw && unit->y == y) {
! 				draw_unit_info(map);
! 			}
! 		}
! 	}
! 	SetPort(oldport);
  }
  
  /* Create a new map window and all its paraphernalia. */
--- 207,225 ----
  	return cell_is_in_middle(map->vp, x, y);
  }
  
! void
! m_focus_on_center(Map *map)
  {
! 	focus_on_center(map->vp);
! }
  
! /* Put vcx,vcy in the middle of the map. */
  
! void
! m_center_on_focus(Map *map)
! {
! 	center_on_focus(map->vp);
! 	set_content_rect(map);
  }
  
  /* Create a new map window and all its paraphernalia. */
***************
*** 465,491 ****
  				  map->contentrect.bottom - map->contentrect.top);
  }
  
  void
! m_focus_on_center(Map *map)
! {
! 	focus_on_center(map->vp);
! }
! 
! /* Put vcx,vcy in the middle of the map. */
! 
! void
! m_center_on_focus(Map *map)
! {
! 	center_on_focus(map->vp);
! 	set_content_rect(map);
! }
! 
! /* Adjust the appearance and thumb of the scroll bars to reflect the map.  This is
!    needed whenever the map is adjusted under program control, such as when magnifying
!    or scrolling to a specified location. */
! 
! void
! set_map_scrollbars(Map *map)
  {
  	int hilite;
  	
--- 388,399 ----
  				  map->contentrect.bottom - map->contentrect.top);
  }
  
+ /* Adjust the appearance and thumb of the scroll bars to reflect the map.  This is
+    needed whenever the map is adjusted under program control, such as when magnifying
+    or scrolling to a specified location. */
+ 
  void
! set_map_scrollbars(Map *map)
  {
  	int hilite;
  	
***************
*** 557,677 ****
  	  make_cell_clip(power);
  }
  
- /* Given a magnification power, compute the clipping regions to be used at
-    that power. */
- 
- void
- make_cell_clip(int power)
- {
- 	int hw = hws[power], hh = hhs[power], delt = (hhs[power] - hcs[power]);
- 	PolyHandle poly;
- 	RgnHandle tmprgn;
- 
- 	/* Make a hexagon region by drawing a polygon and then framing it while
- 	   a region is open. */
- 	poly = OpenPoly();
- 	MoveTo(hw / 2, 0);
- 	LineTo(hw, delt);
- 	LineTo(hw, hh - delt);
- 	LineTo(hw / 2, hh);
- 	LineTo(0, hh - delt);
- 	LineTo(0, delt);
- 	LineTo(hw / 2, 0);
- 	ClosePoly();
- 	cellrgns[power] = NewRgn();
- 	OpenRgn();
- 	FramePoly(poly);
- 	CloseRgn(cellrgns[power]);
- 	/* Make the grid-displaying version of the hexagon. */
- 	gridcellrgns[power] = NewRgn();
- 	CopyRgn(cellrgns[power], gridcellrgns[power]);
- 	/* Cut off a one-pixel line on the side. */
- 	tmprgn = NewRgn();
- 	SetRectRgn(tmprgn, hw - 1, 0, hw + 1, hh); 
- 	DiffRgn(gridcellrgns[power], tmprgn, gridcellrgns[power]);
- 	/* Now intersect with a region shifted upwards by one, which makes
- 	   the grid line along the bottom of the hex. */
- 	tmprgn = NewRgn();
- 	CopyRgn(cellrgns[power], tmprgn);
- 	OffsetRgn(tmprgn, 0, -1);
- 	SectRgn(gridcellrgns[power], tmprgn, gridcellrgns[power]);
- 
- 	/* Similarly, but for cells at an angle. */
- 	/* (should only calc when angle view first requested) */
- 	/* First make a region as viewed at a 30-degree angle. */
- 	hh /= 2;  delt /= 2;
- 	poly = OpenPoly();
- 	MoveTo(hw / 2, 0);
- 	LineTo(hw, delt);
- 	LineTo(hw, hh - delt);
- 	LineTo(hw / 2, hh);
- 	LineTo(0, hh - delt);
- 	LineTo(0, delt);
- 	LineTo(hw / 2, 0);
- 	ClosePoly();
- 	cellrgns30[power] = NewRgn();
- 	OpenRgn();
- 	FramePoly(poly);
- 	CloseRgn(cellrgns30[power]);
- 	gridcellrgns30[power] = NewRgn();
- 	CopyRgn(cellrgns30[power], gridcellrgns30[power]);
- 	/* Cut off a one-pixel line on the side. */
- 	tmprgn = NewRgn();
- 	SetRectRgn(tmprgn, hw - 1, 0, hw + 1, hh/2); 
- 	DiffRgn(gridcellrgns30[power], tmprgn, gridcellrgns30[power]);
- 	/* Now intersect with a region shifted upwards by one, which makes
- 	   the grid line along the bottom of the hex. */
- 	tmprgn = NewRgn();
- 	CopyRgn(cellrgns30[power], tmprgn);
- 	OffsetRgn(tmprgn, 0, -1);
- 	SectRgn(gridcellrgns30[power], tmprgn, gridcellrgns30[power]);
- 
- 	/* Now make a region as viewed at a 15-degree angle. */
- 	hh = hhs[power] / 4;
- 	delt = (hhs[power] - hcs[power]) / 4;
- 	poly = OpenPoly();
- 	MoveTo(hw / 2, 0);
- 	LineTo(hw, delt);
- 	LineTo(hw, hh - delt);
- 	LineTo(hw / 2, hh);
- 	LineTo(0, hh - delt);
- 	LineTo(0, delt);
- 	LineTo(hw / 2, 0);
- 	ClosePoly();
- 	cellrgns15[power] = NewRgn();
- 	OpenRgn();
- 	FramePoly(poly);
- 	CloseRgn(cellrgns15[power]);
- 	gridcellrgns15[power] = NewRgn();
- 	CopyRgn(cellrgns15[power], gridcellrgns15[power]);
- 	/* Cut off a one-pixel line on the side. */
- 	tmprgn = NewRgn();
- 	SetRectRgn(tmprgn, hw - 1, 0, hw + 1, hh/2); 
- 	DiffRgn(gridcellrgns15[power], tmprgn, gridcellrgns15[power]);
- 	/* Now intersect with a region shifted upwards by one, which makes
- 	   the grid line along the bottom of the hex. */
- 	tmprgn = NewRgn();
- 	CopyRgn(cellrgns15[power], tmprgn);
- 	OffsetRgn(tmprgn, 0, -1);
- 	SectRgn(gridcellrgns15[power], tmprgn, gridcellrgns15[power]);
- }
- 
- /* Given a window, find the map that it belongs to. */
- 
- Map *
- map_from_window(WindowPtr window)
- {
- 	Map *map;
- 	
- 	if (dside == NULL)
- 	  return NULL;
- 	for_all_maps(map) {
- 		if (map->window == window)
- 		  return map;
- 	}
- 	return NULL;
- }
- 
  void
  grow_map(Map *map, int w, int h)	/* Manual resizing by dragging the corner */
  {
--- 465,470 ----
***************
*** 754,842 ****
  	SizeControl(map->vscrollbar, sbarwid + 1, h - sbarwid + 1 + 1);
  }
  
- /* Given a map and a cell, compute the pixel coords of the cell's UL corner.
-    This is the core routine that relates cells and pixels. */
- 
  void
! xform(map, x, y, sxp, syp)
! Map *map;
! int x, y, *sxp, *syp;
  {
! 	xform_cell(map->vp, x, y, sxp, syp);
! 	/* Shift the basic viewport result to account for both origin-shift and map decor. */
! 	*sxp += map->osx + map->conw;  *syp += map->osy + map->toph;
  }
  
  void
! xform_fractional(map, x, y, xf, yf, sxp, syp)
  Map *map;
! int x, y, xf, yf, *sxp, *syp;
  {
! 	xform_cell_fractional(map->vp, x, y, xf, yf, sxp, syp);
! 	/* Shift the basic viewport result to account for both origin-shift and map decor. */
! 	*sxp += map->osx + map->conw;  *syp += map->osy + map->toph;
  }
  
  void
! m_xform_unit(map, unit, sxp, syp, swp, shp)
  Map *map;
- Unit *unit;
- int *sxp, *syp, *swp, *shp;
  {
! 	xform_unit(map->vp, unit, sxp, syp, swp, shp);
! 	/* Shift the basic viewport result to account for both origin-shift and map decor. */
! 	*sxp += map->osx + map->conw;  *syp += map->osy + map->toph;
  }
  
  void
! m_xform_unit_self(map, unit, sxp, syp, swp, shp)
  Map *map;
- Unit *unit;
- int *sxp, *syp, *swp, *shp;
  {
! 	xform_unit_self(map->vp, unit, sxp, syp, swp, shp);
! 	/* Shift the basic viewport result to account for both origin-shift and map decor. */
! 	*sxp += map->osx + map->conw;  *syp += map->osy + map->toph;
  }
  
  void
! m_xform_occupant(map, transport, unit, sx, sy, sw, sh, sxp, syp, swp, shp)
  Map *map;
- Unit *transport, *unit;
- int sx, sy, sw, sh, *sxp, *syp, *swp, *shp;
  {
! 	/* Transform the coordinates back to relative values. */
! 	sx -= map->osx + map->conw;  sy -= map->osy + map->toph;
! 	xform_occupant(map->vp, transport, unit, sx, sy, sw, sh, sxp, syp, swp, shp);
! 	/* Shift the basic viewport result to account for both origin-shift and map decor. */
! 	*sxp += map->osx + map->conw;  *syp += map->osy + map->toph;
! }
  
! /* Un-transform screen coordinates (as supplied by mouse perhaps) into
!    map coordinates.  */
  
! /* Note that only drawing is affected by SetOrigin - mouse locations are
!    always window-relative, and thus only need to be adjusted by map decor
!    before going to the generic routines. */
  
! int
! m_nearest_cell(Map *map, int sx, int sy, int *xp, int *yp)
! {
! 	return nearest_cell(map->vp, sx - map->conw, sy - map->toph, xp, yp, NULL, NULL);
! }
  
! /* Find the closest direction of the closest boundary */
  
! int
! m_nearest_boundary(Map *map, int sx, int sy, int *xp, int *yp, int *dirp)
! {
! 	return nearest_boundary(map->vp, sx - map->conw, sy - map->toph, xp, yp, dirp);
! }
  
! int
! m_nearest_unit(Map *map, int sx, int sy, Unit **unitp)
! {
! 	return nearest_unit(map->vp, sx - map->conw, sy - map->toph, unitp);
  }
  
  /* Display a map and all of its paraphernalia. */
--- 547,714 ----
  	SizeControl(map->vscrollbar, sbarwid + 1, h - sbarwid + 1 + 1);
  }
  
  void
! invert_map(Map *map, int x, int y, int r)
  {
! 	int sx, sy, sw, sh;
! 	Rect tmprect;
! 	GrafPtr	oldport;
! 	
! 	GetPort(&oldport);
! 
! 	GO_OFFSCREEN(map);
! 
! 	xform(map, x, y, &sx, &sy);
! 	SetRect(&tmprect, sx - (r * map->vp->hw) / 2, 
! 					  sy - (r * map->vp->hch) / 2,
! 					  sx + (r * map->vp->hw) / 2, 
! 					  sy + (r * map->vp->hch) / 2);
! 
! 	InvertRect(&tmprect);
! 
! 	RETURN_ONSCREEN(map);
! 
! 	/* Copy tmprect to the screen */
! 	copy_from_gworld(map, tmprect);
! 
! 	SetPort(oldport);
  }
  
  void
! activate_map(map, activate)
  Map *map;
! int activate;
  {
! 	Rect growRect;
! 
! 	if (activate) {
! 		HiliteControl(map->vscrollbar, 0);
! 		HiliteControl(map->hscrollbar, 0);
! 		/* Controls need to be redrawn on activation. */
! 		(*(map->vscrollbar))->contrlVis = 255;
! 		(*(map->hscrollbar))->contrlVis = 255;
! 		InvalRect(&(*(map->vscrollbar))->contrlRect);
! 		InvalRect(&(*(map->hscrollbar))->contrlRect);
! 		/* The growbox needs to be redrawn on activation. */
! 		growRect = map->window->portRect;
! 		/* adjust for the scrollbars */
! 		growRect.top = growRect.bottom - sbarwid;
! 		growRect.left = growRect.right - sbarwid;
! 		InvalRect(&growRect);
! 		/* Remember this as the map most recently in front, even if it moves behind
! 		   later. */
! 		frontmap = map;
! 	} else {
! 		/* The scrollbars must be deactivated. */
! 		HiliteControl(map->vscrollbar, 255);
! 		HiliteControl(map->hscrollbar, 255);
! #if 0  /* We don't want to hide them though, because the window bg is not white. */
! 		HideControl(map->vscrollbar);
! 		HideControl(map->hscrollbar);
! #endif
! 		/* The growbox should be changed immediately on deactivation. */
! 		DrawGrowIcon(map->window);
! 	}
! }
! 
! /* Given a window, find the map that it belongs to. */
! 
! Map *
! map_from_window(WindowPtr window)
! {
! 	Map *map;
! 	
! 	if (dside == NULL)
! 	  return NULL;
! 	for_all_maps(map) {
! 		if (map->window == window)
! 		  return map;
! 	}
! 	return NULL;
! }
! 
! /* Return the frontmost map, whether or not it's the frontmost window. */
! 
! Map *
! front_map()
! {
! 	Map *map;
! 
! 	map = map_from_window(FrontWindow());
! 	if (map != NULL)
! 	  return map;
! 	if (frontmap != NULL)
! 	  return frontmap;
! 	return NULL;
  }
  
  void
! force_map_update(map)
  Map *map;
  {
! 	force_update(map->window);
  }
  
  void
! print_map(map)
  Map *map;
  {
! 	/* (should send postscript output from ps.c to printer port) */
  }
  
+ /* Remove and destroy the map object. */
+ 
  void
! destroy_map(map)
  Map *map;
  {
! 	Map *map2;
  
! 	/* Disconnect it from the list. */	
! 	if (maplist == map) {
! 		maplist = map->next;
! 	} else {
! 		for_all_maps(map2) {
! 			if (map2->next == map) {
! 				map2->next = map->next;
! 			}
! 			/* Clean up the map and window numbers. */
! 			if (map2->id > map->id) {
! 				remove_window_menu_item(map2->window);
! 				--map2->id;
! 				sprintf(spbuf, "Map %d", map2->id);
! 				add_window_menu_item(spbuf, map2->window);
! 			}
! 		}
! 	}
! 	if (frontmap == map)
! 	  frontmap = NULL;
! 	free_vp(map->vp);
! 	free(map->selections);
  
! // --- WORLD MAP CRASH FIX -----------------------------
  
! 	/* Sigh. Since nothing else seems to work, we try this. */
! 	if (worldmap == map)
! 	  worldmap = NULL;		      /* Heureka, it works! */
  
! // -------------------------------------------------
  
! 	/* Part of number clean-up */
! 	--mapnum; --nummaps;
  
! 	/* Trash the gworld */
! 	DisposeGWorld(map->gworldPortPtr);
! 	
! 	/* This is NOT done by close_windows! */
! 	DisposeWindow(map->window);
! 
! 	/* Erase other-map boxes in other windows */
! 	draw_related_maps(map);
! 
! 	/* Necessary to indicate somehow that the map no longer exists! */
! 	map->id = 0;
! 	free(map);
  }
  
  /* Display a map and all of its paraphernalia. */
***************
*** 1013,1103 ****
  	  draw_meridians(map);
  }
  
! /* This draws a hexagon or rectangle that covers the totality of the area, whether
!    discovered or not. */
  
! void 
! draw_area_background(Map *map)
  {
! 	int sx, sy, llx, lly, lrx, lry, rx, ry, urx, ury, ulx, uly, lx, ly;
! 	PolyHandle poly;
! 	Rect arearect;
  
! 	/* Don't bother if area magnified greatly. */
! 	/* (should fix to not try to draw giant rects, but still draw something reasonable.
! 	   note that otherwise grid color may be wrong) */
! /*
! 	LineTo uses shorts and does not work over 32K, so a giant hex cannot be drawn.
! 	If the area.wrap option is used instead with a large map, xform will freak out!
! 	The grid/unseen color for large maps is therfore drawn as window background
! 	instead (see draw_window_background).
! */
! 	if (area.width * map->vp->hw > 32000)
! 	  return;
  	if (area.xwrap) {
! 		/* Area is cylinder; draw a rectangle. */
! 		xform(map, 0, area.height-1, &sx, &sy);
! 		/* Make sure the whole gworld gets a background. */
! 	 	arearect.left = map->gworldPortPtr->portRect.left;
!         arearect.top = sy;
! 		xform(map, 0, 0, &sx, &sy);
!  		/* Make sure the whole gworld gets a background. */
! 		arearect.right = map->gworldPortPtr->portRect.right;
! 		arearect.bottom = sy;
! 		/* If there's scrolling, then draw background under the extra scrolling
! 		   area. */
! 		if (map->vp->sxmin != map->vp->sxmax)
! 		  arearect.right += map->vp->pxw;
! 		/* Adjust so that edges of the rect pass through the middles of top/bottom edge cells. */
! 		OffsetRect(&arearect, 0, map->vp->hh / 2);
! 		if (hasColorQD) {
! 			/* If everything is visible, use gridcolor for background. */
! 			if (g_terrain_seen() || (dside)->see_all) {
! 				RGBForeColor(&gridcolor);
! 				grid_matches_unseen = TRUE;
! 			} else {
! 				RGBForeColor(&unseencolor);
! 			}
! 			PaintRect(&arearect);
! 			RGBForeColor(&blackcolor);
! 		} else {
! 			/* Try to use gray patterns if b/w. */
! 			switch (gridgray) {
! 				case blackgray:
! 					FillRect(&arearect, QDPat(black));
! 					break;
! 				case darkgray:
! 					FillRect(&arearect, QDPat(dkGray));
! 					break;
! 				case mediumgray:
! 					FillRect(&arearect, QDPat(gray));
! 					break;
! 				case lightgray:
! 					FillRect(&arearect, QDPat(ltGray));
! 					break;
! 				case whitegray:
! 					FillRect(&arearect, QDPat(white));
! 					break;
! 			}
! 		}
  	} else {
! 		/* Area is hexagon; draw a hexagon. */
! 		/* (should make once and save?) */
! 		poly = OpenPoly();		
! 		xform(map, 0 + area.halfheight, 0, &llx, &lly);
! 		MoveTo(llx, lly);
! 		xform(map, area.width-1, 0, &lrx, &lry);
! 	 	LineTo(lrx, lry);
! 		xform(map, area.width-1, area.halfheight, &rx, &ry);
! 		LineTo(rx, ry);
!  		xform(map, area.width-1 - area.halfheight, area.height-1, &urx, &ury);
! 		LineTo(urx, ury);
!  		xform(map, 0, area.height-1, &ulx, &uly);
! 		LineTo(ulx, uly);
!  		xform(map, 0, area.halfheight, &lx, &ly);
! 		LineTo(lx, ly);
! 		LineTo(llx, lly);
! 		ClosePoly();
  		/* Adjust so that edges of the polygon pass through the middles of edge cells. */
  		OffsetPoly(poly, map->vp->hw/2, map->vp->hh/2);
  		if (hasColorQD) {
--- 885,1201 ----
  	  draw_meridians(map);
  }
  
! // --- NEW FUNCTION - REPLACES IFFED OUT STUFF BELOW ---------------------------
  
! #if 1
! 
! void
! draw_meridians(Map *map)
  {
! 	int latmin, latcen, latmax, lonmin, loncen, lonmax, lat, lon; 
! 	int xfmin, xfmax, yfmin, yfmax, xmin, ymin, xmax, ymax;
! 	int right, left, top, bottom, xend, ymid, incr, interval;
!     	int latdeg, latmit, londeg, lonmit;
! 	int x, y, xf, yf, sx, sx1, sy;
! 	Rect portrect, drawrect;
!     	char mitbuf[4];
  
! 	/* Set origin to Greenwich x equator in wrapped worlds. */
  	if (area.xwrap) {
! 		loncen = latcen = 0;
! 	/* Else set origin to area center. */
  	} else {
! 		loncen = 60 * area.longitude;
! 		latcen = 60 * area.latitude;
! 	}
! 
! 	/* Compute the interval in pixels. */
!     	incr = map->vp->latlong_interval;
!     	latlong_to_xy(latcen, loncen, &xmin, 0, &xfmin, 0);
!     	latlong_to_xy(latcen, loncen + incr, &xmax, 0, &xfmax, 0);
! 	/* Skip if next meridian is outside the area. */
! 	if (!in_area(xmax, 0)) return;
! 	xform_fractional(map, xmin, 0, xfmin, 0, &sx, 0);
! 	xform_fractional(map, xmax, 0, xfmax, 0, &sx1, 0);
! 	interval = abs(sx1 - sx);
! 	/* Skip if interval is too small. */
! 	if (interval < 16) return;
! 		
! 	/* Set up the drawing rect. */
! 	drawrect = portrect = map->gworldPortPtr->portRect;
! 	drawrect.right = min(portrect.right, map->vp->totsw);
! 	drawrect.bottom = min(portrect.bottom, map->vp->totsh);
! 	/* A hack for better positioning of the text. */	
! 	drawrect.top += map->vp->hh/4; 
! 	drawrect.bottom -= map->vp->hh/8; 
! 	
! 	/* Compute min/max values for latitudes and longitudes. */
! 	nearest_cell(map->vp, -map->conw, drawrect.bottom - map->toph, 
! 			    &xmin, &ymin, &xfmin, &yfmin);
! 	nearest_cell(map->vp, drawrect.right - map->conw, -map->toph, 
! 			    &xmax, &ymax, &xfmax, &yfmax);
! 	xy_to_latlong(xmin, ymin, xfmin, yfmin, &latmin, &lonmin);
! 	xy_to_latlong(xmax, ymax, xfmax, yfmax, &latmax, &lonmax);
! 
! 	/* Center the grid on the origin. */
! 	lonmin += (loncen - lonmin) % incr;
! 	lonmax += (loncen - lonmax) % incr;
! 	latmin += (latcen - latmin) % incr;
! 	latmax += (latcen - latmax) % incr;
! 
! 	/* Special fixes for wrapped gworlds etc.*/
! 	if (lonmin > 0 || lonmax < 0 || lonmax <= lonmin) {
! 		lonmin = -10800; 
! 		lonmax = 10800 - incr;
! 	}
! 	
! 	/* Used in clipping code. */
! 	ymid = area.halfheight;
! 	xend = area.width - 1;
! 
! 	/* Set meridian color. */
! 	RGBForeColor(&meridiancolor);
! 	
! 	/* Draw the latitiudes. */
! 	for (lat = latmin; lat <= latmax; lat += incr) {
! 		left = drawrect.left; 
! 		right = drawrect.right;
! 		latlong_to_xy(lat, loncen, &x, &y, &xf, &yf);
! 		/* Skip if outside area. */
! 		if (!in_area(x, y)) continue;
! 		xform_fractional(map, x, y, xf, yf, &sx, &sy);
! 		/* Don't draw latitudes where the longitude text will be. */
! 		if (sy - drawrect.top < 16 || drawrect.bottom - sy < 16) continue;
! 		/* Clip corners to area for non-wrapped worlds. */
! 		if (!area.xwrap) {
! 			/* Compute left endpoint. */
! 			if (in_area(0,y)) { 							
! 				 xform(map, 0, y, &left, 0);
! 				 left += 32;
! 			} else if (in_area(ymid - y, y)) {					
! 				 xform(map, ymid - y, y, &left, 0);
! 				 left += 32;
! 			}
! 			/* Compute right endpoint. */
! 			if (in_area(xend + ymid - y, y)) {				
! 				 xform(map, xend + ymid - y, y, &right, 0);
! 				 right -= 32 - map->vp->hw;
! 			} else if (in_area(xend, y)) {					
! 				 xform(map, xend, y, &right, 0);
! 				 right -= 32 - map->vp->hw;
! 			}
! 			/* Make room for text at left end. */
! 			left = max(left, portrect.left + 32);
! 			/* Make room for text at right end. */
! 			right = min(right, portrect.right - 32);
! 		} else { 
! 			/* Make room for text at right end unless the gworld is wrapped. */
! 			if (map->vp->sxmax > portrect.right - portrect.left) right -= 32;
! 			/* Always make room at left end. */
! 			left += 32; 
! 		}
! 		MoveTo(left, sy);
! 		LineTo(right, sy);
! 		latdeg = abs(lat) / 60;
! 		latmit = abs(lat) % 60;
! 		mitbuf[0] = '\0';
! 		if (latmit != 0) sprintf(mitbuf, "%d«", latmit);
! 		sprintf(tmpbuf, "%d¡%s", latdeg, mitbuf);
! 		if (lat >= 0) strcat(tmpbuf, "N");
! 		if (lat < 0) strcat(tmpbuf, "S");
! 		/* Always draw latitude text at left edge. */
! 		draw_legend_text(left - 3, sy, 12, tmpbuf, +1, 0, 0);
! 		/* Also draw text at right edge unless the gworld is wrapped. */
! 		if (!area.xwrap || map->vp->sxmax > portrect.right - portrect.left)
! 			draw_legend_text(right + 3, sy, 12, tmpbuf, -1, 0, 0);
! 	}
! 
! 	/* Draw the longitudes. */
! 	for (lon = lonmin; lon <= lonmax; lon += incr) {
! 		/* Make room for top and bottom text. */
! 		top = drawrect.top + 16; 
! 		bottom = drawrect.bottom - 16;
! 		latlong_to_xy(latcen, lon, &x, &y, &xf, &yf);
! 		/* Skip if outside area. */
! 		if (!in_area(x, y)) continue;
! 		xform_fractional(map, x, y, xf, yf, &sx, &sy);
! 		/* Clip corners to area for non-wrapped maps. */
! 		if (!area.xwrap) {
! 			/* Compute top endpoint. */
! 			if (in_area(0,  ymid + 2 * x))						
! 				 xform(map, 0, ymid + 2 * x, 0, &top);
! 			else if (in_area(2 * x - xend, ymid + 2 * (xend - x)))	
! 				 xform(map, 2 * x - xend, ymid + 2 * (xend - x), 0, &top);
! 			/* Compute bottom endpoint. */
! 			if (in_area(2 * x, ymid - 2 * x))					
! 				 xform(map, 2 * x, ymid - 2 * x, 0, &bottom);	
! 			else if (in_area(xend, ymid - 2 * (xend - x)))				
! 				 xform(map, xend, ymid - 2 * (xend - x), 0, &bottom);
! 		}
! 		/* Wrap sx if necessary. */
! 		if (area.xwrap && sx < 0)
! 			sx += map->vp->sxmax;
! 		else if (area.xwrap && sx > map->vp->sxmax)
! 			sx -= map->vp->sxmax;
! 		MoveTo(sx, top);
! 		LineTo(sx, bottom);
! 		londeg = abs(lon) / 60;
! 		lonmit = abs(lon) % 60;
! 		mitbuf[0] = '\0';
! 		if (lonmit != 0) sprintf(mitbuf, "%d«", lonmit);
! 		sprintf(tmpbuf, "%d¡%s", londeg, mitbuf);
! 		if (lon > 0) strcat(tmpbuf, "E");
! 		if (lon < 0) strcat(tmpbuf, "W");
! 		/* Draw text at top and bottom. */
! 		if (top == drawrect.top + 16)
! 			draw_legend_text(sx, top - 6, 12, tmpbuf, 0, 0, 0);
! 		if (bottom == drawrect.bottom - 16)
! 			draw_legend_text(sx, bottom + 6, 12, tmpbuf, 0, 0, 0);
! 	}
! 
! 	ForeColor(blackColor);
! }
! 
! // --- IFFED OUT STUFF REPLACED BY REWRITTEN FUNCTION ABOVE ---------------------
! 
! #else
! 
! static void meridian_line_callback(int x1, int y1, int x1f, int y1f, int x2, int y2, int x2f, int y2f);
! static void meridian_text_callback(int x1, int y1, int x1f, int y1f, char *str);
! 
! static Map *tmpmap;
! 
! static void
! draw_meridians(Map *map)
! {
! 	Rect portrect = map->gworldPortPtr->portRect;
! 	int real_pxw = map->vp->pxw, real_pxh = map->vp->pxh;
! 	
! 	tmpmap = map;
! 
! 	/* Necessary to fool the kernel into believing that the vp is bigger than it is. */
! 	map->vp->pxw = portrect.right - portrect.left;		
! 	map->vp->pxh = portrect.bottom - portrect.top;		
! 
! 	RGBForeColor(&meridiancolor);
! 
! 	plot_meridians(map->vp, meridian_line_callback, meridian_text_callback);
! 
! 	ForeColor(blackColor);
! 
! 	/* Restore real vp size. */
! 	map->vp->pxw = real_pxw;  map->vp->pxh = real_pxh;
! }
! 
! static void
! meridian_line_callback(int x1, int y1, int x1f, int y1f, int x2, int y2, int x2f, int y2f)
! {
! 	int sx1, sy1, sx2, sy2;
! 
! 	xform_fractional(tmpmap, x1, y1, x1f, y1f, &sx1, &sy1);
! 	xform_fractional(tmpmap, x2, y2, x2f, y2f, &sx2, &sy2);
! 	MoveTo(sx1, sy1);
! 	LineTo(sx2, sy2);
! }
! 
! static void
! meridian_text_callback(int x1, int y1, int x1f, int y1f, char *str)
! {
! 	int sx1, sy1;
! 
! 	xform_fractional(tmpmap, x1, y1, x1f, y1f, &sx1, &sy1);
! 	draw_legend_text(sx1, sy1 - 12, 12, tmpbuf, 0, 0, 0);
! }
! 
! #endif
! 
! // -------------------------------------------------------------
! 
! /* This draws a hexagon or rectangle that covers the totality of the area, whether
!    discovered or not. */
! 
! void 
! draw_area_background(Map *map)
! {
! 	int sx, sy, llx, lly, lrx, lry, rx, ry, urx, ury, ulx, uly, lx, ly;
! 	PolyHandle poly;
! 	Rect arearect;
! 
! 	/* Don't bother if area magnified greatly. */
! 	/* (should fix to not try to draw giant rects, but still draw something reasonable.
! 	   note that otherwise grid color may be wrong) */
! /*
! 	LineTo uses shorts and does not work over 32K, so a giant hex cannot be drawn.
! 	If the area.wrap option is used instead with a large map, xform will freak out!
! 	The grid/unseen color for large maps is therfore drawn as window background
! 	instead (see draw_window_background).
! */
! 	if (area.width * map->vp->hw > 32000)
! 	  return;
! 	if (area.xwrap) {
! 		/* Area is cylinder; draw a rectangle. */
! 		xform(map, 0, area.height-1, &sx, &sy);
! 		/* Make sure the whole gworld gets a background. */
! 	 	arearect.left = map->gworldPortPtr->portRect.left;
!         arearect.top = sy;
! 		xform(map, 0, 0, &sx, &sy);
!  		/* Make sure the whole gworld gets a background. */
! 		arearect.right = map->gworldPortPtr->portRect.right;
! 		arearect.bottom = sy;
! 		/* If there's scrolling, then draw background under the extra scrolling
! 		   area. */
! 		if (map->vp->sxmin != map->vp->sxmax)
! 		  arearect.right += map->vp->pxw;
! 		/* Adjust so that edges of the rect pass through the middles of top/bottom edge cells. */
! 		OffsetRect(&arearect, 0, map->vp->hh / 2);
! 		if (hasColorQD) {
! 			/* If everything is visible, use gridcolor for background. */
! 			if (g_terrain_seen() || (dside)->see_all) {
! 				RGBForeColor(&gridcolor);
! 				grid_matches_unseen = TRUE;
! 			} else {
! 				RGBForeColor(&unseencolor);
! 			}
! 			PaintRect(&arearect);
! 			RGBForeColor(&blackcolor);
! 		} else {
! 			/* Try to use gray patterns if b/w. */
! 			switch (gridgray) {
! 				case blackgray:
! 					FillRect(&arearect, QDPat(black));
! 					break;
! 				case darkgray:
! 					FillRect(&arearect, QDPat(dkGray));
! 					break;
! 				case mediumgray:
! 					FillRect(&arearect, QDPat(gray));
! 					break;
! 				case lightgray:
! 					FillRect(&arearect, QDPat(ltGray));
! 					break;
! 				case whitegray:
! 					FillRect(&arearect, QDPat(white));
! 					break;
! 			}
! 		}
! 	} else {
! 		/* Area is hexagon; draw a hexagon. */
! 		/* (should make once and save?) */
! 		poly = OpenPoly();		
! 		xform(map, 0 + area.halfheight, 0, &llx, &lly);
! 		MoveTo(llx, lly);
! 		xform(map, area.width-1, 0, &lrx, &lry);
! 	 	LineTo(lrx, lry);
! 		xform(map, area.width-1, area.halfheight, &rx, &ry);
! 		LineTo(rx, ry);
!  		xform(map, area.width-1 - area.halfheight, area.height-1, &urx, &ury);
! 		LineTo(urx, ury);
!  		xform(map, 0, area.height-1, &ulx, &uly);
! 		LineTo(ulx, uly);
!  		xform(map, 0, area.halfheight, &lx, &ly);
! 		LineTo(lx, ly);
! 		LineTo(llx, lly);
! 		ClosePoly();
  		/* Adjust so that edges of the polygon pass through the middles of edge cells. */
  		OffsetPoly(poly, map->vp->hw/2, map->vp->hh/2);
  		if (hasColorQD) {
***************
*** 1458,1463 ****
--- 1556,1563 ----
  	  PenSize(2, 2);
  	PenMode(patXor);
  	FrameRect(&tmpRect);
+ 
+ 	/* UNWRAP the box. */
  	if (area.xwrap) {
  		/* Draw one extra copy to the left if necessary. */
  		if (tmpRect.right > map->vp->sxmax) {
***************
*** 1483,2624 ****
  	PenNormal();
  }
  
! #ifdef GENERIC_MERIDIANS
! 
! static void meridian_line_callback(int x1, int y1, int x1f, int y1f, int x2, int y2, int x2f, int y2f);
! static void meridian_text_callback(int x1, int y1, int x1f, int y1f, char *str);
! 
! static Map *tmpmap;
! 
! static void
! draw_meridians(Map *map)
  {
! 	Rect portrect = map->gworldPortPtr->portRect;
! 	int real_pxw = map->vp->pxw, real_pxh = map->vp->pxh;
  	
! 	tmpmap = map;
! 
! 	/* Necessary to fool the kernel into believing that the vp is bigger than it is. */
! 	map->vp->pxw = portrect.right - portrect.left;		
! 	map->vp->pxh = portrect.bottom - portrect.top;		
! 
! 	RGBForeColor(&meridiancolor);
! 
! 	plot_meridians(map->vp, meridian_line_callback, meridian_text_callback);
! 
! 	ForeColor(blackColor);
  
! 	/* Restore real vp size. */
! 	map->vp->pxw = real_pxw;  map->vp->pxh = real_pxh;
! }
  
! static void
! meridian_line_callback(int x1, int y1, int x1f, int y1f, int x2, int y2, int x2f, int y2f)
! {
! 	int sx1, sy1, sx2, sy2;
  
! 	xform_fractional(tmpmap, x1, y1, x1f, y1f, &sx1, &sy1);
! 	xform_fractional(tmpmap, x2, y2, x2f, y2f, &sx2, &sy2);
! 	MoveTo(sx1, sy1);
! 	LineTo(sx2, sy2);
! }
  
! static void
! meridian_text_callback(int x1, int y1, int x1f, int y1f, char *str)
! {
! 	int sx1, sy1;
  
! 	xform_fractional(tmpmap, x1, y1, x1f, y1f, &sx1, &sy1);
! 	draw_legend_text(sx1, sy1 - 12, 12, tmpbuf, 0, 0, 0);
  }
  
- #else
- 
  void
! draw_meridians(Map *map)
  {
! 	int latmin, latcen, latmax, lonmin, loncen, lonmax, lat, lon; 
! 	int xfmin, xfmax, yfmin, yfmax, xmin, ymin, xmax, ymax;
! 	int right, left, top, bottom, xend, ymid, incr, interval;
!     	int latdeg, latmit, londeg, lonmit;
! 	int x, y, xf, yf, sx, sx1, sy;
! 	Rect portrect, drawrect;
!     	char mitbuf[4];
! 
! 	/* Set origin to Greenwich x equator in wrapped worlds. */
! 	if (area.xwrap) {
! 		loncen = latcen = 0;
! 	/* Else set origin to area center. */
! 	} else {
! 		loncen = 60 * area.longitude;
! 		latcen = 60 * area.latitude;
! 	}
! 
! 	/* Compute the interval in pixels. */
!     	incr = map->vp->latlong_interval;
!     	latlong_to_xy(latcen, loncen, &xmin, 0, &xfmin, 0);
!     	latlong_to_xy(latcen, loncen + incr, &xmax, 0, &xfmax, 0);
! 	/* Skip if next meridian is outside the area. */
! 	if (!in_area(xmax, 0)) return;
! 	xform_fractional(map, xmin, 0, xfmin, 0, &sx, 0);
! 	xform_fractional(map, xmax, 0, xfmax, 0, &sx1, 0);
! 	interval = abs(sx1 - sx);
! 	/* Skip if interval is too small. */
! 	if (interval < 16) return;
! 		
! 	/* Set up the drawing rect. */
! 	drawrect = portrect = map->gworldPortPtr->portRect;
! 	drawrect.right = min(portrect.right, map->vp->totsw);
! 	drawrect.bottom = min(portrect.bottom, map->vp->totsh);
! 	/* A hack for better positioning of the text. */	
! 	drawrect.top += map->vp->hh/4; 
! 	drawrect.bottom -= map->vp->hh/8; 
! 	
! 	/* Compute min/max values for latitudes and longitudes. */
! 	nearest_cell(map->vp, -map->conw, drawrect.bottom - map->toph, 
! 			    &xmin, &ymin, &xfmin, &yfmin);
! 	nearest_cell(map->vp, drawrect.right - map->conw, -map->toph, 
! 			    &xmax, &ymax, &xfmax, &yfmax);
! 	xy_to_latlong(xmin, ymin, xfmin, yfmin, &latmin, &lonmin);
! 	xy_to_latlong(xmax, ymax, xfmax, yfmax, &latmax, &lonmax);
! 
! 	/* Center the grid on the origin. */
! 	lonmin += (loncen - lonmin) % incr;
! 	lonmax += (loncen - lonmax) % incr;
! 	latmin += (latcen - latmin) % incr;
! 	latmax += (latcen - latmax) % incr;
! 	/* Special fixes for wrapped gworlds etc.*/
! 	if (lonmin > 0 || lonmax < 0 || lonmax <= lonmin) {
! 		lonmin = -10800; 
! 		lonmax = 10800 - incr;
! 	}
! 	
! 	/* Used in clipping code. */
! 	ymid = area.halfheight;
! 	xend = area.width - 1;
  
! 	/* Set meridian color. */
! 	RGBForeColor(&meridiancolor);
! 	
! 	/* Draw the latitiudes. */
! 	for (lat = latmin; lat <= latmax; lat += incr) {
! 		left = drawrect.left; 
! 		right = drawrect.right;
! 		latlong_to_xy(lat, loncen, &x, &y, &xf, &yf);
! 		/* Skip if outside area. */
! 		if (!in_area(x, y)) continue;
! 		xform_fractional(map, x, y, xf, yf, &sx, &sy);
! 		/* Don't draw latitudes where the longitude text will be. */
! 		if (sy - drawrect.top < 16 || drawrect.bottom - sy < 16) continue;
! 		/* Clip corners to area for non-wrapped worlds. */
! 		if (!area.xwrap) {
! 			/* Compute left endpoint. */
! 			if (in_area(0,y)) { 							
! 				 xform(map, 0, y, &left, 0);
! 				 left += 32;
! 			} else if (in_area(ymid - y, y)) {					
! 				 xform(map, ymid - y, y, &left, 0);
! 				 left += 32;
! 			}
! 			/* Compute right endpoint. */
! 			if (in_area(xend + ymid - y, y)) {				
! 				 xform(map, xend + ymid - y, y, &right, 0);
! 				 right -= 32 - map->vp->hw;
! 			} else if (in_area(xend, y)) {					
! 				 xform(map, xend, y, &right, 0);
! 				 right -= 32 - map->vp->hw;
! 			}
! 			/* Make room for text at left end. */
! 			left = max(left, portrect.left + 32);
! 			/* Make room for text at right end. */
! 			right = min(right, portrect.right - 32);
! 		} else { 
! 			/* Make room for text at right end unless the gworld is wrapped. */
! 			if (map->vp->sxmax > portrect.right - portrect.left) right -= 32;
! 			/* Always make room at left end. */
! 			left += 32; 
! 		}
! 		MoveTo(left, sy);
! 		LineTo(right, sy);
! 		latdeg = abs(lat) / 60;
! 		latmit = abs(lat) % 60;
! 		mitbuf[0] = '\0';
! 		if (latmit != 0) sprintf(mitbuf, "%d«", latmit);
! 		sprintf(tmpbuf, "%d¡%s", latdeg, mitbuf);
! 		if (lat >= 0) strcat(tmpbuf, "N");
! 		if (lat < 0) strcat(tmpbuf, "S");
! 		/* Always draw latitude text at left edge. */
! 		draw_legend_text(left - 3, sy, 12, tmpbuf, +1, 0, 0);
! 		/* Also draw text at right edge unless the gworld is wrapped. */
! 		if (!area.xwrap || map->vp->sxmax > portrect.right - portrect.left)
! 			draw_legend_text(right + 3, sy, 12, tmpbuf, -1, 0, 0);
! 	}
  
! 	/* Draw the longitudes. */
! 	for (lon = lonmin; lon <= lonmax; lon += incr) {
! 		/* Make room for top and bottom text. */
! 		top = drawrect.top + 16; 
! 		bottom = drawrect.bottom - 16;
! 		latlong_to_xy(latcen, lon, &x, &y, &xf, &yf);
! 		/* Skip if outside area. */
! 		if (!in_area(x, y)) continue;
! 		xform_fractional(map, x, y, xf, yf, &sx, &sy);
! 		/* Clip corners to area for non-wrapped maps. */
! 		if (!area.xwrap) {
! 			/* Compute top endpoint. */
! 			if (in_area(0,  ymid + 2 * x))						
! 				 xform(map, 0, ymid + 2 * x, 0, &top);
! 			else if (in_area(2 * x - xend, ymid + 2 * (xend - x)))	
! 				 xform(map, 2 * x - xend, ymid + 2 * (xend - x), 0, &top);
! 			/* Compute bottom endpoint. */
! 			if (in_area(2 * x, ymid - 2 * x))					
! 				 xform(map, 2 * x, ymid - 2 * x, 0, &bottom);	
! 			else if (in_area(xend, ymid - 2 * (xend - x)))				
! 				 xform(map, xend, ymid - 2 * (xend - x), 0, &bottom);
! 		}
! 		/* Wrap sx if necessary. */
! 		if (area.xwrap && sx < 0)
! 			sx += map->vp->sxmax;
! 		else if (area.xwrap && sx > map->vp->sxmax)
! 			sx -= map->vp->sxmax;
! 		MoveTo(sx, top);
! 		LineTo(sx, bottom);
! 		londeg = abs(lon) / 60;
! 		lonmit = abs(lon) % 60;
! 		mitbuf[0] = '\0';
! 		if (lonmit != 0) sprintf(mitbuf, "%d«", lonmit);
! 		sprintf(tmpbuf, "%d¡%s", londeg, mitbuf);
! 		if (lon > 0) strcat(tmpbuf, "E");
! 		if (lon < 0) strcat(tmpbuf, "W");
! 		/* Draw text at top and bottom. */
! 		if (top == drawrect.top + 16)
! 			draw_legend_text(sx, top - 6, 12, tmpbuf, 0, 0, 0);
! 		if (bottom == drawrect.bottom - 16)
! 			draw_legend_text(sx, bottom + 6, 12, tmpbuf, 0, 0, 0);
  	}
  
! 	ForeColor(blackColor);
! }
  
! #endif
  
! /* x0 may be negative here. */
  
! /* (should add a "draw interior only" version of this routine?) */
  
  void
! draw_row(map, x0, y0, len, clearit)
! Map *map;
! int x0, y0, len, clearit;
  {
! 	int empty = FALSE;
! 	int i = 0, x, xw, sx, sy, t;
  
! 	if (!between(0, y0, area.height - 1))
! 	  return;
! 	/* (should make generic) */
! 	if (!map->see_all && !map->vp->draw_ai && unseen_image == NULL) {
! 		empty = TRUE;
! 		/* Examine row to see if we can skip it entirely. */
! 		for (x = x0; x < x0 + len; ++x) {
! 			xw = wrapx(x);
! 			if (map->see_all
! 				|| terrain_visible(dside, xw, y0)
! 				|| (numbordtypes > 0 && terrain_visible(dside, xw, y0 + 1))
! 				) {
! 				empty = FALSE;
! 				break;
! 			}
! 		}
! 	}
! 	if (empty && !clearit)
! 	  return;
! 	/* The terrain always comes first. */
! 	if (map->vp->draw_terrain) {
! 		draw_terrain_row(map, x0, y0, len);
! 		  draw_shorelines(map, x0, y0, len + 1);
! 		/* Maybe draw cliffs.  Note that we always want to draw cliffs if the view is
! 		   at an angle, since otherwise there's no point in having the view be at an
! 		   angle. */
! 		if ((elevations_defined() || any_thickness) && map->vp->angle != 90) {
! 			for (x = x0; x < x0 + len; ++x) {
! 				if (map->see_all || terrain_visible(dside, x, y0)) {
! 					draw_cliffs(map, x, y0);
! 				}
! 			}
! 		}
! 		if (elevations_defined() && map->vp->draw_elevations && map->vp->angle == 90) {
! 			for (x = x0; x < x0 + len; ++x) {
! 				if (map->see_all || terrain_visible(dside, x, y0)) {
! 					draw_contours(map, x, y0);
! 				}
! 			}
! 		}
! 		/* Note: the check for erase_names is because names will leak into the grid
! 		   if the quick method is used. It is therefore always necessary to use explicit
! 		   drawing of the grid also in this case. */
! 		if (map->vp->draw_grid
! 			&& (map->erase_names
! 				|| !grid_matches_unseen 
! 				|| map->vp->draw_plans
! 				|| map->vp->draw_ai
! 				|| (elevations_defined() 
! 					&& map->vp->draw_elevations && map->vp->angle == 90)))
! 			draw_gridlines(map, x0, y0, len + 1);
! 		/* Maybe draw shorelines. */
! 		if (map->shorelines)
! 		  draw_shorelines(map, x0, y0, len + 1);
! 		if (any_aux_terrain_defined()) {
! 			/* The relative ordering of these is quite important - connections
! 			   should always be drawn on top of borders. */
! 			if (bords_to_draw(map)) {
! 				for_all_terrain_types(t) {
! 					if (map->vp->draw_aux_terrain[t] && t_is_border(t) && aux_terrain_defined(t)) {
! 						for (x = x0; x < x0 + len; ++x) {
! 							draw_borders(map, x, y0, t);
! 						}
! 					}
! 				}
! 			}
! 			if (conns_to_draw(map)) {
! 				for_all_terrain_types(t) {
! 					if (map->vp->draw_aux_terrain[t] && t_is_connection(t) && aux_terrain_defined(t)) {
! 						for (x = x0; x < x0 + len; ++x) {
! 							draw_connections(map, x, y0, t);
! 						}
! 					}
! 				}
! 			}
! 		}
! 	}
! 	if (clouds_defined() && map->vp->draw_clouds) {
! 		for (x = x0; x < x0 + len; ++x) {
! 			if (draw_clouds_here(x, y0)) {
! 				xform(map, x, y0, &sx, &sy);
! 				if (map->vp->hh <= 16) {
! 
! 				  WRAP_SX(map, sx, 
! 					draw_cloud_block(sx, sy, 1, map->vp->power, cloud_view(dside, x, y0), 
! 															map->vp->angle));
  
! 				} else { 
  
! 				  WRAP_SX(map, sx, 
! 					draw_clouds(sx, sy, map->vp->power, cloud_view(dside, x, y0)));
! 				}
! 			}
! 		}
! 	}
! 	if (winds_defined() && map->vp->draw_winds && map->vp->hh > 10) {
! 		for (x = x0; x < x0 + len; ++x) {
! 			if (draw_winds_here(dside, x, y0)) {
! 				xform(map, x, y0, &sx, &sy);
! 				WRAP_SX(map, sx,
! 					draw_winds(sx, sy, map->vp->power, wind_view(dside, x, y0)));
! 			}
! 		}
! 	}
! 	if (temperatures_defined() && map->vp->draw_temperature && map->vp->hh > 10) {
! 		for (x = x0; x < x0 + len; ++x) {
! 			if (draw_temperature_here(dside, x, y0)) {
! 				xform(map, x, y0, &sx, &sy);
! 				WRAP_SX(map, sx,
! 					draw_temperature(sx, sy, map->vp->power, temperature_view(dside, x, y0)));
! 			}
! 		}
! 	}
! 	/* Although we had to draw the terrain on the edge, we can skip everything else,
! 	   since edge cells have no units, features, etc. */
! 	/* Skip the top and bottom edge rows. */
! 	if (!between(1, y0, area.height - 2)) 
! 	  return;
! 	/* Shorten the row by one cell on each side, if those are edge cells. */
! 	if (!inside_area(x0 + len - 1, y0))
! 	  --len;
! 	if (!inside_area(x0, y0)) {
! 		++x0;
! 		--len;
! 	}
! 	if (len <= 0)
! 	  return;
! 	if (features_defined() && map->featureborders && map->vp->hw > 4) {
! 		if (map->simple_borders)
! 		  draw_simple_feature_borders(map, x0, y0, len + 1);
! 		else for (x = x0; x < x0 + len; ++x)
! 		  draw_feature_boundary(map, x, y0);
! 	}
! 	if (any_cell_materials_defined() && map->vp->num_materials_to_draw > 0 && map->vp->hh > 20) {
! 		for (x = x0; x < x0 + len; ++x) {
! 			draw_materials(map, x, y0);
! 		}
! 	}
! 	/* (should be global to entire map drawing somehow?) */
! 	/* Draw feature names even at low power! */
! 	if (map->featurenames && map->vp->hh > 3) {
! 		for (x = x0; x < x0 + len; ++x) {
! 			draw_legend(map, x, y0);
! 		}
! 	}
! 	if ((people_sides_defined() || control_sides_defined()) && bwid2[map->vp->power] > 0) {
! 		draw_people_row(map, x0, y0, len);
! 	}
! 	if (map->vp->draw_units && map->vp->hw > 2) {
! 		for (x = x0; x < x0 + len; ++x) {
! 			draw_units(map, x, y0);
! 		}
  	}
! 	if (map->vp->draw_ai) {
! 		for (x = x0; x < x0 + len; ++x) {
! 			draw_ai_region(map, x, y0);
! 		}
  	}
! 	/* If debugging, draw coverage on top of everything else. */
! 	if (DebugG && !all_see_all && map->vp->hw >= 16) {
! 		for (x = x0; x < x0 + len; ++x) {
! 			xform(map, x, y0, &sx, &sy);
! 			WRAP_SX(map, sx, 
! 				draw_coverage(sx, sy, map->vp->power, cover(dside, x, y0), alt_cover(dside, x, y0)));
! 		}
  	}
  }
  
! /* Is this just to see if a cell is visible? */
  
! int
! cell_update(map, x, y)
! Map *map;
! int x, y;
  {
! #if 0
! 	int sx, sy;
! 	Rect tmprect;
  
! 	xform(map, x, y, &sx, &sy);
! 	SetRect(&tmprect, sx, sy, sx + map->vp->hw, sy + map->vp->hh);
! 	return (RectInRgn(&tmprect, map->window->visRgn));
! #else
! 	return TRUE;
! #endif
! }
  
! /* Draw an entire row of terrain, possibly with a single rectangle fill. */
!  
! /* x0 may be negative. */
  
! void
! draw_terrain_row(map, x0, y0, len)
! Map *map;
! int x0, y0, len;
! {
! 	int x0w, x, xw, x1, x1w, sx, sy, i;
! 	int pwr = map->vp->power, ang = map->vp->angle;
! 	int dogrid = map->vp->draw_grid & grid_matches_unseen; 
! 	int dofill = map->vp->draw_cell_pats;
! 	int dosolid = map->solid_color_terrain;
! 	int inarea, seginarea, style, segstyle, terr, segterr, over, segover, update, segupdate;
! 
! 	tmpdrawlighting = map->vp->draw_lighting;
! 	tmpdrawcoverage = (!dside->see_all && map->vp->draw_cover);
! 	x0w = wrapx(x0);
! 	i = 0;
! 	x1 = x0;
! 	x1w = wrapx(x1);
! 	seginarea = in_area(x0w, y0);
! 	segstyle = cell_style(map, x0w, y0, pwr);
! 	segterr = cell_terrain(map, x0w, y0);
! 	segover = cell_overlay(x0w, y0);
! 	segupdate = (seginarea ? cell_update(map, x0w, y0) : FALSE);
! 	/* Note that in this loop we do NOT wrap x for drawing, just for
! 	   looking at layer data. */
! 	for (x = x0; x < x0 + len + 1; ++x) {
! 		xw = wrapx(x);
! 		inarea = in_area(xw, y0);
! 		style = cell_style(map, xw, y0, pwr);
! 		terr = cell_terrain(map, xw, y0);
! 		over = cell_overlay(xw, y0);
! 		update = (inarea ? cell_update(map, xw, y0) : FALSE);
! 		/* Decide if the run is over and we need to dump some output. */
! 		if (x == x0 + len
! 			|| x == area.width
! 			|| inarea != seginarea
! 			|| style != segstyle
! 			|| terr != segterr
! 			|| over != segover
! 			|| update != segupdate
! /*			|| segstyle == useblocks  fixes, but poor performance */
! 			|| segstyle == usepictures
! 			|| segstyle == usepolygons
! 			|| ang != 90) {
! 			/* don't draw anything that would match the window's bg */
! #if 0 /* use this for heavy-duty debugging only */
! 			DGprintf("Seg is %d,%d len=%d inarea=%d style=%d terr=%d over=%d update=%d\n",
! 					 x1, y0, i, seginarea, segstyle, segterr, segover, segupdate);
! #endif
! 			if (seginarea && segupdate && segstyle != dontdraw) {
! 				xform(map, x1, y0, &sx, &sy);
! 				switch (segstyle) {
! 					case useblocks:
! 						WRAP_SX(map, sx, 
! 							draw_cell_block(sx, sy, i, pwr, segterr, segover, ang, dosolid));													
! 						break;
! 					case usepictures:
! 						break;
! 					case usepolygons:
! 						WRAP_SX(map, sx, 
! 							draw_hex_region(sx, sy, pwr, segterr, segover, ang, dogrid, dosolid));
! 				}
! 			}
! 			/* Set up for the next segment. */
! 			i = 0;
! 			x1 = x;
! 			x1w = wrapx(x1);
! 			seginarea = inarea;
! 			segstyle = style;
! 			segterr = terr;
! 			segover = over;
! 			segupdate = update;
  		}
- 		++i;
  	}
- }
  
! static void
! draw_cliffs(Map *map, int x, int y)
! {
! 	int xw, elev, x1, y1, drop, t, t1, drawit, elev1, offset;
! 	int sx, sy, sx1, sy1;
! 	PolyHandle poly;
! 	RGBColor hexcolor, oldcolor;
  
! 	xw = wrapx(x);
! 	t = cell_terrain(map, xw, y);
! 	elev = (elevations_defined() ? elev_at(xw, y) : 0) + t_thickness(t);
! 	drawit = FALSE;
! 	if (point_in_dir(xw, y, SOUTHWEST, &x1, &y1)) {
! 		t1 = cell_terrain(map, x1, y1);
! 		if (t1 != NONTTYPE) {
! 			drop = elev - ((elevations_defined() ? elev_at(x1, y1) : 0) + t_thickness(t1));
! 			if (drop > 0) {
! 				drawit = TRUE;
! 				xform(map, x, y, &sx, &sy);
! 				xform(map, x1, y1, &sx1, &sy1);
! 			}
! 		}
! 	} else {
! 		drawit = TRUE;
! 		xform(map, x, y, &sx, &sy);
! 	    elev1 = elev - (elevations_defined() ? area.minelev : 0);
! 	    elev1 *= map->vp->vertscale;
! 	    offset = (elev1 * map->vp->hh) / map->vp->cellwidth;
! 	    sy1 = sy + map->vp->hch + offset; 
! 	}
! 	if (drawit) {
! 		if (sy1 > sy + map->vp->hch + (map->vp->draw_grid ? 1 : 0)) {
! 			poly = OpenPoly();
! 			MoveTo(sx, sy + map->vp->hch);
! 			LineTo(sx + map->vp->hw / 2, sy + map->vp->hh);
! 			LineTo(sx + map->vp->hw / 2, sy1 + (map->vp->hh - map->vp->hch));
! 			LineTo(sx, sy1);
! 			LineTo(sx, sy + map->vp->hch);
! 			ClosePoly();
! 			/* if (timg->colrpat != nil
! 			    && (minscreendepth > 1 || !timg->patdefined)) {
! 				FillCPoly(poly, timg->colrpat);
! 			} else */ if (tcolors[t] != NULL && maxscreendepth > 1) {
! 				hexcolor.red   = tcolors[t]->color.red / 2;
! 				hexcolor.green = tcolors[t]->color.green / 2;
! 				hexcolor.blue  = tcolors[t]->color.blue / 2;
! 				RGBForeColor(&hexcolor);
! 				WRAP_POLY(map, poly, 
! 					PaintPoly(poly));
! 				/* Restore the previous color. */
! 				RGBForeColor(&blackcolor);
! 			} else {
! 				hexcolor.red   = (128 << 8) / 2;
! 				hexcolor.green = (128 << 8) / 2;
! 				hexcolor.blue  = (128 << 8) / 2;
! 				RGBForeColor(&hexcolor);
! 				WRAP_POLY(map, poly, 
! 					PaintPoly(poly));
! 				/* Restore the previous color. */
! 				RGBForeColor(&blackcolor);
! 			}
! 			KillPoly(poly);
! 		}
! 	}
! 	drawit = FALSE;
! 	if (point_in_dir(xw, y, SOUTHEAST, &x1, &y1)) {
! 		t1 = cell_terrain(map, x1, y1);
! 		if (t1 != NONTTYPE) {
! 			drop = elev - ((elevations_defined() ? elev_at(x1, y1) : 0) + t_thickness(t1));
! 			if (drop > 0) {
! 				drawit = TRUE;
! 				xform(map, x, y, &sx, &sy);
! 				xform(map, x1, y1, &sx1, &sy1);
! 			}
! 		}
! 	} else {
! 		drawit = TRUE;
! 		xform(map, x, y, &sx, &sy);
! 	    elev1 = elev - (elevations_defined() ? area.minelev : 0);
! 	    elev1 *= map->vp->vertscale;
! 	    offset = (elev1 * map->vp->hh) / map->vp->cellwidth;
! 	    sy1 = sy + map->vp->hch + offset; 
! 	}
! 	if (drawit) {
! 		if (sy1 > sy + map->vp->hch + (map->vp->draw_grid ? 1 : 0)) {
! 			poly = OpenPoly();
! 			MoveTo(sx + map->vp->hw - (map->vp->draw_grid ? 1 : 0),     sy + map->vp->hch);
! 			LineTo(sx + map->vp->hw - (map->vp->draw_grid ? 1 : 0),     sy1);
! 			LineTo(sx + map->vp->hw / 2, sy1 + (map->vp->hh - map->vp->hch));
! 			LineTo(sx + map->vp->hw / 2, sy + map->vp->hh);
! 			LineTo(sx + map->vp->hw - (map->vp->draw_grid ? 1 : 0),     sy + map->vp->hch);
! 			ClosePoly();
! 			/* if (timg->colrpat != nil
! 			    && (minscreendepth > 1 || !timg->patdefined)) {
! 				FillCPoly(poly, timg->colrpat);
! 			} else */ if (tcolors[t] != NULL && maxscreendepth > 1) {
! 				hexcolor.red   = (3 * tcolors[t]->color.red) / 4;
! 				hexcolor.green = (3 * tcolors[t]->color.green) / 4;
! 				hexcolor.blue  = (3 * tcolors[t]->color.blue) / 4;
! 				RGBForeColor(&hexcolor);
! 				WRAP_POLY(map, poly, 
! 					PaintPoly(poly));
! 				/* Restore the previous color. */
! 				RGBForeColor(&blackcolor);
! 			} else {
! 				hexcolor.red   = (3 * 128 << 8) / 4;
! 				hexcolor.green = (3 * 128 << 8) / 4;
! 				hexcolor.blue  = (3 * 128 << 8) / 4;
! 				RGBForeColor(&hexcolor);
! 				WRAP_POLY(map, poly, 
! 					PaintPoly(poly));
! 				/* Restore the previous color. */
! 				RGBForeColor(&blackcolor);
! 			}
! 			KillPoly(poly);
  		}
  	}
  }
  
! static void
! draw_contours(Map *map, int x, int y)
  {
! 	int i, sx, sy, numlines;
! 	LineSegment *lines;
  
! 	init_contour_lines();
! 	if (contour_interval < 1)
! 	  return;
! 	xform(map, x, y, &sx, &sy);
! 	contour_lines_at(map->vp, wrapx(x), y, sx, sy, &lines, &numlines);
! 	RGBForeColor(&contourcolor);
! 	for (i = 0; i < numlines; ++i) {
! 		MoveTo(lines[i].sx1, lines[i].sy1);
! 		LineTo(lines[i].sx2, lines[i].sy2);
! 	}
! 	ForeColor(blackColor);
! }
  
! static void
! draw_borders(map, x, y, b)
! Map *map;
! int x, y, b;
! {
! 	int xw = wrapx(x), dir, sx, sy, bitmask = 0, over;
! 	
!  	if (!(map->see_all || terrain_visible(dside, xw, y)) || !any_borders_at(xw, y, b))
!  	  return;
! 	for_all_directions(dir) {
! 		if (border_at(xw, y, dir, b) && borders_visible(dside, xw, y, dir)) {
! 			bitmask |= 1 << dir;
! 		}
! 	}
! 	if (bitmask != 0) {
! 		tmpdrawlighting = map->vp->draw_lighting;
! 		tmpdrawcoverage = (!all_see_all && map->vp->draw_cover);
! 		over = cell_overlay(xw, y);
! 		xform(map, x, y, &sx, &sy);
! 		/* (should compute and pass in overlay) */
! 		WRAP_SX(map, sx, 
! 			draw_border_line_multiple(map->window, sx, sy, bitmask, map->vp->power, b, 
! 								map->vp->angle, over, map->solid_color_terrain));
! 		
! 	}
! }
  
! /* Draw all the connections of the given cell. */
  
! static void
! draw_connections(map, x, y, c)
! Map *map;
! int x, y, c;
! {
! 	int xw = wrapx(x), dir, sx, sy, bitmask = 0, over;
! 	
! 	if (!(map->see_all || terrain_visible(dside, xw, y)) || !any_connections_at(xw, y, c))
  	  return;
! 	for_all_directions(dir) {
! 		if (connection_at(xw, y, dir, c)) {
! 			bitmask |= 1 << dir;
! 		}
! 	}
! 	if (bitmask != 0) {
! 		tmpdrawlighting = map->vp->draw_lighting;
! 		tmpdrawcoverage = (!all_see_all && map->vp->draw_cover);
! 		over = cell_overlay(xw, y);
! 		xform(map, x, y, &sx, &sy);
! 		/* (should compute and pass in overlay) */
! 		WRAP_SX(map, sx, 
! 			draw_connection_line_multiple(map->window, sx, sy, bitmask, map->vp->power, c, 
! 									map->vp->angle, over, map->solid_color_terrain));
  	}
  }
  
! /* This function draws units at a small magnification */
! /* Draw all the units visible in the given cell. */
! /* (x is not wrapped) */
  
! static void
! draw_units(map, x, y)
! Map *map;
! int x, y;
! {
! 	int xw = wrapx(x), sx, sy, sw, sh, uview, u, s;
! 	Unit *unit;
! 	Rect tmprect;
! 	extern PicHandle dotdotdotpicture;
  
! 	if (map->see_all || units_visible(dside, xw, y)) {
! 		unit = unit_at(xw, y);
! 		if (unit != NULL) {
! 			xform(map, x, y, &sx, &sy);
! 			if (map->vp->uw <= 16) {
! 				/* Adjust to unit part of cell. */
! 				sw = map->vp->uw;  sh = map->vp->uh;
! 				sx += (map->vp->hw - sw) / 2;  sy += (map->vp->hh - sw) / 2;
! 				if (unit->occupant != NULL
! 					&& sw >= 8
! 	    			&& (unit->side == dside || all_see_all || u_see_occupants(unit->type))) {
! 					/* Draw a "grouping box", in white, but with no occs drawn. */
! 					SetRect(&tmprect, sx, sy, sx + sw, sy + sh);
! 					s = side_number(unit->side);
! 					if (map->boxmasks) {
! 						if (map->sidecolors && icon_mask_color[s]) {
! 							RGBBackColor(&(get_sideColor(s, icon_mask_color[s])));
! 						} else {
! 							RGBBackColor(&maskcolor);
! 						}
! 						WRAP_RECT(map, tmprect, 
! 							FillRect(&tmprect, QDPat(white)));
! 						BackColor(whiteColor);
! 					}
! 					WRAP_RECT(map, tmprect, 
! 						FrameRect(&tmprect));
! 	    		}
! 				WRAP_SX(map, sx, 
! 					draw_unit_image(map->window, sx, sy, sw, sh, unit->type, side_number(unit->side), 
! 																!completed(unit), TRUE));
! 				/* Indicate if more than one stacked here.  Since this may cover up the unit's
! 				   picture, adjust it down as far as possible while remaining inside the
! 				   "cell minus grid" area. */
! 				if (unit->nexthere != NULL && sw > 8) {
! 					SetRect(&tmprect, sx + sw/2 - 6, sy + sh - 3,
! 									  sx + sw/2 + 6, sy + sh + 1);
! 					/* (should clip to fit in cell) */
! 					/* (should do a copybits) */
! 					WRAP_RECT(map, tmprect, 
! 						DrawPicture(dotdotdotpicture, &tmprect));
! 				}
! 				if (map->vp->draw_names) {
! 					/* Draw city names in uniform size and position */
! 					if (!mobile(unit->type)) {
! 					WRAP_SX(map, sx, 
! 						draw_unit_name(unit, sx, sy, map->vp->uw, map->vp->uh, map->textmasks, 
! 																map->optimize_fonts)); 
! 					} else
! 					WRAP_SX(map, sx, 
! 						draw_unit_name(unit, sx, sy, sw, sh, map->textmasks, map->optimize_fonts));
! 				}
! 			} else {
! 				for_all_stack(xw, y, unit) {
! 					if (1 /* doesnt work right? - side_sees_unit(dside, unit) */) {
! 						m_xform_unit(map, unit, &sx, &sy, &sw, &sh);
! 						draw_unit_and_occs(map, unit, sx, sy, sw, sh);
! 					}
! 				}
! 			}
! 		}
! 	} else {
! 		uview = unit_view(dside, xw, y);
! 		if (uview != EMPTY) {
! 			u = vtype(uview);  s = vside(uview);
! 			xform(map, x, y, &sx, &sy);
! 			sw = map->vp->uw;  sh = map->vp->uh;
! 			/* Adjust to unit part of cell. */
! 			sx += (map->vp->hw - sw) / 2;  sy += (map->vp->hh - sh) / 2;
! 			WRAP_SX(map, sx, 
! 				draw_unit_image(map->window, sx, sy, sw, sh, u, s, 0, TRUE));
! 		}
! 	}
! }
  
! /* This function draws units at a normal or high magnification */
  
! static void
! draw_unit_and_occs(map, unit, sx, sy, sw, sh)
  Map *map;
  Unit *unit;
- int sx, sy, sw, sh;
  {
! 	int u = unit->type, s = side_number(unit->side), sx2, sy2, sw2, sh2;
! 	int emblem = TRUE;
! 	Unit *occ;
  	Rect tmprect;
- 	
- 	/* If an occupant's side is the same as its transport's, then there's
- 	   really no need to draw its side emblem, since the transport's emblem
- 	   will also be visible. */
- 	if (unit->transport && unit->side == unit->transport->side)
- 	  emblem = FALSE;
- 	if (unit->occupant != NULL
- 		&& sw > 8
- 	    && (dside->see_all
- 		    || unit->side == dside
- 		    || u_see_occupants(unit->type)
- 		    || side_owns_occupant(dside, unit))) {
- 
- 		/* Draw a sort of "grouping box", in white. */
- 		/* Make box 1 pixel smaller to avoid leakage of its lower left corner into the grid. */
- 		SetRect(&tmprect, sx, sy, sx + sw - 1, sy + sh - 1);
- 		if (map->boxmasks) {
- 			if (map->sidecolors && icon_mask_color[s]) {
- 				RGBBackColor(&(get_sideColor(s, icon_mask_color[s])));
- 			} else {
- 				RGBBackColor(&maskcolor);
- 			}
- 			WRAP_RECT(map, tmprect, 
- 				FillRect(&tmprect, QDPat(white)));
- 			BackColor(whiteColor);
- 		}
- 			WRAP_RECT(map, tmprect, 
- 				FrameRect(&tmprect));
- 		/* Draw the transport in the UL quarter of the box. */
- 		m_xform_occupant(map, unit, unit, sx, sy, sw, sh, &sx2, &sy2, &sw2, &sh2);
- 		WRAP_SX(map, sx2, 
- 			draw_unit_image(map->window, sx2, sy2, sw2, sh2, u, s, !completed(unit), TRUE));
- 		if (map->vp->draw_names) {
- 			/* Draw city names in uniform size and position */
- 			if (!mobile(unit->type)) {
- 			  WRAP_SX(map, sx, 
- 				draw_unit_name(unit, sx, sy, map->vp->uw, map->vp->uh, map->textmasks, 
- 															map->optimize_fonts));  
- 			/* sw2 doubled moves the name out of the box so that it can be read more easily */
- 			} else {
  
! 			  WRAP_SX(map, sx2, 
! 				draw_unit_name(unit, sx2, sy2, 2 * sw2, sh2, map->textmasks, map->optimize_fonts)); 
  
! 			}
! 		}				
! 		/* Draw all the occupants, in the bottom half of the box. */
! 		for_all_occupants(unit, occ) {
! 			m_xform_occupant(map, unit, occ, sx, sy, sw, sh, &sx2, &sy2, &sw2, &sh2);
! 			/* Accomodate the smaller box by moving occs 2 pixels up. */
! 			draw_unit_and_occs(map, occ, sx2, sy2 - 2, sw2, sh2);	/* RECURSION! */
  		}
  	} else {
! 		/* Just draw the one unit. */
! 	  WRAP_SX(map, sx, 
! 		draw_unit_image(map->window, sx, sy, sw, sh, u, s, !completed(unit), emblem));
! 		if (map->vp->draw_names) {
! 			/* Draw city names in uniform size and position */
! 			if (!mobile(unit->type)) {
! 			  WRAP_SX(map, sx, 
! 				draw_unit_name(unit, sx, sy, map->vp->uw, map->vp->uh, map->textmasks, 
! 															map->optimize_fonts));  
! 			} else {
! 		
! 			  WRAP_SX(map, sx, 
! 				draw_unit_name(unit, sx, sy, sw, sh, map->textmasks, map->optimize_fonts));
! 			}
! 		}
  	}
! }
! 
! /* Indicate what kind of people are living in the given row. */
! 
! /* (should optimize by sharing border drawing for max efficiency) */
! /* (bulk of compute should go to ui.c) */
! static void
! draw_people_row(map, x0, y, len)
! Map *map;
! int x0, y, len;
! {
! 	int pop, xx, x, sx, sy, sw, sh, ex, ey, ew, eh, dir, x1, y1, pop1;
! 	int con, con1, bitmask1, bitmask2, bitmask3, drawemblemhere;
! 
! 	for (xx = x0; xx < x0 + len; ++xx) {
! 		x = wrapx(xx);
! 		if (!terrain_visible(dside, x, y))
! 		  continue;
! 		pop = (people_sides_defined() ? people_side_at(x, y) : NOBODY);
! 		con = (control_sides_defined() ? control_side_at(x, y) : NOCONTROL);
! 		bitmask1 = bitmask2 = bitmask3 = 0;
! 		drawemblemhere = FALSE;
! 		/* Decide which edges are borders of the country. */
! 		for_all_directions(dir) {
! 			/* Don't do anything about edge cells. */
! 			if (interior_point_in_dir(x, y, dir, &x1, &y1)) {
! 				if (terrain_visible(dside, x1, y1)) {
! 					pop1 = (people_sides_defined() ? people_side_at(x1, y1) : NOBODY);
! 					con1 = (control_sides_defined() ? control_side_at(x1, y1) : NOCONTROL);
! 					if (con != con1) {
! 						if (con == NOCONTROL || con1 == NOCONTROL) {
! 							bitmask2 |= 1 << dir;
! 						} else {
! 							bitmask1 |= 1 << dir;
  						}
! 					} else if (pop != pop1) {
! 						/* Borders with uninhabitated regions are drawn differently. */
! 						if (pop == NOBODY || pop1 == NOBODY) {
! 							bitmask2 |= 1 << dir;
! 						} else if (control_sides_defined()) {
! 							bitmask3 |= 1 << dir;
! 						} else {
! 							bitmask1 |= 1 << dir;
  						}
  					}
- 				} else {
- 					/* Draw just people in the cells right at the edge of the known world. */
- 					drawemblemhere = TRUE;
- 				}
  			}
  		}
! 		/* Now draw both the edges and an emblem for the cell. */
! 		if ((bitmask1 | bitmask2 | bitmask3) != 0
! 			|| ((map->vp->draw_people || map->vp->draw_control) && drawemblemhere)) {
! 			/* Important to use unwrapped xx! */
! 			xform(map, xx, y, &sx, &sy);
! 			RGBForeColor(&frontcolor);		/* Use customized frontline color */
! 			if (bitmask1 != 0) {
! 			  WRAP_SX(map, sx, 
! 				draw_country_borders(map->window, sx, sy, bitmask1, map->vp->power, 0, 
! 														map->vp->angle));
! 			}
! 			/* Do not use shaded border to sea and empty land if simple_borders is on. */
! 			if (bitmask2 != 0 && !map->simple_borders) {
! 			  WRAP_SX(map, sx, 
! 				draw_country_borders(map->window, sx, sy, bitmask2, map->vp->power, 2, 
! 														map->vp->angle));
! 			}
! 			if (bitmask3 != 0 && !map->simple_borders) {
! 			  WRAP_SX(map, sx, 
! 				draw_country_borders(map->window, sx, sy, bitmask3, map->vp->power, 1, 
! 														map->vp->angle));
! 			}
! 			ForeColor(blackColor);					/* Restore Fore Color */
! 
! 			/* Draw an emblem for the people in the cell. */
! 			if (map->vp->draw_people && pop != NOBODY) {
! 				sw = map->vp->uw;  sh = map->vp->uh;
! 				ew = min(sw, max(8, sw / 2));  eh = min(sh, max(8, sh / 2));
! 				ex = sx + (map->vp->hw - map->vp->uw) / 2 + sw / 2 - ew / 2;  
! 				ey = sy + (map->vp->hh - map->vp->uh) / 2 + sh / 2 - eh / 2;
! 				/* Maybe draw emblem so it will be visible underneath control emblem. */
! 				if (map->vp->draw_control && con != pop) {
! 					ex += 2;  ey += 2;
! 				}
! 				WRAP_SX(map, ex, 
! 					draw_side_emblem(map->window, ex, ey, ew, eh, pop, plain_emblem));
  
! 			}
! 			if (map->vp->draw_control && con != NOCONTROL && (bitmask1 | bitmask2) != 0) {
! 				sw = map->vp->uw;  sh = map->vp->uh;
! 				ew = min(sw, max(8, sw / 2));  eh = min(sh, max(8, sh / 2));
! 				ex = sx + (map->vp->hw - map->vp->uw) / 2 + sw / 2 - ew / 2;  
! 				ey = sy + (map->vp->hh - map->vp->uh) / 2 + sh / 2 - eh / 2;
! 				WRAP_SX(map, ex, 
! 					draw_side_emblem(map->window, ex, ey, ew, eh, con, plain_emblem));
! 			}
! 		}
  	}
  }
  
! static void
! draw_feature_boundary(map, x, y)
  Map *map;
! int x, y;
  {
! 	int xw, fid, fid1, dir, x1, y1, bitmask, sx, sy;
! 	Feature *feature;
  
!     xw = wrapx(x);
! 	if (terrain_visible(dside, xw, y)) {
! 		fid = raw_feature_at(xw, y);
! 		if (fid == 0)
! 		  return;
! 		bitmask = 0;
! 		/* Decide which edges are borders of the feature. */
! 		for_all_directions(dir) {
! 			/* Don't do anything about edge cells. */
! 			if (interior_point_in_dir(xw, y, dir, &x1, &y1)) {
! 				fid1 = raw_feature_at(x1, y1);
! 				if (fid != fid1) {
! 					bitmask |= 1 << dir;
! 				}
! 			}
! 		}
! 		if (bitmask != 0) {
! 			xform(map, x, y, &sx, &sy);
! 			if (bitmask != 0) {
! 			  WRAP_SX(map, sx, 
! 				draw_feature_borders(map->window, sx, sy, bitmask, map->vp->power));
! 			}
! 		}
! 	}
! }
  
! /* This draws a small set of bar charts, one for each material type. */
  
! static void
! draw_materials(map, x, y)
! Map *map;
! int x, y;
! {
! 	int m, t, sx, sy, mx, my, mw, mh, amt, maxamt, h;
! 	Rect graphrect;
! 	
! 	if (nummtypes == 0)
! 	  return;
! 	mw = map->vp->uw / nummtypes /* should be count of displayable materials... */;  mh = map->vp->uh;
! 	if (mw <= 2 || mh <= 2)
! 	  return;
! 	/* (should this be apparent instead of real terrain?) */
! 	t = cell_terrain(map, wrapx(x), y);
! 	xform(map, x, y, &sx, &sy);
! 	mx = sx + (map->vp->hw - map->vp->uw) / 2;  my = sy + (map->vp->hh - map->vp->uh) / 2;
! 	for_all_material_types(m) {
! 		if (map->vp->draw_materials[m] && (maxamt = tm_storage_x(t, m)) > 0) {
! 			SetRect(&graphrect, mx + m * mw, my, mx + (m + 1) * mw, my + map->vp->uh);
! 			WRAP_RECT(map, graphrect, 
! 				FrameRect(&graphrect));
! 			amt = material_view(dside, x, y, m);
! 			h = (amt * mh) / maxamt;
! 			graphrect.top -= (mh - h);
! 			/* (should use a per-material color/pattern if available) */
! 			WRAP_RECT(map, graphrect, 
! 				FillRect(&graphrect, QDPat(black)));
! 		}
! 	}
! }
  
! static void
! draw_ai_region(map, x, y)
! Map *map;
! int x, y;
! {
! 	int xw, thid, sx, sy, dir, x1, y1, thid1, bitmask = 0;
  
! 	xw = wrapx(x);
! 	thid = ai_region_at(dside, xw, y);
! 	/* Decide which edges are borders of the theater. */
! 	for_all_directions(dir) {
! 		/* Don't do anything about edge cells. */
! 		if (interior_point_in_dir(xw, y, dir, &x1, &y1)) {
! 			thid1 = ai_region_at(dside, x1, y1);
! 			if (thid != thid1) {
! 				bitmask |= 1 << dir;
! 			}
  		}
  	}
! 	if (bitmask != 0) {
! 		xform(map, x, y, &sx, &sy);
! 		if (bitmask != 0) {
! 		  WRAP_SX(map, sx, 
! 			draw_ai_region_borders(map->window, sx, sy, bitmask, map->vp->power));
! 		}
  	}
! }
! 
! /* Draw any text that should be associated with this cell. */
  
! /* (could precompute what the string will lap over and move or truncate str),
!    should be deterministic for each mag, so redraw doesn't scramble */
  
! void
! draw_legend(map, x, y)
! Map *map;
! int x, y;
! {
! 	int xw, sx, sy;
! 	char *str, buf[BUFSIZE];
! 	Feature *feature;
! 
!     xw = wrapx(x);
! 	/* Draw the name of a terrain feature. */
! 	/* (should limit to one cell of feature, preferably centering on quasi-centroid) */	
! 	if (terrain_visible(dside, x, y)) {
! 		feature = feature_at(x, y);
! 		if (feature != NULL) {
! 			if (feature->size > 0) {
! 				if ((feature->x == x && feature->y == y)
! 					|| (feature->x == 0 && feature->y == 0)
! 					|| 0 /* center far away */) {
! 					str = feature_desc(feature, buf);
! 					if (str != NULL) {
! 						xform(map, x, y, &sx, &sy);
! 						if (map->featurenames) {
! 							RGBForeColor(&featurecolor);
! 							/* use sy instead of sy + map->vp->hh/2 to prevent drawing on top of unit names */
! 							WRAP_SX(map, sx, 
! 								draw_legend_text(sx + map->vp->hw/2, sy, 2 * map->vp->uh, str, 0, 
! 													map->textmasks, map->optimize_fonts));
! 							ForeColor(blackColor);
! 						}
! 					}
! 				}
! 			}
! 		}
! 	}
  }
  
  void
! draw_unit_blast(Map *map, Unit *unit, int blast)
  {
  	int sx, sy, sw, sh;
  	Rect destRect;
  	GrafPtr	oldport;
  	
  	GetPort(&oldport);
! 
  	GO_OFFSCREEN(map);
  
! 	/* Find offscreen coordinates of the unit rect */
! 	m_xform_unit(map, unit, &sx, &sy, &sw, &sh);
! 
! 	draw_blast_image(map->window, sx, sy, sw, sh, blast);
  
  	RETURN_ONSCREEN(map);
  	
! 	/* Dont try to copy a blasted unit outside the map! */
  	if (!in_area(unit->x, unit->y))
  	  return;
! 	/* Find onscreen coordinates of the unit rect */
! 	m_xform_unit(map, unit, &sx, &sy, &sw, &sh);
! 	/* Set copy destination to the unit rect */
! 	SetRect(&destRect, sx, sy, sx + sw, sy + sh);
  	/* Now copy offscreen map to window */
  	copy_from_gworld(map, destRect);			
  
  	SetPort(oldport);
  }
  
  void
! clear_unit_blast(Map *map, Unit *unit, int blast)
  {
! 	int x = unit->x, y = unit->y, sx, sy, i;
! 	Unit *unit2;
  	Rect destRect;
  	GrafPtr	oldport;
  
--- 1583,2120 ----
  	PenNormal();
  }
  
! void
! draw_unit_blast(Map *map, Unit *unit, int blast)
  {
! 	int sx, sy, sw, sh;
! 	Rect destRect;
! 	GrafPtr	oldport;
  	
! 	GetPort(&oldport);
  
! 	GO_OFFSCREEN(map);
  
! 	/* Find offscreen coordinates of the unit rect */
! 	m_xform_unit(map, unit, &sx, &sy, &sw, &sh);
  
! 	draw_blast_image(map->window, sx, sy, sw, sh, blast);
  
! 	RETURN_ONSCREEN(map);
! 	
! 	/* Dont try to copy a blasted unit outside the map! */
! 	if (!in_area(unit->x, unit->y))
! 	  return;
! 	/* Find onscreen coordinates of the unit rect */
! 	m_xform_unit(map, unit, &sx, &sy, &sw, &sh);
! 	/* Set copy destination to the unit rect */
! 	SetRect(&destRect, sx, sy, sx + sw, sy + sh);
! 	/* Now copy offscreen map to window */
! 	copy_from_gworld(map, destRect);			
  
! 	SetPort(oldport);
  }
  
  void
! clear_unit_blast(Map *map, Unit *unit, int blast)
  {
! 	int x = unit->x, y = unit->y, sx, sy, i;
! 	Unit *unit2;
! 	Rect destRect;
! 	GrafPtr	oldport;
  
! 	GetPort(&oldport);
  
! 	GO_OFFSCREEN(map);
! 
! 	/* Re-draw the hex containing the blast */
! 	draw_row(map, x, y, 1, TRUE);
! 
! 	/* Draw any selections that are here. */
! 	for (i = 0; i < map->numselections; ++i) {
! 		unit2 = map->selections[i];
! 		if (unit2 && unit2->x == x && unit2->y == y) {
! 			draw_selected_unit(map, unit2);
! 		}
  	}
  
! 	/* Re-draw gridlines & shorelines for the two hexes below */
  
! 	/* Draw grid explicitly if asked to and the quick method using smaller cells doesn't work. */
! 	if (map->vp->draw_grid 
! 		&& 	(map->erase_names 					/* Leaks into the grid. */
! 			|| !grid_matches_unseen 				/* Can't use quick method. */
! 			|| map->vp->angle!= 90				/* Can't use quick method.  */
! 	    		|| map->vp->draw_plans 				/* Leaks into the grid. */	
! 	    		|| map->vp->draw_ai 					/* Leaks into the grid. */
! 	    		|| map->vp->draw_elevations)) {			/* Leaks into the grid. */
! 				draw_gridlines(map, x, y - 1);
! 				draw_gridlines(map, x + 1, y - 1);
! 	}
! 	/* Always draw shorelines if asked to. */
! 	if (map->shorelines) {
! 		draw_shorelines(map, x, y - 1);
! 		draw_shorelines(map, x + 1, y - 1);
! 	}	
! 
! 	RETURN_ONSCREEN(map);
  
! 	/* Find the pixel coordinates of (x, y) */
! 	xform(map, x, y, &sx, &sy);
! 	/* Set destRect to enclose the redrawn hex */
! 	SetRect(&destRect, 
! 			sx - 2, sy - 2,			/* Add 2 for redrawn W & N shorelines */ 	
! 			sx + map->vp->hw, 
! 			sy + map->vp->hh + 4);	/* Add 4 for redrawn SE & SW shorelines */
! 
! 	/* Now copy offscreen map to window */
! 	copy_from_gworld(map, destRect);			
! 
! 	SetPort(oldport);
! }
  
! /* Draw all the selections of all the units. */
  
  void
! draw_selections(Map *map)
  {
! 	int sx, sy, sw, sh, i;
! 	Unit *unit;
! 	Rect destRect;
! 	GrafPtr	oldport;
  
! 	GetPort(&oldport);
  
! 	GO_OFFSCREEN(map);
  
! 	for (i = 0; i < map->numselections; ++i) {
! 		unit = map->selections[i];
! 		draw_selected_unit(map, unit);
  	}
! 
! 	RETURN_ONSCREEN(map);
! 	
! 	for (i = 0; i < map->numselections; ++i) {
! 		unit = map->selections[i];
! 		/* Dont try to copy a selection outside the map! */
! 		if (!in_area(unit->x, unit->y))
! 		  break;
! 		/* Find the pixel coordinates of (x, y). */
! 		xform(map, unit->x, unit->y, &sx, &sy);
! 		/* Copy the whole cell in case this was an occ within a big box. */
! 		SetRect(&destRect, sx, sy, sx + map->vp->hw, sy + map->vp->hh);
! 		/* Now copy offscreen map to window. */
! 		copy_from_gworld(map, destRect);			
  	}
! 	/* Update the unit info row. */
! 	if (map->numselections > 0) {
! 		draw_unit_info(map);
  	}
+ 	SetPort(oldport);
  }
  
! /* Draw all the selected units in the given cell. */
  
! void
! draw_selections_at(Map *map, int x, int y)
  {
! 	int xw, sx1, sy1, i;
! 	Unit *unit;
! 	Rect destRect;
! 	GrafPtr	oldport;
  
! 	xw = wrapx(x);
! 	
! 	GetPort(&oldport);
  
! 	GO_OFFSCREEN(map);
  
! 	for (i = 0; i < map->numselections; ++i) {
! 		unit = map->selections[i];
! 		if (unit && unit->x == xw && unit->y == y) {
! 			draw_selected_unit(map, unit);
  		}
  	}
  
! 	RETURN_ONSCREEN(map);
! 	
! 	/* Find the pixel coordinates of (x, y) */
! 	xform(map, x, y, &sx1, &sy1);
! 	/* Set destRect to enclose the redrawn cell */
! 	SetRect(&destRect, sx1, sy1, sx1 + map->vp->hw, sy1 + map->vp->hh);
! 	/* Now copy offscreen map to window */
! 	copy_from_gworld(map, destRect);			
  
! 	/* Update unit info line */
! 	if (map->numselections > 0) {
! 		unit = map->selections[0];
! 		if (in_play(unit) && unit->x == xw && unit->y == y) {
! 			draw_unit_info(map);
  		}
  	}
+ 	SetPort(oldport);
  }
  
! void
! draw_selected_unit_setport(Map *map, Unit *unit)
  {
! 	int sx, sy, sw, sh;
! 	Rect destRect;
! 	GrafPtr oldport;
  
! 	GetPort(&oldport);
  
! 	GO_OFFSCREEN(map);
  
! 	draw_selected_unit(map, unit);
  
! 	RETURN_ONSCREEN(map);
! 
! 	/* Dont try to copy a selection outside the map! */
! 	if (!in_area(unit->x, unit->y))
  	  return;
! 	/* Find the pixel coordinates of (x, y) */
! 	xform(map, unit->x, unit->y, &sx, &sy);
! 	/* Copy the whole cell in case this was an occ within a big box */
! 	SetRect(&destRect, sx, sy, sx + map->vp->hw, sy + map->vp->hh);
! 	/* Now copy offscreen map to window */
! 	copy_from_gworld(map, destRect);			
! 
! 	/* Update unit info line */
! 	if (map->numselections > 0) {
! 		unit = map->selections[0];
! 		if (in_play(unit)) {
! 			draw_unit_info(map);
! 		}
  	}
+ 	SetPort(oldport);
  }
  
! /* Draw a single selected unit on the given map.  Assumes that grafport already set. */
  
! /*
  
! The code now handles case with transport + occ and also third unit correctly, by using the transports 
! enclosing box rather than the whole cell as selection box. Moreover, the selected occ is drawn at normal
! magnification, instead of filling up the whole box (the latter caused a clutter of icons on top of each other).
! The fact that a specific occ is selected is instead indicated by drawing the emblem for that particular occ, 
! in addition to the transports emblem. The magnification lines have been removed since they are not needed
! anymore, and since they caused problems with leakage into the grid. 
  
! */
  
! void
! draw_selected_unit(map, unit)
  Map *map;
  Unit *unit;
  {
! 	int sx, sy, sw, sh, size, wholecell = FALSE, drawmag = FALSE;
! 	int sx1, sy1, sw1, sh1;
  	Rect tmprect;
  
! 	if (!in_play(unit))
! 	  return; /* unselect it too? */
! 	if (map->vp->uw >= 32) {
! 
! 		/* First draw the image in smaller ÒselfÓ box */
! 		m_xform_unit_self(map, unit, &sx, &sy, &sw, &sh);
! 
! 		/* Be sure the selected unit is drawn (MOVED FROM BELOW) */
! 		UNWRAP_SX(map, sx, 
! 			draw_unit_image(map->window, sx, sy, sw, sh, unit->type, side_number(unit->side), 
! 														!completed(unit), TRUE));
! 		/* Then use bigger box enclosing also occs as for selection box */
! 		m_xform_unit(map, unit, &sx, &sy, &sw, &sh);
! 		
! 		if (map->numselections == 1
! 			&& sw < 16
! 			&& (unit->transport != NULL) ) {
  
! 			/* Also use the box enclosing transport + occs for selected occ, NOT the whole cell */
! 			m_xform_unit(map, unit->transport, &sx, &sy, &sw, &sh);
! 
! 			sx1 = sx;  sy1 = sy;  sw1 = sw;  sh1 = sh;
  		}
  	} else {
! 		wholecell = TRUE;
  	}
! 	if (wholecell) {
! 		xform(map, unit->x, unit->y, &sx, &sy);
! 		/* Adjust to unit part of cell. */
! 		sx += (map->vp->hw - map->vp->uw) / 2;  
! 		sy += (map->vp->hh - map->vp->uh) / 2;
! 		sw = map->vp->uw;  sh = map->vp->uh;
! 		/* Be sure the selected unit is drawn. */
! 		UNWRAP_SX(map, sx, 
! 			draw_unit_image(map->window, sx, sy, sw, sh, unit->type, side_number(unit->side), 
! 														!completed(unit), TRUE));
! 	}
! 	if (0 /* not actually within visible area */)
! 	  return;
! 	/* Indicate a unit's plans/tasks in some useful fashion. */
! 	if (map->vp->draw_plans
! 		&& unit->plan
! 		&& unit->plan->tasks) {
! 		int sx2, sy2, sx3, sy3, rad;
! 		Task *task = unit->plan->tasks, *nexttask;
! 
! 		if (task != NULL) {
! 			if ((nexttask = task->next) != NULL) {
! 				/* Draw the next task first so it can be overwritten by info
! 				   about the current task. */
! 				switch (nexttask->type) {
! 					case TASK_MOVE_TO:
! 					case TASK_HIT_UNIT:
! 						if (in_area(nexttask->args[0], nexttask->args[1])) {
! 							xform(map, nexttask->args[0], nexttask->args[1], &sx3, &sy3);
! 							if (task->type == TASK_MOVE_TO) {
! 								xform(map, task->args[0], task->args[1], &sx2, &sy2);
! 								sx2 += map->vp->hw/2;  sy2 += map->vp->hh/2;
! 							} else {
! 								sx2 = sx + sw/2;  sy2 = sy + sh/2;
! 							}
! 							PenPat(QDPat(ltGray));
! 							MoveTo(sx2, sy2);
! 							LineTo(sx3 + map->vp->hw/2, sy3 + map->vp->hh/2);
! 							rad = nexttask->args[3];
! 							if (nexttask->type == TASK_MOVE_TO && rad > 1) {
! 								Rect tmprect;
! 
! 								MoveTo(sx3 - rad * map->vp->hh + map->vp->hw/2, sy3 + map->vp->hh/2);
! 								LineTo(sx3 + rad * map->vp->hh + map->vp->hw/2, sy3 + map->vp->hh/2);
! 								MoveTo(sx3 + map->vp->hw/2, sy3 - rad * map->vp->hw + map->vp->hh/2);
! 								LineTo(sx3 + map->vp->hw/2, sy3 + rad * map->vp->hw + map->vp->hh/2);
! 								tmprect.left  = sx3 - rad * map->vp->hh;  tmprect.top    = sy3 - rad * map->vp->hw;
! 								tmprect.right = sx3 + rad * map->vp->hh;  tmprect.bottom = sy3 + rad * map->vp->hw;
! 								OffsetRect(&tmprect, map->vp->hw/2, map->vp->hh/2);
! 								UNWRAP_RECT(map, tmprect, 
! 									FrameOval(&tmprect));
! 							}
! 							PenNormal();
  						}
! 				}
! 			}
! 			switch (task->type) {
! 				case TASK_MOVE_TO:
! 				case TASK_HIT_UNIT:
! 					if (in_area(task->args[0], task->args[1])) {
! 						xform(map, task->args[0], task->args[1], &sx2, &sy2);
! 						PenPat(QDPat(dkGray));
! 						MoveTo(sx + sw/2, sy + sh/2);
! 						LineTo(sx2 + map->vp->hw/2, sy2 + map->vp->hh/2);
! 						rad = task->args[3];
! 						if (task->type == TASK_MOVE_TO && rad > 1) {
! 							Rect tmprect;
! 
! 							MoveTo(sx2 - rad * map->vp->hh + map->vp->hw/2, sy2 + map->vp->hh/2);
! 							LineTo(sx2 + rad * map->vp->hh + map->vp->hw/2, sy2 + map->vp->hh/2);
! 							MoveTo(sx2 + map->vp->hw/2, sy2 - rad * map->vp->hw + map->vp->hh/2);
! 							LineTo(sx2 + map->vp->hw/2, sy2 + rad * map->vp->hw + map->vp->hh/2);
! 							tmprect.left  = sx2 - rad * map->vp->hh;  tmprect.top    = sy2 - rad * map->vp->hw;
! 							tmprect.right = sx2 + rad * map->vp->hh;  tmprect.bottom = sy2 + rad * map->vp->hw;
! 							OffsetRect(&tmprect, map->vp->hw/2, map->vp->hh/2);
! 							UNWRAP_RECT(map, tmprect, 
! 								FrameOval(&tmprect));
  						}
+ 						PenNormal();
  					}
  			}
  		}
! 	}
  
! 	/* Note: not used any longer, drawmag always false. Remove? */
! 	/* Draw magnification lines pointing to the true location of the unit. */
! 	if (drawmag) {
! 		/* PenPat should already be black. */
! 		MoveTo(sx,      sy);       LineTo(sx1,       sy1);
! 		MoveTo(sx + sw, sy);       LineTo(sx1 + sw1, sy1);
! 		MoveTo(sx,      sy + sh);  LineTo(sx1,       sy1 + sh1);
! 		MoveTo(sx + sw, sy + sh);  LineTo(sx1 + sw1, sy1 + sh1);
! 	}
! 
! 	/* Draw a highlighting rectangle. */
! 	SetRect(&tmprect, sx, sy, sx + sw, sy + sh);
! 	/* A hack to prevent leakage into the grid. */
! 	if (map->vp->draw_grid && map->vp->power == 5)
! 	  --tmprect.bottom;
! 	/* First, draw an outer frame, for contrast. */
! 	if (map->autoselect && unit->act && unit->act->initacp > 0 && unit->act->acp > 0) {
! 		PenPat(&animation_patterns[animation_pattern_state]);
! 	} else {
! 		PenPat(QDPat(white));
  	}
+ 	UNWRAP_RECT(map, tmprect, 
+ 		FrameRect(&tmprect));
+ 	InsetRect(&tmprect, 1, 1);
+ 	/* Black is for units that can still act, dark gray for actors, gray if the
+ 	   unit can't do anything. */
+ 	PenPat((unit->act && unit->act->initacp > 0) ?
+ 			((unit->act->acp > 0) ? QDPat(black) : QDPat(dkGray)) : QDPat(gray));
+ 	/* Wide border if awake, narrow if asleep or napping. */
+ 	size = ((unit->plan && (unit->plan->asleep || unit->plan->reserve)) ? 1 : 2);
+ 	PenSize(size, size);
+ 	UNWRAP_RECT(map, tmprect, 
+ 		FrameRect(&tmprect));
+ 	PenNormal();
+ 	DGprintf("draw selection of %s at %d,%d\n", unit_desig(unit));
  }
  
! /* The code now handles case with transport + occ and also third unit correctly,
!    by using the transports enclosing box rather than the whole cell as selection
!    box when either transport or occ is selected. The new definition of contentrect
!    is also handled. The black enclosing box is now drawn here as well. */
! 
! void
! draw_selection_animation(map, unit)
  Map *map;
! Unit *unit;
  {
! 	int sx, sy, sw, sh, wholecell = FALSE, drawmag = FALSE;
! 	int sx1, sy1, sw1, sh1, size;
! 	Rect tmprect, tmpRect;
! 	GrafPtr oldport;
! 	RgnHandle tmprgn;
  
! 	if (!in_play(unit))
! 	  return; /* unselect it too? */
!  	GetPort(&oldport);
! 	SetPort(map->window);
! 	tmprgn = NewRgn();
! 	GetClip(tmprgn);
  
! 	/* Clip to map content */
! 	tmpRect = map->contentrect;
  
! 	/* Nessary to do the offset the since we are drawing directly to the screen */
! 	OffsetRect(&tmpRect, map->vp->sx - map->conw, map->vp->sy - map->toph);
! 
! 	ClipRect(&tmpRect);
! 
! 	/* Old SHIFT_ORIGIN macro, now used only here. */
! 	map->osx = map->vp->sx - map->conw;
! 	map->osy = map->vp->sy - map->toph;
! 	SetOrigin(map->osx, map->osy);
! 
! 	if (map->vp->uw >= 32) {
! 
! 		/* Use bigger box enclosing also occs for selection box */
! 		m_xform_unit(map, unit, &sx, &sy, &sw, &sh);
  
! 		if (map->numselections == 1
! 			&& sw < 16
! 			&& (unit->transport != NULL) ) {
  
! 			m_xform_unit(map, unit->transport, &sx, &sy, &sw, &sh);
! 
! 			sx1 = sx;  sy1 = sy;  sw1 = sw;  sh1 = sh;
  		}
+ 	} else {
+ 		xform(map, unit->x, unit->y, &sx, &sy);
+ 		/* Adjust to unit part of cell. */
+ 		sx += (map->vp->hw - map->vp->uw) / 2;  sy += (map->vp->hh - map->vp->uh) / 2;
+ 		sw = map->vp->uw;  sh = map->vp->uh;
+ 	}
+ 	/* Draw a highlighting rectangle. */
+ 	SetRect(&tmprect, sx, sy, sx + sw, sy + sh);
+ 	/* A hack to prevent leakage into the grid. */
+ 	if (map->vp->draw_grid && map->vp->power == 5)
+ 	  --tmprect.bottom;
+ 	/* First, draw an outer white frame, for contrast. */
+ 	if (unit->act && unit->act->initacp > 0 && unit->act->acp > 0) {
+ 		PenPat(&animation_patterns[animation_pattern_state]);
+ 	} else {
+ 		PenPat(QDPat(white));
  	}
! 	FrameRect(&tmprect);
! 	if (area.xwrap) {
! 		int rest = map->vp->pxw - tmprect.left;
! 		/* Draw one extra copy to the left if necessary */
! 		if (tmprect.right > map->vp->sxmax) {
! 			OffsetRect(&tmprect, -map->vp->sxmax, 0);
! 			FrameRect(&tmprect);
! 			OffsetRect(&tmprect, map->vp->sxmax, 0);
! 		}		
! 		/* Draw more copies to the right if necessary*/
! 		while (rest > 0) {
! 			OffsetRect(&tmprect, map->vp->sxmax, 0);
! 			FrameRect(&tmprect);
! 			rest -= map->vp->sxmax;
! 		} 
! 	}
! 	/* This is important or the black box will disappear for transports at low mag. */
! 	InsetRect(&tmprect, 1, 1);
! 	/* Black is for units that can still act, dark gray for actors, gray if the unit can't do anything. */
! 	PenPat((unit->act && unit->act->initacp > 0) ?
! 			((unit->act->acp > 0) ? QDPat(black) : QDPat(dkGray)) : QDPat(gray));
! 	/* Wide border if awake, narrow if asleep or napping. */
! 	size = ((unit->plan && (unit->plan->asleep || unit->plan->reserve)) ? 1 : 2);
! 	PenSize(size, size);
! 	FrameRect(&tmprect);
! 	if (area.xwrap) {
! 		int rest = map->vp->pxw - tmprect.left;
! 		/* Draw one extra copy to the left if necessary */
! 		if (tmprect.right > map->vp->sxmax) {
! 			OffsetRect(&tmprect, -map->vp->sxmax, 0);
! 			FrameRect(&tmprect);
! 			OffsetRect(&tmprect, map->vp->sxmax, 0);
! 		}		
! 		/* Draw more copies to the right if necessary*/
! 		while (rest > 0) {
! 			OffsetRect(&tmprect, map->vp->sxmax, 0);
! 			FrameRect(&tmprect);
! 			rest -= map->vp->sxmax;
! 		} 
  	}
! 	PenNormal();
! 	PenPat(QDPat(black));
  
! 	/* Old RESET_ORIGIN macro, now used only here. */
! 	map->osx = 0;  map->osy = 0;
! 	SetOrigin(map->osx, map->osy);
  
! 	SetClip(tmprgn);
! 	DisposeRgn(tmprgn);
! 	SetPort(oldport);
  }
  
  void
! erase_selection(Map *map, Unit *unit)
  {
  	int sx, sy, sw, sh;
  	Rect destRect;
  	GrafPtr	oldport;
  	
  	GetPort(&oldport);
! 	
  	GO_OFFSCREEN(map);
  
! 	draw_unselected_unit(map, unit);
  
  	RETURN_ONSCREEN(map);
  	
! 	/* Dont try to copy a selection outside the map! */
  	if (!in_area(unit->x, unit->y))
  	  return;
! 	/* Find the pixel coordinates of (x, y) */
! 	xform(map, unit->x, unit->y, &sx, &sy);
! 	/* Copy the whole cell in case this was an occ within a big box */
! 	SetRect(&destRect, 
! 		sx - 2, sy - 2,			/* Add 2 for W & N shorelines */ 	
! 		sx + map->vp->hw, 
! 		sy + map->vp->hh + 4);	/* Add 4 for SE & SW shorelines */
! 
  	/* Now copy offscreen map to window */
  	copy_from_gworld(map, destRect);			
  
  	SetPort(oldport);
  }
  
+ /* (should only redraw any given cell once) */
+ 
  void
! erase_selections(Map *map)
  {
! 	int sx, sy, sw, sh, i;
! 	Unit *unit;
  	Rect destRect;
  	GrafPtr	oldport;
  
***************
*** 2626,2687 ****
  
  	GO_OFFSCREEN(map);
  
- 	/* Re-draw the hex containing the blast */
- 	draw_row(map, x, y, 1, TRUE);
- 
- 	/* Draw any selections that are here. */
  	for (i = 0; i < map->numselections; ++i) {
! 		unit2 = map->selections[i];
! 		if (unit2 && unit2->x == x && unit2->y == y) {
! 			draw_selected_unit(map, unit2);
! 		}
  	}
  
- 	/* Re-draw gridlines & shorelines for the two hexes below */
- 	if (map->vp->draw_grid & !grid_matches_unseen)
- 	  draw_gridlines(map, x, y - 1, 2);
- 	if (map->shorelines)
- 	  draw_shorelines(map, x, y - 1, 2);
- 	
  	RETURN_ONSCREEN(map);
! 
! 	/* Find the pixel coordinates of (x, y) */
! 	xform(map, x, y, &sx, &sy);
! 	/* Set destRect to enclose the redrawn hex */
! 	SetRect(&destRect, 
! 			sx - 2, sy - 2,			/* Add 2 for redrawn W & N shorelines */ 	
  			sx + map->vp->hw, 
! 			sy + map->vp->hh + 4);	/* Add 4 for redrawn SE & SW shorelines */
! 
! 	/* Now copy offscreen map to window */
! 	copy_from_gworld(map, destRect);			
  
  	SetPort(oldport);
  }
  
  void
! invert_map(Map *map, int x, int y, int r)
  {
! 	int sx, sy, sw, sh;
! 	Rect tmprect;
  	GrafPtr	oldport;
! 	
  	GetPort(&oldport);
  
! 	GO_OFFSCREEN(map);
  
! 	xform(map, x, y, &sx, &sy);
! 	SetRect(&tmprect, sx - (r * map->vp->hw) / 2, 
! 					  sy - (r * map->vp->hch) / 2,
! 					  sx + (r * map->vp->hw) / 2, 
! 					  sy + (r * map->vp->hch) / 2);
  
! 	InvertRect(&tmprect);
  
! 	RETURN_ONSCREEN(map);
  
! 	/* Copy tmprect to the screen */
! 	copy_from_gworld(map, tmprect);
  
  	SetPort(oldport);
  }
--- 2122,2435 ----
  
  	GO_OFFSCREEN(map);
  
  	for (i = 0; i < map->numselections; ++i) {
! 		unit = map->selections[i];
! 		draw_unselected_unit(map, unit);
  	}
  
  	RETURN_ONSCREEN(map);
! 	
! 	for (i = 0; i < map->numselections; ++i) {
! 		unit = map->selections[i];
! 		/* Dont try to find a unit that just died, or xform will freak! */
! 		if (!in_area(unit->x, unit->y))
! 		  return;
! 		/* Find the pixel coordinates of (x, y) */
! 		xform(map, unit->x, unit->y, &sx, &sy);
! 		/* Copy the whole cell in case this was an occ within a big box */
! 		SetRect(&destRect, 
! 			sx - 2, sy - 2,			/* Add 2 for W  & N shorelines */ 	
  			sx + map->vp->hw, 
! 			sy + map->vp->hh + 4);	/* Add 4 for SE & SW shorelines */
  
+ 		/* Now copy offscreen map to window */
+ 		copy_from_gworld(map, destRect);			
+ 	}
  	SetPort(oldport);
  }
  
  void
! draw_unselected_unit(Map *map, Unit *unit)
  {
! 	Unit	*unit2;
! 	int 	cells, x, y, i;
! 
! 	if (!in_play(unit)) return;
! 	x = unit->x;
! 	y = unit->y;
! 		
! 	/* Re-draw the hex containing the unselected unit */
! 	draw_row(map, x, y, 1, TRUE);
! 
! 	/* Re-draw gridlines and shorelines of the two hexes below (x, y) */
! 
! 	/* Draw grid explicitly if asked to and the quick method using smaller cells doesn't work. */
! 	if (map->vp->draw_grid 
! 		&& 	(map->erase_names 					/* Leaks into the grid. */
! 			|| !grid_matches_unseen 				/* Can't use quick method. */
! 			|| map->vp->angle!= 90				/* Can't use quick method.  */
! 	    		|| map->vp->draw_plans 				/* Leaks into the grid. */	
! 	    		|| map->vp->draw_ai 					/* Leaks into the grid. */
! 	    		|| map->vp->draw_elevations)) {			/* Leaks into the grid. */
! 				draw_gridlines(map, x, y - 1);
! 				draw_gridlines(map, x + 1, y - 1);
! 	}
! 	/* Always draw shorelines if asked to. */
! 	if (map->shorelines) { 
! 		draw_shorelines(map, x, y - 1);
! 		draw_shorelines(map, x + 1, y - 1);
! 	}
! 
! 	/* Re-draw any unit names that were erased by the update */
! 	if (map->vp->draw_names) {
! 		/* Find the number of cells that a name can cover at this mag */
! 		switch(map->vp->power) {
! 			case 7: 	cells = 2; break; 	/* 128 x 128 hexes */
! 			case 6: 	cells = 3; break;		/*      64 x 64 hexes */	
! 			case 5: 	cells = 4; break;		/*      32 x 32 hexes */
! 			case 4: 	cells = 4; break;		/*      16 x 16 hexes */
! 			case 3: 	cells = 8; break;		/*          8 x  8 hexes */
! 			default: 	cells = 1; break;
! 		}
! 		/* Re-draw unit names in cells - 1 hexes to the left of (x, y) */
! 		for (i = x - cells + 1; i <  x; i++) {
! 			for_all_stack(wrapx(i), y, unit2) {
! 				if (unit2->name)	{							
! 					draw_unit_names_only(map, i, y);
! 					break;
! 				}
! 			}
! 		}
! 	}					
! 
! 	DGprintf("erase selection of %s at %d,%d\n", unit_desig(unit));
! }
! 
! /* Draw an individual detailed cell, as a row of one, on all maps. */
! 
! void  
! update_cell_display(Side *side, int x, int y, int rightnow)
! {
! 	int xw, leftcells = 0, cells = 1, name = FALSE, sx1, sy1, i, j;		
! 	Rect destRect;
  	GrafPtr	oldport;
! 	Unit *unit;
! 	Map *map;
! 
! 	if (!active_display(side))
! 	  return;
! 	xw = wrapx(x);
  	GetPort(&oldport);
+ 	for_all_maps(map) {
  
! 		/* If update was only to report changes in undrawn info, maybe don't bother. */
! 		if ((rightnow == 34 && !map->vp->draw_temperature) 
! 		    || (rightnow == 37 && !map->vp->draw_clouds)
! 		    || (rightnow == 35 && !map->vp->draw_winds)
! 		    || (rightnow == 36 && !map->vp->draw_cover))
! 		  continue;
  
! 		/* Dont update cells outside the current gworld */
! 		if (!cell_is_in_gworld(map, x, y))
! 		  continue;
  
! 		/* Find the max number of cells a unit name can occupy at this mag */
! 		if (map->vp->draw_names) {
! 			switch(map->vp->power) {
! 				case 7: 	cells = 2; break; 	/* 128 x 128 hexes */
! 				case 6: 	cells = 3; break;		/*      64 x 64 hexes */	
! 				case 5: 	cells = 4; break;		/*      32 x 32 hexes */
! 				case 4: 	cells = 4; break;		/*      16 x 16 hexes */
! 				case 3: 	cells = 8; break;		/*         8 x  8  hexes */
! 				default: 	cells = 1; break;
! 			}
! 		}
! 		/* Compute leftcells now in case we skip the erasing row */
! 		leftcells = cells - 1;
  
! 		/* Skip erasing row if name erasing was not called for */
! 		if (!map->erase_names)
! 		  cells = 1;
  
! 		/* Check if erasing row really is needed, but only if we have one */
! 		if (cells > 1) {
! 			/* First check if there is a named unit at (x, y)*/
! 			for_all_stack(xw, y, unit) 
! 				name = (unit->name != NULL);
! 			/* Check adjacent hexes. Stop as soon as a named unit is found */
! 			if (!name && inside_area(x, y + 1))
! 				for_all_stack(xw, y + 1, unit) 
! 				  name = (unit->name != NULL);	/* NE hex */
! 			if (!name && inside_area(x - 1, y + 1))	
! 				for_all_stack(wrapx(x - 1), y + 1, unit) 
! 				  name = (unit->name != NULL);	/* NW hex */
! 			if (!name && inside_area(x - 1, y))	
! 				for_all_stack(wrapx(x - 1), y, unit) 
! 				  name = (unit->name != NULL);	/* W hex */
! 			if (!name && inside_area(x + 1, y))	
! 				for_all_stack(wrapx(x + 1), y, unit) 
! 				  name = (unit->name != NULL);	/* E hex */
! 			if (!name && inside_area(x, y - 1))	
! 				for_all_stack(xw, y - 1, unit) 
! 				  name = (unit->name != NULL);	/* SW hex */
! 			if (!name && inside_area(x + 1, y - 1))	
! 				for_all_stack(wrapx(x + 1), y - 1, unit) 
! 				  name = (unit->name != NULL);	/* SE hex */
! 			/* No named units in adjacent hexes. A named unit could not */
! 			/* have left (x, y) in this step, thus we skip the erasing row */
! 			if (!name)
! 			  cells = 1;
! 		}
! 
! 		GO_OFFSCREEN(map);
! 
! 		/* First draw a row of cells starting at (x, y) in order to
! 		   erase the name of any unit that moved out of that cell */
! 		draw_row(map, x, y, cells, TRUE);
! 
! 		/* Re-draw gridlines & shorelines for the (cells + 1) hexes
! 		   below the updated row that were erased by the update */				
! 		for (i = x; i < x + cells + 1; i++) {
! 
! 			/* Draw grid explicitly if asked to and the quick method using smaller cells doesn't work. */
! 			if (map->vp->draw_grid 
! 				&& 	(map->erase_names 					/* Leaks into the grid. */
! 					|| !grid_matches_unseen 				/* Can't use quick method. */
! 					|| map->vp->angle!= 90				/* Can't use quick method.  */
! 			    		|| map->vp->draw_plans 				/* Leaks into the grid. */	
! 			    		|| map->vp->draw_ai 					/* Leaks into the grid. */
! 			    		|| map->vp->draw_elevations)) {			/* Leaks into the grid. */
! 			  			draw_gridlines(map, i, y - 1);
! 			}
! 			/* Always draw shorelines if asked to. */
! 			if (map->shorelines) {
! 				draw_shorelines(map, i, y - 1);
! 			}
! 		}
! 
! 		/* Re-draw any named units in the (leftcells) hexes to the */
! 		/* left of (x, y) whose names were erased by the update */
! 		/* Note: this is done even if erase_names is not set! */
! 		if (map->vp->draw_names) {
! 			for (i = x - leftcells; i <  x; i++) {
! 				for_all_stack(wrapx(i), y, unit) {
! 					if (unit->name)	{							
! 						draw_unit_names_only(map, i, y);
! 						break;
! 					}
! 				}
! 			}
! 		}					
! 
! 		/* Re-draw any selected units within the updated row */
! 		for (i = 0; i < map->numselections; ++i) {
! 			unit = map->selections[i];
! 			for (j = 0; j < cells; j++) {
! 				if (unit && unit->x ==  wrapx(x + j) && unit->y == y) {
! 					draw_selected_unit(map, unit);
! 				}						
! 			}
! 		}
  
+ 		RETURN_ONSCREEN(map);
+ 
+ 		/* Find the pixel coordinates of (x, y) */
+ 		xform(map, x, y, &sx1, &sy1);
+ 
+ 		/* Set destRect to enclose the redrawn row of cells */
+ 		SetRect(&destRect, 
+ 				sx1 - 2, sy1 - 2,			/* Add 2 for W & N shorelines */ 	
+ 				sx1 + cells * map->vp->hw, 
+ 				sy1 + map->vp->hh + 4);		/* Add 4 for SE & SW shorelines */
+ 
+ 		/* Now copy offscreen rect to window */
+ 		copy_from_gworld(map, destRect);			
+ 
+ 		/* Update unit info line */
+ 		if (map->numselections > 0) {
+ 			unit = map->selections[0];
+ 			if (in_play(unit) && unit->x == xw && unit->y == y) {
+ 				draw_unit_info(map);
+ 			}
+ 		}
+ 	}
  	SetPort(oldport);
  }
+ 
+ /* Called by update_cell_display and draw_unselected_unit. Draws only the names for named units in (x, y).
+    Based on merged draw_units & draw_unit_and_occs that have been trimmed down
+    Unlike draw_unit_and_occs there is no recursion since names of occs are not shown. */
+ 		
+ void
+ draw_unit_names_only(Map *map, int x, int y)
+ {
+ 	int xw = wrapx(x), sx, sy, sw, sh, sx2, sy2, sw2, sh2;
+ 	Rect tmprect;
+ 	Unit *unit;
+ 
+ 	if (!map->see_all &! units_visible(dside, xw, y))
+ 	  return;
+ 	unit = unit_at(xw, y);
+ 	if (unit == NULL)
+ 	  return;
+ 	xform(map, x, y, &sx, &sy);
+ 
+ 	/* Draws unit names at small mags where contents of grouping boxes is not shown */
+ 	if (map->vp->uw <= 16) {
+ 		/* Adjust to unit part of cell. */
+ 		sw = map->vp->uw;  sh = map->vp->uh;
+ 		sx += (map->vp->hw - sw) / 2;  sy += (map->vp->hh - sw) / 2;
+ 		/* Always draw city and town names at uniform size */
+ 		if (!mobile(unit->type)) {
+ 		  UNWRAP_SX(map, sx,
+ 			draw_unit_name(unit, sx, sy, map->vp->uw, map->vp->uh, 
+ 		  				 map->textmasks, map->optimize_fonts)); 
+ 		} else {
+ 		  UNWRAP_SX(map, sx,
+ 			draw_unit_name(unit, sx, sy, sw, sh, 
+ 						 map->textmasks, map->optimize_fonts));
+ 		}
+ 	} else {
+ 		/* Draw unit names at mediun and high mags. */
+ 		for_all_stack(xw, y, unit) {
+ 			m_xform_unit(map, unit, &sx, &sy, &sw, &sh);
+ 
+ 			/* Draws the name of a boxed carrier with visible occupants */
+ 			if (unit->occupant
+ 				&& sw > 8
+ 				&& (dside->see_all
+ 					|| unit->side == dside
+ 					|| u_see_occupants(unit->type)
+ 					|| side_owns_occupant(dside, unit))) {
+ 				/* Transform carrier to the UL quarter of the box */
+ 				m_xform_occupant(map, unit, unit, sx, sy, sw, sh, &sx2, &sy2, &sw2, &sh2);
+ 				/* Always draw city and town names at uniform size */
+ 				if (!mobile(unit->type)) {
+ 				  UNWRAP_SX(map, sx,
+ 					draw_unit_name(unit, sx, sy, map->vp->uw, map->vp->uh, 
+ 				  				 map->textmasks, map->optimize_fonts));  
+ 				} else {
+ 				  /* sw2 doubled moves the name out of the box so that it can be read more easily */
+ 
+ 				  UNWRAP_SX(map, sx2,
+ 				  	draw_unit_name(unit, sx2, sy2, 2 * sw2, sh2,
+ 				  				  map->textmasks, map->optimize_fonts)); 
+ 				}
+ 			} else {
+ 				/* Draw the names of all other units. */
+ 				/* Always draw city and town names at uniform size */
+ 				if (!mobile(unit->type)) {
+ 				  UNWRAP_SX(map, sx,
+ 				  	draw_unit_name(unit, sx, sy, map->vp->uw, map->vp->uh, 
+ 				  				 map->textmasks, map->optimize_fonts));  
+ 				} else {
+ 
+ 				  UNWRAP_SX(map, sx,
+ 				  	draw_unit_name(unit, sx, sy, sw, sh, 
+ 				  				 map->textmasks, map->optimize_fonts));
+ 				}
+ 			}
+ 		}
+ 	}
+ }
+ 
diff -rcN xconq-7.2.1/mac/macmenus.c xconq-7.2.2/mac/macmenus.c
*** xconq-7.2.1/mac/macmenus.c	Mon Apr  6 01:19:31 1998
--- xconq-7.2.2/mac/macmenus.c	Sun May 31 16:10:50 1998
***************
*** 134,140 ****
  
  int numwindows;
  
! Map *worldmap = NULL;
  
  WindowPtr worldmapwin = nil;
  
--- 134,146 ----
  
  int numwindows;
  
! // --- WORLD MAP CRASH FIX ---------------------------
! 
! extern Map *worldmap = NULL;	/* Needed in macmap.c. */
! 
! //	  Map *worldmap = NULL;
! 
! // ------------------------------------------------
  
  WindowPtr worldmapwin = nil;
  
***************
*** 798,804 ****
  worldmapwin == nil alone does not work here.  
  */
  					/* Also test for worldmap->id == 0 */
! 					if (worldmapwin == nil || worldmap->id == 0) {
  
  						/* winwid should equal the default size of new windows */
  						int power, winwid, mainwidth;
--- 804,818 ----
  worldmapwin == nil alone does not work here.  
  */
  					/* Also test for worldmap->id == 0 */
! 
! // --- WORLD MAP CRASH FIX -------------------------------------------------
! 
! 					/* Destroy_map now explicitly sets worldmap = NULL! */
! 					if (worldmapwin == nil || worldmap == NULL || worldmap->id == 0) {
! 
! //					if (worldmapwin == nil || worldmap->id == 0) {
! 
! // ---------------------------------------------------------------------
  
  						/* winwid should equal the default size of new windows */
  						int power, winwid, mainwidth;
diff -rcN xconq-7.2.1/mac/macmouse.c xconq-7.2.2/mac/macmouse.c
*** xconq-7.2.1/mac/macmouse.c	Wed Dec 31 16:00:00 1969
--- xconq-7.2.2/mac/macmouse.c	Thu May 21 04:57:19 1998
***************
*** 0 ****
--- 1,1230 ----
+ /* 	Mouse-driven user interaction for the Mac interface to Xconq.
+ 
+ 	This file now ONLY contains user interaction code for the mouse
+ 	such as clicking, dragging, selecting, scrolling and toggling items.
+      	It has therefore been renamed from macmap2.c to macmouse.c.    
+ 	All other map-related functions have been moved to macmap.c.
+      
+ 	Copyright (C) 1992-1998 Stanley T. Shebs.
+ 
+ Xconq is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.  See the file COPYING.  */
+ 
+ #include "conq.h"
+ #include "kpublic.h"
+ #include "macconq.h"
+ 
+ #undef DEF_CMD
+ #define DEF_CMD(letter,name,args,FN,help) extern void FN(void);
+ 
+ #include "cmd.def"
+ #include "maccmd.def"
+ 
+ static int selrect;
+ static int downx, downy, downdir;
+ static void drag_for_distance(Map *map, int h0, int v0);
+ 
+ extern void set_position_modally(void);
+ extern int side_owns_occupant PARAMS ((Side *side, Unit *unit));
+ extern int mapnum;
+ extern int nummaps;
+ 
+ int topunithgt;
+ Map *curmap;
+ ControlActionUPP map_scroll_proc;
+ 
+ /* This scroll proc is shared by both the horizontal and vertical scrollbars. */
+ 
+ static pascal void
+ map_scroll_fn(ControlHandle control, short code)
+ {
+ 	int pagesize, jump;
+ 
+ 	/* The page jump should be most but not all of a screenful. */
+ 	if (control == curmap->hscrollbar)
+ 	  pagesize = (3 * curmap->vp->pxw) / 4;
+ 	else
+ 	  pagesize = (3 * curmap->vp->pxh) / 4;
+ 	/* Adjust the pagesize to always be a multiple of 4. */
+ 	pagesize = ((pagesize + 3) / 4) * 4;
+ 
+ 	switch (code) {
+ 		case inPageDown:
+ 			jump = pagesize;
+ 			break;
+ 		case inDownButton:
+ 			jump = 4;
+ 			break;
+ 		case inPageUp:
+ 			jump = 0 - pagesize;
+ 			break;
+ 		case inUpButton:
+ 			jump = -4;
+ 			break;
+ 		default:
+ 			jump = 0;
+ 			break;
+ 	}
+ 	if (control == curmap->hscrollbar) {
+ 		scroll_map_window(curmap, jump, 0);
+ 	} else if (control == curmap->vscrollbar){
+ 		scroll_map_window(curmap, 0, jump);
+ 	}
+ }
+ 
+ void
+ scroll_best_map_to_unit(Unit *unit, int bringtofront)
+ {
+ 	Map *map, *bestmap;
+ 	GrafPtr	oldport;
+ 	
+ 	/* Find the "best" (highest power, unit already visible) map to scroll over
+ 	   to the unit. */
+ 	bestmap = maplist;
+ 	for_all_maps(map) {
+ 		if (map->vp->power > bestmap->vp->power
+ 		    || (map->vp->power == bestmap->vp->power
+ 		        && in_middle(map, unit->x, unit->y)
+ 			 	&& !in_middle(bestmap, unit->x, unit->y))) {
+ 			bestmap = map;
+ 		}
+ 	}
+ 	/* We have a map, now make it show the unit. */
+ 	if (!in_middle(bestmap, unit->x, unit->y)) {
+ 		/* Save the current port. */
+ 		GetPort(&oldport);
+ 		/* Important or junk may appear in the list window. */
+ 		SetPort(bestmap->window);
+ 		scroll_to_unit(bestmap, unit);
+ 		/* Force a gworld update of the whole map content to
+ 		   make sure the scrolled region is updated properly. */
+ 		copy_from_gworld(bestmap, bestmap->contentrect);
+ 		SetPort(oldport);
+ 	}
+ 	if (bringtofront) {
+ 		SelectWindow(bestmap->window);
+ 		update_window(bestmap->window);
+ 		adjust_menus();
+ 	}
+ }
+ 
+ /* Scroll the given map over to display the given unit. */
+ 
+ void
+ scroll_to_unit(Map *map, Unit *unit)
+ {
+ 	int oldsx = map->vp->sx, oldsy = map->vp->sy;
+ 	int	newsx, newsy;
+ 	
+ 	/* Return if unit is not at all on the map */
+ 	if (!inside_area(unit->x, unit->y))
+ 	  return;
+ 
+ 	/* Dont scroll if the unit already is in the window */
+ 	if (in_middle(map, unit->x, unit->y))
+ 	  return;
+ 
+ 	/* Find new vp */
+ 	set_view_focus(map->vp, unit->x, unit->y);
+ 	m_center_on_focus(map);
+ 	newsx = map->vp->sx;
+ 	newsy = map->vp->sy;
+ 
+ 	/* Return if position is unchanged */
+ 	if (oldsx == newsx && oldsy == newsy)
+ 	  return;
+ 	
+ 	/* Restore old vp and let scroll_map_window do the job */
+ 	map->vp->sx = oldsx;
+ 	map->vp->sy = oldsy;
+ 	
+ 	scroll_map_window(map, newsx - oldsx, newsy - oldsy);
+ }
+ 
+ /* Handle a mouse down in the map window. */
+ 
+ void
+ do_mouse_down_map(Map *map, Point mouse, int mods)
+ {
+ 	short part;
+ 	int newsx, newsy, dummy;
+ 	ControlHandle control;
+ 
+ 	if (map_scroll_proc == NULL) 
+ 	  map_scroll_proc = NewControlActionProc(map_scroll_fn);
+ 	part = FindControl(mouse, map->window, &control);
+ 
+ 	/* Horizontal scrollbar */
+ 	if (control == map->hscrollbar) {
+ 		switch (part) {
+ 			case inThumb:
+ 				part = TrackControl(control, mouse, NULL);
+ 				if (part == inThumb) {
+ 					/* Get apparent newsx from the new thumb position */
+ 					newsx = GetCtlValue(control);
+ 					/* Correct newsx for scrollbar scaling used to fix the 32K limit bug */				
+ 					dummy = map->vp->sxmax;
+ 					while (dummy > 32000) {	
+ 						dummy /= 2;
+ 						newsx *= 2;	/* Simulates the scaling but in reverse */
+ 					}		
+ 					/* Scroll the map window within its gworld */
+ 					scroll_map_window(map, newsx - map->vp->sx, 0);
+ 				}
+ 				break;
+ 			default:
+ 				curmap = map;
+ 				part = TrackControl(control, mouse, map_scroll_proc);
+ 				break;
+ 		}
+ 
+ 	/* Vertical scrollbar */
+ 	} else if (control == map->vscrollbar) {
+ 		switch (part) {
+ 			case inThumb:
+ 				part = TrackControl(control, mouse, NULL);
+ 				if (part == inThumb) {
+ 					/* Get apparent newsy from the new thumb position */
+ 					newsy = GetCtlValue(control);
+ 					/* Correct newsy for scrollbar scaling used to fix the 32K limit bug */				
+ 					dummy = map->vp->symax;
+ 					while (dummy > 32000) {	
+ 						dummy /= 2;
+ 						newsy *= 2;	/* Simulates the scaling but in reverse */
+ 					}		
+ 					/* Scroll the map window within its gworld */
+ 					scroll_map_window(map, 0, newsy - map->vp->sy);
+ 				}
+ 				break;
+ 			default:
+ 				curmap = map;
+ 				part = TrackControl(control, mouse, map_scroll_proc);
+ 				break;
+ 		}
+ 	} else if (mouse.h <= conwid) {
+ 		/* Interpret as a control panel hit. */
+ 		do_mouse_down_map_control_panel(map, mouse.h, mouse.v, mods);
+ 	} else {
+ 		do_mouse_down_map_content(map, mouse.h, mouse.v, mods);
+ 	}
+ }
+ 
+ void
+ do_mouse_down_map_control_panel(Map *map, int h, int v, int mods)
+ {
+ 	int winh = map->window->portRect.bottom - map->window->portRect.top;
+ 
+ 	/* (should better organize tests here) */
+ 	if (between(winh - 2 * sbarwid, v, winh)) {
+ 		switch ((winh - v) / sbarwid) {
+ 			case 0:
+ 				magnify_map(map, ((h < conwid / 2) ? -1 : 1));
+ 				break;
+ #if 0
+ 			/* This was too confusing here, so it's now flushed.  However, the
+ 			   capability still seems worthwhile, so it should reappear elsewhere. */
+ 			case 1:
+ 				map_modal = ZOOM_MODAL;
+ 				break;
+ #endif
+ 		}
+ 	} else if (v < 32) {
+ 		toggle_survey(map);
+ 	} else if ((v - 32) < 5 * 15) {
+ 		switch ((v - 32) / 15) {
+ 			case 0:
+ 				if (h < conwid / 2) {
+ 					select_previous_awake_mover(map);
+ 				} else {
+ 					select_next_awake_mover(map);
+ 				}
+ 				break;
+ 			case 1:
+ 				if (h < conwid / 2) {
+ 					select_previous_mover(map);
+ 				} else {
+ 					select_next_mover(map);
+ 				}
+ 				break;
+ 			case 2:
+ 				if (h < conwid / 2) {
+ 					select_previous_actor(map);
+ 				} else {
+ 					select_next_actor(map);
+ 				}
+ 				break;
+ 			case 3:
+ 				if (h < conwid / 2) {
+ 					select_previous_unit(map);
+ 				} else {
+ 					select_next_unit(map);
+ 				}
+ 				break;
+ 			case 4:
+ 				beep();
+ 				break;
+ 		}
+ 
+ 	} else if (v - 32 - 5*15 - 2 - 7/*why?*/ < 9 * 11) {
+ 		switch ((v - 32 - 5*15 - 2 - 7/*why?*/) / 11) {
+ 
+ 			case 0:
+ 				toggle_map_grid(map);
+ 				break;
+ 			case 1:
+ 				map->vp->draw_names = !map->vp->draw_names;
+ 				/* Also toggle featurenames if it had the same old setting as drawnames */
+ 				/* but let it alone if the setting already was different */
+ 				if (map->featurenames != map->vp->draw_names)
+ 			 	      map->featurenames = !map->featurenames;
+ 				force_map_update(map);
+ 				break;
+ 			case 2:
+ 				toggle_map_people(map);
+ 				break;
+ 			case 3:
+ 				toggle_map_control(map);
+ 				break;
+ 			case 4:
+ 				toggle_map_plans(map);
+ 				break;
+ 			case 5:
+ 				toggle_map_ai(map);
+ 				break;
+ 			case 6:
+ 				if (dside->may_set_see_all) {
+ 					map->see_all = !map->see_all;
+ 					force_map_update(map);
+ 				}
+ 				break;
+ 			case 7:
+ 				toggle_map_sidecolors(map);
+ 				break;
+ 			case 8:
+ 				map->iconmasks = !map->iconmasks;
+ 				/* Also toggle boxmasks if it had the same old setting as iconmasks */
+ 				/* but let it alone if the setting already was different */
+ 				if (map->boxmasks != map->iconmasks)
+ 				      map->boxmasks = !map->boxmasks;
+ 				/* Also toggle textmasks if it had the same old setting as iconmasks */
+ 				/* but let it alone if the setting already was different */
+ 				if (map->textmasks != map->iconmasks)
+ 				      map->textmasks = !map->textmasks;
+ 				force_map_update(map);
+ 				break;
+ 		}
+ 	} else {
+ 		/* Unused area, ignore */
+ 	}
+ }
+ 
+ void
+ toggle_survey(Map *map)
+ {
+ 	int i;
+ 	Unit *unit;
+ 
+ 	map->moveonclick = !map->moveonclick;
+ 	map->autoselect = !map->autoselect;
+ 	draw_control_panel(map);
+ 	if (map->autoselect) {
+ 		if (map->numselections > 0) {
+ 			for (i = 0; i < map->numselections; ++i) {
+ 				unit = map->selections[i];
+ 				if (unit != NULL) {
+ 					map->curunit = autonext_unit(dside, unit);
+ 					select_exactly_one_unit(map, map->curunit);
+ 				}
+ 			}
+ 		}
+ 	} else {
+ 		/* Update appearance of selections. */
+ 		draw_selections(map);
+ 	}
+ }
+ 
+ void
+ magnify_map(Map *map, int inout)
+ {
+ 	set_map_mag(map, map->vp->power + inout);
+ }
+ 
+ /* This sets the map's magnification directly and updates it. */
+ 
+ void
+ set_map_mag(Map *map, int newpower)
+ {
+ 	newpower = clip_to_limits(0, newpower, NUMPOWERS-1);
+ 	if (map->vp->power != newpower) {
+ 	
+ 		/* Erase other-map boxes in other windows */
+ 		draw_related_maps(map);
+ 		
+ 		set_map_power(map, newpower);
+ 		m_center_on_focus(map);
+ 		set_map_scrollbars(map);
+ 
+ 		/* Update the gworld (and the map) */
+ 		update_gworld(map);
+ 
+ 		/* Redraw other-map boxes in other windows */
+ 		draw_related_maps(map);
+ 		
+ 	}
+ }
+ 
+ void
+ toggle_map_grid(Map *map)
+ {
+ 	map->vp->draw_grid = !map->vp->draw_grid;
+ 	/* (should not do a total redraw?) */
+ 	force_map_update(map);
+ }
+ 
+ void
+ toggle_map_topline(Map *map)
+ {
+ 	Rect tmprect;
+ 	RgnHandle tmprgn;
+ 	GrafPtr oldport;
+ 	int oldtoph = map->toph;
+ 
+ 	map->draw_topline = !map->draw_topline;
+ 	map->toplineh = (map->draw_topline ? tophgt : 0);
+ 	/* Erase other-map boxes in other windows. */
+ 	draw_related_maps(map);
+ 	map->toph = map->toplineh + map->topunith;
+ 	/* Update without scrolling if we are expanding and the buffer is too small. */ 
+ 	if (map->bufy - map->offsety < oldtoph - map->toph) {
+ 		set_content_rect(map);
+ 		update_gworld(map);
+ 		/* This is not done by update_gworld (unlike update_resized_gworld). */
+ 		if (map->toplineh > 0)
+ 		  draw_top_line(map);
+ 		if (map->topunith > 0)
+ 		  draw_unit_info(map);
+ 	/* Always scroll the map if we are shrinking, or if the buffer is big enough. */
+ 	} else update_resized_map(map);
+ 	/* Redraw other-map boxes in other windows. */
+ 	draw_related_maps(map);
+ }
+ 
+ void
+ toggle_map_topunit(Map *map)
+ {
+ 	int oldtoph;
+ 	Rect tmprect;
+ 	RgnHandle tmprgn;
+ 	GrafPtr oldport;
+ 
+ 	oldtoph = map->toph;
+ 	map->draw_topunit = !map->draw_topunit;
+ 	map->topunith = (map->draw_topunit ? topunithgt : 0);
+ 	/* Erase other-map boxes in other windows. */
+ 	draw_related_maps(map);
+ 	map->toph = map->toplineh + map->topunith;
+ 	/* Update without scrolling if we are expanding and the buffer is too small. */ 
+ 	if (map->bufy - map->offsety < oldtoph - map->toph) {
+ 		set_content_rect(map);
+ 		update_gworld(map);
+ 		/* This is not done by update_gworld (unlike update_resized_gworld). */
+ 		if (map->toplineh > 0)
+ 		  draw_top_line(map);
+ 		if (map->topunith > 0)
+ 		  draw_unit_info(map);
+ 	/* Always scroll the map if we are shrinking, or if the buffer is big enough. */
+ 	} else update_resized_map(map);
+ 	/* Redraw other-map boxes in other windows. */
+ 	draw_related_maps(map);
+ }
+ 
+ void
+ toggle_map_other_maps(Map *map)
+ {
+ 	map->vp->draw_other_maps = !map->vp->draw_other_maps;
+ 	/* (should not do a total redraw) */
+ 	force_map_update(map);
+ }
+ 
+ void
+ toggle_map_lighting(Map *map)
+ {
+ 	map->vp->draw_lighting = !map->vp->draw_lighting;
+ 	/* We have to do a total redraw. */
+ 	force_map_update(map);
+ }
+ 
+ void
+ toggle_map_coverage(Map *map)
+ {
+ 	map->vp->draw_cover = !map->vp->draw_cover;
+ 	/* (should only change newly dimmed/lightened cells) */
+ 	force_map_update(map);
+ }
+ 
+ void
+ toggle_map_names(Map *map)
+ {
+ 	map->vp->draw_names = !map->vp->draw_names;
+ 	/* (if now on, should draw names on top of everything, don't redraw everything) */
+ 	if (map->vp->hh > 5) {
+ 		force_map_update(map);
+ 	} else {
+ 		/* (should be a force update on control panel alone) */
+ 		draw_control_panel(map);
+ 	}
+ }
+ 
+ void
+ toggle_map_people(Map *map)
+ {
+     if (!people_sides_defined())
+       return;
+ 	map->vp->draw_people = !map->vp->draw_people;
+ 	if (bwid2[map->vp->power] > 0) {
+ 		force_map_update(map);
+ 	} else {
+ 		/* (should be a force update on control panel alone) */
+ 		draw_control_panel(map);
+ 	}
+ }
+ 
+ void
+ toggle_map_control(Map *map)
+ {
+     if (!control_sides_defined())
+       return;
+ 	map->vp->draw_control = !map->vp->draw_control;
+ 	if (bwid2[map->vp->power] > 0) {
+ 		force_map_update(map);
+ 	} else {
+ 		/* (should be a force update on control panel alone) */
+ 		draw_control_panel(map);
+ 	}
+ }
+ 
+ void
+ toggle_map_elevations(Map *map)
+ {
+ 	map->vp->draw_elevations = !map->vp->draw_elevations;
+ 	force_map_update(map);
+ }
+ 
+ void
+ toggle_map_materials(Map *map, int m)
+ {
+ 	map->vp->draw_materials[m] = !map->vp->draw_materials[m];
+ 	map->vp->num_materials_to_draw += (map->vp->draw_materials[m] ? 1 : -1);
+ 	force_map_update(map);
+ }
+ 
+ void
+ toggle_map_aux_terrain(Map *map, int t)
+ {
+ 	map->vp->draw_aux_terrain[t] = !map->vp->draw_aux_terrain[t];
+ 	force_map_update(map);
+ }
+ 
+ void
+ toggle_map_temperature(Map *map)
+ {
+ 	map->vp->draw_temperature = !map->vp->draw_temperature;
+ 	force_map_update(map);
+ }
+ 
+ void
+ toggle_map_winds(Map *map)
+ {
+ 	map->vp->draw_winds = !map->vp->draw_winds;
+ 	force_map_update(map);
+ }
+ 
+ void
+ toggle_map_clouds(Map *map)
+ {
+ 	map->vp->draw_clouds = !map->vp->draw_clouds;
+ 	force_map_update(map);
+ }
+ 
+ void
+ toggle_map_storms(Map *map)
+ {
+ 	map->vp->draw_storms = !map->vp->draw_storms;
+ 	force_map_update(map);
+ }
+ 
+ void
+ toggle_map_plans(Map *map)
+ {
+ 	map->vp->draw_plans = !map->vp->draw_plans;
+ 	if (map->numselections > 0) {
+ 		force_map_update(map);
+ 	} else {
+ 		/* (should be a force update on control panel alone) */
+ 		draw_control_panel(map);
+ 	}
+ }
+ 
+ void
+ toggle_map_ai(Map *map)
+ {
+ 	if (!side_has_ai(dside))
+ 	  return;
+ 	map->vp->draw_ai = !map->vp->draw_ai;
+ 	force_map_update(map);
+ }
+ 
+ void
+ toggle_map_sidecolors(Map *map)
+ {
+ 	map->sidecolors = !map->sidecolors;
+ 	force_map_update(map);
+ }
+ 
+ void
+ toggle_iconmasks(Map *map)
+ {
+ 	map->iconmasks = !map->iconmasks;
+ 	force_map_update(map);
+ }
+ 
+ void
+ toggle_boxmasks(Map *map)
+ {
+ 	map->boxmasks = !map->boxmasks;
+ 	force_map_update(map);
+ }
+ 
+ void
+ toggle_textmasks(Map *map)
+ {
+ 	map->textmasks = !map->textmasks;
+ 	force_map_update(map);
+ }
+ 
+ void
+ toggle_featureborders(Map *map)
+ {
+ 	map->featureborders = !map->featureborders;
+ 	force_map_update(map);
+ }
+ 
+ void
+ toggle_featurenames(Map *map)
+ {
+ 	map->featurenames = !map->featurenames;
+ 	force_map_update(map);
+ }
+ 
+ void
+ toggle_shorelines(Map *map)
+ {
+ 	map->shorelines = !map->shorelines;
+ 	force_map_update(map);
+ }
+ 
+ void
+ toggle_simple_borders(Map *map)
+ {
+ 	map->simple_borders = !map->simple_borders;
+ 	force_map_update(map);
+ }
+ 
+ void
+ toggle_optimize_fonts(Map *map)
+ {
+ 	map->optimize_fonts = !map->optimize_fonts;
+ 	force_map_update(map);
+ }
+ 
+ void
+ toggle_draw_latlong(Map *map)
+ {
+ 	map->vp->draw_latlong = !map->vp->draw_latlong;
+ 	force_map_update(map);
+ }
+ 
+ void
+ toggle_solid_color_terrain(Map *map)
+ {
+ 	map->solid_color_terrain = !map->solid_color_terrain;
+ 	force_map_update(map);
+ }
+ 
+ void
+ toggle_erase_names(Map *map)
+ {
+ 	map->erase_names = !map->erase_names;
+ 	force_map_update(map);
+ }
+ 
+ void
+ do_mouse_down_map_content(Map *map, int h, int v, int mods)
+ {
+ 	int i, rslt, anysuccess;
+ 	Unit *unit;
+ 	
+ 	/* Remember this cell. */
+ 	m_nearest_cell(map, h, v, &downx, &downy);
+ 	/* Assume that last place clicked is a reasonable focus. */
+ 	if (inside_area(downx, downy)) {
+ 		map->vp->vcx = downx;  map->vp->vcy = downy;
+ 	}
+ 	if (map_modal != NO_MODAL) {
+ 		switch (map_modal) {
+ 			case ATTACK_MODAL:
+ 				set_position_modally();
+ 				do_attack();
+ 				break;
+ 			case FIRE_MODAL:
+ 				set_position_modally();
+ 				do_fire();
+ 				break;
+ 			case FIRE_INTO_MODAL:
+ 				set_position_modally();
+ 				do_fire_into();
+ 				break;
+ 			case SET_FORMATION_MODAL:
+ 				set_position_modally();
+ 				do_set_formation();
+ 				break;
+ 			case MOVE_TO_MODAL:
+ 				set_position_modally();
+ 				do_move_to_command();
+ 				break;
+ 			case ADD_TERRAIN_MODAL:
+ 				set_position_modally();
+ 				do_add_terrain();
+ 				break;
+ 			case REMOVE_TERRAIN_MODAL:
+ 				set_position_modally();
+ 				do_remove_terrain();
+ 				break;
+ 			case DISTANCE_MODAL:
+ 				drag_for_distance(map, h, v);
+ 				break;
+ 			case ZOOM_MODAL:
+ 				select_area_and_zoom(map, h, v, mods);
+ 				break;
+ 			case GENERIC_MODAL:
+ 				set_position_modally();
+ 				break;
+ 			default:
+ 				run_error("unknown modal tool %d", map_modal);
+ 				break;
+ 		}
+ 		/* Reset modality whether or not the command succeeded, otherwise
+ 		   the player can get caught here if no commands can succeed. */
+ 		map_modal = NO_MODAL;
+ 	} else if (mods & cmdKey) {
+ 		if (map->moveonclick && map->autoselect) {
+ 			unselect_all(map);
+ 			m_nearest_unit(map, h, v, &unit);
+ 			if (unit != NULL && (side_controls_unit(dside, unit) || endofgame)) {
+ 				/* The nearest unit will become the "current unit". */
+ 				map->curunit = unit;
+ 				select_unit_on_map(map, unit);
+ 				draw_selections(map);
+ 				move_on_drag(map, unit, mods);
+ 			} else {
+ 				select_all_dragged_over(map, h, v, mods);
+ 				/* Pick the first of the multiple selection as the "current unit". */
+ 				if (map->numselections > 0) {
+ 					map->curunit = map->selections[0];
+ 				}
+ 			}
+ 		} else {
+ 			anysuccess = FALSE;
+ 			for (i = 0; i < map->numselections; ++i) {
+ 				if ((unit = map->selections[i]) != NULL) {
+ 					rslt = move_the_selected_unit(map, unit, h, v);
+ 					if (rslt)
+ 					  anysuccess = TRUE;
+ 				}
+ 			}
+ 			if (!anysuccess)
+ 			  beep();
+ 		}
+ 	} else if (mods & optionKey) {
+ 		for (i = 0; i < map->numselections; ++i) {
+ 			if ((unit = map->selections[i]) != NULL) {
+ 				fire_the_selected_unit(map, unit, h, v);
+ 			}
+ 		}
+ 	} else if (mods & shiftKey) {
+ 		m_nearest_unit(map, h, v, &unit);
+ 		if (unit && side_sees_unit(dside, unit)) {
+ 			/* Invert the selection status of the unit. */
+ 			if (unit_is_selected(map, unit)) {
+ 				unselect_unit_on_map(map, unit);
+ 				erase_selection(map, unit);
+ 			} else {
+ 				select_unit_on_map(map, unit);
+ 				draw_selections_at(map, unit->x, unit->y);
+ 			}
+ 			draw_unit_info(map);
+ 		} else {
+ 			select_all_dragged_over(map, h, v, mods);
+ 		}
+ 
+ 	/* Focus on clicked point and select closest own unit if control key is down. */
+ 	} else if (mods & controlKey) {
+ 
+ 		long unitdist, mindist = 32000;
+ 
+ 		/* Focus on clicked point */
+ 		set_focus(map, downx, downy);
+ 		/* Find nearest own unit and select it */
+ 	    	for (i = 0; i < dside->actionvector->numunits; ++i) {
+ 	    		unit = (dside->actionvector->units)[i].unit;
+    			 if (could_be_next_unit(unit) && side_controls_unit(dside, unit)) {
+ 				/* Use least square method */
+ 				unitdist = (downx - unit->x) * (downx - unit->x) + 
+ 					        (downy - unit->y) * (downy - unit->y);
+ 				if (unitdist < mindist) {
+ 					mindist = unitdist;
+ 					unselect_all(map);
+ 					map->curunit = unit;
+ 				}
+ 		    	}
+ 	    	}
+ 		select_unit_on_map(map, map->curunit);
+ 		draw_selections(map);
+ 
+ 	} else {
+ 		/* Interpret an unmodified mouse down. */
+ #ifdef DESIGNERS
+ 		if (is_designer(dside) && tooltype != notool) {
+ 			apply_designer_tool(map, h, v, mods);
+ 		} else
+ #endif /* DESIGNERS */
+ 		if (map->moveonclick && !is_designer(dside)) {
+ 			/* Usually will only be one to move, but be general anyway. */
+ 			anysuccess = FALSE;
+ 			for (i = 0; i < map->numselections; ++i) {
+ 				if ((unit = map->selections[i]) != NULL) {
+ 					rslt = move_the_selected_unit(map, unit, h, v);
+ 					if (rslt)
+ 					  anysuccess = TRUE;
+ 				}
+ 			}
+ 			if (!anysuccess)
+ 			  beep();
+ 			map->scrolltocurunit = TRUE;
+ 		} else {
+ 			unselect_all(map);
+ 			m_nearest_unit(map, h, v, &unit);
+ 			if (unit != NULL && (side_controls_unit(dside, unit) || endofgame)) {
+ 				select_unit_on_map(map, unit);
+ 				draw_selections(map);
+ 				move_on_drag(map, unit, mods);
+ 			} else {
+ 				select_all_dragged_over(map, h, v, mods);
+ 			}
+ 		}
+ 	}
+ }
+ 
+ void
+ select_all_dragged_over(Map *map, int h0, int v0, int mods)
+ {
+ 	Point pt0, pt1, newmouse;
+ 	int drawn = FALSE;
+ 	Rect tmprect;
+ 
+ 	SetPt(&pt0, h0, v0);
+ 	SetPt(&pt1, h0, v0);
+ 	SetRect(&tmprect, h0, v0, h0, v0);
+ 	/* (should be a generic subr?) */
+ 	PenMode(patXor);
+ 	PenPat(QDPat(gray));
+ 	while (WaitMouseUp()) {
+ 		GetMouse(&newmouse);
+ 		if (!EqualPt(pt1, newmouse) /* && PtInRect(newmouse, &(map->window->portRect)) */) {
+ 			if (drawn) {
+ 				tmprect.left = min(pt0.h, pt1.h);  tmprect.top = min(pt0.v, pt1.v);
+ 				tmprect.right = max(pt0.h, pt1.h);  tmprect.bottom = max(pt0.v, pt1.v);
+ 				FrameRect(&tmprect);
+ 			}
+ 			pt1 = newmouse;
+ 			tmprect.left = min(pt0.h, pt1.h);  tmprect.top = min(pt0.v, pt1.v);
+ 			tmprect.right = max(pt0.h, pt1.h);  tmprect.bottom = max(pt0.v, pt1.v);
+ 			FrameRect(&tmprect);
+ 			drawn = TRUE;
+ 		}
+ 	}
+ 	if (drawn) {
+ 		tmprect.left = min(pt0.h, pt1.h);  tmprect.top = min(pt0.v, pt1.v);
+ 		tmprect.right = max(pt0.h, pt1.h);  tmprect.bottom = max(pt0.v, pt1.v);
+ 		FrameRect(&tmprect);
+ 	}
+ 	PenNormal();
+ 	select_all_units_in_rect(map, &tmprect);
+ }
+ 
+ void
+ select_area_and_zoom(Map *map, int h0, int v0, int mods)
+ {
+ 	Point pt0, pt1, newmouse;
+ 	int drawn = FALSE, x, y;
+ 	Rect tmprect;
+ 
+ 	SetPt(&pt0, h0, v0);
+ 	SetPt(&pt1, h0, v0);
+ 	/* (should be a generic subr) */
+ 	PenMode(patXor);
+ 	PenPat(QDPat(gray));
+ 	while (WaitMouseUp()) {
+ 		GetMouse(&newmouse);
+ 		if (!EqualPt(pt1, newmouse) /* && PtInRect(newmouse, &(map->window->portRect)) */) {
+ 			if (drawn) {
+ 				tmprect.left = min(pt0.h, pt1.h);  tmprect.top = min(pt0.v, pt1.v);
+ 				tmprect.right = max(pt0.h, pt1.h);  tmprect.bottom = max(pt0.v, pt1.v);
+ 				FrameRect(&tmprect);
+ 			}
+ 			pt1 = newmouse;
+ 			tmprect.left = min(pt0.h, pt1.h);  tmprect.top = min(pt0.v, pt1.v);
+ 			tmprect.right = max(pt0.h, pt1.h);  tmprect.bottom = max(pt0.v, pt1.v);
+ 			FrameRect(&tmprect);
+ 			drawn = TRUE;
+ 		}
+ 	}
+ 	if (drawn) {
+ 		tmprect.left = min(pt0.h, pt1.h);  tmprect.top = min(pt0.v, pt1.v);
+ 		tmprect.right = max(pt0.h, pt1.h);  tmprect.bottom = max(pt0.v, pt1.v);
+ 		FrameRect(&tmprect);
+ 	}
+ 	PenNormal();
+ 	m_nearest_cell(map, pt1.h, pt1.v, &x, &y);
+ 	if (x != downx && y != downy) {
+ 		magnify_to_fit(map, downx, downy, x, y);
+ 	}
+ }
+ 
+ /* This routine changes a map's viewport and magnification to fit the given rectangle. */
+ 
+ void
+ magnify_to_fit(Map *map, int x1, int y1, int x2, int y2)
+ {
+ 	int wid, hgt, wanted, power;
+ 
+ 	DGprintf("Magnifying map to fit in area %d,%d - %d,%d\n", x1, y1, x2, y2);
+ 	/* (still need to do y/2 correction) */
+ 	wid = abs(x2 - x1) + 1;  hgt = abs(y2 - y1) + 1;
+ 	map->vp->vcx = min(x1, x2) + wid / 2;  map->vp->vcy = min(y1, y2) + hgt / 2;
+ 	/* Compute the "ideal" size of a displayed cell. */
+ 	wanted = min(map->vp->pxw / wid, map->vp->pxh / hgt);
+ 	/* Search for the best approximation. */
+ 	for (power = NUMPOWERS-1; power > 0; --power) {
+ 		if (hws[power] < wanted) break;
+ 	}
+ 	set_map_mag(map, power);
+ }
+ 
+ void
+ move_on_drag(Map *map, Unit *unit, int mods)
+ {
+ 	int sx, sy, sw, sh, h0, v0, drawn = FALSE, x, y;
+ 	Point pt0, pt1, newmouse;
+ 
+ 	m_xform_unit_self(map, unit, &sx, &sy, &sw, &sh);
+ 	h0 = sx + sw / 2;  v0 = sy + sh / 2;
+ 	SetPt(&pt0, h0, v0);
+ 	SetPt(&pt1, h0, v0);
+ 	/* (should be a generic subr?) */
+ 	PenMode(patXor);
+ 	while (WaitMouseUp()) {
+ 		GetMouse(&newmouse);
+ 		/* should scroll, then abort if we drag outside the window */
+ 		if (0 /* PtInRect(newmouse, &(map->window->portRect)) */) {
+ 		}
+ 		if (!EqualPt(pt1, newmouse)) {
+ 			if (drawn) {
+ 				MoveTo(h0, v0);  LineTo(pt1.h, pt1.v);
+ 			}
+ 			pt1 = newmouse;
+ 			MoveTo(h0, v0);  LineTo(pt1.h, pt1.v);
+ 			drawn = TRUE;
+ 		}
+ 	}
+ 	/* Erase the last drawn line. */
+ 	if (drawn) {
+ 		MoveTo(h0, v0);  LineTo(pt1.h, pt1.v);
+ 	}
+ 	PenNormal();
+ 	m_nearest_cell(map, pt1.h, pt1.v, &x, &y);
+ 	if (x != downx || y != downy) {
+ 		if (!move_the_selected_unit(map, unit, pt1.h, pt1.v))
+ 		  beep();
+ 	} else {
+ 		/* (should try to enter another unit in this cell) */
+ 	}
+ }
+ 
+ void
+ drag_for_distance(Map *map, int h0, int v0)
+ {
+ 	Point pt0, pt1, newmouse;
+ 	int drawn = FALSE, x, y;
+ 
+ 	SetPt(&pt0, h0, v0);
+ 	SetPt(&pt1, h0, v0);
+ 	/* (should be a generic subr) */
+ 	PenMode(patXor);
+ 	PenPat(QDPat(gray));
+ 	while (WaitMouseUp()) {
+ 		GetMouse(&newmouse);
+ 		/* should scroll, then abort if we drag outside the window */
+ 		if (0 /* PtInRect(newmouse, &(map->window->portRect)) */) {
+ 		}
+ 		if (!EqualPt(pt1, newmouse)) {
+ 			if (drawn) {
+ 				MoveTo(h0, v0);  LineTo(pt1.h, pt1.v);
+ 			}
+ 			pt1 = newmouse;
+ 			MoveTo(h0, v0);  LineTo(pt1.h, pt1.v);
+ 			drawn = TRUE;
+ 		}
+ 	}
+ 	/* Erase the last drawn line. */
+ 	if (drawn) {
+ 		MoveTo(h0, v0);  LineTo(pt1.h, pt1.v);
+ 	}
+ 	PenNormal();
+ 	m_nearest_cell(map, pt1.h, pt1.v, &x, &y);
+ 	notify(dside, "Distance from %d,%d to %d,%d is %d",
+ 		   downx, downy, x, y, distance(downx, downy, x, y));
+ }
+ 
+ void
+ unselect_all(Map *map)
+ {
+ 	int num = map->numselections;
+ 
+ 	if (map->numselections > 0) {
+ 		erase_selections(map);
+ 		map->numselections = 0;
+ 		draw_unit_info(map);
+ 	}
+ }
+ 
+ /* Add the given unit to the array of units selected in the given map.  If we need
+    more space, then grow the array by 50%. */
+ 
+ void
+ select_unit_on_map(Map *map, Unit *unit)
+ {
+ 	if (map->numselections >= map->maxselections) {
+ 		int newsize = map->maxselections + map->maxselections / 2;
+ 		Unit **newarray = (Unit **) realloc((char *) map->selections, newsize * sizeof(Unit *));
+ 
+ 		if (newarray == NULL) {
+ 			run_warning("couldn't realloc map selection array");
+ 			return;
+ 		}
+ 		map->maxselections = newsize;
+ 		map->selections = newarray;
+ 	}
+ 	map->selections[map->numselections++] = unit;
+ }
+ 
+ int
+ unit_is_selected(Map *map, Unit *unit)
+ {
+ 	int i;
+ 
+ 	for (i = 0; i < map->numselections; ++i) {
+ 		if (map->selections[i] == unit)
+ 		  return TRUE;
+ 	}
+ 	return FALSE;
+ }
+ 
+ void
+ unselect_unit_on_map(Map *map, Unit *unit)
+ {
+ 	int i, j;
+ 
+ 	for (i = 0; i < map->numselections; ++i) {
+ 		if (map->selections[i] == unit) {
+ 			/* Keep selection list contiguous, move other units down. */
+ 			for (j = i + 1; j < map->numselections; ++j) {
+ 				map->selections[j - 1] = map->selections[j];
+ 			}
+ 			--map->numselections;
+ 			draw_unit_info(map);
+ 			return;
+ 		}
+ 	}
+ }
+ 
+ /* Given a map and a rectangle in it, select all the units whose images touch on
+    that rectangle. */
+ 
+ void
+ select_all_units_in_rect(Map *map, Rect *rectptr)
+ {
+ 	int rectissmall = FALSE;
+ 	int sx, sy, sw, sh;
+ 	Unit *unit;
+ 	Rect unitrect, tmprect;
+ 	
+ 	/* First see if we're selecting over a large area or within a single cell. */
+ 	if (rectptr->right - rectptr->left < map->vp->hw
+ 		&& rectptr->bottom - rectptr->top < map->vp->hh) rectissmall = TRUE;
+ 	/* Now look at all the plausible units and see if any's image intersects the rect. */
+ 	for_all_units(unit) {
+ 		if (in_play(unit)
+ 			&& (side_controls_unit(dside, unit) || endofgame)
+ 			&& (rectissmall || unit->transport == NULL)) {
+ 			m_xform_unit_self(map, unit, &sx, &sy, &sw, &sh);
+ 			SetRect(&unitrect, sx, sy, sx + sw, sy + sh);
+ 			if (SectRect(&unitrect, rectptr, &tmprect)) {
+ 				select_unit_on_map(map, unit);
+ 				/* (could do setport etc once...) */
+ 				draw_selected_unit_setport(map, unit);
+ 			}
+ 		}
+ 	}
+ }
+ 
+ /* This translates the user's "go to here" into appropriate tasks and/or actions. */
+ 
+ int
+ move_the_selected_unit(Map *map, Unit *unit, int h, int v)
+ {
+ 	int x, y, rslt;
+ 	Unit *other = NULL;
+ 
+ 	m_nearest_cell(map, h, v, &x, &y);
+ 	if (unit_at(x, y) != NULL) {
+ 		m_nearest_unit(map, h, v, &other);
+ 	}
+ 	rslt = advance_into_cell(dside, unit, x, y, other);
+ 	return rslt;
+ }
+ 
+ void
+ fire_the_selected_unit(Map *map, Unit *unit, int h, int v)
+ {
+ 	int x, y;
+ 	Unit *other;
+ 
+ 	m_nearest_cell(map, h, v, &x, &y);
+ 	if (x != unit->x || y != unit->y) {
+ 		if (unit->act && unit->plan) { /* (should be more sophisticated test?) */
+ 			if ((other = unit_at(x, y)) != NULL) {
+ 				/* There's a unit to fire at. */
+ 				if (other->side == unit->side) {
+ 					beep();
+ 				} else {
+ 					net_prep_fire_at_action(unit, unit, other, -1);
+ 				}
+ 			} else {
+ 				beep();
+ 			}
+ 		}
+ 	}
+ }
+ 
+ void
+ select_exactly_one_unit(Map *map, Unit *unit)
+ {
+     Unit *thisunit;
+ 
+ 	if (map->numselections > 0) {		
+ 		thisunit = map->selections[0];
+ 		if (thisunit == unit) return;
+ 	}
+ 	unselect_all(map);
+ 	select_unit_on_map(map, unit);
+ 	scroll_to_unit(map, unit);
+ 	draw_selections(map);
+ }
+ 
+ void
+ select_next_unit(Map *map)
+ {
+ 	select_another(map, find_next_unit);
+ }
+ 
+ void
+ select_previous_unit(Map *map)
+ {
+ 	select_another(map, find_prev_unit);
+ }
+ 
+ void
+ select_next_actor(Map *map)
+ {
+ 	select_another(map, find_next_actor);
+ }
+ 
+ void
+ select_previous_actor(Map *map)
+ {
+ 	select_another(map, find_prev_actor);
+ }
+ 
+ void
+ select_next_mover(Map *map)
+ {
+ 	select_another(map, find_next_mover);
+ }
+ 
+ void
+ select_previous_mover(Map *map)
+ {
+ 	select_another(map, find_prev_mover);
+ }
+ 
+ void
+ select_next_awake_mover(Map *map)
+ {
+ 	select_another(map, find_next_awake_mover);
+ }
+ 
+ void
+ select_previous_awake_mover(Map *map)
+ {
+ 	select_another(map, find_prev_awake_mover);
+ }
+ 
+ /* Given a map and a searching function, go find the "next" matching unit and select it. */
+ 
+ void
+ select_another(Map *map, Unit *(*fn)(Side *side, Unit *unit))
+ {
+     Unit *thisunit, *nextunit;
+ 
+ 	if (fn == NULL) {
+ 		beep();
+ 		return;
+ 	}
+ 	if (map->numselections > 0) {
+ 		thisunit = map->selections[0];
+ 	} else {
+ 		thisunit = NULL;
+ 	}
+ 	nextunit = (*fn)(dside, thisunit);
+ 	if (nextunit != NULL) {
+ 		unselect_all(map);
+ 		select_unit_on_map(map, nextunit);
+ 		scroll_to_unit(map, nextunit);
+ 		draw_selections(map);
+ 		if (map->autoselect) {
+ 			map->curunit = nextunit;
+ 		}
+ 	} else if (thisunit != NULL) {
+ 		scroll_to_unit(map, thisunit);
+ 		/* (should not be done this way, but how else?) */
+ 		if (map->autoselect
+ 			&& (thisunit->act && thisunit->act->acp > 0)
+ 			&& (thisunit->plan && !thisunit->plan->asleep && !thisunit->plan->reserve && !thisunit->plan->delayed)) {
+ 			map->curunit = thisunit;
+ 		}
+ 	}
+ }
+ 
diff -rcN xconq-7.2.1/mac/macprefs.c xconq-7.2.2/mac/macprefs.c
*** xconq-7.2.1/mac/macprefs.c	Mon Apr  6 01:20:24 1998
--- xconq-7.2.2/mac/macprefs.c	Mon Jun  1 09:06:53 1998
***************
*** 1121,1128 ****
  	if (pref_color_unit_images != oldcolor) {
  		/* Get rid of old images and collect new ones. */
  		/* (should be more effective and GC the images themselves too) */
!  		free(uimages);
   		dispose_unit_cicns();
  	  	init_unit_images();
  	}
  
--- 1121,1139 ----
  	if (pref_color_unit_images != oldcolor) {
  		/* Get rid of old images and collect new ones. */
  		/* (should be more effective and GC the images themselves too) */
! 
! // --- CRASHING BUG FIX -------------------------------------------
! 
! 		/* dispose_unit_cicns accesses uimages, so don't free until after that call. */
! 		
   		dispose_unit_cicns();
+  		free(uimages);
+ 
+ //		free(uimages);
+ // 		dispose_unit_cicns();
+  
+ // ------------------------------------------------------------
+ 
  	  	init_unit_images();
  	}
  
diff -rcN xconq-7.2.1/mac/macrow.c xconq-7.2.2/mac/macrow.c
*** xconq-7.2.1/mac/macrow.c	Wed Dec 31 16:00:00 1969
--- xconq-7.2.2/mac/macrow.c	Sun May 31 10:23:57 1998
***************
*** 0 ****
--- 1,1369 ----
+ /* Row drawing functions for the Mac interface to Xconq.
+ 
+ 	Contains draw_row and all the functions that it calls.
+ 
+ 	Copyright (C) 1992-1998 Stanley T. Shebs.
+ 
+ Xconq is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.  See the file COPYING.  */
+ 
+ #include "conq.h"
+ #include "macconq.h"
+ 
+ extern int any_thickness;
+ extern int contour_interval;
+ 
+ int tmpdrawlighting;
+ int tmpdrawcoverage;
+ 
+ static void draw_terrain_row(Map *map, int x0, int y0, int len);
+ static int cell_update(Map *map, int x, int y);
+ static void draw_cliffs(Map *map, int x, int y);
+ static void draw_contours(Map *map, int x, int y);
+ extern void draw_gridlines(Map *map, int x, int y);
+ extern void draw_shorelines(Map *map, int x, int y);
+ static void draw_borders(Map *map, int x, int y, int b);
+ static void draw_connections(Map *map, int x, int y, int c);
+ static void draw_feature_boundary_simple(Map *map, int x, int y);
+ static void draw_feature_boundary(Map *map, int x, int y);
+ static void draw_feature_name(Map *map, int x, int y);
+ static void draw_people_row(Map *map, int x, int y);
+ static void draw_materials(Map *map, int x, int y);
+ static void draw_units(Map *map, int x, int y);
+ static void draw_unit_and_occs(Map *map, Unit *unit, int sx, int sy, int sw, int sh);
+ static void draw_ai_region(Map *map, int x, int y);
+ 
+ /* These three macros are used to handle cases where an item stretches across the */
+ /* edge of a wrapped world. It is then necessary to draw it twice, once at each end. */
+ /* The macros should be applied to all drawing functions that take an sx value, rect */
+ /* or poly as a parameter. */
+ 
+ /* Repeat (function) once using sx shifted one area width to the right. */
+ #define UNWRAP_SX(map, sx, function) { \
+ 	(function); \
+ 	if (area.xwrap && (sx) < 0) { \
+ 		(sx) += (map)->vp->sxmax; \
+ 		(function); \
+ 		(sx) -= (map)->vp->sxmax; \
+ 	} \
+ }
+ 
+ /* Repeat (function) once using rect offset one area width to the right. */
+ #define UNWRAP_RECT(map, rect, function) { \
+ 	(function); \
+ 	if (area.xwrap && (rect).left < 0) { \
+ 		OffsetRect(&(rect), (map)->vp->sxmax, 0); \
+ 		(function); \
+ 		OffsetRect(&(rect), -(map)->vp->sxmax, 0); \
+ 	} \
+ }
+ 
+ /* Repeat (function) once using poly offset one area width to the right. */
+ #define UNWRAP_POLY(map, poly, function) { \
+ 	(function); \
+ 	if (area.xwrap && (*(*(poly))).polyBBox.left < 0) { \
+ 		OffsetPoly((poly), (map)->vp->sxmax, 0); \
+ 		(function); \
+ 		OffsetPoly((poly), -(map)->vp->sxmax, 0); \
+ 	} \
+ }
+ 
+ /* For these accessors, x must already be wrapped. */
+ 
+ #define cell_overlay(x, y)  \
+   ((dside->designer && !map->see_all) \
+    ? ((terrain_view(dside, x, y) == UNSEEN) ? -2 : 0)  \
+    : (tmpdrawlighting  \
+       ? (night_at(x, y)  \
+          ? -2  \
+          : (tmpdrawcoverage ? (cover(dside, x, y) == 0 ? -1 : 0) : 0))  \
+       : (tmpdrawcoverage  \
+           ? (cover(dside, x, y) == 0 ? -1 : 0)  \
+           : 0)))
+ 
+ #define cell_terrain(map, x, y)  \
+   ((map->see_all || dside->designer) \
+    ? terrain_at(x, y)  \
+    : (terrain_visible(dside, x, y)  \
+ 	  ? vterrain(terrain_view(dside, x, y))  \
+ 	  : NONTTYPE))
+ 
+ #define cell_style(map, x, y, power)  \
+   ((map->see_all || terrain_visible(dside, x, y) || unseen_image != NULL)  \
+    ? (power >= 4 ? usepolygons : useblocks)  \
+    : dontdraw);
+ 
+ /* x0 may be negative here. */
+ 
+ #if 0		/* Single-loop version of draw_row. */
+ 
+ void
+ draw_row(Map *map, int x0, int y, int len, int clearit)
+ {
+ 	int	pwr = map->vp->power; 
+ 	int	ang = map->vp->angle; 
+ 	int	empty = FALSE;
+ 	int	x, xw, sx, sy, t;
+ 
+ 	if (!between(0, y, area.height - 1))
+ 	    return;
+ 	if (!map->see_all && !map->vp->draw_ai && unseen_image == NULL) {
+ 		empty = TRUE;
+ 		/* Examine row to see if we can skip it entirely. */
+ 		for (x = x0; x < x0 + len; ++x) {
+ 			if (map->see_all || terrain_visible(dside, x, y)
+ 				|| (numbordtypes > 0 && terrain_visible(dside, x, y + 1))) {
+ 					empty = FALSE;
+ 					break;
+ 			}
+ 		}
+ 	}
+ 	if (empty && !clearit)
+ 	    return;
+ 
+ 	/* First do run-length based drawing of the terrain. */
+ 	draw_terrain_row(map, x0, y, len);
+ 
+ 	/* Then do cell-based drawing of all the other stuff. */
+ 	for (x = x0; x < x0 + len; ++x) {
+ 		if (!in_area(x, y))
+ 			continue;				/* xform crash fix. */
+ 		xform(map, x, y, &sx, &sy);
+ 		xw = wrapx(x);
+ 		/* Draw either cliffs or contour lines, depending on the angle. */
+ 		if ((map->see_all || terrain_visible(dside, x, y)) ) {
+ 			if ((elevations_defined() || any_thickness) && ang != 90) {
+ 				draw_cliffs(map, x, y);
+ 			} else if (elevations_defined() && map->vp->draw_elevations && ang == 90) {
+ 				draw_contours(map, x, y);
+ 			}
+ 		}
+ 		/* Draw grid explicitly if asked to and the quick method using smaller cells doesn't work. */
+ 		if (map->vp->draw_grid 
+ 			&& 	( map->erase_names 					/* Leaks into the grid. */
+ 				|| !grid_matches_unseen 				/* Can't use quick method. */
+ 				|| ang != 90						/* Can't use quick method.  */
+ 		    		|| map->vp->draw_plans 				/* Leaks into the grid. */	
+ 		    		|| map->vp->draw_ai 					/* Leaks into the grid. */
+ 		    		|| map->vp->draw_elevations)) {			/* Leaks into the grid. */
+ 			  		draw_gridlines(map, x, y);
+ 		}
+ 		/* Draw shorelines if desired. */
+ 		if (map->shorelines) { 
+ 			draw_shorelines(map, x, y);
+ 		}
+ 		/* Draw connections and borders. */
+ 		if (any_aux_terrain_defined()) {
+ 			if (bords_to_draw(map)) {
+ 				for_all_terrain_types(t) {
+ 					if (map->vp->draw_aux_terrain[t] 
+ 						&& t_is_border(t) 
+ 						&& aux_terrain_defined(t)) {
+ 							draw_borders(map, x, y, t);
+ 					}
+ 				}
+ 			}
+ 			/* Connections should always be drawn on top of borders. */
+ 			if (conns_to_draw(map)) {
+ 				for_all_terrain_types(t) {
+ 					if (map->vp->draw_aux_terrain[t] 
+ 						&& t_is_connection(t) 
+ 						&& aux_terrain_defined(t)) {
+ 							draw_connections(map, x, y, t);
+ 					}
+ 				}
+ 			}
+ 		}
+ 		/* Draw clouds, winds and temperatures. */
+ 		if (clouds_defined() 
+ 			&& map->vp->draw_clouds 
+ 			&& draw_clouds_here(x, y)) {
+ 				if (map->vp->hh <= 16) {
+ 				    	UNWRAP_SX(map, sx, 
+ 				    		draw_cloud_block(sx, sy, 1, pwr, cloud_view(dside, xw, y), ang));
+ 				} else UNWRAP_SX(map, sx, 
+ 						draw_clouds(sx, sy, pwr, cloud_view(dside, xw, y)));
+ 		}
+ 		if (winds_defined() 
+ 			&& map->vp->draw_winds && map->vp->hh > 10 
+ 			&& draw_winds_here(dside, xw, y)) {
+ 				UNWRAP_SX(map, sx, 
+ 					draw_winds(sx, sy, pwr, wind_view(dside, xw, y)));
+ 		}
+ 		if (temperatures_defined() 
+ 			&& map->vp->draw_temperature && map->vp->hh > 10
+ 			&& draw_temperature_here(dside, xw, y)) {
+ 				UNWRAP_SX(map, sx, 
+ 					draw_temperature(sx, sy, pwr, temperature_view(dside, xw, y)));
+ 		}
+ 
+ 		/* We had to draw the terrain on the edge, but skip everything else. */
+ 		if (!inside_area(x, y))
+ 		    continue;
+ 
+ 		/* Draw feature boundaries and names. */
+ 		if (features_defined()) {
+ 			if (map->featureborders && map->vp->hw > 4) {
+ 				if (map->simple_borders){ 
+ 					 draw_feature_boundary_simple(map, x, y);
+ 				} else draw_feature_boundary(map, x, y);
+ 			}
+ 			if (map->featurenames && map->vp->hh > 3) {
+ 				draw_feature_name(map, x, y);
+ 			}
+ 		}
+ 		/* Draw country borders and people rows. */
+ 		if ((people_sides_defined() || control_sides_defined()) && bwid2[pwr] > 0) {
+ 			draw_people_row(map, x, y);
+ 		}
+ 		/* Draw cell materials. */
+ 		if (any_cell_materials_defined() && map->vp->num_materials_to_draw > 0 && map->vp->hh > 20) {
+ 			draw_materials(map, x, y);
+ 		}
+ 		/* Draw units. */
+ 		if (map->vp->draw_units && map->vp->hw > 2) {
+ 			draw_units(map, x, y);
+ 		}
+ 		/* Draw ai regions. */
+ 		if (map->vp->draw_ai) {
+ 			draw_ai_region(map, x, y);
+ 		}
+ 		/* If debugging, draw coverage on top of everything else. */
+ 		if (DebugG && !all_see_all && map->vp->hw >= 16) {
+ 			UNWRAP_SX(map, sx, 
+ 				draw_coverage(sx, sy, pwr, cover(dside, xw, y), alt_cover(dside, xw, y)));
+ 		}
+ 	}
+ }
+ 
+ /* Multi-loop version, slightly faster than single-loop version. */
+ 
+ #else
+ 
+ void
+ draw_row(Map *map, int x0, int y, int len, int clearit)
+ {
+ 	int	pwr = map->vp->power; 
+ 	int	ang = map->vp->angle; 
+ 	int	empty = FALSE;
+ 	int	x, xw, sx, sy, t;
+ 
+ 	if (!between(0, y, area.height - 1))
+ 	    return;
+ 	if (!map->see_all && !map->vp->draw_ai && unseen_image == NULL) {
+ 		empty = TRUE;
+ 		/* Examine row to see if we can skip it entirely. */
+ 		for (x = x0; x < x0 + len; ++x) {
+ 			if (map->see_all || terrain_visible(dside, x, y)
+ 				|| (numbordtypes > 0 && terrain_visible(dside, x, y + 1))) {
+ 					empty = FALSE;
+ 					break;
+ 			}
+ 		}
+ 	}
+ 	if (empty && !clearit)
+ 	    return;
+ 
+ 	/* First do run-length based drawing of the terrain. */
+ 	draw_terrain_row(map, x0, y, len);
+ 
+ 	/* Draw either cliffs or contour lines, depending on the angle. */
+ 	if ((elevations_defined() || any_thickness) && map->vp->angle != 90) {
+ 		for (x = x0; x < x0 + len; ++x) {
+ 			if (map->see_all || terrain_visible(dside, x, y)) {
+ 				draw_cliffs(map, x, y);
+ 			}
+ 		}
+ 	} else if (elevations_defined() && map->vp->draw_elevations && map->vp->angle == 90) {
+ 		for (x = x0; x < x0 + len; ++x) {
+ 			if (map->see_all || terrain_visible(dside, x, y)) {
+ 				draw_contours(map, x, y);
+ 			}
+ 		}
+ 	}
+ 	/* Draw grid explicitly if asked to and the quick method using smaller cells doesn't work. */
+ 	if (map->vp->draw_grid 
+ 		&& 	(map->erase_names 					/* Leaks into the grid. */
+ 			|| !grid_matches_unseen 				/* Can't use quick method. */
+ 			|| ang != 90						/* Can't use quick method.  */
+ 	    		|| map->vp->draw_plans 				/* Leaks into the grid. */	
+ 	    		|| map->vp->draw_ai 					/* Leaks into the grid. */
+ 	    		|| map->vp->draw_elevations)) {			/* Leaks into the grid. */
+ 				for (x = x0; x < x0 + len + 1; ++x)	
+ 		  			draw_gridlines(map, x, y);		/* Draw one extra cell here! */
+ 	}
+ 	/* Draw shorelines if desired. */
+ 	if (map->shorelines) {
+ 		for (x = x0; x < x0 + len + 1; ++x)
+ 			draw_shorelines(map, x, y);			/* Draw one extra cell here! */
+ 	}
+ 	/* Draw connections and borders. */
+ 	if (any_aux_terrain_defined()) {
+ 		if (bords_to_draw(map)) {
+ 			for_all_terrain_types(t) {
+ 				if (map->vp->draw_aux_terrain[t] 
+ 					&& t_is_border(t) 
+ 					&& aux_terrain_defined(t)) {
+ 						for (x = x0; x < x0 + len; ++x)
+ 							draw_borders(map, x, y, t);
+ 				}
+ 			}
+ 		}
+ 		/* Connections should always be drawn on top of borders. */
+ 		if (conns_to_draw(map)) {
+ 			for_all_terrain_types(t) {
+ 				if (map->vp->draw_aux_terrain[t] 
+ 					&& t_is_connection(t) 
+ 					&& aux_terrain_defined(t)) {
+ 						for (x = x0; x < x0 + len; ++x)
+ 							draw_connections(map, x, y, t);
+ 				}
+ 			}
+ 		}
+ 	}
+ 	/* Draw clouds, winds and temperatures. */
+ 	if (clouds_defined() && map->vp->draw_clouds) {
+ 		for (x = x0; x < x0 + len; ++x) {
+ 			xw = wrapx(x);					
+ 			if (in_area(x,y) && draw_clouds_here(xw, y)) {				/* xform crash fix. */	
+ 				xform(map, x, y, &sx, &sy);
+ 				if (map->vp->hh <= 16) {
+ 				    	 UNWRAP_SX(map, sx, 
+ 				    		draw_cloud_block(sx, sy, 1, pwr, cloud_view(dside, xw, y), ang));
+ 				} else UNWRAP_SX(map, sx, 
+ 						draw_clouds(sx, sy, pwr, cloud_view(dside, xw, y)));
+ 			}
+ 		}
+ 	}
+ 	if (winds_defined() && map->vp->draw_winds && map->vp->hh > 10) { 
+ 		for (x = x0; x < x0 + len; ++x) {
+ 			xw = wrapx(x);						
+ 			if (in_area(x,y) && draw_winds_here(dside, xw, y)) {			/* xform crash fix. */
+ 				xform(map, x, y, &sx, &sy);
+ 				UNWRAP_SX(map, sx, 
+ 					draw_winds(sx, sy, pwr, wind_view(dside, xw, y)));
+ 			}
+ 		}
+ 	}
+ 	if (temperatures_defined() && map->vp->draw_temperature && map->vp->hh > 10) {
+ 		for (x = x0; x < x0 + len; ++x) {
+ 			xw = wrapx(x);							
+ 			if (in_area(x,y) && draw_temperature_here(dside, xw, y)) {	/* xform crash fix. */
+ 				xform(map, x, y, &sx, &sy);
+ 				UNWRAP_SX(map, sx, 
+ 					draw_temperature(sx, sy, pwr, temperature_view(dside, xw, y)));
+ 			}
+ 		}
+ 	}
+ 
+ 	/* Although we had to draw the terrain on the edge, we can skip everything else,
+ 	   since edge cells have no units, features, etc. */
+ 	/* Skip the top and bottom edge rows. */
+ 	if (!between(1, y, area.height - 2)) 
+ 	  return;
+ 	/* Shorten the row by one cell on each side, if those are edge cells. */
+ 	if (!inside_area(x0 + len - 1, y))
+ 	  --len;
+ 	if (!inside_area(x0, y)) {
+ 		++x0;
+ 		--len;
+ 	}
+ 	if (len <= 0)
+ 	  return;
+ 
+ 	/* Draw feature boundaries and names. */
+ 	if (features_defined()) {
+ 		if (map->featureborders && map->vp->hw > 4) {
+ 			for (x = x0; x < x0 + len; ++x) {
+ 				if (map->simple_borders) {
+ 					 draw_feature_boundary_simple(map, x, y);
+ 				} else draw_feature_boundary(map, x, y);
+ 			}
+ 		}
+ 		if (map->featurenames && map->vp->hh > 3) {
+ 			for (x = x0; x < x0 + len; ++x)
+ 				draw_feature_name(map, x, y);
+ 		}
+ 	}
+ 	/* Draw cell materials. */
+ 	if (any_cell_materials_defined() && map->vp->num_materials_to_draw > 0 && map->vp->hh > 20) {
+ 		for (x = x0; x < x0 + len; ++x)
+ 			draw_materials(map, x, y);
+ 	}
+ 	/* Draw people rows and country borders. */
+ 	if ((people_sides_defined() || control_sides_defined()) && bwid2[pwr] > 0) {
+ 		for (x = x0; x < x0 + len; ++x)
+ 			draw_people_row(map, x, y);
+ 	}
+ 	/* Draw units. */
+ 	if (map->vp->draw_units && map->vp->hw > 2) {
+ 		for (x = x0; x < x0 + len; ++x)
+ 			draw_units(map, x, y);
+ 	}
+ 	/* Draw ai regions. */
+ 	if (map->vp->draw_ai) {
+ 		for (x = x0; x < x0 + len; ++x)
+ 			draw_ai_region(map, x, y);
+ 	}
+ 	/* If debugging, draw coverage on top of everything else. */
+ 	if (DebugG && !all_see_all && map->vp->hw >= 16) {
+ 		for (x = x0; x < x0 + len; ++x) {
+ 			xw = wrapx(x);	
+ 			xform(map, x, y, &sx, &sy);		/* No need to test for in_area here. */
+ 			UNWRAP_SX(map, sx, 
+ 				draw_coverage(sx, sy, pwr, cover(dside, xw, y), alt_cover(dside, xw, y)));
+ 		}
+ 	}
+ }
+ 
+ #endif
+ 
+ /* Draw an entire row of terrain, possibly with a single rectangle fill. */
+  /* x0 may be negative. */
+ 
+ void
+ draw_terrain_row(Map *map, int x0, int y, int len)
+ {
+ 	int x0w, x, xw, x1, x1w, sx, sy, i;
+ 	int pwr = map->vp->power, ang = map->vp->angle;
+ 	int dogrid = map->vp->draw_grid & grid_matches_unseen; 
+ 	int dofill = map->vp->draw_cell_pats;
+ 	int dosolid = map->solid_color_terrain;
+ 	int inarea, seginarea, style, segstyle, terr, segterr, over, segover, update, segupdate;
+ 
+ 	tmpdrawlighting = map->vp->draw_lighting;
+ 	tmpdrawcoverage = (!dside->see_all && map->vp->draw_cover);
+ 	x0w = wrapx(x0);
+ 	i = 0;
+ 	x1 = x0;
+ 	x1w = wrapx(x1);
+ 	seginarea = in_area(x0w, y);
+ 	segstyle = cell_style(map, x0w, y, pwr);
+ 	segterr = cell_terrain(map, x0w, y);
+ 	segover = cell_overlay(x0w, y);
+ 	segupdate = (seginarea ? cell_update(map, x0w, y) : FALSE);
+ 	/* Note that in this loop we do NOT wrap x for drawing, just for
+ 	   looking at layer data. */
+ 	for (x = x0; x < x0 + len + 1; ++x) {
+ 		xw = wrapx(x);
+ 		inarea = in_area(xw, y);
+ 		style = cell_style(map, xw, y, pwr);
+ 		terr = cell_terrain(map, xw, y);
+ 		over = cell_overlay(xw, y);
+ 		update = (inarea ? cell_update(map, xw, y) : FALSE);
+ 		/* Decide if the run is over and we need to dump some output. */
+ 		if (x == x0 + len
+ 			|| x == area.width
+ 			|| inarea != seginarea
+ 			|| style != segstyle
+ 			|| terr != segterr
+ 			|| over != segover
+ 			|| update != segupdate
+ /*			|| segstyle == useblocks  fixes, but poor performance */
+ 			|| segstyle == usepictures
+ 			|| segstyle == usepolygons
+ 			|| ang != 90) {
+ 			/* don't draw anything that would match the window's bg */
+ #if 0 /* use this for heavy-duty debugging only */
+ 			DGprintf("Seg is %d,%d len=%d inarea=%d style=%d terr=%d over=%d update=%d\n",
+ 					 x1, y, i, seginarea, segstyle, segterr, segover, segupdate);
+ #endif
+ 			if (seginarea && segupdate && segstyle != dontdraw) {
+ 				xform(map, x1, y, &sx, &sy);
+ 				switch (segstyle) {
+ 					case useblocks:
+ 						UNWRAP_SX(map, sx, 
+ 							draw_cell_block(sx, sy, i, pwr, segterr, segover, ang, dosolid));													
+ 						break;
+ 					case usepictures:
+ 						break;
+ 					case usepolygons:
+ 						UNWRAP_SX(map, sx, 
+ 							draw_hex_region(sx, sy, pwr, segterr, segover, ang, dogrid, dosolid));
+ 				}
+ 			}
+ 			/* Set up for the next segment. */
+ 			i = 0;
+ 			x1 = x;
+ 			x1w = wrapx(x1);
+ 			seginarea = inarea;
+ 			segstyle = style;
+ 			segterr = terr;
+ 			segover = over;
+ 			segupdate = update;
+ 		}
+ 		++i;
+ 	}
+ }
+ 
+ /* Is this just to see if a cell is visible? */
+ 
+ int
+ cell_update(Map *map, int x, int y)
+ {
+ #if 0
+ 	int sx, sy;
+ 	Rect tmprect;
+ 
+ 	xform(map, x, y, &sx, &sy);
+ 	SetRect(&tmprect, sx, sy, sx + map->vp->hw, sy + map->vp->hh);
+ 	return (RectInRgn(&tmprect, map->window->visRgn));
+ #else
+ 	return TRUE;
+ #endif
+ }
+ 
+ static void
+ draw_cliffs(Map *map, int x, int y)
+ {
+ 	int xw, elev, x1, y1, drop, t, t1, drawit, elev1, offset;
+ 	int sx, sy, sx1, sy1;
+ 	PolyHandle poly;
+ 	RGBColor hexcolor, oldcolor;
+ 
+ 	xw = wrapx(x);
+ 	t = cell_terrain(map, xw, y);
+ 	elev = (elevations_defined() ? elev_at(xw, y) : 0) + t_thickness(t);
+ 	drawit = FALSE;
+ 	if (point_in_dir(xw, y, SOUTHWEST, &x1, &y1)) {
+ 		t1 = cell_terrain(map, x1, y1);
+ 		if (t1 != NONTTYPE) {
+ 			drop = elev - ((elevations_defined() ? elev_at(wrapx(x1), y1) : 0) + t_thickness(t1));
+ 			if (drop > 0) {
+ 				drawit = TRUE;
+ 				xform(map, x, y, &sx, &sy);
+ 				xform(map, x1, y1, &sx1, &sy1);
+ 			}
+ 		}
+ 	} else {
+ 		drawit = TRUE;
+ 		xform(map, x, y, &sx, &sy);
+ 	    elev1 = elev - (elevations_defined() ? area.minelev : 0);
+ 	    elev1 *= map->vp->vertscale;
+ 	    offset = (elev1 * map->vp->hh) / map->vp->cellwidth;
+ 	    sy1 = sy + map->vp->hch + offset; 
+ 	}
+ 	if (drawit) {
+ 		if (sy1 > sy + map->vp->hch + (map->vp->draw_grid ? 1 : 0)) {
+ 			poly = OpenPoly();
+ 			MoveTo(sx, sy + map->vp->hch);
+ 			LineTo(sx + map->vp->hw / 2, sy + map->vp->hh);
+ 			LineTo(sx + map->vp->hw / 2, sy1 + (map->vp->hh - map->vp->hch));
+ 			LineTo(sx, sy1);
+ 			LineTo(sx, sy + map->vp->hch);
+ 			ClosePoly();
+ 			/* if (timg->colrpat != nil
+ 			    && (minscreendepth > 1 || !timg->patdefined)) {
+ 				FillCPoly(poly, timg->colrpat);
+ 			} else */ if (tcolors[t] != NULL && maxscreendepth > 1) {
+ 				hexcolor.red   = tcolors[t]->color.red / 2;
+ 				hexcolor.green = tcolors[t]->color.green / 2;
+ 				hexcolor.blue  = tcolors[t]->color.blue / 2;
+ 				RGBForeColor(&hexcolor);
+ 				UNWRAP_POLY(map, poly, 
+ 					PaintPoly(poly));
+ 				/* Restore the previous color. */
+ 				RGBForeColor(&blackcolor);
+ 			} else {
+ 				hexcolor.red   = (128 << 8) / 2;
+ 				hexcolor.green = (128 << 8) / 2;
+ 				hexcolor.blue  = (128 << 8) / 2;
+ 				RGBForeColor(&hexcolor);
+ 				UNWRAP_POLY(map, poly, 
+ 					PaintPoly(poly));
+ 				/* Restore the previous color. */
+ 				RGBForeColor(&blackcolor);
+ 			}
+ 			KillPoly(poly);
+ 		}
+ 	}
+ 	drawit = FALSE;
+ 	if (point_in_dir(xw, y, SOUTHEAST, &x1, &y1)) {
+ 		t1 = cell_terrain(map, x1, y1);
+ 		if (t1 != NONTTYPE) {
+ 			drop = elev - ((elevations_defined() ? elev_at(wrapx(x1), y1) : 0) + t_thickness(t1));
+ 			if (drop > 0) {
+ 				drawit = TRUE;
+ 				xform(map, x, y, &sx, &sy);
+ 				xform(map, x1, y1, &sx1, &sy1);
+ 			}
+ 		}
+ 	} else {
+ 		drawit = TRUE;
+ 		xform(map, x, y, &sx, &sy);
+ 	    elev1 = elev - (elevations_defined() ? area.minelev : 0);
+ 	    elev1 *= map->vp->vertscale;
+ 	    offset = (elev1 * map->vp->hh) / map->vp->cellwidth;
+ 	    sy1 = sy + map->vp->hch + offset; 
+ 	}
+ 	if (drawit) {
+ 		if (sy1 > sy + map->vp->hch + (map->vp->draw_grid ? 1 : 0)) {
+ 			poly = OpenPoly();
+ 			MoveTo(sx + map->vp->hw - (map->vp->draw_grid ? 1 : 0), sy + map->vp->hch);
+ 			LineTo(sx + map->vp->hw - (map->vp->draw_grid ? 1 : 0), sy1);
+ 			LineTo(sx + map->vp->hw / 2, sy1 + (map->vp->hh - map->vp->hch));
+ 			LineTo(sx + map->vp->hw / 2, sy + map->vp->hh);
+ 			LineTo(sx + map->vp->hw - (map->vp->draw_grid ? 1 : 0), sy + map->vp->hch);
+ 			ClosePoly();
+ 			/* if (timg->colrpat != nil
+ 			    && (minscreendepth > 1 || !timg->patdefined)) {
+ 				FillCPoly(poly, timg->colrpat);
+ 			} else */ if (tcolors[t] != NULL && maxscreendepth > 1) {
+ 				hexcolor.red   = (3 * tcolors[t]->color.red) / 4;
+ 				hexcolor.green = (3 * tcolors[t]->color.green) / 4;
+ 				hexcolor.blue  = (3 * tcolors[t]->color.blue) / 4;
+ 				RGBForeColor(&hexcolor);
+ 				UNWRAP_POLY(map, poly, 
+ 					PaintPoly(poly));
+ 				/* Restore the previous color. */
+ 				RGBForeColor(&blackcolor);
+ 			} else {
+ 				hexcolor.red   = (3 * 128 << 8) / 4;
+ 				hexcolor.green = (3 * 128 << 8) / 4;
+ 				hexcolor.blue  = (3 * 128 << 8) / 4;
+ 				RGBForeColor(&hexcolor);
+ 				UNWRAP_POLY(map, poly, 
+ 					PaintPoly(poly));
+ 				/* Restore the previous color. */
+ 				RGBForeColor(&blackcolor);
+ 			}
+ 			KillPoly(poly);
+ 		}
+ 	}
+ }
+ 
+ static void
+ draw_contours(Map *map, int x, int y)
+ {
+ 	int i, sx, sy, numlines;
+ 	LineSegment *lines;
+ 
+ 	init_contour_lines();
+ 	if (contour_interval < 1)
+ 	  return;
+ 	xform(map, x, y, &sx, &sy);
+ 	contour_lines_at(map->vp, wrapx(x), y, sx, sy, &lines, &numlines);
+ 	RGBForeColor(&contourcolor);
+ 	for (i = 0; i < numlines; ++i) {
+ 
+ 		/* Draw the line. */
+ 		MoveTo(lines[i].sx1, lines[i].sy1); 
+ 		LineTo(lines[i].sx2, lines[i].sy2);
+ 
+ 		/* UNWRAP line if necessary. */
+ 		if (area.xwrap && sx < 0) {
+ 			lines[i].sx1 += map->vp->sxmax;
+ 			lines[i].sx2 += map->vp->sxmax;
+ 			MoveTo(lines[i].sx1, lines[i].sy1); 
+ 			LineTo(lines[i].sx2, lines[i].sy2);
+ 		}
+ 	}
+ 	ForeColor(blackColor);
+ }
+ 
+ /* This function draws the grid explicitly on top of the map. It is used when
+    gridcolor differs from unseencolor, and also when map->erase_names is on,
+    since erased names otherwise will leak into the grid. Drawing the grid
+    explicitly is about 30% slower than using the quick method based on the
+    background color and smaller cells. */
+ 
+ void 
+ draw_gridlines(Map *map, int x, int y)
+ {
+ 	int xw, dir, x1, y1, wid, dx1, dy1, dx2, dy2, sx, sy, cliffs = FALSE;
+ 	int pwr = map->vp->power;
+ 	int ang = map->vp->angle;
+ 	
+ 	/* (should use generic drawing style test) */
+ 	if (pwr < 4)
+ 	  return;
+ 	xw = wrapx(x);
+ 	/* Dont draw outside the area (causes crashes) */
+ 	if (!in_area(xw, y))
+ 	  return;
+ 	/* Dont draw grid if (xw, y) is invisible */
+ 	if (!terrain_visible(dside, xw, y))
+ 	  return;
+ 	/* Very important to use UNWRAPPED x here! */
+ 	xform(map, x, y, &sx, &sy);
+ 
+ 	/* Check if we are dealing with cliffs. */
+ 	if ((elevations_defined() || any_thickness) && ang != 90)
+ 	  cliffs = TRUE;
+ 
+ 	RGBForeColor(&gridcolor);
+ 	PenPat(QDPat(black));
+ 	PenSize(1, 1);
+ 
+ 	for_all_directions(dir) {
+ 		/* Draw SE, SW and E gridlines only if we are dealing with cliffs */
+ 		if ((dir == EAST || dir == SOUTHEAST || dir == SOUTHWEST) &! cliffs)
+ 		  continue;
+ 		/* Dont draw grid lines on the edge or to invisible hexes */
+ 		if (!point_in_dir(xw, y, dir, &x1, &y1))
+ 		  continue;
+ 		if (!terrain_visible(dside, wrapx(x1), y1))
+ 		  continue;
+ 
+ 		/* Calculate start point. */
+ 		dx1 = bsx[pwr][dir]; 
+ 		dy1 = bsy[pwr][dir];
+ 		if (ang == 30)
+ 		  dy1 /= 2;
+ 		if (ang == 15)
+ 		  dy1 /= 4;
+ 		if (dir == WEST || dir == EAST)
+ 		  dx1 -=1;
+ 
+ 		/* Calculate end point. */
+ 		dx2 = bsx[pwr][dir+1]; 
+ 		dy2 = bsy[pwr][dir+1];
+ 		if (ang == 30)
+ 		  dy2 /= 2;
+ 		if (ang == 15)
+ 		  dy2 /= 4;
+ 		if (dir == WEST || dir == EAST)
+ 		  dx2 -=1;
+ 
+ 		/* Draw the line. */
+ 		MoveTo(sx + dx1, sy + dy1 - 1);
+ 		LineTo(sx + dx2, sy + dy2 - 1);
+ 
+ 		/* UNWRAP line if necessary. */
+ 		if (area.xwrap && sx < 0) {
+ 			sx += map->vp->sxmax;
+ 			MoveTo(sx + dx1, sy + dy1 - 1);
+ 			LineTo(sx + dx2, sy + dy2 - 1);
+ 			sx -= map->vp->sxmax;
+ 		}
+ 	}
+ 	PenNormal();
+ 	ForeColor(blackColor);
+ }
+ 
+ /* This function draws shorelines in 3D relief, using shorecolor. */
+ 
+ void 
+ draw_shorelines(Map *map, int x, int y)
+ {
+ 	int	dir, x1, y1, dx1, dy1, dx2, dy2, sx, sy;
+ 	int	t, elev, offset = 0, cliffs = FALSE;
+ 	int	pwr = map->vp->power;
+ 	int	ang = map->vp->angle;
+ 	int	wid = bwid2[pwr];
+ 	int	wid2 = wid / 2;
+ 	int	xw = wrapx(x);
+ 
+ 	if (wid == 0)
+ 	  return;
+ 	/* Dont draw outside the area (causes crashes) */
+ 	if (!in_area(xw, y))
+ 	  return;
+ 	/* Dont draw shores if (xw, y) is invisible */
+ 	if (!terrain_visible(dside, xw, y))
+ 	  return;
+ 	/* Very important to use UNWRAPPED x here! */
+ 	xform(map, x, y, &sx, &sy);
+ 
+ 	/* Check if we have cliffs and calculate offset imposed by xform. */
+ 	if ((elevations_defined() || any_thickness) && ang != 90) {
+ 		cliffs = TRUE;
+ 		t = cell_terrain(map, xw, y);
+ 		elev   = (elevations_defined() ? elev_at(xw, y) : 0) + t_thickness(t);
+ 		elev -= (elevations_defined() ? area.minelev : 0);
+ 		elev *= map->vp->vertscale;
+ 		offset = (elev * map->vp->hh) / map->vp->cellwidth;
+ 	}
+ 	
+ 	RGBForeColor(&shorecolor);
+ 	PenPat(QDPat(black));
+ 
+ 	for_all_directions(dir) {
+ 		/* Used to kill xform offset. */
+ 		int adjust = 0;
+ 		/* Never draw SE and SW shores of a given hex */
+ 		if (dir == SOUTHEAST || dir == SOUTHWEST)
+ 		  continue;
+ 		/* Only draw E shore if we have cliffs. */
+ 		if (dir == EAST &! cliffs)
+ 		  continue;
+ 		/* Dont draw shores on the edge or to invisible hexes */
+ 		if (!point_in_dir(xw, y, dir, &x1, &y1))
+ 		  continue;
+ 		if (!terrain_visible(dside, wrapx(x1), y1))
+ 		  continue;
+ 
+ 		/* Use narrow pen */
+ 		PenSize(wid2, wid2);
+ 
+ 		/* WATER HEX */
+ 		if (t_liquid(terrain_at(xw, y))) {
+ 			/* Dont draw shores to other water hexes */
+ 			if (t_liquid(terrain_at(wrapx(x1), y1)))
+ 			  continue;
+ 			/* Draw NE and NW shores using wide pen. */
+ 			if (dir == NORTHWEST || dir == NORTHEAST)
+ 			  PenSize(wid2, wid + wid2);
+ 		/* LAND HEX */
+ 		} else {
+ 			/* Dont draw shores to other land hexes. */ 
+ 			if (!t_liquid(terrain_at(wrapx(x1), y1)))
+ 		  	  continue;
+ 			if (offset) {
+ 				/* Decide if imposed offset should be removed. */
+ 				if ((dir == WEST && in_area (wrapx(x - 1), y + 1) 
+ 				  &! t_liquid(terrain_at(wrapx(x - 1), y + 1)))
+ 				  || (dir == EAST && in_area (xw, y + 1) 
+ 				  &! t_liquid(terrain_at(xw, y + 1)))) {
+ 					adjust = offset;
+ 				}
+ 			}
+ 		}
+ 
+ 		/* Calculate start point. */
+ 		dx1 = bsx[pwr][dir]; 
+ 		dy1 = bsy[pwr][dir];
+ 		if (ang == 30) 
+ 		    dy1 /= 2;
+ 		if (ang == 15) 
+ 		    dy1 /= 4;
+ 		if (dir == NORTHWEST || dir == NORTHEAST) {
+ 			if (!t_liquid(terrain_at(xw, y)))
+ 			  dx1 += 1; 
+ 			else if (pwr > 3)
+ 			  dy1 -= 1;
+ 		}
+ 
+ 		/* Calculate end point. */
+ 		dx2 = bsx[pwr][right_dir(dir)]; 
+ 		dy2 = bsy[pwr][right_dir(dir)];
+ 		if (ang == 30) 
+ 		    dy2 /= 2;
+ 		if (ang == 15) 
+ 		    dy2 /= 4;
+ 		if (dir == NORTHWEST || dir == NORTHEAST) {
+ 			if (!t_liquid(terrain_at(xw, y)))
+ 			  dx2 += 1; 
+ 			else if (pwr > 3)
+ 			  dy2 -= 1;
+ 		}
+ 
+ 		/* Draw the line. */
+ 		MoveTo(sx + dx1 - wid2, sy + dy1 - 1 + adjust);
+ 		LineTo(sx + dx2 - wid2, sy + dy2 - 1 + adjust);
+ 
+ 		/* UNWRAP line if necessary. */
+ 		if (area.xwrap && sx < 0) {
+ 			sx += map->vp->sxmax;
+ 			MoveTo(sx + dx1 - wid2, sy + dy1 - 1 + adjust);
+ 			LineTo(sx + dx2 - wid2, sy + dy2 - 1 + adjust);
+ 			sx -= map->vp->sxmax;
+ 		}
+ 	}
+ 	PenNormal();
+ 	ForeColor(blackColor);
+ }
+ 
+ static void
+ draw_borders(Map *map, int x, int y, int b)
+ {
+ 	int 	xw = wrapx(x), dir, sx, sy, bitmask = 0, over;
+ 	
+  	if (!(map->see_all || terrain_visible(dside, xw, y)) || !any_borders_at(xw, y, b))
+  	  return;
+ 	for_all_directions(dir) {
+ 		if (border_at(xw, y, dir, b) && borders_visible(dside, xw, y, dir)) {
+ 			bitmask |= 1 << dir;
+ 		}
+ 	}
+ 	if (bitmask != 0) {
+ 		tmpdrawlighting = map->vp->draw_lighting;
+ 		tmpdrawcoverage = (!all_see_all && map->vp->draw_cover);
+ 		over = cell_overlay(xw, y);
+ 		xform(map, x, y, &sx, &sy);
+ 		/* (should compute and pass in overlay) */
+ 		UNWRAP_SX(map, sx, 
+ 			draw_border_line_multiple(map->window, sx, sy, bitmask, map->vp->power, b, 
+ 								map->vp->angle, over, map->solid_color_terrain));
+ 		
+ 	}
+ }
+ 
+ /* Draw all the connections of the given cell. */
+ 
+ static void
+ draw_connections(Map *map, int x, int y, int c)
+ {
+ 	int xw = wrapx(x), dir, sx, sy, bitmask = 0, over;
+ 	
+ 	if (!(map->see_all || terrain_visible(dside, xw, y)) || !any_connections_at(xw, y, c))
+ 	  return;
+ 	for_all_directions(dir) {
+ 		if (connection_at(xw, y, dir, c)) {
+ 			bitmask |= 1 << dir;
+ 		}
+ 	}
+ 	if (bitmask != 0) {
+ 		tmpdrawlighting = map->vp->draw_lighting;
+ 		tmpdrawcoverage = (!all_see_all && map->vp->draw_cover);
+ 		over = cell_overlay(xw, y);
+ 		xform(map, x, y, &sx, &sy);
+ 		/* (should compute and pass in overlay) */
+ 		UNWRAP_SX(map, sx, 
+ 			draw_connection_line_multiple(map->window, sx, sy, bitmask, map->vp->power, c, 
+ 									map->vp->angle, over, map->solid_color_terrain));
+ 	}
+ }
+ 
+ /* This function draws feature borders as a single (not double) lines, and only
+    between land areas.  It is an alternative to draw_feature_boundaries which is
+    invoked by chosing map->simple_borders. */
+ 
+ void 
+ draw_feature_boundary_simple(Map *map, int x, int y)
+ {
+ 	int 	xw, dir, x1, y1, pwr, wid, wid2, dx1, dy1, dx2, dy2, sx, sy;
+ 
+ 	pwr = map->vp->power;
+ 	wid = bwid2[pwr];
+ 	if (wid == 0)
+ 	  return;
+ 	xw = wrapx(x);
+ 	if (!terrain_visible(dside, xw, y))
+ 	  return;
+ 	if (t_liquid(terrain_at(xw, y)))
+ 	  return;
+ 	PenSize(wid, wid);
+ 	RGBForeColor(&featurecolor);
+ 	PenPat(QDPat(black));
+ 	wid2 = wid / 2;
+ 	/* Very important to use UNWRAPPED x here! */
+ 	xform(map, x, y, &sx, &sy);
+ 
+ 	for_all_directions(dir) {
+ 		if (!interior_point_in_dir(xw, y, dir, &x1, &y1))
+ 		  continue;
+ 		if (t_liquid(terrain_at(wrapx(x1), y1)))
+ 		  continue;
+ 		if (!terrain_visible(dside, wrapx(x1), y1))
+ 		  continue;
+ 		if (feature_at(xw, y) == feature_at(wrapx(x1), y1))
+ 		  continue;
+ 
+ 		dx1 = bsx[pwr][dir]; dy1 = bsy[pwr][dir];
+ 		if (map->vp->angle == 30)
+ 		  dy1 /= 2;
+ 		if (map->vp->angle == 15)
+ 		  dy1 /= 4;
+ 
+ 		dx2 = bsx[pwr][dir+1]; dy2 = bsy[pwr][dir+1];
+ 		if (map->vp->angle == 30)
+ 		  dy2 /= 2;
+ 		if (map->vp->angle == 15)
+ 		  dy2 /= 4;
+ 
+ 		/* Draw the line. */
+ 		MoveTo(sx + dx1 - wid2, sy + dy1 - wid2);
+ 		LineTo(sx + dx2 - wid2, sy + dy2 - wid2);
+ 
+ 		/* UNWRAP line if necessary. */
+ 		if (area.xwrap && sx < 0) {
+ 			sx += map->vp->sxmax;
+ 			MoveTo(sx + dx1 - wid2, sy + dy1 - wid2);
+ 			LineTo(sx + dx2 - wid2, sy + dy2 - wid2);
+ 			sx -= map->vp->sxmax;
+ 		}
+ 	}
+ 	PenNormal();
+ 	ForeColor(blackColor);
+ }
+ 
+ static void
+ draw_feature_boundary(Map *map, int x, int y)
+ {
+ 	int xw, fid, fid1, dir, x1, y1, bitmask, sx, sy;
+ 	Feature *feature;
+ 
+     xw = wrapx(x);
+ 	if (terrain_visible(dside, xw, y)) {
+ 		fid = raw_feature_at(xw, y);
+ 		if (fid == 0)
+ 		  return;
+ 		bitmask = 0;
+ 		/* Decide which edges are borders of the feature. */
+ 		for_all_directions(dir) {
+ 			/* Don't do anything about edge cells. */
+ 			if (interior_point_in_dir(xw, y, dir, &x1, &y1)) {
+ 				fid1 = raw_feature_at(wrapx(x1), y1);
+ 				if (fid != fid1) {
+ 					bitmask |= 1 << dir;
+ 				}
+ 			}
+ 		}
+ 		if (bitmask != 0) {
+ 			xform(map, x, y, &sx, &sy);
+ 			if (bitmask != 0) {
+ 			  UNWRAP_SX(map, sx, 
+ 				draw_feature_borders(map->window, sx, sy, bitmask, map->vp->power));
+ 			}
+ 		}
+ 	}
+ }
+ 
+ /* Draw feature name. */
+ /* (could precompute what the string will lap over and move or truncate str),
+      should be deterministic for each mag, so redraw doesn't scramble */
+ 
+ void
+ draw_feature_name(Map *map, int x, int y)
+ {
+ 	int xw, sx, sy;
+ 	char *str, buf[BUFSIZE];
+ 	Feature *feature;
+ 	
+ 	xw = wrapx(x);
+ 	
+ 	/* Draw the name of a terrain feature. */
+ 	/* (should limit to one cell of feature, preferably centering on quasi-centroid) */	
+ 	if (terrain_visible(dside, xw, y)) {
+ 		feature = feature_at(xw, y);
+ 		if (feature != NULL) {
+ 			if (feature->size > 0) {
+ 				if ((feature->x == xw && feature->y == y)
+ 					|| (feature->x == 0 && feature->y == 0)
+ 					|| 0 /* center far away */) {
+ 					str = feature_desc(feature, buf);
+ 					if (str != NULL) {
+ 						xform(map, x, y, &sx, &sy);
+ 						if (map->featurenames) {
+ 							RGBForeColor(&featurecolor);
+ 							/* use sy instead of sy + hh/2 to prevent drawing on top of unit names */
+ 							UNWRAP_SX(map, sx, 
+ 								draw_legend_text(sx + map->vp->hw/2, sy, 2 * map->vp->uh, 
+ 											   str, 0, map->textmasks, map->optimize_fonts));
+ 							ForeColor(blackColor);
+ 						}
+ 					}
+ 				}
+ 			}
+ 		}
+ 	}
+ }
+ 
+ /* Indicate what kind of people are living in the given row. */
+ 
+ static void
+ draw_people_row(Map *map, int x, int y)
+ {
+ 	int 	pop, xw, sx, sy, sw, sh, ex, ey, ew, eh, dir, x1, y1, pop1;
+ 	int 	con, con1, bitmask1, bitmask2, bitmask3, drawemblemhere;
+ 	int	pwr = map->vp->power; 
+ 	int	ang = map->vp->angle; 
+ 
+ 	xw = wrapx(x);
+ 	if (!terrain_visible(dside, xw, y))
+ 	  return;
+ 	pop = (people_sides_defined() ? people_side_at(xw, y) : NOBODY);
+ 	con = (control_sides_defined() ? control_side_at(xw, y) : NOCONTROL);
+ 	bitmask1 = bitmask2 = bitmask3 = 0;
+ 	drawemblemhere = FALSE;
+ 	/* Decide which edges are borders of the country. */
+ 	for_all_directions(dir) {
+ 		/* Don't do anything about edge cells. */
+ 		if (interior_point_in_dir(xw, y, dir, &x1, &y1)) {
+ 			if (terrain_visible(dside, wrapx(x1), y1)) {
+ 				pop1 = (people_sides_defined() ? people_side_at(wrapx(x1), y1) : NOBODY);
+ 				con1 = (control_sides_defined() ? control_side_at(wrapx(x1), y1) : NOCONTROL);
+ 				if (con != con1) {
+ 					if (con == NOCONTROL || con1 == NOCONTROL) {
+ 						bitmask2 |= 1 << dir;
+ 					} else {
+ 						bitmask1 |= 1 << dir;
+ 					}
+ 				} else if (pop != pop1) {
+ 					/* Borders with uninhabitated regions are drawn differently. */
+ 					if (pop == NOBODY || pop1 == NOBODY) {
+ 						bitmask2 |= 1 << dir;
+ 					} else if (control_sides_defined()) {
+ 						bitmask3 |= 1 << dir;
+ 					} else {
+ 						bitmask1 |= 1 << dir;
+ 					}
+ 				}
+ 			} else {
+ 				/* Draw just people in the cells right at the edge of the known world. */
+ 				drawemblemhere = TRUE;
+ 			}
+ 		}
+ 	}
+ 	/* Now draw both the edges and an emblem for the cell. */
+ 	if ((bitmask1 | bitmask2 | bitmask3) != 0
+ 		|| ((map->vp->draw_people || map->vp->draw_control) && drawemblemhere)) {
+ 		/* Important to use unwrapped x! */
+ 		xform(map, x, y, &sx, &sy);
+ 		RGBForeColor(&frontcolor);		/* Use customized frontline color */
+ 		if (bitmask1 != 0) {
+ 		  UNWRAP_SX(map, sx, 
+ 		  	draw_country_borders(map->window, sx, sy, bitmask1, pwr, 0, ang));
+ 		}
+ 		/* Do not use shaded border to sea and empty land if simple_borders is on. */
+ 		if (bitmask2 != 0 && !map->simple_borders) {
+ 		  UNWRAP_SX(map, sx, 
+ 		  	draw_country_borders(map->window, sx, sy, bitmask2, pwr, 2, ang));
+ 		}
+ 		if (bitmask3 != 0 && !map->simple_borders) {
+ 		  UNWRAP_SX(map, sx, 
+ 		  	draw_country_borders(map->window, sx, sy, bitmask3, pwr, 1, ang));
+ 		}
+ 		ForeColor(blackColor);					/* Restore Fore Color */
+ 
+ 		/* Draw an emblem for the people in the cell. */
+ 		if (map->vp->draw_people && pop != NOBODY) {
+ 			sw = map->vp->uw;  sh = map->vp->uh;
+ 			ew = min(sw, max(8, sw / 2));  eh = min(sh, max(8, sh / 2));
+ 			ex = sx + (map->vp->hw - map->vp->uw) / 2 + sw / 2 - ew / 2;  
+ 			ey = sy + (map->vp->hh - map->vp->uh) / 2 + sh / 2 - eh / 2;
+ 			/* Maybe draw emblem so it will be visible underneath control emblem. */
+ 			if (map->vp->draw_control && con != pop) {
+ 				ex += 2;  ey += 2;
+ 			}
+ 			UNWRAP_SX(map, ex, 
+ 				draw_side_emblem(map->window, ex, ey, ew, eh, pop, plain_emblem));
+ 		}
+ 		if (map->vp->draw_control && con != NOCONTROL && (bitmask1 | bitmask2) != 0) {
+ 			sw = map->vp->uw;  sh = map->vp->uh;
+ 			ew = min(sw, max(8, sw / 2));  eh = min(sh, max(8, sh / 2));
+ 			ex = sx + (map->vp->hw - map->vp->uw) / 2 + sw / 2 - ew / 2;  
+ 			ey = sy + (map->vp->hh - map->vp->uh) / 2 + sh / 2 - eh / 2;
+ 			UNWRAP_SX(map, ex, 
+ 				draw_side_emblem(map->window, ex, ey, ew, eh, con, plain_emblem));
+ 		}
+ 	}
+ }
+ 
+ /* This draws a small set of bar charts, one for each material type. */
+ 
+ static void
+ draw_materials(Map *map, int x, int y)
+ {
+ 	int m, t, sx, sy, mx, my, mw, mh, amt, maxamt, h;
+ 	Rect graphrect;
+ 	
+ 	if (nummtypes == 0)
+ 	  return;
+ 	mw = map->vp->uw / nummtypes /* should be count of displayable materials... */;
+ 	mh = map->vp->uh;
+ 	if (mw <= 2 || mh <= 2)
+ 	  return;
+ 	/* (should this be apparent instead of real terrain?) */
+ 	t = cell_terrain(map, wrapx(x), y);
+ 	xform(map, x, y, &sx, &sy);
+ 	mx = sx + (map->vp->hw - map->vp->uw) / 2;  my = sy + (map->vp->hh - map->vp->uh) / 2;
+ 	for_all_material_types(m) {
+ 		if (map->vp->draw_materials[m] && (maxamt = tm_storage_x(t, m)) > 0) {
+ 			SetRect(&graphrect, mx + m * mw, my, mx + (m + 1) * mw, my + map->vp->uh);
+ 			UNWRAP_RECT(map, graphrect, 
+ 				FrameRect(&graphrect));
+ 			amt = material_view(dside, wrapx(x), y, m);
+ 			h = (amt * mh) / maxamt;
+ 			graphrect.top -= (mh - h);
+ 			/* (should use a per-material color/pattern if available) */
+ 			UNWRAP_RECT(map, graphrect, 
+ 				FillRect(&graphrect, QDPat(black)));
+ 		}
+ 	}
+ }
+ 
+ /* This function draws units at a small magnification */
+ /* Draw all the units visible in the given cell. */
+ /* (x is not wrapped) */
+ 
+ static void
+ draw_units(Map *map, int x, int y)
+ {
+ 	int xw = wrapx(x), sx, sy, sw, sh, uview, u, s;
+ 	Unit *unit;
+ 	Rect tmprect;
+ 	extern PicHandle dotdotdotpicture;
+ 
+ 	if (map->see_all || units_visible(dside, xw, y)) {
+ 		unit = unit_at(xw, y);
+ 		if (unit != NULL) {
+ 			xform(map, x, y, &sx, &sy);
+ 			if (map->vp->uw <= 16) {
+ 				/* Adjust to unit part of cell. */
+ 				sw = map->vp->uw;  sh = map->vp->uh;
+ 				sx += (map->vp->hw - sw) / 2;  sy += (map->vp->hh - sw) / 2;
+ 				if (unit->occupant != NULL
+ 					&& sw >= 8
+ 	    			&& (unit->side == dside || all_see_all || u_see_occupants(unit->type))) {
+ 					/* Draw a "grouping box", in white, but with no occs drawn. */
+ 					SetRect(&tmprect, sx, sy, sx + sw, sy + sh);
+ 					s = side_number(unit->side);
+ 					if (map->boxmasks) {
+ 						if (map->sidecolors && icon_mask_color[s]) {
+ 							RGBBackColor(&(get_sideColor(s, icon_mask_color[s])));
+ 						} else {
+ 							RGBBackColor(&maskcolor);
+ 						}
+ 						UNWRAP_RECT(map, tmprect, 
+ 							FillRect(&tmprect, QDPat(white)));
+ 						BackColor(whiteColor);
+ 					}
+ 					UNWRAP_RECT(map, tmprect, 
+ 						FrameRect(&tmprect));
+ 	    		}
+ 				UNWRAP_SX(map, sx, 
+ 					draw_unit_image(map->window, sx, sy, sw, sh, unit->type, 
+ 								   side_number(unit->side), !completed(unit), TRUE));
+ 				/* Indicate if more than one stacked here.  Since this may cover up the unit's
+ 				   picture, adjust it down as far as possible while remaining inside the
+ 				   "cell minus grid" area. */
+ 				if (unit->nexthere != NULL && sw > 8) {
+ 					SetRect(&tmprect, sx + sw/2 - 6, sy + sh - 3,
+ 									  sx + sw/2 + 6, sy + sh + 1);
+ 					/* (should clip to fit in cell) */
+ 					/* (should do a copybits) */
+ 					UNWRAP_RECT(map, tmprect, 
+ 						DrawPicture(dotdotdotpicture, &tmprect));
+ 				}
+ 				if (map->vp->draw_names) {
+ 					/* Draw city names in uniform size and position */
+ 					if (!mobile(unit->type)) {
+ 					UNWRAP_SX(map, sx, 
+ 						draw_unit_name(unit, sx, sy, map->vp->uw, map->vp->uh, 
+ 									  map->textmasks, map->optimize_fonts)); 
+ 					} else
+ 					UNWRAP_SX(map, sx, 
+ 						draw_unit_name(unit, sx, sy, sw, sh, 
+ 									  map->textmasks, map->optimize_fonts));
+ 				}
+ 			} else {
+ 				for_all_stack(xw, y, unit) {
+ 					if (1 /* doesnt work right? - side_sees_unit(dside, unit) */) {
+ 						m_xform_unit(map, unit, &sx, &sy, &sw, &sh);
+ 						draw_unit_and_occs(map, unit, sx, sy, sw, sh);
+ 					}
+ 				}
+ 			}
+ 		}
+ 	} else {
+ 		uview = unit_view(dside, xw, y);
+ 		if (uview != EMPTY) {
+ 			u = vtype(uview);  s = vside(uview);
+ 			xform(map, x, y, &sx, &sy);
+ 			sw = map->vp->uw;  sh = map->vp->uh;
+ 			/* Adjust to unit part of cell. */
+ 			sx += (map->vp->hw - sw) / 2;  sy += (map->vp->hh - sh) / 2;
+ 			UNWRAP_SX(map, sx, 
+ 				draw_unit_image(map->window, sx, sy, sw, sh, u, s, 0, TRUE));
+ 		}
+ 	}
+ }
+ 
+ /* This function draws units at a normal or high magnification */
+ 
+ static void
+ draw_unit_and_occs(Map *map, Unit *unit, int sx, int sy, int sw, int sh)
+ {
+ 	int u = unit->type, s = side_number(unit->side), sx2, sy2, sw2, sh2;
+ 	int emblem = TRUE;
+ 	Unit *occ;
+ 	Rect tmprect;
+ 	
+ 	/* If an occupant's side is the same as its transport's, then there's
+ 	   really no need to draw its side emblem, since the transport's emblem
+ 	   will also be visible. */
+ 	if (unit->transport && unit->side == unit->transport->side)
+ 	  emblem = FALSE;
+ 	if (unit->occupant != NULL
+ 		&& sw > 8
+ 	    && (dside->see_all
+ 		    || unit->side == dside
+ 		    || u_see_occupants(unit->type)
+ 		    || side_owns_occupant(dside, unit))) {
+ 
+ 		/* Draw a sort of "grouping box", in white. */
+ 		/* Make box 1 pixel smaller to avoid leakage of its lower left corner into the grid. */
+ 		SetRect(&tmprect, sx, sy, sx + sw - 1, sy + sh - 1);
+ 		if (map->boxmasks) {
+ 			if (map->sidecolors && icon_mask_color[s]) {
+ 				RGBBackColor(&(get_sideColor(s, icon_mask_color[s])));
+ 			} else {
+ 				RGBBackColor(&maskcolor);
+ 			}
+ 			UNWRAP_RECT(map, tmprect, 
+ 				FillRect(&tmprect, QDPat(white)));
+ 			BackColor(whiteColor);
+ 		}
+ 		UNWRAP_RECT(map, tmprect, 
+ 			FrameRect(&tmprect));
+ 			
+ 		/* Draw the transport in the UL quarter of the box. */
+ 		m_xform_occupant(map, unit, unit, sx, sy, sw, sh, &sx2, &sy2, &sw2, &sh2);
+ 		UNWRAP_SX(map, sx2, 
+ 			draw_unit_image(map->window, sx2, sy2, sw2, sh2, u, s, !completed(unit), TRUE));
+ 		if (map->vp->draw_names) {
+ 			/* Draw city names in uniform size and position */
+ 			if (!mobile(unit->type)) {
+ 			    UNWRAP_SX(map, sx, 
+ 				draw_unit_name(unit, sx, sy, map->vp->uw, map->vp->uh, 
+ 						 	 map->textmasks, map->optimize_fonts));  
+ 			/* sw2 doubled moves the name out of the box so that it can be read more easily */
+ 			} else {
+ 			    UNWRAP_SX(map, sx2, 
+ 				draw_unit_name(unit, sx2, sy2, 2 * sw2, sh2, 
+ 							 map->textmasks, map->optimize_fonts)); 
+ 			}
+ 		}				
+ 		/* Draw all the occupants, in the bottom half of the box. */
+ 		for_all_occupants(unit, occ) {
+ 			m_xform_occupant(map, unit, occ, sx, sy, sw, sh, &sx2, &sy2, &sw2, &sh2);
+ 			/* Accomodate the smaller box by moving occs 2 pixels up. */
+ 			draw_unit_and_occs(map, occ, sx2, sy2 - 2, sw2, sh2);	/* RECURSION! */
+ 		}
+ 	} else { /* Just draw the one unit. */
+ 	    UNWRAP_SX(map, sx, 
+ 		draw_unit_image(map->window, sx, sy, sw, sh, u, s, !completed(unit), emblem));
+ 		if (map->vp->draw_names) {
+ 			/* Draw city names in uniform size and position */
+ 			if (!mobile(unit->type)) {
+ 			      UNWRAP_SX(map, sx, 
+ 				draw_unit_name(unit, sx, sy, map->vp->uw, map->vp->uh, 
+ 							 map->textmasks, map->optimize_fonts));  
+ 			} else {
+ 			      UNWRAP_SX(map, sx, 
+ 				draw_unit_name(unit, sx, sy, sw, sh, 
+ 							 map->textmasks, map->optimize_fonts));
+ 			}
+ 		}
+ 	}
+ }
+ 
+ static void
+ draw_ai_region(Map *map, int x, int y)
+ {
+ 	int xw, thid, sx, sy, dir, x1, y1, thid1, bitmask = 0;
+ 
+ 	xw = wrapx(x);
+ 	thid = ai_region_at(dside, xw, y);
+ 	/* Decide which edges are borders of the theater. */
+ 	for_all_directions(dir) {
+ 		/* Don't do anything about edge cells. */
+ 		if (interior_point_in_dir(xw, y, dir, &x1, &y1)) {
+ 			thid1 = ai_region_at(dside, wrapx(x1), y1);
+ 			if (thid != thid1) {
+ 				bitmask |= 1 << dir;
+ 			}
+ 		}
+ 	}
+ 	if (bitmask != 0) {
+ 		xform(map, x, y, &sx, &sy);
+ 		if (bitmask != 0) {
+ 		    UNWRAP_SX(map, sx, 
+ 			draw_ai_region_borders(map->window, sx, sy, bitmask, map->vp->power));
+ 		}
+ 	}
+ }
diff -rcN xconq-7.2.1/mac/macwins.c xconq-7.2.2/mac/macwins.c
*** xconq-7.2.1/mac/macwins.c	Mon Apr  6 01:24:29 1998
--- xconq-7.2.2/mac/macwins.c	Fri May 29 17:17:42 1998
***************
*** 30,35 ****
--- 30,42 ----
  static void calc_history_layout(void);
  static void set_history_scrollbar(void);
  
+ // --- 68K COLORSCHEME BUG FIX ----------------------------------------------------
+ 
+ extern char **current_colorscheme;			/* Color schemes by name (red,pink,blue) */
+ 									/* Defined in maccolors.c */
+ 									
+ // ----------------------------------------------------------------------------
+ 
  /* Globals for the game window. */
  
  WindowPtr gamewin = nil;
***************
*** 1177,1183 ****
  				   so as to avoid fragmentation */				
  				reinit_all_emblem_images();
  
! 				dissect_colorscheme(side_number(side), side->colorscheme);
  				ui_update_state();
  				save_preferences();
  				
--- 1184,1198 ----
  				   so as to avoid fragmentation */				
  				reinit_all_emblem_images();
  
! // --- 68K COLORSCHEME BUG FIX ---------------------------------------
! 
! 				current_colorscheme[side_number(side)] = side->colorscheme;
! 				dissect_colorscheme(side_number(side));
! 
! //				dissect_colorscheme(side_number(side), side->colorscheme);
! 
! // ---------------------------------------------------------------
! 
  				ui_update_state();
  				save_preferences();
  				
diff -rcN xconq-7.2.1/x11/xinit.c xconq-7.2.2/x11/xinit.c
*** xconq-7.2.1/x11/xinit.c	Mon May 18 19:07:53 1998
--- xconq-7.2.2/x11/xinit.c	Wed Jun 10 19:52:10 1998
***************
*** 838,844 ****
      tmp_display = side->ui->dpy;
      tmp_root_window = side->ui->rootwin;
      for_all_unit_types(u) {
! 	imf = get_unit_type_images(side, u, "c");
  	/* (should fabricate something as a substitute) */
  	if (DebugG)
  	  describe_imf(side, "unit type", u_type_name(u), imf);
--- 838,844 ----
      tmp_display = side->ui->dpy;
      tmp_root_window = side->ui->rootwin;
      for_all_unit_types(u) {
! 	imf = get_unit_type_images(side, u, "s");
  	/* (should fabricate something as a substitute) */
  	if (DebugG)
  	  describe_imf(side, "unit type", u_type_name(u), imf);
***************
*** 861,867 ****
  {
      int t, p;
      ImageFamily *imf;
!     Image *timg;
      X11Image *ximg;
  
      side->ui->timages =
--- 861,867 ----
  {
      int t, p;
      ImageFamily *imf;
!     Image *img, *timg;
      X11Image *ximg;
  
      side->ui->timages =
***************
*** 889,895 ****
  	    }
  	}
  	/* Look for a solid color. */
! 	timg = best_image(side->ui->timages[t], 1, 1);
  	if (timg != NULL && timg->w == 1 && timg->h == 1) {
  	    if (timg->hook) {
  		ximg = (X11Image *) timg->hook;
--- 889,901 ----
  	    }
  	}
  	/* Look for a solid color. */
! 	timg = NULL;
! 	for_all_images(side->ui->timages[t], img) {
! 	    if (img->w == 1 && img->h == 1) {
! 		timg = img;
! 		break;
! 	    }
! 	}
  	if (timg != NULL && timg->w == 1 && timg->h == 1) {
  	    if (timg->hook) {
  		ximg = (X11Image *) timg->hook;
diff -rcN xconq-7.2.1/xconq.spec xconq-7.2.2/xconq.spec
*** xconq-7.2.1/xconq.spec	Thu May 21 19:12:49 1998
--- xconq-7.2.2/xconq.spec	Tue Jun 30 20:58:53 1998
***************
*** 1,8 ****
  Name: xconq
  Summary: X11 empire-building strategy game, with game design language
! Version: 7.2.1
  Release: 1
! Source: ftp://ftp.cygnus.com/pub/xconq/xconq-7.2.1.tar.gz
  Copyright: GPL
  Group:  X11/Games/Strategy
  
--- 1,8 ----
  Name: xconq
  Summary: X11 empire-building strategy game, with game design language
! Version: 7.2.2
  Release: 1
! Source: ftp://ftp.cygnus.com/pub/xconq/xconq-7.2.2.tar.gz
  Copyright: GPL
  Group:  X11/Games/Strategy
  
***************
*** 21,27 ****
  them.
  
  %prep
! %setupcd -n xconq-7.2.1
  
  %build
  xmkmf
--- 21,27 ----
  them.
  
  %prep
! %setupcd -n xconq-7.2.2
  
  %build
  xmkmf
