/* Copyright (c) 2017, Computer History Museum 
All rights reserved. 
Redistribution and use in source and binary forms, with or without modification, are permitted (subject to 
the limitations in the disclaimer below) provided that the following conditions are met: 
 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 
 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following 
   disclaimer in the documentation and/or other materials provided with the distribution. 
 * Neither the name of Computer History Museum nor the names of its contributors may be used to endorse or promote products 
   derived from this software without specific prior written permission. 
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE 
COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 
DAMAGE. */

#include "mbdrawer.h"
#include "listview.h"

#define FILE_NUM 143
/* Copyright (c) 2002-2003 by QUALCOMM Incorporated */


#if TARGET_RT_MAC_CFM
//	constants
enum {
  kEventWindowDrawerOpening     = 220,
  kEventWindowDrawerOpened      = 221,
  kEventWindowDrawerClosing     = 222,
  kEventWindowDrawerClosed      = 223
};

// These items aren't in the carbon headers yet
typedef UInt32 WindowDrawerState;
enum { kWindowDrawerOpening = 1, kWindowDrawerOpen = 2, kWindowDrawerClosing = 3, kWindowDrawerClosed = 4 }; 
WindowDrawerState GetDrawerState(WindowRef inDrawerWindow);
#endif


//	structs
typedef struct
{
	ViewListPtr	list;					// mailboxes list
	ExpandInfo	expandList;
	MyWindowPtr	parentWin;
	TOCHandle	tocH;
	ControlRef  listCtl;
	Boolean	hasFocus;
} MBDrawerVars, **MBDrawerHandle;

//	functions
static MBDrawerHandle GetMBDrawerInfo(MyWindowPtr win);
static void MBDrawerClick(MyWindowPtr win,EventRecord *event);
static void MBDrawerDidResize(MyWindowPtr win, Rect *oldContR);
static void MBDrawerGetListRect(WindowRef win,Rect *r);
static Boolean MBDrawerKey(MyWindowPtr win, EventRecord *event);
static long MBDrawerLVCallBack(ViewListPtr pView, VLCallbackMessage message, long data);
static void MBDrawerUpdate(MyWindowPtr win);
static OSErr MBDrawerDragHandler(MyWindowPtr win,DragTrackingMessage which,DragReference drag);
static OSStatus ControlEvents(EventHandlerCallRef inHandlerCallRef, EventRef theEvent, void *userData);
static OSStatus ListControlEvents(EventHandlerCallRef nextHandler, EventRef theEvent, void *userData);
static void OpenMyDrawer(MyWindowPtr winDrawer);
static void SetDrawerIcon(MyWindowPtr winParent,Boolean open);
void MBDrawerSetState(MyWindowPtr winParent,Boolean open);

//	globals

/************************************************************************
 * MBDrawerOpen - open a mailbox drawer
 ************************************************************************/
MyWindowPtr MBDrawerOpen(MyWindowPtr winParent)
{
	TOCHandle	tocH = (TOCHandle)GetMyWindowPrivateData(winParent);
	WindowRef	winWP,winParentWP;
	MyWindowPtr	win;
	OSErr		err;
	CGrafPtr	winPort;
	Rect		r;
	GrafPtr		oldPort;
	MBDrawerVars	vars;
	Handle		hMBDrawerInfo=nil;
	short width = GetPrefLong(PREF_DRAWER_WIDTH);
	EventTypeSpec ctlEventList[] = 
	{ 
		{kEventClassControl, kEventControlHitTest} 
	};
	EventTypeSpec listCtlEventList[] = 
	{ 
		{kEventClassControl, kEventControlDraw}
	};
	DECLARE_UPP(ControlEvents,EventHandler);
	DECLARE_UPP(ListControlEvents,EventHandler);

	INIT_UPP(ControlEvents,EventHandler);
	INIT_UPP(ListControlEvents,EventHandler);

	 
	if (!MBDrawerSupported(winParent))
		// Drawers aren't supported
		return NULL;
	
	UseFeature(featureMBDrawer);

	Zero(vars);
	vars.parentWin = winParent;
	vars.tocH = tocH;
	win = GetNewMyWindowWithClass(0,nil,nil,BehindModal,False,False,DRAWER_WIN,kDrawerWindowClass);
	if (!win)
		{err=MemError(); goto fail;}
		
	winWP = GetMyWindowWindowPtr(win);
	winParentWP = GetMyWindowWindowPtr(winParent);
	SetDrawerParent(winWP,winParentWP);

	SetThemeWindowBackground(winWP,kThemeBrushDrawerBackground,false);

	ConfigFontSetup(win);	
	win->hPitch = FontWidth;
	win->vPitch = FontLead+FontDescent;
	
	// Add mailboxes
	vars.list=NuPtr(sizeof(ViewList));
	vars.expandList.resID = kMBDrawerExpandID;	
	if (err = PtrToHand(&vars,&hMBDrawerInfo,sizeof(vars))) goto fail;
	SetMyWindowPrivateData(win,(long)hMBDrawerInfo);

	// Set size
	if (!width)
		width = kDefaultMBDrawerWidth;
	GetWindowBounds(winParentWP,kWindowContentRgn,&r);
	SizeWindow(winWP,width,r.bottom-r.top,false);
			
	if (vars.list)
	{
	   ControlRef vScroll;

		winPort = GetMyWindowCGrafPtr(win);
		GetPort(&oldPort);
		SetPort_(winPort);
		SetRect(&r,0,0,1,1);
		LVNew(vars.list,win,&r,0,MBDrawerLVCallBack,0);
		SetListFlags(vars.list->hList,lOnlyOne);	// Don't support multiple selection
		SetPort_(oldPort);
	   vScroll = (*vars.list->hList)->vScroll;
		InstallControlEventHandler (vScroll, ControlEventsUPP, GetEventTypeCount(ctlEventList), ctlEventList, vScroll, NULL); 	
   	if (vars.listCtl = NewControl (winWP, &r, "\p", true, kControlSupportsEmbedding, 0, 0, kControlUserPaneProc, NULL))
      	InstallControlEventHandler (vars.listCtl, ListControlEventsUPP, GetEventTypeCount(listCtlEventList), listCtlEventList, win, NULL); 	
	}
		
	win->close = MBDrawerClose;
	win->update = MBDrawerUpdate;
	win->click = MBDrawerClick;
	win->bgClick = MBDrawerClick;
	win->didResize = MBDrawerDidResize;
	win->key = MBDrawerKey;
	win->drag = MBDrawerDragHandler;

/*
	win->position = MBDrawerPosition;
	win->help = MBDrawerHelp;
	win->menu = MBDrawerMenuSelect;
	win->app1 = MBDrawerApp1;
	win->button = MBDrawerButton;
	win->scroll = MBDrawerScroll;
	win->selection = MBDrawerHasSelection;
	win->cursor = MBDrawerCursor;
	win->idle = MBDrawerIdle;
	win->dontControl = true;
	win->zoomSize = MaxSizeZoom;
	win->find = MBDrawerFind;
	win->activate = MBDrawerActivate;
*/
	win->isActive = true;
	win->dontActivate = true;
	
	if (tocH)
		(*tocH)->drawerWin = win;

	// Open drawer
	MBDrawerSetState(winParent,true);
	LVActivate(vars.list, true);
	MBDrawerDidResize(win, nil);
	MBDrawerUpdate(win);

fail:
	return win;
}


/************************************************************************
 * MBDrawerToggle - toggle mailbox widow drawer
 ************************************************************************/
void MBDrawerToggle(MyWindowPtr winParent)
{
	TOCHandle	tocH;

	if (!winParent)
		return;

	tocH = (TOCHandle)GetMyWindowPrivateData(winParent);

	MBDrawerSetState(winParent,!(*tocH)->drawer);
}

/************************************************************************
 * MBDrawerSetState - set state of drawer (open or closed)
 ************************************************************************/
void MBDrawerSetState(MyWindowPtr winParent,Boolean open)
{
	TOCHandle	tocH;
	WindowPtr drawerWP = NULL;

	if (!winParent)
		return;

	tocH = (TOCHandle)GetMyWindowPrivateData(winParent);

	if ((*tocH)->drawerWin)
		drawerWP = GetMyWindowWindowPtr((*tocH)->drawerWin);

	if (open)
	{
		// Open drawer
		if (drawerWP)
		{
			// Already have drawer. Toggle it open
			OpenMyDrawer((*tocH)->drawerWin);
			MBDrawerUpdate((*tocH)->drawerWin);
		}
		else
			// Create drawer
			MBDrawerOpen(winParent);

		if ((*tocH)->drawerWin)
			(*tocH)->drawer = true;
	}
	else
	{
		// Close drawer
		if (drawerWP)
			CloseDrawer(drawerWP,true);
		(*tocH)->drawer = false;
		SetDrawerIcon(winParent,false);
	}
	TOCSetDirty(tocH,true);
}

/**********************************************************************
 * SetDrawerIcon - set state of drawer button icon
 **********************************************************************/
static void SetDrawerIcon(MyWindowPtr winParent,Boolean open)
{
	ControlRef cntl = FindControlByRefCon(winParent,kDrawerSwitch);

	if (cntl)
		SetControlValue(cntl,open ? 1 : 0);
}

/**********************************************************************
 * GetSearchInfo - get search info from window
 **********************************************************************/
static MBDrawerHandle GetMBDrawerInfo(MyWindowPtr win)
{
	return (MBDrawerHandle)GetMyWindowPrivateData(win);
}

/**********************************************************************
 * MBDrawerClose - close this drawer window. Called only if parent is closing
 **********************************************************************/
Boolean MBDrawerClose(MyWindowPtr win)
{
	MBDrawerHandle	dh = GetMBDrawerInfo(win);

	SaveExpandedFolderList(&(*dh)->expandList);	

	if ((*dh)->list)
	{
		LVDispose((*dh)->list);
		ZapPtr((*dh)->list);
	}
	
	ASSERT((*dh)->tocH);
	if ((*dh)->tocH) (*(*dh)->tocH)->drawerWin = nil;
	
	ZapHandle(dh);

	return true;
}

/**********************************************************************
 * MBDrawerUpdate - update drawer window
 **********************************************************************/
static void MBDrawerUpdate(MyWindowPtr win)
{
	MBDrawerHandle	dh = GetMBDrawerInfo(win);
	
	SetPort(GetMyWindowCGrafPtr(win));
	SetOrigin(0,0);
	LVDraw((*dh)->list,nil,true,false);
}

/**********************************************************************
 * MBDrawerClick - handle click in drawer window
 **********************************************************************/
static void MBDrawerClick(MyWindowPtr win,EventRecord *event)
{
	MBDrawerHandle	dh = GetMBDrawerInfo(win);

	if (dh)
	{
		// Make sure mailbox window is active
		if (!(*dh)->parentWin->isActive) SelectWindow_(GetMyWindowWindowPtr((*dh)->parentWin));
		
		// Make sure focus is set
		MBDrawerSetFocus(win, true);
		BoxListFocus((*dh)->tocH,false);
		
		LVClick((*dh)->list,event);
	}
}

/************************************************************************
 * MBDrawerLVCallBack - callback function for List View
 ************************************************************************/
static long MBDrawerLVCallBack(ViewListPtr pView, VLCallbackMessage message, long data)
{
	VLNodeInfo	*pInfo;
	OSErr	err = noErr;
	MBDrawerHandle	dh = GetMBDrawerInfo(pView->wPtr);
	VLNodeInfo info;
	FSSpec spec;
	DEC_STATE(dh);
	
	switch (message)
	{
		case kLVAddNodeItems:
		case kLVExpandCollapseItem:
			L_STATE(dh);
			if (message==kLVAddNodeItems)
				AddMailboxListItems(pView,data,&(*dh)->expandList);
			else
				SaveExpandStatus((VLNodeInfo *)data,&(*dh)->expandList);
			U_STATE(dh);
			break;

		case kLVGetParentID:
			err = MailboxesLVCallBack(pView, message, data);
			break;
		
		case kLVOpenItem:
			//MBListOpen((*dh)->list);
			break;

		case kLVQueryItem:
			pInfo = (VLNodeInfo*)data;
			switch (pInfo->query)
			{
				case kQueryDrop:
					return !pInfo->isParent;
				case kQuerySelect:
				case kQueryDragExpand:
					return true;
				case kQueryDrag:
				case kQueryRename:
				case kQueryDropParent:
					return false;
				default:
					err = MailboxesLVCallBack(pView, message, data);
			}
			break;
		
		case kLVGetFlags:
			return kfSupportsSelectCallbacks+kfSingleSelection;
		
		case kLVSelectItem:
			if (LVGetItem(pView,1,&info,true))
			{	
				if (!info.isParent || info.iconID == IMAP_MAILBOX_FILE_ICON || (info.iconID == kTrashIconResource && IsIMAPBox(&info)))
				{
					// Switch to this mailbox
					MyWindowPtr boxWin = (*dh)->parentWin;
					MyWindowPtr hideWin = NULL;
					TOCHandle	oldToc,newToc;
					ControlRef  cntl;
					short       i;
					Rect			oldContR;
					PETEHandle	pteTemp;
					Boolean     saveNoUpdates;
					Boolean		oldHasTab, newHasTab;
					
					MakeMBSpec(&info,&spec);
					// if this is an IMAP folder we're going to open, adjust the spec so it points to the mailbox inside
					if (IsIMAPCacheFolder(&spec)) spec.parID = SpecDirId(&spec);
					
					oldToc = (TOCHandle)GetMyWindowPrivateData(boxWin);
					if (newToc = FindTOC(&spec))
					{
						if (newToc == oldToc)
							return noErr;	// Selected the one we already have!						
						hideWin = (*newToc)->win;
						HideWindow_(GetMyWindowWindowPtr(hideWin));
					}
					else
					{
						// Need to open this mailbox without showing
						if (GetMailbox(&spec,false))
							return noErr;	// value is going to be ignored here - bail
						newToc = FindTOC(&spec);
						if (!newToc)
							return noErr;	// value is going to be ignored here - bail
						hideWin = (*newToc)->win;
					}
					
					if ((*oldToc)->fileView)
						// Fileview needs to be turned off before swapping. It messes
						// with a lot of controls.				
						SetFileView(boxWin,oldToc,false);
					
					// Let's not do any drawing until we've completely transitioned the window
					saveNoUpdates = boxWin->noUpdates;
					boxWin->noUpdates = true;
					SetEmptyClipRgn(GetMyWindowCGrafPtr(boxWin));
					
					// Setup swapped window data for both windows
					InitMailboxWin(boxWin, newToc, true);
					InitMailboxWin(hideWin, oldToc, false);
					
					// Swap preview ptes
					pteTemp = (*newToc)->previewPTE;
					(*newToc)->previewPTE = (*oldToc)->previewPTE;
					(*oldToc)->previewPTE = pteTemp;
					
					// Cleanup some plugin stuff
	        		for (i=1;cntl = FindControlByRefCon(boxWin,'plug'+i);i++)
	      		   DisposeControl(cntl);	// Cleanup peanut buttons
					FVRemoveButtons(boxWin);	// Cleanup any fileview buttons
					
					cntl=FindControlByRefCon(boxWin,'tabs');
					oldHasTab = cntl != nil;
					newHasTab = ETLHasMBoxContextFolder(boxWin);
					if (oldHasTab != newHasTab)
					{
						if (oldHasTab)
		      			DisposeControl(cntl);	// Remove fileview tab
		      		else
		      		{
		      			// We will be adding a tab control
		      			// Need to remove existing header buttons so they are
		      			// added after the tab control
							for (i=1;i<BoxLinesLimit;i++)
								if (cntl = FindControlByRefCon(boxWin,'wide'+i))
									DisposeControl(cntl);
							// Drawer switch, too
							cntl = FindControlByRefCon(boxWin,kDrawerSwitch);
							if (cntl)
								DisposeControl(cntl);		      			
		      		}
		      	}				

					// If new one already has a drawer, close it.
					if ((*newToc)->drawerWin)
						MBDrawerClose((*newToc)->drawerWin);
					
					// Use this drawer
					(*newToc)->drawerWin = (*oldToc)->drawerWin;
					(*oldToc)->drawerWin = NULL;
					
					// Keep same preview height
					(*newToc)->previewHi = (*oldToc)->previewHi;
					
					// Make sure this TOC has drawer flag set
					 if (!(*newToc)->drawer)
					 {
					 	(*newToc)->drawer = true;
						TOCSetDirty(newToc,true);
					 }

					(*dh)->tocH = newToc;
					MyWindowMaxes(boxWin,boxWin->hMax,(*newToc)->count);
					
					// Update preview pane
					(*newToc)->previewID = -1;

					BoxGonnaShow(boxWin);
					oldContR = boxWin->contR;
					BoxSetBevelButtonValues(boxWin);	//	 Update bevel button (sort) values
					MyWindowDidResize(boxWin,&oldContR);

               // Now draw the entire window at once
					boxWin->noUpdates = saveNoUpdates;
					InfiniteClip(GetMyWindowCGrafPtr(boxWin));
	            InvalWindowRect(GetMyWindowWindowPtr(boxWin),&boxWin->contR);
					UpdateMyWindow(GetMyWindowWindowPtr(boxWin));

					// listFocus is changed by BoxGonnaShow. Need to set it here.
					BoxListFocus(newToc,false);
					
					// Close old (hidden) mailbox window
					CloseMyWindow(GetMyWindowWindowPtr(hideWin));
					
					// If IMAP, resync
					if ((*newToc)->imapTOC)
						FlagForResync(newToc);					
				}
			}
			break;
	}
	return err;
}

/**********************************************************************
 * MBDrawerGetListRect - get list bounds
 **********************************************************************/
static void MBDrawerGetListRect(WindowRef winWP,Rect *r)
{
	GetWindowBounds(winWP,kWindowContentRgn,r);
	OffsetRect(r,-r->left,-r->top);
	r->bottom -= 5;
}

/**********************************************************************
 * MBDrawerSupported - are drawers supported
 **********************************************************************/
Boolean MBDrawerSupported(MyWindowPtr win)
{
	// Drawers require Jaguar (Mac OS 10.2)
	if (GetOSVersion() >= 0x1002)
		// Don't put drawers on search windows
		if (!IsSearchWindow(GetMyWindowWindowPtr(win)))
			// gotta have the feature
			if (HasFeature(featureMBDrawer))
				return true;
	return false;
}

/************************************************************************
 * MBDrawerDidResize - resize the MB window
 ************************************************************************/
static void MBDrawerDidResize(MyWindowPtr win, Rect *oldContR)
{
#pragma unused(oldContR)
	MBDrawerHandle	dh = GetMBDrawerInfo(win);
	short	htAdjustment;
	WindowRef winWP = GetMyWindowWindowPtr(win);
   Rect	r;
   Boolean drawerOpen = GetDrawerState(winWP) != kWindowDrawerClosed;

	// set list bounds
	MBDrawerGetListRect(winWP,&r);
	LVSize((*dh)->list,&r,&htAdjustment);

	// save drawer width preference
	GetWindowBounds(winWP,kWindowContentRgn,&r);
	SetPrefLong(PREF_DRAWER_WIDTH,RectWi(r));
	
	InvalContent(win);
	
	if (drawerOpen != (*(*dh)->tocH)->drawer)
		// User has changed state by resizing
		MBDrawerSetState((*dh)->parentWin,drawerOpen);
}

/************************************************************************
 * MBDrawerKey - key stroke
 ************************************************************************/
static Boolean MBDrawerKey(MyWindowPtr win, EventRecord *event)
{
	MBDrawerHandle	dh = GetMBDrawerInfo(win);

	if (dh)
		return LVKey((*dh)->list,event);
	return false;
}

/**********************************************************************
 * MBDrawerActivate - perform processing for activate/deactivate
 **********************************************************************/
void MBDrawerActivate(MyWindowPtr win, Boolean activate)
{
	MBDrawerHandle	dh = GetMBDrawerInfo(win);

	if (dh)
		LVActivate((*dh)->list, (*dh)->hasFocus && activate);
}

/**********************************************************************
 * MBDrawerSetFocus - set focus
 **********************************************************************/
void MBDrawerSetFocus(MyWindowPtr win, Boolean focus)
{
	MBDrawerHandle	dh = GetMBDrawerInfo(win);

	if (dh)
	{
		if (focus != (*dh)->hasFocus)
		{
			(*dh)->hasFocus = focus;
			LVActivate((*dh)->list, focus);
		}
	}
}

/************************************************************************
 * MBDrawerFixUnread - update mailbox list unread status
 ************************************************************************/
void MBDrawerFixUnread(MenuHandle mh,short item,Boolean unread)
{
	MBDrawerHandle	dh;	
	TOCHandle	tocH;

	//	Find mailbox drawers
	for (tocH=TOCList; tocH; tocH = (*tocH)->next)
	{
		if ((*tocH)->drawerWin)
		if (dh = GetMBDrawerInfo((*tocH)->drawerWin))
			MBFixUnreadLo((*dh)->list,mh,item,unread,true);
	}
}

/************************************************************************
 * MBDrawerReload - mailbox list has changed, reload
 ************************************************************************/
void MBDrawerReload(void)
{
	MBDrawerHandle	dh;	
	TOCHandle	tocH;

	//	Find mailbox drawers
	for (tocH=TOCList; tocH; tocH = (*tocH)->next)
	{
		if ((*tocH)->drawerWin)
		if (dh = GetMBDrawerInfo((*tocH)->drawerWin))
			InvalidListView((*dh)->list);
	}
}



/**********************************************************************
 * MBDrawerDragHandler - handle drags
 *
 *  Supports only dropping of messages
 **********************************************************************/
static OSErr MBDrawerDragHandler(MyWindowPtr win,DragTrackingMessage which,DragReference drag)
{	
	MBDrawerHandle	dh = GetMBDrawerInfo(win);
	OSErr err = noErr;
	VLNodeInfo targetInfo;
	
	if (!dh)
		return noErr;

	if (!DragIsInteresting(drag,MESS_FLAVOR,TOC_FLAVOR,nil))	//	Dragging messages
		return(dragNotAcceptedErr);	//	Nothing here we want

	switch (which)
	{
		case kDragTrackingEnterWindow:
		case kDragTrackingLeaveWindow:
		case kDragTrackingInWindow:
				err = LVDrag((*dh)->list,which,drag);
			break;
		case 0xfff:
			//	Message drag
			if (LVDrop((*dh)->list,&targetInfo))
					err = MBDragMessages(drag, &targetInfo);
			else
				return dragNotAcceptedErr;			
			break;
	}
	return err;
}

/************************************************************************
 * ControlEvents - handle carbon control events
 ************************************************************************/
static OSStatus ControlEvents(EventHandlerCallRef nextHandler, EventRef theEvent, void *userData)
{
	ControlRef vScroll = (ControlRef)userData;
	Rect	rScroll;
	Point pt,topleft;
		
	switch (GetEventKind(theEvent))
	{
		case kEventControlHitTest:
			// Fix bug in List Manager
			GetControlBounds(vScroll,&rScroll);
			GetEventParameter(theEvent,kEventParamMouseLocation,typeQDPoint,NULL,sizeof(Point),NULL,&pt);
			if (PtInRect(pt,&rScroll))
			{
				SetPt(&topleft,rScroll.left,rScroll.top);
				SubPt(topleft,&pt);
				SetEventParameter(theEvent,kEventParamMouseLocation,typeQDPoint,sizeof(Point),&pt);			
			}
  			break;
	}
	return CallNextEventHandler (nextHandler, theEvent);
}

/************************************************************************
 * ListControlEvents - handle carbon control events for list control
 ************************************************************************/
static OSStatus ListControlEvents(EventHandlerCallRef nextHandler, EventRef theEvent, void *userData)
{
   static Boolean drawing;
	MyWindowPtr win = (ControlRef)userData;
	MBDrawerHandle	dh = GetMBDrawerInfo(win);
		
	switch (GetEventKind(theEvent))
	{
		case kEventControlDraw:
         // Time to draw mailbox list
         if (drawing)
            //  Avoid recursion
            break;      	
      	drawing = true;
      	LVDraw((*dh)->list,nil,true,false);
      	drawing = false;
		   break;
	}
	return CallNextEventHandler (nextHandler, theEvent);
}

/************************************************************************
 * OpenMyDrawer - open drawer watching out for toolbar
 ************************************************************************/
static void OpenMyDrawer(MyWindowPtr winDrawer)
{
   OptionBits inEdge;
   Rect	rDrawer;
   short width;
	MBDrawerHandle	dh = GetMBDrawerInfo(winDrawer);

   switch (GetPrefLong(PREF_DRAWER_EDGE))
   {
      case 1:
         inEdge = MainEvent.modifiers & optionKey ? kWindowEdgeRight : kWindowEdgeLeft;
         break;
      case 2:
         inEdge = MainEvent.modifiers & optionKey ? kWindowEdgeLeft : kWindowEdgeRight;
         break;
      default:
         // Make sure there is room on the left without going under toolbar
         width = GetPrefLong(PREF_DRAWER_WIDTH);
         if (!width)
            width = kDefaultMBDrawerWidth;
         GetContentRgnBounds(GetMyWindowWindowPtr((*dh)->parentWin),&rDrawer);
         rDrawer.right = rDrawer.left;
         rDrawer.left -= width;

         if (ToolbarSect(&rDrawer))
            inEdge = kWindowEdgeRight;
         else
            inEdge = kWindowEdgeDefault;				
      break;
   }
   OpenDrawer(GetMyWindowWindowPtr(winDrawer),inEdge,true);
	SetDrawerIcon((*dh)->parentWin,true);
}
