Author Topic: Virtual Terminal Escape Sequences (Windows 10+)  (Read 1654 times)

0 Members and 1 Guest are viewing this topic.

Offline SpriggsySpriggs

  • Forum Resident
  • Posts: 1145
  • Larger than life
    • GitHub
Virtual Terminal Escape Sequences (Windows 10+)
« on: August 17, 2021, 04:57:40 pm »
Happened across this MSDN page on using Virtual Terminal escape sequences and thought it would be neat to try in QB64. So, I converted the example on the page. Perhaps someone would be interested enough to make something more with it.

The code:
Code: QB64: [Select]
  1.  
  2. Type COORD
  3.     As Integer X, Y
  4.  
  5. Type SMALL_RECT
  6.     As Integer Left, Top, Right, Bottom
  7.  
  8. Type CONSOLE_SCREEN_BUFFER_INFO
  9.     As COORD dwSize, dwCursorPosition
  10.     As _Unsigned Integer wAttributes
  11.     As SMALL_RECT srWindow
  12.     As COORD dwMaximumWindowSize
  13.  
  14. Const INVALID_HANDLE_VALUE = -1
  15.  
  16. Const STD_OUTPUT_HANDLE = -11
  17. Const ENABLE_VIRTUAL_TERMINAL_PROCESSING = &H0004
  18.  
  19. Const ESC = ""
  20. Const CSI = "["
  21.  
  22.     Function GetStdHandle%& (ByVal nStdHandle As _Unsigned Long)
  23.     Sub GetConsoleMode (ByVal hConsoleHandle As _Offset, Byval lpMode As _Offset)
  24.     Sub SetConsoleMode (ByVal hConsoleHandle As _Offset, Byval dwMode As _Unsigned Long)
  25.     Sub GetConsoleScreenBufferInfo (ByVal hConsoleOutput As _Offset, Byval lpConsoleScreenBufferInfo As _Offset)
  26.  
  27. EnableVTMode
  28. Dim As _Offset hOut: hOut = GetStdHandle(STD_OUTPUT_HANDLE)
  29. If hOut = INVALID_HANDLE_VALUE Then End
  30. Dim As CONSOLE_SCREEN_BUFFER_INFO ScreenBufferInfo
  31. GetConsoleScreenBufferInfo hOut, _Offset(ScreenBufferInfo)
  32. Dim As COORD Size
  33. Size.X = ScreenBufferInfo.srWindow.Right - ScreenBufferInfo.srWindow.Left + 1
  34. Size.Y = ScreenBufferInfo.srWindow.Bottom - ScreenBufferInfo.srWindow.Top + 1
  35.  
  36. 'Enter the alternate buffer
  37. Print CSI; "?1049h";
  38.  
  39. 'Clear screen, tab stops, set, stop at columns 16, 32
  40. Print CSI; "1;1H";
  41. Print CSI; "2J";
  42.  
  43. Dim As Long iNumTabStops: iNumTabStops = 4 '(0, 20, 40, width)
  44. Print CSI; "3g"; 'Clear all tab stops
  45. Print CSI; "1;20H"; 'Move to column 20
  46. Print ESC; "H"; 'Set a tab stop
  47.  
  48. Print CSI; "1;40H"; 'Move to column 40
  49. Print ESC; "H"; 'Set a tab stop
  50.  
  51. 'Set scrolling margins to 3, h-2
  52. Print CSI; "3;"; LTrim$(Str$(Size.Y - 2)) + "r";
  53. Dim As Long iNumLines: iNumLines = Size.Y - 4
  54.  
  55. Print CSI; "1;1H";
  56. Print CSI; "102;30m";
  57. Print "Windows 10 Anniversary Update - VT Example";
  58. Print CSI; "0m";
  59.  
  60. 'Print a top border - Yellow
  61. Print CSI; "2;1H";
  62. PrintHorizontalBorder Size, -1
  63.  
  64. 'Print a bottom border
  65. Print CSI; LTrim$(Str$(Size.Y - 1)); "1H";
  66. PrintHorizontalBorder Size, 0
  67.  
  68. 'Draw columns
  69. Print CSI; "3;1H";
  70. Dim As Long lin
  71. For lin = 0 To (iNumLines * iNumTabStops) - 1
  72.     PrintVerticalBorder
  73.     If lin + 1 <> iNumLines * iNumTabStops Then Print Chr$(9);
  74.  
  75. PrintStatusLine "Press any key to see text printed between tab stops.", Size
  76.  
  77. 'Fill columns with output
  78. Print CSI; "3;1H";
  79. For lin = 0 To iNumLines - 1
  80.     Dim As Long tabs
  81.     For tabs = 0 To iNumTabStops - 2
  82.         PrintVerticalBorder
  83.         Print "line="; LTrim$(Str$(lin));
  84.         Print Chr$(9);
  85.     Next
  86.     PrintVerticalBorder
  87.     If lin + 1 <> iNumLines Then Print Chr$(9);
  88.  
  89. PrintStatusLine "Press any key to demonstrate scroll margins", Size
  90.  
  91. Print CSI; "3;1H";
  92. For lin = 0 To (iNumLines * 2) - 1
  93.     Print CSI; "K";
  94.     For tabs = 0 To iNumTabStops - 2
  95.         PrintVerticalBorder
  96.         Print "line="; LTrim$(Str$(lin));
  97.         Print Chr$(9);
  98.     Next
  99.     PrintVerticalBorder
  100.     If lin + 1 <> iNumLines * 2 Then
  101.         Print
  102.     End If
  103.  
  104. PrintStatusLine "Press any key to exit", Size
  105.  
  106. Print CSI; "?1049l";
  107.  
  108. Sub EnableVTMode ()
  109.     Dim As _Offset hOut
  110.     hOut = GetStdHandle(STD_OUTPUT_HANDLE)
  111.     Dim As _Unsigned Long dwMode
  112.     GetConsoleMode hOut, _Offset(dwMode)
  113.     dwMode = dwMode Or ENABLE_VIRTUAL_TERMINAL_PROCESSING
  114.     SetConsoleMode hOut, dwMode
  115.  
  116. Sub PrintVerticalBorder ()
  117.     Print ESC; "(0";
  118.     Print CSI; "104;93m";
  119.     Print "x";
  120.     Print CSI; "0m";
  121.     Print ESC; "(B";
  122.  
  123. Sub PrintHorizontalBorder (Size As COORD, fIsTop As _Byte)
  124.     Print ESC; "(0";
  125.     Print CSI; "104;93m";
  126.     If fIsTop Then Print "l"; Else Print "m";
  127.     Dim As Long i
  128.     For i = 1 To Size.X - 2
  129.         Print "q";
  130.     Next
  131.     If fIsTop Then Print "k"; Else Print "j";
  132.     Print CSI; "0m";
  133.     Print ESC; "(B";
  134.  
  135. Sub PrintStatusLine (pszMessage As String, Size As COORD)
  136.     Print CSI; LTrim$(Str$(Size.Y)); "1H";
  137.     Print CSI; "K";
  138.     Print pszMessage;

A screenshot of the output:
 
Screenshot 2021-08-17 165649.png
Shuwatch!