/*******************************************************************************
 * Copyright (c) 2000, 2020 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
 *     Lars Vogel <Lars.Vogel@vogella.com> - Bug 483540
 *******************************************************************************/
package org.eclipse.swt.widgets;

import org.eclipse.swt.*;
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.*;

/**
 * Instances of this class are controls that allow the user
 * to choose an item from a list of items, or optionally
 * enter a new value by typing it into an editable text
 * field. Often, <code>Combo</code>s are used in the same place
 * where a single selection <code>List</code> widget could
 * be used but space is limited. A <code>Combo</code> takes
 * less space than a <code>List</code> widget and shows
 * similar information.
 * <p>
 * Note: Since <code>Combo</code>s can contain both a list
 * and an editable text field, it is possible to confuse methods
 * which access one versus the other (compare for example,
 * <code>clearSelection()</code> and <code>deselectAll()</code>).
 * The API documentation is careful to indicate either "the
 * receiver's list" or the "the receiver's text field" to
 * distinguish between the two cases.
 * </p><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>DROP_DOWN, READ_ONLY, SIMPLE</dd>
 * <dt><b>Events:</b></dt>
 * <dd>DefaultSelection, Modify, Selection, Verify, OrientationChange</dd>
 * </dl>
 * <p>
 * Note: Only one of the styles DROP_DOWN and SIMPLE may be specified.
 * </p><p>
 * IMPORTANT: This class is <em>not</em> intended to be subclassed.
 * </p>
 *
 * @see List
 * @see <a href="http://www.eclipse.org/swt/snippets/#combo">Combo 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>
 * @noextend This class is not intended to be subclassed by clients.
 */
public class Combo extends Composite {
	long buttonHandle, entryHandle, textRenderer, cellHandle, popupHandle, menuHandle,
		buttonBoxHandle, cellBoxHandle, arrowHandle;
	int lastEventTime, visibleCount = 10;
	long imContext;
	long gdkEventKey = 0;
	int fixStart = -1, fixEnd = -1;
	String [] items = new String [0];
	int indexSelected;
	GdkRGBA background, buttonBackground;
	String cssButtonBackground, cssButtonForeground = " ";
	long buttonProvider, comboProvider;
	boolean firstDraw = true;
	boolean unselected = true, fitModelToggled = false;
	/**
	 * the operating system limit for the number of characters
	 * that the text field in an instance of this class can hold
	 */
	public final static int LIMIT;

	/*
	* These values can be different on different platforms.
	* Therefore they are not initialized in the declaration
	* to stop the compiler from inlining.
	*/
	static {
		LIMIT = 0xFFFF;
	}

	private boolean delayedEnableWrap = false; // Bug 489640. Gtk3.

/**
 * 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#DROP_DOWN
 * @see SWT#READ_ONLY
 * @see SWT#SIMPLE
 * @see Widget#checkSubclass
 * @see Widget#getStyle
 */
public Combo (Composite parent, int style) {
	super (parent, checkStyle (style));
}

/**
 * Adds the argument to the end of the receiver's list.
 * <p>
 * Note: If control characters like '\n', '\t' etc. are used
 * in the string, then the behavior is platform dependent.
 * </p>
 * @param string the new item
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the string 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 #add(String,int)
 */
public void add (String string) {
	checkWidget();
	if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
	add (string, items.length);
}

/**
 * Adds the argument to the receiver's list at the given
 * zero-relative index.
 * <p>
 * Note: To add an item at the end of the list, use the
 * result of calling <code>getItemCount()</code> as the
 * index or use <code>add(String)</code>.
 * </p><p>
 * Also note, if control characters like '\n', '\t' etc. are used
 * in the string, then the behavior is platform dependent.
 * </p>
 *
 * @param string the new item
 * @param index the index for the item
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the string is null</li>
 *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list (inclusive)</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 #add(String)
 */
public void add(String string, int index) {
	checkWidget();
	if (string == null) error(SWT.ERROR_NULL_ARGUMENT);
	if (!(0 <= index && index <= items.length)) {
		error(SWT.ERROR_INVALID_RANGE);
	}

	String [] newItems = new String [items.length + 1];
	System.arraycopy (items, 0, newItems, 0, index);
	newItems [index] = string;
	System.arraycopy (items, index, newItems, index + 1, items.length - index);
	items = newItems;

	gtk_combo_box_insert(string, index);
	if ((style & SWT.RIGHT_TO_LEFT) != 0 && popupHandle != 0) {
		GTK3.gtk_container_forall (popupHandle, display.setDirectionProc, GTK.GTK_TEXT_DIR_RTL);
	}
}

private void gtk_combo_box_insert(String string, int index) {
	byte[] buffer = Converter.wcsToMbcs(string, true);
	if (handle != 0) {
		gtk_combo_box_toggle_wrap(false);
		GTK.gtk_combo_box_text_insert (handle, index, null, buffer);
		gtk_combo_box_toggle_wrap(true);
	}
}

/**
 * <p>Bug 489640, 438992. Drop-down appearance.</p>
 *
 * <p>In Gtk3, there is a lot of white space at the top of the combo drop-down.
 *   It's meant to put the first item near the cursor (See screen shots in bug 438992), but makes eclipse look buggy.</p>
 *
 * <p>Solution (438992): gtk_combo_box_get_wrap_width(1) fixes this problem, but introduces a performance regression.
 *    When multiple items are added in a loop, then if 'wrap' is enabled then after every insertion, gtk
 *    traverses the entire list and greedily re-computes the drop-down list size.
 *    This causes O(n^2) performance regression in that the longer the list, the longer the size computation takes.
 *    E.g Adding 1000 items takes almost 30 seconds.</p>
 *
 * <p>Solution ^2 (489640): We enabled wrap in a delayed/lazy way, only when display event loop is ran.
 *   This way the insertions occur at O(n) speed and we get the benefit of a neat drop-down list when the user launches the application.
 *   Run-time insertions and combo.add(..) are also covered by this logic.</p>
 *
 * <p>Gtk4 port note:
 *  - Note, Combo was re-written in Gtk3 and it will be re-written again in Gtk4. See:
 *  https://mail.gnome.org/archives/gtk-list/2016-December/msg00036.html
 *  https://raw.githubusercontent.com/gnome-design-team/gnome-mockups/master/theming/widgets/combobox-replacements.png     // mockup screen shot.
 *  - So probably this workaround should be removed in Gtk4 port. Feel free to validate via Bug489640_SlowCombo and Bug489640_SlowComboSingleItem test snippets.</p>
 *
 * <p>CSS note: Do not use the CSS 'appears-as-list' style as done in:
 *   https://git.eclipse.org/r/#/c/117681/6/bundles/org.eclipse.swt/Eclipse+SWT/gtk/org/eclipse/swt/widgets/Combo.java
 *   It's a poorly working hack. If list has more than +-1000 entries, then we get visual cheese and jvm crashes. </p>
 */
private void gtk_combo_box_toggle_wrap (boolean wrap) {
	if (handle == 0 || GTK.GTK4) return;
	if (!wrap) {
		if (GTK.gtk_combo_box_get_wrap_width(handle) == 1) {
			GTK.gtk_combo_box_set_wrap_width(handle, 0);
		}
	} else  {
		if (delayedEnableWrap) {
			return;
		} else {
			delayedEnableWrap = true;
			display.asyncExec(() -> {
				if (!isDisposed() && handle != 0) {
					GTK.gtk_combo_box_set_wrap_width(handle, 1);
					delayedEnableWrap = false;
				}
			});
		}
	}
}

/**
 * Adds the listener to the collection of listeners who will
 * be notified when the receiver's text is modified, by sending
 * it one of the messages defined in the <code>ModifyListener</code>
 * interface.
 *
 * @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 ModifyListener
 * @see #removeModifyListener
 */
public void addModifyListener (ModifyListener listener) {
	checkWidget();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	TypedListener typedListener = new TypedListener (listener);
	addListener (SWT.Modify, typedListener);
}

/**
 * Adds a segment listener.
 * <p>
 * A <code>SegmentEvent</code> is sent whenever text content is being modified or
 * a segment listener is added or removed. You can
 * customize the appearance of text by indicating certain characters to be inserted
 * at certain text offsets. This may be used for bidi purposes, e.g. when
 * adjacent segments of right-to-left text should not be reordered relative to
 * each other.
 * E.g., multiple Java string literals in a right-to-left language
 * should generally remain in logical order to each other, that is, the
 * way they are stored.
 * </p>
 * <p>
 * <b>Warning</b>: This API is currently only implemented on Windows.
 * <code>SegmentEvent</code>s won't be sent on GTK and Cocoa.
 * </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 SegmentEvent
 * @see SegmentListener
 * @see #removeSegmentListener
 *
 * @since 3.103
 */
public void addSegmentListener (SegmentListener listener) {
	checkWidget ();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	addListener (SWT.Segments, new TypedListener (listener));
}

/**
 * Adds the listener to the collection of listeners who will
 * be notified when the user changes the receiver's selection, 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 combo's list selection.
 * <code>widgetDefaultSelected</code> is typically called when ENTER is pressed the combo's text area.
 * </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);
}

/**
 * Adds the listener to the collection of listeners who will
 * be notified when the receiver's text is verified, by sending
 * it one of the messages defined in the <code>VerifyListener</code>
 * interface.
 *
 * @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 VerifyListener
 * @see #removeVerifyListener
 *
 * @since 3.1
 */
public void addVerifyListener (VerifyListener listener) {
	checkWidget ();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	TypedListener typedListener = new TypedListener (listener);
	addListener (SWT.Verify, typedListener);
}

static int checkStyle (int style) {
	/*
	* Feature in Windows.  It is not possible to create
	* a combo box that has a border using Windows style
	* bits.  All combo boxes draw their own border and
	* do not use the standard Windows border styles.
	* Therefore, no matter what style bits are specified,
	* clear the BORDER bits so that the SWT style will
	* match the Windows widget.
	*
	* The Windows behavior is currently implemented on
	* all platforms.
	*/
	style &= ~SWT.BORDER;

	/*
	* 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.DROP_DOWN, SWT.SIMPLE, 0, 0, 0, 0);
	if ((style & SWT.SIMPLE) != 0) return style & ~SWT.READ_ONLY;
	return style;
}

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

/**
 * Sets the selection in the receiver's text field to an empty
 * selection starting just before the first character. If the
 * text field is editable, this has the effect of placing the
 * i-beam at the start of the text.
 * <p>
 * Note: To clear the selected items in the receiver's list,
 * use <code>deselectAll()</code>.
 * </p>
 *
 * @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 #deselectAll
 */
public void clearSelection () {
	checkWidget();
	if (entryHandle != 0) {
		int position = GTK.gtk_editable_get_position (entryHandle);
		GTK.gtk_editable_select_region (entryHandle, position, position);
	}
}

void clearText () {
	OS.g_signal_handlers_block_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, CHANGED);
	if ((style & SWT.READ_ONLY) != 0) {
		int index = GTK.gtk_combo_box_get_active (handle);
		if (index != -1) {
			long modelHandle = GTK.gtk_combo_box_get_model (handle);
			long [] ptr = new long [1];
			long iter = OS.g_malloc (GTK.GtkTreeIter_sizeof ());
			GTK.gtk_tree_model_iter_nth_child (modelHandle, iter, 0, index);
			GTK.gtk_tree_model_get (modelHandle, iter, 0, ptr, -1);
			OS.g_free (iter);
			if (ptr [0] != 0 && C.strlen (ptr [0]) > 0) postEvent (SWT.Modify);
			OS.g_free (ptr [0]);
		}
	} else {
		if (GTK.GTK4) {
			long bufferHandle = GTK.gtk_entry_get_buffer(entryHandle);
			GTK.gtk_entry_buffer_delete_text(bufferHandle, 0, -1);
		} else {
			GTK.gtk_entry_set_text(entryHandle, new byte[1]);
		}
	}
	GTK.gtk_combo_box_set_active (handle, -1);
	OS.g_signal_handlers_unblock_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, CHANGED);
}

@Override
Point computeSizeInPixels (int wHint, int hHint, boolean changed) {
	checkWidget ();
	return computeNativeSize (handle, wHint, hHint, changed);
}

@Override
Point computeNativeSize (long h, int wHint, int hHint, boolean changed) {
	// Set fit-model property when computing size, if it was previously disabled
	if (fitModelToggled) {
		GTK.gtk_cell_view_set_fit_model(cellHandle, true);
	}
	int [] xpad = new int[1];
	if (textRenderer != 0) GTK.gtk_cell_renderer_get_padding(textRenderer, xpad, null);
	Point nativeSize = super.computeNativeSize(h, wHint, hHint, changed);
	nativeSize.x += xpad[0] * 2;

	/*
	 * Bug 545344 - [GTK3] Read only Combo text small cutoff on Linux, button.combo padding not taken into account
	 *
	 * A read only combo will use a GtkComboBoxText widget, which can be influenced by a css node:
	 *
	 * combobox button.combo
	 *
	 * This node can specify additional padding; if this padding is not taken into account,
	 * Not all of the combo items text will be displayed. Some letters will be cut off, depending on how high the padding is set.
	 */
	if ((style & SWT.READ_ONLY) != 0 && !GTK.GTK4 && GTK.GTK_VERSION >= OS.VERSION(3, 22, 0)) {
		GtkBorder buttonPadding = new GtkBorder();
		long context = GTK.gtk_widget_get_style_context (buttonHandle);
		int stateFlag = GTK.gtk_widget_get_state_flags(buttonHandle);
		gtk_style_context_get_padding(context, stateFlag, buttonPadding);
		nativeSize.x += buttonPadding.left + buttonPadding.right;
	}

	// Re-set fit-model to false as it was before
	if (fitModelToggled) {
		GTK.gtk_cell_view_set_fit_model(cellHandle, false);
	}
	return nativeSize;
}

/**
 * Copies the selected text.
 * <p>
 * The current selection is copied to the clipboard.
 * </p>
 *
 * @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 2.1
 */
public void copy () {
	checkWidget ();
	if (entryHandle != 0) {
		if (GTK.GTK4) {
			long textHandle = GTK.gtk_widget_get_first_child(entryHandle);
			GTK.gtk_widget_activate_action(textHandle, OS.action_copy_clipboard, null);
		} else {
			GTK.gtk_editable_copy_clipboard(entryHandle);
		}
	}
}

@Override
void createHandle (int index) {
	state |= HANDLE | MENU;

	fixedHandle = OS.g_object_new(display.gtk_fixed_get_type(), 0);
	if (fixedHandle == 0) error(SWT.ERROR_NO_HANDLES);
	if (!GTK.GTK4) GTK.gtk_widget_set_has_window(fixedHandle, true);

	long oldList = GTK.gtk_window_list_toplevels();
	if ((style & SWT.READ_ONLY) != 0) {
		handle = GTK.gtk_combo_box_text_new();
		if (handle == 0) error(SWT.ERROR_NO_HANDLES);

		cellHandle = GTK.GTK4 ? GTK.gtk_combo_box_get_child(handle) : GTK3.gtk_bin_get_child (handle);
		if (cellHandle == 0) error(SWT.ERROR_NO_HANDLES);

		gtk_combo_box_toggle_wrap(true);
	} else {
		handle = GTK.gtk_combo_box_text_new_with_entry();
		if (handle == 0) error(SWT.ERROR_NO_HANDLES);

		entryHandle = GTK.GTK4 ? GTK.gtk_combo_box_get_child(handle) : GTK3.gtk_bin_get_child(handle);
		if (entryHandle == 0) error(SWT.ERROR_NO_HANDLES);

		imContext = OS.imContextLast();
	}

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

	textRenderer = GTK.gtk_cell_renderer_text_new();
	if (textRenderer == 0) error(SWT.ERROR_NO_HANDLES);

	GTK.gtk_cell_layout_clear (handle);
	GTK.gtk_cell_layout_pack_start (handle, textRenderer, true);
	GTK.gtk_cell_layout_set_attributes (handle, textRenderer, OS.text, 0, 0);

	/*
	* Feature in GTK. Toggle button creation differs between GTK versions. The
	* fix is to call size_request() to force the creation of the button
	* for those versions of GTK that defer the creation.
	*/
	menuHandle = findMenuHandle();
	if (menuHandle != 0) OS.g_object_ref (menuHandle);
	buttonHandle = findButtonHandle ();
	if (buttonHandle != 0) OS.g_object_ref (buttonHandle);
	if (buttonBoxHandle != 0) OS.g_object_ref (buttonBoxHandle);
	if (cellHandle != 0) cellBoxHandle = GTK.gtk_widget_get_parent(cellHandle);
	if (cellBoxHandle != 0) OS.g_object_ref(cellBoxHandle);
	/*
	* Feature in GTK. By default, read only combo boxes
	* process the RETURN key rather than allowing the
	* default button to process the key. The fix is to
	* clear the GTK_RECEIVES_DEFAULT flag.
	*/
	if ((style & SWT.READ_ONLY) != 0 && buttonHandle != 0) {
		GTK.gtk_widget_set_receives_default (buttonHandle, false);
	}
	/*
	 * Find the arrowHandle, which is the handle belonging to the GtkIcon
	 * drop down arrow. See bug 539367.
	 */
	if ((style & SWT.READ_ONLY) != 0) {
		if (cellBoxHandle != 0) arrowHandle = findArrowHandle();
	}
	// 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);
}

/**
 * Cuts the selected text.
 * <p>
 * The current selection is first copied to the
 * clipboard and then deleted from the widget.
 * </p>
 *
 * @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 2.1
 */
public void cut () {
	checkWidget ();
	if (entryHandle != 0) {
		if (GTK.GTK4) {
			long textHandle = GTK.gtk_widget_get_first_child(entryHandle);
			GTK.gtk_widget_activate_action(textHandle, OS.action_cut_clipboard, null);
		} else {
			GTK.gtk_editable_cut_clipboard(entryHandle);
		}
	}
}

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

GdkRGBA defaultButtonBackground () {
	return display.getSystemColor(SWT.COLOR_WIDGET_BACKGROUND).handle;
}

@Override
void deregister () {
	super.deregister ();
	if (buttonHandle != 0) display.removeWidget (buttonHandle);
	if (entryHandle != 0) display.removeWidget (entryHandle);
	if (popupHandle != 0) display.removeWidget (popupHandle);
	if (menuHandle != 0) display.removeWidget (menuHandle);
	long imContext = imContext ();
	if (imContext != 0) display.removeWidget (imContext);
}

@Override
boolean filterKey (int keyval, long event) {
	int time = GDK.gdk_event_get_time (event);
	if (time != lastEventTime) {
		lastEventTime = time;
		long imContext = imContext ();
		if (imContext != 0) {
			if (GTK.GTK4)
				return GTK4.gtk_im_context_filter_keypress (imContext, event);
			else
				return GTK3.gtk_im_context_filter_keypress (imContext, event);
		}
	}
	gdkEventKey = event;
	return false;
}

long findPopupHandle (long oldList) {
	long result = 0;
	long currentList = GTK.gtk_window_list_toplevels();
	long oldFromList = oldList;
	long newFromList = OS.g_list_last(currentList);
	boolean isFound;
	while (newFromList != 0) {
		long newToplevel = OS.g_list_data(newFromList);
		isFound = false;
		oldFromList = oldList;
		while (oldFromList != 0) {
			long oldToplevel = OS.g_list_data(oldFromList);
			if (newToplevel == oldToplevel) {
				isFound = true;
				break;
			}
			oldFromList = OS.g_list_next(oldFromList);
		}
		if (!isFound) {
			result = newToplevel;
			break;
		}
		newFromList = OS.g_list_previous(newFromList);
	}
	OS.g_list_free(oldList);
	OS.g_list_free(currentList);
	return result;
}

@Override
Point resizeCalculationsGTK3 (long widget, int width, int height) {
	/*
	 * Combo is a complex widget which has many widgets inside of it.
	 * Some of these widgets have large natural and/or minimum sizes. To prevent
	 * API breakage, just set the width and height from setBounds().
	 * See bug 537713.
	 */
	return new Point (width, height);
}

long findButtonHandle() {
	/*
	* Feature in GTK.  There is no API to query the button
	* handle from a combo box although it is possible to get the
	* text field.  The button handle is needed to hook events.  The
	* fix is to walk the combo tree and find the first child that is
	* an instance of button.
	*/
	long result = 0;

	if (GTK.GTK4) {
		for (long child = GTK.gtk_widget_get_first_child(handle); child != 0; child = GTK.gtk_widget_get_next_sibling(child)) {
			if (GTK.GTK_IS_BOX(child)) {
				buttonBoxHandle = child;
				break;
			}
		}

		for (long child = GTK.gtk_widget_get_first_child(buttonBoxHandle); child != 0; child = GTK.gtk_widget_get_next_sibling(child)) {
			if (GTK.GTK_IS_BUTTON(child)) {
				result = child;
				break;
			}
		}
	} else {
		long childHandle = handle;
		/*
		 * The only direct child of GtkComboBox since 3.20 is GtkBox and
		 * gtk_container_forall iterates over direct children only so handle for the
		 * GtkBox has to be retrieved first.
		 * As it's internal child one can't get it in other way.
		 */
		GTK3.gtk_container_forall(handle, display.allChildrenProc, 0);
		if (display.allChildren != 0) {
			long list = display.allChildren;
			while (list != 0) {
				long widget = OS.g_list_data(list);
				if (widget != 0) {
					childHandle = widget;
					break;
				}
				list = OS.g_list_next(list);
			}
			OS.g_list_free(display.allChildren);
			display.allChildren = 0;
		}
		buttonBoxHandle = childHandle;

		GTK3.gtk_container_forall (childHandle, display.allChildrenProc, 0);
		if (display.allChildren != 0) {
			long list = display.allChildren;
			while (list != 0) {
				long widget = OS.g_list_data (list);
				if (GTK.GTK_IS_BUTTON (widget)) {
					result = widget;
					break;
				}
				list = OS.g_list_next (list);
			}
			OS.g_list_free (display.allChildren);
			display.allChildren = 0;
		}
	}

	return result;
}

long findArrowHandle() {
	long result = 0;

	if (cellBoxHandle != 0) {
		if (GTK.GTK4) {
			for (long child = GTK.gtk_widget_get_first_child(cellBoxHandle); child != 0; child = GTK.gtk_widget_get_next_sibling(child)) {
				String name = display.gtk_widget_get_name(child);
				if (name != null && name.equals("GtkBuiltinIcon")) {
					result = child;
					break;
				}
			}
		} else {
			GTK3.gtk_container_forall (cellBoxHandle, display.allChildrenProc, 0);
			if (display.allChildren != 0) {
				long list = display.allChildren;
				while (list != 0) {
					long widget = OS.g_list_data (list);
					/*
					 * Feature in GTK: GtkIcon isn't public, so we have to do
					 * type lookups using gtk_widget_get_name(). See bug 539367.
					 */
					String name = display.gtk_widget_get_name(widget);
					if (name != null && name.contains("GtkIcon")) {
						result = widget;
					}
					list = OS.g_list_next (list);
				}
				OS.g_list_free (display.allChildren);
				display.allChildren = 0;
			}
		}
	}

	return result;
}

long findMenuHandle() {
	/*
	* Feature in GTK.  There is no API to query the menu
	* handle from a combo box. So we walk the popupHandle to
	* find the handle for the menu.
	*/
	long result = 0;

	if (popupHandle != 0) {
		GTK3.gtk_container_forall(popupHandle, display.allChildrenProc, 0);
		if (display.allChildren != 0) {
			long list = display.allChildren;
			while (list != 0) {
				long widget = OS.g_list_data(list);
				String name = display.gtk_widget_get_name(widget);
				if (name != null && name.contains("gtk-combobox-popup-menu")) {
					result = widget;
					break;
				}
				list = OS.g_list_next(list);
			}
			OS.g_list_free(display.allChildren);
			display.allChildren = 0;
		}
	}

	return result;
}

@Override
void fixModal (long group, long modalGroup) {
	if (popupHandle != 0) {
		if (group != 0) {
			GTK.gtk_window_group_add_window (group, popupHandle);
		} else {
			if (modalGroup != 0) {
				GTK.gtk_window_group_remove_window (modalGroup, popupHandle);
			}
		}
	}
}

void fixIM () {
	/*
	*  The IM filter has to be called one time for each key press event.
	*  When the IM is open the key events are duplicated. The first event
	*  is filtered by SWT and the second event is filtered by GTK.  In some
	*  cases the GTK handler does not run (the widget is destroyed, the
	*  application code consumes the event, etc), for these cases the IM
	*  filter has to be called by SWT.
	*/
	if (gdkEventKey != 0 && gdkEventKey != -1) {
		long imContext = imContext ();
		if (imContext != 0) {
			if (GTK.GTK4)
				GTK4.gtk_im_context_filter_keypress (imContext, gdkEventKey);
			else
				GTK3.gtk_im_context_filter_keypress (imContext, gdkEventKey);

			gdkEventKey = -1;
			return;
		}
	}
	gdkEventKey = 0;
}

@Override
long fontHandle () {
	if (entryHandle != 0) return entryHandle;
	return super.fontHandle ();
}

@Override
long focusHandle () {
	if (entryHandle != 0) return entryHandle;
	return super.focusHandle ();
}

@Override
boolean hasFocus () {
	if (super.hasFocus ()) return true;
	if (entryHandle != 0 && GTK.gtk_widget_has_focus (entryHandle)) return true;
	return false;
}

@Override
void hookEvents () {
	super.hookEvents ();
	OS.g_signal_connect_closure (handle, OS.changed, display.getClosure (CHANGED), true);

	if (entryHandle != 0) {
		OS.g_signal_connect_closure (entryHandle, OS.changed, display.getClosure (CHANGED), true);
		OS.g_signal_connect_closure (entryHandle, OS.insert_text, display.getClosure (INSERT_TEXT), false);
		OS.g_signal_connect_closure (entryHandle, OS.delete_text, display.getClosure (DELETE_TEXT), false);
		OS.g_signal_connect_closure (entryHandle, OS.activate, display.getClosure (ACTIVATE), false);
		if (!GTK.GTK4) OS.g_signal_connect_closure (entryHandle, OS.populate_popup, display.getClosure (POPULATE_POPUP), false);
	}

	hookEvents(new long [] {buttonHandle, entryHandle, menuHandle});

	long imContext = imContext ();
	if (imContext != 0) {
		OS.g_signal_connect_closure (imContext, OS.commit, display.getClosure (COMMIT), false);
		int id = OS.g_signal_lookup (OS.commit, GTK.gtk_im_context_get_type ());
		int blockMask =  OS.G_SIGNAL_MATCH_DATA | OS.G_SIGNAL_MATCH_ID;
		OS.g_signal_handlers_block_matched (imContext, blockMask, id, 0, 0, 0, entryHandle);
	}
}

void hookEvents(long [] handles) {
	for (int i = 0; i < handles.length; i++) {
		long eventHandle = handles[i];
		if (eventHandle != 0) {
			if (GTK.GTK4) {
				long motionController = GTK.gtk_event_controller_motion_new();
				GTK.gtk_widget_add_controller(eventHandle, motionController);
				OS.g_signal_connect (motionController, OS.motion, display.enterMotionScrollProc, MOTION);
				OS.g_signal_connect (motionController, OS.motion, display.enterMotionScrollProc, MOTION_INVERSE);

				long gestureController = GTK.gtk_gesture_click_new();
				GTK.gtk_widget_add_controller(eventHandle, gestureController);
				OS.g_signal_connect(gestureController, OS.pressed, display.gesturePressReleaseProc, GESTURE_PRESSED);
				OS.g_signal_connect(gestureController, OS.released, display.gesturePressReleaseProc, GESTURE_RELEASED);

				//TODO: GTK4 event-after
			} else {
				int eventMask =	GDK.GDK_POINTER_MOTION_MASK | GDK.GDK_BUTTON_PRESS_MASK | GDK.GDK_BUTTON_RELEASE_MASK;
				GTK.gtk_widget_add_events (eventHandle, eventMask);
				OS.g_signal_connect_closure_by_id (eventHandle, display.signalIds [MOTION_NOTIFY_EVENT], 0, display.getClosure (MOTION_NOTIFY_EVENT), false);
				OS.g_signal_connect_closure_by_id (eventHandle, display.signalIds [MOTION_NOTIFY_EVENT], 0, display.getClosure (MOTION_NOTIFY_EVENT_INVERSE), true);

				OS.g_signal_connect_closure_by_id (eventHandle, display.signalIds [BUTTON_PRESS_EVENT], 0, display.getClosure (BUTTON_PRESS_EVENT), false);
				OS.g_signal_connect_closure_by_id (eventHandle, display.signalIds [BUTTON_RELEASE_EVENT], 0, display.getClosure (BUTTON_RELEASE_EVENT), false);

				/*
				* Feature in GTK3.  Events such as mouse move are propagated up
				* the widget hierarchy and are seen by the parent.  This is the
				* correct GTK behavior but not correct for SWT.  The fix is to
				* hook a signal after and stop the propagation using a negative
				* event number to distinguish this case.
				*/
				OS.g_signal_connect_closure_by_id (eventHandle, display.signalIds [BUTTON_PRESS_EVENT], 0, display.getClosure (BUTTON_PRESS_EVENT_INVERSE), true);
				OS.g_signal_connect_closure_by_id (eventHandle, display.signalIds [BUTTON_RELEASE_EVENT], 0, display.getClosure (BUTTON_RELEASE_EVENT_INVERSE), true);

				/* Connect the event_after signal for both key and mouse */
				if (eventHandle != focusHandle ()) {
					OS.g_signal_connect_closure_by_id (eventHandle, display.signalIds [EVENT_AFTER], 0, display.getClosure (EVENT_AFTER), false);
				}

				if (OS.G_OBJECT_TYPE (eventHandle) == GTK3.GTK_TYPE_MENU ()) {
					OS.g_signal_connect_closure(eventHandle, OS.selection_done, display.getClosure (SELECTION_DONE), true);
				}
			}
		}
	}
}

long imContext () {
	if (imContext != 0) return imContext;
	return 0;
}

/**
 * Deselects the item at the given zero-relative index in the receiver's
 * list.  If the item at the index was already deselected, it remains
 * deselected. Indices that are out of range are ignored.
 *
 * @param index the index of the item to deselect
 *
 * @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 deselect (int index) {
	checkWidget();
	if (index < 0 || index >= items.length) return;

	if (GTK.gtk_combo_box_get_active (handle) == index) {
		clearText ();
	}
}

/**
 * Deselects all selected items in the receiver's list.
 * <p>
 * Note: To clear the selection in the receiver's text field,
 * use <code>clearSelection()</code>.
 * </p>
 *
 * @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 #clearSelection
 */
public void deselectAll () {
	checkWidget();
	clearText();
}

@Override
boolean dragDetect(int x, int y, boolean filter, boolean dragOnTimeout, boolean[] consume) {
	if (filter && entryHandle != 0) {
		int [] index = new int [1];
		int [] trailing = new int [1];
		long layout = GTK.gtk_entry_get_layout (entryHandle);
		OS.pango_layout_xy_to_index (layout, x * OS.PANGO_SCALE, y * OS.PANGO_SCALE, index, trailing);
		long ptr = OS.pango_layout_get_text (layout);
		int position = (int)OS.g_utf8_pointer_to_offset (ptr, ptr + index[0]) + trailing[0];
		int [] start = new int [1];
		int [] end = new int [1];
		GTK.gtk_editable_get_selection_bounds (entryHandle, start, end);
		if (start [0] <= position && position < end [0]) {
			if (super.dragDetect (x, y, filter, dragOnTimeout, consume)) {
				if (consume != null) consume [0] = true;
				return true;
			}
		}
		return false;
	}
	return super.dragDetect (x, y, filter, dragOnTimeout, consume);
}

@Override
long enterExitHandle () {
	return fixedHandle;
}

@Override
long eventWindow () {
	if ((style & SWT.READ_ONLY) != 0) {
		GTK.gtk_widget_realize (handle);
		return gtk_widget_get_window (handle);
	}

	/*
	 * Single-line Text (GtkEntry in GTK) uses a GDK_INPUT_ONLY
	 * internal window. This window can't be used for any kind
	 * of painting, but this is the window to which functions
	 * like Control.setCursor() should apply.
	 */
	GTK.gtk_widget_realize (entryHandle);
	long window = gtk_widget_get_window (entryHandle);
	// Find the internal GDK_INPUT_ONLY window
	long children = GDK.gdk_window_get_children (window);
	if (children != 0) {
		do {
			window = OS.g_list_data (children);
		} while ((children = OS.g_list_next (children)) != 0);
	}
	OS.g_list_free (children);

	return window;
}

@Override
long eventSurface () {
	return paintSurface ();
}

/**
 * Returns a point describing the location of the caret relative
 * to the receiver.
 *
 * @return a point, the location of the caret
 *
 * @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.8
 */
public Point getCaretLocation () {
	checkWidget ();
	return DPIUtil.autoScaleDown(getCaretLocationInPixels());
}


Point getCaretLocationInPixels () {
	checkWidget ();
	if ((style & SWT.READ_ONLY) != 0) {
		return new Point (0, 0);
	}
	int index = GTK.gtk_editable_get_position (entryHandle);
	index = GTK.gtk_entry_text_index_to_layout_index (entryHandle, index);
	int [] offset_x = new int [1], offset_y = new int [1];
	GTK.gtk_entry_get_layout_offsets (entryHandle, offset_x, offset_y);
	long layout = GTK.gtk_entry_get_layout (entryHandle);
	PangoRectangle pos = new PangoRectangle ();
	OS.pango_layout_index_to_pos (layout, index, pos);
	Point thickness = getThickness (entryHandle);
	int x = offset_x [0] + OS.PANGO_PIXELS (pos.x) - getBorderWidthInPixels () - thickness.x;
	int y = offset_y [0] + OS.PANGO_PIXELS (pos.y) - thickness.y;
	return new Point (x, y);
}

/**
 * Returns the character position of the caret.
 * <p>
 * Indexing is zero based.
 * </p>
 *
 * @return the position of the caret
 *
 * @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.8
 */
public int getCaretPosition () {
	checkWidget ();
	if ((style & SWT.READ_ONLY) != 0) {
		return 0;
	}
	long ptr = GTK.gtk_entry_get_text (entryHandle);
	return (int)OS.g_utf8_offset_to_utf16_offset (ptr, GTK.gtk_editable_get_position (entryHandle));
}

@Override
GdkRGBA getContextBackgroundGdkRGBA () {
	if (background != null && (state & BACKGROUND) != 0) {
		return background;
	}
	return defaultBackground();
}

/**
 * Returns the item at the given, zero-relative index in the
 * receiver's list. Throws an exception if the index is out
 * of range.
 *
 * @param index the index of the item to return
 * @return the item at the given index
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</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>
 */
public String getItem (int index) {
	checkWidget();
	if (!(0 <= index && index < items.length)) {
		error (SWT.ERROR_INVALID_RANGE);
	}
	return items [index];
}

/**
 * Returns the number of items contained in the receiver's list.
 *
 * @return the number of items
 *
 * @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 getItemCount () {
	checkWidget();
	return items.length;
}

/**
 * Returns the height of the area which would be used to
 * display <em>one</em> of the items in the receiver's list.
 *
 * @return the height of one item
 *
 * @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 getItemHeight () {
	checkWidget();

	long fontDesc = getFontDescription ();
	int result = fontHeight (fontDesc, handle);
	OS.pango_font_description_free(fontDesc);

	return result;
}

/**
 * Returns a (possibly empty) array of <code>String</code>s which are
 * the items in the receiver's list.
 * <p>
 * Note: This is not the actual structure used by the receiver
 * to maintain its list of items, so modifying the array will
 * not affect the receiver.
 * </p>
 *
 * @return the items in the receiver's list
 *
 * @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 String[] getItems() {
	checkWidget();
	String [] result = new String [items.length];
	System.arraycopy (items, 0, result, 0, items.length);
	return result;
}

/**
 * Returns <code>true</code> if the receiver's list is visible,
 * and <code>false</code> otherwise.
 * <p>
 * If one of the receiver's ancestors is not visible or some
 * other condition makes the receiver not visible, this method
 * may still indicate that it is considered visible even though
 * it may not actually be showing.
 * </p>
 *
 * @return the receiver's list's visibility state
 *
 * @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 boolean getListVisible () {
	checkWidget ();
	return popupHandle != 0 && GTK.gtk_widget_get_visible (popupHandle);
}

@Override
String getNameText () {
	return getText ();
}

/**
 * Returns the orientation of the receiver.
 *
 * @return the orientation style
 *
 * @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 2.1.2
 */
@Override
public int getOrientation () {
	return super.getOrientation ();
}

/**
 * Returns a <code>Point</code> whose x coordinate is the
 * character position representing the start of the selection
 * in the receiver's text field, and whose y coordinate is the
 * character position representing the end of the selection.
 * An "empty" selection is indicated by the x and y coordinates
 * having the same value.
 * <p>
 * Indexing is zero based.  The range of a selection is from
 * 0..N where N is the number of characters in the widget.
 * </p>
 *
 * @return a point representing the selection start and end
 *
 * @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 Point getSelection () {
	checkWidget ();
	if ((style & SWT.READ_ONLY) != 0) {
		int length = 0;
		int index = GTK.gtk_combo_box_get_active (handle);
		if (index != -1) length = getItem (index).length ();
		return new Point (0, length);
	}
	int [] start = new int [1];
	int [] end = new int [1];
	if (entryHandle != 0) {
		GTK.gtk_editable_get_selection_bounds (entryHandle, start, end);
		long ptr = GTK.gtk_entry_get_text (entryHandle);
		start[0] = (int)OS.g_utf8_offset_to_utf16_offset (ptr, start[0]);
		end[0] = (int)OS.g_utf8_offset_to_utf16_offset (ptr, end[0]);
	}
	return new Point(start [0], end [0]);
}

/**
 * Returns the zero-relative index of the item which is currently
 * selected in the receiver's list, or -1 if no item is selected.
 *
 * @return the index of the selected item
 *
 * @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 getSelectionIndex () {
	checkWidget();
	return GTK.gtk_combo_box_get_active (handle);
}

/**
 * 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 the receiver'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>
 */
public String getText () {
	checkWidget();

	if (entryHandle != 0) {
		long str = 0;
		if (GTK.GTK4) {
			long bufferHandle = GTK.gtk_entry_get_buffer(entryHandle);
			str = GTK.gtk_entry_buffer_get_text(bufferHandle);
		} else {
			str = GTK.gtk_entry_get_text(entryHandle);
		}

		if (str == 0) {
			return "";
		} else {
			int length = C.strlen (str);
			byte[] buffer = new byte[length];
			C.memmove(buffer, str, length);
			return new String (Converter.mbcsToWcs(buffer));
		}
	} else {
		int index = GTK.gtk_combo_box_get_active (handle);
		return index != -1 ? getItem (index) : "";
	}
}

String getText (int start, int stop) {
	/*
	* NOTE: The current implementation uses substring ()
	* which can reference a potentially large character
	* array.
	*/
	return getText ().substring (start, stop - 1);
}

/**
 * Returns the height of the receivers's text field.
 *
 * @return the text height
 *
 * @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 getTextHeight () {
	checkWidget();
	return DPIUtil.autoScaleDown(getTextHeightInPixels());
}


int getTextHeightInPixels () {
	checkWidget();
	GtkRequisition requisition = new GtkRequisition ();
	gtk_widget_get_preferred_size (handle, requisition);
	return requisition.height;
}

/**
 * Returns the maximum number of characters that the receiver's
 * text field is capable of holding. If this has not been changed
 * by <code>setTextLimit()</code>, it will be the constant
 * <code>Combo.LIMIT</code>.
 *
 * @return the text limit
 *
 * @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 #LIMIT
 */
public int getTextLimit () {
	checkWidget();
	int limit = entryHandle != 0 ? GTK.gtk_entry_get_max_length (entryHandle) : 0;
	return limit == 0 ? LIMIT : limit;
}

/**
 * Gets the number of items that are visible in the drop
 * down portion of the receiver's list.
 * <p>
 * Note: This operation is a hint and is not supported on
 * platforms that do not have this concept.
 * </p>
 *
 * @return the number of items that are visible
 *
 * @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.0
 */
public int getVisibleItemCount () {
	checkWidget ();
	return visibleCount;
}

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

@Override
long gtk_button_press_event (long widget, long event) {
	/*
	* Feature in GTK. Depending on where the user clicks, GTK prevents
	* the left mouse button event from being propagated. The fix is to
	* send the mouse event from the event_after handler.
	*/
	int [] eventButton = new int [1];
	if (GTK.GTK4) {
		eventButton[0] = GDK.gdk_button_event_get_button(event);
	} else {
		GDK.gdk_event_get_button(event, eventButton);
	}

	int eventType = GDK.gdk_event_get_event_type(event);
	if (eventType == GDK.GDK_BUTTON_PRESS && eventButton[0] == 1) {
		return gtk_button_press_event(widget, event, false);
	}
	return super.gtk_button_press_event (widget, event);
}

@Override
long gtk_changed (long widget) {
	if (widget == handle) {
		unselected = false;
		if (entryHandle == 0) {
			sendEvent(SWT.Modify);
			if (isDisposed ()) return 0;
		}
		/*
		* Feature in GTK.  GTK emits a changed signal whenever
		* the contents of a combo box are altered by typing or
		* by selecting an item in the list, but the event should
		* only be sent when the list is selected. The fix is to
		* only send out a selection event when there is a selected
		* item.
		*
		* NOTE: This code relies on GTK clearing the selected
		* item and not matching the item as the user types.
		*/
		int index = GTK.gtk_combo_box_get_active (handle);
		if (index != -1) sendSelectionEvent (SWT.Selection);
		indexSelected = -1;
		return 0;
	}
	/*
	* Feature in GTK.  When the user types, GTK positions
	* the caret after sending the changed signal.  This
	* means that application code that attempts to position
	* the caret during a changed signal will fail.  The fix
	* is to post the modify event when the user is typing.
	*/
	boolean keyPress = false;
	long eventPtr = GTK.GTK4 ? 0 : GTK3.gtk_get_current_event ();
	if (eventPtr != 0) {
		int eventType = GDK.gdk_event_get_event_type(eventPtr);
		eventType = fixGdkEventTypeValues(eventType);
		switch (eventType) {
			case GDK.GDK_KEY_PRESS:
				keyPress = true;
				break;
		}
		gdk_event_free (eventPtr);
	}
	if (keyPress) {
		postEvent (SWT.Modify);
	} else {
		sendEvent (SWT.Modify);
	}
	return 0;
}

@Override
long gtk_commit (long imContext, long text) {
	if (text == 0) return 0;
	if (!GTK.gtk_editable_get_editable (entryHandle)) return 0;
	int length = C.strlen (text);
	if (length == 0) return 0;
	byte [] buffer = new byte [length];
	C.memmove (buffer, text, length);
	char [] chars = Converter.mbcsToWcs (buffer);
	char [] newChars = sendIMKeyEvent (SWT.KeyDown, 0, chars);
	if (newChars == null) return 0;
	/*
	* Feature in GTK.  For a GtkEntry, during the insert-text signal,
	* GTK allows the programmer to change only the caret location,
	* not the selection.  If the programmer changes the selection,
	* the new selection is lost.  The fix is to detect a selection
	* change and set it after the insert-text signal has completed.
	*/
	fixStart = fixEnd = -1;
	OS.g_signal_handlers_block_matched (imContext, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, COMMIT);
	int id = OS.g_signal_lookup (OS.commit, GTK.gtk_im_context_get_type ());
	int mask =  OS.G_SIGNAL_MATCH_DATA | OS.G_SIGNAL_MATCH_ID;
	OS.g_signal_handlers_unblock_matched (imContext, mask, id, 0, 0, 0, entryHandle);
	if (newChars == chars) {
		OS.g_signal_emit_by_name (imContext, OS.commit, text);
	} else {
		buffer = Converter.wcsToMbcs (newChars, true);
		OS.g_signal_emit_by_name (imContext, OS.commit, buffer);
	}
	OS.g_signal_handlers_unblock_matched (imContext, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, COMMIT);
	OS.g_signal_handlers_block_matched (imContext, mask, id, 0, 0, 0, entryHandle);
	if (fixStart != -1 && fixEnd != -1) {
		GTK.gtk_editable_set_position (entryHandle, fixStart);
		GTK.gtk_editable_select_region (entryHandle, fixStart, fixEnd);
	}
	fixStart = fixEnd = -1;
	return 0;
}

@Override
long gtk_delete_text (long widget, long start_pos, long end_pos) {
	if (!hooks (SWT.Verify) && !filters (SWT.Verify)) return 0;
	long ptr = GTK.gtk_entry_get_text (entryHandle);
	if (end_pos == -1) end_pos = OS.g_utf8_strlen (ptr, -1);
	int start = (int)OS.g_utf8_offset_to_utf16_offset (ptr, start_pos);
	int end = (int)OS.g_utf8_offset_to_utf16_offset (ptr, end_pos);
	String newText = verifyText ("", start, end);
	if (newText == null) {
		OS.g_signal_stop_emission_by_name (entryHandle, OS.delete_text);
	} else {
		if (newText.length () > 0) {
			int [] pos = new int [1];
			pos [0] = (int)end_pos;
			byte [] buffer = Converter.wcsToMbcs (newText, false);
			OS.g_signal_handlers_block_matched (entryHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, CHANGED);
			OS.g_signal_handlers_block_matched (entryHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, INSERT_TEXT);
			GTK.gtk_editable_insert_text (entryHandle, buffer, buffer.length, pos);
			OS.g_signal_handlers_unblock_matched (entryHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, INSERT_TEXT);
			OS.g_signal_handlers_unblock_matched (entryHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, CHANGED);
			GTK.gtk_editable_set_position (entryHandle, pos [0]);
		}
	}
	return 0;
}

@Override
void adjustChildClipping (long widget) {
	/*
	 * When adjusting the GtkCellView's clip, take into account
	 * the position of the "arrow" icon. We set the clip of the
	 * GtkCellView to the icon's position, minus the icon's width.
	 *
	 * This ensures the text never draws longer than the Combo itself.
	 * See bug 539367.
	 */
	if (widget == cellHandle && (style & SWT.READ_ONLY) != 0 && !unselected) {
		/*
		 * Set "fit-model" mode for READ_ONLY Combos on GTK3.20+ to false.
		 * This means the GtkCellView rendering the text can be set to
		 * a size other than the maximum. See bug 539367.
		 */
		if (!fitModelToggled) {
			GTK.gtk_cell_view_set_fit_model(cellHandle, false);
			fitModelToggled = true;
		}
		GtkAllocation iconAllocation = new GtkAllocation ();
		GTK.gtk_widget_get_allocation(arrowHandle, iconAllocation);
		GtkAllocation cellViewAllocation = new GtkAllocation ();
		GTK.gtk_widget_get_allocation(cellHandle, cellViewAllocation);

		cellViewAllocation.width = (iconAllocation.x - iconAllocation.width);
		GTK.gtk_widget_set_clip(widget, cellViewAllocation);
		return;
	} else {
		super.adjustChildClipping(widget);
	}
}

@Override
long gtk_draw (long widget, long cairo) {
	/*
	 * Feature in GTK3.20+: Combos have their clip unioned
	 * with the parent container (Composite in this case). This causes
	 * overdrawing into neighbouring widgets and breaks resizing.
	 *
	 * The fix is to adjust the clip and allocation of the Combo (and its children)
	 * in the parent Composite's draw handler, as it ensures that the draw events
	 * going to the Combo have the correct geometry specifications. This has to
	 * happen in the parent Composite since neighouring widgets that share the
	 * same parent are affected. See bug 500703.
	 *
	 * An additional fix was implemented to support non-READ_ONLY Combos, as well
	 * as the case when one Composite has multiple Combos within it -- see bug 535323.
	 */
	long parentHandle = GTK.gtk_widget_get_parent(fixedHandle);
	if (parentHandle != 0) {
		if (parent.fixClipHandle == 0) parent.fixClipHandle = parentHandle;
		if (firstDraw) {
			if ((style & SWT.READ_ONLY) != 0) {
				long [] array = {fixedHandle, handle, buttonBoxHandle, buttonHandle, cellBoxHandle, cellHandle};
				parent.fixClipMap.put(this, array);
			} else {
				long [] array = {fixedHandle, handle, entryHandle, buttonBoxHandle, buttonHandle};
				parent.fixClipMap.put(this, array);
			}
			firstDraw = false;
			GTK.gtk_widget_queue_draw(parentHandle);
		}
	}
	return super.gtk_draw(widget, cairo);
}

@Override
long gtk_event_after (long widget, long gdkEvent)  {
	/*
	* Feature in GTK. Depending on where the user clicks, GTK prevents
	* the left mouse button event from being propagated. The fix is to
	* send the mouse event from the event_after handler.
	*
	* Feature in GTK. When the user clicks anywhere in an editable
	* combo box, a single focus event should be issued, despite the
	* fact that focus might switch between the drop down button and
	* the text field. The fix is to use gtk_combo_box_set_focus_on_click ()
	* to eat all focus events while focus is in the combo box. When the
	* user clicks on the drop down button focus is assigned to the text
	* field.
	*/
	int eventType = GDK.gdk_event_get_event_type(gdkEvent);
	eventType = fixGdkEventTypeValues(eventType);
	switch (eventType) {
		case GDK.GDK_BUTTON_PRESS: {
			int [] eventButton = new int [1];
			int [] eventState = new int [1];
			if (GTK.GTK4) {
				eventButton[0] = GDK.gdk_button_event_get_button(gdkEvent);
				eventState[0] = GDK.gdk_event_get_modifier_state(gdkEvent);
			} else {
				GDK.gdk_event_get_button(gdkEvent, eventButton);
				GDK.gdk_event_get_state(gdkEvent, eventState);
			}

			int eventTime = GDK.gdk_event_get_time(gdkEvent);

			double [] eventRX = new double [1];
			double [] eventRY = new double [1];
			GDK.gdk_event_get_root_coords(gdkEvent, eventRX, eventRY);

			if (eventButton[0] == 1) {
				if (!sendMouseEvent (SWT.MouseDown, eventButton[0], display.clickCount, 0, false, eventTime, eventRX[0], eventRY[0], false, eventState[0])) {
					return 1;
				}
				if ((style & SWT.READ_ONLY) == 0 && widget == buttonHandle) {
					GTK.gtk_widget_grab_focus (entryHandle);
				}
			}
			break;
		}
		case GDK.GDK_FOCUS_CHANGE: {
			if ((style & SWT.READ_ONLY) == 0) {
				boolean [] focusIn = new boolean [1];
				if (GTK.GTK4) {
					focusIn[0] = GDK.gdk_focus_event_get_in(gdkEvent);
				} else {
					GdkEventFocus gdkEventFocus = new GdkEventFocus ();
					OS.memmove (gdkEventFocus, gdkEvent, GdkEventFocus.sizeof);
					focusIn[0] = gdkEventFocus.in != 0;
				}
				if (focusIn[0]) {
					GTK.gtk_widget_set_focus_on_click(handle, false);
				} else {
					GTK.gtk_widget_set_focus_on_click(handle, true);
				}
			}
			break;
		}
	}
	return super.gtk_event_after(widget, gdkEvent);
}

@Override
long gtk_focus_out_event (long widget, long event) {
	fixIM ();
	return super.gtk_focus_out_event (widget, event);
}

@Override
long gtk_insert_text (long widget, long new_text, long new_text_length, long position) {
	if (!hooks (SWT.Verify) && !filters (SWT.Verify)) return 0;
	if (new_text == 0 || new_text_length == 0) return 0;
	byte [] buffer = new byte [(int)new_text_length];
	C.memmove (buffer, new_text, buffer.length);
	String oldText = new String (Converter.mbcsToWcs (buffer));
	int [] pos = new int [1];
	C.memmove (pos, position, 4);
	long ptr = GTK.gtk_entry_get_text (entryHandle);
	if (pos [0] == -1) pos [0] = (int)OS.g_utf8_strlen (ptr, -1);
	int start = (int)OS.g_utf8_offset_to_utf16_offset (ptr, pos [0]);
	String newText = verifyText (oldText, start, start);
	if (newText != oldText) {
		int [] newStart = new int [1], newEnd = new int [1];
		GTK.gtk_editable_get_selection_bounds (entryHandle, newStart, newEnd);
		if (newText != null) {
			if (newStart [0] != newEnd [0]) {
				OS.g_signal_handlers_block_matched (entryHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, DELETE_TEXT);
				OS.g_signal_handlers_block_matched (entryHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, CHANGED);
				GTK.gtk_editable_delete_selection (entryHandle);
				OS.g_signal_handlers_unblock_matched (entryHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, DELETE_TEXT);
				OS.g_signal_handlers_unblock_matched (entryHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, CHANGED);
			}
			byte [] buffer3 = Converter.wcsToMbcs (newText, false);
			OS.g_signal_handlers_block_matched (entryHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, INSERT_TEXT);
			GTK.gtk_editable_insert_text (entryHandle, buffer3, buffer3.length, pos);
			OS.g_signal_handlers_unblock_matched (entryHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, INSERT_TEXT);
			newStart [0] = newEnd [0] = pos [0];
		}
		pos [0] = newEnd [0];
		if (newStart [0] != newEnd [0]) {
			fixStart = newStart [0];
			fixEnd = newEnd [0];
		}
		C.memmove (position, pos, 4);
		OS.g_signal_stop_emission_by_name (entryHandle, OS.insert_text);
	}
	return 0;
}

@Override
long gtk_key_press_event (long widget, long event) {
	long result = super.gtk_key_press_event (widget, event);
	if (result != 0) {
		gdkEventKey = 0;
		fixIM ();
		return result;
	}
	if (gdkEventKey == -1) result = 1;
	gdkEventKey = 0;
	if ((style & SWT.READ_ONLY) == 0) {
		int oldIndex = GTK.gtk_combo_box_get_active (handle);
		int newIndex = oldIndex;
		int [] eventKeyval = new int [1];
		if (GTK.GTK4) {
			eventKeyval[0] = GDK.gdk_key_event_get_keyval(event);
		} else {
			GDK.gdk_event_get_keyval(event, eventKeyval);
		}

		switch (eventKeyval[0]) {
			case GDK.GDK_Down:
			case GDK.GDK_KP_Down:
				if (oldIndex != (items.length - 1)) {
					newIndex = oldIndex + 1;
				}
				break;
			case GDK.GDK_Up:
			case GDK.GDK_KP_Up:
				if (oldIndex != -1 && oldIndex != 0) {
					newIndex = oldIndex - 1;
				}
				break;
			/*
			* Feature in GTK. In gtk_combo_box, the PageUp and PageDown keys
			* go the first and last items in the list rather than scrolling
			* a page at a time. The fix is to emulate this behavior for
			* gtk_combo_box_entry.
			*/
			case GDK.GDK_Page_Up:
			case GDK.GDK_KP_Page_Up:
				newIndex = 0;
				break;
			case GDK.GDK_Page_Down:
			case GDK.GDK_KP_Page_Down:
				newIndex = items.length - 1;
				break;
		}
		if (newIndex != oldIndex) {
			GTK.gtk_combo_box_set_active (handle, newIndex);
			return 1;
		}
	}
	return result;
}

@Override
long gtk_populate_popup (long widget, long menu) {
	if ((style & SWT.RIGHT_TO_LEFT) != 0) {
		GTK.gtk_widget_set_direction (menu, GTK.GTK_TEXT_DIR_RTL);
		GTK3.gtk_container_forall (menu, display.setDirectionProc, GTK.GTK_TEXT_DIR_RTL);
	}
	return 0;
}

@Override
long gtk_selection_done(long menushell) {
	int index = GTK.gtk_combo_box_get_active (handle);
	unselected = false;
	if (indexSelected == -1){
		indexSelected = index;
	}
	else if (index != -1 && indexSelected == index) {
		sendSelectionEvent (SWT.Selection);
	}
	return 0;
}

@Override
long gtk_style_updated (long widget) {
	setButtonHandle (findButtonHandle ());
	setMenuHandle (findMenuHandle ());
	return super.gtk_style_updated (widget);
}

/**
 * Searches the receiver's list starting at the first item
 * (index 0) until an item is found that is equal to the
 * argument, and returns the index of that item. If no item
 * is found, returns -1.
 *
 * @param string the search item
 * @return the index of the item
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the string 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>
 */
public int indexOf (String string) {
	checkWidget();
	return indexOf(string, 0);
}

/**
 * Searches the receiver's list starting at the given,
 * zero-relative index until an item is found that is equal
 * to the argument, and returns the index of that item. If
 * no item is found or the starting index is out of range,
 * returns -1.
 *
 * @param string the search item
 * @param start the zero-relative index at which to begin the search
 * @return the index of the item
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the string 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>
 */
public int indexOf (String string, int start) {
	checkWidget();
	if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
	if (!(0 <= start && start < items.length)) return -1;
	for (int i=start; i<items.length; i++) {
		if (string.equals(items [i])) return i;
	}
	return -1;
}

@Override
boolean isFocusHandle(long widget) {
	if (buttonHandle != 0 && widget == buttonHandle) return true;
	if (entryHandle != 0 && widget == entryHandle) return true;
	return super.isFocusHandle (widget);
}

@Override
long paintSurface () {
	long childHandle =  entryHandle != 0 ? entryHandle : handle;
	GTK.gtk_widget_realize (childHandle);
	long surface = gtk_widget_get_surface (childHandle);
	if ((style & SWT.READ_ONLY) != 0) return surface;
	/*
	 * TODO: GTK4 no access to children of the surface
	 * for combobox may need to use gtk_combo_box_get_child ().
	 * See also Bug 570331, maybe entire function just needs to be removed
	 */

	return surface;
}

/**
 * Pastes text from clipboard.
 * <p>
 * The selected text is deleted from the widget
 * and new text inserted from the clipboard.
 * </p>
 *
 * @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 2.1
 */
public void paste () {
	checkWidget ();
	if (entryHandle != 0) GTK.gtk_editable_paste_clipboard (entryHandle);
}

@Override
long parentingHandle() {
	return fixedHandle;
}

@Override
void register () {
	super.register ();
	if (buttonHandle != 0) display.addWidget (buttonHandle, this);
	if (entryHandle != 0) display.addWidget (entryHandle, this);
	if (popupHandle != 0) display.addWidget (popupHandle, this);
	if (menuHandle != 0) display.addWidget (menuHandle, this);
	long imContext = imContext ();
	if (imContext != 0) display.addWidget (imContext, this);
}

@Override
void releaseHandle () {
	super.releaseHandle ();
	if (menuHandle != 0) {
		OS.g_object_unref (menuHandle);
	}
	if (buttonHandle != 0) {
		OS.g_object_unref (buttonHandle);
	}
	if (buttonBoxHandle != 0) {
		OS.g_object_unref (buttonBoxHandle);
	}
	if (cellBoxHandle != 0) {
		OS.g_object_unref (cellBoxHandle);
	}
	cellBoxHandle = buttonBoxHandle = menuHandle = buttonHandle = entryHandle = 0;
}

@Override
void releaseWidget () {
	super.releaseWidget ();
	textRenderer = 0;
	fixIM ();
}

/**
 * Removes the item from the receiver's list at the given
 * zero-relative index.
 *
 * @param index the index for the item
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</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>
 */
public void remove (int index) {
	checkWidget();
	if (!(0 <= index && index < items.length)) {
		error (SWT.ERROR_INVALID_RANGE);
	}
	String [] oldItems = items;
	String [] newItems = new String [oldItems.length - 1];
	System.arraycopy (oldItems, 0, newItems, 0, index);
	System.arraycopy (oldItems, index + 1, newItems, index, oldItems.length - index - 1);
	items = newItems;
	if (GTK.gtk_combo_box_get_active (handle) == index) clearText ();
	if (handle != 0) GTK.gtk_combo_box_text_remove(handle, index);
}

/**
 * Removes the items from the receiver's list which are
 * between the given zero-relative start and end
 * indices (inclusive).
 *
 * @param start the start of the range
 * @param end the end of the range
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_INVALID_RANGE - if either the start or end are not between 0 and the number of elements in the list minus 1 (inclusive)</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>
 */
public void remove (int start, int end) {
	checkWidget();
	if (start > end) return;
	if (!(0 <= start && start <= end && end < items.length)) {
		error (SWT.ERROR_INVALID_RANGE);
	}
	String [] oldItems = items;
	String [] newItems = new String [oldItems.length - (end - start + 1)];
	System.arraycopy (oldItems, 0, newItems, 0, start);
	System.arraycopy (oldItems, end + 1, newItems, start, oldItems.length - end - 1);
	items = newItems;
	int index = GTK.gtk_combo_box_get_active (handle);
	if (start <= index && index <= end) clearText();

	gtk_combo_box_toggle_wrap(false);
	for (int i = end; i >= start; i--) {
		if (handle != 0) GTK.gtk_combo_box_text_remove(handle, i);
	}
	gtk_combo_box_toggle_wrap(true);
}

/**
 * Searches the receiver's list starting at the first item
 * until an item is found that is equal to the argument,
 * and removes that item from the list.
 *
 * @param string the item to remove
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the string is null</li>
 *    <li>ERROR_INVALID_ARGUMENT - if the string is not found in the list</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>
 */
public void remove (String string) {
	checkWidget();
	if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
	int index = indexOf (string, 0);
	if (index == -1) error (SWT.ERROR_INVALID_ARGUMENT);
	remove (index);
}

/**
 * Removes all of the items from the receiver's list and clear the
 * contents of receiver's text field.
 * @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 removeAll () {
	checkWidget();

	items = new String[0];
	clearText();
	gtk_combo_box_text_remove_all();
}

/**
 * Removes the listener from the collection of listeners who will
 * be notified when the receiver's text is modified.
 *
 * @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 ModifyListener
 * @see #addModifyListener
 */
public void removeModifyListener (ModifyListener listener) {
	checkWidget();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	if (eventTable == null) return;
	eventTable.unhook (SWT.Modify, listener);
}

/**
 * Removes the listener from the collection of listeners who will
 * be notified when the receiver's text is modified.
 *
 * @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 SegmentEvent
 * @see SegmentListener
 * @see #addSegmentListener
 *
 * @since 3.103
 */
public void removeSegmentListener (SegmentListener listener) {
	checkWidget ();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	eventTable.unhook (SWT.Segments, listener);
}

/**
 * Removes the listener from the collection of listeners who will
 * be notified when the user changes the receiver's selection.
 *
 * @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);
}

/**
 * Removes the listener from the collection of listeners who will
 * be notified when the control is verified.
 *
 * @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 VerifyListener
 * @see #addVerifyListener
 *
 * @since 3.1
 */
public void removeVerifyListener (VerifyListener listener) {
	checkWidget ();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	if (eventTable == null) return;
	eventTable.unhook (SWT.Verify, listener);
}

/**
 * Selects the item at the given zero-relative index in the receiver's
 * list.  If the item at the index was already selected, it remains
 * selected. Indices that are out of range are ignored.
 *
 * @param index the index of the item to select
 *
 * @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 select (int index) {
	checkWidget();
	if (index < 0 || index >= items.length) return;
	int selected = GTK.gtk_combo_box_get_active (handle);
	OS.g_signal_handlers_block_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, CHANGED);
	GTK.gtk_combo_box_set_active (handle, index);
	OS.g_signal_handlers_unblock_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, CHANGED);
	if ((style & SWT.READ_ONLY) != 0 && selected != index) {
		/*
		* Feature in GTK. Read Only combo boxes do not get a chance to send out a
		* Modify event in the gtk_changed callback. The fix is to send a Modify event
		* here.
		*/
		sendEvent (SWT.Modify);
	}
	unselected = false;
}

void setButtonBackgroundGdkRGBA (GdkRGBA rgba) {
	if (rgba == null) {
		buttonBackground = defaultButtonBackground();
	} else {
		buttonBackground = rgba;
	}
	String color = display.gtk_rgba_to_css_string (buttonBackground);
	String css = "* {background: " + color + ";}\n";
	cssButtonBackground = css;
	String finalCss = display.gtk_css_create_css_color_string (cssButtonBackground, cssButtonForeground, SWT.BACKGROUND);
	long buttonContext = GTK.gtk_widget_get_style_context(buttonHandle);
	if (buttonProvider == 0) {
		buttonProvider = GTK.gtk_css_provider_new();
		GTK.gtk_style_context_add_provider(buttonContext, buttonProvider, GTK.GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
		OS.g_object_unref(buttonProvider);
	}
	if (GTK.GTK4) {
		GTK.gtk_css_provider_load_from_data (buttonProvider, Converter.wcsToMbcs (finalCss, true), -1);
	} else {
		GTK.gtk_css_provider_load_from_data (buttonProvider, Converter.wcsToMbcs (finalCss, true), -1, null);
	}
}

void setButtonForegroundGdkRGBA (GdkRGBA rgba) {
	GdkRGBA toSet;
	if (rgba != null) {
		toSet = rgba;
	} else {
		toSet = display.COLOR_WIDGET_FOREGROUND_RGBA;
	}
	String color = display.gtk_rgba_to_css_string(toSet);
	String css = "* {color: " + color + ";}\n";
	cssButtonForeground = css;
	String finalCss = display.gtk_css_create_css_color_string(cssButtonBackground, cssButtonForeground, SWT.FOREGROUND);
	long buttonContext = GTK.gtk_widget_get_style_context(buttonHandle);
	if (buttonProvider == 0) {
		buttonProvider = GTK.gtk_css_provider_new();
		GTK.gtk_style_context_add_provider(buttonContext, buttonProvider, GTK.GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
		OS.g_object_unref(buttonProvider);
	}
	if (GTK.GTK4) {
		GTK.gtk_css_provider_load_from_data (provider, Converter.wcsToMbcs (finalCss, true), -1);
	} else {
		GTK.gtk_css_provider_load_from_data (provider, Converter.wcsToMbcs (finalCss, true), -1, null);
	}
}

@Override
void setBackgroundGdkRGBA (long context, long handle, GdkRGBA rgba) {
	if (rgba == null) {
		background = defaultBackground();
	} else {
		background = rgba;
	}

	String color, menuColor;
	if (rgba != null) {
		color = display.gtk_rgba_to_css_string (rgba);
		menuColor = color;
	} else {
		if ((style & SWT.READ_ONLY) != 0) {
			color = display.gtk_rgba_to_css_string (display.COLOR_WIDGET_BACKGROUND_RGBA);
		} else {
			color = display.gtk_rgba_to_css_string (display.COLOR_LIST_BACKGROUND_RGBA);
		}

		menuColor = display.gtk_rgba_to_css_string (display.COLOR_LIST_BACKGROUND_RGBA);
	}

	// CSS to be parsed for various widgets within Combo
	String css = "* {background: " + color + ";}\n";
	// Set the selected background color
	GdkRGBA selectedBackground = display.getSystemColor(SWT.COLOR_LIST_SELECTION).handle;
	GdkRGBA selectedForeground = display.getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT).handle;
	css += "entry selection {background-color: " + display.gtk_rgba_to_css_string(selectedBackground) + ";}\n";
	css += "entry selection {color: " + display.gtk_rgba_to_css_string(selectedForeground) + ";}";

	// Cache background color
	cssBackground = css;
	String finalCss = display.gtk_css_create_css_color_string (cssBackground, cssForeground, SWT.BACKGROUND);
	if (entryHandle == 0 || (style & SWT.READ_ONLY) != 0) {
		// For read only Combos, we can just apply the background CSS to the GtkToggleButton.
		gtk_css_provider_load_from_css (GTK.gtk_widget_get_style_context(buttonHandle), finalCss);
	} else {
		// GtkEntry and GtkToggleButton needs to be themed separately with different
		// providers for coherent background. Similar to Tree/Table headers.
		gtk_css_provider_load_from_css (GTK.gtk_widget_get_style_context(entryHandle), finalCss);
		setButtonBackgroundGdkRGBA (rgba);
	}

	String menuCss = "menu { background: " + menuColor + ";}";
	GTK.gtk_css_provider_load_from_data (getComboProvider(), Converter.wcsToMbcs (menuCss, true), -1, null);
}

long getComboProvider() {
	if (comboProvider == 0) {
		comboProvider = GTK.gtk_css_provider_new();
		GTK.gtk_style_context_add_provider(GTK.gtk_widget_get_style_context(menuHandle), comboProvider, GTK.GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
		OS.g_object_unref(comboProvider);
	}

	return comboProvider;
}

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

@Override
int setBounds (int x, int y, int width, int height, boolean move, boolean resize) {
	int newHeight = height;
	if (resize) newHeight = Math.max (getTextHeightInPixels (), height);
	return super.setBounds (x, y, width, newHeight, move, resize);
}

void setButtonHandle (long widget) {
	if (buttonHandle == widget) return;
	if (buttonHandle != 0) {
		display.removeWidget (buttonHandle);
		OS.g_object_unref (buttonHandle);
	}
	buttonHandle = widget;
	if (buttonHandle != 0) {
		OS.g_object_ref (buttonHandle);
		display.addWidget (buttonHandle, this);
		hookEvents (new long []{buttonHandle});
	}
}

void setMenuHandle (long widget) {
	if (menuHandle == widget) return;
	if (menuHandle != 0) {
		display.removeWidget (menuHandle);
		OS.g_object_unref (menuHandle);
	}
	menuHandle = widget;
	if (menuHandle != 0) {
		OS.g_object_ref (menuHandle);
		display.addWidget (menuHandle, this);
		hookEvents (new long []{menuHandle});
	}
}

@Override
void setFontDescription (long font) {
	super.setFontDescription (font);
	if (entryHandle != 0) setFontDescription (entryHandle, font);
	OS.g_object_set (textRenderer, OS.font_desc, font, 0);
	if ((style & SWT.READ_ONLY) != 0) {
		/*
		* Bug in GTK.  Setting the font can leave the combo box with an
		* invalid minimum size.  The fix is to temporarily change the
		* selected item to force the combo box to resize.
		*/
		int index = GTK.gtk_combo_box_get_active (handle);
		OS.g_signal_handlers_block_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, CHANGED);
		GTK.gtk_combo_box_set_active (handle, -1);
		GTK.gtk_combo_box_set_active (handle, index);
		OS.g_signal_handlers_unblock_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, CHANGED);
	}
}

@Override
void setForegroundGdkRGBA (GdkRGBA rgba) {
	if (entryHandle != 0) {
		setForegroundGdkRGBA (entryHandle, rgba);
	}
	if ((style & SWT.READ_ONLY) == 0 && buttonHandle != 0) {
		setButtonForegroundGdkRGBA (rgba);
	}
	OS.g_object_set (textRenderer, OS.foreground_rgba, rgba, 0);
	super.setForegroundGdkRGBA(rgba);
}

@Override
void setInitialBounds () {
	if ((state & ZERO_WIDTH) != 0 && (state & ZERO_HEIGHT) != 0) {
		/*
		* Feature in GTK.  On creation, each widget's allocation is
		* initialized to a position of (-1, -1) until the widget is
		* first sized.  The fix is to set the value to (0, 0) as
		* expected by SWT.
		*/
		long topHandle = topHandle ();
		GtkAllocation allocation = new GtkAllocation();
		if ((parent.style & SWT.MIRRORED) != 0) {
			allocation.x = parent.getClientWidth ();
		} else {
			allocation.x = 0;
		}
		allocation.y = 0;
		GTK.gtk_widget_set_visible(topHandle, true);
		if (GTK.GTK4) {
			GTK.gtk_widget_size_allocate (topHandle, allocation, -1);
		} else {
			// Prevent GTK+ allocation warnings, preferred size should be retrieved before setting allocation size.
			GTK.gtk_widget_get_preferred_size(topHandle, null, null);
			GTK.gtk_widget_set_allocation(topHandle, allocation);
		}
	} else {
		super.setInitialBounds();
	}
}

/**
 * Sets the text of the item in the receiver's list at the given
 * zero-relative index to the string argument.
 *
 * @param index the index for the item
 * @param string the new text for the item
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
 *    <li>ERROR_NULL_ARGUMENT - if the string 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>
 */
public void setItem (int index, String string) {
	checkWidget();
	if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
	if (!(0 <= index && index < items.length)) {
		error (SWT.ERROR_INVALID_ARGUMENT);
	}
	items [index] = string;
	if (handle != 0) {
		GTK.gtk_combo_box_text_remove (handle, index);
	}
	gtk_combo_box_insert(string, index);

	if ((style & SWT.RIGHT_TO_LEFT) != 0 && popupHandle != 0) {
		GTK3.gtk_container_forall (popupHandle, display.setDirectionProc, GTK.GTK_TEXT_DIR_RTL);
	}
}

/**
 * Sets the receiver's list to be the given array of items.
 *
 * @param items the array of items
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the items array is null</li>
 *    <li>ERROR_INVALID_ARGUMENT - if an item in the items array 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>
 */
public void setItems (String... items) {
	checkWidget();
	if (items == null) error (SWT.ERROR_NULL_ARGUMENT);
	for (int i=0; i<items.length; i++) {
		if (items [i] == null) error (SWT.ERROR_INVALID_ARGUMENT);
	}
	this.items = new String [items.length];
	System.arraycopy (items, 0, this.items, 0, items.length);
	clearText ();

	gtk_combo_box_text_remove_all();
	for (int i = 0; i < items.length; i++) {
		String string = items [i];
		gtk_combo_box_insert(string, i);
		if ((style & SWT.RIGHT_TO_LEFT) != 0 && popupHandle != 0) {
			GTK3.gtk_container_forall (popupHandle, display.setDirectionProc, GTK.GTK_TEXT_DIR_RTL);
		}
	}
}

private void gtk_combo_box_text_remove_all() {
	gtk_combo_box_toggle_wrap(false);
	if (handle != 0) GTK.gtk_combo_box_text_remove_all(handle);
	gtk_combo_box_toggle_wrap(true);
}

/**
 * Marks the receiver's list as visible if the argument is <code>true</code>,
 * and marks it invisible otherwise.
 * <p>
 * If one of the receiver's ancestors is not visible or some
 * other condition makes the receiver not visible, marking
 * it visible may not actually cause it to be displayed.
 * </p>
 *
 * @param visible the new visibility state
 *
 * @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 setListVisible (boolean visible) {
	checkWidget ();
	if (visible) {
		GTK.gtk_combo_box_popup (handle);
	} else {
		GTK.gtk_combo_box_popdown (handle);
	}
}

@Override
void setOrientation (boolean create) {
	super.setOrientation (create);
	if ((style & SWT.RIGHT_TO_LEFT) != 0 || !create) {
		int dir = (style & SWT.RIGHT_TO_LEFT) != 0 ? GTK.GTK_TEXT_DIR_RTL : GTK.GTK_TEXT_DIR_LTR;
		if (entryHandle != 0) GTK.gtk_widget_set_direction (entryHandle, dir);
		if (cellHandle != 0) GTK.gtk_widget_set_direction (cellHandle, dir);
		if (!create) {
			if (popupHandle != 0) GTK3.gtk_container_forall (popupHandle, display.setDirectionProc, dir);
		}
	}
}

/**
 * Sets the orientation of the receiver, which must be one
 * of the constants <code>SWT.LEFT_TO_RIGHT</code> or <code>SWT.RIGHT_TO_LEFT</code>.
 * <p>
 *
 * @param orientation new orientation style
 *
 * @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 2.1.2
 */
@Override
public void setOrientation (int orientation) {
	super.setOrientation (orientation);
}

/**
 * Sets the selection in the receiver's text field to the
 * range specified by the argument whose x coordinate is the
 * start of the selection and whose y coordinate is the end
 * of the selection.
 *
 * @param selection a point representing the new selection start and end
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the point 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>
 */
public void setSelection (Point selection) {
	checkWidget();
	if (selection == null) error (SWT.ERROR_NULL_ARGUMENT);
	if ((style & SWT.READ_ONLY) != 0) return;

	if (entryHandle != 0) {
		long textPtr = 0;
		if (GTK.GTK4) {
			long bufferHandle = GTK.gtk_entry_get_buffer(entryHandle);
			textPtr = GTK.gtk_entry_buffer_get_text(bufferHandle);
		} else {
			textPtr = GTK.gtk_entry_get_text(entryHandle);
		}

		int start = (int)OS.g_utf16_offset_to_utf8_offset(textPtr, selection.x);
		int end = (int)OS.g_utf16_offset_to_utf8_offset(textPtr, selection.y);
		GTK.gtk_editable_set_position(entryHandle, start);
		GTK.gtk_editable_select_region(entryHandle, start, end);
	}
}

/**
 * Sets the contents of the receiver's text field to the
 * given string.
 * <p>
 * This call is ignored when the receiver is read only and
 * the given string is not in the receiver's list.
 * </p>
 * <p>
 * Note: The text field in a <code>Combo</code> is typically
 * only capable of displaying a single line of text. Thus,
 * setting the text to a string containing line breaks or
 * other special characters will probably cause it to
 * display incorrectly.
 * </p><p>
 * Also note, if control characters like '\n', '\t' etc. are used
 * in the string, then the behavior is platform dependent.
 * </p>
 *
 * @param string the new text
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the string 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>
 */
public void setText (String string) {
	checkWidget();
	if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
	if ((style & SWT.READ_ONLY) != 0) {
		int index = indexOf (string);
		if (index == -1) return;
		select (index);
		return;
	}
	/*
	* Feature in gtk.  When text is set in gtk, separate events are fired for the deletion and
	* insertion of the text.  This is not wrong, but is inconsistent with other platforms.  The
	* fix is to block the firing of these events and fire them ourselves in a consistent manner.
	*/
	if (hooks (SWT.Verify) || filters (SWT.Verify)) {
		long ptr = GTK.gtk_entry_get_text (entryHandle);
		string = verifyText (string, 0, (int)OS.g_utf16_strlen (ptr, -1));
		if (string == null) return;
	}
	byte [] buffer = Converter.wcsToMbcs (string, true);
	OS.g_signal_handlers_block_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, CHANGED);
	OS.g_signal_handlers_block_matched (entryHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, CHANGED);
	OS.g_signal_handlers_block_matched (entryHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, DELETE_TEXT);
	OS.g_signal_handlers_block_matched (entryHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, INSERT_TEXT);
	if (GTK.GTK4) {
		long bufferHandle = GTK.gtk_entry_get_buffer(entryHandle);
		GTK.gtk_entry_buffer_set_text(bufferHandle, buffer, string.length());
	} else {
		GTK.gtk_entry_set_text (entryHandle, buffer);
	}
	OS.g_signal_handlers_unblock_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, CHANGED);
	OS.g_signal_handlers_unblock_matched (entryHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, CHANGED);
	OS.g_signal_handlers_unblock_matched (entryHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, DELETE_TEXT);
	OS.g_signal_handlers_unblock_matched (entryHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, INSERT_TEXT);
	sendEvent (SWT.Modify);
}

/**
 * Sets the maximum number of characters that the receiver's
 * text field is capable of holding to be the argument.
 * <p>
 * To reset this value to the default, use <code>setTextLimit(Combo.LIMIT)</code>.
 * Specifying a limit value larger than <code>Combo.LIMIT</code> sets the
 * receiver's limit to <code>Combo.LIMIT</code>.
 * </p>
 * @param limit new text limit
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_CANNOT_BE_ZERO - if the limit is zero</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 #LIMIT
 */
public void setTextLimit (int limit) {
	checkWidget();
	if (limit == 0) error (SWT.ERROR_CANNOT_BE_ZERO);
	if (entryHandle != 0) GTK.gtk_entry_set_max_length (entryHandle, limit);
}

@Override
void setToolTipText (Shell shell, String newString) {
	if (entryHandle != 0) shell.setToolTipText (entryHandle, newString);
	if (buttonHandle != 0) shell.setToolTipText (buttonHandle, newString);
}

/**
 * Sets the number of items that are visible in the drop
 * down portion of the receiver's list.
 * <p>
 * Note: This operation is a hint and is not supported on
 * platforms that do not have this concept.
 * </p>
 *
 * @param count the new number of items to be visible
 *
 * @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.0
 */
public void setVisibleItemCount (int count) {
	checkWidget ();
	if (count < 0) return;
	visibleCount = count;
}

@Override
boolean checkSubwindow () {
	return false;
}

@Override
boolean translateTraversal (long event) {
	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_KP_Enter:
		case GDK.GDK_Return: {
			long imContext = imContext ();
			if (imContext != 0) {
				long [] preeditString = new long [1];
				GTK.gtk_im_context_get_preedit_string (imContext, preeditString, null, null);
				if (preeditString [0] != 0) {
					int length = C.strlen (preeditString [0]);
					OS.g_free (preeditString [0]);
					if (length != 0) return false;
				}
			}
		}
	}
	return super.translateTraversal (event);
}

String verifyText (String string, int start, int end) {
	if (string.length () == 0 && start == end) return null;
	Event event = new Event ();
	event.text = string;
	event.start = start;
	event.end = end;
	long eventPtr = GTK.GTK4 ? 0 : GTK3.gtk_get_current_event ();
	if (eventPtr != 0) {
		int type = GDK.gdk_event_get_event_type(eventPtr);
		type = fixGdkEventTypeValues(type);
		switch (type) {
			case GDK.GDK_KEY_PRESS:
				setKeyState (event, eventPtr);
				break;
		}
		gdk_event_free (eventPtr);
	}
	/*
	 * It is possible (but unlikely), that application
	 * code could have disposed the widget in the verify
	 * event.  If this happens, answer null to cancel
	 * the operation.
	 */
	sendEvent (SWT.Verify, event);
	if (!event.doit || isDisposed ()) return null;
	return event.text;
}

}
