//------------------------------------------------------------------------------
//	Copyright (c) 2001-2002, OpenBeOS
//
//	Permission is hereby granted, free of charge, to any person obtaining a
//	copy of this software and associated documentation files (the "Software"),
//	to deal in the Software without restriction, including without limitation
//	the rights to use, copy, modify, merge, publish, distribute, sublicense,
//	and/or sell copies of the Software, and to permit persons to whom the
//	Software is furnished to do so, subject to the following conditions:
//
//	The above copyright notice and this permission notice shall be included in
//	all copies or substantial portions of the Software.
//
//	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
//	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
//	DEALINGS IN THE SOFTWARE.
//
//	File Name:		Workspace.cpp
//	Author:			Adi Oanca <adioanca@myrealbox.com>
//	Description:	Tracks workspaces
//  
//------------------------------------------------------------------------------
#include <stdio.h>
#include <Window.h>

#include "Workspace.h"
#include "Layer.h"
#include "WinBorder.h"
#include "ServerWindow.h"
#include "ServerApp.h"
#include "RGBColor.h"
#include "Globals.h"
#include "FMWList.h"
#include "RootLayer.h"
#include "Desktop.h"

//#define DEBUG_WORKSPACE

#ifdef DEBUG_WORKSPACE
#	include <stdio.h>
#	define STRACE(x) printf x
#else
#	define STRACE(x) ;
#endif

#ifdef DEBUG_WORKSPACE
#	include <stdio.h>
#	define STRACESTREAM() PrintToStream()
#else
#	define STRACESTREAM() ;
#endif


Workspace::Workspace(const uint32 colorspace, int32 ID, const RGBColor& BGColor, RootLayer* owner){
	fID			= ID;
	fSpace		= colorspace;
	fBGColor	= BGColor;

	fOwner		= owner;
	
	fBottomItem	= NULL;
	fTopItem	= NULL;
	fCurrentItem= NULL;
	fFocusItem	= NULL;
	fFrontItem	= NULL;
}
//---------------------------------------------------------------------------
Workspace::~Workspace(){
//printf("~Workspace( %ld )\n", fID);
	ListData		*toast;
	while(fBottomItem){
		toast		= fBottomItem;
		fBottomItem	= fBottomItem->upperItem;
		
		delete toast;
	}
	fBottomItem		= NULL;
	fTopItem		= NULL;
	fCurrentItem	= NULL;
	fFocusItem		= NULL;
	fFrontItem		= NULL;
}
//---------------------------------------------------------------------------
/* Adds layer ptr to workspace's list of WinBorders. After the item is added
 *	a *smart* search is performed to set the new front WinBorder. Of course,
 *	the first candidate is 'layer', but if it is hidden or it has the
 *	B_AVOID_FRONT flag, surely it won't get that status.
 * This method also calls SearchAndSetNewFocus witch searches for a WinBorder,
 *	to give focus to, having as preferred 'layer'.
 * Remember, some windows having B_AVOID_FOCUS can't have the focus state.
 */
bool Workspace::AddLayerPtr(WinBorder* layer){
		// allocate a new item
	ListData		*item;
	item			= new ListData;
	
	item->layerPtr	= layer;
	item->upperItem	= NULL;
	item->lowerItem	= NULL;

	opLock.Lock();
		// insert 'item' at the end. It doesn't matter where we add it,
		// it will be placed correctly by SearchAndSetNewFront(item->layerPtr);
	InsertItem(item, NULL);
	opLock.Unlock();

STRACE(("\n*AddLayerPtr(%s) -", layer->GetName()));

		// this may happen in case of subset windows.
	if(!(layer->IsHidden())){
			// do a *smart* search and set the new 'front'
		SearchAndSetNewFront(layer);
			// do a *smart* search and set the new 'focus' + a redraw
		SetFocusLayer(layer);
	}
	
	return true;
}
/* Removes a WinBorder from workspace's list. It DOES NOT delete it!
 * If this window was the front/focus one it calls SearchAndSetNew(Front/Focus)
 *	to give the respective state to the window below her.
 */
//---------------------------------------------------------------------------
bool Workspace::RemoveLayerPtr(WinBorder* layer){
	if (!layer)
		return false;
STRACE(("\n*Workspace(%ld)::RemoveLayerPtr(%s)\n", ID(), layer->GetName()));
STRACE(("BEFORE ANY opperation:\n"));
STRACESTREAM();
		// search to see if this workspace has WinBorder's pointer in its list
	ListData	*item = NULL;

	opLock.Lock();
	if ((item = HasItem(layer))){
		ListData	*nextItem	= NULL;
		bool		wasFront	= false;
		bool		wasFocus	= false;
		
		wasFront	= FrontLayer() == layer;
		wasFocus	= FocusLayer() == layer;

			// prepare to set new front/focus if this layer was front/focus
		nextItem	= item->upperItem;

		if (wasFront)
			SearchAndSetNewFront(nextItem? nextItem->layerPtr: NULL);

			// remove some windows.
		if (item && item->layerPtr->_level == B_NORMAL_FEEL)
		{
			ListData	*listItem = item->lowerItem;
			while(listItem && (listItem->layerPtr->_level == B_FLOATING_SUBSET_FEEL
								|| listItem->layerPtr->_level == B_FLOATING_APP_FEEL
								|| listItem->layerPtr->_level == B_MODAL_SUBSET_FEEL))
			{
					// *carefuly* remove the item from the list
				ListData	*itemX = listItem;
				listItem	= listItem->lowerItem;
				RemoveItem(itemX);
				delete itemX;
			}
		}
		
		RemoveItem(item);
		delete item;
		STRACESTREAM();		
		opLock.Unlock();

			// reset some internal variables
		layer->SetMainWinBorder(NULL);
		// its RootLayer is set to NULL by Layer::RemoveChild(layer);

		STRACE(("Layer %s found and removed from Workspace No %ld\n", layer->GetName(), ID()));

		if (wasFocus)
			SetFocusLayer(nextItem? nextItem->layerPtr: NULL);
		else
			Invalidate();

		return true;
	}
	else{
		STRACE(("Layer %s NOT found in Workspace No %ld\n", layer->GetName(), ID()));
		opLock.Unlock();
		return false;
	}
}
//---------------------------------------------------------------------------
bool Workspace::HideSubsetWindows(WinBorder* layer){
	if (!layer)
		return false;

		// search to see if this workspace has WinBorder's pointer in its list
	ListData	*item = NULL;

	opLock.Lock();
	if ((item = HasItem(layer))){
		ListData	*nextItem = NULL;

			// prepare to set new front/focus if this layer was front/focus
		nextItem	= item->upperItem;

		SearchAndSetNewFront(nextItem? nextItem->layerPtr: NULL);
			// we don't care bout focus in this method!!!
		//SearchAndSetNewFocus(nextItem? nextItem->layerPtr: NULL);

			// remove some windows.
		if (item && item->layerPtr->_level == B_NORMAL_FEEL)
		{
			ListData	*listItem = item->lowerItem;
			while(listItem && (listItem->layerPtr->_level == B_FLOATING_SUBSET_FEEL
								|| listItem->layerPtr->_level == B_FLOATING_APP_FEEL
								|| listItem->layerPtr->_level == B_MODAL_SUBSET_FEEL))
			{
					// *carefuly* remove the item from the list
				ListData	*itemX = listItem;
				listItem	= listItem->lowerItem;
				RemoveItem(itemX);
				delete itemX;
			}
		}
		
		opLock.Unlock();

		return true;
	}
	else{
		opLock.Unlock();
		return false;
	}
}
//---------------------------------------------------------------------------
WinBorder* Workspace::SetFocusLayer(WinBorder* layer){
STRACE(("\n@Workspace(%ld)::SetFOCUSLayer( %s )\n", ID(), layer? layer->GetName(): "NULL"));

	if(!(desktop->fGeneralLock.IsLocked()))
		debugger("Workspace::SetFocusLayer - desktop->fGeneralLock must be LOCKED!\n");

	WinBorder		*previousFocus = FocusLayer();

	SearchAndSetNewFocus(layer);

	if (previousFocus != FocusLayer()){
		if (previousFocus)
			previousFocus->SetFocus(false);

		if (FocusLayer()){
			FocusLayer()->SetFocus(true);
		}

// TODO: there had to be a Invalidate() vresion witch takes a BRegion parameter
STRACESTREAM();
		Invalidate();
	}
	else{
		// Do nothing!
	}

STRACE(("\n#Workspace(%ld)::SetFOCUSLayer( %s ) ENDED\n", ID(), layer? layer->GetName(): "NULL"));

	return FocusLayer();
}
//---------------------------------------------------------------------------
WinBorder* Workspace::FocusLayer() const{
	return fFocusItem ? fFocusItem->layerPtr : NULL;
}
//---------------------------------------------------------------------------
WinBorder* Workspace::SetFrontLayer(WinBorder* layer){
STRACE(("\n@Workspace(%ld)::SetFrontLayer( %s )\n", ID(), layer? layer->GetName(): "NULL"));

	if(!(desktop->fGeneralLock.IsLocked()))
		debugger("Workspace::SetFRONTLayer - desktop->fGeneralLock must be LOCKED!\n");

	SearchAndSetNewFront(layer);
STRACESTREAM();
// TODO: there had to be a Invalidate() vresion witch takes a BRegion parameter
	Invalidate();

 	return fFrontItem? fFrontItem->layerPtr: NULL;;
}
//---------------------------------------------------------------------------
WinBorder* Workspace::FrontLayer() const{
	return fFrontItem? fFrontItem->layerPtr: NULL;
}
//---------------------------------------------------------------------------
WinBorder* Workspace::GoToBottomItem(){
	fCurrentItem	= fBottomItem;
	return fCurrentItem ? fCurrentItem->layerPtr : NULL;
}
//---------------------------------------------------------------------------
WinBorder* Workspace::GoToUpperItem(){
	if (fCurrentItem){
		fCurrentItem	= fCurrentItem->upperItem;
		return fCurrentItem ? fCurrentItem->layerPtr : NULL;
	}
	else
		return NULL;
}
//---------------------------------------------------------------------------
WinBorder* Workspace::GoToTopItem(){
	fCurrentItem	= fTopItem;
	return fCurrentItem ? fCurrentItem->layerPtr : NULL;
}
//---------------------------------------------------------------------------
WinBorder* Workspace::GoToLowerItem(){
	if (fCurrentItem){
		fCurrentItem	= fCurrentItem->lowerItem;
		return fCurrentItem ? fCurrentItem->layerPtr : NULL;
	}
	else
		return NULL;
}
//---------------------------------------------------------------------------
bool Workspace::GoToItem(WinBorder* layer){
	if (!layer)
		return false;

	if (fCurrentItem && fCurrentItem->layerPtr == layer){
		return true;
	}
	
	for( ListData *item = fBottomItem; item != NULL; item = item->upperItem){
		if (item->layerPtr == layer){
			fCurrentItem	= item;
			return true;
		}
	}
	return false;
}
//---------------------------------------------------------------------------
WinBorder* Workspace::SearchLayerUnderPoint(BPoint pt){
// TODO: implement correctly one you have clipping code working
// For the moment, take windows from front to back and see in witch one 'pt' falls
	WinBorder		*target = NULL;
	opLock.Lock();
	STRACE(("Searching (%f,%f) in...\n", pt.x, pt.y));
	for( WinBorder *wb = GoToBottomItem(); wb; wb = GoToUpperItem()){
//		wb->PrintToStream();
		if (!wb->IsHidden() && wb->HasPoint(pt)){
			STRACE(("%s - SELECTED!\n", wb->GetName()));
			target	= wb;
			break;
		}
	}
	opLock.Unlock();
	return target;
}
//---------------------------------------------------------------------------
void Workspace::Invalidate(){
//TODO: *****!*!*!*!*!*!*!**!***REMOVE this! For Test purposes only!
	opLock.Lock();
	if(fOwner->ActiveWorkspace() == this)
		fOwner->DoInvalidate(BRegion(fOwner->Bounds()), NULL);
	opLock.Unlock();
//----------------
}
//---------------------------------------------------------------------------
void Workspace::InsertItem(ListData* item, ListData* before){
		// insert before one other item;
	if (before){
		if (before->upperItem)
			before->upperItem->lowerItem	= item;
		item->upperItem		= before->upperItem;
		before->upperItem	= item;
		item->lowerItem		= before;

			// if we're inserting at top of the stack, change it accordingly.
		if(fTopItem == before)
			fTopItem = item;
	}
		// insert item at bottom.
	else{
		item->upperItem	= fBottomItem;
		if (fBottomItem)
			fBottomItem->lowerItem	= item;

		fBottomItem		= item;

		if (!fTopItem)
			fTopItem	= item;
	}
}
//---------------------------------------------------------------------------
void Workspace::RemoveItem(ListData* item){
	if (!item)
		return;

	if (fBottomItem == item){
		fBottomItem = item->upperItem;
	}
	else{
		item->lowerItem->upperItem	= item->upperItem;
	}
	if (fTopItem == item){
		fTopItem = item->lowerItem;
	}
	else{
		item->upperItem->lowerItem	= item->lowerItem;
	}

		// set all these to NULL to avoid confusion later.

	item->upperItem	= NULL;
	item->lowerItem	= NULL;
	
	if (fFocusItem == item){
		fFocusItem->layerPtr->SetFocus(false);
		fFocusItem = NULL;
	}
	if (fFrontItem == item)
		fFrontItem = NULL;
	if (fCurrentItem == item)
		fCurrentItem = NULL;
}
//---------------------------------------------------------------------------
ListData* Workspace::HasItem(ListData* item){
	for (ListData *itemX = fBottomItem; itemX != NULL; itemX = itemX->upperItem){
		if (item == itemX){
			return itemX;
		}
	}
	return NULL;
}
//---------------------------------------------------------------------------
ListData* Workspace::HasItem(WinBorder* layer){
	for (ListData *item = fBottomItem; item != NULL; item = item->upperItem){
		if (item->layerPtr == layer){
			return item;
		}
	}
	return NULL;
}
/* This, also is a "smart" method. Firstly this funtionality was in
 *	SearchAndSetNewFront, but I've split it for reasons of clarity. Anyway,
 *	what is to be noticed is that those 2 methods work hand-in-hand.
 * What FindPlace() litelaly does, is *place* the 'pref' item into its
 *	>right< place! If 'pref->layerPtr'(the WinBorder in ListData structure)
 *	does not meet some conditions a search for another, valid, WinBorder is
 *	being made.
 *
 * NOTE: Do NOT be confussed! This method places the preferred window *ONLY*!
 *	Other windows that need to be placed before it, *WILL* be placed by almost
 *	all code found in SearchAndSetNewFront
 */
//---------------------------------------------------------------------------
ListData* Workspace::FindPlace(ListData* pref){
		// if we received a NULL value, we stil have to give 'front' state to some window...
	if (!pref)
		pref	= HasItem(fBottomItem);
	else
		pref	= HasItem(pref);

	ListData	*item = NULL;

		// search a window that is not hidden and does *not* have B_AVOID_FRONT flag.
	item		= pref;
	while(pref && item->lowerItem != pref && (pref->upperItem || pref->lowerItem)){
		if ( !(item->layerPtr->Window()->Flags() & B_AVOID_FRONT) && !(item->layerPtr->IsHidden()) )
			break;
		STRACE(("item: %s - pref: %s\n", item->layerPtr->GetName(), pref->layerPtr->GetName()));
		if (item == fTopItem)
			item = fBottomItem;
		else
			item = item->upperItem;
	}

		// if true, it means we have windows with B_AVOID_FRONT flag *only*,
		// or they are all hidden. Pick one, if you can.
	if (pref && item->lowerItem == pref){
		for (item = fBottomItem; item; item = item->upperItem){
			if ( !(item->layerPtr->IsHidden()) )
				break;
		}
	}

		// if the search took place or not...
	pref = item;

		// we have exhausted all possibilities to make pref a vaid pointer... so... exit now.
	if (!pref)
		return NULL;

		// temporally remove 'pref' to reinsert it later in the *right* place
	RemoveItem(pref);

		// we start searching its place
	ListData		*cursor	= fBottomItem;
	int32			feel	= pref->layerPtr->Window()->Feel();
	
	switch(feel){
		case B_NORMAL_WINDOW_FEEL:{
			while(cursor &&	cursor->layerPtr->_level > B_MODAL_APP_FEEL){
				cursor	= cursor->upperItem;
			}
			InsertItem(pref, cursor? cursor->lowerItem: NULL);
			break;
		}
		
		case B_SYSTEM_LAST:{
			while(cursor &&	cursor->layerPtr->_level > pref->layerPtr->_level){
				cursor	= cursor->upperItem;
			}
			InsertItem(pref, cursor? cursor->lowerItem: fTopItem);
			break;
		}
		
		case B_SYSTEM_FIRST:
		case B_FLOATING_ALL_WINDOW_FEEL:
		case B_MODAL_ALL_WINDOW_FEEL:
		case B_MODAL_APP_WINDOW_FEEL:{
			while(cursor &&	cursor->layerPtr->_level > pref->layerPtr->_level){
				cursor	= cursor->upperItem;
			}
			InsertItem(pref, cursor? cursor->lowerItem: NULL);
			break;
		}

			// place in front of: its main window, other subset windows and in front
			// of other application's floating windows.
			// NOTE that this happens only if its main window is the front most one.
		case B_FLOATING_SUBSET_WINDOW_FEEL:{
			for(cursor = fBottomItem; cursor; cursor = cursor->upperItem){
				if (cursor->layerPtr->_level <= pref->layerPtr->_level
					&& (cursor->layerPtr == pref->layerPtr->MainWinBorder()
						|| cursor->layerPtr->MainWinBorder() == pref->layerPtr->MainWinBorder())
					)
				{ break; }
				else if(pref->layerPtr->_level == B_FLOATING_SUBSET_FEEL
						&& cursor->layerPtr->_level == B_FLOATING_APP_FEEL)
				{ break; }
			}
			if (cursor)
				InsertItem(pref, cursor? cursor->lowerItem: NULL);
			break;
		}

			// place this SUBSET_MODAL behind APP_MODAL ones if they belong
			// to the same application OR, in front of all MODAL/NORMAL if
			// it belongs to another application
		case B_MODAL_SUBSET_WINDOW_FEEL:{
			for(cursor = fBottomItem; cursor; cursor = cursor->upperItem){
				if (cursor->layerPtr->_level <= pref->layerPtr->_level)
					break;
				else if(pref->layerPtr->_level == B_MODAL_SUBSET_FEEL
					&& cursor->layerPtr->_level == B_MODAL_APP_FEEL
					&& pref->layerPtr->Window()->ClientTeamID()
						!=  cursor->layerPtr->Window()->ClientTeamID())
					break;
			}
			if (cursor)
				InsertItem(pref, cursor? cursor->lowerItem: NULL);
			break;
		}

			// place in front of: its main window, other floating windows
			// NOTE that this happens only if its main window is the front most one.
		case B_FLOATING_APP_WINDOW_FEEL:{
			for(cursor = fBottomItem; cursor; cursor = cursor->upperItem){
				if (cursor->layerPtr->_level <= pref->layerPtr->_level
					&& pref->layerPtr->Window()->ClientTeamID() ==
						cursor->layerPtr->Window()->ClientTeamID())
				{ break; }
			}

			if (cursor)
				InsertItem(pref, cursor? cursor->lowerItem: NULL);
			break;
		}
	}
	
	return pref;
}
/* This method is the key to correct window arangement!!!
 * With the help of FindPlace it correctly aranges windows. FindPlace, only
 *	inserted the window in the correct place, this method also brings all
 *	other windows that are supposed to be in front of her - I'm talking here
 *	about floating and modal windows.
 * It also clerverly selects the new FINAL front window.
 */
//---------------------------------------------------------------------------
void Workspace::SearchAndSetNewFront(WinBorder* preferred){
STRACE(("*WS(%ld)::SASNF(%s)\n", ID(), preferred? preferred->GetName(): "NULL"));
opLock.Lock();
		// the new front must not be the same as the previous one.
	if (fFrontItem && fFrontItem->layerPtr == preferred && !(preferred->IsHidden())){
STRACE(("-WS(%ld)::SASNF(%s) - opperation not needed! Workspace data:",
		ID(), preferred? preferred->GetName(): "NULL"));
STRACESTREAM();
STRACE(("#WS(%ld)::SASNF(%s) ENDED 1\n", ID(), preferred? preferred->GetName(): "NULL"));
		opLock.Unlock();
		return;
	}

		// properly place this 'preferred' WinBorder.
	ListData		*lastInserted;
	lastInserted	= FindPlace(HasItem(preferred));
	preferred		= lastInserted? lastInserted->layerPtr: NULL;
STRACE(("-WS(%ld)::SASNF(%s) - after FindPlace...", ID(), preferred? preferred->GetName(): "NULL"));
STRACESTREAM();

		// if the new front layer is the same... there is no point continuing
	if(fFrontItem == lastInserted){
STRACE(("-WS(%ld)::SASNF(%s) - new front layer is the same as the old one. Stop!", ID(), preferred? preferred->GetName(): "NULL"));
STRACESTREAM();
STRACE(("#WS(%ld)::SASNF(%s) ENDED 2\n", ID(), preferred? preferred->GetName(): "NULL"));
		opLock.Unlock();
		return;
	}

if(!lastInserted){
	STRACE(("PAAAAANIC: Workspace::SASNF(): 'lastInserted' IS NULL\n"));	
}
else{
	STRACE(("\n&&&&Processing for: %s\n", lastInserted->layerPtr->GetName()));
}

	if (lastInserted && !(lastInserted->layerPtr->IsHidden())){
		int32		prefFeel = preferred->Window()->Feel();

		if (prefFeel == B_NORMAL_WINDOW_FEEL){
STRACE((" NORMAL Window '%s' -", preferred? preferred->GetName(): "NULL"));
			if (fFrontItem){
				// if they are in the same team...
			if (preferred->Window()->ClientTeamID() == fFrontItem->layerPtr->Window()->ClientTeamID()){
STRACE((" SAME TeamID\n"));
					// collect subset windows that are common to application's windows...
					// NOTE: A subset window *can* be added to more than just one window.
				FMWList	commonFMW;
				FMWList	appFMW;
				FMWList	finalFMWList;
				int32	count, i;
					// collect floating and modal windows spread across the workspace only if
					// they are in our window's subset
					// * also remove them, for repositioning, later.
				ListData	*listItem = fTopItem;
				while(listItem){
					int32	feel = listItem->layerPtr->Window()->Feel();
					if (feel == B_FLOATING_SUBSET_WINDOW_FEEL || feel == B_MODAL_SUBSET_WINDOW_FEEL){
						if(preferred->Window()->fWinFMWList.HasItem(listItem->layerPtr)){
							commonFMW.AddItem(listItem->layerPtr);
								// *carefully* remove the item from the list
							ListData	*item = listItem;
							listItem	= listItem->lowerItem;
							RemoveItem(item);
						}
							// also remove floating windows. Those, SURELY belong to
							// 'fFrontItem' - this being the *old* front window.
						else if (feel == B_FLOATING_SUBSET_WINDOW_FEEL){
								// *carefully* remove the item from the list
							ListData	*item = listItem;
							listItem	= listItem->lowerItem;
							RemoveItem(item);
						}
						else{
							listItem	= listItem->lowerItem;
						}
					}
						// ALSO collect application's floating and modal windows,
						// for reinsertion, later.
					else if (feel == B_FLOATING_APP_WINDOW_FEEL || feel == B_MODAL_APP_WINDOW_FEEL){
						if(listItem->layerPtr->Window()->ClientTeamID() ==
							preferred->Window()->ClientTeamID())
						{
							appFMW.AddItem(listItem->layerPtr);
								// *carefully* remove the item from the list
							ListData	*item = listItem;
							listItem	= listItem->lowerItem;
							RemoveItem(item);
						}
						else
							listItem	= listItem->lowerItem;
					}
					else
						listItem	= listItem->lowerItem;
				}

					// put in the final list, items that are not found in the common list
				count	= preferred->Window()->fWinFMWList.CountItems();
				for (i=0; i<count; i++){
					void	*item = preferred->Window()->fWinFMWList.ItemAt(i);
					if (commonFMW.HasItem(item)){
					}
					else
						finalFMWList.AddItem(item);
				}

					// colapse the 2 lists
				finalFMWList.AddFMWList(&commonFMW);
				finalFMWList.AddFMWList(&appFMW);

					// insert windows found in 'finalFMWList' in Workspace's list.
					// IF *one* modal is found, do not add floating ones!
					
					// see if the last WinBorder in the list is a modal window.
					// OR if the last one in Workspace's list is a modal window...
				WinBorder	*wb = (WinBorder*)finalFMWList.LastItem();
				bool		lastIsModal = false;
				if (	(wb &&
						(wb->Window()->Feel() == B_MODAL_SUBSET_WINDOW_FEEL
							|| wb->Window()->Feel() == B_MODAL_APP_WINDOW_FEEL))
					||	(fBottomItem &&
						(fBottomItem->layerPtr->Window()->Feel() == B_MODAL_ALL_WINDOW_FEEL
							|| fBottomItem->layerPtr->Window()->Feel() == B_SYSTEM_FIRST))
					)
					{ lastIsModal = true; }

					// this variable will help us in deciding the new front WinBorder.
				WinBorder		*finalPreferred = preferred;
					// now insert items found in finalFMWList into Workspace
				count	= finalFMWList.CountItems();
				for(i=0; i<count; i++){
					WinBorder			*wb = (WinBorder*)finalFMWList.ItemAt(i);
					if(wb->Window()->Feel() == B_FLOATING_SUBSET_WINDOW_FEEL
							|| wb->Window()->Feel() == B_FLOATING_APP_WINDOW_FEEL)
					{
							// set its new MainWinBorder
						if(wb->Window()->Feel() == B_FLOATING_SUBSET_WINDOW_FEEL)
							wb->SetMainWinBorder(preferred);
							// don't add if the last WinBorder is a modal one.
						if (lastIsModal)
							continue;
					}
					else{
						if(wb->Window()->Feel() == B_MODAL_SUBSET_WINDOW_FEEL)
							wb->SetMainWinBorder(preferred);
							// if this modal window is not hidden, give it the front status.
						if (!(wb->IsHidden()))
							finalPreferred		= wb;
					}

						// insert item just after the last inserted one.
					ListData			*newItem = new ListData();
					newItem->layerPtr	= wb;
					newItem->lowerItem	= lastInserted->lowerItem;
					newItem->upperItem	= lastInserted;
					if (lastInserted->lowerItem)
						lastInserted->lowerItem->upperItem	= newItem;
					lastInserted->lowerItem		= newItem;
					
					if(lastInserted == fBottomItem)
						fBottomItem = newItem;

					lastInserted		= newItem;
				}
				preferred		= finalPreferred;
			}
			else{
STRACE((" DIFERRENT TeamID\n"));
					// remove front window's floating(_SUBSET_/_APP_) windows, if any.
				ListData	*listItem = fFrontItem->lowerItem;
				while(listItem && (listItem->layerPtr->_level == B_FLOATING_SUBSET_FEEL
									|| listItem->layerPtr->_level == B_FLOATING_APP_FEEL))
				{		// *carefully* remove the item from the list
					ListData	*item = listItem;
					listItem	= listItem->lowerItem;
					RemoveItem(item);
				}
					// now, jump to et1: to make a 'clean' selecting of
					// windows to be inserted
				fFrontItem = NULL;
				goto et1;
			} // END: else - if diferrent ClientTeamID()s.
			} // if (fFrontItem) && NORMAL_WINDOW
			else{
STRACE((" NO previous FRONT Item\n"));
				et1:
				FMWList		finalFMWList;
				int32		count, i;
				ListData	*listItem = fTopItem;
					// remove window's subset and application's *modal* windows spread
					// across Workspace's list, to be insert later, in the corect order.
				while(listItem){
					int32		feel = listItem->layerPtr->Window()->Feel();
					if ((feel == B_MODAL_SUBSET_WINDOW_FEEL
							&& preferred->Window()->fWinFMWList.HasItem(listItem->layerPtr))
						|| (feel == B_MODAL_APP_WINDOW_FEEL
							&& preferred->Window()->ClientTeamID() ==
								listItem->layerPtr->Window()->ClientTeamID()
							))
					{
							// *carefully* remove the item from the list
						ListData	*item = listItem;
						listItem	= listItem->lowerItem;
						RemoveItem(item);
					}
					else
						listItem	= listItem->lowerItem;
				}
					// add to the final list window's subset windows. (..._SUBSET_...)
				finalFMWList.AddFMWList(&(preferred->Window()->fWinFMWList));
					// also add application's ones. (..._APP_...)
				finalFMWList.AddFMWList(&(preferred->Window()->App()->fAppFMWList));
					// insert windows found in 'finalFMWList' in Workspace's list.
					// IF *one* modal is found, do not add floating ones!
					
					// see if the last WinBorder in the list is a modal window.
				WinBorder	*wb = (WinBorder*)finalFMWList.LastItem();
				bool		lastIsModal = false;
				if (	(wb &&
						(wb->Window()->Feel() == B_MODAL_SUBSET_WINDOW_FEEL
							|| wb->Window()->Feel() == B_MODAL_APP_WINDOW_FEEL))
					||	(fBottomItem &&
						(fBottomItem->layerPtr->Window()->Feel() == B_MODAL_ALL_WINDOW_FEEL
							|| fBottomItem->layerPtr->Window()->Feel() == B_SYSTEM_FIRST))
					)
					{ lastIsModal = true; }

					// this variable will help us in deciding the new front WinBorder.
				WinBorder		*finalPreferred = preferred;
					// now insert items found in finalFMWList into Workspace
				count	= finalFMWList.CountItems();
				for(i=0; i<count; i++){
					WinBorder			*wb = (WinBorder*)finalFMWList.ItemAt(i);
						// do not insert floating windows if the last is a modal one.
					if(wb->Window()->Feel() == B_FLOATING_SUBSET_WINDOW_FEEL
							|| wb->Window()->Feel() == B_FLOATING_APP_WINDOW_FEEL)
					{
							// set its new MainWinBorder
						if(wb->Window()->Feel() == B_FLOATING_SUBSET_WINDOW_FEEL)
							wb->SetMainWinBorder(preferred);
							// don't add if the last WinBorder is a modal one.
						if (lastIsModal)
							continue;
					}
					else{
						if(wb->Window()->Feel() == B_MODAL_SUBSET_WINDOW_FEEL)
							wb->SetMainWinBorder(preferred);
							// if this modal window is not hidden, give it the front status.
						if (!(wb->IsHidden()))
							finalPreferred		= wb;
					}
						// insert item just after the last inserted one.
					ListData			*newItem = new ListData();
					newItem->layerPtr	= wb;
					newItem->lowerItem	= lastInserted->lowerItem;
					newItem->upperItem	= lastInserted;
					if (lastInserted->lowerItem)
						lastInserted->lowerItem->upperItem	= newItem;
					lastInserted->lowerItem		= newItem;
					
					if(lastInserted == fBottomItem)
						fBottomItem = newItem;

					lastInserted		= newItem;
				}
				preferred		= finalPreferred;
			} // else - if(fFrontItem);
		} // END: if _NORMAL_ window.
		else if(	prefFeel == B_FLOATING_SUBSET_WINDOW_FEEL
				 || prefFeel == B_FLOATING_APP_WINDOW_FEEL
				 || prefFeel == B_FLOATING_ALL_WINDOW_FEEL)
		{
STRACE((" FLOATING Window '%s'\n", preferred? preferred->GetName(): "NULL"));
			// Do nothing! FindPlace() was called and it has corectly placed our window
			// We don't have to do noting here.
		}
		else if(	prefFeel == B_MODAL_SUBSET_WINDOW_FEEL
				 || prefFeel == B_MODAL_APP_WINDOW_FEEL)
		{
STRACE((" MODAL_APP/SUBSET Window '%s'\n", preferred? preferred->GetName(): "NULL"));
			FMWList		finalMWList;
			int32		count = 0, i;
			int32		prefIndex = -1;

			if (fFrontItem && fFrontItem->layerPtr->_level == B_NORMAL_FEEL)
			{
					// remove front window's floating(_SUBSET_/_APP_) windows, if any.
				ListData	*listItem = fFrontItem->lowerItem;
				while(listItem && (listItem->layerPtr->_level == B_FLOATING_SUBSET_FEEL
									|| listItem->layerPtr->_level == B_FLOATING_APP_FEEL))
				{		// *carefully* remove the item from the list
					ListData	*item = listItem;
					listItem	= listItem->lowerItem;
					RemoveItem(item);
				}
			}

				// If this is a MODAL_SUBSET window, search it's place in its MainWinBorder
				//	window subset, and then take all modals after it; then continue talking
				//	modal windoes *only*, from application's set.
				// If it is a MODAL_APP only search an take windows in/from application's set
			if (prefFeel == B_MODAL_SUBSET_WINDOW_FEEL){
				prefIndex	= preferred->MainWinBorder()->Window()->fWinFMWList.IndexOf(preferred);
				count		= preferred->MainWinBorder()->Window()->fWinFMWList.CountItems();
				if (prefIndex >= 0){
					WinBorder	*wb = NULL;
						// add modal windows from its main window subset - windows that are
						// positioned after 'preferred'.
					FMWList		*listPtr = &(preferred->MainWinBorder()->Window()->fWinFMWList);
					for(i = prefIndex+1; i < count; i++){
							// they *all* are modal windows.
						wb		= (WinBorder*)listPtr->ItemAt(i);
						wb->SetMainWinBorder(preferred);
						finalMWList.AddItem(wb);
							// remove those windows(if in there), for correct re-insertion later.
						ListData	*ld = NULL;
						if((ld = HasItem(wb)))
							RemoveItem(ld);
					}
						// add modal windows that are found in application's subset
					count	= preferred->Window()->App()->fAppFMWList.CountItems();
					listPtr	= &(preferred->Window()->App()->fAppFMWList);
					for(i = 0; i < count; i++){
						wb		= (WinBorder*)listPtr->ItemAt(i);
						if (wb->Window()->Feel() == B_MODAL_APP_WINDOW_FEEL){
							finalMWList.AddItem(wb);
								// remove those windows(if in there), for correct re-insertion later.
							ListData	*ld = NULL;
							if((ld = HasItem(wb)))
								RemoveItem(ld);
						}
					}
				}
			}
			else if(prefFeel == B_MODAL_APP_WINDOW_FEEL){
				prefIndex	= preferred->Window()->App()->fAppFMWList.IndexOf(preferred);
				count		= preferred->Window()->App()->fAppFMWList.CountItems();
				if (prefIndex >= 0){
					WinBorder	*wb = NULL;
						// add modal windows from application's subset - windows that are
						// positioned after 'preferred'.
					FMWList		*listPtr = &(preferred->Window()->App()->fAppFMWList);
					for(i = prefIndex+1; i < count; i++){
						wb		= (WinBorder*)listPtr->ItemAt(i);
							// they *all* are modal windows.
						finalMWList.AddItem(wb);
								// remove those windows(if in there), for correct re-insertion later.
						ListData	*ld = NULL;
						if((ld = HasItem(wb)))
							RemoveItem(ld);
					}
				}
			}
		
				// insert windows found in 'finalMWList' in Workspace's list, after "preferred"
			count		= finalMWList.CountItems();
				// this varable will help us designate the future front.
			WinBorder	*finalPreferred = preferred;
			for(i=0; i<count; i++){
				WinBorder			*wb = (WinBorder*)finalMWList.ItemAt(i);
					// wb is surely a modal so... ATM make it the front one.
				if(!(wb->IsHidden()))
					finalPreferred	= wb;

					// insert item just after the last inserted one.
				ListData			*newItem = new ListData();
				newItem->layerPtr	= wb;
				newItem->lowerItem	= lastInserted->lowerItem;
				newItem->upperItem	= lastInserted;
				if (lastInserted->lowerItem)
					lastInserted->lowerItem->upperItem	= newItem;
				lastInserted->lowerItem		= newItem;
				
				if(lastInserted == fBottomItem){
					fBottomItem = newItem;
				}

				lastInserted		= newItem;
			}
			preferred = finalPreferred;
		}
		else if(prefFeel == B_MODAL_ALL_WINDOW_FEEL
				|| prefFeel == B_SYSTEM_FIRST)
		{
STRACE((" MODAL ALL/SYSTEM FIRST Window '%s'\n", preferred? preferred->GetName(): "NULL"));
				// remove all application's floating windows.
			if (fFrontItem && fFrontItem->layerPtr->_level == B_NORMAL_FEEL)
			{
				ListData	*listItem = fFrontItem->lowerItem;
				while(listItem &&
						(listItem->layerPtr->_level == B_FLOATING_SUBSET_FEEL
						|| listItem->layerPtr->_level == B_FLOATING_APP_FEEL))
				{
						// *carefully* remove the item from the list
					ListData	*item = listItem;
					listItem		= listItem->lowerItem;
					RemoveItem(item);
				}
			}
		}
		else if(prefFeel == B_SYSTEM_LAST){
			; // Do Nothing.
		}
		else{
			// We ***should NOT*** reach this point!
			STRACE(("SERVER: PANIC: \"%s\": What kind of window is this???\n", preferred? preferred->GetName(): "NULL"));
		}
	}
	else
		STRACE((" The window IS Hidden\n"));

	ListData	*exFrontItem	= fFrontItem;
	ListData	*newFrontItem	= NULL;
	if(preferred && fBottomItem){
		int32		feel = fBottomItem->layerPtr->Window()->Feel();

			// if preferred is one of these *don't* give front state to it!
		if(preferred->_level == B_FLOATING_SUBSET_FEEL
			|| preferred->_level == B_FLOATING_APP_FEEL
			|| preferred->_level == B_FLOATING_ALL_FEEL)
		{
			newFrontItem	= exFrontItem;
		}
			// if the last in workspace's list is one of these, GIVE focus to it!
		else if((feel == B_SYSTEM_FIRST || feel == B_MODAL_ALL_WINDOW_FEEL)
				&& !(fBottomItem->layerPtr->IsHidden()) )
		{
			newFrontItem	= fBottomItem;
		}
			// the SYSTEM_LAST will get the front status, only if it's the only
			// WinBorder in this workspace.
		else if (preferred->_level == B_SYSTEM_LAST
				 && !(preferred->IsHidden()) )
		{
			if(fBottomItem->layerPtr == preferred)
				newFrontItem	= HasItem(preferred);
		}
			// this is in case of MODAL[APP/SUBSET] and NORMAL windows
		else if ( !(preferred->IsHidden()) ){
			newFrontItem	= HasItem(preferred);
		}
		else{
			newFrontItem	= NULL;
		}
	}
	else{ newFrontItem	= NULL; }
	
	if (fFrontItem != newFrontItem){
		fFrontItem = newFrontItem;
// TODO: call a method like... WinBorder::MakeFront(true);
	}
opLock.Unlock();
STRACE(("#WS(%ld)::SASNF(%s) ENDED! Workspace data...", ID(), preferred? preferred->GetName(): "NULL"));
STRACESTREAM();
}
/* This method performs a simple opperation. It searched the new focus window
 *	by walking from front to back, cheking for some things, until all variables
 *	correspond.
 */
//---------------------------------------------------------------------------
void Workspace::SearchAndSetNewFocus(WinBorder* preferred){
STRACE(("*WS(%ld)::SASNFocus(%s)\n", ID(), preferred? preferred->GetName(): "NULL"));
	opLock.Lock();

	if(!preferred)
		preferred	= fBottomItem? fBottomItem->layerPtr : NULL;

	bool		selectOthers = false;
	ListData	*item = NULL;

	for(item = fBottomItem; item != NULL; item = item->upperItem){
			// if this WinBorder doesn't want to have focus... get to the next one
		if (item->layerPtr->Window()->Flags() & B_AVOID_FOCUS)
			continue;

		if (preferred && item->layerPtr == preferred){
				// our preffered one is hidden so... select another one
			if (preferred && preferred->IsHidden()){
				selectOthers = true;
				continue;
			}
			else{
				break;
			}
		}

		if (item->layerPtr->_level == B_SYSTEM_FIRST || item->layerPtr->_level == B_MODAL_ALL_FEEL)
		{
			break;
		}

		if (item->layerPtr->_level == B_MODAL_APP_FEEL
			 && (preferred && preferred->Window()->ClientTeamID() == item->layerPtr->Window()->ClientTeamID()))
		{
			break;
		}

		if (item->layerPtr->_level == B_MODAL_SUBSET_FEEL
			&& (preferred && item->layerPtr->MainWinBorder() == preferred))
		{
			break;
		}

			// select one window, other than a system_last one!
		if (selectOthers && item->layerPtr->_level != B_SYSTEM_LAST){
			break;
		}
	}

		// there are no windows below us to select. take the one from above us.
	if(selectOthers && !item){
			// there HAS to be valid
		item 	= HasItem(preferred);
		if (item)
			item= item->lowerItem;
	}

		// there are NO windows in front of us, and no regular window below us
		// maybe there is a system_last window...
	if(!item){
		item = fTopItem;
	}
	
	if (item != fFocusItem){
		// TODO: item->ColorTabInGrey & send message to client
		// TODO: item->ColorTabInYellow & send message to client
		// TODO: Rebuild & Redraw.
		fFocusItem		= item;
	}
	
	opLock.Unlock();
}
//---------------------------------------------------------------------------
void Workspace::BringToFrontANormalWindow(WinBorder* layer){
	switch (layer->Window()->Feel()){
		case B_FLOATING_SUBSET_WINDOW_FEEL:
		case B_MODAL_SUBSET_WINDOW_FEEL:{
			SearchAndSetNewFront(layer->MainWinBorder());
			break;
		}
		case B_FLOATING_APP_WINDOW_FEEL:
		case B_MODAL_APP_WINDOW_FEEL:{
			opLock.Lock();
			ListData	*item	= fBottomItem;
			team_id		tid		= layer->Window()->ClientTeamID();
			while(item){
				if(item->layerPtr->Window()->ClientTeamID() == tid
					&& item->layerPtr->Window()->Feel() == B_NORMAL_WINDOW_FEEL)
				{
					break;
				}
				item	= item->upperItem;
			}
			if(item){
				SearchAndSetNewFront(item->layerPtr);
			}
			opLock.Unlock();
			break;
		}
		default:{
			// in case of MODAL/FLOATING_ALL or _NORMAL_ or SYSTEM_FIRST/LAST do nothing!
		}
	}
}
/* The method moves a window to the back of its subset.
 */
//---------------------------------------------------------------------------
void Workspace::MoveToBack(WinBorder* newLast){
STRACE(("\n!MoveToBack(%s) -", newLast? newLast->GetName(): "NULL"));
		// does the list have this element?
	ListData	*item = HasItem(newLast);
	if(item){
		ListData	*listItem = NULL;

		switch(item->layerPtr->_level){
			case B_FLOATING_ALL_FEEL:{
STRACE((" B_FLOATING_ALL_FEEL window\n"));
					// search the place where we should insert it later
				listItem		= item->upperItem;
				while(listItem && (listItem->layerPtr->_level == item->layerPtr->_level))
					listItem = listItem->upperItem;

				break;
			}

				// those 2 flags form a 'virtual' set, so even if FLOATING_APP
				// has a greater priority than FLOATING_SUBSET, it is still moved
				// behind FLOATING_SUBSET.
			case B_FLOATING_SUBSET_FEEL:
			case B_FLOATING_APP_FEEL:{
STRACE((" B_FLOATING_SUBSET_FEEL/B_FLOATING_APP_FEEL window\n"));
					// search the place where we should insert it later
				listItem		= item->upperItem;
				while(listItem &&
						(listItem->layerPtr->_level == B_FLOATING_SUBSET_FEEL
						|| listItem->layerPtr->_level == B_FLOATING_APP_FEEL))
					listItem = listItem->upperItem;

				break;
			}

				// the same like with floating window. Those 2 and NORMAL form a'virtual' set.
			case B_MODAL_SUBSET_FEEL:
			case B_MODAL_APP_FEEL:{
STRACE((" B_MODAL_SUBSET_FEEL/B_MODAL_APP_FEEL window\n"));
					// search the place where we should insert it later
				listItem		= item->upperItem;
				while(listItem &&
						(listItem->layerPtr->_level == B_MODAL_SUBSET_FEEL
						|| listItem->layerPtr->_level == B_MODAL_APP_FEEL
						|| listItem->layerPtr->_level == B_NORMAL_FEEL))
					listItem = listItem->upperItem;

				break;
			}

				// here is the simplest, we use the priority levels.
			case B_NORMAL_FEEL:{
STRACE((" B_NORMAL_FEEL window\n"));
				listItem		= item->upperItem;
				while(listItem && (listItem->layerPtr->_level >= item->layerPtr->_level)){
					listItem = listItem->upperItem;
				}
												
				break;
			}
		}
		
		if ((listItem && item->lowerItem == listItem->lowerItem)
			|| (listItem == NULL && item == fTopItem))
		{
			// do nothing! The window will be in the same position it is now.
		}
		else{
				// if it's a normal window, first remove any floating windows,
				// it or its application has
			if(newLast->_level == B_NORMAL_FEEL && fFrontItem->layerPtr == newLast){
				ListData	*iter = item->lowerItem;
				while(iter &&
						(iter->layerPtr->_level == B_FLOATING_SUBSET_FEEL
						|| iter->layerPtr->_level == B_FLOATING_APP_FEEL))
				{
						// *carefully* remove the item from the list
					ListData	*itemX = iter;
					iter		= iter->lowerItem;
					RemoveItem(itemX);
				}

			}

			WinBorder	*nextPreferred = item->upperItem? item->upperItem->layerPtr: NULL;
			bool		wasFront = fFrontItem->layerPtr == newLast;
			bool		wasFocus = fFocusItem->layerPtr == newLast;
				// remove item
			RemoveItem(item);
				// insert in the new, right' position.
			InsertItem(item, listItem? listItem->lowerItem: fTopItem);

			if (wasFront)
				SearchAndSetNewFront(nextPreferred);
			if (wasFocus)
				SearchAndSetNewFocus(nextPreferred);
		}
STRACESTREAM();
	}
	else
		STRACE((" this operation was not needed\n"));
}
//---------------------------------------------------------------------------
void Workspace::SetLocalSpace(const uint32 colorspace){
	fSpace		= colorspace;
}
//---------------------------------------------------------------------------
uint32 Workspace::LocalSpace() const{
	return fSpace;
}
//---------------------------------------------------------------------------
void Workspace::SetBGColor(const RGBColor &c){
	fBGColor	= c;
}
//---------------------------------------------------------------------------
RGBColor Workspace::BGColor(void) const{
	return fBGColor;
}
//---------------------------------------------------------------------------
// Debug methods!!!
//---------------------------------------------------------------------------
void Workspace::PrintToStream() const{
	printf("\nWorkspace %ld hierarchy shown from back to front:\n", fID);
	for (ListData *item = fTopItem; item != NULL; item = item->lowerItem){
		WinBorder		*wb = (WinBorder*)item->layerPtr;
		printf("\tName: %s\t%s", wb->GetName(), wb->IsHidden()?"Hidden\t": "NOT Hidden");
		if (wb->Window()->Feel() == B_FLOATING_SUBSET_WINDOW_FEEL)
			printf("\t%s\n", "B_FLOATING_SUBSET_WINDOW_FEEL");
		if (wb->Window()->Feel() == B_FLOATING_APP_WINDOW_FEEL)
			printf("\t%s\n", "B_FLOATING_APP_WINDOW_FEEL");
		if (wb->Window()->Feel() == B_FLOATING_ALL_WINDOW_FEEL)
			printf("\t%s\n", "B_FLOATING_ALL_WINDOW_FEEL");
		if (wb->Window()->Feel() == B_MODAL_SUBSET_WINDOW_FEEL)
			printf("\t%s\n", "B_MODAL_SUBSET_WINDOW_FEEL");
		if (wb->Window()->Feel() == B_MODAL_APP_WINDOW_FEEL)
			printf("\t%s\n", "B_MODAL_APP_WINDOW_FEEL");
		if (wb->Window()->Feel() == B_MODAL_ALL_WINDOW_FEEL)
			printf("\t%s\n", "B_MODAL_ALL_WINDOW_FEEL");
		if (wb->Window()->Feel() == B_NORMAL_WINDOW_FEEL)
			printf("\t%s\n", "B_NORMAL_WINDOW_FEEL");
		if (wb->Window()->Feel() == B_SYSTEM_LAST)
			printf("\t%s\n", "B_SYSTEM_LAST");
		if (wb->Window()->Feel() == B_SYSTEM_FIRST)
			printf("\t%s\n", "B_SYSTEM_FIRST");
	}
	printf("Focus Layer:\t%s\n", fFocusItem? fFocusItem->layerPtr->GetName(): "NULL");
	printf("Front Layer:\t%s\n", fFrontItem? fFrontItem->layerPtr->GetName(): "NULL");
//	printf("Current Layer:\t%s\n", fCurrentItem? fCurrentItem->layerPtr->GetName(): "NULL");
//	printf("Top Layer:\t%s\n", fTopItem? fTopItem->layerPtr->GetName(): "NULL");
//	printf("Bottom Layer:\t%s\n", fBottomItem? fBottomItem->layerPtr->GetName(): "NULL");
}
//---------------------------------------------------------------------------
void Workspace::PrintItem(ListData *item) const{
	printf("ListData members:\n");
	if (item){
		printf("WinBorder:\t%s\n", item->layerPtr? item->layerPtr->GetName(): "NULL");
		printf("UpperItem:\t%s\n", item->upperItem? item->upperItem->layerPtr->GetName(): "NULL");
		printf("LowerItem:\t%s\n", item->lowerItem? item->lowerItem->layerPtr->GetName(): "NULL");
	}
	else{
		printf("NULL item!!!\n");
	}
}
