Beispiel #1
0
        public static bool getXmlMatchedTagsPos(Scintilla scintilla, ref XmlMatchedTagsPos xmlTags, bool prevChar)
        {
            bool tagFound = false;
            int  caret    = scintilla.NativeInterface.GetCurrentPos();

            if (prevChar)
            {
                if (caret > 0)
                {
                    caret--;
                }
            }
            int searchStartPoint = caret;
            int styleAt          = -1;
            // search back for the previous open angle bracket.
            // Keep looking whilst the angle bracked found is inside an XML attribute.
            FindResult openFound = new FindResult();

            do
            {
                openFound        = findText("<", searchStartPoint, 0, 0, scintilla);
                styleAt          = scintilla.NativeInterface.GetStyleAt(openFound.start);
                searchStartPoint = openFound.start - 1;
            } while (openFound.success && (styleAt == Constants.SCE_H_DOUBLESTRING || styleAt == Constants.SCE_H_SINGLESTRING) && searchStartPoint > 0);

            if (openFound.success && styleAt != Constants.SCE_H_CDATA)
            {
                FindResult closeFound = new FindResult();
                searchStartPoint = openFound.start;
                do
                {
                    closeFound       = findText(">", searchStartPoint, caret, 0, scintilla);
                    styleAt          = scintilla.NativeInterface.GetStyleAt(closeFound.start);
                    searchStartPoint = closeFound.end;
                } while (closeFound.success && (styleAt == Constants.SCE_H_DOUBLESTRING || styleAt == Constants.SCE_H_SINGLESTRING) && searchStartPoint <= caret);

                if (!closeFound.success)
                {
                    char nextChar = scintilla.NativeInterface.GetCharAt(openFound.start + 1);
                    if (nextChar == '/')
                    {
                        xmlTags.tagCloseStart = openFound.start;
                        int        docLength   = scintilla.NativeInterface.GetLength();
                        FindResult endCloseTag = findText(">", caret, docLength, 0, scintilla);
                        if (endCloseTag.success)
                        {
                            xmlTags.tagCloseEnd = endCloseTag.end;
                        }


                        // Find the tag name.
                        int    position = openFound.start + 2;
                        string tagName  = "";
                        nextChar = scintilla.NativeInterface.GetCharAt(position);
                        while (position < docLength && !nextChar.IsWhiteSpace() && nextChar != '/' && nextChar != '>' && nextChar != '"' && nextChar != '\'')
                        {
                            tagName += nextChar; // tagName;
                            position++;
                            nextChar = scintilla.NativeInterface.GetCharAt(position);
                        }
                        if (!String.IsNullOrEmpty(tagName))
                        {
                            /* Now we need to find the open tag.  The logic here is that we search for "<TAGNAME",
                             * then check the next character - if it's one of '>', ' ', '\"' then we know we've found
                             * a relevant tag.
                             * We then need to check if either
                             *    a) this tag is a self-closed tag - e.g. <TAGNAME attrib="value" />
                             * or b) this tag has another closing tag after it and before our closing tag
                             *       e.g.  <TAGNAME attrib="value">some text</TAGNAME></TAGNA|ME>
                             *             (cursor represented by |)
                             * If it's either of the above, then we continue searching, but only up to the
                             * the point of the last find. (So in the (b) example above, we'd only search backwards
                             * from the first "<TAGNAME...", as we know there's a close tag for the opened tag.
                             *
                             * NOTE::  NEED TO CHECK THE ROTTEN CASE: ***********************************************************
                             * <TAGNAME attrib="value"><TAGNAME>something</TAGNAME></TAGNAME></TAGNA|ME>
                             * Maybe count all closing tags between start point and start of our end tag.???
                             */
                            int        currentEndPoint   = xmlTags.tagCloseStart;
                            int        openTagsRemaining = 1;
                            FindResult nextOpenTag       = new FindResult();
                            do
                            {
                                nextOpenTag = findOpenTag(tagName, currentEndPoint, 0, scintilla);
                                if (nextOpenTag.success)
                                {
                                    openTagsRemaining--;

                                    FindResult inbetweenCloseTag    = new FindResult();
                                    int        currentStartPosition = nextOpenTag.end;
                                    int        closeTagsFound       = 0;
                                    bool       forwardSearch        = (currentStartPosition < currentEndPoint);

                                    do
                                    {
                                        inbetweenCloseTag = findCloseTag(tagName, currentStartPosition, currentEndPoint, scintilla);
                                        if (inbetweenCloseTag.success)
                                        {
                                            closeTagsFound++;
                                            if (forwardSearch)
                                            {
                                                currentStartPosition = inbetweenCloseTag.end;
                                            }
                                            else
                                            {
                                                currentStartPosition = inbetweenCloseTag.start - 1;
                                            }
                                        }
                                    } while (inbetweenCloseTag.success);

                                    if (closeTagsFound == 0 && openTagsRemaining == 0)
                                    {
                                        xmlTags.tagOpenStart = nextOpenTag.start;
                                        xmlTags.tagOpenEnd   = nextOpenTag.end + 1;
                                        xmlTags.tagNameEnd   = nextOpenTag.start + tagName.Length + 1;
                                        tagFound             = true;
                                    }
                                    else
                                    {
                                        openTagsRemaining += closeTagsFound;
                                        currentEndPoint    = nextOpenTag.start;
                                    }
                                }
                            } while (!tagFound && openTagsRemaining > 0 && nextOpenTag.success);
                        }
                    }

                    else
                    {
                        // Cursor in open tag
                        int position  = openFound.start + 1;
                        int docLength = scintilla.NativeInterface.GetLength();
                        xmlTags.tagOpenStart = openFound.start;

                        string tagName = "";
                        nextChar = scintilla.NativeInterface.GetCharAt(position);
                        while (position < docLength && !nextChar.IsWhiteSpace() && nextChar != '/' && nextChar != '>' && nextChar != '"' && nextChar != '\'')
                        {
                            tagName = tagName + nextChar;
                            position++;
                            nextChar = scintilla.NativeInterface.GetCharAt(position);
                        }

                        if (!String.IsNullOrEmpty(tagName))
                        {
                            xmlTags.tagNameEnd = openFound.start + tagName.Length + 1;
                            int closeAnglePosition = findCloseAngle(position, docLength, scintilla);
                            if (closeAnglePosition != -1)
                            {
                                xmlTags.tagOpenEnd = closeAnglePosition + 1;
                                if (scintilla.NativeInterface.GetCharAt(closeAnglePosition - 1) == '/')
                                {
                                    xmlTags.tagCloseEnd   = -1;
                                    xmlTags.tagCloseStart = -1;
                                    tagFound = true;
                                }
                                else
                                {
                                    int        currentStartPosition = xmlTags.tagOpenEnd;
                                    int        closeTagsRemaining   = 1;
                                    FindResult nextCloseTag         = new FindResult();

                                    do
                                    {
                                        nextCloseTag = findCloseTag(tagName, currentStartPosition, docLength, scintilla);
                                        if (nextCloseTag.success)
                                        {
                                            closeTagsRemaining--;

                                            FindResult inbetweenOpenTag   = new FindResult();
                                            int        currentEndPosition = nextCloseTag.start;
                                            int        openTagsFound      = 0;
                                            do
                                            {
                                                inbetweenOpenTag = findOpenTag(tagName, currentStartPosition, currentEndPosition, scintilla);
                                                if (inbetweenOpenTag.success)
                                                {
                                                    openTagsFound++;
                                                    currentStartPosition = inbetweenOpenTag.end;
                                                }
                                            } while (inbetweenOpenTag.success);

                                            if (openTagsFound == 0 && closeTagsRemaining == 0)
                                            {
                                                xmlTags.tagCloseStart = nextCloseTag.start;
                                                xmlTags.tagCloseEnd   = nextCloseTag.end + 1;
                                                tagFound = true;
                                            }
                                            else
                                            {
                                                closeTagsRemaining  += openTagsFound;
                                                currentStartPosition = nextCloseTag.end;
                                            }
                                        }
                                    } while (!tagFound && closeTagsRemaining > 0 && nextCloseTag.success);
                                }
                            }
                        }
                    }
                }
            }
            return(tagFound);
        }
Beispiel #2
0
        /// <summary>
        ///     If Smart Indenting is enabled, this delegate will be added to the CharAdded multicast event.
        /// </summary>
        internal void CheckSmartIndent(char ch)
        {
            char newline = (Scintilla.EndOfLine.Mode == EndOfLineMode.CR) ? '\r' : '\n';

            switch (SmartIndentType)
            {
            case SmartIndent.None:
                return;

            case SmartIndent.Simple:
                if (ch == newline)
                {
                    Line curLine = Scintilla.Lines.Current;
                    curLine.Indentation  = curLine.Previous.Indentation;
                    Scintilla.CurrentPos = curLine.IndentPosition;
                }
                break;

            case SmartIndent.XML:

                if (ch == '}' || ch == ')' || ch == ']')
                {
                    int styleBit = getPrevStyle(Scintilla.CurrentPos);
                    if (handleWithCpp(styleBit))
                    {
                        handleCpp(ch, newline);
                    }
                }
                if (ch == newline)
                {
                    int cpos    = Scintilla.CurrentPos;
                    int origPos = cpos;
                    if (Scintilla.EndOfLine.Mode == EndOfLineMode.Crlf)
                    {
                        cpos -= 2;
                    }
                    else
                    {
                        cpos -= 1;
                    }

                    int styleBit = getPrevStyle(cpos);



                    if (handleWithCpp(styleBit))
                    {
                        handleCpp(ch, newline);
                    }
                    else
                    {
                        Line   curLine     = Scintilla.Lines.FromPosition(cpos);
                        string line        = curLine.Text;
                        int    col         = Scintilla.GetColumn(cpos);
                        int    i           = 0;
                        int    openCnt     = 0;
                        int    closeCount  = 0;
                        bool   inTag       = false;
                        string tagName     = "";
                        bool   buildingTag = false;
                        while (i < col && i < line.Length)
                        {
                            if (line[i] == '<')
                            {
                                if (curLine.Length > i)
                                {
                                    if (line[i + 1] != '/' && line[i + 1] != '!')
                                    {
                                        buildingTag = true;
                                        inTag       = true;
                                    }
                                    else
                                    {
                                        closeCount++;
                                        inTag = false;
                                    }
                                }
                            }


                            if (inTag && line[i] != '<')
                            {
                                if (line[i].IsWordChar() && buildingTag)
                                {
                                    tagName += line[i];
                                }

                                if (!line[i].IsWordChar())
                                {
                                    buildingTag = false;
                                }


                                if (line[i] == '>' && inTag)
                                {
                                    if (i > 0)
                                    {
                                        if (line[i - 1] != '/')
                                        {
                                            // Ignore br. May be others to ignore.
                                            if (tagName.ToLowerInvariant() != "br")
                                            {
                                                openCnt++;
                                            }
                                            inTag = false;
                                        }
                                    }
                                }
                            }
                            i++;
                        }

                        if (openCnt > closeCount)
                        {
                            cpos = Scintilla.CurrentPos;
                            string lnBreak = "";
                            if (Scintilla.EndOfLine.Mode == EndOfLineMode.CR)
                            {
                                lnBreak = "\r";
                            }
                            else if (Scintilla.EndOfLine.Mode == EndOfLineMode.LF)
                            {
                                lnBreak = "\n";
                            }
                            else
                            {
                                lnBreak = "\r\n";
                            }
                            Scintilla.UndoRedo.BeginUndoAction();
                            // Grab the current line indent
                            int lineIndent = curLine.Indentation;

                            // add in a line break. This also puts cursor on the next line but only
                            // if auto closing html brackets.
                            if (Scintilla.AutoClose.AutoCloseHtmlTags)
                            {
                                Scintilla.Selection.Text = lnBreak;
                            }

                            // Indent the next line back to the current line.
                            Scintilla.Lines.Current.Indentation = curLine.Indentation;

                            // Jump back to the original position (The new line which we want indented further
                            Scintilla.Selection.Start = origPos;
                            Scintilla.Selection.End   = origPos;

                            // Set indentation.
                            Scintilla.Lines.Current.Indentation = curLine.Indentation + TabWidth;
                            Scintilla.CurrentPos = Scintilla.Lines.Current.EndPosition;
                            Scintilla.UndoRedo.EndUndoAction();
                        }
                        else
                        {
                            // maintain indentation
                            Scintilla.UndoRedo.BeginUndoAction();
                            Scintilla.Lines.Current.Indentation = curLine.Indentation;
                            Scintilla.CurrentPos = Scintilla.Lines.Current.EndPosition;
                            Scintilla.UndoRedo.EndUndoAction();
                        }
                    }
                }
                if (ch == '>')
                {
                    XmlMatchedTagsPos xmlTag = new XmlMatchedTagsPos();
                    if (MatchingTag.getXmlMatchedTagsPos(Scintilla, ref xmlTag, true))
                    {
                        int indentSize = Scintilla.NativeInterface.GetLineIndentation(Scintilla.NativeInterface.LineFromPosition(xmlTag.tagOpenStart));
                        Scintilla.NativeInterface.SetLineIndentation(Scintilla.Lines.Current.Number, indentSize);
                    }
                }
                break;

            case SmartIndent.CPP:
            case SmartIndent.CPP2:
                handleCpp(ch, newline);
                break;
            }
        }