Search code examples
javasearchjtextarea

How To Search the Word In Textarea


I want to Highlight The word from Caret Position to End of The Textarea then Highlight the word from Starting of the textarea to end then repeat the process in circular manner.My code works for current caret position to end of the textarea only.Please check it once.

My Code:

public void highLightWholeWord(JTextArea component, String patteren) {
try {
    Document doc = component.getDocument();
    String text = component.getText(0, doc.getLength());
    int pos = component.getCaretPosition();
    boolean found = false;
    int findLength = patteren.length();
    // Rest the search position if we're at the end of the document
    if (pos + findLength > doc.getLength()) {
        pos = 0;
    }
    while (pos + findLength <= doc.getLength()) {
        // Extract the text from teh docuemnt
        String match = doc.getText(pos, findLength).toLowerCase();
        // Check to see if it matches or request
        if (match.equals(patteren)) {
            if (pos - 1 >= 0
                        && Character.isWhitespace(doc.getText(pos - 1, 1).charAt(0))
                                        || Character.isWhitespace(doc.getText(findLength, 1).charAt(0))) {
                if (pos + findLength == doc.getLength()
                                             || Character.isWhitespace(doc.getText(pos + findLength, 1).charAt(0))) {
                    found = true;
                    break;
                }
            }
        }
        pos++;
    }
    if (found) {
    component.setSelectionStart(pos);
    component.setSelectionEnd(pos + patteren.length());
    component.getCaret().setSelectionVisible(true);
    }
} 
catch (Exception e) {
    e.printStackTrace();
}
}

Solution

  • Let's see a text for example, and suppose we are searching for the word "xxx". Suppose the last time you clicked the button it selected the last xxx:

    xxx ttt aaa xxx fff xxx yyy xxx zzz

    The size of this text is 35 characters.

    Now, the caret position is at the end of the highlighted xxx (position 31). And the pattern length is 3. You have an if condition that says:

    if (pos + findLength > doc.getLength()) {
        pos = 0;
    }
    

    Now, pos + findLength is 31+3 which is 34. So it is not greater than doc.getLength(). So it will not set pos = 0.

    So you will start searching for xxx from position 31, but there is no more xxx there. Just zzz. Eventually you'll reach the end of the document and found will not be set. So the selection will not be changed, and the caret will stay in position 31.

    So no matter how many times you press the button, the same thing will happen.

    This means that your condition for setting pos=0 is wrong. It will only work if the xxx is absolutely the last word.

    Here is a suggestion to solve this:

    Define your condition in another method:

    public boolean foundPattern( Document doc, int pos, int findLength  ) {
        String match = doc.getText(pos, findLength).toLowerCase();
        // Check to see if it matches or request
        if (match.equals(patteren)) {
            if (pos - 1 >= 0
                        && Character.isWhitespace(doc.getText(pos - 1, 1).charAt(0))
                                        || Character.isWhitespace(doc.getText(findLength, 1).charAt(0))) {
                if (pos + findLength == doc.getLength()
                                             || Character.isWhitespace(doc.getText(pos + findLength, 1).charAt(0))) {
                    return true;
                }
            }
        }
        return false;
    }
    

    This is just to make writing the actual while part easier:

    while (pos + findLength <= doc.getLength()) {
    
       found = foundPattern( doc, pos, findLength );
    
       if ( found ) {
          break;
       }
    
       pos++;
    
    }
    
    if ( ! found ) {
       pos = 0;
    
       while ( pos + findLength < component.getCaretPosition() ) {
           found = foundPattern( doc, pos, findLength );
           if ( found ) {
              break;
           }
    
           pos++;
       }
    }
    

    So now you have two loops. If the first doesn't find the pattern (from caret position to end of document), then the second one starts looking from start of document to caret position.