OSDN Git Service

起動時にキャレットを表示させるようにした。これにともないタイマー起動タイミングを変更した
[fooeditengine/FooEditEngine.git] / Common / Controller.cs
1 /*\r
2  * Copyright (C) 2013 FooProject\r
3  * * 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
4  * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.\r
5 \r
6  * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of \r
7  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\r
8 \r
9 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
10  */\r
11 using System;\r
12 using System.Globalization;\r
13 using System.Text;\r
14 using System.Linq;\r
15 using System.Diagnostics;\r
16 using System.Text.RegularExpressions;\r
17 #if WINFORM\r
18 using System.Drawing;\r
19 #endif\r
20 \r
21 namespace FooEditEngine\r
22 {\r
23     internal enum MoveFlow\r
24     {\r
25         Horizontical,\r
26         Vertical,\r
27     }\r
28     internal enum ScrollDirection\r
29     {\r
30         Up,\r
31         Down,\r
32         Left,\r
33         Right,\r
34     }\r
35 \r
36     /// <summary>\r
37     /// インデントの方法を表す\r
38     /// </summary>\r
39     public enum IndentMode\r
40     {\r
41         Tab,\r
42         Space,\r
43     }\r
44 \r
45     /// <summary>\r
46     /// ユーザー側からの処理を担当するクラス。一部を除き、こちらで行われた操作はアンドゥの対象になります\r
47     /// </summary>\r
48     internal sealed class Controller\r
49     {\r
50         EditView View;\r
51         Document Document;\r
52         int AnchorIndex;\r
53         \r
54         public Controller(Document doc, EditView view)\r
55         {\r
56             this.Document = doc;\r
57             this.Document.Update += new DocumentUpdateEventHandler(Document_Update);\r
58             this.View = view;\r
59             this.View.render.ChangedRightToLeft += render_ChangedRightToLeft;\r
60             this.View.render.ChangedRenderResource += render_ChangedRenderResource;\r
61             this.View.PerformLayouted += View_LineBreakChanged;\r
62             this.View.PageBoundChanged += View_PageBoundChanged;\r
63             this.SelectionChanged += new EventHandler((s, e) => { });\r
64             this.Document.Clear();\r
65         }\r
66 \r
67         /// <summary>\r
68         /// 選択領域変更時に通知される\r
69         /// </summary>\r
70         public event EventHandler SelectionChanged;\r
71 \r
72         /// <summary>\r
73         /// 矩形選択モードなら真を返し、そうでない場合は偽を返す\r
74         /// </summary>\r
75         public bool RectSelection\r
76         {\r
77             get;\r
78             set;\r
79         }\r
80 \r
81         /// <summary>\r
82         /// インデントの方法を表す\r
83         /// </summary>\r
84         public IndentMode IndentMode\r
85         {\r
86             get;\r
87             set;\r
88         }\r
89 \r
90         /// <summary>\r
91         /// 選択範囲の開始位置\r
92         /// </summary>\r
93         /// <remarks>SelectionLengthが0の場合、キャレット位置を表します</remarks>\r
94         public int SelectionStart\r
95         {\r
96             get\r
97             {\r
98                 if (this.View.Selections.Count == 0)\r
99                     return this.AnchorIndex;\r
100                 else\r
101                     return this.View.Selections.First().start;\r
102             }\r
103         }\r
104 \r
105         /// <summary>\r
106         /// 選択範囲の長さ\r
107         /// </summary>\r
108         /// <remarks>矩形選択モードの場合、選択範囲の文字数ではなく、開始位置から終了位置までの長さとなります</remarks>\r
109         public int SelectionLength\r
110         {\r
111             get\r
112             {\r
113                 if (this.View.Selections.Count == 0)\r
114                     return 0;\r
115                 Selection last = this.View.Selections.Last();\r
116                 return last.start + last.length - this.SelectionStart;\r
117             }\r
118         }\r
119 \r
120         /// <summary>\r
121         /// 選択範囲内の文字列を返す\r
122         /// </summary>\r
123         /// <remarks>\r
124         /// 未選択状態で代入したときは追加され、そうでない場合は選択範囲の文字列と置き換えられます。\r
125         /// </remarks>\r
126         public string SelectedText\r
127         {\r
128             get\r
129             {\r
130                 if (this.View.LayoutLines.Count == 0 || this.View.Selections.Count == 0)\r
131                     return null;\r
132                 if (this.RectSelection)\r
133                     return GetTextFromRectangleSelectArea(this.View.Selections);\r
134                 else\r
135                     return GetTextFromLineSelectArea(this.View.Selections).Replace(Document.NewLine.ToString(), Environment.NewLine);\r
136             }\r
137             set\r
138             {\r
139                 if (this.Document.FireUpdateEvent == false)\r
140                     throw new InvalidOperationException("");\r
141                 if (value == null)\r
142                     return;\r
143                 this.RepleaceSelectionArea(this.View.Selections, value.Replace(Environment.NewLine,Document.NewLine.ToString()));\r
144             }\r
145         }\r
146 \r
147         /// <summary>\r
148         /// 選択範囲が逆転しているかどうかを判定する\r
149         /// </summary>\r
150         /// <returns>逆転しているなら真を返す</returns>\r
151         public bool IsReverseSelect()\r
152         {\r
153             int index = this.View.LayoutLines.GetIndexFromTextPoint(this.View.CaretPostion);\r
154             return index < this.AnchorIndex;\r
155         }\r
156 \r
157         /// <summary>\r
158         /// 指定された範囲を選択する\r
159         /// </summary>\r
160         /// <param name="start"></param>\r
161         /// <param name="length"></param>\r
162         /// <remarks>RectSelectionの値によって動作が変わります。真の場合は矩形選択モードに、そうでない場合は行ごとに選択されます</remarks>\r
163         public void Select(int start, int length)\r
164         {\r
165             if (this.Document.FireUpdateEvent == false)\r
166                 throw new InvalidOperationException("");\r
167             if (start < 0 || start + length < 0 || start + length > this.Document.Length)\r
168                 throw new ArgumentOutOfRangeException("startかendが指定できる範囲を超えてます");\r
169             this.View.Selections.Clear();\r
170             if (length < 0)\r
171             {\r
172                 int oldStart = start;\r
173                 start += length;\r
174                 length = oldStart - start;\r
175             }\r
176             if (this.RectSelection && length != 0)\r
177             {\r
178                 TextPoint startTextPoint = this.View.GetLayoutLineFromIndex(start);\r
179                 TextPoint endTextPoint = this.View.GetLayoutLineFromIndex(start + length);\r
180                 this.SelectByRectangle(new TextRectangle(startTextPoint, endTextPoint));\r
181                 if (startTextPoint.col == endTextPoint.col)\r
182                     this.View.InsertPoint = new SelectCollection(this.View.Selections);\r
183                 else\r
184                     this.View.InsertPoint = null;\r
185             }\r
186             else if(length != 0)\r
187             {\r
188                 this.View.Selections.Add(Selection.Create(start, length));\r
189                 this.View.InsertPoint = null;\r
190             }\r
191             this.SelectionChanged(this, null);\r
192         }\r
193 \r
194         public void Select(TextPoint tp, int width, int height)\r
195         {\r
196             if (this.Document.FireUpdateEvent == false || !this.RectSelection)\r
197                 throw new InvalidOperationException("");\r
198             TextPoint end = tp;\r
199 \r
200             end.row = tp.row + height;\r
201             end.col = tp.col + width;\r
202             \r
203             if (end.row > this.View.LayoutLines.Count - 1)\r
204                 throw new ArgumentOutOfRangeException("");\r
205             \r
206             this.View.Selections.Clear();\r
207             \r
208             this.SelectByRectangle(new TextRectangle(tp,end));\r
209             \r
210             if (width == 0)\r
211                 this.View.InsertPoint = new SelectCollection(this.View.Selections);\r
212             else\r
213                 this.View.InsertPoint = null;\r
214 \r
215             this.SelectionChanged(this, null);\r
216         }\r
217 \r
218         private void SelectByRectangle(TextRectangle rect)\r
219         {\r
220             if (this.Document.FireUpdateEvent == false)\r
221                 throw new InvalidOperationException("");\r
222             if (rect.TopLeft <= rect.BottomRight)\r
223             {\r
224                 for (int i = rect.TopLeft.row; i <= rect.BottomLeft.row; i++)\r
225                 {\r
226                     int length = this.View.LayoutLines.GetLengthFromLineNumber(i);\r
227                     int leftCol = rect.TopLeft.col, rightCol = rect.TopRight.col, lastCol = length;\r
228                     if(length > 0 && this.View.LayoutLines[i][length - 1] == Document.NewLine)\r
229                         lastCol =  length - 1;\r
230                     if (lastCol < 0)\r
231                         lastCol = 0;\r
232                     if (rect.TopLeft.col > lastCol)\r
233                         leftCol = lastCol;\r
234                     if (rect.TopRight.col > lastCol)\r
235                         rightCol = lastCol;\r
236 \r
237                     int StartIndex = this.View.LayoutLines.GetIndexFromTextPoint(new TextPoint(i, leftCol));\r
238                     int EndIndex = this.View.LayoutLines.GetIndexFromTextPoint(new TextPoint(i, rightCol));\r
239 \r
240                     Selection sel;\r
241                     sel = Selection.Create(StartIndex, EndIndex - StartIndex);\r
242 \r
243                     this.View.Selections.Add(sel);\r
244                 }\r
245             }\r
246         }\r
247 \r
248         /// <summary>\r
249         /// 単語単位で選択する\r
250         /// </summary>\r
251         /// <param name="index">探索を開始するインデックス</param>\r
252         public void SelectWord(int index)\r
253         {\r
254             if (this.Document.FireUpdateEvent == false)\r
255                 throw new InvalidOperationException("");\r
256 \r
257             if (this.Document.Length <= 0 || index >= this.Document.Length)\r
258                 return;\r
259 \r
260             Document str = this.Document;\r
261 \r
262             int start = index;\r
263             while (start > 0 && !Util.IsWordSeparator(str[start]))\r
264                 start--;\r
265 \r
266             if (Util.IsWordSeparator(str[start]))\r
267                 start++;\r
268 \r
269             int end = index;\r
270             while (end < this.Document.Length && !Util.IsWordSeparator(str[end]))\r
271                 end++;\r
272 \r
273             this.Select(start, end - start);\r
274         }\r
275 \r
276         /// <summary>\r
277         /// 選択範囲内のUTF32コードポイントを文字列に変換します\r
278         /// </summary>\r
279         /// <returns>成功した場合は真。そうでない場合は偽を返す</returns>\r
280         public bool ConvertToChar()\r
281         {\r
282             if (this.SelectionLength == 0 || this.RectSelection)\r
283                 return false;\r
284             string str = this.Document.ToString(this.SelectionStart, this.SelectionLength);\r
285             string[] codes = str.Split(new char[] { ' ' },StringSplitOptions.RemoveEmptyEntries);\r
286             StringBuilder result = new StringBuilder();\r
287             foreach (string code in codes)\r
288             {\r
289                 int utf32_code;\r
290                 if (code[0] != 'U')\r
291                     return false;\r
292                 if (Int32.TryParse(code.TrimStart('U'),NumberStyles.HexNumber,null, out utf32_code))\r
293                     result.Append(Char.ConvertFromUtf32(utf32_code));\r
294                 else\r
295                     return false;\r
296             }\r
297             this.Document.Lock();\r
298             this.Document.Replace(this.SelectionStart, this.SelectionLength, result.ToString());\r
299             this.Document.UnLock();\r
300             return true;\r
301         }\r
302 \r
303         /// <summary>\r
304         /// 選択文字列をUTF32のコードポイントに変換します\r
305         /// </summary>\r
306         public void ConvertToCodePoint()\r
307         {\r
308             if (this.SelectionLength == 0 || this.RectSelection)\r
309                 return;\r
310             string str = this.Document.ToString(this.SelectionStart, this.SelectionLength);\r
311             StringInfo info = new StringInfo(str);\r
312             StringBuilder result = new StringBuilder();\r
313             for (int i = 0; i < str.Length;)\r
314             {\r
315                 int utf32_code = Char.ConvertToUtf32(str, i); \r
316                 result.Append("U" + Convert.ToString(utf32_code,16));\r
317                 result.Append(' ');\r
318                 if(Char.IsHighSurrogate(str[i]))\r
319                     i += 2;\r
320                 else\r
321                     i++;\r
322             }\r
323             this.Document.Lock();\r
324             this.Document.Replace(this.SelectionStart, this.SelectionLength, result.ToString());\r
325             this.Document.UnLock();\r
326         }\r
327 \r
328         /// <summary>\r
329         /// 選択を解除する\r
330         /// </summary>\r
331         public void DeSelectAll()\r
332         {\r
333             if (this.Document.FireUpdateEvent == false)\r
334                 throw new InvalidOperationException("");\r
335 \r
336             this.View.Selections.Clear();\r
337         }\r
338 \r
339         /// <summary>\r
340         /// 任意のマーカーかどうか\r
341         /// </summary>\r
342         /// <param name="tp"></param>\r
343         /// <param name="type"></param>\r
344         /// <returns>真ならマーカーがある</returns>\r
345         public bool IsMarker(TextPoint tp,HilightType type)\r
346         {\r
347             if (this.Document.FireUpdateEvent == false)\r
348                 throw new InvalidOperationException("");\r
349             int index = this.View.LayoutLines.GetIndexFromTextPoint(tp);\r
350             return this.IsMarker(index, type);\r
351         }\r
352 \r
353         /// <summary>\r
354         /// 任意のマーカーかどうか判定する\r
355         /// </summary>\r
356         /// <param name="index"></param>\r
357         /// <param name="type"></param>\r
358         /// <returns>真ならマーカーがある</returns>\r
359         public bool IsMarker(int index, HilightType type)\r
360         {\r
361             foreach(int id in this.Document.Markers.IDs)\r
362             {\r
363                 foreach (Marker m in this.Document.GetMarkers(index, id))\r
364                 {\r
365                     if (m.hilight == type)\r
366                         return true;\r
367                 }\r
368             }\r
369             return false;\r
370         }\r
371 \r
372         /// <summary>\r
373         /// キャレット位置を再調整する\r
374         /// </summary>\r
375         public void AdjustCaret()\r
376         {\r
377             int row = this.View.CaretPostion.row;\r
378             if (row > this.View.LayoutLines.Count - 1)\r
379                 row = this.View.LayoutLines.Count - 1;\r
380             int col = this.View.CaretPostion.col;\r
381             if (col > 0 && col > this.View.LayoutLines[row].Length)\r
382                 col = this.View.LayoutLines[row].Length;\r
383             this.JumpCaret(row, col);\r
384         }\r
385 \r
386         /// <summary>\r
387         /// キャレットを指定した位置に移動させる\r
388         /// </summary>\r
389         /// <param name="index"></param>\r
390         /// <param name="autoExpand">折り畳みを展開するなら真</param>\r
391         public void JumpCaret(int index,bool autoExpand = true)\r
392         {\r
393             if (index < 0 || index > this.Document.Length)\r
394                 throw new ArgumentOutOfRangeException("indexが設定できる範囲を超えています");\r
395             TextPoint tp = this.View.GetLayoutLineFromIndex(index);\r
396 \r
397             this.JumpCaret(tp.row, tp.col,autoExpand);\r
398          }\r
399 \r
400         /// <summary>\r
401         /// キャレットを指定した位置に移動させる\r
402         /// </summary>\r
403         /// <param name="row"></param>\r
404         /// <param name="col"></param>\r
405         /// <param name="autoExpand">折り畳みを展開するなら真</param>\r
406         public void JumpCaret(int row, int col, bool autoExpand = true)\r
407         {\r
408             if (this.Document.FireUpdateEvent == false)\r
409                 throw new InvalidOperationException("");\r
410 \r
411             this.View.JumpCaret(row, col,autoExpand);\r
412 \r
413             this.View.AdjustCaretAndSrc();\r
414 \r
415             this.SelectWithMoveCaret(false);\r
416         }\r
417 \r
418         /// <summary>\r
419         /// 行の先頭に移動する\r
420         /// </summary>\r
421         /// <param name="row">行</param>\r
422         /// <param name="isSelected">選択状態にするかどうか</param>\r
423         public void JumpToLineHead(int row,bool isSelected)\r
424         {\r
425             this.View.JumpCaret(row, 0);\r
426             this.View.AdjustCaretAndSrc();\r
427             this.SelectWithMoveCaret(isSelected);\r
428         }\r
429 \r
430         /// <summary>\r
431         /// 行の終わりに移動する\r
432         /// </summary>\r
433         /// <param name="row">行</param>\r
434         /// <param name="isSelected">選択状態にするかどうか</param>\r
435         public void JumpToLineEnd(int row, bool isSelected)\r
436         {\r
437             this.View.JumpCaret(row, this.View.LayoutLines[row].Length - 1);\r
438             this.View.AdjustCaretAndSrc();\r
439             this.SelectWithMoveCaret(isSelected);\r
440         }\r
441 \r
442         /// <summary>\r
443         /// ドキュメントの先頭に移動する\r
444         /// </summary>\r
445         /// <param name="isSelected"></param>\r
446         public void JumpToHead(bool isSelected)\r
447         {\r
448             if (this.View.TryScroll(0, 0))\r
449                 return;\r
450             this.View.JumpCaret(0, 0);\r
451             this.View.AdjustCaretAndSrc();\r
452             this.SelectWithMoveCaret(isSelected);\r
453         }\r
454 \r
455         /// <summary>\r
456         /// ドキュメントの終わりにに移動する\r
457         /// </summary>\r
458         /// <param name="isSelected"></param>\r
459         public void JumpToEnd(bool isSelected)\r
460         {\r
461             int srcRow = this.View.LayoutLines.Count - this.View.LineCountOnScreen - 1;\r
462             if(srcRow < 0)\r
463                 srcRow = 0;\r
464             if (this.View.TryScroll(0, srcRow))\r
465                 return;\r
466             this.View.JumpCaret(this.View.LayoutLines.Count - 1, 0);\r
467             this.View.AdjustCaretAndSrc();\r
468             this.SelectWithMoveCaret(isSelected);\r
469         }\r
470 \r
471         /// <summary>\r
472         /// スクロールする\r
473         /// </summary>\r
474         /// <param name="dir">方向を指定する</param>\r
475         /// <param name="delta">スクロールする量。ScrollDirectionの値がUpやDownなら行数。LeftやRightならピクセル単位の値となる</param>\r
476         /// <param name="isSelected">選択状態にするなら真</param>\r
477         /// <param name="withCaret">同時にキャレットを移動させるなら真</param>\r
478         public void Scroll(ScrollDirection dir, int delta, bool isSelected,bool withCaret)\r
479         {\r
480             if (this.Document.FireUpdateEvent == false)\r
481                 throw new InvalidOperationException("");\r
482             int toRow = this.View.Src.Row;\r
483             double toX = this.View.Src.X;\r
484             switch (dir)\r
485             {\r
486                 case ScrollDirection.Up:\r
487                     toRow = Math.Max(0, this.View.Src.Row - delta);\r
488                     toRow = this.View.AdjustRow(toRow, false);\r
489                     break;\r
490                 case ScrollDirection.Down:\r
491                     toRow = Math.Min(this.View.Src.Row + delta, this.View.LayoutLines.Count - 1);\r
492                     toRow = this.View.AdjustRow(toRow, true);\r
493                     break;\r
494                 case ScrollDirection.Left:\r
495                     toX -= delta;\r
496                     break;\r
497                 case ScrollDirection.Right:\r
498                     toX += delta;\r
499                     break;\r
500                 default:\r
501                     throw new ArgumentOutOfRangeException();\r
502             }\r
503             this.Scroll(toX, toRow, isSelected, withCaret);\r
504         }\r
505 \r
506         /// <summary>\r
507         /// スクロールする\r
508         /// </summary>\r
509         /// <param name="toX">スクロール先の座標</param>\r
510         /// <param name="toRow">スクロール先の行</param>\r
511         /// <param name="isSelected">選択状態にするなら真</param>\r
512         /// <param name="withCaret">同時にキャレットを移動させるなら真</param>\r
513         public void Scroll(double toX, int toRow, bool isSelected, bool withCaret)\r
514         {\r
515             if (withCaret)\r
516             {\r
517                 this.View.Scroll(toX, toRow);\r
518                 this.View.JumpCaret(toRow, 0);\r
519                 this.View.AdjustCaretAndSrc();\r
520                 this.SelectWithMoveCaret(isSelected);\r
521             }\r
522             else\r
523             {\r
524                 this.View.Scroll(toX, toRow);\r
525                 this.View.IsFocused = false;\r
526             }\r
527         }\r
528 \r
529         /// <summary>\r
530         /// キャレットを桁方向に移動させる\r
531         /// </summary>\r
532         /// <returns>移動できない場合は真を返す</returns>\r
533         /// <param name="realLength">負の値なら左側へ、そうでないなら右側へ移動する</param>\r
534         /// <param name="isSelected">選択範囲とするなら真。そうでないなら偽</param>\r
535         /// <param name="alignWord">単語単位で移動するなら真。そうでないなら偽</param>\r
536         public void MoveCaretHorizontical(int realLength, bool isSelected,bool alignWord = false)\r
537         {\r
538             for (int i = Math.Abs(realLength); i > 0; i--)\r
539             {\r
540                 bool MoveFlow = realLength > 0;\r
541                 if (this.View.render.RightToLeft)\r
542                     MoveFlow = !MoveFlow;\r
543                 this.MoveCaretHorizontical(MoveFlow);\r
544 \r
545                 if (alignWord)\r
546                     this.AlignNearestWord(MoveFlow);\r
547             }\r
548             this.View.AdjustCaretAndSrc(AdjustFlow.Col);\r
549             this.SelectWithMoveCaret(isSelected);\r
550         }\r
551 \r
552         void AlignNearestWord(bool MoveFlow)\r
553         {\r
554             string str = this.View.LayoutLines[this.View.CaretPostion.row];\r
555             while (this.View.CaretPostion.col > 0 &&\r
556                 this.View.CaretPostion.col < str.Length &&\r
557                 str[this.View.CaretPostion.col] != Document.NewLine)\r
558             {\r
559                 if (!Util.IsWordSeparator(str[this.View.CaretPostion.col]))\r
560                 {\r
561                     this.MoveCaretHorizontical(MoveFlow);\r
562                 }\r
563                 else\r
564                 {\r
565                     if(MoveFlow)\r
566                         this.MoveCaretHorizontical(MoveFlow);\r
567                     break;\r
568                 }\r
569             }\r
570         }\r
571 \r
572         /// <summary>\r
573         /// キャレットを行方向に移動させる\r
574         /// </summary>\r
575         /// <returns>再描写する必要があるなら真を返す</returns>\r
576         /// <param name="deltarow">移動量</param>\r
577         /// <param name="isSelected"></param>\r
578         public void MoveCaretVertical(int deltarow,bool isSelected)\r
579         {\r
580             for (int i = Math.Abs(deltarow); i > 0; i--)\r
581                 this.MoveCaretVertical(deltarow > 0);\r
582             this.View.AdjustCaretAndSrc(AdjustFlow.Both);\r
583             this.SelectWithMoveCaret(isSelected);\r
584         }\r
585 \r
586         /// <summary>\r
587         /// キャレット位置の文字を一文字削除する\r
588         /// </summary>\r
589         public void DoDeleteAction()\r
590         {\r
591             if (this.SelectionLength != 0)\r
592             {\r
593                 this.SelectedText = "";\r
594                 return;\r
595             }\r
596             \r
597             if (this.Document.FireUpdateEvent == false)\r
598                 throw new InvalidOperationException("");\r
599 \r
600             TextPoint CaretPostion = this.View.CaretPostion;\r
601             int index = this.View.GetIndexFromLayoutLine(CaretPostion);\r
602 \r
603             if (index == this.Document.Length)\r
604                 return;\r
605 \r
606             int lineHeadIndex = this.View.LayoutLines.GetIndexFromLineNumber(CaretPostion.row);\r
607             int next = this.View.LayoutLines.GetLayout(CaretPostion.row).AlignIndexToNearestCluster(CaretPostion.col, AlignDirection.Forward) + lineHeadIndex;\r
608 \r
609             if (this.Document[index] == Document.NewLine)\r
610                 next = index + 1;\r
611 \r
612             this.Document.Lock();\r
613             this.Document.Replace(index, next - index, "");\r
614             this.Document.UnLock();\r
615         }\r
616 \r
617         /// <summary>\r
618         /// キャレット位置の文字を一文字削除し、キャレット位置を後ろにずらす\r
619         /// </summary>\r
620         public void DoBackSpaceAction()\r
621         {\r
622             if (this.View.InsertPoint != null)\r
623             {\r
624                 this.ReplaceBeforeSelectionArea(this.View.Selections, 1, "");\r
625                 return;\r
626             }\r
627             else if (this.SelectionLength > 0)\r
628             {\r
629                 this.SelectedText = "";\r
630                 return;\r
631             }\r
632 \r
633             if (this.Document.FireUpdateEvent == false)\r
634                 throw new InvalidOperationException("");\r
635 \r
636             TextPoint CurrentPostion = this.View.CaretPostion;\r
637 \r
638             if (CurrentPostion.row == 0 && CurrentPostion.col == 0)\r
639                 return;\r
640 \r
641             int oldIndex = this.View.GetIndexFromLayoutLine(CurrentPostion);\r
642 \r
643             int newCol, newIndex;\r
644             if (CurrentPostion.col > 0)\r
645             {\r
646                 newCol = this.View.LayoutLines.GetLayout(CurrentPostion.row).AlignIndexToNearestCluster(CurrentPostion.col - 1, AlignDirection.Back);\r
647                 newIndex = this.View.GetIndexFromLayoutLine(new TextPoint(CurrentPostion.row, newCol));\r
648             }\r
649             else\r
650             {\r
651                 newIndex = this.View.GetIndexFromLayoutLine(CurrentPostion);\r
652                 newIndex--;\r
653             }\r
654 \r
655             this.Document.Lock();\r
656             this.Document.Replace(newIndex, oldIndex - newIndex, "");\r
657             this.Document.UnLock();\r
658         }\r
659 \r
660         /// <summary>\r
661         /// キャレット位置で行を分割する\r
662         /// </summary>\r
663         public void DoEnterAction()\r
664         {            \r
665             this.DoInputChar('\n');\r
666         }\r
667 \r
668         /// <summary>\r
669         /// キャレット位置に文字を入力し、その分だけキャレットを進める。isInsertModeの値により動作が変わります\r
670         /// </summary>\r
671         /// <param name="ch"></param>\r
672         public void DoInputChar(char ch)\r
673         {\r
674             this.DoInputString(ch.ToString());\r
675         }\r
676 \r
677         string GetIndentSpace(int col_index)\r
678         {\r
679             int space_count = this.View.TabStops - (col_index % this.View.TabStops);\r
680             return new string(Enumerable.Repeat(' ',space_count).ToArray());\r
681         }\r
682 \r
683         /// <summary>\r
684         /// キャレット位置に文字列を挿入し、その分だけキャレットを進める。isInsertModeの値により動作が変わります\r
685         /// </summary>\r
686         /// <param name="str"></param>\r
687         /// <param name="fromTip"></param>\r
688         public void DoInputString(string str,bool fromTip = false)\r
689         {\r
690             TextPoint CaretPos = this.View.CaretPostion;\r
691 \r
692             if (str == "\t" && this.IndentMode == IndentMode.Space)\r
693                 str = this.GetIndentSpace(CaretPos.col);\r
694 \r
695             if (this.View.InsertPoint != null)\r
696             {\r
697                 this.ReplaceBeforeSelectionArea(this.View.Selections, 0, str);\r
698                 return;\r
699             }\r
700             else if (this.SelectionLength != 0)\r
701             {\r
702                 this.RepleaceSelectionArea(this.View.Selections, str, fromTip);\r
703                 return;\r
704             }\r
705 \r
706             if (this.Document.FireUpdateEvent == false)\r
707                 throw new InvalidOperationException("");\r
708 \r
709             int index = this.View.GetIndexFromLayoutLine(this.View.CaretPostion);\r
710             int length = 0;\r
711             if (this.View.InsertMode == false && index < this.Document.Length && this.Document[index] != Document.NewLine)\r
712             {\r
713                 string lineString = this.View.LayoutLines[CaretPos.row];\r
714                 int end = this.View.LayoutLines.GetLayout(CaretPos.row).AlignIndexToNearestCluster(CaretPos.col + str.Length - 1, AlignDirection.Forward);\r
715                 if (end > lineString.Length - 1)\r
716                     end = lineString.Length - 1;\r
717                 end += this.View.LayoutLines.GetIndexFromLineNumber(CaretPos.row);\r
718                 length = end - index;\r
719             }\r
720             if (str == Document.NewLine.ToString())\r
721             {\r
722                 int lineHeadIndex = this.View.LayoutLines.GetIndexFromLineNumber(CaretPos.row);\r
723                 int lineLength = this.View.LayoutLines.GetLengthFromLineNumber(CaretPos.row);\r
724                 FoldingItem foldingData = this.View.LayoutLines.FoldingCollection.GetFarestHiddenFoldingData(lineHeadIndex, lineLength);\r
725                 if (foldingData != null && !foldingData.Expand && index > foldingData.Start && index <= foldingData.End)\r
726                     index = foldingData.End + 1;\r
727             }\r
728             this.Document.Lock();\r
729             this.Document.Replace(index, length, str);\r
730             this.Document.UnLock();\r
731         }\r
732 \r
733         /// <summary>\r
734         /// キャレットの移動に合わせて選択する\r
735         /// </summary>\r
736         /// <param name="isSelected">選択状態にするかどうか</param>\r
737         /// <remarks>\r
738         /// キャレットを移動後、このメソッドを呼び出さない場合、Select()メソッドは正常に機能しません\r
739         /// </remarks>\r
740         void SelectWithMoveCaret(bool isSelected)\r
741         {\r
742             if (this.View.CaretPostion.col < 0 || this.View.CaretPostion.row < 0)\r
743                 return;\r
744 \r
745             if (this.Document.FireUpdateEvent == false)\r
746                 throw new InvalidOperationException("");\r
747 \r
748             int CaretPostion = this.View.GetIndexFromLayoutLine(this.View.CaretPostion);\r
749             \r
750             SelectCollection Selections = this.View.Selections;\r
751             if (isSelected)\r
752             {\r
753                 this.Select(this.AnchorIndex, CaretPostion - this.AnchorIndex);\r
754             }else{\r
755                 this.AnchorIndex = CaretPostion;\r
756                 this.View.InsertPoint = null;\r
757                 this.Select(CaretPostion, 0);\r
758             }\r
759         }\r
760 \r
761         /// <summary>\r
762         /// JumpCaretで移動した位置からキャレットを移動し、選択状態にする\r
763         /// </summary>\r
764         /// <param name="tp"></param>\r
765         public void MoveCaretAndSelect(TextPoint tp)\r
766         {\r
767             int CaretPostion = this.View.GetIndexFromLayoutLine(tp);\r
768             this.Select(this.AnchorIndex, CaretPostion - this.AnchorIndex);\r
769             this.View.JumpCaret(tp.row, tp.col);\r
770             this.View.AdjustCaretAndSrc();\r
771         }\r
772 \r
773         public void MoveSelectBefore(TextPoint tp)\r
774         {\r
775             int NewAnchorIndex;\r
776             int SelectionLength;\r
777             if (this.IsReverseSelect())\r
778             {\r
779                 NewAnchorIndex = this.View.GetIndexFromLayoutLine(tp);\r
780                 SelectionLength = this.SelectionLength + NewAnchorIndex - this.AnchorIndex;\r
781                 this.Select(this.SelectionStart, SelectionLength);\r
782             }\r
783             else\r
784             {\r
785                 NewAnchorIndex = this.View.GetIndexFromLayoutLine(tp);\r
786                 SelectionLength = this.SelectionLength + this.AnchorIndex - NewAnchorIndex;\r
787                 this.Select(NewAnchorIndex, SelectionLength);\r
788             }\r
789             this.AnchorIndex = NewAnchorIndex;\r
790         }\r
791 \r
792         /// <summary>\r
793         /// キャレット位置を既定の位置に戻す\r
794         /// </summary>\r
795         public void ResetCaretPostion()\r
796         {\r
797             this.JumpCaret(0);\r
798         }\r
799 \r
800         /// <summary>\r
801         /// 行単位で移動後のキャレット位置を取得する\r
802         /// </summary>\r
803         /// <param name="count">移動量</param>\r
804         /// <param name="current">現在のキャレット位置</param>\r
805         /// <returns>移動後のキャレット位置</returns>\r
806         public TextPoint GetTextPointAfterMoveLine(int count, TextPoint current)\r
807         {\r
808             int row = current.row + count;\r
809 \r
810             if (row < 0)\r
811                 row = 0;\r
812             else if (row >= this.View.LayoutLines.Count)\r
813                 row = this.View.LayoutLines.Count - 1;\r
814 \r
815             row = this.View.AdjustRow(row, count > 0);\r
816 \r
817             double colpos = this.View.GetColPostionFromIndex(current.row, current.col);\r
818             int col = this.View.GetIndexFromColPostion(row, colpos);\r
819 \r
820             return new TextPoint(row, col);\r
821         }\r
822 \r
823         /// <summary>\r
824         /// 選択文字列のインデントを一つ増やす\r
825         /// </summary>\r
826         public void UpIndent()\r
827         {\r
828             if (this.RectSelection || this.SelectionLength == 0)\r
829                 return;\r
830             int selectionStart = this.SelectionStart;\r
831             string insertStr = this.IndentMode == IndentMode.Space ? this.GetIndentSpace(0) : "\t";\r
832             string text = this.InsertLineHead(GetTextFromLineSelectArea(this.View.Selections), insertStr);\r
833             this.RepleaceSelectionArea(this.View.Selections,text);\r
834             this.Select(selectionStart, text.Length);\r
835         }\r
836 \r
837         /// <summary>\r
838         /// 選択文字列のインデントを一つ減らす\r
839         /// </summary>\r
840         public void DownIndent()\r
841         {\r
842             if (this.RectSelection || this.SelectionLength == 0)\r
843                 return;\r
844             int selectionStart = this.SelectionStart;\r
845             string insertStr = this.IndentMode == IndentMode.Space ? this.GetIndentSpace(0) : "\t";\r
846             string text = this.RemoveLineHead(GetTextFromLineSelectArea(this.View.Selections), insertStr);\r
847             this.RepleaceSelectionArea(this.View.Selections, text);\r
848             this.Select(selectionStart, text.Length);\r
849         }\r
850 \r
851         string InsertLineHead(string s, string str)\r
852         {\r
853             string[] lines = s.Split(new string[] { Document.NewLine.ToString() }, StringSplitOptions.None);\r
854             StringBuilder output = new StringBuilder();\r
855             for (int i = 0; i < lines.Length; i++)\r
856             {\r
857                 if(lines[i].Length > 0)\r
858                     output.Append(str + lines[i] + Document.NewLine);\r
859                 else if(i < lines.Length - 1)\r
860                     output.Append(lines[i] + Document.NewLine);\r
861             }\r
862             return output.ToString();\r
863         }\r
864 \r
865         public string RemoveLineHead(string s, string str)\r
866         {\r
867             string[] lines = s.Split(new string[] { Document.NewLine.ToString() }, StringSplitOptions.None);\r
868             StringBuilder output = new StringBuilder();\r
869             for (int i = 0; i < lines.Length; i++)\r
870             {\r
871                 if (lines[i].StartsWith(str))\r
872                     output.Append(lines[i].Substring(1) + Document.NewLine);\r
873                 else if (i < lines.Length - 1)\r
874                     output.Append(lines[i] + Document.NewLine);\r
875             }\r
876             return output.ToString();\r
877         }\r
878 \r
879         /// <summary>\r
880         /// キャレットを一文字移動させる\r
881         /// </summary>\r
882         /// <param name="isMoveNext">真なら1文字すすめ、そうでなければ戻す</param>\r
883         /// <remarks>このメソッドを呼び出した後でScrollToCaretメソッドとSelectWithMoveCaretメソッドを呼び出す必要があります</remarks>\r
884         void MoveCaretHorizontical(bool isMoveNext)\r
885         {\r
886             if (this.Document.FireUpdateEvent == false)\r
887                 throw new InvalidOperationException("");\r
888             int delta = isMoveNext ? 0 : -1;\r
889             int prevcol = this.View.CaretPostion.col;\r
890             int col = this.View.CaretPostion.col + delta;\r
891             string lineString = this.View.LayoutLines[this.View.CaretPostion.row];\r
892             if (col < 0 || this.View.CaretPostion.row >= this.View.LayoutLines.Count)\r
893             {\r
894                 if (this.View.CaretPostion.row == 0)\r
895                 {\r
896                     col = 0;\r
897                     return;\r
898                 }\r
899                 this.MoveCaretVertical(false);\r
900                 this.View.AdjustCaretAndSrc(AdjustFlow.Row);  //この段階で調整しないとスクロールされない\r
901                 col = this.View.LayoutLines.GetLengthFromLineNumber(this.View.CaretPostion.row) - 1;  //最終行以外はすべて改行コードが付くはず\r
902             }\r
903             else if (col >= lineString.Length || lineString[col] == Document.NewLine)\r
904             {\r
905                 if (this.View.CaretPostion.row < this.View.LayoutLines.Count - 1)\r
906                 {\r
907                     this.MoveCaretVertical(true);\r
908                     this.View.AdjustCaretAndSrc(AdjustFlow.Row);  //この段階で調整しないとスクロールされない\r
909                     col = 0;\r
910                 }\r
911             }\r
912             else\r
913             {\r
914                 AlignDirection direction = isMoveNext ? AlignDirection.Forward : AlignDirection.Back;\r
915                 col = this.View.LayoutLines.GetLayout(this.View.CaretPostion.row).AlignIndexToNearestCluster(col, direction);\r
916             }\r
917 \r
918             this.View.JumpCaret(this.View.CaretPostion.row, col,false);\r
919         }\r
920 \r
921         /// <summary>\r
922         /// キャレットを行方向に移動させる\r
923         /// </summary>\r
924         /// <param name="isMoveNext">プラス方向に移動するなら真</param>\r
925         /// <remarks>このメソッドを呼び出した後でScrollToCaretメソッドとSelectWithMoveCaretメソッドを呼び出す必要があります</remarks>\r
926         void MoveCaretVertical(bool isMoveNext)\r
927         {\r
928             if (this.Document.FireUpdateEvent == false)\r
929                 throw new InvalidOperationException("");\r
930 \r
931             TextPoint nextPoint = this.GetTextPointAfterMoveLine(isMoveNext ? 1 : -1, this.View.CaretPostion);\r
932             \r
933             this.View.JumpCaret(nextPoint.row, nextPoint.col,false);\r
934         }\r
935 \r
936         private void ReplaceBeforeSelectionArea(SelectCollection Selections, int removeLength, string insertStr)\r
937         {\r
938             if (removeLength == 0 && insertStr.Length == 0)\r
939                 return;\r
940 \r
941             if (this.RectSelection == false || this.Document.FireUpdateEvent == false)\r
942                 throw new InvalidOperationException();\r
943 \r
944             SelectCollection temp = this.View.InsertPoint;\r
945             int selectStart = temp.First().start;\r
946             int selectEnd = temp.Last().start + temp.Last().length;\r
947 \r
948             //ドキュメント操作後に行うとうまくいかないので、あらかじめ取得しておく\r
949             TextPoint start = this.View.LayoutLines.GetTextPointFromIndex(selectStart);\r
950             TextPoint end = this.View.LayoutLines.GetTextPointFromIndex(selectEnd);\r
951 \r
952             bool reverse = temp.First().start > temp.Last().start;\r
953 \r
954             int lineHeadIndex = this.View.LayoutLines.GetIndexFromLineNumber(this.View.LayoutLines.GetLineNumberFromIndex(selectStart));\r
955             if (selectStart - removeLength < lineHeadIndex)\r
956                 return;\r
957 \r
958             this.Document.UndoManager.BeginUndoGroup();\r
959             this.Document.FireUpdateEvent = false;\r
960 \r
961             if (reverse)\r
962             {\r
963                 for (int i = 0; i < temp.Count; i++)\r
964                 {\r
965                     this.ReplaceBeforeSelection(temp[i], removeLength, insertStr);\r
966                 }\r
967             }\r
968             else\r
969             {\r
970                 for (int i = temp.Count - 1; i >= 0; i--)\r
971                 {\r
972                     this.ReplaceBeforeSelection(temp[i], removeLength, insertStr);\r
973                 }\r
974             }\r
975 \r
976             this.Document.FireUpdateEvent = true;\r
977             this.Document.UndoManager.EndUndoGroup();\r
978 \r
979             int delta = insertStr.Length - removeLength;\r
980             start.col += delta;\r
981             end.col += delta;\r
982 \r
983             if (reverse)\r
984                 this.JumpCaret(start.row, start.col);\r
985             else\r
986                 this.JumpCaret(end.row, end.col);\r
987             \r
988             this.Select(start, 0, end.row - start.row);\r
989         }\r
990 \r
991         private void ReplaceBeforeSelection(Selection sel, int removeLength, string insertStr)\r
992         {\r
993             sel = Util.NormalizeIMaker<Selection>(sel);\r
994             this.Document.Lock();\r
995             this.Document.Replace(sel.start - removeLength, removeLength, insertStr);\r
996             this.Document.UnLock();\r
997         }\r
998 \r
999         private void RepleaceSelectionArea(SelectCollection Selections, string value,bool updateInsertPoint = false)\r
1000         {\r
1001             if (value == null)\r
1002                 return;\r
1003 \r
1004             if (this.RectSelection == false)\r
1005             {\r
1006                 Selection sel = Selection.Create(this.AnchorIndex, 0);\r
1007                 if (Selections.Count > 0)\r
1008                     sel = Util.NormalizeIMaker<Selection>(this.View.Selections.First());\r
1009 \r
1010                 this.Document.Lock();\r
1011                 this.Document.Replace(sel.start, sel.length, value);\r
1012                 this.Document.UnLock();\r
1013                 return;\r
1014             }\r
1015 \r
1016             if (this.Document.FireUpdateEvent == false)\r
1017                 throw new InvalidOperationException("");\r
1018 \r
1019             int StartIndex = this.SelectionStart;\r
1020 \r
1021             SelectCollection newInsertPoint = new SelectCollection();\r
1022 \r
1023             if (this.SelectionLength == 0)\r
1024             {\r
1025                 int i;\r
1026 \r
1027                 this.Document.Lock();\r
1028 \r
1029                 this.Document.UndoManager.BeginUndoGroup();\r
1030 \r
1031                 this.Document.FireUpdateEvent = false;\r
1032 \r
1033                 string[] line = value.Split(new string[] { Document.NewLine.ToString() }, StringSplitOptions.RemoveEmptyEntries);\r
1034 \r
1035                 TextPoint Current = this.View.GetLayoutLineFromIndex(this.SelectionStart);\r
1036 \r
1037                 for (i = 0; i < line.Length && Current.row < this.View.LayoutLines.Count; i++, Current.row++)\r
1038                 {\r
1039                     if (Current.col > this.View.LayoutLines[Current.row].Length)\r
1040                         Current.col = this.View.LayoutLines[Current.row].Length;\r
1041                     StartIndex = this.View.GetIndexFromLayoutLine(Current);\r
1042                     this.Document.Replace(StartIndex, 0, line[i]);\r
1043                     StartIndex += line[i].Length;\r
1044                 }\r
1045 \r
1046                 for (; i < line.Length; i++)\r
1047                 {\r
1048                     StartIndex = this.Document.Length;\r
1049                     string str = Document.NewLine + line[i];\r
1050                     this.Document.Replace(StartIndex, 0, str);\r
1051                     StartIndex += str.Length;\r
1052                 }\r
1053 \r
1054                 this.Document.FireUpdateEvent = true;\r
1055 \r
1056                 this.Document.UndoManager.EndUndoGroup();\r
1057 \r
1058                 this.Document.UnLock();\r
1059             }\r
1060             else\r
1061             {\r
1062                 SelectCollection temp = new SelectCollection(this.View.Selections); //コピーしないとReplaceCommandを呼び出した段階で書き換えられてしまう\r
1063 \r
1064                 this.Document.Lock();\r
1065 \r
1066                 this.Document.UndoManager.BeginUndoGroup();\r
1067 \r
1068                 this.Document.FireUpdateEvent = false;\r
1069 \r
1070                 if (temp.First().start < temp.Last().start)\r
1071                 {\r
1072                     for (int i = temp.Count - 1; i >= 0; i--)\r
1073                     {\r
1074                         Selection sel = Util.NormalizeIMaker<Selection>(temp[i]);\r
1075 \r
1076                         StartIndex = sel.start;\r
1077 \r
1078                         this.Document.Replace(sel.start, sel.length, value);\r
1079 \r
1080                         newInsertPoint.Add(Selection.Create(sel.start + (value.Length - sel.length) * i,0));\r
1081                     }\r
1082                 }\r
1083                 else\r
1084                 {\r
1085                     for (int i = 0; i < temp.Count; i++)\r
1086                     {\r
1087                         Selection sel = Util.NormalizeIMaker<Selection>(temp[i]);\r
1088 \r
1089                         StartIndex = sel.start;\r
1090 \r
1091                         this.Document.Replace(sel.start, sel.length, value);\r
1092 \r
1093                         newInsertPoint.Add(Selection.Create(sel.start + (value.Length - sel.length) * i, 0));\r
1094                     }\r
1095                 }\r
1096 \r
1097                 this.Document.FireUpdateEvent = true;\r
1098 \r
1099                 this.Document.UndoManager.EndUndoGroup();\r
1100 \r
1101                 this.Document.UnLock();\r
1102             }\r
1103             this.JumpCaret(StartIndex);\r
1104             if (updateInsertPoint && newInsertPoint.Count > 0)\r
1105                 this.View.InsertPoint = newInsertPoint;\r
1106         }\r
1107 \r
1108         private string GetTextFromLineSelectArea(SelectCollection Selections)\r
1109         {\r
1110             Selection sel = Util.NormalizeIMaker<Selection>(Selections.First());\r
1111 \r
1112             string str = this.Document.ToString(sel.start, sel.length);\r
1113 \r
1114             return str;\r
1115         }\r
1116 \r
1117         string GetTextFromRectangleSelectArea(SelectCollection Selections)\r
1118         {\r
1119             StringBuilder temp = new StringBuilder();\r
1120             if (Selections.First().start < Selections.Last().start)\r
1121             {\r
1122                 for (int i = 0; i < this.View.Selections.Count; i++)\r
1123                 {\r
1124                     Selection sel = Util.NormalizeIMaker<Selection>(Selections[i]);\r
1125 \r
1126                     string str = this.Document.ToString(sel.start, sel.length);\r
1127                     if (str.IndexOf(Environment.NewLine) == -1)\r
1128                         temp.AppendLine(str);\r
1129                     else\r
1130                         temp.Append(str);\r
1131                 }\r
1132             }\r
1133             else\r
1134             {\r
1135                 for (int i = this.View.Selections.Count - 1; i >= 0; i--)\r
1136                 {\r
1137                     Selection sel = Util.NormalizeIMaker<Selection>(Selections[i]);\r
1138 \r
1139                     string str = this.Document.ToString(sel.start, sel.length).Replace(Document.NewLine.ToString(), Environment.NewLine);\r
1140                     if (str.IndexOf(Environment.NewLine) == -1)\r
1141                         temp.AppendLine(str);\r
1142                     else\r
1143                         temp.Append(str);\r
1144                 }\r
1145             }\r
1146             return temp.ToString();\r
1147         }\r
1148 \r
1149         void View_LineBreakChanged(object sender, EventArgs e)\r
1150         {\r
1151             this.DeSelectAll();\r
1152             this.AdjustCaret();\r
1153         }\r
1154 \r
1155         void View_PageBoundChanged(object sender, EventArgs e)\r
1156         {\r
1157             if (this.View.LineBreak == LineBreakMethod.PageBound && this.View.PageBound.Width - this.View.LineBreakingMarginWidth > 0)\r
1158                 this.View.PerfomLayouts();\r
1159             this.AdjustCaret();\r
1160         }\r
1161 \r
1162         void render_ChangedRenderResource(object sender, ChangedRenderRsourceEventArgs e)\r
1163         {\r
1164             if (e.type == ResourceType.Font)\r
1165             {\r
1166                 if (this.View.LineBreak == LineBreakMethod.PageBound)\r
1167                     this.View.PerfomLayouts();\r
1168                 this.AdjustCaret();\r
1169             }\r
1170             if (e.type == ResourceType.InlineChar)\r
1171             {\r
1172                 int oldLineCountOnScreen = this.View.LineCountOnScreen;\r
1173                 this.View.CalculateLineCountOnScreen();\r
1174                 if(this.View.LineCountOnScreen != oldLineCountOnScreen)\r
1175                     this.AdjustCaret();\r
1176             }\r
1177         }\r
1178 \r
1179         void render_ChangedRightToLeft(object sender, EventArgs e)\r
1180         {\r
1181             this.AdjustCaret();\r
1182         }\r
1183 \r
1184         void Document_Update(object sender, DocumentUpdateEventArgs e)\r
1185         {\r
1186             switch (e.type)\r
1187             {\r
1188                 case UpdateType.Replace:\r
1189                     if(e.startIndex < this.Document.Length && this.Document[e.startIndex] == Document.NewLine)\r
1190                         this.View.CalculateLineCountOnScreen();\r
1191                     this.JumpCaret(e.startIndex + e.insertLength,true);\r
1192                     break;\r
1193                 case UpdateType.Clear:\r
1194                     this.JumpCaret(0,0, false);\r
1195                     break;\r
1196             }\r
1197         }\r
1198     }\r
1199 }\r