/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

/*
 * "WordDelineator.java"
 * WordDelineator.java 1.6 01/07/26
 */
package org.netbeans.lib.terminalemulator;

/*
 * Class used by Term to find the boundaries of a <i>word</i>, the region
 * of text that gets selected when you double-click.
 *<p>
 * Term has a default WordDelineator which can be changed by using this class
 * as an adapter and overriding either charClass() or findLeft() and
 * findRight() and assigning an object of the resulting class via
 * Term.setWordDelineator().
 */
public class WordDelineator {

    private String delimiters = new String();
    
    private WordDelineator(String delimeters) {
        this.delimiters = delimeters;
    }

    /**
     * Return the <i>character equivalence class</i> of 'c'.
     * <p>
     * This is used by findLeft() and findRight() which operate such that a
     * <i>word</i> is bounded by a change in character class.
     * <p>
     * A character equivalence class is characterised by a number, any number,
     * that is different from numbers for other character classes. For example,
     * this implementation, which is used as the default WordDelineator for Term
     * returns 1 for spaces, 2 for delimiters defined by user in
     * {@link org.netbeans.lib.terminalemulator.support.TermOptions} and 0 for
     * everything else.
     */
    protected int charClass(char c) {
        if (delimiters.indexOf(c) >= 0) {
            return 2;
        } else {
            return 0;
        }
    }

    /**
     * Return index of a char at the beginning of the word.
     * @param buf text we search at (typically a line)
     * @param start where to start search from
     * @param useLineBound should the line bound be treated (if reached) as a word start
     * @return idx of the left bound or -1 if a bound reached with useLineBound flag
     */
    protected int findLeft(StringBuffer buf, int start, boolean useLineBound) {
        int cclass = charClass(buf.charAt(start));

        // go left until a character of differing class is found
        int lx = start;
        boolean success = false;
        while (lx > 0) {
            success = charClass(buf.charAt(lx - 1)) != cclass;
            if (success) {
                break;
            }
            lx--;
        }
        return (!success && useLineBound) ? -1 : lx;
    }

    /**
     * Return index of char past the word.
     * @param buf text we search at (typically a line)
     * @param start where to start search from
     * @param useLineBound should the line bound be treated (if reached) as a word start
     * @return idx of the right bound or -1 if a bound reached with useLineBound flag
     */
    protected int findRight(StringBuffer buf, int start, boolean useLineBound) {
        int cclass = charClass(buf.charAt(start));

        // go right until a character of a differing class is found.
        int rx = start;
        boolean success = false;
        while (rx < buf.length()) {
            success = charClass(buf.charAt(rx)) != cclass;
            if (success) {
                break;
            }
            rx++;
        }
        rx--;
        return (!success && useLineBound) ? -1 : rx;
    }
    
    public static WordDelineator createCustomDelineator(String delimeters) {
        if (delimeters.contains(" ")) { //NOI18N
            return new WordDelineator(delimeters);
        } else {
            return new WordDelineator(delimeters.concat(" ")); //NOI18N
        }
    }
    
    public static WordDelineator createNewlineDelineator() {
        return new WordDelineator("\n"); //NOI18N
    }
}
