//再接続用に現在ドキュメントの前に挿入 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"); } }
protected void SaveScreen() { _savedScreen = new ArrayList(); GLine l = GetDocument().TopLine; int m = l.ID + GetConnection().TerminalHeight; while (l != null && l.ID < m) { _savedScreen.Add(l.Clone()); l = l.NextLine; } }
private void SaveScreen(int sw) { List <GLine> lines = new List <GLine>(); GLine l = GetDocument().TopLine; int m = l.ID + GetDocument().TerminalHeight; while (l != null && l.ID < m) { lines.Add(l.Clone()); l = l.NextLine; } _savedScreen[sw] = lines; }
private void BuildTransientDocument(PaintEventArgs e, RenderParameter param) { Rectangle clip = e.ClipRectangle; RenderProfile profile = GetRenderProfile(); _transientLines.Clear(); //Win32.SystemMetrics sm = GEnv.SystemMetrics; //param.TargetRect = new Rectangle(sm.ControlBorderWidth+1, sm.ControlBorderHeight, // this.Width - _VScrollBar.Width - sm.ControlBorderWidth + 8, //この8がない値が正当だが、.NETの文字サイズ丸め問題のため行の最終文字が表示されないことがある。これを回避するためにちょっと増やす // this.Height - sm.ControlBorderHeight); param.TargetRect = this.ClientRectangle; int offset1 = (int)Math.Floor((clip.Top - BORDER) / (profile.Pitch.Height + profile.LineSpacing)); if (offset1 < 0) { offset1 = 0; } param.LineFrom = offset1; int offset2 = (int)Math.Floor((clip.Bottom - BORDER) / (profile.Pitch.Height + profile.LineSpacing)); if (offset2 < 0) { offset2 = 0; } param.LineCount = offset2 - offset1 + 1; //Debug.WriteLine(String.Format("{0} {1} ", param.LineFrom, param.LineCount)); int topline_id = GetTopLine().ID; GLine l = _document.FindLineOrNull(topline_id + param.LineFrom); if (l != null) { for (int i = param.LineFrom; i < param.LineFrom + param.LineCount; i++) { _transientLines.Add(l.Clone()); //TODO クローンはきついよなあ だが描画の方が時間かかるので、その間ロックをしないためには仕方ない点もある l = l.NextLine; if (l == null) { break; } } } //以下、_transientLinesにはparam.LineFromから示される値が入っていることに注意 //選択領域の描画 if (!_textSelection.IsEmpty) { TextSelection.TextPoint from = _textSelection.HeadPoint; TextSelection.TextPoint to = _textSelection.TailPoint; l = _document.FindLineOrNull(from.Line); GLine t = _document.FindLineOrNull(to.Line); if (l != null && t != null) //本当はlがnullではいけないはずだが、それを示唆するバグレポートがあったので念のため { t = t.NextLine; int pos = from.Column; //たとえば左端を越えてドラッグしたときの選択範囲は前行末になるので pos==TerminalWidthとなるケースがある。 do { int index = l.ID - (topline_id + param.LineFrom); if (pos >= 0 && pos < l.DisplayLength && index >= 0 && index < _transientLines.Count) { GLine r = null; if (l.ID == to.Line) { if (pos != to.Column) { r = _transientLines[index].CreateInvertedClone(pos, to.Column); } } else { r = _transientLines[index].CreateInvertedClone(pos, l.DisplayLength); } if (r != null) { _transientLines[index] = r; } } pos = 0; //2行目からの選択は行頭から l = l.NextLine; } while (l != t); } } AdjustCaret(_caret); _caret.Enabled = _caret.Enabled && (param.LineFrom <= _caret.Y && _caret.Y < param.LineFrom + param.LineCount); //Caret画面外にあるなら処理はしなくてよい。2番目の条件は、Attach-ResizeTerminalの流れの中でこのOnPaintを実行した場合にTerminalHeight>lines.Countになるケースがあるのを防止するため if (_caret.Enabled) { //ヒクヒク問題のため、キャレットを表示しないときでもこの操作は省けない if (_caret.Style == CaretType.Box) { int y = _caret.Y - param.LineFrom; if (y >= 0 && y < _transientLines.Count) { _transientLines[y].InvertCharacter(_caret.X, _caret.IsActiveTick, _caret.Color); } } } }