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

#include <time.h>
#include <z_combo.hpp>
#include <z_hlist.hpp>
#define USE_RAW_KEYS
#include <z_keymap.hpp>
#include <z_mouse2.hpp>
#include <z_scrll2.hpp>
#include <z_str1.hpp>
#include <z_string.hpp>

// ----- ZafHzList --------------------------------------------------------

static ZafWindowObject *FindBOL(ZafWindowObject *object)
{
	// Find the first object in the line.
	while (object && object->Previous() &&
		object->Previous()->zafRegion.left == object->zafRegion.left)
		object = object->Previous();
	return (object);
}

static ZafWindowObject *FindEOL(ZafWindowObject *object)
{
	// Find the last object in the line.
	while (object && object->Next() &&
		object->Next()->zafRegion.left == object->zafRegion.left)
		object = object->Next();
	return (object);
}

ZafWindowObject *ZafHzList::Add(ZafWindowObject *object, ZafWindowObject *position)
{
	// Mark the object as view only.
	ZafString *string = DynamicPtrCast(object, ZafString);
	if (string)
		string->SetViewOnly(true);
	if (OSDraw())
		object->SetBordered(false);
	if (!object->SupportObject())
	{
		object->SetSystemObject(false);
		object->SetParentPalette(true);
		object->SetParentDrawBorder(true);
		object->SetParentDrawFocus(true);
	}

	ZafWindowObject *oldFirst = First();
	ZafWindow::Add(object, position);
	if (autoSortData)
	{
		Sort();
		if (oldFirst == firstVisible)
			firstVisible = 0;
	}
	if (screenID)
		Event(N_SIZE);

	// Return the added object.
	return (object);
}

ZafRegionStruct ZafHzList::ConvertToDrawRegion(const ZafWindowObject *object,
	const ZafRegionStruct *region) const
{
	return (ZafWindowObject::ConvertToDrawRegion(object, region));
}

ZafEventType ZafHzList::DispatchMouseEvent(const ZafEventStruct &event)
{
	return (ZafWindowObject::DispatchMouseEvent(event));
}

ZafWindowObject *ZafHzList::FindMouseObject(const ZafEventStruct &event)
{
	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.
	ZafPositionStruct mousePosition = ConvertToZafPosition(this, &position);

	ZafRegionStruct windowClient = ClientRegion();
	if (!windowClient.Overlap(mousePosition))
	{
		return ZafWindow::FindMouseObject(event);
	}

	return (ZafWindowObject::FindMouseObject(event));
}

ZafEventType ZafHzList::DragDropEvent(const ZafEventStruct &event)
{
	ZafEventType ccode = event.type;

	switch (ccode)
	{
	case S_DROP_DEFAULT:
		ccode = S_DROP_MOVE;
		// Fall through to S_DROP_MOVE.
	case S_DROP_COPY:
	case S_DROP_MOVE:
		if (Disabled() || !AcceptDrop() || windowManager->dragObject == this)
			return (S_ERROR);
		else
		{
			// Clear all selections if extended selection list.
			if (selectionType == ZAF_EXTENDED_SELECTION)
			{
				for (ZafWindowObject *item = First(); item; item = item->Next())
					item->SetSelected(false);
			}

			if (windowManager->dragObject->IsA(ID_ZAF_LIST))
			{
				ZafWindow *dragList = DynamicPtrCast(windowManager->dragObject, ZafWindow);

				bool saveAutoUpdateSource = dragList->AutomaticUpdate();
				bool saveAutoUpdateTarget = automaticUpdate;

				if (ccode == S_DROP_MOVE)
					dragList->SetAutomaticUpdate(false);
				SetAutomaticUpdate(false);

				// Move the selected objects.
				ZafWindowObject *object;
				if (dragList->IsA(ID_ZAF_COMBO_BOX))
					object = DynamicPtrCast(dragList, ZafComboBox)->First();
				else
					object = dragList->First();
				while (object)
				{
					ZafWindowObject *temp = object->Next();
					if (object->Selected())
					{
						if (ccode == S_DROP_COPY)
							Add(object->Duplicate());
						else
						{
							dragList->Subtract(object);
							Add(object);
						}
					}
					object = temp;
				}
				if (ccode == S_DROP_MOVE)
					dragList->SetAutomaticUpdate(saveAutoUpdateSource);
				SetAutomaticUpdate(saveAutoUpdateTarget);
			}
			else
			{
				const ZafIChar *dropText = windowManager->dragObject->Text();
				if (dropText && *dropText)
				{
					ZafString *newChild = new ZafString(0, 0, 0, new ZafStringData(dropText));
					newChild->SetBordered(false);
					Add(newChild);
					if (ccode != S_DROP_COPY)
						windowManager->dragObject->SetText(ZafLanguageManager::blankString);
				}
				else
					ccode = S_ERROR;
			}
		}
		break;

	default:
		ccode = ZafWindow::DragDropEvent(event);
		break;
	}

	return (ccode);
}

#if defined(ZAF_DEFAULT_DRAW)
ZafEventType ZafHzList::Draw(const ZafEventStruct &event, ZafEventType ccode)
{
	ZafWindow::Draw(event, ccode);

	// Draw the child objects, since they are !systemObject.
	for (ZafWindowObject *object = First(); object; object = object->Next())
	{
		ZafEventStruct childEvent = event;
		if (object->zafRegion.Overlap(event.region, childEvent.region))
		{
			childEvent.region.HzShift(-object->zafRegion.left);
			childEvent.region.VtShift(-object->zafRegion.top);
			object->Draw(childEvent, ccode);
		}
	}

	return (ccode);
}

ZafEventType ZafHzList::DrawFocus(ZafRegionStruct &region, ZafEventType ccode)
{
	display->SetPalette(*((ZafScreenDisplay *)display)->xorPalette);
	display->SetMode(ZAF_MODE_XOR);
	display->Rectangle(region, -1);
	display->SetMode(ZAF_MODE_COPY);
	return (ccode);
}
#endif

ZafEventType ZafHzList::Event(const ZafEventStruct &event)
{
	ZafEventType ccode = LogicalEvent(event);

	ZafEventStruct tEvent = event;
	ZafWindowObject *object;
	// Check for zinc events.
	switch (ccode)
	{
	// ----- Create messages -----
	case S_INITIALIZE:
		ccode = ZafWindow::Event(event);
		firstVisible = lastVisible = ZAF_NULLP(ZafWindowObject);
		break;

	case S_HOT_KEY:
		ccode = S_UNKNOWN;
		break;

	case S_REGISTER_OBJECT:
		// Register the object. By registering children here, we prevent them
		// from being labelled as system objects. This will cause them to
		// get their palettes from the list and to let the list
		// draw their focus.
		RegisterObject();

		for (object = SupportFirst(); object; object = object->Next())
			object->Event(event);

		// Define the children to have the same screenID as their parent.
		for (object = First(); object; object = object->Next())
			object->screenID = screenID;
		break;

	// ----- Position & Size messages -----
	case N_SIZE:
		{
			// width and height are the default sizes of each item in the list.
			// These values are determined by the cellHeight and cellWidth.
			int width = cellWidth;
			int height = cellHeight;
			if (CoordinateType() != ZAF_PIXEL)
			{
				width *= display->cellWidth;
				height *= display->cellHeight;
			}
			if (CoordinateType() == ZAF_MINICELL)
			{
				width = (int)(width * display->miniNumeratorX / display->miniDenominatorX);
				height = (int)(height * display->miniNumeratorY / display->miniDenominatorY);
			}
			if (CoordinateType() == ZAF_CELL)
				height -= 2 * (ZAF_TEXT_MARGIN_SIZE + ZAF_BORDER_SIZE);
			height -= display->preSpace + display->postSpace;

			// left, top, right, and bottom are the bounding areas of the list's
			// client region.
			int left = 0, top = 0;
			int right = clientRegion.right - clientRegion.left;
			int bottom = clientRegion.bottom - clientRegion.top;

			// Position all objects in the list. This algorithm traverses the
			// list by first moving from the first visible and positioning each
			// object, then by moving to all object's above the firstVisible
			// to position them within the list. The first execution sets
			// firstVisible as the first item in the list.
			if (!firstVisible)
				firstVisible = First();

			// Work down from firstVisible.
			int line = top, column = left;
			object = lastVisible = firstVisible;
			for ( ; object; object = object->Next())
			{
				// Compute the desired size.
				object->Event(S_COMPUTE_SIZE);

				// Reset the object's zafRegion.
				object->zafRegion.left = column;
				object->zafRegion.top = line;

#if defined(ZAF_TEXT_MODE)
				object->zafRegion.right = column + width - 1;
				object->zafRegion.bottom = line + height - 1;
#else
				object->zafRegion.right = column + width;
				object->zafRegion.bottom = line + height;
#endif

				// Check the new line.
				line = object->zafRegion.bottom + 1;
#if defined(ZAF_TEXT_MODE)
				if (object->zafRegion.bottom >= bottom)
#else
				if (line + height >= bottom)
#endif
				{
					line = top;
					column = column + width + 1;
				}

				// Check for lastVisible and manage the scroll values.
				if (object->zafRegion.right <= right)
					lastVisible = object;
			}

			// Work up from firstVisible.
			if (firstVisible)
			{
				line = (bottom / height) * height;
				column = left - 1;
				for (object = firstVisible->Previous(); object; object = object->Previous())
				{
					// Compute the desired size.
					object->Event(S_COMPUTE_SIZE);

					// Reset the object's zafRegion.
					object->zafRegion.right = column;
					object->zafRegion.bottom = line;

#if defined(ZAF_TEXT_MODE)
					object->zafRegion.left = column - width - 1;
					object->zafRegion.top = line - height - 1;
#else
					object->zafRegion.left = column - width;
					object->zafRegion.top = line - height;
#endif

					// Check the new line.
					line = object->zafRegion.top - 1;
					if (line < top)
					{
						line = (bottom / height) * height;
						column = column - width - 1;
					}
				}
			}

			// Finalize the sizing operation.
			for (object = First(); object; object = object->Next())
				object->OSSize();

			// Adjust the scroll information.
			ScrollEvent(S_HSCROLL_COMPUTE);
		}
		break;

	// ----- Selection messages -----
	case L_SELECT:
		{
		ZafWindowObject *currentObject = Current();
		if (!currentObject)
			break;

		if (event.key.value != ' ')
		{
			ccode = S_UNKNOWN;
			break;
		}

		if (SelectionType() != ZAF_SINGLE_SELECTION)
			currentObject->ToggleSelected();
		else
			currentObject->SetSelected(true);

		// Call the associated user function.
		(currentObject->*(currentObject->memberUserFunction))(event, ccode);
		}
		break;

	case L_BEGIN_SELECT:
	case L_END_SELECT:
	case L_DOUBLE_CLICK:
		if (editMode)
		{
			ZafWindowObject::Event(event);
			break;
		}
		// Continue to L_CONTINUE_SELECT.
	case L_CONTINUE_SELECT:
//	case L_CONTINUE_COPY_DRAG:
//	case L_END_COPY_DRAG:
		{
			if (Draggable() && ccode != L_VIEW && !windowManager->dragObject)
				ZafWindowObject::Event(event);
			if (editMode || windowManager->dragObject)
			{
				ZafWindowObject::Event(event);
				break;
			}

			// Check for the current focus.
			if (ccode != L_BEGIN_SELECT && !Focus())
				break; // illegal selection process.

			// Check for out-of-bounds.
			ZafPositionStruct mousePosition = event.position;
			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(event.position))
			{
				// Check if over the scroll bar, since this is an atom.
				if (SupportFirst() && SupportFirst()->zafRegion.Overlap(mousePosition))
					return (SupportFirst()->DispatchMouseEvent(event));
				else
					return (ZafWindowObject::Event(event));
			}

/* START BLOCK COMMENT
**				if (ccode == L_BEGIN_SELECT && Draggable())
**					windowManager->dragObject = this;
END BLOCK COMMENT */

/* START BLOCK COMMENT
**				// Adjust for client region.
**				mousePosition.column -= clientRegion.left;
**				mousePosition.line -= clientRegion.top;
END BLOCK COMMENT */

			// Maintain the old current for extended select list.
			if (ccode == L_BEGIN_SELECT)
				oldCurrent = Current();

			// Try to find an overlapping item.
			for (object = firstVisible; object; object = object->Next())
				if (object->zafRegion.Overlap(mousePosition))
				{
					if (object->Disabled())
						return (ccode);

					if (current != object)
					{
						object->SetFocus(true);

						// Change the selected object.
						if (SelectionType() == ZAF_SINGLE_SELECTION)
							object->SetSelected(true);
					}
					break;
				}

			// If the mouse did not overlap any objects, break.
			if (!object)
				break;

			if (ccode == L_DOUBLE_CLICK)
				return (object->Event(event));

			// Check for a new selection.
			if (ccode == L_END_SELECT)
			{
				tEvent.type = L_SELECT;

				//-------
				// Change the selection.
				if ((SelectionType() == ZAF_EXTENDED_SELECTION && 
				 event.modifiers & S_SHIFT) || 
				 (SelectionType() == ZAF_EXTENDED_SELECTION && 
				 !(event.modifiers & S_CTRL)))
				{
					if (object->Selected())
						object->SetSelected(false);
					// If no control key treat as single select list.
					if (!(event.modifiers & S_CTRL))
					{
						selectionType = ZAF_SINGLE_SELECTION;
						object->SetSelected(true);
						selectionType = ZAF_EXTENDED_SELECTION;
					}
					// If shift key select everything between old current and current.
					if (event.modifiers & S_SHIFT)
					{
						ZafWindowObject *firstObj = ZAF_NULLP(ZafWindowObject);
						ZafWindowObject *lastObj = ZAF_NULLP(ZafWindowObject);
						// Find lowest index for starting point.
						if (Index(oldCurrent) < Index(Current()))
						{
							firstObj = oldCurrent;
							lastObj = Current();
						}
						else 
						{
							firstObj = Current();
							lastObj = oldCurrent;
						}
						// Select all of the object between firstObj and lastObj.
						for (; firstObj && firstObj != lastObj; firstObj = firstObj->Next())
							firstObj->SetSelected(true);
						// Make sure last object is selected. For case of Control Key.
						if (!lastObj->Selected())
							lastObj->SetSelected(true);
					}
				}
				// If extended list and control key treat as multiple select list.
				else if (SelectionType() == ZAF_MULTIPLE_SELECTION || 
				 (SelectionType() == ZAF_EXTENDED_SELECTION && 
				 event.modifiers & S_CTRL))
					object->ToggleSelected();
				// Single Select list.
				else
					object->SetSelected(true);
				//-------
/* START BLOCK COMMENT
**					// Change the selection.  Only toggle if not a double-click.
**					// Toggling on a double-click would switch the object back to
**					// the state it was in before the double-click started.
**					if (SelectionType() != ZAF_SINGLE_SELECTION)
**					{
**						if (tEvent.type != L_DOUBLE_CLICK)
**							object->ToggleSelected();
**					}
**					else
**						object->SetSelected(true);
END BLOCK COMMENT */

				// Call the associated user function.
				(object->*(object->memberUserFunction))(tEvent, tEvent.type);

				// Notify the parent if a temporary window.
				if (Temporary())
					windowManager->Event(S_CLOSE_TEMPORARY);
			}
		}
		break;

	case S_CURRENT:
		if (current && SelectionType() == ZAF_SINGLE_SELECTION)
			Current()->SetSelected(true);
		ZafWindow::Event(event);
		break;

	case E_KEY:
		if (temporary && parent)
			ccode = parent->Event(event);
		else
			ccode = ZafWindow::Event(event);
		break;

	// ----- Movement messages -----
	case L_NEXT:
	case L_PREVIOUS:
		ccode = S_UNKNOWN;
		break;

	case L_UP:
	case L_DOWN:
	case L_LEFT:
	case L_RIGHT:
	case L_FIRST:
	case L_LAST:
	case L_PGDN:
	case L_PGUP:
		ccode = MoveEvent(ccode);
		break;

	case E_MOUSE:
		{
			bool modified = false;
			if (event.rawCode == (M_LEFT | M_LEFT_CHANGE))
			{
				modified = true;
				tEvent.type = L_BEGIN_SELECT;
			}
			else if (event.rawCode == M_LEFT)
			{
				modified = true;
				tEvent.type = L_CONTINUE_SELECT;
			}
			else if (event.rawCode == M_LEFT_CHANGE)
			{
				modified = true;
				tEvent.type = L_END_SELECT;
			}
			if (modified)
				Event(tEvent);
		}
		break;

	// ----- Default operation -----
	default:
		ccode = ZafWindow::Event(event);
		break;
	}

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

ZafEventType ZafHzList::MoveEvent(const ZafEventStruct &event)
{
	// Determine the new selection.
	ZafEventType ccode = event.type;
	ZafWindowObject *object = Current();
	ZafWindowObject *pObject = object ? object->Previous() : ZAF_NULLP(ZafWindowObject);
	while (pObject && pObject->Disabled())
		pObject = pObject->Previous();
	ZafWindowObject *nObject = object ? object->Next() : ZAF_NULLP(ZafWindowObject);
	while (nObject && nObject->Disabled())
		nObject = nObject->Next();

	switch (ccode)
	{
	case L_UP:
		if (pObject)
			object = pObject;
		break;

	case L_DOWN:
		if (nObject)
			object = nObject;
		break;

	case L_PGUP:
		// Check for page actions.
		if (!object || !pObject)
			break; // No current object exists.
		else
		{
			object = FindBOL(pObject); // Go to the top of the column.
			// Go to the first non disabled object.
			while (object && object->Disabled())
				object = object->Next();
		}
		break;

	case L_PGDN:
		// Check for page actions.
		if (!object || !nObject)
			break; // No current object exists.
		else
		{
			object = FindEOL(nObject); // Go to the bottom of the column.
			// Go to the first non disabled object.
			while (object && object->Disabled())
				object = object->Previous();
		}
		break;

	case L_FIRST:
		object = First();
		while (object && object->Disabled())
			object = object->Next();
		break;

	case L_LAST:
		object = Last();
		while (object && object->Disabled())
			object = object->Previous();
		break;

	case L_LEFT:
		while (pObject && pObject->zafRegion.top != object->zafRegion.top)
		{
			pObject = pObject->Previous();
			while(pObject && pObject->Disabled())
				pObject = pObject->Previous();
		}
		if (pObject)
			object = pObject;
		break;

	case L_RIGHT:
		while (nObject && nObject->zafRegion.top != object->zafRegion.top)
		{
			nObject = nObject->Next();
			while(nObject && nObject->Disabled())
				nObject = nObject->Next();
		}
		if (nObject)
			object = nObject;
		break;
	}

	// Check the current object.
	if (object != current)
	{
		// Reset the current object.
		object->SetFocus(true);

		// Check the scroll information.
		ScrollEvent(S_HSCROLL_CHECK);

		// Change the selected object.
		if (SelectionType() == ZAF_SINGLE_SELECTION)
		{
			object->SetSelected(true);

			// Call the associated user function.
			(object->*(object->memberUserFunction))(event, L_SELECT);
		}
	}
	return (ccode);
}

ZafWindowObject *ZafHzList::NotifyFocus(ZafWindowObject *focusObject, bool setFocus)
{
	return (ZafWindow::NotifyFocus(focusObject, setFocus));
}

ZafWindowObject *ZafHzList::NotifySelection(ZafWindowObject *newObject,
	bool selected)
{
	return (ZafWindow::NotifySelection(newObject, selected));
}

ZafEventType ZafHzList::ScrollEvent(const ZafEventStruct &event)
{
	ZafWindowObject *object;
	int left = 0;
	int right = clientRegion.right - clientRegion.left;

	if (!screenID)
		return (S_UNKNOWN);

	// Process the scrolling request.  Scrolling at the horizontal list level
	// is based on the number of list items.
	ZafEventType ccode = event.type;
	switch (ccode)
	{
	case S_HSCROLL_CHECK:
		// Check for a valid object.
		object = Current();
		if (!object)
			return (S_ERROR);

		// Scroll the object into view.
		{
		ZafScrollStruct hScroll;
		hScroll.delta = 0;
		if (object->zafRegion.left < firstVisible->zafRegion.left)
		{
			// Determine the downward scrolling delta.
			ZafWindowObject *temp = object;
			while (temp && temp != firstVisible)
			{
				hScroll.delta--;
				temp = FindEOL(temp);
				temp = temp->Next();
			}
		}
		else if (object->zafRegion.right > lastVisible->zafRegion.right)
		{
			// Determine the upward scrolling delta.
			ZafWindowObject *temp = object;
			while (temp && temp != lastVisible)
			{
				hScroll.delta++;
				temp = FindBOL(temp);
				temp = temp->Previous();
			}
		}

		// Scroll the list elements or adjust the values.
		if (hScroll.delta)
			ScrollEvent(ZafEventStruct(S_HSCROLL, 0, hScroll));
		}
		break;

	case S_HSCROLL:
	case N_HSCROLL:
		// Determine the actual scrolling boundary, based on the size of 
		// each list element.
		{
		ZafWindowObject *newFirst = firstVisible;
		ZafWindowObject *newLast = lastVisible;
		if (event.scroll.delta > 0)
		{
			// Scroll downward by adjusting newLast.
			for (int i = (int)event.scroll.delta; i > 0; i--)
				if (newLast->Next())
					newLast = FindEOL(newLast->Next());
				else
					break;

			// Now finish by computing newFirst.
			newFirst = newLast;
			while (newFirst->Previous())
				if (newLast->zafRegion.right - newFirst->Previous()->zafRegion.left < right - left)
					newFirst = FindBOL(newFirst->Previous());
				else
					break;
		}
		else if (event.scroll.delta < 0)
		{
			// Scroll upward by first adjusting newFirst.
			for (int i = (int)event.scroll.delta; i < 0; i++)
				if (newFirst->Previous())
					newFirst = FindBOL(newFirst->Previous());
				else
					break;

			// Now finish by computing newLast.
			newLast = newFirst;
			while (newLast->Next())
				if (newLast->Next()->zafRegion.right - newFirst->zafRegion.left < right - left)
					newLast = FindEOL(newLast->Next());
				else
					break;
		}
		else
			return (S_ERROR);

		// Redisplay the list to get final positioning.
		if (newFirst != firstVisible || newLast != lastVisible)
		{
			// Adjust the first and last visible.
			firstVisible = newFirst;
			lastVisible = newLast;

			// Prevent objects from drawing when they get the OSSize().
			automaticUpdate = false;

			// Adjust all of the child positions.
			int xDelta = firstVisible->zafRegion.left;
			for (object = First(); object; object = object->Next())
			{
				object->zafRegion.left -= xDelta;
				object->zafRegion.right -= xDelta;
				object->OSSize();
			}

			// Allow the list to update its client area all at once.
			automaticUpdate = true;
			OSInvalidateRegion(&clientRegion);

			// Adjust the scroll values, if appropriate.
			if (ccode == S_HSCROLL)
			{
				ZafScrollBar *scrollBar = HorizontalScrollBar();
				if (scrollBar)
					scrollBar->Event(ZafEventStruct(N_HSCROLL, 0, event.scroll));
			}
		}
		}
		break;

	case S_HSCROLL_COMPUTE:
		// Reset the scroll values.
		{
		ZafScrollStruct hScroll;
		hScroll.delta = 1;
		hScroll.minimum = hScroll.maximum = 0;
		hScroll.showing = hScroll.current = 0;

		// Work down from firstVisible.
		for (object = firstVisible; object; object = object->Next())
		{
			if (object->zafRegion.right <= right)
				hScroll.showing++;
			hScroll.maximum++;
			object = FindEOL(object);
		}

		// Work up from firstVisible.
		if (firstVisible)
		{
			for (object = firstVisible->Previous(); object; object = object->Previous())
			{
				hScroll.current++;
				hScroll.maximum++;
				object = FindBOL(object);
			}
		}

		hScroll.maximum -= hScroll.showing;

		// Adjust the vertical scroll-bar values.
		ZafScrollBar *scrollBar = HorizontalScrollBar();
		if (scrollBar)
			scrollBar->Event(ZafEventStruct(S_HSCROLL_SET, 0, hScroll));
		}
		break;

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

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

ZafWindowObject *ZafHzList::Subtract(ZafWindowObject *object)
{
	// Remove the object from the list.
	if (object == firstVisible)
		firstVisible = object->Previous();
	ZafWindowObject *retValue = ZafWindow::Subtract(object);

	if (screenID)
		Event(N_SIZE);

	return (retValue);
}

bool ZafHzList::SetAutomaticUpdate(bool setAutomaticUpdate)
{
	// Defer to the base class.
	return (ZafWindow::SetAutomaticUpdate(setAutomaticUpdate));
}

bool ZafHzList::SetVisible(bool tVisible)
{
	return (ZafWindow::SetVisible(tVisible));
}

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

void ZafHzList::OSDestroy(void)
{
	// Notify each of the children.
	for (ZafWindowObject *object = First(); object; object = object->Next())
		object->Event(S_DEINITIALIZE);

	firstVisible = lastVisible = ZAF_NULLP(ZafWindowObject);
	OSInvalidateRegion(0, false, false);
}

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

void ZafHzList::OSMapPalette(ZafPaletteStruct &palette, ZafPaletteType type, ZafPaletteState state)
{
	ZafWindowObject::OSMapPalette(palette, type, state);
}

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

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

void ZafHzList::OSSize(void)
{
	ZafWindow::OSSize();
//	clientRegion.left++;
}

void ZafHzList::OSSort(void)
{
	if (screenID)
	{
		firstVisible = 0;
		Event(N_SIZE); // Cause the children to be repositioned.
	}
}

ZafError ZafHzList::OSUpdatePalettes(ZafPaletteType zafTypes, ZafPaletteType osTypes)
{
	return (ZafWindow::OSUpdatePalettes(zafTypes, osTypes));
}

