diff --git a/comp/src/gb.form.terminal/.src/TerminalView/CTerminalLine.class b/comp/src/gb.form.terminal/.src/TerminalView/CTerminalLine.class index 4fe36029b..f1dd53ddf 100644 --- a/comp/src/gb.form.terminal/.src/TerminalView/CTerminalLine.class +++ b/comp/src/gb.form.terminal/.src/TerminalView/CTerminalLine.class @@ -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 diff --git a/comp/src/gb.form.terminal/.src/TerminalView/TerminalScreen.class b/comp/src/gb.form.terminal/.src/TerminalView/TerminalScreen.class index 45d2c595d..9d1df439b 100644 --- a/comp/src/gb.form.terminal/.src/TerminalView/TerminalScreen.class +++ b/comp/src/gb.form.terminal/.src/TerminalView/TerminalScreen.class @@ -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: diff --git a/comp/src/gb.form.terminal/.src/TerminalView/TerminalView.class b/comp/src/gb.form.terminal/.src/TerminalView/TerminalView.class index 3920f2a73..dc9238912 100644 --- a/comp/src/gb.form.terminal/.src/TerminalView/TerminalView.class +++ b/comp/src/gb.form.terminal/.src/TerminalView/TerminalView.class @@ -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)