TerminalDataReceiver.cs
上传用户:szltgg
上传日期:2019-05-16
资源大小:604k
文件大小:7k
源码类别:

Telnet服务器

开发平台:

C#

  1. /*
  2. * Copyright (c) 2005 Poderosa Project, All Rights Reserved.
  3. * $Id: TerminalDataReceiver.cs,v 1.2 2005/04/20 08:45:47 okajima Exp $
  4. */
  5. using System;
  6. using System.Diagnostics;
  7. using System.Threading;
  8. using System.Text;
  9. using System.Windows.Forms;
  10. using Poderosa.Connection;
  11. using Poderosa.Config;
  12. using Poderosa.Forms;
  13. using Poderosa.Communication;
  14. using Poderosa.Text;
  15. using Poderosa.Log;
  16. namespace Poderosa.Terminal
  17. {
  18. /// <summary>
  19. /// TerminalDataReceiver 偺奣梫偺愢柧偱偡丅
  20. /// </summary>
  21. public class TerminalDataReceiver : IDataReceiver {
  22. private ConnectionTag _tag;
  23. //庴怣僗儗僢僪偱偙傟傜偺抣傪愝掕偟丄師偺OnPaint摍儊僀儞僗儗僢僪偱偺幚峴偱Commit偡傞
  24. private bool _transientScrollBarDirty; //偙傟偑棫偭偰偄傞偲梫愝掕
  25. private bool _transientScrollBarEnabled;
  26. private int  _transientScrollBarValue;
  27. private int  _transientScrollBarLargeChange;
  28. private int  _transientScrollBarMaximum;
  29. public TerminalDataReceiver(ConnectionTag ct) {
  30. _tag = ct;
  31. }
  32. public void Listen() {
  33. _tag.Connection.RepeatAsyncRead(this);
  34. }
  35. public void DataArrived(byte[] data, int offset, int count) {
  36. try {
  37. TerminalConnection con = _tag.Connection;
  38. con.AddReceivedDataStats(count);
  39. con.BinaryLogger.Append(data, offset, count);
  40. if(_tag.ModalTerminalTask!=null && _tag.ModalTerminalTask.CanReceive)
  41. _tag.ModalTerminalTask.Input(data, offset, count);
  42. else {
  43. TerminalDocument document = _tag.Document;
  44. lock(document) {
  45. _tag.InvalidateParam.Reset();
  46. _tag.Terminal.Input(data, offset, count);
  47. //塃抂偵僉儍儗僢僩偑棃偨偲偒偼曋媂揑偵師峴偺摢偵傕偭偰偄偔
  48. if(document.CaretColumn==_tag.Connection.TerminalWidth) {
  49. document.CurrentLineNumber++; //偙傟偵傛偭偰師峴偺懚嵼傪曐徹
  50. document.CaretColumn = 0;
  51. }
  52. CheckDiscardDocument();
  53. AdjustTransientScrollBar();
  54. int n = document.CurrentLineNumber-_tag.Connection.TerminalHeight+1-document.FirstLineNumber;
  55. if(n < 0) n = 0;
  56. //Debug.WriteLine(String.Format("E={0} C={1} T={2} H={3} LC={4} MAX={5} n={6}", _transientScrollBarEnabled, _tag.Document.CurrentLineNumber, _tag.Document.TopLineNumber, _tag.Connection.TerminalHeight, _transientScrollBarLargeChange, _transientScrollBarMaximum, n));
  57. if(IsAutoScrollMode(n)) {
  58. _transientScrollBarValue = n;
  59. document.TopLineNumber = n + document.FirstLineNumber;
  60. }
  61. else
  62. _transientScrollBarValue = document.TopLineNumber - document.FirstLineNumber;
  63. _tag.NotifyUpdate();
  64. }
  65. //Invalidate傪lock偺奜偵弌偡丅偙偺傎偆偑埨慡偲巚傢傟偨
  66. if(_tag.Pane!=null) _tag.InvalidateParam.InvokeFor(_tag.Pane);
  67. ITerminalTextLogger tl = con.TextLogger;
  68. if(tl!=null) {
  69. tl.PacketDelimiter();
  70. tl.Flush();
  71. }
  72. }
  73. ITerminalBinaryLogger bl = con.BinaryLogger;
  74. if(bl!=null)
  75. bl.Flush();
  76. }
  77. catch(Exception ex) {
  78. GEnv.InterThreadUIService.ReportCriticalError(ex);
  79. }
  80. }
  81. private bool IsAutoScrollMode(int value_candidate) {
  82. return _tag.Terminal.TerminalMode==TerminalMode.Normal && 
  83. _tag.Document.CurrentLineNumber>=_tag.Document.TopLineNumber+_tag.Connection.TerminalHeight-1 &&
  84. (!_transientScrollBarEnabled || value_candidate+_transientScrollBarLargeChange>_transientScrollBarMaximum);
  85. }
  86. private void CheckDiscardDocument() {
  87. if(_tag==null || _tag.Terminal.TerminalMode==TerminalMode.Application) return;
  88. TerminalDocument document = _tag.Document;
  89. int del = document.DiscardOldLines(GEnv.Options.TerminalBufferSize+_tag.Connection.TerminalHeight);
  90. if(del > 0) {
  91. _tag.NotifyUpdate();
  92. TextSelection sel = GEnv.TextSelection;
  93. if(sel.Owner==_tag.Pane)
  94. sel.ClearIfOverlapped(document.FirstLineNumber);
  95. int newvalue = _transientScrollBarValue - del;
  96. if(newvalue<0) newvalue=0;
  97. _transientScrollBarValue = newvalue;
  98. document.InvalidateAll(); //杮摉偼偙偙傑偱偟側偔偰傕椙偝偦偆偩偑擮偺偨傔
  99. }
  100. }
  101. internal void AdjustTransientScrollBar() {
  102. TerminalDocument document = _tag.Document;
  103. int paneheight = _tag.Connection.TerminalHeight;
  104. int docheight = Math.Max(document.LastLineNumber, document.TopLineNumber+paneheight-1)-document.FirstLineNumber+1;
  105. _transientScrollBarDirty = true;
  106. if((_tag.Terminal.TerminalMode==TerminalMode.Application && !GEnv.Options.AllowsScrollInAppMode)
  107. || paneheight >= docheight) {
  108. _transientScrollBarEnabled = false;
  109. _transientScrollBarValue = 0;
  110. }
  111. else {
  112. _transientScrollBarEnabled = true;
  113. _transientScrollBarMaximum = docheight-1;
  114. _transientScrollBarLargeChange = paneheight;
  115. }
  116. //Debug.WriteLine(String.Format("E={0} V={1}", _transientScrollBarEnabled, _transientScrollBarValue));
  117. }
  118. public void SetTransientScrollBarValue(int value) {
  119. _transientScrollBarValue = value;
  120. _transientScrollBarDirty = true;
  121. }
  122. public void CommitScrollBar(VScrollBar sb, bool dirty_only) {
  123. if(dirty_only && !_transientScrollBarDirty) return;
  124. sb.Enabled = _transientScrollBarEnabled;
  125. sb.Maximum = _transientScrollBarMaximum;
  126. sb.LargeChange = _transientScrollBarLargeChange;
  127. //!!杮棃偙偺if暥偼晄梫側偼偢偩偑丄斖埻僄儔乕偵側傞働乕僗偑尒庴偗傜傟偨丅偦偺尨場傪扵偭偰儕儕乕僗捈慜偵偄傠偄傠偄偠傞偺偼婋尟側偺偱偙偙偼摝偘傞丅屻偱偪傖傫偲夝柧偡傞丅
  128. if(_transientScrollBarValue < _transientScrollBarMaximum)
  129. sb.Value = _transientScrollBarValue;
  130. _transientScrollBarDirty = false;
  131. }
  132. public void ErrorOccurred(string msg) {
  133. if(GEnv.Frame.IgnoreErrors) return;
  134. Debug.WriteLine("Closed="+_tag.Connection.IsClosed);
  135. if(!_tag.Connection.IsClosed) { //暵偠傞巜椷傪弌偟偨屻偺僄儔乕偼昞帵偟側偄
  136. GEnv.InterThreadUIService.Warning(String.Format(GEnv.Strings.GetString("Message.TerminalDataReceiver.GenericError"),_tag.Connection.Param.ShortDescription, msg));
  137. try {
  138. _tag.Connection.Close();
  139. }
  140. catch(Exception) { //僄儔乕捠抦屻偺Close偵幐攕偡傞偺偼柍帇丅
  141. }
  142. GEnv.Frame.RefreshConnection(_tag);
  143. _tag.NotifyDisconnect();
  144. }
  145. }
  146. public void DisconnectedFromServer() {
  147. if(GEnv.Frame.IgnoreErrors) return;
  148. _tag.NotifyDisconnect();
  149. TerminalConnection c = _tag.Connection;
  150. GEnv.InterThreadUIService.DisconnectedFromServer(c);
  151. }
  152. public void IndicateBell() {
  153. GEnv.InterThreadUIService.IndicateBell(_tag.Document);
  154. if(GEnv.Options.BeepOnBellChar) Win32.MessageBeep(-1);
  155. }
  156. }
  157. //偙傟傪幚憰偟偨僆僽僕僃僋僩傪ConnectionTag偵僙僢僩偟偰偄傞娫偼丄僨乕僞傪墶庢傝偱偒傞丅
  158. public interface IModalTerminalTask {
  159. void Input(byte[] data, int offset, int count);
  160. bool CanReceive { get; }
  161. string Caption { get; }
  162. }
  163. }