Implemented RObjectIx-based memoryaccess APIs.
Upshot is that objinfo now works again on platforms that define FSHELL_NO_DOBJECTIX_SUPPORT.
// TextView.cpp
//
// Copyright (c) 2010 Accenture. All rights reserved.
// This component and the accompanying materials are made available
// under the terms of the "Eclipse Public License v1.0"
// which accompanies this distribution, and is available
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
//
// Initial Contributors:
// Accenture - Initial contribution
//
#include "Misc.h"
#include "TextView.h"
#include "Window.h"
const int KCursorHeight = 2;
CTextView* CTextView::New(CWindow& aWindow, CTextBuffer& aTextBuffer, int aWidthInChars, int aHeightInChars)
{
std::auto_ptr<CTextView> self(new(EThrow) CTextView(aWindow, aTextBuffer));
self->Construct(aWidthInChars, aHeightInChars);
return self.release();
}
CTextView::~CTextView()
{
}
CTextView::CTextView(CWindow& aWindow, CTextBuffer& aTextBuffer)
: iWindow(aWindow), iTextBuffer(aTextBuffer), iViewWidth(0), iViewHeight(0), iNumOverflowLines(aTextBuffer.NumOverflowLines()), iCursorEnabled(TRUE), iUpdating(FALSE), iCursorHidden(FALSE), iFocused(FALSE), iSelectionX1(-1), iSelectionY1(-1), iSelectionX2(-1), iSelectionY2(-1), iSelecting(FALSE), iDimmed(FALSE)
{
}
void CTextView::Construct(int aWidthInChars, int aHeightInChars)
{
iFont = (HFONT)GetStockObject(ANSI_FIXED_FONT);
LOGFONT logFont;
if (GetObject(iFont, sizeof(LOGFONT), &logFont) == 0)
{
throw KExceptionConsoleWindowConstructFailed;
}
// ToDo - Figure out why logFont appears to be out by 1.
iCharWidth = 8;//logFont.lfWidth;
iCharHeight = 13;//logFont.lfHeight;
iViewWidth = aWidthInChars * iCharWidth;
iViewHeight = aHeightInChars * iCharHeight;
ResetBufferPos();
ConfigureScrollBars(TRUE);
iTextBuffer.SetObserver(this);
}
void CTextView::EnableCursor()
{
if (!iCursorEnabled)
{
iCursorEnabled = TRUE;
SetCursorVisibility();
}
}
void CTextView::DisableCursor()
{
if (iCursorEnabled)
{
iCursorEnabled = FALSE;
SetCursorVisibility();
}
}
void CTextView::BeginUpdate()
{
ASSERT(!iUpdating);
iUpdating = TRUE;
SetCursorVisibility();
}
void CTextView::EndUpdate()
{
ASSERT(iUpdating);
iUpdating = FALSE;
SetCursorVisibility();
}
void CTextView::Draw() const
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(iWindow.Handle(), &ps);
HRGN undrawnRegion = CreateRectRgn(ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom);
--ps.rcPaint.right;
--ps.rcPaint.bottom;
SetMapMode(hdc, MM_TEXT);
HFONT oldFont = (HFONT)SelectObject(hdc, iFont);
int bufferWidth;
int bufferHeight;
iTextBuffer.GetSize(bufferWidth, bufferHeight);
int firstLineToDraw;
int lastLineToDraw;
GetVisibleLines(ps.rcPaint, firstLineToDraw, lastLineToDraw);
RECT selectionRect;
GetSelectionRect(selectionRect);
for (int i = firstLineToDraw; i <= lastLineToDraw; ++i)
{
RECT lineRect;
GetViewRect(0, i, bufferWidth, lineRect);
RECT selectionIntersection;
IntersectRect(&selectionIntersection, &selectionRect, &lineRect);
if (IsRectEmpty(&selectionIntersection))
{
COLORREF origTextColor;
if (iDimmed)
{
origTextColor = SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT));
}
TextOut(hdc, lineRect.left, lineRect.top, iTextBuffer.GetLine(i), bufferWidth);
if (iDimmed)
{
SetTextColor(hdc, origTextColor);
}
}
else
{
LPCTSTR lineText = iTextBuffer.GetLine(i);
RECT drawRect;
drawRect.left = lineRect.left;
drawRect.top = lineRect.top;
drawRect.right = selectionIntersection.left;
drawRect.bottom = selectionIntersection.bottom;
COLORREF origTextColor;
if (iDimmed)
{
origTextColor = SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT));
}
ExtTextOut(hdc, lineRect.left, lineRect.top, ETO_CLIPPED, &drawRect, lineText, bufferWidth, NULL);
if (iDimmed)
{
SetTextColor(hdc, origTextColor);
}
drawRect.left = drawRect.right;
drawRect.right = selectionIntersection.right;
origTextColor = SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
COLORREF origBackgroundColor = SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT));
ExtTextOut(hdc, lineRect.left, lineRect.top, ETO_CLIPPED, &drawRect, lineText, bufferWidth, NULL);
drawRect.left = drawRect.right;
drawRect.right = lineRect.right;
SetTextColor(hdc, origTextColor);
SetBkColor(hdc, origBackgroundColor);
if (iDimmed)
{
origTextColor = SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT));
}
ExtTextOut(hdc, lineRect.left, lineRect.top, ETO_CLIPPED, &drawRect, lineText, bufferWidth, NULL);
if (iDimmed)
{
SetTextColor(hdc, origTextColor);
}
}
HRGN lineRegion = CreateRectRgn(lineRect.left, lineRect.top, lineRect.right, lineRect.bottom);
CombineRgn(undrawnRegion, undrawnRegion, lineRegion, RGN_DIFF);
DeleteObject(lineRegion);
}
HBRUSH brush = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
FillRgn(hdc, undrawnRegion, brush);
DeleteObject(brush);
DeleteObject(undrawnRegion);
SelectObject(hdc, oldFont);
EndPaint(iWindow.Handle(), &ps);
}
void CTextView::HandleFocusGained()
{
iFocused = TRUE;
CreateCaret(iWindow.Handle(), (HBITMAP) NULL, iCharWidth, 2);
iCursorHidden = TRUE;
SetCursorPos();
SetCursorVisibility();
}
void CTextView::HandleFocusLost()
{
iFocused = FALSE;
DestroyCaret();
}
void CTextView::SetSize(int aWidth, int aHeight)
{
iViewWidth = aWidth;
iViewHeight = aHeight;
ResetBufferPos();
SetCursorPos();
ConfigureScrollBars(TRUE);
ReDraw();
}
void CTextView::GetSize(int& aWidth, int& aHeight) const
{
aWidth = iViewWidth;
aHeight = iViewHeight;
}
void CTextView::SetHorzScrollPosition(int aPosX)
{
int newBufferPosX;
int newBufferPosY;
MapScrollPosToBufPix(aPosX, 0, newBufferPosX, newBufferPosY);
int dX = newBufferPosX - iBufferPosX;
SetBufferPos(newBufferPosX, iBufferPosY);
SetCursorPos();
ScrollWindowEx(iWindow.Handle(), dX, 0, NULL, NULL, NULL, NULL, SW_INVALIDATE);
UpdateWindow(iWindow.Handle());
}
void CTextView::SetVertScrollPosition(int aPosY)
{
int newBufferPosX;
int newBufferPosY;
MapScrollPosToBufPix(0, aPosY, newBufferPosX, newBufferPosY);
int dY = newBufferPosY - iBufferPosY;
SetBufferPos(iBufferPosX, newBufferPosY);
SetCursorPos();
ScrollWindowEx(iWindow.Handle(), 0, dY, NULL, NULL, NULL, NULL, SW_INVALIDATE);
UpdateWindow(iWindow.Handle());
}
void CTextView::StartSelection(int aPosX, int aPosY)
{
ASSERT(!iSelecting);
iSelecting = TRUE;
RECT invalidRect;
GetSelectionRect(invalidRect);
if (!IsRectEmpty(&invalidRect))
{
InvalidateRect(iWindow.Handle(), &invalidRect, FALSE);
}
MapViewPixToBufPix(aPosX, aPosY, aPosX, aPosY);
MapBufPixToBufChar(aPosX, aPosY, iSelectionX1, iSelectionY1);
iSelectionX2 = iSelectionX1;
iSelectionY2 = iSelectionY1;
GetSelectionRect(invalidRect);
InvalidateRect(iWindow.Handle(), &invalidRect, FALSE);
UpdateWindow(iWindow.Handle());
}
void CTextView::AdjustSelection(int aPosX, int aPosY)
{
if (iSelecting)
{
RECT previousSelectionRect;
GetSelectionRect(previousSelectionRect);
MapViewPixToBufPix(aPosX, aPosY, aPosX, aPosY);
MapBufPixToBufChar(aPosX, aPosY, iSelectionX2, iSelectionY2);
int bufferWidth;
int bufferHeight;
iTextBuffer.GetSize(bufferWidth, bufferHeight);
if (iSelectionX2 < 0)
{
iSelectionX2 = 0;
}
if (iSelectionX2 >= bufferWidth)
{
iSelectionX2 = bufferWidth - 1;
}
if (iSelectionY2 < -iNumOverflowLines)
{
iSelectionY2 = -iNumOverflowLines;
}
if (iSelectionY2 >= bufferHeight)
{
iSelectionY2 = bufferHeight - 1;
}
RECT newSelectionRect;
GetSelectionRect(newSelectionRect);
HRGN previousSelectionRegion = CreateRectRgn(previousSelectionRect.left, previousSelectionRect.top, previousSelectionRect.right, previousSelectionRect.bottom);
HRGN region = CreateRectRgn(newSelectionRect.left, newSelectionRect.top, newSelectionRect.right, newSelectionRect.bottom);
CombineRgn(region, region, previousSelectionRegion, RGN_XOR);
DeleteObject(previousSelectionRegion);
RECT regionBox;
if (GetRgnBox(region, ®ionBox) != NULLREGION)
{
InvalidateRgn(iWindow.Handle(), region, FALSE);
UpdateWindow(iWindow.Handle());
}
DeleteObject(region);
}
}
void CTextView::EndSelection(int aPosX, int aPosY)
{
if (iSelecting)
{
AdjustSelection(aPosX, aPosY);
}
iSelecting = FALSE;
}
void CTextView::SelectWord(int aPosX, int aPosY)
{
iSelecting = FALSE;
RECT invalidRect;
GetSelectionRect(invalidRect);
if (!IsRectEmpty(&invalidRect))
{
InvalidateRect(iWindow.Handle(), &invalidRect, FALSE);
}
MapViewPixToBufPix(aPosX, aPosY, aPosX, aPosY);
MapBufPixToBufChar(aPosX, aPosY, iSelectionX1, iSelectionY1);
iSelectionX2 = iSelectionX1;
iSelectionY2 = iSelectionY1;
LPCTSTR linePtr = iTextBuffer.GetLine(iSelectionY1);
if (*(linePtr + iSelectionX1) != TCHAR(' '))
{
// Find the beginning of the word.
while ((*(linePtr + iSelectionX1) != TCHAR(' ')) && (iSelectionX1 > 0))
{
--iSelectionX1;
}
if (*(linePtr + iSelectionX1) == TCHAR(' '))
{
++iSelectionX1;
}
int bufferWidth;
int bufferHeight;
iTextBuffer.GetSize(bufferWidth, bufferHeight);
// Find the end of the word.
while ((*(linePtr + iSelectionX2) != TCHAR(' ')) && (iSelectionX2 < bufferWidth))
{
++iSelectionX2;
}
if (*(linePtr + iSelectionX2) == TCHAR(' '))
{
--iSelectionX2;
}
}
GetSelectionRect(invalidRect);
InvalidateRect(iWindow.Handle(), &invalidRect, FALSE);
}
int CTextView::CharHeight() const
{
return iCharHeight;
}
int CTextView::CharWidth() const
{
return iCharWidth;
}
bool CTextView::SelectionAvailable() const
{
if (iSelectionX1 == -1)
{
ASSERT(iSelectionY1 == -1);
ASSERT(iSelectionX2 == -1);
ASSERT(iSelectionY2 == -1);
return FALSE;
}
return TRUE;
}
LPTSTR CTextView::Selection() const
{
ASSERT(iSelectionX1 != -1);
ASSERT(iSelectionY1 != -1);
ASSERT(iSelectionX2 != -1);
ASSERT(iSelectionY2 != -1);
int tlX = min(iSelectionX1, iSelectionX2);
int tlY = min(iSelectionY1, iSelectionY2);
int brX = max(iSelectionX1, iSelectionX2);
int brY = max(iSelectionY1, iSelectionY2);
TCHAR* buf = new TCHAR[((brX - tlX + 3) * (brY - tlY + 1)) + 1];
if (buf)
{
TCHAR* bufPtr = buf;
for (int y = tlY; y <= brY; ++y)
{
LPCTSTR lineText = iTextBuffer.GetLine(y);
int x;
for (x = tlX; x <= brX; ++x)
{
*bufPtr++ = lineText[x];
}
while ((*(bufPtr - 1) == TCHAR(' ')) && (x > tlX))
{ // Remove trailing spaces from line.
--bufPtr;
--x;
}
if (y < brY)
{
*bufPtr++ = TCHAR('\r');
*bufPtr++ = TCHAR('\n');
}
}
*bufPtr = TCHAR('\0');
}
return buf;
}
void CTextView::ClearSelection()
{
RECT invalidRect;
GetSelectionRect(invalidRect);
iSelectionX1 = iSelectionY1 = iSelectionX2 = iSelectionY2 = -1;
if (!IsRectEmpty(&invalidRect))
{
InvalidateRect(iWindow.Handle(), &invalidRect, FALSE);
UpdateWindow(iWindow.Handle());
}
}
void CTextView::SetDimmed(bool aDimmed)
{
if (!aDimmed != !iDimmed)
{
iDimmed = aDimmed;
if (iDimmed)
{
DisableCursor();
}
else
{
EnableCursor();
}
iWindow.Redraw();
}
}
void CTextView::HandleTextBufferChange(int aPosX, int aPosY, PTCHAR aPtr, int aLength)
{
RECT viewRect;
GetViewRect(aPosX, aPosY, aLength, viewRect);
RECT clientRect = {0, 0, iViewWidth, iViewHeight};
RECT intersection;
IntersectRect(&intersection, &clientRect, &viewRect);
if (!IsRectEmpty(&intersection))
{
InvalidateRect(iWindow.Handle(), &intersection, FALSE);
UpdateWindow(iWindow.Handle());
}
}
void CTextView::HandleTextBufferScroll()
{
bool doScroll(FALSE);
ASSERT((iNumOverflowLines == iTextBuffer.NumOverflowLines()) || (iNumOverflowLines + 1 == iTextBuffer.NumOverflowLines()));
bool newOverflowLine(iNumOverflowLines != iTextBuffer.NumOverflowLines());
int moveBufferBy(0);
if (BottomLineVisible())
{
if (newOverflowLine)
{
moveBufferBy = -iCharHeight;
}
doScroll = TRUE;
}
else if (TopLineVisible() && !newOverflowLine)
{
doScroll = TRUE;
}
else if (!newOverflowLine)
{
moveBufferBy = iCharHeight;
}
if (newOverflowLine)
{
++iNumOverflowLines;
}
ScrollSelection();
if (moveBufferBy)
{
MoveBuffer(moveBufferBy);
}
if (doScroll)
{
ScrollWindowEx(iWindow.Handle(), 0, -iCharHeight, NULL, NULL, NULL, NULL, SW_INVALIDATE);
UpdateWindow(iWindow.Handle());
}
SetCursorPos();
ConfigureScrollBars(FALSE);
}
void CTextView::HandleTextBufferCursorChange()
{
SetCursorPos();
}
void CTextView::HandleTextBufferCleared()
{
iNumOverflowLines = 0;
ResetBufferPos();
ConfigureScrollBars(TRUE);
ReDraw();
}
void CTextView::SetCursorVisibility()
{
if (iCursorEnabled && !iUpdating && CursorInView())
{
if (iCursorHidden)
{
ShowCaret(iWindow.Handle());
iCursorHidden = FALSE;
}
}
else if (!iCursorHidden)
{
HideCaret(iWindow.Handle());
iCursorHidden = TRUE;
}
}
bool CTextView::CursorInView() const
{
int cursorX;
int cursorY;
GetCursorPixelPos(cursorX, cursorY);
RECT cursorRect = {cursorX, cursorY, cursorX + iCharWidth, cursorY + KCursorHeight};
return RectVisible(cursorRect);
}
void CTextView::GetCursorPixelPos(int& aX, int& aY) const
{
iTextBuffer.GetCursorPos(aX, aY);
MapBufCharToBufPix(aX, aY, aX, aY);
aY += (iCharHeight - KCursorHeight);
MapBufPixToViewPix(aX, aY, aX, aY);
}
void CTextView::SetCursorPos()
{
if (iFocused)
{
int cursorX;
int cursorY;
GetCursorPixelPos(cursorX, cursorY);
SetCaretPos(cursorX, cursorY);
}
}
void CTextView::ResetBufferPos()
{
SetBufferPos(0, MinBufferPosY());
}
void CTextView::SetBufferPos(int aPosX, int aPosY)
{
iBufferPosX = aPosX;
iBufferPosY = aPosY;
SetCursorVisibility();
}
void CTextView::MoveBuffer(int aDiffY)
{
iBufferPosY += aDiffY;
ASSERT(iBufferPosY <= MaxBufferPosY());
int min = MinBufferPosY();
if (iBufferPosY < min)
{
iBufferPosY = min;
}
}
void CTextView::ConfigureScrollBars(bool aReset)
{
int bufferWidth;
int bufferHeight;
iTextBuffer.GetSize(bufferWidth, bufferHeight);
bufferHeight += iNumOverflowLines;
int vertMax = (bufferHeight * iCharHeight) - 1;
int horzMax = (bufferWidth * iCharWidth) - 1;
SCROLLINFO scrollInfo;
scrollInfo.cbSize = sizeof(scrollInfo);
scrollInfo.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
scrollInfo.nMin = 0;
scrollInfo.nMax = vertMax;
scrollInfo.nPage = iViewHeight;
if (aReset)
{
scrollInfo.nPos = vertMax;
}
else
{
scrollInfo.nPos = -iBufferPosY;
}
SetScrollInfo(iWindow.Handle(), SB_VERT, &scrollInfo, TRUE);
scrollInfo.fMask = aReset ? SIF_RANGE | SIF_PAGE | SIF_POS : SIF_RANGE | SIF_PAGE;
scrollInfo.nMax = horzMax;
scrollInfo.nPage = iViewWidth;
if (aReset)
{
scrollInfo.nPos = 0;
}
SetScrollInfo(iWindow.Handle(), SB_HORZ, &scrollInfo, TRUE);
}
void CTextView::ReDraw() const
{
InvalidateRect(iWindow.Handle(), NULL, FALSE);
}
void CTextView::GetViewRect(int aCharPosX, int aCharPosY, int aNumChars, RECT& aRect) const
{
int x;
int y;
MapBufCharToBufPix(aCharPosX, aCharPosY, x, y);
MapBufPixToViewPix(x, y, x, y);
aRect.left = x;
aRect.top = y;
aRect.right = aRect.left + (aNumChars * iCharWidth);
aRect.bottom = aRect.top + iCharHeight;
}
void CTextView::GetViewRect(int aCharPosX1, int aCharPosY1, int aCharPosX2, int aCharPosY2, RECT& aRect) const
{
int tlX = min(aCharPosX1, aCharPosX2);
int tlY = min(aCharPosY1, aCharPosY2);
int brX = max(aCharPosX1, aCharPosX2);
int brY = max(aCharPosY1, aCharPosY2);
MapBufCharToBufPix(tlX, tlY, tlX, tlY);
MapBufPixToViewPix(tlX, tlY, tlX, tlY);
MapBufCharToBufPix(brX, brY, brX, brY);
MapBufPixToViewPix(brX, brY, brX, brY);
brX += iCharWidth;
brY += iCharHeight;
aRect.left = tlX;
aRect.top = tlY;
aRect.right = brX;
aRect.bottom = brY;
}
bool CTextView::RectVisible(const RECT& aRect) const
{
RECT clientRect = {0, 0, iViewWidth, iViewHeight};
RECT intersection;
IntersectRect(&intersection, &clientRect, &aRect);
return !IsRectEmpty(&intersection);
}
bool CTextView::LineVisible(int aLinePos) const
{
int bufWidth;
int bufHeight;
iTextBuffer.GetSize(bufWidth, bufHeight);
RECT rect;
GetViewRect(0, aLinePos, bufWidth, rect);
return RectVisible(rect);
}
bool CTextView::TopLineVisible() const
{
return LineVisible(-iNumOverflowLines);
}
bool CTextView::BottomLineVisible() const
{
int bufWidth;
int bufHeight;
iTextBuffer.GetSize(bufWidth, bufHeight);
return LineVisible(bufHeight - 1);
}
int CTextView::TotalBufferHeight() const
{
int bufferWidth;
int bufferHeight;
iTextBuffer.GetSize(bufferWidth, bufferHeight);
return (bufferHeight + iNumOverflowLines) * iCharHeight;
}
int CTextView::MinBufferPosY() const
{
return iViewHeight - TotalBufferHeight();
}
int CTextView::MaxBufferPosY() const
{
int minBufferPosY = MinBufferPosY();
if (minBufferPosY <= 0)
{
return 0;
}
return minBufferPosY;
}
void CTextView::GetVisibleLines(const RECT& aRect, int& aFrom, int& aTo) const
{
int x;
int y;
MapViewPixToBufPix(aRect.left, aRect.top, x, y);
MapBufPixToBufChar(x, y, x, aFrom);
MapViewPixToBufPix(aRect.right, aRect.bottom, x, y);
MapBufPixToBufChar(x, y, x, aTo);
int bufWidth;
int bufHeight;
iTextBuffer.GetSize(bufWidth, bufHeight);
if (aFrom < -iNumOverflowLines)
{
aFrom = -iNumOverflowLines;
}
if (aFrom >= bufHeight)
{
aFrom = bufHeight - 1;
}
if (aTo >= bufHeight)
{
aTo = bufHeight - 1;
}
}
void CTextView::MapBufCharToBufPix(int aBufCharPosX, int aBufCharPosY, int& aBufPixPosX, int& aBufPixPosY) const
{
aBufPixPosX = aBufCharPosX * iCharWidth;
aBufPixPosY = (iNumOverflowLines + aBufCharPosY) * iCharHeight;
}
void CTextView::MapBufPixToViewPix(int aBufPixPosX, int aBufPixPosY, int& aViewPixPosX, int& aViewPixPosY) const
{
aViewPixPosX = aBufPixPosX + iBufferPosX;
aViewPixPosY = aBufPixPosY + iBufferPosY;
}
void CTextView::MapBufPixToBufChar(int aBufPixPosX, int aBufPixPosY, int& aBufCharPosX, int& aBufCharPosY) const
{
aBufCharPosX = aBufPixPosX / iCharWidth;
aBufCharPosY = (aBufPixPosY / iCharHeight) - iNumOverflowLines;
}
void CTextView::MapViewPixToBufPix(int aViewPixPosX, int aViewPixPosY, int& aBufPixPosX, int& aBufPixPosY) const
{
aBufPixPosX = aViewPixPosX - iBufferPosX;
aBufPixPosY = aViewPixPosY - iBufferPosY;
}
void CTextView::MapScrollPosToBufPix(int aScrollPosX, int aScrollPosY, int& aBufPixPosX, int& aBufPixPosY) const
{
aBufPixPosX = -aScrollPosX;
aBufPixPosY = -aScrollPosY;
}
void CTextView::GetSelectionRect(RECT& aRect) const
{
if (iSelectionX1 == -1)
{
ASSERT(iSelectionY1 == -1);
ASSERT(iSelectionX2 == -1);
ASSERT(iSelectionY2 == -1);
aRect.bottom = aRect.left = aRect.right = aRect.top = 0;
}
else
{
GetViewRect(iSelectionX1, iSelectionY1, iSelectionX2, iSelectionY2, aRect);
}
}
void CTextView::ScrollSelection()
{
if (iSelectionX1 == -1)
{
ASSERT(iSelectionY1 == -1);
ASSERT(iSelectionX2 == -1);
ASSERT(iSelectionY2 == -1);
}
else
{
if ((iSelectionY1 == -iNumOverflowLines) && (iSelectionY2 == -iNumOverflowLines))
{
iSelectionX1 = iSelectionY1 = iSelectionX2 = iSelectionY2 = -1;
}
else
{
--iSelectionY1;
--iSelectionY2;
if (iSelectionY1 < -iNumOverflowLines)
{
iSelectionY1 = -iNumOverflowLines;
}
if (iSelectionY2 < -iNumOverflowLines)
{
iSelectionY2 = -iNumOverflowLines;
}
}
}
}
void CTextView::ScrollToEndIfNeeded()
{
if (!BottomLineVisible())
{
SetVertScrollPosition(TotalBufferHeight()-iViewHeight);
ConfigureScrollBars(FALSE);
}
}