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

Telnet服务器

开发平台:

C#

  1. /*
  2. * Copyright (c) 2005 Poderosa Project, All Rights Reserved.
  3. * $Id: TerminalBase.cs,v 1.2 2005/04/20 08:45:47 okajima Exp $
  4. */
  5. using System;
  6. using System.Collections;
  7. using System.IO;
  8. using System.Text;
  9. using System.Threading;
  10. using System.Diagnostics;
  11. using System.Windows.Forms;
  12. using Poderosa.Log;
  13. using Poderosa.Config;
  14. using Poderosa.Connection;
  15. using Poderosa.ConnectionParam;
  16. using Poderosa.Text;
  17. using Poderosa.Communication;
  18. namespace Poderosa.Terminal
  19. {
  20. /// <summary>
  21. /// 僞乕儈僫儖
  22. /// 僨乕僞傪庴怣偟偰僪僉儏儊儞僩傪憖嶌偡傞婡擻傪傕偮丅
  23. /// </summary>
  24. internal abstract class AbstractTerminal : ITerminal {
  25. public abstract void ProcessChar(char ch);
  26. public abstract ProcessCharResult State { get; }
  27. public abstract byte[] SequenceKeyData(Keys modifier, Keys body);
  28. protected StringBuilder _bufferForMacro;
  29. protected AutoResetEvent _signalForMacro; //儅僋儘僗儗僢僪偵僨乕僞偺撉傒庢傝壜擻傪抦傜偣傞
  30. protected ICharDecoder     _decoder;
  31. protected GLineManipulator _manipulator;
  32. protected ITerminalTextLogger _logger; //Logger僾儘僷僥傿偲偺廳暋傪壗偲偐偟偨偄
  33. public ITerminalTextLogger Logger {
  34. get {
  35. return _tag.Connection.TextLogger;
  36. }
  37. }
  38. protected ConnectionTag  _tag;
  39. protected TextDecoration _currentdecoration;
  40. protected TerminalMode _terminalMode;
  41. protected TerminalMode _cursorKeyMode; //_terminalMode偼暿暔丅AIX偱偺vi偱丄僇乕僜儖僉乕偼晄曄偲偄偆椺偑妋擣偝傟偰偄傞
  42. public TerminalMode TerminalMode {
  43. get {
  44. return _terminalMode;
  45. }
  46. }
  47. public TerminalMode CursorKeyMode {
  48. get {
  49. return _cursorKeyMode;
  50. }
  51. }
  52. protected TerminalConnection GetConnection() {
  53. return _tag.Connection;
  54. }
  55. protected TerminalDocument GetDocument() {
  56. return _tag.Document;
  57. }
  58. protected abstract void ChangeMode(TerminalMode tm);
  59. protected abstract void ResetInternal();
  60. protected virtual void ChangeCursorKeyMode(TerminalMode tm) {
  61. _cursorKeyMode = tm;
  62. }
  63. /// <summary>
  64. /// 憖嶌偺懳徾偵側傞僪僉儏儊儞僩偲暥帤偺僄儞僐乕僨傿儞僌傪巜掕偟偰峔抸
  65. /// </summary>
  66. public AbstractTerminal(ConnectionTag tag, ICharDecoder decoder) {
  67. _tag = tag;
  68. _decoder = decoder;
  69. _terminalMode = TerminalMode.Normal;
  70. _currentdecoration = TextDecoration.Default;
  71. _manipulator = new GLineManipulator(80);
  72. _bufferForMacro = new StringBuilder();
  73. _signalForMacro = new AutoResetEvent(false);
  74. }
  75. public void Input(byte[] data, int offset, int length) {
  76. _manipulator.Load(GetDocument().CurrentLine, 0);
  77. _manipulator.CaretColumn = GetDocument().CaretColumn;
  78. _manipulator.DefaultDecoration = _currentdecoration;
  79. _decoder.Input(this, data, offset, length);
  80. GetDocument().ReplaceCurrentLine(_manipulator.Export());
  81. GetDocument().CaretColumn = _manipulator.CaretColumn;
  82. }
  83. public void Input(char[] data, int offset, int length) {
  84. _manipulator.Load(GetDocument().CurrentLine, 0);
  85. _manipulator.CaretColumn = GetDocument().CaretColumn;
  86. _manipulator.DefaultDecoration = _currentdecoration;
  87. for(int i=0; i<length; i++)
  88. ProcessChar(data[offset+i]);
  89. GetDocument().ReplaceCurrentLine(_manipulator.Export());
  90. GetDocument().CaretColumn = _manipulator.CaretColumn;
  91. }
  92. public void UnsupportedCharSetDetected(char code) {
  93. string desc;
  94. if(code=='0')
  95. desc = "0 (DEC Special Character)"; //偙傟偼傛偔偁傞偺偱扐偟彂偒偮偒
  96. else
  97. desc = new String(code, 1);
  98. if(GEnv.Options.WarningOption!=WarningOption.Ignore) {
  99. GEnv.InterThreadUIService.UnsupportedCharSetDetected(GetDocument(), String.Format(GEnv.Strings.GetString("Message.AbstractTerminal.UnsupportedCharSet"), desc));
  100. }
  101. }
  102. public void InvalidCharDetected(Encoding enc, byte[] buf) {
  103. if(GEnv.Options.WarningOption!=WarningOption.Ignore) {
  104. GEnv.InterThreadUIService.InvalidCharDetected(GetDocument(), String.Format(GEnv.Strings.GetString("Message.AbstractTerminal.UnexpectedChar"), enc.WebName));
  105. }
  106. }
  107. public void Reset() {
  108. //Encoding偑摨偠帪偼娙扨偵嵪傑偣傞偙偲偑偱偒傞
  109. if(_decoder.Encoding.Type==_tag.Connection.Param.Encoding)
  110. _decoder.Reset(_decoder.Encoding);
  111. else
  112. _decoder = new JapaneseCharDecoder(_tag.Connection);
  113. }
  114. //public void SetEncoding(EncodingProfile enc) {
  115. // _decoder.SetEncoding(enc);
  116. //}
  117. public void ClearMacroBuffer() {
  118. _bufferForMacro.Remove(0, _bufferForMacro.Length);
  119. _signalForMacro.Reset();
  120. }
  121. public void SignalData() {
  122. _signalForMacro.Set();
  123. }
  124. protected void AppendMacroBuffer(char ch) {
  125. if(ch!='r' && ch!='') {
  126. lock(_bufferForMacro) {
  127. _bufferForMacro.Append(ch); //!!挿偝偵忋尷傪偮偗偨傎偆偑埨慡偐傕
  128. }
  129. }
  130. }
  131. //儅僋儘幚峴僗儗僢僪偐傜屇偽傟傞侾峴撉傒弌偟儊僜僢僪
  132. public string ReadLineFromMacroBuffer() {
  133. do {
  134. int l = _bufferForMacro.Length;
  135. int i=0;
  136. for(i=0; i<l; i++) {
  137. if(_bufferForMacro[i]=='n') break;
  138. }
  139. if(l>0 && i<l) { //傔偱偨偔峴枛偑傒偮偐偭偨
  140. int j=i;
  141. if(i>0 && _bufferForMacro[i-1]=='r') j=i-1; //CRLF偺偲偒偼彍偄偰傗傞
  142. string r;
  143. lock(_bufferForMacro) {
  144. r = _bufferForMacro.ToString(0, j);
  145. _bufferForMacro.Remove(0, i+1);
  146. }
  147. return r;
  148. }
  149. else {
  150. _signalForMacro.Reset();
  151. _signalForMacro.WaitOne();
  152. }
  153. } while(true);
  154. }
  155. //儅僋儘幚峴僗儗僢僪偐傜屇偽傟傞丄乽壗偐僨乕僞偑偁傟偽慡晹傕偭偰偄偔乿儊僜僢僪
  156. public string ReadAllFromMacroBuffer() {
  157. if(_bufferForMacro.Length==0) {
  158. _signalForMacro.Reset();
  159. _signalForMacro.WaitOne();
  160. }
  161. lock(_bufferForMacro) {
  162. string r = _bufferForMacro.ToString();
  163. _bufferForMacro.Remove(0, _bufferForMacro.Length);
  164. return r;
  165. }
  166. }
  167. //偙傟偼儊僀儞僗儗僢僪偐傜屇傃弌偡偙偲
  168. public virtual void FullReset() {
  169. lock(_tag.Document) {
  170. ChangeMode(TerminalMode.Normal);
  171. _tag.Document.ClearScrollingRegion();
  172. ResetInternal();
  173. _decoder = new JapaneseCharDecoder(_tag.Connection);
  174. }
  175. }
  176. public void DumpCurrentText() {
  177. Debug.WriteLine(_manipulator.ToString());
  178. }
  179. }
  180. //Escape Sequence傪巊偆僞乕儈僫儖
  181. internal abstract class EscapeSequenceTerminal : AbstractTerminal {
  182. public EscapeSequenceTerminal(ConnectionTag tag, ICharDecoder decoder) : base(tag, decoder) {
  183. _escapeSequence = new StringBuilder();
  184. _processCharResult = ProcessCharResult.Processed;
  185. }
  186. private StringBuilder _escapeSequence;
  187. private ProcessCharResult _processCharResult;
  188. public override ProcessCharResult State {
  189. get {
  190. return _processCharResult;
  191. }
  192. }
  193. protected override void ResetInternal() {
  194. _escapeSequence = new StringBuilder();
  195. _processCharResult = ProcessCharResult.Processed;
  196. }
  197. public override void ProcessChar(char ch) {
  198. _logger = Logger; //_logger偼偙偺ProcessChar偺張棟撪偱偺傒桳岠丅
  199. if(_processCharResult != ProcessCharResult.Escaping) {
  200. if(ch==0x1B) {
  201. _processCharResult = ProcessCharResult.Escaping;
  202. } else {
  203. //!!媣偟傇傝偺偙偺偁偨傝傪尒傞偲偗偭偙偆墭偄暘婒偩側
  204. _logger.Append(ch);
  205. if(GEnv.Frame.MacroIsRunning) AppendMacroBuffer(ch);
  206. if(ch < 0x20 || (ch>=0x80 && ch<0xA0))
  207. _processCharResult = ProcessControlChar(ch);
  208. else
  209. _processCharResult = ProcessNormalChar(ch);
  210. }
  211. }
  212. else {
  213. if(ch=='') return; //僔乕働儞僗拞偵NULL暥帤偑擖偭偰偄傞働乕僗偑妋擣偝傟偨
  214. _escapeSequence.Append(ch);
  215. bool end_flag = false; //escape sequence偺廔傢傝偐偳偆偐傪帵偡僼儔僌
  216. if(_escapeSequence.Length==1) { //ESC+侾暥帤偱偁傞応崌
  217. end_flag = ('0'<=ch && ch<='9') || ('a'<=ch && ch<='z') || ('A'<=ch && ch<='Z') || ch=='>' || ch=='=' || ch=='|' || ch=='}' || ch=='~';
  218. }
  219. else if(_escapeSequence[0]==']') { //OSC偺廔抂偼BEL偐ST(String Terminator)
  220. end_flag = ch==0x07 || ch==0x9c; 
  221. }
  222. else {
  223. end_flag = ('a'<=ch && ch<='z') || ('A'<=ch && ch<='Z') || ch=='@' || ch=='~' || ch=='|' || ch=='{';
  224. }
  225. if(end_flag) { //僔乕働儞僗偺偍傢傝
  226. char[] seq = _escapeSequence.ToString().ToCharArray();
  227. _logger.BeginEscapeSequence();
  228. _logger.Append(seq, 0, seq.Length);
  229. _logger.CommitEscapeSequence();
  230. _logger.Flush();
  231. try {
  232. char code = seq[0];
  233. _processCharResult = ProcessCharResult.Unsupported; //ProcessEscapeSequence偱椺奜偑棃偨屻偱忬懺偑Escaping偼傂偳偄寢壥傪彽偔偺偱
  234. _processCharResult = ProcessEscapeSequence(code, seq, 1);
  235. if(_processCharResult==ProcessCharResult.Unsupported)
  236. throw new UnknownEscapeSequenceException(String.Format("ESC {0}", new string(seq)));
  237. }
  238. catch(UnknownEscapeSequenceException ex) {
  239. if(GEnv.Options.WarningOption!=Poderosa.Config.WarningOption.Ignore)
  240. GEnv.InterThreadUIService.UnsupportedEscapeSequence(GetDocument(), GEnv.Strings.GetString("Message.EscapesequenceTerminal.UnsupportedSequence")+ex.Message);
  241. }
  242. finally {
  243. _escapeSequence.Remove(0, _escapeSequence.Length);
  244. }
  245. }
  246. else
  247. _processCharResult = ProcessCharResult.Escaping;
  248. }
  249. }
  250. protected virtual ProcessCharResult ProcessControlChar(char ch) {
  251. if(ch=='n' || ch==0xB) { //Vertical Tab偼LF偲摍偟偄
  252. LineFeedRule rule = GetConnection().Param.LineFeedRule;
  253. if(rule==LineFeedRule.Normal || rule==LineFeedRule.LFOnly) {
  254. if(rule==LineFeedRule.LFOnly) //LF偺傒偺摦嶌偱偁傞偲偒
  255. DoCarriageReturn();
  256. DoLineFeed();
  257. }
  258. return ProcessCharResult.Processed;
  259. }
  260. else if(ch=='r') {
  261. LineFeedRule rule = GetConnection().Param.LineFeedRule;
  262. if(rule==LineFeedRule.Normal || rule==LineFeedRule.CROnly) {
  263. DoCarriageReturn();
  264. if(rule==LineFeedRule.CROnly)
  265. DoLineFeed();
  266. }
  267. return ProcessCharResult.Processed;
  268. }
  269. else if(ch==0x07) {
  270. _tag.Receiver.IndicateBell();
  271. return ProcessCharResult.Processed;
  272. }
  273. else if(ch==0x08) {
  274. //峴摢偱丄捈慜峴偺枛旜偑宲懕偱偁偭偨応崌峴傪栠偡
  275. if(_manipulator.CaretColumn==0) {
  276. TerminalDocument doc = GetDocument();
  277. int line = doc.CurrentLineNumber-1;
  278. if(line>=0 && doc.FindLineOrEdge(line).EOLType==EOLType.Continue) {
  279. doc.InvalidateLine(doc.CurrentLineNumber);
  280. doc.CurrentLineNumber = line;
  281. if(doc.CurrentLine==null)
  282. _manipulator.Clear(GetConnection().TerminalWidth);
  283. else
  284. _manipulator.Load(doc.CurrentLine, doc.CurrentLine.CharLength-1);
  285. doc.InvalidateLine(doc.CurrentLineNumber);
  286. }
  287. }
  288. else
  289. _manipulator.BackCaret();
  290. return ProcessCharResult.Processed;
  291. }
  292. else if(ch==0x09) {
  293. _manipulator.CaretColumn = GetNextTabStop(_manipulator.CaretColumn);
  294. return ProcessCharResult.Processed;
  295. }
  296. else if(ch==0x0E) {
  297. return ProcessCharResult.Processed; //埲壓俀偮偼CharDecoder偺拞偱張棟偝傟偰偄傞偼偢側偺偱柍帇
  298. }
  299. else if(ch==0x0F) {
  300. return ProcessCharResult.Processed;
  301. }
  302. else if(ch==0x00) {
  303. return ProcessCharResult.Processed; //null char偼柍帇 !!CR NUL傪CR LF偲傒側偡巇條偑偁傞偑丄CR LF CR NUL偲偔傞偙偲傕偁偭偰擄偟偄
  304. }
  305. else {
  306. //Debug.WriteLine("Unknown char " + (int)ch);
  307. //揔摉側僌儔僼傿僢僋昞帵傎偟偄
  308. return ProcessCharResult.Unsupported;
  309. }
  310. }
  311. private void DoLineFeed() {
  312. GLine nl = _manipulator.Export();
  313. nl.EOLType = (nl.EOLType==EOLType.CR || nl.EOLType==EOLType.CRLF)? EOLType.CRLF : EOLType.LF;
  314. _logger.WriteLine(nl); //儘僌偵峴傪commit
  315. GetDocument().ReplaceCurrentLine(nl);
  316. GetDocument().LineFeed();
  317. //僇儔儉曐帩偼昁梫丅僒儞僾儖:linuxconf.log
  318. int col = _manipulator.CaretColumn;
  319. _manipulator.Load(GetDocument().CurrentLine, col);
  320. }
  321. private void DoCarriageReturn() {
  322. _manipulator.CarriageReturn();
  323. }
  324. protected virtual int GetNextTabStop(int start) {
  325. int t = start;
  326. //t傛傝偱嵟彫偺俉偺攞悢傊傕偭偰偄偔
  327. t += (8 - t % 8);
  328. if(t >= _tag.Connection.TerminalWidth) t = _tag.Connection.TerminalWidth-1;
  329. return t;
  330. }
  331. protected virtual ProcessCharResult ProcessNormalChar(char ch) {
  332. //婛偵夋柺塃抂偵僉儍儗僢僩偑偁傞偺偵暥帤偑棃偨傜夵峴傪偡傞
  333. int tw = _tag.Connection.TerminalWidth;
  334. if(_manipulator.CaretColumn+GLine.CalcDisplayLength(ch) > tw) {
  335. GLine l = _manipulator.Export();
  336. l.EOLType = EOLType.Continue;
  337. GetDocument().ReplaceCurrentLine(l);
  338. GetDocument().LineFeed();
  339. _manipulator.Load(GetDocument().CurrentLine, 0);
  340. }
  341. //夋柺偺儕僒僀僘偑偁偭偨偲偒偼丄_manipulator偺僶僢僼傽僒僀僘偑晄懌偺壜擻惈偑偁傞
  342. if(tw > _manipulator.BufferSize)
  343. _manipulator.ExpandBuffer(tw);
  344. //捠忢暥帤偺張棟
  345. _manipulator.PutChar(ch, _currentdecoration);
  346. return ProcessCharResult.Processed;
  347. }
  348. protected abstract ProcessCharResult ProcessEscapeSequence(char code, char[] seq, int offset);
  349. //FormatException偺傎偐偵OverflowException偺壜擻惈傕偁傞偺偱
  350. protected static int ParseInt(string param, int default_value) {
  351. try {
  352. if(param.Length>0)
  353. return Int32.Parse(param);
  354. else
  355. return default_value;
  356. }
  357. catch(Exception ex) {
  358. throw new UnknownEscapeSequenceException(String.Format("bad number format [{0}] : {1}", param, ex.Message));
  359. }
  360. }
  361. protected static IntPair ParseIntPair(string param, int default_first, int default_second) {
  362. IntPair ret = new IntPair(default_first, default_second);
  363. string[] s = param.Split(';');
  364. if(s.Length >= 1 && s[0].Length>0) {
  365. try {
  366. ret.first = Int32.Parse(s[0]);
  367. }
  368. catch(Exception ex) {
  369. throw new UnknownEscapeSequenceException(String.Format("bad number format [{0}] : {1}", s[0], ex.Message));
  370. }
  371. }
  372. if(s.Length >= 2 && s[1].Length>0) {
  373. try {
  374. ret.second = Int32.Parse(s[1]);
  375. }
  376. catch(Exception ex) {
  377. throw new UnknownEscapeSequenceException(String.Format("bad number format [{0}] : {1}", s[1], ex.Message));
  378. }
  379. }
  380. return ret;
  381. }
  382. }
  383. }