View | Details | Raw Unified | Return to bug 174597 | Differences between
and this patch

Collapse All | Expand All

(-)src/org/eclipse/cdt/ui/PreferenceConstants.java (-1 / +9 lines)
Lines 792-798 Link Here
792
	 *
792
	 *
793
	 */
793
	 */
794
	public static final String EDITOR_FOLDING_ENABLED= "editor_folding_enabled"; //$NON-NLS-1$
794
	public static final String EDITOR_FOLDING_ENABLED= "editor_folding_enabled"; //$NON-NLS-1$
795
795
	
796
	/**
796
	/**
797
	 * A named preference that stores the configured folding provider.
797
	 * A named preference that stores the configured folding provider.
798
	 * <p>
798
	 * <p>
Lines 813-818 Link Here
813
	public static final String EDITOR_FOLDING_STRUCTURES= "editor_folding_default_structures"; //$NON-NLS-1$
813
	public static final String EDITOR_FOLDING_STRUCTURES= "editor_folding_default_structures"; //$NON-NLS-1$
814
814
815
	/**
815
	/**
816
	 * A named preference that stores the value for statements (if/else while/do, for, switch statements)
817
	 * <p>
818
	 * Value is of type <code>Boolean</code>.
819
	 * </p>
820
	 */
821
	public static final String EDITOR_FOLDING_STATEMENTS = "editor_folding_statements"; //$NON-NLS-1$
822
	
823
	/**
816
	 * A named preference that stores the value for functions folding for the default folding provider.
824
	 * A named preference that stores the value for functions folding for the default folding provider.
817
	 * <p>
825
	 * <p>
818
	 * Value is of type <code>Boolean</code>.
826
	 * Value is of type <code>Boolean</code>.
(-)src/org/eclipse/cdt/internal/ui/text/folding/FoldingMessages.properties (+1 lines)
Lines 20-24 Link Here
20
DefaultCFoldingPreferenceBlock_headers= &Header Comments
20
DefaultCFoldingPreferenceBlock_headers= &Header Comments
21
DefaultCFoldingPreferenceBlock_inactive_code= &Inactive Preprocessor Branches
21
DefaultCFoldingPreferenceBlock_inactive_code= &Inactive Preprocessor Branches
22
DefaultCFoldingPreferenceBlock_preprocessor_enabled= Enable folding of preprocessor branches (#if/#endif)
22
DefaultCFoldingPreferenceBlock_preprocessor_enabled= Enable folding of preprocessor branches (#if/#endif)
23
DefaultCFoldingPreferenceBlock_statements_enabled= Enable folding of control flow statements (if, else, do/while, for, switch)
23
24
24
EmptyCFoldingPreferenceBlock_emptyCaption=
25
EmptyCFoldingPreferenceBlock_emptyCaption=
(-)src/org/eclipse/cdt/internal/ui/text/folding/DefaultCFoldingPreferenceBlock.java (-1 / +4 lines)
Lines 8-13 Link Here
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Anton Leherbauer (Wind River Systems)
10
 *     Anton Leherbauer (Wind River Systems)
11
 *     Elazar Leibovich (IDF)
11
 *******************************************************************************/
12
 *******************************************************************************/
12
13
13
package org.eclipse.cdt.internal.ui.text.folding;
14
package org.eclipse.cdt.internal.ui.text.folding;
Lines 74-79 Link Here
74
		overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, PreferenceConstants.EDITOR_FOLDING_HEADERS));
75
		overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, PreferenceConstants.EDITOR_FOLDING_HEADERS));
75
		overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, PreferenceConstants.EDITOR_FOLDING_INACTIVE_CODE));
76
		overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, PreferenceConstants.EDITOR_FOLDING_INACTIVE_CODE));
76
		overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, PreferenceConstants.EDITOR_FOLDING_PREPROCESSOR_BRANCHES_ENABLED));
77
		overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, PreferenceConstants.EDITOR_FOLDING_PREPROCESSOR_BRANCHES_ENABLED));
78
		overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, PreferenceConstants.EDITOR_FOLDING_STATEMENTS));
77
		
79
		
78
		return (OverlayKey[]) overlayKeys.toArray(new OverlayKey[overlayKeys.size()]);
80
		return (OverlayKey[]) overlayKeys.toArray(new OverlayKey[overlayKeys.size()]);
79
	}
81
	}
Lines 92-97 Link Here
92
		inner.setLayout(layout);
94
		inner.setLayout(layout);
93
95
94
		addCheckBox(inner, FoldingMessages.DefaultCFoldingPreferenceBlock_preprocessor_enabled, PreferenceConstants.EDITOR_FOLDING_PREPROCESSOR_BRANCHES_ENABLED, 1);
96
		addCheckBox(inner, FoldingMessages.DefaultCFoldingPreferenceBlock_preprocessor_enabled, PreferenceConstants.EDITOR_FOLDING_PREPROCESSOR_BRANCHES_ENABLED, 1);
97
		addCheckBox(inner, FoldingMessages.DefaultCFoldingPreferenceBlock_statements_enabled, PreferenceConstants.EDITOR_FOLDING_STATEMENTS, 1);
95
		ControlFactory.createEmptySpace(inner);
98
		ControlFactory.createEmptySpace(inner);
96
99
97
		Composite group= ControlFactory.createGroup(inner, FoldingMessages.DefaultCFoldingPreferenceBlock_title, 1);
100
		Composite group= ControlFactory.createGroup(inner, FoldingMessages.DefaultCFoldingPreferenceBlock_title, 1);
Lines 101-107 Link Here
101
		addCheckBox(group, FoldingMessages.DefaultCFoldingPreferenceBlock_methods, PreferenceConstants.EDITOR_FOLDING_METHODS, 0); 
104
		addCheckBox(group, FoldingMessages.DefaultCFoldingPreferenceBlock_methods, PreferenceConstants.EDITOR_FOLDING_METHODS, 0); 
102
		addCheckBox(group, FoldingMessages.DefaultCFoldingPreferenceBlock_structures, PreferenceConstants.EDITOR_FOLDING_STRUCTURES, 0); 
105
		addCheckBox(group, FoldingMessages.DefaultCFoldingPreferenceBlock_structures, PreferenceConstants.EDITOR_FOLDING_STRUCTURES, 0); 
103
		addCheckBox(group, FoldingMessages.DefaultCFoldingPreferenceBlock_comments, PreferenceConstants.EDITOR_FOLDING_COMMENTS, 0); 
106
		addCheckBox(group, FoldingMessages.DefaultCFoldingPreferenceBlock_comments, PreferenceConstants.EDITOR_FOLDING_COMMENTS, 0); 
104
		addCheckBox(group, FoldingMessages.DefaultCFoldingPreferenceBlock_headers, PreferenceConstants.EDITOR_FOLDING_HEADERS, 0); 
107
		addCheckBox(group, FoldingMessages.DefaultCFoldingPreferenceBlock_headers, PreferenceConstants.EDITOR_FOLDING_HEADERS, 0);
105
		fInactiveCodeFoldingCheckBox= addCheckBox(group, FoldingMessages.DefaultCFoldingPreferenceBlock_inactive_code, PreferenceConstants.EDITOR_FOLDING_INACTIVE_CODE, 0); 
108
		fInactiveCodeFoldingCheckBox= addCheckBox(group, FoldingMessages.DefaultCFoldingPreferenceBlock_inactive_code, PreferenceConstants.EDITOR_FOLDING_INACTIVE_CODE, 0); 
106
		
109
		
107
		return inner;
110
		return inner;
(-)src/org/eclipse/cdt/internal/ui/text/folding/DefaultCFoldingStructureProvider.java (-442 / +783 lines)
Lines 9-14 Link Here
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Anton Leherbauer (Wind River Systems)
10
 *     Anton Leherbauer (Wind River Systems)
11
 *     Markus Schorn (Wind River Systems)
11
 *     Markus Schorn (Wind River Systems)
12
 *     Elazar Leibovich (IDF)
12
 *******************************************************************************/
13
 *******************************************************************************/
13
14
14
package org.eclipse.cdt.internal.ui.text.folding;
15
package org.eclipse.cdt.internal.ui.text.folding;
Lines 25-30 Link Here
25
import java.util.Stack;
26
import java.util.Stack;
26
27
27
import org.eclipse.core.runtime.Assert;
28
import org.eclipse.core.runtime.Assert;
29
import org.eclipse.core.runtime.FileLocator;
28
import org.eclipse.core.runtime.IProgressMonitor;
30
import org.eclipse.core.runtime.IProgressMonitor;
29
import org.eclipse.core.runtime.IStatus;
31
import org.eclipse.core.runtime.IStatus;
30
import org.eclipse.core.runtime.Platform;
32
import org.eclipse.core.runtime.Platform;
Lines 50-55 Link Here
50
import org.eclipse.ui.texteditor.IDocumentProvider;
52
import org.eclipse.ui.texteditor.IDocumentProvider;
51
import org.eclipse.ui.texteditor.ITextEditor;
53
import org.eclipse.ui.texteditor.ITextEditor;
52
54
55
import org.eclipse.cdt.core.CCorePlugin;
56
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
57
import org.eclipse.cdt.core.dom.ast.IASTBreakStatement;
58
import org.eclipse.cdt.core.dom.ast.IASTCaseStatement;
59
import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement;
60
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
61
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
62
import org.eclipse.cdt.core.dom.ast.IASTDefaultStatement;
63
import org.eclipse.cdt.core.dom.ast.IASTDoStatement;
64
import org.eclipse.cdt.core.dom.ast.IASTElaboratedTypeSpecifier;
65
import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier;
66
import org.eclipse.cdt.core.dom.ast.IASTExpression;
67
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
68
import org.eclipse.cdt.core.dom.ast.IASTForStatement;
69
import org.eclipse.cdt.core.dom.ast.IASTInitializer;
70
import org.eclipse.cdt.core.dom.ast.IASTInitializerList;
71
import org.eclipse.cdt.core.dom.ast.IASTNode;
72
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
73
import org.eclipse.cdt.core.dom.ast.IASTWhileStatement;
74
import org.eclipse.cdt.core.dom.ast.IASTIfStatement;
75
import org.eclipse.cdt.core.dom.ast.IASTStatement;
76
import org.eclipse.cdt.core.dom.ast.IASTSwitchStatement;
77
53
import org.eclipse.cdt.core.dom.ast.IASTNodeLocation;
78
import org.eclipse.cdt.core.dom.ast.IASTNodeLocation;
54
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorElifStatement;
79
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorElifStatement;
55
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorElseStatement;
80
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorElseStatement;
Lines 59-64 Link Here
59
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIfndefStatement;
84
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIfndefStatement;
60
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorStatement;
85
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorStatement;
61
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
86
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
87
import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator;
62
import org.eclipse.cdt.core.model.CModelException;
88
import org.eclipse.cdt.core.model.CModelException;
63
import org.eclipse.cdt.core.model.CoreModel;
89
import org.eclipse.cdt.core.model.CoreModel;
64
import org.eclipse.cdt.core.model.ICElement;
90
import org.eclipse.cdt.core.model.ICElement;
Lines 86-102 Link Here
86
 * Derived from JDT counterpart.
112
 * Derived from JDT counterpart.
87
 * </p>
113
 * </p>
88
 */
114
 */
89
public class DefaultCFoldingStructureProvider implements ICFoldingStructureProvider {
115
public class DefaultCFoldingStructureProvider implements
116
		ICFoldingStructureProvider {
90
117
91
	/**
118
	/**
92
	 * Listen to cursor position changes.
119
	 * Listen to cursor position changes.
93
	 */
120
	 */
94
	private final class SelectionListener implements ISelectionChangedListener {
121
	private final class SelectionListener implements ISelectionChangedListener {
95
		public void selectionChanged(SelectionChangedEvent event) {
122
		public void selectionChanged(SelectionChangedEvent event) {
96
			ISelection s= event.getSelection();
123
			ISelection s = event.getSelection();
97
			if (s instanceof ITextSelection) {
124
			if (s instanceof ITextSelection) {
98
				ITextSelection selection= (ITextSelection)event.getSelection();
125
				ITextSelection selection = (ITextSelection) event
99
				fCursorPosition= selection.getOffset();
126
						.getSelection();
127
				fCursorPosition = selection.getOffset();
100
			}
128
			}
101
		}
129
		}
102
	}
130
	}
Lines 104-148 Link Here
104
	/**
132
	/**
105
	 * Reconcile annotation positions from preprocessor branches.
133
	 * Reconcile annotation positions from preprocessor branches.
106
	 */
134
	 */
107
	private class PreprocessorBranchesReconciler implements ICReconcilingListener {
135
	private class PreprocessorBranchesReconciler implements
136
			ICReconcilingListener {
108
		volatile boolean fReconciling;
137
		volatile boolean fReconciling;
109
138
110
		/*
139
		/*
111
		 * @see org.eclipse.cdt.internal.ui.text.ICReconcilingListener#aboutToBeReconciled()
140
		 * @see org.eclipse.cdt.internal.ui.text.ICReconcilingListener#aboutToBeReconciled()
112
		 */
141
		 */
113
		public void aboutToBeReconciled() {
142
		public void aboutToBeReconciled() {
114
			
143
115
		}
144
		}
116
145
117
		/*
146
		/*
118
		 * @see org.eclipse.cdt.internal.ui.text.ICReconcilingListener#reconciled(IASTTranslationUnit, boolean, IProgressMonitor)
147
		 * @see org.eclipse.cdt.internal.ui.text.ICReconcilingListener#reconciled(IASTTranslationUnit,
148
		 *      boolean, IProgressMonitor)
119
		 */
149
		 */
120
		public void reconciled(IASTTranslationUnit ast, boolean force, IProgressMonitor progressMonitor) {
150
		public void reconciled(IASTTranslationUnit ast, boolean force,
151
				IProgressMonitor progressMonitor) {
121
			if (fInput == null || fReconciling) {
152
			if (fInput == null || fReconciling) {
122
				return;
153
				return;
123
			}
154
			}
124
			if (fPreprocessorBranchFoldingEnabled && ast == null) {
155
			if (fPreprocessorBranchFoldingEnabled && ast == null) {
125
				return;
156
				return;
126
			}
157
			}
127
			fReconciling= true;
158
			fReconciling = true;
128
			try {
159
			try {
129
				FoldingStructureComputationContext ctx= createContext(fInitialReconcilePending);
160
				FoldingStructureComputationContext ctx = createContext(fInitialReconcilePending);
130
				fInitialReconcilePending= false;
161
				fInitialReconcilePending = false;
131
				if (ctx != null) {
162
				if (ctx != null) {
132
					ctx.fAST= ast;
163
					ctx.fAST = ast;
133
					update(ctx);
164
					update(ctx);
134
				}
165
				}
135
			} finally {
166
			} finally {
136
				fReconciling= false;
167
				fReconciling = false;
137
			}
168
			}
138
		}
169
		}
139
170
140
	}
171
	}
141
172
142
143
	/**
173
	/**
144
	 * A context that contains the information needed to compute the folding structure of an
174
	 * A context that contains the information needed to compute the folding
145
	 * {@link ITranslationUnit}. Computed folding regions are collected via
175
	 * structure of an {@link ITranslationUnit}. Computed folding regions are
176
	 * collected via
146
	 * {@linkplain #addProjectionRange(DefaultCFoldingStructureProvider.CProjectionAnnotation, Position) addProjectionRange}.
177
	 * {@linkplain #addProjectionRange(DefaultCFoldingStructureProvider.CProjectionAnnotation, Position) addProjectionRange}.
147
	 */
178
	 */
148
	protected final class FoldingStructureComputationContext {
179
	protected final class FoldingStructureComputationContext {
Lines 152-178 Link Here
152
183
153
		private ISourceReference fFirstType;
184
		private ISourceReference fFirstType;
154
		private boolean fHasHeaderComment;
185
		private boolean fHasHeaderComment;
155
		private LinkedHashMap fMap= new LinkedHashMap();
186
		private LinkedHashMap fMap = new LinkedHashMap();
156
		private IASTTranslationUnit fAST;
187
		private IASTTranslationUnit fAST;
157
188
158
		FoldingStructureComputationContext(IDocument document, ProjectionAnnotationModel model, boolean allowCollapsing) {
189
		FoldingStructureComputationContext(IDocument document,
190
				ProjectionAnnotationModel model, boolean allowCollapsing) {
159
			Assert.isNotNull(document);
191
			Assert.isNotNull(document);
160
			Assert.isNotNull(model);
192
			Assert.isNotNull(model);
161
			fDocument= document;
193
			fDocument = document;
162
			fModel= model;
194
			fModel = model;
163
			fAllowCollapsing= allowCollapsing;
195
			fAllowCollapsing = allowCollapsing;
164
		}
196
		}
165
		
197
166
		void setFirstType(ISourceReference reference) {
198
		void setFirstType(ISourceReference reference) {
167
			if (hasFirstType())
199
			if (hasFirstType())
168
				throw new IllegalStateException();
200
				throw new IllegalStateException();
169
			fFirstType= reference;
201
			fFirstType = reference;
170
		}
202
		}
171
		
203
172
		boolean hasFirstType() {
204
		boolean hasFirstType() {
173
			return fFirstType != null;
205
			return fFirstType != null;
174
		}
206
		}
175
		
207
176
		ISourceReference getFirstType() {
208
		ISourceReference getFirstType() {
177
			return fFirstType;
209
			return fFirstType;
178
		}
210
		}
Lines 182-198 Link Here
182
		}
214
		}
183
215
184
		void setHasHeaderComment() {
216
		void setHasHeaderComment() {
185
			fHasHeaderComment= true;
217
			fHasHeaderComment = true;
186
		}
218
		}
187
		
219
188
		/**
220
		/**
189
		 * Returns <code>true</code> if newly created folding regions may be collapsed,
221
		 * Returns <code>true</code> if newly created folding regions may be
190
		 * <code>false</code> if not. This is usually <code>false</code> when updating the
222
		 * collapsed, <code>false</code> if not. This is usually
191
		 * folding structure while typing; it may be <code>true</code> when computing or restoring
223
		 * <code>false</code> when updating the folding structure while
192
		 * the initial folding structure.
224
		 * typing; it may be <code>true</code> when computing or restoring the
225
		 * initial folding structure.
193
		 * 
226
		 * 
194
		 * @return <code>true</code> if newly created folding regions may be collapsed,
227
		 * @return <code>true</code> if newly created folding regions may be
195
		 *         <code>false</code> if not
228
		 *         collapsed, <code>false</code> if not
196
		 */
229
		 */
197
		public boolean allowCollapsing() {
230
		public boolean allowCollapsing() {
198
			return fAllowCollapsing;
231
			return fAllowCollapsing;
Lines 210-225 Link Here
210
		ProjectionAnnotationModel getModel() {
243
		ProjectionAnnotationModel getModel() {
211
			return fModel;
244
			return fModel;
212
		}
245
		}
213
		
246
214
		/**
247
		/**
215
		 * Adds a projection (folding) region to this context. The created annotation / position
248
		 * Adds a projection (folding) region to this context. The created
216
		 * pair will be added to the {@link ProjectionAnnotationModel} of the
249
		 * annotation / position pair will be added to the
217
		 * {@link ProjectionViewer} of the editor.
250
		 * {@link ProjectionAnnotationModel} of the {@link ProjectionViewer} of
251
		 * the editor.
218
		 * 
252
		 * 
219
		 * @param annotation the annotation to add
253
		 * @param annotation
220
		 * @param position the corresponding position
254
		 *            the annotation to add
255
		 * @param position
256
		 *            the corresponding position
221
		 */
257
		 */
222
		public void addProjectionRange(CProjectionAnnotation annotation, Position position) {
258
		public void addProjectionRange(CProjectionAnnotation annotation,
259
				Position position) {
223
			fMap.put(annotation, position);
260
			fMap.put(annotation, position);
224
		}
261
		}
225
262
Lines 293-326 Link Here
293
			return fAST;
330
			return fAST;
294
		}
331
		}
295
	}
332
	}
296
	
297
333
298
	private static class CProjectionAnnotation extends ProjectionAnnotation {
334
	private static class CProjectionAnnotation extends ProjectionAnnotation {
299
335
300
		public final static int COMMENT= 1;
336
		public final static int COMMENT = 1;
301
		public final static int BRANCH= 2;
337
		public final static int BRANCH = 2;
302
		
338
303
		private Object fKey;
339
		private Object fKey;
304
		private int fCategory;
340
		private int fCategory;
305
		
341
306
		public CProjectionAnnotation(boolean isCollapsed, Object key, boolean isComment) {
342
		public CProjectionAnnotation(boolean isCollapsed, Object key,
343
				boolean isComment) {
307
			this(isCollapsed, key, isComment ? COMMENT : 0);
344
			this(isCollapsed, key, isComment ? COMMENT : 0);
308
		}
345
		}
309
		
346
310
		public CProjectionAnnotation(boolean isCollapsed, Object key, int category) {
347
		public CProjectionAnnotation(boolean isCollapsed, Object key,
348
				int category) {
311
			super(isCollapsed);
349
			super(isCollapsed);
312
			fKey= key;
350
			fKey = key;
313
			fCategory= category;
351
			fCategory = category;
314
		}
352
		}
315
		
353
316
		public Object getElement() {
354
		public Object getElement() {
317
			return fKey;
355
			return fKey;
318
		}
356
		}
319
		
357
320
		public void setElement(Object element) {
358
		public void setElement(Object element) {
321
			fKey= element;
359
			fKey = element;
322
		}
360
		}
323
		
361
324
		public int getCategory() {
362
		public int getCategory() {
325
			return fCategory;
363
			return fCategory;
326
		}
364
		}
Lines 332-369 Link Here
332
		public boolean isComment() {
370
		public boolean isComment() {
333
			return fCategory == COMMENT;
371
			return fCategory == COMMENT;
334
		}
372
		}
335
		
373
336
		public void setIsComment(boolean isComment) {
374
		public void setIsComment(boolean isComment) {
337
			fCategory= isComment ? COMMENT : 0;
375
			fCategory = isComment ? COMMENT : 0;
338
		}
376
		}
377
339
		/*
378
		/*
340
		 * @see java.lang.Object#toString()
379
		 * @see java.lang.Object#toString()
341
		 */
380
		 */
342
		public String toString() {
381
		public String toString() {
343
			return "CProjectionAnnotation:\n" + //$NON-NLS-1$
382
			return "CProjectionAnnotation:\n" + //$NON-NLS-1$
344
					"\tkey: \t"+ fKey + "\n" + //$NON-NLS-1$ //$NON-NLS-2$
383
					"\tkey: \t" + fKey + "\n" + //$NON-NLS-1$ //$NON-NLS-2$
345
					"\tcollapsed: \t" + isCollapsed() + "\n" + //$NON-NLS-1$ //$NON-NLS-2$
384
					"\tcollapsed: \t" + isCollapsed() + "\n" + //$NON-NLS-1$ //$NON-NLS-2$
346
					"\tcomment: \t" + isComment() + "\n"; //$NON-NLS-1$ //$NON-NLS-2$
385
					"\tcomment: \t" + isComment() + "\n"; //$NON-NLS-1$ //$NON-NLS-2$
347
		}
386
		}
348
	}
387
	}
349
	
350
388
351
	private static final class Tuple {
389
	private static final class Tuple {
352
		CProjectionAnnotation annotation;
390
		CProjectionAnnotation annotation;
353
		Position position;
391
		Position position;
392
354
		Tuple(CProjectionAnnotation annotation, Position position) {
393
		Tuple(CProjectionAnnotation annotation, Position position) {
355
			this.annotation= annotation;
394
			this.annotation = annotation;
356
			this.position= position;
395
			this.position = position;
357
		}
396
		}
358
	}
397
	}
359
398
360
	
361
	/**
399
	/**
362
	 * Projection position that will return two foldable regions: one folding away
400
	 * Projection position that will return two foldable regions: one folding
363
	 * the region from after the '/*' to the beginning of the content, the other
401
	 * away the region from after the '/*' to the beginning of the content, the
364
	 * from after the first content line until after the comment.
402
	 * other from after the first content line until after the comment.
365
	 */
403
	 */
366
	private static final class CommentPosition extends Position implements IProjectionPosition {
404
	private static final class CommentPosition extends Position implements
405
			IProjectionPosition {
367
		CommentPosition(int offset, int length) {
406
		CommentPosition(int offset, int length) {
368
			super(offset, length);
407
			super(offset, length);
369
		}
408
		}
Lines 371-401 Link Here
371
		/*
410
		/*
372
		 * @see org.eclipse.jface.text.source.projection.IProjectionPosition#computeFoldingRegions(org.eclipse.jface.text.IDocument)
411
		 * @see org.eclipse.jface.text.source.projection.IProjectionPosition#computeFoldingRegions(org.eclipse.jface.text.IDocument)
373
		 */
412
		 */
374
		public IRegion[] computeProjectionRegions(IDocument document) throws BadLocationException {
413
		public IRegion[] computeProjectionRegions(IDocument document)
375
			DocumentCharacterIterator sequence= new DocumentCharacterIterator(document, offset, offset + length);
414
				throws BadLocationException {
376
			int prefixEnd= 0;
415
			DocumentCharacterIterator sequence = new DocumentCharacterIterator(
377
			int contentStart= findFirstContent(sequence, prefixEnd);
416
					document, offset, offset + length);
378
417
			int prefixEnd = 0;
379
			int firstLine= document.getLineOfOffset(offset + prefixEnd);
418
			int contentStart = findFirstContent(sequence, prefixEnd);
380
			int captionLine= document.getLineOfOffset(offset + contentStart);
419
381
			int lastLine= document.getLineOfOffset(offset + length);
420
			int firstLine = document.getLineOfOffset(offset + prefixEnd);
382
421
			int captionLine = document.getLineOfOffset(offset + contentStart);
383
			Assert.isTrue(firstLine <= captionLine, "first folded line is greater than the caption line"); //$NON-NLS-1$
422
			int lastLine = document.getLineOfOffset(offset + length);
384
			Assert.isTrue(captionLine <= lastLine, "caption line is greater than the last folded line"); //$NON-NLS-1$
423
424
			Assert.isTrue(firstLine <= captionLine,
425
					"first folded line is greater than the caption line"); //$NON-NLS-1$
426
			Assert.isTrue(captionLine <= lastLine,
427
					"caption line is greater than the last folded line"); //$NON-NLS-1$
385
428
386
			IRegion preRegion;
429
			IRegion preRegion;
387
			if (firstLine < captionLine) {
430
			if (firstLine < captionLine) {
388
				int preOffset= document.getLineOffset(firstLine);
431
				int preOffset = document.getLineOffset(firstLine);
389
				IRegion preEndLineInfo= document.getLineInformation(captionLine);
432
				IRegion preEndLineInfo = document
390
				int preEnd= preEndLineInfo.getOffset();
433
						.getLineInformation(captionLine);
391
				preRegion= new Region(preOffset, preEnd - preOffset);
434
				int preEnd = preEndLineInfo.getOffset();
435
				preRegion = new Region(preOffset, preEnd - preOffset);
392
			} else {
436
			} else {
393
				preRegion= null;
437
				preRegion = null;
394
			}
438
			}
395
439
396
			if (captionLine < lastLine) {
440
			if (captionLine < lastLine) {
397
				int postOffset= document.getLineOffset(captionLine + 1);
441
				int postOffset = document.getLineOffset(captionLine + 1);
398
				IRegion postRegion= new Region(postOffset, offset + length - postOffset);
442
				IRegion postRegion = new Region(postOffset, offset + length
443
						- postOffset);
399
444
400
				if (preRegion == null)
445
				if (preRegion == null)
401
					return new IRegion[] { postRegion };
446
					return new IRegion[] { postRegion };
Lines 410-425 Link Here
410
		}
455
		}
411
456
412
		/**
457
		/**
413
		 * Finds the offset of the first identifier part within <code>content</code>.
458
		 * Finds the offset of the first identifier part within
414
		 * Returns 0 if none is found.
459
		 * <code>content</code>. Returns 0 if none is found.
415
		 *
460
		 * 
416
		 * @param content the content to search
461
		 * @param content
417
		 * @return the first index of a unicode identifier part, or zero if none can
462
		 *            the content to search
418
		 *         be found
463
		 * @return the first index of a unicode identifier part, or zero if none
464
		 *         can be found
419
		 */
465
		 */
420
		private int findFirstContent(final CharSequence content, int prefixEnd) {
466
		private int findFirstContent(final CharSequence content, int prefixEnd) {
421
			int lenght= content.length();
467
			int lenght = content.length();
422
			for (int i= prefixEnd; i < lenght; i++) {
468
			for (int i = prefixEnd; i < lenght; i++) {
423
				if (Character.isUnicodeIdentifierPart(content.charAt(i)))
469
				if (Character.isUnicodeIdentifierPart(content.charAt(i)))
424
					return i;
470
					return i;
425
			}
471
			}
Lines 430-506 Link Here
430
		 * @see org.eclipse.jface.text.source.projection.IProjectionPosition#computeCaptionOffset(org.eclipse.jface.text.IDocument)
476
		 * @see org.eclipse.jface.text.source.projection.IProjectionPosition#computeCaptionOffset(org.eclipse.jface.text.IDocument)
431
		 */
477
		 */
432
		public int computeCaptionOffset(IDocument document) {
478
		public int computeCaptionOffset(IDocument document) {
433
//			return 0;
479
			// return 0;
434
			DocumentCharacterIterator sequence= new DocumentCharacterIterator(document, offset, offset + length);
480
			DocumentCharacterIterator sequence = new DocumentCharacterIterator(
481
					document, offset, offset + length);
435
			return findFirstContent(sequence, 0);
482
			return findFirstContent(sequence, 0);
436
		}
483
		}
437
	}
484
	}
438
485
439
	/**
486
	/**
440
	 * Projection position that will return two foldable regions: one folding away
487
	 * Projection position that will return two foldable regions: one folding
441
	 * the lines before the one containing the simple name of the C element, one
488
	 * away the lines before the one containing the simple name of the C
442
	 * folding away any lines after the caption.
489
	 * element, one folding away any lines after the caption.
443
	 */
490
	 */
444
	private static final class CElementPosition extends Position implements IProjectionPosition {
491
	private static final class CElementPosition extends Position implements
492
			IProjectionPosition {
445
493
446
		private ICElement fElement;
494
		private ICElement fElement;
447
495
448
		public CElementPosition(int offset, int length, ICElement element) {
496
		public CElementPosition(int offset, int length, ICElement element) {
449
			super(offset, length);
497
			super(offset, length);
450
			Assert.isNotNull(element);
498
			Assert.isNotNull(element);
451
			fElement= element;
499
			fElement = element;
452
		}
500
		}
453
		
501
454
		public void setElement(ICElement member) {
502
		public void setElement(ICElement member) {
455
			Assert.isNotNull(member);
503
			Assert.isNotNull(member);
456
			fElement= member;
504
			fElement = member;
457
		}
505
		}
458
		
506
459
		/*
507
		/*
460
		 * @see org.eclipse.jface.text.source.projection.IProjectionPosition#computeFoldingRegions(org.eclipse.jface.text.IDocument)
508
		 * @see org.eclipse.jface.text.source.projection.IProjectionPosition#computeFoldingRegions(org.eclipse.jface.text.IDocument)
461
		 */
509
		 */
462
		public IRegion[] computeProjectionRegions(IDocument document) throws BadLocationException {
510
		public IRegion[] computeProjectionRegions(IDocument document)
463
			int nameStart= offset;
511
				throws BadLocationException {
512
			int nameStart = offset;
464
			try {
513
			try {
465
				/* The member's name range may not be correct. However,
514
				/*
515
				 * The member's name range may not be correct. However,
466
				 * reconciling would trigger another element delta which would
516
				 * reconciling would trigger another element delta which would
467
				 * lead to reentrant situations. Therefore, we optimistically
517
				 * lead to reentrant situations. Therefore, we optimistically
468
				 * assume that the name range is correct, but double check the
518
				 * assume that the name range is correct, but double check the
469
				 * received lines below. */
519
				 * received lines below.
520
				 */
470
				if (fElement instanceof ISourceReference) {
521
				if (fElement instanceof ISourceReference) {
471
					ISourceRange sourceRange= ((ISourceReference) fElement).getSourceRange();
522
					ISourceRange sourceRange = ((ISourceReference) fElement)
523
							.getSourceRange();
472
					if (sourceRange != null)
524
					if (sourceRange != null)
473
						nameStart= sourceRange.getIdStartPos();
525
						nameStart = sourceRange.getIdStartPos();
474
				}
526
				}
475
			} catch (CModelException e) {
527
			} catch (CModelException e) {
476
				// ignore and use default
528
				// ignore and use default
477
			}
529
			}
478
530
479
			int firstLine= document.getLineOfOffset(offset);
531
			int firstLine = document.getLineOfOffset(offset);
480
			int captionLine= document.getLineOfOffset(nameStart);
532
			int captionLine = document.getLineOfOffset(nameStart);
481
			int lastLine= document.getLineOfOffset(offset + length);
533
			int lastLine = document.getLineOfOffset(offset + length);
482
534
483
			/* see comment above - adjust the caption line to be inside the
535
			/*
536
			 * see comment above - adjust the caption line to be inside the
484
			 * entire folded region, and rely on later element deltas to correct
537
			 * entire folded region, and rely on later element deltas to correct
485
			 * the name range. */
538
			 * the name range.
539
			 */
486
			if (captionLine < firstLine)
540
			if (captionLine < firstLine)
487
				captionLine= firstLine;
541
				captionLine = firstLine;
488
			if (captionLine > lastLine)
542
			if (captionLine > lastLine)
489
				captionLine= lastLine;
543
				captionLine = lastLine;
490
544
491
			IRegion preRegion;
545
			IRegion preRegion;
492
			if (firstLine < captionLine) {
546
			if (firstLine < captionLine) {
493
				int preOffset= document.getLineOffset(firstLine);
547
				int preOffset = document.getLineOffset(firstLine);
494
				IRegion preEndLineInfo= document.getLineInformation(captionLine);
548
				IRegion preEndLineInfo = document
495
				int preEnd= preEndLineInfo.getOffset();
549
						.getLineInformation(captionLine);
496
				preRegion= new Region(preOffset, preEnd - preOffset);
550
				int preEnd = preEndLineInfo.getOffset();
551
				preRegion = new Region(preOffset, preEnd - preOffset);
497
			} else {
552
			} else {
498
				preRegion= null;
553
				preRegion = null;
499
			}
554
			}
500
555
501
			if (captionLine < lastLine) {
556
			if (captionLine < lastLine) {
502
				int postOffset= document.getLineOffset(captionLine + 1);
557
				int postOffset = document.getLineOffset(captionLine + 1);
503
				IRegion postRegion= new Region(postOffset, offset + length - postOffset);
558
				IRegion postRegion = new Region(postOffset, offset + length
559
						- postOffset);
504
560
505
				if (preRegion == null)
561
				if (preRegion == null)
506
					return new IRegion[] { postRegion };
562
					return new IRegion[] { postRegion };
Lines 517-530 Link Here
517
		/*
573
		/*
518
		 * @see org.eclipse.jface.text.source.projection.IProjectionPosition#computeCaptionOffset(org.eclipse.jface.text.IDocument)
574
		 * @see org.eclipse.jface.text.source.projection.IProjectionPosition#computeCaptionOffset(org.eclipse.jface.text.IDocument)
519
		 */
575
		 */
520
		public int computeCaptionOffset(IDocument document) throws BadLocationException {
576
		public int computeCaptionOffset(IDocument document)
521
			int nameStart= offset;
577
				throws BadLocationException {
578
			int nameStart = offset;
522
			try {
579
			try {
523
				// need a reconcile here?
580
				// need a reconcile here?
524
				if (fElement instanceof ISourceReference) {
581
				if (fElement instanceof ISourceReference) {
525
					ISourceRange sourceRange= ((ISourceReference) fElement).getSourceRange();
582
					ISourceRange sourceRange = ((ISourceReference) fElement)
583
							.getSourceRange();
526
					if (sourceRange != null)
584
					if (sourceRange != null)
527
						nameStart= sourceRange.getIdStartPos();
585
						nameStart = sourceRange.getIdStartPos();
528
				}
586
				}
529
			} catch (CModelException e) {
587
			} catch (CModelException e) {
530
				// ignore and use default
588
				// ignore and use default
Lines 534-540 Link Here
534
		}
592
		}
535
593
536
	}
594
	}
537
	
595
538
	/**
596
	/**
539
	 * Internal projection listener.
597
	 * Internal projection listener.
540
	 */
598
	 */
Lines 544-567 Link Here
544
		/**
602
		/**
545
		 * Registers the listener with the viewer.
603
		 * Registers the listener with the viewer.
546
		 * 
604
		 * 
547
		 * @param viewer the viewer to register a listener with
605
		 * @param viewer
606
		 *            the viewer to register a listener with
548
		 */
607
		 */
549
		public ProjectionListener(ProjectionViewer viewer) {
608
		public ProjectionListener(ProjectionViewer viewer) {
550
			Assert.isLegal(viewer != null);
609
			Assert.isLegal(viewer != null);
551
			fViewer= viewer;
610
			fViewer = viewer;
552
			fViewer.addProjectionListener(this);
611
			fViewer.addProjectionListener(this);
553
		}
612
		}
554
		
613
555
		/**
614
		/**
556
		 * Disposes of this listener and removes the projection listener from the viewer.
615
		 * Disposes of this listener and removes the projection listener from
616
		 * the viewer.
557
		 */
617
		 */
558
		public void dispose() {
618
		public void dispose() {
559
			if (fViewer != null) {
619
			if (fViewer != null) {
560
				fViewer.removeProjectionListener(this);
620
				fViewer.removeProjectionListener(this);
561
				fViewer= null;
621
				fViewer = null;
562
			}
622
			}
563
		}
623
		}
564
		
624
565
		/*
625
		/*
566
		 * @see org.eclipse.jface.text.source.projection.IProjectionListener#projectionEnabled()
626
		 * @see org.eclipse.jface.text.source.projection.IProjectionListener#projectionEnabled()
567
		 */
627
		 */
Lines 578-590 Link Here
578
	}
638
	}
579
639
580
	/**
640
	/**
581
	 * Implementation of <code>IRegion</code> that can be reused
641
	 * Implementation of <code>IRegion</code> that can be reused by setting
582
	 * by setting the offset and the length.
642
	 * the offset and the length.
583
	 */
643
	 */
584
	private static class ModifiableRegion extends Position implements IRegion {
644
	private static class ModifiableRegion extends Position implements IRegion {
585
		ModifiableRegion() {
645
		ModifiableRegion() {
586
			super();
646
			super();
587
		}
647
		}
648
588
		ModifiableRegion(int offset, int length) {
649
		ModifiableRegion(int offset, int length) {
589
			super(offset, length);
650
			super(offset, length);
590
		}
651
		}
Lines 604-610 Link Here
604
		 */
665
		 */
605
		Branch(int offset, boolean taken) {
666
		Branch(int offset, boolean taken) {
606
			super(offset, 0);
667
			super(offset, 0);
607
			fTaken= taken;
668
			fTaken = taken;
608
		}
669
		}
609
670
610
		/**
671
		/**
Lines 614-620 Link Here
614
		 */
675
		 */
615
		Branch(int offset, int length, boolean taken) {
676
		Branch(int offset, int length, boolean taken) {
616
			super(offset, length);
677
			super(offset, length);
617
			fTaken= taken;
678
			fTaken = taken;
618
		}
679
		}
619
680
620
		public void setEndOffset(int endOffset) {
681
		public void setEndOffset(int endOffset) {
Lines 626-685 Link Here
626
		}
687
		}
627
688
628
		public void setInclusive(boolean inclusive) {
689
		public void setInclusive(boolean inclusive) {
629
			fInclusive= inclusive;
690
			fInclusive = inclusive;
630
		}
691
		}
631
	}
692
	}
632
693
633
	private final static boolean DEBUG= "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.cdt.ui/debug/folding"));  //$NON-NLS-1$//$NON-NLS-2$;
694
	private final static boolean DEBUG = "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.cdt.ui/debug/folding")); //$NON-NLS-1$//$NON-NLS-2$;
634
695
635
	private ITextEditor fEditor;
696
	private ITextEditor fEditor;
636
	private ProjectionListener fProjectionListener;
697
	private ProjectionListener fProjectionListener;
637
	protected ICElement fInput;
698
	protected ICElement fInput;
638
	private IElementChangedListener fElementListener;
699
	private IElementChangedListener fElementListener;
639
	
700
640
	private boolean fCollapseHeaderComments= true;
701
	private boolean fCollapseHeaderComments = true;
641
	private boolean fCollapseComments= false;
702
	private boolean fCollapseComments = false;
642
	private boolean fCollapseMacros= false;
703
	private boolean fCollapseMacros = false;
643
	private boolean fCollapseFunctions= true;
704
	private boolean fCollapseFunctions = true;
644
	private boolean fCollapseStructures= true;
705
	private boolean fCollapseStructures = true;
645
	private boolean fCollapseMethods= false;
706
	private boolean fCollapseMethods = false;
646
	private boolean fCollapseInactiveCode= true;
707
	private boolean fCollapseInactiveCode = true;
647
	
708
648
	private int fMinCommentLines= 1;
709
	private int fMinCommentLines = 1;
649
	private boolean fPreprocessorBranchFoldingEnabled= true;
710
	private boolean fPreprocessorBranchFoldingEnabled = true;
650
	private boolean fCommentFoldingEnabled= true;
711
	private boolean fStatementsFoldingEnabled = false;
712
	private boolean fCommentFoldingEnabled = true;
651
713
652
	private ICReconcilingListener fReconilingListener;
714
	private ICReconcilingListener fReconilingListener;
653
	boolean fInitialReconcilePending= true;
715
	boolean fInitialReconcilePending = true;
654
716
655
	private int fCursorPosition;
717
	private int fCursorPosition;
656
718
657
	private SelectionListener fSelectionListener;
719
	private SelectionListener fSelectionListener;
658
720
659
660
	/**
721
	/**
661
	 * Creates a new folding provider. It must be
722
	 * Creates a new folding provider. It must be
662
	 * {@link #install(ITextEditor, ProjectionViewer) installed} on an editor/viewer pair before it
723
	 * {@link #install(ITextEditor, ProjectionViewer) installed} on an
663
	 * can be used, and {@link #uninstall() uninstalled} when not used any longer.
724
	 * editor/viewer pair before it can be used, and
725
	 * {@link #uninstall() uninstalled} when not used any longer.
664
	 * <p>
726
	 * <p>
665
	 * The projection state may be reset by calling {@link #initialize()}.
727
	 * The projection state may be reset by calling {@link #initialize()}.
666
	 * </p>
728
	 * </p>
667
	 */
729
	 */
668
	public DefaultCFoldingStructureProvider() {
730
	public DefaultCFoldingStructureProvider() {
669
	}
731
	}
670
	
732
671
	/*
733
	/*
672
	 * @see org.eclipse.cdt.ui.text.folding.ICFoldingStructureProvider#install(org.eclipse.ui.texteditor.ITextEditor, org.eclipse.jface.text.source.projection.ProjectionViewer)
734
	 * @see org.eclipse.cdt.ui.text.folding.ICFoldingStructureProvider#install(org.eclipse.ui.texteditor.ITextEditor,
735
	 *      org.eclipse.jface.text.source.projection.ProjectionViewer)
673
	 */
736
	 */
674
	public void install(ITextEditor editor, ProjectionViewer viewer) {
737
	public void install(ITextEditor editor, ProjectionViewer viewer) {
675
		Assert.isLegal(editor != null);
738
		Assert.isLegal(editor != null);
676
		Assert.isLegal(viewer != null);
739
		Assert.isLegal(viewer != null);
677
740
678
		internalUninstall();
741
		internalUninstall();
679
		
742
680
		if (editor instanceof CEditor) {
743
		if (editor instanceof CEditor) {
681
			fEditor= editor;
744
			fEditor = editor;
682
			fProjectionListener= new ProjectionListener(viewer);
745
			fProjectionListener = new ProjectionListener(viewer);
683
		}
746
		}
684
	}
747
	}
685
748
Lines 689-695 Link Here
689
	public void uninstall() {
752
	public void uninstall() {
690
		internalUninstall();
753
		internalUninstall();
691
	}
754
	}
692
	
755
693
	/**
756
	/**
694
	 * Internal implementation of {@link #uninstall()}.
757
	 * Internal implementation of {@link #uninstall()}.
695
	 */
758
	 */
Lines 697-765 Link Here
697
		if (isInstalled()) {
760
		if (isInstalled()) {
698
			handleProjectionDisabled();
761
			handleProjectionDisabled();
699
			fProjectionListener.dispose();
762
			fProjectionListener.dispose();
700
			fProjectionListener= null;
763
			fProjectionListener = null;
701
			fEditor= null;
764
			fEditor = null;
702
		}
765
		}
703
	}
766
	}
704
767
705
	/**
768
	/**
706
	 * Returns <code>true</code> if the provider is installed, <code>false</code> otherwise.
769
	 * Returns <code>true</code> if the provider is installed,
770
	 * <code>false</code> otherwise.
707
	 * 
771
	 * 
708
	 * @return <code>true</code> if the provider is installed, <code>false</code> otherwise
772
	 * @return <code>true</code> if the provider is installed,
773
	 *         <code>false</code> otherwise
709
	 */
774
	 */
710
	protected final boolean isInstalled() {
775
	protected final boolean isInstalled() {
711
		return fEditor != null;
776
		return fEditor != null;
712
	}
777
	}
713
		
778
714
	/**
779
	/**
715
	 * Called whenever projection is enabled, for example when the viewer issues a
780
	 * Called whenever projection is enabled, for example when the viewer issues
716
	 * {@link IProjectionListener#projectionEnabled() projectionEnabled} message. When the provider
781
	 * a {@link IProjectionListener#projectionEnabled() projectionEnabled}
717
	 * is already enabled when this method is called, it is first
782
	 * message. When the provider is already enabled when this method is called,
718
	 * {@link #handleProjectionDisabled() disabled}.
783
	 * it is first {@link #handleProjectionDisabled() disabled}.
719
	 * <p>
784
	 * <p>
720
	 * Subclasses may extend.
785
	 * Subclasses may extend.
721
	 * </p>
786
	 * </p>
722
	 */
787
	 */
723
	protected void handleProjectionEnabled() {
788
	protected void handleProjectionEnabled() {
724
		if (DEBUG) System.out.println("DefaultCFoldingStructureProvider.handleProjectionEnabled()"); //$NON-NLS-1$
789
		if (DEBUG)
725
		// projectionEnabled messages are not always paired with projectionDisabled
790
			System.out
791
					.println("DefaultCFoldingStructureProvider.handleProjectionEnabled()"); //$NON-NLS-1$
792
		// projectionEnabled messages are not always paired with
793
		// projectionDisabled
726
		// i.e. multiple enabled messages may be sent out.
794
		// i.e. multiple enabled messages may be sent out.
727
		// we have to make sure that we disable first when getting an enable
795
		// we have to make sure that we disable first when getting an enable
728
		// message.
796
		// message.
729
		handleProjectionDisabled();
797
		handleProjectionDisabled();
730
798
731
		if (fEditor instanceof CEditor) {
799
		if (fEditor instanceof CEditor) {
732
			fInitialReconcilePending= true;
800
			fInitialReconcilePending = true;
733
			initialize();
801
			initialize();
734
			fReconilingListener= new PreprocessorBranchesReconciler();
802
			fReconilingListener = new PreprocessorBranchesReconciler();
735
			((CEditor)fEditor).addReconcileListener(fReconilingListener);
803
			((CEditor) fEditor).addReconcileListener(fReconilingListener);
736
			fSelectionListener= new SelectionListener();
804
			fSelectionListener = new SelectionListener();
737
			fEditor.getSelectionProvider().addSelectionChangedListener(fSelectionListener);
805
			fEditor.getSelectionProvider().addSelectionChangedListener(
806
					fSelectionListener);
738
		}
807
		}
739
	}
808
	}
740
809
741
	/**
810
	/**
742
	 * Called whenever projection is disabled, for example when the provider is
811
	 * Called whenever projection is disabled, for example when the provider is
743
	 * {@link #uninstall() uninstalled}, when the viewer issues a
812
	 * {@link #uninstall() uninstalled}, when the viewer issues a
744
	 * {@link IProjectionListener#projectionDisabled() projectionDisabled} message and before
813
	 * {@link IProjectionListener#projectionDisabled() projectionDisabled}
745
	 * {@link #handleProjectionEnabled() enabling} the provider. Implementations must be prepared to
814
	 * message and before {@link #handleProjectionEnabled() enabling} the
746
	 * handle multiple calls to this method even if the provider is already disabled.
815
	 * provider. Implementations must be prepared to handle multiple calls to
816
	 * this method even if the provider is already disabled.
747
	 * <p>
817
	 * <p>
748
	 * Subclasses may extend.
818
	 * Subclasses may extend.
749
	 * </p>
819
	 * </p>
750
	 */
820
	 */
751
	protected void handleProjectionDisabled() {
821
	protected void handleProjectionDisabled() {
752
		if (fElementListener != null) {
822
		if (fElementListener != null) {
753
			CoreModel.getDefault().removeElementChangedListener(fElementListener);
823
			CoreModel.getDefault().removeElementChangedListener(
754
			fElementListener= null;
824
					fElementListener);
825
			fElementListener = null;
755
		}
826
		}
756
		if (fReconilingListener != null) {
827
		if (fReconilingListener != null) {
757
			((CEditor)fEditor).removeReconcileListener(fReconilingListener);
828
			((CEditor) fEditor).removeReconcileListener(fReconilingListener);
758
			fReconilingListener= null;
829
			fReconilingListener = null;
759
		}
830
		}
760
		if (fSelectionListener != null) {
831
		if (fSelectionListener != null) {
761
			fEditor.getSelectionProvider().removeSelectionChangedListener(fSelectionListener);
832
			fEditor.getSelectionProvider().removeSelectionChangedListener(
762
			fSelectionListener= null;
833
					fSelectionListener);
834
			fSelectionListener = null;
763
		}
835
		}
764
	}
836
	}
765
837
Lines 767-873 Link Here
767
	 * @see org.eclipse.cdt.ui.text.folding.ICFoldingStructureProvider#initialize()
839
	 * @see org.eclipse.cdt.ui.text.folding.ICFoldingStructureProvider#initialize()
768
	 */
840
	 */
769
	public final void initialize() {
841
	public final void initialize() {
770
		if (DEBUG) System.out.println("DefaultCFoldingStructureProvider.initialize()"); //$NON-NLS-1$
842
		if (DEBUG)
843
			System.out.println("DefaultCFoldingStructureProvider.initialize()"); //$NON-NLS-1$
771
		update(createInitialContext());
844
		update(createInitialContext());
772
	}
845
	}
773
846
774
	private FoldingStructureComputationContext createInitialContext() {
847
	private FoldingStructureComputationContext createInitialContext() {
775
		initializePreferences();
848
		initializePreferences();
776
		fInput= getInputElement();
849
		fInput = getInputElement();
777
		if (fInput == null)
850
		if (fInput == null)
778
			return null;
851
			return null;
779
		
852
780
		return createContext(true);
853
		return createContext(true);
781
	}
854
	}
782
855
783
	private FoldingStructureComputationContext createContext(boolean allowCollapse) {
856
	private FoldingStructureComputationContext createContext(
857
			boolean allowCollapse) {
784
		if (!isInstalled())
858
		if (!isInstalled())
785
			return null;
859
			return null;
786
		ProjectionAnnotationModel model= getModel();
860
		ProjectionAnnotationModel model = getModel();
787
		if (model == null)
861
		if (model == null)
788
			return null;
862
			return null;
789
		IDocument doc= getDocument();
863
		IDocument doc = getDocument();
790
		if (doc == null)
864
		if (doc == null)
791
			return null;
865
			return null;
792
		
866
793
		return new FoldingStructureComputationContext(doc, model, allowCollapse);
867
		return new FoldingStructureComputationContext(doc, model, allowCollapse);
794
	}
868
	}
795
	
869
796
	private ICElement getInputElement() {
870
	private ICElement getInputElement() {
797
		if (fEditor instanceof CEditor) {
871
		if (fEditor instanceof CEditor) {
798
			return ((CEditor)fEditor).getInputCElement();
872
			return ((CEditor) fEditor).getInputCElement();
799
		}
873
		}
800
		return null;
874
		return null;
801
	}
875
	}
802
876
803
	private void initializePreferences() {
877
	private void initializePreferences() {
804
		IPreferenceStore store= CUIPlugin.getDefault().getPreferenceStore();
878
		IPreferenceStore store = CUIPlugin.getDefault().getPreferenceStore();
805
		fCollapseFunctions= store.getBoolean(PreferenceConstants.EDITOR_FOLDING_FUNCTIONS);
879
		fCollapseFunctions = store
806
		fCollapseStructures= store.getBoolean(PreferenceConstants.EDITOR_FOLDING_STRUCTURES);
880
				.getBoolean(PreferenceConstants.EDITOR_FOLDING_FUNCTIONS);
807
		fCollapseMacros= store.getBoolean(PreferenceConstants.EDITOR_FOLDING_MACROS);
881
		fCollapseStructures = store
808
		fCollapseMethods= store.getBoolean(PreferenceConstants.EDITOR_FOLDING_METHODS);
882
				.getBoolean(PreferenceConstants.EDITOR_FOLDING_STRUCTURES);
809
		fCollapseHeaderComments= store.getBoolean(PreferenceConstants.EDITOR_FOLDING_HEADERS);
883
		fCollapseMacros = store
810
		fCollapseComments= store.getBoolean(PreferenceConstants.EDITOR_FOLDING_COMMENTS);
884
				.getBoolean(PreferenceConstants.EDITOR_FOLDING_MACROS);
811
		fCollapseInactiveCode= store.getBoolean(PreferenceConstants.EDITOR_FOLDING_INACTIVE_CODE);
885
		fCollapseMethods = store
812
		fPreprocessorBranchFoldingEnabled= store.getBoolean(PreferenceConstants.EDITOR_FOLDING_PREPROCESSOR_BRANCHES_ENABLED);
886
				.getBoolean(PreferenceConstants.EDITOR_FOLDING_METHODS);
813
		fCommentFoldingEnabled= true;
887
		fCollapseHeaderComments = store
888
				.getBoolean(PreferenceConstants.EDITOR_FOLDING_HEADERS);
889
		fCollapseComments = store
890
				.getBoolean(PreferenceConstants.EDITOR_FOLDING_COMMENTS);
891
		fCollapseInactiveCode = store
892
				.getBoolean(PreferenceConstants.EDITOR_FOLDING_INACTIVE_CODE);
893
		fPreprocessorBranchFoldingEnabled = store
894
				.getBoolean(PreferenceConstants.EDITOR_FOLDING_PREPROCESSOR_BRANCHES_ENABLED);
895
		fStatementsFoldingEnabled = store
896
				.getBoolean(PreferenceConstants.EDITOR_FOLDING_STATEMENTS);
897
		fCommentFoldingEnabled = true;
814
	}
898
	}
815
899
816
	private void update(FoldingStructureComputationContext ctx) {
900
	private void update(FoldingStructureComputationContext ctx) {
817
	    if (ctx == null)
901
		if (ctx == null)
818
			return;
902
			return;
819
903
820
		if (!fInitialReconcilePending && fSelectionListener != null) {
904
		if (!fInitialReconcilePending && fSelectionListener != null) {
821
			fEditor.getSelectionProvider().removeSelectionChangedListener(fSelectionListener);
905
			fEditor.getSelectionProvider().removeSelectionChangedListener(
822
			fSelectionListener= null;
906
					fSelectionListener);
907
			fSelectionListener = null;
823
		}
908
		}
824
909
825
		Map additions= new HashMap();
910
		Map additions = new HashMap();
826
		List deletions= new ArrayList();
911
		List deletions = new ArrayList();
827
		List updates= new ArrayList();
912
		List updates = new ArrayList();
828
		
913
829
		computeFoldingStructure(ctx);
914
		computeFoldingStructure(ctx);
830
		Map updated= ctx.fMap;
915
		Map updated = ctx.fMap;
831
		Map previous= computeCurrentStructure(ctx);
916
		Map previous = computeCurrentStructure(ctx);
832
917
833
		Iterator e= updated.keySet().iterator();
918
		Iterator e = updated.keySet().iterator();
834
		while (e.hasNext()) {
919
		while (e.hasNext()) {
835
			CProjectionAnnotation newAnnotation= (CProjectionAnnotation) e.next();
920
			CProjectionAnnotation newAnnotation = (CProjectionAnnotation) e
836
			Object key= newAnnotation.getElement();
921
					.next();
837
			Position newPosition= (Position) updated.get(newAnnotation);
922
			Object key = newAnnotation.getElement();
923
			Position newPosition = (Position) updated.get(newAnnotation);
838
924
839
			List annotations= (List) previous.get(key);
925
			List annotations = (List) previous.get(key);
840
			if (annotations == null) {
926
			if (annotations == null) {
841
				if (DEBUG) System.out.println("DefaultCFoldingStructureProvider.update() new annotation " + newAnnotation); //$NON-NLS-1$
927
				if (DEBUG)
928
					System.out
929
							.println("DefaultCFoldingStructureProvider.update() new annotation " + newAnnotation); //$NON-NLS-1$
842
930
843
				additions.put(newAnnotation, newPosition);
931
				additions.put(newAnnotation, newPosition);
844
932
845
			} else {
933
			} else {
846
				Iterator x= annotations.iterator();
934
				Iterator x = annotations.iterator();
847
				boolean matched= false;
935
				boolean matched = false;
848
				while (x.hasNext()) {
936
				while (x.hasNext()) {
849
					Tuple tuple= (Tuple) x.next();
937
					Tuple tuple = (Tuple) x.next();
850
					CProjectionAnnotation existingAnnotation= tuple.annotation;
938
					CProjectionAnnotation existingAnnotation = tuple.annotation;
851
					Position existingPosition= tuple.position;
939
					Position existingPosition = tuple.position;
852
					if (newAnnotation.isComment() == existingAnnotation.isComment()) {
940
					if (newAnnotation.isComment() == existingAnnotation
853
						if (existingPosition != null && (!newPosition.equals(existingPosition) || ctx.allowCollapsing() && existingAnnotation.isCollapsed() != newAnnotation.isCollapsed())) {
941
							.isComment()) {
942
						if (existingPosition != null
943
								&& (!newPosition.equals(existingPosition) || ctx
944
										.allowCollapsing()
945
										&& existingAnnotation.isCollapsed() != newAnnotation
946
												.isCollapsed())) {
854
							existingPosition.setOffset(newPosition.getOffset());
947
							existingPosition.setOffset(newPosition.getOffset());
855
							existingPosition.setLength(newPosition.getLength());
948
							existingPosition.setLength(newPosition.getLength());
856
							if (ctx.allowCollapsing() && existingAnnotation.isCollapsed() != newAnnotation.isCollapsed())
949
							if (ctx.allowCollapsing()
857
								if (DEBUG) System.out.println("DefaultCFoldingStructureProvider.update() change annotation " + newAnnotation); //$NON-NLS-1$
950
									&& existingAnnotation.isCollapsed() != newAnnotation
858
								if (newAnnotation.isCollapsed())
951
											.isCollapsed())
859
									existingAnnotation.markCollapsed();
952
								if (DEBUG)
860
								else
953
									System.out
861
									existingAnnotation.markExpanded();
954
											.println("DefaultCFoldingStructureProvider.update() change annotation " + newAnnotation); //$NON-NLS-1$
955
							if (newAnnotation.isCollapsed())
956
								existingAnnotation.markCollapsed();
957
							else
958
								existingAnnotation.markExpanded();
862
							updates.add(existingAnnotation);
959
							updates.add(existingAnnotation);
863
						}
960
						}
864
						matched= true;
961
						matched = true;
865
						x.remove();
962
						x.remove();
866
						break;
963
						break;
867
					}
964
					}
868
				}
965
				}
869
				if (!matched) {
966
				if (!matched) {
870
					if (DEBUG) System.out.println("DefaultCFoldingStructureProvider.update() new annotation " + newAnnotation); //$NON-NLS-1$
967
					if (DEBUG)
968
						System.out
969
								.println("DefaultCFoldingStructureProvider.update() new annotation " + newAnnotation); //$NON-NLS-1$
871
970
872
					additions.put(newAnnotation, newPosition);
971
					additions.put(newAnnotation, newPosition);
873
				}
972
				}
Lines 876-948 Link Here
876
			}
975
			}
877
		}
976
		}
878
977
879
		e= previous.values().iterator();
978
		e = previous.values().iterator();
880
		while (e.hasNext()) {
979
		while (e.hasNext()) {
881
			List list= (List) e.next();
980
			List list = (List) e.next();
882
			int size= list.size();
981
			int size = list.size();
883
			for (int i= 0; i < size; i++) {
982
			for (int i = 0; i < size; i++) {
884
				CProjectionAnnotation annotation= ((Tuple) list.get(i)).annotation;
983
				CProjectionAnnotation annotation = ((Tuple) list.get(i)).annotation;
885
				if (DEBUG) System.out.println("DefaultCFoldingStructureProvider.update() deleted annotation " + annotation); //$NON-NLS-1$
984
				if (DEBUG)
985
					System.out
986
							.println("DefaultCFoldingStructureProvider.update() deleted annotation " + annotation); //$NON-NLS-1$
886
				deletions.add(annotation);
987
				deletions.add(annotation);
887
			}
988
			}
888
		}
989
		}
889
990
890
		match(deletions, additions, updates, ctx);
991
		match(deletions, additions, updates, ctx);
891
992
892
		Annotation[] removals= new Annotation[deletions.size()];
993
		Annotation[] removals = new Annotation[deletions.size()];
893
		deletions.toArray(removals);
994
		deletions.toArray(removals);
894
		Annotation[] changes= new Annotation[updates.size()];
995
		Annotation[] changes = new Annotation[updates.size()];
895
		updates.toArray(changes);
996
		updates.toArray(changes);
896
		if (DEBUG) System.out.println("DefaultCFoldingStructureProvider.update() "+removals.length+" deleted, "+additions.size()+" added, "+changes.length+" changed"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
997
		if (DEBUG)
998
			System.out
999
					.println("DefaultCFoldingStructureProvider.update() " + removals.length + " deleted, " + additions.size() + " added, " + changes.length + " changed"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
897
		ctx.getModel().modifyAnnotations(removals, additions, changes);
1000
		ctx.getModel().modifyAnnotations(removals, additions, changes);
898
    }
1001
	}
899
1002
900
	/**
1003
	/**
901
	 * Matches deleted annotations to changed or added ones. A deleted
1004
	 * Matches deleted annotations to changed or added ones. A deleted
902
	 * annotation/position tuple that has a matching addition / change
1005
	 * annotation/position tuple that has a matching addition / change is
903
	 * is updated and marked as changed. The matching tuple is not added
1006
	 * updated and marked as changed. The matching tuple is not added (for
904
	 * (for additions) or marked as deletion instead (for changes). The
1007
	 * additions) or marked as deletion instead (for changes). The result is
905
	 * result is that more annotations are changed and fewer get
1008
	 * that more annotations are changed and fewer get deleted/re-added.
906
	 * deleted/re-added.
907
	 */
1009
	 */
908
	private void match(List deletions, Map additions, List changes, FoldingStructureComputationContext ctx) {
1010
	private void match(List deletions, Map additions, List changes,
1011
			FoldingStructureComputationContext ctx) {
909
		if (deletions.isEmpty() || (additions.isEmpty() && changes.isEmpty()))
1012
		if (deletions.isEmpty() || (additions.isEmpty() && changes.isEmpty()))
910
			return;
1013
			return;
911
1014
912
		List newDeletions= new ArrayList();
1015
		List newDeletions = new ArrayList();
913
		List newChanges= new ArrayList();
1016
		List newChanges = new ArrayList();
914
1017
915
		Iterator deletionIterator= deletions.iterator();
1018
		Iterator deletionIterator = deletions.iterator();
916
		while (deletionIterator.hasNext()) {
1019
		while (deletionIterator.hasNext()) {
917
			CProjectionAnnotation deleted= (CProjectionAnnotation) deletionIterator.next();
1020
			CProjectionAnnotation deleted = (CProjectionAnnotation) deletionIterator
918
			Position deletedPosition= ctx.getModel().getPosition(deleted);
1021
					.next();
1022
			Position deletedPosition = ctx.getModel().getPosition(deleted);
919
			if (deletedPosition == null)
1023
			if (deletedPosition == null)
920
				continue;
1024
				continue;
921
			
922
			Tuple deletedTuple= new Tuple(deleted, deletedPosition);
923
1025
924
			Tuple match= findMatch(deletedTuple, changes, null, ctx);
1026
			Tuple deletedTuple = new Tuple(deleted, deletedPosition);
925
			boolean addToDeletions= true; 
1027
1028
			Tuple match = findMatch(deletedTuple, changes, null, ctx);
1029
			boolean addToDeletions = true;
926
			if (match == null) {
1030
			if (match == null) {
927
				match= findMatch(deletedTuple, additions.keySet(), additions, ctx);
1031
				match = findMatch(deletedTuple, additions.keySet(), additions,
928
				addToDeletions= false;
1032
						ctx);
1033
				addToDeletions = false;
929
			}
1034
			}
930
			
1035
931
			if (match != null) {
1036
			if (match != null) {
932
				Object element= match.annotation.getElement();
1037
				Object element = match.annotation.getElement();
933
				deleted.setElement(element);
1038
				deleted.setElement(element);
934
				deletedPosition.setLength(match.position.getLength());
1039
				deletedPosition.setLength(match.position.getLength());
935
				if (deletedPosition instanceof CElementPosition && element instanceof ICElement) {
1040
				if (deletedPosition instanceof CElementPosition
936
					CElementPosition cep= (CElementPosition) deletedPosition;
1041
						&& element instanceof ICElement) {
1042
					CElementPosition cep = (CElementPosition) deletedPosition;
937
					cep.setElement((ICElement) element);
1043
					cep.setElement((ICElement) element);
938
				}
1044
				}
939
1045
940
				deletionIterator.remove();
1046
				deletionIterator.remove();
941
				if (DEBUG) System.out.println("DefaultCFoldingStructureProvider.update() changed annotation " + deleted); //$NON-NLS-1$
1047
				if (DEBUG)
1048
					System.out
1049
							.println("DefaultCFoldingStructureProvider.update() changed annotation " + deleted); //$NON-NLS-1$
942
				newChanges.add(deleted);
1050
				newChanges.add(deleted);
943
1051
944
				if (addToDeletions) {
1052
				if (addToDeletions) {
945
					if (DEBUG) System.out.println("DefaultCFoldingStructureProvider.update() deleted annotation " + match.annotation); //$NON-NLS-1$
1053
					if (DEBUG)
1054
						System.out
1055
								.println("DefaultCFoldingStructureProvider.update() deleted annotation " + match.annotation); //$NON-NLS-1$
946
					newDeletions.add(match.annotation);
1056
					newDeletions.add(match.annotation);
947
				}
1057
				}
948
			}
1058
			}
Lines 953-986 Link Here
953
	}
1063
	}
954
1064
955
	/**
1065
	/**
956
	 * Finds a match for <code>tuple</code> in a collection of
1066
	 * Finds a match for <code>tuple</code> in a collection of annotations.
957
	 * annotations. The positions for the
1067
	 * The positions for the <code>CProjectionAnnotation</code> instances in
958
	 * <code>CProjectionAnnotation</code> instances in
959
	 * <code>annotations</code> can be found in the passed
1068
	 * <code>annotations</code> can be found in the passed
960
	 * <code>positionMap</code> or <code>fCachedModel</code> if
1069
	 * <code>positionMap</code> or <code>fCachedModel</code> if
961
	 * <code>positionMap</code> is <code>null</code>.
1070
	 * <code>positionMap</code> is <code>null</code>.
962
	 * <p>
1071
	 * <p>
963
	 * A tuple is said to match another if their annotations have the
1072
	 * A tuple is said to match another if their annotations have the same
964
	 * same comment flag and their position offsets are equal.
1073
	 * comment flag and their position offsets are equal.
965
	 * </p>
1074
	 * </p>
966
	 * <p>
1075
	 * <p>
967
	 * If a match is found, the annotation gets removed from
1076
	 * If a match is found, the annotation gets removed from
968
	 * <code>annotations</code>.
1077
	 * <code>annotations</code>.
969
	 * </p>
1078
	 * </p>
970
	 * 
1079
	 * 
971
	 * @param tuple the tuple for which we want to find a match
1080
	 * @param tuple
972
	 * @param annotations collection of
1081
	 *            the tuple for which we want to find a match
973
	 *        <code>CProjectionAnnotation</code>
1082
	 * @param annotations
974
	 * @param positionMap a <code>Map&lt;Annotation, Position&gt;</code>
1083
	 *            collection of <code>CProjectionAnnotation</code>
975
	 *        or <code>null</code>
1084
	 * @param positionMap
1085
	 *            a <code>Map&lt;Annotation, Position&gt;</code> or
1086
	 *            <code>null</code>
976
	 * @return a matching tuple or <code>null</code> for no match
1087
	 * @return a matching tuple or <code>null</code> for no match
977
	 */
1088
	 */
978
	private Tuple findMatch(Tuple tuple, Collection annotations, Map positionMap, FoldingStructureComputationContext ctx) {
1089
	private Tuple findMatch(Tuple tuple, Collection annotations,
979
		Iterator it= annotations.iterator();
1090
			Map positionMap, FoldingStructureComputationContext ctx) {
1091
		Iterator it = annotations.iterator();
980
		while (it.hasNext()) {
1092
		while (it.hasNext()) {
981
			CProjectionAnnotation annotation= (CProjectionAnnotation) it.next();
1093
			CProjectionAnnotation annotation = (CProjectionAnnotation) it
1094
					.next();
982
			if (tuple.annotation.isComment() == annotation.isComment()) {
1095
			if (tuple.annotation.isComment() == annotation.isComment()) {
983
				Position position= positionMap == null ? ctx.getModel().getPosition(annotation) : (Position) positionMap.get(annotation);
1096
				Position position = positionMap == null ? ctx.getModel()
1097
						.getPosition(annotation) : (Position) positionMap
1098
						.get(annotation);
984
				if (position == null)
1099
				if (position == null)
985
					continue;
1100
					continue;
986
1101
Lines 990-1060 Link Here
990
				}
1105
				}
991
			}
1106
			}
992
		}
1107
		}
993
		
1108
994
		return null;
1109
		return null;
995
	}
1110
	}
996
1111
997
	private Map computeCurrentStructure(FoldingStructureComputationContext ctx) {
1112
	private Map computeCurrentStructure(FoldingStructureComputationContext ctx) {
998
		boolean includeBranches= fPreprocessorBranchFoldingEnabled && ctx.fAST != null;
1113
		boolean includeBranches = fPreprocessorBranchFoldingEnabled
999
		Map map= new HashMap();
1114
				&& ctx.fAST != null;
1000
		ProjectionAnnotationModel model= ctx.getModel();
1115
		Map map = new HashMap();
1001
		Iterator e= model.getAnnotationIterator();
1116
		ProjectionAnnotationModel model = ctx.getModel();
1117
		Iterator e = model.getAnnotationIterator();
1002
		while (e.hasNext()) {
1118
		while (e.hasNext()) {
1003
			Object annotation= e.next();
1119
			Object annotation = e.next();
1004
			if (annotation instanceof CProjectionAnnotation) {
1120
			if (annotation instanceof CProjectionAnnotation) {
1005
				CProjectionAnnotation cAnnotation= (CProjectionAnnotation) annotation;
1121
				CProjectionAnnotation cAnnotation = (CProjectionAnnotation) annotation;
1006
				if (!includeBranches && cAnnotation.getCategory() == CProjectionAnnotation.BRANCH) {
1122
				if (!includeBranches
1123
						&& cAnnotation.getCategory() == CProjectionAnnotation.BRANCH) {
1007
					continue;
1124
					continue;
1008
				}
1125
				}
1009
				Position position= model.getPosition(cAnnotation);
1126
				Position position = model.getPosition(cAnnotation);
1010
				Assert.isNotNull(position);
1127
				Assert.isNotNull(position);
1011
				List list= (List) map.get(cAnnotation.getElement());
1128
				List list = (List) map.get(cAnnotation.getElement());
1012
				if (list == null) {
1129
				if (list == null) {
1013
					list= new ArrayList(2);
1130
					list = new ArrayList(2);
1014
					map.put(cAnnotation.getElement(), list);
1131
					map.put(cAnnotation.getElement(), list);
1015
				}
1132
				}
1016
				list.add(new Tuple(cAnnotation, position));
1133
				list.add(new Tuple(cAnnotation, position));
1017
			}
1134
			}
1018
		}
1135
		}
1019
1136
1020
		Comparator comparator= new Comparator() {
1137
		Comparator comparator = new Comparator() {
1021
			public int compare(Object o1, Object o2) {
1138
			public int compare(Object o1, Object o2) {
1022
				return ((Tuple) o1).position.getOffset() - ((Tuple) o2).position.getOffset();
1139
				return ((Tuple) o1).position.getOffset()
1140
						- ((Tuple) o2).position.getOffset();
1023
			}
1141
			}
1024
		};
1142
		};
1025
		for (Iterator it= map.values().iterator(); it.hasNext();) {
1143
		for (Iterator it = map.values().iterator(); it.hasNext();) {
1026
			List list= (List) it.next();
1144
			List list = (List) it.next();
1027
			Collections.sort(list, comparator);
1145
			Collections.sort(list, comparator);
1028
		}
1146
		}
1029
		return map;
1147
		return map;
1030
	}
1148
	}
1031
	
1032
1149
1033
	private void computeFoldingStructure(final FoldingStructureComputationContext ctx) {
1150
	private void computeFoldingStructure(
1151
			final FoldingStructureComputationContext ctx) {
1034
		if (fCommentFoldingEnabled) {
1152
		if (fCommentFoldingEnabled) {
1035
			// compute comment positions from partitioning
1153
			// compute comment positions from partitioning
1036
			try {
1154
			try {
1037
				IDocument doc= ctx.getDocument();
1155
				IDocument doc = ctx.getDocument();
1038
				ITypedRegion[] partitions = TextUtilities.computePartitioning(doc, ICPartitions.C_PARTITIONING, 0, doc.getLength(), false);
1156
				ITypedRegion[] partitions = TextUtilities.computePartitioning(
1157
						doc, ICPartitions.C_PARTITIONING, 0, doc.getLength(),
1158
						false);
1039
				computeFoldingStructure(partitions, ctx);
1159
				computeFoldingStructure(partitions, ctx);
1040
			} catch (BadLocationException e) {
1160
			} catch (BadLocationException e) {
1041
				// ignore
1161
				// ignore
1042
			}
1162
			}
1043
		}
1163
		}
1044
		if (fPreprocessorBranchFoldingEnabled) {
1164
		if (fPreprocessorBranchFoldingEnabled || fStatementsFoldingEnabled) {
1045
			IASTTranslationUnit ast= ctx.getAST();
1165
			IASTTranslationUnit ast = ctx.getAST();
1046
			if (ast == null) {
1166
			if (ast == null) {
1047
				final ASTProvider astProvider= CUIPlugin.getDefault().getASTProvider();
1167
				final ASTProvider astProvider = CUIPlugin.getDefault()
1048
				IStatus status= astProvider.runOnAST(getInputElement(), ASTProvider.WAIT_ACTIVE_ONLY, null, new ASTCache.ASTRunnable() {
1168
						.getASTProvider();
1049
					public IStatus runOnAST(ILanguage lang, IASTTranslationUnit ast) {
1169
				IStatus status = astProvider.runOnAST(getInputElement(),
1050
						if (ast != null) {
1170
						ASTProvider.WAIT_ACTIVE_ONLY, null,
1051
							ctx.fAST= ast;
1171
						new ASTCache.ASTRunnable() {
1052
							fInitialReconcilePending= false;
1172
							public IStatus runOnAST(ILanguage lang,
1053
							computeFoldingStructure(ast, ctx);
1173
									IASTTranslationUnit ast) {
1054
						}
1174
								if (ast != null) {
1055
						return Status.OK_STATUS;
1175
									ctx.fAST = ast;
1056
					}
1176
									fInitialReconcilePending = false;
1057
				});
1177
									computeFoldingStructure(ast, ctx);
1178
								}
1179
								return Status.OK_STATUS;
1180
							}
1181
						});
1058
				if (status.matches(IStatus.ERROR)) {
1182
				if (status.matches(IStatus.ERROR)) {
1059
					CUIPlugin.getDefault().log(status);
1183
					CUIPlugin.getDefault().log(status);
1060
				}
1184
				}
Lines 1063-1093 Link Here
1063
			}
1187
			}
1064
		}
1188
		}
1065
		if (!fInitialReconcilePending || isConsistent(fInput)) {
1189
		if (!fInitialReconcilePending || isConsistent(fInput)) {
1066
			IParent parent= (IParent) fInput;
1190
			IParent parent = (IParent) fInput;
1067
			try {
1191
			try {
1068
				computeFoldingStructure(parent.getChildren(), ctx);
1192
				computeFoldingStructure(parent.getChildren(), ctx);
1069
			} catch (CModelException x) {
1193
			} catch (CModelException x) {
1070
			}
1194
			}
1071
		}
1195
		}
1072
	}
1196
	}
1073
	
1197
1074
	static boolean isConsistent(ICElement element) {
1198
	static boolean isConsistent(ICElement element) {
1075
		if (element instanceof ITranslationUnit) {
1199
		if (element instanceof ITranslationUnit) {
1076
			try {
1200
			try {
1077
				return ((ITranslationUnit)element).isConsistent();
1201
				return ((ITranslationUnit) element).isConsistent();
1078
			} catch (CModelException exc) {
1202
			} catch (CModelException exc) {
1079
			}
1203
			}
1080
		}
1204
		}
1081
		return false;
1205
		return false;
1082
	}
1206
	}
1083
	
1207
1208
	class ModifiableRegionExtra extends ModifiableRegion {
1209
		/*
1210
		 * A modifiable region with extra information about the region it holds.
1211
		 * It tells us whether or not to include the last line of the region
1212
		 */
1213
		public boolean inclusive;
1214
	}
1215
1216
	/**
1217
	 * Computes folding structure for preprocessor branches for the given AST.
1218
	 * 
1219
	 * @param ast
1220
	 * @param ctx
1221
	 */
1222
	private void computeStatementFoldingStructure(IASTTranslationUnit ast, FoldingStructureComputationContext ctx) {
1223
		final Stack iral = new Stack();
1224
		ast.accept(new ASTVisitor() {
1225
			{
1226
				shouldVisitDeclarations = true;
1227
				shouldVisitEnumerators = true;
1228
				shouldVisitStatements = true;
1229
			}
1230
1231
			public int visit(IASTStatement statement) {
1232
				// if it's not part of the displayed - file, we don't need it
1233
				if (!statement.isPartOfTranslationUnitFile())
1234
					return PROCESS_SKIP;// we neither need its descendants
1235
				try {
1236
					ModifiableRegionExtra mr;
1237
					IASTFileLocation fl;
1238
					if (statement instanceof IASTIfStatement) {
1239
						IASTIfStatement ifstmt = (IASTIfStatement) statement;
1240
						IASTStatement tmp;
1241
						mr = new ModifiableRegionExtra();
1242
						tmp = ifstmt.getThenClause();
1243
						if (tmp==null) return PROCESS_CONTINUE;
1244
						fl = tmp.getFileLocation();
1245
						mr.setLength(fl.getNodeLength());
1246
						mr.setOffset(fl.getNodeOffset());
1247
						mr.inclusive = false;
1248
						tmp = ifstmt.getElseClause();
1249
						if (tmp==null) {
1250
							mr.inclusive = true;
1251
							iral.push(mr);
1252
							return PROCESS_CONTINUE;
1253
						}
1254
						iral.push(mr);
1255
						mr = new ModifiableRegionExtra();
1256
						fl = tmp.getFileLocation();
1257
						mr.setLength(fl.getNodeLength());
1258
						mr.setOffset(fl.getNodeOffset());
1259
						mr.inclusive = true;
1260
						iral.push(mr);
1261
					}
1262
					mr = new ModifiableRegionExtra();
1263
					mr.inclusive = true;
1264
					if (statement instanceof IASTDoStatement)
1265
						mr.inclusive = false;
1266
					if (statement instanceof IASTSwitchStatement) {
1267
						IASTStatement switchstmt = ((IASTSwitchStatement)statement).getBody();
1268
						if (switchstmt instanceof IASTCompoundStatement) {
1269
							IASTStatement[] stmts = ((IASTCompoundStatement)switchstmt).getStatements();
1270
							boolean pushedMR = false;
1271
							for (int i = 0; i < stmts.length; i++) {
1272
								IASTStatement tmpstmt = stmts[i];
1273
								ModifiableRegionExtra tmpmr;
1274
								if (!(tmpstmt instanceof IASTCaseStatement || tmpstmt instanceof IASTDefaultStatement)) {
1275
									if (!pushedMR) return PROCESS_SKIP;
1276
									IASTFileLocation tmpfl = tmpstmt.getFileLocation();
1277
									tmpmr = (ModifiableRegionExtra) iral.peek();
1278
									tmpmr.setLength(tmpfl.getNodeLength()+tmpfl.getNodeOffset()-tmpmr.getOffset());
1279
									if (tmpstmt instanceof IASTBreakStatement) pushedMR = false;
1280
									continue;
1281
								}
1282
								IASTFileLocation tmpfl;
1283
								tmpmr = new ModifiableRegionExtra();
1284
								tmpmr.inclusive = true;
1285
								if (tmpstmt instanceof IASTCaseStatement) {
1286
									IASTCaseStatement casestmt = (IASTCaseStatement) tmpstmt;
1287
									tmpfl = casestmt.getExpression().getFileLocation();
1288
									tmpmr.setOffset(tmpfl.getNodeOffset());
1289
									tmpmr.setLength(tmpfl.getNodeLength());
1290
								} else if (tmpstmt instanceof IASTDefaultStatement) {
1291
									IASTDefaultStatement defstmt = (IASTDefaultStatement) tmpstmt;
1292
									tmpfl = defstmt.getFileLocation();
1293
									tmpmr.setOffset(tmpfl.getNodeOffset()+tmpfl.getNodeLength());
1294
									tmpmr.setLength(0);
1295
								}
1296
								iral.push(tmpmr);
1297
								pushedMR = true;
1298
							}
1299
						}			
1300
					}
1301
					if (statement instanceof IASTForStatement ||
1302
							statement instanceof IASTWhileStatement ||
1303
							statement instanceof IASTDoStatement ||
1304
							statement instanceof IASTSwitchStatement ||
1305
							statement instanceof IASTInitializerList) {
1306
						fl = statement.getFileLocation();
1307
						mr.setLength(fl.getNodeLength());
1308
						mr.setOffset(fl.getNodeOffset());
1309
						iral.push(mr);
1310
					} 
1311
					return PROCESS_CONTINUE;
1312
				} catch (Throwable e) {
1313
					CCorePlugin.log(e);
1314
					return PROCESS_CONTINUE;
1315
				}
1316
			}
1317
			public int visit(IASTDeclaration decl) {
1318
				IASTFileLocation fl = decl.getFileLocation();
1319
				ModifiableRegionExtra mr = new ModifiableRegionExtra();
1320
				mr .setLength(fl.getNodeLength());
1321
				mr.inclusive = true;
1322
				mr.setOffset(fl.getNodeOffset());
1323
				iral.push(mr);
1324
				return PROCESS_CONTINUE;
1325
			}
1326
		});
1327
		while (!iral.empty()) {
1328
			ModifiableRegionExtra mr = (ModifiableRegionExtra) iral.pop();
1329
			IRegion aligned = alignRegion(mr, ctx,mr.inclusive);
1330
			if (aligned != null) {
1331
				Position alignedPos= new Position(aligned.getOffset(), aligned.getLength());
1332
				ctx.addProjectionRange(new CProjectionAnnotation(false, computeKey(mr, ctx), false), alignedPos);
1333
			}
1334
		}
1335
	}
1336
1084
	/**
1337
	/**
1085
	 * Compute folding structure of the preprocessor branches for the given AST.
1338
	 * Compute folding structure of things related to the AST tree. Currently it
1339
	 * computes the folding structure for: preprocessor branches for the given
1340
	 * AST. Also, it computes statements folding (if/else do/while for and
1341
	 * switch)
1086
	 * 
1342
	 * 
1087
	 * @param ast
1343
	 * @param ast
1088
	 * @param ctx
1344
	 * @param ctx
1089
	 */
1345
	 */
1090
	private void computeFoldingStructure(IASTTranslationUnit ast, FoldingStructureComputationContext ctx) {
1346
	private void computeFoldingStructure(IASTTranslationUnit ast,
1347
			FoldingStructureComputationContext ctx) {
1091
		if (ast == null) {
1348
		if (ast == null) {
1092
			return;
1349
			return;
1093
		}
1350
		}
Lines 1095-1104 Link Here
1095
		if (fileName == null) {
1352
		if (fileName == null) {
1096
			return;
1353
			return;
1097
		}
1354
		}
1098
		List branches= new ArrayList();
1355
1356
		if (fStatementsFoldingEnabled)
1357
			computeStatementFoldingStructure(ast, ctx);
1358
1359
		if (fPreprocessorBranchFoldingEnabled)
1360
			computePreprocessorFoldingStructure(ast, ctx, fileName);
1361
	}
1362
1363
	/**
1364
	 * Computes folding structure for preprocessor branches for the given AST.
1365
	 * 
1366
	 * @param ast
1367
	 * @param ctx
1368
	 * @param fileName
1369
	 */
1370
	private void computePreprocessorFoldingStructure(IASTTranslationUnit ast,
1371
			FoldingStructureComputationContext ctx, String fileName) {
1372
		List branches = new ArrayList();
1099
		Stack branchStack = new Stack();
1373
		Stack branchStack = new Stack();
1100
1374
1101
		IASTPreprocessorStatement[] preprocStmts = ast.getAllPreprocessorStatements();
1375
		IASTPreprocessorStatement[] preprocStmts = ast
1376
				.getAllPreprocessorStatements();
1102
1377
1103
		for (int i = 0; i < preprocStmts.length; i++) {
1378
		for (int i = 0; i < preprocStmts.length; i++) {
1104
			IASTPreprocessorStatement statement = preprocStmts[i];
1379
			IASTPreprocessorStatement statement = preprocStmts[i];
Lines 1110-1133 Link Here
1110
			if (nodeLocations.length != 1) {
1385
			if (nodeLocations.length != 1) {
1111
				continue;
1386
				continue;
1112
			}
1387
			}
1113
			IASTNodeLocation stmtLocation= nodeLocations[0];
1388
			IASTNodeLocation stmtLocation = nodeLocations[0];
1114
			if (statement instanceof IASTPreprocessorIfStatement) {
1389
			if (statement instanceof IASTPreprocessorIfStatement) {
1115
				IASTPreprocessorIfStatement ifStmt = (IASTPreprocessorIfStatement)statement;
1390
				IASTPreprocessorIfStatement ifStmt = (IASTPreprocessorIfStatement) statement;
1116
				branchStack.push(new Branch(stmtLocation.getNodeOffset(), ifStmt.taken()));
1391
				branchStack.push(new Branch(stmtLocation.getNodeOffset(),
1392
						ifStmt.taken()));
1117
			} else if (statement instanceof IASTPreprocessorIfdefStatement) {
1393
			} else if (statement instanceof IASTPreprocessorIfdefStatement) {
1118
				IASTPreprocessorIfdefStatement ifdefStmt = (IASTPreprocessorIfdefStatement)statement;
1394
				IASTPreprocessorIfdefStatement ifdefStmt = (IASTPreprocessorIfdefStatement) statement;
1119
				branchStack.push(new Branch(stmtLocation.getNodeOffset(), ifdefStmt.taken()));
1395
				branchStack.push(new Branch(stmtLocation.getNodeOffset(),
1396
						ifdefStmt.taken()));
1120
			} else if (statement instanceof IASTPreprocessorIfndefStatement) {
1397
			} else if (statement instanceof IASTPreprocessorIfndefStatement) {
1121
				IASTPreprocessorIfndefStatement ifndefStmt = (IASTPreprocessorIfndefStatement)statement;
1398
				IASTPreprocessorIfndefStatement ifndefStmt = (IASTPreprocessorIfndefStatement) statement;
1122
				branchStack.push(new Branch(stmtLocation.getNodeOffset(), ifndefStmt.taken()));
1399
				branchStack.push(new Branch(stmtLocation.getNodeOffset(),
1400
						ifndefStmt.taken()));
1123
			} else if (statement instanceof IASTPreprocessorElseStatement) {
1401
			} else if (statement instanceof IASTPreprocessorElseStatement) {
1124
				if (branchStack.isEmpty()) {
1402
				if (branchStack.isEmpty()) {
1125
					// #else without #if
1403
					// #else without #if
1126
					continue;
1404
					continue;
1127
				}
1405
				}
1128
				Branch branch= (Branch)branchStack.pop();
1406
				Branch branch = (Branch) branchStack.pop();
1129
				IASTPreprocessorElseStatement elseStmt = (IASTPreprocessorElseStatement)statement;
1407
				IASTPreprocessorElseStatement elseStmt = (IASTPreprocessorElseStatement) statement;
1130
				branchStack.push(new Branch(stmtLocation.getNodeOffset(), elseStmt.taken()));
1408
				branchStack.push(new Branch(stmtLocation.getNodeOffset(),
1409
						elseStmt.taken()));
1131
				branch.setEndOffset(stmtLocation.getNodeOffset());
1410
				branch.setEndOffset(stmtLocation.getNodeOffset());
1132
				branches.add(branch);
1411
				branches.add(branch);
1133
			} else if (statement instanceof IASTPreprocessorElifStatement) {
1412
			} else if (statement instanceof IASTPreprocessorElifStatement) {
Lines 1135-1143 Link Here
1135
					// #elif without #if
1414
					// #elif without #if
1136
					continue;
1415
					continue;
1137
				}
1416
				}
1138
				Branch branch= (Branch)branchStack.pop();
1417
				Branch branch = (Branch) branchStack.pop();
1139
				IASTPreprocessorElifStatement elifStmt = (IASTPreprocessorElifStatement) statement;
1418
				IASTPreprocessorElifStatement elifStmt = (IASTPreprocessorElifStatement) statement;
1140
				branchStack.push(new Branch(stmtLocation.getNodeOffset(), elifStmt.taken()));
1419
				branchStack.push(new Branch(stmtLocation.getNodeOffset(),
1420
						elifStmt.taken()));
1141
				branch.setEndOffset(stmtLocation.getNodeOffset());
1421
				branch.setEndOffset(stmtLocation.getNodeOffset());
1142
				branches.add(branch);
1422
				branches.add(branch);
1143
			} else if (statement instanceof IASTPreprocessorEndifStatement) {
1423
			} else if (statement instanceof IASTPreprocessorEndifStatement) {
Lines 1145-1163 Link Here
1145
					// #endif without #if
1425
					// #endif without #if
1146
					continue;
1426
					continue;
1147
				}
1427
				}
1148
				Branch branch= (Branch)branchStack.pop();
1428
				Branch branch = (Branch) branchStack.pop();
1149
				branch.setEndOffset(stmtLocation.getNodeOffset() + stmtLocation.getNodeLength());
1429
				branch.setEndOffset(stmtLocation.getNodeOffset()
1430
						+ stmtLocation.getNodeLength());
1150
				branch.setInclusive(true);
1431
				branch.setInclusive(true);
1151
				branches.add(branch);
1432
				branches.add(branch);
1152
			}
1433
			}
1153
		}
1434
		}
1154
		for (Iterator iter = branches.iterator(); iter.hasNext(); ) {
1435
		for (Iterator iter = branches.iterator(); iter.hasNext();) {
1155
			Branch branch= (Branch) iter.next();
1436
			Branch branch = (Branch) iter.next();
1156
			IRegion aligned = alignRegion(branch, ctx, branch.fInclusive);
1437
			IRegion aligned = alignRegion(branch, ctx, branch.fInclusive);
1157
			if (aligned != null) {
1438
			if (aligned != null) {
1158
				Position alignedPos= new Position(aligned.getOffset(), aligned.getLength());
1439
				Position alignedPos = new Position(aligned.getOffset(), aligned
1159
				final boolean collapse= !branch.taken() && ctx.collapseInactiveCode() && !alignedPos.includes(fCursorPosition);
1440
						.getLength());
1160
				ctx.addProjectionRange(new CProjectionAnnotation(collapse, computeKey(branch, ctx), false), alignedPos);
1441
				final boolean collapse = !branch.taken()
1442
						&& ctx.collapseInactiveCode()
1443
						&& !alignedPos.includes(fCursorPosition);
1444
				ctx.addProjectionRange(new CProjectionAnnotation(collapse,
1445
						computeKey(branch, ctx), false), alignedPos);
1161
			}
1446
			}
1162
		}
1447
		}
1163
	}
1448
	}
Lines 1169-1175 Link Here
1169
	 * @param ctx
1454
	 * @param ctx
1170
	 * @return a key to recognise an annotation position
1455
	 * @return a key to recognise an annotation position
1171
	 */
1456
	 */
1172
	private Object computeKey(Position pos, FoldingStructureComputationContext ctx) {
1457
	private Object computeKey(Position pos,
1458
			FoldingStructureComputationContext ctx) {
1173
		try {
1459
		try {
1174
			return ctx.getDocument().get(pos.offset, Math.min(16, pos.length));
1460
			return ctx.getDocument().get(pos.offset, Math.min(16, pos.length));
1175
		} catch (BadLocationException exc) {
1461
		} catch (BadLocationException exc) {
Lines 1180-1215 Link Here
1180
	/**
1466
	/**
1181
	 * Compute folding structure based on partioning information.
1467
	 * Compute folding structure based on partioning information.
1182
	 * 
1468
	 * 
1183
	 * @param partitions  array of document partitions
1469
	 * @param partitions
1184
	 * @param ctx  the folding structure context
1470
	 *            array of document partitions
1185
	 * @throws BadLocationException 
1471
	 * @param ctx
1472
	 *            the folding structure context
1473
	 * @throws BadLocationException
1186
	 */
1474
	 */
1187
	private void computeFoldingStructure(ITypedRegion[] partitions, FoldingStructureComputationContext ctx) throws BadLocationException {
1475
	private void computeFoldingStructure(ITypedRegion[] partitions,
1476
			FoldingStructureComputationContext ctx) throws BadLocationException {
1188
		boolean collapse = ctx.collapseComments();
1477
		boolean collapse = ctx.collapseComments();
1189
		IDocument doc= ctx.getDocument();
1478
		IDocument doc = ctx.getDocument();
1190
		int startLine = -1;
1479
		int startLine = -1;
1191
		int endLine = -1;
1480
		int endLine = -1;
1192
		List comments= new ArrayList();
1481
		List comments = new ArrayList();
1193
		ModifiableRegion commentRange = new ModifiableRegion();
1482
		ModifiableRegion commentRange = new ModifiableRegion();
1194
		for (int i = 0; i < partitions.length; i++) {
1483
		for (int i = 0; i < partitions.length; i++) {
1195
			ITypedRegion partition = partitions[i];
1484
			ITypedRegion partition = partitions[i];
1196
			boolean singleLine= false;
1485
			boolean singleLine = false;
1197
			if (ICPartitions.C_MULTI_LINE_COMMENT.equals(partition.getType())) {
1486
			if (ICPartitions.C_MULTI_LINE_COMMENT.equals(partition.getType())) {
1198
				Position position= createCommentPosition(alignRegion(partition, ctx, true));
1487
				Position position = createCommentPosition(alignRegion(
1488
						partition, ctx, true));
1199
				if (position != null) {
1489
				if (position != null) {
1200
					if (startLine >= 0 && endLine - startLine >= fMinCommentLines) {
1490
					if (startLine >= 0
1201
						Position projection = createCommentPosition(alignRegion(commentRange, ctx, true));
1491
							&& endLine - startLine >= fMinCommentLines) {
1492
						Position projection = createCommentPosition(alignRegion(
1493
								commentRange, ctx, true));
1202
						if (projection != null) {
1494
						if (projection != null) {
1203
							comments.add(new Tuple(new CProjectionAnnotation(collapse, doc.get(projection.offset, Math.min(16, projection.length)), true), projection));
1495
							comments.add(new Tuple(
1496
									new CProjectionAnnotation(collapse, doc
1497
											.get(projection.offset, Math.min(
1498
													16, projection.length)),
1499
											true), projection));
1204
						}
1500
						}
1205
						startLine= -1;
1501
						startLine = -1;
1206
					}
1502
					}
1207
					comments.add(new Tuple(new CProjectionAnnotation(collapse, doc.get(position.offset, Math.min(16, position.length)), true), position));
1503
					comments.add(new Tuple(new CProjectionAnnotation(collapse,
1504
							doc.get(position.offset, Math.min(16,
1505
									position.length)), true), position));
1208
				} else {
1506
				} else {
1209
					singleLine= true;
1507
					singleLine = true;
1210
				}
1508
				}
1211
			} else {
1509
			} else {
1212
				singleLine= ICPartitions.C_SINGLE_LINE_COMMENT.equals(partition.getType());
1510
				singleLine = ICPartitions.C_SINGLE_LINE_COMMENT
1511
						.equals(partition.getType());
1213
			}
1512
			}
1214
			if (singleLine) {
1513
			if (singleLine) {
1215
				// if comment starts at column 0 and spans only one line
1514
				// if comment starts at column 0 and spans only one line
Lines 1217-1237 Link Here
1217
				// to the commentRange
1516
				// to the commentRange
1218
				int lineNr = doc.getLineOfOffset(partition.getOffset());
1517
				int lineNr = doc.getLineOfOffset(partition.getOffset());
1219
				IRegion lineRegion = doc.getLineInformation(lineNr);
1518
				IRegion lineRegion = doc.getLineInformation(lineNr);
1220
				boolean isLineStart = partition.getOffset() == lineRegion.getOffset();
1519
				boolean isLineStart = partition.getOffset() == lineRegion
1520
						.getOffset();
1221
				if (!isLineStart) {
1521
				if (!isLineStart) {
1222
					continue;
1522
					continue;
1223
				}
1523
				}
1224
				if (!singleLine) {
1524
				if (!singleLine) {
1225
					singleLine = lineRegion.getOffset() + lineRegion.getLength() >= partition.getOffset() + partition.getLength();
1525
					singleLine = lineRegion.getOffset()
1526
							+ lineRegion.getLength() >= partition.getOffset()
1527
							+ partition.getLength();
1226
					if (!singleLine) {
1528
					if (!singleLine) {
1227
						continue;
1529
						continue;
1228
					}
1530
					}
1229
				}
1531
				}
1230
				if (startLine < 0 || lineNr - endLine > 1) {
1532
				if (startLine < 0 || lineNr - endLine > 1) {
1231
					if (startLine >= 0 && endLine - startLine >= fMinCommentLines) {
1533
					if (startLine >= 0
1232
						Position projection = createCommentPosition(alignRegion(commentRange, ctx, true));
1534
							&& endLine - startLine >= fMinCommentLines) {
1535
						Position projection = createCommentPosition(alignRegion(
1536
								commentRange, ctx, true));
1233
						if (projection != null) {
1537
						if (projection != null) {
1234
							comments.add(new Tuple(new CProjectionAnnotation(collapse, doc.get(projection.offset, Math.min(16, projection.length)), true), projection));
1538
							comments.add(new Tuple(
1539
									new CProjectionAnnotation(collapse, doc
1540
											.get(projection.offset, Math.min(
1541
													16, projection.length)),
1542
											true), projection));
1235
						}
1543
						}
1236
					}
1544
					}
1237
					startLine = lineNr;
1545
					startLine = lineNr;
Lines 1240-1258 Link Here
1240
					commentRange.length = lineRegion.getLength();
1548
					commentRange.length = lineRegion.getLength();
1241
				} else {
1549
				} else {
1242
					endLine = lineNr;
1550
					endLine = lineNr;
1243
					int delta = lineRegion.getOffset() + lineRegion.getLength() - commentRange.offset - commentRange.length;
1551
					int delta = lineRegion.getOffset() + lineRegion.getLength()
1552
							- commentRange.offset - commentRange.length;
1244
					commentRange.length += delta;
1553
					commentRange.length += delta;
1245
				}
1554
				}
1246
			}
1555
			}
1247
		}
1556
		}
1248
		if (startLine >= 0 && endLine - startLine >= fMinCommentLines) {
1557
		if (startLine >= 0 && endLine - startLine >= fMinCommentLines) {
1249
			Position projection = createCommentPosition(alignRegion(commentRange, ctx, true));
1558
			Position projection = createCommentPosition(alignRegion(
1559
					commentRange, ctx, true));
1250
			if (projection != null) {
1560
			if (projection != null) {
1251
				comments.add(new Tuple(new CProjectionAnnotation(collapse, doc.get(projection.offset, Math.min(16, projection.length)), true), projection));
1561
				comments.add(new Tuple(new CProjectionAnnotation(collapse,
1562
						doc.get(projection.offset, Math.min(16,
1563
								projection.length)), true), projection));
1252
			}
1564
			}
1253
		}
1565
		}
1254
		if (!comments.isEmpty()) {
1566
		if (!comments.isEmpty()) {
1255
			// first comment starting before line 10 is considered the header comment
1567
			// first comment starting before line 10 is considered the header
1568
			// comment
1256
			Iterator iter = comments.iterator();
1569
			Iterator iter = comments.iterator();
1257
			Tuple tuple = (Tuple) iter.next();
1570
			Tuple tuple = (Tuple) iter.next();
1258
			int lineNr = doc.getLineOfOffset(tuple.position.getOffset());
1571
			int lineNr = doc.getLineOfOffset(tuple.position.getOffset());
Lines 1271-1297 Link Here
1271
		}
1584
		}
1272
	}
1585
	}
1273
1586
1274
	private void computeFoldingStructure(ICElement[] elements, FoldingStructureComputationContext ctx) throws CModelException {
1587
	private void computeFoldingStructure(ICElement[] elements,
1275
		for (int i= 0; i < elements.length; i++) {
1588
			FoldingStructureComputationContext ctx) throws CModelException {
1276
			ICElement element= elements[i];
1589
		for (int i = 0; i < elements.length; i++) {
1590
			ICElement element = elements[i];
1277
1591
1278
			computeFoldingStructure(element, ctx);
1592
			computeFoldingStructure(element, ctx);
1279
1593
1280
			if (element instanceof IParent) {
1594
			if (element instanceof IParent) {
1281
				IParent parent= (IParent) element;
1595
				IParent parent = (IParent) element;
1282
				computeFoldingStructure(parent.getChildren(), ctx);
1596
				computeFoldingStructure(parent.getChildren(), ctx);
1283
			}
1597
			}
1284
		}
1598
		}
1285
	}
1599
	}
1286
1600
1287
	/**
1601
	/**
1288
	 * Computes the folding structure for a given {@link ICElement C element}. Computed
1602
	 * Computes the folding structure for a given {@link ICElement C element}.
1289
	 * projection annotations are
1603
	 * Computed projection annotations are
1290
	 * {@link DefaultCFoldingStructureProvider.FoldingStructureComputationContext#addProjectionRange(DefaultCFoldingStructureProvider.CProjectionAnnotation, Position) added}
1604
	 * {@link DefaultCFoldingStructureProvider.FoldingStructureComputationContext#addProjectionRange(DefaultCFoldingStructureProvider.CProjectionAnnotation, Position) added}
1291
	 * to the computation context.
1605
	 * to the computation context.
1292
	 * <p>
1606
	 * <p>
1293
	 * Subclasses may extend or replace. The default implementation creates projection annotations
1607
	 * Subclasses may extend or replace. The default implementation creates
1294
	 * for the following elements:
1608
	 * projection annotations for the following elements:
1295
	 * <ul>
1609
	 * <ul>
1296
	 * <li>structs, unions, classes</li>
1610
	 * <li>structs, unions, classes</li>
1297
	 * <li>functions</li>
1611
	 * <li>functions</li>
Lines 1300-1369 Link Here
1300
	 * </ul>
1614
	 * </ul>
1301
	 * </p>
1615
	 * </p>
1302
	 * 
1616
	 * 
1303
	 * @param element the C element to compute the folding structure for
1617
	 * @param element
1304
	 * @param ctx the computation context
1618
	 *            the C element to compute the folding structure for
1619
	 * @param ctx
1620
	 *            the computation context
1305
	 */
1621
	 */
1306
	protected void computeFoldingStructure(ICElement element, FoldingStructureComputationContext ctx) {
1622
	protected void computeFoldingStructure(ICElement element,
1623
			FoldingStructureComputationContext ctx) {
1307
1624
1308
		boolean collapse= false;
1625
		boolean collapse = false;
1309
		switch (element.getElementType()) {
1626
		switch (element.getElementType()) {
1310
1627
1311
		case ICElement.C_STRUCT:
1628
		case ICElement.C_STRUCT:
1312
		case ICElement.C_CLASS:
1629
		case ICElement.C_CLASS:
1313
		case ICElement.C_UNION:
1630
		case ICElement.C_UNION:
1631
		case ICElement.C_ENUMERATION:
1632
		case ICElement.C_VARIABLE_DECLARATION:
1314
		case ICElement.C_TEMPLATE_STRUCT:
1633
		case ICElement.C_TEMPLATE_STRUCT:
1315
		case ICElement.C_TEMPLATE_CLASS:
1634
		case ICElement.C_TEMPLATE_CLASS:
1316
		case ICElement.C_TEMPLATE_UNION:
1635
		case ICElement.C_TEMPLATE_UNION:
1317
			collapse= ctx.collapseStructures();
1636
			collapse = ctx.collapseStructures();
1318
			break;
1637
			break;
1319
		case ICElement.C_MACRO:
1638
		case ICElement.C_MACRO:
1320
			collapse= ctx.collapseMacros();
1639
			collapse = ctx.collapseMacros();
1321
			break;
1640
			break;
1322
		case ICElement.C_FUNCTION:
1641
		case ICElement.C_FUNCTION:
1323
		case ICElement.C_TEMPLATE_FUNCTION:
1642
		case ICElement.C_TEMPLATE_FUNCTION:
1324
			collapse= ctx.collapseFunctions();
1643
			collapse = ctx.collapseFunctions();
1325
			break;
1644
			break;
1326
		case ICElement.C_METHOD:
1645
		case ICElement.C_METHOD:
1327
		case ICElement.C_TEMPLATE_METHOD:
1646
		case ICElement.C_TEMPLATE_METHOD:
1328
			collapse= ctx.collapseMethods();
1647
			collapse = ctx.collapseMethods();
1329
			break;
1648
			break;
1330
		default:
1649
		default:
1331
			return;
1650
			return;
1332
		}
1651
		}
1333
1652
1334
		IRegion[] regions= computeProjectionRanges((ISourceReference) element, ctx);
1653
		IRegion[] regions = computeProjectionRanges((ISourceReference) element,
1654
				ctx);
1335
		if (regions.length > 0) {
1655
		if (regions.length > 0) {
1336
			IRegion normalized= alignRegion(regions[regions.length - 1], ctx, true);
1656
			IRegion normalized = alignRegion(regions[regions.length - 1], ctx,
1657
					true);
1337
			if (normalized != null) {
1658
			if (normalized != null) {
1338
				Position position= createElementPosition(normalized, element);
1659
				Position position = createElementPosition(normalized, element);
1339
				if (position != null) {
1660
				if (position != null) {
1340
					collapse= collapse && !position.includes(fCursorPosition);
1661
					collapse = collapse && !position.includes(fCursorPosition);
1341
					ctx.addProjectionRange(new CProjectionAnnotation(collapse, element, false), position);
1662
					ctx.addProjectionRange(new CProjectionAnnotation(collapse,
1663
							element, false), position);
1342
				}
1664
				}
1343
			}
1665
			}
1344
		}
1666
		}
1345
	}
1667
	}
1346
1668
1347
	/**
1669
	/**
1348
	 * Computes the projection ranges for a given <code>ISourceReference</code>. More than one
1670
	 * Computes the projection ranges for a given <code>ISourceReference</code>.
1349
	 * range or none at all may be returned. If there are no foldable regions, an empty array is
1671
	 * More than one range or none at all may be returned. If there are no
1350
	 * returned.
1672
	 * foldable regions, an empty array is returned.
1351
	 * <p>
1673
	 * <p>
1352
	 * The last region in the returned array (if not empty) describes the region for the C
1674
	 * The last region in the returned array (if not empty) describes the region
1353
	 * element that implements the source reference. Any preceding regions describe comments
1675
	 * for the C element that implements the source reference. Any preceding
1354
	 * of that element.
1676
	 * regions describe comments of that element.
1355
	 * </p>
1677
	 * </p>
1356
	 * 
1678
	 * 
1357
	 * @param reference a C element that is a source reference
1679
	 * @param reference
1358
	 * @param ctx the folding context
1680
	 *            a C element that is a source reference
1681
	 * @param ctx
1682
	 *            the folding context
1359
	 * @return the regions to be folded
1683
	 * @return the regions to be folded
1360
	 */
1684
	 */
1361
	protected final IRegion[] computeProjectionRanges(ISourceReference reference, FoldingStructureComputationContext ctx) {
1685
	protected final IRegion[] computeProjectionRanges(
1686
			ISourceReference reference, FoldingStructureComputationContext ctx) {
1362
		try {
1687
		try {
1363
			ISourceRange range= reference.getSourceRange();
1688
			ISourceRange range = reference.getSourceRange();
1364
			return new IRegion[] {
1689
			return new IRegion[] { new Region(range.getStartPos(), range
1365
				new Region(range.getStartPos(), range.getLength())
1690
					.getLength()) };
1366
			};
1367
		} catch (CModelException e) {
1691
		} catch (CModelException e) {
1368
		}
1692
		}
1369
1693
Lines 1375-1381 Link Here
1375
	 * {@link #alignRegion(IRegion, DefaultCFoldingStructureProvider.FoldingStructureComputationContext, boolean) aligned}
1699
	 * {@link #alignRegion(IRegion, DefaultCFoldingStructureProvider.FoldingStructureComputationContext, boolean) aligned}
1376
	 * region.
1700
	 * region.
1377
	 * 
1701
	 * 
1378
	 * @param aligned an aligned region
1702
	 * @param aligned
1703
	 *            an aligned region
1379
	 * @return a folding position corresponding to <code>aligned</code>
1704
	 * @return a folding position corresponding to <code>aligned</code>
1380
	 */
1705
	 */
1381
	protected final Position createCommentPosition(IRegion aligned) {
1706
	protected final Position createCommentPosition(IRegion aligned) {
Lines 1390-1471 Link Here
1390
	 * {@link #alignRegion(IRegion, DefaultCFoldingStructureProvider.FoldingStructureComputationContext, boolean) aligned}
1715
	 * {@link #alignRegion(IRegion, DefaultCFoldingStructureProvider.FoldingStructureComputationContext, boolean) aligned}
1391
	 * region.
1716
	 * region.
1392
	 * 
1717
	 * 
1393
	 * @param aligned an aligned region
1718
	 * @param aligned
1394
	 * @param element the element to remember
1719
	 *            an aligned region
1720
	 * @param element
1721
	 *            the element to remember
1395
	 * @return a folding position corresponding to <code>aligned</code>
1722
	 * @return a folding position corresponding to <code>aligned</code>
1396
	 */
1723
	 */
1397
	protected final Position createElementPosition(IRegion aligned, ICElement element) {
1724
	protected final Position createElementPosition(IRegion aligned,
1398
		return new CElementPosition(aligned.getOffset(), aligned.getLength(), element);
1725
			ICElement element) {
1726
		return new CElementPosition(aligned.getOffset(), aligned.getLength(),
1727
				element);
1399
	}
1728
	}
1400
1729
1401
	/**
1730
	/**
1402
	 * Aligns <code>region</code> to start and end at a line offset. The region's start is
1731
	 * Aligns <code>region</code> to start and end at a line offset. The
1403
	 * decreased to the next line offset, and the end offset increased to the next line start or the
1732
	 * region's start is decreased to the next line offset, and the end offset
1404
	 * end of the document. <code>null</code> is returned if <code>region</code> is
1733
	 * increased to the next line start or the end of the document.
1405
	 * <code>null</code> itself or does not comprise at least one line delimiter, as a single line
1734
	 * <code>null</code> is returned if <code>region</code> is
1406
	 * cannot be folded.
1735
	 * <code>null</code> itself or does not comprise at least one line
1736
	 * delimiter, as a single line cannot be folded.
1407
	 * 
1737
	 * 
1408
	 * @param region the region to align, may be <code>null</code>
1738
	 * @param region
1409
	 * @param ctx the folding context
1739
	 *            the region to align, may be <code>null</code>
1410
	 * @return a region equal or greater than <code>region</code> that is aligned with line
1740
	 * @param ctx
1411
	 *         offsets, <code>null</code> if the region is too small to be foldable (e.g. covers
1741
	 *            the folding context
1412
	 *         only one line)
1742
	 * @return a region equal or greater than <code>region</code> that is
1743
	 *         aligned with line offsets, <code>null</code> if the region is
1744
	 *         too small to be foldable (e.g. covers only one line)
1413
	 */
1745
	 */
1414
	protected final IRegion alignRegion(IRegion region, FoldingStructureComputationContext ctx) {
1746
	protected final IRegion alignRegion(IRegion region,
1747
			FoldingStructureComputationContext ctx) {
1415
		return alignRegion(region, ctx, true);
1748
		return alignRegion(region, ctx, true);
1416
	}
1749
	}
1417
1750
1418
	/**
1751
	/**
1419
	 * Aligns <code>region</code> to start and end at a line offset. The region's start is
1752
	 * Aligns <code>region</code> to start and end at a line offset. The
1420
	 * decreased to the next line offset, and the end offset increased to the next line start or the
1753
	 * region's start is decreased to the next line offset, and the end offset
1421
	 * end of the document. <code>null</code> is returned if <code>region</code> is
1754
	 * increased to the next line start or the end of the document.
1422
	 * <code>null</code> itself or does not comprise at least one line delimiter, as a single line
1755
	 * <code>null</code> is returned if <code>region</code> is
1423
	 * cannot be folded.
1756
	 * <code>null</code> itself or does not comprise at least one line
1757
	 * delimiter, as a single line cannot be folded.
1424
	 * 
1758
	 * 
1425
	 * @param region the region to align, may be <code>null</code>
1759
	 * @param region
1426
	 * @param ctx the folding context
1760
	 *            the region to align, may be <code>null</code>
1427
	 * @param inclusive include line of end offset
1761
	 * @param ctx
1428
	 * @return a region equal or greater than <code>region</code> that is aligned with line
1762
	 *            the folding context
1429
	 *         offsets, <code>null</code> if the region is too small to be foldable (e.g. covers
1763
	 * @param inclusive
1430
	 *         only one line)
1764
	 *            include line of end offset
1765
	 * @return a region equal or greater than <code>region</code> that is
1766
	 *         aligned with line offsets, <code>null</code> if the region is
1767
	 *         too small to be foldable (e.g. covers only one line)
1431
	 */
1768
	 */
1432
	protected final IRegion alignRegion(IRegion region, FoldingStructureComputationContext ctx, boolean inclusive) {
1769
	protected final IRegion alignRegion(IRegion region,
1770
			FoldingStructureComputationContext ctx, boolean inclusive) {
1433
		if (region == null)
1771
		if (region == null)
1434
			return null;
1772
			return null;
1435
		
1773
1436
		IDocument document= ctx.getDocument();
1774
		IDocument document = ctx.getDocument();
1437
		
1775
1438
		try {
1776
		try {
1439
			
1777
1440
			int start= document.getLineOfOffset(region.getOffset());
1778
			int start = document.getLineOfOffset(region.getOffset());
1441
			int end= document.getLineOfOffset(region.getOffset() + region.getLength());
1779
			int end = document.getLineOfOffset(region.getOffset()
1780
					+ region.getLength());
1442
			if (start >= end)
1781
			if (start >= end)
1443
				return null;
1782
				return null;
1444
			
1783
1445
			int offset= document.getLineOffset(start);
1784
			int offset = document.getLineOffset(start);
1446
			int endOffset;
1785
			int endOffset;
1447
			if (inclusive) {
1786
			if (inclusive) {
1448
				if (document.getNumberOfLines() > end + 1)
1787
				if (document.getNumberOfLines() > end + 1)
1449
					endOffset= document.getLineOffset(end + 1);
1788
					endOffset = document.getLineOffset(end + 1);
1450
				else
1789
				else
1451
					endOffset= document.getLineOffset(end) + document.getLineLength(end);
1790
					endOffset = document.getLineOffset(end)
1791
							+ document.getLineLength(end);
1452
			} else {
1792
			} else {
1453
				endOffset= document.getLineOffset(end);
1793
				endOffset = document.getLineOffset(end);
1454
			}
1794
			}
1455
			return new Region(offset, endOffset - offset);
1795
			return new Region(offset, endOffset - offset);
1456
			
1796
1457
		} catch (BadLocationException x) {
1797
		} catch (BadLocationException x) {
1458
			// concurrent modification
1798
			// concurrent modification
1459
			return null;
1799
			return null;
1460
		}
1800
		}
1461
	}
1801
	}
1462
	
1802
1463
	private ProjectionAnnotationModel getModel() {
1803
	private ProjectionAnnotationModel getModel() {
1464
		return (ProjectionAnnotationModel) fEditor.getAdapter(ProjectionAnnotationModel.class);
1804
		return (ProjectionAnnotationModel) fEditor
1805
				.getAdapter(ProjectionAnnotationModel.class);
1465
	}
1806
	}
1466
1807
1467
	private IDocument getDocument() {
1808
	private IDocument getDocument() {
1468
		IDocumentProvider provider= fEditor.getDocumentProvider();
1809
		IDocumentProvider provider = fEditor.getDocumentProvider();
1469
		return provider.getDocument(fEditor.getEditorInput());
1810
		return provider.getDocument(fEditor.getEditorInput());
1470
	}
1811
	}
1471
1812
(-)src/org/eclipse/cdt/internal/ui/text/folding/FoldingMessages.java (+1 lines)
Lines 30-35 Link Here
30
	public static String DefaultCFoldingPreferenceBlock_inactive_code;
30
	public static String DefaultCFoldingPreferenceBlock_inactive_code;
31
	public static String DefaultCFoldingPreferenceBlock_preprocessor_enabled;
31
	public static String DefaultCFoldingPreferenceBlock_preprocessor_enabled;
32
	public static String EmptyCFoldingPreferenceBlock_emptyCaption;
32
	public static String EmptyCFoldingPreferenceBlock_emptyCaption;
33
	public static String DefaultCFoldingPreferenceBlock_statements_enabled;
33
34
34
	static {
35
	static {
35
		NLS.initializeMessages(BUNDLE_NAME, FoldingMessages.class);
36
		NLS.initializeMessages(BUNDLE_NAME, FoldingMessages.class);
(-)resources/folding/FoldingTest.cpp (+28 lines)
Lines 72-76 Link Here
72
main(int argc,
72
main(int argc,
73
     char *argv[])
73
     char *argv[])
74
{
74
{
75
int MyI = 0,j = 0;
76
	if (0==0) {
77
		puts("Wow ");
78
	} else {
79
		j = j;
80
	}
81
	for (MyI = 0; MyI < 10; ++MyI) {
82
		printf("%d\n",MyI);
83
	}
84
	while (0) {
85
		puts("nothinghere");
86
	}
87
	switch (1) {
88
		case 1:
89
			puts("ab");
90
			break;
91
		case 2:
92
			puts("cd");
93
		default:
94
			puts("xy");
95
	}
96
	do {
97
		puts("tryagain");
98
99
	} while (0);
100
	if (MyI==0) {
101
		return 1;
102
	}
75
    return 0;
103
    return 0;
76
}
104
}
(-)ui/org/eclipse/cdt/ui/tests/text/FoldingTest.java (-2 / +40 lines)
Lines 7-12 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     Anton Leherbauer (Wind River Systems) - initial API and implementation
9
 *     Anton Leherbauer (Wind River Systems) - initial API and implementation
10
 *     Elazar Leibovich (The Open University) - extra folding test
10
 *******************************************************************************/
11
 *******************************************************************************/
11
package org.eclipse.cdt.ui.tests.text;
12
package org.eclipse.cdt.ui.tests.text;
12
13
Lines 80-85 Link Here
80
81
81
		IPreferenceStore store= CUIPlugin.getDefault().getPreferenceStore();
82
		IPreferenceStore store= CUIPlugin.getDefault().getPreferenceStore();
82
		store.setValue(PreferenceConstants.EDITOR_FOLDING_ENABLED, true);
83
		store.setValue(PreferenceConstants.EDITOR_FOLDING_ENABLED, true);
84
		store.setValue(PreferenceConstants.EDITOR_FOLDING_STATEMENTS, true);
83
		store.setValue(PreferenceConstants.EDITOR_FOLDING_PREPROCESSOR_BRANCHES_ENABLED, true);
85
		store.setValue(PreferenceConstants.EDITOR_FOLDING_PREPROCESSOR_BRANCHES_ENABLED, true);
84
		store.setValue(PreferenceConstants.EDITOR_FOLDING_INACTIVE_CODE, false);
86
		store.setValue(PreferenceConstants.EDITOR_FOLDING_INACTIVE_CODE, false);
85
		store.setValue(PreferenceConstants.EDITOR_FOLDING_HEADERS, false);
87
		store.setValue(PreferenceConstants.EDITOR_FOLDING_HEADERS, false);
Lines 193-208 Link Here
193
				createPosition(29, 31),
195
				createPosition(29, 31),
194
				createPosition(34, 35),
196
				createPosition(34, 35),
195
				createPosition(35, 40),
197
				createPosition(35, 40),
198
				createPosition(35, 40),
196
				createPosition(36, 38),
199
				createPosition(36, 38),
197
				createPosition(42, 46),
200
				createPosition(42, 46),
198
				createPosition(48, 55),
201
				createPosition(48, 55),
202
				createPosition(48, 55),
203
				createPosition(51, 53),
199
				createPosition(51, 53),
204
				createPosition(51, 53),
200
				createPosition(57, 59),
205
				createPosition(57, 59),
206
				createPosition(57, 59),
207
				createPosition(61, 63),
201
				createPosition(61, 63),
208
				createPosition(61, 63),
202
				createPosition(65, 67),
209
				createPosition(65, 67),
203
				createPosition(70, 75, 71),
210
				createPosition(65, 67),
211
				createPosition(70, 103),
212
				createPosition(70, 103),
213
				createPosition(75, 76),
214
				createPosition(77, 79),
215
				createPosition(80, 82),
216
				createPosition(83, 85),
217
				createPosition(86, 94),
218
				createPosition(87, 89),
219
				createPosition(90, 91),
220
				createPosition(92, 93),
221
				createPosition(95, 97),
222
				createPosition(99, 101),
204
		};
223
		};
205
		if (false) System.out.println(toString(actual));
224
		if (false) System.out.println(toString(actual));
225
		System.out.println(toString(actual));
226
		System.out.println(toString(expected));
206
		assertEqualPositions(expected, actual);
227
		assertEqualPositions(expected, actual);
207
	}
228
	}
208
	
229
	
Lines 218-230 Link Here
218
				createPosition(4, 7),
239
				createPosition(4, 7),
219
				createPosition(29, 31),
240
				createPosition(29, 31),
220
				createPosition(35, 40),
241
				createPosition(35, 40),
242
				createPosition(35, 40),
221
				createPosition(42, 46),
243
				createPosition(42, 46),
222
				createPosition(48, 55),
244
				createPosition(48, 55),
245
				createPosition(48, 55),
246
				createPosition(51, 53),
223
				createPosition(51, 53),
247
				createPosition(51, 53),
224
				createPosition(57, 59),
248
				createPosition(57, 59),
249
				createPosition(57, 59),
250
				createPosition(61, 63),
225
				createPosition(61, 63),
251
				createPosition(61, 63),
226
				createPosition(65, 67),
252
				createPosition(65, 67),
227
				createPosition(70, 75, 71),
253
				createPosition(65, 67),
254
				createPosition(70, 103),
255
				createPosition(70, 103),
256
				createPosition(75, 76),
257
				createPosition(77, 79),
258
				createPosition(80, 82),
259
				createPosition(83, 85),
260
				createPosition(86, 94),
261
				createPosition(87, 89),
262
				createPosition(90, 91),
263
				createPosition(92, 93),
264
				createPosition(95, 97),
265
				createPosition(99, 101),
228
		};
266
		};
229
		if (false) System.out.println(toString(actual));
267
		if (false) System.out.println(toString(actual));
230
		assertEqualPositions(expected, actual);
268
		assertEqualPositions(expected, actual);

Return to bug 174597