Exemplo n.º 1
0
  // {{{ read() method
  protected SegmentBuffer read(Reader in, long length, boolean insert) throws IOException {
    /* we guess an initial size for the array */
    IntegerArray endOffsets = new IntegerArray(Math.max(1, (int) (length / 50)));

    // only true if the file size is known
    boolean trackProgress = !buffer.isTemporary() && length != 0;

    if (trackProgress) {
      setMaximum(length);
      setValue(0);
    }

    // if the file size is not known, start with a resonable
    // default buffer size
    if (length == 0) length = IOBUFSIZE;

    SegmentBuffer seg = new SegmentBuffer((int) length + 1);

    char[] buf = new char[IOBUFSIZE];

    /* Number of characters in 'buf' array.
    InputStream.read() doesn't always fill the
    array (eg, the file size is not a multiple of
    IOBUFSIZE, or it is a GZipped file, etc) */
    int len;

    // True if a \n was read after a \r. Usually
    // means this is a DOS/Windows file
    boolean CRLF = false;

    // A \r was read, hence a MacOS file
    boolean CROnly = false;

    // Was the previous read character a \r?
    // If we read a \n and this is true, we assume
    // we have a DOS/Windows file
    boolean lastWasCR = false;

    // Number of lines read. Every 100 lines, we update the
    // progress bar
    int lineCount = 0;

    while ((len = in.read(buf, 0, buf.length)) != -1) {
      // Offset of previous line, relative to
      // the start of the I/O buffer (NOT
      // relative to the start of the document)
      int lastLine = 0;

      for (int i = 0; i < len; i++) {
        // Look for line endings.
        switch (buf[i]) {
          case '\r':
            // If we read a \r and
            // lastWasCR is also true,
            // it is probably a Mac file
            // (\r\r in stream)
            if (lastWasCR) {
              CROnly = true;
              CRLF = false;
            }
            // Otherwise set a flag,
            // so that \n knows that last
            // was a \r
            else {
              lastWasCR = true;
            }

            // Insert a line
            seg.append(buf, lastLine, i - lastLine);
            seg.append('\n');
            endOffsets.add(seg.count);
            if (trackProgress && lineCount++ % PROGRESS_INTERVAL == 0) setValue(seg.count);

            // This is i+1 to take the
            // trailing \n into account
            lastLine = i + 1;
            break;
          case '\n':
            /* If lastWasCR is true, we just read a \r followed
            by a \n. We specify that this is a Windows file,
            but take no further action and just ignore the \r. */
            if (lastWasCR) {
              CROnly = false;
              CRLF = true;
              lastWasCR = false;
              /* Bump lastLine so that the next line doesn't erronously
              pick up the \r */
              lastLine = i + 1;
            }
            /* Otherwise, we found a \n that follows some other
             *  character, hence we have a Unix file */
            else {
              CROnly = false;
              CRLF = false;
              seg.append(buf, lastLine, i - lastLine);
              seg.append('\n');
              endOffsets.add(seg.count);
              if (trackProgress && lineCount++ % PROGRESS_INTERVAL == 0) setValue(seg.count);
              lastLine = i + 1;
            }
            break;
          default:
            /*  If we find some other character that follows
            a \r, so it is not a Windows file, and probably
            a Mac file */
            if (lastWasCR) {
              CROnly = true;
              CRLF = false;
              lastWasCR = false;
            }
            break;
        }
      }

      if (trackProgress) setValue(seg.count);

      // Add remaining stuff from buffer
      seg.append(buf, lastLine, len - lastLine);
    }

    setAbortable(false);

    String lineSeparator;
    if (seg.count == 0) {
      // fix for "[ 865589 ] 0-byte files should open using
      // the default line seperator"
      lineSeparator =
          jEdit.getProperty("buffer.lineSeparator", System.getProperty("line.separator"));
    } else if (CRLF) lineSeparator = "\r\n";
    else if (CROnly) lineSeparator = "\r";
    else lineSeparator = "\n";

    // Chop trailing newline and/or ^Z (if any)
    int bufferLength = seg.count;
    if (bufferLength != 0) {
      char ch = seg.array[bufferLength - 1];
      if (ch == 0x1a /* DOS ^Z */) seg.count--;
    }

    buffer.setBooleanProperty(Buffer.TRAILING_EOL, false);
    if (bufferLength != 0 && jEdit.getBooleanProperty("stripTrailingEOL")) {
      char ch = seg.array[bufferLength - 1];
      if (ch == '\n') {
        buffer.setBooleanProperty(Buffer.TRAILING_EOL, true);
        seg.count--;
        endOffsets.setSize(endOffsets.getSize() - 1);
      }
    }

    // add a line marker at the end for proper offset manager
    // operation
    endOffsets.add(seg.count + 1);

    // to avoid having to deal with read/write locks and such,
    // we insert the loaded data into the buffer in the
    // post-load cleanup runnable, which runs in the AWT thread.
    if (!insert) {
      buffer.setProperty(LOAD_DATA, seg);
      buffer.setProperty(END_OFFSETS, endOffsets);
      buffer.setProperty(NEW_PATH, path);
      if (lineSeparator != null) buffer.setProperty(JEditBuffer.LINESEP, lineSeparator);
    }

    // used in insert()
    return seg;
  } // }}}