// Path: src/main/java/waveview/search/SearchFormatException.java
// public class SearchFormatException extends Exception {
//     private final int startOffset;
//     private final int endOffset;
// 
//     SearchFormatException(String what, int startOffset, int endOffset) {
//         super(what);
//         this.startOffset = startOffset;
//         this.endOffset = endOffset;
//     }
// 
//     public int getStartOffset() {
//         return startOffset;
//     }
// 
//     public int getEndOffset() {
//         return endOffset;
//     }
// }


import javax.swing.text.DefaultHighlighter;
import javax.swing.text.Highlighter;
import waveview.search.SearchFormatException;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;
        JPanel findContainer = new JPanel();
        findContainer.setLayout(new FlowLayout(FlowLayout.LEFT));
        findContainer.add(findLabel);
        findContainer.add(new JScrollPane(searchExprTextArea));
        add(findContainer, BorderLayout.CENTER);

        JPanel buttonContainer = new JPanel();
        buttonContainer.setLayout(new FlowLayout(FlowLayout.RIGHT));
        buttonContainer.add(prevButton);
        buttonContainer.add(nextButton);
        add(buttonContainer, BorderLayout.SOUTH);
    }

    /// Called when the user changes the search string.
    // The next time the user hits next/prev, will regenerate the Search object.
    private void invalidateSearch() {
        needToParseSearch = true;

        // When the user begins editing, remove the error highlights
        // so they don't leave boogers all over the place.
        errorHighlighter.removeAllHighlights();
    }

    /// If the user changed the search string, try to parse it and generate
    /// a new Search object. If the search string is invalid, highlight the
    /// position of the error and pop up an error message.
    private void parseSearchIfNeeded() {
        if (needToParseSearch) {
            try {
                mainWindow.setSearch(searchExprTextArea.getText());
// Path: src/main/java/waveview/search/SearchFormatException.java
// public class SearchFormatException extends Exception {
//     private final int startOffset;
//     private final int endOffset;
// 
//     SearchFormatException(String what, int startOffset, int endOffset) {
//         super(what);
//         this.startOffset = startOffset;
//         this.endOffset = endOffset;
//     }
// 
//     public int getStartOffset() {
//         return startOffset;
//     }
// 
//     public int getEndOffset() {
//         return endOffset;
//     }
// }


// Path: src/main/java/waveview/FindView.java
import javax.swing.text.DefaultHighlighter;
import javax.swing.text.Highlighter;
import waveview.search.SearchFormatException;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;

        JPanel findContainer = new JPanel();
        findContainer.setLayout(new FlowLayout(FlowLayout.LEFT));
        findContainer.add(findLabel);
        findContainer.add(new JScrollPane(searchExprTextArea));
        add(findContainer, BorderLayout.CENTER);

        JPanel buttonContainer = new JPanel();
        buttonContainer.setLayout(new FlowLayout(FlowLayout.RIGHT));
        buttonContainer.add(prevButton);
        buttonContainer.add(nextButton);
        add(buttonContainer, BorderLayout.SOUTH);
    }

    /// Called when the user changes the search string.
    // The next time the user hits next/prev, will regenerate the Search object.
    private void invalidateSearch() {
        needToParseSearch = true;

        // When the user begins editing, remove the error highlights
        // so they don't leave boogers all over the place.
        errorHighlighter.removeAllHighlights();
    }

    /// If the user changed the search string, try to parse it and generate
    /// a new Search object. If the search string is invalid, highlight the
    /// position of the error and pop up an error message.
    private void parseSearchIfNeeded() {
        if (needToParseSearch) {
            try {
                mainWindow.setSearch(searchExprTextArea.getText());
            } catch (SearchFormatException exc) {