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

Telnet服务器

开发平台:

C#

  1. /*
  2. * Copyright (c) 2005 Poderosa Project, All Rights Reserved.
  3. * $Id: XTerm.cs,v 1.2 2005/04/20 08:45:48 okajima Exp $
  4. */
  5. using System;
  6. using System.Collections;
  7. using System.IO;
  8. using System.Text;
  9. using System.Diagnostics;
  10. using System.Drawing;
  11. using System.Windows.Forms;
  12. using Poderosa.Connection;
  13. using Poderosa.Text;
  14. namespace Poderosa.Terminal
  15. {
  16. internal class XTerm : VT100Terminal
  17. {
  18. protected bool _wrapAroundMode;
  19. protected bool[] _tabStops;
  20. protected ArrayList _savedScreen; //暿偺僶僢僼傽偵埲崀偟偨偲偒偵GLine傪戅旔偟偰偍偔
  21. public XTerm(ConnectionTag tag, ICharDecoder decoder) : base(tag, decoder) {
  22. _wrapAroundMode = true;
  23. _tabStops = new bool[tag.Connection.TerminalWidth];
  24. InitTabStops();
  25. }
  26. protected override ProcessCharResult ProcessNormalChar(char ch) {
  27. //WrapAround偑false偱丄僉儍儗僢僩偑塃抂偺偲偒偼壗傕偟側偄
  28. if(!_wrapAroundMode && _manipulator.CaretColumn>=GetConnection().TerminalWidth-1)
  29. return ProcessCharResult.Processed;
  30. if(_insertMode)
  31. _manipulator.InsertBlanks(_manipulator.CaretColumn, GLine.CalcDisplayLength(ch));
  32. return base.ProcessNormalChar(ch);
  33. }
  34. protected override ProcessCharResult ProcessControlChar(char ch) {
  35. return base.ProcessControlChar(ch);
  36. /* 暥帤僐乕僪偑岆偭偰偄傞偲偙偺偁偨傝傪晄堄偵幚峴偟偰偟傑偆偙偲偑偁傝丄傛傠偟偔側偄丅
  37. switch(ch) {
  38. //扨弮側曄姺側傜懠偵傕偱偒傞偑丄僒億乕僩偟偰偄傞偺偼偄傑偺偲偙傠偙傟偟偐側偄
  39. case (char)0x8D:
  40. base.ProcessChar((char)0x1B);
  41. base.ProcessChar('M');
  42. return ProcessCharResult.Processed;
  43. case (char)0x9B:
  44. base.ProcessChar((char)0x1B);
  45. base.ProcessChar('[');
  46. return ProcessCharResult.Processed;
  47. case (char)0x9D:
  48. base.ProcessChar((char)0x1B);
  49. base.ProcessChar(']');
  50. return ProcessCharResult.Processed;
  51. default:
  52. return base.ProcessControlChar(ch);
  53. }
  54. */
  55. }
  56. protected override ProcessCharResult ProcessEscapeSequence(char code, char[] seq, int offset) {
  57. ProcessCharResult v = base.ProcessEscapeSequence(code, seq, offset);
  58. if(v!=ProcessCharResult.Unsupported) return v;
  59. switch(code) {
  60. case 'F':
  61. if(seq.Length==offset) { //僷儔儊乕僞側偟偺応崌
  62. ProcessCursorPosition(1, 1);
  63. return ProcessCharResult.Processed;
  64. }
  65. else if(seq.Length>offset && seq[offset]==' ')
  66. return ProcessCharResult.Processed; //7/8價僢僩僐儞僩儘乕儖偼忢偵椉曽傪僒億乕僩
  67. break;
  68. case 'G':
  69. if(seq.Length>offset && seq[offset]==' ')
  70. return ProcessCharResult.Processed; //7/8價僢僩僐儞僩儘乕儖偼忢偵椉曽傪僒億乕僩
  71. break;
  72. case 'L':
  73. if(seq.Length>offset && seq[offset]==' ')
  74. return ProcessCharResult.Processed; //VT100偼嵟弶偐傜OK
  75. break;
  76. case 'H':
  77. SetTabStop(_manipulator.CaretColumn, true);
  78. return ProcessCharResult.Processed;
  79. }
  80. return ProcessCharResult.Unsupported;
  81. }
  82. protected override ProcessCharResult ProcessAfterCSI(string param, char code) {
  83. ProcessCharResult v = base.ProcessAfterCSI(param, code);
  84. if(v!=ProcessCharResult.Unsupported) return v;
  85. switch(code) {
  86. case 'd':
  87. ProcessLinePositionAbsolute(param);
  88. return ProcessCharResult.Processed;
  89. case 'G':
  90. case '`': //CSI G偼幚嵺偵棃偨偙偲偑偁傞偑丄偙傟偼棃偨偙偲偑側偄丅偄偄偺偐丠
  91. ProcessLineColumnAbsolute(param);
  92. return ProcessCharResult.Processed;
  93. case 'X':
  94. ProcessEraseChars(param);
  95. return ProcessCharResult.Processed;
  96. case 'P':
  97. _manipulator.DeleteChars(_manipulator.CaretColumn, ParseInt(param,1));
  98. return ProcessCharResult.Processed;
  99. case 'p':
  100. return SoftTerminalReset(param);
  101. case '@':
  102. _manipulator.InsertBlanks(_manipulator.CaretColumn, ParseInt(param,1));
  103. return ProcessCharResult.Processed;
  104. case 'I':
  105. ProcessForwardTab(param);
  106. return ProcessCharResult.Processed;
  107. case 'Z':
  108. ProcessBackwardTab(param);
  109. return ProcessCharResult.Processed;
  110. case 'S':
  111. ProcessScrollUp(param);
  112. return ProcessCharResult.Processed;
  113. case 'T':
  114. ProcessScrollDown(param);
  115. return ProcessCharResult.Processed;
  116. case 'g':
  117. ProcessTabClear(param);
  118. return ProcessCharResult.Processed;
  119. case 't':
  120. //!!僷儔儊乕僞偵傛偭偰柍帇偟偰傛偄応崌偲丄墳摎傪曉偡傋偒応崌偑偁傞丅墳摎偺曉偟曽偑傛偔傢偐傜側偄偺偱曐棷拞
  121. return ProcessCharResult.Processed;
  122. case 'U': //偙傟偼SFU偱偟偐妋擣偱偒偰側偄
  123. base.ProcessCursorPosition(GetConnection().TerminalHeight, 1);
  124. return ProcessCharResult.Processed;
  125. case 'u': //SFU偱偺傒妋擣丅摿偵b偼懕偔暥帤傪孞傝曉偡傜偟偄偑丄堄枴偺偁傞摦嶌偵側偭偰偄傞偲偙傠傪尒偰偄側偄
  126. case 'b':
  127. return ProcessCharResult.Processed;
  128. default:
  129. return ProcessCharResult.Unsupported;
  130. }
  131. }
  132. protected override void ProcessDeviceAttributes(string param) {
  133. if(param.StartsWith(">")) {
  134. byte[] data = Encoding.ASCII.GetBytes(" [>82;1;0c");
  135. data[0] = 0x1B; //ESC
  136. GetConnection().Write(data);
  137. }
  138. else
  139. base.ProcessDeviceAttributes(param);
  140. }
  141. protected override ProcessCharResult ProcessAfterOSC(string param, char code) {
  142. ProcessCharResult v = base.ProcessAfterOSC(param, code);
  143. if(v!=ProcessCharResult.Unsupported) return v;
  144. int semicolon = param.IndexOf(';');
  145. if(semicolon==-1) return ProcessCharResult.Unsupported;
  146. string ps = param.Substring(0, semicolon);
  147. string pt = param.Substring(semicolon+1);
  148. if(ps=="0" || ps=="2") {
  149. if(pt!=_tag.WindowTitle) {
  150. _tag.WindowTitle = pt;
  151. if(GEnv.Options.AdjustsTabTitleToWindowTitle)
  152. _tag.Connection.Param.Caption = pt;
  153. GEnv.InterThreadUIService.RefreshConnection(_tag);
  154. }
  155. return ProcessCharResult.Processed;
  156. }
  157. else if(ps=="1")
  158. return ProcessCharResult.Processed; //Set Icon Name偲偄偆傗偮偩偑柍帇偱傛偝偦偆
  159. else
  160. return ProcessCharResult.Unsupported;
  161. }
  162. protected override ProcessCharResult ProcessDECSET(string param, char code) {
  163. ProcessCharResult v = base.ProcessDECSET(param, code);
  164. if(v!=ProcessCharResult.Unsupported) return v;
  165. if(param=="1047") { //Screen Buffer: 偲偔偵摿暿側偙偲偼偟側偄
  166. return ProcessCharResult.Processed;
  167. }
  168. else if(param=="1048" || param=="1049") { //Save/Restore Cursor
  169. return ProcessCharResult.Processed;
  170. }
  171. else if(param=="1000" || param=="1001" || param=="1002" || param=="1003") { //儅僂僗娭學偼柍帇
  172. return ProcessCharResult.Processed;
  173. }
  174. else if(param=="3") { //132 Column Mode
  175. return ProcessCharResult.Processed;
  176. }
  177. else if(param=="4") { //Smooth Scroll 側傫偺偙偲傗傜
  178. return ProcessCharResult.Processed;
  179. }
  180. else if(param=="6") { //Origin Mode
  181. _scrollRegionRelative = code=='h';
  182. return ProcessCharResult.Processed;
  183. }
  184. else if(param=="7") {
  185. _wrapAroundMode = code=='h';
  186. return ProcessCharResult.Processed;
  187. }
  188. else if(param=="47") {
  189. if(code=='h')
  190. SaveScreen();
  191. else
  192. RestoreScreen();
  193. return ProcessCharResult.Processed;
  194. }
  195. else
  196. return ProcessCharResult.Unsupported;
  197. }
  198. private void ProcessLinePositionAbsolute(string param) {
  199. foreach(string p in param.Split(';')) {
  200. int row = ParseInt(p,1);
  201. if(row<1) row = 1;
  202. if(row>GetConnection().TerminalHeight) row = GetConnection().TerminalHeight;
  203. int col = _manipulator.CaretColumn;
  204. //埲壓偼CSI H偲傎傏摨偠
  205. GetDocument().ReplaceCurrentLine(_manipulator.Export());
  206. GetDocument().CurrentLineNumber = (GetDocument().TopLineNumber + row - 1);
  207. _manipulator.Load(GetDocument().CurrentLine, col);
  208. }
  209. }
  210. private void ProcessLineColumnAbsolute(string param) {
  211. foreach(string p in param.Split(';')) {
  212. int n = ParseInt(p,1);
  213. if(n<1) n = 1;
  214. if(n>GetConnection().TerminalWidth) n = GetConnection().TerminalWidth;
  215. _manipulator.CaretColumn = n-1;
  216. }
  217. }
  218. private void ProcessEraseChars(string param) {
  219. int n = ParseInt(param, 1);
  220. int s = _manipulator.CaretColumn;
  221. for(int i=0; i<n; i++) {
  222. _manipulator.PutChar(' ', _currentdecoration);
  223. if(_manipulator.CaretColumn>=_manipulator.BufferSize)
  224. break;
  225. }
  226. _manipulator.CaretColumn = s;
  227. }
  228. private void ProcessScrollUp(string param) {
  229. int d = ParseInt(param, 1);
  230. TerminalDocument doc = GetDocument();
  231. int caret_col = _manipulator.CaretColumn;
  232. int offset = doc.CurrentLineNumber - doc.TopLineNumber;
  233. GLine nl = _manipulator.Export();
  234. doc.ReplaceCurrentLine(nl);
  235. if(doc.ScrollingBottom==-1)
  236. doc.SetScrollingRegion(0, GetConnection().TerminalHeight-1);
  237. for(int i=0; i<d; i++) {
  238. doc.ScrollUp(doc.CurrentLineNumber, doc.ScrollingBottom);
  239. doc.CurrentLineNumber = doc.TopLineNumber + offset;
  240. }
  241. _manipulator.Load(doc.CurrentLine, caret_col);
  242. }
  243. private void ProcessScrollDown(string param) {
  244. int d = ParseInt(param, 1);
  245. TerminalDocument doc = GetDocument();
  246. int caret_col = _manipulator.CaretColumn;
  247. int offset = doc.CurrentLineNumber - doc.TopLineNumber;
  248. GLine nl = _manipulator.Export();
  249. doc.ReplaceCurrentLine(nl);
  250. if(doc.ScrollingBottom==-1)
  251. doc.SetScrollingRegion(0, GetConnection().TerminalHeight-1);
  252. for(int i=0; i<d; i++) {
  253. doc.ScrollDown(doc.CurrentLineNumber, doc.ScrollingBottom);
  254. doc.CurrentLineNumber = doc.TopLineNumber + offset;
  255. }
  256. _manipulator.Load(doc.CurrentLine, caret_col);
  257. }
  258. private void ProcessForwardTab(string param) {
  259. int n = ParseInt(param, 1);
  260. int t = _manipulator.CaretColumn;
  261. for(int i=0; i<n; i++)
  262. t = GetNextTabStop(t);
  263. if(t >= GetConnection().TerminalWidth) t = GetConnection().TerminalWidth-1;
  264. _manipulator.CaretColumn = t;
  265. }
  266. private void ProcessBackwardTab(string param) {
  267. int n = ParseInt(param, 1);
  268. int t = _manipulator.CaretColumn;
  269. for(int i=0; i<n; i++)
  270. t = GetPrevTabStop(t);
  271. if(t < 0) t = 0;
  272. _manipulator.CaretColumn = t;
  273. }
  274. private void ProcessTabClear(string param) {
  275. if(param=="0")
  276. SetTabStop(_manipulator.CaretColumn, false);
  277. else if(param=="3")
  278. ClearAllTabStop();
  279. }
  280. private void InitTabStops() {
  281. for(int i=0; i<_tabStops.Length; i++) {
  282. _tabStops[i] = (i % 8)==0;
  283. }
  284. }
  285. private void EnsureTabStops(int length) {
  286. if(length>=_tabStops.Length) {
  287. bool[] newarray = new bool[Math.Max(length, _tabStops.Length*2)];
  288. Array.Copy(_tabStops, 0, newarray, 0, _tabStops.Length);
  289. for(int i=_tabStops.Length; i<newarray.Length; i++) {
  290. newarray[i] = (i % 8)==0;
  291. }
  292. _tabStops = newarray;
  293. }
  294. }
  295. private void SetTabStop(int index, bool value) {
  296. EnsureTabStops(index+1);
  297. _tabStops[index] = value;
  298. }
  299. private void ClearAllTabStop() {
  300. for(int i=0; i<_tabStops.Length; i++) {
  301. _tabStops[i] = false;
  302. }
  303. }
  304. protected override int GetNextTabStop(int start) {
  305. EnsureTabStops(Math.Max(start+1, _tag.Connection.TerminalWidth));
  306. int index = start+1;
  307. while(index<_tag.Connection.TerminalWidth) {
  308. if(_tabStops[index]) return index;
  309. index++;
  310. }
  311. return _tag.Connection.TerminalWidth-1;
  312. }
  313. //偙傟偼vt100偵偼側偄偺偱override偟側偄
  314. protected int GetPrevTabStop(int start) {
  315. EnsureTabStops(start+1);
  316. int index = start-1;
  317. while(index>0) {
  318. if(_tabStops[index]) return index;
  319. index--;
  320. }
  321. return 0;
  322. }
  323. protected void SaveScreen() {
  324. _savedScreen = new ArrayList();
  325. GLine l = GetDocument().TopLine;
  326. int m = l.ID + GetConnection().TerminalHeight;
  327. while(l!=null && l.ID<m) {
  328. _savedScreen.Add(l.Clone());
  329. l = l.NextLine;
  330. }
  331. }
  332. protected void RestoreScreen() {
  333. if(_savedScreen==null) return;
  334. TerminalDocument doc = GetDocument();
  335. int w = GetConnection().TerminalWidth;
  336. int m = GetConnection().TerminalHeight;
  337. GLine t = doc.TopLine;
  338. foreach(GLine l in _savedScreen) {
  339. l.ExpandBuffer(w);
  340. if(t==null)
  341. doc.AddLine(l);
  342. else {
  343. doc.Replace(t, l);
  344. t = l.NextLine;
  345. }
  346. if(--m == 0) break;
  347. }
  348. _savedScreen = null;
  349. }
  350. private ProcessCharResult SoftTerminalReset(string param){
  351. if(param=="!") {
  352. FullReset();
  353. return ProcessCharResult.Processed;
  354. }
  355. else
  356. return ProcessCharResult.Unsupported;
  357. }
  358. public override byte[] SequenceKeyData(Keys modifier, Keys key) {
  359. if((int)Keys.F1 <= (int)key && (int)key <= (int)Keys.F12)
  360. return base.SequenceKeyData(modifier, key);
  361. else if(GUtil.IsCursorKey(key))
  362. return base.SequenceKeyData(modifier, key);
  363. else {
  364. byte[] r = new byte[4];
  365. r[0] = 0x1B;
  366. r[1] = (byte)'[';
  367. r[3] = (byte)'~';
  368. //偙偺偁偨傝偼xterm偱偼妱偲堘偆傛偆偩
  369. if(key==Keys.Insert)
  370. r[2] = (byte)'2';
  371. else if(key==Keys.Home)
  372. r[2] = (byte)'7';
  373. else if(key==Keys.PageUp)
  374. r[2] = (byte)'5';
  375. else if(key==Keys.Delete)
  376. r[2] = (byte)'3';
  377. else if(key==Keys.End)
  378. r[2] = (byte)'8';
  379. else if(key==Keys.PageDown)
  380. r[2] = (byte)'6';
  381. else
  382. throw new ArgumentException("unknown key " + key.ToString());
  383. return r;
  384. }
  385. }
  386. public override void FullReset() {
  387. InitTabStops();
  388. base.FullReset();
  389. }
  390. }
  391. }