// statbar.cpp : definition of old backward compatible CStatusBar
//
// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) 1992-1995 Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.

#include "stdafx.h"
#define _AFX_NO_OLE_SUPPORT
#include <afxpriv.h>
#include "statbar.h"
#include "globals.h"
#ifdef _MAC
#include <macname1.h>
#include <Types.h>
#include <QuickDraw.h>
#include <Fonts.h>
#include <macos\Windows.h>
#include <GestaltEqu.h>
#include <Script.h>
#include <macname2.h>
#endif
#include <algorithm>

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#define new DEBUG_NEW

/////////////////////////////////////////////////////////////////////////////
// CStatusBar creation etc

struct AFX_STATUSPANE
{
	UINT    nID;        // IDC of indicator: 0 => normal text area
	UINT    nStyle;     // style flags (SBPS_*)
	int     cxText;     // width of string area in pixels
						//   on both sides there is a 1 pixel gap and
						//    a one pixel border, making a pane 4 pixels wider
	LPCTSTR  lpszText;  // text in the pane
};

inline AFX_STATUSPANE* CStatusBar::_GetPanePtr(int nIndex) const
{
	ASSERT(nIndex >= 0 && nIndex < m_nCount);
	ASSERT(m_pData != NULL);
	return ((AFX_STATUSPANE*)m_pData) + nIndex;
}

#ifdef AFX_INIT_SEG
#pragma code_seg(AFX_INIT_SEG)
#endif

CStatusBar::CStatusBar()
{
	m_hFont = NULL;

	// setup correct margins
	m_cxRightBorder = m_cxDefaultGap;
	m_cxSizeBox = 0;
	m_bHideSizeBox = FALSE;
	if (globalData.bWin4)
	{
		m_cxLeftBorder = 4;
		m_cyTopBorder = 2;
		m_cyBottomBorder = 0;
		m_cxRightBorder = 0;
	}

	if (globalData.hStatusFont == NULL)
	{
#ifndef _MAC
		// load status bar font
		CClientDC dc(NULL);
		LOGFONT logfont;
		memset(&logfont, 0, sizeof(logfont));
		logfont.lfWeight = FW_NORMAL;
		logfont.lfHeight = -MulDiv(globalData.bWin4 ? 8 : 10, 
			globalData.cyPixelsPerInch, 72);
		lstrcpy(logfont.lfFaceName, _T("MS Sans Serif"));
		BOOL bCustom = AfxCustomLogFont(AFX_IDS_STATUS_FONT, &logfont);
		if (bCustom || !GetSystemMetrics(SM_DBCSENABLED))
		{
			// only set pitch & family if not a custom font
			if (!bCustom)
				logfont.lfPitchAndFamily = VARIABLE_PITCH | FF_SWISS;
			// 10 point height Sans Serif font (8 point for Win4)
			globalData.hStatusFont = ::CreateFontIndirect(&logfont);
		}
#else
		LONG nFondAndSize;
		nFondAndSize = GetScriptVariable(smSystemScript, smScriptHelpFondSize);

		LOGFONT logfont;
		memset(&logfont, 0, sizeof(logfont));
		logfont.lfWeight = FW_NORMAL;
		logfont.lfPitchAndFamily = VARIABLE_PITCH | FF_SWISS;
		logfont.lfHeight = -MulDiv(LOWORD(nFondAndSize), globalData.cyPixelsPerInch, 72);
		GetFontName(HIWORD(nFondAndSize), (StringPtr) logfont.lfFaceName);
		p2cstr((StringPtr) logfont.lfFaceName);
		globalData.hStatusFont = ::CreateFontIndirect(&logfont);
#endif
		if (globalData.hStatusFont == NULL)
		{
			if (!GetSystemMetrics(SM_DBCSENABLED))
				TRACE0("Warning: Using system font for status font.\n");
			globalData.hStatusFont = (HFONT)::GetStockObject(SYSTEM_FONT);
		}
	}
}

void CStatusBar::OnWinIniChange(LPCTSTR /*lpszSection*/)
{
	if (globalData.bWin4)
	{
		// get the drawing area for the status bar 
		CRect rect;
		GetClientRect(rect);
		CalcInsideRect(rect, TRUE);

		// the size box is based off the size of a scrollbar
		m_cxSizeBox = std::min(GetSystemMetrics(SM_CXVSCROLL)+1, rect.Height());
	}
}

CStatusBar::~CStatusBar()
{
	// free strings before freeing array of elements
	for (int i = 0; i < m_nCount; i++)
		VERIFY(SetPaneText(i, NULL, FALSE));    // no update
}

BOOL CStatusBar::PreCreateWindow(CREATESTRUCT& cs)
{
	// in Win4, status bars do not have a border at all, since it is
	//  provided by the client area.
	if (globalData.bWin4 &&
		(m_dwStyle & (CBRS_ALIGN_ANY|CBRS_BORDER_ANY)) == CBRS_BOTTOM)
	{
		m_dwStyle &= ~(CBRS_BORDER_ANY|CBRS_BORDER_3D);
	}

	return CControlBar::PreCreateWindow(cs);
}

BOOL CStatusBar::Create(CWnd* pParentWnd, DWORD dwStyle, UINT nID)
{
	ASSERT_VALID(pParentWnd);   // must have a parent

	// save the style
	m_dwStyle = (UINT)dwStyle;

	// create the HWND
	CRect rect;
	rect.SetRectEmpty();
	LPCTSTR lpszClass = AfxRegisterWndClass(0, ::LoadCursor(NULL, IDC_ARROW),
		(HBRUSH)(COLOR_BTNFACE+1), NULL);
	if (!CWnd::Create(lpszClass, NULL, dwStyle, rect, pParentWnd, nID))
		return FALSE;

	// Note: Parent must resize itself for control bar to be resized

	// set initial font and calculate bar height
	SendMessage(WM_SETFONT, (WPARAM)globalData.hStatusFont);
	return TRUE;
}

BOOL CStatusBar::SetIndicators(const UINT* lpIDArray, int nIDCount)
{
	ASSERT_VALID(this);
	ASSERT(nIDCount >= 1);  // must be at least one of them
	ASSERT(lpIDArray == NULL ||
		AfxIsValidAddress(lpIDArray, sizeof(UINT) * nIDCount, FALSE));

	// free strings before freeing array of elements
	for (int i = 0; i < m_nCount; i++)
		VERIFY(SetPaneText(i, NULL, FALSE));    // no update

	// first allocate array for panes and copy initial data
	if (!AllocElements(nIDCount, sizeof(AFX_STATUSPANE)))
		return FALSE;
	ASSERT(nIDCount == m_nCount);

	BOOL bOK = TRUE;
	if (lpIDArray != NULL)
	{
		ASSERT(m_hFont != NULL);        // must have a font !
		CString strText;
		CClientDC dcScreen(NULL);
		HGDIOBJ hOldFont = dcScreen.SelectObject(m_hFont);
		for (int i = 0; i < nIDCount; i++)
		{
			AFX_STATUSPANE* pSBP = _GetPanePtr(i);
			pSBP->nID = *lpIDArray++;
			if (pSBP->nID != 0)
			{
				if (!strText.LoadString(pSBP->nID))
				{
					TRACE1("Warning: failed to load indicator string 0x%04X.\n",
						pSBP->nID);
					bOK = FALSE;
					break;
				}
				pSBP->cxText = dcScreen.GetTextExtent(strText,
						strText.GetLength()).cx;
				ASSERT(pSBP->cxText >= 0);
				if (!SetPaneText(i, strText, FALSE))
				{
					bOK = FALSE;
					break;
				}
			}
			else
			{
				// no indicator (must access via index)
				// default to 1/4 the screen width (first pane is stretchy)
				pSBP->cxText = ::GetSystemMetrics(SM_CXSCREEN) / 4;
				if (i == 0)
					pSBP->nStyle |= (SBPS_STRETCH | SBPS_NOBORDERS);
			}
		}
		dcScreen.SelectObject(hOldFont);
	}
	return bOK;
}

#ifdef AFX_CORE3_SEG
#pragma code_seg(AFX_CORE3_SEG)
#endif

/////////////////////////////////////////////////////////////////////////////
// CStatusBar attribute access

int CStatusBar::CommandToIndex(UINT nIDFind) const
{
	ASSERT_VALID(this);

	if (m_nCount <= 0)
		return -1;

	AFX_STATUSPANE* pSBP = _GetPanePtr(0);
	for (int i = 0; i < m_nCount; i++, pSBP++)
		if (pSBP->nID == nIDFind)
			return i;

	return -1;
}

UINT CStatusBar::GetItemID(int nIndex) const
{
	ASSERT_VALID(this);
	return _GetPanePtr(nIndex)->nID;
}

void CStatusBar::GetItemRect(int nIndex, LPRECT lpRect) const
{
	ASSERT_VALID(this);
	ASSERT(AfxIsValidAddress(lpRect, sizeof(RECT)));

	// return rectangle containing inset size
	ASSERT(nIndex >= 0 && nIndex < m_nCount);

	CRect rect;
	GetClientRect(rect);
	CalcInsideRect(rect, TRUE);

	// protect space for size box
	int cxSizeBox = m_bHideSizeBox ? 0 : m_cxSizeBox;
	int xMax = (rect.right -= cxSizeBox);
	if (cxSizeBox == 0)
		xMax += m_cxRightBorder + 1;

	// walk through to calculate extra space
	int cxExtra = rect.Width() + m_cxDefaultGap;
	AFX_STATUSPANE* pSBP = (AFX_STATUSPANE*)m_pData;
	for (int i = 0; i < m_nCount; i++, pSBP++)
		cxExtra -= (pSBP->cxText + CX_BORDER * 4 + m_cxDefaultGap);
	// if cxExtra <= 0 then we will not stretch but just clip

	for (i = 0, pSBP = (AFX_STATUSPANE*)m_pData; i < m_nCount; i++, pSBP++)
	{
		ASSERT(pSBP->cxText >= 0);
		int cxText = pSBP->cxText;
		if ((pSBP->nStyle & SBPS_STRETCH) && cxExtra > 0)
		{
			cxText += cxExtra;
			cxExtra = 0;
		}
		rect.right = rect.left + cxText + CX_BORDER * 4;
		rect.right = std::min(rect.right, xMax);
		if (i == nIndex)
			break;  // stop with correct rectangle (includes border)
		rect.left = rect.right + m_cxDefaultGap;
		rect.left = std::min(rect.left, xMax);
	}
	ASSERT(i == nIndex);
	*lpRect = rect;
}

UINT CStatusBar::GetPaneStyle(int nIndex) const
{
	return _GetPanePtr(nIndex)->nStyle;
}

void CStatusBar::SetPaneStyle(int nIndex, UINT nStyle)
{
	AFX_STATUSPANE* pSBP = _GetPanePtr(nIndex);
	if (pSBP->nStyle != nStyle)
	{
		// just change the style of 1 pane, and invalidate it
		pSBP->nStyle = nStyle;
		CRect rect;
		GetItemRect(nIndex, &rect);
		InvalidateRect(rect);
	}
}

void CStatusBar::GetPaneInfo(int nIndex, UINT& nID, UINT& nStyle,
	int& cxWidth) const
{
	ASSERT_VALID(this);

	AFX_STATUSPANE* pSBP = _GetPanePtr(nIndex);
	nID = pSBP->nID;
	nStyle = pSBP->nStyle;
	cxWidth = pSBP->cxText;
}

void CStatusBar::SetPaneInfo(int nIndex, UINT nID, UINT nStyle, int cxWidth)
{
	ASSERT_VALID(this);

	AFX_STATUSPANE* pSBP = _GetPanePtr(nIndex);
	pSBP->nID = nID;
	SetPaneStyle(nIndex, nStyle);  // single pane invalidate
	if (cxWidth != pSBP->cxText)
	{
		// change width of one pane -> invalidate the entire status bar
		pSBP->cxText = cxWidth;
		Invalidate();
	}
}

void CStatusBar::GetPaneText(int nIndex, CString& s) const
{
	ASSERT_VALID(this);

	AFX_STATUSPANE* pSBP = _GetPanePtr(nIndex);
	s = pSBP->lpszText;
}

BOOL CStatusBar::SetPaneText(int nIndex, LPCTSTR lpszNewText, BOOL bUpdate)
{
	ASSERT_VALID(this);

	AFX_STATUSPANE* pSBP = _GetPanePtr(nIndex);
	if (pSBP->lpszText != NULL)
	{
		if (lpszNewText != NULL && lstrcmp(pSBP->lpszText, lpszNewText) == 0)
			return TRUE;        // nothing to change
		free((LPVOID)pSBP->lpszText);
	}

	BOOL bOK = TRUE;
	if (lpszNewText == NULL || *lpszNewText == '\0')
	{
		pSBP->lpszText = NULL;
	}
	else
	{
		pSBP->lpszText = _tcsdup(lpszNewText);
		if (pSBP->lpszText == NULL)
			bOK = FALSE; // old text is lost and replaced by NULL
	}

	if (bUpdate)
	{
		// invalidate the text of the pane - not including the border
		CRect rect;
		GetItemRect(nIndex, &rect);
		if (!(pSBP->nStyle & SBPS_NOBORDERS))
			rect.InflateRect(-CX_BORDER, -CY_BORDER);
		else
			rect.top -= CY_BORDER;  // base line adjustment
		InvalidateRect(rect);
	}
	return bOK;
}

/////////////////////////////////////////////////////////////////////////////
// CStatusBar implementation

CSize CStatusBar::CalcFixedLayout(BOOL, BOOL bHorz)
{
	ASSERT_VALID(this);

	// recalculate based on font height + borders
	TEXTMETRIC tm;
	{
		CClientDC dcScreen(NULL);
		HGDIOBJ hOldFont = dcScreen.SelectObject(m_hFont);
		VERIFY(dcScreen.GetTextMetrics(&tm));
		dcScreen.SelectObject(hOldFont);
	}

	CRect rectSize;
	rectSize.SetRectEmpty();
	CalcInsideRect(rectSize, bHorz);    // will be negative size

	// sizeof text + 1 or 2 extra on top, 2 on bottom + borders
	return CSize(32767, tm.tmHeight - tm.tmInternalLeading +
		CY_BORDER * (globalData.bWin4 ? 4 : 3) - rectSize.Height());
}

void CStatusBar::DoPaint(CDC* pDC)
{
	ASSERT_VALID(this);
	ASSERT_VALID(pDC);

	CControlBar::DoPaint(pDC);      // draw border

	CRect rect;
	GetClientRect(rect);
	CalcInsideRect(rect, TRUE);

	ASSERT(m_hFont != NULL);        // must have a font!
	HGDIOBJ hOldFont = pDC->SelectObject(m_hFont);

	// protect space for size box
	int cxSizeBox = m_bHideSizeBox ? 0 : m_cxSizeBox;
	int xMax = (rect.right -= cxSizeBox);
	if (cxSizeBox == 0)
		xMax += m_cxRightBorder + 1;

	// walk through to calculate extra space
	int cxExtra = rect.Width() + m_cxDefaultGap;
	AFX_STATUSPANE* pSBP = (AFX_STATUSPANE*)m_pData;
	for (int i = 0; i < m_nCount; i++, pSBP++)
		cxExtra -= (pSBP->cxText + CX_BORDER * 4 + m_cxDefaultGap);
	// if cxExtra <= 0 then we will not stretch but just clip

	for (i = 0, pSBP = (AFX_STATUSPANE*)m_pData; i < m_nCount; i++, pSBP++)
	{
		ASSERT(pSBP->cxText >= 0);
		int cxText = pSBP->cxText;
		if ((pSBP->nStyle & SBPS_STRETCH) && cxExtra > 0)
		{
			cxText += cxExtra;
			cxExtra = 0;
		}
		rect.right = rect.left + cxText + CX_BORDER * 4;
		rect.right = std::min(rect.right, xMax);
		if (!globalData.bWin32s || pDC->RectVisible(&rect))
			DrawStatusText(pDC, rect, pSBP->lpszText, pSBP->nStyle);
		rect.left = rect.right + m_cxDefaultGap;
		if (rect.left >= xMax)
			break;
	}
	pDC->SelectObject(hOldFont);

	// draw the size box in the bottom right corner
	if (cxSizeBox != 0)
	{
		int cxMax = std::min(cxSizeBox, rect.Height()+m_cyTopBorder);
		rect.left = xMax + (cxSizeBox - cxMax) + CX_BORDER;
		rect.bottom -= CX_BORDER;
		HPEN hPenOld = (HPEN)pDC->SelectObject(globalData.hpenBtnHilite);
		for (int i = 0; i < cxMax; i += 4)
		{
			pDC->MoveTo(rect.left+i, rect.bottom);
			pDC->LineTo(rect.left+cxMax, rect.bottom-cxMax+i);
		}
		pDC->SelectObject(globalData.hpenBtnShadow);
		for (i = 1; i < cxMax; i += 4)
		{
			pDC->MoveTo(rect.left+i, rect.bottom);
			pDC->LineTo(rect.left+cxMax, rect.bottom-cxMax+i);
		}
		for (i = 2; i < cxMax; i += 4)
		{
			pDC->MoveTo(rect.left+i, rect.bottom);
			pDC->LineTo(rect.left+cxMax, rect.bottom-cxMax+i);
		}
		pDC->SelectObject(hPenOld);
	}
}

void CStatusBar::DrawStatusText(CDC* pDC, const CRect& rect,
	LPCTSTR lpszText, UINT nStyle)
{
	ASSERT_VALID(pDC);

	if (!(nStyle & SBPS_NOBORDERS))
	{
		// draw the borders
		COLORREF clrHilite;
		COLORREF clrShadow;

		if (nStyle & SBPS_POPOUT)
		{
			// reverse colors
			clrHilite = globalData.clrBtnShadow;
			clrShadow = globalData.clrBtnHilite;
		}
		else
		{
			// normal colors
			clrHilite = globalData.clrBtnHilite;
			clrShadow = globalData.clrBtnShadow;
		}
		pDC->Draw3dRect(rect, clrShadow, clrHilite);
	}

	// just support left justified text
	if (lpszText != NULL && !(nStyle & SBPS_DISABLED))
	{
		CRect rectText(rect);
		if (!(nStyle & SBPS_NOBORDERS)) // only adjust if there are borders
			rectText.InflateRect(-2*CX_BORDER, -CY_BORDER);
		else
			rectText.OffsetRect(0, -CY_BORDER); // baselines line up

		// background is already grey
		int nOldMode = pDC->SetBkMode(TRANSPARENT);
		COLORREF crTextColor = pDC->SetTextColor(globalData.clrBtnText);
		COLORREF crBkColor = pDC->SetBkColor(globalData.clrBtnFace);

		// align on bottom (since descent is more important than ascent)
		pDC->SetTextAlign(TA_LEFT | TA_BOTTOM);
		pDC->ExtTextOut(rectText.left, rectText.bottom,
			ETO_CLIPPED, &rectText, lpszText, lstrlen(lpszText), NULL);
	}
}

/////////////////////////////////////////////////////////////////////////////
// CStatusBar message handlers

BEGIN_MESSAGE_MAP(CStatusBar, CControlBar)
	//{{AFX_MSG_MAP(CStatusBar)
	ON_WM_NCHITTEST()
	ON_WM_SYSCOMMAND()
	ON_WM_SIZE()
	ON_MESSAGE(WM_SETFONT, OnSetFont)
	ON_MESSAGE(WM_GETFONT, OnGetFont)
	ON_MESSAGE(WM_SETTEXT, OnSetText)
	ON_MESSAGE(WM_GETTEXT, OnGetText)
	ON_MESSAGE(WM_GETTEXTLENGTH, OnGetTextLength)
	ON_MESSAGE(WM_SIZEPARENT, OnSizeParent)
	ON_WM_WININICHANGE()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

UINT CStatusBar::OnNcHitTest(CPoint point)
{
	// hit test the size box - convert to HTCAPTION if so
	if (!m_bHideSizeBox && m_cxSizeBox != 0)
	{
		CRect rect;
		GetClientRect(rect);
		CalcInsideRect(rect, TRUE);
		int cxMax = std::min(m_cxSizeBox-1, rect.Height());
		rect.left = rect.right - cxMax;
		ClientToScreen(&rect);
		if (rect.PtInRect(point))
			return HTBOTTOMRIGHT;
	}
	return CControlBar::OnNcHitTest(point);
}

void CStatusBar::OnSysCommand(UINT nID, LPARAM lParam)
{
	if (!m_bHideSizeBox && m_cxSizeBox != 0 && (nID & 0xFFF0) == SC_SIZE)
	{
		CFrameWnd* pFrameWnd = GetParentFrame();
		if (pFrameWnd != NULL)
		{
			pFrameWnd->SendMessage(WM_SYSCOMMAND, (WPARAM)nID, lParam);
			return;
		}
	}
	CControlBar::OnSysCommand(nID, lParam);
}

void CStatusBar::OnSize(UINT nType, int cx, int cy)
{
	CControlBar::OnSize(nType, cx, cy);

	// adjust m_cxSizeBox if necessary
	OnWinIniChange(NULL);	

	// force repaint on resize (recalculate stretchy)
	Invalidate();
}

LRESULT CStatusBar::OnSetFont(WPARAM wParam, LPARAM)
{
	m_hFont = (HFONT)wParam;
	ASSERT(m_hFont != NULL);

	return 0L;      // does not re-draw or invalidate - resize parent instead
}

LRESULT CStatusBar::OnGetFont(WPARAM, LPARAM)
{
	return (LRESULT)(UINT)m_hFont;
}

LRESULT CStatusBar::OnSetText(WPARAM, LPARAM lParam)
{
	int nIndex = CommandToIndex(0);
	if (nIndex < 0)
		return -1;
	return SetPaneText(nIndex, (LPCTSTR)lParam) ? 0 : -1;
}

LRESULT CStatusBar::OnGetText(WPARAM wParam, LPARAM lParam)
{
	int nMaxLen = (int)wParam;
	if (nMaxLen == 0)
		return 0;       // nothing copied
	LPTSTR lpszDest = (LPTSTR)lParam;

	int nLen = 0;
	int nIndex = CommandToIndex(0); // use pane with ID zero
	if (nIndex >= 0)
	{
		AFX_STATUSPANE* pSBP = _GetPanePtr(nIndex);
		nLen = pSBP->lpszText != NULL ? lstrlen(pSBP->lpszText) : 0;
		if (nLen > nMaxLen)
			nLen = nMaxLen - 1; // number of characters to copy (less term.)
		memcpy(lpszDest, pSBP->lpszText, nLen*sizeof(TCHAR));
	}
	lpszDest[nLen] = '\0';
	return nLen+1;      // number of bytes copied
}

LRESULT CStatusBar::OnGetTextLength(WPARAM, LPARAM)
{
	int nLen = 0;
	int nIndex = CommandToIndex(0); // use pane with ID zero
	if (nIndex >= 0)
	{
		AFX_STATUSPANE* pSBP = _GetPanePtr(nIndex);
		if (pSBP->lpszText != NULL)
			nLen = lstrlen(pSBP->lpszText);
	}
	return nLen;
}

LRESULT CStatusBar::OnSizeParent(WPARAM wParam, LPARAM lParam)
{
	AFX_SIZEPARENTPARAMS* lpLayout = (AFX_SIZEPARENTPARAMS*)lParam;
	if (lpLayout->hDWP != NULL)
	{
		// hide size box if parent is maximized
		CFrameWnd* pFrameWnd = GetParentFrame();
		if (pFrameWnd != NULL)
		{
			// the size box only appears when status bar is on the bottom
			//  of a non-maximized, sizeable frame window.
			CRect rectFrame;
			pFrameWnd->GetClientRect(rectFrame);
			BOOL bHideSizeBox = pFrameWnd->IsZoomed() ||
				!(pFrameWnd->GetStyle() & WS_THICKFRAME) ||
				rectFrame.bottom != lpLayout->rect.bottom ||
				rectFrame.right != lpLayout->rect.right;

			// update the size box hidden status, if changed
			if (bHideSizeBox != m_bHideSizeBox)
			{
				m_bHideSizeBox = bHideSizeBox;
				Invalidate();
			}
		}
	}

	return CControlBar::OnSizeParent(wParam, lParam);
}

/////////////////////////////////////////////////////////////////////////////
// CStatusBar idle update through CStatusCmdUI class

#define CStatusCmdUI COldStatusCmdUI

class CStatusCmdUI : public CCmdUI      // class private to this file!
{
public: // re-implementations only
	virtual void Enable(BOOL bOn);
	virtual void SetCheck(int nCheck);
	virtual void SetText(LPCTSTR lpszText);
};

void CStatusCmdUI::Enable(BOOL bOn)
{
	m_bEnableChanged = TRUE;
	CStatusBar* pStatusBar = (CStatusBar*)m_pOther;
	ASSERT(pStatusBar != NULL);
	ASSERT_KINDOF(CStatusBar, pStatusBar);
	ASSERT(m_nIndex < m_nIndexMax);

	UINT nNewStyle = pStatusBar->GetPaneStyle(m_nIndex) & ~SBPS_DISABLED;
	if (!bOn)
		nNewStyle |= SBPS_DISABLED;
	pStatusBar->SetPaneStyle(m_nIndex, nNewStyle);
}

void CStatusCmdUI::SetCheck(int nCheck) // "checking" will pop out the text
{
	CStatusBar* pStatusBar = (CStatusBar*)m_pOther;
	ASSERT(pStatusBar != NULL);
	ASSERT_KINDOF(CStatusBar, pStatusBar);
	ASSERT(m_nIndex < m_nIndexMax);

	UINT nNewStyle = pStatusBar->GetPaneStyle(m_nIndex) & ~SBPS_POPOUT;
	if (nCheck != 0)
		nNewStyle |= SBPS_POPOUT;
	pStatusBar->SetPaneStyle(m_nIndex, nNewStyle);
}

void CStatusCmdUI::SetText(LPCTSTR lpszText)
{
	ASSERT(m_pOther != NULL);
	ASSERT_KINDOF(CStatusBar, m_pOther);
	ASSERT(m_nIndex < m_nIndexMax);

	((CStatusBar*)m_pOther)->SetPaneText(m_nIndex, lpszText);
}

void CStatusBar::OnUpdateCmdUI(CFrameWnd* pTarget, BOOL bDisableIfNoHndler)
{
	CStatusCmdUI state;
	state.m_pOther = this;
	state.m_nIndexMax = (UINT)m_nCount;
	for (state.m_nIndex = 0; state.m_nIndex < state.m_nIndexMax;
		state.m_nIndex++)
	{
		state.m_nID = _GetPanePtr(state.m_nIndex)->nID;
		state.DoUpdate(pTarget, bDisableIfNoHndler);
	}

	// update the dialog controls added to the status bar
	UpdateDialogControls(pTarget, bDisableIfNoHndler);
}

/////////////////////////////////////////////////////////////////////////////
// CStatusBar diagnostics

#ifdef _DEBUG
void CStatusBar::AssertValid() const
{
	CControlBar::AssertValid();
}

void CStatusBar::Dump(CDumpContext& dc) const
{
	CControlBar::Dump(dc);

	dc << "\nm_hFont = " << (UINT)m_hFont;

	if (dc.GetDepth() > 0)
	{
		for (int i = 0; i < m_nCount; i++)
		{
			dc << "\nstatus pane[" << i << "] = {";
			dc << "\n\tnID = " << _GetPanePtr(i)->nID;
			dc << "\n\tnStyle = " << _GetPanePtr(i)->nStyle;
			dc << "\n\tcxText = " << _GetPanePtr(i)->cxText;
			dc << "\n\tlpszText = " << _GetPanePtr(i)->lpszText;
			dc << "\n\t}";
		}
	}

	dc << "\n";
}
#endif //_DEBUG

#undef new
#ifdef AFX_INIT_SEG
#pragma code_seg(AFX_INIT_SEG)
#endif

IMPLEMENT_DYNAMIC(CStatusBar, CControlBar)
