/**
   * 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;
  } // }}}
  /**
   * Finds the next instance of the search string in the specified buffer.
   *
   * @param view The view
   * @param buffer The buffer
   * @param start Location where to start the search
   * @param firstTime See {@link
   *     SearchMatcher#nextMatch(CharSequence,boolean,boolean,boolean,boolean)}.
   * @since jEdit 4.1pre7
   */
  public static boolean find(
      View view, Buffer buffer, int start, boolean firstTime, boolean reverse) throws Exception {

    EditBus.send(new PositionChanging(view.getEditPane()));

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

    CharSequence text;
    boolean startOfLine;
    boolean endOfLine;
    if (reverse) {
      text = new ReverseCharSequence(buffer.getSegment(0, start));
      startOfLine = true;
      endOfLine = (buffer.getLineEndOffset(buffer.getLineOfOffset(start)) - 1 == start);
    } else {
      text = buffer.getSegment(start, buffer.getLength() - start);
      startOfLine = (buffer.getLineStartOffset(buffer.getLineOfOffset(start)) == start);
      endOfLine = true;
    }

    String noWordSep = buffer.getStringProperty("noWordSep");
    matcher.setNoWordSep(noWordSep);
    SearchMatcher.Match match = matcher.nextMatch(text, startOfLine, endOfLine, firstTime, reverse);
    if (match != null) {
      jEdit.commitTemporary(buffer);
      view.setBuffer(buffer, true);
      JEditTextArea textArea = view.getTextArea();

      if (reverse) {
        textArea.setSelection(new Selection.Range(start - match.end, start - match.start));
        // make sure end of match is visible
        textArea.scrollTo(start - match.start, false);
        textArea.moveCaretPosition(start - match.end);
      } else {
        textArea.setSelection(new Selection.Range(start + match.start, start + match.end));
        textArea.moveCaretPosition(start + match.end);
        // make sure start of match is visible
        textArea.scrollTo(start + match.start, false);
      }

      return true;
    } else return false;
  } // }}}
  /**
   * 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;
  } // }}}
  /**
   * 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;
  } // }}}
 /** Should be somewhere else... */
 private static int getColumnOnOtherLine(Buffer buffer, int line, int col) {
   int returnValue = buffer.getOffsetOfVirtualColumn(line, col, null);
   if (returnValue == -1) return buffer.getLineEndOffset(line) - 1;
   else return buffer.getLineStartOffset(line) + returnValue;
 } // }}}
Example #7
0
  // {{{ run() method
  public void run() {
    /* if the VFS supports renaming files, we first
     * save to #<filename>#save#, then rename that
     * to <filename>, so that if the save fails,
     * data will not be lost.
     *
     * as of 4.1pre7 we now call vfs.getTwoStageSaveName()
     * instead of constructing the path directly
     * since some VFS's might not allow # in filenames.
     */

    boolean vfsRenameCap = (vfs.getCapabilities() & VFS.RENAME_CAP) != 0;

    boolean wantTwoStage = wantTwoStageSave(buffer);
    boolean twoStageSave = vfsRenameCap && wantTwoStage;

    try {
      String[] args = {vfs.getFileName(path)};
      setStatus(jEdit.getProperty("vfs.status.save", args));

      // the entire save operation can be aborted...
      setAbortable(true);

      path = vfs._canonPath(session, path, view);
      if (!MiscUtilities.isURL(path)) path = MiscUtilities.resolveSymlinks(path);

      String savePath;
      if (twoStageSave) {
        savePath = vfs.getTwoStageSaveName(path);
        if (savePath == null) {
          throw new IOException("Can't get a temporary path for two-stage save: " + path);
        }
      } else {
        makeBackup();
        savePath = path;
      }

      OutputStream out = vfs._createOutputStream(session, savePath, view);
      if (out == null) {
        buffer.setBooleanProperty(ERROR_OCCURRED, true);
        return;
      }
      try {
        // this must be after the stream is created or
        // we deadlock with SSHTools.
        buffer.readLock();
        try {
          // Can't use buffer.getName() here because
          // it is not changed until the save is
          // complete
          if (path.endsWith(".gz")) buffer.setBooleanProperty(Buffer.GZIPPED, true);
          else if (buffer.getName().endsWith(".gz")) {
            // The path do not ends with gz.
            // The buffer name was .gz.
            // So it means it's blabla.txt.gz -> blabla.txt, I remove
            // the gz property
            buffer.setBooleanProperty(Buffer.GZIPPED, false);
          }

          if (buffer.getBooleanProperty(Buffer.GZIPPED)) out = new GZIPOutputStream(out);

          write(buffer, out);
        } finally {
          buffer.readUnlock();
        }
      } finally {
        IOUtilities.closeQuietly(out);
      }

      if (twoStageSave) {
        makeBackup();
        if (!vfs._rename(session, savePath, path, view))
          throw new IOException("Rename failed: " + savePath);
      }

      if (!twoStageSave) VFSManager.sendVFSUpdate(vfs, path, true);
    } catch (FileNotFoundException e) {
      Log.log(Log.ERROR, this, "Unable to save buffer " + e);
      String[] pp = {e.getMessage()};
      VFSManager.error(view, path, "ioerror.write-error", pp);

      buffer.setBooleanProperty(ERROR_OCCURRED, true);
    } catch (UnsupportedCharsetException e) {
      Log.log(Log.ERROR, this, e, e);
      String[] pp = {e.getCharsetName()};
      VFSManager.error(view, path, "ioerror.unsupported-encoding-error", pp);

      buffer.setBooleanProperty(ERROR_OCCURRED, true);
    } catch (Exception e) {
      Log.log(Log.ERROR, this, e);
      String[] pp = {e.toString()};
      VFSManager.error(view, path, "ioerror.write-error", pp);

      buffer.setBooleanProperty(ERROR_OCCURRED, true);
    } catch (WorkThread.Abort a) {
      buffer.setBooleanProperty(ERROR_OCCURRED, true);
    } finally {
      try {
        vfs._saveComplete(session, buffer, path, view);
        if (twoStageSave) {
          vfs._finishTwoStageSave(session, buffer, path, view);
        }
        // clean up left-over markers file
        if (!jEdit.getBooleanProperty("persistentMarkers"))
          vfs._delete(session, Buffer.getMarkersPath(vfs, path), view);
        vfs._endVFSSession(session, view);
      } catch (Exception e) {
        Log.log(Log.ERROR, this, e);
        String[] pp = {e.toString()};
        VFSManager.error(view, path, "ioerror.write-error", pp);

        buffer.setBooleanProperty(ERROR_OCCURRED, true);
      } catch (WorkThread.Abort a) {
        buffer.setBooleanProperty(ERROR_OCCURRED, true);
      }
    }
  } // }}}
Example #8
0
 // {{{ wantTwoStageSave() method
 private static boolean wantTwoStageSave(Buffer buffer) {
   return !buffer.getBooleanProperty("forbidTwoStageSave")
       && (buffer.getBooleanProperty("overwriteReadonly")
           || jEdit.getBooleanProperty("twoStageSave"));
 } // }}}