/**************************************************************************** * [S]imulated [M]edieval [A]dventure multi[U]ser [G]ame | * * -----------------------------------------------------------| \\._.// * * SmaugWizard (C) 1998 by Russ Pillsbury (Windows NT version)| (0...0) * * -----------------------------------------------------------| ).:.( * * SMAUG (C) 1994, 1995, 1996 by Derek Snider | {o o} * * -----------------------------------------------------------| / ' ' \ * * SMAUG code team: Thoric, Altrag, Blodkai, Narn, Haus, |~'~.VxvxV.~'~* * Scryn, Swordbearer, Rennard, Tricops, and Gorog. | * * ------------------------------------------------------------------------ * * Merc 2.1 Diku Mud improvments copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik Staerfeldt, Tom Madsen, and Katja Nyboe. * ****************************************************************************/ // SmaugWizView.cpp : implementation of the CSmaugWizView class #include "stdafx.h" #include "SmaugWiz.h" #include "smaug.h" #include "SmaugSocket.h" #include "sysdata.h" #include "mobiles.h" #include "SmaugWizDoc.h" #include "autostart.h" #include "SmaugWizView.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CSmaugWizView IMPLEMENT_DYNCREATE(CSmaugWizView, CScrollView) BEGIN_MESSAGE_MAP(CSmaugWizView, CScrollView) //{{AFX_MSG_MAP(CSmaugWizView) ON_WM_TIMER() ON_WM_SIZE() //}}AFX_MSG_MAP // Standard printing commands ON_COMMAND(ID_FILE_PRINT, CScrollView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_DIRECT, CScrollView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_PREVIEW, CScrollView::OnFilePrintPreview) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CSmaugWizView construction/destruction CSmaugWizView::CSmaugWizView () { m_pTimerDlg = NULL; } CSmaugWizView::~CSmaugWizView () { } BOOL CSmaugWizView::PreCreateWindow(CREATESTRUCT& cs) { // TODO: Modify the Window class or styles here by modifying // the CREATESTRUCT cs return CScrollView::PreCreateWindow(cs); } ///////////////////////////////////////////////////////////////////////////// // CSmaugWizView drawing void CSmaugWizView::OnDraw(CDC* pDC) { CSmaugWizDoc* pDoc = GetDocument (); ASSERT_VALID(pDoc); CRect rectClip; if (pDoc->GetLineCount () == 0) then return; // The window has been invalidated and needs to be repainted. // First, determine the range of rows that need to be displayed. int nFirstRow, nLastRow; pDC->GetClipBox (&rectClip); // Get the invalidated region. RectLPtoRowRange (rectClip, nFirstRow, nLastRow, TRUE); // Draw each row in the invalidated region of the window, // or on the printed (previewed) page. int nRow = nFirstRow; int y = m_nRowHeight * nFirstRow; while (nRow <= nLastRow) { OnDrawRow (pDC, nRow, y); ++nRow; y += m_nRowHeight; } } void CSmaugWizView::OnDrawRow (CDC* pDC, int Row, int y) { char *s = GetDocument ()->GetData (Row); int len = strlen (s); if (len == 0) then return; pDC->TextOut (0, y, s, len); } ///////////////////////////////////////////////////////////////////////////// // CSmaugWizView printing BOOL CSmaugWizView::OnPreparePrinting(CPrintInfo* pInfo) { // default preparation return DoPreparePrinting(pInfo); } void CSmaugWizView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) { // TODO: add extra initialization before printing } void CSmaugWizView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) { // TODO: add cleanup after printing } ///////////////////////////////////////////////////////////////////////////// // CSmaugWizView diagnostics #ifdef _DEBUG void CSmaugWizView::AssertValid() const { CScrollView::AssertValid(); } void CSmaugWizView::Dump(CDumpContext& dc) const { CScrollView::Dump(dc); } CSmaugWizDoc* CSmaugWizView::GetDocument() // non-debug version is inline { ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CSmaugWizDoc))); return (CSmaugWizDoc*)m_pDocument; } #endif //_DEBUG ///////////////////////////////////////////////////////////////////////////// // CSmaugWizView message handlers void CSmaugWizView::OnTimer(UINT nIDEvent) { #ifdef n_DEBUG // Note I used a convenient flag to trigger the memory dump. By using the config screen // to turn on auto-start, the memory dump is triggered each time. if (SysData.IsAutoStart ()) { newMemState.Checkpoint(); if (diffMemState.Difference( oldMemState, newMemState)) { TRACE ("Memory leaked!\n"); diffMemState.DumpStatistics (); oldMemState.DumpAllObjectsSince (); } SysData.SetAutoStart (FALSE); } #endif if (nIDEvent == 1) then { CClientDC dc (this); GetDocument ()->GameLoop (&dc); if (bSmaugDown) { KillTimer (1); BOOL bAutoReboot = SysData.IsAutoReboot () && gpDoc->IsReboot (); int RebootDelay = SysData.GetRebootDelay (); ClearDatabase (); gpDoc->m_pLog->Close (); delete gpDoc->m_pControl; gpDoc->m_pControl = NULL; // if (! bAutoReboot) // ResendExitMsg (); // Start a timer to restart mud if (bAutoReboot) { SetTimer (2, 1000 * RebootDelay, NULL); } return; } } if (nIDEvent == 2) then { KillTimer (2); AfxGetMainWnd ()->PostMessage (WM_COMMAND, ID_FILE_START); } if (nIDEvent == 3) then { if (! m_pTimerDlg) { m_pTimerDlg = new CAutoStart (this); m_pTimerDlg->Create (); m_pTimerDlg->ShowWindow (SW_SHOW); } if (m_pTimerDlg->m_bCancel) { KillTimer (3); m_pTimerDlg->DestroyWindow (); m_pTimerDlg = NULL; return; } if (m_pTimerDlg->m_bStartNow) then gpDoc->m_TimeTilStart = 1; if (--gpDoc->m_TimeTilStart) { m_pTimerDlg->m_Time = gpDoc->m_TimeTilStart; m_pTimerDlg->UpdateData (FALSE); } else { KillTimer (3); m_pTimerDlg->DestroyWindow (); m_pTimerDlg = NULL; AfxGetMainWnd ()->PostMessage (WM_COMMAND, ID_FILE_START); } } CScrollView::OnTimer(nIDEvent); } void CSmaugWizView::OnInitialUpdate () { m_nPrevRowCount = GetDocument ()->GetLineCount(); SetScrollSizes (MM_TEXT, CSize (620,900)); CScrollView::OnInitialUpdate (); } void CSmaugWizView::OnUpdate (CView* pSender, LPARAM lHint, CObject* pHint) { int InvalidRow = lHint; int nRowCount = GetDocument ()->GetLineCount (); // If the number of rows has changed, then adjust the scrolling range. if (nRowCount != m_nPrevRowCount) { UpdateScrollSizes (); m_nPrevRowCount = nRowCount; } CClientDC dc (this); OnPrepareDC (&dc); CalculateRowMetrics (&dc); // Determine the range of the rows that are currently fully visible // in the window. We want to do discrete scrolling by so that // the next or previous row is always fully visible. int nFirstRow, nLastRow; CRect rectClient; GetClientRect (&rectClient); dc.DPtoLP (&rectClient); RectLPtoRowRange (rectClient, nFirstRow, nLastRow, FALSE); // If necessary, scroll the window so the newly selected row is // visible. POINT pt; pt.x = 0; BOOL bNeedToScroll = TRUE; if (InvalidRow < nFirstRow) { // The newly selected row is above those currently visible // in the window. Scroll so the newly selected row is at the // very top of the window. The last row in the window might // be only partially visible. pt.y = RowToYPos (InvalidRow); } else if (InvalidRow > nLastRow) { // The newly selected row is below those currently visible // in the window. Scroll so the newly selected row is at the // very bottom of the window. The first row in the window might // be only partially visible. pt.y = max (0, RowToYPos (InvalidRow+1) - rectClient.Height ()); } else bNeedToScroll = FALSE; if (bNeedToScroll) { // Scrolling will cause the newly selected row to be // redrawn in the invalidated area of the window. ScrollToDevicePosition (pt); // Need to prepare the DC again because // ScrollToDevicePosition () will have changed the viewport // origin. The DC is used some more below. OnPrepareDC (&dc); CalculateRowMetrics (&dc); } if (InvalidRow < MAX_LINES) then InvalidateRect (NULL); else { CRect rectInvalid = RowToWndRect (&dc, InvalidRow); InvalidateRect (&rectInvalid); } } void CSmaugWizView::UpdateScrollSizes () { CSmaugWizDoc* pDoc = GetDocument (); ASSERT_VALID (pDoc); // UpdateScrollSizes () is called when it is necessary to adjust the // scrolling range or page/line sizes. There are two occassions // where this is necessary: (1) when a new row is added-- see // Update ()-- and (2) when the window size changes-- see OnSize (). CRect rectClient; GetClientRect (&rectClient); CClientDC dc (this); CalculateRowMetrics (&dc); // The vert scrolling range is the total display height of all // of the rows. CSize sizeTotal (m_nRowWidth, m_nRowHeight * pDoc->GetLineCount ()); // The vertical per-page scrolling distance is equal to the // how many rows can be displayed in the current window, less // one row for paging overlap. CSize sizePage(m_nRowWidth/5, max(m_nRowHeight, ((rectClient.bottom/m_nRowHeight)-1)*m_nRowHeight)); // The vertical per-line scrolling distance is equal to the // height of the row. CSize sizeLine(m_nRowWidth/20, m_nRowHeight); SetScrollSizes(MM_TEXT, sizeTotal, sizePage, sizeLine); } void CSmaugWizView::GetRowWidthHeight (CDC* pDC, int& Width, int& Height) { TEXTMETRIC tm; pDC->GetTextMetrics (&tm); Width = tm.tmAveCharWidth * LINE_LEN; Height = tm.tmHeight; } CRect CSmaugWizView::RowToWndRect (CDC* pDC, int nRow) { int nHorzRes = pDC->GetDeviceCaps (HORZRES);; CRect rect (0, nRow * m_nRowHeight, nHorzRes, (nRow + 1) * m_nRowHeight); pDC->LPtoDP (&rect); return rect; } void CSmaugWizView::RectLPtoRowRange(const CRect& rect, int& FirstRow, int& LastRow, BOOL bIncludePartiallyShownRows) { int nRounding = bIncludePartiallyShownRows ? 0 : (m_nRowHeight - 1); FirstRow = (rect.top + nRounding) / m_nRowHeight; LastRow = min ((rect.bottom - nRounding) / m_nRowHeight, GetDocument ()->GetLineCount () - 1); } void CSmaugWizView::OnSize (UINT nType, int cx, int cy) { UpdateScrollSizes (); CScrollView::OnSize (nType, cx, cy); } BOOL CSmaugWizView::OnCommand(WPARAM wParam, LPARAM lParam) { // UINT nID = LOWORD(wParam); // if (nID == WM_BOOT_SMAUG) then { // if (GetDocument ()->BootAndStart ()) then // SetTimer (1, 1000 / PULSE_PER_SECOND, NULL); // return TRUE; // } return CScrollView::OnCommand(wParam, lParam); }