Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/port80/eclipse/xml/editors/XMLAutoIndentStrategy.java


1   package com.port80.eclipse.xml.editors;
2   
3   import org.eclipse.jface.text.BadLocationException;
4   import org.eclipse.jface.text.IDocument;
5   import org.eclipse.jface.text.ITypedRegion;
6   import org.eclipse.jface.text.source.ISourceViewer;
7   
8   import com.port80.eclipse.editors.EditorsPlugin;
9   import com.port80.eclipse.editors.EditorsUtil;
10  import com.port80.eclipse.editors.IEditorConfiguration;
11  import com.port80.eclipse.editors.util.AbstractXMLAutoIndentStrategy;
12  
13  /**
14   * Perform XML auto-indent.
15   * 
16   * @author chrisl
17   */
18  public class XMLAutoIndentStrategy extends AbstractXMLAutoIndentStrategy {
19  
20    ////////////////////////////////////////////////////////////////////////
21  
22    private static final String NAME = "XMLAutoIndentStrategy";
23  
24    /** Preformatted partitions. No tag counting, simple indent strategy. */
25    public static final String[] PREFORMATTED_PARTITIONS =
26      new String[] { IEditorConfiguration.CDATA_PARTITION, IEditorConfiguration.PROC_INST_PARTITION };
27  
28    /** Escaped partitions. No tag counting. */
29    public static final String[] ESCAPED_PARTITIONS =
30      new String[] {
31        IEditorConfiguration.CDATA_PARTITION,
32        IEditorConfiguration.PROC_INST_PARTITION,
33        IEditorConfiguration.COMMENT_PARTITION };
34  
35    public static final String[] CDATA_PARTITIONS = new String[] { IEditorConfiguration.CDATA_PARTITION };
36  
37    ////////////////////////////////////////////////////////////////////////
38  
39    /**
40     * Constructor for XMLAutoIndentStrategy.
41     */
42    public XMLAutoIndentStrategy(XMLEditorConfiguration cf, ISourceViewer viewer) {
43      super(cf, viewer);
44    }
45  
46    ////////////////////////////////////////////////////////////////////////
47  
48    protected String[] getEscapedPartitions() {
49      return ESCAPED_PARTITIONS;
50    }
51    
52    protected String[] getPreformattedPartitions() {
53      return PREFORMATTED_PARTITIONS;
54    }
55    
56    protected boolean isInsideEscapedPartitions(int offset, IDocument doc) {
57      if (EditorsUtil.isInsidePartition(offset, CDATA_PARTITIONS, true, doc))
58        return true;
59      return EditorsUtil.isInsidePartition(offset, ESCAPED_PARTITIONS, doc);
60    }
61  
62    protected boolean isInsidePreformattedPartitions(int offset, IDocument doc) {
63      if (EditorsUtil.isInsidePartition(offset, CDATA_PARTITIONS, true, doc))
64        return true;
65      return EditorsUtil.isInsidePartition(offset, PREFORMATTED_PARTITIONS, doc);
66    }
67  
68    /**
69     * @return Offset of the open angle bracket of the matching open tag before the given offset 'end'.
70     * Assuming there is a close tag at 'end'.
71     */
72    protected int findMatchingOpenTagBefore(int end, IDocument doc) {
73      int level = 0;
74      ITypedRegion partition;
75      try {
76        char c;
77        char prev = 0;
78        for (--end; end >= 0; --end) {
79          if (EditorsUtil.isInsidePartition(end, CDATA_PARTITIONS, true, doc)) {
80            partition = doc.getPartition(end);
81            end = partition.getOffset() - 1;
82          } else if (EditorsUtil.isInsidePartition(end, ESCAPED_PARTITIONS, doc)) {
83            partition = doc.getPartition(end);
84            end = partition.getOffset();
85          }
86          c = doc.getChar(end);
87          if (c == '/') {
88            if (prev == '>') {
89              // self end.
90              end = findOpenBracketBefore(end, doc);
91              c = '<';
92            }
93          } else if (c == '<') {
94            if (prev == '/') {
95              ++level;
96            } else if (prev == '?' || prev == '!') {
97            } else if (level == 0) {
98              return end;
99            } else {
100             --level;
101           }
102         } else if (c == '"' || c == '\'') {
103           end = getStringStart(doc, end, c);
104         }
105         prev = c;
106       }
107     } catch (BadLocationException e) {
108       EditorsPlugin.log(EditorsPlugin.getResourceString("bad_location.message"), 1, e); //$NON-NLS-1$
109     }
110     return -1;
111   }
112 
113   /**
114    * Count number of open tags-close tags in the given range.
115    * NOTE: No white space in char. sequences '&lt;/' and '/>' allowed here.
116    * @param skip True to ignore the first leading end tag.
117    */
118   protected int getTagCount(IDocument document, int start, int end, boolean skip) throws BadLocationException {
119     int bracketcount = 0;
120     char c, c1;
121     ITypedRegion partition;
122     while (start < end) {
123       if (EditorsUtil.isInsidePartition(start, ESCAPED_PARTITIONS, true, document)) {
124         partition = document.getPartition(start);
125         start = partition.getOffset() + partition.getLength();
126       }
127       c = document.getChar(start);
128       start++;
129       switch (c) {
130         case '/' :
131           if (start < end) {
132             c1 = document.getChar(start);
133             if (c1 == '>') {
134               // Self ended tag.
135               skip = false;
136               --bracketcount;
137               ++start;
138             }
139           }
140           break;
141           //        case '-' :
142           //          if (start < end - 1) {
143           //            c1 = document.getChar(start);
144           //            c2 = document.getChar(start + 1);
145           //            if (c1 == '-' && c2 == '>') {
146           //              // end of comment.
147           //              if (!skip)
148           //                --bracketcount;
149           //              skip = false;
150           //              start += 2;
151           //            }
152           //          }
153           //          break;
154           //        case ']' :
155           //          if (start < end - 1) {
156           //            c1 = document.getChar(start);
157           //            c2 = document.getChar(start + 1);
158           //            if (c1 == ']' && c2 == '>') {
159           //              // end of CDATA
160           //              if (!skip)
161           //                --bracketcount;
162           //              skip = false;
163           //              start += 2;
164           //            }
165           //          }
166           //          break;
167         case '<' :
168           if (start < end) {
169             c1 = document.getChar(start);
170             if (c1 == '?' || c1 == '!') {
171               // Process instruction, comment or CDATA no end tag.
172               skip = false;
173             } else if (c1 == '/') {
174               // End tag.
175               if (!skip)
176                 --bracketcount;
177               skip = false;
178               ++start;
179             } else {
180               // start tag
181               ++bracketcount;
182               skip = false;
183             }
184           }
185           break;
186         case '"' :
187         case '\'' :
188           start = getStringEnd(document, start, end, c);
189           break;
190       }
191     }
192     return bracketcount;
193   }
194 
195 }