Tidied iocli exports, build macro tweaks.
Removed 4 overloads of CCommandBase::RunCommand[L] that are no longer used at all, and changed one more to not be exported as it's only used internally to iocli.dll.
fixed builds on platforms that don't support btrace or any form of tracing.
// TextBuffer.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 <fcntl.h>
#include <io.h>
#include <sys/stat.h>
#include "TextBuffer.h"
const int KTabSize = 4;
CTextBuffer* CTextBuffer::New(int aWidth, int aHeight, int aMaxNumOverflowLines)
{
std::auto_ptr<CTextBuffer> self(new(EThrow) CTextBuffer(aWidth, aHeight, aMaxNumOverflowLines));
self->Construct();
return self.release();
}
CTextBuffer::~CTextBuffer()
{
delete iBuffer;
}
void CTextBuffer::SetObserver(MTextBufferObserver* aObserver)
{
iObserver = aObserver;
}
int StringLength(LPCTSTR aStart, LPCTSTR aEnd)
{
return (aEnd - aStart) + 1;
}
void CTextBuffer::Write(LPCTSTR aString, int aLength)
{
LPCTSTR startBlock = aString;
LPCTSTR ptr = aString;
LPCTSTR end = aString + aLength - 1;
int numCharsToLineEnd = NumCharsToLineEnd();
while (ptr <= end)
{
if (!IsOrdinaryChar(*ptr))
{
// Not an ordinary character, so write the block we've gathered so far.
if (StringLength(startBlock, ptr - 1) > 0)
{
WriteBlock(startBlock, StringLength(startBlock, ptr - 1));
}
// Write the special character.
WriteSpecialChar(*ptr);
// Setup variables for the next block.
startBlock = ptr + 1;
numCharsToLineEnd = NumCharsToLineEnd();
}
else if (StringLength(startBlock, ptr) == numCharsToLineEnd)
{
// Reached line end, so write the block we've gathered so far.
ASSERT(numCharsToLineEnd > 0);
WriteBlock(startBlock, numCharsToLineEnd);
// Setup variables for the next block.
startBlock = ptr + 1;
numCharsToLineEnd = NumCharsToLineEnd();
}
else if (ptr == end)
{
// Reached end of buffer.
if (StringLength(startBlock, ptr) > 0)
{
WriteBlock(startBlock, StringLength(startBlock, ptr));
}
}
++ptr;
}
}
void CTextBuffer::GetCursorPos(int& aX, int& aY) const
{
aX = iCursorPosX;
aY = iCursorPosY;
}
void CTextBuffer::SetAbsCursorPos(int aX, int aY)
{
MoveCursor(aX, aY);
}
void CTextBuffer::SetRelCursorPos(int aX, int aY)
{
MoveCursor(iCursorPosX + aX, iCursorPosY + aY);
}
void CTextBuffer::GetSize(int& aWidth, int& aHeight) const
{
aWidth = iWidth;
aHeight = iHeight;
}
int CTextBuffer::NumOverflowLines() const
{
return iNumOverflowLines;
}
void CTextBuffer::Clear()
{
ClearBuffer();
MoveCursor(0, 0);
}
void CTextBuffer::ClearToEndOfLine()
{
const PTCHAR start = CursorPtr();
PTCHAR ptr = start;
const PTCHAR end = LineEndPtr();
while (ptr <= end)
{
*ptr++ = TCHAR(' ');
}
if (iObserver)
{
iObserver->HandleTextBufferChange(iCursorPosX, iCursorPosY, start, StringLength(start, end));
}
}
CTextBuffer::CTextBuffer(int aWidth, int aHeight, int aMaxNumOverflowLines)
: iObserver(NULL), iBuffer(NULL), iWidth(aWidth), iHeight(aHeight), iMaxNumOverflowLines(aMaxNumOverflowLines), iNumOverflowLines(0), iCursorPosX(0), iCursorPosY(0), iCaptureFile(0)
{
}
void CTextBuffer::Construct()
{
iBuffer = new(EThrow) TCHAR[iWidth * (iHeight + iMaxNumOverflowLines)];
ClearBuffer();
}
void CTextBuffer::MoveCursor(int aNewX, int aNewY)
{
ASSERT((aNewX >= 0) && (aNewY >= 0));
if ((aNewX >= 0) && (aNewY >= 0))
{
if (aNewX < iWidth)
{
iCursorPosX = aNewX;
}
if (aNewY < iHeight)
{
iCursorPosY = aNewY;
}
if (iObserver)
{
iObserver->HandleTextBufferCursorChange();
}
}
}
PTCHAR CTextBuffer::CursorPtr() const
{
return iBuffer + (((iMaxNumOverflowLines + iCursorPosY) * iWidth) + iCursorPosX);
}
PTCHAR CTextBuffer::LineEndPtr() const
{
return iBuffer + (((iMaxNumOverflowLines + iCursorPosY) * iWidth) + (iWidth - 1));
}
PTCHAR CTextBuffer::BufEndPtr() const
{
return iBuffer + (iWidth * (iHeight + iMaxNumOverflowLines));
}
void CTextBuffer::WriteSpecialChar(TCHAR aChar)
{
switch(aChar)
{
case 0x00: // Null.
break;
case 0x07: // Bell.
break;
case 0x08: // Backspace.
case 0x7f: // Delete.
BackSpace();
break;
case 0x09:
HorizontalTab();
break;
case 0x0a:
LineFeed();
break;
case 0x0b: // Vertical tab.
break;
case 0x0c:
FormFeed();
break;
case 0x0d:
CarriageReturn();
break;
default:
ASSERT(FALSE);
}
}
void CTextBuffer::WriteBlock(LPCTSTR aString, int aLength)
{
PTCHAR cursorPtr = CursorPtr();
PTCHAR ptr = cursorPtr;
for (int i = 0; i < aLength; ++i)
{
*ptr++ = aString[i];
}
if (iObserver)
{
iObserver->HandleTextBufferChange(iCursorPosX, iCursorPosY, cursorPtr, aLength);
}
if ((iCursorPosX + aLength) == iWidth)
{
MoveCursor(iWidth - 1, iCursorPosY);
CursorRight();
}
else
{
MoveCursor(iCursorPosX + aLength, iCursorPosY);
}
}
bool CTextBuffer::IsOrdinaryChar(TCHAR aChar) const
{
switch(aChar)
{
case 0x00: // Null.
case 0x07: // Bell.
case 0x08: // Backspace.
case 0x7f: // Delete.
case 0x09: // Tab.
case 0x0a: // Line feed.
case 0x0b: // Vertical tab.
case 0x0c: // Form feed.
case 0x0d: // Carriage return.
return FALSE;
default:
return TRUE;
}
}
int CTextBuffer::NumCharsToLineEnd() const
{
return iWidth - iCursorPosX;
}
void CTextBuffer::ClearBuffer()
{
PTCHAR bufPtr = iBuffer;
PTCHAR end = BufEndPtr();
while (bufPtr < end )
{
*bufPtr++ = TCHAR(' ');
}
iNumOverflowLines = 0;
if (iObserver)
{
iObserver->HandleTextBufferCleared();
}
}
LPCTSTR CTextBuffer::GetLine(int aPos) const
{
ASSERT(aPos >= -iNumOverflowLines);
ASSERT(aPos < iHeight);
return iBuffer + ((iMaxNumOverflowLines + aPos) * iWidth);
}
void CTextBuffer::CaptureToFile(LPCTSTR aFileName)
{
ASSERT(iCaptureFile == 0);
iCaptureFile = _wopen(aFileName, _O_CREAT | _O_WRONLY | _O_BINARY, _S_IWRITE);
if (iCaptureFile == -1)
{
iCaptureFile = 0;
throw KExceptionFailedToCreateCaptureFile;
}
WriteOverflowLinesToCaptureFile();
}
void CTextBuffer::StopCaptureToFile()
{
if (iCaptureFile)
{
WriteBufferToCaptureFile();
_close(iCaptureFile);
iCaptureFile = 0;
}
}
bool CTextBuffer::IsCapturingToFile() const
{
return !(iCaptureFile == 0);
}
void CTextBuffer::CursorLeft()
{
if (iCursorPosX > 0)
{
// Not yet reached beginning of line.
MoveCursor(iCursorPosX - 1, iCursorPosY);
}
else if (iCursorPosY > 0)
{
// Reached beginning of line, so jump to end of line above.
MoveCursor(iWidth - 1, iCursorPosY - 1);
}
else
{
// Reached the top left corner of the console - do nothing.
}
}
void CTextBuffer::CursorRight()
{
if (iCursorPosX < (iWidth - 1))
{
// Not yet reached the end of the line.
MoveCursor(iCursorPosX + 1, iCursorPosY);
}
else if (iCursorPosY < (iHeight - 1))
{
// Reached the end of the line and there's space below - jump to the beginning of the line below.
MoveCursor(0, iCursorPosY + 1);
}
else
{
// Reached the end of the line and there's no space below - scroll up a line and jump to the beginning of the newly exposed line.
ScrollUp();
MoveCursor(0, iCursorPosY);
}
}
void CTextBuffer::FormFeed()
{
Clear();
}
void CTextBuffer::LineFeed()
{
if (iCursorPosY < (iHeight - 1))
{
MoveCursor(0, iCursorPosY + 1);
}
else
{
ScrollUp();
MoveCursor(0, iCursorPosY);
}
}
void CTextBuffer::CarriageReturn()
{
MoveCursor(0, iCursorPosY);
}
void CTextBuffer::BackSpace()
{
if (!((iCursorPosX == 0) && (iCursorPosY == 0)))
{
CursorLeft();
WriteBlock(TEXT(" "), 1);
CursorLeft();
}
}
void CTextBuffer::HorizontalTab()
{
MoveCursor(iCursorPosX - (iCursorPosX % KTabSize) + KTabSize, iCursorPosY);
if (iCursorPosX > (iWidth - 1))
{
CarriageReturn();
LineFeed();
}
}
void CTextBuffer::ScrollUp()
{
WriteLineToCaptureFile(GetLine(0));
PTCHAR dst = iBuffer;
PTCHAR end = BufEndPtr();
PTCHAR src = dst + iWidth;
while (src < end)
{
*dst++ = *src++;
}
while (dst < end)
{
*dst++ = TCHAR(' ');
}
if (iNumOverflowLines < iMaxNumOverflowLines)
{
++iNumOverflowLines;
}
if (iObserver)
{
iObserver->HandleTextBufferScroll();
}
}
void CTextBuffer::WriteLineToCaptureFile(LPCTSTR aLinePtr)
{
if (iCaptureFile)
{
LPCTSTR lineEnd = aLinePtr + iWidth - 1;
while ((*lineEnd == TCHAR(' ')) && (lineEnd > aLinePtr))
{
--lineEnd;
}
if (lineEnd == aLinePtr)
{
if (_write(iCaptureFile, "\r\n", 2) != 2)
{
_close(iCaptureFile);
iCaptureFile = 0;
throw KExceptionFailedToWriteToCaptureFile;
}
}
else
{
const int lineLength = (lineEnd - aLinePtr) + 3;
std::auto_ptr<char> narrowBuf(new(EThrow) char[lineLength]);
char* narrowBufPtr = narrowBuf.get();
while (aLinePtr <= lineEnd)
{
*narrowBufPtr++ = (char)*aLinePtr++;
}
*narrowBufPtr++ = '\r';
*narrowBufPtr = '\n';
if (_write(iCaptureFile, narrowBuf.get(), lineLength) != lineLength)
{
_close(iCaptureFile);
iCaptureFile = 0;
throw KExceptionFailedToWriteToCaptureFile;
}
}
}
}
void CTextBuffer::WriteOverflowLinesToCaptureFile()
{
for (int i = -iNumOverflowLines; i < 0; ++i)
{
WriteLineToCaptureFile(GetLine(i));
}
}
void CTextBuffer::WriteBufferToCaptureFile()
{
for (int i = 0; i < iHeight; ++i)
{
WriteLineToCaptureFile(GetLine(i));
}
}