@@ -26,16 +26,16 @@ private void TerminalChanged()
2626 }
2727
2828 //用于存放终端数据的缓存
29- private readonly List < List < TerminalBlock > > _cacheLines = [ ] ;
29+ private List < List < TerminalBlock > > CacheLines { get ; } = [ ] ;
3030
3131 //当前光标位置
3232 //X从0开始,最大可到达窗口宽度(再增加就需要换行了)
3333 //Y从0开始,最大可到达窗口高度-1
34- private int _positionX = 0 ;
35- private int _positionY = 0 ;
34+ private int PositionX { get ; set ; } = 0 ;
35+ private int PositionY { get ; set ; } = 0 ;
3636
3737 //当前的颜色、字体等信息,存到TerminalBlock中
38- private TerminalBlock _currentState = new ( String . Empty ) ;
38+ private TerminalBlock CurrentState { get ; set ; } = new ( String . Empty ) ;
3939
4040 //MaxCacheLines表示终端缓存的行数,超过这个行数后会删除最上面的行
4141 private readonly int _maxCacheLines = Utils . Setting . TerminalBufferLines ;
@@ -48,25 +48,25 @@ private void TerminalChanged()
4848 private void AddLine ( )
4949 {
5050 //添加行
51- _cacheLines . Add ( [ ] ) ;
51+ CacheLines . Add ( [ ] ) ;
5252 //如果超过了最大行数,删除最上面的行
53- if ( _cacheLines . Count > _maxCacheLines )
54- _cacheLines . RemoveAt ( 0 ) ;
55- if ( _currentLine != 0 )
53+ if ( CacheLines . Count > _maxCacheLines )
54+ CacheLines . RemoveAt ( 0 ) ;
55+ if ( CurrentLine != 0 )
5656 {
57- _currentLine -- ;
57+ CurrentLine -- ;
5858 //如果当前行数超过了最大行数,设置为最大行数
59- if ( _currentLine > _cacheLines . Count - _windowHeight )
60- _currentLine = _cacheLines . Count - _windowHeight ;
61- if ( _currentLine < 0 ) _currentLine = 0 ;
59+ if ( CurrentLine > CacheLines . Count - _windowHeight )
60+ CurrentLine = CacheLines . Count - _windowHeight ;
61+ if ( CurrentLine < 0 ) CurrentLine = 0 ;
6262 }
6363 }
6464
6565 /// <summary>
6666 /// 基于当前光标,往后追加文本
6767 /// 文本不得包含不可见字符
6868 /// </summary>
69- /// <param name="text ">待添加的文本</param>
69+ /// <param name="texts ">待添加的文本</param>
7070 public void AddText ( char [ ] texts ) //TODO)) 保持private
7171 {
7272 //防止没有设置窗口大小的时候就添加数据
@@ -77,16 +77,16 @@ public void AddText(char[] texts)//TODO)) 保持private
7777 while ( chars . Length > 0 )
7878 {
7979 //当前光标位置后还有多少个字符的空间
80- var space = _windowWidth - _positionX ;
80+ var space = _windowWidth - PositionX ;
8181 //剩余空间不足,添加新行
8282 if ( space <= 0 )
8383 {
84- _positionX = 0 ;
85- _positionY ++ ; //超过高度后面再管
84+ PositionX = 0 ;
85+ PositionY ++ ; //超过高度后面再管
8686 space = _windowWidth ;
8787 }
8888 //记录一下修改前的X光标位置
89- var oldX = _positionX ;
89+ var oldX = PositionX ;
9090
9191 //放置文本
9292 var sb = new StringBuilder ( ) ;
@@ -103,45 +103,45 @@ public void AddText(char[] texts)//TODO)) 保持private
103103 //去除掉已经添加的字符
104104 chars = chars [ 1 ..] ;
105105 //光标位置往后挪动
106- _positionX += length ;
106+ PositionX += length ;
107107 }
108108 if ( space < 0 )
109109 {
110110 //如果剩余空间不足,说明最后一格放不下这个宽字符
111111 //直接把X位置打到头,交够下一轮来处理
112- _positionX = _windowWidth ;
112+ PositionX = _windowWidth ;
113113 }
114114 //添加文本
115115 var text = sb . ToString ( ) ;
116- var line = _currentState . MakeNew ( text ) ;
116+ var line = CurrentState . MakeNew ( text ) ;
117117
118118 //这一行数据要修改
119119 List < TerminalBlock > needChangeLine ;
120120
121121 //超过了最大高度,说明要新开一行
122- if ( _positionY >= _windowHeight )
122+ if ( PositionY >= _windowHeight )
123123 {
124- _positionY = _windowHeight - 1 ;
124+ PositionY = _windowHeight - 1 ;
125125 AddLine ( ) ;
126- needChangeLine = _cacheLines [ ^ 1 ] ;
126+ needChangeLine = CacheLines [ ^ 1 ] ;
127127 }
128128 //当前缓存的行数还没有达到显示行高,也开新行
129- else if ( _cacheLines . Count - 1 < _positionY )
129+ else if ( CacheLines . Count - 1 < PositionY )
130130 {
131- var needLineCount = _positionY - _cacheLines . Count + 1 ;
131+ var needLineCount = PositionY - CacheLines . Count + 1 ;
132132 for ( int i = 0 ; i < needLineCount ; i ++ )
133133 AddLine ( ) ;
134- needChangeLine = _cacheLines [ ^ 1 ] ;
134+ needChangeLine = CacheLines [ ^ 1 ] ;
135135 }
136136 //不是新行,需要更改当前行的数据
137137 else
138138 {
139139 //计算开始行下标的偏移量
140- var lineStartOffset = _cacheLines . Count - _windowHeight ;
140+ var lineStartOffset = CacheLines . Count - _windowHeight ;
141141 if ( lineStartOffset < 0 )
142142 lineStartOffset = 0 ;
143143 //使用当前行
144- needChangeLine = _cacheLines [ _positionY + lineStartOffset ] ;
144+ needChangeLine = CacheLines [ PositionY + lineStartOffset ] ;
145145 }
146146
147147 var allLength = needChangeLine . Sum ( l => l . Length ) ;
@@ -259,8 +259,8 @@ public void AddText(char[] texts)//TODO)) 保持private
259259 //TODO)) 仅用于测试
260260 public void ChangePosition ( int x , int y )
261261 {
262- _positionX = x ;
263- _positionY = y ;
262+ PositionX = x ;
263+ PositionY = y ;
264264 }
265265
266266 /// <summary>
@@ -272,9 +272,9 @@ public List<List<TerminalBlock>> GetShowLines()
272272 List < List < TerminalBlock > > cacheLines = new ( ) ;
273273
274274 //计算出要显示的行数范围
275- int allLines = _cacheLines . Count ;
275+ int allLines = CacheLines . Count ;
276276 //起始行和结束行,闭区间,从0开始,代表CacheLines的项目下标
277- int startLine = allLines - _windowHeight - _currentLine ;
277+ int startLine = allLines - _windowHeight - CurrentLine ;
278278 if ( startLine < 0 )
279279 startLine = 0 ;
280280 int endLine = startLine + _windowHeight - 1 ;
@@ -285,7 +285,7 @@ public List<List<TerminalBlock>> GetShowLines()
285285 for ( int i = startLine ; i <= endLine ; i ++ )
286286 {
287287 //添加行
288- var line = _cacheLines [ i ] ;
288+ var line = CacheLines [ i ] ;
289289 cacheLines . Add ( line ) ;
290290 }
291291
@@ -296,10 +296,60 @@ public List<List<TerminalBlock>> GetShowLines()
296296 cacheLines . Add ( [ ] ) ;
297297 }
298298 //把当前光标位置背景和前景色反色处理
299- var posY = _positionY ;
300- if ( posY < _cacheLines . Count )
299+ if ( PositionY < cacheLines . Count )
301300 {
302- //TODO)) 这里需要处理光标位置
301+ //这里需要处理光标位置
302+ //复制一个新的行来替换掉现有的行用来展示
303+ var tempLine = new List < TerminalBlock > ( ) ;
304+ foreach ( var block in cacheLines [ PositionY ] )
305+ {
306+ tempLine . Add ( ( TerminalBlock ) block . Clone ( ) ) ;
307+ }
308+
309+ var allLength = tempLine . Sum ( l => l . Length ) ;
310+ //光标没有重叠,说明光标位置在当前行的后面
311+ if ( allLength <= PositionX )
312+ {
313+ //加几个空格,直到光标位置
314+ if ( allLength < PositionX )
315+ tempLine . Add ( new TerminalBlock ( new string ( ' ' , allLength - PositionX ) ) ) ;
316+ tempLine . Add ( new TerminalBlock ( new string ( ' ' , 1 ) , - 1 , - 1 ) ) ;
317+ }
318+ else
319+ {
320+ var charLine = new List < TerminalBlock > ( ) ;
321+ var count = 0 ;
322+ //把这一行按字符拆碎
323+ foreach ( var block in tempLine )
324+ {
325+ //拆碎
326+ var tempChars = block . Text . ToCharArray ( ) ;
327+ foreach ( var c in tempChars )
328+ {
329+ var start = count ;
330+ var length = UnicodeCalculator . GetWidth ( c ) ;
331+ var end = start + length - 1 ;
332+ //如果posx在当前字符范围内,说明光标在这个字符上
333+ if ( PositionX >= start && PositionX <= end )
334+ charLine . Add ( new TerminalBlock ( c . ToString ( ) , - 1 , - 1 ) ) ;
335+ else
336+ charLine . Add ( block . MakeNew ( c . ToString ( ) ) ) ;
337+ count += length ;
338+ //如果字符宽度超过1,加入空白填位
339+ length -- ;
340+ while ( length > 0 )
341+ {
342+ charLine . Add ( block . MakeNew ( string . Empty ) ) ;
343+ length -- ;
344+ }
345+ }
346+ }
347+ tempLine = charLine ; //替换掉当前行为拆字后的行
348+ }
349+ //优化当前这一行数据块
350+ TerminalBlock . OptimizeBlocks ( tempLine ) ;
351+ //替换掉当前行
352+ cacheLines [ PositionY ] = tempLine ;
303353 }
304354
305355 return cacheLines ;
@@ -314,37 +364,37 @@ public void ChangeWindowSize(int width, int height)
314364 }
315365
316366 //当前所在的行数相比较于终端最底部的行数,0表示在最底部,其余数字表示向上挪动的行数
317- private int _currentLine = 0 ;
367+ private int CurrentLine { get ; set ; } = 0 ;
318368
319369 private double CurrentLine2ScrollValue =>
320- ( _currentLine == 0 || _cacheLines . Count < _windowHeight )
370+ ( CurrentLine == 0 || CacheLines . Count < _windowHeight )
321371 ? 100
322- : 100.0 - ( double ) _currentLine / ( _cacheLines . Count - _windowHeight ) * 100.0 ;
372+ : 100.0 - ( double ) CurrentLine / ( CacheLines . Count - _windowHeight ) * 100.0 ;
323373 //向上移动的行数
324374 public double CurrentLineMoveUp ( int delta )
325375 {
326- var lastCurrentLine = _currentLine ;
327- _currentLine += delta ;
328- if ( _currentLine > _cacheLines . Count - _windowHeight )
329- _currentLine = _cacheLines . Count - _windowHeight ;
330- if ( _currentLine < 0 )
331- _currentLine = 0 ;
376+ var lastCurrentLine = CurrentLine ;
377+ CurrentLine += delta ;
378+ if ( CurrentLine > CacheLines . Count - _windowHeight )
379+ CurrentLine = CacheLines . Count - _windowHeight ;
380+ if ( CurrentLine < 0 )
381+ CurrentLine = 0 ;
332382
333- if ( lastCurrentLine != _currentLine )
383+ if ( lastCurrentLine != CurrentLine )
334384 TerminalChanged ( ) ;
335385
336386 return CurrentLine2ScrollValue ;
337387 }
338388 //滚轮事件
339389 public void ScrollBarChanged ( double value )
340390 {
341- var lastCurrentLine = _currentLine ;
342- if ( Math . Abs ( value - 100.0 ) < 0.001 || _cacheLines . Count < _windowHeight )
343- _currentLine = 0 ;
391+ var lastCurrentLine = CurrentLine ;
392+ if ( Math . Abs ( value - 100.0 ) < 0.001 || CacheLines . Count < _windowHeight )
393+ CurrentLine = 0 ;
344394 else
345- _currentLine = ( int ) ( _cacheLines . Count - _windowHeight - value * ( _cacheLines . Count - _windowHeight ) / 100.0 ) ;
395+ CurrentLine = ( int ) ( CacheLines . Count - _windowHeight - value * ( CacheLines . Count - _windowHeight ) / 100.0 ) ;
346396
347- if ( lastCurrentLine != _currentLine )
397+ if ( lastCurrentLine != CurrentLine )
348398 TerminalChanged ( ) ;
349399 }
350400}
0 commit comments