Ejemplo n.º 1
0
        // virtual void SCI_METHOD Fold(Sci_PositionU startPos, i64 lengthDoc, int initStyle, IDocument *pAccess) = 0;
        public static void Fold(IntPtr instance, UIntPtr start_pos, IntPtr length_doc, int init_style, IntPtr p_access)
        {
            /*
             * is called with the exact range that needs folding.
             * Previously, lexers were called with a range that started one line
             * before the range that needs to be folded as this allowed fixing up
             * the last line from the previous folding.
             * The new approach allows the lexer to decide whether to backtrack
             * or to handle this more efficiently.
             *
             * Lessons I have learned so far are
             * - do not start with a base level of 0 to simplify the arithmetic int calculation
             * - scintilla recommends to use 0x400 as a base level
             * - when the value becomes smaller than the base value, set the base value
             * - create an additional margin in which you set the levels of the respective lines,
             *      so it is easy to see when something breaks.
             */

            int length = (int)length_doc;
            int start  = (int)start_pos;

            // allocate a buffer
            IntPtr buffer_ptr = Marshal.AllocHGlobal(length);

            if (buffer_ptr == IntPtr.Zero)
            {
                return;
            }

            IDocument       idoc   = (IDocument)Marshal.PtrToStructure(p_access, typeof(IDocument));
            IDocumentVtable vtable = (IDocumentVtable)Marshal.PtrToStructure((IntPtr)idoc.VTable, typeof(IDocumentVtable));

            // scintilla fills the allocated buffer
            vtable.GetCharRange(p_access, buffer_ptr, (IntPtr)start, (IntPtr)length);
            if (buffer_ptr == IntPtr.Zero)
            {
                return;
            }

            // convert the buffer into a managed string
            string content = Marshal.PtrToStringAnsi(buffer_ptr, length);


            int cur_level = (int)SciMsg.SC_FOLDLEVELBASE;
            int cur_line  = (int)vtable.LineFromPosition(p_access, (IntPtr)start);

            if (cur_line > 0)
            {
                int  prev_level      = (int)vtable.GetLevel(p_access, (IntPtr)(cur_line - 1));
                bool header_flag_set = (prev_level & (int)SciMsg.SC_FOLDLEVELHEADERFLAG) == (int)SciMsg.SC_FOLDLEVELHEADERFLAG;

                if (header_flag_set)
                {
                    cur_level = (prev_level & (int)SciMsg.SC_FOLDLEVELNUMBERMASK) + 1;
                }
                else
                {
                    cur_level = (prev_level & (int)SciMsg.SC_FOLDLEVELNUMBERMASK);
                }
            }

            int next_level = cur_level;

            for (int i = 0; i < length; i++)
            {
                if (!SupportedProperties["fold"])
                {
                    vtable.SetLevel(p_access, (IntPtr)cur_line, (int)SciMsg.SC_FOLDLEVELBASE);
                    while (i < length)
                    {
                        // read rest of the line
                        if (content[i] == '\n')
                        {
                            break;
                        }
                        i++;
                    }
                    cur_line++;
                    continue;
                }

                string tag = "";
                if (i + 2 < length)
                {
                    tag = content.Substring(i, 3);
                }


                if (FoldOpeningTags.Contains(tag))
                {
                    next_level++;
                    cur_level |= (int)SciMsg.SC_FOLDLEVELHEADERFLAG;
                }
                else if (FoldClosingTags.Contains(tag))
                {
                    next_level--;
                    if (SupportedProperties["fold.compact"])
                    {
                        cur_level--;
                    }
                    cur_level &= (int)SciMsg.SC_FOLDLEVELNUMBERMASK;
                }
                else
                {
                    cur_level &= (int)SciMsg.SC_FOLDLEVELNUMBERMASK;
                }

                while (i < length)
                {
                    // read rest of the line
                    if (content[i] == '\n')
                    {
                        break;
                    }
                    i++;
                }
                // set fold level
                if (cur_level < (int)SciMsg.SC_FOLDLEVELBASE)
                {
                    cur_level = (int)SciMsg.SC_FOLDLEVELBASE;
                }
                vtable.SetLevel(p_access, (IntPtr)cur_line, cur_level);
                cur_line++;
                cur_level = next_level;
            }
            // free allocated buffer
            Marshal.FreeHGlobal(buffer_ptr);
        }
Ejemplo n.º 2
0
        // virtual void SCI_METHOD Lex(Sci_PositionU startPos, i64 lengthDoc, int initStyle, IDocument *pAccess) = 0;
        public static void Lex(IntPtr instance, UIntPtr start_pos, IntPtr length_doc, int init_style, IntPtr p_access)
        {
            /* main lexing method.
             * start_pos is always the startposition of a line
             * length_doc is NOT the total length of a document but the size of the text to be styled
             * init_style is the style of last styled byte
             * p_access is the pointer of the IDocument cpp class
             */

            int length = (int)length_doc;
            int start  = (int)start_pos;

            bool bHighlight = SupportedProperties["highlightnumeric"];
            //bool bHighlight = true;

            // allocate a buffer
            IntPtr buffer_ptr = Marshal.AllocHGlobal(length);

            if (buffer_ptr == IntPtr.Zero)
            {
                return;
            }

            // create the IDocument interface (struct) from the provided p_access pointer
            IDocument idoc = (IDocument)Marshal.PtrToStructure(p_access, typeof(IDocument));
            // create/simulate the vtable of the IDocument interface
            IDocumentVtable vtable = (IDocumentVtable)Marshal.PtrToStructure((IntPtr)idoc.VTable, typeof(IDocumentVtable));

            // scintilla fills the allocated buffer
            vtable.GetCharRange(p_access, buffer_ptr, (IntPtr)start, (IntPtr)length);
            if (buffer_ptr == IntPtr.Zero)
            {
                return;
            }

            // convert the buffer into a managed string
            string content = Marshal.PtrToStringAnsi(buffer_ptr, length);


            for (int i = 0; i < length; i++)
            {
                int    start_position = i;
                string tag            = "";
                int    idx            = 0;
                bool   num            = false;
                bool   dot            = false;
                int    start_num      = -1;

                if (i + 2 < length)
                {
                    tag = content.Substring(i, 3);
                }

                if (Segs1.Contains(tag))
                {
                    idx = 1;
                }
                else if (Segs2.Contains(tag))
                {
                    idx = 2;
                }
                else if (Segs3.Contains(tag))
                {
                    idx = 3;
                }
                else if (Segs4.Contains(tag))
                {
                    idx = 4;
                }

                while (i < length)
                {
                    // highlight numeric values
                    if (bHighlight)
                    {
                        if (num && (content[i] == '.'))
                        {
                            dot = true;
                        }
                        else if (!num && (content[i] >= '0') && (content[i] <= '9'))
                        {
                            num       = true;
                            start_num = i;
                        }
                        else if ((content[i] < '0') || (content[i] > '9'))
                        {
                            if (num && dot)
                            {
                                // style up until numeric
                                vtable.StartStyling(p_access, (IntPtr)(start + start_position));
                                vtable.SetStyleFor(p_access, (IntPtr)(start_num - start_position), (char)idx);

                                // style numeric highlight
                                vtable.StartStyling(p_access, (IntPtr)(start + start_num));
                                vtable.SetStyleFor(p_access, (IntPtr)(i - start_num), (char)9); // 9 = highlight numeric

                                // new start position after numeric
                                start_position = i;
                            }

                            // reset
                            num = false;
                            dot = false;
                        }
                    }
                    // read rest of the line
                    if (content[i] == '\n')
                    {
                        break;
                    }
                    i++;
                }
                // let scintilla style this line
                vtable.StartStyling(p_access, (IntPtr)(start + start_position));
                vtable.SetStyleFor(p_access, (IntPtr)(i - start_position), (char)idx);
            }

            // free allocated buffer
            Marshal.FreeHGlobal(buffer_ptr);
        }