if (!isDisposed ()) drawRectangles (rectangles);
if (!isDisposed ()) drawRectangles (rectangles, stippled);
public boolean open () {	checkWidget();	if (rectangles == null) return false;		int input_group = OS.PhInputGroup (0);	PhCursorInfo_t info = new PhCursorInfo_t ();	OS.PhQueryCursor ((short)input_group, info);		if ((style & SWT.MENU) == 0) {		/*		* This code is intentionally commented. Tracking can happen through		* the keyboard.		*///		if ((info.button_state & OS.Ph_BUTTON_SELECT) == 0) return false;	}		int region = 0;	if (info.dragger == 0) {		PhRect_t rect = new PhRect_t ();		OS.PhWindowQueryVisible (OS.Ph_QUERY_CONSOLE, 0, OS.PhInputGroup (0), rect);		int sense = OS.Ph_EV_DRAG | OS.Ph_EV_KEY | OS.Ph_EV_BUT_PRESS |			OS.Ph_EV_BUT_RELEASE | OS.Ph_EV_PTR_MOTION;		int [] args = {			OS.Pt_ARG_WIDTH, rect.lr_x - rect.ul_x + 1, 0,			OS.Pt_ARG_HEIGHT, rect.lr_y - rect.ul_y + 1, 0,			OS.Pt_ARG_REGION_OPAQUE, 0, ~0,			OS.Pt_ARG_REGION_SENSE, sense, ~0,			OS.Pt_ARG_REGION_FLAGS, OS.Ph_FORCE_BOUNDARY, OS.Ph_FORCE_BOUNDARY,			OS.Pt_ARG_FILL_COLOR, OS.Pg_TRANSPARENT, 0,		};		region = OS.PtCreateWidget (OS.PtRegion (), OS.Pt_NO_PARENT, args.length / 3, args);		OS.PtRealizeWidget (region);			rect = new PhRect_t ();		int rid = OS.PtWidgetRid (region);		OS.PhInitDrag (rid, OS.Ph_DRAG_KEY_MOTION | OS.Ph_TRACK_DRAG, rect, null, input_group, null, null, null, null, null);	}	int oldX, oldY;	int size = PhEvent_t.sizeof + 1024;	int buffer = OS.malloc (size);	PhEvent_t phEvent = new PhEvent_t ();	Event event = new Event ();	Point cursorPos;		// 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;	}	drawRectangles (rectangles);	if ((style & SWT.MENU) == 0) {		oldX = info.pos_x;		oldY = info.pos_y;	} else {		if ((style & SWT.RESIZE) != 0) {			cursorPos = adjustResizeCursor ();		} else {			cursorPos = adjustMoveCursor ();		}		oldX = cursorPos.x;		oldY = cursorPos.y;	}		tracking = true;	boolean cancelled = false;	while (tracking && !cancelled) {		if (parent != null && parent.isDisposed ()) break;		int result = OS.PhEventNext (buffer, size);		switch (result) {			case OS.Ph_EVENT_MSG: break;			case OS.Ph_RESIZE_MSG:				size = OS.PhGetMsgSize (buffer);				OS.free (buffer);				buffer = OS.malloc (size);				continue;		}		OS.memmove (phEvent, buffer, PhEvent_t.sizeof);		if (phEvent.type == OS.Ph_EV_DRAG) {			switch (phEvent.subtype) {				case OS.Ph_EV_DRAG_MOTION_EVENT: {					int data = OS.PhGetData (buffer);					if (data == 0) break;					PhPointerEvent_t pe = new PhPointerEvent_t ();					OS.memmove (pe, data, PhPointerEvent_t.sizeof);					int newX = pe.pos_x;					int newY = pe.pos_y;					if (newX != oldX || newY != oldY) {						Rectangle [] oldRectangles = rectangles;						Rectangle [] rectsToErase = new Rectangle [rectangles.length];						for (int i = 0; i < rectangles.length; i++) {							Rectangle current = rectangles [i];							rectsToErase [i] = new Rectangle (current.x, current.y, current.width, current.height);						}						event.x = newX;						event.y = newY;						if ((style & SWT.RESIZE) != 0) {							resizeRectangles (newX - oldX, newY - oldY);							sendEvent (SWT.Resize, event);							/*							* It is possible (but unlikely), that application							* code could have disposed the widget in the move							* event.  If this happens, return false to indicate							* that the tracking has failed.							*/							if (isDisposed ()) {								cancelled = true;								break;							}							boolean draw = false;							/*							 * It is possible that application code could have							 * changed the rectangles in the resize event.  If this							 * happens then only redraw the tracker if the rectangle							 * values have changed.							 */							if (rectangles != oldRectangles) {								int length = rectangles.length;								if (length != rectsToErase.length) {									draw = true;								} else {									for (int i = 0; i < length; i++) {										if (!rectangles [i].equals (rectsToErase [i])) {											draw = true;											break;										}									}								}							} else {								draw = true;							}							if (draw) {								drawRectangles (rectsToErase);								drawRectangles (rectangles);							}							cursorPos = adjustResizeCursor ();							newX = cursorPos.x; newY = cursorPos.y;						} else {							moveRectangles (newX - oldX, newY - oldY);							sendEvent (SWT.Move, event);							/*							* It is possible (but unlikely), that application							* code could have disposed the widget in the move							* event.  If this happens, return false to indicate							* that the tracking has failed.							*/							if (isDisposed ()) {								cancelled = true;								break;							}							boolean draw = false;							/*							 * It is possible that application code could have							 * changed the rectangles in the move event.  If this							 * happens then only redraw the tracker if the rectangle							 * values have changed.							 */							if (rectangles != oldRectangles) {								int length = rectangles.length;								if (length != rectsToErase.length) {									draw = true;								} else {									for (int i = 0; i < length; i++) {										if (!rectangles [i].equals (rectsToErase [i])) {											draw = true;											break;										}									}								}							} else {								draw = true;							}							if (draw) {								drawRectangles (rectsToErase);								drawRectangles (rectangles);							}						}						oldX = newX;  oldY = newY;					}					break;				}				case OS.Ph_EV_DRAG_KEY_EVENT: {					int data = OS.PhGetData (buffer);					if (data == 0) break;					PhKeyEvent_t ke = new PhKeyEvent_t ();					OS.memmove (ke, data, PhKeyEvent_t.sizeof);					if ((ke.key_flags & OS.Pk_KF_Sym_Valid) != 0) {						int stepSize = (ke.key_mods & OS.Pk_KM_Ctrl) != 0 ? STEPSIZE_SMALL : STEPSIZE_LARGE;						int xChange = 0, yChange = 0;						switch (ke.key_sym) {							case OS.Pk_Escape:								cancelled = true;								tracking = false;								break;							case OS.Pk_Return:								tracking = false;								break;							case OS.Pk_Left:								xChange = -stepSize;								break;							case OS.Pk_Right:								xChange = stepSize;								break;							case OS.Pk_Up:								yChange = -stepSize;								break;							case OS.Pk_Down:								yChange = stepSize;								break;						}						if (xChange != 0 || yChange != 0) {							Rectangle [] oldRectangles = rectangles;							Rectangle [] rectsToErase = new Rectangle [rectangles.length];							for (int i = 0; i < rectangles.length; i++) {								Rectangle current = rectangles [i];								rectsToErase [i] = new Rectangle (current.x, current.y, current.width, current.height);							}							int newX = oldX + xChange;							int newY = oldY + yChange;							event.x = newX;							event.y = newY;							if ((style & SWT.RESIZE) != 0) {								resizeRectangles (xChange, yChange);								sendEvent (SWT.Resize, event);								/*								* It is possible (but unlikely) that application								* code could have disposed the widget in the move								* event.  If this happens return false to indicate								* that the tracking has failed.								*/								if (isDisposed ()) {									cancelled = true;									break;								}								boolean draw = false;								/*								 * It is possible that application code could have								 * changed the rectangles in the resize event.  If this								 * happens then only redraw the tracker if the rectangle								 * values have changed.								 */								if (rectangles != oldRectangles) {									int length = rectangles.length;									if (length != rectsToErase.length) {										draw = true;									} else {										for (int i = 0; i < length; i++) {											if (!rectangles [i].equals (rectsToErase [i])) {												draw = true;												break;											}										}									}								} else {									draw = true;								}								if (draw) {									drawRectangles (rectsToErase);									drawRectangles (rectangles);								}								cursorPos = adjustResizeCursor ();							} else {								moveRectangles (xChange, yChange);								sendEvent (SWT.Move, event);								/*								* It is possible (but unlikely) that application								* code could have disposed the widget in the move								* event.  If this happens return false to indicate								* that the tracking has failed.								*/								if (isDisposed ()) {									cancelled = true;									break;								}								boolean draw = false;								/*								 * It is possible that application code could have								 * changed the rectangles in the move event.  If this								 * happens then only redraw the tracker if the rectangle								 * values have changed.								 */								if (rectangles != oldRectangles) {									int length = rectangles.length;									if (length != rectsToErase.length) {										draw = true;									} else {										for (int i = 0; i < length; i++) {											if (!rectangles [i].equals (rectsToErase [i])) {												draw = true;												break;											}										}									}								} else {									draw = true;								}								if (draw) {									drawRectangles (rectsToErase);									drawRectangles (rectangles);								}								cursorPos = adjustMoveCursor ();							}							oldX = cursorPos.x;  oldY = cursorPos.y;						}					}					break;				}				case OS.Ph_EV_DRAG_COMPLETE: {					tracking = false;					break;				}			}			if (phEvent.collector_handle != 0) {				setCursor (phEvent.collector_handle);			}			/*			* Don't dispatch mouse and key events in general, EXCEPT once this			* tracker has finished its work.			*/			if (tracking && !cancelled) continue;						}		OS.PtEventHandler (buffer);	}	OS.free (buffer);	if (!isDisposed ()) drawRectangles (rectangles);	tracking = false;	if (region != 0) OS.PtDestroyWidget (region);	return !cancelled;}