diff options
Diffstat (limited to 'project/dclib/dclib-color.c')
| -rw-r--r-- | project/dclib/dclib-color.c | 4351 |
1 files changed, 4351 insertions, 0 deletions
diff --git a/project/dclib/dclib-color.c b/project/dclib/dclib-color.c new file mode 100644 index 0000000..341c915 --- /dev/null +++ b/project/dclib/dclib-color.c @@ -0,0 +1,4351 @@ + +/*************************************************************************** + * * + * _____ ____ * + * | __ \ / __ \ _ _ _____ * + * | | \ \ / / \_\ | | | | _ \ * + * | | \ \| | | | | | |_| | * + * | | | || | | | | | ___/ * + * | | / /| | __ | | | | _ \ * + * | |__/ / \ \__/ / | |___| | |_| | * + * |_____/ \____/ |_____|_|_____/ * + * * + * Wiimms source code library * + * * + *************************************************************************** + * * + * Copyright (c) 2012-2020 by Dirk Clemens <wiimm@wiimm.de> * + * * + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * See file gpl-2.0.txt or http://www.gnu.org/licenses/gpl-2.0.txt * + * * + ***************************************************************************/ + +#define _GNU_SOURCE 1 + +#include <unistd.h> +#include <stdio.h> +#include <stddef.h> +#include <errno.h> +#include <signal.h> +#include <sys/ioctl.h> +//#include <ncurses/curses.h> +//#include <term.h> + +#include "dclib-color.h" +#include "dclib-basics.h" +#include "dclib-utf8.h" + +#ifdef DCLIB_TERMINAL + #include "dclib-terminal.h" +#endif + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// color modes /////////////// +/////////////////////////////////////////////////////////////////////////////// + +const KeywordTab_t color_mode_keywords[] = +{ + { COLMD_OFF, "OFF", "NONE", 0 }, + { COLMD_OFF, "NO-COLORS", "NOCOLORS", 0 }, + { COLMD_OFF, "0-COLORS", "0COLORS", 0 }, + { COLMD_AUTO, "AUTO", 0, 0 }, + { COLMD_ON, "ON", 0, 0 }, + { COLMD_8_COLORS, "8-COLORS", "8COLORS", 0 }, + { COLMD_256_COLORS, "256-COLORS", "256COLORS", 0 }, + {0,0,0,0} +}; + +ColorMode_t opt_colorize = COLMD_AUTO; + +/////////////////////////////////////////////////////////////////////////////// + +int ScanOptColorize ( ColorMode_t *opt, ccp arg, ccp err_prefix ) +{ + if (!opt) + opt = &opt_colorize; + + if (!arg) + { + if ( *opt < COLMD_ON ) + *opt = COLMD_ON; + return 0; + } + + int abbrev; + const KeywordTab_t *key = ScanKeyword(&abbrev,arg,color_mode_keywords); + if (!key) + return PrintKeywordError( color_mode_keywords, arg, abbrev, + err_prefix ? err_prefix : "Option --color: ", + "keyword"); + + *opt = key->id; + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// + +ccp GetColorModeName ( ColorMode_t col_mode, ccp res_not_found ) +{ + return GetKewordNameById(color_mode_keywords,col_mode,res_not_found); +} + +/////////////////////////////////////////////////////////////////////////////// + +ColorMode_t NormalizeColorMode ( ColorMode_t col_mode, int n_colors ) +{ + // returns COLMD_OFF or COLMD_8_COLORS or COLMD_256_COLORS + + switch (col_mode) + { + case COLMD_OFF: + case COLMD_8_COLORS: + case COLMD_256_COLORS: + return col_mode; + + case COLMD_ON: + return n_colors < 256 ? COLMD_8_COLORS : COLMD_256_COLORS; + + default: + //case COLMD_AUTO: + return n_colors < 8 ? COLMD_OFF + : n_colors < 256 ? COLMD_8_COLORS : COLMD_256_COLORS; + } +} + +/////////////////////////////////////////////////////////////////////////////// + +ColorMode_t NormalizeColorModeByTermName +( + ColorMode_t col_mode, // predefind mode + ccp term_name // find "256color" in terminal name. + // if NULL: use getenv("TERM") + // assume 8 or 256 colors! +) +{ + if (!term_name) + term_name = getenv("TERM"); + const int n_colors = term_name && strstr(term_name,"256color") ? 256 : 8; + return NormalizeColorMode(col_mode,n_colors); +} + +/////////////////////////////////////////////////////////////////////////////// + +ColorMode_t GetNextColorMode ( ColorMode_t col_mode ) +{ + switch(col_mode) + { + case COLMD_8_COLORS: return COLMD_256_COLORS; + case COLMD_256_COLORS: return COLMD_OFF; + default: return COLMD_8_COLORS; + } +} + +/////////////////////////////////////////////////////////////////////////////// + +ColorMode_t GetPrevColorMode ( ColorMode_t col_mode ) +{ + switch(col_mode) + { + case COLMD_8_COLORS: return COLMD_OFF; + case COLMD_256_COLORS: return COLMD_8_COLORS; + default: return COLMD_256_COLORS; + } +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// print lines with autobreak /////////////// +/////////////////////////////////////////////////////////////////////////////// + +void PutLines +( + FILE * f, // valid output stream + int indent, // indent of output + int fw, // field width of output + int first_line, // length without prefix of already printed first line + ccp prefix, // NULL or prefix for each line + ccp text, // text to print + ccp eol // End Of Line test. If NULL -> LF +) +{ + DASSERT(f); + DASSERT( indent >= 0 ); + + if (!prefix) + prefix = ""; + if (!eol) + eol = "\n"; + TRACE("PutLines(,%d,%d,%d,%.10s,%.20s)\n",indent,fw,first_line,prefix,text); + fw -= strlen(prefix); + if ( fw < 10 ) + fw = 10; + + ccp prefix1 = ""; + int indent1, fw1; + if ( indent > first_line ) + { + indent1 = indent - first_line; + fw1 = fw - indent; + } + else + { + indent1 = 0; + fw1 = fw - first_line; + } + + fw -= indent; + if ( fw < 20 ) + fw = 20; + + if ( fw1 < 20 ) + { + fputs(eol,f); + indent1 = indent; + fw1 = fw; + prefix1 = prefix; + } + + while ( *text ) + { + // skip blank and control + if ( *text == '\n' ) + { + // don't skip spaces behind a LF ==> needed for tables + while ( *text > 0 && *text < ' ' ) + text++; + } + else + { + // but ignore spaces on an automatic line break + while ( *text > 0 && *text <= ' ' ) + text++; + } + + // setup + ccp start = text, last_blank = text; + ccp max = text + fw1; + + while ( text < max && *text && *text != '\n' ) + { + if ( *text > 0 && *text <= ' ' ) + last_blank = text; + text++; + } + + // set back to last blank + if ( last_blank > start && (u8)*text > ' ' ) + text = last_blank; + + // print out + if ( *text || text > start ) + fprintf(f,"%s%*s%.*s%s", + prefix1, indent1, "", + (int)(text-start), start, eol ); + + // use standard values for next lines + indent1 = indent; + fw1 = fw; + prefix1 = prefix; + } +} + +/////////////////////////////////////////////////////////////////////////////// + +void PrintArgLines +( + FILE * f, // valid output stream + int indent, // indent of output + int fw, // field width of output + int first_line, // length without prefix of already printed first line + ccp prefix, // NULL or prefix for each line + ccp format, // format string for vsnprintf() + va_list arg // parameters for 'format' +) +{ + DASSERT(f); + DASSERT(format); + + char buf[10000]; + + va_list arg2; + va_copy(arg2,arg); + int stat = vsnprintf(buf,sizeof(buf),format,arg2); + va_end(arg2); + + if ( stat < sizeof(buf) ) + { + PutLines(f,indent,fw,first_line,prefix,buf,0); + return; + } + + + //--- buffer too small, use dynamic memory + + noPRINT("PrintArgGrowBuffer() -> MALLOC(%u)\n",stat+1); + + char *temp = MALLOC(stat+1); + vsnprintf(temp,stat+1,format,arg); + va_end(arg); + PutLines(f,indent,fw,first_line,prefix,temp,0); + FREE(temp); +} + +/////////////////////////////////////////////////////////////////////////////// + +void PrintLines +( + FILE * f, // valid output stream + int indent, // indent of output + int fw, // field width of output + int first_line, // length without prefix of already printed first line + ccp prefix, // NULL or prefix for each line + ccp format, // format string for vsnprintf() + ... // arguments for 'vsnprintf(format,...)' +) +{ + DASSERT(f); + DASSERT(format); + + va_list arg; + va_start(arg,format); + PrintArgLines(f,indent,fw,first_line,prefix,format,arg); + va_end(arg); +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// print colored lines with autobreak /////////////// +/////////////////////////////////////////////////////////////////////////////// + +uint PutColoredLines +( + // returns the number of written lines + + FILE * f, // valid output stream + const ColorSet_t *colset, // NULL or color set + int indent, // indent of output + int fw, // field width; indent+prefix+eol don't count + ccp prefix, // NULL or prefix for each line + ccp eol, // End Of Line test. If NULL -> LF + ccp text // text to print +) +{ + DASSERT(f); + DASSERT(text); + + + //--- normalize params + + indent = NormalizeIndent(indent); + + if ( fw < 1 || fw > 1000 ) + fw = 1000; + else if ( fw < 20 ) + fw = 20; + + if (!eol) + eol = "\n"; + + if (!prefix) + prefix = ""; + indent += strlen(prefix); + + if (!colset) + colset = GetFileColorSet(f); + + + //--- setup tabs + + u8 is_tab[200]; + memset(is_tab,0,sizeof(is_tab)); + + + //--- prepare output buffer + + char buf[10000]; + char *buf_end = buf + 3*sizeof(buf)/4; + int cont_indent = -1; + uint n_lines = 0, n_space = 0; + uint column = 0; + //ccp col_begin = ""; + + enum { GB_NONE, GB_SIGN, GB_COMMA, GB_SPACE } gb_mode = GB_NONE; + + struct gb_save_t + { + ccp text; // text position before code assignment + char *dest; // destination + ccp col_active; // NULL or active color by last "{name}" + ccp col_embed; // NULL or active color "{name|text}" + }; + struct gb_save_t cur = { text, buf, 0, 0 }; + struct gb_save_t save = cur; // only valid if gb_mode != GB_NONE + + + //--- main loop + + for(;;) + { + #ifdef TEST + if ( n_lines > 1000 ) + return n_lines; + #endif + + cur.text = text; + u32 code = ScanUTF8AnsiChar(&text); + switch(code) + { + case 0: + if (!column) + return n_lines; + // fall through + + case '\r': + if ( *text == '\n' ) + code = *text++; + // fall through + + case '\n': + cur.text = text; + new_line: + *cur.dest = 0; + fprintf(f,"%-*s%s%s%s", indent,prefix, buf, + cur.col_active || cur.col_embed ? colset->reset : "", eol ); + cur.dest = buf; + text = cur.text; + n_lines++; + column = 0; + n_space = 0; + gb_mode = GB_NONE; + + if ( code == '\n' ) + cont_indent = -1; + else if (!code) + return n_lines; + else if ( cont_indent > 0 ) + n_space = cont_indent; + + if ( cur.col_embed ) + cur.dest = StringCopyE(cur.dest,buf+sizeof(buf),cur.col_embed); + else if ( cur.col_active ) + cur.dest = StringCopyE(cur.dest,buf+sizeof(buf),cur.col_active); + break; + + case '{': + if ( *text == '{' ) + { + text++; + goto is_char; + } + else if ( *text == '}' ) + { + cur.dest = StringCopyE(cur.dest,buf+sizeof(buf),colset->reset); + cur.col_active = cur.col_embed = 0; + text++; + } + else + { + ccp name = text; + while ( *text && *text != '|' && *text != '}' ) + text++; + if (!*text) + break; + + ccp col = ""; + char namebuf[20]; + const uint nlen = text - name; + if ( nlen < sizeof(namebuf) ) + { + memcpy(namebuf,name,nlen); + namebuf[nlen] = 0; + col = GetColorByName(colset,namebuf); + } + + if (*col) + { + cur.dest = StringCopyE(cur.dest,buf+sizeof(buf),col); + if ( *text == '}' ) + cur.col_active = col; + else + cur.col_embed = col; + } + else if ( *text == '|' ) + cur.col_embed = ""; // to detect the closing '}' + text++; + } + break; + + case '}': + if (!cur.col_embed) + goto is_char; + cur.col_embed = 0; + cur.dest = StringCopyE(cur.dest,buf+sizeof(buf), + cur.col_active ? cur.col_active : colset->reset ); + break; + + case '\t': + case ' ': + if ( !n_space++ && column ) + { + gb_mode = column < fw/2 ? GB_COMMA : GB_SPACE; + save = cur; + } + if ( code == '\t' ) + { + uint pos; + for ( pos = column + n_space; pos < sizeof(is_tab); pos++ ) + if (is_tab[pos]) + { + n_space = pos - column; + break; + } + } + break; + + case '|': + if ( *text == '|' ) + { + text++; + goto is_char; + } + else if ( *text == '+' ) + { + text++; + uint pos = column + n_space; + if ( pos < sizeof(is_tab) ) + is_tab[pos] = 1; + } + else if ( *text == '-' ) + { + uint pos = column + n_space; + if ( pos < sizeof(is_tab) ) + is_tab[pos] = 0; + } + else if ( *text == '[' ) + { + text++; + memset(is_tab,0,sizeof(is_tab)); + for(;;) + { + while ( *text == ',' ) + text++; + + char *end; + uint num = str2ul(text,&end,10); + if ( text == end ) + break; + text = end; + if ( num < sizeof(is_tab) ) + is_tab[num] = 1; + + if ( *text == '*' ) + { + text++; + uint delta = str2ul(text,&end,10); + if ( text == end ) + break; + if ( delta > 0 ) + for ( ; num < sizeof(is_tab); num += delta ) + is_tab[num] = 1; + } + } + if ( *text == ']' ) + text++; + //HexDump16(stderr,0,0,is_tab,sizeof(is_tab)); + } + else + { + if ( *text == '>' ) + text++; + cont_indent = column + n_space; + if ( cont_indent > fw/2 ) + cont_indent = fw/2; + } + break; + + case '+': + case '-': + case '=': + case '/': + if ( gb_mode <= GB_SIGN ) + { + gb_mode = GB_SIGN; + save = cur; + } + // fall through + + default: + is_char: + column += n_space; + if ( column >= fw ) + { + // auto break line + if ( gb_mode > GB_NONE ) + cur = save; + while ( *cur.text == ' ' ) + cur.text++; + goto new_line; + } + + while ( n_space > 0 ) + *cur.dest++ = ' ', n_space--; + cur.dest = PrintUTF8Char(cur.dest,code); + if ( cur.dest > buf_end ) + goto new_line; // should never happen! + column++; + + if ( gb_mode <= GB_COMMA && ( code == ',' || code == ';' )) + { + gb_mode = GB_COMMA; + save = cur; + save.text++; + } + break; + } + } +} + +/////////////////////////////////////////////////////////////////////////////// + +uint PrintArgColoredLines +( + // returns the number of written lines + + FILE * f, // valid output stream + const ColorSet_t *colset, // NULL or color set + int indent, // indent of output + int fw, // field width; indent+prefix+eol don't count + ccp prefix, // NULL or prefix for each line + ccp eol, // End Of Line test. If NULL -> LF + ccp format, // format string for vsnprintf() + va_list arg // parameters for 'format' +) +{ + DASSERT(f); + DASSERT(format); + + char buf[10000]; + + va_list arg2; + va_copy(arg2,arg); + int stat = vsnprintf(buf,sizeof(buf),format,arg2); + va_end(arg2); + + if ( stat < sizeof(buf) ) + return PutColoredLines(f,colset,indent,fw,prefix,eol,buf); + + + //--- buffer too small, use dynamic memory + + noPRINT("PrintArgGrowBuffer() -> MALLOC(%u)\n",stat+1); + + char *temp = MALLOC(stat+1); + stat = vsnprintf(temp,stat+1,format,arg); + const uint res = PutColoredLines(f,colset,indent,fw,prefix,eol,temp); + FREE(temp); + return res; +} + +/////////////////////////////////////////////////////////////////////////////// + +uint PrintColoredLines +( + // returns the number of written lines + + FILE * f, // valid output stream + const ColorSet_t *colset, // NULL or color set + int indent, // indent of output + int fw, // field width; indent+prefix+eol don't count + ccp prefix, // NULL or prefix for each line + ccp eol, // End Of Line test. If NULL -> LF + ccp format, // format string for vsnprintf() + ... // arguments for 'vsnprintf(format,...)' +) +{ + DASSERT(f); + DASSERT(format); + + va_list arg; + va_start(arg,format); + const uint res + = PrintArgColoredLines(f,colset,indent,fw,prefix,eol,format,arg); + va_end(arg); + return res; +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// terminal /////////////// +/////////////////////////////////////////////////////////////////////////////// + +// Sequence counter for output to stdout (and stderr). +// Functions shall increment it on output, so that other functions +// know about a destroyed screen. + +uint stdout_seq_count = 0; + +/////////////////////////////////////////////////////////////////////////////// + +uint opt_width = 0; +uint opt_height = 0; + +int ScanOptWidth ( ccp arg ) +{ + return ERR_OK != ScanSizeOptU32( + &opt_width, // u32 * num + arg, // ccp source + 1, // default_factor1 + 0, // int force_base + "width", // ccp opt_name + 40, // u64 min + 10000, // u64 max + 1, // u32 multiple + 0, // u32 pow2 + true // bool print_err + ); +} + +int ScanOptHeight ( ccp arg ) +{ + return ERR_OK != ScanSizeOptU32( + &opt_height, // u32 * num + arg, // ccp source + 1, // default_factor1 + 0, // int force_base + "height", // ccp opt_name + 40, // u64 min + 10000, // u64 max + 1, // u32 multiple + 0, // u32 pow2 + true // bool print_err + ); +} + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +term_size_t GetTermSize ( int default_width, int default_height ) +{ + TRACE("GetTermWidth(%d,%d) opt=%d,%d\n", + default_width, default_height, opt_width, opt_height ); + + term_size_t ts; + if ( opt_width > 0 && opt_height > 0 ) + { + ts.width = opt_width; + ts.height = opt_height; + } + else + { + ts = GetTermSizeFD(STDOUT_FILENO,default_width,default_height); + if ( opt_width > 0 ) + ts.width = opt_width; + if ( opt_height > 0 ) + ts.height = opt_height; + } + + return ts; +} + +/////////////////////////////////////////////////////////////////////////////// + +term_size_t GetTermSizeFD ( int fd, int default_width, int default_height ) +{ + PRINT("GetTermSizeFD(%d,%d,%d)\n",fd,default_width,default_height); + + #ifdef TIOCGSIZE + TRACE(" - have TIOCGSIZE\n"); + #endif + + #ifdef TIOCGWINSZ + TRACE(" - have TIOCGWINSZ\n"); + #endif + + #ifndef WIN_SZS_LIB + if (isatty(fd)) + { + TRACE(" - isatty\n"); + + #ifdef TIOCGSIZE + { + struct ttysize ts; + if ( !ioctl(fd,TIOCGSIZE,&ts)) + { + PRINT(" - TIOCGSIZE = %d*%d\n",ts.ts_cols,ts.ts_lines); + if ( ts.ts_cols > 0 && ts.ts_lines > 0 ) + { + term_size_t tes = {ts.ts_cols,ts.ts_lines}; + return tes; + } + } + } + #endif + + #ifdef TIOCGWINSZ + { + struct winsize ws; + if ( !ioctl(fd,TIOCGWINSZ,&ws)) + { + PRINT(" - TIOCGWINSZ = %d*%d\n",ws.ws_col,ws.ws_row); + if ( ws.ws_col > 0 && ws.ws_row > 0 ) + { + term_size_t ts = {ws.ws_col,ws.ws_row}; + return ts; + } + } + } + #endif + } + #endif + + term_size_t ts = {default_width,default_height}; + return ts; +} + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +int GetTermWidth ( int default_value, int min_value ) +{ + TRACE("GetTermWidth(%d,%d) opt=%d\n",default_value,min_value,opt_width); + + int term_width = opt_width > 0 + ? opt_width + : GetTermWidthFD(STDOUT_FILENO,-1,min_value); + + return term_width > 0 ? term_width : default_value; +} + +/////////////////////////////////////////////////////////////////////////////// + +int GetTermWidthFD ( int fd, int default_value, int min_value ) +{ + TRACE("GetTermWidthFD(%d,%d,%d)\n",fd,default_value,min_value); + + term_size_t ts = GetTermSizeFD(fd,default_value,25); + return ts.width > min_value ? ts.width : min_value; +} + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +int GetTermHeight ( int default_value, int min_value ) +{ + TRACE("GetTermHeight(%d,%d) opt=%d\n",default_value,min_value,opt_height); + + int term_height = opt_height > 0 + ? opt_height + : GetTermHeightFD(STDOUT_FILENO,-1,min_value); + + return term_height > 0 ? term_height : default_value; +} + +/////////////////////////////////////////////////////////////////////////////// + +int GetTermHeightFD ( int fd, int default_value, int min_value ) +{ + TRACE("GetTermHeightFD(%d,%d,%d)\n",fd,default_value,min_value); + + term_size_t ts = GetTermSizeFD(fd,default_value,25); + return ts.height > min_value ? ts.height : min_value; +} + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +term_size_t auto_term_size = {80,25}; +uint auto_term_resized = 0; // incremented for each resize, init by 0 +uint auto_term_size_dirty = 0; // >0: SIGWINCH received, auto_term_size is dirty + +//----------------------------------------------------------------------------- + +bool GetAutoTermSize() +{ + // return true if changed + + auto_term_size_dirty = 0; + int fd = isatty(1) ? 1 : isatty(0) ? 0 : -1; + if ( fd >= 0 ) + { + term_size_t size + = GetTermSizeFD(fd,auto_term_size.width,auto_term_size.height); + if (memcmp(&auto_term_size,&size,sizeof(size))) + { + auto_term_size = size; + if (!++auto_term_resized) + auto_term_resized++; + return true; + } + } + return false; +} + +//----------------------------------------------------------------------------- + +static void Signal_SIGWINCH ( int signal ) +{ + if (!++auto_term_size_dirty) + auto_term_size_dirty++; +} + +void EnableAutoTermSize() +{ + signal(SIGWINCH,Signal_SIGWINCH); + GetAutoTermSize(); +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +ccp TermCursorUp = TERM_CURSOR_UP; // move cursor up +ccp TermCursorDown = TERM_CURSOR_DOWN; // move cursor down +ccp TermCursorRight = TERM_CURSOR_RIGHT; // move cursor right +ccp TermCursorLeft = TERM_CURSOR_LEFT; // move cursor left + +ccp TermCursorUpN = TERM_CURSOR_UP_N; // move cursor N* up (format 1 '%d') +ccp TermCursorDownN = TERM_CURSOR_DOWN_N; // move cursor N* down (format 1 '%d') +ccp TermCursorRightN = TERM_CURSOR_RIGHT_N; // move cursor N* right (format 1 '%d') +ccp TermCursorLeftN = TERM_CURSOR_LEFT_N; // move cursor N* left (format 1 '%d') + +ccp TermClearEOL = TERM_CLEAR_EOL; // clear from cursor to end of line +ccp TermClearBOL = TERM_CLEAR_BOL; // clear from beginning of line to cursor +ccp TermClearLine = TERM_CLEAR_LINE; // clear entire line + +ccp TermClearEOD = TERM_CLEAR_EOD; // clear from cursor to end of display +ccp TermClearBOD = TERM_CLEAR_BOD; // clear from beginning of display to cursor +ccp TermClearDisplay = TERM_CLEAR_DISPLAY; // clear Entire display + +ccp TermSetWrap = TERM_SET_WRAP; // enabled line wrapping +ccp TermResetWrap = TERM_RESET_WRAP; // disable line wrapping + +ccp TermTextModeBeg = TERM_TEXT_MODE_BEG; // begin of text mode sequence +ccp TermTextModeEnd = TERM_TEXT_MODE_END; // end of text mode sequence +ccp TermTextModeReset = TERM_TEXT_MODE_RESET; // reset text mode + +static uint grayscale_tab[4] = {0,8,7,15}; + +#if SUPPORT_36_COLORS + + const char ColorIndexName[TCI__N][16] = + { + "black", + "dark_gray_1", + "dark_gray_2", + "dark_gray_3", + "light_gray_1", + "light_gray_2", + "light_gray_3", + "white", + + "red", + "red_orange", + "orange", + "orange_yellow", + "yellow", + "yellow_green", + "green", + "green_cyan", + "cyan", + "cyan_blue", + "blue", + "blue_magenta", + "magenta", + "magenta_red", + + "b_red", + "b_red_orange", + "b_orange", + "b_orange_yellow", + "b_yellow", + "b_yellow_green", + "b_green", + "b_green_cyan", + "b_cyan", + "b_cyan_blue", + "b_blue", + "b_blue_magenta", + "b_magenta", + "b_magenta_red", + }; +#else // !SUPPORT_36_COLORS + + const char ColorIndexName[TCI__N][11] = + { + "black", + "dark gray", + "light gray", + "white", + + "red", + "orange", + "yellow", + "green", + "cyan", + "blue", + "magenta", + + "b_red", + "b_orange", + "b_yellow", + "b_green", + "b_cyan", + "b_blue", + "b_magenta", + }; +#endif // !SUPPORT_36_COLORS + +const int Color18Index[18+1] = // 18 elements + -1 as terminator +{ + TCI_BLACK, // gray scale + TCI_DARKGRAY, + TCI_LIGHTGRAY, + TCI_WHITE, + + TCI_RED, // normal colors in rainbow order + TCI_ORANGE, + TCI_YELLOW, + TCI_GREEN, + TCI_CYAN, + TCI_BLUE, + TCI_MAGENTA, + + TCI_B_RED, // bold colors in rainbow order + TCI_B_ORANGE, + TCI_B_YELLOW, + TCI_B_GREEN, + TCI_B_CYAN, + TCI_B_BLUE, + TCI_B_MAGENTA, + + -1 +}; + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +static char * GetColorCircBuf ( uint len ) +{ + static char circ_buf[1024]; + static char *circ_ptr = circ_buf; + DASSERT( circ_ptr >= circ_buf && circ_ptr <= circ_buf + sizeof(circ_buf) ); + + if ( len > sizeof(circ_buf)/8 ) + return GetCircBuf(len); + + if ( circ_buf + sizeof(circ_buf) - circ_ptr < len ) + circ_ptr = circ_buf; + + char *buf = circ_ptr; + circ_ptr += len; + DASSERT( circ_ptr >= circ_buf && circ_ptr <= circ_buf + sizeof(circ_buf) ); + + return buf; +} + +//----------------------------------------------------------------------------- + +ccp GetTextMode +( + // returns a pointer to an internal circulary buffer (not GetCircBuf()) + ColorMode_t col_mode, // if < COLMD_ON: return an empty string + TermTextMode_t mode // mode for text generation +) +{ + if ( col_mode < COLMD_ON ) + return EmptyString; + + if ( mode == TTM_RESET ) + return TermTextModeReset; + + uint len = strlen(TermTextModeBeg) + strlen(TermTextModeEnd) + 2; + + if ( mode & TTM_F_COLOR ) + len += 3; + else if ( mode & TTM_F_GRAYSCALE ) + len += 8; + + if ( mode & TTM_F_BG_COLOR ) + len += 3; + else if ( mode & TTM_F_BG_GRAYSCALE ) + len += 8; + + if ( mode & TTM_RESET ) + len += 2; + if ( mode & (TTM_BOLD|TTM_NO_BOLD) ) + len += 3; + if ( mode & (TTM_UL|TTM_NO_UL) ) + len += 3; + + //--- use a private circulary buffer (long term valid) + + char *buf = GetColorCircBuf(len); + + //--- compose string + + uint sep = 0; + char *end = buf + len; + char *dest = StringCopyS(buf,len,TermTextModeBeg); + + if ( mode & TTM_RESET ) + { + *dest++ = '0'; + sep++; + } + + if ( mode & TTM_BOLD ) + { + if (sep++) + *dest++ = ';'; + *dest++ = '1'; + } + else if ( mode & TTM_NO_BOLD ) + { + if (sep++) + *dest++ = ';'; + *dest++ = '2'; + *dest++ = '2'; + } + + if ( mode & TTM_UL ) + { + if (sep++) + *dest++ = ';'; + *dest++ = '4'; + } + else if ( mode & TTM_NO_UL ) + { + if (sep++) + *dest++ = ';'; + *dest++ = '2'; + *dest++ = '4'; + } + + if ( mode & TTM_F_COLOR ) + { + if (sep++) + *dest++ = ';'; + dest = snprintfE(dest,end,"%u",(mode&TTM_M_COLOR)+30); + } + else if ( mode & TTM_F_GRAYSCALE ) + { + if (sep++) + *dest++ = ';'; + dest = snprintfE(dest,end,"38;5;%u", + grayscale_tab[ mode & TTM_M_GRAYSCALE ]); + } + + if ( mode & TTM_F_BG_COLOR ) + { + if (sep++) + *dest++ = ';'; + dest = snprintfE(dest,end,"%u",((mode&TTM_M_BG_COLOR)>>TTM_SHIFT_BG)+40); + } + else if ( mode & TTM_F_BG_GRAYSCALE ) + { + if (sep++) + *dest++ = ';'; + dest = snprintfE(dest,end,"48;5;%u", + grayscale_tab[ (mode & TTM_M_BG_GRAYSCALE) >> TTM_SHIFT_BG ]); + } + + StringCopyE(dest,end,TermTextModeEnd); + return buf; +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +#if SUPPORT_36_COLORS + + ccp GetColorMode // 36 colors version + ( + // returns a pointer to an internal circulary buffer (not GetCircBuf()) + + ColorMode_t col_mode, // if < COLMD_ON: return an empty string + TermColorIndex_t font_index, // index of font color + TermColorIndex_t bg_index, // index of background color + GetColorOption_t option // execution options + ) + { + col_mode = NormalizeColorMode(col_mode,8); + if ( col_mode < COLMD_ON ) + return EmptyString; + + + //--- recommended combinations + + if ( option & GCM_ALT + && (uint)font_index < TCI__IGNORE + && (uint)bg_index < TCI__IGNORE ) + { + static const u8 tab[TCI__N_BG][TCI__N_FONT] = + { + //--- TCI_GRAY0 = TCI_BLACK + { + TCI_GRAY2, // TCI_GRAY0 = TCI_BLACK + TCI_GRAY2, // TCI_GRAY1 + TCI_GRAY3, // TCI_GRAY2 = TCI_DARKGRAY + TCI_GRAY3, // TCI_GRAY3 + TCI_GRAY4, // TCI_GRAY4 + TCI_GRAY5, // TCI_GRAY5 = TCI_LIGHTGRAY + TCI_GRAY6, // TCI_GRAY6 + TCI_GRAY7, // TCI_GRAY7 = TCI_WHITE + + TCI_B_RED, // TCI_RED + TCI_B_RED_ORANGE, // TCI_RED_ORANGE + TCI_B_ORANGE, // TCI_ORANGE + TCI_B_ORANGE_YELLOW, // TCI_ORANGE_YELLOW + TCI_B_YELLOW, // TCI_YELLOW + TCI_B_YELLOW_GREEN, // TCI_YELLOW_GREEN + TCI_B_GREEN, // TCI_GREEN + TCI_B_GREEN_CYAN, // TCI_GREEN_CYAN + TCI_B_CYAN, // TCI_CYAN + TCI_B_CYAN_BLUE, // TCI_CYAN_BLUE + TCI_B_BLUE, // TCI_BLUE + TCI_B_BLUE_MAGENTA, // TCI_BLUE_MAGENTA + TCI_B_MAGENTA, // TCI_MAGENTA + TCI_B_MAGENTA_RED, // TCI_MAGENTA_RED + }, + + //--- TCI_GRAY1 + { + TCI_GRAY3, // TCI_GRAY0 = TCI_BLACK + TCI_GRAY3, // TCI_GRAY1 + TCI_GRAY4, // TCI_GRAY2 = TCI_DARKGRAY + TCI_GRAY4, // TCI_GRAY3 + TCI_GRAY5, // TCI_GRAY4 + TCI_GRAY5, // TCI_GRAY5 = TCI_LIGHTGRAY + TCI_GRAY6, // TCI_GRAY6 + TCI_GRAY7, // TCI_GRAY7 = TCI_WHITE + + TCI_B_RED, // TCI_RED + TCI_B_RED_ORANGE, // TCI_RED_ORANGE + TCI_B_ORANGE, // TCI_ORANGE + TCI_B_ORANGE_YELLOW, // TCI_ORANGE_YELLOW + TCI_B_YELLOW, // TCI_YELLOW + TCI_B_YELLOW_GREEN, // TCI_YELLOW_GREEN + TCI_B_GREEN, // TCI_GREEN + TCI_B_GREEN_CYAN, // TCI_GREEN_CYAN + TCI_B_CYAN, // TCI_CYAN + TCI_B_CYAN_BLUE, // TCI_CYAN_BLUE + TCI_B_BLUE, // TCI_BLUE + TCI_B_BLUE_MAGENTA, // TCI_BLUE_MAGENTA + TCI_B_MAGENTA, // TCI_MAGENTA + TCI_B_MAGENTA_RED, // TCI_MAGENTA_RED + }, + + //--- TCI_GRAY2 = TCI_DARKGRAY + { + TCI_GRAY0, // TCI_GRAY0 = TCI_BLACK + TCI_GRAY0, // TCI_GRAY1 + TCI_GRAY0, // TCI_GRAY2 = TCI_DARKGRAY + TCI_GRAY4, // TCI_GRAY3 + TCI_GRAY4, // TCI_GRAY4 + TCI_GRAY5, // TCI_GRAY5 = TCI_LIGHTGRAY + TCI_GRAY6, // TCI_GRAY6 + TCI_GRAY7, // TCI_GRAY7 = TCI_WHITE + + TCI_B_RED, // TCI_RED + TCI_B_RED_ORANGE, // TCI_RED_ORANGE + TCI_B_ORANGE, // TCI_ORANGE + TCI_B_ORANGE_YELLOW, // TCI_ORANGE_YELLOW + TCI_B_YELLOW, // TCI_YELLOW + TCI_B_YELLOW_GREEN, // TCI_YELLOW_GREEN + TCI_B_GREEN, // TCI_GREEN + TCI_B_GREEN_CYAN, // TCI_GREEN_CYAN + TCI_B_CYAN, // TCI_CYAN + TCI_B_CYAN_BLUE, // TCI_CYAN_BLUE + TCI_B_BLUE, // TCI_BLUE + TCI_B_BLUE_MAGENTA, // TCI_BLUE_MAGENTA + TCI_B_MAGENTA, // TCI_MAGENTA + TCI_B_MAGENTA_RED, // TCI_MAGENTA_RED + }, + + //--- TCI_GRAY3 + { + TCI_GRAY0, // TCI_GRAY0 = TCI_BLACK + TCI_GRAY0, // TCI_GRAY1 + TCI_GRAY1, // TCI_GRAY2 = TCI_DARKGRAY + TCI_GRAY1, // TCI_GRAY3 + TCI_GRAY5, // TCI_GRAY4 + TCI_GRAY5, // TCI_GRAY5 = TCI_LIGHTGRAY + TCI_GRAY6, // TCI_GRAY6 + TCI_GRAY7, // TCI_GRAY7 = TCI_WHITE + + TCI_B_RED, // TCI_RED + TCI_B_RED_ORANGE, // TCI_RED_ORANGE + TCI_B_ORANGE, // TCI_ORANGE + TCI_B_ORANGE_YELLOW, // TCI_ORANGE_YELLOW + TCI_B_YELLOW, // TCI_YELLOW + TCI_B_YELLOW_GREEN, // TCI_YELLOW_GREEN + TCI_B_GREEN, // TCI_GREEN + TCI_B_GREEN_CYAN, // TCI_GREEN_CYAN + TCI_B_CYAN, // TCI_CYAN + TCI_B_CYAN_BLUE, // TCI_CYAN_BLUE + TCI_B_BLUE, // TCI_BLUE + TCI_B_BLUE_MAGENTA, // TCI_BLUE_MAGENTA + TCI_B_MAGENTA, // TCI_MAGENTA + TCI_B_MAGENTA_RED, // TCI_MAGENTA_RED + }, + + //--- TCI_GRAY4 = TCI_LIGHTGRAY + { + TCI_GRAY0, // TCI_GRAY0 = TCI_BLACK + TCI_GRAY1, // TCI_GRAY1 + TCI_GRAY1, // TCI_GRAY2 = TCI_DARKGRAY + TCI_GRAY2, // TCI_GRAY3 + TCI_GRAY2, // TCI_GRAY4 + TCI_GRAY6, // TCI_GRAY5 = TCI_LIGHTGRAY + TCI_GRAY6, // TCI_GRAY6 + TCI_GRAY7, // TCI_GRAY7 = TCI_WHITE + + TCI_RED, // TCI_RED + TCI_RED_ORANGE, // TCI_RED_ORANGE + TCI_B_ORANGE, // TCI_ORANGE + TCI_B_ORANGE_YELLOW, // TCI_ORANGE_YELLOW + TCI_B_YELLOW, // TCI_YELLOW + TCI_B_YELLOW_GREEN, // TCI_YELLOW_GREEN + TCI_B_GREEN, // TCI_GREEN + TCI_B_GREEN_CYAN, // TCI_GREEN_CYAN + TCI_B_CYAN, // TCI_CYAN + TCI_CYAN_BLUE, // TCI_CYAN_BLUE + TCI_BLUE, // TCI_BLUE + TCI_BLUE_MAGENTA, // TCI_BLUE_MAGENTA + TCI_MAGENTA, // TCI_MAGENTA + TCI_MAGENTA_RED, // TCI_MAGENTA_RED + }, + + //--- TCI_GRAY5 = TCI_LIGHTGRAY + { + TCI_GRAY0, // TCI_GRAY0 = TCI_BLACK + TCI_GRAY1, // TCI_GRAY1 + TCI_GRAY2, // TCI_GRAY2 = TCI_DARKGRAY + TCI_GRAY2, // TCI_GRAY3 + TCI_GRAY3, // TCI_GRAY4 + TCI_GRAY3, // TCI_GRAY5 = TCI_LIGHTGRAY + TCI_GRAY7, // TCI_GRAY6 + TCI_GRAY7, // TCI_GRAY7 = TCI_WHITE + + TCI_RED, // TCI_RED + TCI_RED_ORANGE, // TCI_RED_ORANGE + TCI_ORANGE, // TCI_ORANGE + TCI_ORANGE_YELLOW, // TCI_ORANGE_YELLOW + TCI_B_YELLOW, // TCI_YELLOW + TCI_B_YELLOW_GREEN, // TCI_YELLOW_GREEN + TCI_B_GREEN, // TCI_GREEN + TCI_B_GREEN_CYAN, // TCI_GREEN_CYAN + TCI_B_CYAN, // TCI_CYAN + TCI_CYAN_BLUE, // TCI_CYAN_BLUE + TCI_BLUE, // TCI_BLUE + TCI_BLUE_MAGENTA, // TCI_BLUE_MAGENTA + TCI_MAGENTA, // TCI_MAGENTA + TCI_MAGENTA_RED, // TCI_MAGENTA_RED + }, + + //--- TCI_GRAY6 + { + TCI_GRAY0, // TCI_GRAY0 = TCI_BLACK + TCI_GRAY1, // TCI_GRAY1 + TCI_GRAY2, // TCI_GRAY2 = TCI_DARKGRAY + TCI_GRAY2, // TCI_GRAY3 + TCI_GRAY3, // TCI_GRAY4 + TCI_GRAY3, // TCI_GRAY5 = TCI_LIGHTGRAY + TCI_GRAY4, // TCI_GRAY6 + TCI_GRAY4, // TCI_GRAY7 = TCI_WHITE + + TCI_RED, // TCI_RED + TCI_RED_ORANGE, // TCI_RED_ORANGE + TCI_ORANGE, // TCI_ORANGE + TCI_ORANGE_YELLOW, // TCI_ORANGE_YELLOW + TCI_ORANGE_YELLOW, // TCI_YELLOW + TCI_YELLOW_GREEN, // TCI_YELLOW_GREEN + TCI_GREEN, // TCI_GREEN + TCI_GREEN_CYAN, // TCI_GREEN_CYAN + TCI_CYAN, // TCI_CYAN + TCI_CYAN_BLUE, // TCI_CYAN_BLUE + TCI_BLUE, // TCI_BLUE + TCI_BLUE_MAGENTA, // TCI_BLUE_MAGENTA + TCI_MAGENTA, // TCI_MAGENTA + TCI_MAGENTA_RED, // TCI_MAGENTA_RED + }, + + //--- TCI_GRAY7 = TCI_WHITE + { + TCI_GRAY0, // TCI_GRAY0 = TCI_BLACK + TCI_GRAY1, // TCI_GRAY1 + TCI_GRAY2, // TCI_GRAY2 = TCI_DARKGRAY + TCI_GRAY3, // TCI_GRAY3 + TCI_GRAY4, // TCI_GRAY4 + TCI_GRAY4, // TCI_GRAY5 = TCI_LIGHTGRAY + TCI_GRAY5, // TCI_GRAY6 + TCI_GRAY5, // TCI_GRAY7 = TCI_WHITE + + TCI_RED, // TCI_RED + TCI_RED_ORANGE, // TCI_RED_ORANGE + TCI_ORANGE, // TCI_ORANGE + TCI_ORANGE_YELLOW, // TCI_ORANGE_YELLOW + TCI_ORANGE_YELLOW, // TCI_YELLOW + TCI_YELLOW_GREEN, // TCI_YELLOW_GREEN + TCI_GREEN, // TCI_GREEN + TCI_GREEN_CYAN, // TCI_GREEN_CYAN + TCI_CYAN, // TCI_CYAN + TCI_CYAN_BLUE, // TCI_CYAN_BLUE + TCI_BLUE, // TCI_BLUE + TCI_BLUE_MAGENTA, // TCI_BLUE_MAGENTA + TCI_MAGENTA, // TCI_MAGENTA + TCI_MAGENTA_RED, // TCI_MAGENTA_RED + }, + + //--- TCI_RED + { + TCI_GRAY0, // TCI_GRAY0 = TCI_BLACK + TCI_GRAY1, // TCI_GRAY1 + TCI_GRAY1, // TCI_GRAY2 = TCI_DARKGRAY + TCI_GRAY4, // TCI_GRAY3 + TCI_GRAY4, // TCI_GRAY4 + TCI_GRAY5, // TCI_GRAY5 = TCI_LIGHTGRAY + TCI_GRAY6, // TCI_GRAY6 + TCI_GRAY7, // TCI_GRAY7 = TCI_WHITE + + TCI_B_ORANGE, // TCI_RED + TCI_B_ORANGE, // TCI_RED_ORANGE + TCI_B_ORANGE, // TCI_ORANGE + TCI_B_ORANGE_YELLOW, // TCI_ORANGE_YELLOW + TCI_B_YELLOW, // TCI_YELLOW + TCI_B_YELLOW_GREEN, // TCI_YELLOW_GREEN + TCI_B_GREEN, // TCI_GREEN + TCI_B_GREEN_CYAN, // TCI_GREEN_CYAN + TCI_B_CYAN, // TCI_CYAN + TCI_B_CYAN_BLUE, // TCI_CYAN_BLUE + TCI_B_BLUE, // TCI_BLUE + TCI_B_BLUE_MAGENTA, // TCI_BLUE_MAGENTA + TCI_B_MAGENTA, // TCI_MAGENTA + TCI_B_MAGENTA, // TCI_MAGENTA_RED + }, + + //--- TCI_RED_ORANGE + { + TCI_GRAY0, // TCI_GRAY0 = TCI_BLACK + TCI_GRAY1, // TCI_GRAY1 + TCI_GRAY2, // TCI_GRAY2 = TCI_DARKGRAY + TCI_GRAY2, // TCI_GRAY3 + TCI_GRAY5, // TCI_GRAY4 + TCI_GRAY5, // TCI_GRAY5 = TCI_LIGHTGRAY + TCI_GRAY6, // TCI_GRAY6 + TCI_GRAY7, // TCI_GRAY7 = TCI_WHITE + + TCI_RED, // TCI_RED + TCI_RED, // TCI_RED_ORANGE + TCI_B_ORANGE_YELLOW, // TCI_ORANGE + TCI_B_ORANGE_YELLOW, // TCI_ORANGE_YELLOW + TCI_B_YELLOW, // TCI_YELLOW + TCI_B_YELLOW_GREEN, // TCI_YELLOW_GREEN + TCI_B_GREEN, // TCI_GREEN + TCI_B_GREEN_CYAN, // TCI_GREEN_CYAN + TCI_B_CYAN, // TCI_CYAN + TCI_B_CYAN_BLUE, // TCI_CYAN_BLUE + TCI_BLUE, // TCI_BLUE + TCI_B_BLUE_MAGENTA, // TCI_BLUE_MAGENTA + TCI_B_MAGENTA, // TCI_MAGENTA + TCI_MAGENTA_RED, // TCI_MAGENTA_RED + }, + + //--- TCI_ORANGE + { + TCI_GRAY0, // TCI_GRAY0 = TCI_BLACK + TCI_GRAY1, // TCI_GRAY1 + TCI_GRAY2, // TCI_GRAY2 = TCI_DARKGRAY + TCI_GRAY3, // TCI_GRAY3 + TCI_GRAY3, // TCI_GRAY4 + TCI_GRAY5, // TCI_GRAY5 = TCI_LIGHTGRAY + TCI_GRAY6, // TCI_GRAY6 + TCI_GRAY7, // TCI_GRAY7 = TCI_WHITE + + TCI_RED, // TCI_RED + TCI_RED, // TCI_RED_ORANGE + TCI_B_ORANGE_YELLOW, // TCI_ORANGE + TCI_B_ORANGE_YELLOW, // TCI_ORANGE_YELLOW + TCI_B_YELLOW, // TCI_YELLOW + TCI_B_YELLOW_GREEN, // TCI_YELLOW_GREEN + TCI_B_GREEN, // TCI_GREEN + TCI_B_GREEN_CYAN, // TCI_GREEN_CYAN + TCI_B_CYAN, // TCI_CYAN + TCI_B_CYAN_BLUE, // TCI_CYAN_BLUE + TCI_BLUE, // TCI_BLUE + TCI_BLUE_MAGENTA, // TCI_BLUE_MAGENTA + TCI_MAGENTA, // TCI_MAGENTA + TCI_MAGENTA_RED, // TCI_MAGENTA_RED + }, + + //--- TCI_ORANGE_YELLOW + { + TCI_GRAY0, // TCI_GRAY0 = TCI_BLACK + TCI_GRAY1, // TCI_GRAY1 + TCI_GRAY2, // TCI_GRAY2 = TCI_DARKGRAY + TCI_GRAY3, // TCI_GRAY3 + TCI_GRAY3, // TCI_GRAY4 + TCI_GRAY6, // TCI_GRAY5 = TCI_LIGHTGRAY + TCI_GRAY6, // TCI_GRAY6 + TCI_GRAY7, // TCI_GRAY7 = TCI_WHITE + + TCI_RED, // TCI_RED + TCI_RED, // TCI_RED_ORANGE + TCI_B_ORANGE, // TCI_ORANGE + TCI_B_ORANGE_YELLOW, // TCI_ORANGE_YELLOW + TCI_B_YELLOW, // TCI_YELLOW + TCI_B_YELLOW_GREEN, // TCI_YELLOW_GREEN + TCI_B_GREEN, // TCI_GREEN + TCI_B_GREEN_CYAN, // TCI_GREEN_CYAN + TCI_B_CYAN, // TCI_CYAN + TCI_B_CYAN_BLUE, // TCI_CYAN_BLUE + TCI_BLUE, // TCI_BLUE + TCI_BLUE_MAGENTA, // TCI_BLUE_MAGENTA + TCI_MAGENTA, // TCI_MAGENTA + TCI_MAGENTA_RED, // TCI_MAGENTA_RED + }, + + //--- TCI_YELLOW + { + TCI_GRAY0, // TCI_GRAY0 = TCI_BLACK + TCI_GRAY1, // TCI_GRAY1 + TCI_GRAY2, // TCI_GRAY2 = TCI_DARKGRAY + TCI_GRAY2, // TCI_GRAY3 + TCI_GRAY3, // TCI_GRAY4 + TCI_GRAY3, // TCI_GRAY5 = TCI_LIGHTGRAY + TCI_GRAY6, // TCI_GRAY6 + TCI_GRAY7, // TCI_GRAY7 = TCI_WHITE + + TCI_B_RED, // TCI_RED + TCI_B_RED_ORANGE, // TCI_RED_ORANGE + TCI_B_ORANGE, // TCI_ORANGE + TCI_B_ORANGE_YELLOW, // TCI_ORANGE_YELLOW + TCI_B_YELLOW, // TCI_YELLOW + TCI_B_YELLOW_GREEN, // TCI_YELLOW_GREEN + TCI_B_GREEN, // TCI_GREEN + TCI_B_GREEN_CYAN, // TCI_GREEN_CYAN + TCI_B_CYAN, // TCI_CYAN + TCI_CYAN_BLUE, // TCI_CYAN_BLUE + TCI_BLUE, // TCI_BLUE + TCI_BLUE_MAGENTA, // TCI_BLUE_MAGENTA + TCI_MAGENTA, // TCI_MAGENTA + TCI_MAGENTA_RED, // TCI_MAGENTA_RED + }, + + //--- TCI_YELLOW_GREEN + { + TCI_GRAY0, // TCI_GRAY0 = TCI_BLACK + TCI_GRAY1, // TCI_GRAY1 + TCI_GRAY2, // TCI_GRAY2 = TCI_DARKGRAY + TCI_GRAY3, // TCI_GRAY3 + TCI_GRAY3, // TCI_GRAY4 + TCI_GRAY6, // TCI_GRAY5 = TCI_LIGHTGRAY + TCI_GRAY6, // TCI_GRAY6 + TCI_GRAY7, // TCI_GRAY7 = TCI_WHITE + + TCI_RED, // TCI_RED + TCI_RED_ORANGE, // TCI_RED_ORANGE + TCI_ORANGE, // TCI_ORANGE + TCI_B_ORANGE_YELLOW, // TCI_ORANGE_YELLOW + TCI_B_YELLOW, // TCI_YELLOW + TCI_B_YELLOW_GREEN, // TCI_YELLOW_GREEN + TCI_B_GREEN, // TCI_GREEN + TCI_B_GREEN_CYAN, // TCI_GREEN_CYAN + TCI_B_CYAN, // TCI_CYAN + TCI_CYAN_BLUE, // TCI_CYAN_BLUE + TCI_BLUE, // TCI_BLUE + TCI_BLUE_MAGENTA, // TCI_BLUE_MAGENTA + TCI_MAGENTA, // TCI_MAGENTA + TCI_MAGENTA_RED, // TCI_MAGENTA_RED + }, + + //--- TCI_GREEN + { + TCI_GRAY0, // TCI_GRAY0 = TCI_BLACK + TCI_GRAY1, // TCI_GRAY1 + TCI_GRAY2, // TCI_GRAY2 = TCI_DARKGRAY + TCI_GRAY3, // TCI_GRAY3 + TCI_GRAY3, // TCI_GRAY4 + TCI_GRAY5, // TCI_GRAY5 = TCI_LIGHTGRAY + TCI_GRAY6, // TCI_GRAY6 + TCI_GRAY7, // TCI_GRAY7 = TCI_WHITE + + TCI_RED, // TCI_RED + TCI_RED_ORANGE, // TCI_RED_ORANGE + TCI_ORANGE, // TCI_ORANGE + TCI_B_ORANGE_YELLOW, // TCI_ORANGE_YELLOW + TCI_B_YELLOW, // TCI_YELLOW + TCI_B_YELLOW_GREEN, // TCI_YELLOW_GREEN + TCI_B_GREEN, // TCI_GREEN + TCI_B_GREEN_CYAN, // TCI_GREEN_CYAN + TCI_B_CYAN, // TCI_CYAN + TCI_CYAN_BLUE, // TCI_CYAN_BLUE + TCI_BLUE, // TCI_BLUE + TCI_BLUE_MAGENTA, // TCI_BLUE_MAGENTA + TCI_MAGENTA, // TCI_MAGENTA + TCI_MAGENTA_RED, // TCI_MAGENTA_RED + }, + + //--- TCI_GREEN_CYAN + { + TCI_GRAY0, // TCI_GRAY0 = TCI_BLACK + TCI_GRAY1, // TCI_GRAY1 + TCI_GRAY2, // TCI_GRAY2 = TCI_DARKGRAY + TCI_GRAY3, // TCI_GRAY3 + TCI_GRAY3, // TCI_GRAY4 + TCI_GRAY6, // TCI_GRAY5 = TCI_LIGHTGRAY + TCI_GRAY6, // TCI_GRAY6 + TCI_GRAY7, // TCI_GRAY7 = TCI_WHITE + + TCI_RED, // TCI_RED + TCI_B_RED_ORANGE, // TCI_RED_ORANGE + TCI_B_ORANGE, // TCI_ORANGE + TCI_B_ORANGE_YELLOW, // TCI_ORANGE_YELLOW + TCI_B_YELLOW, // TCI_YELLOW + TCI_B_YELLOW_GREEN, // TCI_YELLOW_GREEN + TCI_B_GREEN, // TCI_GREEN + TCI_B_GREEN_CYAN, // TCI_GREEN_CYAN + TCI_B_CYAN, // TCI_CYAN + TCI_CYAN_BLUE, // TCI_CYAN_BLUE + TCI_BLUE, // TCI_BLUE + TCI_BLUE_MAGENTA, // TCI_BLUE_MAGENTA + TCI_MAGENTA, // TCI_MAGENTA + TCI_MAGENTA_RED, // TCI_MAGENTA_RED + }, + + //--- TCI_CYAN + { + TCI_GRAY0, // TCI_GRAY0 = TCI_BLACK + TCI_GRAY1, // TCI_GRAY1 + TCI_GRAY2, // TCI_GRAY2 = TCI_DARKGRAY + TCI_GRAY3, // TCI_GRAY3 + TCI_GRAY3, // TCI_GRAY4 + TCI_GRAY6, // TCI_GRAY5 = TCI_LIGHTGRAY + TCI_GRAY6, // TCI_GRAY6 + TCI_GRAY7, // TCI_GRAY7 = TCI_WHITE + + TCI_RED, // TCI_RED + TCI_B_RED_ORANGE, // TCI_RED_ORANGE + TCI_B_ORANGE, // TCI_ORANGE + TCI_B_ORANGE_YELLOW, // TCI_ORANGE_YELLOW + TCI_B_YELLOW, // TCI_YELLOW + TCI_B_YELLOW_GREEN, // TCI_YELLOW_GREEN + TCI_B_GREEN, // TCI_GREEN + TCI_B_GREEN_CYAN, // TCI_GREEN_CYAN + TCI_B_CYAN, // TCI_CYAN + TCI_CYAN_BLUE, // TCI_CYAN_BLUE + TCI_BLUE, // TCI_BLUE + TCI_BLUE_MAGENTA, // TCI_BLUE_MAGENTA + TCI_MAGENTA, // TCI_MAGENTA + TCI_MAGENTA_RED, // TCI_MAGENTA_RED + }, + + //--- TCI_CYAN_BLUE + { + TCI_GRAY0, // TCI_GRAY0 = TCI_BLACK + TCI_GRAY1, // TCI_GRAY1 + TCI_GRAY1, // TCI_GRAY2 = TCI_DARKGRAY + TCI_GRAY2, // TCI_GRAY3 + TCI_GRAY2, // TCI_GRAY4 + TCI_GRAY6, // TCI_GRAY5 = TCI_LIGHTGRAY + TCI_GRAY6, // TCI_GRAY6 + TCI_GRAY7, // TCI_GRAY7 = TCI_WHITE + + TCI_B_RED, // TCI_RED + TCI_B_RED_ORANGE, // TCI_RED_ORANGE + TCI_B_ORANGE, // TCI_ORANGE + TCI_B_ORANGE_YELLOW, // TCI_ORANGE_YELLOW + TCI_B_YELLOW, // TCI_YELLOW + TCI_B_YELLOW_GREEN, // TCI_YELLOW_GREEN + TCI_B_GREEN, // TCI_GREEN + TCI_B_GREEN_CYAN, // TCI_GREEN_CYAN + TCI_B_CYAN, // TCI_CYAN + TCI_B_CYAN_BLUE, // TCI_CYAN_BLUE + TCI_BLUE, // TCI_BLUE + TCI_BLUE_MAGENTA, // TCI_BLUE_MAGENTA + TCI_MAGENTA, // TCI_MAGENTA + TCI_MAGENTA_RED, // TCI_MAGENTA_RED + }, + + //--- TCI_BLUE + { + TCI_GRAY0, // TCI_GRAY0 = TCI_BLACK + TCI_GRAY0, // TCI_GRAY1 + TCI_GRAY3, // TCI_GRAY2 = TCI_DARKGRAY + TCI_GRAY4, // TCI_GRAY3 + TCI_GRAY4, // TCI_GRAY4 + TCI_GRAY5, // TCI_GRAY5 = TCI_LIGHTGRAY + TCI_GRAY6, // TCI_GRAY6 + TCI_GRAY7, // TCI_GRAY7 = TCI_WHITE + + TCI_B_RED, // TCI_RED + TCI_B_RED_ORANGE, // TCI_RED_ORANGE + TCI_B_ORANGE, // TCI_ORANGE + TCI_B_ORANGE_YELLOW, // TCI_ORANGE_YELLOW + TCI_B_YELLOW, // TCI_YELLOW + TCI_B_YELLOW_GREEN, // TCI_YELLOW_GREEN + TCI_B_GREEN, // TCI_GREEN + TCI_B_GREEN_CYAN, // TCI_GREEN_CYAN + TCI_B_CYAN, // TCI_CYAN + TCI_B_CYAN_BLUE, // TCI_CYAN_BLUE + TCI_B_BLUE, // TCI_BLUE + TCI_B_BLUE_MAGENTA, // TCI_BLUE_MAGENTA + TCI_B_MAGENTA, // TCI_MAGENTA + TCI_B_MAGENTA_RED, // TCI_MAGENTA_RED + }, + + //--- TCI_BLUE_MAGENTA + { + TCI_GRAY0, // TCI_GRAY0 = TCI_BLACK + TCI_GRAY0, // TCI_GRAY1 + TCI_GRAY3, // TCI_GRAY2 = TCI_DARKGRAY + TCI_GRAY4, // TCI_GRAY3 + TCI_GRAY4, // TCI_GRAY4 + TCI_GRAY5, // TCI_GRAY5 = TCI_LIGHTGRAY + TCI_GRAY6, // TCI_GRAY6 + TCI_GRAY7, // TCI_GRAY7 = TCI_WHITE + + TCI_B_RED, // TCI_RED + TCI_B_RED_ORANGE, // TCI_RED_ORANGE + TCI_B_ORANGE, // TCI_ORANGE + TCI_B_ORANGE_YELLOW, // TCI_ORANGE_YELLOW + TCI_B_YELLOW, // TCI_YELLOW + TCI_B_YELLOW_GREEN, // TCI_YELLOW_GREEN + TCI_B_GREEN, // TCI_GREEN + TCI_B_GREEN_CYAN, // TCI_GREEN_CYAN + TCI_B_CYAN, // TCI_CYAN + TCI_B_CYAN_BLUE, // TCI_CYAN_BLUE + TCI_B_BLUE, // TCI_BLUE + TCI_B_BLUE_MAGENTA, // TCI_BLUE_MAGENTA + TCI_B_MAGENTA, // TCI_MAGENTA + TCI_B_MAGENTA_RED, // TCI_MAGENTA_RED + }, + + //--- TCI_MAGENTA + { + TCI_GRAY0, // TCI_GRAY0 = TCI_BLACK + TCI_GRAY1, // TCI_GRAY1 + TCI_GRAY1, // TCI_GRAY2 = TCI_DARKGRAY + TCI_GRAY4, // TCI_GRAY3 + TCI_GRAY4, // TCI_GRAY4 + TCI_GRAY5, // TCI_GRAY5 = TCI_LIGHTGRAY + TCI_GRAY6, // TCI_GRAY6 + TCI_GRAY7, // TCI_GRAY7 = TCI_WHITE + + TCI_B_RED_ORANGE, // TCI_RED + TCI_B_RED_ORANGE, // TCI_RED_ORANGE + TCI_B_ORANGE, // TCI_ORANGE + TCI_B_ORANGE_YELLOW, // TCI_ORANGE_YELLOW + TCI_B_YELLOW, // TCI_YELLOW + TCI_B_YELLOW_GREEN, // TCI_YELLOW_GREEN + TCI_B_GREEN, // TCI_GREEN + TCI_B_GREEN_CYAN, // TCI_GREEN_CYAN + TCI_B_CYAN, // TCI_CYAN + TCI_B_CYAN_BLUE, // TCI_CYAN_BLUE + TCI_BLUE, // TCI_BLUE + TCI_B_BLUE_MAGENTA, // TCI_BLUE_MAGENTA + TCI_B_MAGENTA, // TCI_MAGENTA + TCI_B_MAGENTA_RED, // TCI_MAGENTA_RED + }, + + //--- TCI_MAGENTA_RED + { + TCI_GRAY0, // TCI_GRAY0 = TCI_BLACK + TCI_GRAY1, // TCI_GRAY1 + TCI_GRAY1, // TCI_GRAY2 = TCI_DARKGRAY + TCI_GRAY4, // TCI_GRAY3 + TCI_GRAY4, // TCI_GRAY4 + TCI_GRAY5, // TCI_GRAY5 = TCI_LIGHTGRAY + TCI_GRAY6, // TCI_GRAY6 + TCI_GRAY7, // TCI_GRAY7 = TCI_WHITE + + TCI_B_RED_ORANGE, // TCI_RED + TCI_B_RED_ORANGE, // TCI_RED_ORANGE + TCI_B_ORANGE, // TCI_ORANGE + TCI_B_ORANGE_YELLOW, // TCI_ORANGE_YELLOW + TCI_B_YELLOW, // TCI_YELLOW + TCI_B_YELLOW_GREEN, // TCI_YELLOW_GREEN + TCI_B_GREEN, // TCI_GREEN + TCI_B_GREEN_CYAN, // TCI_GREEN_CYAN + TCI_B_CYAN, // TCI_CYAN + TCI_B_CYAN_BLUE, // TCI_CYAN_BLUE + TCI_BLUE, // TCI_BLUE + TCI_B_BLUE_MAGENTA, // TCI_BLUE_MAGENTA + TCI_B_MAGENTA, // TCI_MAGENTA + TCI_B_MAGENTA_RED, // TCI_MAGENTA_RED + }, + + //--- TCI_B_RED + { + TCI_GRAY0, // TCI_GRAY0 = TCI_BLACK + TCI_GRAY1, // TCI_GRAY1 + TCI_GRAY1, // TCI_GRAY2 = TCI_DARKGRAY + TCI_GRAY4, // TCI_GRAY3 + TCI_GRAY4, // TCI_GRAY4 + TCI_GRAY5, // TCI_GRAY5 = TCI_LIGHTGRAY + TCI_GRAY6, // TCI_GRAY6 + TCI_GRAY7, // TCI_GRAY7 = TCI_WHITE + + TCI_B_ORANGE, // TCI_RED + TCI_B_ORANGE, // TCI_RED_ORANGE + TCI_B_ORANGE, // TCI_ORANGE + TCI_B_ORANGE_YELLOW, // TCI_ORANGE_YELLOW + TCI_B_YELLOW, // TCI_YELLOW + TCI_B_YELLOW_GREEN, // TCI_YELLOW_GREEN + TCI_B_GREEN, // TCI_GREEN + TCI_B_GREEN_CYAN, // TCI_GREEN_CYAN + TCI_B_CYAN, // TCI_CYAN + TCI_B_CYAN_BLUE, // TCI_CYAN_BLUE + TCI_BLUE, // TCI_BLUE + TCI_BLUE_MAGENTA, // TCI_BLUE_MAGENTA + TCI_B_MAGENTA, // TCI_MAGENTA + TCI_B_MAGENTA, // TCI_MAGENTA_RED + }, + + //--- TCI_B_RED_ORANGE + { + TCI_GRAY0, // TCI_GRAY0 = TCI_BLACK + TCI_GRAY1, // TCI_GRAY1 + TCI_GRAY2, // TCI_GRAY2 = TCI_DARKGRAY + TCI_GRAY2, // TCI_GRAY3 + TCI_GRAY5, // TCI_GRAY4 + TCI_GRAY5, // TCI_GRAY5 = TCI_LIGHTGRAY + TCI_GRAY6, // TCI_GRAY6 + TCI_GRAY7, // TCI_GRAY7 = TCI_WHITE + + TCI_RED, // TCI_RED + TCI_RED, // TCI_RED_ORANGE + TCI_B_ORANGE_YELLOW, // TCI_ORANGE + TCI_B_ORANGE_YELLOW, // TCI_ORANGE_YELLOW + TCI_B_YELLOW, // TCI_YELLOW + TCI_B_YELLOW_GREEN, // TCI_YELLOW_GREEN + TCI_B_GREEN, // TCI_GREEN + TCI_B_GREEN_CYAN, // TCI_GREEN_CYAN + TCI_B_CYAN, // TCI_CYAN + TCI_B_CYAN_BLUE, // TCI_CYAN_BLUE + TCI_BLUE, // TCI_BLUE + TCI_BLUE_MAGENTA, // TCI_BLUE_MAGENTA + TCI_MAGENTA, // TCI_MAGENTA + TCI_MAGENTA_RED, // TCI_MAGENTA_RED + }, + + //--- TCI_B_ORANGE + { + TCI_GRAY0, // TCI_GRAY0 = TCI_BLACK + TCI_GRAY1, // TCI_GRAY1 + TCI_GRAY2, // TCI_GRAY2 = TCI_DARKGRAY + TCI_GRAY3, // TCI_GRAY3 + TCI_GRAY3, // TCI_GRAY4 + TCI_GRAY5, // TCI_GRAY5 = TCI_LIGHTGRAY + TCI_GRAY6, // TCI_GRAY6 + TCI_GRAY7, // TCI_GRAY7 = TCI_WHITE + + TCI_RED, // TCI_RED + TCI_RED_ORANGE, // TCI_RED_ORANGE + TCI_B_ORANGE_YELLOW, // TCI_ORANGE + TCI_B_ORANGE_YELLOW, // TCI_ORANGE_YELLOW + TCI_B_YELLOW, // TCI_YELLOW + TCI_B_YELLOW_GREEN, // TCI_YELLOW_GREEN + TCI_B_GREEN, // TCI_GREEN + TCI_B_GREEN_CYAN, // TCI_GREEN_CYAN + TCI_B_CYAN, // TCI_CYAN + TCI_B_CYAN_BLUE, // TCI_CYAN_BLUE + TCI_BLUE, // TCI_BLUE + TCI_BLUE_MAGENTA, // TCI_BLUE_MAGENTA + TCI_MAGENTA, // TCI_MAGENTA + TCI_MAGENTA_RED, // TCI_MAGENTA_RED + }, + + //--- TCI_B_ORANGE_YELLOW + { + + TCI_GRAY0, // TCI_GRAY0 = TCI_BLACK + TCI_GRAY1, // TCI_GRAY1 + TCI_GRAY2, // TCI_GRAY2 = TCI_DARKGRAY + TCI_GRAY3, // TCI_GRAY3 + TCI_GRAY4, // TCI_GRAY4 + TCI_GRAY4, // TCI_GRAY5 = TCI_LIGHTGRAY + TCI_GRAY6, // TCI_GRAY6 + TCI_GRAY7, // TCI_GRAY7 = TCI_WHITE + + TCI_RED, // TCI_RED + TCI_RED_ORANGE, // TCI_RED_ORANGE + TCI_ORANGE, // TCI_ORANGE + TCI_ORANGE_YELLOW, // TCI_ORANGE_YELLOW + TCI_YELLOW, // TCI_YELLOW + TCI_YELLOW_GREEN, // TCI_YELLOW_GREEN + TCI_GREEN, // TCI_GREEN + TCI_GREEN_CYAN, // TCI_GREEN_CYAN + TCI_CYAN, // TCI_CYAN + TCI_CYAN_BLUE, // TCI_CYAN_BLUE + TCI_BLUE, // TCI_BLUE + TCI_BLUE_MAGENTA, // TCI_BLUE_MAGENTA + TCI_MAGENTA, // TCI_MAGENTA + TCI_MAGENTA_RED, // TCI_MAGENTA_RED + }, + + //--- TCI_B_YELLOW + { + TCI_GRAY0, // TCI_GRAY0 = TCI_BLACK + TCI_GRAY1, // TCI_GRAY1 + TCI_GRAY2, // TCI_GRAY2 = TCI_DARKGRAY + TCI_GRAY3, // TCI_GRAY3 + TCI_GRAY4, // TCI_GRAY4 + TCI_GRAY4, // TCI_GRAY5 = TCI_LIGHTGRAY + TCI_GRAY5, // TCI_GRAY6 + TCI_GRAY5, // TCI_GRAY7 = TCI_WHITE + + TCI_RED, // TCI_RED + TCI_RED_ORANGE, // TCI_RED_ORANGE + TCI_ORANGE, // TCI_ORANGE + TCI_ORANGE_YELLOW, // TCI_ORANGE_YELLOW + TCI_YELLOW, // TCI_YELLOW + TCI_YELLOW_GREEN, // TCI_YELLOW_GREEN + TCI_GREEN, // TCI_GREEN + TCI_GREEN_CYAN, // TCI_GREEN_CYAN + TCI_CYAN, // TCI_CYAN + TCI_CYAN_BLUE, // TCI_CYAN_BLUE + TCI_BLUE, // TCI_BLUE + TCI_BLUE_MAGENTA, // TCI_BLUE_MAGENTA + TCI_MAGENTA, // TCI_MAGENTA + TCI_MAGENTA_RED, // TCI_MAGENTA_RED + }, + + //--- TCI_B_YELLOW_GREEN + { + TCI_GRAY0, // TCI_GRAY0 = TCI_BLACK + TCI_GRAY1, // TCI_GRAY1 + TCI_GRAY2, // TCI_GRAY2 = TCI_DARKGRAY + TCI_GRAY3, // TCI_GRAY3 + TCI_GRAY4, // TCI_GRAY4 + TCI_GRAY4, // TCI_GRAY5 = TCI_LIGHTGRAY + TCI_GRAY5, // TCI_GRAY6 + TCI_GRAY5, // TCI_GRAY7 = TCI_WHITE + + TCI_RED, // TCI_RED + TCI_RED_ORANGE, // TCI_RED_ORANGE + TCI_ORANGE, // TCI_ORANGE + TCI_ORANGE_YELLOW, // TCI_ORANGE_YELLOW + TCI_YELLOW, // TCI_YELLOW + TCI_YELLOW_GREEN, // TCI_YELLOW_GREEN + TCI_GREEN, // TCI_GREEN + TCI_GREEN_CYAN, // TCI_GREEN_CYAN + TCI_CYAN, // TCI_CYAN + TCI_CYAN_BLUE, // TCI_CYAN_BLUE + TCI_BLUE, // TCI_BLUE + TCI_BLUE_MAGENTA, // TCI_BLUE_MAGENTA + TCI_MAGENTA, // TCI_MAGENTA + TCI_MAGENTA_RED, // TCI_MAGENTA_RED + }, + + //--- TCI_B_GREEN + { + TCI_GRAY0, // TCI_GRAY0 = TCI_BLACK + TCI_GRAY1, // TCI_GRAY1 + TCI_GRAY2, // TCI_GRAY2 = TCI_DARKGRAY + TCI_GRAY3, // TCI_GRAY3 + TCI_GRAY4, // TCI_GRAY4 + TCI_GRAY4, // TCI_GRAY5 = TCI_LIGHTGRAY + TCI_GRAY5, // TCI_GRAY6 + TCI_GRAY5, // TCI_GRAY7 = TCI_WHITE + + TCI_RED, // TCI_RED + TCI_RED_ORANGE, // TCI_RED_ORANGE + TCI_ORANGE, // TCI_ORANGE + TCI_ORANGE_YELLOW, // TCI_ORANGE_YELLOW + TCI_YELLOW, // TCI_YELLOW + TCI_YELLOW_GREEN, // TCI_YELLOW_GREEN + TCI_GREEN, // TCI_GREEN + TCI_GREEN_CYAN, // TCI_GREEN_CYAN + TCI_CYAN, // TCI_CYAN + TCI_CYAN_BLUE, // TCI_CYAN_BLUE + TCI_BLUE, // TCI_BLUE + TCI_BLUE_MAGENTA, // TCI_BLUE_MAGENTA + TCI_MAGENTA, // TCI_MAGENTA + TCI_MAGENTA_RED, // TCI_MAGENTA_RED + }, + + //--- TCI_B_GREEN_CYAN + { + TCI_GRAY0, // TCI_GRAY0 = TCI_BLACK + TCI_GRAY1, // TCI_GRAY1 + TCI_GRAY2, // TCI_GRAY2 = TCI_DARKGRAY + TCI_GRAY3, // TCI_GRAY3 + TCI_GRAY4, // TCI_GRAY4 + TCI_GRAY4, // TCI_GRAY5 = TCI_LIGHTGRAY + TCI_GRAY5, // TCI_GRAY6 + TCI_GRAY5, // TCI_GRAY7 = TCI_WHITE + + TCI_RED, // TCI_RED + TCI_RED_ORANGE, // TCI_RED_ORANGE + TCI_ORANGE, // TCI_ORANGE + TCI_ORANGE_YELLOW, // TCI_ORANGE_YELLOW + TCI_YELLOW, // TCI_YELLOW + TCI_YELLOW_GREEN, // TCI_YELLOW_GREEN + TCI_GREEN, // TCI_GREEN + TCI_GREEN_CYAN, // TCI_GREEN_CYAN + TCI_CYAN, // TCI_CYAN + TCI_CYAN_BLUE, // TCI_CYAN_BLUE + TCI_BLUE, // TCI_BLUE + TCI_BLUE_MAGENTA, // TCI_BLUE_MAGENTA + TCI_MAGENTA, // TCI_MAGENTA + TCI_MAGENTA_RED, // TCI_MAGENTA_RED + }, + + //--- TCI_B_CYAN + { + TCI_GRAY0, // TCI_GRAY0 = TCI_BLACK + TCI_GRAY1, // TCI_GRAY1 + TCI_GRAY2, // TCI_GRAY2 = TCI_DARKGRAY + TCI_GRAY3, // TCI_GRAY3 + TCI_GRAY4, // TCI_GRAY4 + TCI_GRAY4, // TCI_GRAY5 = TCI_LIGHTGRAY + TCI_GRAY5, // TCI_GRAY6 + TCI_GRAY5, // TCI_GRAY7 = TCI_WHITE + + TCI_RED, // TCI_RED + TCI_RED_ORANGE, // TCI_RED_ORANGE + TCI_ORANGE, // TCI_ORANGE + TCI_ORANGE_YELLOW, // TCI_ORANGE_YELLOW + TCI_YELLOW, // TCI_YELLOW + TCI_YELLOW_GREEN, // TCI_YELLOW_GREEN + TCI_GREEN, // TCI_GREEN + TCI_GREEN_CYAN, // TCI_GREEN_CYAN + TCI_CYAN, // TCI_CYAN + TCI_CYAN_BLUE, // TCI_CYAN_BLUE + TCI_BLUE, // TCI_BLUE + TCI_BLUE_MAGENTA, // TCI_BLUE_MAGENTA + TCI_MAGENTA, // TCI_MAGENTA + TCI_MAGENTA_RED, // TCI_MAGENTA_RED + }, + + //--- TCI_CYAN_BLUE + { + TCI_GRAY0, // TCI_GRAY0 = TCI_BLACK + TCI_GRAY1, // TCI_GRAY1 + TCI_GRAY2, // TCI_GRAY2 = TCI_DARKGRAY + TCI_GRAY3, // TCI_GRAY3 + TCI_GRAY4, // TCI_GRAY4 + TCI_GRAY5, // TCI_GRAY5 = TCI_LIGHTGRAY + TCI_GRAY6, // TCI_GRAY6 + TCI_GRAY7, // TCI_GRAY7 = TCI_WHITE + + TCI_RED, // TCI_RED + TCI_RED_ORANGE, // TCI_RED_ORANGE + TCI_ORANGE, // TCI_ORANGE + TCI_B_ORANGE_YELLOW, // TCI_ORANGE_YELLOW + TCI_B_YELLOW, // TCI_YELLOW + TCI_B_YELLOW_GREEN, // TCI_YELLOW_GREEN + TCI_B_GREEN, // TCI_GREEN + TCI_B_GREEN_CYAN, // TCI_GREEN_CYAN + TCI_B_CYAN, // TCI_CYAN + TCI_CYAN_BLUE, // TCI_CYAN_BLUE + TCI_BLUE, // TCI_BLUE + TCI_BLUE_MAGENTA, // TCI_BLUE_MAGENTA + TCI_MAGENTA, // TCI_MAGENTA + TCI_MAGENTA_RED, // TCI_MAGENTA_RED + }, + + //--- TCI_B_BLUE + { + TCI_GRAY0, // TCI_GRAY0 = TCI_BLACK + TCI_GRAY1, // TCI_GRAY1 + TCI_GRAY2, // TCI_GRAY2 = TCI_DARKGRAY + TCI_GRAY3, // TCI_GRAY3 + TCI_GRAY4, // TCI_GRAY4 + TCI_GRAY5, // TCI_GRAY5 = TCI_LIGHTGRAY + TCI_GRAY6, // TCI_GRAY6 + TCI_GRAY7, // TCI_GRAY7 = TCI_WHITE + + TCI_RED, // TCI_RED + TCI_RED_ORANGE, // TCI_RED_ORANGE + TCI_ORANGE, // TCI_ORANGE + TCI_B_ORANGE_YELLOW, // TCI_ORANGE_YELLOW + TCI_B_YELLOW, // TCI_YELLOW + TCI_B_YELLOW_GREEN, // TCI_YELLOW_GREEN + TCI_B_GREEN, // TCI_GREEN + TCI_B_GREEN_CYAN, // TCI_GREEN_CYAN + TCI_B_CYAN, // TCI_CYAN + TCI_CYAN_BLUE, // TCI_CYAN_BLUE + TCI_BLUE, // TCI_BLUE + TCI_BLUE_MAGENTA, // TCI_BLUE_MAGENTA + TCI_MAGENTA, // TCI_MAGENTA + TCI_MAGENTA_RED, // TCI_MAGENTA_RED + }, + + //--- TCI_B_BLUE_MAGENTA + { + TCI_GRAY0, // TCI_GRAY0 = TCI_BLACK + TCI_GRAY1, // TCI_GRAY1 + TCI_GRAY2, // TCI_GRAY2 = TCI_DARKGRAY + TCI_GRAY3, // TCI_GRAY3 + TCI_GRAY4, // TCI_GRAY4 + TCI_GRAY5, // TCI_GRAY5 = TCI_LIGHTGRAY + TCI_GRAY6, // TCI_GRAY6 + TCI_GRAY7, // TCI_GRAY7 = TCI_WHITE + + TCI_RED, // TCI_RED + TCI_RED_ORANGE, // TCI_RED_ORANGE + TCI_B_ORANGE, // TCI_ORANGE + TCI_B_ORANGE_YELLOW, // TCI_ORANGE_YELLOW + TCI_B_YELLOW, // TCI_YELLOW + TCI_B_YELLOW_GREEN, // TCI_YELLOW_GREEN + TCI_B_GREEN, // TCI_GREEN + TCI_B_GREEN_CYAN, // TCI_GREEN_CYAN + TCI_B_CYAN, // TCI_CYAN + TCI_B_CYAN_BLUE, // TCI_CYAN_BLUE + TCI_BLUE, // TCI_BLUE + TCI_BLUE_MAGENTA, // TCI_BLUE_MAGENTA + TCI_MAGENTA, // TCI_MAGENTA + TCI_MAGENTA_RED, // TCI_MAGENTA_RED + }, + + //--- TCI_B_MAGENTA + { + TCI_GRAY0, // TCI_GRAY0 = TCI_BLACK + TCI_GRAY1, // TCI_GRAY1 + TCI_GRAY2, // TCI_GRAY2 = TCI_DARKGRAY + TCI_GRAY3, // TCI_GRAY3 + TCI_GRAY4, // TCI_GRAY4 + TCI_GRAY5, // TCI_GRAY5 = TCI_LIGHTGRAY + TCI_GRAY6, // TCI_GRAY6 + TCI_GRAY7, // TCI_GRAY7 = TCI_WHITE + + TCI_RED, // TCI_RED + TCI_RED_ORANGE, // TCI_RED_ORANGE + TCI_B_ORANGE, // TCI_ORANGE + TCI_B_ORANGE_YELLOW, // TCI_ORANGE_YELLOW + TCI_B_YELLOW, // TCI_YELLOW + TCI_B_YELLOW_GREEN, // TCI_YELLOW_GREEN + TCI_B_GREEN, // TCI_GREEN + TCI_B_GREEN_CYAN, // TCI_GREEN_CYAN + TCI_B_CYAN, // TCI_CYAN + TCI_CYAN_BLUE, // TCI_CYAN_BLUE + TCI_BLUE, // TCI_BLUE + TCI_BLUE_MAGENTA, // TCI_BLUE_MAGENTA + TCI_MAGENTA, // TCI_MAGENTA + TCI_MAGENTA_RED, // TCI_MAGENTA_RED + }, + + //--- TCI_B_MAGENTA_RED + { + TCI_GRAY0, // TCI_GRAY0 = TCI_BLACK + TCI_GRAY1, // TCI_GRAY1 + TCI_GRAY2, // TCI_GRAY2 = TCI_DARKGRAY + TCI_GRAY3, // TCI_GRAY3 + TCI_GRAY4, // TCI_GRAY4 + TCI_GRAY5, // TCI_GRAY5 = TCI_LIGHTGRAY + TCI_GRAY6, // TCI_GRAY6 + TCI_GRAY7, // TCI_GRAY7 = TCI_WHITE + + TCI_RED, // TCI_RED + TCI_RED, // TCI_RED_ORANGE + TCI_B_ORANGE, // TCI_ORANGE + TCI_B_ORANGE_YELLOW, // TCI_ORANGE_YELLOW + TCI_B_YELLOW, // TCI_YELLOW + TCI_B_YELLOW_GREEN, // TCI_YELLOW_GREEN + TCI_B_GREEN, // TCI_GREEN + TCI_B_GREEN_CYAN, // TCI_GREEN_CYAN + TCI_B_CYAN, // TCI_CYAN + TCI_CYAN_BLUE, // TCI_CYAN_BLUE + TCI_BLUE, // TCI_BLUE + TCI_BLUE_MAGENTA, // TCI_BLUE_MAGENTA + TCI_MAGENTA, // TCI_MAGENTA + TCI_MAGENTA_RED, // TCI_MAGENTA_RED + }, + }; + + const uint font = font_index < TCI_B_RED ? font_index + : font_index - (TCI_B_RED-TCI_RED); + font_index = tab[bg_index][font]; + } + + + //--- color index + + static const u8 color_index_8[] = + { + 0, // TCI_GRAY0 = TCI_BLACK + 0, // TCI_GRAY1 + 8, // TCI_GRAY2 = TCI_DARKGRAY + 8, // TCI_GRAY3 + 7, // TCI_GRAY4 + 7, // TCI_GRAY5 = TCI_LIGHTGRAY + 15, // TCI_GRAY6 + 15, // TCI_GRAY7 = TCI_WHITE + + 1, // TCI_RED + 1, // TCI_RED_ORANGE + 1, // TCI_ORANGE + 1, // TCI_ORANGE_YELLOW + 3, // TCI_YELLOW + 3, // TCI_YELLOW_GREEN + 2, // TCI_GREEN + 2, // TCI_GREEN_CYAN + 6, // TCI_CYAN + 6, // TCI_CYAN_BLUE + 4, // TCI_BLUE + 4, // TCI_BLUE_MAGENTA + 5, // TCI_MAGENTA + 5, // TCI_MAGENTA_RED + + 9, // TCI_B_RED + 9, // TCI_B_RED_ORANGE + 9, // TCI_B_ORANGE + 9, // TCI_B_ORANGE_YELLOW + 11, // TCI_B_YELLOW + 11, // TCI_B_YELLOW_GREEN + 10, // TCI_B_GREEN + 10, // TCI_B_GREEN_CYAN + 14, // TCI_B_CYAN + 14, // TCI_B_CYAN_BLUE + 12, // TCI_B_BLUE + 12, // TCI_B_BLUE_MAGENTA + 13, // TCI_B_MAGENTA + 13, // TCI_B_MAGENTA_RED + }; + + static const u8 color_index_256[] = + { + 232, // TCI_GRAY0 = TCI_BLACK + 236, // TCI_GRAY1 + 240, // TCI_GRAY2 = TCI_DARKGRAY + 243, // TCI_GRAY3 + 246, // TCI_GRAY4 + 249, // TCI_GRAY5 = TCI_LIGHTGRAY + 252, // TCI_GRAY6 + 255, // TCI_GRAY7 = TCI_WHITE + + 160, // TCI_RED + 166, // TCI_RED_ORANGE + 172, // TCI_ORANGE + 136, // TCI_ORANGE_YELLOW + 142, // TCI_YELLOW + 106, // TCI_YELLOW_GREEN + 34, // TCI_GREEN + 36, // TCI_GREEN_CYAN + 37, // TCI_CYAN + 32, // TCI_CYAN_BLUE + 21, // TCI_BLUE + 92, // TCI_BLUE_MAGENTA + 164, // TCI_MAGENTA + 162, // TCI_MAGENTA_RED + + 196, // TCI_B_RED + 202, // TCI_B_RED_ORANGE + 208, // TCI_B_ORANGE + 214, // TCI_B_ORANGE_YELLOW + 226, // TCI_B_YELLOW + 154, // TCI_B_YELLOW_GREEN + 46, // TCI_B_GREEN + 49, // TCI_B_GREEN_CYAN + 51, // TCI_B_CYAN + 75, // TCI_B_CYAN_BLUE + 105, // TCI_B_BLUE + 177, // TCI_B_BLUE_MAGENTA + 207, // TCI_B_MAGENTA + 204, // TCI_B_MAGENTA_RED + }; + + const u8 *color_index; + uint x_bg; + if ( col_mode == COLMD_256_COLORS ) + { + color_index = color_index_256; + x_bg = 8; + } + else + { + color_index = color_index_8; + x_bg = 16; + option |= GCM_SHORT; + } + + + //--- output + + char buf[100], *end = buf + sizeof(buf); + char *dest = StringCopyE(buf,end,TermTextModeBeg); + + const uint bg = (uint)bg_index < TCI__IGNORE ? color_index[bg_index] : ~0; + + ccp sep = ""; + if ( (uint)font_index < TCI__IGNORE ) + { + uint idx = color_index[font_index]; + if ( idx < 16 && idx == (bg&7) && option & GCM_ALT ) + idx = idx ^ 8; + + if ( !(option & GCM_SHORT) || idx >= 16 ) + dest = snprintfE(dest,end,"38;5;%u",idx); + else if ( idx < 8 ) + dest = snprintfE(dest,end,"0;%u",30+idx); + else + dest = snprintfE(dest,end,"1;%u",22+idx); + sep = ";"; + } + + if ( (uint)bg_index < TCI__IGNORE ) + { + if ( !(option & GCM_SHORT) || bg >= x_bg ) + dest = snprintfE(dest,end,"%s48;5;%u",sep,bg); + else + dest = snprintfE(dest,end,"%s%u",sep,40+(bg&7)); + } + + dest = StringCopyE(dest,end,TermTextModeEnd); + const int len = dest + 1 - buf; + char *res = GetColorCircBuf(len); + memcpy(res,buf,len); + return res; + } + +#else // !SUPPORT_36_COLORS + + ccp GetColorMode // 18 colors version + ( + // returns a pointer to an internal circulary buffer (not GetCircBuf()) + + ColorMode_t col_mode, // if < COLMD_ON: return an empty string + TermColorIndex_t font_index, // index of font color + TermColorIndex_t bg_index, // index of background color + GetColorOption_t option // execution options + ) + { + col_mode = NormalizeColorMode(col_mode,8); + if ( col_mode < COLMD_ON ) + return EmptyString; + + + //--- recommended combinations + + if ( option & GCM_ALT + && (uint)font_index < TCI__IGNORE + && (uint)bg_index < TCI__IGNORE ) + { + + static const u8 tab[TCI__N_BG][TCI__N_FONT] = + { + //--- TCI_BLACK + { + TCI_DARKGRAY, // TCI_BLACK + TCI_DARKGRAY, // TCI_DARKGRAY + TCI_LIGHTGRAY, // TCI_LIGHTGRAY + TCI_WHITE, // TCI_WHITE + TCI_B_RED, // TCI_RED + TCI_B_ORANGE, // TCI_ORANGE + TCI_B_YELLOW, // TCI_YELLOW + TCI_B_GREEN, // TCI_GREEN + TCI_B_CYAN, // TCI_CYAN + TCI_B_BLUE, // TCI_BLUE + TCI_B_MAGENTA, // TCI_MAGENTA + }, + + //--- TCI_DARKGRAY + { + TCI_BLACK, // TCI_BLACK + TCI_LIGHTGRAY, // TCI_DARKGRAY + TCI_LIGHTGRAY, // TCI_LIGHTGRAY + TCI_WHITE, // TCI_WHITE + TCI_B_RED, // TCI_RED + TCI_B_ORANGE, // TCI_ORANGE + TCI_B_YELLOW, // TCI_YELLOW + TCI_B_GREEN, // TCI_GREEN + TCI_B_CYAN, // TCI_CYAN + TCI_B_BLUE, // TCI_BLUE + TCI_B_MAGENTA, // TCI_MAGENTA + }, + + //--- TCI_LIGHTGRAY + { + TCI_BLACK, // TCI_BLACK + TCI_DARKGRAY, // TCI_DARKGRAY + TCI_DARKGRAY, // TCI_LIGHTGRAY + TCI_WHITE, // TCI_WHITE + TCI_RED, // TCI_RED + TCI_ORANGE, // TCI_ORANGE + TCI_B_YELLOW, // TCI_YELLOW + TCI_GREEN, // TCI_GREEN + TCI_CYAN, // TCI_CYAN + TCI_BLUE, // TCI_BLUE + TCI_MAGENTA, // TCI_MAGENTA + }, + + //--- TCI_WHITE + { + TCI_BLACK, // TCI_BLACK + TCI_DARKGRAY, // TCI_DARKGRAY + TCI_LIGHTGRAY, // TCI_LIGHTGRAY + TCI_LIGHTGRAY, // TCI_WHITE + TCI_RED, // TCI_RED + TCI_ORANGE, // TCI_ORANGE + TCI_ORANGE, // TCI_YELLOW + TCI_GREEN, // TCI_GREEN + TCI_CYAN, // TCI_CYAN + TCI_BLUE, // TCI_BLUE + TCI_MAGENTA, // TCI_MAGENTA + }, + + //--- TCI_RED + { + TCI_BLACK, // TCI_BLACK + TCI_LIGHTGRAY, // TCI_DARKGRAY + TCI_LIGHTGRAY, // TCI_LIGHTGRAY + TCI_WHITE, // TCI_WHITE + TCI_B_RED, // TCI_RED + TCI_B_ORANGE, // TCI_ORANGE + TCI_B_YELLOW, // TCI_YELLOW + TCI_B_GREEN, // TCI_GREEN + TCI_B_CYAN, // TCI_CYAN + TCI_B_BLUE, // TCI_BLUE + TCI_B_MAGENTA, // TCI_MAGENTA + }, + + //--- TCI_ORANGE + { + TCI_BLACK, // TCI_BLACK + TCI_DARKGRAY, // TCI_DARKGRAY + TCI_WHITE, // TCI_LIGHTGRAY + TCI_WHITE, // TCI_WHITE + TCI_RED, // TCI_RED + TCI_B_ORANGE, // TCI_ORANGE + TCI_B_YELLOW, // TCI_YELLOW + TCI_B_GREEN, // TCI_GREEN + TCI_B_CYAN, // TCI_CYAN + TCI_BLUE, // TCI_BLUE + TCI_MAGENTA, // TCI_MAGENTA + }, + + //--- TCI_YELLOW + { + TCI_BLACK, // TCI_BLACK + TCI_DARKGRAY, // TCI_DARKGRAY + TCI_WHITE, // TCI_LIGHTGRAY + TCI_WHITE, // TCI_WHITE + TCI_RED, // TCI_RED + TCI_ORANGE, // TCI_ORANGE + TCI_B_YELLOW, // TCI_YELLOW + TCI_B_GREEN, // TCI_GREEN + TCI_B_CYAN, // TCI_CYAN + TCI_BLUE, // TCI_BLUE + TCI_MAGENTA, // TCI_MAGENTA + }, + + //--- TCI_GREEN + { + TCI_BLACK, // TCI_BLACK + TCI_DARKGRAY, // TCI_DARKGRAY + TCI_LIGHTGRAY, // TCI_LIGHTGRAY + TCI_WHITE, // TCI_WHITE + TCI_RED, // TCI_RED + TCI_ORANGE, // TCI_ORANGE + TCI_B_YELLOW, // TCI_YELLOW + TCI_B_GREEN, // TCI_GREEN + TCI_B_CYAN, // TCI_CYAN + TCI_BLUE, // TCI_BLUE + TCI_MAGENTA, // TCI_MAGENTA + }, + + //--- TCI_CYAN + { + TCI_BLACK, // TCI_BLACK + TCI_DARKGRAY, // TCI_DARKGRAY + TCI_LIGHTGRAY, // TCI_LIGHTGRAY + TCI_WHITE, // TCI_WHITE + TCI_RED, // TCI_RED + TCI_ORANGE, // TCI_ORANGE + TCI_B_YELLOW, // TCI_YELLOW + TCI_B_GREEN, // TCI_GREEN + TCI_B_CYAN, // TCI_CYAN + TCI_BLUE, // TCI_BLUE + TCI_MAGENTA, // TCI_MAGENTA + }, + + //--- TCI_BLUE + { + TCI_BLACK, // TCI_BLACK + TCI_LIGHTGRAY, // TCI_DARKGRAY + TCI_LIGHTGRAY, // TCI_LIGHTGRAY + TCI_WHITE, // TCI_WHITE + TCI_RED, // TCI_RED + TCI_ORANGE, // TCI_ORANGE + TCI_B_YELLOW, // TCI_YELLOW + TCI_B_GREEN, // TCI_GREEN + TCI_B_CYAN, // TCI_CYAN + TCI_CYAN, // TCI_BLUE + TCI_B_MAGENTA, // TCI_MAGENTA + }, + + //--- TCI_MAGENTA + { + TCI_BLACK, // TCI_BLACK + TCI_LIGHTGRAY, // TCI_DARKGRAY + TCI_LIGHTGRAY, // TCI_LIGHTGRAY + TCI_WHITE, // TCI_WHITE + TCI_RED, // TCI_RED + TCI_ORANGE, // TCI_ORANGE + TCI_B_YELLOW, // TCI_YELLOW + TCI_B_GREEN, // TCI_GREEN + TCI_B_CYAN, // TCI_CYAN + TCI_CYAN, // TCI_BLUE + TCI_B_MAGENTA, // TCI_MAGENTA + }, + + //--- TCI_B_RED + { + TCI_BLACK, // TCI_BLACK + TCI_DARKGRAY, // TCI_DARKGRAY + TCI_WHITE, // TCI_LIGHTGRAY + TCI_WHITE, // TCI_WHITE + TCI_RED, // TCI_RED + TCI_ORANGE, // TCI_ORANGE + TCI_B_YELLOW, // TCI_YELLOW + TCI_B_GREEN, // TCI_GREEN + TCI_B_CYAN, // TCI_CYAN + TCI_BLUE, // TCI_BLUE + TCI_MAGENTA, // TCI_MAGENTA + }, + + //--- TCI_B_ORANGE + { + TCI_BLACK, // TCI_BLACK + TCI_DARKGRAY, // TCI_DARKGRAY + TCI_WHITE, // TCI_LIGHTGRAY + TCI_WHITE, // TCI_WHITE + TCI_RED, // TCI_RED + TCI_ORANGE, // TCI_ORANGE + TCI_B_YELLOW, // TCI_YELLOW + TCI_B_GREEN, // TCI_GREEN + TCI_B_CYAN, // TCI_CYAN + TCI_BLUE, // TCI_BLUE + TCI_MAGENTA, // TCI_MAGENTA + }, + + //--- TCI_B_YELLOW + { + TCI_BLACK, // TCI_BLACK + TCI_DARKGRAY, // TCI_DARKGRAY + TCI_DARKGRAY, // TCI_LIGHTGRAY + TCI_DARKGRAY, // TCI_WHITE + TCI_RED, // TCI_RED + TCI_ORANGE, // TCI_ORANGE + TCI_YELLOW, // TCI_YELLOW + TCI_GREEN, // TCI_GREEN + TCI_CYAN, // TCI_CYAN + TCI_BLUE, // TCI_BLUE + TCI_MAGENTA, // TCI_MAGENTA + }, + + //--- TCI_B_GREEN + { + TCI_BLACK, // TCI_BLACK + TCI_DARKGRAY, // TCI_DARKGRAY + TCI_DARKGRAY, // TCI_LIGHTGRAY + TCI_WHITE, // TCI_WHITE + TCI_RED, // TCI_RED + TCI_ORANGE, // TCI_ORANGE + TCI_B_YELLOW, // TCI_YELLOW + TCI_GREEN, // TCI_GREEN + TCI_CYAN, // TCI_CYAN + TCI_BLUE, // TCI_BLUE + TCI_MAGENTA, // TCI_MAGENTA + }, + + //--- TCI_B_CYAN + { + TCI_BLACK, // TCI_BLACK + TCI_DARKGRAY, // TCI_DARKGRAY + TCI_DARKGRAY, // TCI_LIGHTGRAY + TCI_WHITE, // TCI_WHITE + TCI_RED, // TCI_RED + TCI_ORANGE, // TCI_ORANGE + TCI_YELLOW, // TCI_YELLOW + TCI_GREEN, // TCI_GREEN + TCI_CYAN, // TCI_CYAN + TCI_BLUE, // TCI_BLUE + TCI_MAGENTA, // TCI_MAGENTA + }, + + //--- TCI_B_BLUE + { + TCI_BLACK, // TCI_BLACK + TCI_DARKGRAY, // TCI_DARKGRAY + TCI_DARKGRAY, // TCI_LIGHTGRAY + TCI_WHITE, // TCI_WHITE + TCI_RED, // TCI_RED + TCI_B_ORANGE, // TCI_ORANGE + TCI_B_YELLOW, // TCI_YELLOW + TCI_B_GREEN, // TCI_GREEN + TCI_B_CYAN, // TCI_CYAN + TCI_CYAN, // TCI_BLUE + TCI_MAGENTA, // TCI_MAGENTA + }, + + //--- TCI_B_MAGENTA + { + TCI_BLACK, // TCI_BLACK + TCI_DARKGRAY, // TCI_DARKGRAY + TCI_DARKGRAY, // TCI_LIGHTGRAY + TCI_WHITE, // TCI_WHITE + TCI_RED, // TCI_RED + TCI_B_ORANGE, // TCI_ORANGE + TCI_B_YELLOW, // TCI_YELLOW + TCI_GREEN, // TCI_GREEN + TCI_B_CYAN, // TCI_CYAN + TCI_CYAN, // TCI_BLUE + TCI_MAGENTA, // TCI_MAGENTA + }, + }; + + const uint font = font_index < TCI_B_RED ? font_index + : font_index - (TCI_B_RED-TCI_RED); + font_index = tab[bg_index][font]; + } + + + //--- color index + + static const u8 color_index_8[] = + { + 0, // TCI_BLACK + 8, // TCI_DARKGRAY + 7, // TCI_LIGHTGRAY + 15, // TCI_WHITE + + 1, // TCI_RED + 1, // TCI_ORANGE + 3, // TCI_YELLOW + 2, // TCI_GREEN + 6, // TCI_CYAN + 4, // TCI_BLUE + 5, // TCI_MAGENTA + + 9, // TCI_B_RED + 9, // TCI_B_ORANGE + 11, // TCI_B_YELLOW + 10, // TCI_B_GREEN + 14, // TCI_B_CYAN + 12, // TCI_B_BLUE + 13, // TCI_B_MAGENTA + }; + + static const u8 color_index_256[] = + { + 0, // TCI_BLACK + 8, // TCI_DARKGRAY + 7, // TCI_LIGHTGRAY + 15, // TCI_WHITE + + 160, // TCI_RED + 172, // TCI_ORANGE + 142, // TCI_YELLOW + 34, // TCI_GREEN + 37, // TCI_CYAN + 21, // TCI_BLUE + 164, // TCI_MAGENTA + + 196, // TCI_B_RED + 208, // TCI_B_ORANGE + 226, // TCI_B_YELLOW + 46, // TCI_B_GREEN + 51, // TCI_B_CYAN + 105, // TCI_B_BLUE + 207, // TCI_B_MAGENTA + }; + + const u8 *color_index; + uint x_bg; + if ( col_mode == COLMD_256_COLORS ) + { + color_index = color_index_256; + x_bg = 8; + } + else + { + color_index = color_index_8; + x_bg = 16; + option |= GCM_SHORT; + } + + + //--- output + + char buf[100], *end = buf + sizeof(buf); + char *dest = StringCopyE(buf,end,TermTextModeBeg); + + ccp sep = ""; + if ( (uint)font_index < TCI__IGNORE ) + { + const uint idx = color_index[font_index]; + if ( !(option & GCM_SHORT) || idx >= 16 ) + dest = snprintfE(dest,end,"38;5;%u",idx); + else if ( idx < 8 ) + dest = snprintfE(dest,end,"0;%u",30+idx); + else + dest = snprintfE(dest,end,"1;%u",22+idx); + sep = ";"; + } + + if ( (uint)bg_index < TCI__IGNORE ) + { + const uint idx = color_index[bg_index]; + if ( !(option & GCM_SHORT) || idx >= x_bg ) + dest = snprintfE(dest,end,"%s48;5;%u",sep,idx); + else + dest = snprintfE(dest,end,"%s%u",sep,40+(idx&7)); + } + + dest = StringCopyE(dest,end,TermTextModeEnd); + const int len = dest + 1 - buf; + char *res = GetColorCircBuf(len); + memcpy(res,buf,len); + return res; + } + +#endif // !SUPPORT_36_COLORS + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// colors /////////////// +/////////////////////////////////////////////////////////////////////////////// + +const ColorSet_t * GetColorSet0() +{ + static ColorSet_t col = {0}; + if (!col.col_mode) + { + col.col_mode = COLMD_OFF; + col.colorize = false; + col.n_colors = 0; + + col.space = EmptyString; + col.tab = EmptyString; + col.lf = EmptyString; + + ccp *ptr = &col.reset; + ccp *end = (ccp*)((ccp)&col + sizeof(col)); + while ( ptr < end ) + *ptr++ = EmptyString; + } + return &col; +} + +/////////////////////////////////////////////////////////////////////////////// + +const ColorSet_t * GetColorSet8() +{ + static ColorSet_t col = {0}; + if (!col.col_mode) + { + col.col_mode = COLMD_8_COLORS; + col.colorize = true; + col.n_colors = 8; + + col.space = Space200; + col.tab = Tabs20; + col.lf = LF20; + + col.reset = TermTextModeReset; + col.setup = STRDUP(GetTextMode(1,TTM_COL_SETUP)); + col.run = STRDUP(GetTextMode(1,TTM_COL_RUN)); + col.abort = STRDUP(GetTextMode(1,TTM_COL_ABORT)); + col.finish = STRDUP(GetTextMode(1,TTM_COL_FINISH)); + col.script = STRDUP(GetTextMode(1,TTM_COL_SCRIPT)); + col.open = STRDUP(GetTextMode(1,TTM_COL_OPEN)); + col.close = STRDUP(GetTextMode(1,TTM_COL_CLOSE)); + col.file = STRDUP(GetTextMode(1,TTM_COL_FILE)); + col.job = STRDUP(GetTextMode(1,TTM_COL_JOB)); + col.info = STRDUP(GetTextMode(1,TTM_COL_INFO)); + col.hint = STRDUP(GetTextMode(1,TTM_COL_HINT)); + col.warn = STRDUP(GetTextMode(1,TTM_COL_WARN)); + col.debug = STRDUP(GetTextMode(1,TTM_COL_DEBUG)); + col.log = STRDUP(GetTextMode(1,TTM_COL_LOG)); + col.name = STRDUP(GetTextMode(1,TTM_COL_NAME)); + col.value = STRDUP(GetTextMode(1,TTM_COL_VALUE)); + col.success = STRDUP(GetTextMode(1,TTM_COL_SUCCESS)); + col.error = STRDUP(GetTextMode(1,TTM_COL_ERROR)); + col.fail = STRDUP(GetTextMode(1,TTM_COL_FAIL)); + col.fail2 = STRDUP(GetTextMode(1,TTM_COL_FAIL2)); + col.fatal = STRDUP(GetTextMode(1,TTM_COL_FATAL)); + col.mark = STRDUP(GetTextMode(1,TTM_COL_MARK)); + col.bad = STRDUP(GetTextMode(1,TTM_COL_BAD)); + col.select = STRDUP(GetTextMode(1,TTM_COL_SELECT)); + col.differ = STRDUP(GetTextMode(1,TTM_COL_DIFFER)); + col.stat_line = STRDUP(GetTextMode(1,TTM_COL_STAT_LINE)); + col.warn_line = STRDUP(GetTextMode(1,TTM_COL_WARN_LINE)); + col.proc_line = STRDUP(GetTextMode(1,TTM_COL_PROC_LINE)); + col.cite = STRDUP(GetTextMode(1,TTM_COL_CITE)); + col.status = STRDUP(GetTextMode(1,TTM_COL_STATUS)); + col.highlight = STRDUP(GetTextMode(1,TTM_COL_HIGHLIGHT)); + col.hide = STRDUP(GetTextMode(1,TTM_COL_HIDE)); + col.heading = STRDUP(GetTextMode(1,TTM_COL_HEADING)); + col.caption = STRDUP(GetTextMode(1,TTM_COL_CAPTION)); + col.section = STRDUP(GetTextMode(1,TTM_COL_SECTION)); + col.syntax = STRDUP(GetTextMode(1,TTM_COL_SYNTAX)); + col.cmd = STRDUP(GetTextMode(1,TTM_COL_CMD)); + col.option = STRDUP(GetTextMode(1,TTM_COL_OPTION)); + col.param = STRDUP(GetTextMode(1,TTM_COL_PARAM)); + col.on = STRDUP(GetTextMode(1,TTM_COL_ON)); + col.off = STRDUP(GetTextMode(1,TTM_COL_OFF)); + + col.black = STRDUP(GetTextMode(1,TTM_NO_BOLD|TTM_BLACK)); + col.b_black = STRDUP(GetTextMode(1,TTM_BOLD|TTM_BLACK)); + col.white = STRDUP(GetTextMode(1,TTM_NO_BOLD|TTM_WHITE)); + col.b_white = STRDUP(GetTextMode(1,TTM_BOLD|TTM_WHITE)); + + col.red = STRDUP(GetTextMode(1,TTM_NO_BOLD|TTM_RED)); + col.red_orange = col.red; + col.orange = col.red; + col.yellow = STRDUP(GetTextMode(1,TTM_NO_BOLD|TTM_YELLOW)); + col.orange_yellow = col.yellow; + col.yellow_green = col.yellow; + col.green = STRDUP(GetTextMode(1,TTM_NO_BOLD|TTM_GREEN)); + col.green_cyan = col.green; + col.cyan = STRDUP(GetTextMode(1,TTM_NO_BOLD|TTM_CYAN)); + col.cyan_blue = col.cyan; + col.blue = STRDUP(GetTextMode(1,TTM_NO_BOLD|TTM_BLUE)); + col.blue_magenta = col.blue; + col.magenta = STRDUP(GetTextMode(1,TTM_NO_BOLD|TTM_MAGENTA)); + col.magenta_red = col.magenta; + + col.b_red = STRDUP(GetTextMode(1,TTM_BOLD|TTM_RED)); + col.b_red_orange = col.b_red; + col.b_orange = col.b_red; + col.b_yellow = STRDUP(GetTextMode(1,TTM_BOLD|TTM_YELLOW)); + col.b_orange_yellow = col.b_yellow; + col.b_yellow_green = col.b_yellow; + col.b_green = STRDUP(GetTextMode(1,TTM_BOLD|TTM_GREEN)); + col.b_green_cyan = col.b_green; + col.b_cyan = STRDUP(GetTextMode(1,TTM_BOLD|TTM_CYAN)); + col.b_cyan_blue = col.b_cyan; + col.b_blue = STRDUP(GetTextMode(1,TTM_BOLD|TTM_BLUE)); + col.b_blue_magenta = col.b_blue; + col.b_magenta = STRDUP(GetTextMode(1,TTM_BOLD|TTM_MAGENTA)); + col.b_magenta_red = col.b_magenta; + + TermColorIndex_t font, bg; + for ( font = 0; font < TCI__N_FONT; font++ ) + for ( bg = 0; bg < TCI__N_BG; bg++ ) + col.matrix[font][bg] + = STRDUP(GetColorMode(COLMD_8_COLORS,font,bg,GCM_ALT|GCM_SHORT)); + } + + return &col; +} + +/////////////////////////////////////////////////////////////////////////////// + +const ColorSet_t * GetColorSet256() +{ + static ColorSet_t col = {0}; + if (!col.col_mode) + { + //--- default settings (copy of 8-COLORS) + + memcpy(&col,GetColorSet8(),sizeof(col)); + col.col_mode = COLMD_256_COLORS; + col.n_colors = 256; + + + //--- special settings + + col.setup = "\e[38;5;86;40m"; + col.run = "\e[38;5;229;40m"; + col.abort = "\e[38;5;198;40m"; + col.finish = "\e[38;5;154;40m"; + col.script = "\e[0;30;48;5;219m"; + col.open = "\e[38;5;225;40m"; + col.close = "\e[38;5;219;40m"; + col.heading = "\e[38;5;111;40m"; + col.info = "\e[38;5;49;40m"; + col.hint = "\e[38;5;220;40m"; + col.warn = "\e[38;5;208;40m"; + col.debug = "\e[38;5;210;40m"; + col.error = "\e[38;5;255;48;5;130m"; + col.fail = "\e[38;5;251;48;5;88m"; + col.fail2 = "\e[38;5;255;48;5;88m"; + col.fatal = "\e[38;5;255;48;5;129m"; + col.differ = "\e[38;5;226;48;5;19m"; + col.stat_line = "\e[38;5;231;48;5;19m"; + col.warn_line = "\e[38;5;215;48;5;19m"; + col.hide = "\e[38;5;245;40m"; + + + //--- special settings: color names + + // dark: + // ./mkw-ana testcol 400-420 420-330 330-030 030-033 033-005 005-404 404-400 + // ./mkw-ana testcol 400 410 420 320 330 230 030 032 033 024 005 204 404 402 400 + + col.red = "\e[38;5;160m"; + col.red_orange = "\e[38;5;166m"; + col.orange = "\e[38;5;172m"; + col.orange_yellow = "\e[38;5;136m"; + col.yellow = "\e[38;5;142m"; + col.yellow_green = "\e[38;5;106m"; + col.green = "\e[38;5;34m"; + col.green_cyan = "\e[38;5;36m"; + col.cyan = "\e[38;5;37m"; + col.cyan_blue = "\e[38;5;32m"; + col.blue = "\e[38;5;21m"; + col.blue_magenta = "\e[38;5;92m"; + col.magenta = "\e[38;5;164m"; + col.magenta_red = "\e[38;5;162m"; + + // bold: + // ./mkw-ana testcol 500-520 520-550 550-050 050-055 055-225 225-515 515-500 + // ./mkw-ana testcol 500 510 520 530 550 350 050 053 055 135 225 425 515 512 500 + + col.b_red = "\e[38;5;196m"; + col.b_red_orange = "\e[38;5;202m"; + col.b_orange = "\e[38;5;208m"; + col.b_orange_yellow = "\e[38;5;214m"; + col.b_yellow = "\e[38;5;226m"; + col.b_yellow_green = "\e[38;5;154m"; + col.b_green = "\e[38;5;46m"; + col.b_green_cyan = "\e[38;5;49m"; + col.b_cyan = "\e[38;5;51m"; + col.b_cyan_blue = "\e[38;5;75m"; + col.b_blue = "\e[38;5;105m"; + col.b_blue_magenta = "\e[38;5;177m"; + col.b_magenta = "\e[38;5;207m"; + col.b_magenta_red = "\e[38;5;204m"; + + TermColorIndex_t font, bg; + for ( font = 0; font < TCI__N_FONT; font++ ) + for ( bg = 0; bg < TCI__N_BG; bg++ ) + col.matrix[font][bg] + = STRDUP(GetColorMode(COLMD_256_COLORS,font,bg,GCM_ALT|GCM_SHORT)); + } + + return &col; + +//---------- old definitions ---------- +// +// col.differ = STRDUP(GetColorMode(COLMD_256_COLORS, +// TCI_YELLOW, TCI_BLUE, GCM_ALT|GCM_SHORT )); +// col.stat_line = STRDUP(GetColorMode(COLMD_256_COLORS, +// TCI_WHITE, TCI_BLUE, GCM_ALT|GCM_SHORT )); +// col.warn_line = STRDUP(GetColorMode(COLMD_256_COLORS, +// TCI_ORANGE, TCI_BLUE, GCM_ALT|GCM_SHORT )); +// +// col.orange = STRDUP(GetColorMode(COLMD_256_COLORS, +// TCI_ORANGE, TCI__IGNORE, GCM_ALT|GCM_SHORT )); +// col.b_orange = STRDUP(GetColorMode(COLMD_256_COLORS, +// TCI_B_ORANGE, TCI__IGNORE, GCM_ALT|GCM_SHORT )); +// +//------------------------------------- +} + +/////////////////////////////////////////////////////////////////////////////// + +int setupterm(char *term, int fildes, int *errret); +int tigetnum(char *capname); + +const ColorSet_t * GetColorSetAuto ( bool force_on ) +{ + static ColorMode_t auto_mode = COLMD_AUTO; + if ( opt_colorize != COLMD_AUTO ) + { + if ( opt_colorize == COLMD_ON ) + force_on = true; + else + auto_mode = opt_colorize; + } + + if ( auto_mode == COLMD_AUTO ) + { + int error; + setupterm(getenv("TERM"),1,&error); + const int ncol = tigetnum("colors"); + + auto_mode = ncol >= 256 ? COLMD_256_COLORS + : ncol >= 8 ? COLMD_8_COLORS + : COLMD_OFF; + if ( auto_mode == COLMD_OFF && !strcmp(getenv("TERM"),"cygwin") ) + auto_mode = COLMD_8_COLORS; + + #ifdef TEST + fprintf(stderr,">>> GetColorSetAuto(%d) => \"%s\" n=%d => %d [%s]\n", + force_on, getenv("TERM"), ncol, + auto_mode, GetColorModeName(auto_mode,0) ); + #endif + } + + switch(auto_mode) + { + case COLMD_8_COLORS: + return GetColorSet8(); + + case COLMD_256_COLORS: + return GetColorSet256(); + + default: + return force_on ? GetColorSet8() : GetColorSet0(); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +const ColorSet_t * GetColorSet ( ColorMode_t col_mode ) +{ + switch(col_mode) + { + case COLMD_AUTO: + return GetColorSetAuto(false); + + case COLMD_ON: + return GetColorSetAuto(true); + + case COLMD_8_COLORS: + return GetColorSet8(); + + case COLMD_256_COLORS: + return GetColorSet256(); + + default: + return GetColorSet0(); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +const ColorSet_t * GetFileColorSet ( FILE *f ) +{ + return GetColorSet(GetFileColorized(f)); +} + +/////////////////////////////////////////////////////////////////////////////// + +bool SetupColorSet ( ColorSet_t *cs, FILE *f ) +{ + DASSERT(cs); + memcpy(cs,GetColorSet(GetFileColorized(f)),sizeof(*cs)); + return cs->colorize; +} + +/////////////////////////////////////////////////////////////////////////////// + +ccp GetColorByName ( const ColorSet_t *colset, ccp name ) +{ + struct cdef_t + { + u16 delta; + char name[16]; + }; + + #undef DEF1 + #undef DEF2 + #define DEF1(n) { offsetof(ColorSet_t,n), #n }, + #define DEF2(t,n) { offsetof(ColorSet_t,n), #t }, + + static const struct cdef_t tab[] = + { + DEF1(abort) + DEF1(b_black) + DEF1(b_blue) + DEF1(b_blue_magenta) + DEF1(b_cyan) + DEF1(b_cyan_blue) + DEF1(b_green) + DEF1(b_green_cyan) + DEF1(b_magenta) + DEF1(b_magenta_red) + DEF1(b_orange) + DEF1(b_orange_yellow) + DEF1(b_red) + DEF1(b_red_orange) + DEF1(b_white) + DEF1(b_yellow) + DEF1(b_yellow_green) + DEF1(bad) + DEF1(black) + DEF1(blue) + DEF1(blue_magenta) + DEF1(caption) + DEF1(cite) + DEF1(close) + DEF1(cmd) + DEF1(cyan) + DEF1(cyan_blue) + DEF1(debug) + DEF1(differ) + DEF1(error) + DEF1(fail) + DEF1(fail2) + DEF1(fatal) + DEF1(file) + DEF1(finish) + DEF1(green) + DEF1(green_cyan) + DEF2(head,heading) + DEF1(heading) + DEF1(hide) + DEF1(highlight) + DEF1(hint) + DEF2(hl,highlight) + DEF1(info) + DEF1(job) + DEF1(log) + DEF1(magenta) + DEF1(magenta_red) + DEF1(mark) + DEF1(name) + DEF1(off) + DEF1(on) + DEF1(open) + DEF2(opt,option) + DEF1(option) + DEF1(orange) + DEF1(orange_yellow) + DEF2(par,param) + DEF1(param) + DEF1(proc_line) + DEF1(red) + DEF1(red_orange) + DEF1(reset) + DEF1(run) + DEF1(script) + DEF1(section) + DEF1(select) + DEF1(setup) + DEF1(stat_line) + DEF1(status) + DEF1(success) + DEF1(syntax) + DEF2(val,value) + DEF1(value) + DEF1(warn) + DEF1(warn_line) + DEF1(white) + DEF1(yellow) + DEF1(yellow_green) + }; + + #if HAVE_PRINT + static bool done = false; + if (!done) + { + done = true; + uint i, max_len = 0, err_count = 0; + const struct cdef_t *cd = tab; + for ( i = 0; i < sizeof(tab)/sizeof(*tab); i++, cd++ ) + { + if ( max_len < strlen(cd->name) ) + max_len = strlen(cd->name); + + if ( i > 0 && strcmp(cd[-1].name,cd->name) >= 0 ) + { + err_count++; + PRINT("WRONG COL ORDER: %s > %s\n", cd[-1].name, cd->name); + } + } + + DASSERT_MSG( max_len < sizeof(cd->name), + "%s(): max name len = %d, possible = %zd\n", + __FUNCTION__, max_len, sizeof(cd->name)-1 ); + DASSERT_MSG( !err_count, + "%s(): color order is %d* wrong!\n", + __FUNCTION__, err_count ); + } + #endif + + //--- search the name + + if ( colset && name ) + { + int beg = 0; + int end = sizeof(tab)/sizeof(*tab) - 1; + while ( beg <= end ) + { + const uint idx = (beg+end)/2; + const int stat = strcmp(name,tab[idx].name); + if ( stat < 0 ) + end = idx - 1 ; + else if ( stat > 0 ) + beg = idx + 1; + else + return *(ccp*)((u8*)colset+tab[idx].delta); + } + } + return EmptyString; +} + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +void PrintColorSetHelper +( + FILE *f, // valid output file + int indent, // indention of output + const ColorSet_t *cs, // valid color set; if NULL: use std colors + PrintColorFunc func, // output function, never NULL + uint mode // output mode (bit field, NULL=default): + // 1: print normal colors (e.g. RED) + // 2: print bold colors (e.g. B_RED) + // 4: print background (e.g. BLUE_RED) + // 8: print color names (e.g. HIGHLIGHT) + // 16: include alternative names too (e.g. HL) +) +{ + DASSERT(f); + DASSERT(func); + + if (!cs) + cs = GetColorSet(COLMD_ON); + indent = NormalizeIndent(indent) + 10; // +10 is max name width + if (!mode) + mode = 15; + + #undef JOB1 + #undef JOB2 + #define JOB1(m,n) func(f,indent,cs,m,#n,cs->n) + #define JOB2(m,t,n) func(f,indent,cs,m,#t,cs->n) + + if ( mode & 1 ) + { + func(f,indent,cs,1,0,0); + JOB1(1,black); + JOB1(1,red); + JOB1(1,red_orange); + JOB1(1,orange); + JOB1(1,orange_yellow); + JOB1(1,yellow); + JOB1(1,yellow_green); + JOB1(1,green); + JOB1(1,green_cyan); + JOB1(1,cyan); + JOB1(1,cyan_blue); + JOB1(1,blue); + JOB1(1,blue_magenta); + JOB1(1,magenta); + JOB1(1,magenta_red); + JOB1(1,white); + } + + if ( mode & 2 ) + { + func(f,indent,cs,2,0,0); + JOB1(2,b_black); + JOB1(2,b_red); + JOB1(2,b_red_orange); + JOB1(2,b_orange); + JOB1(2,b_orange_yellow); + JOB1(2,b_yellow); + JOB1(2,b_yellow_green); + JOB1(2,b_green); + JOB1(2,b_green_cyan); + JOB1(2,b_cyan); + JOB1(2,b_cyan_blue); + JOB1(2,b_blue); + JOB1(2,b_blue_magenta); + JOB1(2,b_magenta); + JOB1(2,b_magenta_red); + JOB1(2,b_white); + } + + if ( mode & 8 ) + { + const bool alt = ( mode & 16 ) != 0; + func(f,indent,cs,8,0,0); + + JOB1(4,setup); + JOB1(4,run); + JOB1(4,abort); + JOB1(4,finish); + JOB1(4,script); + JOB1(4,open); + JOB1(4,close); + JOB1(4,file); + JOB1(4,job); + + JOB1(4,info); + JOB1(4,hint); + JOB1(4,warn); + JOB1(4,debug); + JOB1(4,log); + + JOB1(4,name); + JOB1(4,value); if (alt) JOB2(12,val,value); + JOB1(4,success); + JOB1(4,error); + JOB1(4,fail); + JOB1(4,fail2); + JOB1(4,fatal); + JOB1(4,mark); + JOB1(4,bad); + + JOB1(4,select); + JOB1(4,differ); + JOB1(4,stat_line); + JOB1(4,warn_line); + JOB1(4,proc_line); + JOB1(4,cite); + JOB1(4,status); + JOB1(4,highlight); if (alt) JOB2(12,hl,highlight); + JOB1(4,hide); + + JOB1(4,heading); if (alt) JOB2(12,head,heading); + JOB1(4,caption); + JOB1(4,section); + JOB1(4,syntax); + JOB1(4,cmd); + JOB1(4,option); if (alt) JOB2(12,opt,option); + JOB1(4,param); if (alt) JOB2(12,par,param); + + JOB1(4,off); + JOB1(4,on); + } + + #undef JOB1 + #undef JOB2 +} + +/////////////////////////////////////////////////////////////////////////////// + +static void PrintColorSetCOL +( + // On start of group: col_name := NULL, col_string := NULL + + FILE *f, // valid output file + int indent, // normalized indention of output + const ColorSet_t *cs, // valid color set, never NULL + uint mode, // output mode of PrintColorSetHelper() + ccp col_name, // name of color + ccp col_string // escape string for the color +) +{ + if (!col_name) + fputc('\n',f); + else + { + DASSERT(col_string); + #ifdef TEST + fprintf(f,"%*s %s %s %s | %s %s %s\n", \ + indent, col_name, col_string, col_name, cs->reset, + GetColorByName(cs,col_name), col_name, cs->reset ); + #else + fprintf(f,"%*s %s %s %s\n", + indent, col_name, col_string, col_name, cs->reset ); + #endif + } +} + +//----------------------------------------------------------------------------- + +static void PrintColorSetSH +( + // On start of group: col_name := NULL, col_string := NULL + + FILE *f, // valid output file + int indent, // normalized indention of output + const ColorSet_t *cs, // valid color set, never NULL + uint mode, // output mode of PrintColorSetHelper() + ccp col_name, // name of color + ccp col_string // escape string for the color +) +{ + if (col_name) + { + DASSERT(col_string); + + char name[50], buf[50]; + char *dest = name; + while ( *col_name && dest < name + sizeof(name) - 1 ) + *dest++ = toupper((int)*col_name++); + *dest = 0; + + PrintEscapedString(buf,sizeof(buf),col_string,-1,CHMD_ESC,0,0); + if (memcmp(buf,"\\x1B",4)) + fprintf(f,"COL_%s=$'%s'\n",name,buf); + else + fprintf(f,"COL_%s='\\033%s'\n",name,buf+4); + } +} + +//----------------------------------------------------------------------------- + +static void PrintColorSetPHP +( + // On start of group: col_name := NULL, col_string := NULL + + FILE *f, // valid output file + int indent, // normalized indention of output + const ColorSet_t *cs, // valid color set, never NULL + uint mode, // output mode of PrintColorSetHelper() + ccp col_name, // name of color + ccp col_string // escape string for the color +) +{ + if (col_name) + { + DASSERT(col_string); + + char buf[50]; + PrintEscapedString(buf,sizeof(buf),col_string,-1,CHMD_ESC,0,0); + if (memcmp(buf,"\\x1B",4)) + fprintf(f,"$COL->%-15s = \"%s\";\n",col_name,buf); + else + fprintf(f,"$COL->%-15s = \"\\033%s\";\n",col_name,buf+4); + } +} + +//----------------------------------------------------------------------------- + +void PrintColorSet +( + FILE *f, // valid output file + int indent, // indention of output + const ColorSet_t *cs // valid color set; if NULL: use std colors +) +{ + DASSERT(f); + PrintColorSetHelper(f,indent,cs,PrintColorSetCOL,4); + fputc('\n',f); +} + +//----------------------------------------------------------------------------- + +void PrintColorSetEx +( + FILE *f, // valid output file + int indent, // indention of output + const ColorSet_t *cs, // valid color set; if NULL: use std colors + uint mode, // output mode => see PrintColorSetHelper() + uint format // output format + // 0: colored list + // 1: shell definitions + // 2: php class +) +{ + DASSERT(f); + char buf[50]; + + switch(format) + { + case 1: + if (!cs) + cs = GetColorSet(COLMD_ON); + PrintColorSetHelper(f,indent,cs,PrintColorSetSH,mode); + PrintEscapedString(buf,sizeof(buf),cs->reset,-1,CHMD_ESC,0,0); + if (memcmp(buf,"\\x1B",4)) + fprintf(f,"COL0=$'%s'\n",buf); + else + fprintf(f,"COL0=$'\\033%s'\n",buf+4); + break; + + case 2: + if (!cs) + cs = GetColorSet(COLMD_ON); + PrintColorSetHelper(f,indent,cs,PrintColorSetPHP,mode); + break; + + default: + PrintColorSetHelper(f,indent,cs,PrintColorSetCOL,mode); + fputc('\n',f); + break; + } +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// ViewColor*() /////////////// +/////////////////////////////////////////////////////////////////////////////// + +void SetupColorView ( ColorView_t *cv ) +{ + DASSERT(cv); + + if (!cv->f) + cv->f = stdout; + cv->indent = NormalizeIndent(cv->indent); + +#ifdef DCLIB_TERMINAL + cv->col_mode = cv->colset + ? cv->colset->col_mode + : NormalizeColorMode(cv->col_mode, + cv->term ? cv->term->colors : 8 ); +#else + cv->col_mode = cv->colset + ? cv->colset->col_mode + : NormalizeColorMode(cv->col_mode,8); +#endif + if (!cv->colset) + cv->colset = GetColorSet(cv->col_mode); + + switch(cv->order) + { + case 'r': case 'R': cv->order = 0; break; + case 'g': case 'G': cv->order = 1; break; + case 'b': case 'B': cv->order = 2; break; + } +} + +/////////////////////////////////////////////////////////////////////////////// + +void SetupColorViewMode ( ColorView_t *cv, ColorMode_t col_mode ) +{ + DASSERT(cv); + cv->col_mode = col_mode; + cv->colset = 0; + SetupColorView(cv); +} + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +static ccp col_names[] = +{ + "black:", + "red:", + "green:", + "yellow:", + "blue:", + "magenta:", + "cyan:", + "white:", + 0 +}; + +//----------------------------------------------------------------------------- + +void ViewColorsAttrib8 ( ColorView_t *cv ) +{ + DASSERT(cv); + SetupColorView(cv); + DASSERT(cv->colset); + + #ifdef TEST + fprintf(cv->f,"%*s%s() %s, %u colors, mode %d, stdcol %d, order %d\n", + cv->indent,"", __FUNCTION__, + GetColorModeName(cv->colset->col_mode,0), + cv->colset->n_colors, cv->mode, cv->std_col, cv->order ); + #endif + + //-------------------------------------------------- + + fprintf(cv->f, + "%s\n%*sStandard font colors with attributes (ul=underline) for mode %s:\n\n", + cv->colset->reset, cv->indent, "", + GetColorModeName(cv->col_mode,0) ); + + uint fg = 0, bg = 0; + switch( (int)cv->std_col ) + { + case TCI_BLACK: + case TCI_DARKGRAY: fg = TTM_WHITE|TTM_BOLD; bg = TTM_BG_BLACK; break; + case TCI_LIGHTGRAY: + case TCI_WHITE: fg = TTM_BLACK; bg = TTM_BG_WHITE; break; + case TCI_RED: + case TCI_B_RED: + case TCI_ORANGE: + case TCI_B_ORANGE: fg = TTM_WHITE|TTM_BOLD; bg = TTM_BG_RED; break; + case TCI_YELLOW: + case TCI_B_YELLOW: fg = TTM_BLACK; bg = TTM_BG_YELLOW; break; + case TCI_GREEN: + case TCI_B_GREEN: fg = TTM_WHITE|TTM_BOLD; bg = TTM_BG_GREEN; break; + case TCI_CYAN: + case TCI_B_CYAN: fg = TTM_BLACK; bg = TTM_BG_CYAN; break; + case TCI_BLUE: + case TCI_B_BLUE: fg = TTM_WHITE|TTM_BOLD; bg = TTM_BG_BLUE; break; + case TCI_MAGENTA: + case TCI_B_MAGENTA: fg = TTM_WHITE|TTM_BOLD; bg = TTM_BG_MAGENTA; break; + } + + ccp *cname; + TermTextMode_t mode = TTM_BLACK; + for ( cname = col_names; *cname; cname++, mode += 0x01 ) + { + fprintf(cv->f,"%*s%s %u %-9s %snormal %sbold %sbold+ul %sul%s reset %s\n", + cv->indent, "", + GetTextMode(cv->col_mode,fg|bg), + (int)(cname - col_names) + 30, + *cname, + GetTextMode(cv->col_mode,bg|mode), + GetTextMode(cv->col_mode,bg|TTM_BOLD), + GetTextMode(cv->col_mode,bg|TTM_UL), + GetTextMode(cv->col_mode,bg|TTM_NO_BOLD), + GetTextMode(cv->col_mode,bg|TTM_RESET), + cv->colset->reset ); + } + + //-------------------------------------------------- + + fprintf(cv->f, + "\n%*sStandard background colors with attributes (ul=underline) for mode %s:\n\n", + cv->indent, "", GetColorModeName(cv->col_mode,0) ); + + mode = TTM_BG_BLACK; + for ( cname = col_names; *cname; cname++, mode += 0x10 ) + { + fprintf(cv->f,"%*s %u %-9s %s white %s bold %sul%s black %sbold %sul%s %s\n", + cv->indent, "", + (int)(cname - col_names) + 40, + *cname, + GetTextMode(cv->col_mode,mode|TTM_WHITE), + GetTextMode(cv->col_mode,TTM_BOLD), + GetTextMode(cv->col_mode,TTM_UL|TTM_NO_BOLD), + GetTextMode(cv->col_mode,mode|TTM_BLACK|TTM_RESET), + GetTextMode(cv->col_mode,TTM_BOLD), + GetTextMode(cv->col_mode,TTM_UL|TTM_NO_BOLD), + GetTextMode(cv->col_mode,TTM_NO_UL), + GetTextMode(cv->col_mode,TTM_RESET) ); + } +} + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +void ViewColorsCombi8 ( ColorView_t *cv ) +{ + DASSERT(cv); + SetupColorView(cv); + DASSERT(cv->colset); + + #ifdef TEST + fprintf(cv->f,"%*s%s() %s, %u colors, mode %d, stdcol %d, order %d\n", + cv->indent,"", __FUNCTION__, + GetColorModeName(cv->colset->col_mode,0), + cv->colset->n_colors, cv->mode, cv->std_col, cv->order ); + #endif + + fprintf(cv->f, + "%s\n%*sFont and background color combinations (no=normal, bo=bold) for mode %s:\n\n", + cv->colset->reset, cv->indent, "", + GetColorModeName(cv->col_mode,0) ); + + uint mode = TTM_BG_BLACK; + ccp *cname; + for ( cname = col_names; *cname; cname++, mode += 0x10 ) + { + fprintf(cv->f,"%*s %u %-9s ", + cv->indent, "", + (int)(cname - col_names) + 40, + *cname ); + + TermTextMode_t mode2; + for ( mode2 = TTM_BLACK; mode2 <= TTM_WHITE; mode2++ ) + fprintf(cv->f,"%s no %sbo ", + GetTextMode(cv->col_mode,mode|mode2|TTM_NO_BOLD), + GetTextMode(cv->col_mode,TTM_BOLD) ); + fprintf(cv->f," %s\n",cv->colset->reset ); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +void ViewColors18 ( ColorView_t *cv ) +{ + DASSERT(cv); + SetupColorView(cv); + DASSERT(cv->colset); + + #ifdef TEST + fprintf(cv->f,"%*s%s() %s, %u colors, mode %d, stdcol %d, order %d\n", + cv->indent,"", __FUNCTION__, + GetColorModeName(cv->colset->col_mode,0), + cv->colset->n_colors, cv->mode, cv->std_col, cv->order ); + #endif + + GetColorOption_t col_option = cv->col_option & ~GCM_ALT; + + fprintf(cv->f, + "%s\n%*s18x18 color table ('0'=std, '1'=optimized%s) for mode %s:\n\n", + cv->colset->reset, cv->indent, "", + col_option & GCM_SHORT ? "; allow short codes" : "", + GetColorModeName(cv->col_mode,0) ); + + const int *pbg; + for ( pbg = Color18Index; *pbg >= 0; pbg++ ) + { + uint bg = *pbg; + if ( bg == TCI_RED || bg == TCI_B_RED ) + fputc('\n',cv->f); + fprintf(cv->f,"%*s %-12s ", + cv->indent, "", ColorIndexName[bg] ); + + const int *pfont; + for ( pfont = Color18Index; *pfont >= 0; pfont++ ) + { + uint font = *pfont; + if ( font == TCI_RED || font == TCI_B_RED ) + fprintf(cv->f," %s ",TERM_TEXT_MODE_RESET); + fprintf(cv->f,"%s 0%s1", + GetColorMode(cv->col_mode,font,bg,col_option), + GetColorMode(cv->col_mode,font,bg,col_option|GCM_ALT) ); + } + fprintf(cv->f," %s\n",TERM_TEXT_MODE_RESET); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +void ViewColorsDC ( ColorView_t *cv, bool optimized ) +{ + DASSERT(cv); + SetupColorView(cv); + DASSERT(cv->colset); + + #ifdef TEST + fprintf(cv->f,"%*s%s() %s, %u colors, mode %d, stdcol %d, order %d\n", + cv->indent,"", __FUNCTION__, + GetColorModeName(cv->colset->col_mode,0), + cv->colset->n_colors, cv->mode, cv->std_col, cv->order ); + #endif + + GetColorOption_t col_option = cv->col_option & ~GCM_ALT; + if (optimized) + col_option |= GCM_ALT; + + fprintf(cv->f, + "%s\n%*s%ux%u color table (%s%s) for mode %s:\n\n", + cv->colset->reset, cv->indent, "", + TCI__N, TCI__N, + optimized ? "optimized" : "standard", + col_option & GCM_SHORT ? "; allow short codes" : "", + GetColorModeName(cv->col_mode,0) ); + + uint bg; + for ( bg = 0; bg < TCI__N; bg++ ) + { + if ( bg == TCI_RED || bg == TCI_B_RED ) + fputc('\n',cv->f); + fprintf(cv->f,"%*s %-15s ", + cv->indent, "", ColorIndexName[bg] ); + + ccp fill = " "; + uint font; + for ( font = 0; font < TCI__N; font++ ) + { + if ( font == TCI_RED || font == TCI_B_RED ) + { + fprintf(cv->f," %s ",TERM_TEXT_MODE_RESET); + fill = " "; + } + fprintf(cv->f,"%s%sx", + GetColorMode(cv->col_mode,font,bg,col_option), fill ); + fill = ""; + } + fprintf(cv->f," %s\n",TERM_TEXT_MODE_RESET); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +static void ViewColors256_helper +( + ColorView_t *cv, // basic data + uint beg, // first color printed + uint end, // first color not printed + uint step // increment +) +{ + if ( cv->colset->n_colors < 8 ) + { + uint i; + for ( i = beg; i < end; i += step ) + fprintf(cv->f," %03u ",i); + } + #if 0 // [[2do]] + else if ( cv->colset->n_colors < 256 ) + { + } + #endif + else + { + const int mode = cv->mode & 1 ? 48 : 38; + + uint i; + for ( i = beg; i < end; i += step ) + fprintf(cv->f,"\e[%u;5;%um %03u ",mode,i,i); + fputs("\e[0m",cv->f); + } +} + +//----------------------------------------------------------------------------- + +void ViewColors256 ( ColorView_t *cv ) +{ + DASSERT(cv); + SetupColorView(cv); + DASSERT(cv->colset); + + #ifdef TEST + fprintf(cv->f,"%*s%s() %s, %u colors, mode %d, stdcol %d, order %d\n", + cv->indent,"", __FUNCTION__, + GetColorModeName(cv->colset->col_mode,0), + cv->colset->n_colors, cv->mode, cv->std_col, cv->order ); + #endif + + fprintf(cv->f, + "%s\n%*s256 colors = 16 std colors + 6x6x6 colors + 24 gray for mode %s:\n", + cv->colset->reset, cv->indent, "", + GetColorModeName(cv->col_mode,0) ); + + int step, inc_horz, inc_vert; + switch (cv->order) + { + case 1: + step = 1; + inc_horz = 6; + inc_vert = 36; + break; + + case 2: + step = 6; + inc_horz = 1; + inc_vert = 36; + break; + + default: + step = 1; + inc_horz = 36; + inc_vert = 6; + break; + } + + //--- 16 standard colors in 2 rows + + fprintf(cv->f,"\n%*s ",cv->indent,""); + ViewColors256_helper(cv,0,8,1); + fprintf(cv->f,"\n%*s ",cv->indent,""); + ViewColors256_helper(cv,8,16,1); + fputs("\e[0m\n\n",cv->f); + + uint bl, num = 16; + + for ( bl = 0; bl < 3; bl++ ) + { + uint i, n = num; + for ( i = 0; i < 6; i++ ) + { + fprintf(cv->f,"%*s ",cv->indent,""); + ViewColors256_helper(cv,n,n+6*step,step); + fputs(" ",cv->f); + + ViewColors256_helper(cv,n+inc_horz,n+inc_horz+6*step,step); + fputc('\n',cv->f); + n += inc_vert; + } + + fputc('\n',cv->f); + num += 2*inc_horz; + } + + fprintf(cv->f,"%*s ",cv->indent,""); + ViewColors256_helper(cv,232,232+12,1); + fprintf(cv->f,"\n%*s ",cv->indent,""); + ViewColors256_helper(cv,232+12,232+24,1); + fputs("\e[0m\n",cv->f); +} + +/////////////////////////////////////////////////////////////////////////////// + +static void ViewColorsPredef_helper +( + ColorView_t *cv, // basic data + ccp col_name, // name of color + ccp col_string // escape string for the color +) +{ + DASSERT(cv); + DASSERT(col_string); + + if ( col_string && *col_string ) + fprintf(cv->f,"%*s %s %-15s %s \\e%s\n", + cv->indent, col_name, col_string, col_name, + cv->colset->reset, col_string+1 ); + else + fprintf(cv->f,"%*s %s\n", + cv->indent, col_name, col_name ); +} + +//----------------------------------------------------------------------------- + +void ViewColorsPredef ( ColorView_t *cv, uint mode ) +{ + DASSERT(cv); + SetupColorView(cv); + DASSERT(cv->colset); + + #ifdef TEST + fprintf(cv->f,"%*s%s() %s, %u colors, mode %d, stdcol %d, order %d\n", + cv->indent,"", __FUNCTION__, + GetColorModeName(cv->colset->col_mode,0), + cv->colset->n_colors, cv->mode, cv->std_col, cv->order ); + #endif + + fprintf(cv->f, + "%s\n%*sPredefined%s color names for mode %s:\n\n", + cv->colset->reset, cv->indent, "", + ( mode & 3 ) == 1 ? " semantic" : "", + GetColorModeName(cv->col_mode,0) ); + + cv->indent += 14; + + #undef JOB1 + #undef JOB2 + #define JOB1(n) ViewColorsPredef_helper(cv,#n,cv->colset->n) + #define JOB2(n,c) ViewColorsPredef_helper(cv,#n,cv->colset->c) + + if ( mode & 1 ) + { + const bool alt = cv->mode & 1; + + JOB1(setup); + JOB1(run); + JOB1(abort); + JOB1(finish); + JOB1(script); + JOB1(open); + JOB1(close); + JOB1(file); + JOB1(job); + + JOB1(info); + JOB1(hint); + JOB1(warn); + JOB1(debug); + JOB1(log); + + JOB1(name); + JOB1(value); if (alt) JOB2(val,value); + JOB1(success); + JOB1(error); + JOB1(fail); + JOB1(fail2); + JOB1(fatal); + JOB1(mark); + JOB1(bad); + + JOB1(select); + JOB1(differ); + JOB1(stat_line); + JOB1(warn_line); + JOB1(proc_line); + JOB1(cite); + JOB1(status); + JOB1(highlight); if (alt) JOB2(hl,highlight); + JOB1(hide); + + JOB1(heading); + JOB1(caption); + JOB1(section); + JOB1(syntax); + JOB1(cmd); + JOB1(option); if (alt) JOB2(opt,option); + JOB1(param); if (alt) JOB2(par,param); + + JOB1(off); + JOB1(on); + } + + if ( mode & 2 ) + { + if ( mode & 1 ) + fputc('\n',cv->f); + JOB1(black); + JOB1(b_black); + JOB1(white); + JOB1(b_white); + + if ( !(mode & 1) ) + fputc('\n',cv->f); + JOB1(red); + JOB1(red_orange); + JOB1(orange); + JOB1(orange_yellow); + JOB1(yellow); + JOB1(yellow_green); + JOB1(green); + JOB1(green_cyan); + JOB1(cyan); + JOB1(cyan_blue); + JOB1(blue); + JOB1(blue_magenta); + JOB1(magenta); + JOB1(magenta_red); + JOB1(red); + + if ( !(mode & 1) ) + fputc('\n',cv->f); + JOB1(b_red); + JOB1(b_red_orange); + JOB1(b_orange); + JOB1(b_orange_yellow); + JOB1(b_yellow); + JOB1(b_yellow_green); + JOB1(b_green); + JOB1(b_green_cyan); + JOB1(b_cyan); + JOB1(b_cyan_blue); + JOB1(b_blue); + JOB1(b_blue_magenta); + JOB1(b_magenta); + JOB1(b_magenta_red); + JOB1(b_red); + } + + #undef JOB1 + #undef JOB2 + cv->indent -= 14; +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// old color views (wrapper) /////////////// +/////////////////////////////////////////////////////////////////////////////// + +void PrintTextModes +( + FILE *f, // valid output file + int indent, // indention of output + ColorMode_t col_mode // color mode +) +{ + ColorView_t cv; + InitializeColorView(&cv); + cv.f = f; + cv.indent = indent; + cv.col_mode = col_mode; + ViewColorsAttrib8(&cv); + ViewColorsCombi8(&cv); +} + +/////////////////////////////////////////////////////////////////////////////// + +void PrintColorModes +( + FILE *f, // valid output file + int indent, // indention of output + ColorMode_t col_mode, // color mode -> NormalizeColorMode() + GetColorOption_t option // execution options (GCM_ALT ignored) +) +{ + ColorView_t cv; + InitializeColorView(&cv); + cv.f = f; + cv.indent = indent; + cv.col_mode = col_mode; + cv.col_option = option; + ViewColors18(&cv); +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// stdout, stderr, stdlog and colors /////////////// +/////////////////////////////////////////////////////////////////////////////// + +FILE *stdlog = 0; // NULL or logfile +bool close_stdlog = 0; // true: close file behing 'stdlog' + +FILE *stdmsg = 0; // 'stdlog' or 'stdout' or 'stderr' or NULL +FILE *stdwrn = 0; // used by PrintError(), initialized with 'stderr' + +ColorMode_t colorize_stdout = COLMD_AUTO; +ColorMode_t colorize_stderr = COLMD_AUTO; +ColorMode_t colorize_stdlog = COLMD_AUTO; +ColorMode_t colorize_stdmsg = COLMD_AUTO; +ColorMode_t colorize_stdwrn = COLMD_AUTO; + +const ColorSet_t *colout = 0; // color set for 'stdout' +const ColorSet_t *colerr = 0; // color set for 'stderr' +const ColorSet_t *collog = 0; // color set for 'stdlog' +const ColorSet_t *colmsg = 0; // color set for 'stdmsg' +const ColorSet_t *colwrn = 0; // color set for 'stdwrn' + +/////////////////////////////////////////////////////////////////////////////// + +ColorMode_t GetFileColorized ( FILE *f ) +{ + if (!stdmsg) + SetupStdMsg(); + + return !f ? COLMD_OFF + : f == stdlog && colorize_stdlog != COLMD_AUTO ? colorize_stdlog + : f == stdout && colorize_stdout != COLMD_AUTO ? colorize_stdout + : f == stderr && colorize_stderr != COLMD_AUTO ? colorize_stderr + : f == stdmsg && colorize_stdmsg != COLMD_AUTO ? colorize_stdmsg + : f == stdwrn && colorize_stdwrn != COLMD_AUTO ? colorize_stdwrn + : opt_colorize >= COLMD_ON ? opt_colorize + : opt_colorize == COLMD_AUTO && isatty(fileno(f)) + ? COLMD_AUTO + : COLMD_OFF; +} + +/////////////////////////////////////////////////////////////////////////////// + +void SetupStdMsg() +{ + //--- setup + + static bool active = false; // avoid loops + if (!active) + { + active = true; + + stdwrn = stderr; + colwrn = colerr; + colorize_stdwrn = colorize_stderr; + + if (!colout) + { + colorize_stdout = GetFileColorized(stdout); + colout = GetColorSet(colorize_stdout); + } + + if (!colerr) + { + colorize_stderr = GetFileColorized(stderr); + colerr = GetColorSet(colorize_stderr); + } + + if (!collog) + { + colorize_stdlog = GetFileColorized(stdlog); + collog = GetColorSet(colorize_stdlog); + } + + active = false; + } + + //--- assign to msg + + if (stdlog) + { + stdmsg = stdlog; + colmsg = collog; + colorize_stdmsg = colorize_stdlog; + } + else if (stdout) + { + stdmsg = stdout; + colmsg = colout; + colorize_stdmsg = colorize_stdout; + } + else if (stderr) + { + stdmsg = stderr; + colmsg = colerr; + colorize_stdmsg = colorize_stderr; + } + else + { + stdmsg = 0; + colmsg = GetColorSet0(); + colorize_stdmsg = 0; + } + + noPRINT("SetupStdMsg() : out=%d[%zd], err=%d[%zd], log=%d[%zd], msg=%d[%zd]\n", + colorize_stdout, colout ? strlen(colout->reset) : -1, + colorize_stderr, colerr ? strlen(colerr->reset) : -1, + colorize_stdlog, collog ? strlen(collog->reset) : -1, + colorize_stdmsg, colmsg ? strlen(colmsg->reset) : -1 ); +} + +/////////////////////////////////////////////////////////////////////////////// + +enumError OpenStdLog +( + ccp fname, // If NULL or empty: don't open and use 'fallback' + // If first char == '+': open file in append mode + FILE *fallback // Fall back to this file, if no file name given + // If NULL: just clode 'stdlog'. +) +{ + CloseStdLog(); + + bool append = fname && *fname == '+'; + if (append) + fname++; + + if ( !fname || !*fname ) + { + if (fallback) + { + stdlog = fallback; + colorize_stdlog = GetFileColorized(stdlog); + PRINT("COLORIZE/LOG/FALLBACK: opt=%d, out=%d, err=%d, log=%d\n", + opt_colorize, colorize_stdout, colorize_stderr, colorize_stdlog ); + } + } + else + { + if (!strcmp(fname,"-")) + { + stdlog = stdout; + colorize_stdlog = colorize_stdout; + } + else + { + stdlog = fopen( fname, append ? "ab" : "wb" ); + if (!stdlog) + return ERROR1(ERR_CANT_CREATE, + "Can't open log file (mode=%s): %s\n", + append ? "append" : "create", fname ); + + close_stdlog = true; + colorize_stdlog = GetFileColorized(stdlog); + } + + PRINT("COLORIZE/LOG: opt=%d, out=%d, err=%d, log=%d\n", + opt_colorize, colorize_stdout, colorize_stderr, colorize_stdlog ); + } + + collog = GetColorSet(colorize_stdlog); + SetupStdMsg(); + return ERR_OK; +} + +/////////////////////////////////////////////////////////////////////////////// + +void CloseStdLog() +{ + if (stdlog) + { + if (close_stdlog) + fclose(stdlog); + else + fflush(stdlog); + stdlog = 0; + } + + close_stdlog = false; + colorize_stdlog = 0; + collog = GetColorSet0(); + + SetupStdMsg(); +} + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +void SaveStdFiles ( SavedStdFiles_t *ssf ) +{ + DASSERT(ssf); + + ssf->std_out = stdout; + ssf->std_err = stderr; + ssf->std_log = stdlog; + ssf->std_msg = stdmsg; + ssf->std_wrn = stdwrn; + + ssf->col_out = colout; + ssf->col_err = colerr; + ssf->col_log = collog; + ssf->col_msg = colmsg; + ssf->col_wrn = colwrn; + + ssf->stdout_seq_count = stdout_seq_count; + + ssf->f = 0; + ssf->data = 0; + ssf->size = 0; + ssf->marker = 0; +} + +/////////////////////////////////////////////////////////////////////////////// + +void RestoreStdFiles ( SavedStdFiles_t *ssf ) +{ + DASSERT(ssf); + + stdout = ssf->std_out; + stderr = ssf->std_err; + stdlog = ssf->std_log; + stdmsg = ssf->std_msg; + stdwrn = ssf->std_wrn; + + colout = ssf->col_out; + colerr = ssf->col_err; + collog = ssf->col_log; + colmsg = ssf->col_msg; + colwrn = ssf->col_wrn; + + stdout_seq_count = ssf->stdout_seq_count; +} + +/////////////////////////////////////////////////////////////////////////////// + +void RedirectStdFiles +( + SavedStdFiles_t *ssf, // not NULL: save old output here + FILE *f, // use this as out,err,log and msg, never NULL + const ColorSet_t *colset,// new colset; if NULL: use GetFileColorSet(f) + bool err_too // true: redirect stderr too +) +{ + DASSERT(f); + if (ssf) + SaveStdFiles(ssf); + + stdout = stdwrn = stdmsg = f; + colout = colwrn = colmsg = colset ? colset : GetFileColorSet(f); + + // special handling for stdlog + if (stdlog) + { + stdlog = stdout; + collog = colout; + } + + if (err_too) + { + stderr = stdout; + colerr = colout; + } +} + +/////////////////////////////////////////////////////////////////////////////// +#ifndef __APPLE__ + +enumError CatchStdFiles +( + SavedStdFiles_t *ssf, // save old output and data here, never NULL + const ColorSet_t *colset // new colset; if NULL: no color support +) +{ + DASSERT(ssf); + SaveStdFiles(ssf); + FILE *f = open_memstream(&ssf->data,&ssf->size); + if (!f) + return ERR_CANT_CREATE; + + ssf->f = f; + RedirectStdFiles(0,f,colset,false); + return ERR_OK; +} + +#endif // !__APPLE__ +/////////////////////////////////////////////////////////////////////////////// + +void TermCatchStdFiles ( SavedStdFiles_t *ssf ) +{ + DASSERT(ssf); + RestoreStdFiles(ssf); + if (ssf->f) + { + fclose(ssf->f); + ssf->f = 0; + } +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// END /////////////// +/////////////////////////////////////////////////////////////////////////////// + |
