/** ******************************************************************************************** * * The implementation of the abstract method of parent class TextLogger. Logs messages to the * application console and/or the VStudio output window. * * @param domain The <em>Log Domain</em>. * @param verbosity The verbosity. This has been checked to be active already on this * stage and is provided to be able to be logged out only. * @param msg The log message. * @param scope Information about the scope of the <em>Log Statement</em>.. * @param lineNumber The line number of a multi-line message, starting with 0. For * single line messages this is -1. **********************************************************************************************/ override protected void logText(Domain domain, Verbosity verbosity, AString msg, ScopeInfo scope, int lineNumber) { // get actual console attributes ConsoleColor actualFGCol = Console.ForegroundColor; ConsoleColor actualBGCol = Console.BackgroundColor; // loop over message, print the parts between the escape sequences Tokenizer msgParts = new Tokenizer(msg, '\x1B'); Substring actual = msgParts.Actual; Substring rest = msgParts.Rest; int column = 0; for (;;) { if (msgParts.Next(Whitespaces.Keep).IsNotEmpty()) { #if !(ALOX_WP71 || ALOX_WP8) Console.Write(msg.Buffer(), actual.Start, actual.Length()); #else Console.Write(msg.ToString(0, actual.Start, actual.Length()); #endif column += actual.Length(); } // end of loop? if (!msgParts.HasNext()) { break; } // found an ESC sequence char c = rest.Consume(); // Colors bool isForeGround = true; if (c == 'C' || c == 'c') { isForeGround = c == 'c'; c = rest.Consume(); int colNo = c - '0'; ALIB.ASSERT_WARNING(colNo >= 0 && colNo <= 9, "Unknown ESC-c code"); // set color if (colNo >= 0 && colNo <= 8 || colNo == 8) { ConsoleColor[] cols = (isForeGround ? !IsBackgroundLight : IsBackgroundLight) ? lightColors : darkColors; if (isForeGround) { Console.ForegroundColor = cols[colNo]; } else { Console.BackgroundColor = cols[colNo]; } } else if (colNo == 9) { if (isForeGround) { Console.ForegroundColor = actualFGCol; } else { Console.BackgroundColor = actualBGCol; } } else { ALIB.WARNING("Unknown ESC- code"); } } // Styles else if (c == 's') { // bold/italics style not supported in Windows console // reset all if (rest.Consume() == 'a') { Console.ForegroundColor = actualFGCol; Console.BackgroundColor = actualBGCol; } } // auto tab / end of meta else if (c == 't' || c == 'A') { bool endOfMeta = c == 'A'; c = rest.Consume(); int extraSpace = c >= '0' && c <= '9' ? (int) (c - '0') : (int)(c - 'A') + 10; int tabStop = AutoSizes.Next(column, extraSpace); Util.WriteSpaces(Console.Out, tabStop - column); column = tabStop; if (endOfMeta) { switch (verbosity) { case Verbosity.Verbose: Console.ForegroundColor = MsgColorVerbose; break; case Verbosity.Info: Console.ForegroundColor = MsgColorInfo; break; case Verbosity.Warning: Console.ForegroundColor = MsgColorWarning; break; case Verbosity.Error: Console.ForegroundColor = MsgColorError; break; default: break; } } } // Link (we just colorize links here) else if (c == 'l') { if (rest.Consume() == 'S') { Console.ForegroundColor = IsBackgroundLight ? ConsoleColor.DarkBlue : ConsoleColor.Blue; } else { Console.ForegroundColor = actualFGCol; } } else { ALIB.WARNING("Unknown ESC code"); } } // write loop // reset colors Console.ForegroundColor = actualFGCol; Console.BackgroundColor = actualBGCol; // write NL #if !(ALOX_WP71 || ALOX_WP8) Console.WriteLine(); #else Console.WriteLine(); #endif }
// ############################################################################################# // logText // ############################################################################################# /** ******************************************************************************************** * * The implementation of the abstract method of parent class TextLogger. Logs messages to the * application console and/or the VStudio output window. * * @param domain The <em>Log Domain</em>. * @param verbosity The verbosity. This has been checked to be active already on this * stage and is provided to be able to be logged out only. * @param msg The log message * @param scope Information about the scope of the <em>Log Statement</em>.. * @param lineNumber The line number of a multi-line message, starting with 0. For * single line messages this is -1. **********************************************************************************************/ override protected void logText(Domain domain, Verbosity verbosity, AString msg, ScopeInfo scope, int lineNumber) { // loop over message, print the parts between the escape sequences Tokenizer msgParts = new Tokenizer(msg, '\x001B'); Substring actual = msgParts.Actual; Substring rest = msgParts.Rest; int column = 0; for (;;) { msgParts.Next(Whitespaces.Keep); // check if this is an ANSI sequence already if (rest.CharAtStart() == '[') { // read the 'm' int idx = rest.IndexOf('m'); if (idx < 0) // unknown ANSI Code { ALIB.WARNING("Unknown ANSI ESC Code "); textWriter.Write(actual.Buf, actual.Start, actual.Length()); continue; } column += actual.Length(); actual.End = rest.Start + idx; rest.Start += idx + 1; textWriter.Write(actual.Buf, actual.Start, actual.Length()); continue; } else { if (actual.IsNotEmpty()) { textWriter.Write(actual.Buf, actual.Start, actual.Length()); column += actual.Length(); } } // end of loop? if (!msgParts.HasNext()) { break; } // found an ESC sequence char c = rest.Consume(); // Colors bool isForeGround = true; if (c == 'C' || c == 'c') { isForeGround = c == 'c'; c = rest.Consume(); int colNo = c - '0'; ALIB.ASSERT_WARNING(colNo >= 0 && colNo <= 9, "Unknown ESC-c code"); // add bg colNo += isForeGround ? 0 : 10; // add light colNo += (isForeGround ? !IsBackgroundLight : IsBackgroundLight) ? 20 : 0; textWriter.Write(ansiCols[colNo]); } // Styles else if (c == 's') { // bold/italics style not supported in Windows console // reset all if (rest.Consume() == 'a') { textWriter.Write(ANSI_RESET); } } // auto tab / end of meta else if (c == 't' || c == 'A') { bool endOfMeta = c == 'A'; c = rest.Consume(); int extraSpace = c >= '0' && c <= '9' ? (int)(c - '0') : (int)(c - 'A') + 10; int tabStop = AutoSizes.Next(column, extraSpace); Util.WriteSpaces(textWriter, tabStop - column); column = tabStop; if (endOfMeta) { String msgPrefix; switch (verbosity) { case lox.Verbosity.Verbose: msgPrefix = MsgPrefixVerbose; break; case lox.Verbosity.Info: msgPrefix = MsgPrefixInfo; break; case lox.Verbosity.Warning: msgPrefix = MsgPrefixWarning; break; case lox.Verbosity.Error: msgPrefix = MsgPrefixError; break; default: msgPrefix = ""; break; } textWriter.Write(msgPrefix); } } // Link (we just colorize links here) else if (c == 'l') { textWriter.Write(rest.Consume() == 'S' ? (IsBackgroundLight ? ANSI_LIGHT_BLUE : ANSI_LIGHT_BLUE) : ANSI_STD_COL); } else { ALIB.WARNING("Unknown ESC code"); } } // write loop textWriter.WriteLine(MsgSuffix); }
/** ******************************************************************************************** * The implementation of the abstract method of parent class TextLogger. * Loops over the log text, removes or ignores ESC sequences (all but ESC.TAB) and invokes * abstract methods of descendants as follows: * - \ref notifyLogOp "notifyLogOp(true)" * - #logSubstring() * - ... * - \ref notifyLogOp "notifyLogOp(Phase.End)" * * @param domain The <em>Log Domain</em>. * @param verbosity The verbosity. This has been checked to be active already on this stage * and is provided to be able to be logged out only. * @param msg The log message. * @param scope Information about the scope of the <em>Log Statement</em>.. * @param lineNumber The line number of a multi-line message, starting with 0. For single * line messages this is -1. **********************************************************************************************/ override protected void logText(Domain domain, Verbosity verbosity, AString msg, ScopeInfo scope, int lineNumber) { if (!notifyLogOp(Phase.Begin)) { return; } // loop over message, print the parts between the escape sequences int msgLength = msg.Length(); int start = 0; int end; int column = 0; while (start < msgLength) { bool foundESC = true; end = msg.IndexOf('\x1B', start); if (end < 0) { foundESC = false; end = msgLength; } if (end > start) { if (!logSubstring(msg, start, end - start)) { return; } column += end - start; } // interpret escape sequence if (foundESC) { char c = msg[++end]; // auto tab or end of meta info part if (c == 't' || c == 'A') { end++; c = msg[end++]; int extraSpace = c >= '0' && c <= '9' ? (int)(c - '0') : (int)(c - 'A') + 10; int tabStop = AutoSizes.Next(column, extraSpace); if (tabStop > column) { AString spaces = Util.GetSpaces(); int spacesLength = spaces.Length(); int qty = tabStop - column; while (qty > 0) { int size = qty < spacesLength ? qty : spacesLength; if (!logSubstring(spaces, 0, size)) { return; } qty -= size; } column = tabStop; } } // prune or ignore all others else { if (!PruneESCSequences) { if (!logSubstring(msg, end - 1, 3)) { return; } } end += 2; } } // next start = end; } // write loop ALIB.ASSERT_WARNING(start == msgLength, "Loop error when pruning ESC codes"); notifyLogOp(Phase.End); }