/// <summary> /// ����̑ΏۂɂȂ�h�L�������g�ƕ����̃G���R�[�f�B���O��w�肵�č\�z /// </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); }
/// <summary> /// 文字列、デコレーション、オフセットを指定するコンストラクタ。TypeはNormalになる。 /// </summary> internal GWord(TextDecoration d, int o, CharGroup chargroup) { Debug.Assert(d != null); _offset = o; _decoration = d; _next = null; _charGroup = chargroup; nextOffsetCache = -1; displayLengthCache = -1; }
public object Clone() { TextDecoration t = new TextDecoration(); t._bgColorType = _bgColorType; t._bgColor = _bgColor; t._textColorType = _textColorType; t._textColor = _textColor; t._bold = _bold; t._underline = _underline; return(t); }
public void FillSpace(int from, int to, TextDecoration dec) { if (to > _text.Length) { to = _text.Length; } for (int i = from; i < to; i++) { _text[i] = ' '; _decorations[i] = dec; } }
internal void ClearRange(int from, int to, TextDecoration dec) { GLine l = FindLineOrEdge(from); if (l == null) { return; } while (l.ID < to) { l.Clear(dec); InvalidateLine(l.ID); l = l.NextLine; } AssertValid(); }
internal void ClearAfter(int from, TextDecoration dec) { if (from > _lastLine.ID) { return; } GLine l = FindLineOrEdge(from); if (l == null) { return; } while (l != null) { l.Clear(dec); l = l.NextLine; } AssertValid(); _invalidatedAll = true; }
public object Clone() { TextDecoration t = new TextDecoration(); t._bgColorType = _bgColorType; t._bgColor = _bgColor; t._textColorType = _textColorType; t._textColor = _textColor; t._bold = _bold; t._underline = _underline; return t; }
internal Color CalcTextColor(TextDecoration dec) { if(_brush==null) CreateBrushes(); if(dec==null) return _forecolor; switch(dec.TextColorType) { case ColorType.Custom: return dec.TextColor; case ColorType.DefaultBack: return _bgcolor; case ColorType.DefaultText: return _forecolor; default: throw new Exception("Unexpected decoration object"); } }
internal Brush CalcTextBrush(TextDecoration dec) { if(_brush==null) CreateBrushes(); if(dec==null) return _brush; switch(dec.TextColorType) { case ColorType.Custom: return new SolidBrush(dec.TextColor); case ColorType.DefaultBack: return _bgbrush; case ColorType.DefaultText: return _brush; default: throw new Exception("Unexpected decoration object"); } }
internal IntPtr CalcHFONT_NoUnderline(TextDecoration dec, CharGroup cg) { return CalcFontInternal(dec, cg, true).HFONT; }
private FontHandle CalcFontInternal(TextDecoration dec, CharGroup cg, bool ignore_underline) { if(_font==null) CreateFonts(); if(cg==CharGroup.TwoBytes) { if(dec==null) return _japaneseFont; if(dec.Bold) { if(!ignore_underline && dec.Underline) return _japaneseBoldunderlinefont; else return _japaneseBoldfont; } else if(!ignore_underline && dec.Underline) return _japaneseUnderlinefont; else return _japaneseFont; } else { if(dec==null) return _font; if(dec.Bold) { if(!ignore_underline && dec.Underline) return _boldunderlinefont; else return _boldfont; } else if(!ignore_underline && dec.Underline) return _underlinefont; else return _font; } }
internal void ClearRange(int from, int to, TextDecoration dec) { GLine l = FindLineOrEdge(from); if(l==null) return; while(l.ID < to) { l.Clear(dec); InvalidateLine(l.ID); l = l.NextLine; } AssertValid(); }
/// <summary> /// ������A�f�R���[�V�����A�I�t�Z�b�g��w�肷��R���X�g���N�^�BType��Normal�ɂȂ�B /// </summary> internal GWord(TextDecoration d, int o, CharGroup chargroup) { Debug.Assert(d!=null); _offset = o; _decoration = d; _next = null; _charGroup = chargroup; nextOffsetCache = -1; displayLengthCache = -1; }
internal GLine InverseRange(int from, int to) { ExpandBuffer(Math.Max(from+1,to)); //���������T�C�Y�����Ƃ��Ȃǂɂ��̏�����������Ȃ����Ƃ����� Debug.Assert(from>=0 && from<_text.Length); if(from<_text.Length && _text[from]==WIDECHAR_PAD) from--; if(to>0 && to-1<_text.Length && _text[to-1]==WIDECHAR_PAD) to--; GLine ret = new GLine(_text, null); ret.ID = _id; ret.EOLType = _eolType; //�����̔z���Z�b�g TextDecoration[] dec = new TextDecoration[_text.Length]; GWord w = _firstWord; while(w!=null) { Debug.Assert(w.Decoration!=null); dec[w.Offset] = w.Decoration; w = w.Next; } //���]�J�n�_ TextDecoration original = null; TextDecoration inverse = null; for(int i=from; i>=0; i--) { if(dec[i]!=null) { original = dec[i]; break; } } Debug.Assert(original!=null); inverse = (TextDecoration)original.Clone(); inverse.Inverse(); dec[from] = inverse; //�͈͂ɓn���Ĕ��]��� for(int i=from+1; i<to; i++) { if(i<dec.Length && dec[i]!=null) { original = dec[i]; inverse = (TextDecoration)original.Clone(); inverse.Inverse(); dec[i] = inverse; } } if(to<dec.Length && dec[to]==null) dec[to] = original; //����ɏ]����GWord���� w = null; for(int i=dec.Length-1; i>=0; i--) { char ch = _text[i]; if(dec[i]!=null && ch!='\0') { int j = i; if(ch==WIDECHAR_PAD) j++; GWord ww = new GWord(dec[i], j, CalcCharGroup(ch)); ww.Next = w; w = ww; } } ret.Append(w); return ret; }
internal void Clear(TextDecoration dec) { for(int i=0; i<_text.Length; i++) _text[i] = ' '; _firstWord = new GWord(dec, 0, CharGroup.SingleByte); }
public void SetDecoration(TextDecoration dec) { if(_caretColumn<_decorations.Length) _decorations[_caretColumn] = dec; }
public void PutChar(char ch, TextDecoration dec) { Debug.Assert(dec!=null); Debug.Assert(_caretColumn>=0); Debug.Assert(_caretColumn<_text.Length); //�ȉ��킩��ɂ������A�v�͏ꍇ�����B����̎d�l��������������� bool onZenkakuRight = (_text[_caretColumn] == GLine.WIDECHAR_PAD); bool onZenkaku = onZenkakuRight || (_text.Length>_caretColumn+1 && _text[_caretColumn+1] == GLine.WIDECHAR_PAD); if(onZenkaku) { //�S�p�̏�ɏ��� if(!onZenkakuRight) { _text[_caretColumn] = ch; _decorations[_caretColumn] = dec; if(GLine.CalcDisplayLength(ch)==1) { //�S�p�̏�ɔ��p��������ꍇ�A�ׂɃX�y�[�X�����Ȃ��ƕ\��������� if(_caretColumn+1<_text.Length) _text[_caretColumn+1] = ' '; _caretColumn++; } else { _decorations[_caretColumn+1] = dec; _caretColumn+=2; } } else { _text[_caretColumn-1] = ' '; _text[_caretColumn] = ch; _decorations[_caretColumn] = dec; if(GLine.CalcDisplayLength(ch)==2) { if(GLine.CalcDisplayLength(_text[_caretColumn+1])==2) if(_caretColumn+2<_text.Length) _text[_caretColumn+2] = ' '; _text[_caretColumn+1] = GLine.WIDECHAR_PAD; _decorations[_caretColumn+1] = _decorations[_caretColumn]; _caretColumn += 2; } else _caretColumn++; } } else { //���p�̏�ɏ��� _text[_caretColumn] = ch; _decorations[_caretColumn] = dec; if(GLine.CalcDisplayLength(ch)==2) { if(GLine.CalcDisplayLength(_text[_caretColumn+1])==2) //���p�A�S�p�ƂȂ��Ă���Ƃ���ɑS�p��������� if(_caretColumn+2<_text.Length) _text[_caretColumn+2] = ' '; _text[_caretColumn+1] = GLine.WIDECHAR_PAD; _decorations[_caretColumn+1] = _decorations[_caretColumn]; _caretColumn += 2; } else _caretColumn++; //���ꂪ�ł�common�ȃP�[�X���� } }
public void PutChar(char ch, TextDecoration dec) { Debug.Assert(dec != null); Debug.Assert(_caretColumn >= 0); Debug.Assert(_caretColumn < _text.Length); //以下わかりにくいが、要は場合分け。これの仕様を書いた資料あり bool onZenkakuRight = (_text[_caretColumn] == GLine.WIDECHAR_PAD); bool onZenkaku = onZenkakuRight || (_text.Length > _caretColumn + 1 && _text[_caretColumn + 1] == GLine.WIDECHAR_PAD); if (onZenkaku) { //全角の上に書く if (!onZenkakuRight) { _text[_caretColumn] = ch; _decorations[_caretColumn] = dec; if (GLine.CalcDisplayLength(ch) == 1) { //全角の上に半角を書いた場合、隣にスペースを入れないと表示が乱れる if (_caretColumn + 1 < _text.Length) { _text[_caretColumn + 1] = ' '; } _caretColumn++; } else { _decorations[_caretColumn + 1] = dec; _caretColumn += 2; } } else { _text[_caretColumn - 1] = ' '; _text[_caretColumn] = ch; _decorations[_caretColumn] = dec; if (GLine.CalcDisplayLength(ch) == 2) { if (GLine.CalcDisplayLength(_text[_caretColumn + 1]) == 2) { if (_caretColumn + 2 < _text.Length) { _text[_caretColumn + 2] = ' '; } } _text[_caretColumn + 1] = GLine.WIDECHAR_PAD; _decorations[_caretColumn + 1] = _decorations[_caretColumn]; _caretColumn += 2; } else { _caretColumn++; } } } else //半角の上に書く { _text[_caretColumn] = ch; _decorations[_caretColumn] = dec; if (GLine.CalcDisplayLength(ch) == 2) { if (GLine.CalcDisplayLength(_text[_caretColumn + 1]) == 2) //半角、全角となっているところに全角を書いたら { if (_caretColumn + 2 < _text.Length) { _text[_caretColumn + 2] = ' '; } } _text[_caretColumn + 1] = GLine.WIDECHAR_PAD; _decorations[_caretColumn + 1] = _decorations[_caretColumn]; _caretColumn += 2; } else { _caretColumn++; //これが最もcommonなケースだが } } }
public void FillSpace(int from, int to, TextDecoration dec) { if(to>_text.Length) to = _text.Length; for(int i=from; i<to; i++) { _text[i] = ' '; _decorations[i] = dec; } }
//indexの位置の表示を反転した新しいGLineを返す //inverseがfalseだと、GWordの分割はするがDecorationの反転はしない。ヒクヒク問題の対処として実装。 internal GLine InverseCaret(int index, bool inverse, bool underline) { ExpandBuffer(index + 1); if (_text[index] == WIDECHAR_PAD) { index--; } GLine ret = new GLine(_text, null); ret.ID = _id; ret.EOLType = _eolType; GWord w = _firstWord; int nextoffset = 0; while (w != null) { nextoffset = WordNextOffset(w); if (w.Offset <= index && index < nextoffset) { //!!tailから順に連結した方が効率はよい if (w.Offset < index) { GWord head = new GWord(w.Decoration, w.Offset, w.CharGroup); ret.Append(head); } TextDecoration dec = (TextDecoration)w.Decoration.Clone(); if (inverse) { //色つきキャレットのサポート dec.ToCaretStyle(); } if (underline) { dec.Underline = true; } GWord mid = new GWord(dec, index, w.CharGroup); ret.Append(mid); if (index + CalcDisplayLength(_text[index]) < nextoffset) { GWord tail = new GWord(w.Decoration, index + CalcDisplayLength(_text[index]), w.CharGroup); ret.Append(tail); } } else { ret.Append(w.StandAloneClone()); } w = w.Next; } //!!この、キャレット位置にスペースを入れるのはInverseとは違う処理であるから分離すること if (nextoffset <= index) { while (nextoffset <= index) { Debug.Assert(nextoffset < ret.Text.Length); ret.Text[nextoffset++] = ' '; } TextDecoration dec = TextDecoration.ClonedDefault(); if (inverse) { dec.ToCaretStyle(); } if (underline) { dec.Underline = true; } ret.Append(new GWord(dec, index, CharGroup.SingleByte)); } return(ret); }
internal void Render(IntPtr hdc, RenderParameter param, RenderProfile prof, int y) { if (_text[0] == '\0') { return; //何も描かなくてよい } float fx = (float)param.TargetRect.Left; RectangleF rect = new RectangleF(); rect.Y = param.TargetRect.Top + y; rect.Height = prof.Pitch.Height; GWord word = _firstWord; while (word != null) { rect.X = fx /*- prof.CharGap*/; //Nativeな描画では不要? rect.Width = param.TargetRect.Right - rect.X; int ix = (int)rect.X; int iy = (int)rect.Y; TextDecoration dec = word.Decoration; //Brush brush = prof.CalcTextBrush(dec); uint forecolorref = DrawUtil.ToCOLORREF(prof.CalcTextColor(dec)); Color bkcolor = prof.CalcBackColor(dec); uint bkcolorref = DrawUtil.ToCOLORREF(bkcolor); IntPtr hfont = prof.CalcHFONT_NoUnderline(dec, word.CharGroup); Win32.SelectObject(hdc, hfont); Win32.SetTextColor(hdc, forecolorref); Win32.SetBkColor(hdc, bkcolorref); Win32.SetBkMode(hdc, bkcolor == prof.BackColor? 1 : 2); //基本背景色と一緒ならTRANSPARENT, 異なればOPAQUE IntPtr bkbrush = bkcolor == prof.BackColor? IntPtr.Zero : Win32.CreateSolidBrush(bkcolorref); int display_length = WordDisplayLength(word); if (word.Decoration == null) //装飾なし //g.DrawString(WordText(word), font, brush, rect); { DrawWord(hdc, ix, iy, word); } else { //if(dec.Bold || (!prof.UsingIdenticalFont && word.CharGroup==CharGroup.TwoBytes)) if (dec.Bold || word.CharGroup == CharGroup.TwoBytes) //同じフォント指定でも日本語が半角の2倍でない場合あり。パフォーマンス問題はクリアされつつあるので確実に1文字ずつ描画 { DrawStringByOneChar2(hdc, word, display_length, bkbrush, rect.X, iy, prof); } else { DrawWord(hdc, ix, iy, word); //いまやアホな描画エンジンの問題からは解放された! } } //Debug.WriteLine("PW="+p.Pitch.Width+",TL="+(pb.Text.Length*p.Pitch.Width)+", real="+g.MeasureString(pb.Text, p.Font).Width); if (dec.Underline) { DrawUnderline(hdc, forecolorref, ix, iy + (int)prof.Pitch.Height - 1, (int)(prof.Pitch.Width * display_length)); } fx += prof.Pitch.Width * display_length; word = word.Next; if (bkbrush != IntPtr.Zero) { Win32.DeleteObject(bkbrush); } } }
internal Font CalcFont(TextDecoration dec, CharGroup cg) { return CalcFontInternal(dec, cg, false).Font; }
internal GLine InverseRange(int from, int to) { ExpandBuffer(Math.Max(from + 1, to)); //激しくリサイズしたときなどにこの条件が満たせないことがある Debug.Assert(from >= 0 && from < _text.Length); if (from < _text.Length && _text[from] == WIDECHAR_PAD) { from--; } if (to > 0 && to - 1 < _text.Length && _text[to - 1] == WIDECHAR_PAD) { to--; } GLine ret = new GLine(_text, null); ret.ID = _id; ret.EOLType = _eolType; //装飾の配列をセット TextDecoration[] dec = new TextDecoration[_text.Length]; GWord w = _firstWord; while (w != null) { Debug.Assert(w.Decoration != null); dec[w.Offset] = w.Decoration; w = w.Next; } //反転開始点 TextDecoration original = null; TextDecoration inverse = null; for (int i = from; i >= 0; i--) { if (dec[i] != null) { original = dec[i]; break; } } Debug.Assert(original != null); inverse = (TextDecoration)original.Clone(); inverse.Inverse(); dec[from] = inverse; //範囲に渡って反転作業 for (int i = from + 1; i < to; i++) { if (i < dec.Length && dec[i] != null) { original = dec[i]; inverse = (TextDecoration)original.Clone(); inverse.Inverse(); dec[i] = inverse; } } if (to < dec.Length && dec[to] == null) { dec[to] = original; } //これに従ってGWordを作る w = null; for (int i = dec.Length - 1; i >= 0; i--) { char ch = _text[i]; if (dec[i] != null && ch != '\0') { int j = i; if (ch == WIDECHAR_PAD) { j++; } GWord ww = new GWord(dec[i], j, CalcCharGroup(ch)); ww.Next = w; w = ww; } } ret.Append(w); return(ret); }
internal void ClearAfter(int from, TextDecoration dec) { if(from > _lastLine.ID) return; GLine l = FindLineOrEdge(from); if(l==null) return; while(l!=null) { l.Clear(dec); l = l.NextLine; } AssertValid(); _invalidatedAll = true; }