//これを送ってくるアプリケーションは viで上方スクロール protected void ProcessInsertLines(string param) { int d = ParseInt(param, 1); /* * TerminalDocument doc = GetDocument(); * for(int i=0; i<d; i++) * doc.InsertAfter(doc.CurrentLine, new GLine(GetConnection().TerminalWidth)); */ TerminalDocument doc = GetDocument(); int caret_pos = _manipulator.CaretColumn; int offset = doc.CurrentLineNumber - doc.TopLineNumber; GLine nl = _manipulator.Export(); doc.ReplaceCurrentLine(nl); if (doc.ScrollingBottom == -1) { doc.SetScrollingRegion(0, GetConnection().TerminalHeight - 1); } for (int i = 0; i < d; i++) { doc.ScrollUp(doc.CurrentLineNumber, doc.ScrollingBottom); doc.CurrentLineNumber = doc.TopLineNumber + offset; } _manipulator.Load(doc.CurrentLine, caret_pos); }
//ポップアップ対象の行を集めて構築。ここは受信スレッドでの実行であることに注意 private void ProcessCommandResult(int end_line_id) { List <GLine> result = new List <GLine>(); TerminalDocument doc = _terminal.GetDocument(); GLine line = doc.FindLineOrNull(_commandStartLineID); while (line != null && line.ID <= end_line_id) { //Debug.WriteLine("P]"+new string(line.Text, 0, line.DisplayLength)); result.Add(line); line = line.NextLine; } //何かとれていたら実行 if (result.Count > 0) { _currentProcessor.EndCommand(result); } else { Debug.WriteLineIf(DebugOpt.CommandPopup, String.Format("Ignored for 0-length, start={0} end={1}", _commandStartLineID, end_line_id)); } _currentProcessor = null; }
private void CheckDiscardDocument() { //mwg20111225 // ApplicationMode でも上から流れて出て行く様に変更した為、ちゃんと discard しないといけない。 // * それとは別に、CheckDiscardDocument を呼び出すタイミングが OnReception である事も疑問である。 // OnReception というよりは Document の(行数)変更時にチェックするべきではないのか? // →データを 4KB 単位で受け取っている為、此方の方が呼び出される回数が少ないので妥当 if (_session == null) { return; } //if(_session==null || _terminalMode==TerminalMode.Application) return; TerminalDocument document = _document; int del = document.DiscardOldLines(GEnv.Options.TerminalBufferSize + document.TerminalHeight); if (del > 0) { int newvalue = _scrollBarValues.Value - del; if (newvalue < 0) { newvalue = 0; } _scrollBarValues.Value = newvalue; document.InvalidatedRegion.InvalidatedAll = true; //本当はここまでしなくても良さそうだが念のため } }
private void RestoreScreen(int sw) { if (_savedScreen[sw] == null) { ClearScreen(); // emulate new buffer return; } TerminalDocument doc = GetDocument(); int w = doc.TerminalWidth; int m = doc.TerminalHeight; GLine t = doc.TopLine; foreach (GLine l in _savedScreen[sw]) { l.ExpandBuffer(w); if (t == null) { doc.AddLine(l); } else { doc.Replace(t, l); t = l.NextLine; } if (--m == 0) { break; } } }
protected void RestoreScreen() { if (_savedScreen == null) { return; } TerminalDocument doc = GetDocument(); int w = GetConnection().TerminalWidth; int m = GetConnection().TerminalHeight; GLine t = doc.TopLine; foreach (GLine l in _savedScreen) { l.ExpandBuffer(w); if (t == null) { doc.AddLine(l); } else { doc.Replace(t, l); t = l.NextLine; } if (--m == 0) { break; } } _savedScreen = null; }
private static CommandResult CmdClearScreen(ICommandTarget target) { TerminalDocument doc = TerminalCommandTarget.AsTerminalDocument(target); if (doc == null) { return(CommandResult.Ignored); } TerminalControl tc = TerminalCommandTarget.AsTerminalControl(target); lock (doc) { GLine l = doc.TopLine; int top_id = l.ID; int limit = l.ID + doc.TerminalHeight; while (l != null && l.ID < limit) { l.Clear(); l = l.NextLine; } doc.CurrentLineNumber = top_id; doc.CaretColumn = 0; doc.InvalidatedRegion.InvalidatedAll = true; if (tc != null) { tc.ITextSelection.Clear(); tc.Invalidate(); } } return(CommandResult.Succeeded); }
private void InternalDataArrived() { if (_session == null) { return; // ペインを閉じる時に _tag が null になっていることがある } TerminalDocument document = GetDocument(); if (!this.ITextSelection.IsEmpty) { document.InvalidatedRegion.InvalidatedAll = true; //面倒だし this.ITextSelection.Clear(); } //Debug.WriteLine(String.Format("v={0} l={1} m={2}", _VScrollBar.Value, _VScrollBar.LargeChange, _VScrollBar.Maximum)); if (DebugOpt.DrawingPerformance) { DrawingPerformance.MarkReceiveData(GetDocument().InvalidatedRegion); } SmartInvalidate(); //部分変換中であったときのための調整 if (_inIMEComposition) { if (this.InvokeRequired) { this.Invoke(new AdjustIMECompositionDelegate(AdjustIMEComposition)); } else { AdjustIMEComposition(); } } }
//CSI J protected void ProcessEraseInDisplay(string param) { int d = ParseInt(param, 0); TerminalDocument doc = GetDocument(); int col = _manipulator.CaretColumn; switch (d) { case 0: //erase below _manipulator.RemoveAfterCaret(); doc.ReplaceCurrentLine(_manipulator.Export()); doc.RemoveAfter(doc.TopLineNumber + GetConnection().TerminalHeight); if (_currentdecoration.IsDefault) { doc.ClearAfter(doc.CurrentLineNumber + 1); } else { doc.ClearAfter(doc.CurrentLineNumber + 1, _currentdecoration); } _manipulator.Load(doc.CurrentLine, col); break; case 1: //erase above _manipulator.FillSpace(0, _manipulator.CaretColumn); doc.ReplaceCurrentLine(_manipulator.Export()); if (_currentdecoration.IsDefault) { doc.ClearRange(doc.TopLineNumber, doc.CurrentLineNumber); } else { doc.ClearRange(doc.TopLineNumber, doc.CurrentLineNumber, _currentdecoration); } _manipulator.Load(doc.CurrentLine, col); break; case 2: //erase all doc.ReplaceCurrentLine(_manipulator.Export()); if (_homePositionOnCSIJ2) //SFUではこうなる { ProcessCursorPosition(1, 1); col = 0; } if (_currentdecoration.IsDefault) { doc.ClearAfter(doc.TopLineNumber); } else { doc.ClearAfter(doc.TopLineNumber, _currentdecoration); } _manipulator.Load(doc.CurrentLine, col); break; default: throw new UnknownEscapeSequenceException(String.Format("unknown ED option {0}", param)); } }
public void Recognize() { if (_promptExpression == null) { return; } if (_terminal.TerminalMode == TerminalMode.Application) { return; //アプリケーションモードは通知の必要なし } //一応、前回チェック時とデータ受信の有無をもらってくれば処理の簡略化は可能 TerminalDocument doc = _terminal.GetDocument(); GLine prompt_candidate = FindPromptCandidateLine(doc); if (prompt_candidate == null) { return; // too large command line } string prompt; string command; if (!DeterminePromptLine(prompt_candidate, doc.CurrentLine.ID, doc.CaretColumn, out prompt, out command)) //プロンプトではないとき { NotifyNotPromptLine(); } else { Debug.WriteLineIf(DebugOpt.PromptRecog, "Prompt " + command); NotifyPromptLine(prompt_candidate, prompt, command); } }
//これを送ってくるアプリケーションは viで下方スクロール protected void ProcessDeleteLines(string param) { int d = ParseInt(param, 1); /* * TerminalDocument doc = GetDocument(); * _manipulator.Clear(GetConnection().TerminalWidth); * GLine target = doc.CurrentLine; * for(int i=0; i<d; i++) { * target.Clear(); * target = target.NextLine; * } */ TerminalDocument doc = GetDocument(); int caret_col = _manipulator.CaretColumn; int offset = doc.CurrentLineNumber - doc.TopLineNumber; GLine nl = _manipulator.Export(); doc.ReplaceCurrentLine(nl); if (doc.ScrollingBottom == -1) { doc.SetScrollingRegion(0, doc.TerminalHeight - 1); } for (int i = 0; i < d; i++) { doc.ScrollDown(doc.CurrentLineNumber, doc.ScrollingBottom); doc.CurrentLineNumber = doc.TopLineNumber + offset; } _manipulator.Load(doc.CurrentLine, caret_col); }
//現在行が見えるように自動的に追随していくべきかどうかの判定 private bool IsAutoScrollMode() { TerminalDocument doc = GetDocument(); return(GetTerminal().TerminalMode == TerminalMode.Normal && doc.CurrentLineNumber >= doc.TopLineNumber + doc.TerminalHeight - 1 && (!_VScrollBar.Enabled || _VScrollBar.Value + _VScrollBar.LargeChange > _VScrollBar.Maximum)); }
private bool IsAutoScrollMode(int value_candidate) { TerminalDocument doc = _document; return(_terminalMode == TerminalMode.Normal && doc.CurrentLineNumber >= doc.TopLineNumber + doc.TerminalHeight - 1 && (!_scrollBarValues.Enabled || value_candidate + _scrollBarValues.LargeChange > _scrollBarValues.Maximum)); }
public void DataArrived(byte[] data, int offset, int count) { try { TerminalConnection con = _tag.Connection; con.AddReceivedDataStats(count); con.BinaryLogger.Append(data, offset, count); if(_tag.ModalTerminalTask!=null && _tag.ModalTerminalTask.CanReceive) _tag.ModalTerminalTask.Input(data, offset, count); else { TerminalDocument document = _tag.Document; lock(document) { _tag.InvalidateParam.Reset(); _tag.Terminal.Input(data, offset, count); //右端にキャレットが来たときは便宜的に次行の頭にもっていく if(document.CaretColumn==_tag.Connection.TerminalWidth) { document.CurrentLineNumber++; //これによって次行の存在を保証 document.CaretColumn = 0; } CheckDiscardDocument(); AdjustTransientScrollBar(); int n = document.CurrentLineNumber-_tag.Connection.TerminalHeight+1-document.FirstLineNumber; if(n < 0) n = 0; //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)); if(IsAutoScrollMode(n)) { _transientScrollBarValue = n; document.TopLineNumber = n + document.FirstLineNumber; } else _transientScrollBarValue = document.TopLineNumber - document.FirstLineNumber; _tag.NotifyUpdate(); } //Invalidateをlockの外に出す。このほうが安全と思われた if(_tag.Pane!=null) _tag.InvalidateParam.InvokeFor(_tag.Pane); ITerminalTextLogger tl = con.TextLogger; if(tl!=null) { tl.PacketDelimiter(); tl.Flush(); } } ITerminalBinaryLogger bl = con.BinaryLogger; if(bl!=null) bl.Flush(); } catch(Exception ex) { GEnv.InterThreadUIService.ReportCriticalError(ex); } }
private void SendBytes(byte[] data) { TerminalDocument doc = GetDocument(); lock (doc) { //キーを押しっぱなしにしたときにキャレットがブリンクするのはちょっと見苦しいのでキー入力があるたびにタイマをリセット _caret.KeepActiveUntilNextTick(); MakeCurrentLineVisible(); } GetTerminalTransmission().Transmit(data); }
protected override void VScrollBarValueChanged() { if (_ignoreValueChangeEvent) { return; } TerminalDocument document = GetDocument(); lock (document) { document.TopLineNumber = document.FirstLineNumber + _VScrollBar.Value; _session.Terminal.TransientScrollBarValues.Value = _VScrollBar.Value; Invalidate(); } }
//CSI J protected void ProcessEraseInDisplay(string param) { int d = ParseInt(param, 0); TerminalDocument doc = GetDocument(); int col = _manipulator.CaretColumn; switch (d) { case 0: //erase below { EraseRight(); doc.ReplaceCurrentLine(_manipulator.Export()); int bottom = doc.TopLineNumber + doc.TerminalHeight; doc.EnsureLine(bottom - 1); doc.RemoveAfter(bottom); doc.ClearRange(doc.CurrentLineNumber + 1, bottom, _currentdecoration); _manipulator.Load(doc.CurrentLine, col); } break; case 1: //erase above { EraseLeft(); doc.ReplaceCurrentLine(_manipulator.Export()); doc.ClearRange(doc.TopLineNumber, doc.CurrentLineNumber, _currentdecoration); _manipulator.Load(doc.CurrentLine, col); } break; case 2: //erase all { doc.ReplaceCurrentLine(_manipulator.Export()); //if(_homePositionOnCSIJ2) { //SFUではこうなる // ProcessCursorPosition(1,1); // col = 0; //} int top = doc.TopLineNumber; int bottom = top + doc.TerminalHeight; doc.EnsureLine(bottom - 1); doc.RemoveAfter(bottom); doc.ClearRange(top, bottom, _currentdecoration); _manipulator.Load(doc.CurrentLine, col); } break; default: throw new UnknownEscapeSequenceException(String.Format("unknown ED option {0}", param)); } }
//ふつうは現在行だが、前行が非改行終端ならさかのぼる private GLine FindPromptCandidateLine(TerminalDocument doc, int maxLines) { GLine line = doc.CurrentLine; for (int i = 0; i < maxLines; i++) { GLine prev = line.PrevLine; if (prev == null || prev.EOLType != EOLType.Continue) { return(line); } line = prev; } return(null); }
//ふつうは現在行だが、前行が非改行終端ならさかのぼる private GLine FindPromptCandidateLine(TerminalDocument doc) { GLine line = doc.CurrentLine; int maxLines = PromptRecognizerPreferences.Instance.PromptSearchMaxLines; for (int i = 0; i < maxLines; i++) { GLine prev = line.PrevLine; if (prev == null || prev.EOLType != EOLType.Continue) { return(line); } line = prev; } return(null); }
internal void AdjustTransientScrollBar() { TerminalDocument document = _tag.Document; int paneheight = _tag.Connection.TerminalHeight; int docheight = Math.Max(document.LastLineNumber, document.TopLineNumber+paneheight-1)-document.FirstLineNumber+1; _transientScrollBarDirty = true; if((_tag.Terminal.TerminalMode==TerminalMode.Application && !GEnv.Options.AllowsScrollInAppMode) || paneheight >= docheight) { _transientScrollBarEnabled = false; _transientScrollBarValue = 0; } else { _transientScrollBarEnabled = true; _transientScrollBarMaximum = docheight-1; _transientScrollBarLargeChange = paneheight; } //Debug.WriteLine(String.Format("E={0} V={1}", _transientScrollBarEnabled, _transientScrollBarValue)); }
private void ShowMenu() { TerminalControl tc = _terminal.TerminalHost.TerminalControl; Debug.Assert(tc != null); TerminalDocument doc = _terminal.GetDocument(); SizeF pitch = tc.GetRenderProfile().Pitch; Point popup = new Point((int)(doc.CaretColumn * pitch.Width), (int)((doc.CurrentLineNumber - doc.TopLineNumber + 1) * pitch.Height)); IPoderosaForm f = tc.FindForm() as IPoderosaForm; Debug.Assert(f != null); //EXTPにしてもいいんだけど f.ShowContextMenu(new IPoderosaMenuGroup[] { new PoderosaMenuGroupImpl(CreatePopupMenuItems()) }, (ICommandTarget)tc.GetAdapter(typeof(ICommandTarget)), tc.PointToScreen(popup), ContextMenuFlags.SelectFirstItem); }
protected override void AdjustCaret(Caret caret) { if (_session == null) { return; } if (IsConnectionClosed() || !this.Focused || _inIMEComposition) { caret.Enabled = false; } else { TerminalDocument d = GetDocument(); caret.X = d.CaretColumn; caret.Y = d.CurrentLineNumber - d.TopLineNumber; caret.Enabled = caret.Y >= 0 && caret.Y < d.TerminalHeight; } }
public AbstractTerminal(TerminalInitializeInfo info) { TerminalEmulatorPlugin.Instance.LaterInitialize(); _session = info.Session; //_invalidateParam = new InvalidateParam(); _document = new TerminalDocument(info.InitialWidth, info.InitialHeight); _document.SetOwner(_session.ISession); _afterExitLockActions = new List <AfterExitLockDelegate>(); _encodingProfile = EncodingProfile.Create(info.Session.TerminalSettings.Encoding); _decoder = new ISO2022CharDecoder(this, _encodingProfile); _unicodeCharConverter = _encodingProfile.CreateUnicodeCharConverter(); _terminalMode = TerminalMode.Normal; _currentdecoration = TextDecoration.Default; _manipulator = new GLineManipulator(); _scrollBarValues = new ScrollBarValues(); _logService = new LogService(info.TerminalParameter, _session.TerminalSettings); _promptRecognizer = new PromptRecognizer(this); _intelliSense = new IntelliSense(this); _commandResultRecognizer = new PopupStyleCommandResultRecognizer(this); if (info.Session.TerminalSettings.LogSettings != null) { _logService.ApplyLogSettings(_session.TerminalSettings.LogSettings, false); } //event handlers ITerminalSettings ts = info.Session.TerminalSettings; ts.ChangeEncoding += delegate(EncodingType t) { this.Reset(); }; ts.ChangeRenderProfile += delegate(RenderProfile prof) { TerminalControl tc = _session.TerminalControl; if (tc != null) { tc.ApplyRenderProfile(prof); } }; }
private void MakeCurrentLineVisible() { TerminalDocument document = GetDocument(); if (document.CurrentLineNumber - document.FirstLineNumber < _VScrollBar.Value) //上に隠れた { document.TopLineNumber = document.CurrentLineNumber; _session.Terminal.TransientScrollBarValues.Value = document.TopLineNumber - document.FirstLineNumber; } else if (_VScrollBar.Value + document.TerminalHeight <= document.CurrentLineNumber - document.FirstLineNumber) //下に隠れた { int n = document.CurrentLineNumber - document.FirstLineNumber - document.TerminalHeight + 1; if (n < 0) { n = 0; } GetTerminal().TransientScrollBarValues.Value = n; GetDocument().TopLineNumber = n + document.FirstLineNumber; } }
//これを送ってくるアプリケーションは viで上方スクロール protected void ProcessInsertLines(string param) { int d = ParseInt(param, 1); TerminalDocument doc = GetDocument(); int caret_pos = _manipulator.CaretColumn; int offset = doc.CurrentLineNumber - doc.TopLineNumber; doc.UpdateCurrentLine(_manipulator); if (doc.ScrollingBottom == -1) { doc.SetScrollingRegion(0, GetDocument().TerminalHeight - 1); } for (int i = 0; i < d; i++) { doc.ScrollUp(doc.CurrentLineNumber, doc.ScrollingBottom); doc.CurrentLineNumber = doc.TopLineNumber + offset; } _manipulator.Load(doc.CurrentLine, caret_pos); }
private void ProcessScrollUp(string param) { int d = ParseInt(param, 1); TerminalDocument doc = GetDocument(); int caret_col = _manipulator.CaretColumn; int offset = doc.CurrentLineNumber - doc.TopLineNumber; GLine nl = _manipulator.Export(); doc.ReplaceCurrentLine(nl); if (doc.ScrollingBottom == -1) { doc.SetScrollingRegion(0, GetDocument().TerminalHeight - 1); } for (int i = 0; i < d; i++) { doc.ScrollDown(doc.ScrollingTop, doc.ScrollingBottom); // TerminalDocument's "Scroll-Down" means XTerm's "Scroll-Up" doc.CurrentLineNumber = doc.TopLineNumber + offset; // find correct GLine } _manipulator.Load(doc.CurrentLine, caret_col); }
//IMEの位置合わせなど。日本語入力開始時、現在のキャレット位置からIMEをスタートさせる。 private void AdjustIMEComposition() { TerminalDocument document = GetDocument(); IntPtr hIMC = Win32.ImmGetContext(this.Handle); RenderProfile prof = GetRenderProfile(); //フォントのセットは1回やればよいのか? Win32.LOGFONT lf = new Win32.LOGFONT(); prof.CalcFont(null, CharGroup.Zenkaku).ToLogFont(lf); Win32.ImmSetCompositionFont(hIMC, lf); Win32.COMPOSITIONFORM form = new Win32.COMPOSITIONFORM(); form.dwStyle = Win32.CFS_POINT; Win32.SystemMetrics sm = GEnv.SystemMetrics; //Debug.WriteLine(String.Format("{0} {1} {2}", document.CaretColumn, charwidth, document.CurrentLine.CharPosToDisplayPos(document.CaretColumn))); form.ptCurrentPos.x = sm.ControlBorderWidth + (int)(prof.Pitch.Width * (document.CaretColumn)); form.ptCurrentPos.y = sm.ControlBorderHeight + (int)((prof.Pitch.Height + prof.LineSpacing) * (document.CurrentLineNumber - document.TopLineNumber)); bool r = Win32.ImmSetCompositionWindow(hIMC, ref form); Debug.Assert(r); Win32.ImmReleaseContext(this.Handle, hIMC); }
//ふつうは現在行だが、前行が非改行終端ならさかのぼる private GLine FindPromptCandidateLine(TerminalDocument doc, int maxLines) { GLine line = doc.CurrentLine; for (int i = 0; i < maxLines; i++) { GLine prev = line.PrevLine; if (prev == null || prev.EOLType != EOLType.Continue) return line; line = prev; } return null; }
//�Đڑ��p�Ɍ��݃h�L�������g�̑O�ɑ}�� public void InsertBefore(TerminalDocument olddoc, int paneheight) { lock (this) { GLine c = olddoc.LastLine; int offset = _currentLine.ID - _topLine.ID; bool flag = false; while (c != null) { if (flag || c.DisplayLength == 0) { flag = true; GLine nl = c.Clone(); nl.ID = _firstLine.ID - 1; InsertBefore(_firstLine, nl); //�ŏ��ɋ�łȂ��s������Έȍ~�͑S���}�� offset++; } c = c.PrevLine; } //ID�����ɂȂ�̂͂�����ƕ|���̂ŏC�� if (_firstLine.ID < 0) { int t = -_firstLine.ID; c = _firstLine; while (c != null) { c.ID += t; c = c.NextLine; } } _topLine = FindLineOrEdge(_currentLine.ID - Math.Min(offset, paneheight)); //Dump("insert doc"); } }
//再接続用に現在ドキュメントの前に挿入 public void InsertBefore(TerminalDocument olddoc, int paneheight) { lock (this) { GLine c = olddoc.LastLine; int offset = _currentLine.ID - _topLine.ID; bool flag = false; while (c != null) { if (flag || c.DisplayLength == 0) { flag = true; GLine nl = c.Clone(); nl.ID = _firstLine.ID - 1; InsertBefore(_firstLine, nl); //最初に空でない行があれば以降は全部挿入 offset++; } c = c.PrevLine; } //IDが負になるのはちょっと怖いので修正 if (_firstLine.ID < 0) { int t = -_firstLine.ID; c = _firstLine; while (c != null) { c.ID += t; c = c.NextLine; } } _topLine = FindLineOrEdge(_currentLine.ID - Math.Min(offset, paneheight)); //Dump("insert doc"); } }
public AbstractTerminal(TerminalInitializeInfo info) { TerminalEmulatorPlugin.Instance.LaterInitialize(); _session = info.Session; //_invalidateParam = new InvalidateParam(); _document = new TerminalDocument(info.InitialWidth, info.InitialHeight); _document.SetOwner(_session.ISession); _afterExitLockActions = new List<AfterExitLockDelegate>(); _decoder = new ISO2022CharDecoder(this, EncodingProfile.Get(info.Session.TerminalSettings.Encoding)); _terminalMode = TerminalMode.Normal; _currentdecoration = TextDecoration.Default; _manipulator = new GLineManipulator(); _scrollBarValues = new ScrollBarValues(); _logService = new LogService(info.TerminalParameter, _session.TerminalSettings); _promptRecognizer = new PromptRecognizer(this); _intelliSense = new IntelliSense(this); _commandResultRecognizer = new PopupStyleCommandResultRecognizer(this); if (info.Session.TerminalSettings.LogSettings != null) _logService.ApplyLogSettings(_session.TerminalSettings.LogSettings, false); //event handlers ITerminalSettings ts = info.Session.TerminalSettings; ts.ChangeEncoding += delegate(EncodingType t) { this.Reset(); }; ts.ChangeRenderProfile += delegate(RenderProfile prof) { TerminalControl tc = _session.TerminalControl; if (tc != null) tc.ApplyRenderProfile(prof); }; }