// // ANSI font modes -- private class // class AnsiMode { unsigned long fg, fg_curr, fg_base; unsigned long bg, bg_curr, bg_base; int fg_bright, bg_bright; // 0=norm, 1=bright, -1=dim int underscore; int fontface_base, fontsize_base; int fontface_curr, fontsize_curr; // Change 'brightness' of specified color 'col' by offset amount 'ofs' Fl_Color Brightness(unsigned long col, int ofs) { int c; unsigned long out = 0; if ( col >= 0 && col <= 8 ) { out = (( ofs < 0 ) ? col : (col + 8)); } else { c = (col & 0xff000000) >> 24; c += ofs; c = ( c < 0 ) ? 0 : (( c > 0xff ) ? 0xff : c); out |= ( c << 24 ); c = (col & 0x00ff0000) >> 16; c += ofs; c = ( c < 0 ) ? 0 : (( c > 0xff ) ? 0xff : c); out |= ( c << 16 ); c = (col & 0x0000ff00) >> 8; c += ofs; c = ( c < 0 ) ? 0 : (( c > 0xff ) ? 0xff : c); out |= ( c << 8 ); } return(Fl_Color(out)); } public: AnsiMode(Fl_Color nfg, Fl_Color nbg, int nfontface, int nfontsize) { fg_bright = 0; bg_bright = 0; underscore = 0; fg_base = fg_curr = fg = nfg; bg_base = bg_curr = bg = nbg; fontface_base = fontface_curr = nfontface; fontsize_base = fontsize_curr = nfontsize; } void Fg(unsigned long v) { fg = v; fg_curr = fg; switch ( fg_bright ) { case 1: fg_curr = Brightness(fg, 0x40); break; case 0: fg_curr = fg; break; case -1: fg_curr = Brightness(fg, -0x40); break; } } void Bg(unsigned long v) { bg = v; bg_curr = bg; switch ( bg_bright ) { case 1: bg_curr = Brightness(bg, 0x40); break; case 0: bg_curr = bg; break; case -1: bg_curr = Brightness(bg, -0x40); break; } } void Fg(Fl_Color v) { Fg((unsigned long)v); } void Bg(Fl_Color v) { Bg((unsigned long)v); } Fl_Color Fg() const { return(Fl_Color(fg_curr)); } Fl_Color Bg() const { return(Fl_Color(bg_curr)); } void FgBrightMode(int v) { fg_bright = v; Fg(fg); // apply brightness to current color } void BgBrightMode(int v) { bg_bright = v; Bg(bg); // apply brightness to current color } void Underscore(int mode) { underscore = mode; } int Underscore() const { return(underscore); } void Bold(int mode) { if ( mode ) fontface_curr |= FL_BOLD; else fontface_curr &= ~FL_BOLD; } int Bold() const { return((fontface_curr & FL_BOLD) ? 1 : 0); } void FontFace(int val) { fontface_curr = val; } int FontFace() const { return(fontface_curr); } void FontSize(int val) { fontsize_curr = val; } int FontSize() const { return(fontsize_curr); } void ReverseVideo(int mode) { Fg(mode ? bg_base : fg_base); Bg(mode ? fg_base : bg_base); } void Reset() { // Reset all modes to default FgBrightMode(0); BgBrightMode(0); Underscore(0); Bold(0); Fg(fg_base); Bg(bg_base); FontFace(fontface_base); FontSize(fontsize_base); } void AnsiColor(int col); char* ParseAnsi(char *ss); void DecodeEscapeCodes(int escapeCode); }; // Apply a new ansi color value to the class void AnsiMode::AnsiColor(int col) { switch ( col ) { case 0: Reset(); break; // reset all attributes to defaults case 1: Bold(1); FgBrightMode(1); break; // bold case 2: FgBrightMode(-1); break; // dim case 3: break; // ? (not currently supported) case 4: Underscore(1); break; // underscore on case 24: Underscore(0); break; // underscore off case 5: break; // blink (not currently supported) case 6: break; // ? case 7: ReverseVideo(1); break; // reverse video on case 27: ReverseVideo(0); break; // reverse video off // RGB EQUIVS (unaffected by colormap changes) case 30: Fg(Fl_Color(0)); break; // Fg(Fl_Color(0x00000000)); break; // blk case 31: Fg(Fl_Color(1)); break; // Fg(Fl_Color(0xdd000000)); break; // red case 32: Fg(Fl_Color(2)); break; // Fg(Fl_Color(0x00dd0000)); break; // grn case 33: Fg(Fl_Color(90)); break; // Fg(Fl_Color(0xdd660000)); break; // orn (docs say brown, some use orn. We'll use orn) case 34: Fg(Fl_Color(4)); break; // Fg(Fl_Color(0x0000dd00)); break; // blu case 35: Fg(Fl_Color(5)); break; // Fg(Fl_Color(0xdd00dd00)); break; // mag case 36: Fg(Fl_Color(6)); break; // Fg(Fl_Color(0x00dddd00)); break; // cyn case 37: Fg(Fl_Color(7)); break; // Fg(Fl_Color(0xdddddd00)); break; // wht case 38: // underscore on, default fg color Underscore(1); Fg(Fl_Color(fg_base)); break; case 39: // underscore on, default fg color Underscore(0); Fg(Fl_Color(fg_base)); break; // RGB EQUIVS (unaffected by colormap changes) case 40: Bg(Fl_Color(0)); break; // Bg(Fl_Color(0x00000000)); break; // blk case 41: Bg(Fl_Color(1)); break; // Bg(Fl_Color(0xdd000000)); break; // red case 42: Bg(Fl_Color(2)); break; // Bg(Fl_Color(0x00dd0000)); break; // grn case 43: Bg(Fl_Color(90)); break; // Bg(Fl_Color(0xdd660000)); break; // orn (docs say brown, some use orn. We'll use orn) case 44: Bg(Fl_Color(4)); break; // Bg(Fl_Color(0x0000dd00)); break; // blu case 45: Bg(Fl_Color(5)); break; // Bg(Fl_Color(0xdd00dd00)); break; // mag case 46: Bg(Fl_Color(6)); break; // Bg(Fl_Color(0x00dddd00)); break; // cyn case 47: Bg(Fl_Color(7)); break; // Bg(Fl_Color(0xdddddd00)); break; // wht case 49: Bg(Fl_Color(bg_base)); break; // default bg color } } const unsigned int TerminalColors[]= { // Normal colors. 0x00000000, // Black 0xcd000000, // Red 0x00cd0000, // Green 0xcdcd0000, // Yellow 0x0000cd00, // Blue 0xcd00cd00, // Magenta 0x00cdcd00, // Cyan 0xfaebd700, // White // Bright colors. 0x40404000, // Black 0xff000000, // Red 0x00ff0000, // Green 0xffff0000, // Yellow 0x1e90ff00, // Blue 0xff00ff00, // Magenta 0x00ffff00, // Cyan 0xffffff00 // White }; enum { NumOfColors=sizeof(TerminalColors) / sizeof(TerminalColors[0]) }; void AnsiMode::DecodeEscapeCodes(int escapeCode) { int boldCode=0; // Gets set if bold mode gets changed. int fgCode=-1; // Becomes >= 0 for a foreground color change request. int bgCode=-1; // Becomes >= 0 for a background color change request. int count; switch(escapeCode) { case 0: Reset(); break; // Reset all settings to default values case 1: Bold(1); boldCode=1; break; // Enable bold text case 22: Bold(0); boldCode=1; break; // Disable bold text case 4: Underscore(1); break; // Enable underlined text case 24: Underscore(0); break; // Disable underlined text //case 7: ReverseVideo(1); break; // Enable reverse video text //case 27: ReverseVideo(0); break; // Disable reverse video text case 30: fgCode=0; break; // Black case 31: fgCode=1; break; // Red case 32: fgCode=2; break; // Green case 33: fgCode=3; break; // Yellow case 34: fgCode=4; break; // Blue case 35: fgCode=5; break; // Magenta case 36: fgCode=6; break; // Cyan case 37: fgCode=7; break; // White case 39: Fg(fg_base); break; // Set foreground color to default case 40: bgCode=0; break; // Black case 41: bgCode=1; break; // Red case 42: bgCode=2; break; // Green case 43: bgCode=3; break; // Yellow case 44: bgCode=4; break; // Blue case 45: bgCode=5; break; // Magenta case 46: bgCode=6; break; // Cyan case 47: bgCode=7; break; // White case 49: Bg(bg_base); break; // Set background color to default default: return; break; // Unrecognized codes get ignored } if(fgCode >= 0) { // If bold mode is enabled, force bright colors by adding 8. fgCode+=(8 * Bold()); Fg(Fl_Color(TerminalColors[fgCode])); } else if(bgCode >= 0) { Bg(Fl_Color(TerminalColors[bgCode])); } else if(boldCode) { // Get the current color. Fl_Color fgColor=Fg(); for(count=0; count < NumOfColors; count++) { // See if it matches a color in our array. if(fgColor == TerminalColors[count]) { // Bold mode forces bright colors. if(Bold()) Fg(Fl_Color(TerminalColors[(count | 8)])); // Non-bold mode forces normal colors. else Fg(Fl_Color(TerminalColors[(count & 7)])); } } } } // Parse ansi sequence, leaves ss pointing to first char after ANSI sequence char* AnsiMode::ParseAnsi(char *ss) { long cols[8]; // ansi code buffer int tc = 0; while ( isdigit(*ss) ) { // parse all ';' separated ansi values int a = strtol(ss, &ss, 10); if ( tc < 8 ) { cols[tc++] = a; } switch ( *ss ) { case '\0': return(ss); // end of line case ';': ++ss; continue; // ansi value separator case 'm': // set ansi color (only mode we support) ++ss; for ( int i=0; i