Example #1
0
void CMUSHclientDoc::AnsiNote(LPCTSTR Text) 
{
// save old colours
bool bOldNotesInRGB = m_bNotesInRGB;
COLORREF iOldNoteColourFore = m_iNoteColourFore;
COLORREF iOldNoteColourBack = m_iNoteColourBack;
unsigned short iOldNoteStyle = m_iNoteStyle;

bool bBold = false;
bool bInverse = false;
bool bItalic = false;
bool bUnderline = false;
int iCurrentForeGround = WHITE;
int iCurrentBackGround = BLACK;

m_iNoteStyle = NORMAL;   // start off with normal style

const char * p,
           * start;
char c;
long length;

  p = start = Text;
  while (c = *p)
    {
    if (c == ESC)
      {
      length = p - start;

      // output earlier block
      if (length > 0)
        Tell (CString (start, length));
      p++;    // skip the ESC

      if (*p == '[')
        {
        p++;    // skip the [

        int iCode = 0;
        while (isdigit (*p) || *p == ';' || *p == 'm')
          {
          if (isdigit (c = *p))
            {
            iCode *= 10;
            iCode += c - '0';
            }
          else
            if (c == ';' || c == 'm')
              {
              switch (iCode)
                {
                // reset colours to defaults
                case ANSI_RESET:
                   iCurrentForeGround = WHITE;
                   iCurrentBackGround = BLACK;
                   bBold = false;     
                   bInverse = false;
                   bItalic = false;   
                   bUnderline = false;
                   break;

                // bold
                case ANSI_BOLD:
                   bBold = true;
                   break;

                // inverse
                case ANSI_INVERSE:
                   bInverse = true;
                   break;

                // blink
                case ANSI_BLINK:
                case ANSI_SLOW_BLINK:
                case ANSI_FAST_BLINK:
                   bItalic = true;
                   break;

                // underline
                case ANSI_UNDERLINE:
                   bUnderline = true;
                   break;

                // not bold
                case ANSI_CANCEL_BOLD:
                   bBold = false;
                   break;

                // not inverse
                case ANSI_CANCEL_INVERSE:
                   bInverse = false;
                   break;

                // not blink
                case ANSI_CANCEL_BLINK:
                case ANSI_CANCEL_SLOW_BLINK:
                   bItalic = false;
                   break;

                // not underline
                case ANSI_CANCEL_UNDERLINE:
                   bUnderline = false;
                   break;

                // different foreground colour
                case ANSI_TEXT_BLACK:
                case ANSI_TEXT_RED    :
                case ANSI_TEXT_GREEN  :
                case ANSI_TEXT_YELLOW :
                case ANSI_TEXT_BLUE   :
                case ANSI_TEXT_MAGENTA:
                case ANSI_TEXT_CYAN   :
                case ANSI_TEXT_WHITE  :
                   iCurrentForeGround = iCode - ANSI_TEXT_BLACK;
                   break;

                // different background colour
                case ANSI_BACK_BLACK  :
                case ANSI_BACK_RED    :
                case ANSI_BACK_GREEN  :
                case ANSI_BACK_YELLOW :
                case ANSI_BACK_BLUE   :
                case ANSI_BACK_MAGENTA:
                case ANSI_BACK_CYAN   :
                case ANSI_BACK_WHITE  :
                   iCurrentBackGround = iCode - ANSI_BACK_BLACK;
                   break;

                } // end of switch

              m_iNoteStyle = NORMAL;

              // select colours
              if (bBold)
                {
                SetNoteColourFore (m_boldcolour [iCurrentForeGround]);
                SetNoteColourBack (m_normalcolour [iCurrentBackGround]);
                m_iNoteStyle |= HILITE;
                }
              else
                {
                SetNoteColourFore (m_normalcolour [iCurrentForeGround]);
                SetNoteColourBack (m_normalcolour [iCurrentBackGround]);
                }

              // select other style bits
              if (bInverse)
                m_iNoteStyle |= INVERSE;

              if (bItalic)
                m_iNoteStyle |= BLINK;

              if (bUnderline)
                m_iNoteStyle |= UNDERLINE;

              p++;  // skip m or ;
              }   // end of ESC [ nn ; or ESC [ nn m

          if (c == ';')
            iCode = 0;
          else
            if (c == 'm')
              break;
            else
              p++;    // next character
          } // end of getting code
        } // end of ESC [ something
       else
         p++; // skip it

      start = p;  // ready to start a new batch
      } // end of ESC something
    else
      p++;  // just keep counting characters

    } // end of processing each character

// output remaining text  - and newline
Note (start);

// put the colours back
if (bOldNotesInRGB)
  {
  m_iNoteColourFore = iOldNoteColourFore;
  m_iNoteColourBack = iOldNoteColourBack;
  }
else  
  m_bNotesInRGB = false;

// put style back
m_iNoteStyle = iOldNoteStyle;

} // end of CMUSHclientDoc::AnsiNote
Example #2
0
// rewritten: 20th November 2016 - version 5.04
void CMUSHclientDoc::AnsiNote(LPCTSTR Text) 
{
// save old colours
bool bOldNotesInRGB = m_bNotesInRGB;
COLORREF iOldNoteColourFore = m_iNoteColourFore;
COLORREF iOldNoteColourBack = m_iNoteColourBack;
unsigned short iOldNoteStyle = m_iNoteStyle;
unsigned short iOldNoteTextColour = m_iNoteTextColour;

COLORREF rgbNormalForeGround = GetNoteColourFore ();
COLORREF rgbNormalBackGround = GetNoteColourBack ();
COLORREF rgbBoldForeGround   = GetNoteColourFore ();  // not sure about these

// state machine control variable
int ansiState = NONE;

m_iNoteStyle = NORMAL;   // start off with normal style

const char * p,
           * start;
char c;
int iCode = 0;

  // p points to the current character in the text
  p = start = Text;
  while ((c = *p++))  // intentional assignment
    {

    // we basically have ESC followed by various things, or normal text
    switch (c)
      {
      // ESC potentially starts and ANSI sequence
      case ESC:
        // output earlier block
        if ((p - start) > 0)
          Tell (CString (start, p - start));
        ansiState = HAVE_ESC;
        break;  // end of ESC

      // it has to be ESC [ ...
      case '[':
        if (ansiState == HAVE_ESC)
          {
          ansiState = DOING_CODE;
          iCode = 0;
          }
        else
          ansiState = NONE;  // unexpected [ inside an ANSI sequence
        break;  // end of '['

      // digits?  (eg. ESC [ 5
      case '0':
      case '1':
      case '2':
      case '3':
      case '4':
      case '5':
      case '6':
      case '7':
      case '8':
      case '9':
        {
        switch (ansiState)
            {
            case DOING_CODE:
            case HAVE_FOREGROUND_256_START:
            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:
                  iCode *= 10;
                  iCode += c - '0';
                  break;

            } // end of switch on ansiState
          }  // end of digits
        break;  // end of digits

      // one of 'm', ';' or ':' terminates the current number, eg. ESC [1;
      case ';':
      case ':':
      case 'm':

        // interpret the previous code in iCode
        switch (ansiState)
          {
          case DOING_CODE:

            switch (iCode)
              {
              // reset colours to defaults
              case ANSI_RESET:
                 m_iNoteStyle = NORMAL;
                 // save colours for later (eg. if it becomes bold or not bold)
                 rgbNormalForeGround = m_normalcolour [WHITE];
                 rgbNormalBackGround = m_normalcolour [BLACK];
                 rgbBoldForeGround   = m_boldcolour   [WHITE];
                 // Note: this sets m_bNotesInRGB mode on
                 SetNoteColourFore (rgbNormalForeGround);
                 SetNoteColourBack (rgbNormalBackGround);
                 break;

              // bold
              case ANSI_BOLD:
                 // Note: this sets m_bNotesInRGB mode on
                 SetNoteColourFore (rgbBoldForeGround);
                 m_iNoteStyle |= HILITE;
                 break;

              // inverse
              case ANSI_INVERSE:
                 m_iNoteStyle |= INVERSE;
                 break;

              // blink
              case ANSI_BLINK:
              case ANSI_SLOW_BLINK:
              case ANSI_FAST_BLINK:
                 m_iNoteStyle |= BLINK;
                 break;

              // underline
              case ANSI_UNDERLINE:
                 m_iNoteStyle |= UNDERLINE;
                 break;

              // not bold
              case ANSI_CANCEL_BOLD:
                 SetNoteColourFore (rgbNormalForeGround);
                 m_iNoteStyle &= ~HILITE;
                 break;

              // not inverse
              case ANSI_CANCEL_INVERSE:
                 m_iNoteStyle &= ~INVERSE;
                 break;

              // not blink
              case ANSI_CANCEL_BLINK:
              case ANSI_CANCEL_SLOW_BLINK:
                 m_iNoteStyle &= ~BLINK;
                 break;

              // not underline
              case ANSI_CANCEL_UNDERLINE:
                 m_iNoteStyle &= ~UNDERLINE;
                 break;

              // different foreground colour
              case ANSI_TEXT_BLACK:
              case ANSI_TEXT_RED    :
              case ANSI_TEXT_GREEN  :
              case ANSI_TEXT_YELLOW :
              case ANSI_TEXT_BLUE   :
              case ANSI_TEXT_MAGENTA:
              case ANSI_TEXT_CYAN   :
              case ANSI_TEXT_WHITE  :
                // save colour for possible later use
                rgbNormalForeGround = m_normalcolour [iCode - ANSI_TEXT_BLACK];
                rgbBoldForeGround   = m_boldcolour   [iCode - ANSI_TEXT_BLACK];
                if (m_iNoteStyle & HILITE)
                  SetNoteColourFore (rgbBoldForeGround);
                else
                  SetNoteColourFore (rgbNormalForeGround);
                break;

              // different background colour
              case ANSI_BACK_BLACK  :
              case ANSI_BACK_RED    :
              case ANSI_BACK_GREEN  :
              case ANSI_BACK_YELLOW :
              case ANSI_BACK_BLUE   :
              case ANSI_BACK_MAGENTA:
              case ANSI_BACK_CYAN   :
              case ANSI_BACK_WHITE  :
                // save colour for possible later use
                rgbNormalBackGround = m_normalcolour [iCode - ANSI_BACK_BLACK];
                SetNoteColourBack (rgbNormalBackGround);
                break;

              // we have: ESC 38;
              case ANSI_TEXT_256_COLOUR :
                ansiState = HAVE_FOREGROUND_256_START;
                break;

              // we have: ESC 48;
              case ANSI_BACK_256_COLOUR :
                ansiState = HAVE_BACKGROUND_256_START;
                break;

              } // end of switch on iCode

            iCode = 0;  // possibly starting a new code
            break;      // end of DOING_CODE


          // we now have: ESC [ 38;5; or ESC [ 38;2;
          case HAVE_FOREGROUND_256_START:
            if (iCode == 5)  // 8-bit colour
              {
              ansiState = HAVE_FOREGROUND_256_FINISH;
              iCode = 0;  // start collecting the colour number
              }
            else if (iCode == 2)           // 24-bit RGB
              {
              iCode = 0;  // start collecting the red component
              ansiState = HAVE_FOREGROUND_24B_FINISH;
              }
            else          // if it isn't 2 or 5 I don't know what the hell it is!
              {
              iCode = 0;  // possibly starting a new code
              ansiState = DOING_CODE;  // give up and look for another code
              }
            break;  // end of HAVE_FOREGROUND_256_START

          case HAVE_FOREGROUND_256_FINISH:
            rgbNormalForeGround = xterm_256_colours [iCode & 0xFF];
            rgbBoldForeGround   = rgbNormalForeGround;  // both the same
            SetNoteColourFore (rgbNormalForeGround);
            iCode = 0;  // starting a new code
            ansiState = DOING_CODE; // no longer collecting 256-colours
            break;  // end of HAVE_FOREGROUND_256_FINISH

          // have the red component of a 24-bit colour
          case HAVE_FOREGROUND_24B_FINISH:
            rgbNormalForeGround = RGB (iCode & 0xFF, 0, 0);
            rgbBoldForeGround   = rgbNormalForeGround;  // both the same
            SetNoteColourFore (rgbNormalForeGround);
            ansiState = HAVE_FOREGROUND_24BR_FINISH; // now looking for green
            iCode = 0;  // start collecting the green component
            break;  // end of HAVE_FOREGROUND_24B_FINISH

          // have the green component of a 24-bit colour
          case HAVE_FOREGROUND_24BR_FINISH:
            rgbNormalForeGround = RGB (GetRValue(rgbNormalForeGround), iCode & 0xFF, 0);
            rgbBoldForeGround   = rgbNormalForeGround;  // both the same
            SetNoteColourFore (rgbNormalForeGround);
            ansiState = HAVE_FOREGROUND_24BG_FINISH; // now looking for blue
            iCode = 0;  // start collecting the blue component
            break;  // end of HAVE_FOREGROUND_24BR_FINISH

          // have the blue component of a 24-bit colour
          case HAVE_FOREGROUND_24BG_FINISH:
            rgbNormalForeGround =  RGB (GetRValue(rgbNormalForeGround), GetGValue(rgbNormalForeGround), iCode & 0xFF);
            rgbBoldForeGround   = rgbNormalForeGround;  // both the same
            SetNoteColourFore (rgbNormalForeGround);
            ansiState = DOING_CODE;                     // no longer collecting 24-bit colours
            iCode = 0;  // starting a new code
            break;  // end of HAVE_FOREGROUND_24BG_FINISH

          // we now have: ESC [ 48;5;  or ESC [ 48;2;
          case HAVE_BACKGROUND_256_START:
            if (iCode == 5)  // 8-bit colour
              {
              ansiState = HAVE_BACKGROUND_256_FINISH;
              iCode = 0;  // start collecting the colour number
              }
            else if (iCode == 2)            // 24-bit RGB
              {
              iCode = 0;  // start collecting the red component
              ansiState = HAVE_BACKGROUND_24B_FINISH;
              }
            else          // if it isn't 2 or 5 I don't know what the hell it is!
              {
              iCode = 0;  // starting a new code
              ansiState = DOING_CODE;  // give up and look for another code
              }
            break;  // end of HAVE_BACKGROUND_256_START

          case HAVE_BACKGROUND_256_FINISH:
            rgbNormalBackGround = xterm_256_colours [iCode & 0xFF];
            SetNoteColourBack (rgbNormalBackGround);
            ansiState = DOING_CODE; // no longer collecting 256-colours
            iCode = 0;  // starting a new code
            break;  // end of HAVE_FOREGROUND_256_FINISH

          // have the red component of a 24-bit colour
          case HAVE_BACKGROUND_24B_FINISH:
            rgbNormalBackGround = RGB (iCode & 0xFF, 0, 0);
            SetNoteColourBack (rgbNormalBackGround);
            ansiState = HAVE_BACKGROUND_24BR_FINISH; // now looking for green
            iCode = 0;  // start collecting the green component
            break;  // end of HAVE_BACKGROUND_24B_FINISH

          // have the green component of a 24-bit colour
          case HAVE_BACKGROUND_24BR_FINISH:
            rgbNormalBackGround = RGB (GetRValue(rgbNormalBackGround), iCode & 0xFF, 0);
            SetNoteColourBack (rgbNormalBackGround);
            ansiState = HAVE_BACKGROUND_24BG_FINISH; // now looking for blue
            iCode = 0;  // start collecting the blue component
            break;  // end of HAVE_BACKGROUND_24BR_FINISH

          // have the blue component of a 24-bit colour
          case HAVE_BACKGROUND_24BG_FINISH:
            rgbNormalBackGround =  RGB (GetRValue(rgbNormalBackGround), GetGValue(rgbNormalBackGround), iCode & 0xFF);
            SetNoteColourBack (rgbNormalBackGround);
            ansiState = DOING_CODE;                     // no longer collecting 24-bit colours
            iCode = 0;  // starting a new code
            break;  // end of HAVE_BACKGROUND_24BG_FINISH

          default:
            // just accumulate the text
            break;

          } // end of switch on ansiState

        // an 'm' terminates this ANSI sequence (unless we weren't in one)
        if (ansiState != NONE && c == 'm')
          {
          start = p;  // ready for outputting the next batch of non-ANSI sequences
          ansiState = NONE;
          }
       break;   // end of 'm' or ';'

      } // end of switch on current character

    } // end of processing each character

  // output remaining text  - and newline
  Note (start);

  // put the colours back
  if (bOldNotesInRGB)
    {
    m_iNoteColourFore = iOldNoteColourFore;
    m_iNoteColourBack = iOldNoteColourBack;
    }
  else  
    {
    m_bNotesInRGB = false;
    // put old text colour back
    m_iNoteTextColour = iOldNoteTextColour;
    }

  // put style back
  m_iNoteStyle = iOldNoteStyle;
  SetNewLineColour(0);
} // end of CMUSHclientDoc::AnsiNote