]> O.S.I.I.S - jp/crowedit.git/commitdiff
simplifications, parsing and syntax has to be reworked
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Tue, 7 Nov 2017 19:10:02 +0000 (20:10 +0100)
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Tue, 7 Nov 2017 19:10:02 +0000 (20:10 +0100)
CrowEdit.csproj
src/CSharpParser.cs
src/CodeBuffer.cs
src/CodeLine.cs [new file with mode: 0644]
src/Node.cs
src/Parser.cs
src/SourceEditor.cs
src/TokenList.cs [deleted file]
src/XMLParser.cs

index 3c197e192d3eb1305f754f11c958006e37078932..08986e6f1aacd4ede70cea75d57ea28a19e098d5 100644 (file)
@@ -72,7 +72,6 @@
     <Compile Include="src\Parser.cs" />
     <Compile Include="src\XMLParser.cs" />
     <Compile Include="src\CSharpParser.cs" />
-    <Compile Include="src\TokenList.cs" />
     <Compile Include="src\CodeBuffer.cs" />
     <Compile Include="src\TextFormatting.cs" />
     <Compile Include="ParsingException.cs" />
@@ -84,6 +83,7 @@
     <Compile Include="OpenGL\Shader.cs" />
     <Compile Include="OpenGL\Texture.cs" />
     <Compile Include="OpenGL\vaoMesh.cs" />
+    <Compile Include="src\CodeLine.cs" />
   </ItemGroup>
   <ItemGroup>
     <Folder Include="ui\" />
index 14e3de8ce6a43e72089245b5aafbe8fcb3e1f76a..7d2e28e515f13c0d03773133decdc187d5bbd145 100644 (file)
@@ -32,7 +32,7 @@ namespace Crow.Coding
                {
                }
 
-               public override void Parse (int line)
+               public override void ParseCurrentLine ()
                {
                        throw new NotImplementedException ();
                }
index 424aa4aad437adde1d8358b9e632431341d28a35..399d10abb48f7f6fc7ea678cc5a409cfba2aa8a9 100644 (file)
@@ -31,23 +31,27 @@ namespace Crow.Coding
        /// </summary>
        public class CodeBuffer
        {
+               public object EditMutex = new object();
                //those events are handled in SourceEditor to help keeping sync between textbuffer,parser and editor.
                //modified lines are marked for reparse
                #region Events
                public event EventHandler<CodeBufferEventArgs> LineUpadateEvent;
                public event EventHandler<CodeBufferEventArgs> LineRemoveEvent;
                public event EventHandler<CodeBufferEventArgs> LineAdditionEvent;
+               public event EventHandler<CodeBufferEventArgs> FoldingEvent;
                public event EventHandler BufferCleared;
+               public event EventHandler SelectionChanged;
+               public event EventHandler PositionChanged;
                #endregion
 
                #region CTOR
                public CodeBuffer () {
-                       this.Add ("");
+
                }
                #endregion
 
                string lineBreak = Interface.LineBreak;
-               List<string> lines = new List<string>();
+               List<CodeLine> lines = new List<CodeLine>();
                public int longestLineIdx = 0;
                public int longestLineCharCount = 0;
                /// <summary>
@@ -57,47 +61,83 @@ namespace Crow.Coding
                int _currentCol = 0;
 
                public int LineCount { get { return lines.Count;}}
-
-               /// <summary>
-               /// Return line with tabs replaced by spaces
-               /// </summary>
-               public string GetPrintableLine(int i){
-                       return string.IsNullOrEmpty(lines[i]) ? "" : lines[i].Replace("\t", new String(' ', Interface.TabSize));
+               public int IndexOf (CodeLine cl) {
+                       return lines.IndexOf (cl);
                }
 
-               public string this[int i]
+               public CodeLine this[int i]
                {
                        get { return lines[i]; }
                        set {
                                if (lines [i] == value)
                                        return;
-                               lines[i] = value;
-                               LineUpadateEvent.Raise (this, new CodeBufferEventArgs (i));
+                               lock (EditMutex) {
+                                       lines [i] = value;
+                                       LineUpadateEvent.Raise (this, new CodeBufferEventArgs (i));
+                               }
                        }
                }
 
                public void RemoveAt(int i){
-                       lines.RemoveAt(i);
-                       LineRemoveEvent.Raise (this, new CodeBufferEventArgs (i));
+                       lock (EditMutex) {
+                               lines.RemoveAt (i);
+                               LineRemoveEvent.Raise (this, new CodeBufferEventArgs (i));
+                       }
                }
                public void Insert(int i, string item){
-                       lines.Insert (i, item);
-                       LineAdditionEvent.Raise (this, new CodeBufferEventArgs (i));
+                       lock (EditMutex) {
+                               lines.Insert (i, item);
+                               LineAdditionEvent.Raise (this, new CodeBufferEventArgs (i));
+                       }
                }
-               public void Add(string item){
-                       lines.Add (item);
-                       LineAdditionEvent.Raise (this, new CodeBufferEventArgs (lines.Count - 1));
+               public void Add(CodeLine item){
+                       lock (EditMutex) {
+                               lines.Add (item);
+                               LineAdditionEvent.Raise (this, new CodeBufferEventArgs (lines.Count - 1));
+                       }
                }
                public void AddRange (string[] items){
                        int start = lines.Count;
-                       lines.AddRange (items);
-                       LineAdditionEvent.Raise (this, new CodeBufferEventArgs (start, items.Length));
+                       lock (EditMutex) {
+                               for (int i = 0; i < items.Length; i++)
+                                       lines.Add (items [i]);
+                               LineAdditionEvent.Raise (this, new CodeBufferEventArgs (start, items.Length));
+                       }
+               }
+               public void AddRange (CodeLine[] items){
+                       int start = lines.Count;
+                       lock (EditMutex) {
+                               lines.AddRange (items);
+                               LineAdditionEvent.Raise (this, new CodeBufferEventArgs (start, items.Length));
+                       }
                }
                public void Clear () {
-                       lines.Clear();
-                       BufferCleared.Raise (this, null);
+                       lock (EditMutex) {
+                               longestLineCharCount = 0;
+                               lines.Clear ();
+                               BufferCleared.Raise (this, null);
+                       }
+               }
+               public void UpdateLine(int i, string newContent){
+                       lock (EditMutex) {
+                               this [i].Content = newContent;
+                               LineUpadateEvent.Raise (this, new CodeBufferEventArgs (i));
+                       }
+               }
+               public void AppenedLine(int i, string newContent){
+                       lock (EditMutex) {
+                               this [i].Content += newContent;
+                               LineUpadateEvent.Raise (this, new CodeBufferEventArgs (i));
+                       }
+               }
+               public void ToogleFolding (int line) {
+                       if (!this [line].IsFoldable)
+                               return;
+                       lock (EditMutex) {
+                               this [line].IsFolded = !this [line].IsFolded;
+                               FoldingEvent.Raise (this, new CodeBufferEventArgs (line));
+                       }
                }
-
                public void Load(string rawSource) {
                        this.Clear();
 
@@ -107,7 +147,6 @@ namespace Crow.Coding
                        AddRange (Regex.Split (rawSource, "\r\n|\r|\n|\\\\n"));
 
                        lineBreak = detectLineBreakKind (rawSource);
-                       FindLongestVisualLine ();
                }
 
                /// <summary>
@@ -116,8 +155,8 @@ namespace Crow.Coding
                public void FindLongestVisualLine(){
                        longestLineCharCount = 0;
                        for (int i = 0; i < this.LineCount; i++) {
-                               if (this.GetPrintableLine(i).Length > longestLineCharCount) {
-                                       longestLineCharCount = this.GetPrintableLine(i).Length;
+                               if (lines[i].PrintableLength > longestLineCharCount) {
+                                       longestLineCharCount = lines[i].PrintableLength;
                                        longestLineIdx = i;
                                }
                        }
@@ -152,7 +191,30 @@ namespace Crow.Coding
                /// </summary>
                public string FullText{
                        get {
-                               return lines.Count > 0 ? lines.Aggregate((i, j) => i + this.lineBreak + j) : "";
+                               if (lines.Count == 0)
+                                       return "";
+                               string tmp = "";
+                               for (int i = 0; i < lines.Count -1; i++)
+                                       tmp += lines [i].Content + this.lineBreak;
+                               tmp += lines [lines.Count - 1].Content;
+                               return tmp;
+                       }
+               }
+
+               /// <summary>
+               /// unfolded and not in folds line count
+               /// </summary>
+               public int UnfoldedLines {
+                       get {
+                               int i = 0, vl = 0;
+                               while (i < LineCount) {
+                                       if (this [i].IsFolded)
+                                               i = GetEndNodeIndex (i);
+                                       i++;
+                                       vl++;
+                               }
+                               //Debug.WriteLine ("unfolded lines: " + vl);
+                               return vl;
                        }
                }
 
@@ -171,56 +233,76 @@ namespace Crow.Coding
                        }
                        return new Point (buffCol, visualPos.Y);
                }
+
+               public int GetEndNodeIndex (int line) {
+                       return IndexOf (this [line].SyntacticNode.EndLine);
+               }
                /// <summary>
                /// Gets visual position computed from actual buffer position
                /// </summary>
-               public Point TabulatedPosition {
-                       get { return new Point (TabulatedColumn, _currentLine); }
+//             public Point TabulatedPosition {
+//                     get { return new Point (TabulatedColumn, _currentLine); }
+//             }
+               /// <summary>
+               /// set buffer current position from visual position
+               /// </summary>
+//             public void SetBufferPos(Point tabulatedPosition) {
+//                     CurrentPosition = getBuffPos(tabulatedPosition);
+//             }
+
+               #region Editing and moving cursor
+               Point selStartPos = -1; //selection start (row,column)
+               Point selEndPos = -1;   //selection end (row,column)
+
+               public bool SelectionInProgress { get { return selStartPos >= 0; }}
+               public void SetSelStartPos () {
+                       selStartPos = selEndPos = CurrentPosition;
+                       SelectionChanged.Raise (this, null);
                }
-               public int TabulatedColumn {
-                       get { return this [_currentLine].Substring (0, _currentCol).Replace ("\t", new String (' ', Interface.TabSize)).Length; }
+               public void SetSelEndPos () {
+                       selEndPos = CurrentPosition;
+                       SelectionChanged.Raise (this, null);
                }
                /// <summary>
-               /// set buffer current position from visual position
+               /// Set selection in buffer to -1, empty selection
                /// </summary>
-               public void SetBufferPos(Point tabulatedPosition) {
-                       CurrentPosition = getBuffPos(tabulatedPosition);
+               public void ResetSelection () {
+                       selStartPos = selEndPos = -1;
+                       SelectionChanged.Raise (this, null);
                }
 
-               #region Editing and moving cursor
                public string SelectedText {
                        get {
-                               if (selectionIsEmpty)
+                               if (SelectionIsEmpty)
                                        return "";
-                               if (selectionStart.Y == selectionEnd.Y)
-                                       return this [selectionStart.Y].Substring (selectionStart.X, selectionEnd.X - selectionStart.X);
+                               Point selStart = SelectionStart;
+                               Point selEnd = SelectionEnd;
+                               if (selStart.Y == selEnd.Y)
+                                       return this [selStart.Y].Content.Substring (selStart.X, selEnd.X - selStart.X);
                                string tmp = "";
-                               tmp = this [selectionStart.Y].Substring (selectionStart.X);
-                               for (int l = selectionStart.Y + 1; l < selectionEnd.Y; l++) {
-                                       tmp += Interface.LineBreak + this [l];
+                               tmp = this [selStart.Y].Content.Substring (selStart.X);
+                               for (int l = selStart.Y + 1; l < selEnd.Y; l++) {
+                                       tmp += Interface.LineBreak + this [l].Content;
                                }
-                               tmp += Interface.LineBreak + this [selectionEnd.Y].Substring (0, selectionEnd.X);
+                               tmp += Interface.LineBreak + this [selEnd.Y].Content.Substring (0, selEnd.X);
                                return tmp;
                        }
                }
-               Point selectionStart = -1;
-               Point selectionEnd = -1;
                /// <summary>
-               /// Set selection in buffer coords from tabulated coords
+               /// ordered selection start and end positions in char units
                /// </summary>
-               public void SetSelection (Point tabulatedStart, Point tabulatedEnd) {
-                       selectionStart = getBuffPos (tabulatedStart);
-                       selectionEnd = getBuffPos (tabulatedEnd);
+               public Point SelectionStart     {
+                       get { return selEndPos < 0 || selStartPos.Y < selEndPos.Y ? selStartPos :
+                                       selStartPos.Y > selEndPos.Y ? selEndPos :
+                                       selStartPos.X < selEndPos.X ? selStartPos : selEndPos; }
                }
-               /// <summary>
-               /// Set selection in buffer to -1, empty selection
-               /// </summary>
-               public void ResetSelection () {
-                       selectionStart = selectionEnd = -1;
-               }
-               bool selectionIsEmpty {
-                       get { return selectionStart == selectionEnd; }
+               public Point SelectionEnd {
+                       get { return selEndPos < 0 || selStartPos.Y > selEndPos.Y ? selStartPos :
+                                       selStartPos.Y < selEndPos.Y ? selEndPos :
+                                       selStartPos.X > selEndPos.X ? selStartPos : selEndPos; }
                }
+               public bool SelectionIsEmpty
+               { get { return selEndPos == selStartPos; } }
                /// <summary>
                /// Current column in buffer coordinate, tabulation = 1 char
                /// </summary>
@@ -235,6 +317,8 @@ namespace Crow.Coding
                                        _currentCol = lines [_currentLine].Length;
                                else
                                        _currentCol = value;
+
+                               PositionChanged.Raise (this, null);
                        }
                }
                /// <summary>
@@ -251,57 +335,31 @@ namespace Crow.Coding
                                        _currentLine = 0;
                                else
                                        _currentLine = value;
-                               //force recheck of currentCol for bounding
-                               int cc = _currentCol;
-                               _currentCol = 0;
-                               CurrentColumn = cc;
+
+                               if (_currentCol >  lines [_currentLine].Length)
+                                       _currentCol = lines [_currentLine].Length;
+                               Debug.WriteLine ("buff cur line: " + _currentLine);
+                               PositionChanged.Raise (this, null);
                        }
                }
+               public CodeLine CurrentCodeLine {
+                       get { return this [_currentLine]; }
+               }
                /// <summary>
                /// Current position in buffer coordinate, tabulation = 1 char
                /// </summary>
                public Point CurrentPosition {
                        get { return new Point(CurrentColumn, CurrentLine); }
-                       set {
-                               _currentCol = value.X;
-                               _currentLine = value.Y;
-                       }
+//                     set {
+//                             _currentCol = value.X;
+//                             _currentLine = value.Y;
+//                     }
                }
                /// <summary>
                /// get char at current position in buffer
                /// </summary>
                protected Char CurrentChar { get { return lines [CurrentLine] [CurrentColumn]; } }
 
-               /// <summary>
-               /// Moves cursor one char to the left, move up if cursor reaches start of line
-               /// </summary>
-               /// <returns><c>true</c> if move succeed</returns>
-               public bool MoveLeft(){
-                       int tmp = _currentCol - 1;
-                       if (tmp < 0) {
-                               if (_currentLine == 0)
-                                       return false;
-                               _currentCol = int.MaxValue;
-                               CurrentLine--;
-                       } else
-                               CurrentColumn = tmp;
-                       return true;
-               }
-               /// <summary>
-               /// Moves cursor one char to the right, move down if cursor reaches end of line
-               /// </summary>
-               /// <returns><c>true</c> if move succeed</returns>
-               public bool MoveRight(){
-                       int tmp = _currentCol + 1;
-                       if (tmp > this [_currentLine].Length){
-                               if (CurrentLine == this.LineCount - 1)
-                                       return false;
-                               CurrentLine++;
-                               CurrentColumn = 0;
-                       } else
-                               CurrentColumn = tmp;
-                       return true;
-               }
                public void GotoWordStart(){
                        if (this[CurrentLine].Length == 0)
                                return;
@@ -327,34 +385,36 @@ namespace Crow.Coding
                }
                public void DeleteChar()
                {
-                       if (selectionIsEmpty) {
-                               if (CurrentColumn == 0) {
-                                       if (CurrentLine == 0 && this.LineCount == 1)
+                       lock (EditMutex) {
+                               if (SelectionIsEmpty) {
+                                       if (CurrentColumn == 0) {
+                                               if (CurrentLine == 0)
+                                                       return;
+                                               CurrentLine--;
+                                               CurrentColumn = this [CurrentLine].Length;
+                                               AppenedLine (CurrentLine, this [CurrentLine + 1].Content);
+                                               RemoveAt (CurrentLine + 1);
                                                return;
-                                       CurrentLine--;
-                                       CurrentColumn = this [CurrentLine].Length;
-                                       this [CurrentLine] += this [CurrentLine + 1];
-                                       RemoveAt (CurrentLine + 1);
-                                       return;
-                               }
-                               CurrentColumn--;
-                               this [CurrentLine] = this [CurrentLine].Remove (CurrentColumn, 1);
-                       } else {
-                               int linesToRemove = selectionEnd.Y - selectionStart.Y + 1;
-                               int l = selectionStart.Y;
+                                       }
+                                       CurrentColumn--;
+                                       UpdateLine (CurrentLine, this [CurrentLine].Content.Remove (CurrentColumn, 1));
+                               } else {
+                                       int linesToRemove = SelectionEnd.Y - SelectionStart.Y + 1;
+                                       int l = SelectionStart.Y;
 
-                               if (linesToRemove > 0) {
-                                       this [l] = this [l].Remove (selectionStart.X, this [l].Length - selectionStart.X) +
-                                               this [selectionEnd.Y].Substring (selectionEnd.X, this [selectionEnd.Y].Length - selectionEnd.X);
-                                       l++;
-                                       for (int c = 0; c < linesToRemove-1; c++)
-                                               RemoveAt (l);
-                                       CurrentLine = selectionStart.Y;
-                                       CurrentColumn = selectionStart.X;
-                               } else
-                                       this [l] = this [l].Remove (selectionStart.X, selectionEnd.X - selectionStart.X);
-                               CurrentColumn = selectionStart.X;
-                               ResetSelection ();
+                                       if (linesToRemove > 0) {
+                                               UpdateLine (l, this [l].Content.Remove (SelectionStart.X, this [l].Length - SelectionStart.X) +
+                                               this [SelectionEnd.Y].Content.Substring (SelectionEnd.X, this [SelectionEnd.Y].Length - SelectionEnd.X));
+                                               l++;
+                                               for (int c = 0; c < linesToRemove - 1; c++)
+                                                       RemoveAt (l);
+                                               CurrentLine = SelectionStart.Y;
+                                               CurrentColumn = SelectionStart.X;
+                                       } else
+                                               UpdateLine (l, this [l].Content.Remove (SelectionStart.X, SelectionEnd.X - SelectionStart.X));
+                                       CurrentColumn = SelectionStart.X;
+                                       ResetSelection ();
+                               }
                        }
                }
                /// <summary>
@@ -363,14 +423,14 @@ namespace Crow.Coding
                /// <param name="str">String.</param>
                public void Insert(string str)
                {
-                       if (!selectionIsEmpty)
+                       if (!SelectionIsEmpty)
                                this.DeleteChar ();
                        string[] strLines = Regex.Split (str, "\r\n|\r|\n|" + @"\\n").ToArray();
-                       this [CurrentLine] = this [CurrentLine].Insert (CurrentColumn, strLines[0]);
+                       UpdateLine (CurrentLine, this [CurrentLine].Content.Insert (CurrentColumn, strLines[0]));
                        CurrentColumn += strLines[0].Length;
                        for (int i = 1; i < strLines.Length; i++) {
                                InsertLineBreak ();
-                               this [CurrentLine] = this [CurrentLine].Insert (CurrentColumn, strLines[i]);
+                               UpdateLine (CurrentLine, this [CurrentLine].Content.Insert (CurrentColumn, strLines[i]));
                                CurrentColumn += strLines[i].Length;
                        }
                }
@@ -380,13 +440,13 @@ namespace Crow.Coding
                public void InsertLineBreak()
                {
                        if (CurrentColumn > 0) {
-                               Insert (CurrentLine + 1, this [CurrentLine].Substring (CurrentColumn));
-                               this [CurrentLine] = this [CurrentLine].Substring (0, CurrentColumn);
+                               Insert (CurrentLine + 1, this [CurrentLine].Content.Substring (CurrentColumn));
+                               UpdateLine (CurrentLine, this [CurrentLine].Content.Substring (0, CurrentColumn));
                        } else
                                Insert(CurrentLine, "");
 
-                       CurrentLine++;
                        CurrentColumn = 0;
+                       CurrentLine++;
                }
                #endregion
        }
diff --git a/src/CodeLine.cs b/src/CodeLine.cs
new file mode 100644 (file)
index 0000000..622584c
--- /dev/null
@@ -0,0 +1,76 @@
+using System;
+using System.Text;
+using System.Collections.Generic;
+
+namespace Crow.Coding
+{
+       public class CodeLine
+       {
+               public string Content;
+               public List<Token> Tokens;
+               public int EndingState = 0;
+               public Node SyntacticNode;
+               public ParsingException exception;
+
+               public CodeLine (string _content){
+                       Content = _content;
+                       Tokens = null;
+                       exception = null;
+               }
+
+               public char this[int i]
+               {
+                       get { return Content[i]; }
+                       set {
+                               if (Content [i] == value)
+                                       return;
+                               StringBuilder sb = new StringBuilder(Content);
+                               sb[i] = value;
+                               Content = sb.ToString();
+                               Tokens = null;
+                               //LineUpadateEvent.Raise (this, new CodeBufferEventArgs (i));
+                       }
+               }
+               public bool IsFoldable { get { return SyntacticNode != null; } }
+               public bool IsFolded = false;
+               public bool IsParsed {
+                       get { return Tokens != null; }
+               }
+               public string PrintableContent {
+                       get {
+                               return string.IsNullOrEmpty (Content) ? "" : Content.Replace ("\t", new String (' ', Interface.TabSize));
+                       }
+               }
+               public int PrintableLength {
+                       get {
+                               return PrintableContent.Length;
+                       }
+               }
+               public int Length {
+                       get {
+                               return string.IsNullOrEmpty (Content) ? 0 : Content.Length;
+                       }
+               }
+
+               public void SetLineInError (ParsingException ex) {
+                       Tokens = null; 
+                       exception = ex;
+               }
+
+//             public static implicit operator string(CodeLine sl) {
+//                     return sl == null ? "" : sl.Content;
+//             }
+               public static implicit operator CodeLine(string s) {
+                       return new CodeLine(s);
+               }
+               public static bool operator ==(string s1, CodeLine s2)
+               {
+                       return string.Equals (s1, s2.Content);
+               }
+               public static bool operator !=(string s1, CodeLine s2)
+               {
+                       return !string.Equals (s1, s2.Content);
+               }
+       }
+}
+
index 94eceb60610d3f77c839c6bed7cd11d3a8a6a276..24818e019fc65afb481d3cc1c191b133403fbcc9 100644 (file)
@@ -8,8 +8,8 @@ namespace Crow.Coding
                public Node Parent;
                public string Name;
                public string Type;
-               public int StartLine;
-               public int EndLine;
+               public CodeLine StartLine;
+               public CodeLine EndLine;
                public Dictionary<string,string> Attributes = new Dictionary<string, string> ();
 
                public List<Node> Children = new List<Node>();
index dcb2c62359f59e9f83d50a3f9c68614fc9016517..79dc086fc039a3931bac849fb17bfa167495f8ae 100644 (file)
@@ -20,7 +20,9 @@ namespace Crow.Coding
                        WhiteSpace,
                        NewLine,
                        LineComment,
+                       BlockCommentStart,
                        BlockComment,
+                       BlockCommentEnd,
                        Type,
                        Identifier,
                        Indexer,
@@ -46,10 +48,6 @@ namespace Crow.Coding
                        //buffer.LineAdditionEvent += Buffer_LineAdditionEvent;;
                        buffer.LineRemoveEvent += Buffer_LineRemoveEvent;
                        buffer.BufferCleared += Buffer_BufferCleared;
-
-                       Tokens = new List<TokenList> ();
-                       if (buffer.LineCount > 0)
-                               eof = false;
                }
 
                #endregion
@@ -57,7 +55,7 @@ namespace Crow.Coding
                #region Buffer events handlers
                void Buffer_BufferCleared (object sender, EventArgs e)
                {
-                       Tokens.Clear ();
+
                }
                void Buffer_LineAdditionEvent (object sender, CodeBufferEventArgs e)
                {
@@ -65,8 +63,6 @@ namespace Crow.Coding
                }
                void Buffer_LineRemoveEvent (object sender, CodeBufferEventArgs e)
                {
-                       for (int i = 0; i < e.LineCount; i++)
-                               Tokens.RemoveAt (e.LineStart + i);
                        reparseSource ();
                }
                void Buffer_LineUpadateEvent (object sender, CodeBufferEventArgs e)
@@ -117,8 +113,8 @@ namespace Crow.Coding
                        //                      }
                }
                public void reparseSource () {
-                       for (int i = 0; i < Tokens.Count; i++) {
-                               if (Tokens[i].Dirty)
+                       for (int i = 0; i < buffer.LineCount; i++) {
+                               if (!buffer[i].IsParsed)
                                        tryParseBufferLine (i);
                        }
                        try {
@@ -130,8 +126,13 @@ namespace Crow.Coding
                        }
                }
                public void tryParseBufferLine(int lPtr) {
+                       buffer [lPtr].exception = null;
+                       currentLine = lPtr;
+                       currentColumn = 0;
+                       eol = false;
+
                        try {
-                               Parse (lPtr);
+                               ParseCurrentLine ();
                        } catch (Exception ex) {
                                Debug.WriteLine (ex.ToString ());
                                if (ex is ParsingException)
@@ -140,54 +141,33 @@ namespace Crow.Coding
 
                }
 
-               CodeBuffer buffer;
+               protected CodeBuffer buffer;
 
                internal int currentLine = 0;
                internal int currentColumn = 0;
                protected Token currentTok;
-               protected bool eof = true;
-
-               public List<TokenList> Tokens;
-               protected TokenList TokensLine;
+               protected bool eol = true;
 
                public Node RootNode;
 
-               public Point CurrentPosition {
+               protected Point CurrentPosition {
                        get { return new Point (currentLine, currentColumn); }
                        set {
                                currentLine = value.Y;
                                currentColumn = value.X;
                        }
                }
-               public int LineCount {
-                       get { return Tokens.Count; }
-               }
 
-               /// <summary>
-               /// unfolded and not in folds line count
-               /// </summary>
-               public int VisibleLines {
-                       get {
-                               int i = 0, vl = 0;
-                               while (i<Tokens.Count) {
-                                       if (Tokens [i].folded && Tokens [i].SyntacticNode != null) {
-                                               i = Tokens [i].SyntacticNode.EndLine;
-                                       }
-                                       i++;
-                                       vl++;
-                               }
-                               return vl;
-                       }
-               }
-                       
-               public abstract void Parse(int line);
+               public abstract void ParseCurrentLine();
                public abstract void SyntaxAnalysis ();
 
                public virtual void SetLineInError(ParsingException ex) {
                        currentTok = default(Token);
-                       Tokens [ex.Line].Clear ();
-                       Tokens [ex.Line].Add(new Token() {Content = buffer [ex.Line]});
-                       Tokens [ex.Line].exception = ex; 
+                       if (ex.Line >= buffer.LineCount)
+                               ex.Line = buffer.LineCount - 1;
+                       if (buffer [ex.Line].IsFolded)
+                               buffer.ToogleFolding (ex.Line);
+                       buffer [ex.Line].SetLineInError (ex);
                }
 
                #region low level parsing
@@ -212,7 +192,7 @@ namespace Crow.Coding
                /// </summary>
                protected void saveAndResetCurrentTok() {
                        currentTok.End = CurrentPosition;
-                       TokensLine.Add (currentTok);
+                       buffer[currentLine].Tokens.Add (currentTok);
                        currentTok = default(Token);
                }
                /// <summary>
@@ -237,8 +217,8 @@ namespace Crow.Coding
                /// Throw error if eof is true
                /// </summary>
                protected virtual char Peek() {
-                       if (eof)
-                               throw new ParsingException (this, "Unexpected End of File");
+                       if (eol)
+                               throw new ParsingException (this, "Unexpected End of line");
                        return currentColumn < buffer [currentLine].Length ?
                                buffer [currentLine] [currentColumn] : '\n';
                }
@@ -250,12 +230,12 @@ namespace Crow.Coding
                /// </summary>
                /// <param name="length">Length.</param>
                protected virtual string Peek(int length) {
-                       if (eof)
-                               throw new ParsingException (this, "Unexpected End of File");
+                       if (eol)
+                               throw new ParsingException (this, "Unexpected End of Line");
                        int lg = Math.Min(length, Math.Max (buffer [currentLine].Length - currentColumn, buffer [currentLine].Length - currentColumn - length));
                        if (lg == 0)
                                return "";
-                       return buffer [currentLine].Substring (currentColumn, lg);
+                       return buffer [currentLine].Content.Substring (currentColumn, lg);
                }
                /// <summary>
                /// read one char from buffer at current position, if '\n' is read, current line is incremented
@@ -263,14 +243,9 @@ namespace Crow.Coding
                /// </summary>
                protected virtual char Read() {
                        char c = Peek ();
-                       //TODO: the parsing is done line by line, we should be able to remove the next line handling from read
-                       if (c == '\n') {
-                               currentLine++;
-                               if (currentLine >= buffer.LineCount)
-                                       eof = true;
-                               currentColumn = 0;
-                       } else
-                               currentColumn++;
+                       if (c == '\n')
+                               eol = true;
+                       currentColumn++;
                        return c;
                }
                /// <summary>
@@ -279,11 +254,8 @@ namespace Crow.Coding
                /// <returns>string read</returns>
                protected virtual string ReadLine () {
                        string tmp = "";
-                       while (!eof) {
-                               if (Peek () == '\n')
-                                       return tmp;
+                       while (!eol)
                                tmp += Read ();
-                       }
                        return tmp;
                }
                /// <summary>
@@ -294,7 +266,7 @@ namespace Crow.Coding
                protected virtual string ReadLineUntil (string endExp){
                        string tmp = "";
 
-                       while (!eof) {
+                       while (!eol) {
                                if (buffer [currentLine].Length - currentColumn - endExp.Length < 0) {
                                        tmp += ReadLine();
                                        break;
@@ -311,7 +283,7 @@ namespace Crow.Coding
                protected void SkipWhiteSpaces () {
                        if (currentTok.Type != TokenType.Unknown)
                                throw new ParsingException (this, "current token should be reset to unknown (0) before skiping white spaces");
-                       while (!eof) {
+                       while (!eol) {
                                if (!char.IsWhiteSpace (Peek ())||Peek()=='\n')
                                        break;
                                readToCurrTok (currentTok.Type == TokenType.Unknown);
index 2c53ba7b275b6f711d0fcc861e5e77eaa6c9e858..57c5757090c444ad79c677ea449dccb6bac5fe58 100644 (file)
@@ -45,7 +45,7 @@ namespace Crow.Coding
        public class SourceEditor : ScrollingObject
        {
                #region CTOR
-               public SourceEditor ():base()
+               public SourceEditor (): base()
                {
                        formatting.Add ((int)XMLParser.TokenType.AttributeName, new TextFormatting (Color.UnitedNationsBlue, Color.Transparent));
                        formatting.Add ((int)XMLParser.TokenType.ElementName, new TextFormatting (Color.DarkBlue, Color.Transparent));
@@ -67,10 +67,14 @@ namespace Crow.Coding
                        buffer.LineAdditionEvent += Buffer_LineAdditionEvent;;
                        buffer.LineRemoveEvent += Buffer_LineRemoveEvent;
                        buffer.BufferCleared += Buffer_BufferCleared;
+                       buffer.SelectionChanged += Buffer_SelectionChanged;
+                       buffer.PositionChanged += Buffer_PositionChanged;
+                       buffer.FoldingEvent += Buffer_FoldingEvent;
+                       buffer.Add (new CodeLine(""));
                }
                #endregion
 
-               const int leftMarginGap = 5;//gap between items in margin and text
+               const int leftMarginGap = 3;//gap between items in margin and text
                const int foldSize = 9;//folding rectangles size
 
                #region private and protected fields
@@ -83,10 +87,9 @@ namespace Crow.Coding
                Parser parser;
                Color selBackground;
                Color selForeground;
-               int _currentCol;        //0 based cursor position in string
-               int _currentLine;
-               Point _selBegin = -1;   //selection start (row,column)
-               Point _selRelease = -1; //selection end (row,column)
+//             int _currentCol;        //0 based cursor position in string
+//             int _currentLine;
+
 
                Dictionary<int, TextFormatting> formatting = new Dictionary<int, TextFormatting>();
                Dictionary<string, string> parsing = new Dictionary<string, string>();
@@ -132,52 +135,46 @@ namespace Crow.Coding
                        if (parser == null || !foldingEnabled)
                                MaxScrollY = Math.Max (0, buffer.LineCount - visibleLines);
                        else
-                               MaxScrollY = Math.Max (0, parser.VisibleLines - visibleLines);                  
+                               MaxScrollY = Math.Max (0, buffer.UnfoldedLines - visibleLines);
                }
 
                int firstPrintedLine = -1;
                /// <summary>
                /// list of lines visible in the Editor depending on scrolling and folding
                /// </summary>
-               List<TokenList> PrintedLines;
+               List<CodeLine> PrintedLines;
 
                void updatePrintedLines () {
-                       if (parser == null)
-                               return;
-                       PrintedLines = new List<TokenList> ();
-                       int curL = 0;
-                       int i = 0;
-
-                       while (curL < parser.LineCount && i < ScrollY) {
-                               if (parser.Tokens [curL].folded && parser.Tokens [curL].SyntacticNode != null)
-                                       curL = parser.Tokens [curL].SyntacticNode.EndLine;
-                               curL++;
-                               i++;
-                       }
+                       lock (buffer.EditMutex) {
+                               PrintedLines = new List<CodeLine> ();
+                               int curL = 0;
+                               int i = 0;
+
+                               while (curL < buffer.LineCount && i < ScrollY) {
+                                       if (buffer [curL].IsFolded)
+                                               curL = buffer.GetEndNodeIndex (curL);
+                                       curL++;
+                                       i++;
+                               }
 
-                       firstPrintedLine = curL;
-                       i = 0;
-                       while (i < visibleLines && curL < parser.LineCount) {
-                               PrintedLines.Add (parser.Tokens [curL]);
+                               firstPrintedLine = curL;
+                               i = 0;
+                               while (i < visibleLines && curL < buffer.LineCount) {
+                                       PrintedLines.Add (buffer [curL]);
 
-                               if (parser.Tokens [curL].folded && parser.Tokens [curL].SyntacticNode != null)
-                                       curL = parser.Tokens [curL].SyntacticNode.EndLine;
+                                       if (buffer [curL].IsFolded)
+                                               curL = buffer.GetEndNodeIndex (curL);
 
-                               curL++;
-                               i++;
-                       }       
+                                       curL++;
+                                       i++;
+                               }
+                       }
                        RegisterForGraphicUpdate ();
                }
                void toogleFolding (int line) {
                        if (parser == null || !foldingEnabled)
                                return;
-                       if (parser.Tokens [line].SyntacticNode == null)
-                               return;
-                       parser.Tokens [line].folded = !parser.Tokens [line].folded;
-                       updatePrintedLines ();
-                       updateMaxScrollY ();
-
-                       RegisterForGraphicUpdate ();
+                       buffer.ToogleFolding (line);
                }
 
                #region Buffer events handlers
@@ -187,13 +184,14 @@ namespace Crow.Coding
                        buffer.longestLineIdx = 0;
                        measureLeftMargin ();
                        MaxScrollX = MaxScrollY = 0;
+                       PrintedLines = null;
                        RegisterForGraphicUpdate ();
                }
                void Buffer_LineAdditionEvent (object sender, CodeBufferEventArgs e)
                {
                        for (int i = 0; i < e.LineCount; i++) {
                                int lptr = e.LineStart + i;
-                               int charCount = buffer.GetPrintableLine (lptr).Length;
+                               int charCount = buffer[lptr].PrintableLength;
                                if (charCount > buffer.longestLineCharCount) {
                                        buffer.longestLineIdx = lptr;
                                        buffer.longestLineCharCount = charCount;
@@ -201,7 +199,6 @@ namespace Crow.Coding
                                        buffer.longestLineIdx++;
                                if (parser == null)
                                        continue;
-                               parser.Tokens.Insert (lptr, new TokenList ());
                                parser.tryParseBufferLine (e.LineStart + i);
                        }
                        measureLeftMargin ();
@@ -209,13 +206,10 @@ namespace Crow.Coding
                        if (parser != null)
                                parser.reparseSource ();
 
-
                        updatePrintedLines ();
-                       updateOnScreenPosFromBuffPos ();
-
+                       updateMaxScrollY ();
                        RegisterForGraphicUpdate ();
                }
-
                void Buffer_LineRemoveEvent (object sender, CodeBufferEventArgs e)
                {
                        bool trigFindLongestLine = false;
@@ -226,20 +220,22 @@ namespace Crow.Coding
                        }
                        if (trigFindLongestLine)
                                findLongestLineAndUpdateMaxScrollX ();
+
                        measureLeftMargin ();
                        updatePrintedLines ();
+                       updateMaxScrollY ();
                        RegisterForGraphicUpdate ();
                }
-
                void Buffer_LineUpadateEvent (object sender, CodeBufferEventArgs e)
                {
                        bool trigFindLongestLine = false;
                        for (int i = 0; i < e.LineCount; i++) {
+
                                int lptr = e.LineStart + i;
                                if (lptr == buffer.longestLineIdx)
                                        trigFindLongestLine = true;
-                               else if (buffer.GetPrintableLine (lptr).Length > buffer.longestLineCharCount) {
-                                       buffer.longestLineCharCount = buffer.GetPrintableLine (lptr).Length;
+                               else if (buffer[lptr].PrintableLength > buffer.longestLineCharCount) {
+                                       buffer.longestLineCharCount = buffer[lptr].PrintableLength;
                                        buffer.longestLineIdx = lptr;
                                }
                        }
@@ -247,6 +243,21 @@ namespace Crow.Coding
                                findLongestLineAndUpdateMaxScrollX ();
                        RegisterForGraphicUpdate ();
                }
+               void Buffer_PositionChanged (object sender, EventArgs e)
+               {
+                       updateOnScreenCurLineFromBuffCurLine ();
+               }
+
+               void Buffer_SelectionChanged (object sender, EventArgs e)
+               {
+                       RegisterForGraphicUpdate ();
+               }
+               void Buffer_FoldingEvent (object sender, CodeBufferEventArgs e)
+               {
+                       updatePrintedLines ();
+                       updateMaxScrollY ();
+                       RegisterForGraphicUpdate ();
+               }
                #endregion
 
                Parser getParserFromExt (string extension) {
@@ -333,229 +344,101 @@ namespace Crow.Coding
                                RegisterForRedraw ();
                        }
                }
-               [XmlAttributeAttribute][DefaultValue(0)]
-               public int CurrentColumn{
-                       get { return _currentCol; }
-                       set {
-                               if (value == _currentCol)
-                                       return;
-                               if (value < 0)
-                                       _currentCol = 0;
-                               else if (value > buffer.GetPrintableLine(_currentLine).Length)
-                                       _currentCol = buffer.GetPrintableLine(_currentLine).Length;
-                               else
-                                       _currentCol = value;
-
-                               buffer.SetBufferPos (CurrentPosition);
-
-                               if (_currentCol < ScrollX)
-                                       ScrollX = _currentCol;
-                               else if (_currentCol >= ScrollX + visibleColumns)
-                                       ScrollX = _currentCol - visibleColumns + 1;
-
-                               NotifyValueChanged ("CurrentColumn", _currentCol);
-                       }
-               }
-               [XmlAttributeAttribute][DefaultValue(0)]
-               public int CurrentLine{
-                       get { return _currentLine; }
-                       set {
-                               if (value == _currentLine)
-                                       return;
-                               if (value >= buffer.LineCount)
-                                       _currentLine = buffer.LineCount-1;
-                               else if (value < 0)
-                                       _currentLine = 0;
-                               else
-                                       _currentLine = value;
-
-                               if (_currentCol > buffer.GetPrintableLine(_currentLine).Length)
-                                       CurrentColumn = buffer.GetPrintableLine(_currentLine).Length;//buffer.setBufferPos is called inside
-                               else
-                                       buffer.SetBufferPos (CurrentPosition);
-
-//                             if (_currentLine < ScrollY)
-//                                     ScrollY = _currentLine;
-//                             else if (_currentLine >= ScrollY + visibleLines)
-//                                     ScrollY = _currentLine - visibleLines + 1;
-                               
-                               NotifyValueChanged ("CurrentLine", _currentLine);
-                       }
-               }
-               /// <summary>
-               /// Current position is in the printed coord system, tabulation chars are replaced with 4 spaces,
-               /// while in the buffer, the position holds tabulations as single chars
-               /// </summary>
-               /// <value>The current position.</value>
-               [XmlIgnore]public Point CurrentPosition {
-                       get { return new Point(CurrentColumn, CurrentLine); }
-                       set {
-                               _currentCol = value.X;
-                               _currentLine = value.Y;
-
-                               if (_currentCol < ScrollX)
-                                       ScrollX = _currentCol;
-                               else if (_currentCol >= ScrollX + visibleColumns)
-                                       ScrollX = _currentCol - visibleColumns + 1;
+//             [XmlAttributeAttribute][DefaultValue(0)]
+//             public int CurrentColumn{
+//                     get { return _currentCol; }
+////                   set {
+////                           if (value == _currentCol)
+////                                   return;
+////                           if (value < 0)
+////                                   _currentCol = 0;
+////                           else if (value > buffer[_currentLine].PrintableLength)
+////                                   _currentCol = buffer[_currentLine].PrintableLength;
+////                           else
+////                                   _currentCol = value;
+////
+////                           buffer.SetBufferPos (CurrentPosition);
+////
+////                           if (_currentCol < ScrollX)
+////                                   ScrollX = _currentCol;
+////                           else if (_currentCol >= ScrollX + visibleColumns)
+////                                   ScrollX = _currentCol - visibleColumns + 1;
+////
+////                           NotifyValueChanged ("CurrentColumn", _currentCol);
+////                   }
+//             }
+//             [XmlAttributeAttribute][DefaultValue(0)]
+//             public int CurrentLine{
+//                     get { return _currentLine; }
+////                   set {
+////                           if (value == _currentLine)
+////                                   return;
+////                           if (value >= buffer.LineCount)
+////                                   _currentLine = buffer.LineCount-1;
+////                           else if (value < 0)
+////                                   _currentLine = 0;
+////                           else
+////                                   _currentLine = value;
+////
+////                           if (_currentCol > buffer[_currentLine].PrintableLength)
+////                                   CurrentColumn = buffer[_currentLine].PrintableLength;//buffer.setBufferPos is called inside
+////                           else
+////                                   buffer.SetBufferPos (CurrentPosition);
+////
+//////                         if (_currentLine < ScrollY)
+//////                                 ScrollY = _currentLine;
+//////                         else if (_currentLine >= ScrollY + visibleLines)
+//////                                 ScrollY = _currentLine - visibleLines + 1;
+////
+////                           NotifyValueChanged ("CurrentLine", _currentLine);
+////                   }
+//             }
+//             /// <summary>
+//             /// Current position is in the printed coord system, tabulation chars are replaced with 4 spaces,
+//             /// while in the buffer, the position holds tabulations as single chars
+//             /// </summary>
+//             /// <value>The current position.</value>
+//             [XmlIgnore]public Point CurrentPosition {
+//                     get { return new Point(CurrentColumn, CurrentLine); }
+//                     set {
+//                             _currentCol = value.X;
+//                             _currentLine = value.Y;
 //
-//                             if (_currentLine < ScrollY)
-//                                     ScrollY = _currentLine;
-//                             else if (_currentLine >= ScrollY + visibleLines)
-//                                     ScrollY = _currentLine - visibleLines + 1;
+//                             if (_currentCol < ScrollX)
+//                                     ScrollX = _currentCol;
+//                             else if (_currentCol >= ScrollX + visibleColumns)
+//                                     ScrollX = _currentCol - visibleColumns + 1;
+////
+////                           if (_currentLine < ScrollY)
+////                                   ScrollY = _currentLine;
+////                           else if (_currentLine >= ScrollY + visibleLines)
+////                                   ScrollY = _currentLine - visibleLines + 1;
+//
+//                             NotifyValueChanged ("CurrentColumn", _currentCol);
+//                             NotifyValueChanged ("CurrentLine", _currentLine);
+//                     }
+//             }
+
+//             [XmlIgnore]public string SelectedText
+//             {
+//                     get {
+//                             if (!selectionIsEmpty)
+//                                     buffer.SetSelection (selectionStart, selectionEnd);
+//                             return buffer.SelectedText;
+//                     }
+//             }
 
-                               NotifyValueChanged ("CurrentColumn", _currentCol);
-                               NotifyValueChanged ("CurrentLine", _currentLine);
-                       }
-               }
-               //TODO:using HasFocus for drawing selection cause SelBegin and Release binding not to work
-               /// <summary>
-               /// Selection begin position in char units (line, column)
-               /// </summary>
-               [XmlAttributeAttribute][DefaultValue("-1")]
-               public Point SelBegin {
-                       get { return _selBegin; }
-                       set {
-                               if (value == _selBegin)
-                                       return;
-                               _selBegin = value;
-                               System.Diagnostics.Debug.WriteLine ("SelBegin=" + _selBegin);
-                               NotifyValueChanged ("SelBegin", _selBegin);
-                               //NotifyValueChanged ("SelectedText", SelectedText);
-                       }
-               }
-               /// <summary>
-               /// Selection release position in char units (line, column)
-               /// </summary>
-               [XmlAttributeAttribute][DefaultValue("-1")]
-               public Point SelRelease {
-                       get {
-                               return _selRelease;
-                       }
-                       set {
-                               if (value == _selRelease)
-                                       return;
-                               _selRelease = value;
-                               System.Diagnostics.Debug.WriteLine ("SelRelease=" + _selRelease);
-                               NotifyValueChanged ("SelRelease", _selRelease);
-                               //NotifyValueChanged ("SelectedText", SelectedText);
-                       }
-               }
-               /// <summary>
-               /// ordered selection start and end positions in char units
-               /// </summary>
-               [XmlIgnore]protected Point selectionStart
-               {
-                       get {
-                               return SelRelease < 0 || SelBegin.Y < SelRelease.Y ? SelBegin :
-                                       SelBegin.Y > SelRelease.Y ? SelRelease :
-                                       SelBegin.X < SelRelease.X ? SelBegin : SelRelease;
-                       }
-               }
-               [XmlIgnore]public Point selectionEnd
-               {
-                       get {
-                               return SelRelease < 0 || SelBegin.Y > SelRelease.Y ? SelBegin :
-                                       SelBegin.Y < SelRelease.Y ? SelRelease :
-                                       SelBegin.X > SelRelease.X ? SelBegin : SelRelease;
-                       }
-               }
-               [XmlIgnore]public string SelectedText
-               {
-                       get {
-                               if (!selectionIsEmpty)
-                                       buffer.SetSelection (selectionStart, selectionEnd);
-                               return buffer.SelectedText;
-                       }
-               }
-               [XmlIgnore]public bool selectionIsEmpty
-               { get { return SelRelease == SelBegin; } }
                #endregion
 
-               #region Editing and moving cursor
-               /// <summary>
-               /// Moves cursor one char to the left.
-               /// </summary>
-               /// <returns><c>true</c> if move succeed</returns>
-               public void MoveLeft(){
-                       if (CurrentPosition == 0)
-                               return;                 
-                       if (_currentCol == 0) {
-                               PrintedCurrentLine--;
-                               CurrentColumn = int.MaxValue;
-                       } else {
-                               //do move in the buffer so that tabulations are treated as single char
-                               buffer.CurrentColumn --;
-                               CurrentPosition = buffer.TabulatedPosition;
-                       }
-               }
-               /// <summary>
-               /// Moves cursor one char to the right.
-               /// </summary>
-               /// <returns><c>true</c> if move succeed</returns>
-               public void MoveRight(){
-                       if (_currentCol == buffer.GetPrintableLine(CurrentLine).Length && _currentLine < buffer.LineCount - 1) {
-                               PrintedCurrentLine++;
-                               CurrentColumn = 0;
-                       } else {
-                               //do move in the buffer so that tabulations are treated as single char
-                               buffer.CurrentColumn ++;
-                               CurrentPosition = buffer.TabulatedPosition;
-                       }
-               }
-               public void MoveUp (){
-                       PrintedCurrentLine--;
-               }
-               public void MoveDown (){
-                       PrintedCurrentLine++;
-               }
-               public void GotoWordStart(){
-                       buffer.GotoWordStart();
-                       updateOnScreenPosFromBuffPos ();
-               }
-               public void GotoWordEnd(){
-                       buffer.GotoWordEnd();
-                       updateOnScreenPosFromBuffPos ();
-               }
-
-               public void DeleteChar()
-               {
-                       if (!selectionIsEmpty)
-                               buffer.SetSelection (selectionStart, selectionEnd);
-                       buffer.DeleteChar ();
-                       updateOnScreenPosFromBuffPos ();
-                       SelBegin = -1;
-                       SelRelease = -1;
-               }
-               /// <summary>
-               /// Insert new string at caret position, should be sure no line break is inside.
-               /// </summary>
-               /// <param name="str">String.</param>
-               protected void Insert(string str)
-               {
-                       if (!selectionIsEmpty)
-                               DeleteChar ();
-
-                       buffer.Insert (str);
-                       CurrentPosition = buffer.TabulatedPosition;
-
-                       RegisterForGraphicUpdate();
-               }
-               #endregion
 
-               void updateOnScreenPosFromBuffPos(){
-                       if (parser.Tokens.Count == 0 || PrintedLines.Count == 0)
-                               return;
-                       if (!PrintedLines.Contains (parser.Tokens [buffer.CurrentLine]))
-                               return;
-                       printedCurrentLine = PrintedLines.IndexOf (parser.Tokens [buffer.CurrentLine]);
-                       setCurrentLineFromBuffer ();
-                       CurrentColumn = buffer.TabulatedColumn;
+               void updateOnScreenCurLineFromBuffCurLine(){
+                       printedCurrentLine = PrintedLines.IndexOf (buffer.CurrentCodeLine);
                }
 
-               void setCurrentLineFromBuffer () {
-                       _currentLine = buffer.CurrentLine;
-                       NotifyValueChanged ("CurrentLine", _currentLine);
-               }
+//             void setCurrentLineFromBuffer () {
+//                     _currentLine = buffer.CurrentLine;
+//                     NotifyValueChanged ("CurrentLine", _currentLine);
+//             }
 
                public override int ScrollY {
                        get {
@@ -575,6 +458,9 @@ namespace Crow.Coding
                /// </summary>
                int printedCurrentLine = 0;
 
+               /// <summary>
+               /// Current editor line, when set, update buffer.CurrentLine
+               /// </summary>
                int PrintedCurrentLine {
                        get { return printedCurrentLine;}
                        set {
@@ -588,158 +474,86 @@ namespace Crow.Coding
                                        printedCurrentLine = visibleLines - 1;
                                }else
                                        printedCurrentLine = value;
-
+                               Debug.WriteLine ("printed current line:" + printedCurrentLine.ToString ());
                                //update position in buffer
-                               CurrentLine = parser.Tokens.IndexOf (PrintedLines[printedCurrentLine]);
+                               buffer.CurrentLine = buffer.IndexOf (PrintedLines[printedCurrentLine]);
                        }
                }
-
-
-               #region Drawing
+               int getTabulatedColumn (int col, int line) {
+                       return buffer [line].Content.Substring (0, col).Replace ("\t", new String (' ', Interface.TabSize)).Length;
+               }
+               int getTabulatedColumn (Point pos) {
+                       return getTabulatedColumn (pos.X,pos.Y);
+               }
                /// <summary>
-               /// Draw unparsed buffer.
+               /// Moves cursor one char to the left, move up if cursor reaches start of line
                /// </summary>
-               void draw(Context gr){
-                       gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight);
-                       gr.SetFontSize (Font.Size);
-                       gr.FontOptions = Interface.FontRenderingOptions;
-                       gr.Antialias = Interface.Antialias;
-
-                       Rectangle cb = ClientRectangle;
-
-                       bool selectionInProgress = false;
-
-                       Foreground.SetAsSource (gr);
-
-                       #region draw text cursor
-                       if (SelBegin != SelRelease)
-                               selectionInProgress = true;
-                       else if (HasFocus){
-                               gr.LineWidth = 1.0;
-                               double cursorX = cb.X + (CurrentColumn - ScrollX) * fe.MaxXAdvance + leftMargin;
-                               gr.MoveTo (0.5 + cursorX, cb.Y + (CurrentLine - ScrollY) * fe.Height);
-                               gr.LineTo (0.5 + cursorX, cb.Y + (CurrentLine + 1 - ScrollY) * fe.Height);
-                               gr.Stroke();
-                       }
-                       #endregion
-
-                       for (int i = 0; i < visibleLines; i++) {
-                               int curL = i + ScrollY;
-                               if (curL >= buffer.LineCount)
-                                       break;
-                               string lstr = buffer.GetPrintableLine(curL);
-                               if (ScrollX < lstr.Length)
-                                       lstr = lstr.Substring (ScrollX);
-                               else
-                                       lstr = "";
-
-                               gr.MoveTo (cb.X, cb.Y + fe.Ascent + fe.Height * i);
-                               gr.ShowText (lstr);
-                               gr.Fill ();
-
-                               if (selectionInProgress && curL >= selectionStart.Y && curL <= selectionEnd.Y) {
-
-                                       double rLineX = cb.X,
-                                       rLineY = cb.Y + i * fe.Height,
-                                       rLineW = lstr.Length * fe.MaxXAdvance;
-
-                                       System.Diagnostics.Debug.WriteLine ("sel start: " + selectionStart + " sel end: " + selectionEnd);
-                                       if (curL == selectionStart.Y) {
-                                               rLineX += (selectionStart.X - ScrollX) * fe.MaxXAdvance;
-                                               rLineW -= selectionStart.X * fe.MaxXAdvance;
-                                       }
-                                       if (curL == selectionEnd.Y)
-                                               rLineW -= (lstr.Length - selectionEnd.X) * fe.MaxXAdvance;
-
-                                       gr.Save ();
-                                       gr.Operator = Operator.Source;
-                                       gr.Rectangle (rLineX, rLineY, rLineW, fe.Height);
-                                       gr.SetSourceColor (SelectionBackground);
-                                       gr.FillPreserve ();
-                                       gr.Clip ();
-                                       gr.Operator = Operator.Over;
-                                       gr.SetSourceColor (SelectionForeground);
-                                       gr.MoveTo (cb.X, cb.Y + fe.Ascent + fe.Height * i);
-                                       gr.ShowText (lstr);
-                                       gr.Fill ();
-                                       gr.Restore ();
-                               }
-                       }
+               /// <returns><c>true</c> if move succeed</returns>
+               public bool MoveLeft(){
+                       if (buffer.CurrentColumn == 0) {
+                               if (printedCurrentLine == 0)
+                                       return false;
+                               PrintedCurrentLine--;
+                               buffer.CurrentColumn = int.MaxValue;
+                       } else
+                               buffer.CurrentColumn--;
+                       return true;
                }
-               void drawParsed(Context gr){
-                       if (PrintedLines == null)
-                               return;
-
-                       gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight);
-                       gr.SetFontSize (Font.Size);
-                       gr.FontOptions = Interface.FontRenderingOptions;
-                       gr.Antialias = Interface.Antialias;
-
-                       Rectangle cb = ClientRectangle;
-                       gr.Save ();
-                       CairoHelpers.CairoRectangle (gr, cb, CornerRadius);
-                       gr.Clip ();
-
-                       bool selectionInProgress = false;
-
-                       Foreground.SetAsSource (gr);
-
-                       #region draw text cursor
-                       if (SelBegin != SelRelease)
-                               selectionInProgress = true;
-                       else if (HasFocus){
-                               gr.LineWidth = 1.0;
-                               double cursorX = + leftMargin + cb.X + (CurrentColumn - ScrollX) * fe.MaxXAdvance;
-                               gr.MoveTo (0.5 + cursorX, cb.Y + printedCurrentLine * fe.Height);
-                               gr.LineTo (0.5 + cursorX, cb.Y + (printedCurrentLine + 1) * fe.Height);
-                               gr.Stroke();
-                       }
-                       #endregion
-
-                       for (int i = 0; i < PrintedLines.Count; i++)
-                               drawTokenLine (gr, i, selectionInProgress, cb);
-
-                       gr.Restore ();
+               /// <summary>
+               /// Moves cursor one char to the right, move down if cursor reaches end of line
+               /// </summary>
+               /// <returns><c>true</c> if move succeed</returns>
+               public bool MoveRight(){
+                       if (buffer.CurrentColumn >= buffer.CurrentCodeLine.Length) {
+                               if (PrintedCurrentLine == buffer.UnfoldedLines - 1)
+                                       return false;
+                               buffer.CurrentColumn = 0;
+                               PrintedCurrentLine++;
+                       } else
+                               buffer.CurrentColumn++;
+                       return true;
                }
-               void drawTokenLine(Context gr, int i, bool selectionInProgress, Rectangle cb) {
-                       TokenList tokens = PrintedLines[i];
-                       int lineIndex = parser.Tokens.IndexOf(tokens);
+               #region Drawing
+               void drawLine(Context gr, Rectangle cb, int i) {
+                       CodeLine cl = PrintedLines[i];
+                       int lineIndex = buffer.IndexOf(cl);
 
-                       int lPtr = 0;
-                       double y = cb.Y + fe.Height * i;
+                       double y = cb.Y + fe.Height * i, x = cb.X;
 
                        //Draw line numbering
                        Color mgFg = Color.Gray;
                        Color mgBg = Color.White;
                        if (PrintLineNumbers){
-                               Rectangle mgR = new Rectangle (cb.X, (int)y, leftMargin - leftMarginGap, (int)Math.Ceiling(fe.Height));
-                               if (tokens.exception != null) {
+                               Rectangle mgR = new Rectangle ((int)x, (int)y, leftMargin - leftMarginGap, (int)Math.Ceiling(fe.Height));
+                               if (cl.exception != null) {
                                        mgBg = Color.Red;
-                                       if (CurrentLine == lineIndex)
+                                       if (buffer.CurrentLine == lineIndex)
                                                mgFg = Color.White;
                                        else
                                                mgFg = Color.LightGray;
-                               }else if (CurrentLine == lineIndex) {
+                               }else if (buffer.CurrentLine == lineIndex) {
                                        mgFg = Color.Black;
                                }
-                               string strLN = lineIndex.ToString ();
+                               string strLN = (lineIndex+1).ToString ();
                                gr.SetSourceColor (mgBg);
                                gr.Rectangle (mgR);
                                gr.Fill();
                                gr.SetSourceColor (mgFg);
 
-                               gr.MoveTo (cb.X + (int)(gr.TextExtents (parser.Tokens.Count.ToString()).Width - gr.TextExtents (strLN).Width), y + fe.Ascent);
+                               gr.MoveTo (cb.X + (int)(gr.TextExtents (buffer.LineCount.ToString()).Width - gr.TextExtents (strLN).Width), y + fe.Ascent);
                                gr.ShowText (strLN);
                                gr.Fill ();
                        }
+
+
                        //draw folding
                        if (foldingEnabled){
-                               if (tokens.SyntacticNode != null) {
-                                       if (tokens.SyntacticNode.StartLine < tokens.SyntacticNode.EndLine) {
+                               if (cl.IsFoldable) {
+                                       if (cl.SyntacticNode.StartLine != cl.SyntacticNode.EndLine) {
                                                gr.SetSourceColor (Color.Black);
                                                Rectangle rFld = new Rectangle (cb.X + leftMargin - leftMarginGap - foldSize, (int)(y + fe.Height / 2.0 - foldSize / 2.0), foldSize, foldSize);
                                                gr.Rectangle (rFld, 1.0);
-                                               if (tokens.folded) {
+                                               if (cl.IsFolded) {
                                                        gr.MoveTo (rFld.Center.X + 0.5, rFld.Y + 2);
                                                        gr.LineTo (rFld.Center.X + 0.5, rFld.Bottom - 2);
                                                }
@@ -750,8 +564,93 @@ namespace Crow.Coding
                                }
                        }
 
-                       for (int t = 0; t < tokens.Count; t++) {
-                               string lstr = tokens [t].PrintableContent;
+                       gr.SetSourceColor (Foreground);
+                       x += leftMargin;
+
+                       if (cl.Tokens == null)
+                               drawRawCodeLine (gr, x, y, i, lineIndex);
+                       else
+                               drawParsedCodeLine (gr, x, y, i, lineIndex);
+               }
+//             void drawParsed(Context gr){
+//                     if (PrintedLines == null)
+//                             return;
+//
+//                     gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight);
+//                     gr.SetFontSize (Font.Size);
+//                     gr.FontOptions = Interface.FontRenderingOptions;
+//                     gr.Antialias = Interface.Antialias;
+//
+//                     Rectangle cb = ClientRectangle;
+//                     gr.Save ();
+//                     CairoHelpers.CairoRectangle (gr, cb, CornerRadius);
+//                     gr.Clip ();
+//
+//                     bool selectionInProgress = false;
+//
+//                     Foreground.SetAsSource (gr);
+//
+//                     #region draw text cursor
+//                     if (SelBegin != SelRelease)
+//                             selectionInProgress = true;
+//                     else if (HasFocus){
+//                             gr.LineWidth = 1.0;
+//                             double cursorX = + leftMargin + cb.X + (CurrentColumn - ScrollX) * fe.MaxXAdvance;
+//                             gr.MoveTo (0.5 + cursorX, cb.Y + printedCurrentLine * fe.Height);
+//                             gr.LineTo (0.5 + cursorX, cb.Y + (printedCurrentLine + 1) * fe.Height);
+//                             gr.Stroke();
+//                     }
+//                     #endregion
+//
+//                     for (int i = 0; i < PrintedLines.Count; i++)
+//                             drawTokenLine (gr, i, selectionInProgress, cb);
+//
+//                     gr.Restore ();
+//             }
+               void drawRawCodeLine(Context gr, double x, double y, int i, int lineIndex) {
+                       string lstr = buffer[lineIndex].PrintableContent;
+                       if (ScrollX < lstr.Length)
+                               lstr = lstr.Substring (ScrollX);
+                       else
+                               lstr = "";
+
+                       gr.MoveTo (x, y + fe.Ascent);
+                       gr.ShowText (lstr);
+                       gr.Fill ();
+
+                       if (!buffer.SelectionIsEmpty && lineIndex >= buffer.SelectionStart.Y && lineIndex <= buffer.SelectionEnd.Y) {
+                               double rLineX = x,
+                               rLineY = y,
+                               rLineW = lstr.Length * fe.MaxXAdvance;
+
+                               //System.Diagnostics.Debug.WriteLine ("sel start: " + buffer.SelectionStart + " sel end: " + buffer.SelectionEnd);
+                               if (lineIndex == buffer.SelectionStart.Y) {
+                                       rLineX += (selStartCol - ScrollX) * fe.MaxXAdvance;
+                                       rLineW -= selStartCol * fe.MaxXAdvance;
+                               }
+                               if (lineIndex == buffer.SelectionEnd.Y)
+                                       rLineW -= (lstr.Length - selEndCol) * fe.MaxXAdvance;
+
+                               gr.Save ();
+                               gr.Operator = Operator.Source;
+                               gr.Rectangle (rLineX, rLineY, rLineW, fe.Height);
+                               gr.SetSourceColor (SelectionBackground);
+                               gr.FillPreserve ();
+                               gr.Clip ();
+                               gr.Operator = Operator.Over;
+                               gr.SetSourceColor (SelectionForeground);
+                               gr.MoveTo (x, y + fe.Ascent);
+                               gr.ShowText (lstr);
+                               gr.Fill ();
+                               gr.Restore ();
+                       }
+               }
+               void drawParsedCodeLine (Context gr, double x, double y, int i, int lineIndex) {
+                       int lPtr = 0;
+                       CodeLine cl = PrintedLines[i];
+
+                       for (int t = 0; t < cl.Tokens.Count; t++) {
+                               string lstr = cl.Tokens [t].PrintableContent;
                                if (lPtr < ScrollX) {
                                        if (lPtr - ScrollX + lstr.Length <= 0) {
                                                lPtr += lstr.Length;
@@ -767,8 +666,8 @@ namespace Crow.Coding
                                FontSlant fts = FontSlant.Normal;
                                FontWeight ftw = FontWeight.Normal;
 
-                               if (formatting.ContainsKey ((int)tokens [t].Type)) {
-                                       TextFormatting tf = formatting [(int)tokens [t].Type];
+                               if (formatting.ContainsKey ((int)cl.Tokens [t].Type)) {
+                                       TextFormatting tf = formatting [(int)cl.Tokens [t].Type];
                                        bg = tf.Background;
                                        fg = tf.Foreground;
                                        if (tf.Bold)
@@ -780,26 +679,24 @@ namespace Crow.Coding
                                gr.SelectFontFace (Font.Name, fts, ftw);
                                gr.SetSourceColor (fg);
 
-                               int x = leftMargin + cb.X + (int)((lPtr - ScrollX) * fe.MaxXAdvance);
-
                                gr.MoveTo (x, y + fe.Ascent);
                                gr.ShowText (lstr);
                                gr.Fill ();
 
-                               if (selectionInProgress && lineIndex >= selectionStart.Y && lineIndex <= selectionEnd.Y &&
-                                       !(lineIndex == selectionStart.Y && lPtr + lstr.Length <= selectionStart.X) &&
-                                       !(lineIndex == selectionEnd.Y && selectionEnd.X <= lPtr)) {
+                               if (buffer.SelectionInProgress && lineIndex >= buffer.SelectionStart.Y && lineIndex <= buffer.SelectionEnd.Y &&
+                                       !(lineIndex == buffer.SelectionStart.Y && lPtr + lstr.Length <= selStartCol) &&
+                                       !(lineIndex == buffer.SelectionEnd.Y && selEndCol <= lPtr)) {
 
                                        double rLineX = x,
-                                       rLineY = cb.Y + i * fe.Height,
+                                       rLineY = y,
                                        rLineW = lstr.Length * fe.MaxXAdvance;
                                        double startAdjust = 0.0;
 
-                                       if ((lineIndex == selectionStart.Y) && (selectionStart.X < lPtr + lstr.Length) && (selectionStart.X > lPtr))
-                                               startAdjust = (selectionStart.X - lPtr) * fe.MaxXAdvance;
+                                       if ((lineIndex == buffer.SelectionStart.Y) && (selStartCol < lPtr + lstr.Length) && (selStartCol > lPtr))
+                                               startAdjust = (selStartCol - lPtr) * fe.MaxXAdvance;
                                        rLineX += startAdjust;
-                                       if ((lineIndex == selectionEnd.Y) && (selectionEnd.X < lPtr + lstr.Length))
-                                               rLineW = (selectionEnd.X - lPtr) * fe.MaxXAdvance;
+                                       if ((lineIndex == buffer.SelectionEnd.Y) && (selEndCol < lPtr + lstr.Length))
+                                               rLineW = (selEndCol - lPtr) * fe.MaxXAdvance;
                                        rLineW -= startAdjust;
 
                                        gr.Save ();
@@ -810,15 +707,16 @@ namespace Crow.Coding
                                        gr.Clip ();
                                        gr.Operator = Operator.Over;
                                        gr.SetSourceColor (selfg);
-                                       gr.MoveTo (x, cb.Y + fe.Ascent + fe.Height * i);
+                                       gr.MoveTo (x, y + fe.Ascent);
                                        gr.ShowText (lstr);
                                        gr.Fill ();
                                        gr.Restore ();
                                }
-
+                               x += (int)lstr.Length * fe.MaxXAdvance;
                                lPtr += lstr.Length;
                        }
                }
+
                #endregion
 
                #region GraphicObject overrides
@@ -856,46 +754,90 @@ namespace Crow.Coding
                                updateVisibleColumns ();
                }
 
+               int selStartCol;
+               int selEndCol;
+
                protected override void onDraw (Context gr)
                {
+//                     if (!System.Threading.Monitor.TryEnter (buffer.EditMutex)) {
+//                             RegisterForGraphicUpdate ();
+//                             return;
+//                     }
+
                        base.onDraw (gr);
 
-                       if (parser != null)
-                               drawParsed (gr);
-                       else
-                               draw(gr);
+                       gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight);
+                       gr.SetFontSize (Font.Size);
+                       gr.FontOptions = Interface.FontRenderingOptions;
+                       gr.Antialias = Interface.Antialias;
 
+                       Rectangle cb = ClientRectangle;
+
+                       Foreground.SetAsSource (gr);
+
+                       lock (buffer.EditMutex) {
+                               #region draw text cursor
+                               if (buffer.SelectionInProgress){
+                                       selStartCol = getTabulatedColumn (buffer.SelectionStart);
+                                       selEndCol = getTabulatedColumn (buffer.SelectionEnd);
+                               }else if (HasFocus){
+                                       gr.LineWidth = 1.0;
+                                       double cursorX = cb.X + (getTabulatedColumn(buffer.CurrentPosition) - ScrollX) * fe.MaxXAdvance + leftMargin;
+                                       gr.MoveTo (0.5 + cursorX, cb.Y + (printedCurrentLine) * fe.Height);
+                                       gr.LineTo (0.5 + cursorX, cb.Y + (printedCurrentLine + 1) * fe.Height);
+                                       gr.Stroke();
+                               }
+                               #endregion
+
+                               if (PrintedLines != null) {
+                                       for (int i = 0; i < visibleLines; i++) {
+                                               if (i + ScrollY >= buffer.UnfoldedLines)//TODO:need optimize
+                                                       break;
+                                               drawLine (gr, cb, i);
+                                       }
+                               }
+                       }
+                       //System.Threading.Monitor.Exit (buffer.EditMutex);
                }
                #endregion
 
                #region Mouse handling
                Point mouseLocalPos;
+               bool doubleClicked = false;
 
                void updateCurrentPos(){
-                       if (mouseLocalPos.X < 0)
-                               CurrentColumn--;
-                       else
-                               CurrentColumn = ScrollX +  (int)Math.Round ((mouseLocalPos.X - leftMargin) / fe.MaxXAdvance);
-
+//                     if (mouseLocalPos.X < 0)
+//                             CurrentColumn--;
+//                     else
                        PrintedCurrentLine = (int)Math.Max (0, Math.Floor (mouseLocalPos.Y / fe.Height));
+                       int curVisualCol = ScrollX +  (int)Math.Round ((mouseLocalPos.X - leftMargin) / fe.MaxXAdvance);
 
-                       if (mouseLocalPos.Y < 0)
-                               ScrollY--;
+                       int i = 0;
+                       int buffCol = 0;
+                       while (i < curVisualCol && buffCol < buffer.CurrentCodeLine.Length) {
+                               if (buffer.CurrentCodeLine[buffCol] == '\t')
+                                       i += Interface.TabSize;
+                               else
+                                       i++;
+                               buffCol++;
+                       }
+                       buffer.CurrentColumn = buffCol;
 
-                       CurrentPosition = buffer.TabulatedPosition; //for rounding if in middle of tabs
+//                     if (mouseLocalPos.Y < 0)
+//                             ScrollY--;
                }
                public override void onMouseEnter (object sender, MouseMoveEventArgs e)
                {
                        base.onMouseEnter (sender, e);
                        if (e.X - ScreenCoordinates(Slot).X < leftMargin + ClientRectangle.X)
-                               currentInterface.MouseCursor = XCursor.Default;
+                               CurrentInterface.MouseCursor = XCursor.Default;
                        else
-                               currentInterface.MouseCursor = XCursor.Text;
+                               CurrentInterface.MouseCursor = XCursor.Text;
                }
                public override void onMouseLeave (object sender, MouseMoveEventArgs e)
                {
                        base.onMouseLeave (sender, e);
-                       currentInterface.MouseCursor = XCursor.Default;
+                       CurrentInterface.MouseCursor = XCursor.Default;
                }
                public override void onMouseMove (object sender, MouseMoveEventArgs e)
                {
@@ -905,20 +847,18 @@ namespace Crow.Coding
 
                        if (!e.Mouse.IsButtonDown (MouseButton.Left)) {
                                if (mouseLocalPos.X < leftMargin)
-                                       currentInterface.MouseCursor = XCursor.Default;
+                                       CurrentInterface.MouseCursor = XCursor.Default;
                                else
-                                       currentInterface.MouseCursor = XCursor.Text;
+                                       CurrentInterface.MouseCursor = XCursor.Text;
                                return;
                        }
 
-                       if (!HasFocus || SelBegin < 0)
+                       if (!HasFocus || !buffer.SelectionInProgress)
                                return;
 
                        //mouse is down
-                       updateCurrentPos ();
-                       SelRelease = CurrentPosition;
-
-                       RegisterForRedraw();
+                       updateCurrentPos();
+                       buffer.SetSelEndPos ();
                }
                public override void onMouseDown (object sender, MouseButtonEventArgs e)
                {
@@ -934,36 +874,35 @@ namespace Crow.Coding
                        }
 
                        if (mouseLocalPos.X < leftMargin) {
-                               toogleFolding (parser.Tokens.IndexOf (PrintedLines[(int)Math.Max (0, Math.Floor (mouseLocalPos.Y / fe.Height))]));
-                       } else {
-                               updateCurrentPos ();
-                               SelBegin = SelRelease = CurrentPosition;
-                       }               
-                       RegisterForRedraw();
+                               toogleFolding (buffer.IndexOf (PrintedLines [(int)Math.Max (0, Math.Floor (mouseLocalPos.Y / fe.Height))]));
+                               return;
+                       }
+
+                       updateCurrentPos ();
+                       buffer.SetSelStartPos ();
                }
                public override void onMouseUp (object sender, MouseButtonEventArgs e)
                {
-                       Debug.WriteLine ("MouseUp");
                        base.onMouseUp (sender, e);
 
-                       if (SelBegin == SelRelease)
-                               SelBegin = SelRelease = -1;
-
-                       updateCurrentPos ();
-                       RegisterForRedraw ();
+                       if (buffer.SelectionIsEmpty)
+                               buffer.ResetSelection ();
                }
-               bool doubleClicked = false;
+
                public override void onMouseDoubleClick (object sender, MouseButtonEventArgs e)
                {
                        doubleClicked = true;
-                       Debug.WriteLine ("DoubleClick");
                        base.onMouseDoubleClick (sender, e);
 
-                       GotoWordStart ();
-                       SelBegin = CurrentPosition;
-                       GotoWordEnd ();
-                       SelRelease = CurrentPosition;
-                       RegisterForRedraw ();
+                       buffer.GotoWordStart ();
+                       buffer.SetSelStartPos ();
+                       buffer.GotoWordEnd ();
+                       buffer.SetSelEndPos ();
+               }
+
+               public override void onMouseWheel (object sender, MouseWheelEventArgs e)
+               {
+                       base.onMouseWheel (sender, e);
                }
                #endregion
 
@@ -977,119 +916,117 @@ namespace Crow.Coding
                        switch (key)
                        {
                        case Key.Back:
-                               if (CurrentPosition == 0)
-                                       return;
-                               this.DeleteChar();
+                               buffer.DeleteChar ();
                                break;
                        case Key.Clear:
                                break;
                        case Key.Delete:
-                               if (selectionIsEmpty) {
+                               if (buffer.SelectionIsEmpty)
                                        MoveRight ();
-                               }else if (e.Shift)
-                                       currentInterface.Clipboard = this.SelectedText;
-                               this.DeleteChar ();
+                               else if (e.Shift)
+                                       CurrentInterface.Clipboard = buffer.SelectedText;
+                               buffer.DeleteChar ();
                                break;
                        case Key.Enter:
                        case Key.KeypadEnter:
-                               if (!selectionIsEmpty)
-                                       this.DeleteChar ();
+                               if (!buffer.SelectionIsEmpty)
+                                       buffer.DeleteChar ();
                                buffer.InsertLineBreak ();
                                break;
                        case Key.Escape:
-                               SelRelease = SelBegin = -1;
+                               buffer.ResetSelection ();
                                break;
                        case Key.Home:
                                if (e.Shift) {
-                                       if (selectionIsEmpty)
-                                               SelBegin = new Point (CurrentColumn, CurrentLine);
+                                       if (buffer.SelectionIsEmpty)
+                                               buffer.SetSelStartPos ();
                                        if (e.Control)
-                                               CurrentLine = 0;
-                                       CurrentColumn = 0;
-                                       SelRelease = new Point (CurrentColumn, CurrentLine);
+                                               buffer.CurrentLine = 0;
+                                       buffer.CurrentColumn = 0;
+                                       buffer.SetSelEndPos ();
                                        break;
                                }
-                               SelRelease = SelBegin = -1;
+                               buffer.ResetSelection ();
                                if (e.Control)
-                                       CurrentLine = 0;
-                               CurrentColumn = 0;
+                                       buffer.CurrentLine = 0;
+                               buffer.CurrentColumn = 0;
                                break;
                        case Key.End:
                                if (e.Shift) {
-                                       if (selectionIsEmpty)
-                                               SelBegin = CurrentPosition;
+                                       if (buffer.SelectionIsEmpty)
+                                               buffer.SetSelStartPos ();
                                        if (e.Control)
-                                               CurrentLine = int.MaxValue;
-                                       CurrentColumn = int.MaxValue;
-                                       SelRelease = CurrentPosition;
+                                               buffer.CurrentLine = int.MaxValue;
+                                       buffer.CurrentColumn = int.MaxValue;
+                                       buffer.SetSelEndPos ();
                                        break;
                                }
-                               SelRelease = SelBegin = -1;
+                               buffer.ResetSelection ();
                                if (e.Control)
-                                       CurrentLine = int.MaxValue;
-                               CurrentColumn = int.MaxValue;
+                                       buffer.CurrentLine = int.MaxValue;
+                               buffer.CurrentColumn = int.MaxValue;
                                break;
                        case Key.Insert:
                                if (e.Shift)
-                                       this.Insert (currentInterface.Clipboard);
-                               else if (e.Control && !selectionIsEmpty)
-                                       currentInterface.Clipboard = this.SelectedText;
+                                       buffer.Insert (CurrentInterface.Clipboard);
+                               else if (e.Control && !buffer.SelectionIsEmpty)
+                                       CurrentInterface.Clipboard = buffer.SelectedText;
                                break;
                        case Key.Left:
                                if (e.Shift) {
-                                       if (selectionIsEmpty)
-                                               SelBegin = CurrentPosition;
+                                       if (buffer.SelectionIsEmpty)
+                                               buffer.SetSelStartPos ();
                                        if (e.Control)
-                                               GotoWordStart ();
+                                               buffer.GotoWordStart ();
                                        else
                                                MoveLeft ();
-                                       SelRelease = CurrentPosition;
+                                       buffer.SetSelEndPos ();
                                        break;
                                }
-                               SelRelease = SelBegin = -1;
+                               buffer.ResetSelection ();
                                if (e.Control)
-                                       GotoWordStart ();
+                                       buffer.GotoWordStart ();
                                else
                                        MoveLeft();
                                break;
                        case Key.Right:
                                if (e.Shift) {
-                                       if (selectionIsEmpty)
-                                               SelBegin = CurrentPosition;
+                                       if (buffer.SelectionIsEmpty)
+                                               buffer.SetSelStartPos ();
                                        if (e.Control)
-                                               GotoWordEnd ();
+                                               buffer.GotoWordEnd ();
                                        else
                                                MoveRight ();
-                                       SelRelease = CurrentPosition;
+                                       buffer.SetSelEndPos ();
                                        break;
                                }
-                               SelRelease = SelBegin = -1;
+                               buffer.ResetSelection ();
                                if (e.Control)
-                                       GotoWordEnd ();
+                                       buffer.GotoWordEnd ();
                                else
                                        MoveRight ();
                                break;
                        case Key.Up:
                                if (e.Shift) {
-                                       if (selectionIsEmpty)
-                                               SelBegin = CurrentPosition;
-                                       MoveUp ();
-                                       SelRelease = CurrentPosition;
+                                       if (buffer.SelectionIsEmpty)
+                                               buffer.SetSelStartPos ();
+                                       PrintedCurrentLine--;
+                                       buffer.SetSelEndPos ();
                                        break;
                                }
-                               SelRelease = SelBegin = -1;
-                               MoveUp ();
+                               buffer.ResetSelection ();
+                               PrintedCurrentLine--;
                                break;
                        case Key.Down:
                                if (e.Shift) {
-                                       if (selectionIsEmpty)
-                                               SelBegin = CurrentPosition;
-                                       MoveDown ();
-                                       SelRelease = CurrentPosition;
+                                       if (buffer.SelectionIsEmpty)
+                                               buffer.SetSelStartPos ();
+                                       PrintedCurrentLine++;
+                                       buffer.SetSelEndPos ();
                                        break;
                                }
-                               SelRelease = SelBegin = -1;
-                               MoveDown ();
+                               buffer.ResetSelection ();
+                               PrintedCurrentLine++;
                                break;
                        case Key.Menu:
                                break;
@@ -1097,32 +1034,33 @@ namespace Crow.Coding
                                break;
                        case Key.PageDown:
                                if (e.Shift) {
-                                       if (selectionIsEmpty)
-                                               SelBegin = CurrentPosition;
-                                       CurrentLine += visibleLines;
-                                       SelRelease = CurrentPosition;
+                                       if (buffer.SelectionIsEmpty)
+                                               buffer.SetSelStartPos ();
+                                       PrintedCurrentLine += visibleLines;
+                                       buffer.SetSelEndPos ();
                                        break;
                                }
-                               SelRelease = -1;
-                               CurrentLine += visibleLines;
+                               buffer.ResetSelection ();
+                               PrintedCurrentLine += visibleLines;
                                break;
                        case Key.PageUp:
                                if (e.Shift) {
-                                       if (selectionIsEmpty)
-                                               SelBegin = CurrentPosition;
-                                       CurrentLine -= visibleLines;
-                                       SelRelease = CurrentPosition;
+                                       if (buffer.SelectionIsEmpty)
+                                               buffer.SetSelStartPos ();
+                                       PrintedCurrentLine -= visibleLines;
+                                       buffer.SetSelEndPos ();
                                        break;
                                }
-                               CurrentLine -= visibleLines;
+                               buffer.ResetSelection ();
+                               PrintedCurrentLine -= visibleLines;
                                break;
                        case Key.RWin:
                                break;
                        case Key.Tab:
-                               this.Insert ("\t");
+                               buffer.Insert ("\t");
                                break;
                        case Key.F8:
-                               toogleFolding (CurrentLine);
+                               toogleFolding (buffer.CurrentLine);
 //                             if (parser != null)
 //                                     reparseSource ();
                                break;
@@ -1135,12 +1073,10 @@ namespace Crow.Coding
                {
                        base.onKeyPress (sender, e);
 
-                       this.Insert (e.KeyChar.ToString());
-
-                       SelRelease = -1;
-                       SelBegin = -1; //new Point(CurrentColumn, SelBegin.Y);
+                       buffer.Insert (e.KeyChar.ToString());
+                       buffer.ResetSelection ();
 
-                       RegisterForGraphicUpdate();
+                       //RegisterForGraphicUpdate();
                }
                #endregion
        }
diff --git a/src/TokenList.cs b/src/TokenList.cs
deleted file mode 100644 (file)
index f4d03c7..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-using System;
-using System.Collections.Generic;
-
-namespace Crow.Coding
-{
-       public class TokenList : List<Token>
-       {
-               /// <summary> The dirty state indicate that this line has changed and should be reparsed </summary>
-               public bool Dirty = true;
-               /// <summary>
-               /// The state of the parser when end of line was reached, used to setup initial state for next line parsing
-               /// </summary>
-               public int EndingState;
-               /// <summary>
-               /// Folding state reside here because it's the highest level of abstraction line per line
-               /// </summary>
-               public bool folded = false;
-               public Node SyntacticNode = null;
-               /// <summary>
-               /// if parsing issue error, exception is not null and tokenlist should contains only one token with line content and type = unknown
-               /// </summary>
-               public ParsingException exception = null;
-
-               public TokenList () : base ()
-               {
-                       EndingState = 0;
-               }
-               /// <summary>
-               /// Initializes an in  error source line
-               /// </summary>
-               public TokenList (ParsingException ex, string rawLineTxt){
-                       exception = ex;
-                       this.Add (new Token () { Content = rawLineTxt });
-               }
-
-               public int FirstNonBlankTokenIndex {
-                       get {
-                               for (int i = 0; i < this.Count; i++) {
-                                       if (this [i].Type != Parser.TokenType.WhiteSpace && this [i].Type != Parser.TokenType.Unknown)
-                                               return i;
-                               }
-                               return -1;
-                       }
-               }
-
-               //override list.clear to clear additional states of tokenList
-               public new void Clear() {
-                       EndingState = 0;
-                       SyntacticNode = null;
-                       exception = null;
-                       Dirty = true;
-                       base.Clear ();
-               }
-       }
-}
-
index dcb826a25e65e16cf3a54877037987d387d3d045..2a8ffeb10a96d29d7c958532d05518a63ae0014b 100644 (file)
@@ -14,7 +14,9 @@ namespace Crow.Coding
                        WhiteSpace = Parser.TokenType.WhiteSpace,
                        NewLine = Parser.TokenType.NewLine,
                        LineComment = Parser.TokenType.LineComment,
+                       BlockCommentStart = Parser.TokenType.BlockCommentStart,
                        BlockComment = Parser.TokenType.BlockComment,
+                       BlockCommentEnd = Parser.TokenType.BlockCommentEnd,
                        Affectation = Parser.TokenType.Affectation,
                        XMLDecl = Parser.TokenType.Preprocessor,
                        ElementStart,
@@ -83,32 +85,28 @@ namespace Crow.Coding
                public override void SetLineInError (ParsingException ex)
                {
                        base.SetLineInError (ex);
-                       Tokens[ex.Line].EndingState = (int)States.init;
+                       //buffer[ex.Line].Tokens.EndingState = (int)States.init;
                }
 
-               public override void Parse (int line)
+               public override void ParseCurrentLine ()
                {
-                       Debug.WriteLine (string.Format("parsing line:{0}", line));
-
-                       currentLine = line;
-                       currentColumn = 0;
-                       eof = false;
-                       bool eol = false;
-                       TokensLine = Tokens [line];
+                       Debug.WriteLine (string.Format("parsing line:{0}", currentLine));
+                       CodeLine cl = buffer [currentLine];
+                       cl.Tokens = new List<Token> ();
 
                        //retrieve current parser state from previous line
-                       if (line > 0)
-                               curState = (States)Tokens [line - 1].EndingState;
+                       if (currentLine > 0)
+                               curState = (States)buffer[currentLine - 1].EndingState;
                        else
                                curState = States.init;
 
-                       States previousEndingState = (States)TokensLine.EndingState;
-                       TokensLine.Clear ();
+                       States previousEndingState = (States)cl.EndingState;
+
 
-                       while (! (eof||eol)) {
+                       while (! eol) {
                                SkipWhiteSpaces ();
 
-                               if (eof)
+                               if (eol)
                                        break;
 
                                if (Peek () == '\n') {
@@ -247,11 +245,10 @@ namespace Crow.Coding
                                }
                        }
 
-                       TokensLine.EndingState = (int)curState;
-                       TokensLine.Dirty = false;
+                       if (cl.EndingState != (int)curState && currentLine < buffer.LineCount - 1)
+                               buffer [currentLine + 1].Tokens = null;
 
-                       if (previousEndingState != curState && line < Tokens.Count - 1)
-                               Tokens [line + 1].Dirty = true;
+                       cl.EndingState = (int)curState;
                }
 
                public override void SyntaxAnalysis ()
@@ -260,28 +257,31 @@ namespace Crow.Coding
 
                        Node currentNode = RootNode;
 
-                       for (int i = 0; i < Tokens.Count; i++) {
-                               TokenList curTL = Tokens [i];
-                               curTL.SyntacticNode = null;
+                       for (int i = 0; i < buffer.LineCount; i++) {
+                               CodeLine cl = buffer[i];
+                               if (cl.Tokens == null)
+                                       continue;
+                               cl.SyntacticNode = null;
 
                                int tokPtr = 0;
-                               while (tokPtr < curTL.Count) {
-                                       switch ((XMLParser.TokenType)curTL [tokPtr].Type) {
+                               while (tokPtr < cl.Tokens.Count) {
+                                       switch ((XMLParser.TokenType)cl.Tokens [tokPtr].Type) {
                                        case TokenType.ElementStart:
                                                tokPtr++;
-                                               Node newElt = new Node () { Name = curTL [tokPtr].Content, StartLine = i };
+                                               Node newElt = new Node () { Name = cl.Tokens [tokPtr].Content, StartLine = cl };
                                                currentNode.AddChild (newElt);
                                                currentNode = newElt;
-                                               if (curTL.SyntacticNode == null)
-                                                       curTL.SyntacticNode = newElt;
+                                               if (cl.SyntacticNode == null)
+                                                       cl.SyntacticNode = newElt;
                                                break;
                                        case TokenType.ElementEnd:
                                                tokPtr++;
-                                               if (tokPtr < curTL.Count) {
-                                                       if ((XMLParser.TokenType)curTL [tokPtr].Type == TokenType.ElementName && curTL [tokPtr].Content != currentNode.Name)
+                                               if (tokPtr < cl.Tokens.Count) {
+                                                       if ((XMLParser.TokenType)cl.Tokens [tokPtr].Type == TokenType.ElementName &&
+                                                               cl.Tokens [tokPtr].Content != currentNode.Name)
                                                                throw new ParsingException (this, "Closing tag mismatch");
                                                }
-                                               currentNode.EndLine = i;
+                                               currentNode.EndLine = cl;
                                                currentNode = currentNode.Parent;
                                                break;
                                        case TokenType.ElementClosing: