mirror of
https://github.com/autc04/Retro68.git
synced 2024-06-01 15:41:39 +00:00
Merge pull request #102 from DarwinNE/master
Add a limited degree of support for ANSI commands to the Console library
This commit is contained in:
commit
f962ac5ec2
|
@ -9,7 +9,7 @@ namespace retro
|
|||
int main()
|
||||
{
|
||||
retro::InitConsole();
|
||||
std::string out = "Hello, world.\nEnter \"exit\" to quit.\n";
|
||||
std::string out = "Hello, \033[1mexternal world of \033[0m\033[3mtrue beauty and \033[4mgreatness\033[0m.\nEnter \"exit\" to quit.\n";
|
||||
retro::Console::currentInstance->write(out.data(), out.size());
|
||||
|
||||
std::string in;
|
||||
|
|
17
Console/readme.txt
Normal file
17
Console/readme.txt
Normal file
|
@ -0,0 +1,17 @@
|
|||
IConsole
|
||||
|
||||
This is a slightly improved version of Retro68's Console library, offering a
|
||||
support for a subset of ANSI control sequences.
|
||||
|
||||
Here is a list of the supported sequences and their meaning:
|
||||
|
||||
ESC[0m Reset all text style
|
||||
ESC[1m Bold font (*)
|
||||
ESC[3m Italic font
|
||||
ESC[4m Underline font
|
||||
|
||||
|
||||
NOTES:
|
||||
(*) Obtained with bold + condense style together, so that the character grid
|
||||
remains regular (this way, the width of bold characters remains the same as
|
||||
regular ones).
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright 2012 Wolfgang Thaller.
|
||||
Copyright 2012-2020 Wolfgang Thaller, Davide Bucci
|
||||
|
||||
This file is part of Retro68.
|
||||
|
||||
|
@ -32,11 +32,73 @@ using namespace retro;
|
|||
|
||||
Console *Console::currentInstance = NULL;
|
||||
|
||||
Attributes::Attributes(void)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
void Attributes::reset(void)
|
||||
{
|
||||
cBold=false;
|
||||
cUnderline=false;
|
||||
cItalic=false;
|
||||
}
|
||||
|
||||
bool Attributes::isBold(void) const
|
||||
{
|
||||
return cBold;
|
||||
}
|
||||
|
||||
|
||||
bool Attributes::isUnderline(void) const
|
||||
{
|
||||
return cUnderline;
|
||||
}
|
||||
|
||||
bool Attributes::isItalic(void) const
|
||||
{
|
||||
return cItalic;
|
||||
}
|
||||
|
||||
void Attributes::setBold(const bool v)
|
||||
{
|
||||
cBold=v;
|
||||
}
|
||||
|
||||
void Attributes::setItalic(const bool v)
|
||||
{
|
||||
cItalic=v;
|
||||
}
|
||||
|
||||
void Attributes::setUnderline(const bool v)
|
||||
{
|
||||
cUnderline=v;
|
||||
}
|
||||
|
||||
inline bool operator==(const Attributes& lhs, const Attributes& rhs)
|
||||
{
|
||||
return lhs.isBold()==rhs.isBold() && lhs.isUnderline()==rhs.isUnderline() && lhs.isItalic()==rhs.isItalic();
|
||||
}
|
||||
|
||||
inline bool operator!=(const Attributes& lhs, const Attributes& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
inline bool operator==(const AttributedChar& lhs, const AttributedChar& rhs)
|
||||
{
|
||||
return lhs.c==rhs.c && lhs.attrs==rhs.attrs;
|
||||
}
|
||||
|
||||
inline bool operator!=(const AttributedChar& lhs, const AttributedChar& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
class FontSetup
|
||||
{
|
||||
short saveFont, saveSize;
|
||||
short saveFont, saveSize, saveFace;
|
||||
public:
|
||||
FontSetup()
|
||||
{
|
||||
|
@ -48,15 +110,18 @@ namespace
|
|||
#else
|
||||
saveFont = qd.thePort->txFont;
|
||||
saveSize = qd.thePort->txSize;
|
||||
saveFace = qd.thePort->txFace;
|
||||
#endif
|
||||
TextFont(kFontIDMonaco);
|
||||
TextSize(9);
|
||||
TextFace(normal);
|
||||
}
|
||||
|
||||
~FontSetup()
|
||||
{
|
||||
TextFont(saveFont);
|
||||
TextSize(saveSize);
|
||||
TextFace(saveFace);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -92,11 +157,17 @@ void Console::Init(GrafPtr port, Rect r)
|
|||
rows = (bounds.bottom - bounds.top) / cellSizeY;
|
||||
cols = (bounds.right - bounds.left) / cellSizeX;
|
||||
|
||||
chars = std::vector<char>(rows*cols, ' ');
|
||||
chars = std::vector<AttributedChar>(rows*cols, AttributedChar(' ',currentAttr));
|
||||
|
||||
onscreen = chars;
|
||||
|
||||
cursorX = cursorY = 0;
|
||||
isProcessingEscSequence=false;
|
||||
}
|
||||
|
||||
void Console::SetAttributes(Attributes aa)
|
||||
{
|
||||
TextFace(aa.isBold()?bold+condense:0 + aa.isUnderline()?underline:0 + aa.isItalic()?italic:0);
|
||||
}
|
||||
|
||||
Rect Console::CellRect(short x, short y)
|
||||
|
@ -120,14 +191,13 @@ void Console::DrawCell(short x, short y, bool erase)
|
|||
if(erase)
|
||||
EraseRect(&r);
|
||||
MoveTo(r.left, r.bottom - 2);
|
||||
DrawChar(chars[y * cols + x]);
|
||||
DrawChar(chars[y * cols + x].c);
|
||||
}
|
||||
|
||||
void Console::DrawCells(short x1, short x2, short y, bool erase)
|
||||
{
|
||||
Rect r = { (short) (bounds.top + y * cellSizeY), (short) (bounds.left + x1 * cellSizeX),
|
||||
(short) (bounds.top + (y+1) * cellSizeY), (short) (bounds.left + x2 * cellSizeX) };
|
||||
|
||||
if(cursorDrawn)
|
||||
{
|
||||
if(y == cursorY && x1 <= cursorX && x2 > cursorX)
|
||||
|
@ -140,7 +210,17 @@ void Console::DrawCells(short x1, short x2, short y, bool erase)
|
|||
if(erase)
|
||||
EraseRect(&r);
|
||||
MoveTo(r.left, r.bottom - 2);
|
||||
DrawText(&chars[y * cols + x1], 0, x2 - x1);
|
||||
|
||||
Attributes a=chars[y * cols + x1].attrs;
|
||||
SetAttributes(a);
|
||||
for(int i=x1; i<x2; ++i)
|
||||
{
|
||||
if(a!=chars[y * cols + i].attrs) {
|
||||
a=chars[y * cols + i].attrs;
|
||||
SetAttributes(a);
|
||||
}
|
||||
DrawChar(chars[y * cols + i].c);
|
||||
}
|
||||
}
|
||||
|
||||
void Console::Draw(Rect r)
|
||||
|
@ -175,9 +255,9 @@ void Console::ScrollUp(short n)
|
|||
{
|
||||
cursorY--;
|
||||
std::copy(chars.begin() + cols, chars.end(), chars.begin());
|
||||
std::fill(chars.end() - cols, chars.end(), ' ');
|
||||
std::fill(chars.end() - cols, chars.end(), AttributedChar(' ', currentAttr));
|
||||
std::copy(onscreen.begin() + cols, onscreen.end(), onscreen.begin());
|
||||
std::fill(onscreen.end() - cols, onscreen.end(), ' ');
|
||||
std::fill(onscreen.end() - cols, onscreen.end(), AttributedChar(' ', currentAttr));
|
||||
RgnHandle rgn = NewRgn();
|
||||
ScrollRect(&bounds, 0, -cellSizeY, rgn);
|
||||
DisposeRgn(rgn);
|
||||
|
@ -185,12 +265,63 @@ void Console::ScrollUp(short n)
|
|||
dirtyRect.bottom = dirtyRect.bottom > 0 ? dirtyRect.bottom - 1 : 0;
|
||||
}
|
||||
|
||||
void Console::ProcessEscSequence(char c)
|
||||
{
|
||||
switch(sequenceStep)
|
||||
{
|
||||
case 0:
|
||||
if(c=='[')
|
||||
++sequenceStep;
|
||||
else
|
||||
isProcessingEscSequence=false;
|
||||
break;
|
||||
case 1:
|
||||
++sequenceStep;
|
||||
switch(c)
|
||||
{
|
||||
case '0': // Normal character
|
||||
currentAttr.reset();
|
||||
break;
|
||||
case '1': // Bold
|
||||
currentAttr.setBold(true);
|
||||
break;
|
||||
case '3': // Italic
|
||||
currentAttr.setItalic(true);
|
||||
break;
|
||||
case '4': // Underline
|
||||
currentAttr.setUnderline(true);
|
||||
break;
|
||||
default:
|
||||
isProcessingEscSequence=false;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if(c=='m')
|
||||
isProcessingEscSequence=false;
|
||||
else if(c==';')
|
||||
sequenceStep=1;
|
||||
else
|
||||
isProcessingEscSequence=false;
|
||||
break;
|
||||
default:
|
||||
sequenceStep=0;
|
||||
}
|
||||
}
|
||||
|
||||
void Console::PutCharNoUpdate(char c)
|
||||
{
|
||||
if(isProcessingEscSequence)
|
||||
{
|
||||
ProcessEscSequence(c);
|
||||
return;
|
||||
}
|
||||
InvalidateCursor();
|
||||
switch(c)
|
||||
{
|
||||
case '\033': // Begin of an ANSI escape sequence
|
||||
isProcessingEscSequence=true;
|
||||
sequenceStep=0;
|
||||
break;
|
||||
case '\r':
|
||||
cursorX = 0;
|
||||
break;
|
||||
|
@ -201,7 +332,9 @@ void Console::PutCharNoUpdate(char c)
|
|||
ScrollUp();
|
||||
break;
|
||||
default:
|
||||
chars[cursorY * cols + cursorX] = c;
|
||||
chars[cursorY * cols + cursorX].c = c;
|
||||
chars[cursorY * cols + cursorX].attrs = currentAttr;
|
||||
|
||||
if(dirtyRect.right == 0)
|
||||
{
|
||||
dirtyRect.right = (dirtyRect.left = cursorX) + 1;
|
||||
|
@ -232,12 +365,12 @@ void Console::Update()
|
|||
bool needclear = false;
|
||||
for(short col = dirtyRect.left; col < dirtyRect.right; ++col)
|
||||
{
|
||||
char old = onscreen[row * cols + col];
|
||||
AttributedChar old = onscreen[row * cols + col];
|
||||
if(chars[row * cols + col] != old)
|
||||
{
|
||||
if(start == -1)
|
||||
start = col;
|
||||
if(old != ' ')
|
||||
if(old.c != ' ')
|
||||
needclear = true;
|
||||
onscreen[row * cols + col] = chars[row * cols + col];
|
||||
}
|
||||
|
@ -335,7 +468,6 @@ void Console::InvalidateCursor()
|
|||
if(cursorDrawn)
|
||||
{
|
||||
PortSetter setport(consolePort);
|
||||
|
||||
DrawCell(cursorX, cursorY, true);
|
||||
cursorDrawn = false;
|
||||
}
|
||||
|
@ -372,11 +504,11 @@ void Console::Reshape(Rect newBounds)
|
|||
cursorY = newRows - 1;
|
||||
}
|
||||
|
||||
std::vector<char> newChars(newRows*newCols, ' ');
|
||||
std::vector<AttributedChar> newChars(newRows*newCols, AttributedChar(' ', currentAttr));
|
||||
for(short row = 0; row < newRows && row + upshift < rows; row++)
|
||||
{
|
||||
char *src = &chars[(row+upshift) * cols];
|
||||
char *dst = &newChars[row * newCols];
|
||||
AttributedChar *src = &chars[(row+upshift) * cols];
|
||||
AttributedChar *dst = &newChars[row * newCols];
|
||||
std::copy(src, src + std::min(cols, newCols), dst);
|
||||
}
|
||||
chars.swap(newChars);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright 2012 Wolfgang Thaller.
|
||||
Copyright 2012-2020 Wolfgang Thaller, Davide Bucci
|
||||
|
||||
This file is part of Retro68.
|
||||
|
||||
|
@ -29,6 +29,39 @@
|
|||
|
||||
namespace retro
|
||||
{
|
||||
class Attributes
|
||||
{
|
||||
public:
|
||||
|
||||
bool isBold(void) const;
|
||||
bool isUnderline(void) const;
|
||||
bool isItalic(void) const;
|
||||
|
||||
void setBold(const bool v);
|
||||
void setUnderline(const bool v);
|
||||
void setItalic(const bool v);
|
||||
|
||||
Attributes(void);
|
||||
void reset(void);
|
||||
|
||||
private:
|
||||
|
||||
bool cBold;
|
||||
bool cUnderline;
|
||||
bool cItalic;
|
||||
};
|
||||
|
||||
class AttributedChar
|
||||
{
|
||||
public:
|
||||
char c;
|
||||
Attributes attrs;
|
||||
AttributedChar(char cc, Attributes aa) {c=cc; attrs=aa;}
|
||||
};
|
||||
|
||||
// inline bool operator==(const Attributes& lhs, const Attributes& rhs);
|
||||
// inline bool operator!=(const Attributes& lhs, const Attributes& rhs);
|
||||
|
||||
class Console
|
||||
{
|
||||
public:
|
||||
|
@ -56,8 +89,11 @@ namespace retro
|
|||
private:
|
||||
GrafPtr consolePort = nullptr;
|
||||
Rect bounds;
|
||||
Attributes currentAttr;
|
||||
|
||||
std::vector<char> chars, onscreen;
|
||||
std::vector<AttributedChar> chars, onscreen;
|
||||
bool isProcessingEscSequence;
|
||||
int sequenceStep;
|
||||
|
||||
short cellSizeX;
|
||||
short cellSizeY;
|
||||
|
@ -76,10 +112,13 @@ namespace retro
|
|||
void PutCharNoUpdate(char c);
|
||||
void Update();
|
||||
|
||||
short CalcStartX(short x, short y);
|
||||
Rect CellRect(short x, short y);
|
||||
void DrawCell(short x, short y, bool erase = true);
|
||||
void DrawCells(short x1, short x2, short y, bool erase = true);
|
||||
void ScrollUp(short n = 1);
|
||||
void ProcessEscSequence(char c);
|
||||
void SetAttributes(Attributes aa);
|
||||
|
||||
void InvalidateCursor();
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright 2012 Wolfgang Thaller.
|
||||
Copyright 2012-2020 Wolfgang Thaller, Davide Bucci
|
||||
|
||||
This file is part of Retro68.
|
||||
|
||||
|
@ -35,8 +35,8 @@ namespace
|
|||
ConsoleWindow::ConsoleWindow(Rect r, ConstStr255Param title)
|
||||
{
|
||||
GrafPtr port;
|
||||
|
||||
win = NewWindow(NULL, &r, "\pRetro68 Console", true, 0, (WindowPtr)-1, false, 0);
|
||||
//Retro68 Improved Console
|
||||
win = NewWindow(NULL, &r, "\pRetro68 Console", true, 0, (WindowPtr)-1, true, 0);
|
||||
|
||||
#if !TARGET_API_MAC_CARBON
|
||||
port = win;
|
||||
|
@ -109,7 +109,6 @@ char ConsoleWindow::WaitNextChar()
|
|||
}
|
||||
break;
|
||||
case mouseDown:
|
||||
|
||||
switch(FindWindow(event.where, &eventWin))
|
||||
{
|
||||
case inDrag:
|
||||
|
@ -122,6 +121,12 @@ char ConsoleWindow::WaitNextChar()
|
|||
Reshape(Rect {0, 0, (short) (growResult >> 16), (short) (growResult & 0xFFFF) });
|
||||
}
|
||||
break;
|
||||
case inGoAway:
|
||||
{
|
||||
if (TrackGoAway(eventWin,event.where))
|
||||
exit(0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright 2012 Wolfgang Thaller.
|
||||
Copyright 2012-2020 Wolfgang Thaller, Davide Bucci
|
||||
|
||||
This file is part of Retro68.
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user