001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.internal.ui.text.java;
011:
012: import org.eclipse.jface.preference.IPreferenceStore;
013:
014: import org.eclipse.jface.text.BadLocationException;
015: import org.eclipse.jface.text.DefaultIndentLineAutoEditStrategy;
016: import org.eclipse.jface.text.DocumentCommand;
017: import org.eclipse.jface.text.IDocument;
018: import org.eclipse.jface.text.IRegion;
019: import org.eclipse.jface.text.ITypedRegion;
020: import org.eclipse.jface.text.TextUtilities;
021:
022: import org.eclipse.ui.IEditorPart;
023: import org.eclipse.ui.IWorkbenchPage;
024: import org.eclipse.ui.texteditor.ITextEditorExtension3;
025:
026: import org.eclipse.jdt.ui.PreferenceConstants;
027:
028: import org.eclipse.jdt.internal.ui.JavaPlugin;
029:
030: /**
031: * Auto indent strategy for java strings
032: */
033: public class JavaStringAutoIndentStrategy extends
034: DefaultIndentLineAutoEditStrategy {
035:
036: private String fPartitioning;
037:
038: /**
039: * The input string doesn't contain any line delimiter.
040: *
041: * @param inputString the given input string
042: * @return the displayable string.
043: */
044: private String displayString(String inputString,
045: String indentation, String delimiter) {
046:
047: int length = inputString.length();
048: StringBuffer buffer = new StringBuffer(length);
049: java.util.StringTokenizer tokenizer = new java.util.StringTokenizer(
050: inputString, "\n\r", true); //$NON-NLS-1$
051: while (tokenizer.hasMoreTokens()) {
052:
053: String token = tokenizer.nextToken();
054: if (token.equals("\r")) { //$NON-NLS-1$
055: buffer.append("\\r"); //$NON-NLS-1$
056: if (tokenizer.hasMoreTokens()) {
057: token = tokenizer.nextToken();
058: if (token.equals("\n")) { //$NON-NLS-1$
059: buffer.append("\\n"); //$NON-NLS-1$
060: buffer.append("\" + " + delimiter); //$NON-NLS-1$
061: buffer.append(indentation);
062: buffer.append("\""); //$NON-NLS-1$
063: continue;
064: } else {
065: buffer.append("\" + " + delimiter); //$NON-NLS-1$
066: buffer.append(indentation);
067: buffer.append("\""); //$NON-NLS-1$
068: }
069: } else {
070: continue;
071: }
072: } else if (token.equals("\n")) { //$NON-NLS-1$
073: buffer.append("\\n"); //$NON-NLS-1$
074: buffer.append("\" + " + delimiter); //$NON-NLS-1$
075: buffer.append(indentation);
076: buffer.append("\""); //$NON-NLS-1$
077: continue;
078: }
079:
080: StringBuffer tokenBuffer = new StringBuffer();
081: for (int i = 0; i < token.length(); i++) {
082: char c = token.charAt(i);
083: switch (c) {
084: case '\r':
085: tokenBuffer.append("\\r"); //$NON-NLS-1$
086: break;
087: case '\n':
088: tokenBuffer.append("\\n"); //$NON-NLS-1$
089: break;
090: case '\b':
091: tokenBuffer.append("\\b"); //$NON-NLS-1$
092: break;
093: case '\t':
094: // keep tabs verbatim
095: tokenBuffer.append("\t"); //$NON-NLS-1$
096: break;
097: case '\f':
098: tokenBuffer.append("\\f"); //$NON-NLS-1$
099: 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: return buffer.toString();
116: }
117:
118: /**
119: * Creates a new Java string auto indent strategy for the given document partitioning.
120: *
121: * @param partitioning the document partitioning
122: */
123: public JavaStringAutoIndentStrategy(String partitioning) {
124: super ();
125: fPartitioning = partitioning;
126: }
127:
128: private boolean isLineDelimiter(IDocument document, String text) {
129: String[] delimiters = document.getLegalLineDelimiters();
130: if (delimiters != null)
131: return TextUtilities.equals(delimiters, text) > -1;
132: return false;
133: }
134:
135: private String getLineIndentation(IDocument document, int offset)
136: throws BadLocationException {
137:
138: // find start of line
139: int adjustedOffset = (offset == document.getLength() ? offset - 1
140: : offset);
141: IRegion line = document
142: .getLineInformationOfOffset(adjustedOffset);
143: int start = line.getOffset();
144:
145: // find white spaces
146: int end = findEndOfWhiteSpace(document, start, offset);
147:
148: return document.get(start, end - start);
149: }
150:
151: private String getModifiedText(String string, String indentation,
152: String delimiter) {
153: return displayString(string, indentation, delimiter);
154: }
155:
156: private void javaStringIndentAfterNewLine(IDocument document,
157: DocumentCommand command) throws BadLocationException {
158:
159: ITypedRegion partition = TextUtilities.getPartition(document,
160: fPartitioning, command.offset, true);
161: int offset = partition.getOffset();
162: int length = partition.getLength();
163:
164: if (command.offset == offset + length
165: && document.getChar(offset + length - 1) == '\"')
166: return;
167:
168: String indentation = getLineIndentation(document,
169: command.offset);
170: String delimiter = TextUtilities
171: .getDefaultLineDelimiter(document);
172:
173: IRegion line = document.getLineInformationOfOffset(offset);
174: String string = document.get(line.getOffset(), offset
175: - line.getOffset());
176: if (string.trim().length() != 0)
177: indentation += String.valueOf("\t\t"); //$NON-NLS-1$
178:
179: IPreferenceStore preferenceStore = JavaPlugin.getDefault()
180: .getPreferenceStore();
181: if (isLineDelimiter(document, command.text))
182: command.text = "\" +" + command.text + indentation + "\""; //$NON-NLS-1$//$NON-NLS-2$
183: else if (command.text.length() > 1
184: && preferenceStore
185: .getBoolean(PreferenceConstants.EDITOR_ESCAPE_STRINGS))
186: command.text = getModifiedText(command.text, indentation,
187: delimiter);
188: }
189:
190: private boolean isSmartMode() {
191: IWorkbenchPage page = JavaPlugin.getActivePage();
192: if (page != null) {
193: IEditorPart part = page.getActiveEditor();
194: if (part instanceof ITextEditorExtension3) {
195: ITextEditorExtension3 extension = (ITextEditorExtension3) part;
196: return extension.getInsertMode() == ITextEditorExtension3.SMART_INSERT;
197: }
198: }
199: return false;
200: }
201:
202: /*
203: * @see org.eclipse.jface.text.IAutoIndentStrategy#customizeDocumentCommand(IDocument, DocumentCommand)
204: */
205: public void customizeDocumentCommand(IDocument document,
206: DocumentCommand command) {
207: try {
208: if (command.text == null)
209: return;
210:
211: IPreferenceStore preferenceStore = JavaPlugin.getDefault()
212: .getPreferenceStore();
213:
214: if (preferenceStore
215: .getBoolean(PreferenceConstants.EDITOR_WRAP_STRINGS)
216: && isSmartMode()) {
217: javaStringIndentAfterNewLine(document, command);
218: }
219:
220: } catch (BadLocationException e) {
221: }
222: }
223: }
|