[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
This commit is contained in:
Benoît Minisini 2016-03-26 10:08:12 +00:00
parent 5d0151fe32
commit 0e52f6d63b
7 changed files with 304 additions and 69 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 250 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 507 B

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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