/*******************************************************************************
 * Copyright (c) 2000, 2019 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
 *     Paul Pazderski  - Bug 544970: reimplementation with correct text change event calculation
 *******************************************************************************/
package org.eclipse.ui.internal.console;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentAdapter;
import org.eclipse.jface.text.IDocumentListener;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.MultiStringMatcher;
import org.eclipse.jface.text.MultiStringMatcher.Match;
import org.eclipse.jface.text.Region;
import org.eclipse.swt.custom.TextChangeListener;
import org.eclipse.swt.custom.TextChangedEvent;
import org.eclipse.swt.custom.TextChangingEvent;
import org.eclipse.ui.console.ConsolePlugin;

/**
 * Adapts a Console's document to the viewer StyledText widget. Allows proper
 * line wrapping of fixed width consoles without having to add line delimiters
 * to the StyledText.
 *
 * By using this adapter, the offset of any character is the same in both the
 * widget and the document.
 *
 * <p>
 * Note: tab character (\t) is not handled special and counts as one character.
 * So wrapped content may look less fixed width if it contains tab characters.
 * </p>
 *
 * @since 3.1
 */
public class ConsoleDocumentAdapter implements IDocumentAdapter, IDocumentListener {
	/*
	 * Because of the fixed width feature this adapter knows two types of lines.
	 * Document lines are lines as known to the adapted document and are terminated
	 * by a line delimiter (except for the last line). Widget lines are lines as
	 * seen in the text viewer. If a document line is wrapped due to fixed width it
	 * starts a new widget line. Widget lines generated by line wrapping do not have
	 * additional line delimiters. If fixed width is disabled widget line and
	 * document line are the same.
	 */

	/**
	 * If <code>true</code> the adapter will check if the predicted document change
	 * calculated for the TextChangingEvent matches the document after the applied
	 * change. Useful for developing/debugging.
	 */
	private static final boolean ASSERT = false;

	/**
	 * If {@link #widgetLineOffsets} need to grow add some extra space to prevent
	 * frequent array copies.
	 */
	private static final int GROW = 500;

	/** Registered {@link TextChangeListener}s. */
	private final List<TextChangeListener> textChangeListeners = new ArrayList<>();

	/** Fixed console width. If &lt;= 0 fixed console mode is disabled. */
	private int fixedConsoleWidth;

	/** Adapted document. */
	private IDocument document;
	/**
	 * The matcher to find the legal line delimiters of the connected document in
	 * some text. <code>null</code> if no document connected.
	 * <p>
	 * This usually matches <code>{ "\r", "\n", "\r\n" }</code>.
	 * </p>
	 */
	private MultiStringMatcher docLegalLineDelimiterMatcher;

	/**
	 * Number of widget lines in document. If fixed width is disabled it is always
	 * equal to {@link IDocument#getNumberOfLines()}. If fixed width mode is enabled
	 * there may be more widget lines then doc lines but never less.
	 */
	private int widgetLines;

	/**
	 * Start offsets of widget lines.
	 * <p>
	 * <b>Note:</b> offsets are only valid and updated if fixed width is enabled.
	 * </p>
	 * <p>
	 * Example content: if the document contains the following content (with
	 * <code>\r\n</code> as line delimiter)
	 *
	 * <pre>
	 *     0123456789ABCD\r\n
	 *     ---\r\n
	 *     0123456789
	 * </pre>
	 *
	 * a fixed width of <code>10</code> the widget will show it as
	 *
	 * <pre>
	 *     0123456789
	 *     ABCD\r\n
	 *     ---\r\n
	 *     0123456789
	 * </pre>
	 *
	 * the content of the {@link #widgetLineOffsets} array is:
	 * <code>{ 0, 10, 16, 21 }</code> which represent the start offsets from each of
	 * the four widget lines.
	 * </p>
	 * <p>
	 * Initialized with one element to save memory in non fixed width mode but at
	 * the same time prevent NPE.
	 * </p>
	 *
	 * @see #isFixedWidth()
	 * @see #ensureOffsetsCapacity(int)
	 */
	private int[] widgetLineOffsets = new int[1];

	/**
	 * The fact that wrapped lines are new lines without a newline delimiter leads
	 * to some hard to handle edge cases since all involved interfaces (implicit)
	 * assume a newline has its unique offset.
	 * <p>
	 * Consider a fixed with of 10 and a console filled with (automatically wrapped)
	 * content of:
	 * </p>
	 *
	 * <pre>
	 * 0123456789
	 * 0
	 * </pre>
	 *
	 * <p>
	 * If we remove the last character ('0') we must set replaceLineCount to 1 since
	 * there is one line less due to the unwrapped line. The replaceLineCount is
	 * necessary so that StyledTextRenderer updates the lines which possible follow
	 * below and have changed due to moved content.
	 * </p>
	 * <p>
	 * But StyledTextRenderer presumes that the line index where the event occurs is
	 * the same before and after the text change. This is not the case for our auto
	 * wrapped lines since getLineAtOffset(10) is 1 before text change and 0 after
	 * </p>
	 * <p>
	 * To solve this unlucky situation we will lie to StyledText(Renderer) for the
	 * short time between text changing event and actual text change. If we know the
	 * same (start) offset will yield a different line index before and after change
	 * we will return for this offset the line index it will have after the change
	 * already before the change is applied. In this example if StyledText ask for
	 * getLineAtOffset(10) we return 0 already before the text is actual changed.
	 * </p>
	 * <p>
	 * This field store the offset for which we should preempt the new line index.
	 * It must be an offset at fixed width border (or negative for none) because
	 * only those have the potential for two different line indexes at same offset.
	 * </p>
	 */
	private int preemptLineWrapChange = -1;

	/**
	 * New {@link ConsoleDocumentAdapter} with no {@link IDocument} connected yet.
	 *
	 * @param width fixed console width to enforce text wrap or &lt;= 0 to disable
	 *              fixed console width
	 */
	public ConsoleDocumentAdapter(int width) {
		setWidth(width);
	}

	@Override
	public void setDocument(IDocument doc) {
		if (document != null) {
			document.removeDocumentListener(this);
		}

		document = doc;
		docLegalLineDelimiterMatcher = null;
		updateWidgetOffsets(0);

		if (doc != null) {
			doc.addDocumentListener(this);
			docLegalLineDelimiterMatcher = MultiStringMatcher.create(doc.getLegalLineDelimiters());
		}
	}

	@Override
	public synchronized void addTextChangeListener(TextChangeListener listener) {
		Assert.isLegal(listener != null, "listener null"); //$NON-NLS-1$
		if (!textChangeListeners.contains(listener)) {
			textChangeListeners.add(listener);
		}
	}

	@Override
	public synchronized void removeTextChangeListener(TextChangeListener listener) {
		Assert.isLegal(listener != null, "listener null"); //$NON-NLS-1$
		textChangeListeners.remove(listener);
	}

	@Override
	public int getCharCount() {
		return document.getLength();
	}

	@Override
	public String getLine(int lineIndex) {
		try {
			final IRegion lineRegion = getLineInformation(lineIndex);
			return document.get(lineRegion.getOffset(), lineRegion.getLength());
		} catch (BadLocationException e) {
			log(e);
			return ""; //$NON-NLS-1$
		}
	}

	/**
	 * Return information about a widget line.
	 * <p>
	 * Note: in contrast to some implementations of
	 * {@link org.eclipse.jface.text.ILineTracker#getLineInformation(int)} this
	 * implementation throws an exception if line after last line is queried.
	 * </p>
	 *
	 * @param widgetLineIndex the widget line number (first line has number 0)
	 * @return the lines start offset and length excluding line delimiter
	 * @throws BadLocationException if widget line does not exist
	 * @see IDocument#getLineInformation(int)
	 */
	private IRegion getLineInformation(int widgetLineIndex) throws BadLocationException {
		if (!isFixedWidth()) {
			return document.getLineInformation(widgetLineIndex);
		}

		final int widgetLineOffset = getLineOffset(widgetLineIndex);
		final IRegion docLine = document.getLineInformationOfOffset(widgetLineOffset);
		// widget line length is calculated as: length of containing document line
		int widgetLineLength = docLine.getLength();
		// minus preceding wrapped lines
		widgetLineLength -= (widgetLineOffset - docLine.getOffset());
		// now widgetLinelength is length from widget line start offset until real
		// document line end. If widgetLinelength is still greater than
		// fixedConsoleWidth there are more wrapped content after this widget line
		// therefore this widget line length must equal fixedConsoleWidth otherwise it
		// is the length of requested widget line.
		widgetLineLength = Math.min(widgetLineLength, fixedConsoleWidth);
		return new Region(widgetLineOffset, widgetLineLength);
	}

	@Override
	public int getLineAtOffset(int offset) {
		try {
			return getLineOfOffset(offset);
		} catch (BadLocationException e) {
			log(e);
			// Note: this strange return value is inherited from the previous implementation
			// of this method which did no boundary checks on the offset and either returned
			// the first or last line index for bad locations.
			return offset < 0 ? 0 : widgetLines - 1;
		}
	}

	/**
	 * Return the widget line index at the given character offset.
	 * <p>
	 * Like {@link #getLineAtOffset(int)} but throws exception in case of invalid
	 * offset.
	 * </p>
	 *
	 * @param offset offset in document
	 * @return the number of the widget line at offset (0 for first line)
	 * @throws BadLocationException if the offset is invalid in adapted document
	 * @see #getLineAtOffset(int)
	 * @see IDocument#getLineOfOffset(int)
	 */
	private int getLineOfOffset(int offset) throws BadLocationException {
		if (!isFixedWidth()) {
			return document.getLineOfOffset(offset);
		} else {
			if (offset < 0 || offset > getCharCount()) {
				throw new BadLocationException(offset + " is not a valid offset."); //$NON-NLS-1$
			}
			int widgetLine = Arrays.binarySearch(widgetLineOffsets, 0, widgetLines, offset);
			if (widgetLine < 0) {
				// no exact offset match. At this point (-widgetLine) - 1 can be used as
				// insertion point to insert the searched offset in the array. Since we do not
				// want to insert but request the line containing the offset the desired answer
				// is the index before the insertion index.
				widgetLine = (-widgetLine) - 2;
			}
			if (offset == preemptLineWrapChange) {
				// The requested offset is at fixed width border. In some text change situations
				// we must return the line index it will have after the change even if the
				// change is not applied yet. See #preemptLineWrapChange Javadoc for more
				// details.
				widgetLine--;
			}
			return widgetLine;
		}
	}

	@Override
	public int getLineCount() {
		return widgetLines;
	}

	@Override
	public String getLineDelimiter() {
		return System.lineSeparator();
	}

	@Override
	public int getOffsetAtLine(int lineIndex) {
		try {
			return getLineOffset(lineIndex);
		} catch (BadLocationException e) {
			log(e);
			return -1;
		}
	}

	/**
	 * Return the character offset of the first character of the given line.
	 * <p>
	 * Like {@link #getOffsetAtLine(int)} but throws exception in case of invalid
	 * line numbers.
	 * </p>
	 *
	 * @param widgetLineIndex the widget line number (first line has number 0)
	 * @return offset of the first character of the line
	 * @throws BadLocationException if widget line does not exist
	 * @see #getOffsetAtLine(int)
	 * @see IDocument#getLineOffset(int)
	 */
	private int getLineOffset(int widgetLineIndex) throws BadLocationException {
		if (!isFixedWidth()) {
			return document.getLineOffset(widgetLineIndex);
		} else {
			if (widgetLineIndex < 0 || widgetLineIndex >= widgetLines) {
				throw new BadLocationException(widgetLineIndex + " is not a valid line index."); //$NON-NLS-1$
			}
			return widgetLineOffsets[widgetLineIndex];
		}
	}

	@Override
	public String getTextRange(int start, int length) {
		try {
			return document.get(start, length);
		} catch (BadLocationException e) {
			log(e);
			return null;
		}
	}

	@Override
	public void replaceTextRange(int start, int replaceLength, String text) {
		try {
			document.replace(start, replaceLength, text);
		} catch (BadLocationException e) {
			log(e);
		}
	}

	@Override
	public synchronized void setText(String text) {
		document.set(text == null ? "" : text); //$NON-NLS-1$
		TextChangedEvent changeEvent = new TextChangedEvent(this);
		for (TextChangeListener listener : textChangeListeners) {
			listener.textSet(changeEvent);
		}
	}

	@Override
	public synchronized void documentAboutToBeChanged(DocumentEvent event) {
		TextChangingEvent changingEvent;
		if (!isFixedWidth()) {
			changingEvent = new TextChangingEvent(this);
			changingEvent.start = event.getOffset();
			changingEvent.newText = event.getText() == null ? "" : event.getText(); //$NON-NLS-1$
			changingEvent.replaceCharCount = event.getLength();
			changingEvent.newCharCount = changingEvent.newText.length();
			try {
				changingEvent.replaceLineCount = document.getNumberOfLines(event.getOffset(), event.getLength()) - 1;
			} catch (BadLocationException e) {
				log(e);
			}
			changingEvent.newLineCount = document.computeNumberOfLines(changingEvent.newText);
		} else {
			try {
				changingEvent = generateTextChangingEvent(event);
			} catch (BadLocationException e) {
				log(e);
				// Should never happen.
				// But provide empty changing event to hopefully reduce damage.
				changingEvent = new TextChangingEvent(this);
			}
		}

		for (TextChangeListener listener : textChangeListeners) {
			listener.textChanging(changingEvent);
		}

		if (ASSERT) {
			updatePrediction(changingEvent);
		}
	}

	/**
	 * Generate the {@link TextChangingEvent} for <b>fixed width mode</b>. Due to
	 * the dynamic wrapping of lines and the lack of line delimiters it is much more
	 * complicated than without fixed width.
	 *
	 * @param event the document change event
	 * @return the text changing event for the widget
	 * @throws BadLocationException if document event is invalid
	 */
	private TextChangingEvent generateTextChangingEvent(DocumentEvent event) throws BadLocationException {
		final String newText = event.getText() == null ? "" : event.getText(); //$NON-NLS-1$
		final int newTextLength = newText.length();
		final int eventOffset = event.getOffset();
		final int eventLength = event.getLength();
		int replaceLineCount = 0;
		int newLineCount = 0;

		// The primary duty of this method is to calculate new and removed line which
		// includes the changing in line wrapping.
		// The number of new and replaced lines must include any line whose line content
		// is changing. Normally this only includes lines directly affected by the
		// change event. But due to our magic line wrapping, as an extreme case, a
		// single character inserted at first offset can, from StyledText-Widgets
		// perspective, change the content of every line.

		if (newTextLength > 0 || eventLength > 0) {
			// In this method first and last refer to the first and last line affected by
			// the current document event
			final int eventEnd = eventOffset + eventLength;
			final int firstWidgetLineIndex = getLineOfOffset(eventOffset);
			final int firstWidgetLineOffset = getLineOffset(firstWidgetLineIndex);

			final int firstInsertLength;
			final int lastInsertLength;
			int lastDocLineLengthDiff = -eventLength;

			int newTextOffset = 0;
			Match newLineMatch = docLegalLineDelimiterMatcher.indexOf(newText, newTextOffset);
			if (newLineMatch == null) {
				// single line insert
				firstInsertLength = newTextLength;
				lastInsertLength = eventOffset - firstWidgetLineOffset + newTextLength;
				lastDocLineLengthDiff += newTextLength;
			} else {
				// multiline insert
				// processed in three parts:
				// 1. First line: everything from start of inserted text to (including) first
				// line delimiter
				// 2. Middle lines: everything from first line delimiter (exclusive) to last
				// line delimiter (inclusive) (may contain additional delimiters)
				// 3. Last line: everything (including) last line delimiter to end of inserted
				// text

				firstInsertLength = newLineMatch.getOffset();
				// newLineCount here is numbers of lines required if text is wrapped -1 because
				// we start inserting in an existing line and +1 for the first line delimiter we
				// had found
				newLineCount = linesIfWrapped(eventOffset - firstWidgetLineOffset + firstInsertLength);

				while (true) {
					newTextOffset = newLineMatch.getOffset() + newLineMatch.getText().length();
					newLineMatch = docLegalLineDelimiterMatcher.indexOf(newText, newTextOffset);
					if (newLineMatch == null) {
						break;
					}
					final int insertedLineLength = newLineMatch.getOffset() - newTextOffset;
					// new text's middle lines are unaffected from existing content and simply count
					// as number of lines they need with wrapping
					newLineCount += linesIfWrapped(insertedLineLength);
				}

				final int lastTextPartLength = newTextLength - newTextOffset;
				lastInsertLength = lastTextPartLength;
				lastDocLineLengthDiff += lastTextPartLength;
				lastDocLineLengthDiff -= eventOffset - firstWidgetLineOffset;
			}

			final int lastDocLineIndex = document.getLineOfOffset(eventEnd);
			final IRegion lastDocLine = document.getLineInformation(lastDocLineIndex);

			int affectedContentAfterRange = 0;
			if (lastDocLineLengthDiff != 0) {
				// the content after actual event range moved due to wrapping and must be
				// reported as replaced lines to StyledTextRenderer to update lines rendering
				affectedContentAfterRange = lastDocLine.getOffset() + lastDocLine.getLength() - eventEnd;
			}

			// newLineCount here is numbers of lines required if text is wrapped -1 because
			// we are prepending an existing line
			// (and no real line delimiter left to consider)
			newLineCount += linesIfWrapped(lastInsertLength + affectedContentAfterRange) - 1;

			// replaceLineCount is basically the difference between the index of the last
			// affected line (line at event offset + replace length) and the index of the
			// first affected line (line at event offset)
			// There is one special case caused by the wrapping without delimiter approach.
			// If the replace (a real replace event at this point, removing as many
			// characters as inserting) is ending at a virtual wrap border the
			// lastAffectedOffset would indicate the next line after wrap is affected even
			// if this line isn't really affected.
			final int lastAffectedOffset = eventEnd + affectedContentAfterRange;
			int lastAffectedWidgetLineIndex = getLineOfOffset(lastAffectedOffset);
			final int lastAffectedWidgetLineOffset = getLineOffset(lastAffectedWidgetLineIndex);
			if (lastAffectedWidgetLineOffset == lastAffectedOffset && lastDocLine.getOffset() != lastAffectedOffset) {
				lastAffectedWidgetLineIndex--;
			}
			replaceLineCount = lastAffectedWidgetLineIndex - firstWidgetLineIndex;

			if (firstInsertLength == 0 && eventLength > 0 && affectedContentAfterRange == 0) {
				final int firstDocLineOffset = document.getLineInformationOfOffset(eventOffset).getOffset();
				if (eventOffset != firstDocLineOffset && (eventOffset - firstDocLineOffset) % fixedConsoleWidth == 0) {
					// Text change produce a tricky wrapped line change. Change start at fixed width
					// border and is at start of wrapped line because there is wrapped content after
					// event start. After change there is no more wrapped content after so the same
					// event start offset is now one widget line above.
					replaceLineCount++;
					preemptLineWrapChange = eventOffset;
				}
			}
		}

		final TextChangingEvent changingEvent = new TextChangingEvent(this);
		changingEvent.start = eventOffset;
		changingEvent.newText = newText;
		changingEvent.replaceCharCount = eventLength;
		changingEvent.newCharCount = newTextLength;
		changingEvent.replaceLineCount = replaceLineCount;
		changingEvent.newLineCount = newLineCount;
		return changingEvent;
	}

	/**
	 * For the given text length calculate number of wrapped lines this text
	 * requires with current {@link #fixedConsoleWidth} setting.
	 * <p>
	 * A line ending at the fixed length border will not result in an extra line,
	 * i.e. a line with length of <i>consoleWidth</i> results in one line.
	 * </p>
	 * <p>
	 * Line delimiters are ignored and count like any other character. Since line
	 * delimiters should not cause line wraps this method is intended to be called
	 * with line length excluding line delimiter.
	 * </p>
	 *
	 * @param lineLength line length to calculate
	 * @return number of lines if given length is wrapped with current
	 *         {@link #fixedConsoleWidth} (always &gt;= 1)
	 */
	private int linesIfWrapped(int lineLength) {
		if (fixedConsoleWidth <= 0 || lineLength <= 0) {
			return 1;
		}
		return ((lineLength - 1) / fixedConsoleWidth) + 1;
	}

	@Override
	public synchronized void documentChanged(DocumentEvent event) {
		preemptLineWrapChange = -1;
		updateWidgetOffsets(event.getOffset());

		TextChangedEvent changeEvent = new TextChangedEvent(this);
		for (TextChangeListener listener : textChangeListeners) {
			listener.textChanged(changeEvent);
		}

		if (ASSERT) {
			verifyPrediction();
		}
	}

	/**
	 * Update list of widget line offsets.
	 * <p>
	 * <b>Note:</b> the widget line offset lookup is only used for fixed width
	 * console and therefore only updated if fixed width is enabled.
	 * </p>
	 *
	 * @param fromOffset all offsets before given offset are considered valid. Only
	 *                   update widget offsets from this offset onwards.
	 * @see #widgetLines
	 * @see #widgetLineOffsets
	 */
	private void updateWidgetOffsets(int fromOffset) {
		if (document == null) {
			widgetLines = 0;
			return;
		}

		final int docLines = document.getNumberOfLines();
		if (!isFixedWidth()) {
			widgetLines = docLines;
		} else {
			try {
				final int offset = Math.max(fromOffset, 0);
				// if someone manages to set the documents text to null the document may return
				// a negative line number
				int docLineIndex = Math.max(document.getLineOfOffset(offset), 0);
				final int docLineOffset = document.getLineOffset(docLineIndex);
				int widgetLineIndex;
				if (docLineOffset > 0) {
					widgetLineIndex = getLineOfOffset(docLineOffset);
				} else {
					widgetLineIndex = 0;
					setLookupEntry(widgetLineIndex, 0);
				}

				for (; docLineIndex < docLines; docLineIndex++) {
					int lineLength = document.getLineInformation(docLineIndex).getLength();
					for (; lineLength > fixedConsoleWidth; lineLength -= fixedConsoleWidth) {
						widgetLineIndex++;
						setLookupEntry(widgetLineIndex, widgetLineOffsets[widgetLineIndex - 1] + fixedConsoleWidth);
					}

					final String docLineDelimiter = document.getLineDelimiter(docLineIndex);
					if (docLineDelimiter != null) {
						widgetLineIndex++;
						setLookupEntry(widgetLineIndex,
								widgetLineOffsets[widgetLineIndex - 1] + lineLength + docLineDelimiter.length());
					}
				}
				widgetLines = widgetLineIndex + 1;
			} catch (BadLocationException e) {
				// should be impossible if document is not changed meanwhile
				log(e);
			}
		}
	}

	/**
	 * Set an entry in the {@link #widgetLineOffsets} lookup. Will grow the lookup
	 * array if necessary.
	 *
	 * @param widgetLineIndex the lookup entry to set (does not have to exist yet)
	 * @param value           the entry value to set
	 */
	private void setLookupEntry(int widgetLineIndex, int value) {
		ensureOffsetsCapacity(widgetLineIndex + 1);
		widgetLineOffsets[widgetLineIndex] = value;
	}

	/**
	 * Ensure the offset lookup array can store at least <i>size</i> entries.
	 *
	 * @param requiredSize minimum size lookup array should have after
	 * @see #widgetLineOffsets
	 */
	private void ensureOffsetsCapacity(int requiredSize) {
		final int oldSize = widgetLineOffsets != null ? widgetLineOffsets.length : 0;
		if (oldSize < requiredSize) {
			final int[] oldWidgetOffsets = widgetLineOffsets;
			widgetLineOffsets = new int[requiredSize + GROW];
			if (oldSize > 0) {
				System.arraycopy(oldWidgetOffsets, 0, widgetLineOffsets, 0, oldSize);
			}
		}
	}

	/**
	 * Check if fixed width console feature is enabled or not.
	 *
	 * @return true if lines are wrapped at fixed width
	 * @see #getWidth()
	 */
	public boolean isFixedWidth() {
		return fixedConsoleWidth > 0;
	}

	/**
	 * Get current consoles fixed width.
	 *
	 * @return current fixed console width or &lt;= 0 if disabled
	 * @see #isFixedWidth()
	 */
	public int getWidth() {
		return fixedConsoleWidth;
	}

	/**
	 * Set new fixed console width. Also signals text viewer widget to render
	 * content with new fixed width.
	 *
	 * @param width the fixed console width or &lt;= 0 to not break lines at fixed
	 *              width
	 */
	public void setWidth(int width) {
		if (width != fixedConsoleWidth) {
			fixedConsoleWidth = width;
			updateWidgetOffsets(0);
			TextChangedEvent changeEvent = new TextChangedEvent(this);
			for (TextChangeListener listener : textChangeListeners) {
				listener.textSet(changeEvent);
			}
		}
	}

	/**
	 * Log an exception and include if error occurred in fixed or non fixed width
	 * mode.
	 *
	 * @param error the error to log
	 */
	private void log(Throwable error) {
		ConsolePlugin.log(ConsolePlugin.newErrorStatus("fixed width: " + isFixedWidth(), error)); //$NON-NLS-1$
	}

	// +---------------------+
	// | Debug and test code |
	// +---------------------+
	/**
	 * The expected document length after next document change is applied. Only used
	 * if {@link #ASSERT} is <code>true</code>.
	 */
	private int predictedCharCount;
	/**
	 * The expected number of lines after next document change is applied. Only used
	 * if {@link #ASSERT} is <code>true</code>.
	 */
	private int predictedLines;

	/**
	 * Set the expected document length and lines from the current document state
	 * and the changes predicted by the changing event.
	 *
	 * @param event the {@link TextChangingEvent} describing the next document
	 *              change
	 */
	private void updatePrediction(TextChangingEvent event) {
		predictedCharCount = getCharCount() + event.newCharCount - event.replaceCharCount;
		predictedLines = getLineCount() + event.newLineCount - event.replaceLineCount;
	}

	/**
	 * Check if the last change prediction was correct. Throws an
	 * AssertionFailedException if the prediction was wrong.
	 */
	private void verifyPrediction() {
		final int charCount = getCharCount();
		Assert.isTrue(predictedCharCount == charCount, String.format(java.util.Locale.ROOT,
				"Wrong char count. Expected<%d>, Actual<%d>", predictedCharCount, charCount)); //$NON-NLS-1$
		final int lineCount = getLineCount();
		Assert.isTrue(predictedLines == lineCount, String.format(java.util.Locale.ROOT,
				"Wrong line count. Expected<%d>, Actual<%d>", predictedLines, lineCount)); //$NON-NLS-1$
	}
}
