private boolean findEntry() {
    Cursor waitCursor = new Cursor(shell.getDisplay(), SWT.CURSOR_WAIT);
    shell.setCursor(waitCursor);

    boolean matchCase = searchDialog.getMatchCase();
    boolean matchWord = searchDialog.getMatchWord();
    String searchString = searchDialog.getSearchString();
    int column = searchDialog.getSelectedSearchArea();

    searchString = matchCase ? searchString : searchString.toLowerCase();

    boolean found = false;
    if (searchDialog.getSearchDown()) {
      for (int i = table.getSelectionIndex() + 1; i < table.getItemCount(); i++) {
        if (found = findMatch(searchString, table.getItem(i), column, matchWord, matchCase)) {
          table.setSelection(i);
          break;
        }
      }
    } else {
      for (int i = table.getSelectionIndex() - 1; i > -1; i--) {
        if (found = findMatch(searchString, table.getItem(i), column, matchWord, matchCase)) {
          table.setSelection(i);
          break;
        }
      }
    }

    shell.setCursor(null);
    if (waitCursor != null) waitCursor.dispose();

    return found;
  }
  private boolean save() {
    if (file == null) return saveAs();

    Cursor waitCursor = new Cursor(shell.getDisplay(), SWT.CURSOR_WAIT);
    shell.setCursor(waitCursor);

    TableItem[] items = table.getItems();
    String[] lines = new String[items.length];
    for (int i = 0; i < items.length; i++) {
      String[] itemText = new String[table.getColumnCount()];
      for (int j = 0; j < itemText.length; j++) {
        itemText[j] = items[i].getText(j);
      }
      lines[i] = encodeLine(itemText);
    }

    FileWriter fileWriter = null;
    try {
      fileWriter = new FileWriter(file.getAbsolutePath(), false);
      for (int i = 0; i < lines.length; i++) {
        fileWriter.write(lines[i]);
      }
    } catch (FileNotFoundException e) {
      displayError(resMessages.getString("File_not_found") + "\n" + file.getName());
      return false;
    } catch (IOException e) {
      displayError(resMessages.getString("IO_error_write") + "\n" + file.getName());
      return false;
    } finally {
      shell.setCursor(null);
      waitCursor.dispose();

      if (fileWriter != null) {
        try {
          fileWriter.close();
        } catch (IOException e) {
          displayError(resMessages.getString("IO_error_close") + "\n" + file.getName());
          return false;
        }
      }
    }

    shell.setText(resMessages.getString("Title_bar") + file.getName());
    isModified = false;
    return true;
  }
  /**
   * Displays the Tracker rectangles for manipulation by the user. Returns when the user has either
   * finished manipulating the rectangles or has cancelled the Tracker.
   *
   * @return <code>true</code> if the user did not cancel the Tracker, <code>false</code> otherwise
   * @exception SWTException
   *     <ul>
   *       <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
   *       <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
   *     </ul>
   */
  public boolean open() {
    checkWidget();
    Display display = this.display;
    cancelled = false;
    tracking = true;
    window = (NSWindow) new NSWindow().alloc();
    NSArray screens = NSScreen.screens();
    double /*float*/ minX = Float.MAX_VALUE, maxX = Float.MIN_VALUE;
    double /*float*/ minY = Float.MAX_VALUE, maxY = Float.MIN_VALUE;
    int count = (int) /*64*/ screens.count();
    for (int i = 0; i < count; i++) {
      NSScreen screen = new NSScreen(screens.objectAtIndex(i));
      NSRect frame = screen.frame();
      double /*float*/ x1 = frame.x, x2 = frame.x + frame.width;
      double /*float*/ y1 = frame.y, y2 = frame.y + frame.height;
      if (x1 < minX) minX = x1;
      if (x2 < minX) minX = x2;
      if (x1 > maxX) maxX = x1;
      if (x2 > maxX) maxX = x2;
      if (y1 < minY) minY = y1;
      if (y2 < minY) minY = y2;
      if (y1 > maxY) maxY = y1;
      if (y2 > maxY) maxY = y2;
    }
    NSRect frame = new NSRect();
    frame.x = minX;
    frame.y = minY;
    frame.width = maxX - minX;
    frame.height = maxY - minY;
    window =
        window.initWithContentRect(
            frame, OS.NSBorderlessWindowMask, OS.NSBackingStoreBuffered, false);
    window.setOpaque(false);
    window.setLevel(OS.NSStatusWindowLevel);
    window.setContentView(null);
    window.setBackgroundColor(NSColor.clearColor());
    NSGraphicsContext context = window.graphicsContext();
    NSGraphicsContext.static_saveGraphicsState();
    NSGraphicsContext.setCurrentContext(context);
    context.setCompositingOperation(OS.NSCompositeClear);
    frame.x = frame.y = 0;
    NSBezierPath.fillRect(frame);
    NSGraphicsContext.static_restoreGraphicsState();
    window.orderFrontRegardless();

    drawRectangles(window, rectangles, false);

    /*
     * If exactly one of UP/DOWN is specified as a style then set the cursor
     * orientation accordingly (the same is done for LEFT/RIGHT styles below).
     */
    int vStyle = style & (SWT.UP | SWT.DOWN);
    if (vStyle == SWT.UP || vStyle == SWT.DOWN) {
      cursorOrientation |= vStyle;
    }
    int hStyle = style & (SWT.LEFT | SWT.RIGHT);
    if (hStyle == SWT.LEFT || hStyle == SWT.RIGHT) {
      cursorOrientation |= hStyle;
    }

    Point cursorPos;
    boolean down = false;
    NSApplication application = NSApplication.sharedApplication();
    NSEvent currentEvent = application.currentEvent();
    if (currentEvent != null) {
      switch ((int) /*64*/ currentEvent.type()) {
        case OS.NSLeftMouseDown:
        case OS.NSLeftMouseDragged:
        case OS.NSRightMouseDown:
        case OS.NSRightMouseDragged:
        case OS.NSOtherMouseDown:
        case OS.NSOtherMouseDragged:
          down = true;
      }
    }
    if (down) {
      cursorPos = display.getCursorLocation();
    } else {
      if ((style & SWT.RESIZE) != 0) {
        cursorPos = adjustResizeCursor(true);
      } else {
        cursorPos = adjustMoveCursor();
      }
    }
    if (cursorPos != null) {
      oldX = cursorPos.x;
      oldY = cursorPos.y;
    }

    Control oldTrackingControl = display.trackingControl;
    display.trackingControl = null;
    /* Tracker behaves like a Dialog with its own OS event loop. */
    while (tracking && !cancelled) {
      display.addPool();
      try {
        if (parent != null && parent.isDisposed()) break;
        display.runSkin();
        display.runDeferredLayouts();
        NSEvent event =
            application.nextEventMatchingMask(
                0, NSDate.distantFuture(), OS.NSDefaultRunLoopMode, true);
        if (event == null) continue;
        int type = (int) /*64*/ event.type();
        switch (type) {
          case OS.NSLeftMouseUp:
          case OS.NSRightMouseUp:
          case OS.NSOtherMouseUp:
          case OS.NSMouseMoved:
          case OS.NSLeftMouseDragged:
          case OS.NSRightMouseDragged:
          case OS.NSOtherMouseDragged:
            mouse(event);
            break;
          case OS.NSKeyDown:
          case OS.NSKeyUp:
          case OS.NSFlagsChanged:
            key(event);
            break;
        }
        boolean dispatch = true;
        switch (type) {
          case OS.NSLeftMouseDown:
          case OS.NSLeftMouseUp:
          case OS.NSRightMouseDown:
          case OS.NSRightMouseUp:
          case OS.NSOtherMouseDown:
          case OS.NSOtherMouseUp:
          case OS.NSMouseMoved:
          case OS.NSLeftMouseDragged:
          case OS.NSRightMouseDragged:
          case OS.NSOtherMouseDragged:
          case OS.NSMouseEntered:
          case OS.NSMouseExited:
          case OS.NSKeyDown:
          case OS.NSKeyUp:
          case OS.NSFlagsChanged:
            dispatch = false;
        }
        if (dispatch) application.sendEvent(event);
        if (clientCursor != null && resizeCursor == null) {
          display.lockCursor = false;
          clientCursor.handle.set();
          display.lockCursor = true;
        }
        display.runAsyncMessages(false);
      } finally {
        display.removePool();
      }
    }

    /*
     * Cleanup: If this tracker was resizing then the last cursor that it created
     * needs to be destroyed.
     */
    if (resizeCursor != null) resizeCursor.dispose();
    resizeCursor = null;

    if (oldTrackingControl != null && !oldTrackingControl.isDisposed()) {
      display.trackingControl = oldTrackingControl;
    }
    display.setCursor(display.findControl(true));
    if (!isDisposed()) {
      drawRectangles(window, rectangles, true);
    }
    if (window != null) window.close();
    tracking = false;
    window = null;
    return !cancelled;
  }
  Point adjustResizeCursor(boolean movePointer) {
    if (bounds == null) return null;
    int newX, newY;

    if ((cursorOrientation & SWT.LEFT) != 0) {
      newX = bounds.x;
    } else if ((cursorOrientation & SWT.RIGHT) != 0) {
      newX = bounds.x + bounds.width;
    } else {
      newX = bounds.x + bounds.width / 2;
    }

    if ((cursorOrientation & SWT.UP) != 0) {
      newY = bounds.y;
    } else if ((cursorOrientation & SWT.DOWN) != 0) {
      newY = bounds.y + bounds.height;
    } else {
      newY = bounds.y + bounds.height / 2;
    }

    /*
     * Convert to screen coordinates if needed
     */
    if (parent != null) {
      Point pt = parent.toDisplay(newX, newY);
      newX = pt.x;
      newY = pt.y;
    }
    if (movePointer) {
      display.setCursorLocation(newX, newY);
    }

    /*
     * If the client has not provided a custom cursor then determine
     * the appropriate resize cursor.
     */
    if (clientCursor == null) {
      Cursor newCursor = null;
      switch (cursorOrientation) {
        case SWT.UP:
          newCursor = new Cursor(display, SWT.CURSOR_SIZENS);
          break;
        case SWT.DOWN:
          newCursor = new Cursor(display, SWT.CURSOR_SIZENS);
          break;
        case SWT.LEFT:
          newCursor = new Cursor(display, SWT.CURSOR_SIZEWE);
          break;
        case SWT.RIGHT:
          newCursor = new Cursor(display, SWT.CURSOR_SIZEWE);
          break;
        case SWT.LEFT | SWT.UP:
          newCursor = new Cursor(display, SWT.CURSOR_SIZENWSE);
          break;
        case SWT.RIGHT | SWT.DOWN:
          newCursor = new Cursor(display, SWT.CURSOR_SIZENWSE);
          break;
        case SWT.LEFT | SWT.DOWN:
          newCursor = new Cursor(display, SWT.CURSOR_SIZENESW);
          break;
        case SWT.RIGHT | SWT.UP:
          newCursor = new Cursor(display, SWT.CURSOR_SIZENESW);
          break;
        default:
          newCursor = new Cursor(display, SWT.CURSOR_SIZEALL);
          break;
      }
      display.lockCursor = false;
      newCursor.handle.set();
      display.lockCursor = true;
      if (resizeCursor != null) {
        resizeCursor.dispose();
      }
      resizeCursor = newCursor;
    }

    return new Point(newX, newY);
  }
  private void openAddressBook(String name) {
    if (name == null) return;
    File file = new File(name);
    if (!file.exists()) {
      displayError(
          resMessages.getString("File")
              + file.getName()
              + " "
              + resMessages.getString("Does_not_exist"));
      return;
    }

    Cursor waitCursor = new Cursor(shell.getDisplay(), SWT.CURSOR_WAIT);
    shell.setCursor(waitCursor);

    FileReader fileReader = null;
    BufferedReader bufferedReader = null;
    String[] data = new String[0];
    try {
      fileReader = new FileReader(file.getAbsolutePath());
      bufferedReader = new BufferedReader(fileReader);
      String nextLine = bufferedReader.readLine();
      while (nextLine != null) {
        String[] newData = new String[data.length + 1];
        System.arraycopy(data, 0, newData, 0, data.length);
        newData[data.length] = nextLine;
        data = newData;
        nextLine = bufferedReader.readLine();
      }
    } catch (FileNotFoundException e) {
      displayError(resMessages.getString("File_not_found") + "\n" + file.getName());
      return;
    } catch (IOException e) {
      displayError(resMessages.getString("IO_error_read") + "\n" + file.getName());
      return;
    } finally {

      shell.setCursor(null);
      waitCursor.dispose();

      if (fileReader != null) {
        try {
          fileReader.close();
        } catch (IOException e) {
          displayError(resMessages.getString("IO_error_close") + "\n" + file.getName());
          return;
        }
      }
    }

    String[][] tableInfo = new String[data.length][table.getColumnCount()];
    for (int i = 0; i < data.length; i++) {
      tableInfo[i] = decodeLine(data[i]);
    }

    Arrays.sort(tableInfo, new RowComparator(0));

    for (int i = 0; i < tableInfo.length; i++) {
      TableItem item = new TableItem(table, SWT.NONE);
      item.setText(tableInfo[i]);
    }
    shell.setText(resMessages.getString("Title_bar") + file.getName());
    isModified = false;
    this.file = file;
  }