d7642bff6009f3bd4eaf419760fc37ebb854db10
[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 double quoted PHP strings 
30  */
31 public class JavaStringAutoIndentStrategyDQ 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                                         
57                                         if (token.equals("\n")) { //$NON-NLS-1$
58                                                 buffer.append("\\n"); //$NON-NLS-1$
59                                                 buffer.append("\" . " + delimiter); //$NON-NLS-1$
60                                                 buffer.append(indentation);
61                                                 buffer.append("\""); //$NON-NLS-1$
62                                                 continue;
63                                         } else {
64                                                 buffer.append("\" . " + delimiter); //$NON-NLS-1$
65                                                 buffer.append(indentation);
66                                                 buffer.append("\""); //$NON-NLS-1$
67                                         }
68                                 } else {
69                                         continue;
70                                 }
71                         } else if (token.equals("\n")) { //$NON-NLS-1$
72                                 buffer.append("\\n"); //$NON-NLS-1$
73                                 buffer.append("\" . " + delimiter); //$NON-NLS-1$
74                                 buffer.append(indentation);
75                                 buffer.append("\""); //$NON-NLS-1$
76                                 continue;
77                         }
78
79                         StringBuffer tokenBuffer = new StringBuffer();
80
81                         for (int i = 0; i < token.length(); i++) {
82                                 char c = token.charAt(i);
83                                 switch (c) {
84                                 case '\r':
85                                         tokenBuffer.append("\\r"); //$NON-NLS-1$
86                                         break;
87                                 case '\n':
88                                         tokenBuffer.append("\\n"); //$NON-NLS-1$
89                                         break;
90                                 case '\b':
91                                         tokenBuffer.append("\\b"); //$NON-NLS-1$
92                                         break;
93                                 case '\t':
94                                         // keep tabs verbatim
95                                         tokenBuffer.append("\t"); //$NON-NLS-1$
96                                         break;
97                                 case '\f':
98                                         tokenBuffer.append("\\f"); //$NON-NLS-1$
99                                         break;
100                                 case '\"':
101                                         tokenBuffer.append("\\\""); //$NON-NLS-1$
102                                         break;
103                                 case '\'':
104                                         tokenBuffer.append("\\'"); //$NON-NLS-1$
105                                         break;
106                                 case '\\':
107                                         tokenBuffer.append("\\\\"); //$NON-NLS-1$
108                                         break;
109                                 default:
110                                         tokenBuffer.append(c);
111                                 }
112                         }
113                         buffer.append(tokenBuffer);
114                 }
115
116                 return buffer.toString();
117         }
118
119         /**
120          * Creates a new Java string auto indent strategy for the given document
121          * partitioning.
122          * 
123          * @param partitioning
124          *            the document partitioning
125          */
126         public JavaStringAutoIndentStrategyDQ (String partitioning) {
127                 super ();
128                 fPartitioning = partitioning;
129         }
130
131         /**
132          * Check whether the 'text' is one of the allowed line delimiters (e.g. \n \r)
133          * 
134          * @param document The document object for which we do the check
135          * @param text     The text with the possible delimiter
136          * @return
137          *  - true if 'text' is a valid delimiter
138          *  - false if 'text' is not a valid delimiter 
139          */
140         private boolean isLineDelimiter (IDocument document, String text) {
141                 String[] delimiters = document.getLegalLineDelimiters();
142                 
143                 if (delimiters != null) {
144                         return TextUtilities.equals (delimiters, text) > -1;
145                 }
146                 
147                 return false;
148         }
149         
150         /**
151          * Get back the indentation of the line to which the offset belongs.
152          * 
153          * It searches the first occurrence of a white space (non space/non tab)
154          * 
155          * @param document
156          * @param offset
157          * @return
158          * @throws BadLocationException
159          */
160         private String getLineIndentation (IDocument document, int offset)
161                         throws BadLocationException {
162                 String indentation = "";
163                 int    start;
164                 int    end;
165                 int    length;
166                 
167                 // find start of line
168                 int adjustedOffset = (offset == document.getLength() ? offset - 1 : offset);// Check whether the offset is not at the end of file
169                 IRegion line = document.getLineInformationOfOffset (adjustedOffset);            // Get the start and the length of the line
170                 
171                 start = line.getOffset ();                                                                      // Get the start of the line
172                 end = findStringStart (document, start, offset);
173                 
174                 IPreferenceStore preferenceStore = PHPeclipsePlugin.getDefault().getPreferenceStore();
175                 length = end - start;
176                 
177                 if (preferenceStore.getBoolean (PreferenceConstants.EDITOR_SPACES_FOR_TABS)) {  // Indentation with spaces only
178                         if (length > 0) {
179                                 indentation = String.format ("%" + length + "s", "");
180                         }
181                 }
182                 else {                                                                                                                                                  // Indentation with tabs
183                         if (length > 0) {
184                                 int spaces;
185                                 int tabs;
186                                 int tabWidth = preferenceStore.getInt (PreferenceConstants.EDITOR_TAB_WIDTH);
187
188                                 tabs   = length / tabWidth;
189                                 spaces = length % tabWidth;
190                                 
191                                 indentation  = new String (new char[tabs]).replace('\0', '\t');
192                                 indentation += String.format ("%" + spaces + "s", "");
193                         }
194                 }               
195                 
196                 return indentation;
197         }
198         
199         /**
200          * Return the position of the string start (first occurrence of a quote or double quote) 
201          * 
202          * @param offset 
203          * @param start 
204          * @param document 
205          * @return
206          */
207         private int findStringStart(IDocument document, int offset, int end) throws BadLocationException {
208                 while (offset < end) {
209                         char c = document.getChar (offset);
210                         
211                         if ((c == '\'') || (c == '\"')) {
212                                 return offset;
213                         }
214                         
215                         offset++;
216                 }
217                 
218                 return end;
219         }
220
221         /**
222          * 
223          * @param string
224          * @param indentation
225          * @param delimiter
226          * @return
227          * @throws BadLocationException
228          */
229         private String getModifiedText (String string, String indentation, String delimiter) 
230                         throws BadLocationException {
231                 return displayString (string, indentation, delimiter);
232         }
233
234         /**
235          * 
236          * @param document
237          * @param command
238          * @throws BadLocationException
239          */
240         private void javaStringIndentAfterNewLine (IDocument document, DocumentCommand command) throws BadLocationException {
241                 ITypedRegion partition = TextUtilities.getPartition (document, fPartitioning, command.offset, false);
242                 int offset = partition.getOffset();
243                 int length = partition.getLength();
244
245                 if (command.offset == offset) {
246                         // we are really just before the string partition -> feet the event
247                         // through the java indenter
248                         // new
249                         // JavaAutoIndentStrategy(fPartitioning).customizeDocumentCommand(document,
250                         // command);
251                         return;
252                 }
253
254                 if ((command.offset == offset + length) && 
255                         (document.getChar (offset + length - 1) == '\"')) {
256                         return;
257                 }
258
259                 String indentation = getLineIndentation (document, command.offset);
260                 String delimiter = TextUtilities.getDefaultLineDelimiter (document);
261
262                 IRegion line = document.getLineInformationOfOffset (offset);
263                 String string = document.get (line.getOffset(), 
264                                                       offset - line.getOffset());               // Get the current line as string
265 /*              
266                 if (string.trim().length() != 0) {
267                         indentation += String.valueOf ("\t\t"); //$NON-NLS-1$
268                 }
269 */
270                 IPreferenceStore preferenceStore = PHPeclipsePlugin.getDefault ().getPreferenceStore();
271                 
272                 if (isLineDelimiter (document, command.text)) {
273                         command.text = "\" ." + command.text + indentation + "\""; //$NON-NLS-1$//$NON-NLS-2$
274                 }
275                 else if ((command.text.length() > 1) && 
276                                  preferenceStore.getBoolean (PreferenceConstants.EDITOR_ESCAPE_STRINGS_DQ)) {
277                         command.text = getModifiedText(command.text, indentation, delimiter);
278                 }
279         }
280
281         /**
282          * 
283          * @return
284          */
285         private boolean isSmartMode () {
286                 IWorkbenchPage page = PHPeclipsePlugin.getActivePage();
287                 
288                 if (page != null) {
289                         IEditorPart part = page.getActiveEditor ();
290                         
291                         if (part instanceof ITextEditorExtension3) {
292                                 ITextEditorExtension3 extension = (ITextEditorExtension3) part;
293                                 return extension.getInsertMode() == ITextEditorExtension3.SMART_INSERT;
294                         }
295                 }
296                 
297                 return false;
298         }
299
300         /*
301          * @see org.eclipse.jface.text.IAutoIndentStrategy#customizeDocumentCommand(IDocument,
302          *      DocumentCommand)
303          */
304         public void customizeDocumentCommand (IDocument document, DocumentCommand command) {
305                 try {
306                         if ((command.length != 0) || 
307                                 (command.text == null)) {
308                                 return;
309                         }
310
311                         IPreferenceStore preferenceStore = PHPeclipsePlugin.getDefault().getPreferenceStore();
312
313                         if (preferenceStore.getBoolean (PreferenceConstants.EDITOR_WRAP_STRINGS_DQ) && isSmartMode ()) {
314                                 javaStringIndentAfterNewLine (document, command);
315                         }
316
317                 } catch (BadLocationException e) {
318                 }
319         }
320 }