import java.awt.*; import java.awt.event.*; import java.awt.datatransfer.*; import java.awt.dnd.*; import java.awt.print.*; import java.io.*; import java.util.*; import javax.swing.*; import javax.swing.event.*; import javax.swing.text.*; /** MTTE.java -- MikesTextTableEditor * Classes: MTTE, TextEditFrame, Delay, TextDropTargetListener, TextPrinter, SearchDialog * Has Drag and Drop; has Search and Replace. * Handles EOLs from PC, Mac, Unix seamlessly. * @author M.Lampton UCB SSL 2003, 2011, 2014, 2017 * JScrollPane with JTextArea: combo is fully automatic & invisible. * Does not use explicit paintComponent(), nor Graphics2D except for printing. * ..these are built into JTextArea. * Fonts are installed into JTextArea, not any JPanel. * Because the main() is in public class "MTTE" the manifest must specify this: * Main-Class: MTTE * Author: M.Lampton * Has buttons for table management "Narrow" and "Widen." */ @SuppressWarnings("serial") // before each private class public class MTTE { public static void main(String[] args) { javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { createAndShowGUI(); } }); } private static void createAndShowGUI() { TextEditFrame frame = new TextEditFrame(); // window close is handled by the WindowListener below, not here. frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); frame.setVisible(true); } } /** A frame with a menubar and a text area. * M.Lampton Stellar Software 2003, 2011 */ @SuppressWarnings("serial") // before each private class class TextEditFrame extends JFrame { static private JTextArea myJTA = null; static private SearchDialog mySD = null; static public boolean bDirty = false; static private boolean bWaken = false; static private JFileChooser myJFC = null; static private File file = null; //----Named JMenuItems are accessible to dynamic graying--- static JMenuItem fileNew, fileOpen, fileSave, fileSaveAs, filePrint, fileQuit; static JRadioButtonMenuItem fileDNDappend, fileDNDreplace; static JMenuItem editCut, editCopy, editPaste, editDelete, editFind, editAll; static private JFrame myJF = null; static private ButtonGroup fontBG; public static String getSelectedFont() // must explicitly setActionCommand() to get it. // This works only after fontBG + fontMenu construction. { return fontBG.getSelection().getActionCommand(); } public boolean isDNDappend() // mode queried by Drag-n-Drop { return fileDNDappend.isSelected(); } public void setFile(File f) // New file from DnD { file = f; setTitle(f.getPath()); bDirty = false; } public TextEditFrame() // constructor { setTitle("MikesTextTableEditor"); setSize(600, 300); setLocation(100, 100); //-----set up JFileChooser and local directory---- myJFC = new JFileChooser(); String sDir = System.getProperty("user.dir"); if (sDir != null) { File fDir = new File(sDir); if ((fDir != null) && (fDir.isDirectory())) myJFC.setCurrentDirectory(fDir); } else myJFC.setCurrentDirectory(null); //---next must come the JTextArea---------- myJTA = new JTextArea(8, 40); myJTA.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3)); myJTA.setCaretColor(Color.red); myJTA.putClientProperty("caretWidth", 3); // Font installation is done by the the JRBMI listener. myJTA.setFont(new Font("Courier New", Font.BOLD, 14)); // coordinate line 188 myJTA.setText(""); myJTA.addCaretListener(new MyCaretListener()); // for line number myJTA.getDocument().addDocumentListener(new MyDocumentListener()); myJTA.setSelectionColor(Color.CYAN); myJTA.setLineWrap(false); //----create local drop target using JTA callback-------- new DropTarget(myJTA, new TextDropTargetListener(this, myJTA)); //---search dialog, visibility coordinated with main window------ mySD = new SearchDialog(this, myJTA); mySD.setVisible(false); addWindowListener(new WindowAdapter() { public void windowIconified(WindowEvent we) { bWaken = mySD.isVisible(); mySD.setVisible(false); } public void windowDeiconified(WindowEvent we) { if (bWaken) mySD.setVisible(true); } public void windowClosing(WindowEvent we) { if (bDirty && !bAbandon()) return; // do not close System.exit(0); // close } }); //------menus: be sure no two accelerators are the same!----- JMenu fileMenu = new JMenu("File"); fileMenu.setMnemonic('F'); fileMenu.addMenuListener(fileGrayingListener); FMIListener fileL = new FMIListener(); fileMenu.add(fileNew = makeItem("New", fileL, 'N', KeyEvent.VK_N)); fileMenu.add(fileOpen = makeItem("Open", fileL, 'O', KeyEvent.VK_O)); fileMenu.add(fileSave = makeItem("Save", fileL, 'S', KeyEvent.VK_S)); fileMenu.add(fileSaveAs = makeItem("SaveAs", fileL, 0, 0)); fileMenu.addSeparator(); ButtonGroup fileBG = new ButtonGroup(); fileMenu.add(fileDNDappend = makeJRBMI("DnD append", null, fileBG, false)); fileMenu.add(fileDNDreplace = makeJRBMI("DnD replace", null, fileBG, true)); fileMenu.addSeparator(); fileMenu.add(filePrint = makeItem("Print", fileL, 'P', KeyEvent.VK_P)); fileMenu.addSeparator(); fileMenu.add(fileQuit = makeItem("Quit", fileL, 'X', KeyEvent.VK_Q)); JMenu editMenu = new JMenu("Edit"); editMenu.setMnemonic('E'); editMenu.addMenuListener(editGrayingListener); EMIListener editL = new EMIListener(); editMenu.add(editCut = makeItem("Cut", editL, 'T', KeyEvent.VK_X)); editMenu.add(editCopy = makeItem("Copy", editL, 'C', KeyEvent.VK_C)); editMenu.add(editPaste = makeItem("Paste", editL, 'P', KeyEvent.VK_V)); editMenu.add(editDelete = makeItem("Delete", editL, 'D', KeyEvent.VK_D)); editMenu.addSeparator(); editMenu.add(editFind = makeItem("Find", editL, 'F', KeyEvent.VK_F)); editMenu.addSeparator(); editMenu.add(editAll = makeItem("SelectAll", editL, 'A', KeyEvent.VK_A)); JMenu fontMenu = new JMenu("Font"); FontListener fontL = new FontListener(); fontBG = new ButtonGroup(); fontMenu.add(makeJRBMI("10 pt", fontL, fontBG, false)); fontMenu.add(makeJRBMI("12 pt", fontL, fontBG, false)); fontMenu.add(makeJRBMI("14 pt", fontL, fontBG, false)); fontMenu.add(makeJRBMI("16 pt", fontL, fontBG, false)); fontMenu.add(makeJRBMI("10 BOLD", fontL, fontBG, false)); fontMenu.add(makeJRBMI("12 BOLD", fontL, fontBG, false)); fontMenu.add(makeJRBMI("14 BOLD", fontL, fontBG, true)); //see line 111 fontMenu.add(makeJRBMI("16 BOLD", fontL, fontBG, false)); JMenu aboutMenu = new JMenu("About"); JMenuItem authorMenuItem = new JMenuItem("Author info"); authorMenuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { String sAuthor = " Mike's Text Table Editor\n" + "for Java version 1.5.0 and up\n" + " www.MikeLampton.com\n\n"; JOptionPane.showMessageDialog(null, sAuthor); } }); JMenuItem hostMenuItem = new JMenuItem("Host info"); hostMenuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { String sHost = java.lang.System.getProperty("java.version"); sHost = "host Java version is "+getVersionNumber(sHost); JOptionPane.showMessageDialog(null, sHost); } }); aboutMenu.add(authorMenuItem); aboutMenu.add(hostMenuItem); //---these are for narrowing and widening a table---- JButton jbNarrow = new JButton("Narrow"); jbNarrow.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { java.awt.Toolkit.getDefaultToolkit().beep(); doNarrow(); } }); JButton jbWidenSpace = new JButton("Widen Space"); jbWidenSpace.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { java.awt.Toolkit.getDefaultToolkit().beep(); doWiden(" "); } }); JButton jbWidenComma = new JButton("Widen Comma"); jbWidenComma.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { java.awt.Toolkit.getDefaultToolkit().beep(); doWiden(","); } }); //---assemble the menubar------- JMenuBar jmb = new JMenuBar(); jmb.add(fileMenu); jmb.add(editMenu); jmb.add(fontMenu); jmb.add(aboutMenu); jmb.add(jbNarrow); jmb.add(jbWidenSpace); jmb.add(jbWidenComma); setJMenuBar(jmb); //---install the JTextArea------------ Container contentPane = getContentPane(); contentPane.add(new JScrollPane(myJTA)); setVisible(true); } //-------helper methods--------------- String getVersionNumber(String arg) { int length = arg.length(); StringBuffer sb = new StringBuffer(); for (int i=0; i='0') && (c<='9')) || (c=='.') || (c=='_'); } JMenuItem makeItem(String s, ActionListener al, int mnem, int acc) // Convenience routine: assembles a JMI from strings, listener, etc. // Most useful when there is a single listener for an entire menu. // Can create either anonymous or named JMI's. { JMenuItem item = new JMenuItem(s); item.addActionListener(al); item.setActionCommand(s); if (mnem != 0) item.setMnemonic((char) mnem); if (acc != 0) { int iMask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); item.setAccelerator(KeyStroke.getKeyStroke(acc, iMask)); } return item; } JRadioButtonMenuItem makeJRBMI(String s, FontListener fl, ButtonGroup bg, boolean active) { JRadioButtonMenuItem item = new JRadioButtonMenuItem(s); item.setActionCommand(s); item.addActionListener(fl); item.setSelected(active); bg.add(item); return item; } void doPost() // Displays file & line number on titlebar { int caretpos = myJTA.getCaretPosition(); int row = 1; int col = 1; try { row = myJTA.getLineOfOffset(caretpos); col = caretpos - myJTA.getLineStartOffset(row); } catch (BadLocationException ble) {} setTitle((file==null) ? "" : file.getPath()+" "+row+" "+col); } MenuListener fileGrayingListener = new MenuListener() // Sets up graying for file menu items { public void menuSelected(MenuEvent me) { boolean bText = myJTA.getText().length() > 0; fileNew.setEnabled(true); fileOpen.setEnabled(true); fileSave.setEnabled(true); fileSaveAs.setEnabled(bText); filePrint.setEnabled(bText); fileQuit.setEnabled(true); } public void menuDeselected(MenuEvent me) {} public void menuCanceled(MenuEvent me) {} }; MenuListener editGrayingListener = new MenuListener() // Sets up graying for edit menu items { public void menuSelected(MenuEvent me) { boolean bMarked = myJTA.getSelectionEnd() > myJTA.getSelectionStart(); boolean bClip = getClipboardTextLength() > 0; boolean bText = myJTA.getText().length() > 0; editCut.setEnabled(bMarked); editCopy.setEnabled(bMarked); editPaste.setEnabled(bClip); editDelete.setEnabled(bMarked); editFind.setEnabled(bText); editAll.setEnabled(bText); } public void menuDeselected(MenuEvent me) {} public void menuCanceled(MenuEvent me) {} }; //-----clipboard support methods--------------- String getClipboardText() // http://www.exampledepot.com/egs/java.awt.datatransfer/ToClip.html { Transferable t = Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null); try { if (t != null && t.isDataFlavorSupported(DataFlavor.stringFlavor)) return (String)t.getTransferData(DataFlavor.stringFlavor); } catch (UnsupportedFlavorException e) {} catch (IOException e) {} return null; } int getClipboardTextLength() { String s = getClipboardText(); return (s == null) ? 0 : s.length(); } //------file support methods--------------- void doOpen() // Uses static jfc for file persistence. { int result = myJFC.showOpenDialog(null); if (result == JFileChooser.APPROVE_OPTION) { File f = myJFC.getSelectedFile(); if (f.isFile() && f.canRead()) { try { FileReader fr = new FileReader(f.getPath()); BufferedReader br = new BufferedReader(fr); String s; while ((s = br.readLine()) != null) myJTA.append(s + "\n"); file = f; bDirty = false; } catch (FileNotFoundException fnfe) {} catch (IOException ioe) {} setTitle(file.getPath()); } } } private String getLineText(int lineNumber) { int nlines = myJTA.getLineCount(); if ((lineNumber < 0) || (lineNumber >= nlines)) { // System.out.println("error: getLineText() was passed lineNumber = " + lineNumber); return ""; } try { int startIndex = myJTA.getLineStartOffset(lineNumber); int endIndex = myJTA.getLineEndOffset(lineNumber); String line = myJTA.getText().substring(startIndex, endIndex - startIndex); return line; } catch (BadLocationException ex) { return ""; } } private void doNarrow() { try { int ix = myJTA.getCaretPosition(); // System.out.println("getCaretPosition = "+ix); int row = myJTA.getLineOfOffset(ix); // System.out.println("getLineOfOffset = "+row); int col = ix - myJTA.getLineStartOffset(row); // System.out.println("getLineStartOffset = "+col); if (col>0) { myJTA.setCaretPosition(myJTA.getCaretPosition()-1); // shift left modifyAllLines("", col-1, col); } myJTA.grabFocus(); // otherwise the caret vanishes } catch (BadLocationException ex) { } } private void doWiden(String s) { try { int ix = myJTA.getCaretPosition(); // System.out.println("getCaretPosition = "+ix); int row = myJTA.getLineOfOffset(ix); // System.out.println("getLineOfOffset = "+row); int col = ix - myJTA.getLineStartOffset(row); // System.out.println("getLineStartOffset = "+col); modifyAllLines(s, col, col); myJTA.grabFocus(); // otherwise the caret vanishes } catch (BadLocationException ex) { } } private void modifyAllLines(String s, int jstart, int jstop) // Here, jstart and jstop are in the input file row zero. // The string "s" will shrink or grow its line, according to its length. // For multi-line table editing the entire table will narrow or widen. // Crashes in iline increases from zero; also crashes decreasing from nlines. { int nchars = myJTA.getText().length(); int nrows = myJTA.getLineCount(); // - 1; // System.out.println("modifyAllLines is starting with nchars="+nchars+" nrows="+nrows+" jstart="+jstart+" jstop="+jstop); try { for (int iline=nrows-1; iline>=0; iline--) { int j0 = myJTA.getLineStartOffset(iline); // System.out.println("For iline = "+iline+" getLineStartOffset = "+j0); int j1 = myJTA.getLineEndOffset(iline); // System.out.println("For iline = "+iline+" getLineEndOffset = "+j1); int mystart = j0 + jstart; int mystop = j0 + jstop; // System.out.println("For iline = "+iline+" starting index = "+mystart+" Stopping index = "+mystop); if (mystop < j1) { // System.out.println("Since mystop < endLine, going ahead with replaceRange()."); myJTA.replaceRange(s, mystart, mystop); } else { // System.out.println("Not within nchars, so skipping replaceRange()."); } nchars = myJTA.getText().length(); // System.out.println("modifyAllLines has finished this line; total nchars = "+nchars+" nrows = "+nrows); } } catch (BadLocationException ex) { // System.out.println("BadLocationException"); } } void doSave() { if (file == null) doSaveAs(); String lines[] = myJTA.getText().split("\\n"); try { PrintWriter pw = new PrintWriter(new FileWriter(file.getPath())); for (int i=0; i -1); } private int iAnalyzeDropFlavor(DropTargetDropEvent event) { Transferable transferable = event.getTransferable(); DataFlavor[] flavors = transferable.getTransferDataFlavors(); for (int i=0; i sList; // separate lines of text int nlines = 0; public TextPrinter(JTextArea gJTA) // called by user; constructor triggers action { myJTA = gJTA; // nlines = getStringList(); PrinterJob job = PrinterJob.getPrinterJob(); job.setPrintable(this); if (job.printDialog()) { try { job.print(); } catch (PrinterException ex) { JOptionPane.showMessageDialog(null, "Job did not print."); } } } public int print(Graphics g, PageFormat pf, int iPage) throws PrinterException // called by OS with details of chosen printer. { Font font = myJTA.getFont(); FontMetrics metrics = g.getFontMetrics(font); int lineHeight = metrics.getHeight(); // PageFormat, PDF, letter, portrait: X=0.0, y=0.0, W=612.0, H=792.0 // subtracting margins allows automatic landscape/portrait switching double leftMargin=72.0, topMargin=72.0, rightMargin=72.0, botMargin=72.0; double height = pf.getImageableHeight() - topMargin - botMargin; double width = pf.getImageableWidth() - leftMargin - rightMargin; double xOrigin = pf.getImageableX() + leftMargin; double yOrigin = pf.getImageableY() + topMargin; if ((breaks == null) || (sList == null)) { nlines = getStringList(); int linesPerPage = (int)(height/lineHeight); int numBreaks = (nlines-1)/linesPerPage; breaks = new int[numBreaks]; for (int b=0; b breaks.length) { return NO_SUCH_PAGE; } Graphics2D g2d = (Graphics2D)g; g2d.translate(xOrigin, yOrigin); int y = 0; int start = (iPage == 0) ? 0 : breaks[iPage-1]; int end = (iPage == breaks.length) ? nlines : breaks[iPage]; for (int line=start; line(); int j=0, istart=0, iend=0; boolean ok = true; do { try { istart = myJTA.getLineStartOffset(j); iend = myJTA.getLineEndOffset(j); String s = myJTA.getText().substring(istart, iend); sList.add(s); ok = true; j++; } catch (BadLocationException ex) { ok = false; } } while (ok); return sList.size(); } } //----------end of Printer class------------------ /** Search+Replace nonmodal Dialog class for JTextArea. * Uses host's WindowListener to disappear when host hides. * M.Lampton Stellar Software 2003, 2011 */ @SuppressWarnings("serial") // before each private class class SearchDialog extends JDialog { JFrame myJF = null; JTextArea myJTA = null; int index = 0; JTextField searchJTF = null; JTextField replaceJTF = null; ButtonGroup dirBG, sensBG; public SearchDialog(JFrame givenJF, JTextArea givenJTA) { myJF = givenJF; myJTA = givenJTA; searchJTF = new JTextField("", 10); searchJTF.setMaximumSize(new Dimension(150, 20)); replaceJTF = new JTextField("", 10); replaceJTF.setMaximumSize(new Dimension(150, 20)); setVisible(false); setTitle("Search & Replace"); //-----Panel 1: search panel-------------- JPanel jp1 = new JPanel(); jp1.setPreferredSize(new Dimension(100,20)); jp1.setLayout(new BoxLayout(jp1, BoxLayout.X_AXIS)); JLabel jl1 = new JLabel("Find what?"); jp1.add(Box.createGlue()); jp1.add(jl1); jp1.add(Box.createHorizontalStrut(5)); jp1.add(searchJTF); jp1.add(Box.createHorizontalStrut(50)); //-------Panel 2: replace panel------------- JPanel jp2 = new JPanel(); jp2.setPreferredSize(new Dimension(100,20)); jp2.setLayout(new BoxLayout(jp2, BoxLayout.X_AXIS)); JLabel jl2 = new JLabel("Replace with?"); jp2.add(Box.createGlue()); jp2.add(jl2); jp2.add(Box.createHorizontalStrut(5)); jp2.add(replaceJTF); jp2.add(Box.createHorizontalStrut(50)); //------Panel 3: search direction panel---------- JPanel jp3 = new JPanel(); jp3.setPreferredSize(new Dimension(150, 25)); jp3.setMinimumSize(jp3.getPreferredSize()); dirBG = new ButtonGroup(); JRadioButton fwdJRB = new JRadioButton("forward", true); fwdJRB.setActionCommand("fwd"); fwdJRB.setVerticalTextPosition(AbstractButton.CENTER); fwdJRB.setHorizontalTextPosition(AbstractButton.LEFT); dirBG.add(fwdJRB); JRadioButton revJRB = new JRadioButton("reverse", true); revJRB.setActionCommand("rev"); revJRB.setVerticalTextPosition(AbstractButton.CENTER); revJRB.setHorizontalTextPosition(AbstractButton.RIGHT); dirBG.add(revJRB); jp3.add(Box.createGlue()); jp3.add(Box.createGlue()); jp3.add(fwdJRB); jp3.add(revJRB); jp3.add(Box.createGlue()); //-----Panel 4: case sensitivity panel----------- JPanel jp4 = new JPanel(); jp4.setPreferredSize(new Dimension(150, 25)); jp4.setMinimumSize(jp4.getPreferredSize()); sensBG = new ButtonGroup(); JRadioButton ignoreJRB = new JRadioButton("ignore case", true); ignoreJRB.setActionCommand("ignore"); ignoreJRB.setVerticalTextPosition(AbstractButton.CENTER); ignoreJRB.setHorizontalTextPosition(AbstractButton.LEFT); sensBG.add(ignoreJRB); JRadioButton matchJRB = new JRadioButton("match case", true); matchJRB.setActionCommand("match"); matchJRB.setVerticalTextPosition(AbstractButton.CENTER); matchJRB.setHorizontalTextPosition(AbstractButton.RIGHT); sensBG.add(matchJRB); jp4.add(Box.createGlue()); jp4.add(Box.createGlue()); jp4.add(ignoreJRB); jp4.add(matchJRB); jp4.add(Box.createGlue()); //-----Panel 5: button panel----------------- JPanel jp5 = new JPanel(); jp5.setPreferredSize(new Dimension(150, 40)); jp5.setMinimumSize(jp5.getPreferredSize()); jp5.setLayout(new BoxLayout(jp5, BoxLayout.X_AXIS)); JButton nextButton = new JButton("Next"); nextButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int ix = getNextPosition(false); setTitle((ix >= 0) ? "Found" : "Not found"); } }); JButton replaceButton = new JButton("Replace"); replaceButton.addActionListener(new ActionListener() // must replace possible current selection, and then search to next selection. { public void actionPerformed(ActionEvent e) { int ix = getNextPosition(true); setTitle((ix >= 0) ? "Found" : "Not found"); } }); JButton allButton = new JButton(" All "); allButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int ix=0, n=0; while (ix >= 0) { ix = getNextPosition(true); if (ix >= 0) n++; } setTitle(n + " replacements"); } }); JButton closeButton = new JButton("Close"); closeButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { setVisible(false); } }); jp5.add(Box.createGlue()); jp5.add(nextButton); jp5.add(Box.createGlue()); jp5.add(replaceButton); jp5.add(Box.createGlue()); jp5.add(allButton); jp5.add(Box.createGlue()); jp5.add(closeButton); jp5.add(Box.createGlue()); Container cp = getContentPane(); cp.setLayout(new BoxLayout(cp, BoxLayout.Y_AXIS)); cp.add(Box.createVerticalStrut(5)); cp.add(jp1); cp.add(Box.createVerticalStrut(5)); cp.add(jp2); cp.add(jp3); cp.add(jp4); cp.add(jp5); cp.setPreferredSize(new Dimension(320, 160)); cp.setMinimumSize(getPreferredSize()); pack(); setLocationRelativeTo(myJF); setVisible(false); } int getNextPosition(boolean bReplace) { String sc = myJTA.getSelectedText(); String sr = replaceJTF.getText(); String ss = searchJTF.getText(); String st = myJTA.getText(); int ir = sr.length(); int is = ss.length(); int it = st.length(); if ((is < 1) || (it < 1)) return -1; if (bReplace && (sc!=null) && (sr!=null)) { if (bIgnoreCase()) { sc = sc.toUpperCase(); ss = ss.toUpperCase(); } if (sc.equals(ss)) { myJTA.replaceSelection(sr); // changes text st = myJTA.getText(); // get new text it = st.length(); // get new length } } //----now search for next selection------ if (bIgnoreCase()) { st = st.toUpperCase(); ss = ss.toUpperCase(); } int ix = myJTA.getCaretPosition(); // On repeats, caret is always found at the end of selection if (bForward()) { if (ix == it) // special startup case ix = 0; ix = st.indexOf(ss, ix); // = startNext. or -1. } else { ix -= is + 1; // back up if (ix < is) // absent ix = -1; else ix = st.lastIndexOf(ss, ix); } if (ix >= 0) // success { myJTA.requestFocus(true); myJTA.setSelectionStart(ix); myJTA.setSelectionEnd(ix+is); // Caret must remain at SelectionEnd } return ix; } boolean bIgnoreCase() { String sens = sensBG.getSelection().getActionCommand(); return sens.equals("ignore"); } boolean bForward() { String dir = dirBG.getSelection().getActionCommand(); return dir.equals("fwd"); } } //---end of SearchDialog--------------------