diff -r 000000000000 -r 7f656887cf89 plugins/consoles/rcons/server/win32/TextView.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/consoles/rcons/server/win32/TextView.cpp Wed Jun 23 15:52:26 2010 +0100 @@ -0,0 +1,811 @@ +// 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 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); + } + }