/**
   * Replaces text in the specified range with the replacement string.
   *
   * @param view The view
   * @param buffer The buffer
   * @param start The start offset
   * @param end The end offset
   * @return True if the operation was successful, false otherwise
   */
  public static boolean replace(View view, Buffer buffer, int start, int end) {
    if (!buffer.isEditable()) return false;

    // component that will parent any dialog boxes
    Component comp = SearchDialog.getSearchDialog(view);
    if (comp == null) comp = view;

    boolean smartCaseReplace = getSmartCaseReplace();

    try {
      buffer.beginCompoundEdit();

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

      initReplace();

      int retVal = 0;

      retVal += _replace(view, buffer, matcher, start, end, smartCaseReplace);

      if (retVal != 0) return true;
    } catch (Exception e) {
      handleError(comp, e);
    } finally {
      buffer.endCompoundEdit();
    }

    return false;
  } // }}}
 /**
  * insert text.
  *
  * <p>/** invokes an Action.
  *
  * @param view The view to run the script in.
  * @param node The node item
  * @param text The node content to be inserted.
  */
 public static void insertText(View view, String text, XTreeNode node) {
   CommandQueue queue = new CommandQueue();
   ScriptContext context = new ScriptContext(view, node, queue);
   Buffer buffer = view.getBuffer();
   buffer.beginCompoundEdit();
   InsertTextCommand.insertText(text, context);
   buffer.endCompoundEdit();
 }
 /**
  * runs an XInsertScript.
  *
  * @param view The view to run the script in.
  * @param script The node content to be run as a script.
  * @param node The node from where to start searching for variable substitutions
  */
 public static void runXInsertScript(View view, String script, XTreeNode node) {
   CommandQueue queue = new CommandQueue();
   Buffer buffer = view.getBuffer();
   buffer.beginCompoundEdit();
   try {
     char[] chars = script.toCharArray();
     int start = 0;
     for (int i = start; i < chars.length; i++) {
       switch (chars[i]) {
         case '{':
           if (chars[i + 1] == '$'
               || chars[i + 1] == '@'
               || chars[i + 1] == '!'
               || chars[i + 1] == '%'
               || chars[i + 1] == '#'
               || chars[i + 1] == '*'
               || chars[i + 1] == '&') {
             // Log.log(Log.DEBUG, XScripter.class, "Adding insert text (\"" + text + "\") command
             // to queue");
             // Insert the text between the last command and this one
             String text = script.substring(start, i);
             queue.add(new InsertTextCommand(text));
             int j;
             inner:
             for (j = i; j < chars.length; j++) {
               if (chars[j] == '}' && chars[j - 1] != '\\') { // If end of command
                 String cmd = script.substring(i + 1, j);
                 cmd = Utilities.replace(cmd, "\\}", "}");
                 queue.add(getCommand(view, node, cmd)); // Add this command to queue
                 break inner;
               }
             }
             i = j; // set parsing to continue at the end of the command
             start = j + 1; // set the start position for the next insert text command
           }
           break;
       }
     }
     String remainder = script.substring(start, script.length());
     queue.add(new InsertTextCommand(remainder)); // Insert the text left over
     // Run commands in queue
     ScriptContext context = new ScriptContext(view, node, queue);
     queue.executeAll(context);
   } catch (StringIndexOutOfBoundsException e) {
     doError("Unknown", "Missing \"}\"");
     return;
   } catch (Exception e) {
     doError("Unknown", "Syntax error in script - Execution Aborted", e);
     return;
   } finally {
     buffer.endCompoundEdit();
   }
 } // }}}
  /**
   * Replaces all occurrences of the search string with the replacement string.
   *
   * @param view The view
   * @param dontOpenChangedFiles Whether to open changed files or to autosave them quietly
   * @return the number of modified files
   */
  public static boolean replaceAll(View view, boolean dontOpenChangedFiles) {
    // component that will parent any dialog boxes
    Component comp = SearchDialog.getSearchDialog(view);
    if (comp == null) comp = view;

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

    record(view, "replaceAll(view)", true, true);

    view.showWaitCursor();

    boolean smartCaseReplace = getSmartCaseReplace();

    int fileCount = 0;
    int occurCount = 0;
    try {
      SearchMatcher matcher = getSearchMatcher();
      if (matcher == null) return false;

      initReplace();

      String path = fileset.getFirstFile(view);
      loop:
      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. */
        path = fileset.getNextFile(view, path);

        if (buffer == null) continue loop;

        // Wait for buffer to finish loading
        if (buffer.isPerformingIO()) VFSManager.waitForRequests();

        if (!buffer.isEditable()) continue loop;

        // Leave buffer in a consistent state if
        // an error occurs
        int retVal = 0;

        try {
          buffer.beginCompoundEdit();
          retVal = _replace(view, buffer, matcher, 0, buffer.getLength(), smartCaseReplace);
        } finally {
          buffer.endCompoundEdit();
        }

        if (retVal != 0) {
          fileCount++;
          occurCount += retVal;
          if (dontOpenChangedFiles) {
            buffer.save(null, null);
          } else {
            jEdit.commitTemporary(buffer);
            jEdit.getBufferSetManager().addBuffer(view, buffer);
          }
        }
      }
    } catch (Exception e) {
      handleError(comp, e);
    } finally {
      view.hideWaitCursor();
    }

    /* Don't do this when playing a macro, cos it's annoying */
    if (!BeanShell.isScriptRunning()) {
      Object[] args = {Integer.valueOf(occurCount), Integer.valueOf(fileCount)};
      view.getStatus().setMessageAndClear(jEdit.getProperty("view.status.replace-all", args));
      if (occurCount == 0) view.getToolkit().beep();
    }

    return (fileCount != 0);
  } // }}}
  /**
   * 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;
  } // }}}