plugins/consoles/rcons/server/win32/TextView.cpp
changeset 0 7f656887cf89
equal deleted inserted replaced
-1:000000000000 0:7f656887cf89
       
     1 // TextView.cpp
       
     2 // 
       
     3 // Copyright (c) 2010 Accenture. All rights reserved.
       
     4 // This component and the accompanying materials are made available
       
     5 // under the terms of the "Eclipse Public License v1.0"
       
     6 // which accompanies this distribution, and is available
       
     7 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 // 
       
     9 // Initial Contributors:
       
    10 // Accenture - Initial contribution
       
    11 //
       
    12 #include "Misc.h"
       
    13 #include "TextView.h"
       
    14 #include "Window.h"
       
    15 
       
    16 
       
    17 const int KCursorHeight = 2;
       
    18 
       
    19 
       
    20 CTextView* CTextView::New(CWindow& aWindow, CTextBuffer& aTextBuffer, int aWidthInChars, int aHeightInChars)
       
    21 	{
       
    22 	std::auto_ptr<CTextView> self(new(EThrow) CTextView(aWindow, aTextBuffer));
       
    23 	self->Construct(aWidthInChars, aHeightInChars);
       
    24 	return self.release();
       
    25 	}
       
    26 
       
    27 CTextView::~CTextView()
       
    28 	{
       
    29 	}
       
    30 
       
    31 CTextView::CTextView(CWindow& aWindow, CTextBuffer& aTextBuffer)
       
    32 	: 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)
       
    33 	{
       
    34 	}
       
    35 
       
    36 void CTextView::Construct(int aWidthInChars, int aHeightInChars)
       
    37 	{
       
    38 	iFont = (HFONT)GetStockObject(ANSI_FIXED_FONT);
       
    39 	LOGFONT logFont;
       
    40 	if (GetObject(iFont, sizeof(LOGFONT), &logFont) == 0)
       
    41 		{
       
    42 		throw KExceptionConsoleWindowConstructFailed;
       
    43 		}
       
    44 
       
    45 	// ToDo - Figure out why logFont appears to be out by 1.
       
    46 	iCharWidth = 8;//logFont.lfWidth;
       
    47 	iCharHeight = 13;//logFont.lfHeight;
       
    48 	iViewWidth = aWidthInChars * iCharWidth;
       
    49 	iViewHeight = aHeightInChars * iCharHeight;
       
    50 
       
    51 	ResetBufferPos();
       
    52 	ConfigureScrollBars(TRUE);
       
    53 	iTextBuffer.SetObserver(this);
       
    54 	}
       
    55 
       
    56 void CTextView::EnableCursor()
       
    57 	{
       
    58 	if (!iCursorEnabled)
       
    59 		{
       
    60 		iCursorEnabled = TRUE;
       
    61 		SetCursorVisibility();
       
    62 		}
       
    63 	}
       
    64 
       
    65 void CTextView::DisableCursor()
       
    66 	{
       
    67 	if (iCursorEnabled)
       
    68 		{
       
    69 		iCursorEnabled = FALSE;
       
    70 		SetCursorVisibility();
       
    71 		}
       
    72 	}
       
    73 
       
    74 void CTextView::BeginUpdate()
       
    75 	{
       
    76 	ASSERT(!iUpdating);
       
    77 	iUpdating = TRUE;
       
    78 	SetCursorVisibility();
       
    79 	}
       
    80 
       
    81 void CTextView::EndUpdate()
       
    82 	{
       
    83 	ASSERT(iUpdating);
       
    84 	iUpdating = FALSE;
       
    85 	SetCursorVisibility();
       
    86 	}
       
    87 
       
    88 void CTextView::Draw() const
       
    89 	{
       
    90 	PAINTSTRUCT ps;
       
    91 	HDC hdc = BeginPaint(iWindow.Handle(), &ps);
       
    92 	HRGN undrawnRegion = CreateRectRgn(ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom);
       
    93 	--ps.rcPaint.right;
       
    94 	--ps.rcPaint.bottom;
       
    95 	SetMapMode(hdc, MM_TEXT);
       
    96 	HFONT oldFont = (HFONT)SelectObject(hdc, iFont);
       
    97 	int bufferWidth;
       
    98 	int bufferHeight;
       
    99 	iTextBuffer.GetSize(bufferWidth, bufferHeight);
       
   100 	int firstLineToDraw;
       
   101 	int lastLineToDraw;
       
   102 	GetVisibleLines(ps.rcPaint, firstLineToDraw, lastLineToDraw);
       
   103 	RECT selectionRect;
       
   104 	GetSelectionRect(selectionRect);
       
   105 
       
   106 	for (int i = firstLineToDraw; i <= lastLineToDraw; ++i)
       
   107 		{
       
   108 		RECT lineRect;
       
   109 		GetViewRect(0, i, bufferWidth, lineRect);
       
   110 		RECT selectionIntersection;
       
   111 		IntersectRect(&selectionIntersection, &selectionRect, &lineRect);
       
   112 		if (IsRectEmpty(&selectionIntersection))
       
   113 			{
       
   114 			COLORREF origTextColor;
       
   115 			if (iDimmed)
       
   116 				{
       
   117 				origTextColor = SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT));
       
   118 				}
       
   119 			TextOut(hdc, lineRect.left, lineRect.top, iTextBuffer.GetLine(i), bufferWidth);
       
   120 			if (iDimmed)
       
   121 				{
       
   122 				SetTextColor(hdc, origTextColor);
       
   123 				}
       
   124 			}
       
   125 		else
       
   126 			{
       
   127 			LPCTSTR lineText = iTextBuffer.GetLine(i);
       
   128 			RECT drawRect;
       
   129 			drawRect.left = lineRect.left;
       
   130 			drawRect.top = lineRect.top;
       
   131 			drawRect.right = selectionIntersection.left;
       
   132 			drawRect.bottom = selectionIntersection.bottom;
       
   133 			COLORREF origTextColor;
       
   134 			if (iDimmed)
       
   135 				{
       
   136 				origTextColor = SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT));
       
   137 				}
       
   138 			ExtTextOut(hdc, lineRect.left, lineRect.top, ETO_CLIPPED, &drawRect, lineText, bufferWidth, NULL);
       
   139 			if (iDimmed)
       
   140 				{
       
   141 				SetTextColor(hdc, origTextColor);
       
   142 				}
       
   143 			drawRect.left = drawRect.right;
       
   144 			drawRect.right = selectionIntersection.right;
       
   145 			origTextColor = SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
       
   146 			COLORREF origBackgroundColor = SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT));
       
   147 			ExtTextOut(hdc, lineRect.left, lineRect.top, ETO_CLIPPED, &drawRect, lineText, bufferWidth, NULL);
       
   148 			drawRect.left = drawRect.right;
       
   149 			drawRect.right = lineRect.right;
       
   150 			SetTextColor(hdc, origTextColor);
       
   151 			SetBkColor(hdc, origBackgroundColor);
       
   152 			if (iDimmed)
       
   153 				{
       
   154 				origTextColor = SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT));
       
   155 				}
       
   156 			ExtTextOut(hdc, lineRect.left, lineRect.top, ETO_CLIPPED, &drawRect, lineText, bufferWidth, NULL);
       
   157 			if (iDimmed)
       
   158 				{
       
   159 				SetTextColor(hdc, origTextColor);
       
   160 				}
       
   161 			}
       
   162 		HRGN lineRegion = CreateRectRgn(lineRect.left, lineRect.top, lineRect.right, lineRect.bottom);
       
   163 		CombineRgn(undrawnRegion, undrawnRegion, lineRegion, RGN_DIFF);
       
   164 		DeleteObject(lineRegion);
       
   165 		}
       
   166 
       
   167 	HBRUSH brush = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
       
   168 	FillRgn(hdc, undrawnRegion, brush);
       
   169 	DeleteObject(brush);
       
   170 	DeleteObject(undrawnRegion);
       
   171 	SelectObject(hdc, oldFont);
       
   172 	EndPaint(iWindow.Handle(), &ps);
       
   173 	}
       
   174 
       
   175 void CTextView::HandleFocusGained()
       
   176 	{
       
   177 	iFocused = TRUE;
       
   178 	CreateCaret(iWindow.Handle(), (HBITMAP) NULL, iCharWidth, 2);
       
   179 	iCursorHidden = TRUE;
       
   180 	SetCursorPos();
       
   181 	SetCursorVisibility();
       
   182 	}
       
   183 
       
   184 void CTextView::HandleFocusLost()
       
   185 	{
       
   186 	iFocused = FALSE;
       
   187 	DestroyCaret();
       
   188 	}
       
   189 
       
   190 void CTextView::SetSize(int aWidth, int aHeight)
       
   191 	{
       
   192 	iViewWidth = aWidth;
       
   193 	iViewHeight = aHeight;
       
   194 	ResetBufferPos();
       
   195 	SetCursorPos();
       
   196 	ConfigureScrollBars(TRUE);
       
   197 	ReDraw();
       
   198 	}
       
   199 
       
   200 void CTextView::GetSize(int& aWidth, int& aHeight) const
       
   201 	{
       
   202 	aWidth = iViewWidth;
       
   203 	aHeight = iViewHeight;
       
   204 	}
       
   205 
       
   206 void CTextView::SetHorzScrollPosition(int aPosX)
       
   207 	{
       
   208 	int newBufferPosX;
       
   209 	int newBufferPosY;
       
   210 	MapScrollPosToBufPix(aPosX, 0, newBufferPosX, newBufferPosY);
       
   211 	int dX = newBufferPosX - iBufferPosX;
       
   212 	SetBufferPos(newBufferPosX, iBufferPosY);
       
   213 	SetCursorPos();
       
   214 	ScrollWindowEx(iWindow.Handle(), dX, 0, NULL, NULL, NULL, NULL, SW_INVALIDATE);
       
   215 	UpdateWindow(iWindow.Handle());
       
   216 	}
       
   217 
       
   218 void CTextView::SetVertScrollPosition(int aPosY)
       
   219 	{
       
   220 	int newBufferPosX;
       
   221 	int newBufferPosY;
       
   222 	MapScrollPosToBufPix(0, aPosY, newBufferPosX, newBufferPosY);
       
   223 	int dY = newBufferPosY - iBufferPosY;
       
   224 	SetBufferPos(iBufferPosX, newBufferPosY);
       
   225 	SetCursorPos();
       
   226 	ScrollWindowEx(iWindow.Handle(), 0, dY, NULL, NULL, NULL, NULL, SW_INVALIDATE);
       
   227 	UpdateWindow(iWindow.Handle());
       
   228 	}
       
   229 
       
   230 void CTextView::StartSelection(int aPosX, int aPosY)
       
   231 	{
       
   232 	ASSERT(!iSelecting);
       
   233 	iSelecting = TRUE;
       
   234 	RECT invalidRect;
       
   235 	GetSelectionRect(invalidRect);
       
   236 	if (!IsRectEmpty(&invalidRect))
       
   237 		{
       
   238 		InvalidateRect(iWindow.Handle(), &invalidRect, FALSE);
       
   239 		}
       
   240 	MapViewPixToBufPix(aPosX, aPosY, aPosX, aPosY);
       
   241 	MapBufPixToBufChar(aPosX, aPosY, iSelectionX1, iSelectionY1);
       
   242 	iSelectionX2 = iSelectionX1;
       
   243 	iSelectionY2 = iSelectionY1;
       
   244 	GetSelectionRect(invalidRect);
       
   245 	InvalidateRect(iWindow.Handle(), &invalidRect, FALSE);
       
   246 	UpdateWindow(iWindow.Handle());
       
   247 	}
       
   248 
       
   249 void CTextView::AdjustSelection(int aPosX, int aPosY)
       
   250 	{
       
   251 	if (iSelecting)
       
   252 		{
       
   253 		RECT previousSelectionRect;
       
   254 		GetSelectionRect(previousSelectionRect);
       
   255 		MapViewPixToBufPix(aPosX, aPosY, aPosX, aPosY);
       
   256 		MapBufPixToBufChar(aPosX, aPosY, iSelectionX2, iSelectionY2);
       
   257 		int bufferWidth;
       
   258 		int bufferHeight;
       
   259 		iTextBuffer.GetSize(bufferWidth, bufferHeight);
       
   260 		if (iSelectionX2 < 0)
       
   261 			{
       
   262 			iSelectionX2 = 0;
       
   263 			}
       
   264 		if (iSelectionX2 >= bufferWidth)
       
   265 			{
       
   266 			iSelectionX2 = bufferWidth - 1;
       
   267 			}
       
   268 		if (iSelectionY2 < -iNumOverflowLines)
       
   269 			{
       
   270 			iSelectionY2 = -iNumOverflowLines;
       
   271 			}
       
   272 		if (iSelectionY2 >= bufferHeight)
       
   273 			{
       
   274 			iSelectionY2 = bufferHeight - 1;
       
   275 			}
       
   276 		RECT newSelectionRect;
       
   277 		GetSelectionRect(newSelectionRect);
       
   278 
       
   279 		HRGN previousSelectionRegion = CreateRectRgn(previousSelectionRect.left, previousSelectionRect.top, previousSelectionRect.right, previousSelectionRect.bottom);
       
   280 		HRGN region = CreateRectRgn(newSelectionRect.left, newSelectionRect.top, newSelectionRect.right, newSelectionRect.bottom);
       
   281 		CombineRgn(region, region, previousSelectionRegion, RGN_XOR);
       
   282 		DeleteObject(previousSelectionRegion);
       
   283 
       
   284 		RECT regionBox;
       
   285 		if (GetRgnBox(region, &regionBox) != NULLREGION)
       
   286 			{
       
   287 			InvalidateRgn(iWindow.Handle(), region, FALSE);
       
   288 			UpdateWindow(iWindow.Handle());
       
   289 			}
       
   290 		DeleteObject(region);
       
   291 		}
       
   292 	}
       
   293 
       
   294 void CTextView::EndSelection(int aPosX, int aPosY)
       
   295 	{
       
   296 	if (iSelecting)
       
   297 		{
       
   298 		AdjustSelection(aPosX, aPosY);
       
   299 		}
       
   300 	iSelecting = FALSE;
       
   301 	}
       
   302 
       
   303 void CTextView::SelectWord(int aPosX, int aPosY)
       
   304 	{
       
   305 	iSelecting = FALSE;
       
   306 	RECT invalidRect;
       
   307 	GetSelectionRect(invalidRect);
       
   308 	if (!IsRectEmpty(&invalidRect))
       
   309 		{
       
   310 		InvalidateRect(iWindow.Handle(), &invalidRect, FALSE);
       
   311 		}
       
   312 
       
   313 	MapViewPixToBufPix(aPosX, aPosY, aPosX, aPosY);
       
   314 	MapBufPixToBufChar(aPosX, aPosY, iSelectionX1, iSelectionY1);
       
   315 	iSelectionX2 = iSelectionX1;
       
   316 	iSelectionY2 = iSelectionY1;
       
   317 	LPCTSTR linePtr = iTextBuffer.GetLine(iSelectionY1);
       
   318 
       
   319 	if (*(linePtr + iSelectionX1) != TCHAR(' '))
       
   320 		{
       
   321 		// Find the beginning of the word.
       
   322 		while ((*(linePtr + iSelectionX1) != TCHAR(' ')) && (iSelectionX1 > 0))
       
   323 			{
       
   324 			--iSelectionX1;
       
   325 			}
       
   326 		if (*(linePtr + iSelectionX1) == TCHAR(' '))
       
   327 			{
       
   328 			++iSelectionX1;
       
   329 			}
       
   330 		int bufferWidth;
       
   331 		int bufferHeight;
       
   332 		iTextBuffer.GetSize(bufferWidth, bufferHeight);
       
   333 
       
   334 		// Find the end of the word.
       
   335 		while ((*(linePtr + iSelectionX2) != TCHAR(' ')) && (iSelectionX2 < bufferWidth))
       
   336 			{
       
   337 			++iSelectionX2;
       
   338 			}
       
   339 		if (*(linePtr + iSelectionX2) == TCHAR(' '))
       
   340 			{
       
   341 			--iSelectionX2;
       
   342 			}
       
   343 		}
       
   344 
       
   345 	GetSelectionRect(invalidRect);
       
   346 	InvalidateRect(iWindow.Handle(), &invalidRect, FALSE);
       
   347 	}
       
   348 
       
   349 int CTextView::CharHeight() const
       
   350 	{
       
   351 	return iCharHeight;
       
   352 	}
       
   353 
       
   354 int CTextView::CharWidth() const
       
   355 	{
       
   356 	return iCharWidth;
       
   357 	}
       
   358 
       
   359 bool CTextView::SelectionAvailable() const
       
   360 	{
       
   361 	if (iSelectionX1 == -1)
       
   362 		{
       
   363 		ASSERT(iSelectionY1 == -1);
       
   364 		ASSERT(iSelectionX2 == -1);
       
   365 		ASSERT(iSelectionY2 == -1);
       
   366 		return FALSE;
       
   367 		}
       
   368 	return TRUE;
       
   369 	}
       
   370 
       
   371 LPTSTR CTextView::Selection() const
       
   372 	{
       
   373 	ASSERT(iSelectionX1 != -1);
       
   374 	ASSERT(iSelectionY1 != -1);
       
   375 	ASSERT(iSelectionX2 != -1);
       
   376 	ASSERT(iSelectionY2 != -1);
       
   377 	int tlX = min(iSelectionX1, iSelectionX2);
       
   378 	int tlY = min(iSelectionY1, iSelectionY2);
       
   379 	int brX = max(iSelectionX1, iSelectionX2);
       
   380 	int brY = max(iSelectionY1, iSelectionY2);
       
   381 	TCHAR* buf = new TCHAR[((brX - tlX + 3) * (brY - tlY + 1)) + 1];
       
   382 	if (buf)
       
   383 		{
       
   384 		TCHAR* bufPtr = buf;
       
   385 		for (int y = tlY; y <= brY; ++y)
       
   386 			{
       
   387 			LPCTSTR lineText = iTextBuffer.GetLine(y);
       
   388 			int x;
       
   389 			for (x = tlX; x <= brX; ++x)
       
   390 				{
       
   391 				*bufPtr++ = lineText[x];
       
   392 				}
       
   393 			while ((*(bufPtr - 1) == TCHAR(' ')) && (x > tlX))
       
   394 				{	// Remove trailing spaces from line.
       
   395 				--bufPtr;
       
   396 				--x;
       
   397 				}
       
   398 			if (y < brY)
       
   399 				{
       
   400 				*bufPtr++ = TCHAR('\r');
       
   401 				*bufPtr++ = TCHAR('\n');
       
   402 				}
       
   403 			}
       
   404 		*bufPtr = TCHAR('\0');
       
   405 		}
       
   406 	return buf;
       
   407 	}
       
   408 
       
   409 void CTextView::ClearSelection()
       
   410 	{
       
   411 	RECT invalidRect;
       
   412 	GetSelectionRect(invalidRect);
       
   413 	iSelectionX1 = iSelectionY1 = iSelectionX2 = iSelectionY2 = -1;
       
   414 	if (!IsRectEmpty(&invalidRect))
       
   415 		{
       
   416 		InvalidateRect(iWindow.Handle(), &invalidRect, FALSE);
       
   417 		UpdateWindow(iWindow.Handle());
       
   418 		}
       
   419 	}
       
   420 
       
   421 void CTextView::SetDimmed(bool aDimmed)
       
   422 	{
       
   423 	if (!aDimmed != !iDimmed)
       
   424 		{
       
   425 		iDimmed = aDimmed;
       
   426 		if (iDimmed)
       
   427 			{
       
   428 			DisableCursor();
       
   429 			}
       
   430 		else
       
   431 			{
       
   432 			EnableCursor();
       
   433 			}
       
   434 		iWindow.Redraw();
       
   435 		}
       
   436 	}
       
   437 
       
   438 void CTextView::HandleTextBufferChange(int aPosX, int aPosY, PTCHAR aPtr, int aLength)
       
   439 	{
       
   440 	RECT viewRect;
       
   441 	GetViewRect(aPosX, aPosY, aLength, viewRect);
       
   442 	RECT clientRect = {0, 0, iViewWidth, iViewHeight};
       
   443 	RECT intersection;
       
   444 	IntersectRect(&intersection, &clientRect, &viewRect);
       
   445 	if (!IsRectEmpty(&intersection))
       
   446 		{
       
   447 		InvalidateRect(iWindow.Handle(), &intersection, FALSE);
       
   448 		UpdateWindow(iWindow.Handle());
       
   449 		}
       
   450 	}
       
   451 
       
   452 void CTextView::HandleTextBufferScroll()
       
   453 	{
       
   454 	bool doScroll(FALSE);
       
   455 	ASSERT((iNumOverflowLines == iTextBuffer.NumOverflowLines()) || (iNumOverflowLines + 1 == iTextBuffer.NumOverflowLines()));
       
   456 	bool newOverflowLine(iNumOverflowLines != iTextBuffer.NumOverflowLines());
       
   457 	int moveBufferBy(0);
       
   458 
       
   459 	if (BottomLineVisible())
       
   460 		{
       
   461 		if (newOverflowLine)
       
   462 			{
       
   463 			moveBufferBy = -iCharHeight;
       
   464 			}
       
   465 		doScroll = TRUE;
       
   466 		}
       
   467 	else if (TopLineVisible() && !newOverflowLine)
       
   468 		{
       
   469 		doScroll = TRUE;
       
   470 		}
       
   471 	else if (!newOverflowLine)
       
   472 		{
       
   473 		moveBufferBy = iCharHeight;
       
   474 		}
       
   475 
       
   476 	if (newOverflowLine)
       
   477 		{
       
   478 		++iNumOverflowLines;
       
   479 		}
       
   480 
       
   481 	ScrollSelection();
       
   482 
       
   483 	if (moveBufferBy)
       
   484 		{
       
   485 		MoveBuffer(moveBufferBy);
       
   486 		}
       
   487 
       
   488 	if (doScroll)
       
   489 		{
       
   490 		ScrollWindowEx(iWindow.Handle(), 0, -iCharHeight, NULL, NULL, NULL, NULL, SW_INVALIDATE);
       
   491 		UpdateWindow(iWindow.Handle());
       
   492 		}
       
   493 
       
   494 	SetCursorPos();
       
   495 	ConfigureScrollBars(FALSE);
       
   496 	}
       
   497 
       
   498 void CTextView::HandleTextBufferCursorChange()
       
   499 	{
       
   500 	SetCursorPos();
       
   501 	}
       
   502 
       
   503 void CTextView::HandleTextBufferCleared()
       
   504 	{
       
   505 	iNumOverflowLines = 0;
       
   506 	ResetBufferPos();
       
   507 	ConfigureScrollBars(TRUE);
       
   508 	ReDraw();
       
   509 	}
       
   510 
       
   511 void CTextView::SetCursorVisibility()
       
   512 	{
       
   513 	if (iCursorEnabled && !iUpdating && CursorInView())
       
   514 		{
       
   515 		if (iCursorHidden)
       
   516 			{
       
   517 			ShowCaret(iWindow.Handle());
       
   518 			iCursorHidden = FALSE;
       
   519 			}
       
   520 		}
       
   521 	else if (!iCursorHidden)
       
   522 		{
       
   523 		HideCaret(iWindow.Handle());
       
   524 		iCursorHidden = TRUE;
       
   525 		}
       
   526 	}
       
   527 
       
   528 bool CTextView::CursorInView() const
       
   529 	{
       
   530 	int cursorX;
       
   531 	int cursorY;
       
   532 	GetCursorPixelPos(cursorX, cursorY);
       
   533 	RECT cursorRect = {cursorX, cursorY, cursorX + iCharWidth, cursorY + KCursorHeight};
       
   534 	return RectVisible(cursorRect);
       
   535 	}
       
   536 
       
   537 void CTextView::GetCursorPixelPos(int& aX, int& aY) const
       
   538 	{
       
   539 	iTextBuffer.GetCursorPos(aX, aY);
       
   540 	MapBufCharToBufPix(aX, aY, aX, aY);
       
   541 	aY += (iCharHeight - KCursorHeight);
       
   542 	MapBufPixToViewPix(aX, aY, aX, aY);
       
   543 	}
       
   544 
       
   545 void CTextView::SetCursorPos()
       
   546 	{
       
   547 	if (iFocused)
       
   548 		{
       
   549 		int cursorX;
       
   550 		int cursorY;
       
   551 		GetCursorPixelPos(cursorX, cursorY);
       
   552 		SetCaretPos(cursorX, cursorY);
       
   553 		}
       
   554 	}
       
   555 
       
   556 void CTextView::ResetBufferPos()
       
   557 	{
       
   558 	SetBufferPos(0, MinBufferPosY());
       
   559 	}
       
   560 
       
   561 void CTextView::SetBufferPos(int aPosX, int aPosY)
       
   562 	{
       
   563 	iBufferPosX = aPosX;
       
   564 	iBufferPosY = aPosY;
       
   565 	SetCursorVisibility();
       
   566 	}
       
   567 
       
   568 void CTextView::MoveBuffer(int aDiffY)
       
   569 	{
       
   570 	iBufferPosY += aDiffY;
       
   571 	ASSERT(iBufferPosY <= MaxBufferPosY());
       
   572 	int min = MinBufferPosY();
       
   573 	if (iBufferPosY < min)
       
   574 		{
       
   575 		iBufferPosY = min;
       
   576 		}
       
   577 	}
       
   578 
       
   579 void CTextView::ConfigureScrollBars(bool aReset)
       
   580 	{
       
   581 	int bufferWidth;
       
   582 	int bufferHeight;
       
   583 	iTextBuffer.GetSize(bufferWidth, bufferHeight);
       
   584 	bufferHeight += iNumOverflowLines;
       
   585 
       
   586 	int vertMax = (bufferHeight * iCharHeight) - 1;
       
   587 	int horzMax = (bufferWidth * iCharWidth) - 1;
       
   588 
       
   589 	SCROLLINFO scrollInfo;
       
   590 	scrollInfo.cbSize = sizeof(scrollInfo);
       
   591 	scrollInfo.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
       
   592 	scrollInfo.nMin = 0;
       
   593 	scrollInfo.nMax = vertMax;
       
   594 	scrollInfo.nPage = iViewHeight;
       
   595 	if (aReset)
       
   596 		{
       
   597 		scrollInfo.nPos = vertMax;
       
   598 		}
       
   599 	else
       
   600 		{
       
   601 		scrollInfo.nPos = -iBufferPosY;
       
   602 		}
       
   603 	SetScrollInfo(iWindow.Handle(), SB_VERT, &scrollInfo, TRUE);
       
   604 
       
   605 	scrollInfo.fMask = aReset ? SIF_RANGE | SIF_PAGE | SIF_POS : SIF_RANGE | SIF_PAGE;
       
   606 	scrollInfo.nMax = horzMax;
       
   607 	scrollInfo.nPage = iViewWidth;
       
   608 	if (aReset)
       
   609 		{
       
   610 		scrollInfo.nPos = 0;
       
   611 		}
       
   612 	SetScrollInfo(iWindow.Handle(), SB_HORZ, &scrollInfo, TRUE);
       
   613 	}
       
   614 
       
   615 void CTextView::ReDraw() const
       
   616 	{
       
   617 	InvalidateRect(iWindow.Handle(), NULL, FALSE);
       
   618 	}
       
   619 
       
   620 void CTextView::GetViewRect(int aCharPosX, int aCharPosY, int aNumChars, RECT& aRect) const
       
   621 	{
       
   622 	int x;
       
   623 	int y;
       
   624 	MapBufCharToBufPix(aCharPosX, aCharPosY, x, y);
       
   625 	MapBufPixToViewPix(x, y, x, y);
       
   626 	aRect.left = x;
       
   627 	aRect.top = y;
       
   628 	aRect.right = aRect.left + (aNumChars * iCharWidth);
       
   629 	aRect.bottom = aRect.top + iCharHeight;
       
   630 	}
       
   631 
       
   632 void CTextView::GetViewRect(int aCharPosX1, int aCharPosY1, int aCharPosX2, int aCharPosY2, RECT& aRect) const
       
   633 	{
       
   634 	int tlX = min(aCharPosX1, aCharPosX2);
       
   635 	int tlY = min(aCharPosY1, aCharPosY2);
       
   636 	int brX = max(aCharPosX1, aCharPosX2);
       
   637 	int brY = max(aCharPosY1, aCharPosY2);
       
   638 	MapBufCharToBufPix(tlX, tlY, tlX, tlY);
       
   639 	MapBufPixToViewPix(tlX, tlY, tlX, tlY);
       
   640 	MapBufCharToBufPix(brX, brY, brX, brY);
       
   641 	MapBufPixToViewPix(brX, brY, brX, brY);
       
   642 	brX += iCharWidth;
       
   643 	brY += iCharHeight;
       
   644 	aRect.left = tlX;
       
   645 	aRect.top = tlY;
       
   646 	aRect.right = brX;
       
   647 	aRect.bottom = brY;
       
   648 	}
       
   649 
       
   650 bool CTextView::RectVisible(const RECT& aRect) const
       
   651 	{
       
   652 	RECT clientRect = {0, 0, iViewWidth, iViewHeight};
       
   653 	RECT intersection;
       
   654 	IntersectRect(&intersection, &clientRect, &aRect);
       
   655 	return !IsRectEmpty(&intersection);
       
   656 	}
       
   657 
       
   658 bool CTextView::LineVisible(int aLinePos) const
       
   659 	{
       
   660 	int bufWidth;
       
   661 	int bufHeight;
       
   662 	iTextBuffer.GetSize(bufWidth, bufHeight);
       
   663 	RECT rect;
       
   664 	GetViewRect(0, aLinePos, bufWidth, rect);
       
   665 	return RectVisible(rect);
       
   666 	}
       
   667 
       
   668 bool CTextView::TopLineVisible() const
       
   669 	{
       
   670 	return LineVisible(-iNumOverflowLines);
       
   671 	}
       
   672 
       
   673 bool CTextView::BottomLineVisible() const
       
   674 	{
       
   675 	int bufWidth;
       
   676 	int bufHeight;
       
   677 	iTextBuffer.GetSize(bufWidth, bufHeight);
       
   678 	return LineVisible(bufHeight - 1);
       
   679 	}
       
   680 
       
   681 int CTextView::TotalBufferHeight() const
       
   682 	{
       
   683 	int bufferWidth;
       
   684 	int bufferHeight;
       
   685 	iTextBuffer.GetSize(bufferWidth, bufferHeight);
       
   686 	return (bufferHeight + iNumOverflowLines) * iCharHeight;
       
   687 	}
       
   688 
       
   689 int CTextView::MinBufferPosY() const
       
   690 	{
       
   691 	return iViewHeight - TotalBufferHeight();
       
   692 	}
       
   693 
       
   694 int CTextView::MaxBufferPosY() const
       
   695 	{
       
   696 	int minBufferPosY = MinBufferPosY();
       
   697 	if (minBufferPosY <= 0)
       
   698 		{
       
   699 		return 0;
       
   700 		}
       
   701 	return minBufferPosY;
       
   702 	}
       
   703 
       
   704 void CTextView::GetVisibleLines(const RECT& aRect, int& aFrom, int& aTo) const
       
   705 	{
       
   706 	int x;
       
   707 	int y;
       
   708 	MapViewPixToBufPix(aRect.left, aRect.top, x, y);
       
   709 	MapBufPixToBufChar(x, y, x, aFrom);
       
   710 	MapViewPixToBufPix(aRect.right, aRect.bottom, x, y);
       
   711 	MapBufPixToBufChar(x, y, x, aTo);
       
   712 	int bufWidth;
       
   713 	int bufHeight;
       
   714 	iTextBuffer.GetSize(bufWidth, bufHeight);
       
   715 	if (aFrom < -iNumOverflowLines)
       
   716 		{
       
   717 		aFrom = -iNumOverflowLines;
       
   718 		}
       
   719 	if (aFrom >= bufHeight)
       
   720 		{
       
   721 		aFrom = bufHeight - 1;
       
   722 		}
       
   723 	if (aTo >= bufHeight)
       
   724 		{
       
   725 		aTo = bufHeight - 1;
       
   726 		}
       
   727 	}
       
   728 
       
   729 void CTextView::MapBufCharToBufPix(int aBufCharPosX, int aBufCharPosY, int& aBufPixPosX, int& aBufPixPosY) const
       
   730 	{
       
   731 	aBufPixPosX = aBufCharPosX * iCharWidth;
       
   732 	aBufPixPosY = (iNumOverflowLines + aBufCharPosY) * iCharHeight;
       
   733 	}
       
   734 
       
   735 void CTextView::MapBufPixToViewPix(int aBufPixPosX, int aBufPixPosY, int& aViewPixPosX, int& aViewPixPosY) const
       
   736 	{
       
   737 	aViewPixPosX = aBufPixPosX + iBufferPosX;
       
   738 	aViewPixPosY = aBufPixPosY + iBufferPosY;
       
   739 	}
       
   740 
       
   741 void CTextView::MapBufPixToBufChar(int aBufPixPosX, int aBufPixPosY, int& aBufCharPosX, int& aBufCharPosY) const
       
   742 	{
       
   743 	aBufCharPosX = aBufPixPosX / iCharWidth;
       
   744 	aBufCharPosY = (aBufPixPosY / iCharHeight) - iNumOverflowLines;
       
   745 	}
       
   746 
       
   747 void CTextView::MapViewPixToBufPix(int aViewPixPosX, int aViewPixPosY, int& aBufPixPosX, int& aBufPixPosY) const
       
   748 	{
       
   749 	aBufPixPosX = aViewPixPosX - iBufferPosX;
       
   750 	aBufPixPosY = aViewPixPosY - iBufferPosY;
       
   751 	}
       
   752 
       
   753 void CTextView::MapScrollPosToBufPix(int aScrollPosX, int aScrollPosY, int& aBufPixPosX, int& aBufPixPosY) const
       
   754 	{
       
   755 	aBufPixPosX = -aScrollPosX;
       
   756 	aBufPixPosY = -aScrollPosY;
       
   757 	}
       
   758 
       
   759 void CTextView::GetSelectionRect(RECT& aRect) const
       
   760 	{
       
   761 	if (iSelectionX1 == -1)
       
   762 		{
       
   763 		ASSERT(iSelectionY1 == -1);
       
   764 		ASSERT(iSelectionX2 == -1);
       
   765 		ASSERT(iSelectionY2 == -1);
       
   766 		aRect.bottom = aRect.left = aRect.right = aRect.top = 0;
       
   767 		}
       
   768 	else
       
   769 		{
       
   770 		GetViewRect(iSelectionX1, iSelectionY1, iSelectionX2, iSelectionY2, aRect);
       
   771 		}
       
   772 	}
       
   773 
       
   774 void CTextView::ScrollSelection()
       
   775 	{
       
   776 	if (iSelectionX1 == -1)
       
   777 		{
       
   778 		ASSERT(iSelectionY1 == -1);
       
   779 		ASSERT(iSelectionX2 == -1);
       
   780 		ASSERT(iSelectionY2 == -1);
       
   781 		}
       
   782 	else
       
   783 		{
       
   784 		if ((iSelectionY1 == -iNumOverflowLines) && (iSelectionY2 == -iNumOverflowLines))
       
   785 			{
       
   786 			iSelectionX1 = iSelectionY1 = iSelectionX2 = iSelectionY2 = -1;
       
   787 			}
       
   788 		else
       
   789 			{
       
   790 			--iSelectionY1;
       
   791 			--iSelectionY2;
       
   792 			if (iSelectionY1 < -iNumOverflowLines)
       
   793 				{
       
   794 				iSelectionY1 = -iNumOverflowLines;
       
   795 				}
       
   796 			if (iSelectionY2 < -iNumOverflowLines)
       
   797 				{
       
   798 				iSelectionY2 = -iNumOverflowLines;
       
   799 				}
       
   800 			}
       
   801 		}
       
   802 	}
       
   803 
       
   804 void CTextView::ScrollToEndIfNeeded()
       
   805 	{
       
   806 	if (!BottomLineVisible())
       
   807 		{
       
   808 		SetVertScrollPosition(TotalBufferHeight()-iViewHeight);
       
   809 		ConfigureScrollBars(FALSE);
       
   810 		}
       
   811 	}