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:
gambas 2020-12-30 01:22:57 +01:00
parent e4da796e5b
commit a8b9bf14b6
3 changed files with 212 additions and 8 deletions

View file

@ -1,12 +1,14 @@
' Gambas class file
Fast
Fast Unsafe
Public Text As String
Public Length As Integer
Private Attr As New Integer[]
Public NewLine As Boolean
Private $bCompressed As Boolean
Private Enum FLAG_BG, FLAG_FG, FLAG_BOLD, FLAG_DIM, FLAG_REV, FLAG_UND, FLAG_BLK
@ -35,7 +37,7 @@ Private Sub Uncompress()
End
Private Sub Compress()
Private Sub Compress(bFull As Boolean)
Dim I As Integer
Dim iAttr As Integer
@ -59,8 +61,13 @@ Private Sub Compress()
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
Attr = aAttr
End
@ -128,16 +135,72 @@ End
Public Sub GetAttr() As Integer[]
If Not $bCompressed Then Compress()
If Not $bCompressed Then Compress(False)
Return Attr
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()
Text = ""
Length = 0
NewLine = False
Attr.Clear
$bCompressed = False

View file

@ -91,6 +91,9 @@ Public Lines As New CTerminalLine[]
Private $W As Integer
Private $H As Integer
' If a line had to be broken
Private $bBrokenLine As Boolean
' Cursor position
Private $X As Integer
Private $Y As Integer
@ -144,18 +147,127 @@ End
Public Sub Clear()
Lines.Clear
$bBrokenLine = False
GetView()._UpdateSize
Goto(0, 0)
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
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
$H = H
$X = Min($X, $W - 1)
$Y = ScreenTop() + Max(0, Min($Y - ScreenTop(), $H - 1))
$X1 = 0
$Y1 = 0
$X2 = 0
@ -163,6 +275,7 @@ Public Sub Resize(W As Integer, H As Integer) As Boolean
'Debug "$Y = "; $Y
$iScrollStart = -1
$iScrollEnd = -1
If GetView().AlternateScreen Then
If Lines.Count > $H Then
Lines.Resize($H)
@ -170,12 +283,17 @@ Public Sub Resize(W As Integer, H As Integer) As Boolean
Endif
Endif
$hLineCache = Null
$X = Min($X, $W - 1)
$Y = ScreenTop() + Max(0, Min($Y - ScreenTop(), $H - 1))
Return True
Endif
End
Public Sub GetLine(Y As Integer) As CTerminalLine
Fast Public Sub GetLine(Y As Integer) 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)
Endif
If WrapMode Then
$bBrokenLine = True
Index()
$X = 0
Insert(sText)
@ -323,6 +442,11 @@ Public Sub Print(sText As String)
End
Private Sub NewLine()
Dim hLine As CTerminalLine
hLine = GetLine($Y)
hLine.NewLine = True
If NewlineMode Then $X = 0
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 hLine.NewLine Then Paint.FillRect(Paint.W - 1, Y, 1, 4, Color.Yellow)
Return
DRAW_TEXT:

View file

@ -135,6 +135,7 @@ Private $bIgnoreNextAnimation As Boolean
Private $bReadOnly As Boolean
Private Const PADDING As Integer = 2
Private $iDisableUpdateSize As Integer
'Private $bDoubleFont As Boolean = True
@ -254,7 +255,21 @@ Public Sub _RefreshLine(Y As Integer)
End
Public Sub _DisableUpdateSize()
Inc $iDisableUpdateSize
End
Public Sub _EnableUpdateSize()
Dec $iDisableUpdateSize
End
Public Sub _UpdateSize()
If $iDisableUpdateSize Then Return
$hScroll.MinValue = 0
$hScroll.MaxValue = Max(0, $hScreen.Lines.Count - $H)
@ -272,7 +287,7 @@ Private Sub UpdateScreen()
If $bAutoResize Then
W = Me.W
W = Me.W - PADDING * 2
If Me.Border Then W -= 2
If $bShowScrollBar Then W -= $hScroll.W
W = Max(2, W \ $CW)