From 0e52f6d63b75b52fbab337cce6e2e8c50f47ad89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Minisini?= Date: Sat, 26 Mar 2016 10:08:12 +0000 Subject: [PATCH] [GB.FORM.TERMINAL] * NEW: A icon for TerminalView. * NEW: Initial VT100 terminal filter. * NEW: TerminalView: Exec() and Shell() are two new methods to run a process inside the virtual terminal. Process input management is not implemented, and process output support is rudimentary. git-svn-id: svn://localhost/gambas/trunk@7667 867c0c6c-44f3-4631-809d-bfa615b0a4ec --- .../.hidden/control/scrollview.png | Bin 0 -> 250 bytes .../.hidden/control/terminalview.png | Bin 0 -> 507 bytes .../.src/TerminalView/FTestTerminalView.class | 25 +- .../.src/TerminalView/FTestTerminalView.form | 2 +- .../.src/TerminalView/TerminalFilter.class | 14 ++ .../TerminalView/TerminalFilter_VT100.class | 115 ++++++++++ .../.src/TerminalView/TerminalView.class | 217 ++++++++++++++---- 7 files changed, 304 insertions(+), 69 deletions(-) create mode 100644 comp/src/gb.form.terminal/.hidden/control/scrollview.png create mode 100644 comp/src/gb.form.terminal/.hidden/control/terminalview.png create mode 100644 comp/src/gb.form.terminal/.src/TerminalView/TerminalFilter.class create mode 100644 comp/src/gb.form.terminal/.src/TerminalView/TerminalFilter_VT100.class diff --git a/comp/src/gb.form.terminal/.hidden/control/scrollview.png b/comp/src/gb.form.terminal/.hidden/control/scrollview.png new file mode 100644 index 0000000000000000000000000000000000000000..4c165354d723fc62203e4d7f15aab0ed854e6a30 GIT binary patch literal 250 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5D7ePc z#W5tJ_3iYHyv&L`uKSh479=pbd7Ng-G;+OWkUZyz(UzNsMV&3qs_uH?r|HKewV&(G zA9WqY+EbSILrWPS7*2C@;oshNf5y+7#=fDY)#8HjUXd~k_pSfAjBZ?4Ooa+Df!~K`m>H?p>-`Wy zyZ{;zmhbzoilRKLLWq|}qoEmw5oJEE>*}^`4^==j3nMuy?cwmj5uDFwR;v~LexE|2fMr>zYM?b706?Wu!Llr5S!OsK(&==f z13W!Fkxr*sEEcTSYv%JgrBW#rKww{!$s~^B;5ZJ3VGxhUF-2xBW&ods6LjeSKKnTHRv*CC=lFQ}TZnvR?!yjJ4%jH6|*?gb3S}m^EYv9OaGG79G zdbjTPJGa~IeLfnEm`cZGhj)^E^Dy`%=(H^>6=%55NQP06YNy1wi$E|J8L} xT?i3r@P5AsII4=GJlnQClx10uQ~(a}^9{Cxl{cNbIVu1E002ovPDHLkV1iD?+8_V` literal 0 HcmV?d00001 diff --git a/comp/src/gb.form.terminal/.src/TerminalView/FTestTerminalView.class b/comp/src/gb.form.terminal/.src/TerminalView/FTestTerminalView.class index a1f680fd2..e41166a50 100644 --- a/comp/src/gb.form.terminal/.src/TerminalView/FTestTerminalView.class +++ b/comp/src/gb.form.terminal/.src/TerminalView/FTestTerminalView.class @@ -1,14 +1,8 @@ ' Gambas class file -Private $hProcess As Process - - - Public Sub TextBox1_Activate() - If $hProcess Then Return - - $hProcess = Shell TextBox1.Text For Input Output As "Process" + TerminalView1.Exec(Split(TextBox1.Text, " ", Chr$(34))) End @@ -25,23 +19,6 @@ Public Sub Button1_Click() End -Public Sub Process_Read() - - Dim sData As String - - sData = Read #$hProcess, Lof($hProcess) - TerminalView1.Print(sData) - TerminalView1.EnsureVisible - -End - -Public Sub Process_Kill() - - $hProcess = Null - -End - - Public Sub Form_Open() TextBox1.SetFocus diff --git a/comp/src/gb.form.terminal/.src/TerminalView/FTestTerminalView.form b/comp/src/gb.form.terminal/.src/TerminalView/FTestTerminalView.form index 8722d853e..5f90fa870 100644 --- a/comp/src/gb.form.terminal/.src/TerminalView/FTestTerminalView.form +++ b/comp/src/gb.form.terminal/.src/TerminalView/FTestTerminalView.form @@ -1,7 +1,7 @@ # Gambas Form File 3.0 { Form Form - MoveScaled(0,0,87,64) + MoveScaled(0,0,125,64) Arrangement = Arrange.Vertical { TerminalView1 TerminalView MoveScaled(2,1,59,52) diff --git a/comp/src/gb.form.terminal/.src/TerminalView/TerminalFilter.class b/comp/src/gb.form.terminal/.src/TerminalView/TerminalFilter.class new file mode 100644 index 000000000..7ef27078b --- /dev/null +++ b/comp/src/gb.form.terminal/.src/TerminalView/TerminalFilter.class @@ -0,0 +1,14 @@ +' Gambas class file + +Public Sub Clear() + +End + +Public Sub OutputTo((hView) As TerminalView, (sData) As String) + +End + +Public Sub InputTo((hProcess) As Process, (iKeyCode) As Integer, (sKeyText) As String) + +End + diff --git a/comp/src/gb.form.terminal/.src/TerminalView/TerminalFilter_VT100.class b/comp/src/gb.form.terminal/.src/TerminalView/TerminalFilter_VT100.class new file mode 100644 index 000000000..59770b38d --- /dev/null +++ b/comp/src/gb.form.terminal/.src/TerminalView/TerminalFilter_VT100.class @@ -0,0 +1,115 @@ +' Gambas class file + +Inherits TerminalFilter + +Private $sLeft As String +Private $X As Integer +Private $Y As Integer + +Public Sub OutputTo(hView As TerminalView, sData As String) + + Dim iPos As Integer + Dim iPos2 As Integer + Dim iCode As Integer + + If $sLeft Then sData = $sLeft & sData + + Do + + Inc iPos + + iPos2 = InStr(sData, Chr$(27), iPos) + If iPos2 = 0 Then + hView.Print(Mid$(sData, iPos)) + Break + Endif + + hView.Print(Mid$(sData, iPos, iPos2 - iPos)) + + iPos = iPos2 + Inc iPos + If Mid$(sData, iPos, 1) = "[" Then + Inc iPos + Endif + + Do + + If iPos > Len(sData) Then + $sLeft = Mid$(sData, iPos2) + Return + Endif + + iCode = Asc(Mid$(sData, iPos, 1)) + If iCode >= 64 And If iCode <= 126 Then Break + + Inc iPos + + Loop + + Escape(hView, Mid$(sData, iPos2 + 1, iPos - iPos2)) + + Loop + +End + +' Escape sequence without the initial 27 character. + +Private Sub Escape(hView As TerminalView, sStr As String) + + Dim Y As Integer + Dim X As Integer + Dim aArg As String[] + + Select Case Left(sStr) + + Case "7" ' Save cursor + + $X = hView.Column + $Y = hView.Line + + Case "8" ' Restore cursor + + hView.CursorGoto($X, $Y) + + Case "[" + + Select Case Right(sStr) + + Case "H", "f" ' Cursor goto + + GoSub GET_ARGS + + If aArg Then + Try Y = CInt(aArg[0]) - 1 + Try X = CInt(aArg[1]) - 1 + Endif + hView.CursorGoto(X, Y) + + Case "K" ' Erase end of line + + hView.EraseEndOfLine + + Case "s" ' Save cursor + + $X = hView.Column + $Y = hView.Line + + Case "u" ' Restore cursor + + hView.CursorGoto($X, $Y) + + End Select + + End Select + + Return + +GET_ARGS: + + If Len(sStr) > 2 Then + aArg = Split(Mid$(sStr, 2, -1), ";") + Else + aArg = Null + Endif + +End diff --git a/comp/src/gb.form.terminal/.src/TerminalView/TerminalView.class b/comp/src/gb.form.terminal/.src/TerminalView/TerminalView.class index 2a489de1b..ce5578e14 100644 --- a/comp/src/gb.form.terminal/.src/TerminalView/TerminalView.class +++ b/comp/src/gb.form.terminal/.src/TerminalView/TerminalView.class @@ -6,6 +6,9 @@ Export Public Const _Properties As String = "*,Border=True,ScrollBar=True,Limit" Public Const _DrawWith As String = "-" +Public Const _Group As String = "View" + +Event Kill Property Border As Boolean Property ScrollBar As Boolean @@ -14,6 +17,8 @@ Property Foreground As Integer Property Read Column As Integer Property Read Line As Integer Property Limit As Integer +Property Read Screen As Rect +Property Type As String Static Private $aColor As Integer[] = [Color.Black, Color.Red, Color.Green, Color.Yellow, Color.Blue, Color.Magenta, Color.Cyan, Color.White] Static Private $sControlChar As String @@ -27,7 +32,10 @@ Private $hFont As Font Private $LH As Integer Private $iAscent As Integer Private $CW As Integer -Private $WMax As Integer + +' Screen size +Private $W As Integer +Private $H As Integer Private $X As Integer Private $Y As Integer @@ -42,6 +50,9 @@ Private $iLimit As Integer Private $hCursorTimer As Timer Private $bHideCursor As Boolean Private $hMouseTimer As Timer +Private $hProcess As Process +Private $hFilter As TerminalFilter +Private $sType As String Public Sub _new() @@ -69,6 +80,8 @@ Public Sub _new() Me.Proxy = $hView + Me.Type = "VT100" + CalcSize End @@ -100,8 +113,10 @@ Private Sub CalcWidth() $hView.ResizeContents($hView.ClientW, Max($hView.ClientH, $aLine.Count * $LH)) W = $hView.ClientW - If $hView.ScrollH > $hView.ClientH Then W -= Style.ScrollbarSize + Style.ScrollbarSpacing - $WMax = Max(1, CInt(W / $CW)) + If $hView.ScrollH <= $hView.ClientH Then W -= Style.ScrollbarSize + Style.ScrollbarSpacing + $W = Max(1, CInt(W / $CW)) + $H = Max(1, $hView.ClientH \ $LH) + ' TODO: How to tell running process about terminal size change? End @@ -233,7 +248,7 @@ DRAW_TEXT: Paint.DrawText(sText, X + 1, Y + $iAscent) If hAttr.Bold Then Paint.DrawText(sText, X + 2, Y + $iAscent) Endif - If hAttr.Underline Then Paint.FillRect(X, Y + $LH - 1, L * $CW, 1, Paint.Background) + If hAttr.Underline Then Paint.FillRect(X, Y + $LH - 1, iLen * $CW, 1, Paint.Background) X += iLen * $CW P = I Return @@ -316,6 +331,19 @@ Private Sub GetLine(Y As Integer) As CTerminalLine End +Private Sub ClearLine(Y As Integer) + + Dim hLine As CTerminalLine + + If Y > $aLine.Max Then Return + hLine = $aLine[Y] + hLine.Text = "" + hLine.Length = 0 + hLine.Attr.Clear + +End + + Private Sub Insert(sText As String) Dim hLine As CTerminalLine @@ -323,8 +351,8 @@ Private Sub Insert(sText As String) If iLen = 0 Then Return - If ($X + iLen) > $WMax Then - iLen = Max(0, $WMax - $X) + If ($X + iLen) > $W Then + iLen = Max(0, $W - $X) If iLen Then Insert(String.Left(sText, iLen)) sText = String.Mid$(sText, iLen + 1) @@ -386,49 +414,25 @@ Public Sub Print(sText As String) End -Public Sub NewLine() +Private Sub NewLine() Goto(0, $Y + 1) End -Public Sub Tab() +Private Sub Tab() Goto($X + 8 - $X Mod 8, $Y) End -Public Sub CursorUp() - - Goto($X, $Y - 1) - -End - -Public Sub CursorDown() - - Goto($X, $Y + 1) - -End - -Public Sub CursorLeft() - - Goto($X - 1, $Y) - -End - -Public Sub CursorRight() - - Goto($X + 1, $Y) - -End - Public Sub Goto(X As Integer, Y As Integer) - If X >= $WMax Then + If X >= $W Then X = 0 Inc Y Else If X < 0 Then - X = $WMax - 1 + X = $W - 1 Dec Y Endif @@ -440,6 +444,7 @@ Public Sub Goto(X As Integer, Y As Integer) End + Private Function Border_Read() As Boolean Return $hPanel.Border <> Border.None @@ -498,7 +503,7 @@ Private Sub GotoMouse() X = (Mouse.ScreenX - $hView.ScreenX) \ $CW Y = (Mouse.ScreenY - $hView.ScreenY + $hView.ScrollY) \ $LH - Goto(Max(0, Min($WMax - 1, X)), Max(0, Min(Max($aLine.Max, $hView.ClientH \ $LH - 1), Y))) + Goto(Max(0, Min($W - 1, X)), Max(0, Min(Max($aLine.Max, $hView.ClientH \ $LH - 1), Y))) EnsureVisible End @@ -598,6 +603,86 @@ Public Sub CursorTimer_Timer() End +Public Sub MouseTimer_Timer() + + GotoMouse + $X2 = $X + $Y2 = $Y + EnsureVisible + +End + +Private Sub ScreenTop() As Integer + + Return Max(0, $aLine.Count - $H) + +End + + +Private Function Screen_Read() As Rect + + Return Rect(0, ScreenTop(), $W, $H) + +End + +Private Function Type_Read() As String + + Return $sType + +End + +Private Sub Type_Write(Value As String) + + Try $hFilter = Object.New("TerminalFilter_" & Value) + If Error Then Error.Raise("Unknown terminal type: " & Value) + $sType = UCase(Value) + +End + +' Terminal VT100 commands + +Public Sub CursorGoto(X As Integer, Y As Integer) + + If X >= $W Then + X = 0 + Inc Y + Else If X < 0 Then + X = $W - 1 + Dec Y + Endif + + If Y < 0 Then Y = 0 + + $X = X + $Y = Y + ScreenTop() + Refresh + +End + +Public Sub CursorUp() + + CursorGoto($X, $Y - 1) + +End + +Public Sub CursorDown() + + CursorGoto($X, $Y + 1) + +End + +Public Sub CursorLeft() + + CursorGoto($X - 1, $Y) + +End + +Public Sub CursorRight() + + CursorGoto($X + 1, $Y) + +End + Public Sub EraseEndOfLine() Dim hLine As CTerminalLine @@ -637,9 +722,27 @@ Public Sub EraseLine() End +Public Sub EraseScreen() + + Dim Y As Integer + + For Y = ScreenTop() To $aLine.Max + ClearLine(Y) + Next + + Refresh + CursorGoto(0, 0) + +End + Public Sub EraseDown() - $aLine.Fill(Null, $Y, -1) + Dim Y As Integer + + For Y = Max(ScreenTop(), $Y) To $aLine.Max + ClearLine(Y) + Next + Refresh End @@ -647,23 +750,49 @@ End Public Sub EraseUp() - $aLine.Fill(Null, 0, $Y) + Dim Y As Integer + + For Y = ScreenTop() To Max(ScreenTop() - 1, $Y) + ClearLine(Y) + Next + Refresh End -Public Sub EraseScreen() +' Running a command + +Public Sub Exec(aCommand As String[]) As Process + + If $hProcess Then Return - $aLine.Fill(Null) - Refresh + $hProcess = Exec aCommand For Input Output As "Process" End -Public Sub MouseTimer_Timer() +Public Sub Shell(sCommand As String) As Process + + If $hProcess Then Return - GotoMouse - $X2 = $X - $Y2 = $Y + $hProcess = Shell sCommand For Input Output As "Process" + +End + +Public Sub Process_Kill() + + $hProcess = Null + Raise Kill + +End + +Public Sub Process_Read() + + Dim sData As String + + sData = Read #$hProcess, Lof($hProcess) + $hFilter.OutputTo(Me, sData) EnsureVisible End + +