Gianni Posted April 7, 2018 Posted April 7, 2018 Hi, this is a followup from this previous post (https://www.autoitscript.com/forum/topic/192953-regexp-and-ansi-escape-sequences/ I'm trying to make an ANSI file viewer. Some basic functions, even if still with some issues, let me do some early tests. I use a Rich Edit control as the "blackboard" where to print colored chars coming from the ANSI file (downloaded from the net), and in this "pre alpha" testing, I'm facing on a "basic" problem, that is: the chars are viewed with a wrong code page. I think that should be printed using the 437 codepage, but even trying to convert the string using the way found here (https://www.autoitscript.com/forum/topic/121847-convert-text-string-from-codepage-437-or-850-to-1252/), the result seems even worst. How can I display correctly the chars from the ANSI file so to produce the image, as the one shown in the InternetExplorer preview picture instead of that with altered chars shown in the rich edit control? Any idea on the direction to take? Thanks on advance. (to test the script, save both files in the same directory) expandcollapse popup#include '.\TextMode_udf.au3' #include <ie.au3> $oIe = _IECreate() ; just to see the original picture $hGUI = GUICreate("Ansi viewer", 700, 420, -1, -1, -1, $WS_EX_COMPOSITED) GUISetBkColor(0xFFFFFF) ; $Button1 = GUICtrlCreateButton("Test beastie ANSI", 590, 20, 100, 60) $Button2 = GUICtrlCreateButton("Test face_2 ANSI", 590, 100, 100, 60) $Button3 = GUICtrlCreateButton("Test flower ANSI", 590, 180, 100, 60) $Button4 = GUICtrlCreateButton("Test belinda ANSI", 590, 260, 100, 60) $Button5 = GUICtrlCreateButton("Test bambi 'text'", 590, 340, 100, 60) $Button6 = GUICtrlCreateButton("Clear screen", 15, 370, 555, 30) ; ; create a richedit _TextMode_GUICtrl_Create($hGUI, 10, 15, 80, 25, 9, "consolas") ; "Lucida console" ; "Terminal" ; "Courier new" GUISetState(@SW_SHOW, HWnd($hGUI)) ; While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop Case $Button1 _IENavigate($oIe,"http://artscene.textfiles.com/ansi/artwork/.png/beastie.ans.png", 0) $sMessage = BinaryToString(InetRead("http://artscene.textfiles.com/ansi/artwork/beastie.ans")) _Test($sMessage) Case $Button2 _IENavigate($oIe,"http://artscene.textfiles.com/ansi/artwork/.png/face_2.ans.png", 0) $sMessage = BinaryToString(InetRead("http://artscene.textfiles.com/ansi/artwork/face_2.ans")) _Test($sMessage) Case $Button3 _IENavigate($oIe,"http://artscene.textfiles.com/ansi/artwork/.png/flower.ans.png", 0) $sMessage = BinaryToString(InetRead("http://artscene.textfiles.com/ansi/artwork/flower.ans")) _Test($sMessage) Case $Button4 _IENavigate($oIe,"http://artscene.textfiles.com/ansi/artwork/.png/belinda.ans.png", 0) $sMessage = BinaryToString(InetRead("http://artscene.textfiles.com/ansi/artwork/belinda.ans")) _Test($sMessage) Case $Button5 _IENavigate($oIe,"http://artscene.textfiles.com/vt100/bambi.vt", 0) $sMessage = BinaryToString(InetRead("http://artscene.textfiles.com/vt100/bambi.vt")) _Test($sMessage) Case $Button6 _TextMode_CLS() EndSwitch WEnd _IEQuit($oIe) Exit ; Func _Test($sMessage) ; $sMessage = _StringToCodepage($sMessage, 437) _TextMode_Print($sMessage); parse the ANSI string and print result to the RichEdit EndFunc ;==>_Test ; https://www.autoitscript.com/forum/topic/121847-convert-text-string-from-codepage-437-or-850-to-1252/ Func _StringToCodepage($ansi, $codepage) Local $struct = DllStructCreate("byte[" & StringLen($ansi) * 2 + 4 & "]") ;platz für UTF16 $string = _WinAPI_MultiByteToWideCharEx($ansi, DllStructGetPtr($struct), Number($codepage), $MB_PRECOMPOSED) ; $MB_USEGLYPHCHARS) ;Ansi-String in Codepage umwandeln Return BinaryToString(DllStructGetData($struct, 1), 2) EndFunc ;==>_StringToCodepage save this as "TextMode_udf.au3" (pre alpha code) expandcollapse popup; the following include is by @melba23 ; get it here -> https://www.autoitscript.com/forum/topic/114034-stringsize-m23-new-version-16-aug-11/ ; #include <stringsize.au3> ; for the moment is not used here since I'm using a fixed width control just for testing #include <array.au3> #include <GuiRichEdit.au3> #include <GUIConstants.au3> ; ===== !! PRE ALPHA CODE FOR EARLY TESTING !! ===== ; 'paper' dimension in chars (columns and lines) Global $iHwidth = 80 ; width of screen (nr. of chars per line) Global $iVheight = 24 ; height of screen (nr. of lines) ; Font and size (a monospaced font is MANDATORY!) Global $iFontSize = 12, $sFontName = "Consolas" ; "Terminal" ; "Perfect DOS VGA 437 Win" ; "Courier New" ; "Lucida Sans Typewriter" ; "Lucida Console" ; Global $iTabStop = 8 ; Horizontal tab stops (Historically tab stops where every 8th character) Global $iCharSet = 2 ; see --> _GUICtrlRichEdit_SetFont() #cs the character set - one of: $ANSI_CHARSET - 0 $BALTIC_CHARSET - 186 $CHINESEBIG5_CHARSET - 136 $DEFAULT_CHARSET - 1 $EASTEUROPE_CHARSET - 238 $GB2312_CHARSET - 134 $GREEK_CHARSET - 161 $HANGEUL_CHARSET - 129 $MAC_CHARSET - 77 $OEM_CHARSET - 255 $RUSSIAN_CHARSET - 204 $SHIFTJIS_CHARSET - 128 $SYMBOL_CHARSET - 2 $TURKISH_CHARSET - 162 $VIETNAMESE_CHARSET - 163 #ce ; ; the screen text buffer Global $sBuffer = "" Global $_hVintageGui, $hScreen[2] ; initialize cursor position Global $iCursorPosX = 1 ; horizontal position Global $iCursorPosY = 1 ; vertical position Global $iCursorPushX = $iCursorPosX ; Save X (for a later pull) Global $iCursorPushY = $iCursorPosY ; Save Y (for a later pull) Global $iVisibleLayer = 0 ; there are 2 screens (0 and 1) ; possible text modes. ; To set a text mode use _TextMode_Mode($mode). Without a parameter it returns current mode Global Enum $Normal, $Inverse, $Blink, $Flash ; Text attributes (to be set each for himself True/False) Global $Bold = False Global $Italic = False Global $Underline = False Global $aAttribute[2] = ['-', '+'] ; False = - True = + ; Color names Global Enum $Black, $Red, $Green, $Yellow, $Blue, $Magenta, $Cyan, $White, _ $BrightBlack, $BrightRed, $BrightGreen, $BrightYellow, $BrightBlue, $BrightMagenta, $BrightCyan, $BrightWhite ; Set ANSI color values (GRB color values from here: https://en.wikipedia.org/wiki/ANSI_escape_code#Colors) Global $aColor[16] $aColor[$Black] = 0x000000 ; 00 = Black bk .......0 $aColor[$Red] = 0x000080 ; 01 = Red rd .....128 $aColor[$Green] = 0x008000 ; 02 = Green gn ...32768 $aColor[$Yellow] = 0x008080 ; 03 = Yellow yl ...32896 $aColor[$Blue] = 0x800000 ; 04 = Blue bu .8388608 $aColor[$Magenta] = 0x800080 ; 05 = Magenta mg .8388736 $aColor[$Cyan] = 0x808000 ; 06 = Cyan cy .8421376 $aColor[$White] = 0xC0C0C0 ; 07 = White wt 12632256 $aColor[$BrightBlack] = 0x808080 ; 08 = Bright Black BK .8421504 $aColor[$BrightRed] = 0x0000FF ; 09 = Bright Red RD .....255 $aColor[$BrightGreen] = 0x00FF00 ; 10 = Bright Green GN ...65280 $aColor[$BrightYellow] = 0x00FFFF ; 11 = Bright Yellow YE ...65535 $aColor[$BrightBlue] = 0xFF0000 ; 12 = Bright Blue BU 16711680 $aColor[$BrightMagenta] = 0xFF00FF ; 13 = Bright Magenta MG 16711935 $aColor[$BrightCyan] = 0xFFFF00 ; 14 = Bright Cyan CY 16776960 $aColor[$BrightWhite] = 0xFFFFFF ; 15 = Bright White WT 16777215 ; default text colors Global Static $iDefaultForeground = $BrightWhite Global Static $iDefaultBackground = $Black Global $iActiveFGColor = $iDefaultForeground Global $iActiveBGColor = $iDefaultBackground ; ensure creation of only one TextMode 'control' Global $bControlExists = False HotKeySet("{ESC}", "_EndANSI") ; press 'esc' to end ; create a control to be placed on a parent GUI Func _TextMode_GUICtrl_Create($hWnd, $iLeft = 0, $iTop = 0, $i_Hwidth = $iHwidth, $i_Vheight = $iVheight, $i_FontSize = $iFontSize, $s_FontName = $sFontName, $i_DefaultForeground = $iDefaultForeground, $i_DefaultBackground = $iDefaultBackground) If $bControlExists = True Then Return ; if default values are changed then set also global variables accordingly $iHwidth = $i_Hwidth $iVheight = $i_Vheight $sFontName = $s_FontName $iFontSize = $i_FontSize $iDefaultForeground = $i_DefaultForeground $iDefaultBackground = $i_DefaultBackground ; fill the buffer $sBuffer = _StringReplay(_StringReplay(" ", $i_Hwidth) & @CRLF, $i_Vheight - 1) & _StringReplay(" ", $i_Hwidth) ; a string of width * height blank spaces + @crlf #cs ; determine the size of the screen according to the font parameters (by @Melba23) Local $aWinDim = _StringSize($sBuffer, $i_FontSize, 400, 0, $s_FontName) $aWinDim[2] += _StringSize(" ", $i_FontSize, 400, 0, $s_FontName)[2] Local $iWidth = $aWinDim[2], $iHeight = $aWinDim[3] ; Screen dimensions #ce Local $iWidth = 567, $iHeight = 354 ; Screen dimensions (fixed here just for the test) ; a transparent layer above the rich edit to protect it from clicks and to allow dragging of the GUI Local $hGlass = GUICtrlCreateLabel("", $iLeft, $iTop, $iWidth, $iHeight, -1, $GUI_WS_EX_PARENTDRAG) GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT) ; This is like a glass over the underlying RichEdit GUICtrlSetCursor(-1, 2) ; Cursor is an arrow (instead of the default I-beam) $hScreen[0] = HWnd(_GUICtrlRichEdit_Create($hWnd, "", $iLeft, $iTop, $iWidth, $iHeight, BitXOR($ES_READONLY, $ES_MULTILINE))) ; DllCall('user32.dll', 'uint_ptr', 'SetTimer', 'hwnd', 0, 'uint_ptr', 0, 'uint', 500, 'ptr', DllCallbackGetPtr(DllCallbackRegister('__SwitchScreen', 'none', 'hwnd;uint;uint_ptr;dword'))) _TextMode_CLS() ; Initialize and clear the screen $bControlExists = True Return $hScreen EndFunc ;==>_TextMode_GUICtrl_Create ; From Htab Vtab (1 based) to absolute within the screen buffer Func __GetAbsPos($iHtab = 1, $iVtab = 1, $iScreenWidth = $iHwidth) Return ($iVtab - 1) * ($iScreenWidth + 1) + $iHtab EndFunc ;==>__GetAbsPos ; From Absolute To Htab Vtab (1 based) Func __GetTabsPos($iAbsolutePos = 1, $iScreenWidth = $iHwidth) Local $aXY[2] $aXY[0] = Mod($iAbsolutePos - 1, $iScreenWidth) + 1 ; Horizontal position within the Screen (column) $iHtab $aXY[1] = Int(($iAbsolutePos - 1) / $iScreenWidth) + 1 ; Vertical position within the Screen (row) $iVtab Return $aXY EndFunc ;==>__GetTabsPos ; don't show drawing activity (draw behind the shenes) Func _TextMode_PauseRedraw() _GUICtrlRichEdit_PauseRedraw($hScreen[0]) EndFunc ;==>_TextMode_PauseRedraw ; show what's been drawn Func _TextMode_ResumeRedraw() _GUICtrlRichEdit_ResumeRedraw($hScreen[0]) EndFunc ;==>_TextMode_ResumeRedraw ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TextMode_Print ; Description ...: Main printing function ; Syntax ........: _TextMode_Print([$sString = ""[, $iHtab = $iCursorPosX[, $iVtab = $iCursorPosY[, $iForegroundColor = $iActiveFGColor[, ; $iBackgroundColor = $iActiveBGColor]]]]]) ; Parameters ....: $sString - [optional] a string value. Default is "". ; $iHtab - [optional] column where to start printing ; $iVtab - [optional] row where to start printnting ; $iForegroundColor - [optional] wanted foreground color ; $iBackgroundColor - [optional] Wanted bckground color ; =============================================================================================================================== Func _TextMode_Print($sString = "", $iHtab = $iCursorPosX, $iVtab = $iCursorPosY, $iForegroundColor = $iActiveFGColor, $iBackgroundColor = $iActiveBGColor) If $iHtab = Default Then $iHtab = $iCursorPosX If $iVtab = Default Then $iVtab = $iCursorPosY ; Local $aString = __StringSplitKeepTokens($sString) ; break the string to find the control characters Local $iStartingHtab = $iHtab ; Local $iActiveFGColor = $iForegroundColor ; Local $iActiveBGColor = $iBackgroundColor Local $sANSI_Escape Local $aParameters[1] ; split string on ansi escape sequences and control codes (if any) ; ---------------------------------------------------------------- ; Main RegExp pattern by @jchd (Thanks to @jchd) https://www.autoitscript.com/forum/topic/192953-regexp-and-ansi-escape-sequences/?do=findComment&comment=1386039 ; pattern also modified by @mikell (Thanks to @mikell) https://www.autoitscript.com/forum/topic/192953-regexp-and-ansi-escape-sequences/?do=findComment&comment=1387160 Local $aStringChunks = StringRegExp($sString, "(?x)(?(DEFINE) (?<ANSI_Escape> \[ (?:\s*\d*\s*;?)* [[:alpha:]]) )(?| \x1B(?&ANSI_Escape) | [\x01-\x1A\x1C-\x1F] | \x1B(?!(?&ANSI_Escape)) | (?:[^\x01-\x1F] (?!(?&ANSI_Escape)))+ )", 3) ; _ArrayDisplay($aStringChunks, "Debug") For $iChunk = 0 To UBound($aStringChunks) - 1 ; check presence of escape sequences or control chars $sANSI_Escape = StringReplace($aStringChunks[$iChunk], " ", "") ; clean unneeded (and disturbing)spaces If StringLeft($sANSI_Escape, 2) = Chr(27) & "[" Then ; it is a CSI (Control Sequence Introducer) ; ConsoleWrite("Debug: CSI -> " & $sANSI_Escape & @CRLF) ; get ansi escape sequence parameters $aParameters = StringSplit(StringMid(StringTrimRight($sANSI_Escape, 1), 3), ";") ; extract the parameters of this sequence $aParameters[0] = StringRight($sANSI_Escape, 1) ; gat the final character (put it in [0]) ; _ArrayDisplay($aParameters, "Debug") ; ; ANSI Escape squence interpreter ; ------------------------------- Select Case $aParameters[0] == "a" ; HPR Move cursor right the indicated # of columns. $iHtab += Number($aParameters[1]) + ($aParameters[1] = 0) $iCursorPosX = $iHtab Case $aParameters[0] == "d" ; VPA Move cursor to the indicated row, current column. $iHtab = Number($aParameters[1]) $iCursorPosX = $iHtab Case $aParameters[0] == "e" ; VPR Move cursor down the indicated # of rows. $iVtab += Number($aParameters[1]) + ($aParameters[1] = 0) $iCursorPosY = $iVtab Case $aParameters[0] == "f" ; HVP Move cursor to the indicated row, column. ReDim $aParameters[3] ; mandatory 2 parameters $iVtab = Number($aParameters[1]) + ($aParameters[1] = 0) $iCursorPosY = $iVtab $iHtab = Number($aParameters[2]) + ($aParameters[2] = 0) $iCursorPosX = $iHtab Case $aParameters[0] == "g" ; TBC Without parameter: clear tab stop at current position. ; ? Case $aParameters[0] == "h" ; SM Set Mode ; ? Case $aParameters[0] == "l" ; RM Reset Mode ; ? Case $aParameters[0] == "m" ; SGR Set attributes. ; _ArrayDisplay($aParameters,"Debug") For $iParam = 1 To UBound($aParameters) - 1 Switch Number($aParameters[$iParam]) Case 0 ; reset all attributes to their defaults _TextMode_SetDefaultColors() _TextMode_SetMode($Normal) $Bold = False $Italic = False $Underline = False Case 1 ; set bold $Bold = True Case 4 ; set underscore $Underline = True Case 5 ; set blink _TextMode_SetMode($Blink) Case 7 ; set reverse video _TextMode_SetMode($Inverse) Case 8 ; concealed (foreground becomes background) _TextMode_SetMode($Inverse) Case 22 ; bold off $Bold = False Case 24 ; underline off $Underline = False Case 25 ; blink off _TextMode_SetMode($Normal) Case 27 ; reverse video off _TextMode_SetMode($Normal) Case 28 ; concealed off _TextMode_SetMode($Normal) Case 30 To 37 ; set foreground color $iForegroundColor = _TextMode_SetActiveForeColor(Number($aParameters[$iParam]) - 30) Case 38 ; set default foreground color ; 38;2;# foreground based on index (0-255) ; 38;5;#;#;# foreground based on RGB Case 39 ; set default foreground (using current intensity) Case 40 To 47 ; set background color $iBackgroundColor = _TextMode_SetActiveBackColor(Number($aParameters[$iParam]) - 40) Case 48 ; 48;2;# background based on index (0-255) ; 48;5;#;#;# background based on RGB Case 49 ; set default background (using current intensity) Case 90 To 97 ; set foreground bright color $iForegroundColor = _TextMode_SetActiveForeColor(Number($aParameters[$iParam]) - 82) Case 100 To 107 ; ; set background bright color $iBackgroundColor = _TextMode_SetActiveBackColor(Number($aParameters[$iParam]) - 92) EndSwitch Next Case $aParameters[0] == "n" ; DSR Status report ; ? Case $aParameters[0] == "q" ; DECLL Set keyboard LEDs. ; ESC [ 0 q: clear all LEDs ; ESC [ 1 q: set Scroll Lock LED ; ESC [ 2 q: set Num Lock LED ; ESC [ 3 q: set Caps Lock LED Case $aParameters[0] == "r" ; DECSTBM Set scrolling region; parameters are top and bottom row. Case $aParameters[0] == "s" ; ? Save cursor location. _PushCursor() Case $aParameters[0] == "u" ; ? Restore cursor location. _PullCursor() $iHtab = $iCursorPosX $iVtab = $iCursorPosY Case $aParameters[0] == "`" ; HPA Move cursor to indicated column in current row. $iHtab = Number($aParameters[1]) $iCursorPosX = $iHtab Case $aParameters[0] == "@" ; ICH Insert the indicated # of blank characters. Case $aParameters[0] == "A" ; CUU Move cursor up the indicated # of rows. ; ConsoleWrite("Debug: " & Number($aParameters[1]) - ($aParameters[1] = 0) & @CRLF) $iVtab -= Number($aParameters[1]) - ($aParameters[1] = 0) $iCursorPosY = $iVtab Case $aParameters[0] == "B" ; CUD Move cursor down the indicated # of rows. $iVtab += Number($aParameters[1]) + ($aParameters[1] = 0) $iCursorPosY = $iVtab Case $aParameters[0] == "C" ; CUF Move cursor right the indicated # of columns. $iHtab += Number($aParameters[1]) + ($aParameters[1] = 0) $iCursorPosX = $iHtab Case $aParameters[0] == "D" ; CUB Move cursor left the indicated # of columns. $iHtab -= Number($aParameters[1]) - ($aParameters[1] = 0) $iCursorPosX = $iHtab Case $aParameters[0] == "E" ; CNL Move cursor down the indicated # of rows, to column 1. $iVtab += Number($aParameters[1]) + ($aParameters[1] = 0) $iCursorPosY = $iVtab $iHtab = 1 $iCursorPosX = $iHtab Case $aParameters[0] == "F" ; CPL Move cursor up the indicated # of rows, to column 1. $iVtab -= Number($aParameters[1]) - ($aParameters[1] = 0) $iCursorPosY = $iVtab $iHtab = 1 $iCursorPosX = $iHtab Case $aParameters[0] == "G" ; CHA Move cursor to indicated column in current row. $iHtab = Number($aParameters[1]) $iCursorPosX = $iHtab Case $aParameters[0] == "H" ; CUP Move cursor to the indicated row, column (origin at 1,1). ReDim $aParameters[3] ; mandatory 2 parameters $iVtab = Number($aParameters[1]) + ($aParameters[1] = 0) $iCursorPosY = $iVtab $iHtab = Number($aParameters[2]) + ($aParameters[2] = 0) $iCursorPosX = $iHtab Case $aParameters[0] == "J" ; ED Erase display (default: from cursor to end of display). ReDim $aParameters[2] ; mandatory 1 parameters Switch Number($aParameters[1]) Case 0 ; Pn=0: erases from active position to end of display. __Sub_Print(_StringReplay(" ", $iHwidth - $iHtab + 1), $iHtab, $iVtab, $iDefaultForeground, $iDefaultBackground) If $iVtab < $iVheight Then For $y = $iVtab + 1 To $iVheight __Sub_Print(_StringReplay(" ", $iHwidth), 1, $y, $iDefaultForeground, $iDefaultBackground) Next EndIf Case 1 ; Pn=1: erases from the beginning of display to active position. __Sub_Print(_StringReplay(" ", $iHtab), 1, $iVtab, $iDefaultForeground, $iDefaultBackground) If $iVtab > 1 Then For $y = 1 To $iVtab - 1 __Sub_Print(_StringReplay(" ", $iHwidth), 1, $y, $iDefaultForeground, $iDefaultBackground) Next EndIf Case 2 ; Pn=2: erases entire display and move cursor to the top-left. _TextMode_CLS() $iHtab = 1 $iVtab = 1 EndSwitch Case $aParameters[0] == "K" ; EL Erase line (default: from cursor to end of line). __Sub_Print(_StringReplay(" ", $iHwidth - $iHtab + 1), $iHtab, $iVtab, $iActiveFGColor, $iActiveBGColor) Case $aParameters[0] == "L" ; IL Insert the indicated # of blank lines. Case $aParameters[0] == "M" ; DL Delete the indicated # of lines. Case $aParameters[0] == "P" ; DCH Delete the indicated # of characters on current line. __Sub_Print(_StringReplay(" ", $aParameters[1]), $iHtab, $iVtab, $iActiveFGColor, $iActiveBGColor) Case $aParameters[0] == "X" ; ECH Erase the indicated # of characters on current line. __Sub_Print(_StringReplay(" ", $aParameters[1]), $iHtab, $iVtab, $iDefaultForeground, $iDefaultBackground) EndSelect ; ; is it a single Control character ? (http://jkorpela.fi/chars/c0.html) ElseIf StringLen($sANSI_Escape) = 1 And (AscW($sANSI_Escape) >= 0 And AscW($sANSI_Escape) <= 0x1F) Then ; and 1 = 2 ; ConsoleWrite("Debug: ctrl -> " & @TAB & "[" & Ascw($sANSI_Escape) & "]" & @TAB & "[" & Asc($sANSI_Escape) & "]" & @TAB & "<-----------------------------" & @CRLF) ; control character interpreter ; --------------------------------------------------------------------------------------- $aParameters[0] = $sANSI_Escape Select Case $aParameters[0] = Chr(7) ; Bell, rings the bell Beep(900, 150) Case $aParameters[0] = Chr(8) ; Backspace <-- $iHtab -= 1 $iCursorPosX = $iHtab Case $aParameters[0] = Chr(9) ; Horizontal tab ; (Historically tab stops were every 8th character) If $iHtab >= 0 Then $iHtab = $iHtab + (Mod($iHtab, $iTabStop) * -1) + $iTabStop Else $iHtab = $iHtab + (Mod(Abs($iHtab) - 1, $iTabStop) + 1) EndIf $iCursorPosX = $iHtab Case $aParameters[0] = Chr(10) ; Line Feed @LF (move cursor down by 1 line) $iVtab += 1 $iCursorPosY = $iVtab Case $aParameters[0] = Chr(11) ; Vertical tab (move cusros up by 1 line) $iVtab -= 1 $iCursorPosY = $iVtab Case $aParameters[0] = Chr(12) ; Form Feed ; Case $aParameters[0] = Chr(13) ; Carriage Return @CR (move cursor to the beginning of this line) $iHtab = 1 $iCursorPosX = $iHtab Case $aParameters[0] = Chr(24) ; backspace with deletion (Cancel) $iHtab -= 1 __Sub_Print(" ", $iHtab, $iVtab, $iActiveFGColor, $iActiveBGColor) $iCursorPosX = $iHtab Case $aParameters[0] = Chr(30) ; LF + a partial CR (Carriage Return stops below previous HTab) ; (custom private) $iVtab += 1 $iHtab = $iStartingHtab $iCursorPosX = $iHtab $iCursorPosY = $iVtab Case $aParameters[0] = Chr(31) ; move cursor to the right by 1 char --> ; ConsoleWrite(".") $iHtab += 1 $iCursorPosX = $iHtab EndSelect Else ; print the text ; ConsoleWrite("Debug: FG=" & $iActiveFGColor & @TAB & "BG=" & $iActiveBGColor & @CRLF) ; $aStringChunks[$iChunk] = StringReplace(StringStripCR(_StringToCodepage($aStringChunks[$iChunk], 437)), @LF, "") __Sub_Print(StringReplace($aStringChunks[$iChunk], ChrW(0), ""), $iHtab, $iVtab, $iForegroundColor, $iBackgroundColor) $iHtab = $iCursorPosX $iVtab = $iCursorPosY EndIf Next EndFunc ;==>_TextMode_Print ; keep only the string portion that will fall into the the screen (parts outside the screen will be discarded) Func __Sub_Print($sString = "", $iHtab = $iCursorPosX, $iVtab = $iCursorPosY, $iForegroundColor = $iActiveFGColor, $iBackgroundColor = $iActiveBGColor) Local $iStringFullLen = StringLen($sString) Local $iStringLen = $iStringFullLen If Not $iStringLen Then Return ; no string to print Local $iStringEnd = $iHtab + $iStringLen - 1 $iCursorPosX = $iHtab + $iStringLen $iCursorPosY = $iVtab If _ ; check if all the string falls outside the printable area $iHtab > $iHwidth Or _ ; over the right edge $iVtab > $iVheight Or _ ; below the bottom $iVtab < 1 Or _ ; over the top edges $iStringEnd < 1 _ ; over the left edge Then Return ; adjust string if only a part has to be Printed If $iHtab < 1 Then ; remove the part outside on the left $sString = StringRight($sString, $iStringEnd) $iStringLen = StringLen($sString) $iHtab = 1 EndIf If $iStringEnd > $iHwidth Then ; removes the exceeding part on the right $sString = StringTrimRight($sString, $iStringEnd - $iHwidth) $iStringLen = StringLen($sString) EndIf Local $iAnchor = __GetAbsPos($iHtab, $iVtab) - 1 Local $iActive = $iAnchor + $iStringLen Switch _TextMode_Mode() Case $Normal ; print normal text on both layers __PokeText(0, $sString, $iAnchor, $iActive, $iForegroundColor, $iBackgroundColor) Case $Inverse ; switch foreground and background colors and print on both layers __PokeText(0, $sString, $iAnchor, $iActive, $iBackgroundColor, $iForegroundColor) Case $Blink ; to be continued .... __PokeText(0, $sString, $iAnchor, $iActive, $iForegroundColor, $iBackgroundColor) Case $Flash ; to be continued .... __PokeText(0, $sString, $iAnchor, $iActive, $iForegroundColor, $iBackgroundColor) Case Else EndSwitch EndFunc ;==>__Sub_Print ; Place string on the "screen" buffer Func __PokeText($iLayer, $sString, $iAnchor, $iActive, $iForeColor, $iBackColor) ; select the part of the screen buffer to be replaced with the incoming $sString _GUICtrlRichEdit_SetSel($hScreen[$iLayer], $iAnchor, $iActive, True) ; set styles for the incoming text _GUICtrlRichEdit_SetFont($hScreen[$iLayer], $iFontSize, $sFontName, $iCharSet) _GUICtrlRichEdit_SetCharColor($hScreen[$iLayer], __PeekColor($iForeColor)) _GUICtrlRichEdit_SetCharBkColor($hScreen[$iLayer], __PeekColor($iBackColor)) ; set or unset bold, italic, underline according if the rispective variable is set to true or false _GUICtrlRichEdit_SetCharAttributes($hScreen[$iLayer], $aAttribute[$Bold] & 'bo' & $aAttribute[$Italic] & 'it' & $aAttribute[$Underline] & 'un') ; place the text on the screen _GUICtrlRichEdit_ReplaceText($hScreen[$iLayer], $sString, False) _GUICtrlRichEdit_Deselect($hScreen[$iLayer]) EndFunc ;==>__PokeText Func _PushCursor($sAction = "Push") Local Static $iCursorPushX = $iCursorPosX Local Static $iCursorPushY = $iCursorPosY If $sAction = "Push" Then $iCursorPushX = $iCursorPosX $iCursorPushY = $iCursorPosY EndIf Local $aXY[2] = [$iCursorPushX, $iCursorPushY] Return $aXY EndFunc ;==>_PushCursor Func _PullCursor() Local $aXY = _PushCursor("Pull") $iCursorPosX = $aXY[0] $iCursorPosY = $aXY[1] EndFunc ;==>_PullCursor ; if you pass a number 0-15 it returns a predefined color from the $aColor[] array. ; if the number is > 15 and <= 0xFFFFFF it returns the same number, while if the passed ; number is out of range it return 0 ($Black)and sets @error Func __PeekColor($iColor) $iColor = Number($iColor) If $iColor >= 0 And $iColor < UBound($aColor) Then Return $aColor[$iColor] ; predefined colors ElseIf $iColor >= UBound($aColor) And $iColor <= 0xFFFFFF Then Return $iColor ; value is <= 0xFFFFFF Else Return SetError(1, 0, 0) ; if out of range return Black and set error EndIf EndFunc ;==>__PeekColor ; clear the screen (fill screen buffer with spaces) ; (for 'crazy' effects you could also select another char instead of the space and custom colors) Func _TextMode_CLS($sFillChr = " ", $iForegroundColor = $iActiveFGColor, $iBackgroundColor = $iActiveBGColor) ; clear the screen ; fill screen with white spaces (screen buffer) _GUICtrlRichEdit_SetText($hScreen[0], _StringReplay(_StringReplay($sFillChr, $iHwidth) & @CRLF, $iVheight - 1) & _StringReplay($sFillChr, $iHwidth)) _GUICtrlRichEdit_SetSel($hScreen[0], 0, -1, True) ; select whole screen ; set parameters _GUICtrlRichEdit_SetFont($hScreen[0], $iFontSize, $sFontName, $iCharSet) ; Set Font _GUICtrlRichEdit_SetCharColor($hScreen[0], __PeekColor($iForegroundColor)) ; Set Foreground default color _GUICtrlRichEdit_SetCharBkColor($hScreen[0], __PeekColor($iBackgroundColor)) ; Set Background default color _GUICtrlRichEdit_SetSel($hScreen[0], 0, 0, False) ; set cursor to home $iCursorPosX = 1 $iCursorPosY = 1 EndFunc ;==>_TextMode_CLS Func _TextMode_SetDefaultColors($iForeColor = $iDefaultForeground, $iBackColor = $iDefaultBackground) If $iForeColor = Default Then $iForeColor = $iDefaultForeground If $iForeColor < $Black Or $iForeColor > $BrightWhite Or $iForeColor = "" Then $iForeColor = $iActiveFGColor If $iBackColor = Default Then $iBackColor = $iDefaultBackground If $iBackColor < $Black Or $iBackColor > $BrightWhite Or $iBackColor = "" Then $iBackColor = $iActiveBGColor $iActiveFGColor = $iForeColor $iActiveBGColor = $iBackColor Local $aDefaultColors = [$iActiveFGColor, $iActiveBGColor] Return $aDefaultColors EndFunc ;==>_TextMode_SetDefaultColors Func _TextMode_SetActiveForeColor($iForeColor = $iActiveFGColor) If $iForeColor = Default Then $iForeColor = $iDefaultForeground If $iForeColor < $Black Or $iForeColor > $BrightWhite Then $iForeColor = $iActiveFGColor $iActiveFGColor = $iForeColor Return $iActiveFGColor EndFunc ;==>_TextMode_SetActiveForeColor Func _TextMode_SetActiveBackColor($iBackColor = $iActiveBGColor) If $iBackColor = Default Then $iBackColor = $iDefaultBackground If $iBackColor < $Black Or $iBackColor > $BrightWhite Then $iBackColor = $iActiveBGColor $iActiveBGColor = $iBackColor Return $iActiveBGColor EndFunc ;==>_TextMode_SetActiveBackColor ; Get / Set active TextMode effect Func _TextMode_Mode($iMode = -1) Local Static $iTextMode If $iMode >= $Normal And $iMode <= $Flash Then $iTextMode = $iMode Return $iTextMode EndFunc ;==>_TextMode_Mode ; set Normal or Inverse or Blink or Flash Func _TextMode_SetMode($iMode = $Normal) If $iMode >= $Normal And $iMode <= $Flash Then Return _TextMode_Mode($iMode) Else Return _TextMode_Mode() EndIf EndFunc ;==>_TextMode_SetMode ; check if is within color ranges Func _IsRGB($iColor) Return $iColor >= 0x000000 And $iColor <= 0xFFFFFF EndFunc ;==>_IsRGB ; move the TextMode GUI to Func _TextMode_GUIMoveTo($iX = 5, $iY = 5, $_hGUI = $_hVintageGui) If IsHWnd($_hGUI) Then WinMove($_hGUI, "", $iX, $iY) EndFunc ;==>_TextMode_GUIMoveTo Func _EndANSI() _GUICtrlRichEdit_Destroy($hScreen[0]) Exit EndFunc ;==>_EndANSI ; returns one or more chars replicated n times ; Example: ConsoleWrite(_StringReplay('*', 5) & @CRLF) Func _StringReplay($sChars = "", $iRepeats = 0) $sChars = String($sChars) $iRepeats = Int(Abs(Number($iRepeats))) Return StringReplace(StringFormat('%' & $iRepeats & 's', ""), " ", $sChars) EndFunc ;==>_StringReplay Chimp small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....
Gianni Posted April 10, 2018 Author Posted April 10, 2018 (edited) well, just to don't leave this unsolved... the 'main' issue in this case was due to the fact that if you want to color a text, you have to:first print the text on the RichEdit (or replace an old text with a new one as in my case here) and then, after the text has been placed, select the new text and set foreground and background colors as needed. I was instead doing in "reverse order", that is setting the foreground and background colors for the incoming text, before to place the new text on the richedit, and in this way I got strange results. Anyway, on the help about the _GUICtrlRichEdit_SetCharColor() function I read: "Sets the background color of selected text or, if none selected, sets the background color of text inserted at the insertion point" and this last part of the sentence made me think I could set the colors before the text, but doing so was the cause of the problem. here the modified listings to see the differences example: expandcollapse popup#include '.\TextMode_udf.au3' #include <ie.au3> $oIe = _IECreate() ; just to see the original picture $hGUI = GUICreate("Ansi viewer", 700, 420, -1, -1, -1, $WS_EX_COMPOSITED) GUISetBkColor(0xFFFFFF) ; $Button1 = GUICtrlCreateButton("Test beastie ANSI", 590, 20, 100, 60) $Button2 = GUICtrlCreateButton("Test face_2 ANSI", 590, 100, 100, 60) $Button3 = GUICtrlCreateButton("Test flower ANSI", 590, 180, 100, 60) $Button4 = GUICtrlCreateButton("Test belinda ANSI", 590, 260, 100, 60) $Button5 = GUICtrlCreateButton("Test bambi 'text'", 590, 340, 100, 60) $Button6 = GUICtrlCreateButton("Clear screen", 15, 370, 555, 30) ; ; create a richedit _TextMode_GUICtrl_Create($hGUI, 10, 15, 80, 25, 9, "consolas") ; "Lucida console" ; "Terminal" ; "Courier new" GUISetState(@SW_SHOW, HWnd($hGUI)) ; While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop Case $Button1 _IENavigate($oIe,"http://artscene.textfiles.com/ansi/artwork/.png/beastie.ans.png", 0) $sMessage = BinaryToString(InetRead("http://artscene.textfiles.com/ansi/artwork/beastie.ans")) _Test($sMessage) Case $Button2 _IENavigate($oIe,"http://artscene.textfiles.com/ansi/artwork/.png/face_2.ans.png", 0) $sMessage = BinaryToString(InetRead("http://artscene.textfiles.com/ansi/artwork/face_2.ans")) _Test($sMessage) Case $Button3 _IENavigate($oIe,"http://artscene.textfiles.com/ansi/artwork/.png/flower.ans.png", 0) $sMessage = BinaryToString(InetRead("http://artscene.textfiles.com/ansi/artwork/flower.ans")) _Test($sMessage) Case $Button4 _IENavigate($oIe,"http://artscene.textfiles.com/ansi/artwork/.png/belinda.ans.png", 0) $sMessage = BinaryToString(InetRead("http://artscene.textfiles.com/ansi/artwork/belinda.ans")) _Test($sMessage) Case $Button5 _IENavigate($oIe,"http://artscene.textfiles.com/vt100/bambi.vt", 0) $sMessage = BinaryToString(InetRead("http://artscene.textfiles.com/vt100/bambi.vt")) _Test($sMessage) Case $Button6 _TextMode_CLS() EndSwitch WEnd _IEQuit($oIe) Exit ; Func _Test($sMessage) $sMessage = _StringToCodepage($sMessage, 437) _TextMode_Print($sMessage); parse the ANSI string and print result to the RichEdit EndFunc ;==>_Test ; https://www.autoitscript.com/forum/topic/121847-convert-text-string-from-codepage-437-or-850-to-1252/ Func _StringToCodepage($ansi, $codepage) Local $struct = DllStructCreate("byte[" & StringLen($ansi) * 2 + 4 & "]") ;platz für UTF16 $string = _WinAPI_MultiByteToWideCharEx($ansi, DllStructGetPtr($struct), Number($codepage), $MB_PRECOMPOSED) ; $MB_USEGLYPHCHARS) ;Ansi-String in Codepage umwandeln Return BinaryToString(DllStructGetData($struct, 1), 2) EndFunc ;==>_StringToCodepage TextMode_udf.au3 expandcollapse popup#include <array.au3> #include <GuiRichEdit.au3> #include <GUIConstants.au3> ; ===== !! PRE ALPHA CODE FOR EARLY TESTING !! ===== ; 'paper' dimension in chars (columns and lines) Global $iHwidth = 80 ; width of screen (nr. of chars per line) Global $iVheight = 24 ; height of screen (nr. of lines) ; Font and size (a monospaced font is MANDATORY!) Global $iFontSize = 12, $sFontName = "Consolas" ; "Terminal" ; "Perfect DOS VGA 437 Win" ; "Courier New" ; "Lucida Sans Typewriter" ; "Lucida Console" ; Global $iTabStop = 8 ; Horizontal tab stops (Historically tab stops where every 8th character) Global $iCharSet = 134 ; 134 ; see --> _GUICtrlRichEdit_SetFont() #cs the character set - one of: $ANSI_CHARSET - 0 $BALTIC_CHARSET - 186 $CHINESEBIG5_CHARSET - 136 $DEFAULT_CHARSET - 1 $EASTEUROPE_CHARSET - 238 $GB2312_CHARSET - 134 $GREEK_CHARSET - 161 $HANGEUL_CHARSET - 129 $MAC_CHARSET - 77 $OEM_CHARSET - 255 $RUSSIAN_CHARSET - 204 $SHIFTJIS_CHARSET - 128 $SYMBOL_CHARSET - 2 $TURKISH_CHARSET - 162 $VIETNAMESE_CHARSET - 163 #ce ; ; the screen text buffer Global $sBuffer = "" Global $_hVintageGui, $hScreen[2] ; initialize cursor position Global $iCursorPosX = 1 ; horizontal position Global $iCursorPosY = 1 ; vertical position Global $iCursorPushX = $iCursorPosX ; Save X (for a later pull) Global $iCursorPushY = $iCursorPosY ; Save Y (for a later pull) Global $iVisibleLayer = 0 ; there are 2 screens (0 and 1) ; possible text modes. ; To set a text mode use _TextMode_Mode($mode). Without a parameter it returns current mode Global Enum $Normal, $Inverse, $Blink, $Flash ; Text attributes (to be set each for himself True/False) Global $Bold = False Global $Italic = False Global $Underline = False Global $aAttribute[2] = ['-', '+'] ; False = - True = + ; Color names Global Enum $Black, $Red, $Green, $Yellow, $Blue, $Magenta, $Cyan, $White , _ $BrightBlack, $BrightRed, $BrightGreen, $BrightYellow, $BrightBlue, $BrightMagenta, $BrightCyan, $BrightWhite ; Set ANSI color values (GRB color values from here: https://en.wikipedia.org/wiki/ANSI_escape_code#Colors) Global $aColor[16] $aColor[$Black] = 0x000000 ; 00 = Black bk .......0 $aColor[$Red] = 0x000080 ; 01 = Red rd .....128 $aColor[$Green] = 0x008000 ; 02 = Green gn ...32768 $aColor[$Yellow] = 0x008080 ; 03 = Yellow yl ...32896 $aColor[$Blue] = 0x800000 ; 04 = Blue bu .8388608 $aColor[$Magenta] = 0x800080 ; 05 = Magenta mg .8388736 $aColor[$Cyan] = 0x808000 ; 06 = Cyan cy .8421376 $aColor[$White] = 0xC0C0C0 ; 07 = White wt 12632256 $aColor[$BrightBlack] = 0x808080 ; 08 = Bright Black BK .8421504 $aColor[$BrightRed] = 0x0000FF ; 09 = Bright Red RD .....255 $aColor[$BrightGreen] = 0x00FF00 ; 10 = Bright Green GN ...65280 $aColor[$BrightYellow] = 0x00FFFF ; 11 = Bright Yellow YE ...65535 $aColor[$BrightBlue] = 0xFF0000 ; 12 = Bright Blue BU 16711680 $aColor[$BrightMagenta] = 0xFF00FF ; 13 = Bright Magenta MG 16711935 $aColor[$BrightCyan] = 0xFFFF00 ; 14 = Bright Cyan CY 16776960 $aColor[$BrightWhite] = 0xFFFFFF ; 15 = Bright White WT 16777215 ; default text colors Global Static $iDefaultForeground = $BrightWhite Global Static $iDefaultBackground = $Black Global $iActiveFGColor = $iDefaultForeground Global $iActiveBGColor = $iDefaultBackground ; ensure creation of only one TextMode 'control' Global $bControlExists = False HotKeySet("{ESC}", "_EndANSI") ; press 'esc' to end ; create a control to be placed on a parent GUI Func _TextMode_GUICtrl_Create($hWnd, $iLeft = 0, $iTop = 0, $i_Hwidth = $iHwidth, $i_Vheight = $iVheight, $i_FontSize = $iFontSize, $s_FontName = $sFontName, $i_DefaultForeground = $iDefaultForeground, $i_DefaultBackground = $iDefaultBackground) If $bControlExists = True Then Return ; if default values are changed then set also global variables accordingly $iHwidth = $i_Hwidth $iVheight = $i_Vheight $sFontName = $s_FontName $iFontSize = $i_FontSize $iDefaultForeground = $i_DefaultForeground $iDefaultBackground = $i_DefaultBackground ; fill the buffer $sBuffer = _StringReplay(_StringReplay(" ", $i_Hwidth) & @CRLF, $i_Vheight - 1) & _StringReplay(" ", $i_Hwidth) ; a string of width * height blank spaces + @crlf #cs ; determine the size of the screen according to the font parameters (by @Melba23) Local $aWinDim = _StringSize($sBuffer, $i_FontSize, 400, 0, $s_FontName) $aWinDim[2] += _StringSize(" ", $i_FontSize, 400, 0, $s_FontName)[2] Local $iWidth = $aWinDim[2], $iHeight = $aWinDim[3] ; Screen dimensions #ce Local $iWidth = 567, $iHeight = 354 ; Screen dimensions (fixed here just for the test) ; a transparent layer above the rich edit to protect it from clicks and to allow dragging of the GUI Local $hGlass = GUICtrlCreateLabel("", $iLeft, $iTop, $iWidth, $iHeight, -1, $GUI_WS_EX_PARENTDRAG) GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT) ; This is like a glass over the underlying RichEdit GUICtrlSetCursor(-1, 2) ; Cursor is an arrow (instead of the default I-beam) $hScreen[0] = HWnd(_GUICtrlRichEdit_Create($hWnd, "", $iLeft, $iTop, $iWidth, $iHeight, BitXOR($ES_READONLY, $ES_MULTILINE))) ; DllCall('user32.dll', 'uint_ptr', 'SetTimer', 'hwnd', 0, 'uint_ptr', 0, 'uint', 500, 'ptr', DllCallbackGetPtr(DllCallbackRegister('__SwitchScreen', 'none', 'hwnd;uint;uint_ptr;dword'))) _TextMode_CLS() ; Initialize and clear the screen $bControlExists = True Return $hScreen EndFunc ;==>_TextMode_GUICtrl_Create ; From Htab Vtab (1 based) to absolute within the screen buffer Func __GetAbsPos($iHtab = 1, $iVtab = 1, $iScreenWidth = $iHwidth) Return ($iVtab - 1) * ($iScreenWidth + 1) + $iHtab EndFunc ;==>__GetAbsPos ; From Absolute To Htab Vtab (1 based) Func __GetTabsPos($iAbsolutePos = 1, $iScreenWidth = $iHwidth) Local $aXY[2] $aXY[0] = Mod($iAbsolutePos - 1, $iScreenWidth) + 1 ; Horizontal position within the Screen (column) $iHtab $aXY[1] = Int(($iAbsolutePos - 1) / $iScreenWidth) + 1 ; Vertical position within the Screen (row) $iVtab Return $aXY EndFunc ;==>__GetTabsPos ; don't show drawing activity (draw behind the shenes) Func _TextMode_PauseRedraw() _GUICtrlRichEdit_PauseRedraw($hScreen[0]) EndFunc ;==>_TextMode_PauseRedraw ; show what's been drawn Func _TextMode_ResumeRedraw() _GUICtrlRichEdit_ResumeRedraw($hScreen[0]) EndFunc ;==>_TextMode_ResumeRedraw ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TextMode_Print ; Description ...: Main printing function ; Syntax ........: _TextMode_Print([$sString = ""[, $iHtab = $iCursorPosX[, $iVtab = $iCursorPosY[, $iForegroundColor = $iActiveFGColor[, ; $iBackgroundColor = $iActiveBGColor]]]]]) ; Parameters ....: $sString - [optional] a string value. Default is "". ; $iHtab - [optional] column where to start printing ; $iVtab - [optional] row where to start printnting ; $iForegroundColor - [optional] wanted foreground color ; $iBackgroundColor - [optional] Wanted bckground color ; =============================================================================================================================== Func _TextMode_Print($sString = "", $iHtab = $iCursorPosX, $iVtab = $iCursorPosY, $iForegroundColor = $iActiveFGColor, $iBackgroundColor = $iActiveBGColor) If $iHtab = Default Then $iHtab = $iCursorPosX If $iVtab = Default Then $iVtab = $iCursorPosY ; Local $aString = __StringSplitKeepTokens($sString) ; break the string to find the control characters Local $iStartingHtab = $iHtab ; Local $iActiveFGColor = $iForegroundColor ; Local $iActiveBGColor = $iBackgroundColor Local $sANSI_Escape Local $aParameters[1] ; remove escape sequences ; $sString = StringRegExpReplace($sString, "(?x) (\x1B \[ (?:\s*\d*\s*;?)* [[:alpha:]])", "") ; split string on ansi escape sequences and control codes (if any) ; ---------------------------------------------------------------- ; Main RegExp pattern by @jchd (Thanks to @jchd) https://www.autoitscript.com/forum/topic/192953-regexp-and-ansi-escape-sequences/?do=findComment&comment=1386039 ; pattern also modified by @mikell (Thanks to @mikell) https://www.autoitscript.com/forum/topic/192953-regexp-and-ansi-escape-sequences/?do=findComment&comment=1387160 Local $aStringChunks = StringRegExp($sString, "(?x)(?(DEFINE) (?<ANSI_Escape> \[ (?:\s*\d*\s*;?)* [[:alpha:]]) )(?| \x1B(?&ANSI_Escape) | [\x01-\x1A\x1C-\x1F] | \x1B(?!(?&ANSI_Escape)) | (?:[^\x01-\x1F] (?!(?&ANSI_Escape)))+ )", 3) ; _ArrayDisplay($aStringChunks, "Debug") For $iChunk = 0 To UBound($aStringChunks) - 1 ; check presence of escape sequences or control chars $sANSI_Escape = StringReplace($aStringChunks[$iChunk], " ", "") ; clean unneeded (and disturbing)spaces If StringLeft($sANSI_Escape, 2) = Chr(27) & "[" Then ; it is a CSI (Control Sequence Introducer) ; ConsoleWrite("Debug: CSI -> " & $sANSI_Escape & @CRLF) ; get ansi escape sequence parameters $aParameters = "" $aParameters = StringSplit(StringMid(StringTrimRight($sANSI_Escape, 1), 3), ";") ; extract the parameters of this sequence $aParameters[0] = StringRight($sANSI_Escape, 1) ; gat the final character (put it in [0]) ; ReDim $aParameters[6] ; _ArrayDisplay($aParameters, "Debug") ; ; ANSI Escape squence interpreter ; ------------------------------- Select Case $aParameters[0] == "a" ; HPR Move cursor right the indicated # of columns. $iHtab += Number($aParameters[1]) + ($aParameters[1] = 0) $iCursorPosX = $iHtab Case $aParameters[0] == "d" ; VPA Move cursor to the indicated row, current column. $iHtab = Number($aParameters[1]) $iCursorPosX = $iHtab Case $aParameters[0] == "e" ; VPR Move cursor down the indicated # of rows. $iVtab += Number($aParameters[1]) + ($aParameters[1] = 0) $iCursorPosY = $iVtab Case $aParameters[0] == "f" ; HVP Move cursor to the indicated row, column. ReDim $aParameters[3] ; mandatory 2 parameters $iVtab = Number($aParameters[1]) + ($aParameters[1] = 0) $iCursorPosY = $iVtab $iHtab = Number($aParameters[2]) + ($aParameters[2] = 0) $iCursorPosX = $iHtab Case $aParameters[0] == "g" ; TBC Without parameter: clear tab stop at current position. ; ? Case $aParameters[0] == "h" ; SM Set Mode ; ? Case $aParameters[0] == "l" ; RM Reset Mode ; ? Case $aParameters[0] == "m" ; SGR Set attributes. ; _ArrayDisplay($aParameters,"Debug") For $iParam = 1 To UBound($aParameters) - 1 Switch Number($aParameters[$iParam]) Case 0 ; reset all attributes to their defaults _TextMode_SetDefaultColors() $iForegroundColor = $iDefaultForeground $iBackgroundColor = $iDefaultBackground _TextMode_SetMode($Normal) $Bold = False $Italic = False $Underline = False Case 1 ; set bold $Bold = True Case 4 ; set underscore $Underline = True Case 5 ; set blink _TextMode_SetMode($Blink) Case 7 ; set reverse video _TextMode_SetMode($Inverse) Case 8 ; concealed (foreground becomes background) _TextMode_SetMode($Inverse) Case 22 ; bold off $Bold = False Case 24 ; underline off $Underline = False Case 25 ; blink off _TextMode_SetMode($Normal) Case 27 ; reverse video off _TextMode_SetMode($Normal) Case 28 ; concealed off _TextMode_SetMode($Normal) ;#cs Case 30 To 37 ; set foreground color $iForegroundColor = _TextMode_SetActiveForeColor(Number($aParameters[$iParam]) - 30) ; ConsoleWrite("Debug: foreground=" & $aParameters[$iParam] & @CRLF) ;#ce Case 38 ; set default foreground color ; 38;2;# foreground based on index (0-255) ; 38;5;#;#;# foreground based on RGB Case 39 ; set default foreground (using current intensity) Case 40 To 47 ; set background color $iBackgroundColor = _TextMode_SetActiveBackColor(Number($aParameters[$iParam]) - 40) ; ConsoleWrite("Debug: Background=" & $aParameters[$iParam] & @CRLF) ; #cs Case 48 ; 48;2;# background based on index (0-255) ; 48;5;#;#;# background based on RGB Case 49 ; set default background (using current intensity) Case 90 To 97 ; set foreground bright color $iForegroundColor = _TextMode_SetActiveForeColor(Number($aParameters[$iParam]) - 82) Case 100 To 107 ; ; set background bright color $iBackgroundColor = _TextMode_SetActiveBackColor(Number($aParameters[$iParam]) - 92) ; #ce EndSwitch Next Case $aParameters[0] == "n" ; DSR Status report ; ? Case $aParameters[0] == "q" ; DECLL Set keyboard LEDs. ; ESC [ 0 q: clear all LEDs ; ESC [ 1 q: set Scroll Lock LED ; ESC [ 2 q: set Num Lock LED ; ESC [ 3 q: set Caps Lock LED Case $aParameters[0] == "r" ; DECSTBM Set scrolling region; parameters are top and bottom row. Case $aParameters[0] == "s" ; ? Save cursor location. _PushCursor() Case $aParameters[0] == "u" ; ? Restore cursor location. _PullCursor() $iHtab = $iCursorPosX $iVtab = $iCursorPosY Case $aParameters[0] == "`" ; HPA Move cursor to indicated column in current row. $iHtab = Number($aParameters[1]) $iCursorPosX = $iHtab Case $aParameters[0] == "@" ; ICH Insert the indicated # of blank characters. Case $aParameters[0] == "A" ; CUU Move cursor up the indicated # of rows. ; ConsoleWrite("Debug: " & Number($aParameters[1]) - ($aParameters[1] = 0) & @CRLF) $iVtab -= Number($aParameters[1]) - ($aParameters[1] = 0) $iCursorPosY = $iVtab Case $aParameters[0] == "B" ; CUD Move cursor down the indicated # of rows. $iVtab += Number($aParameters[1]) + ($aParameters[1] = 0) $iCursorPosY = $iVtab Case $aParameters[0] == "C" ; CUF Move cursor right the indicated # of columns. $iHtab += Number($aParameters[1]) + ($aParameters[1] = 0) $iCursorPosX = $iHtab Case $aParameters[0] == "D" ; CUB Move cursor left the indicated # of columns. $iHtab -= Number($aParameters[1]) - ($aParameters[1] = 0) $iCursorPosX = $iHtab Case $aParameters[0] == "E" ; CNL Move cursor down the indicated # of rows, to column 1. $iVtab += Number($aParameters[1]) + ($aParameters[1] = 0) $iCursorPosY = $iVtab $iHtab = 1 $iCursorPosX = $iHtab Case $aParameters[0] == "F" ; CPL Move cursor up the indicated # of rows, to column 1. $iVtab -= Number($aParameters[1]) - ($aParameters[1] = 0) $iCursorPosY = $iVtab $iHtab = 1 $iCursorPosX = $iHtab Case $aParameters[0] == "G" ; CHA Move cursor to indicated column in current row. $iHtab = Number($aParameters[1]) $iCursorPosX = $iHtab Case $aParameters[0] == "H" ; CUP Move cursor to the indicated row, column (origin at 1,1). ReDim $aParameters[3] ; mandatory 2 parameters $iVtab = Number($aParameters[1]) + ($aParameters[1] = 0) $iCursorPosY = $iVtab $iHtab = Number($aParameters[2]) + ($aParameters[2] = 0) $iCursorPosX = $iHtab Case $aParameters[0] == "J" ; ED Erase display (default: from cursor to end of display). ReDim $aParameters[2] ; mandatory 1 parameters Switch Number($aParameters[1]) Case 0 ; Pn=0: erases from active position to end of display. __Sub_Print(_StringReplay(" ", $iHwidth - $iHtab + 1), $iHtab, $iVtab, $iDefaultForeground, $iDefaultBackground) If $iVtab < $iVheight Then For $y = $iVtab + 1 To $iVheight __Sub_Print(_StringReplay(" ", $iHwidth), 1, $y, $iDefaultForeground, $iDefaultBackground) Next EndIf Case 1 ; Pn=1: erases from the beginning of display to active position. __Sub_Print(_StringReplay(" ", $iHtab), 1, $iVtab, $iDefaultForeground, $iDefaultBackground) If $iVtab > 1 Then For $y = 1 To $iVtab - 1 __Sub_Print(_StringReplay(" ", $iHwidth), 1, $y, $iDefaultForeground, $iDefaultBackground) Next EndIf Case 2 ; Pn=2: erases entire display and move cursor to the top-left. _TextMode_CLS() $iHtab = 1 $iVtab = 1 EndSwitch Case $aParameters[0] == "K" ; EL Erase line (default: from cursor to end of line). __Sub_Print(_StringReplay(" ", $iHwidth - $iHtab + 1), $iHtab, $iVtab, $iActiveFGColor, $iActiveBGColor) Case $aParameters[0] == "L" ; IL Insert the indicated # of blank lines. Case $aParameters[0] == "M" ; DL Delete the indicated # of lines. Case $aParameters[0] == "P" ; DCH Delete the indicated # of characters on current line. __Sub_Print(_StringReplay(" ", $aParameters[1]), $iHtab, $iVtab, $iActiveFGColor, $iActiveBGColor) Case $aParameters[0] == "X" ; ECH Erase the indicated # of characters on current line. __Sub_Print(_StringReplay(" ", $aParameters[1]), $iHtab, $iVtab, $iDefaultForeground, $iDefaultBackground) EndSelect ; ; is it a single Control character ? (http://jkorpela.fi/chars/c0.html) ElseIf StringLen($sANSI_Escape) = 1 And (AscW($sANSI_Escape) >= 0 And AscW($sANSI_Escape) <= 0x1F) Then ; and 1 = 2 ; ConsoleWrite("Debug: ctrl -> " & @TAB & "[" & Ascw($sANSI_Escape) & "]" & @TAB & "[" & Asc($sANSI_Escape) & "]" & @TAB & "<-----------------------------" & @CRLF) ; control character interpreter ; --------------------------------------------------------------------------------------- $aParameters[0] = $sANSI_Escape Select Case $aParameters[0] = Chr(7) ; Bell, rings the bell Beep(900, 150) Case $aParameters[0] = Chr(8) ; Backspace <-- $iHtab -= 1 $iCursorPosX = $iHtab Case $aParameters[0] = Chr(9) ; Horizontal tab ; (Historically tab stops were every 8th character) If $iHtab >= 0 Then $iHtab = $iHtab + (Mod($iHtab, $iTabStop) * -1) + $iTabStop Else $iHtab = $iHtab + (Mod(Abs($iHtab) - 1, $iTabStop) + 1) EndIf $iCursorPosX = $iHtab Case $aParameters[0] = Chr(10) ; Line Feed @LF (move cursor down by 1 line) $iVtab += 1 $iCursorPosY = $iVtab Case $aParameters[0] = Chr(11) ; Vertical tab (move cusros up by 1 line) $iVtab -= 1 $iCursorPosY = $iVtab Case $aParameters[0] = Chr(12) ; Form Feed ; Case $aParameters[0] = Chr(13) ; Carriage Return @CR (move cursor to the beginning of this line) $iHtab = 1 $iCursorPosX = $iHtab Case $aParameters[0] = Chr(24) ; backspace with deletion (Cancel) $iHtab -= 1 __Sub_Print(" ", $iHtab, $iVtab, $iActiveFGColor, $iActiveBGColor) $iCursorPosX = $iHtab Case $aParameters[0] = Chr(30) ; LF + a partial CR (Carriage Return stops below previous HTab) ; (custom private) $iVtab += 1 $iHtab = $iStartingHtab $iCursorPosX = $iHtab $iCursorPosY = $iVtab Case $aParameters[0] = Chr(31) ; move cursor to the right by 1 char --> ; ConsoleWrite(".") $iHtab += 1 $iCursorPosX = $iHtab EndSelect Else ; print the text ; ConsoleWrite("Debug: FG=" & $iActiveFGColor & @TAB & "BG=" & $iActiveBGColor & @CRLF) ; $aStringChunks[$iChunk] = StringReplace(StringStripCR(_StringToCodepage($aStringChunks[$iChunk], 437)), @LF, "") __Sub_Print(StringReplace($aStringChunks[$iChunk], ChrW(0), ""), $iHtab, $iVtab, $iForegroundColor, $iBackgroundColor) $iHtab = $iCursorPosX $iVtab = $iCursorPosY ; $iForegroundColor = $iDefaultForeground ; $iActiveFGColor ; ; $iBackgroundColor = $iDefaultBackground ; $iActiveBGColor ; EndIf Next EndFunc ;==>_TextMode_Print ; keep only the string portion that will fall into the the screen (parts outside the screen will be discarded) Func __Sub_Print($sString = "", $iHtab = $iCursorPosX, $iVtab = $iCursorPosY, $iForegroundColor = $iActiveFGColor, $iBackgroundColor = $iActiveBGColor) Local $iStringFullLen = StringLen($sString) Local $iStringLen = $iStringFullLen If Not $iStringLen Then Return ; no string to print Local $iStringEnd = $iHtab + $iStringLen - 1 $iCursorPosX = $iHtab + $iStringLen $iCursorPosY = $iVtab If _ ; check if all the string falls outside the printable area $iHtab > $iHwidth Or _ ; over the right edge $iVtab > $iVheight Or _ ; below the bottom $iVtab < 1 Or _ ; over the top edges $iStringEnd < 1 _ ; over the left edge Then Return ; adjust string if only a part has to be Printed If $iHtab < 1 Then ; remove the part outside on the left $sString = StringRight($sString, $iStringEnd) $iStringLen = StringLen($sString) $iHtab = 1 EndIf If $iStringEnd > $iHwidth Then ; removes the exceeding part on the right $sString = StringTrimRight($sString, $iStringEnd - $iHwidth) $iStringLen = StringLen($sString) EndIf Local $iAnchor = __GetAbsPos($iHtab, $iVtab) - 1 Local $iActive = $iAnchor + $iStringLen Switch _TextMode_Mode() Case $Normal ; print normal text on both layers __PokeText(0, $sString, $iAnchor, $iActive, $iForegroundColor, $iBackgroundColor) Case $Inverse ; switch foreground and background colors and print on both layers __PokeText(0, $sString, $iAnchor, $iActive, $iBackgroundColor, $iForegroundColor) Case $Blink ; to be continued .... __PokeText(0, $sString, $iAnchor, $iActive, $iForegroundColor, $iBackgroundColor) Case $Flash ; to be continued .... __PokeText(0, $sString, $iAnchor, $iActive, $iForegroundColor, $iBackgroundColor) Case Else EndSwitch EndFunc ;==>__Sub_Print ; Place string on the "screen" buffer Func __PokeText($iLayer, $sString, $iAnchor, $iActive, $iForeColor, $iBackColor) ; select the part of the screen buffer to be replaced with the incoming $sString _GUICtrlRichEdit_SetSel($hScreen[$iLayer], $iAnchor, $iActive, True) _GUICtrlRichEdit_ReplaceText($hScreen[$iLayer], $sString, False) ; test _GUICtrlRichEdit_SetSel($hScreen[$iLayer], $iAnchor, $iActive, True) ; test ; set styles for the incoming text _GUICtrlRichEdit_SetFont($hScreen[$iLayer], $iFontSize, $sFontName, $iCharSet) _GUICtrlRichEdit_SetCharColor($hScreen[$iLayer], __PeekColor($iForeColor)) _GUICtrlRichEdit_SetCharBkColor($hScreen[$iLayer], __PeekColor($iBackColor)) ; set or unset bold, italic, underline according if the rispective variable is set to true or false _GUICtrlRichEdit_SetCharAttributes($hScreen[$iLayer], $aAttribute[$Bold] & 'bo' & $aAttribute[$Italic] & 'it' & $aAttribute[$Underline] & 'un') ; place the text on the screen ;; _GUICtrlRichEdit_ReplaceText($hScreen[$iLayer], $sString, False) _GUICtrlRichEdit_Deselect($hScreen[$iLayer]) EndFunc ;==>__PokeText #cs Func _GUICtrlRichEdit_AppendTextColor($hWnd, $sText, $iColor) Local $iLength = _GUICtrlRichEdit_GetTextLength($hWnd, True, True) Local $iCp = _GUICtrlRichEdit_GetCharPosOfNextWord($hWnd, $iLength) _GUICtrlRichEdit_AppendText($hWnd, $sText) _GUICtrlRichEdit_SetSel($hWnd, $iCp-1, $iLength + StringLen($sText)) _GUICtrlRichEdit_SetCharColor($hWnd, $iColor) _GuiCtrlRichEdit_Deselect($hWnd) EndFunc #ce Func _PushCursor($sAction = "Push") Local Static $iCursorPushX = $iCursorPosX Local Static $iCursorPushY = $iCursorPosY If $sAction = "Push" Then $iCursorPushX = $iCursorPosX $iCursorPushY = $iCursorPosY EndIf Local $aXY[2] = [$iCursorPushX, $iCursorPushY] Return $aXY EndFunc ;==>_PushCursor Func _PullCursor() Local $aXY = _PushCursor("Pull") $iCursorPosX = $aXY[0] $iCursorPosY = $aXY[1] EndFunc ;==>_PullCursor ; if you pass a number 0-15 it returns a predefined color from the $aColor[] array. ; if the number is > 15 and <= 0xFFFFFF it returns the same number, while if the passed ; number is out of range it return 0 ($Black)and sets @error Func __PeekColor($iColor) $iColor = Number($iColor) If $iColor >= 0 And $iColor < UBound($aColor) Then Return $aColor[$iColor] ; predefined colors ElseIf $iColor >= UBound($aColor) And $iColor <= 0xFFFFFF Then Return $iColor ; value is <= 0xFFFFFF Else Return SetError(1, 0, 0) ; if out of range return Black and set error EndIf EndFunc ;==>__PeekColor ; clear the screen (fill screen buffer with spaces) ; (for 'crazy' effects you could also select another char instead of the space and custom colors) Func _TextMode_CLS($sFillChr = " ", $iForegroundColor = $iActiveFGColor, $iBackgroundColor = $iActiveBGColor) ; clear the screen ; fill screen with white spaces (screen buffer) _GUICtrlRichEdit_SetText($hScreen[0], _StringReplay(_StringReplay($sFillChr, $iHwidth) & @CRLF, $iVheight - 1) & _StringReplay($sFillChr, $iHwidth)) _GUICtrlRichEdit_SetSel($hScreen[0], 0, -1, True) ; select whole screen ; set parameters _GUICtrlRichEdit_SetFont($hScreen[0], $iFontSize, $sFontName, $iCharSet) ; Set Font _GUICtrlRichEdit_SetCharColor($hScreen[0], __PeekColor($iForegroundColor)) ; Set Foreground default color _GUICtrlRichEdit_SetCharBkColor($hScreen[0], __PeekColor($iBackgroundColor)) ; Set Background default color _GUICtrlRichEdit_SetSel($hScreen[0], 0, 0, False) ; set cursor to home $iCursorPosX = 1 $iCursorPosY = 1 EndFunc ;==>_TextMode_CLS Func _TextMode_SetDefaultColors($iForeColor = $iDefaultForeground, $iBackColor = $iDefaultBackground) If $iForeColor = Default Then $iForeColor = $iDefaultForeground If $iForeColor < $Black Or $iForeColor > $BrightWhite Or $iForeColor = "" Then $iForeColor = $iActiveFGColor If $iBackColor = Default Then $iBackColor = $iDefaultBackground If $iBackColor < $Black Or $iBackColor > $BrightWhite Or $iBackColor = "" Then $iBackColor = $iActiveBGColor $iActiveFGColor = $iForeColor $iActiveBGColor = $iBackColor Local $aDefaultColors = [$iActiveFGColor, $iActiveBGColor] Return $aDefaultColors EndFunc ;==>_TextMode_SetDefaultColors Func _TextMode_SetActiveForeColor($iForeColor = $iActiveFGColor) If $iForeColor = Default Then $iForeColor = $iDefaultForeground If $iForeColor < $Black Or $iForeColor > $BrightWhite Then $iForeColor = $iActiveFGColor $iActiveFGColor = $iForeColor Return $iActiveFGColor EndFunc ;==>_TextMode_SetActiveForeColor Func _TextMode_SetActiveBackColor($iBackColor = $iActiveBGColor) If $iBackColor = Default Then $iBackColor = $iDefaultBackground If $iBackColor < $Black Or $iBackColor > $BrightWhite Then $iBackColor = $iActiveBGColor $iActiveBGColor = $iBackColor Return $iActiveBGColor EndFunc ;==>_TextMode_SetActiveBackColor ; Get / Set active TextMode effect Func _TextMode_Mode($iMode = -1) Local Static $iTextMode If $iMode >= $Normal And $iMode <= $Flash Then $iTextMode = $iMode Return $iTextMode EndFunc ;==>_TextMode_Mode ; set Normal or Inverse or Blink or Flash Func _TextMode_SetMode($iMode = $Normal) If $iMode >= $Normal And $iMode <= $Flash Then Return _TextMode_Mode($iMode) Else Return _TextMode_Mode() EndIf EndFunc ;==>_TextMode_SetMode ; check if is within color ranges Func _IsRGB($iColor) Return $iColor >= 0x000000 And $iColor <= 0xFFFFFF EndFunc ;==>_IsRGB ; move the TextMode GUI to Func _TextMode_GUIMoveTo($iX = 5, $iY = 5, $_hGUI = $_hVintageGui) If IsHWnd($_hGUI) Then WinMove($_hGUI, "", $iX, $iY) EndFunc ;==>_TextMode_GUIMoveTo Func _EndANSI() _GUICtrlRichEdit_Destroy($hScreen[0]) Exit EndFunc ;==>_EndANSI ; returns one or more chars replicated n times ; Example: ConsoleWrite(_StringReplay('*', 5) & @CRLF) Func _StringReplay($sChars = "", $iRepeats = 0) $sChars = String($sChars) $iRepeats = Int(Abs(Number($iRepeats))) Return StringReplace(StringFormat('%' & $iRepeats & 's', ""), " ", $sChars) EndFunc ;==>_StringReplay Edited April 10, 2018 by Chimp Danyfirex 1 Chimp small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now