public void actionPerformed(ActionEvent evt)
		{
			JEditTextArea textArea = getTextArea(evt);
			int caret = textArea.getCaretPosition();
			int line = textArea.getCaretLine();

			if(line == 0)
			{
				textArea.getToolkit().beep();
				return;
			}

			int magic = textArea.getMagicCaretPosition();
			if(magic == -1)
			{
				magic = textArea.offsetToX(line,
					caret - textArea.getLineStartOffset(line));
			}

			caret = textArea.getLineStartOffset(line - 1)
				+ textArea.xToOffset(line - 1,magic);
			if(select)
				textArea.select(textArea.getMarkPosition(),caret);
			else
				textArea.setCaretPosition(caret);
			textArea.setMagicCaretPosition(magic);
		}
		public void actionPerformed(ActionEvent evt)
		{
			JEditTextArea textArea = getTextArea(evt);
			int caret = textArea.getCaretPosition();
			int line = textArea.getCaretLine();
			int lineStart = textArea.getLineStartOffset(line);
			caret -= lineStart;

			String lineText = textArea.getLineText(textArea
				.getCaretLine());

			if(caret == 0)
			{
				if(lineStart == 0)
				{
					textArea.getToolkit().beep();
					return;
				}
				caret--;
			}
			else
			{
				String noWordSep = (String)textArea.getDocument().getProperty("noWordSep");
				caret = TextUtilities.findWordStart(lineText,caret,noWordSep);
			}

			if(select)
				textArea.select(textArea.getMarkPosition(),
					lineStart + caret);
			else
				textArea.setCaretPosition(lineStart + caret);
		}
		public void actionPerformed(ActionEvent evt)
		{
			JEditTextArea textArea = getTextArea(evt);

			int caret = textArea.getCaretPosition();

			int firstLine = textArea.getFirstLine();

			int firstOfLine = textArea.getLineStartOffset(
				textArea.getCaretLine());
			int firstVisibleLine = (firstLine == 0 ? 0 :
				firstLine + textArea.getElectricScroll());
			int firstVisible = textArea.getLineStartOffset(
				firstVisibleLine);

			if(caret == 0)
			{
				textArea.getToolkit().beep();
				return;
			}
			else if(!Boolean.TRUE.equals(textArea.getClientProperty(
				SMART_HOME_END_PROPERTY)))
				caret = firstOfLine;
			else if(caret == firstVisible)
				caret = 0;
			else if(caret == firstOfLine)
				caret = firstVisible;
			else
				caret = firstOfLine;

			if(select)
				textArea.select(textArea.getMarkPosition(),caret);
			else
				textArea.setCaretPosition(caret);
		}
		public void actionPerformed(ActionEvent evt)
		{
			JEditTextArea textArea = getTextArea(evt);

			if(!textArea.isEditable())
			{
				textArea.getToolkit().beep();
				return;
			}

			if(textArea.getSelectionStart()
			   != textArea.getSelectionEnd())
			{
				textArea.setSelectedText("");
			}
			else
			{
				int caret = textArea.getCaretPosition();
				if(caret == textArea.getDocumentLength())
				{
					textArea.getToolkit().beep();
					return;
				}
				try
				{
					textArea.getDocument().remove(caret,1);
				}
				catch(BadLocationException bl)
				{
					bl.printStackTrace();
				}
			}
		}
  protected void paintCaret(Graphics gfx, int line, int y) {
    // System.out.println("painting caret " + line + " " + y);
    if (textArea.isCaretVisible()) {
      // System.out.println("caret is visible");
      int offset = textArea.getCaretPosition() - textArea.getLineStartOffset(line);
      int caretX = textArea._offsetToX(line, offset);
      int caretWidth = ((blockCaret || textArea.isOverwriteEnabled()) ? fm.charWidth('w') : 1);
      y += fm.getLeading() + fm.getMaxDescent();
      int height = fm.getHeight();

      // System.out.println("caretX, width = " + caretX + " " + caretWidth);

      gfx.setColor(caretColor);

      if (textArea.isOverwriteEnabled()) {
        gfx.fillRect(caretX, y + height - 1, caretWidth, 1);

      } else {
        // some machines don't like the drawRect for the single
        // pixel caret.. this caused a lot of hell because on that
        // minority of machines, the caret wouldn't show up past
        // the first column. the fix is to use drawLine() in
        // those cases, as a workaround.
        if (caretWidth == 1) {
          gfx.drawLine(caretX, y, caretX, y + height - 1);
        } else {
          gfx.drawRect(caretX, y, caretWidth - 1, height - 1);
        }
        // gfx.drawRect(caretX, y, caretWidth, height - 1);
      }
    }
  }
		public void actionPerformed(ActionEvent evt)
		{
			JEditTextArea textArea = getTextArea(evt);
			int caret = textArea.getCaretPosition();
			if(caret == 0)
			{
				textArea.getToolkit().beep();
				return;
			}

			if(select)
				textArea.select(textArea.getMarkPosition(),
					caret - 1);
			else
				textArea.setCaretPosition(caret - 1);
		}
  protected void paintCaret(Graphics gfx, int line, int y) {
    if (textArea.isCaretVisible()) {
      int offset = textArea.getCaretPosition() - textArea.getLineStartOffset(line);
      int caretX = textArea._offsetToX(line, offset);
      int caretWidth = ((blockCaret || textArea.isOverwriteEnabled()) ? fm.charWidth('w') : 1);
      y += fm.getLeading() + fm.getMaxDescent();
      int height = fm.getHeight();

      gfx.setColor(caretColor);

      if (textArea.isOverwriteEnabled()) {
        gfx.fillRect(caretX, y + height - 1, caretWidth, 1);
      } else {
        gfx.drawRect(caretX, y, caretWidth - 1, height - 1);
      }
    }
  }
		public void actionPerformed(ActionEvent evt)
		{
			JEditTextArea textArea = getTextArea(evt);

			int caret = textArea.getCaretPosition();

			int lastOfLine = textArea.getLineEndOffset(
				textArea.getCaretLine()) - 1;
			int lastVisibleLine = textArea.getFirstLine()
				+ textArea.getVisibleLines();
			if(lastVisibleLine >= textArea.getLineCount())
			{
				lastVisibleLine = Math.min(textArea.getLineCount() - 1,
					lastVisibleLine);
			}
			else
				lastVisibleLine -= (textArea.getElectricScroll() + 1);

			int lastVisible = textArea.getLineEndOffset(lastVisibleLine) - 1;
			int lastDocument = textArea.getDocumentLength();

			if(caret == lastDocument)
			{
				textArea.getToolkit().beep();
				return;
			}
			else if(!Boolean.TRUE.equals(textArea.getClientProperty(
				SMART_HOME_END_PROPERTY)))
				caret = lastOfLine;
			else if(caret == lastVisible)
				caret = lastDocument;
			else if(caret == lastOfLine)
				caret = lastVisible;
			else
				caret = lastOfLine;

			if(select)
				textArea.select(textArea.getMarkPosition(),caret);
			else
				textArea.setCaretPosition(caret);
		}
  /**
   * Replaces the current selection with the replacement string.
   *
   * @param view The view
   * @return True if the operation was successful, false otherwise
   */
  public static boolean replace(View view) {
    // component that will parent any dialog boxes
    Component comp = SearchDialog.getSearchDialog(view);
    if (comp == null) comp = view;

    JEditTextArea textArea = view.getTextArea();

    Buffer buffer = view.getBuffer();
    if (!buffer.isEditable()) return false;

    boolean smartCaseReplace = getSmartCaseReplace();

    Selection[] selection = textArea.getSelection();
    if (selection.length == 0) {
      view.getToolkit().beep();
      return false;
    }

    record(view, "replace(view)", true, false);

    // a little hack for reverse replace and find
    int caret = textArea.getCaretPosition();
    Selection s = textArea.getSelectionAtOffset(caret);
    if (s != null) caret = s.getStart();

    try {
      buffer.beginCompoundEdit();

      SearchMatcher matcher = getSearchMatcher();
      if (matcher == null) return false;

      initReplace();

      int retVal = 0;

      for (int i = 0; i < selection.length; i++) {
        s = selection[i];

        retVal += replaceInSelection(view, textArea, buffer, matcher, smartCaseReplace, s);
      }

      if (reverse) {
        // so that Replace and Find continues from
        // the right location
        textArea.moveCaretPosition(caret);
      } else {
        s = textArea.getSelectionAtOffset(textArea.getCaretPosition());
        if (s != null) textArea.moveCaretPosition(s.getEnd());
      }

      if (!BeanShell.isScriptRunning()) {
        Object[] args = {Integer.valueOf(retVal), Integer.valueOf(1)};
        view.getStatus().setMessageAndClear(jEdit.getProperty("view.status.replace-all", args));
      }

      if (retVal == 0) {
        view.getToolkit().beep();
        return false;
      }

      return true;
    } catch (Exception e) {
      handleError(comp, e);
    } finally {
      buffer.endCompoundEdit();
    }

    return false;
  } // }}}
  /**
   * Finds the next occurrence of the search string.
   *
   * @param view The view
   * @return True if the operation was successful, false otherwise
   */
  public static boolean find(View view) {
    // component that will parent any dialog boxes
    Component comp = SearchDialog.getSearchDialog(view);
    if (comp == null || !comp.isShowing()) comp = view;

    String path = fileset.getNextFile(view, null);
    if (path == null) {
      GUIUtilities.error(comp, "empty-fileset", null);
      return false;
    }

    try {
      view.showWaitCursor();

      SearchMatcher matcher = getSearchMatcher();
      if (matcher == null) {
        view.getToolkit().beep();
        return false;
      }

      record(view, "find(view)", false, true);

      boolean repeat = false;
      loop:
      for (; ; ) {
        while (path != null) {
          Buffer buffer = jEdit.openTemporary(view, null, path, false);

          /* this is stupid and misleading.
           * but 'path' is not used anywhere except
           * the above line, and if this is done
           * after the 'continue', then we will
           * either hang, or be forced to duplicate
           * it inside the buffer == null, or add
           * a 'finally' clause. you decide which one's
           * worse. */
          if (reverse) {
            path = fileset.getPrevFile(view, path);
          } else {
            path = fileset.getNextFile(view, path);
          }

          if (buffer == null) continue loop;

          // Wait for the buffer to load
          if (!buffer.isLoaded()) VFSManager.waitForRequests();

          int start;

          if (view.getBuffer() == buffer && !repeat) {
            JEditTextArea textArea = view.getTextArea();
            Selection s = textArea.getSelectionAtOffset(textArea.getCaretPosition());
            if (s == null) start = textArea.getCaretPosition();
            else if (reverse) start = s.getStart();
            else start = s.getEnd();
          } else if (reverse) start = buffer.getLength();
          else start = 0;

          if (find(view, buffer, start, repeat, reverse)) return true;
        }

        if (repeat) {
          if (!BeanShell.isScriptRunning()) {
            view.getStatus().setMessageAndClear(jEdit.getProperty("view.status.search-not-found"));

            view.getToolkit().beep();
          }
          return false;
        }

        boolean restart;

        // if auto wrap is on, always restart search.
        // if auto wrap is off, and we're called from
        // a macro, stop search. If we're called
        // interactively, ask the user what to do.
        if (wrap) {
          if (!BeanShell.isScriptRunning()) {
            view.getStatus().setMessageAndClear(jEdit.getProperty("view.status.auto-wrap"));
            // beep if beep property set
            if (jEdit.getBooleanProperty("search.beepOnSearchAutoWrap")) {
              view.getToolkit().beep();
            }
          }
          restart = true;
        } else if (BeanShell.isScriptRunning()) {
          restart = false;
        } else {
          Integer[] args = {Integer.valueOf(reverse ? 1 : 0)};
          int result =
              GUIUtilities.confirm(
                  comp,
                  "keepsearching",
                  args,
                  JOptionPane.YES_NO_OPTION,
                  JOptionPane.QUESTION_MESSAGE);
          restart = (result == JOptionPane.YES_OPTION);
        }

        if (restart) {
          // start search from beginning
          path = fileset.getFirstFile(view);
          repeat = true;
        } else break loop;
      }
    } catch (Exception e) {
      handleError(comp, e);
    } finally {
      view.hideWaitCursor();
    }

    return false;
  } // }}}