0b29a0b888882caf6306af38f8a530ab9057a2ca
[phpeclipse.git] /
1 /*******************************************************************************
2  * Copyright (c) 2000, 2003 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package net.sourceforge.phpdt.internal.ui.text.java;
12
13 import net.sourceforge.phpdt.ui.PreferenceConstants;
14 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
15
16 import org.eclipse.jface.preference.IPreferenceStore;
17 import org.eclipse.jface.text.BadLocationException;
18 import org.eclipse.jface.text.DefaultIndentLineAutoEditStrategy;
19 import org.eclipse.jface.text.DocumentCommand;
20 import org.eclipse.jface.text.IDocument;
21 import org.eclipse.jface.text.IRegion;
22 import org.eclipse.jface.text.ITypedRegion;
23 import org.eclipse.jface.text.TextUtilities;
24 import org.eclipse.ui.IEditorPart;
25 import org.eclipse.ui.IWorkbenchPage;
26 import org.eclipse.ui.texteditor.ITextEditorExtension3;
27
28 /**
29  * Auto indent strategy for single quoted PHP strings
30  */
31 public class JavaStringAutoIndentStrategySQ extends
32                 DefaultIndentLineAutoEditStrategy {
33
34         private String fPartitioning;
35
36         /**
37          * The input string doesn't contain any line delimiter.
38          * 
39          * @param inputString
40          *            the given input string
41          * @return the displayable string.
42          */
43         private String displayString (String inputString, String indentation, String delimiter) {
44                 int length = inputString.length();
45                 StringBuffer buffer = new StringBuffer(length);
46                 java.util.StringTokenizer tokenizer = 
47                                 new java.util.StringTokenizer (inputString, "\n\r", true); //$NON-NLS-1$
48                 
49                 while (tokenizer.hasMoreTokens ()) {
50                         String token = tokenizer.nextToken ();
51
52                         if (token.equals("\r")) { //$NON-NLS-1$
53                                 buffer.append("\\r"); //$NON-NLS-1$
54                                 if (tokenizer.hasMoreTokens()) {
55                                         token = tokenizer.nextToken();
56                                         if (token.equals("\n")) { //$NON-NLS-1$
57                                                 buffer.append("\\n"); //$NON-NLS-1$
58                                                 buffer.append("\" . " + delimiter); //$NON-NLS-1$
59                                                 buffer.append(indentation);
60                                                 buffer.append("\'"); //$NON-NLS-1$
61                                                 continue;
62                                         } else {
63                                                 buffer.append("\' . " + delimiter); //$NON-NLS-1$
64                                                 buffer.append(indentation);
65                                                 buffer.append("\'"); //$NON-NLS-1$
66                                         }
67                                 } else {
68                                         continue;
69                                 }
70                         } else if (token.equals("\n")) { //$NON-NLS-1$
71                                 buffer.append("\\n"); //$NON-NLS-1$
72                                 buffer.append("\' . " + delimiter); //$NON-NLS-1$
73                                 buffer.append(indentation);
74                                 buffer.append("\'"); //$NON-NLS-1$
75                                 continue;
76                         }
77
78                         StringBuffer tokenBuffer = new StringBuffer();
79
80                         for (int i = 0; i < token.length(); i++) {
81                                 char c = token.charAt(i);
82                                 switch (c) {
83                                 case '\r':
84                                         tokenBuffer.append("\\r"); //$NON-NLS-1$
85                                         break;
86                                 case '\n':
87                                         tokenBuffer.append("\\n"); //$NON-NLS-1$
88                                         break;
89                                 case '\b':
90                                         tokenBuffer.append("\\b"); //$NON-NLS-1$
91                                         break;
92                                 case '\t':
93                                         // keep tabs verbatim
94                                         tokenBuffer.append("\t"); //$NON-NLS-1$
95                                         break;
96                                 case '\f':
97                                         tokenBuffer.append("\\f"); //$NON-NLS-1$
98                                         break;
99                                 case '\"':
100                                         tokenBuffer.append("\\\""); //$NON-NLS-1$
101                                         break;
102                                 case '\'':
103                                         tokenBuffer.append("\\'"); //$NON-NLS-1$
104                                         break;
105                                 case '\\':
106                                         tokenBuffer.append("\\\\"); //$NON-NLS-1$
107                                         break;
108                                 default:
109                                         tokenBuffer.append(c);
110                                 }
111                         }
112                         buffer.append(tokenBuffer);
113                 }
114
115                 return buffer.toString();
116         }
117
118         /**
119          * Creates a new Java string auto indent strategy for the given document
120          * partitioning.
121          * 
122          * @param partitioning
123          *            the document partitioning
124          */
125         public JavaStringAutoIndentStrategySQ (String partitioning) {
126                 super();
127                 fPartitioning = partitioning;
128         }
129
130         /**
131          * Check whether the 'text' is one of the allowed line delimiters (e.g. \n \r)
132          * 
133          * @param document The document object for which we do the check
134          * @param text     The text with the possible delimiter
135          * @return
136          *  - true if 'text' is a valid delimiter
137          *  - false if 'text' is not a valid delimiter 
138          */
139         private boolean isLineDelimiter(IDocument document, String text) {
140                 String[] delimiters = document.getLegalLineDelimiters();
141                 
142                 if (delimiters != null) {
143                         return TextUtilities.equals(delimiters, text) > -1;
144                 }
145                 
146                 return false;
147         }
148
149         /**
150          * Get back the indentation of the line to which the offset belongs.
151          * 
152          * It searches the first occurrence of a white space (non space/non tab)
153          * 
154          * @param document
155          * @param offset
156          * @return
157          * @throws BadLocationException
158          */
159         private String getLineIndentation(IDocument document, int offset)
160                         throws BadLocationException {
161                 String indentation = "";
162                 int    start;
163                 int    end;
164                 int    length;
165
166                 // find start of line
167                 int adjustedOffset = (offset == document.getLength() ? offset - 1 : offset);// Check whether the offset is not at the end of file
168                 IRegion line = document.getLineInformationOfOffset (adjustedOffset);            // Get the start and the length of the line
169
170                 start = line.getOffset ();                                                                      // Get the start of the line
171                 end = findStringStart (document, start, offset);
172                 
173                 IPreferenceStore preferenceStore = PHPeclipsePlugin.getDefault().getPreferenceStore();
174                 length = end - start;
175                 
176                 if (preferenceStore.getBoolean (PreferenceConstants.EDITOR_SPACES_FOR_TABS)) {  // Indentation with spaces only
177                         if (length > 0) {
178                   indentation = String.format ("%" + length + "s", "");
179                 }
180                 }
181                 else {                                                                                                                                                  // Indentation with tabs
182                         if (length > 0) {
183                                 int spaces;
184                                 int tabs;
185                                 int tabWidth = preferenceStore.getInt (PreferenceConstants.EDITOR_TAB_WIDTH);
186
187                                 tabs   = length / tabWidth;
188                                 spaces = length % tabWidth;
189                                 
190                                 indentation  = new String (new char[tabs]).replace('\0', '\t');
191                                 indentation += String.format ("%" + spaces + "s", "");
192                         }
193                 }               
194
195                 return indentation;
196         }
197         
198         /**
199          * Return the position of the string start (first occurrence of a quote or double quote) 
200          * 
201          * @param offset 
202          * @param start 
203          * @param document 
204          * @return
205          */
206         private int findStringStart(IDocument document, int offset, int end) throws BadLocationException {
207                 while (offset < end) {
208                         char c = document.getChar (offset);
209                         
210                         if ((c == '\'') || (c == '\"')) {
211                                 return offset;
212                         }
213                         
214                         offset++;
215         }
216
217                 return end;
218         }
219
220         /**
221          * 
222          * @param string
223          * @param indentation
224          * @param delimiter
225          * @return
226          * @throws BadLocationException
227          */
228         private String getModifiedText (String string, String indentation, String delimiter) 
229                         throws BadLocationException {
230                 return displayString(string, indentation, delimiter);
231         }
232
233         /**
234          * 
235          * @param document
236          * @param command
237          * @throws BadLocationException
238          */
239         private void javaStringIndentAfterNewLine (IDocument document, DocumentCommand command) throws BadLocationException {
240                 ITypedRegion partition = TextUtilities.getPartition (document, fPartitioning, command.offset, false);
241                 int offset = partition.getOffset();
242                 int length = partition.getLength();
243
244                 if (command.offset == offset) {
245                         // we are really just before the string partition -> feet the event
246                         // through the java indenter
247                         // new
248                         // JavaAutoIndentStrategy(fPartitioning).customizeDocumentCommand(document,
249                         // command);
250                         return;
251                 }
252
253                 if ((command.offset == offset + length) && 
254                         (document.getChar (offset + length - 1) == '\'')) {
255                         return;
256                 }
257
258                 String indentation = getLineIndentation(document, command.offset);
259                 String delimiter = TextUtilities.getDefaultLineDelimiter(document);
260
261                 IRegion line = document.getLineInformationOfOffset(offset);
262                 String string = document.get (line.getOffset(), 
263                                                       offset - line.getOffset());               // Get the current line as string
264 /*              
265                 if (string.trim().length() != 0) {
266                         indentation += String.valueOf("\t\t"); //$NON-NLS-1$
267                 }
268 */
269                 IPreferenceStore preferenceStore = PHPeclipsePlugin.getDefault ().getPreferenceStore();
270
271                 if (isLineDelimiter (document, command.text)) {
272                         command.text = "\' ." + command.text + indentation + "\'"; //$NON-NLS-1$//$NON-NLS-2$
273                 }
274                 else if ((command.text.length() > 1) && 
275                                  preferenceStore.getBoolean (PreferenceConstants.EDITOR_ESCAPE_STRINGS_SQ)) {
276                         command.text = getModifiedText(command.text, indentation, delimiter);
277         }
278         }
279
280         /**
281          * 
282          * @return
283          */
284         private boolean isSmartMode() {
285                 IWorkbenchPage page = PHPeclipsePlugin.getActivePage();
286
287                 if (page != null) {
288                         IEditorPart part = page.getActiveEditor();
289
290                         if (part instanceof ITextEditorExtension3) {
291                                 ITextEditorExtension3 extension = (ITextEditorExtension3) part;
292                                 return extension.getInsertMode() == ITextEditorExtension3.SMART_INSERT;
293                         }
294                 }
295
296                 return false;
297         }
298
299         /*
300          * @see org.eclipse.jface.text.IAutoIndentStrategy#customizeDocumentCommand(IDocument,
301          *      DocumentCommand)
302          */
303         public void customizeDocumentCommand(IDocument document, DocumentCommand command) {
304                 try {
305                         if ((command.length != 0) || 
306                 (command.text == null)) {
307                                 return;
308             }
309
310                         IPreferenceStore preferenceStore = PHPeclipsePlugin.getDefault().getPreferenceStore();
311
312                         if (preferenceStore.getBoolean (PreferenceConstants.EDITOR_WRAP_STRINGS_SQ) && isSmartMode()) {
313                                 javaStringIndentAfterNewLine(document, command);
314             }
315
316                 } catch (BadLocationException e) {
317                 }
318         }
319 }