OSDN Git Service

コントローラーと被っている部分があったので共通化した
[fooeditengine/FooEditEngine.git] / Core / Controller.cs
index dd051eb..86c4e90 100644 (file)
@@ -20,10 +20,12 @@ using System.Drawing;
 
 namespace FooEditEngine
 {
-    internal enum MoveFlow
+    public enum MoveFlow
     {
-        Horizontical,
-        Vertical,
+        Character,
+        Word,
+        Line,
+        Paragraph
     }
     internal enum ScrollDirection
     {
@@ -38,7 +40,13 @@ namespace FooEditEngine
     /// </summary>
     public enum IndentMode
     {
+        /// <summary>
+        /// タブ
+        /// </summary>
         Tab,
+        /// <summary>
+        /// スペース
+        /// </summary>
         Space,
     }
 
@@ -48,34 +56,81 @@ namespace FooEditEngine
     internal sealed class Controller
     {
         EditView View;
-        Document Document;
-        int AnchorIndex;
+        Document _Document;
         
         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();
+            //this.Document.Clear();
         }
 
-        /// <summary>
-        /// 選択領域変更時に通知される
-        /// </summary>
-        public event EventHandler SelectionChanged;
+        public Document Document
+        {
+            get
+            {
+                return this._Document;
+            }
+            set
+            {
+                //メモリリークを防ぐためにパンドラーを除く
+                if (this._Document != null)
+                {
+                    this._Document.Update -= Document_Update;
+                    this._Document.StatusUpdate -= Document_StatusChanged;
+                    this._Document.SelectionChanged -= Document_SelectionChanged;
+                    this._Document.PerformLayouted -= View_LineBreakChanged;
+                    this._Document.CaretChanged -= _Document_CaretChanged;
+                }
+
+                this._Document = value;
+
+                this._Document.Update += new DocumentUpdateEventHandler(Document_Update);
+                this._Document.StatusUpdate += Document_StatusChanged;
+                this._Document.SelectionChanged += Document_SelectionChanged;
+                this._Document.PerformLayouted += View_LineBreakChanged;
+                this._Document.CaretChanged += _Document_CaretChanged;
+            }
+        }
+
+        private void _Document_CaretChanged(object sender, EventArgs e)
+        {
+            TextPoint pos = this.Document.CaretPostion;
+            this.JumpCaret(pos.row, pos.col);
+        }
+
+        private void Document_SelectionChanged(object sender, EventArgs e)
+        {
+            if (this.IsReverseSelect())
+            {
+                if (this.Document.SelectGrippers.BottomRight.Enabled)
+                    this.Document.SelectGrippers.BottomRight.MoveByIndex(this.View, this.SelectionStart);
+                if (this.Document.SelectGrippers.BottomLeft.Enabled)
+                    this.Document.SelectGrippers.BottomLeft.MoveByIndex(this.View, this.SelectionStart + this.SelectionLength);
+            }
+            else
+            {
+                if (this.Document.SelectGrippers.BottomLeft.Enabled)
+                    this.Document.SelectGrippers.BottomLeft.MoveByIndex(this.View, this.SelectionStart);
+                if (this.Document.SelectGrippers.BottomRight.Enabled)
+                    this.Document.SelectGrippers.BottomRight.MoveByIndex(this.View, this.SelectionStart + this.SelectionLength);
+            }
+        }
+
+        void Document_StatusChanged(object sender,EventArgs e)
+        {
+            this.AdjustCaret();
+        }
 
         /// <summary>
         /// 矩形選択モードなら真を返し、そうでない場合は偽を返す
         /// </summary>
         public bool RectSelection
         {
-            get;
-            set;
+            get { return this.Document.RectSelection; }
+            set { this.Document.RectSelection = value; }
         }
 
         /// <summary>
@@ -83,8 +138,8 @@ namespace FooEditEngine
         /// </summary>
         public IndentMode IndentMode
         {
-            get;
-            set;
+            get { return this.Document.IndentMode; }
+            set { this.Document.IndentMode = value; }
         }
 
         /// <summary>
@@ -96,7 +151,7 @@ namespace FooEditEngine
             get
             {
                 if (this.View.Selections.Count == 0)
-                    return this.AnchorIndex;
+                    return this.Document.AnchorIndex;
                 else
                     return this.View.Selections.First().start;
             }
@@ -150,121 +205,8 @@ namespace FooEditEngine
         /// <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));
-            }
-            else if(length != 0)
-            {
-                this.View.Selections.Add(Selection.Create(start, length));
-            }
-            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));
-            
-            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>
-        /// <param name="changeAnchor">選択の起点となるとインデックスを変更するなら真。そうでなければ偽</param>
-        public void SelectWord(int index, bool changeAnchor = false)
-        {
-            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);
-
-            if(changeAnchor)
-                this.AnchorIndex = start;
+            int index = this.View.LayoutLines.GetIndexFromTextPoint(this.Document.CaretPostion);
+            return index < this.Document.AnchorIndex;
         }
 
         /// <summary>
@@ -288,9 +230,7 @@ namespace FooEditEngine
                 else
                     return false;
             }
-            this.Document.Lock();
             this.Document.Replace(this.SelectionStart, this.SelectionLength, result.ToString());
-            this.Document.UnLock();
             return true;
         }
 
@@ -314,9 +254,7 @@ namespace FooEditEngine
                 else
                     i++;
             }
-            this.Document.Lock();
             this.Document.Replace(this.SelectionStart, this.SelectionLength, result.ToString());
-            this.Document.UnLock();
         }
 
         /// <summary>
@@ -354,7 +292,7 @@ namespace FooEditEngine
         {
             foreach(int id in this.Document.Markers.IDs)
             {
-                foreach (Marker m in this.Document.GetMarkers(index, id))
+                foreach (Marker m in this.Document.GetMarkers(id, index))
                 {
                     if (m.hilight == type)
                         return true;
@@ -368,13 +306,20 @@ namespace FooEditEngine
         /// </summary>
         public void AdjustCaret()
         {
-            int row = this.View.CaretPostion.row;
+            int row = this.Document.CaretPostion.row;
             if (row > this.View.LayoutLines.Count - 1)
                 row = this.View.LayoutLines.Count - 1;
-            int col = this.View.CaretPostion.col;
+            int col = this.Document.CaretPostion.col;
             if (col > 0 && col > this.View.LayoutLines[row].Length)
                 col = this.View.LayoutLines[row].Length;
+
+            //選択領域が消えてしまうので覚えておく
+            int sel_start = this.SelectionStart;
+            int sel_length = this.SelectionLength;
+
             this.JumpCaret(row, col);
+
+            this.Document.Select(sel_start, sel_length);
         }
 
         /// <summary>
@@ -462,6 +407,50 @@ namespace FooEditEngine
             this.SelectWithMoveCaret(isSelected);
         }
 
+        double noti;
+        /// <summary>
+        /// スクロールする
+        /// </summary>
+        /// <param name="dir">方向を指定する</param>
+        /// <param name="delta">ピクセル単位の値でスクロール量を指定する</param>
+        /// <param name="isSelected">選択状態にするなら真</param>
+        /// <param name="withCaret">同時にキャレットを移動させるなら真</param>
+        public void ScrollByPixel(ScrollDirection dir,int delta, bool isSelected, bool withCaret)
+        {
+            if (this.Document.FireUpdateEvent == false)
+                throw new InvalidOperationException("");
+
+            if (dir == ScrollDirection.Left || dir == ScrollDirection.Right)
+            {
+                this.View.TryScroll(delta, 0);
+                return;
+            }
+
+            if(dir == ScrollDirection.Up || dir == ScrollDirection.Down)
+            {
+                noti += delta;
+
+                if (noti < this.View.render.emSize.Height)
+                    return;
+
+                int delta_row = (int)(noti / this.View.render.emSize.Height + 1.0);
+
+                noti = 0;
+
+                this.View.TryScroll(0, delta);
+            }
+
+            if (withCaret)
+            {
+                //カーソルを適切な位置に移動させる必要がある
+                this.View.AdjustCaretAndSrc();
+                this.SelectWithMoveCaret(isSelected);
+            }
+
+            this.Document.SelectGrippers.BottomLeft.MoveByIndex(this.View, this.SelectionStart);
+            this.Document.SelectGrippers.BottomRight.MoveByIndex(this.View, this.SelectionStart + this.SelectionLength);
+        }
+
         /// <summary>
         /// スクロールする
         /// </summary>
@@ -516,8 +505,10 @@ namespace FooEditEngine
             else
             {
                 this.View.Scroll(toX, toRow);
-                this.View.IsFocused = false;
             }
+
+            this.Document.SelectGrippers.BottomLeft.MoveByIndex(this.View, this.SelectionStart);
+            this.Document.SelectGrippers.BottomRight.MoveByIndex(this.View, this.SelectionStart + this.SelectionLength);
         }
 
         /// <summary>
@@ -529,38 +520,71 @@ namespace FooEditEngine
         /// <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);
+            TextPoint caret = this.Document.CaretPostion;
+            int moved;
+            caret = GetNextCaret(caret, realLength, alignWord ? MoveFlow.Word : MoveFlow.Character,out moved);
+            this.View.JumpCaret(caret.row, caret.col, false);
+            this.View.AdjustCaretAndSrc(AdjustFlow.Both);
+            this.SelectWithMoveCaret(isSelected);
+        }
 
-                if (alignWord)
-                    this.AlignNearestWord(MoveFlow);
+        /// <summary>
+        /// 移動後のキャレット位置を求める
+        /// </summary>
+        /// <param name="caret">起点となるキャレット位置</param>
+        /// <param name="count">移動量</param>
+        /// <param name="method">移動方法</param>
+        /// <param name="moved">実際に移動した量</param>
+        /// <returns>移動後のキャレット位置</returns>
+        public TextPoint GetNextCaret(TextPoint caret, int count,MoveFlow method,out int moved)
+        {
+            moved = 0;
+            if(method == MoveFlow.Character || method == MoveFlow.Word)
+            {
+                for (int i = Math.Abs(count); i > 0; i--)
+                {
+                    bool moveFlow = count > 0;
+                    if (this.Document.RightToLeft)
+                        moveFlow = !moveFlow;
+                    caret = this.MoveCaretHorizontical(caret, moveFlow);
+
+                    if (method == FooEditEngine.MoveFlow.Word)
+                        caret = this.AlignNearestWord(caret, moveFlow);
+                    moved++;
+                }
             }
-            this.View.AdjustCaretAndSrc(AdjustFlow.Col);
-            this.SelectWithMoveCaret(isSelected);
+            if(method == MoveFlow.Line || method == MoveFlow.Paragraph)
+            {
+                for (int i = Math.Abs(count); i > 0; i--)
+                {
+                    caret = this.MoveCaretVertical(caret, count > 0);
+                    moved++;
+                }
+            }
+            if (count < 0)
+                moved = -moved;
+            return caret;
         }
 
-        void AlignNearestWord(bool MoveFlow)
+        TextPoint AlignNearestWord(TextPoint caret,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)
+            string str = this.View.LayoutLines[caret.row];
+            while (caret.col > 0 &&
+                caret.col < str.Length &&
+                str[caret.col] != Document.NewLine)
             {
-                if (!Util.IsWordSeparator(str[this.View.CaretPostion.col]))
+                if (!Util.IsWordSeparator(str[caret.col]))
                 {
-                    this.MoveCaretHorizontical(MoveFlow);
+                    caret = this.MoveCaretHorizontical(caret, MoveFlow);
                 }
                 else
                 {
                     if(MoveFlow)
-                        this.MoveCaretHorizontical(MoveFlow);
+                        caret = this.MoveCaretHorizontical(caret, MoveFlow);
                     break;
                 }
             }
+            return caret;
         }
 
         /// <summary>
@@ -571,8 +595,10 @@ namespace FooEditEngine
         /// <param name="isSelected"></param>
         public void MoveCaretVertical(int deltarow,bool isSelected)
         {
-            for (int i = Math.Abs(deltarow); i > 0; i--)
-                this.MoveCaretVertical(deltarow > 0);
+            TextPoint caret = this.Document.CaretPostion;
+            int moved;
+            caret = this.GetNextCaret(caret, deltarow, MoveFlow.Line,out moved);
+            this.View.JumpCaret(caret.row, caret.col, true);
             this.View.AdjustCaretAndSrc(AdjustFlow.Both);
             this.SelectWithMoveCaret(isSelected);
         }
@@ -591,7 +617,7 @@ namespace FooEditEngine
             if (this.Document.FireUpdateEvent == false)
                 throw new InvalidOperationException("");
 
-            TextPoint CaretPostion = this.View.CaretPostion;
+            TextPoint CaretPostion = this.Document.CaretPostion;
             int index = this.View.GetIndexFromLayoutLine(CaretPostion);
 
             if (index == this.Document.Length)
@@ -603,9 +629,7 @@ namespace FooEditEngine
             if (this.Document[index] == Document.NewLine)
                 next = index + 1;
 
-            this.Document.Lock();
-            this.Document.Replace(index, next - index, "");
-            this.Document.UnLock();
+            this.Document.Replace(index, next - index, "", true);
         }
 
         public bool IsRectInsertMode()
@@ -639,7 +663,7 @@ namespace FooEditEngine
             if (this.Document.FireUpdateEvent == false)
                 throw new InvalidOperationException("");
 
-            TextPoint CurrentPostion = this.View.CaretPostion;
+            TextPoint CurrentPostion = this.Document.CaretPostion;
 
             if (CurrentPostion.row == 0 && CurrentPostion.col == 0)
                 return;
@@ -658,9 +682,7 @@ namespace FooEditEngine
                 newIndex--;
             }
 
-            this.Document.Lock();
-            this.Document.Replace(newIndex, oldIndex - newIndex, "");
-            this.Document.UnLock();
+            this.Document.Replace(newIndex, oldIndex - newIndex, "", true);
         }
 
         /// <summary>
@@ -682,18 +704,18 @@ namespace FooEditEngine
 
         string GetIndentSpace(int col_index)
         {
-            int space_count = this.View.TabStops - (col_index % this.View.TabStops);
+            int space_count = this.Document.TabStops - (col_index % this.Document.TabStops);
             return new string(Enumerable.Repeat(' ',space_count).ToArray());
         }
 
         /// <summary>
         /// キャレット位置に文字列を挿入し、その分だけキャレットを進める。isInsertModeの値により動作が変わります
         /// </summary>
-        /// <param name="str"></param>
-        /// <param name="fromTip"></param>
+        /// <param name="str">挿入したい文字列</param>
+        /// <param name="fromTip">真の場合、矩形選択の幅にかかわらず矩形編集モードとして動作します。そうでない場合は選択領域を文字列で置き換えます</param>
         public void DoInputString(string str,bool fromTip = false)
         {
-            TextPoint CaretPos = this.View.CaretPostion;
+            TextPoint CaretPos = this.Document.CaretPostion;
 
             if (str == "\t" && this.IndentMode == IndentMode.Space)
                 str = this.GetIndentSpace(CaretPos.col);
@@ -712,7 +734,7 @@ namespace FooEditEngine
             if (this.Document.FireUpdateEvent == false)
                 throw new InvalidOperationException("");
 
-            int index = this.View.GetIndexFromLayoutLine(this.View.CaretPostion);
+            int index = this.View.GetIndexFromLayoutLine(this.Document.CaretPostion);
             int length = 0;
             if (this.View.InsertMode == false && index < this.Document.Length && this.Document[index] != Document.NewLine)
             {
@@ -731,9 +753,7 @@ namespace FooEditEngine
                 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();
+            this.Document.Replace(index, length, str, true);
         }
 
         /// <summary>
@@ -745,21 +765,21 @@ namespace FooEditEngine
         /// </remarks>
         void SelectWithMoveCaret(bool isSelected)
         {
-            if (this.View.CaretPostion.col < 0 || this.View.CaretPostion.row < 0)
+            if (this.Document.CaretPostion.col < 0 || this.Document.CaretPostion.row < 0)
                 return;
 
             if (this.Document.FireUpdateEvent == false)
                 throw new InvalidOperationException("");
 
-            int CaretPostion = this.View.GetIndexFromLayoutLine(this.View.CaretPostion);
+            int CaretPostion = this.View.GetIndexFromLayoutLine(this.Document.CaretPostion);
             
             SelectCollection Selections = this.View.Selections;
             if (isSelected)
             {
-                this.Select(this.AnchorIndex, CaretPostion - this.AnchorIndex);
+                this.Document.Select(this.Document.AnchorIndex, CaretPostion - this.Document.AnchorIndex);
             }else{
-                this.AnchorIndex = CaretPostion;
-                this.Select(CaretPostion, 0);
+                this.Document.AnchorIndex = CaretPostion;
+                this.Document.Select(CaretPostion, 0);
             }
         }
 
@@ -767,11 +787,23 @@ namespace FooEditEngine
         /// JumpCaretで移動した位置からキャレットを移動し、選択状態にする
         /// </summary>
         /// <param name="tp"></param>
-        public void MoveCaretAndSelect(TextPoint tp)
+        /// <param name="alignWord">単語単位で選択するかどうか</param>
+        public void MoveCaretAndSelect(TextPoint tp,bool alignWord = false)
         {
+            TextPoint endSelectPostion = tp;
             int CaretPostion = this.View.GetIndexFromLayoutLine(tp);
-            this.Select(this.AnchorIndex, CaretPostion - this.AnchorIndex);
-            this.View.JumpCaret(tp.row, tp.col);
+            if (alignWord)
+            {
+                if (this.IsReverseSelect())
+                    while (CaretPostion >= 0 && CaretPostion < this.Document.Length && !Util.IsWordSeparator(this.Document[CaretPostion])) CaretPostion--;
+                else
+                    while (CaretPostion < this.Document.Length && !Util.IsWordSeparator(this.Document[CaretPostion])) CaretPostion++;
+                if (CaretPostion < 0)
+                    CaretPostion = 0;
+                endSelectPostion = this.View.LayoutLines.GetTextPointFromIndex(CaretPostion);
+            }
+            this.Document.Select(this.Document.AnchorIndex, CaretPostion - this.Document.AnchorIndex);
+            this.View.JumpCaret(endSelectPostion.row, endSelectPostion.col);
             this.View.AdjustCaretAndSrc();
         }
 
@@ -782,43 +814,48 @@ namespace FooEditEngine
         /// <param name="hittedGripper">動かす対象となるグリッパー</param>
         /// <returns>移動できた場合は真を返す。そうでなければ偽を返す</returns>
         /// <remarks>グリッパー内にポインターが存在しない場合、グリッパーはポインターの座標近くの行に移動する</remarks>
-        public bool MoveCaretAndGripper(Point p, GripperView hittedGripper)
+        public bool MoveCaretAndGripper(Point p, Gripper hittedGripper)
         {
             bool HittedCaret = false;
             TextPoint tp = this.View.GetTextPointFromPostion(p);
-            if (tp == this.View.CaretPostion)
+            if (tp == this.Document.CaretPostion)
             {
                 HittedCaret = true;
             }
 
             if (HittedCaret || hittedGripper != null)
             {
+                TextPointSearchRange searchRange;
+                if (this.View.HitTextArea(p.X, p.Y))
+                    searchRange = TextPointSearchRange.TextAreaOnly;
+                else if (this.SelectionLength > 0)
+                    searchRange = TextPointSearchRange.Full;
+                else
+                    return false;
+
                 if (hittedGripper != null)
                 {
-                    tp = this.View.GetTextPointFromPostion(hittedGripper.AdjustPoint(p));
-                    if (this.IsReverseSelect())
-                    {
-                        if (Object.ReferenceEquals(hittedGripper, this.View.SelectGrippers.BottomRight))
-                            this.MoveSelectBefore(tp);
-                        else
-                            this.MoveCaretAndSelect(tp);
-                    }
-                    else
-                    {
-                        if (Object.ReferenceEquals(hittedGripper, this.View.SelectGrippers.BottomLeft))
-                            this.MoveSelectBefore(tp);
-                        else
-                            this.MoveCaretAndSelect(tp);
-                    }
-                    hittedGripper.Move(this.View, tp);
+                    tp = this.View.GetTextPointFromPostion(hittedGripper.AdjustPoint(p), searchRange);
+                    if (tp == TextPoint.Null)
+                        return false;
+                    if (Object.ReferenceEquals(hittedGripper, this.Document.SelectGrippers.BottomRight))
+                        this.MoveCaretAndSelect(tp);
+                    else if(Object.ReferenceEquals(hittedGripper, this.Document.SelectGrippers.BottomLeft))
+                        this.MoveSelectBefore(tp);
                 }
                 else
                 {
-                    tp = this.View.GetTextPointFromPostion(p);
+                    tp = this.View.GetTextPointFromPostion(p, searchRange);
                     if (tp != TextPoint.Null)
+                    {
                         this.MoveCaretAndSelect(tp);
+                    }
+                    else
+                    {
+                        return false;
+                    }
                 }
-                this.View.SelectGrippers.BottomLeft.Enabled = this.SelectionLength != 0;
+                this.Document.SelectGrippers.BottomLeft.Enabled = this.SelectionLength != 0;
                 return true;
             }
             return false;
@@ -831,24 +868,16 @@ namespace FooEditEngine
             if (this.IsReverseSelect())
             {
                 NewAnchorIndex = this.View.GetIndexFromLayoutLine(tp);
-                SelectionLength = this.SelectionLength + NewAnchorIndex - this.AnchorIndex;
-                this.Select(this.SelectionStart, SelectionLength);
+                SelectionLength = this.SelectionLength + NewAnchorIndex - this.Document.AnchorIndex;
+                this.Document.Select(this.SelectionStart, SelectionLength);
             }
             else
             {
                 NewAnchorIndex = this.View.GetIndexFromLayoutLine(tp);
-                SelectionLength = this.SelectionLength + this.AnchorIndex - NewAnchorIndex;
-                this.Select(NewAnchorIndex, SelectionLength);
+                SelectionLength = this.SelectionLength + this.Document.AnchorIndex - NewAnchorIndex;
+                this.Document.Select(NewAnchorIndex, SelectionLength);
             }
-            this.AnchorIndex = NewAnchorIndex;
-        }
-
-        /// <summary>
-        /// キャレット位置を既定の位置に戻す
-        /// </summary>
-        public void ResetCaretPostion()
-        {
-            this.JumpCaret(0);
+            this.Document.AnchorIndex = NewAnchorIndex;
         }
 
         /// <summary>
@@ -859,19 +888,40 @@ namespace FooEditEngine
         /// <returns>移動後のキャレット位置</returns>
         public TextPoint GetTextPointAfterMoveLine(int count, TextPoint current)
         {
-            int row = current.row + count;
+            if(this.Document.LineBreak == LineBreakMethod.None)
+            {
+                int row = current.row + count;
 
-            if (row < 0)
-                row = 0;
-            else if (row >= this.View.LayoutLines.Count)
-                row = this.View.LayoutLines.Count - 1;
+                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);
 
-            row = this.View.AdjustRow(row, count > 0);
+                Point pos = this.View.LayoutLines.GetLayout(current.row).GetPostionFromIndex(current.col);
+                int col = this.View.LayoutLines.GetLayout(row).GetIndexFromPostion(pos.X, pos.Y);
+                return new TextPoint(row, col);
+            }
+            else
+            {
+                Point pos = this.View.GetPostionFromTextPoint(current);
+                pos.Y += this.View.render.emSize.Height * count;
+                //この値を足さないとうまく動作しない
+                pos.Y += this.View.render.emSize.Height / 2;   
+                var new_tp = this.View.GetTextPointFromPostion(pos,TextPointSearchRange.Full);
+                return new_tp;
+
+            }
+        }
 
-            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 ResetCaretPostion()
+        {
+            this.JumpCaret(0);
         }
 
         /// <summary>
@@ -885,7 +935,7 @@ namespace FooEditEngine
             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);
+            this.Document.Select(selectionStart, text.Length);
         }
 
         /// <summary>
@@ -897,9 +947,9 @@ namespace FooEditEngine
                 return;
             int selectionStart = this.SelectionStart;
             string insertStr = this.IndentMode == IndentMode.Space ? this.GetIndentSpace(0) : "\t";
-            string text = this.RemoveLineHead(GetTextFromLineSelectArea(this.View.Selections), insertStr);
+            string text = this.RemoveLineHead(GetTextFromLineSelectArea(this.View.Selections), insertStr, insertStr.Length);
             this.RepleaceSelectionArea(this.View.Selections, text);
-            this.Select(selectionStart, text.Length);
+            this.Document.Select(selectionStart, text.Length);
         }
 
         string InsertLineHead(string s, string str)
@@ -916,14 +966,14 @@ namespace FooEditEngine
             return output.ToString();
         }
 
-        public string RemoveLineHead(string s, string str)
+        public string RemoveLineHead(string s, string str,int remove_count)
         {
             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);
+                    output.Append(lines[i].Substring(remove_count) + Document.NewLine);
                 else if (i < lines.Length - 1)
                     output.Append(lines[i] + Document.NewLine);
             }
@@ -933,43 +983,41 @@ namespace FooEditEngine
         /// <summary>
         /// キャレットを一文字移動させる
         /// </summary>
+        /// <param name="caret">キャレット</param>
         /// <param name="isMoveNext">真なら1文字すすめ、そうでなければ戻す</param>
         /// <remarks>このメソッドを呼び出した後でScrollToCaretメソッドとSelectWithMoveCaretメソッドを呼び出す必要があります</remarks>
-        void MoveCaretHorizontical(bool isMoveNext)
+        TextPoint MoveCaretHorizontical(TextPoint caret,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)
+            int prevcol = caret.col;
+            int col = caret.col + delta;
+            string lineString = this.View.LayoutLines[caret.row];
+            if (col < 0 || caret.row >= this.View.LayoutLines.Count)
             {
-                if (this.View.CaretPostion.row == 0)
+                if (caret.row == 0)
                 {
-                    col = 0;
-                    return;
+                    caret.col = 0;
+                    return caret;
                 }
-                this.MoveCaretVertical(false);
-                this.View.AdjustCaretAndSrc(AdjustFlow.Row);  //この段階で調整しないとスクロールされない
-                col = this.View.LayoutLines.GetLengthFromLineNumber(this.View.CaretPostion.row) - 1;  //最終行以外はすべて改行コードが付くはず
+                caret = this.MoveCaretVertical(caret,false);
+                caret.col = this.View.LayoutLines.GetLengthFromLineNumber(caret.row) - 1;  //最終行以外はすべて改行コードが付くはず
             }
             else if (col >= lineString.Length || lineString[col] == Document.NewLine)
             {
-                if (this.View.CaretPostion.row < this.View.LayoutLines.Count - 1)
+                if (caret.row < this.View.LayoutLines.Count - 1)
                 {
-                    this.MoveCaretVertical(true);
-                    this.View.AdjustCaretAndSrc(AdjustFlow.Row);  //この段階で調整しないとスクロールされない
-                    col = 0;
+                    caret = this.MoveCaretVertical(caret, true);
+                    caret.col = 0;
                 }
             }
             else
             {
                 AlignDirection direction = isMoveNext ? AlignDirection.Forward : AlignDirection.Back;
-                col = this.View.LayoutLines.GetLayout(this.View.CaretPostion.row).AlignIndexToNearestCluster(col, direction);
+                caret.col = this.View.LayoutLines.GetLayout(caret.row).AlignIndexToNearestCluster(col, direction);
             }
-
-            this.View.JumpCaret(this.View.CaretPostion.row, col,false);
+            return caret;
         }
 
         /// <summary>
@@ -977,14 +1025,12 @@ namespace FooEditEngine
         /// </summary>
         /// <param name="isMoveNext">プラス方向に移動するなら真</param>
         /// <remarks>このメソッドを呼び出した後でScrollToCaretメソッドとSelectWithMoveCaretメソッドを呼び出す必要があります</remarks>
-        void MoveCaretVertical(bool isMoveNext)
+        TextPoint MoveCaretVertical(TextPoint caret,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);
+            return this.GetTextPointAfterMoveLine(isMoveNext ? 1 : -1, this.Document.CaretPostion);
         }
 
         private void ReplaceBeforeSelectionArea(SelectCollection Selections, int removeLength, string insertStr)
@@ -1039,15 +1085,13 @@ namespace FooEditEngine
             else
                 this.JumpCaret(end.row, end.col);
             
-            this.Select(start, 0, end.row - start.row);
+            this.Document.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)
@@ -1057,13 +1101,11 @@ namespace FooEditEngine
 
             if (this.RectSelection == false)
             {
-                Selection sel = Selection.Create(this.AnchorIndex, 0);
+                Selection sel = Selection.Create(this.Document.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;
             }
 
@@ -1078,8 +1120,6 @@ namespace FooEditEngine
             {
                 int i;
 
-                this.Document.Lock();
-
                 this.Document.UndoManager.BeginUndoGroup();
 
                 this.Document.FireUpdateEvent = false;
@@ -1108,15 +1148,11 @@ namespace FooEditEngine
                 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;
@@ -1151,8 +1187,6 @@ namespace FooEditEngine
                 this.Document.FireUpdateEvent = true;
 
                 this.Document.UndoManager.EndUndoGroup();
-
-                this.Document.UnLock();
             }
             this.JumpCaret(StartIndex);
             if (updateInsertPoint && newInsertPoint.Count > 0)
@@ -1208,8 +1242,8 @@ namespace FooEditEngine
 
         void View_PageBoundChanged(object sender, EventArgs e)
         {
-            if (this.View.LineBreak == LineBreakMethod.PageBound && this.View.PageBound.Width - this.View.LineBreakingMarginWidth > 0)
-                this.View.PerfomLayouts();
+            if (this.Document.LineBreak == LineBreakMethod.PageBound && this.View.PageBound.Width - this.View.LineBreakingMarginWidth > 0)
+                this.Document.PerformLayout();
             this.AdjustCaret();
         }
 
@@ -1217,8 +1251,8 @@ namespace FooEditEngine
         {
             if (e.type == ResourceType.Font)
             {
-                if (this.View.LineBreak == LineBreakMethod.PageBound)
-                    this.View.PerfomLayouts();
+                if (this.Document.LineBreak == LineBreakMethod.PageBound)
+                    this.Document.PerformLayout();
                 this.AdjustCaret();
             }
             if (e.type == ResourceType.InlineChar)
@@ -1230,18 +1264,11 @@ namespace FooEditEngine
             }
         }
 
-        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: