--- /dev/null
+###############################################################################
+# Set default behavior to automatically normalize line endings.
+###############################################################################
+* text=auto
+
+###############################################################################
+# Set default behavior for command prompt diff.
+#
+# This is need for earlier builds of msysgit that does not have it on by
+# default for csharp files.
+# Note: This is only used by command line
+###############################################################################
+#*.cs diff=csharp
+
+###############################################################################
+# Set the merge driver for project and solution files
+#
+# Merging from the command prompt will add diff markers to the files if there
+# are conflicts (Merging from VS is not affected by the settings below, in VS
+# the diff markers are never inserted). Diff markers may cause the following
+# file extensions to fail to load in VS. An alternative would be to treat
+# these files as binary and thus will always conflict and require user
+# intervention with every merge. To do so, just uncomment the entries below
+###############################################################################
+#*.sln merge=binary
+#*.csproj merge=binary
+#*.vbproj merge=binary
+#*.vcxproj merge=binary
+#*.vcproj merge=binary
+#*.dbproj merge=binary
+#*.fsproj merge=binary
+#*.lsproj merge=binary
+#*.wixproj merge=binary
+#*.modelproj merge=binary
+#*.sqlproj merge=binary
+#*.wwaproj merge=binary
+
+###############################################################################
+# behavior for image files
+#
+# image files are treated as binary by default.
+###############################################################################
+#*.jpg binary
+#*.png binary
+#*.gif binary
+
+###############################################################################
+# diff behavior for common document formats
+#
+# Convert binary document formats to text before diffing them. This feature
+# is only available from the command line. Turn it on by uncommenting the
+# entries below.
+###############################################################################
+#*.doc diff=astextplain
+#*.DOC diff=astextplain
+#*.docx diff=astextplain
+#*.DOCX diff=astextplain
+#*.dot diff=astextplain
+#*.DOT diff=astextplain
+#*.pdf diff=astextplain
+#*.PDF diff=astextplain
+#*.rtf diff=astextplain
+#*.RTF diff=astextplain
namespace FooEditEngine
{
+#if METRO || WPF
/// <summary>
/// Automation Peer class for CustomInputBox2.
///
}
#endif
- #region Implementation for ITextPattern interface
+ #region Implementation for ITextPattern interface
// Complete implementation of the ITextPattern is beyond the scope of this sample. The implementation provided
// is specific to this sample's custom control, so it is unlikely that they are directly transferable to other
// custom control.
get { return SupportedTextSelection.Single; }
}
- #endregion
+ #endregion
- #region Implementation for IValueProvider interface
+ #region Implementation for IValueProvider interface
// Complete implementation of the IValueProvider is beyond the scope of this sample. The implementation provided
// is specific to this sample's custom control, so it is unlikely that they are directly transferable to other
// custom control.
}
}
- #endregion //Implementation for IValueProvider interface
+ #endregion //Implementation for IValueProvider interface
public IRawElementProviderSimple GetRawElementProviderSimple()
{
this.textbox.Select(this.start, this.end - this.start + 1);
}
}
+#endif
}
-/*\r
- * Copyright (C) 2013 FooProject\r
- * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.\r
-\r
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of \r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\r
-\r
-You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.\r
- */\r
-using System;\r
-using System.Globalization;\r
-using System.Text;\r
-using System.Linq;\r
-using System.Diagnostics;\r
-using System.Text.RegularExpressions;\r
-#if WINFORM\r
-using System.Drawing;\r
-#endif\r
-\r
-namespace FooEditEngine\r
-{\r
- internal enum MoveFlow\r
- {\r
- Horizontical,\r
- Vertical,\r
- }\r
- internal enum ScrollDirection\r
- {\r
- Up,\r
- Down,\r
- Left,\r
- Right,\r
- }\r
-\r
- /// <summary>\r
- /// インデントの方法を表す\r
- /// </summary>\r
- public enum IndentMode\r
- {\r
- Tab,\r
- Space,\r
- }\r
-\r
- /// <summary>\r
- /// ユーザー側からの処理を担当するクラス。一部を除き、こちらで行われた操作はアンドゥの対象になります\r
- /// </summary>\r
- internal sealed class Controller\r
- {\r
- EditView View;\r
- Document Document;\r
- int AnchorIndex;\r
- \r
- public Controller(Document doc, EditView view)\r
- {\r
- this.Document = doc;\r
- this.Document.Update += new DocumentUpdateEventHandler(Document_Update);\r
- this.View = view;\r
- this.View.render.ChangedRightToLeft += render_ChangedRightToLeft;\r
- this.View.render.ChangedRenderResource += render_ChangedRenderResource;\r
- this.View.PerformLayouted += View_LineBreakChanged;\r
- this.View.PageBoundChanged += View_PageBoundChanged;\r
- this.SelectionChanged += new EventHandler((s, e) => { });\r
- this.Document.Clear();\r
- }\r
-\r
- /// <summary>\r
- /// 選択領域変更時に通知される\r
- /// </summary>\r
- public event EventHandler SelectionChanged;\r
-\r
- /// <summary>\r
- /// 矩形選択モードなら真を返し、そうでない場合は偽を返す\r
- /// </summary>\r
- public bool RectSelection\r
- {\r
- get;\r
- set;\r
- }\r
-\r
- /// <summary>\r
- /// インデントの方法を表す\r
- /// </summary>\r
- public IndentMode IndentMode\r
- {\r
- get;\r
- set;\r
- }\r
-\r
- /// <summary>\r
- /// 選択範囲の開始位置\r
- /// </summary>\r
- /// <remarks>SelectionLengthが0の場合、キャレット位置を表します</remarks>\r
- public int SelectionStart\r
- {\r
- get\r
- {\r
- if (this.View.Selections.Count == 0)\r
- return this.AnchorIndex;\r
- else\r
- return this.View.Selections.First().start;\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// 選択範囲の長さ\r
- /// </summary>\r
- /// <remarks>矩形選択モードの場合、選択範囲の文字数ではなく、開始位置から終了位置までの長さとなります</remarks>\r
- public int SelectionLength\r
- {\r
- get\r
- {\r
- if (this.View.Selections.Count == 0)\r
- return 0;\r
- Selection last = this.View.Selections.Last();\r
- return last.start + last.length - this.SelectionStart;\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// 選択範囲内の文字列を返す\r
- /// </summary>\r
- /// <remarks>\r
- /// 未選択状態で代入したときは追加され、そうでない場合は選択範囲の文字列と置き換えられます。\r
- /// </remarks>\r
- public string SelectedText\r
- {\r
- get\r
- {\r
- if (this.View.LayoutLines.Count == 0 || this.View.Selections.Count == 0)\r
- return null;\r
- if (this.RectSelection)\r
- return GetTextFromRectangleSelectArea(this.View.Selections);\r
- else\r
- return GetTextFromLineSelectArea(this.View.Selections).Replace(Document.NewLine.ToString(), Environment.NewLine);\r
- }\r
- set\r
- {\r
- if (this.Document.FireUpdateEvent == false)\r
- throw new InvalidOperationException("");\r
- if (value == null)\r
- return;\r
- this.RepleaceSelectionArea(this.View.Selections, value.Replace(Environment.NewLine,Document.NewLine.ToString()));\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// 選択範囲が逆転しているかどうかを判定する\r
- /// </summary>\r
- /// <returns>逆転しているなら真を返す</returns>\r
- public bool IsReverseSelect()\r
- {\r
- int index = this.View.LayoutLines.GetIndexFromTextPoint(this.View.CaretPostion);\r
- return index < this.AnchorIndex;\r
- }\r
-\r
- /// <summary>\r
- /// 指定された範囲を選択する\r
- /// </summary>\r
- /// <param name="start"></param>\r
- /// <param name="length"></param>\r
- /// <remarks>RectSelectionの値によって動作が変わります。真の場合は矩形選択モードに、そうでない場合は行ごとに選択されます</remarks>\r
- public void Select(int start, int length)\r
- {\r
- if (this.Document.FireUpdateEvent == false)\r
- throw new InvalidOperationException("");\r
- if (start < 0 || start + length < 0 || start + length > this.Document.Length)\r
- throw new ArgumentOutOfRangeException("startかendが指定できる範囲を超えてます");\r
- this.View.Selections.Clear();\r
- if (length < 0)\r
- {\r
- int oldStart = start;\r
- start += length;\r
- length = oldStart - start;\r
- }\r
- if (this.RectSelection && length != 0)\r
- {\r
- TextPoint startTextPoint = this.View.GetLayoutLineFromIndex(start);\r
- TextPoint endTextPoint = this.View.GetLayoutLineFromIndex(start + length);\r
- this.SelectByRectangle(new TextRectangle(startTextPoint, endTextPoint));\r
- if (startTextPoint.col == endTextPoint.col)\r
- this.View.InsertPoint = new SelectCollection(this.View.Selections);\r
- else\r
- this.View.InsertPoint = null;\r
- }\r
- else if(length != 0)\r
- {\r
- this.View.Selections.Add(Selection.Create(start, length));\r
- this.View.InsertPoint = null;\r
- }\r
- this.SelectionChanged(this, null);\r
- }\r
-\r
- public void Select(TextPoint tp, int width, int height)\r
- {\r
- if (this.Document.FireUpdateEvent == false || !this.RectSelection)\r
- throw new InvalidOperationException("");\r
- TextPoint end = tp;\r
-\r
- end.row = tp.row + height;\r
- end.col = tp.col + width;\r
- \r
- if (end.row > this.View.LayoutLines.Count - 1)\r
- throw new ArgumentOutOfRangeException("");\r
- \r
- this.View.Selections.Clear();\r
- \r
- this.SelectByRectangle(new TextRectangle(tp,end));\r
- \r
- if (width == 0)\r
- this.View.InsertPoint = new SelectCollection(this.View.Selections);\r
- else\r
- this.View.InsertPoint = null;\r
-\r
- this.SelectionChanged(this, null);\r
- }\r
-\r
- private void SelectByRectangle(TextRectangle rect)\r
- {\r
- if (this.Document.FireUpdateEvent == false)\r
- throw new InvalidOperationException("");\r
- if (rect.TopLeft <= rect.BottomRight)\r
- {\r
- for (int i = rect.TopLeft.row; i <= rect.BottomLeft.row; i++)\r
- {\r
- int length = this.View.LayoutLines.GetLengthFromLineNumber(i);\r
- int leftCol = rect.TopLeft.col, rightCol = rect.TopRight.col, lastCol = length;\r
- if(length > 0 && this.View.LayoutLines[i][length - 1] == Document.NewLine)\r
- lastCol = length - 1;\r
- if (lastCol < 0)\r
- lastCol = 0;\r
- if (rect.TopLeft.col > lastCol)\r
- leftCol = lastCol;\r
- if (rect.TopRight.col > lastCol)\r
- rightCol = lastCol;\r
-\r
- int StartIndex = this.View.LayoutLines.GetIndexFromTextPoint(new TextPoint(i, leftCol));\r
- int EndIndex = this.View.LayoutLines.GetIndexFromTextPoint(new TextPoint(i, rightCol));\r
-\r
- Selection sel;\r
- sel = Selection.Create(StartIndex, EndIndex - StartIndex);\r
-\r
- this.View.Selections.Add(sel);\r
- }\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// 単語単位で選択する\r
- /// </summary>\r
- /// <param name="index">探索を開始するインデックス</param>\r
- public void SelectWord(int index)\r
- {\r
- if (this.Document.FireUpdateEvent == false)\r
- throw new InvalidOperationException("");\r
-\r
- if (this.Document.Length <= 0 || index >= this.Document.Length)\r
- return;\r
-\r
- Document str = this.Document;\r
-\r
- int start = index;\r
- while (start > 0 && !Util.IsWordSeparator(str[start]))\r
- start--;\r
-\r
- if (Util.IsWordSeparator(str[start]))\r
- start++;\r
-\r
- int end = index;\r
- while (end < this.Document.Length && !Util.IsWordSeparator(str[end]))\r
- end++;\r
-\r
- this.Select(start, end - start);\r
- }\r
-\r
- /// <summary>\r
- /// 選択範囲内のUTF32コードポイントを文字列に変換します\r
- /// </summary>\r
- /// <returns>成功した場合は真。そうでない場合は偽を返す</returns>\r
- public bool ConvertToChar()\r
- {\r
- if (this.SelectionLength == 0 || this.RectSelection)\r
- return false;\r
- string str = this.Document.ToString(this.SelectionStart, this.SelectionLength);\r
- string[] codes = str.Split(new char[] { ' ' },StringSplitOptions.RemoveEmptyEntries);\r
- StringBuilder result = new StringBuilder();\r
- foreach (string code in codes)\r
- {\r
- int utf32_code;\r
- if (code[0] != 'U')\r
- return false;\r
- if (Int32.TryParse(code.TrimStart('U'),NumberStyles.HexNumber,null, out utf32_code))\r
- result.Append(Char.ConvertFromUtf32(utf32_code));\r
- else\r
- return false;\r
- }\r
- this.Document.Lock();\r
- this.Document.Replace(this.SelectionStart, this.SelectionLength, result.ToString());\r
- this.Document.UnLock();\r
- return true;\r
- }\r
-\r
- /// <summary>\r
- /// 選択文字列をUTF32のコードポイントに変換します\r
- /// </summary>\r
- public void ConvertToCodePoint()\r
- {\r
- if (this.SelectionLength == 0 || this.RectSelection)\r
- return;\r
- string str = this.Document.ToString(this.SelectionStart, this.SelectionLength);\r
- StringInfo info = new StringInfo(str);\r
- StringBuilder result = new StringBuilder();\r
- for (int i = 0; i < str.Length;)\r
- {\r
- int utf32_code = Char.ConvertToUtf32(str, i); \r
- result.Append("U" + Convert.ToString(utf32_code,16));\r
- result.Append(' ');\r
- if(Char.IsHighSurrogate(str[i]))\r
- i += 2;\r
- else\r
- i++;\r
- }\r
- this.Document.Lock();\r
- this.Document.Replace(this.SelectionStart, this.SelectionLength, result.ToString());\r
- this.Document.UnLock();\r
- }\r
-\r
- /// <summary>\r
- /// 選択を解除する\r
- /// </summary>\r
- public void DeSelectAll()\r
- {\r
- if (this.Document.FireUpdateEvent == false)\r
- throw new InvalidOperationException("");\r
-\r
- this.View.Selections.Clear();\r
- }\r
-\r
- /// <summary>\r
- /// 任意のマーカーかどうか\r
- /// </summary>\r
- /// <param name="tp"></param>\r
- /// <param name="type"></param>\r
- /// <returns>真ならマーカーがある</returns>\r
- public bool IsMarker(TextPoint tp,HilightType type)\r
- {\r
- if (this.Document.FireUpdateEvent == false)\r
- throw new InvalidOperationException("");\r
- int index = this.View.LayoutLines.GetIndexFromTextPoint(tp);\r
- return this.IsMarker(index, type);\r
- }\r
-\r
- /// <summary>\r
- /// 任意のマーカーかどうか判定する\r
- /// </summary>\r
- /// <param name="index"></param>\r
- /// <param name="type"></param>\r
- /// <returns>真ならマーカーがある</returns>\r
- public bool IsMarker(int index, HilightType type)\r
- {\r
- foreach(int id in this.Document.Markers.IDs)\r
- {\r
- foreach (Marker m in this.Document.GetMarkers(index, id))\r
- {\r
- if (m.hilight == type)\r
- return true;\r
- }\r
- }\r
- return false;\r
- }\r
-\r
- /// <summary>\r
- /// キャレット位置を再調整する\r
- /// </summary>\r
- public void AdjustCaret()\r
- {\r
- int row = this.View.CaretPostion.row;\r
- if (row > this.View.LayoutLines.Count - 1)\r
- row = this.View.LayoutLines.Count - 1;\r
- int col = this.View.CaretPostion.col;\r
- if (col > 0 && col > this.View.LayoutLines[row].Length)\r
- col = this.View.LayoutLines[row].Length;\r
- this.JumpCaret(row, col);\r
- }\r
-\r
- /// <summary>\r
- /// キャレットを指定した位置に移動させる\r
- /// </summary>\r
- /// <param name="index"></param>\r
- /// <param name="autoExpand">折り畳みを展開するなら真</param>\r
- public void JumpCaret(int index,bool autoExpand = true)\r
- {\r
- if (index < 0 || index > this.Document.Length)\r
- throw new ArgumentOutOfRangeException("indexが設定できる範囲を超えています");\r
- TextPoint tp = this.View.GetLayoutLineFromIndex(index);\r
-\r
- this.JumpCaret(tp.row, tp.col,autoExpand);\r
- }\r
-\r
- /// <summary>\r
- /// キャレットを指定した位置に移動させる\r
- /// </summary>\r
- /// <param name="row"></param>\r
- /// <param name="col"></param>\r
- /// <param name="autoExpand">折り畳みを展開するなら真</param>\r
- public void JumpCaret(int row, int col, bool autoExpand = true)\r
- {\r
- if (this.Document.FireUpdateEvent == false)\r
- throw new InvalidOperationException("");\r
-\r
- this.View.JumpCaret(row, col,autoExpand);\r
-\r
- this.View.AdjustCaretAndSrc();\r
-\r
- this.SelectWithMoveCaret(false);\r
- }\r
-\r
- /// <summary>\r
- /// 行の先頭に移動する\r
- /// </summary>\r
- /// <param name="row">行</param>\r
- /// <param name="isSelected">選択状態にするかどうか</param>\r
- public void JumpToLineHead(int row,bool isSelected)\r
- {\r
- this.View.JumpCaret(row, 0);\r
- this.View.AdjustCaretAndSrc();\r
- this.SelectWithMoveCaret(isSelected);\r
- }\r
-\r
- /// <summary>\r
- /// 行の終わりに移動する\r
- /// </summary>\r
- /// <param name="row">行</param>\r
- /// <param name="isSelected">選択状態にするかどうか</param>\r
- public void JumpToLineEnd(int row, bool isSelected)\r
- {\r
- this.View.JumpCaret(row, this.View.LayoutLines[row].Length - 1);\r
- this.View.AdjustCaretAndSrc();\r
- this.SelectWithMoveCaret(isSelected);\r
- }\r
-\r
- /// <summary>\r
- /// ドキュメントの先頭に移動する\r
- /// </summary>\r
- /// <param name="isSelected"></param>\r
- public void JumpToHead(bool isSelected)\r
- {\r
- if (this.View.TryScroll(0, 0))\r
- return;\r
- this.View.JumpCaret(0, 0);\r
- this.View.AdjustCaretAndSrc();\r
- this.SelectWithMoveCaret(isSelected);\r
- }\r
-\r
- /// <summary>\r
- /// ドキュメントの終わりにに移動する\r
- /// </summary>\r
- /// <param name="isSelected"></param>\r
- public void JumpToEnd(bool isSelected)\r
- {\r
- int srcRow = this.View.LayoutLines.Count - this.View.LineCountOnScreen - 1;\r
- if(srcRow < 0)\r
- srcRow = 0;\r
- if (this.View.TryScroll(0, srcRow))\r
- return;\r
- this.View.JumpCaret(this.View.LayoutLines.Count - 1, 0);\r
- this.View.AdjustCaretAndSrc();\r
- this.SelectWithMoveCaret(isSelected);\r
- }\r
-\r
- /// <summary>\r
- /// スクロールする\r
- /// </summary>\r
- /// <param name="dir">方向を指定する</param>\r
- /// <param name="delta">スクロールする量。ScrollDirectionの値がUpやDownなら行数。LeftやRightならピクセル単位の値となる</param>\r
- /// <param name="isSelected">選択状態にするなら真</param>\r
- /// <param name="withCaret">同時にキャレットを移動させるなら真</param>\r
- public void Scroll(ScrollDirection dir, int delta, bool isSelected,bool withCaret)\r
- {\r
- if (this.Document.FireUpdateEvent == false)\r
- throw new InvalidOperationException("");\r
- int toRow = this.View.Src.Row;\r
- double toX = this.View.Src.X;\r
- switch (dir)\r
- {\r
- case ScrollDirection.Up:\r
- toRow = Math.Max(0, this.View.Src.Row - delta);\r
- toRow = this.View.AdjustRow(toRow, false);\r
- break;\r
- case ScrollDirection.Down:\r
- toRow = Math.Min(this.View.Src.Row + delta, this.View.LayoutLines.Count - 1);\r
- toRow = this.View.AdjustRow(toRow, true);\r
- break;\r
- case ScrollDirection.Left:\r
- toX -= delta;\r
- break;\r
- case ScrollDirection.Right:\r
- toX += delta;\r
- break;\r
- default:\r
- throw new ArgumentOutOfRangeException();\r
- }\r
- this.Scroll(toX, toRow, isSelected, withCaret);\r
- }\r
-\r
- /// <summary>\r
- /// スクロールする\r
- /// </summary>\r
- /// <param name="toX">スクロール先の座標</param>\r
- /// <param name="toRow">スクロール先の行</param>\r
- /// <param name="isSelected">選択状態にするなら真</param>\r
- /// <param name="withCaret">同時にキャレットを移動させるなら真</param>\r
- public void Scroll(double toX, int toRow, bool isSelected, bool withCaret)\r
- {\r
- if (withCaret)\r
- {\r
- this.View.Scroll(toX, toRow);\r
- this.View.JumpCaret(toRow, 0);\r
- this.View.AdjustCaretAndSrc();\r
- this.SelectWithMoveCaret(isSelected);\r
- }\r
- else\r
- {\r
- this.View.Scroll(toX, toRow);\r
- this.View.IsFocused = false;\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// キャレットを桁方向に移動させる\r
- /// </summary>\r
- /// <returns>移動できない場合は真を返す</returns>\r
- /// <param name="realLength">負の値なら左側へ、そうでないなら右側へ移動する</param>\r
- /// <param name="isSelected">選択範囲とするなら真。そうでないなら偽</param>\r
- /// <param name="alignWord">単語単位で移動するなら真。そうでないなら偽</param>\r
- public void MoveCaretHorizontical(int realLength, bool isSelected,bool alignWord = false)\r
- {\r
- for (int i = Math.Abs(realLength); i > 0; i--)\r
- {\r
- bool MoveFlow = realLength > 0;\r
- if (this.View.render.RightToLeft)\r
- MoveFlow = !MoveFlow;\r
- this.MoveCaretHorizontical(MoveFlow);\r
-\r
- if (alignWord)\r
- this.AlignNearestWord(MoveFlow);\r
- }\r
- this.View.AdjustCaretAndSrc(AdjustFlow.Col);\r
- this.SelectWithMoveCaret(isSelected);\r
- }\r
-\r
- void AlignNearestWord(bool MoveFlow)\r
- {\r
- string str = this.View.LayoutLines[this.View.CaretPostion.row];\r
- while (this.View.CaretPostion.col > 0 &&\r
- this.View.CaretPostion.col < str.Length &&\r
- str[this.View.CaretPostion.col] != Document.NewLine)\r
- {\r
- if (!Util.IsWordSeparator(str[this.View.CaretPostion.col]))\r
- {\r
- this.MoveCaretHorizontical(MoveFlow);\r
- }\r
- else\r
- {\r
- if(MoveFlow)\r
- this.MoveCaretHorizontical(MoveFlow);\r
- break;\r
- }\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// キャレットを行方向に移動させる\r
- /// </summary>\r
- /// <returns>再描写する必要があるなら真を返す</returns>\r
- /// <param name="deltarow">移動量</param>\r
- /// <param name="isSelected"></param>\r
- public void MoveCaretVertical(int deltarow,bool isSelected)\r
- {\r
- for (int i = Math.Abs(deltarow); i > 0; i--)\r
- this.MoveCaretVertical(deltarow > 0);\r
- this.View.AdjustCaretAndSrc(AdjustFlow.Both);\r
- this.SelectWithMoveCaret(isSelected);\r
- }\r
-\r
- /// <summary>\r
- /// キャレット位置の文字を一文字削除する\r
- /// </summary>\r
- public void DoDeleteAction()\r
- {\r
- if (this.SelectionLength != 0)\r
- {\r
- this.SelectedText = "";\r
- return;\r
- }\r
- \r
- if (this.Document.FireUpdateEvent == false)\r
- throw new InvalidOperationException("");\r
-\r
- TextPoint CaretPostion = this.View.CaretPostion;\r
- int index = this.View.GetIndexFromLayoutLine(CaretPostion);\r
-\r
- if (index == this.Document.Length)\r
- return;\r
-\r
- int lineHeadIndex = this.View.LayoutLines.GetIndexFromLineNumber(CaretPostion.row);\r
- int next = this.View.LayoutLines.GetLayout(CaretPostion.row).AlignIndexToNearestCluster(CaretPostion.col, AlignDirection.Forward) + lineHeadIndex;\r
-\r
- if (this.Document[index] == Document.NewLine)\r
- next = index + 1;\r
-\r
- this.Document.Lock();\r
- this.Document.Replace(index, next - index, "");\r
- this.Document.UnLock();\r
- }\r
-\r
- /// <summary>\r
- /// キャレット位置の文字を一文字削除し、キャレット位置を後ろにずらす\r
- /// </summary>\r
- public void DoBackSpaceAction()\r
- {\r
- if (this.View.InsertPoint != null)\r
- {\r
- this.ReplaceBeforeSelectionArea(this.View.Selections, 1, "");\r
- return;\r
- }\r
- else if (this.SelectionLength > 0)\r
- {\r
- this.SelectedText = "";\r
- return;\r
- }\r
-\r
- if (this.Document.FireUpdateEvent == false)\r
- throw new InvalidOperationException("");\r
-\r
- TextPoint CurrentPostion = this.View.CaretPostion;\r
-\r
- if (CurrentPostion.row == 0 && CurrentPostion.col == 0)\r
- return;\r
-\r
- int oldIndex = this.View.GetIndexFromLayoutLine(CurrentPostion);\r
-\r
- int newCol, newIndex;\r
- if (CurrentPostion.col > 0)\r
- {\r
- newCol = this.View.LayoutLines.GetLayout(CurrentPostion.row).AlignIndexToNearestCluster(CurrentPostion.col - 1, AlignDirection.Back);\r
- newIndex = this.View.GetIndexFromLayoutLine(new TextPoint(CurrentPostion.row, newCol));\r
- }\r
- else\r
- {\r
- newIndex = this.View.GetIndexFromLayoutLine(CurrentPostion);\r
- newIndex--;\r
- }\r
-\r
- this.Document.Lock();\r
- this.Document.Replace(newIndex, oldIndex - newIndex, "");\r
- this.Document.UnLock();\r
- }\r
-\r
- /// <summary>\r
- /// キャレット位置で行を分割する\r
- /// </summary>\r
- public void DoEnterAction()\r
- { \r
- this.DoInputChar('\n');\r
- }\r
-\r
- /// <summary>\r
- /// キャレット位置に文字を入力し、その分だけキャレットを進める。isInsertModeの値により動作が変わります\r
- /// </summary>\r
- /// <param name="ch"></param>\r
- public void DoInputChar(char ch)\r
- {\r
- this.DoInputString(ch.ToString());\r
- }\r
-\r
- string GetIndentSpace(int col_index)\r
- {\r
- int space_count = this.View.TabStops - (col_index % this.View.TabStops);\r
- return new string(Enumerable.Repeat(' ',space_count).ToArray());\r
- }\r
-\r
- /// <summary>\r
- /// キャレット位置に文字列を挿入し、その分だけキャレットを進める。isInsertModeの値により動作が変わります\r
- /// </summary>\r
- /// <param name="str"></param>\r
- /// <param name="fromTip"></param>\r
- public void DoInputString(string str,bool fromTip = false)\r
- {\r
- TextPoint CaretPos = this.View.CaretPostion;\r
-\r
- if (str == "\t" && this.IndentMode == IndentMode.Space)\r
- str = this.GetIndentSpace(CaretPos.col);\r
-\r
- if (this.View.InsertPoint != null)\r
- {\r
- this.ReplaceBeforeSelectionArea(this.View.Selections, 0, str);\r
- return;\r
- }\r
- else if (this.SelectionLength != 0)\r
- {\r
- this.RepleaceSelectionArea(this.View.Selections, str, fromTip);\r
- return;\r
- }\r
-\r
- if (this.Document.FireUpdateEvent == false)\r
- throw new InvalidOperationException("");\r
-\r
- int index = this.View.GetIndexFromLayoutLine(this.View.CaretPostion);\r
- int length = 0;\r
- if (this.View.InsertMode == false && index < this.Document.Length && this.Document[index] != Document.NewLine)\r
- {\r
- string lineString = this.View.LayoutLines[CaretPos.row];\r
- int end = this.View.LayoutLines.GetLayout(CaretPos.row).AlignIndexToNearestCluster(CaretPos.col + str.Length - 1, AlignDirection.Forward);\r
- if (end > lineString.Length - 1)\r
- end = lineString.Length - 1;\r
- end += this.View.LayoutLines.GetIndexFromLineNumber(CaretPos.row);\r
- length = end - index;\r
- }\r
- if (str == Document.NewLine.ToString())\r
- {\r
- int lineHeadIndex = this.View.LayoutLines.GetIndexFromLineNumber(CaretPos.row);\r
- int lineLength = this.View.LayoutLines.GetLengthFromLineNumber(CaretPos.row);\r
- FoldingItem foldingData = this.View.LayoutLines.FoldingCollection.GetFarestHiddenFoldingData(lineHeadIndex, lineLength);\r
- if (foldingData != null && !foldingData.Expand && index > foldingData.Start && index <= foldingData.End)\r
- index = foldingData.End + 1;\r
- }\r
- this.Document.Lock();\r
- this.Document.Replace(index, length, str);\r
- this.Document.UnLock();\r
- }\r
-\r
- /// <summary>\r
- /// キャレットの移動に合わせて選択する\r
- /// </summary>\r
- /// <param name="isSelected">選択状態にするかどうか</param>\r
- /// <remarks>\r
- /// キャレットを移動後、このメソッドを呼び出さない場合、Select()メソッドは正常に機能しません\r
- /// </remarks>\r
- void SelectWithMoveCaret(bool isSelected)\r
- {\r
- if (this.View.CaretPostion.col < 0 || this.View.CaretPostion.row < 0)\r
- return;\r
-\r
- if (this.Document.FireUpdateEvent == false)\r
- throw new InvalidOperationException("");\r
-\r
- int CaretPostion = this.View.GetIndexFromLayoutLine(this.View.CaretPostion);\r
- \r
- SelectCollection Selections = this.View.Selections;\r
- if (isSelected)\r
- {\r
- this.Select(this.AnchorIndex, CaretPostion - this.AnchorIndex);\r
- }else{\r
- this.AnchorIndex = CaretPostion;\r
- this.View.InsertPoint = null;\r
- this.Select(CaretPostion, 0);\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// JumpCaretで移動した位置からキャレットを移動し、選択状態にする\r
- /// </summary>\r
- /// <param name="tp"></param>\r
- public void MoveCaretAndSelect(TextPoint tp)\r
- {\r
- int CaretPostion = this.View.GetIndexFromLayoutLine(tp);\r
- this.Select(this.AnchorIndex, CaretPostion - this.AnchorIndex);\r
- this.View.JumpCaret(tp.row, tp.col);\r
- this.View.AdjustCaretAndSrc();\r
- }\r
-\r
- public void MoveSelectBefore(TextPoint tp)\r
- {\r
- int NewAnchorIndex;\r
- int SelectionLength;\r
- if (this.IsReverseSelect())\r
- {\r
- NewAnchorIndex = this.View.GetIndexFromLayoutLine(tp);\r
- SelectionLength = this.SelectionLength + NewAnchorIndex - this.AnchorIndex;\r
- this.Select(this.SelectionStart, SelectionLength);\r
- }\r
- else\r
- {\r
- NewAnchorIndex = this.View.GetIndexFromLayoutLine(tp);\r
- SelectionLength = this.SelectionLength + this.AnchorIndex - NewAnchorIndex;\r
- this.Select(NewAnchorIndex, SelectionLength);\r
- }\r
- this.AnchorIndex = NewAnchorIndex;\r
- }\r
-\r
- /// <summary>\r
- /// キャレット位置を既定の位置に戻す\r
- /// </summary>\r
- public void ResetCaretPostion()\r
- {\r
- this.JumpCaret(0);\r
- }\r
-\r
- /// <summary>\r
- /// 行単位で移動後のキャレット位置を取得する\r
- /// </summary>\r
- /// <param name="count">移動量</param>\r
- /// <param name="current">現在のキャレット位置</param>\r
- /// <returns>移動後のキャレット位置</returns>\r
- public TextPoint GetTextPointAfterMoveLine(int count, TextPoint current)\r
- {\r
- int row = current.row + count;\r
-\r
- if (row < 0)\r
- row = 0;\r
- else if (row >= this.View.LayoutLines.Count)\r
- row = this.View.LayoutLines.Count - 1;\r
-\r
- row = this.View.AdjustRow(row, count > 0);\r
-\r
- double colpos = this.View.GetColPostionFromIndex(current.row, current.col);\r
- int col = this.View.GetIndexFromColPostion(row, colpos);\r
-\r
- return new TextPoint(row, col);\r
- }\r
-\r
- /// <summary>\r
- /// 選択文字列のインデントを一つ増やす\r
- /// </summary>\r
- public void UpIndent()\r
- {\r
- if (this.RectSelection || this.SelectionLength == 0)\r
- return;\r
- int selectionStart = this.SelectionStart;\r
- string insertStr = this.IndentMode == IndentMode.Space ? this.GetIndentSpace(0) : "\t";\r
- string text = this.InsertLineHead(GetTextFromLineSelectArea(this.View.Selections), insertStr);\r
- this.RepleaceSelectionArea(this.View.Selections,text);\r
- this.Select(selectionStart, text.Length);\r
- }\r
-\r
- /// <summary>\r
- /// 選択文字列のインデントを一つ減らす\r
- /// </summary>\r
- public void DownIndent()\r
- {\r
- if (this.RectSelection || this.SelectionLength == 0)\r
- return;\r
- int selectionStart = this.SelectionStart;\r
- string insertStr = this.IndentMode == IndentMode.Space ? this.GetIndentSpace(0) : "\t";\r
- string text = this.RemoveLineHead(GetTextFromLineSelectArea(this.View.Selections), insertStr);\r
- this.RepleaceSelectionArea(this.View.Selections, text);\r
- this.Select(selectionStart, text.Length);\r
- }\r
-\r
- string InsertLineHead(string s, string str)\r
- {\r
- string[] lines = s.Split(new string[] { Document.NewLine.ToString() }, StringSplitOptions.None);\r
- StringBuilder output = new StringBuilder();\r
- for (int i = 0; i < lines.Length; i++)\r
- {\r
- if(lines[i].Length > 0)\r
- output.Append(str + lines[i] + Document.NewLine);\r
- else if(i < lines.Length - 1)\r
- output.Append(lines[i] + Document.NewLine);\r
- }\r
- return output.ToString();\r
- }\r
-\r
- public string RemoveLineHead(string s, string str)\r
- {\r
- string[] lines = s.Split(new string[] { Document.NewLine.ToString() }, StringSplitOptions.None);\r
- StringBuilder output = new StringBuilder();\r
- for (int i = 0; i < lines.Length; i++)\r
- {\r
- if (lines[i].StartsWith(str))\r
- output.Append(lines[i].Substring(1) + Document.NewLine);\r
- else if (i < lines.Length - 1)\r
- output.Append(lines[i] + Document.NewLine);\r
- }\r
- return output.ToString();\r
- }\r
-\r
- /// <summary>\r
- /// キャレットを一文字移動させる\r
- /// </summary>\r
- /// <param name="isMoveNext">真なら1文字すすめ、そうでなければ戻す</param>\r
- /// <remarks>このメソッドを呼び出した後でScrollToCaretメソッドとSelectWithMoveCaretメソッドを呼び出す必要があります</remarks>\r
- void MoveCaretHorizontical(bool isMoveNext)\r
- {\r
- if (this.Document.FireUpdateEvent == false)\r
- throw new InvalidOperationException("");\r
- int delta = isMoveNext ? 0 : -1;\r
- int prevcol = this.View.CaretPostion.col;\r
- int col = this.View.CaretPostion.col + delta;\r
- string lineString = this.View.LayoutLines[this.View.CaretPostion.row];\r
- if (col < 0 || this.View.CaretPostion.row >= this.View.LayoutLines.Count)\r
- {\r
- if (this.View.CaretPostion.row == 0)\r
- {\r
- col = 0;\r
- return;\r
- }\r
- this.MoveCaretVertical(false);\r
- this.View.AdjustCaretAndSrc(AdjustFlow.Row); //この段階で調整しないとスクロールされない\r
- col = this.View.LayoutLines.GetLengthFromLineNumber(this.View.CaretPostion.row) - 1; //最終行以外はすべて改行コードが付くはず\r
- }\r
- else if (col >= lineString.Length || lineString[col] == Document.NewLine)\r
- {\r
- if (this.View.CaretPostion.row < this.View.LayoutLines.Count - 1)\r
- {\r
- this.MoveCaretVertical(true);\r
- this.View.AdjustCaretAndSrc(AdjustFlow.Row); //この段階で調整しないとスクロールされない\r
- col = 0;\r
- }\r
- }\r
- else\r
- {\r
- AlignDirection direction = isMoveNext ? AlignDirection.Forward : AlignDirection.Back;\r
- col = this.View.LayoutLines.GetLayout(this.View.CaretPostion.row).AlignIndexToNearestCluster(col, direction);\r
- }\r
-\r
- this.View.JumpCaret(this.View.CaretPostion.row, col,false);\r
- }\r
-\r
- /// <summary>\r
- /// キャレットを行方向に移動させる\r
- /// </summary>\r
- /// <param name="isMoveNext">プラス方向に移動するなら真</param>\r
- /// <remarks>このメソッドを呼び出した後でScrollToCaretメソッドとSelectWithMoveCaretメソッドを呼び出す必要があります</remarks>\r
- void MoveCaretVertical(bool isMoveNext)\r
- {\r
- if (this.Document.FireUpdateEvent == false)\r
- throw new InvalidOperationException("");\r
-\r
- TextPoint nextPoint = this.GetTextPointAfterMoveLine(isMoveNext ? 1 : -1, this.View.CaretPostion);\r
- \r
- this.View.JumpCaret(nextPoint.row, nextPoint.col,false);\r
- }\r
-\r
- private void ReplaceBeforeSelectionArea(SelectCollection Selections, int removeLength, string insertStr)\r
- {\r
- if (removeLength == 0 && insertStr.Length == 0)\r
- return;\r
-\r
- if (this.RectSelection == false || this.Document.FireUpdateEvent == false)\r
- throw new InvalidOperationException();\r
-\r
- SelectCollection temp = this.View.InsertPoint;\r
- int selectStart = temp.First().start;\r
- int selectEnd = temp.Last().start + temp.Last().length;\r
-\r
- //ドキュメント操作後に行うとうまくいかないので、あらかじめ取得しておく\r
- TextPoint start = this.View.LayoutLines.GetTextPointFromIndex(selectStart);\r
- TextPoint end = this.View.LayoutLines.GetTextPointFromIndex(selectEnd);\r
-\r
- bool reverse = temp.First().start > temp.Last().start;\r
-\r
- int lineHeadIndex = this.View.LayoutLines.GetIndexFromLineNumber(this.View.LayoutLines.GetLineNumberFromIndex(selectStart));\r
- if (selectStart - removeLength < lineHeadIndex)\r
- return;\r
-\r
- this.Document.UndoManager.BeginUndoGroup();\r
- this.Document.FireUpdateEvent = false;\r
-\r
- if (reverse)\r
- {\r
- for (int i = 0; i < temp.Count; i++)\r
- {\r
- this.ReplaceBeforeSelection(temp[i], removeLength, insertStr);\r
- }\r
- }\r
- else\r
- {\r
- for (int i = temp.Count - 1; i >= 0; i--)\r
- {\r
- this.ReplaceBeforeSelection(temp[i], removeLength, insertStr);\r
- }\r
- }\r
-\r
- this.Document.FireUpdateEvent = true;\r
- this.Document.UndoManager.EndUndoGroup();\r
-\r
- int delta = insertStr.Length - removeLength;\r
- start.col += delta;\r
- end.col += delta;\r
-\r
- if (reverse)\r
- this.JumpCaret(start.row, start.col);\r
- else\r
- this.JumpCaret(end.row, end.col);\r
- \r
- this.Select(start, 0, end.row - start.row);\r
- }\r
-\r
- private void ReplaceBeforeSelection(Selection sel, int removeLength, string insertStr)\r
- {\r
- sel = Util.NormalizeIMaker<Selection>(sel);\r
- this.Document.Lock();\r
- this.Document.Replace(sel.start - removeLength, removeLength, insertStr);\r
- this.Document.UnLock();\r
- }\r
-\r
- private void RepleaceSelectionArea(SelectCollection Selections, string value,bool updateInsertPoint = false)\r
- {\r
- if (value == null)\r
- return;\r
-\r
- if (this.RectSelection == false)\r
- {\r
- Selection sel = Selection.Create(this.AnchorIndex, 0);\r
- if (Selections.Count > 0)\r
- sel = Util.NormalizeIMaker<Selection>(this.View.Selections.First());\r
-\r
- this.Document.Lock();\r
- this.Document.Replace(sel.start, sel.length, value);\r
- this.Document.UnLock();\r
- return;\r
- }\r
-\r
- if (this.Document.FireUpdateEvent == false)\r
- throw new InvalidOperationException("");\r
-\r
- int StartIndex = this.SelectionStart;\r
-\r
- SelectCollection newInsertPoint = new SelectCollection();\r
-\r
- if (this.SelectionLength == 0)\r
- {\r
- int i;\r
-\r
- this.Document.Lock();\r
-\r
- this.Document.UndoManager.BeginUndoGroup();\r
-\r
- this.Document.FireUpdateEvent = false;\r
-\r
- string[] line = value.Split(new string[] { Document.NewLine.ToString() }, StringSplitOptions.RemoveEmptyEntries);\r
-\r
- TextPoint Current = this.View.GetLayoutLineFromIndex(this.SelectionStart);\r
-\r
- for (i = 0; i < line.Length && Current.row < this.View.LayoutLines.Count; i++, Current.row++)\r
- {\r
- if (Current.col > this.View.LayoutLines[Current.row].Length)\r
- Current.col = this.View.LayoutLines[Current.row].Length;\r
- StartIndex = this.View.GetIndexFromLayoutLine(Current);\r
- this.Document.Replace(StartIndex, 0, line[i]);\r
- StartIndex += line[i].Length;\r
- }\r
-\r
- for (; i < line.Length; i++)\r
- {\r
- StartIndex = this.Document.Length;\r
- string str = Document.NewLine + line[i];\r
- this.Document.Replace(StartIndex, 0, str);\r
- StartIndex += str.Length;\r
- }\r
-\r
- this.Document.FireUpdateEvent = true;\r
-\r
- this.Document.UndoManager.EndUndoGroup();\r
-\r
- this.Document.UnLock();\r
- }\r
- else\r
- {\r
- SelectCollection temp = new SelectCollection(this.View.Selections); //コピーしないとReplaceCommandを呼び出した段階で書き換えられてしまう\r
-\r
- this.Document.Lock();\r
-\r
- this.Document.UndoManager.BeginUndoGroup();\r
-\r
- this.Document.FireUpdateEvent = false;\r
-\r
- if (temp.First().start < temp.Last().start)\r
- {\r
- for (int i = temp.Count - 1; i >= 0; i--)\r
- {\r
- Selection sel = Util.NormalizeIMaker<Selection>(temp[i]);\r
-\r
- StartIndex = sel.start;\r
-\r
- this.Document.Replace(sel.start, sel.length, value);\r
-\r
- newInsertPoint.Add(Selection.Create(sel.start + (value.Length - sel.length) * i,0));\r
- }\r
- }\r
- else\r
- {\r
- for (int i = 0; i < temp.Count; i++)\r
- {\r
- Selection sel = Util.NormalizeIMaker<Selection>(temp[i]);\r
-\r
- StartIndex = sel.start;\r
-\r
- this.Document.Replace(sel.start, sel.length, value);\r
-\r
- newInsertPoint.Add(Selection.Create(sel.start + (value.Length - sel.length) * i, 0));\r
- }\r
- }\r
-\r
- this.Document.FireUpdateEvent = true;\r
-\r
- this.Document.UndoManager.EndUndoGroup();\r
-\r
- this.Document.UnLock();\r
- }\r
- this.JumpCaret(StartIndex);\r
- if (updateInsertPoint && newInsertPoint.Count > 0)\r
- this.View.InsertPoint = newInsertPoint;\r
- }\r
-\r
- private string GetTextFromLineSelectArea(SelectCollection Selections)\r
- {\r
- Selection sel = Util.NormalizeIMaker<Selection>(Selections.First());\r
-\r
- string str = this.Document.ToString(sel.start, sel.length);\r
-\r
- return str;\r
- }\r
-\r
- string GetTextFromRectangleSelectArea(SelectCollection Selections)\r
- {\r
- StringBuilder temp = new StringBuilder();\r
- if (Selections.First().start < Selections.Last().start)\r
- {\r
- for (int i = 0; i < this.View.Selections.Count; i++)\r
- {\r
- Selection sel = Util.NormalizeIMaker<Selection>(Selections[i]);\r
-\r
- string str = this.Document.ToString(sel.start, sel.length);\r
- if (str.IndexOf(Environment.NewLine) == -1)\r
- temp.AppendLine(str);\r
- else\r
- temp.Append(str);\r
- }\r
- }\r
- else\r
- {\r
- for (int i = this.View.Selections.Count - 1; i >= 0; i--)\r
- {\r
- Selection sel = Util.NormalizeIMaker<Selection>(Selections[i]);\r
-\r
- string str = this.Document.ToString(sel.start, sel.length).Replace(Document.NewLine.ToString(), Environment.NewLine);\r
- if (str.IndexOf(Environment.NewLine) == -1)\r
- temp.AppendLine(str);\r
- else\r
- temp.Append(str);\r
- }\r
- }\r
- return temp.ToString();\r
- }\r
-\r
- void View_LineBreakChanged(object sender, EventArgs e)\r
- {\r
- this.DeSelectAll();\r
- this.AdjustCaret();\r
- }\r
-\r
- void View_PageBoundChanged(object sender, EventArgs e)\r
- {\r
- if (this.View.LineBreak == LineBreakMethod.PageBound && this.View.PageBound.Width - this.View.LineBreakingMarginWidth > 0)\r
- this.View.PerfomLayouts();\r
- this.AdjustCaret();\r
- }\r
-\r
- void render_ChangedRenderResource(object sender, ChangedRenderRsourceEventArgs e)\r
- {\r
- if (e.type == ResourceType.Font)\r
- {\r
- if (this.View.LineBreak == LineBreakMethod.PageBound)\r
- this.View.PerfomLayouts();\r
- this.AdjustCaret();\r
- }\r
- if (e.type == ResourceType.InlineChar)\r
- {\r
- int oldLineCountOnScreen = this.View.LineCountOnScreen;\r
- this.View.CalculateLineCountOnScreen();\r
- if(this.View.LineCountOnScreen != oldLineCountOnScreen)\r
- this.AdjustCaret();\r
- }\r
- }\r
-\r
- void render_ChangedRightToLeft(object sender, EventArgs e)\r
- {\r
- this.AdjustCaret();\r
- }\r
-\r
- void Document_Update(object sender, DocumentUpdateEventArgs e)\r
- {\r
- switch (e.type)\r
- {\r
- case UpdateType.Replace:\r
- if(e.startIndex < this.Document.Length && this.Document[e.startIndex] == Document.NewLine)\r
- this.View.CalculateLineCountOnScreen();\r
- this.JumpCaret(e.startIndex + e.insertLength,true);\r
- break;\r
- case UpdateType.Clear:\r
- this.JumpCaret(0,0, false);\r
- break;\r
- }\r
- }\r
- }\r
-}\r
+/*
+ * Copyright (C) 2013 FooProject
+ * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+using System.Globalization;
+using System.Text;
+using System.Linq;
+using System.Diagnostics;
+using System.Text.RegularExpressions;
+#if WINFORM
+using System.Drawing;
+#endif
+
+namespace FooEditEngine
+{
+ internal enum MoveFlow
+ {
+ Horizontical,
+ Vertical,
+ }
+ internal enum ScrollDirection
+ {
+ Up,
+ Down,
+ Left,
+ Right,
+ }
+
+ /// <summary>
+ /// インデントの方法を表す
+ /// </summary>
+ public enum IndentMode
+ {
+ Tab,
+ Space,
+ }
+
+ /// <summary>
+ /// ユーザー側からの処理を担当するクラス。一部を除き、こちらで行われた操作はアンドゥの対象になります
+ /// </summary>
+ internal sealed class Controller
+ {
+ EditView View;
+ Document Document;
+ int AnchorIndex;
+
+ public Controller(Document doc, EditView view)
+ {
+ this.Document = doc;
+ this.Document.Update += new DocumentUpdateEventHandler(Document_Update);
+ this.View = view;
+ this.View.render.ChangedRightToLeft += render_ChangedRightToLeft;
+ this.View.render.ChangedRenderResource += render_ChangedRenderResource;
+ this.View.PerformLayouted += View_LineBreakChanged;
+ this.View.PageBoundChanged += View_PageBoundChanged;
+ this.SelectionChanged += new EventHandler((s, e) => { });
+ this.Document.Clear();
+ }
+
+ /// <summary>
+ /// 選択領域変更時に通知される
+ /// </summary>
+ public event EventHandler SelectionChanged;
+
+ /// <summary>
+ /// 矩形選択モードなら真を返し、そうでない場合は偽を返す
+ /// </summary>
+ public bool RectSelection
+ {
+ get;
+ set;
+ }
+
+ /// <summary>
+ /// インデントの方法を表す
+ /// </summary>
+ public IndentMode IndentMode
+ {
+ get;
+ set;
+ }
+
+ /// <summary>
+ /// 選択範囲の開始位置
+ /// </summary>
+ /// <remarks>SelectionLengthが0の場合、キャレット位置を表します</remarks>
+ public int SelectionStart
+ {
+ get
+ {
+ if (this.View.Selections.Count == 0)
+ return this.AnchorIndex;
+ else
+ return this.View.Selections.First().start;
+ }
+ }
+
+ /// <summary>
+ /// 選択範囲の長さ
+ /// </summary>
+ /// <remarks>矩形選択モードの場合、選択範囲の文字数ではなく、開始位置から終了位置までの長さとなります</remarks>
+ public int SelectionLength
+ {
+ get
+ {
+ if (this.View.Selections.Count == 0)
+ return 0;
+ Selection last = this.View.Selections.Last();
+ return last.start + last.length - this.SelectionStart;
+ }
+ }
+
+ /// <summary>
+ /// 選択範囲内の文字列を返す
+ /// </summary>
+ /// <remarks>
+ /// 未選択状態で代入したときは追加され、そうでない場合は選択範囲の文字列と置き換えられます。
+ /// </remarks>
+ public string SelectedText
+ {
+ get
+ {
+ if (this.View.LayoutLines.Count == 0 || this.View.Selections.Count == 0)
+ return null;
+ if (this.RectSelection)
+ return GetTextFromRectangleSelectArea(this.View.Selections);
+ else
+ return GetTextFromLineSelectArea(this.View.Selections).Replace(Document.NewLine.ToString(), Environment.NewLine);
+ }
+ set
+ {
+ if (this.Document.FireUpdateEvent == false)
+ throw new InvalidOperationException("");
+ if (value == null)
+ return;
+ this.RepleaceSelectionArea(this.View.Selections, value.Replace(Environment.NewLine,Document.NewLine.ToString()));
+ }
+ }
+
+ /// <summary>
+ /// 選択範囲が逆転しているかどうかを判定する
+ /// </summary>
+ /// <returns>逆転しているなら真を返す</returns>
+ public bool IsReverseSelect()
+ {
+ int index = this.View.LayoutLines.GetIndexFromTextPoint(this.View.CaretPostion);
+ return index < this.AnchorIndex;
+ }
+
+ /// <summary>
+ /// 指定された範囲を選択する
+ /// </summary>
+ /// <param name="start"></param>
+ /// <param name="length"></param>
+ /// <remarks>RectSelectionの値によって動作が変わります。真の場合は矩形選択モードに、そうでない場合は行ごとに選択されます</remarks>
+ public void Select(int start, int length)
+ {
+ if (this.Document.FireUpdateEvent == false)
+ throw new InvalidOperationException("");
+ if (start < 0 || start + length < 0 || start + length > this.Document.Length)
+ throw new ArgumentOutOfRangeException("startかendが指定できる範囲を超えてます");
+ this.View.Selections.Clear();
+ if (length < 0)
+ {
+ int oldStart = start;
+ start += length;
+ length = oldStart - start;
+ }
+ if (this.RectSelection && length != 0)
+ {
+ TextPoint startTextPoint = this.View.GetLayoutLineFromIndex(start);
+ TextPoint endTextPoint = this.View.GetLayoutLineFromIndex(start + length);
+ this.SelectByRectangle(new TextRectangle(startTextPoint, endTextPoint));
+ if (startTextPoint.col == endTextPoint.col)
+ this.View.InsertPoint = new SelectCollection(this.View.Selections);
+ else
+ this.View.InsertPoint = null;
+ }
+ else if(length != 0)
+ {
+ this.View.Selections.Add(Selection.Create(start, length));
+ this.View.InsertPoint = null;
+ }
+ this.SelectionChanged(this, null);
+ }
+
+ public void Select(TextPoint tp, int width, int height)
+ {
+ if (this.Document.FireUpdateEvent == false || !this.RectSelection)
+ throw new InvalidOperationException("");
+ TextPoint end = tp;
+
+ end.row = tp.row + height;
+ end.col = tp.col + width;
+
+ if (end.row > this.View.LayoutLines.Count - 1)
+ throw new ArgumentOutOfRangeException("");
+
+ this.View.Selections.Clear();
+
+ this.SelectByRectangle(new TextRectangle(tp,end));
+
+ if (width == 0)
+ this.View.InsertPoint = new SelectCollection(this.View.Selections);
+ else
+ this.View.InsertPoint = null;
+
+ this.SelectionChanged(this, null);
+ }
+
+ private void SelectByRectangle(TextRectangle rect)
+ {
+ if (this.Document.FireUpdateEvent == false)
+ throw new InvalidOperationException("");
+ if (rect.TopLeft <= rect.BottomRight)
+ {
+ for (int i = rect.TopLeft.row; i <= rect.BottomLeft.row; i++)
+ {
+ int length = this.View.LayoutLines.GetLengthFromLineNumber(i);
+ int leftCol = rect.TopLeft.col, rightCol = rect.TopRight.col, lastCol = length;
+ if(length > 0 && this.View.LayoutLines[i][length - 1] == Document.NewLine)
+ lastCol = length - 1;
+ if (lastCol < 0)
+ lastCol = 0;
+ if (rect.TopLeft.col > lastCol)
+ leftCol = lastCol;
+ if (rect.TopRight.col > lastCol)
+ rightCol = lastCol;
+
+ int StartIndex = this.View.LayoutLines.GetIndexFromTextPoint(new TextPoint(i, leftCol));
+ int EndIndex = this.View.LayoutLines.GetIndexFromTextPoint(new TextPoint(i, rightCol));
+
+ Selection sel;
+ sel = Selection.Create(StartIndex, EndIndex - StartIndex);
+
+ this.View.Selections.Add(sel);
+ }
+ }
+ }
+
+ /// <summary>
+ /// 単語単位で選択する
+ /// </summary>
+ /// <param name="index">探索を開始するインデックス</param>
+ public void SelectWord(int index)
+ {
+ if (this.Document.FireUpdateEvent == false)
+ throw new InvalidOperationException("");
+
+ if (this.Document.Length <= 0 || index >= this.Document.Length)
+ return;
+
+ Document str = this.Document;
+
+ int start = index;
+ while (start > 0 && !Util.IsWordSeparator(str[start]))
+ start--;
+
+ if (Util.IsWordSeparator(str[start]))
+ start++;
+
+ int end = index;
+ while (end < this.Document.Length && !Util.IsWordSeparator(str[end]))
+ end++;
+
+ this.Select(start, end - start);
+ }
+
+ /// <summary>
+ /// 選択範囲内のUTF32コードポイントを文字列に変換します
+ /// </summary>
+ /// <returns>成功した場合は真。そうでない場合は偽を返す</returns>
+ public bool ConvertToChar()
+ {
+ if (this.SelectionLength == 0 || this.RectSelection)
+ return false;
+ string str = this.Document.ToString(this.SelectionStart, this.SelectionLength);
+ string[] codes = str.Split(new char[] { ' ' },StringSplitOptions.RemoveEmptyEntries);
+ StringBuilder result = new StringBuilder();
+ foreach (string code in codes)
+ {
+ int utf32_code;
+ if (code[0] != 'U')
+ return false;
+ if (Int32.TryParse(code.TrimStart('U'),NumberStyles.HexNumber,null, out utf32_code))
+ result.Append(Char.ConvertFromUtf32(utf32_code));
+ else
+ return false;
+ }
+ this.Document.Lock();
+ this.Document.Replace(this.SelectionStart, this.SelectionLength, result.ToString());
+ this.Document.UnLock();
+ return true;
+ }
+
+ /// <summary>
+ /// 選択文字列をUTF32のコードポイントに変換します
+ /// </summary>
+ public void ConvertToCodePoint()
+ {
+ if (this.SelectionLength == 0 || this.RectSelection)
+ return;
+ string str = this.Document.ToString(this.SelectionStart, this.SelectionLength);
+ StringInfo info = new StringInfo(str);
+ StringBuilder result = new StringBuilder();
+ for (int i = 0; i < str.Length;)
+ {
+ int utf32_code = Char.ConvertToUtf32(str, i);
+ result.Append("U" + Convert.ToString(utf32_code,16));
+ result.Append(' ');
+ if(Char.IsHighSurrogate(str[i]))
+ i += 2;
+ else
+ i++;
+ }
+ this.Document.Lock();
+ this.Document.Replace(this.SelectionStart, this.SelectionLength, result.ToString());
+ this.Document.UnLock();
+ }
+
+ /// <summary>
+ /// 選択を解除する
+ /// </summary>
+ public void DeSelectAll()
+ {
+ if (this.Document.FireUpdateEvent == false)
+ throw new InvalidOperationException("");
+
+ this.View.Selections.Clear();
+ }
+
+ /// <summary>
+ /// 任意のマーカーかどうか
+ /// </summary>
+ /// <param name="tp"></param>
+ /// <param name="type"></param>
+ /// <returns>真ならマーカーがある</returns>
+ public bool IsMarker(TextPoint tp,HilightType type)
+ {
+ if (this.Document.FireUpdateEvent == false)
+ throw new InvalidOperationException("");
+ int index = this.View.LayoutLines.GetIndexFromTextPoint(tp);
+ return this.IsMarker(index, type);
+ }
+
+ /// <summary>
+ /// 任意のマーカーかどうか判定する
+ /// </summary>
+ /// <param name="index"></param>
+ /// <param name="type"></param>
+ /// <returns>真ならマーカーがある</returns>
+ public bool IsMarker(int index, HilightType type)
+ {
+ foreach(int id in this.Document.Markers.IDs)
+ {
+ foreach (Marker m in this.Document.GetMarkers(index, id))
+ {
+ if (m.hilight == type)
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /// <summary>
+ /// キャレット位置を再調整する
+ /// </summary>
+ public void AdjustCaret()
+ {
+ int row = this.View.CaretPostion.row;
+ if (row > this.View.LayoutLines.Count - 1)
+ row = this.View.LayoutLines.Count - 1;
+ int col = this.View.CaretPostion.col;
+ if (col > 0 && col > this.View.LayoutLines[row].Length)
+ col = this.View.LayoutLines[row].Length;
+ this.JumpCaret(row, col);
+ }
+
+ /// <summary>
+ /// キャレットを指定した位置に移動させる
+ /// </summary>
+ /// <param name="index"></param>
+ /// <param name="autoExpand">折り畳みを展開するなら真</param>
+ public void JumpCaret(int index,bool autoExpand = true)
+ {
+ if (index < 0 || index > this.Document.Length)
+ throw new ArgumentOutOfRangeException("indexが設定できる範囲を超えています");
+ TextPoint tp = this.View.GetLayoutLineFromIndex(index);
+
+ this.JumpCaret(tp.row, tp.col,autoExpand);
+ }
+
+ /// <summary>
+ /// キャレットを指定した位置に移動させる
+ /// </summary>
+ /// <param name="row"></param>
+ /// <param name="col"></param>
+ /// <param name="autoExpand">折り畳みを展開するなら真</param>
+ public void JumpCaret(int row, int col, bool autoExpand = true)
+ {
+ if (this.Document.FireUpdateEvent == false)
+ throw new InvalidOperationException("");
+
+ this.View.JumpCaret(row, col,autoExpand);
+
+ this.View.AdjustCaretAndSrc();
+
+ this.SelectWithMoveCaret(false);
+ }
+
+ /// <summary>
+ /// 行の先頭に移動する
+ /// </summary>
+ /// <param name="row">行</param>
+ /// <param name="isSelected">選択状態にするかどうか</param>
+ public void JumpToLineHead(int row,bool isSelected)
+ {
+ this.View.JumpCaret(row, 0);
+ this.View.AdjustCaretAndSrc();
+ this.SelectWithMoveCaret(isSelected);
+ }
+
+ /// <summary>
+ /// 行の終わりに移動する
+ /// </summary>
+ /// <param name="row">行</param>
+ /// <param name="isSelected">選択状態にするかどうか</param>
+ public void JumpToLineEnd(int row, bool isSelected)
+ {
+ this.View.JumpCaret(row, this.View.LayoutLines[row].Length - 1);
+ this.View.AdjustCaretAndSrc();
+ this.SelectWithMoveCaret(isSelected);
+ }
+
+ /// <summary>
+ /// ドキュメントの先頭に移動する
+ /// </summary>
+ /// <param name="isSelected"></param>
+ public void JumpToHead(bool isSelected)
+ {
+ if (this.View.TryScroll(0, 0))
+ return;
+ this.View.JumpCaret(0, 0);
+ this.View.AdjustCaretAndSrc();
+ this.SelectWithMoveCaret(isSelected);
+ }
+
+ /// <summary>
+ /// ドキュメントの終わりにに移動する
+ /// </summary>
+ /// <param name="isSelected"></param>
+ public void JumpToEnd(bool isSelected)
+ {
+ int srcRow = this.View.LayoutLines.Count - this.View.LineCountOnScreen - 1;
+ if(srcRow < 0)
+ srcRow = 0;
+ if (this.View.TryScroll(0, srcRow))
+ return;
+ this.View.JumpCaret(this.View.LayoutLines.Count - 1, 0);
+ this.View.AdjustCaretAndSrc();
+ this.SelectWithMoveCaret(isSelected);
+ }
+
+ /// <summary>
+ /// スクロールする
+ /// </summary>
+ /// <param name="dir">方向を指定する</param>
+ /// <param name="delta">スクロールする量。ScrollDirectionの値がUpやDownなら行数。LeftやRightならピクセル単位の値となる</param>
+ /// <param name="isSelected">選択状態にするなら真</param>
+ /// <param name="withCaret">同時にキャレットを移動させるなら真</param>
+ public void Scroll(ScrollDirection dir, int delta, bool isSelected,bool withCaret)
+ {
+ if (this.Document.FireUpdateEvent == false)
+ throw new InvalidOperationException("");
+ int toRow = this.View.Src.Row;
+ double toX = this.View.Src.X;
+ switch (dir)
+ {
+ case ScrollDirection.Up:
+ toRow = Math.Max(0, this.View.Src.Row - delta);
+ toRow = this.View.AdjustRow(toRow, false);
+ break;
+ case ScrollDirection.Down:
+ toRow = Math.Min(this.View.Src.Row + delta, this.View.LayoutLines.Count - 1);
+ toRow = this.View.AdjustRow(toRow, true);
+ break;
+ case ScrollDirection.Left:
+ toX -= delta;
+ break;
+ case ScrollDirection.Right:
+ toX += delta;
+ break;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ this.Scroll(toX, toRow, isSelected, withCaret);
+ }
+
+ /// <summary>
+ /// スクロールする
+ /// </summary>
+ /// <param name="toX">スクロール先の座標</param>
+ /// <param name="toRow">スクロール先の行</param>
+ /// <param name="isSelected">選択状態にするなら真</param>
+ /// <param name="withCaret">同時にキャレットを移動させるなら真</param>
+ public void Scroll(double toX, int toRow, bool isSelected, bool withCaret)
+ {
+ if (withCaret)
+ {
+ this.View.Scroll(toX, toRow);
+ this.View.JumpCaret(toRow, 0);
+ this.View.AdjustCaretAndSrc();
+ this.SelectWithMoveCaret(isSelected);
+ }
+ else
+ {
+ this.View.Scroll(toX, toRow);
+ this.View.IsFocused = false;
+ }
+ }
+
+ /// <summary>
+ /// キャレットを桁方向に移動させる
+ /// </summary>
+ /// <returns>移動できない場合は真を返す</returns>
+ /// <param name="realLength">負の値なら左側へ、そうでないなら右側へ移動する</param>
+ /// <param name="isSelected">選択範囲とするなら真。そうでないなら偽</param>
+ /// <param name="alignWord">単語単位で移動するなら真。そうでないなら偽</param>
+ public void MoveCaretHorizontical(int realLength, bool isSelected,bool alignWord = false)
+ {
+ for (int i = Math.Abs(realLength); i > 0; i--)
+ {
+ bool MoveFlow = realLength > 0;
+ if (this.View.render.RightToLeft)
+ MoveFlow = !MoveFlow;
+ this.MoveCaretHorizontical(MoveFlow);
+
+ if (alignWord)
+ this.AlignNearestWord(MoveFlow);
+ }
+ this.View.AdjustCaretAndSrc(AdjustFlow.Col);
+ this.SelectWithMoveCaret(isSelected);
+ }
+
+ void AlignNearestWord(bool MoveFlow)
+ {
+ string str = this.View.LayoutLines[this.View.CaretPostion.row];
+ while (this.View.CaretPostion.col > 0 &&
+ this.View.CaretPostion.col < str.Length &&
+ str[this.View.CaretPostion.col] != Document.NewLine)
+ {
+ if (!Util.IsWordSeparator(str[this.View.CaretPostion.col]))
+ {
+ this.MoveCaretHorizontical(MoveFlow);
+ }
+ else
+ {
+ if(MoveFlow)
+ this.MoveCaretHorizontical(MoveFlow);
+ break;
+ }
+ }
+ }
+
+ /// <summary>
+ /// キャレットを行方向に移動させる
+ /// </summary>
+ /// <returns>再描写する必要があるなら真を返す</returns>
+ /// <param name="deltarow">移動量</param>
+ /// <param name="isSelected"></param>
+ public void MoveCaretVertical(int deltarow,bool isSelected)
+ {
+ for (int i = Math.Abs(deltarow); i > 0; i--)
+ this.MoveCaretVertical(deltarow > 0);
+ this.View.AdjustCaretAndSrc(AdjustFlow.Both);
+ this.SelectWithMoveCaret(isSelected);
+ }
+
+ /// <summary>
+ /// キャレット位置の文字を一文字削除する
+ /// </summary>
+ public void DoDeleteAction()
+ {
+ if (this.SelectionLength != 0)
+ {
+ this.SelectedText = "";
+ return;
+ }
+
+ if (this.Document.FireUpdateEvent == false)
+ throw new InvalidOperationException("");
+
+ TextPoint CaretPostion = this.View.CaretPostion;
+ int index = this.View.GetIndexFromLayoutLine(CaretPostion);
+
+ if (index == this.Document.Length)
+ return;
+
+ int lineHeadIndex = this.View.LayoutLines.GetIndexFromLineNumber(CaretPostion.row);
+ int next = this.View.LayoutLines.GetLayout(CaretPostion.row).AlignIndexToNearestCluster(CaretPostion.col, AlignDirection.Forward) + lineHeadIndex;
+
+ if (this.Document[index] == Document.NewLine)
+ next = index + 1;
+
+ this.Document.Lock();
+ this.Document.Replace(index, next - index, "");
+ this.Document.UnLock();
+ }
+
+ /// <summary>
+ /// キャレット位置の文字を一文字削除し、キャレット位置を後ろにずらす
+ /// </summary>
+ public void DoBackSpaceAction()
+ {
+ if (this.View.InsertPoint != null)
+ {
+ this.ReplaceBeforeSelectionArea(this.View.Selections, 1, "");
+ return;
+ }
+ else if (this.SelectionLength > 0)
+ {
+ this.SelectedText = "";
+ return;
+ }
+
+ if (this.Document.FireUpdateEvent == false)
+ throw new InvalidOperationException("");
+
+ TextPoint CurrentPostion = this.View.CaretPostion;
+
+ if (CurrentPostion.row == 0 && CurrentPostion.col == 0)
+ return;
+
+ int oldIndex = this.View.GetIndexFromLayoutLine(CurrentPostion);
+
+ int newCol, newIndex;
+ if (CurrentPostion.col > 0)
+ {
+ newCol = this.View.LayoutLines.GetLayout(CurrentPostion.row).AlignIndexToNearestCluster(CurrentPostion.col - 1, AlignDirection.Back);
+ newIndex = this.View.GetIndexFromLayoutLine(new TextPoint(CurrentPostion.row, newCol));
+ }
+ else
+ {
+ newIndex = this.View.GetIndexFromLayoutLine(CurrentPostion);
+ newIndex--;
+ }
+
+ this.Document.Lock();
+ this.Document.Replace(newIndex, oldIndex - newIndex, "");
+ this.Document.UnLock();
+ }
+
+ /// <summary>
+ /// キャレット位置で行を分割する
+ /// </summary>
+ public void DoEnterAction()
+ {
+ this.DoInputChar('\n');
+ }
+
+ /// <summary>
+ /// キャレット位置に文字を入力し、その分だけキャレットを進める。isInsertModeの値により動作が変わります
+ /// </summary>
+ /// <param name="ch"></param>
+ public void DoInputChar(char ch)
+ {
+ this.DoInputString(ch.ToString());
+ }
+
+ string GetIndentSpace(int col_index)
+ {
+ int space_count = this.View.TabStops - (col_index % this.View.TabStops);
+ return new string(Enumerable.Repeat(' ',space_count).ToArray());
+ }
+
+ /// <summary>
+ /// キャレット位置に文字列を挿入し、その分だけキャレットを進める。isInsertModeの値により動作が変わります
+ /// </summary>
+ /// <param name="str"></param>
+ /// <param name="fromTip"></param>
+ public void DoInputString(string str,bool fromTip = false)
+ {
+ TextPoint CaretPos = this.View.CaretPostion;
+
+ if (str == "\t" && this.IndentMode == IndentMode.Space)
+ str = this.GetIndentSpace(CaretPos.col);
+
+ if (this.View.InsertPoint != null)
+ {
+ this.ReplaceBeforeSelectionArea(this.View.Selections, 0, str);
+ return;
+ }
+ else if (this.SelectionLength != 0)
+ {
+ this.RepleaceSelectionArea(this.View.Selections, str, fromTip);
+ return;
+ }
+
+ if (this.Document.FireUpdateEvent == false)
+ throw new InvalidOperationException("");
+
+ int index = this.View.GetIndexFromLayoutLine(this.View.CaretPostion);
+ int length = 0;
+ if (this.View.InsertMode == false && index < this.Document.Length && this.Document[index] != Document.NewLine)
+ {
+ string lineString = this.View.LayoutLines[CaretPos.row];
+ int end = this.View.LayoutLines.GetLayout(CaretPos.row).AlignIndexToNearestCluster(CaretPos.col + str.Length - 1, AlignDirection.Forward);
+ if (end > lineString.Length - 1)
+ end = lineString.Length - 1;
+ end += this.View.LayoutLines.GetIndexFromLineNumber(CaretPos.row);
+ length = end - index;
+ }
+ if (str == Document.NewLine.ToString())
+ {
+ int lineHeadIndex = this.View.LayoutLines.GetIndexFromLineNumber(CaretPos.row);
+ int lineLength = this.View.LayoutLines.GetLengthFromLineNumber(CaretPos.row);
+ FoldingItem foldingData = this.View.LayoutLines.FoldingCollection.GetFarestHiddenFoldingData(lineHeadIndex, lineLength);
+ if (foldingData != null && !foldingData.Expand && index > foldingData.Start && index <= foldingData.End)
+ index = foldingData.End + 1;
+ }
+ this.Document.Lock();
+ this.Document.Replace(index, length, str);
+ this.Document.UnLock();
+ }
+
+ /// <summary>
+ /// キャレットの移動に合わせて選択する
+ /// </summary>
+ /// <param name="isSelected">選択状態にするかどうか</param>
+ /// <remarks>
+ /// キャレットを移動後、このメソッドを呼び出さない場合、Select()メソッドは正常に機能しません
+ /// </remarks>
+ void SelectWithMoveCaret(bool isSelected)
+ {
+ if (this.View.CaretPostion.col < 0 || this.View.CaretPostion.row < 0)
+ return;
+
+ if (this.Document.FireUpdateEvent == false)
+ throw new InvalidOperationException("");
+
+ int CaretPostion = this.View.GetIndexFromLayoutLine(this.View.CaretPostion);
+
+ SelectCollection Selections = this.View.Selections;
+ if (isSelected)
+ {
+ this.Select(this.AnchorIndex, CaretPostion - this.AnchorIndex);
+ }else{
+ this.AnchorIndex = CaretPostion;
+ this.View.InsertPoint = null;
+ this.Select(CaretPostion, 0);
+ }
+ }
+
+ /// <summary>
+ /// JumpCaretで移動した位置からキャレットを移動し、選択状態にする
+ /// </summary>
+ /// <param name="tp"></param>
+ public void MoveCaretAndSelect(TextPoint tp)
+ {
+ int CaretPostion = this.View.GetIndexFromLayoutLine(tp);
+ this.Select(this.AnchorIndex, CaretPostion - this.AnchorIndex);
+ this.View.JumpCaret(tp.row, tp.col);
+ this.View.AdjustCaretAndSrc();
+ }
+
+ public void MoveSelectBefore(TextPoint tp)
+ {
+ int NewAnchorIndex;
+ int SelectionLength;
+ if (this.IsReverseSelect())
+ {
+ NewAnchorIndex = this.View.GetIndexFromLayoutLine(tp);
+ SelectionLength = this.SelectionLength + NewAnchorIndex - this.AnchorIndex;
+ this.Select(this.SelectionStart, SelectionLength);
+ }
+ else
+ {
+ NewAnchorIndex = this.View.GetIndexFromLayoutLine(tp);
+ SelectionLength = this.SelectionLength + this.AnchorIndex - NewAnchorIndex;
+ this.Select(NewAnchorIndex, SelectionLength);
+ }
+ this.AnchorIndex = NewAnchorIndex;
+ }
+
+ /// <summary>
+ /// キャレット位置を既定の位置に戻す
+ /// </summary>
+ public void ResetCaretPostion()
+ {
+ this.JumpCaret(0);
+ }
+
+ /// <summary>
+ /// 行単位で移動後のキャレット位置を取得する
+ /// </summary>
+ /// <param name="count">移動量</param>
+ /// <param name="current">現在のキャレット位置</param>
+ /// <returns>移動後のキャレット位置</returns>
+ public TextPoint GetTextPointAfterMoveLine(int count, TextPoint current)
+ {
+ int row = current.row + count;
+
+ if (row < 0)
+ row = 0;
+ else if (row >= this.View.LayoutLines.Count)
+ row = this.View.LayoutLines.Count - 1;
+
+ row = this.View.AdjustRow(row, count > 0);
+
+ double colpos = this.View.GetColPostionFromIndex(current.row, current.col);
+ int col = this.View.GetIndexFromColPostion(row, colpos);
+
+ return new TextPoint(row, col);
+ }
+
+ /// <summary>
+ /// 選択文字列のインデントを一つ増やす
+ /// </summary>
+ public void UpIndent()
+ {
+ if (this.RectSelection || this.SelectionLength == 0)
+ return;
+ int selectionStart = this.SelectionStart;
+ string insertStr = this.IndentMode == IndentMode.Space ? this.GetIndentSpace(0) : "\t";
+ string text = this.InsertLineHead(GetTextFromLineSelectArea(this.View.Selections), insertStr);
+ this.RepleaceSelectionArea(this.View.Selections,text);
+ this.Select(selectionStart, text.Length);
+ }
+
+ /// <summary>
+ /// 選択文字列のインデントを一つ減らす
+ /// </summary>
+ public void DownIndent()
+ {
+ if (this.RectSelection || this.SelectionLength == 0)
+ return;
+ int selectionStart = this.SelectionStart;
+ string insertStr = this.IndentMode == IndentMode.Space ? this.GetIndentSpace(0) : "\t";
+ string text = this.RemoveLineHead(GetTextFromLineSelectArea(this.View.Selections), insertStr);
+ this.RepleaceSelectionArea(this.View.Selections, text);
+ this.Select(selectionStart, text.Length);
+ }
+
+ string InsertLineHead(string s, string str)
+ {
+ string[] lines = s.Split(new string[] { Document.NewLine.ToString() }, StringSplitOptions.None);
+ StringBuilder output = new StringBuilder();
+ for (int i = 0; i < lines.Length; i++)
+ {
+ if(lines[i].Length > 0)
+ output.Append(str + lines[i] + Document.NewLine);
+ else if(i < lines.Length - 1)
+ output.Append(lines[i] + Document.NewLine);
+ }
+ return output.ToString();
+ }
+
+ public string RemoveLineHead(string s, string str)
+ {
+ string[] lines = s.Split(new string[] { Document.NewLine.ToString() }, StringSplitOptions.None);
+ StringBuilder output = new StringBuilder();
+ for (int i = 0; i < lines.Length; i++)
+ {
+ if (lines[i].StartsWith(str))
+ output.Append(lines[i].Substring(1) + Document.NewLine);
+ else if (i < lines.Length - 1)
+ output.Append(lines[i] + Document.NewLine);
+ }
+ return output.ToString();
+ }
+
+ /// <summary>
+ /// キャレットを一文字移動させる
+ /// </summary>
+ /// <param name="isMoveNext">真なら1文字すすめ、そうでなければ戻す</param>
+ /// <remarks>このメソッドを呼び出した後でScrollToCaretメソッドとSelectWithMoveCaretメソッドを呼び出す必要があります</remarks>
+ void MoveCaretHorizontical(bool isMoveNext)
+ {
+ if (this.Document.FireUpdateEvent == false)
+ throw new InvalidOperationException("");
+ int delta = isMoveNext ? 0 : -1;
+ int prevcol = this.View.CaretPostion.col;
+ int col = this.View.CaretPostion.col + delta;
+ string lineString = this.View.LayoutLines[this.View.CaretPostion.row];
+ if (col < 0 || this.View.CaretPostion.row >= this.View.LayoutLines.Count)
+ {
+ if (this.View.CaretPostion.row == 0)
+ {
+ col = 0;
+ return;
+ }
+ this.MoveCaretVertical(false);
+ this.View.AdjustCaretAndSrc(AdjustFlow.Row); //この段階で調整しないとスクロールされない
+ col = this.View.LayoutLines.GetLengthFromLineNumber(this.View.CaretPostion.row) - 1; //最終行以外はすべて改行コードが付くはず
+ }
+ else if (col >= lineString.Length || lineString[col] == Document.NewLine)
+ {
+ if (this.View.CaretPostion.row < this.View.LayoutLines.Count - 1)
+ {
+ this.MoveCaretVertical(true);
+ this.View.AdjustCaretAndSrc(AdjustFlow.Row); //この段階で調整しないとスクロールされない
+ col = 0;
+ }
+ }
+ else
+ {
+ AlignDirection direction = isMoveNext ? AlignDirection.Forward : AlignDirection.Back;
+ col = this.View.LayoutLines.GetLayout(this.View.CaretPostion.row).AlignIndexToNearestCluster(col, direction);
+ }
+
+ this.View.JumpCaret(this.View.CaretPostion.row, col,false);
+ }
+
+ /// <summary>
+ /// キャレットを行方向に移動させる
+ /// </summary>
+ /// <param name="isMoveNext">プラス方向に移動するなら真</param>
+ /// <remarks>このメソッドを呼び出した後でScrollToCaretメソッドとSelectWithMoveCaretメソッドを呼び出す必要があります</remarks>
+ void MoveCaretVertical(bool isMoveNext)
+ {
+ if (this.Document.FireUpdateEvent == false)
+ throw new InvalidOperationException("");
+
+ TextPoint nextPoint = this.GetTextPointAfterMoveLine(isMoveNext ? 1 : -1, this.View.CaretPostion);
+
+ this.View.JumpCaret(nextPoint.row, nextPoint.col,false);
+ }
+
+ private void ReplaceBeforeSelectionArea(SelectCollection Selections, int removeLength, string insertStr)
+ {
+ if (removeLength == 0 && insertStr.Length == 0)
+ return;
+
+ if (this.RectSelection == false || this.Document.FireUpdateEvent == false)
+ throw new InvalidOperationException();
+
+ SelectCollection temp = this.View.InsertPoint;
+ int selectStart = temp.First().start;
+ int selectEnd = temp.Last().start + temp.Last().length;
+
+ //ドキュメント操作後に行うとうまくいかないので、あらかじめ取得しておく
+ TextPoint start = this.View.LayoutLines.GetTextPointFromIndex(selectStart);
+ TextPoint end = this.View.LayoutLines.GetTextPointFromIndex(selectEnd);
+
+ bool reverse = temp.First().start > temp.Last().start;
+
+ int lineHeadIndex = this.View.LayoutLines.GetIndexFromLineNumber(this.View.LayoutLines.GetLineNumberFromIndex(selectStart));
+ if (selectStart - removeLength < lineHeadIndex)
+ return;
+
+ this.Document.UndoManager.BeginUndoGroup();
+ this.Document.FireUpdateEvent = false;
+
+ if (reverse)
+ {
+ for (int i = 0; i < temp.Count; i++)
+ {
+ this.ReplaceBeforeSelection(temp[i], removeLength, insertStr);
+ }
+ }
+ else
+ {
+ for (int i = temp.Count - 1; i >= 0; i--)
+ {
+ this.ReplaceBeforeSelection(temp[i], removeLength, insertStr);
+ }
+ }
+
+ this.Document.FireUpdateEvent = true;
+ this.Document.UndoManager.EndUndoGroup();
+
+ int delta = insertStr.Length - removeLength;
+ start.col += delta;
+ end.col += delta;
+
+ if (reverse)
+ this.JumpCaret(start.row, start.col);
+ else
+ this.JumpCaret(end.row, end.col);
+
+ this.Select(start, 0, end.row - start.row);
+ }
+
+ private void ReplaceBeforeSelection(Selection sel, int removeLength, string insertStr)
+ {
+ sel = Util.NormalizeIMaker<Selection>(sel);
+ this.Document.Lock();
+ this.Document.Replace(sel.start - removeLength, removeLength, insertStr);
+ this.Document.UnLock();
+ }
+
+ private void RepleaceSelectionArea(SelectCollection Selections, string value,bool updateInsertPoint = false)
+ {
+ if (value == null)
+ return;
+
+ if (this.RectSelection == false)
+ {
+ Selection sel = Selection.Create(this.AnchorIndex, 0);
+ if (Selections.Count > 0)
+ sel = Util.NormalizeIMaker<Selection>(this.View.Selections.First());
+
+ this.Document.Lock();
+ this.Document.Replace(sel.start, sel.length, value);
+ this.Document.UnLock();
+ return;
+ }
+
+ if (this.Document.FireUpdateEvent == false)
+ throw new InvalidOperationException("");
+
+ int StartIndex = this.SelectionStart;
+
+ SelectCollection newInsertPoint = new SelectCollection();
+
+ if (this.SelectionLength == 0)
+ {
+ int i;
+
+ this.Document.Lock();
+
+ this.Document.UndoManager.BeginUndoGroup();
+
+ this.Document.FireUpdateEvent = false;
+
+ string[] line = value.Split(new string[] { Document.NewLine.ToString() }, StringSplitOptions.RemoveEmptyEntries);
+
+ TextPoint Current = this.View.GetLayoutLineFromIndex(this.SelectionStart);
+
+ for (i = 0; i < line.Length && Current.row < this.View.LayoutLines.Count; i++, Current.row++)
+ {
+ if (Current.col > this.View.LayoutLines[Current.row].Length)
+ Current.col = this.View.LayoutLines[Current.row].Length;
+ StartIndex = this.View.GetIndexFromLayoutLine(Current);
+ this.Document.Replace(StartIndex, 0, line[i]);
+ StartIndex += line[i].Length;
+ }
+
+ for (; i < line.Length; i++)
+ {
+ StartIndex = this.Document.Length;
+ string str = Document.NewLine + line[i];
+ this.Document.Replace(StartIndex, 0, str);
+ StartIndex += str.Length;
+ }
+
+ this.Document.FireUpdateEvent = true;
+
+ this.Document.UndoManager.EndUndoGroup();
+
+ this.Document.UnLock();
+ }
+ else
+ {
+ SelectCollection temp = new SelectCollection(this.View.Selections); //コピーしないとReplaceCommandを呼び出した段階で書き換えられてしまう
+
+ this.Document.Lock();
+
+ this.Document.UndoManager.BeginUndoGroup();
+
+ this.Document.FireUpdateEvent = false;
+
+ if (temp.First().start < temp.Last().start)
+ {
+ for (int i = temp.Count - 1; i >= 0; i--)
+ {
+ Selection sel = Util.NormalizeIMaker<Selection>(temp[i]);
+
+ StartIndex = sel.start;
+
+ this.Document.Replace(sel.start, sel.length, value);
+
+ newInsertPoint.Add(Selection.Create(sel.start + (value.Length - sel.length) * i,0));
+ }
+ }
+ else
+ {
+ for (int i = 0; i < temp.Count; i++)
+ {
+ Selection sel = Util.NormalizeIMaker<Selection>(temp[i]);
+
+ StartIndex = sel.start;
+
+ this.Document.Replace(sel.start, sel.length, value);
+
+ newInsertPoint.Add(Selection.Create(sel.start + (value.Length - sel.length) * i, 0));
+ }
+ }
+
+ this.Document.FireUpdateEvent = true;
+
+ this.Document.UndoManager.EndUndoGroup();
+
+ this.Document.UnLock();
+ }
+ this.JumpCaret(StartIndex);
+ if (updateInsertPoint && newInsertPoint.Count > 0)
+ this.View.InsertPoint = newInsertPoint;
+ }
+
+ private string GetTextFromLineSelectArea(SelectCollection Selections)
+ {
+ Selection sel = Util.NormalizeIMaker<Selection>(Selections.First());
+
+ string str = this.Document.ToString(sel.start, sel.length);
+
+ return str;
+ }
+
+ string GetTextFromRectangleSelectArea(SelectCollection Selections)
+ {
+ StringBuilder temp = new StringBuilder();
+ if (Selections.First().start < Selections.Last().start)
+ {
+ for (int i = 0; i < this.View.Selections.Count; i++)
+ {
+ Selection sel = Util.NormalizeIMaker<Selection>(Selections[i]);
+
+ string str = this.Document.ToString(sel.start, sel.length);
+ if (str.IndexOf(Environment.NewLine) == -1)
+ temp.AppendLine(str);
+ else
+ temp.Append(str);
+ }
+ }
+ else
+ {
+ for (int i = this.View.Selections.Count - 1; i >= 0; i--)
+ {
+ Selection sel = Util.NormalizeIMaker<Selection>(Selections[i]);
+
+ string str = this.Document.ToString(sel.start, sel.length).Replace(Document.NewLine.ToString(), Environment.NewLine);
+ if (str.IndexOf(Environment.NewLine) == -1)
+ temp.AppendLine(str);
+ else
+ temp.Append(str);
+ }
+ }
+ return temp.ToString();
+ }
+
+ void View_LineBreakChanged(object sender, EventArgs e)
+ {
+ this.DeSelectAll();
+ this.AdjustCaret();
+ }
+
+ void View_PageBoundChanged(object sender, EventArgs e)
+ {
+ if (this.View.LineBreak == LineBreakMethod.PageBound && this.View.PageBound.Width - this.View.LineBreakingMarginWidth > 0)
+ this.View.PerfomLayouts();
+ this.AdjustCaret();
+ }
+
+ void render_ChangedRenderResource(object sender, ChangedRenderRsourceEventArgs e)
+ {
+ if (e.type == ResourceType.Font)
+ {
+ if (this.View.LineBreak == LineBreakMethod.PageBound)
+ this.View.PerfomLayouts();
+ this.AdjustCaret();
+ }
+ if (e.type == ResourceType.InlineChar)
+ {
+ int oldLineCountOnScreen = this.View.LineCountOnScreen;
+ this.View.CalculateLineCountOnScreen();
+ if(this.View.LineCountOnScreen != oldLineCountOnScreen)
+ this.AdjustCaret();
+ }
+ }
+
+ void render_ChangedRightToLeft(object sender, EventArgs e)
+ {
+ this.AdjustCaret();
+ }
+
+ void Document_Update(object sender, DocumentUpdateEventArgs e)
+ {
+ switch (e.type)
+ {
+ case UpdateType.Replace:
+ if(e.startIndex < this.Document.Length && this.Document[e.startIndex] == Document.NewLine)
+ this.View.CalculateLineCountOnScreen();
+ this.JumpCaret(e.startIndex + e.insertLength,true);
+ break;
+ case UpdateType.Clear:
+ this.JumpCaret(0,0, false);
+ break;
+ }
+ }
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
+ <HasSharedItems>true</HasSharedItems>
+ <SharedGUID>c244f4e5-45d2-4c1f-bd2a-a5cc90d9421b</SharedGUID>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration">
+ <Import_RootNamespace>Core</Import_RootNamespace>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="$(MSBuildThisFileDirectory)Automaion\FooTextBoxAutomationPeer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)CacheManager.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)CollectionDebugView.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Controller.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Direct2D\CustomTextRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Direct2D\D2DRenderCommon.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Direct2D\DrawingEffect.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Direct2D\InlineChar.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Direct2D\MarkerFactory.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Direct2D\MultiSet.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Direct2D\MyTextLayout.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Document.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)EditView.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)FoldingCollection.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)GapBuffer+Enumerator.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)GapBuffer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)IFoldingStrategy.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)IHilighter.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)ITextRender.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)LineToIndex.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)MarkerCollection.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)PrintableView.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Range.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)RangeCollection.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)RangeTree.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)RangeTreeNode.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)ResourceManager.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)SelectCollection.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)StringBuffer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Test\CharFoldingMethod.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Test\XmlHilighter.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)TextPoint.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)TextServiceFramework\TextStoreHelper.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)UndoCommands.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)UndoManager.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Util.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)ViewBase.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)WatchDogPattern.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)WinFileStream.cs" />
+ </ItemGroup>
+</Project>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>c244f4e5-45d2-4c1f-bd2a-a5cc90d9421b</ProjectGuid>
+ <MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
+ </PropertyGroup>
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.Default.props" />
+ <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.props" />
+ <PropertyGroup />
+ <Import Project="Core.projitems" Label="Shared" />
+ <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.CSharp.targets" />
+</Project>
-/*\r
- * Copyright (C) 2013 FooProject\r
- * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.\r
-\r
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of \r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\r
-\r
-You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.\r
- */\r
-using System;\r
-using SharpDX;\r
-using D2D = SharpDX.Direct2D1;\r
-using DW = SharpDX.DirectWrite;\r
-\r
-namespace FooEditEngine\r
-{\r
- sealed class InlineChar : DW.InlineObject\r
- {\r
- DW.TextLayout Layout;\r
- D2D.SolidColorBrush brush; //キャッシュされたやつが渡されるのでDisposeする必要はない\r
- public InlineChar(DW.Factory factory, DW.TextFormat format,D2D.SolidColorBrush brush,char c)\r
- {\r
- this.Layout = new DW.TextLayout(factory,c.ToString(),format,float.MaxValue,float.MaxValue);\r
- this.Layout.ReadingDirection = DW.ReadingDirection.LeftToRight;\r
- this.AlternativeChar = c;\r
- this.brush = brush;\r
- }\r
-\r
- public char AlternativeChar\r
- {\r
- get;\r
- private set;\r
- }\r
-\r
- public void Draw(object clientDrawingContext, DW.TextRenderer renderer, float originX, float originY, bool isSideways, bool isRightToLeft, ComObject clientDrawingEffect)\r
- {\r
- D2D.RenderTarget render = clientDrawingContext as D2D.RenderTarget;\r
- if (render == null)\r
- return;\r
-\r
- render.DrawTextLayout(\r
- new Vector2(originX, originY),\r
- this.Layout,\r
- this.brush);\r
- }\r
-\r
- public void GetBreakConditions(out DW.BreakCondition breakConditionBefore, out DW.BreakCondition breakConditionAfter)\r
- {\r
- breakConditionAfter = DW.BreakCondition.CanBreak;\r
- breakConditionBefore = DW.BreakCondition.CanBreak;\r
- }\r
-\r
- public DW.InlineObjectMetrics Metrics\r
- {\r
- get\r
- {\r
- DW.InlineObjectMetrics value = new DW.InlineObjectMetrics();\r
- value.Height = this.Layout.Metrics.Height;\r
- value.Width = this.Layout.Metrics.Width;\r
- DW.LineMetrics[] lines = this.Layout.GetLineMetrics();\r
- value.Baseline = lines[0].Baseline;\r
- return value;\r
- }\r
- }\r
-\r
- public DW.OverhangMetrics OverhangMetrics\r
- {\r
- get\r
- {\r
- DW.OverhangMetrics value = new DW.OverhangMetrics();\r
- DW.TextMetrics metrics = this.Layout.Metrics;\r
- value.Left = metrics.Left;\r
- value.Right = metrics.Left + metrics.Width;\r
- value.Top = metrics.Top;\r
- value.Bottom = metrics.Top + metrics.Height;\r
- return value;\r
- }\r
- }\r
-\r
- public IDisposable Shadow\r
- {\r
- get;\r
- set;\r
- }\r
-\r
- public void Dispose()\r
- {\r
- this.Layout.Dispose();\r
- return;\r
- }\r
- }\r
-\r
- sealed class InlineTab : DW.InlineObject\r
- {\r
- double _TabWidth;\r
- double LineHeight;\r
- D2D.SolidColorBrush Brush;\r
- public InlineTab(D2D.SolidColorBrush brush,double witdh,double lineHeight)\r
- {\r
- this._TabWidth = witdh;\r
- this.LineHeight = lineHeight;\r
- this.Brush = brush;\r
- }\r
-\r
- public DW.InlineObjectMetrics Metrics\r
- {\r
- get\r
- {\r
- DW.InlineObjectMetrics value = new DW.InlineObjectMetrics();\r
- value.Width = (float)this._TabWidth;\r
- value.Height = (float)LineHeight;\r
- value.Baseline = (float)(value.Height * 0.8); //デフォルトでは8割らしい\r
- value.SupportsSideways = false;\r
- return value;\r
- }\r
- }\r
- public DW.OverhangMetrics OverhangMetrics\r
- {\r
- get\r
- {\r
- DW.OverhangMetrics value = new DW.OverhangMetrics();\r
- DW.InlineObjectMetrics metrics = this.Metrics;\r
- value.Left = 0;\r
- value.Right = metrics.Width;\r
- value.Top = 0;\r
- value.Bottom = metrics.Height;\r
- return value;\r
- }\r
- }\r
-\r
- public void Draw(object clientDrawingContext, DW.TextRenderer renderer, float originX, float originY, bool isSideways, bool isRightToLeft, ComObject clientDrawingEffect)\r
- {\r
- D2D.RenderTarget render = clientDrawingContext as D2D.RenderTarget;\r
- if (render == null)\r
- return;\r
- DW.InlineObjectMetrics metrics = this.Metrics;\r
- float width = metrics.Width - 1;\r
- if (isRightToLeft)\r
- {\r
- originX += 1;\r
- render.DrawLine(new Vector2(originX, originY + metrics.Baseline), new Vector2(originX + width, originY + metrics.Baseline), this.Brush);\r
- render.DrawLine(new Vector2(originX, originY + metrics.Baseline / 2), new Vector2(originX, originY + metrics.Baseline), this.Brush);\r
- }\r
- else\r
- {\r
- render.DrawLine(new Vector2(originX, originY + metrics.Baseline), new Vector2(originX + width, originY + metrics.Baseline), this.Brush);\r
- render.DrawLine(new Vector2(originX + width, originY + metrics.Baseline / 2), new Vector2(originX + width, originY + metrics.Baseline), this.Brush);\r
- }\r
- }\r
-\r
- public void GetBreakConditions(out DW.BreakCondition breakConditionBefore, out DW.BreakCondition breakConditionAfter)\r
- {\r
- breakConditionAfter = DW.BreakCondition.CanBreak;\r
- breakConditionBefore = DW.BreakCondition.CanBreak;\r
- }\r
-\r
- public IDisposable Shadow\r
- {\r
- get;\r
- set;\r
- }\r
-\r
- public void Dispose()\r
- {\r
- }\r
- }\r
-}\r
+/*
+ * Copyright (C) 2013 FooProject
+ * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+using SharpDX;
+using D2D = SharpDX.Direct2D1;
+using DW = SharpDX.DirectWrite;
+
+namespace FooEditEngine
+{
+ sealed class InlineChar : DW.InlineObject
+ {
+ DW.TextLayout Layout;
+ D2D.SolidColorBrush brush; //キャッシュされたやつが渡されるのでDisposeする必要はない
+ public InlineChar(DW.Factory factory, DW.TextFormat format,D2D.SolidColorBrush brush,char c)
+ {
+ this.Layout = new DW.TextLayout(factory,c.ToString(),format,float.MaxValue,float.MaxValue);
+ this.Layout.ReadingDirection = DW.ReadingDirection.LeftToRight;
+ this.AlternativeChar = c;
+ this.brush = brush;
+ }
+
+ public char AlternativeChar
+ {
+ get;
+ private set;
+ }
+
+ public void Draw(object clientDrawingContext, DW.TextRenderer renderer, float originX, float originY, bool isSideways, bool isRightToLeft, ComObject clientDrawingEffect)
+ {
+ D2D.RenderTarget render = clientDrawingContext as D2D.RenderTarget;
+ if (render == null)
+ return;
+
+ render.DrawTextLayout(
+ new Vector2(originX, originY),
+ this.Layout,
+ this.brush);
+ }
+
+ public void GetBreakConditions(out DW.BreakCondition breakConditionBefore, out DW.BreakCondition breakConditionAfter)
+ {
+ breakConditionAfter = DW.BreakCondition.CanBreak;
+ breakConditionBefore = DW.BreakCondition.CanBreak;
+ }
+
+ public DW.InlineObjectMetrics Metrics
+ {
+ get
+ {
+ DW.InlineObjectMetrics value = new DW.InlineObjectMetrics();
+ value.Height = this.Layout.Metrics.Height;
+ value.Width = this.Layout.Metrics.Width;
+ DW.LineMetrics[] lines = this.Layout.GetLineMetrics();
+ value.Baseline = lines[0].Baseline;
+ return value;
+ }
+ }
+
+ public DW.OverhangMetrics OverhangMetrics
+ {
+ get
+ {
+ DW.OverhangMetrics value = new DW.OverhangMetrics();
+ DW.TextMetrics metrics = this.Layout.Metrics;
+ value.Left = metrics.Left;
+ value.Right = metrics.Left + metrics.Width;
+ value.Top = metrics.Top;
+ value.Bottom = metrics.Top + metrics.Height;
+ return value;
+ }
+ }
+
+ public IDisposable Shadow
+ {
+ get;
+ set;
+ }
+
+ public void Dispose()
+ {
+ this.Layout.Dispose();
+ return;
+ }
+ }
+
+ sealed class InlineTab : DW.InlineObject
+ {
+ double _TabWidth;
+ double LineHeight;
+ D2D.SolidColorBrush Brush;
+ public InlineTab(D2D.SolidColorBrush brush,double witdh,double lineHeight)
+ {
+ this._TabWidth = witdh;
+ this.LineHeight = lineHeight;
+ this.Brush = brush;
+ }
+
+ public DW.InlineObjectMetrics Metrics
+ {
+ get
+ {
+ DW.InlineObjectMetrics value = new DW.InlineObjectMetrics();
+ value.Width = (float)this._TabWidth;
+ value.Height = (float)LineHeight;
+ value.Baseline = (float)(value.Height * 0.8); //デフォルトでは8割らしい
+ value.SupportsSideways = false;
+ return value;
+ }
+ }
+ public DW.OverhangMetrics OverhangMetrics
+ {
+ get
+ {
+ DW.OverhangMetrics value = new DW.OverhangMetrics();
+ DW.InlineObjectMetrics metrics = this.Metrics;
+ value.Left = 0;
+ value.Right = metrics.Width;
+ value.Top = 0;
+ value.Bottom = metrics.Height;
+ return value;
+ }
+ }
+
+ public void Draw(object clientDrawingContext, DW.TextRenderer renderer, float originX, float originY, bool isSideways, bool isRightToLeft, ComObject clientDrawingEffect)
+ {
+ D2D.RenderTarget render = clientDrawingContext as D2D.RenderTarget;
+ if (render == null)
+ return;
+ DW.InlineObjectMetrics metrics = this.Metrics;
+ float width = metrics.Width - 1;
+ if (isRightToLeft)
+ {
+ originX += 1;
+ render.DrawLine(new Vector2(originX, originY + metrics.Baseline), new Vector2(originX + width, originY + metrics.Baseline), this.Brush);
+ render.DrawLine(new Vector2(originX, originY + metrics.Baseline / 2), new Vector2(originX, originY + metrics.Baseline), this.Brush);
+ }
+ else
+ {
+ render.DrawLine(new Vector2(originX, originY + metrics.Baseline), new Vector2(originX + width, originY + metrics.Baseline), this.Brush);
+ render.DrawLine(new Vector2(originX + width, originY + metrics.Baseline / 2), new Vector2(originX + width, originY + metrics.Baseline), this.Brush);
+ }
+ }
+
+ public void GetBreakConditions(out DW.BreakCondition breakConditionBefore, out DW.BreakCondition breakConditionAfter)
+ {
+ breakConditionAfter = DW.BreakCondition.CanBreak;
+ breakConditionBefore = DW.BreakCondition.CanBreak;
+ }
+
+ public IDisposable Shadow
+ {
+ get;
+ set;
+ }
+
+ public void Dispose()
+ {
+ }
+ }
+}
-/*\r
- * Copyright (C) 2013 FooProject\r
- * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.\r
-\r
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of \r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\r
-\r
-You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.\r
- */\r
-\r
-//#define TEST_ASYNC\r
-\r
-using System;\r
-using System.IO;\r
-using System.Collections.Generic;\r
-using System.Text;\r
-using System.Text.RegularExpressions;\r
-using System.Threading;\r
-using System.Threading.Tasks;\r
-using System.Linq;\r
-\r
-namespace FooEditEngine\r
-{\r
- /// <summary>\r
- /// 進行状況を表す列挙体\r
- /// </summary>\r
- public enum ProgressState\r
- {\r
- /// <summary>\r
- /// 操作が開始したことを表す\r
- /// </summary>\r
- Start,\r
- /// <summary>\r
- /// 操作が終了したことを表す\r
- /// </summary>\r
- Complete,\r
- }\r
- /// <summary>\r
- /// 進行状況を表すためのイベントデータ\r
- /// </summary>\r
- public sealed class ProgressEventArgs : EventArgs\r
- {\r
- /// <summary>\r
- /// 進行状況\r
- /// </summary>\r
- public ProgressState state;\r
- /// <summary>\r
- /// コンストラクター\r
- /// </summary>\r
- /// <param name="state">ProgressStateオブジェクト</param>\r
- public ProgressEventArgs(ProgressState state)\r
- {\r
- this.state = state;\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// 進行状況を通知するためのデリゲート\r
- /// </summary>\r
- /// <param name="sender">送信元クラス</param>\r
- /// <param name="e">イベントデータ</param>\r
- public delegate void ProgressEventHandler(object sender, ProgressEventArgs e);\r
-\r
- /// <summary>\r
- /// 更新タイプを表す列挙体\r
- /// </summary>\r
- public enum UpdateType\r
- {\r
- /// <summary>\r
- /// ドキュメントが置き換えられたことを表す\r
- /// </summary>\r
- Replace,\r
- /// <summary>\r
- /// ドキュメント全体が削除されたことを表す\r
- /// </summary>\r
- Clear,\r
- }\r
-\r
- /// <summary>\r
- /// 更新タイプを通知するためのイベントデータ\r
- /// </summary>\r
- public sealed class DocumentUpdateEventArgs : EventArgs\r
- {\r
- /// <summary>\r
- /// 更新タイプ\r
- /// </summary>\r
- public UpdateType type;\r
- /// <summary>\r
- /// 開始位置\r
- /// </summary>\r
- public int startIndex;\r
- /// <summary>\r
- /// 削除された長さ\r
- /// </summary>\r
- public int removeLength;\r
- /// <summary>\r
- /// 追加された長さ\r
- /// </summary>\r
- public int insertLength;\r
- /// <summary>\r
- /// 更新イベントが発生した行。行が不明な場合や行をまたぐ場合はnullを指定すること。\r
- /// </summary>\r
- public int? row;\r
- /// <summary>\r
- /// コンストラクター\r
- /// </summary>\r
- /// <param name="type">更新タイプ</param>\r
- /// <param name="startIndex">開始インデックス</param>\r
- /// <param name="removeLength">削除された長さ</param>\r
- /// <param name="insertLength">追加された長さ</param>\r
- /// <param name="row">開始行。nullを指定することができる</param>\r
- public DocumentUpdateEventArgs(UpdateType type, int startIndex, int removeLength, int insertLength, int? row = null)\r
- {\r
- this.type = type;\r
- this.startIndex = startIndex;\r
- this.removeLength = removeLength;\r
- this.insertLength = insertLength;\r
- this.row = row;\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// ドキュメントに更新があったことを伝えるためのデリゲート\r
- /// </summary>\r
- /// <param name="sender">送信元クラス</param>\r
- /// <param name="e">イベントデータ</param>\r
- public delegate void DocumentUpdateEventHandler(object sender, DocumentUpdateEventArgs e);\r
-\r
- /// <summary>\r
- /// ドキュメントの管理を行う\r
- /// </summary>\r
- /// <remarks>この型のすべてのメソッド・プロパティはスレッドセーフです</remarks>\r
- public sealed class Document : IEnumerable<char>, IRandomEnumrator<char>\r
- {\r
- const int MaxSemaphoreCount = 1;\r
- Regex regex;\r
- Match match;\r
- StringBuffer buffer;\r
- LineToIndexTable _LayoutLines;\r
- bool _EnableFireUpdateEvent = true;\r
- SemaphoreSlim Semaphore = new SemaphoreSlim(MaxSemaphoreCount);\r
-\r
- /// <summary>\r
- /// コンストラクター\r
- /// </summary>\r
- internal Document()\r
- : this(null)\r
- {\r
- }\r
-\r
- internal Document(Document doc)\r
- {\r
- if (doc == null)\r
- this.buffer = new StringBuffer();\r
- else\r
- this.buffer = new StringBuffer(doc.buffer);\r
- this.buffer.Update = new DocumentUpdateEventHandler(buffer_Update);\r
- this.UpdateCalledAlways += (s, e) => { };\r
- this.Update += new DocumentUpdateEventHandler((s, e) => { });\r
- this.ChangeFireUpdateEvent += new EventHandler((s, e) => { });\r
- this.Markers = new MarkerCollection(this);\r
- this.UndoManager = new UndoManager();\r
- this._LayoutLines = new LineToIndexTable(this);\r
- this._LayoutLines.SpilitString = LayoutLines_SpilitStringByChar;\r
- this._LayoutLines.Clear();\r
- }\r
-\r
- /// <summary>\r
- /// レイアウト行を表す\r
- /// </summary>\r
- public LineToIndexTable LayoutLines\r
- {\r
- get\r
- {\r
- return this._LayoutLines;\r
- }\r
- }\r
-\r
- IList<LineToIndexTableData> LayoutLines_SpilitStringByChar(object sender, SpilitStringEventArgs e)\r
- {\r
- return this.CreateLineList(e.index, e.length);\r
- }\r
-\r
- /// <summary>\r
- /// レイアウト行を返す\r
- /// </summary>\r
- /// <param name="index">開始インデックス</param>\r
- /// <param name="length">長さ</param>\r
- /// <param name="lineLimitLength">1行当たりの最大文字数。-1で無制限</param>\r
- /// <returns>レイアウト行リスト</returns>\r
- internal IList<LineToIndexTableData> CreateLineList(int index, int length, int lineLimitLength = -1)\r
- {\r
- int startIndex = index;\r
- int endIndex = index + length - 1;\r
- List<LineToIndexTableData> output = new List<LineToIndexTableData>();\r
-\r
- foreach (Tuple<int, int> range in this.ForEachLines(startIndex, endIndex, lineLimitLength))\r
- {\r
- int lineHeadIndex = range.Item1;\r
- int lineLength = range.Item2;\r
- char c = this.buffer[lineHeadIndex + lineLength - 1];\r
- bool hasNewLine = c == Document.NewLine;\r
- output.Add(this.LayoutLines.CreateLineToIndexTableData(lineHeadIndex, lineLength, hasNewLine, null));\r
- }\r
-\r
- if (output.Count > 0)\r
- output.Last().LineEnd = true;\r
-\r
- return output;\r
- }\r
-\r
- internal void FireUpdate(DocumentUpdateEventArgs e)\r
- {\r
- this.buffer_Update(this.buffer, e);\r
- }\r
-\r
- /// <summary>\r
- /// ドキュメントが更新された時に呼ばれるイベント\r
- /// </summary>\r
- public event DocumentUpdateEventHandler Update;\r
-\r
- /// <summary>\r
- /// ドキュメントが更新された時に呼びされるイベント\r
- /// </summary>\r
- /// <remarks>\r
- /// FireUpdateEventの値に関わらず常に呼びされます\r
- /// </remarks>\r
- internal event DocumentUpdateEventHandler UpdateCalledAlways;\r
-\r
- /// <summary>\r
- /// FireUpdateEventの値が変わったときに呼び出されるイベント\r
- /// </summary>\r
- public event EventHandler ChangeFireUpdateEvent;\r
-\r
- /// <summary>\r
- /// 改行コードの内部表現\r
- /// </summary>\r
- public const char NewLine = '\n';\r
-\r
- /// <summary>\r
- /// EOFの内部表現\r
- /// </summary>\r
- public const char EndOfFile = '\u001a';\r
-\r
- /// <summary>\r
- /// ロック中なら真を返し、そうでないなら偽を返す\r
- /// </summary>\r
- public bool IsLocked\r
- {\r
- get\r
- {\r
- return this.Semaphore.CurrentCount == 0;\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// アンドゥ管理クラスを表す\r
- /// </summary>\r
- public UndoManager UndoManager\r
- {\r
- get;\r
- private set;\r
- }\r
-\r
- /// <summary>\r
- /// 文字列の長さ\r
- /// </summary>\r
- public int Length\r
- {\r
- get\r
- {\r
- return this.buffer.Length;\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// 変更のたびにUpdateイベントを発生させるかどうか\r
- /// </summary>\r
- public bool FireUpdateEvent\r
- {\r
- get\r
- {\r
- return this._EnableFireUpdateEvent;\r
- }\r
- set\r
- {\r
- this._EnableFireUpdateEvent = value;\r
- this.ChangeFireUpdateEvent(this, null);\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// インデクサー\r
- /// </summary>\r
- /// <param name="i">インデックス(自然数でなければならない)</param>\r
- /// <returns>Char型</returns>\r
- public char this[int i]\r
- {\r
- get\r
- {\r
- return this.buffer[i];\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// マーカーコレクション\r
- /// </summary>\r
- public MarkerCollection Markers\r
- {\r
- get;\r
- private set;\r
- }\r
-\r
- internal StringBuffer StringBuffer\r
- {\r
- get\r
- {\r
- return this.buffer;\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// DocumentReaderを作成します\r
- /// </summary>\r
- /// <returns>DocumentReaderオブジェクト</returns>\r
- public DocumentReader CreateReader()\r
- {\r
- return new DocumentReader(this.buffer);\r
- }\r
-\r
- /// <summary>\r
- /// ロックを解除します\r
- /// </summary>\r
- public void UnLock()\r
- {\r
- this.Semaphore.Release();\r
- }\r
-\r
- /// <summary>\r
- /// ロックします\r
- /// </summary>\r
- public void Lock()\r
- {\r
- this.Semaphore.Wait();\r
- }\r
-\r
- /// <summary>\r
- /// ロックします\r
- /// </summary>\r
- /// <returns>Taskオブジェクト</returns>\r
- public Task LockAsync()\r
- {\r
- return this.Semaphore.WaitAsync();\r
- }\r
-\r
- /// <summary>\r
- /// マーカーを設定する\r
- /// </summary>\r
- /// <param name="id">マーカーID</param>\r
- /// <param name="m">設定したいマーカー</param>\r
- public void SetMarker(int id,Marker m)\r
- {\r
- if (m.start < 0 || m.start + m.length > this.Length)\r
- throw new ArgumentOutOfRangeException("startもしくはendが指定できる範囲を超えています");\r
-\r
- this.Markers.Add(id,m);\r
- }\r
-\r
- /// <summary>\r
- /// マーカーを削除する\r
- /// </summary>\r
- /// <param name="id">マーカーID</param>\r
- /// <param name="start">開始インデックス</param>\r
- /// <param name="length">削除する長さ</param>\r
- public void RemoveMarker(int id,int start, int length)\r
- {\r
- if (start < 0 || start + length > this.Length)\r
- throw new ArgumentOutOfRangeException("startもしくはendが指定できる範囲を超えています");\r
-\r
- this.Markers.RemoveAll(id,start, length);\r
- }\r
-\r
- /// <summary>\r
- /// マーカーを削除する\r
- /// </summary>\r
- /// <param name="id">マーカーID</param>\r
- /// <param name="type">削除したいマーカーのタイプ</param>\r
- public void RemoveMarker(int id, HilightType type)\r
- {\r
- this.Markers.RemoveAll(id,type);\r
- }\r
-\r
- /// <summary>\r
- /// インデックスに対応するマーカーを得る\r
- /// </summary>\r
- /// <param name="id">マーカーID</param>\r
- /// <param name="index">インデックス</param>\r
- /// <returns>Marker構造体の列挙子</returns>\r
- public IEnumerable<Marker> GetMarkers(int id, int index)\r
- {\r
- if (index < 0 || index > this.Length)\r
- throw new ArgumentOutOfRangeException("indexが範囲を超えています");\r
- return this.Markers.Get(id,index);\r
- }\r
-\r
- /// <summary>\r
- /// 部分文字列を取得する\r
- /// </summary>\r
- /// <param name="index">開始インデックス</param>\r
- /// <param name="length">長さ</param>\r
- /// <returns>Stringオブジェクト</returns>\r
- public string ToString(int index, int length)\r
- {\r
- return this.buffer.ToString(index, length);\r
- }\r
-\r
- /// <summary>\r
- /// インデックスを開始位置とする文字列を返す\r
- /// </summary>\r
- /// <param name="index">開始インデックス</param>\r
- /// <returns>Stringオブジェクト</returns>\r
- public string ToString(int index)\r
- {\r
- return this.ToString(index, this.buffer.Length - index);\r
- }\r
-\r
- /// <summary>\r
- /// 行を取得する\r
- /// </summary>\r
- /// <param name="startIndex">開始インデックス</param>\r
- /// <param name="endIndex">終了インデックス</param>\r
- /// <param name="maxCharCount">最大長</param>\r
- /// <returns>行イテレーターが返される</returns>\r
- public IEnumerable<string> GetLines(int startIndex, int endIndex, int maxCharCount = -1)\r
- {\r
- return this.buffer.GetLines(startIndex, endIndex, maxCharCount);\r
- }\r
-\r
- internal IEnumerable<Tuple<int, int>> ForEachLines(int startIndex, int endIndex, int maxCharCount = -1)\r
- {\r
- return this.buffer.ForEachLines(startIndex, endIndex, maxCharCount);\r
- }\r
-\r
-\r
- /// <summary>\r
- /// 文字列を追加する\r
- /// </summary>\r
- /// <param name="s">追加したい文字列</param>\r
- /// <remarks>非同期操作中はこのメソッドを実行することはできません</remarks>\r
- public void Append(string s)\r
- {\r
- this.Replace(this.buffer.Length, 0, s);\r
- }\r
-\r
- /// <summary>\r
- /// 文字列を挿入する\r
- /// </summary>\r
- /// <param name="index">開始インデックス</param>\r
- /// <param name="s">追加したい文字列</param>\r
- /// <remarks>読み出し操作中はこのメソッドを実行することはできません</remarks>\r
- public void Insert(int index, string s)\r
- {\r
- this.Replace(index, 0, s);\r
- }\r
-\r
- /// <summary>\r
- /// 文字列を削除する\r
- /// </summary>\r
- /// <param name="index">開始インデックス</param>\r
- /// <param name="length">長さ</param>\r
- /// <remarks>読み出し操作中はこのメソッドを実行することはできません</remarks>\r
- public void Remove(int index, int length)\r
- {\r
- this.Replace(index, length, "");\r
- }\r
-\r
- /// <summary>\r
- /// ドキュメントを置き換える\r
- /// </summary>\r
- /// <param name="index">開始インデックス</param>\r
- /// <param name="length">長さ</param>\r
- /// <param name="s">文字列</param>\r
- /// <remarks>読み出し操作中はこのメソッドを実行することはできません</remarks>\r
- public void Replace(int index, int length, string s)\r
- {\r
- if (index < 0 || index > this.buffer.Length || index + length > this.buffer.Length || length < 0)\r
- throw new ArgumentOutOfRangeException();\r
- if (length == 0 && (s == string.Empty || s == null))\r
- return;\r
-\r
- foreach(int id in this.Markers.IDs)\r
- this.RemoveMarker(id,index, length);\r
-\r
- ReplaceCommand cmd = new ReplaceCommand(this.buffer, index, length, s);\r
- this.UndoManager.push(cmd);\r
- cmd.redo();\r
- }\r
-\r
- /// <summary>\r
- /// 物理行をすべて削除する\r
- /// </summary>\r
- /// <remarks>Dirtyフラグも同時にクリアーされます</remarks>\r
- /// <remarks>非同期操作中はこのメソッドを実行することはできません</remarks>\r
- public void Clear()\r
- {\r
- this.buffer.Clear();\r
- }\r
-\r
- /// <summary>\r
- /// ストリームからドキュメントを非同期的に構築します\r
- /// </summary>\r
- /// <param name="fs">IStreamReaderオブジェクト</param>\r
- /// <param name="tokenSource">キャンセルトークン</param>\r
- /// <returns>Taskオブジェクト</returns>\r
- /// <remarks>\r
- /// 読み取り操作は別スレッドで行われます。\r
- /// また、非同期操作中はこのメソッドを実行することはできません。\r
- /// </remarks>\r
- internal async Task LoadAsync(IStreamReader fs, CancellationTokenSource tokenSource = null)\r
- {\r
- if (fs.IsEnd())\r
- return;\r
-\r
- try\r
- {\r
- await this.LockAsync().ConfigureAwait(false);\r
- this.Clear();\r
- this.FireUpdateEvent = false;\r
- await this.buffer.LoadAsync(fs, tokenSource);\r
- }\r
- finally\r
- {\r
- this.FireUpdateEvent = true;\r
- this.UnLock();\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// ストリームに非同期モードで保存します\r
- /// </summary>\r
- /// <param name="fs">IStreamWriterオブジェクト</param>\r
- /// <param name="tokenSource">キャンセルトークン</param>\r
- /// <returns>Taskオブジェクト</returns>\r
- /// <remarks>非同期操作中はこのメソッドを実行することはできません</remarks>\r
- internal async Task SaveAsync(IStreamWriter fs, CancellationTokenSource tokenSource = null)\r
- {\r
- try\r
- {\r
- await this.LockAsync().ConfigureAwait(false);\r
- StringBuilder line = new StringBuilder();\r
- for (int i = 0; i < this.Length; i++)\r
- {\r
- char c = this[i];\r
- line.Append(c);\r
- if (c == Document.NewLine || i == this.Length - 1)\r
- {\r
- string str = line.ToString();\r
- str = str.Replace(Document.NewLine.ToString(), fs.NewLine);\r
- await fs.WriteAsync(str).ConfigureAwait(false);\r
- line.Clear();\r
- if (tokenSource != null)\r
- tokenSource.Token.ThrowIfCancellationRequested();\r
-#if TEST_ASYNC\r
- System.Threading.Thread.Sleep(10);\r
-#endif\r
- }\r
- }\r
- }\r
- finally\r
- {\r
- this.UnLock();\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// Find()およびReplaceAll()で使用するパラメーターをセットします\r
- /// </summary>\r
- /// <param name="pattern">検索したい文字列</param>\r
- /// <param name="UseRegex">正規表現を使用するなら真</param>\r
- /// <param name="opt">RegexOptions列挙体</param>\r
- public void SetFindParam(string pattern, bool UseRegex, RegexOptions opt)\r
- {\r
- this.match = null;\r
- if (UseRegex)\r
- this.regex = new Regex(pattern, opt);\r
- else\r
- this.regex = new Regex(Regex.Escape(pattern), opt);\r
- }\r
-\r
- /// <summary>\r
- /// 現在の検索パラメーターでWatchDogを生成する\r
- /// </summary>\r
- /// <param name="type">ハイライトタイプ</param>\r
- /// <param name="color">色</param>\r
- /// <returns>WatchDogオブジェクト</returns>\r
- public RegexMarkerPattern CreateWatchDogByFindParam(HilightType type,Color color)\r
- {\r
- if (this.regex == null)\r
- throw new InvalidOperationException("SetFindParam()を呼び出してください");\r
- return new RegexMarkerPattern(this.regex,type,color);\r
- }\r
-\r
- /// <summary>\r
- /// 指定した文字列を検索します\r
- /// </summary>\r
- /// <returns>見つかった場合はSearchResult列挙子を返却します</returns>\r
- /// <remarks>見つかったパターン以外を置き換えた場合、正常に動作しないことがあります</remarks>\r
- public IEnumerator<SearchResult> Find()\r
- {\r
- return this.Find(0, this.Length);\r
- }\r
-\r
- /// <summary>\r
- /// 指定した文字列を検索します\r
- /// </summary>\r
- /// <returns>見つかった場合はSearchResult列挙子を返却します</returns>\r
- /// <param name="start">開始インデックス</param>\r
- /// <param name="length">検索する長さ</param>\r
- /// <remarks>見つかったパターン以外を置き換えた場合、正常に動作しないことがあります</remarks>\r
- public IEnumerator<SearchResult> Find(int start, int length)\r
- {\r
- if (this.regex == null)\r
- throw new InvalidOperationException();\r
- if (start < 0 || start >= this.Length)\r
- throw new ArgumentOutOfRangeException();\r
-\r
- int end = start + length - 1;\r
-\r
- if(end > this.Length - 1)\r
- throw new ArgumentOutOfRangeException();\r
-\r
- StringBuilder line = new StringBuilder();\r
- int oldLength = this.Length;\r
- for (int i = start; i <= end; i++)\r
- {\r
- char c = this[i];\r
- line.Append(c);\r
- if (c == Document.NewLine || i == end)\r
- {\r
- this.match = this.regex.Match(line.ToString());\r
- while (this.match.Success)\r
- {\r
- int startIndex = i - line.Length + 1 + this.match.Index;\r
- int endIndex = startIndex + this.match.Length - 1;\r
-\r
- yield return new SearchResult(this.match, startIndex, endIndex);\r
-\r
- if (this.Length != oldLength) //長さが変わった場合は置き換え後のパターンの終点+1まで戻る\r
- {\r
- int delta = this.Length - oldLength;\r
- i = endIndex + delta;\r
- end = end + delta;\r
- oldLength = this.Length;\r
- break;\r
- }\r
-\r
- this.match = this.match.NextMatch();\r
- }\r
- line.Clear();\r
- }\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// 任意のパターンですべて置き換えます\r
- /// </summary>\r
- /// <param name="replacePattern">置き換え後のパターン</param>\r
- /// <param name="groupReplace">グループ置き換えを行うなら真。そうでないなら偽</param>\r
- public void ReplaceAll(string replacePattern,bool groupReplace)\r
- {\r
- if (this.regex == null)\r
- throw new InvalidOperationException();\r
- ReplaceAllCommand cmd = new ReplaceAllCommand(this.buffer, this.LayoutLines, this.regex, replacePattern, groupReplace);\r
- this.UndoManager.push(cmd);\r
- cmd.redo();\r
- }\r
-\r
- /// <summary>\r
- /// 任意のパターンで置き換える\r
- /// </summary>\r
- /// <param name="target">対象となる文字列</param>\r
- /// <param name="pattern">置き換え後の文字列</param>\r
- /// <param name="ci">大文字も文字を区別しないなら真。そうでないなら偽</param>\r
- /// <remarks>\r
- /// 検索時に大文字小文字を区別します。また、このメソッドでは正規表現を使用することはできません\r
- /// </remarks>\r
- public void ReplaceAll2(string target, string pattern,bool ci = false)\r
- {\r
- FastReplaceAllCommand cmd = new FastReplaceAllCommand(this.buffer, this.LayoutLines, target, pattern,ci);\r
- this.UndoManager.push(cmd);\r
- cmd.redo();\r
- }\r
-\r
- #region IEnumerable<char> メンバー\r
-\r
- /// <summary>\r
- /// 列挙子を返します\r
- /// </summary>\r
- /// <returns>IEnumeratorオブジェクトを返す</returns>\r
- public IEnumerator<char> GetEnumerator()\r
- {\r
- return this.buffer.GetEnumerator();\r
- }\r
-\r
- #endregion\r
-\r
- #region IEnumerable メンバー\r
-\r
- System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()\r
- {\r
- throw new NotImplementedException();\r
- }\r
-\r
- #endregion\r
-\r
- void buffer_Update(object sender, DocumentUpdateEventArgs e)\r
- {\r
- switch (e.type)\r
- {\r
- case UpdateType.Replace:\r
- if (e.row == null)\r
- this._LayoutLines.UpdateAsReplace(e.startIndex, e.removeLength, e.insertLength);\r
- else\r
- this._LayoutLines.UpdateLineAsReplace(e.row.Value, e.removeLength, e.insertLength);\r
- break;\r
- case UpdateType.Clear:\r
- this._LayoutLines.Clear();\r
- break;\r
- }\r
- this.UpdateCalledAlways(this, e);\r
- if(this.FireUpdateEvent)\r
- this.Update(this, e);\r
- }\r
- }\r
-\r
- public interface IStreamReader\r
- {\r
- /// <summary>\r
- /// ストリームが空かどうかを返す\r
- /// </summary>\r
- bool IsEnd();\r
-\r
- /// <summary>\r
- /// ストリームから行を読み取った物を返す。LoadAsyncを呼び出す場合は必ず実装してください\r
- /// </summary>\r
- Task<string> ReadLineAsync();\r
- /// <summary>\r
- /// ストリームから指定した文字数だけ読み取る\r
- /// </summary>\r
- /// <param name="buffer">書き込み先バッファー</param>\r
- /// <param name="index">書き込み先バッファーのインデックス</param>\r
- /// <param name="count">読み取る文字数</param>\r
- /// <returns>読み取った文字数</returns>\r
- Task<int> ReadAsync(char[] buffer, int index, int count);\r
- }\r
-\r
- public interface IStreamWriter\r
- {\r
- /// <summary>\r
- /// ストリームに書き込む。SaveAsyncを呼び出す場合は必ず実装してください\r
- /// </summary>\r
- Task WriteAsync(string str);\r
-\r
- /// <summary>\r
- /// 書き込む際に使用する改行コード\r
- /// </summary>\r
- string NewLine\r
- {\r
- get;\r
- set;\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// 検索結果を表す\r
- /// </summary>\r
- public class SearchResult\r
- {\r
- private Match Match;\r
-\r
- /// <summary>\r
- /// 一致した場所の開始位置を表す\r
- /// </summary>\r
- public int Start;\r
-\r
- /// <summary>\r
- /// 一致した場所の終了位置を表す\r
- /// </summary>\r
- public int End;\r
-\r
- /// <summary>\r
- /// 見つかった文字列を返す\r
- /// </summary>\r
- public string Value\r
- {\r
- get { return this.Match.Value; }\r
- }\r
-\r
- /// <summary>\r
- /// 指定したパターンを置き換えて返す\r
- /// </summary>\r
- /// <param name="replacement">置き換える文字列</param>\r
- /// <returns>置き換え後の文字列</returns>\r
- public string Result(string replacement)\r
- {\r
- return this.Match.Result(replacement);\r
- }\r
-\r
- /// <summary>\r
- /// コンストラクター\r
- /// </summary>\r
- /// <param name="m">Matchオブジェクト</param>\r
- /// <param name="start">開始インデックス</param>\r
- /// <param name="end">終了インデックス</param>\r
- public SearchResult(Match m, int start,int end)\r
- {\r
- this.Match = m;\r
- this.Start = start;\r
- this.End = end;\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// ドキュメントリーダー\r
- /// </summary>\r
- public class DocumentReader : TextReader\r
- {\r
- StringBuffer document; \r
- int currentIndex;\r
-\r
- /// <summary>\r
- /// コンストラクター\r
- /// </summary>\r
- /// <param name="doc"></param>\r
- internal DocumentReader(StringBuffer doc)\r
- {\r
- if (doc == null)\r
- throw new ArgumentNullException();\r
- this.document = doc;\r
- }\r
-\r
- /// <summary>\r
- /// 文字を取得する\r
- /// </summary>\r
- /// <returns>文字。取得できない場合は-1</returns>\r
- public override int Peek()\r
- {\r
- if (this.document == null)\r
- throw new InvalidOperationException();\r
- if (this.currentIndex >= this.document.Length)\r
- return -1;\r
- return this.document[this.currentIndex];\r
- }\r
-\r
- /// <summary>\r
- /// 文字を取得し、イテレーターを一つ進める\r
- /// </summary>\r
- /// <returns>文字。取得できない場合は-1</returns>\r
- public override int Read()\r
- {\r
- int c = this.Peek();\r
- if(c != -1)\r
- this.currentIndex++;\r
- return c;\r
- }\r
-\r
- /// <summary>\r
- /// 文字列を読み取りバッファーに書き込む\r
- /// </summary>\r
- /// <param name="buffer">バッファー</param>\r
- /// <param name="index">開始インデックス</param>\r
- /// <param name="count">カウント</param>\r
- /// <returns>読み取られた文字数</returns>\r
- public override int Read(char[] buffer, int index, int count)\r
- {\r
- if (this.document == null)\r
- throw new InvalidOperationException();\r
-\r
- if (buffer == null)\r
- throw new ArgumentNullException();\r
-\r
- if (this.document.Length < count)\r
- throw new ArgumentException();\r
-\r
- if (index < 0 || count < 0)\r
- throw new ArgumentOutOfRangeException();\r
-\r
- if (this.document.Length == 0)\r
- return 0;\r
-\r
- int actualCount = count;\r
- if (index + count - 1 > this.document.Length - 1)\r
- actualCount = this.document.Length - index;\r
-\r
- string str = this.document.ToString(index, actualCount);\r
-\r
- for (int i = 0; i < str.Length; i++) //ToCharArray()だと戻った時に消えてしまう\r
- buffer[i] = str[i];\r
-\r
- this.currentIndex = index + actualCount;\r
- \r
- return actualCount;\r
- }\r
-\r
- /// <summary>\r
- /// オブジェクトを破棄する\r
- /// </summary>\r
- /// <param name="disposing">真ならアンマネージドリソースを解放する</param>\r
- protected override void Dispose(bool disposing)\r
- {\r
- this.document = null;\r
- }\r
- }\r
-}\r
+/*
+ * Copyright (C) 2013 FooProject
+ * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+//#define TEST_ASYNC
+
+using System;
+using System.IO;
+using System.Collections.Generic;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Linq;
+
+namespace FooEditEngine
+{
+ /// <summary>
+ /// 進行状況を表す列挙体
+ /// </summary>
+ public enum ProgressState
+ {
+ /// <summary>
+ /// 操作が開始したことを表す
+ /// </summary>
+ Start,
+ /// <summary>
+ /// 操作が終了したことを表す
+ /// </summary>
+ Complete,
+ }
+ /// <summary>
+ /// 進行状況を表すためのイベントデータ
+ /// </summary>
+ public sealed class ProgressEventArgs : EventArgs
+ {
+ /// <summary>
+ /// 進行状況
+ /// </summary>
+ public ProgressState state;
+ /// <summary>
+ /// コンストラクター
+ /// </summary>
+ /// <param name="state">ProgressStateオブジェクト</param>
+ public ProgressEventArgs(ProgressState state)
+ {
+ this.state = state;
+ }
+ }
+
+ /// <summary>
+ /// 進行状況を通知するためのデリゲート
+ /// </summary>
+ /// <param name="sender">送信元クラス</param>
+ /// <param name="e">イベントデータ</param>
+ public delegate void ProgressEventHandler(object sender, ProgressEventArgs e);
+
+ /// <summary>
+ /// 更新タイプを表す列挙体
+ /// </summary>
+ public enum UpdateType
+ {
+ /// <summary>
+ /// ドキュメントが置き換えられたことを表す
+ /// </summary>
+ Replace,
+ /// <summary>
+ /// ドキュメント全体が削除されたことを表す
+ /// </summary>
+ Clear,
+ }
+
+ /// <summary>
+ /// 更新タイプを通知するためのイベントデータ
+ /// </summary>
+ public sealed class DocumentUpdateEventArgs : EventArgs
+ {
+ /// <summary>
+ /// 更新タイプ
+ /// </summary>
+ public UpdateType type;
+ /// <summary>
+ /// 開始位置
+ /// </summary>
+ public int startIndex;
+ /// <summary>
+ /// 削除された長さ
+ /// </summary>
+ public int removeLength;
+ /// <summary>
+ /// 追加された長さ
+ /// </summary>
+ public int insertLength;
+ /// <summary>
+ /// 更新イベントが発生した行。行が不明な場合や行をまたぐ場合はnullを指定すること。
+ /// </summary>
+ public int? row;
+ /// <summary>
+ /// コンストラクター
+ /// </summary>
+ /// <param name="type">更新タイプ</param>
+ /// <param name="startIndex">開始インデックス</param>
+ /// <param name="removeLength">削除された長さ</param>
+ /// <param name="insertLength">追加された長さ</param>
+ /// <param name="row">開始行。nullを指定することができる</param>
+ public DocumentUpdateEventArgs(UpdateType type, int startIndex, int removeLength, int insertLength, int? row = null)
+ {
+ this.type = type;
+ this.startIndex = startIndex;
+ this.removeLength = removeLength;
+ this.insertLength = insertLength;
+ this.row = row;
+ }
+ }
+
+ /// <summary>
+ /// ドキュメントに更新があったことを伝えるためのデリゲート
+ /// </summary>
+ /// <param name="sender">送信元クラス</param>
+ /// <param name="e">イベントデータ</param>
+ public delegate void DocumentUpdateEventHandler(object sender, DocumentUpdateEventArgs e);
+
+ /// <summary>
+ /// ドキュメントの管理を行う
+ /// </summary>
+ /// <remarks>この型のすべてのメソッド・プロパティはスレッドセーフです</remarks>
+ public sealed class Document : IEnumerable<char>, IRandomEnumrator<char>
+ {
+ const int MaxSemaphoreCount = 1;
+ Regex regex;
+ Match match;
+ StringBuffer buffer;
+ LineToIndexTable _LayoutLines;
+ bool _EnableFireUpdateEvent = true;
+ SemaphoreSlim Semaphore = new SemaphoreSlim(MaxSemaphoreCount);
+
+ /// <summary>
+ /// コンストラクター
+ /// </summary>
+ internal Document()
+ : this(null)
+ {
+ }
+
+ internal Document(Document doc)
+ {
+ if (doc == null)
+ this.buffer = new StringBuffer();
+ else
+ this.buffer = new StringBuffer(doc.buffer);
+ this.buffer.Update = new DocumentUpdateEventHandler(buffer_Update);
+ this.UpdateCalledAlways += (s, e) => { };
+ this.Update += new DocumentUpdateEventHandler((s, e) => { });
+ this.ChangeFireUpdateEvent += new EventHandler((s, e) => { });
+ this.Markers = new MarkerCollection(this);
+ this.UndoManager = new UndoManager();
+ this._LayoutLines = new LineToIndexTable(this);
+ this._LayoutLines.SpilitString = LayoutLines_SpilitStringByChar;
+ this._LayoutLines.Clear();
+ }
+
+ /// <summary>
+ /// レイアウト行を表す
+ /// </summary>
+ public LineToIndexTable LayoutLines
+ {
+ get
+ {
+ return this._LayoutLines;
+ }
+ }
+
+ IList<LineToIndexTableData> LayoutLines_SpilitStringByChar(object sender, SpilitStringEventArgs e)
+ {
+ return this.CreateLineList(e.index, e.length);
+ }
+
+ /// <summary>
+ /// レイアウト行を返す
+ /// </summary>
+ /// <param name="index">開始インデックス</param>
+ /// <param name="length">長さ</param>
+ /// <param name="lineLimitLength">1行当たりの最大文字数。-1で無制限</param>
+ /// <returns>レイアウト行リスト</returns>
+ internal IList<LineToIndexTableData> CreateLineList(int index, int length, int lineLimitLength = -1)
+ {
+ int startIndex = index;
+ int endIndex = index + length - 1;
+ List<LineToIndexTableData> output = new List<LineToIndexTableData>();
+
+ foreach (Tuple<int, int> range in this.ForEachLines(startIndex, endIndex, lineLimitLength))
+ {
+ int lineHeadIndex = range.Item1;
+ int lineLength = range.Item2;
+ char c = this.buffer[lineHeadIndex + lineLength - 1];
+ bool hasNewLine = c == Document.NewLine;
+ output.Add(this.LayoutLines.CreateLineToIndexTableData(lineHeadIndex, lineLength, hasNewLine, null));
+ }
+
+ if (output.Count > 0)
+ output.Last().LineEnd = true;
+
+ return output;
+ }
+
+ internal void FireUpdate(DocumentUpdateEventArgs e)
+ {
+ this.buffer_Update(this.buffer, e);
+ }
+
+ /// <summary>
+ /// ドキュメントが更新された時に呼ばれるイベント
+ /// </summary>
+ public event DocumentUpdateEventHandler Update;
+
+ /// <summary>
+ /// ドキュメントが更新された時に呼びされるイベント
+ /// </summary>
+ /// <remarks>
+ /// FireUpdateEventの値に関わらず常に呼びされます
+ /// </remarks>
+ internal event DocumentUpdateEventHandler UpdateCalledAlways;
+
+ /// <summary>
+ /// FireUpdateEventの値が変わったときに呼び出されるイベント
+ /// </summary>
+ public event EventHandler ChangeFireUpdateEvent;
+
+ /// <summary>
+ /// 改行コードの内部表現
+ /// </summary>
+ public const char NewLine = '\n';
+
+ /// <summary>
+ /// EOFの内部表現
+ /// </summary>
+ public const char EndOfFile = '\u001a';
+
+ /// <summary>
+ /// ロック中なら真を返し、そうでないなら偽を返す
+ /// </summary>
+ public bool IsLocked
+ {
+ get
+ {
+ return this.Semaphore.CurrentCount == 0;
+ }
+ }
+
+ /// <summary>
+ /// アンドゥ管理クラスを表す
+ /// </summary>
+ public UndoManager UndoManager
+ {
+ get;
+ private set;
+ }
+
+ /// <summary>
+ /// 文字列の長さ
+ /// </summary>
+ public int Length
+ {
+ get
+ {
+ return this.buffer.Length;
+ }
+ }
+
+ /// <summary>
+ /// 変更のたびにUpdateイベントを発生させるかどうか
+ /// </summary>
+ public bool FireUpdateEvent
+ {
+ get
+ {
+ return this._EnableFireUpdateEvent;
+ }
+ set
+ {
+ this._EnableFireUpdateEvent = value;
+ this.ChangeFireUpdateEvent(this, null);
+ }
+ }
+
+ /// <summary>
+ /// インデクサー
+ /// </summary>
+ /// <param name="i">インデックス(自然数でなければならない)</param>
+ /// <returns>Char型</returns>
+ public char this[int i]
+ {
+ get
+ {
+ return this.buffer[i];
+ }
+ }
+
+ /// <summary>
+ /// マーカーコレクション
+ /// </summary>
+ public MarkerCollection Markers
+ {
+ get;
+ private set;
+ }
+
+ internal StringBuffer StringBuffer
+ {
+ get
+ {
+ return this.buffer;
+ }
+ }
+
+ /// <summary>
+ /// DocumentReaderを作成します
+ /// </summary>
+ /// <returns>DocumentReaderオブジェクト</returns>
+ public DocumentReader CreateReader()
+ {
+ return new DocumentReader(this.buffer);
+ }
+
+ /// <summary>
+ /// ロックを解除します
+ /// </summary>
+ public void UnLock()
+ {
+ this.Semaphore.Release();
+ }
+
+ /// <summary>
+ /// ロックします
+ /// </summary>
+ public void Lock()
+ {
+ this.Semaphore.Wait();
+ }
+
+ /// <summary>
+ /// ロックします
+ /// </summary>
+ /// <returns>Taskオブジェクト</returns>
+ public Task LockAsync()
+ {
+ return this.Semaphore.WaitAsync();
+ }
+
+ /// <summary>
+ /// マーカーを設定する
+ /// </summary>
+ /// <param name="id">マーカーID</param>
+ /// <param name="m">設定したいマーカー</param>
+ public void SetMarker(int id,Marker m)
+ {
+ if (m.start < 0 || m.start + m.length > this.Length)
+ throw new ArgumentOutOfRangeException("startもしくはendが指定できる範囲を超えています");
+
+ this.Markers.Add(id,m);
+ }
+
+ /// <summary>
+ /// マーカーを削除する
+ /// </summary>
+ /// <param name="id">マーカーID</param>
+ /// <param name="start">開始インデックス</param>
+ /// <param name="length">削除する長さ</param>
+ public void RemoveMarker(int id,int start, int length)
+ {
+ if (start < 0 || start + length > this.Length)
+ throw new ArgumentOutOfRangeException("startもしくはendが指定できる範囲を超えています");
+
+ this.Markers.RemoveAll(id,start, length);
+ }
+
+ /// <summary>
+ /// マーカーを削除する
+ /// </summary>
+ /// <param name="id">マーカーID</param>
+ /// <param name="type">削除したいマーカーのタイプ</param>
+ public void RemoveMarker(int id, HilightType type)
+ {
+ this.Markers.RemoveAll(id,type);
+ }
+
+ /// <summary>
+ /// インデックスに対応するマーカーを得る
+ /// </summary>
+ /// <param name="id">マーカーID</param>
+ /// <param name="index">インデックス</param>
+ /// <returns>Marker構造体の列挙子</returns>
+ public IEnumerable<Marker> GetMarkers(int id, int index)
+ {
+ if (index < 0 || index > this.Length)
+ throw new ArgumentOutOfRangeException("indexが範囲を超えています");
+ return this.Markers.Get(id,index);
+ }
+
+ /// <summary>
+ /// 部分文字列を取得する
+ /// </summary>
+ /// <param name="index">開始インデックス</param>
+ /// <param name="length">長さ</param>
+ /// <returns>Stringオブジェクト</returns>
+ public string ToString(int index, int length)
+ {
+ return this.buffer.ToString(index, length);
+ }
+
+ /// <summary>
+ /// インデックスを開始位置とする文字列を返す
+ /// </summary>
+ /// <param name="index">開始インデックス</param>
+ /// <returns>Stringオブジェクト</returns>
+ public string ToString(int index)
+ {
+ return this.ToString(index, this.buffer.Length - index);
+ }
+
+ /// <summary>
+ /// 行を取得する
+ /// </summary>
+ /// <param name="startIndex">開始インデックス</param>
+ /// <param name="endIndex">終了インデックス</param>
+ /// <param name="maxCharCount">最大長</param>
+ /// <returns>行イテレーターが返される</returns>
+ public IEnumerable<string> GetLines(int startIndex, int endIndex, int maxCharCount = -1)
+ {
+ return this.buffer.GetLines(startIndex, endIndex, maxCharCount);
+ }
+
+ internal IEnumerable<Tuple<int, int>> ForEachLines(int startIndex, int endIndex, int maxCharCount = -1)
+ {
+ return this.buffer.ForEachLines(startIndex, endIndex, maxCharCount);
+ }
+
+
+ /// <summary>
+ /// 文字列を追加する
+ /// </summary>
+ /// <param name="s">追加したい文字列</param>
+ /// <remarks>非同期操作中はこのメソッドを実行することはできません</remarks>
+ public void Append(string s)
+ {
+ this.Replace(this.buffer.Length, 0, s);
+ }
+
+ /// <summary>
+ /// 文字列を挿入する
+ /// </summary>
+ /// <param name="index">開始インデックス</param>
+ /// <param name="s">追加したい文字列</param>
+ /// <remarks>読み出し操作中はこのメソッドを実行することはできません</remarks>
+ public void Insert(int index, string s)
+ {
+ this.Replace(index, 0, s);
+ }
+
+ /// <summary>
+ /// 文字列を削除する
+ /// </summary>
+ /// <param name="index">開始インデックス</param>
+ /// <param name="length">長さ</param>
+ /// <remarks>読み出し操作中はこのメソッドを実行することはできません</remarks>
+ public void Remove(int index, int length)
+ {
+ this.Replace(index, length, "");
+ }
+
+ /// <summary>
+ /// ドキュメントを置き換える
+ /// </summary>
+ /// <param name="index">開始インデックス</param>
+ /// <param name="length">長さ</param>
+ /// <param name="s">文字列</param>
+ /// <remarks>読み出し操作中はこのメソッドを実行することはできません</remarks>
+ public void Replace(int index, int length, string s)
+ {
+ if (index < 0 || index > this.buffer.Length || index + length > this.buffer.Length || length < 0)
+ throw new ArgumentOutOfRangeException();
+ if (length == 0 && (s == string.Empty || s == null))
+ return;
+
+ foreach(int id in this.Markers.IDs)
+ this.RemoveMarker(id,index, length);
+
+ ReplaceCommand cmd = new ReplaceCommand(this.buffer, index, length, s);
+ this.UndoManager.push(cmd);
+ cmd.redo();
+ }
+
+ /// <summary>
+ /// 物理行をすべて削除する
+ /// </summary>
+ /// <remarks>Dirtyフラグも同時にクリアーされます</remarks>
+ /// <remarks>非同期操作中はこのメソッドを実行することはできません</remarks>
+ public void Clear()
+ {
+ this.buffer.Clear();
+ }
+
+ /// <summary>
+ /// ストリームからドキュメントを非同期的に構築します
+ /// </summary>
+ /// <param name="fs">IStreamReaderオブジェクト</param>
+ /// <param name="tokenSource">キャンセルトークン</param>
+ /// <returns>Taskオブジェクト</returns>
+ /// <remarks>
+ /// 読み取り操作は別スレッドで行われます。
+ /// また、非同期操作中はこのメソッドを実行することはできません。
+ /// </remarks>
+ internal async Task LoadAsync(IStreamReader fs, CancellationTokenSource tokenSource = null)
+ {
+ if (fs.IsEnd())
+ return;
+
+ try
+ {
+ await this.LockAsync().ConfigureAwait(false);
+ this.Clear();
+ this.FireUpdateEvent = false;
+ await this.buffer.LoadAsync(fs, tokenSource);
+ }
+ finally
+ {
+ this.FireUpdateEvent = true;
+ this.UnLock();
+ }
+ }
+
+ /// <summary>
+ /// ストリームに非同期モードで保存します
+ /// </summary>
+ /// <param name="fs">IStreamWriterオブジェクト</param>
+ /// <param name="tokenSource">キャンセルトークン</param>
+ /// <returns>Taskオブジェクト</returns>
+ /// <remarks>非同期操作中はこのメソッドを実行することはできません</remarks>
+ internal async Task SaveAsync(IStreamWriter fs, CancellationTokenSource tokenSource = null)
+ {
+ try
+ {
+ await this.LockAsync().ConfigureAwait(false);
+ StringBuilder line = new StringBuilder();
+ for (int i = 0; i < this.Length; i++)
+ {
+ char c = this[i];
+ line.Append(c);
+ if (c == Document.NewLine || i == this.Length - 1)
+ {
+ string str = line.ToString();
+ str = str.Replace(Document.NewLine.ToString(), fs.NewLine);
+ await fs.WriteAsync(str).ConfigureAwait(false);
+ line.Clear();
+ if (tokenSource != null)
+ tokenSource.Token.ThrowIfCancellationRequested();
+#if TEST_ASYNC
+ System.Threading.Thread.Sleep(10);
+#endif
+ }
+ }
+ }
+ finally
+ {
+ this.UnLock();
+ }
+ }
+
+ /// <summary>
+ /// Find()およびReplaceAll()で使用するパラメーターをセットします
+ /// </summary>
+ /// <param name="pattern">検索したい文字列</param>
+ /// <param name="UseRegex">正規表現を使用するなら真</param>
+ /// <param name="opt">RegexOptions列挙体</param>
+ public void SetFindParam(string pattern, bool UseRegex, RegexOptions opt)
+ {
+ this.match = null;
+ if (UseRegex)
+ this.regex = new Regex(pattern, opt);
+ else
+ this.regex = new Regex(Regex.Escape(pattern), opt);
+ }
+
+ /// <summary>
+ /// 現在の検索パラメーターでWatchDogを生成する
+ /// </summary>
+ /// <param name="type">ハイライトタイプ</param>
+ /// <param name="color">色</param>
+ /// <returns>WatchDogオブジェクト</returns>
+ public RegexMarkerPattern CreateWatchDogByFindParam(HilightType type,Color color)
+ {
+ if (this.regex == null)
+ throw new InvalidOperationException("SetFindParam()を呼び出してください");
+ return new RegexMarkerPattern(this.regex,type,color);
+ }
+
+ /// <summary>
+ /// 指定した文字列を検索します
+ /// </summary>
+ /// <returns>見つかった場合はSearchResult列挙子を返却します</returns>
+ /// <remarks>見つかったパターン以外を置き換えた場合、正常に動作しないことがあります</remarks>
+ public IEnumerator<SearchResult> Find()
+ {
+ return this.Find(0, this.Length);
+ }
+
+ /// <summary>
+ /// 指定した文字列を検索します
+ /// </summary>
+ /// <returns>見つかった場合はSearchResult列挙子を返却します</returns>
+ /// <param name="start">開始インデックス</param>
+ /// <param name="length">検索する長さ</param>
+ /// <remarks>見つかったパターン以外を置き換えた場合、正常に動作しないことがあります</remarks>
+ public IEnumerator<SearchResult> Find(int start, int length)
+ {
+ if (this.regex == null)
+ throw new InvalidOperationException();
+ if (start < 0 || start >= this.Length)
+ throw new ArgumentOutOfRangeException();
+
+ int end = start + length - 1;
+
+ if(end > this.Length - 1)
+ throw new ArgumentOutOfRangeException();
+
+ StringBuilder line = new StringBuilder();
+ int oldLength = this.Length;
+ for (int i = start; i <= end; i++)
+ {
+ char c = this[i];
+ line.Append(c);
+ if (c == Document.NewLine || i == end)
+ {
+ this.match = this.regex.Match(line.ToString());
+ while (this.match.Success)
+ {
+ int startIndex = i - line.Length + 1 + this.match.Index;
+ int endIndex = startIndex + this.match.Length - 1;
+
+ yield return new SearchResult(this.match, startIndex, endIndex);
+
+ if (this.Length != oldLength) //長さが変わった場合は置き換え後のパターンの終点+1まで戻る
+ {
+ int delta = this.Length - oldLength;
+ i = endIndex + delta;
+ end = end + delta;
+ oldLength = this.Length;
+ break;
+ }
+
+ this.match = this.match.NextMatch();
+ }
+ line.Clear();
+ }
+ }
+ }
+
+ /// <summary>
+ /// 任意のパターンですべて置き換えます
+ /// </summary>
+ /// <param name="replacePattern">置き換え後のパターン</param>
+ /// <param name="groupReplace">グループ置き換えを行うなら真。そうでないなら偽</param>
+ public void ReplaceAll(string replacePattern,bool groupReplace)
+ {
+ if (this.regex == null)
+ throw new InvalidOperationException();
+ ReplaceAllCommand cmd = new ReplaceAllCommand(this.buffer, this.LayoutLines, this.regex, replacePattern, groupReplace);
+ this.UndoManager.push(cmd);
+ cmd.redo();
+ }
+
+ /// <summary>
+ /// 任意のパターンで置き換える
+ /// </summary>
+ /// <param name="target">対象となる文字列</param>
+ /// <param name="pattern">置き換え後の文字列</param>
+ /// <param name="ci">大文字も文字を区別しないなら真。そうでないなら偽</param>
+ /// <remarks>
+ /// 検索時に大文字小文字を区別します。また、このメソッドでは正規表現を使用することはできません
+ /// </remarks>
+ public void ReplaceAll2(string target, string pattern,bool ci = false)
+ {
+ FastReplaceAllCommand cmd = new FastReplaceAllCommand(this.buffer, this.LayoutLines, target, pattern,ci);
+ this.UndoManager.push(cmd);
+ cmd.redo();
+ }
+
+ #region IEnumerable<char> メンバー
+
+ /// <summary>
+ /// 列挙子を返します
+ /// </summary>
+ /// <returns>IEnumeratorオブジェクトを返す</returns>
+ public IEnumerator<char> GetEnumerator()
+ {
+ return this.buffer.GetEnumerator();
+ }
+
+ #endregion
+
+ #region IEnumerable メンバー
+
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+ {
+ throw new NotImplementedException();
+ }
+
+ #endregion
+
+ void buffer_Update(object sender, DocumentUpdateEventArgs e)
+ {
+ switch (e.type)
+ {
+ case UpdateType.Replace:
+ if (e.row == null)
+ this._LayoutLines.UpdateAsReplace(e.startIndex, e.removeLength, e.insertLength);
+ else
+ this._LayoutLines.UpdateLineAsReplace(e.row.Value, e.removeLength, e.insertLength);
+ break;
+ case UpdateType.Clear:
+ this._LayoutLines.Clear();
+ break;
+ }
+ this.UpdateCalledAlways(this, e);
+ if(this.FireUpdateEvent)
+ this.Update(this, e);
+ }
+ }
+
+ public interface IStreamReader
+ {
+ /// <summary>
+ /// ストリームが空かどうかを返す
+ /// </summary>
+ bool IsEnd();
+
+ /// <summary>
+ /// ストリームから行を読み取った物を返す。LoadAsyncを呼び出す場合は必ず実装してください
+ /// </summary>
+ Task<string> ReadLineAsync();
+ /// <summary>
+ /// ストリームから指定した文字数だけ読み取る
+ /// </summary>
+ /// <param name="buffer">書き込み先バッファー</param>
+ /// <param name="index">書き込み先バッファーのインデックス</param>
+ /// <param name="count">読み取る文字数</param>
+ /// <returns>読み取った文字数</returns>
+ Task<int> ReadAsync(char[] buffer, int index, int count);
+ }
+
+ public interface IStreamWriter
+ {
+ /// <summary>
+ /// ストリームに書き込む。SaveAsyncを呼び出す場合は必ず実装してください
+ /// </summary>
+ Task WriteAsync(string str);
+
+ /// <summary>
+ /// 書き込む際に使用する改行コード
+ /// </summary>
+ string NewLine
+ {
+ get;
+ set;
+ }
+ }
+
+ /// <summary>
+ /// 検索結果を表す
+ /// </summary>
+ public class SearchResult
+ {
+ private Match Match;
+
+ /// <summary>
+ /// 一致した場所の開始位置を表す
+ /// </summary>
+ public int Start;
+
+ /// <summary>
+ /// 一致した場所の終了位置を表す
+ /// </summary>
+ public int End;
+
+ /// <summary>
+ /// 見つかった文字列を返す
+ /// </summary>
+ public string Value
+ {
+ get { return this.Match.Value; }
+ }
+
+ /// <summary>
+ /// 指定したパターンを置き換えて返す
+ /// </summary>
+ /// <param name="replacement">置き換える文字列</param>
+ /// <returns>置き換え後の文字列</returns>
+ public string Result(string replacement)
+ {
+ return this.Match.Result(replacement);
+ }
+
+ /// <summary>
+ /// コンストラクター
+ /// </summary>
+ /// <param name="m">Matchオブジェクト</param>
+ /// <param name="start">開始インデックス</param>
+ /// <param name="end">終了インデックス</param>
+ public SearchResult(Match m, int start,int end)
+ {
+ this.Match = m;
+ this.Start = start;
+ this.End = end;
+ }
+ }
+
+ /// <summary>
+ /// ドキュメントリーダー
+ /// </summary>
+ public class DocumentReader : TextReader
+ {
+ StringBuffer document;
+ int currentIndex;
+
+ /// <summary>
+ /// コンストラクター
+ /// </summary>
+ /// <param name="doc"></param>
+ internal DocumentReader(StringBuffer doc)
+ {
+ if (doc == null)
+ throw new ArgumentNullException();
+ this.document = doc;
+ }
+
+ /// <summary>
+ /// 文字を取得する
+ /// </summary>
+ /// <returns>文字。取得できない場合は-1</returns>
+ public override int Peek()
+ {
+ if (this.document == null)
+ throw new InvalidOperationException();
+ if (this.currentIndex >= this.document.Length)
+ return -1;
+ return this.document[this.currentIndex];
+ }
+
+ /// <summary>
+ /// 文字を取得し、イテレーターを一つ進める
+ /// </summary>
+ /// <returns>文字。取得できない場合は-1</returns>
+ public override int Read()
+ {
+ int c = this.Peek();
+ if(c != -1)
+ this.currentIndex++;
+ return c;
+ }
+
+ /// <summary>
+ /// 文字列を読み取りバッファーに書き込む
+ /// </summary>
+ /// <param name="buffer">バッファー</param>
+ /// <param name="index">開始インデックス</param>
+ /// <param name="count">カウント</param>
+ /// <returns>読み取られた文字数</returns>
+ public override int Read(char[] buffer, int index, int count)
+ {
+ if (this.document == null)
+ throw new InvalidOperationException();
+
+ if (buffer == null)
+ throw new ArgumentNullException();
+
+ if (this.document.Length < count)
+ throw new ArgumentException();
+
+ if (index < 0 || count < 0)
+ throw new ArgumentOutOfRangeException();
+
+ if (this.document.Length == 0)
+ return 0;
+
+ int actualCount = count;
+ if (index + count - 1 > this.document.Length - 1)
+ actualCount = this.document.Length - index;
+
+ string str = this.document.ToString(index, actualCount);
+
+ for (int i = 0; i < str.Length; i++) //ToCharArray()だと戻った時に消えてしまう
+ buffer[i] = str[i];
+
+ this.currentIndex = index + actualCount;
+
+ return actualCount;
+ }
+
+ /// <summary>
+ /// オブジェクトを破棄する
+ /// </summary>
+ /// <param name="disposing">真ならアンマネージドリソースを解放する</param>
+ protected override void Dispose(bool disposing)
+ {
+ this.document = null;
+ }
+ }
+}
-/*\r
- * Copyright (C) 2013 FooProject\r
- * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.\r
-\r
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of \r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\r
-\r
-You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.\r
- */\r
-using System;\r
-using System.Linq;\r
-using System.Collections.Generic;\r
-\r
-namespace FooEditEngine\r
-{\r
- enum AdjustFlow\r
- {\r
- Row,\r
- Col,\r
- Both,\r
- }\r
-\r
- /// <summary>\r
- /// キャレットとドキュメントの表示を担当します。レイアウト関連もこちらで行います\r
- /// </summary>\r
- sealed class EditView : ViewBase\r
-\r
- {\r
- internal const float LineMarkerThickness = 2;\r
- Point _CaretLocation = new Point();\r
- TextPoint _CaretPostion = new TextPoint();\r
- long tickCount;\r
- bool _CaretBlink,_HideRuler = true;\r
- internal const int LineNumberLength = 6;\r
- const int UpdateAreaPaddingWidth = 2;\r
- const int UpdateAreaWidth = 4;\r
- const int UpdateAreaTotalWidth = UpdateAreaWidth + UpdateAreaPaddingWidth;\r
-\r
- /// <summary>\r
- /// コンストラクター\r
- /// </summary>\r
- public EditView(Document doc, IEditorRender r,int MarginLeftAndRight = 5)\r
- : this(doc,r,new Padding(MarginLeftAndRight, 0, MarginLeftAndRight, 0))\r
- {\r
- }\r
-\r
- /// <summary>\r
- /// コンストラクター\r
- /// </summary>\r
- /// <param name="doc">ドキュメント</param>\r
- /// <param name="r">レンダー</param>\r
- /// <param name="margin">マージン(1番目:左、2番目:上、3番目:右、4番目:下)</param>\r
- public EditView(Document doc, IEditorRender r, Padding margin)\r
- : base(doc,r,margin)\r
- {\r
- this.CaretBlinkTime = 500;\r
- this.CaretWidthOnInsertMode = 1;\r
- this.CalculateClipRect();\r
- this._CaretLocation.X = this.render.TextArea.X;\r
- this._CaretLocation.Y = this.render.TextArea.Y;\r
- this.LayoutLines.FoldingCollection.StatusChanged += FoldingCollection_StatusChanged;\r
- this.InsertPoint = null;\r
- this.HideLineMarker = true;\r
- this.IsFocused = false;\r
- this.Selections = new SelectCollection();\r
- }\r
-\r
- /// <summary>\r
- /// 選択範囲コレクション\r
- /// </summary>\r
- internal SelectCollection Selections\r
- {\r
- get;\r
- private set;\r
- }\r
-\r
- /// <summary>\r
- /// ラインマーカーを描くなら偽。そうでなければ真\r
- /// </summary>\r
- public bool HideLineMarker\r
- {\r
- get;\r
- set;\r
- }\r
-\r
- /// <summary>\r
- /// キャレットを描くなら偽。そうでなければ真\r
- /// </summary>\r
- public bool HideCaret\r
- {\r
- get;\r
- set;\r
- }\r
-\r
- /// <summary>\r
- /// 挿入モードなら真を返し、上書きモードなら偽を返す\r
- /// </summary>\r
- public bool InsertMode\r
- {\r
- get;\r
- set;\r
- }\r
-\r
- /// <summary>\r
- /// キャレットの点滅間隔\r
- /// </summary>\r
- public int CaretBlinkTime\r
- {\r
- get;\r
- set;\r
- }\r
-\r
- /// <summary>\r
- /// 挿入モード時のキャレットの幅\r
- /// </summary>\r
- public double CaretWidthOnInsertMode\r
- {\r
- get;\r
- set;\r
- }\r
-\r
- /// <summary>\r
- /// フォーカスがあるなら真をセットする\r
- /// </summary>\r
- public bool IsFocused\r
- {\r
- get;\r
- set;\r
- }\r
-\r
- /// <summary>\r
- /// キャレットを点滅させるなら真。そうでないなら偽\r
- /// </summary>\r
- /// <remarks>キャレット点滅タイマーもリセットされます</remarks>\r
- public bool CaretBlink\r
- {\r
- get { return this._CaretBlink; }\r
- set\r
- {\r
- this._CaretBlink = value;\r
- if (value)\r
- this.tickCount = DateTime.Now.Ticks + this.To100nsTime(this.CaretBlinkTime);\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// 一ページの高さに収まる行数を返す(こちらは表示されていない行も含みます)\r
- /// </summary>\r
- public int LineCountOnScreenWithInVisible\r
- {\r
- get;\r
- private set;\r
- }\r
-\r
- /// <summary>\r
- /// スクロール時に確保するマージン幅\r
- /// </summary>\r
- public double ScrollMarginWidth\r
- {\r
- get { return this.PageBound.Width * 20 / 100; }\r
- }\r
-\r
- /// <summary>\r
- /// ルーラーを表示しないなら真、そうでないなら偽\r
- /// </summary>\r
- public bool HideRuler\r
- {\r
- get { return this._HideRuler; }\r
- set\r
- {\r
- this._HideRuler = value;\r
- this.LayoutLines.ClearLayoutCache();\r
- CalculateClipRect();\r
- CalculateLineCountOnScreen();\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// 矩形選択モード中に文字列が挿入される位置を表す\r
- /// </summary>\r
- public SelectCollection InsertPoint\r
- {\r
- get;\r
- set;\r
- }\r
-\r
- /// <summary>\r
- /// キャレットがある領域を示す\r
- /// </summary>\r
- public Point CaretLocation\r
- {\r
- get { return this._CaretLocation; }\r
- }\r
-\r
- /// <summary>\r
- /// レイアウト行のどこにキャレットがあるかを表す\r
- /// </summary>\r
- public TextPoint CaretPostion\r
- {\r
- get { return this._CaretPostion; }\r
- }\r
-\r
- /// <summary>\r
- /// ヒットテストを行う\r
- /// </summary>\r
- /// <param name="x">x座標</param>\r
- /// <param name="y">y座標</param>\r
- /// <returns>テキストエリア内にあれば真。そうでなければ偽</returns>\r
- public bool HitTextArea(double x, double y)\r
- {\r
- if (x >= this.render.TextArea.X && x <= this.render.TextArea.Right &&\r
- y >= this.render.TextArea.Y && y <= this.render.TextArea.Bottom)\r
- return true;\r
- else\r
- return false;\r
- }\r
-\r
- /// <summary>\r
- /// ヒットテストを行う\r
- /// </summary>\r
- /// <param name="x">x座標</param>\r
- /// <param name="row">行</param>\r
- /// <returns>ヒットした場合はFoldingDataオブジェクトが返され、そうでない場合はnullが返る</returns>\r
- public FoldingItem HitFoldingData(double x, int row)\r
- {\r
- IEditorRender render = (IEditorRender)base.render;\r
-\r
- if (x >= this.GetRealtiveX(AreaType.FoldingArea) && x <= this.GetRealtiveX(AreaType.FoldingArea) + render.FoldingWidth)\r
- {\r
- int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(row);\r
- int lineLength = this.LayoutLines.GetLengthFromLineNumber(row);\r
- FoldingItem foldingData = this.LayoutLines.FoldingCollection.Get(lineHeadIndex, lineLength);\r
- if (foldingData != null && foldingData.IsFirstLine(this.LayoutLines,row))\r
- return foldingData;\r
- }\r
- return null;\r
- }\r
-\r
- /// <summary>\r
- /// Rectで指定された範囲にドキュメントを描く\r
- /// </summary>\r
- /// <param name="updateRect">描写する範囲</param>\r
- /// <remarks>キャレットを点滅させる場合、定期的のこのメソッドを呼び出してください</remarks>\r
- public override void Draw(Rectangle updateRect)\r
- {\r
- if (this.LayoutLines.Count == 0)\r
- return;\r
-\r
- IEditorRender render = (IEditorRender)base.render;\r
-\r
- if ((updateRect.Height < this.PageBound.Height ||\r
- updateRect.Width < this.PageBound.Width) && \r
- render.IsVaildCache())\r
- {\r
- render.DrawCachedBitmap(updateRect);\r
- }\r
- else\r
- {\r
- Rectangle background = this.PageBound;\r
- render.FillBackground(background);\r
-\r
- if (this.HideRuler == false)\r
- this.DrawRuler();\r
-\r
- this.DrawLineMarker(this.CaretPostion.row);\r
-\r
- Point pos = this.render.TextArea.TopLeft;\r
- pos.X -= this.Src.X;\r
- double endposy = this.render.TextArea.Bottom;\r
- Size lineNumberSize = new Size(this.render.LineNemberWidth,this.render.TextArea.Height);\r
- for (int i = this.Src.Row; i < this.LayoutLines.Count; i++)\r
- {\r
- int lineIndex = this.LayoutLines.GetIndexFromLineNumber(i);\r
- int lineLength = this.LayoutLines.GetLengthFromLineNumber(i);\r
- ITextLayout layout = this.LayoutLines.GetLayout(i);\r
-\r
- if (pos.Y + layout.Height > endposy)\r
- break;\r
-\r
- FoldingItem foldingData = this.LayoutLines.FoldingCollection.Get(lineIndex, lineLength);\r
-\r
- if (foldingData != null)\r
- {\r
- if ((!this.LayoutLines.FoldingCollection.IsHasParent(foldingData) || \r
- !this.LayoutLines.FoldingCollection.IsParentHidden(foldingData))\r
- && foldingData.IsFirstLine(this.LayoutLines, i))\r
- render.DrawFoldingMark(foldingData.Expand, this.PageBound.X + this.GetRealtiveX(AreaType.FoldingArea), pos.Y);\r
- if (this.LayoutLines.FoldingCollection.IsHidden(lineIndex))\r
- continue;\r
- }\r
-\r
- var selectRange = from s in this.Selections.Get(lineIndex, lineLength)\r
- let n = Util.ConvertAbsIndexToRelIndex(s, lineIndex, lineLength)\r
- select n;\r
-\r
- this.render.DrawOneLine(this.LayoutLines, i, pos.X, pos.Y, selectRange);\r
-\r
- if (this.DrawLineNumber)\r
- {\r
- this.render.DrawString((i + 1).ToString(), this.PageBound.X + this.GetRealtiveX(AreaType.LineNumberArea), pos.Y, StringAlignment.Right, lineNumberSize,StringColorType.LineNumber);\r
- }\r
-\r
- DrawUpdateArea(i, pos.Y);\r
-\r
- pos.Y += this.LayoutLines.GetLayout(i).Height;\r
- }\r
-\r
- if (this.InsertPoint != null)\r
- this.DrawInsertPoint();\r
-\r
- render.CacheContent();\r
- }\r
-\r
- this.DrawCaret();\r
- }\r
-\r
- void DrawUpdateArea(int row,double ypos)\r
- {\r
- IEditorRender render = (IEditorRender)base.render;\r
- if(this.LayoutLines.GetDirtyFlag(row))\r
- {\r
- Point pos = new Point(this.PageBound.X + this.GetRealtiveX(AreaType.UpdateArea), ypos);\r
- Rectangle rect = new Rectangle(pos.X, pos.Y, UpdateAreaWidth, this.LayoutLines.GetLayout(row).Height);\r
- render.FillRectangle(rect, FillRectType.UpdateArea);\r
- }\r
- }\r
-\r
- void DrawRuler()\r
- {\r
- IEditorRender render = (IEditorRender)base.render;\r
-\r
- Point pos, from, to;\r
- Size emSize = render.emSize;\r
- Rectangle clipRect = this.render.TextArea;\r
- int count = 0;\r
- double markerHeight = emSize.Height / 2;\r
- if (this.render.RightToLeft)\r
- {\r
- pos = new Point(clipRect.TopRight.X, clipRect.TopRight.Y - emSize.Height - LineMarkerThickness);\r
- for (; pos.X >= clipRect.TopLeft.X; pos.X -= emSize.Width, count++)\r
- {\r
- from = pos;\r
- to = new Point(pos.X, pos.Y + emSize.Height);\r
- int mod = count % 10;\r
- if (mod == 0)\r
- {\r
- string countStr = (count / 10).ToString();\r
- double counterWidth = emSize.Width * countStr.Length;\r
- this.render.DrawString(countStr, pos.X - counterWidth, pos.Y, StringAlignment.Right, new Size(counterWidth, double.MaxValue));\r
- }\r
- else if (mod == 5)\r
- from.Y = from.Y + emSize.Height / 2;\r
- else\r
- from.Y = from.Y + emSize.Height * 3 / 4;\r
- render.DrawLine(from, to);\r
- if (this.CaretLocation.X >= pos.X && this.CaretLocation.X < pos.X + emSize.Width)\r
- render.FillRectangle(new Rectangle(pos.X, pos.Y + markerHeight, emSize.Width, markerHeight), FillRectType.OverwriteCaret);\r
- }\r
- }\r
- else\r
- {\r
- pos = new Point(clipRect.TopLeft.X, clipRect.TopLeft.Y - emSize.Height - LineMarkerThickness);\r
- for (; pos.X < clipRect.TopRight.X; pos.X += emSize.Width, count++)\r
- {\r
- from = pos;\r
- to = new Point(pos.X, pos.Y + emSize.Height);\r
- int mod = count % 10;\r
- if (mod == 0)\r
- this.render.DrawString((count / 10).ToString(), pos.X, pos.Y, StringAlignment.Left, new Size(double.MaxValue, double.MaxValue));\r
- else if (mod == 5)\r
- from.Y = from.Y + emSize.Height / 2;\r
- else\r
- from.Y = from.Y + emSize.Height * 3 / 4;\r
- render.DrawLine(from, to);\r
- if (this.CaretLocation.X >= pos.X && this.CaretLocation.X < pos.X + emSize.Width)\r
- render.FillRectangle(new Rectangle(pos.X, pos.Y + markerHeight, emSize.Width, markerHeight), FillRectType.OverwriteCaret);\r
- }\r
- }\r
- from = clipRect.TopLeft;\r
- from.Y -= LineMarkerThickness;\r
- to = clipRect.TopRight;\r
- to.Y -= LineMarkerThickness;\r
- render.DrawLine(from, to);\r
- }\r
-\r
- void DrawInsertPoint()\r
- {\r
- IEditorRender render = (IEditorRender)base.render;\r
- foreach (Selection sel in this.InsertPoint)\r
- {\r
- if (sel.length == 0)\r
- {\r
- TextPoint tp = this.GetLayoutLineFromIndex(sel.start);\r
- Point left = this.GetPostionFromTextPoint(tp);\r
- double lineHeight = this.LayoutLines.GetLayout(tp.row).Height;\r
- Rectangle InsertRect = new Rectangle(left.X,\r
- left.Y,\r
- CaretWidthOnInsertMode,\r
- lineHeight);\r
- render.FillRectangle(InsertRect, FillRectType.InsertPoint);\r
- }\r
- }\r
- }\r
-\r
- void DrawCaret()\r
- {\r
- if (this.HideCaret || !this.IsFocused)\r
- return;\r
-\r
- long diff = DateTime.Now.Ticks - this.tickCount;\r
- long blinkTime = this.To100nsTime(this.CaretBlinkTime);\r
-\r
- if (this._CaretBlink && diff % blinkTime >= blinkTime / 2)\r
- return;\r
-\r
- Rectangle CaretRect = new Rectangle();\r
-\r
- IEditorRender render = (IEditorRender)base.render;\r
-\r
- int row = this.CaretPostion.row;\r
- double lineHeight = this.LayoutLines.GetLayout(row).Height;\r
- double charWidth = this.LayoutLines.GetLayout(row).GetWidthFromIndex(this.CaretPostion.col);\r
-\r
- if (this.InsertMode || charWidth == 0)\r
- {\r
- CaretRect.Size = new Size(CaretWidthOnInsertMode, lineHeight);\r
- CaretRect.Location = new Point(this.CaretLocation.X, this.CaretLocation.Y);\r
- render.FillRectangle(CaretRect, FillRectType.InsertCaret);\r
- }\r
- else\r
- {\r
- double height = lineHeight / 3;\r
- CaretRect.Size = new Size(charWidth, height);\r
- CaretRect.Location = new Point(this.CaretLocation.X, this.CaretLocation.Y + lineHeight - height);\r
- render.FillRectangle(CaretRect, FillRectType.OverwriteCaret);\r
- }\r
- }\r
-\r
- long To100nsTime(int ms)\r
- {\r
- return ms * 10000;\r
- }\r
-\r
- public void DrawLineMarker(int row)\r
- {\r
- if (this.HideLineMarker || !this.IsFocused)\r
- return;\r
- IEditorRender render = (IEditorRender)base.render;\r
- Point p = this.CaretLocation;\r
- double height = this.LayoutLines.GetLayout(this.CaretPostion.row).Height;\r
- double width = this.render.TextArea.Width;\r
- render.FillRectangle(new Rectangle(this.PageBound.X + this.render.TextArea.X, this.CaretLocation.Y, width, height), FillRectType.LineMarker);\r
- }\r
-\r
- /// <summary>\r
- /// 指定した座標の一番近くにあるTextPointを取得する\r
- /// </summary>\r
- /// <param name="p">テキストエリアを左上とする相対位置</param>\r
- /// <returns>レイアウトラインを指し示すTextPoint</returns>\r
- public TextPoint GetTextPointFromPostion(Point p)\r
- {\r
- if (p.Y < this.render.TextArea.TopLeft.Y || \r
- p.Y > this.render.TextArea.BottomRight.Y)\r
- return TextPoint.Null;\r
- TextPoint tp = new TextPoint();\r
-\r
- if (this.LayoutLines.Count == 0)\r
- return tp;\r
-\r
- p.Y -= this.render.TextArea.Y;\r
-\r
- int lineHeadIndex, lineLength;\r
- double y = 0;\r
- tp.row = this.LayoutLines.Count - 1;\r
- for (int i = this.Src.Row; i < this.LayoutLines.Count; i++)\r
- {\r
- double height = this.LayoutLines.GetLayout(i).Height;\r
-\r
- lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(i);\r
- lineLength = this.LayoutLines.GetLengthFromLineNumber(i);\r
-\r
- if (this.LayoutLines.FoldingCollection.IsHidden(lineHeadIndex))\r
- continue;\r
-\r
- if (y + height > p.Y)\r
- {\r
- tp.row = i;\r
- break;\r
- }\r
- y += height;\r
- }\r
-\r
- if (p.X < this.render.TextArea.X)\r
- return tp;\r
-\r
- tp.col = GetIndexFromColPostion(tp.row, p.X);\r
-\r
- lineLength = this.LayoutLines.GetLengthFromLineNumber(tp.row);\r
- if (tp.col > lineLength)\r
- tp.col = lineLength;\r
-\r
- return tp;\r
- }\r
-\r
- /// <summary>\r
- /// 桁方向の座標に対応するインデックスを取得する\r
- /// </summary>\r
- /// <param name="row">対象となる行</param>\r
- /// <param name="x">テキストエリアからの相対位置</param>\r
- /// <returns></returns>\r
- public int GetIndexFromColPostion(int row, double x)\r
- {\r
- x -= this.render.TextArea.X;\r
- int lineLength = this.LayoutLines.GetLengthFromLineNumber(row);\r
- if (lineLength == 0)\r
- return 0;\r
- int index = this.LayoutLines.GetLayout(row).GetIndexFromColPostion(this.Src.X + x);\r
- return index;\r
- }\r
-\r
- /// <summary>\r
- /// インデックスに対応する桁方向の座標を得る\r
- /// </summary>\r
- /// <param name="row">対象となる行</param>\r
- /// <param name="index">インデックス</param>\r
- /// <returns>テキストエリアからの相対位置を返す</returns>\r
- public double GetColPostionFromIndex(int row, int index)\r
- {\r
- double x = this.LayoutLines.GetLayout(row).GetColPostionFromIndex(index);\r
- return x - Src.X + this.render.TextArea.X;\r
- }\r
-\r
- /// <summary>\r
- /// TextPointに対応する座標を得る\r
- /// </summary>\r
- /// <param name="tp">レイアウトライン上の位置</param>\r
- /// <returns>テキストエリアを左上とする相対位置</returns>\r
- public Point GetPostionFromTextPoint(TextPoint tp)\r
- {\r
- Point p = new Point();\r
- for (int i = this.Src.Row; i < tp.row; i++)\r
- {\r
- int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(i);\r
- int lineLength = this.LayoutLines.GetLengthFromLineNumber(i);\r
- if (this.LayoutLines.FoldingCollection.IsHidden(lineHeadIndex))\r
- continue;\r
- p.Y += this.LayoutLines.GetLayout(i).Height;\r
- }\r
- p.X = this.GetColPostionFromIndex(tp.row, tp.col);\r
- p.Y += this.render.TextArea.Y;\r
- return p;\r
- }\r
-\r
- /// <summary>\r
- /// キャレットを指定した位置に移動させる\r
- /// </summary>\r
- /// <param name="row"></param>\r
- /// <param name="col"></param>\r
- /// <param name="autoExpand">折り畳みを展開するなら真</param>\r
- public void JumpCaret(int row, int col, bool autoExpand = true)\r
- {\r
- if (autoExpand)\r
- {\r
- int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(row);\r
- int lineLength = this.LayoutLines.GetLengthFromLineNumber(row);\r
- FoldingItem foldingData = this.LayoutLines.FoldingCollection.Get(lineHeadIndex, lineLength);\r
- if(foldingData != null)\r
- {\r
- if (this.LayoutLines.FoldingCollection.IsParentHidden(foldingData) || !foldingData.IsFirstLine(this.LayoutLines, row))\r
- {\r
- this.LayoutLines.FoldingCollection.Expand(foldingData);\r
- }\r
- }\r
- }\r
-\r
- this._CaretPostion.row = row;\r
- this._CaretPostion.col = col;\r
- }\r
-\r
- /// <summary>\r
- /// index上の文字が表示されるようにSrcを調整する\r
- /// </summary>\r
- /// <param name="index">インデックス</param>\r
- /// <returns>調整されたら真。そうでなければ偽</returns>\r
- public bool AdjustSrc(int index)\r
- {\r
- TextPoint startTextPoint = this.GetLayoutLineFromIndex(index);\r
- double x = this.LayoutLines.GetLayout(startTextPoint.row).GetColPostionFromIndex(startTextPoint.col);\r
- if (x < this.Src.X ||\r
- x > this.Src.X + this.PageBound.Width)\r
- {\r
- this.TryScroll(x, this.Src.Row);\r
- return true;\r
- }\r
- if (startTextPoint.row < this.Src.Row ||\r
- startTextPoint.row > this.Src.Row + this.LineCountOnScreenWithInVisible)\r
- {\r
- this.TryScroll(this.Src.X, startTextPoint.row);\r
- return true;\r
- }\r
- return false;\r
- }\r
-\r
- /// <summary>\r
- /// キャレットがあるところまでスクロールする\r
- /// </summary>\r
- /// <return>再描写する必要があるなら真を返す</return>\r
- /// <remarks>Document.Update(type == UpdateType.Clear)イベント時に呼び出した場合、例外が発生します</remarks>\r
- public bool AdjustCaretAndSrc(AdjustFlow flow = AdjustFlow.Both)\r
- {\r
- IEditorRender render = (IEditorRender)base.render;\r
-\r
- if (this.PageBound.Width == 0 || this.PageBound.Height == 0)\r
- {\r
- this.SetCaretPostion(this.Padding.Left + render.FoldingWidth, 0);\r
- return false;\r
- }\r
-\r
- bool result = false;\r
- TextPoint tp = this.CaretPostion;\r
- double x = this.CaretLocation.X;\r
- double y = this.CaretLocation.Y;\r
-\r
- if (flow == AdjustFlow.Col || flow == AdjustFlow.Both)\r
- {\r
- x = this.LayoutLines.GetLayout(tp.row).GetColPostionFromIndex(tp.col);\r
-\r
- double left = this.Src.X;\r
- double right = this.Src.X + this.render.TextArea.Width;\r
-\r
- if (x >= left && x <= right) //xは表示領域にないにある\r
- {\r
- x -= left;\r
- }\r
- else if (x > right) //xは表示領域の右側にある\r
- {\r
- this._Src.X = x - this.render.TextArea.Width + this.ScrollMarginWidth;\r
- if (this.render.RightToLeft && this._Src.X > 0)\r
- {\r
- System.Diagnostics.Debug.Assert(x > 0);\r
- this._Src.X = 0;\r
- }\r
- else\r
- {\r
- x = this.render.TextArea.Width - this.ScrollMarginWidth;\r
- }\r
- result = true;\r
- }\r
- else if (x < left) //xは表示領域の左側にある\r
- {\r
- this._Src.X = x - this.ScrollMarginWidth;\r
- if (!this.render.RightToLeft && this._Src.X < this.render.TextArea.X)\r
- {\r
- this._Src.X = 0;\r
- }\r
- else\r
- {\r
- x = this.ScrollMarginWidth;\r
- }\r
- result = true;\r
- }\r
- x += this.render.TextArea.X;\r
- }\r
-\r
- if (flow == AdjustFlow.Row || flow == AdjustFlow.Both)\r
- {\r
- int caretRow = 0;\r
- int lineCount = this.LineCountOnScreenWithInVisible;\r
- if (tp.row >= this.Src.Row && tp.row < this.Src.Row + lineCount)\r
- caretRow = tp.row - this.Src.Row;\r
- else if (tp.row >= this.Src.Row + lineCount)\r
- {\r
- this._Src.Row = this.GetSrcRow(tp.row, this.LineCountOnScreen);\r
- caretRow = tp.row - this._Src.Row;\r
- result = true;\r
- CalculateLineCountOnScreen();\r
- }\r
- else if (tp.row < this.Src.Row)\r
- {\r
- this._Src.Row = tp.row;\r
- result = true;\r
- CalculateLineCountOnScreen();\r
- }\r
-\r
- y = 0;\r
-\r
- if (caretRow > 0)\r
- {\r
- for (int i = 0; i < caretRow; i++)\r
- {\r
- int currentRow = this.Src.Row + i;\r
- int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(currentRow);\r
- int lineLength = this.LayoutLines.GetLengthFromLineNumber(currentRow);\r
-\r
- if (this.LayoutLines.FoldingCollection.IsHidden(lineHeadIndex))\r
- continue;\r
-\r
- y += this.LayoutLines.GetLayout(currentRow).Height;\r
- }\r
- }\r
- y += this.render.TextArea.Y;\r
- }\r
-\r
- this.SetCaretPostion(x, y);\r
-\r
- if (result)\r
- this.OnSrcChanged(null);\r
-\r
- return result;\r
- }\r
-\r
- int GetSrcRow(int row,int count)\r
- {\r
- if (this.LayoutLines.FoldingStrategy == null)\r
- return row - count;\r
- for (int i = row; i >= 0; i--)\r
- {\r
- int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(i);\r
- int lineLength = this.LayoutLines.GetLengthFromLineNumber(i);\r
- if (this.LayoutLines.FoldingCollection.IsHidden(lineHeadIndex))\r
- continue;\r
- if (count <= 0)\r
- return i;\r
- count--;\r
- }\r
- return 0;\r
- }\r
-\r
- /// <summary>\r
- /// レイアウト行をテキストポイントからインデックスに変換する\r
- /// </summary>\r
- /// <param name="tp">テキストポイント表す</param>\r
- /// <returns>インデックスを返す</returns>\r
- public int GetIndexFromLayoutLine(TextPoint tp)\r
- {\r
- return this.LayoutLines.GetIndexFromTextPoint(tp);\r
- }\r
-\r
- /// <summary>\r
- /// インデックスからレイアウト行を指し示すテキストポイントに変換する\r
- /// </summary>\r
- /// <param name="index">インデックスを表す</param>\r
- /// <returns>テキストポイント返す</returns>\r
- public TextPoint GetLayoutLineFromIndex(int index)\r
- {\r
- return this.LayoutLines.GetTextPointFromIndex(index);\r
- }\r
-\r
- /// <summary>\r
- /// 指定した座標までスクロールする\r
- /// </summary>\r
- /// <param name="x"></param>\r
- /// <param name="row"></param>\r
- /// <remarks>\r
- /// 範囲外の座標を指定した場合、範囲内に収まるように調整されます\r
- /// </remarks>\r
- public void Scroll(double x, int row)\r
- {\r
- if (x < 0)\r
- x = 0;\r
- if(row < 0)\r
- row = 0;\r
- int endRow = this.LayoutLines.Count - 1 - this.LineCountOnScreen;\r
- if (endRow < 0)\r
- endRow = 0;\r
- if (row > endRow)\r
- row = endRow;\r
- base.TryScroll(x, row);\r
- }\r
-\r
- /// <summary>\r
- /// 指定行までスクロールする\r
- /// </summary>\r
- /// <param name="row">行</param>\r
- /// <param name="alignTop">指定行を画面上に置くなら真。そうでないなら偽</param>\r
- public void ScrollIntoView(int row, bool alignTop)\r
- {\r
- this.Scroll(0, row);\r
- if (alignTop)\r
- return;\r
- double y = this.render.TextArea.Height;\r
- for (int i = row; i >= 0; i--)\r
- {\r
- int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(i);\r
- int lineLength = this.LayoutLines.GetLengthFromLineNumber(i);\r
- double height = this.LayoutLines.GetLayout(i).Height;\r
- if (y - height <= 0)\r
- {\r
- this.Scroll(0, i);\r
- }\r
- if (this.LayoutLines.FoldingCollection.IsHidden(lineHeadIndex))\r
- continue;\r
- y -= height;\r
- }\r
- }\r
-\r
- public int AdjustRow(int row, bool isMoveNext)\r
- {\r
- if (this.LayoutLines.FoldingStrategy == null)\r
- return row;\r
- int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(row);\r
- int lineLength = this.LayoutLines.GetLengthFromLineNumber(row);\r
- FoldingItem foldingData = this.LayoutLines.FoldingCollection.GetFarestHiddenFoldingData(lineHeadIndex, lineLength);\r
- if (foldingData != null && !foldingData.Expand)\r
- {\r
- if (foldingData.End == this.Document.Length)\r
- return row;\r
- if (isMoveNext && lineHeadIndex > foldingData.Start)\r
- row = this.LayoutLines.GetLineNumberFromIndex(foldingData.End) + 1;\r
- else\r
- row = this.LayoutLines.GetLineNumberFromIndex(foldingData.Start);\r
- if(row > this.LayoutLines.Count - 1)\r
- row = this.LayoutLines.GetLineNumberFromIndex(foldingData.Start);\r
- }\r
- return row;\r
- }\r
-\r
- protected override void CalculateClipRect()\r
- {\r
- IEditorRender render = (IEditorRender)base.render;\r
- double x, y, width, height;\r
-\r
- if (this.DrawLineNumber)\r
- {\r
- if (this.render.RightToLeft)\r
- x = this.Padding.Left;\r
- else\r
- x = this.Padding.Left + UpdateAreaTotalWidth + this.render.LineNemberWidth + this.LineNumberMargin + render.FoldingWidth;\r
- width = this.PageBound.Width - this.render.LineNemberWidth - this.LineNumberMargin - this.Padding.Left - this.Padding.Right - render.FoldingWidth - UpdateAreaTotalWidth;\r
- }\r
- else\r
- {\r
- if (this.render.RightToLeft)\r
- x = this.Padding.Left;\r
- else\r
- x = this.Padding.Left + UpdateAreaTotalWidth + render.FoldingWidth;\r
- width = this.PageBound.Width - this.Padding.Left - this.Padding.Right - render.FoldingWidth - UpdateAreaTotalWidth;\r
- }\r
-\r
- y = this.Padding.Top;\r
- height = this.PageBound.Height - this.Padding.Top - this.Padding.Bottom;\r
-\r
- if (this.HideRuler == false)\r
- {\r
- double rulerHeight = this.render.emSize.Height + LineMarkerThickness;\r
- y += rulerHeight;\r
- height -= rulerHeight;\r
- }\r
-\r
- if (width < 0)\r
- width = 0;\r
-\r
- if (height < 0)\r
- height = 0;\r
-\r
- this.render.TextArea = new Rectangle(x, y, width, height);\r
-\r
- this.LineBreakingMarginWidth = width * 5 / 100;\r
- }\r
-\r
- public override void CalculateLineCountOnScreen()\r
- {\r
- if (this.LayoutLines.Count == 0 || this.PageBound.Height == 0)\r
- return;\r
-\r
- double y = 0;\r
- int i = this.Src.Row;\r
- int visualCount = this.Src.Row;\r
- for (; true; i++)\r
- {\r
- int row = i < this.LayoutLines.Count ? i : this.LayoutLines.Count - 1;\r
-\r
- int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(row);\r
- int lineLength = this.LayoutLines.GetLengthFromLineNumber(row);\r
-\r
- if (this.LayoutLines.FoldingCollection.IsHidden(lineHeadIndex) && row < this.LayoutLines.Count - 1)\r
- continue;\r
-\r
- ITextLayout layout = this.LayoutLines.GetLayout(row);\r
-\r
- double width = layout.Width;\r
-\r
- if (width > this._LongestWidth)\r
- this._LongestWidth = width;\r
-\r
- double lineHeight = layout.Height;\r
-\r
- y += lineHeight;\r
-\r
- if (y >= this.render.TextArea.Height)\r
- break;\r
- visualCount++;\r
- }\r
- this.LineCountOnScreen = Math.Max(visualCount - this.Src.Row - 1, 0);\r
- this.LineCountOnScreenWithInVisible = Math.Max(i - this.Src.Row - 1, 0);\r
- }\r
-\r
- void SetCaretPostion(double x, double y)\r
- {\r
- this._CaretLocation = new Point(x + this.PageBound.X, y + this.PageBound.Y);\r
- }\r
-\r
- void FoldingCollection_StatusChanged(object sender, FoldingItemStatusChangedEventArgs e)\r
- {\r
- this.CalculateLineCountOnScreen();\r
- }\r
-\r
- enum AreaType\r
- {\r
- UpdateArea,\r
- FoldingArea,\r
- LineNumberArea,\r
- TextArea\r
- }\r
-\r
- double GetRealtiveX(AreaType type)\r
- {\r
- IEditorRender render = (IEditorRender)base.render;\r
- switch (type)\r
- {\r
- case AreaType.UpdateArea:\r
- if (this.render.RightToLeft)\r
- return this.PageBound.TopRight.X - UpdateAreaTotalWidth;\r
- if (this.DrawLineNumber)\r
- return this.render.TextArea.X - this.render.LineNemberWidth - this.LineNumberMargin - render.FoldingWidth - UpdateAreaTotalWidth;\r
- else\r
- return this.render.TextArea.X - render.FoldingWidth - UpdateAreaTotalWidth;\r
- case AreaType.FoldingArea:\r
- if (this.render.RightToLeft)\r
- return this.PageBound.TopRight.X - render.FoldingWidth;\r
- if (this.DrawLineNumber)\r
- return this.render.TextArea.X - this.render.LineNemberWidth - this.LineNumberMargin - render.FoldingWidth;\r
- else\r
- return this.render.TextArea.X - render.FoldingWidth;\r
- case AreaType.LineNumberArea:\r
- if (this.DrawLineNumber == false)\r
- throw new InvalidOperationException();\r
- if (this.render.RightToLeft)\r
- return this.PageBound.TopRight.X - UpdateAreaTotalWidth - render.FoldingWidth - this.render.LineNemberWidth;\r
- else\r
- return this.render.TextArea.X - this.render.LineNemberWidth - this.LineNumberMargin;\r
- case AreaType.TextArea:\r
- return this.render.TextArea.X;\r
- }\r
- throw new ArgumentOutOfRangeException();\r
- }\r
- }\r
-}\r
+/*
+ * Copyright (C) 2013 FooProject
+ * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+using System.Linq;
+using System.Collections.Generic;
+
+namespace FooEditEngine
+{
+ enum AdjustFlow
+ {
+ Row,
+ Col,
+ Both,
+ }
+
+ /// <summary>
+ /// キャレットとドキュメントの表示を担当します。レイアウト関連もこちらで行います
+ /// </summary>
+ sealed class EditView : ViewBase
+
+ {
+ internal const float LineMarkerThickness = 2;
+ Point _CaretLocation = new Point();
+ TextPoint _CaretPostion = new TextPoint();
+ long tickCount;
+ bool _CaretBlink,_HideRuler = true;
+ internal const int LineNumberLength = 6;
+ const int UpdateAreaPaddingWidth = 2;
+ const int UpdateAreaWidth = 4;
+ const int UpdateAreaTotalWidth = UpdateAreaWidth + UpdateAreaPaddingWidth;
+
+ /// <summary>
+ /// コンストラクター
+ /// </summary>
+ public EditView(Document doc, IEditorRender r,int MarginLeftAndRight = 5)
+ : this(doc,r,new Padding(MarginLeftAndRight, 0, MarginLeftAndRight, 0))
+ {
+ }
+
+ /// <summary>
+ /// コンストラクター
+ /// </summary>
+ /// <param name="doc">ドキュメント</param>
+ /// <param name="r">レンダー</param>
+ /// <param name="margin">マージン(1番目:左、2番目:上、3番目:右、4番目:下)</param>
+ public EditView(Document doc, IEditorRender r, Padding margin)
+ : base(doc,r,margin)
+ {
+ this.CaretBlinkTime = 500;
+ this.CaretWidthOnInsertMode = 1;
+ this.CalculateClipRect();
+ this._CaretLocation.X = this.render.TextArea.X;
+ this._CaretLocation.Y = this.render.TextArea.Y;
+ this.LayoutLines.FoldingCollection.StatusChanged += FoldingCollection_StatusChanged;
+ this.InsertPoint = null;
+ this.HideLineMarker = true;
+ this.IsFocused = false;
+ this.Selections = new SelectCollection();
+ }
+
+ /// <summary>
+ /// 選択範囲コレクション
+ /// </summary>
+ internal SelectCollection Selections
+ {
+ get;
+ private set;
+ }
+
+ /// <summary>
+ /// ラインマーカーを描くなら偽。そうでなければ真
+ /// </summary>
+ public bool HideLineMarker
+ {
+ get;
+ set;
+ }
+
+ /// <summary>
+ /// キャレットを描くなら偽。そうでなければ真
+ /// </summary>
+ public bool HideCaret
+ {
+ get;
+ set;
+ }
+
+ /// <summary>
+ /// 挿入モードなら真を返し、上書きモードなら偽を返す
+ /// </summary>
+ public bool InsertMode
+ {
+ get;
+ set;
+ }
+
+ /// <summary>
+ /// キャレットの点滅間隔
+ /// </summary>
+ public int CaretBlinkTime
+ {
+ get;
+ set;
+ }
+
+ /// <summary>
+ /// 挿入モード時のキャレットの幅
+ /// </summary>
+ public double CaretWidthOnInsertMode
+ {
+ get;
+ set;
+ }
+
+ /// <summary>
+ /// フォーカスがあるなら真をセットする
+ /// </summary>
+ public bool IsFocused
+ {
+ get;
+ set;
+ }
+
+ /// <summary>
+ /// キャレットを点滅させるなら真。そうでないなら偽
+ /// </summary>
+ /// <remarks>キャレット点滅タイマーもリセットされます</remarks>
+ public bool CaretBlink
+ {
+ get { return this._CaretBlink; }
+ set
+ {
+ this._CaretBlink = value;
+ if (value)
+ this.tickCount = DateTime.Now.Ticks + this.To100nsTime(this.CaretBlinkTime);
+ }
+ }
+
+ /// <summary>
+ /// 一ページの高さに収まる行数を返す(こちらは表示されていない行も含みます)
+ /// </summary>
+ public int LineCountOnScreenWithInVisible
+ {
+ get;
+ private set;
+ }
+
+ /// <summary>
+ /// スクロール時に確保するマージン幅
+ /// </summary>
+ public double ScrollMarginWidth
+ {
+ get { return this.PageBound.Width * 20 / 100; }
+ }
+
+ /// <summary>
+ /// ルーラーを表示しないなら真、そうでないなら偽
+ /// </summary>
+ public bool HideRuler
+ {
+ get { return this._HideRuler; }
+ set
+ {
+ this._HideRuler = value;
+ this.LayoutLines.ClearLayoutCache();
+ CalculateClipRect();
+ CalculateLineCountOnScreen();
+ }
+ }
+
+ /// <summary>
+ /// 矩形選択モード中に文字列が挿入される位置を表す
+ /// </summary>
+ public SelectCollection InsertPoint
+ {
+ get;
+ set;
+ }
+
+ /// <summary>
+ /// キャレットがある領域を示す
+ /// </summary>
+ public Point CaretLocation
+ {
+ get { return this._CaretLocation; }
+ }
+
+ /// <summary>
+ /// レイアウト行のどこにキャレットがあるかを表す
+ /// </summary>
+ public TextPoint CaretPostion
+ {
+ get { return this._CaretPostion; }
+ }
+
+ /// <summary>
+ /// ヒットテストを行う
+ /// </summary>
+ /// <param name="x">x座標</param>
+ /// <param name="y">y座標</param>
+ /// <returns>テキストエリア内にあれば真。そうでなければ偽</returns>
+ public bool HitTextArea(double x, double y)
+ {
+ if (x >= this.render.TextArea.X && x <= this.render.TextArea.Right &&
+ y >= this.render.TextArea.Y && y <= this.render.TextArea.Bottom)
+ return true;
+ else
+ return false;
+ }
+
+ /// <summary>
+ /// ヒットテストを行う
+ /// </summary>
+ /// <param name="x">x座標</param>
+ /// <param name="row">行</param>
+ /// <returns>ヒットした場合はFoldingDataオブジェクトが返され、そうでない場合はnullが返る</returns>
+ public FoldingItem HitFoldingData(double x, int row)
+ {
+ IEditorRender render = (IEditorRender)base.render;
+
+ if (x >= this.GetRealtiveX(AreaType.FoldingArea) && x <= this.GetRealtiveX(AreaType.FoldingArea) + render.FoldingWidth)
+ {
+ int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(row);
+ int lineLength = this.LayoutLines.GetLengthFromLineNumber(row);
+ FoldingItem foldingData = this.LayoutLines.FoldingCollection.Get(lineHeadIndex, lineLength);
+ if (foldingData != null && foldingData.IsFirstLine(this.LayoutLines,row))
+ return foldingData;
+ }
+ return null;
+ }
+
+ /// <summary>
+ /// Rectで指定された範囲にドキュメントを描く
+ /// </summary>
+ /// <param name="updateRect">描写する範囲</param>
+ /// <remarks>キャレットを点滅させる場合、定期的のこのメソッドを呼び出してください</remarks>
+ public override void Draw(Rectangle updateRect)
+ {
+ if (this.LayoutLines.Count == 0)
+ return;
+
+ IEditorRender render = (IEditorRender)base.render;
+
+ if ((updateRect.Height < this.PageBound.Height ||
+ updateRect.Width < this.PageBound.Width) &&
+ render.IsVaildCache())
+ {
+ render.DrawCachedBitmap(updateRect);
+ }
+ else
+ {
+ Rectangle background = this.PageBound;
+ render.FillBackground(background);
+
+ if (this.HideRuler == false)
+ this.DrawRuler();
+
+ this.DrawLineMarker(this.CaretPostion.row);
+
+ Point pos = this.render.TextArea.TopLeft;
+ pos.X -= this.Src.X;
+ double endposy = this.render.TextArea.Bottom;
+ Size lineNumberSize = new Size(this.render.LineNemberWidth,this.render.TextArea.Height);
+ for (int i = this.Src.Row; i < this.LayoutLines.Count; i++)
+ {
+ int lineIndex = this.LayoutLines.GetIndexFromLineNumber(i);
+ int lineLength = this.LayoutLines.GetLengthFromLineNumber(i);
+ ITextLayout layout = this.LayoutLines.GetLayout(i);
+
+ if (pos.Y + layout.Height > endposy)
+ break;
+
+ FoldingItem foldingData = this.LayoutLines.FoldingCollection.Get(lineIndex, lineLength);
+
+ if (foldingData != null)
+ {
+ if ((!this.LayoutLines.FoldingCollection.IsHasParent(foldingData) ||
+ !this.LayoutLines.FoldingCollection.IsParentHidden(foldingData))
+ && foldingData.IsFirstLine(this.LayoutLines, i))
+ render.DrawFoldingMark(foldingData.Expand, this.PageBound.X + this.GetRealtiveX(AreaType.FoldingArea), pos.Y);
+ if (this.LayoutLines.FoldingCollection.IsHidden(lineIndex))
+ continue;
+ }
+
+ var selectRange = from s in this.Selections.Get(lineIndex, lineLength)
+ let n = Util.ConvertAbsIndexToRelIndex(s, lineIndex, lineLength)
+ select n;
+
+ this.render.DrawOneLine(this.LayoutLines, i, pos.X, pos.Y, selectRange);
+
+ if (this.DrawLineNumber)
+ {
+ this.render.DrawString((i + 1).ToString(), this.PageBound.X + this.GetRealtiveX(AreaType.LineNumberArea), pos.Y, StringAlignment.Right, lineNumberSize,StringColorType.LineNumber);
+ }
+
+ DrawUpdateArea(i, pos.Y);
+
+ pos.Y += this.LayoutLines.GetLayout(i).Height;
+ }
+
+ if (this.InsertPoint != null)
+ this.DrawInsertPoint();
+
+ render.CacheContent();
+ }
+
+ this.DrawCaret();
+ }
+
+ void DrawUpdateArea(int row,double ypos)
+ {
+ IEditorRender render = (IEditorRender)base.render;
+ if(this.LayoutLines.GetDirtyFlag(row))
+ {
+ Point pos = new Point(this.PageBound.X + this.GetRealtiveX(AreaType.UpdateArea), ypos);
+ Rectangle rect = new Rectangle(pos.X, pos.Y, UpdateAreaWidth, this.LayoutLines.GetLayout(row).Height);
+ render.FillRectangle(rect, FillRectType.UpdateArea);
+ }
+ }
+
+ void DrawRuler()
+ {
+ IEditorRender render = (IEditorRender)base.render;
+
+ Point pos, from, to;
+ Size emSize = render.emSize;
+ Rectangle clipRect = this.render.TextArea;
+ int count = 0;
+ double markerHeight = emSize.Height / 2;
+ if (this.render.RightToLeft)
+ {
+ pos = new Point(clipRect.TopRight.X, clipRect.TopRight.Y - emSize.Height - LineMarkerThickness);
+ for (; pos.X >= clipRect.TopLeft.X; pos.X -= emSize.Width, count++)
+ {
+ from = pos;
+ to = new Point(pos.X, pos.Y + emSize.Height);
+ int mod = count % 10;
+ if (mod == 0)
+ {
+ string countStr = (count / 10).ToString();
+ double counterWidth = emSize.Width * countStr.Length;
+ this.render.DrawString(countStr, pos.X - counterWidth, pos.Y, StringAlignment.Right, new Size(counterWidth, double.MaxValue));
+ }
+ else if (mod == 5)
+ from.Y = from.Y + emSize.Height / 2;
+ else
+ from.Y = from.Y + emSize.Height * 3 / 4;
+ render.DrawLine(from, to);
+ if (this.CaretLocation.X >= pos.X && this.CaretLocation.X < pos.X + emSize.Width)
+ render.FillRectangle(new Rectangle(pos.X, pos.Y + markerHeight, emSize.Width, markerHeight), FillRectType.OverwriteCaret);
+ }
+ }
+ else
+ {
+ pos = new Point(clipRect.TopLeft.X, clipRect.TopLeft.Y - emSize.Height - LineMarkerThickness);
+ for (; pos.X < clipRect.TopRight.X; pos.X += emSize.Width, count++)
+ {
+ from = pos;
+ to = new Point(pos.X, pos.Y + emSize.Height);
+ int mod = count % 10;
+ if (mod == 0)
+ this.render.DrawString((count / 10).ToString(), pos.X, pos.Y, StringAlignment.Left, new Size(double.MaxValue, double.MaxValue));
+ else if (mod == 5)
+ from.Y = from.Y + emSize.Height / 2;
+ else
+ from.Y = from.Y + emSize.Height * 3 / 4;
+ render.DrawLine(from, to);
+ if (this.CaretLocation.X >= pos.X && this.CaretLocation.X < pos.X + emSize.Width)
+ render.FillRectangle(new Rectangle(pos.X, pos.Y + markerHeight, emSize.Width, markerHeight), FillRectType.OverwriteCaret);
+ }
+ }
+ from = clipRect.TopLeft;
+ from.Y -= LineMarkerThickness;
+ to = clipRect.TopRight;
+ to.Y -= LineMarkerThickness;
+ render.DrawLine(from, to);
+ }
+
+ void DrawInsertPoint()
+ {
+ IEditorRender render = (IEditorRender)base.render;
+ foreach (Selection sel in this.InsertPoint)
+ {
+ if (sel.length == 0)
+ {
+ TextPoint tp = this.GetLayoutLineFromIndex(sel.start);
+ Point left = this.GetPostionFromTextPoint(tp);
+ double lineHeight = this.LayoutLines.GetLayout(tp.row).Height;
+ Rectangle InsertRect = new Rectangle(left.X,
+ left.Y,
+ CaretWidthOnInsertMode,
+ lineHeight);
+ render.FillRectangle(InsertRect, FillRectType.InsertPoint);
+ }
+ }
+ }
+
+ void DrawCaret()
+ {
+ if (this.HideCaret || !this.IsFocused)
+ return;
+
+ long diff = DateTime.Now.Ticks - this.tickCount;
+ long blinkTime = this.To100nsTime(this.CaretBlinkTime);
+
+ if (this._CaretBlink && diff % blinkTime >= blinkTime / 2)
+ return;
+
+ Rectangle CaretRect = new Rectangle();
+
+ IEditorRender render = (IEditorRender)base.render;
+
+ int row = this.CaretPostion.row;
+ double lineHeight = this.LayoutLines.GetLayout(row).Height;
+ double charWidth = this.LayoutLines.GetLayout(row).GetWidthFromIndex(this.CaretPostion.col);
+
+ if (this.InsertMode || charWidth == 0)
+ {
+ CaretRect.Size = new Size(CaretWidthOnInsertMode, lineHeight);
+ CaretRect.Location = new Point(this.CaretLocation.X, this.CaretLocation.Y);
+ render.FillRectangle(CaretRect, FillRectType.InsertCaret);
+ }
+ else
+ {
+ double height = lineHeight / 3;
+ CaretRect.Size = new Size(charWidth, height);
+ CaretRect.Location = new Point(this.CaretLocation.X, this.CaretLocation.Y + lineHeight - height);
+ render.FillRectangle(CaretRect, FillRectType.OverwriteCaret);
+ }
+ }
+
+ long To100nsTime(int ms)
+ {
+ return ms * 10000;
+ }
+
+ public void DrawLineMarker(int row)
+ {
+ if (this.HideLineMarker || !this.IsFocused)
+ return;
+ IEditorRender render = (IEditorRender)base.render;
+ Point p = this.CaretLocation;
+ double height = this.LayoutLines.GetLayout(this.CaretPostion.row).Height;
+ double width = this.render.TextArea.Width;
+ render.FillRectangle(new Rectangle(this.PageBound.X + this.render.TextArea.X, this.CaretLocation.Y, width, height), FillRectType.LineMarker);
+ }
+
+ /// <summary>
+ /// 指定した座標の一番近くにあるTextPointを取得する
+ /// </summary>
+ /// <param name="p">テキストエリアを左上とする相対位置</param>
+ /// <returns>レイアウトラインを指し示すTextPoint</returns>
+ public TextPoint GetTextPointFromPostion(Point p)
+ {
+ if (p.Y < this.render.TextArea.TopLeft.Y ||
+ p.Y > this.render.TextArea.BottomRight.Y)
+ return TextPoint.Null;
+ TextPoint tp = new TextPoint();
+
+ if (this.LayoutLines.Count == 0)
+ return tp;
+
+ p.Y -= this.render.TextArea.Y;
+
+ int lineHeadIndex, lineLength;
+ double y = 0;
+ tp.row = this.LayoutLines.Count - 1;
+ for (int i = this.Src.Row; i < this.LayoutLines.Count; i++)
+ {
+ double height = this.LayoutLines.GetLayout(i).Height;
+
+ lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(i);
+ lineLength = this.LayoutLines.GetLengthFromLineNumber(i);
+
+ if (this.LayoutLines.FoldingCollection.IsHidden(lineHeadIndex))
+ continue;
+
+ if (y + height > p.Y)
+ {
+ tp.row = i;
+ break;
+ }
+ y += height;
+ }
+
+ if (p.X < this.render.TextArea.X)
+ return tp;
+
+ tp.col = GetIndexFromColPostion(tp.row, p.X);
+
+ lineLength = this.LayoutLines.GetLengthFromLineNumber(tp.row);
+ if (tp.col > lineLength)
+ tp.col = lineLength;
+
+ return tp;
+ }
+
+ /// <summary>
+ /// 桁方向の座標に対応するインデックスを取得する
+ /// </summary>
+ /// <param name="row">対象となる行</param>
+ /// <param name="x">テキストエリアからの相対位置</param>
+ /// <returns></returns>
+ public int GetIndexFromColPostion(int row, double x)
+ {
+ x -= this.render.TextArea.X;
+ int lineLength = this.LayoutLines.GetLengthFromLineNumber(row);
+ if (lineLength == 0)
+ return 0;
+ int index = this.LayoutLines.GetLayout(row).GetIndexFromColPostion(this.Src.X + x);
+ return index;
+ }
+
+ /// <summary>
+ /// インデックスに対応する桁方向の座標を得る
+ /// </summary>
+ /// <param name="row">対象となる行</param>
+ /// <param name="index">インデックス</param>
+ /// <returns>テキストエリアからの相対位置を返す</returns>
+ public double GetColPostionFromIndex(int row, int index)
+ {
+ double x = this.LayoutLines.GetLayout(row).GetColPostionFromIndex(index);
+ return x - Src.X + this.render.TextArea.X;
+ }
+
+ /// <summary>
+ /// TextPointに対応する座標を得る
+ /// </summary>
+ /// <param name="tp">レイアウトライン上の位置</param>
+ /// <returns>テキストエリアを左上とする相対位置</returns>
+ public Point GetPostionFromTextPoint(TextPoint tp)
+ {
+ Point p = new Point();
+ for (int i = this.Src.Row; i < tp.row; i++)
+ {
+ int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(i);
+ int lineLength = this.LayoutLines.GetLengthFromLineNumber(i);
+ if (this.LayoutLines.FoldingCollection.IsHidden(lineHeadIndex))
+ continue;
+ p.Y += this.LayoutLines.GetLayout(i).Height;
+ }
+ p.X = this.GetColPostionFromIndex(tp.row, tp.col);
+ p.Y += this.render.TextArea.Y;
+ return p;
+ }
+
+ /// <summary>
+ /// キャレットを指定した位置に移動させる
+ /// </summary>
+ /// <param name="row"></param>
+ /// <param name="col"></param>
+ /// <param name="autoExpand">折り畳みを展開するなら真</param>
+ public void JumpCaret(int row, int col, bool autoExpand = true)
+ {
+ if (autoExpand)
+ {
+ int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(row);
+ int lineLength = this.LayoutLines.GetLengthFromLineNumber(row);
+ FoldingItem foldingData = this.LayoutLines.FoldingCollection.Get(lineHeadIndex, lineLength);
+ if(foldingData != null)
+ {
+ if (this.LayoutLines.FoldingCollection.IsParentHidden(foldingData) || !foldingData.IsFirstLine(this.LayoutLines, row))
+ {
+ this.LayoutLines.FoldingCollection.Expand(foldingData);
+ }
+ }
+ }
+
+ this._CaretPostion.row = row;
+ this._CaretPostion.col = col;
+ }
+
+ /// <summary>
+ /// index上の文字が表示されるようにSrcを調整する
+ /// </summary>
+ /// <param name="index">インデックス</param>
+ /// <returns>調整されたら真。そうでなければ偽</returns>
+ public bool AdjustSrc(int index)
+ {
+ TextPoint startTextPoint = this.GetLayoutLineFromIndex(index);
+ double x = this.LayoutLines.GetLayout(startTextPoint.row).GetColPostionFromIndex(startTextPoint.col);
+ if (x < this.Src.X ||
+ x > this.Src.X + this.PageBound.Width)
+ {
+ this.TryScroll(x, this.Src.Row);
+ return true;
+ }
+ if (startTextPoint.row < this.Src.Row ||
+ startTextPoint.row > this.Src.Row + this.LineCountOnScreenWithInVisible)
+ {
+ this.TryScroll(this.Src.X, startTextPoint.row);
+ return true;
+ }
+ return false;
+ }
+
+ /// <summary>
+ /// キャレットがあるところまでスクロールする
+ /// </summary>
+ /// <return>再描写する必要があるなら真を返す</return>
+ /// <remarks>Document.Update(type == UpdateType.Clear)イベント時に呼び出した場合、例外が発生します</remarks>
+ public bool AdjustCaretAndSrc(AdjustFlow flow = AdjustFlow.Both)
+ {
+ IEditorRender render = (IEditorRender)base.render;
+
+ if (this.PageBound.Width == 0 || this.PageBound.Height == 0)
+ {
+ this.SetCaretPostion(this.Padding.Left + render.FoldingWidth, 0);
+ return false;
+ }
+
+ bool result = false;
+ TextPoint tp = this.CaretPostion;
+ double x = this.CaretLocation.X;
+ double y = this.CaretLocation.Y;
+
+ if (flow == AdjustFlow.Col || flow == AdjustFlow.Both)
+ {
+ x = this.LayoutLines.GetLayout(tp.row).GetColPostionFromIndex(tp.col);
+
+ double left = this.Src.X;
+ double right = this.Src.X + this.render.TextArea.Width;
+
+ if (x >= left && x <= right) //xは表示領域にないにある
+ {
+ x -= left;
+ }
+ else if (x > right) //xは表示領域の右側にある
+ {
+ this._Src.X = x - this.render.TextArea.Width + this.ScrollMarginWidth;
+ if (this.render.RightToLeft && this._Src.X > 0)
+ {
+ System.Diagnostics.Debug.Assert(x > 0);
+ this._Src.X = 0;
+ }
+ else
+ {
+ x = this.render.TextArea.Width - this.ScrollMarginWidth;
+ }
+ result = true;
+ }
+ else if (x < left) //xは表示領域の左側にある
+ {
+ this._Src.X = x - this.ScrollMarginWidth;
+ if (!this.render.RightToLeft && this._Src.X < this.render.TextArea.X)
+ {
+ this._Src.X = 0;
+ }
+ else
+ {
+ x = this.ScrollMarginWidth;
+ }
+ result = true;
+ }
+ x += this.render.TextArea.X;
+ }
+
+ if (flow == AdjustFlow.Row || flow == AdjustFlow.Both)
+ {
+ int caretRow = 0;
+ int lineCount = this.LineCountOnScreenWithInVisible;
+ if (tp.row >= this.Src.Row && tp.row < this.Src.Row + lineCount)
+ caretRow = tp.row - this.Src.Row;
+ else if (tp.row >= this.Src.Row + lineCount)
+ {
+ this._Src.Row = this.GetSrcRow(tp.row, this.LineCountOnScreen);
+ caretRow = tp.row - this._Src.Row;
+ result = true;
+ CalculateLineCountOnScreen();
+ }
+ else if (tp.row < this.Src.Row)
+ {
+ this._Src.Row = tp.row;
+ result = true;
+ CalculateLineCountOnScreen();
+ }
+
+ y = 0;
+
+ if (caretRow > 0)
+ {
+ for (int i = 0; i < caretRow; i++)
+ {
+ int currentRow = this.Src.Row + i;
+ int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(currentRow);
+ int lineLength = this.LayoutLines.GetLengthFromLineNumber(currentRow);
+
+ if (this.LayoutLines.FoldingCollection.IsHidden(lineHeadIndex))
+ continue;
+
+ y += this.LayoutLines.GetLayout(currentRow).Height;
+ }
+ }
+ y += this.render.TextArea.Y;
+ }
+
+ this.SetCaretPostion(x, y);
+
+ if (result)
+ this.OnSrcChanged(null);
+
+ return result;
+ }
+
+ int GetSrcRow(int row,int count)
+ {
+ if (this.LayoutLines.FoldingStrategy == null)
+ return row - count;
+ for (int i = row; i >= 0; i--)
+ {
+ int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(i);
+ int lineLength = this.LayoutLines.GetLengthFromLineNumber(i);
+ if (this.LayoutLines.FoldingCollection.IsHidden(lineHeadIndex))
+ continue;
+ if (count <= 0)
+ return i;
+ count--;
+ }
+ return 0;
+ }
+
+ /// <summary>
+ /// レイアウト行をテキストポイントからインデックスに変換する
+ /// </summary>
+ /// <param name="tp">テキストポイント表す</param>
+ /// <returns>インデックスを返す</returns>
+ public int GetIndexFromLayoutLine(TextPoint tp)
+ {
+ return this.LayoutLines.GetIndexFromTextPoint(tp);
+ }
+
+ /// <summary>
+ /// インデックスからレイアウト行を指し示すテキストポイントに変換する
+ /// </summary>
+ /// <param name="index">インデックスを表す</param>
+ /// <returns>テキストポイント返す</returns>
+ public TextPoint GetLayoutLineFromIndex(int index)
+ {
+ return this.LayoutLines.GetTextPointFromIndex(index);
+ }
+
+ /// <summary>
+ /// 指定した座標までスクロールする
+ /// </summary>
+ /// <param name="x"></param>
+ /// <param name="row"></param>
+ /// <remarks>
+ /// 範囲外の座標を指定した場合、範囲内に収まるように調整されます
+ /// </remarks>
+ public void Scroll(double x, int row)
+ {
+ if (x < 0)
+ x = 0;
+ if(row < 0)
+ row = 0;
+ int endRow = this.LayoutLines.Count - 1 - this.LineCountOnScreen;
+ if (endRow < 0)
+ endRow = 0;
+ if (row > endRow)
+ row = endRow;
+ base.TryScroll(x, row);
+ }
+
+ /// <summary>
+ /// 指定行までスクロールする
+ /// </summary>
+ /// <param name="row">行</param>
+ /// <param name="alignTop">指定行を画面上に置くなら真。そうでないなら偽</param>
+ public void ScrollIntoView(int row, bool alignTop)
+ {
+ this.Scroll(0, row);
+ if (alignTop)
+ return;
+ double y = this.render.TextArea.Height;
+ for (int i = row; i >= 0; i--)
+ {
+ int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(i);
+ int lineLength = this.LayoutLines.GetLengthFromLineNumber(i);
+ double height = this.LayoutLines.GetLayout(i).Height;
+ if (y - height <= 0)
+ {
+ this.Scroll(0, i);
+ }
+ if (this.LayoutLines.FoldingCollection.IsHidden(lineHeadIndex))
+ continue;
+ y -= height;
+ }
+ }
+
+ public int AdjustRow(int row, bool isMoveNext)
+ {
+ if (this.LayoutLines.FoldingStrategy == null)
+ return row;
+ int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(row);
+ int lineLength = this.LayoutLines.GetLengthFromLineNumber(row);
+ FoldingItem foldingData = this.LayoutLines.FoldingCollection.GetFarestHiddenFoldingData(lineHeadIndex, lineLength);
+ if (foldingData != null && !foldingData.Expand)
+ {
+ if (foldingData.End == this.Document.Length)
+ return row;
+ if (isMoveNext && lineHeadIndex > foldingData.Start)
+ row = this.LayoutLines.GetLineNumberFromIndex(foldingData.End) + 1;
+ else
+ row = this.LayoutLines.GetLineNumberFromIndex(foldingData.Start);
+ if(row > this.LayoutLines.Count - 1)
+ row = this.LayoutLines.GetLineNumberFromIndex(foldingData.Start);
+ }
+ return row;
+ }
+
+ protected override void CalculateClipRect()
+ {
+ IEditorRender render = (IEditorRender)base.render;
+ double x, y, width, height;
+
+ if (this.DrawLineNumber)
+ {
+ if (this.render.RightToLeft)
+ x = this.Padding.Left;
+ else
+ x = this.Padding.Left + UpdateAreaTotalWidth + this.render.LineNemberWidth + this.LineNumberMargin + render.FoldingWidth;
+ width = this.PageBound.Width - this.render.LineNemberWidth - this.LineNumberMargin - this.Padding.Left - this.Padding.Right - render.FoldingWidth - UpdateAreaTotalWidth;
+ }
+ else
+ {
+ if (this.render.RightToLeft)
+ x = this.Padding.Left;
+ else
+ x = this.Padding.Left + UpdateAreaTotalWidth + render.FoldingWidth;
+ width = this.PageBound.Width - this.Padding.Left - this.Padding.Right - render.FoldingWidth - UpdateAreaTotalWidth;
+ }
+
+ y = this.Padding.Top;
+ height = this.PageBound.Height - this.Padding.Top - this.Padding.Bottom;
+
+ if (this.HideRuler == false)
+ {
+ double rulerHeight = this.render.emSize.Height + LineMarkerThickness;
+ y += rulerHeight;
+ height -= rulerHeight;
+ }
+
+ if (width < 0)
+ width = 0;
+
+ if (height < 0)
+ height = 0;
+
+ this.render.TextArea = new Rectangle(x, y, width, height);
+
+ this.LineBreakingMarginWidth = width * 5 / 100;
+ }
+
+ public override void CalculateLineCountOnScreen()
+ {
+ if (this.LayoutLines.Count == 0 || this.PageBound.Height == 0)
+ return;
+
+ double y = 0;
+ int i = this.Src.Row;
+ int visualCount = this.Src.Row;
+ for (; true; i++)
+ {
+ int row = i < this.LayoutLines.Count ? i : this.LayoutLines.Count - 1;
+
+ int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(row);
+ int lineLength = this.LayoutLines.GetLengthFromLineNumber(row);
+
+ if (this.LayoutLines.FoldingCollection.IsHidden(lineHeadIndex) && row < this.LayoutLines.Count - 1)
+ continue;
+
+ ITextLayout layout = this.LayoutLines.GetLayout(row);
+
+ double width = layout.Width;
+
+ if (width > this._LongestWidth)
+ this._LongestWidth = width;
+
+ double lineHeight = layout.Height;
+
+ y += lineHeight;
+
+ if (y >= this.render.TextArea.Height)
+ break;
+ visualCount++;
+ }
+ this.LineCountOnScreen = Math.Max(visualCount - this.Src.Row - 1, 0);
+ this.LineCountOnScreenWithInVisible = Math.Max(i - this.Src.Row - 1, 0);
+ }
+
+ void SetCaretPostion(double x, double y)
+ {
+ this._CaretLocation = new Point(x + this.PageBound.X, y + this.PageBound.Y);
+ }
+
+ void FoldingCollection_StatusChanged(object sender, FoldingItemStatusChangedEventArgs e)
+ {
+ this.CalculateLineCountOnScreen();
+ }
+
+ enum AreaType
+ {
+ UpdateArea,
+ FoldingArea,
+ LineNumberArea,
+ TextArea
+ }
+
+ double GetRealtiveX(AreaType type)
+ {
+ IEditorRender render = (IEditorRender)base.render;
+ switch (type)
+ {
+ case AreaType.UpdateArea:
+ if (this.render.RightToLeft)
+ return this.PageBound.TopRight.X - UpdateAreaTotalWidth;
+ if (this.DrawLineNumber)
+ return this.render.TextArea.X - this.render.LineNemberWidth - this.LineNumberMargin - render.FoldingWidth - UpdateAreaTotalWidth;
+ else
+ return this.render.TextArea.X - render.FoldingWidth - UpdateAreaTotalWidth;
+ case AreaType.FoldingArea:
+ if (this.render.RightToLeft)
+ return this.PageBound.TopRight.X - render.FoldingWidth;
+ if (this.DrawLineNumber)
+ return this.render.TextArea.X - this.render.LineNemberWidth - this.LineNumberMargin - render.FoldingWidth;
+ else
+ return this.render.TextArea.X - render.FoldingWidth;
+ case AreaType.LineNumberArea:
+ if (this.DrawLineNumber == false)
+ throw new InvalidOperationException();
+ if (this.render.RightToLeft)
+ return this.PageBound.TopRight.X - UpdateAreaTotalWidth - render.FoldingWidth - this.render.LineNemberWidth;
+ else
+ return this.render.TextArea.X - this.render.LineNemberWidth - this.LineNumberMargin;
+ case AreaType.TextArea:
+ return this.render.TextArea.X;
+ }
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+}
-/*\r
- * Copyright (C) 2013 FooProject\r
- * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.\r
-\r
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of \r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\r
-\r
-You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.\r
- */\r
-using System;\r
-using System.Collections;\r
-using System.Collections.Generic;\r
-using System.Linq;\r
-using System.Text;\r
-using System.Threading.Tasks;\r
-\r
-namespace FooEditEngine\r
-{\r
- /// <summary>\r
- /// 新しく作成されるフォールティングアイテムを表す\r
- /// </summary>\r
- public class FoldingItem : IRangeProvider<int>\r
- {\r
- /// <summary>\r
- /// 開始インデックス\r
- /// </summary>\r
- public int Start\r
- {\r
- get\r
- {\r
- return this.Range.From;\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// 終了インデックス\r
- /// </summary>\r
- public int End\r
- {\r
- get\r
- {\r
- return this.Range.To;\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// 展開されているなら真。そうでないなら偽\r
- /// </summary>\r
- public bool Expand\r
- {\r
- get;\r
- internal set;\r
- }\r
-\r
- /// <summary>\r
- /// 内部で使用しているメンバーです。外部から参照しないでください\r
- /// </summary>\r
- public Range<int> Range\r
- {\r
- get;\r
- set;\r
- }\r
-\r
- /// <summary>\r
- /// コンストラクター\r
- /// </summary>\r
- /// <param name="start">開始インデックス</param>\r
- /// <param name="end">終了インデックス</param>\r
- /// <param name="expand">展開フラグ</param>\r
- public FoldingItem(int start, int end,bool expand = true)\r
- {\r
- if (start >= end)\r
- throw new ArgumentException("start < endである必要があります");\r
- this.Range = new Range<int>(start, end);\r
- this.Expand = expand;\r
- }\r
-\r
- internal bool IsFirstLine(LineToIndexTable layoutLines, int row)\r
- {\r
- int firstRow = layoutLines.GetLineNumberFromIndex(this.Start);\r
- return row == firstRow;\r
- }\r
- }\r
-\r
- sealed class RangeItemComparer : IComparer<FoldingItem>\r
- {\r
- public int Compare(FoldingItem x, FoldingItem y)\r
- {\r
- return x.Range.CompareTo(y.Range);\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// イベントデーター\r
- /// </summary>\r
- public sealed class FoldingItemStatusChangedEventArgs : EventArgs\r
- {\r
- /// <summary>\r
- /// 状態に変化があったアイテム\r
- /// </summary>\r
- public FoldingItem Item;\r
- /// <summary>\r
- /// コンストラクター\r
- /// </summary>\r
- /// <param name="item">FoldingItemオブジェクト</param>\r
- public FoldingItemStatusChangedEventArgs(FoldingItem item)\r
- {\r
- this.Item = item;\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// 折り畳み関係のコレクションを表す\r
- /// </summary>\r
- public sealed class FoldingCollection : IEnumerable<FoldingItem>\r
- {\r
- RangeTree<int, FoldingItem> collection = new RangeTree<int, FoldingItem>(new RangeItemComparer());\r
-\r
- internal FoldingCollection()\r
- {\r
- this.collection.AutoRebuild = false;\r
- this.StatusChanged += (s, e) => { };\r
- }\r
-\r
- internal void UpdateData(Document doc,int startIndex,int insertLength,int removeLength)\r
- {\r
- if (this.collection.Count == 0)\r
- return;\r
- int delta = insertLength - removeLength;\r
- foreach (FoldingItem item in this.collection.Items)\r
- {\r
- int endIndex = startIndex + removeLength - 1;\r
- if (startIndex <= item.Start)\r
- {\r
- if ((endIndex >= item.Start && endIndex <= item.End) || endIndex > item.End)\r
- item.Range = new Range<int>(item.Start, item.Start); //ここで削除すると例外が発生する\r
- else\r
- item.Range = new Range<int>(item.Start + delta, item.End + delta);\r
- }\r
- else if (startIndex >= item.Start && startIndex <= item.End)\r
- {\r
- if (endIndex > item.End)\r
- item.Range = new Range<int>(item.Start, item.Start); //ここで削除すると例外が発生する\r
- else\r
- item.Range = new Range<int>(item.Start, item.End + delta);\r
- }\r
- }\r
- this.collection.Rebuild();\r
- }\r
-\r
- internal void CollectEmptyFolding(int startIndex,int endIndex)\r
- {\r
- foreach (FoldingItem foldingData in this.GetRange(startIndex, endIndex - startIndex + 1))\r
- if (foldingData.Start == foldingData.End)\r
- this.Remove(foldingData);\r
- }\r
-\r
- /// <summary>\r
- /// 状態が変わったことを表す\r
- /// </summary>\r
- public event EventHandler<FoldingItemStatusChangedEventArgs> StatusChanged;\r
-\r
- /// <summary>\r
- /// 折り畳みを追加する\r
- /// </summary>\r
- /// <param name="data">FoldingItemオブジェクト</param>\r
- public void Add(FoldingItem data)\r
- {\r
- foreach (FoldingItem item in this.collection.Items)\r
- {\r
- if (item.Start == data.Start && item.End == data.End)\r
- return;\r
- }\r
- this.collection.Add(data);\r
- }\r
-\r
- /// <summary>\r
- /// 折り畳みを追加する\r
- /// </summary>\r
- /// <param name="collection">FoldingItemのコレクション</param>\r
- public void AddRange(IEnumerable<FoldingItem> collection)\r
- {\r
- foreach (FoldingItem data in collection)\r
- {\r
- this.Add(data);\r
- }\r
- }\r
- \r
- /// <summary>\r
- /// 折り畳みを削除する\r
- /// </summary>\r
- /// <param name="data">FoldingItemオブジェクト</param>\r
- public void Remove(FoldingItem data)\r
- {\r
- this.collection.Remove(data);\r
- }\r
-\r
- /// <summary>\r
- /// 指定した範囲の折り畳みを取得する\r
- /// </summary>\r
- /// <param name="index">開始インデックス</param>\r
- /// <param name="length">長さ</param>\r
- /// <returns>FoldingItemイテレーター</returns>\r
- public IEnumerable<FoldingItem> GetRange(int index, int length)\r
- {\r
- if (this.collection.Count == 0)\r
- yield break;\r
-\r
- this.collection.Rebuild();\r
-\r
- List<FoldingItem> items = this.collection.Query(new Range<int>(index, index + length - 1));\r
- foreach (FoldingItem item in items)\r
- yield return item;\r
- }\r
-\r
- /// <summary>\r
- /// 指定した範囲に最も近い折り畳みを取得する\r
- /// </summary>\r
- /// <param name="index">開始インデックス</param>\r
- /// <param name="length">長さ</param>\r
- /// <returns>FoldingItemオブジェクト</returns>\r
- public FoldingItem Get(int index, int length)\r
- {\r
- if (this.collection.Count == 0)\r
- return null;\r
- \r
- this.collection.Rebuild();\r
-\r
- List<FoldingItem> items = this.collection.Query(new Range<int>(index, index + length - 1));\r
-\r
- int minLength = Int32.MaxValue;\r
- FoldingItem minItem = null;\r
- foreach (FoldingItem item in items)\r
- if (index - item.Start < minLength)\r
- minItem = item;\r
- return minItem;\r
- }\r
-\r
- /// <summary>\r
- /// すべて削除する\r
- /// </summary>\r
- public void Clear()\r
- {\r
- this.collection.Clear();\r
- }\r
-\r
- /// <summary>\r
- /// 展開状態を一括で変更する\r
- /// </summary>\r
- /// <param name="items"></param>\r
- public void ApplyExpandStatus(IEnumerable<FoldingItem> items)\r
- {\r
- foreach(var item in items)\r
- {\r
- var target_items = from i in this where i.Start == item.Start && i.End == item.End select i;\r
- foreach (var target_item in target_items)\r
- target_item.Expand = item.Expand;\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// 展開する\r
- /// </summary>\r
- /// <param name="foldingData">foldingItemオブジェクト</param>\r
- /// <remarks>親ノードも含めてすべて展開されます</remarks>\r
- public void Expand(FoldingItem foldingData)\r
- {\r
- if (this.collection.Count == 0)\r
- return;\r
- this.collection.Rebuild();\r
- List<FoldingItem> items = this.collection.Query(foldingData.Range);\r
- foreach (FoldingItem item in items)\r
- item.Expand = true;\r
- this.StatusChanged(this, new FoldingItemStatusChangedEventArgs(foldingData));\r
- }\r
-\r
- /// <summary>\r
- /// 折りたたむ\r
- /// </summary>\r
- /// <param name="foldingData">foldingItemオブジェクト</param>\r
- /// <remarks>全ての子ノードは折りたたまれます</remarks>\r
- public void Collapse(FoldingItem foldingData)\r
- {\r
- if (foldingData == null)\r
- return;\r
- this.collection.Rebuild();\r
- List<FoldingItem> items = this.collection.Query(foldingData.Range);\r
- foldingData.Expand = false;\r
- foreach (FoldingItem item in items)\r
- if (item.Start > foldingData.Start && item.End <= foldingData.End)\r
- item.Expand = false;\r
- this.StatusChanged(this, new FoldingItemStatusChangedEventArgs(foldingData));\r
- }\r
-\r
- /// <summary>\r
- /// インデックスを含むノードが折りたたまれているかを判定する\r
- /// </summary>\r
- /// <param name="index">インデックス</param>\r
- /// <returns>折りたたまれていれば真を返す。そうでない場合・ノードが存在しない場合は偽を返す</returns>\r
- public bool IsHidden(int index)\r
- {\r
- this.collection.Rebuild();\r
- List<FoldingItem> items = this.collection.Query(index);\r
- if (items.Count == 0)\r
- return false;\r
- int hiddenCount = items.Count((item) =>{\r
- return !item.Expand && index > item.Start && index <= item.End;\r
- });\r
- return hiddenCount > 0;\r
- }\r
-\r
- /// <summary>\r
- /// 親ノードが隠されているかどうかを判定する\r
- /// </summary>\r
- /// <param name="foldingItem">判定したいノード</param>\r
- /// <returns>隠されていれば真を返す</returns>\r
- public bool IsParentHidden(FoldingItem foldingItem)\r
- {\r
- if (foldingItem == null)\r
- return false;\r
- this.collection.Rebuild();\r
- List<FoldingItem> items = this.collection.Query(foldingItem.Range);\r
- if (items.Count == 0)\r
- return false;\r
- int hiddenCount = items.Count((item) =>\r
- {\r
- //自分自身ノードか\r
- if (foldingItem.Range.Equals(item.Range))\r
- return false;\r
- //ノードが親かつ隠されているかどうか\r
- return !item.Expand && item.Start < foldingItem.Start && item.End > foldingItem.End;\r
- });\r
- return hiddenCount > 0;\r
- }\r
-\r
- /// <summary>\r
- /// 親を持っているか判定する\r
- /// </summary>\r
- /// <param name="foldingItem">判定したいノード</param>\r
- /// <returns>親を持っていれば真を返す</returns>\r
- public bool IsHasParent(FoldingItem foldingItem)\r
- {\r
- if (foldingItem == null)\r
- return false;\r
- this.collection.Rebuild();\r
- List<FoldingItem> items = this.collection.Query(foldingItem.Range);\r
- if (items.Count == 0 || items.Count == 1)\r
- return false;\r
- int parentItemCount = items.Count((item) => item.Start < foldingItem.Start && item.End > foldingItem.End);\r
- return parentItemCount > 0;\r
- }\r
-\r
- /// <summary>\r
- /// 指定した範囲に属する親ノードを取得する\r
- /// </summary>\r
- /// <param name="index">開始インデックス</param>\r
- /// <param name="length">長さ</param>\r
- /// <returns>FoldingItemオブジェクト</returns>\r
- /// <remarks>指定した範囲には属する中で隠された親ノードだけが取得される</remarks>\r
- public FoldingItem GetFarestHiddenFoldingData(int index, int length)\r
- {\r
- if (this.collection.Count == 0)\r
- return null;\r
- this.collection.Rebuild();\r
- List<FoldingItem> items = this.collection.Query(new Range<int>(index, index + length - 1));\r
-\r
- //もっとも範囲の広いアイテムが親を表す\r
- FoldingItem parentItem = null;\r
- int max = 0;\r
- foreach(FoldingItem item in items)\r
- {\r
- int item_length = item.End -item.Start + 1;\r
- if(item_length > max)\r
- {\r
- max = item_length;\r
- parentItem = item;\r
- }\r
- }\r
-\r
- return parentItem;\r
- }\r
-\r
- /// <summary>\r
- /// FlodingItemの列挙子を返す\r
- /// </summary>\r
- /// <returns></returns>\r
- public IEnumerator<FoldingItem> GetEnumerator()\r
- {\r
- foreach (var item in this.collection.Items)\r
- yield return item;\r
- }\r
-\r
- IEnumerator IEnumerable.GetEnumerator()\r
- {\r
- throw new NotImplementedException();\r
- }\r
- }\r
-}\r
+/*
+ * Copyright (C) 2013 FooProject
+ * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace FooEditEngine
+{
+ /// <summary>
+ /// 新しく作成されるフォールティングアイテムを表す
+ /// </summary>
+ public class FoldingItem : IRangeProvider<int>
+ {
+ /// <summary>
+ /// 開始インデックス
+ /// </summary>
+ public int Start
+ {
+ get
+ {
+ return this.Range.From;
+ }
+ }
+
+ /// <summary>
+ /// 終了インデックス
+ /// </summary>
+ public int End
+ {
+ get
+ {
+ return this.Range.To;
+ }
+ }
+
+ /// <summary>
+ /// 展開されているなら真。そうでないなら偽
+ /// </summary>
+ public bool Expand
+ {
+ get;
+ internal set;
+ }
+
+ /// <summary>
+ /// 内部で使用しているメンバーです。外部から参照しないでください
+ /// </summary>
+ public Range<int> Range
+ {
+ get;
+ set;
+ }
+
+ /// <summary>
+ /// コンストラクター
+ /// </summary>
+ /// <param name="start">開始インデックス</param>
+ /// <param name="end">終了インデックス</param>
+ /// <param name="expand">展開フラグ</param>
+ public FoldingItem(int start, int end,bool expand = true)
+ {
+ if (start >= end)
+ throw new ArgumentException("start < endである必要があります");
+ this.Range = new Range<int>(start, end);
+ this.Expand = expand;
+ }
+
+ internal bool IsFirstLine(LineToIndexTable layoutLines, int row)
+ {
+ int firstRow = layoutLines.GetLineNumberFromIndex(this.Start);
+ return row == firstRow;
+ }
+ }
+
+ sealed class RangeItemComparer : IComparer<FoldingItem>
+ {
+ public int Compare(FoldingItem x, FoldingItem y)
+ {
+ return x.Range.CompareTo(y.Range);
+ }
+ }
+
+ /// <summary>
+ /// イベントデーター
+ /// </summary>
+ public sealed class FoldingItemStatusChangedEventArgs : EventArgs
+ {
+ /// <summary>
+ /// 状態に変化があったアイテム
+ /// </summary>
+ public FoldingItem Item;
+ /// <summary>
+ /// コンストラクター
+ /// </summary>
+ /// <param name="item">FoldingItemオブジェクト</param>
+ public FoldingItemStatusChangedEventArgs(FoldingItem item)
+ {
+ this.Item = item;
+ }
+ }
+
+ /// <summary>
+ /// 折り畳み関係のコレクションを表す
+ /// </summary>
+ public sealed class FoldingCollection : IEnumerable<FoldingItem>
+ {
+ RangeTree<int, FoldingItem> collection = new RangeTree<int, FoldingItem>(new RangeItemComparer());
+
+ internal FoldingCollection()
+ {
+ this.collection.AutoRebuild = false;
+ this.StatusChanged += (s, e) => { };
+ }
+
+ internal void UpdateData(Document doc,int startIndex,int insertLength,int removeLength)
+ {
+ if (this.collection.Count == 0)
+ return;
+ int delta = insertLength - removeLength;
+ foreach (FoldingItem item in this.collection.Items)
+ {
+ int endIndex = startIndex + removeLength - 1;
+ if (startIndex <= item.Start)
+ {
+ if ((endIndex >= item.Start && endIndex <= item.End) || endIndex > item.End)
+ item.Range = new Range<int>(item.Start, item.Start); //ここで削除すると例外が発生する
+ else
+ item.Range = new Range<int>(item.Start + delta, item.End + delta);
+ }
+ else if (startIndex >= item.Start && startIndex <= item.End)
+ {
+ if (endIndex > item.End)
+ item.Range = new Range<int>(item.Start, item.Start); //ここで削除すると例外が発生する
+ else
+ item.Range = new Range<int>(item.Start, item.End + delta);
+ }
+ }
+ this.collection.Rebuild();
+ }
+
+ internal void CollectEmptyFolding(int startIndex,int endIndex)
+ {
+ foreach (FoldingItem foldingData in this.GetRange(startIndex, endIndex - startIndex + 1))
+ if (foldingData.Start == foldingData.End)
+ this.Remove(foldingData);
+ }
+
+ /// <summary>
+ /// 状態が変わったことを表す
+ /// </summary>
+ public event EventHandler<FoldingItemStatusChangedEventArgs> StatusChanged;
+
+ /// <summary>
+ /// 折り畳みを追加する
+ /// </summary>
+ /// <param name="data">FoldingItemオブジェクト</param>
+ public void Add(FoldingItem data)
+ {
+ foreach (FoldingItem item in this.collection.Items)
+ {
+ if (item.Start == data.Start && item.End == data.End)
+ return;
+ }
+ this.collection.Add(data);
+ }
+
+ /// <summary>
+ /// 折り畳みを追加する
+ /// </summary>
+ /// <param name="collection">FoldingItemのコレクション</param>
+ public void AddRange(IEnumerable<FoldingItem> collection)
+ {
+ foreach (FoldingItem data in collection)
+ {
+ this.Add(data);
+ }
+ }
+
+ /// <summary>
+ /// 折り畳みを削除する
+ /// </summary>
+ /// <param name="data">FoldingItemオブジェクト</param>
+ public void Remove(FoldingItem data)
+ {
+ this.collection.Remove(data);
+ }
+
+ /// <summary>
+ /// 指定した範囲の折り畳みを取得する
+ /// </summary>
+ /// <param name="index">開始インデックス</param>
+ /// <param name="length">長さ</param>
+ /// <returns>FoldingItemイテレーター</returns>
+ public IEnumerable<FoldingItem> GetRange(int index, int length)
+ {
+ if (this.collection.Count == 0)
+ yield break;
+
+ this.collection.Rebuild();
+
+ List<FoldingItem> items = this.collection.Query(new Range<int>(index, index + length - 1));
+ foreach (FoldingItem item in items)
+ yield return item;
+ }
+
+ /// <summary>
+ /// 指定した範囲に最も近い折り畳みを取得する
+ /// </summary>
+ /// <param name="index">開始インデックス</param>
+ /// <param name="length">長さ</param>
+ /// <returns>FoldingItemオブジェクト</returns>
+ public FoldingItem Get(int index, int length)
+ {
+ if (this.collection.Count == 0)
+ return null;
+
+ this.collection.Rebuild();
+
+ List<FoldingItem> items = this.collection.Query(new Range<int>(index, index + length - 1));
+
+ int minLength = Int32.MaxValue;
+ FoldingItem minItem = null;
+ foreach (FoldingItem item in items)
+ if (index - item.Start < minLength)
+ minItem = item;
+ return minItem;
+ }
+
+ /// <summary>
+ /// すべて削除する
+ /// </summary>
+ public void Clear()
+ {
+ this.collection.Clear();
+ }
+
+ /// <summary>
+ /// 展開状態を一括で変更する
+ /// </summary>
+ /// <param name="items"></param>
+ public void ApplyExpandStatus(IEnumerable<FoldingItem> items)
+ {
+ foreach(var item in items)
+ {
+ var target_items = from i in this where i.Start == item.Start && i.End == item.End select i;
+ foreach (var target_item in target_items)
+ target_item.Expand = item.Expand;
+ }
+ }
+
+ /// <summary>
+ /// 展開する
+ /// </summary>
+ /// <param name="foldingData">foldingItemオブジェクト</param>
+ /// <remarks>親ノードも含めてすべて展開されます</remarks>
+ public void Expand(FoldingItem foldingData)
+ {
+ if (this.collection.Count == 0)
+ return;
+ this.collection.Rebuild();
+ List<FoldingItem> items = this.collection.Query(foldingData.Range);
+ foreach (FoldingItem item in items)
+ item.Expand = true;
+ this.StatusChanged(this, new FoldingItemStatusChangedEventArgs(foldingData));
+ }
+
+ /// <summary>
+ /// 折りたたむ
+ /// </summary>
+ /// <param name="foldingData">foldingItemオブジェクト</param>
+ /// <remarks>全ての子ノードは折りたたまれます</remarks>
+ public void Collapse(FoldingItem foldingData)
+ {
+ if (foldingData == null)
+ return;
+ this.collection.Rebuild();
+ List<FoldingItem> items = this.collection.Query(foldingData.Range);
+ foldingData.Expand = false;
+ foreach (FoldingItem item in items)
+ if (item.Start > foldingData.Start && item.End <= foldingData.End)
+ item.Expand = false;
+ this.StatusChanged(this, new FoldingItemStatusChangedEventArgs(foldingData));
+ }
+
+ /// <summary>
+ /// インデックスを含むノードが折りたたまれているかを判定する
+ /// </summary>
+ /// <param name="index">インデックス</param>
+ /// <returns>折りたたまれていれば真を返す。そうでない場合・ノードが存在しない場合は偽を返す</returns>
+ public bool IsHidden(int index)
+ {
+ this.collection.Rebuild();
+ List<FoldingItem> items = this.collection.Query(index);
+ if (items.Count == 0)
+ return false;
+ int hiddenCount = items.Count((item) =>{
+ return !item.Expand && index > item.Start && index <= item.End;
+ });
+ return hiddenCount > 0;
+ }
+
+ /// <summary>
+ /// 親ノードが隠されているかどうかを判定する
+ /// </summary>
+ /// <param name="foldingItem">判定したいノード</param>
+ /// <returns>隠されていれば真を返す</returns>
+ public bool IsParentHidden(FoldingItem foldingItem)
+ {
+ if (foldingItem == null)
+ return false;
+ this.collection.Rebuild();
+ List<FoldingItem> items = this.collection.Query(foldingItem.Range);
+ if (items.Count == 0)
+ return false;
+ int hiddenCount = items.Count((item) =>
+ {
+ //自分自身ノードか
+ if (foldingItem.Range.Equals(item.Range))
+ return false;
+ //ノードが親かつ隠されているかどうか
+ return !item.Expand && item.Start < foldingItem.Start && item.End > foldingItem.End;
+ });
+ return hiddenCount > 0;
+ }
+
+ /// <summary>
+ /// 親を持っているか判定する
+ /// </summary>
+ /// <param name="foldingItem">判定したいノード</param>
+ /// <returns>親を持っていれば真を返す</returns>
+ public bool IsHasParent(FoldingItem foldingItem)
+ {
+ if (foldingItem == null)
+ return false;
+ this.collection.Rebuild();
+ List<FoldingItem> items = this.collection.Query(foldingItem.Range);
+ if (items.Count == 0 || items.Count == 1)
+ return false;
+ int parentItemCount = items.Count((item) => item.Start < foldingItem.Start && item.End > foldingItem.End);
+ return parentItemCount > 0;
+ }
+
+ /// <summary>
+ /// 指定した範囲に属する親ノードを取得する
+ /// </summary>
+ /// <param name="index">開始インデックス</param>
+ /// <param name="length">長さ</param>
+ /// <returns>FoldingItemオブジェクト</returns>
+ /// <remarks>指定した範囲には属する中で隠された親ノードだけが取得される</remarks>
+ public FoldingItem GetFarestHiddenFoldingData(int index, int length)
+ {
+ if (this.collection.Count == 0)
+ return null;
+ this.collection.Rebuild();
+ List<FoldingItem> items = this.collection.Query(new Range<int>(index, index + length - 1));
+
+ //もっとも範囲の広いアイテムが親を表す
+ FoldingItem parentItem = null;
+ int max = 0;
+ foreach(FoldingItem item in items)
+ {
+ int item_length = item.End -item.Start + 1;
+ if(item_length > max)
+ {
+ max = item_length;
+ parentItem = item;
+ }
+ }
+
+ return parentItem;
+ }
+
+ /// <summary>
+ /// FlodingItemの列挙子を返す
+ /// </summary>
+ /// <returns></returns>
+ public IEnumerator<FoldingItem> GetEnumerator()
+ {
+ foreach (var item in this.collection.Items)
+ yield return item;
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
-/*\r
- * Copyright (C) 2013 FooProject\r
- * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.\r
-\r
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of \r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\r
-\r
-You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.\r
- */\r
-using System;\r
-using System.Collections.Generic;\r
-\r
-namespace FooEditEngine\r
-{\r
- /// <summary>\r
- /// フォールティング作成の方法を表す\r
- /// </summary>\r
- public interface IFoldingStrategy\r
- {\r
- /// <summary>\r
- /// ドキュメントを解析する\r
- /// </summary>\r
- /// <param name="doc">ドキュメント</param>\r
- /// <param name="start">開始インデックス</param>\r
- /// <param name="end">終了インデックス</param>\r
- /// <returns>作成したフォールディングを表すイテレーター</returns>\r
- IEnumerable<FoldingItem> AnalyzeDocument(Document doc,int start,int end);\r
- }\r
-}\r
+/*
+ * Copyright (C) 2013 FooProject
+ * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+using System.Collections.Generic;
+
+namespace FooEditEngine
+{
+ /// <summary>
+ /// フォールティング作成の方法を表す
+ /// </summary>
+ public interface IFoldingStrategy
+ {
+ /// <summary>
+ /// ドキュメントを解析する
+ /// </summary>
+ /// <param name="doc">ドキュメント</param>
+ /// <param name="start">開始インデックス</param>
+ /// <param name="end">終了インデックス</param>
+ /// <returns>作成したフォールディングを表すイテレーター</returns>
+ IEnumerable<FoldingItem> AnalyzeDocument(Document doc,int start,int end);
+ }
+}
-/*\r
- * Copyright (C) 2013 FooProject\r
- * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.\r
-\r
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of \r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\r
-\r
-You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.\r
- */\r
-using System;\r
-\r
-namespace FooEditEngine\r
-{\r
- /// <summary>\r
- /// トークンのタイプを表す\r
- /// </summary>\r
- public enum TokenType\r
- {\r
- /// <summary>\r
- /// どのカテゴリーにも属さないトークンを表す\r
- /// </summary>\r
- None = 0,\r
- /// <summary>\r
- /// キーワード1として表示するトークンを表す\r
- /// </summary>\r
- Keyword1,\r
- /// <summary>\r
- /// キーワード2として表示するトークンを表す\r
- /// </summary>\r
- Keyword2,\r
- /// <summary>\r
- /// コメントとして表示するトークンを表す\r
- /// </summary>\r
- Comment,\r
- /// <summary>\r
- /// 文字リテラルとして表示するトークンを表す\r
- /// </summary>\r
- Literal,\r
- /// <summary>\r
- /// コントロールとして表示するトークンを表す\r
- /// </summary>\r
- Control,\r
- }\r
-\r
- /// <summary>\r
- /// イベントデータを表す\r
- /// </summary>\r
- public class TokenSpilitEventArgs\r
- {\r
- /// <summary>\r
- /// 単語長\r
- /// </summary>\r
- public int length;\r
- /// <summary>\r
- /// トークンのタイプ\r
- /// </summary>\r
- public TokenType type;\r
- /// <summary>\r
- /// トークンの切り出しをやめるなら真をセットし、そうでないなら偽をセットする(規定値は偽)\r
- /// </summary>\r
- public bool breaked;\r
- /// <summary>\r
- /// トークンがあるインデックス\r
- /// </summary>\r
- public int index;\r
-\r
- /// <summary>\r
- /// コンストラクター\r
- /// </summary>\r
- public TokenSpilitEventArgs()\r
- {\r
- }\r
-\r
- /// <summary>\r
- /// コンストラクター\r
- /// </summary>\r
- /// <param name="index">開始インデックス</param>\r
- /// <param name="length">長さ</param>\r
- /// <param name="type">トークンタイプ</param>\r
- public TokenSpilitEventArgs(int index,int length, TokenType type)\r
- {\r
- this.length = length;\r
- this.type = type;\r
- this.index = index;\r
- this.breaked = false;\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// トークンが切り出された時に呼ばれるイベント\r
- /// </summary>\r
- /// <param name="state">イベントデータ</param>\r
- /// <returns></returns>\r
- public delegate void TokenSpilitHandeler(TokenSpilitEventArgs state);\r
-\r
- /// <summary>\r
- /// シンタックスハイライトを行うためのインターフェイス\r
- /// </summary>\r
- public interface IHilighter\r
- {\r
- /// <summary>\r
- /// 初期状態に戻す\r
- /// </summary>\r
- void Reset();\r
-\r
- /// <summary>\r
- /// ハイライト処理を実行します\r
- /// </summary>\r
- /// <param name="text">対象となる文字列</param>\r
- /// <param name="length">文字列の長さ</param>\r
- /// <param name="action">トークンが切り出されたときに呼び出されるデリゲート</param>\r
- /// <returns>エンクロージャーレベル。開始エンクロージャーだけを検出した場合は1以上の値を返し、\r
- /// 終了エンクロージャーだけを検出した場合を-1以下の値を返すようにします。\r
- /// 何も検出しなかった場合、開始エンクロージャーと終了エンクロージャーが対になっている場合、\r
- /// エンクロージャー内で開始エンクロージャーを検出した場合は0を返します\r
- /// なお、開始エンクロージャーがすでに検出されている状態で検出したことを返した場合、その結果は無視されます\r
- /// </returns>\r
- /// <example>\r
- /// int DoHilight(string text,int length, TokenSpilitHandeler action)\r
- /// {\r
- /// if(length > 3 && text == "foo")\r
- /// action(new TokenSpilitEventArgs(0,3,TokenType.Keyword1);\r
- /// return 0;\r
- /// }\r
- /// </example>\r
- int DoHilight(string text,int length, TokenSpilitHandeler action);\r
- }\r
-}\r
+/*
+ * Copyright (C) 2013 FooProject
+ * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+
+namespace FooEditEngine
+{
+ /// <summary>
+ /// トークンのタイプを表す
+ /// </summary>
+ public enum TokenType
+ {
+ /// <summary>
+ /// どのカテゴリーにも属さないトークンを表す
+ /// </summary>
+ None = 0,
+ /// <summary>
+ /// キーワード1として表示するトークンを表す
+ /// </summary>
+ Keyword1,
+ /// <summary>
+ /// キーワード2として表示するトークンを表す
+ /// </summary>
+ Keyword2,
+ /// <summary>
+ /// コメントとして表示するトークンを表す
+ /// </summary>
+ Comment,
+ /// <summary>
+ /// 文字リテラルとして表示するトークンを表す
+ /// </summary>
+ Literal,
+ /// <summary>
+ /// コントロールとして表示するトークンを表す
+ /// </summary>
+ Control,
+ }
+
+ /// <summary>
+ /// イベントデータを表す
+ /// </summary>
+ public class TokenSpilitEventArgs
+ {
+ /// <summary>
+ /// 単語長
+ /// </summary>
+ public int length;
+ /// <summary>
+ /// トークンのタイプ
+ /// </summary>
+ public TokenType type;
+ /// <summary>
+ /// トークンの切り出しをやめるなら真をセットし、そうでないなら偽をセットする(規定値は偽)
+ /// </summary>
+ public bool breaked;
+ /// <summary>
+ /// トークンがあるインデックス
+ /// </summary>
+ public int index;
+
+ /// <summary>
+ /// コンストラクター
+ /// </summary>
+ public TokenSpilitEventArgs()
+ {
+ }
+
+ /// <summary>
+ /// コンストラクター
+ /// </summary>
+ /// <param name="index">開始インデックス</param>
+ /// <param name="length">長さ</param>
+ /// <param name="type">トークンタイプ</param>
+ public TokenSpilitEventArgs(int index,int length, TokenType type)
+ {
+ this.length = length;
+ this.type = type;
+ this.index = index;
+ this.breaked = false;
+ }
+ }
+
+ /// <summary>
+ /// トークンが切り出された時に呼ばれるイベント
+ /// </summary>
+ /// <param name="state">イベントデータ</param>
+ /// <returns></returns>
+ public delegate void TokenSpilitHandeler(TokenSpilitEventArgs state);
+
+ /// <summary>
+ /// シンタックスハイライトを行うためのインターフェイス
+ /// </summary>
+ public interface IHilighter
+ {
+ /// <summary>
+ /// 初期状態に戻す
+ /// </summary>
+ void Reset();
+
+ /// <summary>
+ /// ハイライト処理を実行します
+ /// </summary>
+ /// <param name="text">対象となる文字列</param>
+ /// <param name="length">文字列の長さ</param>
+ /// <param name="action">トークンが切り出されたときに呼び出されるデリゲート</param>
+ /// <returns>エンクロージャーレベル。開始エンクロージャーだけを検出した場合は1以上の値を返し、
+ /// 終了エンクロージャーだけを検出した場合を-1以下の値を返すようにします。
+ /// 何も検出しなかった場合、開始エンクロージャーと終了エンクロージャーが対になっている場合、
+ /// エンクロージャー内で開始エンクロージャーを検出した場合は0を返します
+ /// なお、開始エンクロージャーがすでに検出されている状態で検出したことを返した場合、その結果は無視されます
+ /// </returns>
+ /// <example>
+ /// int DoHilight(string text,int length, TokenSpilitHandeler action)
+ /// {
+ /// if(length > 3 && text == "foo")
+ /// action(new TokenSpilitEventArgs(0,3,TokenType.Keyword1);
+ /// return 0;
+ /// }
+ /// </example>
+ int DoHilight(string text,int length, TokenSpilitHandeler action);
+ }
+}
-/*\r
- * Copyright (C) 2013 FooProject\r
- * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.\r
-\r
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of \r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\r
-\r
-You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.\r
- */\r
-using System;\r
-using System.Collections.Generic;\r
-\r
-namespace FooEditEngine\r
-{\r
- struct Point\r
- {\r
- public double X;\r
- public double Y;\r
- public Point(double x, double y)\r
- {\r
- this.X = x;\r
- this.Y = y;\r
- }\r
- /// <summary>\r
- /// 比較演算子を実装します\r
- /// </summary>\r
- /// <param name="a">比較される方</param>\r
- /// <param name="b">比較対象</param>\r
- /// <returns>条件を満たすなら真</returns>\r
- public static bool operator ==(Point a, Point b)\r
- {\r
- return a.Equals(b);\r
- }\r
-\r
- /// <summary>\r
- /// 比較演算子を実装します\r
- /// </summary>\r
- /// <param name="a">比較される方</param>\r
- /// <param name="b">比較対象</param>\r
- /// <returns>条件を満たすなら真</returns>\r
- public static bool operator !=(Point a, Point b)\r
- {\r
- return !a.Equals(b);\r
- }\r
-\r
- /// <summary>\r
- /// 一致するかどうか\r
- /// </summary>\r
- /// <param name="o">比較対象</param>\r
- /// <returns>一致するなら真</returns>\r
- public override bool Equals(object o)\r
- {\r
- Point b = (Point)o;\r
- return this.X == b.X && this.Y == b.Y;\r
- }\r
-\r
- /// <summary>\r
- /// ハッシュを返す\r
- /// </summary>\r
- /// <returns>ハッシュを返す</returns>\r
- public override int GetHashCode()\r
- {\r
- int result = this.X.GetHashCode();\r
- result ^= this.Y.GetHashCode();\r
- return result;\r
- }\r
-\r
- public Point Scale(double scale)\r
- {\r
- this.X *= scale;\r
- this.Y *= scale;\r
- return this;\r
- }\r
-#if WINFORM\r
- public static implicit operator Point(System.Drawing.Point p)\r
- {\r
- return new Point(p.X, p.Y);\r
- }\r
- public static implicit operator System.Drawing.Point(Point p)\r
- {\r
- return new System.Drawing.Point((int)p.X, (int)p.Y);\r
- }\r
- public static implicit operator SharpDX.Vector2(Point p)\r
- {\r
- return new SharpDX.Vector2((float)p.X, (float)p.Y);\r
- }\r
-#endif\r
-#if WPF\r
- public static implicit operator Point(System.Windows.Point p)\r
- {\r
- return new Point(p.X, p.Y);\r
- }\r
- public static implicit operator System.Windows.Point(Point p)\r
- {\r
- return new System.Windows.Point(p.X, p.Y);\r
- }\r
- public static implicit operator SharpDX.Vector2(Point p)\r
- {\r
- return new SharpDX.Vector2((float)p.X, (float)p.Y);\r
- }\r
-#endif\r
-#if METRO\r
- public static implicit operator Point(Windows.Foundation.Point p)\r
- {\r
- return new Point(p.X, p.Y);\r
- }\r
- public static implicit operator Windows.Foundation.Point(Point p)\r
- {\r
- return new Windows.Foundation.Point(p.X, p.Y);\r
- }\r
- public static implicit operator SharpDX.Vector2(Point p)\r
- {\r
- return new SharpDX.Vector2((float)p.X, (float)p.Y);\r
- }\r
-#endif\r
- }\r
- struct Size\r
- {\r
- public double Width;\r
- public double Height;\r
- public Size(double width, double height)\r
- {\r
- this.Width = width;\r
- this.Height = height;\r
- }\r
-\r
- /// <summary>\r
- /// 比較演算子を実装します\r
- /// </summary>\r
- /// <param name="a">比較される方</param>\r
- /// <param name="b">比較対象</param>\r
- /// <returns>条件を満たすなら真</returns>\r
- public static bool operator ==(Size a, Size b)\r
- {\r
- return a.Equals(b);\r
- }\r
-\r
- /// <summary>\r
- /// 比較演算子を実装します\r
- /// </summary>\r
- /// <param name="a">比較される方</param>\r
- /// <param name="b">比較対象</param>\r
- /// <returns>条件を満たすなら真</returns>\r
- public static bool operator !=(Size a, Size b)\r
- {\r
- return !a.Equals(b);\r
- }\r
-\r
- /// <summary>\r
- /// 一致するかどうか\r
- /// </summary>\r
- /// <param name="o">比較対象</param>\r
- /// <returns>一致するなら真</returns>\r
- public override bool Equals(object o)\r
- {\r
- Size b = (Size)o;\r
- return this.Width == b.Width && this.Height == b.Height;\r
- }\r
-\r
- /// <summary>\r
- /// ハッシュを返す\r
- /// </summary>\r
- /// <returns>ハッシュを返す</returns>\r
- public override int GetHashCode()\r
- {\r
- int result = this.Height.GetHashCode();\r
- result ^= this.Width.GetHashCode();\r
- return result;\r
- }\r
-#if WINFORM\r
- public static implicit operator Size(System.Drawing.Size p)\r
- {\r
- return new Size(p.Width, p.Height);\r
- }\r
- public static implicit operator System.Drawing.Size(Size p)\r
- {\r
- return new System.Drawing.Size((int)p.Width, (int)p.Height);\r
- }\r
-#endif\r
-#if WPF\r
- public static implicit operator Size(System.Windows.Size p)\r
- {\r
- return new Size(p.Width, p.Height);\r
- }\r
- public static implicit operator System.Windows.Size(Size p)\r
- {\r
- return new System.Windows.Size(p.Width, p.Height);\r
- }\r
-#endif\r
-#if METRO\r
- public static implicit operator Size(Windows.Foundation.Size p)\r
- {\r
- return new Size(p.Width, p.Height);\r
- }\r
- public static implicit operator Windows.Foundation.Size(Size p)\r
- {\r
- return new Windows.Foundation.Size(p.Width, p.Height);\r
- }\r
-#endif\r
- }\r
- struct Rectangle\r
- {\r
- public Point Location;\r
- public Size Size;\r
- public Point TopLeft\r
- {\r
- get { return this.Location; }\r
- }\r
- public Point TopRight\r
- {\r
- get { return new Point(this.Right, this.Location.Y); }\r
- }\r
- public Point BottomLeft\r
- {\r
- get { return new Point(this.Location.X, this.Bottom); }\r
- }\r
- public Point BottomRight\r
- {\r
- get { return new Point(this.Right, this.Bottom); }\r
- }\r
- public double Right\r
- {\r
- get { return this.X + this.Width; }\r
- }\r
- public double Bottom\r
- {\r
- get { return this.Y + this.Height; }\r
- }\r
- public double Height\r
- {\r
- get { return this.Size.Height; }\r
- set { this.Size.Height = value; }\r
- }\r
- public double Width\r
- {\r
- get { return this.Size.Width; }\r
- set { this.Size.Width = value; }\r
- }\r
- public double X\r
- {\r
- get { return this.Location.X; }\r
- }\r
- public double Y\r
- {\r
- get { return this.Location.Y; }\r
- }\r
- public Rectangle(double x, double y, double width, double height)\r
- {\r
- this.Location = new Point(x, y);\r
- this.Size = new Size(width, height);\r
- }\r
- public Rectangle(Point leftTop, Point bottomRight)\r
- {\r
- this.Location = leftTop;\r
- this.Size = new Size(bottomRight.X - leftTop.X, bottomRight.Y - leftTop.Y);\r
- }\r
-\r
- /// <summary>\r
- /// どの領域も指さないことを表す\r
- /// </summary>\r
- public static Rectangle Empty = new Rectangle(0, 0, 0, 0);\r
-\r
- /// <summary>\r
- /// 任意の点が領域内にあるなら真を返す\r
- /// </summary>\r
- /// <param name="p"></param>\r
- /// <returns></returns>\r
- public bool IsHit(Point p)\r
- {\r
- if (p.X >= this.TopLeft.X &&\r
- p.Y >= this.TopLeft.Y &&\r
- p.X <= this.BottomRight.X &&\r
- p.Y <= this.BottomRight.Y)\r
- return true;\r
- return false;\r
- }\r
-\r
- /// <summary>\r
- /// 比較演算子を実装します\r
- /// </summary>\r
- /// <param name="a">比較される方</param>\r
- /// <param name="b">比較対象</param>\r
- /// <returns>条件を満たすなら真</returns>\r
- public static bool operator ==(Rectangle a, Rectangle b)\r
- {\r
- return a.Equals(b);\r
- }\r
-\r
- /// <summary>\r
- /// 比較演算子を実装します\r
- /// </summary>\r
- /// <param name="a">比較される方</param>\r
- /// <param name="b">比較対象</param>\r
- /// <returns>条件を満たすなら真</returns>\r
- public static bool operator !=(Rectangle a, Rectangle b)\r
- {\r
- return !a.Equals(b);\r
- }\r
-\r
- /// <summary>\r
- /// 一致するかどうか\r
- /// </summary>\r
- /// <param name="o">比較対象</param>\r
- /// <returns>一致するなら真</returns>\r
- public override bool Equals(object o)\r
- {\r
- Rectangle b = (Rectangle)o;\r
- return this.Location.Equals(b.Location) && this.Size.Equals(b.Size);\r
- }\r
-\r
- /// <summary>\r
- /// ハッシュを返す\r
- /// </summary>\r
- /// <returns>ハッシュを返す</returns>\r
- public override int GetHashCode()\r
- {\r
- int result = this.Location.GetHashCode();\r
- result ^= this.Size.GetHashCode();\r
- return result;\r
- }\r
-#if WINFORM\r
- public static implicit operator Rectangle(System.Drawing.Rectangle p)\r
- {\r
- return new Rectangle(p.X,p.Y,p.Width,p.Height);\r
- }\r
- public static implicit operator System.Drawing.Rectangle(Rectangle p)\r
- {\r
- return new System.Drawing.Rectangle((int)p.X, (int)p.Y, (int)p.Width, (int)p.Height);\r
- }\r
- public static implicit operator SharpDX.RectangleF(Rectangle p)\r
- {\r
- return new SharpDX.RectangleF((float)p.X, (float)p.Y, (float)p.Width, (float)p.Height);\r
- }\r
-#endif\r
-#if WPF\r
- public static implicit operator Rectangle(System.Windows.Rect p)\r
- {\r
- return new Rectangle(p.X,p.Y,p.Width,p.Height);\r
- }\r
- public static implicit operator System.Windows.Rect(Rectangle p)\r
- {\r
- return new System.Windows.Rect(p.X, p.Y, p.Width, p.Height);\r
- }\r
- public static implicit operator SharpDX.RectangleF(Rectangle p)\r
- {\r
- return new SharpDX.RectangleF((float)p.X, (float)p.Y, (float)p.Width, (float)p.Height);\r
- }\r
-#endif\r
-#if METRO\r
- public static implicit operator Rectangle(Windows.Foundation.Rect p)\r
- {\r
- return new Rectangle(p.X, p.Y, p.Width, p.Height);\r
- }\r
- public static implicit operator Windows.Foundation.Rect(Rectangle p)\r
- {\r
- return new Windows.Foundation.Rect(p.X, p.Y, p.Width, p.Height);\r
- }\r
- public static implicit operator SharpDX.RectangleF(Rectangle p)\r
- {\r
- return new SharpDX.RectangleF((float)p.X, (float)p.Y, (float)p.Width, (float)p.Height);\r
- }\r
-#endif\r
- }\r
- /// <summary>\r
- /// 色構造体\r
- /// </summary>\r
- public struct Color: IEqualityComparer<Color>\r
- {\r
- /// <summary>\r
- /// アルファ成分\r
- /// </summary>\r
- public byte A;\r
- /// <summary>\r
- /// 赤成分\r
- /// </summary>\r
- public byte R;\r
- /// <summary>\r
- /// 緑成分\r
- /// </summary>\r
- public byte G;\r
- /// <summary>\r
- /// 青成分\r
- /// </summary>\r
- public byte B;\r
-\r
- /// <summary>\r
- /// コンストラクター\r
- /// </summary>\r
- /// <param name="a">A成分</param>\r
- /// <param name="r">R成分</param>\r
- /// <param name="g">G成分</param>\r
- /// <param name="b">B成分</param>\r
- public Color(byte a = 255, byte r = 0, byte g = 0, byte b = 0)\r
- {\r
- this.A = a;\r
- this.R = r;\r
- this.B = b;\r
- this.G = g;\r
- }\r
-\r
- /// <summary>\r
- /// 等しいかどうかを調べます\r
- /// </summary>\r
- /// <param name="x">比較される方</param>\r
- /// <param name="y">比較する方</param>\r
- /// <returns>等しいなら真。そうでなければ偽</returns>\r
- public bool Equals(Color x, Color y)\r
- {\r
- return x.A == y.A && x.R == y.R && x.G == y.G && x.B == y.B;\r
- }\r
-\r
- /// <summary>\r
- /// ハッシュを得ます\r
- /// </summary>\r
- /// <param name="obj">Colorオブジェクト</param>\r
- /// <returns>ハッシュ</returns>\r
- public int GetHashCode(Color obj)\r
- {\r
- return this.A ^ this.R ^ this.B ^ this.G;\r
- }\r
-\r
- /// <summary>\r
- /// 一致するかどうか\r
- /// </summary>\r
- /// <param name="o">比較対象</param>\r
- /// <returns>一致するなら真</returns>\r
- public override bool Equals(object o)\r
- {\r
- Color b = (Color)o;\r
- return this.Equals(this,b);\r
- }\r
-\r
- /// <summary>\r
- /// ハッシュを返す\r
- /// </summary>\r
- /// <returns>ハッシュを返す</returns>\r
- public override int GetHashCode()\r
- {\r
- return this.GetHashCode(this);\r
- }\r
- }\r
- enum AlignDirection\r
- {\r
- Forward,\r
- Back,\r
- }\r
- enum ResourceType\r
- {\r
- Font,\r
- Brush,\r
- Antialias,\r
- InlineChar,\r
- }\r
- enum FillRectType\r
- {\r
- OverwriteCaret,\r
- InsertCaret,\r
- InsertPoint,\r
- LineMarker,\r
- UpdateArea,\r
- }\r
- enum StringColorType\r
- {\r
- Forground,\r
- LineNumber,\r
- }\r
- class ChangedRenderRsourceEventArgs : EventArgs\r
- {\r
- public ResourceType type;\r
- public ChangedRenderRsourceEventArgs(ResourceType type)\r
- {\r
- this.type = type;\r
- }\r
- }\r
- delegate void ChangedRenderResourceEventHandler(object sender, ChangedRenderRsourceEventArgs e);\r
- interface ITextRender\r
- {\r
- /// <summary>\r
- /// 右から左に表示するなら真\r
- /// </summary>\r
- bool RightToLeft { get; set; }\r
-\r
- /// <summary>\r
- /// ドキュメントを表示する領域\r
- /// </summary>\r
- Rectangle TextArea { get; set; }\r
-\r
- /// <summary>\r
- /// 行番号の幅\r
- /// </summary>\r
- double LineNemberWidth { get; }\r
-\r
- /// <summary>\r
- /// タブの文字数\r
- /// </summary>\r
- int TabWidthChar { get; set; }\r
-\r
- /// <summary>\r
- /// 1文字当たりの高さと幅\r
- /// </summary>\r
- Size emSize { get; }\r
-\r
- /// <summary>\r
- /// 保持しているリソースに変化があったことを通知する\r
- /// </summary>\r
- event ChangedRenderResourceEventHandler ChangedRenderResource;\r
-\r
- /// <summary>\r
- /// RightToLeftの値が変わったことを通知する\r
- /// </summary>\r
- event EventHandler ChangedRightToLeft;\r
-\r
- /// <summary>\r
- /// 文字列を表示する\r
- /// </summary>\r
- /// <param name="str">文字列</param>\r
- /// <param name="x">x座標</param>\r
- /// <param name="y">y座標</param>\r
- /// <param name="align">書式方向</param>\r
- /// <param name="layoutRect">レイアウト領域</param>\r
- void DrawString(string str, double x, double y, StringAlignment align, Size layoutRect,StringColorType colorType = StringColorType.Forground);\r
-\r
- /// <summary>\r
- /// 行を表示する\r
- /// </summary>\r
- /// <param name="lti">LineToIndexオブジェクト</param>\r
- /// <param name="row">行</param>\r
- /// <param name="x">行の左上を表すX座標</param>\r
- /// <param name="y">行の左上を表すY座標</param>\r
- /// <param name="SelectRanges">選択領域を保持しているコレクション。選択領域の開始位置は行の先頭を0とする相対位置としてください(位置が-1の場合表示されません)</param>\r
- void DrawOneLine(LineToIndexTable lti, int row, double x, double y, IEnumerable<Selection> SelectRanges);\r
-\r
- /// <summary>\r
- /// 行を折り返す\r
- /// </summary>\r
- /// <param name="doc">ドキュメント</param>\r
- /// <param name="layoutLineCollection">レイアウトライン</param>\r
- /// <param name="startIndex">開始インデックス</param>\r
- /// <param name="endIndex">終了インデックス</param>\r
- /// <param name="wrapwidth">折り返しの幅</param>\r
- /// <returns>行のリスト</returns>\r
- List<LineToIndexTableData> BreakLine(Document doc,LineToIndexTable layoutLineCollection, int startIndex, int endIndex, double wrapwidth);\r
-\r
- /// <summary>\r
- /// レイアウトを生成する\r
- /// </summary>\r
- /// <param name="str">文字列</param>\r
- /// <returns>ITextLayoutオブジェクト</returns>\r
- /// <param name="syntaxCollection">ハイライト関連の情報を保持しているコレクション</param>\r
- /// <param name="MarkerRanges">マーカーを保持しているコレクション。マーカーの開始位置は行の先頭を0とする相対位置としてください(位置が-1の場合表示しないこと)</param>\r
- ITextLayout CreateLaytout(string str, SyntaxInfo[] syntaxCollection, IEnumerable<Marker> MarkerRanges);\r
- }\r
- interface IEditorRender : ITextRender\r
- {\r
- /// <summary>\r
- /// フォールティングエリアの幅\r
- /// </summary>\r
- double FoldingWidth { get; }\r
-\r
- /// <summary>\r
- /// キャッシュされたビットマップを描写する\r
- /// </summary>\r
- /// <param name="rect">描く領域</param>\r
- void DrawCachedBitmap(Rectangle rect);\r
-\r
- /// <summary>\r
- /// 線を描く\r
- /// </summary>\r
- /// <param name="from">開始座標</param>\r
- /// <param name="to">修了座標</param>\r
- void DrawLine(Point from, Point to);\r
-\r
- /// <summary>\r
- /// 描写したものをキャッシュする\r
- /// </summary>\r
- void CacheContent();\r
-\r
- /// <summary>\r
- /// キャッシュが存在するなら真を返し、そうでないなら偽を返す\r
- /// </summary>\r
- bool IsVaildCache();\r
-\r
- /// <summary>\r
- /// 四角形を描く\r
- /// </summary>\r
- /// <param name="rect"></param>\r
- /// <param name="type"></param>\r
- void FillRectangle(Rectangle rect,FillRectType type);\r
-\r
- /// <summary>\r
- /// ツリーに使用するマークを描く\r
- /// </summary>\r
- /// <param name="expand">展開済みなら真</param>\r
- /// <param name="x">x座標</param>\r
- /// <param name="y">y座標</param>\r
- void DrawFoldingMark(bool expand, double x, double y);\r
-\r
- /// <summary>\r
- /// 背景を塗りつぶす\r
- /// </summary>\r
- /// <param name="rect">塗りつぶすべき領域</param>\r
- void FillBackground(Rectangle rect);\r
- }\r
-\r
- enum StringAlignment\r
- {\r
- Left,\r
- Center,\r
- Right,\r
- }\r
- interface IPrintableTextRender : ITextRender\r
- {\r
- /// <summary>\r
- /// ヘッダーの高さ\r
- /// </summary>\r
- float HeaderHeight { get; }\r
-\r
- /// <summary>\r
- /// フッターの高さ\r
- /// </summary>\r
- float FooterHeight { get; }\r
- }\r
-}\r
+/*
+ * Copyright (C) 2013 FooProject
+ * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+using System.Collections.Generic;
+
+namespace FooEditEngine
+{
+ struct Point
+ {
+ public double X;
+ public double Y;
+ public Point(double x, double y)
+ {
+ this.X = x;
+ this.Y = y;
+ }
+ /// <summary>
+ /// 比較演算子を実装します
+ /// </summary>
+ /// <param name="a">比較される方</param>
+ /// <param name="b">比較対象</param>
+ /// <returns>条件を満たすなら真</returns>
+ public static bool operator ==(Point a, Point b)
+ {
+ return a.Equals(b);
+ }
+
+ /// <summary>
+ /// 比較演算子を実装します
+ /// </summary>
+ /// <param name="a">比較される方</param>
+ /// <param name="b">比較対象</param>
+ /// <returns>条件を満たすなら真</returns>
+ public static bool operator !=(Point a, Point b)
+ {
+ return !a.Equals(b);
+ }
+
+ /// <summary>
+ /// 一致するかどうか
+ /// </summary>
+ /// <param name="o">比較対象</param>
+ /// <returns>一致するなら真</returns>
+ public override bool Equals(object o)
+ {
+ Point b = (Point)o;
+ return this.X == b.X && this.Y == b.Y;
+ }
+
+ /// <summary>
+ /// ハッシュを返す
+ /// </summary>
+ /// <returns>ハッシュを返す</returns>
+ public override int GetHashCode()
+ {
+ int result = this.X.GetHashCode();
+ result ^= this.Y.GetHashCode();
+ return result;
+ }
+
+ public Point Scale(double scale)
+ {
+ this.X *= scale;
+ this.Y *= scale;
+ return this;
+ }
+#if WINFORM
+ public static implicit operator Point(System.Drawing.Point p)
+ {
+ return new Point(p.X, p.Y);
+ }
+ public static implicit operator System.Drawing.Point(Point p)
+ {
+ return new System.Drawing.Point((int)p.X, (int)p.Y);
+ }
+ public static implicit operator SharpDX.Vector2(Point p)
+ {
+ return new SharpDX.Vector2((float)p.X, (float)p.Y);
+ }
+#endif
+#if WPF
+ public static implicit operator Point(System.Windows.Point p)
+ {
+ return new Point(p.X, p.Y);
+ }
+ public static implicit operator System.Windows.Point(Point p)
+ {
+ return new System.Windows.Point(p.X, p.Y);
+ }
+ public static implicit operator SharpDX.Vector2(Point p)
+ {
+ return new SharpDX.Vector2((float)p.X, (float)p.Y);
+ }
+#endif
+#if METRO
+ public static implicit operator Point(Windows.Foundation.Point p)
+ {
+ return new Point(p.X, p.Y);
+ }
+ public static implicit operator Windows.Foundation.Point(Point p)
+ {
+ return new Windows.Foundation.Point(p.X, p.Y);
+ }
+ public static implicit operator SharpDX.Vector2(Point p)
+ {
+ return new SharpDX.Vector2((float)p.X, (float)p.Y);
+ }
+#endif
+ }
+ struct Size
+ {
+ public double Width;
+ public double Height;
+ public Size(double width, double height)
+ {
+ this.Width = width;
+ this.Height = height;
+ }
+
+ /// <summary>
+ /// 比較演算子を実装します
+ /// </summary>
+ /// <param name="a">比較される方</param>
+ /// <param name="b">比較対象</param>
+ /// <returns>条件を満たすなら真</returns>
+ public static bool operator ==(Size a, Size b)
+ {
+ return a.Equals(b);
+ }
+
+ /// <summary>
+ /// 比較演算子を実装します
+ /// </summary>
+ /// <param name="a">比較される方</param>
+ /// <param name="b">比較対象</param>
+ /// <returns>条件を満たすなら真</returns>
+ public static bool operator !=(Size a, Size b)
+ {
+ return !a.Equals(b);
+ }
+
+ /// <summary>
+ /// 一致するかどうか
+ /// </summary>
+ /// <param name="o">比較対象</param>
+ /// <returns>一致するなら真</returns>
+ public override bool Equals(object o)
+ {
+ Size b = (Size)o;
+ return this.Width == b.Width && this.Height == b.Height;
+ }
+
+ /// <summary>
+ /// ハッシュを返す
+ /// </summary>
+ /// <returns>ハッシュを返す</returns>
+ public override int GetHashCode()
+ {
+ int result = this.Height.GetHashCode();
+ result ^= this.Width.GetHashCode();
+ return result;
+ }
+#if WINFORM
+ public static implicit operator Size(System.Drawing.Size p)
+ {
+ return new Size(p.Width, p.Height);
+ }
+ public static implicit operator System.Drawing.Size(Size p)
+ {
+ return new System.Drawing.Size((int)p.Width, (int)p.Height);
+ }
+#endif
+#if WPF
+ public static implicit operator Size(System.Windows.Size p)
+ {
+ return new Size(p.Width, p.Height);
+ }
+ public static implicit operator System.Windows.Size(Size p)
+ {
+ return new System.Windows.Size(p.Width, p.Height);
+ }
+#endif
+#if METRO
+ public static implicit operator Size(Windows.Foundation.Size p)
+ {
+ return new Size(p.Width, p.Height);
+ }
+ public static implicit operator Windows.Foundation.Size(Size p)
+ {
+ return new Windows.Foundation.Size(p.Width, p.Height);
+ }
+#endif
+ }
+ struct Rectangle
+ {
+ public Point Location;
+ public Size Size;
+ public Point TopLeft
+ {
+ get { return this.Location; }
+ }
+ public Point TopRight
+ {
+ get { return new Point(this.Right, this.Location.Y); }
+ }
+ public Point BottomLeft
+ {
+ get { return new Point(this.Location.X, this.Bottom); }
+ }
+ public Point BottomRight
+ {
+ get { return new Point(this.Right, this.Bottom); }
+ }
+ public double Right
+ {
+ get { return this.X + this.Width; }
+ }
+ public double Bottom
+ {
+ get { return this.Y + this.Height; }
+ }
+ public double Height
+ {
+ get { return this.Size.Height; }
+ set { this.Size.Height = value; }
+ }
+ public double Width
+ {
+ get { return this.Size.Width; }
+ set { this.Size.Width = value; }
+ }
+ public double X
+ {
+ get { return this.Location.X; }
+ }
+ public double Y
+ {
+ get { return this.Location.Y; }
+ }
+ public Rectangle(double x, double y, double width, double height)
+ {
+ this.Location = new Point(x, y);
+ this.Size = new Size(width, height);
+ }
+ public Rectangle(Point leftTop, Point bottomRight)
+ {
+ this.Location = leftTop;
+ this.Size = new Size(bottomRight.X - leftTop.X, bottomRight.Y - leftTop.Y);
+ }
+
+ /// <summary>
+ /// どの領域も指さないことを表す
+ /// </summary>
+ public static Rectangle Empty = new Rectangle(0, 0, 0, 0);
+
+ /// <summary>
+ /// 任意の点が領域内にあるなら真を返す
+ /// </summary>
+ /// <param name="p"></param>
+ /// <returns></returns>
+ public bool IsHit(Point p)
+ {
+ if (p.X >= this.TopLeft.X &&
+ p.Y >= this.TopLeft.Y &&
+ p.X <= this.BottomRight.X &&
+ p.Y <= this.BottomRight.Y)
+ return true;
+ return false;
+ }
+
+ /// <summary>
+ /// 比較演算子を実装します
+ /// </summary>
+ /// <param name="a">比較される方</param>
+ /// <param name="b">比較対象</param>
+ /// <returns>条件を満たすなら真</returns>
+ public static bool operator ==(Rectangle a, Rectangle b)
+ {
+ return a.Equals(b);
+ }
+
+ /// <summary>
+ /// 比較演算子を実装します
+ /// </summary>
+ /// <param name="a">比較される方</param>
+ /// <param name="b">比較対象</param>
+ /// <returns>条件を満たすなら真</returns>
+ public static bool operator !=(Rectangle a, Rectangle b)
+ {
+ return !a.Equals(b);
+ }
+
+ /// <summary>
+ /// 一致するかどうか
+ /// </summary>
+ /// <param name="o">比較対象</param>
+ /// <returns>一致するなら真</returns>
+ public override bool Equals(object o)
+ {
+ Rectangle b = (Rectangle)o;
+ return this.Location.Equals(b.Location) && this.Size.Equals(b.Size);
+ }
+
+ /// <summary>
+ /// ハッシュを返す
+ /// </summary>
+ /// <returns>ハッシュを返す</returns>
+ public override int GetHashCode()
+ {
+ int result = this.Location.GetHashCode();
+ result ^= this.Size.GetHashCode();
+ return result;
+ }
+#if WINFORM
+ public static implicit operator Rectangle(System.Drawing.Rectangle p)
+ {
+ return new Rectangle(p.X,p.Y,p.Width,p.Height);
+ }
+ public static implicit operator System.Drawing.Rectangle(Rectangle p)
+ {
+ return new System.Drawing.Rectangle((int)p.X, (int)p.Y, (int)p.Width, (int)p.Height);
+ }
+ public static implicit operator SharpDX.RectangleF(Rectangle p)
+ {
+ return new SharpDX.RectangleF((float)p.X, (float)p.Y, (float)p.Width, (float)p.Height);
+ }
+#endif
+#if WPF
+ public static implicit operator Rectangle(System.Windows.Rect p)
+ {
+ return new Rectangle(p.X,p.Y,p.Width,p.Height);
+ }
+ public static implicit operator System.Windows.Rect(Rectangle p)
+ {
+ return new System.Windows.Rect(p.X, p.Y, p.Width, p.Height);
+ }
+ public static implicit operator SharpDX.RectangleF(Rectangle p)
+ {
+ return new SharpDX.RectangleF((float)p.X, (float)p.Y, (float)p.Width, (float)p.Height);
+ }
+#endif
+#if METRO
+ public static implicit operator Rectangle(Windows.Foundation.Rect p)
+ {
+ return new Rectangle(p.X, p.Y, p.Width, p.Height);
+ }
+ public static implicit operator Windows.Foundation.Rect(Rectangle p)
+ {
+ return new Windows.Foundation.Rect(p.X, p.Y, p.Width, p.Height);
+ }
+ public static implicit operator SharpDX.RectangleF(Rectangle p)
+ {
+ return new SharpDX.RectangleF((float)p.X, (float)p.Y, (float)p.Width, (float)p.Height);
+ }
+#endif
+ }
+ /// <summary>
+ /// 色構造体
+ /// </summary>
+ public struct Color: IEqualityComparer<Color>
+ {
+ /// <summary>
+ /// アルファ成分
+ /// </summary>
+ public byte A;
+ /// <summary>
+ /// 赤成分
+ /// </summary>
+ public byte R;
+ /// <summary>
+ /// 緑成分
+ /// </summary>
+ public byte G;
+ /// <summary>
+ /// 青成分
+ /// </summary>
+ public byte B;
+
+ /// <summary>
+ /// コンストラクター
+ /// </summary>
+ /// <param name="a">A成分</param>
+ /// <param name="r">R成分</param>
+ /// <param name="g">G成分</param>
+ /// <param name="b">B成分</param>
+ public Color(byte a = 255, byte r = 0, byte g = 0, byte b = 0)
+ {
+ this.A = a;
+ this.R = r;
+ this.B = b;
+ this.G = g;
+ }
+
+ /// <summary>
+ /// 等しいかどうかを調べます
+ /// </summary>
+ /// <param name="x">比較される方</param>
+ /// <param name="y">比較する方</param>
+ /// <returns>等しいなら真。そうでなければ偽</returns>
+ public bool Equals(Color x, Color y)
+ {
+ return x.A == y.A && x.R == y.R && x.G == y.G && x.B == y.B;
+ }
+
+ /// <summary>
+ /// ハッシュを得ます
+ /// </summary>
+ /// <param name="obj">Colorオブジェクト</param>
+ /// <returns>ハッシュ</returns>
+ public int GetHashCode(Color obj)
+ {
+ return this.A ^ this.R ^ this.B ^ this.G;
+ }
+
+ /// <summary>
+ /// 一致するかどうか
+ /// </summary>
+ /// <param name="o">比較対象</param>
+ /// <returns>一致するなら真</returns>
+ public override bool Equals(object o)
+ {
+ Color b = (Color)o;
+ return this.Equals(this,b);
+ }
+
+ /// <summary>
+ /// ハッシュを返す
+ /// </summary>
+ /// <returns>ハッシュを返す</returns>
+ public override int GetHashCode()
+ {
+ return this.GetHashCode(this);
+ }
+ }
+ enum AlignDirection
+ {
+ Forward,
+ Back,
+ }
+ enum ResourceType
+ {
+ Font,
+ Brush,
+ Antialias,
+ InlineChar,
+ }
+ enum FillRectType
+ {
+ OverwriteCaret,
+ InsertCaret,
+ InsertPoint,
+ LineMarker,
+ UpdateArea,
+ }
+ enum StringColorType
+ {
+ Forground,
+ LineNumber,
+ }
+ class ChangedRenderRsourceEventArgs : EventArgs
+ {
+ public ResourceType type;
+ public ChangedRenderRsourceEventArgs(ResourceType type)
+ {
+ this.type = type;
+ }
+ }
+ delegate void ChangedRenderResourceEventHandler(object sender, ChangedRenderRsourceEventArgs e);
+ interface ITextRender
+ {
+ /// <summary>
+ /// 右から左に表示するなら真
+ /// </summary>
+ bool RightToLeft { get; set; }
+
+ /// <summary>
+ /// ドキュメントを表示する領域
+ /// </summary>
+ Rectangle TextArea { get; set; }
+
+ /// <summary>
+ /// 行番号の幅
+ /// </summary>
+ double LineNemberWidth { get; }
+
+ /// <summary>
+ /// タブの文字数
+ /// </summary>
+ int TabWidthChar { get; set; }
+
+ /// <summary>
+ /// 1文字当たりの高さと幅
+ /// </summary>
+ Size emSize { get; }
+
+ /// <summary>
+ /// 保持しているリソースに変化があったことを通知する
+ /// </summary>
+ event ChangedRenderResourceEventHandler ChangedRenderResource;
+
+ /// <summary>
+ /// RightToLeftの値が変わったことを通知する
+ /// </summary>
+ event EventHandler ChangedRightToLeft;
+
+ /// <summary>
+ /// 文字列を表示する
+ /// </summary>
+ /// <param name="str">文字列</param>
+ /// <param name="x">x座標</param>
+ /// <param name="y">y座標</param>
+ /// <param name="align">書式方向</param>
+ /// <param name="layoutRect">レイアウト領域</param>
+ void DrawString(string str, double x, double y, StringAlignment align, Size layoutRect,StringColorType colorType = StringColorType.Forground);
+
+ /// <summary>
+ /// 行を表示する
+ /// </summary>
+ /// <param name="lti">LineToIndexオブジェクト</param>
+ /// <param name="row">行</param>
+ /// <param name="x">行の左上を表すX座標</param>
+ /// <param name="y">行の左上を表すY座標</param>
+ /// <param name="SelectRanges">選択領域を保持しているコレクション。選択領域の開始位置は行の先頭を0とする相対位置としてください(位置が-1の場合表示されません)</param>
+ void DrawOneLine(LineToIndexTable lti, int row, double x, double y, IEnumerable<Selection> SelectRanges);
+
+ /// <summary>
+ /// 行を折り返す
+ /// </summary>
+ /// <param name="doc">ドキュメント</param>
+ /// <param name="layoutLineCollection">レイアウトライン</param>
+ /// <param name="startIndex">開始インデックス</param>
+ /// <param name="endIndex">終了インデックス</param>
+ /// <param name="wrapwidth">折り返しの幅</param>
+ /// <returns>行のリスト</returns>
+ List<LineToIndexTableData> BreakLine(Document doc,LineToIndexTable layoutLineCollection, int startIndex, int endIndex, double wrapwidth);
+
+ /// <summary>
+ /// レイアウトを生成する
+ /// </summary>
+ /// <param name="str">文字列</param>
+ /// <returns>ITextLayoutオブジェクト</returns>
+ /// <param name="syntaxCollection">ハイライト関連の情報を保持しているコレクション</param>
+ /// <param name="MarkerRanges">マーカーを保持しているコレクション。マーカーの開始位置は行の先頭を0とする相対位置としてください(位置が-1の場合表示しないこと)</param>
+ ITextLayout CreateLaytout(string str, SyntaxInfo[] syntaxCollection, IEnumerable<Marker> MarkerRanges);
+ }
+ interface IEditorRender : ITextRender
+ {
+ /// <summary>
+ /// フォールティングエリアの幅
+ /// </summary>
+ double FoldingWidth { get; }
+
+ /// <summary>
+ /// キャッシュされたビットマップを描写する
+ /// </summary>
+ /// <param name="rect">描く領域</param>
+ void DrawCachedBitmap(Rectangle rect);
+
+ /// <summary>
+ /// 線を描く
+ /// </summary>
+ /// <param name="from">開始座標</param>
+ /// <param name="to">修了座標</param>
+ void DrawLine(Point from, Point to);
+
+ /// <summary>
+ /// 描写したものをキャッシュする
+ /// </summary>
+ void CacheContent();
+
+ /// <summary>
+ /// キャッシュが存在するなら真を返し、そうでないなら偽を返す
+ /// </summary>
+ bool IsVaildCache();
+
+ /// <summary>
+ /// 四角形を描く
+ /// </summary>
+ /// <param name="rect"></param>
+ /// <param name="type"></param>
+ void FillRectangle(Rectangle rect,FillRectType type);
+
+ /// <summary>
+ /// ツリーに使用するマークを描く
+ /// </summary>
+ /// <param name="expand">展開済みなら真</param>
+ /// <param name="x">x座標</param>
+ /// <param name="y">y座標</param>
+ void DrawFoldingMark(bool expand, double x, double y);
+
+ /// <summary>
+ /// 背景を塗りつぶす
+ /// </summary>
+ /// <param name="rect">塗りつぶすべき領域</param>
+ void FillBackground(Rectangle rect);
+ }
+
+ enum StringAlignment
+ {
+ Left,
+ Center,
+ Right,
+ }
+ interface IPrintableTextRender : ITextRender
+ {
+ /// <summary>
+ /// ヘッダーの高さ
+ /// </summary>
+ float HeaderHeight { get; }
+
+ /// <summary>
+ /// フッターの高さ
+ /// </summary>
+ float FooterHeight { get; }
+ }
+}
-/*\r
- * Copyright (C) 2013 FooProject\r
- * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.\r
-\r
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of \r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\r
-\r
-You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.\r
- */\r
-using System;\r
-using System.Text.RegularExpressions;\r
-using System.Threading;\r
-using System.Linq;\r
-using System.Collections.Generic;\r
-using System.Diagnostics;\r
-using Slusser.Collections.Generic;\r
-\r
-namespace FooEditEngine\r
-{\r
- internal interface ITextLayout : IDisposable\r
- {\r
- /// <summary>\r
- /// 文字列の幅\r
- /// </summary>\r
- double Width\r
- {\r
- get;\r
- }\r
-\r
- /// <summary>\r
- /// 文字列の高さ\r
- /// </summary>\r
- double Height\r
- {\r
- get;\r
- }\r
-\r
- /// <summary>\r
- /// Disposeされているなら真を返す\r
- /// </summary>\r
- bool Disposed\r
- {\r
- get;\r
- }\r
-\r
- /// <summary>\r
- /// 破棄すべきなら真。そうでなければ偽\r
- /// </summary>\r
- bool Invaild\r
- {\r
- get;\r
- }\r
-\r
- /// <summary>\r
- /// 桁方向の座標に対応するインデックスを得る\r
- /// </summary>\r
- /// <param name="colpos">桁方向の座標</param>\r
- /// <returns>インデックス</returns>\r
- /// <remarks>行番号の幅は考慮されてないのでView以外のクラスは呼び出さないでください</remarks>\r
- int GetIndexFromColPostion(double colpos);\r
-\r
- /// <summary>\r
- /// インデックスに対応する文字の幅を得る\r
- /// </summary>\r
- /// <param name="index">インデックス</param>\r
- /// <returns>文字の幅</returns>\r
- double GetWidthFromIndex(int index);\r
-\r
- /// <summary>\r
- /// インデックスに対応する桁方向の座標を得る\r
- /// </summary>\r
- /// <param name="index">インデックス</param>\r
- /// <returns>桁方向の座標</returns>\r
- /// <remarks>行頭にEOFが含まれている場合、0が返ります</remarks>\r
- double GetColPostionFromIndex(int index);\r
-\r
- /// <summary>\r
- /// 適切な位置にインデックスを調整する\r
- /// </summary>\r
- /// <param name="index">インデックス</param>\r
- /// <param name="flow">真の場合は隣接するクラスターを指すように調整し、\r
- /// そうでない場合は対応するクラスターの先頭を指すように調整します</param>\r
- /// <returns>調整後のインデックス</returns>\r
- int AlignIndexToNearestCluster(int index, AlignDirection flow);\r
- }\r
-\r
- internal class SpilitStringEventArgs : EventArgs\r
- {\r
- public Document buffer;\r
- public int index;\r
- public int length;\r
- public int row;\r
- public SpilitStringEventArgs(Document buf, int index, int length,int row)\r
- {\r
- this.buffer = buf;\r
- this.index = index;\r
- this.length = length;\r
- this.row = row;\r
- }\r
- }\r
-\r
- internal struct SyntaxInfo\r
- {\r
- public TokenType type;\r
- public int index;\r
- public int length;\r
- public SyntaxInfo(int index, int length, TokenType type)\r
- {\r
- this.type = type;\r
- this.index = index;\r
- this.length = length;\r
- }\r
- }\r
-\r
- internal enum EncloserType\r
- {\r
- None,\r
- Begin,\r
- Now,\r
- End,\r
- }\r
-\r
- internal class LineToIndexTableData : IDisposable\r
- {\r
- /// <summary>\r
- /// 行の先頭。正しい行の先頭位置を取得するにはGetLineHeadIndex()を使用してください\r
- /// </summary>\r
- public int Index;\r
- /// <summary>\r
- /// 行の長さ\r
- /// </summary>\r
- public int Length;\r
- /// <summary>\r
- /// 改行マークかEOFなら真を返す\r
- /// </summary>\r
- public bool LineEnd;\r
- public SyntaxInfo[] Syntax;\r
- public EncloserType EncloserType;\r
- internal ITextLayout Layout;\r
- public bool Dirty = false;\r
-\r
- /// <summary>\r
- /// コンストラクター。LineToIndexTable以外のクラスで呼び出さないでください\r
- /// </summary>\r
- public LineToIndexTableData()\r
- {\r
- }\r
-\r
- /// <summary>\r
- /// コンストラクター。LineToIndexTable以外のクラスで呼び出さないでください\r
- /// </summary>\r
- public LineToIndexTableData(int index, int length, bool lineend,bool dirty, SyntaxInfo[] syntax)\r
- {\r
- this.Index = index;\r
- this.Length = length;\r
- this.LineEnd = lineend;\r
- this.Syntax = syntax;\r
- this.EncloserType = EncloserType.None;\r
- this.Dirty = dirty;\r
- }\r
-\r
- public void Dispose()\r
- {\r
- if(this.Layout != null)\r
- this.Layout.Dispose();\r
- }\r
- }\r
-\r
- internal delegate IList<LineToIndexTableData> SpilitStringEventHandler(object sender, SpilitStringEventArgs e);\r
-\r
- internal sealed class CreateLayoutEventArgs\r
- {\r
- /// <summary>\r
- /// 開始インデックス\r
- /// </summary>\r
- public int Index\r
- {\r
- get;\r
- private set;\r
- }\r
- /// <summary>\r
- /// 長さ\r
- /// </summary>\r
- public int Length\r
- {\r
- get;\r
- private set;\r
- }\r
- /// <summary>\r
- /// 文字列\r
- /// </summary>\r
- public string Content\r
- {\r
- get;\r
- private set;\r
- }\r
- public CreateLayoutEventArgs(int index, int length,string content)\r
- {\r
- this.Index = index;\r
- this.Length = length;\r
- this.Content = content;\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// 行番号とインデックスを相互変換するためのクラス\r
- /// </summary>\r
- public sealed class LineToIndexTable : IEnumerable<string>\r
- {\r
- const int MaxEntries = 100;\r
- Queue<ITextLayout> CacheEntries = new Queue<ITextLayout>();\r
- GapBuffer<LineToIndexTableData> Lines = new GapBuffer<LineToIndexTableData>();\r
- Document Document;\r
- long lastUpdateTicks = DateTime.Now.Ticks;\r
- const long AllowCallTicks = 1000 * 10000; //see.DateTime.Ticks プロパティ\r
- bool _IsSync;\r
- ITextRender render;\r
- int stepRow = -1,stepLength = 0;\r
- const int STEP_ROW_IS_NONE = -1;\r
-\r
- internal LineToIndexTable(Document buf)\r
- {\r
- this.Document = buf;\r
- this.Document.Markers.Updated += Markers_Updated;\r
- this.FoldingCollection = new FoldingCollection();\r
- this._IsSync = true;\r
-#if DEBUG && !NETFX_CORE\r
- if (!Debugger.IsAttached)\r
- {\r
- Guid guid = Guid.NewGuid();\r
- string path = string.Format("{0}\\footextbox_lti_debug_{1}.log", System.IO.Path.GetTempPath(), guid);\r
- Debug.Listeners.Add(new TextWriterTraceListener(path));\r
- Debug.AutoFlush = true;\r
- }\r
-#endif\r
- }\r
-\r
- void Markers_Updated(object sender, EventArgs e)\r
- {\r
- this.ClearLayoutCache();\r
- }\r
-\r
- /// <summary>\r
- /// ITextRenderインターフェイスのインスタンス。必ずセットすること\r
- /// </summary>\r
- internal ITextRender Render\r
- {\r
- get { return this.render; }\r
- set\r
- {\r
- this.render = value;\r
- }\r
- }\r
-\r
- internal SpilitStringEventHandler SpilitString;\r
-\r
- /// <summary>\r
- /// 行数を返す\r
- /// </summary>\r
- public int Count\r
- {\r
- get { return this.Lines.Count; }\r
- }\r
-\r
- /// <summary>\r
- /// 折り畳み関係の情報を収めたコレクション\r
- /// </summary>\r
- public FoldingCollection FoldingCollection\r
- {\r
- get;\r
- private set;\r
- }\r
-\r
- /// <summary>\r
- /// シンタックスハイライター\r
- /// </summary>\r
- internal IHilighter Hilighter { get; set; }\r
-\r
- internal IFoldingStrategy FoldingStrategy { get; set; }\r
-\r
- /// <summary>\r
- /// 保持しているレイアウトキャッシュをクリアーする\r
- /// </summary>\r
- public void ClearLayoutCache()\r
- {\r
- foreach (ITextLayout data in this.CacheEntries)\r
- {\r
- data.Dispose();\r
- }\r
- this.CacheEntries.Clear();\r
- }\r
-\r
- /// <summary>\r
- /// 行番号に対応する文字列を返します\r
- /// </summary>\r
- /// <param name="n"></param>\r
- /// <returns></returns>\r
- public string this[int n]\r
- {\r
- get\r
- {\r
- LineToIndexTableData data = this.Lines[n];\r
- string str = this.Document.ToString(this.GetLineHeadIndex(n), data.Length);\r
-\r
- return str;\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// 更新フラグを更新しないなら真\r
- /// </summary>\r
- public bool IsFrozneDirtyFlag\r
- {\r
- get;\r
- set;\r
- }\r
-\r
- int GetLineHeadIndex(int row)\r
- {\r
- if (this.Lines.Count == 0)\r
- return 0;\r
- if (this.stepRow != STEP_ROW_IS_NONE && row > this.stepRow)\r
- return this.Lines[row].Index + this.stepLength;\r
- else\r
- return this.Lines[row].Index;\r
- }\r
-\r
- internal LineToIndexTableData CreateLineToIndexTableData(int index, int length, bool lineend, SyntaxInfo[] syntax)\r
- {\r
- LineToIndexTableData result = new LineToIndexTableData(index, length, lineend,this.IsFrozneDirtyFlag == false, syntax);\r
- return result;\r
- }\r
-\r
- internal void UpdateLineAsReplace(int row,int removedLength, int insertedLength)\r
- {\r
- int deltaLength = insertedLength - removedLength;\r
-\r
- this.Lines[row] = new LineToIndexTableData(this.GetLineHeadIndex(row), this.GetLengthFromLineNumber(row) + deltaLength, true, true, null);\r
-\r
- //行テーブルを更新する\r
- this.UpdateLineHeadIndex(deltaLength, row, 1);\r
-\r
- this.FoldingCollection.UpdateData(this.Document, this.GetLineHeadIndex(row), insertedLength, removedLength);\r
-\r
- this._IsSync = false;\r
-\r
- this.lastUpdateTicks = DateTime.Now.Ticks;\r
- }\r
-\r
- internal void UpdateAsReplace(int index, int removedLength, int insertedLength)\r
- {\r
-#if DEBUG\r
- Debug.WriteLine("Replaced Index:{0} RemoveLength:{1} InsertLength:{2}", index, removedLength, insertedLength);\r
-#endif\r
- int startRow, endRow;\r
- GetRemoveRange(index, removedLength, out startRow, out endRow);\r
-\r
- int deltaLength = insertedLength - removedLength;\r
-\r
- var result = GetAnalyzeLength(startRow, endRow, index, removedLength, insertedLength);\r
- int HeadIndex = result.Item1;\r
- int analyzeLength = result.Item2;\r
-\r
- //挿入範囲内のドキュメントから行を生成する\r
- SpilitStringEventArgs e = new SpilitStringEventArgs(this.Document, HeadIndex, analyzeLength, startRow);\r
- IList<LineToIndexTableData> newLines = SpilitString(this, e);\r
-\r
- //消すべき行が複数ある場合は消すが、そうでない場合は最適化のため長さを変えるだけにとどめておく\r
- int removeCount = endRow - startRow + 1;\r
- if (removeCount == 1 && newLines.Count == 1)\r
- {\r
- this.Lines[startRow] = newLines.First();\r
- }\r
- else\r
- {\r
- this.RemoveLine(startRow, removeCount);\r
-\r
- //行を挿入する\r
- this.InsertLine(startRow, newLines, removeCount, deltaLength);\r
- }\r
-\r
- //行テーブルを更新する\r
- this.UpdateLineHeadIndex(deltaLength, startRow, newLines.Count);\r
-\r
- this.AddDummyLine();\r
-\r
- this.FoldingCollection.UpdateData(this.Document, index, insertedLength, removedLength); \r
-\r
- this._IsSync = false;\r
-\r
- this.lastUpdateTicks = DateTime.Now.Ticks;\r
- }\r
-\r
- void GetRemoveRange(int index,int length,out int startRow,out int endRow)\r
- {\r
- startRow = this.GetLineNumberFromIndex(index);\r
- while (startRow > 0 && this.Lines[startRow - 1].LineEnd == false)\r
- startRow--;\r
-\r
- endRow = this.GetLineNumberFromIndex(index + length);\r
- while (endRow < this.Lines.Count && this.Lines[endRow].LineEnd == false)\r
- endRow++;\r
- if (endRow >= this.Lines.Count)\r
- endRow = this.Lines.Count - 1;\r
- }\r
-\r
- Tuple<int,int> GetAnalyzeLength(int startRow,int endRow,int updateStartIndex,int removedLength,int insertedLength)\r
- {\r
- int HeadIndex = this.GetIndexFromLineNumber(startRow);\r
- int LastIndex = this.GetIndexFromLineNumber(endRow) + this.GetLengthFromLineNumber(endRow) - 1;\r
-\r
- //SpilitStringの対象となる範囲を求める\r
- int fisrtPartLength = updateStartIndex - HeadIndex;\r
- int secondPartLength = LastIndex - (updateStartIndex + removedLength - 1);\r
- int analyzeLength = fisrtPartLength + secondPartLength + insertedLength;\r
- Debug.Assert(analyzeLength <= this.Document.Length - 1 - HeadIndex + 1);\r
-\r
- return new Tuple<int, int>(HeadIndex, analyzeLength);\r
- }\r
-\r
- void RemoveLine(int startRow, int removeCount)\r
- {\r
- for (int i = startRow; i < startRow + removeCount; i++)\r
- this.Lines[i].Dispose();\r
-\r
- this.Lines.RemoveRange(startRow, removeCount);\r
- }\r
-\r
- void InsertLine(int startRow, IList<LineToIndexTableData> collection,int removeCount, int deltaLength)\r
- {\r
- int newCount = collection.Count;\r
- if (this.stepRow > startRow && newCount > 0 && newCount != removeCount)\r
- {\r
- //stepRowは1か2のうち、大きな方になる\r
- // 1.stepRow - (削除された行数 - 挿入された行数)\r
- // 2.行の挿入箇所\r
- //行が削除や置換された場合、1の処理をしないと正しいIndexが求められない\r
- this.stepRow = Math.Max(this.stepRow - (removeCount - newCount), startRow);\r
-#if DEBUG\r
- if (this.stepRow < 0 || this.stepRow > this.Lines.Count + newCount)\r
- {\r
- Debug.WriteLine("step row < 0 or step row >= lines.count");\r
- Debugger.Break();\r
- }\r
-#endif\r
- }\r
-\r
- //startRowが挿入した行の開始位置なのであらかじめ引いておく\r
- for (int i = 1; i < collection.Count; i++)\r
- {\r
- if (this.stepRow != STEP_ROW_IS_NONE && startRow + i > this.stepRow)\r
- collection[i].Index -= deltaLength + this.stepLength;\r
- else\r
- collection[i].Index -= deltaLength;\r
- }\r
-\r
- this.Lines.InsertRange(startRow, collection);\r
- }\r
-\r
- void AddDummyLine()\r
- {\r
- LineToIndexTableData dummyLine = null;\r
- if (this.Lines.Count == 0)\r
- {\r
- dummyLine = new LineToIndexTableData();\r
- this.Lines.Add(dummyLine);\r
- return;\r
- }\r
-\r
- int lastLineRow = this.Lines.Count > 0 ? this.Lines.Count - 1 : 0;\r
- int lastLineHeadIndex = this.GetIndexFromLineNumber(lastLineRow);\r
- int lastLineLength = this.GetLengthFromLineNumber(lastLineRow);\r
-\r
- if (lastLineLength != 0 && this.Document[Document.Length - 1] == Document.NewLine)\r
- {\r
- int realIndex = lastLineHeadIndex + lastLineLength;\r
- if (lastLineRow >= this.stepRow)\r
- realIndex -= this.stepLength;\r
- dummyLine = new LineToIndexTableData(realIndex, 0, true,false, null);\r
- this.Lines.Add(dummyLine);\r
- }\r
- }\r
-\r
- void UpdateLineHeadIndex(int deltaLength,int startRow,int insertedLineCount)\r
- {\r
- if (this.Lines.Count == 0)\r
- {\r
- this.stepRow = STEP_ROW_IS_NONE;\r
- this.stepLength = 0;\r
- return;\r
- }\r
-\r
- if (this.stepRow == STEP_ROW_IS_NONE)\r
- {\r
- this.stepRow = startRow;\r
- this.stepLength = deltaLength;\r
- return;\r
- }\r
-\r
-\r
- if (startRow < this.stepRow)\r
- {\r
- //ドキュメントの後半部分をごっそり削除した場合、this.stepRow >= this.Lines.Countになる可能性がある\r
- if (this.stepRow >= this.Lines.Count)\r
- this.stepRow = this.Lines.Count - 1;\r
- for (int i = this.stepRow; i > startRow; i--)\r
- this.Lines[i].Index -= this.stepLength;\r
- }\r
- else if (startRow > this.stepRow)\r
- {\r
- for (int i = this.stepRow + 1; i < startRow; i++)\r
- this.Lines[i].Index += this.stepLength;\r
- }\r
-\r
- this.stepRow = startRow;\r
- this.stepLength += deltaLength;\r
-\r
- this.ValidateLines();\r
- }\r
-\r
- void ValidateLines()\r
- {\r
-#if DEBUG\r
- int nextIndex = 0;\r
- for (int i = 0; i < this.Lines.Count; i++)\r
- {\r
- int lineHeadIndex = this.GetLineHeadIndex(i);\r
- if (lineHeadIndex != nextIndex)\r
- {\r
- Debug.WriteLine("Invaild Line");\r
- System.Diagnostics.Debugger.Break();\r
- }\r
- nextIndex = lineHeadIndex + this.Lines[i].Length;\r
- }\r
-#endif\r
- }\r
-\r
- /// <summary>\r
- /// 行番号をインデックスに変換します\r
- /// </summary>\r
- /// <param name="row">行番号</param>\r
- /// <returns>0から始まるインデックスを返す</returns>\r
- public int GetIndexFromLineNumber(int row)\r
- {\r
- if (row < 0 || row > this.Lines.Count)\r
- throw new ArgumentOutOfRangeException();\r
- return this.GetLineHeadIndex(row);\r
- }\r
-\r
- /// <summary>\r
- /// 行の長さを得ます\r
- /// </summary>\r
- /// <param name="row">行番号</param>\r
- /// <returns>行の文字長を返します</returns>\r
- public int GetLengthFromLineNumber(int row)\r
- {\r
- if (row < 0 || row > this.Lines.Count)\r
- throw new ArgumentOutOfRangeException();\r
- return this.Lines[row].Length;\r
- }\r
-\r
- /// <summary>\r
- /// 更新フラグを取得します\r
- /// </summary>\r
- /// <param name="row">行番号</param>\r
- /// <returns>更新されていれば真。そうでなければ偽</returns>\r
- public bool GetDirtyFlag(int row)\r
- {\r
- if (row < 0 || row > this.Lines.Count)\r
- throw new ArgumentOutOfRangeException();\r
- return this.Lines[row].Dirty;\r
- }\r
-\r
- internal ITextLayout GetLayout(int row)\r
- {\r
- if (this.Lines[row].Layout != null && this.Lines[row].Layout.Invaild)\r
- {\r
- this.Lines[row].Layout.Dispose();\r
- this.Lines[row].Layout = null;\r
- }\r
- if (this.Lines[row].Layout == null || this.Lines[row].Layout.Disposed)\r
- this.Lines[row].Layout = this.CreateLayout(row);\r
- return this.Lines[row].Layout;\r
- }\r
-\r
- internal event EventHandler<CreateLayoutEventArgs> CreateingLayout;\r
-\r
- ITextLayout CreateLayout(int row)\r
- {\r
- ITextLayout layout;\r
- LineToIndexTableData lineData = this.Lines[row];\r
- if (lineData.Length == 0)\r
- {\r
- layout = this.render.CreateLaytout("", null, null);\r
- }\r
- else\r
- {\r
- int lineHeadIndex = this.GetLineHeadIndex(row);\r
-\r
- string content = this.Document.ToString(lineHeadIndex, lineData.Length);\r
-\r
- if (this.CreateingLayout != null)\r
- this.CreateingLayout(this, new CreateLayoutEventArgs(lineHeadIndex, lineData.Length,content));\r
- \r
- var markerRange = from id in this.Document.Markers.IDs\r
- from s in this.Document.Markers.Get(id,lineHeadIndex,lineData.Length)\r
- let n = Util.ConvertAbsIndexToRelIndex(s, lineHeadIndex, lineData.Length)\r
- select n;\r
- layout = this.render.CreateLaytout(content, lineData.Syntax, markerRange);\r
- }\r
-\r
- if (this.CacheEntries.Count > MaxEntries)\r
- {\r
- ITextLayout oldItem = this.CacheEntries.Dequeue();\r
- oldItem.Dispose();\r
- }\r
- this.CacheEntries.Enqueue(layout);\r
-\r
- return layout;\r
- }\r
-\r
- int lastLineNumber;\r
- /// <summary>\r
- /// インデックスを行番号に変換します\r
- /// </summary>\r
- /// <param name="index">インデックス</param>\r
- /// <returns>行番号を返します</returns>\r
- public int GetLineNumberFromIndex(int index)\r
- {\r
- if (index < 0)\r
- throw new ArgumentOutOfRangeException("indexに負の値を設定することはできません");\r
-\r
- if (index == 0 && this.Lines.Count > 0)\r
- return 0;\r
-\r
- LineToIndexTableData line;\r
- int lineHeadIndex;\r
-\r
- if (lastLineNumber < this.Lines.Count - 1)\r
- {\r
- line = this.Lines[lastLineNumber];\r
- lineHeadIndex = this.GetLineHeadIndex(lastLineNumber);\r
- if (index >= lineHeadIndex && index < lineHeadIndex + line.Length)\r
- return lastLineNumber;\r
- }\r
-\r
- int left = 0, right = this.Lines.Count - 1, mid;\r
- while (left <= right)\r
- {\r
- mid = (left + right) / 2;\r
- line = this.Lines[mid];\r
- lineHeadIndex = this.GetLineHeadIndex(mid);\r
- if (index >= lineHeadIndex && index < lineHeadIndex + line.Length)\r
- {\r
- lastLineNumber = mid;\r
- return mid;\r
- }\r
- if (index < lineHeadIndex)\r
- {\r
- right = mid - 1;\r
- }\r
- else\r
- {\r
- left = mid + 1;\r
- }\r
- }\r
-\r
- int lastRow = this.Lines.Count - 1;\r
- line = this.Lines[lastRow];\r
- lineHeadIndex = this.GetLineHeadIndex(lastRow);\r
- if (index >= lineHeadIndex && index <= lineHeadIndex + line.Length) //最終行長+1までキャレットが移動する可能性があるので\r
- {\r
- lastLineNumber = this.Lines.Count - 1;\r
- return lastLineNumber;\r
- }\r
-\r
- throw new ArgumentOutOfRangeException("該当する行が見つかりませんでした");\r
- }\r
-\r
- /// <summary>\r
- /// インデックスからテキストポイントに変換します\r
- /// </summary>\r
- /// <param name="index">インデックス</param>\r
- /// <returns>TextPoint構造体を返します</returns>\r
- public TextPoint GetTextPointFromIndex(int index)\r
- {\r
- TextPoint tp = new TextPoint();\r
- tp.row = GetLineNumberFromIndex(index);\r
- tp.col = index - this.GetLineHeadIndex(tp.row);\r
- Debug.Assert(tp.row < this.Lines.Count && tp.col <= this.Lines[tp.row].Length);\r
- return tp;\r
- }\r
-\r
- /// <summary>\r
- /// テキストポイントからインデックスに変換します\r
- /// </summary>\r
- /// <param name="tp">TextPoint構造体</param>\r
- /// <returns>インデックスを返します</returns>\r
- public int GetIndexFromTextPoint(TextPoint tp)\r
- {\r
- if (tp == TextPoint.Null)\r
- throw new ArgumentNullException("TextPoint.Null以外の値でなければなりません");\r
- if(tp.row < 0 || tp.row > this.Lines.Count)\r
- throw new ArgumentOutOfRangeException("tp.rowが設定できる範囲を超えています");\r
- if (tp.col < 0 || tp.col > this.Lines[tp.row].Length)\r
- throw new ArgumentOutOfRangeException("tp.colが設定できる範囲を超えています");\r
- return this.GetLineHeadIndex(tp.row) + tp.col;\r
- }\r
-\r
- /// <summary>\r
- /// フォールディングを再生成します\r
- /// </summary>\r
- /// <param name="force">ドキュメントが更新されていなくても再生成する</param>\r
- /// <returns>生成された場合は真を返す</returns>\r
- /// <remarks>デフォルトではドキュメントが更新されている時にだけ再生成されます</remarks>\r
- public bool GenerateFolding(bool force = false)\r
- {\r
- if (this.Document.Length == 0 || this.Document.IsLocked)\r
- return false;\r
- long nowTick = DateTime.Now.Ticks;\r
- bool sync = force || !this._IsSync;\r
- if (sync || Math.Abs(nowTick - this.lastUpdateTicks) >= AllowCallTicks)\r
- {\r
- this.GenerateFolding(0, this.Document.Length - 1);\r
- this.lastUpdateTicks = nowTick;\r
- return true;\r
- }\r
- return false;\r
- }\r
-\r
- void GenerateFolding(int start, int end)\r
- {\r
- if (start > end)\r
- throw new ArgumentException("start <= endである必要があります");\r
- if (this.FoldingStrategy != null)\r
- {\r
- //再生成するとすべて展開状態になってしまうので、閉じてるやつだけを保存しておく\r
- FoldingItem[] closed_items = this.FoldingCollection.Where((e)=> { return !e.Expand; }).ToArray();\r
-\r
- this.FoldingCollection.Clear();\r
-\r
- var items = this.FoldingStrategy.AnalyzeDocument(this.Document, start, end)\r
- .Where((item) =>\r
- {\r
- int startRow = this.GetLineNumberFromIndex(item.Start);\r
- int endRow = this.GetLineNumberFromIndex(item.End);\r
- return startRow != endRow;\r
- })\r
- .Select((item) => item);\r
- this.FoldingCollection.AddRange(items);\r
-\r
- this.FoldingCollection.ApplyExpandStatus(closed_items);\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// フォールディングをすべて削除します\r
- /// </summary>\r
- public void ClearFolding()\r
- {\r
- this.FoldingCollection.Clear();\r
- this._IsSync = false;\r
- }\r
-\r
- /// <summary>\r
- /// すべての行に対しシンタックスハイライトを行います\r
- /// </summary>\r
- public bool HilightAll(bool force = false)\r
- {\r
- if (this.Hilighter == null || this.Document.IsLocked)\r
- return false;\r
-\r
- long nowTick = DateTime.Now.Ticks;\r
- bool sync = force || !this._IsSync;\r
- if (sync || Math.Abs(nowTick - this.lastUpdateTicks) >= AllowCallTicks)\r
- {\r
- for (int i = 0; i < this.Lines.Count; i++)\r
- this.HilightLine(i);\r
-\r
- this.Hilighter.Reset();\r
- this.ClearLayoutCache();\r
-\r
- this.lastUpdateTicks = nowTick;\r
-\r
- return true;\r
- }\r
- return false;\r
- }\r
-\r
- /// <summary>\r
- /// ハイライト関連の情報をすべて削除します\r
- /// </summary>\r
- public void ClearHilight()\r
- {\r
- foreach (LineToIndexTableData line in this.Lines)\r
- line.Syntax = null;\r
- this.ClearLayoutCache();\r
- }\r
-\r
- /// <summary>\r
- /// すべて削除します\r
- /// </summary>\r
- internal void Clear()\r
- {\r
- this.ClearLayoutCache();\r
- this.FoldingCollection.Clear();\r
- this.Lines.Clear();\r
- LineToIndexTableData dummy = new LineToIndexTableData();\r
- this.Lines.Add(dummy);\r
- this.stepRow = STEP_ROW_IS_NONE;\r
- this.stepLength = 0;\r
- Debug.WriteLine("Clear");\r
- }\r
-\r
- private void HilightLine(int row)\r
- {\r
- //シンタックスハイライトを行う\r
- List<SyntaxInfo> syntax = new List<SyntaxInfo>();\r
- string str = this[row];\r
- int level = this.Hilighter.DoHilight(str, str.Length, (s) =>\r
- {\r
- if (s.type == TokenType.None || s.type == TokenType.Control)\r
- return;\r
- if (str[s.index + s.length - 1] == Document.NewLine)\r
- s.length--;\r
- syntax.Add(new SyntaxInfo(s.index, s.length, s.type));\r
- });\r
-\r
- LineToIndexTableData lineData = this.Lines[row];\r
- lineData.Syntax = syntax.ToArray();\r
-\r
- }\r
-\r
- #region IEnumerable<string> メンバー\r
-\r
- /// <summary>\r
- /// コレクションを反復処理するためのIEnumeratorを返す\r
- /// </summary>\r
- /// <returns>IEnumeratorオブジェクト</returns>\r
- public IEnumerator<string> GetEnumerator()\r
- {\r
- for (int i = 0; i < this.Lines.Count; i++)\r
- yield return this[i];\r
- }\r
-\r
- #endregion\r
-\r
- #region IEnumerable メンバー\r
-\r
- System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()\r
- {\r
- for (int i = 0; i < this.Lines.Count; i++)\r
- yield return this[i];\r
- }\r
-\r
- #endregion\r
- }\r
-\r
-}\r
+/*
+ * Copyright (C) 2013 FooProject
+ * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+using System.Text.RegularExpressions;
+using System.Threading;
+using System.Linq;
+using System.Collections.Generic;
+using System.Diagnostics;
+using Slusser.Collections.Generic;
+
+namespace FooEditEngine
+{
+ internal interface ITextLayout : IDisposable
+ {
+ /// <summary>
+ /// 文字列の幅
+ /// </summary>
+ double Width
+ {
+ get;
+ }
+
+ /// <summary>
+ /// 文字列の高さ
+ /// </summary>
+ double Height
+ {
+ get;
+ }
+
+ /// <summary>
+ /// Disposeされているなら真を返す
+ /// </summary>
+ bool Disposed
+ {
+ get;
+ }
+
+ /// <summary>
+ /// 破棄すべきなら真。そうでなければ偽
+ /// </summary>
+ bool Invaild
+ {
+ get;
+ }
+
+ /// <summary>
+ /// 桁方向の座標に対応するインデックスを得る
+ /// </summary>
+ /// <param name="colpos">桁方向の座標</param>
+ /// <returns>インデックス</returns>
+ /// <remarks>行番号の幅は考慮されてないのでView以外のクラスは呼び出さないでください</remarks>
+ int GetIndexFromColPostion(double colpos);
+
+ /// <summary>
+ /// インデックスに対応する文字の幅を得る
+ /// </summary>
+ /// <param name="index">インデックス</param>
+ /// <returns>文字の幅</returns>
+ double GetWidthFromIndex(int index);
+
+ /// <summary>
+ /// インデックスに対応する桁方向の座標を得る
+ /// </summary>
+ /// <param name="index">インデックス</param>
+ /// <returns>桁方向の座標</returns>
+ /// <remarks>行頭にEOFが含まれている場合、0が返ります</remarks>
+ double GetColPostionFromIndex(int index);
+
+ /// <summary>
+ /// 適切な位置にインデックスを調整する
+ /// </summary>
+ /// <param name="index">インデックス</param>
+ /// <param name="flow">真の場合は隣接するクラスターを指すように調整し、
+ /// そうでない場合は対応するクラスターの先頭を指すように調整します</param>
+ /// <returns>調整後のインデックス</returns>
+ int AlignIndexToNearestCluster(int index, AlignDirection flow);
+ }
+
+ internal class SpilitStringEventArgs : EventArgs
+ {
+ public Document buffer;
+ public int index;
+ public int length;
+ public int row;
+ public SpilitStringEventArgs(Document buf, int index, int length,int row)
+ {
+ this.buffer = buf;
+ this.index = index;
+ this.length = length;
+ this.row = row;
+ }
+ }
+
+ internal struct SyntaxInfo
+ {
+ public TokenType type;
+ public int index;
+ public int length;
+ public SyntaxInfo(int index, int length, TokenType type)
+ {
+ this.type = type;
+ this.index = index;
+ this.length = length;
+ }
+ }
+
+ internal enum EncloserType
+ {
+ None,
+ Begin,
+ Now,
+ End,
+ }
+
+ internal class LineToIndexTableData : IDisposable
+ {
+ /// <summary>
+ /// 行の先頭。正しい行の先頭位置を取得するにはGetLineHeadIndex()を使用してください
+ /// </summary>
+ public int Index;
+ /// <summary>
+ /// 行の長さ
+ /// </summary>
+ public int Length;
+ /// <summary>
+ /// 改行マークかEOFなら真を返す
+ /// </summary>
+ public bool LineEnd;
+ public SyntaxInfo[] Syntax;
+ public EncloserType EncloserType;
+ internal ITextLayout Layout;
+ public bool Dirty = false;
+
+ /// <summary>
+ /// コンストラクター。LineToIndexTable以外のクラスで呼び出さないでください
+ /// </summary>
+ public LineToIndexTableData()
+ {
+ }
+
+ /// <summary>
+ /// コンストラクター。LineToIndexTable以外のクラスで呼び出さないでください
+ /// </summary>
+ public LineToIndexTableData(int index, int length, bool lineend,bool dirty, SyntaxInfo[] syntax)
+ {
+ this.Index = index;
+ this.Length = length;
+ this.LineEnd = lineend;
+ this.Syntax = syntax;
+ this.EncloserType = EncloserType.None;
+ this.Dirty = dirty;
+ }
+
+ public void Dispose()
+ {
+ if(this.Layout != null)
+ this.Layout.Dispose();
+ }
+ }
+
+ internal delegate IList<LineToIndexTableData> SpilitStringEventHandler(object sender, SpilitStringEventArgs e);
+
+ internal sealed class CreateLayoutEventArgs
+ {
+ /// <summary>
+ /// 開始インデックス
+ /// </summary>
+ public int Index
+ {
+ get;
+ private set;
+ }
+ /// <summary>
+ /// 長さ
+ /// </summary>
+ public int Length
+ {
+ get;
+ private set;
+ }
+ /// <summary>
+ /// 文字列
+ /// </summary>
+ public string Content
+ {
+ get;
+ private set;
+ }
+ public CreateLayoutEventArgs(int index, int length,string content)
+ {
+ this.Index = index;
+ this.Length = length;
+ this.Content = content;
+ }
+ }
+
+ /// <summary>
+ /// 行番号とインデックスを相互変換するためのクラス
+ /// </summary>
+ public sealed class LineToIndexTable : IEnumerable<string>
+ {
+ const int MaxEntries = 100;
+ Queue<ITextLayout> CacheEntries = new Queue<ITextLayout>();
+ GapBuffer<LineToIndexTableData> Lines = new GapBuffer<LineToIndexTableData>();
+ Document Document;
+ long lastUpdateTicks = DateTime.Now.Ticks;
+ const long AllowCallTicks = 1000 * 10000; //see.DateTime.Ticks プロパティ
+ bool _IsSync;
+ ITextRender render;
+ int stepRow = -1,stepLength = 0;
+ const int STEP_ROW_IS_NONE = -1;
+
+ internal LineToIndexTable(Document buf)
+ {
+ this.Document = buf;
+ this.Document.Markers.Updated += Markers_Updated;
+ this.FoldingCollection = new FoldingCollection();
+ this._IsSync = true;
+#if DEBUG && !NETFX_CORE
+ if (!Debugger.IsAttached)
+ {
+ Guid guid = Guid.NewGuid();
+ string path = string.Format("{0}\\footextbox_lti_debug_{1}.log", System.IO.Path.GetTempPath(), guid);
+ Debug.Listeners.Add(new TextWriterTraceListener(path));
+ Debug.AutoFlush = true;
+ }
+#endif
+ }
+
+ void Markers_Updated(object sender, EventArgs e)
+ {
+ this.ClearLayoutCache();
+ }
+
+ /// <summary>
+ /// ITextRenderインターフェイスのインスタンス。必ずセットすること
+ /// </summary>
+ internal ITextRender Render
+ {
+ get { return this.render; }
+ set
+ {
+ this.render = value;
+ }
+ }
+
+ internal SpilitStringEventHandler SpilitString;
+
+ /// <summary>
+ /// 行数を返す
+ /// </summary>
+ public int Count
+ {
+ get { return this.Lines.Count; }
+ }
+
+ /// <summary>
+ /// 折り畳み関係の情報を収めたコレクション
+ /// </summary>
+ public FoldingCollection FoldingCollection
+ {
+ get;
+ private set;
+ }
+
+ /// <summary>
+ /// シンタックスハイライター
+ /// </summary>
+ internal IHilighter Hilighter { get; set; }
+
+ internal IFoldingStrategy FoldingStrategy { get; set; }
+
+ /// <summary>
+ /// 保持しているレイアウトキャッシュをクリアーする
+ /// </summary>
+ public void ClearLayoutCache()
+ {
+ foreach (ITextLayout data in this.CacheEntries)
+ {
+ data.Dispose();
+ }
+ this.CacheEntries.Clear();
+ }
+
+ /// <summary>
+ /// 行番号に対応する文字列を返します
+ /// </summary>
+ /// <param name="n"></param>
+ /// <returns></returns>
+ public string this[int n]
+ {
+ get
+ {
+ LineToIndexTableData data = this.Lines[n];
+ string str = this.Document.ToString(this.GetLineHeadIndex(n), data.Length);
+
+ return str;
+ }
+ }
+
+ /// <summary>
+ /// 更新フラグを更新しないなら真
+ /// </summary>
+ public bool IsFrozneDirtyFlag
+ {
+ get;
+ set;
+ }
+
+ int GetLineHeadIndex(int row)
+ {
+ if (this.Lines.Count == 0)
+ return 0;
+ if (this.stepRow != STEP_ROW_IS_NONE && row > this.stepRow)
+ return this.Lines[row].Index + this.stepLength;
+ else
+ return this.Lines[row].Index;
+ }
+
+ internal LineToIndexTableData CreateLineToIndexTableData(int index, int length, bool lineend, SyntaxInfo[] syntax)
+ {
+ LineToIndexTableData result = new LineToIndexTableData(index, length, lineend,this.IsFrozneDirtyFlag == false, syntax);
+ return result;
+ }
+
+ internal void UpdateLineAsReplace(int row,int removedLength, int insertedLength)
+ {
+ int deltaLength = insertedLength - removedLength;
+
+ this.Lines[row] = new LineToIndexTableData(this.GetLineHeadIndex(row), this.GetLengthFromLineNumber(row) + deltaLength, true, true, null);
+
+ //行テーブルを更新する
+ this.UpdateLineHeadIndex(deltaLength, row, 1);
+
+ this.FoldingCollection.UpdateData(this.Document, this.GetLineHeadIndex(row), insertedLength, removedLength);
+
+ this._IsSync = false;
+
+ this.lastUpdateTicks = DateTime.Now.Ticks;
+ }
+
+ internal void UpdateAsReplace(int index, int removedLength, int insertedLength)
+ {
+#if DEBUG
+ Debug.WriteLine("Replaced Index:{0} RemoveLength:{1} InsertLength:{2}", index, removedLength, insertedLength);
+#endif
+ int startRow, endRow;
+ GetRemoveRange(index, removedLength, out startRow, out endRow);
+
+ int deltaLength = insertedLength - removedLength;
+
+ var result = GetAnalyzeLength(startRow, endRow, index, removedLength, insertedLength);
+ int HeadIndex = result.Item1;
+ int analyzeLength = result.Item2;
+
+ //挿入範囲内のドキュメントから行を生成する
+ SpilitStringEventArgs e = new SpilitStringEventArgs(this.Document, HeadIndex, analyzeLength, startRow);
+ IList<LineToIndexTableData> newLines = SpilitString(this, e);
+
+ //消すべき行が複数ある場合は消すが、そうでない場合は最適化のため長さを変えるだけにとどめておく
+ int removeCount = endRow - startRow + 1;
+ if (removeCount == 1 && newLines.Count == 1)
+ {
+ this.Lines[startRow] = newLines.First();
+ }
+ else
+ {
+ this.RemoveLine(startRow, removeCount);
+
+ //行を挿入する
+ this.InsertLine(startRow, newLines, removeCount, deltaLength);
+ }
+
+ //行テーブルを更新する
+ this.UpdateLineHeadIndex(deltaLength, startRow, newLines.Count);
+
+ this.AddDummyLine();
+
+ this.FoldingCollection.UpdateData(this.Document, index, insertedLength, removedLength);
+
+ this._IsSync = false;
+
+ this.lastUpdateTicks = DateTime.Now.Ticks;
+ }
+
+ void GetRemoveRange(int index,int length,out int startRow,out int endRow)
+ {
+ startRow = this.GetLineNumberFromIndex(index);
+ while (startRow > 0 && this.Lines[startRow - 1].LineEnd == false)
+ startRow--;
+
+ endRow = this.GetLineNumberFromIndex(index + length);
+ while (endRow < this.Lines.Count && this.Lines[endRow].LineEnd == false)
+ endRow++;
+ if (endRow >= this.Lines.Count)
+ endRow = this.Lines.Count - 1;
+ }
+
+ Tuple<int,int> GetAnalyzeLength(int startRow,int endRow,int updateStartIndex,int removedLength,int insertedLength)
+ {
+ int HeadIndex = this.GetIndexFromLineNumber(startRow);
+ int LastIndex = this.GetIndexFromLineNumber(endRow) + this.GetLengthFromLineNumber(endRow) - 1;
+
+ //SpilitStringの対象となる範囲を求める
+ int fisrtPartLength = updateStartIndex - HeadIndex;
+ int secondPartLength = LastIndex - (updateStartIndex + removedLength - 1);
+ int analyzeLength = fisrtPartLength + secondPartLength + insertedLength;
+ Debug.Assert(analyzeLength <= this.Document.Length - 1 - HeadIndex + 1);
+
+ return new Tuple<int, int>(HeadIndex, analyzeLength);
+ }
+
+ void RemoveLine(int startRow, int removeCount)
+ {
+ for (int i = startRow; i < startRow + removeCount; i++)
+ this.Lines[i].Dispose();
+
+ this.Lines.RemoveRange(startRow, removeCount);
+ }
+
+ void InsertLine(int startRow, IList<LineToIndexTableData> collection,int removeCount, int deltaLength)
+ {
+ int newCount = collection.Count;
+ if (this.stepRow > startRow && newCount > 0 && newCount != removeCount)
+ {
+ //stepRowは1か2のうち、大きな方になる
+ // 1.stepRow - (削除された行数 - 挿入された行数)
+ // 2.行の挿入箇所
+ //行が削除や置換された場合、1の処理をしないと正しいIndexが求められない
+ this.stepRow = Math.Max(this.stepRow - (removeCount - newCount), startRow);
+#if DEBUG
+ if (this.stepRow < 0 || this.stepRow > this.Lines.Count + newCount)
+ {
+ Debug.WriteLine("step row < 0 or step row >= lines.count");
+ Debugger.Break();
+ }
+#endif
+ }
+
+ //startRowが挿入した行の開始位置なのであらかじめ引いておく
+ for (int i = 1; i < collection.Count; i++)
+ {
+ if (this.stepRow != STEP_ROW_IS_NONE && startRow + i > this.stepRow)
+ collection[i].Index -= deltaLength + this.stepLength;
+ else
+ collection[i].Index -= deltaLength;
+ }
+
+ this.Lines.InsertRange(startRow, collection);
+ }
+
+ void AddDummyLine()
+ {
+ LineToIndexTableData dummyLine = null;
+ if (this.Lines.Count == 0)
+ {
+ dummyLine = new LineToIndexTableData();
+ this.Lines.Add(dummyLine);
+ return;
+ }
+
+ int lastLineRow = this.Lines.Count > 0 ? this.Lines.Count - 1 : 0;
+ int lastLineHeadIndex = this.GetIndexFromLineNumber(lastLineRow);
+ int lastLineLength = this.GetLengthFromLineNumber(lastLineRow);
+
+ if (lastLineLength != 0 && this.Document[Document.Length - 1] == Document.NewLine)
+ {
+ int realIndex = lastLineHeadIndex + lastLineLength;
+ if (lastLineRow >= this.stepRow)
+ realIndex -= this.stepLength;
+ dummyLine = new LineToIndexTableData(realIndex, 0, true,false, null);
+ this.Lines.Add(dummyLine);
+ }
+ }
+
+ void UpdateLineHeadIndex(int deltaLength,int startRow,int insertedLineCount)
+ {
+ if (this.Lines.Count == 0)
+ {
+ this.stepRow = STEP_ROW_IS_NONE;
+ this.stepLength = 0;
+ return;
+ }
+
+ if (this.stepRow == STEP_ROW_IS_NONE)
+ {
+ this.stepRow = startRow;
+ this.stepLength = deltaLength;
+ return;
+ }
+
+
+ if (startRow < this.stepRow)
+ {
+ //ドキュメントの後半部分をごっそり削除した場合、this.stepRow >= this.Lines.Countになる可能性がある
+ if (this.stepRow >= this.Lines.Count)
+ this.stepRow = this.Lines.Count - 1;
+ for (int i = this.stepRow; i > startRow; i--)
+ this.Lines[i].Index -= this.stepLength;
+ }
+ else if (startRow > this.stepRow)
+ {
+ for (int i = this.stepRow + 1; i < startRow; i++)
+ this.Lines[i].Index += this.stepLength;
+ }
+
+ this.stepRow = startRow;
+ this.stepLength += deltaLength;
+
+ this.ValidateLines();
+ }
+
+ void ValidateLines()
+ {
+#if DEBUG
+ int nextIndex = 0;
+ for (int i = 0; i < this.Lines.Count; i++)
+ {
+ int lineHeadIndex = this.GetLineHeadIndex(i);
+ if (lineHeadIndex != nextIndex)
+ {
+ Debug.WriteLine("Invaild Line");
+ System.Diagnostics.Debugger.Break();
+ }
+ nextIndex = lineHeadIndex + this.Lines[i].Length;
+ }
+#endif
+ }
+
+ /// <summary>
+ /// 行番号をインデックスに変換します
+ /// </summary>
+ /// <param name="row">行番号</param>
+ /// <returns>0から始まるインデックスを返す</returns>
+ public int GetIndexFromLineNumber(int row)
+ {
+ if (row < 0 || row > this.Lines.Count)
+ throw new ArgumentOutOfRangeException();
+ return this.GetLineHeadIndex(row);
+ }
+
+ /// <summary>
+ /// 行の長さを得ます
+ /// </summary>
+ /// <param name="row">行番号</param>
+ /// <returns>行の文字長を返します</returns>
+ public int GetLengthFromLineNumber(int row)
+ {
+ if (row < 0 || row > this.Lines.Count)
+ throw new ArgumentOutOfRangeException();
+ return this.Lines[row].Length;
+ }
+
+ /// <summary>
+ /// 更新フラグを取得します
+ /// </summary>
+ /// <param name="row">行番号</param>
+ /// <returns>更新されていれば真。そうでなければ偽</returns>
+ public bool GetDirtyFlag(int row)
+ {
+ if (row < 0 || row > this.Lines.Count)
+ throw new ArgumentOutOfRangeException();
+ return this.Lines[row].Dirty;
+ }
+
+ internal ITextLayout GetLayout(int row)
+ {
+ if (this.Lines[row].Layout != null && this.Lines[row].Layout.Invaild)
+ {
+ this.Lines[row].Layout.Dispose();
+ this.Lines[row].Layout = null;
+ }
+ if (this.Lines[row].Layout == null || this.Lines[row].Layout.Disposed)
+ this.Lines[row].Layout = this.CreateLayout(row);
+ return this.Lines[row].Layout;
+ }
+
+ internal event EventHandler<CreateLayoutEventArgs> CreateingLayout;
+
+ ITextLayout CreateLayout(int row)
+ {
+ ITextLayout layout;
+ LineToIndexTableData lineData = this.Lines[row];
+ if (lineData.Length == 0)
+ {
+ layout = this.render.CreateLaytout("", null, null);
+ }
+ else
+ {
+ int lineHeadIndex = this.GetLineHeadIndex(row);
+
+ string content = this.Document.ToString(lineHeadIndex, lineData.Length);
+
+ if (this.CreateingLayout != null)
+ this.CreateingLayout(this, new CreateLayoutEventArgs(lineHeadIndex, lineData.Length,content));
+
+ var markerRange = from id in this.Document.Markers.IDs
+ from s in this.Document.Markers.Get(id,lineHeadIndex,lineData.Length)
+ let n = Util.ConvertAbsIndexToRelIndex(s, lineHeadIndex, lineData.Length)
+ select n;
+ layout = this.render.CreateLaytout(content, lineData.Syntax, markerRange);
+ }
+
+ if (this.CacheEntries.Count > MaxEntries)
+ {
+ ITextLayout oldItem = this.CacheEntries.Dequeue();
+ oldItem.Dispose();
+ }
+ this.CacheEntries.Enqueue(layout);
+
+ return layout;
+ }
+
+ int lastLineNumber;
+ /// <summary>
+ /// インデックスを行番号に変換します
+ /// </summary>
+ /// <param name="index">インデックス</param>
+ /// <returns>行番号を返します</returns>
+ public int GetLineNumberFromIndex(int index)
+ {
+ if (index < 0)
+ throw new ArgumentOutOfRangeException("indexに負の値を設定することはできません");
+
+ if (index == 0 && this.Lines.Count > 0)
+ return 0;
+
+ LineToIndexTableData line;
+ int lineHeadIndex;
+
+ if (lastLineNumber < this.Lines.Count - 1)
+ {
+ line = this.Lines[lastLineNumber];
+ lineHeadIndex = this.GetLineHeadIndex(lastLineNumber);
+ if (index >= lineHeadIndex && index < lineHeadIndex + line.Length)
+ return lastLineNumber;
+ }
+
+ int left = 0, right = this.Lines.Count - 1, mid;
+ while (left <= right)
+ {
+ mid = (left + right) / 2;
+ line = this.Lines[mid];
+ lineHeadIndex = this.GetLineHeadIndex(mid);
+ if (index >= lineHeadIndex && index < lineHeadIndex + line.Length)
+ {
+ lastLineNumber = mid;
+ return mid;
+ }
+ if (index < lineHeadIndex)
+ {
+ right = mid - 1;
+ }
+ else
+ {
+ left = mid + 1;
+ }
+ }
+
+ int lastRow = this.Lines.Count - 1;
+ line = this.Lines[lastRow];
+ lineHeadIndex = this.GetLineHeadIndex(lastRow);
+ if (index >= lineHeadIndex && index <= lineHeadIndex + line.Length) //最終行長+1までキャレットが移動する可能性があるので
+ {
+ lastLineNumber = this.Lines.Count - 1;
+ return lastLineNumber;
+ }
+
+ throw new ArgumentOutOfRangeException("該当する行が見つかりませんでした");
+ }
+
+ /// <summary>
+ /// インデックスからテキストポイントに変換します
+ /// </summary>
+ /// <param name="index">インデックス</param>
+ /// <returns>TextPoint構造体を返します</returns>
+ public TextPoint GetTextPointFromIndex(int index)
+ {
+ TextPoint tp = new TextPoint();
+ tp.row = GetLineNumberFromIndex(index);
+ tp.col = index - this.GetLineHeadIndex(tp.row);
+ Debug.Assert(tp.row < this.Lines.Count && tp.col <= this.Lines[tp.row].Length);
+ return tp;
+ }
+
+ /// <summary>
+ /// テキストポイントからインデックスに変換します
+ /// </summary>
+ /// <param name="tp">TextPoint構造体</param>
+ /// <returns>インデックスを返します</returns>
+ public int GetIndexFromTextPoint(TextPoint tp)
+ {
+ if (tp == TextPoint.Null)
+ throw new ArgumentNullException("TextPoint.Null以外の値でなければなりません");
+ if(tp.row < 0 || tp.row > this.Lines.Count)
+ throw new ArgumentOutOfRangeException("tp.rowが設定できる範囲を超えています");
+ if (tp.col < 0 || tp.col > this.Lines[tp.row].Length)
+ throw new ArgumentOutOfRangeException("tp.colが設定できる範囲を超えています");
+ return this.GetLineHeadIndex(tp.row) + tp.col;
+ }
+
+ /// <summary>
+ /// フォールディングを再生成します
+ /// </summary>
+ /// <param name="force">ドキュメントが更新されていなくても再生成する</param>
+ /// <returns>生成された場合は真を返す</returns>
+ /// <remarks>デフォルトではドキュメントが更新されている時にだけ再生成されます</remarks>
+ public bool GenerateFolding(bool force = false)
+ {
+ if (this.Document.Length == 0 || this.Document.IsLocked)
+ return false;
+ long nowTick = DateTime.Now.Ticks;
+ bool sync = force || !this._IsSync;
+ if (sync || Math.Abs(nowTick - this.lastUpdateTicks) >= AllowCallTicks)
+ {
+ this.GenerateFolding(0, this.Document.Length - 1);
+ this.lastUpdateTicks = nowTick;
+ return true;
+ }
+ return false;
+ }
+
+ void GenerateFolding(int start, int end)
+ {
+ if (start > end)
+ throw new ArgumentException("start <= endである必要があります");
+ if (this.FoldingStrategy != null)
+ {
+ //再生成するとすべて展開状態になってしまうので、閉じてるやつだけを保存しておく
+ FoldingItem[] closed_items = this.FoldingCollection.Where((e)=> { return !e.Expand; }).ToArray();
+
+ this.FoldingCollection.Clear();
+
+ var items = this.FoldingStrategy.AnalyzeDocument(this.Document, start, end)
+ .Where((item) =>
+ {
+ int startRow = this.GetLineNumberFromIndex(item.Start);
+ int endRow = this.GetLineNumberFromIndex(item.End);
+ return startRow != endRow;
+ })
+ .Select((item) => item);
+ this.FoldingCollection.AddRange(items);
+
+ this.FoldingCollection.ApplyExpandStatus(closed_items);
+ }
+ }
+
+ /// <summary>
+ /// フォールディングをすべて削除します
+ /// </summary>
+ public void ClearFolding()
+ {
+ this.FoldingCollection.Clear();
+ this._IsSync = false;
+ }
+
+ /// <summary>
+ /// すべての行に対しシンタックスハイライトを行います
+ /// </summary>
+ public bool HilightAll(bool force = false)
+ {
+ if (this.Hilighter == null || this.Document.IsLocked)
+ return false;
+
+ long nowTick = DateTime.Now.Ticks;
+ bool sync = force || !this._IsSync;
+ if (sync || Math.Abs(nowTick - this.lastUpdateTicks) >= AllowCallTicks)
+ {
+ for (int i = 0; i < this.Lines.Count; i++)
+ this.HilightLine(i);
+
+ this.Hilighter.Reset();
+ this.ClearLayoutCache();
+
+ this.lastUpdateTicks = nowTick;
+
+ return true;
+ }
+ return false;
+ }
+
+ /// <summary>
+ /// ハイライト関連の情報をすべて削除します
+ /// </summary>
+ public void ClearHilight()
+ {
+ foreach (LineToIndexTableData line in this.Lines)
+ line.Syntax = null;
+ this.ClearLayoutCache();
+ }
+
+ /// <summary>
+ /// すべて削除します
+ /// </summary>
+ internal void Clear()
+ {
+ this.ClearLayoutCache();
+ this.FoldingCollection.Clear();
+ this.Lines.Clear();
+ LineToIndexTableData dummy = new LineToIndexTableData();
+ this.Lines.Add(dummy);
+ this.stepRow = STEP_ROW_IS_NONE;
+ this.stepLength = 0;
+ Debug.WriteLine("Clear");
+ }
+
+ private void HilightLine(int row)
+ {
+ //シンタックスハイライトを行う
+ List<SyntaxInfo> syntax = new List<SyntaxInfo>();
+ string str = this[row];
+ int level = this.Hilighter.DoHilight(str, str.Length, (s) =>
+ {
+ if (s.type == TokenType.None || s.type == TokenType.Control)
+ return;
+ if (str[s.index + s.length - 1] == Document.NewLine)
+ s.length--;
+ syntax.Add(new SyntaxInfo(s.index, s.length, s.type));
+ });
+
+ LineToIndexTableData lineData = this.Lines[row];
+ lineData.Syntax = syntax.ToArray();
+
+ }
+
+ #region IEnumerable<string> メンバー
+
+ /// <summary>
+ /// コレクションを反復処理するためのIEnumeratorを返す
+ /// </summary>
+ /// <returns>IEnumeratorオブジェクト</returns>
+ public IEnumerator<string> GetEnumerator()
+ {
+ for (int i = 0; i < this.Lines.Count; i++)
+ yield return this[i];
+ }
+
+ #endregion
+
+ #region IEnumerable メンバー
+
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+ {
+ for (int i = 0; i < this.Lines.Count; i++)
+ yield return this[i];
+ }
+
+ #endregion
+ }
+
+}
-/*\r
- * Copyright (C) 2013 FooProject\r
- * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.\r
-\r
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of \r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\r
-\r
-You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.\r
- */\r
-using System;\r
-using System.Linq;\r
-using System.Collections.Generic;\r
-\r
-namespace FooEditEngine\r
-{\r
- /// <summary>\r
- /// 既定のIDリスト\r
- /// </summary>\r
- public static class MarkerIDs\r
- {\r
- /// <summary>\r
- /// デフォルトIDを表す\r
- /// </summary>\r
- public static int Defalut = 0;\r
- /// <summary>\r
- /// URLを表す\r
- /// </summary>\r
- public static int URL = 1;\r
- }\r
- /// <summary>\r
- /// マーカーのタイプを表す列挙体\r
- /// </summary>\r
- public enum HilightType\r
- {\r
- /// <summary>\r
- /// マーカーとして表示しないことを表す\r
- /// </summary>\r
- None,\r
- /// <summary>\r
- /// 選択状態を表す\r
- /// </summary>\r
- Select,\r
- /// <summary>\r
- /// URLを表す\r
- /// </summary>\r
- Url,\r
- /// <summary>\r
- /// 実線を表す\r
- /// </summary>\r
- Sold,\r
- /// <summary>\r
- /// 破線を表す\r
- /// </summary>\r
- Dash,\r
- /// <summary>\r
- /// 一点鎖線を表す\r
- /// </summary>\r
- DashDot,\r
- /// <summary>\r
- /// 二点鎖線を表す\r
- /// </summary>\r
- DashDotDot,\r
- /// <summary>\r
- /// 点線を表す\r
- /// </summary>\r
- Dot,\r
- /// <summary>\r
- /// 波線を表す\r
- /// </summary>\r
- Squiggle,\r
- }\r
-\r
- /// <summary>\r
- /// マーカー自身を表します\r
- /// </summary>\r
- public struct Marker : IRange, IEqualityComparer<Marker>\r
- {\r
- #region IRange メンバー\r
-\r
- /// <summary>\r
- /// 開始位置\r
- /// </summary>\r
- public int start\r
- {\r
- get;\r
- set;\r
- }\r
-\r
- /// <summary>\r
- /// 長さ\r
- /// </summary>\r
- public int length\r
- {\r
- get;\r
- set;\r
- }\r
-\r
- #endregion\r
-\r
- /// <summary>\r
- /// マーカーのタイプ\r
- /// </summary>\r
- public HilightType hilight;\r
-\r
- /// <summary>\r
- /// 色を指定する\r
- /// </summary>\r
- public Color color;\r
-\r
- /// <summary>\r
- /// マーカーを作成します\r
- /// </summary>\r
- /// <param name="start">開始インデックス</param>\r
- /// <param name="length">長さ</param>\r
- /// <param name="hilight">タイプ</param>\r
- /// <returns>マーカー</returns>\r
- public static Marker Create(int start, int length, HilightType hilight)\r
- {\r
- return new Marker { start = start, length = length, hilight = hilight, color = new Color()};\r
- }\r
-\r
- /// <summary>\r
- /// マーカーを作成します\r
- /// </summary>\r
- /// <param name="start">開始インデックス</param>\r
- /// <param name="length">長さ</param>\r
- /// <param name="hilight">タイプ</param>\r
- /// <param name="color">色</param>\r
- /// <returns>マーカー</returns>\r
- public static Marker Create(int start, int length, HilightType hilight,Color color)\r
- {\r
- return new Marker { start = start, length = length, hilight = hilight ,color = color};\r
- }\r
-\r
- /// <summary>\r
- /// 等しいかどうかを調べます\r
- /// </summary>\r
- /// <param name="x">比較されるマーカー</param>\r
- /// <param name="y">比較するマーカー</param>\r
- /// <returns>等しいなら真。そうでなければ偽</returns>\r
- public bool Equals(Marker x, Marker y)\r
- {\r
- return x.hilight == y.hilight && x.length == y.length && x.start == y.start;\r
- }\r
-\r
- /// <summary>\r
- /// ハッシュを得ます\r
- /// </summary>\r
- /// <param name="obj">マーカー</param>\r
- /// <returns>ハッシュ</returns>\r
- public int GetHashCode(Marker obj)\r
- {\r
- return this.start ^ this.length ^ (int)this.hilight;\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// マーカークラスのコレクションを表します\r
- /// </summary>\r
- public sealed class MarkerCollection\r
- {\r
- Dictionary<int, RangeCollection<Marker>> collection = new Dictionary<int, RangeCollection<Marker>>();\r
-\r
- internal MarkerCollection(Document doc)\r
- {\r
- doc.UpdateCalledAlways += new DocumentUpdateEventHandler(doc_Update);\r
- this.Updated +=new EventHandler((s,e)=>{});\r
- }\r
-\r
- /// <summary>\r
- /// 更新されたことを通知します\r
- /// </summary>\r
- public event EventHandler Updated;\r
-\r
- internal void Add(int id,Marker m)\r
- {\r
- this.AddImpl(id, m);\r
- this.Updated(this, null);\r
- }\r
-\r
- void AddImpl(int id, Marker m)\r
- {\r
- RangeCollection<Marker> markers;\r
- if (this.collection.TryGetValue(id, out markers))\r
- {\r
- markers.Remove(m.start, m.length);\r
- markers.Add(m);\r
- }\r
- else\r
- {\r
- markers = new RangeCollection<Marker>();\r
- markers.Add(m);\r
- this.collection.Add(id, markers);\r
- }\r
- }\r
-\r
- internal void AddRange(int id, IEnumerable<Marker> collection)\r
- {\r
- foreach (Marker m in collection)\r
- this.AddImpl(id, m);\r
- this.Updated(this, null);\r
- }\r
-\r
- internal void RemoveAll(int id,int start, int length)\r
- {\r
- RangeCollection<Marker> markers;\r
- if (this.collection.TryGetValue(id, out markers))\r
- {\r
- markers.Remove(start, length);\r
- }\r
- this.Updated(this, null);\r
- }\r
-\r
- internal void RemoveAll(int id, HilightType type)\r
- {\r
- RangeCollection<Marker> markers;\r
- if (this.collection.TryGetValue(id, out markers))\r
- {\r
- for (int i = 0; i < markers.Count; i++)\r
- {\r
- if (markers[i].hilight == type)\r
- markers.RemoveAt(i);\r
- }\r
- }\r
- this.Updated(this, null);\r
- }\r
-\r
- internal IEnumerable<int> IDs\r
- {\r
- get\r
- {\r
- return this.collection.Keys;\r
- }\r
- }\r
-\r
- internal IEnumerable<Marker> Get(int id)\r
- {\r
- RangeCollection<Marker> markers;\r
- if (this.collection.TryGetValue(id, out markers))\r
- {\r
- foreach (var m in markers)\r
- yield return m;\r
- }\r
- yield break;\r
- }\r
-\r
- internal IEnumerable<Marker> Get(int id, int index)\r
- {\r
- RangeCollection<Marker> markers;\r
- if (this.collection.TryGetValue(id, out markers))\r
- {\r
- foreach (var m in markers.Get(index))\r
- yield return m;\r
- }\r
- yield break;\r
- }\r
-\r
- internal IEnumerable<Marker> Get(int id, int index, int length)\r
- {\r
- RangeCollection<Marker> markers;\r
- if (this.collection.TryGetValue(id, out markers))\r
- {\r
- foreach (var m in markers.Get(index, length))\r
- yield return m;\r
- }\r
- yield break;\r
- }\r
-\r
- /// <summary>\r
- /// マーカーをすべて削除します\r
- /// </summary>\r
- /// <param name="id">マーカーID</param>\r
- public void Clear(int id)\r
- {\r
- RangeCollection<Marker> markers;\r
- if (this.collection.TryGetValue(id, out markers))\r
- markers.Clear();\r
- this.Updated(this, null);\r
- }\r
-\r
- /// <summary>\r
- /// マーカーをすべて削除します\r
- /// </summary>\r
- public void Clear()\r
- {\r
- this.collection.Clear();\r
- this.Updated(this, null);\r
- }\r
-\r
- void doc_Update(object sender, DocumentUpdateEventArgs e)\r
- {\r
- int deltaLength = 0;\r
- switch (e.type)\r
- {\r
- case UpdateType.Replace:\r
- deltaLength = e.insertLength - e.removeLength;\r
- foreach (RangeCollection<Marker> markers in this.collection.Values)\r
- {\r
- for (int i = 0; i < markers.Count; i++)\r
- {\r
- Marker m = markers[i];\r
- if (m.start + m.length - 1 < e.startIndex)\r
- {\r
- continue;\r
- }\r
- else\r
- {\r
- m.start += deltaLength;\r
- }\r
- markers[i] = m;\r
- }\r
- }\r
- break;\r
- default:\r
- return;\r
- }\r
- }\r
-\r
- }\r
-}\r
+/*
+ * Copyright (C) 2013 FooProject
+ * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+using System.Linq;
+using System.Collections.Generic;
+
+namespace FooEditEngine
+{
+ /// <summary>
+ /// 既定のIDリスト
+ /// </summary>
+ public static class MarkerIDs
+ {
+ /// <summary>
+ /// デフォルトIDを表す
+ /// </summary>
+ public static int Defalut = 0;
+ /// <summary>
+ /// URLを表す
+ /// </summary>
+ public static int URL = 1;
+ }
+ /// <summary>
+ /// マーカーのタイプを表す列挙体
+ /// </summary>
+ public enum HilightType
+ {
+ /// <summary>
+ /// マーカーとして表示しないことを表す
+ /// </summary>
+ None,
+ /// <summary>
+ /// 選択状態を表す
+ /// </summary>
+ Select,
+ /// <summary>
+ /// URLを表す
+ /// </summary>
+ Url,
+ /// <summary>
+ /// 実線を表す
+ /// </summary>
+ Sold,
+ /// <summary>
+ /// 破線を表す
+ /// </summary>
+ Dash,
+ /// <summary>
+ /// 一点鎖線を表す
+ /// </summary>
+ DashDot,
+ /// <summary>
+ /// 二点鎖線を表す
+ /// </summary>
+ DashDotDot,
+ /// <summary>
+ /// 点線を表す
+ /// </summary>
+ Dot,
+ /// <summary>
+ /// 波線を表す
+ /// </summary>
+ Squiggle,
+ }
+
+ /// <summary>
+ /// マーカー自身を表します
+ /// </summary>
+ public struct Marker : IRange, IEqualityComparer<Marker>
+ {
+ #region IRange メンバー
+
+ /// <summary>
+ /// 開始位置
+ /// </summary>
+ public int start
+ {
+ get;
+ set;
+ }
+
+ /// <summary>
+ /// 長さ
+ /// </summary>
+ public int length
+ {
+ get;
+ set;
+ }
+
+ #endregion
+
+ /// <summary>
+ /// マーカーのタイプ
+ /// </summary>
+ public HilightType hilight;
+
+ /// <summary>
+ /// 色を指定する
+ /// </summary>
+ public Color color;
+
+ /// <summary>
+ /// マーカーを作成します
+ /// </summary>
+ /// <param name="start">開始インデックス</param>
+ /// <param name="length">長さ</param>
+ /// <param name="hilight">タイプ</param>
+ /// <returns>マーカー</returns>
+ public static Marker Create(int start, int length, HilightType hilight)
+ {
+ return new Marker { start = start, length = length, hilight = hilight, color = new Color()};
+ }
+
+ /// <summary>
+ /// マーカーを作成します
+ /// </summary>
+ /// <param name="start">開始インデックス</param>
+ /// <param name="length">長さ</param>
+ /// <param name="hilight">タイプ</param>
+ /// <param name="color">色</param>
+ /// <returns>マーカー</returns>
+ public static Marker Create(int start, int length, HilightType hilight,Color color)
+ {
+ return new Marker { start = start, length = length, hilight = hilight ,color = color};
+ }
+
+ /// <summary>
+ /// 等しいかどうかを調べます
+ /// </summary>
+ /// <param name="x">比較されるマーカー</param>
+ /// <param name="y">比較するマーカー</param>
+ /// <returns>等しいなら真。そうでなければ偽</returns>
+ public bool Equals(Marker x, Marker y)
+ {
+ return x.hilight == y.hilight && x.length == y.length && x.start == y.start;
+ }
+
+ /// <summary>
+ /// ハッシュを得ます
+ /// </summary>
+ /// <param name="obj">マーカー</param>
+ /// <returns>ハッシュ</returns>
+ public int GetHashCode(Marker obj)
+ {
+ return this.start ^ this.length ^ (int)this.hilight;
+ }
+ }
+
+ /// <summary>
+ /// マーカークラスのコレクションを表します
+ /// </summary>
+ public sealed class MarkerCollection
+ {
+ Dictionary<int, RangeCollection<Marker>> collection = new Dictionary<int, RangeCollection<Marker>>();
+
+ internal MarkerCollection(Document doc)
+ {
+ doc.UpdateCalledAlways += new DocumentUpdateEventHandler(doc_Update);
+ this.Updated +=new EventHandler((s,e)=>{});
+ }
+
+ /// <summary>
+ /// 更新されたことを通知します
+ /// </summary>
+ public event EventHandler Updated;
+
+ internal void Add(int id,Marker m)
+ {
+ this.AddImpl(id, m);
+ this.Updated(this, null);
+ }
+
+ void AddImpl(int id, Marker m)
+ {
+ RangeCollection<Marker> markers;
+ if (this.collection.TryGetValue(id, out markers))
+ {
+ markers.Remove(m.start, m.length);
+ markers.Add(m);
+ }
+ else
+ {
+ markers = new RangeCollection<Marker>();
+ markers.Add(m);
+ this.collection.Add(id, markers);
+ }
+ }
+
+ internal void AddRange(int id, IEnumerable<Marker> collection)
+ {
+ foreach (Marker m in collection)
+ this.AddImpl(id, m);
+ this.Updated(this, null);
+ }
+
+ internal void RemoveAll(int id,int start, int length)
+ {
+ RangeCollection<Marker> markers;
+ if (this.collection.TryGetValue(id, out markers))
+ {
+ markers.Remove(start, length);
+ }
+ this.Updated(this, null);
+ }
+
+ internal void RemoveAll(int id, HilightType type)
+ {
+ RangeCollection<Marker> markers;
+ if (this.collection.TryGetValue(id, out markers))
+ {
+ for (int i = 0; i < markers.Count; i++)
+ {
+ if (markers[i].hilight == type)
+ markers.RemoveAt(i);
+ }
+ }
+ this.Updated(this, null);
+ }
+
+ internal IEnumerable<int> IDs
+ {
+ get
+ {
+ return this.collection.Keys;
+ }
+ }
+
+ internal IEnumerable<Marker> Get(int id)
+ {
+ RangeCollection<Marker> markers;
+ if (this.collection.TryGetValue(id, out markers))
+ {
+ foreach (var m in markers)
+ yield return m;
+ }
+ yield break;
+ }
+
+ internal IEnumerable<Marker> Get(int id, int index)
+ {
+ RangeCollection<Marker> markers;
+ if (this.collection.TryGetValue(id, out markers))
+ {
+ foreach (var m in markers.Get(index))
+ yield return m;
+ }
+ yield break;
+ }
+
+ internal IEnumerable<Marker> Get(int id, int index, int length)
+ {
+ RangeCollection<Marker> markers;
+ if (this.collection.TryGetValue(id, out markers))
+ {
+ foreach (var m in markers.Get(index, length))
+ yield return m;
+ }
+ yield break;
+ }
+
+ /// <summary>
+ /// マーカーをすべて削除します
+ /// </summary>
+ /// <param name="id">マーカーID</param>
+ public void Clear(int id)
+ {
+ RangeCollection<Marker> markers;
+ if (this.collection.TryGetValue(id, out markers))
+ markers.Clear();
+ this.Updated(this, null);
+ }
+
+ /// <summary>
+ /// マーカーをすべて削除します
+ /// </summary>
+ public void Clear()
+ {
+ this.collection.Clear();
+ this.Updated(this, null);
+ }
+
+ void doc_Update(object sender, DocumentUpdateEventArgs e)
+ {
+ int deltaLength = 0;
+ switch (e.type)
+ {
+ case UpdateType.Replace:
+ deltaLength = e.insertLength - e.removeLength;
+ foreach (RangeCollection<Marker> markers in this.collection.Values)
+ {
+ for (int i = 0; i < markers.Count; i++)
+ {
+ Marker m = markers[i];
+ if (m.start + m.length - 1 < e.startIndex)
+ {
+ continue;
+ }
+ else
+ {
+ m.start += deltaLength;
+ }
+ markers[i] = m;
+ }
+ }
+ break;
+ default:
+ return;
+ }
+ }
+
+ }
+}
-/*\r
- * Copyright (C) 2013 FooProject\r
- * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.\r
-\r
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of \r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\r
-\r
-You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.\r
- */\r
-using System;\r
-\r
-namespace FooEditEngine\r
-{\r
- sealed class PrintableView : ViewBase\r
- {\r
- public PrintableView(Document doc, IPrintableTextRender r, Padding margin)\r
- : base (doc,r,margin)\r
- {\r
- }\r
-\r
- public string Header\r
- {\r
- get;\r
- set;\r
- }\r
-\r
- public string Footer\r
- {\r
- get;\r
- set;\r
- }\r
-\r
- public override void Draw(Rectangle updateRect)\r
- {\r
- if (this.LayoutLines.Count == 0)\r
- return;\r
-\r
- if (this.Hilighter != null)\r
- this.Hilighter.Reset();\r
-\r
- Point pos = this.render.TextArea.TopLeft;\r
- pos.X -= Src.X;\r
-\r
- int endRow = Math.Min(this.LayoutLines.Count - 1, Src.Row + this.LineCountOnScreen - 1);\r
-\r
- Size lineNumberSize = new Size(this.render.LineNemberWidth, this.render.TextArea.Height);\r
-\r
- IPrintableTextRender render = (IPrintableTextRender)this.render;\r
-\r
- //ヘッダーを印刷する\r
- if (this.Header != null && this.Header != string.Empty)\r
- {\r
- this.render.DrawString(this.Header, pos.X, pos.Y, StringAlignment.Center,\r
- new Size(render.TextArea.Width - this.GetRealtiveX(AreaType.TextArea),render.FooterHeight));\r
-\r
- pos.Y += (int)render.HeaderHeight;\r
- }\r
-\r
- //レイアウト行を印刷する\r
- for (int i = Src.Row; i <= endRow; i++)\r
- {\r
- double lineHeight = this.LayoutLines.GetLayout(i).Height;\r
-\r
- this.render.DrawOneLine(this.LayoutLines,i, pos.X + this.render.TextArea.X, pos.Y, null);\r
-\r
- if (this.DrawLineNumber)\r
- this.render.DrawString((i + 1).ToString(), this.PageBound.X + this.GetRealtiveX(AreaType.LineNumberArea), pos.Y, StringAlignment.Right, lineNumberSize);\r
-\r
- pos.Y += lineHeight;\r
- }\r
-\r
- //フッターを印刷する\r
- if (this.Footer != null && this.Footer != string.Empty)\r
- {\r
- pos.Y = render.TextArea.Bottom;\r
- this.render.DrawString(this.Footer, pos.X, pos.Y, StringAlignment.Center,\r
- new Size(render.TextArea.Width - this.GetRealtiveX(AreaType.TextArea), render.FooterHeight));\r
- }\r
- }\r
-\r
- public bool TryPageDown()\r
- {\r
- return base.TryScroll(this.Src.X, this.Src.Row + this.LineCountOnScreen);\r
- }\r
-\r
- protected override void CalculateClipRect()\r
- {\r
- double x, y, width, height;\r
-\r
- if (this.DrawLineNumber)\r
- {\r
- if (this.render.RightToLeft)\r
- x = this.Padding.Left;\r
- else\r
- x = this.render.LineNemberWidth + this.render.emSize.Width + this.Padding.Left + this.LineNumberMargin;\r
- width = this.PageBound.Width - this.render.LineNemberWidth - this.render.emSize.Width - this.Padding.Right - this.Padding.Left - this.LineNumberMargin;\r
- }\r
- else\r
- {\r
- x = this.Padding.Left;\r
- width = this.PageBound.Width - this.Padding.Right - this.Padding.Left;\r
- }\r
-\r
- y = this.Padding.Top;\r
- height = this.PageBound.Height - this.Padding.Bottom - this.Padding.Top;\r
-\r
- if (width < 0)\r
- width = 0;\r
-\r
- if (height < 0)\r
- height = 0;\r
-\r
- IPrintableTextRender render = (IPrintableTextRender)this.render;\r
-\r
- if (this.Footer != null && this.Footer != string.Empty)\r
- height -= render.FooterHeight;\r
- if (this.Header != null && this.Header != string.Empty)\r
- height -= render.HeaderHeight;\r
-\r
- this.render.TextArea = new Rectangle(x, y, width, height);\r
- }\r
-\r
- public override void CalculateLineCountOnScreen()\r
- {\r
- if (this.LayoutLines.Count == 0)\r
- return;\r
-\r
- double y = 0;\r
- int i = this.Src.Row;\r
- for (; true; i++)\r
- {\r
- int row = i < this.LayoutLines.Count ? i : this.LayoutLines.Count - 1;\r
-\r
- ITextLayout layout = this.LayoutLines.GetLayout(row);\r
-\r
- double lineHeight = layout.Height;\r
-\r
- y += lineHeight;\r
-\r
- if (y >= this.render.TextArea.Height)\r
- break;\r
- }\r
- this.LineCountOnScreen = Math.Max(i - this.Src.Row - 1, 0); //ループを抜けると+1されている\r
- }\r
-\r
- enum AreaType\r
- {\r
- LineNumberArea,\r
- TextArea\r
- }\r
-\r
- double GetRealtiveX(AreaType type)\r
- {\r
- switch (type)\r
- {\r
- case AreaType.LineNumberArea:\r
- if (this.DrawLineNumber == false)\r
- throw new InvalidOperationException();\r
- if (this.render.RightToLeft)\r
- return this.PageBound.TopRight.X - this.render.LineNemberWidth;\r
- else\r
- return this.render.TextArea.X - this.render.LineNemberWidth - this.render.emSize.Width - this.LineNumberMargin;\r
- case AreaType.TextArea:\r
- return this.render.TextArea.X;\r
- }\r
- throw new ArgumentOutOfRangeException();\r
- }\r
- }\r
-}\r
+/*
+ * Copyright (C) 2013 FooProject
+ * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+
+namespace FooEditEngine
+{
+ sealed class PrintableView : ViewBase
+ {
+ public PrintableView(Document doc, IPrintableTextRender r, Padding margin)
+ : base (doc,r,margin)
+ {
+ }
+
+ public string Header
+ {
+ get;
+ set;
+ }
+
+ public string Footer
+ {
+ get;
+ set;
+ }
+
+ public override void Draw(Rectangle updateRect)
+ {
+ if (this.LayoutLines.Count == 0)
+ return;
+
+ if (this.Hilighter != null)
+ this.Hilighter.Reset();
+
+ Point pos = this.render.TextArea.TopLeft;
+ pos.X -= Src.X;
+
+ int endRow = Math.Min(this.LayoutLines.Count - 1, Src.Row + this.LineCountOnScreen - 1);
+
+ Size lineNumberSize = new Size(this.render.LineNemberWidth, this.render.TextArea.Height);
+
+ IPrintableTextRender render = (IPrintableTextRender)this.render;
+
+ //ヘッダーを印刷する
+ if (this.Header != null && this.Header != string.Empty)
+ {
+ this.render.DrawString(this.Header, pos.X, pos.Y, StringAlignment.Center,
+ new Size(render.TextArea.Width - this.GetRealtiveX(AreaType.TextArea),render.FooterHeight));
+
+ pos.Y += (int)render.HeaderHeight;
+ }
+
+ //レイアウト行を印刷する
+ for (int i = Src.Row; i <= endRow; i++)
+ {
+ double lineHeight = this.LayoutLines.GetLayout(i).Height;
+
+ this.render.DrawOneLine(this.LayoutLines,i, pos.X + this.render.TextArea.X, pos.Y, null);
+
+ if (this.DrawLineNumber)
+ this.render.DrawString((i + 1).ToString(), this.PageBound.X + this.GetRealtiveX(AreaType.LineNumberArea), pos.Y, StringAlignment.Right, lineNumberSize);
+
+ pos.Y += lineHeight;
+ }
+
+ //フッターを印刷する
+ if (this.Footer != null && this.Footer != string.Empty)
+ {
+ pos.Y = render.TextArea.Bottom;
+ this.render.DrawString(this.Footer, pos.X, pos.Y, StringAlignment.Center,
+ new Size(render.TextArea.Width - this.GetRealtiveX(AreaType.TextArea), render.FooterHeight));
+ }
+ }
+
+ public bool TryPageDown()
+ {
+ return base.TryScroll(this.Src.X, this.Src.Row + this.LineCountOnScreen);
+ }
+
+ protected override void CalculateClipRect()
+ {
+ double x, y, width, height;
+
+ if (this.DrawLineNumber)
+ {
+ if (this.render.RightToLeft)
+ x = this.Padding.Left;
+ else
+ x = this.render.LineNemberWidth + this.render.emSize.Width + this.Padding.Left + this.LineNumberMargin;
+ width = this.PageBound.Width - this.render.LineNemberWidth - this.render.emSize.Width - this.Padding.Right - this.Padding.Left - this.LineNumberMargin;
+ }
+ else
+ {
+ x = this.Padding.Left;
+ width = this.PageBound.Width - this.Padding.Right - this.Padding.Left;
+ }
+
+ y = this.Padding.Top;
+ height = this.PageBound.Height - this.Padding.Bottom - this.Padding.Top;
+
+ if (width < 0)
+ width = 0;
+
+ if (height < 0)
+ height = 0;
+
+ IPrintableTextRender render = (IPrintableTextRender)this.render;
+
+ if (this.Footer != null && this.Footer != string.Empty)
+ height -= render.FooterHeight;
+ if (this.Header != null && this.Header != string.Empty)
+ height -= render.HeaderHeight;
+
+ this.render.TextArea = new Rectangle(x, y, width, height);
+ }
+
+ public override void CalculateLineCountOnScreen()
+ {
+ if (this.LayoutLines.Count == 0)
+ return;
+
+ double y = 0;
+ int i = this.Src.Row;
+ for (; true; i++)
+ {
+ int row = i < this.LayoutLines.Count ? i : this.LayoutLines.Count - 1;
+
+ ITextLayout layout = this.LayoutLines.GetLayout(row);
+
+ double lineHeight = layout.Height;
+
+ y += lineHeight;
+
+ if (y >= this.render.TextArea.Height)
+ break;
+ }
+ this.LineCountOnScreen = Math.Max(i - this.Src.Row - 1, 0); //ループを抜けると+1されている
+ }
+
+ enum AreaType
+ {
+ LineNumberArea,
+ TextArea
+ }
+
+ double GetRealtiveX(AreaType type)
+ {
+ switch (type)
+ {
+ case AreaType.LineNumberArea:
+ if (this.DrawLineNumber == false)
+ throw new InvalidOperationException();
+ if (this.render.RightToLeft)
+ return this.PageBound.TopRight.X - this.render.LineNemberWidth;
+ else
+ return this.render.TextArea.X - this.render.LineNemberWidth - this.render.emSize.Width - this.LineNumberMargin;
+ case AreaType.TextArea:
+ return this.render.TextArea.X;
+ }
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+}
-/* https://github.com/mbuchetics/RangeTree よりコピペ。このファイルのみMITライセンスに従います */\r
-using System;\r
-using System.Collections.Generic;\r
-using System.Linq;\r
-using System.Text;\r
-using System.Threading.Tasks;\r
-\r
-namespace FooEditEngine\r
-{\r
- /// <summary>\r
- /// マーカーを表す\r
- /// </summary>\r
- internal interface IRange\r
- {\r
- /// <summary>\r
- /// マーカーの開始位置。-1を設定した場合、そのマーカーはレタリングされません\r
- /// </summary>\r
- int start { get; set; }\r
- /// <summary>\r
- /// マーカーの長さ。0を設定した場合、そのマーカーはレタリングされません\r
- /// </summary>\r
- int length { get; set; }\r
- }\r
-\r
- internal sealed class RangeCollection<T> : IEnumerable<T>\r
- where T : IRange\r
- {\r
- List<T> collection;\r
-\r
- public RangeCollection()\r
- : this(null)\r
- {\r
- }\r
-\r
- public RangeCollection(IEnumerable<T> collection)\r
- {\r
- if (collection == null)\r
- this.collection = new List<T>();\r
- else\r
- this.collection = new List<T>(collection);\r
- }\r
-\r
- public T this[int i]\r
- {\r
- get\r
- {\r
- return this.collection[i];\r
- }\r
- set\r
- {\r
- this.collection[i] = value;\r
- }\r
- }\r
-\r
- public int Count\r
- {\r
- get\r
- {\r
- return this.collection.Count;\r
- }\r
- }\r
-\r
- public void Add(T item)\r
- {\r
- this.collection.Add(item);\r
- for (int i = this.collection.Count - 1; i >= 0; i--)\r
- {\r
- if (i > 0 && this.collection[i].start < this.collection[i - 1].start)\r
- {\r
- T temp = this.collection[i];\r
- this.collection[i] = this.collection[i - 1];\r
- this.collection[i - 1] = temp;\r
- }\r
- else\r
- {\r
- break;\r
- }\r
- }\r
- }\r
-\r
- public void Remove(int start, int length)\r
- {\r
- if (this.collection.Count == 0)\r
- return;\r
-\r
- int at = this.IndexOf(start);\r
-\r
- int endAt = this.IndexOf(start + length - 1);\r
-\r
- if(at != -1 && endAt != -1)\r
- {\r
- for (int i = endAt; i >= at; i--)\r
- {\r
- this.collection.RemoveAt(i);\r
- }\r
- }\r
- else if (at != -1)\r
- {\r
- this.collection.RemoveAt(at);\r
- }\r
- else if(endAt != -1)\r
- {\r
- this.collection.RemoveAt(endAt);\r
- }\r
- }\r
-\r
- public void RemoveNearest(int start, int length)\r
- {\r
- if (this.collection.Count == 0)\r
- return;\r
- \r
- int nearAt;\r
- int at = this.IndexOfNearest(start, out nearAt);\r
- if (at == -1)\r
- at = nearAt;\r
- \r
- int nearEndAt;\r
- int endAt = this.IndexOfNearest(start + length - 1, out nearEndAt);\r
- if (endAt == -1)\r
- endAt = nearEndAt;\r
- \r
- int end = start + length - 1; \r
- for (int i = endAt; i >= at; i--)\r
- {\r
- int markerEnd = this.collection[i].start + this.collection[i].length - 1;\r
- if (this.collection[i].start >= start && markerEnd <= end ||\r
- markerEnd >= start && markerEnd <= end ||\r
- this.collection[i].start >= start && this.collection[i].start <= end ||\r
- this.collection[i].start < start && markerEnd > end)\r
- this.collection.RemoveAt(i);\r
- }\r
- }\r
-\r
- public void RemoveAt(int index)\r
- {\r
- this.collection.RemoveAt(index);\r
- }\r
-\r
- public int IndexOf(int start)\r
- {\r
- int dummy;\r
- return this.IndexOfNearest(start, out dummy);\r
- }\r
-\r
- int IndexOfNearest(int start,out int nearIndex)\r
- {\r
- nearIndex = -1;\r
- int left = 0, right = this.collection.Count - 1, mid;\r
- while (left <= right)\r
- {\r
- mid = (left + right) / 2;\r
- T item = this.collection[mid];\r
- if (start >= item.start && start < item.start + item.length)\r
- {\r
- return mid;\r
- }\r
- if (start < item.start)\r
- {\r
- right = mid - 1;\r
- }\r
- else\r
- {\r
- left = mid + 1;\r
- }\r
- }\r
- System.Diagnostics.Debug.Assert(left >= 0 || right >= 0);\r
- nearIndex = left >= 0 ? left : right;\r
- if (nearIndex > this.collection.Count - 1)\r
- nearIndex = right;\r
- return -1;\r
- }\r
-\r
- public IEnumerable<T> Get(int index)\r
- {\r
- int at = this.IndexOf(index);\r
- if (at == -1)\r
- yield break;\r
- yield return this.collection[at];\r
- }\r
-\r
- public IEnumerable<T> Get(int start, int length)\r
- {\r
- int nearAt;\r
- int at = this.IndexOfNearest(start,out nearAt);\r
- if (at == -1)\r
- at = nearAt;\r
-\r
- if (at == -1)\r
- yield break;\r
-\r
- int end = start + length - 1;\r
- for (int i = at; i < this.collection.Count; i++)\r
- {\r
- int markerEnd = this.collection[i].start + this.collection[i].length - 1;\r
- if (this.collection[i].start >= start && markerEnd <= end ||\r
- markerEnd >= start && markerEnd <= end ||\r
- this.collection[i].start >= start && this.collection[i].start <= end ||\r
- this.collection[i].start < start && markerEnd > end)\r
- yield return this.collection[i];\r
- else if (this.collection[i].start > start + length)\r
- yield break;\r
- }\r
- }\r
-\r
- public void Clear()\r
- {\r
- this.collection.Clear();\r
- }\r
-\r
- public IEnumerator<T> GetEnumerator()\r
- {\r
- foreach (T item in this.collection)\r
- yield return item;\r
- }\r
-\r
- System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()\r
- {\r
- throw new NotImplementedException();\r
- }\r
- }\r
-\r
-}\r
+/* https://github.com/mbuchetics/RangeTree よりコピペ。このファイルのみMITライセンスに従います */
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace FooEditEngine
+{
+ /// <summary>
+ /// マーカーを表す
+ /// </summary>
+ internal interface IRange
+ {
+ /// <summary>
+ /// マーカーの開始位置。-1を設定した場合、そのマーカーはレタリングされません
+ /// </summary>
+ int start { get; set; }
+ /// <summary>
+ /// マーカーの長さ。0を設定した場合、そのマーカーはレタリングされません
+ /// </summary>
+ int length { get; set; }
+ }
+
+ internal sealed class RangeCollection<T> : IEnumerable<T>
+ where T : IRange
+ {
+ List<T> collection;
+
+ public RangeCollection()
+ : this(null)
+ {
+ }
+
+ public RangeCollection(IEnumerable<T> collection)
+ {
+ if (collection == null)
+ this.collection = new List<T>();
+ else
+ this.collection = new List<T>(collection);
+ }
+
+ public T this[int i]
+ {
+ get
+ {
+ return this.collection[i];
+ }
+ set
+ {
+ this.collection[i] = value;
+ }
+ }
+
+ public int Count
+ {
+ get
+ {
+ return this.collection.Count;
+ }
+ }
+
+ public void Add(T item)
+ {
+ this.collection.Add(item);
+ for (int i = this.collection.Count - 1; i >= 0; i--)
+ {
+ if (i > 0 && this.collection[i].start < this.collection[i - 1].start)
+ {
+ T temp = this.collection[i];
+ this.collection[i] = this.collection[i - 1];
+ this.collection[i - 1] = temp;
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+ public void Remove(int start, int length)
+ {
+ if (this.collection.Count == 0)
+ return;
+
+ int at = this.IndexOf(start);
+
+ int endAt = this.IndexOf(start + length - 1);
+
+ if(at != -1 && endAt != -1)
+ {
+ for (int i = endAt; i >= at; i--)
+ {
+ this.collection.RemoveAt(i);
+ }
+ }
+ else if (at != -1)
+ {
+ this.collection.RemoveAt(at);
+ }
+ else if(endAt != -1)
+ {
+ this.collection.RemoveAt(endAt);
+ }
+ }
+
+ public void RemoveNearest(int start, int length)
+ {
+ if (this.collection.Count == 0)
+ return;
+
+ int nearAt;
+ int at = this.IndexOfNearest(start, out nearAt);
+ if (at == -1)
+ at = nearAt;
+
+ int nearEndAt;
+ int endAt = this.IndexOfNearest(start + length - 1, out nearEndAt);
+ if (endAt == -1)
+ endAt = nearEndAt;
+
+ int end = start + length - 1;
+ for (int i = endAt; i >= at; i--)
+ {
+ int markerEnd = this.collection[i].start + this.collection[i].length - 1;
+ if (this.collection[i].start >= start && markerEnd <= end ||
+ markerEnd >= start && markerEnd <= end ||
+ this.collection[i].start >= start && this.collection[i].start <= end ||
+ this.collection[i].start < start && markerEnd > end)
+ this.collection.RemoveAt(i);
+ }
+ }
+
+ public void RemoveAt(int index)
+ {
+ this.collection.RemoveAt(index);
+ }
+
+ public int IndexOf(int start)
+ {
+ int dummy;
+ return this.IndexOfNearest(start, out dummy);
+ }
+
+ int IndexOfNearest(int start,out int nearIndex)
+ {
+ nearIndex = -1;
+ int left = 0, right = this.collection.Count - 1, mid;
+ while (left <= right)
+ {
+ mid = (left + right) / 2;
+ T item = this.collection[mid];
+ if (start >= item.start && start < item.start + item.length)
+ {
+ return mid;
+ }
+ if (start < item.start)
+ {
+ right = mid - 1;
+ }
+ else
+ {
+ left = mid + 1;
+ }
+ }
+ System.Diagnostics.Debug.Assert(left >= 0 || right >= 0);
+ nearIndex = left >= 0 ? left : right;
+ if (nearIndex > this.collection.Count - 1)
+ nearIndex = right;
+ return -1;
+ }
+
+ public IEnumerable<T> Get(int index)
+ {
+ int at = this.IndexOf(index);
+ if (at == -1)
+ yield break;
+ yield return this.collection[at];
+ }
+
+ public IEnumerable<T> Get(int start, int length)
+ {
+ int nearAt;
+ int at = this.IndexOfNearest(start,out nearAt);
+ if (at == -1)
+ at = nearAt;
+
+ if (at == -1)
+ yield break;
+
+ int end = start + length - 1;
+ for (int i = at; i < this.collection.Count; i++)
+ {
+ int markerEnd = this.collection[i].start + this.collection[i].length - 1;
+ if (this.collection[i].start >= start && markerEnd <= end ||
+ markerEnd >= start && markerEnd <= end ||
+ this.collection[i].start >= start && this.collection[i].start <= end ||
+ this.collection[i].start < start && markerEnd > end)
+ yield return this.collection[i];
+ else if (this.collection[i].start > start + length)
+ yield break;
+ }
+ }
+
+ public void Clear()
+ {
+ this.collection.Clear();
+ }
+
+ public IEnumerator<T> GetEnumerator()
+ {
+ foreach (T item in this.collection)
+ yield return item;
+ }
+
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+}
-/*\r
- * Copyright (C) 2013 FooProject\r
- * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.\r
-\r
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of \r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\r
-\r
-You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.\r
- */\r
-using System;\r
-using System.Collections.Generic;\r
-using System.Linq;\r
-using System.Text;\r
-\r
-namespace FooEditEngine\r
-{\r
- class ResourceManager<TKey, TValue> : Dictionary<TKey, TValue>\r
- {\r
- /// <summary>\r
- /// 任意のキーに関連付けられている値を取得・設定する\r
- /// </summary>\r
- /// <param name="key">キー</param>\r
- /// <returns>関連付けられている値</returns>\r
- public new TValue this[TKey key]\r
- {\r
- get\r
- {\r
- return base[key];\r
- }\r
- set\r
- {\r
- if (value is IDisposable && base.ContainsKey(key))\r
- ((IDisposable)base[key]).Dispose();\r
- base[key] = value;\r
- }\r
- }\r
- /// <summary>\r
- /// 任意のキーに関連づけられてる値を削除する\r
- /// </summary>\r
- /// <param name="key">キー</param>\r
- /// <returns>IDispseableを継承している場合、Dispose()が呼び出されます</returns>\r
- public new bool Remove(TKey key)\r
- {\r
- TValue value;\r
- bool result = base.TryGetValue(key, out value);\r
- if (value is IDisposable)\r
- ((IDisposable)value).Dispose();\r
- if (result)\r
- base.Remove(key);\r
- return result;\r
- }\r
- /// <summary>\r
- /// すべて削除する\r
- /// </summary>\r
- /// <remarks>IDispseableを継承している場合、Dispose()が呼び出されます</remarks>\r
- public new void Clear()\r
- {\r
- if (this.Count == 0)\r
- return;\r
- TValue first = this.Values.First();\r
- if (first is IDisposable)\r
- {\r
- foreach (IDisposable v in this.Values)\r
- v.Dispose();\r
- }\r
- base.Clear();\r
- }\r
- }\r
-}\r
+/*
+ * Copyright (C) 2013 FooProject
+ * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace FooEditEngine
+{
+ class ResourceManager<TKey, TValue> : Dictionary<TKey, TValue>
+ {
+ /// <summary>
+ /// 任意のキーに関連付けられている値を取得・設定する
+ /// </summary>
+ /// <param name="key">キー</param>
+ /// <returns>関連付けられている値</returns>
+ public new TValue this[TKey key]
+ {
+ get
+ {
+ return base[key];
+ }
+ set
+ {
+ if (value is IDisposable && base.ContainsKey(key))
+ ((IDisposable)base[key]).Dispose();
+ base[key] = value;
+ }
+ }
+ /// <summary>
+ /// 任意のキーに関連づけられてる値を削除する
+ /// </summary>
+ /// <param name="key">キー</param>
+ /// <returns>IDispseableを継承している場合、Dispose()が呼び出されます</returns>
+ public new bool Remove(TKey key)
+ {
+ TValue value;
+ bool result = base.TryGetValue(key, out value);
+ if (value is IDisposable)
+ ((IDisposable)value).Dispose();
+ if (result)
+ base.Remove(key);
+ return result;
+ }
+ /// <summary>
+ /// すべて削除する
+ /// </summary>
+ /// <remarks>IDispseableを継承している場合、Dispose()が呼び出されます</remarks>
+ public new void Clear()
+ {
+ if (this.Count == 0)
+ return;
+ TValue first = this.Values.First();
+ if (first is IDisposable)
+ {
+ foreach (IDisposable v in this.Values)
+ v.Dispose();
+ }
+ base.Clear();
+ }
+ }
+}
-/*\r
- * Copyright (C) 2013 FooProject\r
- * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.\r
-\r
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of \r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\r
-\r
-You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.\r
- */\r
-using System;\r
-using System.Collections.Generic;\r
-\r
-namespace FooEditEngine\r
-{\r
- /// <summary>\r
- /// 選択領域を表すクラス\r
- /// </summary>\r
- struct Selection : IRange,IEqualityComparer<Selection>\r
- {\r
- public int start\r
- {\r
- get;\r
- set;\r
- }\r
-\r
- public int length\r
- {\r
- get;\r
- set;\r
- }\r
-\r
- public static Selection Create(int start, int length)\r
- {\r
- return new Selection { start = start, length = length};\r
- }\r
-\r
- public bool Equals(Selection x, Selection y)\r
- {\r
- return x.length == y.length && x.start == y.start;\r
- }\r
-\r
- public int GetHashCode(Selection obj)\r
- {\r
- return this.start ^ this.length;\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// 選択範囲が更新されたことを通知するデリゲート\r
- /// </summary>\r
- /// <param name="sender">送信元クラス</param>\r
- /// <param name="e">イベントデータ</param>\r
- public delegate void SelectChangeEventHandler(object sender,EventArgs e);\r
-\r
- /// <summary>\r
- /// 選択範囲を格納するコレクションを表します\r
- /// </summary>\r
- sealed class SelectCollection : IEnumerable<Selection>\r
- {\r
- RangeCollection<Selection> collection;\r
-\r
- /// <summary>\r
- /// コンストラクター\r
- /// </summary>\r
- public SelectCollection()\r
- : this(null)\r
- {\r
- }\r
-\r
- /// <summary>\r
- /// コンストラクター\r
- /// </summary>\r
- /// <param name="selections">コレクションを表します</param>\r
- public SelectCollection(IEnumerable<Selection> selections)\r
- {\r
- if (selections != null)\r
- collection = new RangeCollection<Selection>(selections);\r
- else\r
- collection = new RangeCollection<Selection>();\r
- this.SelectChange += new SelectChangeEventHandler((s,e)=>{});\r
- }\r
-\r
- /// <summary>\r
- /// 選択領域が更新されたことを通知します\r
- /// </summary>\r
- public event SelectChangeEventHandler SelectChange;\r
-\r
- /// <summary>\r
- /// インデクサー\r
- /// </summary>\r
- /// <param name="i">0から始まるインデックス</param>\r
- /// <returns>選択領域を返します</returns>\r
- public Selection this[int i]\r
- {\r
- get\r
- {\r
- return this.collection[i];\r
- }\r
- set\r
- {\r
- this.collection[i] = value;\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// 追加します\r
- /// </summary>\r
- /// <param name="sel">選択領域</param>\r
- public void Add(Selection sel)\r
- {\r
- this.collection.Add(sel);\r
- this.SelectChange(this, null);\r
- }\r
-\r
- /// <summary>\r
- /// すべて削除します\r
- /// </summary>\r
- public void Clear()\r
- {\r
- this.collection.Clear();\r
- this.SelectChange(this, null);\r
- }\r
-\r
- /// <summary>\r
- /// 要素を取得します\r
- /// </summary>\r
- /// <param name="index">インデックス</param>\r
- /// <param name="length">長さ</param>\r
- /// <returns>要素を表すイテレーター</returns>\r
- public IEnumerable<Selection> Get(int index, int length)\r
- {\r
- return this.collection.Get(index, length);\r
- }\r
-\r
- /// <summary>\r
- /// 格納されている選択領域の数を返します\r
- /// </summary>\r
- public int Count\r
- {\r
- get\r
- {\r
- return this.collection.Count;\r
- }\r
- }\r
-\r
- #region IEnumerable<Selection> メンバー\r
-\r
- /// <summary>\r
- /// 列挙子を返します\r
- /// </summary>\r
- /// <returns>IEnumeratorオブジェクトを返す</returns>\r
- public IEnumerator<Selection> GetEnumerator()\r
- {\r
- for (int i = 0; i < this.collection.Count; i++)\r
- yield return this.collection[i];\r
- }\r
-\r
- #endregion\r
-\r
- #region IEnumerable メンバー\r
-\r
- System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()\r
- {\r
- throw new NotImplementedException();\r
- }\r
-\r
- #endregion\r
- }\r
-}\r
+/*
+ * Copyright (C) 2013 FooProject
+ * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+using System.Collections.Generic;
+
+namespace FooEditEngine
+{
+ /// <summary>
+ /// 選択領域を表すクラス
+ /// </summary>
+ struct Selection : IRange,IEqualityComparer<Selection>
+ {
+ public int start
+ {
+ get;
+ set;
+ }
+
+ public int length
+ {
+ get;
+ set;
+ }
+
+ public static Selection Create(int start, int length)
+ {
+ return new Selection { start = start, length = length};
+ }
+
+ public bool Equals(Selection x, Selection y)
+ {
+ return x.length == y.length && x.start == y.start;
+ }
+
+ public int GetHashCode(Selection obj)
+ {
+ return this.start ^ this.length;
+ }
+ }
+
+ /// <summary>
+ /// 選択範囲が更新されたことを通知するデリゲート
+ /// </summary>
+ /// <param name="sender">送信元クラス</param>
+ /// <param name="e">イベントデータ</param>
+ public delegate void SelectChangeEventHandler(object sender,EventArgs e);
+
+ /// <summary>
+ /// 選択範囲を格納するコレクションを表します
+ /// </summary>
+ sealed class SelectCollection : IEnumerable<Selection>
+ {
+ RangeCollection<Selection> collection;
+
+ /// <summary>
+ /// コンストラクター
+ /// </summary>
+ public SelectCollection()
+ : this(null)
+ {
+ }
+
+ /// <summary>
+ /// コンストラクター
+ /// </summary>
+ /// <param name="selections">コレクションを表します</param>
+ public SelectCollection(IEnumerable<Selection> selections)
+ {
+ if (selections != null)
+ collection = new RangeCollection<Selection>(selections);
+ else
+ collection = new RangeCollection<Selection>();
+ this.SelectChange += new SelectChangeEventHandler((s,e)=>{});
+ }
+
+ /// <summary>
+ /// 選択領域が更新されたことを通知します
+ /// </summary>
+ public event SelectChangeEventHandler SelectChange;
+
+ /// <summary>
+ /// インデクサー
+ /// </summary>
+ /// <param name="i">0から始まるインデックス</param>
+ /// <returns>選択領域を返します</returns>
+ public Selection this[int i]
+ {
+ get
+ {
+ return this.collection[i];
+ }
+ set
+ {
+ this.collection[i] = value;
+ }
+ }
+
+ /// <summary>
+ /// 追加します
+ /// </summary>
+ /// <param name="sel">選択領域</param>
+ public void Add(Selection sel)
+ {
+ this.collection.Add(sel);
+ this.SelectChange(this, null);
+ }
+
+ /// <summary>
+ /// すべて削除します
+ /// </summary>
+ public void Clear()
+ {
+ this.collection.Clear();
+ this.SelectChange(this, null);
+ }
+
+ /// <summary>
+ /// 要素を取得します
+ /// </summary>
+ /// <param name="index">インデックス</param>
+ /// <param name="length">長さ</param>
+ /// <returns>要素を表すイテレーター</returns>
+ public IEnumerable<Selection> Get(int index, int length)
+ {
+ return this.collection.Get(index, length);
+ }
+
+ /// <summary>
+ /// 格納されている選択領域の数を返します
+ /// </summary>
+ public int Count
+ {
+ get
+ {
+ return this.collection.Count;
+ }
+ }
+
+ #region IEnumerable<Selection> メンバー
+
+ /// <summary>
+ /// 列挙子を返します
+ /// </summary>
+ /// <returns>IEnumeratorオブジェクトを返す</returns>
+ public IEnumerator<Selection> GetEnumerator()
+ {
+ for (int i = 0; i < this.collection.Count; i++)
+ yield return this.collection[i];
+ }
+
+ #endregion
+
+ #region IEnumerable メンバー
+
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+ {
+ throw new NotImplementedException();
+ }
+
+ #endregion
+ }
+}
-/*\r
- * Copyright (C) 2013 FooProject\r
- * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.\r
-\r
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of \r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\r
-\r
-You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.\r
- */\r
-using System;\r
-using System.Collections.Generic;\r
-using System.Globalization;\r
-using System.Linq;\r
-using System.Text;\r
-using System.Text.RegularExpressions;\r
-using System.Threading;\r
-using System.Threading.Tasks;\r
-using Slusser.Collections.Generic;\r
-\r
-namespace FooEditEngine\r
-{\r
- /// <summary>\r
- /// ランダムアクセス可能な列挙子を提供するインターフェイス\r
- /// </summary>\r
- /// <typeparam name="T"></typeparam>\r
- public interface IRandomEnumrator<T>\r
- {\r
- /// <summary>\r
- /// インデクサーを表す\r
- /// </summary>\r
- /// <param name="index">インデックス</param>\r
- /// <returns>Tを返す</returns>\r
- T this[int index]{get;}\r
- }\r
-\r
- sealed class StringBuffer : IEnumerable<char>, IRandomEnumrator<char>\r
- {\r
- GapBuffer<char> buf = new GapBuffer<char>();\r
-\r
- public StringBuffer()\r
- {\r
- this.Update = (s, e) => { };\r
- }\r
-\r
- public StringBuffer(StringBuffer buffer)\r
- : this()\r
- {\r
- buf.AddRange(buffer.buf, buffer.Length);\r
- }\r
-\r
- public char this[int index]\r
- {\r
- get\r
- {\r
- char c = buf[index];\r
- return c;\r
- }\r
- }\r
-\r
- public string ToString(int index, int length)\r
- {\r
- StringBuilder temp = new StringBuilder();\r
- temp.Clear();\r
- for (int i = index; i < index + length; i++)\r
- temp.Append(buf[i]);\r
- return temp.ToString();\r
- }\r
-\r
- public IEnumerable<string> GetLines(int startIndex, int endIndex, int maxCharCount = -1)\r
- {\r
- foreach (Tuple<int, int> range in this.ForEachLines(startIndex, endIndex, maxCharCount))\r
- {\r
- StringBuilder temp = new StringBuilder();\r
- temp.Clear();\r
- int lineEndIndex = range.Item1;\r
- if (range.Item2 > 0)\r
- lineEndIndex += range.Item2 - 1;\r
- for (int i = range.Item1; i <= lineEndIndex; i++)\r
- temp.Append(buf[i]);\r
- yield return temp.ToString();\r
- }\r
- }\r
-\r
- public IEnumerable<Tuple<int,int>> ForEachLines(int startIndex, int endIndex, int maxCharCount = -1)\r
- {\r
- int currentLineHeadIndex = startIndex;\r
- int currentLineLength = 0;\r
- \r
- for (int i = startIndex; i <= endIndex; i++)\r
- {\r
- currentLineLength++;\r
- char c = this.buf[i];\r
- if (c == Document.NewLine ||\r
- (maxCharCount != -1 && currentLineLength >= maxCharCount))\r
- {\r
- UnicodeCategory uc = CharUnicodeInfo.GetUnicodeCategory(c);\r
- if (uc != UnicodeCategory.NonSpacingMark &&\r
- uc != UnicodeCategory.SpacingCombiningMark &&\r
- uc != UnicodeCategory.EnclosingMark &&\r
- uc != UnicodeCategory.Surrogate)\r
- {\r
- yield return new Tuple<int,int>(currentLineHeadIndex, currentLineLength);\r
- currentLineHeadIndex += currentLineLength;\r
- currentLineLength = 0;\r
- }\r
- }\r
- }\r
- if (currentLineLength > 0)\r
- yield return new Tuple<int, int>(currentLineHeadIndex, currentLineLength);\r
- }\r
- \r
- public int Length\r
- {\r
- get { return this.buf.Count; }\r
- }\r
-\r
- internal DocumentUpdateEventHandler Update;\r
-\r
- internal void Replace(StringBuffer buf)\r
- {\r
- this.Replace(buf.buf);\r
- }\r
-\r
- internal void Replace(GapBuffer<char> buf)\r
- {\r
- this.Clear();\r
- this.buf = buf;\r
- this.Update(this, new DocumentUpdateEventArgs(UpdateType.Replace, 0, 0, buf.Count));\r
- }\r
-\r
- internal void Replace(int index, int length, IEnumerable<char> chars,int count)\r
- {\r
- if (length > 0)\r
- this.buf.RemoveRange(index, length);\r
- this.buf.InsertRange(index, chars,count);\r
- this.Update(this, new DocumentUpdateEventArgs(UpdateType.Replace, index, length, count));\r
- }\r
-\r
- internal async Task LoadAsync(IStreamReader fs, CancellationTokenSource tokenSource = null)\r
- {\r
- char[] str = new char[1024 * 256];\r
- int readCount;\r
- do\r
- {\r
- int index = this.Length;\r
- if (index < 0)\r
- index = 0;\r
-\r
- readCount = await fs.ReadAsync(str, 0, str.Length).ConfigureAwait(false);\r
- \r
- //内部形式に変換する\r
- var internal_str = from s in str where s != '\r' && s != '\0' select s;\r
-\r
- //str.lengthは事前に確保しておくために使用するので影響はない\r
- this.buf.InsertRange(index, internal_str, str.Length);\r
-\r
- if (tokenSource != null)\r
- tokenSource.Token.ThrowIfCancellationRequested();\r
-#if TEST_ASYNC\r
- System.Threading.Thread.Sleep(10);\r
-#endif\r
- Array.Clear(str, 0, str.Length);\r
- } while (readCount > 0);\r
- this.Update(this, new DocumentUpdateEventArgs(UpdateType.Clear, -1, -1, -1));\r
- this.Update(this, new DocumentUpdateEventArgs(UpdateType.Replace, 0, 0, buf.Count));\r
- }\r
-\r
- internal void ReplaceRegexAll(LineToIndexTable layoutlines, Regex regex, string pattern, bool groupReplace)\r
- {\r
- for (int i = 0; i < layoutlines.Count; i++)\r
- {\r
- int lineHeadIndex = layoutlines.GetIndexFromLineNumber(i), lineLength = layoutlines.GetLengthFromLineNumber(i);\r
- int left = lineHeadIndex, right = lineHeadIndex;\r
- string output = regex.Replace(layoutlines[i], (m) => {\r
- if (groupReplace)\r
- return m.Result(pattern);\r
- else\r
- return pattern;\r
- });\r
- this.buf.RemoveRange(lineHeadIndex, lineLength);\r
- this.buf.InsertRange(lineHeadIndex, output, output.Length);\r
- this.Update(this, new DocumentUpdateEventArgs(UpdateType.Replace, lineHeadIndex, lineLength, output.Length, i));\r
- }\r
- }\r
-\r
- internal void ReplaceAll(LineToIndexTable layoutlines,string target, string pattern, bool ci = false)\r
- {\r
- TextSearch ts = new TextSearch(target, ci);\r
- char[] pattern_chars = pattern.ToCharArray();\r
- for(int i = 0; i < layoutlines.Count; i++)\r
- {\r
- int lineHeadIndex = layoutlines.GetIndexFromLineNumber(i), lineLength = layoutlines.GetLengthFromLineNumber(i);\r
- int left = lineHeadIndex, right = lineHeadIndex;\r
- int newLineLength = lineLength;\r
- while ((right = ts.IndexOf(this.buf, left, lineHeadIndex + newLineLength)) != -1)\r
- {\r
- this.buf.RemoveRange(right, target.Length);\r
- this.buf.InsertRange(right, pattern_chars, pattern.Length);\r
- left = right + pattern.Length;\r
- newLineLength += pattern.Length - target.Length;\r
- }\r
- this.Update(this, new DocumentUpdateEventArgs(UpdateType.Replace, lineHeadIndex, lineLength, newLineLength, i));\r
- }\r
- }\r
-\r
- internal int IndexOf(string target, int start,bool ci = false)\r
- {\r
- TextSearch ts = new TextSearch(target,ci);\r
- return ts.IndexOf(this.buf, start,this.buf.Count);\r
- }\r
-\r
- /// <summary>\r
- /// 文字列を削除する\r
- /// </summary>\r
- internal void Clear()\r
- {\r
- this.buf.Clear();\r
- this.Update(this, new DocumentUpdateEventArgs(UpdateType.Clear, 0, this.buf.Count,0));\r
- }\r
-\r
- internal IEnumerable<char> GetEnumerator(int start, int length)\r
- {\r
- for (int i = start; i < start + length; i++)\r
- yield return this.buf[i];\r
- }\r
-\r
- #region IEnumerable<char> メンバー\r
-\r
- public IEnumerator<char> GetEnumerator()\r
- {\r
- for (int i = 0; i < this.Length; i++)\r
- yield return this.buf[i];\r
- }\r
-\r
- #endregion\r
-\r
- #region IEnumerable メンバー\r
-\r
- System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()\r
- {\r
- for (int i = 0; i < this.Length; i++)\r
- yield return this[i];\r
- }\r
-\r
- #endregion\r
- }\r
-\r
- sealed class TextSearch\r
- {\r
- char[] pattern;\r
- int patternLength;\r
- Dictionary<char, int> qsTable = new Dictionary<char, int>();\r
- bool caseInsenstive;\r
- public TextSearch(string pattern,bool ci = false)\r
- {\r
- this.patternLength = pattern.Length;\r
- this.caseInsenstive = ci;\r
- if (ci)\r
- {\r
- this.CreateQSTable(pattern.ToLower());\r
- this.CreateQSTable(pattern.ToUpper());\r
- this.pattern = new char[pattern.Length];\r
- for (int i = 0; i < pattern.Length; i++)\r
- this.pattern[i] = CharTool.ToUpperFastIf(pattern[i]);\r
- }\r
- else\r
- {\r
- this.CreateQSTable(pattern);\r
- this.pattern = pattern.ToCharArray();\r
- }\r
- }\r
- void CreateQSTable(string pattern)\r
- {\r
- int len = pattern.Length;\r
- for (int i = 0; i < len; i++)\r
- {\r
- if (!this.qsTable.ContainsKey(pattern[i]))\r
- this.qsTable.Add(pattern[i], len - i);\r
- else\r
- this.qsTable[pattern[i]] = len - i;\r
- }\r
- }\r
- public int IndexOf(GapBuffer<char> buf, int start,int end)\r
- {\r
- //QuickSearch法\r
- int buflen = buf.Count - 1;\r
- int plen = this.patternLength;\r
- int i = start;\r
- int search_end = end - plen;\r
- //最適化のためわざとコピペした\r
- if (this.caseInsenstive)\r
- {\r
- while (i <= search_end)\r
- {\r
- int j = 0;\r
- while (j < plen)\r
- {\r
- if (CharTool.ToUpperFastIf(buf[i + j]) != this.pattern[j])\r
- break;\r
- j++;\r
- }\r
- if (j == plen)\r
- {\r
- return i;\r
- }\r
- else\r
- {\r
- int k = i + plen;\r
- if (k <= buflen) //buffer以降にアクセスする可能性がある\r
- {\r
- int moveDelta;\r
- if (this.qsTable.TryGetValue(buf[k], out moveDelta))\r
- i += moveDelta;\r
- else\r
- i += plen;\r
- }\r
- else\r
- {\r
- break;\r
- }\r
- }\r
- }\r
-\r
- }\r
- else\r
- {\r
- while (i <= search_end)\r
- {\r
- int j = 0;\r
- while (j < plen)\r
- {\r
- if (buf[i + j] != this.pattern[j])\r
- break;\r
- j++;\r
- }\r
- if (j == plen)\r
- {\r
- return i;\r
- }\r
- else\r
- {\r
- int k = i + plen;\r
- if (k <= buflen) //buffer以降にアクセスする可能性がある\r
- {\r
- int moveDelta;\r
- if (this.qsTable.TryGetValue(buf[k], out moveDelta))\r
- i += moveDelta;\r
- else\r
- i += plen;\r
- }\r
- else\r
- {\r
- break;\r
- }\r
- }\r
- }\r
- }\r
- return -1;\r
- }\r
- }\r
- static class CharTool\r
- {\r
- /// <summary>\r
- /// Converts characters to lowercase.\r
- /// </summary>\r
- const string _lookupStringL =\r
- "---------------------------------!-#$%&-()*+,-./0123456789:;<=>?@abcdefghijklmnopqrstuvwxyz[-]^_`abcdefghijklmnopqrstuvwxyz{|}~-";\r
-\r
- /// <summary>\r
- /// Converts characters to uppercase.\r
- /// </summary>\r
- const string _lookupStringU =\r
- "---------------------------------!-#$%&-()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[-]^_`ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~-";\r
-\r
- /// <summary>\r
- /// Get lowercase version of this ASCII character.\r
- /// </summary>\r
- public static char ToLower(char c)\r
- {\r
- return _lookupStringL[c];\r
- }\r
-\r
- /// <summary>\r
- /// Get uppercase version of this ASCII character.\r
- /// </summary>\r
- public static char ToUpper(char c)\r
- {\r
- return _lookupStringU[c];\r
- }\r
-\r
- /// <summary>\r
- /// Translate uppercase ASCII characters to lowercase.\r
- /// </summary>\r
- public static char ToLowerFastIf(char c)\r
- {\r
- if (c >= 'A' && c <= 'Z')\r
- {\r
- return (char)(c + 32);\r
- }\r
- else\r
- {\r
- return c;\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// Translate lowercase ASCII characters to uppercase.\r
- /// </summary>\r
- public static char ToUpperFastIf(char c)\r
- {\r
- if (c >= 'a' && c <= 'z')\r
- {\r
- return (char)(c - 32);\r
- }\r
- else\r
- {\r
- return c;\r
- }\r
- }\r
- }\r
+/*
+ * Copyright (C) 2013 FooProject
+ * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading;
+using System.Threading.Tasks;
+using Slusser.Collections.Generic;
+
+namespace FooEditEngine
+{
+ /// <summary>
+ /// ランダムアクセス可能な列挙子を提供するインターフェイス
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ public interface IRandomEnumrator<T>
+ {
+ /// <summary>
+ /// インデクサーを表す
+ /// </summary>
+ /// <param name="index">インデックス</param>
+ /// <returns>Tを返す</returns>
+ T this[int index]{get;}
+ }
+
+ sealed class StringBuffer : IEnumerable<char>, IRandomEnumrator<char>
+ {
+ GapBuffer<char> buf = new GapBuffer<char>();
+
+ public StringBuffer()
+ {
+ this.Update = (s, e) => { };
+ }
+
+ public StringBuffer(StringBuffer buffer)
+ : this()
+ {
+ buf.AddRange(buffer.buf, buffer.Length);
+ }
+
+ public char this[int index]
+ {
+ get
+ {
+ char c = buf[index];
+ return c;
+ }
+ }
+
+ public string ToString(int index, int length)
+ {
+ StringBuilder temp = new StringBuilder();
+ temp.Clear();
+ for (int i = index; i < index + length; i++)
+ temp.Append(buf[i]);
+ return temp.ToString();
+ }
+
+ public IEnumerable<string> GetLines(int startIndex, int endIndex, int maxCharCount = -1)
+ {
+ foreach (Tuple<int, int> range in this.ForEachLines(startIndex, endIndex, maxCharCount))
+ {
+ StringBuilder temp = new StringBuilder();
+ temp.Clear();
+ int lineEndIndex = range.Item1;
+ if (range.Item2 > 0)
+ lineEndIndex += range.Item2 - 1;
+ for (int i = range.Item1; i <= lineEndIndex; i++)
+ temp.Append(buf[i]);
+ yield return temp.ToString();
+ }
+ }
+
+ public IEnumerable<Tuple<int,int>> ForEachLines(int startIndex, int endIndex, int maxCharCount = -1)
+ {
+ int currentLineHeadIndex = startIndex;
+ int currentLineLength = 0;
+
+ for (int i = startIndex; i <= endIndex; i++)
+ {
+ currentLineLength++;
+ char c = this.buf[i];
+ if (c == Document.NewLine ||
+ (maxCharCount != -1 && currentLineLength >= maxCharCount))
+ {
+ UnicodeCategory uc = CharUnicodeInfo.GetUnicodeCategory(c);
+ if (uc != UnicodeCategory.NonSpacingMark &&
+ uc != UnicodeCategory.SpacingCombiningMark &&
+ uc != UnicodeCategory.EnclosingMark &&
+ uc != UnicodeCategory.Surrogate)
+ {
+ yield return new Tuple<int,int>(currentLineHeadIndex, currentLineLength);
+ currentLineHeadIndex += currentLineLength;
+ currentLineLength = 0;
+ }
+ }
+ }
+ if (currentLineLength > 0)
+ yield return new Tuple<int, int>(currentLineHeadIndex, currentLineLength);
+ }
+
+ public int Length
+ {
+ get { return this.buf.Count; }
+ }
+
+ internal DocumentUpdateEventHandler Update;
+
+ internal void Replace(StringBuffer buf)
+ {
+ this.Replace(buf.buf);
+ }
+
+ internal void Replace(GapBuffer<char> buf)
+ {
+ this.Clear();
+ this.buf = buf;
+ this.Update(this, new DocumentUpdateEventArgs(UpdateType.Replace, 0, 0, buf.Count));
+ }
+
+ internal void Replace(int index, int length, IEnumerable<char> chars,int count)
+ {
+ if (length > 0)
+ this.buf.RemoveRange(index, length);
+ this.buf.InsertRange(index, chars,count);
+ this.Update(this, new DocumentUpdateEventArgs(UpdateType.Replace, index, length, count));
+ }
+
+ internal async Task LoadAsync(IStreamReader fs, CancellationTokenSource tokenSource = null)
+ {
+ char[] str = new char[1024 * 256];
+ int readCount;
+ do
+ {
+ int index = this.Length;
+ if (index < 0)
+ index = 0;
+
+ readCount = await fs.ReadAsync(str, 0, str.Length).ConfigureAwait(false);
+
+ //内部形式に変換する
+ var internal_str = from s in str where s != '\r' && s != '\0' select s;
+
+ //str.lengthは事前に確保しておくために使用するので影響はない
+ this.buf.InsertRange(index, internal_str, str.Length);
+
+ if (tokenSource != null)
+ tokenSource.Token.ThrowIfCancellationRequested();
+#if TEST_ASYNC
+ System.Threading.Thread.Sleep(10);
+#endif
+ Array.Clear(str, 0, str.Length);
+ } while (readCount > 0);
+ this.Update(this, new DocumentUpdateEventArgs(UpdateType.Clear, -1, -1, -1));
+ this.Update(this, new DocumentUpdateEventArgs(UpdateType.Replace, 0, 0, buf.Count));
+ }
+
+ internal void ReplaceRegexAll(LineToIndexTable layoutlines, Regex regex, string pattern, bool groupReplace)
+ {
+ for (int i = 0; i < layoutlines.Count; i++)
+ {
+ int lineHeadIndex = layoutlines.GetIndexFromLineNumber(i), lineLength = layoutlines.GetLengthFromLineNumber(i);
+ int left = lineHeadIndex, right = lineHeadIndex;
+ string output = regex.Replace(layoutlines[i], (m) => {
+ if (groupReplace)
+ return m.Result(pattern);
+ else
+ return pattern;
+ });
+ this.buf.RemoveRange(lineHeadIndex, lineLength);
+ this.buf.InsertRange(lineHeadIndex, output, output.Length);
+ this.Update(this, new DocumentUpdateEventArgs(UpdateType.Replace, lineHeadIndex, lineLength, output.Length, i));
+ }
+ }
+
+ internal void ReplaceAll(LineToIndexTable layoutlines,string target, string pattern, bool ci = false)
+ {
+ TextSearch ts = new TextSearch(target, ci);
+ char[] pattern_chars = pattern.ToCharArray();
+ for(int i = 0; i < layoutlines.Count; i++)
+ {
+ int lineHeadIndex = layoutlines.GetIndexFromLineNumber(i), lineLength = layoutlines.GetLengthFromLineNumber(i);
+ int left = lineHeadIndex, right = lineHeadIndex;
+ int newLineLength = lineLength;
+ while ((right = ts.IndexOf(this.buf, left, lineHeadIndex + newLineLength)) != -1)
+ {
+ this.buf.RemoveRange(right, target.Length);
+ this.buf.InsertRange(right, pattern_chars, pattern.Length);
+ left = right + pattern.Length;
+ newLineLength += pattern.Length - target.Length;
+ }
+ this.Update(this, new DocumentUpdateEventArgs(UpdateType.Replace, lineHeadIndex, lineLength, newLineLength, i));
+ }
+ }
+
+ internal int IndexOf(string target, int start,bool ci = false)
+ {
+ TextSearch ts = new TextSearch(target,ci);
+ return ts.IndexOf(this.buf, start,this.buf.Count);
+ }
+
+ /// <summary>
+ /// 文字列を削除する
+ /// </summary>
+ internal void Clear()
+ {
+ this.buf.Clear();
+ this.Update(this, new DocumentUpdateEventArgs(UpdateType.Clear, 0, this.buf.Count,0));
+ }
+
+ internal IEnumerable<char> GetEnumerator(int start, int length)
+ {
+ for (int i = start; i < start + length; i++)
+ yield return this.buf[i];
+ }
+
+ #region IEnumerable<char> メンバー
+
+ public IEnumerator<char> GetEnumerator()
+ {
+ for (int i = 0; i < this.Length; i++)
+ yield return this.buf[i];
+ }
+
+ #endregion
+
+ #region IEnumerable メンバー
+
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+ {
+ for (int i = 0; i < this.Length; i++)
+ yield return this[i];
+ }
+
+ #endregion
+ }
+
+ sealed class TextSearch
+ {
+ char[] pattern;
+ int patternLength;
+ Dictionary<char, int> qsTable = new Dictionary<char, int>();
+ bool caseInsenstive;
+ public TextSearch(string pattern,bool ci = false)
+ {
+ this.patternLength = pattern.Length;
+ this.caseInsenstive = ci;
+ if (ci)
+ {
+ this.CreateQSTable(pattern.ToLower());
+ this.CreateQSTable(pattern.ToUpper());
+ this.pattern = new char[pattern.Length];
+ for (int i = 0; i < pattern.Length; i++)
+ this.pattern[i] = CharTool.ToUpperFastIf(pattern[i]);
+ }
+ else
+ {
+ this.CreateQSTable(pattern);
+ this.pattern = pattern.ToCharArray();
+ }
+ }
+ void CreateQSTable(string pattern)
+ {
+ int len = pattern.Length;
+ for (int i = 0; i < len; i++)
+ {
+ if (!this.qsTable.ContainsKey(pattern[i]))
+ this.qsTable.Add(pattern[i], len - i);
+ else
+ this.qsTable[pattern[i]] = len - i;
+ }
+ }
+ public int IndexOf(GapBuffer<char> buf, int start,int end)
+ {
+ //QuickSearch法
+ int buflen = buf.Count - 1;
+ int plen = this.patternLength;
+ int i = start;
+ int search_end = end - plen;
+ //最適化のためわざとコピペした
+ if (this.caseInsenstive)
+ {
+ while (i <= search_end)
+ {
+ int j = 0;
+ while (j < plen)
+ {
+ if (CharTool.ToUpperFastIf(buf[i + j]) != this.pattern[j])
+ break;
+ j++;
+ }
+ if (j == plen)
+ {
+ return i;
+ }
+ else
+ {
+ int k = i + plen;
+ if (k <= buflen) //buffer以降にアクセスする可能性がある
+ {
+ int moveDelta;
+ if (this.qsTable.TryGetValue(buf[k], out moveDelta))
+ i += moveDelta;
+ else
+ i += plen;
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+ }
+ else
+ {
+ while (i <= search_end)
+ {
+ int j = 0;
+ while (j < plen)
+ {
+ if (buf[i + j] != this.pattern[j])
+ break;
+ j++;
+ }
+ if (j == plen)
+ {
+ return i;
+ }
+ else
+ {
+ int k = i + plen;
+ if (k <= buflen) //buffer以降にアクセスする可能性がある
+ {
+ int moveDelta;
+ if (this.qsTable.TryGetValue(buf[k], out moveDelta))
+ i += moveDelta;
+ else
+ i += plen;
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+ }
+ return -1;
+ }
+ }
+ static class CharTool
+ {
+ /// <summary>
+ /// Converts characters to lowercase.
+ /// </summary>
+ const string _lookupStringL =
+ "---------------------------------!-#$%&-()*+,-./0123456789:;<=>?@abcdefghijklmnopqrstuvwxyz[-]^_`abcdefghijklmnopqrstuvwxyz{|}~-";
+
+ /// <summary>
+ /// Converts characters to uppercase.
+ /// </summary>
+ const string _lookupStringU =
+ "---------------------------------!-#$%&-()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[-]^_`ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~-";
+
+ /// <summary>
+ /// Get lowercase version of this ASCII character.
+ /// </summary>
+ public static char ToLower(char c)
+ {
+ return _lookupStringL[c];
+ }
+
+ /// <summary>
+ /// Get uppercase version of this ASCII character.
+ /// </summary>
+ public static char ToUpper(char c)
+ {
+ return _lookupStringU[c];
+ }
+
+ /// <summary>
+ /// Translate uppercase ASCII characters to lowercase.
+ /// </summary>
+ public static char ToLowerFastIf(char c)
+ {
+ if (c >= 'A' && c <= 'Z')
+ {
+ return (char)(c + 32);
+ }
+ else
+ {
+ return c;
+ }
+ }
+
+ /// <summary>
+ /// Translate lowercase ASCII characters to uppercase.
+ /// </summary>
+ public static char ToUpperFastIf(char c)
+ {
+ if (c >= 'a' && c <= 'z')
+ {
+ return (char)(c - 32);
+ }
+ else
+ {
+ return c;
+ }
+ }
+ }
}
\ No newline at end of file
using System.Linq;
using FooEditEngine;
-namespace Test
+namespace FooEditEngine.Test
{
- class CharFoldingMethod : IFoldingStrategy
+ /// <summary>
+ /// テスト用折り畳みメソッドの実装
+ /// </summary>
+ public class CharFoldingMethod : IFoldingStrategy
{
public CharFoldingMethod(char begin, char end)
{
this.EndChar = end;
}
+ /// <summary>
+ /// 折り畳みの開始文字を表す
+ /// </summary>
public char BeginChar
{
get;
set;
}
-
+
+ /// <summary>
+ /// 折り畳みの終了文字を表す
+ /// </summary>
public char EndChar
{
get;
-/*\r
- * Copyright (C) 2013 FooProject\r
- * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.\r
-\r
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of \r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\r
-\r
-You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.\r
- */\r
-using System;\r
-using System.Text;\r
-using FooEditEngine;\r
-\r
-namespace Test\r
-{\r
- enum TextParserMode\r
- {\r
- Literal,\r
- ScriptPart,\r
- MultiLineComment,\r
- TextPart,\r
- }\r
- class XmlHilighter : IHilighter\r
- {\r
- private TextParserMode mode;\r
- private StringBuilder word;\r
- private TokenType KeyWordType;\r
-\r
- public XmlHilighter()\r
- {\r
- this.word = new StringBuilder();\r
- this.Reset();\r
- }\r
-\r
- #region IHilighter メンバー\r
-\r
- public void Reset()\r
- {\r
- this.mode = TextParserMode.TextPart;\r
- this.KeyWordType = TokenType.None;\r
- this.word.Clear();\r
- }\r
-\r
- public int DoHilight(string text, int length, TokenSpilitHandeler action)\r
- {\r
- int encloserLevel = 0;\r
- int i,wordPos = 0;\r
- for (i = 0; i < length;)\r
- {\r
- if (IsMatch(text,i,"<!--"))\r
- {\r
- encloserLevel++;\r
- if (TransModeAndAction(TextParserMode.MultiLineComment, action, word, 4, false,ref i, wordPos))\r
- break;\r
- }\r
- else if (IsMatch(text, i, "-->"))\r
- {\r
- encloserLevel--;\r
- if (TransModeAndAction(TextParserMode.TextPart, action, word, 3, true, ref i, wordPos))\r
- break;\r
- }\r
- else if (text[i] == '<' && this.mode != TextParserMode.MultiLineComment)\r
- {\r
- encloserLevel++;\r
- if (TransModeAndAction(TextParserMode.ScriptPart, action, word, 1, true, ref i, wordPos))\r
- break;\r
- this.KeyWordType = TokenType.Keyword1;\r
- }\r
- else if (text[i] == '>' && this.mode == TextParserMode.ScriptPart)\r
- {\r
- encloserLevel--;\r
- if (TransModeAndAction(TextParserMode.TextPart, action, word, 1, false, ref i, wordPos))\r
- break;\r
- }\r
- else if (IsMatch(text, i, "![CDATA[") && this.mode == TextParserMode.ScriptPart)\r
- {\r
- encloserLevel++;\r
- if (TransModeAndAction(TextParserMode.Literal, action, word, 8, false, ref i, wordPos))\r
- break;\r
- }\r
- else if ((text[i] == '\"' || text[i] == '\'') && this.mode == TextParserMode.ScriptPart)\r
- {\r
- encloserLevel++;\r
- if (TransModeAndAction(TextParserMode.Literal, action, word, 1, false, ref i, wordPos))\r
- break;\r
- }\r
- else if ((text[i] == '\"' || text[i] == '\'' ) && this.mode == TextParserMode.Literal)\r
- {\r
- encloserLevel--;\r
- if (TransModeAndAction(TextParserMode.ScriptPart, action, word, 1, true, ref i, wordPos))\r
- break;\r
- }\r
- else if (IsMatch(text, i, "]]") && this.mode == TextParserMode.Literal)\r
- {\r
- encloserLevel--;\r
- if (TransModeAndAction(TextParserMode.ScriptPart, action, word, 2, true, ref i, wordPos))\r
- break;\r
- }\r
- else if (text[i] == ' ')\r
- {\r
- if (TransModeAndAction(this.mode, action, word, 1, false, ref i, wordPos))\r
- break;\r
- this.KeyWordType = TokenType.Keyword2;\r
- }\r
- else if (text[i] == '=')\r
- {\r
- if (TransModeAndAction(this.mode, action, word, 1, false, ref i, wordPos))\r
- break;\r
- this.KeyWordType = TokenType.None;\r
- }\r
- else\r
- {\r
- if (word.Length == 0)\r
- wordPos = i;\r
- word.Append(text[i]);\r
- i++;\r
- continue;\r
- }\r
- }\r
-\r
- if (word.Length > 0)\r
- {\r
- action(new TokenSpilitEventArgs(wordPos,word.Length, GetMode(this.mode,KeyWordType)));\r
- word.Clear();\r
- }\r
-\r
- return encloserLevel;\r
- }\r
-\r
- #endregion\r
-\r
- /// <summary>\r
- /// 文字列が一致するかどうか確かめる\r
- /// </summary>\r
- /// <param name="s">検査される文字列</param>\r
- /// <param name="index">検査を開始するインデックス</param>\r
- /// <param name="pattern">検査対象の文字列</param>\r
- /// <returns></returns>\r
- private bool IsMatch(string s, int index, string pattern)\r
- {\r
- if (index + pattern.Length >= s.Length)\r
- return false;\r
- bool result = false;\r
- for (int i = index, j = 0; i < index + pattern.Length; i++, j++)\r
- {\r
- if ((j == 0 || j > 0 && result) && s[i] == pattern[j])\r
- result = true;\r
- else\r
- result = false;\r
- }\r
-\r
- return result;\r
- }\r
-\r
- private bool TransModeAndAction(TextParserMode toMode, TokenSpilitHandeler action, StringBuilder word, int tokenLength, bool TranAfterAction, ref int index, int wordPos)\r
- {\r
- TokenSpilitEventArgs e = new TokenSpilitEventArgs();\r
-\r
- if (word.Length > 0)\r
- {\r
- e.index = wordPos;\r
- e.length = word.Length;\r
- e.type = GetMode(this.mode, this.KeyWordType);\r
- action(e);\r
- word.Clear();\r
- if (e.breaked)\r
- return true;\r
- }\r
-\r
- if (TranAfterAction == false)\r
- this.mode = toMode;\r
-\r
- e.index = index;\r
- e.length = tokenLength;\r
- e.type = GetMode(this.mode, TokenType.None);\r
- action(e);\r
- if (e.breaked)\r
- return true;\r
-\r
- if (TranAfterAction)\r
- this.mode = toMode;\r
-\r
- index += tokenLength;\r
-\r
- return false;\r
- }\r
- \r
- private TokenType GetMode(TextParserMode mode,TokenType isKeyword)\r
- {\r
- switch (mode)\r
- {\r
- case TextParserMode.Literal:\r
- return TokenType.Literal;\r
- case TextParserMode.ScriptPart:\r
- return isKeyword;\r
- case TextParserMode.MultiLineComment:\r
- return TokenType.Comment;\r
- default:\r
- return TokenType.None;\r
- }\r
- }\r
- }\r
-}\r
+/*
+ * Copyright (C) 2013 FooProject
+ * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+using System.Text;
+using FooEditEngine;
+
+namespace FooEditEngine.Test
+{
+ enum TextParserMode
+ {
+ Literal,
+ ScriptPart,
+ MultiLineComment,
+ TextPart,
+ }
+ /// <summary>
+ /// XMLドキュメント用ハイライター
+ /// </summary>
+ public class XmlHilighter : IHilighter
+ {
+ private TextParserMode mode;
+ private StringBuilder word;
+ private TokenType KeyWordType;
+
+ public XmlHilighter()
+ {
+ this.word = new StringBuilder();
+ this.Reset();
+ }
+
+ #region IHilighter メンバー
+
+ public void Reset()
+ {
+ this.mode = TextParserMode.TextPart;
+ this.KeyWordType = TokenType.None;
+ this.word.Clear();
+ }
+
+ public int DoHilight(string text, int length, TokenSpilitHandeler action)
+ {
+ int encloserLevel = 0;
+ int i,wordPos = 0;
+ for (i = 0; i < length;)
+ {
+ if (IsMatch(text,i,"<!--"))
+ {
+ encloserLevel++;
+ if (TransModeAndAction(TextParserMode.MultiLineComment, action, word, 4, false,ref i, wordPos))
+ break;
+ }
+ else if (IsMatch(text, i, "-->"))
+ {
+ encloserLevel--;
+ if (TransModeAndAction(TextParserMode.TextPart, action, word, 3, true, ref i, wordPos))
+ break;
+ }
+ else if (text[i] == '<' && this.mode != TextParserMode.MultiLineComment)
+ {
+ encloserLevel++;
+ if (TransModeAndAction(TextParserMode.ScriptPart, action, word, 1, true, ref i, wordPos))
+ break;
+ this.KeyWordType = TokenType.Keyword1;
+ }
+ else if (text[i] == '>' && this.mode == TextParserMode.ScriptPart)
+ {
+ encloserLevel--;
+ if (TransModeAndAction(TextParserMode.TextPart, action, word, 1, false, ref i, wordPos))
+ break;
+ }
+ else if (IsMatch(text, i, "![CDATA[") && this.mode == TextParserMode.ScriptPart)
+ {
+ encloserLevel++;
+ if (TransModeAndAction(TextParserMode.Literal, action, word, 8, false, ref i, wordPos))
+ break;
+ }
+ else if ((text[i] == '\"' || text[i] == '\'') && this.mode == TextParserMode.ScriptPart)
+ {
+ encloserLevel++;
+ if (TransModeAndAction(TextParserMode.Literal, action, word, 1, false, ref i, wordPos))
+ break;
+ }
+ else if ((text[i] == '\"' || text[i] == '\'' ) && this.mode == TextParserMode.Literal)
+ {
+ encloserLevel--;
+ if (TransModeAndAction(TextParserMode.ScriptPart, action, word, 1, true, ref i, wordPos))
+ break;
+ }
+ else if (IsMatch(text, i, "]]") && this.mode == TextParserMode.Literal)
+ {
+ encloserLevel--;
+ if (TransModeAndAction(TextParserMode.ScriptPart, action, word, 2, true, ref i, wordPos))
+ break;
+ }
+ else if (text[i] == ' ')
+ {
+ if (TransModeAndAction(this.mode, action, word, 1, false, ref i, wordPos))
+ break;
+ this.KeyWordType = TokenType.Keyword2;
+ }
+ else if (text[i] == '=')
+ {
+ if (TransModeAndAction(this.mode, action, word, 1, false, ref i, wordPos))
+ break;
+ this.KeyWordType = TokenType.None;
+ }
+ else
+ {
+ if (word.Length == 0)
+ wordPos = i;
+ word.Append(text[i]);
+ i++;
+ continue;
+ }
+ }
+
+ if (word.Length > 0)
+ {
+ action(new TokenSpilitEventArgs(wordPos,word.Length, GetMode(this.mode,KeyWordType)));
+ word.Clear();
+ }
+
+ return encloserLevel;
+ }
+
+ #endregion
+
+ /// <summary>
+ /// 文字列が一致するかどうか確かめる
+ /// </summary>
+ /// <param name="s">検査される文字列</param>
+ /// <param name="index">検査を開始するインデックス</param>
+ /// <param name="pattern">検査対象の文字列</param>
+ /// <returns></returns>
+ private bool IsMatch(string s, int index, string pattern)
+ {
+ if (index + pattern.Length >= s.Length)
+ return false;
+ bool result = false;
+ for (int i = index, j = 0; i < index + pattern.Length; i++, j++)
+ {
+ if ((j == 0 || j > 0 && result) && s[i] == pattern[j])
+ result = true;
+ else
+ result = false;
+ }
+
+ return result;
+ }
+
+ private bool TransModeAndAction(TextParserMode toMode, TokenSpilitHandeler action, StringBuilder word, int tokenLength, bool TranAfterAction, ref int index, int wordPos)
+ {
+ TokenSpilitEventArgs e = new TokenSpilitEventArgs();
+
+ if (word.Length > 0)
+ {
+ e.index = wordPos;
+ e.length = word.Length;
+ e.type = GetMode(this.mode, this.KeyWordType);
+ action(e);
+ word.Clear();
+ if (e.breaked)
+ return true;
+ }
+
+ if (TranAfterAction == false)
+ this.mode = toMode;
+
+ e.index = index;
+ e.length = tokenLength;
+ e.type = GetMode(this.mode, TokenType.None);
+ action(e);
+ if (e.breaked)
+ return true;
+
+ if (TranAfterAction)
+ this.mode = toMode;
+
+ index += tokenLength;
+
+ return false;
+ }
+
+ private TokenType GetMode(TextParserMode mode,TokenType isKeyword)
+ {
+ switch (mode)
+ {
+ case TextParserMode.Literal:
+ return TokenType.Literal;
+ case TextParserMode.ScriptPart:
+ return isKeyword;
+ case TextParserMode.MultiLineComment:
+ return TokenType.Comment;
+ default:
+ return TokenType.None;
+ }
+ }
+ }
+}
-/*\r
- * Copyright (C) 2013 FooProject\r
- * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.\r
-\r
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of \r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\r
-\r
-You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.\r
- */\r
-using System;\r
-\r
-namespace FooEditEngine\r
-{\r
- struct Point2\r
- {\r
- public double X;\r
- public int Row;\r
- public Point2(double x, int row)\r
- {\r
- this.X = x;\r
- this.Row = row;\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// テキストの範囲を表す\r
- /// </summary>\r
- public struct TextRange\r
- {\r
- /// <summary>\r
- /// 開始インデックス\r
- /// </summary>\r
- public int Index;\r
- /// <summary>\r
- /// 長さ\r
- /// </summary>\r
- public int Length;\r
-\r
- /// <summary>\r
- /// 空の範囲を表す\r
- /// </summary>\r
- public static TextRange Null = new TextRange(0, 0);\r
-\r
- /// <summary>\r
- /// コンストラクター\r
- /// </summary>\r
- /// <param name="index">開始インデックス</param>\r
- /// <param name="length">長さ</param>\r
- public TextRange(int index, int length)\r
- {\r
- this.Index = index;\r
- this.Length = length;\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// 文章の位置を示すクラス\r
- /// </summary>\r
- public struct TextPoint : IComparable<TextPoint>\r
- {\r
- /// <summary>\r
- /// 行番号\r
- /// </summary>\r
- public int row;\r
- /// <summary>\r
- /// 桁\r
- /// </summary>\r
- public int col;\r
-\r
- /// <summary>\r
- /// TextPointがドキュメント上のどこも指していないことを表す\r
- /// </summary>\r
- public static readonly TextPoint Null = new TextPoint(-1,-1);\r
-\r
- /// <summary>\r
- /// コンストラクター\r
- /// </summary>\r
- /// <param name="row">行番号</param>\r
- /// <param name="col">桁</param>\r
- public TextPoint(int row, int col)\r
- {\r
- this.row = row;\r
- this.col = col;\r
- }\r
-\r
- /// <summary>\r
- /// 比較演算子を実装します\r
- /// </summary>\r
- /// <param name="a">比較される方</param>\r
- /// <param name="b">比較対象</param>\r
- /// <returns>条件を満たすなら真</returns>\r
- public static bool operator <(TextPoint a, TextPoint b)\r
- {\r
- return a.CompareTo(b) == -1;\r
- }\r
-\r
- /// <summary>\r
- /// 比較演算子を実装します\r
- /// </summary>\r
- /// <param name="a">比較される方</param>\r
- /// <param name="b">比較対象</param>\r
- /// <returns>条件を満たすなら真</returns>\r
- public static bool operator <=(TextPoint a, TextPoint b)\r
- {\r
- return a.CompareTo(b) != 1;\r
- }\r
-\r
- /// <summary>\r
- /// 比較演算子を実装します\r
- /// </summary>\r
- /// <param name="a">比較される方</param>\r
- /// <param name="b">比較対象</param>\r
- /// <returns>条件を満たすなら真</returns>\r
- public static bool operator >(TextPoint a, TextPoint b)\r
- {\r
- return a.CompareTo(b) == 1;\r
- }\r
-\r
- /// <summary>\r
- /// 比較演算子を実装します\r
- /// </summary>\r
- /// <param name="a">比較される方</param>\r
- /// <param name="b">比較対象</param>\r
- /// <returns>条件を満たすなら真</returns>\r
- public static bool operator >=(TextPoint a, TextPoint b)\r
- {\r
- return a.CompareTo(b) != -1;\r
- }\r
-\r
- /// <summary>\r
- /// 比較演算子を実装します\r
- /// </summary>\r
- /// <param name="a">比較される方</param>\r
- /// <param name="b">比較対象</param>\r
- /// <returns>条件を満たすなら真</returns>\r
- public static bool operator ==(TextPoint a, TextPoint b)\r
- {\r
- return a.Equals(b);\r
- }\r
-\r
- /// <summary>\r
- /// 比較演算子を実装します\r
- /// </summary>\r
- /// <param name="a">比較される方</param>\r
- /// <param name="b">比較対象</param>\r
- /// <returns>条件を満たすなら真</returns>\r
- public static bool operator !=(TextPoint a, TextPoint b)\r
- {\r
- return !a.Equals(b);\r
- }\r
-\r
- /// <summary>\r
- /// 一致するかどうか\r
- /// </summary>\r
- /// <param name="o">比較対象</param>\r
- /// <returns>一致するなら真</returns>\r
- public override bool Equals(object o)\r
- {\r
- TextPoint b = (TextPoint)o;\r
- return this.col == b.col && this.row == b.row;\r
- }\r
-\r
- /// <summary>\r
- /// ハッシュを返す\r
- /// </summary>\r
- /// <returns>ハッシュを返す</returns>\r
- public override int GetHashCode()\r
- {\r
- int result = this.row.GetHashCode();\r
- result ^= this.col.GetHashCode();\r
- return result;\r
- }\r
-\r
- #region IComparable<TextPoint> メンバー\r
-\r
- /// <summary>\r
- /// 比較する\r
- /// </summary>\r
- /// <param name="other">比較対象となるTextPointオブジェクト</param>\r
- /// <returns>相対値を返す</returns>\r
- public int CompareTo(TextPoint other)\r
- {\r
- if (this.row == other.row && this.col == other.col)\r
- return 0;\r
- if (this.row < other.row)\r
- return -1;\r
- else if (this.row == other.row && this.col < other.col)\r
- return -1;\r
- else\r
- return 1;\r
- }\r
-\r
- #endregion\r
- }\r
-\r
- /// <summary>\r
- /// 文章上での矩形エリアを表す\r
- /// </summary>\r
- public struct TextRectangle\r
- {\r
- TextPoint _TopLeft;\r
- \r
- TextPoint _BottomRight;\r
-\r
- /// <summary>\r
- /// 矩形エリアがドキュメントのどこも指していないことを表す\r
- /// </summary>\r
- public static readonly TextRectangle Null = new TextRectangle(new TextPoint(-1,-1),new TextPoint(-1,-1));\r
-\r
- /// <summary>\r
- /// 左上を表す\r
- /// </summary>\r
- public TextPoint TopLeft\r
- {\r
- get\r
- {\r
- return this._TopLeft;\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// 右上を表す\r
- /// </summary>\r
- public TextPoint TopRight\r
- {\r
- get\r
- {\r
- return new TextPoint(this._TopLeft.row, this._BottomRight.col);\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// 左下を表す\r
- /// </summary>\r
- public TextPoint BottomLeft\r
- {\r
- get\r
- {\r
- return new TextPoint(this._BottomRight.row, this._TopLeft.col);\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// 右下を表す\r
- /// </summary>\r
- public TextPoint BottomRight\r
- {\r
- get\r
- {\r
- return this._BottomRight;\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// コンストラクター\r
- /// </summary>\r
- /// <param name="row">行</param>\r
- /// <param name="col">桁</param>\r
- /// <param name="height">高さ</param>\r
- /// <param name="width">幅</param>\r
- public TextRectangle(int row, int col, int height,int width)\r
- {\r
- this._TopLeft = new TextPoint(row, col);\r
- this._BottomRight = new TextPoint(row + height - 1, col + width - 1);\r
- }\r
- \r
- /// <summary>\r
- /// コンストラクター\r
- /// </summary>\r
- /// <param name="topLeft">矩形の左上</param>\r
- /// <param name="bottomRight">矩形の右下</param>\r
- public TextRectangle(TextPoint topLeft, TextPoint bottomRight)\r
- {\r
- this._TopLeft = topLeft;\r
- this._BottomRight = bottomRight;\r
- }\r
-\r
- /// <summary>\r
- /// 比較演算子を実装します\r
- /// </summary>\r
- /// <param name="a">比較される方</param>\r
- /// <param name="b">比較対象</param>\r
- /// <returns>条件を満たすなら真</returns>\r
- public static bool operator ==(TextRectangle a, TextRectangle b)\r
- {\r
- return a.Equals(b);\r
- }\r
-\r
- /// <summary>\r
- /// 比較演算子を実装します\r
- /// </summary>\r
- /// <param name="a">比較される方</param>\r
- /// <param name="b">比較対象</param>\r
- /// <returns>条件を満たすなら真</returns>\r
- public static bool operator !=(TextRectangle a, TextRectangle b)\r
- {\r
- return !a.Equals(b);\r
- }\r
-\r
- /// <summary>\r
- /// 一致するかどうか\r
- /// </summary>\r
- /// <param name="o">比較対象</param>\r
- /// <returns>一致するなら真</returns>\r
- public override bool Equals(object o)\r
- {\r
- TextRectangle b = (TextRectangle)o;\r
- return this._TopLeft == b._TopLeft && this._BottomRight == b._BottomRight;\r
- }\r
-\r
- /// <summary>\r
- /// ハッシュを返す\r
- /// </summary>\r
- /// <returns>ハッシュを返す</returns>\r
- public override int GetHashCode()\r
- {\r
- int result = this._TopLeft.GetHashCode();\r
- result ^= this._BottomRight.GetHashCode();\r
- return result;\r
- }\r
- }\r
-}\r
+/*
+ * Copyright (C) 2013 FooProject
+ * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+
+namespace FooEditEngine
+{
+ struct Point2
+ {
+ public double X;
+ public int Row;
+ public Point2(double x, int row)
+ {
+ this.X = x;
+ this.Row = row;
+ }
+ }
+
+ /// <summary>
+ /// テキストの範囲を表す
+ /// </summary>
+ public struct TextRange
+ {
+ /// <summary>
+ /// 開始インデックス
+ /// </summary>
+ public int Index;
+ /// <summary>
+ /// 長さ
+ /// </summary>
+ public int Length;
+
+ /// <summary>
+ /// 空の範囲を表す
+ /// </summary>
+ public static TextRange Null = new TextRange(0, 0);
+
+ /// <summary>
+ /// コンストラクター
+ /// </summary>
+ /// <param name="index">開始インデックス</param>
+ /// <param name="length">長さ</param>
+ public TextRange(int index, int length)
+ {
+ this.Index = index;
+ this.Length = length;
+ }
+ }
+
+ /// <summary>
+ /// 文章の位置を示すクラス
+ /// </summary>
+ public struct TextPoint : IComparable<TextPoint>
+ {
+ /// <summary>
+ /// 行番号
+ /// </summary>
+ public int row;
+ /// <summary>
+ /// 桁
+ /// </summary>
+ public int col;
+
+ /// <summary>
+ /// TextPointがドキュメント上のどこも指していないことを表す
+ /// </summary>
+ public static readonly TextPoint Null = new TextPoint(-1,-1);
+
+ /// <summary>
+ /// コンストラクター
+ /// </summary>
+ /// <param name="row">行番号</param>
+ /// <param name="col">桁</param>
+ public TextPoint(int row, int col)
+ {
+ this.row = row;
+ this.col = col;
+ }
+
+ /// <summary>
+ /// 比較演算子を実装します
+ /// </summary>
+ /// <param name="a">比較される方</param>
+ /// <param name="b">比較対象</param>
+ /// <returns>条件を満たすなら真</returns>
+ public static bool operator <(TextPoint a, TextPoint b)
+ {
+ return a.CompareTo(b) == -1;
+ }
+
+ /// <summary>
+ /// 比較演算子を実装します
+ /// </summary>
+ /// <param name="a">比較される方</param>
+ /// <param name="b">比較対象</param>
+ /// <returns>条件を満たすなら真</returns>
+ public static bool operator <=(TextPoint a, TextPoint b)
+ {
+ return a.CompareTo(b) != 1;
+ }
+
+ /// <summary>
+ /// 比較演算子を実装します
+ /// </summary>
+ /// <param name="a">比較される方</param>
+ /// <param name="b">比較対象</param>
+ /// <returns>条件を満たすなら真</returns>
+ public static bool operator >(TextPoint a, TextPoint b)
+ {
+ return a.CompareTo(b) == 1;
+ }
+
+ /// <summary>
+ /// 比較演算子を実装します
+ /// </summary>
+ /// <param name="a">比較される方</param>
+ /// <param name="b">比較対象</param>
+ /// <returns>条件を満たすなら真</returns>
+ public static bool operator >=(TextPoint a, TextPoint b)
+ {
+ return a.CompareTo(b) != -1;
+ }
+
+ /// <summary>
+ /// 比較演算子を実装します
+ /// </summary>
+ /// <param name="a">比較される方</param>
+ /// <param name="b">比較対象</param>
+ /// <returns>条件を満たすなら真</returns>
+ public static bool operator ==(TextPoint a, TextPoint b)
+ {
+ return a.Equals(b);
+ }
+
+ /// <summary>
+ /// 比較演算子を実装します
+ /// </summary>
+ /// <param name="a">比較される方</param>
+ /// <param name="b">比較対象</param>
+ /// <returns>条件を満たすなら真</returns>
+ public static bool operator !=(TextPoint a, TextPoint b)
+ {
+ return !a.Equals(b);
+ }
+
+ /// <summary>
+ /// 一致するかどうか
+ /// </summary>
+ /// <param name="o">比較対象</param>
+ /// <returns>一致するなら真</returns>
+ public override bool Equals(object o)
+ {
+ TextPoint b = (TextPoint)o;
+ return this.col == b.col && this.row == b.row;
+ }
+
+ /// <summary>
+ /// ハッシュを返す
+ /// </summary>
+ /// <returns>ハッシュを返す</returns>
+ public override int GetHashCode()
+ {
+ int result = this.row.GetHashCode();
+ result ^= this.col.GetHashCode();
+ return result;
+ }
+
+ #region IComparable<TextPoint> メンバー
+
+ /// <summary>
+ /// 比較する
+ /// </summary>
+ /// <param name="other">比較対象となるTextPointオブジェクト</param>
+ /// <returns>相対値を返す</returns>
+ public int CompareTo(TextPoint other)
+ {
+ if (this.row == other.row && this.col == other.col)
+ return 0;
+ if (this.row < other.row)
+ return -1;
+ else if (this.row == other.row && this.col < other.col)
+ return -1;
+ else
+ return 1;
+ }
+
+ #endregion
+ }
+
+ /// <summary>
+ /// 文章上での矩形エリアを表す
+ /// </summary>
+ public struct TextRectangle
+ {
+ TextPoint _TopLeft;
+
+ TextPoint _BottomRight;
+
+ /// <summary>
+ /// 矩形エリアがドキュメントのどこも指していないことを表す
+ /// </summary>
+ public static readonly TextRectangle Null = new TextRectangle(new TextPoint(-1,-1),new TextPoint(-1,-1));
+
+ /// <summary>
+ /// 左上を表す
+ /// </summary>
+ public TextPoint TopLeft
+ {
+ get
+ {
+ return this._TopLeft;
+ }
+ }
+
+ /// <summary>
+ /// 右上を表す
+ /// </summary>
+ public TextPoint TopRight
+ {
+ get
+ {
+ return new TextPoint(this._TopLeft.row, this._BottomRight.col);
+ }
+ }
+
+ /// <summary>
+ /// 左下を表す
+ /// </summary>
+ public TextPoint BottomLeft
+ {
+ get
+ {
+ return new TextPoint(this._BottomRight.row, this._TopLeft.col);
+ }
+ }
+
+ /// <summary>
+ /// 右下を表す
+ /// </summary>
+ public TextPoint BottomRight
+ {
+ get
+ {
+ return this._BottomRight;
+ }
+ }
+
+ /// <summary>
+ /// コンストラクター
+ /// </summary>
+ /// <param name="row">行</param>
+ /// <param name="col">桁</param>
+ /// <param name="height">高さ</param>
+ /// <param name="width">幅</param>
+ public TextRectangle(int row, int col, int height,int width)
+ {
+ this._TopLeft = new TextPoint(row, col);
+ this._BottomRight = new TextPoint(row + height - 1, col + width - 1);
+ }
+
+ /// <summary>
+ /// コンストラクター
+ /// </summary>
+ /// <param name="topLeft">矩形の左上</param>
+ /// <param name="bottomRight">矩形の右下</param>
+ public TextRectangle(TextPoint topLeft, TextPoint bottomRight)
+ {
+ this._TopLeft = topLeft;
+ this._BottomRight = bottomRight;
+ }
+
+ /// <summary>
+ /// 比較演算子を実装します
+ /// </summary>
+ /// <param name="a">比較される方</param>
+ /// <param name="b">比較対象</param>
+ /// <returns>条件を満たすなら真</returns>
+ public static bool operator ==(TextRectangle a, TextRectangle b)
+ {
+ return a.Equals(b);
+ }
+
+ /// <summary>
+ /// 比較演算子を実装します
+ /// </summary>
+ /// <param name="a">比較される方</param>
+ /// <param name="b">比較対象</param>
+ /// <returns>条件を満たすなら真</returns>
+ public static bool operator !=(TextRectangle a, TextRectangle b)
+ {
+ return !a.Equals(b);
+ }
+
+ /// <summary>
+ /// 一致するかどうか
+ /// </summary>
+ /// <param name="o">比較対象</param>
+ /// <returns>一致するなら真</returns>
+ public override bool Equals(object o)
+ {
+ TextRectangle b = (TextRectangle)o;
+ return this._TopLeft == b._TopLeft && this._BottomRight == b._BottomRight;
+ }
+
+ /// <summary>
+ /// ハッシュを返す
+ /// </summary>
+ /// <returns>ハッシュを返す</returns>
+ public override int GetHashCode()
+ {
+ int result = this._TopLeft.GetHashCode();
+ result ^= this._BottomRight.GetHashCode();
+ return result;
+ }
+ }
+}
You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#if METRO || WPF
using System.Linq;
using DotNetTextStore.UnmanagedAPI.WinDef;
using DotNetTextStore.UnmanagedAPI.TSF;
}
}
}
+#endif
-/*\r
- * Copyright (C) 2013 FooProject\r
- * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.\r
-\r
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of \r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\r
-\r
-You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.\r
- */\r
-using System;\r
-using System.Collections.Generic;\r
-using System.Linq;\r
-\r
-namespace FooEditEngine\r
-{\r
- interface ICommand\r
- {\r
- /// <summary>\r
- /// アンドゥする\r
- /// </summary>\r
- void undo();\r
- /// <summary>\r
- /// リドゥする\r
- /// </summary>\r
- void redo();\r
- /// <summary>\r
- /// マージする\r
- /// </summary>\r
- /// <param name="a"></param>\r
- /// <returns>マージできた場合は真、そうでない場合は偽を返す</returns>\r
- bool marge(ICommand a);\r
- /// <summary>\r
- /// コマンドを結合した結果が空なら真。そうでないなら偽を返す\r
- /// </summary>\r
- /// <returns></returns>\r
- bool isempty();\r
-\r
- }\r
-\r
- sealed class BeginActionCommand : ICommand\r
- {\r
- #region ICommand メンバー\r
-\r
- public void undo()\r
- {\r
- }\r
-\r
- public void redo()\r
- {\r
- }\r
-\r
- public bool marge(ICommand a)\r
- {\r
- return false;\r
- }\r
-\r
- public bool isempty()\r
- {\r
- return false;\r
- }\r
- #endregion\r
- }\r
-\r
- sealed class EndActionCommand : ICommand\r
- {\r
- #region ICommand メンバー\r
-\r
- public void undo()\r
- {\r
- }\r
-\r
- public void redo()\r
- {\r
- }\r
-\r
- public bool marge(ICommand a)\r
- {\r
- return false;\r
- }\r
-\r
- public bool isempty()\r
- {\r
- return false;\r
- }\r
- #endregion\r
- }\r
-\r
- /// <summary>\r
- /// アンドゥバッファーを管理するクラス\r
- /// </summary>\r
- public sealed class UndoManager\r
- {\r
- private bool locked = false;\r
- private Stack<ICommand> UndoStack = new Stack<ICommand>();\r
- private Stack<ICommand> RedoStack = new Stack<ICommand>();\r
- private int groupLevel = 0;\r
-\r
- /// <summary>\r
- /// コンストラクター\r
- /// </summary>\r
- internal UndoManager()\r
- {\r
- this.Grouping = false;\r
- }\r
-\r
- /// <summary>\r
- /// 操作を履歴として残します\r
- /// </summary>\r
- /// <param name="cmd">ICommandインターフェイス</param>\r
- internal void push(ICommand cmd)\r
- {\r
- if (this.locked == true)\r
- return;\r
- ICommand last = null;\r
- if (this.AutoMerge && UndoStack.Count() > 0)\r
- last = UndoStack.First();\r
- if(last == null || last.marge(cmd) == false)\r
- UndoStack.Push(cmd);\r
- if (last != null && last.isempty())\r
- UndoStack.Pop();\r
- if (this.RedoStack.Count > 0)\r
- RedoStack.Clear();\r
- }\r
-\r
- /// <summary>\r
- /// 履歴として残される操作が一連のグループとして追加されるなら真を返し、そうでなければ偽を返す\r
- /// </summary>\r
- internal bool Grouping\r
- {\r
- get;\r
- set;\r
- }\r
-\r
-\r
- /// <summary>\r
- /// アクションを結合するなら真。そうでないなら偽\r
- /// </summary>\r
- internal bool AutoMerge\r
- {\r
- get;\r
- set;\r
- }\r
-\r
- /// <summary>\r
- /// 一連のアンドゥアクションの開始を宣言します\r
- /// </summary>\r
- public void BeginUndoGroup()\r
- {\r
- if (this.Grouping)\r
- {\r
- this.groupLevel++;\r
- }\r
- else\r
- {\r
- this.push(new BeginActionCommand());\r
- this.Grouping = true;\r
- this.AutoMerge = true;\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// 一連のアンドゥアクションの終了を宣言します\r
- /// </summary>\r
- public void EndUndoGroup()\r
- {\r
- if (this.Grouping == false)\r
- throw new InvalidOperationException("BeginUndoGroup()を呼び出してください");\r
- if (this.groupLevel > 0)\r
- {\r
- this.groupLevel--;\r
- }\r
- else\r
- {\r
- ICommand last = UndoStack.First();\r
- if (last != null && last is BeginActionCommand)\r
- this.UndoStack.Pop();\r
- else\r
- this.push(new EndActionCommand());\r
- this.Grouping = false;\r
- this.AutoMerge = false;\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// 元に戻します\r
- /// </summary>\r
- public void undo()\r
- {\r
- if (this.UndoStack.Count == 0 || this.locked == true)\r
- return; \r
- \r
- ICommand cmd;\r
- bool isGrouped = false;\r
-\r
- do\r
- {\r
- cmd = this.UndoStack.Pop();\r
- this.RedoStack.Push(cmd);\r
- this.BeginLock();\r
- cmd.undo();\r
- this.EndLock();\r
- //アンドゥスタック上ではEndActionCommand,...,BeginActionCommandの順番になる\r
- if (cmd is EndActionCommand)\r
- isGrouped = true;\r
- else if (cmd is BeginActionCommand)\r
- isGrouped = false;\r
- } while (isGrouped);\r
-\r
- }\r
-\r
- /// <summary>\r
- /// 元に戻した動作をやり直します\r
- /// </summary>\r
- public void redo()\r
- {\r
- if (this.RedoStack.Count == 0 || this.locked == true)\r
- return;\r
- ICommand cmd;\r
- bool isGrouped = false;\r
-\r
- do\r
- {\r
- cmd = this.RedoStack.Pop();\r
- this.UndoStack.Push(cmd);\r
- this.BeginLock();\r
- cmd.redo();\r
- this.EndLock();\r
- //リドゥスタック上ではBeginActionCommand,...,EndActionCommandの順番になる\r
- if (cmd is BeginActionCommand)\r
- isGrouped = true;\r
- else if (cmd is EndActionCommand)\r
- isGrouped = false;\r
- } while (isGrouped);\r
- }\r
-\r
- /// <summary>\r
- /// 操作履歴をすべて削除します\r
- /// </summary>\r
- public void clear()\r
- {\r
- if (this.locked == true)\r
- return;\r
- this.UndoStack.Clear();\r
- this.RedoStack.Clear();\r
- }\r
- /// <summary>\r
- /// 以後の操作をアンドゥ不能にする\r
- /// </summary>\r
- public void BeginLock()\r
- {\r
- this.locked = true;\r
- }\r
-\r
- /// <summary>\r
- /// 以後の操作をアンドゥ可能にする\r
- /// </summary>\r
- public void EndLock()\r
- {\r
- this.locked = false;\r
- }\r
- }\r
-}\r
+/*
+ * Copyright (C) 2013 FooProject
+ * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace FooEditEngine
+{
+ interface ICommand
+ {
+ /// <summary>
+ /// アンドゥする
+ /// </summary>
+ void undo();
+ /// <summary>
+ /// リドゥする
+ /// </summary>
+ void redo();
+ /// <summary>
+ /// マージする
+ /// </summary>
+ /// <param name="a"></param>
+ /// <returns>マージできた場合は真、そうでない場合は偽を返す</returns>
+ bool marge(ICommand a);
+ /// <summary>
+ /// コマンドを結合した結果が空なら真。そうでないなら偽を返す
+ /// </summary>
+ /// <returns></returns>
+ bool isempty();
+
+ }
+
+ sealed class BeginActionCommand : ICommand
+ {
+ #region ICommand メンバー
+
+ public void undo()
+ {
+ }
+
+ public void redo()
+ {
+ }
+
+ public bool marge(ICommand a)
+ {
+ return false;
+ }
+
+ public bool isempty()
+ {
+ return false;
+ }
+ #endregion
+ }
+
+ sealed class EndActionCommand : ICommand
+ {
+ #region ICommand メンバー
+
+ public void undo()
+ {
+ }
+
+ public void redo()
+ {
+ }
+
+ public bool marge(ICommand a)
+ {
+ return false;
+ }
+
+ public bool isempty()
+ {
+ return false;
+ }
+ #endregion
+ }
+
+ /// <summary>
+ /// アンドゥバッファーを管理するクラス
+ /// </summary>
+ public sealed class UndoManager
+ {
+ private bool locked = false;
+ private Stack<ICommand> UndoStack = new Stack<ICommand>();
+ private Stack<ICommand> RedoStack = new Stack<ICommand>();
+ private int groupLevel = 0;
+
+ /// <summary>
+ /// コンストラクター
+ /// </summary>
+ internal UndoManager()
+ {
+ this.Grouping = false;
+ }
+
+ /// <summary>
+ /// 操作を履歴として残します
+ /// </summary>
+ /// <param name="cmd">ICommandインターフェイス</param>
+ internal void push(ICommand cmd)
+ {
+ if (this.locked == true)
+ return;
+ ICommand last = null;
+ if (this.AutoMerge && UndoStack.Count() > 0)
+ last = UndoStack.First();
+ if(last == null || last.marge(cmd) == false)
+ UndoStack.Push(cmd);
+ if (last != null && last.isempty())
+ UndoStack.Pop();
+ if (this.RedoStack.Count > 0)
+ RedoStack.Clear();
+ }
+
+ /// <summary>
+ /// 履歴として残される操作が一連のグループとして追加されるなら真を返し、そうでなければ偽を返す
+ /// </summary>
+ internal bool Grouping
+ {
+ get;
+ set;
+ }
+
+
+ /// <summary>
+ /// アクションを結合するなら真。そうでないなら偽
+ /// </summary>
+ internal bool AutoMerge
+ {
+ get;
+ set;
+ }
+
+ /// <summary>
+ /// 一連のアンドゥアクションの開始を宣言します
+ /// </summary>
+ public void BeginUndoGroup()
+ {
+ if (this.Grouping)
+ {
+ this.groupLevel++;
+ }
+ else
+ {
+ this.push(new BeginActionCommand());
+ this.Grouping = true;
+ this.AutoMerge = true;
+ }
+ }
+
+ /// <summary>
+ /// 一連のアンドゥアクションの終了を宣言します
+ /// </summary>
+ public void EndUndoGroup()
+ {
+ if (this.Grouping == false)
+ throw new InvalidOperationException("BeginUndoGroup()を呼び出してください");
+ if (this.groupLevel > 0)
+ {
+ this.groupLevel--;
+ }
+ else
+ {
+ ICommand last = UndoStack.First();
+ if (last != null && last is BeginActionCommand)
+ this.UndoStack.Pop();
+ else
+ this.push(new EndActionCommand());
+ this.Grouping = false;
+ this.AutoMerge = false;
+ }
+ }
+
+ /// <summary>
+ /// 元に戻します
+ /// </summary>
+ public void undo()
+ {
+ if (this.UndoStack.Count == 0 || this.locked == true)
+ return;
+
+ ICommand cmd;
+ bool isGrouped = false;
+
+ do
+ {
+ cmd = this.UndoStack.Pop();
+ this.RedoStack.Push(cmd);
+ this.BeginLock();
+ cmd.undo();
+ this.EndLock();
+ //アンドゥスタック上ではEndActionCommand,...,BeginActionCommandの順番になる
+ if (cmd is EndActionCommand)
+ isGrouped = true;
+ else if (cmd is BeginActionCommand)
+ isGrouped = false;
+ } while (isGrouped);
+
+ }
+
+ /// <summary>
+ /// 元に戻した動作をやり直します
+ /// </summary>
+ public void redo()
+ {
+ if (this.RedoStack.Count == 0 || this.locked == true)
+ return;
+ ICommand cmd;
+ bool isGrouped = false;
+
+ do
+ {
+ cmd = this.RedoStack.Pop();
+ this.UndoStack.Push(cmd);
+ this.BeginLock();
+ cmd.redo();
+ this.EndLock();
+ //リドゥスタック上ではBeginActionCommand,...,EndActionCommandの順番になる
+ if (cmd is BeginActionCommand)
+ isGrouped = true;
+ else if (cmd is EndActionCommand)
+ isGrouped = false;
+ } while (isGrouped);
+ }
+
+ /// <summary>
+ /// 操作履歴をすべて削除します
+ /// </summary>
+ public void clear()
+ {
+ if (this.locked == true)
+ return;
+ this.UndoStack.Clear();
+ this.RedoStack.Clear();
+ }
+ /// <summary>
+ /// 以後の操作をアンドゥ不能にする
+ /// </summary>
+ public void BeginLock()
+ {
+ this.locked = true;
+ }
+
+ /// <summary>
+ /// 以後の操作をアンドゥ可能にする
+ /// </summary>
+ public void EndLock()
+ {
+ this.locked = false;
+ }
+ }
+}
-/*\r
- * Copyright (C) 2013 FooProject\r
- * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.\r
-\r
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of \r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\r
-\r
-You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.\r
- */\r
-using System;\r
-using System.Collections.Generic;\r
-using System.Linq;\r
-using System.Text;\r
-using System.Text.RegularExpressions;\r
-using System.Threading.Tasks;\r
-\r
-namespace FooEditEngine\r
-{\r
- /// <summary>\r
- /// LineBreakMethod列挙体\r
- /// </summary>\r
- public enum LineBreakMethod\r
- {\r
- /// <summary>\r
- /// 折り返さない\r
- /// </summary>\r
- None = 0,\r
- /// <summary>\r
- /// 右端で折り返す\r
- /// </summary>\r
- PageBound = 1,\r
- /// <summary>\r
- /// 文字数で折り返す\r
- /// </summary>\r
- CharUnit = 2\r
- }\r
-\r
- /// <summary>\r
- /// 余白を表す\r
- /// </summary>\r
- public struct Padding\r
- {\r
- /// <summary>\r
- /// 左余白\r
- /// </summary>\r
- public int Left;\r
- /// <summary>\r
- /// 上余白\r
- /// </summary>\r
- public int Top;\r
- /// <summary>\r
- /// 右余白\r
- /// </summary>\r
- public int Right;\r
- /// <summary>\r
- /// 下余白\r
- /// </summary>\r
- public int Bottom;\r
- /// <summary>\r
- /// コンストラクター\r
- /// </summary>\r
- /// <param name="left">左</param>\r
- /// <param name="top">上</param>\r
- /// <param name="right">右</param>\r
- /// <param name="bottom">下</param>\r
- public Padding(int left, int top, int right, int bottom)\r
- {\r
- this.Left = left;\r
- this.Top = top;\r
- this.Right = right;\r
- this.Bottom = bottom;\r
- }\r
- }\r
-\r
- abstract class ViewBase : IDisposable\r
- {\r
- const int SpiltCharCount = 1024;\r
-\r
- protected Document Document;\r
- protected Point2 _Src = new Point2();\r
- protected Rectangle _Rect;\r
- protected double _LongestWidth;\r
- Padding _Padding;\r
- bool _DrawLineNumber,_UrlMark;\r
- LineBreakMethod _LineBreak;\r
- int _LineBreakCharCount = 80;\r
-\r
- public ViewBase(Document doc, ITextRender r,Padding padding)\r
- {\r
- this._Padding = padding;\r
- this.Document = doc;\r
- this.Document.UpdateCalledAlways += new DocumentUpdateEventHandler(doc_Update);\r
- this._LayoutLines.SpilitString = new SpilitStringEventHandler(LayoutLines_SpilitStringByChar);\r
- this.render = r;\r
- this.render.ChangedRenderResource += new ChangedRenderResourceEventHandler(render_ChangedRenderResource);\r
- this.render.ChangedRightToLeft += render_ChangedRightToLeft;\r
- this.SrcChanged += new EventHandler((s, e) => { });\r
- this.PerformLayouted += new EventHandler((s, e) => { });\r
- this.PageBoundChanged += new EventHandler((s, e) => { });\r
- this.MarkerPatternSet = new MarkerPatternSet(this._LayoutLines, doc.Markers);\r
- this.MarkerPatternSet.Updated += WacthDogPattern_Updated;\r
- }\r
-\r
- protected LineToIndexTable _LayoutLines\r
- {\r
- get\r
- {\r
- return this.Document.LayoutLines;\r
- }\r
- }\r
-\r
- public event EventHandler SrcChanged;\r
-\r
- public event EventHandler PerformLayouted;\r
-\r
- public event EventHandler PageBoundChanged;\r
-\r
- /// <summary>\r
- /// マーカーパターンセット\r
- /// </summary>\r
- public MarkerPatternSet MarkerPatternSet\r
- {\r
- get;\r
- private set;\r
- }\r
-\r
- /// <summary>\r
- /// URLをハイパーリンクとして表示するなら真。そうでないなら偽\r
- /// </summary>\r
- public bool UrlMark\r
- {\r
- get { return this._UrlMark; }\r
- set\r
- {\r
- this._UrlMark = value;\r
- if (value)\r
- {\r
- Regex regex = new Regex("(http|https|ftp)(:\\/\\/[-_.!~*\\'()a-zA-Z0-9;\\/?:\\@&=+\\$,%#]+)");\r
- this.MarkerPatternSet.Add(MarkerIDs.URL, new RegexMarkerPattern(regex, HilightType.Url,new Color()));\r
- }\r
- else\r
- {\r
- this.MarkerPatternSet.Remove(MarkerIDs.URL);\r
- }\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// テキストレンダラ―\r
- /// </summary>\r
- public ITextRender render\r
- {\r
- get;\r
- set;\r
- }\r
-\r
- /// <summary>\r
- /// 一ページの高さに収まる行数を返す\r
- /// </summary>\r
- public int LineCountOnScreen\r
- {\r
- get;\r
- protected set;\r
- }\r
-\r
- /// <summary>\r
- /// 折り返し時の右マージン\r
- /// </summary>\r
- public double LineBreakingMarginWidth\r
- {\r
- get;\r
- protected set;\r
- }\r
-\r
- /// <summary>\r
- /// 保持しているレイアウト行\r
- /// </summary>\r
- public LineToIndexTable LayoutLines\r
- {\r
- get { return this._LayoutLines; }\r
- }\r
-\r
- /// <summary>\r
- /// 最も長い行の幅\r
- /// </summary>\r
- public double LongestWidth\r
- {\r
- get { return this._LongestWidth; }\r
- }\r
-\r
- /// <summary>\r
- /// 桁折り処理の方法を指定する\r
- /// </summary>\r
- /// <remarks>\r
- /// 変更した場合、呼び出し側で再描写とレイアウトの再構築を行う必要があります\r
- /// </remarks>\r
- public LineBreakMethod LineBreak\r
- {\r
- get\r
- {\r
- return this._LineBreak;\r
- }\r
- set\r
- {\r
- this._LineBreak = value;\r
- if (value != LineBreakMethod.None)\r
- this._LayoutLines.SpilitString = new SpilitStringEventHandler(LayoutLines_SpilitStringByPixelbase);\r
- else\r
- this._LayoutLines.SpilitString = new SpilitStringEventHandler(LayoutLines_SpilitStringByChar);\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// 折り返し行う文字数。実際に折り返しが行われる幅はem単位×この値となります\r
- /// </summary>\r
- public int LineBreakCharCount\r
- {\r
- get\r
- {\r
- return this._LineBreakCharCount;\r
- }\r
- set\r
- {\r
- this._LineBreakCharCount = value;\r
- }\r
- }\r
-\r
- public double LineNumberMargin\r
- {\r
- get\r
- {\r
- return this.render.emSize.Width;\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// シンタックスハイライター\r
- /// </summary>\r
- public IHilighter Hilighter\r
- {\r
- get { return this._LayoutLines.Hilighter; }\r
- set { this._LayoutLines.Hilighter = value; }\r
- }\r
-\r
- /// <summary>\r
- /// タブの幅\r
- /// </summary>\r
- /// <remarks>変更した場合、呼び出し側で再描写する必要があります</remarks>\r
- public int TabStops\r
- {\r
- get { return this.render.TabWidthChar; }\r
- set { this.render.TabWidthChar = value; }\r
- }\r
-\r
- /// <summary>\r
- /// すべてのレイアウト行を破棄し、再度レイアウトをやり直す\r
- /// </summary>\r
- public virtual void PerfomLayouts()\r
- {\r
- this.Document.FireUpdate(new DocumentUpdateEventArgs(UpdateType.Clear, -1, -1, -1));\r
- this.Document.FireUpdate(new DocumentUpdateEventArgs(UpdateType.Replace, 0, 0, this.Document.Length));\r
- CalculateLineCountOnScreen();\r
- this.PerformLayouted(this, null);\r
- }\r
-\r
- /// <summary>\r
- /// 余白を表す\r
- /// </summary>\r
- public Padding Padding\r
- {\r
- get {\r
- return this._Padding;\r
- }\r
- set {\r
- this._Padding = value;\r
- CalculateClipRect();\r
- CalculateLineCountOnScreen();\r
- if (this.render.RightToLeft)\r
- this._LayoutLines.ClearLayoutCache();\r
- this.PageBoundChanged(this, null);\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// ページ全体を表す領域\r
- /// </summary>\r
- public Rectangle PageBound\r
- {\r
- get { return this._Rect; }\r
- set\r
- {\r
- if (value.Width < 0 || value.Height < 0)\r
- throw new ArgumentOutOfRangeException("");\r
- this._Rect = value;\r
- CalculateClipRect();\r
- CalculateLineCountOnScreen();\r
- if (this.render.RightToLeft)\r
- this._LayoutLines.ClearLayoutCache();\r
- this.PageBoundChanged(this, null);\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// Draw()の対象となる領域の左上を表す\r
- /// </summary>\r
- public Point2 Src\r
- {\r
- get { return this._Src; }\r
- set { this._Src = value; }\r
- }\r
-\r
- /// <summary>\r
- /// 行番号を表示するかどうか\r
- /// </summary>\r
- public bool DrawLineNumber\r
- {\r
- get { return this._DrawLineNumber; }\r
- set\r
- {\r
- this._DrawLineNumber = value;\r
- this._LayoutLines.ClearLayoutCache();\r
- CalculateClipRect();\r
- }\r
- }\r
-\r
- public virtual void Draw(Rectangle updateRect)\r
- {\r
- }\r
-\r
- public virtual bool TryScroll(double x, int row)\r
- {\r
- if (row < 0)\r
- return true;\r
- if (row > this.LayoutLines.Count - 1)\r
- return true;\r
- this._Src.X = x;\r
- this._Src.Row = row;\r
- CalculateLineCountOnScreen();\r
- this.SrcChanged(this,null);\r
- return false;\r
- }\r
-\r
- public void Dispose()\r
- {\r
- this.Dispose(true);\r
- GC.SuppressFinalize(this);\r
- }\r
-\r
- public virtual void CalculateLineCountOnScreen()\r
- {\r
- }\r
-\r
- protected virtual void Dispose(bool disposing)\r
- {\r
- if (disposing)\r
- {\r
- this.Document.UpdateCalledAlways -= new DocumentUpdateEventHandler(this.doc_Update); //これをしないと複数のビューを作成した時に妙なエラーが発生する\r
- }\r
- this._LayoutLines.Clear();\r
- }\r
-\r
- protected virtual void CalculateClipRect()\r
- {\r
- }\r
-\r
-\r
- protected virtual void OnSrcChanged(EventArgs e)\r
- {\r
- EventHandler handler = this.SrcChanged;\r
- if (handler != null)\r
- this.SrcChanged(this, e);\r
- }\r
-\r
- protected virtual void OnPerformLayoutedChanged(EventArgs e)\r
- {\r
- EventHandler handler = this.PerformLayouted;\r
- if (handler != null)\r
- this.PerformLayouted(this, e);\r
- }\r
-\r
- protected virtual void OnPageBoundChanged(EventArgs e)\r
- {\r
- EventHandler handler = this.PageBoundChanged;\r
- if (handler != null)\r
- this.PageBoundChanged(this, e);\r
- }\r
-\r
- void WacthDogPattern_Updated(object sender, EventArgs e)\r
- {\r
- this._LayoutLines.ClearLayoutCache();\r
- }\r
-\r
- void render_ChangedRightToLeft(object sender, EventArgs e)\r
- {\r
- this._Src.X = 0;\r
- this._LayoutLines.ClearLayoutCache();\r
- this.CalculateClipRect();\r
- }\r
-\r
- void render_ChangedRenderResource(object sender, ChangedRenderRsourceEventArgs e)\r
- {\r
- this._LayoutLines.ClearLayoutCache();\r
- if (e.type == ResourceType.Font)\r
- {\r
- this.CalculateClipRect();\r
- this.CalculateLineCountOnScreen();\r
- }\r
- }\r
-\r
- void doc_Update(object sender, DocumentUpdateEventArgs e)\r
- {\r
- switch (e.type)\r
- {\r
- case UpdateType.Clear:\r
- this._LongestWidth = 0;\r
- break;\r
- }\r
- }\r
-\r
- IList<LineToIndexTableData> LayoutLines_SpilitStringByPixelbase(object sender, SpilitStringEventArgs e)\r
- {\r
- double WrapWidth;\r
- if (_LineBreak == LineBreakMethod.PageBound)\r
- WrapWidth = this.render.TextArea.Width - LineBreakingMarginWidth; //余白を残さないと欠ける\r
- else\r
- WrapWidth = this.render.emSize.Width * this._LineBreakCharCount;\r
-\r
- if (WrapWidth < 0 && this._LineBreak != LineBreakMethod.None)\r
- throw new InvalidOperationException();\r
-\r
- int startIndex = e.index;\r
- int endIndex = e.index + e.length - 1;\r
-\r
- LineToIndexTable layoutLineCollection = (LineToIndexTable)sender;\r
-\r
- return this.render.BreakLine(e.buffer,layoutLineCollection, startIndex, endIndex, WrapWidth);\r
- }\r
-\r
- IList<LineToIndexTableData> LayoutLines_SpilitStringByChar(object sender, SpilitStringEventArgs e)\r
- {\r
- return this.Document.CreateLineList(e.index, e.length,1000);\r
- }\r
- }\r
-}\r
+/*
+ * Copyright (C) 2013 FooProject
+ * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+
+namespace FooEditEngine
+{
+ /// <summary>
+ /// LineBreakMethod列挙体
+ /// </summary>
+ public enum LineBreakMethod
+ {
+ /// <summary>
+ /// 折り返さない
+ /// </summary>
+ None = 0,
+ /// <summary>
+ /// 右端で折り返す
+ /// </summary>
+ PageBound = 1,
+ /// <summary>
+ /// 文字数で折り返す
+ /// </summary>
+ CharUnit = 2
+ }
+
+ /// <summary>
+ /// 余白を表す
+ /// </summary>
+ public struct Padding
+ {
+ /// <summary>
+ /// 左余白
+ /// </summary>
+ public int Left;
+ /// <summary>
+ /// 上余白
+ /// </summary>
+ public int Top;
+ /// <summary>
+ /// 右余白
+ /// </summary>
+ public int Right;
+ /// <summary>
+ /// 下余白
+ /// </summary>
+ public int Bottom;
+ /// <summary>
+ /// コンストラクター
+ /// </summary>
+ /// <param name="left">左</param>
+ /// <param name="top">上</param>
+ /// <param name="right">右</param>
+ /// <param name="bottom">下</param>
+ public Padding(int left, int top, int right, int bottom)
+ {
+ this.Left = left;
+ this.Top = top;
+ this.Right = right;
+ this.Bottom = bottom;
+ }
+ }
+
+ abstract class ViewBase : IDisposable
+ {
+ const int SpiltCharCount = 1024;
+
+ protected Document Document;
+ protected Point2 _Src = new Point2();
+ protected Rectangle _Rect;
+ protected double _LongestWidth;
+ Padding _Padding;
+ bool _DrawLineNumber,_UrlMark;
+ LineBreakMethod _LineBreak;
+ int _LineBreakCharCount = 80;
+
+ public ViewBase(Document doc, ITextRender r,Padding padding)
+ {
+ this._Padding = padding;
+ this.Document = doc;
+ this.Document.UpdateCalledAlways += new DocumentUpdateEventHandler(doc_Update);
+ this._LayoutLines.SpilitString = new SpilitStringEventHandler(LayoutLines_SpilitStringByChar);
+ this.render = r;
+ this.render.ChangedRenderResource += new ChangedRenderResourceEventHandler(render_ChangedRenderResource);
+ this.render.ChangedRightToLeft += render_ChangedRightToLeft;
+ this.SrcChanged += new EventHandler((s, e) => { });
+ this.PerformLayouted += new EventHandler((s, e) => { });
+ this.PageBoundChanged += new EventHandler((s, e) => { });
+ this.MarkerPatternSet = new MarkerPatternSet(this._LayoutLines, doc.Markers);
+ this.MarkerPatternSet.Updated += WacthDogPattern_Updated;
+ }
+
+ protected LineToIndexTable _LayoutLines
+ {
+ get
+ {
+ return this.Document.LayoutLines;
+ }
+ }
+
+ public event EventHandler SrcChanged;
+
+ public event EventHandler PerformLayouted;
+
+ public event EventHandler PageBoundChanged;
+
+ /// <summary>
+ /// マーカーパターンセット
+ /// </summary>
+ public MarkerPatternSet MarkerPatternSet
+ {
+ get;
+ private set;
+ }
+
+ /// <summary>
+ /// URLをハイパーリンクとして表示するなら真。そうでないなら偽
+ /// </summary>
+ public bool UrlMark
+ {
+ get { return this._UrlMark; }
+ set
+ {
+ this._UrlMark = value;
+ if (value)
+ {
+ Regex regex = new Regex("(http|https|ftp)(:\\/\\/[-_.!~*\\'()a-zA-Z0-9;\\/?:\\@&=+\\$,%#]+)");
+ this.MarkerPatternSet.Add(MarkerIDs.URL, new RegexMarkerPattern(regex, HilightType.Url,new Color()));
+ }
+ else
+ {
+ this.MarkerPatternSet.Remove(MarkerIDs.URL);
+ }
+ }
+ }
+
+ /// <summary>
+ /// テキストレンダラ―
+ /// </summary>
+ public ITextRender render
+ {
+ get;
+ set;
+ }
+
+ /// <summary>
+ /// 一ページの高さに収まる行数を返す
+ /// </summary>
+ public int LineCountOnScreen
+ {
+ get;
+ protected set;
+ }
+
+ /// <summary>
+ /// 折り返し時の右マージン
+ /// </summary>
+ public double LineBreakingMarginWidth
+ {
+ get;
+ protected set;
+ }
+
+ /// <summary>
+ /// 保持しているレイアウト行
+ /// </summary>
+ public LineToIndexTable LayoutLines
+ {
+ get { return this._LayoutLines; }
+ }
+
+ /// <summary>
+ /// 最も長い行の幅
+ /// </summary>
+ public double LongestWidth
+ {
+ get { return this._LongestWidth; }
+ }
+
+ /// <summary>
+ /// 桁折り処理の方法を指定する
+ /// </summary>
+ /// <remarks>
+ /// 変更した場合、呼び出し側で再描写とレイアウトの再構築を行う必要があります
+ /// </remarks>
+ public LineBreakMethod LineBreak
+ {
+ get
+ {
+ return this._LineBreak;
+ }
+ set
+ {
+ this._LineBreak = value;
+ if (value != LineBreakMethod.None)
+ this._LayoutLines.SpilitString = new SpilitStringEventHandler(LayoutLines_SpilitStringByPixelbase);
+ else
+ this._LayoutLines.SpilitString = new SpilitStringEventHandler(LayoutLines_SpilitStringByChar);
+ }
+ }
+
+ /// <summary>
+ /// 折り返し行う文字数。実際に折り返しが行われる幅はem単位×この値となります
+ /// </summary>
+ public int LineBreakCharCount
+ {
+ get
+ {
+ return this._LineBreakCharCount;
+ }
+ set
+ {
+ this._LineBreakCharCount = value;
+ }
+ }
+
+ public double LineNumberMargin
+ {
+ get
+ {
+ return this.render.emSize.Width;
+ }
+ }
+
+ /// <summary>
+ /// シンタックスハイライター
+ /// </summary>
+ public IHilighter Hilighter
+ {
+ get { return this._LayoutLines.Hilighter; }
+ set { this._LayoutLines.Hilighter = value; }
+ }
+
+ /// <summary>
+ /// タブの幅
+ /// </summary>
+ /// <remarks>変更した場合、呼び出し側で再描写する必要があります</remarks>
+ public int TabStops
+ {
+ get { return this.render.TabWidthChar; }
+ set { this.render.TabWidthChar = value; }
+ }
+
+ /// <summary>
+ /// すべてのレイアウト行を破棄し、再度レイアウトをやり直す
+ /// </summary>
+ public virtual void PerfomLayouts()
+ {
+ this.Document.FireUpdate(new DocumentUpdateEventArgs(UpdateType.Clear, -1, -1, -1));
+ this.Document.FireUpdate(new DocumentUpdateEventArgs(UpdateType.Replace, 0, 0, this.Document.Length));
+ CalculateLineCountOnScreen();
+ this.PerformLayouted(this, null);
+ }
+
+ /// <summary>
+ /// 余白を表す
+ /// </summary>
+ public Padding Padding
+ {
+ get {
+ return this._Padding;
+ }
+ set {
+ this._Padding = value;
+ CalculateClipRect();
+ CalculateLineCountOnScreen();
+ if (this.render.RightToLeft)
+ this._LayoutLines.ClearLayoutCache();
+ this.PageBoundChanged(this, null);
+ }
+ }
+
+ /// <summary>
+ /// ページ全体を表す領域
+ /// </summary>
+ public Rectangle PageBound
+ {
+ get { return this._Rect; }
+ set
+ {
+ if (value.Width < 0 || value.Height < 0)
+ throw new ArgumentOutOfRangeException("");
+ this._Rect = value;
+ CalculateClipRect();
+ CalculateLineCountOnScreen();
+ if (this.render.RightToLeft)
+ this._LayoutLines.ClearLayoutCache();
+ this.PageBoundChanged(this, null);
+ }
+ }
+
+ /// <summary>
+ /// Draw()の対象となる領域の左上を表す
+ /// </summary>
+ public Point2 Src
+ {
+ get { return this._Src; }
+ set { this._Src = value; }
+ }
+
+ /// <summary>
+ /// 行番号を表示するかどうか
+ /// </summary>
+ public bool DrawLineNumber
+ {
+ get { return this._DrawLineNumber; }
+ set
+ {
+ this._DrawLineNumber = value;
+ this._LayoutLines.ClearLayoutCache();
+ CalculateClipRect();
+ }
+ }
+
+ public virtual void Draw(Rectangle updateRect)
+ {
+ }
+
+ public virtual bool TryScroll(double x, int row)
+ {
+ if (row < 0)
+ return true;
+ if (row > this.LayoutLines.Count - 1)
+ return true;
+ this._Src.X = x;
+ this._Src.Row = row;
+ CalculateLineCountOnScreen();
+ this.SrcChanged(this,null);
+ return false;
+ }
+
+ public void Dispose()
+ {
+ this.Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ public virtual void CalculateLineCountOnScreen()
+ {
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ this.Document.UpdateCalledAlways -= new DocumentUpdateEventHandler(this.doc_Update); //これをしないと複数のビューを作成した時に妙なエラーが発生する
+ }
+ this._LayoutLines.Clear();
+ }
+
+ protected virtual void CalculateClipRect()
+ {
+ }
+
+
+ protected virtual void OnSrcChanged(EventArgs e)
+ {
+ EventHandler handler = this.SrcChanged;
+ if (handler != null)
+ this.SrcChanged(this, e);
+ }
+
+ protected virtual void OnPerformLayoutedChanged(EventArgs e)
+ {
+ EventHandler handler = this.PerformLayouted;
+ if (handler != null)
+ this.PerformLayouted(this, e);
+ }
+
+ protected virtual void OnPageBoundChanged(EventArgs e)
+ {
+ EventHandler handler = this.PageBoundChanged;
+ if (handler != null)
+ this.PageBoundChanged(this, e);
+ }
+
+ void WacthDogPattern_Updated(object sender, EventArgs e)
+ {
+ this._LayoutLines.ClearLayoutCache();
+ }
+
+ void render_ChangedRightToLeft(object sender, EventArgs e)
+ {
+ this._Src.X = 0;
+ this._LayoutLines.ClearLayoutCache();
+ this.CalculateClipRect();
+ }
+
+ void render_ChangedRenderResource(object sender, ChangedRenderRsourceEventArgs e)
+ {
+ this._LayoutLines.ClearLayoutCache();
+ if (e.type == ResourceType.Font)
+ {
+ this.CalculateClipRect();
+ this.CalculateLineCountOnScreen();
+ }
+ }
+
+ void doc_Update(object sender, DocumentUpdateEventArgs e)
+ {
+ switch (e.type)
+ {
+ case UpdateType.Clear:
+ this._LongestWidth = 0;
+ break;
+ }
+ }
+
+ IList<LineToIndexTableData> LayoutLines_SpilitStringByPixelbase(object sender, SpilitStringEventArgs e)
+ {
+ double WrapWidth;
+ if (_LineBreak == LineBreakMethod.PageBound)
+ WrapWidth = this.render.TextArea.Width - LineBreakingMarginWidth; //余白を残さないと欠ける
+ else
+ WrapWidth = this.render.emSize.Width * this._LineBreakCharCount;
+
+ if (WrapWidth < 0 && this._LineBreak != LineBreakMethod.None)
+ throw new InvalidOperationException();
+
+ int startIndex = e.index;
+ int endIndex = e.index + e.length - 1;
+
+ LineToIndexTable layoutLineCollection = (LineToIndexTable)sender;
+
+ return this.render.BreakLine(e.buffer,layoutLineCollection, startIndex, endIndex, WrapWidth);
+ }
+
+ IList<LineToIndexTableData> LayoutLines_SpilitStringByChar(object sender, SpilitStringEventArgs e)
+ {
+ return this.Document.CreateLineList(e.index, e.length,1000);
+ }
+ }
+}
-/*\r
- * Copyright (C) 2013 FooProject\r
- * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.\r
-\r
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of \r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\r
-\r
-You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.\r
- */\r
-using System;\r
-using System.Collections.Generic;\r
-using System.Text.RegularExpressions;\r
-\r
-namespace FooEditEngine\r
-{\r
- /// <summary>\r
- /// IMarkerPattern\83C\83\93\83^\81[\83t\83F\83C\83X\r
- /// </summary>\r
- public interface IMarkerPattern\r
- {\r
- /// <summary>\r
- /// \83}\81[\83J\81[\82ð\95Ô\82·\r
- /// </summary>\r
- /// <param name="lineHeadIndex">\8ds\93ª\82Ö\82Ì\83C\83\93\83f\83b\83N\83X\82ð\95\\82·</param>\r
- /// <param name="s">\95¶\8e\9a\97ñ</param>\r
- /// <returns>Marker\97ñ\8b\93\91Ì\82ð\95Ô\82·</returns>\r
- IEnumerable<Marker> GetMarker(int lineHeadIndex, string s);\r
- }\r
- /// <summary>\r
- /// \90³\8bK\95\\8c»\82Å\83}\81[\83J\81[\82Ì\8eæ\93¾\82ð\8ds\82¤\83N\83\89\83X\r
- /// </summary>\r
- public sealed class RegexMarkerPattern : IMarkerPattern\r
- {\r
- Regex regex;\r
- HilightType type;\r
- Color color;\r
- /// <summary>\r
- /// \83R\83\93\83X\83g\83\89\83N\83^\81[\r
- /// </summary>\r
- /// <param name="regex">regex\83I\83u\83W\83F\83N\83g</param>\r
- /// <param name="type">\83n\83C\83\89\83C\83g\83^\83C\83v</param>\r
- /// <param name="color">\90F</param>\r
- public RegexMarkerPattern(Regex regex,HilightType type,Color color)\r
- {\r
- this.regex = regex;\r
- this.type = type;\r
- this.color = color;\r
- }\r
-\r
- /// <summary>\r
- /// \83}\81[\83J\81[\82ð\95Ô\82·\r
- /// </summary>\r
- /// <param name="lineHeadIndex">\8ds\93ª\82Ö\82Ì\83C\83\93\83f\83b\83N\83X\82ð\95\\82·</param>\r
- /// <param name="s">\95¶\8e\9a\97ñ</param>\r
- /// <returns>Marker\97ñ\8b\93\91Ì\82ð\95Ô\82·</returns>\r
- public IEnumerable<Marker> GetMarker(int lineHeadIndex, string s)\r
- {\r
- foreach (Match m in this.regex.Matches(s))\r
- {\r
- yield return Marker.Create(lineHeadIndex + m.Index, m.Length, this.type,this.color);\r
- }\r
- }\r
- }\r
- /// <summary>\r
- /// MarkerPattern\83Z\83b\83g\r
- /// </summary>\r
- public sealed class MarkerPatternSet\r
- {\r
- MarkerCollection markers;\r
- Dictionary<int, IMarkerPattern> set = new Dictionary<int, IMarkerPattern>();\r
-\r
- internal MarkerPatternSet(LineToIndexTable lti,MarkerCollection markers)\r
- {\r
- lti.CreateingLayout += lti_CreateingLayout;\r
- this.markers = markers;\r
- }\r
-\r
- void lti_CreateingLayout(object sender, CreateLayoutEventArgs e)\r
- {\r
- LineToIndexTable lti = (LineToIndexTable)sender;\r
- foreach (int id in this.set.Keys)\r
- {\r
- this.markers.RemoveAll(id, e.Index, e.Length);\r
- this.markers.AddRange(id, this.set[id].GetMarker(e.Index,e.Content));\r
- }\r
- }\r
-\r
- internal event EventHandler Updated;\r
-\r
- /// <summary>\r
- /// WatchDog\82ð\92Ç\89Á\82·\82é\r
- /// </summary>\r
- /// <param name="id">\83}\81[\83J\81[ID</param>\r
- /// <param name="dog">IMarkerPattern\83C\83\93\83^\81[\83t\83F\83C\83X</param>\r
- public void Add(int id, IMarkerPattern dog)\r
- {\r
- this.set.Add(id, dog);\r
- this.Updated(this, null);\r
- }\r
-\r
- /// <summary>\r
- /// \83}\81[\83J\81[ID\82ª\8aÜ\82Ü\82ê\82Ä\82¢\82é\82©\82Ç\82¤\82©\82ð\92²\82×\82é\r
- /// </summary>\r
- /// <param name="id">\83}\81[\83J\81[ID</param>\r
- /// <returns>\8aÜ\82Ü\82ê\82Ä\82¢\82ê\82Î\90^\81B\82»\82¤\82Å\82È\82¯\82ê\82Î\8bU</returns>\r
- public bool Contains(int id)\r
- {\r
- return this.set.ContainsKey(id);\r
- }\r
-\r
- /// <summary>\r
- /// WatchDog\82ð\92Ç\89Á\82·\82é\r
- /// </summary>\r
- /// <param name="id">\83}\81[\83J\81[ID</param>\r
- public void Remove(int id)\r
- {\r
- this.markers.Clear(id);\r
- this.set.Remove(id);\r
- this.Updated(this, null);\r
- }\r
- }\r
+/*
+ * Copyright (C) 2013 FooProject
+ * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+using System.Collections.Generic;
+using System.Text.RegularExpressions;
+
+namespace FooEditEngine
+{
+ /// <summary>
+ /// IMarkerPattern\83C\83\93\83^\81[\83t\83F\83C\83X
+ /// </summary>
+ public interface IMarkerPattern
+ {
+ /// <summary>
+ /// \83}\81[\83J\81[\82ð\95Ô\82·
+ /// </summary>
+ /// <param name="lineHeadIndex">\8ds\93ª\82Ö\82Ì\83C\83\93\83f\83b\83N\83X\82ð\95\\82·</param>
+ /// <param name="s">\95¶\8e\9a\97ñ</param>
+ /// <returns>Marker\97ñ\8b\93\91Ì\82ð\95Ô\82·</returns>
+ IEnumerable<Marker> GetMarker(int lineHeadIndex, string s);
+ }
+ /// <summary>
+ /// \90³\8bK\95\\8c»\82Å\83}\81[\83J\81[\82Ì\8eæ\93¾\82ð\8ds\82¤\83N\83\89\83X
+ /// </summary>
+ public sealed class RegexMarkerPattern : IMarkerPattern
+ {
+ Regex regex;
+ HilightType type;
+ Color color;
+ /// <summary>
+ /// \83R\83\93\83X\83g\83\89\83N\83^\81[
+ /// </summary>
+ /// <param name="regex">regex\83I\83u\83W\83F\83N\83g</param>
+ /// <param name="type">\83n\83C\83\89\83C\83g\83^\83C\83v</param>
+ /// <param name="color">\90F</param>
+ public RegexMarkerPattern(Regex regex,HilightType type,Color color)
+ {
+ this.regex = regex;
+ this.type = type;
+ this.color = color;
+ }
+
+ /// <summary>
+ /// \83}\81[\83J\81[\82ð\95Ô\82·
+ /// </summary>
+ /// <param name="lineHeadIndex">\8ds\93ª\82Ö\82Ì\83C\83\93\83f\83b\83N\83X\82ð\95\\82·</param>
+ /// <param name="s">\95¶\8e\9a\97ñ</param>
+ /// <returns>Marker\97ñ\8b\93\91Ì\82ð\95Ô\82·</returns>
+ public IEnumerable<Marker> GetMarker(int lineHeadIndex, string s)
+ {
+ foreach (Match m in this.regex.Matches(s))
+ {
+ yield return Marker.Create(lineHeadIndex + m.Index, m.Length, this.type,this.color);
+ }
+ }
+ }
+ /// <summary>
+ /// MarkerPattern\83Z\83b\83g
+ /// </summary>
+ public sealed class MarkerPatternSet
+ {
+ MarkerCollection markers;
+ Dictionary<int, IMarkerPattern> set = new Dictionary<int, IMarkerPattern>();
+
+ internal MarkerPatternSet(LineToIndexTable lti,MarkerCollection markers)
+ {
+ lti.CreateingLayout += lti_CreateingLayout;
+ this.markers = markers;
+ }
+
+ void lti_CreateingLayout(object sender, CreateLayoutEventArgs e)
+ {
+ LineToIndexTable lti = (LineToIndexTable)sender;
+ foreach (int id in this.set.Keys)
+ {
+ this.markers.RemoveAll(id, e.Index, e.Length);
+ this.markers.AddRange(id, this.set[id].GetMarker(e.Index,e.Content));
+ }
+ }
+
+ internal event EventHandler Updated;
+
+ /// <summary>
+ /// WatchDog\82ð\92Ç\89Á\82·\82é
+ /// </summary>
+ /// <param name="id">\83}\81[\83J\81[ID</param>
+ /// <param name="dog">IMarkerPattern\83C\83\93\83^\81[\83t\83F\83C\83X</param>
+ public void Add(int id, IMarkerPattern dog)
+ {
+ this.set.Add(id, dog);
+ this.Updated(this, null);
+ }
+
+ /// <summary>
+ /// \83}\81[\83J\81[ID\82ª\8aÜ\82Ü\82ê\82Ä\82¢\82é\82©\82Ç\82¤\82©\82ð\92²\82×\82é
+ /// </summary>
+ /// <param name="id">\83}\81[\83J\81[ID</param>
+ /// <returns>\8aÜ\82Ü\82ê\82Ä\82¢\82ê\82Î\90^\81B\82»\82¤\82Å\82È\82¯\82ê\82Î\8bU</returns>
+ public bool Contains(int id)
+ {
+ return this.set.ContainsKey(id);
+ }
+
+ /// <summary>
+ /// WatchDog\82ð\92Ç\89Á\82·\82é
+ /// </summary>
+ /// <param name="id">\83}\81[\83J\81[ID</param>
+ public void Remove(int id)
+ {
+ this.markers.Clear(id);
+ this.set.Remove(id);
+ this.Updated(this, null);
+ }
+ }
}
\ No newline at end of file
-using System.Reflection;\r
-using System.Runtime.CompilerServices;\r
-using System.Runtime.InteropServices;\r
-\r
-// アセンブリに関する一般情報は以下の属性セットをとおして制御されます。\r
-// アセンブリに関連付けられている情報を変更するには、\r
-// これらの属性値を変更してください。\r
-[assembly: AssemblyTitle("CSTextStore")]\r
-[assembly: AssemblyDescription("")]\r
-[assembly: AssemblyConfiguration("")]\r
-[assembly: AssemblyCompany("")]\r
-[assembly: AssemblyProduct("CSTextStore")]\r
-[assembly: AssemblyCopyright("Copyright © 2012")]\r
-[assembly: AssemblyTrademark("")]\r
-[assembly: AssemblyCulture("")]\r
-\r
-// ComVisible を false に設定すると、その型はこのアセンブリ内で COM コンポーネントから \r
-// 参照不可能になります。COM からこのアセンブリ内の型にアクセスする場合は、\r
-// その型の ComVisible 属性を true に設定してください。\r
-[assembly: ComVisible(false)]\r
-\r
-// 次の GUID は、このプロジェクトが COM に公開される場合の、typelib の ID です\r
-[assembly: Guid("9797fc81-c5c8-4f58-8194-c744e31a0c2f")]\r
-\r
-// アセンブリのバージョン情報は、以下の 4 つの値で構成されています:\r
-//\r
-// Major Version\r
-// Minor Version \r
-// Build Number\r
-// Revision\r
-//\r
-// すべての値を指定するか、下のように '*' を使ってビルドおよびリビジョン番号を \r
-// 既定値にすることができます:\r
-// [assembly: AssemblyVersion("1.0.*")]\r
-[assembly: AssemblyVersion("1.0.0.0")]\r
-[assembly: AssemblyFileVersion("1.0.0.0")]\r
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// アセンブリに関する一般情報は以下の属性セットをとおして制御されます。
+// アセンブリに関連付けられている情報を変更するには、
+// これらの属性値を変更してください。
+[assembly: AssemblyTitle("CSTextStore")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("CSTextStore")]
+[assembly: AssemblyCopyright("Copyright © 2012")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// ComVisible を false に設定すると、その型はこのアセンブリ内で COM コンポーネントから
+// 参照不可能になります。COM からこのアセンブリ内の型にアクセスする場合は、
+// その型の ComVisible 属性を true に設定してください。
+[assembly: ComVisible(false)]
+
+// 次の GUID は、このプロジェクトが COM に公開される場合の、typelib の ID です
+[assembly: Guid("9797fc81-c5c8-4f58-8194-c744e31a0c2f")]
+
+// アセンブリのバージョン情報は、以下の 4 つの値で構成されています:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// すべての値を指定するか、下のように '*' を使ってビルドおよびリビジョン番号を
+// 既定値にすることができます:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
-このプロジェクトファイルは以下の人により制作されました\r
-\r
-WPF(XAML, XBAP, .NET4.0)GUIプログラミング Part13 395\r
+このプロジェクトファイルは以下の人により制作されました
+
+WPF(XAML, XBAP, .NET4.0)GUIプログラミング Part13 395
-using System;\r
-using System.Collections.Generic;\r
-using System.Linq;\r
-using System.Text;\r
-using System.Diagnostics;\r
-using System.Reflection;\r
-using System.Runtime.InteropServices;\r
-using System.Globalization;\r
-\r
-using DotNetTextStore.UnmanagedAPI.TSF;\r
-using DotNetTextStore.UnmanagedAPI.TSF.TextStore;\r
-using DotNetTextStore.UnmanagedAPI.WinDef;\r
-using DotNetTextStore.UnmanagedAPI.WinError;\r
-\r
-namespace DotNetTextStore \r
-{\r
-\r
-\r
- //========================================================================================\r
-\r
- /// <summary>\r
- /// テキストストアの実装を担うクラス。\r
- /// <pre>\r
- /// 各ドキュメント毎に実装すべき部分をイベントとして切り離して、テキストストアの実装を楽に\r
- /// させる。\r
- /// </pre>\r
- /// <pre>\r
- /// 使用側としては各イベントハンドラの実装、フォーカスを取得した時に SetFocus() メソッドの\r
- /// 呼び出し、選択やテキストが変更された時に NotifySelectionChanged() メソッドや\r
- /// NotifyTextChange() メソッドの呼び出しを行う必要がある。\r
- /// </pre>\r
- public sealed class TextStore : TextStoreBase,IDisposable, ITextStoreACP, ITfContextOwnerCompositionSink\r
- {\r
- public delegate IntPtr GetHWndHandler();\r
- public event GetHWndHandler GetHWnd;\r
-\r
- #region "生成と破棄"\r
- /// <summary>\r
- /// 後処理\r
- /// </summary>\r
- public void Dispose()\r
- {\r
- base.Dispose(false);\r
- GC.SuppressFinalize(this);\r
- }\r
- #endregion\r
-\r
- #region ITextStoreACPの実装\r
- public void GetWnd(int i_viewCookie, out IntPtr o_hwnd)\r
- {\r
-#if TSF_DEBUG_OUTPUT\r
- using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )\r
-#endif\r
- {\r
- if (GetHWnd != null)\r
- o_hwnd = GetHWnd();\r
- else\r
- o_hwnd = IntPtr.Zero;\r
- }\r
- }\r
- #endregion\r
-\r
- #region TSF 関連のラッパメソッド\r
- /// <summary>\r
- /// スレッドマネージャの生成\r
- /// </summary>\r
- /// \r
- /// <exception cref="COMException">\r
- /// スレッドマネージャーの生成に失敗した場合。\r
- /// </exception>\r
- protected override void CreateThreadMgr()\r
- {\r
- if( _threadMgr == null )\r
- {\r
- TextFrameworkFunctions.TF_GetThreadMgr(out _threadMgr);\r
- if( _threadMgr == null )\r
- {\r
- Type clsid = Marshal.GetTypeFromCLSID(TfDeclarations.CLSID_TF_ThreadMgr);\r
- _threadMgr = Activator.CreateInstance(clsid) as ITfThreadMgr;\r
-\r
- if( _threadMgr == null )\r
- {\r
- const string message = "スレッドマネージャーの生成に失敗しました。";\r
- Debug.WriteLine(message);\r
- throw new COMException(message, HRESULT.E_NOTIMPL);\r
- }\r
- }\r
- }\r
- }\r
-\r
- #endregion\r
-\r
- }\r
-}\r
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Diagnostics;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Globalization;
+
+using DotNetTextStore.UnmanagedAPI.TSF;
+using DotNetTextStore.UnmanagedAPI.TSF.TextStore;
+using DotNetTextStore.UnmanagedAPI.WinDef;
+using DotNetTextStore.UnmanagedAPI.WinError;
+
+namespace DotNetTextStore
+{
+
+
+ //========================================================================================
+
+ /// <summary>
+ /// テキストストアの実装を担うクラス。
+ /// <pre>
+ /// 各ドキュメント毎に実装すべき部分をイベントとして切り離して、テキストストアの実装を楽に
+ /// させる。
+ /// </pre>
+ /// <pre>
+ /// 使用側としては各イベントハンドラの実装、フォーカスを取得した時に SetFocus() メソッドの
+ /// 呼び出し、選択やテキストが変更された時に NotifySelectionChanged() メソッドや
+ /// NotifyTextChange() メソッドの呼び出しを行う必要がある。
+ /// </pre>
+ public sealed class TextStore : TextStoreBase,IDisposable, ITextStoreACP, ITfContextOwnerCompositionSink
+ {
+ public delegate IntPtr GetHWndHandler();
+ public event GetHWndHandler GetHWnd;
+
+ #region "生成と破棄"
+ /// <summary>
+ /// 後処理
+ /// </summary>
+ public void Dispose()
+ {
+ base.Dispose(false);
+ GC.SuppressFinalize(this);
+ }
+ #endregion
+
+ #region ITextStoreACPの実装
+ public void GetWnd(int i_viewCookie, out IntPtr o_hwnd)
+ {
+#if TSF_DEBUG_OUTPUT
+ using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
+#endif
+ {
+ if (GetHWnd != null)
+ o_hwnd = GetHWnd();
+ else
+ o_hwnd = IntPtr.Zero;
+ }
+ }
+ #endregion
+
+ #region TSF 関連のラッパメソッド
+ /// <summary>
+ /// スレッドマネージャの生成
+ /// </summary>
+ ///
+ /// <exception cref="COMException">
+ /// スレッドマネージャーの生成に失敗した場合。
+ /// </exception>
+ protected override void CreateThreadMgr()
+ {
+ if( _threadMgr == null )
+ {
+ TextFrameworkFunctions.TF_GetThreadMgr(out _threadMgr);
+ if( _threadMgr == null )
+ {
+ Type clsid = Marshal.GetTypeFromCLSID(TfDeclarations.CLSID_TF_ThreadMgr);
+ _threadMgr = Activator.CreateInstance(clsid) as ITfThreadMgr;
+
+ if( _threadMgr == null )
+ {
+ const string message = "スレッドマネージャーの生成に失敗しました。";
+ Debug.WriteLine(message);
+ throw new COMException(message, HRESULT.E_NOTIMPL);
+ }
+ }
+ }
+ }
+
+ #endregion
+
+ }
+}
-//#define TSF_DEBUG_OUTPUT\r
-#define METRO\r
-using System;\r
-using System.Text;\r
-using System.Diagnostics;\r
-using System.Reflection;\r
-using System.Runtime.InteropServices;\r
-using System.Globalization;\r
-\r
-using DotNetTextStore.UnmanagedAPI.TSF;\r
-using DotNetTextStore.UnmanagedAPI.TSF.TextStore;\r
-using DotNetTextStore.UnmanagedAPI.WinDef;\r
-using DotNetTextStore.UnmanagedAPI.WinError;\r
-\r
-namespace DotNetTextStore\r
-{\r
- public sealed class TextStore2 : TextStoreBase, IDisposable, ITextStoreACP2, ITfContextOwnerCompositionSink\r
- {\r
- #region 生成と破棄\r
- public void Dispose()\r
- {\r
- base.Dispose(false);\r
- GC.SuppressFinalize(this);\r
- }\r
-\r
- protected override void CreateThreadMgr()\r
- {\r
- if (_threadMgr == null)\r
- {\r
- Type clsid = Marshal.GetTypeFromCLSID(TfDeclarations.CLSID_TF_ThreadMgr);\r
- ITfThreadMgr2 threadMgr = Activator.CreateInstance(clsid) as ITfThreadMgr2;\r
-\r
- if (threadMgr == null)\r
- {\r
- const string message = "スレッドマネージャーの生成に失敗しました。";\r
- Debug.WriteLine(message);\r
- throw new COMException(message, HRESULT.E_NOTIMPL);\r
- }\r
-\r
- this._threadMgr = threadMgr;\r
- }\r
- }\r
-\r
- #endregion\r
- }\r
-}\r
+//#define TSF_DEBUG_OUTPUT
+#define METRO
+using System;
+using System.Text;
+using System.Diagnostics;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Globalization;
+
+using DotNetTextStore.UnmanagedAPI.TSF;
+using DotNetTextStore.UnmanagedAPI.TSF.TextStore;
+using DotNetTextStore.UnmanagedAPI.WinDef;
+using DotNetTextStore.UnmanagedAPI.WinError;
+
+namespace DotNetTextStore
+{
+ public sealed class TextStore2 : TextStoreBase, IDisposable, ITextStoreACP2, ITfContextOwnerCompositionSink
+ {
+ #region 生成と破棄
+ public void Dispose()
+ {
+ base.Dispose(false);
+ GC.SuppressFinalize(this);
+ }
+
+ protected override void CreateThreadMgr()
+ {
+ if (_threadMgr == null)
+ {
+ Type clsid = Marshal.GetTypeFromCLSID(TfDeclarations.CLSID_TF_ThreadMgr);
+ ITfThreadMgr2 threadMgr = Activator.CreateInstance(clsid) as ITfThreadMgr2;
+
+ if (threadMgr == null)
+ {
+ const string message = "スレッドマネージャーの生成に失敗しました。";
+ Debug.WriteLine(message);
+ throw new COMException(message, HRESULT.E_NOTIMPL);
+ }
+
+ this._threadMgr = threadMgr;
+ }
+ }
+
+ #endregion
+ }
+}
-// TSF のデバッグ表示を行うかどうか?\r
-//#define TSF_DEBUG_OUTPUT\r
-//#define TSF_DEBUG_OUTPUT_DISPLAY_ATTR\r
-using System;\r
-using System.Collections.Generic;\r
-using System.Linq;\r
-using System.Text;\r
-using System.Diagnostics;\r
-using System.Reflection;\r
-using System.Runtime.CompilerServices;\r
-using System.Runtime.InteropServices;\r
-using System.Globalization;\r
-\r
-using DotNetTextStore.UnmanagedAPI.TSF;\r
-using DotNetTextStore.UnmanagedAPI.TSF.TextStore;\r
-using DotNetTextStore.UnmanagedAPI.WinDef;\r
-using DotNetTextStore.UnmanagedAPI.WinError;\r
-\r
-namespace DotNetTextStore\r
-{\r
-#if TSF_DEBUG_OUTPUT\r
- /// <summary>コールスタックの階層にあわせてインデントしてデバッグ表示するクラス。</summary>\r
- public class DebugOut : IDisposable\r
- {\r
- public DebugOut(string i_string, params object[] i_params)\r
- {\r
- _text = string.Format(i_string, i_params);\r
-\r
- s_callCount++;\r
- Debug.WriteLine("");\r
- Debug.WriteLine(string.Format("{0, 4} : ↓↓↓ ", s_callCount) + _text);\r
- }\r
-\r
- public static void Print(string i_string, params object[] i_params)\r
- {\r
- Debug.WriteLine(i_string, i_params);\r
- }\r
-\r
- public void Dispose()\r
- {\r
- s_callCount++;\r
- Debug.WriteLine(string.Format("{0, 4} : ↑↑↑ ", s_callCount) + _text);\r
- }\r
-\r
- public static string GetCaller([CallerMemberName] string caller="")\r
- {\r
- return caller;\r
- }\r
-\r
- string _text;\r
- static int s_callCount = 0;\r
- }\r
-#endif\r
-\r
- //=============================================================================================\r
-\r
-\r
- public struct TextDisplayAttribute\r
- {\r
- public int startIndex;\r
- public int endIndex;\r
- public TF_DISPLAYATTRIBUTE attribute;\r
- }\r
-\r
- //========================================================================================\r
-\r
-\r
- /// <summary>Dispose() で TextStore のロック解除を行うクラス。</summary>\r
- public class Unlocker : IDisposable\r
- {\r
- /// <summary>コンストラクタ</summary>\r
- public Unlocker(TextStoreBase io_textStore)\r
- {\r
- _textStore = io_textStore;\r
- }\r
- /// <summary>ロックが成功したかどうか調べる。</summary>\r
- public bool IsLocked\r
- {\r
- get { return _textStore != null; }\r
- }\r
- /// <summary>アンロックを行う。</summary>\r
- void IDisposable.Dispose()\r
- {\r
- if (_textStore != null)\r
- {\r
- _textStore.UnlockDocument();\r
- _textStore = null;\r
- }\r
- }\r
-\r
- /// <summary>アンロックを行うテキストストア</summary>\r
- TextStoreBase _textStore;\r
- }\r
-\r
- public abstract class TextStoreBase\r
- {\r
- public delegate bool IsReadOnlyHandler();\r
- public event IsReadOnlyHandler IsReadOnly;\r
-\r
- public delegate bool IsLoadingHandler();\r
- public event IsLoadingHandler IsLoading;\r
-\r
- public delegate int GetStringLengthHandler();\r
- public event GetStringLengthHandler GetStringLength;\r
-\r
- public delegate void GetSelectionIndexHandler(out int o_start, out int o_end);\r
- public event GetSelectionIndexHandler GetSelectionIndex;\r
-\r
- public delegate void SetSelectionIndexHandler(int i_start, int i_end);\r
- public event SetSelectionIndexHandler SetSelectionIndex;\r
-\r
- public delegate string GetStringHandler(int start, int length);\r
- public event GetStringHandler GetString;\r
-\r
- public delegate void InsertAtSelectionHandler(string i_value,ref int o_startIndex,ref int o_endIndex);\r
- public event InsertAtSelectionHandler InsertAtSelection;\r
-\r
- public delegate void GetScreenExtentHandler(\r
- out POINT o_pointTopLeft,\r
- out POINT o_pointBottomRight\r
- );\r
- public event GetScreenExtentHandler GetScreenExtent;\r
-\r
- public delegate void GetStringExtentHandler(\r
- int i_startIndex,\r
- int i_endIndex,\r
- out POINT o_pointTopLeft,\r
- out POINT o_pointBottomRight\r
- );\r
- public event GetStringExtentHandler GetStringExtent;\r
-\r
- public delegate bool CompositionStartedHandler();\r
- public event CompositionStartedHandler CompositionStarted;\r
-\r
- public delegate void CompostionUpdateHandler(int start, int end);\r
- public event CompostionUpdateHandler CompositionUpdated;\r
-\r
- public delegate void CompositionEndedHandler();\r
- public event CompositionEndedHandler CompositionEnded;\r
-\r
- #region "生成と破棄"\r
- public TextStoreBase()\r
- {\r
-#if TSF_DEBUG_OUTPUT\r
- using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )\r
-#endif\r
- {\r
- try\r
- {\r
- // スレッドマネージャ-の生成\r
- CreateThreadMgr();\r
- // カテゴリマネージャーの生成\r
- CreateCategoryMgr();\r
- // 表示属性マネージャーの生成\r
- CreateDisplayAttributeMgr();\r
-\r
- // ドキュメントマネージャーの生成\r
- _threadMgr.CreateDocumentMgr(out _documentMgr);\r
-\r
- // スレッドマネージャのアクティブ化\r
- int clientId = 0;\r
- _threadMgr.Activate(out clientId);\r
-\r
- // コンテキストの生成\r
- _documentMgr.CreateContext(clientId, 0, this, out _context, out _editCookie);\r
-\r
- // コンテキストの push\r
- _documentMgr.Push(_context);\r
-\r
- // ファンクションプロバイダーを取得する。\r
- Guid guid = TfDeclarations.GUID_SYSTEM_FUNCTIONPROVIDER;\r
- _threadMgr.GetFunctionProvider(ref guid, out _functionProvider);\r
-\r
- // ITfReconversion オブジェクトを取得する。\r
- var guidNull = new Guid();\r
- var guidReconversion = new Guid("4cea93c0-0a58-11d3-8df0-00105a2799b5"); //ITfFnReconversionの定義から\r
- object reconversion = null;\r
- _functionProvider.GetFunction(\r
- ref guidNull,\r
- ref guidReconversion,\r
- out reconversion\r
- );\r
- _reconversion = reconversion as ITfFnReconversion;\r
-\r
- // MODEBIAS の初期化\r
- uint guidAtom = 0;\r
- Guid guidModebiasNone = TfDeclarations.GUID_MODEBIAS_NONE;\r
- _categoryMgr.RegisterGUID(ref guidModebiasNone, out guidAtom);\r
- _attributeInfo[0].attrID = TfDeclarations.GUID_PROP_MODEBIAS;\r
- _attributeInfo[0].flags = AttributeInfoFlags.None;\r
- _attributeInfo[0].currentValue.vt = (short)VarEnum.VT_EMPTY;\r
- _attributeInfo[0].defaultValue.vt = (short)VarEnum.VT_I4;\r
- _attributeInfo[0].defaultValue.data1 = (IntPtr)guidAtom;\r
- }\r
- catch (Exception exception)\r
- {\r
- Debug.WriteLine(exception.Message);\r
- Dispose(false);\r
- }\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// オブジェクトの破棄を行う。このメソッドは必ず呼び出す必要があります\r
- /// </summary>\r
- /// <param name="flag"></param>\r
- protected void Dispose(bool flag)\r
- {\r
- if (flag)\r
- return;\r
-#if TSF_DEBUG_OUTPUT\r
- using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )\r
-#endif\r
- {\r
- ReleaseComObject("_reconversion", ref _reconversion);\r
- ReleaseComObject("_functionProvider", ref _functionProvider);\r
- ReleaseComObject("_context", ref _context);\r
- DestroyDocumentMgr();\r
- DestroyDisplayAttributeMgr();\r
- DestroyCategoryMgr();\r
- DestroyThreadMgr();\r
-\r
- GC.SuppressFinalize(this);\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// スレッドマネージャの生成。このメソッドの実装は必須です\r
- /// </summary>\r
- /// \r
- /// <exception cref="COMException">\r
- /// スレッドマネージャーの生成に失敗した場合。\r
- /// </exception>\r
- protected virtual void CreateThreadMgr()\r
- {\r
- throw new NotImplementedException();\r
- }\r
-\r
- /// <summary>\r
- /// スレッドマネージャーの解放。\r
- /// </summary>\r
- void DestroyThreadMgr()\r
- {\r
- if (_threadMgr != null)\r
- {\r
- try { _threadMgr.Deactivate(); }\r
- catch (Exception) { }\r
-\r
- ReleaseComObject("_threadMgr", ref _threadMgr);\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// カテゴリマネージャーの生成。\r
- /// </summary>\r
- /// \r
- /// <exception cref="COMException">\r
- /// カテゴリマネージャーの生成に失敗した場合。\r
- /// </exception>\r
- void CreateCategoryMgr()\r
- {\r
- if (_categoryMgr == null)\r
- {\r
- var clsid = Marshal.GetTypeFromCLSID(TfDeclarations.CLSID_TF_CategoryMgr);\r
- _categoryMgr = Activator.CreateInstance(clsid) as ITfCategoryMgr;\r
-\r
- if (_categoryMgr == null)\r
- {\r
- const string message = "カテゴリマネージャーの生成に失敗しました。";\r
- Debug.WriteLine(message);\r
- throw new COMException(message, HRESULT.E_NOTIMPL);\r
- }\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// カテゴリマネージャーの解放。\r
- /// </summary>\r
- void DestroyCategoryMgr()\r
- {\r
- ReleaseComObject("_categoryMgr", ref _categoryMgr);\r
- }\r
-\r
- /// <summary>\r
- /// 表示属性マネージャーの生成。\r
- /// </summary>\r
- /// \r
- /// <exception cref="COMException">\r
- /// 表示属性マネージャーの生成に失敗した場合。\r
- /// </exception>\r
- void CreateDisplayAttributeMgr()\r
- {\r
- if (_displayAttributeMgr == null)\r
- {\r
- var clsid = Marshal.GetTypeFromCLSID(TfDeclarations.CLSID_TF_DisplayAttributeMgr);\r
- _displayAttributeMgr = Activator.CreateInstance(clsid) as ITfDisplayAttributeMgr;\r
-\r
- if (_displayAttributeMgr == null)\r
- {\r
- const string message = "表示属性マネージャーの生成に失敗しました。";\r
- Debug.WriteLine(message);\r
- throw new COMException(message, HRESULT.E_NOTIMPL);\r
- }\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// 表示属性マネージャーの解放。\r
- /// </summary>\r
- void DestroyDisplayAttributeMgr()\r
- {\r
- ReleaseComObject("_displayAttributeMgr", ref _displayAttributeMgr);\r
- }\r
-\r
- /// <summary>\r
- /// ドキュメントマネージャーの解放\r
- /// </summary>\r
- void DestroyDocumentMgr()\r
- {\r
- if (_documentMgr != null)\r
- {\r
- try { _documentMgr.Pop(PopFlags.TF_POPF_ALL); }\r
- catch (Exception) { }\r
-\r
- ReleaseComObject("_documentMgr", ref _documentMgr);\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// COM オブジェクトのリリースとデバッグメッセージ出力。\r
- /// </summary>\r
- protected static void ReleaseComObject<ComObject>(\r
- string i_objectName,\r
- ref ComObject io_comObject\r
- )\r
- {\r
- if (io_comObject != null)\r
- {\r
- var refCount = Marshal.ReleaseComObject(io_comObject);\r
-#if TSF_DEBUG_OUTPUT\r
- Debug.WriteLine(\r
- "Marshal.ReleaseComObject({0}) returns {1}.",\r
- i_objectName,\r
- refCount\r
- );\r
-#endif\r
-\r
- io_comObject = default(ComObject);\r
- }\r
- }\r
- #endregion\r
-\r
- #region "コントロール側が状況に応じて呼び出さなければいけない TSF に通知を送るメソッド"\r
- /// <summary>\r
- /// 選択領域が変更されたことをTSFに伝える。各種ハンドラ内からコールしてはいけない。\r
- /// </summary>\r
- public void NotifySelectionChanged()\r
- {\r
- if( _sink != null )\r
- {\r
-#if TSF_DEBUG_OUTPUT\r
- DebugOut.Print(DebugOut.GetCaller());\r
-#endif\r
- if ((_adviseFlags & AdviseFlags.TS_AS_SEL_CHANGE) != 0)\r
- _sink.OnSelectionChange();\r
- }\r
- }\r
-\r
- \r
- //=========================================================================================\r
-\r
-\r
- /// <summary>\r
- /// テキストが変更されたことをTSFに伝える。各種ハンドラ内からコールしてはいけない。\r
- /// </summary>\r
- void NotifyTextChanged(TS_TEXTCHANGE textChange)\r
- {\r
- if( _sink != null )\r
- {\r
-#if TSF_DEBUG_OUTPUT\r
- DebugOut.Print(DebugOut.GetCaller());\r
-#endif\r
- if ((_adviseFlags & AdviseFlags.TS_AS_TEXT_CHANGE) != 0)\r
- _sink.OnTextChange(0, ref textChange);\r
- _sink.OnLayoutChange(TsLayoutCode.TS_LC_CHANGE, 1);\r
- }\r
- }\r
-\r
- \r
- //=========================================================================================\r
-\r
- /// <summary>\r
- /// テキストが変更されたことをTSFに伝える。各種ハンドラ内からコールしてはいけない。\r
- /// </summary>\r
- /// <param name="start">開始位置</param>\r
- /// <param name="oldend">更新前の終了位置</param>\r
- /// <param name="newend">更新後の終了位置</param>\r
- /// <remarks>\r
- /// 詳しいことはITextStoreACPSink::OnTextChangeを参照してください\r
- /// </remarks>\r
- public void NotifyTextChanged(int start,int oldend,int newend)\r
- {\r
- if (_sink != null)\r
- {\r
-#if TSF_DEBUG_OUTPUT\r
- DebugOut.Print(DebugOut.GetCaller());\r
-#endif\r
- if ((_adviseFlags & AdviseFlags.TS_AS_TEXT_CHANGE) != 0)\r
- {\r
- var textChange = new TS_TEXTCHANGE();\r
- textChange.start = start;\r
- textChange.oldEnd = oldend;\r
- textChange.newEnd = newend;\r
-\r
- _sink.OnTextChange(0, ref textChange);\r
- }\r
- _sink.OnLayoutChange(TsLayoutCode.TS_LC_CHANGE, 1);\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// テキストが変更されたことをTSFに伝える。各種ハンドラ内からコールしてはいけない。\r
- /// </summary>\r
- /// <param name="i_oldLength"></param>\r
- /// <param name="i_newLength"></param>\r
- public void NotifyTextChanged(int i_oldLength, int i_newLength)\r
- {\r
- if( _sink != null )\r
- {\r
-#if TSF_DEBUG_OUTPUT\r
- DebugOut.Print(DebugOut.GetCaller());\r
-#endif\r
- if ((_adviseFlags & AdviseFlags.TS_AS_TEXT_CHANGE) != 0)\r
- {\r
- var textChange = new TS_TEXTCHANGE();\r
- textChange.start = 0;\r
- textChange.oldEnd = i_oldLength;\r
- textChange.newEnd = i_newLength;\r
-\r
- _sink.OnTextChange(0, ref textChange);\r
- }\r
- _sink.OnLayoutChange(TsLayoutCode.TS_LC_CHANGE, 1);\r
- }\r
- }\r
-\r
- \r
- \r
- //=========================================================================================\r
-\r
-\r
- /// <summary>コントロールがフォーカスを取得した時に呼び出さなければいけない。</summary>\r
- public void SetFocus()\r
- {\r
-#if TSF_DEBUG_OUTPUT\r
- DebugOut.Print(DebugOut.GetCaller());\r
-#endif\r
- if (_threadMgr != null)\r
- _threadMgr.SetFocus(_documentMgr);\r
- }\r
- #endregion "コントロール側が状況に応じて呼び出さなければいけない TSF に通知を送るメソッド"\r
-\r
- #region ロック関連\r
- /// <summary>\r
- /// ドキュメントのロックを行う。\r
- /// </summary>\r
- /// <param name="i_writable">読み書き両用ロックか?false の場合、読み取り専用。</param>\r
- /// <returns>Unlocker のインスタンスを返す。失敗した場合 null を返す。</returns>\r
- public Unlocker LockDocument(bool i_writable)\r
- {\r
- #if TSF_DEBUG_OUTPUT\r
- using(var dbgout = new DebugOut("{0}({1})", DebugOut.GetCaller(),\r
- i_writable) )\r
- #endif\r
- {\r
- lock(this)\r
- {\r
- if( this._lockFlags == 0 )\r
- {\r
- if( i_writable )\r
- this._lockFlags = LockFlags.TS_LF_READWRITE;\r
- else\r
- this._lockFlags = LockFlags.TS_LF_READ;\r
-\r
- #if TSF_DEBUG_OUTPUT\r
- Debug.WriteLine("LockDocument is succeeded.");\r
- #endif\r
-\r
- return new Unlocker(this);\r
- }\r
- else\r
- {\r
- #if TSF_DEBUG_OUTPUT\r
- Debug.WriteLine("LockDocument is failed. {0}", _lockFlags);\r
- #endif\r
-\r
- return null;\r
- }\r
- }\r
- }\r
- }\r
-\r
-\r
- //========================================================================================\r
-\r
- \r
- /// <summary>\r
- /// ドキュメントのロックを行う。\r
- /// </summary>\r
- /// <param name="i_writable">読み書き両用ロックか?false の場合、読み取り専用。</param>\r
- /// <returns>Unlocker のインスタンスを返す。失敗した場合 null を返す。</returns>\r
- public Unlocker LockDocument(LockFlags i_flags)\r
- {\r
- #if TSF_DEBUG_OUTPUT\r
- using(var dbgout = new DebugOut("{0}({1})", DebugOut.GetCaller(),\r
- i_flags) )\r
- #endif\r
- {\r
- lock(this)\r
- {\r
- if( this._lockFlags == 0 )\r
- {\r
- this._lockFlags = i_flags;\r
-\r
- #if TSF_DEBUG_OUTPUT\r
- Debug.WriteLine("LockDocument is succeeded.");\r
- #endif\r
-\r
- return new Unlocker(this);\r
- }\r
- else\r
- {\r
- #if TSF_DEBUG_OUTPUT\r
- Debug.WriteLine("LockDocument is failed. {0}", _lockFlags);\r
- #endif\r
-\r
- return null;\r
- }\r
- }\r
- }\r
- }\r
-\r
-\r
- //========================================================================================\r
-\r
- \r
- /// <summary>\r
- /// ドキュメントのアンロックを行う。\r
- /// </summary>\r
- public void UnlockDocument()\r
- {\r
- #if TSF_DEBUG_OUTPUT\r
- using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )\r
- #endif\r
- {\r
- lock(this)\r
- {\r
- _lockFlags = 0;\r
- }\r
-\r
- if( _pendingLockUpgrade )\r
- {\r
- _pendingLockUpgrade = false;\r
- int sessionResult;\r
- RequestLock(LockFlags.TS_LF_READWRITE, out sessionResult);\r
- }\r
- }\r
- }\r
-\r
-\r
- //========================================================================================\r
-\r
- \r
- /// <summary>\r
- /// 指定されたフラグでロックしている状態かどうか調べる。\r
- /// </summary>\r
- /// <param name="i_lockFlags"></param>\r
- /// <returns>ロックされている場合は true, されていない場合は false を返す。</returns>\r
- public bool IsLocked(LockFlags i_lockFlags)\r
- {\r
- #if TSF_DEBUG_OUTPUT\r
- using(var dbgout = new DebugOut("{0}({1})",\r
- DebugOut.GetCaller(), i_lockFlags) )\r
- #endif\r
- {\r
- #if TSF_DEBUG_OUTPUT\r
- Debug.WriteLine(\r
- "IsLocked() returns " + ((this._lockFlags & i_lockFlags) == i_lockFlags)\r
- );\r
- #endif\r
- return (this._lockFlags & i_lockFlags) == i_lockFlags;\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// ロックされているか調べる\r
- /// </summary>\r
- /// <returns>ロックされているなら真、そうでなければ偽を返す</returns>\r
- public bool IsLocked()\r
- {\r
-#if TSF_DEBUG_OUTPUT\r
- using(var dbgout = new DebugOut("{0}",\r
- DebugOut.GetCaller()) )\r
-#endif\r
- {\r
- bool retval = this._lockFlags != 0;\r
-#if TSF_DEBUG_OUTPUT\r
- Debug.WriteLine(\r
- "IsLocked() returns " + retval\r
- );\r
-#endif\r
- return retval;\r
- }\r
- }\r
- #endregion\r
-\r
- #region ITextStroeACP,ITextStoreACP2の共通部分\r
-\r
- /// <summary>\r
- /// 文字列を挿入する。\r
- /// </summary>\r
- public void InsertTextAtSelection(string s)\r
- {\r
- TS_TEXTCHANGE textChange = new TS_TEXTCHANGE();\r
-\r
- using (var unlocker = LockDocument(true))\r
- {\r
- if (unlocker != null)\r
- {\r
- int startIndex, endIndex;\r
-\r
- InsertTextAtSelection(\r
- UnmanagedAPI.TSF.TextStore.InsertAtSelectionFlags.TF_IAS_NOQUERY,\r
- s.ToCharArray(),\r
- s.Length,\r
- out startIndex,\r
- out endIndex,\r
- out textChange\r
- );\r
- }\r
- }\r
-\r
- // シンクの OnSelectionChange() をコール。\r
- NotifySelectionChanged();\r
- NotifyTextChanged(textChange);\r
- }\r
-\r
- public void InsertEmbeddedAtSelection(\r
- InsertAtSelectionFlags flags,\r
- object obj,\r
- out int start,\r
- out int end,\r
- out TS_TEXTCHANGE change\r
- )\r
- {\r
-#if TSF_DEBUG_OUTPUT\r
- using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )\r
-#endif\r
- {\r
- throw new NotImplementedException();\r
- }\r
- }\r
-\r
- public void AdviseSink(ref Guid i_riid, object i_unknown, AdviseFlags i_mask)\r
- {\r
-#if TSF_DEBUG_OUTPUT\r
- using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )\r
-#endif\r
- {\r
- if (i_riid != new Guid("22d44c94-a419-4542-a272-ae26093ececf")) //ITextStoreACPSinkの定義より\r
- {\r
- throw new COMException(\r
- "ITextStoreACPSink 以外のIIDが渡されました。",\r
- UnmanagedAPI.WinError.HRESULT.E_INVALIDARG\r
- );\r
- }\r
-\r
- // 既存のシンクのマスクのみを更新\r
- if (_sink == i_unknown)\r
- {\r
- _adviseFlags = i_mask;\r
- }\r
- // シンクを複数登録しようとした\r
- else if (_sink != null)\r
- {\r
- throw new COMException(\r
- "既にシンクを登録済みです。",\r
- UnmanagedAPI.TSF.TextStore.TsResult.CONNECT_E_ADVISELIMIT\r
- );\r
- }\r
- else\r
- {\r
- // 各種値を保存\r
- _services = (ITextStoreACPServices)i_unknown;\r
- _sink = (ITextStoreACPSink)i_unknown;\r
- _adviseFlags = i_mask;\r
- }\r
- }\r
- }\r
-\r
- public void UnadviseSink(object i_unknown)\r
- {\r
-#if TSF_DEBUG_OUTPUT\r
- using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )\r
-#endif\r
- {\r
- if (_sink == null || _sink != i_unknown)\r
- {\r
- throw new COMException(\r
- "シンクは登録されていません。",\r
- UnmanagedAPI.TSF.TextStore.TsResult.CONNECT_E_NOCONNECTION\r
- );\r
- }\r
-\r
- _services = null;\r
- _sink = null;\r
- _adviseFlags = 0;\r
- }\r
- }\r
-\r
- public void RequestLock(LockFlags i_lockFlags, out int o_sessionResult)\r
- {\r
-#if TSF_DEBUG_OUTPUT\r
- using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )\r
-#endif\r
- {\r
- o_sessionResult = UnmanagedAPI.WinError.HRESULT.E_FAIL;\r
-\r
- if (_sink == null)\r
- {\r
- throw new COMException(\r
- "シンクが登録されていません。",\r
- UnmanagedAPI.TSF.TextStore.TsResult.CONNECT_E_NOCONNECTION\r
- );\r
- }\r
-\r
- if (_lockFlags != 0) // すでにロックされた状態の場合。\r
- {\r
- if ((i_lockFlags & LockFlags.TS_LF_SYNC) != 0)\r
- {\r
- o_sessionResult = TsResult.TS_E_SYNCHRONOUS;\r
- return;\r
- }\r
- else\r
- if ((_lockFlags & LockFlags.TS_LF_READWRITE) == LockFlags.TS_LF_READ\r
- && (i_lockFlags & LockFlags.TS_LF_READWRITE) == LockFlags.TS_LF_READWRITE)\r
- {\r
- _pendingLockUpgrade = true;\r
- o_sessionResult = TsResult.TS_S_ASYNC;\r
- return;\r
- }\r
-\r
- throw new COMException();\r
- }\r
-\r
- using (var unlocker = LockDocument(i_lockFlags))\r
- {\r
- // ロックに失敗した場合は TS_E_SYNCHRONOUS をセットして S_OK を返す。\r
- if (unlocker == null)\r
- {\r
- o_sessionResult = TsResult.TS_E_SYNCHRONOUS;\r
- }\r
- // ロックに成功した場合は OnLockGranted() を呼び出す。\r
- else\r
- {\r
- try\r
- {\r
- o_sessionResult = _sink.OnLockGranted(i_lockFlags);\r
- }\r
- catch (COMException comException)\r
- {\r
- Debug.WriteLine("OnLockGranted() 呼び出し中に例外が発生。");\r
- Debug.WriteLine(" " + comException.Message);\r
- o_sessionResult = comException.HResult;\r
- }\r
- catch (Exception exception)\r
- {\r
- Debug.WriteLine("OnLockGranted() 呼び出し中に例外が発生。");\r
- Debug.WriteLine(" " + exception.Message);\r
- }\r
- }\r
- }\r
- }\r
- }\r
-\r
- public void GetStatus(out TS_STATUS o_documentStatus)\r
- {\r
-#if TSF_DEBUG_OUTPUT\r
- using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )\r
-#endif\r
- {\r
- if (IsReadOnly != null && IsReadOnly())\r
- o_documentStatus.dynamicFlags = DynamicStatusFlags.TS_SD_READONLY;\r
- if (IsLoading != null && IsLoading())\r
- o_documentStatus.dynamicFlags = DynamicStatusFlags.TS_SD_LOADING;\r
- else\r
- o_documentStatus.dynamicFlags = 0;\r
- o_documentStatus.staticFlags = StaticStatusFlags.TS_SS_REGIONS;\r
- }\r
- }\r
-\r
- public void QueryInsert(\r
- int i_startIndex,\r
- int i_endIndex,\r
- int i_length,\r
- out int o_startIndex,\r
- out int o_endIndex\r
- )\r
- {\r
-#if TSF_DEBUG_OUTPUT\r
- using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )\r
-#endif\r
- {\r
- if (GetStringLength == null)\r
- throw new NotImplementedException();\r
-\r
- int documentLength = GetStringLength();\r
-\r
- if (i_startIndex < 0\r
- || i_startIndex > i_endIndex\r
- || i_endIndex > documentLength)\r
- {\r
- throw new COMException(\r
- "インデックスが無効です。",\r
- UnmanagedAPI.WinError.HRESULT.E_INVALIDARG\r
- );\r
- }\r
- o_startIndex = i_startIndex;\r
- o_endIndex = i_endIndex;\r
-\r
-#if TSF_DEBUG_OUTPUT\r
- DebugOut.Print("o_startIndex:{0} o_endIndex:{1}", i_startIndex, i_endIndex);\r
-#endif\r
- }\r
- }\r
-\r
- public void GetSelection(\r
- int i_index,\r
- int i_selectionBufferLength,\r
- TS_SELECTION_ACP[] o_selections,\r
- out int o_fetchedLength\r
- )\r
- {\r
-#if TSF_DEBUG_OUTPUT\r
- using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )\r
-#endif\r
- {\r
- if (GetSelectionIndex == null)\r
- throw new NotImplementedException();\r
-\r
- o_fetchedLength = 0;\r
-\r
- if (IsLocked(LockFlags.TS_LF_READ) == false)\r
- {\r
- throw new COMException(\r
- "読取用ロックがされていません。",\r
- TsResult.TS_E_NOLOCK\r
- );\r
- }\r
-\r
- // -1 は TF_DEFAULT_SELECTION。選択は1つだけしかサポートしないので、\r
- // TF_DEFAULT_SELECTION でもなく、0 を超える数値が指定された場合はエラー。\r
- if (i_index != -1 && i_index > 0)\r
- {\r
- throw new COMException(\r
- "選択は1つだけしかサポートしていません。",\r
- UnmanagedAPI.WinError.HRESULT.E_INVALIDARG\r
- );\r
- }\r
-\r
- if (i_selectionBufferLength > 0)\r
- {\r
- int start = 0, end = 0;\r
- GetSelectionIndex(out start, out end);\r
- if (start <= end)\r
- {\r
- o_selections[0].start = start;\r
- o_selections[0].end = end;\r
- o_selections[0].style.ase = TsActiveSelEnd.TS_AE_END;\r
- o_selections[0].style.interimChar = false;\r
- }\r
- else\r
- {\r
- o_selections[0].start = end;\r
- o_selections[0].end = start;\r
- o_selections[0].style.ase = TsActiveSelEnd.TS_AE_START;\r
- o_selections[0].style.interimChar = false;\r
- }\r
-\r
- o_fetchedLength = 1;\r
-\r
-#if TSF_DEBUG_OUTPUT\r
- DebugOut.Print("sel start:{0} end:{1}", start, end);\r
-#endif\r
- }\r
- }\r
- }\r
-\r
- public void SetSelection(int i_count, TS_SELECTION_ACP[] i_selections)\r
- {\r
-#if TSF_DEBUG_OUTPUT\r
- using(var dbgout = new DebugOut("{0}({1}, {2})",\r
- DebugOut.GetCaller(),\r
- i_selections[0].start,\r
- i_selections[0].end))\r
-#endif\r
- {\r
- if (SetSelectionIndex == null)\r
- throw new NotImplementedException();\r
-\r
- if (i_count != 1)\r
- {\r
- throw new COMException(\r
- "選択は1つだけしかサポートしていません。",\r
- UnmanagedAPI.WinError.HRESULT.E_INVALIDARG\r
- );\r
- }\r
-\r
- if (IsLocked(LockFlags.TS_LF_READWRITE) == false)\r
- {\r
- throw new COMException(\r
- "ロックされていません。",\r
- TsResult.TS_E_NOLOCK\r
- );\r
- }\r
-\r
- SetSelectionIndex(i_selections[0].start, i_selections[0].end);\r
-\r
-#if TSF_DEBUG_OUTPUT\r
- DebugOut.Print("set selection startIndex:{0} endIndex:{1}", i_selections[0].start, i_selections[0].end);\r
-#endif\r
- }\r
- }\r
-\r
- public void GetText(\r
- int i_startIndex,\r
- int i_endIndex,\r
- char[] o_plainText,\r
- int i_plainTextLength,\r
- out int o_plainTextLength,\r
- TS_RUNINFO[] o_runInfos,\r
- int i_runInfoLength,\r
- out int o_runInfoLength,\r
- out int o_nextUnreadCharPos\r
- )\r
- {\r
-#if TSF_DEBUG_OUTPUT\r
- using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )\r
-#endif\r
- {\r
- if (GetStringLength == null || GetString == null)\r
- throw new NotImplementedException();\r
-\r
- if (IsLocked(LockFlags.TS_LF_READ) == false)\r
- {\r
- throw new COMException(\r
- "読取用ロックがされていません。",\r
- TsResult.TS_E_NOLOCK\r
- );\r
- }\r
-\r
- if ((i_endIndex != -1 && i_startIndex > i_endIndex)\r
- || i_startIndex < 0 || i_startIndex > GetStringLength()\r
- || i_endIndex > GetStringLength())\r
- {\r
- throw new COMException(\r
- "インデックスが無効です。",\r
- UnmanagedAPI.WinError.HRESULT.E_INVALIDARG\r
- );\r
- }\r
-\r
- var textLength = 0;\r
- var copyLength = 0;\r
-\r
- if (i_endIndex == -1)\r
- textLength = GetStringLength() - i_startIndex;\r
- else\r
- textLength = i_endIndex - i_startIndex;\r
- copyLength = Math.Min(i_plainTextLength, textLength);\r
-\r
- // 文字列を格納。\r
- var text = GetString(i_startIndex, copyLength);\r
-#if TSF_DEBUG_OUTPUT\r
- DebugOut.Print("got text:{0} from {1} length {2}", text,i_startIndex,copyLength);\r
-#endif\r
- for (int i = 0; i < copyLength; i++)\r
- {\r
- o_plainText[i] = text[i];\r
- }\r
-\r
- // 文字数を格納。\r
- o_plainTextLength = copyLength;\r
- // RUNINFO を格納。\r
- if (i_runInfoLength > 0)\r
- {\r
- o_runInfos[0].type = TsRunType.TS_RT_PLAIN;\r
- o_runInfos[0].length = copyLength;\r
- }\r
- o_runInfoLength = 1;\r
-\r
- // 次の文字の位置を格納。\r
- o_nextUnreadCharPos = i_startIndex + copyLength;\r
- }\r
- }\r
-\r
- public void SetText(\r
- SetTextFlags i_flags,\r
- int i_startIndex,\r
- int i_endIndex,\r
- char[] i_text,\r
- int i_length,\r
- out TS_TEXTCHANGE o_textChange\r
- )\r
- {\r
-#if TSF_DEBUG_OUTPUT\r
- using(var dbgout = new DebugOut("{0}({1}, {2})",\r
- DebugOut.GetCaller(),\r
- i_startIndex, i_endIndex) )\r
-#endif\r
- {\r
- var selections = new TS_SELECTION_ACP[]\r
- {\r
- new TS_SELECTION_ACP\r
- {\r
- start = i_startIndex,\r
- end = i_endIndex,\r
- style = new TS_SELECTIONSTYLE\r
- {\r
- ase = TsActiveSelEnd.TS_AE_END,\r
- interimChar = false\r
- }\r
- }\r
- };\r
-\r
- int startIndex = 0, endIndex = 0;\r
- SetSelection(1, selections);\r
- InsertTextAtSelection(\r
- InsertAtSelectionFlags.TF_IAS_NOQUERY,\r
- i_text,\r
- i_length,\r
- out startIndex,\r
- out endIndex,\r
- out o_textChange\r
- );\r
- }\r
- }\r
-\r
- public void GetFormattedText(int i_start, int i_end, out object o_obj)\r
- {\r
-#if TSF_DEBUG_OUTPUT\r
- using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )\r
-#endif\r
- {\r
- throw new NotImplementedException();\r
- }\r
- }\r
-\r
- public void GetEmbedded(\r
- int i_position,\r
- ref Guid i_guidService,\r
- ref Guid i_riid,\r
- out object o_obj\r
- )\r
- {\r
-#if TSF_DEBUG_OUTPUT\r
- using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )\r
-#endif\r
- {\r
- throw new NotImplementedException();\r
- }\r
- }\r
-\r
- public void QueryInsertEmbedded(\r
- ref Guid i_guidService,\r
- int i_formatEtc,\r
- out bool o_insertable\r
- )\r
- {\r
-#if TSF_DEBUG_OUTPUT\r
- using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )\r
-#endif\r
- {\r
- throw new NotImplementedException();\r
- }\r
- }\r
-\r
- public void InsertEmbedded(\r
- InsertEmbeddedFlags i_flags,\r
- int i_start,\r
- int i_end,\r
- object i_obj,\r
- out TS_TEXTCHANGE o_textChange\r
- )\r
- {\r
-#if TSF_DEBUG_OUTPUT\r
- using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )\r
-#endif\r
- {\r
- throw new NotImplementedException();\r
- }\r
- }\r
-\r
- public void InsertTextAtSelection(\r
- InsertAtSelectionFlags i_flags,\r
- char[] i_text,\r
- int i_length,\r
- out int o_startIndex,\r
- out int o_endIndex,\r
- out TS_TEXTCHANGE o_textChange\r
- )\r
- {\r
-#if TSF_DEBUG_OUTPUT\r
- using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )\r
-#endif\r
- {\r
- if (GetSelectionIndex == null || InsertAtSelection == null)\r
- throw new NotImplementedException();\r
-\r
- int selectionStart = 0, selectionEnd = 0;\r
- GetSelectionIndex(out selectionStart, out selectionEnd);\r
-\r
- // 問い合わせのみで実際には操作を行わない\r
- if ((i_flags & InsertAtSelectionFlags.TF_IAS_QUERYONLY) != 0)\r
- {\r
- o_startIndex = Math.Min(selectionStart, selectionEnd);\r
- o_endIndex = Math.Max(selectionStart, selectionEnd);//o_startIndex + i_length;\r
-\r
- o_textChange.start = o_startIndex;\r
- o_textChange.oldEnd = o_endIndex;\r
- o_textChange.newEnd = o_startIndex + i_length;\r
- }\r
- else\r
- {\r
- var start = Math.Min(selectionStart, selectionEnd);\r
- var end = Math.Max(selectionStart, selectionEnd);\r
-\r
-#if TSF_DEBUG_OUTPUT\r
- DebugOut.Print("start: {0}, end: {1}, text: {2}", start, end, new string(i_text));\r
-#endif\r
-\r
- o_startIndex = start;\r
- o_endIndex = start + i_length;\r
-\r
- InsertAtSelection(new string(i_text), ref o_startIndex, ref o_endIndex);\r
-\r
- o_textChange.start = start;\r
- o_textChange.oldEnd = end;\r
- o_textChange.newEnd = o_endIndex;\r
- // InsertAtSelection() 内でカーソル位置を更新しているため、ここでは不要。\r
- // 改行した時に位置が狂う。\r
- // SetSelectionIndex(start, start + i_length);\r
- }\r
- }\r
- }\r
-\r
- public void GetEndACP(out int o_length)\r
- {\r
-#if TSF_DEBUG_OUTPUT\r
- using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )\r
-#endif\r
- {\r
- if (GetStringLength == null)\r
- throw new NotImplementedException();\r
-\r
- if (IsLocked(LockFlags.TS_LF_READ) == false)\r
- {\r
- throw new COMException(\r
- "読取用ロックがされていません。",\r
- TsResult.TS_E_NOLOCK\r
- );\r
- }\r
-\r
- o_length = GetStringLength();\r
- }\r
- }\r
-\r
- public void GetActiveView(out int o_viewCookie)\r
- {\r
-#if TSF_DEBUG_OUTPUT\r
- using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )\r
-#endif\r
- {\r
- o_viewCookie = 1;\r
- }\r
- }\r
-\r
- public void GetACPFromPoint(\r
- int i_viewCookie,\r
- ref POINT i_point,\r
- GetPositionFromPointFlags i_flags,\r
- out int o_index\r
- )\r
- {\r
-#if TSF_DEBUG_OUTPUT\r
- using (var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()))\r
-#endif\r
- {\r
- throw new NotImplementedException();\r
- }\r
- }\r
-\r
- public void GetTextExt(\r
- int i_viewCookie,\r
- int i_startIndex,\r
- int i_endIndex,\r
- out RECT o_rect,\r
- out bool o_isClipped\r
- )\r
- {\r
-#if TSF_DEBUG_OUTPUT\r
- using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )\r
-#endif\r
- {\r
- if (GetStringLength == null)\r
- throw new NotImplementedException();\r
-\r
- // 読取用ロックの確認。\r
- if (IsLocked(LockFlags.TS_LF_READ) == false)\r
- {\r
- throw new COMException(\r
- "読取用ロックがされていません。",\r
- TsResult.TS_E_NOLOCK\r
- );\r
- }\r
-\r
- if ((i_endIndex != -1 && i_startIndex > i_endIndex)\r
- || i_startIndex < 0 || i_startIndex > GetStringLength()\r
- || i_endIndex > GetStringLength())\r
- {\r
- throw new COMException(\r
- "インデックスが無効です。",\r
- UnmanagedAPI.WinError.HRESULT.E_INVALIDARG\r
- );\r
- }\r
-\r
- if (i_endIndex == -1)\r
- i_endIndex = GetStringLength();\r
-\r
- var pointTopLeft = new POINT();\r
- var pointBotttomRight = new POINT();\r
- GetStringExtent(i_startIndex, i_endIndex, out pointTopLeft, out pointBotttomRight);\r
-\r
- o_rect.left = (int)(pointTopLeft.x);\r
- o_rect.top = (int)(pointTopLeft.y);\r
- o_rect.bottom = (int)(pointBotttomRight.y);\r
- o_rect.right = (int)(pointBotttomRight.x);\r
- o_isClipped = false;\r
-#if TSF_DEBUG_OUTPUT\r
- DebugOut.Print("rect left:{0} top:{1} bottom:{2} right:{3}", o_rect.left, o_rect.top, o_rect.bottom, o_rect.right);\r
-#endif\r
- }\r
- }\r
-\r
- public void GetScreenExt(int i_viewCookie, out RECT o_rect)\r
- {\r
-#if TSF_DEBUG_OUTPUT\r
- using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )\r
-#endif\r
- {\r
- if (GetScreenExtent == null)\r
- throw new NotImplementedException();\r
-\r
- POINT pointTopLeft, pointBottomRight;\r
-\r
- GetScreenExtent(out pointTopLeft, out pointBottomRight);\r
-\r
- o_rect.left = (int)(pointTopLeft.x);\r
- o_rect.top = (int)(pointTopLeft.y);\r
- o_rect.bottom = (int)(pointBottomRight.y);\r
- o_rect.right = (int)(pointBottomRight.x);\r
-#if TSF_DEBUG_OUTPUT\r
- DebugOut.Print("rect left:{0} top:{1} bottom:{2} right:{3}", o_rect.left, o_rect.top, o_rect.bottom, o_rect.right);\r
-#endif\r
- }\r
- }\r
-\r
- public void RequestSupportedAttrs(\r
- AttributeFlags i_flags,\r
- int i_length,\r
- Guid[] i_filterAttributes\r
- )\r
- {\r
-#if TSF_DEBUG_OUTPUT\r
- using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )\r
-#endif\r
- {\r
- for (int i = 0; i < i_length; i++)\r
- {\r
- if (i_filterAttributes[i].Equals(_attributeInfo[0].attrID))\r
- {\r
- _attributeInfo[0].flags = AttributeInfoFlags.Requested;\r
- if ((i_flags & AttributeFlags.TS_ATTR_FIND_WANT_VALUE) != 0)\r
- {\r
- _attributeInfo[0].flags |= AttributeInfoFlags.Default;\r
- }\r
- else\r
- {\r
- _attributeInfo[0].currentValue = _attributeInfo[0].defaultValue;\r
- }\r
- }\r
- }\r
- }\r
- }\r
-\r
- public void RequestAttrsAtPosition(\r
- int i_position,\r
- int i_length,\r
- Guid[] i_filterAttributes,\r
- AttributeFlags i_flags\r
- )\r
- {\r
-#if TSF_DEBUG_OUTPUT\r
- using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )\r
-#endif\r
- {\r
- for (int i = 0; i < i_length; i++)\r
- {\r
- if (i_filterAttributes[i].Equals(_attributeInfo[0].attrID))\r
- {\r
- _attributeInfo[0].flags = AttributeInfoFlags.Requested;\r
- if ((i_flags & AttributeFlags.TS_ATTR_FIND_WANT_VALUE) != 0)\r
- {\r
- _attributeInfo[0].flags |= AttributeInfoFlags.Default;\r
- }\r
- else\r
- {\r
- _attributeInfo[0].currentValue = _attributeInfo[0].defaultValue;\r
- }\r
- }\r
- }\r
- }\r
- }\r
-\r
- public void RequestAttrsTransitioningAtPosition(\r
- int i_position,\r
- int i_length,\r
- Guid[] i_filterAttributes,\r
- AttributeFlags i_flags\r
- )\r
- {\r
-#if TSF_DEBUG_OUTPUT\r
- using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()))\r
-#endif\r
- {\r
- // 何もしない。\r
- }\r
- }\r
-\r
- public void FindNextAttrTransition(\r
- int i_start,\r
- int i_halt,\r
- int i_length,\r
- Guid[] i_filterAttributes,\r
- AttributeFlags i_flags,\r
- out int o_nextIndex,\r
- out bool o_found,\r
- out int o_foundOffset\r
- )\r
- {\r
-#if TSF_DEBUG_OUTPUT\r
- using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )\r
-#endif\r
- {\r
- throw new NotImplementedException();\r
- }\r
- }\r
-\r
- public void RetrieveRequestedAttrs(\r
- int i_length,\r
- TS_ATTRVAL[] o_attributeVals,\r
- out int o_fetchedLength\r
- )\r
- {\r
-#if TSF_DEBUG_OUTPUT\r
- using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )\r
-#endif\r
- {\r
- o_fetchedLength = 0;\r
- for (int i = 0; i < _attributeInfo.Length && o_fetchedLength < i_length; i++)\r
- {\r
- if ((_attributeInfo[i].flags & AttributeInfoFlags.Requested) != 0)\r
- {\r
- o_attributeVals[o_fetchedLength].overlappedId = 0;\r
- o_attributeVals[o_fetchedLength].attributeId = _attributeInfo[i].attrID;\r
- o_attributeVals[o_fetchedLength].val = _attributeInfo[i].currentValue;\r
-\r
- if ((_attributeInfo[i].flags & AttributeInfoFlags.Default) != 0)\r
- _attributeInfo[i].currentValue = _attributeInfo[i].defaultValue;\r
-\r
- o_fetchedLength++;\r
- _attributeInfo[i].flags = AttributeInfoFlags.None;\r
- }\r
- }\r
- }\r
- }\r
- #endregion\r
-\r
- #region "ITfContextOwnerCompositionSink インターフェイスの実装"\r
- /// <summary>コンポジション入力が開始された時の処理。</summary>\r
- public void OnStartComposition(ITfCompositionView view, out bool ok)\r
- {\r
- #if TSF_DEBUG_OUTPUT\r
- using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )\r
- #endif\r
- {\r
- if( CompositionStarted != null )\r
- ok = CompositionStarted();\r
- else\r
- ok = true;\r
- }\r
- }\r
-\r
-\r
- //========================================================================================\r
-\r
-\r
- /// <summary>コンポジションが変更された時の処理。</summary>\r
- public void OnUpdateComposition(ITfCompositionView view, ITfRange rangeNew)\r
- {\r
- #if TSF_DEBUG_OUTPUT\r
- using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )\r
- #endif\r
- {\r
- if (rangeNew == null)\r
- return;\r
-\r
- int start, count;\r
- \r
- ITfRangeACP rangeAcp = (ITfRangeACP)rangeNew;\r
- \r
- rangeAcp.GetExtent(out start, out count);\r
- \r
- if (this.CompositionUpdated != null)\r
- this.CompositionUpdated(start, start + count);\r
- }\r
- }\r
-\r
- \r
- //========================================================================================\r
-\r
-\r
- /// <summary>コンポジション入力が終了した時の処理。</summary>\r
- public void OnEndComposition(ITfCompositionView view)\r
- {\r
- #if TSF_DEBUG_OUTPUT\r
- using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )\r
- #endif\r
- {\r
- if( CompositionEnded != null )\r
- CompositionEnded();\r
- }\r
- }\r
- #endregion "ITfContextOwnerCompositionSink インターフェイスの実装"\r
-\r
- #region 表示属性\r
- /// <summary>表示属性の取得</summary>\r
- public IEnumerable<TextDisplayAttribute> EnumAttributes(int start, int end)\r
- {\r
- ITfRangeACP allRange;\r
- _services.CreateRange(start, end, out allRange);\r
-\r
- foreach (TextDisplayAttribute attr in this.EnumAttributes((ITfRange)allRange))\r
- yield return attr;\r
-\r
- ReleaseComObject("allRange", ref allRange);\r
- }\r
-\r
- IEnumerable<TextDisplayAttribute> EnumAttributes(ITfRange range)\r
- {\r
-#if TSF_DEBUG_OUTPUT\r
- using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()))\r
-#endif\r
- {\r
- ITfProperty property = null; // プロパティインターフェイス\r
- IEnumTfRanges enumRanges; // 範囲の列挙子\r
- Guid guidPropAttribute = TfDeclarations.GUID_PROP_ATTRIBUTE;\r
-\r
- if (_context == null || _services == null)\r
- yield break;\r
-\r
- // GUID_PROP_ATTRIBUTE プロパティを取得。\r
- _context.GetProperty(ref guidPropAttribute, out property);\r
- if (property == null)\r
- yield break;\r
-\r
- // 全範囲の中で表示属性プロパティをもつ範囲を列挙する。\r
- property.EnumRanges((int)_editCookie, out enumRanges, range);\r
-\r
- ITfRange[] ranges = new ITfRange[1];\r
- int fetchedLength = 0;\r
- while (HRESULT.Succeeded(enumRanges.Next(1, ranges, out fetchedLength))\r
- && fetchedLength > 0)\r
- {\r
- // ItfRange から ItfRangeACP を取得。\r
- ITfRangeACP rangeACP = ranges[0] as ITfRangeACP;\r
- if (rangeACP == null)\r
- continue; // 普通はあり得ない\r
-\r
- // 範囲の開始位置と文字数を取得。\r
- int start, count;\r
- rangeACP.GetExtent(out start, out count);\r
-\r
- // VARIANT 値としてプロパティ値を取得。VT_I4 の GUID ATOM がとれる。\r
- VARIANT value = new VARIANT();\r
- property.GetValue((int)_editCookie, ranges[0], ref value);\r
- if (value.vt == (short)VarEnum.VT_I4)\r
- {\r
- Guid guid, clsid;\r
- ITfDisplayAttributeInfo info;\r
- TF_DISPLAYATTRIBUTE attribute;\r
-\r
- // GUID ATOM から GUID を取得する。\r
- _categoryMgr.GetGUID((int)value.data1, out guid);\r
- // その GUID から IDisplayAttributeInfo インターフェイスを取得。\r
- _displayAttributeMgr.GetDisplayAttributeInfo(\r
- ref guid,\r
- out info,\r
- out clsid\r
- );\r
- // さらに IDisplayAttributeInfo インターフェイスから表示属性を取得する。\r
- info.GetAttributeInfo(out attribute);\r
- ReleaseComObject("info", ref info);\r
-\r
- yield return new TextDisplayAttribute\r
- {\r
- startIndex = start,\r
- endIndex = start + count,\r
- attribute = attribute\r
- };\r
-\r
-#if TSF_DEBUG_OUTPUT_DISPLAY_ATTR\r
- Debug.WriteLine(\r
- "*******:::: DisplayAttribute: {0} ~ {1} :::::: *********",\r
- start, start + count\r
- );\r
- Debug.WriteLine(attribute.bAttr);\r
- Debug.WriteLine(\r
- "LineColorType: {0}, {1}",\r
- attribute.crLine.type, attribute.crLine.indexOrColorRef\r
- );\r
- Debug.WriteLine(\r
- "TextColorType: {0}, {1}",\r
- attribute.crText.type, attribute.crText.indexOrColorRef\r
- );\r
- Debug.WriteLine(\r
- "BackColorType: {0}, {1}",\r
- attribute.crBk.type, attribute.crBk.indexOrColorRef\r
- );\r
- Debug.WriteLine(\r
- "Bold, Style : {0}, {1}",\r
- attribute.fBoldLine, attribute.lsStyle\r
- );\r
-#endif\r
- }\r
-\r
- ReleaseComObject("rangeACP", ref rangeACP);\r
- }\r
-\r
- ReleaseComObject("ranges[0]", ref ranges[0]);\r
- ReleaseComObject("enumRanges", ref enumRanges);\r
- ReleaseComObject("property", ref property);\r
- }\r
- }\r
- #endregion\r
-\r
-#if METRO\r
- protected ITfThreadMgr2 _threadMgr;\r
-#else\r
- protected ITfThreadMgr _threadMgr;\r
-#endif\r
- protected ITfDocumentMgr _documentMgr;\r
- protected ITfFunctionProvider _functionProvider;\r
- protected ITfFnReconversion _reconversion;\r
- protected ITfContext _context;\r
- protected ITfCategoryMgr _categoryMgr;\r
- protected ITfDisplayAttributeMgr _displayAttributeMgr;\r
- protected ITextStoreACPSink _sink;\r
- protected uint _editCookie = 0;\r
- protected ITextStoreACPServices _services;\r
- protected AdviseFlags _adviseFlags = 0;\r
- protected LockFlags _lockFlags = 0;\r
- protected bool _pendingLockUpgrade = false;\r
-\r
- /// <summary>\r
- /// AttributeInfo で使用されるフラグ。各属性の状態を示す。\r
- /// </summary>\r
- protected enum AttributeInfoFlags\r
- {\r
- /// <summary>何もない。</summary>\r
- None = 0,\r
- /// <summary>デフォルト値の要求。</summary>\r
- Default = 1 << 0,\r
- /// <summary>要求された。</summary>\r
- Requested = 1 << 1\r
- }\r
-\r
- protected struct AttributeInfo\r
- {\r
- public Guid attrID;\r
- public AttributeInfoFlags flags;\r
- public VARIANT currentValue;\r
- public VARIANT defaultValue;\r
- }\r
-\r
- protected AttributeInfo[] _attributeInfo = new AttributeInfo[1];\r
-\r
- }\r
-}\r
+// TSF のデバッグ表示を行うかどうか?
+//#define TSF_DEBUG_OUTPUT
+//#define TSF_DEBUG_OUTPUT_DISPLAY_ATTR
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Diagnostics;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Globalization;
+
+using DotNetTextStore.UnmanagedAPI.TSF;
+using DotNetTextStore.UnmanagedAPI.TSF.TextStore;
+using DotNetTextStore.UnmanagedAPI.WinDef;
+using DotNetTextStore.UnmanagedAPI.WinError;
+
+namespace DotNetTextStore
+{
+#if TSF_DEBUG_OUTPUT
+ /// <summary>コールスタックの階層にあわせてインデントしてデバッグ表示するクラス。</summary>
+ public class DebugOut : IDisposable
+ {
+ public DebugOut(string i_string, params object[] i_params)
+ {
+ _text = string.Format(i_string, i_params);
+
+ s_callCount++;
+ Debug.WriteLine("");
+ Debug.WriteLine(string.Format("{0, 4} : ↓↓↓ ", s_callCount) + _text);
+ }
+
+ public static void Print(string i_string, params object[] i_params)
+ {
+ Debug.WriteLine(i_string, i_params);
+ }
+
+ public void Dispose()
+ {
+ s_callCount++;
+ Debug.WriteLine(string.Format("{0, 4} : ↑↑↑ ", s_callCount) + _text);
+ }
+
+ public static string GetCaller([CallerMemberName] string caller="")
+ {
+ return caller;
+ }
+
+ string _text;
+ static int s_callCount = 0;
+ }
+#endif
+
+ //=============================================================================================
+
+
+ public struct TextDisplayAttribute
+ {
+ public int startIndex;
+ public int endIndex;
+ public TF_DISPLAYATTRIBUTE attribute;
+ }
+
+ //========================================================================================
+
+
+ /// <summary>Dispose() で TextStore のロック解除を行うクラス。</summary>
+ public class Unlocker : IDisposable
+ {
+ /// <summary>コンストラクタ</summary>
+ public Unlocker(TextStoreBase io_textStore)
+ {
+ _textStore = io_textStore;
+ }
+ /// <summary>ロックが成功したかどうか調べる。</summary>
+ public bool IsLocked
+ {
+ get { return _textStore != null; }
+ }
+ /// <summary>アンロックを行う。</summary>
+ void IDisposable.Dispose()
+ {
+ if (_textStore != null)
+ {
+ _textStore.UnlockDocument();
+ _textStore = null;
+ }
+ }
+
+ /// <summary>アンロックを行うテキストストア</summary>
+ TextStoreBase _textStore;
+ }
+
+ public abstract class TextStoreBase
+ {
+ public delegate bool IsReadOnlyHandler();
+ public event IsReadOnlyHandler IsReadOnly;
+
+ public delegate bool IsLoadingHandler();
+ public event IsLoadingHandler IsLoading;
+
+ public delegate int GetStringLengthHandler();
+ public event GetStringLengthHandler GetStringLength;
+
+ public delegate void GetSelectionIndexHandler(out int o_start, out int o_end);
+ public event GetSelectionIndexHandler GetSelectionIndex;
+
+ public delegate void SetSelectionIndexHandler(int i_start, int i_end);
+ public event SetSelectionIndexHandler SetSelectionIndex;
+
+ public delegate string GetStringHandler(int start, int length);
+ public event GetStringHandler GetString;
+
+ public delegate void InsertAtSelectionHandler(string i_value,ref int o_startIndex,ref int o_endIndex);
+ public event InsertAtSelectionHandler InsertAtSelection;
+
+ public delegate void GetScreenExtentHandler(
+ out POINT o_pointTopLeft,
+ out POINT o_pointBottomRight
+ );
+ public event GetScreenExtentHandler GetScreenExtent;
+
+ public delegate void GetStringExtentHandler(
+ int i_startIndex,
+ int i_endIndex,
+ out POINT o_pointTopLeft,
+ out POINT o_pointBottomRight
+ );
+ public event GetStringExtentHandler GetStringExtent;
+
+ public delegate bool CompositionStartedHandler();
+ public event CompositionStartedHandler CompositionStarted;
+
+ public delegate void CompostionUpdateHandler(int start, int end);
+ public event CompostionUpdateHandler CompositionUpdated;
+
+ public delegate void CompositionEndedHandler();
+ public event CompositionEndedHandler CompositionEnded;
+
+ #region "生成と破棄"
+ public TextStoreBase()
+ {
+#if TSF_DEBUG_OUTPUT
+ using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
+#endif
+ {
+ try
+ {
+ // スレッドマネージャ-の生成
+ CreateThreadMgr();
+ // カテゴリマネージャーの生成
+ CreateCategoryMgr();
+ // 表示属性マネージャーの生成
+ CreateDisplayAttributeMgr();
+
+ // ドキュメントマネージャーの生成
+ _threadMgr.CreateDocumentMgr(out _documentMgr);
+
+ // スレッドマネージャのアクティブ化
+ int clientId = 0;
+ _threadMgr.Activate(out clientId);
+
+ // コンテキストの生成
+ _documentMgr.CreateContext(clientId, 0, this, out _context, out _editCookie);
+
+ // コンテキストの push
+ _documentMgr.Push(_context);
+
+ // ファンクションプロバイダーを取得する。
+ Guid guid = TfDeclarations.GUID_SYSTEM_FUNCTIONPROVIDER;
+ _threadMgr.GetFunctionProvider(ref guid, out _functionProvider);
+
+ // ITfReconversion オブジェクトを取得する。
+ var guidNull = new Guid();
+ var guidReconversion = new Guid("4cea93c0-0a58-11d3-8df0-00105a2799b5"); //ITfFnReconversionの定義から
+ object reconversion = null;
+ _functionProvider.GetFunction(
+ ref guidNull,
+ ref guidReconversion,
+ out reconversion
+ );
+ _reconversion = reconversion as ITfFnReconversion;
+
+ // MODEBIAS の初期化
+ uint guidAtom = 0;
+ Guid guidModebiasNone = TfDeclarations.GUID_MODEBIAS_NONE;
+ _categoryMgr.RegisterGUID(ref guidModebiasNone, out guidAtom);
+ _attributeInfo[0].attrID = TfDeclarations.GUID_PROP_MODEBIAS;
+ _attributeInfo[0].flags = AttributeInfoFlags.None;
+ _attributeInfo[0].currentValue.vt = (short)VarEnum.VT_EMPTY;
+ _attributeInfo[0].defaultValue.vt = (short)VarEnum.VT_I4;
+ _attributeInfo[0].defaultValue.data1 = (IntPtr)guidAtom;
+ }
+ catch (Exception exception)
+ {
+ Debug.WriteLine(exception.Message);
+ Dispose(false);
+ }
+ }
+ }
+
+ /// <summary>
+ /// オブジェクトの破棄を行う。このメソッドは必ず呼び出す必要があります
+ /// </summary>
+ /// <param name="flag"></param>
+ protected void Dispose(bool flag)
+ {
+ if (flag)
+ return;
+#if TSF_DEBUG_OUTPUT
+ using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
+#endif
+ {
+ ReleaseComObject("_reconversion", ref _reconversion);
+ ReleaseComObject("_functionProvider", ref _functionProvider);
+ ReleaseComObject("_context", ref _context);
+ DestroyDocumentMgr();
+ DestroyDisplayAttributeMgr();
+ DestroyCategoryMgr();
+ DestroyThreadMgr();
+
+ GC.SuppressFinalize(this);
+ }
+ }
+
+ /// <summary>
+ /// スレッドマネージャの生成。このメソッドの実装は必須です
+ /// </summary>
+ ///
+ /// <exception cref="COMException">
+ /// スレッドマネージャーの生成に失敗した場合。
+ /// </exception>
+ protected virtual void CreateThreadMgr()
+ {
+ throw new NotImplementedException();
+ }
+
+ /// <summary>
+ /// スレッドマネージャーの解放。
+ /// </summary>
+ void DestroyThreadMgr()
+ {
+ if (_threadMgr != null)
+ {
+ try { _threadMgr.Deactivate(); }
+ catch (Exception) { }
+
+ ReleaseComObject("_threadMgr", ref _threadMgr);
+ }
+ }
+
+ /// <summary>
+ /// カテゴリマネージャーの生成。
+ /// </summary>
+ ///
+ /// <exception cref="COMException">
+ /// カテゴリマネージャーの生成に失敗した場合。
+ /// </exception>
+ void CreateCategoryMgr()
+ {
+ if (_categoryMgr == null)
+ {
+ var clsid = Marshal.GetTypeFromCLSID(TfDeclarations.CLSID_TF_CategoryMgr);
+ _categoryMgr = Activator.CreateInstance(clsid) as ITfCategoryMgr;
+
+ if (_categoryMgr == null)
+ {
+ const string message = "カテゴリマネージャーの生成に失敗しました。";
+ Debug.WriteLine(message);
+ throw new COMException(message, HRESULT.E_NOTIMPL);
+ }
+ }
+ }
+
+ /// <summary>
+ /// カテゴリマネージャーの解放。
+ /// </summary>
+ void DestroyCategoryMgr()
+ {
+ ReleaseComObject("_categoryMgr", ref _categoryMgr);
+ }
+
+ /// <summary>
+ /// 表示属性マネージャーの生成。
+ /// </summary>
+ ///
+ /// <exception cref="COMException">
+ /// 表示属性マネージャーの生成に失敗した場合。
+ /// </exception>
+ void CreateDisplayAttributeMgr()
+ {
+ if (_displayAttributeMgr == null)
+ {
+ var clsid = Marshal.GetTypeFromCLSID(TfDeclarations.CLSID_TF_DisplayAttributeMgr);
+ _displayAttributeMgr = Activator.CreateInstance(clsid) as ITfDisplayAttributeMgr;
+
+ if (_displayAttributeMgr == null)
+ {
+ const string message = "表示属性マネージャーの生成に失敗しました。";
+ Debug.WriteLine(message);
+ throw new COMException(message, HRESULT.E_NOTIMPL);
+ }
+ }
+ }
+
+ /// <summary>
+ /// 表示属性マネージャーの解放。
+ /// </summary>
+ void DestroyDisplayAttributeMgr()
+ {
+ ReleaseComObject("_displayAttributeMgr", ref _displayAttributeMgr);
+ }
+
+ /// <summary>
+ /// ドキュメントマネージャーの解放
+ /// </summary>
+ void DestroyDocumentMgr()
+ {
+ if (_documentMgr != null)
+ {
+ try { _documentMgr.Pop(PopFlags.TF_POPF_ALL); }
+ catch (Exception) { }
+
+ ReleaseComObject("_documentMgr", ref _documentMgr);
+ }
+ }
+
+ /// <summary>
+ /// COM オブジェクトのリリースとデバッグメッセージ出力。
+ /// </summary>
+ protected static void ReleaseComObject<ComObject>(
+ string i_objectName,
+ ref ComObject io_comObject
+ )
+ {
+ if (io_comObject != null)
+ {
+ var refCount = Marshal.ReleaseComObject(io_comObject);
+#if TSF_DEBUG_OUTPUT
+ Debug.WriteLine(
+ "Marshal.ReleaseComObject({0}) returns {1}.",
+ i_objectName,
+ refCount
+ );
+#endif
+
+ io_comObject = default(ComObject);
+ }
+ }
+ #endregion
+
+ #region "コントロール側が状況に応じて呼び出さなければいけない TSF に通知を送るメソッド"
+ /// <summary>
+ /// 選択領域が変更されたことをTSFに伝える。各種ハンドラ内からコールしてはいけない。
+ /// </summary>
+ public void NotifySelectionChanged()
+ {
+ if( _sink != null )
+ {
+#if TSF_DEBUG_OUTPUT
+ DebugOut.Print(DebugOut.GetCaller());
+#endif
+ if ((_adviseFlags & AdviseFlags.TS_AS_SEL_CHANGE) != 0)
+ _sink.OnSelectionChange();
+ }
+ }
+
+
+ //=========================================================================================
+
+
+ /// <summary>
+ /// テキストが変更されたことをTSFに伝える。各種ハンドラ内からコールしてはいけない。
+ /// </summary>
+ void NotifyTextChanged(TS_TEXTCHANGE textChange)
+ {
+ if( _sink != null )
+ {
+#if TSF_DEBUG_OUTPUT
+ DebugOut.Print(DebugOut.GetCaller());
+#endif
+ if ((_adviseFlags & AdviseFlags.TS_AS_TEXT_CHANGE) != 0)
+ _sink.OnTextChange(0, ref textChange);
+ _sink.OnLayoutChange(TsLayoutCode.TS_LC_CHANGE, 1);
+ }
+ }
+
+
+ //=========================================================================================
+
+ /// <summary>
+ /// テキストが変更されたことをTSFに伝える。各種ハンドラ内からコールしてはいけない。
+ /// </summary>
+ /// <param name="start">開始位置</param>
+ /// <param name="oldend">更新前の終了位置</param>
+ /// <param name="newend">更新後の終了位置</param>
+ /// <remarks>
+ /// 詳しいことはITextStoreACPSink::OnTextChangeを参照してください
+ /// </remarks>
+ public void NotifyTextChanged(int start,int oldend,int newend)
+ {
+ if (_sink != null)
+ {
+#if TSF_DEBUG_OUTPUT
+ DebugOut.Print(DebugOut.GetCaller());
+#endif
+ if ((_adviseFlags & AdviseFlags.TS_AS_TEXT_CHANGE) != 0)
+ {
+ var textChange = new TS_TEXTCHANGE();
+ textChange.start = start;
+ textChange.oldEnd = oldend;
+ textChange.newEnd = newend;
+
+ _sink.OnTextChange(0, ref textChange);
+ }
+ _sink.OnLayoutChange(TsLayoutCode.TS_LC_CHANGE, 1);
+ }
+ }
+
+ /// <summary>
+ /// テキストが変更されたことをTSFに伝える。各種ハンドラ内からコールしてはいけない。
+ /// </summary>
+ /// <param name="i_oldLength"></param>
+ /// <param name="i_newLength"></param>
+ public void NotifyTextChanged(int i_oldLength, int i_newLength)
+ {
+ if( _sink != null )
+ {
+#if TSF_DEBUG_OUTPUT
+ DebugOut.Print(DebugOut.GetCaller());
+#endif
+ if ((_adviseFlags & AdviseFlags.TS_AS_TEXT_CHANGE) != 0)
+ {
+ var textChange = new TS_TEXTCHANGE();
+ textChange.start = 0;
+ textChange.oldEnd = i_oldLength;
+ textChange.newEnd = i_newLength;
+
+ _sink.OnTextChange(0, ref textChange);
+ }
+ _sink.OnLayoutChange(TsLayoutCode.TS_LC_CHANGE, 1);
+ }
+ }
+
+
+
+ //=========================================================================================
+
+
+ /// <summary>コントロールがフォーカスを取得した時に呼び出さなければいけない。</summary>
+ public void SetFocus()
+ {
+#if TSF_DEBUG_OUTPUT
+ DebugOut.Print(DebugOut.GetCaller());
+#endif
+ if (_threadMgr != null)
+ _threadMgr.SetFocus(_documentMgr);
+ }
+ #endregion "コントロール側が状況に応じて呼び出さなければいけない TSF に通知を送るメソッド"
+
+ #region ロック関連
+ /// <summary>
+ /// ドキュメントのロックを行う。
+ /// </summary>
+ /// <param name="i_writable">読み書き両用ロックか?false の場合、読み取り専用。</param>
+ /// <returns>Unlocker のインスタンスを返す。失敗した場合 null を返す。</returns>
+ public Unlocker LockDocument(bool i_writable)
+ {
+ #if TSF_DEBUG_OUTPUT
+ using(var dbgout = new DebugOut("{0}({1})", DebugOut.GetCaller(),
+ i_writable) )
+ #endif
+ {
+ lock(this)
+ {
+ if( this._lockFlags == 0 )
+ {
+ if( i_writable )
+ this._lockFlags = LockFlags.TS_LF_READWRITE;
+ else
+ this._lockFlags = LockFlags.TS_LF_READ;
+
+ #if TSF_DEBUG_OUTPUT
+ Debug.WriteLine("LockDocument is succeeded.");
+ #endif
+
+ return new Unlocker(this);
+ }
+ else
+ {
+ #if TSF_DEBUG_OUTPUT
+ Debug.WriteLine("LockDocument is failed. {0}", _lockFlags);
+ #endif
+
+ return null;
+ }
+ }
+ }
+ }
+
+
+ //========================================================================================
+
+
+ /// <summary>
+ /// ドキュメントのロックを行う。
+ /// </summary>
+ /// <param name="i_writable">読み書き両用ロックか?false の場合、読み取り専用。</param>
+ /// <returns>Unlocker のインスタンスを返す。失敗した場合 null を返す。</returns>
+ public Unlocker LockDocument(LockFlags i_flags)
+ {
+ #if TSF_DEBUG_OUTPUT
+ using(var dbgout = new DebugOut("{0}({1})", DebugOut.GetCaller(),
+ i_flags) )
+ #endif
+ {
+ lock(this)
+ {
+ if( this._lockFlags == 0 )
+ {
+ this._lockFlags = i_flags;
+
+ #if TSF_DEBUG_OUTPUT
+ Debug.WriteLine("LockDocument is succeeded.");
+ #endif
+
+ return new Unlocker(this);
+ }
+ else
+ {
+ #if TSF_DEBUG_OUTPUT
+ Debug.WriteLine("LockDocument is failed. {0}", _lockFlags);
+ #endif
+
+ return null;
+ }
+ }
+ }
+ }
+
+
+ //========================================================================================
+
+
+ /// <summary>
+ /// ドキュメントのアンロックを行う。
+ /// </summary>
+ public void UnlockDocument()
+ {
+ #if TSF_DEBUG_OUTPUT
+ using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
+ #endif
+ {
+ lock(this)
+ {
+ _lockFlags = 0;
+ }
+
+ if( _pendingLockUpgrade )
+ {
+ _pendingLockUpgrade = false;
+ int sessionResult;
+ RequestLock(LockFlags.TS_LF_READWRITE, out sessionResult);
+ }
+ }
+ }
+
+
+ //========================================================================================
+
+
+ /// <summary>
+ /// 指定されたフラグでロックしている状態かどうか調べる。
+ /// </summary>
+ /// <param name="i_lockFlags"></param>
+ /// <returns>ロックされている場合は true, されていない場合は false を返す。</returns>
+ public bool IsLocked(LockFlags i_lockFlags)
+ {
+ #if TSF_DEBUG_OUTPUT
+ using(var dbgout = new DebugOut("{0}({1})",
+ DebugOut.GetCaller(), i_lockFlags) )
+ #endif
+ {
+ #if TSF_DEBUG_OUTPUT
+ Debug.WriteLine(
+ "IsLocked() returns " + ((this._lockFlags & i_lockFlags) == i_lockFlags)
+ );
+ #endif
+ return (this._lockFlags & i_lockFlags) == i_lockFlags;
+ }
+ }
+
+ /// <summary>
+ /// ロックされているか調べる
+ /// </summary>
+ /// <returns>ロックされているなら真、そうでなければ偽を返す</returns>
+ public bool IsLocked()
+ {
+#if TSF_DEBUG_OUTPUT
+ using(var dbgout = new DebugOut("{0}",
+ DebugOut.GetCaller()) )
+#endif
+ {
+ bool retval = this._lockFlags != 0;
+#if TSF_DEBUG_OUTPUT
+ Debug.WriteLine(
+ "IsLocked() returns " + retval
+ );
+#endif
+ return retval;
+ }
+ }
+ #endregion
+
+ #region ITextStroeACP,ITextStoreACP2の共通部分
+
+ /// <summary>
+ /// 文字列を挿入する。
+ /// </summary>
+ public void InsertTextAtSelection(string s)
+ {
+ TS_TEXTCHANGE textChange = new TS_TEXTCHANGE();
+
+ using (var unlocker = LockDocument(true))
+ {
+ if (unlocker != null)
+ {
+ int startIndex, endIndex;
+
+ InsertTextAtSelection(
+ UnmanagedAPI.TSF.TextStore.InsertAtSelectionFlags.TF_IAS_NOQUERY,
+ s.ToCharArray(),
+ s.Length,
+ out startIndex,
+ out endIndex,
+ out textChange
+ );
+ }
+ }
+
+ // シンクの OnSelectionChange() をコール。
+ NotifySelectionChanged();
+ NotifyTextChanged(textChange);
+ }
+
+ public void InsertEmbeddedAtSelection(
+ InsertAtSelectionFlags flags,
+ object obj,
+ out int start,
+ out int end,
+ out TS_TEXTCHANGE change
+ )
+ {
+#if TSF_DEBUG_OUTPUT
+ using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
+#endif
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ public void AdviseSink(ref Guid i_riid, object i_unknown, AdviseFlags i_mask)
+ {
+#if TSF_DEBUG_OUTPUT
+ using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
+#endif
+ {
+ if (i_riid != new Guid("22d44c94-a419-4542-a272-ae26093ececf")) //ITextStoreACPSinkの定義より
+ {
+ throw new COMException(
+ "ITextStoreACPSink 以外のIIDが渡されました。",
+ UnmanagedAPI.WinError.HRESULT.E_INVALIDARG
+ );
+ }
+
+ // 既存のシンクのマスクのみを更新
+ if (_sink == i_unknown)
+ {
+ _adviseFlags = i_mask;
+ }
+ // シンクを複数登録しようとした
+ else if (_sink != null)
+ {
+ throw new COMException(
+ "既にシンクを登録済みです。",
+ UnmanagedAPI.TSF.TextStore.TsResult.CONNECT_E_ADVISELIMIT
+ );
+ }
+ else
+ {
+ // 各種値を保存
+ _services = (ITextStoreACPServices)i_unknown;
+ _sink = (ITextStoreACPSink)i_unknown;
+ _adviseFlags = i_mask;
+ }
+ }
+ }
+
+ public void UnadviseSink(object i_unknown)
+ {
+#if TSF_DEBUG_OUTPUT
+ using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
+#endif
+ {
+ if (_sink == null || _sink != i_unknown)
+ {
+ throw new COMException(
+ "シンクは登録されていません。",
+ UnmanagedAPI.TSF.TextStore.TsResult.CONNECT_E_NOCONNECTION
+ );
+ }
+
+ _services = null;
+ _sink = null;
+ _adviseFlags = 0;
+ }
+ }
+
+ public void RequestLock(LockFlags i_lockFlags, out int o_sessionResult)
+ {
+#if TSF_DEBUG_OUTPUT
+ using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
+#endif
+ {
+ o_sessionResult = UnmanagedAPI.WinError.HRESULT.E_FAIL;
+
+ if (_sink == null)
+ {
+ throw new COMException(
+ "シンクが登録されていません。",
+ UnmanagedAPI.TSF.TextStore.TsResult.CONNECT_E_NOCONNECTION
+ );
+ }
+
+ if (_lockFlags != 0) // すでにロックされた状態の場合。
+ {
+ if ((i_lockFlags & LockFlags.TS_LF_SYNC) != 0)
+ {
+ o_sessionResult = TsResult.TS_E_SYNCHRONOUS;
+ return;
+ }
+ else
+ if ((_lockFlags & LockFlags.TS_LF_READWRITE) == LockFlags.TS_LF_READ
+ && (i_lockFlags & LockFlags.TS_LF_READWRITE) == LockFlags.TS_LF_READWRITE)
+ {
+ _pendingLockUpgrade = true;
+ o_sessionResult = TsResult.TS_S_ASYNC;
+ return;
+ }
+
+ throw new COMException();
+ }
+
+ using (var unlocker = LockDocument(i_lockFlags))
+ {
+ // ロックに失敗した場合は TS_E_SYNCHRONOUS をセットして S_OK を返す。
+ if (unlocker == null)
+ {
+ o_sessionResult = TsResult.TS_E_SYNCHRONOUS;
+ }
+ // ロックに成功した場合は OnLockGranted() を呼び出す。
+ else
+ {
+ try
+ {
+ o_sessionResult = _sink.OnLockGranted(i_lockFlags);
+ }
+ catch (COMException comException)
+ {
+ Debug.WriteLine("OnLockGranted() 呼び出し中に例外が発生。");
+ Debug.WriteLine(" " + comException.Message);
+ o_sessionResult = comException.HResult;
+ }
+ catch (Exception exception)
+ {
+ Debug.WriteLine("OnLockGranted() 呼び出し中に例外が発生。");
+ Debug.WriteLine(" " + exception.Message);
+ }
+ }
+ }
+ }
+ }
+
+ public void GetStatus(out TS_STATUS o_documentStatus)
+ {
+#if TSF_DEBUG_OUTPUT
+ using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
+#endif
+ {
+ if (IsReadOnly != null && IsReadOnly())
+ o_documentStatus.dynamicFlags = DynamicStatusFlags.TS_SD_READONLY;
+ if (IsLoading != null && IsLoading())
+ o_documentStatus.dynamicFlags = DynamicStatusFlags.TS_SD_LOADING;
+ else
+ o_documentStatus.dynamicFlags = 0;
+ o_documentStatus.staticFlags = StaticStatusFlags.TS_SS_REGIONS;
+ }
+ }
+
+ public void QueryInsert(
+ int i_startIndex,
+ int i_endIndex,
+ int i_length,
+ out int o_startIndex,
+ out int o_endIndex
+ )
+ {
+#if TSF_DEBUG_OUTPUT
+ using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
+#endif
+ {
+ if (GetStringLength == null)
+ throw new NotImplementedException();
+
+ int documentLength = GetStringLength();
+
+ if (i_startIndex < 0
+ || i_startIndex > i_endIndex
+ || i_endIndex > documentLength)
+ {
+ throw new COMException(
+ "インデックスが無効です。",
+ UnmanagedAPI.WinError.HRESULT.E_INVALIDARG
+ );
+ }
+ o_startIndex = i_startIndex;
+ o_endIndex = i_endIndex;
+
+#if TSF_DEBUG_OUTPUT
+ DebugOut.Print("o_startIndex:{0} o_endIndex:{1}", i_startIndex, i_endIndex);
+#endif
+ }
+ }
+
+ public void GetSelection(
+ int i_index,
+ int i_selectionBufferLength,
+ TS_SELECTION_ACP[] o_selections,
+ out int o_fetchedLength
+ )
+ {
+#if TSF_DEBUG_OUTPUT
+ using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
+#endif
+ {
+ if (GetSelectionIndex == null)
+ throw new NotImplementedException();
+
+ o_fetchedLength = 0;
+
+ if (IsLocked(LockFlags.TS_LF_READ) == false)
+ {
+ throw new COMException(
+ "読取用ロックがされていません。",
+ TsResult.TS_E_NOLOCK
+ );
+ }
+
+ // -1 は TF_DEFAULT_SELECTION。選択は1つだけしかサポートしないので、
+ // TF_DEFAULT_SELECTION でもなく、0 を超える数値が指定された場合はエラー。
+ if (i_index != -1 && i_index > 0)
+ {
+ throw new COMException(
+ "選択は1つだけしかサポートしていません。",
+ UnmanagedAPI.WinError.HRESULT.E_INVALIDARG
+ );
+ }
+
+ if (i_selectionBufferLength > 0)
+ {
+ int start = 0, end = 0;
+ GetSelectionIndex(out start, out end);
+ if (start <= end)
+ {
+ o_selections[0].start = start;
+ o_selections[0].end = end;
+ o_selections[0].style.ase = TsActiveSelEnd.TS_AE_END;
+ o_selections[0].style.interimChar = false;
+ }
+ else
+ {
+ o_selections[0].start = end;
+ o_selections[0].end = start;
+ o_selections[0].style.ase = TsActiveSelEnd.TS_AE_START;
+ o_selections[0].style.interimChar = false;
+ }
+
+ o_fetchedLength = 1;
+
+#if TSF_DEBUG_OUTPUT
+ DebugOut.Print("sel start:{0} end:{1}", start, end);
+#endif
+ }
+ }
+ }
+
+ public void SetSelection(int i_count, TS_SELECTION_ACP[] i_selections)
+ {
+#if TSF_DEBUG_OUTPUT
+ using(var dbgout = new DebugOut("{0}({1}, {2})",
+ DebugOut.GetCaller(),
+ i_selections[0].start,
+ i_selections[0].end))
+#endif
+ {
+ if (SetSelectionIndex == null)
+ throw new NotImplementedException();
+
+ if (i_count != 1)
+ {
+ throw new COMException(
+ "選択は1つだけしかサポートしていません。",
+ UnmanagedAPI.WinError.HRESULT.E_INVALIDARG
+ );
+ }
+
+ if (IsLocked(LockFlags.TS_LF_READWRITE) == false)
+ {
+ throw new COMException(
+ "ロックされていません。",
+ TsResult.TS_E_NOLOCK
+ );
+ }
+
+ SetSelectionIndex(i_selections[0].start, i_selections[0].end);
+
+#if TSF_DEBUG_OUTPUT
+ DebugOut.Print("set selection startIndex:{0} endIndex:{1}", i_selections[0].start, i_selections[0].end);
+#endif
+ }
+ }
+
+ public void GetText(
+ int i_startIndex,
+ int i_endIndex,
+ char[] o_plainText,
+ int i_plainTextLength,
+ out int o_plainTextLength,
+ TS_RUNINFO[] o_runInfos,
+ int i_runInfoLength,
+ out int o_runInfoLength,
+ out int o_nextUnreadCharPos
+ )
+ {
+#if TSF_DEBUG_OUTPUT
+ using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
+#endif
+ {
+ if (GetStringLength == null || GetString == null)
+ throw new NotImplementedException();
+
+ if (IsLocked(LockFlags.TS_LF_READ) == false)
+ {
+ throw new COMException(
+ "読取用ロックがされていません。",
+ TsResult.TS_E_NOLOCK
+ );
+ }
+
+ if ((i_endIndex != -1 && i_startIndex > i_endIndex)
+ || i_startIndex < 0 || i_startIndex > GetStringLength()
+ || i_endIndex > GetStringLength())
+ {
+ throw new COMException(
+ "インデックスが無効です。",
+ UnmanagedAPI.WinError.HRESULT.E_INVALIDARG
+ );
+ }
+
+ var textLength = 0;
+ var copyLength = 0;
+
+ if (i_endIndex == -1)
+ textLength = GetStringLength() - i_startIndex;
+ else
+ textLength = i_endIndex - i_startIndex;
+ copyLength = Math.Min(i_plainTextLength, textLength);
+
+ // 文字列を格納。
+ var text = GetString(i_startIndex, copyLength);
+#if TSF_DEBUG_OUTPUT
+ DebugOut.Print("got text:{0} from {1} length {2}", text,i_startIndex,copyLength);
+#endif
+ for (int i = 0; i < copyLength; i++)
+ {
+ o_plainText[i] = text[i];
+ }
+
+ // 文字数を格納。
+ o_plainTextLength = copyLength;
+ // RUNINFO を格納。
+ if (i_runInfoLength > 0)
+ {
+ o_runInfos[0].type = TsRunType.TS_RT_PLAIN;
+ o_runInfos[0].length = copyLength;
+ }
+ o_runInfoLength = 1;
+
+ // 次の文字の位置を格納。
+ o_nextUnreadCharPos = i_startIndex + copyLength;
+ }
+ }
+
+ public void SetText(
+ SetTextFlags i_flags,
+ int i_startIndex,
+ int i_endIndex,
+ char[] i_text,
+ int i_length,
+ out TS_TEXTCHANGE o_textChange
+ )
+ {
+#if TSF_DEBUG_OUTPUT
+ using(var dbgout = new DebugOut("{0}({1}, {2})",
+ DebugOut.GetCaller(),
+ i_startIndex, i_endIndex) )
+#endif
+ {
+ var selections = new TS_SELECTION_ACP[]
+ {
+ new TS_SELECTION_ACP
+ {
+ start = i_startIndex,
+ end = i_endIndex,
+ style = new TS_SELECTIONSTYLE
+ {
+ ase = TsActiveSelEnd.TS_AE_END,
+ interimChar = false
+ }
+ }
+ };
+
+ int startIndex = 0, endIndex = 0;
+ SetSelection(1, selections);
+ InsertTextAtSelection(
+ InsertAtSelectionFlags.TF_IAS_NOQUERY,
+ i_text,
+ i_length,
+ out startIndex,
+ out endIndex,
+ out o_textChange
+ );
+ }
+ }
+
+ public void GetFormattedText(int i_start, int i_end, out object o_obj)
+ {
+#if TSF_DEBUG_OUTPUT
+ using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
+#endif
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ public void GetEmbedded(
+ int i_position,
+ ref Guid i_guidService,
+ ref Guid i_riid,
+ out object o_obj
+ )
+ {
+#if TSF_DEBUG_OUTPUT
+ using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
+#endif
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ public void QueryInsertEmbedded(
+ ref Guid i_guidService,
+ int i_formatEtc,
+ out bool o_insertable
+ )
+ {
+#if TSF_DEBUG_OUTPUT
+ using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
+#endif
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ public void InsertEmbedded(
+ InsertEmbeddedFlags i_flags,
+ int i_start,
+ int i_end,
+ object i_obj,
+ out TS_TEXTCHANGE o_textChange
+ )
+ {
+#if TSF_DEBUG_OUTPUT
+ using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
+#endif
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ public void InsertTextAtSelection(
+ InsertAtSelectionFlags i_flags,
+ char[] i_text,
+ int i_length,
+ out int o_startIndex,
+ out int o_endIndex,
+ out TS_TEXTCHANGE o_textChange
+ )
+ {
+#if TSF_DEBUG_OUTPUT
+ using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
+#endif
+ {
+ if (GetSelectionIndex == null || InsertAtSelection == null)
+ throw new NotImplementedException();
+
+ int selectionStart = 0, selectionEnd = 0;
+ GetSelectionIndex(out selectionStart, out selectionEnd);
+
+ // 問い合わせのみで実際には操作を行わない
+ if ((i_flags & InsertAtSelectionFlags.TF_IAS_QUERYONLY) != 0)
+ {
+ o_startIndex = Math.Min(selectionStart, selectionEnd);
+ o_endIndex = Math.Max(selectionStart, selectionEnd);//o_startIndex + i_length;
+
+ o_textChange.start = o_startIndex;
+ o_textChange.oldEnd = o_endIndex;
+ o_textChange.newEnd = o_startIndex + i_length;
+ }
+ else
+ {
+ var start = Math.Min(selectionStart, selectionEnd);
+ var end = Math.Max(selectionStart, selectionEnd);
+
+#if TSF_DEBUG_OUTPUT
+ DebugOut.Print("start: {0}, end: {1}, text: {2}", start, end, new string(i_text));
+#endif
+
+ o_startIndex = start;
+ o_endIndex = start + i_length;
+
+ InsertAtSelection(new string(i_text), ref o_startIndex, ref o_endIndex);
+
+ o_textChange.start = start;
+ o_textChange.oldEnd = end;
+ o_textChange.newEnd = o_endIndex;
+ // InsertAtSelection() 内でカーソル位置を更新しているため、ここでは不要。
+ // 改行した時に位置が狂う。
+ // SetSelectionIndex(start, start + i_length);
+ }
+ }
+ }
+
+ public void GetEndACP(out int o_length)
+ {
+#if TSF_DEBUG_OUTPUT
+ using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
+#endif
+ {
+ if (GetStringLength == null)
+ throw new NotImplementedException();
+
+ if (IsLocked(LockFlags.TS_LF_READ) == false)
+ {
+ throw new COMException(
+ "読取用ロックがされていません。",
+ TsResult.TS_E_NOLOCK
+ );
+ }
+
+ o_length = GetStringLength();
+ }
+ }
+
+ public void GetActiveView(out int o_viewCookie)
+ {
+#if TSF_DEBUG_OUTPUT
+ using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
+#endif
+ {
+ o_viewCookie = 1;
+ }
+ }
+
+ public void GetACPFromPoint(
+ int i_viewCookie,
+ ref POINT i_point,
+ GetPositionFromPointFlags i_flags,
+ out int o_index
+ )
+ {
+#if TSF_DEBUG_OUTPUT
+ using (var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()))
+#endif
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ public void GetTextExt(
+ int i_viewCookie,
+ int i_startIndex,
+ int i_endIndex,
+ out RECT o_rect,
+ out bool o_isClipped
+ )
+ {
+#if TSF_DEBUG_OUTPUT
+ using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
+#endif
+ {
+ if (GetStringLength == null)
+ throw new NotImplementedException();
+
+ // 読取用ロックの確認。
+ if (IsLocked(LockFlags.TS_LF_READ) == false)
+ {
+ throw new COMException(
+ "読取用ロックがされていません。",
+ TsResult.TS_E_NOLOCK
+ );
+ }
+
+ if ((i_endIndex != -1 && i_startIndex > i_endIndex)
+ || i_startIndex < 0 || i_startIndex > GetStringLength()
+ || i_endIndex > GetStringLength())
+ {
+ throw new COMException(
+ "インデックスが無効です。",
+ UnmanagedAPI.WinError.HRESULT.E_INVALIDARG
+ );
+ }
+
+ if (i_endIndex == -1)
+ i_endIndex = GetStringLength();
+
+ var pointTopLeft = new POINT();
+ var pointBotttomRight = new POINT();
+ GetStringExtent(i_startIndex, i_endIndex, out pointTopLeft, out pointBotttomRight);
+
+ o_rect.left = (int)(pointTopLeft.x);
+ o_rect.top = (int)(pointTopLeft.y);
+ o_rect.bottom = (int)(pointBotttomRight.y);
+ o_rect.right = (int)(pointBotttomRight.x);
+ o_isClipped = false;
+#if TSF_DEBUG_OUTPUT
+ DebugOut.Print("rect left:{0} top:{1} bottom:{2} right:{3}", o_rect.left, o_rect.top, o_rect.bottom, o_rect.right);
+#endif
+ }
+ }
+
+ public void GetScreenExt(int i_viewCookie, out RECT o_rect)
+ {
+#if TSF_DEBUG_OUTPUT
+ using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
+#endif
+ {
+ if (GetScreenExtent == null)
+ throw new NotImplementedException();
+
+ POINT pointTopLeft, pointBottomRight;
+
+ GetScreenExtent(out pointTopLeft, out pointBottomRight);
+
+ o_rect.left = (int)(pointTopLeft.x);
+ o_rect.top = (int)(pointTopLeft.y);
+ o_rect.bottom = (int)(pointBottomRight.y);
+ o_rect.right = (int)(pointBottomRight.x);
+#if TSF_DEBUG_OUTPUT
+ DebugOut.Print("rect left:{0} top:{1} bottom:{2} right:{3}", o_rect.left, o_rect.top, o_rect.bottom, o_rect.right);
+#endif
+ }
+ }
+
+ public void RequestSupportedAttrs(
+ AttributeFlags i_flags,
+ int i_length,
+ Guid[] i_filterAttributes
+ )
+ {
+#if TSF_DEBUG_OUTPUT
+ using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
+#endif
+ {
+ for (int i = 0; i < i_length; i++)
+ {
+ if (i_filterAttributes[i].Equals(_attributeInfo[0].attrID))
+ {
+ _attributeInfo[0].flags = AttributeInfoFlags.Requested;
+ if ((i_flags & AttributeFlags.TS_ATTR_FIND_WANT_VALUE) != 0)
+ {
+ _attributeInfo[0].flags |= AttributeInfoFlags.Default;
+ }
+ else
+ {
+ _attributeInfo[0].currentValue = _attributeInfo[0].defaultValue;
+ }
+ }
+ }
+ }
+ }
+
+ public void RequestAttrsAtPosition(
+ int i_position,
+ int i_length,
+ Guid[] i_filterAttributes,
+ AttributeFlags i_flags
+ )
+ {
+#if TSF_DEBUG_OUTPUT
+ using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
+#endif
+ {
+ for (int i = 0; i < i_length; i++)
+ {
+ if (i_filterAttributes[i].Equals(_attributeInfo[0].attrID))
+ {
+ _attributeInfo[0].flags = AttributeInfoFlags.Requested;
+ if ((i_flags & AttributeFlags.TS_ATTR_FIND_WANT_VALUE) != 0)
+ {
+ _attributeInfo[0].flags |= AttributeInfoFlags.Default;
+ }
+ else
+ {
+ _attributeInfo[0].currentValue = _attributeInfo[0].defaultValue;
+ }
+ }
+ }
+ }
+ }
+
+ public void RequestAttrsTransitioningAtPosition(
+ int i_position,
+ int i_length,
+ Guid[] i_filterAttributes,
+ AttributeFlags i_flags
+ )
+ {
+#if TSF_DEBUG_OUTPUT
+ using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()))
+#endif
+ {
+ // 何もしない。
+ }
+ }
+
+ public void FindNextAttrTransition(
+ int i_start,
+ int i_halt,
+ int i_length,
+ Guid[] i_filterAttributes,
+ AttributeFlags i_flags,
+ out int o_nextIndex,
+ out bool o_found,
+ out int o_foundOffset
+ )
+ {
+#if TSF_DEBUG_OUTPUT
+ using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
+#endif
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ public void RetrieveRequestedAttrs(
+ int i_length,
+ TS_ATTRVAL[] o_attributeVals,
+ out int o_fetchedLength
+ )
+ {
+#if TSF_DEBUG_OUTPUT
+ using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
+#endif
+ {
+ o_fetchedLength = 0;
+ for (int i = 0; i < _attributeInfo.Length && o_fetchedLength < i_length; i++)
+ {
+ if ((_attributeInfo[i].flags & AttributeInfoFlags.Requested) != 0)
+ {
+ o_attributeVals[o_fetchedLength].overlappedId = 0;
+ o_attributeVals[o_fetchedLength].attributeId = _attributeInfo[i].attrID;
+ o_attributeVals[o_fetchedLength].val = _attributeInfo[i].currentValue;
+
+ if ((_attributeInfo[i].flags & AttributeInfoFlags.Default) != 0)
+ _attributeInfo[i].currentValue = _attributeInfo[i].defaultValue;
+
+ o_fetchedLength++;
+ _attributeInfo[i].flags = AttributeInfoFlags.None;
+ }
+ }
+ }
+ }
+ #endregion
+
+ #region "ITfContextOwnerCompositionSink インターフェイスの実装"
+ /// <summary>コンポジション入力が開始された時の処理。</summary>
+ public void OnStartComposition(ITfCompositionView view, out bool ok)
+ {
+ #if TSF_DEBUG_OUTPUT
+ using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
+ #endif
+ {
+ if( CompositionStarted != null )
+ ok = CompositionStarted();
+ else
+ ok = true;
+ }
+ }
+
+
+ //========================================================================================
+
+
+ /// <summary>コンポジションが変更された時の処理。</summary>
+ public void OnUpdateComposition(ITfCompositionView view, ITfRange rangeNew)
+ {
+ #if TSF_DEBUG_OUTPUT
+ using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
+ #endif
+ {
+ if (rangeNew == null)
+ return;
+
+ int start, count;
+
+ ITfRangeACP rangeAcp = (ITfRangeACP)rangeNew;
+
+ rangeAcp.GetExtent(out start, out count);
+
+ if (this.CompositionUpdated != null)
+ this.CompositionUpdated(start, start + count);
+ }
+ }
+
+
+ //========================================================================================
+
+
+ /// <summary>コンポジション入力が終了した時の処理。</summary>
+ public void OnEndComposition(ITfCompositionView view)
+ {
+ #if TSF_DEBUG_OUTPUT
+ using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
+ #endif
+ {
+ if( CompositionEnded != null )
+ CompositionEnded();
+ }
+ }
+ #endregion "ITfContextOwnerCompositionSink インターフェイスの実装"
+
+ #region 表示属性
+ /// <summary>表示属性の取得</summary>
+ public IEnumerable<TextDisplayAttribute> EnumAttributes(int start, int end)
+ {
+ ITfRangeACP allRange;
+ _services.CreateRange(start, end, out allRange);
+
+ foreach (TextDisplayAttribute attr in this.EnumAttributes((ITfRange)allRange))
+ yield return attr;
+
+ ReleaseComObject("allRange", ref allRange);
+ }
+
+ IEnumerable<TextDisplayAttribute> EnumAttributes(ITfRange range)
+ {
+#if TSF_DEBUG_OUTPUT
+ using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()))
+#endif
+ {
+ ITfProperty property = null; // プロパティインターフェイス
+ IEnumTfRanges enumRanges; // 範囲の列挙子
+ Guid guidPropAttribute = TfDeclarations.GUID_PROP_ATTRIBUTE;
+
+ if (_context == null || _services == null)
+ yield break;
+
+ // GUID_PROP_ATTRIBUTE プロパティを取得。
+ _context.GetProperty(ref guidPropAttribute, out property);
+ if (property == null)
+ yield break;
+
+ // 全範囲の中で表示属性プロパティをもつ範囲を列挙する。
+ property.EnumRanges((int)_editCookie, out enumRanges, range);
+
+ ITfRange[] ranges = new ITfRange[1];
+ int fetchedLength = 0;
+ while (HRESULT.Succeeded(enumRanges.Next(1, ranges, out fetchedLength))
+ && fetchedLength > 0)
+ {
+ // ItfRange から ItfRangeACP を取得。
+ ITfRangeACP rangeACP = ranges[0] as ITfRangeACP;
+ if (rangeACP == null)
+ continue; // 普通はあり得ない
+
+ // 範囲の開始位置と文字数を取得。
+ int start, count;
+ rangeACP.GetExtent(out start, out count);
+
+ // VARIANT 値としてプロパティ値を取得。VT_I4 の GUID ATOM がとれる。
+ VARIANT value = new VARIANT();
+ property.GetValue((int)_editCookie, ranges[0], ref value);
+ if (value.vt == (short)VarEnum.VT_I4)
+ {
+ Guid guid, clsid;
+ ITfDisplayAttributeInfo info;
+ TF_DISPLAYATTRIBUTE attribute;
+
+ // GUID ATOM から GUID を取得する。
+ _categoryMgr.GetGUID((int)value.data1, out guid);
+ // その GUID から IDisplayAttributeInfo インターフェイスを取得。
+ _displayAttributeMgr.GetDisplayAttributeInfo(
+ ref guid,
+ out info,
+ out clsid
+ );
+ // さらに IDisplayAttributeInfo インターフェイスから表示属性を取得する。
+ info.GetAttributeInfo(out attribute);
+ ReleaseComObject("info", ref info);
+
+ yield return new TextDisplayAttribute
+ {
+ startIndex = start,
+ endIndex = start + count,
+ attribute = attribute
+ };
+
+#if TSF_DEBUG_OUTPUT_DISPLAY_ATTR
+ Debug.WriteLine(
+ "*******:::: DisplayAttribute: {0} ~ {1} :::::: *********",
+ start, start + count
+ );
+ Debug.WriteLine(attribute.bAttr);
+ Debug.WriteLine(
+ "LineColorType: {0}, {1}",
+ attribute.crLine.type, attribute.crLine.indexOrColorRef
+ );
+ Debug.WriteLine(
+ "TextColorType: {0}, {1}",
+ attribute.crText.type, attribute.crText.indexOrColorRef
+ );
+ Debug.WriteLine(
+ "BackColorType: {0}, {1}",
+ attribute.crBk.type, attribute.crBk.indexOrColorRef
+ );
+ Debug.WriteLine(
+ "Bold, Style : {0}, {1}",
+ attribute.fBoldLine, attribute.lsStyle
+ );
+#endif
+ }
+
+ ReleaseComObject("rangeACP", ref rangeACP);
+ }
+
+ ReleaseComObject("ranges[0]", ref ranges[0]);
+ ReleaseComObject("enumRanges", ref enumRanges);
+ ReleaseComObject("property", ref property);
+ }
+ }
+ #endregion
+
+#if METRO
+ protected ITfThreadMgr2 _threadMgr;
+#else
+ protected ITfThreadMgr _threadMgr;
+#endif
+ protected ITfDocumentMgr _documentMgr;
+ protected ITfFunctionProvider _functionProvider;
+ protected ITfFnReconversion _reconversion;
+ protected ITfContext _context;
+ protected ITfCategoryMgr _categoryMgr;
+ protected ITfDisplayAttributeMgr _displayAttributeMgr;
+ protected ITextStoreACPSink _sink;
+ protected uint _editCookie = 0;
+ protected ITextStoreACPServices _services;
+ protected AdviseFlags _adviseFlags = 0;
+ protected LockFlags _lockFlags = 0;
+ protected bool _pendingLockUpgrade = false;
+
+ /// <summary>
+ /// AttributeInfo で使用されるフラグ。各属性の状態を示す。
+ /// </summary>
+ protected enum AttributeInfoFlags
+ {
+ /// <summary>何もない。</summary>
+ None = 0,
+ /// <summary>デフォルト値の要求。</summary>
+ Default = 1 << 0,
+ /// <summary>要求された。</summary>
+ Requested = 1 << 1
+ }
+
+ protected struct AttributeInfo
+ {
+ public Guid attrID;
+ public AttributeInfoFlags flags;
+ public VARIANT currentValue;
+ public VARIANT defaultValue;
+ }
+
+ protected AttributeInfo[] _attributeInfo = new AttributeInfo[1];
+
+ }
+}
-using System;\r
-using System.Reflection;\r
-using System.Runtime.InteropServices;\r
-using System.Security;\r
-using DotNetTextStore.UnmanagedAPI.WinDef;\r
-\r
-\r
-namespace DotNetTextStore.UnmanagedAPI.TSF\r
-{\r
- public enum TfAnchor\r
- {\r
- TF_ANCHOR_START,\r
- TF_ANCHOR_END\r
- }\r
-\r
- \r
- public enum TfGravity\r
- {\r
- TF_GR_BACKWARD,\r
- TF_GR_FORWARD\r
- }\r
-\r
-\r
- public enum TfShiftDir\r
- {\r
- TF_SD_BACKWARD,\r
- TF_SD_FORWARD\r
- }\r
-\r
-\r
- [Flags]\r
- public enum PopFlags\r
- {\r
- TF_POPF_ALL = 1\r
- }\r
-\r
-\r
- public enum TfCandidateResult\r
- {\r
- CAND_FINALIZED,\r
- CAND_SELECTED,\r
- CAND_CANCELED\r
- }\r
-\r
-\r
-//============================================================================\r
-\r
-\r
- [ComImport, Guid("AA80E808-2021-11D2-93E0-0060B067B86E"),\r
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)\r
- ]\r
- public interface IEnumTfDocumentMgrs\r
- {\r
- void Clone([Out, MarshalAs(UnmanagedType.Interface)] out IEnumTfDocumentMgrs ppEnum);\r
- void Next([In] uint ulCount, [Out, MarshalAs(UnmanagedType.Interface)] out ITfDocumentMgr rgDocumentMgr, [Out] out uint pcFetched);\r
- void Reset();\r
- void Skip([In] uint ulCount);\r
- }\r
-\r
-\r
-//============================================================================\r
-\r
-\r
- /// <summary>\r
- /// カテゴリマネージャー。\r
- /// \r
- /// <pre>\r
- /// カテゴリマネージャーはテキストサービスのオブジェクトのカテゴリを管理\r
- /// する。GUID アトムから GUID を取得する機能を提供する。\r
- /// </pre>\r
- /// </summary>\r
- [ComImport,\r
- Guid("c3acefb5-f69d-4905-938f-fcadcf4be830"),\r
- SecurityCritical,\r
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown),\r
- ]\r
- public interface ITfCategoryMgr\r
- {\r
- [SecurityCritical]\r
- void stub_RegisterCategory();\r
- [SecurityCritical]\r
- void stub_UnregisterCategory();\r
- [SecurityCritical]\r
- void stub_EnumCategoriesInItem();\r
- [SecurityCritical]\r
- void stub_EnumItemsInCategory();\r
- [SecurityCritical]\r
- void stub_FindClosestCategory();\r
- [SecurityCritical]\r
- void stub_RegisterGUIDDescription();\r
- [SecurityCritical]\r
- void stub_UnregisterGUIDDescription();\r
- [SecurityCritical]\r
- void stub_GetGUIDDescription();\r
- [SecurityCritical]\r
- void stub_RegisterGUIDDWORD();\r
- [SecurityCritical]\r
- void stub_UnregisterGUIDDWORD();\r
- [SecurityCritical]\r
- void stub_GetGUIDDWORD();\r
- /// <summary>GUID を登録して GUID アトムを取得する。</summary>\r
- [PreserveSig, SecurityCritical]\r
- int RegisterGUID(\r
- [In] ref Guid i_guid,\r
- [Out] out uint o_guidAtom\r
- );\r
-\r
- /// <summary>\r
- /// GUID アトムから GUID を取得する。\r
- /// </summary>\r
- /// <param name="i_guidAtom">GUID アトム。</param>\r
- /// <param name="o_guid">GUID。</param>\r
- [SecurityCritical]\r
- void GetGUID(\r
- [In] int i_guidAtom,\r
- [Out] out Guid o_guid\r
- );\r
-\r
- [SecurityCritical]\r
- void stub_IsEqualTfGuidAtom();\r
- }\r
-\r
-\r
-//============================================================================\r
-\r
-\r
- public enum TF_DA_COLORTYPE\r
- {\r
- TF_CT_NONE,\r
- TF_CT_SYSCOLOR,\r
- TF_CT_COLORREF\r
- }\r
-\r
-\r
- /// <summary>表示属性の線のスタイル</summary>\r
- public enum TF_DA_LINESTYLE\r
- {\r
- /// <summary>なし</summary>\r
- TF_LS_NONE,\r
- /// <summary>ソリッド線</summary>\r
- TF_LS_SOLID,\r
- /// <summary>ドット線</summary>\r
- TF_LS_DOT,\r
- /// <summary>ダッシュ線</summary>\r
- TF_LS_DASH,\r
- /// <summary>波線</summary>\r
- TF_LS_SQUIGGLE\r
- }\r
-\r
-\r
- public enum TF_DA_ATTR_INFO\r
- {\r
- TF_ATTR_CONVERTED = 2,\r
- TF_ATTR_FIXEDCONVERTED = 5,\r
- TF_ATTR_INPUT = 0,\r
- TF_ATTR_INPUT_ERROR = 4,\r
- TF_ATTR_OTHER = -1,\r
- TF_ATTR_TARGET_CONVERTED = 1,\r
- TF_ATTR_TARGET_NOTCONVERTED = 3\r
- }\r
-\r
- \r
- [StructLayout(LayoutKind.Sequential)]\r
- public struct TF_DA_COLOR\r
- {\r
- public TF_DA_COLORTYPE type;\r
- public uint indexOrColorRef;\r
- }\r
-\r
-\r
- [StructLayout(LayoutKind.Sequential)]\r
- public struct TF_DISPLAYATTRIBUTE\r
- {\r
- public TF_DA_COLOR crText;\r
- public TF_DA_COLOR crBk;\r
- public TF_DA_LINESTYLE lsStyle;\r
- [MarshalAs(UnmanagedType.Bool)]\r
- public bool fBoldLine;\r
- public TF_DA_COLOR crLine;\r
- public TF_DA_ATTR_INFO bAttr;\r
- }\r
-\r
-\r
-//============================================================================\r
-\r
-\r
- [ComImport,\r
- Guid("70528852-2f26-4aea-8c96-215150578932"),\r
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown),\r
- SecurityCritical\r
- ]\r
- public interface ITfDisplayAttributeInfo\r
- {\r
- [SecurityCritical]\r
- void stub_GetGUID();\r
- [SecurityCritical]\r
- void stub_GetDescription();\r
- [SecurityCritical]\r
- void GetAttributeInfo(out TF_DISPLAYATTRIBUTE attr);\r
- [SecurityCritical]\r
- void stub_SetAttributeInfo();\r
- [SecurityCritical]\r
- void stub_Reset();\r
- }\r
-\r
-\r
-//============================================================================\r
-\r
-\r
- [ComImport,\r
- SecurityCritical,\r
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown),\r
- Guid("8ded7393-5db1-475c-9e71-a39111b0ff67")\r
- ]\r
- public interface ITfDisplayAttributeMgr\r
- {\r
- [SecurityCritical]\r
- void OnUpdateInfo();\r
-\r
- [SecurityCritical]\r
- void stub_EnumDisplayAttributeInfo();\r
-\r
- [SecurityCritical]\r
- void GetDisplayAttributeInfo(\r
- [In] ref Guid i_guid,\r
- [Out] out ITfDisplayAttributeInfo o_info,\r
- [Out] out Guid o_clsid\r
- );\r
- }\r
-\r
- \r
-//============================================================================\r
-#if !METRO\r
- [ComImport,\r
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown),\r
- Guid("aa80e801-2021-11d2-93e0-0060b067b86e")\r
- ]\r
- public interface ITfThreadMgr\r
- {\r
- [SecurityCritical]\r
- void Activate(out int clientId);\r
-\r
- [SecurityCritical]\r
- void Deactivate();\r
-\r
- [SecurityCritical]\r
- void CreateDocumentMgr(out ITfDocumentMgr docMgr);\r
- void EnumDocumentMgrs(out IEnumTfDocumentMgrs enumDocMgrs);\r
- void GetFocus(out ITfDocumentMgr docMgr);\r
- [SecurityCritical]\r
- void SetFocus(ITfDocumentMgr docMgr);\r
- void AssociateFocus(IntPtr hwnd, ITfDocumentMgr newDocMgr, out ITfDocumentMgr prevDocMgr);\r
- void IsThreadFocus([MarshalAs(UnmanagedType.Bool)] out bool isFocus);\r
- [SecurityCritical]\r
- void GetFunctionProvider(ref Guid classId, out ITfFunctionProvider funcProvider);\r
- void EnumFunctionProviders(out IEnumTfFunctionProviders enumProviders);\r
- [SecurityCritical]\r
- void GetGlobalCompartment(out ITfCompartmentMgr compartmentMgr);\r
- }\r
-#endif\r
-\r
- //============================================================================\r
- public enum TfNameFlags\r
- {\r
- NOACTIVATETIP = 0x01,\r
- SECUREMODE = 0x02,\r
- UIELEMENTENABLEDONLY = 0x04,\r
- COMLESS = 0x08,\r
- WOW16 = 0x10,\r
- NOACTIVATEKEYBOARDLAYOUT = 0x20,\r
- CONSOLE = 0x40\r
- }\r
-\r
- [ComImport,\r
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown),\r
- Guid("0ab198ef-6477-4ee8-8812-6780edb82d5e")\r
- ]\r
- public interface ITfThreadMgr2\r
- {\r
- /// <summary>\r
- /// ITfThreadMgr2::Activate\r
- /// </summary>\r
- /// <param name="clientId"></param>\r
- [SecurityCritical]\r
- void Activate(out int clientId);\r
-\r
- /// <summary>\r
- /// ITfThreadMgr2::Deactivate\r
- /// </summary>\r
- [SecurityCritical]\r
- void Deactivate();\r
-\r
- /// <summary>\r
- /// ITfThreadMgr2::CreateDocumentMgr\r
- /// </summary>\r
- /// <param name="docMgr"></param>\r
- [SecurityCritical]\r
- void CreateDocumentMgr(out ITfDocumentMgr docMgr);\r
-\r
- /// <summary>\r
- /// ITfThreadMgr2::EnumDocumentMgrs\r
- /// </summary>\r
- /// <param name="enumDocMgrs"></param>\r
- void EnumDocumentMgrs(out IEnumTfDocumentMgrs enumDocMgrs);\r
-\r
- /// <summary>\r
- /// ITfThreadMgr2::GetFocus\r
- /// </summary>\r
- /// <param name="docMgr"></param>\r
- void GetFocus(out ITfDocumentMgr docMgr);\r
-\r
- /// <summary>\r
- /// ITfThreadMgr2::SetFocus\r
- /// </summary>\r
- /// <param name="docMgr"></param>\r
- [SecurityCritical]\r
- void SetFocus(ITfDocumentMgr docMgr);\r
-\r
- /// <summary>\r
- /// ITfThreadMgr2::IsThreadFocus\r
- /// </summary>\r
- /// <param name="isFocus"></param>\r
- void IsThreadFocus([MarshalAs(UnmanagedType.Bool)] out bool isFocus);\r
-\r
- /// <summary>\r
- /// ITfThreadMgr2::GetFunctionProvider\r
- /// </summary>\r
- /// <param name="classId"></param>\r
- /// <param name="funcProvider"></param>\r
- [SecurityCritical]\r
- void GetFunctionProvider(ref Guid classId, out ITfFunctionProvider funcProvider);\r
-\r
- /// <summary>\r
- /// ITfThreadMgr2::EnumFunctionProviders\r
- /// </summary>\r
- /// <param name="enumProviders"></param>\r
- void EnumFunctionProviders(out IEnumTfFunctionProviders enumProviders);\r
-\r
- /// <summary>\r
- /// ITfThreadMgr2::GetGlobalCompartment\r
- /// </summary>\r
- /// <param name="compartmentMgr"></param>\r
- [SecurityCritical]\r
- void GetGlobalCompartment(out ITfCompartmentMgr compartmentMgr);\r
-\r
- /// <summary>\r
- /// ITfThreadMgr2::ActivateEx\r
- /// </summary>\r
- /// <param name="clientId"></param>\r
- /// <param name="?"></param>\r
- [SecurityCritical]\r
- void ActivateEx(out int clientId,[In] TfNameFlags flags);\r
-\r
- /// <summary>\r
- /// ITfThreadMgr2::GetActiveFlags\r
- /// </summary>\r
- /// <param name="flags"></param>\r
- void GetActiveFlags(out TfNameFlags flags);\r
-\r
- /// <summary>\r
- /// ITfThreadMgr2::SuspendKeystrokeHandling\r
- /// </summary>\r
- void SuspendKeystrokeHandling();\r
-\r
- /// <summary>\r
- /// ITfThreadMgr2::ResumeKeystrokeHandling\r
- /// </summary>\r
- void ResumeKeystrokeHandling();\r
- }\r
-\r
-//============================================================================\r
-\r
-\r
- [ComImport, \r
- Guid("7dcf57ac-18ad-438b-824d-979bffb74b7c"), \r
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)\r
- ]\r
- public interface ITfCompartmentMgr\r
- {\r
- [SecurityCritical,]\r
- void GetCompartment(ref Guid guid, out ITfCompartment comp);\r
- void ClearCompartment(int tid, Guid guid);\r
- void EnumCompartments(out object enumGuid);\r
- }\r
-\r
-\r
-//============================================================================\r
-\r
-\r
- [ComImport,\r
- Guid("bb08f7a9-607a-4384-8623-056892b64371"),\r
- SecurityCritical,\r
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)\r
- ]\r
- public interface ITfCompartment\r
- {\r
- [PreserveSig, SecurityCritical]\r
- int SetValue(int tid, ref object varValue);\r
- [SecurityCritical]\r
- void GetValue(out object varValue);\r
- }\r
-\r
-\r
-//============================================================================\r
-\r
-\r
- [ComImport,\r
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown),\r
- Guid("E4B24DB0-0990-11D3-8DF0-00105A2799B5")\r
- ]\r
- public interface IEnumTfFunctionProviders\r
- {\r
- void Clone([Out, MarshalAs(UnmanagedType.Interface)] out IEnumTfFunctionProviders ppEnum);\r
- void Next([In] uint ulCount, [Out, MarshalAs(UnmanagedType.Interface)] out ITfFunctionProvider ppCmdobj, [Out] out uint pcFetch);\r
- void Reset();\r
- void Skip([In] uint ulCount);\r
- }\r
-\r
- \r
-//============================================================================\r
-\r
-\r
- [ComImport,\r
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown),\r
- Guid("101d6610-0990-11d3-8df0-00105a2799b5")\r
- ]\r
- public interface ITfFunctionProvider\r
- {\r
- void GetType(out Guid guid);\r
- void GetDescription([MarshalAs(UnmanagedType.BStr)] out string desc);\r
- [SecurityCritical, ]\r
- void GetFunction(ref Guid guid, ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out object obj);\r
- }\r
-\r
- \r
-//============================================================================\r
-\r
-\r
- [ComImport,\r
- Guid("aa80e7f4-2021-11d2-93e0-0060b067b86e"),\r
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)\r
- ]\r
- public interface ITfDocumentMgr\r
- {\r
- [SecurityCritical]\r
- void CreateContext(int clientId, uint flags, [MarshalAs(UnmanagedType.Interface)] object obj, out ITfContext context, out uint editCookie);\r
- [SecurityCritical, ]\r
- void Push(ITfContext context);\r
- [SecurityCritical]\r
- void Pop(PopFlags flags);\r
- void GetTop(out ITfContext context);\r
- [SecurityCritical, ]\r
- void GetBase(out ITfContext context);\r
- void EnumContexts([MarshalAs(UnmanagedType.Interface)] out object enumContexts);\r
- }\r
-\r
-\r
-//============================================================================\r
-\r
-\r
- [StructLayout(LayoutKind.Sequential, Pack=4),\r
- Guid("75EB22F2-B0BF-46A8-8006-975A3B6EFCF1")\r
- ]\r
- public struct TF_SELECTION\r
- {\r
- [MarshalAs(UnmanagedType.Interface)]\r
- public ITfRange range;\r
- public TF_SELECTIONSTYLE style;\r
- }\r
-\r
-\r
-//============================================================================\r
-\r
-\r
- /// <summary>\r
- /// 選択範囲の終了位置を示すフラグ。\r
- /// </summary>\r
- public enum TfActiveSelEnd\r
- {\r
- /// <summary>\r
- /// アクティブな選択は無い。\r
- /// </summary>\r
- TF_AE_NONE,\r
- /// <summary>\r
- /// 開始位置が選択範囲の終了位置である。\r
- /// </summary>\r
- TF_AE_START,\r
- /// <summary>\r
- /// 終了位置と選択範囲の終了位置は同じである。\r
- /// </summary>\r
- TF_AE_END\r
- }\r
-\r
-\r
- /// <summary>\r
- /// TF_SELECTION のメンバとして使用される構造体。\r
- /// </summary>\r
- [StructLayout(LayoutKind.Sequential)]\r
- public struct TF_SELECTIONSTYLE\r
- {\r
- /// <summary>\r
- /// 選択範囲の開始位置が終了位置なのか開始位置なのか示す\r
- /// </summary>\r
- public TfActiveSelEnd ase;\r
- /// <summary>\r
- /// 用途不明。説明を見ると変換中の文字のことのようだが変換中の文字に対\r
- /// しても true が渡されたことは無い・・・\r
- /// </summary>\r
- [MarshalAs(UnmanagedType.Bool)]\r
- public bool interimChar;\r
- }\r
-\r
-\r
-//============================================================================\r
-\r
-\r
- [ComImport,\r
- Guid("aa80e7fd-2021-11d2-93e0-0060b067b86e"),\r
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)\r
- ]\r
- public interface ITfContext\r
- {\r
- int stub_RequestEditSession();\r
- void InWriteSession(int clientId, [MarshalAs(UnmanagedType.Bool)] out bool inWriteSession);\r
- void GetSelection(\r
- [In] uint ec,\r
- [In] uint ulIndex,\r
- [In] uint ulCount,\r
- [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=3)] TF_SELECTION[] pSelection,\r
- [Out] out uint pcFetched\r
- );\r
- void stub_SetSelection();\r
- [SecurityCritical]\r
- void GetStart(int ec, out ITfRange range);\r
- void stub_GetEnd();\r
- void stub_GetActiveView();\r
- void stub_EnumViews();\r
- void stub_GetStatus();\r
- [SecurityCritical]\r
- void GetProperty(ref Guid guid, out ITfProperty property);\r
- void stub_GetAppProperty();\r
-\r
- void TrackProperties(\r
- [In] ref Guid[] guids,\r
- [In] uint propertyGuidLength,\r
- [In] IntPtr prgAppProp,\r
- [In] uint cAppProp,\r
- [Out, MarshalAs(UnmanagedType.Interface)] out ITfReadOnlyProperty ppProperty\r
- ); \r
-\r
- void EnumProperties([Out, MarshalAs(UnmanagedType.Interface)] out IEnumTfProperties ppEnum);\r
- void stub_GetDocumentMgr();\r
- void stub_CreateRangeBackup();\r
- }\r
-\r
-\r
-//============================================================================\r
-\r
- \r
- [ComImport, Guid("19188CB0-ACA9-11D2-AFC5-00105A2799B5"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]\r
- public interface IEnumTfProperties\r
- {\r
- void Clone([Out, MarshalAs(UnmanagedType.Interface)] out IEnumTfProperties ppEnum);\r
-\r
- [PreserveSig, SecurityCritical]\r
- int Next(\r
- [In] uint i_count,\r
- [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=2)] ITfProperty[] o_properties,\r
- [Out] out int o_fetchedLength\r
- );\r
-\r
- void Reset();\r
-\r
- void Skip([In] uint ulCount);\r
- }\r
-\r
-\r
-//============================================================================\r
-\r
-\r
- [ComImport,\r
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown),\r
- SecurityCritical,\r
- Guid("aa80e7ff-2021-11d2-93e0-0060b067b86e")\r
- ]\r
- public interface ITfRange\r
- {\r
- [SecurityCritical]\r
- void GetText(int ec, int flags, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=3)] char[] text, int countMax, out int count);\r
- [SecurityCritical]\r
- void SetText(int ec, int flags, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=3)] char[] text, int count);\r
- [SecurityCritical]\r
- void GetFormattedText(int ec, [MarshalAs(UnmanagedType.Interface)] out object data);\r
- [SecurityCritical]\r
- void GetEmbedded(int ec, ref Guid guidService, ref Guid iid, [MarshalAs(UnmanagedType.Interface)] out object obj);\r
- [SecurityCritical]\r
- void InsertEmbedded(int ec, int flags, [MarshalAs(UnmanagedType.Interface)] object data);\r
- [SecurityCritical]\r
- void ShiftStart(int ec, int count, out int result, int ZeroForNow);\r
- [SecurityCritical]\r
- void ShiftEnd(int ec, int count, out int result, int ZeroForNow);\r
- [SecurityCritical]\r
- void ShiftStartToRange(int ec, ITfRange range, TfAnchor position);\r
- [SecurityCritical]\r
- void ShiftEndToRange(int ec, ITfRange range, TfAnchor position);\r
- [SecurityCritical]\r
- void ShiftStartRegion(int ec, TfShiftDir dir, [MarshalAs(UnmanagedType.Bool)] out bool noRegion);\r
- [SecurityCritical]\r
- void ShiftEndRegion(int ec, TfShiftDir dir, [MarshalAs(UnmanagedType.Bool)] out bool noRegion);\r
- [SecurityCritical]\r
- void IsEmpty(int ec, [MarshalAs(UnmanagedType.Bool)] out bool empty);\r
- [SecurityCritical]\r
- void Collapse(int ec, TfAnchor position);\r
- [SecurityCritical]\r
- void IsEqualStart(int ec, ITfRange with, TfAnchor position, [MarshalAs(UnmanagedType.Bool)] out bool equal);\r
- [SecurityCritical]\r
- void IsEqualEnd(int ec, ITfRange with, TfAnchor position, [MarshalAs(UnmanagedType.Bool)] out bool equal);\r
- [SecurityCritical]\r
- void CompareStart(int ec, ITfRange with, TfAnchor position, out int result);\r
- [SecurityCritical]\r
- void CompareEnd(int ec, ITfRange with, TfAnchor position, out int result);\r
- [SecurityCritical]\r
- void AdjustForInsert(int ec, int count, [MarshalAs(UnmanagedType.Bool)] out bool insertOk);\r
- [SecurityCritical]\r
- void GetGravity(out TfGravity start, out TfGravity end);\r
- [SecurityCritical]\r
- void SetGravity(int ec, TfGravity start, TfGravity end);\r
- [SecurityCritical]\r
- void Clone(out ITfRange clone);\r
- [SecurityCritical]\r
- void GetContext(out ITfContext context);\r
- }\r
-\r
-\r
-//============================================================================\r
-\r
-\r
- [ComImport,\r
- SecurityCritical,\r
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown),\r
- Guid("057a6296-029b-4154-b79a-0d461d4ea94c")\r
- ]\r
- public interface ITfRangeACP\r
- {\r
- [SecurityCritical]\r
- void GetText(int ec, int flags, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=3)] char[] text, int countMax, out int count);\r
- [SecurityCritical]\r
- void SetText(int ec, int flags, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=3)] char[] text, int count);\r
- [SecurityCritical]\r
- void GetFormattedText(int ec, [MarshalAs(UnmanagedType.Interface)] out object data);\r
- [SecurityCritical]\r
- void GetEmbedded(int ec, ref Guid guidService, ref Guid iid, [MarshalAs(UnmanagedType.Interface)] out object obj);\r
- [SecurityCritical]\r
- void InsertEmbedded(int ec, int flags, [MarshalAs(UnmanagedType.Interface)] object data);\r
- [SecurityCritical]\r
- void ShiftStart(int ec, int count, out int result, int ZeroForNow);\r
- [SecurityCritical]\r
- void ShiftEnd(int ec, int count, out int result, int ZeroForNow);\r
- [SecurityCritical]\r
- void ShiftStartToRange(int ec, ITfRange range, TfAnchor position);\r
- [SecurityCritical]\r
- void ShiftEndToRange(int ec, ITfRange range, TfAnchor position);\r
- [SecurityCritical]\r
- void ShiftStartRegion(int ec, TfShiftDir dir, [MarshalAs(UnmanagedType.Bool)] out bool noRegion);\r
- [SecurityCritical]\r
- void ShiftEndRegion(int ec, TfShiftDir dir, [MarshalAs(UnmanagedType.Bool)] out bool noRegion);\r
- [SecurityCritical]\r
- void IsEmpty(int ec, [MarshalAs(UnmanagedType.Bool)] out bool empty);\r
- [SecurityCritical]\r
- void Collapse(int ec, TfAnchor position);\r
- [SecurityCritical]\r
- void IsEqualStart(int ec, ITfRange with, TfAnchor position, [MarshalAs(UnmanagedType.Bool)] out bool equal);\r
- [SecurityCritical]\r
- void IsEqualEnd(int ec, ITfRange with, TfAnchor position, [MarshalAs(UnmanagedType.Bool)] out bool equal);\r
- [SecurityCritical]\r
- void CompareStart(int ec, ITfRange with, TfAnchor position, out int result);\r
- [SecurityCritical]\r
- void CompareEnd(int ec, ITfRange with, TfAnchor position, out int result);\r
- [SecurityCritical]\r
- void AdjustForInsert(int ec, int count, [MarshalAs(UnmanagedType.Bool)] out bool insertOk);\r
- [SecurityCritical]\r
- void GetGravity(out TfGravity start, out TfGravity end);\r
- [SecurityCritical]\r
- void SetGravity(int ec, TfGravity start, TfGravity end);\r
- [SecurityCritical]\r
- void Clone(out ITfRange clone);\r
- [SecurityCritical]\r
- void GetContext(out ITfContext context);\r
- [SecurityCritical]\r
- void GetExtent(out int start, out int count);\r
- [SecurityCritical]\r
- void SetExtent(int start, int count);\r
- }\r
-\r
-\r
-//============================================================================\r
-\r
-\r
- [ComImport,\r
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown),\r
- Guid("17D49A3D-F8B8-4B2F-B254-52319DD64C53"),\r
- SecurityCritical, \r
- \r
- ]\r
- public interface ITfReadOnlyProperty\r
- {\r
- void GetType(\r
- [Out] out Guid o_guid\r
- );\r
-\r
- void EnumRanges(\r
- [In] int i_editCookie,\r
- [Out, MarshalAs(UnmanagedType.Interface)] out IEnumTfRanges o_enumRanges,\r
- [In, MarshalAs(UnmanagedType.Interface)] ITfRange i_targetRange\r
- );\r
-\r
- void GetValue(\r
- [In] int i_editCookie,\r
- [In, MarshalAs(UnmanagedType.Interface)] ITfRange i_range,\r
- [In, Out, MarshalAs(UnmanagedType.Struct)] ref VARIANT o_varValue\r
- );\r
-\r
- void GetContext(\r
- [Out, MarshalAs(UnmanagedType.Interface)] out ITfContext o_ppContext\r
- );\r
- }\r
-\r
- \r
-//============================================================================\r
-\r
-\r
- //[ComImport,\r
- // Guid("e2449660-9542-11d2-bf46-00105a2799b5"),\r
- // InterfaceType(ComInterfaceType.InterfaceIsIUnknown), \r
- // SecurityCritical, \r
- // \r
- //]\r
- //public interface ITfProperty : ITfReadOnlyProperty\r
- //{\r
- // void FindRange(int editCookie, ITfRange inRange, out ITfRange outRange, TfAnchor position);\r
- // void stub_SetValueStore();\r
- // void SetValue(int editCookie, ITfRange range, object value);\r
- // void Clear(int editCookie, ITfRange range);\r
- //}\r
-\r
-\r
- [ComImport, Guid("e2449660-9542-11d2-bf46-00105a2799b5"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), SecurityCritical]\r
- public interface ITfProperty\r
- {\r
- void GetType(out Guid type);\r
- [PreserveSig]\r
- int EnumRanges(int editcookie, out IEnumTfRanges ranges, ITfRange targetRange);\r
- void GetValue(int editCookie, ITfRange range, ref VARIANT value);\r
- void GetContext(out ITfContext context);\r
- void FindRange(int editCookie, ITfRange inRange, out ITfRange outRange, TfAnchor position);\r
- void stub_SetValueStore();\r
- void SetValue(int editCookie, ITfRange range, object value);\r
- void Clear(int editCookie, ITfRange range);\r
- }\r
-\r
- \r
-//============================================================================\r
-\r
-\r
- [StructLayout(LayoutKind.Sequential, Pack = 8), Guid("D678C645-EB6A-45C9-B4EE-0F3E3A991348")]\r
- public struct TF_PROPERTYVAL\r
- {\r
- public Guid guidId;\r
- [MarshalAs(UnmanagedType.Struct)]\r
- public VARIANT varValue;\r
- }\r
-\r
- \r
-//============================================================================\r
-\r
- \r
- [ComImport, Guid("8ED8981B-7C10-4D7D-9FB3-AB72E9C75F72"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]\r
- public interface IEnumTfPropertyValue\r
- {\r
- void Clone([Out, MarshalAs(UnmanagedType.Interface)] out IEnumTfPropertyValue ppEnum);\r
- [PreserveSig, SecurityCritical]\r
- int Next([In] uint ulCount, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=2)] TF_PROPERTYVAL[] values, [Out] out int fetched);\r
- void Reset();\r
- void Skip([In] uint ulCount);\r
- }\r
-\r
- \r
-//============================================================================\r
-\r
- \r
- [ComImport, \r
- Guid("f99d3f40-8e32-11d2-bf46-00105a2799b5"), \r
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown), \r
- SecurityCritical\r
- ]\r
- public interface IEnumTfRanges\r
- {\r
- [SecurityCritical]\r
- void Clone(out IEnumTfRanges ranges);\r
- [PreserveSig, SecurityCritical]\r
- int Next(int count, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=2)] ITfRange[] ranges, out int fetched);\r
- [SecurityCritical]\r
- void Reset();\r
- [PreserveSig, SecurityCritical]\r
- int Skip(int count);\r
- }\r
-\r
-\r
-//============================================================================\r
-\r
-\r
- [ComImport, \r
- Guid("a3ad50fb-9bdb-49e3-a843-6c76520fbf5d"), \r
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)\r
- ]\r
- public interface ITfCandidateList\r
- {\r
- void EnumCandidates(out object enumCand);\r
- [SecurityCritical]\r
- void GetCandidate(int nIndex, out ITfCandidateString candstring);\r
- [SecurityCritical]\r
- void GetCandidateNum(out int nCount);\r
- [SecurityCritical]\r
- void SetResult(int nIndex, TfCandidateResult result);\r
- }\r
-\r
-\r
-//============================================================================\r
-\r
-\r
- [ComImport,\r
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown),\r
- Guid("581f317e-fd9d-443f-b972-ed00467c5d40")\r
- ]\r
- public interface ITfCandidateString\r
- {\r
- [SecurityCritical]\r
- void GetString([MarshalAs(UnmanagedType.BStr)] out string funcName);\r
- void GetIndex(out int nIndex);\r
- }\r
- \r
-\r
-//============================================================================\r
-\r
-\r
- [ComImport, \r
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown), \r
- Guid("4cea93c0-0a58-11d3-8df0-00105a2799b5")\r
- ]\r
- public interface ITfFnReconversion\r
- {\r
- void GetDisplayName([MarshalAs(UnmanagedType.BStr)] out string funcName);\r
- [PreserveSig, SecurityCritical, ]\r
- int QueryRange(ITfRange range, out ITfRange newRange, [MarshalAs(UnmanagedType.Bool)] out bool isConvertable);\r
- [PreserveSig, SecurityCritical, ]\r
- int GetReconversion(ITfRange range, out ITfCandidateList candList);\r
- [PreserveSig, SecurityCritical]\r
- int Reconvert(ITfRange range);\r
- }\r
-\r
-\r
-//============================================================================\r
-\r
-\r
- [ComImport, \r
- SecurityCritical, \r
- Guid("D7540241-F9A1-4364-BEFC-DBCD2C4395B7"), \r
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)\r
- ]\r
- public interface ITfCompositionView\r
- {\r
- [SecurityCritical]\r
- void GetOwnerClsid(out Guid clsid);\r
- [SecurityCritical]\r
- void GetRange(out ITfRange range);\r
- }\r
-\r
- \r
-//============================================================================\r
-\r
-#if !METRO\r
- /// <summary>\r
- /// テキストフレームワークの関数。\r
- /// </summary>\r
- public static class TextFrameworkFunctions\r
- {\r
- /// <summary>\r
- /// スレッドマネージャーの生成。\r
- /// </summary>\r
- /// <param name="o_threadManager">スレッドマネージャーの受け取り先。</param>\r
- [DllImport("msctf.dll")]\r
- public static extern void TF_CreateThreadMgr(\r
- [Out, MarshalAs(UnmanagedType.Interface)] out ITfThreadMgr o_threadManager\r
- );\r
-\r
- /// <summary>\r
- /// スレッドマネージャーが既に生成されている場合、そのポインタを取得する。\r
- /// </summary>\r
- /// <param name="o_threadManager">スレッドマネージャーの受け取り先。</param>\r
- [DllImport("msctf.dll")]\r
- public static extern void TF_GetThreadMgr(\r
- [Out, MarshalAs(UnmanagedType.Interface)] out ITfThreadMgr o_threadManager\r
- );\r
- }\r
-#endif\r
-\r
-//============================================================================\r
-\r
-\r
- /// <summary>\r
- /// テキストフレームワークで宣言されている定数等。\r
- /// </summary>\r
- public static class TfDeclarations\r
- {\r
- public static readonly Guid CLSID_TF_ThreadMgr = new Guid("529a9e6b-6587-4f23-ab9e-9c7d683e3c50");\r
- public static readonly Guid GUID_SYSTEM_FUNCTIONPROVIDER = new Guid("9a698bb0-0f21-11d3-8df1-00105a2799b5");\r
- public static readonly Guid CLSID_TF_DisplayAttributeMgr = new Guid("3ce74de4-53d3-4d74-8b83-431b3828ba53");\r
- public static readonly Guid CLSID_TF_CategoryMgr = new Guid("a4b544a1-438d-4b41-9325-869523e2d6c7");\r
- public static readonly Guid GUID_PROP_ATTRIBUTE = new Guid("34b45670-7526-11d2-a147-00105a2799b5");\r
- public static readonly Guid GUID_PROP_MODEBIAS = new Guid("372e0716-974f-40ac-a088-08cdc92ebfbc");\r
- public static readonly Guid GUID_MODEBIAS_NONE = Guid.Empty;\r
- }\r
-\r
-\r
- [StructLayout(LayoutKind.Sequential)]\r
- public struct VARIANT\r
- {\r
- [MarshalAs(UnmanagedType.I2)]\r
- public short vt;\r
- [MarshalAs(UnmanagedType.I2)]\r
- public short reserved1;\r
- [MarshalAs(UnmanagedType.I2)]\r
- public short reserved2;\r
- [MarshalAs(UnmanagedType.I2)]\r
- public short reserved3;\r
- public IntPtr data1;\r
- public IntPtr data2;\r
- }\r
- \r
-}\r
+using System;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Security;
+using DotNetTextStore.UnmanagedAPI.WinDef;
+
+
+namespace DotNetTextStore.UnmanagedAPI.TSF
+{
+ public enum TfAnchor
+ {
+ TF_ANCHOR_START,
+ TF_ANCHOR_END
+ }
+
+
+ public enum TfGravity
+ {
+ TF_GR_BACKWARD,
+ TF_GR_FORWARD
+ }
+
+
+ public enum TfShiftDir
+ {
+ TF_SD_BACKWARD,
+ TF_SD_FORWARD
+ }
+
+
+ [Flags]
+ public enum PopFlags
+ {
+ TF_POPF_ALL = 1
+ }
+
+
+ public enum TfCandidateResult
+ {
+ CAND_FINALIZED,
+ CAND_SELECTED,
+ CAND_CANCELED
+ }
+
+
+//============================================================================
+
+
+ [ComImport, Guid("AA80E808-2021-11D2-93E0-0060B067B86E"),
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown)
+ ]
+ public interface IEnumTfDocumentMgrs
+ {
+ void Clone([Out, MarshalAs(UnmanagedType.Interface)] out IEnumTfDocumentMgrs ppEnum);
+ void Next([In] uint ulCount, [Out, MarshalAs(UnmanagedType.Interface)] out ITfDocumentMgr rgDocumentMgr, [Out] out uint pcFetched);
+ void Reset();
+ void Skip([In] uint ulCount);
+ }
+
+
+//============================================================================
+
+
+ /// <summary>
+ /// カテゴリマネージャー。
+ ///
+ /// <pre>
+ /// カテゴリマネージャーはテキストサービスのオブジェクトのカテゴリを管理
+ /// する。GUID アトムから GUID を取得する機能を提供する。
+ /// </pre>
+ /// </summary>
+ [ComImport,
+ Guid("c3acefb5-f69d-4905-938f-fcadcf4be830"),
+ SecurityCritical,
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
+ ]
+ public interface ITfCategoryMgr
+ {
+ [SecurityCritical]
+ void stub_RegisterCategory();
+ [SecurityCritical]
+ void stub_UnregisterCategory();
+ [SecurityCritical]
+ void stub_EnumCategoriesInItem();
+ [SecurityCritical]
+ void stub_EnumItemsInCategory();
+ [SecurityCritical]
+ void stub_FindClosestCategory();
+ [SecurityCritical]
+ void stub_RegisterGUIDDescription();
+ [SecurityCritical]
+ void stub_UnregisterGUIDDescription();
+ [SecurityCritical]
+ void stub_GetGUIDDescription();
+ [SecurityCritical]
+ void stub_RegisterGUIDDWORD();
+ [SecurityCritical]
+ void stub_UnregisterGUIDDWORD();
+ [SecurityCritical]
+ void stub_GetGUIDDWORD();
+ /// <summary>GUID を登録して GUID アトムを取得する。</summary>
+ [PreserveSig, SecurityCritical]
+ int RegisterGUID(
+ [In] ref Guid i_guid,
+ [Out] out uint o_guidAtom
+ );
+
+ /// <summary>
+ /// GUID アトムから GUID を取得する。
+ /// </summary>
+ /// <param name="i_guidAtom">GUID アトム。</param>
+ /// <param name="o_guid">GUID。</param>
+ [SecurityCritical]
+ void GetGUID(
+ [In] int i_guidAtom,
+ [Out] out Guid o_guid
+ );
+
+ [SecurityCritical]
+ void stub_IsEqualTfGuidAtom();
+ }
+
+
+//============================================================================
+
+
+ public enum TF_DA_COLORTYPE
+ {
+ TF_CT_NONE,
+ TF_CT_SYSCOLOR,
+ TF_CT_COLORREF
+ }
+
+
+ /// <summary>表示属性の線のスタイル</summary>
+ public enum TF_DA_LINESTYLE
+ {
+ /// <summary>なし</summary>
+ TF_LS_NONE,
+ /// <summary>ソリッド線</summary>
+ TF_LS_SOLID,
+ /// <summary>ドット線</summary>
+ TF_LS_DOT,
+ /// <summary>ダッシュ線</summary>
+ TF_LS_DASH,
+ /// <summary>波線</summary>
+ TF_LS_SQUIGGLE
+ }
+
+
+ public enum TF_DA_ATTR_INFO
+ {
+ TF_ATTR_CONVERTED = 2,
+ TF_ATTR_FIXEDCONVERTED = 5,
+ TF_ATTR_INPUT = 0,
+ TF_ATTR_INPUT_ERROR = 4,
+ TF_ATTR_OTHER = -1,
+ TF_ATTR_TARGET_CONVERTED = 1,
+ TF_ATTR_TARGET_NOTCONVERTED = 3
+ }
+
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct TF_DA_COLOR
+ {
+ public TF_DA_COLORTYPE type;
+ public uint indexOrColorRef;
+ }
+
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct TF_DISPLAYATTRIBUTE
+ {
+ public TF_DA_COLOR crText;
+ public TF_DA_COLOR crBk;
+ public TF_DA_LINESTYLE lsStyle;
+ [MarshalAs(UnmanagedType.Bool)]
+ public bool fBoldLine;
+ public TF_DA_COLOR crLine;
+ public TF_DA_ATTR_INFO bAttr;
+ }
+
+
+//============================================================================
+
+
+ [ComImport,
+ Guid("70528852-2f26-4aea-8c96-215150578932"),
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
+ SecurityCritical
+ ]
+ public interface ITfDisplayAttributeInfo
+ {
+ [SecurityCritical]
+ void stub_GetGUID();
+ [SecurityCritical]
+ void stub_GetDescription();
+ [SecurityCritical]
+ void GetAttributeInfo(out TF_DISPLAYATTRIBUTE attr);
+ [SecurityCritical]
+ void stub_SetAttributeInfo();
+ [SecurityCritical]
+ void stub_Reset();
+ }
+
+
+//============================================================================
+
+
+ [ComImport,
+ SecurityCritical,
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
+ Guid("8ded7393-5db1-475c-9e71-a39111b0ff67")
+ ]
+ public interface ITfDisplayAttributeMgr
+ {
+ [SecurityCritical]
+ void OnUpdateInfo();
+
+ [SecurityCritical]
+ void stub_EnumDisplayAttributeInfo();
+
+ [SecurityCritical]
+ void GetDisplayAttributeInfo(
+ [In] ref Guid i_guid,
+ [Out] out ITfDisplayAttributeInfo o_info,
+ [Out] out Guid o_clsid
+ );
+ }
+
+
+//============================================================================
+#if !METRO
+ [ComImport,
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
+ Guid("aa80e801-2021-11d2-93e0-0060b067b86e")
+ ]
+ public interface ITfThreadMgr
+ {
+ [SecurityCritical]
+ void Activate(out int clientId);
+
+ [SecurityCritical]
+ void Deactivate();
+
+ [SecurityCritical]
+ void CreateDocumentMgr(out ITfDocumentMgr docMgr);
+ void EnumDocumentMgrs(out IEnumTfDocumentMgrs enumDocMgrs);
+ void GetFocus(out ITfDocumentMgr docMgr);
+ [SecurityCritical]
+ void SetFocus(ITfDocumentMgr docMgr);
+ void AssociateFocus(IntPtr hwnd, ITfDocumentMgr newDocMgr, out ITfDocumentMgr prevDocMgr);
+ void IsThreadFocus([MarshalAs(UnmanagedType.Bool)] out bool isFocus);
+ [SecurityCritical]
+ void GetFunctionProvider(ref Guid classId, out ITfFunctionProvider funcProvider);
+ void EnumFunctionProviders(out IEnumTfFunctionProviders enumProviders);
+ [SecurityCritical]
+ void GetGlobalCompartment(out ITfCompartmentMgr compartmentMgr);
+ }
+#endif
+
+ //============================================================================
+ public enum TfNameFlags
+ {
+ NOACTIVATETIP = 0x01,
+ SECUREMODE = 0x02,
+ UIELEMENTENABLEDONLY = 0x04,
+ COMLESS = 0x08,
+ WOW16 = 0x10,
+ NOACTIVATEKEYBOARDLAYOUT = 0x20,
+ CONSOLE = 0x40
+ }
+
+ [ComImport,
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
+ Guid("0ab198ef-6477-4ee8-8812-6780edb82d5e")
+ ]
+ public interface ITfThreadMgr2
+ {
+ /// <summary>
+ /// ITfThreadMgr2::Activate
+ /// </summary>
+ /// <param name="clientId"></param>
+ [SecurityCritical]
+ void Activate(out int clientId);
+
+ /// <summary>
+ /// ITfThreadMgr2::Deactivate
+ /// </summary>
+ [SecurityCritical]
+ void Deactivate();
+
+ /// <summary>
+ /// ITfThreadMgr2::CreateDocumentMgr
+ /// </summary>
+ /// <param name="docMgr"></param>
+ [SecurityCritical]
+ void CreateDocumentMgr(out ITfDocumentMgr docMgr);
+
+ /// <summary>
+ /// ITfThreadMgr2::EnumDocumentMgrs
+ /// </summary>
+ /// <param name="enumDocMgrs"></param>
+ void EnumDocumentMgrs(out IEnumTfDocumentMgrs enumDocMgrs);
+
+ /// <summary>
+ /// ITfThreadMgr2::GetFocus
+ /// </summary>
+ /// <param name="docMgr"></param>
+ void GetFocus(out ITfDocumentMgr docMgr);
+
+ /// <summary>
+ /// ITfThreadMgr2::SetFocus
+ /// </summary>
+ /// <param name="docMgr"></param>
+ [SecurityCritical]
+ void SetFocus(ITfDocumentMgr docMgr);
+
+ /// <summary>
+ /// ITfThreadMgr2::IsThreadFocus
+ /// </summary>
+ /// <param name="isFocus"></param>
+ void IsThreadFocus([MarshalAs(UnmanagedType.Bool)] out bool isFocus);
+
+ /// <summary>
+ /// ITfThreadMgr2::GetFunctionProvider
+ /// </summary>
+ /// <param name="classId"></param>
+ /// <param name="funcProvider"></param>
+ [SecurityCritical]
+ void GetFunctionProvider(ref Guid classId, out ITfFunctionProvider funcProvider);
+
+ /// <summary>
+ /// ITfThreadMgr2::EnumFunctionProviders
+ /// </summary>
+ /// <param name="enumProviders"></param>
+ void EnumFunctionProviders(out IEnumTfFunctionProviders enumProviders);
+
+ /// <summary>
+ /// ITfThreadMgr2::GetGlobalCompartment
+ /// </summary>
+ /// <param name="compartmentMgr"></param>
+ [SecurityCritical]
+ void GetGlobalCompartment(out ITfCompartmentMgr compartmentMgr);
+
+ /// <summary>
+ /// ITfThreadMgr2::ActivateEx
+ /// </summary>
+ /// <param name="clientId"></param>
+ /// <param name="?"></param>
+ [SecurityCritical]
+ void ActivateEx(out int clientId,[In] TfNameFlags flags);
+
+ /// <summary>
+ /// ITfThreadMgr2::GetActiveFlags
+ /// </summary>
+ /// <param name="flags"></param>
+ void GetActiveFlags(out TfNameFlags flags);
+
+ /// <summary>
+ /// ITfThreadMgr2::SuspendKeystrokeHandling
+ /// </summary>
+ void SuspendKeystrokeHandling();
+
+ /// <summary>
+ /// ITfThreadMgr2::ResumeKeystrokeHandling
+ /// </summary>
+ void ResumeKeystrokeHandling();
+ }
+
+//============================================================================
+
+
+ [ComImport,
+ Guid("7dcf57ac-18ad-438b-824d-979bffb74b7c"),
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown)
+ ]
+ public interface ITfCompartmentMgr
+ {
+ [SecurityCritical,]
+ void GetCompartment(ref Guid guid, out ITfCompartment comp);
+ void ClearCompartment(int tid, Guid guid);
+ void EnumCompartments(out object enumGuid);
+ }
+
+
+//============================================================================
+
+
+ [ComImport,
+ Guid("bb08f7a9-607a-4384-8623-056892b64371"),
+ SecurityCritical,
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown)
+ ]
+ public interface ITfCompartment
+ {
+ [PreserveSig, SecurityCritical]
+ int SetValue(int tid, ref object varValue);
+ [SecurityCritical]
+ void GetValue(out object varValue);
+ }
+
+
+//============================================================================
+
+
+ [ComImport,
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
+ Guid("E4B24DB0-0990-11D3-8DF0-00105A2799B5")
+ ]
+ public interface IEnumTfFunctionProviders
+ {
+ void Clone([Out, MarshalAs(UnmanagedType.Interface)] out IEnumTfFunctionProviders ppEnum);
+ void Next([In] uint ulCount, [Out, MarshalAs(UnmanagedType.Interface)] out ITfFunctionProvider ppCmdobj, [Out] out uint pcFetch);
+ void Reset();
+ void Skip([In] uint ulCount);
+ }
+
+
+//============================================================================
+
+
+ [ComImport,
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
+ Guid("101d6610-0990-11d3-8df0-00105a2799b5")
+ ]
+ public interface ITfFunctionProvider
+ {
+ void GetType(out Guid guid);
+ void GetDescription([MarshalAs(UnmanagedType.BStr)] out string desc);
+ [SecurityCritical, ]
+ void GetFunction(ref Guid guid, ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out object obj);
+ }
+
+
+//============================================================================
+
+
+ [ComImport,
+ Guid("aa80e7f4-2021-11d2-93e0-0060b067b86e"),
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown)
+ ]
+ public interface ITfDocumentMgr
+ {
+ [SecurityCritical]
+ void CreateContext(int clientId, uint flags, [MarshalAs(UnmanagedType.Interface)] object obj, out ITfContext context, out uint editCookie);
+ [SecurityCritical, ]
+ void Push(ITfContext context);
+ [SecurityCritical]
+ void Pop(PopFlags flags);
+ void GetTop(out ITfContext context);
+ [SecurityCritical, ]
+ void GetBase(out ITfContext context);
+ void EnumContexts([MarshalAs(UnmanagedType.Interface)] out object enumContexts);
+ }
+
+
+//============================================================================
+
+
+ [StructLayout(LayoutKind.Sequential, Pack=4),
+ Guid("75EB22F2-B0BF-46A8-8006-975A3B6EFCF1")
+ ]
+ public struct TF_SELECTION
+ {
+ [MarshalAs(UnmanagedType.Interface)]
+ public ITfRange range;
+ public TF_SELECTIONSTYLE style;
+ }
+
+
+//============================================================================
+
+
+ /// <summary>
+ /// 選択範囲の終了位置を示すフラグ。
+ /// </summary>
+ public enum TfActiveSelEnd
+ {
+ /// <summary>
+ /// アクティブな選択は無い。
+ /// </summary>
+ TF_AE_NONE,
+ /// <summary>
+ /// 開始位置が選択範囲の終了位置である。
+ /// </summary>
+ TF_AE_START,
+ /// <summary>
+ /// 終了位置と選択範囲の終了位置は同じである。
+ /// </summary>
+ TF_AE_END
+ }
+
+
+ /// <summary>
+ /// TF_SELECTION のメンバとして使用される構造体。
+ /// </summary>
+ [StructLayout(LayoutKind.Sequential)]
+ public struct TF_SELECTIONSTYLE
+ {
+ /// <summary>
+ /// 選択範囲の開始位置が終了位置なのか開始位置なのか示す
+ /// </summary>
+ public TfActiveSelEnd ase;
+ /// <summary>
+ /// 用途不明。説明を見ると変換中の文字のことのようだが変換中の文字に対
+ /// しても true が渡されたことは無い・・・
+ /// </summary>
+ [MarshalAs(UnmanagedType.Bool)]
+ public bool interimChar;
+ }
+
+
+//============================================================================
+
+
+ [ComImport,
+ Guid("aa80e7fd-2021-11d2-93e0-0060b067b86e"),
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown)
+ ]
+ public interface ITfContext
+ {
+ int stub_RequestEditSession();
+ void InWriteSession(int clientId, [MarshalAs(UnmanagedType.Bool)] out bool inWriteSession);
+ void GetSelection(
+ [In] uint ec,
+ [In] uint ulIndex,
+ [In] uint ulCount,
+ [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=3)] TF_SELECTION[] pSelection,
+ [Out] out uint pcFetched
+ );
+ void stub_SetSelection();
+ [SecurityCritical]
+ void GetStart(int ec, out ITfRange range);
+ void stub_GetEnd();
+ void stub_GetActiveView();
+ void stub_EnumViews();
+ void stub_GetStatus();
+ [SecurityCritical]
+ void GetProperty(ref Guid guid, out ITfProperty property);
+ void stub_GetAppProperty();
+
+ void TrackProperties(
+ [In] ref Guid[] guids,
+ [In] uint propertyGuidLength,
+ [In] IntPtr prgAppProp,
+ [In] uint cAppProp,
+ [Out, MarshalAs(UnmanagedType.Interface)] out ITfReadOnlyProperty ppProperty
+ );
+
+ void EnumProperties([Out, MarshalAs(UnmanagedType.Interface)] out IEnumTfProperties ppEnum);
+ void stub_GetDocumentMgr();
+ void stub_CreateRangeBackup();
+ }
+
+
+//============================================================================
+
+
+ [ComImport, Guid("19188CB0-ACA9-11D2-AFC5-00105A2799B5"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ public interface IEnumTfProperties
+ {
+ void Clone([Out, MarshalAs(UnmanagedType.Interface)] out IEnumTfProperties ppEnum);
+
+ [PreserveSig, SecurityCritical]
+ int Next(
+ [In] uint i_count,
+ [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=2)] ITfProperty[] o_properties,
+ [Out] out int o_fetchedLength
+ );
+
+ void Reset();
+
+ void Skip([In] uint ulCount);
+ }
+
+
+//============================================================================
+
+
+ [ComImport,
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
+ SecurityCritical,
+ Guid("aa80e7ff-2021-11d2-93e0-0060b067b86e")
+ ]
+ public interface ITfRange
+ {
+ [SecurityCritical]
+ void GetText(int ec, int flags, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=3)] char[] text, int countMax, out int count);
+ [SecurityCritical]
+ void SetText(int ec, int flags, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=3)] char[] text, int count);
+ [SecurityCritical]
+ void GetFormattedText(int ec, [MarshalAs(UnmanagedType.Interface)] out object data);
+ [SecurityCritical]
+ void GetEmbedded(int ec, ref Guid guidService, ref Guid iid, [MarshalAs(UnmanagedType.Interface)] out object obj);
+ [SecurityCritical]
+ void InsertEmbedded(int ec, int flags, [MarshalAs(UnmanagedType.Interface)] object data);
+ [SecurityCritical]
+ void ShiftStart(int ec, int count, out int result, int ZeroForNow);
+ [SecurityCritical]
+ void ShiftEnd(int ec, int count, out int result, int ZeroForNow);
+ [SecurityCritical]
+ void ShiftStartToRange(int ec, ITfRange range, TfAnchor position);
+ [SecurityCritical]
+ void ShiftEndToRange(int ec, ITfRange range, TfAnchor position);
+ [SecurityCritical]
+ void ShiftStartRegion(int ec, TfShiftDir dir, [MarshalAs(UnmanagedType.Bool)] out bool noRegion);
+ [SecurityCritical]
+ void ShiftEndRegion(int ec, TfShiftDir dir, [MarshalAs(UnmanagedType.Bool)] out bool noRegion);
+ [SecurityCritical]
+ void IsEmpty(int ec, [MarshalAs(UnmanagedType.Bool)] out bool empty);
+ [SecurityCritical]
+ void Collapse(int ec, TfAnchor position);
+ [SecurityCritical]
+ void IsEqualStart(int ec, ITfRange with, TfAnchor position, [MarshalAs(UnmanagedType.Bool)] out bool equal);
+ [SecurityCritical]
+ void IsEqualEnd(int ec, ITfRange with, TfAnchor position, [MarshalAs(UnmanagedType.Bool)] out bool equal);
+ [SecurityCritical]
+ void CompareStart(int ec, ITfRange with, TfAnchor position, out int result);
+ [SecurityCritical]
+ void CompareEnd(int ec, ITfRange with, TfAnchor position, out int result);
+ [SecurityCritical]
+ void AdjustForInsert(int ec, int count, [MarshalAs(UnmanagedType.Bool)] out bool insertOk);
+ [SecurityCritical]
+ void GetGravity(out TfGravity start, out TfGravity end);
+ [SecurityCritical]
+ void SetGravity(int ec, TfGravity start, TfGravity end);
+ [SecurityCritical]
+ void Clone(out ITfRange clone);
+ [SecurityCritical]
+ void GetContext(out ITfContext context);
+ }
+
+
+//============================================================================
+
+
+ [ComImport,
+ SecurityCritical,
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
+ Guid("057a6296-029b-4154-b79a-0d461d4ea94c")
+ ]
+ public interface ITfRangeACP
+ {
+ [SecurityCritical]
+ void GetText(int ec, int flags, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=3)] char[] text, int countMax, out int count);
+ [SecurityCritical]
+ void SetText(int ec, int flags, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=3)] char[] text, int count);
+ [SecurityCritical]
+ void GetFormattedText(int ec, [MarshalAs(UnmanagedType.Interface)] out object data);
+ [SecurityCritical]
+ void GetEmbedded(int ec, ref Guid guidService, ref Guid iid, [MarshalAs(UnmanagedType.Interface)] out object obj);
+ [SecurityCritical]
+ void InsertEmbedded(int ec, int flags, [MarshalAs(UnmanagedType.Interface)] object data);
+ [SecurityCritical]
+ void ShiftStart(int ec, int count, out int result, int ZeroForNow);
+ [SecurityCritical]
+ void ShiftEnd(int ec, int count, out int result, int ZeroForNow);
+ [SecurityCritical]
+ void ShiftStartToRange(int ec, ITfRange range, TfAnchor position);
+ [SecurityCritical]
+ void ShiftEndToRange(int ec, ITfRange range, TfAnchor position);
+ [SecurityCritical]
+ void ShiftStartRegion(int ec, TfShiftDir dir, [MarshalAs(UnmanagedType.Bool)] out bool noRegion);
+ [SecurityCritical]
+ void ShiftEndRegion(int ec, TfShiftDir dir, [MarshalAs(UnmanagedType.Bool)] out bool noRegion);
+ [SecurityCritical]
+ void IsEmpty(int ec, [MarshalAs(UnmanagedType.Bool)] out bool empty);
+ [SecurityCritical]
+ void Collapse(int ec, TfAnchor position);
+ [SecurityCritical]
+ void IsEqualStart(int ec, ITfRange with, TfAnchor position, [MarshalAs(UnmanagedType.Bool)] out bool equal);
+ [SecurityCritical]
+ void IsEqualEnd(int ec, ITfRange with, TfAnchor position, [MarshalAs(UnmanagedType.Bool)] out bool equal);
+ [SecurityCritical]
+ void CompareStart(int ec, ITfRange with, TfAnchor position, out int result);
+ [SecurityCritical]
+ void CompareEnd(int ec, ITfRange with, TfAnchor position, out int result);
+ [SecurityCritical]
+ void AdjustForInsert(int ec, int count, [MarshalAs(UnmanagedType.Bool)] out bool insertOk);
+ [SecurityCritical]
+ void GetGravity(out TfGravity start, out TfGravity end);
+ [SecurityCritical]
+ void SetGravity(int ec, TfGravity start, TfGravity end);
+ [SecurityCritical]
+ void Clone(out ITfRange clone);
+ [SecurityCritical]
+ void GetContext(out ITfContext context);
+ [SecurityCritical]
+ void GetExtent(out int start, out int count);
+ [SecurityCritical]
+ void SetExtent(int start, int count);
+ }
+
+
+//============================================================================
+
+
+ [ComImport,
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
+ Guid("17D49A3D-F8B8-4B2F-B254-52319DD64C53"),
+ SecurityCritical,
+
+ ]
+ public interface ITfReadOnlyProperty
+ {
+ void GetType(
+ [Out] out Guid o_guid
+ );
+
+ void EnumRanges(
+ [In] int i_editCookie,
+ [Out, MarshalAs(UnmanagedType.Interface)] out IEnumTfRanges o_enumRanges,
+ [In, MarshalAs(UnmanagedType.Interface)] ITfRange i_targetRange
+ );
+
+ void GetValue(
+ [In] int i_editCookie,
+ [In, MarshalAs(UnmanagedType.Interface)] ITfRange i_range,
+ [In, Out, MarshalAs(UnmanagedType.Struct)] ref VARIANT o_varValue
+ );
+
+ void GetContext(
+ [Out, MarshalAs(UnmanagedType.Interface)] out ITfContext o_ppContext
+ );
+ }
+
+
+//============================================================================
+
+
+ //[ComImport,
+ // Guid("e2449660-9542-11d2-bf46-00105a2799b5"),
+ // InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
+ // SecurityCritical,
+ //
+ //]
+ //public interface ITfProperty : ITfReadOnlyProperty
+ //{
+ // void FindRange(int editCookie, ITfRange inRange, out ITfRange outRange, TfAnchor position);
+ // void stub_SetValueStore();
+ // void SetValue(int editCookie, ITfRange range, object value);
+ // void Clear(int editCookie, ITfRange range);
+ //}
+
+
+ [ComImport, Guid("e2449660-9542-11d2-bf46-00105a2799b5"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), SecurityCritical]
+ public interface ITfProperty
+ {
+ void GetType(out Guid type);
+ [PreserveSig]
+ int EnumRanges(int editcookie, out IEnumTfRanges ranges, ITfRange targetRange);
+ void GetValue(int editCookie, ITfRange range, ref VARIANT value);
+ void GetContext(out ITfContext context);
+ void FindRange(int editCookie, ITfRange inRange, out ITfRange outRange, TfAnchor position);
+ void stub_SetValueStore();
+ void SetValue(int editCookie, ITfRange range, object value);
+ void Clear(int editCookie, ITfRange range);
+ }
+
+
+//============================================================================
+
+
+ [StructLayout(LayoutKind.Sequential, Pack = 8), Guid("D678C645-EB6A-45C9-B4EE-0F3E3A991348")]
+ public struct TF_PROPERTYVAL
+ {
+ public Guid guidId;
+ [MarshalAs(UnmanagedType.Struct)]
+ public VARIANT varValue;
+ }
+
+
+//============================================================================
+
+
+ [ComImport, Guid("8ED8981B-7C10-4D7D-9FB3-AB72E9C75F72"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ public interface IEnumTfPropertyValue
+ {
+ void Clone([Out, MarshalAs(UnmanagedType.Interface)] out IEnumTfPropertyValue ppEnum);
+ [PreserveSig, SecurityCritical]
+ int Next([In] uint ulCount, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=2)] TF_PROPERTYVAL[] values, [Out] out int fetched);
+ void Reset();
+ void Skip([In] uint ulCount);
+ }
+
+
+//============================================================================
+
+
+ [ComImport,
+ Guid("f99d3f40-8e32-11d2-bf46-00105a2799b5"),
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
+ SecurityCritical
+ ]
+ public interface IEnumTfRanges
+ {
+ [SecurityCritical]
+ void Clone(out IEnumTfRanges ranges);
+ [PreserveSig, SecurityCritical]
+ int Next(int count, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=2)] ITfRange[] ranges, out int fetched);
+ [SecurityCritical]
+ void Reset();
+ [PreserveSig, SecurityCritical]
+ int Skip(int count);
+ }
+
+
+//============================================================================
+
+
+ [ComImport,
+ Guid("a3ad50fb-9bdb-49e3-a843-6c76520fbf5d"),
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown)
+ ]
+ public interface ITfCandidateList
+ {
+ void EnumCandidates(out object enumCand);
+ [SecurityCritical]
+ void GetCandidate(int nIndex, out ITfCandidateString candstring);
+ [SecurityCritical]
+ void GetCandidateNum(out int nCount);
+ [SecurityCritical]
+ void SetResult(int nIndex, TfCandidateResult result);
+ }
+
+
+//============================================================================
+
+
+ [ComImport,
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
+ Guid("581f317e-fd9d-443f-b972-ed00467c5d40")
+ ]
+ public interface ITfCandidateString
+ {
+ [SecurityCritical]
+ void GetString([MarshalAs(UnmanagedType.BStr)] out string funcName);
+ void GetIndex(out int nIndex);
+ }
+
+
+//============================================================================
+
+
+ [ComImport,
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
+ Guid("4cea93c0-0a58-11d3-8df0-00105a2799b5")
+ ]
+ public interface ITfFnReconversion
+ {
+ void GetDisplayName([MarshalAs(UnmanagedType.BStr)] out string funcName);
+ [PreserveSig, SecurityCritical, ]
+ int QueryRange(ITfRange range, out ITfRange newRange, [MarshalAs(UnmanagedType.Bool)] out bool isConvertable);
+ [PreserveSig, SecurityCritical, ]
+ int GetReconversion(ITfRange range, out ITfCandidateList candList);
+ [PreserveSig, SecurityCritical]
+ int Reconvert(ITfRange range);
+ }
+
+
+//============================================================================
+
+
+ [ComImport,
+ SecurityCritical,
+ Guid("D7540241-F9A1-4364-BEFC-DBCD2C4395B7"),
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown)
+ ]
+ public interface ITfCompositionView
+ {
+ [SecurityCritical]
+ void GetOwnerClsid(out Guid clsid);
+ [SecurityCritical]
+ void GetRange(out ITfRange range);
+ }
+
+
+//============================================================================
+
+#if !METRO
+ /// <summary>
+ /// テキストフレームワークの関数。
+ /// </summary>
+ public static class TextFrameworkFunctions
+ {
+ /// <summary>
+ /// スレッドマネージャーの生成。
+ /// </summary>
+ /// <param name="o_threadManager">スレッドマネージャーの受け取り先。</param>
+ [DllImport("msctf.dll")]
+ public static extern void TF_CreateThreadMgr(
+ [Out, MarshalAs(UnmanagedType.Interface)] out ITfThreadMgr o_threadManager
+ );
+
+ /// <summary>
+ /// スレッドマネージャーが既に生成されている場合、そのポインタを取得する。
+ /// </summary>
+ /// <param name="o_threadManager">スレッドマネージャーの受け取り先。</param>
+ [DllImport("msctf.dll")]
+ public static extern void TF_GetThreadMgr(
+ [Out, MarshalAs(UnmanagedType.Interface)] out ITfThreadMgr o_threadManager
+ );
+ }
+#endif
+
+//============================================================================
+
+
+ /// <summary>
+ /// テキストフレームワークで宣言されている定数等。
+ /// </summary>
+ public static class TfDeclarations
+ {
+ public static readonly Guid CLSID_TF_ThreadMgr = new Guid("529a9e6b-6587-4f23-ab9e-9c7d683e3c50");
+ public static readonly Guid GUID_SYSTEM_FUNCTIONPROVIDER = new Guid("9a698bb0-0f21-11d3-8df1-00105a2799b5");
+ public static readonly Guid CLSID_TF_DisplayAttributeMgr = new Guid("3ce74de4-53d3-4d74-8b83-431b3828ba53");
+ public static readonly Guid CLSID_TF_CategoryMgr = new Guid("a4b544a1-438d-4b41-9325-869523e2d6c7");
+ public static readonly Guid GUID_PROP_ATTRIBUTE = new Guid("34b45670-7526-11d2-a147-00105a2799b5");
+ public static readonly Guid GUID_PROP_MODEBIAS = new Guid("372e0716-974f-40ac-a088-08cdc92ebfbc");
+ public static readonly Guid GUID_MODEBIAS_NONE = Guid.Empty;
+ }
+
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct VARIANT
+ {
+ [MarshalAs(UnmanagedType.I2)]
+ public short vt;
+ [MarshalAs(UnmanagedType.I2)]
+ public short reserved1;
+ [MarshalAs(UnmanagedType.I2)]
+ public short reserved2;
+ [MarshalAs(UnmanagedType.I2)]
+ public short reserved3;
+ public IntPtr data1;
+ public IntPtr data2;
+ }
+
+}
-using System;\r
-using System.Reflection;\r
-using System.Runtime.InteropServices;\r
-using System.Runtime.InteropServices.ComTypes;\r
-using System.Security;\r
-using DotNetTextStore.UnmanagedAPI.WinDef;\r
-\r
-\r
-namespace DotNetTextStore.UnmanagedAPI.TSF.TextStore\r
-{\r
- /// <summary>\r
- /// ITextStoreACP::RequestLock() で使用されるロックのフラグ。\r
- /// </summary>\r
- public enum LockFlags\r
- {\r
- /// <summary>\r
- /// 読み取り専用。\r
- /// </summary>\r
- TS_LF_READ = 2,\r
- /// <summary>\r
- /// 読み書き両用。\r
- /// </summary>\r
- TS_LF_READWRITE = 6,\r
- /// <summary>\r
- /// 同期ロック。その他のフラグと組み合わせて使用する。\r
- /// </summary>\r
- TS_LF_SYNC = 1,\r
- /// <summary>\r
- /// 書き込み用。\r
- /// </summary>\r
- TS_LF_WRITE = 4\r
- }\r
-\r
-\r
- /// <summary>\r
- /// TS_STATUS 構造体の dynamicFlags メンバで使用されるフラグ\r
- /// </summary>\r
- public enum DynamicStatusFlags\r
- {\r
- /// <summary>\r
- /// ドキュメントはロード中の状態。\r
- /// </summary>\r
- TS_SD_LOADING = 2,\r
- /// <summary>\r
- /// ドキュメントは読み取り専用。\r
- /// </summary>\r
- TS_SD_READONLY = 1\r
- }\r
-\r
-\r
- /// <summary>\r
- /// TS_STATUS 構造体の staticFlags メンバで使用するフラグ。\r
- /// </summary>\r
- public enum StaticStatusFlags\r
- {\r
- /// <summary>\r
- /// ドキュメントは複数選択をサポートしている。\r
- /// </summary>\r
- TS_SS_DISJOINTSEL = 1,\r
- /// <summary>\r
- /// 隠しテキストを含めることはない。\r
- /// </summary>\r
- TS_SS_NOHIDDENTEXT = 8,\r
- /// <summary>\r
- /// ドキュメントは複数のリージョンを含められる。\r
- /// </summary>\r
- TS_SS_REGIONS = 2,\r
- /// <summary>\r
- /// ドキュメントは短い使用サイクルを持つ。\r
- /// </summary>\r
- TS_SS_TRANSITORY = 4,\r
- /// <summary>\r
- /// ドキュメントはタッチキーボードによるオートコレクションをサポートしている\r
- /// </summary>\r
- TS_SS_TKBAUTOCORRECTENABLE = 0x10,\r
- /// <summary>\r
- /// ドキュメントはタッチキーボードによる予測入力に対応している\r
- /// </summary>\r
- TS_SS_TKBPREDICTIONENABLE = 0x20\r
- }\r
-\r
-\r
- /// <summary>\r
- /// ドキュメントのステータスを示す構造体。ITextStoreACP::GetStatus() で使用される。\r
- /// </summary>\r
- [StructLayout(LayoutKind.Sequential, Pack=4),\r
- Guid("BC7D979A-846A-444D-AFEF-0A9BFA82B961")\r
- ]\r
- public struct TS_STATUS\r
- {\r
- /// <summary>\r
- /// 実行時に変更できる状態フラグ。\r
- /// </summary>\r
- public DynamicStatusFlags dynamicFlags;\r
- /// <summary>\r
- /// 実行時に変更できない一貫性をもつフラグ。\r
- /// </summary>\r
- public StaticStatusFlags staticFlags;\r
- }\r
-\r
-\r
- /// <summary>\r
- /// ITextStoreACP::SetText() で使用されるフラグ。\r
- /// </summary>\r
- [Flags]\r
- public enum SetTextFlags\r
- {\r
- /// <summary>\r
- /// 既存のコンテントの移動(訂正)であり、特別なテキストマークアップ情報\r
- /// (メタデータ: .wav ファイルデータや言語IDなど)が保持される。クライア\r
- /// ントは保持されるマークアップ情報のタイプを定義する。\r
- /// </summary>\r
- TS_ST_CORRECTION = 1\r
- }\r
-\r
-\r
- /// <summary>\r
- /// ITextStoreACP::AdviseSink() メソッドに渡されるフラグ。要求する変更通知\r
- /// を組み合わせて使用する。\r
- /// </summary>\r
- public enum AdviseFlags\r
- {\r
- /// <summary>\r
- /// ドキュメントの属性が変更された。\r
- /// </summary>\r
- TS_AS_ATTR_CHANGE = 8,\r
- /// <summary>\r
- /// ドキュメントのレイアウトが変更された。\r
- /// </summary>\r
- TS_AS_LAYOUT_CHANGE = 4,\r
- /// <summary>\r
- /// テキストはドキュメント内で選択された。\r
- /// </summary>\r
- TS_AS_SEL_CHANGE = 2,\r
- /// <summary>\r
- /// ドキュメントのステータスが変更された。\r
- /// </summary>\r
- TS_AS_STATUS_CHANGE = 0x10,\r
- /// <summary>\r
- /// テキストはドキュメント内で変更された。\r
- /// </summary>\r
- TS_AS_TEXT_CHANGE = 1\r
- }\r
-\r
-\r
- /// <summary>\r
- /// 選択範囲を示す構造体。\r
- /// </summary>\r
- [StructLayout(LayoutKind.Sequential, Pack=4),\r
- Guid("C4B9C33B-8A0D-4426-BEBE-D444A4701FE9")\r
- ]\r
- public struct TS_SELECTION_ACP\r
- {\r
- /// <summary>\r
- /// 開始文字位置。\r
- /// </summary>\r
- public int start;\r
- /// <summary>\r
- /// 終了文字位置。\r
- /// </summary>\r
- public int end;\r
- /// <summary>\r
- /// スタイル。選択範囲の開始位置が終了位置なのか開始位置なのか示すフラ\r
- /// グの ase と仮決定を示す真偽値 interimChar を持つ。\r
- /// </summary>\r
- public TS_SELECTIONSTYLE style;\r
- }\r
-\r
-\r
- /// <summary>\r
- /// TS_SELECTION_ACP のメンバとして使用される構造体。\r
- /// </summary>\r
- [StructLayout(LayoutKind.Sequential, Pack=4),\r
- Guid("7ECC3FFA-8F73-4D91-98ED-76F8AC5B1600")\r
- ]\r
- public struct TS_SELECTIONSTYLE\r
- {\r
- /// <summary>\r
- /// 選択範囲の開始位置が終了位置なのか開始位置なのか示す\r
- /// </summary>\r
- public TsActiveSelEnd ase;\r
- /// <summary>\r
- /// 用途不明。説明を見ると変換中の文字のことのようだが変換中の文字に対\r
- /// しても true が渡されたことは無い・・・\r
- /// </summary>\r
- [MarshalAs(UnmanagedType.Bool)]\r
- public bool interimChar;\r
- }\r
-\r
-\r
- /// <summary>\r
- /// 選択範囲の終了位置を示すフラグ。\r
- /// </summary>\r
- public enum TsActiveSelEnd\r
- {\r
- /// <summary>\r
- /// アクティブな選択は無い。\r
- /// </summary>\r
- TS_AE_NONE,\r
- /// <summary>\r
- /// 開始位置が選択範囲の終了位置である。\r
- /// </summary>\r
- TS_AE_START,\r
- /// <summary>\r
- /// 終了位置と選択範囲の終了位置は同じである。\r
- /// </summary>\r
- TS_AE_END\r
- }\r
-\r
-\r
- /// <summary>\r
- /// ITextStoreACP.FindNextAttrTransition() などで使用されるフラグ。\r
- /// </summary>\r
- [Flags]\r
- public enum AttributeFlags\r
- {\r
- /// <summary>\r
- /// バックワード検索。\r
- /// </summary>\r
- TS_ATTR_FIND_BACKWARDS = 1,\r
- /// <summary>\r
- /// 不明。資料なし。\r
- /// </summary>\r
- TS_ATTR_FIND_HIDDEN = 0x20,\r
- /// <summary>\r
- /// 不明。資料なし。\r
- /// </summary>\r
- TS_ATTR_FIND_UPDATESTART = 4,\r
- /// <summary>\r
- /// 不明。資料なし。\r
- /// </summary>\r
- TS_ATTR_FIND_WANT_END = 0x10,\r
- /// <summary>\r
- /// o_foundOffset パラメータは i_start からの属性変更のオフセットを受け取る。\r
- /// </summary>\r
- TS_ATTR_FIND_WANT_OFFSET = 2,\r
- /// <summary>\r
- /// 不明。資料なし。\r
- /// </summary>\r
- TS_ATTR_FIND_WANT_VALUE = 8\r
- }\r
-\r
-\r
- /// <summary>\r
- /// ITextStoreACP::InsertEmbedded() で使用されるフラグ\r
- /// </summary>\r
- [Flags]\r
- public enum InsertEmbeddedFlags\r
- {\r
- /// <summary>\r
- /// 既存のコンテントの移動(訂正)であり、特別なテキストマークアップ情報\r
- /// (メタデータ: .wav ファイルデータや言語IDなど)が保持される。クライア\r
- /// ントは保持されるマークアップ情報のタイプを定義する。\r
- /// </summary>\r
- TS_IE_CORRECTION = 1\r
- }\r
-\r
-\r
- /// <summary>\r
- /// ITextStoreACP::InsertTextAtSelection(),\r
- /// ITextStoreACP::InsertEmbeddedAtSelection() で使用されるフラグ。\r
- /// </summary>\r
- [Flags]\r
- public enum InsertAtSelectionFlags\r
- {\r
- /// <summary>\r
- /// テキストは挿入され、挿入後の開始位置・終了位置を受け取るパラメータ\r
- /// の値は NULL にでき、TS_TEXTCHANGE 構造体は埋められなければいけない。\r
- /// このフラグはテキスト挿入の結果を見るために使用する。\r
- /// </summary>\r
- TF_IAS_NOQUERY = 1,\r
- /// <summary>\r
- /// テキストは実際には挿入されず、挿入後の開始位置・終了位置を受け取る\r
- /// パラメータはテキスト挿入の結果を含む。これらのパラメータの値は、\r
- /// アプリケーションがどのようにドキュメントにテキストを挿入するかに依\r
- /// 存している。このフラグは実際にはテキストを挿入しないでテキスト挿入\r
- /// の結果を見るために使用する。このフラグを使う場合はTS_TEXTCHANGE \r
- /// 構造体を埋める必要はない。\r
- /// </summary>\r
- TF_IAS_QUERYONLY = 2\r
- }\r
-\r
-\r
- /// <summary>\r
- /// ランタイプ\r
- /// </summary>\r
- public enum TsRunType\r
- {\r
- /// <summary>\r
- /// プレーンテキスト。\r
- /// </summary>\r
- TS_RT_PLAIN,\r
- /// <summary>\r
- /// 不可視。\r
- /// </summary>\r
- TS_RT_HIDDEN,\r
- /// <summary>\r
- /// アプリケーションや ITextStore インターフェイスを実装するテキスト\r
- /// サービスによるテキスト内の組み込まれたプライベートデータタイプ。\r
- /// </summary>\r
- TS_RT_OPAQUE\r
- }\r
-\r
-\r
- /// <summary>\r
- /// ラン情報を示す構造体。\r
- /// </summary>\r
- [StructLayout(LayoutKind.Sequential, Pack=4),\r
- Guid("A6231949-37C5-4B74-A24E-2A26C327201D")\r
- ]\r
- public struct TS_RUNINFO\r
- {\r
- /// <summary>\r
- /// テキストラン内の文字数。\r
- /// </summary>\r
- public int length;\r
- /// <summary>\r
- /// テキストランのタイプ。\r
- /// </summary>\r
- public TsRunType type;\r
- }\r
-\r
-\r
- /// <summary>\r
- /// 変更前および変更後の開始位置・終了位置を示す構造体。\r
- /// </summary>\r
- [StructLayout(LayoutKind.Sequential, Pack=4),\r
- Guid("F3181BD6-BCF0-41D3-A81C-474B17EC38FB")\r
- ]\r
- public struct TS_TEXTCHANGE\r
- {\r
- /// <summary>\r
- /// テキストがドキュメントに挿入される前の開始位置。\r
- /// </summary>\r
- public int start;\r
- /// <summary>\r
- /// テキストがドキュメントに挿入される前の終了位置。値は挿入位置である\r
- /// start と同じ値となる。もし、start と異なっている場合は、テキストは\r
- /// テキストの挿入の前に選択されていた。\r
- /// </summary>\r
- public int oldEnd;\r
- /// <summary>\r
- /// テキストを挿入した後の終了位置。\r
- /// </summary>\r
- public int newEnd;\r
- }\r
-\r
-\r
- [StructLayout(LayoutKind.Sequential, Pack=8),\r
- Guid("2CC2B33F-1174-4507-B8D9-5BC0EB37C197")\r
- ]\r
- public struct TS_ATTRVAL\r
- {\r
- public Guid attributeId;\r
- public int overlappedId;\r
- public int reserved;\r
- public VARIANT val;\r
- }\r
-\r
-\r
- /// <summary>\r
- /// ITextStoreACP::GetACPFromPoint() で使用されるフラグ。\r
- /// \r
- /// <para>詳しくは http://msdn.microsoft.com/en-us/library/ms538418(v=VS.85).aspx の Remarks 参照。</para>\r
- /// </summary>\r
- [Flags]\r
- public enum GetPositionFromPointFlags\r
- {\r
- /// <summary>\r
- /// もし、スクリーン座標での点が文字バウンディングボックスに含まれてい\r
- /// ないなら、もっとも近い文字位置が返される。\r
- /// </summary>\r
- GXFPF_NEAREST = 2,\r
- /// <summary>\r
- /// もし、スクリーン座標での点が文字バウンディングボックスの中に含まれ\r
- /// ている場合、返される文字位置は ptScreen にもっとも近いバウンディン\r
- /// グの端を持つ文字の位置である。\r
- /// </summary>\r
- GXFPF_ROUND_NEAREST = 1\r
- }\r
-\r
-\r
- /// <summary>\r
- /// ITextStoreACPSink::OnTextChange() で使用されるフラグ。\r
- /// </summary>\r
- [Flags]\r
- public enum OnTextChangeFlags\r
- {\r
- NONE = 0,\r
- TS_TC_CORRECTION = 1\r
- }\r
-\r
-\r
- /// <summary>\r
- /// ITextStoreACPSink::OnLayoutChange() で使用されるフラグ。\r
- /// </summary>\r
- public enum TsLayoutCode\r
- {\r
- /// <summary>\r
- /// ビューが生成された。\r
- /// </summary>\r
- TS_LC_CREATE,\r
- /// <summary>\r
- /// レイアウトが変更された。\r
- /// </summary>\r
- TS_LC_CHANGE,\r
- /// <summary>\r
- /// レイアウトが破棄された。\r
- /// </summary>\r
- TS_LC_DESTROY\r
- }\r
-\r
-\r
- /// <summary>\r
- /// GetSelection() の i_index 引数に使用する定数。\r
- /// </summary>\r
- public enum GetSelectionIndex : int\r
- {\r
- /// <summary>\r
- /// デフォルト選択を意味する。\r
- /// </summary>\r
- TS_DEFAULT_SELECTION = -1\r
- }\r
-\r
-\r
-//============================================================================\r
-\r
-\r
- /// <summary>\r
- /// テキストストアのメソッドの戻り値(C# では COMException のエラーコード)\r
- /// </summary>\r
- public static class TsResult\r
- {\r
- /// <summary>\r
- /// Application does not support the data type contained in the IDataObject object to be inserted using ITextStoreACP::InsertEmbedded. \r
- /// </summary>\r
- public const int TS_E_FORMAT = unchecked((int)0x8004020a);\r
- /// <summary>\r
- /// Parameter is not within the bounding box of any character.\r
- /// </summary>\r
- public const int TS_E_INVALIDPOINT = unchecked((int)0x80040207);\r
- /// <summary>\r
- /// Range specified extends outside the document.\r
- /// </summary>\r
- public const int TS_E_INVALIDPOS = unchecked((int)0x80040200);\r
- /// <summary>\r
- /// Object does not support the requested interface.\r
- /// </summary>\r
- public const int TS_E_NOINTERFACE = unchecked((int)0x80040204);\r
- /// <summary>\r
- /// Application has not calculated a text layout.\r
- /// </summary>\r
- public const int TS_E_NOLAYOUT = unchecked((int)0x80040206);\r
- /// <summary>\r
- /// Application does not have a read-only lock or read/write lock for the document.\r
- /// </summary>\r
- public const int TS_E_NOLOCK = unchecked((int)0x80040201);\r
- /// <summary>\r
- /// Embedded content offset is not positioned before a TF_CHAR_EMBEDDED character.\r
- /// </summary>\r
- public const int TS_E_NOOBJECT = unchecked((int)0x80040202);\r
- /// <summary>\r
- /// Document has no selection.\r
- /// </summary>\r
- public const int TS_E_NOSELECTION = unchecked((int)0x80040205);\r
- /// <summary>\r
- /// Content cannot be returned to match the service GUID.\r
- /// </summary>\r
- public const int TS_E_NOSERVICE = unchecked((int)0x80040203);\r
- /// <summary>\r
- /// Document is read-only. Cannot modify content.\r
- /// </summary>\r
- public const int TS_E_READONLY = unchecked((int)0x80040209);\r
- /// <summary>\r
- /// Document cannot be locked synchronously.\r
- /// </summary>\r
- /// <remarks>\r
- /// CAUTION: this value is marked as 0x00040300 in the document.\r
- /// </remarks>\r
- public const int TS_E_SYNCHRONOUS = unchecked((int)0x00040208);\r
- /// <summary>\r
- /// Document successfully received an asynchronous lock.\r
- /// </summary>\r
- public const int TS_S_ASYNC = 0x01;\r
- /// <summary>\r
- /// COMCTL.h より。SINK をこれ以上登録できない。\r
- /// </summary>\r
- public const int CONNECT_E_ADVISELIMIT = -2147220991;\r
- /// <summary>\r
- /// COMCTL.h より。SINK は登録されていない。\r
- /// </summary>\r
- public const int CONNECT_E_NOCONNECTION = -2147220992;\r
- }\r
-\r
-\r
- //============================================================================\r
-\r
-\r
-#if !METRO\r
- /// <summary>\r
- /// テキストストア\r
- /// </summary>\r
- [ComImport,\r
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown),\r
- Guid("28888fe3-c2a0-483a-a3ea-8cb1ce51ff3d")\r
- ]\r
- public interface ITextStoreACP\r
- {\r
- /// <summary>\r
- /// TSF マネージャのシンクインターフェイスを識別する。\r
- /// <para>\r
- /// ITextStoreACP::AdviseSink() メソッドは ITextStoreACPSink インターフェイス\r
- /// から新しいアドバイズシンクをインストール、または既存のアドバイズシンクの\r
- /// 修正を行う。シンクインターフェイスは io_unknown_cp パラメータによって指定\r
- /// される。\r
- /// </para>\r
- /// </summary>\r
- ///\r
- /// <param name="i_riid">\r
- /// シンクインターフェイスを指定する。\r
- /// </param>\r
- ///\r
- /// <param name="i_unknown">\r
- /// シンクインターフェイスへのポインタ。NULL 不可。\r
- /// </param>\r
- ///\r
- /// <param name="i_mask">\r
- /// アドバイズシンクを通知するイベントを指定する。\r
- /// <list type="table">\r
- /// <listheader>\r
- /// <term>フラグ(値)</term>\r
- /// <description>コメント</description>\r
- /// </listheader>\r
- /// <item>\r
- /// <term>TS_AS_TEXT_CHANGE(0x1)</term>\r
- /// <description>テキストはドキュメント内で変更された。</description>\r
- /// </item>\r
- /// <item>\r
- /// <term>TS_AS_SEL_CHANGE(0x2)</term>\r
- /// <description>テキストはドキュメント内で選択された。</description>\r
- /// </item>\r
- /// <item>\r
- /// <term>TS_AS_LAYOUT_CHANGE(0x04)</term>\r
- /// <description>ドキュメントのレイアウトが変更された。</description>\r
- /// </item>\r
- /// <item>\r
- /// <term>TS_AS_ATTR_CHANGE(0x08)</term>\r
- /// <description>ドキュメントの属性が変更された。</description>\r
- /// </item>\r
- /// <item>\r
- /// <term>TS_AS_STATUS_CHANGE(0x10)</term>\r
- /// <description>ドキュメントのステータスが変更された。</description>\r
- /// </item>\r
- /// <item>\r
- /// <term>TS_AS_ALL_SINKS</term>\r
- /// <description>上記全て</description>\r
- /// </item>\r
- /// </list>\r
- /// </param>\r
- void AdviseSink(\r
- [In] ref Guid i_riid,\r
- [In, MarshalAs(UnmanagedType.Interface)] object i_unknown,\r
- [In] AdviseFlags i_mask\r
- );\r
-\r
-\r
- //====================================================================\r
-\r
-\r
- /// <summary>\r
- /// アプリケーションはもはやTSFマネージャから通知を必要としないことを示す\r
- /// ためにアプリケーションによって呼ばれる。TSFマネージャはシンクインター\r
- /// フェイスの解放と通知の停止を行う。\r
- /// </summary>\r
- ///\r
- /// <param name="i_unknown">\r
- /// シンクオブジェクトへのポインタ。NULL 不可。\r
- /// </param>\r
- ///\r
- /// <remark>\r
- /// 新しいシンクオブジェクトを登録する ITextStoreACP::AdviseSink メソッド\r
- /// の全ての呼び出しは、このメソッドの呼び出しと対応していなければならない。\r
- /// 以前に登録されたシンクの dwMask パラメータを更新するだけの\r
- /// ITextStoreACP::AdviseSink() メソッドの呼び出しは\r
- /// ITextStoreACP::UnadviseSink() メソッドの呼び出しを必要としない。\r
- ///\r
- /// <para>\r
- /// io_unknown_cp パラメータは ITextStoreACP::AdviseSink メソッドに渡さ\r
- /// れたオリジナルのポインタとして同じ COM 識別子でなければいけない。\r
- /// </para>\r
- /// </remark>\r
- ///\r
- /// <returns>\r
- /// <list type="table">\r
- /// <listheader>\r
- /// <term>戻り値</term>\r
- /// <description>意味</description>\r
- /// </listheader>\r
- /// <item>\r
- /// <term>S_OK</term>\r
- /// <description>メソッドは成功した。</description>\r
- /// </item>\r
- /// <item>\r
- /// <term>CONNECT_E_NOCONNECTION</term>\r
- /// <description>\r
- /// アクティブなシンクオブジェクトは存在しない。\r
- /// </description>\r
- /// </item>\r
- /// </list>\r
- /// </returns>\r
- void UnadviseSink(\r
- [In, MarshalAs(UnmanagedType.Interface)] object i_unknown\r
- );\r
-\r
-\r
- //====================================================================\r
-\r
-\r
- /// <summary>\r
- /// TSFマネージャがドキュメントを修正するためにドキュメントロックを提供す\r
- /// るためにTSFマネージャによって呼び出される。このメソッドはドキュメント\r
- /// ロックを作成するために ITextStoreACPSink::OnLockGranted() メソッドを呼\r
- /// び出さなければいけない。\r
- /// </summary>\r
- ///\r
- /// <param name="i_lockFlags">ロック要求のタイプを指定する。\r
- /// <list type="table">\r
- /// <listheader>\r
- /// <term>フラグ</term>\r
- /// <description>意味</description>\r
- /// </listheader>\r
- /// <item>\r
- /// <term>TS_LF_READ</term>\r
- /// <description>\r
- /// ドキュメントは読取専用ロックで、修正はできない。\r
- /// </description>\r
- /// </item>\r
- /// <item>\r
- /// <term>TS_LF_READWRITE</term>\r
- /// <description>\r
- /// ドキュメントは読み書き両用で、修正できる。\r
- /// </description>\r
- /// </item>\r
- /// <item>\r
- /// <term>TS_LF_SYNC</term>\r
- /// <description>\r
- /// 他のフラグと一緒に指定された場合は、ドキュメントは同期ロックである。\r
- /// </description>\r
- /// </item>\r
- /// </list>\r
- /// </param>\r
- ///\r
- /// <param name="o_sessionResult">\r
- /// ロックリクエストが同期ならば、ロック要求の結果である\r
- /// ITextStoreACP::OnLockGranted() メソッドからの HRESULT を受け取る。\r
- ///\r
- /// <para>\r
- /// ロック要求が非同期で結果が TS_S_ASYNC の場合、ドキュメントは非同期ロッ\r
- /// クを受け取る。ロック要求が非同期で結果が TS_E_SYNCHRONOUS の場合は、ド\r
- /// キュメントは非同期でロックできない。\r
- /// </para>\r
- /// </param>\r
- ///\r
- /// <remark>\r
- /// このメソッドはドキュメントをロックするために\r
- /// ITextStoreACPSink::OnLockGranted() メソッドを使用する。アプリケーショ\r
- /// ンは ITextStoreACP::RequestLock() メソッド内でドキュメントを修正したり\r
- /// ITextStoreACPSink::OnTextChange() メソッドを使用して変更通知を送ったり\r
- /// してはいけない。もし、アプリケーションがレポートするための変更をペンディ\r
- /// ングしているなら、アプリケーションは非同期ロック要求のみを返さなければ\r
- /// いけない。\r
- ///\r
- /// <para>\r
- /// アプリケーションは複数の RequestLock() メソッド呼び出しをキューに入\r
- /// れることを試みてはいけない、なぜなら、アプリケーションは一つのコール\r
- /// バックのみを要求されるから。もし、呼び出し元がいくつかの読取要求や一\r
- /// つ以上の書き込み要求を作ったとしても、コールバックは書き込みアクセス\r
- /// でなければいけない。\r
- /// </para>\r
- ///\r
- /// <para>\r
- /// 成功は、非同期ロックの要求にとって代わって同期ロックを要求する。失敗は\r
- /// (複数の)非同期ロックの要求を同期ロックに代えることができない。実装は、\r
- /// 要求が存在すれば発行済みの非同期要求をまだ満たしていなければいけない。\r
- /// </para>\r
- ///\r
- /// <para>\r
- /// もしロックが ITextStoreACP::RequestLock() メソッドが返る前に認められ\r
- /// たなら、o_sessionResult パラメータは\r
- /// ITextStoreACPSink::OnLockGranted() メソッドから返された HRESULT を受\r
- /// け取る。もし、呼び出しが成功したが、ロックは後で認められるなら、\r
- /// o_sessionResult パラメータは TS_S_ASYNC フラグを受け取る。もし、\r
- /// RequestLock() が S_OK 以外を返した場合は o_sessionResult パラメー\r
- /// ターは無視すべきである。\r
- /// </para>\r
- ///\r
- /// <para>\r
- /// ドキュメントが既にロックされている状態で、同期ロック要求の場合は\r
- /// o_sessionResult に TS_E_SYNCHRONOUS をセットして S_OK を返す。\r
- /// これは同期要求は認められなかったことを示す。\r
- /// ドキュメントが既にロックされている状態で、非同期ロック要求の場合は、\r
- /// アプリケーションはリクエストをキューに追加し、 o_sessionResult に\r
- /// TS_S_ASYNC をセットし、S_OK を返す。ドキュメントが有効になったとき、\r
- /// アプリケーションはリクエストをキューから削除して、 OnLockGranted() \r
- /// を呼び出す。このロックリクエストのキューは任意である。アプリケーション\r
- /// がサポートしなければいけないシナリオが一つある。ドキュメントが読み取\r
- /// り専用ロックで、アプリケーションが OnLockGranted の内部で新しい読み\r
- /// 書き両用の非同期ロック要求を出した場合、RequestLock は再帰呼び出しを\r
- /// 引き起こす。アプリケーションは OnLockGranted() を TS_LF_READWRITE と\r
- /// 共に呼び出してリクエストをアップグレードすべきである。\r
- /// </para>\r
- ///\r
- /// <para>\r
- /// 呼び出し元が読み取り専用ロックを維持している場合を除いて、呼び出し元\r
- /// はこのメソッドを再帰的に呼び出してはいけない。この場合、メソッドは非\r
- /// 同期に書き込み要求を尋ねるために再帰的に呼び出すことができる。書き込\r
- /// みロックは読取専用ロックが終わった後に認められるだろう。\r
- /// </para>\r
- ///\r
- /// <para>\r
- /// ロックの強要:アプリケーションは適切なロックのタイプが存在するかどうか\r
- /// ドキュメントへのアクセスを許す前に確かめなければいけない。例えば、\r
- /// GetText() を処理することを許可する前に少なくとも読み取り専用ロックが\r
- /// 行われているかどうか確かめなければいけない。もし、適切なロックがされ\r
- /// ていなければ、アプリケーションは TF_E_NOLOCK を返さなければいけない。\r
- /// </para>\r
- /// </remark>\r
- void RequestLock(\r
- [In] LockFlags i_lockFlags,\r
- [Out, MarshalAs(UnmanagedType.Error)] out int o_sessionResult\r
- );\r
-\r
-\r
- //====================================================================\r
-\r
- \r
- /// <summary>\r
- /// ドキュメントのステータスを取得するために使用される。ドキュメントのステー\r
- /// タスは TS_STATUS 構造体を通して返される。\r
- /// </summary>\r
- ///\r
- /// <param name="o_documentStatus">\r
- /// ドキュメントのステータスを含む TS_STATUS 構造体を受け取る。NULL 不可。\r
- /// </param>\r
- void GetStatus(\r
- [Out] out TS_STATUS o_documentStatus\r
- );\r
-\r
-\r
- //====================================================================\r
-\r
-\r
- /// <summary>\r
- /// ドキュメントが選択や挿入を許可することができるかどうかを決めるためにア\r
- /// プリケーションから呼ばれる。\r
- ///\r
- /// <para>\r
- /// QueryInsert() メソッドは指定した開始位置と終了位置が有効かどうかを決\r
- /// める。編集を実行する前にドキュメントの編集を調整するために使用される。\r
- /// メソッドはドキュメントの範囲外の値を返してはいけない。\r
- /// </para>\r
- /// </summary>\r
- ///\r
- /// <param name="i_startIndex">\r
- /// テキストを挿入する開始位置。\r
- /// </param>\r
- ///\r
- /// <param name="i_endIndex">\r
- /// テキストを挿入する終了位置。選択中のテキストを置換する代わりに指定した\r
- /// 位置へテキストを挿入する場合は、この値は i_startIndex と同じになる。\r
- /// </param>\r
- ///\r
- /// <param name="i_length">\r
- /// 置換するテキストの長さ。\r
- /// </param>\r
- ///\r
- /// <param name="o_startIndex">\r
- /// 挿入されるテキストの新しい開始位置を返す。このパラメータが NULL の場合、\r
- /// テキストは指定された位置に挿入できない。この値はドキュメントの範囲外を\r
- /// 指定できない。\r
- /// </param>\r
- ///\r
- /// <param name="o_endIndex">\r
- /// 挿入されるテキストの新しい終了位置を返す。このパラメータが NULL の場合、\r
- /// テキストは指定された位置に挿入できない。この値はドキュメントの範囲外を\r
- /// 指定できない\r
- /// </param>\r
- ///\r
- /// <remark>\r
- /// o_startIndex と o_endIndex の値は、アプリケーションがどのように\r
- /// ドキュメントにテキストを挿入するかに依存している。もし、o_startIndex \r
- /// と o_endIndex が i_startIndex と同じならば、カーソルは挿入後のテキ\r
- /// ストの始まりにある。\r
- /// もし、o_startIndex と o_endIndex が i_endIndex と同じならば、\r
- /// カーソルは挿入後のテキストの終わりにある。o_startIndex と\r
- /// o_endIndex の差が挿入されたテキストの長さと同じなら、挿入後、挿入さ\r
- /// れたテキストはハイライトされている。\r
- /// </remark>\r
- void QueryInsert(\r
- [In] int i_startIndex,\r
- [In] int i_endIndex,\r
- [In] int i_length,\r
- [Out] out int o_startIndex, \r
- [Out] out int o_endIndex\r
- );\r
-\r
-\r
- //====================================================================\r
-\r
- \r
- /// <summary>\r
- /// ドキュメント内のテキスト選択の位置を返す。このメソッドは複数テキスト選\r
- /// 択をサポートする。呼び出し元はこのメソッドを呼び出す前にドキュメントに\r
- /// 読取専用ロックをかけておかなければいけない。\r
- /// </summary>\r
- ///\r
- /// <param name="i_index">\r
- /// 処理を開始するテキスト選択を指定する。もし、TS_DEFAULT_SELECTION(-1)\r
- /// 定数が指定された場合、入力選択は処理を開始する。\r
- /// </param>\r
- ///\r
- /// <param name="i_selectionBufferLength">\r
- /// 返す選択の最大数を指定する。\r
- /// </param>\r
- ///\r
- /// <param name="o_selections">\r
- /// 選択されたテキストのスタイル、開始位置、終了位置を受け取る。これらの値\r
- /// は TS_SELECTION_ACP 構造体に出力される。\r
- /// </param>\r
- ///\r
- /// <param name="o_fetchedLength">\r
- /// o_selections に返された構造体の数を受け取る。\r
- /// </param>\r
- void GetSelection(\r
- [In] int i_index,\r
- [In] int i_selectionBufferLength,\r
- [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)] TS_SELECTION_ACP[] o_selections,\r
- out int o_fetchedLength\r
- );\r
-\r
-\r
- //====================================================================\r
-\r
- \r
- /// <summary>\r
- /// ドキュメント内のテキストを選択する。アプリケーションはこのメソッドを呼\r
- /// ぶ前に読み書き両用ロックをかけなればいけない。\r
- /// </summary>\r
- ///\r
- /// <param name="i_count">\r
- /// i_selections 内のテキスト選択の数を指定する。\r
- /// </param>\r
- ///\r
- /// <param name="i_selections">\r
- /// TS_SELECTION_ACP 構造体を通して選択されたテキストのスタイル、開始位置、\r
- /// 終了位置を指定する。\r
- /// \r
- /// <para>\r
- /// 開始位置と終了位置が同じ場合は、指定した位置にキャレットを配置する。\r
- /// ドキュメント内に一度に一つのみキャレットを配置できる。\r
- /// </para>\r
- /// </param>\r
- void SetSelection(\r
- [In] int i_count,\r
- [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] TS_SELECTION_ACP[] i_selections\r
- );\r
-\r
-\r
- //====================================================================\r
-\r
- \r
- /// <summary>\r
- /// 指定された位置のテキストに関する情報を返す。このメソッドは可視状態およ\r
- /// び不可視状態のテキストや埋め込まれたデータがテキストに関連付けられてい\r
- /// るかどうかを返す。\r
- /// </summary>\r
- ///\r
- /// <param name="i_startIndex">\r
- /// 開始位置を指定する。\r
- /// </param>\r
- ///\r
- /// <param name="i_endIndex">\r
- /// 終了位置を指定する。このパラメータが -1 の場合はテキストストア内の全て\r
- /// のテキストを返す。\r
- /// </param>\r
- ///\r
- /// <param name="o_plainText">\r
- /// プレインテキストデータを受け取るバッファを指定する。このパラメータが\r
- /// NULL の場合は、 cchPlainReq は 0 でなければいけない。\r
- /// </param>\r
- ///\r
- /// <param name="i_plainTextLength">\r
- /// プレインテキストの文字数を指定する。\r
- /// </param>\r
- ///\r
- /// <param name="o_plainTextLength">\r
- /// プレインテキストバッファへコピーされた文字数を受け取る。このパラメータ\r
- /// は NULL を指定できない。値が必要でないときに使用する。\r
- /// </param>\r
- ///\r
- /// <param name="o_runInfos">\r
- /// TS_RUNINFO 構造体の配列を受け取る。i_runInfoLength が 0 の場合は NULL。\r
- /// </param>\r
- ///\r
- /// <param name="i_runInfoLength">\r
- /// o_runInfos の許容数を指定する。\r
- /// </param>\r
- ///\r
- /// <param name="o_runInfoLength">\r
- /// o_runInfosに書き込まれた数を受け取る。このパラメータは NULL を指定で\r
- /// きない。\r
- /// </param>\r
- ///\r
- /// <param name="o_nextUnreadCharPos">\r
- /// 次の読み込んでいない文字の位置を受け取る。このパラメータは NULL を指定\r
- /// できない。\r
- /// </param>\r
- ///\r
- /// <remark>\r
- /// このメソッドを使う呼び出し元は ITextStoreACP::RequestLock() メソッドを\r
- /// 呼ぶことでドキュメントに読取専用ロックをかけなければいけない。ロックし\r
- /// ていない場合はメソッドは失敗し、TF_E_NOLOCK を返す。\r
- ///\r
- /// <para>\r
- /// アプリケーションはまた、内部の理由によって戻り値を切り取ることができる。\r
- /// 呼び出し元は必須の戻り値を取得するために戻された文字やテキストのラン\r
- /// 数を注意深く調査しなければいけない。戻り値が不完全ならば、戻り値が完\r
- /// 全なものとなるまでメソッドを繰り返し呼び出さなければいけない。\r
- /// </para>\r
- ///\r
- /// <para>\r
- /// 呼び出し元は i_runInfoLength パラメータを0にセットし、o_runInfos \r
- /// パラメータを NULL にすることで、プレインテキストを要求できる。しかし\r
- /// ながら、呼び出し元は o_plainTextLength に非 NULL の有効な値を提\r
- /// 供しなければならない、パラメータを使用しないとしても。\r
- /// </para>\r
- ///\r
- /// <para>\r
- /// i_endIndex が -1 の場合、ストリームの最後がセットされたものとして処\r
- /// 理しなければいけない。その他の場合、0 以上でなければいけない。\r
- /// </para>\r
- ///\r
- /// <para>\r
- /// メソッドを抜ける際に、o_nextUnreadCharPos は戻り値によって参照\r
- /// されていないストリーム内の次の文字の位置をセットされていなければなら\r
- /// ない。呼び出し元はこれを使用して複数の GetText() 呼び出しで素早くテ\r
- /// キストをスキャンする。\r
- /// </para>\r
- ///\r
- /// </remark>\r
- void GetText(\r
- [In] int i_startIndex,\r
- [In] int i_endIndex,\r
- [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=3)] char[] o_plainText,\r
- [In] int i_plainTextLength,\r
- [Out] out int o_plainTextLength,\r
- [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=6)] TS_RUNINFO[] o_runInfos,\r
- [In] int i_runInfoLength,\r
- [Out] out int o_runInfoLength,\r
- [Out] out int o_nextUnreadCharPos\r
- );\r
-\r
-\r
- //====================================================================\r
-\r
- \r
- /// <summary>\r
- /// SetText() メソッドは与えられた文字位置のテキスト選択をセットする。\r
- /// </summary>\r
- ///\r
- /// <param name="i_flags">\r
- /// TS_ST_CORRECTION がセットされている場合、テキストは既存のコンテントの\r
- /// 移動(訂正)であり、特別なテキストマークアップ情報(メタデータ)が保持され\r
- /// る - .wav ファイルデータや言語IDなど。クライアントは保持されるマークアッ\r
- /// プ情報のタイプを定義する。\r
- /// </param>\r
- ///\r
- /// <param name="i_startIndex">\r
- /// 置換するテキストの開始位置を指定する。\r
- /// </param>\r
- ///\r
- /// <param name="i_endIndex">\r
- /// 置換するテキストの終了位置を指定する。-1 の場合は無視される。\r
- /// </param>\r
- ///\r
- /// <param name="i_text">\r
- /// 置き換えるテキストへのポインタを指定する。テキストの文字数は i_length\r
- /// パラメータによって指定されるため、テキスト文字列は NULL 終端文字を持っ\r
- /// ていない。\r
- /// </param>\r
- ///\r
- /// <param name="i_length">\r
- /// i_text の文字数。\r
- /// </param>\r
- ///\r
- /// <param name="o_textChange">\r
- /// 次のデータをもつ TS_TEXTCHANGE 構造体へのポインタ。\r
- ///\r
- /// <list type="table">\r
- /// <listheader>\r
- /// <term>メンバー名</term>\r
- /// <description>意味</description>\r
- /// </listheader>\r
- /// <item>\r
- /// <term>acpStart</term>\r
- /// <description>\r
- /// テキストがドキュメントに挿入される前の開始位置。\r
- /// </description>\r
- /// </item>\r
- /// <item>\r
- /// <term>acpOldEnd</term>\r
- /// <description>\r
- /// テキストがドキュメントに挿入される前の終了位置。値は挿入位置であ\r
- /// る acpStart と同じ値となる。もし、acpStart と異なっている場合は、\r
- /// テキストはテキストの挿入の前に選択されていた。\r
- /// </description>\r
- /// </item>\r
- /// <item>\r
- /// <term>acpNewEnd</term>\r
- /// <description>\r
- /// テキストを挿入した後の終了位置。\r
- /// </description>\r
- /// </item>\r
- /// </list>\r
- /// </param>\r
- void SetText(\r
- [In] SetTextFlags i_flags,\r
- [In] int i_startIndex,\r
- [In] int i_endIndex,\r
- [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=4)] char[] i_text,\r
- [In] int i_length,\r
- [Out] out TS_TEXTCHANGE o_textChange\r
- );\r
-\r
-\r
- //====================================================================\r
-\r
- \r
- /// <summary>\r
- /// 指定されたテキスト文字列について Formatted Text データを返す。呼び\r
- /// 出し元はこのメソッドを呼ぶ前に読み書き両用ロックをかけなければいけない。\r
- /// </summary>\r
- void GetFormattedText(\r
- [In] int i_start,\r
- [In] int i_end,\r
- [Out, MarshalAs(UnmanagedType.Interface)] out object o_obj\r
- );\r
-\r
-\r
- //====================================================================\r
-\r
-\r
- /// <summary>\r
- /// 組み込みオブジェクトを取得する。\r
- /// </summary>\r
- void GetEmbedded(\r
- [In] int i_position,\r
- [In] ref Guid i_guidService,\r
- [In] ref Guid i_riid,\r
- [Out, MarshalAs(UnmanagedType.Interface)] out object o_obj\r
- );\r
-\r
-\r
- //====================================================================\r
-\r
-\r
- /// <summary>\r
- /// 組み込みオブジェクトを挿入できるか問い合わせる。\r
- /// </summary>\r
- void QueryInsertEmbedded(\r
- [In] ref Guid i_guidService,\r
- [In] int i_formatEtc,\r
- [Out, MarshalAs(UnmanagedType.Bool)] out bool o_insertable\r
- );\r
-\r
-\r
- //====================================================================\r
-\r
-\r
- /// <summary>\r
- /// 組み込みオブジェクトを挿入する。\r
- /// </summary>\r
- void InsertEmbedded(\r
- [In] InsertEmbeddedFlags i_flags,\r
- [In] int i_start,\r
- [In] int i_end,\r
- [In, MarshalAs(UnmanagedType.Interface)] object i_obj,\r
- [Out] out TS_TEXTCHANGE o_textChange\r
- );\r
-\r
-\r
- //====================================================================\r
-\r
-\r
- /// <summary>\r
- /// ITextStoreACP::InsertTextAtSelection() メソッドは挿入位置や選択位置に\r
- /// テキストを挿入する。呼び出し元はテキストを挿入する前に読み書き両用ロッ\r
- /// クをかけていなければならない。\r
- /// </summary>\r
- ///\r
- /// <param name="i_flags">\r
- /// o_startIndex, o_endIndex パラメータと TS_TEXTCHANGE 構造体のどち\r
- /// らがテキストの挿入の結果を含んでいるかを示す。\r
- /// TF_IAS_NOQUERY と TF_IAS_QUERYONLY フラグは同時に指定できない。\r
- ///\r
- /// <list type="table">\r
- /// <listheader>\r
- /// <term>値</term>\r
- /// <description>意味</description>\r
- /// </listheader>\r
- /// <item>\r
- /// <term>0</term>\r
- /// <description>\r
- /// テキスト挿入が発生し、o_startIndex と o_endIndex パラメータ\r
- /// はテキスト挿入の結果を含んでいる。TS_TEXTCHANGE 構造体は 0 で埋め\r
- /// られていなければならない。\r
- /// </description>\r
- /// </item>\r
- /// <item>\r
- /// <term>TF_IAS_NOQUERY</term>\r
- /// <description>\r
- /// テキストは挿入され、o_startIndex と o_endIndex パラメータ\r
- /// の値は NULL にでき、TS_TEXTCHANGE 構造体は埋められなければいけない。\r
- /// このフラグはテキスト挿入の結果を見るために使用する。\r
- /// </description>\r
- /// </item>\r
- /// <item>\r
- /// <term>TF_IAS_QUERYONLY</term>\r
- /// <description>\r
- /// テキストは挿入されず、o_startIndex と o_endIndex パラメータ\r
- /// はテキスト挿入の結果を含む。これらのパラメータの値は、アプリケー\r
- /// ションがどのようにドキュメントにテキストを挿入するかに依存している。\r
- /// 詳しくは注意を見ること。このフラグは実際にはテキストを挿入しない\r
- /// でテキスト挿入の結果を見るために使用する。このフラグを使う場合は\r
- /// TS_TEXTCHANGE 構造体を埋める必要はない。\r
- /// </description>\r
- /// </item>\r
- /// </list>\r
- /// </param>\r
- ///\r
- /// <param name="i_text">\r
- /// 挿入する文字列へのポインタ。NULL 終端にすることができる。\r
- /// </param>\r
- ///\r
- /// <param name="i_length">\r
- /// テキスト長を指定する。\r
- /// </param>\r
- ///\r
- /// <param name="o_startIndex">\r
- /// テキスト挿入が発生した場所の開始位置へのポインタ。\r
- /// </param>\r
- ///\r
- /// <param name="o_endIndex">\r
- /// テキスト挿入が発生した場所の終了位置へのポインタ。このパラメータは挿入\r
- /// の場合、o_startIndex パラメータと同じ値になる。\r
- /// </param>\r
- ///\r
- /// <param name="o_textChange">\r
- /// 次のメンバーを持つ TS_TEXTCHANGE 構造体へのポインタ。\r
- ///\r
- /// <list type="table">\r
- /// <listheader>\r
- /// <term>メンバー名</term>\r
- /// <description>意味</description>\r
- /// </listheader>\r
- /// <item>\r
- /// <term>acpStart</term>\r
- /// <description>\r
- /// テキストがドキュメントに挿入される前の開始位置。\r
- /// </description>\r
- /// </item>\r
- /// <item>\r
- /// <term>acpOldEnd</term>\r
- /// <description>\r
- /// テキストがドキュメントに挿入される前の終了位置。値は挿入位置であ\r
- /// る acpStart と同じ値となる。もし、acpStart と異なっている場合は、\r
- /// テキストはテキストの挿入の前に選択されていた。\r
- /// </description>\r
- /// </item>\r
- /// <item>\r
- /// <term>acpNewEnd</term>\r
- /// <description>\r
- /// テキストを挿入した後の終了位置。\r
- /// </description>\r
- /// </item>\r
- /// </list>\r
- /// </param>\r
- ///\r
- /// <remark>\r
- /// o_startIndex と o_endIndex パラメータの値はアプリケーションがド\r
- /// キュメントにどのようにテキストを挿入したかによる。たとえば、アプリケー\r
- /// ションがテキストを挿入後、挿入したテキストの開始位置にカーソルをセット\r
- /// したなら、o_startIndex と o_endIndex パラメータは TS_TEXTCHANGE \r
- /// 構造体の acpStart メンバと同じ値になる。\r
- /// <para>\r
- /// アプリケーションは ITextStoreACPSink::OnTextChange() メソッドをこの\r
- /// メソッド内で呼ぶべきではない。\r
- /// </para>\r
- /// </remark>\r
- void InsertTextAtSelection(\r
- [In] InsertAtSelectionFlags i_flags,\r
- [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=2)] char[] i_text,\r
- [In] int i_length,\r
- [Out] out int o_startIndex,\r
- [Out] out int o_endIndex,\r
- [Out] out TS_TEXTCHANGE o_textChange\r
- );\r
-\r
-\r
- //====================================================================\r
-\r
-\r
- /// <summary>\r
- /// 選択位置もしくは挿入位置に組み込みオブジェクトを挿入する。\r
- /// </summary>\r
- void InsertEmbeddedAtSelection(\r
- InsertAtSelectionFlags flags,\r
- [MarshalAs(UnmanagedType.Interface)] object obj,\r
- out int start,\r
- out int end,\r
- out TS_TEXTCHANGE change\r
- );\r
-\r
-\r
- //====================================================================\r
-\r
-\r
- /// <summary>\r
- /// ドキュメントのサポートされている属性を取得する。\r
- /// </summary>\r
- /// \r
- /// <param name="i_flags">\r
- /// 後続の ITextStoreACP::RetrieveRequestedAttrs() メソッド呼び出し\r
- /// がサポートされる属性を含むかどうかを指定する。もし、\r
- /// TS_ATTR_FIND_WANT_VALUE フラグが指定されたなら、後続の\r
- /// ITextStoreAcp::RetrieveRequestedAttrs() 呼び出しの後に\r
- /// TS_ATTRVAL 構造体のそれらはデフォルト属性の値になる。もし、他の\r
- /// フラグが指定されたなら属性がサポートされているかどうか確認する\r
- /// だけで、 TS_ATTRVAL 構造体の varValue メンバには VT_EMPTY がセッ\r
- /// トされる。\r
- /// </param>\r
- /// \r
- /// <param name="i_length">\r
- /// 取得するサポートされる属性の数を指定する。\r
- /// </param>\r
- /// \r
- /// <param name="i_filterAttributes">\r
- /// 確認するための属性が指定された TS_ATTRID データタイプへのポイン\r
- /// タ。メソッドは TS_ATTRID によって指定された属性のみを返す(他の\r
- /// 属性をサポートしていたとしても)。\r
- /// </param>\r
- void RequestSupportedAttrs(\r
- [In] AttributeFlags i_flags,\r
- [In] int i_length,\r
- [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)] Guid[] i_filterAttributes\r
- );\r
-\r
- \r
- //====================================================================\r
-\r
-\r
- /// <summary>\r
- /// 指定した文字位置の属性を取得する。\r
- /// </summary>\r
- /// \r
- /// <param name="i_position">\r
- /// ドキュメント内の開始位置。\r
- /// </param>\r
- /// \r
- /// <param name="i_length">\r
- /// 取得する属性の数。\r
- /// </param>\r
- /// \r
- /// <param name="i_filterAttributes">\r
- /// 確認するための属性が指定された TS_ATTRID データタイプへのポインタ。\r
- /// </param>\r
- /// \r
- /// <param name="i_flags">\r
- /// 0 でなければいけない。\r
- /// </param>\r
- void RequestAttrsAtPosition(\r
- [In] int i_position,\r
- [In] int i_length,\r
- [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)] Guid[] i_filterAttributes,\r
- [In] AttributeFlags i_flags\r
- );\r
-\r
-\r
- //====================================================================\r
-\r
- \r
- /// <summary>\r
- /// 指定した文字位置の属性のリストを取得する。\r
- /// </summary>\r
- /// <param name="i_position">ドキュメント内の開始位置。</param>\r
- /// \r
- /// <param name="i_length">取得する属性の数。</param>\r
- /// \r
- /// <param name="i_filterAttributes">\r
- /// RetrieveRequestedAttr() メソッドを呼ぶための属性を指定する。\r
- /// このパラメータがセットされていなければメソッドは指定された位置で\r
- /// 始まる属性を返す。他の指定可能な値は以下のとおり。\r
- /// <list type="table">\r
- /// <listheader>\r
- /// <term>値</term>\r
- /// <description>意味</description>\r
- /// </listheader>\r
- /// <item>\r
- /// <term>TS_ATTR_FIND_WANT_END</term>\r
- /// <description>\r
- /// 指定した文字位置で終了する属性を取得する。\r
- /// </description>\r
- /// </item>\r
- /// <item>\r
- /// <term>TS_ATTR_FIND_WANT_VALUD</term>\r
- /// <description>\r
- /// 属性の取得に加えて属性の値を取得する。属性値は\r
- /// ITextStoreACP::RetrieveRequestedAttrs() メソッド呼び出しの\r
- /// TS_ATTRVAL 構造体の varValue メンバにセットされる。\r
- /// </description>\r
- /// </item>\r
- /// </list>\r
- /// </param>\r
- /// <param name="i_flags"></param>\r
- void RequestAttrsTransitioningAtPosition(\r
- [In] int i_position,\r
- [In] int i_length,\r
- [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)] Guid[] i_filterAttributes,\r
- [In] AttributeFlags i_flags\r
- );\r
-\r
-\r
- //====================================================================\r
-\r
- \r
- /// <summary>\r
- /// 属性変更が発生している場所の文字位置を決定する。\r
- /// </summary>\r
- /// <param name="i_start">属性変更を検索する開始位置を指定する。</param>\r
- /// <param name="i_halt">属性変更を検索する終了位置を指定する。</param>\r
- /// <param name="i_length">チェックするための属性の数を指定する。</param>\r
- /// <param name="i_filterAttributes">\r
- /// チェックするための属性を指定する TS_ATTRID データタイプへのポインタ。\r
- /// </param>\r
- /// <param name="i_flags">\r
- /// 検索方向を指定する。デフォルトではフォワード検索。\r
- /// <list type="table">\r
- /// <listheader>\r
- /// <term>フラグ</term>\r
- /// <description>意味</description>\r
- /// </listheader>\r
- /// \r
- /// <item>\r
- /// <term>TS_ATTR_FIND_BACKWARDS</term>\r
- /// <description>バックワード検索。</description>\r
- /// </item>\r
- /// <item>\r
- /// <term>tS_ATTR_FIND_WANT_OFFSET</term>\r
- /// <description>\r
- /// o_foundOffset パラメータは i_start からの属性変更のオフセットを受け取る。\r
- /// </description>\r
- /// </item>\r
- /// </list>\r
- /// </param>\r
- /// <param name="o_nextIndex">\r
- /// 属性変更をチェックする次の文字位置を受け取る。\r
- /// </param>\r
- /// <param name="o_found">\r
- /// 属性変更が発見された場合に TRUE を受け取る。そのほかは FALSE を受け取る。\r
- /// </param>\r
- /// <param name="o_foundOffset">\r
- /// 属性変更の開始位置(文字位置ではない)を受け取る。TS_ATTR_FIND_WANT_OFFSET\r
- /// フラグが dwFlags にセットされていれば、 acpStart からのオフセットを受け取る。\r
- /// </param>\r
- void FindNextAttrTransition(\r
- [In] int i_start,\r
- [In] int i_halt,\r
- [In] int i_length,\r
- [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=2)] Guid[] i_filterAttributes,\r
- [In] AttributeFlags i_flags,\r
- [Out] out int o_nextIndex,\r
- [Out, MarshalAs(UnmanagedType.Bool)] out bool o_found,\r
- [Out] out int o_foundOffset\r
- );\r
-\r
- \r
- //====================================================================\r
-\r
- \r
- /// <summary>\r
- /// ITextStoreACP::RequestAttrsAtPosition(),\r
- /// TextStoreACP::RequestAttrsTransitioningAtPosition(),\r
- /// ITextStoreACP::RequestSupportedAttrs() によって取得された属性を返す。\r
- /// </summary>\r
- /// <param name="i_length">取得するサポートされる属性の数を指定する。</param>\r
- /// <param name="o_attributeVals">\r
- /// サポートされる属性を受け取る TS_ATTRVAL 構造体へのポインタ。この\r
- /// 構造体のメンバはメソッド呼び出しの i_flags パラメータによる。\r
- /// </param>\r
- /// <param name="o_fetchedLength">サポートされる属性の数を受け取る。</param>\r
- void RetrieveRequestedAttrs(\r
- [In] int i_length,\r
- [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] TS_ATTRVAL[] o_attributeVals,\r
- [Out] out int o_fetchedLength\r
- );\r
-\r
- \r
- //====================================================================\r
-\r
- \r
- /// <summary>ドキュメント内の文字数を取得する。</summary>\r
- ///\r
- /// <param name="o_length">最後の文字位置 + 1 を受け取る。</param>\r
- void GetEndACP(\r
- [Out] out int o_length\r
- );\r
-\r
- \r
- //====================================================================\r
-\r
- \r
- /// <summary>\r
- /// 現在のアクティブビューの TsViewCookie データタイプを返す。\r
- /// </summary>\r
- void GetActiveView(\r
- [Out] out int o_viewCookie\r
- );\r
-\r
- \r
- //====================================================================\r
-\r
- \r
- /// <summary>\r
- /// スクリーン座標をアプリケーション文字位置に変換する。\r
- /// </summary>\r
- /// <param name="i_viewCookie">コンテキストビューを指定する。</param>\r
- /// <param name="i_point">スクリーン座標の位置を示す POINT 構造体へのポインタ。</param>\r
- /// <param name="i_flags">\r
- /// 文字バウンディングボックスからの相対位置に基づくスクリーン座標を\r
- /// 戻すための文字位置を指定する。デフォルトでは、返される文字位置は\r
- /// スクリーン座標を含む文字バウンディングボックスをもつ文字の位置で\r
- /// ある。もし、ポイントが文字を囲むボックス外ならメソッドは NULL ま\r
- /// たは TF_E_INVALIDPOINT を返す。その他のフラグは以下のとおり。\r
- /// <list>\r
- /// <listheader>\r
- /// <term>フラグ</term>\r
- /// <description>意味</description>\r
- /// </listheader>\r
- /// \r
- /// <item>\r
- /// <term>GXFPF_ROUND_NEAREST</term>\r
- /// <description>\r
- /// もし、スクリーン座標での点が文字バウンディングボックスの中\r
- /// に含まれている場合、返される文字位置は ptScreen にもっとも\r
- /// 近いバウンディングの端を持つ文字の位置である。\r
- /// </description>\r
- /// </item>\r
- /// <item>\r
- /// <term>GXFPF_NEAREST</term>\r
- /// <description>\r
- /// もし、スクリーン座標での点が文字バウンディングボックスに含\r
- /// まれていないなら、もっとも近い文字位置が返される。\r
- /// <para>\r
- /// http://msdn.microsoft.com/en-us/library/ms538418(v=VS.85).aspx の Remarks 参照。\r
- /// </para>\r
- /// </description>\r
- /// </item>\r
- /// </list>\r
- /// </param>\r
- /// <param name="o_index"></param>\r
- void GetACPFromPoint(\r
- [In] int i_viewCookie,\r
- [In] ref POINT i_point,\r
- [In] GetPositionFromPointFlags i_flags,\r
- [Out] out int o_index\r
- );\r
-\r
- \r
- //====================================================================\r
-\r
- \r
- /// <summary>\r
- /// 指定した文字位置のスクリーン座標を返す。読み取り専用ロックをかけて呼ば\r
- /// なければいけない。\r
- /// </summary>\r
- ///\r
- /// <param name="i_viewCookie">\r
- /// コンテキストビューを指定する。\r
- /// </param>\r
- ///\r
- /// <param name="i_startIndex">\r
- /// ドキュメント内の取得するテキストの開始位置を指定する。\r
- /// </param>\r
- ///\r
- /// <param name="i_endIndex">\r
- /// ドキュメント内の取得するテキストの終了位置を指定する。\r
- /// </param>\r
- ///\r
- /// <param name="o_rect">\r
- /// 指定した文字位置のテキストのスクリーン座標でのバウンディングボックスを\r
- /// 受け取る。\r
- /// </param>\r
- ///\r
- /// <param name="o_isClipped">\r
- /// バウンディングボックスがクリッピングされたかどうかを受け取る。TRUE の\r
- /// 場合、バウンディングボックスはクリップされたテキストを含み、完全な要求\r
- /// されたテキストの範囲を含んでいない。バウンディングボックスは要求された\r
- /// 範囲が可視状態でないため、クリップされた。\r
- /// </param>\r
- ///\r
- /// <remark>\r
- /// ドキュメントウィンドウが最小化されていたり、指定されたテキストが現在表\r
- /// 示されていないならば、メソッドは S_OK を返して o_rect パラメータに\r
- /// { 0, 0, 0, 0 }をセットしなければいけない。\r
- ///\r
- /// <para>\r
- /// TSF マネージャー側から変換候補ウィンドウの表示位置を割り出すために使用\r
- /// される。\r
- /// </para>\r
- /// </remark>\r
- void GetTextExt(\r
- [In] int i_viewCookie,\r
- [In] int i_startIndex,\r
- [In] int i_endIndex,\r
- [Out] out RECT o_rect,\r
- [MarshalAs(UnmanagedType.Bool)] out bool o_isClipped\r
- );\r
-\r
- \r
- //====================================================================\r
-\r
- \r
- /// <summary>\r
- /// テキストストリームが描画されるディスプレイサーフェイスのスクリーン座標\r
- /// でのバウンディングボックスを取得する。\r
- /// </summary>\r
- ///\r
- /// <remark>\r
- /// ドキュメントウィンドウが最小化されていたり、指定されたテキストが現在表\r
- /// 示されていないならば、メソッドは S_OK を返して o_rect パラメータに\r
- /// { 0, 0, 0, 0 }をセットしなければいけない。\r
- /// </remark>\r
- void GetScreenExt(\r
- [In] int i_viewCookie,\r
- [Out] out RECT o_rect\r
- );\r
-\r
- \r
- //====================================================================\r
-\r
- \r
- /// <summary>\r
- /// 現在のドキュメントに一致するウィンドウのハンドルを取得する。\r
- /// </summary>\r
- ///\r
- /// <param name="i_viewCookie">\r
- /// 現在のドキュメントに一致する TsViewCookie データタイプを指定する。\r
- /// </param>\r
- ///\r
- /// <param name="o_hwnd">\r
- /// 現在のドキュメントに一致するウィンドウのハンドルへのポインタを受け取る。\r
- /// 一致するウィンドウがなければ NULL にできる。\r
- /// </param>\r
- ///\r
- /// <remark>\r
- /// ドキュメントはメモリにあるが、スクリーンに表示されていない場合や、ウィ\r
- /// ンドウがないコントロールや、ウィンドウがないコントロールのオーナーのウィ\r
- /// ンドウハンドルを認識しない場合、ドキュメントは一致するウィンドウハンド\r
- /// ルをもてない。呼び出し元は メソッドが成功したとしても o_hwnd パラメー\r
- /// タに非 NULL 値を受け取ると想定してはいけない。\r
- /// </remark>\r
- void GetWnd(\r
- [In] int i_viewCookie,\r
- [Out] out IntPtr o_hwnd\r
- );\r
- }\r
-#endif\r
-\r
-\r
- //============================================================================\r
- /// <summary>\r
- /// テキストストア\r
- /// </summary>\r
- [ComImport,\r
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown),\r
- Guid("f86ad89f-5fe4-4b8d-bb9f-ef3797a84f1f")\r
- ]\r
- public interface ITextStoreACP2\r
- {\r
- /// <summary>\r
- /// ITextStoreACP2::AdviseSink\r
- /// </summary>\r
- /// <param name="i_riid"></param>\r
- /// <param name="i_unknown"></param>\r
- /// <param name="i_mask"></param>\r
- void AdviseSink(\r
- [In] ref Guid i_riid,\r
- [In, MarshalAs(UnmanagedType.Interface)] object i_unknown,\r
- [In] AdviseFlags i_mask\r
- );\r
- /// <summary>\r
- /// ITextStoreACP2::UnadviseSink\r
- /// </summary>\r
- /// <param name="i_unknown"></param>\r
- void UnadviseSink(\r
- [In, MarshalAs(UnmanagedType.Interface)] object i_unknown\r
- );\r
- /// <summary>\r
- /// ITextStoreACP2::RequestLock\r
- /// </summary>\r
- /// <param name="i_lockFlags"></param>\r
- /// <param name="o_sessionResult"></param>\r
- void RequestLock(\r
- [In] LockFlags i_lockFlags,\r
- [Out, MarshalAs(UnmanagedType.Error)] out int o_sessionResult\r
- );\r
- /// <summary>\r
- /// ITextStoreACP2::GetStatus\r
- /// </summary>\r
- /// <param name="o_documentStatus"></param>\r
- void GetStatus(\r
- [Out] out TS_STATUS o_documentStatus\r
- );\r
- /// <summary>\r
- /// ITextStoreACP2::QueryInsert\r
- /// </summary>\r
- /// <param name="i_startIndex"></param>\r
- /// <param name="i_endIndex"></param>\r
- /// <param name="i_length"></param>\r
- /// <param name="o_startIndex"></param>\r
- /// <param name="o_endIndex"></param>\r
- void QueryInsert(\r
- [In] int i_startIndex,\r
- [In] int i_endIndex,\r
- [In] int i_length,\r
- [Out] out int o_startIndex,\r
- [Out] out int o_endIndex\r
- );\r
- /// <summary>\r
- /// ITextStoreACP2::GetSelection\r
- /// </summary>\r
- /// <param name="i_index"></param>\r
- /// <param name="i_selectionBufferLength"></param>\r
- /// <param name="o_selections"></param>\r
- /// <param name="o_fetchedLength"></param>\r
- void GetSelection(\r
- [In] int i_index,\r
- [In] int i_selectionBufferLength,\r
- [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] TS_SELECTION_ACP[] o_selections,\r
- out int o_fetchedLength\r
- );\r
- /// <summary>\r
- /// ITextStoreACP2::SetSelection\r
- /// </summary>\r
- /// <param name="i_count"></param>\r
- /// <param name="i_selections"></param>\r
- void SetSelection(\r
- [In] int i_count,\r
- [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] TS_SELECTION_ACP[] i_selections\r
- );\r
- /// <summary>\r
- /// ITextStoreACP2::GetText\r
- /// </summary>\r
- /// <param name="i_startIndex"></param>\r
- /// <param name="i_endIndex"></param>\r
- /// <param name="o_plainText"></param>\r
- /// <param name="i_plainTextLength"></param>\r
- /// <param name="o_plainTextLength"></param>\r
- /// <param name="o_runInfos"></param>\r
- /// <param name="i_runInfoLength"></param>\r
- /// <param name="o_runInfoLength"></param>\r
- /// <param name="o_nextUnreadCharPos"></param>\r
- void GetText(\r
- [In] int i_startIndex,\r
- [In] int i_endIndex,\r
- [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] char[] o_plainText,\r
- [In] int i_plainTextLength,\r
- [Out] out int o_plainTextLength,\r
- [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 6)] TS_RUNINFO[] o_runInfos,\r
- [In] int i_runInfoLength,\r
- [Out] out int o_runInfoLength,\r
- [Out] out int o_nextUnreadCharPos\r
- );\r
- /// <summary>\r
- /// ITextStoreACP2::SetText\r
- /// </summary>\r
- /// <param name="i_flags"></param>\r
- /// <param name="i_startIndex"></param>\r
- /// <param name="i_endIndex"></param>\r
- /// <param name="i_text"></param>\r
- /// <param name="i_length"></param>\r
- /// <param name="o_textChange"></param>\r
- void SetText(\r
- [In] SetTextFlags i_flags,\r
- [In] int i_startIndex,\r
- [In] int i_endIndex,\r
- [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] char[] i_text,\r
- [In] int i_length,\r
- [Out] out TS_TEXTCHANGE o_textChange\r
- );\r
- /// <summary>\r
- /// ITextStoreACP2::GetFormattedText\r
- /// </summary>\r
- /// <param name="i_start"></param>\r
- /// <param name="i_end"></param>\r
- /// <param name="o_obj"></param>\r
- void GetFormattedText(\r
- [In] int i_start,\r
- [In] int i_end,\r
- [Out, MarshalAs(UnmanagedType.Interface)] out object o_obj\r
- );\r
- /// <summary>\r
- /// ITextStoreACP2::GetEmbedded\r
- /// </summary>\r
- /// <param name="i_position"></param>\r
- /// <param name="i_guidService"></param>\r
- /// <param name="i_riid"></param>\r
- /// <param name="o_obj"></param>\r
- void GetEmbedded(\r
- [In] int i_position,\r
- [In] ref Guid i_guidService,\r
- [In] ref Guid i_riid,\r
- [Out, MarshalAs(UnmanagedType.Interface)] out object o_obj\r
- );\r
- /// <summary>\r
- /// ITextStoreACP2::QueryInsertEmbedded\r
- /// </summary>\r
- /// <param name="i_guidService"></param>\r
- /// <param name="i_formatEtc"></param>\r
- /// <param name="o_insertable"></param>\r
- void QueryInsertEmbedded(\r
- [In] ref Guid i_guidService,\r
- [In] int i_formatEtc,\r
- [Out, MarshalAs(UnmanagedType.Bool)] out bool o_insertable\r
- );\r
- /// <summary>\r
- /// ITextStoreACP2::InsertEmbedded\r
- /// </summary>\r
- /// <param name="i_flags"></param>\r
- /// <param name="i_start"></param>\r
- /// <param name="i_end"></param>\r
- /// <param name="i_obj"></param>\r
- /// <param name="o_textChange"></param>\r
- void InsertEmbedded(\r
- [In] InsertEmbeddedFlags i_flags,\r
- [In] int i_start,\r
- [In] int i_end,\r
- [In, MarshalAs(UnmanagedType.Interface)] object i_obj,\r
- [Out] out TS_TEXTCHANGE o_textChange\r
- );\r
- /// <summary>\r
- /// ITextStoreACP2::InsertTextAtSelection\r
- /// </summary>\r
- /// <param name="i_flags"></param>\r
- /// <param name="i_text"></param>\r
- /// <param name="i_length"></param>\r
- /// <param name="o_startIndex"></param>\r
- /// <param name="o_endIndex"></param>\r
- /// <param name="o_textChange"></param>\r
- void InsertTextAtSelection(\r
- [In] InsertAtSelectionFlags i_flags,\r
- [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] char[] i_text,\r
- [In] int i_length,\r
- [Out] out int o_startIndex,\r
- [Out] out int o_endIndex,\r
- [Out] out TS_TEXTCHANGE o_textChange\r
- );\r
- /// <summary>\r
- /// ITextStoreACP2::InsertEmbeddedAtSelection\r
- /// </summary>\r
- /// <param name="flags"></param>\r
- /// <param name="obj"></param>\r
- /// <param name="start"></param>\r
- /// <param name="end"></param>\r
- /// <param name="change"></param>\r
- void InsertEmbeddedAtSelection(\r
- InsertAtSelectionFlags flags,\r
- [MarshalAs(UnmanagedType.Interface)] object obj,\r
- out int start,\r
- out int end,\r
- out TS_TEXTCHANGE change\r
- );\r
- /// <summary>\r
- /// ITextStoreACP2::RequestSupportedAttrs\r
- /// </summary>\r
- /// <param name="i_flags"></param>\r
- /// <param name="i_length"></param>\r
- /// <param name="i_filterAttributes"></param>\r
- void RequestSupportedAttrs(\r
- [In] AttributeFlags i_flags,\r
- [In] int i_length,\r
- [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] Guid[] i_filterAttributes\r
- );\r
- /// <summary>\r
- /// ITextStoreACP2::RequestAttrsAtPosition\r
- /// </summary>\r
- /// <param name="i_position"></param>\r
- /// <param name="i_length"></param>\r
- /// <param name="i_filterAttributes"></param>\r
- /// <param name="i_flags"></param>\r
- void RequestAttrsAtPosition(\r
- [In] int i_position,\r
- [In] int i_length,\r
- [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] Guid[] i_filterAttributes,\r
- [In] AttributeFlags i_flags\r
- );\r
- /// <summary>\r
- /// ITextStoreACP2::RequestAttrsTransitioningAtPosition\r
- /// </summary>\r
- /// <param name="i_position"></param>\r
- /// <param name="i_length"></param>\r
- /// <param name="i_filterAttributes"></param>\r
- /// <param name="i_flags"></param>\r
- void RequestAttrsTransitioningAtPosition(\r
- [In] int i_position,\r
- [In] int i_length,\r
- [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] Guid[] i_filterAttributes,\r
- [In] AttributeFlags i_flags\r
- );\r
- /// <summary>\r
- /// ITextStoreACP2::FindNextAttrTransition\r
- /// </summary>\r
- /// <param name="i_start"></param>\r
- /// <param name="i_halt"></param>\r
- /// <param name="i_length"></param>\r
- /// <param name="i_filterAttributes"></param>\r
- /// <param name="i_flags"></param>\r
- /// <param name="o_nextIndex"></param>\r
- /// <param name="o_found"></param>\r
- /// <param name="o_foundOffset"></param>\r
- void FindNextAttrTransition(\r
- [In] int i_start,\r
- [In] int i_halt,\r
- [In] int i_length,\r
- [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] Guid[] i_filterAttributes,\r
- [In] AttributeFlags i_flags,\r
- [Out] out int o_nextIndex,\r
- [Out, MarshalAs(UnmanagedType.Bool)] out bool o_found,\r
- [Out] out int o_foundOffset\r
- );\r
- /// <summary>\r
- /// ITextStoreACP2::RetrieveRequestedAttrs\r
- /// </summary>\r
- /// <param name="i_length"></param>\r
- /// <param name="o_attributeVals"></param>\r
- /// <param name="o_fetchedLength"></param>\r
- void RetrieveRequestedAttrs(\r
- [In] int i_length,\r
- [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] TS_ATTRVAL[] o_attributeVals,\r
- [Out] out int o_fetchedLength\r
- );\r
- /// <summary>\r
- /// ITextStoreACP2::GetEndACP\r
- /// </summary>\r
- /// <param name="o_length"></param>\r
- void GetEndACP(\r
- [Out] out int o_length\r
- );\r
- /// <summary>\r
- /// ITextStoreACP2::GetActiveView\r
- /// </summary>\r
- /// <param name="o_viewCookie"></param>\r
- void GetActiveView(\r
- [Out] out int o_viewCookie\r
- );\r
- /// <summary>\r
- /// ITextStoreACP2::GetACPFromPoint\r
- /// </summary>\r
- /// <param name="i_viewCookie"></param>\r
- /// <param name="i_point"></param>\r
- /// <param name="i_flags"></param>\r
- /// <param name="o_index"></param>\r
- void GetACPFromPoint(\r
- [In] int i_viewCookie,\r
- [In] ref POINT i_point,\r
- [In] GetPositionFromPointFlags i_flags,\r
- [Out] out int o_index\r
- );\r
- /// <summary>\r
- /// ITextStoreACP2::GetTextExt\r
- /// </summary>\r
- /// <param name="i_viewCookie"></param>\r
- /// <param name="i_startIndex"></param>\r
- /// <param name="i_endIndex"></param>\r
- /// <param name="o_rect"></param>\r
- /// <param name="o_isClipped"></param>\r
- void GetTextExt(\r
- [In] int i_viewCookie,\r
- [In] int i_startIndex,\r
- [In] int i_endIndex,\r
- [Out] out RECT o_rect,\r
- [MarshalAs(UnmanagedType.Bool)] out bool o_isClipped\r
- );\r
- /// <summary>\r
- /// ITextStoreACP2::GetScreenExt\r
- /// </summary>\r
- /// <param name="i_viewCookie"></param>\r
- /// <param name="o_rect"></param>\r
- void GetScreenExt(\r
- [In] int i_viewCookie,\r
- [Out] out RECT o_rect\r
- );\r
- }\r
- //============================================================================\r
-\r
- \r
- /// <summary>\r
- /// コンポジション関連の通知を受け取るためにアプリケーション側で実装される\r
- /// インターフェイス。\r
- /// \r
- /// <para>\r
- /// ITfDocumentMgr::CreateContext() が呼ばれた時に TSF マネージャは\r
- /// ITextStoreACP に対してこのインターフェイスを問い合わせる。\r
- /// </para>\r
- /// </summary>\r
- [ComImport,\r
- Guid("5F20AA40-B57A-4F34-96AB-3576F377CC79"),\r
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)\r
- ]\r
- public interface ITfContextOwnerCompositionSink\r
- {\r
- /// <summary>\r
- /// コンポジションが開始された時に TSF マネージャから呼ばれる。\r
- /// </summary>\r
- /// \r
- /// <param name="i_view">\r
- /// 新しいコンポジションを表す ITfCompositionView へのポインタ。\r
- /// </param>\r
- /// \r
- /// <param name="o_ok">\r
- /// 新しいコンポジションを許可するかどうかを受け取る。true の\r
- /// 場合はコンポジションを許可し、false の場合は許可しない。\r
- /// </param>\r
- void OnStartComposition(\r
- [In] ITfCompositionView i_view,\r
- [Out, MarshalAs(UnmanagedType.Bool)] out bool o_ok\r
- );\r
-\r
-\r
- /// <summary>\r
- /// 既存のコンポジションが変更された時に TSF マネージャから呼ばれる。\r
- /// </summary>\r
- /// \r
- /// <param name="i_view">\r
- /// 更新されるコンポジションを表す ITfCompositionView へのポインタ。\r
- /// </param>\r
- /// \r
- /// <param name="i_rangeNew">\r
- /// コンポジションが更新された後にコンポジションがカバーするテキスト\r
- /// の範囲を含む ITfRange へのポインタ。\r
- /// </param>\r
- void OnUpdateComposition(\r
- [In] ITfCompositionView i_view,\r
- [In] ITfRange i_rangeNew\r
- );\r
-\r
-\r
- /// <summary>\r
- /// コンポジションが終了した時に TSF マネージャから呼ばれる。\r
- /// </summary>\r
- /// <param name="i_view">\r
- /// 終了したコンポジションを表す ITfCompositionView へのポインタ。\r
- /// </param>\r
- void OnEndComposition(\r
- [In] ITfCompositionView i_view\r
- );\r
- }\r
-\r
-\r
-//============================================================================\r
-\r
-\r
- /// <summary>\r
- /// ITextStoreACP::AdviseSink() で渡されるシンクのインターフェイス。\r
- /// </summary>\r
- [ComImport,\r
- Guid("22d44c94-a419-4542-a272-ae26093ececf"),\r
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)\r
- ]\r
- public interface ITextStoreACPSink\r
- {\r
- /// <summary>\r
- /// テキストが変更された時に呼び出される。\r
- /// </summary>\r
- /// <param name="i_flags">追加情報を示すフラグ。</param>\r
- /// <param name="i_change">テキスト変更データを含む TS_TEXTCHANGE データ。</param>\r
- [SecurityCritical]\r
- void OnTextChange(\r
- [In] OnTextChangeFlags i_flags,\r
- [In] ref TS_TEXTCHANGE i_change\r
- );\r
-\r
-\r
- /// <summary>\r
- /// ドキュメント内部で選択が変更された時に呼び出される。\r
- /// </summary>\r
- [SecurityCritical]\r
- void OnSelectionChange();\r
-\r
-\r
-\r
- /// <summary>\r
- /// ドキュメントのレイアウトが変更された時に呼び出される。\r
- /// </summary>\r
- /// \r
- /// <param name="i_layoutCode">変更のタイプを定義する値。</param>\r
- /// <param name="i_viewCookie">ドキュメントを識別するアプリケーション定義のクッキー値。</param>\r
- [SecurityCritical]\r
- void OnLayoutChange(\r
- [In] TsLayoutCode i_layoutCode, \r
- [In] int i_viewCookie\r
- );\r
-\r
- \r
- /// <summary>\r
- /// ステータスが変更された時に呼び出される。\r
- /// </summary>\r
- /// \r
- /// <param name="i_flags">新しいステータスフラグ。</param>\r
- [SecurityCritical]\r
- void OnStatusChange(\r
- [In] DynamicStatusFlags i_flags\r
- );\r
-\r
-\r
- /// <summary>\r
- /// 一つ以上の属性が変更された時に呼び出される。\r
- /// </summary>\r
- /// \r
- /// <param name="i_start">属性が変更されたテキストの開始位置。</param>\r
- /// <param name="i_end">属性が変更されたテキストの終了位置。</param>\r
- /// <param name="i_length">i_attributes パラメータの要素数。</param>\r
- /// <param name="i_attributes">変更された属性を識別する値。</param>\r
- [SecurityCritical]\r
- void OnAttrsChange(\r
- [In] int i_start,\r
- [In] int i_end,\r
- [In] int i_length,\r
- [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=2)] Guid[] i_attributes\r
- );\r
-\r
- \r
- /// <summary>\r
- /// ITextStoreACP::RequestLock() でロックが成功した場合に呼び出される。\r
- /// </summary>\r
- /// \r
- /// <param name="i_flags">ロックフラグ。</param>\r
- /// \r
- /// <returns>HRESULT のエラーコード。</returns>\r
- [PreserveSig, SecurityCritical]\r
- int OnLockGranted(\r
- [In] LockFlags i_flags\r
- );\r
-\r
-\r
- /// <summary>\r
- /// エディットトランザクションが開始された時に呼び出される。\r
- /// \r
- /// <pre>\r
- /// エディットトランザクションは、一度に処理されるべきテキストの変更\r
- /// のグループ。ITextStoreACPSink::OnStartEditTransaction() 呼び出し\r
- /// は、テキストサービスに ITextStoreACPSink::OnEndEditTransaction()\r
- /// が呼ばれるまで、テキストの変更通知をキューに入れさせることが\r
- /// できる。ITextStoreACPSink::OnEndEditTransaction() が呼び出される\r
- /// と、キューに入れられた変更通知はすべて処理される。\r
- /// </pre>\r
- /// \r
- /// <pre>\r
- /// エディットトランザクションの実装は任意。\r
- /// </pre>\r
- /// </summary>\r
- [SecurityCritical]\r
- void OnStartEditTransaction();\r
-\r
-\r
- /// <summary>\r
- /// エディットトランザクションが終了した時に呼び出される。\r
- /// </summary>\r
- /// \r
- /// <pre>\r
- /// エディットトランザクションは、一度に処理されるべきテキストの変更\r
- /// のグループ。ITextStoreACPSink::OnStartEditTransaction() 呼び出し\r
- /// は、テキストサービスに ITextStoreACPSink::OnEndEditTransaction()\r
- /// が呼ばれるまで、テキストの変更通知をキューに入れさせることが\r
- /// できる。ITextStoreACPSink::OnEndEditTransaction() が呼び出される\r
- /// と、キューに入れられた変更通知はすべて処理される。\r
- /// </pre>\r
- /// \r
- /// <pre>\r
- /// エディットトランザクションの実装は任意。\r
- /// </pre>\r
- [SecurityCritical]\r
- void OnEndEditTransaction();\r
- }\r
-\r
-\r
-//============================================================================\r
-\r
-\r
- [StructLayout(LayoutKind.Sequential, Pack=4),\r
- Guid("E26D9E1D-691E-4F29-90D7-338DCF1F8CEF")\r
- ]\r
- public struct TF_PERSISTENT_PROPERTY_HEADER_ACP\r
- {\r
- /// <summary>\r
- /// プロパティを識別する GUID。\r
- /// </summary>\r
- public Guid guidOfType;\r
- /// <summary>\r
- /// プロパティの開始文字位置。\r
- /// </summary>\r
- public int start;\r
- /// <summary>\r
- /// プロパティの文字数。\r
- /// </summary>\r
- public int length;\r
- /// <summary>\r
- /// プロパティのバイト数。\r
- /// </summary>\r
- public uint bytes;\r
- /// <summary>\r
- /// プロパティオーナーによって定義された値。\r
- /// </summary>\r
- public uint privateValue;\r
- /// <summary>\r
- /// プロパティオーナーの CLSID。\r
- /// </summary>\r
- public Guid clsidOfTip;\r
- }\r
-\r
- \r
-//============================================================================\r
-\r
-\r
- /// <summary>\r
- /// アプリケーション側で実装し、TSF マネージャーがドキュメントを非同期に\r
- /// ロードするために使用されるインターフェイス。\r
- /// </summary>\r
- [ComImport,\r
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown), \r
- Guid("4EF89150-0807-11D3-8DF0-00105A2799B5")\r
- ]\r
- public interface ITfPersistentPropertyLoaderACP\r
- {\r
- /// <summary>\r
- /// プロパティをロードするときに使用される。\r
- /// </summary>\r
- /// \r
- /// <param name="i_propertyHeader">\r
- /// ロードするプロパティを識別する TF_PERSISTENT_PROPERTY_HEADER_ACP\r
- /// データ。\r
- /// </param>\r
- /// \r
- /// <param name="o_stream">\r
- /// ストリームオブジェクトの受け取り先。\r
- /// </param>\r
- void LoadProperty(\r
- [In] ref TF_PERSISTENT_PROPERTY_HEADER_ACP i_propertyHeader,\r
- [Out, MarshalAs(UnmanagedType.Interface)] out IStream o_stream\r
- );\r
- }\r
-\r
- \r
-//============================================================================\r
-\r
- \r
- /// <summary>\r
- /// ACP ベースのアプリケーションにいくつかの機能を提供するために TSF マ\r
- /// ネージャーによって実装されるインターフェイス。\r
- /// <pre>\r
- /// ITextStoreACP::AdviseSink() に渡されるシンクオブジェクトに\r
- /// QueryInterface() をすることで得られる。\r
- /// </pre>\r
- /// </summary>\r
- [ComImport, \r
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown),\r
- Guid("AA80E901-2021-11D2-93E0-0060B067B86E")\r
- ]\r
- public interface ITextStoreACPServices\r
- {\r
- /// <summary>\r
- /// ITfRange オブジェクトからプロパティを取得して、ストリームオブジェクトに\r
- /// 書き出す。\r
- /// </summary>\r
- void Serialize(\r
- [In, MarshalAs(UnmanagedType.Interface)] ITfProperty i_property,\r
- [In, MarshalAs(UnmanagedType.Interface)] ITfRange i_range,\r
- [Out] out TF_PERSISTENT_PROPERTY_HEADER_ACP o_propertyHeader,\r
- [In, MarshalAs(UnmanagedType.Interface)] IStream i_stream\r
- );\r
-\r
-\r
- /// <summary>\r
- /// 以前にシリアライズされたプロパティデータを取得してプロパティオブジェクトに\r
- /// 適用する。\r
- /// </summary>\r
- void Unserialize(\r
- [In, MarshalAs(UnmanagedType.Interface)] ITfProperty i_property,\r
- [In] ref TF_PERSISTENT_PROPERTY_HEADER_ACP i_propertyHeader,\r
- [In, MarshalAs(UnmanagedType.Interface)] IStream i_stream,\r
- [In, MarshalAs(UnmanagedType.Interface)] ITfPersistentPropertyLoaderACP i_loader\r
- );\r
-\r
-\r
- /// <summary>\r
- /// Forces all values of an asynchronously loaded property to be loaded.\r
- /// </summary>\r
- void ForceLoadProperty(\r
- [In, MarshalAs(UnmanagedType.Interface)] ITfProperty i_property\r
- );\r
-\r
-\r
- /// <summary>\r
- /// 終了位置と開始位置から ITfRangeACP を生成する。\r
- /// </summary>\r
- /// <param name="i_startIndex">開始位置。</param>\r
- /// <param name="i_endIndex">終了位置。</param>\r
- /// <param name="o_range">ITfRangeACP の受け取り先。</param>\r
- void CreateRange(\r
- [In] int i_startIndex,\r
- [In] int i_endIndex,\r
- [Out, MarshalAs(UnmanagedType.Interface)] out ITfRangeACP o_range\r
- );\r
- }\r
-\r
-\r
-}\r
+using System;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.ComTypes;
+using System.Security;
+using DotNetTextStore.UnmanagedAPI.WinDef;
+
+
+namespace DotNetTextStore.UnmanagedAPI.TSF.TextStore
+{
+ /// <summary>
+ /// ITextStoreACP::RequestLock() で使用されるロックのフラグ。
+ /// </summary>
+ public enum LockFlags
+ {
+ /// <summary>
+ /// 読み取り専用。
+ /// </summary>
+ TS_LF_READ = 2,
+ /// <summary>
+ /// 読み書き両用。
+ /// </summary>
+ TS_LF_READWRITE = 6,
+ /// <summary>
+ /// 同期ロック。その他のフラグと組み合わせて使用する。
+ /// </summary>
+ TS_LF_SYNC = 1,
+ /// <summary>
+ /// 書き込み用。
+ /// </summary>
+ TS_LF_WRITE = 4
+ }
+
+
+ /// <summary>
+ /// TS_STATUS 構造体の dynamicFlags メンバで使用されるフラグ
+ /// </summary>
+ public enum DynamicStatusFlags
+ {
+ /// <summary>
+ /// ドキュメントはロード中の状態。
+ /// </summary>
+ TS_SD_LOADING = 2,
+ /// <summary>
+ /// ドキュメントは読み取り専用。
+ /// </summary>
+ TS_SD_READONLY = 1
+ }
+
+
+ /// <summary>
+ /// TS_STATUS 構造体の staticFlags メンバで使用するフラグ。
+ /// </summary>
+ public enum StaticStatusFlags
+ {
+ /// <summary>
+ /// ドキュメントは複数選択をサポートしている。
+ /// </summary>
+ TS_SS_DISJOINTSEL = 1,
+ /// <summary>
+ /// 隠しテキストを含めることはない。
+ /// </summary>
+ TS_SS_NOHIDDENTEXT = 8,
+ /// <summary>
+ /// ドキュメントは複数のリージョンを含められる。
+ /// </summary>
+ TS_SS_REGIONS = 2,
+ /// <summary>
+ /// ドキュメントは短い使用サイクルを持つ。
+ /// </summary>
+ TS_SS_TRANSITORY = 4,
+ /// <summary>
+ /// ドキュメントはタッチキーボードによるオートコレクションをサポートしている
+ /// </summary>
+ TS_SS_TKBAUTOCORRECTENABLE = 0x10,
+ /// <summary>
+ /// ドキュメントはタッチキーボードによる予測入力に対応している
+ /// </summary>
+ TS_SS_TKBPREDICTIONENABLE = 0x20
+ }
+
+
+ /// <summary>
+ /// ドキュメントのステータスを示す構造体。ITextStoreACP::GetStatus() で使用される。
+ /// </summary>
+ [StructLayout(LayoutKind.Sequential, Pack=4),
+ Guid("BC7D979A-846A-444D-AFEF-0A9BFA82B961")
+ ]
+ public struct TS_STATUS
+ {
+ /// <summary>
+ /// 実行時に変更できる状態フラグ。
+ /// </summary>
+ public DynamicStatusFlags dynamicFlags;
+ /// <summary>
+ /// 実行時に変更できない一貫性をもつフラグ。
+ /// </summary>
+ public StaticStatusFlags staticFlags;
+ }
+
+
+ /// <summary>
+ /// ITextStoreACP::SetText() で使用されるフラグ。
+ /// </summary>
+ [Flags]
+ public enum SetTextFlags
+ {
+ /// <summary>
+ /// 既存のコンテントの移動(訂正)であり、特別なテキストマークアップ情報
+ /// (メタデータ: .wav ファイルデータや言語IDなど)が保持される。クライア
+ /// ントは保持されるマークアップ情報のタイプを定義する。
+ /// </summary>
+ TS_ST_CORRECTION = 1
+ }
+
+
+ /// <summary>
+ /// ITextStoreACP::AdviseSink() メソッドに渡されるフラグ。要求する変更通知
+ /// を組み合わせて使用する。
+ /// </summary>
+ public enum AdviseFlags
+ {
+ /// <summary>
+ /// ドキュメントの属性が変更された。
+ /// </summary>
+ TS_AS_ATTR_CHANGE = 8,
+ /// <summary>
+ /// ドキュメントのレイアウトが変更された。
+ /// </summary>
+ TS_AS_LAYOUT_CHANGE = 4,
+ /// <summary>
+ /// テキストはドキュメント内で選択された。
+ /// </summary>
+ TS_AS_SEL_CHANGE = 2,
+ /// <summary>
+ /// ドキュメントのステータスが変更された。
+ /// </summary>
+ TS_AS_STATUS_CHANGE = 0x10,
+ /// <summary>
+ /// テキストはドキュメント内で変更された。
+ /// </summary>
+ TS_AS_TEXT_CHANGE = 1
+ }
+
+
+ /// <summary>
+ /// 選択範囲を示す構造体。
+ /// </summary>
+ [StructLayout(LayoutKind.Sequential, Pack=4),
+ Guid("C4B9C33B-8A0D-4426-BEBE-D444A4701FE9")
+ ]
+ public struct TS_SELECTION_ACP
+ {
+ /// <summary>
+ /// 開始文字位置。
+ /// </summary>
+ public int start;
+ /// <summary>
+ /// 終了文字位置。
+ /// </summary>
+ public int end;
+ /// <summary>
+ /// スタイル。選択範囲の開始位置が終了位置なのか開始位置なのか示すフラ
+ /// グの ase と仮決定を示す真偽値 interimChar を持つ。
+ /// </summary>
+ public TS_SELECTIONSTYLE style;
+ }
+
+
+ /// <summary>
+ /// TS_SELECTION_ACP のメンバとして使用される構造体。
+ /// </summary>
+ [StructLayout(LayoutKind.Sequential, Pack=4),
+ Guid("7ECC3FFA-8F73-4D91-98ED-76F8AC5B1600")
+ ]
+ public struct TS_SELECTIONSTYLE
+ {
+ /// <summary>
+ /// 選択範囲の開始位置が終了位置なのか開始位置なのか示す
+ /// </summary>
+ public TsActiveSelEnd ase;
+ /// <summary>
+ /// 用途不明。説明を見ると変換中の文字のことのようだが変換中の文字に対
+ /// しても true が渡されたことは無い・・・
+ /// </summary>
+ [MarshalAs(UnmanagedType.Bool)]
+ public bool interimChar;
+ }
+
+
+ /// <summary>
+ /// 選択範囲の終了位置を示すフラグ。
+ /// </summary>
+ public enum TsActiveSelEnd
+ {
+ /// <summary>
+ /// アクティブな選択は無い。
+ /// </summary>
+ TS_AE_NONE,
+ /// <summary>
+ /// 開始位置が選択範囲の終了位置である。
+ /// </summary>
+ TS_AE_START,
+ /// <summary>
+ /// 終了位置と選択範囲の終了位置は同じである。
+ /// </summary>
+ TS_AE_END
+ }
+
+
+ /// <summary>
+ /// ITextStoreACP.FindNextAttrTransition() などで使用されるフラグ。
+ /// </summary>
+ [Flags]
+ public enum AttributeFlags
+ {
+ /// <summary>
+ /// バックワード検索。
+ /// </summary>
+ TS_ATTR_FIND_BACKWARDS = 1,
+ /// <summary>
+ /// 不明。資料なし。
+ /// </summary>
+ TS_ATTR_FIND_HIDDEN = 0x20,
+ /// <summary>
+ /// 不明。資料なし。
+ /// </summary>
+ TS_ATTR_FIND_UPDATESTART = 4,
+ /// <summary>
+ /// 不明。資料なし。
+ /// </summary>
+ TS_ATTR_FIND_WANT_END = 0x10,
+ /// <summary>
+ /// o_foundOffset パラメータは i_start からの属性変更のオフセットを受け取る。
+ /// </summary>
+ TS_ATTR_FIND_WANT_OFFSET = 2,
+ /// <summary>
+ /// 不明。資料なし。
+ /// </summary>
+ TS_ATTR_FIND_WANT_VALUE = 8
+ }
+
+
+ /// <summary>
+ /// ITextStoreACP::InsertEmbedded() で使用されるフラグ
+ /// </summary>
+ [Flags]
+ public enum InsertEmbeddedFlags
+ {
+ /// <summary>
+ /// 既存のコンテントの移動(訂正)であり、特別なテキストマークアップ情報
+ /// (メタデータ: .wav ファイルデータや言語IDなど)が保持される。クライア
+ /// ントは保持されるマークアップ情報のタイプを定義する。
+ /// </summary>
+ TS_IE_CORRECTION = 1
+ }
+
+
+ /// <summary>
+ /// ITextStoreACP::InsertTextAtSelection(),
+ /// ITextStoreACP::InsertEmbeddedAtSelection() で使用されるフラグ。
+ /// </summary>
+ [Flags]
+ public enum InsertAtSelectionFlags
+ {
+ /// <summary>
+ /// テキストは挿入され、挿入後の開始位置・終了位置を受け取るパラメータ
+ /// の値は NULL にでき、TS_TEXTCHANGE 構造体は埋められなければいけない。
+ /// このフラグはテキスト挿入の結果を見るために使用する。
+ /// </summary>
+ TF_IAS_NOQUERY = 1,
+ /// <summary>
+ /// テキストは実際には挿入されず、挿入後の開始位置・終了位置を受け取る
+ /// パラメータはテキスト挿入の結果を含む。これらのパラメータの値は、
+ /// アプリケーションがどのようにドキュメントにテキストを挿入するかに依
+ /// 存している。このフラグは実際にはテキストを挿入しないでテキスト挿入
+ /// の結果を見るために使用する。このフラグを使う場合はTS_TEXTCHANGE
+ /// 構造体を埋める必要はない。
+ /// </summary>
+ TF_IAS_QUERYONLY = 2
+ }
+
+
+ /// <summary>
+ /// ランタイプ
+ /// </summary>
+ public enum TsRunType
+ {
+ /// <summary>
+ /// プレーンテキスト。
+ /// </summary>
+ TS_RT_PLAIN,
+ /// <summary>
+ /// 不可視。
+ /// </summary>
+ TS_RT_HIDDEN,
+ /// <summary>
+ /// アプリケーションや ITextStore インターフェイスを実装するテキスト
+ /// サービスによるテキスト内の組み込まれたプライベートデータタイプ。
+ /// </summary>
+ TS_RT_OPAQUE
+ }
+
+
+ /// <summary>
+ /// ラン情報を示す構造体。
+ /// </summary>
+ [StructLayout(LayoutKind.Sequential, Pack=4),
+ Guid("A6231949-37C5-4B74-A24E-2A26C327201D")
+ ]
+ public struct TS_RUNINFO
+ {
+ /// <summary>
+ /// テキストラン内の文字数。
+ /// </summary>
+ public int length;
+ /// <summary>
+ /// テキストランのタイプ。
+ /// </summary>
+ public TsRunType type;
+ }
+
+
+ /// <summary>
+ /// 変更前および変更後の開始位置・終了位置を示す構造体。
+ /// </summary>
+ [StructLayout(LayoutKind.Sequential, Pack=4),
+ Guid("F3181BD6-BCF0-41D3-A81C-474B17EC38FB")
+ ]
+ public struct TS_TEXTCHANGE
+ {
+ /// <summary>
+ /// テキストがドキュメントに挿入される前の開始位置。
+ /// </summary>
+ public int start;
+ /// <summary>
+ /// テキストがドキュメントに挿入される前の終了位置。値は挿入位置である
+ /// start と同じ値となる。もし、start と異なっている場合は、テキストは
+ /// テキストの挿入の前に選択されていた。
+ /// </summary>
+ public int oldEnd;
+ /// <summary>
+ /// テキストを挿入した後の終了位置。
+ /// </summary>
+ public int newEnd;
+ }
+
+
+ [StructLayout(LayoutKind.Sequential, Pack=8),
+ Guid("2CC2B33F-1174-4507-B8D9-5BC0EB37C197")
+ ]
+ public struct TS_ATTRVAL
+ {
+ public Guid attributeId;
+ public int overlappedId;
+ public int reserved;
+ public VARIANT val;
+ }
+
+
+ /// <summary>
+ /// ITextStoreACP::GetACPFromPoint() で使用されるフラグ。
+ ///
+ /// <para>詳しくは http://msdn.microsoft.com/en-us/library/ms538418(v=VS.85).aspx の Remarks 参照。</para>
+ /// </summary>
+ [Flags]
+ public enum GetPositionFromPointFlags
+ {
+ /// <summary>
+ /// もし、スクリーン座標での点が文字バウンディングボックスに含まれてい
+ /// ないなら、もっとも近い文字位置が返される。
+ /// </summary>
+ GXFPF_NEAREST = 2,
+ /// <summary>
+ /// もし、スクリーン座標での点が文字バウンディングボックスの中に含まれ
+ /// ている場合、返される文字位置は ptScreen にもっとも近いバウンディン
+ /// グの端を持つ文字の位置である。
+ /// </summary>
+ GXFPF_ROUND_NEAREST = 1
+ }
+
+
+ /// <summary>
+ /// ITextStoreACPSink::OnTextChange() で使用されるフラグ。
+ /// </summary>
+ [Flags]
+ public enum OnTextChangeFlags
+ {
+ NONE = 0,
+ TS_TC_CORRECTION = 1
+ }
+
+
+ /// <summary>
+ /// ITextStoreACPSink::OnLayoutChange() で使用されるフラグ。
+ /// </summary>
+ public enum TsLayoutCode
+ {
+ /// <summary>
+ /// ビューが生成された。
+ /// </summary>
+ TS_LC_CREATE,
+ /// <summary>
+ /// レイアウトが変更された。
+ /// </summary>
+ TS_LC_CHANGE,
+ /// <summary>
+ /// レイアウトが破棄された。
+ /// </summary>
+ TS_LC_DESTROY
+ }
+
+
+ /// <summary>
+ /// GetSelection() の i_index 引数に使用する定数。
+ /// </summary>
+ public enum GetSelectionIndex : int
+ {
+ /// <summary>
+ /// デフォルト選択を意味する。
+ /// </summary>
+ TS_DEFAULT_SELECTION = -1
+ }
+
+
+//============================================================================
+
+
+ /// <summary>
+ /// テキストストアのメソッドの戻り値(C# では COMException のエラーコード)
+ /// </summary>
+ public static class TsResult
+ {
+ /// <summary>
+ /// Application does not support the data type contained in the IDataObject object to be inserted using ITextStoreACP::InsertEmbedded.
+ /// </summary>
+ public const int TS_E_FORMAT = unchecked((int)0x8004020a);
+ /// <summary>
+ /// Parameter is not within the bounding box of any character.
+ /// </summary>
+ public const int TS_E_INVALIDPOINT = unchecked((int)0x80040207);
+ /// <summary>
+ /// Range specified extends outside the document.
+ /// </summary>
+ public const int TS_E_INVALIDPOS = unchecked((int)0x80040200);
+ /// <summary>
+ /// Object does not support the requested interface.
+ /// </summary>
+ public const int TS_E_NOINTERFACE = unchecked((int)0x80040204);
+ /// <summary>
+ /// Application has not calculated a text layout.
+ /// </summary>
+ public const int TS_E_NOLAYOUT = unchecked((int)0x80040206);
+ /// <summary>
+ /// Application does not have a read-only lock or read/write lock for the document.
+ /// </summary>
+ public const int TS_E_NOLOCK = unchecked((int)0x80040201);
+ /// <summary>
+ /// Embedded content offset is not positioned before a TF_CHAR_EMBEDDED character.
+ /// </summary>
+ public const int TS_E_NOOBJECT = unchecked((int)0x80040202);
+ /// <summary>
+ /// Document has no selection.
+ /// </summary>
+ public const int TS_E_NOSELECTION = unchecked((int)0x80040205);
+ /// <summary>
+ /// Content cannot be returned to match the service GUID.
+ /// </summary>
+ public const int TS_E_NOSERVICE = unchecked((int)0x80040203);
+ /// <summary>
+ /// Document is read-only. Cannot modify content.
+ /// </summary>
+ public const int TS_E_READONLY = unchecked((int)0x80040209);
+ /// <summary>
+ /// Document cannot be locked synchronously.
+ /// </summary>
+ /// <remarks>
+ /// CAUTION: this value is marked as 0x00040300 in the document.
+ /// </remarks>
+ public const int TS_E_SYNCHRONOUS = unchecked((int)0x00040208);
+ /// <summary>
+ /// Document successfully received an asynchronous lock.
+ /// </summary>
+ public const int TS_S_ASYNC = 0x01;
+ /// <summary>
+ /// COMCTL.h より。SINK をこれ以上登録できない。
+ /// </summary>
+ public const int CONNECT_E_ADVISELIMIT = -2147220991;
+ /// <summary>
+ /// COMCTL.h より。SINK は登録されていない。
+ /// </summary>
+ public const int CONNECT_E_NOCONNECTION = -2147220992;
+ }
+
+
+ //============================================================================
+
+
+#if !METRO
+ /// <summary>
+ /// テキストストア
+ /// </summary>
+ [ComImport,
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
+ Guid("28888fe3-c2a0-483a-a3ea-8cb1ce51ff3d")
+ ]
+ public interface ITextStoreACP
+ {
+ /// <summary>
+ /// TSF マネージャのシンクインターフェイスを識別する。
+ /// <para>
+ /// ITextStoreACP::AdviseSink() メソッドは ITextStoreACPSink インターフェイス
+ /// から新しいアドバイズシンクをインストール、または既存のアドバイズシンクの
+ /// 修正を行う。シンクインターフェイスは io_unknown_cp パラメータによって指定
+ /// される。
+ /// </para>
+ /// </summary>
+ ///
+ /// <param name="i_riid">
+ /// シンクインターフェイスを指定する。
+ /// </param>
+ ///
+ /// <param name="i_unknown">
+ /// シンクインターフェイスへのポインタ。NULL 不可。
+ /// </param>
+ ///
+ /// <param name="i_mask">
+ /// アドバイズシンクを通知するイベントを指定する。
+ /// <list type="table">
+ /// <listheader>
+ /// <term>フラグ(値)</term>
+ /// <description>コメント</description>
+ /// </listheader>
+ /// <item>
+ /// <term>TS_AS_TEXT_CHANGE(0x1)</term>
+ /// <description>テキストはドキュメント内で変更された。</description>
+ /// </item>
+ /// <item>
+ /// <term>TS_AS_SEL_CHANGE(0x2)</term>
+ /// <description>テキストはドキュメント内で選択された。</description>
+ /// </item>
+ /// <item>
+ /// <term>TS_AS_LAYOUT_CHANGE(0x04)</term>
+ /// <description>ドキュメントのレイアウトが変更された。</description>
+ /// </item>
+ /// <item>
+ /// <term>TS_AS_ATTR_CHANGE(0x08)</term>
+ /// <description>ドキュメントの属性が変更された。</description>
+ /// </item>
+ /// <item>
+ /// <term>TS_AS_STATUS_CHANGE(0x10)</term>
+ /// <description>ドキュメントのステータスが変更された。</description>
+ /// </item>
+ /// <item>
+ /// <term>TS_AS_ALL_SINKS</term>
+ /// <description>上記全て</description>
+ /// </item>
+ /// </list>
+ /// </param>
+ void AdviseSink(
+ [In] ref Guid i_riid,
+ [In, MarshalAs(UnmanagedType.Interface)] object i_unknown,
+ [In] AdviseFlags i_mask
+ );
+
+
+ //====================================================================
+
+
+ /// <summary>
+ /// アプリケーションはもはやTSFマネージャから通知を必要としないことを示す
+ /// ためにアプリケーションによって呼ばれる。TSFマネージャはシンクインター
+ /// フェイスの解放と通知の停止を行う。
+ /// </summary>
+ ///
+ /// <param name="i_unknown">
+ /// シンクオブジェクトへのポインタ。NULL 不可。
+ /// </param>
+ ///
+ /// <remark>
+ /// 新しいシンクオブジェクトを登録する ITextStoreACP::AdviseSink メソッド
+ /// の全ての呼び出しは、このメソッドの呼び出しと対応していなければならない。
+ /// 以前に登録されたシンクの dwMask パラメータを更新するだけの
+ /// ITextStoreACP::AdviseSink() メソッドの呼び出しは
+ /// ITextStoreACP::UnadviseSink() メソッドの呼び出しを必要としない。
+ ///
+ /// <para>
+ /// io_unknown_cp パラメータは ITextStoreACP::AdviseSink メソッドに渡さ
+ /// れたオリジナルのポインタとして同じ COM 識別子でなければいけない。
+ /// </para>
+ /// </remark>
+ ///
+ /// <returns>
+ /// <list type="table">
+ /// <listheader>
+ /// <term>戻り値</term>
+ /// <description>意味</description>
+ /// </listheader>
+ /// <item>
+ /// <term>S_OK</term>
+ /// <description>メソッドは成功した。</description>
+ /// </item>
+ /// <item>
+ /// <term>CONNECT_E_NOCONNECTION</term>
+ /// <description>
+ /// アクティブなシンクオブジェクトは存在しない。
+ /// </description>
+ /// </item>
+ /// </list>
+ /// </returns>
+ void UnadviseSink(
+ [In, MarshalAs(UnmanagedType.Interface)] object i_unknown
+ );
+
+
+ //====================================================================
+
+
+ /// <summary>
+ /// TSFマネージャがドキュメントを修正するためにドキュメントロックを提供す
+ /// るためにTSFマネージャによって呼び出される。このメソッドはドキュメント
+ /// ロックを作成するために ITextStoreACPSink::OnLockGranted() メソッドを呼
+ /// び出さなければいけない。
+ /// </summary>
+ ///
+ /// <param name="i_lockFlags">ロック要求のタイプを指定する。
+ /// <list type="table">
+ /// <listheader>
+ /// <term>フラグ</term>
+ /// <description>意味</description>
+ /// </listheader>
+ /// <item>
+ /// <term>TS_LF_READ</term>
+ /// <description>
+ /// ドキュメントは読取専用ロックで、修正はできない。
+ /// </description>
+ /// </item>
+ /// <item>
+ /// <term>TS_LF_READWRITE</term>
+ /// <description>
+ /// ドキュメントは読み書き両用で、修正できる。
+ /// </description>
+ /// </item>
+ /// <item>
+ /// <term>TS_LF_SYNC</term>
+ /// <description>
+ /// 他のフラグと一緒に指定された場合は、ドキュメントは同期ロックである。
+ /// </description>
+ /// </item>
+ /// </list>
+ /// </param>
+ ///
+ /// <param name="o_sessionResult">
+ /// ロックリクエストが同期ならば、ロック要求の結果である
+ /// ITextStoreACP::OnLockGranted() メソッドからの HRESULT を受け取る。
+ ///
+ /// <para>
+ /// ロック要求が非同期で結果が TS_S_ASYNC の場合、ドキュメントは非同期ロッ
+ /// クを受け取る。ロック要求が非同期で結果が TS_E_SYNCHRONOUS の場合は、ド
+ /// キュメントは非同期でロックできない。
+ /// </para>
+ /// </param>
+ ///
+ /// <remark>
+ /// このメソッドはドキュメントをロックするために
+ /// ITextStoreACPSink::OnLockGranted() メソッドを使用する。アプリケーショ
+ /// ンは ITextStoreACP::RequestLock() メソッド内でドキュメントを修正したり
+ /// ITextStoreACPSink::OnTextChange() メソッドを使用して変更通知を送ったり
+ /// してはいけない。もし、アプリケーションがレポートするための変更をペンディ
+ /// ングしているなら、アプリケーションは非同期ロック要求のみを返さなければ
+ /// いけない。
+ ///
+ /// <para>
+ /// アプリケーションは複数の RequestLock() メソッド呼び出しをキューに入
+ /// れることを試みてはいけない、なぜなら、アプリケーションは一つのコール
+ /// バックのみを要求されるから。もし、呼び出し元がいくつかの読取要求や一
+ /// つ以上の書き込み要求を作ったとしても、コールバックは書き込みアクセス
+ /// でなければいけない。
+ /// </para>
+ ///
+ /// <para>
+ /// 成功は、非同期ロックの要求にとって代わって同期ロックを要求する。失敗は
+ /// (複数の)非同期ロックの要求を同期ロックに代えることができない。実装は、
+ /// 要求が存在すれば発行済みの非同期要求をまだ満たしていなければいけない。
+ /// </para>
+ ///
+ /// <para>
+ /// もしロックが ITextStoreACP::RequestLock() メソッドが返る前に認められ
+ /// たなら、o_sessionResult パラメータは
+ /// ITextStoreACPSink::OnLockGranted() メソッドから返された HRESULT を受
+ /// け取る。もし、呼び出しが成功したが、ロックは後で認められるなら、
+ /// o_sessionResult パラメータは TS_S_ASYNC フラグを受け取る。もし、
+ /// RequestLock() が S_OK 以外を返した場合は o_sessionResult パラメー
+ /// ターは無視すべきである。
+ /// </para>
+ ///
+ /// <para>
+ /// ドキュメントが既にロックされている状態で、同期ロック要求の場合は
+ /// o_sessionResult に TS_E_SYNCHRONOUS をセットして S_OK を返す。
+ /// これは同期要求は認められなかったことを示す。
+ /// ドキュメントが既にロックされている状態で、非同期ロック要求の場合は、
+ /// アプリケーションはリクエストをキューに追加し、 o_sessionResult に
+ /// TS_S_ASYNC をセットし、S_OK を返す。ドキュメントが有効になったとき、
+ /// アプリケーションはリクエストをキューから削除して、 OnLockGranted()
+ /// を呼び出す。このロックリクエストのキューは任意である。アプリケーション
+ /// がサポートしなければいけないシナリオが一つある。ドキュメントが読み取
+ /// り専用ロックで、アプリケーションが OnLockGranted の内部で新しい読み
+ /// 書き両用の非同期ロック要求を出した場合、RequestLock は再帰呼び出しを
+ /// 引き起こす。アプリケーションは OnLockGranted() を TS_LF_READWRITE と
+ /// 共に呼び出してリクエストをアップグレードすべきである。
+ /// </para>
+ ///
+ /// <para>
+ /// 呼び出し元が読み取り専用ロックを維持している場合を除いて、呼び出し元
+ /// はこのメソッドを再帰的に呼び出してはいけない。この場合、メソッドは非
+ /// 同期に書き込み要求を尋ねるために再帰的に呼び出すことができる。書き込
+ /// みロックは読取専用ロックが終わった後に認められるだろう。
+ /// </para>
+ ///
+ /// <para>
+ /// ロックの強要:アプリケーションは適切なロックのタイプが存在するかどうか
+ /// ドキュメントへのアクセスを許す前に確かめなければいけない。例えば、
+ /// GetText() を処理することを許可する前に少なくとも読み取り専用ロックが
+ /// 行われているかどうか確かめなければいけない。もし、適切なロックがされ
+ /// ていなければ、アプリケーションは TF_E_NOLOCK を返さなければいけない。
+ /// </para>
+ /// </remark>
+ void RequestLock(
+ [In] LockFlags i_lockFlags,
+ [Out, MarshalAs(UnmanagedType.Error)] out int o_sessionResult
+ );
+
+
+ //====================================================================
+
+
+ /// <summary>
+ /// ドキュメントのステータスを取得するために使用される。ドキュメントのステー
+ /// タスは TS_STATUS 構造体を通して返される。
+ /// </summary>
+ ///
+ /// <param name="o_documentStatus">
+ /// ドキュメントのステータスを含む TS_STATUS 構造体を受け取る。NULL 不可。
+ /// </param>
+ void GetStatus(
+ [Out] out TS_STATUS o_documentStatus
+ );
+
+
+ //====================================================================
+
+
+ /// <summary>
+ /// ドキュメントが選択や挿入を許可することができるかどうかを決めるためにア
+ /// プリケーションから呼ばれる。
+ ///
+ /// <para>
+ /// QueryInsert() メソッドは指定した開始位置と終了位置が有効かどうかを決
+ /// める。編集を実行する前にドキュメントの編集を調整するために使用される。
+ /// メソッドはドキュメントの範囲外の値を返してはいけない。
+ /// </para>
+ /// </summary>
+ ///
+ /// <param name="i_startIndex">
+ /// テキストを挿入する開始位置。
+ /// </param>
+ ///
+ /// <param name="i_endIndex">
+ /// テキストを挿入する終了位置。選択中のテキストを置換する代わりに指定した
+ /// 位置へテキストを挿入する場合は、この値は i_startIndex と同じになる。
+ /// </param>
+ ///
+ /// <param name="i_length">
+ /// 置換するテキストの長さ。
+ /// </param>
+ ///
+ /// <param name="o_startIndex">
+ /// 挿入されるテキストの新しい開始位置を返す。このパラメータが NULL の場合、
+ /// テキストは指定された位置に挿入できない。この値はドキュメントの範囲外を
+ /// 指定できない。
+ /// </param>
+ ///
+ /// <param name="o_endIndex">
+ /// 挿入されるテキストの新しい終了位置を返す。このパラメータが NULL の場合、
+ /// テキストは指定された位置に挿入できない。この値はドキュメントの範囲外を
+ /// 指定できない
+ /// </param>
+ ///
+ /// <remark>
+ /// o_startIndex と o_endIndex の値は、アプリケーションがどのように
+ /// ドキュメントにテキストを挿入するかに依存している。もし、o_startIndex
+ /// と o_endIndex が i_startIndex と同じならば、カーソルは挿入後のテキ
+ /// ストの始まりにある。
+ /// もし、o_startIndex と o_endIndex が i_endIndex と同じならば、
+ /// カーソルは挿入後のテキストの終わりにある。o_startIndex と
+ /// o_endIndex の差が挿入されたテキストの長さと同じなら、挿入後、挿入さ
+ /// れたテキストはハイライトされている。
+ /// </remark>
+ void QueryInsert(
+ [In] int i_startIndex,
+ [In] int i_endIndex,
+ [In] int i_length,
+ [Out] out int o_startIndex,
+ [Out] out int o_endIndex
+ );
+
+
+ //====================================================================
+
+
+ /// <summary>
+ /// ドキュメント内のテキスト選択の位置を返す。このメソッドは複数テキスト選
+ /// 択をサポートする。呼び出し元はこのメソッドを呼び出す前にドキュメントに
+ /// 読取専用ロックをかけておかなければいけない。
+ /// </summary>
+ ///
+ /// <param name="i_index">
+ /// 処理を開始するテキスト選択を指定する。もし、TS_DEFAULT_SELECTION(-1)
+ /// 定数が指定された場合、入力選択は処理を開始する。
+ /// </param>
+ ///
+ /// <param name="i_selectionBufferLength">
+ /// 返す選択の最大数を指定する。
+ /// </param>
+ ///
+ /// <param name="o_selections">
+ /// 選択されたテキストのスタイル、開始位置、終了位置を受け取る。これらの値
+ /// は TS_SELECTION_ACP 構造体に出力される。
+ /// </param>
+ ///
+ /// <param name="o_fetchedLength">
+ /// o_selections に返された構造体の数を受け取る。
+ /// </param>
+ void GetSelection(
+ [In] int i_index,
+ [In] int i_selectionBufferLength,
+ [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)] TS_SELECTION_ACP[] o_selections,
+ out int o_fetchedLength
+ );
+
+
+ //====================================================================
+
+
+ /// <summary>
+ /// ドキュメント内のテキストを選択する。アプリケーションはこのメソッドを呼
+ /// ぶ前に読み書き両用ロックをかけなればいけない。
+ /// </summary>
+ ///
+ /// <param name="i_count">
+ /// i_selections 内のテキスト選択の数を指定する。
+ /// </param>
+ ///
+ /// <param name="i_selections">
+ /// TS_SELECTION_ACP 構造体を通して選択されたテキストのスタイル、開始位置、
+ /// 終了位置を指定する。
+ ///
+ /// <para>
+ /// 開始位置と終了位置が同じ場合は、指定した位置にキャレットを配置する。
+ /// ドキュメント内に一度に一つのみキャレットを配置できる。
+ /// </para>
+ /// </param>
+ void SetSelection(
+ [In] int i_count,
+ [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] TS_SELECTION_ACP[] i_selections
+ );
+
+
+ //====================================================================
+
+
+ /// <summary>
+ /// 指定された位置のテキストに関する情報を返す。このメソッドは可視状態およ
+ /// び不可視状態のテキストや埋め込まれたデータがテキストに関連付けられてい
+ /// るかどうかを返す。
+ /// </summary>
+ ///
+ /// <param name="i_startIndex">
+ /// 開始位置を指定する。
+ /// </param>
+ ///
+ /// <param name="i_endIndex">
+ /// 終了位置を指定する。このパラメータが -1 の場合はテキストストア内の全て
+ /// のテキストを返す。
+ /// </param>
+ ///
+ /// <param name="o_plainText">
+ /// プレインテキストデータを受け取るバッファを指定する。このパラメータが
+ /// NULL の場合は、 cchPlainReq は 0 でなければいけない。
+ /// </param>
+ ///
+ /// <param name="i_plainTextLength">
+ /// プレインテキストの文字数を指定する。
+ /// </param>
+ ///
+ /// <param name="o_plainTextLength">
+ /// プレインテキストバッファへコピーされた文字数を受け取る。このパラメータ
+ /// は NULL を指定できない。値が必要でないときに使用する。
+ /// </param>
+ ///
+ /// <param name="o_runInfos">
+ /// TS_RUNINFO 構造体の配列を受け取る。i_runInfoLength が 0 の場合は NULL。
+ /// </param>
+ ///
+ /// <param name="i_runInfoLength">
+ /// o_runInfos の許容数を指定する。
+ /// </param>
+ ///
+ /// <param name="o_runInfoLength">
+ /// o_runInfosに書き込まれた数を受け取る。このパラメータは NULL を指定で
+ /// きない。
+ /// </param>
+ ///
+ /// <param name="o_nextUnreadCharPos">
+ /// 次の読み込んでいない文字の位置を受け取る。このパラメータは NULL を指定
+ /// できない。
+ /// </param>
+ ///
+ /// <remark>
+ /// このメソッドを使う呼び出し元は ITextStoreACP::RequestLock() メソッドを
+ /// 呼ぶことでドキュメントに読取専用ロックをかけなければいけない。ロックし
+ /// ていない場合はメソッドは失敗し、TF_E_NOLOCK を返す。
+ ///
+ /// <para>
+ /// アプリケーションはまた、内部の理由によって戻り値を切り取ることができる。
+ /// 呼び出し元は必須の戻り値を取得するために戻された文字やテキストのラン
+ /// 数を注意深く調査しなければいけない。戻り値が不完全ならば、戻り値が完
+ /// 全なものとなるまでメソッドを繰り返し呼び出さなければいけない。
+ /// </para>
+ ///
+ /// <para>
+ /// 呼び出し元は i_runInfoLength パラメータを0にセットし、o_runInfos
+ /// パラメータを NULL にすることで、プレインテキストを要求できる。しかし
+ /// ながら、呼び出し元は o_plainTextLength に非 NULL の有効な値を提
+ /// 供しなければならない、パラメータを使用しないとしても。
+ /// </para>
+ ///
+ /// <para>
+ /// i_endIndex が -1 の場合、ストリームの最後がセットされたものとして処
+ /// 理しなければいけない。その他の場合、0 以上でなければいけない。
+ /// </para>
+ ///
+ /// <para>
+ /// メソッドを抜ける際に、o_nextUnreadCharPos は戻り値によって参照
+ /// されていないストリーム内の次の文字の位置をセットされていなければなら
+ /// ない。呼び出し元はこれを使用して複数の GetText() 呼び出しで素早くテ
+ /// キストをスキャンする。
+ /// </para>
+ ///
+ /// </remark>
+ void GetText(
+ [In] int i_startIndex,
+ [In] int i_endIndex,
+ [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=3)] char[] o_plainText,
+ [In] int i_plainTextLength,
+ [Out] out int o_plainTextLength,
+ [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=6)] TS_RUNINFO[] o_runInfos,
+ [In] int i_runInfoLength,
+ [Out] out int o_runInfoLength,
+ [Out] out int o_nextUnreadCharPos
+ );
+
+
+ //====================================================================
+
+
+ /// <summary>
+ /// SetText() メソッドは与えられた文字位置のテキスト選択をセットする。
+ /// </summary>
+ ///
+ /// <param name="i_flags">
+ /// TS_ST_CORRECTION がセットされている場合、テキストは既存のコンテントの
+ /// 移動(訂正)であり、特別なテキストマークアップ情報(メタデータ)が保持され
+ /// る - .wav ファイルデータや言語IDなど。クライアントは保持されるマークアッ
+ /// プ情報のタイプを定義する。
+ /// </param>
+ ///
+ /// <param name="i_startIndex">
+ /// 置換するテキストの開始位置を指定する。
+ /// </param>
+ ///
+ /// <param name="i_endIndex">
+ /// 置換するテキストの終了位置を指定する。-1 の場合は無視される。
+ /// </param>
+ ///
+ /// <param name="i_text">
+ /// 置き換えるテキストへのポインタを指定する。テキストの文字数は i_length
+ /// パラメータによって指定されるため、テキスト文字列は NULL 終端文字を持っ
+ /// ていない。
+ /// </param>
+ ///
+ /// <param name="i_length">
+ /// i_text の文字数。
+ /// </param>
+ ///
+ /// <param name="o_textChange">
+ /// 次のデータをもつ TS_TEXTCHANGE 構造体へのポインタ。
+ ///
+ /// <list type="table">
+ /// <listheader>
+ /// <term>メンバー名</term>
+ /// <description>意味</description>
+ /// </listheader>
+ /// <item>
+ /// <term>acpStart</term>
+ /// <description>
+ /// テキストがドキュメントに挿入される前の開始位置。
+ /// </description>
+ /// </item>
+ /// <item>
+ /// <term>acpOldEnd</term>
+ /// <description>
+ /// テキストがドキュメントに挿入される前の終了位置。値は挿入位置であ
+ /// る acpStart と同じ値となる。もし、acpStart と異なっている場合は、
+ /// テキストはテキストの挿入の前に選択されていた。
+ /// </description>
+ /// </item>
+ /// <item>
+ /// <term>acpNewEnd</term>
+ /// <description>
+ /// テキストを挿入した後の終了位置。
+ /// </description>
+ /// </item>
+ /// </list>
+ /// </param>
+ void SetText(
+ [In] SetTextFlags i_flags,
+ [In] int i_startIndex,
+ [In] int i_endIndex,
+ [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=4)] char[] i_text,
+ [In] int i_length,
+ [Out] out TS_TEXTCHANGE o_textChange
+ );
+
+
+ //====================================================================
+
+
+ /// <summary>
+ /// 指定されたテキスト文字列について Formatted Text データを返す。呼び
+ /// 出し元はこのメソッドを呼ぶ前に読み書き両用ロックをかけなければいけない。
+ /// </summary>
+ void GetFormattedText(
+ [In] int i_start,
+ [In] int i_end,
+ [Out, MarshalAs(UnmanagedType.Interface)] out object o_obj
+ );
+
+
+ //====================================================================
+
+
+ /// <summary>
+ /// 組み込みオブジェクトを取得する。
+ /// </summary>
+ void GetEmbedded(
+ [In] int i_position,
+ [In] ref Guid i_guidService,
+ [In] ref Guid i_riid,
+ [Out, MarshalAs(UnmanagedType.Interface)] out object o_obj
+ );
+
+
+ //====================================================================
+
+
+ /// <summary>
+ /// 組み込みオブジェクトを挿入できるか問い合わせる。
+ /// </summary>
+ void QueryInsertEmbedded(
+ [In] ref Guid i_guidService,
+ [In] int i_formatEtc,
+ [Out, MarshalAs(UnmanagedType.Bool)] out bool o_insertable
+ );
+
+
+ //====================================================================
+
+
+ /// <summary>
+ /// 組み込みオブジェクトを挿入する。
+ /// </summary>
+ void InsertEmbedded(
+ [In] InsertEmbeddedFlags i_flags,
+ [In] int i_start,
+ [In] int i_end,
+ [In, MarshalAs(UnmanagedType.Interface)] object i_obj,
+ [Out] out TS_TEXTCHANGE o_textChange
+ );
+
+
+ //====================================================================
+
+
+ /// <summary>
+ /// ITextStoreACP::InsertTextAtSelection() メソッドは挿入位置や選択位置に
+ /// テキストを挿入する。呼び出し元はテキストを挿入する前に読み書き両用ロッ
+ /// クをかけていなければならない。
+ /// </summary>
+ ///
+ /// <param name="i_flags">
+ /// o_startIndex, o_endIndex パラメータと TS_TEXTCHANGE 構造体のどち
+ /// らがテキストの挿入の結果を含んでいるかを示す。
+ /// TF_IAS_NOQUERY と TF_IAS_QUERYONLY フラグは同時に指定できない。
+ ///
+ /// <list type="table">
+ /// <listheader>
+ /// <term>値</term>
+ /// <description>意味</description>
+ /// </listheader>
+ /// <item>
+ /// <term>0</term>
+ /// <description>
+ /// テキスト挿入が発生し、o_startIndex と o_endIndex パラメータ
+ /// はテキスト挿入の結果を含んでいる。TS_TEXTCHANGE 構造体は 0 で埋め
+ /// られていなければならない。
+ /// </description>
+ /// </item>
+ /// <item>
+ /// <term>TF_IAS_NOQUERY</term>
+ /// <description>
+ /// テキストは挿入され、o_startIndex と o_endIndex パラメータ
+ /// の値は NULL にでき、TS_TEXTCHANGE 構造体は埋められなければいけない。
+ /// このフラグはテキスト挿入の結果を見るために使用する。
+ /// </description>
+ /// </item>
+ /// <item>
+ /// <term>TF_IAS_QUERYONLY</term>
+ /// <description>
+ /// テキストは挿入されず、o_startIndex と o_endIndex パラメータ
+ /// はテキスト挿入の結果を含む。これらのパラメータの値は、アプリケー
+ /// ションがどのようにドキュメントにテキストを挿入するかに依存している。
+ /// 詳しくは注意を見ること。このフラグは実際にはテキストを挿入しない
+ /// でテキスト挿入の結果を見るために使用する。このフラグを使う場合は
+ /// TS_TEXTCHANGE 構造体を埋める必要はない。
+ /// </description>
+ /// </item>
+ /// </list>
+ /// </param>
+ ///
+ /// <param name="i_text">
+ /// 挿入する文字列へのポインタ。NULL 終端にすることができる。
+ /// </param>
+ ///
+ /// <param name="i_length">
+ /// テキスト長を指定する。
+ /// </param>
+ ///
+ /// <param name="o_startIndex">
+ /// テキスト挿入が発生した場所の開始位置へのポインタ。
+ /// </param>
+ ///
+ /// <param name="o_endIndex">
+ /// テキスト挿入が発生した場所の終了位置へのポインタ。このパラメータは挿入
+ /// の場合、o_startIndex パラメータと同じ値になる。
+ /// </param>
+ ///
+ /// <param name="o_textChange">
+ /// 次のメンバーを持つ TS_TEXTCHANGE 構造体へのポインタ。
+ ///
+ /// <list type="table">
+ /// <listheader>
+ /// <term>メンバー名</term>
+ /// <description>意味</description>
+ /// </listheader>
+ /// <item>
+ /// <term>acpStart</term>
+ /// <description>
+ /// テキストがドキュメントに挿入される前の開始位置。
+ /// </description>
+ /// </item>
+ /// <item>
+ /// <term>acpOldEnd</term>
+ /// <description>
+ /// テキストがドキュメントに挿入される前の終了位置。値は挿入位置であ
+ /// る acpStart と同じ値となる。もし、acpStart と異なっている場合は、
+ /// テキストはテキストの挿入の前に選択されていた。
+ /// </description>
+ /// </item>
+ /// <item>
+ /// <term>acpNewEnd</term>
+ /// <description>
+ /// テキストを挿入した後の終了位置。
+ /// </description>
+ /// </item>
+ /// </list>
+ /// </param>
+ ///
+ /// <remark>
+ /// o_startIndex と o_endIndex パラメータの値はアプリケーションがド
+ /// キュメントにどのようにテキストを挿入したかによる。たとえば、アプリケー
+ /// ションがテキストを挿入後、挿入したテキストの開始位置にカーソルをセット
+ /// したなら、o_startIndex と o_endIndex パラメータは TS_TEXTCHANGE
+ /// 構造体の acpStart メンバと同じ値になる。
+ /// <para>
+ /// アプリケーションは ITextStoreACPSink::OnTextChange() メソッドをこの
+ /// メソッド内で呼ぶべきではない。
+ /// </para>
+ /// </remark>
+ void InsertTextAtSelection(
+ [In] InsertAtSelectionFlags i_flags,
+ [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=2)] char[] i_text,
+ [In] int i_length,
+ [Out] out int o_startIndex,
+ [Out] out int o_endIndex,
+ [Out] out TS_TEXTCHANGE o_textChange
+ );
+
+
+ //====================================================================
+
+
+ /// <summary>
+ /// 選択位置もしくは挿入位置に組み込みオブジェクトを挿入する。
+ /// </summary>
+ void InsertEmbeddedAtSelection(
+ InsertAtSelectionFlags flags,
+ [MarshalAs(UnmanagedType.Interface)] object obj,
+ out int start,
+ out int end,
+ out TS_TEXTCHANGE change
+ );
+
+
+ //====================================================================
+
+
+ /// <summary>
+ /// ドキュメントのサポートされている属性を取得する。
+ /// </summary>
+ ///
+ /// <param name="i_flags">
+ /// 後続の ITextStoreACP::RetrieveRequestedAttrs() メソッド呼び出し
+ /// がサポートされる属性を含むかどうかを指定する。もし、
+ /// TS_ATTR_FIND_WANT_VALUE フラグが指定されたなら、後続の
+ /// ITextStoreAcp::RetrieveRequestedAttrs() 呼び出しの後に
+ /// TS_ATTRVAL 構造体のそれらはデフォルト属性の値になる。もし、他の
+ /// フラグが指定されたなら属性がサポートされているかどうか確認する
+ /// だけで、 TS_ATTRVAL 構造体の varValue メンバには VT_EMPTY がセッ
+ /// トされる。
+ /// </param>
+ ///
+ /// <param name="i_length">
+ /// 取得するサポートされる属性の数を指定する。
+ /// </param>
+ ///
+ /// <param name="i_filterAttributes">
+ /// 確認するための属性が指定された TS_ATTRID データタイプへのポイン
+ /// タ。メソッドは TS_ATTRID によって指定された属性のみを返す(他の
+ /// 属性をサポートしていたとしても)。
+ /// </param>
+ void RequestSupportedAttrs(
+ [In] AttributeFlags i_flags,
+ [In] int i_length,
+ [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)] Guid[] i_filterAttributes
+ );
+
+
+ //====================================================================
+
+
+ /// <summary>
+ /// 指定した文字位置の属性を取得する。
+ /// </summary>
+ ///
+ /// <param name="i_position">
+ /// ドキュメント内の開始位置。
+ /// </param>
+ ///
+ /// <param name="i_length">
+ /// 取得する属性の数。
+ /// </param>
+ ///
+ /// <param name="i_filterAttributes">
+ /// 確認するための属性が指定された TS_ATTRID データタイプへのポインタ。
+ /// </param>
+ ///
+ /// <param name="i_flags">
+ /// 0 でなければいけない。
+ /// </param>
+ void RequestAttrsAtPosition(
+ [In] int i_position,
+ [In] int i_length,
+ [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)] Guid[] i_filterAttributes,
+ [In] AttributeFlags i_flags
+ );
+
+
+ //====================================================================
+
+
+ /// <summary>
+ /// 指定した文字位置の属性のリストを取得する。
+ /// </summary>
+ /// <param name="i_position">ドキュメント内の開始位置。</param>
+ ///
+ /// <param name="i_length">取得する属性の数。</param>
+ ///
+ /// <param name="i_filterAttributes">
+ /// RetrieveRequestedAttr() メソッドを呼ぶための属性を指定する。
+ /// このパラメータがセットされていなければメソッドは指定された位置で
+ /// 始まる属性を返す。他の指定可能な値は以下のとおり。
+ /// <list type="table">
+ /// <listheader>
+ /// <term>値</term>
+ /// <description>意味</description>
+ /// </listheader>
+ /// <item>
+ /// <term>TS_ATTR_FIND_WANT_END</term>
+ /// <description>
+ /// 指定した文字位置で終了する属性を取得する。
+ /// </description>
+ /// </item>
+ /// <item>
+ /// <term>TS_ATTR_FIND_WANT_VALUD</term>
+ /// <description>
+ /// 属性の取得に加えて属性の値を取得する。属性値は
+ /// ITextStoreACP::RetrieveRequestedAttrs() メソッド呼び出しの
+ /// TS_ATTRVAL 構造体の varValue メンバにセットされる。
+ /// </description>
+ /// </item>
+ /// </list>
+ /// </param>
+ /// <param name="i_flags"></param>
+ void RequestAttrsTransitioningAtPosition(
+ [In] int i_position,
+ [In] int i_length,
+ [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)] Guid[] i_filterAttributes,
+ [In] AttributeFlags i_flags
+ );
+
+
+ //====================================================================
+
+
+ /// <summary>
+ /// 属性変更が発生している場所の文字位置を決定する。
+ /// </summary>
+ /// <param name="i_start">属性変更を検索する開始位置を指定する。</param>
+ /// <param name="i_halt">属性変更を検索する終了位置を指定する。</param>
+ /// <param name="i_length">チェックするための属性の数を指定する。</param>
+ /// <param name="i_filterAttributes">
+ /// チェックするための属性を指定する TS_ATTRID データタイプへのポインタ。
+ /// </param>
+ /// <param name="i_flags">
+ /// 検索方向を指定する。デフォルトではフォワード検索。
+ /// <list type="table">
+ /// <listheader>
+ /// <term>フラグ</term>
+ /// <description>意味</description>
+ /// </listheader>
+ ///
+ /// <item>
+ /// <term>TS_ATTR_FIND_BACKWARDS</term>
+ /// <description>バックワード検索。</description>
+ /// </item>
+ /// <item>
+ /// <term>tS_ATTR_FIND_WANT_OFFSET</term>
+ /// <description>
+ /// o_foundOffset パラメータは i_start からの属性変更のオフセットを受け取る。
+ /// </description>
+ /// </item>
+ /// </list>
+ /// </param>
+ /// <param name="o_nextIndex">
+ /// 属性変更をチェックする次の文字位置を受け取る。
+ /// </param>
+ /// <param name="o_found">
+ /// 属性変更が発見された場合に TRUE を受け取る。そのほかは FALSE を受け取る。
+ /// </param>
+ /// <param name="o_foundOffset">
+ /// 属性変更の開始位置(文字位置ではない)を受け取る。TS_ATTR_FIND_WANT_OFFSET
+ /// フラグが dwFlags にセットされていれば、 acpStart からのオフセットを受け取る。
+ /// </param>
+ void FindNextAttrTransition(
+ [In] int i_start,
+ [In] int i_halt,
+ [In] int i_length,
+ [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=2)] Guid[] i_filterAttributes,
+ [In] AttributeFlags i_flags,
+ [Out] out int o_nextIndex,
+ [Out, MarshalAs(UnmanagedType.Bool)] out bool o_found,
+ [Out] out int o_foundOffset
+ );
+
+
+ //====================================================================
+
+
+ /// <summary>
+ /// ITextStoreACP::RequestAttrsAtPosition(),
+ /// TextStoreACP::RequestAttrsTransitioningAtPosition(),
+ /// ITextStoreACP::RequestSupportedAttrs() によって取得された属性を返す。
+ /// </summary>
+ /// <param name="i_length">取得するサポートされる属性の数を指定する。</param>
+ /// <param name="o_attributeVals">
+ /// サポートされる属性を受け取る TS_ATTRVAL 構造体へのポインタ。この
+ /// 構造体のメンバはメソッド呼び出しの i_flags パラメータによる。
+ /// </param>
+ /// <param name="o_fetchedLength">サポートされる属性の数を受け取る。</param>
+ void RetrieveRequestedAttrs(
+ [In] int i_length,
+ [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] TS_ATTRVAL[] o_attributeVals,
+ [Out] out int o_fetchedLength
+ );
+
+
+ //====================================================================
+
+
+ /// <summary>ドキュメント内の文字数を取得する。</summary>
+ ///
+ /// <param name="o_length">最後の文字位置 + 1 を受け取る。</param>
+ void GetEndACP(
+ [Out] out int o_length
+ );
+
+
+ //====================================================================
+
+
+ /// <summary>
+ /// 現在のアクティブビューの TsViewCookie データタイプを返す。
+ /// </summary>
+ void GetActiveView(
+ [Out] out int o_viewCookie
+ );
+
+
+ //====================================================================
+
+
+ /// <summary>
+ /// スクリーン座標をアプリケーション文字位置に変換する。
+ /// </summary>
+ /// <param name="i_viewCookie">コンテキストビューを指定する。</param>
+ /// <param name="i_point">スクリーン座標の位置を示す POINT 構造体へのポインタ。</param>
+ /// <param name="i_flags">
+ /// 文字バウンディングボックスからの相対位置に基づくスクリーン座標を
+ /// 戻すための文字位置を指定する。デフォルトでは、返される文字位置は
+ /// スクリーン座標を含む文字バウンディングボックスをもつ文字の位置で
+ /// ある。もし、ポイントが文字を囲むボックス外ならメソッドは NULL ま
+ /// たは TF_E_INVALIDPOINT を返す。その他のフラグは以下のとおり。
+ /// <list>
+ /// <listheader>
+ /// <term>フラグ</term>
+ /// <description>意味</description>
+ /// </listheader>
+ ///
+ /// <item>
+ /// <term>GXFPF_ROUND_NEAREST</term>
+ /// <description>
+ /// もし、スクリーン座標での点が文字バウンディングボックスの中
+ /// に含まれている場合、返される文字位置は ptScreen にもっとも
+ /// 近いバウンディングの端を持つ文字の位置である。
+ /// </description>
+ /// </item>
+ /// <item>
+ /// <term>GXFPF_NEAREST</term>
+ /// <description>
+ /// もし、スクリーン座標での点が文字バウンディングボックスに含
+ /// まれていないなら、もっとも近い文字位置が返される。
+ /// <para>
+ /// http://msdn.microsoft.com/en-us/library/ms538418(v=VS.85).aspx の Remarks 参照。
+ /// </para>
+ /// </description>
+ /// </item>
+ /// </list>
+ /// </param>
+ /// <param name="o_index"></param>
+ void GetACPFromPoint(
+ [In] int i_viewCookie,
+ [In] ref POINT i_point,
+ [In] GetPositionFromPointFlags i_flags,
+ [Out] out int o_index
+ );
+
+
+ //====================================================================
+
+
+ /// <summary>
+ /// 指定した文字位置のスクリーン座標を返す。読み取り専用ロックをかけて呼ば
+ /// なければいけない。
+ /// </summary>
+ ///
+ /// <param name="i_viewCookie">
+ /// コンテキストビューを指定する。
+ /// </param>
+ ///
+ /// <param name="i_startIndex">
+ /// ドキュメント内の取得するテキストの開始位置を指定する。
+ /// </param>
+ ///
+ /// <param name="i_endIndex">
+ /// ドキュメント内の取得するテキストの終了位置を指定する。
+ /// </param>
+ ///
+ /// <param name="o_rect">
+ /// 指定した文字位置のテキストのスクリーン座標でのバウンディングボックスを
+ /// 受け取る。
+ /// </param>
+ ///
+ /// <param name="o_isClipped">
+ /// バウンディングボックスがクリッピングされたかどうかを受け取る。TRUE の
+ /// 場合、バウンディングボックスはクリップされたテキストを含み、完全な要求
+ /// されたテキストの範囲を含んでいない。バウンディングボックスは要求された
+ /// 範囲が可視状態でないため、クリップされた。
+ /// </param>
+ ///
+ /// <remark>
+ /// ドキュメントウィンドウが最小化されていたり、指定されたテキストが現在表
+ /// 示されていないならば、メソッドは S_OK を返して o_rect パラメータに
+ /// { 0, 0, 0, 0 }をセットしなければいけない。
+ ///
+ /// <para>
+ /// TSF マネージャー側から変換候補ウィンドウの表示位置を割り出すために使用
+ /// される。
+ /// </para>
+ /// </remark>
+ void GetTextExt(
+ [In] int i_viewCookie,
+ [In] int i_startIndex,
+ [In] int i_endIndex,
+ [Out] out RECT o_rect,
+ [MarshalAs(UnmanagedType.Bool)] out bool o_isClipped
+ );
+
+
+ //====================================================================
+
+
+ /// <summary>
+ /// テキストストリームが描画されるディスプレイサーフェイスのスクリーン座標
+ /// でのバウンディングボックスを取得する。
+ /// </summary>
+ ///
+ /// <remark>
+ /// ドキュメントウィンドウが最小化されていたり、指定されたテキストが現在表
+ /// 示されていないならば、メソッドは S_OK を返して o_rect パラメータに
+ /// { 0, 0, 0, 0 }をセットしなければいけない。
+ /// </remark>
+ void GetScreenExt(
+ [In] int i_viewCookie,
+ [Out] out RECT o_rect
+ );
+
+
+ //====================================================================
+
+
+ /// <summary>
+ /// 現在のドキュメントに一致するウィンドウのハンドルを取得する。
+ /// </summary>
+ ///
+ /// <param name="i_viewCookie">
+ /// 現在のドキュメントに一致する TsViewCookie データタイプを指定する。
+ /// </param>
+ ///
+ /// <param name="o_hwnd">
+ /// 現在のドキュメントに一致するウィンドウのハンドルへのポインタを受け取る。
+ /// 一致するウィンドウがなければ NULL にできる。
+ /// </param>
+ ///
+ /// <remark>
+ /// ドキュメントはメモリにあるが、スクリーンに表示されていない場合や、ウィ
+ /// ンドウがないコントロールや、ウィンドウがないコントロールのオーナーのウィ
+ /// ンドウハンドルを認識しない場合、ドキュメントは一致するウィンドウハンド
+ /// ルをもてない。呼び出し元は メソッドが成功したとしても o_hwnd パラメー
+ /// タに非 NULL 値を受け取ると想定してはいけない。
+ /// </remark>
+ void GetWnd(
+ [In] int i_viewCookie,
+ [Out] out IntPtr o_hwnd
+ );
+ }
+#endif
+
+
+ //============================================================================
+ /// <summary>
+ /// テキストストア
+ /// </summary>
+ [ComImport,
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
+ Guid("f86ad89f-5fe4-4b8d-bb9f-ef3797a84f1f")
+ ]
+ public interface ITextStoreACP2
+ {
+ /// <summary>
+ /// ITextStoreACP2::AdviseSink
+ /// </summary>
+ /// <param name="i_riid"></param>
+ /// <param name="i_unknown"></param>
+ /// <param name="i_mask"></param>
+ void AdviseSink(
+ [In] ref Guid i_riid,
+ [In, MarshalAs(UnmanagedType.Interface)] object i_unknown,
+ [In] AdviseFlags i_mask
+ );
+ /// <summary>
+ /// ITextStoreACP2::UnadviseSink
+ /// </summary>
+ /// <param name="i_unknown"></param>
+ void UnadviseSink(
+ [In, MarshalAs(UnmanagedType.Interface)] object i_unknown
+ );
+ /// <summary>
+ /// ITextStoreACP2::RequestLock
+ /// </summary>
+ /// <param name="i_lockFlags"></param>
+ /// <param name="o_sessionResult"></param>
+ void RequestLock(
+ [In] LockFlags i_lockFlags,
+ [Out, MarshalAs(UnmanagedType.Error)] out int o_sessionResult
+ );
+ /// <summary>
+ /// ITextStoreACP2::GetStatus
+ /// </summary>
+ /// <param name="o_documentStatus"></param>
+ void GetStatus(
+ [Out] out TS_STATUS o_documentStatus
+ );
+ /// <summary>
+ /// ITextStoreACP2::QueryInsert
+ /// </summary>
+ /// <param name="i_startIndex"></param>
+ /// <param name="i_endIndex"></param>
+ /// <param name="i_length"></param>
+ /// <param name="o_startIndex"></param>
+ /// <param name="o_endIndex"></param>
+ void QueryInsert(
+ [In] int i_startIndex,
+ [In] int i_endIndex,
+ [In] int i_length,
+ [Out] out int o_startIndex,
+ [Out] out int o_endIndex
+ );
+ /// <summary>
+ /// ITextStoreACP2::GetSelection
+ /// </summary>
+ /// <param name="i_index"></param>
+ /// <param name="i_selectionBufferLength"></param>
+ /// <param name="o_selections"></param>
+ /// <param name="o_fetchedLength"></param>
+ void GetSelection(
+ [In] int i_index,
+ [In] int i_selectionBufferLength,
+ [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] TS_SELECTION_ACP[] o_selections,
+ out int o_fetchedLength
+ );
+ /// <summary>
+ /// ITextStoreACP2::SetSelection
+ /// </summary>
+ /// <param name="i_count"></param>
+ /// <param name="i_selections"></param>
+ void SetSelection(
+ [In] int i_count,
+ [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] TS_SELECTION_ACP[] i_selections
+ );
+ /// <summary>
+ /// ITextStoreACP2::GetText
+ /// </summary>
+ /// <param name="i_startIndex"></param>
+ /// <param name="i_endIndex"></param>
+ /// <param name="o_plainText"></param>
+ /// <param name="i_plainTextLength"></param>
+ /// <param name="o_plainTextLength"></param>
+ /// <param name="o_runInfos"></param>
+ /// <param name="i_runInfoLength"></param>
+ /// <param name="o_runInfoLength"></param>
+ /// <param name="o_nextUnreadCharPos"></param>
+ void GetText(
+ [In] int i_startIndex,
+ [In] int i_endIndex,
+ [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] char[] o_plainText,
+ [In] int i_plainTextLength,
+ [Out] out int o_plainTextLength,
+ [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 6)] TS_RUNINFO[] o_runInfos,
+ [In] int i_runInfoLength,
+ [Out] out int o_runInfoLength,
+ [Out] out int o_nextUnreadCharPos
+ );
+ /// <summary>
+ /// ITextStoreACP2::SetText
+ /// </summary>
+ /// <param name="i_flags"></param>
+ /// <param name="i_startIndex"></param>
+ /// <param name="i_endIndex"></param>
+ /// <param name="i_text"></param>
+ /// <param name="i_length"></param>
+ /// <param name="o_textChange"></param>
+ void SetText(
+ [In] SetTextFlags i_flags,
+ [In] int i_startIndex,
+ [In] int i_endIndex,
+ [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] char[] i_text,
+ [In] int i_length,
+ [Out] out TS_TEXTCHANGE o_textChange
+ );
+ /// <summary>
+ /// ITextStoreACP2::GetFormattedText
+ /// </summary>
+ /// <param name="i_start"></param>
+ /// <param name="i_end"></param>
+ /// <param name="o_obj"></param>
+ void GetFormattedText(
+ [In] int i_start,
+ [In] int i_end,
+ [Out, MarshalAs(UnmanagedType.Interface)] out object o_obj
+ );
+ /// <summary>
+ /// ITextStoreACP2::GetEmbedded
+ /// </summary>
+ /// <param name="i_position"></param>
+ /// <param name="i_guidService"></param>
+ /// <param name="i_riid"></param>
+ /// <param name="o_obj"></param>
+ void GetEmbedded(
+ [In] int i_position,
+ [In] ref Guid i_guidService,
+ [In] ref Guid i_riid,
+ [Out, MarshalAs(UnmanagedType.Interface)] out object o_obj
+ );
+ /// <summary>
+ /// ITextStoreACP2::QueryInsertEmbedded
+ /// </summary>
+ /// <param name="i_guidService"></param>
+ /// <param name="i_formatEtc"></param>
+ /// <param name="o_insertable"></param>
+ void QueryInsertEmbedded(
+ [In] ref Guid i_guidService,
+ [In] int i_formatEtc,
+ [Out, MarshalAs(UnmanagedType.Bool)] out bool o_insertable
+ );
+ /// <summary>
+ /// ITextStoreACP2::InsertEmbedded
+ /// </summary>
+ /// <param name="i_flags"></param>
+ /// <param name="i_start"></param>
+ /// <param name="i_end"></param>
+ /// <param name="i_obj"></param>
+ /// <param name="o_textChange"></param>
+ void InsertEmbedded(
+ [In] InsertEmbeddedFlags i_flags,
+ [In] int i_start,
+ [In] int i_end,
+ [In, MarshalAs(UnmanagedType.Interface)] object i_obj,
+ [Out] out TS_TEXTCHANGE o_textChange
+ );
+ /// <summary>
+ /// ITextStoreACP2::InsertTextAtSelection
+ /// </summary>
+ /// <param name="i_flags"></param>
+ /// <param name="i_text"></param>
+ /// <param name="i_length"></param>
+ /// <param name="o_startIndex"></param>
+ /// <param name="o_endIndex"></param>
+ /// <param name="o_textChange"></param>
+ void InsertTextAtSelection(
+ [In] InsertAtSelectionFlags i_flags,
+ [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] char[] i_text,
+ [In] int i_length,
+ [Out] out int o_startIndex,
+ [Out] out int o_endIndex,
+ [Out] out TS_TEXTCHANGE o_textChange
+ );
+ /// <summary>
+ /// ITextStoreACP2::InsertEmbeddedAtSelection
+ /// </summary>
+ /// <param name="flags"></param>
+ /// <param name="obj"></param>
+ /// <param name="start"></param>
+ /// <param name="end"></param>
+ /// <param name="change"></param>
+ void InsertEmbeddedAtSelection(
+ InsertAtSelectionFlags flags,
+ [MarshalAs(UnmanagedType.Interface)] object obj,
+ out int start,
+ out int end,
+ out TS_TEXTCHANGE change
+ );
+ /// <summary>
+ /// ITextStoreACP2::RequestSupportedAttrs
+ /// </summary>
+ /// <param name="i_flags"></param>
+ /// <param name="i_length"></param>
+ /// <param name="i_filterAttributes"></param>
+ void RequestSupportedAttrs(
+ [In] AttributeFlags i_flags,
+ [In] int i_length,
+ [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] Guid[] i_filterAttributes
+ );
+ /// <summary>
+ /// ITextStoreACP2::RequestAttrsAtPosition
+ /// </summary>
+ /// <param name="i_position"></param>
+ /// <param name="i_length"></param>
+ /// <param name="i_filterAttributes"></param>
+ /// <param name="i_flags"></param>
+ void RequestAttrsAtPosition(
+ [In] int i_position,
+ [In] int i_length,
+ [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] Guid[] i_filterAttributes,
+ [In] AttributeFlags i_flags
+ );
+ /// <summary>
+ /// ITextStoreACP2::RequestAttrsTransitioningAtPosition
+ /// </summary>
+ /// <param name="i_position"></param>
+ /// <param name="i_length"></param>
+ /// <param name="i_filterAttributes"></param>
+ /// <param name="i_flags"></param>
+ void RequestAttrsTransitioningAtPosition(
+ [In] int i_position,
+ [In] int i_length,
+ [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] Guid[] i_filterAttributes,
+ [In] AttributeFlags i_flags
+ );
+ /// <summary>
+ /// ITextStoreACP2::FindNextAttrTransition
+ /// </summary>
+ /// <param name="i_start"></param>
+ /// <param name="i_halt"></param>
+ /// <param name="i_length"></param>
+ /// <param name="i_filterAttributes"></param>
+ /// <param name="i_flags"></param>
+ /// <param name="o_nextIndex"></param>
+ /// <param name="o_found"></param>
+ /// <param name="o_foundOffset"></param>
+ void FindNextAttrTransition(
+ [In] int i_start,
+ [In] int i_halt,
+ [In] int i_length,
+ [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] Guid[] i_filterAttributes,
+ [In] AttributeFlags i_flags,
+ [Out] out int o_nextIndex,
+ [Out, MarshalAs(UnmanagedType.Bool)] out bool o_found,
+ [Out] out int o_foundOffset
+ );
+ /// <summary>
+ /// ITextStoreACP2::RetrieveRequestedAttrs
+ /// </summary>
+ /// <param name="i_length"></param>
+ /// <param name="o_attributeVals"></param>
+ /// <param name="o_fetchedLength"></param>
+ void RetrieveRequestedAttrs(
+ [In] int i_length,
+ [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] TS_ATTRVAL[] o_attributeVals,
+ [Out] out int o_fetchedLength
+ );
+ /// <summary>
+ /// ITextStoreACP2::GetEndACP
+ /// </summary>
+ /// <param name="o_length"></param>
+ void GetEndACP(
+ [Out] out int o_length
+ );
+ /// <summary>
+ /// ITextStoreACP2::GetActiveView
+ /// </summary>
+ /// <param name="o_viewCookie"></param>
+ void GetActiveView(
+ [Out] out int o_viewCookie
+ );
+ /// <summary>
+ /// ITextStoreACP2::GetACPFromPoint
+ /// </summary>
+ /// <param name="i_viewCookie"></param>
+ /// <param name="i_point"></param>
+ /// <param name="i_flags"></param>
+ /// <param name="o_index"></param>
+ void GetACPFromPoint(
+ [In] int i_viewCookie,
+ [In] ref POINT i_point,
+ [In] GetPositionFromPointFlags i_flags,
+ [Out] out int o_index
+ );
+ /// <summary>
+ /// ITextStoreACP2::GetTextExt
+ /// </summary>
+ /// <param name="i_viewCookie"></param>
+ /// <param name="i_startIndex"></param>
+ /// <param name="i_endIndex"></param>
+ /// <param name="o_rect"></param>
+ /// <param name="o_isClipped"></param>
+ void GetTextExt(
+ [In] int i_viewCookie,
+ [In] int i_startIndex,
+ [In] int i_endIndex,
+ [Out] out RECT o_rect,
+ [MarshalAs(UnmanagedType.Bool)] out bool o_isClipped
+ );
+ /// <summary>
+ /// ITextStoreACP2::GetScreenExt
+ /// </summary>
+ /// <param name="i_viewCookie"></param>
+ /// <param name="o_rect"></param>
+ void GetScreenExt(
+ [In] int i_viewCookie,
+ [Out] out RECT o_rect
+ );
+ }
+ //============================================================================
+
+
+ /// <summary>
+ /// コンポジション関連の通知を受け取るためにアプリケーション側で実装される
+ /// インターフェイス。
+ ///
+ /// <para>
+ /// ITfDocumentMgr::CreateContext() が呼ばれた時に TSF マネージャは
+ /// ITextStoreACP に対してこのインターフェイスを問い合わせる。
+ /// </para>
+ /// </summary>
+ [ComImport,
+ Guid("5F20AA40-B57A-4F34-96AB-3576F377CC79"),
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown)
+ ]
+ public interface ITfContextOwnerCompositionSink
+ {
+ /// <summary>
+ /// コンポジションが開始された時に TSF マネージャから呼ばれる。
+ /// </summary>
+ ///
+ /// <param name="i_view">
+ /// 新しいコンポジションを表す ITfCompositionView へのポインタ。
+ /// </param>
+ ///
+ /// <param name="o_ok">
+ /// 新しいコンポジションを許可するかどうかを受け取る。true の
+ /// 場合はコンポジションを許可し、false の場合は許可しない。
+ /// </param>
+ void OnStartComposition(
+ [In] ITfCompositionView i_view,
+ [Out, MarshalAs(UnmanagedType.Bool)] out bool o_ok
+ );
+
+
+ /// <summary>
+ /// 既存のコンポジションが変更された時に TSF マネージャから呼ばれる。
+ /// </summary>
+ ///
+ /// <param name="i_view">
+ /// 更新されるコンポジションを表す ITfCompositionView へのポインタ。
+ /// </param>
+ ///
+ /// <param name="i_rangeNew">
+ /// コンポジションが更新された後にコンポジションがカバーするテキスト
+ /// の範囲を含む ITfRange へのポインタ。
+ /// </param>
+ void OnUpdateComposition(
+ [In] ITfCompositionView i_view,
+ [In] ITfRange i_rangeNew
+ );
+
+
+ /// <summary>
+ /// コンポジションが終了した時に TSF マネージャから呼ばれる。
+ /// </summary>
+ /// <param name="i_view">
+ /// 終了したコンポジションを表す ITfCompositionView へのポインタ。
+ /// </param>
+ void OnEndComposition(
+ [In] ITfCompositionView i_view
+ );
+ }
+
+
+//============================================================================
+
+
+ /// <summary>
+ /// ITextStoreACP::AdviseSink() で渡されるシンクのインターフェイス。
+ /// </summary>
+ [ComImport,
+ Guid("22d44c94-a419-4542-a272-ae26093ececf"),
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown)
+ ]
+ public interface ITextStoreACPSink
+ {
+ /// <summary>
+ /// テキストが変更された時に呼び出される。
+ /// </summary>
+ /// <param name="i_flags">追加情報を示すフラグ。</param>
+ /// <param name="i_change">テキスト変更データを含む TS_TEXTCHANGE データ。</param>
+ [SecurityCritical]
+ void OnTextChange(
+ [In] OnTextChangeFlags i_flags,
+ [In] ref TS_TEXTCHANGE i_change
+ );
+
+
+ /// <summary>
+ /// ドキュメント内部で選択が変更された時に呼び出される。
+ /// </summary>
+ [SecurityCritical]
+ void OnSelectionChange();
+
+
+
+ /// <summary>
+ /// ドキュメントのレイアウトが変更された時に呼び出される。
+ /// </summary>
+ ///
+ /// <param name="i_layoutCode">変更のタイプを定義する値。</param>
+ /// <param name="i_viewCookie">ドキュメントを識別するアプリケーション定義のクッキー値。</param>
+ [SecurityCritical]
+ void OnLayoutChange(
+ [In] TsLayoutCode i_layoutCode,
+ [In] int i_viewCookie
+ );
+
+
+ /// <summary>
+ /// ステータスが変更された時に呼び出される。
+ /// </summary>
+ ///
+ /// <param name="i_flags">新しいステータスフラグ。</param>
+ [SecurityCritical]
+ void OnStatusChange(
+ [In] DynamicStatusFlags i_flags
+ );
+
+
+ /// <summary>
+ /// 一つ以上の属性が変更された時に呼び出される。
+ /// </summary>
+ ///
+ /// <param name="i_start">属性が変更されたテキストの開始位置。</param>
+ /// <param name="i_end">属性が変更されたテキストの終了位置。</param>
+ /// <param name="i_length">i_attributes パラメータの要素数。</param>
+ /// <param name="i_attributes">変更された属性を識別する値。</param>
+ [SecurityCritical]
+ void OnAttrsChange(
+ [In] int i_start,
+ [In] int i_end,
+ [In] int i_length,
+ [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=2)] Guid[] i_attributes
+ );
+
+
+ /// <summary>
+ /// ITextStoreACP::RequestLock() でロックが成功した場合に呼び出される。
+ /// </summary>
+ ///
+ /// <param name="i_flags">ロックフラグ。</param>
+ ///
+ /// <returns>HRESULT のエラーコード。</returns>
+ [PreserveSig, SecurityCritical]
+ int OnLockGranted(
+ [In] LockFlags i_flags
+ );
+
+
+ /// <summary>
+ /// エディットトランザクションが開始された時に呼び出される。
+ ///
+ /// <pre>
+ /// エディットトランザクションは、一度に処理されるべきテキストの変更
+ /// のグループ。ITextStoreACPSink::OnStartEditTransaction() 呼び出し
+ /// は、テキストサービスに ITextStoreACPSink::OnEndEditTransaction()
+ /// が呼ばれるまで、テキストの変更通知をキューに入れさせることが
+ /// できる。ITextStoreACPSink::OnEndEditTransaction() が呼び出される
+ /// と、キューに入れられた変更通知はすべて処理される。
+ /// </pre>
+ ///
+ /// <pre>
+ /// エディットトランザクションの実装は任意。
+ /// </pre>
+ /// </summary>
+ [SecurityCritical]
+ void OnStartEditTransaction();
+
+
+ /// <summary>
+ /// エディットトランザクションが終了した時に呼び出される。
+ /// </summary>
+ ///
+ /// <pre>
+ /// エディットトランザクションは、一度に処理されるべきテキストの変更
+ /// のグループ。ITextStoreACPSink::OnStartEditTransaction() 呼び出し
+ /// は、テキストサービスに ITextStoreACPSink::OnEndEditTransaction()
+ /// が呼ばれるまで、テキストの変更通知をキューに入れさせることが
+ /// できる。ITextStoreACPSink::OnEndEditTransaction() が呼び出される
+ /// と、キューに入れられた変更通知はすべて処理される。
+ /// </pre>
+ ///
+ /// <pre>
+ /// エディットトランザクションの実装は任意。
+ /// </pre>
+ [SecurityCritical]
+ void OnEndEditTransaction();
+ }
+
+
+//============================================================================
+
+
+ [StructLayout(LayoutKind.Sequential, Pack=4),
+ Guid("E26D9E1D-691E-4F29-90D7-338DCF1F8CEF")
+ ]
+ public struct TF_PERSISTENT_PROPERTY_HEADER_ACP
+ {
+ /// <summary>
+ /// プロパティを識別する GUID。
+ /// </summary>
+ public Guid guidOfType;
+ /// <summary>
+ /// プロパティの開始文字位置。
+ /// </summary>
+ public int start;
+ /// <summary>
+ /// プロパティの文字数。
+ /// </summary>
+ public int length;
+ /// <summary>
+ /// プロパティのバイト数。
+ /// </summary>
+ public uint bytes;
+ /// <summary>
+ /// プロパティオーナーによって定義された値。
+ /// </summary>
+ public uint privateValue;
+ /// <summary>
+ /// プロパティオーナーの CLSID。
+ /// </summary>
+ public Guid clsidOfTip;
+ }
+
+
+//============================================================================
+
+
+ /// <summary>
+ /// アプリケーション側で実装し、TSF マネージャーがドキュメントを非同期に
+ /// ロードするために使用されるインターフェイス。
+ /// </summary>
+ [ComImport,
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
+ Guid("4EF89150-0807-11D3-8DF0-00105A2799B5")
+ ]
+ public interface ITfPersistentPropertyLoaderACP
+ {
+ /// <summary>
+ /// プロパティをロードするときに使用される。
+ /// </summary>
+ ///
+ /// <param name="i_propertyHeader">
+ /// ロードするプロパティを識別する TF_PERSISTENT_PROPERTY_HEADER_ACP
+ /// データ。
+ /// </param>
+ ///
+ /// <param name="o_stream">
+ /// ストリームオブジェクトの受け取り先。
+ /// </param>
+ void LoadProperty(
+ [In] ref TF_PERSISTENT_PROPERTY_HEADER_ACP i_propertyHeader,
+ [Out, MarshalAs(UnmanagedType.Interface)] out IStream o_stream
+ );
+ }
+
+
+//============================================================================
+
+
+ /// <summary>
+ /// ACP ベースのアプリケーションにいくつかの機能を提供するために TSF マ
+ /// ネージャーによって実装されるインターフェイス。
+ /// <pre>
+ /// ITextStoreACP::AdviseSink() に渡されるシンクオブジェクトに
+ /// QueryInterface() をすることで得られる。
+ /// </pre>
+ /// </summary>
+ [ComImport,
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
+ Guid("AA80E901-2021-11D2-93E0-0060B067B86E")
+ ]
+ public interface ITextStoreACPServices
+ {
+ /// <summary>
+ /// ITfRange オブジェクトからプロパティを取得して、ストリームオブジェクトに
+ /// 書き出す。
+ /// </summary>
+ void Serialize(
+ [In, MarshalAs(UnmanagedType.Interface)] ITfProperty i_property,
+ [In, MarshalAs(UnmanagedType.Interface)] ITfRange i_range,
+ [Out] out TF_PERSISTENT_PROPERTY_HEADER_ACP o_propertyHeader,
+ [In, MarshalAs(UnmanagedType.Interface)] IStream i_stream
+ );
+
+
+ /// <summary>
+ /// 以前にシリアライズされたプロパティデータを取得してプロパティオブジェクトに
+ /// 適用する。
+ /// </summary>
+ void Unserialize(
+ [In, MarshalAs(UnmanagedType.Interface)] ITfProperty i_property,
+ [In] ref TF_PERSISTENT_PROPERTY_HEADER_ACP i_propertyHeader,
+ [In, MarshalAs(UnmanagedType.Interface)] IStream i_stream,
+ [In, MarshalAs(UnmanagedType.Interface)] ITfPersistentPropertyLoaderACP i_loader
+ );
+
+
+ /// <summary>
+ /// Forces all values of an asynchronously loaded property to be loaded.
+ /// </summary>
+ void ForceLoadProperty(
+ [In, MarshalAs(UnmanagedType.Interface)] ITfProperty i_property
+ );
+
+
+ /// <summary>
+ /// 終了位置と開始位置から ITfRangeACP を生成する。
+ /// </summary>
+ /// <param name="i_startIndex">開始位置。</param>
+ /// <param name="i_endIndex">終了位置。</param>
+ /// <param name="o_range">ITfRangeACP の受け取り先。</param>
+ void CreateRange(
+ [In] int i_startIndex,
+ [In] int i_endIndex,
+ [Out, MarshalAs(UnmanagedType.Interface)] out ITfRangeACP o_range
+ );
+ }
+
+
+}
-using System;\r
-using System.Reflection;\r
-using System.Runtime.InteropServices;\r
-using System.Security;\r
-\r
-namespace DotNetTextStore.UnmanagedAPI.WinDef\r
-{\r
- /// <summary>\r
- /// WindowsAPI の POINT 構造体。\r
- /// </summary>\r
- [StructLayout(LayoutKind.Sequential)]\r
- public struct POINT\r
- {\r
- public int x;\r
- public int y;\r
- public POINT(int x, int y)\r
- {\r
- this.x = x;\r
- this.y = y;\r
- }\r
- }\r
-\r
-\r
- /// <summary>\r
- /// WindowsAPI の RECT 構造体。\r
- /// </summary>\r
- [StructLayout(LayoutKind.Sequential)]\r
- public struct RECT\r
- {\r
- public int left;\r
- public int top;\r
- public int right;\r
- public int bottom;\r
- public RECT(int left, int top, int right, int bottom)\r
- {\r
- this.left = left;\r
- this.top = top;\r
- this.right = right;\r
- this.bottom = bottom;\r
- }\r
- }\r
-\r
-\r
-\r
-}\r
+using System;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Security;
+
+namespace DotNetTextStore.UnmanagedAPI.WinDef
+{
+ /// <summary>
+ /// WindowsAPI の POINT 構造体。
+ /// </summary>
+ [StructLayout(LayoutKind.Sequential)]
+ public struct POINT
+ {
+ public int x;
+ public int y;
+ public POINT(int x, int y)
+ {
+ this.x = x;
+ this.y = y;
+ }
+ }
+
+
+ /// <summary>
+ /// WindowsAPI の RECT 構造体。
+ /// </summary>
+ [StructLayout(LayoutKind.Sequential)]
+ public struct RECT
+ {
+ public int left;
+ public int top;
+ public int right;
+ public int bottom;
+ public RECT(int left, int top, int right, int bottom)
+ {
+ this.left = left;
+ this.top = top;
+ this.right = right;
+ this.bottom = bottom;
+ }
+ }
+
+
+
+}
-using System;\r
-using System.Reflection;\r
-using System.Runtime.InteropServices;\r
-using System.Security;\r
-\r
-\r
-namespace DotNetTextStore.UnmanagedAPI.WinError\r
-{\r
- public static class HRESULT\r
- {\r
- /// <summary>i_errorCode が成功した値かどうか調べる。</summary>\r
- public static bool Succeeded(int i_errorCode)\r
- {\r
- return i_errorCode >= 0;\r
- }\r
-\r
- /// <summary>\r
- /// The method was successful.\r
- /// </summary>\r
- public const int S_OK = 0;\r
- /// <summary>\r
- /// The method was successful.\r
- /// </summary>\r
- public const int S_FALSE = 0x00000001;\r
- /// <summary>\r
- /// An unspecified error occurred.\r
- /// </summary>\r
- public const int E_FAIL = unchecked((int)0x80004005);\r
- /// <summary>\r
- /// An invalid parameter was passed to the returning function.\r
- /// </summary>\r
- public const int E_INVALIDARG = unchecked((int)0x80070057);\r
- /// <summary>\r
- /// The method is not implemented.\r
- /// </summary>\r
- public const int E_NOTIMPL = unchecked((int)0x80004001);\r
- /// <summary>\r
- /// The data necessary to complete this operation is not yet available.\r
- /// </summary>\r
- public const int E_PENDING = unchecked((int)0x8000000A);\r
- /// <summary>\r
- /// There is insufficient disk space to complete operation.\r
- /// </summary>\r
- public const int STG_E_MEDIUMFULL = unchecked((int)0x80030070);\r
- /// <summary>\r
- /// Attempted to use an object that has ceased to exist.\r
- /// </summary>\r
- public const int STG_E_REVERTED = unchecked((int)0x80030102);\r
- }\r
+using System;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Security;
+
+
+namespace DotNetTextStore.UnmanagedAPI.WinError
+{
+ public static class HRESULT
+ {
+ /// <summary>i_errorCode が成功した値かどうか調べる。</summary>
+ public static bool Succeeded(int i_errorCode)
+ {
+ return i_errorCode >= 0;
+ }
+
+ /// <summary>
+ /// The method was successful.
+ /// </summary>
+ public const int S_OK = 0;
+ /// <summary>
+ /// The method was successful.
+ /// </summary>
+ public const int S_FALSE = 0x00000001;
+ /// <summary>
+ /// An unspecified error occurred.
+ /// </summary>
+ public const int E_FAIL = unchecked((int)0x80004005);
+ /// <summary>
+ /// An invalid parameter was passed to the returning function.
+ /// </summary>
+ public const int E_INVALIDARG = unchecked((int)0x80070057);
+ /// <summary>
+ /// The method is not implemented.
+ /// </summary>
+ public const int E_NOTIMPL = unchecked((int)0x80004001);
+ /// <summary>
+ /// The data necessary to complete this operation is not yet available.
+ /// </summary>
+ public const int E_PENDING = unchecked((int)0x8000000A);
+ /// <summary>
+ /// There is insufficient disk space to complete operation.
+ /// </summary>
+ public const int STG_E_MEDIUMFULL = unchecked((int)0x80030070);
+ /// <summary>
+ /// Attempted to use an object that has ceased to exist.
+ /// </summary>
+ public const int STG_E_REVERTED = unchecked((int)0x80030102);
+ }
}
\ No newline at end of file
-<?xml version="1.0" encoding="utf-8"?>\r
-<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">\r
- <PropertyGroup>\r
- <!-- The configuration and platform will be used to determine which\r
- assemblies to include from solution and project documentation\r
- sources -->\r
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>\r
- <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>\r
- <SchemaVersion>2.0</SchemaVersion>\r
- <ProjectGuid>{6794fc71-7341-436f-abf0-3337b9f87ea7}</ProjectGuid>\r
- <SHFBSchemaVersion>1.9.5.0</SHFBSchemaVersion>\r
- <!-- AssemblyName, Name, and RootNamespace are not used by SHFB but Visual\r
- Studio adds them anyway -->\r
- <AssemblyName>Documentation</AssemblyName>\r
- <RootNamespace>Documentation</RootNamespace>\r
- <Name>Documentation</Name>\r
- <!-- SHFB properties -->\r
- <OutputPath>.\Help\</OutputPath>\r
- <HtmlHelpName>Documentation</HtmlHelpName>\r
- <Language>ja-JP</Language>\r
- <HelpTitle>FooEditEngine Class Library</HelpTitle>\r
- <DocumentationSources>\r
- <DocumentationSource sourceFile="..\Metro\FooEditEngnine\bin\Release\FooEditEngine.Metro.dll" />\r
-<DocumentationSource sourceFile="..\Metro\FooEditEngnine\bin\Release\FooEditEngine.Metro.xml" />\r
-<DocumentationSource sourceFile="..\Windows\FooEditEngine\bin\Release\FooEditEngine.Windows.dll" />\r
-<DocumentationSource sourceFile="..\Windows\FooEditEngine\bin\Release\FooEditEngine.Windows.XML" />\r
-<DocumentationSource sourceFile="..\WPF\FooEditEngine\bin\Release\FooEditEngine.WPF.dll" />\r
-<DocumentationSource sourceFile="..\WPF\FooEditEngine\bin\Release\FooEditEngine.WPF.XML" /></DocumentationSources>\r
- <NamespaceSummaries>\r
- <NamespaceSummaryItem name="FooEditEngine" isDocumented="True">FooEditEngineの核となる機能を提供します</NamespaceSummaryItem>\r
- <NamespaceSummaryItem name="FooEditEngine.Windows" isDocumented="True">FooEditEngineをWindowsで使用するためのクラス、列挙体などを含みます</NamespaceSummaryItem>\r
- <NamespaceSummaryItem name="FooEditEngine.WPF" isDocumented="True">FooEditEngineをWPFで使用するためのクラス、列挙体などを含みます</NamespaceSummaryItem>\r
- <NamespaceSummaryItem name="XamlGeneratedNamespace" isDocumented="False" />\r
- </NamespaceSummaries>\r
- <BuildAssemblerVerbosity>OnlyWarningsAndErrors</BuildAssemblerVerbosity>\r
- <HelpFileFormat>HtmlHelp1</HelpFileFormat>\r
- <IndentHtml>False</IndentHtml>\r
- <FrameworkVersion>.NET Framework 4.5</FrameworkVersion>\r
- <KeepLogFile>True</KeepLogFile>\r
- <DisableCodeBlockComponent>False</DisableCodeBlockComponent>\r
- <CppCommentsFixup>False</CppCommentsFixup>\r
- <CleanIntermediates>True</CleanIntermediates>\r
- </PropertyGroup>\r
- <!-- There are no properties for these groups. AnyCPU needs to appear in\r
- order for Visual Studio to perform the build. The others are optional\r
- common platform types that may appear. -->\r
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">\r
- </PropertyGroup>\r
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">\r
- </PropertyGroup>\r
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">\r
- </PropertyGroup>\r
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">\r
- </PropertyGroup>\r
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">\r
- </PropertyGroup>\r
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">\r
- </PropertyGroup>\r
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|Win32' ">\r
- </PropertyGroup>\r
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|Win32' ">\r
- </PropertyGroup>\r
- <ItemGroup>\r
- <Reference Include="Windows">\r
- <HintPath>..\..\..\..\..\..\..\Program Files (x86)\Windows Kits\8.0\References\CommonConfiguration\Neutral\Windows.winmd</HintPath>\r
- </Reference>\r
- </ItemGroup>\r
- <!-- Import the SHFB build targets -->\r
- <Import Project="$(SHFBROOT)\SandcastleHelpFileBuilder.targets" />\r
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
+ <PropertyGroup>
+ <!-- The configuration and platform will be used to determine which
+ assemblies to include from solution and project documentation
+ sources -->
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{6794fc71-7341-436f-abf0-3337b9f87ea7}</ProjectGuid>
+ <SHFBSchemaVersion>1.9.9.0</SHFBSchemaVersion>
+ <!-- AssemblyName, Name, and RootNamespace are not used by SHFB but Visual
+ Studio adds them anyway -->
+ <AssemblyName>Documentation</AssemblyName>
+ <RootNamespace>Documentation</RootNamespace>
+ <Name>Documentation</Name>
+ <!-- SHFB properties -->
+ <OutputPath>.\Help\</OutputPath>
+ <HtmlHelpName>Documentation</HtmlHelpName>
+ <Language>ja-JP</Language>
+ <HelpTitle>FooEditEngine Class Library</HelpTitle>
+ <DocumentationSources>
+ <DocumentationSource sourceFile="..\Metro\FooEditEngine\bin\Release\FooEditEngine.Metro.dll" />
+ <DocumentationSource sourceFile="..\Metro\FooEditEngine\bin\Release\FooEditEngine.Metro.xml" />
+ <DocumentationSource sourceFile="..\Windows\FooEditEngine\bin\Release\FooEditEngine.Windows.dll" />
+ <DocumentationSource sourceFile="..\Windows\FooEditEngine\bin\Release\FooEditEngine.Windows.XML" />
+ <DocumentationSource sourceFile="..\WPF\FooEditEngine\bin\Release\FooEditEngine.WPF.dll" />
+ <DocumentationSource sourceFile="..\WPF\FooEditEngine\bin\Release\FooEditEngine.WPF.XML" />
+ </DocumentationSources>
+ <NamespaceSummaries>
+ <NamespaceSummaryItem name="FooEditEngine" isDocumented="True">FooEditEngineの核となる機能を提供します</NamespaceSummaryItem>
+<NamespaceSummaryItem name="FooEditEngine.Windows" isDocumented="True">FooEditEngineをWindowsで使用するためのクラス、列挙体などを含みます</NamespaceSummaryItem>
+<NamespaceSummaryItem name="FooEditEngine.WPF" isDocumented="True">FooEditEngineをWPFで使用するためのクラス、列挙体などを含みます</NamespaceSummaryItem>
+<NamespaceSummaryItem name="XamlGeneratedNamespace" isDocumented="False" />
+<NamespaceSummaryItem name="FooEditEngine.Test" isDocumented="True">テスト用のクラス、構造体などを含みます</NamespaceSummaryItem>
+<NamespaceSummaryItem name="FooEditEngine.Metro" isDocumented="True">FooEditEngineをWindows Store Appで使用するためのクラス、列挙体などを含みます</NamespaceSummaryItem>
+<NamespaceSummaryItem name="FooEditEngine.FooEditEngine_XamlTypeInfo" isDocumented="False" /></NamespaceSummaries>
+ <BuildAssemblerVerbosity>OnlyWarningsAndErrors</BuildAssemblerVerbosity>
+ <HelpFileFormat>HtmlHelp1</HelpFileFormat>
+ <IndentHtml>False</IndentHtml>
+ <FrameworkVersion>.NET for Windows Store Apps (8.1)</FrameworkVersion>
+ <KeepLogFile>True</KeepLogFile>
+ <DisableCodeBlockComponent>False</DisableCodeBlockComponent>
+ <CppCommentsFixup>False</CppCommentsFixup>
+ <CleanIntermediates>True</CleanIntermediates>
+ </PropertyGroup>
+ <!-- There are no properties for these groups. AnyCPU needs to appear in
+ order for Visual Studio to perform the build. The others are optional
+ common platform types that may appear. -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|Win32' ">
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|Win32' ">
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Windows">
+ <HintPath>..\..\..\..\..\..\..\Program Files (x86)\Windows Kits\8.0\References\CommonConfiguration\Neutral\Windows.winmd</HintPath>
+ </Reference>
+ </ItemGroup>
+ <!-- Import the SHFB build targets -->
+ <Import Project="$(SHFBROOT)\SandcastleHelpFileBuilder.targets" />
</Project>
\ No newline at end of file
</Page>
</ItemGroup>
<ItemGroup>
- <Compile Include="..\..\Common\Automaion\FooTextBoxAutomationPeer.cs">
- <Link>FooTextBoxAutomationPeer.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\CacheManager.cs">
- <Link>CacheManager.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\CollectionDebugView.cs">
- <Link>CollectionDebugView.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\Controller.cs">
- <Link>Controller.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\Direct2D\CustomTextRenderer.cs">
- <Link>Direct2D\CustomTextRenderer.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\Direct2D\D2DRenderCommon.cs">
- <Link>Direct2D\D2DRenderCommon.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\Direct2D\DrawingEffect.cs">
- <Link>Direct2D\DrawingEffect.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\Direct2D\InlineChar.cs">
- <Link>Direct2D\InlineChar.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\Direct2D\MarkerFactory.cs">
- <Link>Direct2D\MarkerFactory.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\Direct2D\MultiSet.cs">
- <Link>Direct2D\MultiSet.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\Direct2D\MyTextLayout.cs">
- <Link>Direct2D\MyTextLayout.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\Document.cs">
- <Link>Document.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\EditView.cs">
- <Link>EditView.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\FoldingCollection.cs">
- <Link>FoldingCollection.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\GapBuffer+Enumerator.cs">
- <Link>GapBuffer+Enumerator.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\GapBuffer.cs">
- <Link>GapBuffer.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\IFoldingStrategy.cs">
- <Link>IFoldingStrategy.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\IHilighter.cs">
- <Link>IHilighter.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\ITextRender.cs">
- <Link>ITextRender.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\LineToIndex.cs">
- <Link>LineToIndex.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\MarkerCollection.cs">
- <Link>MarkerCollection.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\PrintableView.cs">
- <Link>PrintableView.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\Range.cs">
- <Link>Range.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\RangeCollection.cs">
- <Link>RangeCollection.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\RangeTree.cs">
- <Link>RangeTree.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\RangeTreeNode.cs">
- <Link>RangeTreeNode.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\ResourceManager.cs">
- <Link>ResourceManager.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\SelectCollection.cs">
- <Link>SelectCollection.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\StringBuffer.cs">
- <Link>StringBuffer.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\TextPoint.cs">
- <Link>TextPoint.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\TextServiceFramework\TextStoreHelper.cs">
- <Link>TextStoreHelper.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\UndoCommands.cs">
- <Link>UndoCommands.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\UndoManager.cs">
- <Link>UndoManager.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\Util.cs">
- <Link>Util.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\ViewBase.cs">
- <Link>ViewBase.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\WatchDogPattern.cs">
- <Link>WatchDogPattern.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\WinFileStream.cs">
- <Link>WinFileStream.cs</Link>
- </Compile>
<Compile Include="Direct2D\D2DRender.cs" />
<Compile Include="Direct2D\D2DRenderBase.cs" />
<Compile Include="FooPrintText.cs" />
</Reference>
</ItemGroup>
<ItemGroup>
- <ProjectReference Include="..\..\Common\DotNetTextStore\DotNetTextStore.Metro.csproj">
- <Project>{453c491e-ef3a-41ad-a725-8855c1cb2c84}</Project>
- <Name>DotNetTextStore.Metro</Name>
- </ProjectReference>
- </ItemGroup>
- <ItemGroup>
<PRIResource Include="strings\en-US\Resources.resw" />
</ItemGroup>
<ItemGroup>
<PRIResource Include="strings\ja-JP\Resources.resw" />
</ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\DotNetTextStore\DotNetTextStore.Metro.csproj">
+ <Project>{453c491e-ef3a-41ad-a725-8855c1cb2c84}</Project>
+ <Name>DotNetTextStore.Metro</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="..\..\Core\Core.projitems" Label="Shared" />
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' < '12.0' ">
<VisualStudioVersion>12.0</VisualStudioVersion>
</PropertyGroup>
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 2013
-VisualStudioVersion = 12.0.21005.1
+# Visual Studio 14
+VisualStudioVersion = 14.0.23107.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test", "Test\Test.csproj", "{D5A54EBE-15AC-48E9-819B-99314266B683}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetTextStore.Metro", "..\Common\DotNetTextStore\DotNetTextStore.Metro.csproj", "{453C491E-EF3A-41AD-A725-8855C1CB2C84}"
-EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FooEditEngine", "FooEditEngine\FooEditEngine.csproj", "{AC23EBF4-4CD0-43EA-9808-0E6DCD12E791}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetTextStore.Metro", "..\DotNetTextStore\DotNetTextStore.Metro.csproj", "{453C491E-EF3A-41AD-A725-8855C1CB2C84}"
+EndProject
+Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Core", "..\Core\Core.shproj", "{C244F4E5-45D2-4C1F-BD2A-A5CC90D9421B}"
+EndProject
Global
+ GlobalSection(SharedMSBuildProjectFiles) = preSolution
+ ..\Core\Core.projitems*{ac23ebf4-4cd0-43ea-9808-0e6dcd12e791}*SharedItemsImports = 4
+ ..\Core\Core.projitems*{c244f4e5-45d2-4c1f-bd2a-a5cc90d9421b}*SharedItemsImports = 13
+ EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|ARM = Debug|ARM
{D5A54EBE-15AC-48E9-819B-99314266B683}.Release|x86.ActiveCfg = Release|x86
{D5A54EBE-15AC-48E9-819B-99314266B683}.Release|x86.Build.0 = Release|x86
{D5A54EBE-15AC-48E9-819B-99314266B683}.Release|x86.Deploy.0 = Release|x86
- {453C491E-EF3A-41AD-A725-8855C1CB2C84}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {453C491E-EF3A-41AD-A725-8855C1CB2C84}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {453C491E-EF3A-41AD-A725-8855C1CB2C84}.Debug|ARM.ActiveCfg = Debug|Any CPU
- {453C491E-EF3A-41AD-A725-8855C1CB2C84}.Debug|x64.ActiveCfg = Debug|Any CPU
- {453C491E-EF3A-41AD-A725-8855C1CB2C84}.Debug|x86.ActiveCfg = Debug|Any CPU
- {453C491E-EF3A-41AD-A725-8855C1CB2C84}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {453C491E-EF3A-41AD-A725-8855C1CB2C84}.Release|Any CPU.Build.0 = Release|Any CPU
- {453C491E-EF3A-41AD-A725-8855C1CB2C84}.Release|ARM.ActiveCfg = Release|Any CPU
- {453C491E-EF3A-41AD-A725-8855C1CB2C84}.Release|x64.ActiveCfg = Release|Any CPU
- {453C491E-EF3A-41AD-A725-8855C1CB2C84}.Release|x86.ActiveCfg = Release|Any CPU
{AC23EBF4-4CD0-43EA-9808-0E6DCD12E791}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AC23EBF4-4CD0-43EA-9808-0E6DCD12E791}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AC23EBF4-4CD0-43EA-9808-0E6DCD12E791}.Debug|ARM.ActiveCfg = Debug|ARM
{AC23EBF4-4CD0-43EA-9808-0E6DCD12E791}.Release|x64.Build.0 = Release|x64
{AC23EBF4-4CD0-43EA-9808-0E6DCD12E791}.Release|x86.ActiveCfg = Release|x86
{AC23EBF4-4CD0-43EA-9808-0E6DCD12E791}.Release|x86.Build.0 = Release|x86
+ {453C491E-EF3A-41AD-A725-8855C1CB2C84}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {453C491E-EF3A-41AD-A725-8855C1CB2C84}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {453C491E-EF3A-41AD-A725-8855C1CB2C84}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {453C491E-EF3A-41AD-A725-8855C1CB2C84}.Debug|ARM.Build.0 = Debug|Any CPU
+ {453C491E-EF3A-41AD-A725-8855C1CB2C84}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {453C491E-EF3A-41AD-A725-8855C1CB2C84}.Debug|x64.Build.0 = Debug|Any CPU
+ {453C491E-EF3A-41AD-A725-8855C1CB2C84}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {453C491E-EF3A-41AD-A725-8855C1CB2C84}.Debug|x86.Build.0 = Debug|Any CPU
+ {453C491E-EF3A-41AD-A725-8855C1CB2C84}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {453C491E-EF3A-41AD-A725-8855C1CB2C84}.Release|Any CPU.Build.0 = Release|Any CPU
+ {453C491E-EF3A-41AD-A725-8855C1CB2C84}.Release|ARM.ActiveCfg = Release|Any CPU
+ {453C491E-EF3A-41AD-A725-8855C1CB2C84}.Release|ARM.Build.0 = Release|Any CPU
+ {453C491E-EF3A-41AD-A725-8855C1CB2C84}.Release|x64.ActiveCfg = Release|Any CPU
+ {453C491E-EF3A-41AD-A725-8855C1CB2C84}.Release|x64.Build.0 = Release|Any CPU
+ {453C491E-EF3A-41AD-A725-8855C1CB2C84}.Release|x86.ActiveCfg = Release|Any CPU
+ {453C491E-EF3A-41AD-A725-8855C1CB2C84}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
-/*\r
- * Copyright (C) 2013 FooProject\r
- * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.\r
-\r
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of \r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\r
-\r
-You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.\r
- */\r
-using System;\r
-using System.Collections.Generic;\r
-using System.Text;\r
-using System.IO;\r
-using Windows.Graphics.Printing;\r
-using Windows.Storage.Pickers;\r
-using Windows.Storage;\r
-using Windows.UI.ViewManagement;\r
-using Windows.UI.Xaml;\r
-using Windows.UI.Xaml.Controls;\r
-using Windows.UI.Xaml.Navigation;\r
-using Windows.UI.ApplicationSettings;\r
-using FooEditEngine;\r
-using FooEditEngine.Metro;\r
-\r
-// 空白ページのアイテム テンプレートについては、http://go.microsoft.com/fwlink/?LinkId=234238 を参照してください\r
-\r
-namespace Test\r
-{\r
- /// <summary>\r
- /// それ自体で使用できる空白ページまたはフレーム内に移動できる空白ページ。\r
- /// </summary>\r
- public sealed partial class MainPage : Page\r
- {\r
- public MainPage()\r
- {\r
- this.InitializeComponent();\r
- this.Current_ChangedSetting(AppSettings.Current, null);\r
- InputPane currentView = InputPane.GetForCurrentView();\r
- currentView.Showing += currentView_Showing;\r
- currentView.Hiding += currentView_Hiding;\r
- PrintManager.GetForCurrentView().PrintTaskRequested += MainPage_PrintTaskRequested;\r
- }\r
-\r
- void MainPage_PrintTaskRequested(PrintManager sender, PrintTaskRequestedEventArgs args)\r
- {\r
- FooPrintText printtext = new FooPrintText();\r
- printtext.Fotter = "fotter";\r
- printtext.Header = "header";\r
- printtext.Padding = new FooEditEngine.Padding(20, 20, 20, 20);\r
- printtext.Print(args.Request, "Text Print", this.fooTextBox);\r
- }\r
-\r
- /// <summary>\r
- /// このページがフレームに表示されるときに呼び出されます。\r
- /// </summary>\r
- /// <param name="e">このページにどのように到達したかを説明するイベント データ。Parameter \r
- /// プロパティは、通常、ページを構成するために使用します。</param>\r
- protected override void OnNavigatedTo(NavigationEventArgs e)\r
- {\r
- AppSettings.Current.ChangedSetting += Current_ChangedSetting;\r
- }\r
-\r
- void currentView_Hiding(InputPane sender, InputPaneVisibilityEventArgs args)\r
- {\r
- this.fooTextBox.Margin = new Thickness(0);\r
- args.EnsuredFocusedElementInView = true;\r
- }\r
-\r
- void currentView_Showing(InputPane sender, InputPaneVisibilityEventArgs args)\r
- {\r
- this.fooTextBox.Margin = new Thickness(0, 0, 0, args.OccludedRect.Height);\r
- args.EnsuredFocusedElementInView = true;\r
- }\r
-\r
- void Current_ChangedSetting(object sender, EventArgs e)\r
- {\r
- AppSettings setting = (AppSettings)sender;\r
- this.fooTextBox.FlowDirection = setting.IsRTL ? FlowDirection.RightToLeft : FlowDirection.LeftToRight;\r
- this.fooTextBox.DrawCaretLine = setting.ShowLineMarker;\r
- this.fooTextBox.DrawLineNumber = setting.ShowLineNumber;\r
- this.fooTextBox.DrawRuler = setting.ShowRuler;\r
- if (setting.HilightXML)\r
- {\r
- this.fooTextBox.Hilighter = new XmlHilighter();\r
- this.fooTextBox.LayoutLineCollection.HilightAll();\r
- }\r
- else\r
- {\r
- this.fooTextBox.Hilighter = null;\r
- this.fooTextBox.LayoutLineCollection.ClearHilight();\r
- }\r
- this.fooTextBox.Visibility = setting.IsVisible ? Visibility.Visible : Visibility.Collapsed;\r
- this.fooTextBox.LineBreakMethod = setting.CurrentLineBreakMethod.Method;\r
- this.fooTextBox.LineBreakCharCount = 50;\r
- this.fooTextBox.Refresh();\r
- }\r
-\r
- private async void Button_Click(object sender, RoutedEventArgs e)\r
- {\r
- FileOpenPicker openPicker = new FileOpenPicker();\r
-\r
- openPicker.ViewMode = PickerViewMode.List;\r
-\r
- // ファイル形式\r
- openPicker.FileTypeFilter.Add("*");\r
-\r
- // 最初に表示される場所\r
- openPicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;\r
-\r
- StorageFile file = await openPicker.PickSingleFileAsync();\r
- if (file != null)\r
- {\r
- this.fooTextBox.IsEnabled = false;\r
- using (Stream stream = await file.OpenStreamForReadAsync())\r
- using(StreamReader reader = new StreamReader(stream))\r
- {\r
- await this.fooTextBox.LoadFileAsync(reader,null);\r
- this.fooTextBox.FoldingStrategy = new CharFoldingMethod('{', '}');\r
- this.fooTextBox.LayoutLineCollection.GenerateFolding();\r
- this.fooTextBox.IsEnabled = true;\r
- this.fooTextBox.Refresh();\r
- }\r
- }\r
- }\r
-\r
- private async void Button_Click_1(object sender, RoutedEventArgs e)\r
- {\r
- FileSavePicker savePicker = new FileSavePicker();\r
- savePicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;\r
- savePicker.FileTypeChoices.Add("Text Types", new List<string>() { ".txt" });\r
- savePicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;\r
- StorageFile file = await savePicker.PickSaveFileAsync();\r
- if (file != null)\r
- {\r
- using (Stream stream = await file.OpenStreamForWriteAsync())\r
- using (StreamWriter writer = new StreamWriter(stream))\r
- {\r
- await this.fooTextBox.SaveFile(writer,null);\r
- }\r
- }\r
- }\r
-\r
- }\r
-}\r
+/*
+ * Copyright (C) 2013 FooProject
+ * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.IO;
+using Windows.Graphics.Printing;
+using Windows.Storage.Pickers;
+using Windows.Storage;
+using Windows.UI.ViewManagement;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Navigation;
+using Windows.UI.ApplicationSettings;
+using FooEditEngine;
+using FooEditEngine.Metro;
+using FooEditEngine.Test;
+
+// 空白ページのアイテム テンプレートについては、http://go.microsoft.com/fwlink/?LinkId=234238 を参照してください
+
+namespace Test
+{
+ /// <summary>
+ /// それ自体で使用できる空白ページまたはフレーム内に移動できる空白ページ。
+ /// </summary>
+ public sealed partial class MainPage : Page
+ {
+ public MainPage()
+ {
+ this.InitializeComponent();
+ this.Current_ChangedSetting(AppSettings.Current, null);
+ InputPane currentView = InputPane.GetForCurrentView();
+ currentView.Showing += currentView_Showing;
+ currentView.Hiding += currentView_Hiding;
+ PrintManager.GetForCurrentView().PrintTaskRequested += MainPage_PrintTaskRequested;
+ }
+
+ void MainPage_PrintTaskRequested(PrintManager sender, PrintTaskRequestedEventArgs args)
+ {
+ FooPrintText printtext = new FooPrintText();
+ printtext.Fotter = "fotter";
+ printtext.Header = "header";
+ printtext.Padding = new FooEditEngine.Padding(20, 20, 20, 20);
+ printtext.Print(args.Request, "Text Print", this.fooTextBox);
+ }
+
+ /// <summary>
+ /// このページがフレームに表示されるときに呼び出されます。
+ /// </summary>
+ /// <param name="e">このページにどのように到達したかを説明するイベント データ。Parameter
+ /// プロパティは、通常、ページを構成するために使用します。</param>
+ protected override void OnNavigatedTo(NavigationEventArgs e)
+ {
+ AppSettings.Current.ChangedSetting += Current_ChangedSetting;
+ }
+
+ void currentView_Hiding(InputPane sender, InputPaneVisibilityEventArgs args)
+ {
+ this.fooTextBox.Margin = new Thickness(0);
+ args.EnsuredFocusedElementInView = true;
+ }
+
+ void currentView_Showing(InputPane sender, InputPaneVisibilityEventArgs args)
+ {
+ this.fooTextBox.Margin = new Thickness(0, 0, 0, args.OccludedRect.Height);
+ args.EnsuredFocusedElementInView = true;
+ }
+
+ void Current_ChangedSetting(object sender, EventArgs e)
+ {
+ AppSettings setting = (AppSettings)sender;
+ this.fooTextBox.FlowDirection = setting.IsRTL ? FlowDirection.RightToLeft : FlowDirection.LeftToRight;
+ this.fooTextBox.DrawCaretLine = setting.ShowLineMarker;
+ this.fooTextBox.DrawLineNumber = setting.ShowLineNumber;
+ this.fooTextBox.DrawRuler = setting.ShowRuler;
+ if (setting.HilightXML)
+ {
+ this.fooTextBox.Hilighter = new XmlHilighter();
+ this.fooTextBox.LayoutLineCollection.HilightAll();
+ }
+ else
+ {
+ this.fooTextBox.Hilighter = null;
+ this.fooTextBox.LayoutLineCollection.ClearHilight();
+ }
+ this.fooTextBox.Visibility = setting.IsVisible ? Visibility.Visible : Visibility.Collapsed;
+ this.fooTextBox.LineBreakMethod = setting.CurrentLineBreakMethod.Method;
+ this.fooTextBox.LineBreakCharCount = 50;
+ this.fooTextBox.Refresh();
+ }
+
+ private async void Button_Click(object sender, RoutedEventArgs e)
+ {
+ FileOpenPicker openPicker = new FileOpenPicker();
+
+ openPicker.ViewMode = PickerViewMode.List;
+
+ // ファイル形式
+ openPicker.FileTypeFilter.Add("*");
+
+ // 最初に表示される場所
+ openPicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
+
+ StorageFile file = await openPicker.PickSingleFileAsync();
+ if (file != null)
+ {
+ this.fooTextBox.IsEnabled = false;
+ using (Stream stream = await file.OpenStreamForReadAsync())
+ using(StreamReader reader = new StreamReader(stream))
+ {
+ await this.fooTextBox.LoadFileAsync(reader,null);
+ this.fooTextBox.FoldingStrategy = new CharFoldingMethod('{', '}');
+ this.fooTextBox.LayoutLineCollection.GenerateFolding();
+ this.fooTextBox.IsEnabled = true;
+ this.fooTextBox.Refresh();
+ }
+ }
+ }
+
+ private async void Button_Click_1(object sender, RoutedEventArgs e)
+ {
+ FileSavePicker savePicker = new FileSavePicker();
+ savePicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
+ savePicker.FileTypeChoices.Add("Text Types", new List<string>() { ".txt" });
+ savePicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
+ StorageFile file = await savePicker.PickSaveFileAsync();
+ if (file != null)
+ {
+ using (Stream stream = await file.OpenStreamForWriteAsync())
+ using (StreamWriter writer = new StreamWriter(stream))
+ {
+ await this.fooTextBox.SaveFile(writer,null);
+ }
+ }
+ }
+
+ }
+}
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
- <Compile Include="..\..\Common\Test\CharFoldingMethod.cs">
- <Link>CharFoldingMethod.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\Test\XmlHilighter.cs">
- <Link>XmlHilighter.cs</Link>
- </Compile>
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
</Compile>
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 2012
+# Visual Studio 14
+VisualStudioVersion = 14.0.23107.0
+MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FooEditEngine", "FooEditEngine\FooEditEngine.csproj", "{DF4749AD-66F4-44F3-B0E4-84214CB48BA8}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test", "Test\Test.csproj", "{7E9B304F-B087-46F7-AE70-C7ACF64C5FCC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTest", "UnitTest\UnitTest.csproj", "{F75730B1-0B7E-428C-9534-4F9CA586D806}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetTextStore", "..\Common\DotNetTextStore\DotNetTextStore.csproj", "{453C491E-EF3A-41AD-A725-8855C1CB2C84}"
+Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Core", "..\Core\Core.shproj", "{C244F4E5-45D2-4C1F-BD2A-A5CC90D9421B}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetTextStore", "..\DotNetTextStore\DotNetTextStore.csproj", "{453C491E-EF3A-41AD-A725-8855C1CB2C84}"
EndProject
Global
+ GlobalSection(SharedMSBuildProjectFiles) = preSolution
+ ..\Core\Core.projitems*{c244f4e5-45d2-4c1f-bd2a-a5cc90d9421b}*SharedItemsImports = 13
+ ..\Core\Core.projitems*{df4749ad-66f4-44f3-b0e4-84214cb48ba8}*SharedItemsImports = 4
+ EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|Mixed Platforms = Debug|Mixed Platforms
{453C491E-EF3A-41AD-A725-8855C1CB2C84}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{453C491E-EF3A-41AD-A725-8855C1CB2C84}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{453C491E-EF3A-41AD-A725-8855C1CB2C84}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {453C491E-EF3A-41AD-A725-8855C1CB2C84}.Debug|x86.Build.0 = Debug|Any CPU
{453C491E-EF3A-41AD-A725-8855C1CB2C84}.Release|Any CPU.ActiveCfg = Release|Any CPU
{453C491E-EF3A-41AD-A725-8855C1CB2C84}.Release|Any CPU.Build.0 = Release|Any CPU
{453C491E-EF3A-41AD-A725-8855C1CB2C84}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{453C491E-EF3A-41AD-A725-8855C1CB2C84}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{453C491E-EF3A-41AD-A725-8855C1CB2C84}.Release|x86.ActiveCfg = Release|Any CPU
+ {453C491E-EF3A-41AD-A725-8855C1CB2C84}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
</Page>
</ItemGroup>
<ItemGroup>
- <Compile Include="..\..\Common\Automaion\FooTextBoxAutomationPeer.cs">
- <Link>FooTextBoxAutomationPeer.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\CollectionDebugView.cs">
- <Link>CollectionDebugView.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\Controller.cs">
- <Link>Controller.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\Direct2D\CustomTextRenderer.cs">
- <Link>Direct2D\CustomTextRenderer.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\Direct2D\D2DRenderCommon.cs">
- <Link>Direct2D\D2DRenderCommon.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\Direct2D\DrawingEffect.cs">
- <Link>Direct2D\DrawingEffect.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\Direct2D\InlineChar.cs">
- <Link>Direct2D\InlineChar.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\Direct2D\MarkerFactory.cs">
- <Link>Direct2D\MarkerFactory.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\Direct2D\MultiSet.cs">
- <Link>Direct2D\MultiSet.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\Direct2D\MyTextLayout.cs">
- <Link>Direct2D\MyTextLayout.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\Document.cs">
- <Link>Document.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\EditView.cs">
- <Link>EditView.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\FoldingCollection.cs">
- <Link>FoldingCollection.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\GapBuffer+Enumerator.cs">
- <Link>GapBuffer+Enumerator.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\GapBuffer.cs">
- <Link>GapBuffer.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\IFoldingStrategy.cs">
- <Link>IFoldingStrategy.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\IHilighter.cs">
- <Link>IHilighter.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\ITextRender.cs">
- <Link>ITextRender.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\LineToIndex.cs">
- <Link>LineToIndex.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\MarkerCollection.cs">
- <Link>MarkerCollection.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\PrintableView.cs">
- <Link>PrintableView.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\Range.cs">
- <Link>Range.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\RangeCollection.cs">
- <Link>RangeCollection.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\RangeTree.cs">
- <Link>RangeTree.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\RangeTreeNode.cs">
- <Link>RangeTreeNode.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\ResourceManager.cs">
- <Link>ResourceManager.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\SelectCollection.cs">
- <Link>SelectCollection.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\StringBuffer.cs">
- <Link>StringBuffer.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\TextPoint.cs">
- <Link>TextPoint.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\TextServiceFramework\TextStoreHelper.cs">
- <Link>TextStoreHelper.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\UndoCommands.cs">
- <Link>UndoCommands.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\UndoManager.cs">
- <Link>UndoManager.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\Util.cs">
- <Link>Util.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\ViewBase.cs">
- <Link>ViewBase.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\WatchDogPattern.cs">
- <Link>WatchDogPattern.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\WinFileStream.cs">
- <Link>WinFileStream.cs</Link>
- </Compile>
<Compile Include="Direct2D\D2DRender.cs" />
<Compile Include="Direct2D\NativeMethods.cs" />
<Compile Include="FooPrintText.cs" />
<Compile Include="WPF\WPFRender.cs" />
</ItemGroup>
<ItemGroup>
- <ProjectReference Include="..\..\Common\DotNetTextStore\DotNetTextStore.csproj">
+ <ProjectReference Include="..\..\DotNetTextStore\DotNetTextStore.csproj">
<Project>{453c491e-ef3a-41ad-a725-8855c1cb2c84}</Project>
<Name>DotNetTextStore</Name>
</ProjectReference>
</ItemGroup>
+ <Import Project="..\..\Core\Core.projitems" Label="Shared" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
using System.Windows.Threading;
using FooEditEngine;
using FooEditEngine.WPF;
+using FooEditEngine.Test;
using Microsoft.Win32;
namespace Test
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
- <Compile Include="..\..\Common\Test\CharFoldingMethod.cs">
- <Link>CharFoldingMethod.cs</Link>
- </Compile>
<Page Include="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
- <Compile Include="..\..\Common\Test\XmlHilighter.cs">
- <Link>XmlHilighter.cs</Link>
- </Compile>
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
<SubType>Code</SubType>
-Microsoft Visual Studio Solution File, Format Version 11.00
-# Visual Studio 2010
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.23107.0
+MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FooEditEngine", "FooEditEngine\FooEditEngine.csproj", "{4A78E675-764C-46FB-B539-B0C0F367F670}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test", "Test\Test.csproj", "{8A8CE1F1-B51B-49DF-984E-74B66A08FF11}"
EndProject
+Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Core", "..\Core\Core.shproj", "{C244F4E5-45D2-4C1F-BD2A-A5CC90D9421B}"
+EndProject
Global
+ GlobalSection(SharedMSBuildProjectFiles) = preSolution
+ ..\Core\Core.projitems*{4a78e675-764c-46fb-b539-b0c0f367f670}*SharedItemsImports = 4
+ ..\Core\Core.projitems*{c244f4e5-45d2-4c1f-bd2a-a5cc90d9421b}*SharedItemsImports = 13
+ EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|Mixed Platforms = Debug|Mixed Platforms
<Reference Include="System.Windows.Forms" />
</ItemGroup>
<ItemGroup>
- <Compile Include="..\..\Common\CollectionDebugView.cs">
- <Link>CollectionDebugView.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\Controller.cs">
- <Link>Controller.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\Direct2D\CustomTextRenderer.cs">
- <Link>CustomTextRenderer.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\Direct2D\D2DRenderCommon.cs">
- <Link>D2DRenderCommon.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\Direct2D\DrawingEffect.cs">
- <Link>DrawingEffect.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\Direct2D\InlineChar.cs">
- <Link>InlineChar.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\Direct2D\MarkerFactory.cs">
- <Link>MarkerFactory.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\Direct2D\MultiSet.cs">
- <Link>MultiSet.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\Direct2D\MyTextLayout.cs">
- <Link>MyTextLayout.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\Document.cs">
- <Link>Document.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\EditView.cs">
- <Link>EditView.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\FoldingCollection.cs">
- <Link>FoldingCollection.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\GapBuffer+Enumerator.cs">
- <Link>GapBuffer+Enumerator.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\GapBuffer.cs">
- <Link>GapBuffer.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\IFoldingStrategy.cs">
- <Link>IFoldingStrategy.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\IHilighter.cs">
- <Link>IHilighter.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\ITextRender.cs">
- <Link>ITextRender.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\LineToIndex.cs">
- <Link>LineToIndex.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\MarkerCollection.cs">
- <Link>MarkerCollection.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\PrintableView.cs">
- <Link>PrintableView.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\Range.cs">
- <Link>Range.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\RangeCollection.cs">
- <Link>RangeCollection.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\RangeTree.cs">
- <Link>RangeTree.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\RangeTreeNode.cs">
- <Link>RangeTreeNode.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\ResourceManager.cs">
- <Link>ResourceManager.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\SelectCollection.cs">
- <Link>SelectCollection.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\StringBuffer.cs">
- <Link>StringBuffer.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\TextPoint.cs">
- <Link>TextPoint.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\UndoCommands.cs">
- <Link>UndoCommands.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\UndoManager.cs">
- <Link>UndoManager.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\Util.cs">
- <Link>Util.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\ViewBase.cs">
- <Link>ViewBase.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\WatchDogPattern.cs">
- <Link>WatchDogPattern.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\WinFileStream.cs">
- <Link>WinFileStream.cs</Link>
- </Compile>
<Compile Include="D2DTextRender.cs" />
<Compile Include="FooPrintText.cs" />
<Compile Include="FooTextBox.cs">
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="WinIME.cs" />
</ItemGroup>
+ <Import Project="..\..\Core\Core.projitems" Label="Shared" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
using System.Windows.Forms;
using FooEditEngine;
using FooEditEngine.Windows;
+using FooEditEngine.Test;
namespace Test.Windows
{
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
- <Compile Include="..\..\Common\Test\CharFoldingMethod.cs">
- <Link>CharFoldingMethod.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\Test\XmlHilighter.cs">
- <Link>XmlHilighter.cs</Link>
- </Compile>
<Compile Include="Form1.cs">
<SubType>Form</SubType>
</Compile>