Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[cdt-patch] Code completion - first round


Hi,
This patch updates code completion to use search. It also includes my previous patch which enabled the class wizard to use search as well.

Current Code Completion has the following restrictions:
- It will only work within the scope of a function or a method.
-It will look for globals (variables, functions, classes, strucs, unions, enumerations, and macros).
-In the scope of a method, it will also look for the methods and fields that belong to the owner class of this method.
- It will NOT search the parent classes of the method in the method scope case.
- It will NOT de-reference after a "." or an "->"


Thanks,
Hoda Amer
Staff Software Engineer
Rational Software - IBM Software Group



 
Index: ChangeLog
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/ChangeLog,v
retrieving revision 1.122
diff -u -r1.122 ChangeLog
--- ChangeLog	12 Aug 2003 14:29:07 -0000	1.122
+++ ChangeLog	12 Aug 2003 19:00:17 -0000
@@ -1,3 +1,8 @@
+2003-08-12 Hoda Amer
+	Moved CharOperations and Utils from internal.core.search to internal.core
+	Added CConventions class to validate class names
+	Used the new search (indexer) for Code completion in CCompletionProcessor
+	
 2003-08-11 Andrew Niefer
 	Added getSharedWorkingCopies to CCorePlugin.
 	
Index: dependency/org/eclipse/cdt/internal/core/sourcedependency/AddFileToDependencyTree.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/AddFileToDependencyTree.java,v
retrieving revision 1.1
diff -u -r1.1 AddFileToDependencyTree.java
--- dependency/org/eclipse/cdt/internal/core/sourcedependency/AddFileToDependencyTree.java	24 Jul 2003 14:15:06 -0000	1.1
+++ dependency/org/eclipse/cdt/internal/core/sourcedependency/AddFileToDependencyTree.java	12 Aug 2003 19:00:17 -0000
@@ -84,7 +84,7 @@
 			try {
 				IPath location = resource.getLocation();
 				if (location != null)
-					this.contents = org.eclipse.cdt.internal.core.search.Util.getFileCharContent(location.toFile(), null);
+					this.contents = org.eclipse.cdt.internal.core.Util.getFileCharContent(location.toFile(), null);
 			} catch (IOException e) {
 			}
 		}
Index: dependency/org/eclipse/cdt/internal/core/sourcedependency/DependencyManager.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/DependencyManager.java,v
retrieving revision 1.1
diff -u -r1.1 DependencyManager.java
--- dependency/org/eclipse/cdt/internal/core/sourcedependency/DependencyManager.java	24 Jul 2003 14:15:06 -0000	1.1
+++ dependency/org/eclipse/cdt/internal/core/sourcedependency/DependencyManager.java	12 Aug 2003 19:00:17 -0000
@@ -21,7 +21,7 @@
 
 import org.eclipse.cdt.core.CCorePlugin;
 import org.eclipse.cdt.core.parser.IScannerInfo;
-import org.eclipse.cdt.internal.core.search.CharOperation;
+import org.eclipse.cdt.internal.core.CharOperation;
 import org.eclipse.cdt.internal.core.search.SimpleLookupTable;
 import org.eclipse.cdt.internal.core.search.indexing.ReadWriteMonitor;
 import org.eclipse.cdt.internal.core.search.processing.JobManager;
@@ -207,7 +207,7 @@
 	
 	private char[] readDTreeState() {
 		try {
-			return org.eclipse.cdt.internal.core.search.Util.getFileCharContent(savedDTreesFile, null);
+			return org.eclipse.cdt.internal.core.Util.getFileCharContent(savedDTreesFile, null);
 		} catch (IOException ignored) {
 			if (VERBOSE)
 				JobManager.verbose("Failed to read saved dTree file names"); //$NON-NLS-1$
@@ -216,7 +216,7 @@
 	}
 	
 	private void rebuildDTree(String treeName, IPath path) {
-		Object target = org.eclipse.cdt.internal.core.search.Util.getTarget(ResourcesPlugin.getWorkspace().getRoot(), path, true);
+		Object target = org.eclipse.cdt.internal.core.Util.getTarget(ResourcesPlugin.getWorkspace().getRoot(), path, true);
 		if (target == null) return;
 	
 		if (VERBOSE)
Index: dependency/org/eclipse/cdt/internal/core/sourcedependency/EntireProjectDependencyTree.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/EntireProjectDependencyTree.java,v
retrieving revision 1.1
diff -u -r1.1 EntireProjectDependencyTree.java
--- dependency/org/eclipse/cdt/internal/core/sourcedependency/EntireProjectDependencyTree.java	24 Jul 2003 14:15:06 -0000	1.1
+++ dependency/org/eclipse/cdt/internal/core/sourcedependency/EntireProjectDependencyTree.java	12 Aug 2003 19:00:17 -0000
@@ -14,10 +14,10 @@
 import java.util.HashSet;
 
 import org.eclipse.cdt.core.build.managed.ManagedBuildManager;
+import org.eclipse.cdt.internal.core.Util;
 import org.eclipse.cdt.internal.core.index.IQueryResult;
 import org.eclipse.cdt.internal.core.index.impl.IFileDocument;
 import org.eclipse.cdt.internal.core.search.SimpleLookupTable;
-import org.eclipse.cdt.internal.core.search.Util;
 import org.eclipse.cdt.internal.core.search.indexing.ReadWriteMonitor;
 import org.eclipse.cdt.internal.core.search.processing.JobManager;
 import org.eclipse.core.resources.IFile;
Index: dependency/org/eclipse/cdt/internal/core/sourcedependency/impl/IncludeEntry.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/impl/IncludeEntry.java,v
retrieving revision 1.1
diff -u -r1.1 IncludeEntry.java
--- dependency/org/eclipse/cdt/internal/core/sourcedependency/impl/IncludeEntry.java	24 Jul 2003 14:15:06 -0000	1.1
+++ dependency/org/eclipse/cdt/internal/core/sourcedependency/impl/IncludeEntry.java	12 Aug 2003 19:00:17 -0000
@@ -14,7 +14,7 @@
 import java.util.ArrayList;
 import java.util.Iterator;
 
-import org.eclipse.cdt.internal.core.search.CharOperation;
+import org.eclipse.cdt.internal.core.CharOperation;
 
 /**
  * @author bgheorgh
Index: dependency/org/eclipse/cdt/internal/core/sourcedependency/impl/IncludeEntryHashedArray.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/impl/IncludeEntryHashedArray.java,v
retrieving revision 1.1
diff -u -r1.1 IncludeEntryHashedArray.java
--- dependency/org/eclipse/cdt/internal/core/sourcedependency/impl/IncludeEntryHashedArray.java	24 Jul 2003 14:15:06 -0000	1.1
+++ dependency/org/eclipse/cdt/internal/core/sourcedependency/impl/IncludeEntryHashedArray.java	12 Aug 2003 19:00:17 -0000
@@ -11,7 +11,7 @@
 
 package org.eclipse.cdt.internal.core.sourcedependency.impl;
 
-import org.eclipse.cdt.internal.core.search.CharOperation;
+import org.eclipse.cdt.internal.core.CharOperation;
 
 public final class IncludeEntryHashedArray {
 
Index: index/org/eclipse/cdt/internal/core/CharOperation.java
===================================================================
RCS file: index/org/eclipse/cdt/internal/core/CharOperation.java
diff -N index/org/eclipse/cdt/internal/core/CharOperation.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ index/org/eclipse/cdt/internal/core/CharOperation.java	12 Aug 2003 19:00:18 -0000
@@ -0,0 +1,2548 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.internal.core;
+
+/**
+ * This class is a collection of helper methods to manipulate char arrays.
+ * 
+ * @since 2.1
+ */
+public final class CharOperation {
+
+	/**
+	 * Constant for an empty char array
+	 */
+	public static final char[] NO_CHAR = new char[0];
+	/**
+	 * Constant for an empty char array with two dimensions.
+	 */
+	public static final char[][] NO_CHAR_CHAR = new char[0][];
+	/**
+	 * Answers a new array with appending the suffix character at the end of the array.
+	 * <br>
+	 * <br>
+	 * For example:<br>
+	 * <ol>
+	 * <li><pre>
+	 *    array = { 'a', 'b' }
+	 *    suffix = 'c'
+	 *    => result = { 'a', 'b' , 'c' }
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    array = null
+	 *    suffix = 'c'
+	 *    => result = { 'c' }
+	 * </pre></li>
+	 * </ol>
+	 * 
+	 * @param array the array that is concanated with the suffix character
+	 * @param suffix the suffix character
+	 * @return the new array
+	 */
+	public static final char[] append(char[] array, char suffix) {
+		if (array == null)
+			return new char[] { suffix };
+		int length = array.length;
+		System.arraycopy(array, 0, array = new char[length + 1], 0, length);
+		array[length] = suffix;
+		return array;
+	}
+	/**
+	 * Append the given subarray to the target array starting at the given index in the target array.
+	 * The start of the subarray is inclusive, the end is exclusive.
+	 * Answers a new target array if it needs to grow, otherwise answers the same target array.
+	 * <br>
+	 * For example:<br>
+	 * <ol>
+	 * <li><pre>
+	 *    target = { 'a', 'b', '0' }
+	 *    index = 2
+	 *    array = { 'c', 'd' }
+	 *    start = 0
+	 *    end = 1
+	 *    => result = { 'a', 'b' , 'c' }
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    target = { 'a', 'b' }
+	 *    index = 2
+	 *    array = { 'c', 'd' }
+	 *    start = 0
+	 *    end = 1
+	 *    => result = { 'a', 'b' , 'c', '0', '0' , '0' } (new array)
+	 * </pre></li>
+	 * <li><pre>
+	 *    target = { 'a', 'b', 'c' }
+	 *    index = 1
+	 *    array = { 'c', 'd', 'e', 'f' }
+	 *    start = 1
+	 *    end = 4
+	 *    => result = { 'a', 'd' , 'e', 'f', '0', '0', '0', '0' } (new array)
+	 * </pre></li>
+	 * </ol>
+	 * 
+	 * @param target the given target
+	 * @param index the given index
+	 * @param array the given array
+	 * @param start the given start index
+	 * @param end the given end index
+	 * 
+	 * @return the new array
+	 * @throws NullPointerException if the target array is null
+	 */
+	public static final char[] append(char[] target, int index, char[] array, int start, int end) {
+		int targetLength = target.length;
+		int subLength = end-start;
+		int newTargetLength = subLength+index;
+		if (newTargetLength > targetLength) {
+			System.arraycopy(target, 0, target = new char[newTargetLength*2], 0, index);
+		}
+		System.arraycopy(array, start, target, index, subLength);
+		return target;
+	}
+	/**
+	 * Answers the concatenation of the two arrays. It answers null if the two arrays are null.
+	 * If the first array is null, then the second array is returned.
+	 * If the second array is null, then the first array is returned.
+	 * <br>
+	 * <br>
+	 * For example:
+	 * <ol>
+	 * <li><pre>
+	 *    first = null
+	 *    second = null
+	 *    => result = null
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    first = { { ' a' } }
+	 *    second = null
+	 *    => result = { { ' a' } }
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    first = null
+	 *    second = { { ' a' } }
+	 *    => result = { { ' a' } }
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    first = { { ' b' } }
+	 *    second = { { ' a' } }
+	 *    => result = { { ' b' }, { ' a' } }
+	 * </pre>
+	 * </li>
+	 * </ol>
+	 * 
+	 * @param first the first array to concatenate
+	 * @param second the second array to concatenate
+	 * @return the concatenation of the two arrays, or null if the two arrays are null.
+	 */
+	public static final char[][] arrayConcat(char[][] first, char[][] second) {
+		if (first == null)
+			return second;
+		if (second == null)
+			return first;
+
+		int length1 = first.length;
+		int length2 = second.length;
+		char[][] result = new char[length1 + length2][];
+		System.arraycopy(first, 0, result, 0, length1);
+		System.arraycopy(second, 0, result, length1, length2);
+		return result;
+	}
+	/**
+	 * Answers a new array adding the second array at the end of first array.
+	 * It answers null if the first and second are null.
+	 * If the first array is null, then a new array char[][] is created with second.
+	 * If the second array is null, then the first array is returned.
+	 * <br>
+	 * <br>
+	 * For example:
+	 * <ol>
+	 * <li><pre>
+	 *    first = null
+	 *    second = { 'a' }
+	 *    => result = { { ' a' } }
+	 * </pre>
+	 * <li><pre>
+	 *    first = { { ' a' } }
+	 *    second = null
+	 *    => result = { { ' a' } }
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    first = { { ' a' } }
+	 *    second = { ' b' }
+	 *    => result = { { ' a' } , { ' b' } }
+	 * </pre>
+	 * </li>
+	 * </ol>
+	 * 
+	 * @param first the first array to concatenate
+	 * @param second the array to add at the end of the first array
+	 * @return a new array adding the second array at the end of first array, or null if the two arrays are null.
+	 */
+	public static final char[][] arrayConcat(char[][] first, char[] second) {
+		if (second == null)
+			return first;
+		if (first == null)
+			return new char[][] { second };
+
+		int length = first.length;
+		char[][] result = new char[length + 1][];
+		System.arraycopy(first, 0, result, 0, length);
+		result[length] = second;
+		return result;
+	}
+
+	/**
+	 * Compares the contents of the two arrays array and prefix. Returns
+	 * <ul>
+	 * <li>zero if the array starts with the prefix contents</li>
+	 * <li>the difference between the first two characters that are not equal </li>
+	 * <li>one if array length is lower than the prefix length and that the prefix starts with the 
+	 * array contents.</li>
+	 * </ul>
+	 * <p>
+	 * For example:
+	 * <ol>
+	 * <li><pre>
+	 *    array = null
+	 *    prefix = null
+	 *    => result = NullPointerException
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    array = { 'a', 'b', 'c', 'd', 'e' }
+	 *    prefix = { 'a', 'b', 'c'}
+	 *    => result = 0
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    array = { 'a', 'b', 'c', 'd', 'e' }
+	 *    prefix = { 'a', 'B', 'c'}
+	 *    => result = 32
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    array = { 'd', 'b', 'c', 'd', 'e' }
+	 *    prefix = { 'a', 'b', 'c'}
+	 *    => result = 3
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    array = { 'a', 'b', 'c', 'd', 'e' }
+	 *    prefix = { 'd', 'b', 'c'}
+	 *    => result = -3
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    array = { 'a', 'a', 'c', 'd', 'e' }
+	 *    prefix = { 'a', 'e', 'c'}
+	 *    => result = -4
+	 * </pre>
+	 * </li>
+	 * </ol>
+	 * </p>
+	 * 
+	 * @param array the given array
+	 * @param prefix the given prefix
+	 * @return the result of the comparison
+	 * @exception NullPointerException if either array or prefix is null
+	 */
+	public static final int compareWith(char[] array, char[] prefix) {
+		int arrayLength = array.length;
+		int prefixLength = prefix.length;
+		int min = Math.min(arrayLength, prefixLength);
+		int i = 0;
+		while (min-- != 0) {
+			char c1 = array[i];
+			char c2 = prefix[i++];
+			if (c1 != c2)
+				return c1 - c2;
+		}
+		if (prefixLength == i)
+			return 0;
+		return 1;	
+	}
+	/**
+	 * Answers the concatenation of the two arrays. It answers null if the two arrays are null.
+	 * If the first array is null, then the second array is returned.
+	 * If the second array is null, then the first array is returned.
+	 * <br>
+	 * <br>
+	 * For example:
+	 * <ol>
+	 * <li><pre>
+	 *    first = null
+	 *    second = { 'a' }
+	 *    => result = { ' a' }
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    first = { ' a' }
+	 *    second = null
+	 *    => result = { ' a' }
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    first = { ' a' }
+	 *    second = { ' b' }
+	 *    => result = { ' a' , ' b' }
+	 * </pre>
+	 * </li>
+	 * </ol>
+	 * 
+	 * @param first the first array to concatenate
+	 * @param second the second array to concatenate
+	 * @return the concatenation of the two arrays, or null if the two arrays are null.
+	 */
+	public static final char[] concat(char[] first, char[] second) {
+		if (first == null)
+			return second;
+		if (second == null)
+			return first;
+
+		int length1 = first.length;
+		int length2 = second.length;
+		char[] result = new char[length1 + length2];
+		System.arraycopy(first, 0, result, 0, length1);
+		System.arraycopy(second, 0, result, length1, length2);
+		return result;
+	}
+	/**
+	 * Answers the concatenation of the three arrays. It answers null if the three arrays are null.
+	 * If first is null, it answers the concatenation of second and third.
+	 * If second is null, it answers the concatenation of first and third.
+	 * If third is null, it answers the concatenation of first and second.
+	 * <br>
+	 * <br>
+	 * For example:
+	 * <ol>
+	 * <li><pre>
+	 *    first = null
+	 *    second = { 'a' }
+	 *    third = { 'b' }
+	 *    => result = { ' a', 'b' }
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    first = { 'a' }
+	 *    second = null
+	 *    third = { 'b' }
+	 *    => result = { ' a', 'b' }
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    first = { 'a' }
+	 *    second = { 'b' }
+	 *    third = null
+	 *    => result = { ' a', 'b' }
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    first = null
+	 *    second = null
+	 *    third = null
+	 *    => result = null
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    first = { 'a' }
+	 *    second = { 'b' }
+	 *    third = { 'c' }
+	 *    => result = { 'a', 'b', 'c' }
+	 * </pre>
+	 * </li>
+	 * </ol>
+	 * 
+	 * @param first the first array to concatenate
+	 * @param second the second array to concatenate
+	 * @param third the third array to concatenate
+	 * 
+	 * @return the concatenation of the three arrays, or null if the three arrays are null.
+	 */
+	public static final char[] concat(
+		char[] first,
+		char[] second,
+		char[] third) {
+		if (first == null)
+			return concat(second, third);
+		if (second == null)
+			return concat(first, third);
+		if (third == null)
+			return concat(first, second);
+
+		int length1 = first.length;
+		int length2 = second.length;
+		int length3 = third.length;
+		char[] result = new char[length1 + length2 + length3];
+		System.arraycopy(first, 0, result, 0, length1);
+		System.arraycopy(second, 0, result, length1, length2);
+		System.arraycopy(third, 0, result, length1 + length2, length3);
+		return result;
+	}
+	/**
+	 * Answers the concatenation of the two arrays inserting the separator character between the two arrays.
+	 * It answers null if the two arrays are null.
+	 * If the first array is null, then the second array is returned.
+	 * If the second array is null, then the first array is returned.
+	 * <br>
+	 * <br>
+	 * For example:
+	 * <ol>
+	 * <li><pre>
+	 *    first = null
+	 *    second = { 'a' }
+	 *    separator = '/'
+	 *    => result = { ' a' }
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    first = { ' a' }
+	 *    second = null
+	 *    separator = '/'
+	 *    => result = { ' a' }
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    first = { ' a' }
+	 *    second = { ' b' }
+	 *    separator = '/'
+	 *    => result = { ' a' , '/', 'b' }
+	 * </pre>
+	 * </li>
+	 * </ol>
+	 * 
+	 * @param first the first array to concatenate
+	 * @param second the second array to concatenate
+	 * @param separator the character to insert
+	 * @return the concatenation of the two arrays inserting the separator character 
+	 * between the two arrays , or null if the two arrays are null.
+	 */
+	public static final char[] concat(
+		char[] first,
+		char[] second,
+		char separator) {
+		if (first == null)
+			return second;
+		if (second == null)
+			return first;
+
+		int length1 = first.length;
+		if (length1 == 0)
+			return second;
+		int length2 = second.length;
+		if (length2 == 0)
+			return first;
+
+		char[] result = new char[length1 + length2 + 1];
+		System.arraycopy(first, 0, result, 0, length1);
+		result[length1] = separator;
+		System.arraycopy(second, 0, result, length1 + 1, length2);
+		return result;
+	}
+	/**
+	 * Answers the concatenation of the three arrays inserting the sep1 character between the 
+	 * two arrays and sep2 between the last two.
+	 * It answers null if the three arrays are null.
+	 * If the first array is null, then it answers the concatenation of second and third inserting
+	 * the sep2 character between them.
+	 * If the second array is null, then it answers the concatenation of first and third inserting
+	 * the sep1 character between them.
+	 * If the third array is null, then it answers the concatenation of first and second inserting
+	 * the sep1 character between them.
+	 * <br>
+	 * <br>
+	 * For example:
+	 * <ol>
+	 * <li><pre>
+	 *    first = null
+	 *    sep1 = '/'
+	 *    second = { 'a' }
+	 *    sep2 = ':'
+	 *    third = { 'b' }
+	 *    => result = { ' a' , ':', 'b' }
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    first = { 'a' }
+	 *    sep1 = '/'
+	 *    second = null
+	 *    sep2 = ':'
+	 *    third = { 'b' }
+	 *    => result = { ' a' , '/', 'b' }
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    first = { 'a' }
+	 *    sep1 = '/'
+	 *    second = { 'b' }
+	 *    sep2 = ':'
+	 *    third = null
+	 *    => result = { ' a' , '/', 'b' }
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    first = { 'a' }
+	 *    sep1 = '/'
+	 *    second = { 'b' }
+	 *    sep2 = ':'
+	 *    third = { 'c' }
+	 *    => result = { ' a' , '/', 'b' , ':', 'c' }
+	 * </pre>
+	 * </li>
+	 * </ol>
+	 * 
+	 * @param first the first array to concatenate
+	 * @param sep1 the character to insert
+	 * @param second the second array to concatenate
+	 * @param sep2 the character to insert
+	 * @param third the second array to concatenate
+	 * @return the concatenation of the three arrays inserting the sep1 character between the 
+	 * two arrays and sep2 between the last two.
+	 */
+	public static final char[] concat(
+		char[] first,
+		char sep1,
+		char[] second,
+		char sep2,
+		char[] third) {
+		if (first == null)
+			return concat(second, third, sep2);
+		if (second == null)
+			return concat(first, third, sep1);
+		if (third == null)
+			return concat(first, second, sep1);
+
+		int length1 = first.length;
+		int length2 = second.length;
+		int length3 = third.length;
+		char[] result = new char[length1 + length2 + length3 + 2];
+		System.arraycopy(first, 0, result, 0, length1);
+		result[length1] = sep1;
+		System.arraycopy(second, 0, result, length1 + 1, length2);
+		result[length1 + length2 + 1] = sep2;
+		System.arraycopy(third, 0, result, length1 + length2 + 2, length3);
+		return result;
+	}
+	/**
+	 * Answers a new array with prepending the prefix character and appending the suffix 
+	 * character at the end of the array. If array is null, it answers a new array containing the 
+	 * prefix and the suffix characters.
+	 * <br>
+	 * <br>
+	 * For example:<br>
+	 * <ol>
+	 * <li><pre>
+	 *    prefix = 'a'
+	 *    array = { 'b' }
+	 *    suffix = 'c'
+	 *    => result = { 'a', 'b' , 'c' }
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    prefix = 'a'
+	 *    array = null
+	 *    suffix = 'c'
+	 *    => result = { 'a', 'c' }
+	 * </pre></li>
+	 * </ol>
+	 * 
+	 * @param prefix the prefix character
+	 * @param array the array that is concanated with the prefix and suffix characters
+	 * @param suffix the suffix character
+	 * @return the new array
+	 */
+	public static final char[] concat(char prefix, char[] array, char suffix) {
+		if (array == null)
+			return new char[] { prefix, suffix };
+
+		int length = array.length;
+		char[] result = new char[length + 2];
+		result[0] = prefix;
+		System.arraycopy(array, 0, result, 1, length);
+		result[length + 1] = suffix;
+		return result;
+	}
+	/**
+	 * Answers the concatenation of the given array parts using the given separator between each
+	 * part and appending the given name at the end.
+	 * <br>
+	 * <br>
+	 * For example:<br>
+	 * <ol>
+	 * <li><pre>
+	 *    name = { 'c' }
+	 *    array = { { 'a' }, { 'b' } }
+	 *    separator = '.'
+	 *    => result = { 'a', '.', 'b' , '.', 'c' }
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    name = null
+	 *    array = { { 'a' }, { 'b' } }
+	 *    separator = '.'
+	 *    => result = { 'a', '.', 'b' }
+	 * </pre></li>
+	 * <li><pre>
+	 *    name = { ' c' }
+	 *    array = null
+	 *    separator = '.'
+	 *    => result = { 'c' }
+	 * </pre></li>
+	 * </ol>
+	 * 
+	 * @param name the given name
+	 * @param array the given array
+	 * @param separator the given separator
+	 * @return the concatenation of the given array parts using the given separator between each
+	 * part and appending the given name at the end
+	 */
+	public static final char[] concatWith(
+		char[] name,
+		char[][] array,
+		char separator) {
+		int nameLength = name == null ? 0 : name.length;
+		if (nameLength == 0)
+			return concatWith(array, separator);
+
+		int length = array == null ? 0 : array.length;
+		if (length == 0)
+			return name;
+
+		int size = nameLength;
+		int index = length;
+		while (--index >= 0)
+			if (array[index].length > 0)
+				size += array[index].length + 1;
+		char[] result = new char[size];
+		index = size;
+		for (int i = length - 1; i >= 0; i--) {
+			int subLength = array[i].length;
+			if (subLength > 0) {
+				index -= subLength;
+				System.arraycopy(array[i], 0, result, index, subLength);
+				result[--index] = separator;
+			}
+		}
+		System.arraycopy(name, 0, result, 0, nameLength);
+		return result;
+	}
+	/**
+	 * Answers the concatenation of the given array parts using the given separator between each
+	 * part and appending the given name at the end.
+	 * <br>
+	 * <br>
+	 * For example:<br>
+	 * <ol>
+	 * <li><pre>
+	 *    name = { 'c' }
+	 *    array = { { 'a' }, { 'b' } }
+	 *    separator = '.'
+	 *    => result = { 'a', '.', 'b' , '.', 'c' }
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    name = null
+	 *    array = { { 'a' }, { 'b' } }
+	 *    separator = '.'
+	 *    => result = { 'a', '.', 'b' }
+	 * </pre></li>
+	 * <li><pre>
+	 *    name = { ' c' }
+	 *    array = null
+	 *    separator = '.'
+	 *    => result = { 'c' }
+	 * </pre></li>
+	 * </ol>
+	 * 
+	 * @param array the given array
+	 * @param name the given name
+	 * @param separator the given separator
+	 * @return the concatenation of the given array parts using the given separator between each
+	 * part and appending the given name at the end
+	 */
+	public static final char[] concatWith(
+		char[][] array,
+		char[] name,
+		char separator) {
+		int nameLength = name == null ? 0 : name.length;
+		if (nameLength == 0)
+			return concatWith(array, separator);
+
+		int length = array == null ? 0 : array.length;
+		if (length == 0)
+			return name;
+
+		int size = nameLength;
+		int index = length;
+		while (--index >= 0)
+			if (array[index].length > 0)
+				size += array[index].length + 1;
+		char[] result = new char[size];
+		index = 0;
+		for (int i = 0; i < length; i++) {
+			int subLength = array[i].length;
+			if (subLength > 0) {
+				System.arraycopy(array[i], 0, result, index, subLength);
+				index += subLength;
+				result[index++] = separator;
+			}
+		}
+		System.arraycopy(name, 0, result, index, nameLength);
+		return result;
+	}
+	/**
+	 * Answers the concatenation of the given array parts using the given separator between each part.
+	 * <br>
+	 * <br>
+	 * For example:<br>
+	 * <ol>
+	 * <li><pre>
+	 *    array = { { 'a' }, { 'b' } }
+	 *    separator = '.'
+	 *    => result = { 'a', '.', 'b' }
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    array = null
+	 *    separator = '.'
+	 *    => result = { }
+	 * </pre></li>
+	 * </ol>
+	 * 
+	 * @param array the given array
+	 * @param separator the given separator
+	 * @return the concatenation of the given array parts using the given separator between each part
+	 */
+	public static final char[] concatWith(char[][] array, char separator) {
+		int length = array == null ? 0 : array.length;
+		if (length == 0)
+			return CharOperation.NO_CHAR;
+
+		int size = length - 1;
+		int index = length;
+		while (--index >= 0) {
+			if (array[index].length == 0)
+				size--;
+			else
+				size += array[index].length;
+		}
+		if (size <= 0)
+			return CharOperation.NO_CHAR;
+		char[] result = new char[size];
+		index = length;
+		while (--index >= 0) {
+			length = array[index].length;
+			if (length > 0) {
+				System.arraycopy(
+					array[index],
+					0,
+					result,
+					(size -= length),
+					length);
+				if (--size >= 0)
+					result[size] = separator;
+			}
+		}
+		return result;
+	}
+	/**
+	 * Answers true if the array contains an occurrence of character, false otherwise.
+	 * 
+	 * <br>
+	 * <br>
+	 * For example:
+	 * <ol>
+	 * <li><pre>
+	 *    character = 'c'
+	 *    array = { { ' a' }, { ' b' } }
+	 *    result => false
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    character = 'a'
+	 *    array = { { ' a' }, { ' b' } }
+	 *    result => true
+	 * </pre>
+	 * </li>
+	 * </ol>
+	 * 
+	 * @param character the character to search
+	 * @param array the array in which the search is done
+	 * @return true if the array contains an occurrence of character, false otherwise.
+	 * @exception NullPointerException if array is null.
+	 */
+	public static final boolean contains(char character, char[][] array) {
+		for (int i = array.length; --i >= 0;) {
+			char[] subarray = array[i];
+			for (int j = subarray.length; --j >= 0;)
+				if (subarray[j] == character)
+					return true;
+		}
+		return false;
+	}
+	/**
+	 * Answers true if the array contains an occurrence of character, false otherwise.
+	 * 
+	 * <br>
+	 * <br>
+	 * For example:
+	 * <ol>
+	 * <li><pre>
+	 *    character = 'c'
+	 *    array = { ' b'  }
+	 *    result => false
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    character = 'a'
+	 *    array = { ' a' , ' b' }
+	 *    result => true
+	 * </pre>
+	 * </li>
+	 * </ol>
+	 * 
+	 * @param character the character to search
+	 * @param array the array in which the search is done
+	 * @return true if the array contains an occurrence of character, false otherwise.
+	 * @exception NullPointerException if array is null.
+	 */
+	public static final boolean contains(char character, char[] array) {
+		for (int i = array.length; --i >= 0;)
+			if (array[i] == character)
+				return true;
+		return false;
+	}
+	/**
+	 * Answers a deep copy of the toCopy array.
+	 * 
+	 * @param toCopy the array to copy
+	 * @return a deep copy of the toCopy array.
+	 */
+	public static final char[][] deepCopy(char[][] toCopy) {
+		int toCopyLength = toCopy.length;
+		char[][] result = new char[toCopyLength][];
+		for (int i = 0; i < toCopyLength; i++) {
+			char[] toElement = toCopy[i];
+			int toElementLength = toElement.length;
+			char[] resultElement = new char[toElementLength];
+			System.arraycopy(toElement, 0, resultElement, 0, toElementLength);
+			result[i] = resultElement;
+		}
+		return result;
+	}
+	/**
+	 * Return true if array ends with the sequence of characters contained in toBeFound, 
+	 * otherwise false.
+	 * <br>
+	 * <br>
+	 * For example:
+	 * <ol>
+	 * <li><pre>
+	 *    array = { 'a', 'b', 'c', 'd' }
+	 *    toBeFound = { 'b', 'c' }
+	 *    result => false
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    array = { 'a', 'b', 'c' }
+	 *    toBeFound = { 'b', 'c' }
+	 *    result => true
+	 * </pre>
+	 * </li>
+	 * </ol>
+	 * 
+	 * @param array the array to check
+	 * @param toBeFound the array to find
+	 * @return true if array ends with the sequence of characters contained in toBeFound, 
+	 * otherwise false.
+	 * @exception NullPointerException if array is null or toBeFound is null
+	 */
+	public static final boolean endsWith(char[] array, char[] toBeFound) {
+		int i = toBeFound.length;
+		int j = array.length - i;
+
+		if (j < 0)
+			return false;
+		while (--i >= 0)
+			if (toBeFound[i] != array[i + j])
+				return false;
+		return true;
+	}
+	/**
+	 * Answers true if the two arrays are identical character by character, otherwise false.
+	 * The equality is case sensitive.
+	 * <br>
+	 * <br>
+	 * For example:
+	 * <ol>
+	 * <li><pre>
+	 *    first = null
+	 *    second = null
+	 *    result => true
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    first = { { } }
+	 *    second = null
+	 *    result => false
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    first = { { 'a' } }
+	 *    second = { { 'a' } }
+	 *    result => true
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    first = { { 'A' } }
+	 *    second = { { 'a' } }
+	 *    result => false
+	 * </pre>
+	 * </li>
+	 * </ol>
+	 * @param first the first array
+	 * @param second the second array
+	 * @return true if the two arrays are identical character by character, otherwise false
+	 */
+	public static final boolean equals(char[][] first, char[][] second) {
+		if (first == second)
+			return true;
+		if (first == null || second == null)
+			return false;
+		if (first.length != second.length)
+			return false;
+
+		for (int i = first.length; --i >= 0;)
+			if (!equals(first[i], second[i]))
+				return false;
+		return true;
+	}
+	/**
+	 * If isCaseSensite is true, answers true if the two arrays are identical character
+	 * by character, otherwise false.
+	 * If it is false, answers true if the two arrays are identical character by 
+	 * character without checking the case, otherwise false.
+	 * <br>
+	 * <br>
+	 * For example:
+	 * <ol>
+	 * <li><pre>
+	 *    first = null
+	 *    second = null
+	 *    isCaseSensitive = true
+	 *    result => true
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    first = { { } }
+	 *    second = null
+	 *    isCaseSensitive = true
+	 *    result => false
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    first = { { 'A' } }
+	 *    second = { { 'a' } }
+	 *    isCaseSensitive = true
+	 *    result => false
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    first = { { 'A' } }
+	 *    second = { { 'a' } }
+	 *    isCaseSensitive = false
+	 *    result => true
+	 * </pre>
+	 * </li>
+	 * </ol>
+	 * 
+	 * @param first the first array
+	 * @param second the second array
+	 * @param isCaseSensitive check whether or not the equality should be case sensitive
+	 * @return true if the two arrays are identical character by character according to the value
+	 * of isCaseSensitive, otherwise false
+	 */
+	public static final boolean equals(
+		char[][] first,
+		char[][] second,
+		boolean isCaseSensitive) {
+
+		if (isCaseSensitive) {
+			return equals(first, second);
+		}
+		if (first == second)
+			return true;
+		if (first == null || second == null)
+			return false;
+		if (first.length != second.length)
+			return false;
+
+		for (int i = first.length; --i >= 0;)
+			if (!equals(first[i], second[i], false))
+				return false;
+		return true;
+	}
+	/**
+	 * Answers true if the two arrays are identical character by character, otherwise false.
+	 * The equality is case sensitive.
+	 * <br>
+	 * <br>
+	 * For example:
+	 * <ol>
+	 * <li><pre>
+	 *    first = null
+	 *    second = null
+	 *    result => true
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    first = { }
+	 *    second = null
+	 *    result => false
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    first = { 'a' }
+	 *    second = { 'a' }
+	 *    result => true
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    first = { 'a' }
+	 *    second = { 'A' }
+	 *    result => false
+	 * </pre>
+	 * </li>
+	 * </ol>
+	 * @param first the first array
+	 * @param second the second array
+	 * @return true if the two arrays are identical character by character, otherwise false
+	 */
+	public static final boolean equals(char[] first, char[] second) {
+		if (first == second)
+			return true;
+		if (first == null || second == null)
+			return false;
+		if (first.length != second.length)
+			return false;
+
+		for (int i = first.length; --i >= 0;)
+			if (first[i] != second[i])
+				return false;
+		return true;
+	}
+	/**
+	 * If isCaseSensite is true, answers true if the two arrays are identical character
+	 * by character, otherwise false.
+	 * If it is false, answers true if the two arrays are identical character by 
+	 * character without checking the case, otherwise false.
+	 * <br>
+	 * <br>
+	 * For example:
+	 * <ol>
+	 * <li><pre>
+	 *    first = null
+	 *    second = null
+	 *    isCaseSensitive = true
+	 *    result => true
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    first = { }
+	 *    second = null
+	 *    isCaseSensitive = true
+	 *    result => false
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    first = { 'A' }
+	 *    second = { 'a' }
+	 *    isCaseSensitive = true
+	 *    result => false
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    first = { 'A' }
+	 *    second = { 'a' }
+	 *    isCaseSensitive = false
+	 *    result => true
+	 * </pre>
+	 * </li>
+	 * </ol>
+	 * 
+	 * @param first the first array
+	 * @param second the second array
+	 * @param isCaseSensitive check whether or not the equality should be case sensitive
+	 * @return true if the two arrays are identical character by character according to the value
+	 * of isCaseSensitive, otherwise false
+	 */
+	public static final boolean equals(
+		char[] first,
+		char[] second,
+		boolean isCaseSensitive) {
+
+		if (isCaseSensitive) {
+			return equals(first, second);
+		}
+		if (first == second)
+			return true;
+		if (first == null || second == null)
+			return false;
+		if (first.length != second.length)
+			return false;
+
+		for (int i = first.length; --i >= 0;)
+			if (Character.toLowerCase(first[i])
+				!= Character.toLowerCase(second[i]))
+				return false;
+		return true;
+	}
+	/**
+	 * If isCaseSensite is true, the equality is case sensitive, otherwise it is case insensitive.
+	 * 
+	 * Answers true if the name contains the fragment at the starting index startIndex, otherwise false.
+	 * <br>
+	 * <br>
+	 * For example:
+	 * <ol>
+	 * <li><pre>
+	 *    fragment = { 'b', 'c' , 'd' }
+	 *    name = { 'a', 'b', 'c' , 'd' }
+	 *    startIndex = 1
+	 *    isCaseSensitive = true
+	 *    result => true
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    fragment = { 'b', 'c' , 'd' }
+	 *    name = { 'a', 'b', 'C' , 'd' }
+	 *    startIndex = 1
+	 *    isCaseSensitive = true
+	 *    result => false
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    fragment = { 'b', 'c' , 'd' }
+	 *    name = { 'a', 'b', 'C' , 'd' }
+	 *    startIndex = 0
+	 *    isCaseSensitive = false
+	 *    result => false
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    fragment = { 'b', 'c' , 'd' }
+	 *    name = { 'a', 'b'}
+	 *    startIndex = 0
+	 *    isCaseSensitive = true
+	 *    result => false
+	 * </pre>
+	 * </li>
+	 * </ol>
+	 * 
+	 * @param fragment the fragment to check
+	 * @param second the array to check
+	 * @param startIndex the starting index
+	 * @param isCaseSensitive check whether or not the equality should be case sensitive
+	 * @return true if the name contains the fragment at the starting index startIndex according to the 
+	 * value of isCaseSensitive, otherwise false.
+	 * @exception NullPointerException if fragment or name is null.
+	 */
+	public static final boolean fragmentEquals(
+		char[] fragment,
+		char[] name,
+		int startIndex,
+		boolean isCaseSensitive) {
+
+		int max = fragment.length;
+		if (name.length < max + startIndex)
+			return false;
+		if (isCaseSensitive) {
+			for (int i = max;
+				--i >= 0;
+				) // assumes the prefix is not larger than the name
+				if (fragment[i] != name[i + startIndex])
+					return false;
+			return true;
+		}
+		for (int i = max;
+			--i >= 0;
+			) // assumes the prefix is not larger than the name
+			if (Character.toLowerCase(fragment[i])
+				!= Character.toLowerCase(name[i + startIndex]))
+				return false;
+		return true;
+	}
+	/**
+	 * Answers a hashcode for the array
+	 * 
+	 * @param array the array for which a hashcode is required
+	 * @return the hashcode
+	 * @exception NullPointerException if array is null
+	 */
+	public static final int hashCode(char[] array) {
+		int hash = 0;
+		int offset = 0;
+		int length = array.length;
+		if (length < 16) {
+			for (int i = length; i > 0; i--)
+				hash = (hash * 37) + array[offset++];
+		} else {
+			// only sample some characters
+			int skip = length / 8;
+			for (int i = length; i > 0; i -= skip, offset += skip)
+				hash = (hash * 39) + array[offset];
+		}
+		return hash & 0x7FFFFFFF;
+	}
+	/**
+	 * Answers true if c is a whitespace according to the JLS (&#92;u000a, &#92;u000c, &#92;u000d, &#92;u0009), otherwise false.
+	 * <br>
+	 * <br>
+	 * For example:
+	 * <ol>
+	 * <li><pre>
+	 *    c = ' '
+	 *    result => true
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    c = '&#92;u3000'
+	 *    result => false
+	 * </pre>
+	 * </li>
+	 * </ol>
+	 * 
+	 * @param c the character to check
+	 * @return true if c is a whitespace according to the JLS, otherwise false.
+	 */
+	public static boolean isWhitespace(char c) {
+		switch (c) {
+			case 10 : /* \ u000a: LINE FEED               */
+			case 12 : /* \ u000c: FORM FEED               */
+			case 13 : /* \ u000d: CARRIAGE RETURN         */
+			case 32 : /* \ u0020: SPACE                   */
+			case 9 : /* \ u0009: HORIZONTAL TABULATION   */
+				return true;
+			default :
+				return false;
+		}
+	}
+	/**
+	 * Answers the first index in the array for which the corresponding character is
+	 * equal to toBeFound. Answers -1 if no occurrence of this character is found.
+	 * <br>
+	 * <br>
+	 * For example:
+	 * <ol>
+	 * <li><pre>
+	 *    toBeFound = 'c'
+	 *    array = { ' a', 'b', 'c', 'd' }
+	 *    result => 2
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    toBeFound = 'e'
+	 *    array = { ' a', 'b', 'c', 'd' }
+	 *    result => -1
+	 * </pre>
+	 * </li>
+	 * </ol>
+	 * 
+	 * @param toBeFound the character to search
+	 * @param array the array to be searched
+	 * @return the first index in the array for which the corresponding character is
+	 * equal to toBeFound, -1 otherwise
+	 * @exception NullPointerException if array is null
+	 */
+	public static final int indexOf(char toBeFound, char[] array) {
+		for (int i = 0; i < array.length; i++)
+			if (toBeFound == array[i])
+				return i;
+		return -1;
+	}
+	/**
+	 * Answers the first index in the array for which the corresponding character is
+	 * equal to toBeFound starting the search at index start.
+	 * Answers -1 if no occurrence of this character is found.
+	 * <br>
+	 * <br>
+	 * For example:
+	 * <ol>
+	 * <li><pre>
+	 *    toBeFound = 'c'
+	 *    array = { ' a', 'b', 'c', 'd' }
+	 *    start = 2
+	 *    result => 2
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    toBeFound = 'c'
+	 *    array = { ' a', 'b', 'c', 'd' }
+	 *    start = 3
+	 *    result => -1
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    toBeFound = 'e'
+	 *    array = { ' a', 'b', 'c', 'd' }
+	 *    start = 1
+	 *    result => -1
+	 * </pre>
+	 * </li>
+	 * </ol>
+	 * 
+	 * @param toBeFound the character to search
+	 * @param array the array to be searched
+	 * @param start the starting index
+	 * @return the first index in the array for which the corresponding character is
+	 * equal to toBeFound, -1 otherwise
+	 * @exception NullPointerException if array is null
+	 * @exception ArrayIndexOutOfBoundsException if  start is lower than 0
+	 */
+	public static final int indexOf(char toBeFound, char[] array, int start) {
+		for (int i = start; i < array.length; i++)
+			if (toBeFound == array[i])
+				return i;
+		return -1;
+	}
+	/**
+	 * Answers the last index in the array for which the corresponding character is
+	 * equal to toBeFound starting from the end of the array.
+	 * Answers -1 if no occurrence of this character is found.
+	 * <br>
+	 * <br>
+	 * For example:
+	 * <ol>
+	 * <li><pre>
+	 *    toBeFound = 'c'
+	 *    array = { ' a', 'b', 'c', 'd' , 'c', 'e' }
+	 *    result => 4
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    toBeFound = 'e'
+	 *    array = { ' a', 'b', 'c', 'd' }
+	 *    result => -1
+	 * </pre>
+	 * </li>
+	 * </ol>
+	 *
+	 * @param toBeFound the character to search
+	 * @param array the array to be searched
+	 * @return the last index in the array for which the corresponding character is
+	 * equal to toBeFound starting from the end of the array, -1 otherwise
+	 * @exception NullPointerException if array is null
+	 */
+	public static final int lastIndexOf(char toBeFound, char[] array) {
+		for (int i = array.length; --i >= 0;)
+			if (toBeFound == array[i])
+				return i;
+		return -1;
+	}
+	/**
+	 * Answers the last index in the array for which the corresponding character is
+	 * equal to toBeFound stopping at the index startIndex.
+	 * Answers -1 if no occurrence of this character is found.
+	 * <br>
+	 * <br>
+	 * For example:
+	 * <ol>
+	 * <li><pre>
+	 *    toBeFound = 'c'
+	 *    array = { ' a', 'b', 'c', 'd' }
+	 *    startIndex = 2
+	 *    result => 2
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    toBeFound = 'c'
+	 *    array = { ' a', 'b', 'c', 'd', 'e' }
+	 *    startIndex = 3
+	 *    result => -1
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    toBeFound = 'e'
+	 *    array = { ' a', 'b', 'c', 'd' }
+	 *    startIndex = 0
+	 *    result => -1
+	 * </pre>
+	 * </li>
+	 * </ol>
+	 *
+	 * @param toBeFound the character to search
+	 * @param array the array to be searched
+	 * @param startIndex the stopping index
+	 * @return the last index in the array for which the corresponding character is
+	 * equal to toBeFound stopping at the index startIndex, -1 otherwise
+	 * @exception NullPointerException if array is null
+	 * @exception ArrayIndexOutOfBoundsException if startIndex is lower than 0
+	 */
+	public static final int lastIndexOf(
+		char toBeFound,
+		char[] array,
+		int startIndex) {
+		for (int i = array.length; --i >= startIndex;)
+			if (toBeFound == array[i])
+				return i;
+		return -1;
+	}
+	/**
+	 * Answers the last index in the array for which the corresponding character is
+	 * equal to toBeFound starting from endIndex to startIndex.
+	 * Answers -1 if no occurrence of this character is found.
+	 * <br>
+	 * <br>
+	 * For example:
+	 * <ol>
+	 * <li><pre>
+	 *    toBeFound = 'c'
+	 *    array = { ' a', 'b', 'c', 'd' }
+	 *    startIndex = 2
+	 *    endIndex = 2
+	 *    result => 2
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    toBeFound = 'c'
+	 *    array = { ' a', 'b', 'c', 'd', 'e' }
+	 *    startIndex = 3
+	 *    endIndex = 4
+	 *    result => -1
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    toBeFound = 'e'
+	 *    array = { ' a', 'b', 'c', 'd' }
+	 *    startIndex = 0
+	 *    endIndex = 3
+	 *    result => -1
+	 * </pre>
+	 * </li>
+	 * </ol>
+	 * 
+	 * @param toBeFound the character to search
+	 * @param array the array to be searched
+	 * @param startIndex the stopping index
+	 * @param endIndex the starting index
+	 * @return the last index in the array for which the corresponding character is
+	 * equal to toBeFound starting from endIndex to startIndex, -1 otherwise
+	 * @exception NullPointerException if array is null
+	 * @exception ArrayIndexOutOfBoundsException if endIndex is greater or equals to array length or starting is lower than 0
+	 */
+	public static final int lastIndexOf(
+		char toBeFound,
+		char[] array,
+		int startIndex,
+		int endIndex) {
+		for (int i = endIndex; --i >= startIndex;)
+			if (toBeFound == array[i])
+				return i;
+		return -1;
+	}
+	/**
+	 * Answers the last portion of a name given a separator.
+	 * <br>
+	 * <br>
+	 * For example,
+	 * <pre>
+	 * 	lastSegment("java.lang.Object".toCharArray(),'.') --> Object
+	 * </pre>
+	 * 
+	 * @param array the array
+	 * @param separator the given separator
+	 * @return the last portion of a name given a separator
+	 * @exception NullPointerException if array is null
+	 */
+	final static public char[] lastSegment(char[] array, char separator) {
+		int pos = lastIndexOf(separator, array);
+		if (pos < 0)
+			return array;
+		return subarray(array, pos + 1, array.length);
+	}
+	/**
+	 * Answers true if the pattern matches the given name, false otherwise. This char[] pattern matching
+	 * accepts wild-cards '*' and '?'.
+	 *
+	 * When not case sensitive, the pattern is assumed to already be lowercased, the
+	 * name will be lowercased character per character as comparing.
+	 * If name is null, the answer is false.
+	 * If pattern is null, the answer is true if name is not null.
+	 * <br>
+	 * <br>
+	 * For example:
+	 * <ol>
+	 * <li><pre>
+	 *    pattern = { '?', 'b', '*' }
+	 *    name = { 'a', 'b', 'c' , 'd' }
+	 *    isCaseSensitive = true
+	 *    result => true
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    pattern = { '?', 'b', '?' }
+	 *    name = { 'a', 'b', 'c' , 'd' }
+	 *    isCaseSensitive = true
+	 *    result => false
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    pattern = { 'b', '*' }
+	 *    name = { 'a', 'b', 'c' , 'd' }
+	 *    isCaseSensitive = true
+	 *    result => false
+	 * </pre>
+	 * </li>
+	 * </ol>
+	 * 
+	 * @param pattern the given pattern
+	 * @param name the given name
+	 * @param isCaseSensitive flag to know whether or not the matching should be case sensitive
+	 * @return true if the pattern matches the given name, false otherwise
+	 */
+	public static final boolean match(
+		char[] pattern,
+		char[] name,
+		boolean isCaseSensitive) {
+
+		if (name == null)
+			return false; // null name cannot match
+		if (pattern == null)
+			return true; // null pattern is equivalent to '*'
+
+		return match(
+			pattern,
+			0,
+			pattern.length,
+			name,
+			0,
+			name.length,
+			isCaseSensitive);
+	}
+	/**
+	 * Answers true if the a sub-pattern matches the subpart of the given name, false otherwise.
+	 * char[] pattern matching, accepting wild-cards '*' and '?'. Can match only subset of name/pattern.
+	 * end positions are non-inclusive.
+	 * The subpattern is defined by the patternStart and pattternEnd positions.
+	 * When not case sensitive, the pattern is assumed to already be lowercased, the
+	 * name will be lowercased character per character as comparing.
+	 * <br>
+	 * <br>
+	 * For example:
+	 * <ol>
+	 * <li><pre>
+	 *    pattern = { '?', 'b', '*' }
+	 *    patternStart = 1
+	 *    patternEnd = 3
+	 *    name = { 'a', 'b', 'c' , 'd' }
+	 *    nameStart = 1
+	 *    nameEnd = 4
+	 *    isCaseSensitive = true
+	 *    result => true
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    pattern = { '?', 'b', '*' }
+	 *    patternStart = 1
+	 *    patternEnd = 2
+	 *    name = { 'a', 'b', 'c' , 'd' }
+	 *    nameStart = 1
+	 *    nameEnd = 2
+	 *    isCaseSensitive = true
+	 *    result => false
+	 * </pre>
+	 * </li>
+	 * </ol>
+	 * 
+	 * @param pattern the given pattern
+	 * @param patternStart the given pattern start
+	 * @param patternEnd the given pattern end
+	 * @param name the given name
+	 * @param nameStart the given name start
+	 * @param nameEnd the given name end
+	 * @param isCaseSensitive flag to know if the matching should be case sensitive
+	 * @return true if the a sub-pattern matches the subpart of the given name, false otherwise
+	 */
+	public static final boolean match(
+		char[] pattern,
+		int patternStart,
+		int patternEnd,
+		char[] name,
+		int nameStart,
+		int nameEnd,
+		boolean isCaseSensitive) {
+
+		if (name == null)
+			return false; // null name cannot match
+		if (pattern == null)
+			return true; // null pattern is equivalent to '*'
+		int iPattern = patternStart;
+		int iName = nameStart;
+
+		if (patternEnd < 0)
+			patternEnd = pattern.length;
+		if (nameEnd < 0)
+			nameEnd = name.length;
+
+		/* check first segment */
+		char patternChar = 0;
+		while ((iPattern < patternEnd)
+			&& (patternChar = pattern[iPattern]) != '*') {
+			if (iName == nameEnd)
+				return false;
+			if (patternChar
+				!= (isCaseSensitive
+					? name[iName]
+					: Character.toLowerCase(name[iName]))
+				&& patternChar != '?') {
+				return false;
+			}
+			iName++;
+			iPattern++;
+		}
+		/* check sequence of star+segment */
+		int segmentStart;
+		if (patternChar == '*') {
+			segmentStart = ++iPattern; // skip star
+		} else {
+			segmentStart = 0; // force iName check
+		}
+		int prefixStart = iName;
+		checkSegment : while (iName < nameEnd) {
+			if (iPattern == patternEnd) {
+				iPattern = segmentStart; // mismatch - restart current segment
+				iName = ++prefixStart;
+				continue checkSegment;
+			}
+			/* segment is ending */
+			if ((patternChar = pattern[iPattern]) == '*') {
+				segmentStart = ++iPattern; // skip start
+				if (segmentStart == patternEnd) {
+					return true;
+				}
+				prefixStart = iName;
+				continue checkSegment;
+			}
+			/* check current name character */
+			if ((isCaseSensitive ? name[iName] : Character.toLowerCase(name[iName]))
+						!= patternChar
+					&& patternChar != '?') {
+				iPattern = segmentStart; // mismatch - restart current segment
+				iName = ++prefixStart;
+				continue checkSegment;
+			}
+			iName++;
+			iPattern++;
+		}
+
+		return (segmentStart == patternEnd)
+			|| (iName == nameEnd && iPattern == patternEnd)
+			|| (iPattern == patternEnd - 1 && pattern[iPattern] == '*');
+	}
+	/**
+	 * Answers true if the pattern matches the filepath using the pathSepatator, false otherwise.
+	 * 
+	 * Path char[] pattern matching, accepting wild-cards '**', '*' and '?' (using Ant directory tasks
+	 * conventions, also see "http://jakarta.apache.org/ant/manual/dirtasks.html#defaultexcludes";).
+	 * Path pattern matching is enhancing regular pattern matching in supporting extra rule where '**' represent
+	 * any folder combination.
+	 * Special rules: 
+	 * - foo\  is equivalent to foo\**   
+	 * - *.java is equivalent to **\*.java
+	 * When not case sensitive, the pattern is assumed to already be lowercased, the
+	 * name will be lowercased character per character as comparing.
+	 * 
+	 * @param pattern the given pattern
+	 * @param filepath the given path 
+	 * @param isCaseSensitive to find out whether or not the matching should be case sensitive
+	 * @param pathSeparator the given path separator
+	 * @return true if the pattern matches the filepath using the pathSepatator, false otherwise
+	 */
+	public static final boolean pathMatch(
+		char[] pattern,
+		char[] filepath,
+		boolean isCaseSensitive,
+		char pathSeparator) {
+
+		if (filepath == null)
+			return false; // null name cannot match
+		if (pattern == null)
+			return true; // null pattern is equivalent to '*'
+
+		// special case: pattern foo is equivalent to **\foo (not absolute)
+		boolean freeLeadingDoubleStar;
+
+		// offsets inside pattern
+		int pSegmentStart, pLength = pattern.length;
+
+		if (freeLeadingDoubleStar = pattern[0] != pathSeparator){
+			pSegmentStart = 0;
+		} else {
+			pSegmentStart = 1;
+		}
+		int pSegmentEnd = CharOperation.indexOf(pathSeparator, pattern, pSegmentStart+1);
+		if (pSegmentEnd < 0) pSegmentEnd = pLength;
+
+		// special case: pattern foo\ is equivalent to foo\**
+		boolean freeTrailingDoubleStar = pattern[pLength - 1] == pathSeparator;
+
+		// offsets inside filepath
+		int fSegmentStart, fLength = filepath.length;
+		if (filepath[0] != pathSeparator){
+			fSegmentStart = 0;
+		} else {
+			fSegmentStart = 1;
+		}
+		if (fSegmentStart != pSegmentStart) {
+			return false; // both must start with a separator or none.
+		}
+		int fSegmentEnd = CharOperation.indexOf(pathSeparator, filepath, fSegmentStart+1);
+		if (fSegmentEnd < 0) fSegmentEnd = fLength;
+
+		// first segments
+		while (pSegmentStart < pLength
+			&& !freeLeadingDoubleStar
+			&& !(pSegmentEnd == pLength && freeTrailingDoubleStar
+					|| (pSegmentEnd == pSegmentStart + 2
+							&& pattern[pSegmentStart] == '*'
+							&& pattern[pSegmentStart + 1] == '*'))) {
+
+			if (fSegmentStart >= fLength)
+				return false;
+			if (!CharOperation
+				.match(
+					pattern,
+					pSegmentStart,
+					pSegmentEnd,
+					filepath,
+					fSegmentStart,
+					fSegmentEnd,
+					isCaseSensitive)) {
+				return false;
+			}
+
+			// jump to next segment		
+			pSegmentEnd =
+				CharOperation.indexOf(
+					pathSeparator,
+					pattern,
+					pSegmentStart = pSegmentEnd + 1);
+			// skip separator
+			if (pSegmentEnd < 0)
+				pSegmentEnd = pLength;
+
+			fSegmentEnd =
+				CharOperation.indexOf(
+					pathSeparator,
+					filepath,
+					fSegmentStart = fSegmentEnd + 1);
+			// skip separator
+			if (fSegmentEnd < 0) fSegmentEnd = fLength;
+		}
+
+		/* check sequence of doubleStar+segment */
+		int pSegmentRestart;
+		if ((pSegmentStart >= pLength && freeTrailingDoubleStar)
+				|| (pSegmentEnd == pSegmentStart + 2
+					&& pattern[pSegmentStart] == '*'
+					&& pattern[pSegmentStart + 1] == '*')) {
+			pSegmentEnd =
+				CharOperation.indexOf(
+					pathSeparator,
+					pattern,
+					pSegmentStart = pSegmentEnd + 1);
+			// skip separator
+			if (pSegmentEnd < 0) pSegmentEnd = pLength;
+			pSegmentRestart = pSegmentStart;
+		} else {
+			if (pSegmentStart >= pLength) return fSegmentStart >= fLength; // true if filepath is done too.
+			pSegmentRestart = 0; // force fSegmentStart check
+		}
+		int fSegmentRestart = fSegmentStart;
+		checkSegment : while (fSegmentStart < fLength) {
+				
+			if (pSegmentStart >= pLength) {
+				if (freeTrailingDoubleStar) return true;
+				// mismatch - restart current path segment
+				pSegmentEnd =
+					CharOperation.indexOf(pathSeparator, pattern, pSegmentStart = pSegmentRestart);
+				if (pSegmentEnd < 0) pSegmentEnd = pLength;
+
+				fSegmentRestart = 
+					CharOperation.indexOf(pathSeparator, filepath, fSegmentRestart + 1);
+				// skip separator
+				if (fSegmentRestart < 0) {
+					fSegmentRestart = fLength;
+				} else {
+					fSegmentRestart++;
+				}
+				fSegmentEnd =
+					CharOperation.indexOf(pathSeparator, filepath, fSegmentStart = fSegmentRestart);
+				if (fSegmentEnd < 0) fSegmentEnd = fLength;
+				continue checkSegment;
+			}
+			
+			/* path segment is ending */
+			if (pSegmentEnd == pSegmentStart + 2
+				&& pattern[pSegmentStart] == '*'
+				&& pattern[pSegmentStart + 1] == '*') {
+				pSegmentEnd =
+					CharOperation.indexOf(pathSeparator, pattern, pSegmentStart = pSegmentEnd + 1);
+				// skip separator
+				if (pSegmentEnd < 0) pSegmentEnd = pLength;
+				pSegmentRestart = pSegmentStart;
+				fSegmentRestart = fSegmentStart;
+				if (pSegmentStart >= pLength) return true;
+				continue checkSegment;
+			}
+			/* chech current path segment */
+			if (!CharOperation.match(
+								pattern,
+								pSegmentStart,
+								pSegmentEnd,
+								filepath,
+								fSegmentStart,
+								fSegmentEnd,
+								isCaseSensitive)) {
+				// mismatch - restart current path segment
+				pSegmentEnd =
+					CharOperation.indexOf(pathSeparator, pattern, pSegmentStart = pSegmentRestart);
+				if (pSegmentEnd < 0) pSegmentEnd = pLength;
+
+				fSegmentRestart = 
+					CharOperation.indexOf(pathSeparator, filepath, fSegmentRestart + 1);
+				// skip separator
+				if (fSegmentRestart < 0) {
+					fSegmentRestart = fLength;
+				} else {
+					fSegmentRestart++;
+				}
+				fSegmentEnd =
+					CharOperation.indexOf(pathSeparator, filepath, fSegmentStart = fSegmentRestart);
+				if (fSegmentEnd < 0) fSegmentEnd = fLength;
+				continue checkSegment;
+			}
+			// jump to next segment		
+			pSegmentEnd =
+				CharOperation.indexOf(
+					pathSeparator,
+					pattern,
+					pSegmentStart = pSegmentEnd + 1);
+			// skip separator
+			if (pSegmentEnd < 0)
+				pSegmentEnd = pLength;
+
+			fSegmentEnd =
+				CharOperation.indexOf(
+					pathSeparator,
+					filepath,
+					fSegmentStart = fSegmentEnd + 1);
+			// skip separator
+			if (fSegmentEnd < 0)
+				fSegmentEnd = fLength;
+		}
+
+		return (pSegmentRestart >= pSegmentEnd)
+			|| (fSegmentStart >= fLength && pSegmentStart >= pLength)
+			|| (pSegmentStart == pLength - 2
+				&& pattern[pSegmentStart] == '*'
+				&& pattern[pSegmentStart + 1] == '*')
+			|| (pSegmentStart == pLength && freeTrailingDoubleStar);
+	}
+	/**
+	 * Answers the number of occurrences of the given character in the given array, 0 if any.
+	 * 
+	 * <br>
+	 * <br>
+	 * For example:
+	 * <ol>
+	 * <li><pre>
+	 *    toBeFound = 'b'
+	 *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+	 *    result => 3
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    toBeFound = 'c'
+	 *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+	 *    result => 0
+	 * </pre>
+	 * </li>
+	 * </ol>
+	 * 
+	 * @param toBeFound the given character
+	 * @param array the given array
+	 * @return the number of occurrences of the given character in the given array, 0 if any
+	 * @exception NullPointerException if array is null
+	 */
+	public static final int occurencesOf(char toBeFound, char[] array) {
+		int count = 0;
+		for (int i = 0; i < array.length; i++)
+			if (toBeFound == array[i])
+				count++;
+		return count;
+	}
+	/**
+	 * Answers the number of occurrences of the given character in the given array starting
+	 * at the given index, 0 if any.
+	 * 
+	 * <br>
+	 * <br>
+	 * For example:
+	 * <ol>
+	 * <li><pre>
+	 *    toBeFound = 'b'
+	 *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+	 *    start = 2
+	 *    result => 2
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    toBeFound = 'c'
+	 *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+	 *    start = 0
+	 *    result => 0
+	 * </pre>
+	 * </li>
+	 * </ol>
+	 * 
+	 * @param toBeFound the given character
+	 * @param array the given array
+	 * @return the number of occurrences of the given character in the given array, 0 if any
+	 * @exception NullPointerException if array is null
+	 * @exception ArrayIndexOutOfBoundsException if start is lower than 0
+	 */
+	public static final int occurencesOf(
+		char toBeFound,
+		char[] array,
+		int start) {
+		int count = 0;
+		for (int i = start; i < array.length; i++)
+			if (toBeFound == array[i])
+				count++;
+		return count;
+	}
+	/**
+	 * Answers true if the given name starts with the given prefix, false otherwise.
+	 * The comparison is case sensitive.
+	 * <br>
+	 * <br>
+	 * For example:
+	 * <ol>
+	 * <li><pre>
+	 *    prefix = { 'a' , 'b' }
+	 *    name = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+	 *    result => true
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    prefix = { 'a' , 'c' }
+	 *    name = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+	 *    result => false
+	 * </pre>
+	 * </li>
+	 * </ol>
+	 * 
+	 * @param prefix the given prefix
+	 * @param name the given name
+	 * @return true if the given name starts with the given prefix, false otherwise
+	 * @exception NullPointerException if the given name is null or if the given prefix is null
+	 */
+	public static final boolean prefixEquals(char[] prefix, char[] name) {
+
+		int max = prefix.length;
+		if (name.length < max)
+			return false;
+		for (int i = max;
+			--i >= 0;
+			) // assumes the prefix is not larger than the name
+			if (prefix[i] != name[i])
+				return false;
+		return true;
+	}
+	/**
+	 * Answers true if the given name starts with the given prefix, false otherwise.
+	 * isCaseSensitive is used to find out whether or not the comparison should be case sensitive.
+	 * <br>
+	 * <br>
+	 * For example:
+	 * <ol>
+	 * <li><pre>
+	 *    prefix = { 'a' , 'B' }
+	 *    name = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+	 *    isCaseSensitive = false
+	 *    result => true
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    prefix = { 'a' , 'B' }
+	 *    name = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+	 *    isCaseSensitive = true
+	 *    result => false
+	 * </pre>
+	 * </li>
+	 * </ol>
+	 * 
+	 * @param prefix the given prefix
+	 * @param name the given name
+	 * @param isCaseSensitive to find out whether or not the comparison should be case sensitive
+	 * @return true if the given name starts with the given prefix, false otherwise
+	 * @exception NullPointerException if the given name is null or if the given prefix is null
+	 */
+	public static final boolean prefixEquals(
+		char[] prefix,
+		char[] name,
+		boolean isCaseSensitive) {
+
+		int max = prefix.length;
+		if (name.length < max)
+			return false;
+		if (isCaseSensitive) {
+			for (int i = max;
+				--i >= 0;
+				) // assumes the prefix is not larger than the name
+				if (prefix[i] != name[i])
+					return false;
+			return true;
+		}
+
+		for (int i = max;
+			--i >= 0;
+			) // assumes the prefix is not larger than the name
+			if (Character.toLowerCase(prefix[i])
+				!= Character.toLowerCase(name[i]))
+				return false;
+		return true;
+	}
+	/**
+	 * Replace all occurrence of the character to be replaced with the remplacement character in the
+	 * given array.
+	 * <br>
+	 * <br>
+	 * For example:
+	 * <ol>
+	 * <li><pre>
+	 *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+	 *    toBeReplaced = 'b'
+	 *    replacementChar = 'a'
+	 *    result => No returned value, but array is now equals to { 'a' , 'a', 'a', 'a', 'a', 'a' }
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+	 *    toBeReplaced = 'c'
+	 *    replacementChar = 'a'
+	 *    result => No returned value, but array is now equals to { 'a' , 'b', 'b', 'a', 'b', 'a' }
+	 * </pre>
+	 * </li>
+	 * </ol>
+	 * 
+	 * @param array the given array
+	 * @param toBeReplaced the character to be replaced
+	 * @param replacementChar the replacement character
+	 * @exception NullPointerException if the given array is null
+	 */
+	public static final void replace(
+		char[] array,
+		char toBeReplaced,
+		char replacementChar) {
+		if (toBeReplaced != replacementChar) {
+			for (int i = 0, max = array.length; i < max; i++) {
+				if (array[i] == toBeReplaced)
+					array[i] = replacementChar;
+			}
+		}
+	}
+	/**
+	 * Answers a new array of characters with substitutions. No side-effect is operated on the original
+	 * array, in case no substitution happened, then the result is the same as the
+	 * original one.
+	 * <br>
+	 * <br>
+	 * For example:
+	 * <ol>
+	 * <li><pre>
+	 *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+	 *    toBeReplaced = { 'b' }
+	 *    replacementChar = { 'a', 'a' }
+	 *    result => { 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a' }
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+	 *    toBeReplaced = { 'c' }
+	 *    replacementChar = { 'a' }
+	 *    result => { 'a' , 'b', 'b', 'a', 'b', 'a' }
+	 * </pre>
+	 * </li>
+	 * </ol>
+	 * 
+	 * @param the given array
+	 * @param toBeReplaced characters to be replaced
+	 * @param the replacement characters
+	 * @return a new array of characters with substitutions or the given array if none
+	 * @exception NullPointerException if the given array is null
+	 */
+	public static final char[] replace(
+		char[] array,
+		char[] toBeReplaced,
+		char[] replacementChars) {
+
+		int max = array.length;
+		int replacedLength = toBeReplaced.length;
+		int replacementLength = replacementChars.length;
+
+		int[] starts = new int[5];
+		int occurrenceCount = 0;
+
+		if (!equals(toBeReplaced, replacementChars)) {
+
+			next : for (int i = 0; i < max; i++) {
+				int j = 0;
+				while (j < replacedLength) {
+					if (i + j == max)
+						continue next;
+					if (array[i + j] != toBeReplaced[j++])
+						continue next;
+				}
+				if (occurrenceCount == starts.length) {
+					System.arraycopy(
+						starts,
+						0,
+						starts = new int[occurrenceCount * 2],
+						0,
+						occurrenceCount);
+				}
+				starts[occurrenceCount++] = i;
+			}
+		}
+		if (occurrenceCount == 0)
+			return array;
+		char[] result =
+			new char[max
+				+ occurrenceCount * (replacementLength - replacedLength)];
+		int inStart = 0, outStart = 0;
+		for (int i = 0; i < occurrenceCount; i++) {
+			int offset = starts[i] - inStart;
+			System.arraycopy(array, inStart, result, outStart, offset);
+			inStart += offset;
+			outStart += offset;
+			System.arraycopy(
+				replacementChars,
+				0,
+				result,
+				outStart,
+				replacementLength);
+			inStart += replacedLength;
+			outStart += replacementLength;
+		}
+		System.arraycopy(array, inStart, result, outStart, max - inStart);
+		return result;
+	}
+	/**
+	 * Return a new array which is the split of the given array using the given divider and triming each subarray to remove
+	 * whitespaces equals to ' '.
+	 * <br>
+	 * <br>
+	 * For example:
+	 * <ol>
+	 * <li><pre>
+	 *    divider = 'b'
+	 *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+	 *    result => { { 'a' }, {  }, { 'a' }, { 'a' } }
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    divider = 'c'
+	 *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+	 *    result => { { 'a', 'b', 'b', 'a', 'b', 'a' } }
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    divider = 'b'
+	 *    array = { 'a' , ' ', 'b', 'b', 'a', 'b', 'a' }
+	 *    result => { { 'a' }, {  }, { 'a' }, { 'a' } }
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    divider = 'c'
+	 *    array = { ' ', ' ', 'a' , 'b', 'b', 'a', 'b', 'a', ' ' }
+	 *    result => { { 'a', 'b', 'b', 'a', 'b', 'a' } }
+	 * </pre>
+	 * </li>
+	 * </ol>
+	 * 
+	 * @param divider the given divider
+	 * @param array the given array
+	 * @return a new array which is the split of the given array using the given divider and triming each subarray to remove
+	 * whitespaces equals to ' '
+	 */
+	public static final char[][] splitAndTrimOn(char divider, char[] array) {
+		int length = array == null ? 0 : array.length;
+		if (length == 0)
+			return NO_CHAR_CHAR;
+
+		int wordCount = 1;
+		for (int i = 0; i < length; i++)
+			if (array[i] == divider)
+				wordCount++;
+		char[][] split = new char[wordCount][];
+		int last = 0, currentWord = 0;
+		for (int i = 0; i < length; i++) {
+			if (array[i] == divider) {
+				int start = last, end = i - 1;
+				while (start < i && array[start] == ' ')
+					start++;
+				while (end > start && array[end] == ' ')
+					end--;
+				split[currentWord] = new char[end - start + 1];
+				System.arraycopy(
+					array,
+					start,
+					split[currentWord++],
+					0,
+					end - start + 1);
+				last = i + 1;
+			}
+		}
+		int start = last, end = length - 1;
+		while (start < length && array[start] == ' ')
+			start++;
+		while (end > start && array[end] == ' ')
+			end--;
+		split[currentWord] = new char[end - start + 1];
+		System.arraycopy(
+			array,
+			start,
+			split[currentWord++],
+			0,
+			end - start + 1);
+		return split;
+	}
+	/**
+	 * Return a new array which is the split of the given array using the given divider.
+	 * <br>
+	 * <br>
+	 * For example:
+	 * <ol>
+	 * <li><pre>
+	 *    divider = 'b'
+	 *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+	 *    result => { { 'a' }, {  }, { 'a' }, { 'a' } }
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    divider = 'c'
+	 *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+	 *    result => { { 'a', 'b', 'b', 'a', 'b', 'a' } }
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    divider = 'c'
+	 *    array = { ' ', ' ', 'a' , 'b', 'b', 'a', 'b', 'a', ' ' }
+	 *    result => { { ' ', 'a', 'b', 'b', 'a', 'b', 'a', ' ' } }
+	 * </pre>
+	 * </li>
+	 * </ol>
+	 * 
+	 * @param divider the given divider
+	 * @param array the given array
+	 * @return a new array which is the split of the given array using the given divider
+	 */
+	public static final char[][] splitOn(char divider, char[] array) {
+		int length = array == null ? 0 : array.length;
+		if (length == 0)
+			return NO_CHAR_CHAR;
+
+		int wordCount = 1;
+		for (int i = 0; i < length; i++)
+			if (array[i] == divider)
+				wordCount++;
+		char[][] split = new char[wordCount][];
+		int last = 0, currentWord = 0;
+		for (int i = 0; i < length; i++) {
+			if (array[i] == divider) {
+				split[currentWord] = new char[i - last];
+				System.arraycopy(
+					array,
+					last,
+					split[currentWord++],
+					0,
+					i - last);
+				last = i + 1;
+			}
+		}
+		split[currentWord] = new char[length - last];
+		System.arraycopy(array, last, split[currentWord], 0, length - last);
+		return split;
+	}
+	/**
+	 * Return a new array which is the split of the given array using the given divider. The given end 
+	 * is exclusive and the given start is inclusive.
+	 * <br>
+	 * <br>
+	 * For example:
+	 * <ol>
+	 * <li><pre>
+	 *    divider = 'b'
+	 *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+	 *    start = 2
+	 *    end = 5
+	 *    result => { {  }, {  }, { 'a' } }
+	 * </pre>
+	 * </li>
+	 * </ol>
+	 * 
+	 * @param divider the given divider
+	 * @param array the given array
+	 * @param start the given starting index
+	 * @param end the given ending index
+	 * @return a new array which is the split of the given array using the given divider
+	 * @exception ArrayIndexOutOfBoundsException if start is lower than 0 or end is greater than the array length
+	 */
+	public static final char[][] splitOn(
+		char divider,
+		char[] array,
+		int start,
+		int end) {
+		int length = array == null ? 0 : array.length;
+		if (length == 0 || start > end)
+			return NO_CHAR_CHAR;
+
+		int wordCount = 1;
+		for (int i = start; i < end; i++)
+			if (array[i] == divider)
+				wordCount++;
+		char[][] split = new char[wordCount][];
+		int last = start, currentWord = 0;
+		for (int i = start; i < end; i++) {
+			if (array[i] == divider) {
+				split[currentWord] = new char[i - last];
+				System.arraycopy(
+					array,
+					last,
+					split[currentWord++],
+					0,
+					i - last);
+				last = i + 1;
+			}
+		}
+		split[currentWord] = new char[end - last];
+		System.arraycopy(array, last, split[currentWord], 0, end - last);
+		return split;
+	}
+	/**
+	 * Answers a new array which is a copy of the given array starting at the given start and 
+	 * ending at the given end. The given start is inclusive and the given end is exclusive.
+	 * Answers null if start is greater than end, if start is lower than 0 or if end is greater 
+	 * than the length of the given array. If end  equals -1, it is converted to the array length.
+	 * <br>
+	 * <br>
+	 * For example:
+	 * <ol>
+	 * <li><pre>
+	 *    array = { { 'a' } , { 'b' } }
+	 *    start = 0
+	 *    end = 1
+	 *    result => { { 'a' } }
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    array = { { 'a' } , { 'b' } }
+	 *    start = 0
+	 *    end = -1
+	 *    result => { { 'a' }, { 'b' } }
+	 * </pre>
+	 * </li>
+	 * </ol>
+	 *  
+	 * @param array the given array
+	 * @param start the given starting index
+	 * @param end the given ending index
+	 * @return a new array which is a copy of the given array starting at the given start and 
+	 * ending at the given end
+	 * @exception NullPointerException if the given array is null
+	 */
+	public static final char[][] subarray(char[][] array, int start, int end) {
+		if (end == -1)
+			end = array.length;
+		if (start > end)
+			return null;
+		if (start < 0)
+			return null;
+		if (end > array.length)
+			return null;
+
+		char[][] result = new char[end - start][];
+		System.arraycopy(array, start, result, 0, end - start);
+		return result;
+	}
+	/**
+	 * Answers a new array which is a copy of the given array starting at the given start and 
+	 * ending at the given end. The given start is inclusive and the given end is exclusive.
+	 * Answers null if start is greater than end, if start is lower than 0 or if end is greater 
+	 * than the length of the given array. If end  equals -1, it is converted to the array length.
+	 * <br>
+	 * <br>
+	 * For example:
+	 * <ol>
+	 * <li><pre>
+	 *    array = { 'a' , 'b' }
+	 *    start = 0
+	 *    end = 1
+	 *    result => { 'a' }
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    array = { 'a', 'b' }
+	 *    start = 0
+	 *    end = -1
+	 *    result => { 'a' , 'b' }
+	 * </pre>
+	 * </li>
+	 * </ol>
+	 *  
+	 * @param array the given array
+	 * @param start the given starting index
+	 * @param end the given ending index
+	 * @return a new array which is a copy of the given array starting at the given start and 
+	 * ending at the given end
+	 * @exception NullPointerException if the given array is null
+	 */
+	public static final char[] subarray(char[] array, int start, int end) {
+		if (end == -1)
+			end = array.length;
+		if (start > end)
+			return null;
+		if (start < 0)
+			return null;
+		if (end > array.length)
+			return null;
+
+		char[] result = new char[end - start];
+		System.arraycopy(array, start, result, 0, end - start);
+		return result;
+	}
+	/**
+	 * Answers the result of a char[] conversion to lowercase. Answers null if the given chars array is null.
+	 * <br>
+	 * NOTE: If no conversion was necessary, then answers back the argument one.
+	 * <br>
+	 * <br>
+	 * For example:
+	 * <ol>
+	 * <li><pre>
+	 *    chars = { 'a' , 'b' }
+	 *    result => { 'a' , 'b' }
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    array = { 'A', 'b' }
+	 *    result => { 'a' , 'b' }
+	 * </pre>
+	 * </li>
+	 * </ol>
+	 * 
+	 * @param chars the chars to convert
+	 * @return the result of a char[] conversion to lowercase
+	 */
+	final static public char[] toLowerCase(char[] chars) {
+		if (chars == null)
+			return null;
+		int length = chars.length;
+		char[] lowerChars = null;
+		for (int i = 0; i < length; i++) {
+			char c = chars[i];
+			char lc = Character.toLowerCase(c);
+			if ((c != lc) || (lowerChars != null)) {
+				if (lowerChars == null) {
+					System.arraycopy(
+						chars,
+						0,
+						lowerChars = new char[length],
+						0,
+						i);
+				}
+				lowerChars[i] = lc;
+			}
+		}
+		return lowerChars == null ? chars : lowerChars;
+	}
+	/**
+	 * Answers a new array removing leading and trailing spaces (' '). Answers the given array if there is no
+	 * space characters to remove.
+	 * <br>
+	 * <br>
+	 * For example:
+	 * <ol>
+	 * <li><pre>
+	 *    chars = { ' ', 'a' , 'b', ' ',  ' ' }
+	 *    result => { 'a' , 'b' }
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    array = { 'A', 'b' }
+	 *    result => { 'A' , 'b' }
+	 * </pre>
+	 * </li>
+	 * </ol>
+	 * 
+	 * @param chars the given array
+	 * @return a new array removing leading and trailing spaces (' ')
+	 */
+	final static public char[] trim(char[] chars) {
+
+		if (chars == null)
+			return null;
+
+		int start = 0, length = chars.length, end = length - 1;
+		while (start < length && chars[start] == ' ') {
+			start++;
+		}
+		while (end > start && chars[end] == ' ') {
+			end--;
+		}
+		if (start != 0 || end != length - 1) {
+			return subarray(chars, start, end + 1);
+		}
+		return chars;
+	}
+	/**
+	 * Answers a string which is the concatenation of the given array using the '.' as a separator.
+	 * <br>
+	 * <br>
+	 * For example:
+	 * <ol>
+	 * <li><pre>
+	 *    array = { { 'a' } , { 'b' } }
+	 *    result => "a.b"
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    array = { { ' ',  'a' } , { 'b' } }
+	 *    result => " a.b"
+	 * </pre>
+	 * </li>
+	 * </ol>
+	 * 
+	 * @param chars the given array
+	 * @return a string which is the concatenation of the given array using the '.' as a separator
+	 */
+	final static public String toString(char[][] array) {
+		char[] result = concatWith(array, '.');
+		return new String(result);
+	}
+}
\ No newline at end of file
Index: index/org/eclipse/cdt/internal/core/Util.java
===================================================================
RCS file: index/org/eclipse/cdt/internal/core/Util.java
diff -N index/org/eclipse/cdt/internal/core/Util.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ index/org/eclipse/cdt/internal/core/Util.java	12 Aug 2003 19:00:18 -0000
@@ -0,0 +1,368 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.internal.core;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+import org.eclipse.cdt.internal.core.*;
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IPath;
+
+public class Util {
+	
+	private final static char[] DOUBLE_QUOTES = "''".toCharArray(); //$NON-NLS-1$
+	private final static char[] SINGLE_QUOTE = "'".toCharArray(); //$NON-NLS-1$
+	private static final int DEFAULT_READING_SIZE = 8192;
+
+	/* Bundle containing messages */
+	protected static ResourceBundle bundle;
+	private final static String bundleName = "org.eclipse.cdt.internal.core.messages"; //$NON-NLS-1$
+	static {
+		relocalize();
+	}
+	/**
+	 * Lookup the message with the given ID in this catalog and bind its
+	 * substitution locations with the given strings.
+	 */
+	public static String bind(String id, String binding1, String binding2) {
+		return bind(id, new String[] {binding1, binding2});
+	}
+	/**
+	 * Lookup the message with the given ID in this catalog and bind its
+	 * substitution locations with the given string.
+	 */
+	public static String bind(String id, String binding) {
+		return bind(id, new String[] {binding});
+	}
+	/**
+	 * Lookup the message with the given ID in this catalog and bind its
+	 * substitution locations with the given string values.
+	 */
+	public static String bind(String id, String[] bindings) {
+		if (id == null)
+			return "No message available"; //$NON-NLS-1$
+		String message = null;
+		try {
+			message = bundle.getString(id);
+		} catch (MissingResourceException e) {
+			// If we got an exception looking for the message, fail gracefully by just returning
+			// the id we were looking for.  In most cases this is semi-informative so is not too bad.
+			return "Missing message: " + id + " in: " + bundleName; //$NON-NLS-2$ //$NON-NLS-1$
+		}
+		// for compatibility with MessageFormat which eliminates double quotes in original message
+		char[] messageWithNoDoubleQuotes =
+		CharOperation.replace(message.toCharArray(), DOUBLE_QUOTES, SINGLE_QUOTE);
+		message = new String(messageWithNoDoubleQuotes);
+	
+		if (bindings == null)
+			return message;
+		int length = message.length();
+		int start = -1;
+		int end = length;
+		StringBuffer output = new StringBuffer(80);
+		while (true) {
+			if ((end = message.indexOf('{', start)) > -1) {
+				output.append(message.substring(start + 1, end));
+				if ((start = message.indexOf('}', end)) > -1) {
+					int index = -1;
+					try {
+						index = Integer.parseInt(message.substring(end + 1, start));
+						output.append(bindings[index]);
+					} catch (NumberFormatException nfe) {
+						output.append(message.substring(end + 1, start + 1));
+					} catch (ArrayIndexOutOfBoundsException e) {
+						output.append("{missing " + Integer.toString(index) + "}"); //$NON-NLS-2$ //$NON-NLS-1$
+					}
+				} else {
+					output.append(message.substring(end, length));
+					break;
+				}
+			} else {
+				output.append(message.substring(start + 1, length));
+				break;
+			}
+		}
+		return output.toString();
+	}
+	/**
+	 * Lookup the message with the given ID in this catalog 
+	 */
+	public static String bind(String id) {
+		return bind(id, (String[])null);
+	}
+	/**
+	 * Creates a NLS catalog for the given locale.
+	 */
+	public static void relocalize() {
+		try  {		
+			bundle = ResourceBundle.getBundle(bundleName, Locale.getDefault());
+		} catch(MissingResourceException e) {
+			System.out.println("Missing resource : " + bundleName.replace('.', '/') + ".properties for locale " + Locale.getDefault()); //$NON-NLS-1$//$NON-NLS-2$
+			throw e;
+		}
+	}
+	
+	/**
+	 * Returns the contents of the given file as a byte array.
+	 * @throws IOException if a problem occured reading the file.
+	 */
+	public static byte[] getFileByteContent(File file) throws IOException {
+		InputStream stream = null;
+		try {
+			stream = new BufferedInputStream(new FileInputStream(file));
+			return getInputStreamAsByteArray(stream, (int) file.length());
+		} finally {
+			if (stream != null) {
+				try {
+					stream.close();
+				} catch (IOException e) {
+				}
+			}
+		}
+	}
+	/**
+	 * Returns the contents of the given file as a char array.
+	 * When encoding is null, then the platform default one is used
+	 * @throws IOException if a problem occured reading the file.
+	 */
+	public static char[] getFileCharContent(File file, String encoding) throws IOException {
+		InputStream stream = null;
+		try {
+			stream = new BufferedInputStream(new FileInputStream(file));
+			return Util.getInputStreamAsCharArray(stream, (int) file.length(), encoding);
+		} finally {
+			if (stream != null) {
+				try {
+					stream.close();
+				} catch (IOException e) {
+				}
+			}
+		}
+	}
+	
+	/**
+	 * Returns the given input stream's contents as a byte array.
+	 * If a length is specified (ie. if length != -1), only length bytes
+	 * are returned. Otherwise all bytes in the stream are returned.
+	 * Note this doesn't close the stream.
+	 * @throws IOException if a problem occured reading the stream.
+	 */
+	public static byte[] getInputStreamAsByteArray(InputStream stream, int length)
+		throws IOException {
+		byte[] contents;
+		if (length == -1) {
+			contents = new byte[0];
+			int contentsLength = 0;
+			int amountRead = -1;
+			do {
+				int amountRequested = Math.max(stream.available(), DEFAULT_READING_SIZE);  // read at least 8K
+				
+				// resize contents if needed
+				if (contentsLength + amountRequested > contents.length) {
+					System.arraycopy(
+						contents,
+						0,
+						contents = new byte[contentsLength + amountRequested],
+						0,
+						contentsLength);
+				}
+
+				// read as many bytes as possible
+				amountRead = stream.read(contents, contentsLength, amountRequested);
+
+				if (amountRead > 0) {
+					// remember length of contents
+					contentsLength += amountRead;
+				}
+			} while (amountRead != -1); 
+
+			// resize contents if necessary
+			if (contentsLength < contents.length) {
+				System.arraycopy(
+					contents,
+					0,
+					contents = new byte[contentsLength],
+					0,
+					contentsLength);
+			}
+		} else {
+			contents = new byte[length];
+			int len = 0;
+			int readSize = 0;
+			while ((readSize != -1) && (len != length)) {
+				// See PR 1FMS89U
+				// We record first the read size. In this case len is the actual read size.
+				len += readSize;
+				readSize = stream.read(contents, len, length - len);
+			}
+		}
+
+		return contents;
+	}
+
+	/**
+	 * Returns the given input stream's contents as a character array.
+	 * If a length is specified (ie. if length != -1), only length chars
+	 * are returned. Otherwise all chars in the stream are returned.
+	 * Note this doesn't close the stream.
+	 * @throws IOException if a problem occured reading the stream.
+	 */
+	public static char[] getInputStreamAsCharArray(InputStream stream, int length, String encoding)
+		throws IOException {
+		InputStreamReader reader = null;
+		reader = encoding == null
+					? new InputStreamReader(stream)
+					: new InputStreamReader(stream, encoding);
+		char[] contents;
+		if (length == -1) {
+			contents = CharOperation.NO_CHAR;
+			int contentsLength = 0;
+			int amountRead = -1;
+			do {
+				int amountRequested = Math.max(stream.available(), DEFAULT_READING_SIZE);  // read at least 8K
+
+				// resize contents if needed
+				if (contentsLength + amountRequested > contents.length) {
+					System.arraycopy(
+						contents,
+						0,
+						contents = new char[contentsLength + amountRequested],
+						0,
+						contentsLength);
+				}
+
+				// read as many chars as possible
+				amountRead = reader.read(contents, contentsLength, amountRequested);
+
+				if (amountRead > 0) {
+					// remember length of contents
+					contentsLength += amountRead;
+				}
+			} while (amountRead != -1);
+
+			// resize contents if necessary
+			if (contentsLength < contents.length) {
+				System.arraycopy(
+					contents,
+					0,
+					contents = new char[contentsLength],
+					0,
+					contentsLength);
+			}
+		} else {
+			contents = new char[length];
+			int len = 0;
+			int readSize = 0;
+			while ((readSize != -1) && (len != length)) {
+				// See PR 1FMS89U
+				// We record first the read size. In this case len is the actual read size.
+				len += readSize;
+				readSize = reader.read(contents, len, length - len);
+			}
+			// See PR 1FMS89U
+			// Now we need to resize in case the default encoding used more than one byte for each
+			// character
+			if (len != length)
+				System.arraycopy(contents, 0, (contents = new char[len]), 0, len);
+		}
+
+		return contents;
+	}
+	
+
+	/**
+	 * Helper method - returns the targeted item (IResource if internal or java.io.File if external), 
+	 * or null if unbound
+	 * Internal items must be referred to using container relative paths.
+	 */
+	public static Object getTarget(IContainer container, IPath path, boolean checkResourceExistence) {
+
+		if (path == null) return null;
+	
+		// lookup - inside the container
+		if (path.getDevice() == null) { // container relative paths should not contain a device 
+													// (see http://dev.eclipse.org/bugs/show_bug.cgi?id=18684)
+													// (case of a workspace rooted at d:\ )
+			IResource resource = container.findMember(path);
+			if (resource != null){
+				if (!checkResourceExistence ||resource.exists()) return resource;
+				return null;
+			}
+		}
+	
+		// if path is relative, it cannot be an external path
+		// (see http://dev.eclipse.org/bugs/show_bug.cgi?id=22517)
+		if (!path.isAbsolute()) return null; 
+
+		// lookup - outside the container
+		File externalFile = new File(path.toOSString());
+		if (!checkResourceExistence) {
+			return externalFile;
+		} else if (existingExternalFiles.contains(externalFile)) {
+			return externalFile;
+		} else {
+			if (externalFile.exists()) {
+				// cache external file
+				existingExternalFiles.add(externalFile);
+				return externalFile;
+			}
+		}
+		
+		return null;	
+	}
+		/**
+		 * A set of java.io.Files used as a cache of external jars that 
+		 * are known to be existing.
+		 * Note this cache is kept for the whole session.
+		 */ 
+		public static HashSet existingExternalFiles = new HashSet();
+		
+	/*
+	 * Returns whether the given resource matches one of the exclusion patterns.
+	 * 
+	 * @see IClasspathEntry#getExclusionPatterns
+	 */
+	public final static boolean isExcluded(IResource resource, char[][] exclusionPatterns) {
+		IPath path = resource.getFullPath();
+		// ensure that folders are only excluded if all of their children are excluded
+		if (resource.getType() == IResource.FOLDER)
+			path = path.append("*"); //$NON-NLS-1$
+		return isExcluded(path, exclusionPatterns);
+	}
+	
+	/*
+	 * Returns whether the given resource path matches one of the exclusion
+	 * patterns.
+	 * 
+	 * @see IClasspathEntry#getExclusionPatterns
+	 */
+	public final static boolean isExcluded(IPath resourcePath, char[][] exclusionPatterns) {
+		if (exclusionPatterns == null) return false;
+		char[] path = resourcePath.toString().toCharArray();
+		for (int i = 0, length = exclusionPatterns.length; i < length; i++)
+			if (CharOperation.pathMatch(exclusionPatterns[i], path, true, '/'))
+				return true;
+		return false;
+	}	
+		
+}
+
+
Index: index/org/eclipse/cdt/internal/core/messages.properties
===================================================================
RCS file: index/org/eclipse/cdt/internal/core/messages.properties
diff -N index/org/eclipse/cdt/internal/core/messages.properties
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ index/org/eclipse/cdt/internal/core/messages.properties	12 Aug 2003 19:00:19 -0000
@@ -0,0 +1,29 @@
+###############################################################################
+# Copyright (c) 2000, 2003 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials 
+# are made available under the terms of the Common Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/cpl-v10.html
+# 
+# Contributors:
+#     IBM Corporation - initial API and implementation
+###############################################################################
+### Eclipse CDT Core Search messages.
+
+engine.searching = Searching...
+exception.wrongFormat = Wrong format
+process.name = CDT Indexer
+manager.filesToIndex = {0} files to index
+
+convention.illegalIdentifier= Illegal Identifier
+convention.scope.lowercaseName= Scope starts with lower case
+convention.scope.nullName= Scope name is null
+convention.scope.emptyName= Scope name is empty
+convention.scope.dotName= Scope name starts or ends with a .
+convention.scope.nameWithBlanks= Scop name has blanks
+
+convention.class.nullName= Class name is null
+convention.class.nameWithBlanks= Class name has blanks
+convention.class.dollarName= Class name has $
+convention.class.lowercaseName= Class name starts with lower case
+convention.class.invalidName= Class name is invalid
Index: index/org/eclipse/cdt/internal/core/index/impl/BlocksIndexInput.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/index/impl/BlocksIndexInput.java,v
retrieving revision 1.2
diff -u -r1.2 BlocksIndexInput.java
--- index/org/eclipse/cdt/internal/core/index/impl/BlocksIndexInput.java	4 Jul 2003 03:02:07 -0000	1.2
+++ index/org/eclipse/cdt/internal/core/index/impl/BlocksIndexInput.java	12 Aug 2003 19:00:19 -0000
@@ -15,11 +15,11 @@
 import java.io.RandomAccessFile;
 import java.util.ArrayList;
 
-import org.eclipse.cdt.internal.core.search.CharOperation;
+import org.eclipse.cdt.internal.core.CharOperation;
+import org.eclipse.cdt.internal.core.Util;
 import org.eclipse.cdt.internal.core.index.IDocument;
 import org.eclipse.cdt.internal.core.index.IEntryResult;
 import org.eclipse.cdt.internal.core.index.IQueryResult;
-import org.eclipse.cdt.internal.core.search.Util;
 import org.eclipse.cdt.internal.core.util.LRUCache;
 
 /**
Index: index/org/eclipse/cdt/internal/core/index/impl/EntryResult.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/index/impl/EntryResult.java,v
retrieving revision 1.2
diff -u -r1.2 EntryResult.java
--- index/org/eclipse/cdt/internal/core/index/impl/EntryResult.java	4 Jul 2003 03:02:07 -0000	1.2
+++ index/org/eclipse/cdt/internal/core/index/impl/EntryResult.java	12 Aug 2003 19:00:19 -0000
@@ -10,8 +10,8 @@
  *******************************************************************************/
 package org.eclipse.cdt.internal.core.index.impl;
 
+import org.eclipse.cdt.internal.core.CharOperation;
 import org.eclipse.cdt.internal.core.index.IEntryResult;
-import org.eclipse.cdt.internal.core.search.CharOperation;
 
 
 public class EntryResult implements IEntryResult {
Index: index/org/eclipse/cdt/internal/core/index/impl/IFileDocument.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/index/impl/IFileDocument.java,v
retrieving revision 1.2
diff -u -r1.2 IFileDocument.java
--- index/org/eclipse/cdt/internal/core/index/impl/IFileDocument.java	4 Jul 2003 03:02:07 -0000	1.2
+++ index/org/eclipse/cdt/internal/core/index/impl/IFileDocument.java	12 Aug 2003 19:00:19 -0000
@@ -14,7 +14,7 @@
 
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.runtime.IPath;
-import org.eclipse.cdt.internal.core.search.CharOperation;
+import org.eclipse.cdt.internal.core.CharOperation;
 
 
 /**
@@ -54,7 +54,7 @@
 		if (byteContents != null) return byteContents;
 		IPath location = file.getLocation();
 		if (location == null) return new byte[0];
-		return byteContents = org.eclipse.cdt.internal.core.search.Util.getFileByteContent(location.toFile());
+		return byteContents = org.eclipse.cdt.internal.core.Util.getFileByteContent(location.toFile());
 	}
 	/**
 	 * @see org.eclipse.jdt.internal.core.index.IDocument#getCharContent()
@@ -63,7 +63,7 @@
 		if (charContents != null) return charContents;
 		IPath location = file.getLocation();
 		if (location == null) return CharOperation.NO_CHAR;
-		return charContents = org.eclipse.cdt.internal.core.search.Util.getFileCharContent(
+		return charContents = org.eclipse.cdt.internal.core.Util.getFileCharContent(
 					location.toFile(), 
 					getEncoding());
 	}
Index: index/org/eclipse/cdt/internal/core/index/impl/IndexBlock.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/index/impl/IndexBlock.java,v
retrieving revision 1.2
diff -u -r1.2 IndexBlock.java
--- index/org/eclipse/cdt/internal/core/index/impl/IndexBlock.java	4 Jul 2003 03:02:07 -0000	1.2
+++ index/org/eclipse/cdt/internal/core/index/impl/IndexBlock.java	12 Aug 2003 19:00:19 -0000
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.cdt.internal.core.index.impl;
 
-import org.eclipse.cdt.internal.core.search.CharOperation;
+import org.eclipse.cdt.internal.core.CharOperation;
 
 /**
  * An indexBlock stores wordEntries.
Index: index/org/eclipse/cdt/internal/core/index/impl/IndexSummary.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/index/impl/IndexSummary.java,v
retrieving revision 1.2
diff -u -r1.2 IndexSummary.java
--- index/org/eclipse/cdt/internal/core/index/impl/IndexSummary.java	4 Jul 2003 03:02:07 -0000	1.2
+++ index/org/eclipse/cdt/internal/core/index/impl/IndexSummary.java	12 Aug 2003 19:00:19 -0000
@@ -14,7 +14,7 @@
 import java.io.RandomAccessFile;
 import java.util.ArrayList;
 
-import org.eclipse.cdt.internal.core.search.CharOperation;
+import org.eclipse.cdt.internal.core.CharOperation;
 
 /**
  * An indexSummary is used when saving an index into a BlocksIndexOuput or 
Index: index/org/eclipse/cdt/internal/core/index/impl/WordEntry.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/index/impl/WordEntry.java,v
retrieving revision 1.2
diff -u -r1.2 WordEntry.java
--- index/org/eclipse/cdt/internal/core/index/impl/WordEntry.java	4 Jul 2003 03:02:07 -0000	1.2
+++ index/org/eclipse/cdt/internal/core/index/impl/WordEntry.java	12 Aug 2003 19:00:19 -0000
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.cdt.internal.core.index.impl;
 
-import org.eclipse.cdt.internal.core.search.CharOperation;
+import org.eclipse.cdt.internal.core.CharOperation;
 
 public class WordEntry {
 	protected char[] fWord;
Index: index/org/eclipse/cdt/internal/core/index/impl/WordEntryHashedArray.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/index/impl/WordEntryHashedArray.java,v
retrieving revision 1.2
diff -u -r1.2 WordEntryHashedArray.java
--- index/org/eclipse/cdt/internal/core/index/impl/WordEntryHashedArray.java	4 Jul 2003 03:02:07 -0000	1.2
+++ index/org/eclipse/cdt/internal/core/index/impl/WordEntryHashedArray.java	12 Aug 2003 19:00:19 -0000
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.cdt.internal.core.index.impl;
 
-import org.eclipse.cdt.internal.core.search.CharOperation;
+import org.eclipse.cdt.internal.core.CharOperation;
 
 public final class WordEntryHashedArray {
 	
Index: index/org/eclipse/cdt/internal/core/search/CharOperation.java
===================================================================
RCS file: index/org/eclipse/cdt/internal/core/search/CharOperation.java
diff -N index/org/eclipse/cdt/internal/core/search/CharOperation.java
--- index/org/eclipse/cdt/internal/core/search/CharOperation.java	4 Jul 2003 03:02:07 -0000	1.2
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -1,2548 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2000, 2003 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials 
- * are made available under the terms of the Common Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/cpl-v10.html
- * 
- * Contributors:
- *     IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.cdt.internal.core.search;
-
-/**
- * This class is a collection of helper methods to manipulate char arrays.
- * 
- * @since 2.1
- */
-public final class CharOperation {
-
-	/**
-	 * Constant for an empty char array
-	 */
-	public static final char[] NO_CHAR = new char[0];
-	/**
-	 * Constant for an empty char array with two dimensions.
-	 */
-	public static final char[][] NO_CHAR_CHAR = new char[0][];
-	/**
-	 * Answers a new array with appending the suffix character at the end of the array.
-	 * <br>
-	 * <br>
-	 * For example:<br>
-	 * <ol>
-	 * <li><pre>
-	 *    array = { 'a', 'b' }
-	 *    suffix = 'c'
-	 *    => result = { 'a', 'b' , 'c' }
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    array = null
-	 *    suffix = 'c'
-	 *    => result = { 'c' }
-	 * </pre></li>
-	 * </ol>
-	 * 
-	 * @param array the array that is concanated with the suffix character
-	 * @param suffix the suffix character
-	 * @return the new array
-	 */
-	public static final char[] append(char[] array, char suffix) {
-		if (array == null)
-			return new char[] { suffix };
-		int length = array.length;
-		System.arraycopy(array, 0, array = new char[length + 1], 0, length);
-		array[length] = suffix;
-		return array;
-	}
-	/**
-	 * Append the given subarray to the target array starting at the given index in the target array.
-	 * The start of the subarray is inclusive, the end is exclusive.
-	 * Answers a new target array if it needs to grow, otherwise answers the same target array.
-	 * <br>
-	 * For example:<br>
-	 * <ol>
-	 * <li><pre>
-	 *    target = { 'a', 'b', '0' }
-	 *    index = 2
-	 *    array = { 'c', 'd' }
-	 *    start = 0
-	 *    end = 1
-	 *    => result = { 'a', 'b' , 'c' }
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    target = { 'a', 'b' }
-	 *    index = 2
-	 *    array = { 'c', 'd' }
-	 *    start = 0
-	 *    end = 1
-	 *    => result = { 'a', 'b' , 'c', '0', '0' , '0' } (new array)
-	 * </pre></li>
-	 * <li><pre>
-	 *    target = { 'a', 'b', 'c' }
-	 *    index = 1
-	 *    array = { 'c', 'd', 'e', 'f' }
-	 *    start = 1
-	 *    end = 4
-	 *    => result = { 'a', 'd' , 'e', 'f', '0', '0', '0', '0' } (new array)
-	 * </pre></li>
-	 * </ol>
-	 * 
-	 * @param target the given target
-	 * @param index the given index
-	 * @param array the given array
-	 * @param start the given start index
-	 * @param end the given end index
-	 * 
-	 * @return the new array
-	 * @throws NullPointerException if the target array is null
-	 */
-	public static final char[] append(char[] target, int index, char[] array, int start, int end) {
-		int targetLength = target.length;
-		int subLength = end-start;
-		int newTargetLength = subLength+index;
-		if (newTargetLength > targetLength) {
-			System.arraycopy(target, 0, target = new char[newTargetLength*2], 0, index);
-		}
-		System.arraycopy(array, start, target, index, subLength);
-		return target;
-	}
-	/**
-	 * Answers the concatenation of the two arrays. It answers null if the two arrays are null.
-	 * If the first array is null, then the second array is returned.
-	 * If the second array is null, then the first array is returned.
-	 * <br>
-	 * <br>
-	 * For example:
-	 * <ol>
-	 * <li><pre>
-	 *    first = null
-	 *    second = null
-	 *    => result = null
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    first = { { ' a' } }
-	 *    second = null
-	 *    => result = { { ' a' } }
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    first = null
-	 *    second = { { ' a' } }
-	 *    => result = { { ' a' } }
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    first = { { ' b' } }
-	 *    second = { { ' a' } }
-	 *    => result = { { ' b' }, { ' a' } }
-	 * </pre>
-	 * </li>
-	 * </ol>
-	 * 
-	 * @param first the first array to concatenate
-	 * @param second the second array to concatenate
-	 * @return the concatenation of the two arrays, or null if the two arrays are null.
-	 */
-	public static final char[][] arrayConcat(char[][] first, char[][] second) {
-		if (first == null)
-			return second;
-		if (second == null)
-			return first;
-
-		int length1 = first.length;
-		int length2 = second.length;
-		char[][] result = new char[length1 + length2][];
-		System.arraycopy(first, 0, result, 0, length1);
-		System.arraycopy(second, 0, result, length1, length2);
-		return result;
-	}
-	/**
-	 * Answers a new array adding the second array at the end of first array.
-	 * It answers null if the first and second are null.
-	 * If the first array is null, then a new array char[][] is created with second.
-	 * If the second array is null, then the first array is returned.
-	 * <br>
-	 * <br>
-	 * For example:
-	 * <ol>
-	 * <li><pre>
-	 *    first = null
-	 *    second = { 'a' }
-	 *    => result = { { ' a' } }
-	 * </pre>
-	 * <li><pre>
-	 *    first = { { ' a' } }
-	 *    second = null
-	 *    => result = { { ' a' } }
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    first = { { ' a' } }
-	 *    second = { ' b' }
-	 *    => result = { { ' a' } , { ' b' } }
-	 * </pre>
-	 * </li>
-	 * </ol>
-	 * 
-	 * @param first the first array to concatenate
-	 * @param second the array to add at the end of the first array
-	 * @return a new array adding the second array at the end of first array, or null if the two arrays are null.
-	 */
-	public static final char[][] arrayConcat(char[][] first, char[] second) {
-		if (second == null)
-			return first;
-		if (first == null)
-			return new char[][] { second };
-
-		int length = first.length;
-		char[][] result = new char[length + 1][];
-		System.arraycopy(first, 0, result, 0, length);
-		result[length] = second;
-		return result;
-	}
-
-	/**
-	 * Compares the contents of the two arrays array and prefix. Returns
-	 * <ul>
-	 * <li>zero if the array starts with the prefix contents</li>
-	 * <li>the difference between the first two characters that are not equal </li>
-	 * <li>one if array length is lower than the prefix length and that the prefix starts with the 
-	 * array contents.</li>
-	 * </ul>
-	 * <p>
-	 * For example:
-	 * <ol>
-	 * <li><pre>
-	 *    array = null
-	 *    prefix = null
-	 *    => result = NullPointerException
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    array = { 'a', 'b', 'c', 'd', 'e' }
-	 *    prefix = { 'a', 'b', 'c'}
-	 *    => result = 0
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    array = { 'a', 'b', 'c', 'd', 'e' }
-	 *    prefix = { 'a', 'B', 'c'}
-	 *    => result = 32
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    array = { 'd', 'b', 'c', 'd', 'e' }
-	 *    prefix = { 'a', 'b', 'c'}
-	 *    => result = 3
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    array = { 'a', 'b', 'c', 'd', 'e' }
-	 *    prefix = { 'd', 'b', 'c'}
-	 *    => result = -3
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    array = { 'a', 'a', 'c', 'd', 'e' }
-	 *    prefix = { 'a', 'e', 'c'}
-	 *    => result = -4
-	 * </pre>
-	 * </li>
-	 * </ol>
-	 * </p>
-	 * 
-	 * @param array the given array
-	 * @param prefix the given prefix
-	 * @return the result of the comparison
-	 * @exception NullPointerException if either array or prefix is null
-	 */
-	public static final int compareWith(char[] array, char[] prefix) {
-		int arrayLength = array.length;
-		int prefixLength = prefix.length;
-		int min = Math.min(arrayLength, prefixLength);
-		int i = 0;
-		while (min-- != 0) {
-			char c1 = array[i];
-			char c2 = prefix[i++];
-			if (c1 != c2)
-				return c1 - c2;
-		}
-		if (prefixLength == i)
-			return 0;
-		return 1;	
-	}
-	/**
-	 * Answers the concatenation of the two arrays. It answers null if the two arrays are null.
-	 * If the first array is null, then the second array is returned.
-	 * If the second array is null, then the first array is returned.
-	 * <br>
-	 * <br>
-	 * For example:
-	 * <ol>
-	 * <li><pre>
-	 *    first = null
-	 *    second = { 'a' }
-	 *    => result = { ' a' }
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    first = { ' a' }
-	 *    second = null
-	 *    => result = { ' a' }
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    first = { ' a' }
-	 *    second = { ' b' }
-	 *    => result = { ' a' , ' b' }
-	 * </pre>
-	 * </li>
-	 * </ol>
-	 * 
-	 * @param first the first array to concatenate
-	 * @param second the second array to concatenate
-	 * @return the concatenation of the two arrays, or null if the two arrays are null.
-	 */
-	public static final char[] concat(char[] first, char[] second) {
-		if (first == null)
-			return second;
-		if (second == null)
-			return first;
-
-		int length1 = first.length;
-		int length2 = second.length;
-		char[] result = new char[length1 + length2];
-		System.arraycopy(first, 0, result, 0, length1);
-		System.arraycopy(second, 0, result, length1, length2);
-		return result;
-	}
-	/**
-	 * Answers the concatenation of the three arrays. It answers null if the three arrays are null.
-	 * If first is null, it answers the concatenation of second and third.
-	 * If second is null, it answers the concatenation of first and third.
-	 * If third is null, it answers the concatenation of first and second.
-	 * <br>
-	 * <br>
-	 * For example:
-	 * <ol>
-	 * <li><pre>
-	 *    first = null
-	 *    second = { 'a' }
-	 *    third = { 'b' }
-	 *    => result = { ' a', 'b' }
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    first = { 'a' }
-	 *    second = null
-	 *    third = { 'b' }
-	 *    => result = { ' a', 'b' }
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    first = { 'a' }
-	 *    second = { 'b' }
-	 *    third = null
-	 *    => result = { ' a', 'b' }
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    first = null
-	 *    second = null
-	 *    third = null
-	 *    => result = null
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    first = { 'a' }
-	 *    second = { 'b' }
-	 *    third = { 'c' }
-	 *    => result = { 'a', 'b', 'c' }
-	 * </pre>
-	 * </li>
-	 * </ol>
-	 * 
-	 * @param first the first array to concatenate
-	 * @param second the second array to concatenate
-	 * @param third the third array to concatenate
-	 * 
-	 * @return the concatenation of the three arrays, or null if the three arrays are null.
-	 */
-	public static final char[] concat(
-		char[] first,
-		char[] second,
-		char[] third) {
-		if (first == null)
-			return concat(second, third);
-		if (second == null)
-			return concat(first, third);
-		if (third == null)
-			return concat(first, second);
-
-		int length1 = first.length;
-		int length2 = second.length;
-		int length3 = third.length;
-		char[] result = new char[length1 + length2 + length3];
-		System.arraycopy(first, 0, result, 0, length1);
-		System.arraycopy(second, 0, result, length1, length2);
-		System.arraycopy(third, 0, result, length1 + length2, length3);
-		return result;
-	}
-	/**
-	 * Answers the concatenation of the two arrays inserting the separator character between the two arrays.
-	 * It answers null if the two arrays are null.
-	 * If the first array is null, then the second array is returned.
-	 * If the second array is null, then the first array is returned.
-	 * <br>
-	 * <br>
-	 * For example:
-	 * <ol>
-	 * <li><pre>
-	 *    first = null
-	 *    second = { 'a' }
-	 *    separator = '/'
-	 *    => result = { ' a' }
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    first = { ' a' }
-	 *    second = null
-	 *    separator = '/'
-	 *    => result = { ' a' }
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    first = { ' a' }
-	 *    second = { ' b' }
-	 *    separator = '/'
-	 *    => result = { ' a' , '/', 'b' }
-	 * </pre>
-	 * </li>
-	 * </ol>
-	 * 
-	 * @param first the first array to concatenate
-	 * @param second the second array to concatenate
-	 * @param separator the character to insert
-	 * @return the concatenation of the two arrays inserting the separator character 
-	 * between the two arrays , or null if the two arrays are null.
-	 */
-	public static final char[] concat(
-		char[] first,
-		char[] second,
-		char separator) {
-		if (first == null)
-			return second;
-		if (second == null)
-			return first;
-
-		int length1 = first.length;
-		if (length1 == 0)
-			return second;
-		int length2 = second.length;
-		if (length2 == 0)
-			return first;
-
-		char[] result = new char[length1 + length2 + 1];
-		System.arraycopy(first, 0, result, 0, length1);
-		result[length1] = separator;
-		System.arraycopy(second, 0, result, length1 + 1, length2);
-		return result;
-	}
-	/**
-	 * Answers the concatenation of the three arrays inserting the sep1 character between the 
-	 * two arrays and sep2 between the last two.
-	 * It answers null if the three arrays are null.
-	 * If the first array is null, then it answers the concatenation of second and third inserting
-	 * the sep2 character between them.
-	 * If the second array is null, then it answers the concatenation of first and third inserting
-	 * the sep1 character between them.
-	 * If the third array is null, then it answers the concatenation of first and second inserting
-	 * the sep1 character between them.
-	 * <br>
-	 * <br>
-	 * For example:
-	 * <ol>
-	 * <li><pre>
-	 *    first = null
-	 *    sep1 = '/'
-	 *    second = { 'a' }
-	 *    sep2 = ':'
-	 *    third = { 'b' }
-	 *    => result = { ' a' , ':', 'b' }
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    first = { 'a' }
-	 *    sep1 = '/'
-	 *    second = null
-	 *    sep2 = ':'
-	 *    third = { 'b' }
-	 *    => result = { ' a' , '/', 'b' }
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    first = { 'a' }
-	 *    sep1 = '/'
-	 *    second = { 'b' }
-	 *    sep2 = ':'
-	 *    third = null
-	 *    => result = { ' a' , '/', 'b' }
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    first = { 'a' }
-	 *    sep1 = '/'
-	 *    second = { 'b' }
-	 *    sep2 = ':'
-	 *    third = { 'c' }
-	 *    => result = { ' a' , '/', 'b' , ':', 'c' }
-	 * </pre>
-	 * </li>
-	 * </ol>
-	 * 
-	 * @param first the first array to concatenate
-	 * @param sep1 the character to insert
-	 * @param second the second array to concatenate
-	 * @param sep2 the character to insert
-	 * @param third the second array to concatenate
-	 * @return the concatenation of the three arrays inserting the sep1 character between the 
-	 * two arrays and sep2 between the last two.
-	 */
-	public static final char[] concat(
-		char[] first,
-		char sep1,
-		char[] second,
-		char sep2,
-		char[] third) {
-		if (first == null)
-			return concat(second, third, sep2);
-		if (second == null)
-			return concat(first, third, sep1);
-		if (third == null)
-			return concat(first, second, sep1);
-
-		int length1 = first.length;
-		int length2 = second.length;
-		int length3 = third.length;
-		char[] result = new char[length1 + length2 + length3 + 2];
-		System.arraycopy(first, 0, result, 0, length1);
-		result[length1] = sep1;
-		System.arraycopy(second, 0, result, length1 + 1, length2);
-		result[length1 + length2 + 1] = sep2;
-		System.arraycopy(third, 0, result, length1 + length2 + 2, length3);
-		return result;
-	}
-	/**
-	 * Answers a new array with prepending the prefix character and appending the suffix 
-	 * character at the end of the array. If array is null, it answers a new array containing the 
-	 * prefix and the suffix characters.
-	 * <br>
-	 * <br>
-	 * For example:<br>
-	 * <ol>
-	 * <li><pre>
-	 *    prefix = 'a'
-	 *    array = { 'b' }
-	 *    suffix = 'c'
-	 *    => result = { 'a', 'b' , 'c' }
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    prefix = 'a'
-	 *    array = null
-	 *    suffix = 'c'
-	 *    => result = { 'a', 'c' }
-	 * </pre></li>
-	 * </ol>
-	 * 
-	 * @param prefix the prefix character
-	 * @param array the array that is concanated with the prefix and suffix characters
-	 * @param suffix the suffix character
-	 * @return the new array
-	 */
-	public static final char[] concat(char prefix, char[] array, char suffix) {
-		if (array == null)
-			return new char[] { prefix, suffix };
-
-		int length = array.length;
-		char[] result = new char[length + 2];
-		result[0] = prefix;
-		System.arraycopy(array, 0, result, 1, length);
-		result[length + 1] = suffix;
-		return result;
-	}
-	/**
-	 * Answers the concatenation of the given array parts using the given separator between each
-	 * part and appending the given name at the end.
-	 * <br>
-	 * <br>
-	 * For example:<br>
-	 * <ol>
-	 * <li><pre>
-	 *    name = { 'c' }
-	 *    array = { { 'a' }, { 'b' } }
-	 *    separator = '.'
-	 *    => result = { 'a', '.', 'b' , '.', 'c' }
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    name = null
-	 *    array = { { 'a' }, { 'b' } }
-	 *    separator = '.'
-	 *    => result = { 'a', '.', 'b' }
-	 * </pre></li>
-	 * <li><pre>
-	 *    name = { ' c' }
-	 *    array = null
-	 *    separator = '.'
-	 *    => result = { 'c' }
-	 * </pre></li>
-	 * </ol>
-	 * 
-	 * @param name the given name
-	 * @param array the given array
-	 * @param separator the given separator
-	 * @return the concatenation of the given array parts using the given separator between each
-	 * part and appending the given name at the end
-	 */
-	public static final char[] concatWith(
-		char[] name,
-		char[][] array,
-		char separator) {
-		int nameLength = name == null ? 0 : name.length;
-		if (nameLength == 0)
-			return concatWith(array, separator);
-
-		int length = array == null ? 0 : array.length;
-		if (length == 0)
-			return name;
-
-		int size = nameLength;
-		int index = length;
-		while (--index >= 0)
-			if (array[index].length > 0)
-				size += array[index].length + 1;
-		char[] result = new char[size];
-		index = size;
-		for (int i = length - 1; i >= 0; i--) {
-			int subLength = array[i].length;
-			if (subLength > 0) {
-				index -= subLength;
-				System.arraycopy(array[i], 0, result, index, subLength);
-				result[--index] = separator;
-			}
-		}
-		System.arraycopy(name, 0, result, 0, nameLength);
-		return result;
-	}
-	/**
-	 * Answers the concatenation of the given array parts using the given separator between each
-	 * part and appending the given name at the end.
-	 * <br>
-	 * <br>
-	 * For example:<br>
-	 * <ol>
-	 * <li><pre>
-	 *    name = { 'c' }
-	 *    array = { { 'a' }, { 'b' } }
-	 *    separator = '.'
-	 *    => result = { 'a', '.', 'b' , '.', 'c' }
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    name = null
-	 *    array = { { 'a' }, { 'b' } }
-	 *    separator = '.'
-	 *    => result = { 'a', '.', 'b' }
-	 * </pre></li>
-	 * <li><pre>
-	 *    name = { ' c' }
-	 *    array = null
-	 *    separator = '.'
-	 *    => result = { 'c' }
-	 * </pre></li>
-	 * </ol>
-	 * 
-	 * @param array the given array
-	 * @param name the given name
-	 * @param separator the given separator
-	 * @return the concatenation of the given array parts using the given separator between each
-	 * part and appending the given name at the end
-	 */
-	public static final char[] concatWith(
-		char[][] array,
-		char[] name,
-		char separator) {
-		int nameLength = name == null ? 0 : name.length;
-		if (nameLength == 0)
-			return concatWith(array, separator);
-
-		int length = array == null ? 0 : array.length;
-		if (length == 0)
-			return name;
-
-		int size = nameLength;
-		int index = length;
-		while (--index >= 0)
-			if (array[index].length > 0)
-				size += array[index].length + 1;
-		char[] result = new char[size];
-		index = 0;
-		for (int i = 0; i < length; i++) {
-			int subLength = array[i].length;
-			if (subLength > 0) {
-				System.arraycopy(array[i], 0, result, index, subLength);
-				index += subLength;
-				result[index++] = separator;
-			}
-		}
-		System.arraycopy(name, 0, result, index, nameLength);
-		return result;
-	}
-	/**
-	 * Answers the concatenation of the given array parts using the given separator between each part.
-	 * <br>
-	 * <br>
-	 * For example:<br>
-	 * <ol>
-	 * <li><pre>
-	 *    array = { { 'a' }, { 'b' } }
-	 *    separator = '.'
-	 *    => result = { 'a', '.', 'b' }
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    array = null
-	 *    separator = '.'
-	 *    => result = { }
-	 * </pre></li>
-	 * </ol>
-	 * 
-	 * @param array the given array
-	 * @param separator the given separator
-	 * @return the concatenation of the given array parts using the given separator between each part
-	 */
-	public static final char[] concatWith(char[][] array, char separator) {
-		int length = array == null ? 0 : array.length;
-		if (length == 0)
-			return CharOperation.NO_CHAR;
-
-		int size = length - 1;
-		int index = length;
-		while (--index >= 0) {
-			if (array[index].length == 0)
-				size--;
-			else
-				size += array[index].length;
-		}
-		if (size <= 0)
-			return CharOperation.NO_CHAR;
-		char[] result = new char[size];
-		index = length;
-		while (--index >= 0) {
-			length = array[index].length;
-			if (length > 0) {
-				System.arraycopy(
-					array[index],
-					0,
-					result,
-					(size -= length),
-					length);
-				if (--size >= 0)
-					result[size] = separator;
-			}
-		}
-		return result;
-	}
-	/**
-	 * Answers true if the array contains an occurrence of character, false otherwise.
-	 * 
-	 * <br>
-	 * <br>
-	 * For example:
-	 * <ol>
-	 * <li><pre>
-	 *    character = 'c'
-	 *    array = { { ' a' }, { ' b' } }
-	 *    result => false
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    character = 'a'
-	 *    array = { { ' a' }, { ' b' } }
-	 *    result => true
-	 * </pre>
-	 * </li>
-	 * </ol>
-	 * 
-	 * @param character the character to search
-	 * @param array the array in which the search is done
-	 * @return true if the array contains an occurrence of character, false otherwise.
-	 * @exception NullPointerException if array is null.
-	 */
-	public static final boolean contains(char character, char[][] array) {
-		for (int i = array.length; --i >= 0;) {
-			char[] subarray = array[i];
-			for (int j = subarray.length; --j >= 0;)
-				if (subarray[j] == character)
-					return true;
-		}
-		return false;
-	}
-	/**
-	 * Answers true if the array contains an occurrence of character, false otherwise.
-	 * 
-	 * <br>
-	 * <br>
-	 * For example:
-	 * <ol>
-	 * <li><pre>
-	 *    character = 'c'
-	 *    array = { ' b'  }
-	 *    result => false
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    character = 'a'
-	 *    array = { ' a' , ' b' }
-	 *    result => true
-	 * </pre>
-	 * </li>
-	 * </ol>
-	 * 
-	 * @param character the character to search
-	 * @param array the array in which the search is done
-	 * @return true if the array contains an occurrence of character, false otherwise.
-	 * @exception NullPointerException if array is null.
-	 */
-	public static final boolean contains(char character, char[] array) {
-		for (int i = array.length; --i >= 0;)
-			if (array[i] == character)
-				return true;
-		return false;
-	}
-	/**
-	 * Answers a deep copy of the toCopy array.
-	 * 
-	 * @param toCopy the array to copy
-	 * @return a deep copy of the toCopy array.
-	 */
-	public static final char[][] deepCopy(char[][] toCopy) {
-		int toCopyLength = toCopy.length;
-		char[][] result = new char[toCopyLength][];
-		for (int i = 0; i < toCopyLength; i++) {
-			char[] toElement = toCopy[i];
-			int toElementLength = toElement.length;
-			char[] resultElement = new char[toElementLength];
-			System.arraycopy(toElement, 0, resultElement, 0, toElementLength);
-			result[i] = resultElement;
-		}
-		return result;
-	}
-	/**
-	 * Return true if array ends with the sequence of characters contained in toBeFound, 
-	 * otherwise false.
-	 * <br>
-	 * <br>
-	 * For example:
-	 * <ol>
-	 * <li><pre>
-	 *    array = { 'a', 'b', 'c', 'd' }
-	 *    toBeFound = { 'b', 'c' }
-	 *    result => false
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    array = { 'a', 'b', 'c' }
-	 *    toBeFound = { 'b', 'c' }
-	 *    result => true
-	 * </pre>
-	 * </li>
-	 * </ol>
-	 * 
-	 * @param array the array to check
-	 * @param toBeFound the array to find
-	 * @return true if array ends with the sequence of characters contained in toBeFound, 
-	 * otherwise false.
-	 * @exception NullPointerException if array is null or toBeFound is null
-	 */
-	public static final boolean endsWith(char[] array, char[] toBeFound) {
-		int i = toBeFound.length;
-		int j = array.length - i;
-
-		if (j < 0)
-			return false;
-		while (--i >= 0)
-			if (toBeFound[i] != array[i + j])
-				return false;
-		return true;
-	}
-	/**
-	 * Answers true if the two arrays are identical character by character, otherwise false.
-	 * The equality is case sensitive.
-	 * <br>
-	 * <br>
-	 * For example:
-	 * <ol>
-	 * <li><pre>
-	 *    first = null
-	 *    second = null
-	 *    result => true
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    first = { { } }
-	 *    second = null
-	 *    result => false
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    first = { { 'a' } }
-	 *    second = { { 'a' } }
-	 *    result => true
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    first = { { 'A' } }
-	 *    second = { { 'a' } }
-	 *    result => false
-	 * </pre>
-	 * </li>
-	 * </ol>
-	 * @param first the first array
-	 * @param second the second array
-	 * @return true if the two arrays are identical character by character, otherwise false
-	 */
-	public static final boolean equals(char[][] first, char[][] second) {
-		if (first == second)
-			return true;
-		if (first == null || second == null)
-			return false;
-		if (first.length != second.length)
-			return false;
-
-		for (int i = first.length; --i >= 0;)
-			if (!equals(first[i], second[i]))
-				return false;
-		return true;
-	}
-	/**
-	 * If isCaseSensite is true, answers true if the two arrays are identical character
-	 * by character, otherwise false.
-	 * If it is false, answers true if the two arrays are identical character by 
-	 * character without checking the case, otherwise false.
-	 * <br>
-	 * <br>
-	 * For example:
-	 * <ol>
-	 * <li><pre>
-	 *    first = null
-	 *    second = null
-	 *    isCaseSensitive = true
-	 *    result => true
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    first = { { } }
-	 *    second = null
-	 *    isCaseSensitive = true
-	 *    result => false
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    first = { { 'A' } }
-	 *    second = { { 'a' } }
-	 *    isCaseSensitive = true
-	 *    result => false
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    first = { { 'A' } }
-	 *    second = { { 'a' } }
-	 *    isCaseSensitive = false
-	 *    result => true
-	 * </pre>
-	 * </li>
-	 * </ol>
-	 * 
-	 * @param first the first array
-	 * @param second the second array
-	 * @param isCaseSensitive check whether or not the equality should be case sensitive
-	 * @return true if the two arrays are identical character by character according to the value
-	 * of isCaseSensitive, otherwise false
-	 */
-	public static final boolean equals(
-		char[][] first,
-		char[][] second,
-		boolean isCaseSensitive) {
-
-		if (isCaseSensitive) {
-			return equals(first, second);
-		}
-		if (first == second)
-			return true;
-		if (first == null || second == null)
-			return false;
-		if (first.length != second.length)
-			return false;
-
-		for (int i = first.length; --i >= 0;)
-			if (!equals(first[i], second[i], false))
-				return false;
-		return true;
-	}
-	/**
-	 * Answers true if the two arrays are identical character by character, otherwise false.
-	 * The equality is case sensitive.
-	 * <br>
-	 * <br>
-	 * For example:
-	 * <ol>
-	 * <li><pre>
-	 *    first = null
-	 *    second = null
-	 *    result => true
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    first = { }
-	 *    second = null
-	 *    result => false
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    first = { 'a' }
-	 *    second = { 'a' }
-	 *    result => true
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    first = { 'a' }
-	 *    second = { 'A' }
-	 *    result => false
-	 * </pre>
-	 * </li>
-	 * </ol>
-	 * @param first the first array
-	 * @param second the second array
-	 * @return true if the two arrays are identical character by character, otherwise false
-	 */
-	public static final boolean equals(char[] first, char[] second) {
-		if (first == second)
-			return true;
-		if (first == null || second == null)
-			return false;
-		if (first.length != second.length)
-			return false;
-
-		for (int i = first.length; --i >= 0;)
-			if (first[i] != second[i])
-				return false;
-		return true;
-	}
-	/**
-	 * If isCaseSensite is true, answers true if the two arrays are identical character
-	 * by character, otherwise false.
-	 * If it is false, answers true if the two arrays are identical character by 
-	 * character without checking the case, otherwise false.
-	 * <br>
-	 * <br>
-	 * For example:
-	 * <ol>
-	 * <li><pre>
-	 *    first = null
-	 *    second = null
-	 *    isCaseSensitive = true
-	 *    result => true
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    first = { }
-	 *    second = null
-	 *    isCaseSensitive = true
-	 *    result => false
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    first = { 'A' }
-	 *    second = { 'a' }
-	 *    isCaseSensitive = true
-	 *    result => false
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    first = { 'A' }
-	 *    second = { 'a' }
-	 *    isCaseSensitive = false
-	 *    result => true
-	 * </pre>
-	 * </li>
-	 * </ol>
-	 * 
-	 * @param first the first array
-	 * @param second the second array
-	 * @param isCaseSensitive check whether or not the equality should be case sensitive
-	 * @return true if the two arrays are identical character by character according to the value
-	 * of isCaseSensitive, otherwise false
-	 */
-	public static final boolean equals(
-		char[] first,
-		char[] second,
-		boolean isCaseSensitive) {
-
-		if (isCaseSensitive) {
-			return equals(first, second);
-		}
-		if (first == second)
-			return true;
-		if (first == null || second == null)
-			return false;
-		if (first.length != second.length)
-			return false;
-
-		for (int i = first.length; --i >= 0;)
-			if (Character.toLowerCase(first[i])
-				!= Character.toLowerCase(second[i]))
-				return false;
-		return true;
-	}
-	/**
-	 * If isCaseSensite is true, the equality is case sensitive, otherwise it is case insensitive.
-	 * 
-	 * Answers true if the name contains the fragment at the starting index startIndex, otherwise false.
-	 * <br>
-	 * <br>
-	 * For example:
-	 * <ol>
-	 * <li><pre>
-	 *    fragment = { 'b', 'c' , 'd' }
-	 *    name = { 'a', 'b', 'c' , 'd' }
-	 *    startIndex = 1
-	 *    isCaseSensitive = true
-	 *    result => true
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    fragment = { 'b', 'c' , 'd' }
-	 *    name = { 'a', 'b', 'C' , 'd' }
-	 *    startIndex = 1
-	 *    isCaseSensitive = true
-	 *    result => false
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    fragment = { 'b', 'c' , 'd' }
-	 *    name = { 'a', 'b', 'C' , 'd' }
-	 *    startIndex = 0
-	 *    isCaseSensitive = false
-	 *    result => false
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    fragment = { 'b', 'c' , 'd' }
-	 *    name = { 'a', 'b'}
-	 *    startIndex = 0
-	 *    isCaseSensitive = true
-	 *    result => false
-	 * </pre>
-	 * </li>
-	 * </ol>
-	 * 
-	 * @param fragment the fragment to check
-	 * @param second the array to check
-	 * @param startIndex the starting index
-	 * @param isCaseSensitive check whether or not the equality should be case sensitive
-	 * @return true if the name contains the fragment at the starting index startIndex according to the 
-	 * value of isCaseSensitive, otherwise false.
-	 * @exception NullPointerException if fragment or name is null.
-	 */
-	public static final boolean fragmentEquals(
-		char[] fragment,
-		char[] name,
-		int startIndex,
-		boolean isCaseSensitive) {
-
-		int max = fragment.length;
-		if (name.length < max + startIndex)
-			return false;
-		if (isCaseSensitive) {
-			for (int i = max;
-				--i >= 0;
-				) // assumes the prefix is not larger than the name
-				if (fragment[i] != name[i + startIndex])
-					return false;
-			return true;
-		}
-		for (int i = max;
-			--i >= 0;
-			) // assumes the prefix is not larger than the name
-			if (Character.toLowerCase(fragment[i])
-				!= Character.toLowerCase(name[i + startIndex]))
-				return false;
-		return true;
-	}
-	/**
-	 * Answers a hashcode for the array
-	 * 
-	 * @param array the array for which a hashcode is required
-	 * @return the hashcode
-	 * @exception NullPointerException if array is null
-	 */
-	public static final int hashCode(char[] array) {
-		int hash = 0;
-		int offset = 0;
-		int length = array.length;
-		if (length < 16) {
-			for (int i = length; i > 0; i--)
-				hash = (hash * 37) + array[offset++];
-		} else {
-			// only sample some characters
-			int skip = length / 8;
-			for (int i = length; i > 0; i -= skip, offset += skip)
-				hash = (hash * 39) + array[offset];
-		}
-		return hash & 0x7FFFFFFF;
-	}
-	/**
-	 * Answers true if c is a whitespace according to the JLS (&#92;u000a, &#92;u000c, &#92;u000d, &#92;u0009), otherwise false.
-	 * <br>
-	 * <br>
-	 * For example:
-	 * <ol>
-	 * <li><pre>
-	 *    c = ' '
-	 *    result => true
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    c = '&#92;u3000'
-	 *    result => false
-	 * </pre>
-	 * </li>
-	 * </ol>
-	 * 
-	 * @param c the character to check
-	 * @return true if c is a whitespace according to the JLS, otherwise false.
-	 */
-	public static boolean isWhitespace(char c) {
-		switch (c) {
-			case 10 : /* \ u000a: LINE FEED               */
-			case 12 : /* \ u000c: FORM FEED               */
-			case 13 : /* \ u000d: CARRIAGE RETURN         */
-			case 32 : /* \ u0020: SPACE                   */
-			case 9 : /* \ u0009: HORIZONTAL TABULATION   */
-				return true;
-			default :
-				return false;
-		}
-	}
-	/**
-	 * Answers the first index in the array for which the corresponding character is
-	 * equal to toBeFound. Answers -1 if no occurrence of this character is found.
-	 * <br>
-	 * <br>
-	 * For example:
-	 * <ol>
-	 * <li><pre>
-	 *    toBeFound = 'c'
-	 *    array = { ' a', 'b', 'c', 'd' }
-	 *    result => 2
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    toBeFound = 'e'
-	 *    array = { ' a', 'b', 'c', 'd' }
-	 *    result => -1
-	 * </pre>
-	 * </li>
-	 * </ol>
-	 * 
-	 * @param toBeFound the character to search
-	 * @param array the array to be searched
-	 * @return the first index in the array for which the corresponding character is
-	 * equal to toBeFound, -1 otherwise
-	 * @exception NullPointerException if array is null
-	 */
-	public static final int indexOf(char toBeFound, char[] array) {
-		for (int i = 0; i < array.length; i++)
-			if (toBeFound == array[i])
-				return i;
-		return -1;
-	}
-	/**
-	 * Answers the first index in the array for which the corresponding character is
-	 * equal to toBeFound starting the search at index start.
-	 * Answers -1 if no occurrence of this character is found.
-	 * <br>
-	 * <br>
-	 * For example:
-	 * <ol>
-	 * <li><pre>
-	 *    toBeFound = 'c'
-	 *    array = { ' a', 'b', 'c', 'd' }
-	 *    start = 2
-	 *    result => 2
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    toBeFound = 'c'
-	 *    array = { ' a', 'b', 'c', 'd' }
-	 *    start = 3
-	 *    result => -1
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    toBeFound = 'e'
-	 *    array = { ' a', 'b', 'c', 'd' }
-	 *    start = 1
-	 *    result => -1
-	 * </pre>
-	 * </li>
-	 * </ol>
-	 * 
-	 * @param toBeFound the character to search
-	 * @param array the array to be searched
-	 * @param start the starting index
-	 * @return the first index in the array for which the corresponding character is
-	 * equal to toBeFound, -1 otherwise
-	 * @exception NullPointerException if array is null
-	 * @exception ArrayIndexOutOfBoundsException if  start is lower than 0
-	 */
-	public static final int indexOf(char toBeFound, char[] array, int start) {
-		for (int i = start; i < array.length; i++)
-			if (toBeFound == array[i])
-				return i;
-		return -1;
-	}
-	/**
-	 * Answers the last index in the array for which the corresponding character is
-	 * equal to toBeFound starting from the end of the array.
-	 * Answers -1 if no occurrence of this character is found.
-	 * <br>
-	 * <br>
-	 * For example:
-	 * <ol>
-	 * <li><pre>
-	 *    toBeFound = 'c'
-	 *    array = { ' a', 'b', 'c', 'd' , 'c', 'e' }
-	 *    result => 4
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    toBeFound = 'e'
-	 *    array = { ' a', 'b', 'c', 'd' }
-	 *    result => -1
-	 * </pre>
-	 * </li>
-	 * </ol>
-	 *
-	 * @param toBeFound the character to search
-	 * @param array the array to be searched
-	 * @return the last index in the array for which the corresponding character is
-	 * equal to toBeFound starting from the end of the array, -1 otherwise
-	 * @exception NullPointerException if array is null
-	 */
-	public static final int lastIndexOf(char toBeFound, char[] array) {
-		for (int i = array.length; --i >= 0;)
-			if (toBeFound == array[i])
-				return i;
-		return -1;
-	}
-	/**
-	 * Answers the last index in the array for which the corresponding character is
-	 * equal to toBeFound stopping at the index startIndex.
-	 * Answers -1 if no occurrence of this character is found.
-	 * <br>
-	 * <br>
-	 * For example:
-	 * <ol>
-	 * <li><pre>
-	 *    toBeFound = 'c'
-	 *    array = { ' a', 'b', 'c', 'd' }
-	 *    startIndex = 2
-	 *    result => 2
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    toBeFound = 'c'
-	 *    array = { ' a', 'b', 'c', 'd', 'e' }
-	 *    startIndex = 3
-	 *    result => -1
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    toBeFound = 'e'
-	 *    array = { ' a', 'b', 'c', 'd' }
-	 *    startIndex = 0
-	 *    result => -1
-	 * </pre>
-	 * </li>
-	 * </ol>
-	 *
-	 * @param toBeFound the character to search
-	 * @param array the array to be searched
-	 * @param startIndex the stopping index
-	 * @return the last index in the array for which the corresponding character is
-	 * equal to toBeFound stopping at the index startIndex, -1 otherwise
-	 * @exception NullPointerException if array is null
-	 * @exception ArrayIndexOutOfBoundsException if startIndex is lower than 0
-	 */
-	public static final int lastIndexOf(
-		char toBeFound,
-		char[] array,
-		int startIndex) {
-		for (int i = array.length; --i >= startIndex;)
-			if (toBeFound == array[i])
-				return i;
-		return -1;
-	}
-	/**
-	 * Answers the last index in the array for which the corresponding character is
-	 * equal to toBeFound starting from endIndex to startIndex.
-	 * Answers -1 if no occurrence of this character is found.
-	 * <br>
-	 * <br>
-	 * For example:
-	 * <ol>
-	 * <li><pre>
-	 *    toBeFound = 'c'
-	 *    array = { ' a', 'b', 'c', 'd' }
-	 *    startIndex = 2
-	 *    endIndex = 2
-	 *    result => 2
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    toBeFound = 'c'
-	 *    array = { ' a', 'b', 'c', 'd', 'e' }
-	 *    startIndex = 3
-	 *    endIndex = 4
-	 *    result => -1
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    toBeFound = 'e'
-	 *    array = { ' a', 'b', 'c', 'd' }
-	 *    startIndex = 0
-	 *    endIndex = 3
-	 *    result => -1
-	 * </pre>
-	 * </li>
-	 * </ol>
-	 * 
-	 * @param toBeFound the character to search
-	 * @param array the array to be searched
-	 * @param startIndex the stopping index
-	 * @param endIndex the starting index
-	 * @return the last index in the array for which the corresponding character is
-	 * equal to toBeFound starting from endIndex to startIndex, -1 otherwise
-	 * @exception NullPointerException if array is null
-	 * @exception ArrayIndexOutOfBoundsException if endIndex is greater or equals to array length or starting is lower than 0
-	 */
-	public static final int lastIndexOf(
-		char toBeFound,
-		char[] array,
-		int startIndex,
-		int endIndex) {
-		for (int i = endIndex; --i >= startIndex;)
-			if (toBeFound == array[i])
-				return i;
-		return -1;
-	}
-	/**
-	 * Answers the last portion of a name given a separator.
-	 * <br>
-	 * <br>
-	 * For example,
-	 * <pre>
-	 * 	lastSegment("java.lang.Object".toCharArray(),'.') --> Object
-	 * </pre>
-	 * 
-	 * @param array the array
-	 * @param separator the given separator
-	 * @return the last portion of a name given a separator
-	 * @exception NullPointerException if array is null
-	 */
-	final static public char[] lastSegment(char[] array, char separator) {
-		int pos = lastIndexOf(separator, array);
-		if (pos < 0)
-			return array;
-		return subarray(array, pos + 1, array.length);
-	}
-	/**
-	 * Answers true if the pattern matches the given name, false otherwise. This char[] pattern matching
-	 * accepts wild-cards '*' and '?'.
-	 *
-	 * When not case sensitive, the pattern is assumed to already be lowercased, the
-	 * name will be lowercased character per character as comparing.
-	 * If name is null, the answer is false.
-	 * If pattern is null, the answer is true if name is not null.
-	 * <br>
-	 * <br>
-	 * For example:
-	 * <ol>
-	 * <li><pre>
-	 *    pattern = { '?', 'b', '*' }
-	 *    name = { 'a', 'b', 'c' , 'd' }
-	 *    isCaseSensitive = true
-	 *    result => true
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    pattern = { '?', 'b', '?' }
-	 *    name = { 'a', 'b', 'c' , 'd' }
-	 *    isCaseSensitive = true
-	 *    result => false
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    pattern = { 'b', '*' }
-	 *    name = { 'a', 'b', 'c' , 'd' }
-	 *    isCaseSensitive = true
-	 *    result => false
-	 * </pre>
-	 * </li>
-	 * </ol>
-	 * 
-	 * @param pattern the given pattern
-	 * @param name the given name
-	 * @param isCaseSensitive flag to know whether or not the matching should be case sensitive
-	 * @return true if the pattern matches the given name, false otherwise
-	 */
-	public static final boolean match(
-		char[] pattern,
-		char[] name,
-		boolean isCaseSensitive) {
-
-		if (name == null)
-			return false; // null name cannot match
-		if (pattern == null)
-			return true; // null pattern is equivalent to '*'
-
-		return match(
-			pattern,
-			0,
-			pattern.length,
-			name,
-			0,
-			name.length,
-			isCaseSensitive);
-	}
-	/**
-	 * Answers true if the a sub-pattern matches the subpart of the given name, false otherwise.
-	 * char[] pattern matching, accepting wild-cards '*' and '?'. Can match only subset of name/pattern.
-	 * end positions are non-inclusive.
-	 * The subpattern is defined by the patternStart and pattternEnd positions.
-	 * When not case sensitive, the pattern is assumed to already be lowercased, the
-	 * name will be lowercased character per character as comparing.
-	 * <br>
-	 * <br>
-	 * For example:
-	 * <ol>
-	 * <li><pre>
-	 *    pattern = { '?', 'b', '*' }
-	 *    patternStart = 1
-	 *    patternEnd = 3
-	 *    name = { 'a', 'b', 'c' , 'd' }
-	 *    nameStart = 1
-	 *    nameEnd = 4
-	 *    isCaseSensitive = true
-	 *    result => true
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    pattern = { '?', 'b', '*' }
-	 *    patternStart = 1
-	 *    patternEnd = 2
-	 *    name = { 'a', 'b', 'c' , 'd' }
-	 *    nameStart = 1
-	 *    nameEnd = 2
-	 *    isCaseSensitive = true
-	 *    result => false
-	 * </pre>
-	 * </li>
-	 * </ol>
-	 * 
-	 * @param pattern the given pattern
-	 * @param patternStart the given pattern start
-	 * @param patternEnd the given pattern end
-	 * @param name the given name
-	 * @param nameStart the given name start
-	 * @param nameEnd the given name end
-	 * @param isCaseSensitive flag to know if the matching should be case sensitive
-	 * @return true if the a sub-pattern matches the subpart of the given name, false otherwise
-	 */
-	public static final boolean match(
-		char[] pattern,
-		int patternStart,
-		int patternEnd,
-		char[] name,
-		int nameStart,
-		int nameEnd,
-		boolean isCaseSensitive) {
-
-		if (name == null)
-			return false; // null name cannot match
-		if (pattern == null)
-			return true; // null pattern is equivalent to '*'
-		int iPattern = patternStart;
-		int iName = nameStart;
-
-		if (patternEnd < 0)
-			patternEnd = pattern.length;
-		if (nameEnd < 0)
-			nameEnd = name.length;
-
-		/* check first segment */
-		char patternChar = 0;
-		while ((iPattern < patternEnd)
-			&& (patternChar = pattern[iPattern]) != '*') {
-			if (iName == nameEnd)
-				return false;
-			if (patternChar
-				!= (isCaseSensitive
-					? name[iName]
-					: Character.toLowerCase(name[iName]))
-				&& patternChar != '?') {
-				return false;
-			}
-			iName++;
-			iPattern++;
-		}
-		/* check sequence of star+segment */
-		int segmentStart;
-		if (patternChar == '*') {
-			segmentStart = ++iPattern; // skip star
-		} else {
-			segmentStart = 0; // force iName check
-		}
-		int prefixStart = iName;
-		checkSegment : while (iName < nameEnd) {
-			if (iPattern == patternEnd) {
-				iPattern = segmentStart; // mismatch - restart current segment
-				iName = ++prefixStart;
-				continue checkSegment;
-			}
-			/* segment is ending */
-			if ((patternChar = pattern[iPattern]) == '*') {
-				segmentStart = ++iPattern; // skip start
-				if (segmentStart == patternEnd) {
-					return true;
-				}
-				prefixStart = iName;
-				continue checkSegment;
-			}
-			/* check current name character */
-			if ((isCaseSensitive ? name[iName] : Character.toLowerCase(name[iName]))
-						!= patternChar
-					&& patternChar != '?') {
-				iPattern = segmentStart; // mismatch - restart current segment
-				iName = ++prefixStart;
-				continue checkSegment;
-			}
-			iName++;
-			iPattern++;
-		}
-
-		return (segmentStart == patternEnd)
-			|| (iName == nameEnd && iPattern == patternEnd)
-			|| (iPattern == patternEnd - 1 && pattern[iPattern] == '*');
-	}
-	/**
-	 * Answers true if the pattern matches the filepath using the pathSepatator, false otherwise.
-	 * 
-	 * Path char[] pattern matching, accepting wild-cards '**', '*' and '?' (using Ant directory tasks
-	 * conventions, also see "http://jakarta.apache.org/ant/manual/dirtasks.html#defaultexcludes";).
-	 * Path pattern matching is enhancing regular pattern matching in supporting extra rule where '**' represent
-	 * any folder combination.
-	 * Special rules: 
-	 * - foo\  is equivalent to foo\**   
-	 * - *.java is equivalent to **\*.java
-	 * When not case sensitive, the pattern is assumed to already be lowercased, the
-	 * name will be lowercased character per character as comparing.
-	 * 
-	 * @param pattern the given pattern
-	 * @param filepath the given path 
-	 * @param isCaseSensitive to find out whether or not the matching should be case sensitive
-	 * @param pathSeparator the given path separator
-	 * @return true if the pattern matches the filepath using the pathSepatator, false otherwise
-	 */
-	public static final boolean pathMatch(
-		char[] pattern,
-		char[] filepath,
-		boolean isCaseSensitive,
-		char pathSeparator) {
-
-		if (filepath == null)
-			return false; // null name cannot match
-		if (pattern == null)
-			return true; // null pattern is equivalent to '*'
-
-		// special case: pattern foo is equivalent to **\foo (not absolute)
-		boolean freeLeadingDoubleStar;
-
-		// offsets inside pattern
-		int pSegmentStart, pLength = pattern.length;
-
-		if (freeLeadingDoubleStar = pattern[0] != pathSeparator){
-			pSegmentStart = 0;
-		} else {
-			pSegmentStart = 1;
-		}
-		int pSegmentEnd = CharOperation.indexOf(pathSeparator, pattern, pSegmentStart+1);
-		if (pSegmentEnd < 0) pSegmentEnd = pLength;
-
-		// special case: pattern foo\ is equivalent to foo\**
-		boolean freeTrailingDoubleStar = pattern[pLength - 1] == pathSeparator;
-
-		// offsets inside filepath
-		int fSegmentStart, fLength = filepath.length;
-		if (filepath[0] != pathSeparator){
-			fSegmentStart = 0;
-		} else {
-			fSegmentStart = 1;
-		}
-		if (fSegmentStart != pSegmentStart) {
-			return false; // both must start with a separator or none.
-		}
-		int fSegmentEnd = CharOperation.indexOf(pathSeparator, filepath, fSegmentStart+1);
-		if (fSegmentEnd < 0) fSegmentEnd = fLength;
-
-		// first segments
-		while (pSegmentStart < pLength
-			&& !freeLeadingDoubleStar
-			&& !(pSegmentEnd == pLength && freeTrailingDoubleStar
-					|| (pSegmentEnd == pSegmentStart + 2
-							&& pattern[pSegmentStart] == '*'
-							&& pattern[pSegmentStart + 1] == '*'))) {
-
-			if (fSegmentStart >= fLength)
-				return false;
-			if (!CharOperation
-				.match(
-					pattern,
-					pSegmentStart,
-					pSegmentEnd,
-					filepath,
-					fSegmentStart,
-					fSegmentEnd,
-					isCaseSensitive)) {
-				return false;
-			}
-
-			// jump to next segment		
-			pSegmentEnd =
-				CharOperation.indexOf(
-					pathSeparator,
-					pattern,
-					pSegmentStart = pSegmentEnd + 1);
-			// skip separator
-			if (pSegmentEnd < 0)
-				pSegmentEnd = pLength;
-
-			fSegmentEnd =
-				CharOperation.indexOf(
-					pathSeparator,
-					filepath,
-					fSegmentStart = fSegmentEnd + 1);
-			// skip separator
-			if (fSegmentEnd < 0) fSegmentEnd = fLength;
-		}
-
-		/* check sequence of doubleStar+segment */
-		int pSegmentRestart;
-		if ((pSegmentStart >= pLength && freeTrailingDoubleStar)
-				|| (pSegmentEnd == pSegmentStart + 2
-					&& pattern[pSegmentStart] == '*'
-					&& pattern[pSegmentStart + 1] == '*')) {
-			pSegmentEnd =
-				CharOperation.indexOf(
-					pathSeparator,
-					pattern,
-					pSegmentStart = pSegmentEnd + 1);
-			// skip separator
-			if (pSegmentEnd < 0) pSegmentEnd = pLength;
-			pSegmentRestart = pSegmentStart;
-		} else {
-			if (pSegmentStart >= pLength) return fSegmentStart >= fLength; // true if filepath is done too.
-			pSegmentRestart = 0; // force fSegmentStart check
-		}
-		int fSegmentRestart = fSegmentStart;
-		checkSegment : while (fSegmentStart < fLength) {
-				
-			if (pSegmentStart >= pLength) {
-				if (freeTrailingDoubleStar) return true;
-				// mismatch - restart current path segment
-				pSegmentEnd =
-					CharOperation.indexOf(pathSeparator, pattern, pSegmentStart = pSegmentRestart);
-				if (pSegmentEnd < 0) pSegmentEnd = pLength;
-
-				fSegmentRestart = 
-					CharOperation.indexOf(pathSeparator, filepath, fSegmentRestart + 1);
-				// skip separator
-				if (fSegmentRestart < 0) {
-					fSegmentRestart = fLength;
-				} else {
-					fSegmentRestart++;
-				}
-				fSegmentEnd =
-					CharOperation.indexOf(pathSeparator, filepath, fSegmentStart = fSegmentRestart);
-				if (fSegmentEnd < 0) fSegmentEnd = fLength;
-				continue checkSegment;
-			}
-			
-			/* path segment is ending */
-			if (pSegmentEnd == pSegmentStart + 2
-				&& pattern[pSegmentStart] == '*'
-				&& pattern[pSegmentStart + 1] == '*') {
-				pSegmentEnd =
-					CharOperation.indexOf(pathSeparator, pattern, pSegmentStart = pSegmentEnd + 1);
-				// skip separator
-				if (pSegmentEnd < 0) pSegmentEnd = pLength;
-				pSegmentRestart = pSegmentStart;
-				fSegmentRestart = fSegmentStart;
-				if (pSegmentStart >= pLength) return true;
-				continue checkSegment;
-			}
-			/* chech current path segment */
-			if (!CharOperation.match(
-								pattern,
-								pSegmentStart,
-								pSegmentEnd,
-								filepath,
-								fSegmentStart,
-								fSegmentEnd,
-								isCaseSensitive)) {
-				// mismatch - restart current path segment
-				pSegmentEnd =
-					CharOperation.indexOf(pathSeparator, pattern, pSegmentStart = pSegmentRestart);
-				if (pSegmentEnd < 0) pSegmentEnd = pLength;
-
-				fSegmentRestart = 
-					CharOperation.indexOf(pathSeparator, filepath, fSegmentRestart + 1);
-				// skip separator
-				if (fSegmentRestart < 0) {
-					fSegmentRestart = fLength;
-				} else {
-					fSegmentRestart++;
-				}
-				fSegmentEnd =
-					CharOperation.indexOf(pathSeparator, filepath, fSegmentStart = fSegmentRestart);
-				if (fSegmentEnd < 0) fSegmentEnd = fLength;
-				continue checkSegment;
-			}
-			// jump to next segment		
-			pSegmentEnd =
-				CharOperation.indexOf(
-					pathSeparator,
-					pattern,
-					pSegmentStart = pSegmentEnd + 1);
-			// skip separator
-			if (pSegmentEnd < 0)
-				pSegmentEnd = pLength;
-
-			fSegmentEnd =
-				CharOperation.indexOf(
-					pathSeparator,
-					filepath,
-					fSegmentStart = fSegmentEnd + 1);
-			// skip separator
-			if (fSegmentEnd < 0)
-				fSegmentEnd = fLength;
-		}
-
-		return (pSegmentRestart >= pSegmentEnd)
-			|| (fSegmentStart >= fLength && pSegmentStart >= pLength)
-			|| (pSegmentStart == pLength - 2
-				&& pattern[pSegmentStart] == '*'
-				&& pattern[pSegmentStart + 1] == '*')
-			|| (pSegmentStart == pLength && freeTrailingDoubleStar);
-	}
-	/**
-	 * Answers the number of occurrences of the given character in the given array, 0 if any.
-	 * 
-	 * <br>
-	 * <br>
-	 * For example:
-	 * <ol>
-	 * <li><pre>
-	 *    toBeFound = 'b'
-	 *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
-	 *    result => 3
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    toBeFound = 'c'
-	 *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
-	 *    result => 0
-	 * </pre>
-	 * </li>
-	 * </ol>
-	 * 
-	 * @param toBeFound the given character
-	 * @param array the given array
-	 * @return the number of occurrences of the given character in the given array, 0 if any
-	 * @exception NullPointerException if array is null
-	 */
-	public static final int occurencesOf(char toBeFound, char[] array) {
-		int count = 0;
-		for (int i = 0; i < array.length; i++)
-			if (toBeFound == array[i])
-				count++;
-		return count;
-	}
-	/**
-	 * Answers the number of occurrences of the given character in the given array starting
-	 * at the given index, 0 if any.
-	 * 
-	 * <br>
-	 * <br>
-	 * For example:
-	 * <ol>
-	 * <li><pre>
-	 *    toBeFound = 'b'
-	 *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
-	 *    start = 2
-	 *    result => 2
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    toBeFound = 'c'
-	 *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
-	 *    start = 0
-	 *    result => 0
-	 * </pre>
-	 * </li>
-	 * </ol>
-	 * 
-	 * @param toBeFound the given character
-	 * @param array the given array
-	 * @return the number of occurrences of the given character in the given array, 0 if any
-	 * @exception NullPointerException if array is null
-	 * @exception ArrayIndexOutOfBoundsException if start is lower than 0
-	 */
-	public static final int occurencesOf(
-		char toBeFound,
-		char[] array,
-		int start) {
-		int count = 0;
-		for (int i = start; i < array.length; i++)
-			if (toBeFound == array[i])
-				count++;
-		return count;
-	}
-	/**
-	 * Answers true if the given name starts with the given prefix, false otherwise.
-	 * The comparison is case sensitive.
-	 * <br>
-	 * <br>
-	 * For example:
-	 * <ol>
-	 * <li><pre>
-	 *    prefix = { 'a' , 'b' }
-	 *    name = { 'a' , 'b', 'b', 'a', 'b', 'a' }
-	 *    result => true
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    prefix = { 'a' , 'c' }
-	 *    name = { 'a' , 'b', 'b', 'a', 'b', 'a' }
-	 *    result => false
-	 * </pre>
-	 * </li>
-	 * </ol>
-	 * 
-	 * @param prefix the given prefix
-	 * @param name the given name
-	 * @return true if the given name starts with the given prefix, false otherwise
-	 * @exception NullPointerException if the given name is null or if the given prefix is null
-	 */
-	public static final boolean prefixEquals(char[] prefix, char[] name) {
-
-		int max = prefix.length;
-		if (name.length < max)
-			return false;
-		for (int i = max;
-			--i >= 0;
-			) // assumes the prefix is not larger than the name
-			if (prefix[i] != name[i])
-				return false;
-		return true;
-	}
-	/**
-	 * Answers true if the given name starts with the given prefix, false otherwise.
-	 * isCaseSensitive is used to find out whether or not the comparison should be case sensitive.
-	 * <br>
-	 * <br>
-	 * For example:
-	 * <ol>
-	 * <li><pre>
-	 *    prefix = { 'a' , 'B' }
-	 *    name = { 'a' , 'b', 'b', 'a', 'b', 'a' }
-	 *    isCaseSensitive = false
-	 *    result => true
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    prefix = { 'a' , 'B' }
-	 *    name = { 'a' , 'b', 'b', 'a', 'b', 'a' }
-	 *    isCaseSensitive = true
-	 *    result => false
-	 * </pre>
-	 * </li>
-	 * </ol>
-	 * 
-	 * @param prefix the given prefix
-	 * @param name the given name
-	 * @param isCaseSensitive to find out whether or not the comparison should be case sensitive
-	 * @return true if the given name starts with the given prefix, false otherwise
-	 * @exception NullPointerException if the given name is null or if the given prefix is null
-	 */
-	public static final boolean prefixEquals(
-		char[] prefix,
-		char[] name,
-		boolean isCaseSensitive) {
-
-		int max = prefix.length;
-		if (name.length < max)
-			return false;
-		if (isCaseSensitive) {
-			for (int i = max;
-				--i >= 0;
-				) // assumes the prefix is not larger than the name
-				if (prefix[i] != name[i])
-					return false;
-			return true;
-		}
-
-		for (int i = max;
-			--i >= 0;
-			) // assumes the prefix is not larger than the name
-			if (Character.toLowerCase(prefix[i])
-				!= Character.toLowerCase(name[i]))
-				return false;
-		return true;
-	}
-	/**
-	 * Replace all occurrence of the character to be replaced with the remplacement character in the
-	 * given array.
-	 * <br>
-	 * <br>
-	 * For example:
-	 * <ol>
-	 * <li><pre>
-	 *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
-	 *    toBeReplaced = 'b'
-	 *    replacementChar = 'a'
-	 *    result => No returned value, but array is now equals to { 'a' , 'a', 'a', 'a', 'a', 'a' }
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
-	 *    toBeReplaced = 'c'
-	 *    replacementChar = 'a'
-	 *    result => No returned value, but array is now equals to { 'a' , 'b', 'b', 'a', 'b', 'a' }
-	 * </pre>
-	 * </li>
-	 * </ol>
-	 * 
-	 * @param array the given array
-	 * @param toBeReplaced the character to be replaced
-	 * @param replacementChar the replacement character
-	 * @exception NullPointerException if the given array is null
-	 */
-	public static final void replace(
-		char[] array,
-		char toBeReplaced,
-		char replacementChar) {
-		if (toBeReplaced != replacementChar) {
-			for (int i = 0, max = array.length; i < max; i++) {
-				if (array[i] == toBeReplaced)
-					array[i] = replacementChar;
-			}
-		}
-	}
-	/**
-	 * Answers a new array of characters with substitutions. No side-effect is operated on the original
-	 * array, in case no substitution happened, then the result is the same as the
-	 * original one.
-	 * <br>
-	 * <br>
-	 * For example:
-	 * <ol>
-	 * <li><pre>
-	 *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
-	 *    toBeReplaced = { 'b' }
-	 *    replacementChar = { 'a', 'a' }
-	 *    result => { 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a' }
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
-	 *    toBeReplaced = { 'c' }
-	 *    replacementChar = { 'a' }
-	 *    result => { 'a' , 'b', 'b', 'a', 'b', 'a' }
-	 * </pre>
-	 * </li>
-	 * </ol>
-	 * 
-	 * @param the given array
-	 * @param toBeReplaced characters to be replaced
-	 * @param the replacement characters
-	 * @return a new array of characters with substitutions or the given array if none
-	 * @exception NullPointerException if the given array is null
-	 */
-	public static final char[] replace(
-		char[] array,
-		char[] toBeReplaced,
-		char[] replacementChars) {
-
-		int max = array.length;
-		int replacedLength = toBeReplaced.length;
-		int replacementLength = replacementChars.length;
-
-		int[] starts = new int[5];
-		int occurrenceCount = 0;
-
-		if (!equals(toBeReplaced, replacementChars)) {
-
-			next : for (int i = 0; i < max; i++) {
-				int j = 0;
-				while (j < replacedLength) {
-					if (i + j == max)
-						continue next;
-					if (array[i + j] != toBeReplaced[j++])
-						continue next;
-				}
-				if (occurrenceCount == starts.length) {
-					System.arraycopy(
-						starts,
-						0,
-						starts = new int[occurrenceCount * 2],
-						0,
-						occurrenceCount);
-				}
-				starts[occurrenceCount++] = i;
-			}
-		}
-		if (occurrenceCount == 0)
-			return array;
-		char[] result =
-			new char[max
-				+ occurrenceCount * (replacementLength - replacedLength)];
-		int inStart = 0, outStart = 0;
-		for (int i = 0; i < occurrenceCount; i++) {
-			int offset = starts[i] - inStart;
-			System.arraycopy(array, inStart, result, outStart, offset);
-			inStart += offset;
-			outStart += offset;
-			System.arraycopy(
-				replacementChars,
-				0,
-				result,
-				outStart,
-				replacementLength);
-			inStart += replacedLength;
-			outStart += replacementLength;
-		}
-		System.arraycopy(array, inStart, result, outStart, max - inStart);
-		return result;
-	}
-	/**
-	 * Return a new array which is the split of the given array using the given divider and triming each subarray to remove
-	 * whitespaces equals to ' '.
-	 * <br>
-	 * <br>
-	 * For example:
-	 * <ol>
-	 * <li><pre>
-	 *    divider = 'b'
-	 *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
-	 *    result => { { 'a' }, {  }, { 'a' }, { 'a' } }
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    divider = 'c'
-	 *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
-	 *    result => { { 'a', 'b', 'b', 'a', 'b', 'a' } }
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    divider = 'b'
-	 *    array = { 'a' , ' ', 'b', 'b', 'a', 'b', 'a' }
-	 *    result => { { 'a' }, {  }, { 'a' }, { 'a' } }
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    divider = 'c'
-	 *    array = { ' ', ' ', 'a' , 'b', 'b', 'a', 'b', 'a', ' ' }
-	 *    result => { { 'a', 'b', 'b', 'a', 'b', 'a' } }
-	 * </pre>
-	 * </li>
-	 * </ol>
-	 * 
-	 * @param divider the given divider
-	 * @param array the given array
-	 * @return a new array which is the split of the given array using the given divider and triming each subarray to remove
-	 * whitespaces equals to ' '
-	 */
-	public static final char[][] splitAndTrimOn(char divider, char[] array) {
-		int length = array == null ? 0 : array.length;
-		if (length == 0)
-			return NO_CHAR_CHAR;
-
-		int wordCount = 1;
-		for (int i = 0; i < length; i++)
-			if (array[i] == divider)
-				wordCount++;
-		char[][] split = new char[wordCount][];
-		int last = 0, currentWord = 0;
-		for (int i = 0; i < length; i++) {
-			if (array[i] == divider) {
-				int start = last, end = i - 1;
-				while (start < i && array[start] == ' ')
-					start++;
-				while (end > start && array[end] == ' ')
-					end--;
-				split[currentWord] = new char[end - start + 1];
-				System.arraycopy(
-					array,
-					start,
-					split[currentWord++],
-					0,
-					end - start + 1);
-				last = i + 1;
-			}
-		}
-		int start = last, end = length - 1;
-		while (start < length && array[start] == ' ')
-			start++;
-		while (end > start && array[end] == ' ')
-			end--;
-		split[currentWord] = new char[end - start + 1];
-		System.arraycopy(
-			array,
-			start,
-			split[currentWord++],
-			0,
-			end - start + 1);
-		return split;
-	}
-	/**
-	 * Return a new array which is the split of the given array using the given divider.
-	 * <br>
-	 * <br>
-	 * For example:
-	 * <ol>
-	 * <li><pre>
-	 *    divider = 'b'
-	 *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
-	 *    result => { { 'a' }, {  }, { 'a' }, { 'a' } }
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    divider = 'c'
-	 *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
-	 *    result => { { 'a', 'b', 'b', 'a', 'b', 'a' } }
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    divider = 'c'
-	 *    array = { ' ', ' ', 'a' , 'b', 'b', 'a', 'b', 'a', ' ' }
-	 *    result => { { ' ', 'a', 'b', 'b', 'a', 'b', 'a', ' ' } }
-	 * </pre>
-	 * </li>
-	 * </ol>
-	 * 
-	 * @param divider the given divider
-	 * @param array the given array
-	 * @return a new array which is the split of the given array using the given divider
-	 */
-	public static final char[][] splitOn(char divider, char[] array) {
-		int length = array == null ? 0 : array.length;
-		if (length == 0)
-			return NO_CHAR_CHAR;
-
-		int wordCount = 1;
-		for (int i = 0; i < length; i++)
-			if (array[i] == divider)
-				wordCount++;
-		char[][] split = new char[wordCount][];
-		int last = 0, currentWord = 0;
-		for (int i = 0; i < length; i++) {
-			if (array[i] == divider) {
-				split[currentWord] = new char[i - last];
-				System.arraycopy(
-					array,
-					last,
-					split[currentWord++],
-					0,
-					i - last);
-				last = i + 1;
-			}
-		}
-		split[currentWord] = new char[length - last];
-		System.arraycopy(array, last, split[currentWord], 0, length - last);
-		return split;
-	}
-	/**
-	 * Return a new array which is the split of the given array using the given divider. The given end 
-	 * is exclusive and the given start is inclusive.
-	 * <br>
-	 * <br>
-	 * For example:
-	 * <ol>
-	 * <li><pre>
-	 *    divider = 'b'
-	 *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
-	 *    start = 2
-	 *    end = 5
-	 *    result => { {  }, {  }, { 'a' } }
-	 * </pre>
-	 * </li>
-	 * </ol>
-	 * 
-	 * @param divider the given divider
-	 * @param array the given array
-	 * @param start the given starting index
-	 * @param end the given ending index
-	 * @return a new array which is the split of the given array using the given divider
-	 * @exception ArrayIndexOutOfBoundsException if start is lower than 0 or end is greater than the array length
-	 */
-	public static final char[][] splitOn(
-		char divider,
-		char[] array,
-		int start,
-		int end) {
-		int length = array == null ? 0 : array.length;
-		if (length == 0 || start > end)
-			return NO_CHAR_CHAR;
-
-		int wordCount = 1;
-		for (int i = start; i < end; i++)
-			if (array[i] == divider)
-				wordCount++;
-		char[][] split = new char[wordCount][];
-		int last = start, currentWord = 0;
-		for (int i = start; i < end; i++) {
-			if (array[i] == divider) {
-				split[currentWord] = new char[i - last];
-				System.arraycopy(
-					array,
-					last,
-					split[currentWord++],
-					0,
-					i - last);
-				last = i + 1;
-			}
-		}
-		split[currentWord] = new char[end - last];
-		System.arraycopy(array, last, split[currentWord], 0, end - last);
-		return split;
-	}
-	/**
-	 * Answers a new array which is a copy of the given array starting at the given start and 
-	 * ending at the given end. The given start is inclusive and the given end is exclusive.
-	 * Answers null if start is greater than end, if start is lower than 0 or if end is greater 
-	 * than the length of the given array. If end  equals -1, it is converted to the array length.
-	 * <br>
-	 * <br>
-	 * For example:
-	 * <ol>
-	 * <li><pre>
-	 *    array = { { 'a' } , { 'b' } }
-	 *    start = 0
-	 *    end = 1
-	 *    result => { { 'a' } }
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    array = { { 'a' } , { 'b' } }
-	 *    start = 0
-	 *    end = -1
-	 *    result => { { 'a' }, { 'b' } }
-	 * </pre>
-	 * </li>
-	 * </ol>
-	 *  
-	 * @param array the given array
-	 * @param start the given starting index
-	 * @param end the given ending index
-	 * @return a new array which is a copy of the given array starting at the given start and 
-	 * ending at the given end
-	 * @exception NullPointerException if the given array is null
-	 */
-	public static final char[][] subarray(char[][] array, int start, int end) {
-		if (end == -1)
-			end = array.length;
-		if (start > end)
-			return null;
-		if (start < 0)
-			return null;
-		if (end > array.length)
-			return null;
-
-		char[][] result = new char[end - start][];
-		System.arraycopy(array, start, result, 0, end - start);
-		return result;
-	}
-	/**
-	 * Answers a new array which is a copy of the given array starting at the given start and 
-	 * ending at the given end. The given start is inclusive and the given end is exclusive.
-	 * Answers null if start is greater than end, if start is lower than 0 or if end is greater 
-	 * than the length of the given array. If end  equals -1, it is converted to the array length.
-	 * <br>
-	 * <br>
-	 * For example:
-	 * <ol>
-	 * <li><pre>
-	 *    array = { 'a' , 'b' }
-	 *    start = 0
-	 *    end = 1
-	 *    result => { 'a' }
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    array = { 'a', 'b' }
-	 *    start = 0
-	 *    end = -1
-	 *    result => { 'a' , 'b' }
-	 * </pre>
-	 * </li>
-	 * </ol>
-	 *  
-	 * @param array the given array
-	 * @param start the given starting index
-	 * @param end the given ending index
-	 * @return a new array which is a copy of the given array starting at the given start and 
-	 * ending at the given end
-	 * @exception NullPointerException if the given array is null
-	 */
-	public static final char[] subarray(char[] array, int start, int end) {
-		if (end == -1)
-			end = array.length;
-		if (start > end)
-			return null;
-		if (start < 0)
-			return null;
-		if (end > array.length)
-			return null;
-
-		char[] result = new char[end - start];
-		System.arraycopy(array, start, result, 0, end - start);
-		return result;
-	}
-	/**
-	 * Answers the result of a char[] conversion to lowercase. Answers null if the given chars array is null.
-	 * <br>
-	 * NOTE: If no conversion was necessary, then answers back the argument one.
-	 * <br>
-	 * <br>
-	 * For example:
-	 * <ol>
-	 * <li><pre>
-	 *    chars = { 'a' , 'b' }
-	 *    result => { 'a' , 'b' }
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    array = { 'A', 'b' }
-	 *    result => { 'a' , 'b' }
-	 * </pre>
-	 * </li>
-	 * </ol>
-	 * 
-	 * @param chars the chars to convert
-	 * @return the result of a char[] conversion to lowercase
-	 */
-	final static public char[] toLowerCase(char[] chars) {
-		if (chars == null)
-			return null;
-		int length = chars.length;
-		char[] lowerChars = null;
-		for (int i = 0; i < length; i++) {
-			char c = chars[i];
-			char lc = Character.toLowerCase(c);
-			if ((c != lc) || (lowerChars != null)) {
-				if (lowerChars == null) {
-					System.arraycopy(
-						chars,
-						0,
-						lowerChars = new char[length],
-						0,
-						i);
-				}
-				lowerChars[i] = lc;
-			}
-		}
-		return lowerChars == null ? chars : lowerChars;
-	}
-	/**
-	 * Answers a new array removing leading and trailing spaces (' '). Answers the given array if there is no
-	 * space characters to remove.
-	 * <br>
-	 * <br>
-	 * For example:
-	 * <ol>
-	 * <li><pre>
-	 *    chars = { ' ', 'a' , 'b', ' ',  ' ' }
-	 *    result => { 'a' , 'b' }
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    array = { 'A', 'b' }
-	 *    result => { 'A' , 'b' }
-	 * </pre>
-	 * </li>
-	 * </ol>
-	 * 
-	 * @param chars the given array
-	 * @return a new array removing leading and trailing spaces (' ')
-	 */
-	final static public char[] trim(char[] chars) {
-
-		if (chars == null)
-			return null;
-
-		int start = 0, length = chars.length, end = length - 1;
-		while (start < length && chars[start] == ' ') {
-			start++;
-		}
-		while (end > start && chars[end] == ' ') {
-			end--;
-		}
-		if (start != 0 || end != length - 1) {
-			return subarray(chars, start, end + 1);
-		}
-		return chars;
-	}
-	/**
-	 * Answers a string which is the concatenation of the given array using the '.' as a separator.
-	 * <br>
-	 * <br>
-	 * For example:
-	 * <ol>
-	 * <li><pre>
-	 *    array = { { 'a' } , { 'b' } }
-	 *    result => "a.b"
-	 * </pre>
-	 * </li>
-	 * <li><pre>
-	 *    array = { { ' ',  'a' } , { 'b' } }
-	 *    result => " a.b"
-	 * </pre>
-	 * </li>
-	 * </ol>
-	 * 
-	 * @param chars the given array
-	 * @return a string which is the concatenation of the given array using the '.' as a separator
-	 */
-	final static public String toString(char[][] array) {
-		char[] result = concatWith(array, '.');
-		return new String(result);
-	}
-}
\ No newline at end of file
Index: index/org/eclipse/cdt/internal/core/search/Util.java
===================================================================
RCS file: index/org/eclipse/cdt/internal/core/search/Util.java
diff -N index/org/eclipse/cdt/internal/core/search/Util.java
--- index/org/eclipse/cdt/internal/core/search/Util.java	11 Aug 2003 13:42:47 -0000	1.5
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -1,367 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2000, 2003 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials 
- * are made available under the terms of the Common Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/cpl-v10.html
- * 
- * Contributors:
- *     IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.cdt.internal.core.search;
-
-import java.io.BufferedInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.util.HashSet;
-import java.util.Locale;
-import java.util.MissingResourceException;
-import java.util.ResourceBundle;
-
-import org.eclipse.core.resources.IContainer;
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.runtime.IPath;
-
-public class Util {
-	
-	private final static char[] DOUBLE_QUOTES = "''".toCharArray(); //$NON-NLS-1$
-	private final static char[] SINGLE_QUOTE = "'".toCharArray(); //$NON-NLS-1$
-	private static final int DEFAULT_READING_SIZE = 8192;
-
-	/* Bundle containing messages */
-	protected static ResourceBundle bundle;
-	private final static String bundleName = "org.eclipse.cdt.internal.core.search.messages"; //$NON-NLS-1$
-	static {
-		relocalize();
-	}
-	/**
-	 * Lookup the message with the given ID in this catalog and bind its
-	 * substitution locations with the given strings.
-	 */
-	public static String bind(String id, String binding1, String binding2) {
-		return bind(id, new String[] {binding1, binding2});
-	}
-	/**
-	 * Lookup the message with the given ID in this catalog and bind its
-	 * substitution locations with the given string.
-	 */
-	public static String bind(String id, String binding) {
-		return bind(id, new String[] {binding});
-	}
-	/**
-	 * Lookup the message with the given ID in this catalog and bind its
-	 * substitution locations with the given string values.
-	 */
-	public static String bind(String id, String[] bindings) {
-		if (id == null)
-			return "No message available"; //$NON-NLS-1$
-		String message = null;
-		try {
-			message = bundle.getString(id);
-		} catch (MissingResourceException e) {
-			// If we got an exception looking for the message, fail gracefully by just returning
-			// the id we were looking for.  In most cases this is semi-informative so is not too bad.
-			return "Missing message: " + id + " in: " + bundleName; //$NON-NLS-2$ //$NON-NLS-1$
-		}
-		// for compatibility with MessageFormat which eliminates double quotes in original message
-		char[] messageWithNoDoubleQuotes =
-		CharOperation.replace(message.toCharArray(), DOUBLE_QUOTES, SINGLE_QUOTE);
-		message = new String(messageWithNoDoubleQuotes);
-	
-		if (bindings == null)
-			return message;
-		int length = message.length();
-		int start = -1;
-		int end = length;
-		StringBuffer output = new StringBuffer(80);
-		while (true) {
-			if ((end = message.indexOf('{', start)) > -1) {
-				output.append(message.substring(start + 1, end));
-				if ((start = message.indexOf('}', end)) > -1) {
-					int index = -1;
-					try {
-						index = Integer.parseInt(message.substring(end + 1, start));
-						output.append(bindings[index]);
-					} catch (NumberFormatException nfe) {
-						output.append(message.substring(end + 1, start + 1));
-					} catch (ArrayIndexOutOfBoundsException e) {
-						output.append("{missing " + Integer.toString(index) + "}"); //$NON-NLS-2$ //$NON-NLS-1$
-					}
-				} else {
-					output.append(message.substring(end, length));
-					break;
-				}
-			} else {
-				output.append(message.substring(start + 1, length));
-				break;
-			}
-		}
-		return output.toString();
-	}
-	/**
-	 * Lookup the message with the given ID in this catalog 
-	 */
-	public static String bind(String id) {
-		return bind(id, (String[])null);
-	}
-	/**
-	 * Creates a NLS catalog for the given locale.
-	 */
-	public static void relocalize() {
-		try  {		
-			bundle = ResourceBundle.getBundle(bundleName, Locale.getDefault());
-		} catch(MissingResourceException e) {
-			System.out.println("Missing resource : " + bundleName.replace('.', '/') + ".properties for locale " + Locale.getDefault()); //$NON-NLS-1$//$NON-NLS-2$
-			throw e;
-		}
-	}
-	
-	/**
-	 * Returns the contents of the given file as a byte array.
-	 * @throws IOException if a problem occured reading the file.
-	 */
-	public static byte[] getFileByteContent(File file) throws IOException {
-		InputStream stream = null;
-		try {
-			stream = new BufferedInputStream(new FileInputStream(file));
-			return getInputStreamAsByteArray(stream, (int) file.length());
-		} finally {
-			if (stream != null) {
-				try {
-					stream.close();
-				} catch (IOException e) {
-				}
-			}
-		}
-	}
-	/**
-	 * Returns the contents of the given file as a char array.
-	 * When encoding is null, then the platform default one is used
-	 * @throws IOException if a problem occured reading the file.
-	 */
-	public static char[] getFileCharContent(File file, String encoding) throws IOException {
-		InputStream stream = null;
-		try {
-			stream = new BufferedInputStream(new FileInputStream(file));
-			return Util.getInputStreamAsCharArray(stream, (int) file.length(), encoding);
-		} finally {
-			if (stream != null) {
-				try {
-					stream.close();
-				} catch (IOException e) {
-				}
-			}
-		}
-	}
-	
-	/**
-	 * Returns the given input stream's contents as a byte array.
-	 * If a length is specified (ie. if length != -1), only length bytes
-	 * are returned. Otherwise all bytes in the stream are returned.
-	 * Note this doesn't close the stream.
-	 * @throws IOException if a problem occured reading the stream.
-	 */
-	public static byte[] getInputStreamAsByteArray(InputStream stream, int length)
-		throws IOException {
-		byte[] contents;
-		if (length == -1) {
-			contents = new byte[0];
-			int contentsLength = 0;
-			int amountRead = -1;
-			do {
-				int amountRequested = Math.max(stream.available(), DEFAULT_READING_SIZE);  // read at least 8K
-				
-				// resize contents if needed
-				if (contentsLength + amountRequested > contents.length) {
-					System.arraycopy(
-						contents,
-						0,
-						contents = new byte[contentsLength + amountRequested],
-						0,
-						contentsLength);
-				}
-
-				// read as many bytes as possible
-				amountRead = stream.read(contents, contentsLength, amountRequested);
-
-				if (amountRead > 0) {
-					// remember length of contents
-					contentsLength += amountRead;
-				}
-			} while (amountRead != -1); 
-
-			// resize contents if necessary
-			if (contentsLength < contents.length) {
-				System.arraycopy(
-					contents,
-					0,
-					contents = new byte[contentsLength],
-					0,
-					contentsLength);
-			}
-		} else {
-			contents = new byte[length];
-			int len = 0;
-			int readSize = 0;
-			while ((readSize != -1) && (len != length)) {
-				// See PR 1FMS89U
-				// We record first the read size. In this case len is the actual read size.
-				len += readSize;
-				readSize = stream.read(contents, len, length - len);
-			}
-		}
-
-		return contents;
-	}
-
-	/**
-	 * Returns the given input stream's contents as a character array.
-	 * If a length is specified (ie. if length != -1), only length chars
-	 * are returned. Otherwise all chars in the stream are returned.
-	 * Note this doesn't close the stream.
-	 * @throws IOException if a problem occured reading the stream.
-	 */
-	public static char[] getInputStreamAsCharArray(InputStream stream, int length, String encoding)
-		throws IOException {
-		InputStreamReader reader = null;
-		reader = encoding == null
-					? new InputStreamReader(stream)
-					: new InputStreamReader(stream, encoding);
-		char[] contents;
-		if (length == -1) {
-			contents = CharOperation.NO_CHAR;
-			int contentsLength = 0;
-			int amountRead = -1;
-			do {
-				int amountRequested = Math.max(stream.available(), DEFAULT_READING_SIZE);  // read at least 8K
-
-				// resize contents if needed
-				if (contentsLength + amountRequested > contents.length) {
-					System.arraycopy(
-						contents,
-						0,
-						contents = new char[contentsLength + amountRequested],
-						0,
-						contentsLength);
-				}
-
-				// read as many chars as possible
-				amountRead = reader.read(contents, contentsLength, amountRequested);
-
-				if (amountRead > 0) {
-					// remember length of contents
-					contentsLength += amountRead;
-				}
-			} while (amountRead != -1);
-
-			// resize contents if necessary
-			if (contentsLength < contents.length) {
-				System.arraycopy(
-					contents,
-					0,
-					contents = new char[contentsLength],
-					0,
-					contentsLength);
-			}
-		} else {
-			contents = new char[length];
-			int len = 0;
-			int readSize = 0;
-			while ((readSize != -1) && (len != length)) {
-				// See PR 1FMS89U
-				// We record first the read size. In this case len is the actual read size.
-				len += readSize;
-				readSize = reader.read(contents, len, length - len);
-			}
-			// See PR 1FMS89U
-			// Now we need to resize in case the default encoding used more than one byte for each
-			// character
-			if (len != length)
-				System.arraycopy(contents, 0, (contents = new char[len]), 0, len);
-		}
-
-		return contents;
-	}
-	
-
-	/**
-	 * Helper method - returns the targeted item (IResource if internal or java.io.File if external), 
-	 * or null if unbound
-	 * Internal items must be referred to using container relative paths.
-	 */
-	public static Object getTarget(IContainer container, IPath path, boolean checkResourceExistence) {
-
-		if (path == null) return null;
-	
-		// lookup - inside the container
-		if (path.getDevice() == null) { // container relative paths should not contain a device 
-													// (see http://dev.eclipse.org/bugs/show_bug.cgi?id=18684)
-													// (case of a workspace rooted at d:\ )
-			IResource resource = container.findMember(path);
-			if (resource != null){
-				if (!checkResourceExistence ||resource.exists()) return resource;
-				return null;
-			}
-		}
-	
-		// if path is relative, it cannot be an external path
-		// (see http://dev.eclipse.org/bugs/show_bug.cgi?id=22517)
-		if (!path.isAbsolute()) return null; 
-
-		// lookup - outside the container
-		File externalFile = new File(path.toOSString());
-		if (!checkResourceExistence) {
-			return externalFile;
-		} else if (existingExternalFiles.contains(externalFile)) {
-			return externalFile;
-		} else {
-			if (externalFile.exists()) {
-				// cache external file
-				existingExternalFiles.add(externalFile);
-				return externalFile;
-			}
-		}
-		
-		return null;	
-	}
-		/**
-		 * A set of java.io.Files used as a cache of external jars that 
-		 * are known to be existing.
-		 * Note this cache is kept for the whole session.
-		 */ 
-		public static HashSet existingExternalFiles = new HashSet();
-		
-	/*
-	 * Returns whether the given resource matches one of the exclusion patterns.
-	 * 
-	 * @see IClasspathEntry#getExclusionPatterns
-	 */
-	public final static boolean isExcluded(IResource resource, char[][] exclusionPatterns) {
-		IPath path = resource.getFullPath();
-		// ensure that folders are only excluded if all of their children are excluded
-		if (resource.getType() == IResource.FOLDER)
-			path = path.append("*"); //$NON-NLS-1$
-		return isExcluded(path, exclusionPatterns);
-	}
-	
-	/*
-	 * Returns whether the given resource path matches one of the exclusion
-	 * patterns.
-	 * 
-	 * @see IClasspathEntry#getExclusionPatterns
-	 */
-	public final static boolean isExcluded(IPath resourcePath, char[][] exclusionPatterns) {
-		if (exclusionPatterns == null) return false;
-		char[] path = resourcePath.toString().toCharArray();
-		for (int i = 0, length = exclusionPatterns.length; i < length; i++)
-			if (CharOperation.pathMatch(exclusionPatterns[i], path, true, '/'))
-				return true;
-		return false;
-	}	
-		
-}
-
-
Index: index/org/eclipse/cdt/internal/core/search/messages.properties
===================================================================
RCS file: index/org/eclipse/cdt/internal/core/search/messages.properties
diff -N index/org/eclipse/cdt/internal/core/search/messages.properties
--- index/org/eclipse/cdt/internal/core/search/messages.properties	27 Jun 2003 14:31:27 -0000	1.1
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -1,16 +0,0 @@
-###############################################################################
-# Copyright (c) 2000, 2003 IBM Corporation and others.
-# All rights reserved. This program and the accompanying materials 
-# are made available under the terms of the Common Public License v1.0
-# which accompanies this distribution, and is available at
-# http://www.eclipse.org/legal/cpl-v10.html
-# 
-# Contributors:
-#     IBM Corporation - initial API and implementation
-###############################################################################
-### Eclipse CDT Core Search messages.
-
-engine.searching = Searching...
-exception.wrongFormat = Wrong format
-process.name = CDT Indexer
-manager.filesToIndex = {0} files to index
\ No newline at end of file
Index: index/org/eclipse/cdt/internal/core/search/indexing/AbstractIndexer.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/search/indexing/AbstractIndexer.java,v
retrieving revision 1.12
diff -u -r1.12 AbstractIndexer.java
--- index/org/eclipse/cdt/internal/core/search/indexing/AbstractIndexer.java	12 Aug 2003 15:20:21 -0000	1.12
+++ index/org/eclipse/cdt/internal/core/search/indexing/AbstractIndexer.java	12 Aug 2003 19:00:19 -0000
@@ -26,10 +26,10 @@
 import org.eclipse.cdt.core.parser.ast.IASTTypedefDeclaration;
 import org.eclipse.cdt.core.parser.ast.IASTVariable;
 import org.eclipse.cdt.core.search.ICSearchConstants;
+import org.eclipse.cdt.internal.core.CharOperation;
 import org.eclipse.cdt.internal.core.index.IDocument;
 import org.eclipse.cdt.internal.core.index.IIndexer;
 import org.eclipse.cdt.internal.core.index.IIndexerOutput;
-import org.eclipse.cdt.internal.core.search.CharOperation;
 
 public abstract class AbstractIndexer implements IIndexer, IIndexConstants, ICSearchConstants {
 	
Index: index/org/eclipse/cdt/internal/core/search/indexing/AddCompilationUnitToIndex.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/search/indexing/AddCompilationUnitToIndex.java,v
retrieving revision 1.3
diff -u -r1.3 AddCompilationUnitToIndex.java
--- index/org/eclipse/cdt/internal/core/search/indexing/AddCompilationUnitToIndex.java	11 Jul 2003 22:12:35 -0000	1.3
+++ index/org/eclipse/cdt/internal/core/search/indexing/AddCompilationUnitToIndex.java	12 Aug 2003 19:00:19 -0000
@@ -34,7 +34,7 @@
 			try {
 				IPath location = resource.getLocation();
 				if (location != null)
-					this.contents = org.eclipse.cdt.internal.core.search.Util.getFileCharContent(location.toFile(), null);
+					this.contents = org.eclipse.cdt.internal.core.Util.getFileCharContent(location.toFile(), null);
 			} catch (IOException e) {
 			}
 		}
Index: index/org/eclipse/cdt/internal/core/search/indexing/AddFolderToIndex.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/search/indexing/AddFolderToIndex.java,v
retrieving revision 1.3
diff -u -r1.3 AddFolderToIndex.java
--- index/org/eclipse/cdt/internal/core/search/indexing/AddFolderToIndex.java	11 Jul 2003 22:12:35 -0000	1.3
+++ index/org/eclipse/cdt/internal/core/search/indexing/AddFolderToIndex.java	12 Aug 2003 19:00:19 -0000
@@ -11,8 +11,8 @@
 
 package org.eclipse.cdt.internal.core.search.indexing;
 
+import org.eclipse.cdt.internal.core.Util;
 import org.eclipse.cdt.internal.core.index.IIndex;
-import org.eclipse.cdt.internal.core.search.Util;
 import org.eclipse.cdt.internal.core.search.processing.JobManager;
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IProject;
Index: index/org/eclipse/cdt/internal/core/search/indexing/IndexAllProject.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/search/indexing/IndexAllProject.java,v
retrieving revision 1.2
diff -u -r1.2 IndexAllProject.java
--- index/org/eclipse/cdt/internal/core/search/indexing/IndexAllProject.java	4 Jul 2003 03:02:07 -0000	1.2
+++ index/org/eclipse/cdt/internal/core/search/indexing/IndexAllProject.java	12 Aug 2003 19:00:20 -0000
@@ -24,7 +24,7 @@
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.IProgressMonitor;
 import  org.eclipse.cdt.core.model.ICProject;
-import org.eclipse.cdt.internal.core.search.Util;
+import org.eclipse.cdt.internal.core.Util;
 import org.eclipse.cdt.internal.core.index.IIndex;
 import org.eclipse.cdt.internal.core.index.IQueryResult;
 import org.eclipse.cdt.internal.core.index.impl.IFileDocument;
Index: index/org/eclipse/cdt/internal/core/search/indexing/IndexManager.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/search/indexing/IndexManager.java,v
retrieving revision 1.4
diff -u -r1.4 IndexManager.java
--- index/org/eclipse/cdt/internal/core/search/indexing/IndexManager.java	11 Aug 2003 13:42:47 -0000	1.4
+++ index/org/eclipse/cdt/internal/core/search/indexing/IndexManager.java	12 Aug 2003 19:00:20 -0000
@@ -21,6 +21,16 @@
 import java.util.Map;
 import java.util.zip.CRC32;
 
+import org.eclipse.cdt.core.CCorePlugin;
+import org.eclipse.cdt.internal.core.CharOperation;
+import org.eclipse.cdt.internal.core.index.IIndex;
+import org.eclipse.cdt.internal.core.index.impl.Index;
+import org.eclipse.cdt.internal.core.model.CProject;
+import org.eclipse.cdt.internal.core.search.CWorkspaceScope;
+import org.eclipse.cdt.internal.core.search.IndexSelector;
+import org.eclipse.cdt.internal.core.search.SimpleLookupTable;
+import org.eclipse.cdt.internal.core.search.processing.IJob;
+import org.eclipse.cdt.internal.core.search.processing.JobManager;
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.resources.IWorkspace;
@@ -28,16 +38,7 @@
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.QualifiedName;
-import org.eclipse.cdt.internal.core.search.processing.JobManager;
-import org.eclipse.cdt.internal.core.search.processing.IJob;
-import org.eclipse.cdt.internal.core.search.CWorkspaceScope;
-import org.eclipse.cdt.internal.core.search.IndexSelector;
-import org.eclipse.cdt.internal.core.search.SimpleLookupTable;
-import org.eclipse.cdt.internal.core.search.CharOperation;
-import org.eclipse.cdt.internal.core.index.IIndex;
-import org.eclipse.cdt.internal.core.index.impl.Index;
-import org.eclipse.cdt.internal.core.model.CProject;
-import org.eclipse.cdt.core.CCorePlugin;
+
 
 public class IndexManager extends JobManager implements IIndexConstants {
 	/* number of file contents in memory */
@@ -303,11 +304,11 @@
 	 * Name of the background process
 	 */
 	public String processName(){
-		return org.eclipse.cdt.internal.core.search.Util.bind("process.name"); //$NON-NLS-1$
+		return org.eclipse.cdt.internal.core.Util.bind("process.name"); //$NON-NLS-1$
 	}
 	
 	private void rebuildIndex(String indexName, IPath path) {
-		Object target = org.eclipse.cdt.internal.core.search.Util.getTarget(ResourcesPlugin.getWorkspace().getRoot(), path, true);
+		Object target = org.eclipse.cdt.internal.core.Util.getTarget(ResourcesPlugin.getWorkspace().getRoot(), path, true);
 		if (target == null) return;
 
 		if (VERBOSE)
@@ -546,7 +547,7 @@
 
 	private char[] readIndexState() {
 		try {
-			return org.eclipse.cdt.internal.core.search.Util.getFileCharContent(savedIndexNamesFile, null);
+			return org.eclipse.cdt.internal.core.Util.getFileCharContent(savedIndexNamesFile, null);
 		} catch (IOException ignored) {
 			if (VERBOSE)
 				JobManager.verbose("Failed to read saved index file names"); //$NON-NLS-1$
Index: index/org/eclipse/cdt/internal/core/search/indexing/RemoveFolderFromIndex.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/search/indexing/RemoveFolderFromIndex.java,v
retrieving revision 1.3
diff -u -r1.3 RemoveFolderFromIndex.java
--- index/org/eclipse/cdt/internal/core/search/indexing/RemoveFolderFromIndex.java	11 Jul 2003 22:12:35 -0000	1.3
+++ index/org/eclipse/cdt/internal/core/search/indexing/RemoveFolderFromIndex.java	12 Aug 2003 19:00:20 -0000
@@ -13,9 +13,9 @@
 
 import java.io.IOException;
 
+import org.eclipse.cdt.internal.core.Util;
 import org.eclipse.cdt.internal.core.index.IIndex;
 import org.eclipse.cdt.internal.core.index.IQueryResult;
-import org.eclipse.cdt.internal.core.search.Util;
 import org.eclipse.cdt.internal.core.search.processing.JobManager;
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.runtime.IPath;
Index: model/org/eclipse/cdt/core/model/ICElement.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICElement.java,v
retrieving revision 1.12
diff -u -r1.12 ICElement.java
--- model/org/eclipse/cdt/core/model/ICElement.java	13 Jun 2003 15:01:23 -0000	1.12
+++ model/org/eclipse/cdt/core/model/ICElement.java	12 Aug 2003 19:00:20 -0000
@@ -201,9 +201,13 @@
 	static final int CPP_PUBLIC = 0x2000;
 
 	/**
+	 * Modifier indicating a protected class
+	 */
+	static final int CPP_PROTECTED = 0x4000;
+	/**
 	 * Modifier indicating a friend class
 	 */
-	static final int CPP_FRIEND = 0x4000;
+	static final int CPP_FRIEND = 0x8000;
 
 	/**
 	 * Returns whether this C element exists in the model.
Index: model/org/eclipse/cdt/core/model/ITranslationUnit.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ITranslationUnit.java,v
retrieving revision 1.3
diff -u -r1.3 ITranslationUnit.java
--- model/org/eclipse/cdt/core/model/ITranslationUnit.java	27 Mar 2003 16:04:19 -0000	1.3
+++ model/org/eclipse/cdt/core/model/ITranslationUnit.java	12 Aug 2003 19:00:20 -0000
@@ -4,6 +4,8 @@
  * (c) Copyright IBM Corp. 2000, 2001.
  * All Rights Reserved.
  */
+import java.util.Map;
+
 import org.eclipse.cdt.internal.core.model.IBufferFactory;
 import org.eclipse.cdt.internal.core.model.IWorkingCopy;
 import org.eclipse.core.runtime.IProgressMonitor;
@@ -204,4 +206,9 @@
 	 * @return boolean
 	 */
 	boolean isWorkingCopy();	
+	/**
+	 * parse()
+	 * returns a map of all new elements and their element info
+	 */
+	Map parse();
 }
Index: model/org/eclipse/cdt/internal/core/model/CModelBuilder.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelBuilder.java,v
retrieving revision 1.10
diff -u -r1.10 CModelBuilder.java
--- model/org/eclipse/cdt/internal/core/model/CModelBuilder.java	30 Jul 2003 19:17:11 -0000	1.10
+++ model/org/eclipse/cdt/internal/core/model/CModelBuilder.java	12 Aug 2003 19:00:21 -0000
@@ -73,7 +73,9 @@
 	{
 		ParserMode mode = quick ? ParserMode.QUICK_PARSE : ParserMode.COMPLETE_PARSE; 
 		quickParseCallback = ParserFactory.createQuickParseCallback(); 
-		IParser parser = ParserFactory.createParser( ParserFactory.createScanner( new StringReader( code ), "code", new ScannerInfo(), mode, quickParseCallback), quickParseCallback, mode );
+		IParser parser = ParserFactory.createParser( 
+			ParserFactory.createScanner( new StringReader( code ), "code", 
+			new ScannerInfo(), mode, quickParseCallback), quickParseCallback, mode );
 		parser.setCppNature(hasCppNature);
 		if( ! parser.parse() && throwExceptionOnError )
 			throw new ParserException("Parse failure");
@@ -459,8 +461,7 @@
 		}
 		element.setTypeName ( getType(varDeclaration.getAbstractDeclaration()) );
 		element.setConst(varDeclaration.getAbstractDeclaration().isConst());
-		// TODO : fix volatile for variables
-		// element.setVolatile(varDeclaration.isVolatile());
+		element.setVolatile(varDeclaration.getAbstractDeclaration().isVolatile());
 		element.setStatic(varDeclaration.isStatic());
 		// add to parent
 		parent.addChild( element ); 	
@@ -519,6 +520,8 @@
 				}
 				
 			}
+			element.setVolatile(methodDeclaration.isVolatile());
+			element.setConst(methodDeclaration.isConst());				
 		}
 		else // instance of IASTFunction 
 		{
@@ -547,10 +550,7 @@
 		}						
 		element.setParameterTypes(parameterTypes);
 		element.setReturnType( getType(functionDeclaration.getReturnType()) );
-		// TODO: Fix volatile and const
-		//element.setVolatile(functionDeclaration.isVolatile());
 		element.setStatic(functionDeclaration.isStatic());
-		//element.setConst(functionDeclaration.isConst());				
 
 		// add to parent
 		parent.addChild( element ); 	
Index: model/org/eclipse/cdt/internal/core/model/CModelStatus.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelStatus.java,v
retrieving revision 1.2
diff -u -r1.2 CModelStatus.java
--- model/org/eclipse/cdt/internal/core/model/CModelStatus.java	15 Oct 2002 17:47:49 -0000	1.2
+++ model/org/eclipse/cdt/internal/core/model/CModelStatus.java	12 Aug 2003 19:00:21 -0000
@@ -44,7 +44,7 @@
 	/**
 	 * Singleton OK object
 	 */
-	public static final ICModelStatus VERIFIED_OK = new CModelStatus(OK);
+	public static final ICModelStatus VERIFIED_OK = new CModelStatus(OK, OK, org.eclipse.cdt.internal.core.Util.bind("status.OK"));;
 
 	/**
 	 * Constructs an C model status with no corresponding elements.
@@ -59,7 +59,7 @@
 	 */
 	public CModelStatus(int code) {
 		super(ERROR, CCorePlugin.PLUGIN_ID, code, "CModelStatus", null); //$NON-NLS-1$
-		//fElements= CElementInfo.fgEmptyChildren;
+		fElements= CElementInfo.fgEmptyChildren;
 	}
 
 	/**
@@ -76,18 +76,22 @@
 	 * Constructs an C model status with no corresponding elements.
 	 */
 	public CModelStatus(int code, String string) {
-		super(ERROR, CCorePlugin.PLUGIN_ID, code, "CModelStatus", null); //$NON-NLS-1$
-		//fElements= CElementInfo.fgEmptyChildren;
+		this(ERROR, code, string);
+	}
+
+	public CModelStatus(int severity, int code, String string) {
+		super(severity, CCorePlugin.PLUGIN_ID, code, "CModelStatus", null); //$NON-NLS-1$
+		fElements= CElementInfo.fgEmptyChildren;
 		fPath= null;
 		fString = string;
-	}
+	}	
 
 	/**
 	 * Constructs an C model status with no corresponding elements.
 	 */
 	public CModelStatus(int code, Throwable throwable) {
 		super(ERROR, CCorePlugin.PLUGIN_ID, code, "CModelStatus", throwable); //$NON-NLS-1$
-		//fElements= CElementInfo.fgEmptyChildren;
+		fElements= CElementInfo.fgEmptyChildren;
 	}
 
 	/**
@@ -95,7 +99,7 @@
 	 */
 	public CModelStatus(int code, IPath path) {
 		super(ERROR, CCorePlugin.PLUGIN_ID, code, "CModelStatus", null); //$NON-NLS-1$
-		//fElements= CElementInfo.fgEmptyChildren;
+		fElements= CElementInfo.fgEmptyChildren;
 		fPath= path;
 	}
 
@@ -115,6 +119,11 @@
 		this(code, new ICElement[]{element});
 		fString= string;
 	}
+
+	public CModelStatus(int code, ICElement element, IPath path) {
+		this(code, new ICElement[]{element});
+		fPath = path;
+	}	
 
 	/**
 	 * Constructs an C model status with no corresponding elements.
Index: model/org/eclipse/cdt/internal/core/model/TranslationUnit.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/TranslationUnit.java,v
retrieving revision 1.9
diff -u -r1.9 TranslationUnit.java
--- model/org/eclipse/cdt/internal/core/model/TranslationUnit.java	7 Jul 2003 15:35:46 -0000	1.9
+++ model/org/eclipse/cdt/internal/core/model/TranslationUnit.java	12 Aug 2003 19:00:21 -0000
@@ -321,7 +321,7 @@
 		TranslationUnitInfo unitInfo = (TranslationUnitInfo) info;
 		
 		// generate structure
-		Map mapping = this.parse(false); // false since this is for working copies
+		Map mapping = this.parse(); 
 		
 		// this is temporary until the New Model Builder is implemented
 		if(mapping == null) {
@@ -481,7 +481,7 @@
 	/**
 	 * Parse the buffer contents of this element.
 	 */
-	public Map parse(boolean requireLineNumbers){
+	public Map parse(){
 		try{
 			String buf =this.getBuffer().getContents();
 			if (buf != null) {
Index: search/org/eclipse/cdt/core/search/BasicSearchMatch.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/search/org/eclipse/cdt/core/search/BasicSearchMatch.java,v
retrieving revision 1.3
diff -u -r1.3 BasicSearchMatch.java
--- search/org/eclipse/cdt/core/search/BasicSearchMatch.java	1 Aug 2003 19:26:50 -0000	1.3
+++ search/org/eclipse/cdt/core/search/BasicSearchMatch.java	12 Aug 2003 19:00:22 -0000
@@ -139,4 +139,74 @@
 	public boolean isVolatile() {
 		return isVolatile;
 	}
+	/**
+	 * @return
+	 */
+	public int getType() {
+		return type;
+	}
+
+	/**
+	 * @param i
+	 */
+	public void setEndOffset(int i) {
+		endOffset = i;
+	}
+
+	/**
+	 * @param b
+	 */
+	public void setConst(boolean b) {
+		isConst = b;
+	}
+
+	/**
+	 * @param b
+	 */
+	public void setStatic(boolean b) {
+		isStatic = b;
+	}
+
+	/**
+	 * @param b
+	 */
+	public void setVolatile(boolean b) {
+		isVolatile = b;
+	}
+
+	/**
+	 * @param string
+	 */
+	public void setName(String string) {
+		name = string;
+	}
+
+	/**
+	 * @param string
+	 */
+	public void setParentName(String string) {
+		parentName = string;
+	}
+
+	/**
+	 * @param i
+	 */
+	public void setStartOffset(int i) {
+		startOffset = i;
+	}
+
+	/**
+	 * @param i
+	 */
+	public void setType(int i) {
+		type = i;
+	}
+
+	/**
+	 * @param i
+	 */
+	public void setVisibility(int i) {
+		visibility = i;
+	}
+
 }
Index: search/org/eclipse/cdt/core/search/BasicSearchResultCollector.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/search/org/eclipse/cdt/core/search/BasicSearchResultCollector.java,v
retrieving revision 1.3
diff -u -r1.3 BasicSearchResultCollector.java
--- search/org/eclipse/cdt/core/search/BasicSearchResultCollector.java	11 Aug 2003 13:48:35 -0000	1.3
+++ search/org/eclipse/cdt/core/search/BasicSearchResultCollector.java	12 Aug 2003 19:00:22 -0000
@@ -28,6 +28,7 @@
 import org.eclipse.cdt.core.parser.ast.IASTEnumerator;
 import org.eclipse.cdt.core.parser.ast.IASTField;
 import org.eclipse.cdt.core.parser.ast.IASTFunction;
+import org.eclipse.cdt.core.parser.ast.IASTMacro;
 import org.eclipse.cdt.core.parser.ast.IASTMethod;
 import org.eclipse.cdt.core.parser.ast.IASTNamespaceDefinition;
 import org.eclipse.cdt.core.parser.ast.IASTOffsetableElement;
@@ -200,6 +201,8 @@
 			match.type = ICElement.C_NAMESPACE;
 		} else if ( node instanceof IASTEnumerationSpecifier ){
 			match.type = ICElement.C_ENUMERATION;
+		} else if ( node instanceof IASTMacro ){
+			match.type = ICElement.C_MACRO;
 		} else if ( node instanceof IASTField ){
 			match.type = ICElement.C_FIELD;
 			IASTField  field = (IASTField)node;
Index: search/org/eclipse/cdt/core/search/SearchEngine.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/search/org/eclipse/cdt/core/search/SearchEngine.java,v
retrieving revision 1.5
diff -u -r1.5 SearchEngine.java
--- search/org/eclipse/cdt/core/search/SearchEngine.java	11 Aug 2003 13:42:47 -0000	1.5
+++ search/org/eclipse/cdt/core/search/SearchEngine.java	12 Aug 2003 19:00:22 -0000
@@ -17,13 +17,13 @@
 
 import org.eclipse.cdt.core.model.ICElement;
 import org.eclipse.cdt.core.model.ICProject;
+import org.eclipse.cdt.internal.core.Util;
 import org.eclipse.cdt.internal.core.model.CModelManager;
 import org.eclipse.cdt.internal.core.model.IWorkingCopy;
 import org.eclipse.cdt.internal.core.search.CSearchScope;
 import org.eclipse.cdt.internal.core.search.CWorkspaceScope;
 import org.eclipse.cdt.internal.core.search.PathCollector;
 import org.eclipse.cdt.internal.core.search.PatternSearchJob;
-import org.eclipse.cdt.internal.core.search.Util;
 import org.eclipse.cdt.internal.core.search.indexing.IndexManager;
 import org.eclipse.cdt.internal.core.search.matching.CSearchPattern;
 import org.eclipse.cdt.internal.core.search.matching.MatchLocator;
Index: search/org/eclipse/cdt/internal/core/search/matching/CSearchPattern.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/search/org/eclipse/cdt/internal/core/search/matching/CSearchPattern.java,v
retrieving revision 1.15
diff -u -r1.15 CSearchPattern.java
--- search/org/eclipse/cdt/internal/core/search/matching/CSearchPattern.java	12 Aug 2003 15:20:21 -0000	1.15
+++ search/org/eclipse/cdt/internal/core/search/matching/CSearchPattern.java	12 Aug 2003 19:00:22 -0000
@@ -27,12 +27,12 @@
 import org.eclipse.cdt.core.search.ICSearchConstants;
 import org.eclipse.cdt.core.search.ICSearchPattern;
 import org.eclipse.cdt.core.search.ICSearchScope;
+import org.eclipse.cdt.internal.core.CharOperation;
 import org.eclipse.cdt.internal.core.index.IEntryResult;
 import org.eclipse.cdt.internal.core.index.IIndex;
 import org.eclipse.cdt.internal.core.index.impl.BlocksIndexInput;
 import org.eclipse.cdt.internal.core.index.impl.IndexInput;
 import org.eclipse.cdt.internal.core.parser.ScannerInfo;
-import org.eclipse.cdt.internal.core.search.CharOperation;
 import org.eclipse.cdt.internal.core.search.IIndexSearchRequestor;
 import org.eclipse.cdt.internal.core.search.indexing.IIndexConstants;
 import org.eclipse.core.runtime.IProgressMonitor;
Index: search/org/eclipse/cdt/internal/core/search/matching/ClassDeclarationPattern.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/search/org/eclipse/cdt/internal/core/search/matching/ClassDeclarationPattern.java,v
retrieving revision 1.10
diff -u -r1.10 ClassDeclarationPattern.java
--- search/org/eclipse/cdt/internal/core/search/matching/ClassDeclarationPattern.java	7 Aug 2003 14:52:18 -0000	1.10
+++ search/org/eclipse/cdt/internal/core/search/matching/ClassDeclarationPattern.java	12 Aug 2003 19:00:22 -0000
@@ -22,10 +22,10 @@
 import org.eclipse.cdt.core.parser.ast.IASTOffsetableNamedElement;
 import org.eclipse.cdt.core.parser.ast.IASTQualifiedNameElement;
 import org.eclipse.cdt.core.search.ICSearchScope;
+import org.eclipse.cdt.internal.core.CharOperation;
 import org.eclipse.cdt.internal.core.index.IEntryResult;
 import org.eclipse.cdt.internal.core.index.impl.IndexInput;
 import org.eclipse.cdt.internal.core.index.impl.IndexedFile;
-import org.eclipse.cdt.internal.core.search.CharOperation;
 import org.eclipse.cdt.internal.core.search.IIndexSearchRequestor;
 import org.eclipse.cdt.internal.core.search.indexing.AbstractIndexer;
 
Index: search/org/eclipse/cdt/internal/core/search/matching/FieldDeclarationPattern.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/search/org/eclipse/cdt/internal/core/search/matching/FieldDeclarationPattern.java,v
retrieving revision 1.7
diff -u -r1.7 FieldDeclarationPattern.java
--- search/org/eclipse/cdt/internal/core/search/matching/FieldDeclarationPattern.java	12 Aug 2003 15:20:21 -0000	1.7
+++ search/org/eclipse/cdt/internal/core/search/matching/FieldDeclarationPattern.java	12 Aug 2003 19:00:22 -0000
@@ -21,10 +21,10 @@
 import org.eclipse.cdt.core.parser.ast.IASTQualifiedNameElement;
 import org.eclipse.cdt.core.parser.ast.IASTVariable;
 import org.eclipse.cdt.core.search.ICSearchScope;
+import org.eclipse.cdt.internal.core.CharOperation;
 import org.eclipse.cdt.internal.core.index.IEntryResult;
 import org.eclipse.cdt.internal.core.index.impl.IndexInput;
 import org.eclipse.cdt.internal.core.index.impl.IndexedFile;
-import org.eclipse.cdt.internal.core.search.CharOperation;
 import org.eclipse.cdt.internal.core.search.IIndexSearchRequestor;
 import org.eclipse.cdt.internal.core.search.indexing.AbstractIndexer;
 
Index: search/org/eclipse/cdt/internal/core/search/matching/MacroDeclarationPattern.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/search/org/eclipse/cdt/internal/core/search/matching/MacroDeclarationPattern.java,v
retrieving revision 1.1
diff -u -r1.1 MacroDeclarationPattern.java
--- search/org/eclipse/cdt/internal/core/search/matching/MacroDeclarationPattern.java	12 Aug 2003 14:29:07 -0000	1.1
+++ search/org/eclipse/cdt/internal/core/search/matching/MacroDeclarationPattern.java	12 Aug 2003 19:00:23 -0000
@@ -19,10 +19,10 @@
 import org.eclipse.cdt.core.parser.ast.IASTMacro;
 import org.eclipse.cdt.core.parser.ast.IASTOffsetableNamedElement;
 import org.eclipse.cdt.core.search.ICSearchScope;
+import org.eclipse.cdt.internal.core.CharOperation;
 import org.eclipse.cdt.internal.core.index.IEntryResult;
 import org.eclipse.cdt.internal.core.index.impl.IndexInput;
 import org.eclipse.cdt.internal.core.index.impl.IndexedFile;
-import org.eclipse.cdt.internal.core.search.CharOperation;
 import org.eclipse.cdt.internal.core.search.IIndexSearchRequestor;
 import org.eclipse.cdt.internal.core.search.indexing.AbstractIndexer;
 
Index: search/org/eclipse/cdt/internal/core/search/matching/MethodDeclarationPattern.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/search/org/eclipse/cdt/internal/core/search/matching/MethodDeclarationPattern.java,v
retrieving revision 1.7
diff -u -r1.7 MethodDeclarationPattern.java
--- search/org/eclipse/cdt/internal/core/search/matching/MethodDeclarationPattern.java	12 Aug 2003 14:29:07 -0000	1.7
+++ search/org/eclipse/cdt/internal/core/search/matching/MethodDeclarationPattern.java	12 Aug 2003 19:00:23 -0000
@@ -25,10 +25,10 @@
 import org.eclipse.cdt.core.parser.ast.IASTSimpleTypeSpecifier;
 import org.eclipse.cdt.core.parser.ast.IASTTypeSpecifier;
 import org.eclipse.cdt.core.search.ICSearchScope;
+import org.eclipse.cdt.internal.core.CharOperation;
 import org.eclipse.cdt.internal.core.index.IEntryResult;
 import org.eclipse.cdt.internal.core.index.impl.IndexInput;
 import org.eclipse.cdt.internal.core.index.impl.IndexedFile;
-import org.eclipse.cdt.internal.core.search.CharOperation;
 import org.eclipse.cdt.internal.core.search.IIndexSearchRequestor;
 import org.eclipse.cdt.internal.core.search.indexing.AbstractIndexer;
 
Index: search/org/eclipse/cdt/internal/core/search/matching/NamespaceDeclarationPattern.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/search/org/eclipse/cdt/internal/core/search/matching/NamespaceDeclarationPattern.java,v
retrieving revision 1.6
diff -u -r1.6 NamespaceDeclarationPattern.java
--- search/org/eclipse/cdt/internal/core/search/matching/NamespaceDeclarationPattern.java	7 Aug 2003 14:52:18 -0000	1.6
+++ search/org/eclipse/cdt/internal/core/search/matching/NamespaceDeclarationPattern.java	12 Aug 2003 19:00:23 -0000
@@ -18,10 +18,10 @@
 import org.eclipse.cdt.core.parser.ISourceElementCallbackDelegate;
 import org.eclipse.cdt.core.parser.ast.IASTNamespaceDefinition;
 import org.eclipse.cdt.core.search.ICSearchScope;
+import org.eclipse.cdt.internal.core.CharOperation;
 import org.eclipse.cdt.internal.core.index.IEntryResult;
 import org.eclipse.cdt.internal.core.index.impl.IndexInput;
 import org.eclipse.cdt.internal.core.index.impl.IndexedFile;
-import org.eclipse.cdt.internal.core.search.CharOperation;
 import org.eclipse.cdt.internal.core.search.IIndexSearchRequestor;
 import org.eclipse.cdt.internal.core.search.indexing.AbstractIndexer;
 
Index: search/org/eclipse/cdt/internal/core/search/processing/JobManager.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/search/org/eclipse/cdt/internal/core/search/processing/JobManager.java,v
retrieving revision 1.3
diff -u -r1.3 JobManager.java
--- search/org/eclipse/cdt/internal/core/search/processing/JobManager.java	11 Jul 2003 22:12:35 -0000	1.3
+++ search/org/eclipse/cdt/internal/core/search/processing/JobManager.java	12 Aug 2003 19:00:23 -0000
@@ -13,7 +13,7 @@
  */
 package org.eclipse.cdt.internal.core.search.processing;
 
-import org.eclipse.cdt.internal.core.search.Util;
+import org.eclipse.cdt.internal.core.Util;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.OperationCanceledException;
 import org.eclipse.core.runtime.SubProgressMonitor;
Index: src/org/eclipse/cdt/core/CConventions.java
===================================================================
RCS file: src/org/eclipse/cdt/core/CConventions.java
diff -N src/org/eclipse/cdt/core/CConventions.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/cdt/core/CConventions.java	12 Aug 2003 19:00:23 -0000
@@ -0,0 +1,137 @@
+/*******************************************************************************
+ * Copyright (c) 2001 Rational Software Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     Rational Software - initial implementation
+ ******************************************************************************/
+package org.eclipse.cdt.core;
+
+import java.util.StringTokenizer;
+
+import org.eclipse.cdt.internal.core.CharOperation;
+import org.eclipse.cdt.internal.core.Util;
+import org.eclipse.cdt.internal.core.model.CModelStatus;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+/**
+ * @author hamer
+ *
+ * To change the template for this generated type comment go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+ */
+
+public class CConventions {
+	private final static String scopeResolutionOperator= "::";
+	private final static char fgDot= '.';
+	private final static char fgColon= ':';
+	
+	/**
+	 * Validate the given CPP class name, either simple or qualified.
+	 * For example, <code>"A::B::C"</code>, or <code>"C"</code>.
+	 * <p>
+	 *
+	 * @param name the name of a class
+	 * @return a status object with code <code>IStatus.OK</code> if
+	 *		the given name is valid as a CPP class name, 
+	 *      a status with code <code>IStatus.WARNING</code>
+	 *		indicating why the given name is discouraged, 
+	 *      otherwise a status object indicating what is wrong with 
+	 *      the name
+	 */
+	public static IStatus validateClassName(String name) {
+		if (name == null) {
+			return new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, -1, Util.bind("convention.class.nullName"), null); //$NON-NLS-1$
+		}
+		String trimmed = name.trim();
+		if ((!name.equals(trimmed)) || (name.indexOf(" ") != -1) ){
+			return new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, -1, Util.bind("convention.class.nameWithBlanks"), null); //$NON-NLS-1$
+		}
+		int index = name.lastIndexOf(scopeResolutionOperator);
+		char[] scannedID;
+		if (index == -1) {
+			// simple name
+			scannedID = name.toCharArray();
+		} else {
+			// qualified name
+			String pkg = name.substring(0, index).trim();
+			IStatus status = validateScopeName(pkg);
+			if (!status.isOK()) {
+				return status;
+			}
+			String type = name.substring(index + 1).trim();
+			scannedID = type.toCharArray();
+		}
+	
+		if (scannedID != null) {
+			IStatus status = ResourcesPlugin.getWorkspace().validateName(new String(scannedID), IResource.FILE);
+			if (!status.isOK()) {
+				return status;
+			}
+			if (CharOperation.contains('$', scannedID)) {
+				return new Status(IStatus.WARNING, CCorePlugin.PLUGIN_ID, -1, Util.bind("convention.class.dollarName"), null); //$NON-NLS-1$
+			}
+			if ((scannedID.length > 0 && Character.isLowerCase(scannedID[0]))) {
+				return new Status(IStatus.WARNING, CCorePlugin.PLUGIN_ID, -1, Util.bind("convention.class.lowercaseName"), null); //$NON-NLS-1$
+			}
+			return CModelStatus.VERIFIED_OK;
+		} else {
+			return new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, -1, Util.bind("convention.class.invalidName", name), null); //$NON-NLS-1$
+		}
+	}
+	/**
+	 * Validate the given scope name.
+	 * <p>
+	 * @return a status object with code <code>IStatus.OK</code> if
+	 *		the given name is valid as a class name, otherwise a status 
+	 *		object indicating what is wrong with the name
+	 */
+	public static IStatus validateScopeName(String name) {
+	
+		if (name == null) {
+			return new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, -1, Util.bind("convention.scope.nullName"), null); //$NON-NLS-1$
+		}
+		int length;
+		if ((length = name.length()) == 0) {
+			return new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, -1, Util.bind("convention.scope.emptyName"), null); //$NON-NLS-1$
+		}
+		if (name.charAt(0) == fgDot || name.charAt(length-1) == fgDot) {
+			return new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, -1, Util.bind("convention.scope.dotName"), null); //$NON-NLS-1$
+		}
+		if (CharOperation.isWhitespace(name.charAt(0)) || CharOperation.isWhitespace(name.charAt(name.length() - 1))) {
+			return new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, -1, Util.bind("convention.scope.nameWithBlanks"), null); //$NON-NLS-1$
+		}
+//		int dot = 0;
+//		while (dot != -1 && dot < length-1) {
+//			if ((dot = name.indexOf(fgDot, dot+1)) != -1 && dot < length-1 && name.charAt(dot+1) == fgDot) {
+//				return new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, -1, Util.bind("convention.package.consecutiveDotsName"), null); //$NON-NLS-1$
+//				}
+//		}
+		IWorkspace workspace = ResourcesPlugin.getWorkspace();
+		StringTokenizer st = new StringTokenizer(name, scopeResolutionOperator);
+		boolean firstToken = true;
+		while (st.hasMoreTokens()) {
+			String typeName = st.nextToken();
+			typeName = typeName.trim(); // grammar allows spaces
+			char[] scannedID = typeName.toCharArray(); 
+			if (scannedID == null) {
+				return new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, -1, Util.bind("convention.illegalIdentifier", typeName), null); //$NON-NLS-1$
+			}
+			IStatus status = workspace.validateName(new String(scannedID), IResource.FOLDER);
+			if (!status.isOK()) {
+				return status;
+			}
+			if (firstToken && scannedID.length > 0 && Character.isLowerCase(scannedID[0])) {
+				return new Status(IStatus.WARNING, CCorePlugin.PLUGIN_ID, -1, Util.bind("convention.scope.lowercaseName"), null); //$NON-NLS-1$
+			}
+			firstToken = false;
+		}
+		return CModelStatus.VERIFIED_OK;
+	}
+}
Index: ChangeLog
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core.tests/ChangeLog,v
retrieving revision 1.54
diff -u -r1.54 ChangeLog
--- ChangeLog	12 Aug 2003 15:20:13 -0000	1.54
+++ ChangeLog	12 Aug 2003 19:01:39 -0000
@@ -1,3 +1,7 @@
+2003-08-12
+	Added CompletionProposalsTest to the suit to test the generation 
+	of completion proposals.
+
 2003-08-12 Bogdan Gheorghe
 	- Changed testVariableIndexPrefix, testVariableDeclaration to
 	  reflect changes to the var search pattern
Index: failures/org/eclipse/cdt/core/model/failedTests/CModelElementsFailedTests.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core.tests/failures/org/eclipse/cdt/core/model/failedTests/CModelElementsFailedTests.java,v
retrieving revision 1.3
diff -u -r1.3 CModelElementsFailedTests.java
--- failures/org/eclipse/cdt/core/model/failedTests/CModelElementsFailedTests.java	25 Jul 2003 18:09:57 -0000	1.3
+++ failures/org/eclipse/cdt/core/model/failedTests/CModelElementsFailedTests.java	12 Aug 2003 19:01:39 -0000
@@ -97,7 +97,7 @@
 	public void testBug36379() {
 		TranslationUnit tu = new TranslationUnit(fCProject, headerFile);
 		// parse the translation unit to get the elements tree		
-		Map newElement = tu.parse(true); // require line numbers
+		Map newElement = tu.parse(); // require line numbers
 		
 		// tu ---> namespace: MyPackage
 		ArrayList tuPackages = tu.getChildrenOfType(ICElement.C_NAMESPACE);		
Index: model/org/eclipse/cdt/core/model/tests/CModelElementsTests.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core.tests/model/org/eclipse/cdt/core/model/tests/CModelElementsTests.java,v
retrieving revision 1.6
diff -u -r1.6 CModelElementsTests.java
--- model/org/eclipse/cdt/core/model/tests/CModelElementsTests.java	12 Aug 2003 18:19:54 -0000	1.6
+++ model/org/eclipse/cdt/core/model/tests/CModelElementsTests.java	12 Aug 2003 19:01:39 -0000
@@ -105,7 +105,7 @@
 	public void testCModelElements(){
 		TranslationUnit tu = new TranslationUnit(fCProject, headerFile);
 		// parse the translation unit to get the elements tree		
-		Map newElement = tu.parse(true); // require line numbers
+		Map newElement = tu.parse(); 
 		
 		// tu ---> include
 		checkInclude(tu);
Index: model/org/eclipse/cdt/core/model/tests/IntegratedCModelTest.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core.tests/model/org/eclipse/cdt/core/model/tests/IntegratedCModelTest.java,v
retrieving revision 1.1
diff -u -r1.1 IntegratedCModelTest.java
--- model/org/eclipse/cdt/core/model/tests/IntegratedCModelTest.java	18 Jun 2003 21:29:47 -0000	1.1
+++ model/org/eclipse/cdt/core/model/tests/IntegratedCModelTest.java	12 Aug 2003 19:01:39 -0000
@@ -98,7 +98,7 @@
 	protected ITranslationUnit getTU() {
 		TranslationUnit tu = new TranslationUnit(fCProject, sourceFile);
 		// parse the translation unit to get the elements tree		
-		Map newElement = tu.parse(false); // FALSE=require line numbers
+		Map newElement = tu.parse(); 
 		return tu;
 	}
 }
Index: parser/org/eclipse/cdt/core/parser/tests/ParserTestSuite.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ParserTestSuite.java,v
retrieving revision 1.8
diff -u -r1.8 ParserTestSuite.java
--- parser/org/eclipse/cdt/core/parser/tests/ParserTestSuite.java	12 Aug 2003 18:19:54 -0000	1.8
+++ parser/org/eclipse/cdt/core/parser/tests/ParserTestSuite.java	12 Aug 2003 19:01:39 -0000
@@ -14,6 +14,7 @@
 import junit.framework.TestCase;
 import junit.framework.TestSuite;
 
+import org.eclipse.cdt.core.codeassist.CompletionProposalsTest;
 import org.eclipse.cdt.core.model.tests.CModelElementsTests;
 
 /**
@@ -36,6 +37,7 @@
 		suite.addTestSuite( PreprocessorConditionalTest.class );
 		suite.addTestSuite( QuickParseASTQualifiedNameTest.class);
 		suite.addTestSuite( CompleteParseASTTest.class );
+		suite.addTestSuite(CompletionProposalsTest.class);		
 		return suite;
 	}
 
Index: resources/cfiles/CompletionProposalsTestStart.h
===================================================================
RCS file: resources/cfiles/CompletionProposalsTestStart.h
diff -N resources/cfiles/CompletionProposalsTestStart.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ resources/cfiles/CompletionProposalsTestStart.h	12 Aug 2003 19:01:39 -0000
@@ -0,0 +1,32 @@
+#define aMacro(x) x+1
+
+int aVariable = 0;
+void aFunction(char P1, int P2){
+	int f1 = 0;
+}
+
+enum anEnumeration {
+	first,
+	second, 
+	third 
+};
+
+struct aStruct{
+	int aStructField = 0;
+};
+
+class aClass {
+public:
+	int aField;
+	int aMethod(int P1, char P2){
+		return P1 + P2;
+	}
+};
+
+class anotherClass {
+public:
+	int anotherField = 0;
+	void anotherMethod(int P1, char P2){
+		a
+	}
+};
\ No newline at end of file
Index: search/org/eclipse/cdt/core/search/tests/ClassDeclarationPatternTests.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core.tests/search/org/eclipse/cdt/core/search/tests/ClassDeclarationPatternTests.java,v
retrieving revision 1.11
diff -u -r1.11 ClassDeclarationPatternTests.java
--- search/org/eclipse/cdt/core/search/tests/ClassDeclarationPatternTests.java	12 Aug 2003 18:19:50 -0000	1.11
+++ search/org/eclipse/cdt/core/search/tests/ClassDeclarationPatternTests.java	12 Aug 2003 19:01:39 -0000
@@ -20,7 +20,7 @@
 import org.eclipse.cdt.core.search.ICSearchPattern;
 import org.eclipse.cdt.core.search.IMatch;
 import org.eclipse.cdt.core.search.SearchEngine;
-import org.eclipse.cdt.internal.core.search.CharOperation;
+import org.eclipse.cdt.internal.core.CharOperation;
 import org.eclipse.cdt.internal.core.search.matching.ClassDeclarationPattern;
 import org.eclipse.cdt.internal.core.search.matching.MatchLocator;
 import org.eclipse.cdt.internal.core.search.matching.OrPattern;
Index: search/org/eclipse/cdt/core/search/tests/FunctionMethodPatternTests.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core.tests/search/org/eclipse/cdt/core/search/tests/FunctionMethodPatternTests.java,v
retrieving revision 1.5
diff -u -r1.5 FunctionMethodPatternTests.java
--- search/org/eclipse/cdt/core/search/tests/FunctionMethodPatternTests.java	12 Aug 2003 14:28:07 -0000	1.5
+++ search/org/eclipse/cdt/core/search/tests/FunctionMethodPatternTests.java	12 Aug 2003 19:01:40 -0000
@@ -17,7 +17,7 @@
 
 import org.eclipse.cdt.core.search.ICSearchPattern;
 import org.eclipse.cdt.core.search.SearchEngine;
-import org.eclipse.cdt.internal.core.search.CharOperation;
+import org.eclipse.cdt.internal.core.CharOperation;
 import org.eclipse.cdt.internal.core.search.matching.MethodDeclarationPattern;
 
 /**
Index: search/org/eclipse/cdt/core/search/tests/OtherPatternTests.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core.tests/search/org/eclipse/cdt/core/search/tests/OtherPatternTests.java,v
retrieving revision 1.7
diff -u -r1.7 OtherPatternTests.java
--- search/org/eclipse/cdt/core/search/tests/OtherPatternTests.java	12 Aug 2003 15:20:13 -0000	1.7
+++ search/org/eclipse/cdt/core/search/tests/OtherPatternTests.java	12 Aug 2003 19:01:40 -0000
@@ -18,7 +18,7 @@
 import org.eclipse.cdt.core.search.ICSearchPattern;
 import org.eclipse.cdt.core.search.IMatch;
 import org.eclipse.cdt.core.search.SearchEngine;
-import org.eclipse.cdt.internal.core.search.CharOperation;
+import org.eclipse.cdt.internal.core.CharOperation;
 import org.eclipse.cdt.internal.core.search.matching.FieldDeclarationPattern;
 import org.eclipse.cdt.internal.core.search.matching.NamespaceDeclarationPattern;
 import org.eclipse.cdt.internal.core.search.matching.OrPattern;
Index: ChangeLog
===================================================================
RCS file: /home/tools/org.eclipse.cdt.ui/ChangeLog,v
retrieving revision 1.137
diff -u -r1.137 ChangeLog
--- ChangeLog	12 Aug 2003 14:31:55 -0000	1.137
+++ ChangeLog	12 Aug 2003 19:02:05 -0000
@@ -1,3 +1,7 @@
+2003-08-12
+	Added class name validation to NewClassWizardPage
+	Used the new search (indexer) for Code completion in CCompletionProcessor
+
 2003-08-11 Andrew Niefer
 	- Added some code to CUIPlugin to access working copies 
 	
Index: src/org/eclipse/cdt/internal/ui/text/CCompletionProcessor.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CCompletionProcessor.java,v
retrieving revision 1.8
diff -u -r1.8 CCompletionProcessor.java
--- src/org/eclipse/cdt/internal/ui/text/CCompletionProcessor.java	24 Jun 2003 14:22:14 -0000	1.8
+++ src/org/eclipse/cdt/internal/ui/text/CCompletionProcessor.java	12 Aug 2003 19:02:07 -0000
@@ -7,24 +7,42 @@
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
 
-import org.eclipse.cdt.core.index.ITagEntry;
-import org.eclipse.cdt.core.index.IndexModel;
 import org.eclipse.cdt.core.index.TagFlags;
 import org.eclipse.cdt.core.model.CoreModel;
+import org.eclipse.cdt.core.model.ICElement;
+import org.eclipse.cdt.core.model.IField;
+import org.eclipse.cdt.core.model.IFunction;
+import org.eclipse.cdt.core.model.IFunctionDeclaration;
+import org.eclipse.cdt.core.model.IMember;
+import org.eclipse.cdt.core.model.IMethod;
+import org.eclipse.cdt.core.model.IMethodDeclaration;
+import org.eclipse.cdt.core.model.IStructure;
+import org.eclipse.cdt.core.model.ITranslationUnit;
+import org.eclipse.cdt.core.parser.ast.ASTAccessVisibility;
+import org.eclipse.cdt.core.search.BasicSearchMatch;
+import org.eclipse.cdt.core.search.BasicSearchResultCollector;
+import org.eclipse.cdt.core.search.ICSearchConstants;
+import org.eclipse.cdt.core.search.ICSearchScope;
+import org.eclipse.cdt.core.search.SearchEngine;
+import org.eclipse.cdt.internal.core.model.CElement;
+import org.eclipse.cdt.internal.core.search.matching.OrPattern;
 import org.eclipse.cdt.internal.corext.template.ContextType;
 import org.eclipse.cdt.internal.corext.template.ContextTypeRegistry;
 import org.eclipse.cdt.internal.ui.CCompletionContributorManager;
 import org.eclipse.cdt.internal.ui.CPluginImages;
 import org.eclipse.cdt.internal.ui.editor.CEditor;
 import org.eclipse.cdt.internal.ui.text.template.TemplateEngine;
-import org.eclipse.cdt.ui.CElementLabelProvider;
+import org.eclipse.cdt.ui.CSearchResultLabelProvider;
 import org.eclipse.cdt.ui.CUIPlugin;
 import org.eclipse.cdt.ui.FunctionPrototypeSummary;
 import org.eclipse.cdt.ui.IFunctionSummary;
+import org.eclipse.cdt.ui.IWorkingCopyManager;
 import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.runtime.CoreException;
 import org.eclipse.jface.text.BadLocationException;
 import org.eclipse.jface.text.IDocument;
 import org.eclipse.jface.text.IRegion;
@@ -36,9 +54,7 @@
 import org.eclipse.jface.text.contentassist.IContextInformationValidator;
 import org.eclipse.swt.graphics.Image;
 import org.eclipse.swt.graphics.Point;
-import org.eclipse.ui.IEditorInput;
 import org.eclipse.ui.IEditorPart;
-import org.eclipse.ui.IFileEditorInput;
 
 /**
  * C completion processor.
@@ -55,11 +71,17 @@
 	private boolean fRestrictToMatchingCase;
 	private boolean fAllowAddIncludes;
 
-	private CElementLabelProvider fElementLabelProvider;
-	//private ImageRegistry fImageRegistry;
-
+	BasicSearchResultCollector  resultCollector = null;
+	SearchEngine searchEngine = null;
+	CSearchResultLabelProvider labelProvider = null;
+	
 	public CCompletionProcessor(IEditorPart editor) {
 		fEditor = (CEditor) editor;
+	
+		// Needed for search
+		labelProvider = new CSearchResultLabelProvider();
+		resultCollector = new BasicSearchResultCollector ();
+		searchEngine = new SearchEngine();
 		
 		//Determine if this is a C or a C++ file for the context completion       +        //This is _totally_ ugly and likely belongs in the main editor class.
 		String contextNames[] = new String[2];
@@ -102,9 +124,6 @@
 		fAllowAddIncludes = true;
 
 		fComparator = new CCompletionProposalComparator();
-
-		fElementLabelProvider = new CElementLabelProvider();
-		//fImageRegistry= CUIPlugin.getDefault().getImageRegistry();
 	}
 
 	/**
@@ -188,7 +207,9 @@
 	 * @see IContentAssistProcessor#computeCompletionProposals(ITextViewer, int)
 	 */
 	public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int documentOffset) {
-		//IDocument unit= fManager.getWorkingCopy(fEditor.getEditorInput());
+		IWorkingCopyManager fManager = CUIPlugin.getDefault().getWorkingCopyManager();
+		ITranslationUnit unit = fManager.getWorkingCopy(fEditor.getEditorInput());
+							
 		IDocument document = viewer.getDocument();
 
 		ICCompletionProposal[] results = null;
@@ -205,9 +226,7 @@
 					length = selection.y;
 				}
 
-				//CCompletionEvaluator evaluator= new CCompletionEvaluator(document, offset, length);
-				//evaluator.restrictProposalsToMatchingCases(fRestrictToMatchingCase);
-				results = evalProposals(document, offset, length);
+				results = evalProposals(document, offset, length, unit);
 			}
 		} catch (Exception e) {
 			CUIPlugin.getDefault().log(e);
@@ -248,22 +267,67 @@
 		return results;
 	}
 
+	private ICElement getCurrentScope(ITranslationUnit unit, int documentOffset){
+		// quick parse the unit
+		Map elements = unit.parse();
+		// figure out what element is the enclosing the current offset
+		ICElement currentScope = unit;
+		Iterator i = elements.keySet().iterator();
+		while (i.hasNext()){
+			CElement element = (CElement) i.next();
+			
+			if ((element.getStartPos() < documentOffset ) 
+				&& ( element.getStartPos() + element.getLength() > documentOffset)
+				)
+			{
+				if(currentScope instanceof ITranslationUnit){
+					currentScope = element;
+				}else
+				if (currentScope instanceof CElement){
+					CElement currentScopeElement = (CElement) currentScope;
+					if(
+					 (currentScopeElement.getStartPos() < element.getStartPos())
+					 && (
+					 (currentScopeElement.getStartPos() + currentScopeElement.getLength() )
+					  > (element.getStartPos() + element.getLength()) )
+					)
+					currentScope = element;  
+				}
+			}
+		}
+		return currentScope;
+	}
+
 	/**
 	 * Order the given proposals.
 	 */
 	private ICCompletionProposal[] order(ICCompletionProposal[] proposals) {
-		Arrays.sort(proposals, fComparator);
+		if(proposals != null)
+			Arrays.sort(proposals, fComparator);
 		return proposals;
 	}
 
 	/**
 	 * Evaluate the actual proposals for C
 	 */
-	private ICCompletionProposal[] evalProposals(IDocument document, int pos, int length) {
+	public ICCompletionProposal[] evalProposals(IDocument document, int pos, int length, ITranslationUnit unit) {
+		return order (evalProposals(document, pos, length, getCurrentScope (unit, pos)));
+	}
+
+	private ICCompletionProposal[] evalProposals(IDocument document, int pos, int length, ICElement currentScope) {
 		boolean isDereference = false;
 		IRegion region; 
 		String frag = "";
-		
+
+		// TODO: Do all possible scopes
+		// possible scopes include IStructure, INamespace, and ITranslationUnit
+		if(	( !(currentScope instanceof IMethod))
+		&&  ( !(currentScope instanceof IMethodDeclaration)) 
+		&&  ( !(currentScope instanceof IFunction)) 
+		&&  ( !(currentScope instanceof IFunctionDeclaration)) 
+		){		
+			return null;
+		}
 		// Move back the pos by one the position is 0-based
 		if (pos > 0) {
 			pos--;
@@ -342,7 +406,7 @@
 		ArrayList completions = new ArrayList();
 
 		// Look in index manager
-		addProposalsFromModel(region, frag, completions);
+		addProposalsFromModel(region, frag,currentScope,  completions);
 		
 		// Loot in the contributed completions
 		addProposalsFromCompletionContributors(region, frag, completions);
@@ -384,7 +448,8 @@
 		}
 	}
 	
-	private void addProposalsFromModel(IRegion region, String frag, ArrayList completions) {
+// It is not needed to follow referenced projects since search does this for us now
+/*	private void addProposalsFromModel(IRegion region, String frag, ICElement currentScope, ArrayList completions) {
 		IProject project = null;
 		IEditorInput input = fEditor.getEditorInput();
 		if (input instanceof IFileEditorInput) {
@@ -396,22 +461,182 @@
 			}
 		}
 		if (project != null) {
-			addProjectCompletions(project, region, frag, completions);
+			addProjectCompletions(project, region, frag, currentScope, completions);
 			// Now query referenced projects
 			IProject referenced[];
 			try {
 				referenced = project.getReferencedProjects();
 				if (referenced.length > 0) {
 					for (int i = 0; i < referenced.length; i++) {
-						addProjectCompletions(referenced[i], region, frag, completions);
+						addProjectCompletions(referenced[i], region, frag, currentScope, completions);
 					}
 				}
 			} catch (CoreException e) {
 			}
 		}
 	}
+*/
+	private FunctionPrototypeSummary getPrototype (BasicSearchMatch match) {
+		switch(match.getElementType()){
+			case ICElement.C_FUNCTION:
+			case ICElement.C_FUNCTION_DECLARATION:
+			case ICElement.C_METHOD:
+			case ICElement.C_METHOD_DECLARATION:
+			{
+				return (new FunctionPrototypeSummary ( match.getName() ));
+			}
+		default:
+			return null;						
+		}
+	}
+	
+	private int calculateRelevance (BasicSearchMatch element){
+		
+		int type = element.getElementType();
+			
+		switch (type){
+			case ICElement.C_FIELD:
+				return 9;
+			case ICElement.C_VARIABLE:
+			case ICElement.C_VARIABLE_DECLARATION:
+				return 8;
+			case ICElement.C_METHOD:
+			case ICElement.C_METHOD_DECLARATION:
+				return 7;
+			case ICElement.C_FUNCTION:
+			case ICElement.C_FUNCTION_DECLARATION:
+				return 6;
+			case ICElement.C_CLASS:
+				return 5;
+			case ICElement.C_STRUCT:
+				return 4;
+			case ICElement.C_UNION:
+				return 3;
+			case ICElement.C_MACRO:
+				return 2;			
+			case ICElement.C_ENUMERATION:
+				return 1;
+			default :
+				return 0;
+		}
+	}
+	private void addProposalsFromModel (IRegion region, String frag, ICElement currentScope, ArrayList completions) {
+		List elementsFound = new LinkedList();
+		String prefix = frag + "*";
+		
+		//  TODO: change that to resource scope later
+		ICElement[] projectScopeElement = new ICElement[1];
+		projectScopeElement[0] = (ICElement)currentScope.getCProject();
+		ICSearchScope scope = SearchEngine.createCSearchScope(projectScopeElement, true);
+		OrPattern orPattern = new OrPattern();
+		// search for global variables, functions, classes, structs, unions, enums and macros
+		orPattern.addPattern(SearchEngine.createSearchPattern( prefix, ICSearchConstants.VAR, ICSearchConstants.DECLARATIONS, true ));
+		orPattern.addPattern(SearchEngine.createSearchPattern( prefix, ICSearchConstants.FUNCTION, ICSearchConstants.DECLARATIONS, true ));
+		orPattern.addPattern(SearchEngine.createSearchPattern( prefix, ICSearchConstants.FUNCTION, ICSearchConstants.DEFINITIONS, true ));
+		orPattern.addPattern(SearchEngine.createSearchPattern( prefix, ICSearchConstants.TYPE, ICSearchConstants.DECLARATIONS, true ));
+		orPattern.addPattern(SearchEngine.createSearchPattern( prefix, ICSearchConstants.ENUM, ICSearchConstants.DECLARATIONS, true ));
+		orPattern.addPattern(SearchEngine.createSearchPattern( prefix, ICSearchConstants.MACRO, ICSearchConstants.DECLARATIONS, true ));
+		searchEngine.search(CUIPlugin.getWorkspace(), orPattern, scope, resultCollector);
+		elementsFound.addAll(resultCollector.getSearchResults());
+
+		if((currentScope instanceof IMethod) || (currentScope instanceof IMethodDeclaration) ){
+			// add the methods and fields of the parent class
+/*			// use search with CElement Scope 
+			ICElement[] classScopeElements = new ICElement[1];
+			classScopeElements[0] = currentScope.getParent();		
+			ICSearchScope classScope = SearchEngine.createCSearchScope(classScopeElements);
+			OrPattern classOrPattern = new OrPattern();
+			classOrPattern.addPattern(SearchEngine.createSearchPattern(prefix, ICSearchConstants.FIELD, ICSearchConstants.DECLARATIONS, true));
+			classOrPattern.addPattern(SearchEngine.createSearchPattern(prefix, ICSearchConstants.METHOD, ICSearchConstants.DECLARATIONS, true));
+			classOrPattern.addPattern(SearchEngine.createSearchPattern(prefix, ICSearchConstants.METHOD, ICSearchConstants.DEFINITIONS, true));
+			searchEngine.search(CUIPlugin.getWorkspace(), classOrPattern, classScope, resultCollector);
+			elementsFound.addAll(resultCollector.getSearchResults());
+*/
+			// Work around until CElement scope is implemented
+			IStructure parentClass = (IStructure) currentScope.getParent();
+			ArrayList children = new ArrayList();
+			children.addAll(parentClass.getChildrenOfType(ICElement.C_METHOD));
+			children.addAll(parentClass.getChildrenOfType(ICElement.C_METHOD_DECLARATION));
+			children.addAll(parentClass.getChildrenOfType(ICElement.C_FIELD));
+			Iterator c = children.iterator();
+			while (c.hasNext()){
+				IMember child = (IMember)c.next();
+				if (child.getElementName().startsWith(frag))
+				{
+					BasicSearchMatch childMatch = new BasicSearchMatch();
+					childMatch.setType(child.getElementType());
+					childMatch.setParentName(parentClass.getElementName());
+					if(child.getVisibility() == ASTAccessVisibility.PUBLIC )
+						childMatch.setVisibility(ICElement.CPP_PUBLIC);
+					else if(child.getVisibility() == ASTAccessVisibility.PROTECTED )
+						childMatch.setVisibility(ICElement.CPP_PROTECTED);
+					else if(child.getVisibility() == ASTAccessVisibility.PRIVATE )
+						childMatch.setVisibility(ICElement.CPP_PRIVATE);
+					childMatch.setConst(child.isConst());
+					childMatch.setVolatile(child.isVolatile());
+					childMatch.setStatic(child.isStatic());
+					if(child instanceof IMethodDeclaration){
+						childMatch.setName(((IMethodDeclaration)child).getSignature());
+					}
+					else {
+						childMatch.setName(child.getElementName());
+					}
+				 
+					elementsFound.add(childMatch);		
+				}
+			}
+						
+		}
+
+		Iterator i = elementsFound.iterator();
+		while (i.hasNext()){
+			CCompletionProposal proposal;
+			FunctionPrototypeSummary fproto = null;
+			String fname = "";
+			String displayString = "";
+			Image image = null;
+			StringBuffer infoString = new StringBuffer();
+			
+			BasicSearchMatch match = (BasicSearchMatch)i.next();
+			fproto = getPrototype(match);						
+			fname = (fproto == null) ? match.getName() : fproto.getName();
+			displayString = (fproto == null) ? fname : fproto.getPrototypeString(true);
+			image = labelProvider.getImage(match);
+			infoString.append(displayString);
+			if(match.getParentName().length() > 0) {
+				infoString.append(" - Parent: ");
+				infoString.append(match.getParentName());
+			}							 
+			
+			
+			 
+			proposal = new CCompletionProposal(
+												fname, // replacement string
+											   	region.getOffset(), 
+											   	region.getLength(),
+											   	image,
+											   	displayString, // displayString
+											   	calculateRelevance(match)
+											  );
+			completions.add(proposal);
+
+			// No summary information available yet
+			// context information is available for methods only
+			if(fproto != null){
+				String fargs = fproto.getArguments();
+				if(fargs != null && fargs.length() > 0) {
+					proposal.setContextInformation(new ContextInformation(fname, fargs));
+				}
+			}
+			
+			// The info string could be populated with documentation info.
+			// For now, it has the name and the parent's name if available.
+			proposal.setAdditionalProposalInfo(infoString.toString());
+		}
+	}
 
-	private void addProjectCompletions(IProject project, IRegion region, String frag, ArrayList completions) {
+// Search (and the new indexer) is used now instead of the old indexer and CTags
+/*	private void addProjectCompletions(IProject project, IRegion region, String frag, ArrayList completions) {
 		IndexModel model = IndexModel.getDefault();
 
 		ITagEntry[] tags = model.query(project, frag + "*", false, false);
@@ -457,7 +682,7 @@
 			}
 		}
 	}
-
+*/
 	private Image getTagImage(int kind) {
 		switch (kind) {
 			case TagFlags.T_PROTOTYPE :
Index: src/org/eclipse/cdt/ui/CSearchResultLabelProvider.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CSearchResultLabelProvider.java,v
retrieving revision 1.1
diff -u -r1.1 CSearchResultLabelProvider.java
--- src/org/eclipse/cdt/ui/CSearchResultLabelProvider.java	29 Jul 2003 22:47:59 -0000	1.1
+++ src/org/eclipse/cdt/ui/CSearchResultLabelProvider.java	12 Aug 2003 19:02:07 -0000
@@ -72,6 +72,7 @@
 			case ICElement.C_UNION:			imageDescriptor = CPluginImages.DESC_OBJS_UNION;		break;
 			case ICElement.C_NAMESPACE:		imageDescriptor = CPluginImages.DESC_OBJS_CONTAINER;	break;
 			case ICElement.C_ENUMERATION:	imageDescriptor = CPluginImages.DESC_OBJS_ENUMERATION;	break;
+			case ICElement.C_MACRO:			imageDescriptor = CPluginImages.DESC_OBJS_MACRO;		break;
 			case ICElement.C_FUNCTION:		imageDescriptor = CPluginImages.DESC_OBJS_FUNCTION;		break;
 			case ICElement.C_VARIABLE:		imageDescriptor = CPluginImages.DESC_OBJS_FIELD;		break;
 			case ICElement.C_ENUMERATOR:	imageDescriptor = CPluginImages.DESC_OBJS_ENUMERATOR;	break;
Index: src/org/eclipse/cdt/ui/wizards/NewClassWizard.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/NewClassWizard.java,v
retrieving revision 1.1
diff -u -r1.1 NewClassWizard.java
--- src/org/eclipse/cdt/ui/wizards/NewClassWizard.java	27 May 2003 21:33:02 -0000	1.1
+++ src/org/eclipse/cdt/ui/wizards/NewClassWizard.java	12 Aug 2003 19:02:07 -0000
@@ -68,7 +68,7 @@
 	/**
 	 * @see Wizard#performFinish
 	 */
-	public boolean performFinish()  {
+	public boolean performFinish()  {			
 		IWorkspaceRunnable op= new IWorkspaceRunnable() {
 			public void run(IProgressMonitor monitor) throws CoreException, OperationCanceledException {
 				try {
Index: src/org/eclipse/cdt/ui/wizards/NewClassWizardPage.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/NewClassWizardPage.java,v
retrieving revision 1.5
diff -u -r1.5 NewClassWizardPage.java
--- src/org/eclipse/cdt/ui/wizards/NewClassWizardPage.java	30 Jul 2003 19:17:14 -0000	1.5
+++ src/org/eclipse/cdt/ui/wizards/NewClassWizardPage.java	12 Aug 2003 19:02:07 -0000
@@ -15,10 +15,11 @@
 import java.io.InputStream;
 import java.lang.reflect.InvocationTargetException;
 import java.text.MessageFormat;
-import java.util.LinkedList;
 import java.util.Iterator;
+import java.util.LinkedList;
 import java.util.List;
 
+import org.eclipse.cdt.core.CConventions;
 import org.eclipse.cdt.core.model.CModelException;
 import org.eclipse.cdt.core.model.CoreModel;
 import org.eclipse.cdt.core.model.ICElement;
@@ -347,7 +348,7 @@
 			if(fBaseClassDialogField.getText().length() > 0)
 			{
 				fAccessButtons.setEnabled(true);
-				fBaseClassStatus = baseClassChanged();
+				fBaseClassStatus = baseClassNameChanged();
 			}
 			else{
 				fAccessButtons.setEnabled(false);
@@ -405,8 +406,9 @@
 	
 	private void searchForClasses(ICProject cProject, List elementsFound, IProgressMonitor monitor, int worked){
 		ICSearchPattern pattern = SearchEngine.createSearchPattern( "*", ICSearchConstants.CLASS, ICSearchConstants.DECLARATIONS, false );
-		//  TODO: change that to project scope later
-		ICSearchScope scope = SearchEngine.createWorkspaceScope();;
+		ICElement[] elements = new ICElement[1];
+		elements[0] = cProject;
+		ICSearchScope scope = SearchEngine.createCSearchScope(elements, true);
 
 		searchEngine.search(CUIPlugin.getWorkspace(), pattern, scope, resultCollector);
 		elementsFound.addAll(resultCollector.getSearchResults());
@@ -761,13 +763,13 @@
 		{
 			extendingBase = true;
 			List classElements = findClassElementsInProject();
-			BasicSearchMatch baseClass = (BasicSearchMatch)findInList(baseClassName, classElements);
+			BasicSearchMatch baseClass = (BasicSearchMatch)findInList(baseClassName, null, classElements);
 
-			if(baseClass != null){
-				baseClassFileName = baseClass.getLocation().toString();
-			} else {
+//			if(baseClass != null){
+//				baseClassFileName = baseClass.getLocation().toString();
+//			} else {
 				baseClassFileName = baseClassName + HEADER_EXT;
-			}
+//			}
 		}
 		
 		if(isIncludeGuard()){
@@ -915,26 +917,30 @@
 	 */
 	protected IStatus classNameChanged() {
 		StatusInfo status= new StatusInfo();
-		String typeName= getNewClassName();
-		// class name must not be empty
-		if (typeName.length() == 0) {
+		String className= getNewClassName();
+		// must not be empty
+		if (className.length() == 0) {
 			status.setError(NewWizardMessages.getString("NewClassWizardPage.error.EnterClassName")); //$NON-NLS-1$
 			return status;
 		}
-		
-		// class name must not be qualified
-		if (typeName.indexOf('.') != -1) {
+		if (className.indexOf("::") != -1) {
 			status.setError(NewWizardMessages.getString("NewClassWizardPage.error.QualifiedName")); //$NON-NLS-1$
 			return status;
 		}
-		
-		// class name must follow the C/CPP convensions
+		IStatus val= CConventions.validateClassName(className);
+		if (val.getSeverity() == IStatus.ERROR) {
+			status.setError(NewWizardMessages.getFormattedString("NewClassWizardPage.error.InvalidClassName", val.getMessage())); //$NON-NLS-1$
+			return status;
+		} else if (val.getSeverity() == IStatus.WARNING) {
+			status.setWarning(NewWizardMessages.getFormattedString("NewClassWizardPage.warning.ClassNameDiscouraged", val.getMessage())); //$NON-NLS-1$
+			// continue checking
+		}		
 
-		// class must NOT exist
-//		ArrayList elementsFound = findClassElementsInProject();
-//		if(foundInList(getNewClassName(), elementsFound)){
-//			status.setWarning(NewWizardMessages.getString("NewClassWizardPage.error.ClassNameExists")); //$NON-NLS-1$
-//		}
+		// must not exist
+		List elementsFound = findClassElementsInProject();
+		if(foundInList(getNewClassName(), getContainerPath(linkedResourceGroupForHeader), elementsFound)){
+			status.setWarning(NewWizardMessages.getString("NewClassWizardPage.error.ClassNameExists")); //$NON-NLS-1$
+		}
 		return status;
 	}
 	/**
@@ -946,32 +952,48 @@
 	 * 
 	 * @return the status of the validation
 	 */
-	protected IStatus baseClassChanged() {
+	protected IStatus baseClassNameChanged() {
+		String baseClassName = getBaseClassName();		
 		StatusInfo status= new StatusInfo();
+		if (baseClassName.length() == 0) {
+			// accept the empty field (stands for java.lang.Object)
+			return status;
+		}
 
 		// class name must follow the C/CPP convensions
+		IStatus val= CConventions.validateClassName(baseClassName);
+		if (val.getSeverity() == IStatus.ERROR) {
+			status.setError(NewWizardMessages.getString("NewClassWizardPage.error.InvalidBaseClassName")); //$NON-NLS-1$
+			return status;
+		} 
 
 		// if class does not exist, give warning 
 		List elementsFound = findClassElementsInProject();
-		if(!foundInList(getBaseClassName(), elementsFound)){
+		if(!foundInList(baseClassName, null, elementsFound)){
 			status.setWarning(NewWizardMessages.getString("NewClassWizardPage.warning.BaseClassNotExists")); //$NON-NLS-1$
 		}
-		return status;
-		
+		return status;		
 	}
-	
-	private Object findInList(String name, List elements){
+		
+	private Object findInList(String name, IPath path, List elements){
 		Iterator i = elements.iterator();
 		while (i.hasNext()){
 			BasicSearchMatch element = (BasicSearchMatch)i.next();
-			if (name.equals(element.getName()))
-				return element;
+			if(path != null){
+				// check both the name and the path
+				if ((name.equals(element.getName())) && (path.makeAbsolute().equals(element.getLocation())))
+					return element;
+			} else {
+				// we don't care about the path
+				if (name.equals(element.getName()))
+					return element;				
+			}
 		}
 		return null;
 	}
 	
-	private boolean foundInList(String name, List elements){
-		if(findInList(name, elements) != null)
+	private boolean foundInList(String name, IPath path, List elements){
+		if(findInList(name, path, elements) != null)
 			return true;
 		else
 			return false;

Back to the top