OSDN Git Service

More fun with script editor
authorLatif Khalifa <latifer@streamgrid.net>
Sat, 4 Jul 2009 00:51:39 +0000 (00:51 +0000)
committerLatif Khalifa <latifer@streamgrid.net>
Sat, 4 Jul 2009 00:51:39 +0000 (00:51 +0000)
git-svn-id: https://radegast.googlecode.com/svn/trunk@91 f7a694da-4d33-11de-9ad6-1127a62b9fcd

Radegast/Core/LSLKeywordParser.cs
Radegast/Core/Types/RRichTextBox.cs
Radegast/Core/Types/StringTokenizer.cs [new file with mode: 0644]
Radegast/GUI/Consoles/Assets/ScriptEditor.Designer.cs
Radegast/GUI/Consoles/Assets/ScriptEditor.cs
Radegast/GUI/Consoles/Inventory/InventoryConsole.cs
Radegast/Radegast.csproj

index 4da007c..8fb5ebd 100644 (file)
@@ -38,7 +38,7 @@ using OpenMetaverse;
 \r
 namespace Radegast\r
 {\r
-    struct LSLKeyWord\r
+    public struct LSLKeyWord\r
     {\r
         public string KeyWord;\r
         public string ToolTip;\r
@@ -50,7 +50,7 @@ namespace Radegast
         }\r
     }\r
 \r
-    class LSLKeywordParser\r
+    public class LSLKeywordParser\r
     {\r
         private static Dictionary<string, LSLKeyWord> keyWords;\r
         \r
index 11a1fac..2e6015a 100644 (file)
@@ -33,6 +33,9 @@ using System.Collections.Generic;
 using System.Linq;\r
 using System.Text;\r
 using System.Windows.Forms;\r
+using System.Drawing;\r
+using System.Runtime.InteropServices;\r
+using HWND = System.IntPtr;\r
 \r
 namespace Radegast\r
 {\r
@@ -42,11 +45,26 @@ namespace Radegast
 \r
         private const short WM_PAINT = 0x00f;\r
         private bool _Paint = true;\r
+        private bool monoRuntime;\r
+        private System.Threading.Timer ttTimer;\r
+        private ToolTip ttKeyWords = new ToolTip();\r
 \r
         public RRichTextBox()\r
             : base()\r
         {\r
             SetStyle(ControlStyles.SupportsTransparentBackColor, true);\r
+            \r
+            // Are we running mono?\r
+            if (null == Type.GetType("Mono.Runtime"))\r
+            {\r
+                monoRuntime = false;\r
+            }\r
+            else\r
+            {\r
+                monoRuntime = true;\r
+            }\r
+            \r
+            ttTimer = new System.Threading.Timer(ttTimerElapsed, null, System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);\r
         }\r
 \r
         protected override void WndProc(ref System.Windows.Forms.Message m)\r
@@ -77,15 +95,137 @@ namespace Radegast
         public virtual void BeginUpdate()\r
         {\r
             _Paint = false;\r
-            SuspendLayout();\r
+            if (!monoRuntime)\r
+                Win32.LockWindowUpdate(Handle);\r
         }\r
 \r
         public virtual void EndUpdate()\r
         {\r
-            ResumeLayout();\r
+            if (!monoRuntime)\r
+            {\r
+                Win32.LockWindowUpdate((IntPtr)0);\r
+                Invalidate();\r
+            }\r
             _Paint = true;\r
         }\r
 \r
+        #region Syntax highligting\r
+        private string rtfEscaped(string s)\r
+        {\r
+            return s.Replace(@"\", @"\\").Replace("{", @"\{").Replace("}", @"\}").Replace("\n", "\\par\n");\r
+        }\r
+\r
+        private List<Color> usedColors = new List<Color>();\r
+\r
+        private string colorTag(Color c, string s)\r
+        {\r
+            int index;\r
+\r
+            if (usedColors.Contains(c))\r
+            {\r
+                index = usedColors.IndexOf(c) + 1;\r
+            }\r
+            else\r
+            {\r
+                usedColors.Add(c);\r
+                index = usedColors.Count;\r
+            }\r
+\r
+            return "\\cf" + index + " " + rtfEscaped(s) + "\\cf1 ";\r
+        }\r
+\r
+        public Color CommentColor = Color.FromArgb(204, 76, 38);\r
+        public Color StringColor = Color.FromArgb(0, 51, 0);\r
+        public Dictionary<string, LSLKeyWord> KeyWords = LSLKeywordParser.KeyWords;\r
+\r
+        protected override void OnTextChanged(EventArgs e)\r
+        {\r
+            if (monoRuntime)\r
+            {\r
+                // base.OnTextChanged(e);\r
+                // return;\r
+            }\r
+\r
+            if (!_Paint) return;\r
+            \r
+            BeginUpdate();\r
+            Win32.POINT scrollStatus = GetScrollPos();\r
+            int selectionStart = SelectionStart;\r
+            int selectionLength = SelectionLength;\r
+\r
+            StringTokenizer tokenizer = new StringTokenizer(Text.Replace("\t", "    "));\r
+            Token token;\r
+            StringBuilder body = new StringBuilder();\r
+            usedColors.Clear();\r
+            usedColors.Add(ForeColor);\r
+\r
+            do\r
+            {\r
+                token = tokenizer.Next();\r
+\r
+                switch (token.Kind)\r
+                {\r
+                    case TokenKind.Word:\r
+                        if (KeyWords.ContainsKey(token.Value))\r
+                        {\r
+                            body.Append(colorTag(KeyWords[token.Value].Color, token.Value));\r
+                        }\r
+                        else\r
+                        {\r
+                            goto default;\r
+                        }\r
+                        break;\r
+\r
+                    case TokenKind.QuotedString:\r
+                        body.Append(colorTag(StringColor, token.Value));\r
+                        break;\r
+\r
+                    case TokenKind.Comment:\r
+                        body.Append(colorTag(CommentColor, token.Value));\r
+                        break;\r
+\r
+                    case TokenKind.EOL:\r
+                        body.Append("\\par\n\\cf1 ");\r
+                        break;\r
+\r
+                    default:\r
+                        body.Append(rtfEscaped(token.Value));\r
+                        break;\r
+                }\r
+\r
+            } while (token.Kind != TokenKind.EOF);\r
+\r
+            StringBuilder colorTable = new StringBuilder();\r
+            colorTable.Append(@"{\colortbl;");\r
+\r
+            foreach (Color color in usedColors)\r
+            {\r
+                colorTable.AppendFormat("\\red{0}\\green{1}\\blue{2};", color.R, color.G, color.B);\r
+            }\r
+\r
+            colorTable.Append("}");\r
+\r
+            // Construct final rtf\r
+            StringBuilder rtf = new StringBuilder();\r
+            rtf.AppendLine(@"{\rtf1\ansi\deff0{\fonttbl{\f0\fnil\fcharset0 Courier New;}}");\r
+            //rtf.Append(@"\viewkind4\uc1\pard\lang1033\f0\fs20 ");\r
+            //rtf.AppendLine(@"{\rtf1\ansi\ansicpg1252\deff0\deflang1033{\f0\fnil\fcharset0 Courier New;}}");\r
+            rtf.AppendLine(colorTable.ToString());\r
+            rtf.Append(@"\pard\f0\fs18 ");\r
+            rtf.Append(body);\r
+            rtf.AppendLine(@"\par}");\r
+\r
+            // System.Console.WriteLine(rtf);\r
+\r
+            // Restore scrollbars and cursor position\r
+            Rtf = rtf.ToString();\r
+            SelectionStart = selectionStart;\r
+            SelectionLength = selectionLength;\r
+            SetScrollPos(scrollStatus);\r
+            EndUpdate();\r
+        }\r
+        #endregion\r
+\r
         public struct CursorLocation\r
         {\r
             public CursorLocation(int Line, int Column)\r
@@ -151,5 +291,134 @@ namespace Radegast
                 Select(Offset + value.Column, 0);\r
             }\r
         }\r
+\r
+        #region ToolTips\r
+        private bool validWordChar(char c)\r
+        {\r
+            return\r
+                (c >= 'a' && c <= 'z') ||\r
+                (c >= 'A' && c <= 'Z') ||\r
+                (c >= '0' && c <= '9') ||\r
+                c == '_';\r
+        }\r
+\r
+        private void ttTimerElapsed(Object sender)\r
+        {\r
+            if (InvokeRequired)\r
+            {\r
+                BeginInvoke(new MethodInvoker(delegate() { ttTimerElapsed(sender); }));\r
+                return;\r
+            }\r
+\r
+            char trackedChar = GetCharFromPosition(trackedMousePos);\r
+\r
+            if (!validWordChar(trackedChar))\r
+            {\r
+                return;\r
+            }\r
+\r
+            string trackedString = Text;\r
+            int trackedPos = GetCharIndexFromPosition(trackedMousePos);\r
+            int starPos;\r
+            int endPos;\r
+\r
+            for (starPos = trackedPos; starPos >= 0 && validWordChar(trackedString[starPos]); starPos--) ;\r
+            for (endPos = trackedPos; endPos < trackedString.Length && validWordChar(trackedString[endPos]); endPos++) ;\r
+            string word = trackedString.Substring(starPos + 1, endPos - starPos - 1);\r
+\r
+            if (!KeyWords.ContainsKey(word) || KeyWords[word].ToolTip == string.Empty)\r
+            {\r
+                return;\r
+            }\r
+\r
+            ttKeyWords.Show(KeyWords[word].ToolTip, this, new Point(trackedMousePos.X, trackedMousePos.Y + 15), 120 * 1000);\r
+        }\r
+\r
+        private Point trackedMousePos = new Point(0, 0);\r
+\r
+        protected override void OnMouseMove(MouseEventArgs e)\r
+        {\r
+            Point currentMousePos = new Point(e.X, e.Y);\r
+\r
+            if (currentMousePos != trackedMousePos)\r
+            {\r
+                trackedMousePos = currentMousePos;\r
+                ttTimer.Change(500, System.Threading.Timeout.Infinite);\r
+                ttKeyWords.Hide(this);\r
+            }\r
+            base.OnMouseMove(e);\r
+        }\r
+        #endregion\r
+\r
+        #region Scrollbar positions functions\r
+        /// <summary>\r
+        /// Sends a win32 message to get the scrollbars' position.\r
+        /// </summary>\r
+        /// <returns>a POINT structre containing horizontal\r
+        ///       and vertical scrollbar position.</returns>\r
+        private unsafe Win32.POINT GetScrollPos()\r
+        {\r
+            Win32.POINT res = new Win32.POINT();\r
+            IntPtr ptr = new IntPtr(&res);\r
+            Win32.SendMessage(Handle, Win32.EM_GETSCROLLPOS, 0, ptr);\r
+            return res;\r
+\r
+        }\r
+\r
+        /// <summary>\r
+        /// Sends a win32 message to set scrollbars position.\r
+        /// </summary>\r
+        /// <param name="point">a POINT\r
+        ///        conatining H/Vscrollbar scrollpos.</param>\r
+        private unsafe void SetScrollPos(Win32.POINT point)\r
+        {\r
+            IntPtr ptr = new IntPtr(&point);\r
+            Win32.SendMessage(Handle, Win32.EM_SETSCROLLPOS, 0, ptr);\r
+\r
+        }\r
+\r
+        /// <summary>\r
+        /// Summary description for Win32.\r
+        /// </summary>\r
+        private class Win32\r
+        {\r
+            private Win32()\r
+            {\r
+            }\r
+\r
+            public const int WM_USER = 0x400;\r
+            public const int WM_PAINT = 0xF;\r
+            public const int WM_KEYDOWN = 0x100;\r
+            public const int WM_KEYUP = 0x101;\r
+            public const int WM_CHAR = 0x102;\r
+\r
+            public const int EM_GETSCROLLPOS = (WM_USER + 221);\r
+            public const int EM_SETSCROLLPOS = (WM_USER + 222);\r
+\r
+            public const int VK_CONTROL = 0x11;\r
+            public const int VK_UP = 0x26;\r
+            public const int VK_DOWN = 0x28;\r
+            public const int VK_NUMLOCK = 0x90;\r
+\r
+            public const short KS_ON = 0x01;\r
+            public const short KS_KEYDOWN = 0x80;\r
+\r
+            [StructLayout(LayoutKind.Sequential)]\r
+            public struct POINT\r
+            {\r
+                public int x;\r
+                public int y;\r
+            }\r
+\r
+            [DllImport("user32")]\r
+            public static extern int SendMessage(HWND hwnd, int wMsg, int wParam, IntPtr lParam);\r
+            [DllImport("user32")]\r
+            public static extern int PostMessage(HWND hwnd, int wMsg, int wParam, int lParam);\r
+            [DllImport("user32")]\r
+            public static extern short GetKeyState(int nVirtKey);\r
+            [DllImport("user32")]\r
+            public static extern int LockWindowUpdate(HWND hwnd);\r
+        }\r
+        #endregion\r
     }\r
 }
\ No newline at end of file
diff --git a/Radegast/Core/Types/StringTokenizer.cs b/Radegast/Core/Types/StringTokenizer.cs
new file mode 100644 (file)
index 0000000..8575819
--- /dev/null
@@ -0,0 +1,456 @@
+/********************************************************8\r
+ *     Author: Andrew Deren\r
+ *     Date: July, 2004\r
+ *     http://www.adersoftware.com\r
+ * \r
+ *     StringTokenizer class. You can use this class in any way you want\r
+ * as long as this header remains in this file.\r
+ * \r
+ **********************************************************/\r
+using System;\r
+using System.IO;\r
+using System.Text;\r
+\r
+namespace Radegast\r
+{\r
+    public enum TokenKind\r
+    {\r
+        Unknown,\r
+        Word,\r
+        Number,\r
+        QuotedString,\r
+        WhiteSpace,\r
+        Symbol,\r
+        Comment,\r
+        EOL,\r
+        EOF\r
+    }\r
+\r
+    public class Token\r
+    {\r
+        int line;\r
+        int column;\r
+        string value;\r
+        TokenKind kind;\r
+\r
+        public Token(TokenKind kind, string value, int line, int column)\r
+        {\r
+            this.kind = kind;\r
+            this.value = value;\r
+            this.line = line;\r
+            this.column = column;\r
+        }\r
+\r
+        public int Column\r
+        {\r
+            get { return this.column; }\r
+        }\r
+\r
+        public TokenKind Kind\r
+        {\r
+            get { return this.kind; }\r
+        }\r
+\r
+        public int Line\r
+        {\r
+            get { return this.line; }\r
+        }\r
+\r
+        public string Value\r
+        {\r
+            get { return this.value; }\r
+        }\r
+    }\r
+\r
+       /// <summary>\r
+       /// StringTokenizer tokenized string (or stream) into tokens.\r
+       /// </summary>\r
+       public class StringTokenizer\r
+       {\r
+               const char EOF = (char)0;\r
+\r
+               int line;\r
+               int column;\r
+               int pos;        // position within data\r
+\r
+               string data;\r
+\r
+               bool ignoreWhiteSpace;\r
+               char[] symbolChars;\r
+\r
+               int saveLine;\r
+               int saveCol;\r
+               int savePos;\r
+\r
+               public StringTokenizer(TextReader reader)\r
+               {\r
+                       if (reader == null)\r
+                               throw new ArgumentNullException("reader");\r
+\r
+                       data = reader.ReadToEnd();\r
+\r
+                       Reset();\r
+               }\r
+\r
+               public StringTokenizer(string data)\r
+               {\r
+                       if (data == null)\r
+                               throw new ArgumentNullException("data");\r
+\r
+                       this.data = data;\r
+\r
+                       Reset();\r
+               }\r
+\r
+               /// <summary>\r
+               /// gets or sets which characters are part of TokenKind.Symbol\r
+               /// </summary>\r
+               public char[] SymbolChars\r
+               {\r
+                       get { return this.symbolChars; }\r
+                       set { this.symbolChars = value; }\r
+               }\r
+\r
+               /// <summary>\r
+               /// if set to true, white space characters will be ignored,\r
+               /// but EOL and whitespace inside of string will still be tokenized\r
+               /// </summary>\r
+               public bool IgnoreWhiteSpace\r
+               {\r
+                       get { return this.ignoreWhiteSpace; }\r
+                       set { this.ignoreWhiteSpace = value; }\r
+               }\r
+\r
+               private void Reset()\r
+               {\r
+                       this.ignoreWhiteSpace = false;\r
+                       this.symbolChars = new char[]{'=', '+', '-', '/', ',', '.', '*', '~', '!', '@', '#', '$', '%', '^', '&', '(', ')', '{', '}', '[', ']', ':', ';', '<', '>', '?', '|', '\\'};\r
+\r
+                       line = 1;\r
+                       column = 1;\r
+                       pos = 0;\r
+               }\r
+\r
+               protected char LA(int count)\r
+               {\r
+                       if (pos + count >= data.Length)\r
+                               return EOF;\r
+                       else\r
+                               return data[pos+count];\r
+               }\r
+\r
+               protected char Consume()\r
+               {\r
+                       char ret = data[pos];\r
+                       pos++;\r
+                       column++;\r
+\r
+                       return ret;\r
+               }\r
+\r
+               protected Token CreateToken(TokenKind kind, string value)\r
+               {\r
+                       return new Token(kind, value, line, column);\r
+               }\r
+\r
+               protected Token CreateToken(TokenKind kind)\r
+               {\r
+                       string tokenData = data.Substring(savePos, pos-savePos);\r
+                       return new Token(kind, tokenData, saveLine, saveCol);\r
+               }\r
+\r
+               public Token Next()\r
+               {\r
+                       ReadToken:\r
+\r
+                       char ch = LA(0);\r
+                       switch (ch)\r
+                       {\r
+                               case EOF:\r
+                                       return CreateToken(TokenKind.EOF, string.Empty);\r
+\r
+                               case ' ':\r
+                               case '\t':\r
+                               {\r
+                                       if (this.ignoreWhiteSpace)\r
+                                       {\r
+                                               Consume();\r
+                                               goto ReadToken;\r
+                                       }\r
+                                       else\r
+                                               return ReadWhitespace();\r
+                               }\r
+                               case '0':\r
+                               case '1':\r
+                               case '2':\r
+                               case '3':\r
+                               case '4':\r
+                               case '5':\r
+                               case '6':\r
+                               case '7':\r
+                               case '8':\r
+                               case '9':\r
+                                       return ReadNumber();\r
+\r
+                               case '\r':\r
+                               {\r
+                                       StartRead();\r
+                                       Consume();\r
+                                       if (LA(0) == '\n')\r
+                                               Consume();      // on DOS/Windows we have \r\n for new line\r
+\r
+                                       line++;\r
+                                       column=1;\r
+\r
+                                       return CreateToken(TokenKind.EOL);\r
+                               }\r
+                               case '\n':\r
+                               {\r
+                                       StartRead();\r
+                                       Consume();\r
+                                       line++;\r
+                                       column=1;\r
+                                       \r
+                                       return CreateToken(TokenKind.EOL);\r
+                               }\r
+\r
+                               case '"':\r
+                               {\r
+                                       return ReadString();\r
+                               }\r
+\r
+                case '/':\r
+                {\r
+                    if (LA(1) == '/')\r
+                    {\r
+                        return ReadComment();\r
+                    }\r
+                    else if (LA(1) == '*')\r
+                    {\r
+                        return ReadStarComment();\r
+                    }\r
+                    else\r
+                    {\r
+                        StartRead();\r
+                        Consume();\r
+                        return CreateToken(TokenKind.Symbol);\r
+                    }\r
+                }\r
+\r
+                               default:\r
+                               {\r
+                                       if (Char.IsLetter(ch) || ch == '_')\r
+                                               return ReadWord();\r
+                                       else if (IsSymbol(ch))\r
+                                       {\r
+                                               StartRead();\r
+                                               Consume();\r
+                                               return CreateToken(TokenKind.Symbol);\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               StartRead();\r
+                                               Consume();\r
+                                               return CreateToken(TokenKind.Unknown);                                          \r
+                                       }\r
+                               }\r
+\r
+                       }\r
+               }\r
+\r
+               /// <summary>\r
+               /// save read point positions so that CreateToken can use those\r
+               /// </summary>\r
+               private void StartRead()\r
+               {\r
+                       saveLine = line;\r
+                       saveCol = column;\r
+                       savePos = pos;\r
+               }\r
+\r
+               /// <summary>\r
+               /// reads all whitespace characters (does not include newline)\r
+               /// </summary>\r
+               /// <returns></returns>\r
+               protected Token ReadWhitespace()\r
+               {\r
+                       StartRead();\r
+\r
+                       Consume(); // consume the looked-ahead whitespace char\r
+\r
+                       while (true)\r
+                       {\r
+                               char ch = LA(0);\r
+                               if (ch == '\t' || ch == ' ')\r
+                                       Consume();\r
+                               else\r
+                                       break;\r
+                       }\r
+\r
+                       return CreateToken(TokenKind.WhiteSpace);\r
+                       \r
+               }\r
+\r
+               /// <summary>\r
+               /// reads number. Number is: DIGIT+ ("." DIGIT*)?\r
+               /// </summary>\r
+               /// <returns></returns>\r
+               protected Token ReadNumber()\r
+               {\r
+                       StartRead();\r
+\r
+                       bool hadDot = false;\r
+\r
+                       Consume(); // read first digit\r
+\r
+                       while (true)\r
+                       {\r
+                               char ch = LA(0);\r
+                               if (Char.IsDigit(ch))\r
+                                       Consume();\r
+                               else if (ch == '.' && !hadDot)\r
+                               {\r
+                                       hadDot = true;\r
+                                       Consume();\r
+                               }\r
+                               else\r
+                                       break;\r
+                       }\r
+\r
+                       return CreateToken(TokenKind.Number);\r
+               }\r
+\r
+               /// <summary>\r
+               /// reads word. Word contains any alpha character or _\r
+               /// </summary>\r
+               protected Token ReadWord()\r
+               {\r
+                       StartRead();\r
+\r
+                       Consume(); // consume first character of the word\r
+\r
+                       while (true)\r
+                       {\r
+                               char ch = LA(0);\r
+                               if (Char.IsLetter(ch) || ch == '_')\r
+                                       Consume();\r
+                               else\r
+                                       break;\r
+                       }\r
+\r
+                       return CreateToken(TokenKind.Word);\r
+               }\r
+\r
+        /// <summary>\r
+        /// Reads he rest of line in // comment\r
+        /// </summary>\r
+        protected Token ReadComment()\r
+        {\r
+            StartRead();\r
+\r
+            Consume(); // consume first character of the comment\r
+\r
+            while (true)\r
+            {\r
+                char ch = LA(0);\r
+                if (ch != EOF && ch != '\n' && ch != '\r')\r
+                    Consume();\r
+                else\r
+                    break;\r
+            }\r
+\r
+            return CreateToken(TokenKind.Comment);\r
+        }\r
+\r
+        /// <summary>\r
+        /// Read c-style comments /* */\r
+        /// </summary>\r
+        protected Token ReadStarComment()\r
+        {\r
+            StartRead();\r
+\r
+            Consume(); // consume first character of the comment\r
+\r
+            while (true)\r
+            {\r
+                char ch = LA(0);\r
+                if (ch == EOF)\r
+                {\r
+                    break;\r
+                }\r
+                else if (ch == '*' && LA(1) == '/')\r
+                {\r
+                    Consume();\r
+                    Consume();\r
+                    break;\r
+                }\r
+                else\r
+                {\r
+                    Consume();\r
+                }\r
+            }\r
+\r
+            return CreateToken(TokenKind.Comment);\r
+        }\r
+\r
+               /// <summary>\r
+               /// reads all characters until next " is found.\r
+               /// If "" (2 quotes) are found, then they are consumed as\r
+               /// part of the string\r
+               /// </summary>\r
+               /// <returns></returns>\r
+               protected Token ReadString()\r
+               {\r
+                       StartRead();\r
+\r
+                       Consume(); // read "\r
+\r
+                       while (true)\r
+                       {\r
+                               char ch = LA(0);\r
+                               if (ch == EOF)\r
+                                       break;\r
+                               else if (ch == '\r')    // handle CR in strings\r
+                               {\r
+                                       Consume();\r
+                                       if (LA(0) == '\n')      // for DOS & windows\r
+                                               Consume();\r
+\r
+                                       line++;\r
+                                       column = 1;\r
+                               }\r
+                               else if (ch == '\n')    // new line in quoted string\r
+                               {\r
+                                       Consume();\r
+\r
+                                       line++;\r
+                                       column = 1;\r
+                               }\r
+                               else if (ch == '"')\r
+                               {\r
+                                       Consume();\r
+                                       if (LA(0) != '"')\r
+                                               break;  // done reading, and this quotes does not have escape character\r
+                                       else\r
+                                               Consume(); // consume second ", because first was just an escape\r
+                               }\r
+                               else\r
+                                       Consume();\r
+                       }\r
+\r
+                       return CreateToken(TokenKind.QuotedString);\r
+               }\r
+\r
+               /// <summary>\r
+               /// checks whether c is a symbol character.\r
+               /// </summary>\r
+               protected bool IsSymbol(char c)\r
+               {\r
+                       for (int i=0; i<symbolChars.Length; i++)\r
+                               if (symbolChars[i] == c)\r
+                                       return true;\r
+\r
+                       return false;\r
+               }\r
+       }\r
+}\r
index ca5c87f..8268472 100644 (file)
@@ -66,14 +66,15 @@ namespace Radegast
             this.tbtbLoadFromDisk = new System.Windows.Forms.ToolStripMenuItem();\r
             this.tbtbSave = new System.Windows.Forms.ToolStripMenuItem();\r
             this.tbtbSaveToDisk = new System.Windows.Forms.ToolStripMenuItem();\r
+            this.tbtbSaveToDiskAs = new System.Windows.Forms.ToolStripMenuItem();\r
             this.tSeparator1 = new System.Windows.Forms.ToolStripSeparator();\r
             this.tbtnExit = new System.Windows.Forms.ToolStripMenuItem();\r
             this.tbtnAttach = new System.Windows.Forms.ToolStripButton();\r
             this.strpStatus = new System.Windows.Forms.ToolStrip();\r
             this.lblScripStatus = new System.Windows.Forms.ToolStripLabel();\r
-            this.lblLine = new System.Windows.Forms.ToolStripLabel();\r
             this.lblCol = new System.Windows.Forms.ToolStripLabel();\r
             this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();\r
+            this.lblLine = new System.Windows.Forms.ToolStripLabel();\r
             this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator();\r
             this.rtbCode = new Radegast.RRichTextBox();\r
             this.strpMenu.SuspendLayout();\r
@@ -98,6 +99,7 @@ namespace Radegast
             this.tbtbLoadFromDisk,\r
             this.tbtbSave,\r
             this.tbtbSaveToDisk,\r
+            this.tbtbSaveToDiskAs,\r
             this.tSeparator1,\r
             this.tbtnExit});\r
             this.tbtbFile.Image = ((System.Drawing.Image)(resources.GetObject("tbtbFile.Image")));\r
@@ -109,7 +111,7 @@ namespace Radegast
             // tbtbLoadFromDisk\r
             // \r
             this.tbtbLoadFromDisk.Name = "tbtbLoadFromDisk";\r
-            this.tbtbLoadFromDisk.Size = new System.Drawing.Size(165, 22);\r
+            this.tbtbLoadFromDisk.Size = new System.Drawing.Size(168, 22);\r
             this.tbtbLoadFromDisk.Text = "Open...";\r
             this.tbtbLoadFromDisk.Click += new System.EventHandler(this.tbtbLoadFromDisk_Click);\r
             // \r
@@ -117,26 +119,33 @@ namespace Radegast
             // \r
             this.tbtbSave.Enabled = false;\r
             this.tbtbSave.Name = "tbtbSave";\r
-            this.tbtbSave.Size = new System.Drawing.Size(165, 22);\r
-            this.tbtbSave.Text = "Save to inventory";\r
+            this.tbtbSave.Size = new System.Drawing.Size(168, 22);\r
+            this.tbtbSave.Text = "Save To Inventory";\r
             // \r
             // tbtbSaveToDisk\r
             // \r
             this.tbtbSaveToDisk.Name = "tbtbSaveToDisk";\r
-            this.tbtbSaveToDisk.Size = new System.Drawing.Size(165, 22);\r
-            this.tbtbSaveToDisk.Text = "Save to disk...";\r
-            this.tbtbSaveToDisk.Click += new System.EventHandler(this.tbtbSaveToDisk_Click);\r
+            this.tbtbSaveToDisk.Size = new System.Drawing.Size(168, 22);\r
+            this.tbtbSaveToDisk.Text = "Save To Disk";\r
+            this.tbtbSaveToDisk.Click += new System.EventHandler(this.tbtbSaveToDisk_Click_1);\r
+            // \r
+            // tbtbSaveToDiskAs\r
+            // \r
+            this.tbtbSaveToDiskAs.Name = "tbtbSaveToDiskAs";\r
+            this.tbtbSaveToDiskAs.Size = new System.Drawing.Size(168, 22);\r
+            this.tbtbSaveToDiskAs.Text = "Save To Disk As...";\r
+            this.tbtbSaveToDiskAs.Click += new System.EventHandler(this.tbtbSaveToDisk_Click);\r
             // \r
             // tSeparator1\r
             // \r
             this.tSeparator1.Name = "tSeparator1";\r
-            this.tSeparator1.Size = new System.Drawing.Size(162, 6);\r
+            this.tSeparator1.Size = new System.Drawing.Size(165, 6);\r
             this.tSeparator1.Visible = false;\r
             // \r
             // tbtnExit\r
             // \r
             this.tbtnExit.Name = "tbtnExit";\r
-            this.tbtnExit.Size = new System.Drawing.Size(165, 22);\r
+            this.tbtnExit.Size = new System.Drawing.Size(168, 22);\r
             this.tbtnExit.Text = "Close";\r
             this.tbtnExit.Visible = false;\r
             this.tbtnExit.Click += new System.EventHandler(this.tbtnExit_Click);\r
@@ -172,16 +181,6 @@ namespace Radegast
             this.lblScripStatus.Size = new System.Drawing.Size(59, 22);\r
             this.lblScripStatus.Text = "Loading...";\r
             // \r
-            // lblLine\r
-            // \r
-            this.lblLine.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right;\r
-            this.lblLine.AutoSize = false;\r
-            this.lblLine.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;\r
-            this.lblLine.Name = "lblLine";\r
-            this.lblLine.Size = new System.Drawing.Size(55, 22);\r
-            this.lblLine.Text = "Ln 1";\r
-            this.lblLine.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;\r
-            // \r
             // lblCol\r
             // \r
             this.lblCol.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right;\r
@@ -198,6 +197,16 @@ namespace Radegast
             this.toolStripSeparator1.Name = "toolStripSeparator1";\r
             this.toolStripSeparator1.Size = new System.Drawing.Size(6, 25);\r
             // \r
+            // lblLine\r
+            // \r
+            this.lblLine.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right;\r
+            this.lblLine.AutoSize = false;\r
+            this.lblLine.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;\r
+            this.lblLine.Name = "lblLine";\r
+            this.lblLine.Size = new System.Drawing.Size(55, 22);\r
+            this.lblLine.Text = "Ln 1";\r
+            this.lblLine.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;\r
+            // \r
             // toolStripSeparator2\r
             // \r
             this.toolStripSeparator2.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right;\r
@@ -206,9 +215,9 @@ namespace Radegast
             // \r
             // rtbCode\r
             // \r
-            this.rtbCode.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(250)))), ((int)(((byte)(255)))), ((int)(((byte)(250)))));\r
+            this.rtbCode.BackColor = System.Drawing.Color.WhiteSmoke;\r
             this.rtbCode.Dock = System.Windows.Forms.DockStyle.Fill;\r
-            this.rtbCode.Font = new System.Drawing.Font("Courier New", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));\r
+            this.rtbCode.Font = new System.Drawing.Font("Courier New", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));\r
             this.rtbCode.HideSelection = false;\r
             this.rtbCode.Location = new System.Drawing.Point(0, 25);\r
             this.rtbCode.Name = "rtbCode";\r
@@ -216,9 +225,9 @@ namespace Radegast
             this.rtbCode.TabIndex = 1;\r
             this.rtbCode.Text = "";\r
             this.rtbCode.WordWrap = false;\r
+            this.rtbCode.KeyDown += new System.Windows.Forms.KeyEventHandler(this.rtbCode_KeyDown);\r
             this.rtbCode.SelectionChanged += new System.EventHandler(this.rtbCode_SelectionChanged);\r
-            this.rtbCode.MouseMove += new System.Windows.Forms.MouseEventHandler(this.rtbCode_MouseMove);\r
-            this.rtbCode.TextChanged += new System.EventHandler(this.rtbCode_TextChanged);\r
+            this.rtbCode.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.rtbCode_KeyPress);\r
             // \r
             // ScriptEditor\r
             // \r
@@ -245,7 +254,7 @@ namespace Radegast
         private System.Windows.Forms.ToolStrip strpMenu;\r
         private System.Windows.Forms.ToolStripDropDownButton tbtbFile;\r
         private System.Windows.Forms.ToolStripMenuItem tbtbSave;\r
-        private System.Windows.Forms.ToolStripMenuItem tbtbSaveToDisk;\r
+        private System.Windows.Forms.ToolStripMenuItem tbtbSaveToDiskAs;\r
         private System.Windows.Forms.ToolStripMenuItem tbtbLoadFromDisk;\r
         private System.Windows.Forms.ToolStripButton tbtnAttach;\r
         private System.Windows.Forms.ToolStripSeparator tSeparator1;\r
@@ -256,5 +265,6 @@ namespace Radegast
         private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;\r
         private System.Windows.Forms.ToolStripLabel lblLine;\r
         private System.Windows.Forms.ToolStripSeparator toolStripSeparator2;\r
+        private System.Windows.Forms.ToolStripMenuItem tbtbSaveToDisk;\r
     }\r
 }\r
index c1dc191..3110ea2 100644 (file)
@@ -45,14 +45,11 @@ namespace Radegast
     {\r
         private RadegastInstance instance;\r
         private GridClient client { get { return instance.Client; } }\r
-        private Dictionary<string, LSLKeyWord> keywords = LSLKeywordParser.KeyWords;\r
         private InventoryLSL script;\r
         private UUID requestID;\r
         private bool populating = true;\r
-        private List<WordAndPosition> lineBuffer = new List<WordAndPosition>();\r
-        private Color commentColor = Color.FromArgb(204, 76, 38);\r
         private string scriptName;\r
-        private System.Threading.Timer ttTimer;\r
+        private string fileName;\r
         \r
         public ScriptEditor(RadegastInstance instance)\r
             : this(instance, null)\r
@@ -68,8 +65,8 @@ namespace Radegast
             this.instance = instance;\r
             this.script = script;\r
             lblScripStatus.Text = string.Empty;\r
-            ttTimer = new System.Threading.Timer(ttTimerElapsed, null, System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);\r
-\r
+            Dock = DockStyle.Fill;\r
+            this.TabStop = false;\r
             // Callbacks\r
             client.Assets.OnAssetReceived += new AssetManager.AssetReceivedCallback(Assets_OnAssetReceived);\r
 \r
@@ -104,197 +101,17 @@ namespace Radegast
             }\r
 \r
             asset.Decode();\r
-            rtbCode.BeginUpdate();\r
             rtbCode.Text = ((AssetScriptText)asset).Source;\r
-            MakeColorSyntaxForAllText();\r
-            rtbCode.EndUpdate();\r
-            lblScripStatus.Text = scriptName;\r
-        }\r
-\r
-        #region Syntax highlighting\r
-        struct WordAndPosition\r
-        {\r
-            public string Word;\r
-            public int Position;\r
-            public int Length;\r
-            public override string ToString()\r
-            {\r
-                string s = "Word = " + Word + ", Position = " + Position + ", Length = " + Length + "\n";\r
-                return s;\r
-            }\r
-        };\r
-\r
-        private int ParseLine(string s)\r
-        {\r
-            lineBuffer.Clear();\r
-            Regex r = new Regex(@"\w+|[^A-Za-z0-9_ \f\t\v]", RegexOptions.IgnoreCase | RegexOptions.Compiled);\r
-            Match m;\r
-\r
-            for (m = r.Match(s); m.Success; m = m.NextMatch())\r
-            {\r
-                WordAndPosition w = new WordAndPosition();\r
-                w.Word = m.Value;\r
-                w.Position = m.Index;\r
-                w.Length = m.Length;\r
-                lineBuffer.Add(w);\r
-            }\r
-\r
-            return lineBuffer.Count();\r
-        }\r
-\r
-        private Color Lookup(string s)\r
-        {\r
-            if (keywords.ContainsKey(s))\r
-            {\r
-                return keywords[s].Color;\r
-            }\r
-            else\r
-            {\r
-                return Color.Black;\r
-            }\r
-        }\r
-\r
-        private bool TestComment(string s)\r
-        {\r
-            string testString = s.Trim();\r
-            if ((testString.Length >= 2) &&\r
-                 (testString[0] == '/') &&\r
-                 (testString[1] == '/')\r
-                )\r
-                return true;\r
-\r
-            return false;\r
-        }\r
-\r
-        private void MakeColorSyntaxForCurrentLine()\r
-        {\r
-            int CurrentSelectionStart = rtbCode.SelectionStart;\r
-            int CurrentSelectionLength = rtbCode.SelectionLength;\r
-\r
-            // find start of line\r
-            int pos = CurrentSelectionStart;\r
-            while ((pos > 0) && (rtbCode.Text[pos - 1] != '\n'))\r
-                pos--;\r
-\r
-            int pos2 = CurrentSelectionStart;\r
-            while ((pos2 < rtbCode.Text.Length) &&\r
-                    (rtbCode.Text[pos2] != '\n'))\r
-                pos2++;\r
-\r
-            string s = rtbCode.Text.Substring(pos, pos2 - pos);\r
-            if (TestComment(s) == true)\r
-            {\r
-                rtbCode.Select(pos, pos2 - pos);\r
-                rtbCode.SelectionColor = commentColor;\r
-            }\r
-            else\r
-            {\r
-                string previousWord = "";\r
-                int count = ParseLine(s);\r
-                for (int i = 0; i < count; i++)\r
-                {\r
-                    WordAndPosition wp = lineBuffer[i];\r
-\r
-                    // check for comment\r
-                    if (wp.Word == "/" && previousWord == "/")\r
-                    {\r
-                        // color until end of line\r
-                        int posCommentStart = wp.Position - 1;\r
-                        int posCommentEnd = pos2;\r
-                        while (wp.Word != "\n" && i < count)\r
-                        {\r
-                            wp = lineBuffer[i];\r
-                            i++;\r
-                        }\r
-\r
-                        i--;\r
-\r
-                        posCommentEnd = pos2;\r
-                        rtbCode.Select(posCommentStart + pos, posCommentEnd - (posCommentStart + pos));\r
-                        rtbCode.SelectionColor = this.commentColor;\r
-\r
-                    }\r
-                    else\r
-                    {\r
-\r
-                        Color c = Lookup(wp.Word);\r
-                        rtbCode.Select(wp.Position + pos, wp.Length);\r
-                        rtbCode.SelectionColor = c;\r
-                    }\r
-\r
-                    previousWord = wp.Word;\r
-\r
-                }\r
-            }\r
-\r
-            if (CurrentSelectionStart >= 0)\r
-                rtbCode.Select(CurrentSelectionStart, CurrentSelectionLength);\r
-        }\r
-\r
-        private void MakeColorSyntaxForAllText()\r
-        {\r
-            populating = true;\r
-\r
-            string s = rtbCode.Text;\r
-            int CurrentSelectionStart = rtbCode.SelectionStart;\r
-            int CurrentSelectionLength = rtbCode.SelectionLength;\r
-\r
-            int count = ParseLine(s);\r
-            string previousWord = "";\r
-            for (int i = 0; i < count; i++)\r
-            {\r
-                WordAndPosition wp = lineBuffer[i];\r
-\r
-                // check for comment\r
-                if (wp.Word == "/" && previousWord == "/")\r
-                {\r
-                    // color until end of line\r
-                    int posCommentStart = wp.Position - 1;\r
-                    int posCommentEnd = i;\r
-                    while (wp.Word != "\n" && i < count)\r
-                    {\r
-                        wp = lineBuffer[i];\r
-                        i++;\r
-                    }\r
-\r
-                    i--;\r
-\r
-                    posCommentEnd = wp.Position;\r
-                    rtbCode.Select(posCommentStart, posCommentEnd - posCommentStart);\r
-                    rtbCode.SelectionColor = this.commentColor;\r
-\r
-                }\r
-                else\r
-                {\r
-\r
-                    Color c = Lookup(wp.Word);\r
-                    rtbCode.Select(wp.Position, wp.Length);\r
-                    rtbCode.SelectionColor = c;\r
-                }\r
-\r
-                previousWord = wp.Word;\r
-\r
-                //                             Console.WriteLine(wp.ToString());\r
-            }\r
-\r
-            if (CurrentSelectionStart >= 0)\r
-                rtbCode.Select(CurrentSelectionStart, CurrentSelectionLength);\r
-\r
-            populating = false;\r
-\r
+            SetTitle();\r
         }\r
 \r
-        private void rtbCode_TextChanged(object sender, EventArgs e)\r
+        private void SetTitle()\r
         {\r
-            if (populating)\r
+            if (detached)\r
             {\r
-                return;\r
+                FindForm().Text = scriptName + " - " + Properties.Resources.ProgramName + " script editor";\r
             }\r
-            rtbCode.BeginUpdate();\r
-            MakeColorSyntaxForCurrentLine();\r
-            rtbCode.EndUpdate();\r
         }\r
-        #endregion\r
 \r
         #region Detach/Attach\r
         private Control originalParent;\r
@@ -343,7 +160,8 @@ namespace Radegast
             originalParent = Parent;\r
             Parent = detachedForm;\r
             detachedForm.ClientSize = new Size(873, 580);\r
-            detachedForm.Text = scriptName + " - " + Properties.Resources.ProgramName + " script editor"; \r
+            SetTitle();\r
+            detachedForm.ActiveControl = this;\r
             detachedForm.Show();\r
             detachedForm.FormClosing += new FormClosingEventHandler(detachedForm_FormClosing);\r
 \r
@@ -422,74 +240,32 @@ namespace Radegast
         }\r
         #endregion\r
 \r
-        #region ToolTips\r
-        private bool validWordChar(char c)\r
\r
+        #region File I/O\r
+        private void tbtbSaveToDisk_Click_1(object sender, EventArgs e)\r
         {\r
-            return\r
-                (c >= 'a' && c <= 'z') ||\r
-                (c >= 'A' && c <= 'Z') ||\r
-                (c >= '0' && c <= '9') ||\r
-                c == '_';\r
-        }\r
-\r
-        private void ttTimerElapsed(Object sender)\r
-        {\r
-            if (InvokeRequired)\r
-            {\r
-                BeginInvoke(new MethodInvoker(delegate() { ttTimerElapsed(sender); }));\r
-                return;\r
-            }\r
-\r
-            char trackedChar = rtbCode.GetCharFromPosition(trackedMousePos);\r
-            \r
-            if (!validWordChar(trackedChar))\r
-            {\r
-                return;\r
-            }\r
-\r
-            string trackedString = rtbCode.Text;\r
-            int trackedPos = rtbCode.GetCharIndexFromPosition(trackedMousePos);\r
-            int starPos;\r
-            int endPos;\r
-\r
-            for (starPos = trackedPos; starPos >= 0 && validWordChar(trackedString[starPos]); starPos--) ;\r
-            for (endPos = trackedPos; endPos < trackedString.Length && validWordChar(trackedString[endPos]); endPos++) ;\r
-            string word = trackedString.Substring(starPos + 1, endPos - starPos - 1);\r
-\r
-            if (!keywords.ContainsKey(word) || keywords[word].ToolTip == string.Empty)\r
+            if (string.IsNullOrEmpty(fileName))\r
             {\r
+                tbtbSaveToDisk_Click(sender, e);\r
                 return;\r
             }\r
-\r
-            ttKeyWords.Show(keywords[word].ToolTip, rtbCode, new Point(trackedMousePos.X, trackedMousePos.Y + 15), 120 * 1000);\r
+            File.WriteAllText(fileName, rtbCode.Text);\r
         }\r
 \r
-        private Point trackedMousePos = new Point(0, 0);\r
-\r
-        private void rtbCode_MouseMove(object sender, MouseEventArgs e)\r
-        {\r
-            Point currentMousePos = new Point(e.X, e.Y);\r
-\r
-            if (currentMousePos != trackedMousePos)\r
-            {\r
-                trackedMousePos = currentMousePos;\r
-                ttTimer.Change(500, System.Threading.Timeout.Infinite);\r
-                ttKeyWords.Hide(rtbCode);\r
-            }\r
-        }\r
-        #endregion\r
-\r
         private void tbtbSaveToDisk_Click(object sender, EventArgs e)\r
         {\r
             SaveFileDialog dlg = new SaveFileDialog();\r
             dlg.Title = "Save script";\r
-            dlg.Filter = "LSL script file (*.lsl)|*.lsl";\r
+            dlg.Filter = "LSL script file (*.lsl)|*.lsl|Plain text file (*.txt)|*.txt";\r
             dlg.FileName = RadegastMisc.SafeFileName(scriptName);\r
             DialogResult res = dlg.ShowDialog();\r
 \r
             if (res == DialogResult.OK)\r
             {\r
-                File.WriteAllText(dlg.FileName, rtbCode.Text);\r
+                fileName = dlg.FileName;\r
+                scriptName = Path.GetFileName(fileName);\r
+                SetTitle();\r
+                File.WriteAllText(fileName, rtbCode.Text);\r
             }\r
 \r
         }\r
@@ -498,19 +274,19 @@ namespace Radegast
         {\r
             OpenFileDialog dlg = new OpenFileDialog();\r
             dlg.Title = "Open script";\r
-            dlg.Filter = "LSL script file (*.lsl)|*.lsl";\r
+            dlg.Filter = "LSL script files (*.lsl)|*.lsl|Plain text files (*.txt)|*.txt|All files (*.*)|*.*";\r
             dlg.Multiselect = false;\r
             DialogResult res = dlg.ShowDialog();\r
 \r
             if (res == DialogResult.OK)\r
             {\r
-                scriptName = dlg.FileName;\r
-                rtbCode.Text = File.ReadAllText(dlg.FileName);\r
-                rtbCode.BeginUpdate();\r
-                MakeColorSyntaxForAllText();\r
-                rtbCode.EndUpdate();\r
+                fileName = dlg.FileName;\r
+                scriptName = Path.GetFileName(fileName);\r
+                SetTitle();\r
+                rtbCode.Text = File.ReadAllText(fileName);\r
             }\r
         }\r
+        #endregion\r
 \r
         private void tbtnExit_Click(object sender, EventArgs e)\r
         {\r
@@ -523,5 +299,84 @@ namespace Radegast
             lblLine.Text = string.Format("Ln {0}", c.Line + 1);\r
             lblCol.Text = string.Format("Col {0}", c.Column + 1);\r
         }\r
+\r
+        private bool spaceOrTab(char c)\r
+        {\r
+            return c == ' ' || c == '\t';\r
+        }\r
+\r
+        private int lastPos(string s, char c)\r
+        {\r
+            s = s.TrimEnd();\r
+            \r
+            if (s == string.Empty)\r
+                return -1;\r
+\r
+            if (s[s.Length - 1] == c)\r
+            {\r
+                return s.LastIndexOf(c);\r
+            }\r
+            return -1;\r
+        }\r
+\r
+        private void rtbCode_KeyDown(object sender, KeyEventArgs e)\r
+        {\r
+            if (e.KeyCode == Keys.Tab)\r
+            {\r
+                rtbCode.SelectedText = "    ";\r
+                e.Handled = true;\r
+            }\r
+            else if (e.KeyCode == Keys.Enter)\r
+            {\r
+                if (rtbCode.Lines.Length > 0)\r
+                {\r
+                    RRichTextBox.CursorLocation cl = rtbCode.CursorPosition;\r
+                    string prevLine = rtbCode.Lines[cl.Line];\r
+                    string addIndent = "\n";\r
+                    int pos;\r
+\r
+                    for (int spaces = 0;\r
+                        spaces < prevLine.Length && spaceOrTab(prevLine[spaces]);\r
+                        addIndent += prevLine[spaces++]) ;\r
+\r
+                    if ((pos = lastPos(prevLine.Substring(0, cl.Column), '{')) != -1)\r
+                    {\r
+                        addIndent += "    ";\r
+                    }\r
+\r
+                    rtbCode.SelectedText = addIndent;\r
+                    int eat = 0;\r
+                    for (eat = 0; (eat + rtbCode.SelectionStart) < rtbCode.Text.Length && rtbCode.Text[rtbCode.SelectionStart + eat] == ' '; eat++) ;\r
+                    rtbCode.SelectionLength = eat;\r
+                    rtbCode.SelectedText = "";\r
+                    e.Handled = true;\r
+                }\r
+            }\r
+        }\r
+\r
+        private void rtbCode_KeyPress(object sender, KeyPressEventArgs e)\r
+        {\r
+            if (e.KeyChar == '}' && rtbCode.Lines.Length > 0)\r
+            {\r
+                string li = rtbCode.Lines[rtbCode.GetLineFromCharIndex(rtbCode.SelectionStart)];\r
+\r
+                if (li.Trim() == "")\r
+                {\r
+                    rtbCode.BeginUpdate();\r
+                    int toDelete = li.Length;\r
+\r
+                    if (toDelete > 4)\r
+                    {\r
+                        toDelete = 4;\r
+                    }\r
+\r
+                    rtbCode.SelectionStart -= toDelete;\r
+                    rtbCode.SelectionLength = toDelete;\r
+                    rtbCode.SelectedText = "}";\r
+                    rtbCode.EndUpdate();\r
+                    e.Handled = true;\r
+                }\r
+            }\r
+        }\r
     }\r
 }\r
index bffed46..366e46c 100644 (file)
@@ -842,7 +842,7 @@ namespace Radegast
                     }\r
 \r
 \r
-                    //if (folder.PreferredType == AssetType.Unknown)\r
+                    if (folder.PreferredType == AssetType.Unknown)\r
                     {\r
                         ctxInv.Items.Add(new ToolStripSeparator());\r
                         ctxItem = new ToolStripMenuItem("Delete", null, OnInvContextClick);\r
@@ -859,6 +859,13 @@ namespace Radegast
 \r
                     ToolStripMenuItem ctxItem;\r
 \r
+                    if (item.InventoryType == InventoryType.LSL)\r
+                    {\r
+                        ctxItem = new ToolStripMenuItem("Edit script", null, OnInvContextClick);\r
+                        ctxItem.Name = "edit_script";\r
+                        ctxInv.Items.Add(ctxItem);\r
+                    }\r
+\r
                     ctxItem = new ToolStripMenuItem("Rename", null, OnInvContextClick);\r
                     ctxItem.Name = "rename_item";\r
                     ctxInv.Items.Add(ctxItem);\r
@@ -1033,6 +1040,11 @@ namespace Radegast
                         AttachmentPoint pt = (AttachmentPoint)((ToolStripMenuItem)sender).Tag;\r
                         client.Appearance.Attach(item, pt);\r
                         break;\r
+\r
+                    case "edit_script":\r
+                        ScriptEditor se = new ScriptEditor(instance, (InventoryLSL)item);\r
+                        se.Detached = true;\r
+                        return;\r
                 }\r
                 #endregion\r
             }\r
index a7cc85b..1a4ffec 100644 (file)
@@ -45,6 +45,7 @@
     <DefineConstants>DEBUG;TRACE</DefineConstants>\r
     <ErrorReport>prompt</ErrorReport>\r
     <WarningLevel>4</WarningLevel>\r
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>\r
   </PropertyGroup>\r
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">\r
     <DebugType>pdbonly</DebugType>\r
@@ -53,6 +54,7 @@
     <DefineConstants>TRACE</DefineConstants>\r
     <ErrorReport>prompt</ErrorReport>\r
     <WarningLevel>4</WarningLevel>\r
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>\r
   </PropertyGroup>\r
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">\r
     <DebugSymbols>true</DebugSymbols>\r
@@ -61,6 +63,7 @@
     <DebugType>full</DebugType>\r
     <PlatformTarget>x86</PlatformTarget>\r
     <ErrorReport>prompt</ErrorReport>\r
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>\r
   </PropertyGroup>\r
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">\r
     <OutputPath>..\bin\Release\</OutputPath>\r
@@ -69,6 +72,7 @@
     <DebugType>pdbonly</DebugType>\r
     <PlatformTarget>x86</PlatformTarget>\r
     <ErrorReport>prompt</ErrorReport>\r
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>\r
   </PropertyGroup>\r
   <ItemGroup>\r
     <Reference Include="AIMLbot, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL" />\r
     <Compile Include="Core\Types\RRichTextBox.cs">\r
       <SubType>Component</SubType>\r
     </Compile>\r
+    <Compile Include="Core\Types\StringTokenizer.cs" />\r
     <Compile Include="Core\Types\TransparentButton.cs">\r
       <SubType>Component</SubType>\r
     </Compile>\r