From 1e36d12ac7b7d3c2f4a3405b7bc739f8ab996489 Mon Sep 17 00:00:00 2001 From: Oldes Date: Thu, 11 Oct 2018 13:40:02 +0200 Subject: [PATCH] FIX: revisited color attributes in ANSI escape codes on Windows so it is more consistent with POSIX terminals now. --- src/mezz/mezz-help.r | 145 +++++++++++++++++++-------------------- src/os/win32/dev-stdio.c | 132 ++++++++++++++++++++++++----------- 2 files changed, 165 insertions(+), 112 deletions(-) diff --git a/src/mezz/mezz-help.r b/src/mezz/mezz-help.r index 4141a1df79..c705611cd3 100644 --- a/src/mezz/mezz-help.r +++ b/src/mezz/mezz-help.r @@ -75,13 +75,13 @@ dump-obj: function [ ] ] ][ - str: join "^[[1;32;49m" form-pad word 15 - append str "^[[0m " + str: join "^[[1;32m" form-pad word 15 + append str "^[[m " append str form-pad type 24 - ((length? str) - 15) append out reform [ " " str "^[[32m" if type <> 'unset! [form-val :val] - "^[[0m^/" + "^[[m^/" ] ] ] @@ -96,45 +96,45 @@ dump-obj: function [ ][ if unset? get/any 'word [ print trim/auto { - Use ^[[1;32;49mHELP^[[0m or ^[[1;32;49m?^[[0m to see built-in info: - ^[[1;32;49m + Use ^[[1;32mHELP^[[m or ^[[1;32m?^[[m to see built-in info: + ^[[1;32m help insert ? insert - ^[[0m + ^[[m To search within the system, use quotes: - ^[[1;32;49m + ^[[1;32m ? "insert" - ^[[0m + ^[[m To browse online web documents: - ^[[1;32;49m + ^[[1;32m help/doc insert - ^[[0m + ^[[m To view words and values of a context or object: - ^[[1;32;49m? lib^[[0m - the runtime library - ^[[1;32;49m? self^[[0m - your user context - ^[[1;32;49m? system^[[0m - the system object - ^[[1;32;49m? system/options^[[0m - special settings + ^[[1;32m? lib^[[m - the runtime library + ^[[1;32m? self^[[m - your user context + ^[[1;32m? system^[[m - the system object + ^[[1;32m? system/options^[[m - special settings To see all words of a specific datatype: - ^[[1;32;49m + ^[[1;32m ? native! ? function! ? datatype! - ^[[0m + ^[[m Other debug functions: - ^[[1;32;49m??^[[0m - display a variable and its value - ^[[1;32;49mprobe^[[0m - print a value (molded) - ^[[1;32;49msource^[[0m - show source code of func - ^[[1;32;49mtrace^[[0m - trace evaluation steps - ^[[1;32;49mwhat^[[0m - show a list of known functions + ^[[1;32m??^[[m - display a variable and its value + ^[[1;32mprobe^[[m - print a value (molded) + ^[[1;32msource^[[m - show source code of func + ^[[1;32mtrace^[[m - trace evaluation steps + ^[[1;32mwhat^[[m - show a list of known functions Other information: - ^[[1;32;49mabout^[[0m - see general product info - ^[[1;32;49mlicense^[[0m - show user license - ^[[1;32;49musage^[[0m - program cmd line options + ^[[1;32mabout^[[m - see general product info + ^[[1;32mlicense^[[m - show user license + ^[[1;32musage^[[m - program cmd line options } exit ] @@ -194,23 +194,23 @@ dump-obj: function [ if all [word? :word datatype? get :word] [ value: spec-of get :word print ajoin [ - "^[[1;32;49m" mold :word "^[[0m is a datatype" newline + "^[[1;32m" mold :word "^[[m is a datatype" newline "It is defined as " either find "aeiou" first value/title ["an "] ["a "] value/title newline - "It is of the general type ^[[1;32;49m" value/type "^[[0m^/" + "It is of the general type ^[[1;32m" value/type "^[[m^/" ] ] if any [:word = 'unset! not value? :word] [exit] types: dump-obj/match lib :word sort types if not empty? types [ - print ["Found these related words:^[[32m" newline types "^[[0m"] + print ["Found these related words:^[[32m" newline types "^[[m"] exit ] if all [word? :word datatype? get :word] [ - print ["No values defined for^[[1;32;49m" word "^[[0m"] + print ["No values defined for^[[1;32m" word "^[[m"] exit ] - print ["No information on^[[1;32;49m" word "^[[0m"] + print ["No information on^[[1;32m" word "^[[m"] exit ] @@ -223,7 +223,7 @@ dump-obj: function [ ; Print literal values: if not any [word? :word path? :word][ - print ajoin ["^[[1;32;49m" mold :word "^[[0m is " type-name :word] + print ajoin ["^[[1;32m" mold :word "^[[m is " type-name :word] exit ] @@ -250,9 +250,9 @@ dump-obj: function [ value: get :word ] unless any-function? :value [ - prin ajoin ["^[[1;32;49m" uppercase mold word "^[[0m is " type-name :value " of value: ^[[32m"] + prin ajoin ["^[[1;32m" uppercase mold word "^[[m is " type-name :value " of value: ^[[32m"] prin either any [object? value port? value] [print "" dump-obj value][mold/all :value] - print "^[[0m" + print "^[[m" exit ] @@ -261,7 +261,7 @@ dump-obj: function [ ;if path? :word [word: first :word] ;-- Print info about function: - prin "USAGE:^/^-" + prin "^[[4;1;36mUSAGE^[[m:^/^-" args: words-of :value clear find args /local @@ -272,7 +272,7 @@ dump-obj: function [ ] print ajoin [ - newline "DESCRIPTION:" newline + newline "^[[4;1;36mDESCRIPTION^[[m:" newline tab any [title-of :value "(undocumented)"] newline tab uppercase mold word " is " type-name :value " value." ] @@ -309,8 +309,8 @@ dump-obj: function [ ] ] - print-args "^/ARGUMENTS:" argl - print-args/extra "^/REFINEMENTS:" refl + print-args "^/^[[4;1;36mARGUMENTS^[[m:" argl + print-args/extra "^/^[[4;1;36mREFINEMENTS^[[m:" refl ] exit ; return unset @@ -327,43 +327,42 @@ about: func [ usage: func [ "Prints command-line arguments." ][ - print trim/auto { - Command line usage: - - REBOL |options| |script| |arguments| - - Standard options: - - --args data Explicit arguments to script (quoted) - --do expr Evaluate expression (quoted) - --help (-?) Display this usage information - --script file Explicit script filename - --version tuple Script must be this version or greater - - Special options: - - --boot level Valid levels: base sys mods - --debug flags For user scripts (system/options/debug) - --halt (-h) Leave console open when script is done - --import file Import a module prior to script - --quiet (-q) No startup banners or information - --secure policy Can be: none allow ask throw quit - --trace (-t) Enable trace mode during boot - --verbose Show detailed startup information - - Other quick options: - - -s No security - +s Full security - -v Display version only (then quit) - - Examples: - - REBOL script.r - REBOL -s script.r - REBOL script.r 10:30 test@example.com - REBOL --do "watch: on" script.r - } + print { + ^[[4;1;36mCommand line usage^[[m: + + ^[[1;32mREBOL |options| |script| |arguments|^[[m + + ^[[4;1;36mStandard options^[[m: + + ^[[1;32m--args data^[[m Explicit arguments to script (quoted) + ^[[1;32m--do expr^[[m Evaluate expression (quoted) + ^[[1;32m--help (-?)^[[m Display this usage information + ^[[1;32m--script file^[[m Explicit script filename + ^[[1;32m--version tuple^[[m Script must be this version or greater + + ^[[4;1;36mSpecial options^[[m: + + ^[[1;32m--boot level^[[m Valid levels: base sys mods + ^[[1;32m--debug flags^[[m For user scripts (system/options/debug) + ^[[1;32m--halt (-h)^[[m Leave console open when script is done + ^[[1;32m--import file^[[m Import a module prior to script + ^[[1;32m--quiet (-q)^[[m No startup banners or information + ^[[1;32m--secure policy^[[m Can be: none allow ask throw quit + ^[[1;32m--trace (-t)^[[m Enable trace mode during boot + ^[[1;32m--verbose^[[m Show detailed startup information + + ^[[4;1;36mOther quick options^[[m: + + ^[[1;32m-s^[[m No security + ^[[1;32m+s^[[m Full security + ^[[1;32m-v^[[m Display version only (then quit) + + ^[[4;1;36mExamples^[[m: + + REBOL script.r + REBOL -s script.r + REBOL script.r 10:30 test@example.com + REBOL --do "watch: on" script.r} ] license: func [ diff --git a/src/os/win32/dev-stdio.c b/src/os/win32/dev-stdio.c index 2abed38179..0dc0c19790 100644 --- a/src/os/win32/dev-stdio.c +++ b/src/os/win32/dev-stdio.c @@ -95,7 +95,7 @@ static int ANSI_Value1 = 0; static int ANSI_Value2 = 0; static int ANSI_Attr = -1; -int Update_Graphic_Mode(int attribute, int value); +int Update_Graphic_Mode(int attribute, int value, boolean set); REBYTE* Parse_ANSI_sequence(REBYTE *cp, REBYTE *ep); //********************************************************************** @@ -493,7 +493,7 @@ DEFINE_DEV(Dev_StdIO, "Standard IO", 1, Dev_Cmds, RDC_MAX, 0); /*********************************************************************** ** -*/ int Update_Graphic_Mode(int attribute, int value) +*/ int Update_Graphic_Mode(int attribute, int value, boolean set) /* ** ***********************************************************************/ @@ -508,30 +508,52 @@ DEFINE_DEV(Dev_StdIO, "Standard IO", 1, Dev_Cmds, RDC_MAX, 0); switch (value) { case 0: attribute = FOREGROUND_GREY; break; - case 1: attribute = attribute | FOREGROUND_INTENSITY | BACKGROUND_INTENSITY; break; + case 1: attribute = attribute | FOREGROUND_INTENSITY; break; case 4: attribute = attribute | COMMON_LVB_UNDERSCORE; break; - case 7: tmp = (attribute & 0xF0) >> 4; - attribute = ((attribute & 0x0F) << 4) | tmp; break; //reverse - case 30: attribute = attribute & 0xF8; break; - case 31: attribute = (attribute & 0xF8) | FOREGROUND_RED; break; - case 32: attribute = (attribute & 0xF8) | FOREGROUND_GREEN; break; - case 33: attribute = (attribute & 0xF8) | FOREGROUND_YELLOW; break; - case 34: attribute = (attribute & 0xF8) | FOREGROUND_BLUE; break; - case 35: attribute = (attribute & 0xF8) | FOREGROUND_MAGENTA; break; - case 36: attribute = (attribute & 0xF8) | FOREGROUND_CYAN; break; - case 37: attribute = (attribute & 0xF8) | FOREGROUND_GREY; break; - case 39: attribute = attribute & 0xF7; break; //FOREGROUND_INTENSITY reset - case 40: attribute = attribute & 0x8F; break; - case 41: attribute = (attribute & 0x8F) | BACKGROUND_RED; break; - case 42: attribute = (attribute & 0x8F) | BACKGROUND_GREEN; break; - case 43: attribute = (attribute & 0x8F) | BACKGROUND_YELLOW; break; - case 44: attribute = (attribute & 0x8F) | BACKGROUND_BLUE; break; - case 45: attribute = (attribute & 0x8F) | BACKGROUND_MAGENTA; break; - case 46: attribute = (attribute & 0x8F) | BACKGROUND_CYAN; break; - case 47: attribute = (attribute & 0x8F) | BACKGROUND_GREY; break; - case 49: attribute = attribute & 0x7F; break; //BACKGROUND_INTENSITY reset - default: attribute = value; + case 7: tmp = (attribute & 0xFFF0) >> 4; + attribute = ((attribute & 0xFF0F) << 4) | tmp; break; //reverse + case 22: attribute = attribute & 0xFFF7; break; //FOREGROUND_INTENSITY reset + case 24: attribute = attribute & 0x7FFF; break; //reset underscore + case 30: attribute = attribute & 0xFFF8; break; + case 31: attribute = (attribute & 0xFFF8) | FOREGROUND_RED; break; + case 32: attribute = (attribute & 0xFFF8) | FOREGROUND_GREEN; break; + case 33: attribute = (attribute & 0xFFF8) | FOREGROUND_YELLOW; break; + case 34: attribute = (attribute & 0xFFF8) | FOREGROUND_BLUE; break; + case 35: attribute = (attribute & 0xFFF8) | FOREGROUND_MAGENTA; break; + case 36: attribute = (attribute & 0xFFF8) | FOREGROUND_CYAN; break; + case 37: attribute = (attribute & 0xFFF8) | FOREGROUND_GREY; break; + case 39: attribute = attribute & 0xFFF7; break; //FOREGROUND_INTENSITY reset + case 40: attribute = attribute & 0xFF8F; break; + case 41: attribute = (attribute & 0xFF8F) | BACKGROUND_RED; break; + case 42: attribute = (attribute & 0xFF8F) | BACKGROUND_GREEN; break; + case 43: attribute = (attribute & 0xFF8F) | BACKGROUND_YELLOW; break; + case 44: attribute = (attribute & 0xFF8F) | BACKGROUND_BLUE; break; + case 45: attribute = (attribute & 0xFF8F) | BACKGROUND_MAGENTA; break; + case 46: attribute = (attribute & 0xFF8F) | BACKGROUND_CYAN; break; + case 47: attribute = (attribute & 0xFF8F) | BACKGROUND_GREY; break; + case 49: attribute = attribute & 0xFF7F; break; //BACKGROUND_INTENSITY reset + //bright foreground colors + case 90: attribute = (attribute & 0xFFF8) | FOREGROUND_INTENSITY; break; + case 91: attribute = (attribute & 0xFFF8) | FOREGROUND_INTENSITY | FOREGROUND_RED; break; + case 92: attribute = (attribute & 0xFFF8) | FOREGROUND_INTENSITY | FOREGROUND_GREEN; break; + case 93: attribute = (attribute & 0xFFF8) | FOREGROUND_INTENSITY | FOREGROUND_YELLOW; break; + case 94: attribute = (attribute & 0xFFF8) | FOREGROUND_INTENSITY | FOREGROUND_BLUE; break; + case 95: attribute = (attribute & 0xFFF8) | FOREGROUND_INTENSITY | FOREGROUND_MAGENTA; break; + case 96: attribute = (attribute & 0xFFF8) | FOREGROUND_INTENSITY | FOREGROUND_CYAN; break; + case 97: attribute = (attribute & 0xFFF8) | FOREGROUND_INTENSITY | FOREGROUND_GREY; break; + //bright background colors + case 100: attribute = (attribute & 0xFF8F) | BACKGROUND_INTENSITY; break; + case 101: attribute = (attribute & 0xFF8F) | BACKGROUND_INTENSITY | BACKGROUND_RED; break; + case 102: attribute = (attribute & 0xFF8F) | BACKGROUND_INTENSITY | BACKGROUND_GREEN; break; + case 103: attribute = (attribute & 0xFF8F) | BACKGROUND_INTENSITY | BACKGROUND_YELLOW; break; + case 104: attribute = (attribute & 0xFF8F) | BACKGROUND_INTENSITY | BACKGROUND_BLUE; break; + case 105: attribute = (attribute & 0xFF8F) | BACKGROUND_INTENSITY | BACKGROUND_MAGENTA; break; + case 106: attribute = (attribute & 0xFF8F) | BACKGROUND_INTENSITY | BACKGROUND_CYAN; break; + case 107: attribute = (attribute & 0xFF8F) | BACKGROUND_INTENSITY | BACKGROUND_GREY; break; + + //default: attribute = value1; } + if(set) SetConsoleTextAttribute(Std_Out, attribute); return attribute; } @@ -599,6 +621,10 @@ DEFINE_DEV(Dev_StdIO, "Standard IO", 1, Dev_Cmds, RDC_MAX, 0); SetConsoleCursorPosition(Std_Out, coordScreen); ANSI_State = -1; } + else if (*cp == 'm') { + ANSI_Attr = Update_Graphic_Mode(ANSI_Attr, 0, TRUE); + ANSI_State = -1; + } else { ANSI_State = -1; } @@ -612,8 +638,7 @@ DEFINE_DEV(Dev_StdIO, "Standard IO", 1, Dev_Cmds, RDC_MAX, 0); ANSI_State = 3; } else if (*cp == 'm') { - ANSI_Attr = Update_Graphic_Mode(ANSI_Attr, ANSI_Value1); - SetConsoleTextAttribute(Std_Out, ANSI_Attr); + ANSI_Attr = Update_Graphic_Mode(ANSI_Attr, ANSI_Value1, TRUE); ANSI_State = -1; } else if (*cp == 'A') { @@ -677,19 +702,48 @@ DEFINE_DEV(Dev_StdIO, "Standard IO", 1, Dev_Cmds, RDC_MAX, 0); ANSI_Value2 = ((ANSI_Value2 * 10) + (*cp - (int)'0')) % 0xFFFF; ANSI_State = 4; } - else if (*cp == 'm') { - ANSI_Attr = Update_Graphic_Mode(ANSI_Attr, ANSI_Value1); - ANSI_Attr = Update_Graphic_Mode(ANSI_Attr, ANSI_Value2); - SetConsoleTextAttribute(Std_Out, ANSI_Attr); - ANSI_State = -1; - } - else if (*cp == ';') { - ANSI_Attr = Update_Graphic_Mode(ANSI_Attr, ANSI_Value1); - ANSI_Attr = Update_Graphic_Mode(ANSI_Attr, ANSI_Value2); - SetConsoleTextAttribute(Std_Out, ANSI_Attr); - ANSI_Value1 = 0; - ANSI_Value2 = 0; - ANSI_State = 1; + else if (*cp == 'm' || *cp == ';') { + if(ANSI_Value2 == 5 && (ANSI_Value1 == 38 || ANSI_Value1 == 48)) { + // 8-bit colors... try to emulate it at least partially + if(*cp == 'm') { + // ignored + ANSI_State = -1; + break; + } else { + // 256-color lookup; fetch one more value + ANSI_Value1 = -ANSI_Value1; + ANSI_Value2 = 0; + ANSI_State = 3; + break; + } + } + else if(ANSI_Value1 < 0) { + // 256-color lookup + ANSI_Value1 = -ANSI_Value1 - 8; + if(ANSI_Value2 < 8) { + // standard colors (as in ESC [ 30–37 m) + ANSI_Attr = Update_Graphic_Mode(ANSI_Attr, ANSI_Value2 + ANSI_Value1, TRUE); + + } else if(ANSI_Value2 < 16) { + // high intensity colors (as in ESC [ 90–97 m) + ANSI_Attr = Update_Graphic_Mode(ANSI_Attr, ANSI_Value2 + ANSI_Value1 + 60 - 8, TRUE); + } else { + // on POSIX it is 216 colors and or 24 grey colors + // this is not possible on Windows.. so just ignore it. + } + } + else { + ANSI_Attr = Update_Graphic_Mode(ANSI_Attr, ANSI_Value1, FALSE); + ANSI_Attr = Update_Graphic_Mode(ANSI_Attr, ANSI_Value2, TRUE); + } + if (*cp == ';') { + ANSI_Value1 = 0; + ANSI_Value2 = 0; + ANSI_State = 1; + } + else { + ANSI_State = -1; + } } else if (*cp == 'H' || *cp == 'f') { coordScreen.Y = ANSI_Value1;