TerminalView: The last lines are now automatically relayouted when the width of the terminal changes.
[GB.FORM.TERMINAL] * NEW: TerminalView: The last lines are now automatically relayouted when the width of the terminal changes. * BUG: TerminalView: The padding is now correctly taking into account when computing the terminal character width.
This commit is contained in:
parent
e4da796e5b
commit
a8b9bf14b6
3 changed files with 212 additions and 8 deletions
|
@ -1,12 +1,14 @@
|
||||||
' Gambas class file
|
' Gambas class file
|
||||||
|
|
||||||
Fast
|
Fast Unsafe
|
||||||
|
|
||||||
Public Text As String
|
Public Text As String
|
||||||
Public Length As Integer
|
Public Length As Integer
|
||||||
|
|
||||||
Private Attr As New Integer[]
|
Private Attr As New Integer[]
|
||||||
|
|
||||||
|
Public NewLine As Boolean
|
||||||
|
|
||||||
Private $bCompressed As Boolean
|
Private $bCompressed As Boolean
|
||||||
|
|
||||||
Private Enum FLAG_BG, FLAG_FG, FLAG_BOLD, FLAG_DIM, FLAG_REV, FLAG_UND, FLAG_BLK
|
Private Enum FLAG_BG, FLAG_FG, FLAG_BOLD, FLAG_DIM, FLAG_REV, FLAG_UND, FLAG_BLK
|
||||||
|
@ -35,7 +37,7 @@ Private Sub Uncompress()
|
||||||
|
|
||||||
End
|
End
|
||||||
|
|
||||||
Private Sub Compress()
|
Private Sub Compress(bFull As Boolean)
|
||||||
|
|
||||||
Dim I As Integer
|
Dim I As Integer
|
||||||
Dim iAttr As Integer
|
Dim iAttr As Integer
|
||||||
|
@ -59,8 +61,13 @@ Private Sub Compress()
|
||||||
|
|
||||||
If iCount Then aAttr.Add(iOldAttr Or Lsl(iCount - 1, 8))
|
If iCount Then aAttr.Add(iOldAttr Or Lsl(iCount - 1, 8))
|
||||||
|
|
||||||
Attr = aAttr
|
If bFull And If Attr.Count < Length Then
|
||||||
|
iCount = Length - Attr.Count
|
||||||
|
aAttr.Add(Lsl(iCount - 1, 8))
|
||||||
|
Endif
|
||||||
|
|
||||||
$bCompressed = True
|
$bCompressed = True
|
||||||
|
Attr = aAttr
|
||||||
|
|
||||||
End
|
End
|
||||||
|
|
||||||
|
@ -128,16 +135,72 @@ End
|
||||||
|
|
||||||
Public Sub GetAttr() As Integer[]
|
Public Sub GetAttr() As Integer[]
|
||||||
|
|
||||||
If Not $bCompressed Then Compress()
|
If Not $bCompressed Then Compress(False)
|
||||||
Return Attr
|
Return Attr
|
||||||
|
|
||||||
End
|
End
|
||||||
|
|
||||||
|
Public Sub GetFullAttr() As Integer[]
|
||||||
|
|
||||||
|
If $bCompressed Then Uncompress()
|
||||||
|
Compress(True)
|
||||||
|
Return Attr
|
||||||
|
|
||||||
|
End
|
||||||
|
|
||||||
|
Public Sub InitAttr(aInit As Integer[])
|
||||||
|
|
||||||
|
Dim L As Integer
|
||||||
|
Dim I As Integer
|
||||||
|
Dim iAttr As Integer
|
||||||
|
Dim iCount As Integer
|
||||||
|
Dim C As Integer
|
||||||
|
Dim aAttr As Integer[]
|
||||||
|
Dim aTemp As Integer[]
|
||||||
|
Dim N As Integer
|
||||||
|
|
||||||
|
L = Length
|
||||||
|
aAttr = New Integer[]
|
||||||
|
|
||||||
|
For I = 0 To aInit.Max
|
||||||
|
|
||||||
|
If L = 0 Then Break
|
||||||
|
|
||||||
|
iAttr = aInit[0]
|
||||||
|
iCount = (Lsr(iAttr, 8) And 255) + 1
|
||||||
|
C = Min(L, iCount)
|
||||||
|
iAttr = iAttr And &HFFFF00FF
|
||||||
|
aTemp = New Integer[C]
|
||||||
|
aTemp.Fill(iAttr)
|
||||||
|
aAttr.Insert(aTemp)
|
||||||
|
|
||||||
|
L -= C
|
||||||
|
If C = iCount Then
|
||||||
|
aInit.Remove(0)
|
||||||
|
Else
|
||||||
|
iCount -= C
|
||||||
|
aInit[0] = iAttr Or Lsl(iCount - 1, 8)
|
||||||
|
Endif
|
||||||
|
|
||||||
|
Next
|
||||||
|
|
||||||
|
For I = aAttr.Max DownTo 0
|
||||||
|
If aAttr[I] Then Break
|
||||||
|
Next
|
||||||
|
|
||||||
|
If I < aAttr.Max Then aAttr.Remove(I + 1, -1)
|
||||||
|
|
||||||
|
Attr = aAttr
|
||||||
|
$bCompressed = False
|
||||||
|
|
||||||
|
End
|
||||||
|
|
||||||
|
|
||||||
Public Sub Clear()
|
Public Sub Clear()
|
||||||
|
|
||||||
Text = ""
|
Text = ""
|
||||||
Length = 0
|
Length = 0
|
||||||
|
NewLine = False
|
||||||
Attr.Clear
|
Attr.Clear
|
||||||
$bCompressed = False
|
$bCompressed = False
|
||||||
|
|
||||||
|
|
|
@ -91,6 +91,9 @@ Public Lines As New CTerminalLine[]
|
||||||
Private $W As Integer
|
Private $W As Integer
|
||||||
Private $H As Integer
|
Private $H As Integer
|
||||||
|
|
||||||
|
' If a line had to be broken
|
||||||
|
Private $bBrokenLine As Boolean
|
||||||
|
|
||||||
' Cursor position
|
' Cursor position
|
||||||
Private $X As Integer
|
Private $X As Integer
|
||||||
Private $Y As Integer
|
Private $Y As Integer
|
||||||
|
@ -144,18 +147,127 @@ End
|
||||||
Public Sub Clear()
|
Public Sub Clear()
|
||||||
|
|
||||||
Lines.Clear
|
Lines.Clear
|
||||||
|
$bBrokenLine = False
|
||||||
GetView()._UpdateSize
|
GetView()._UpdateSize
|
||||||
Goto(0, 0)
|
Goto(0, 0)
|
||||||
|
|
||||||
End
|
End
|
||||||
|
|
||||||
|
Fast Private Sub Relayout(W As Integer)
|
||||||
|
|
||||||
|
Dim aAttr As Integer[]
|
||||||
|
Dim aLines As String[]
|
||||||
|
Dim I As Integer
|
||||||
|
Dim hLine As CTerminalLine
|
||||||
|
Dim sText As String
|
||||||
|
Dim SY As Integer
|
||||||
|
Dim L As Integer
|
||||||
|
Dim sLine As String
|
||||||
|
Dim hView As TerminalView
|
||||||
|
Dim D As Integer
|
||||||
|
|
||||||
|
hView = GetView()
|
||||||
|
|
||||||
|
'fTimer = Timer
|
||||||
|
aAttr = New Integer[]
|
||||||
|
aLines = New String[]
|
||||||
|
|
||||||
|
D = Lines.Count - 10000
|
||||||
|
If D < 0 Then D = 0
|
||||||
|
|
||||||
|
SY = -1
|
||||||
|
|
||||||
|
For I = D To Lines.Max
|
||||||
|
If I = $Y Then SY = aLines.Count
|
||||||
|
hLine = Lines[I]
|
||||||
|
If hLine Then
|
||||||
|
sText &= hLine.Text
|
||||||
|
aAttr.Insert(hLine.GetFullAttr())
|
||||||
|
If hLine.NewLine Then
|
||||||
|
aLines.Add(sText)
|
||||||
|
sText = ""
|
||||||
|
'aAttr.Insert(&H00000100)
|
||||||
|
Endif
|
||||||
|
Endif
|
||||||
|
Next
|
||||||
|
|
||||||
|
aLines.Add(sText)
|
||||||
|
'Debug "#1 "; Timer - fTimer;; $X;; $Y
|
||||||
|
|
||||||
|
'fTimer = Timer
|
||||||
|
|
||||||
|
'SX = $X
|
||||||
|
'SY = $Y
|
||||||
|
|
||||||
|
hView._DisableUpdateSize()
|
||||||
|
|
||||||
|
Lines.Remove(D, -1)
|
||||||
|
If D = 0 Then $bBrokenLine = False
|
||||||
|
'GetView()._UpdateSize
|
||||||
|
'Goto(0, D)
|
||||||
|
|
||||||
|
L = D
|
||||||
|
For I = 0 To aLines.Max
|
||||||
|
|
||||||
|
If I = SY Then $Y = L
|
||||||
|
|
||||||
|
sLine = aLines[I]
|
||||||
|
While String.Len(sLine) > W
|
||||||
|
With GetLine(L)
|
||||||
|
.Text = String.Left(sLine, W)
|
||||||
|
.Length = W
|
||||||
|
End With
|
||||||
|
sLine = String.Mid$(sLine, W + 1)
|
||||||
|
Inc L
|
||||||
|
$bBrokenLine = True
|
||||||
|
|
||||||
|
If I = SY Then
|
||||||
|
If $X >= W Then
|
||||||
|
$X -= W
|
||||||
|
$Y = L
|
||||||
|
Endif
|
||||||
|
Endif
|
||||||
|
|
||||||
|
Wend
|
||||||
|
|
||||||
|
With GetLine(L)
|
||||||
|
.Text = sLine
|
||||||
|
.Length = String.Len(sLine)
|
||||||
|
.NewLine = I < aLines.Max
|
||||||
|
End With
|
||||||
|
Inc L
|
||||||
|
|
||||||
|
Next
|
||||||
|
|
||||||
|
'Debug "#2 "; Timer - fTimer;; $X;; $Y
|
||||||
|
|
||||||
|
'fTimer = Timer
|
||||||
|
|
||||||
|
For I = D To Lines.Max
|
||||||
|
Lines[I].InitAttr(aAttr)
|
||||||
|
Next
|
||||||
|
|
||||||
|
'Debug "#3 "; Timer - fTimer
|
||||||
|
|
||||||
|
hView._EnableUpdateSize()
|
||||||
|
hView._UpdateSize
|
||||||
|
'hView.EnsureVisible()
|
||||||
|
|
||||||
|
End
|
||||||
|
|
||||||
Public Sub Resize(W As Integer, H As Integer) As Boolean
|
Public Sub Resize(W As Integer, H As Integer) As Boolean
|
||||||
|
|
||||||
If W <> $W Or If H <> $H Then
|
If W <> $W Or If H <> $H Then
|
||||||
|
|
||||||
|
If Not GetView().AlternateScreen And If Lines.Count < 100000 Then
|
||||||
|
If $bBrokenLine Or If W < $W Then
|
||||||
|
Relayout(W)
|
||||||
|
Endif
|
||||||
|
Endif
|
||||||
|
|
||||||
$W = W
|
$W = W
|
||||||
$H = H
|
$H = H
|
||||||
$X = Min($X, $W - 1)
|
|
||||||
$Y = ScreenTop() + Max(0, Min($Y - ScreenTop(), $H - 1))
|
|
||||||
$X1 = 0
|
$X1 = 0
|
||||||
$Y1 = 0
|
$Y1 = 0
|
||||||
$X2 = 0
|
$X2 = 0
|
||||||
|
@ -163,6 +275,7 @@ Public Sub Resize(W As Integer, H As Integer) As Boolean
|
||||||
'Debug "$Y = "; $Y
|
'Debug "$Y = "; $Y
|
||||||
$iScrollStart = -1
|
$iScrollStart = -1
|
||||||
$iScrollEnd = -1
|
$iScrollEnd = -1
|
||||||
|
|
||||||
If GetView().AlternateScreen Then
|
If GetView().AlternateScreen Then
|
||||||
If Lines.Count > $H Then
|
If Lines.Count > $H Then
|
||||||
Lines.Resize($H)
|
Lines.Resize($H)
|
||||||
|
@ -170,12 +283,17 @@ Public Sub Resize(W As Integer, H As Integer) As Boolean
|
||||||
Endif
|
Endif
|
||||||
Endif
|
Endif
|
||||||
$hLineCache = Null
|
$hLineCache = Null
|
||||||
|
|
||||||
|
$X = Min($X, $W - 1)
|
||||||
|
$Y = ScreenTop() + Max(0, Min($Y - ScreenTop(), $H - 1))
|
||||||
|
|
||||||
Return True
|
Return True
|
||||||
|
|
||||||
Endif
|
Endif
|
||||||
|
|
||||||
End
|
End
|
||||||
|
|
||||||
Public Sub GetLine(Y As Integer) As CTerminalLine
|
Fast Public Sub GetLine(Y As Integer) As CTerminalLine
|
||||||
|
|
||||||
Dim hLine As CTerminalLine
|
Dim hLine As CTerminalLine
|
||||||
|
|
||||||
|
@ -234,6 +352,7 @@ Private Sub Insert(sText As String, Optional X As Integer = $X)
|
||||||
sText = String.Mid$(sText, iLen + 1)
|
sText = String.Mid$(sText, iLen + 1)
|
||||||
Endif
|
Endif
|
||||||
If WrapMode Then
|
If WrapMode Then
|
||||||
|
$bBrokenLine = True
|
||||||
Index()
|
Index()
|
||||||
$X = 0
|
$X = 0
|
||||||
Insert(sText)
|
Insert(sText)
|
||||||
|
@ -323,6 +442,11 @@ Public Sub Print(sText As String)
|
||||||
End
|
End
|
||||||
|
|
||||||
Private Sub NewLine()
|
Private Sub NewLine()
|
||||||
|
|
||||||
|
Dim hLine As CTerminalLine
|
||||||
|
|
||||||
|
hLine = GetLine($Y)
|
||||||
|
hLine.NewLine = True
|
||||||
|
|
||||||
If NewlineMode Then $X = 0
|
If NewlineMode Then $X = 0
|
||||||
Index()
|
Index()
|
||||||
|
@ -854,6 +978,8 @@ Private Sub DrawLine(hView As TerminalView, L As Integer, X As Integer, Y As Int
|
||||||
|
|
||||||
If Paint.W > X Then Paint.FillRect(X, Y, Paint.W - X, LH, hView.Background)
|
If Paint.W > X Then Paint.FillRect(X, Y, Paint.W - X, LH, hView.Background)
|
||||||
|
|
||||||
|
'If hLine.NewLine Then Paint.FillRect(Paint.W - 1, Y, 1, 4, Color.Yellow)
|
||||||
|
|
||||||
Return
|
Return
|
||||||
|
|
||||||
DRAW_TEXT:
|
DRAW_TEXT:
|
||||||
|
|
|
@ -135,6 +135,7 @@ Private $bIgnoreNextAnimation As Boolean
|
||||||
Private $bReadOnly As Boolean
|
Private $bReadOnly As Boolean
|
||||||
|
|
||||||
Private Const PADDING As Integer = 2
|
Private Const PADDING As Integer = 2
|
||||||
|
Private $iDisableUpdateSize As Integer
|
||||||
|
|
||||||
'Private $bDoubleFont As Boolean = True
|
'Private $bDoubleFont As Boolean = True
|
||||||
|
|
||||||
|
@ -254,7 +255,21 @@ Public Sub _RefreshLine(Y As Integer)
|
||||||
|
|
||||||
End
|
End
|
||||||
|
|
||||||
|
Public Sub _DisableUpdateSize()
|
||||||
|
|
||||||
|
Inc $iDisableUpdateSize
|
||||||
|
|
||||||
|
End
|
||||||
|
|
||||||
|
Public Sub _EnableUpdateSize()
|
||||||
|
|
||||||
|
Dec $iDisableUpdateSize
|
||||||
|
|
||||||
|
End
|
||||||
|
|
||||||
Public Sub _UpdateSize()
|
Public Sub _UpdateSize()
|
||||||
|
|
||||||
|
If $iDisableUpdateSize Then Return
|
||||||
|
|
||||||
$hScroll.MinValue = 0
|
$hScroll.MinValue = 0
|
||||||
$hScroll.MaxValue = Max(0, $hScreen.Lines.Count - $H)
|
$hScroll.MaxValue = Max(0, $hScreen.Lines.Count - $H)
|
||||||
|
@ -272,7 +287,7 @@ Private Sub UpdateScreen()
|
||||||
|
|
||||||
If $bAutoResize Then
|
If $bAutoResize Then
|
||||||
|
|
||||||
W = Me.W
|
W = Me.W - PADDING * 2
|
||||||
If Me.Border Then W -= 2
|
If Me.Border Then W -= 2
|
||||||
If $bShowScrollBar Then W -= $hScroll.W
|
If $bShowScrollBar Then W -= $hScroll.W
|
||||||
W = Max(2, W \ $CW)
|
W = Max(2, W \ $CW)
|
||||||
|
|
Loading…
Reference in a new issue