
#include <classes/Layouter/Layouter.h>

TransparentLayoutC::TransparentLayoutC(WORD width, WORD height)
{
	Left = 0;
	Top = 0;
	Width = width;
	Height = height;
	aWidth = (width == LAYOUT_AUTOSIZE);
	aHeight = (height == LAYOUT_AUTOSIZE);
};

BOOL TransparentLayoutC::layoutWidth()
{
	if (aWidth)
		Width = 0;
	return FALSE;
}

BOOL TransparentLayoutC::layoutHeight()
{
	if (aHeight)
		Height = 0;
	return FALSE;
}

VOID TransparentLayoutC::setWidth(WORD w)
{
	Width = w;
	if (w == LAYOUT_AUTOSIZE)
		aWidth = TRUE;
}

VOID TransparentLayoutC::setHeight(WORD h)
{
	Height = h;
	if (h == LAYOUT_AUTOSIZE)
		aHeight = TRUE;
}

// *************************************************************

TransparentGroupLayoutC::TransparentGroupLayoutC(
		WORD width, WORD height)
	: GroupLayoutC()
{
	Left = 0;
	Top = 0;
	Width = width;
	Height = height;
	aWidth = (width == LAYOUT_AUTOSIZE);
	aHeight = (height == LAYOUT_AUTOSIZE);
}

BOOL TransparentGroupLayoutC::layoutWidth()
{
	if (aWidth)
		Width = 0;
	return FALSE;
}

BOOL TransparentGroupLayoutC::layoutHeight()
{
	if (aHeight)
		Height = 0;
	return FALSE;
}

VOID TransparentGroupLayoutC::setWidth(WORD w)
{
	Width = w;
	if (w == LAYOUT_AUTOSIZE)
		aWidth = TRUE;
}

VOID TransparentGroupLayoutC::setHeight(WORD h)
{
	Height = h;
	if (h == LAYOUT_AUTOSIZE)
		aHeight = TRUE;
}

// *************************************************************

GeometryHookC::GeometryHookC(APTR data)
	: HookC(data)
{
}

ULONG GeometryHookC::layout(GeometryC *, struct LayoutParamPkt *)
{
	return LAYOUTR_UNKNOWN;
}

ULONG GeometryHookC::hook(APTR o, APTR p)
{
	return layout((GeometryC *) o, (struct LayoutParamPkt *) p);
}

ULONG GeometryHookC::call(GeometryC *o, struct LayoutParamPkt *p)
{
	return HookC::call(o,p);
}

// *************************************************************

GeometryC::GeometryC(LayoutC &g,
		ULONG topRelation, GeometryBaseC *topObject, WORD topOffset,
		ULONG bottomRelation, GeometryBaseC *bottomObject, WORD bottomOffset,
		ULONG leftRelation, GeometryBaseC *leftObject, WORD leftOffset,
		ULONG rightRelation, GeometryBaseC *rightObject, WORD rightOffset)
{
	gadget = &g;
	parent = NULL;
	tRel = topRelation;
	tObj = (GeometryC *) topObject;
	tOffset = topOffset;
	bRel = bottomRelation;
	bObj = (GeometryC *) bottomObject;
	bOffset = bottomOffset;
	lRel = leftRelation;
	lObj = (GeometryC *) leftObject;
	lOffset = leftOffset;
	rRel = rightRelation;
	rObj = (GeometryC *) rightObject;
	rOffset = rightOffset;
	xLayouting = FALSE;
	yLayouting = FALSE;
	counterX = 0;
	counterY = 0;
	preCounterX = 0;
	preCounterY = 0;
}

GeometryC::~GeometryC()
{
}

BOOL GeometryC::preLayoutX(ULONG countX)
{
	if (countX > preCounterX)
	{
		xLayouting = TRUE;
		preCounterX++;
		preWidth = 0;
		struct LayoutParamPkt lparam;
		lparam.parent = parent;
		lparam.count = countX;
		ULONG hookR;
// Zuerst einmal die vermutliche Breite (preWidth) feststellen
		switch (lRel)
		{
			case LAYOUT_SIZE:
				preWidth = gadget->width();
				break;
			case LAYOUT_MAXSIZE:
				if (lObj)
					return FALSE;
				if (parent)
					preWidth = parent->maxWidth();
				break;
			case LAYOUT_SAMESIZE:
				if (!lObj)
					return FALSE;
				if (!lObj->preLayoutX(countX))
					return FALSE;
				preWidth = lObj->preWidth;
				break;
			case LAYOUT_MAXSAMEBORDER:
				if (lObj)
					return FALSE;
				if (parent)
					preWidth = parent->maxLeftBorder();
				break;
			case LAYOUT_MAXOPPBORDER:
				if (lObj)
					return FALSE;
				if (parent)
					preWidth = parent->maxRightBorder();
				break;
			case LAYOUT_HOOK:
				if (!lObj)
					return FALSE;
				lparam.command = LAYOUTC_PREWIDTH;
				lparam.flags = LAYOUTF_LAST_CHANCE;
				lparam.offset = lOffset;
				hookR = ((GeometryHookC *) (GeometryBaseC *) lObj)->call(this,&lparam);
				if (hookR == LAYOUTR_ERROR)
					return FALSE;
				if (hookR == LAYOUTR_OK)
					preWidth = lparam.coor_result;
				break;
			default:
				break;
		};
		switch (rRel)
		{
			case LAYOUT_SIZE:
				preWidth = gadget->width();
				break;
			case LAYOUT_MAXSIZE:
				if (rObj)
					return FALSE;
				if (parent)
					preWidth = parent->maxWidth();
				break;
			case LAYOUT_SAMESIZE:
				if (!rObj)
					return FALSE;
				if (!rObj->preLayoutX(countX))
					return FALSE;
				preWidth = rObj->preWidth;
				break;
			case LAYOUT_MAXSAMEBORDER:
				if (rObj)
					return FALSE;
				if (parent)
					preWidth = parent->maxRightBorder();
				break;
			case LAYOUT_MAXOPPBORDER:
				if (rObj)
					return FALSE;
				if (parent)
					preWidth = parent->maxLeftBorder();
				break;
			case LAYOUT_HOOK:
				if (!rObj)
					return FALSE;
				lparam.command = LAYOUTC_PREWIDTH;
				lparam.flags = LAYOUTF_LAST_CHANCE;
				lparam.offset = rOffset;
				hookR = ((GeometryHookC *) (GeometryBaseC *) rObj)->call(this,&lparam);
				if (hookR == LAYOUTR_ERROR)
					return FALSE;
				if (hookR == LAYOUTR_OK)
					preWidth = lparam.coor_result;
				break;
			default:
				break;
		};
		if (!preWidth)
			preWidth = gadget->minWidth();
// Jetzt den rechten und linken Abstand zum Gruppenrand (preLeft, preRight)
// berechnen
		BOOL LeftIsLayouted = FALSE;
		switch (lRel)
		{
			case LAYOUT_SIZE:
			{
				if (lObj)
				{
					if (!lObj->preLayoutX(countX))
						return FALSE;
					preLeft = lObj->preLeft + lObj->preWidth +
						lObj->rightBorder() + leftBorder();
				}
				else
					preLeft = leftBorder();
				LeftIsLayouted = TRUE;
				break;
			};
			case LAYOUT_SAME:
			{
				if (!lObj)
					return FALSE;
				if (!lObj->preLayoutX(countX))
					return FALSE;
				preLeft = lObj->preLeft + lOffset;
				LeftIsLayouted = TRUE;
				break;
			};
			case LAYOUT_SAMEBORDER:
			{
				if (!lObj)
					return FALSE;
				if (!lObj->preLayoutX(countX))
					return FALSE;
				preLeft = lObj->preLeft - lObj->leftBorder() + lOffset +
					leftBorder();
				LeftIsLayouted = TRUE;
				break;
			};
			case LAYOUT_GROUP:
			{
				if (lObj)
					return FALSE;
				preLeft = lOffset + leftBorder();
				LeftIsLayouted = TRUE;
				break;
			};
			case LAYOUT_OPP:
			{
				if (!lObj)
					return FALSE;
				if (!lObj->preLayoutX(countX))
					return FALSE;
				preLeft = lObj->preLeft + lObj->preWidth + lOffset;
				LeftIsLayouted = TRUE;
				break;
			};
			case LAYOUT_OPPBORDER:
			{
				if (!lObj)
					return FALSE;
				if (!lObj->preLayoutX(countX))
					return FALSE;
				preLeft = lObj->preLeft + lObj->preWidth + lObj->rightBorder() +
					lOffset + leftBorder();
				LeftIsLayouted = TRUE;
				break;
			};
			case LAYOUT_OPPGROUP:
			{
				if (lObj)
					return FALSE;
				preLeft = leftBorder();
				LeftIsLayouted = TRUE;
				break;
			};
			case LAYOUT_MAXSIZE:
			{
				preLeft = leftBorder();
				LeftIsLayouted = TRUE;
				break;
			};
			case LAYOUT_SAMESIZE:
			{
				preLeft = leftBorder();
				LeftIsLayouted = TRUE;
				break;
			};
			case LAYOUT_PROCENT:
			{
				break;
			};
			case LAYOUT_PROCENTCENTER:
			{
				break;
			};
			case LAYOUT_MAXSAMEBORDER:
			{
				preLeft = leftBorder();
				LeftIsLayouted = TRUE;
				break;
			};
			case LAYOUT_MAXOPPBORDER:
			{
				preLeft = leftBorder();
				LeftIsLayouted = TRUE;
				break;
			};
			case LAYOUT_HOOK:
				if (!lObj)
					return FALSE;
				lparam.command = LAYOUTC_PRELEFT;
				lparam.flags = LAYOUTF_LAST_CHANCE;
				lparam.offset = lOffset;
				hookR = ((GeometryHookC *) (GeometryBaseC *) lObj)->call(this,&lparam);
				switch (hookR)
				{
					case LAYOUTR_UNKNOWN:
						return FALSE;
						break;
					case LAYOUTR_OK:
						preLeft = lparam.coor_result;
						LeftIsLayouted = TRUE;
						break;
					case LAYOUTR_ERROR:
						return FALSE;
						break;
					case LAYOUTR_NOTYET:
						return FALSE;
						break;
					default:
						return FALSE;
						break;
				};
				break;
			case LAYOUT_BORDERGROUP:
			{
				if (lObj)
					return FALSE;
				preLeft = lOffset;
				LeftIsLayouted = TRUE;
				break;
			};
			default:
			{
				return FALSE;
				break;
			};
		};
		switch (rRel)
		{
			case LAYOUT_SIZE:
			{
				if (rObj)
				{
					if (!rObj->preLayoutX(countX))
						return FALSE;
					preRight = rObj->preRight -
						rObj->leftBorder() + rightBorder();
				}
				else
					preRight = rightBorder();
				break;
			};
			case LAYOUT_SAME:
			{
				if (!rObj)
					return FALSE;
				if (!rObj->preLayoutX(countX))
					return FALSE;
				preRight = rObj->preRight - rOffset;
				break;
			};
			case LAYOUT_SAMEBORDER:
			{
				if (!rObj)
					return FALSE;
				if (!rObj->preLayoutX(countX))
					return FALSE;
				preRight = rObj->preRight - rObj->rightBorder() - rOffset +
					rightBorder();
				break;
			};
			case LAYOUT_GROUP:
			{
				if (rObj)
					return FALSE;
				preRight = -rOffset + rightBorder();
				break;
			};
			case LAYOUT_OPP:
			{
				if (!rObj)
					return FALSE;
				if (!rObj->preLayoutX(countX))
					return FALSE;
				preRight = rObj->preRight + rObj->preWidth - rOffset;
				break;
			};
			case LAYOUT_OPPBORDER:
			{
				if (!rObj)
					return FALSE;
				if (!rObj->preLayoutX(countX))
					return FALSE;
				preRight = rObj->preRight + rObj->preWidth + rObj->leftBorder()
					- rOffset + rightBorder();
				break;
			};
			case LAYOUT_OPPGROUP:
			{
				if (rObj)
					return FALSE;
				preRight = rightBorder() - rOffset;
				break;
			};
			case LAYOUT_MAXSIZE:
			{
				preRight = rightBorder();
				break;
			};
			case LAYOUT_SAMESIZE:
			{
				preRight = rightBorder();
				break;
			};
			case LAYOUT_PROCENT:
			{
				WORD dr = rightBorder();
				if (rObj)
				{
					if (!rObj->preLayoutX(countX))
						return FALSE;
					switch (rObj->rRel)
					{
					case LAYOUT_PROCENTCENTER:
						dr = (rOffset*(((rObj->preWidth + 1) >> 1) + rObj->leftBorder()+
								rightBorder()))/(rOffset - rObj->rOffset);
							break;
						case LAYOUT_PROCENT:
							dr = (rOffset*(rObj->preWidth + rObj->leftBorder()+
								rightBorder()))/(rOffset - rObj->rOffset);
							break;
						default:
							switch (rObj->lRel)
							{
								case LAYOUT_PROCENTCENTER:
									dr = (rOffset*(((rObj->preWidth + 1) >> 1) + rObj->leftBorder()+
										rightBorder()))/(rOffset - rObj->lOffset);
									break;
								case LAYOUT_PROCENT:
									dr = (rOffset*(rObj->leftBorder()+
										rightBorder()))/(rOffset - rObj->lOffset);
									break;
								default:
									dr += rObj->preRight + rObj->preWidth +
										rObj->leftBorder();
									break;
							};
					};
				};
				WORD dl;
				if (LeftIsLayouted)
					dl = preLeft + preWidth
				else
					dl = leftBorder() + preWidth;
//				WORD dl1 = (dr*(100-rOffset))/rOffset;
				WORD dl1 = (dr*rOffset)/(100-rOffset);
//				WORD dr1 = (dl*rOffset)/(100-rOffset);
				WORD dr1 = (dl*(100-rOffset))/rOffset;
				if (dl1 > dl)
					preLeft = dl1 - preWidth;
				if (dr1 > dr)
					preRight = dr1
				else
					preRight = dr;
				break;
			};
			case LAYOUT_PROCENTCENTER:
			{
				WORD dr = rightBorder() + ((preWidth + 1) >> 1);
				if (rObj)
				{
					if (!rObj->preLayoutX(countX))
						return FALSE;
					switch (rObj->rRel)
					{
						case LAYOUT_PROCENTCENTER:
							dr = (rOffset*(((rObj->preWidth + 1) >> 1) + rObj->leftBorder()+
								((preWidth + 1) >> 1) + rightBorder()))/(rOffset - rObj->rOffset);
							break;
						case LAYOUT_PROCENT:
							dr = (rOffset*(rObj->preWidth + rObj->leftBorder()+
								((preWidth + 1) >> 1) + rightBorder()))/(rOffset - rObj->rOffset);
							break;
						default:
							switch (rObj->lRel)
							{
								case LAYOUT_PROCENTCENTER:
									dr = (rOffset*(((rObj->preWidth + 1) >> 1) + rObj->leftBorder()+
										((preWidth + 1) >> 1) + rightBorder()))/(rOffset - rObj->rOffset);
									break;
								case LAYOUT_PROCENT:
									dr = (rOffset*(rObj->leftBorder()+
										((preWidth + 1) >> 1) + rightBorder()))/(rOffset - rObj->rOffset);
									break;
								default:
									dr += rObj->preRight + rObj->preWidth +
										rObj->leftBorder();
										break;
								};
						};
				};
				WORD dl;
				if (LeftIsLayouted)
					dl = preLeft + ((preWidth + 1) >> 1)
				else
					dl = leftBorder() + ((preWidth + 1) >> 1);
				WORD dl1 = (dr*(100-rOffset))/rOffset;
				WORD dr1 = (dl*rOffset)/(100-rOffset);
				if (dl1 > dl)
					preLeft = dl1 - ((preWidth + 1) >> 1);
				if (dr1 > dr)
					preRight = dr1 - ((preWidth + 1) >> 1)
				else
					preRight = dr - ((preWidth + 1) >> 1);
				break;
			};
			case LAYOUT_MAXSAMEBORDER:
			{
				preRight = rightBorder();
				break;
			};
			case LAYOUT_MAXOPPBORDER:
			{
				preRight = rightBorder();
				break;
			};
			case LAYOUT_HOOK:
				if (!rObj)
					return FALSE;
				lparam.command = LAYOUTC_PRERIGHT;
				lparam.flags = LAYOUTF_LAST_CHANCE;
				lparam.offset = rOffset;
				hookR = ((GeometryHookC *) (GeometryBaseC *) rObj)->call(this,&lparam);
				switch (hookR)
				{
					case LAYOUTR_UNKNOWN:
						return FALSE;
						break;
					case LAYOUTR_OK:
						preRight = lparam.coor_result;
						break;
					case LAYOUTR_ERROR:
						return FALSE;
						break;
					case LAYOUTR_NOTYET:
						return FALSE;
						break;
					default:
						return FALSE;
						break;
				};
				break;
			case LAYOUT_BORDERGROUP:
			{
				if (rObj)
					return FALSE;
				preRight = -rOffset;
				break;
			};
			default:
			{
				return FALSE;
				break;
			};
		};
		if (!LeftIsLayouted)
		{
			switch (lRel)
			{
				case LAYOUT_PROCENT:
				{
					WORD dl = leftBorder();
					if (lObj)
					{
						if (!lObj->preLayoutX(countX))
							return FALSE;
						switch (lObj->lRel)
						{
							case LAYOUT_PROCENTCENTER:
								dl = (lOffset*(((lObj->preWidth + 1) >> 1) + lObj->rightBorder()+
									leftBorder()))/(lOffset - lObj->lOffset);
								break;
							case LAYOUT_PROCENT:
								dl = (lOffset*(lObj->preWidth + lObj->rightBorder()+
									leftBorder()))/(lOffset - lObj->lOffset);
								break;
							default:
								switch (lObj->rRel)
								{
									case LAYOUT_PROCENTCENTER:
										dl = (lOffset*(((lObj->preWidth + 1) >> 1) + lObj->rightBorder()+
											leftBorder()))/(lOffset - lObj->rOffset);
										break;
									case LAYOUT_PROCENT:
										dl = (lOffset*(lObj->rightBorder()+
											leftBorder()))/(lOffset - lObj->rOffset);
										break;
									default:
										dl += lObj->preLeft + lObj->preWidth +
										lObj->rightBorder();
										break;
								};
						};
					};
					WORD dr = preRight + preWidth;
					WORD dr1  = (dl*(100-lOffset))/lOffset;
					WORD dl1 = (dr*lOffset)/(100-lOffset);
					if (dr1 > dr)
						preRight = dr1 - preWidth;
					if (dl1 > dl)
						preLeft = dl1
					else
						preLeft = dl;
					break;
				};
				case LAYOUT_PROCENTCENTER:
				{
					WORD dl = leftBorder() + ((preWidth + 1) >> 1);
					if (lObj)
					{
						if (!lObj->preLayoutX(countX))
							return FALSE;
						switch (lObj->lRel)
						{
							case LAYOUT_PROCENTCENTER:
								dl = (lOffset*(((lObj->preWidth + 1) >> 1) + lObj->rightBorder()+
									((preWidth + 1) >> 1) + leftBorder()))/(lOffset - lObj->lOffset);
								break;
							case LAYOUT_PROCENT:
								dl = (lOffset*(lObj->preWidth + lObj->rightBorder()+
									((preWidth + 1) >> 1) + leftBorder()))/(lOffset - lObj->lOffset);
								break;
							default:
								switch (lObj->rRel)
								{
									case LAYOUT_PROCENTCENTER:
										dl = (lOffset*(((lObj->preWidth + 1) >> 1) + lObj->rightBorder()+
											((preWidth + 1) >> 1) + leftBorder()))/(lOffset - lObj->rOffset);
										break;
									case LAYOUT_PROCENT:
										dl = (lOffset*(lObj->rightBorder()+
											((preWidth + 1) >> 1) + leftBorder()))/(lOffset - lObj->lOffset);
										break;
									default:
										dl += lObj->preLeft + lObj->preWidth +
											lObj->rightBorder();
										break;
								};
						};
					};
					WORD dr = preRight + ((preWidth + 1) >> 1);
					WORD dr1 = (dl*(100-lOffset))/lOffset;
					WORD dl1 = (dr*lOffset)/(100-lOffset);
					if (dr1 > dr)
						preRight = dr1 - ((preWidth + 1) >> 1);
					if (dl1 > dl)
						preLeft = dl1 - ((preWidth + 1) >> 1)
					else
						preLeft = dl - ((preWidth + 1) >> 1);
					break;
				};
				default:
				{
					return FALSE;
					break;
				};
			};
		};
		xLayouting = FALSE;
	};
	return TRUE;
}

BOOL GeometryC::preLayoutY(ULONG countY)
{
	if (countY > preCounterY)
	{
		yLayouting = TRUE;
		preCounterY++;
		preHeight = 0;
// Zuerst einmal die vermutliche Hoehe (preHeight) feststellen
		switch (tRel)
		{
			case LAYOUT_SIZE:
				preHeight = gadget->height();
				break;
			case LAYOUT_MAXSIZE:
				if (tObj)
					return FALSE;
				if (parent)
					preHeight = parent->maxHeight();
				break;
			case LAYOUT_SAMESIZE:
				if (!tObj)
					return FALSE;
				if (!tObj->preLayoutY(countY))
					return FALSE;
				preHeight = tObj->preHeight;
				break;
			case LAYOUT_MAXSAMEBORDER:
				if (tObj)
					return FALSE;
				if (parent)
					preHeight = parent->maxTopBorder();
				break;
			case LAYOUT_MAXOPPBORDER:
				if (tObj)
					return FALSE;
				if (parent)
					preHeight = parent->maxBottomBorder();
				break;
			default:
				break;
		};
		switch (bRel)
		{
			case LAYOUT_SIZE:
				preHeight = gadget->height();
				break;
			case LAYOUT_MAXSIZE:
				if (bObj)
					return FALSE;
				if (parent)
					preHeight = parent->maxHeight();
				break;
			case LAYOUT_SAMESIZE:
				if (!bObj)
					return FALSE;
				if (!bObj->preLayoutY(countY))
					return FALSE;
				preHeight = bObj->preHeight;
				break;
			case LAYOUT_MAXSAMEBORDER:
				if (bObj)
					return FALSE;
				if (parent)
					preHeight = parent->maxBottomBorder();
				break;
			case LAYOUT_MAXOPPBORDER:
				if (bObj)
					return FALSE;
				if (parent)
					preHeight = parent->maxTopBorder();
				break;
			default:
				break;
		};
		if (!preHeight)
			preHeight = gadget->minHeight();
// Jetzt den oberen und unteren Abstand zum Gruppenrand (preTop, preBottom)
// berechnen
		BOOL TopIsLayouted = FALSE;
		switch (tRel)
		{
			case LAYOUT_SIZE:
			{
				if (tObj)
				{
					if (!tObj->preLayoutY(countY))
						return FALSE;
					preTop = tObj->preTop + tObj->preHeight +
						tObj->bottomBorder() + topBorder();
				}
				else
					preTop = topBorder();
			 	TopIsLayouted = TRUE;
				break;
			};
			case LAYOUT_SAME:
			{
				if (!tObj)
					return FALSE;
				if (!tObj->preLayoutY(countY))
					return FALSE;
				preTop = tObj->preTop + tOffset;
				TopIsLayouted = TRUE;
				break;
			};
			case LAYOUT_SAMEBORDER:
			{
				if (!tObj)
					return FALSE;
				if (!tObj->preLayoutY(countY))
					return FALSE;
				preTop = tObj->preTop - tObj->topBorder() + tOffset +
					topBorder();
				TopIsLayouted = TRUE;
				break;
			};
			case LAYOUT_GROUP:
			{
				if (tObj)
					return FALSE;
				preTop = tOffset + topBorder();
				TopIsLayouted = TRUE;
				break;
			};
			case LAYOUT_OPP:
			{
				if (!tObj)
					return FALSE;
				if (!tObj->preLayoutY(countY))
					return FALSE;
				preTop = tObj->preTop + tObj->preHeight + tOffset;
				TopIsLayouted = TRUE;
				break;
			};
			case LAYOUT_OPPBORDER:
			{
				if (!tObj)
					return FALSE;
				if (!tObj->preLayoutY(countY))
					return FALSE;
				preTop = tObj->preTop + tObj->preHeight + tObj->bottomBorder() +
					tOffset + topBorder();
				TopIsLayouted = TRUE;
				break;
			};
			case LAYOUT_OPPGROUP:
			{
				if (tObj)
					return FALSE;
				preTop = topBorder();
				TopIsLayouted = TRUE;
				break;
			};
			case LAYOUT_MAXSIZE:
			{
				preTop = topBorder();
				TopIsLayouted = TRUE;
				break;
			};
			case LAYOUT_SAMESIZE:
			{
				preTop = topBorder();
				TopIsLayouted = TRUE;
				break;
			};
			case LAYOUT_PROCENT:
			{
				break;
			};
			case LAYOUT_PROCENTCENTER:
			{
				break;
			};
			case LAYOUT_MAXSAMEBORDER:
			{
				preTop = topBorder();
				TopIsLayouted = TRUE;
				break;
			};
			case LAYOUT_MAXOPPBORDER:
			{
				preTop = topBorder();
				TopIsLayouted = TRUE;
				break;
			};
			case LAYOUT_BORDERGROUP:
			{
				if (tObj)
					return FALSE;
				preTop = tOffset;
				TopIsLayouted = TRUE;
				break;
			};
			default:
			{
				return FALSE;
				break;
			};
		};
		switch (bRel)
		{
			case LAYOUT_SIZE:
			{
				if (bObj)
				{
					if (!bObj->preLayoutY(countY))
						return FALSE;
					preBottom = bObj->preRight -
						bObj->topBorder() + bottomBorder();
				}
				else
					preBottom = bottomBorder();
				break;
			};
			case LAYOUT_SAME:
			{
				if (!bObj)
					return FALSE;
				if (!bObj->preLayoutY(countY))
					return FALSE;
				preBottom = bObj->preBottom - bOffset;
				break;
			};
			case LAYOUT_SAMEBORDER:
			{
				if (!bObj)
					return FALSE;
				if (!bObj->preLayoutY(countY))
					return FALSE;
				preBottom = bObj->preBottom - bObj->bottomBorder() - bOffset +
					bottomBorder();
				break;
			};
			case LAYOUT_GROUP:
			{
				if (bObj)
					return FALSE;
				preBottom = -bOffset + bottomBorder();
				break;
			};
			case LAYOUT_OPP:
			{
				if (!bObj)
					return FALSE;
				if (!bObj->preLayoutY(countY))
					return FALSE;
				preBottom = bObj->preBottom + bObj->preHeight - bOffset;
				break;
			};
			case LAYOUT_OPPBORDER:
			{
				if (!bObj)
					return FALSE;
				if (!bObj->preLayoutY(countY))
					return FALSE;
				preBottom = bObj->preBottom + bObj->preHeight + bObj->topBorder()
					- bOffset + bottomBorder();
				break;
			};
			case LAYOUT_OPPGROUP:
			{
				if (bObj)
					return FALSE;
				preBottom = bottomBorder() - bOffset;
				break;
			};
			case LAYOUT_MAXSIZE:
			{
				preBottom = bottomBorder();
				break;
			};
			case LAYOUT_SAMESIZE:
			{
				preBottom = bottomBorder();
				break;
			};
			case LAYOUT_PROCENT:
			{
				WORD db = bottomBorder();
				if (bObj)
				{
					if (!bObj->preLayoutY(countY))
						return FALSE;
					switch (bObj->bRel)
					{
						case LAYOUT_PROCENTCENTER:
							db = (bOffset*(((bObj->preHeight + 1) >> 1) + bObj->topBorder()+
								bottomBorder()))/(bOffset - bObj->bOffset);
							break;
						case LAYOUT_PROCENT:
							db = (bOffset*(bObj->preHeight + bObj->topBorder()+
								bottomBorder()))/(bOffset - bObj->bOffset);
							break;
						default:
							switch (bObj->tRel)
							{
								case LAYOUT_PROCENTCENTER:
									db = (bOffset*(((bObj->preHeight + 1) >> 1) + bObj->topBorder()+
										bottomBorder()))/(bOffset - bObj->tOffset);
									break;
								case LAYOUT_PROCENT:
									db = (bOffset*(bObj->topBorder()+
										bottomBorder()))/(bOffset - bObj->tOffset);
									break;
								default:
									db += bObj->preBottom + bObj->preHeight +
										bObj->topBorder();
									break;
							};
					};
				};
				WORD dt;
				if (TopIsLayouted)
					dt = preTop + preHeight
				else
					dt = topBorder() + preHeight;
				WORD dt1 = (db*(100-bOffset))/bOffset;
				WORD db1 = (dt*bOffset)/(100-bOffset);
				if (dt1 > dt)
					preTop = dt1 - preHeight;
				if (db1 > db)
					preBottom = db1
				else
					preBottom = db;
				break;
			};
			case LAYOUT_PROCENTCENTER:
			{
				WORD db = bottomBorder() + ((preHeight + 1) >> 1);
				if (bObj)
				{
					if (!bObj->preLayoutY(countY))
						return FALSE;
					switch (bObj->bRel)
					{
						case LAYOUT_PROCENTCENTER:
							db = (bOffset*(((bObj->preHeight + 1) >> 1) + bObj->topBorder()+
								((preHeight + 1) >> 1) + bottomBorder()))/(bOffset - bObj->bOffset);
							break;
						case LAYOUT_PROCENT:
							db = (bOffset*(bObj->preHeight + bObj->topBorder()+
								((preHeight + 1) >> 1) + bottomBorder()))/(bOffset - bObj->bOffset);
							break;
						default:
							switch (bObj->tRel)
							{
								case LAYOUT_PROCENTCENTER:
									db = (bOffset*(((bObj->preHeight + 1) >> 1) + bObj->topBorder()+
										((preHeight + 1) >> 1) + bottomBorder()))/(bOffset - bObj->bOffset);
									break;
								case LAYOUT_PROCENT:
									db = (bOffset*(bObj->topBorder()+
										((preHeight + 1) >> 1) + bottomBorder()))/(bOffset - bObj->bOffset);
									break;
								default:
									db += bObj->preBottom + bObj->preHeight +
										bObj->topBorder();
									break;
								};
						};
				};
				WORD dt;
				if (TopIsLayouted)
					dt = preTop + ((preHeight + 1) >> 1)
				else
					dt = topBorder() + ((preHeight + 1) >> 1);
				WORD dt1 = (db*(100-bOffset))/bOffset;
				WORD db1 = (dt*bOffset)/(100-bOffset);
				if (dt1 > dt)
					preTop = dt1 - ((preHeight + 1) >> 1);
				if (db1 > db)
					preBottom = db1 - ((preHeight + 1) >> 1)
				else
					preBottom = db - ((preHeight + 1) >> 1);
				break;
			};
			case LAYOUT_MAXSAMEBORDER:
			{
				preBottom = bottomBorder();
				break;
			};
			case LAYOUT_MAXOPPBORDER:
			{
				preBottom = bottomBorder();
				break;
			};
			case LAYOUT_BORDERGROUP:
			{
				if (bObj)
					return FALSE;
				preBottom = -bOffset;
				break;
			};
			default:
			{
				return FALSE;
				break;
			};
		};
		if (!TopIsLayouted)
		{
			switch (tRel)
			{
				case LAYOUT_PROCENT:
				{
					WORD dt = topBorder();
					if (tObj)
					{
						if (!tObj->preLayoutY(countY))
							return FALSE;
						switch (tObj->tRel)
						{
							case LAYOUT_PROCENTCENTER:
								dt = (tOffset*(((tObj->preHeight + 1) >> 1) + tObj->bottomBorder()+
									topBorder()))/(tOffset - tObj->tOffset);
								break;
							case LAYOUT_PROCENT:
								dt = (tOffset*(tObj->preHeight + tObj->bottomBorder()+
									topBorder()))/(tOffset - tObj->tOffset);
								break;
							default:
								switch (tObj->bRel)
								{
									case LAYOUT_PROCENTCENTER:
										dt = (tOffset*(((tObj->preHeight + 1) >> 1) + tObj->bottomBorder()+
											topBorder()))/(tOffset - tObj->bOffset);
										break;
									case LAYOUT_PROCENT:
										dt = (tOffset*(tObj->bottomBorder()+
											topBorder()))/(tOffset - tObj->bOffset);
										break;
									default:
										dt += tObj->preTop + tObj->preHeight +
											tObj->bottomBorder();
										break;
								};
						};
					};
					WORD db = preBottom + preHeight;
					WORD db1  = (dt*(100-tOffset))/tOffset;
					WORD dt1 = (db*tOffset)/(100-tOffset);
					if (db1 > db)
						preBottom = db1 - preHeight;
					if (dt1 > dt)
						preTop = dt1
					else
						preTop = dt;
					break;
				};
				case LAYOUT_PROCENTCENTER:
				{
					WORD dt = topBorder() + ((preHeight + 1) >> 1);
					if (tObj)
					{
						if (!tObj->preLayoutY(countY))
							return FALSE;
						switch (tObj->tRel)
						{
							case LAYOUT_PROCENTCENTER:
								dt = (tOffset*(((tObj->preHeight + 1) >> 1) + tObj->bottomBorder()+
									((preHeight + 1) >> 1) + topBorder()))/(tOffset - tObj->tOffset);
								break;
							case LAYOUT_PROCENT:
								dt = (tOffset*(tObj->preHeight + tObj->bottomBorder()+
									((preHeight + 1) >> 1) + topBorder()))/(tOffset - tObj->tOffset);
								break;
							default:
								switch (tObj->bRel)
								{
									case LAYOUT_PROCENTCENTER:
										dt = (tOffset*(((tObj->preHeight + 1) >> 1) + tObj->bottomBorder()+
											((preHeight + 1) >> 1) + topBorder()))/(tOffset - tObj->bOffset);
										break;
									case LAYOUT_PROCENT:
										dt = (tOffset*(tObj->bottomBorder()+
											((preHeight + 1) >> 1) + topBorder()))/(tOffset - tObj->tOffset);
										break;
									default:
										dt += tObj->preTop + tObj->preHeight +
											tObj->bottomBorder();
										break;
								};
						};
					};
					WORD db = preBottom + ((preHeight + 1) >> 1);
					WORD db1 = (dt*(100-tOffset))/tOffset;
					WORD dt1 = (db*tOffset)/(100-tOffset);
					if (db1 > db)
						preBottom = db1 - ((preHeight + 1) >> 1);
					if (db1 > db)
						preTop = db1 - ((preHeight + 1) >> 1)
					else
						preTop = db - ((preHeight + 1) >> 1);
					break;
				};
				default:
				{
					return FALSE;
					break;
				};
			};
		};
		yLayouting = FALSE;
	};
	return TRUE;
}

VOID GeometryC::move(WORD dx, WORD dy)
{
	dx += gadget->left();
	gadget->setLeft(dx);
	dy += gadget->top();
	gadget->setTop(dy);
}

BOOL GeometryC::layoutX(WORD parentLeft, WORD parentWidth, ULONG countX)
{
	if (countX > counterX)
	{
		xLayouting = TRUE;
		counterX++;
		struct LayoutParamPkt lparam;
		lparam.parent = parent;
		lparam.parentPosition = parentLeft;
		lparam.parentSize = parentWidth;
		lparam.count = countX;
		ULONG hookR;
		BOOL LeftIsLayouted = FALSE;
		switch (lRel)
		{
			case LAYOUT_SIZE:
			{
				break;
			};
			case LAYOUT_SAME:
			{
				if (!lObj)
					return FALSE;
				if (!lObj->layoutX(parentLeft,parentWidth,countX))
					return FALSE;
				left = lObj->layoutedLeft()+lOffset;
				LeftIsLayouted = TRUE;
				break;
			};
			case LAYOUT_SAMEBORDER:
			{
				if (!lObj)
					return FALSE;
				if (!lObj->layoutX(parentLeft,parentWidth,countX))
					return FALSE;
				left = lObj->layoutedLeft()-lObj->leftBorder()+leftBorder()+lOffset;
				LeftIsLayouted = TRUE;
				break;
			};
			case LAYOUT_GROUP:
			{
				if (lObj)
					return FALSE;
				left = parentLeft+leftBorder()+lOffset;
				LeftIsLayouted = TRUE;
				break;
			};
			case LAYOUT_OPP:
			{
				if (!lObj)
					return FALSE;
				if (!lObj->layoutX(parentLeft,parentWidth,countX))
					return FALSE;
				left = lObj->layoutedRight()+lOffset;
				LeftIsLayouted = TRUE;
				break;
			};
			case LAYOUT_OPPBORDER:
			{
				if (!lObj)
					return FALSE;
				if (!lObj->layoutX(parentLeft,parentWidth,countX))
					return FALSE;
				left = lObj->layoutedRight()+lObj->rightBorder()+
					leftBorder()+lOffset;
				LeftIsLayouted = TRUE;
				break;
			};
			case LAYOUT_OPPGROUP:
			{
				if (lObj)
					return FALSE;
				left = parentLeft+parentWidth+lOffset;
				LeftIsLayouted = TRUE;
				break;
			};
			case LAYOUT_MAXSIZE:
			{
				break;
			};
			case LAYOUT_SAMESIZE:
			{
				break;
			};
			case LAYOUT_PROCENT:
			{
				left = parentLeft+(parentWidth*lOffset)/100;
				LeftIsLayouted = TRUE;
				break;
			};
			case LAYOUT_PROCENTCENTER:
			{
				break;
			};
			case LAYOUT_MAXSAMEBORDER:
			{
				break;
			};
			case LAYOUT_MAXOPPBORDER:
			{
				break;
			};
			case LAYOUT_HOOK:
				if (!lObj)
					return FALSE;
				lparam.command = LAYOUTC_LEFT;
				lparam.flags = LAYOUTF_LAST_CHANCE;
				lparam.offset = lOffset;
				hookR = ((GeometryHookC *) (GeometryBaseC *) lObj)->call(this,&lparam);
				switch (hookR)
				{
					case LAYOUTR_UNKNOWN:
						return FALSE;
						break;
					case LAYOUTR_OK:
						left = lparam.coor_result;
						LeftIsLayouted = TRUE;
						break;
					case LAYOUTR_ERROR:
						return FALSE;
						break;
					case LAYOUTR_NOTYET:
						return FALSE;
						break;
					default:
						return FALSE;
						break;
				};
				break;
			case LAYOUT_BORDERGROUP:
			{
				if (lObj)
					return FALSE;
				left = parentLeft+lOffset;
				LeftIsLayouted = TRUE;
				break;
			};
			default:
			{
				return FALSE;
				break;
			};
		};
		BOOL RightIsLayouted = FALSE;
		switch (rRel)
		{
			case LAYOUT_SIZE:
			{
				if (LeftIsLayouted)
				{
					right = left+gadget->width();
					RightIsLayouted = TRUE;
				};
				break;
			};
			case LAYOUT_SAME:
			{
				if (!rObj)
					return FALSE;
				if (!rObj->layoutX(parentLeft,parentWidth,countX))
					return FALSE;
				right = rObj->layoutedRight()+rOffset;
				RightIsLayouted = TRUE;
				break;
			};
			case LAYOUT_SAMEBORDER:
			{
				if (!rObj)
					return FALSE;
				if (!rObj->layoutX(parentLeft,parentWidth,countX))
					return FALSE;
				right = rObj->layoutedRight()+rObj->rightBorder()-
					rightBorder()+rOffset;
				RightIsLayouted = TRUE;
				break;
			};
			case LAYOUT_GROUP:
			{
				if (rObj)
					return FALSE;
				right = parentLeft+parentWidth-rightBorder()+rOffset;
				RightIsLayouted = TRUE;
				break;
			};
			case LAYOUT_OPP:
			{
				if (!rObj)
					return FALSE;
				if (!rObj->layoutX(parentLeft,parentWidth,countX))
					return FALSE;
				right = rObj->layoutedLeft()+rOffset;
				RightIsLayouted = TRUE;
				break;
			};
			case LAYOUT_OPPBORDER:
			{
				if (!rObj)
					return FALSE;
				if (!rObj->layoutX(parentLeft,parentWidth,countX))
					return FALSE;
				right = rObj->layoutedLeft()-rObj->leftBorder()-
					rightBorder()+rOffset;
				RightIsLayouted = TRUE;
				break;
			};
			case LAYOUT_OPPGROUP:
			{
				if (rObj)
					return FALSE;
				right = parentLeft+rOffset;
				RightIsLayouted = TRUE;
				break;
			};
			case LAYOUT_MAXSIZE:
			{
				if (LeftIsLayouted)
				{
					if (rObj)
						return FALSE;
					if (!parent)
						return FALSE;
					right = left+parent->maxWidth();
					RightIsLayouted = TRUE;
				};
				break;
			};
			case LAYOUT_SAMESIZE:
			{
				if (!rObj)
					return FALSE;
				if (!rObj->layoutX(parentLeft,parentWidth,countX))
					return FALSE;
				if (LeftIsLayouted)
				{
					right = left + rObj->layoutedWidth();
					RightIsLayouted = TRUE;
				};
				break;
			};
			case LAYOUT_PROCENT:
			{
				right = parentLeft+(parentWidth*rOffset)/100;
				RightIsLayouted = TRUE;
				break;
			};
			case LAYOUT_PROCENTCENTER:
			{
				WORD center = parentLeft+(parentWidth*rOffset)/100;
				if (LeftIsLayouted)
				{
					right = center + (center - left);
					RightIsLayouted = TRUE;
				}
				else
					switch (lRel)
					{
						case LAYOUT_SIZE:
							right = center+(gadget->width() >> 1);
							RightIsLayouted = TRUE;
							break;
						case LAYOUT_MAXSIZE:
							if (!parent)
								return FALSE;
							right = center+(parent->maxWidth() >> 1);
							RightIsLayouted = TRUE;
							break;
						case LAYOUT_SAMESIZE:
							right = center+(lObj->layoutedWidth() >> 1);
							RightIsLayouted = TRUE;
							break;
						case LAYOUT_MAXSAMEBORDER:
							if (!parent)
								return FALSE;
							right = center+(parent->maxLeftBorder() >> 1);
							RightIsLayouted = TRUE;
							break;
						case LAYOUT_MAXOPPBORDER:
							if (!parent)
								return FALSE;
							right = center+(parent->maxRightBorder() >> 1);
							RightIsLayouted = TRUE;
							break;
						default:
							return FALSE;
							break;
					};
				break;
			};
			case LAYOUT_MAXSAMEBORDER:
			{
				if (LeftIsLayouted)
				{
					if (rObj)
						return FALSE;
					if (!parent)
						return FALSE;
					right = left+parent->maxRightBorder();
					RightIsLayouted = TRUE;
				};
				break;
			};
			case LAYOUT_MAXOPPBORDER:
			{
				if (LeftIsLayouted)
				{
					if (rObj)
						return FALSE;
					if (!parent)
						return FALSE;
					right = left+parent->maxLeftBorder();
					RightIsLayouted = TRUE;
				};
				break;
			};
			case LAYOUT_HOOK:
				if (!rObj)
					return FALSE;
				lparam.command = LAYOUTC_RIGHT;
				lparam.flags = LAYOUTF_LAST_CHANCE;
				lparam.offset = rOffset;
				hookR = ((GeometryHookC *) (GeometryBaseC *) rObj)->call(this,&lparam);
				switch (hookR)
				{
					case LAYOUTR_UNKNOWN:
						return FALSE;
						break;
					case LAYOUTR_OK:
						right = lparam.coor_result;
						RightIsLayouted = TRUE;
						break;
					case LAYOUTR_ERROR:
						return FALSE;
						break;
					case LAYOUTR_NOTYET:
						return FALSE;
						break;
					default:
						return FALSE;
						break;
				};
				break;
			case LAYOUT_BORDERGROUP:
			{
				if (rObj)
					return FALSE;
				right = parentLeft+parentWidth+rOffset;
				RightIsLayouted = TRUE;
				break;
			};
			default:
			{
				return FALSE;
				break;
			};
		};
		if (!LeftIsLayouted)
		{
			switch (lRel)
			{
				case LAYOUT_SIZE:
				{
					if (!RightIsLayouted)
						return FALSE;
					left = right-gadget->width();
					break;
				};
				case LAYOUT_MAXSIZE:
				{
					if (lObj)
						return FALSE;
					if (!RightIsLayouted)
						return FALSE;
					if (!parent)
						return FALSE;
					left = right-parent->maxWidth();
					break;
				};
				case LAYOUT_SAMESIZE:
				{
					if (!lObj)
						return FALSE;
					if (!lObj->layoutX(parentLeft,parentWidth,countX))
						return FALSE;
					if (!RightIsLayouted)
						return FALSE;
					left = right-lObj->layoutedWidth();
					break;
				};
				case LAYOUT_PROCENTCENTER:
				{
					WORD center = parentLeft+(parentWidth*lOffset)/100;
					if (RightIsLayouted)
						left = center - (right - center)
					else
						switch (rRel)
						{
							case LAYOUT_SIZE:
								left = center-(gadget->width() >> 1);
								right = left + gadget->width();
								break;
							case LAYOUT_MAXSIZE:
								if (!parent)
									return FALSE;
								left = center-(parent->maxWidth() >> 1);
								right = left+parent->maxWidth();
								break;
							case LAYOUT_SAMESIZE:
								left = center-(rObj->layoutedWidth() >> 1);
								right = left+rObj->layoutedWidth();
								break;
							case LAYOUT_MAXSAMEBORDER:
								if (!parent)
									return FALSE;
								left = center-(parent->maxRightBorder() >> 1);
								break;
							case LAYOUT_MAXOPPBORDER:
								if (!parent)
									return FALSE;
								left = center-(parent->maxLeftBorder() >> 1);
								break;
							default:
								return FALSE;
								break;
						};
					break;
				};
				case LAYOUT_MAXSAMEBORDER:
				{
					if (lObj)
						return FALSE;
					if (!RightIsLayouted)
						return FALSE;
					if (!parent)
						return FALSE;
					left = right-parent->maxLeftBorder();
					break;
				};
				case LAYOUT_MAXOPPBORDER:
				{
					if (lObj)
						return FALSE;
					if (!RightIsLayouted)
						return FALSE;
					if (!parent)
						return FALSE;
					left = right-parent->maxRightBorder();
					break;
				};
				default:
				{
					return FALSE;
					break;
				};
			};
		};
		xLayouting = FALSE;
		gadget->setLeft(layoutedLeft());
		gadget->setWidth(layoutedWidth());
	};
	return TRUE;
}

BOOL GeometryC::layoutY(WORD parentTop, WORD parentHeight, ULONG countY)
{
	if (countY > counterY)
	{
		xLayouting = TRUE;
		counterY++;
		BOOL TopIsLayouted = FALSE;
		switch (tRel)
		{
			case LAYOUT_SIZE:
			{
				break;
			};
			case LAYOUT_SAME:
			{
				if (!tObj)
					return FALSE;
				if (!tObj->layoutY(parentTop,parentHeight,countY))
					return FALSE;
				top = tObj->layoutedTop()+tOffset;
				TopIsLayouted = TRUE;
				break;
			};
			case LAYOUT_SAMEBORDER:
			{
				if (!tObj)
					return FALSE;
				if (!tObj->layoutY(parentTop,parentHeight,countY))
					return FALSE;
				top = tObj->layoutedTop()-tObj->topBorder()+topBorder()+tOffset;
				TopIsLayouted = TRUE;
				break;
			};
			case LAYOUT_GROUP:
			{
				if (tObj)
					return FALSE;
				top = parentTop+topBorder()+tOffset;
				TopIsLayouted = TRUE;
				break;
			};
			case LAYOUT_OPP:
			{
				if (!tObj)
					return FALSE;
				if (!tObj->layoutY(parentTop,parentHeight,countY))
					return FALSE;
				top = tObj->layoutedRight()+tOffset;
				TopIsLayouted = TRUE;
				break;
			};
			case LAYOUT_OPPBORDER:
			{
				if (!tObj)
					return FALSE;
				if (!tObj->layoutY(parentTop,parentHeight,countY))
					return FALSE;
				top = tObj->layoutedBottom()+tObj->bottomBorder()+
					topBorder()+tOffset;
				TopIsLayouted = TRUE;
				break;
			};
			case LAYOUT_OPPGROUP:
			{
				if (tObj)
					return FALSE;
				top = parentTop+parentHeight+tOffset;
				TopIsLayouted = TRUE;
				break;
			};
			case LAYOUT_MAXSIZE:
			{
				break;
			};
			case LAYOUT_SAMESIZE:
			{
				break;
			};
			case LAYOUT_PROCENT:
			{
				top = parentTop+(parentHeight*tOffset)/100;
				TopIsLayouted = TRUE;
				break;
			};
			case LAYOUT_PROCENTCENTER:
			{
				break;
			};
			case LAYOUT_MAXSAMEBORDER:
			{
				break;
			};
			case LAYOUT_MAXOPPBORDER:
			{
				break;
			};
			case LAYOUT_BORDERGROUP:
			{
				if (tObj)
					return FALSE;
				top = parentTop+tOffset;
				TopIsLayouted = TRUE;
				break;
			};
			default:
			{
				return FALSE;
				break;
			};
		};
		BOOL BottomIsLayouted = FALSE;
		switch (bRel)
		{
			case LAYOUT_SIZE:
			{
				if (TopIsLayouted)
				{
					bottom = top+gadget->height();
					BottomIsLayouted = TRUE;
				};
				break;
			};
			case LAYOUT_SAME:
			{
				if (!bObj)
					return FALSE;
				if (!bObj->layoutY(parentTop,parentHeight,countY))
					return FALSE;
				bottom = bObj->layoutedBottom()+bOffset;
				BottomIsLayouted = TRUE;
				break;
			};
			case LAYOUT_SAMEBORDER:
			{
				if (!bObj)
					return FALSE;
				if (!bObj->layoutY(parentTop,parentHeight,countY))
					return FALSE;
				bottom = bObj->layoutedBottom()+bObj->bottomBorder()-
					bottomBorder()+bOffset;
				BottomIsLayouted = TRUE;
				break;
			};
			case LAYOUT_GROUP:
			{
				if (bObj)
					return FALSE;
				bottom = parentTop+parentHeight-bottomBorder()+bOffset;
				BottomIsLayouted = TRUE;
				break;
			};
			case LAYOUT_OPP:
			{
				if (!bObj)
					return FALSE;
				if (!bObj->layoutY(parentTop,parentHeight,countY))
					return FALSE;
				bottom = bObj->layoutedTop()+bOffset;
				BottomIsLayouted = TRUE;
				break;
			};
			case LAYOUT_OPPBORDER:
			{
				if (!bObj)
					return FALSE;
				if (!bObj->layoutY(parentTop,parentHeight,countY))
					return FALSE;
				bottom = bObj->layoutedTop()-bObj->topBorder()-
					bottomBorder()+bOffset;
				BottomIsLayouted = TRUE;
				break;
			};
			case LAYOUT_OPPGROUP:
			{
				if (bObj)
					return FALSE;
				bottom = parentTop+bOffset;
				BottomIsLayouted = TRUE;
				break;
			};
			case LAYOUT_MAXSIZE:
			{
				if (TopIsLayouted)
				{
					if (bObj)
						return FALSE;
					if (!parent)
						return FALSE;
					bottom = top+parent->maxHeight();
					BottomIsLayouted = TRUE;
				};
				break;
			};
			case LAYOUT_SAMESIZE:
			{
				if (!bObj)
					return FALSE;
				if (!bObj->layoutY(parentTop,parentHeight,countY))
					return FALSE;
				if (TopIsLayouted)
				{
					bottom = top + bObj->layoutedHeight();
					BottomIsLayouted = TRUE;
				};
				break;
			};
			case LAYOUT_PROCENT:
			{
				bottom = parentTop+(parentHeight*bOffset)/100;
				BottomIsLayouted = TRUE;
				break;
			};
			case LAYOUT_PROCENTCENTER:
			{
				WORD center = parentTop+(parentHeight*bOffset)/100;
				if (TopIsLayouted)
				{
					bottom = center + (center - top);
					BottomIsLayouted = TRUE;
				}
				else
					switch (tRel)
					{
						case LAYOUT_SIZE:
							bottom = center+(gadget->height() >> 1);
							BottomIsLayouted = TRUE;
							break;
						case LAYOUT_MAXSIZE:
							if (!parent)
								return FALSE;
							bottom = center+(parent->maxHeight() >> 1);
							BottomIsLayouted = TRUE;
							break;
						case LAYOUT_SAMESIZE:
							bottom = center+(tObj->layoutedHeight() >> 1);
							BottomIsLayouted = TRUE;
							break;
						case LAYOUT_MAXSAMEBORDER:
							if (!parent)
								return FALSE;
							bottom = center+(parent->maxTopBorder() >> 1);
							BottomIsLayouted = TRUE;
							break;
						case LAYOUT_MAXOPPBORDER:
							if (!parent)
								return FALSE;
							bottom = center+(parent->maxBottomBorder() >> 1);
							BottomIsLayouted = TRUE;
							break;
						default:
							return FALSE;
							break;
					};
				break;
			};
			case LAYOUT_MAXSAMEBORDER:
			{
				if (TopIsLayouted)
				{
					if (bObj)
						return FALSE;
					if (!parent)
						return FALSE;
					bottom = top+parent->maxBottomBorder();
					BottomIsLayouted = TRUE;
				};
				break;
			};
			case LAYOUT_MAXOPPBORDER:
			{
				if (TopIsLayouted)
				{
					if (bObj)
						return FALSE;
					if (!parent)
						return FALSE;
					bottom = top+parent->maxTopBorder();
					BottomIsLayouted = TRUE;
				};
				break;
			};
			case LAYOUT_BORDERGROUP:
			{
				if (bObj)
					return FALSE;
				bottom = parentTop+parentHeight+bOffset;
				BottomIsLayouted = TRUE;
				break;
			};
			default:
			{
				return FALSE;
				break;
			};
		};
		if (!TopIsLayouted)
		{
			switch (tRel)
			{
				case LAYOUT_SIZE:
				{
					if (!BottomIsLayouted)
						return FALSE;
					top = bottom-gadget->height();
					break;
				};
				case LAYOUT_MAXSIZE:
				{
					if (tObj)
						return FALSE;
					if (!BottomIsLayouted)
						return FALSE;
					if (!parent)
						return FALSE;
					top = bottom-parent->maxHeight();
					break;
				};
				case LAYOUT_SAMESIZE:
				{
					if (!tObj)
						return FALSE;
					if (!tObj->layoutY(parentTop,parentHeight,countY))
						return FALSE;
					if (!BottomIsLayouted)
						return FALSE;
					top = bottom-tObj->layoutedHeight();
					break;
				};
				case LAYOUT_PROCENTCENTER:
				{
					WORD center = parentTop+(parentHeight*tOffset)/100;
					if (BottomIsLayouted)
						top = center - (bottom - center)
					else
						switch (bRel)
						{
							case LAYOUT_SIZE:
								top = center-(gadget->height() >> 1);
								bottom = top + gadget->height();
								break;
							case LAYOUT_MAXSIZE:
								if (!parent)
									return FALSE;
								top = center-(parent->maxHeight() >> 1);
								bottom = top+parent->maxHeight();
								break;
							case LAYOUT_SAMESIZE:
								top = center-(bObj->layoutedHeight() >> 1);
								bottom = top+bObj->layoutedHeight();
								break;
							case LAYOUT_MAXSAMEBORDER:
								if (!parent)
									return FALSE;
								top = center-(parent->maxBottomBorder() >> 1);
								break;
							case LAYOUT_MAXOPPBORDER:
								if (!parent)
									return FALSE;
								top = center-(parent->maxTopBorder() >> 1);
								break;
							default:
								return FALSE;
								break;
						};
					break;
				};
				case LAYOUT_MAXSAMEBORDER:
				{
					if (tObj)
						return FALSE;
					if (!BottomIsLayouted)
						return FALSE;
					if (!parent)
						return FALSE;
					top = bottom-parent->maxTopBorder();
					break;
				};
				case LAYOUT_MAXOPPBORDER:
				{
					if (tObj)
						return FALSE;
					if (!BottomIsLayouted)
						return FALSE;
					if (!parent)
						return FALSE;
					top = bottom-parent->maxBottomBorder();
					break;
				};
				default:
				{
					return FALSE;
					break;
				};
			};
		};
		xLayouting = FALSE;
		gadget->setTop(layoutedTop());
		gadget->setHeight(layoutedHeight());
	};
	return TRUE;
}

BOOL GeometryC::layoutGadWidth()
{
	return gadget->layoutWidth();
}

BOOL GeometryC::layoutGadHeight()
{
	return gadget->layoutHeight();
}

VOID GeometryC::setTopRule(ULONG relation, GeometryBaseC *object, WORD offset)
{
	tRel = relation;
	tObj = (GeometryC *) object;
	tOffset = offset;
}

VOID GeometryC::setBottomRule(ULONG relation, GeometryBaseC *object, WORD offset)
{
	bRel = relation;
	bObj = (GeometryC *) object;
	bOffset = offset;
}

VOID GeometryC::setLeftRule(ULONG relation, GeometryBaseC *object, WORD offset)
{
	lRel = relation;
	lObj = (GeometryC *) object;
	lOffset = offset;
}

VOID GeometryC::setRightRule(ULONG relation, GeometryBaseC *object, WORD offset)
{
	rRel = relation;
	rObj = (GeometryC *) object;
	rOffset = offset;
}

ULONG GeometryC::topRule(GeometryBaseC *&object, WORD &offset)
{
	object = tObj;
	offset = tOffset;
	return tRel;
}

ULONG GeometryC::bottomRule(GeometryBaseC *&object, WORD &offset)
{
	object = bObj;
	offset = bOffset;
	return bRel;
}

ULONG GeometryC::leftRule(GeometryBaseC *&object, WORD &offset)
{
	object = lObj;
	offset = lOffset;
	return lRel;
}

ULONG GeometryC::rightRule(GeometryBaseC *&object, WORD &offset)
{
	object = rObj;
	offset = rOffset;
	return rRel;
}

VOID GeometryC::setCounters(ULONG cX, ULONG cY, ULONG pX, ULONG pY)
{
	xLayouting = FALSE;
	yLayouting = FALSE;
	counterX = cX;
	counterY = cY;
	preCounterX = pX;
	preCounterY = pY;
}

// ****************************************************************

GeometryGroupC::GeometryGroupC(GroupLayoutC &g,
		ULONG topRelation, GeometryBaseC *topObject, WORD topOffset,
		ULONG bottomRelation, GeometryBaseC *bottomObject, WORD bottomOffset,
		ULONG leftRelation, GeometryBaseC *leftObject, WORD leftOffset,
		ULONG rightRelation, GeometryBaseC *rightObject, WORD rightOffset)
	: GeometryC(g,
		topRelation, topObject, topOffset,
		bottomRelation, bottomObject, bottomOffset,
		leftRelation, leftObject, leftOffset,
		rightRelation, rightObject, rightOffset),
	  maximumLeftB(0),
	  maximumRightB(0),
	  maximumTopB(0),
	  maximumBottomB(0),
	  maxLBorder(0),
	  maxRBorder(0),
	  maxTBorder(0),
	  maxBBorder(0)
{
	border = &g;
	maximumWidth = 0;
	maximumHeight = 0;
}

GeometryGroupC::~GeometryGroupC()
{
}

VOID GeometryGroupC::add(GeometryC &g)
{
	if (!g.isInList())
	{
		g.parent = this;
		g.setCounters(counterX,counterY,preCounterX,preCounterY);
		ListC::addTail(g);
	};
}

BOOL GeometryGroupC::preLayoutX(ULONG countX)
{
	if (countX > preCounterX)
	{
		if (gadget->autoWidth())
		{
			WORD width = 0;
			ListCursorC lc(*this);
			while (!lc.isDone()) {
				if (!((GeometryC *) lc.item())->preLayoutX(countX))
					return FALSE;
				WORD w = ((GeometryC *) lc.item())->preLeft +
					((GeometryC *) lc.item())->preRight +
					((GeometryC *) lc.item())->preWidth;
				if (w > width)
					width = w;
				lc.next();
			};
			if (width < 0)
				return FALSE;
			WORD w = width +
				border->innerLeftBorder()+
				border->innerRightBorder();
			gadget->setWidth(w);
			border->setMinWidth(w);
		};
		return GeometryC::preLayoutX(countX);
	};
	return TRUE;
}

BOOL GeometryGroupC::preLayoutY(ULONG countY)
{
	if (countY > preCounterY)
	{
		if (gadget->autoHeight())
		{
			WORD height = 0;
			ListCursorC lc(*this);
			while (!lc.isDone()) {
				if (!((GeometryC *) lc.item())->preLayoutY(countY))
					return FALSE;
				WORD h = ((GeometryC *) lc.item())->preTop +
					((GeometryC *) lc.item())->preBottom +
					((GeometryC *) lc.item())->preHeight;
				if (h > height)
					height = h;
				lc.next();
			};
			if (height < 0)
				return FALSE;
			WORD h = height +
				border->innerTopBorder()+
				border->innerBottomBorder();
			gadget->setHeight(h);
			border->setMinHeight(h);
		};
		return GeometryC::preLayoutY(countY);
	};
	return TRUE;
}

VOID GeometryGroupC::move(WORD dx, WORD dy)
{
	GeometryC::move(dx,dy);
	ListCursorC lc(*this);
	while (!lc.isDone()) {
		((GeometryC *) lc.item())->move(dx,dy);
		lc.next();
	};
}

BOOL GeometryGroupC::layoutX(WORD parentLeft, WORD parentWidth, ULONG countX)
{
	if (countX > counterX)
	{
		if (gadget->autoWidth() && (parentWidth == LAYOUT_AUTOSIZE))
		{
			WORD width = 0;
			preCounterX++;
			ListCursorC lc(*this);
			while (!lc.isDone()) {
				if (!((GeometryC *) lc.item())->preLayoutX(preCounterX))
					return FALSE;
				WORD w = ((GeometryC *) lc.item())->preLeft +
					((GeometryC *) lc.item())->preRight +
					((GeometryC *) lc.item())->preWidth;
				if (w > width)
					width = w;
				lc.next();
			};
			if (width < 0)
				return FALSE;
			WORD w = width +
				border->innerLeftBorder()+
				border->innerRightBorder();
			gadget->setWidth(w);
		};
		if (!GeometryC::layoutX(parentLeft,parentWidth,countX))
			return FALSE;
		ListCursorC lc(*this);
		while (!lc.isDone()) {
			if (!((GeometryC *) lc.item())->layoutX(
					layoutedLeft() + border->innerLeftBorder(),
					layoutedWidth() - border->innerLeftBorder() -
						border->innerRightBorder(),
					countX))
				return FALSE;
			lc.next();
		};
	};
	return TRUE;
}

BOOL GeometryGroupC::layoutY(WORD parentTop, WORD parentHeight, ULONG countY)
{
	if (countY > counterY)
	{
		if (gadget->autoHeight() && (parentHeight == LAYOUT_AUTOSIZE))
		{
			WORD height = 0;
			preCounterY++;
			ListCursorC lc(*this);
			while (!lc.isDone()) {
				if (!((GeometryC *) lc.item())->preLayoutY(preCounterY))
					return FALSE;
				WORD h = ((GeometryC *) lc.item())->preTop +
					((GeometryC *) lc.item())->preBottom +
					((GeometryC *) lc.item())->preHeight;
				if (h > height)
					height = h;
				lc.next();
			};
			if (height < 0)
				return FALSE;
			WORD h = height +
				border->innerTopBorder()+
				border->innerBottomBorder();
			gadget->setHeight(h);
		};
		if (!GeometryC::layoutY(parentTop,parentHeight,countY))
			return FALSE;
		ListCursorC lc(*this);
		while (!lc.isDone()) {
			if (!((GeometryC *) lc.item())->layoutY(
					layoutedTop() + border->innerTopBorder(),
					layoutedHeight() - border->innerTopBorder() -
						border->innerBottomBorder(),
					countY))
				return FALSE;
			lc.next();
		};
	};
	return TRUE;
}

BOOL GeometryGroupC::layoutGadWidth()
{
	WORD width = 0;
	WORD left = 0;
	WORD right = 0;
	maxLBorder = gadget->leftBorder();
	maxRBorder = gadget->rightBorder();
	ListCursorC lc(*this);
	while (!lc.isDone()) {
		if (((GeometryC *) lc.item())->layoutGadWidth())
		{
			WORD w = ((GeometryC *) lc.item())->gadget->width();
			if (((GeometryC *) lc.item())->lRel == LAYOUT_MAXSIZE)
				if (w < ((GeometryC *) lc.item())->lOffset)
					w = ((GeometryC *) lc.item())->lOffset;
			if (((GeometryC *) lc.item())->rRel == LAYOUT_MAXSIZE)
				if (w < ((GeometryC *) lc.item())->rOffset)
					w = ((GeometryC *) lc.item())->rOffset;
			if (width < w)
				width = w;
			w = ((GeometryC *) lc.item())->leftBorder();
			if (left < w)
				left = w;
			if (((GeometryC *) lc.item())->lRel == LAYOUT_BORDERGROUP)
			{
				w -= ((GeometryC *) lc.item())->lOffset;
				if (w > maxLBorder)
					maxLBorder = w;
			};
			w = ((GeometryC *) lc.item())->rightBorder();
			if (right < w)
				right = w;
			if (((GeometryC *) lc.item())->rRel == LAYOUT_BORDERGROUP)
			{
				w -= ((GeometryC *) lc.item())->rOffset;
				if (w > maxRBorder)
					maxRBorder = w;
			};
		};
		lc.next();
	};
	maximumWidth = width;
	maximumLeftB = left;
	maximumRightB = right;
	return gadget->layoutWidth();
}

BOOL GeometryGroupC::layoutGadHeight()
{
	WORD height = 0;
	WORD top = 0;
	WORD bottom = 0;
	maxTBorder = gadget->topBorder();
	maxRBorder = gadget->bottomBorder();
	ListCursorC lc(*this);
	while (!lc.isDone()) {
		if (((GeometryC *) lc.item())->layoutGadHeight())
		{
			WORD h = ((GeometryC *) lc.item())->gadget->height();
			if (((GeometryC *) lc.item())->tRel == LAYOUT_MAXSIZE)
				if (h < ((GeometryC *) lc.item())->tOffset)
					h = ((GeometryC *) lc.item())->tOffset;
			if (((GeometryC *) lc.item())->bRel == LAYOUT_MAXSIZE)
				if (h < ((GeometryC *) lc.item())->bOffset)
					h = ((GeometryC *) lc.item())->bOffset;
			if (height < h)
				height = h;
			h = ((GeometryC *) lc.item())->topBorder();
			if (top < h)
				top = h;
			if (((GeometryC *) lc.item())->tRel == LAYOUT_BORDERGROUP)
			{
				h -= ((GeometryC *) lc.item())->tOffset;
				if (h > maxTBorder)
					maxTBorder = h;
			};
			h = ((GeometryC *) lc.item())->bottomBorder();
			if (bottom < h)
				bottom = h;
			if (((GeometryC *) lc.item())->bRel == LAYOUT_BORDERGROUP)
			{
				h -= ((GeometryC *) lc.item())->bOffset;
				if (h > maxBBorder)
					maxBBorder = h;
			};
		};
		lc.next();
	};
	maximumHeight = height;
	maximumTopB = top;
	maximumBottomB = bottom;
	return gadget->layoutHeight();
}

VOID GeometryGroupC::setCounters(ULONG cX, ULONG cY, ULONG pX, ULONG pY)
{
	ListCursorC lc(*this);
	while (!lc.isDone()) {
		((GeometryC *) lc.item())->setCounters(cX,cY,pX,pY);
		lc.next();
	};
	GeometryC::setCounters(cX,cY,pX,pY);
}

// *******************************************************************

RootGeometryC::RootGeometryC()
	: transparent(),
	  gadget(transparent),
	  group(gadget,
		LAYOUT_GROUP,NULL,0, LAYOUT_SIZE,NULL,0,
		LAYOUT_GROUP,NULL,0, LAYOUT_SIZE,NULL,0)
{
	counterX = 0;
	counterY = 0;
}

RootGeometryC::RootGeometryC(GroupLayoutC &g)
	: transparent(),
	  gadget(g),
	  group(gadget,
		LAYOUT_GROUP,NULL,0, LAYOUT_SIZE,NULL,0,
		LAYOUT_GROUP,NULL,0, LAYOUT_SIZE,NULL,0)
{
	counterX = 0;
	counterY = 0;
}

VOID RootGeometryC::add(GeometryC &g)
{
	group.add(g);
}

VOID RootGeometryC::layout(WORD parentTop, WORD parentLeft,
		WORD parentWidth, WORD parentHeight)
{
	gadget.setWidth(parentWidth);
	gadget.setHeight(parentHeight);
	if (parentWidth == LAYOUT_AUTOSIZE)
		group.layoutGadWidth();
	if (parentHeight == LAYOUT_AUTOSIZE)
		group.layoutGadHeight();
	counterX++;
	counterY++;
	if (!group.layoutX(parentLeft,parentWidth,counterX))
	{
		throw LayouterX();
	};
	if (!group.layoutY(parentTop,parentHeight,counterY))
	{
		throw LayouterX();
	};
}
