NT4/private/windows/win4help/ftsrch/textview.cpp
2020-09-30 17:12:29 +02:00

1919 lines
39 KiB
C++

// Class Semantics for TextView windows
// Created 5 August 1992 by Ron Murray
#include "stdafx.h"
#include "FTSrch.h"
#include "TxDBase.h"
#include "TextView.h"
#include "usermsgs.h"
#include "ftslex.h" //rmk
#include "CSHelp.h"
extern HINSTANCE hinstDLL;
BOOL CTextView::RegisterWndClass(HINSTANCE hInstance)
{
PSZ szName = "TextViewer";
WNDCLASS wndcls;
// see if the class already exists
if (::GetClassInfo(hInstance, szName, &wndcls)) return TRUE;
// otherwise we need to register a new class
wndcls.style = CS_DBLCLKS;
wndcls.lpfnWndProc = &CTextView::WindowProc;
wndcls.cbClsExtra = 0;
wndcls.cbWndExtra = 4;
wndcls.hInstance = hInstance;
wndcls.hIcon = NULL;
wndcls.hCursor = hcurArrow;
wndcls.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
wndcls.lpszMenuName = NULL;
wndcls.lpszClassName = szName;
return ::RegisterClass(&wndcls);
}
HWND CTextView::OpenWindow(PSZ pszWindowName, RECT *prc, HINSTANCE hinst, HWND hwndParent)
{
ASSERT(!m_hwnd);
HWND hwnd= CreateWindow("TextViewer", pszWindowName, WS_CHILD | WS_TABSTOP | WS_VISIBLE,
prc->left, prc->top, prc->right - prc->left, prc->bottom - prc->top,
hwndParent, NULL, hinst, this
);
ASSERT(hwnd);
m_hwnd= hwnd;
return hwnd;
}
LRESULT CALLBACK CTextView::WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
CTextView *ptv= (CTextView *) GetWindowLong(hwnd, GWL_USERDATA);
if (!ptv) return ::DefWindowProc(hwnd, msg, wparam, lparam);
switch (msg)
{
case WM_HELP:
case WM_CONTEXTMENU:
return SendMessage(GetParent(hwnd), msg, wparam, lparam);
case WM_GETDLGCODE:
return DLGC_WANTARROWS;
case WM_ERASEBKGND:
return ptv->OnEraseBkgnd(HDC(wparam));
case WM_PAINT:
ptv->OnPaint(); return 0;
case WM_SIZE:
ptv->OnSize(wparam, LOWORD(lparam), HIWORD(lparam)); return 0;
case WM_WINDOWPOSCHANGED:
ptv->OnWindowPosChanged((WINDOWPOS *) lparam); return 0;
case WM_SETFOCUS:
ptv->OnSetFocus((HWND) wparam); return 0;
case WM_KILLFOCUS:
ptv->OnKillFocus((HWND) wparam); return 0;
case WM_LBUTTONDOWN:
ptv->OnLButtonDown(wparam, MAKEPOINTS(lparam)); return 0;
case WM_LBUTTONDBLCLK:
ptv->OnLButtonDblClk(wparam, MAKEPOINTS(lparam)); return 0;
case WM_LBUTTONUP:
ptv->OnLButtonUp(wparam, MAKEPOINTS(lparam)); return 0;
case WM_MOUSEMOVE:
ptv->OnMouseMove(wparam, MAKEPOINTS(lparam)); return 0;
case WM_MOUSEACTIVATE:
return ptv->OnMouseActivate((HWND) wparam, LOWORD(lparam), HIWORD(lparam));
case WM_NCHITTEST:
return ptv->OnNcHitTest(MAKEPOINTS(lparam));
case WM_SETCURSOR:
return ptv->OnSetCursor((HWND) wparam, LOWORD(lparam), HIWORD(lparam));
case WM_TIMER:
ptv->OnTimer(wparam); return 0;
case WM_KEYDOWN:
ptv->OnKeyDown(wparam, LOWORD(lparam), HIWORD(lparam)); return 0;
case WM_KEYUP:
ptv->OnKeyUp(wparam, LOWORD(lparam), HIWORD(lparam)); return 0;
default:
return ::DefWindowProc(hwnd, msg, wparam, lparam);
}
}
// CTextView constructor:
// Create the text view window with the appropriate style, size, menu, etc.
CTextView::CTextView()
{
m_hwnd = NULL;
m_ptdm = NULL;
m_pbText = NULL;
m_cbText = 0;
m_fGotFocus = FALSE;
m_fMouseCaptured = FALSE;
m_fSwallowMouseActivate = FALSE;
m_fMarquee = FALSE;
m_fMarqueeActive = FALSE;
m_fMarqueePhase = FALSE;
m_fMarqueeTimerOn = FALSE;
m_fTimerActive = FALSE;
m_hTimer = 0;
m_idTimer = 0;
m_cImageFullRows = 0;
m_cImageFullCols = 0;
m_cImageRows = 0;
m_cImageCols = 0;
m_lTopLine = 0;
m_iLeftCol = 0;
m_nCxChar = 0;
m_nCyChar = 0;
m_clrfg = 0;
m_clrbg = 0xFFFFFF;
m_iCharsetAlternate = 0xFFFFFF;
m_iCharset = 0;
m_iHeight = 0;
m_rowFocus = 0;
m_colFocus = 0;
m_cRowsFocus = 1;
m_cColsFocus = 1;
m_cHighlightsAllocated = 0;
m_cHighlightsActive = 0;
m_clFileRows = 0;
m_clFileCols = 0;
m_cLinesScrollContext = 0;
m_cCharsets = 0;
m_pHighlights = NULL;
m_fpOldWndProc = NULL;
m_pba = NULL;
m_hFontDefault = NULL;
m_hFontAlternate = NULL;
m_hFont = NULL;
m_pCharsets = NULL;
m_hCheck = NULL;
m_hNoCheck = NULL;
m_iCheckHeight = 0;
m_iCheckWidth = 0;
m_bUseCheck = FALSE;
m_pba = NULL;
}
CTextView *CTextView::NewTextView()
{
CTextView *ptv= NULL;
__try
{
ptv= New CTextView;
ptv->Init();
}
__finally
{
if (_abnormal_termination() && ptv)
{
delete ptv; ptv= NULL;
}
}
return ptv;
}
CTextView *CTextView::NewTextView(PSZ pszWindowName, RECT *prc, HINSTANCE hinst, HWND hwndParent)
{
CTextView *ptv= NULL;
__try
{
ptv= New CTextView;
ptv->Init();
ptv->OpenWindow(pszWindowName, prc, hinst, hwndParent);
}
__finally
{
if (_abnormal_termination() && ptv)
{
delete ptv; ptv= NULL;
}
}
return ptv;
}
static UINT iCharsetDefault = UINT(-1);
UINT DefaultCharacterSet()
{
if (iCharsetDefault != UINT(-1)) return iCharsetDefault;
TEXTMETRIC tm;
HDC hdc;
iCharsetDefault= ANSI_CHARSET;
hdc= GetDC(NULL);
if (!hdc) return iCharsetDefault;
if (GetTextMetrics(hdc, &tm))
iCharsetDefault= tm.tmCharSet;
return iCharsetDefault;
}
void CTextView::Init()
{
AttachRef(m_pba, New CByteVector);
}
// SetFont for drawing the list boxes
void CTextView::SetFont(HFONT hFont)
{
ASSERT( hFont); // Dont call me with a bogus font please
ASSERT(!m_hFont); // Must not have a font installed already
m_hFont = hFont;
HDC hdc= GetDC(m_hwnd);
HGDIOBJ hsavFont= ::SelectObject(hdc, hFont);
::GetTextMetrics(hdc, &m_FontMetrics);
::SelectObject(hdc, hsavFont);
m_nCxChar = m_FontMetrics.tmMaxCharWidth;
m_nCyChar = m_FontMetrics.tmHeight + m_FontMetrics.tmExternalLeading;
m_LeftMargin = m_nCxChar >> 1;
RECT rc;
GetWindowRect(m_hwnd, &rc);
OnSize(SIZENORMAL, rc.right - rc.left, rc.bottom - rc.top);
LOGFONT lf;
::GetObject(hFont, sizeof(lf), &lf);
m_iCharset= lf.lfCharSet;
::ReleaseDC(m_hwnd, hdc);
Invalidate();
}
// Release the drawing font and go back to the default font
HGDIOBJ CTextView::ReleaseFont()
{
ASSERT(m_hFont); // Don't call me if the font has not be set first!
HGDIOBJ hTemp = m_hFont;
m_hFont = NULL;
return hTemp;
}
CTextView *CTextView::NewTextView(CTextMatrix * ptdm)
{
CTextView *ptv= NULL;
__try
{
ptv= New CTextView;
ptv->Init(ptdm);
}
__finally
{
if (_abnormal_termination() && ptv)
{
delete ptv; ptv= NULL;
}
}
return ptv;
}
void CTextView::Init(CTextMatrix * ptdm)
{
Init();
if (ptdm)
{
AttachRef(m_ptdm, ptdm);
ptdm->Connect(this);
m_clFileRows= ptdm->RowCount();
m_clFileCols= ptdm->ColCount();
}
m_cLinesScrollContext = 0;
}
CTextView *CTextView::NewTextView(CTextMatrix * ptdm, PSZ pszWindowName, RECT *prc, HINSTANCE hinst, HWND hwndParent)
{
CTextView *ptv= NULL;
__try
{
ptv= New CTextView;
ptv->Init(ptdm);
ptv->OpenWindow(pszWindowName, prc, hinst, hwndParent);
}
__finally
{
if (_abnormal_termination() && ptv)
{
delete ptv; ptv= NULL;
}
}
return ptv;
}
void CTextView::SetTextDatabase(CTextMatrix * ptdm)
{
if (m_ptdm)
{
m_ptdm->Disconnect(this);
DetachRef(m_ptdm);
if (m_cHighlightsAllocated)
{
m_cHighlightsAllocated = 0;
m_cHighlightsActive = 0;
delete [] m_pHighlights;
m_pHighlights= NULL;
}
}
if (ptdm)
{
AttachRef(m_ptdm, ptdm);
ptdm->Connect(this);
}
if (ptdm)
{
m_clFileRows= ptdm->RowCount();
m_clFileCols= ptdm->ColCount();
FillBuff();
}
else
{
m_clFileRows= 0;
m_clFileCols= 0;
}
InvalidateRect(m_hwnd, NULL, TRUE);
}
void CTextView::RawDataEvent(UINT uEventType)
{
BOOL fOriginChange = FALSE;
BOOL fMarquee = m_fMarquee;
BOOL fMarqueeActive = m_fMarqueeActive;
switch(uEventType)
{
case CTextMatrix::SelectionChange:
break;
case CTextMatrix::FocusChange:
if (fMarquee) RemoveMarquee();
if (m_ptdm->GetFocusRect(&m_rowFocus , &m_colFocus,
&m_cRowsFocus, &m_cColsFocus
)
)
{
ScrollTo(m_rowFocus, m_colFocus, 1, 1);
if(m_fGotFocus) SetupMarquee();
}
if (m_fGotFocus)
if (m_fMarqueeActive && !fMarqueeActive)
{
m_idTimer= ::SetTimer(m_hwnd, MARQUEE_TIMER_ID, MARQUEE_TIMER_SPAN, NULL);
m_fMarqueeTimerOn= m_idTimer? TRUE : FALSE;
}
else
if (fMarqueeActive && !m_fMarqueeActive) ::KillTimer(m_hwnd, m_idTimer);
::UpdateWindow(m_hwnd);
break;
case CTextMatrix::ShapeChange:
m_clFileRows= m_ptdm->RowCount();
m_clFileCols= m_ptdm->ColCount();
MatchBuffToWindow();
if (m_lTopLine && m_lTopLine > m_clFileRows - m_cImageFullRows - 1)
{
m_lTopLine = m_clFileRows - m_cImageFullRows - 1;
if (m_lTopLine < 0) m_lTopLine= 0;
fOriginChange= TRUE;
}
if (m_iLeftCol && m_iLeftCol > m_clFileCols - m_cImageFullCols - 1)
{
m_iLeftCol = m_clFileCols - m_cImageFullCols - 1;
if (m_iLeftCol < 0) m_iLeftCol= 0;
fOriginChange= TRUE;
}
m_fMarquee = FALSE;
m_fMarqueeActive = FALSE;
if (m_ptdm->GetFocusRect(&m_rowFocus , &m_colFocus,
&m_cRowsFocus, &m_cColsFocus
)
)
{
ScrollTo(m_rowFocus, m_colFocus, 1, 1);
if (m_fGotFocus) SetupMarquee();
}
if (m_fGotFocus)
if (m_fMarqueeActive && !fMarqueeActive)
{
m_idTimer= ::SetTimer(m_hwnd, MARQUEE_TIMER_ID, MARQUEE_TIMER_SPAN, NULL);
m_fMarqueeTimerOn= m_idTimer? TRUE : FALSE;
}
else
if (fMarqueeActive && !m_fMarqueeActive) ::KillTimer(m_hwnd, m_idTimer);
::UpdateWindow(m_hwnd);
break;
case CTextMatrix::DataDeath:
break;
}
if (fOriginChange) NotifyInterface(OriginChange);
}
CTextView::~CTextView()
{
if (m_hFontDefault)
{
DeleteObject(m_hFontDefault);
m_hFontDefault = NULL;
}
if (m_hFontAlternate)
{
DeleteObject(m_hFontAlternate);
m_hFontAlternate = NULL;
}
if (m_hCheck)
{
DeleteObject(m_hCheck);
m_hCheck = NULL;
}
if (m_hNoCheck)
{
DeleteObject(m_hNoCheck);
m_hNoCheck = NULL;
}
if (m_ptdm)
{
m_ptdm->Disconnect(this);
DetachRef(m_ptdm);
}
if (m_pHighlights) delete m_pHighlights;
if (m_pba) DetachRef(m_pba);
if (m_pCharsets) delete m_pCharsets;
if (m_pbText) delete m_pbText;
}
BOOL CTextView::SubclassDlgItem(UINT nId, HWND hwndParent)
{
ASSERT(!m_hwnd);
HWND hwndCtrl= ::GetDlgItem(hwndParent, nId);
ASSERT(hwndCtrl);
Attach(hwndCtrl);
m_hwnd= hwndCtrl;
m_fpOldWndProc = (WNDPROC)::GetWindowLong(hwndCtrl, GWL_USERDATA);
::SetWindowLong(hwndCtrl, GWL_USERDATA, long(this));
InitState();
return(TRUE);
}
void CTextView::InitState()
{
// Assumption: We assume that all member variables are initialed with
// zero!
m_cImageFullRows = 0;
m_cImageFullCols = 0;
m_cImageRows = 0;
m_cImageCols = 0;
m_lTopLine = 0;
m_iLeftCol = 0;
m_clFileRows = 0;
m_clFileCols = 0;
m_iHeight = 0;
m_iCharset = 0;
m_cCharsets = 0;
m_pCharsets = NULL;
m_iCharsetAlternate = 0xFFFFFF;
char acName[128];
::LoadString(hinstDLL,IDS_LISTBOX_FONT,acName,79);
char *pcPointSize;
char c;
for (pcPointSize= acName; (c= *pcPointSize) && c != ','; ++pcPointSize);
m_iHeight= 8;
if (c == ',')
{
*pcPointSize++ = 0;
int iHeight= atoi(pcPointSize);
if (iHeight) m_iHeight= iHeight;
}
m_iCharset = 0;
m_iFamily = 3;
m_iPitch = 2;
HDC hdc= GetDC(m_hwnd);
// Create a font for the list box for default;
m_iHeight = 72 / ((m_iHeight < 8) ? 8 : (m_iHeight > 37) ? 36 : m_iHeight); // Make sure it is reasonable sized
m_iHeight = (hdc) ? GetDeviceCaps(hdc,LOGPIXELSY) / m_iHeight : 8; // convert to point size
if (strlen(acName))
m_hFontDefault = CreateFont(-m_iHeight,0,0,0,0,0,0,0,m_iCharset,OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,m_iPitch | m_iFamily,
acName);
if (!m_hFontDefault) // Assume this means they gave me a bad name use my own
{
m_iCharset = ANSI_CHARSET;
m_iFamily = FF_MODERN;
m_iPitch = VARIABLE_PITCH;
m_hFontDefault = CreateFont(-m_iHeight,0,0,0,0,0,0,0,m_iCharset,OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,m_iPitch | m_iFamily,
"MS Sans Serif");
}
HGDIOBJ hsavFont= ::SelectObject(hdc, m_hFontDefault);
::GetTextMetrics(hdc, &m_FontMetrics);
::SelectObject(hdc, hsavFont);
m_nCxChar = m_FontMetrics.tmMaxCharWidth;
m_nCyChar = m_FontMetrics.tmHeight + m_FontMetrics.tmExternalLeading;
m_LeftMargin = m_nCxChar >> 1;
::ReleaseDC(m_hwnd, hdc);
m_hCheck = LoadBitmap(hinstDLL,MAKEINTRESOURCE(IDB_CHECK));
m_hNoCheck = LoadBitmap(hinstDLL,MAKEINTRESOURCE(IDB_NOCHECK));
BITMAP bmp;
GetObject(m_hCheck,sizeof(bmp),&bmp);
m_iCheckHeight = bmp.bmHeight;
m_iCheckWidth = bmp.bmWidth;
}
void CTextView::MatchBuffToWindow()
{
if (!m_ptdm) return;
if (IsIconic(m_hwnd)) return;
RECT rectClient;
GetClientRect(m_hwnd, &rectClient);
OnSize(SIZENORMAL, rectClient.right - rectClient.left, rectClient.bottom - rectClient.top);
}
void CTextView::RedrawFocusBar()
{
RECT rc;
::GetClientRect(m_hwnd, &rc);
::InvalidateRect(m_hwnd, &rc, TRUE);
::UpdateWindow(m_hwnd);
}
void CTextView::SetupMarquee()
{
ASSERT(!m_fMarquee);
long rowTop, colLeft, cRows, cCols, rowLimit, colLimit;
long rowLimitImage= m_lTopLine + m_cImageRows;
long colLimitImage= m_iLeftCol + m_cImageCols;
cRows = 1;
rowTop = m_rowFocus;
rowLimit= rowTop+ cRows;
if (m_cColsFocus < 0)
{
colLeft = m_colFocus + 1 + m_cColsFocus;
cCols = -m_cColsFocus;
}
else
{
colLeft = m_colFocus;
cCols = m_cColsFocus;
}
colLimit= colLeft+cCols;
#if 0
if ( rowLimit <= m_lTopLine
|| rowTop >= rowLimitImage
|| colLimit <= m_iLeftCol
|| colLeft >= colLimitImage
)
{
m_rcMarquee.top = 0;
m_rcMarquee.bottom = 0;
m_rcMarquee.left = 0;
m_rcMarquee.right = 0;
return;
}
#endif
if (rowTop < m_lTopLine ) rowTop = m_lTopLine - 2;
if (colLeft < m_iLeftCol ) colLeft = m_iLeftCol - 2;
if (rowLimit > rowLimitImage) rowLimit = rowLimitImage + 2;
if (colLimit > colLimitImage) colLimit = colLimitImage + 2;
RECT rc; // RonM -- To make marquees and focus rectangles
// go across the complete display width.
GetWindowRect(m_hwnd, &rc);
m_rcMarquee.top = TopMargin + (rowTop - m_lTopLine) * m_nCyChar;
m_rcMarquee.left = 0; // (colLeft - m_iLeftCol) * m_nCxChar;
m_rcMarquee.bottom = m_rcMarquee.top + (rowLimit - rowTop )* m_nCyChar;
m_rcMarquee.right = rc.right - rc.left; // m_rcMarquee.left + (colLimit - colLeft)* m_nCxChar;
m_fMarquee= TRUE ;
InvalidateMarquee();
}
void CTextView::StartMarquee(HDC hdc)
{
ASSERT(m_fMarquee);
HDC hdcWnd= hdc;
if (!hdcWnd) hdcWnd= GetDC(m_hwnd);
COLORREF clrTextSave = ::SetTextColor(hdcWnd, RGB( 0, 0, 0));
COLORREF clrBkSave = ::SetBkColor (hdcWnd, RGB(256,256,256));
HBRUSH hbrFrame= CreatePatternBrush(m_fMarqueeActive? hbmCheckered : hbmGray50pc);
long xOffset= (m_iLeftCol * (m_nCxChar % 8)) % 8;
long yOffset= (m_lTopLine * (m_nCyChar % 8)) % 8;
::SetBrushOrgEx(hdcWnd, m_LeftMargin - int(xOffset), TopMargin - int(yOffset), NULL);
HBRUSH hbrSave= (HBRUSH)::SelectObject(hdcWnd, HGDIOBJ(hbrFrame));
DrawMarquee(hdcWnd, PATCOPY);
::SetTextColor(hdcWnd, clrTextSave);
::SetBkColor (hdcWnd, clrBkSave );
m_fMarqueePhase = FALSE;
::SelectObject(hdcWnd, hbrSave);
DeleteObject(hbrFrame);
if (!hdc) ReleaseDC(m_hwnd, hdcWnd);
}
void CTextView::DrawMarquee(HDC hdcWnd, DWORD dwRop)
{
if ( m_rcMarquee.top >= m_rcMarquee.bottom
|| m_rcMarquee.left >= m_rcMarquee.right
) return;
RECT rcClip;
::GetClientRect(m_hwnd, &rcClip);
rcClip.top = TopMargin;
rcClip.left = 0;
::IntersectClipRect(hdcWnd, rcClip.left, rcClip.top, rcClip.right, rcClip.bottom);
int cx= m_rcMarquee.right - m_rcMarquee.left;
int cy= m_rcMarquee.bottom - m_rcMarquee.top;
::PatBlt(hdcWnd, m_rcMarquee.left, m_rcMarquee.top , cx, 1, dwRop);
::PatBlt(hdcWnd, m_rcMarquee.left, m_rcMarquee.bottom-1, cx, 1, dwRop);
::PatBlt(hdcWnd, m_rcMarquee.left , m_rcMarquee.top+1, 1, cy-2, dwRop);
::PatBlt(hdcWnd, m_rcMarquee.right-1, m_rcMarquee.top+1, 1, cy-2, dwRop);
}
void CTextView::CycleMarquee(HDC hdc)
{
HDC hdcWnd= hdc;
if (!hdcWnd) hdcWnd= GetDC(m_hwnd);
DrawMarquee(hdcWnd, DSTINVERT);
m_fMarqueePhase= !m_fMarqueePhase;
if (!hdc) ReleaseDC(m_hwnd, hdcWnd);
}
void CTextView::RemoveMarquee(HDC hdc)
{
ASSERT(m_fMarquee);
// bugbug: Need to turn off the marquee timer here.
// bugbug: also need an OnTimer message handler.
InvalidateMarquee();
m_fMarquee = FALSE;
m_fMarqueeActive = FALSE;
}
void CTextView::InvalidateMarquee()
{
RECT rc= m_rcMarquee;
rc.bottom= rc.top+1;
::InvalidateRect(m_hwnd, &rc, TRUE);
rc.bottom= m_rcMarquee.bottom;
rc.top = rc .bottom-1;
InvalidateRect(m_hwnd, &rc, TRUE);
rc.top = m_rcMarquee.top;
rc.right = rc .left+1;
InvalidateRect(m_hwnd, &rc, TRUE);
rc.right = m_rcMarquee.right;
rc.left = rc .right-1;
InvalidateRect(m_hwnd, &rc, TRUE);
}
void CTextView::RepaintMarquee(HDC hdc)
{
ASSERT(m_fMarquee);
BOOL fCycle= m_fMarqueePhase;
StartMarquee(hdc);
if (fCycle) CycleMarquee(hdc);
}
void CTextView::OnSetFocus(HWND hwndOld)
{
m_fGotFocus= TRUE;
SetupMarquee();
RedrawFocusBar();
if (m_fMarqueeActive)
{
m_idTimer= ::SetTimer(m_hwnd, MARQUEE_TIMER_ID, MARQUEE_TIMER_SPAN, NULL);
m_fMarqueeTimerOn= m_idTimer? TRUE : FALSE;
}
}
void CTextView::OnKillFocus(HWND hwndNew)
{
m_fGotFocus= FALSE;
if (m_fMarquee) RemoveMarquee();
RedrawFocusBar();
if (m_fMarqueeActive && m_fMarqueeTimerOn)
{
::KillTimer(m_hwnd, m_idTimer);
m_idTimer= 0;
m_fMarqueeTimerOn= FALSE;
}
}
void CTextView::OnWindowPosChanged(WINDOWPOS FAR* lpwndpos )
{
OnSize(SIZENORMAL, lpwndpos->cx, lpwndpos->cy);
}
void CTextView::OnSize(UINT nType, int cx, int cy)
{
if (nType != SIZEFULLSCREEN && nType != SIZENORMAL) return;
short cColsFull = (short) m_ptdm->ColCount();
short cRowsFull = (cy- TopMargin)/m_nCyChar;
m_cImageFullCols = (cColsFull > 0)? cColsFull : 0;
m_cImageFullRows = (cRowsFull > 0)? cRowsFull : 0;
int cRowsClient = (cy+m_nCyChar-1- TopMargin)/m_nCyChar;
int cColsClient = m_ptdm->ColCount();
if (cRowsClient < 0) cRowsClient= 0;
if (cColsClient < 0) cColsClient= 0;
if (cRowsClient != m_cImageRows || cColsClient != m_cImageCols)
{
m_cImageRows= cRowsClient;
m_cImageCols= cColsClient;
if (m_cImageRows > m_cCharsets)
{
if (m_pCharsets)
{
delete m_pCharsets;
m_pCharsets = NULL;
m_cCharsets = 0;
}
if (m_pCharsets = New UINT[m_cImageRows])
m_cCharsets = m_cImageRows;
}
m_pba->SetSize(cRowsClient*cColsClient);
}
if (m_ptdm) FillBuff();
InvalidateRect(m_hwnd, NULL, TRUE);
}
void CTextView::OnSizeChar(int cx,int cy)
{
short cColsFull = cx;
short cRowsFull = cy;
m_cImageFullCols = (cColsFull > 0)? cColsFull : 0;
m_cImageFullRows = (cRowsFull > 0)? cRowsFull : 0;
int cColsClient = cx;
int cRowsClient = cy;
if (cColsClient < 0) cColsClient= 0;
if (cRowsClient < 0) cRowsClient= 0;
if (cColsClient != m_cImageCols || cRowsClient != m_cImageRows)
{
m_cImageCols= cColsClient;
m_cImageRows= cRowsClient;
if (m_cImageRows > m_cCharsets)
{
if (m_pCharsets)
{
delete m_pCharsets;
m_pCharsets = NULL;
m_cCharsets = 0;
}
if (m_pCharsets = New UINT[m_cImageRows])
m_cCharsets = m_cImageRows;
}
m_pba->SetSize(m_cImageRows * m_cImageCols);
}
if (m_ptdm) FillBuff();
InvalidateRect(m_hwnd, NULL, TRUE);
}
void CTextView::FillBuff()
{
m_ptdm->GetTextMatrixImage
(m_lTopLine, m_iLeftCol, m_cImageRows, m_cImageCols, m_pba->ElementAt(0), m_pCharsets); //rmk
UINT iCharsetDef= DefaultCharacterSet();
for (int c= m_cImageRows; c--; )
if (m_pCharsets[c] == DEFAULT_CHARSET)
m_pCharsets[c] = iCharsetDef;
UINT cHighlights= m_ptdm->GetHighlights(m_lTopLine, m_iLeftCol,
m_cImageRows, m_cImageCols,
0, NULL
);
if (cHighlights)
{
if (cHighlights > m_cHighlightsAllocated)
{
if (m_cHighlightsAllocated)
delete [] m_pHighlights;
m_cHighlightsAllocated=cHighlights;
m_pHighlights= New CHighlight[m_cHighlightsAllocated];
}
m_ptdm->GetHighlights(m_lTopLine, m_iLeftCol,
m_cImageRows, m_cImageCols,
cHighlights, m_pHighlights
);
// The highlight data is initially relative to the full data image.
// For convenience during repainting we make it relative to the buffer
// image.
// Bug: C 7.00 won't accept the declaration for phl within the
// init phrase of the for statement!
PCHighlight phl= m_pHighlights;
for (UINT c= cHighlights;
c--;
phl++
)
{
phl->m_row -= m_lTopLine;
phl->m_col -= m_iLeftCol;
}
}
m_cHighlightsActive= cHighlights;
}
BOOL CTextView::OnEraseBkgnd(HDC hdc)
{
RECT rect;
UINT wLM= m_LeftMargin;
::GetClientRect(m_hwnd, &rect );
#if 0 // #ifndef CHICAGO
HBRUSH hbrushSave;
if (m_fGotFocus)
{
HBRUSH hbrFocus= ::CreateSolidBrush(::GetSysColor(COLOR_ACTIVECAPTION));
hbrushSave= ::SelectObject(hdc, hbrFocus);
::BitBlt(hdc, rect.left, rect.top, FocusMargin, rect.bottom - rect.top, NULL, 0, 0, PATCOPY);
SelectObject(hdc, hbrushSave);
DeleteObject(hbrFocus);
rect.left += FocusMargin;
wLM -= FocusMargin;
}
#endif // 0
#if 0
HBRUSH hbrTextBG= (HBRUSH) ::SendMessage(GetParent(m_hwnd), WM_CTLCOLORDLG, (WPARAM) hdc, (LPARAM) GetParent(m_hwnd));
hbrushSave= ::SelectObject(hdc, hbrTextBG);
if (m_ptdm)
{
::BitBlt(hdc, rect.left, rect.top, wLM, rect.bottom - rect.top, NULL, 0, 0, PATCOPY);
::BitBlt(hdc, rect.left+wLM, rect.top, (rect.right - rect.left)-wLM, TopMargin, NULL, 0, 0, PATCOPY);
}
else ::BitBlt(hdc, rect.left, rect.top, (rect.right - rect.left), rect.bottom - rect.top, NULL, 0, 0, PATCOPY);
::SelectObject(hdc, hbrushSave);
DeleteObject(hbrTextBG);
#endif // 0
return TRUE;
}
void CTextView::ColorTextOut(HDC hdc, int x, int y,
PWCHAR lpChar, int row, int cChar, //rmk
COLORREF clrfg, COLORREF clrbg
)
{
if (m_clrfg != clrfg) ::SetTextColor(hdc, m_clrfg= clrfg);
if (m_clrbg != clrbg) ::SetBkColor (hdc, m_clrbg= clrbg);
RECT rcClip;
::GetClientRect(m_hwnd, &rcClip);
rcClip.top = y;
if (rcClip.bottom > y + m_nCyChar)
rcClip.bottom = y + m_nCyChar;
//rmk-->
cChar <<= 1; // each WC can generate two MB characters
if (cChar > m_cbText)
{
m_cbText = 0;
if (m_pbText) { delete m_pbText; m_pbText= NULL; }
m_pbText = New char[cChar];
m_cbText = cChar;
}
if (!m_pbText) return;
int cText = WideCharToMultiByte(GetCPFromCharset(m_pCharsets[row]), 0, lpChar, cChar>>1, m_pbText, m_cbText, NULL, NULL); //rmk
//rmk<--
ExtTextOut(hdc, x, y, ETO_OPAQUE, &rcClip, m_pbText, cText, NULL); //rmk
}
// OnPaint
//
#ifdef _DEBUG
static UINT cRepaints= 0;
#endif // _DEBUG
void CTextView::OnPaint()
{
PAINTSTRUCT ps;
int iLastHilite = -1;
HDC hdc= ::BeginPaint(m_hwnd, &ps);
if (! m_ptdm ) { EndPaint(m_hwnd, &ps); return; }
#ifdef _DEBUG
++cRepaints;
#endif // _DEBUG
// if we are using the 3d drawing stuff we need to setup the
// background manually
HBRUSH hbrTextBG= (HBRUSH) ::SendMessage(GetParent(m_hwnd), WM_CTLCOLORDLG, (WPARAM) hdc, (LPARAM) GetParent(m_hwnd));
LOGBRUSH lb;
::GetObject(hbrTextBG, sizeof(LOGBRUSH),&lb);
::SetBkColor(hdc, lb.lbColor);
::SetTextAlign(hdc, TA_LEFT);
HFONT hfontDefault= m_hFont? m_hFont : m_hFontDefault;
HGDIOBJ hSaveFont= ::SelectObject(hdc, hfontDefault);
m_clrfg= ::GetTextColor(hdc); // Set up to use ColorTextOut routine...
m_clrbg= ::GetBkColor (hdc);
COLORREF clrfgText = ::GetSysColor(COLOR_WINDOWTEXT );
COLORREF clrbgText = ::GetSysColor(COLOR_WINDOW );// m_clrbg;
COLORREF clrfgTextHighlight = ::GetSysColor(COLOR_HIGHLIGHTTEXT);
COLORREF clrbgTextHighlight = ::GetSysColor(COLOR_HIGHLIGHT );
HBRUSH hbrFrame = ::CreateSolidBrush(clrbgTextHighlight);
HBRUSH hbrDotBox = ::CreatePatternBrush(hbmGray50pc );
HBRUSH hbrDashBox = ::CreatePatternBrush(hbmCheckered);
RECT rcFrame;
HBRUSH hbrSave= (HBRUSH)::SelectObject(hdc, HGDIOBJ(hbrFrame));
UINT cHighlightsLeft = m_cHighlightsActive;
CHighlight *pHighlight = m_pHighlights;
RECT rect, rect2;
int y;
PWCHAR lpb; //rmk
::GetClientRect(m_hwnd, &rect);
RECT rectUpdate= rect;
int yOff= TopMargin;
int xOff= m_LeftMargin;
if (rectUpdate.top < (int) yOff)
rectUpdate.top = yOff;
int rowFirst= (rectUpdate.top - yOff)/m_nCyChar;
int rowLimit= (rectUpdate.bottom + m_nCyChar - 1 - yOff) / m_nCyChar;
if (rectUpdate.left < (int) xOff)
rectUpdate.left= xOff;
int colFirst= 0;
int colLimit= m_cImageCols;
int cols= colLimit - colFirst;
rect2.left = xOff + colFirst*m_nCxChar;
rect2.right = rect.right;
y = yOff + m_nCyChar * rowFirst;
int row= rowFirst;
for ( lpb= m_pba->ElementAt(colFirst + rowFirst * m_cImageCols);
row < rowLimit; // y < rectUpdate.bottom;
y += m_nCyChar, lpb+= m_cImageCols, ++row
)
{
rect2.top = y;
rect2.bottom = y + m_nCyChar;
for (; cHighlightsLeft && ( pHighlight->m_iType
!= CHighlight::HIGHLIGHT_TEXT
|| pHighlight->m_row < row
);
cHighlightsLeft--, pHighlight++
);
UINT colsDrawn = 0;
int col = colFirst;
int left = rect2.left;
PWCHAR lpchar = lpb; //rmk
for (int cChar= cols;
cChar;
cChar -= colsDrawn,
col += colsDrawn,
left += colsDrawn*m_nCxChar,
lpchar += colsDrawn
)
{
for (; cHighlightsLeft && ( pHighlight->m_iType
!= CHighlight::HIGHLIGHT_TEXT
|| ( pHighlight->m_row == row
&& (pHighlight->m_col
+ pHighlight->m_cChars) <= col
)
);
cHighlightsLeft--, pHighlight++
);
if (m_pCharsets[row] == m_iCharset)
::SelectObject(hdc, hfontDefault);
else if (m_pCharsets[row] == m_iCharsetAlternate)
::SelectObject(hdc, m_hFontAlternate);
else
{
if (m_hFontAlternate)
DeleteObject(m_hFontAlternate);
m_hFontAlternate = NULL;
m_iCharsetAlternate = m_pCharsets[row];
LOGFONT lf;
GetObject(hfontDefault, sizeof(lf), &lf);
lf.lfCharSet= m_iCharsetAlternate;
if (m_iCharsetAlternate == SYMBOL_CHARSET)
strcpy(lf.lfFaceName, "SYMBOL");
m_hFontAlternate = CreateFontIndirect(&lf);
// m_hFontAlternate = CreateFont(-m_iHeight,0,0,0,0,0,0,0,m_iCharsetAlternate,OUT_DEFAULT_PRECIS,
// CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,m_iPitch | m_iFamily, NULL);
if (m_hFontAlternate)
{
::SelectObject(hdc, m_hFontAlternate);
TEXTMETRIC tm;
if (GetTextMetrics(hdc, &tm))
//ASSERT(tm.tmCharSet == m_iCharsetAlternate);
;
else
{
::SelectObject(hdc, hfontDefault);
::DeleteObject(m_hFontAlternate);
m_pCharsets[row] = m_iCharset;
m_iCharsetAlternate = 0xFFFFFF;
m_hFontAlternate = NULL;
}
}
else
{
m_pCharsets[row] = m_iCharset;
m_iCharsetAlternate = 0xFFFFFF;
::SelectObject(hdc, hfontDefault);
}
}
if (cHighlightsLeft && pHighlight->m_row == row
&& pHighlight->m_col < colFirst+cols
)
{
if (pHighlight->m_col > col)
{
colsDrawn= pHighlight->m_col-col;
ColorTextOut(hdc, left, rect2.top, lpchar, row, colsDrawn, clrfgText, clrbgText);
}
cChar -= colsDrawn;
lpchar += colsDrawn;
col += colsDrawn;
left += colsDrawn*m_nCxChar;
int colHL= pHighlight->m_col;
int cbHL= m_cImageCols - colHL; // pHighlight->m_cChars;
if (colHL < col)
{
cbHL -= col-colHL;
colHL = col;
}
if (cbHL > cChar) cbHL= cChar;
ColorTextOut(hdc, left, rect2.top, lpchar, row, colsDrawn= cbHL, clrfgTextHighlight, clrbgTextHighlight);
iLastHilite = row;
++pHighlight; --cHighlightsLeft;
}
else
{
ColorTextOut(hdc, left, rect2.top, lpchar, row, cChar, clrfgText, clrbgText);
break;
}
}
}
cHighlightsLeft = m_cHighlightsActive;
pHighlight = m_pHighlights;
for (row= rowFirst; row < rowLimit; ++row)
{
for (;
cHighlightsLeft && (pHighlight->m_iType == CHighlight::HIGHLIGHT_TEXT || pHighlight->m_row < row);
cHighlightsLeft--, pHighlight++
);
if (!cHighlightsLeft) break;
int col;
for (row= pHighlight->m_row, col= colFirst; col < colLimit; )
{
for (;
cHighlightsLeft && ( pHighlight->m_iType == CHighlight::HIGHLIGHT_TEXT
|| (pHighlight->m_row == row && (pHighlight->m_col + pHighlight->m_cChars)<= col)
);
cHighlightsLeft--, pHighlight++
);
if (!cHighlightsLeft) break;
for (;
cHighlightsLeft && pHighlight->m_iType != CHighlight::HIGHLIGHT_TEXT
&& pHighlight->m_row == row
&& pHighlight->m_col < colLimit;
col= pHighlight->m_col + pHighlight->m_cChars,
cHighlightsLeft--, pHighlight++
)
{
RECT rcBounds;
rcBounds.top = yOff + pHighlight->m_row * m_nCyChar;
rcBounds.left = xOff + pHighlight->m_col * m_nCxChar;
rcBounds.bottom = rcBounds.top + m_nCyChar;
rcBounds.right = rcBounds.left + pHighlight->m_cChars
* m_nCxChar;
switch (pHighlight->m_iType)
{
case CHighlight::CHECK_MARK:
case CHighlight::NOCHECK_MARK:
{
if (m_bUseCheck)
{
HDC hSrcDC = CreateCompatibleDC(hdc);
COLORREF crBkg, crText;
crText = SetTextColor(hdc,(iLastHilite == row) ? clrfgTextHighlight : clrfgText);
crBkg = SetBkColor(hdc,(iLastHilite == row) ? clrbgTextHighlight : clrbgText);
HBITMAP hbmpSave = (HBITMAP) SelectObject(hSrcDC,(pHighlight->m_iType == CHighlight::CHECK_MARK) ? m_hCheck : m_hNoCheck);
RECT rcClip;
::GetClientRect(m_hwnd, &rcClip);
if (rcBounds.bottom <= rcClip.bottom)
{
BitBlt(hdc,(m_LeftMargin - m_iCheckWidth) / 2,rcBounds.top + ((m_nCyChar - m_iCheckHeight) / 2),
m_iCheckWidth,m_iCheckHeight,hSrcDC,0,0,SRCCOPY);
}
SetBkColor(hSrcDC,crBkg);
SetTextColor(hSrcDC,crText);
SelectObject(hSrcDC,hbmpSave);
DeleteDC(hSrcDC);
}
break;
}
case CHighlight::DOT_BOX_TEXT:
::FrameRect(hdc, &rcBounds, hbrDotBox);
break;
case CHighlight::DASH_BOX_TEXT:
::FrameRect(hdc, &rcBounds, hbrDashBox);
break;
case CHighlight::UNDERSCORE_TEXT:
::PatBlt(hdc, rcBounds.left, rcBounds.bottom-1, rcBounds.right - rcBounds.left, 1, PATCOPY);
break;
case CHighlight::OVERSCORE_TEXT:
::PatBlt(hdc, rcBounds.left, rcBounds.top, rcBounds.right - rcBounds.left, 1, PATCOPY);
break;
case CHighlight::BOX_TEXT:
FrameRect(hdc, &rcFrame, hbrFrame);
break;
}
}
}
}
::SelectObject(hdc, hbrSave );
::SelectObject(hdc, hSaveFont);
if (m_fMarquee) RepaintMarquee(hdc);
::DeleteObject(hbrFrame );
::DeleteObject(hbrDotBox );
::DeleteObject(hbrDashBox);
::EndPaint(m_hwnd, &ps);
}
void CTextView::InvalidateImage(long row, long col, long cRows, long cCols)
{
long rowLimit= row+cRows;
long colLimit= col+cCols;
// Undone: When row is -1, the data object has changed its shape.
// In that case cRows and cCols give the new data shape.
//
// For that situation we must notify our owner that the
// scroll bar range must be modified.
if (row < m_lTopLine ) row= m_lTopLine;
if (col < long(m_iLeftCol)) col= long(m_iLeftCol);
long rowLimitImage= m_lTopLine + m_cImageRows;
long colLimitImage= long(m_iLeftCol) + m_cImageCols;
if (rowLimit > rowLimitImage) rowLimit= rowLimitImage;
if (colLimit > colLimitImage) colLimit= colLimitImage;
// if (row >= rowLimit || col >= colLimit) return;
FillBuff();
RECT rc;
GetClientRect(m_hwnd,&rc);
rc.top = TopMargin + m_nCyChar * UINT(row - m_lTopLine);
// This causes the bottom to not be emptied
// rc.bottom = rc.top + m_nCyChar * UINT(rowLimit - row );
InvalidateRect(m_hwnd, &rc, TRUE);
}
//
// MoveToRow:
void CTextView::MoveToRow(long row, BOOL fForceUpdate, BOOL fNotify)
{
if ( m_ptdm == NULL ) return;
LONG oldLine= m_lTopLine;
if (row > m_clFileRows - long(m_cImageFullRows))
row = m_clFileRows - long(m_cImageFullRows);
if (row < 0) row= 0;
long distance= oldLine - row;
if (!distance) return;
BOOL fMarquee= m_fMarquee;
if (fMarquee) RemoveMarquee();
m_lTopLine= row;
FillBuff();
if (fMarquee) SetupMarquee();
int udistance= (distance < 0)? - distance : distance;
if (udistance > m_cImageFullRows) InvalidateRect(m_hwnd, NULL, FALSE);
else
{
HDC hdc= ::GetWindowDC(m_hwnd);
RECT rectText, rectUpdate,rectClip;
::GetClientRect(m_hwnd, &rectText);
::GetClientRect(m_hwnd, &rectClip);
// rectClip.bottom = ((rectText.bottom - rectText.top) / m_nCyChar) * m_nCyChar;
rectText.top += TopMargin;
::ScrollDC(hdc, 0, m_nCyChar * (int) distance, &rectText, &rectClip, NULL, &rectUpdate);
rectUpdate.top -= (rectUpdate.top >= m_nCyChar) ? m_nCyChar : rectUpdate.top;
::InvalidateRect(m_hwnd, &rectUpdate, TRUE);
ReleaseDC(m_hwnd, hdc);
}
if (fForceUpdate) UpdateWindow();
if (fNotify) NotifyInterface(OriginChange);
}
void CTextView::RepaintFrom(long row, long col)
{
m_lTopLine= row;
m_iLeftCol= int(col);
BOOL fMarquee= m_fMarquee;
if (fMarquee) RemoveMarquee();
m_lTopLine= row;
FillBuff();
if (fMarquee) SetupMarquee();
::InvalidateRect(m_hwnd, NULL, TRUE);
::UpdateWindow(m_hwnd);
}
// MoveToCol:
//
void
CTextView::MoveToCol(long col, BOOL fForceUpdate, BOOL fNotify)
{
if ( m_ptdm == NULL ) return;
int oldLeftCol = m_iLeftCol;
if (col > m_clFileCols - long(m_cImageFullCols))
col = m_clFileCols - long(m_cImageFullCols);
if (col < 0) col= 0;
long distance= oldLeftCol - int(col);
if (!distance) return;
BOOL fMarquee= m_fMarquee;
if (fMarquee) RemoveMarquee();
m_iLeftCol= int(col);
FillBuff();
if (fMarquee) SetupMarquee();
int udistance= (distance < 0)? - distance : distance;
if (udistance > m_cImageFullCols)
{
InvalidateRect(m_hwnd, NULL, FALSE);
return;
}
HDC hdcClient= GetWindowDC(m_hwnd);
RECT rectText, rectUpdate,rectClip;
GetClientRect(m_hwnd, &rectText);
GetClientRect(m_hwnd, &rectClip);
rectClip.bottom = ((rectText.bottom - rectText.top) / m_nCyChar) * m_nCyChar;
rectText.top += TopMargin;
::ScrollDC(hdcClient, m_nCxChar * int(distance), 0, &rectText, &rectClip, NULL, &rectUpdate);
::ReleaseDC(m_hwnd, hdcClient);
rectUpdate.top -= (rectUpdate.top >= m_nCyChar) ? m_nCyChar : rectUpdate.top;
::InvalidateRect(m_hwnd, &rectUpdate, TRUE);
if (fForceUpdate) ::UpdateWindow(m_hwnd);
if (fNotify) NotifyInterface(OriginChange);
}
void CTextView::MoveTo(long rowTop, long colLeft, BOOL fNotify)
{
if (rowTop == m_lTopLine && colLeft == m_iLeftCol) return;
UpdateWindow();
MoveToRow(rowTop , FALSE, FALSE);
MoveToCol(colLeft, FALSE, FALSE);
if (fNotify) NotifyInterface(OriginChange);
}
void CTextView::PaddedScrollTo(long rowTop, long colLeft,
unsigned short cRows, unsigned short cCols
)
{
if (m_cImageFullRows > cRows)
{
int cLinesExtra= m_cImageFullRows - cRows;
if (cLinesExtra > m_cLinesScrollContext)
cLinesExtra = m_cLinesScrollContext;
cRows += cLinesExtra;
rowTop -= cLinesExtra/2;
if (rowTop < 0) rowTop= 0;
}
ScrollTo(rowTop, colLeft, cRows, cCols);
}
void CTextView::ScrollTo(int rowTop, int colLeft,
int cRows, int cCols
)
{
int rowNew= m_lTopLine;
if (rowTop <= m_lTopLine) rowNew= rowTop;
else
if (rowTop + cRows >= m_lTopLine+m_cImageFullRows)
{
rowNew= rowTop + cRows - m_cImageFullRows;
if (rowNew > rowTop) rowNew= rowTop;
}
int colNew= m_iLeftCol;
if (colLeft <= m_iLeftCol) colNew= colLeft;
else
if (colLeft + cCols > m_iLeftCol+m_cImageFullCols)
{
colNew= colLeft + cCols - m_cImageFullCols;
if (colNew > colLeft) colNew= colLeft;
}
MoveTo(rowNew, colNew);
}
UINT CTextView::OnNcHitTest(POINTS point)
{
return HTCLIENT;
}
BOOL CTextView::OnSetCursor(HWND hWnd, UINT nHitTest, UINT message)
{
SetCursor((HCURSOR)hcurArrow);
return TRUE;
}
void CTextView::CharacterMouseEvent(UINT nFlags, POINTS point,
long& row, long& col
)
{
long x= point.x - long(m_LeftMargin);
long y= point.y - long( TopMargin);
if (y >= 0) row= y/m_nCyChar;
else row= -((m_nCyChar-1-y)/m_nCyChar);
if (x >= 0) col= x/m_nCxChar;
else col= -((m_nCxChar-1-x)/m_nCxChar);
row+= m_lTopLine;
col+= m_iLeftCol;
if (row < 0) row= 0;
else
if (row >= m_clFileRows) row= m_clFileRows-1;
if (col < 0) col= 0;
else
if (col >= m_clFileCols) col= m_clFileCols-1;
if ( row >= m_lTopLine && row < m_lTopLine + m_cImageFullRows
&& col >= m_iLeftCol && col < m_iLeftCol + m_cImageFullCols
)
{
if (m_fTimerActive)
{
m_fTimerActive= FALSE;
::KillTimer(m_hwnd, m_hTimer);
}
return;
}
if (row < m_lTopLine) MoveToRow(row);
else
if (row >= m_lTopLine+m_cImageFullRows)
MoveToRow(row+1-m_cImageFullRows);
if (col < long(m_iLeftCol)) MoveToCol(col);
else
if (col >= long(m_iLeftCol)+long(m_cImageFullCols))
MoveToCol(col+1-long(m_cImageFullCols));
if (m_fTimerActive) return;
m_fTimerActive= TRUE;
m_hTimer= SetTimer(m_hwnd, MOUSE_TIMER_ID, GetProfileInt("Windows", "KeyboardSpeed", 100), NULL);
}
void CTextView::OnLButtonDown(UINT nFlags, POINTS point)
{
if (::GetFocus() != m_hwnd) ::SetFocus(m_hwnd);
if (!m_ptdm) return;
if (GetCapture()) return;
SetCapture(m_hwnd);
m_fMouseCaptured = TRUE;
m_fTimerActive = FALSE;
long row, col;
CharacterMouseEvent(nFlags, point, row, col);
m_ptdm->OnLButtonDown(nFlags, row, col);
}
void CTextView::OnLButtonUp(UINT nFlags, POINTS point)
{
if (!m_fMouseCaptured) return;
long row, col;
CharacterMouseEvent(nFlags, point, row, col);
int x = (m_LeftMargin - m_iCheckWidth) / 2;
int y = (TopMargin + (row-m_lTopLine) * m_nCyChar) + ((m_nCyChar - m_iCheckHeight) / 2);
int w = m_iCheckWidth;
int h = m_iCheckHeight;
m_ptdm->OnLButtonUp(nFlags, row, col,
m_bUseCheck ? (point.x >= x &&
point.y >= y &&
point.x <= x+w &&
point.y <= y+h) : FALSE
);
if (m_fTimerActive)
{
KillTimer(m_hwnd, m_hTimer);
m_fTimerActive= FALSE;
}
m_fMouseCaptured= FALSE;
::ReleaseCapture();
}
void CTextView::OnLButtonDblClk(UINT nFlags, POINTS point)
{
long row, col;
CharacterMouseEvent(nFlags, point, row, col);
int x = (m_LeftMargin - m_iCheckWidth) / 2;
int y = (TopMargin + (row-m_lTopLine) * m_nCyChar) + ((m_nCyChar - m_iCheckHeight) / 2);
int w = m_iCheckWidth;
int h = m_iCheckHeight;
if (!(m_bUseCheck ? (point.x >= x && point.y >= y &&
point.x <= x+w && point.y <= y+h) : FALSE))
m_ptdm->OnLButtonDblClk(nFlags, row, col);
}
void CTextView::OnMouseMove(UINT nFlags, POINTS point)
{
BOOL fStartedWithTimer= m_fTimerActive;
long row, col;
if (!m_fMouseCaptured) return;
CharacterMouseEvent(nFlags, point, row, col);
if (fStartedWithTimer && m_fTimerActive) return;
m_ptdm->OnMouseMove(nFlags, row, col);
}
void CTextView::OnTimer(UINT nIDEvent)
{
if (m_fMarqueeTimerOn && nIDEvent == m_idTimer)
{
return;
}
if (nIDEvent != m_hTimer) return;
long info= ::GetMessagePos();
POINT point;
point.x = LOWORD(info),
point.y = HIWORD(info);
ScreenToClient(m_hwnd, &point);
long row, col;
POINTS points;
points.x= short(point.x);
points.y= short(point.y);
CharacterMouseEvent(0, points, row, col);
m_ptdm->OnMouseMove(0, row, col);
}
void CTextView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
if (!m_ptdm) return;
m_ptdm->OnKeyDown(this, nChar, nRepCnt, nFlags);
}
void CTextView::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
{
if (!m_ptdm) return;
m_ptdm->OnKeyUp(this, nChar, nRepCnt, nFlags);
}