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

View file

@ -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)
@ -324,6 +443,11 @@ 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:

View file

@ -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,8 +255,22 @@ 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)
$hScroll.PageStep = $H $hScroll.PageStep = $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)