//	Zinc Application Framework - D_SCLWIN.CPP
//	COPYRIGHT (C) 1990-1999.  All Rights Reserved.
//	Zinc Software Incorporated.  Pleasant Grove, Utah  USA

#include <z_sclwin.hpp>
#include <z_border.hpp>
#include <z_icon1.hpp>
#include <z_string.hpp>
#include <z_utils.hpp>

// ----- ZafScrolledWindow ------------------------------------------------

ZafPositionStruct ZafScrolledWindow::ConvertToOSPosition(const ZafWindowObject *object,
	const ZafPositionStruct *zafPosition) const
{
	ZafPositionStruct osPosition = ZafWindow::ConvertToOSPosition(object, zafPosition);
	if (object && object != this && !object->SupportObject())
	{
		osPosition.column += scrollRegion.left;
		osPosition.line += scrollRegion.top;
	}
	return (osPosition);
}

ZafPositionStruct ZafScrolledWindow::ConvertToZafPosition(const ZafWindowObject *object,
	const ZafPositionStruct *osPosition) const
{
	ZafPositionStruct zafPosition = ZafWindow::ConvertToZafPosition(object, osPosition);
	if (object != this && !object->SupportObject())
	{
		zafPosition.column -= scrollRegion.left;
		zafPosition.line -= scrollRegion.top;
	}
	return (zafPosition);
}

ZafEventType ZafScrolledWindow::DispatchMouseEvent(const ZafEventStruct &event)
{
	// Dispatch all mouse events to the leaf-most object.
	// LogicalEvent() must be called first to map the logical events (L_*) and
	// to convert the event to the context of this object.
	ZafEventType ccode = LogicalEvent(event);

	if (modifyMode)
		return (Modify(event));

	if (windowManager->MouseEventRoute() == this)
	{
		ccode = Event(event);
		return (ccode);
	}

/* START BLOCK COMMENT
**		// If minimized, pass the event to the minimize icon.
**		if (Minimized())
**			return (MinimizeIcon()->DispatchMouseEvent(event));
END BLOCK COMMENT */

	// Convert mouse position to the coordinates of this object.
	bool overClient = false;
	ZafPositionStruct mousePosition = event.position;
	ZafRegionStruct windowClient = ClientRegion();
	if (windowClient.Overlap(mousePosition))
	{
		// If the mouse is over the client region, convert to the client
		// region's coordinates.
		overClient = true;
		mousePosition.column -= windowClient.left;
		mousePosition.line -= windowClient.top;
		mousePosition.line -= scrollRegion.top;
		mousePosition.column -= scrollRegion.left;
		// Cast away the constness so we can have event.position relative
		// to the client region.
		((ZafEventStruct &)event).position = mousePosition;
	}

	// Process drag and drop events.
	ZafWindowObject *object;
	if (windowManager->dragObject)
	{
		if (overClient)
		{
			for (object = First(); object; object = object->Next())
				if (object->Visible() && object->zafRegion.Overlap(mousePosition))
				{
					ccode = object->DispatchMouseEvent(event);
					break;
				}
		}
		else
		{
			for (object = SupportLast(); object; object = object->Previous())
				if (!object->IsA(ID_ZAF_BORDER) &&
					object->Visible() && object->zafRegion.Overlap(mousePosition))
				{
					ccode = object->DispatchMouseEvent(event);
					break;
				}
		}

		// If the mouse is not over a child object, this is the
		// leaf-most object so it processes the event.
		if (!object)
			ccode = ZafWindowObject::DispatchMouseEvent(event);
		return (ccode);
	}

	if (overClient)
	{
		for (object = First(); object; object = object->Next())
			if (object->Visible() && object->zafRegion.Overlap(mousePosition))
			{
				// An object being clicked on receives focus before
				// processing the selection event.
				if (ccode == L_BEGIN_SELECT &&
					!object->Disabled() && !object->Noncurrent())
					object->SetFocus(true);

				ccode = object->DispatchMouseEvent(event);
				break;
			}
	}
	else
	{
		// Start with last object, since the border is the first object
		// and its region covers the entire window.
		for (object = SupportLast(); object; object = object->Previous())
			if (object->Visible() && object->zafRegion.Overlap(mousePosition))
			{
				// An object being clicked on receives focus before processing
				// the selection event.
				if (ccode == L_BEGIN_SELECT && !object->Disabled() && !object->Noncurrent())
					object->SetFocus(true);
//				ZafWindow::Add(object);

				ccode = object->DispatchMouseEvent(event);
				break;
			}

		if (!object && Border())
		{
//??? Check to see that mouse overlaps the border.				
			// Allow the border object to process its mouse events.
			// Set the object variable so we know an object was found.
			object = Border();
			ccode = object->DispatchMouseEvent(event);
		}
	}

	// If the mouse is not over a child object, this is the
	// leaf-most object so it processes the event.
	if (!object)
		ccode = ZafWindowObject::DispatchMouseEvent(event);

	return (ccode);
}

ZafWindowObject *ZafScrolledWindow::FindMouseObject(const ZafEventStruct &event)
{
	if (modifyMode)
		return (this);

	if (windowManager->MouseEventRoute() == this)
		return (this);

	ZafPositionStruct position;
	position.line = event.osEvent.position.line;
	position.column = event.osEvent.position.column;
#if defined(ZAF_GRAPHICS_MODE)
	position.coordinateType = ZAF_PIXEL;
#else
	position.coordinateType = ZAF_CELL;
#endif

	// Convert mouse position to the coordinates of this object.
	bool overClient = false;
	ZafPositionStruct mousePosition = ConvertToZafPosition(this, &position);
//	ZafPositionStruct mousePosition = position;
	ZafRegionStruct windowClient = ClientRegion();
	if (windowClient.Overlap(mousePosition))
	{
		// If the mouse is over the client region, convert to the client
		// region's coordinates.
		overClient = true;
		mousePosition.column -= windowClient.left;
		mousePosition.line -= windowClient.top;
		mousePosition.line -= scrollRegion.top;
		mousePosition.column -= scrollRegion.left;
	}

	ZafWindowObject *object;
	ZafWindowObject *mouseObject = 0;

	if (overClient)
	{
		for (object = First(); object; object = object->Next())
			if (object->Visible() && object->zafRegion.Overlap(mousePosition))
			{
				mouseObject = object->FindMouseObject(event);
				break;
			}
	}
	else
	{
		// Start with last object, since the border is the first object
		// and its region covers the entire window.
		for (object = SupportLast(); object; object = object->Previous())
			if (object->Visible() && object->zafRegion.Overlap(mousePosition))
			{

				mouseObject = object->FindMouseObject(event);
				break;
			}
	}

	if (!mouseObject)
		mouseObject = this;
	return (mouseObject);
}

void ZafScrolledWindow::GetClip(ZafWindowObject *object, ZafRegionStruct &clip,
	ZafRegionStruct &viewPort)
{
	ZafWindow::GetClip(object, clip, viewPort);
	if (object != this && !object->SupportObject())
	{
		viewPort.HzShift((int)scrollRegion.left);
		viewPort.VtShift((int)scrollRegion.top);
	}
}

ZafEventType ZafScrolledWindow::Event(const ZafEventStruct &event)
{
	if (modifyMode && event.InputType() == E_MOUSE)
		return (Modify(event));

	// Check for zinc events.
	ZafEventType ccode = LogicalEvent(event);
	switch (ccode)
	{
	case S_INITIALIZE:
		ConvertRegion(scrollRegion, ZAF_PIXEL);
		ccode = ZafWindow::Event(event);
		break;

	// ----- Position & Size messages -----
	case N_SIZE:
		// Defer to the base class.
		ccode = ZafWindow::Event(event);

		// Adjust the scroll information.
		ScrollEvent(S_VSCROLL_COMPUTE);
		ScrollEvent(S_HSCROLL_COMPUTE);

		// Adjust the scroll region.
		if (scrollRegion.left < 0 &&
			scrollRegion.right < clientRegion.Width() - 1)
		{
			ZafEventStruct scrollEvent(S_HSCROLL);
			scrollEvent.scroll.delta = scrollRegion.left;
			Event(scrollEvent);
		}

		if (scrollRegion.top < 0 && scrollRegion.bottom < clientRegion.Height() - 1)
		{
			ZafEventStruct scrollEvent(S_VSCROLL);
			scrollEvent.scroll.delta = scrollRegion.top;
			Event(scrollEvent);
		}
		break;

	case L_PREVIOUS:
	case L_NEXT:
		ccode = ZafWindow::Event(event);
		if (ccode != S_UNKNOWN)
		{
			ScrollEvent(S_VSCROLL_CHECK);
			ScrollEvent(S_HSCROLL_CHECK);
		}
		break;

	case L_BEGIN_SELECT:
		if (!VerticalScrollBar() || !HorizontalScrollBar())
			return (ZafWindow::Event(event));

		// Close any temporary windows, such as pop-up menus.
		while (windowManager->First() != this &&
			DynamicPtrCast(windowManager->First(), ZafWindow)->Temporary())
			windowManager->Event(S_CLOSE_TEMPORARY);

		// Fall through to L_CONTINUE_SELECT, etc.
	case L_CONTINUE_SELECT:
	case L_END_SELECT:
		{
			ZafScrollBar *vtScrollBar = VerticalScrollBar();
			ZafScrollBar *hzScrollBar = HorizontalScrollBar();
			if (!vtScrollBar || !hzScrollBar)
				return (ZafWindow::Event(event));

			if (minimized)
			{
				MinimizeIcon()->Event(event);
				break;
			}

			// If the mouse is over the client region, convert to the client 
			// region's coordinates.
//			bool overClient = false;
			bool overClient = true;
			ZafPositionStruct mousePosition = event.position;
/* START BLOCK COMMENT
**				ZafRegionStruct windowClient = clientRegion;
**				// event.position is 0,0 based for the visible client region after 
**				// it has been dispatched.
**				windowClient.HzShift(-windowClient.left);
**				windowClient.VtShift(-windowClient.top);
**	
**				if (windowClient.Overlap(mousePosition) && vtScrollBar && hzScrollBar)
**				{
**					overClient = true;
**	#* START BLOCK COMMENT
**	**					mousePosition.column -= clientRegion.left;
**	**					mousePosition.line -= clientRegion.top;
**	**					mousePosition.column += (int)hzScrollBar->ScrollData()->Current();
**	**					mousePosition.line += (int)vtScrollBar->ScrollData()->Current();
**	END BLOCK COMMENT #/
**				}
END BLOCK COMMENT */

			// Let object deactivate its region.
			if ((ccode == L_END_SELECT || ccode == L_END_ESCAPE ||
		 		ccode == L_CONTINUE_SELECT || ccode == L_CONTINUE_ESCAPE) &&
				current && !Current()->zafRegion.Overlap(mousePosition))
			{
				Current()->Event(event);
/* START BLOCK COMMENT
**					if (Current()->Noncurrent())
**					{
**						for (object = First(); object; object = object->Next())
**							if (object->Focus())
**							{
**								current = object;
**								break;
**							}
**					}
END BLOCK COMMENT */
			}

			ZafWindowObject *object;
			if (overClient)
			{
				for (object = First();
					object && !object->zafRegion.Overlap(mousePosition);
					object = object->Next())
						; // Do nothing.

				// object points to overlapped object.
				if (object)
				{
					if (ccode == L_BEGIN_SELECT && !object->Disabled() && !object->Noncurrent())
						object->SetFocus(true);
					object->Event(event);
				}
			}
			else
			{
				// Start with last object, since the border is the first object
				// and its region covers the entire window.
				for (object = SupportLast();
					object && !object->zafRegion.Overlap(mousePosition);
					object = object->Previous())
						; // Do nothing.

				// object points to overlapped object.
				if (object)
				{
					if (ccode == L_BEGIN_SELECT && !object->Disabled() && !object->Noncurrent())
						object->SetFocus(true);
//						ZafWindow::Add(object);
					object->Event(event);
				}
//??? Check to see that mouse overlaps the border.				
				else if (Border())
					Border()->Event(event);
			}

/* START BLOCK COMMENT
**				// If the click didn't overlap any objects, close any temporary 
**				// windows.
**				if (!object && ccode == L_BEGIN_SELECT)
**				{
**					while (windowManager->First() != this &&
**						DynamicPtrCast(windowManager->First(), ZafWindow)->Temporary())
**						windowManager->Event(S_CLOSE_TEMPORARY);
**				}
END BLOCK COMMENT */
		}
		break;

/* START BLOCK COMMENT
**		case S_REDISPLAY_REGION:
**			{
**				ZafScrollBar *vtScrollBar = VerticalScrollBar();
**				ZafScrollBar *hzScrollBar = HorizontalScrollBar();
**	#* START BLOCK COMMENT
**	**				if (!vtScrollBar || !hzScrollBar)
**	**					return ZafWindow::Event(event);
**	END BLOCK COMMENT #/
**	
**				if (!AutomaticUpdate())
**					break;
**	
**				if (minimized)
**				{
**					Draw(event, ccode);
**					break;
**				}
**	
**				// When an object is sent a display message, the region passed is
**				// relative to the object's top-left corner being (0,0).
**				// So compare the drawing region to the object's (0,0)-based region.
**				ZafRegionStruct region;
**				region.left = region.top = 0;
**				region.right = zafRegion.Width() - 1;
**				region.bottom = zafRegion.Height() - 1;
**				region.coordinateType = zafRegion.coordinateType;
**				if (!region.Overlap(event.region))
**					break;
**	
**				Draw(event, ccode);
**	
**				ZafRegionStruct updateRegion = event.region;
**				ZafEventStruct drawEvent(ccode);
**	
**				ZafWindowObject *object;
**				for (object = SupportFirst(); object; object = object->Next())
**					if (object->zafRegion.Overlap(updateRegion))
**					{
**						// Create update region in the object's coordinates.
**						ZafRegionStruct drawRegion;
**						drawRegion.left = updateRegion.left - object->zafRegion.left;
**						drawRegion.right = updateRegion.right - object->zafRegion.left;
**						drawRegion.top = updateRegion.top - object->zafRegion.top;
**						drawRegion.bottom = updateRegion.bottom - object->zafRegion.top;
**						drawRegion.coordinateType = updateRegion.coordinateType;
**	
**						if (drawRegion.left < 0)
**							drawRegion.left = 0;
**						if (drawRegion.top < 0)
**							drawRegion.top = 0;
**						drawEvent.region = drawRegion;
**						object->Event(drawEvent);
**					}
**					else if (object->RegionType() == ZAF_OUTSIDE_REGION)
**					{
**						ZafBorder *border = DynamicPtrCast(object, ZafBorder);
**	
**						if (border)
**						{
**							ZafRegionStruct realRegion = border->zafRegion;
**							realRegion += border->Width();
**	
**							if (realRegion.Overlap(updateRegion))
**							{
**								// Create update region in the object's coordinates.
**								ZafRegionStruct drawRegion;
**								drawRegion.left = updateRegion.left - realRegion.left;
**								drawRegion.right = updateRegion.right - realRegion.left;
**								drawRegion.top = updateRegion.top - realRegion.top;
**								drawRegion.bottom = updateRegion.bottom - realRegion.top;
**								drawRegion.coordinateType = updateRegion.coordinateType;
**								if (drawRegion.left < 0)
**									drawRegion.left = 0;
**								if (drawRegion.top < 0)
**									drawRegion.top = 0;
**								drawEvent.region = drawRegion;
**								object->Event(drawEvent);
**							}
**						}
**					}
**	
**				// Don't try to draw children if the clientRegion region is "flat."
**				if (clientRegion.right <= clientRegion.left || clientRegion.bottom <= clientRegion.top)
**					break;
**	
**				// Shift region so can display what is in view.
**				if (hzScrollBar)
**					updateRegion.HzShift((int)hzScrollBar->ScrollData()->Current());
**				if (vtScrollBar)
**					updateRegion.VtShift((int)vtScrollBar->ScrollData()->Current());
**	
**				if (updateRegion.left < 0)
**					updateRegion.left = 0;
**				if (updateRegion.top < 0)
**					updateRegion.top = 0;
**				for (object = First(); object; object = object->Next())
**					if (object->zafRegion.Overlap(updateRegion))
**					{
**						// Create update region in the object's coordinates.
**						ZafRegionStruct drawRegion;
**						drawRegion.left = updateRegion.left - object->zafRegion.left;
**						drawRegion.top = updateRegion.top - object->zafRegion.top;
**						drawRegion.right = updateRegion.right - object->zafRegion.left;
**						drawRegion.bottom = updateRegion.bottom - object->zafRegion.top;
**						drawRegion.coordinateType = updateRegion.coordinateType;
**						if (drawRegion.left < 0)
**							drawRegion.left = 0;
**						if (drawRegion.top < 0)
**							drawRegion.top = 0;
**						drawEvent.region = drawRegion;
**						object->Event(drawEvent);
**					}
**			}
**			break;
**	
END BLOCK COMMENT */
	default:
		// Defer to the base class.
		ccode = ZafWindow::Event(event);
		break;
	}

	// Return the control code.
	return (ccode);
}

ZafWindowObject *ZafScrolledWindow::NotifyFocus(ZafWindowObject *object, bool setFocus)
{
	// Defer to the base class.
	return (ZafWindow::NotifyFocus(object, setFocus));
}

ZafEventType ZafScrolledWindow::ScrollEvent(const ZafEventStruct &event)
{
	// Process the scrolling request.  Scrolling at the window level is based 
	// on pixel boundaries.
	ZafEventType ccode = event.type;
	switch (ccode)
	{
	case S_VSCROLL:
		// Scroll the window contents <delta> cells in the direction 
		// indicated by the type of scrolling operation.
		if (VerticalScrollBar())
		{
			ZafEventStruct scrollEvent = event;
			scrollEvent.type = N_VSCROLL;
			VerticalScrollBar()->Event(scrollEvent);
			ScrollEvent(scrollEvent);
		}
		break;

	case S_HSCROLL:
		// Scroll the window contents <delta> cells in the direction 
		// indicated by the type of scrolling operation.
		if (HorizontalScrollBar())
		{
			ZafEventStruct scrollEvent = event;
			scrollEvent.type = N_HSCROLL;
			HorizontalScrollBar()->Event(scrollEvent);
			ScrollEvent(scrollEvent);
		}
		break;

	case N_VSCROLL:
		{
			// Scroll the window contents <delta> cells in the direction 
			// indicated by the type of scrolling operation.
			ZafRegionStruct updateRegion = clientRegion;
			updateRegion.left = updateRegion.top = 0;
			updateRegion.right = clientRegion.Width() - 1;
			updateRegion.bottom = clientRegion.Height() - 1;
			int delta = (int)event.scroll.delta;
			scrollRegion.top -= delta;
			
			if (event.scroll.delta < 0)
				updateRegion.bottom += delta;
			else
				updateRegion.top += delta;

			// Entire client region needs to be redrawn?
			if (updateRegion.top > updateRegion.bottom)
				OSInvalidateRegion(&clientRegion, false, false);
			else
			{
				// Scroll contents of client region.
				BeginDraw();
				display->RegionCopy(updateRegion, updateRegion.left, updateRegion.top - delta);
				EndDraw();

				// Paint exposed region.
				updateRegion = clientRegion;
				if (event.scroll.delta < 0)
					updateRegion.bottom = updateRegion.top - delta;
				else
					updateRegion.top = updateRegion.bottom - delta;

				OSInvalidateRegion(&updateRegion, false, false);
			}
			if (windowManager->cursorObject)
				windowManager->cursorObject->Event(S_REDISPLAY_CURSOR);
		}
		break;

	case N_HSCROLL:
		{
			// Scroll the window contents <delta> cells in the direction 
			// indicated by the type of scrolling operation.
			ZafRegionStruct updateRegion = clientRegion;
			updateRegion.left = updateRegion.top = 0;
			updateRegion.right = clientRegion.Width() - 1;
			updateRegion.bottom = clientRegion.Height() - 1;
			int delta = (int)event.scroll.delta;
			scrollRegion.left -= delta;
			
			if (event.scroll.delta < 0)
				updateRegion.right += delta;
			else
				updateRegion.left += delta;

			// Entire client region needs to be redrawn?
			if (updateRegion.left > updateRegion.right)
				OSInvalidateRegion(&clientRegion, false, false);
			else
			{
				// Scroll contents of client region.
				BeginDraw();
				display->RegionCopy(updateRegion, updateRegion.left - (int)event.scroll.delta, updateRegion.top);
				EndDraw();

				updateRegion = clientRegion;
				if (delta < 0)
					updateRegion.right = updateRegion.left - delta;
				else
					updateRegion.left = updateRegion.right - delta;

				OSInvalidateRegion(&updateRegion, false, false);
			}
			if (windowManager->cursorObject)
				windowManager->cursorObject->Event(S_REDISPLAY_CURSOR);
		}
		break;

	case S_VSCROLL_CHECK:
		{
			if (!VerticalScrollBar())
				break;

			// Check the current object to ensure it is currently visible within
			// the window.  If not, scroll the window so the object appears on 
			// the screen.

			long delta = 0;
			long current = VerticalScrollBar()->ScrollData()->Current();
			ZafWindowObject *object = Current();
			if (object && ((object->zafRegion.Height() <= clientRegion.Height()) ||
				(object->zafRegion.top > clientRegion.bottom ||
				object->zafRegion.bottom < clientRegion.top)))
			{
				if (object->zafRegion.top < current)
					delta = object->zafRegion.top - current;
				else if (object->zafRegion.bottom > current + clientRegion.Height())
					delta = object->zafRegion.bottom - clientRegion.Height() - current;
			}

			if (delta)
			{
				ZafEventStruct sEvent(S_VSCROLL);
				sEvent.scroll.delta = delta;
				Event(sEvent);
			}
		}
		break;

	case S_HSCROLL_CHECK:
		{
			if (!HorizontalScrollBar())
				break;

			// Check the current object to ensure it is currently visible within
			// the window.  If not, scroll the window so the object appears on 
			// the screen.

			long delta = 0;
			long current = HorizontalScrollBar()->ScrollData()->Current();
			ZafWindowObject *object = Current();
			if (object && ((object->zafRegion.Width() <= clientRegion.Width()) ||
				(object->zafRegion.left > clientRegion.right ||
				object->zafRegion.right < clientRegion.left)))
			{
				if (object->zafRegion.left < current)
					delta = object->zafRegion.left - current;
				else if (object->zafRegion.right > current + clientRegion.Width())
					delta = object->zafRegion.right - clientRegion.Width() - current;
			}

			if (delta)
			{
				ZafEventStruct sEvent(S_HSCROLL);
				sEvent.scroll.delta = delta;
				Event(sEvent);
			}
		}
		break;

	case S_HSCROLL_COMPUTE:
		{
			ZafScrollBar *hzScrollBar = HorizontalScrollBar();
			if (hzScrollBar)
			{
				ZafScrollStruct hScroll;
				hScroll.minimum = 0;
				hScroll.maximum = scrollRegion.Width() - clientRegion.Width();
				hScroll.showing = clientRegion.Width();
				hScroll.current = -scrollRegion.left;
				hScroll.delta = display->cellWidth;

				if (hScroll.maximum < 0)
					hScroll.maximum = 0;
				hzScrollBar->ScrollData()->SetScroll(hScroll);
			}
		}
		break;

	case S_VSCROLL_COMPUTE:
		{
			ZafScrollBar *vtScrollBar = VerticalScrollBar();
			if (vtScrollBar)
			{
				ZafScrollStruct vScroll;
				vScroll.minimum = 0;
				vScroll.maximum = scrollRegion.Height() - clientRegion.Height();
				vScroll.showing = clientRegion.Height();
				vScroll.current = -scrollRegion.top;
				vScroll.delta = display->cellHeight;

				if (vScroll.maximum < 0)
					vScroll.maximum = 0;
				vtScrollBar->ScrollData()->SetScroll(vScroll);
			}
		}
		break;

	default:
		// No other messages apply to the scrolling window object.
		return (S_ERROR);
	}

	// Return the control code.
	return (event.type);
}

// ----- OS Specific Functions ----------------------------------------------

ZafEventType ZafScrolledWindow::OSEvent(const ZafEventStruct &)
{
	return (S_ERROR);
}

void ZafScrolledWindow::OSInvalidateRegion(ZafRegionStruct *region, bool immediateRedraw, bool client)
{
	if (AutomaticUpdate() && Visible() && screenID)
	{
		ZafRegionStruct tRegion = region ? *region : zafRegion;
		if (!region)
		{
			tRegion.HzShift(-zafRegion.left);
			tRegion.VtShift(-zafRegion.top);
		}
		if (client)
		{
			tRegion.HzShift(clientRegion.left);
			tRegion.VtShift(clientRegion.top);
			tRegion.HzShift(scrollRegion.left);
			tRegion.VtShift(scrollRegion.top);
		}

		// Don't need to worry about whether this is an overlapped
		// child, since ZafWO::OSInvalidateReg() will.
		if (!systemObject)
			ZafWindowObject::OSInvalidateRegion(&tRegion, immediateRedraw, client);
		else
		{
			// If this is an overlapped child object, make sure we only
			// invalidate the exposed pieces of the object.
			if (parent && overlapped)
			{
				ZafWindowObject::OSInvalidateRegion(&tRegion, immediateRedraw, false);
				// The comparison with other regions is based on
				// zafRegion.  ie, with respect to all the siblings'
				// parent origin.  So, need to shift the region that 
				// got passed in, since it was relative to the object's
				// origin.
			}
			else
				windowManager->OSInvalidateObject(&tRegion, this);

			if (immediateRedraw)
				windowManager->RepairDamage();
		}
		return;

	}
}

void ZafScrolledWindow::ModifyOSShift(ZafPositionStruct &osPosition)
{
	osPosition.line -= clientRegion.top;
	osPosition.column -= clientRegion.left;
	osPosition.line -= scrollRegion.top;
	osPosition.column -= scrollRegion.left;
}

void ZafScrolledWindow::OSRegisterObject(void)
{
	ZafWindow::OSRegisterObject();
}

OSWindowID ZafScrolledWindow::OSScreenID(ZafScreenIDType) const
{
	return (screenID);
}

void ZafScrolledWindow::OSSize(void)
{
	// Defer to the base class.
	ZafWindow::OSSize();
}

