/*******************************************************************************
 * Copyright (c) 2000, 2018 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Red Hat         - GtkSpinButton rewrite. 2014.10.09
 *     Lablicate GmbH  - add locale support/improve editing support for date/time styles. 2017.02.08
 *******************************************************************************/
package org.eclipse.swt.widgets;

import java.text.*;
import java.text.AttributedCharacterIterator.*;
import java.text.DateFormat.*;
import java.util.*;

import org.eclipse.swt.*;
import org.eclipse.swt.accessibility.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.internal.*;
import org.eclipse.swt.internal.gtk.*;
import org.eclipse.swt.internal.gtk3.*;
import org.eclipse.swt.internal.gtk4.*;

/*
 * Developer note: Unit tests for this class can be found under:
 * org.eclipse.swt.tests.junit.Test_org_eclipse_swt_widgets_DateTime
 */

/**
 * Instances of this class are selectable user interface
 * objects that allow the user to enter and modify date
 * or time values.
 * <p>
 * Note that although this class is a subclass of <code>Composite</code>,
 * it does not make sense to add children to it, or set a layout on it.
 * </p>
 * <dl>
 * <dt><b>Styles:</b></dt>
 * <dd>DATE, TIME, CALENDAR, SHORT, MEDIUM, LONG, DROP_DOWN, CALENDAR_WEEKNUMBERS</dd>
 * <dt><b>Events:</b></dt>
 * <dd>DefaultSelection, Selection</dd>
 * </dl>
 * <p>
 * Note: Only one of the styles DATE, TIME, or CALENDAR may be specified,
 * and only one of the styles SHORT, MEDIUM, or LONG may be specified.
 * The DROP_DOWN style is only valid with the DATE style.
 * </p><p>
 * IMPORTANT: This class is <em>not</em> intended to be subclassed.
 * </p>
 *
 * @see <a href="http://www.eclipse.org/swt/snippets/#datetime">DateTime snippets</a>
 * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
 *
 * @since 3.3
 * @noextend This class is not intended to be subclassed by clients.
 */
public class DateTime extends Composite {
	int day, month, year, hours, minutes, seconds;

	/**
	 * Major handles of this class.
	 * Note, these can vary or all equal each other depending on Date/Time/Calendar/Drop_down
	 * configuration used. See createHandle () */
	long textEntryHandle, spinButtonHandle,
	containerHandle,
	calendarHandle;

	/* Emulated DATE and TIME fields */
	Calendar calendar;
	Button down;
	FieldPosition currentField;
	StringBuilder typeBuffer = new StringBuilder();
	int typeBufferPos = -1;
	boolean firstTime = true;
	private DateFormat dateFormat;
	/* DROP_DOWN calendar fields for DATE */
	Color fg, bg;
	boolean hasFocus;
	int savedYear, savedMonth, savedDay;
	Shell popupShell;
	DateTime popupCalendar;
	Listener popupListener, popupFilter;

	Point prefferedSize;
	Locale locale;

	/** Used when SWT.DROP_DOWN is set */
	Listener mouseEventListener;

	/*
	 * Used for easier access to format pattern of DATE and TIME.
	 * See https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html
	 */
	static final String DEFAULT_SHORT_DATE_FORMAT = "dd/MM/yy";
	static final String DEFAULT_MEDIUM_DATE_FORMAT = "d-MMM-yyyy";
	static final String DEFAULT_LONG_DATE_FORMAT = "MMMM d, yyyy";
	static final String DEFAULT_SHORT_TIME_FORMAT = "h:mm a";
	static final String DEFAULT_MEDIUM_TIME_FORMAT = "h:mm:ss a";
	static final String DEFAULT_LONG_TIME_FORMAT = "h:mm:ss z a";
	static final int MIN_YEAR = 1752; // Gregorian switchover in North America: September 19, 1752
	static final int MAX_YEAR = 9999;
	static final int SPACE_FOR_CURSOR = 1;

	private int mdYear;

	private int mdMonth;

/**
 * Constructs a new instance of this class given its parent
 * and a style value describing its behavior and appearance.
 * <p>
 * The style value is either one of the style constants defined in
 * class <code>SWT</code> which is applicable to instances of this
 * class, or must be built by <em>bitwise OR</em>'ing together
 * (that is, using the <code>int</code> "|" operator) two or more
 * of those <code>SWT</code> style constants. The class description
 * lists the style constants that are applicable to the class.
 * Style bits are also inherited from superclasses.
 * </p>
 *
 * @param parent a composite control which will be the parent of the new instance (cannot be null)
 * @param style the style of control to construct
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
 *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
 * </ul>
 *
 * @see SWT#DATE
 * @see SWT#TIME
 * @see SWT#CALENDAR
 * @see SWT#CALENDAR_WEEKNUMBERS
 * @see SWT#SHORT
 * @see SWT#MEDIUM
 * @see SWT#LONG
 * @see SWT#DROP_DOWN
 * @see Widget#checkSubclass
 * @see Widget#getStyle
 */
public DateTime (Composite parent, int style) {
	super (parent, checkStyle (style));
	if (isDate () || isTime ()) {
		createText ();
	}

	if (isCalendar ()) {
		GTK.gtk_calendar_mark_day (calendarHandle, Calendar.getInstance ().get (Calendar.DAY_OF_MONTH));
	}

	if (isDateWithDropDownButton ()) {
		createDropDownButton ();
		createPopupShell (-1, -1, -1);
		addListener (SWT.Resize, event -> setDropDownButtonSize ());
	}
	initAccessible ();

	if (isDateWithDropDownButton ()) {
		//Date w/ drop down button is in containers.
		//first time round we set the bounds manually for correct Right_to_left behaviour
		Point size = computeSizeInPixels (SWT.DEFAULT, SWT.DEFAULT);
		setBoundsInPixels (0, 0, size.x, size.y);
	}
}

void createText() {
	String property = System.getProperty("swt.datetime.locale");
	if (property == null || property.isEmpty()) {
		locale = Locale.getDefault();
	} else {
		locale = Locale.forLanguageTag(property);
	}
	dateFormat = getFormat(locale, style);
	dateFormat.setLenient(false);
	calendar = Calendar.getInstance(locale);
	updateControl();
	selectField(updateField(currentField));
}

DateFormat getFormat(Locale locale, int style) {
	int dfStyle;
	if ((style & SWT.LONG) != 0) {
		dfStyle = DateFormat.LONG;
	} else if ((style & SWT.SHORT) != 0) {
		dfStyle = DateFormat.SHORT;
	} else {
		dfStyle = DateFormat.MEDIUM;
	}
	if (isDate()) {
		return DateFormat.getDateInstance(dfStyle, locale);
	} else if (isTime()) {
		return DateFormat.getTimeInstance(dfStyle, locale);
	} else {
		throw new IllegalStateException("can only be called for date or time widgets!");
	}
}

static int checkStyle (int style) {
	/*
	* Even though it is legal to create this widget
	* with scroll bars, they serve no useful purpose
	* because they do not automatically scroll the
	* widget's client area.  The fix is to clear
	* the SWT style.
	*/
	style &= ~(SWT.H_SCROLL | SWT.V_SCROLL);

	style = checkBits (style, SWT.DATE, SWT.TIME, SWT.CALENDAR, 0, 0, 0);
	if ((style & SWT.DATE) == 0) style &=~ SWT.DROP_DOWN;
	return checkBits (style, SWT.MEDIUM, SWT.SHORT, SWT.LONG, 0, 0, 0);
}

/**
 * Adds the listener to the collection of listeners who will
 * be notified when the control is selected by the user, by sending
 * it one of the messages defined in the <code>SelectionListener</code>
 * interface.
 * <p>
 * <code>widgetSelected</code> is called when the user changes the control's value.
 * <code>widgetDefaultSelected</code> is typically called when ENTER is pressed.
 * </p>
 *
 * @param listener the listener which should be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see SelectionListener
 * @see #removeSelectionListener
 * @see SelectionEvent
 */
public void addSelectionListener (SelectionListener listener) {
	checkWidget ();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	TypedListener typedListener = new TypedListener (listener);
	addListener (SWT.Selection, typedListener);
	addListener (SWT.DefaultSelection, typedListener);
}

@Override
protected void checkSubclass () {
	if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
}

/**
 * Compute the native text entry size when the formatted text inside the entry
 * is at the longest length possible. i.e. Assume DATE/HOUR field to be double digit,
 * MONTH field for SWT.DATE | SWT.LONG is the longest text.
 *
 * @param wHint
 * @param hHint
 * @param changed
 * @return text entry size to hold the longest possible formatted text.
 */
Point computeMaxTextSize (int wHint, int hHint, boolean changed) {
	String currentText = getFormattedString();
	String formatPattern = getComputeSizeString(style);

	switch (formatPattern) {
		case DEFAULT_MEDIUM_DATE_FORMAT:
			// Make the DATE field a double digit
			String longDateText = currentText.replaceFirst("\\d{1,2}", "00");
			setText(longDateText);
			break;
		case DEFAULT_LONG_DATE_FORMAT:
			// Make the MONTH field the longest length possible, the DATE field a double digit.
			Set<String> months = calendar.getDisplayNames(Calendar.MONTH, Calendar.LONG, locale).keySet();
			String longestMonth = Collections.max(months, (s1, s2) -> s1.length() - s2.length()); // Probably September
			String doubleDigitDate = currentText.replaceFirst("\\d{1,2}", "00");
			String longText = doubleDigitDate.replaceFirst("[^\\s]+", longestMonth);
			setText(longText);
			break;
		case DEFAULT_SHORT_TIME_FORMAT:
		case DEFAULT_MEDIUM_TIME_FORMAT:
		case DEFAULT_LONG_TIME_FORMAT:
			// Make the HOUR field a double digit
			String longTimeText = currentText.replaceFirst("\\d{1,2}", "00");
			setText(longTimeText);
			break;
		default:
			// Fixed length for DEFAULT_SHORT_DATE_FORMAT, no need to adjust text length.
	}

	Point textSize = computeNativeSize (GTK.GTK4 ? handle : textEntryHandle, wHint, hHint, changed);
	// Change the text back to match the current calendar
	updateControl();
	return textSize;
}

@Override
Point computeSizeInPixels (int wHint, int hHint, boolean changed) {
	checkWidget ();

	int width = 0, height = 0;
	//For Date and Time, we cache the preffered size as there is no need to recompute it.
	if (!changed && (isDate () || isTime ()) && prefferedSize != null) {
		width = (wHint != SWT.DEFAULT) ? wHint : prefferedSize.x;
		height= (hHint != SWT.DEFAULT) ? hHint : prefferedSize.y;
		return new Point (width,height);
	}

	if (wHint == SWT.DEFAULT || hHint == SWT.DEFAULT) {
		if (isCalendar ()) {
			Point size = computeNativeSize (containerHandle, wHint, hHint, changed);
			width = size.x;
			height = size.y;
		} else {
			/*
			 * Bug 538612: Computing the native size for textEntry when the current text
			 * is not the longest length possible causes sizing issues when the entry text
			 * is changed. Fix is to always allocate enough size to hold the longest possible
			 * formatted text.
			 */
			Point textSize = computeMaxTextSize (wHint, hHint, changed);
			Rectangle trim = computeTrimInPixels (0,0, textSize.x,textSize.y);
			if (isDateWithDropDownButton ()){
				Point buttonSize = down.computeSizeInPixels (SWT.DEFAULT, SWT.DEFAULT, changed);
				width = trim.width + buttonSize.x;
				height = Math.max (trim.height, buttonSize.y);
			} else if (isDate () || isTime ()) {
				width = trim.width;
				height = trim.height;
			}
		}
	}
	if (width == 0) width = DEFAULT_WIDTH;
	if (height == 0) height = DEFAULT_HEIGHT;
	if (wHint != SWT.DEFAULT) width = wHint;
	if (hHint != SWT.DEFAULT) height = hHint;
	int borderWidth = getBorderWidthInPixels ();

	if (prefferedSize == null && isDateWithDropDownButton ()) {
		prefferedSize = new Point (width + 2*borderWidth, height+ 2*borderWidth);
		return prefferedSize;
	} else {
		return new Point (width + 2*borderWidth, height+ 2*borderWidth);
	}
}

@Override
Rectangle computeTrimInPixels (int x, int y, int width, int height) {
	if (isCalendar ()) {
		return super.computeTrimInPixels (x, y, width, height);
	}

	checkWidget ();
	Rectangle trim = super.computeTrimInPixels (x, y, width, height);
	int xborder = 0, yborder = 0;
		GtkBorder tmp = new GtkBorder ();
		long context = GTK.gtk_widget_get_style_context (textEntryHandle);
		int state_flag = GTK.gtk_widget_get_state_flags(textEntryHandle);
		gtk_style_context_get_padding(context, state_flag, tmp);
		trim.x -= tmp.left;
		trim.y -= tmp.top;
		trim.width += tmp.left + tmp.right;
		trim.height += tmp.top + tmp.bottom;
		if ((style & SWT.BORDER) != 0) {
			int state = GTK.gtk_widget_get_state_flags(textEntryHandle);
			gtk_style_context_get_border(context, state, tmp);
			trim.x -= tmp.left;
			trim.y -= tmp.top;
			trim.width += tmp.left + tmp.right;
			trim.height += tmp.top + tmp.bottom;
		}
		trim.x -= xborder;
		trim.y -= yborder;
		trim.width += 2 * xborder;
		trim.height += 2 * yborder;
		trim.width += SPACE_FOR_CURSOR;
		return new Rectangle (trim.x, trim.y, trim.width, trim.height);
}


@Override
void createHandle (int index) {
	createHandle ();
}

/**
 * Here we carefully define the three internal handles:
 *  textEntryHandle
 *  containerHandle
 *  calendarHandle
 */
void createHandle () {
	if (isCalendar ()) {
		state |= HANDLE;
		createHandleForFixed ();
		createHandleForCalendar ();

	} else {
		createHandleForFixed ();
		if (isDateWithDropDownButton ()) {
			createHandleForDateWithDropDown ();
		} else {
			createHandleForDateTime ();
		}
		GTK.gtk_editable_set_editable (textEntryHandle, (style & SWT.READ_ONLY) == 0);
	}
}

private void createHandleForFixed () {
	fixedHandle = OS.g_object_new (display.gtk_fixed_get_type (), 0);
	if (fixedHandle == 0) error (SWT.ERROR_NO_HANDLES);
	if (!GTK.GTK4) GTK3.gtk_widget_set_has_window(fixedHandle, true);
}

private void createHandleForCalendar () {
	calendarHandle = GTK.gtk_calendar_new ();
	if (calendarHandle == 0) error (SWT.ERROR_NO_HANDLES);

	//Calendar becomes container in this case.
	handle = calendarHandle;
	containerHandle = calendarHandle;

	if (GTK.GTK4) {
		OS.swt_fixed_add(fixedHandle, calendarHandle);

		GTK4.gtk_calendar_set_show_heading(calendarHandle, true);
		GTK4.gtk_calendar_set_show_day_names(calendarHandle, true);
		GTK4.gtk_calendar_set_show_week_numbers(calendarHandle, showWeekNumbers());
	} else {
		GTK3.gtk_container_add (fixedHandle, calendarHandle);

		int flags = GTK.GTK_CALENDAR_SHOW_HEADING | GTK.GTK_CALENDAR_SHOW_DAY_NAMES;
		if (showWeekNumbers()) {
			flags |= GTK.GTK_CALENDAR_SHOW_WEEK_NUMBERS;
		}
		GTK3.gtk_calendar_set_display_options (calendarHandle, flags);
		GTK.gtk_widget_show (calendarHandle);
	}
}

private void createHandleForDateWithDropDown () {
	handle = gtk_box_new(GTK.GTK_ORIENTATION_HORIZONTAL, false, 0);
	if (handle == 0) error(SWT.ERROR_NO_HANDLES);
	containerHandle = handle;

	textEntryHandle = GTK.gtk_entry_new();
	if (textEntryHandle == 0) error(SWT.ERROR_NO_HANDLES);

	if (GTK.GTK4) {
		OS.swt_fixed_add(fixedHandle, containerHandle);
		GTK4.gtk_box_append(containerHandle, textEntryHandle);
	} else {
		GTK3.gtk_container_add(fixedHandle, containerHandle);
		GTK3.gtk_container_add(containerHandle, textEntryHandle);
		GTK.gtk_widget_show(containerHandle);
		GTK.gtk_widget_show(textEntryHandle);
	}

	// In GTK 3 font description is inherited from parent widget which is not how SWT has always worked,
	// reset to default font to get the usual behavior
	setFontDescription(defaultFont().handle);
}

private void createHandleForDateTime () {
	long adjusment = GTK.gtk_adjustment_new (0, -9999, 9999, 1, 0, 0);
	if (GTK.GTK4) {
		handle =  GTK.gtk_spin_button_new(adjusment, 1, 0);
		textEntryHandle = GTK4.gtk_widget_get_first_child(handle);
		containerHandle = spinButtonHandle;
	} else {
		textEntryHandle = GTK.gtk_spin_button_new (adjusment, 1, 0);
		handle = textEntryHandle;
		containerHandle = textEntryHandle;
	}
	if (textEntryHandle == 0) error (SWT.ERROR_NO_HANDLES);

	if (GTK.GTK4) {
		OS.swt_fixed_add(fixedHandle, handle);
	} else {
		GTK3.gtk_container_add (fixedHandle, handle);
	}

	GTK.gtk_spin_button_set_numeric (handle, false);
	GTK.gtk_spin_button_set_wrap (handle, (style & SWT.WRAP) != 0);
}

void createDropDownButton () {
	down = new Button (this, SWT.ARROW  | SWT.DOWN);
	GTK.gtk_widget_set_can_focus (down.handle, false);
	down.addListener (SWT.Selection, event -> {
		setFocus ();
		dropDownCalendar (!isDropped ());
	});

	popupListener = event -> {
		if (event.widget == popupShell) {
			popupShellEvent (event);
			return;
		}
		if (event.widget == popupCalendar) {
			popupCalendarEvent (event);
			return;
		}
		if (event.widget == DateTime.this) {
			onDispose (event);
			return;
		}
		if (event.widget == getShell ()) {
			getDisplay ().asyncExec (() -> {
				if (isDisposed ()) return;
				handleFocus (SWT.FocusOut);
			});
		}
	};
	popupFilter = event -> {
		Shell shell = ((Control)event.widget).getShell ();
		if (shell == DateTime.this.getShell ()) {
			handleFocus (SWT.FocusOut);
		}
	};
}

void createPopupShell (int year, int month, int day) {
	popupShell = new Shell (getShell (), SWT.NO_TRIM | SWT.ON_TOP);
	int popupStyle = SWT.CALENDAR;
	if (showWeekNumbers()) {
		popupStyle |= SWT.CALENDAR_WEEKNUMBERS;
	}
	popupCalendar = new DateTime (popupShell, popupStyle);
	if (font != null) popupCalendar.setFont (font);
	if (fg != null) popupCalendar.setForeground (fg);
	if (bg != null) popupCalendar.setBackground (bg);

	mouseEventListener = event -> {
		if (event.widget instanceof Control) {
			Control c = (Control)event.widget;
			if (c != down && c.getShell () != popupShell)
				dropDownCalendar (false);
		}
	};

	int [] listeners = {SWT.Close, SWT.MouseUp};
	for (int i=0; i < listeners.length; i++) {
		popupShell.addListener (listeners [i], popupListener);
	}
	listeners = new int [] {SWT.MouseDown, SWT.MouseUp, SWT.Selection, SWT.Traverse, SWT.KeyDown, SWT.KeyUp, SWT.FocusIn, SWT.FocusOut, SWT.Dispose};
	for (int i=0; i < listeners.length; i++) {
		popupCalendar.addListener (listeners [i], popupListener);
	}
	addListener (SWT.Dispose, popupListener);
	if (year != -1) popupCalendar.setDate (year, month, day);
}

@Override
void setFontDescription (long font) {
	if (isDateWithDropDownButton ()) {
		prefferedSize = null; //flush cache for computeSize as font can cause size to change.
		setFontDescription (textEntryHandle, font);
	}
	super.setFontDescription (font);
}

@Override
boolean checkSubwindow () {
	return false;
}

@Override
void createWidget (int index) {
	super.createWidget (index);
	if (isCalendar ()) {
		getDate ();
	}
}

void onDispose (Event event) {
	if (popupShell != null && !popupShell.isDisposed ()) {
		popupCalendar.removeListener (SWT.Dispose, popupListener);
		popupShell.dispose ();
	}
	Shell shell = getShell ();
	shell.removeListener (SWT.Deactivate, popupListener);
	Display display = getDisplay ();
	display.removeFilter (SWT.FocusIn, popupFilter);
	popupShell = null;
	popupCalendar = null;
	down = null;
}

/**
 * Called when pressing the SWT.DROP_DOWN button on a Date Field
 * @param drop true if the calendar is suppose to drop down.
 */
void dropDownCalendar (boolean drop) {
	if (drop == isDropped ()) return;

	if (!drop) {
		hideDropDownCalendar ();
		return;
	}

	setCurrentDate ();

	if (getShell () != popupShell.getParent ()) {
		recreateCalendar ();
	}

	//This is the x/y/width/height of the container of DateTime
	Point containerBounds = getSizeInPixels ();
	Point calendarSize = popupCalendar.computeSizeInPixels (SWT.DEFAULT, SWT.DEFAULT, false);

	//Set the inner calendar pos/size. (not the popup shell pos/size)
	popupCalendar.setBoundsInPixels (1, 1, Math.max (containerBounds.x - 2, calendarSize.x), calendarSize.y);

	//Set Date & focus current day
	popupCalendar.setDate (savedYear, savedMonth, savedDay);
	focusDayOnPopupCalendar ();

	Display display = getDisplay ();

	//To display popup calendar, we need to know where the parent is relative to the whole screen.
	Rectangle coordsRelativeToScreen = display.mapInPixels (getParent (), null, getBoundsInPixels ());
	Rectangle displayRect = DPIUtil.autoScaleUp(getMonitor ().getClientArea ());

	showPopupShell (containerBounds, calendarSize, coordsRelativeToScreen, displayRect);

	display.addFilter (SWT.MouseDown, mouseEventListener);
}

private void showPopupShell (Point containerBounds, Point calendarSize, Rectangle coordsRelativeToScreen,
		Rectangle displayRect) {
	int width = Math.max (containerBounds.x, calendarSize.x + 2);
	int height = calendarSize.y + 2;
	int y = calculateCalendarYpos (containerBounds, coordsRelativeToScreen, height, displayRect);
	int x = calculateCalendarXpos (calendarSize, coordsRelativeToScreen, displayRect, width);

	popupShell.setBoundsInPixels (x, y, width, height);
	popupShell.setVisible (true);
	if (isFocusControl ()) {
		popupCalendar.setFocus ();
	}
}

private int calculateCalendarYpos (Point containerBounds, Rectangle coordsRelativeToScreen, int height,
		Rectangle displayRect) {
	int dateEntryHeight = computeNativeSize (containerHandle, SWT.DEFAULT, SWT.DEFAULT, false).y;
	int y = coordsRelativeToScreen.y + containerBounds.y/2 + dateEntryHeight/2;

	//Put Calendar above control if it would be cut off at the bottom.
	if (y + height > displayRect.y + displayRect.height) {
		y -= (height + dateEntryHeight);
	}
	return y;
}

private int calculateCalendarXpos (Point calendarSize, Rectangle coordsRelativeToScreen, Rectangle displayRect,
		int width) {
	Integer x;
	x = coordsRelativeToScreen.x;
	//Move calendar to the right if it would be cut off.
	if (x + width > displayRect.x + displayRect.width) {
		x = displayRect.x + displayRect.width - calendarSize.x;
	}
	return x;
}


private void focusDayOnPopupCalendar () {
	int currentYear = Calendar.getInstance ().get (Calendar.YEAR);
	int currentMonth = Calendar.getInstance ().get (Calendar.MONTH);

	if (savedYear == currentYear && savedMonth == currentMonth) {
		int currentDay = Calendar.getInstance ().get (Calendar.DAY_OF_MONTH);
		GTK.gtk_calendar_mark_day (popupCalendar.handle, currentDay);
	}
}

private void setCurrentDate () {
	savedYear = getYear ();
	savedMonth = getMonth ();
	savedDay = getDay ();
}

private void recreateCalendar () {
	int year = popupCalendar.getYear ();
	int month = popupCalendar.getMonth ();
	int day = popupCalendar.getDay ();
	popupCalendar.removeListener (SWT.Dispose, popupListener);
	popupShell.dispose ();
	popupShell = null;
	popupCalendar = null;
	createPopupShell (year, month, day);
}

private void hideDropDownCalendar () {
	popupShell.setVisible (false);
	GTK.gtk_calendar_clear_marks (popupCalendar.handle);
	display.removeFilter (SWT.MouseDown, mouseEventListener);
	return;
}

String getComputeSizeString (int style) {
	if ((style & SWT.DATE) != 0) {
		return (style & SWT.SHORT) != 0 ? DEFAULT_SHORT_DATE_FORMAT : (style & SWT.LONG) != 0 ? DEFAULT_LONG_DATE_FORMAT : DEFAULT_MEDIUM_DATE_FORMAT;
	}
	// SWT.TIME
	return (style & SWT.SHORT) != 0 ? DEFAULT_SHORT_TIME_FORMAT : (style & SWT.LONG) != 0 ? DEFAULT_LONG_TIME_FORMAT : DEFAULT_MEDIUM_TIME_FORMAT;
}

String getFormattedString() {
	return dateFormat.format(calendar.getTime());
}

void getDate () {
	int [] y = new int [1];
	int [] m = new int [1];
	int [] d = new int [1];

	if (GTK.GTK4) {
		long dateTime = GTK4.gtk_calendar_get_date(calendarHandle);
		OS.g_date_time_get_ymd(dateTime, y, m, d);
	} else {
		GTK3.gtk_calendar_get_date (calendarHandle, y, m, d);
	}

	year = y[0];
	month = m[0];
	day = d[0];
}

/**
 * Returns the receiver's date, or day of the month.
 * <p>
 * The first day of the month is 1, and the last day depends on the month and year.
 * </p>
 *
 * @return a positive integer beginning with 1
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public int getDay () {
	checkWidget ();
	if (isCalendar ()) {
		getDate ();
		return day;
	} else {
		return calendar.get (Calendar.DAY_OF_MONTH);
	}
}

/**
 * Returns the receiver's hours.
 * <p>
 * Hours is an integer between 0 and 23.
 * </p>
 *
 * @return an integer between 0 and 23
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public int getHours () {
	checkWidget ();
	if (isCalendar ()) {
		return hours;
	} else {
		return calendar.get (Calendar.HOUR_OF_DAY);
	}
}

/**
 * Returns the receiver's minutes.
 * <p>
 * Minutes is an integer between 0 and 59.
 * </p>
 *
 * @return an integer between 0 and 59
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public int getMinutes () {
	checkWidget ();
	if (isCalendar ()) {
		return minutes;
	} else {
		return calendar.get (Calendar.MINUTE);
	}
}

/**
 * Returns the receiver's month.
 * <p>
 * The first month of the year is 0, and the last month is 11.
 * </p>
 *
 * @return an integer between 0 and 11
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public int getMonth () {
	checkWidget ();
	if (isCalendar ()) {
		getDate ();
		return month;
	} else {
		return calendar.get (Calendar.MONTH);
	}
}

@Override
String getNameText () {
	if(calendar == null) {
		return "";
	}
	if (isTime ()) {
		return getHours () + ":" + getMinutes () + ":" + getSeconds ();
	} else {
		return (getMonth () + 1) + "/" + getDay () + "/" + getYear ();
	}
}

/**
 * Returns the receiver's seconds.
 * <p>
 * Seconds is an integer between 0 and 59.
 * </p>
 *
 * @return an integer between 0 and 59
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public int getSeconds () {
	checkWidget ();
	if (isCalendar ()) {
		return seconds;
	} else {
		return calendar.get (Calendar.SECOND);
	}
}

/*
 * Returns a textual representation of the receiver,
 * intended for speaking the text aloud.
 */
String getSpokenText() {
	if (isTime()) {
		return DateFormat.getTimeInstance(DateFormat.FULL).format(calendar.getTime());
	} else if (isDate()) {
		return DateFormat.getDateInstance(DateFormat.FULL).format(calendar.getTime());
	} else {
		Calendar cal = Calendar.getInstance();
		getDate();
		cal.set(year, month, day);
		return DateFormat.getDateInstance(DateFormat.FULL).format(cal.getTime());
	}
}

/**
 * Returns the receiver's year.
 * <p>
 * The first year is 1752 and the last year is 9999.
 * </p>
 *
 * @return an integer between 1752 and 9999
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public int getYear () {
	checkWidget ();
	if (isCalendar ()) {
		getDate ();
		return year;
	} else {
		return calendar.get (Calendar.YEAR);
	}
}

@Override
long gtk_day_selected (long widget) {
	sendSelectionEvent ();
	return 0;
}

@Override
long gtk_day_selected_double_click (long widget) {
	sendSelectionEvent (SWT.DefaultSelection);
	return 0;
}

@Override
long gtk_month_changed (long widget) {
	sendSelectionEvent ();
	return 0;
}

@Override
long eventHandle () {
	return dateTimeHandle ();
}

@Override
long focusHandle () {
	return dateTimeHandle ();
}

@Override
long fontHandle () {
	return dateTimeHandle ();
}

private long dateTimeHandle () {
	if (isCalendar () && calendarHandle != 0) {
		return calendarHandle;
	} else if ((isDate () || isTime ())) {
		if (GTK.GTK4) {
			return handle;
		} else {
			if (textEntryHandle != 0) return textEntryHandle;
		}
		return super.focusHandle ();
	} else {
		return super.focusHandle ();
	}
}

@Override
void hookEvents () {
	super.hookEvents ();
	if (isCalendar ()) {
		hookEventsForCalendar ();
	} else {
		int eventMask =	GDK.GDK_POINTER_MOTION_MASK | GDK.GDK_BUTTON_PRESS_MASK | GDK.GDK_BUTTON_RELEASE_MASK;
		GTK3.gtk_widget_add_events (textEntryHandle, eventMask);


		if ((style & SWT.DROP_DOWN) == 0 ) {
			hookEventsForDateTimeSpinner ();
		}

		if (!GTK.GTK4) {
			if (OS.G_OBJECT_TYPE (textEntryHandle) == GTK3.GTK_TYPE_MENU ()) {
				hookEventsForMenu ();
			}
		}
	}
}


final private void hookEventsForCalendar () {
	OS.g_signal_connect_closure(calendarHandle, OS.day_selected, display.getClosure(DAY_SELECTED), false);

	if (GTK.GTK4) {
		OS.g_signal_connect_closure(calendarHandle, OS.next_month, display.getClosure(MONTH_CHANGED), false);
		OS.g_signal_connect_closure(calendarHandle, OS.next_year, display.getClosure(MONTH_CHANGED), false);
		OS.g_signal_connect_closure(calendarHandle, OS.prev_month, display.getClosure(MONTH_CHANGED), false);
		OS.g_signal_connect_closure(calendarHandle, OS.prev_year, display.getClosure(MONTH_CHANGED), false);
	} else {
		OS.g_signal_connect_closure(calendarHandle, OS.day_selected_double_click, display.getClosure(DAY_SELECTED_DOUBLE_CLICK), false);
		OS.g_signal_connect_closure(calendarHandle, OS.month_changed, display.getClosure(MONTH_CHANGED), false);
	}
}

final private void hookEventsForDateTimeSpinner () {
	OS.g_signal_connect_closure (handle, OS.output, display.getClosure (OUTPUT), true);
	if (GTK.GTK4) {
		//TODO: GTK4 focus-in (focus event)?
	} else {
		OS.g_signal_connect_closure (textEntryHandle, OS.focus_in_event, display.getClosure (FOCUS_IN_EVENT), true);
	}
}

final private void hookEventsForMenu () {
	OS.g_signal_connect_closure (down.handle, OS.selection_done, display.getClosure (SELECTION_DONE), true);
}

void incrementField(int amount) {
	if (currentField != null) {
		int field = getCalendarField(currentField);
		if (field == Calendar.HOUR && hasAmPm()) {
			int max = calendar.getMaximum(Calendar.HOUR);
			int min = calendar.getMinimum(Calendar.HOUR);
			int value = calendar.get(Calendar.HOUR);
			if ((value == max && amount == 1) || (value == min && amount == -1)) {
				calendar.roll(Calendar.AM_PM, amount);
			}
		}
		if (field > -1) {
			calendar.roll(field, amount);
			updateControl();
			selectField(updateField(currentField));
		}
	}
}

private boolean hasAmPm() {
	AttributedCharacterIterator iterator = dateFormat.formatToCharacterIterator(calendar.getTime());
	while (iterator.current() != CharacterIterator.DONE) {
		for (Attribute attribute : iterator.getAttributes().keySet()) {
			if (Field.AM_PM.equals(attribute)) {
				return true;
			}
		}
		iterator.setIndex(iterator.getRunLimit());
	}
	return false;
}

boolean isDropped () {
	return popupShell.getVisible ();
}

private boolean isCalendar () {
	return ((style & SWT.CALENDAR) != 0);
}

private boolean isDateWithDropDownButton () {
	return ((style & SWT.DROP_DOWN) != 0 && (style & SWT.DATE) != 0);
}

private boolean isDate () {
	return ((style & SWT.DATE) != 0);
}

private boolean isTime () {
	return ((style & SWT.TIME) != 0);
}

private boolean isReadOnly () {
	return ((style & SWT.READ_ONLY) != 0);
}

private boolean showWeekNumbers() {
	return ((style & SWT.CALENDAR_WEEKNUMBERS) != 0);
}

void initAccessible () {
	Accessible accessible = getAccessible ();
	accessible.addAccessibleListener (new AccessibleAdapter () {
		@Override
		public void getName (AccessibleEvent e) {
			e.result = getSpokenText ();
		}

		@Override
		public void getHelp (AccessibleEvent e) {
			e.result = getToolTipText ();
		}
	});

	accessible.addAccessibleControlListener (new AccessibleControlAdapter () {
		@Override
		public void getChildAtPoint (AccessibleControlEvent e) {
			e.childID = ACC.CHILDID_SELF;
		}

		@Override
		public void getLocation (AccessibleControlEvent e) {
			Rectangle rect = display.map (getParent (), null, getBounds ());
			e.x = rect.x;
			e.y = rect.y;
			e.width = rect.width;
			e.height = rect.height;
		}

		@Override
		public void getChildCount (AccessibleControlEvent e) {
			e.detail = 0;
		}

		@Override
		public void getRole (AccessibleControlEvent e) {
			e.detail = (isCalendar ()) ? ACC.ROLE_LABEL : ACC.ROLE_TEXT;
		}

		@Override
		public void getState (AccessibleControlEvent e) {
			e.detail = ACC.STATE_FOCUSABLE;
			if (hasFocus ()) e.detail |= ACC.STATE_FOCUSED;
		}

		@Override
		public void getSelection (AccessibleControlEvent e) {
			if (hasFocus ()) e.childID = ACC.CHILDID_SELF;
		}

		@Override
		public void getFocus (AccessibleControlEvent e) {
			if (hasFocus ()) e.childID = ACC.CHILDID_SELF;
		}
	});
}

boolean isValidTime (int fieldName, int value) {
	Calendar validCalendar;
	if (isCalendar ()) {
		validCalendar = Calendar.getInstance ();
	} else {
		validCalendar = calendar;
	}
	int min = validCalendar.getActualMinimum (fieldName);
	int max = validCalendar.getActualMaximum (fieldName);
	return value >= min && value <= max;
}

boolean isValidDate (int year, int month, int day) {
	if (year < MIN_YEAR || year > MAX_YEAR) return false;
	Calendar valid = Calendar.getInstance ();
	valid.set (year, month, day);
	return valid.get (Calendar.YEAR) == year
		&& valid.get (Calendar.MONTH) == month
		&& valid.get (Calendar.DAY_OF_MONTH) == day;
}

void popupCalendarEvent (Event event) {
	switch (event.type) {
		case SWT.Dispose:
			if (popupShell != null && !popupShell.isDisposed () && !isDisposed () && getShell () != popupShell.getParent ()) {
				int year = popupCalendar.getYear ();
				int month = popupCalendar.getMonth ();
				int day = popupCalendar.getDay ();
				popupShell = null;
				popupCalendar = null;
				createPopupShell (year, month, day);
			}
			break;
		case SWT.FocusIn: {
			handleFocus (SWT.FocusIn);
			break;
		}
		case SWT.MouseDown: {
			if (event.button != 1) return;
			mdYear = getYear();
			mdMonth = getMonth();
			break;
		}
		case SWT.MouseUp: {
			if (event.button != 1) return;
			/*
			* The drop-down should stay visible when
			* either the year or month is changed.
			*/
			if (mdYear == getYear() && mdMonth == getMonth()) {
				dropDownCalendar (false);
			}
			break;
		}
		case SWT.Selection: {
			int year = popupCalendar.getYear ();
			int month = popupCalendar.getMonth ();
			int day = popupCalendar.getDay ();
			setDate (year, month, day);
			Event e = new Event ();
			e.time = event.time;
			e.stateMask = event.stateMask;
			e.doit = event.doit;
			notifyListeners (SWT.Selection, e);
			event.doit = e.doit;
			break;
		}
		case SWT.Traverse: {
			switch (event.detail) {
				case SWT.TRAVERSE_RETURN:
				case SWT.TRAVERSE_ESCAPE:
				case SWT.TRAVERSE_ARROW_PREVIOUS:
				case SWT.TRAVERSE_ARROW_NEXT:
					event.doit = false;
					break;
				case SWT.TRAVERSE_TAB_NEXT:
				case SWT.TRAVERSE_TAB_PREVIOUS:
//					event.doit = text.traverse (event.detail);
					event.detail = SWT.TRAVERSE_NONE;
					if (event.doit) dropDownCalendar (false);
					return;
				case SWT.TRAVERSE_PAGE_NEXT:
				case SWT.TRAVERSE_PAGE_PREVIOUS:
					return;
			}
			Event e = new Event ();
			e.time = event.time;
			e.detail = event.detail;
			e.doit = event.doit;
			e.character = event.character;
			e.keyCode = event.keyCode;
			notifyListeners (SWT.Traverse, e);
			event.doit = e.doit;
			event.detail = e.detail;
			break;
		}
		case SWT.KeyUp: {
			Event e = new Event ();
			e.time = event.time;
			e.character = event.character;
			e.keyCode = event.keyCode;
			e.stateMask = event.stateMask;
			notifyListeners (SWT.KeyUp, e);
			break;
		}
		case SWT.KeyDown: {
			if (event.character == SWT.ESC) {
				/* Escape key cancels popupCalendar and reverts date */
				popupCalendar.setDate (savedYear, savedMonth, savedDay);
				setDate (savedYear, savedMonth, savedDay);
				dropDownCalendar (false);
			}
			if (event.keyCode == SWT.CR || (event.stateMask & SWT.ALT) != 0 && (event.keyCode == SWT.ARROW_UP || event.keyCode == SWT.ARROW_DOWN)) {
				/* Return, Alt+Down, and Alt+Up cancel popupCalendar and select date. */
				dropDownCalendar (false);
			}
			if (event.keyCode == SWT.SPACE) {
				dropDownCalendar (false);
			}
			/* At this point the widget may have been disposed.
			 * If so, do not continue. */
			if (isDisposed ()) break;
			Event e = new Event ();
			e.time = event.time;
			e.character = event.character;
			e.keyCode = event.keyCode;
			e.stateMask = event.stateMask;
			notifyListeners (SWT.KeyDown, e);
			break;
		}
	}
}

void handleFocus (int type) {
	if (isDisposed ()) return;
	switch (type) {
		case SWT.FocusIn: {
			if (hasFocus) return;
			selectAll ();
			hasFocus = true;
			Shell shell = getShell ();
			shell.removeListener (SWT.Deactivate, popupListener);
			shell.addListener (SWT.Deactivate, popupListener);
			Display display = getDisplay ();
			display.removeFilter (SWT.FocusIn, popupFilter);
			Event e = new Event ();
			notifyListeners (SWT.FocusIn, e);
			break;
		}
		case SWT.FocusOut: {
			if (!hasFocus) return;
			Control focusControl = getDisplay ().getFocusControl ();
			if (focusControl == down || focusControl == popupCalendar ) return;
			hasFocus = false;
			Shell shell = getShell ();
			shell.removeListener (SWT.Deactivate, popupListener);
			Display display = getDisplay ();
			display.removeFilter (SWT.MouseDown, mouseEventListener);
			Event e = new Event ();
			notifyListeners (SWT.FocusOut, e);
			break;
		}
	}
}

void popupShellEvent (Event event) {
	switch (event.type) {
		case SWT.Close:
			event.doit = false;
			dropDownCalendar (false);
			break;
		case SWT.MouseUp:
			dropDownCalendar (false);
			break;
	}
}

/**
 * Removes the listener from the collection of listeners who will
 * be notified when the control is selected by the user.
 *
 * @param listener the listener which should no longer be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see SelectionListener
 * @see #addSelectionListener
 */
public void removeSelectionListener (SelectionListener listener) {
	checkWidget ();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	if (eventTable == null) return;
	eventTable.unhook (SWT.Selection, listener);
	eventTable.unhook (SWT.DefaultSelection, listener);
}

/**
 * selects the first occurrence of the given field
 *
 * @param field
 */
void selectField(Field field) {
	AttributedCharacterIterator iterator = dateFormat.formatToCharacterIterator(calendar.getTime());
	while (iterator.current() != CharacterIterator.DONE) {
		for (Attribute attribute : iterator.getAttributes().keySet()) {
			if (attribute.equals(field)) {
				selectField(getFieldPosition(field, iterator));
				return;
			}
		}
		iterator.setIndex(iterator.getRunLimit());
	}
}

/**
 * Selects the given field at the given start/end coordinates
 *
 * @param field
 * @param start
 * @param end
 */
void selectField(FieldPosition fieldPosition) {
	boolean sameField = isSameField(fieldPosition, currentField);
	if (sameField) {
		if (typeBufferPos > -1) {
			typeBufferPos = 0;
		}
	} else {
		typeBufferPos = -1;
		commitData();
		fieldPosition = updateField(fieldPosition);
	}
	Point pt = getTextSelection();
	int start = fieldPosition.getBeginIndex();
	int end = fieldPosition.getEndIndex();
	if (sameField && start == pt.x && end == pt.y) {
		return;
	}
	currentField = fieldPosition;
	display.syncExec(() -> {
		if (textEntryHandle != 0) {
			String value = getText(getText(), start, end - 1);
			int s = value.lastIndexOf(' ');
			s = (s == -1) ? start : start + s + 1;
			setTextSelection(s, end);
		}
	});
	sendSelectionEvent(SWT.Selection);
}

void sendSelectionEvent () {
	int [] y = new int [1];
	int [] m = new int [1];
	int [] d = new int [1];

	if (GTK.GTK4) {
		long dateTime = GTK4.gtk_calendar_get_date(calendarHandle);
		OS.g_date_time_get_ymd(dateTime, y, m, d);
	} else {
		GTK3.gtk_calendar_get_date (calendarHandle, y, m, d);
	}

	if (d[0] != day ||
		m[0] != month ||
		y[0] != year) {
		year = y[0];
		month = m[0];
		day = d[0];
		/* Highlight the current (today) date */
		if (year == Calendar.getInstance ().get (Calendar.YEAR) && month == Calendar.getInstance ().get (Calendar.MONTH)) {
			GTK.gtk_calendar_mark_day (calendarHandle, Calendar.getInstance ().get (Calendar.DAY_OF_MONTH));
		} else {
			GTK.gtk_calendar_clear_marks (calendarHandle);
		}
		sendSelectionEvent (SWT.Selection);
	}
}

@Override
public void setBackground (Color color) {
	super.setBackground (color);
	bg = color;
	if (popupCalendar != null) popupCalendar.setBackground (color);
}

@Override
void setBackgroundGdkRGBA (GdkRGBA rgba) {
	super.setBackgroundGdkRGBA(rgba);
	if (calendarHandle != 0) {
		setBackgroundGdkRGBA (calendarHandle, rgba);
	}
	super.setBackgroundGdkRGBA(rgba);

}

@Override
void setBackgroundGdkRGBA (long context, long handle, GdkRGBA rgba) {
	// We need to override here because DateTime widgets use "background" instead of
	// "background-color" as their CSS property.

	// Form background string
	String name = display.gtk_widget_class_get_css_name(handle);
	String css = name + " {background: " + display.gtk_rgba_to_css_string (rgba) + ";}\n" +
			name + ":selected" + " {background: " + display.gtk_rgba_to_css_string(display.COLOR_LIST_SELECTION_RGBA) + ";}";

	// Cache background
	cssBackground = css;

	// Apply background color and any cached foreground color
	String finalCss = display.gtk_css_create_css_color_string (cssBackground, cssForeground, SWT.BACKGROUND);
	gtk_css_provider_load_from_css (context, finalCss);
}

@Override
public void setEnabled (boolean enabled){
	super.setEnabled (enabled);
	if (isDateWithDropDownButton ())
		down.setEnabled (enabled);
}

@Override
public void setFont (Font font) {
	super.setFont (font);
	this.font = font;
	if (popupCalendar != null) popupCalendar.setFont (font);
	redraw ();
}

@Override
void setForegroundGdkRGBA (GdkRGBA rgba) {
	setForegroundGdkRGBA (containerHandle, rgba);
}

@Override
public void setForeground (Color color) {
	super.setForeground (color);
	fg = color;
	if (popupCalendar != null) popupCalendar.setForeground (color);
}

void setFieldOfInternalDataStructure(FieldPosition field, int value) {
	int calendarField = getCalendarField(field);
	if (calendar.get(calendarField) == value)
		return;
	if (calendarField == Calendar.AM_PM && hasAmPm()) {
		calendar.roll(Calendar.HOUR_OF_DAY, 12);
	}
	calendar.set(calendarField, value);

	//When dealing with months with 31 days and have days set to 31, then if you change the month
	//to one that has 30 (or less) days, then in calendar only the day is changed but the month stays.
	//e.g 10.31.2014  -> decrement month, becomes:
	//    10.01.2014.
	//To get around this behaviour, we set the field again.
	if (calendar.get(calendarField) != value) {
		calendar.set(calendarField, value);
	}
	sendSelectionEvent (SWT.Selection);
}

/**
 * Sets the receiver's year, month, and day in a single operation.
 * <p>
 * This is the recommended way to set the date, because setting the year,
 * month, and day separately may result in invalid intermediate dates.
 * </p>
 *
 * @param year an integer between 1752 and 9999
 * @param month an integer between 0 and 11
 * @param day a positive integer beginning with 1
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @since 3.4
 */
public void setDate (int year, int month, int day) {
	checkWidget ();
	if (!isValidDate (year, month, day)) return;
	if (isCalendar ()) {
		this.year = year;
		this.month = month;
		this.day = day;

		if (GTK.GTK4) {
			long dateTime = OS.g_date_time_new_local(year, month + 1, day, 0, 0, 0);
			GTK4.gtk_calendar_select_day(calendarHandle, dateTime);
		} else {
			GTK3.gtk_calendar_select_month (calendarHandle, month, year);
			GTK3.gtk_calendar_select_day (calendarHandle, day);
		}
	} else {
		calendar.set (year, month, day);
		updateControl ();
	}
}

/**
 * Sets the receiver's date, or day of the month, to the specified day.
 * <p>
 * The first day of the month is 1, and the last day depends on the month and year.
 * If the specified day is not valid for the receiver's month and year, then it is ignored.
 * </p>
 *
 * @param day a positive integer beginning with 1
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see #setDate
 */
public void setDay (int day) {
	checkWidget ();
	if (!isValidDate (getYear (), getMonth (), day)) return;
	if (isCalendar ()) {
		this.day = day;

		if (GTK.GTK4) {
			long dateTime = OS.g_date_time_new_local(this.year, this.month + 1, day, 0, 0, 0);
			GTK4.gtk_calendar_select_day(calendarHandle, dateTime);
		} else {
			GTK3.gtk_calendar_select_day (calendarHandle, day);
		}
	} else {
		calendar.set (Calendar.DAY_OF_MONTH, day);
		updateControl ();
	}
}

/**
 * Sets the receiver's hours.
 * <p>
 * Hours is an integer between 0 and 23.
 * </p>
 *
 * @param hours an integer between 0 and 23
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void setHours (int hours) {
	checkWidget ();
	if (!isValidTime (Calendar.HOUR_OF_DAY, hours)) return;
	if (isCalendar ()) {
		this.hours = hours;
	} else {
		calendar.set (Calendar.HOUR_OF_DAY, hours);
		updateControl ();
	}
}

@Override
public void setMenu (Menu menu) {
	super.setMenu (menu);
	if (down != null) down.setMenu (menu);
}

/**
 * Sets the receiver's minutes.
 * <p>
 * Minutes is an integer between 0 and 59.
 * </p>
 *
 * @param minutes an integer between 0 and 59
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void setMinutes (int minutes) {
	checkWidget ();
	if (!isValidTime (Calendar.MINUTE, minutes)) return;
	if (isCalendar ()) {
		this.minutes = minutes;
	} else {
		calendar.set (Calendar.MINUTE, minutes);
		updateControl ();
	}
}

/**
 * Sets the receiver's month.
 * <p>
 * The first month of the year is 0, and the last month is 11.
 * If the specified month is not valid for the receiver's day and year, then it is ignored.
 * </p>
 *
 * @param month an integer between 0 and 11
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see #setDate
 */
public void setMonth (int month) {
	checkWidget ();
	if (!isValidDate (getYear (), month, getDay ())) return;
	if (isCalendar ()) {
		this.month = month;
		GTK3.gtk_calendar_select_month (calendarHandle, month, year);
	} else {
		calendar.set (Calendar.MONTH, month);
		updateControl ();
	}
}

/**
 * Sets the receiver's seconds.
 * <p>
 * Seconds is an integer between 0 and 59.
 * </p>
 *
 * @param seconds an integer between 0 and 59
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void setSeconds (int seconds) {
	checkWidget ();
	if (!isValidTime (Calendar.SECOND, seconds)) return;
	if (isCalendar ()) {
		this.seconds = seconds;
	} else {
		calendar.set (Calendar.SECOND, seconds);
		updateControl ();
	}
}

/**
 * Sets the receiver's hours, minutes, and seconds in a single operation.
 *
 * @param hours an integer between 0 and 23
 * @param minutes an integer between 0 and 59
 * @param seconds an integer between 0 and 59
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @since 3.4
 */
public void setTime (int hours, int minutes, int seconds) {
	checkWidget ();
	if (!isValidTime (Calendar.HOUR_OF_DAY, hours)) return;
	if (!isValidTime (Calendar.MINUTE, minutes)) return;
	if (!isValidTime (Calendar.SECOND, seconds)) return;
	if (isCalendar ()) {
		this.hours = hours;
		this.minutes = minutes;
		this.seconds = seconds;
	} else {
		calendar.set (Calendar.HOUR_OF_DAY, hours);
		calendar.set (Calendar.MINUTE, minutes);
		calendar.set (Calendar.SECOND, seconds);
		updateControl ();
	}
}

/**
 * Sets the receiver's year.
 * <p>
 * The first year is 1752 and the last year is 9999.
 * If the specified year is not valid for the receiver's day and month, then it is ignored.
 * </p>
 *
 * @param year an integer between 1752 and 9999
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see #setDate
 */
public void setYear (int year) {
	checkWidget ();
	if (!isValidDate (year, getMonth (), getDay ())) return;
	if (isCalendar ()) {
		this.year = year;
		GTK3.gtk_calendar_select_month (calendarHandle, month, year);
	} else {
		calendar.set (Calendar.YEAR, year);
		updateControl ();
	}
}

@Override
void setBoundsInPixels (int x, int y, int width, int height) {

	//Date with Drop down is in container. Needs extra handling.
	if (isDateWithDropDownButton ()) {
		long sizingHandle = textEntryHandle;
		GtkRequisition requisition = new GtkRequisition ();
		GTK.gtk_widget_get_preferred_size (sizingHandle, null, requisition);
		int oldHeight = requisition.height; //Entry should not expand vertically. It is single liner.

		int newWidth = width - (down.getSizeInPixels ().x + getGtkBorderPadding ().right);
		GTK.gtk_widget_set_size_request (sizingHandle, (newWidth >= 0) ? newWidth : 0, oldHeight);
	}

	super.setBoundsInPixels (x, y, width, height);
}

/**
 * Usually called when control is resized or first initialized.
 */
private void setDropDownButtonSize () {
	Rectangle rect = getClientAreaInPixels ();
	int parentWidth = rect.width;
	int parentHeight = rect.height;
	Point buttonSize = down.computeSizeInPixels (SWT.DEFAULT, parentHeight);

	//TAG_GTK3__NO_VERTICAL_FILL_ADJUSTMENT
	int dateEntryHeight = computeNativeSize (textEntryHandle, SWT.DEFAULT, SWT.DEFAULT, false).y;
	int newHeight = dateEntryHeight;

	//Move button a little closer to entry field, by amount of padding.
	int newXpos = parentWidth - buttonSize.x - getGtkBorderPadding().left - getGtkBorderPadding().right;

	int newYPos = parentHeight/2 - dateEntryHeight/2;
	down.setBoundsInPixels (newXpos, newYPos, buttonSize.x, newHeight);
}

/**
 * Gets the border padding structure, which can be used to determine the inner padding of the text field.
 * Note, this function returns the correct padding only under GTK3.
 * Under Gtk2, it returns a constant.
 * @return GtkBorder object that holds the padding values.
 */
GtkBorder getGtkBorderPadding () {
	//In Gtk3, acquire border.
	GtkBorder gtkBorderPadding = new GtkBorder ();
	long contextHandle = textEntryHandle;
	long context = GTK.gtk_widget_get_style_context (contextHandle);
	int state_flag = GTK.gtk_widget_get_state_flags(contextHandle);
	gtk_style_context_get_padding(context, state_flag, gtkBorderPadding);
	return gtkBorderPadding;
}

boolean onNumberKeyInput(int key) {
	if (currentField == null) {
		return false;
	}
	int fieldName = getCalendarField(currentField);
	StringBuilder prefix = new StringBuilder();
	StringBuilder current = new StringBuilder();
	StringBuilder suffix = new StringBuilder();

	AttributedCharacterIterator iterator = dateFormat.formatToCharacterIterator(calendar.getTime());
	char c = iterator.first();
	do {
		if (isSameField(currentField, getFieldPosition(iterator))) {
			current.append(c);
		} else if (current.length() == 0) {
			prefix.append(c);
		} else {
			suffix.append(c);
		}
	} while ((c = iterator.next()) != CharacterIterator.DONE);

	if (typeBufferPos < 0) {
		typeBuffer.setLength(0);
		typeBuffer.append(current);
		typeBufferPos = 0;
	}
	if (key == GDK.GDK_BackSpace) {
		if (typeBufferPos > 0 && typeBufferPos <= typeBuffer.length()) {
			typeBuffer.deleteCharAt(typeBufferPos - 1);
			typeBufferPos--;
		}
	} else if (key == GDK.GDK_Delete) {
		if (typeBufferPos >= 0 && typeBufferPos < typeBuffer.length()) {
			typeBuffer.deleteCharAt(typeBufferPos);
		}
	} else {
		char newText = keyToString(key);
		// Don't allow non-digit character inputs for SWT.TIME, unless modifying the AM/PM field
		if ((style & SWT.TIME) != 0 && fieldName != Calendar.AM_PM && !Character.isDigit(newText)) {
			return false;
		}
		if (!Character.isAlphabetic(newText) && !Character.isDigit(newText)) {
			return false;
		}
		if (fieldName == Calendar.AM_PM) {
			if (dateFormat instanceof SimpleDateFormat) {
				String[] amPmStrings = ((SimpleDateFormat) dateFormat).getDateFormatSymbols().getAmPmStrings();
				if (amPmStrings[Calendar.AM].charAt(0) == newText) {
					setTextField(currentField, Calendar.AM);
					return false;
				} else if (amPmStrings[Calendar.PM].charAt(0) == newText) {
					setTextField(currentField, Calendar.PM);
					return false;
				}
			}
		}
		if (typeBufferPos < typeBuffer.length()) {
			typeBuffer.replace(typeBufferPos, typeBufferPos + 1, Character.toString(newText));
		} else {
			typeBuffer.append(newText);
		}
		typeBufferPos++;
	}
	StringBuilder newText = new StringBuilder(prefix);
	newText.append(typeBuffer);
	newText.append(suffix);
	setText(newText.toString());
	setTextSelection(prefix.length() + typeBufferPos, prefix.length() + typeBuffer.length());
	currentField.setBeginIndex(prefix.length());
	currentField.setEndIndex(prefix.length() + typeBuffer.length());
	if (!isCalendar()) {
		try {
			Date date = dateFormat.parse(getText());
			calendar.setTime(date);
		} catch (ParseException e) {
			// invalid value, input will reset...
		}
	}
	return false;
}

private char keyToString(int key) {
	// If numberpad keys were pressed.
	if (key >= GDK.GDK_KP_0 && key <= GDK.GDK_KP_9) {
		// convert numberpad button to regular key;
		key -= 65408;
	}
	return (char) GDK.gdk_keyval_to_unicode(key);
}

void updateControl() {
	if ((isDate() || isTime()) && textEntryHandle != 0) {
		setText(getFormattedString());
	}
	redraw ();
}

@Override
void register () {
	super.register ();
	if (handle != 0 && display.getWidget(handle) == null) display.addWidget(handle, this);
	if (containerHandle != 0 && containerHandle != handle) display.addWidget (containerHandle, this);
	if (textEntryHandle != 0 && textEntryHandle != containerHandle) display.addWidget (textEntryHandle, this);
}

@Override
GdkRGBA defaultBackground () {
	return display.getSystemColor(SWT.COLOR_LIST_BACKGROUND).handle;
}

@Override
void deregister () {
	super.deregister ();
	if (handle != 0 && display.getWidget(handle) != null) display.removeWidget(handle);
	if (containerHandle != 0 && containerHandle != handle) display.removeWidget (containerHandle);
	if (textEntryHandle != 0 && textEntryHandle != containerHandle) display.removeWidget (textEntryHandle);
}

int getArrow(long widget) {
	updateControl();
	int adj_value = (int) GTK.gtk_adjustment_get_value(GTK.gtk_spin_button_get_adjustment(widget));
	int new_value = 0;
	if (isDate()) {
		FieldPosition firstField = getNextField(null);
		int firstFieldConstant = getCalendarField(firstField);
		new_value = calendar.get(getCalendarField(firstField));
		if (firstFieldConstant == Calendar.MONTH) {
			if ((style & SWT.SHORT) != 0) {
				// adj_value returns the month as a number between 1-12
				// new_value gets the month as a number between 0-11
				// shift the adj_value by offset so that we get the correct arrow direction
				adj_value--;
			} else if ((style & SWT.MEDIUM) != 0 || (style & SWT.LONG) != 0 ) {
				// adj_value is either +1, 0, -1 when month is displayed as string
				if (adj_value == 0) {
					return 0;
				} else {
					return adj_value > 0 ? SWT.ARROW_UP : SWT.ARROW_DOWN;
				}
			}
		}
	} else if (isTime()) {
		new_value = getHours();
		if (hasAmPm()) {
			// as getHours () has 24h format but spinner 12h format, new_value needs to be
			// converted to 12h format
			if (getHours() > 12) {
				new_value = getHours() - 12;
			}
			if (new_value == 0)
				new_value = 12;
		}
	}
	if (adj_value == 0 && firstTime)
		return 0;
	firstTime = false;
	if (adj_value == new_value)
		return 0;
	return adj_value > new_value ? SWT.ARROW_UP : SWT.ARROW_DOWN;
}

/**
 * Calculates appropriate width of GtkEntry and
 * adds Date/Time string to the Date/Time Spinner
 */
void setText (String dateTimeText) {
	if (dateTimeText != null){
		byte [] dateTimeConverted = Converter.wcsToMbcs (dateTimeText, true);

		if (GTK.GTK4) {
			long bufferHandle = isDateWithDropDownButton() ? GTK4.gtk_entry_get_buffer(textEntryHandle) : GTK4.gtk_text_get_buffer(textEntryHandle);
			GTK.gtk_entry_buffer_set_text(bufferHandle, dateTimeConverted, dateTimeText.length());
		} else {
			//note, this is ignored if the control is in a fill-layout.
			GTK3.gtk_entry_set_width_chars(textEntryHandle, dateTimeText.length());
			GTK3.gtk_entry_set_text(textEntryHandle, dateTimeConverted);
		}

		if (popupCalendar != null && calendar != null) {
			Date parse;
			try {
				parse = dateFormat.parse(dateTimeText);
			} catch(ParseException e) {
				//not a valid date (yet), return for now
				return;
			}
			Calendar clone = (Calendar) calendar.clone();
			clone.setTime(parse);
			try {
				popupCalendar.setDate (clone.get(Calendar.YEAR), clone.get(Calendar.MONTH), clone.get(Calendar.DAY_OF_MONTH));
			} catch(SWTException e) {
				if (e.code == SWT.ERROR_WIDGET_DISPOSED) {
					//the calendar popup was disposed in the meantime so nothing to update
					return;
				}
				throw e;
			}
		}
	}
}

@Override
long gtk_key_press_event (long widget, long event) {
	if (!isReadOnly () && (isTime () || isDate ())) {
		int [] key = new int[1];
		if (GTK.GTK4) {
			key[0] = GDK.gdk_key_event_get_keyval(event);
		} else {
			GDK.gdk_event_get_keyval(event, key);
		}

		switch (key[0]) {
		case GDK.GDK_Up:
		case GDK.GDK_KP_Up:
			incrementField(+1);
			commitData();
			break;
		case GDK.GDK_Down:
		case GDK.GDK_KP_Down:
			incrementField(-1);
			commitData();
			break;
		case GDK.GDK_Tab:
		case GDK.GDK_Right:
		case GDK.GDK_KP_Right:
			selectField(getNextField(currentField));
			sendEvent(SWT.Traverse);
			break;
		case GDK.GDK_Left:
		case GDK.GDK_KP_Left:
			selectField(getPreviousField(currentField));
			sendEvent(SWT.Traverse);
			break;
		case GDK.GDK_Home:
		case GDK.GDK_KP_Home:
			/* Set the value of the current field to its minimum */
			if (currentField != null) {
				setTextField(currentField, calendar.getActualMinimum(getCalendarField(currentField)));
			}
			break;
		case GDK.GDK_End:
		case GDK.GDK_KP_End:
			/* Set the value of the current field to its maximum */
			if (currentField != null) {
				setTextField(currentField, calendar.getActualMaximum(getCalendarField(currentField)));
			}
			break;
		default:
			onNumberKeyInput(key[0]);
		}
	}
	return 1;
}

void commitData() {
	try {
		Date date = dateFormat.parse(getText());
		calendar.setTime(date);
	} catch (ParseException e) {
		// invalid value, input will reset...
	}
	updateControl();
}

/**
 * Returns a string containing a copy of the contents of the
 * receiver's text field, or an empty string if there are no
 * contents.
 *
 * @return Spinner's text
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
String getText() {
	checkWidget();
	if (textEntryHandle != 0) {
		long stringPtr;

		if (GTK.GTK4) {
			long bufferHandle = isDateWithDropDownButton() ? GTK4.gtk_entry_get_buffer(textEntryHandle) : GTK4.gtk_text_get_buffer(textEntryHandle);
			stringPtr = GTK.gtk_entry_buffer_get_text(bufferHandle);
		} else {
			stringPtr = GTK3.gtk_entry_get_text(textEntryHandle);
		}

		if (stringPtr == 0) return "";
		int length = C.strlen(stringPtr);
		byte[] buffer = new byte[length];
		C.memmove(buffer, stringPtr, length);
		return new String(Converter.mbcsToWcs(buffer));
	} else {
		return "";
	}
}

/**
 * returns GtkEntry starting from index and ending with index
 * provided by the user
 */
String getText (String str,int start, int end) {
	checkWidget ();
	if (!(start <= end && 0 <= end)) return "";
	int length = str.length ();
	end = Math.min (end, length - 1);
	if (start > end) return "";
	start = Math.max (0, start);
	/*
	* NOTE: The current implementation uses substring ()
	* which can reference a potentially large character
	* array.
	*/
	return str.substring (start, end + 1);
}

/**
 * Returns the selected text. If selected text is less than
 * one character the returned Point has equal start and end values.
 *
 * @return the highlighted (selected) text or position of cursor
 **/
Point getTextSelection() {
	checkWidget();
	int[] start = new int[1];
	int[] end = new int[1];
	GTK.gtk_editable_get_selection_bounds(textEntryHandle, start, end);

	long stringPtr;
	if (GTK.GTK4) {
		long bufferHandle = isDateWithDropDownButton() ? GTK4.gtk_entry_get_buffer(textEntryHandle) : GTK4.gtk_text_get_buffer(textEntryHandle);
		stringPtr = GTK.gtk_entry_buffer_get_text(bufferHandle);
	} else {
		stringPtr = GTK3.gtk_entry_get_text (textEntryHandle);
	}

	start[0] = (int)OS.g_utf8_offset_to_utf16_offset(stringPtr, start[0]);
	end[0] = (int)OS.g_utf8_offset_to_utf16_offset(stringPtr, end[0]);

	return new Point(start[0], end[0]);
}

/** Highlight (select) the text between the start and end. **/
void setTextSelection(int start, int end) {
	checkWidget();

	long stringPtr;
	if (GTK.GTK4) {
		long bufferHandle = isDateWithDropDownButton() ? GTK4.gtk_entry_get_buffer(textEntryHandle) : GTK4.gtk_text_get_buffer(textEntryHandle);
		stringPtr = GTK.gtk_entry_buffer_get_text(bufferHandle);
	} else {
		stringPtr = GTK3.gtk_entry_get_text(textEntryHandle);
	}

	start = (int) OS.g_utf16_offset_to_utf8_offset(stringPtr, start);
	end = (int) OS.g_utf16_offset_to_utf8_offset(stringPtr, end);

	GTK.gtk_editable_set_position(textEntryHandle, start);
	GTK.gtk_editable_select_region(textEntryHandle, start, end);
}

void setTextField(FieldPosition field, int value) {
	int validValue = validateValueBounds(field, value);
	setFieldOfInternalDataStructure(field, validValue);
	setFieldOfInternalDataStructure(field, value);
	updateControl();
	if (currentField != null) {
		selectField(currentField);
	}
}

private int validateValueBounds(FieldPosition field, int value) {
	int calendarField = getCalendarField(field);
	int max = calendar.getActualMaximum (calendarField);
	int min = calendar.getActualMinimum (calendarField);
	if (calendarField == Calendar.YEAR) {
		max = MAX_YEAR;
		min = MIN_YEAR;
		/* Special case: convert 1 or 2-digit years into reasonable 4-digit years. */
		int currentYear = Calendar.getInstance ().get (Calendar.YEAR);
		int currentCentury = (currentYear / 100) * 100;
		if (value < (currentYear + 30) % 100) value += currentCentury;
		else if (value < 100) value += currentCentury - 100;
	}
	if (value > max) value = min; // wrap
	if (value < min) value = max; // wrap
	return value;
}

@Override
long gtk_button_release_event (long widget, long event) {
	if (isDate() || isTime()) {
		int [] eventButton = new int [1];
		GDK.gdk_event_get_button(event, eventButton);

		if (eventButton[0] == 1) { // left mouse button.
			onTextMouseClick();
		}
	}
	return super.gtk_button_release_event(widget, event);
}

@Override
void gtk_gesture_release_event(long gesture, int n_press, double x, double y, long event) {
	if (isDate() || isTime()) {
		int button = GTK.gtk_gesture_single_get_current_button(gesture);

		if (button == 1) {
			onTextMouseClick();
		}
	}

	super.gtk_gesture_release_event(gesture, n_press, x, y, event);
}

/**
 * Output signal is called when Spinner's arrow buttons are triggered,
 * usually by clicking the mouse on the [gtk2: up/down] [gtk3: +/-] buttons.
 * On every click output is called twice presenting current and previous value.
 * This method compares two values and determines if Up or down arrow was called.
 */
@Override
long gtk_output (long widget) {
	if (calendar == null) {
		return 0; //Guard: Object not fully initialized yet.
	}
	int arrowType = getArrow(widget);
	switch (arrowType) {
	case SWT.ARROW_UP: // Gtk3 "+" button.
		commitData();
		incrementField(+1);
		break;
	case SWT.ARROW_DOWN: // Gtk3 "-" button.
		commitData();
		incrementField(-1);
		break;
	}
	return 1;
}

void replaceCurrentlySelectedTextRegion (String string) {
	checkWidget ();
	if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
	byte [] buffer = Converter.wcsToMbcs (string, false);
	int [] start = new int [1], end = new int [1];
	GTK.gtk_editable_get_selection_bounds (textEntryHandle, start, end);
	GTK.gtk_editable_delete_selection (textEntryHandle);
	GTK.gtk_editable_insert_text (textEntryHandle, buffer, buffer.length, start);
	GTK.gtk_editable_set_position (textEntryHandle, start [0]);
}

void onTextMouseClick() {
	if (calendar == null) {
		return; // Guard: Object not fully initialized yet.
	}
	int clickPosition = getTextSelection().x;
	AttributedCharacterIterator iterator = dateFormat.formatToCharacterIterator(calendar.getTime());
	iterator.first();
	int pos = 0;
	do {
		FieldPosition position = getFieldPosition(iterator);
		iterator.setIndex(iterator.getRunLimit());
		if (isSameField(position, currentField)) {
			// use the current field instead then!
			position = currentField;
		}
		int fieldWidth = position.getEndIndex() - position.getBeginIndex();
		pos += fieldWidth;
		if (position.getFieldAttribute() == null) {
			continue;
		}
		if (pos >= clickPosition) {
			FieldPosition selectField = new FieldPosition(position.getFieldAttribute());
			selectField.setBeginIndex(pos - fieldWidth);
			selectField.setEndIndex(pos);
			selectField(selectField);
			break;
		}
	} while (iterator.current() != CharacterIterator.DONE);

}

String getText (int start, int end) {
	checkWidget ();
	if (!(start <= end && 0 <= end)) return "";
	String str = getText ();
	int length = str.length ();
	end = Math.min (end, length - 1);
	if (start > end) return "";
	start = Math.max (0, start);
	/*
	* NOTE: The current implementation uses substring ()
	* which can reference a potentially large character
	* array.
	*/
	return str.substring (start, end + 1);
}

void selectAll () {
	checkWidget ();
	if (textEntryHandle != 0)
		GTK.gtk_editable_select_region (textEntryHandle, 0, -1);
}


void hideDateTime () {
	if (isDate () || isTime ()){
		GTK.gtk_widget_hide (fixedHandle);
	}
}

@Override
void releaseWidget () {
	super.releaseWidget ();
	if (fixedHandle != 0)
		hideDateTime ();
}

/**
 * Returns a field with updated positionla data
 *
 * @param field
 * @return
 */
private FieldPosition updateField(FieldPosition field) {
	AttributedCharacterIterator iterator = dateFormat.formatToCharacterIterator(calendar.getTime());
	while (iterator.current() != CharacterIterator.DONE) {
		FieldPosition current = getFieldPosition(iterator);
		iterator.setIndex(iterator.getRunLimit());
		if (field == null || isSameField(current, field)) {
			return current;
		}
	}
	return field;
}

/**
 * Given a {@link FieldPosition} searches the next field in the format string
 *
 * @param field
 *            the Field to start from
 * @return the next {@link FieldPosition}
 */
private FieldPosition getNextField(FieldPosition field) {
	AttributedCharacterIterator iterator = dateFormat.formatToCharacterIterator(calendar.getTime());
	FieldPosition first = null;
	boolean found = false;
	while (iterator.current() != CharacterIterator.DONE) {
		FieldPosition current = getFieldPosition(iterator);
		iterator.setIndex(iterator.getRunLimit());
		if (current.getFieldAttribute() == null) {
			continue;
		}
		if (found) {
			return current;
		}
		if (first == null) {
			first = current;
		}
		if (isSameField(current, field)) {
			found = true;
		}
	}
	return first;
}

/**
 *
 * @param field
 * @return the next field of the given one
 */
private FieldPosition getPreviousField(FieldPosition field) {
	AttributedCharacterIterator iterator = dateFormat.formatToCharacterIterator(calendar.getTime());
	FieldPosition last = null;
	do {
		FieldPosition current = getFieldPosition(iterator);
		if (isSameField(current, field)) {
			if (last != null) {
				return last;
			}
		}
		if (current.getFieldAttribute() != null) {
			last = current;
		}
		iterator.setIndex(iterator.getRunLimit());
	} while (iterator.current() != CharacterIterator.DONE);
	return last;
}

/**
 * Searches the current postion of the iterator for a {@link Field} and
 * constructs a {@link FieldPosition} from it
 *
 * @param iterator
 *            the iterator to use
 * @return a new {@link FieldPosition}
 */
private static FieldPosition getFieldPosition(AttributedCharacterIterator iterator) {
	Set<Attribute> keySet = iterator.getAttributes().keySet();
	for (Attribute attribute : keySet) {
		if (attribute instanceof Field) {
			return getFieldPosition((Field) attribute, iterator);
		}
	}
	return getFieldPosition((Field) null, iterator);
}

/**
 * creates a {@link FieldPosition} out of a {@link Field} and and a
 * {@link AttributedCharacterIterator}s current position
 *
 * @param field
 *            the field to use
 * @param iterator
 *            the iterator to extract the data from
 * @return a {@link FieldPosition} init to this Field and begin/end index
 */
private static FieldPosition getFieldPosition(Field field, AttributedCharacterIterator iterator) {
	FieldPosition position = new FieldPosition(field);
	position.setBeginIndex(iterator.getRunStart());
	position.setEndIndex(iterator.getRunLimit());
	return position;
}

/**
 * Check if the given {@link FieldPosition} are considdered "the same", this is
 * when both are not <code>null</code> and reference the same
 * {@link java.text.Format.Field} attribute, or both of them have no
 * fieldattribute and have the same position
 *
 * @param p1
 *            first position to compare
 * @param p2
 *            second position to compare
 * @return <code>true</code> if considered the same, <code>false</code>
 *         otherwise
 */
private static boolean isSameField(FieldPosition p1, FieldPosition p2) {
	if (p1 == p2) {
		return true;
	}
	if (p1 == null || p2 == null) {
		return false;
	}
	if (p1.getFieldAttribute() == null && p2.getFieldAttribute() == null) {
		return p1.equals(p2);
	}
	if (p1.getFieldAttribute() == null) {
		return false;
	}
	return p1.getFieldAttribute().equals(p2.getFieldAttribute());
}

/**
 * Extracts the calendarfield for the given fieldposition
 *
 * @param fieldPosition
 * @return the {@link Calendar} field or -1 if this is not a valid Fieldposition
 */
private static int getCalendarField(FieldPosition fieldPosition) {
	if ((fieldPosition.getFieldAttribute() instanceof Field)) {
		return getCalendarField((Field) fieldPosition.getFieldAttribute());
	} else {
		return -1;
	}
}

/**
 * Extracts the calendarfield transforming HOUR1 types to HOUR0
 *
 * @param field
 * @return the calendarfield coresponding to the {@link Field}
 */
private static int getCalendarField(Field field) {
	if (Field.HOUR1.equals(field)) {
		field = Field.HOUR0;
	} else if (Field.HOUR_OF_DAY1.equals(field)) {
		field = Field.HOUR_OF_DAY0;
	}
	return field.getCalendarField();
}

}