Skip to content

Commit

Permalink
Merge branch 'zinmirai-24bit-color'
Browse files Browse the repository at this point in the history
  • Loading branch information
nickgammon committed Nov 29, 2018
2 parents f490698 + 87b8296 commit f3b9168
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 12 deletions.
97 changes: 87 additions & 10 deletions ansi.cpp
Expand Up @@ -3,6 +3,7 @@
#include "stdafx.h"
#include "MUSHclient.h"

#include "Color.h"
#include "doc.h"

/*
Expand Down Expand Up @@ -282,23 +283,44 @@ CAction * pAction = pOldStyle->pAction;
void CMUSHclientDoc::Interpret256ANSIcode (const int iCode)
{

/*
See: https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit
ESC[ 38:5:<n> m Select foreground color
ESC[ 48:5:<n> m Select background color
ESC[ 38;2;<r>;<g>;<b> m Select RGB foreground color
ESC[ 48;2;<r>;<g>;<b> m Select RGB background color
*/

switch (m_phase)
{
case HAVE_FOREGROUND_256_START:
if (iCode == 5)
case HAVE_FOREGROUND_256_START: // ESC[ 38: (foreground)
if (iCode == 5) // 8-bit colour
{
m_code = 0;
m_phase = HAVE_FOREGROUND_256_FINISH;
}
else if (iCode == 2) // 24-bit RGB
{
m_code = 0;
m_phase = HAVE_FOREGROUND_24B_FINISH;
}
else
m_phase = NONE;
return;

case HAVE_BACKGROUND_256_START:
if (iCode == 5)
case HAVE_BACKGROUND_256_START: // ESC[ 48: (background)
if (iCode == 5) // 8-bit colour
{
m_code = 0;
m_phase = HAVE_BACKGROUND_256_FINISH;
m_phase = HAVE_BACKGROUND_256_FINISH;
}
else if (iCode == 2) // 24-bit RGB
{
m_code = 0;
m_phase = HAVE_BACKGROUND_24B_FINISH;
}
else
m_phase = NONE;
Expand All @@ -324,6 +346,11 @@ COLORREF iForeColour = pOldStyle->iForeColour;
COLORREF iBackColour = pOldStyle->iBackColour;
CAction * pAction = pOldStyle->pAction;

bool iForegroundMode = m_phase == HAVE_FOREGROUND_24B_FINISH ||
m_phase == HAVE_FOREGROUND_24BR_FINISH ||
m_phase == HAVE_FOREGROUND_24BG_FINISH ||
m_phase == HAVE_FOREGROUND_24BB_FINISH;


// if they are in custom mode, we'll have to switch to RGB mode

Expand All @@ -334,10 +361,58 @@ CAction * pAction = pOldStyle->pAction;
iFlags |= COLOUR_RGB;
} // end of switching to RGB mode

CColor p;
if (iForegroundMode && (iFlags & INVERSE) || (!iForegroundMode && !(iFlags & INVERSE)))
p = CColor(iBackColour);
else
p = CColor(iForeColour);

switch (m_phase) {
case HAVE_FOREGROUND_24B_FINISH:
iFlags &= ~COLOURTYPE; // clear custom bits
iFlags |= COLOUR_RGB;
p.SetRed(iCode);
m_phase = HAVE_FOREGROUND_24BR_FINISH;
break;

case HAVE_FOREGROUND_24BR_FINISH:
p.SetGreen(iCode);
m_phase = HAVE_FOREGROUND_24BG_FINISH;
break;

case HAVE_FOREGROUND_24BG_FINISH:
p.SetBlue(iCode);
m_phase = HAVE_FOREGROUND_24BB_FINISH;
break;
}


switch (m_phase) {
case HAVE_BACKGROUND_24B_FINISH:
iFlags &= ~COLOURTYPE; // clear custom bits
iFlags |= COLOUR_RGB;
p.SetRed(iCode);
m_phase = HAVE_BACKGROUND_24BR_FINISH;
break;

case HAVE_BACKGROUND_24BR_FINISH:
p.SetGreen(iCode);
m_phase = HAVE_BACKGROUND_24BG_FINISH;
break;

case HAVE_BACKGROUND_24BG_FINISH:
p.SetBlue(iCode);
m_phase = HAVE_BACKGROUND_24BB_FINISH;
break;
}

if (iForegroundMode && (iFlags & INVERSE) || (!iForegroundMode && !(iFlags & INVERSE)))
iBackColour = p;
else
iForeColour = p;

// if they are in RGB mode we have to do the RGB conversion now, not at display time
if ((iFlags & COLOURTYPE) == COLOUR_RGB)
if ((iFlags & COLOURTYPE) == COLOUR_RGB && (m_phase == HAVE_FOREGROUND_256_FINISH || m_phase == HAVE_BACKGROUND_256_FINISH))
{
switch (m_phase)
{
Expand All @@ -356,7 +431,7 @@ CAction * pAction = pOldStyle->pAction;
break;
} // end of switch
} // end style in RGB
else
else if(m_phase == HAVE_FOREGROUND_256_FINISH || m_phase == HAVE_BACKGROUND_256_FINISH)
{
// must be in ANSI mode
switch (m_phase)
Expand All @@ -375,11 +450,13 @@ CAction * pAction = pOldStyle->pAction;
iBackColour = iCode;
break;
} // end of switch


}

m_phase = DOING_CODE;
if (m_phase == HAVE_BACKGROUND_256_FINISH ||
m_phase == HAVE_FOREGROUND_256_FINISH ||
m_phase == HAVE_FOREGROUND_24BB_FINISH ||
m_phase == HAVE_BACKGROUND_24BB_FINISH)
m_phase = DOING_CODE;

// if the net effect is that nothing changed (eg. blue following blue) leave
// the same style running
Expand Down
10 changes: 9 additions & 1 deletion doc.cpp
Expand Up @@ -1997,10 +1997,18 @@ CString strLine (lpszText, size);
case HAVE_ESC: Phase_ESC (c); continue;
case HAVE_UTF8_CHARACTER: Phase_UTF8 (c); continue;

case HAVE_FOREGROUND_256_START: // these 4 are similar to Phase_ANSI
case HAVE_FOREGROUND_256_START: // these 12 are similar to Phase_ANSI
case HAVE_FOREGROUND_256_FINISH:
case HAVE_BACKGROUND_256_START:
case HAVE_BACKGROUND_256_FINISH:
case HAVE_FOREGROUND_24B_FINISH:
case HAVE_FOREGROUND_24BR_FINISH:
case HAVE_FOREGROUND_24BG_FINISH:
case HAVE_FOREGROUND_24BB_FINISH:
case HAVE_BACKGROUND_24B_FINISH:
case HAVE_BACKGROUND_24BR_FINISH:
case HAVE_BACKGROUND_24BG_FINISH:
case HAVE_BACKGROUND_24BB_FINISH:
case DOING_CODE:
Phase_ANSI (c); continue;

Expand Down
12 changes: 12 additions & 0 deletions doc.h
Expand Up @@ -84,11 +84,23 @@ enum { NONE, // normal text
HAVE_SUBNEGOTIATION_IAC, // received TELNET IAC SB c <data> IAC (awaiting IAC or SE)
HAVE_COMPRESS, // received TELNET IAC COMPRESS
HAVE_COMPRESS_WILL, // received TELNET IAC COMPRESS WILL

// see: https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit
HAVE_FOREGROUND_256_START, // received ESC[38;
HAVE_FOREGROUND_256_FINISH, // received ESC[38;5;
HAVE_BACKGROUND_256_START, // received ESC[48;
HAVE_BACKGROUND_256_FINISH, // received ESC[48;5;

// see: https://en.wikipedia.org/wiki/ANSI_escape_code#24-bit
HAVE_FOREGROUND_24B_FINISH, // received ESC[38;2;
HAVE_FOREGROUND_24BR_FINISH, // received ESC[38;2;r;
HAVE_FOREGROUND_24BG_FINISH, // received ESC[38;2;r;g;
HAVE_FOREGROUND_24BB_FINISH, // received ESC[38;2;r;g;b;
HAVE_BACKGROUND_24B_FINISH, // received ESC[48;2;
HAVE_BACKGROUND_24BR_FINISH, // received ESC[48;2;r;
HAVE_BACKGROUND_24BG_FINISH, // received ESC[48;2;r;g;
HAVE_BACKGROUND_24BB_FINISH, // received ESC[48;2;r;g;b

// utf-8 modes
HAVE_UTF8_CHARACTER, // received 110 xxxxx, 1110 xxxx, or 11110 xxx

Expand Down
2 changes: 1 addition & 1 deletion telnet_phases.cpp
Expand Up @@ -63,7 +63,7 @@ void CMUSHclientDoc::Phase_ANSI (const unsigned char c)
InterpretANSIcode (m_code);
m_phase = NONE;
}
else if (c == ';')
else if (c == ';' || c == ':') // separator, eg. ESC[ 38:5:<n>
{
if (m_phase != DOING_CODE)
Interpret256ANSIcode (m_code);
Expand Down

0 comments on commit f3b9168

Please sign in to comment.