/*******************************************************************************
 * Copyright (c) 2000, 2018 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Sean Montgomery, sean_montgomery@comcast.net - https://bugs.eclipse.org/bugs/show_bug.cgi?id=116454
 *     Marcel Bruch, bruch@cs.tu-darmstadt.de - [content assist] Allow to re-sort proposals - https://bugs.eclipse.org/bugs/show_bug.cgi?id=350991
 *     Terry Parker, tparker@google.com - Protect against poorly behaved completion proposers - http://bugs.eclipse.org/429925
 *     Lars Vogel <Lars.Vogel@vogella.com> - Bug 493649
 *     Mickael Istria (Red Hat Inc.) - [251156] Allow multiple contentAssitProviders internally & inheritance
 *******************************************************************************/
package org.eclipse.jface.text.contentassist;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

import org.eclipse.osgi.util.TextProcessor;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.events.TraverseListener;
import org.eclipse.swt.events.VerifyEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Monitor;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.ILog;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;

import org.eclipse.jface.bindings.keys.KeySequence;
import org.eclipse.jface.bindings.keys.SWTKeySupport;
import org.eclipse.jface.contentassist.IContentAssistSubjectControl;
import org.eclipse.jface.internal.text.InformationControlReplacer;
import org.eclipse.jface.internal.text.TableOwnerDrawSupport;
import org.eclipse.jface.preference.JFacePreferences;
import org.eclipse.jface.resource.JFaceColors;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.util.Geometry;
import org.eclipse.jface.util.Util;
import org.eclipse.jface.viewers.StyledString;

import org.eclipse.jface.text.AbstractInformationControlManager;
import org.eclipse.jface.text.AbstractInformationControlManager.Anchor;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentListener;
import org.eclipse.jface.text.IEditingSupport;
import org.eclipse.jface.text.IEditingSupportRegistry;
import org.eclipse.jface.text.IInformationControl;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.IRewriteTarget;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.ITextViewerExtension;
import org.eclipse.jface.text.TextUtilities;


/**
 * This class is used to present proposals to the user. If additional
 * information exists for a proposal, then selecting that proposal
 * will result in the information being displayed in a secondary
 * window.
 *
 * @see org.eclipse.jface.text.contentassist.ICompletionProposal
 * @see org.eclipse.jface.text.contentassist.AdditionalInfoController
 */
class CompletionProposalPopup implements IContentAssistListener {

	/**
	 * Completion proposal selection handler.
	 *
	 * @since 3.4
	 */
	final class ProposalSelectionHandler extends AbstractHandler {

		/**
		 * Selection operation codes.
		 */
		static final int SELECT_NEXT= 1;
		static final int SELECT_PREVIOUS= 2;


		private final int fOperationCode;

		/**
		 * Creates a new selection handler.
		 *
		 * @param operationCode the operation code
		 * @since 3.4
		 */
		public ProposalSelectionHandler(int operationCode) {
			Assert.isLegal(operationCode == SELECT_NEXT || operationCode == SELECT_PREVIOUS);
			fOperationCode= operationCode;
		}

		@Override
		public Object execute(ExecutionEvent event) throws ExecutionException {
			if (fProposalTable.isDisposed()) {
				return null;
			}
			int itemCount= fProposalTable.getItemCount();
			int selectionIndex= fProposalTable.getSelectionIndex();
			switch (fOperationCode) {
			case SELECT_NEXT:
				selectionIndex+= 1;
				if (selectionIndex > itemCount - 1)
					selectionIndex= 0;
				break;
			case SELECT_PREVIOUS:
				selectionIndex-= 1;
				if (selectionIndex < 0)
					selectionIndex= itemCount - 1;
				break;
			default:
				break;
			}
			selectProposal(selectionIndex, false);
			return null;
		}

	}


	/**
	 * The empty proposal displayed if there is nothing else to show.
	 *
	 * @since 3.2
	 */
	private static final class EmptyProposal implements ICompletionProposal, ICompletionProposalExtension {

		String fDisplayString;
		int fOffset;
		@Override
		public void apply(IDocument document) {
		}

		@Override
		public Point getSelection(IDocument document) {
			return new Point(fOffset, 0);
		}

		@Override
		public IContextInformation getContextInformation() {
			return null;
		}

		@Override
		public Image getImage() {
			return null;
		}

		@Override
		public String getDisplayString() {
			return fDisplayString;
		}

		@Override
		public String getAdditionalProposalInfo() {
			return null;
		}

		@Override
		public void apply(IDocument document, char trigger, int offset) {
		}

		@Override
		public boolean isValidFor(IDocument document, int offset) {
			return false;
		}

		@Override
		public char[] getTriggerCharacters() {
			return null;
		}

		@Override
		public int getContextInformationPosition() {
			return -1;
		}
	}

	final class ProposalSelectionListener implements KeyListener {
		@Override
		public void keyPressed(KeyEvent e) {
			if (!Helper.okToUse(fProposalShell))
				return;

			if (e.character == 0 && e.keyCode == SWT.CTRL) {
				// http://dev.eclipse.org/bugs/show_bug.cgi?id=34754
				int index= fProposalTable.getSelectionIndex();
				if (index >= 0)
					selectProposal(index, true);
			}
		}

		@Override
		public void keyReleased(KeyEvent e) {
			if (!Helper.okToUse(fProposalShell))
				return;

			if (e.character == 0 && e.keyCode == SWT.CTRL) {
				// http://dev.eclipse.org/bugs/show_bug.cgi?id=34754
				int index= fProposalTable.getSelectionIndex();
				if (index >= 0)
					selectProposal(index, false);
			}
		}
	}

	private final class CommandKeyListener extends KeyAdapter {
		private final KeySequence fCommandSequence;

		private CommandKeyListener(KeySequence keySequence) {
			fCommandSequence= keySequence;
		}

		@Override
		public void keyPressed(KeyEvent e) {
			if (!Helper.okToUse(fProposalShell))
				return;

			int accelerator= SWTKeySupport.convertEventToUnmodifiedAccelerator(e);
			KeySequence sequence= KeySequence.getInstance(SWTKeySupport.convertAcceleratorToKeyStroke(accelerator));
			if (sequence.equals(fCommandSequence))
				if (fContentAssistant.isPrefixCompletionEnabled())
					incrementalComplete();
				else
					showProposals(false);

		}
	}


	/** The associated text viewer. */
	ITextViewer fViewer;
	/** The associated content assistant. */
	final ContentAssistant fContentAssistant;
	/** The used additional info controller, or <code>null</code> if none. */
	private final AdditionalInfoController fAdditionalInfoController;
	/** The closing strategy for this completion proposal popup. */
	private final PopupCloser fPopupCloser= new PopupCloser();
	/** The popup shell. */
	Shell fProposalShell;
	/** The proposal table. */
	private Table fProposalTable;
	/** Indicates whether a completion proposal is being inserted. */
	private boolean fInserting= false;
	/** The key listener to control navigation. */
	ProposalSelectionListener fKeyListener;
	/** List of document events used for filtering proposals. */
	private final List<DocumentEvent> fDocumentEvents= new ArrayList<>();
	/** Listener filling the document event queue. */
	private IDocumentListener fDocumentListener;
	/** The filter list of proposals. */
	List<ICompletionProposal> fFilteredProposals;
	/** The computed list of proposals. */
	List<ICompletionProposal> fComputedProposals;
	/** The offset for which the proposals have been computed. */
	int fInvocationOffset;
	/** The offset for which the computed proposals have been filtered. */
	int fFilterOffset;
	/**
	 * The most recently selected proposal.
	 * @since 3.0
	 */
	private ICompletionProposal fLastProposal;
	/**
	 * The content assist subject control.
	 * This replaces <code>fViewer</code>
	 *
	 * @since 3.0
	 */
	IContentAssistSubjectControl fContentAssistSubjectControl;
	/**
	 * The content assist subject control adapter.
	 * This replaces <code>fViewer</code>
	 *
	 * @since 3.0
	 */
	final ContentAssistSubjectControlAdapter fContentAssistSubjectControlAdapter;
	/**
	 * Remembers the size for this completion proposal popup.
	 * @since 3.0
	 */
	private Point fSize;
	/**
	 * Editor helper that communicates that the completion proposal popup may
	 * have focus while the 'logical focus' is still with the editor.
	 * @since 3.1
	 */
	private IEditingSupport fFocusHelper;
	/**
	 * Set to true by {@link #computeFilteredProposals(int, DocumentEvent)} if
	 * the returned proposals are a subset of {@link #fFilteredProposals},
	 * <code>false</code> if not.
	 * @since 3.1
	 */
	private boolean fIsFilteredSubset;
	/**
	 * The filter runnable.
	 *
	 * @since 3.1.1
	 */
	private final Runnable fFilterRunnable= new Runnable() {
		@Override
		public void run() {
			if (!fIsFilterPending.compareAndSet(true, false))
				return;

			if (!Helper.okToUse(fContentAssistSubjectControlAdapter.getControl()))
				return;

			int offset= fContentAssistSubjectControlAdapter.getSelectedRange().x;
			List<ICompletionProposal> proposals= null;
			DocumentEvent event= null;
			try {
				if (offset > -1) {
					event= TextUtilities.mergeProcessedDocumentEvents(fDocumentEvents);
					proposals= computeFilteredProposals(offset, event);
				}
			} catch (BadLocationException x) {
				fDocumentEvents.clear();
			}
			fFilterOffset= offset;

			if (proposals != null && !proposals.isEmpty())
				setProposals(proposals, fIsFilteredSubset);
			else {
				hide();
				if (fContentAssistant.isAutoActivation() && offset > 0 && event != null) {
					try {
						char charBeforeOffset= event.getDocument().getChar(offset - 1);
						if (fContentAssistant.isAutoActivationTriggerChar(charBeforeOffset)) {
							fContentAssistant.fireSessionBeginEvent(true);
							showProposals(true);
						}
					} catch (BadLocationException e) {
					}
				}
			}
		}
	};
	/**
	 * <code>true</code> if <code>fFilterRunnable</code> has been
	 * posted, <code>false</code> if not.
	 *
	 * @since 3.1.1
	 */
	private final AtomicBoolean fIsFilterPending= new AtomicBoolean(false);
	/**
	 * The info message at the bottom of the popup, or <code>null</code> for no popup (if
	 * ContentAssistant does not provide one).
	 *
	 * @since 3.2
	 */
	private Label fMessageText;
	/**
	 * The font used for <code>fMessageText</code> or null; dispose when done.
	 *
	 * @since 3.2
	 */
	private Font fMessageTextFont;
	/**
	 * The most recent completion offset (used to determine repeated invocation)
	 *
	 * @since 3.2
	 */
	int fLastCompletionOffset;
	/**
	 * The (reusable) empty proposal.
	 *
	 * @since 3.2
	 */
	private final EmptyProposal fEmptyProposal= new EmptyProposal();
	/**
	 * The text for the empty proposal, or <code>null</code> to use the default text.
	 *
	 * @since 3.2
	 */
	private String fEmptyMessage= null;
	/**
	 * Tells whether colored labels support is enabled.
	 * Only valid while the popup is active.
	 *
	 * @since 3.4
	 */
	private boolean fIsColoredLabelsSupportEnabled= false;

	/**
	 * The sorter to be used for sorting the proposals or <code>null</code> if no sorting is
	 * requested.
	 *
	 * @since 3.8
	 */
	ICompletionProposalSorter fSorter;

	/**
	 * Set to true by {@link #computeProposals(int)} when initial sorting is performed on the
	 * computed proposals using {@link #fSorter}.
	 *
	 * @since 3.11
	 */
	boolean fIsInitialSort;

	/**
	 * Creates a new completion proposal popup for the given elements.
	 *
	 * @param contentAssistant the content assistant feeding this popup
	 * @param viewer the viewer on top of which this popup appears
	 * @param infoController the information control collaborating with this popup, or <code>null</code>
	 * @since 2.0
	 */
	public CompletionProposalPopup(ContentAssistant contentAssistant, ITextViewer viewer, AdditionalInfoController infoController) {
		fContentAssistant= contentAssistant;
		fViewer= viewer;
		fAdditionalInfoController= infoController;
		fContentAssistSubjectControlAdapter= new ContentAssistSubjectControlAdapter(fViewer);
	}

	/**
	 * Creates a new completion proposal popup for the given elements.
	 *
	 * @param contentAssistant the content assistant feeding this popup
	 * @param contentAssistSubjectControl the content assist subject control on top of which this popup appears
	 * @param infoController the information control collaborating with this popup, or <code>null</code>
	 * @since 3.0
	 */
	public CompletionProposalPopup(ContentAssistant contentAssistant, IContentAssistSubjectControl contentAssistSubjectControl, AdditionalInfoController infoController) {
		fContentAssistant= contentAssistant;
		fContentAssistSubjectControl= contentAssistSubjectControl;
		fAdditionalInfoController= infoController;
		fContentAssistSubjectControlAdapter= new ContentAssistSubjectControlAdapter(fContentAssistSubjectControl);
	}

	/**
	 * Computes and presents completion proposals. The flag indicates whether this call has
	 * be made out of an auto activation context.
	 *
	 * @param autoActivated <code>true</code> if auto activation context
	 * @return an error message or <code>null</code> in case of no error
	 */
	public String showProposals(final boolean autoActivated) {

		if (fKeyListener == null)
			fKeyListener= new ProposalSelectionListener();

		final Control control= fContentAssistSubjectControlAdapter.getControl();

		if (!Helper.okToUse(fProposalShell) && control != null && !control.isDisposed()) {
			// add the listener before computing the proposals so we don't move the caret
			// when the user types fast.
			fContentAssistSubjectControlAdapter.addKeyListener(fKeyListener);

			BusyIndicator.showWhile(control.getDisplay(), () -> {

				fInvocationOffset= fContentAssistSubjectControlAdapter.getSelectedRange().x;
				fFilterOffset= fInvocationOffset;
				fLastCompletionOffset= fFilterOffset;
				fComputedProposals= computeProposals(fInvocationOffset);

				int count= (fComputedProposals == null ? 0 : fComputedProposals.size());
				if (count == 0 && hideWhenNoProposals(autoActivated))
					return;

				if (count == 1 && !autoActivated && canAutoInsert(fComputedProposals.get(0))) {
					insertProposal(fComputedProposals.get(0), (char) 0, 0, fInvocationOffset);
					hide();
				} else {
					createProposalSelector();
					setProposals(fComputedProposals, false);
					displayProposals();
				}
			});
		} else {
			fLastCompletionOffset= fFilterOffset;
			handleRepeatedInvocation();
		}

		return getErrorMessage();
	}

	/**
	 * Hides the popup and returns <code>true</code> if the popup is configured
	 * to never display an empty list. Returns <code>false</code> otherwise.
	 *
	 * @param autoActivated whether the invocation was auto-activated
	 * @return <code>false</code> if an empty list should be displayed, <code>true</code> otherwise
	 * @since 3.2
	 */
	boolean hideWhenNoProposals(boolean autoActivated) {
		if (autoActivated || !fContentAssistant.isShowEmptyList()) {
			if (!autoActivated) {
				Control control= fContentAssistSubjectControlAdapter.getControl();
				if (control != null && !control.isDisposed())
					control.getDisplay().beep();
			}
			hide();
			return true;
		}
		return false;
	}

	/**
	 * If content assist is set up to handle cycling, then the proposals are recomputed. Otherwise,
	 * nothing happens.
	 *
	 * @since 3.2
	 */
	void handleRepeatedInvocation() {
		if (fContentAssistant.isRepeatedInvocationMode()) {
			fComputedProposals= computeProposals(fFilterOffset);
			setProposals(fComputedProposals, false);
		}
	}

	/**
	 * Returns the completion proposals available at the given offset of the viewer's document.
	 * Delegates the work to the content assistant. Sorts the computed proposals if sorting is
	 * requested with {@link #fSorter}.
	 *
	 * @param offset the offset
	 * @return the completion proposals available at this offset, never null
	 */
	List<ICompletionProposal> computeProposals(int offset) {
		ICompletionProposal[] completionProposals;
		if (fContentAssistSubjectControl != null) {
			completionProposals= fContentAssistant.computeCompletionProposals(fContentAssistSubjectControl, offset);
		} else {
			completionProposals= fContentAssistant.computeCompletionProposals(fViewer, offset);
		}
		if (completionProposals == null) {
			return Collections.emptyList();
		}
		List<ICompletionProposal> proposals= Arrays.asList(completionProposals);
		if (fSorter != null) {
			sortProposals(proposals);
			fIsInitialSort= true;
		}
		return proposals;
	}

	/**
	 * Returns the error message.
	 *
	 * @return the error message
	 */
	String getErrorMessage() {
		return fContentAssistant.getErrorMessage();
	}

	/**
	 * Creates the proposal selector.
	 */
	void createProposalSelector() {
		if (Helper.okToUse(fProposalShell))
			return;

		Control control= fContentAssistSubjectControlAdapter.getControl();
		fProposalShell= new Shell(control.getShell(), SWT.ON_TOP | SWT.RESIZE );
		fProposalShell.setFont(JFaceResources.getDefaultFont());
		fProposalTable= new Table(fProposalShell, SWT.H_SCROLL | SWT.V_SCROLL | SWT.VIRTUAL);

		Listener listener= this::handleSetData;
		fProposalTable.addListener(SWT.SetData, listener);

		fIsColoredLabelsSupportEnabled= fContentAssistant.isColoredLabelsSupportEnabled();
		if (fIsColoredLabelsSupportEnabled)
			TableOwnerDrawSupport.install(fProposalTable);

		fProposalTable.setLocation(0, 0);
		if (fAdditionalInfoController != null)
			fAdditionalInfoController.setSizeConstraints(50, 10, true, true);

		GridLayout layout= new GridLayout();
		layout.marginWidth= 0;
		layout.marginHeight= 0;
		layout.verticalSpacing= 1;
		fProposalShell.setLayout(layout);

		if (fContentAssistant.isStatusLineVisible()) {
			createMessageText();
		}

		GridData data= new GridData(GridData.FILL_BOTH);

		Point size= fContentAssistant.restoreCompletionProposalPopupSize();
		if (size != null) {
			fProposalTable.setLayoutData(data);
			fProposalShell.setSize(size);
		} else {
			int height= fProposalTable.getItemHeight() * 10;
			// use 2 x ratio as default aspect ratio instead of (1 + Math.sqrt(5)) / 2
			double aspectRatio= 2;
			int width= (int) (height * aspectRatio);

			// Make sure our bounds still fit to the screen
			Monitor monitor= Util.getClosestMonitor(fProposalShell.getDisplay(), getLocation());
			Rectangle bounds= monitor.getClientArea();
			width= Math.min(width, bounds.width / 4);
			height= Math.min(height, bounds.height / 4);

			Rectangle trim= fProposalTable.computeTrim(0, 0, width, height);
			data.heightHint= trim.height;
			data.widthHint= trim.width;
			fProposalTable.setLayoutData(data);
			fProposalShell.pack();
		}
		fContentAssistant.addToLayout(this, fProposalShell, ContentAssistant.LayoutManager.LAYOUT_PROPOSAL_SELECTOR, fContentAssistant.getSelectionOffset());

		fProposalShell.addControlListener(new ControlListener() {

			@Override
			public void controlMoved(ControlEvent e) {}

			@Override
			public void controlResized(ControlEvent e) {
				if (fAdditionalInfoController != null) {
					// reset the cached resize constraints
					fAdditionalInfoController.setSizeConstraints(50, 10, true, false);
					fAdditionalInfoController.hideInformationControl();
					fAdditionalInfoController.handleTableSelectionChanged();
				}

				fSize= fProposalShell.getSize();
			}
		});

		Color background= getBackgroundColor(control);
		if (background == null) {
			background= JFaceColors.getInformationViewerBackgroundColor(Display.getDefault());
		}

		Color foreground= getForegroundColor(control);
		if (foreground == null) {
			foreground= JFaceColors.getInformationViewerForegroundColor(Display.getDefault());
		}

		fProposalShell.setBackground(background);
		fProposalTable.setBackground(background);
		fProposalTable.setForeground(foreground);

		fProposalTable.addSelectionListener(new SelectionListener() {

			@Override
			public void widgetSelected(SelectionEvent e) {}

			@Override
			public void widgetDefaultSelected(SelectionEvent e) {
				insertSelectedProposalWithMask(e.stateMask);
			}
		});

		fPopupCloser.install(fContentAssistant, fProposalTable, fAdditionalInfoController);

		fProposalShell.addDisposeListener(event -> unregister());

		fProposalTable.setHeaderVisible(false);

		addCommandSupport(fProposalTable);
	}

	/**
	 * Returns the minimal required height for the proposal, may return 0 if the popup has not been
	 * created yet.
	 *
	 * @return the minimal height
	 * @since 3.3
	 */
	int getMinimalHeight() {
		int height= 0;
		if (Helper.okToUse(fProposalTable)) {
			int items= fProposalTable.getItemHeight() * 10;
			Rectangle trim= fProposalTable.computeTrim(0, 0, SWT.DEFAULT, items);
			height= trim.height;
		}
		if (Helper.okToUse(fMessageText))
			height+= fMessageText.getSize().y + 1;
		return height;
	}

	/**
	 * Adds command support to the given control.
	 *
	 * @param control the control to watch for focus
	 * @since 3.2
	 */
	private void addCommandSupport(final Control control) {
		final KeySequence commandSequence= fContentAssistant.getRepeatedInvocationKeySequence();
		if (commandSequence != null && !commandSequence.isEmpty() && fContentAssistant.isRepeatedInvocationMode()) {
			control.addFocusListener(new FocusListener() {
				private CommandKeyListener fCommandKeyListener;
				@Override
				public void focusGained(FocusEvent e) {
					if (Helper.okToUse(control)) {
						if (fCommandKeyListener == null) {
							fCommandKeyListener= new CommandKeyListener(commandSequence);
							fProposalTable.addKeyListener(fCommandKeyListener);
						}
					}
				}
				@Override
				public void focusLost(FocusEvent e) {
					if (fCommandKeyListener != null) {
						control.removeKeyListener(fCommandKeyListener);
						fCommandKeyListener= null;
					}
				}
			});
		}
		if (fAdditionalInfoController != null) {
			control.addFocusListener(new FocusListener() {
				private TraverseListener fTraverseListener;
				@Override
				public void focusGained(FocusEvent e) {
					if (Helper.okToUse(control)) {
						if (fTraverseListener == null) {
							fTraverseListener= event -> {
								if (event.detail == SWT.TRAVERSE_TAB_NEXT) {
									IInformationControl iControl= fAdditionalInfoController.getCurrentInformationControl2();
									if (fAdditionalInfoController.getInternalAccessor().canReplace(iControl)) {
										fAdditionalInfoController.getInternalAccessor().replaceInformationControl(true);
										event.doit= false;
									}
								}
							};
							fProposalTable.addTraverseListener(fTraverseListener);
						}
					}
				}
				@Override
				public void focusLost(FocusEvent e) {
					if (fTraverseListener != null) {
						control.removeTraverseListener(fTraverseListener);
						fTraverseListener= null;
					}
				}
			});
		}
	}

	/**
	 * Returns the background color to use.
	 *
	 * @param control the control to get the display from
	 * @return the background color
	 * @since 3.2
	 */
	private Color getBackgroundColor(Control control) {
		Color c= fContentAssistant.getProposalSelectorBackground();
		if (c == null)
			c= JFaceResources.getColorRegistry().get(JFacePreferences.CONTENT_ASSIST_BACKGROUND_COLOR);
		return c;
	}

	/**
	 * Returns the foreground color to use.
	 *
	 * @param control the control to get the display from
	 * @return the foreground color
	 * @since 3.2
	 */
	private Color getForegroundColor(Control control) {
		Color c= fContentAssistant.getProposalSelectorForeground();
		if (c == null)
			c= JFaceResources.getColorRegistry().get(JFacePreferences.CONTENT_ASSIST_FOREGROUND_COLOR);
		return c;
	}

	/**
	 * Creates the caption line under the proposal table.
	 *
	 * @since 3.2
	 */
	private void createMessageText() {
		if (fMessageText == null) {
			fMessageText= new Label(fProposalShell, SWT.RIGHT);
			GridData textData= new GridData(SWT.FILL, SWT.BOTTOM, true, false);
			fMessageText.setLayoutData(textData);
			fMessageText.setText(fContentAssistant.getStatusMessage() + " "); //$NON-NLS-1$
			if (fMessageTextFont == null) {
				Font font= fMessageText.getFont();
				Display display= fProposalShell.getDisplay();
				FontData[] fontDatas= font.getFontData();
				for (FontData fontData : fontDatas)
					fontData.setHeight(fontData.getHeight() * 9 / 10);
				fMessageTextFont= new Font(display, fontDatas);
			}
			fMessageText.setFont(fMessageTextFont);
			fMessageText.setBackground(getBackgroundColor(fProposalShell));
			fMessageText.setForeground(getForegroundColor(fProposalShell));

			if (fContentAssistant.isRepeatedInvocationMode()) {
				fMessageText.setCursor(fProposalShell.getDisplay().getSystemCursor(SWT.CURSOR_HAND));
				fMessageText.addMouseListener(new MouseAdapter() {
					@Override
					public void mouseUp(MouseEvent e) {
						fLastCompletionOffset= fFilterOffset;
						fProposalTable.setFocus();
						handleRepeatedInvocation();
					}

					@Override
					public void mouseDown(MouseEvent e) {
					}
				});
			}
		}
	}

	/*
	 * @since 3.1
	 */
	private void handleSetData(Event event) {
		TableItem item= (TableItem) event.item;
		int index= fProposalTable.indexOf(item);

		if (0 <= index && index < fFilteredProposals.size()) {
			ICompletionProposal current= fFilteredProposals.get(index);

			String displayString;
			StyleRange[] styleRanges= null;
			Image image= null;
			try {
				if (fIsColoredLabelsSupportEnabled && current instanceof ICompletionProposalExtension7 && Helper.okToUse(fProposalShell)) {
					BoldStylerProvider boldStylerProvider= fContentAssistant.getBoldStylerProvider();
					if (boldStylerProvider == null) {
						boldStylerProvider= new BoldStylerProvider(fProposalShell.getFont());
						fContentAssistant.setBoldStylerProvider(boldStylerProvider);
					}
					StyledString styledString= ((ICompletionProposalExtension7) current).getStyledDisplayString(fContentAssistSubjectControlAdapter.getDocument(), fFilterOffset,
							boldStylerProvider);
					displayString= styledString.getString();
					styleRanges= styledString.getStyleRanges();
				} else if (fIsColoredLabelsSupportEnabled && current instanceof ICompletionProposalExtension6) {
					StyledString styledString= ((ICompletionProposalExtension6) current).getStyledDisplayString();
					displayString= styledString.getString();
					styleRanges= styledString.getStyleRanges();
				} else {
					displayString= current.getDisplayString();
				}
			} catch (RuntimeException e) {
				// On failures to retrieve the proposal's text, insert a dummy entry and log the error.
				displayString= JFaceTextMessages.getString("CompletionProposalPopup.error_retrieving_proposal"); //$NON-NLS-1$

				String PLUGIN_ID= "org.eclipse.jface.text"; //$NON-NLS-1$
				ILog log= Platform.getLog(Platform.getBundle(PLUGIN_ID));
				log.log(new Status(IStatus.ERROR, PLUGIN_ID, IStatus.OK, JFaceTextMessages.getString("CompletionProposalPopup.unexpected_error"), e)); //$NON-NLS-1$
			}

			try {
				image= current.getImage();
			} catch (RuntimeException e) {
				// If we are unable to retrieve the proposal's image, leave it blank.
			}

			item.setText(displayString);
			if (fIsColoredLabelsSupportEnabled)
				TableOwnerDrawSupport.storeStyleRanges(item, 0, styleRanges);

			item.setImage(image);
			item.setData(current);
		} else {
			// this should not happen, but does on win32
		}
	}

	/**
	 * Returns the proposal selected in the proposal selector.
	 *
	 * @return the selected proposal
	 * @since 2.0
	 */
	private ICompletionProposal getSelectedProposal() {
		/* Make sure that there is no filter runnable pending.
		 * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=31427
		 */
		if (fIsFilterPending.get())
			fFilterRunnable.run();

		// filter runnable may have hidden the proposals
		if (!Helper.okToUse(fProposalTable))
			return null;

		int i= fProposalTable.getSelectionIndex();
		if (fFilteredProposals == null || i < 0 || i >= fFilteredProposals.size())
			return null;
		return fFilteredProposals.get(i);
	}

	/**
	 * Takes the selected proposal and applies it.
	 *
	 * @param stateMask the state mask
	 * @since 3.2
	 */
	private void insertSelectedProposalWithMask(int stateMask) {
		ICompletionProposal p= getSelectedProposal();
		hide();
		if (p != null)
			insertProposal(p, (char) 0, stateMask, fContentAssistSubjectControlAdapter.getSelectedRange().x);
	}

	/**
	 * Applies the given proposal at the given offset. The given character is the
	 * one that triggered the insertion of this proposal.
	 *
	 * @param p the completion proposal
	 * @param trigger the trigger character
	 * @param stateMask the state mask
	 * @param offset the offset
	 * @since 2.1
	 */
	void insertProposal(ICompletionProposal p, char trigger, int stateMask, final int offset) {

		fInserting= true;
		IRewriteTarget target= null;
		IEditingSupport helper= new IEditingSupport() {

			@Override
			public boolean isOriginator(DocumentEvent event, IRegion focus) {
				return focus.getOffset() <= offset && focus.getOffset() + focus.getLength() >= offset;
			}

			@Override
			public boolean ownsFocusShell() {
				return false;
			}

		};

		try {

			IDocument document= fContentAssistSubjectControlAdapter.getDocument();

			if (fViewer instanceof ITextViewerExtension) {
				ITextViewerExtension extension= (ITextViewerExtension) fViewer;
				target= extension.getRewriteTarget();
			}

			if (target != null)
				target.beginCompoundChange();

			if (fViewer instanceof IEditingSupportRegistry) {
				IEditingSupportRegistry registry= (IEditingSupportRegistry) fViewer;
				registry.register(helper);
			}


			if (p instanceof ICompletionProposalExtension2 && fViewer != null) {
				ICompletionProposalExtension2 e= (ICompletionProposalExtension2) p;
				e.apply(fViewer, trigger, stateMask, offset);
			} else if (p instanceof ICompletionProposalExtension) {
				ICompletionProposalExtension e= (ICompletionProposalExtension) p;
				e.apply(document, trigger, offset);
			} else {
				p.apply(document);
			}
			fireAppliedEvent(p);

			Point selection= p.getSelection(document);
			if (selection != null) {
				fContentAssistSubjectControlAdapter.setSelectedRange(selection.x, selection.y);
				fContentAssistSubjectControlAdapter.revealRange(selection.x, selection.y);
			}

			IContextInformation info= p.getContextInformation();
			if (info != null) {

				int contextInformationOffset;
				if (p instanceof ICompletionProposalExtension) {
					ICompletionProposalExtension e= (ICompletionProposalExtension) p;
					contextInformationOffset= e.getContextInformationPosition();
				} else {
					if (selection == null)
						selection= fContentAssistSubjectControlAdapter.getSelectedRange();
					contextInformationOffset= selection.x + selection.y;
				}

				fContentAssistant.showContextInformation(info, contextInformationOffset);
			} else
				fContentAssistant.showContextInformation(null, -1);


		} finally {
			if (target != null)
				target.endCompoundChange();

			if (fViewer instanceof IEditingSupportRegistry) {
				IEditingSupportRegistry registry= (IEditingSupportRegistry) fViewer;
				registry.unregister(helper);
			}
			fInserting= false;
		}
	}

	/**
	 * Returns whether this popup has the focus.
	 *
	 * @return <code>true</code> if the popup has the focus
	 */
	public boolean hasFocus() {
		if (Helper.okToUse(fProposalShell)) {
			if ((fProposalShell.getDisplay().getActiveShell() == fProposalShell))
				return true;
			/*
			 * We have to delegate this query to the additional info controller
			 * as well, since the content assistant is the widget token owner
			 * and its closer does not know that the additional info control can
			 * now also take focus.
			 */
			if (fAdditionalInfoController != null) {
				IInformationControl informationControl= fAdditionalInfoController.getCurrentInformationControl2();
				if (informationControl != null && informationControl.isFocusControl())
					return true;
				InformationControlReplacer replacer= fAdditionalInfoController.getInternalAccessor().getInformationControlReplacer();
				if (replacer != null) {
					informationControl= replacer.getCurrentInformationControl2();
					if (informationControl != null && informationControl.isFocusControl())
						return true;
				}
			}
		}

		return false;
	}

	/**
	 * Hides this popup.
	 */
	public void hide() {

		unregister();

		if (fViewer instanceof IEditingSupportRegistry) {
			IEditingSupportRegistry registry= (IEditingSupportRegistry) fViewer;
			registry.unregister(fFocusHelper);
		}

		if (Helper.okToUse(fProposalShell)) {

			fContentAssistant.removeContentAssistListener(this, ContentAssistant.PROPOSAL_SELECTOR);

			fPopupCloser.uninstall();
			fProposalShell.setVisible(false);
			fProposalShell.dispose();
			fProposalShell= null;
		}

		if (fMessageTextFont != null) {
			fMessageTextFont.dispose();
			fMessageTextFont= null;
		}

		if (fMessageText != null) {
			fMessageText= null;
		}

		fEmptyMessage= null;

		fLastCompletionOffset= -1;

		fContentAssistant.fireSessionEndEvent();
	}

	/**
	 * Unregister this completion proposal popup.
	 *
	 * @since 3.0
	 */
	private void unregister() {
		if (fDocumentListener != null) {
			IDocument document= fContentAssistSubjectControlAdapter.getDocument();
			if (document != null)
				document.removeDocumentListener(fDocumentListener);
			fDocumentListener= null;
		}
		fDocumentEvents.clear();

		if (fKeyListener != null && fContentAssistSubjectControlAdapter.getControl() != null && !fContentAssistSubjectControlAdapter.getControl().isDisposed()) {
			fContentAssistSubjectControlAdapter.removeKeyListener(fKeyListener);
			fKeyListener= null;
		}

		if (fLastProposal != null) {
			if (fLastProposal instanceof ICompletionProposalExtension2 && fViewer != null) {
				ICompletionProposalExtension2 extension= (ICompletionProposalExtension2) fLastProposal;
				extension.unselected(fViewer);
			}
			fLastProposal= null;
		}

		fFilteredProposals= null;
		fComputedProposals= null;

		fContentAssistant.possibleCompletionsClosed();
	}

	/**
	 *Returns whether this popup is active. It is active if the proposal selector is visible.
	 *
	 * @return <code>true</code> if this popup is active
	 */
	public boolean isActive() {
		return fProposalShell != null && !fProposalShell.isDisposed();
	}

	/**
	 * Initializes the proposal selector with these given proposals. If a proposal sorter is
	 * configured, the given proposals are sorted before.
	 *
	 * @param proposals the proposals
	 * @param isFilteredSubset if <code>true</code>, the proposal table is
	 *        not cleared, but the proposals that are not in the passed array
	 *        are removed from the displayed set
	 */
	void setProposals(List<ICompletionProposal> proposals, boolean isFilteredSubset) {
		List<ICompletionProposal> oldProposals= fFilteredProposals;
		ICompletionProposal oldProposal= getSelectedProposal(); // may trigger filtering and a reentrant call to setProposals()
		if (oldProposals != fFilteredProposals) // reentrant call was first - abort
			return;

		if (Helper.okToUse(fProposalTable)) {
			if (oldProposal instanceof ICompletionProposalExtension2 && fViewer != null)
				((ICompletionProposalExtension2) oldProposal).unselected(fViewer);

			if (proposals == null || proposals.isEmpty()) {
				fEmptyProposal.fOffset= fFilterOffset;
				fEmptyProposal.fDisplayString= fEmptyMessage != null ? fEmptyMessage : JFaceTextMessages.getString("CompletionProposalPopup.no_proposals"); //$NON-NLS-1$
				proposals= Collections.singletonList(fEmptyProposal);
			}

			if (fSorter != null && !fIsInitialSort) {
				sortProposals(proposals);
			}
			fIsInitialSort= false;

			fFilteredProposals= proposals;
			final int newLen= proposals.size();

			fProposalTable.clearAll();
			fProposalTable.setItemCount(newLen);

			Point currentLocation= fProposalShell.getLocation();
			Point newLocation= getLocation();
			if ((newLocation.x < currentLocation.x && newLocation.y == currentLocation.y) || newLocation.y < currentLocation.y)
				fProposalShell.setLocation(newLocation);

			selectProposal(0, false);
		}
	}

	/**
	 * Returns the graphical location at which this popup should be made visible.
	 *
	 * @return the location of this popup
	 */
	private Point getLocation() {
		int caret= fContentAssistSubjectControlAdapter.getCaretOffset();
		Rectangle location= fContentAssistant.getLayoutManager().computeBoundsBelowAbove(fProposalShell, fSize == null ? fProposalShell.getSize() : fSize, caret, this);
		return Geometry.getLocation(location);
	}

	/**
	 * Returns the size of this completion proposal popup.
	 *
	 * @return a Point containing the size
	 * @since 3.0
	 */
	Point getSize() {
		return fSize;
	}

	/**
	 * Displays this popup and install the additional info controller, so that additional info
	 * is displayed when a proposal is selected and additional info is available.
	 */
	void displayProposals() {

		if (!Helper.okToUse(fProposalShell) ||  !Helper.okToUse(fProposalTable))
			return;

		if (fContentAssistant.addContentAssistListener(this, ContentAssistant.PROPOSAL_SELECTOR)) {

			ensureDocumentListenerInstalled();

			if (fFocusHelper == null) {
				fFocusHelper= new IEditingSupport() {

					@Override
					public boolean isOriginator(DocumentEvent event, IRegion focus) {
						return false; // this helper just covers the focus change to the proposal shell, no remote editions
					}

					@Override
					public boolean ownsFocusShell() {
						return true;
					}

				};
			}
			if (fViewer instanceof IEditingSupportRegistry) {
				IEditingSupportRegistry registry= (IEditingSupportRegistry) fViewer;
				registry.register(fFocusHelper);
			}


			/* https://bugs.eclipse.org/bugs/show_bug.cgi?id=52646
			 * on GTK, setVisible and such may run the event loop
			 * (see also https://bugs.eclipse.org/bugs/show_bug.cgi?id=47511)
			 * Since the user may have already canceled the popup or selected
			 * an entry (ESC or RETURN), we have to double check whether
			 * the table is still okToUse. See comments below
			 */
			fProposalShell.setVisible(true); // may run event loop on GTK
			// transfer focus since no verify key listener can be attached
			if (!fContentAssistSubjectControlAdapter.supportsVerifyKeyListener() && Helper.okToUse(fProposalShell))
				fProposalShell.setFocus(); // may run event loop on GTK ??

			if (fAdditionalInfoController != null && Helper.okToUse(fProposalTable)) {
				fAdditionalInfoController.install(fProposalTable);
				fAdditionalInfoController.handleTableSelectionChanged();
			}
		} else
			hide();
	}

	/**
	 * Installs the document listener if not already done.
	 *
	 * @since 3.2
	 */
	void ensureDocumentListenerInstalled() {
		if (fDocumentListener == null) {
			fDocumentListener=  new IDocumentListener()  {
				@Override
				public void documentAboutToBeChanged(DocumentEvent event) {
					if (!fInserting)
						fDocumentEvents.add(event);
				}

				@Override
				public void documentChanged(DocumentEvent event) {
					if (!fInserting)
						filterProposals();
				}
			};
			IDocument document= fContentAssistSubjectControlAdapter.getDocument();
			if (document != null)
				document.addDocumentListener(fDocumentListener);
		}
	}

	@Override
	public boolean verifyKey(VerifyEvent e) {
		if (!Helper.okToUse(fProposalShell))
			return true;

		char key= e.character;
		if (key == 0) {
			int newSelection= fProposalTable.getSelectionIndex();
			int visibleRows= (fProposalTable.getSize().y / fProposalTable.getItemHeight()) - 1;
			int itemCount= fProposalTable.getItemCount();
			switch (e.keyCode) {

				case SWT.ARROW_LEFT :
				case SWT.ARROW_RIGHT :
					filterProposals();
					return true;

				case SWT.ARROW_UP :
					newSelection -= 1;
					if (newSelection < 0)
						newSelection= itemCount - 1;
					break;

				case SWT.ARROW_DOWN :
					newSelection += 1;
					if (newSelection > itemCount - 1)
						newSelection= 0;
					break;

				case SWT.PAGE_DOWN :
					newSelection += visibleRows;
					if (newSelection >= itemCount)
						newSelection= itemCount - 1;
					break;

				case SWT.PAGE_UP :
					newSelection -= visibleRows;
					if (newSelection < 0)
						newSelection= 0;
					break;

				case SWT.HOME :
					newSelection= 0;
					break;

				case SWT.END :
					newSelection= itemCount - 1;
					break;

				default :
					if (e.keyCode != SWT.CAPS_LOCK && e.keyCode != SWT.MOD1 && e.keyCode != SWT.MOD2 && e.keyCode != SWT.MOD3 && e.keyCode != SWT.MOD4)
						hide();
					return true;
			}

			selectProposal(newSelection, (e.stateMask & SWT.CTRL) != 0);

			e.doit= false;
			return false;

		}

		// key != 0
		switch (key) {
			case 0x1B: // Esc
				e.doit= false;
				hide();
				break;

			case '\n': // Ctrl-Enter on w2k
			case '\r': // Enter
				e.doit= false;
				insertSelectedProposalWithMask(e.stateMask);
				break;

			case '\t':
				e.doit= false;
				fProposalShell.setFocus();
				return false;

			default:
				if (fContentAssistant.isCompletionProposalTriggerCharsEnabled()) {
					ICompletionProposal p= getSelectedProposal();
					if (p instanceof ICompletionProposalExtension) {
						ICompletionProposalExtension t= (ICompletionProposalExtension) p;
						char[] triggers= t.getTriggerCharacters();
						if (contains(triggers, key)) {
							e.doit= false;
							hide();
							insertProposal(p, key, e.stateMask, fContentAssistSubjectControlAdapter.getSelectedRange().x);
						}
					}
				}
		}

		return true;
	}

	/**
	 * Selects the entry with the given index in the proposal selector and feeds
	 * the selection to the additional info controller.
	 *
	 * @param index the index in the list
	 * @param smartToggle <code>true</code> if the smart toggle key has been pressed
	 * @since 2.1
	 */
	private void selectProposal(int index, boolean smartToggle) {

		ICompletionProposal oldProposal= getSelectedProposal();
		if (oldProposal instanceof ICompletionProposalExtension2 && fViewer != null)
			((ICompletionProposalExtension2) oldProposal).unselected(fViewer);

		if (fFilteredProposals == null) {
			fireSelectionEvent(null, smartToggle);
			return;
		}

		ICompletionProposal proposal= fFilteredProposals.get(index);
		if (proposal instanceof ICompletionProposalExtension2 && fViewer != null)
			((ICompletionProposalExtension2) proposal).selected(fViewer, smartToggle);

		fireSelectionEvent(proposal, smartToggle);

		fLastProposal= proposal;

		fProposalTable.setSelection(index);
		fProposalTable.showSelection();
		if (fAdditionalInfoController != null)
			fAdditionalInfoController.handleTableSelectionChanged();
	}

	/**
	 * Fires a selection event, see {@link ICompletionListener}.
	 *
	 * @param proposal the selected proposal, possibly <code>null</code>
	 * @param smartToggle true if the smart toggle is on
	 * @since 3.2
	 */
	private void fireSelectionEvent(ICompletionProposal proposal, boolean smartToggle) {
		fContentAssistant.fireSelectionEvent(proposal, smartToggle);
	}

	/**
	 * Fires an event after applying the given proposal, see {@link ICompletionListenerExtension2}.
	 *
	 * @param proposal the applied proposal
	 * @since 3.8
	 */
	private void fireAppliedEvent(ICompletionProposal proposal) {
		fContentAssistant.fireAppliedEvent(proposal);
	}

	/**
	 * Returns whether the given character is contained in the given array of characters.
	 *
	 * @param characters the list of characters
	 * @param c the character to look for in the list
	 * @return <code>true</code> if character belongs to the list
	 * @since 2.0
	 */
	private boolean contains(char[] characters, char c) {

		if (characters == null)
			return false;

		for (char character : characters) {
			if (c == character)
				return true;
		}

		return false;
	}

	@Override
	public void processEvent(VerifyEvent e) {
	}

	/**
	 * Filters the displayed proposal based on the given cursor position and the
	 * offset of the original invocation of the content assistant.
	 */
	void filterProposals() {
		if (fIsFilterPending.compareAndSet(false, true)) {
			Control control= fContentAssistSubjectControlAdapter.getControl();
			control.getDisplay().asyncExec(fFilterRunnable);
		}
	}

	/**
	 * Computes the subset of already computed proposals that are still valid for
	 * the given offset.
	 *
	 * @param offset the offset
	 * @param event the merged document event
	 * @return the set of filtered proposals
	 * @since 3.0
	 */
	List<ICompletionProposal> computeFilteredProposals(int offset, DocumentEvent event) {
		fDocumentEvents.clear();

		if (offset == fInvocationOffset && event == null) {
			fIsFilteredSubset= false;
			return fComputedProposals;
		}

		if (offset < fInvocationOffset) {
			fIsFilteredSubset= false;
			fInvocationOffset= offset;
			fContentAssistant.fireSessionRestartEvent();
			fComputedProposals= computeProposals(fInvocationOffset);
			return fComputedProposals;
		}

		List<ICompletionProposal> proposals;
		if (offset < fFilterOffset) {
			proposals= fComputedProposals;
			fIsFilteredSubset= false;
		} else {
			proposals= fFilteredProposals;
			fIsFilteredSubset= true;
		}

		if (proposals == null) {
			fIsFilteredSubset= false;
			return null;
		}

		IDocument document= fContentAssistSubjectControlAdapter.getDocument();
		int length= proposals.size();
		List<ICompletionProposal> filtered= new ArrayList<>(length);
		for (ICompletionProposal proposal : proposals) {

			if (proposal instanceof ICompletionProposalExtension2) {

				ICompletionProposalExtension2 p= (ICompletionProposalExtension2) proposal;
				try {
					if (p.validate(document, offset, event))
						filtered.add(proposal);
				} catch (RuntimeException e) {
					// Make sure that poorly behaved completion proposers do not break filtering.
				}
			} else if (proposal instanceof ICompletionProposalExtension) {

				ICompletionProposalExtension p= (ICompletionProposalExtension) proposal;
				try {
					if (p.isValidFor(document, offset))
						filtered.add(proposal);
				} catch (RuntimeException e) {
					// Make sure that poorly behaved completion proposers do not break filtering.
				}
			} else {
				// restore original behavior
				fIsFilteredSubset= false;
				fInvocationOffset= offset;
				fContentAssistant.fireSessionRestartEvent();
				fComputedProposals= computeProposals(fInvocationOffset);
				return fComputedProposals;
			}
		}

		return filtered;
	}

	/**
	 * Requests the proposal shell to take focus.
	 *
	 * @since 3.0
	 */
	public void setFocus() {
		if (Helper.okToUse(fProposalShell)) {
			fProposalShell.setFocus();
		}
	}

	/**
	 * Returns <code>true</code> if <code>proposal</code> should be auto-inserted,
	 * <code>false</code> otherwise.
	 *
	 * @param proposal the single proposal that might be automatically inserted
	 * @return <code>true</code> if <code>proposal</code> can be inserted automatically,
	 *         <code>false</code> otherwise
	 * @since 3.1
	 */
	boolean canAutoInsert(ICompletionProposal proposal) {
		if (fContentAssistant.isAutoInserting()) {
			if (proposal instanceof ICompletionProposalExtension4) {
				ICompletionProposalExtension4 ext= (ICompletionProposalExtension4) proposal;
				return ext.isAutoInsertable();
			}
			return true; // default behavior before ICompletionProposalExtension4 was introduced
		}
		return false;
	}

	/**
	 * Completes the common prefix of all proposals directly in the code. If no
	 * common prefix can be found, the proposal popup is shown.
	 *
	 * @return an error message if completion failed.
	 * @since 3.0
	 */
	public String incrementalComplete() {
		if (Helper.okToUse(fProposalShell) && fFilteredProposals != null) {
			if (fLastCompletionOffset == fFilterOffset) {
				handleRepeatedInvocation();
			} else {
				fLastCompletionOffset= fFilterOffset;
				completeCommonPrefix();
			}
		} else {
			final Control control= fContentAssistSubjectControlAdapter.getControl();

			if (fKeyListener == null)
				fKeyListener= new ProposalSelectionListener();

			if (!Helper.okToUse(fProposalShell) && !control.isDisposed())
				fContentAssistSubjectControlAdapter.addKeyListener(fKeyListener);

			BusyIndicator.showWhile(control.getDisplay(), () -> {

				fInvocationOffset= fContentAssistSubjectControlAdapter.getSelectedRange().x;
				fFilterOffset= fInvocationOffset;
				fLastCompletionOffset= fFilterOffset;
				fFilteredProposals= computeProposals(fInvocationOffset);

				int count= (fFilteredProposals == null ? 0 : fFilteredProposals.size());
				if (count == 0 && hideWhenNoProposals(false))
					return;

				if (count == 1 && canAutoInsert(fFilteredProposals.get(0))) {
					insertProposal(fFilteredProposals.get(0), (char) 0, 0, fInvocationOffset);
					hide();
				} else {
					ensureDocumentListenerInstalled();
					if (count > 0 && completeCommonPrefix())
						hide();
					else {
						fComputedProposals= fFilteredProposals;
						createProposalSelector();
						setProposals(fComputedProposals, false);
						displayProposals();
					}
				}
			});
		}
		return getErrorMessage();
	}

	/**
	 * Acts upon <code>fFilteredProposals</code>: if there is just one valid
	 * proposal, it is inserted, otherwise, the common prefix of all proposals
	 * is inserted into the document. If there is no common prefix, nothing
	 * happens and <code>false</code> is returned.
	 *
	 * @return <code>true</code> if a single proposal was inserted and the
	 *         selector can be closed, <code>false</code> otherwise
	 * @since 3.0
	 */
	boolean completeCommonPrefix() {

		// 0: insert single proposals
		if (fFilteredProposals.size() == 1) {
			if (canAutoInsert(fFilteredProposals.get(0))) {
				insertProposal(fFilteredProposals.get(0), (char) 0, 0, fFilterOffset);
				hide();
				return true;
			}
			return false;
		}

		// 1: extract pre- and postfix from all remaining proposals
		IDocument document= fContentAssistSubjectControlAdapter.getDocument();

		// contains the common postfix in the case that there are any proposals matching our LHS
		StringBuilder rightCasePostfix= null;
		List<ICompletionProposal> rightCase= new ArrayList<>();

		boolean isWrongCaseMatch= false;

		// the prefix of all case insensitive matches. This differs from the document
		// contents and will be replaced.
		CharSequence wrongCasePrefix= null;
		int wrongCasePrefixStart= 0;
		// contains the common postfix of all case-insensitive matches
		StringBuilder wrongCasePostfix= null;
		List<ICompletionProposal> wrongCase= new ArrayList<>();

		boolean hasMixedProposals= hasMixedProposals();
		for (int i= 0; i < fFilteredProposals.size(); i++) {
			ICompletionProposal proposal= fFilteredProposals.get(i);

			if (!(proposal instanceof ICompletionProposalExtension3))
				return false;

			int start= ((ICompletionProposalExtension3)proposal).getPrefixCompletionStart(document, fFilterOffset);
			CharSequence insertion= ((ICompletionProposalExtension3)proposal).getPrefixCompletionText(document, fFilterOffset);
			if (insertion == null)
				insertion= TextProcessor.deprocess(proposal.getDisplayString());
			try {
				int prefixLength= fFilterOffset - start;
				int relativeCompletionOffset= Math.min(insertion.length(), prefixLength);
				String prefix= document.get(start, prefixLength);
				if (!isWrongCaseMatch && insertion.toString().startsWith(prefix) && !hasMixedProposals) {
					isWrongCaseMatch= false;
					rightCase.add(proposal);
					CharSequence newPostfix= insertion.subSequence(relativeCompletionOffset, insertion.length());
					if (rightCasePostfix == null)
						rightCasePostfix= new StringBuilder(newPostfix.toString());
					else
						truncatePostfix(rightCasePostfix, newPostfix, false);
				} else if (i == 0 || isWrongCaseMatch) {
					String insertionStrLowerCase= insertion.toString().toLowerCase();
					String prefixLowerCase= prefix.toLowerCase();
					boolean isSubstringMatch= !insertionStrLowerCase.startsWith(prefixLowerCase) && insertionStrLowerCase.contains(prefixLowerCase);

					CharSequence newPrefix;
					if (isSubstringMatch) {
						int subStrStart= insertionStrLowerCase.indexOf(prefixLowerCase);
						newPrefix= insertion.subSequence(subStrStart, subStrStart + relativeCompletionOffset);
					} else {
						newPrefix= insertion.subSequence(0, relativeCompletionOffset);
					}
					if (isPrefixCompatible(wrongCasePrefix, wrongCasePrefixStart, newPrefix, start, document, hasMixedProposals)) {
						isWrongCaseMatch= true;
						if (insertionStrLowerCase.isEmpty()) {
							newPrefix= prefix;
						}
						if (wrongCasePrefix == null || !hasMixedProposals || !wrongCasePrefix.toString().equalsIgnoreCase(newPrefix.toString())) {
							wrongCasePrefix= newPrefix; // ignore casing when there are mixed proposals - don't update if newPrefix differs only in case
						}
						wrongCasePrefixStart= start;
						CharSequence newPostfix;
						if (isSubstringMatch) {
							int subStrStart= insertionStrLowerCase.indexOf(prefixLowerCase);
							newPostfix= insertion.subSequence(subStrStart + prefixLength, insertion.length());
						} else {
							newPostfix= insertion.subSequence(relativeCompletionOffset, insertion.length());
						}
						if (wrongCasePostfix == null)
							wrongCasePostfix= new StringBuilder(newPostfix.toString());
						else
							truncatePostfix(wrongCasePostfix, newPostfix, hasMixedProposals);
						wrongCase.add(proposal);
					} else {
						return false;
					}
				} else
					return false;
			} catch (BadLocationException e2) {
				// bail out silently
				return false;
			}

			if (rightCasePostfix != null && rightCasePostfix.length() == 0 && rightCase.size() > 1)
				return false;
		}

		// 2: replace single proposals

		if (rightCase.size() == 1) {
			ICompletionProposal proposal= rightCase.get(0);
			if (canAutoInsert(proposal) && rightCasePostfix.length() > 0) {
				insertProposal(proposal, (char) 0, 0, fInvocationOffset);
				hide();
				return true;
			}
			return false;
		} else if (isWrongCaseMatch && wrongCase.size() == 1) {
			ICompletionProposal proposal= wrongCase.get(0);
			if (canAutoInsert(proposal)) {
				insertProposal(proposal, (char) 0, 0, fInvocationOffset);
				hide();
			return true;
			}
			return false;
		}

		// 3: replace post- / prefixes

		CharSequence prefix;
		if (isWrongCaseMatch)
			prefix= wrongCasePrefix;
		else
			prefix= "";  //$NON-NLS-1$

		CharSequence postfix;
		if (isWrongCaseMatch)
			postfix= wrongCasePostfix;
		else
			postfix= rightCasePostfix;

		if (prefix == null || postfix == null)
			return false;

		try {
			// 4: check if parts of the postfix are already in the document
			int to= Math.min(document.getLength(), fFilterOffset + postfix.length());
			StringBuilder inDocument= new StringBuilder(document.get(fFilterOffset, to - fFilterOffset));
			truncatePostfix(inDocument, postfix, hasMixedProposals);

			// 5: replace and reveal
			document.replace(fFilterOffset - prefix.length(), prefix.length() + inDocument.length(), prefix.toString() + postfix.toString());

			fContentAssistSubjectControlAdapter.setSelectedRange(fFilterOffset + postfix.length(), 0);
			fContentAssistSubjectControlAdapter.revealRange(fFilterOffset + postfix.length(), 0);
			fFilterOffset+= postfix.length();
			fLastCompletionOffset= fFilterOffset;

			return false;
		} catch (BadLocationException e) {
			// ignore and return false
			return false;
		}
	}

	/**
	 * Checks if {@link #fFilteredProposals} list contains proposals based on different rules
	 * (prefix and substring match rules). While extracting the common prefix, if substring
	 * proposals are also present along with prefix proposals (i.e. <code>fFilteredProposals</code>
	 * list has mixed proposals) then casing of substring matches is ignored for the computation of
	 * common prefix.
	 *
	 * @return <code>true</code> if <code>fFilteredProposals</code> list contains proposals based on
	 *         different rules
	 */
	private boolean hasMixedProposals() {
		IDocument document= fContentAssistSubjectControlAdapter.getDocument();
		boolean hasSubstringMatch= false;
		boolean hasPrefixMatch= false;
		for (ICompletionProposal proposal : fFilteredProposals) {
			if (!(proposal instanceof ICompletionProposalExtension3))
				return false;

			int start= ((ICompletionProposalExtension3) proposal).getPrefixCompletionStart(document, fFilterOffset);
			CharSequence insertion= ((ICompletionProposalExtension3) proposal).getPrefixCompletionText(document, fFilterOffset);
			if (insertion == null) {
				insertion= TextProcessor.deprocess(proposal.getDisplayString());
			}
			int prefixLength= fFilterOffset - start;
			try {
				String prefix= document.get(start, prefixLength);
				String insertionString= insertion.toString();
				if (insertionString.isEmpty() || insertionString.toLowerCase().startsWith(prefix.toLowerCase())) {
					hasPrefixMatch= true;
				} else if (insertionString.toLowerCase().contains(prefix.toLowerCase())) {
					hasSubstringMatch= true;
				}
			} catch (BadLocationException e) {
				return false;
			}
			if (hasPrefixMatch && hasSubstringMatch) {
				return true;
			}
		}
		return false;
	}

	/*
	 * @since 3.1
	 */
	private boolean isPrefixCompatible(CharSequence oneSequence, int oneOffset, CharSequence twoSequence, int twoOffset, IDocument document, boolean ignoreCase) throws BadLocationException {
		if (oneSequence == null || twoSequence == null)
			return true;

		int min= Math.min(oneOffset, twoOffset);
		int oneEnd= oneOffset + oneSequence.length();
		int twoEnd= twoOffset + twoSequence.length();

		String one= document.get(oneOffset, min - oneOffset) + oneSequence + document.get(oneEnd, Math.min(fFilterOffset, fFilterOffset - oneEnd));
		String two= document.get(twoOffset, min - twoOffset) + twoSequence + document.get(twoEnd, Math.min(fFilterOffset, fFilterOffset - twoEnd));

		return ignoreCase ? one.equalsIgnoreCase(two) : one.equals(two);
	}

	/**
	 * Truncates <code>buffer</code> to the common prefix of <code>buffer</code>
	 * and <code>sequence</code>.
	 *
	 * @param buffer the common postfix to truncate
	 * @param sequence the characters to truncate with
	 * @param ignoreCase <code>true</code> to ignore case while comparing
	 */
	private void truncatePostfix(StringBuilder buffer, CharSequence sequence, boolean ignoreCase) {
		// find common prefix
		int min= Math.min(buffer.length(), sequence.length());
		for (int c= 0; c < min; c++) {
			boolean matches;
			if (ignoreCase) {
				matches= Character.toUpperCase(sequence.charAt(c)) == Character.toUpperCase(buffer.charAt(c));
			} else {
				matches= sequence.charAt(c) == buffer.charAt(c);
			}
			if (!matches) {
				buffer.delete(c, buffer.length());
				return;
			}
		}

		// all equal up to minimum
		buffer.delete(min, buffer.length());
	}

	/**
	 * Sets the message for the repetition affordance text at the bottom of the proposal. Only has
	 * an effect if {@link ContentAssistant#isRepeatedInvocationMode()} returns <code>true</code>.
	 *
	 * @param message the new caption
	 * @since 3.2
	 */
	void setMessage(String message) {
		Assert.isNotNull(message);
		if (isActive() && fMessageText != null && !fMessageText.isDisposed())
			fMessageText.setText(message + " "); //$NON-NLS-1$
	}

	/**
	 * Sets the text to be displayed if no proposals are available. Only has an effect if
	 * {@link ContentAssistant#isShowEmptyList()} returns <code>true</code>.
	 *
	 * @param message the empty message
	 * @since 3.2
	 */
	void setEmptyMessage(String message) {
		Assert.isNotNull(message);
		fEmptyMessage= message;
	}

	/**
	 * Enables or disables showing of the caption line. See also {@link #setMessage(String)}.
	 *
	 * @param show <code>true</code> if the status line is visible
	 * @since 3.2
	 */
	public void setStatusLineVisible(boolean show) {
		if (!isActive() || show == (fMessageText != null && !fMessageText.isDisposed()))
			return; // nothing to do

		if (show) {
			createMessageText();
		} else {
			fMessageText.dispose();
			fMessageText= null;
		}
		fProposalShell.layout();
	}

	/**
	 * Informs the popup that it is being placed above the caret line instead of below.
	 *
	 * @param above <code>true</code> if the location of the popup is above the caret line, <code>false</code> if it is below
	 * @since 3.3
	 */
	void switchedPositionToAbove(boolean above) {
		if (fAdditionalInfoController != null) {
			fAdditionalInfoController.setFallbackAnchors(new Anchor[] {
					AbstractInformationControlManager.ANCHOR_RIGHT,
					AbstractInformationControlManager.ANCHOR_LEFT,
					above ? AbstractInformationControlManager.ANCHOR_TOP : AbstractInformationControlManager.ANCHOR_BOTTOM
			});
		}
	}

	/**
	 * Returns a new proposal selection handler.
	 *
	 * @param operationCode the operation code
	 * @return the handler
	 * @since 3.4
	 */
	IHandler createProposalSelectionHandler(int operationCode) {
		return new ProposalSelectionHandler(operationCode);
	}

	/**
	 * Sets the proposal sorter.
	 *
	 * @param sorter the sorter to be used, or <code>null</code> if no sorting is requested
	 * @since 3.8
	 * @see ContentAssistant#setSorter(ICompletionProposalSorter)
	 */
	public void setSorter(ICompletionProposalSorter sorter) {
		fSorter= sorter;
	}

	/**
	 * Sorts the given proposal array.
	 *
	 * @param proposals the new proposals to display in the popup window
	 * @throws NullPointerException if no sorter has been set
	 * @since 3.8
	 */
	void sortProposals(final List<ICompletionProposal> proposals) {
		proposals.sort(fSorter::compare);
	}
}
