private int getCorrectionOffset(FilePanel fp) {
    JTextComponent editor;
    int offset;
    Rectangle rect;
    Point p;
    JViewport viewport;

    editor = fp.getEditor();
    viewport = fp.getScrollPane().getViewport();
    p = viewport.getViewPosition();
    offset = editor.viewToModel(p);

    try {
      // This happens when you scroll to the bottom. The upper line won't
      //   start at the right position (You can see half of the line)
      // Correct this offset with the pane next to it to keep in sync.
      rect = editor.modelToView(offset);
      if (rect != null) {
        return p.y - rect.getLocation().y;
      }
    } catch (Exception ex) {
      ex.printStackTrace();
    }

    return 0;
  }
  private int getCurrentLineCenter(FilePanel fp) {
    JScrollPane scrollPane;
    BufferDocumentIF bd;
    JTextComponent editor;
    JViewport viewport;
    int line;
    Rectangle rect;
    int offset;
    Point p;

    editor = fp.getEditor();
    scrollPane = fp.getScrollPane();
    viewport = scrollPane.getViewport();
    p = viewport.getViewPosition();
    offset = editor.viewToModel(p);

    // Scroll around the center of the editpane
    p.y += getHeightOffset(fp);

    offset = editor.viewToModel(p);
    bd = fp.getBufferDocument();
    if (bd == null) {
      return -1;
    }
    line = bd.getLineForOffset(offset);

    return line;
  }
  public void scrollToLine(FilePanel fp, int line) {
    JScrollPane scrollPane;
    FilePanel fp2;
    BufferDocumentIF bd;
    JTextComponent editor;
    JViewport viewport;
    Rectangle rect;
    int offset;
    Point p;
    Rectangle viewRect;
    Dimension viewSize;
    Dimension extentSize;
    int x;

    fp2 = fp == filePanelLeft ? filePanelRight : filePanelLeft;

    bd = fp.getBufferDocument();
    if (bd == null) {
      return;
    }

    offset = bd.getOffsetForLine(line);
    if (offset < 0) {
      return;
    }

    viewport = fp.getScrollPane().getViewport();
    editor = fp.getEditor();

    try {
      rect = editor.modelToView(offset);
      if (rect == null) {
        return;
      }

      p = rect.getLocation();
      p.y -= getHeightOffset(fp);
      p.y += getCorrectionOffset(fp2);

      // Do not allow scrolling before the begin.
      if (p.y < 0) {
        p.y = 0;
      }

      // Do not allow scrolling after the end.
      viewSize = viewport.getViewSize();
      viewRect = viewport.getViewRect();
      extentSize = viewport.getExtentSize();
      if (p.y > viewSize.height - extentSize.height) {
        p.y = viewSize.height - extentSize.height;
      }

      p.x = viewRect.x;

      viewport.setViewPosition(p);
    } catch (Exception ex) {
      ex.printStackTrace();
    }
  }
  private void init() {
    JScrollBar o;
    JScrollBar r;

    // Synchronize the horizontal scrollbars:
    o = filePanelLeft.getScrollPane().getHorizontalScrollBar();
    r = filePanelRight.getScrollPane().getHorizontalScrollBar();
    r.addAdjustmentListener(getHorizontalAdjustmentListener());
    o.addAdjustmentListener(getHorizontalAdjustmentListener());

    // Synchronize the vertical scrollbars:
    o = filePanelLeft.getScrollPane().getVerticalScrollBar();
    r = filePanelRight.getScrollPane().getVerticalScrollBar();
    r.addAdjustmentListener(getVerticalAdjustmentListener());
    o.addAdjustmentListener(getVerticalAdjustmentListener());
  }
  private int getHeightOffset(FilePanel fp) {
    JScrollPane scrollPane;
    JViewport viewport;
    int offset;
    int unitIncrement;

    scrollPane = fp.getScrollPane();
    viewport = scrollPane.getViewport();

    offset = viewport.getSize().height / 2;
    unitIncrement = scrollPane.getHorizontalScrollBar().getUnitIncrement();
    offset = offset - (offset % unitIncrement);

    return offset;
  }