TerminalBase.cs
上传用户:szltgg
上传日期:2019-05-16
资源大小:604k
文件大小:14k
- /*
- * Copyright (c) 2005 Poderosa Project, All Rights Reserved.
- * $Id: TerminalBase.cs,v 1.2 2005/04/20 08:45:47 okajima Exp $
- */
- using System;
- using System.Collections;
- using System.IO;
- using System.Text;
- using System.Threading;
- using System.Diagnostics;
- using System.Windows.Forms;
- using Poderosa.Log;
- using Poderosa.Config;
- using Poderosa.Connection;
- using Poderosa.ConnectionParam;
- using Poderosa.Text;
- using Poderosa.Communication;
- namespace Poderosa.Terminal
- {
- /// <summary>
- /// 僞乕儈僫儖
- /// 僨乕僞傪庴怣偟偰僪僉儏儊儞僩傪憖嶌偡傞婡擻傪傕偮丅
- /// </summary>
- internal abstract class AbstractTerminal : ITerminal {
- public abstract void ProcessChar(char ch);
- public abstract ProcessCharResult State { get; }
- public abstract byte[] SequenceKeyData(Keys modifier, Keys body);
- protected StringBuilder _bufferForMacro;
- protected AutoResetEvent _signalForMacro; //儅僋儘僗儗僢僪偵僨乕僞偺撉傒庢傝壜擻傪抦傜偣傞
- protected ICharDecoder _decoder;
- protected GLineManipulator _manipulator;
- protected ITerminalTextLogger _logger; //Logger僾儘僷僥傿偲偺廳暋傪壗偲偐偟偨偄
- public ITerminalTextLogger Logger {
- get {
- return _tag.Connection.TextLogger;
- }
- }
- protected ConnectionTag _tag;
- protected TextDecoration _currentdecoration;
-
- protected TerminalMode _terminalMode;
- protected TerminalMode _cursorKeyMode; //_terminalMode偼暿暔丅AIX偱偺vi偱丄僇乕僜儖僉乕偼晄曄偲偄偆椺偑妋擣偝傟偰偄傞
- public TerminalMode TerminalMode {
- get {
- return _terminalMode;
- }
- }
- public TerminalMode CursorKeyMode {
- get {
- return _cursorKeyMode;
- }
- }
- protected TerminalConnection GetConnection() {
- return _tag.Connection;
- }
- protected TerminalDocument GetDocument() {
- return _tag.Document;
- }
- protected abstract void ChangeMode(TerminalMode tm);
- protected abstract void ResetInternal();
- protected virtual void ChangeCursorKeyMode(TerminalMode tm) {
- _cursorKeyMode = tm;
- }
- /// <summary>
- /// 憖嶌偺懳徾偵側傞僪僉儏儊儞僩偲暥帤偺僄儞僐乕僨傿儞僌傪巜掕偟偰峔抸
- /// </summary>
- public AbstractTerminal(ConnectionTag tag, ICharDecoder decoder) {
- _tag = tag;
- _decoder = decoder;
- _terminalMode = TerminalMode.Normal;
- _currentdecoration = TextDecoration.Default;
- _manipulator = new GLineManipulator(80);
- _bufferForMacro = new StringBuilder();
- _signalForMacro = new AutoResetEvent(false);
- }
- public void Input(byte[] data, int offset, int length) {
- _manipulator.Load(GetDocument().CurrentLine, 0);
- _manipulator.CaretColumn = GetDocument().CaretColumn;
- _manipulator.DefaultDecoration = _currentdecoration;
-
- _decoder.Input(this, data, offset, length);
- GetDocument().ReplaceCurrentLine(_manipulator.Export());
- GetDocument().CaretColumn = _manipulator.CaretColumn;
- }
- public void Input(char[] data, int offset, int length) {
- _manipulator.Load(GetDocument().CurrentLine, 0);
- _manipulator.CaretColumn = GetDocument().CaretColumn;
- _manipulator.DefaultDecoration = _currentdecoration;
-
- for(int i=0; i<length; i++)
- ProcessChar(data[offset+i]);
- GetDocument().ReplaceCurrentLine(_manipulator.Export());
- GetDocument().CaretColumn = _manipulator.CaretColumn;
- }
- public void UnsupportedCharSetDetected(char code) {
- string desc;
- if(code=='0')
- desc = "0 (DEC Special Character)"; //偙傟偼傛偔偁傞偺偱扐偟彂偒偮偒
- else
- desc = new String(code, 1);
- if(GEnv.Options.WarningOption!=WarningOption.Ignore) {
- GEnv.InterThreadUIService.UnsupportedCharSetDetected(GetDocument(), String.Format(GEnv.Strings.GetString("Message.AbstractTerminal.UnsupportedCharSet"), desc));
- }
- }
- public void InvalidCharDetected(Encoding enc, byte[] buf) {
- if(GEnv.Options.WarningOption!=WarningOption.Ignore) {
- GEnv.InterThreadUIService.InvalidCharDetected(GetDocument(), String.Format(GEnv.Strings.GetString("Message.AbstractTerminal.UnexpectedChar"), enc.WebName));
- }
- }
- public void Reset() {
- //Encoding偑摨偠帪偼娙扨偵嵪傑偣傞偙偲偑偱偒傞
- if(_decoder.Encoding.Type==_tag.Connection.Param.Encoding)
- _decoder.Reset(_decoder.Encoding);
- else
- _decoder = new JapaneseCharDecoder(_tag.Connection);
- }
- //public void SetEncoding(EncodingProfile enc) {
- // _decoder.SetEncoding(enc);
- //}
- public void ClearMacroBuffer() {
- _bufferForMacro.Remove(0, _bufferForMacro.Length);
- _signalForMacro.Reset();
- }
- public void SignalData() {
- _signalForMacro.Set();
- }
- protected void AppendMacroBuffer(char ch) {
- if(ch!='r' && ch!=' ') {
- lock(_bufferForMacro) {
- _bufferForMacro.Append(ch); //!!挿偝偵忋尷傪偮偗偨傎偆偑埨慡偐傕
- }
- }
- }
- //儅僋儘幚峴僗儗僢僪偐傜屇偽傟傞侾峴撉傒弌偟儊僜僢僪
- public string ReadLineFromMacroBuffer() {
- do {
- int l = _bufferForMacro.Length;
- int i=0;
- for(i=0; i<l; i++) {
- if(_bufferForMacro[i]=='n') break;
- }
- if(l>0 && i<l) { //傔偱偨偔峴枛偑傒偮偐偭偨
- int j=i;
- if(i>0 && _bufferForMacro[i-1]=='r') j=i-1; //CRLF偺偲偒偼彍偄偰傗傞
- string r;
- lock(_bufferForMacro) {
- r = _bufferForMacro.ToString(0, j);
- _bufferForMacro.Remove(0, i+1);
- }
- return r;
- }
- else {
- _signalForMacro.Reset();
- _signalForMacro.WaitOne();
- }
- } while(true);
- }
- //儅僋儘幚峴僗儗僢僪偐傜屇偽傟傞丄乽壗偐僨乕僞偑偁傟偽慡晹傕偭偰偄偔乿儊僜僢僪
- public string ReadAllFromMacroBuffer() {
- if(_bufferForMacro.Length==0) {
- _signalForMacro.Reset();
- _signalForMacro.WaitOne();
- }
- lock(_bufferForMacro) {
- string r = _bufferForMacro.ToString();
- _bufferForMacro.Remove(0, _bufferForMacro.Length);
- return r;
- }
- }
- //偙傟偼儊僀儞僗儗僢僪偐傜屇傃弌偡偙偲
- public virtual void FullReset() {
- lock(_tag.Document) {
- ChangeMode(TerminalMode.Normal);
- _tag.Document.ClearScrollingRegion();
- ResetInternal();
- _decoder = new JapaneseCharDecoder(_tag.Connection);
- }
- }
- public void DumpCurrentText() {
- Debug.WriteLine(_manipulator.ToString());
- }
- }
-
- //Escape Sequence傪巊偆僞乕儈僫儖
- internal abstract class EscapeSequenceTerminal : AbstractTerminal {
- public EscapeSequenceTerminal(ConnectionTag tag, ICharDecoder decoder) : base(tag, decoder) {
- _escapeSequence = new StringBuilder();
- _processCharResult = ProcessCharResult.Processed;
- }
- private StringBuilder _escapeSequence;
- private ProcessCharResult _processCharResult;
- public override ProcessCharResult State {
- get {
- return _processCharResult;
- }
- }
- protected override void ResetInternal() {
- _escapeSequence = new StringBuilder();
- _processCharResult = ProcessCharResult.Processed;
- }
- public override void ProcessChar(char ch) {
-
- _logger = Logger; //_logger偼偙偺ProcessChar偺張棟撪偱偺傒桳岠丅
-
- if(_processCharResult != ProcessCharResult.Escaping) {
- if(ch==0x1B) {
- _processCharResult = ProcessCharResult.Escaping;
- } else {
- //!!媣偟傇傝偺偙偺偁偨傝傪尒傞偲偗偭偙偆墭偄暘婒偩側
- _logger.Append(ch);
- if(GEnv.Frame.MacroIsRunning) AppendMacroBuffer(ch);
- if(ch < 0x20 || (ch>=0x80 && ch<0xA0))
- _processCharResult = ProcessControlChar(ch);
- else
- _processCharResult = ProcessNormalChar(ch);
- }
- }
- else {
- if(ch==' ') return; //僔乕働儞僗拞偵NULL暥帤偑擖偭偰偄傞働乕僗偑妋擣偝傟偨
- _escapeSequence.Append(ch);
- bool end_flag = false; //escape sequence偺廔傢傝偐偳偆偐傪帵偡僼儔僌
- if(_escapeSequence.Length==1) { //ESC+侾暥帤偱偁傞応崌
- end_flag = ('0'<=ch && ch<='9') || ('a'<=ch && ch<='z') || ('A'<=ch && ch<='Z') || ch=='>' || ch=='=' || ch=='|' || ch=='}' || ch=='~';
- }
- else if(_escapeSequence[0]==']') { //OSC偺廔抂偼BEL偐ST(String Terminator)
- end_flag = ch==0x07 || ch==0x9c;
- }
- else {
- end_flag = ('a'<=ch && ch<='z') || ('A'<=ch && ch<='Z') || ch=='@' || ch=='~' || ch=='|' || ch=='{';
- }
-
- if(end_flag) { //僔乕働儞僗偺偍傢傝
- char[] seq = _escapeSequence.ToString().ToCharArray();
- _logger.BeginEscapeSequence();
- _logger.Append(seq, 0, seq.Length);
- _logger.CommitEscapeSequence();
- _logger.Flush();
- try {
- char code = seq[0];
- _processCharResult = ProcessCharResult.Unsupported; //ProcessEscapeSequence偱椺奜偑棃偨屻偱忬懺偑Escaping偼傂偳偄寢壥傪彽偔偺偱
- _processCharResult = ProcessEscapeSequence(code, seq, 1);
- if(_processCharResult==ProcessCharResult.Unsupported)
- throw new UnknownEscapeSequenceException(String.Format("ESC {0}", new string(seq)));
- }
- catch(UnknownEscapeSequenceException ex) {
- if(GEnv.Options.WarningOption!=Poderosa.Config.WarningOption.Ignore)
- GEnv.InterThreadUIService.UnsupportedEscapeSequence(GetDocument(), GEnv.Strings.GetString("Message.EscapesequenceTerminal.UnsupportedSequence")+ex.Message);
- }
- finally {
- _escapeSequence.Remove(0, _escapeSequence.Length);
- }
- }
- else
- _processCharResult = ProcessCharResult.Escaping;
- }
- }
- protected virtual ProcessCharResult ProcessControlChar(char ch) {
- if(ch=='n' || ch==0xB) { //Vertical Tab偼LF偲摍偟偄
- LineFeedRule rule = GetConnection().Param.LineFeedRule;
- if(rule==LineFeedRule.Normal || rule==LineFeedRule.LFOnly) {
- if(rule==LineFeedRule.LFOnly) //LF偺傒偺摦嶌偱偁傞偲偒
- DoCarriageReturn();
- DoLineFeed();
- }
- return ProcessCharResult.Processed;
- }
- else if(ch=='r') {
- LineFeedRule rule = GetConnection().Param.LineFeedRule;
- if(rule==LineFeedRule.Normal || rule==LineFeedRule.CROnly) {
- DoCarriageReturn();
- if(rule==LineFeedRule.CROnly)
- DoLineFeed();
- }
- return ProcessCharResult.Processed;
- }
- else if(ch==0x07) {
- _tag.Receiver.IndicateBell();
- return ProcessCharResult.Processed;
- }
- else if(ch==0x08) {
- //峴摢偱丄捈慜峴偺枛旜偑宲懕偱偁偭偨応崌峴傪栠偡
- if(_manipulator.CaretColumn==0) {
- TerminalDocument doc = GetDocument();
- int line = doc.CurrentLineNumber-1;
- if(line>=0 && doc.FindLineOrEdge(line).EOLType==EOLType.Continue) {
- doc.InvalidateLine(doc.CurrentLineNumber);
- doc.CurrentLineNumber = line;
- if(doc.CurrentLine==null)
- _manipulator.Clear(GetConnection().TerminalWidth);
- else
- _manipulator.Load(doc.CurrentLine, doc.CurrentLine.CharLength-1);
- doc.InvalidateLine(doc.CurrentLineNumber);
- }
- }
- else
- _manipulator.BackCaret();
- return ProcessCharResult.Processed;
- }
- else if(ch==0x09) {
- _manipulator.CaretColumn = GetNextTabStop(_manipulator.CaretColumn);
- return ProcessCharResult.Processed;
- }
- else if(ch==0x0E) {
- return ProcessCharResult.Processed; //埲壓俀偮偼CharDecoder偺拞偱張棟偝傟偰偄傞偼偢側偺偱柍帇
- }
- else if(ch==0x0F) {
- return ProcessCharResult.Processed;
- }
- else if(ch==0x00) {
- return ProcessCharResult.Processed; //null char偼柍帇 !!CR NUL傪CR LF偲傒側偡巇條偑偁傞偑丄CR LF CR NUL偲偔傞偙偲傕偁偭偰擄偟偄
- }
- else {
- //Debug.WriteLine("Unknown char " + (int)ch);
- //揔摉側僌儔僼傿僢僋昞帵傎偟偄
- return ProcessCharResult.Unsupported;
- }
- }
- private void DoLineFeed() {
- GLine nl = _manipulator.Export();
- nl.EOLType = (nl.EOLType==EOLType.CR || nl.EOLType==EOLType.CRLF)? EOLType.CRLF : EOLType.LF;
- _logger.WriteLine(nl); //儘僌偵峴傪commit
- GetDocument().ReplaceCurrentLine(nl);
- GetDocument().LineFeed();
-
- //僇儔儉曐帩偼昁梫丅僒儞僾儖:linuxconf.log
- int col = _manipulator.CaretColumn;
- _manipulator.Load(GetDocument().CurrentLine, col);
- }
- private void DoCarriageReturn() {
- _manipulator.CarriageReturn();
- }
- protected virtual int GetNextTabStop(int start) {
- int t = start;
- //t傛傝偱嵟彫偺俉偺攞悢傊傕偭偰偄偔
- t += (8 - t % 8);
- if(t >= _tag.Connection.TerminalWidth) t = _tag.Connection.TerminalWidth-1;
- return t;
- }
-
- protected virtual ProcessCharResult ProcessNormalChar(char ch) {
- //婛偵夋柺塃抂偵僉儍儗僢僩偑偁傞偺偵暥帤偑棃偨傜夵峴傪偡傞
- int tw = _tag.Connection.TerminalWidth;
- if(_manipulator.CaretColumn+GLine.CalcDisplayLength(ch) > tw) {
- GLine l = _manipulator.Export();
- l.EOLType = EOLType.Continue;
- GetDocument().ReplaceCurrentLine(l);
- GetDocument().LineFeed();
- _manipulator.Load(GetDocument().CurrentLine, 0);
- }
- //夋柺偺儕僒僀僘偑偁偭偨偲偒偼丄_manipulator偺僶僢僼傽僒僀僘偑晄懌偺壜擻惈偑偁傞
- if(tw > _manipulator.BufferSize)
- _manipulator.ExpandBuffer(tw);
- //捠忢暥帤偺張棟
- _manipulator.PutChar(ch, _currentdecoration);
-
- return ProcessCharResult.Processed;
- }
- protected abstract ProcessCharResult ProcessEscapeSequence(char code, char[] seq, int offset);
- //FormatException偺傎偐偵OverflowException偺壜擻惈傕偁傞偺偱
- protected static int ParseInt(string param, int default_value) {
- try {
- if(param.Length>0)
- return Int32.Parse(param);
- else
- return default_value;
- }
- catch(Exception ex) {
- throw new UnknownEscapeSequenceException(String.Format("bad number format [{0}] : {1}", param, ex.Message));
- }
- }
- protected static IntPair ParseIntPair(string param, int default_first, int default_second) {
- IntPair ret = new IntPair(default_first, default_second);
- string[] s = param.Split(';');
-
- if(s.Length >= 1 && s[0].Length>0) {
- try {
- ret.first = Int32.Parse(s[0]);
- }
- catch(Exception ex) {
- throw new UnknownEscapeSequenceException(String.Format("bad number format [{0}] : {1}", s[0], ex.Message));
- }
- }
- if(s.Length >= 2 && s[1].Length>0) {
- try {
- ret.second = Int32.Parse(s[1]);
- }
- catch(Exception ex) {
- throw new UnknownEscapeSequenceException(String.Format("bad number format [{0}] : {1}", s[1], ex.Message));
- }
- }
- return ret;
- }
- }
- }