mirror of
https://github.com/autc04/Retro68.git
synced 2024-11-28 21:49:33 +00:00
Merge pull request #103 from DarwinNE/master
Implement escape sequence to change window title
This commit is contained in:
commit
cf75b4d9ba
@ -9,7 +9,8 @@ namespace retro
|
||||
int main()
|
||||
{
|
||||
retro::InitConsole();
|
||||
std::string out = "Hello, \033[1mexternal world of \033[0m\033[3mtrue beauty and \033[4mgreatness\033[0m.\nEnter \"exit\" to quit.\n";
|
||||
std::string out = "\033]0;Hello world win\007Hello, \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;
|
||||
|
@ -1,7 +1,6 @@
|
||||
IConsole
|
||||
Console
|
||||
|
||||
This is a slightly improved version of Retro68's Console library, offering a
|
||||
support for a subset of ANSI control sequences.
|
||||
This library provides a simple console library, offering a limited support for ANSI control sequences.
|
||||
|
||||
Here is a list of the supported sequences and their meaning:
|
||||
|
||||
@ -10,8 +9,10 @@ ESC[1m Bold font (*)
|
||||
ESC[3m Italic font
|
||||
ESC[4m Underline font
|
||||
|
||||
ESC]0;NewnameBEL Set the window title to "Newname" (**)
|
||||
|
||||
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).
|
||||
(**) BEL is ASCII character 7.
|
||||
|
@ -30,6 +30,9 @@
|
||||
|
||||
using namespace retro;
|
||||
|
||||
const char BEL = 7;
|
||||
const char MAX_LEN = 250;
|
||||
|
||||
Console *Console::currentInstance = NULL;
|
||||
|
||||
Attributes::Attributes(void)
|
||||
@ -162,7 +165,7 @@ void Console::Init(GrafPtr port, Rect r)
|
||||
onscreen = chars;
|
||||
|
||||
cursorX = cursorY = 0;
|
||||
isProcessingEscSequence=false;
|
||||
sequenceState=State::noSequence;
|
||||
}
|
||||
|
||||
void Console::SetAttributes(Attributes aa)
|
||||
@ -265,18 +268,22 @@ void Console::ScrollUp(short n)
|
||||
dirtyRect.bottom = dirtyRect.bottom > 0 ? dirtyRect.bottom - 1 : 0;
|
||||
}
|
||||
|
||||
void Console::ProcessEscSequence(char c)
|
||||
bool Console::ProcessEscSequence(char c)
|
||||
{
|
||||
switch(sequenceStep)
|
||||
switch(sequenceState)
|
||||
{
|
||||
case 0:
|
||||
case State::noSequence:
|
||||
return false; // Break is not needed there.
|
||||
case State::waitingForSequenceStart:
|
||||
if(c=='[')
|
||||
++sequenceStep;
|
||||
sequenceState=State::waitingForControlSequence;
|
||||
else if(c==']')
|
||||
sequenceState=State::waitingForOSCStart;
|
||||
else
|
||||
isProcessingEscSequence=false;
|
||||
sequenceState=State::noSequence; // Unrecognized sequence
|
||||
break;
|
||||
case 1:
|
||||
++sequenceStep;
|
||||
case State::waitingForControlSequence:
|
||||
sequenceState=State::waitingForM;
|
||||
switch(c)
|
||||
{
|
||||
case '0': // Normal character
|
||||
@ -292,35 +299,59 @@ void Console::ProcessEscSequence(char c)
|
||||
currentAttr.setUnderline(true);
|
||||
break;
|
||||
default:
|
||||
isProcessingEscSequence=false;
|
||||
sequenceState=State::noSequence; // Unrecognized sequence
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
case State::waitingForM:
|
||||
if(c=='m')
|
||||
isProcessingEscSequence=false;
|
||||
else if(c==';')
|
||||
sequenceStep=1;
|
||||
sequenceState=State::noSequence; // Normal end of sequence
|
||||
else
|
||||
isProcessingEscSequence=false;
|
||||
sequenceState=State::noSequence; // Unrecognized sequence (but we end it anyway!)
|
||||
break;
|
||||
case State::waitingForOSCStart:
|
||||
if(c=='0')
|
||||
sequenceState=State::waitingForSemicolon;
|
||||
else
|
||||
sequenceState=State::noSequence; // Normal end of sequence
|
||||
break;
|
||||
case State::waitingForSemicolon:
|
||||
if(c==';')
|
||||
{
|
||||
sequenceState=State::inWindowName;
|
||||
windowName="";
|
||||
}
|
||||
else
|
||||
sequenceState=State::noSequence; // Normal end of sequence
|
||||
break;
|
||||
case State::inWindowName:
|
||||
if(c==BEL)
|
||||
{
|
||||
setWindowName(std::move(windowName));
|
||||
sequenceState=State::noSequence; // Normal end of sequence
|
||||
}
|
||||
else
|
||||
{
|
||||
if(windowName.size() < MAX_LEN) // Ignore subsequent characters
|
||||
windowName+=c;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
sequenceStep=0;
|
||||
sequenceState=State::noSequence;
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Console::PutCharNoUpdate(char c)
|
||||
{
|
||||
if(isProcessingEscSequence)
|
||||
{
|
||||
ProcessEscSequence(c);
|
||||
if(ProcessEscSequence(c))
|
||||
return;
|
||||
}
|
||||
|
||||
InvalidateCursor();
|
||||
switch(c)
|
||||
{
|
||||
case '\033': // Begin of an ANSI escape sequence
|
||||
isProcessingEscSequence=true;
|
||||
sequenceStep=0;
|
||||
sequenceState=State::waitingForSequenceStart;
|
||||
break;
|
||||
case '\r':
|
||||
cursorX = 0;
|
||||
|
@ -59,8 +59,16 @@ namespace retro
|
||||
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);
|
||||
enum class State
|
||||
{
|
||||
noSequence,
|
||||
waitingForSequenceStart,
|
||||
waitingForControlSequence,
|
||||
waitingForM,
|
||||
waitingForOSCStart,
|
||||
waitingForSemicolon,
|
||||
inWindowName
|
||||
};
|
||||
|
||||
class Console
|
||||
{
|
||||
@ -83,17 +91,22 @@ namespace retro
|
||||
short GetRows() const { return rows; }
|
||||
short GetCols() const { return cols; }
|
||||
|
||||
virtual void setWindowName(std::string newName) {};
|
||||
|
||||
|
||||
void Idle();
|
||||
|
||||
bool IsEOF() const { return eof; }
|
||||
|
||||
private:
|
||||
|
||||
State sequenceState;
|
||||
std::string windowName;
|
||||
GrafPtr consolePort = nullptr;
|
||||
Rect bounds;
|
||||
Attributes currentAttr;
|
||||
|
||||
std::vector<AttributedChar> chars, onscreen;
|
||||
bool isProcessingEscSequence;
|
||||
int sequenceStep;
|
||||
|
||||
short cellSizeX;
|
||||
short cellSizeY;
|
||||
@ -117,7 +130,7 @@ namespace retro
|
||||
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);
|
||||
bool ProcessEscSequence(char c);
|
||||
void SetAttributes(Attributes aa);
|
||||
|
||||
void InvalidateCursor();
|
||||
|
@ -24,6 +24,8 @@
|
||||
#include "ConsoleWindow.h"
|
||||
#include "Events.h"
|
||||
#include <unordered_map>
|
||||
#include <cstring>
|
||||
#include <TextUtils.h>
|
||||
|
||||
using namespace retro;
|
||||
|
||||
@ -35,7 +37,6 @@ namespace
|
||||
ConsoleWindow::ConsoleWindow(Rect r, ConstStr255Param title)
|
||||
{
|
||||
GrafPtr port;
|
||||
//Retro68 Improved Console
|
||||
win = NewWindow(NULL, &r, "\pRetro68 Console", true, 0, (WindowPtr)-1, true, 0);
|
||||
|
||||
#if !TARGET_API_MAC_CARBON
|
||||
@ -63,6 +64,25 @@ ConsoleWindow::~ConsoleWindow()
|
||||
DisposeWindow(win);
|
||||
}
|
||||
|
||||
void ConsoleWindow::setWindowName(std::string newName)
|
||||
{
|
||||
Str255 pname;
|
||||
#if TARGET_API_MAC_CARBON
|
||||
// Carbon has the new, sane version.
|
||||
c2pstrcpy(pname,newName.c_str());
|
||||
#else
|
||||
// It is also availble in various glue code libraries and
|
||||
// in some versions of InterfaceLib, but it's confusing.
|
||||
// Using the inplace variant, c2pstr, isn't much better than
|
||||
// doing things by hand:
|
||||
strncpy((char *)&pname[1],newName.c_str(),255);
|
||||
pname[0] = newName.length();
|
||||
#endif
|
||||
|
||||
SetWTitle(win, pname);
|
||||
}
|
||||
|
||||
|
||||
char ConsoleWindow::WaitNextChar()
|
||||
{
|
||||
EventRecord event;
|
||||
|
@ -34,6 +34,8 @@ namespace retro
|
||||
public:
|
||||
ConsoleWindow(Rect r, ConstStr255Param title);
|
||||
~ConsoleWindow();
|
||||
void setWindowName(std::string newName);
|
||||
|
||||
private:
|
||||
WindowPtr win;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user