/* Advanced unit and advance code for the Mac interface to Xconq.
   Copyright (C) 1998-1999 Hans Ronne.

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"

/* Base numbers of resource cicns. */
#define LARGE_CICNS 2000
#define SMALL_CICNS 2100

/* Max number of facilities and occs displayed in city dialog. Should always agree with the DITL!  */
#define MAX_DISPLAYED_FACS 12
#define MAX_DISPLAYED_OCCS 24
#define CLEAR_AGENDA 99

int default_drawsizes = TRUE;		/* Draw unit (city) sizes in maps and lists. */

extern void city_dialog(Map *map, Unit *unit);		
extern void mac_init_cicn(Image *img);
extern void unit_advance_dialog(Unit *unit);			
extern void global_advance_dialog(Side *side, Unit *unit, int advance);			
extern void unit_plan_dialog(Unit *unit);
extern int unit_build_dialog(Unit *unit);
extern int has_advance_to_research(Side *side, int atype);
extern CIconHandle mac_create_cicn(Image *img);

static void copy_rect_from_gworld(WindowPtr win, Map *map, Rect cityrect, Rect itemrect);
static void draw_city_statistics(WindowPtr win, Unit *unit);
static void plot_resource_cicns(Map *map, Rect plotrect, int x, int y);
static void draw_landuse_near_unit(Map *map, WindowPtr win, Rect itemrect, Unit *unit, int near);
static void toggle_landuse_one_cell(Map *map, WindowPtr win, Rect itemrect, Unit *unit, int x, int y);

/*
	Main city dialog. Called by ctrl-clicking on the unit or by City Dialog in the Play menu. 
*/

void
city_dialog(Map *map, Unit *unit)
{
	short 		ditem, mitem, done = FALSE, disabled, i, u, u2, a, x = unit->x, y = unit->y, x1, y1;
	int			run =0, width, height, downsx, downsy, downx, downy, sx, sy, m, d;
	char			buf[32], cname[32], uname[32], sname[32];
	MenuHandle	buildMenu, advanceMenu, planMenu;
	Side			*side = unit->side;
	Rect 			itemrect, cityrect;
	Str255 		pname, pnumber;
	Handle 		itemhandle;  
	RGBColor		oldBack;
	GrafPtr 		oldport;
	Point			mouse;
 	DialogPtr		win;

	Unit			*occ;

	/* Skip if this is not an advanced unit. */
	if (!u_advanced(unit->type))
		return;
	/* Skip if we may not examine this unit at all. */	
	if (!side_sees_unit(dside, unit))
		return;
	/* Give controlling side (including debuggers 
	and designers) full control. */
	if (side_controls_unit(dside, unit))
		disabled = FALSE;

	/* Never happens, but check anyway.*/
	if (unit->plan == NULL)
		init_unit_plan(unit);

	/* Draw unit info for the unit. */
	unselect_all(map);
	select_unit_on_map(map, unit);
	draw_selections(map);

	/* Make sure visibility is up to date. */
	if (side) {
		for_all_cells_within_reach(unit, x1, y1) {
			if (terrain_visible(side, x1, y1)) {
				see_exact(side, x1, y1);
			}
		}
	}
	win = GetNewDialog(dCity, NULL, (DialogPtr) -1);
	planMenu = GetMenu(mPlanTypes);
	advanceMenu = GetMenu(mAdvancePopup);
	buildMenu = GetMenu(mBuildPopup);
	GetPort(&oldport);	
	SetPort(win);

	/* Get the type name of unit that is being constructed, if any. */
	if (unit->plan->tasks 
	      && unit->plan->tasks->type == TASK_BUILD
	      && is_unit_type(unit->plan->tasks->args[0])) {
	   	 strcpy(uname, u_type_name(unit->plan->tasks->args[0]));
	} else strcpy(uname, "Idle");
		/* Load constructable unit type names into popup menu. */
	for_all_unit_types(u) {
		if (type_allowed_on_side(u, side)
 		      && has_advance_to_build(side, u)
		      && could_create(unit->type, u) 
		      && (type_can_occupy(u, unit)
		    	   || u == unit->plan->tasks->args[0])) {
	   		c2p(u_type_name(u), pname);
			AppendMenu(buildMenu, pname);
		}
	}

	/* Get the advance that is being researched by this unit, if any. */
	if (unit->curadvance > 0) { 
	   	 strcpy(sname, a_type_name(unit->curadvance));
	} else strcpy(sname, "Idle"); 
	/* Load scientific advances that can be researched into the popup menu. */
	if (unit->side) {
		for_all_advance_types(a) {
			if (has_advance_to_research(side, a)
			     &! has_advance(side, a)) {
	   			c2p(a_type_name(a), pname);
				AppendMenu(advanceMenu, pname);
			}
		}
	}

	GetDItem(win, diCityMap, NULL, NULL, &itemrect);
	width = itemrect.right - itemrect.left;
	height = itemrect.bottom - itemrect.top;

	/* Save the Dialog background color. */
	oldBack = ((CGrafPtr) win)->rgbBkColor;
	BackColor(whiteColor);

	/* Draw background and frame. */
	InsetRect(&itemrect, -2, -2);
	RGBForeColor(&backcolor);
	PaintRect(&itemrect);
	PenSize(2, 2);
	ForeColor(blackColor);
	FrameRect(&itemrect);
	PenNormal();
	InsetRect(&itemrect, 2, 2);

	/* Find the city position. */
	xform(map, x, y, &sx, &sy);

	/* Center cityrect around the city. */
	cityrect.left 	= sx + map->vp->hw/2 - width/2;
	cityrect.right 	= sx + map->vp->hw/2 + width/2;
	cityrect.top 	= sy + map->vp->hh/2 - height/2;
	cityrect.bottom 	= sy + map->vp->hh/2 + height/2;
	
	/* Find cityrect position in the offscreen gworld. */
	OffsetRect(&cityrect, map->offsetx + map->bufx - map->conw, 
				        map->offsety + map->bufy - map->toph);

	/* Copy cityrect from the offscreen gworld. */
	copy_rect_from_gworld(win, map, cityrect, itemrect);

	/* Handle cityrect part that extends beyond left end of gworld. */
	if (area.xwrap && cityrect.left < map->gworldPortPtr->portRect.left) {
		OffsetRect(&cityrect, map->vp->sxmax, 0);
		copy_rect_from_gworld(win, map, cityrect, itemrect);
	}
	/* Handle cityrect part that extends beyond right end of gworld. */
	if (area.xwrap && cityrect.right > map->gworldPortPtr->portRect.right) {
		OffsetRect(&cityrect, -map->vp->sxmax, 0);
		copy_rect_from_gworld(win, map, cityrect, itemrect);
	}
			
	/* Draw landuse within the cityrect. */
	d = max(width/map->vp->hw, height/map->vp->hh);	/* d could be smaller? */
	draw_landuse_near_unit(map, win, itemrect, unit, d);

	/* Restore dialog background. */
	RGBBackColor(&oldBack);

	/*Hide "click map text from disabled sides. */
	if (disabled)
		HideDItem(win, diCityClickText);

	/* Set the AI control checkbox. */
	GetDItem(win, diCityAICheck, NULL, &itemhandle, NULL);
	SetCtlValue((ControlHandle) itemhandle, unit->plan->aicontrol);
	/* Don't allow disabled sides to use the AI box. */
	if (disabled)
		HiliteControl((ControlHandle) itemhandle, 255); 

	/* Set the plan checkbox. */
	GetDItem(win, diCityPlanCheck, NULL, &itemhandle, NULL);
	SetCtlValue((ControlHandle) itemhandle, unit->autoplan);

	/* Set the advance checkbox. */
	GetDItem(win, diCityAdvanceCheck, NULL, &itemhandle, NULL);
	SetCtlValue((ControlHandle) itemhandle, unit->autoresearch);

	/* Set the autobuild radio button. */
	GetDItem(win, diCityBuildCheck, NULL, &itemhandle, NULL);
	SetCtlValue((ControlHandle) itemhandle, unit->autobuild);

	/* Set the manual build radio button. */
	GetDItem(win, diCityBuildRepeat, NULL, &itemhandle, NULL);
	SetCtlValue((ControlHandle) itemhandle, !unit->autobuild);

	/* Draw the run in its textfield. */
	GetDItem(win, diCityBuildEdit, NULL, &itemhandle, NULL);
	if (unit->plan->last_task.args[3] > 0)
		NumToString(unit->plan->last_task.args[3], pname);
	else	NumToString(g_default_runlength(), pname);
	SetIText(itemhandle, pname);
	SelIText(win, diCityBuildEdit, 0, 32767);

	/* Set plan type popup menu to current plan. */
	GetDItem(win, diCityPlanPopup, NULL, &itemhandle, NULL);
	if (unit->plan->type == PLAN_NONE)
		SetCtlValue((ControlHandle) itemhandle, miPlanTypeNone);
	else if (unit->plan->type == PLAN_PASSIVE)
		SetCtlValue((ControlHandle) itemhandle, miPlanTypePassive);
	else if (unit->plan->type == PLAN_DEFENSIVE)
		SetCtlValue((ControlHandle) itemhandle, miPlanTypeDefensive);
	else if (unit->plan->type == PLAN_EXPLORATORY)
		SetCtlValue((ControlHandle) itemhandle, miPlanTypeExploratory);
	else if (unit->plan->type == PLAN_OFFENSIVE)
		SetCtlValue((ControlHandle) itemhandle, miPlanTypeOffensive);
	else if (unit->plan->type == PLAN_COLONIZING)
		SetCtlValue((ControlHandle) itemhandle, miPlanTypeColonizing);
	else if (unit->plan->type == PLAN_IMPROVING)
		SetCtlValue((ControlHandle) itemhandle, miPlanTypeImproving);
	else if (unit->plan->type == PLAN_RANDOM)
		SetCtlValue((ControlHandle) itemhandle, miPlanTypeRandom);

	/* Also update the checkmarks, since this menu is used elsewhere. */
	CheckItem(planMenu, miPlanTypeNone, (unit->plan->type == PLAN_NONE));
	CheckItem(planMenu, miPlanTypePassive, (unit->plan->type == PLAN_PASSIVE));
	CheckItem(planMenu, miPlanTypeDefensive, (unit->plan->type == PLAN_DEFENSIVE));
	CheckItem(planMenu, miPlanTypeExploratory, (unit->plan->type == PLAN_EXPLORATORY));
	CheckItem(planMenu, miPlanTypeOffensive, (unit->plan->type == PLAN_OFFENSIVE));
	CheckItem(planMenu, miPlanTypeColonizing, (unit->plan->type == PLAN_COLONIZING));
	CheckItem(planMenu, miPlanTypeImproving, (unit->plan->type == PLAN_IMPROVING));
	CheckItem(planMenu, miPlanTypeRandom, (unit->plan->type == PLAN_RANDOM));

	/* Disable controls for disabled sides and when under active AI control. */
	if (disabled || (side_has_ai(side) && unit->plan->aicontrol)) {
		GetDItem(win, diCityPlanCheck, NULL, &itemhandle, NULL);
		HiliteControl((ControlHandle) itemhandle, 255); 
		GetDItem(win, diCityAdvanceCheck, NULL, &itemhandle, NULL);
		HiliteControl((ControlHandle) itemhandle, 255); 
		GetDItem(win, diCityBuildCheck, NULL, &itemhandle, NULL);
		HiliteControl((ControlHandle) itemhandle, 255); 
		GetDItem(win, diCityBuildEdit, NULL, &itemhandle, NULL);
		HiliteControl((ControlHandle) itemhandle, 255); 
		GetDItem(win, diCityBuildRepeat, NULL, &itemhandle, NULL);
		HiliteControl((ControlHandle) itemhandle, 255); 
		GetDItem(win, diCityPlanPopup, NULL, &itemhandle, NULL);
		HiliteControl((ControlHandle) itemhandle, 255); 
		GetDItem(win, diCityAdvancePopup, NULL, &itemhandle, NULL);
		HiliteControl((ControlHandle) itemhandle, 255); 
		GetDItem(win, diCityBuildPopup, NULL, &itemhandle, NULL);
		HiliteControl((ControlHandle) itemhandle, 255); 
	}
	
	/* Draw all the other text fields. */
	draw_city_statistics(win, unit);

	ShowWindow(win);
	while (!done) {

		SetCursor(&QD(arrow));
		draw_default_button(win, OkButton);

		/* Set build popup to uname. */
		m = CountMItems(buildMenu);
		GetDItem(win, diCityBuildPopup, NULL, &itemhandle, NULL);
		SetCtlMax((ControlHandle) itemhandle, m);
		for (i = 1; i <= m; i++) {
			GetItem(buildMenu, i, pname);
			p2c(pname, cname);
			if (strcmp(uname, cname) != 0)
				continue;
			SetCtlValue((ControlHandle) itemhandle, i);
		}

		/* Set advance popup to sname. */
		m = CountMItems(advanceMenu);
		GetDItem(win, diCityAdvancePopup, NULL, &itemhandle, NULL);
		SetCtlMax((ControlHandle) itemhandle, m);
		for (i = 1; i <= m; i++) {
			GetItem(advanceMenu, i, pname);
			p2c(pname, cname);
			if (strcmp(sname, cname) != 0)
				continue;
			SetCtlValue((ControlHandle) itemhandle, i);
		}

		ModalDialog(NULL, &ditem);
		switch (ditem) {

			case 	diCityMap:		/* Find the cell that was clicked. */
				if (disabled)	/* Don't allow other sides to change things. */	
					break;
				get_global_mouse(&mouse);	
				GlobalToLocal(&mouse);
				downsx = mouse.h - itemrect.left + sx + map->vp->hw/2 - width/2;
				downsy = mouse.v - itemrect.top + sy + map->vp->hh/2 - height/2;
				m_nearest_cell(map, downsx, downsy, &downx, &downy);
				if (!inside_area(downx, downy)) 
					break;
				if (!cell_is_within_reach(unit, downx, downy))
					break;
				/* Toggle landuse on or off for the cell. */
				toggle_landuse_one_cell(map, win, itemrect, unit, downx, downy);
				break;

			case diCityAICheck: 	/* Toggle AI control checkbox. */
				GetDItem(win, ditem, NULL, &itemhandle, NULL);
				SetCtlValue((ControlHandle) itemhandle, !GetCtlValue((ControlHandle) itemhandle));
				if (side_has_ai(side) && GetCtlValue((ControlHandle) itemhandle)) {
					/* Disable controls. */
					GetDItem(win, diCityPlanCheck, NULL, &itemhandle, NULL);
					HiliteControl((ControlHandle) itemhandle, 255); 
					GetDItem(win, diCityAdvanceCheck, NULL, &itemhandle, NULL);
					HiliteControl((ControlHandle) itemhandle, 255); 
					GetDItem(win, diCityBuildCheck, NULL, &itemhandle, NULL);
					HiliteControl((ControlHandle) itemhandle, 255); 
					GetDItem(win, diCityBuildEdit, NULL, &itemhandle, NULL);
					HiliteControl((ControlHandle) itemhandle, 255); 
					GetDItem(win, diCityBuildRepeat, NULL, &itemhandle, NULL);
					HiliteControl((ControlHandle) itemhandle, 255); 
					GetDItem(win, diCityPlanPopup, NULL, &itemhandle, NULL);
					HiliteControl((ControlHandle) itemhandle, 255); 
					GetDItem(win, diCityAdvancePopup, NULL, &itemhandle, NULL);
					HiliteControl((ControlHandle) itemhandle, 255); 
					GetDItem(win, diCityBuildPopup, NULL, &itemhandle, NULL);
					HiliteControl((ControlHandle) itemhandle, 255); 
					/* Update AI control info. */
					GetDItem(win, diCityStats, NULL, &itemhandle, NULL);
					strcpy(buf, "Under ");
					if (indep(unit))
						strcat(buf, "brainless");
					else 	strcat(buf, side->player->aitypename);
					strcat(buf, " control");
					c2p(buf, pname);
					SetIText(itemhandle, pname);
				} else {
					/* Enable controls. */
					GetDItem(win, diCityPlanCheck, NULL, &itemhandle, NULL);
					HiliteControl((ControlHandle) itemhandle, 0); 
					GetDItem(win, diCityAdvanceCheck, NULL, &itemhandle, NULL);
					HiliteControl((ControlHandle) itemhandle, 0); 
					GetDItem(win, diCityBuildCheck, NULL, &itemhandle, NULL);
					HiliteControl((ControlHandle) itemhandle, 0); 
					GetDItem(win, diCityBuildEdit, NULL, &itemhandle, NULL);
					HiliteControl((ControlHandle) itemhandle, 0); 
					GetDItem(win, diCityBuildRepeat, NULL, &itemhandle, NULL);
					HiliteControl((ControlHandle) itemhandle, 0); 
					GetDItem(win, diCityPlanPopup, NULL, &itemhandle, NULL);
					HiliteControl((ControlHandle) itemhandle, 0); 
					GetDItem(win, diCityAdvancePopup, NULL, &itemhandle, NULL);
					HiliteControl((ControlHandle) itemhandle, 0); 
					GetDItem(win, diCityBuildPopup, NULL, &itemhandle, NULL);
					HiliteControl((ControlHandle) itemhandle, 0); 
					/* Update AI control info. */
					GetDItem(win, diCityStats, NULL, &itemhandle, NULL);
					strcpy(buf, "Under manual control");
					c2p(buf, pname);
					SetIText(itemhandle, pname);
				}
				break;

			case diCityPlanCheck: 		/* Toggle autoplan checkbox. */
				GetDItem(win, ditem, NULL, &itemhandle, NULL);
				SetCtlValue((ControlHandle) itemhandle, !GetCtlValue((ControlHandle) itemhandle));
				break;

			case diCityAdvanceCheck: 	/* Toggle autoresearch checkbox. */
				GetDItem(win, ditem, NULL, &itemhandle, NULL);
				SetCtlValue((ControlHandle) itemhandle, !GetCtlValue((ControlHandle) itemhandle));
				break;

			case diCityBuildCheck: 	/* Switch autobuild button. */
				GetDItem(win, ditem, NULL, &itemhandle, NULL);
				SetCtlValue((ControlHandle) itemhandle, !GetCtlValue((ControlHandle) itemhandle));
				GetDItem(win, diCityBuildRepeat, NULL, &itemhandle, NULL);
				SetCtlValue((ControlHandle) itemhandle, !GetCtlValue((ControlHandle) itemhandle));
				break;

			case diCityBuildRepeat: 	/* Switch manual build button. */
				GetDItem(win, ditem, NULL, &itemhandle, NULL);
				SetCtlValue((ControlHandle) itemhandle, !GetCtlValue((ControlHandle) itemhandle));
				GetDItem(win, diCityBuildCheck, NULL, &itemhandle, NULL);
				SetCtlValue((ControlHandle) itemhandle, !GetCtlValue((ControlHandle) itemhandle));
				break;

			case 	diCityBuildPopup: 	/* Find selected unit type. */
				GetDItem(win, ditem, NULL, &itemhandle, NULL);
				mitem = GetCtlValue((ControlHandle) itemhandle);
				GetItem(buildMenu, mitem, pname);
				p2c(pname, uname);
		    		break;

			case 	diCityAdvancePopup: 	/* Find selected advance type. */
				GetDItem(win, ditem, NULL, &itemhandle, NULL);
				mitem = GetCtlValue((ControlHandle) itemhandle);
				GetItem(advanceMenu, mitem, pname);
				p2c(pname, sname);
		    		break;

			case 	OkButton:
				/* Don't allow others to save any changes. */
				if (disabled) {
					done = TRUE;
					break;
				}
				/* Save the AI control state. */
				GetDItem(win, diCityAICheck, NULL, &itemhandle, NULL);
				unit->plan->aicontrol = GetCtlValue((ControlHandle) itemhandle);

				/* Save the autoplan state. */
				GetDItem(win, diCityPlanCheck, NULL, &itemhandle, NULL);
				unit->autoplan = GetCtlValue((ControlHandle) itemhandle);

				/* Save the autoresearch state. */
				GetDItem(win, diCityAdvanceCheck, NULL, &itemhandle, NULL);
				unit->autoresearch = GetCtlValue((ControlHandle) itemhandle);

				/* Save the autobuild state. */
				GetDItem(win, diCityBuildCheck, NULL, &itemhandle, NULL);
				unit->autobuild = GetCtlValue((ControlHandle) itemhandle);

				/* Save the selected plan type. */
				GetDItem(win, diCityPlanPopup, NULL, &itemhandle, NULL);
				mitem = GetCtlValue((ControlHandle) itemhandle);
				switch (mitem)  {
					case miPlanTypeNone:
						net_set_unit_plan_type(side, unit, PLAN_NONE);
						break;
					case miPlanTypePassive:
						net_set_unit_plan_type(side, unit, PLAN_PASSIVE);
						break;
					case miPlanTypeDefensive:
						net_set_unit_plan_type(side, unit, PLAN_DEFENSIVE);
						break;
					case miPlanTypeExploratory:
						net_set_unit_plan_type(side, unit, PLAN_EXPLORATORY);
						break;
					case miPlanTypeOffensive:
						net_set_unit_plan_type(side, unit, PLAN_OFFENSIVE);
						break;
					case miPlanTypeColonizing:
						net_set_unit_plan_type(side, unit, PLAN_COLONIZING);
						break;
					case miPlanTypeImproving:
						net_set_unit_plan_type(side, unit, PLAN_IMPROVING);
						break;
					case miPlanTypeRandom:
						net_set_unit_plan_type(side, unit, PLAN_RANDOM);
						break;
				}
				/* Save the selected research task. */
				if (strcmp("Idle", sname) == 0)
					unit->curadvance = NOADVANCE;
				else for_all_advance_types(a) {
					if (strcmp(a_type_name(a), sname) != 0)
						continue;
					unit->curadvance = a;
					break;
				}
				/* Always set runlength to default if on autobuild. */
				if (unit->autobuild 
				    || (side && side_has_ai(side) && unit->plan->aicontrol))
					run = g_default_runlength();
				else {					
					/* Else get the runlength from its text field. */
					GetDItem(win, diCityBuildEdit, NULL, &itemhandle, NULL);
		        			GetIText(itemhandle, pname);
					StringToNum(pname, (long *) &run);
					run = min(max(run, 0), CLEAR_AGENDA);
				}

				/* Save the selected build task. */
				u = NONUTYPE;
				for_all_unit_types(u2) {
					/* Find the utype that was selected in the menu. */
					if (strcmp(u_type_name(u2), uname) == NULL) {
						net_set_build_task(unit, u2, run);
						u = u2;
						break;
					}
				}
				if (u == NONUTYPE) {
					/* No matching utype means "Idle" was selected. */
					net_clear_task_agenda(side, unit);
					net_set_unit_asleep(side, unit, TRUE, FALSE);
				}
				done = TRUE;
				break;

			case CancelButton:
				done = TRUE;
				break;

			default:
				break;
		}
	}
	/* Close the dialog. */
	DisposeDialog(win);
	/* Restore old port. */
	SetPort(oldport);
	/* Restore old selection in map. */
	unselect_unit_on_map(map, unit);
	update_cell(map, unit->x, unit->y);
}

static void
copy_rect_from_gworld(WindowPtr win, Map *map, Rect cityrect, Rect itemrect)
{
	Rect	portrect = map->gworldPortPtr->portRect;
	Rect	destrect = itemrect;
	Rect	sourcerect;
	
	/* Clip sourcerect to portrect. */
	SectRect(&cityrect, &portrect, &sourcerect);

	/* Clip destrect so that it will match sourcerect. */ 
	destrect.top 	+= max(0, portrect.top - cityrect.top);
	destrect.bottom 	-= max(0, cityrect.bottom - portrect.bottom);
	destrect.left 	+= max(0, portrect.left - cityrect.left);
	destrect.right 	-= max(0, cityrect.right - portrect.right);

	/* Copy from the map gworld. */
	LockPixels(GetGWorldPixMap(map->gworldPortPtr));
	CopyBits(  &((GrafPtr) map->gworldPortPtr)->portBits,
			&((GrafPtr) win)->portBits,
			&sourcerect, &destrect, srcCopy, NULL  );
	UnlockPixels(GetGWorldPixMap(map->gworldPortPtr));
}		

void
draw_city_statistics(WindowPtr win, Unit *unit)
{
	int			occupants[MAX_DISPLAYED_OCCS] = {0};
	char			cname[32], sname[32], buf[BUFSIZE];
	RGBColor 		tmpcolor, oldBack;
	Str255 		pname, pnumber;
	Handle 		itemhandle;  
	CIconHandle 	cicnhandle;
	Rect			itemrect;
	Unit			*unit2;
	int			i, m, n; 

	/* Draw the unit icon. */
	GetDItem(win, diCityIcon, NULL, NULL, &itemrect);
	draw_unit_image(win, itemrect.left, itemrect.top,
				itemrect.right - itemrect.left, itemrect.bottom - itemrect.top,
				unit->type, side_number(unit->side), !completed(unit), TRUE);
	/* Draw unit size on top of the icon. */
/*	if (default_drawsizes) 
		draw_unit_size(unit, win, tmprect.left, tmprect.top,
				tmprect.right - tmprect.left, tmprect.bottom - tmprect.top);

	/* Draw the unit's name, type and side. */
	GetDItem(win, diCityName, NULL, &itemhandle, NULL);
	if (indep(unit))
		strcpy(buf, "Independent");
	else	strcpy(buf, side_adjective(unit->side));
	strcat(buf, " ");
	strcat(buf, u_type_name(unit->type));
	strcat(buf, " ");
	strcat(buf, unit->name);
	c2p(buf, pname);
	SetIText(itemhandle, pname);

	/* Draw the unit's size. */
	GetDItem(win, diCitySize, NULL, &itemhandle, NULL);
	strcpy(buf, "Size : ");
	NumToString(unit->size, pnumber);
	p2c(pnumber, cname);
	strcat(buf, cname);
	c2p(buf, pname);
	SetIText(itemhandle, pname);

	/* Draw AI control info. */
	GetDItem(win, diCityStats, NULL, &itemhandle, NULL);
	strcpy(buf, "Under ");
	if (indep(unit) && unit->plan->aicontrol)
		strcat(buf, "brainless");
	else if (unit->side && side_has_ai(unit->side) && unit->plan->aicontrol)
		strcat(buf, unit->side->player->aitypename);
	else 	strcat(buf, "manual"); 
	strcat(buf, " control");
	c2p(buf, pname);
	SetIText(itemhandle, pname);

	/* Draw cyan background for materials panel. */ 
	GetDItem(win, diCityMatPanel, NULL, NULL, &itemrect);
	tmpcolor.red = 0xBFFF;
	tmpcolor.green = 0xFFFF; 
	tmpcolor.blue = 0xFFFF;
	RGBForeColor(&tmpcolor);
	FillRect(&itemrect, QDPat(black));
	ForeColor(blackColor);
	FrameRect(&itemrect);
	
	/* Draw green background for facilities panel. */ 
	GetDItem(win, diCityFacPanel, NULL, NULL, &itemrect);
	tmpcolor.red = 0xBFFF;
	tmpcolor.green = 0xFFFF; 
	tmpcolor.blue = 0xBFFF;
	RGBForeColor(&tmpcolor);
	FillRect(&itemrect, QDPat(black));
	ForeColor(blackColor);
	FrameRect(&itemrect);

	/* Draw pink background for garrison panel. */ 
	GetDItem(win, diCityOccPanel, NULL, NULL, &itemrect);
	tmpcolor.red = 0xFFFF;
	tmpcolor.green = 0xBFFF; 
	tmpcolor.blue = 0xFFFF; 
	RGBForeColor(&tmpcolor);
	FillRect(&itemrect, QDPat(black));
	ForeColor(blackColor);
	FrameRect(&itemrect);

	/* Draw statistics for material types 1 to 4. */
	for (m = 1; m < min(5, nummtypes); m++) {
		if (m_resource_icon(m)) {
			/* Plot material icon. */
			GetDItem(win, diCityMatBase + (5 * m), NULL, NULL, &itemrect);
			cicnhandle = GetCIcon(LARGE_CICNS + 10 * m_resource_icon(m) + 6);
			PlotCIcon(&itemrect, cicnhandle);
		}
		/* Plot material name. */
		GetDItem(win, diCityMatBase + (5 * m) + 1, NULL, &itemhandle, NULL);
		c2p(mtypes[m].name, pname);
		SetIText(itemhandle, pname);
		/* Plot material production. */
		GetDItem(win, diCityMatBase + (5 * m) + 2, NULL, &itemhandle, NULL);
		NumToString(unit->production[m], pnumber);
		SetIText(itemhandle, pnumber);
		/* Plot material supply. */
		GetDItem(win, diCityMatBase + (5 * m) + 3, NULL, &itemhandle, NULL);
		NumToString(unit->supply[m], pnumber);
		SetIText(itemhandle, pnumber);
		/* Plot global treasury supply. */
		GetDItem(win, diCityMatBase + (5 * m) + 4, NULL, &itemhandle, NULL);
		if (unit->side && m_treasury(m))
			NumToString(unit->side->treasury[m], pnumber);
		else	NumToString(0, pnumber);
		SetIText(itemhandle, pnumber);
	}

	/* Draw construction status. */
	if (unit->plan && unit->plan->tasks && unit->plan->tasks->type == TASK_BUILD) {
		GetDItem(win, diCityBuildStatus, NULL, &itemhandle, NULL);

		/* Print cps of current unit if it exists, else print "0". */
	    	if (find_unit(unit->plan->tasks->args[1]) != NULL) {
			 NumToString((find_unit(unit->plan->tasks->args[1]))->cp, pnumber);
			 p2c(pnumber, cname);
		} else	 strcpy(cname, "0");

		strcat(cname, " / ");
		NumToString(u_cp(unit->plan->tasks->args[0]), pnumber);
		p2c(pnumber, sname);
		strcat(cname, sname);
		
		/* Also print run progress. */
		if (unit->plan->tasks->args[3] > 1) {
			strcat(cname, "   ( ");
			NumToString(unit->plan->tasks->args[2] + 1, pnumber);
			p2c(pnumber, sname);
			strcat(cname, sname);
			strcat(cname, " of ");
			NumToString(unit->plan->tasks->args[3], pnumber);
			p2c(pnumber, sname);
			strcat(cname, sname);
			strcat(cname, " )");			
		}			
		c2p(cname, pnumber);
		SetIText(itemhandle, pnumber);
	}

	/* Draw research status. */
	if (unit->curadvance > 0 && unit->side) { 
		GetDItem(win, diCityResearchStatus, NULL, &itemhandle, NULL);
		NumToString(unit->side->advance[unit->curadvance], pnumber);
		p2c(pnumber, cname);
		strcat(cname, " / ");
		NumToString(a_rp(unit->curadvance), pnumber);
		p2c(pnumber, sname);
		strcat(cname, sname);
		c2p(cname, pnumber);
		SetIText(itemhandle, pnumber);
	}
	/* Sort the occupants. First load facilities. */
	i = 0;
	for_all_occupants(unit, unit2)
		if (alive(unit2) && u_facility(unit2->type))
			occupants[i++] = unit2->id;

	/* Move to the end of the facilities list. */
	i = MAX_DISPLAYED_FACS;

	/* Then load other units. */
	for_all_occupants(unit, unit2)
		if (alive(unit2) &! u_facility(unit2->type))
			occupants[i++] = unit2->id;

	/* Save the old Dialog background color. */
	oldBack = ((CGrafPtr) win)->rgbBkColor;
	BackColor(whiteColor);

	/* Draw all facilities and other occupants. */
	m = 0;
	n = min(i, MAX_DISPLAYED_OCCS);
	for (i = 0; i < n; i++) {
		CIconHandle cicnhandle;
		Rect srcrect, itemrect;
		MacImage *macuimg;
		BitMap bm, mm;		
		Image *uimg;
		Unit *unit2;
		int e;

		if (occupants[i] == 0) {
			m++;
			continue;
		}
		unit2 = find_unit(occupants[i]);
 		e = side_number(unit2->side);

		/* First plot each unit icon. */
		GetDItem(win, diCityOccBase + 2 * m, 0, 0, &itemrect);
		RGBForeColor(&(get_sideColor(e, icon_mask_color[e])));
		FillRect(&itemrect, QDPat(black));
		/* Get the best 16 x 16 unit image from family */
		uimg = best_image(uimages[unit2->type], 16, 16);
		macuimg = (MacImage *) uimg->hook;
		/* This is necessary if using imf data instead of lib-mac. */
		if (!macuimg->colricon) {
    			macuimg->colricon = (Handle) mac_create_cicn(uimg);
    			macuimg->cicn_inited = FALSE;
			mac_init_cicn(uimg);
		}
		/* Get bitmap & maskmap from cicn and set srcrect. */
		cicnhandle = (CIconHandle) macuimg->colricon;
		bm = (*(cicnhandle))->iconBMap;
		mm = (*(cicnhandle))->iconMask;
		SetRect(&srcrect, 0, 0, 16, 16);
		bm.rowBytes = 2;
		bm.bounds = srcrect;
		/* Plot the BitMap using the main icon color. */ 
		RGBForeColor(&(get_sideColor(e, main_icon_color[e])));
		CopyBits(&bm, &win->portBits, &srcrect, &itemrect, srcOr, 0);
		/* Optionally use a second side color to plot the right half of the icon */
		if (half_icon_color[e] && split_icon[e]) {
			RGBForeColor(&(get_sideColor(e, half_icon_color[e])));
			/* Restrict plotting to right half of image */
			srcrect.left += 8;
			itemrect.left +=8;
			CopyBits(&bm, &win->portBits, &srcrect, &itemrect, srcOr, 0);
			itemrect.left -=8;
		}
		/* Gray out units under construction. */
		if (!completed(unit2))
			gray_out_rect(&itemrect);
		/* Restore fore color. */
		ForeColor(blackColor);
		/* Draw a box around completed unit. */
		if (completed(unit2))
		FrameRect(&itemrect);

		/* Then plot each unit name. */
		GetDItem(win, diCityOccBase + 2 * m + 1, NULL, &itemhandle, NULL);
		if (unit2->name) {
		   	strcpy(buf, u_type_name(unit2->type));
		    	strcat(buf, " ");
		    	strcat(buf, unit2->name);
		/* Skip the unit number for facilities. */
		} else if (unit2->number > 0 &! u_facility(unit2->type)) {
		   	NumToString(unit2->number, pnumber);
			p2c(pnumber, cname);
	 	   	strcpy(buf, cname);
	 	    	strcat(buf, ordinal_suffix(unit2->number));
		    	strcat(buf, " ");
	 	    	strcat(buf, u_type_name(unit2->type));
		} else
			 strcpy(buf, u_type_name(unit2->type));

	/* Write out cps for each unit if debugging. */
	if (Debug || DebugG || DebugM) {
		strcat(buf, " ");
		NumToString(unit2->cp, pnumber);
		p2c(pnumber, cname);
		strcat(buf, cname);
		strcat(buf, "/");
		NumToString(u_cp(unit2->type), pnumber);
		p2c(pnumber, cname);
		strcat(buf, cname);
	}
		c2p(buf, pname);
		SetIText(itemhandle, pname);
		m++;
	}
	/* Restore dialog background. */
	RGBBackColor(&oldBack);
}

/* 
	Draw landuse in all cells near unit. Assumes the port is already set. 
*/

static void
draw_landuse_near_unit(Map *map, WindowPtr win, Rect itemrect, Unit *unit, int near)
{
	int 			mapsx, mapsy, winsx, winsy, sx, sy, x, y;
	Rect 			imagerect;
	Str255		pnumber;
	RgnHandle 		tmprgn;

	/* Return if landuse is not defined. */
	if (!user_defined())
		return;

	/* Clip to itemrect. */
	tmprgn = NewRgn();
	GetClip(tmprgn);
	ClipRect(&itemrect);

	/* Find win coordinates of unit (city) cell. */ 
	winsx = (itemrect.right + itemrect.left) / 2 - map->vp->hw/2;
	winsy = (itemrect.bottom + itemrect.top) / 2 - map->vp->hh/2;
	
	/* Find map coordinates of unit (city) cell. */
	xform(map, unit->x, unit->y, &mapsx, &mapsy);
	
	/* Zero the number of used cells. */
	unit->usedcells = 0;
	/* Go through all cells within "near" steps from unit. */
	for_all_cells_within_range(unit->x, unit->y, near, x, y) {
		/* Skip if cell is unused. */
		if (user_at(x, y) == NOUSER)
			continue;
		/* Skip if cell is outside area. */
		if (!inside_area(x, y))
			continue;
		/* Skip if the cell is not visible to the unit's side. */
		if (!terrain_visible(unit->side, x, y))
			continue;
		/* Recalculate the number of used cells. */
		if (user_at(x, y) == unit->id)
			unit->usedcells += 1;
		/* Find map coordinates of cell. */
		xform(map, x, y, &sx, &sy);
		/* Add win-map offset. */
		sx += winsx - mapsx;
		sy += winsy - mapsy;
		/* Adjust to unit part of cell. */
		sx += (map->vp->hw - map->vp->uw) / 2;  
		sy += (map->vp->hh - map->vp->uh) / 2;
		/* Set imagerect. */
		SetRect(&imagerect, sx, sy, sx + map->vp->uw, sy + map->vp->uh);
		/* Draw a colored square if cell is used by another unit. */
		if (find_unit(user_at(x, y)) && user_at(x, y) != unit->id) {
			int e = side_number(find_unit(user_at(x, y))->side);
			PenSize(2, 2);
			RGBForeColor(&(get_sideColor(e, main_icon_color[e])));
			FrameRect(&imagerect);
			PenNormal();
			ForeColor(blackColor);
		/* Else plot the resource cicns for that cell. */
		} else plot_resource_cicns(map, imagerect, x, y);
	}
	/* Restore old clip. */
	SetClip(tmprgn);
	DisposeRgn(tmprgn);
}

/* 
	Toggle landuse for a single cell. Assumes the port already is set. 
*/

void
toggle_landuse_one_cell(Map *map, WindowPtr win, Rect itemrect, Unit *unit, int x, int y)
{
	int 			mapsx, mapsy, winsx, winsy, sx, sy, nearx, neary;
	Rect 			maprect, winrect;
	RgnHandle		tmprgn;

	/* Return if landuse is undefined. */
	if (!user_defined())
		return;
	/* Return if the cell is not visible to this side. */
	if (!terrain_visible(unit->side, x, y))
		return;
	/* Return if the cell is used by another unit. */
	if (user_at(x, y) != NOUSER && user_at(x, y) != unit->id)
		return;
	/* Return if using maxcells and we are trying to add one more. */
	if (unit->usedcells >= unit->maxcells && user_at(x, y) != unit->id)
		return;
	/* Return if independents or untrusted side has a unit in the cell. */
	if (unit_at(x, y) != NULL) {
		Unit *unit2;
		for_all_stack(x, y, unit2)
			if (!trusted_side(unit->side, unit2->side))
				return;
	}
	/* Toggle landuse by unit either on or off for the cell. */
	if (user_at(x, y) == NOUSER) {
		set_user_at(x, y, unit->id);
		unit->usedcells += 1;
	} else if (user_at(x, y) == unit->id) {
		set_user_at(x, y, NOUSER);
		unit->usedcells -= 1;
	} else return;
	
	/* Clip to itemrect. */
	tmprgn = NewRgn();
	GetClip(tmprgn);
	ClipRect(&itemrect);

	/* Find the cell position. */
	xform(map, x, 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;

	/* Find cell rect position in the map. */
	SetRect(&maprect, sx, sy, sx + map->vp->uw, sy + map->vp->uh);

	/* Find cell rect position in the offscreen gworld. */
	OffsetRect(&maprect, map->offsetx + map->bufx - map->conw, 
				        map->offsety + map->bufy - map->toph);

	/* Find win coordinates of unit (city) cell. */ 
	winsx = (itemrect.right + itemrect.left) / 2 - map->vp->hw/2;
	winsy = (itemrect.bottom + itemrect.top) / 2 - map->vp->hh/2;
	
	/* Find map coordinates of unit (city) cell. */
	xform(map, unit->x, unit->y, &mapsx, &mapsy);
	
	/* Add win-map offset. */
	sx += winsx - mapsx;
	sy += winsy - mapsy;

	/* Find cell rect position in the dialog window. */
	SetRect(&winrect, sx, sy, sx + map->vp->uw, sy + map->vp->uh);

	/* Copy cellrect from gworld to dialog window. */
	LockPixels(GetGWorldPixMap(map->gworldPortPtr));
	CopyBits(  &((GrafPtr) map->gworldPortPtr)->portBits,
			&((GrafPtr) win)->portBits,
			&maprect, &winrect, srcCopy, NULL  );
	UnlockPixels(GetGWorldPixMap(map->gworldPortPtr));

	/* Plot resource cicns on top if cell is used by city. */
	if (user_at(x, y) == unit->id) 
		plot_resource_cicns(map, winrect, x, y);

	/* Restore old clip. */
	SetClip(tmprgn);
	DisposeRgn(tmprgn);
}

/* 
	Plot resource cicns in single cell. Assumes that the port already is set.
	Max 4 material types can be displayed at the same time. The icon used for
	each material type is determined by the mtype property m_resource_icon. 
*/

void
plot_resource_cicns(Map *map, Rect plotrect, int x, int y)
{
	CIconHandle cicnhandle;
	int m, n, i;

	n = (map->vp->uh > 16 ? LARGE_CICNS : SMALL_CICNS);
	for_all_material_types(m) {
		i = m_resource_icon(m);
		if (i) {
			cicnhandle = GetCIcon(n + 10 * i + tm_production(terrain_at(x, y), m));
			PlotCIcon(&plotrect, cicnhandle);
		}
	}
}

/* 
	Draw the size number of a city on top of its unit icon. 
*/

void
draw_unit_size(Unit *unit, WindowPtr win, int sx, int sy, int sw, int sh)
{
	Map 		*curmap;
	List		*curlist;
	Str255  	pnumber;
	int		e;

	/* Filter out very small images. */
	if (sw < 16)
		return; 
	/* Find current map or list. */
	curmap = map_from_window(win);
	curlist = list_from_window(win);
	e = side_number(unit->side);
		
	/* Default colors used in the absence of defined side colors. */
	RGBForeColor(&forecolor);
	RGBBackColor(&maskcolor);

	/* Draw the unit size. */
	if (unit && unit->size) {
		
		/* Load city size into pascal string. */
		NumToString(unit->size, pnumber);

		/* Use Chicago. */
		TextFont(0);

		/* Use fixed optimized fonts if asked to do so. */
		if (curmap && curmap->optimize_fonts) {

			switch (sh) {
				case 16:	TextSize(9); break;
				case 32:	TextSize(12); break;
				case 64:	TextSize(24); break;
				case 128:	TextSize(48); break;
				default:	TextSize(9); break;
			}

		/* Else scale text sizes according to formula. */
		} else TextSize(min(max(9, sh/2), 48));

		/* First use the mask color to plot the core. */
		if (((curmap && curmap->sidecolors) 
		    || (curlist && curlist->sidecolors)) 
		    && icon_mask_color[e]) {
		  	RGBForeColor(&(get_sideColor(e, icon_mask_color[e])));
		} else	RGBForeColor(&maskcolor);
		TextFace(bold + condense);

		/* Handtuned setting for 16 x 16. */
		if (sh < 32) MoveTo(sx + 1, sy + 10);
		else MoveTo(sx + sw/5, sy + 3 * sh/5);
		DrawString(pnumber);

		/* Then use the main color to plot the outline. */
		if (((curmap && curmap->sidecolors) 
		    || (curlist && curlist->sidecolors)) 
		    && main_icon_color[e]) {
		  	RGBForeColor(&(get_sideColor(e, main_icon_color[e])));
		} else	RGBForeColor(&forecolor);
		TextFace(shadow + condense);

		/* Handtuned setting for 16 x 16. */
		if (sh < 32) MoveTo(sx + 1, sy + 10);
		else MoveTo(sx + sw/5, sy + 3 * sh/5);
		DrawString(pnumber);

		/* Restore normal text. */
		TextSize(small_font_size);
		TextFont(small_font_id);
		TextFace(normal);

		ForeColor(blackColor);
		BackColor(whiteColor);
	}
}

/*
	Advance dialog for a single advanced unit. 
*/

void
unit_advance_dialog(Unit *unit)
{
	short 		ditem, mitem, done = FALSE, i, m, d, s;
	char			cname[32], sname[32], buf[BUFSIZE];
	Str255 		pname, pnumber;
	Handle 		itemhandle; 
	MenuHandle	popMenu;
	GrafPtr 		oldport;
 	DialogPtr		win;
	
	/* Open the dialog. */
	win = GetNewDialog(dAdvance, NULL, (DialogPtr) -1);
	GetPort(&oldport);	
	SetPort(win);

	/* Hide all scientists. */
	HideDItem(win, diAdvanceMadScientist);
	HideDItem(win, diAdvanceBusyScientist);
	HideDItem(win, diAdvanceIdleScientist);
	popMenu = GetMenu(mAdvancePopup);

	s = unit->curadvance;
	/* Research is going on. */
	if (s >= 0) { 
	   	strcpy(sname, a_type_name(s));
		/* Check if current advance has been completed. */
		if (has_advance(unit->side, s)) {
			/* Do bells and whistles. */
			strcpy(buf, "Scientists in ");
			strcat(buf, unit->name);
			strcat(buf, " discover ");
			strcat(buf, sname);
			strcat(buf, "!\r\r");
			strcat(buf, "Pick new research:");
			/* Show mad scientist. */
			ShowDItem(win, diAdvanceMadScientist);
			/* Only do it once. */
				unit->curadvance = NOADVANCE;
		} else {
			/* Report ongoing research. */
			strcpy(buf, "The scientists in ");
			strcat( buf, unit->name);
			strcat( buf, " are researching ");
			strcat(buf, sname);
			strcat(buf, ".");			
			/* Show busy scientist. */
			ShowDItem(win, diAdvanceBusyScientist);
		}
	/* No current research. */
	} else {
		strcpy(buf, "The scientists in ");
		strcat( buf, unit->name);
		strcat( buf, " are idle.\r");
		strcat( buf, "You should put them to work!\r\r");
		strcat( buf, "Pick new research:");
		/* Show idle scientist. */
		ShowDItem(win, diAdvanceIdleScientist);
	}
	c2p(buf, pname);
	GetDItem(win, diAdvanceMainText, NULL, &itemhandle, NULL);
	SetIText(itemhandle, pname);
	/* Set the advance auto checkbox. */
	GetDItem(win, diAdvanceCheck, NULL, &itemhandle, NULL);
	SetCtlValue((ControlHandle) itemhandle, unit->autoresearch);
	/* Load researchable advance types into popup menu. */
	for_all_advance_types(s) {
		if (has_advance_to_research(unit->side, s)
		    /* Skip advances already done. */
		    && unit->side->advance[s] != DONE) {
   			c2p(a_type_name(s), pname);
			AppendMenu(popMenu, pname);
		}
	}

	ShowWindow(win);
	while (!done) {
		SetCursor(&QD(arrow));
		draw_default_button(win, OkButton);

		/* Set popup to sname. */
		m = CountMItems(popMenu);
		GetDItem(win, diAdvancePopup, NULL, &itemhandle, NULL);
		SetCtlMax((ControlHandle) itemhandle, m);	/* Important! */
		for (i = 1; i <= m; i++) {
			GetItem(popMenu, i, pname);
			p2c(pname, cname);
			if (strcmp(sname, cname) != 0)
				continue;
			SetCtlValue((ControlHandle) itemhandle, i);
		}

		ModalDialog(NULL, &ditem);
		switch (ditem) {
			case diAdvanceCheck: /* Toggle advance auto checkbox. */
				GetDItem(win, ditem, NULL, &itemhandle, NULL);
				SetCtlValue((ControlHandle) itemhandle, !GetCtlValue((ControlHandle) itemhandle));
				break;

			case 	diAdvancePopup: /* Current research popup menu. */
				GetDItem(win, ditem, NULL, &itemhandle, NULL);
				mitem = GetCtlValue((ControlHandle) itemhandle);
				GetItem(popMenu, mitem, pname);
				p2c(pname, sname);
		    		break;

			case 	OkButton:
				/* Get the advance auto checkbox state. */
				GetDItem(win, diAdvanceCheck, NULL, &itemhandle, NULL);
				unit->autoresearch = GetCtlValue((ControlHandle) itemhandle);
				/* Stop any research if "Idle" was selected. */
				if (strcmp("Idle", sname) == 0) {
					unit->curadvance = NOADVANCE;
				/* Else select new advance to research. */
				} else for_all_advance_types(s) {
					/* Skip until we find atype that is selected in popMenu. */
					if (strcmp(a_type_name(s), sname) != 0)
						continue;
					unit->curadvance = s;
					}
				done = TRUE;
				break;

			case 	CancelButton:
				done = TRUE;
				break;

			default:
				break;
		}
	}

	/* Close the dialog. */
	DisposeDialog(win);
	/* Restore old port. */
	SetPort(oldport);
}

/*
	Build dialog for a single advanced unit. 
*/

int
unit_build_dialog(Unit *unit)
{
	short 		ditem, mitem, done = FALSE, i, m, d, u, u2;
	char			cname[32], uname[32], buf[BUFSIZE];
	Task 			*lasttask = &(unit->plan->last_task);
	Str255 		pname, pnumber;
	Handle 		itemhandle; 
	MenuHandle	popMenu;
	GrafPtr 		oldport;
 	DialogPtr		win;
	int			run;
	
	/* Open the dialog. */
	win = GetNewDialog(dBuild, NULL, (DialogPtr) -1);
	GetPort(&oldport);	
	SetPort(win);

	/* Hide all scientists. */
	HideDItem(win, diBuildMadScientist);
	HideDItem(win, diBuildBusyScientist);
	HideDItem(win, diBuildIdleScientist);

	/* Check if a real building task just was completed. */
	if (lasttask->type == TASK_BUILD
	     && unit->plan->last_task_outcome == TASK_IS_COMPLETE
	     && lasttask->args[3] > 0) {
	   	NumToString(lasttask->args[3], pnumber);
		p2c(pnumber, cname);
		if (lasttask->args[3] > 1) {
 	   		 strcpy(uname, cname);
	    		 strcat(uname, " ");
			 strcat(uname, plural_form(u_type_name(lasttask->args[0])));
		} else strcpy(uname, u_type_name(lasttask->args[0]));
		strcpy(buf, "Workers in ");
		strcat(buf, unit->name);
		strcat(buf, " complete ");
		strcat(buf, uname);
		strcat(buf, "!\r\r");
		strcat(buf, "Pick new building task:");
		/* Show mad scientist. */
		ShowDItem(win, diBuildMadScientist);
		/* Set menu task to Idle. */
		strcpy(uname, "Idle");
	/* We are not building anything at all. */
	} else {
		strcpy(uname, "Idle");
		strcpy(buf, "The workers in ");
		strcat( buf, unit->name);
		strcat( buf, " are idle.\r");
		strcat( buf, "You should put them to work!\r\r");
		strcat( buf, "Pick new building task:");
		/* Show idle scientist. */
		ShowDItem(win, diBuildIdleScientist);
	}
	c2p(buf, pname);
	GetDItem(win, diBuildMainText, NULL, &itemhandle, NULL);
	SetIText(itemhandle, pname);

	/* Set the autobuild radio button. */
	GetDItem(win, diBuildCheck, NULL, &itemhandle, NULL);
	SetCtlValue((ControlHandle) itemhandle, unit->autobuild);

	/* Set the manual build radio button. */
	GetDItem(win, diBuildStatus, NULL, &itemhandle, NULL);
	SetCtlValue((ControlHandle) itemhandle, !unit->autobuild);

	/* Draw the run in its textfield. */
	GetDItem(win, diBuildEdit, NULL, &itemhandle, NULL);
	if (lasttask->args[3] > 0)
		NumToString(lasttask->args[3], pname);
	else	NumToString(g_default_runlength(), pname);
	SetIText(itemhandle, pname);
	SelIText(win, diBuildEdit, 0, 32767);

	/* Load constructable unit type names into popup menu. */
	popMenu = GetMenu(mBuildPopup);
	for_all_unit_types(u) {
		if (type_allowed_on_side(u, unit->side)
		    && has_advance_to_build(unit->side, u)
		    && could_create(unit->type, u)
		    && (type_can_occupy(u, unit)
		    	  || u == unit->plan->tasks->args[0])) {
	   		c2p(u_type_name(u), pname);
			AppendMenu(popMenu, pname);
		}
	}
	ShowWindow(win);
	while (!done) {
		SetCursor(&QD(arrow));
		draw_default_button(win, OkButton);

		/* Set build popup to uname. */
		m = CountMItems(popMenu);
		GetDItem(win, diBuildPopup, NULL, &itemhandle, NULL);
		SetCtlMax((ControlHandle) itemhandle, m);
		for (i = 1; i <= m; i++) {
			GetItem(popMenu, i, pname);
			p2c(pname, cname);
			if (strcmp(uname, cname) != 0)
				continue;
			SetCtlValue((ControlHandle) itemhandle, i);
		}

		ModalDialog(NULL, &ditem);
		switch (ditem) {

			case diBuildCheck: 	/* Toggle autobuild and manual build buttons. */
				GetDItem(win, ditem, NULL, &itemhandle, NULL);
				SetCtlValue((ControlHandle) itemhandle, !GetCtlValue((ControlHandle) itemhandle));
				GetDItem(win, diBuildStatus, NULL, &itemhandle, NULL);
				SetCtlValue((ControlHandle) itemhandle, !GetCtlValue((ControlHandle) itemhandle));
				break;

			case diBuildStatus: 	/* Toggle autobuild and manual build buttons. */
				GetDItem(win, ditem, NULL, &itemhandle, NULL);
				SetCtlValue((ControlHandle) itemhandle, !GetCtlValue((ControlHandle) itemhandle));
				GetDItem(win, diBuildCheck, NULL, &itemhandle, NULL);
				SetCtlValue((ControlHandle) itemhandle, !GetCtlValue((ControlHandle) itemhandle));
				break;


			case 	diBuildPopup: 	/* Find selected unit type. */
				GetDItem(win, ditem, NULL, &itemhandle, NULL);
				mitem = GetCtlValue((ControlHandle) itemhandle);
				GetItem(popMenu, mitem, pname);
				p2c(pname, uname);
		    		break;

			case 	OkButton:
				/* Save the autobuild state. */
				GetDItem(win, diBuildCheck, NULL, &itemhandle, NULL);
				unit->autobuild = GetCtlValue((ControlHandle) itemhandle);

				/* Get the runlength from its text field. */
				GetDItem(win, diBuildEdit, NULL, &itemhandle, NULL);
	        			GetIText(itemhandle, pname);
				StringToNum(pname, (long *) &run);
				run = min(max(run, 0), CLEAR_AGENDA);

				/* Save the selected build task. */
				u = NONUTYPE;
				for_all_unit_types(u2) {
					/* Find the utype that was selected in the menu. */
					if (strcmp(u_type_name(u2), uname) == NULL) {
						net_set_build_task(unit, u2, run);
						u = u2;
						break;
					}
				}
				if (u == NONUTYPE) {
					/* No matching utype means "Idle" was selected. */
					net_clear_task_agenda(unit->side, unit);
					net_set_unit_asleep(unit->side, unit, TRUE, FALSE);
				}
				done = TRUE;
				break;

			case 	CancelButton:
				done = TRUE;
				break;

			default:
				break;
		}
	}
	/* Close the dialog. */
	DisposeDialog(win);
	/* Restore old port. */
	SetPort(oldport);
	/* Return the selected unit type. */
	return u;
}

/*
	Planning dialog for a single advanced unit. 
*/

void
unit_plan_dialog(Unit *unit)
{
	short 		ditem, mitem, done = FALSE, i, m, d, s;
	char			cname[32], sname[32], buf[BUFSIZE];
	Str255 		pname, pnumber;
	Handle 		itemhandle; 
	MenuHandle	planMenu;
	GrafPtr 		oldport;
 	DialogPtr		win;
	
	/* Open the dialog. */
	win = GetNewDialog(dPlan, NULL, (DialogPtr) -1);
	GetPort(&oldport);	
	SetPort(win);

	strcpy( buf, unit->name);
	strcat( buf, " needs a plan.\r\rPick one:\r");
	c2p(buf, pname);
	GetDItem(win, diPlanMainText, NULL, &itemhandle, NULL);
	SetIText(itemhandle, pname);

	/* Set plan type popup menu to current plan. */
	GetDItem(win, diPlanPopup, NULL, &itemhandle, NULL);
	if (unit->plan->type == PLAN_NONE)
		SetCtlValue((ControlHandle) itemhandle, miPlanTypeNone);
	else if (unit->plan->type == PLAN_PASSIVE)
		SetCtlValue((ControlHandle) itemhandle, miPlanTypePassive);
	else if (unit->plan->type == PLAN_DEFENSIVE)
		SetCtlValue((ControlHandle) itemhandle, miPlanTypeDefensive);
	else if (unit->plan->type == PLAN_EXPLORATORY)
		SetCtlValue((ControlHandle) itemhandle, miPlanTypeExploratory);
	else if (unit->plan->type == PLAN_OFFENSIVE)
		SetCtlValue((ControlHandle) itemhandle, miPlanTypeOffensive);
	else if (unit->plan->type == PLAN_COLONIZING)
		SetCtlValue((ControlHandle) itemhandle, miPlanTypeColonizing);
	else if (unit->plan->type == PLAN_IMPROVING)
		SetCtlValue((ControlHandle) itemhandle, miPlanTypeImproving);
	else if (unit->plan->type == PLAN_RANDOM)
		SetCtlValue((ControlHandle) itemhandle, miPlanTypeRandom);
	/* Also update the checkmarks, since this menu is used elsewhere. */
	planMenu = GetMenu(mPlanTypes);
	CheckItem(planMenu, miPlanTypeNone, (unit->plan->type == PLAN_NONE));
	CheckItem(planMenu, miPlanTypePassive, (unit->plan->type == PLAN_PASSIVE));
	CheckItem(planMenu, miPlanTypeDefensive, (unit->plan->type == PLAN_DEFENSIVE));
	CheckItem(planMenu, miPlanTypeExploratory, (unit->plan->type == PLAN_EXPLORATORY));
	CheckItem(planMenu, miPlanTypeOffensive, (unit->plan->type == PLAN_OFFENSIVE));
	CheckItem(planMenu, miPlanTypeColonizing, (unit->plan->type == PLAN_COLONIZING));
	CheckItem(planMenu, miPlanTypeImproving, (unit->plan->type == PLAN_IMPROVING));
	CheckItem(planMenu, miPlanTypeRandom, (unit->plan->type == PLAN_RANDOM));

	ShowWindow(win);
	while (!done) {
		SetCursor(&QD(arrow));
		draw_default_button(win, OkButton);

		ModalDialog(NULL, &ditem);
		switch (ditem) {
			case diPlanCheck: /* Toggle plan auto checkbox. */
				GetDItem(win, ditem, NULL, &itemhandle, NULL);
				SetCtlValue((ControlHandle) itemhandle, !GetCtlValue((ControlHandle) itemhandle));
				break;

			case 	OkButton:
				/* Get the advance auto checkbox state. */
				GetDItem(win, diPlanCheck, NULL, &itemhandle, NULL);
				unit->autoplan = GetCtlValue((ControlHandle) itemhandle);
				/* Get selected plan type. */
				GetDItem(win, diPlanPopup, NULL, &itemhandle, NULL);
				mitem = GetCtlValue((ControlHandle) itemhandle);
				switch (mitem)  {
					case miPlanTypeNone:
						net_set_unit_plan_type(unit->side, unit, PLAN_NONE);
						break;
					case miPlanTypePassive:
						net_set_unit_plan_type(unit->side, unit, PLAN_PASSIVE);
						break;
					case miPlanTypeDefensive:
						net_set_unit_plan_type(unit->side, unit, PLAN_DEFENSIVE);
						break;
					case miPlanTypeExploratory:
						net_set_unit_plan_type(unit->side, unit, PLAN_EXPLORATORY);
						break;
					case miPlanTypeOffensive:
						net_set_unit_plan_type(unit->side, unit, PLAN_OFFENSIVE);
						break;
					case miPlanTypeColonizing:
						net_set_unit_plan_type(unit->side, unit, PLAN_COLONIZING);
						break;
					case miPlanTypeImproving:
						net_set_unit_plan_type(unit->side, unit, PLAN_IMPROVING);
						break;
					case miPlanTypeRandom:
						net_set_unit_plan_type(unit->side, unit, PLAN_RANDOM);
						break;
				}
				done = TRUE;
				break;

			case 	CancelButton:
				done = TRUE;
				break;

			default:
				break;
		}
	}

	/* Close the dialog. */
	DisposeDialog(win);
	/* Restore old port. */
	SetPort(oldport);
}

/*
	Science dialog for all advanced units belonging to a side. Unit is the city that just made a
	discovery and advance the discovery itself. Set to NULL and (-1) if no discovery was made. 
*/

void
global_advance_dialog(Side *side, Unit *unit, int advance)
{
	short 		ditem, mitem, menu, num, text, status, check, done = FALSE, disabled, i, m, s;
	char			cname[32], sname[32], buf[BUFSIZE];
	int			oldprojects[MAXPROJMENUS + 1];
	int			participants[MAXATYPES];	
	Str255 		pname, pnumber;
	int			numprojects = 0;
	int			maxprojects;
	int			loafers = 0;	
	Handle 		itemhandle; 
	MenuHandle	doneMenu;
	MenuHandle	popMenu;
	GrafPtr 		oldport;
	Unit 			*unit2;
 	DialogPtr		win;
	
	/* Crash bug fix. */
	if (!side)
	  return;
	memset(oldprojects, 0, (MAXPROJMENUS + 1) * sizeof(int));
	memset(participants, 0, MAXATYPES * sizeof(int));

	/* Always give the own side, designers and debuggers full control. */
	if ((side && side == dside) || Debug || DebugG || DebugM || is_designer(dside)) {
		disabled = FALSE;
	/* Allow peeking at trusted side but with controls disabled. */
	} else if (trusted_side(dside, side)) {
		disabled = TRUE;
	/* Allow peeking at enemy if it is permitted, else return. */ 
	} else if (g_peek_at_enemy() == TRUE) {
		disabled = TRUE;
	} else return;

	/* Open the dialog. */
	win = GetNewDialog(dGlobalAdvance, NULL, (DialogPtr) -1);
	GetPort(&oldport);	
	SetPort(win);

	/* Hide everything except main text. */
	HideDItem(win, diGlobalMadScientist);
	HideDItem(win, diGlobalBusyScientist);
	HideDItem(win, diGlobalIdleScientist);
	for (i = diGlobalIdleMenu; i < diGlobalIdleMenu + 4 * (MAXPROJMENUS + 1); i++)
		HideDItem(win, i);
	for (i = diGlobalIdleCheck; i <= diGlobalIdleCheck + MAXPROJMENUS; i++)
		HideDItem(win, i);
	HideDItem(win, diGlobalMoreNote);
	
	/* Count loafers and project participants. */
	for_all_side_units(side, unit2) {
		if (!u_advanced(unit2->type))
			continue;
		if (unit2->curadvance != NOADVANCE && unit2->curadvance != advance)
			participants[unit2->curadvance] += 1;				
		else loafers += 1;
	}
	/* Count the number of active projects. */
	for_all_advance_types(s) {
		if (participants[s] > 0) {
			numprojects += 1;
			oldprojects[numprojects] = s;
		}
	}
	maxprojects = min(numprojects, MAXPROJMENUS);

	/* Load achieved advances into done menu. */
	doneMenu = GetMenu(mAdvanceAchieved);
	for_all_advance_types(s) {
		if (side->advance[s] == DONE) {
			c2p(a_type_name(s), pname);
			AppendMenu(doneMenu, pname);
		}
	}
	/* Load available advances into popup menu. */
	popMenu = GetMenu(mAdvancePopup);
	for_all_advance_types(s) {
		if (has_advance_to_research(side, s)
		    /* Skip advances already done. */
		    && side->advance[s] != DONE) {
			c2p(a_type_name(s), pname);
			AppendMenu(popMenu, pname);
		}
	}
	m = CountMItems(popMenu);

	/* Show mad scientist and relevant text if new discovery was signaled. */
	if (advance != NOADVANCE) {
		ShowDItem(win, diGlobalMadScientist);
		if (side == dside)
			strcpy(buf, "Your");
		else	strcpy(buf, side_adjective(side));
		strcat(buf, " scientists in ");
		strcat(buf, unit->name);
		strcat(buf, " discover ");
		strcat(buf,  a_type_name(advance));
		strcat(buf, "!\r\r");
		strcat(buf, "Pick new advance to research:");
	/* Else show busy scientist and report ongoing research. */
	} else {
		ShowDItem(win, diGlobalBusyScientist);
		if (side == dside)
			strcpy(buf, "Your");
		else	strcpy(buf, side_adjective(side));
			strcat(buf, " scientists are busy with the following projects:");
		if (loafers)
			strcat(buf, "\r\rNote : some of them are idle. You should put them to work!");
	}
	/* Show the main text. */
	c2p(buf, pname);
	GetDItem(win, diGlobalMainText, NULL, &itemhandle, NULL);
	SetIText(itemhandle, pname);

	/* Maybe show warning about more projects than shown. */
	if (numprojects > MAXPROJMENUS)
		ShowDItem(win, diGlobalMoreNote);

	if (loafers) {
		/* Show first menu (idle units) only if needed. */
		GetDItem(win, diGlobalIdleNum, NULL, &itemhandle, NULL);
		NumToString(loafers, pnumber);
		SetIText(itemhandle, pnumber);
		ShowDItem(win, diGlobalIdleNum);
		ShowDItem(win, diGlobalIdleText);
		GetDItem(win, diGlobalIdleMenu, NULL, &itemhandle, NULL);
		ShowDItem(win, diGlobalIdleMenu);
		/* Don't allow other sides to use the menu. */
		if (disabled)
			HiliteControl((ControlHandle) itemhandle, 255); 
		/* Also show first checkbox (idle units) if needed. */
		GetDItem(win, diGlobalIdleCheck, NULL, &itemhandle, NULL);
		SetCtlValue((ControlHandle) itemhandle, TRUE);
		for_all_side_units(side, unit2) {
			if (!u_advanced(unit2->type))
				continue;
			if (unit2->curadvance != NOADVANCE && unit2->curadvance != advance)
				continue;
			if (unit2->autoresearch != TRUE)
				SetCtlValue((ControlHandle) itemhandle, FALSE);
		}
		ShowDItem(win, diGlobalIdleCheck);
		/* Don't allow other sides to use the checkbox. */
		if (disabled)
			HiliteControl((ControlHandle) itemhandle, 255); 
	}
	/* Show project popup menus and associated text items. */
	num = diGlobalIdleNum;
	status = diGlobalIdleStatus;
	check = diGlobalIdleCheck;
	text = diGlobalIdleText;
	menu = diGlobalIdleMenu;
	for (s = 1; s <= maxprojects; s++) {
		/* Show the number of citites on each project. */
		GetDItem(win, ++num, NULL, &itemhandle, NULL);
		NumToString(participants[oldprojects[s]], pnumber);
		SetIText(itemhandle, pnumber);
		ShowDItem(win, num);
		/* Show the "are currently researching" text. */
		ShowDItem(win, ++text);
		/* Show the popup menu with the advance name. */
		GetDItem(win, ++menu, NULL, &itemhandle, NULL);
		SetCtlMax((ControlHandle) itemhandle, m);	/* Important! */
		for (i = 1; i <= m; i++) {
			GetItem(popMenu, i, pname);
			p2c(pname, cname);
			if (strcmp(a_type_name(oldprojects[s]), cname) != 0)
				continue;
			SetCtlValue((ControlHandle) itemhandle, i);
		}
		ShowDItem(win, menu);
		/* Don't allow other sides to use the menu. */
		if (disabled)
			HiliteControl((ControlHandle) itemhandle, 255); 
		/* Show the status info on the advence. */
		GetDItem(win, ++status, NULL, &itemhandle, NULL);
		NumToString(side->advance[oldprojects[s]], pnumber);
		p2c(pnumber, cname);
		strcat(cname, " / ");
		NumToString(a_rp(oldprojects[s]), pnumber);
		p2c(pnumber, sname);
		strcat(cname, sname);
		c2p(cname, pnumber);
		SetIText(itemhandle, pnumber);
		ShowDItem(win, status);
		/* Show the auto checkbox. */
		GetDItem(win, ++check, NULL, &itemhandle, NULL);
		SetCtlValue((ControlHandle) itemhandle, TRUE);
		for_all_side_units(side, unit2) {
			if (!u_advanced(unit2->type))
				continue;
			if (unit2->curadvance != oldprojects[s])
				continue;
			if (unit2->autoresearch != TRUE)
				SetCtlValue((ControlHandle) itemhandle, FALSE);
		}
		ShowDItem(win, check);
		/* Don't allow other sides to use the checkbox. */
		if (disabled)
			HiliteControl((ControlHandle) itemhandle, 255); 
	}

	/* Finally handle the All units checkbox. */
	GetDItem(win, diGlobalAllCheck, NULL, &itemhandle, NULL);
	/* First assume autoresearch is ON for all units. */
	SetCtlValue((ControlHandle) itemhandle, TRUE);
	for_all_side_units(side, unit2) {
		if (!u_advanced(unit2->type))
			continue;
		/*Uncheck the box if at least one unit is not on autoresearch. */ 
		if (unit2->autoresearch != TRUE) {		
			SetCtlValue((ControlHandle) itemhandle, FALSE);
			break;
		}
	}

	/* Don't allow other sides to use the checkbox. */
	if (disabled)
		HiliteControl((ControlHandle) itemhandle, 255); 

	ShowWindow(win);
	while (!done) {
		SetCursor(&QD(arrow));
		draw_default_button(win, OkButton);
		ModalDialog(NULL, &ditem);
		switch (ditem) {
			case 	OkButton:
				/* Don't allow others to change anything. */
				if (disabled) {
					done = TRUE;
					break;
				}					
				/* First deal with any idle units. */
				if (loafers) {
					GetDItem(win, diGlobalIdleMenu, NULL, &itemhandle, NULL);
					mitem = GetCtlValue((ControlHandle) itemhandle);
					GetItem(popMenu, mitem, pname);
					p2c(pname, sname);
					/* A new task was chosen for the idle units. */
					if (strcmp("Idle", sname) != 0) {
						for_all_side_units(side, unit2) {
							if (!u_advanced(unit2->type))
								continue;
							/* Set all Idle units and those who worked on the just acquired advance 
							to do selected research instead. */
							if (unit2->curadvance == NOADVANCE || unit2->curadvance == advance)
								unit2->curadvance = atype_from_name(sname);
						}
					} else {
						for_all_side_units(side, unit2) {
							if (!u_advanced(unit2->type))
								continue;
							/* Set all units who worked on the just acquired advance to Idle. */
							if (unit2->curadvance == advance)
								unit2->curadvance = NOADVANCE;
						}						
					}
					/* Then deal with the first auto checkbox. */
					GetDItem(win, diGlobalIdleCheck, NULL, &itemhandle, NULL);
					check = GetCtlValue((ControlHandle) itemhandle);
					for_all_side_units(side, unit2) {
						if (!u_advanced(unit2->type))
							continue;
						if (strcmp("Idle", sname) == 0) {
							if (unit2->curadvance == NOADVANCE || unit2->curadvance == advance) {
								unit2->autoresearch = check;
							} else continue;
						} else {
							if (unit2->curadvance == atype_from_name(sname)) {
								unit2->autoresearch = check;
							} else	 continue;
						}
					}
				}
				/* Then deal with ongoing research projects. */
				for (i = 1; i <= maxprojects; i++) {
					GetDItem(win, diGlobalIdleMenu + i, NULL, &itemhandle, NULL);
					mitem = GetCtlValue((ControlHandle) itemhandle);
					GetItem(popMenu, mitem, pname);
					p2c(pname, sname);
					/* Only proceed if we changed the project. */
					if (strcmp(a_type_name(oldprojects[i]), sname) != 0) {
						for_all_side_units(side, unit2) {
							if (!u_advanced(unit2->type))
								continue;
							/* Change units involved in the old project to new goal. */
							if (unit2->curadvance == oldprojects[i]) {
								if (strcmp("Idle", sname) == 0)
									unit2->curadvance = NOADVANCE;
								else 	unit2->curadvance = atype_from_name(sname);			
							}
						}
					}
					/* Finally deal with auto checkboxes. */
					GetDItem(win, diGlobalIdleCheck + i, NULL, &itemhandle, NULL);
					check = GetCtlValue((ControlHandle) itemhandle);
					for_all_side_units(side, unit2) {
						if (!u_advanced(unit2->type))
							continue;
						if (unit2->curadvance != oldprojects[i])
							continue;
						unit2->autoresearch = check;
					}
				}
				done = TRUE;
				break;

			case 	CancelButton:
				done = TRUE;
				break;

			default:
				/* Handle auto checkboxes. */
				for (i = 0; i <= maxprojects;  i++) {
					if (ditem == diGlobalIdleCheck + i) {
						GetDItem(win, ditem, NULL, &itemhandle, NULL);
						SetCtlValue((ControlHandle) itemhandle, 
							!GetCtlValue((ControlHandle) itemhandle));
					}
				}
				/* Handle All units checkbox. Toggle all other checkboxes. */
				if (ditem == diGlobalAllCheck) {
					GetDItem(win, ditem, NULL, &itemhandle, NULL);
					SetCtlValue((ControlHandle) itemhandle, 
						!GetCtlValue((ControlHandle) itemhandle));
					check = GetCtlValue((ControlHandle) itemhandle);
					for (i = 0; i <= maxprojects;  i++) {
						GetDItem(win, diGlobalIdleCheck + i, NULL, &itemhandle, NULL);
						SetCtlValue((ControlHandle) itemhandle, check);
					}
				}
				break;
		}
	}
	/* Close the dialog. */
	DisposeDialog(win);
	/* Restore old port. */
	SetPort(oldport);
}
