package org.eclipse.jface.text;

/*
 * (c) Copyright IBM Corp. 2000, 2001.
 * All Rights Reserved.
 */


import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.LineBackgroundEvent;
import org.eclipse.swt.custom.LineBackgroundListener;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.custom.ST;
import org.eclipse.swt.custom.VerifyKeyListener;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
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.MouseMoveListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.events.TraverseEvent;
import org.eclipse.swt.events.TraverseListener;
import org.eclipse.swt.events.VerifyEvent;
import org.eclipse.swt.events.VerifyListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.printing.PrintDialog;
import org.eclipse.swt.printing.Printer;
import org.eclipse.swt.printing.PrinterData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.ScrollBar;

import org.eclipse.jface.util.Assert;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.Viewer;



/**
 * SWT based implementation of <code>ITextViewer</code>. Once the viewer and its SWT control
 * have been created the viewer can only indirectly be disposed by disposing its SWT control.<p>
 * Clients are supposed to instantiate a text viewer and subsequently to communicate with it 
 * exclusively using the <code>ITextViewer</code> interface. Clients should no subclass this
 * class as it is rather likely that subclasses will be broken by future releases.
 * 
 * @see ITextViewer
 */  
public class TextViewer extends Viewer implements ITextViewer, ITextViewerExtension, ITextOperationTarget, IWidgetTokenOwner {
	
	
	public static boolean TRACE_ERRORS= false;
	
	/**
	 * Represent a replace command that brings the text viewer's text widget
	 * back in sync with text viewer's document after the document has been changed.
	 */
	protected class WidgetCommand {
		
		public DocumentEvent event;
		public int start, length;
		public String text, preservedText;
				
		/**
		 * Translates a document event into the presentation coordinates of this text viewer.
		 *
		 * @param e the event to be translated
		 */
		public void setEvent(DocumentEvent e) {
			
			event= e;
			
			start= e.getOffset();
			length= e.getLength();
			text= e.getText();
			
			if (length != 0) {
				try {
					preservedText= e.getDocument().get(e.getOffset(), e.getLength());
				} catch (BadLocationException x) {
					preservedText= null;
					if (TRACE_ERRORS)
						System.out.println(JFaceTextMessages.getString("TextViewer.error.bad_location.WidgetCommand.setEvent")); //$NON-NLS-1$
				}
			} else
				preservedText= null;
		}
	};
		
	/**
	 * Connects a text double click strategy to this viewer's text widget. 
	 * Calls the double click strategy when the mouse has been double clicked 
	 * inside the text editor.
	 */	
	class TextDoubleClickStrategyConnector extends MouseAdapter {
		
		private boolean fDoubleClicked= false;
		
		public TextDoubleClickStrategyConnector() {
		}
				
		public void mouseDoubleClick(MouseEvent e) {
			fDoubleClicked= true;
		}
			
		public void mouseUp(MouseEvent e) {
			if (fDoubleClicked) {
				fDoubleClicked= false;
				ITextDoubleClickStrategy s= (ITextDoubleClickStrategy) selectContentTypePlugin(getSelectedRange().x, fDoubleClickStrategies);
				if (s != null)
					s.doubleClicked(TextViewer.this);
			}
		}
	};
	
	/**
	 * Monitors the area of the viewer's document that is visible in the viewer. 
	 * If the area might have been changed, it informs the text viewer about this
	 * potential change and its origin. The origin is internally used for optimization purposes.
	 */
	class ViewportGuard extends MouseAdapter 
		implements ControlListener, KeyListener, MouseMoveListener, SelectionListener {
		
		/*
		 * @see ControlListener#controlResized(ControlEvent)
		 */
		public void controlResized(ControlEvent e) {
			updateViewportListeners(RESIZE);
		}
		
		/*
		 * @see ControlListener#controlMoved(ControlEvent)
		 */
		public void controlMoved(ControlEvent e) {
		}
		
		/*
		 * @see KeyListener#keyReleased
		 */
		public void keyReleased(KeyEvent e) {
			updateViewportListeners(KEY);
		}

		/*
		 * @see KeyListener#keyPressed
		 */
		public void keyPressed(KeyEvent e) {
			updateViewportListeners(KEY);
		}

		/*
		 * @see MouseListener#mouseUp
		 */
		public void mouseUp(MouseEvent e) {
			if (fTextWidget != null)
				fTextWidget.removeMouseMoveListener(this);
			updateViewportListeners(MOUSE_END);
		}

		/*
		 * @see MouseListener#mouseDown
		 */
		public void mouseDown(MouseEvent e) {
			if (fTextWidget != null)
				fTextWidget.addMouseMoveListener(this);
		}

		/*
		 * @see MouseMoveListener#mouseMove
		 */
		public void mouseMove(MouseEvent e) {
			updateViewportListeners(MOUSE);
		}

		/*
		 * @see SelectionListener#widgetSelected
		 */
		public void widgetSelected(SelectionEvent e) {
			updateViewportListeners(SCROLLER);
		}

		/*
		 * @see SelectionListener#widgetDefaultSelected
		 */
		public void widgetDefaultSelected(SelectionEvent e) {}
	};
		
	/**
	 * This position updater is used to keep the selection during text shift operations.
	 */
	static class ShiftPositionUpdater extends DefaultPositionUpdater {
		
		/**
		 * Creates the position updater for the given category.
		 *
		 * @param category the category this updater takes care of
		 */
		protected ShiftPositionUpdater(String category) {
			super(category);
		}
		
		/*
		 * If an insertion happens at the selection's start offset,
		 * the position is extended rather than shifted.
		 *
		 * @see DefaultPositionUpdater#adaptToInsert
		 */
		protected void adaptToInsert() {
			
			int myStart= fPosition.offset;
			int myEnd=   fPosition.offset + fPosition.length -1;
			myEnd= Math.max(myStart, myEnd);
			
			int yoursStart= fOffset;
			int yoursEnd=   fOffset + fReplaceLength -1;
			yoursEnd= Math.max(yoursStart, yoursEnd);
			
			if (myEnd < yoursStart)
				return;
			
			if (myStart <= yoursStart) {
				fPosition.length += fReplaceLength;
				return;
			}
			
			if (myStart > yoursStart)
				fPosition.offset += fReplaceLength;		
		}
	};
	
	/**
	 * Internal document listener and hover reset timer.
	 */
	class DocumentListener implements IDocumentListener, Runnable {
		
		private Object fSyncPoint= new Object();
		private Thread fThread;
		private boolean fIsReset= false;
		
		/*
		 * @see IDocumentListener#documentAboutToBeChanged
		 */
		public void documentAboutToBeChanged(DocumentEvent e) {
			if (e.getDocument() == getVisibleDocument()) {
				fWidgetCommand.setEvent(e);
				if (fTextHoverManager != null && (fThread == null || !fThread.isAlive())) {
					fThread= new Thread(this, JFaceTextMessages.getString("TextViewer.timer.name")); //$NON-NLS-1$
					fThread.start();
				}
			}
		}
		
		/*
		 * @see IDocumentListener#documentChanged
		 */
		public void documentChanged(final DocumentEvent e) {
			if (fWidgetCommand.event == e) {
				
				updateTextListeners(fWidgetCommand);
				
				if (fTextHoverManager != null) {
					synchronized (fSyncPoint) {
						fIsReset= true;
					}
					fTextHoverManager.setEnabled(false);
				}
			}
		}
		
		/*
		 * @see IRunnable#run
		 */
		public void run() {
			try {
				while (true) {
					
					synchronized (fSyncPoint) {
						fSyncPoint.wait(1500);
						if (fIsReset) {
							fIsReset= false;
							continue;
						}
					}
					
					break;
				}
			} catch (InterruptedException e) {
			}
			
			fThread= null;
			
			if (fTextHoverManager != null) {
				Control c= getControl();
				if (c != null && !c.isDisposed()) {
					Display d= c.getDisplay();
					if (d != null) {
						d.asyncExec(new Runnable() {
							public void run() {
								if (fTextHoverManager != null)
									fTextHoverManager.setEnabled(true);
							}
						});
					}
				}
			}
		}
		
		/**
		 * Stops the running hover timer thread.
		 */
		public void stop() {
			if (fThread != null) {
				if (fThread.isAlive())
					fThread.interrupt();
				fThread= null;
			}
		}
	};
	
	/**
	 * Internal verify listener.
	 */
	class TextVerifyListener implements VerifyListener {
		
		private boolean fForward= true;
		
		/**
		 * Tells the listener to forward received events.
		 */
		public void forward(boolean forward) {
			fForward= forward;
		}
		
		/*
		 * @see VerifyListener#verifyText(VerifyEvent)
		 */
		public void verifyText(VerifyEvent e) {
			if (fForward)
				handleVerifyEvent(e);
		}	
	};
	
	/**
	 * The viewer's manager of registered verify key listeners.
	 * Uses batches rather than robust iterators because of
	 * performance issues.
	 */
	class VerifyKeyListenersManager implements VerifyKeyListener {
		
		class Batch {
			int index;
			VerifyKeyListener listener;
			
			public Batch(VerifyKeyListener l, int i) {
				listener= l;
				index= i;
			}
		};
		
		private List fListeners= new ArrayList();
		private List fBatched= new ArrayList();
		private Iterator fIterator;
		
		/*
		 * @see VerifyKeyListener#verifyKey(VerifyEvent)
		 */
		public void verifyKey(VerifyEvent event) {
			if (fListeners.isEmpty())
				return;
				
			fIterator= fListeners.iterator();
			while (fIterator.hasNext() && event.doit) {
				VerifyKeyListener listener= (VerifyKeyListener) fIterator.next();
				listener.verifyKey(event);
			}
			fIterator= null;
			
			processBatchedRequests();
		}
		
		private void processBatchedRequests() {
			if (!fBatched.isEmpty()) {
				Iterator e= fBatched.iterator();
				while (e.hasNext()) {
					Batch batch= (Batch) e.next();
					insertListener(batch.listener, batch.index);
				}
				fBatched.clear();
			}
		}
		
		/**
		 * Returns the number of registered verify key listeners.
		 */
		public int numberOfListeners() {
			return fListeners.size();
		}
		
		/**
		 * Inserts the given listener at the given index or moves it
		 * to that index.
		 * 
		 * @param listener the listener to be inserted
		 * @param index the index of the listener or -1 for remove
		 */
		public void insertListener(VerifyKeyListener listener, int index) {
			
			if (index == -1) {
				removeListener(listener);
			} else if (listener != null) {
				
				if (fIterator != null) {
					
					fBatched.add(new Batch(listener, index));
				
				} else {
					
					int idx= -1;
					
					// find index based on identity
					int size= fListeners.size();
					for (int i= 0; i < size; i++) {
						if (listener == fListeners.get(i)) {
							idx= i;
							break;
						}
					}
					
					// move or add it
					if (idx != index) {
						
						if (idx != -1)
							fListeners.remove(idx);
							
						if (index > fListeners.size())
							fListeners.add(listener);
						else
							fListeners.add(index, listener);
					}
					
					if (size == 0)  // checking old size, i.e. current size == size + 1
						install();
				}
			}
		}
		
		/**
		 * Removes the given listener.
		 * 
		 * @param listener the listener to be removed
		 */
		public void removeListener(VerifyKeyListener listener) {
			if (listener == null)
				return;
			
			if (fIterator != null) {
				
				fBatched.add(new Batch(listener, -1));
			
			} else {
				
				int size= fListeners.size();
				for (int i= 0; i < size; i++) {
					if (listener == fListeners.get(i)) {
						fListeners.remove(i);
						if (size == 1)  // checking old size, i.e. current size == size - 1
							uninstall();
						return;
					}
				}
			}
		}
		
		/**
		 * Installs this manager.
		 */
		private void install() {
			getTextWidget().addVerifyKeyListener(this);
		}
		
		/**
		 * Uninstalls this manager.
		 */
		private void uninstall() {
			getTextWidget().removeVerifyKeyListener(this);
		}
	};
	
	/**
	 * MISSING
	 */
	private class FindReplaceRange implements LineBackgroundListener, ITextListener, IPositionUpdater {		

		private final static String RANGE_CATEGORY= "org.eclipse.jface.text.TextViewer.find.range"; //$NON-NLS-1$

		private Color fHighlightColor;
		private IRegion fRange;
		private Position fPosition;
		
		public FindReplaceRange(IRegion range) {
			setRange(range);
		}
		
		public void setRange(IRegion range) {
			fPosition= new Position(range.getOffset(), range.getLength());
		}
		
		public IRegion getRange() {
			return new Region(fPosition.getOffset(), fPosition.getLength());
		}
		
		public void setHighlightColor(Color color) {
			fHighlightColor= color;
			paint();
		}

		/*
		 * @see LineBackgroundListener#lineGetBackground(LineBackgroundEvent)
		 */
		public void lineGetBackground(LineBackgroundEvent event) {
			/* Don't use cached line information because of patched redrawing events. */
			
			if (fTextWidget != null) {
				int offset= event.lineOffset + TextViewer.this.getVisibleRegionOffset();
				
				if (fPosition.includes(offset))
					event.lineBackground= fHighlightColor;
			}
		}
		
		public void install() {
			TextViewer.this.addTextListener(this);						
			fTextWidget.addLineBackgroundListener(this);

			IDocument document= TextViewer.this.getDocument();
			try {
				document.addPositionCategory(RANGE_CATEGORY);
				document.addPosition(RANGE_CATEGORY, fPosition);
				document.addPositionUpdater(this);
			} catch (BadPositionCategoryException e) {
				// should not happen
			} catch (BadLocationException e) {
				// should not happen
			}

			paint();
		}
		
		public void uninstall() {
			IDocument document= TextViewer.this.getDocument();
			document.removePositionUpdater(this);
			document.removePosition(fPosition);

			fTextWidget.removeLineBackgroundListener(this);
			TextViewer.this.removeTextListener(this);						

			clear();
		}
		
		private void clear() {
			fTextWidget.redraw();
		}
		
		private void paint() {
			int offset= fPosition.getOffset() - TextViewer.this.getVisibleRegionOffset();
			int length= fPosition.getLength();

			int count= fTextWidget.getCharCount();
			if (offset + length >= count) {
				length= count - offset; // clip

				Point upperLeft= fTextWidget.getLocationAtOffset(offset);
				Point lowerRight= fTextWidget.getLocationAtOffset(offset + length);
				int width= fTextWidget.getClientArea().width;
				int height= fTextWidget.getLineHeight() + lowerRight.y - upperLeft.y;
				fTextWidget.redraw(upperLeft.x, upperLeft.y, width, height, false);
			}			
			
			fTextWidget.redrawRange(offset, length, true);
		}

		/*
		 * @see ITextListener#textChanged(TextEvent)
		 */
		public void textChanged(TextEvent event) {
			paint();
		}

		/*
		 * @see IPositionUpdater#update(DocumentEvent)
		 */
		public void update(DocumentEvent event) {
			int offset= event.getOffset();
			int length= event.getLength();
			int delta= event.getText().length() - length;

			if (offset < fPosition.getOffset())
				fPosition.setOffset(fPosition.getOffset() + delta);
			else if (offset < fPosition.getOffset() + fPosition.getLength())
				fPosition.setLength(fPosition.getLength() + delta);
		}

	}
	
	/**
	 * This viewer's find/replace target.
	 */
	class FindReplaceTarget implements IFindReplaceTarget, IFindReplaceTargetExtension {

		private FindReplaceRange fRange;
		private Color fScopeHighlightColor;
		
		/*
		 * @see IFindReplaceTarget#getSelectionText()
		 */
		public String getSelectionText() {
			if (fTextWidget != null)
				return fTextWidget.getSelectionText();
			return null;
		}
		
		/*
		 * @see IFindReplaceTarget#replaceSelection(String)
		 */
		public void replaceSelection(String text) {
			if (fTextWidget != null) {
				Point s= fTextWidget.getSelectionRange();
				fTextWidget.replaceTextRange(s.x, s.y, text);
				if (text != null && text.length() > 0)
					fTextWidget.setSelectionRange(s.x, text.length());
			}
		}
		
		/*
		 * @see IFindReplaceTarget#isEditable()
		 */
		public boolean isEditable() {
			return TextViewer.this.isEditable();
		}
				
		/*
		 * @see IFindReplaceTarget#getSelection()
		 */
		public Point getSelection() {
			Point point= TextViewer.this.getSelectedRange();
			point.x -= TextViewer.this.getVisibleRegionOffset();
			return point;
		}
		
		/*
		 * @see IFindReplaceTarget#findAndSelect(int, String, boolean, boolean, boolean)
		 */
		public int findAndSelect(int offset, String findString, boolean searchForward, boolean caseSensitive, boolean wholeWord) {
			if (offset != -1)
				offset += TextViewer.this.getVisibleRegionOffset();

			if (fRange != null) {
				IRegion range= fRange.getRange();
				offset= TextViewer.this.findAndSelectInRange(offset, findString, searchForward, caseSensitive, wholeWord, range.getOffset(), range.getLength());
			} else {
				offset= TextViewer.this.findAndSelect(offset, findString, searchForward, caseSensitive, wholeWord);
			}

			if (offset != -1)
				offset -= TextViewer.this.getVisibleRegionOffset();

			return offset;
		}
		
		/*
		 * @see IFindReplaceTarget#canPerformFind()
		 */
		public boolean canPerformFind() {
			return TextViewer.this.canPerformFind();
		}	

		/*
		 * @see IFindReplaceTargetExtension#beginSession()
		 */
		public void beginSession() {
			fRange= null;
		}

		/*
		 * @see IFindReplaceTargetExtension#endSession()
		 */
		public void endSession() {
			if (fRange != null) {
				fRange.uninstall();
				fRange= null;
			}
		}

		/*
		 * @see IFindReplaceTargetExtension#getScope()
		 */
		public IRegion getScope() {			
			return fRange == null ? null : fRange.getRange();
		}

		/*
		 * @see IFindReplaceTargetExtension#getLineSelection()
		 */
		public Point getLineSelection() {
			Point point= TextViewer.this.getSelectedRange();

			try {
				IDocument document= TextViewer.this.getDocument();

				// beginning of line
				int line= document.getLineOfOffset(point.x);
				int offset= document.getLineOffset(line);

				// end of line
				line= document.getLineOfOffset(point.x + point.y);
				int length= document.getLineOffset(line) + document.getLineLength(line)	- offset;

				return new Point(offset, length);

			} catch (BadLocationException e) {
				// should not happen			
				return null;
			}
		}

		/*
		 * @see IFindReplaceTargetExtension#setSelection(int, int)
		 */
		public void setSelection(int offset, int length) {
			TextViewer.this.setSelectedRange(offset /*+ TextViewer.this.getVisibleRegionOffset()*/, length);
		}

		/*
		 * @see IFindReplaceTargetExtension#setScope(IRegion)
		 */
		public void setScope(IRegion scope) {
			if (fRange != null)
				fRange.uninstall();

			if (scope == null) {
				fRange= null;
				return;
			}
			
			fRange= new FindReplaceRange(scope);
			fRange.setHighlightColor(fScopeHighlightColor);
			fRange.install();			
		}

		/*
		 * @see IFindReplaceTargetExtension#setScopeHighlightColor(Color)
		 */
		public void setScopeHighlightColor(Color color) {
			if (fRange != null)
				fRange.setHighlightColor(color);
			fScopeHighlightColor= color;
		}

	}
	
		
	/** ID for originators of view port changes */
	protected static final int SCROLLER=	1;
	protected static final int MOUSE=		2;
	protected static final int MOUSE_END=	3;
	protected static final int KEY=		4;
	protected static final int RESIZE=		5;
	protected static final int INTERNAL=	6;
		
	/** Internal name of the position category used selection preservation during shift */
	protected static final String SHIFTING= "__TextViewer_shifting"; //$NON-NLS-1$

	/** The viewer's text widget */
	private StyledText fTextWidget;
	/** The viewer's input document */
	private IDocument fDocument;
	/** The viewer's visible document */
	private IDocument fVisibleDocument;
	/** The viewer's document adapter */
	private IDocumentAdapter fDocumentAdapter;
	/** The child document manager */
	private ChildDocumentManager fChildDocumentManager;
	/** The text viewer's double click strategies connector */
	private TextDoubleClickStrategyConnector fDoubleClickStrategyConnector;
	/** The text viewer's hovering controller */
	private AbstractHoverInformationControlManager fTextHoverManager;
	/** The text viewer's viewport guard */
	private ViewportGuard fViewportGuard;
	/** Caches the graphical coordinate of the first visible line */ 
	private int fTopInset= 0;
	/** The most recent document modification as widget command */
	private WidgetCommand fWidgetCommand= new WidgetCommand();	
	/** The SWT control's scrollbars */
	private ScrollBar fScroller;
	/** Document listener */
	private DocumentListener fDocumentListener= new DocumentListener();
	/** Verify listener */
	private TextVerifyListener fVerifyListener= new TextVerifyListener();
	/** The most recent widget modification as document command */
	private DocumentCommand fDocumentCommand= new DocumentCommand();
	/** The viewer's find/replace target */
	private IFindReplaceTarget fFindReplaceTarget;
	/** The viewer widget token keeper */
	private Object fWidgetTokenKeeper;
	/** The viewer's manager of verify key listeners */
	private VerifyKeyListenersManager fVerifyKeyListenersManager= new VerifyKeyListenersManager();

	
	/** Should the auto indent strategies ignore the next edit operation */
	protected boolean  fIgnoreAutoIndent= false;
	/** The strings a line is prefixed with on SHIFT_RIGHT and removed from each line on SHIFT_LEFT */
	protected Map fIndentChars;
	/** The string a line is prefixed with on PREFIX and removed from each line on STRIP_PREFIX */
	protected Map fDefaultPrefixChars;
	/** The text viewer's text double click strategies */
	protected Map fDoubleClickStrategies;
	/** The text viewer's undo manager */
	protected IUndoManager fUndoManager;
	/** The text viewer's auto indent strategies */
	protected Map fAutoIndentStrategies;
	/** The text viewer's text hovers */
	protected Map fTextHovers;
	/** The creator of the text hover control */
	protected IInformationControlCreator fHoverControlCreator;
	/** All registered viewport listeners> */
	protected List fViewportListeners;
	/** The last visible vertical position of the top line */
	protected int fLastTopPixel;
	/** All registered text listeners */
	protected List fTextListeners;
	/** All registered text input listeners */
	protected List fTextInputListeners;
	/** The text viewer's event consumer */
	protected IEventConsumer fEventConsumer;
	/** Indicates whether the viewer's text presentation should be replaced are modified. */
	protected boolean fReplaceTextPresentation= false;
	
	
	//---- Construction and disposal ------------------
	
	
	/**
	 * Internal use only
	 */
	protected TextViewer() {
	}
		
	/**
	 * Create a new text viewer with the given SWT style bits.
	 * The viewer is ready to use but does not have any plug-in installed.
	 *
	 * @param parent the parent of the viewer's control
	 * @param styles the SWT style bits for the viewer's control
	 */
	public TextViewer(Composite parent, int styles) {
		createControl(parent, styles);
	}
		
	/**
	 * Factory method to create the text widget to be used as the viewer's text widget.
	 * 
	 * @return the text widget to be used
	 */
	protected StyledText createTextWidget(Composite parent, int styles) {
		return new StyledText(parent, styles);
	}
	
	/**
	 * Factory method to create the document adapter to be used by this viewer.
	 * 
	 * @return the document adapter to be used
	 */
	protected IDocumentAdapter createDocumentAdapter() {
		return new DocumentAdapter();
	}
	
	/**
	 * Creates the viewer's SWT control. The viewer's text widget either is
	 * the control or is a child of the control.
	 *
	 * @param parent the parent of the viewer's control
	 * @param styles the SWT style bits for the viewer's control
	 */
	protected void createControl(Composite parent, int styles) {
					
		fTextWidget= createTextWidget(parent, styles);
		fTextWidget.addDisposeListener(
			new DisposeListener() {
				public void widgetDisposed(DisposeEvent e) {
					setDocument(null);
					handleDispose();
					fTextWidget= null;		
				}
			}
		);
		
		fTextWidget.setFont(parent.getFont());
		fTextWidget.setDoubleClickEnabled(false);
		
		/*
		 * Disable SWT Shift+TAB traversal in this viewer
		 * 1GIYQ9K: ITPUI:WINNT - StyledText swallows Shift+TAB
		 */
		fTextWidget.addTraverseListener(new TraverseListener() {
			public void keyTraversed(TraverseEvent e) {
				if ((SWT.SHIFT == e.stateMask) && ('\t' == e.character))
					e.doit = false;
			}	
		});
		
		// where does the first line start
		fTopInset= -fTextWidget.computeTrim(0, 0, 0, 0).y;
		
		fVerifyListener.forward(true);
		fTextWidget.addVerifyListener(fVerifyListener);
		
		fTextWidget.addSelectionListener(new SelectionListener() {
			public void widgetDefaultSelected(SelectionEvent event) {
				selectionChanged(event.x, event.y - event.x);
			}
			public void widgetSelected(SelectionEvent event) {
				selectionChanged(event.x, event.y - event.x);
			}
		});
		
		initializeViewportUpdate();
	}
		
	/*
	 * @see Viewer#getControl
	 */
	public Control getControl() {
		return fTextWidget;
	}
	
	/*
	 * @see ITextViewer#activatePlugin
	 */
	public void activatePlugins() {
		
		if (fDoubleClickStrategies != null && !fDoubleClickStrategies.isEmpty() && fDoubleClickStrategyConnector == null) {
			fDoubleClickStrategyConnector= new TextDoubleClickStrategyConnector();
			fTextWidget.addMouseListener(fDoubleClickStrategyConnector);
		}
		
		if (fTextHovers != null && !fTextHovers.isEmpty() && fHoverControlCreator != null && fTextHoverManager == null) {			
			fTextHoverManager= new TextViewerHoverManager(this, fHoverControlCreator);
			fTextHoverManager.install(this.getTextWidget());
		}
		
		if (fUndoManager != null) {
			fUndoManager.connect(this);
			fUndoManager.reset();
		}
	}
	
	/*
	 * @see ITextViewer#resetPlugins()
	 */
	public void resetPlugins() {
		if (fUndoManager != null)
			fUndoManager.reset();
	}
	
	/**
	 * Frees all resources allocated by this viewer. Internally called when the viewer's control
	 * has been disposed.
	 */
	protected void handleDispose() {
		
		removeViewPortUpdate();
		fViewportGuard= null;
				
		if (fViewportListeners != null) {
			fViewportListeners.clear();
			fViewportListeners= null;
		}
		
		if (fTextListeners != null) {
			fTextListeners.clear();
			fTextListeners= null;
		}
		
		if (fAutoIndentStrategies != null) {
			fAutoIndentStrategies.clear();
			fAutoIndentStrategies= null;
		}
		
		if (fUndoManager != null) {
			fUndoManager.disconnect();
			fUndoManager= null;
		}
		
		if (fDoubleClickStrategies != null) {
			fDoubleClickStrategies.clear();
			fDoubleClickStrategies= null;
		}
		
		if (fTextHovers != null) {
			fTextHovers.clear();
			fTextHovers= null;
		}
		
		fDoubleClickStrategyConnector= null;
		
		if (fTextHoverManager != null) {
			fTextHoverManager.dispose();
			fTextHoverManager= null;
		}
		
		if (fDocumentListener != null) {
			fDocumentListener.stop();
			fDocumentListener= null;
		}
		
		if (fVisibleDocument instanceof ChildDocument) {
			ChildDocument child = (ChildDocument) fVisibleDocument;
			child.removeDocumentListener(fDocumentListener);
			getChildDocumentManager().freeChildDocument(child);
		}
		
		if (fDocumentAdapter != null) {
			fDocumentAdapter.setDocument(null);
			fDocumentAdapter= null;
		}
		
		fVisibleDocument= null;
		fDocument= null;
		fChildDocumentManager= null;
		fScroller= null;
	}
	
			
	//---- simple getters and setters
			
	/**
	 * Returns viewer's text widget.
	 */
	public StyledText getTextWidget() {
		return fTextWidget;
	}
			
	/*
	 * @see ITextViewer#setAutoIndentStrategy
	 */
	public void setAutoIndentStrategy(IAutoIndentStrategy strategy, String contentType) {
		
		if (strategy != null) {
			if (fAutoIndentStrategies == null)
				fAutoIndentStrategies= new HashMap();
			fAutoIndentStrategies.put(contentType, strategy);
		} else if (fAutoIndentStrategies != null)
			fAutoIndentStrategies.remove(contentType);
	}
	
	/*
	 * @see ITextViewer#setEventConsumer
	 */
	public void setEventConsumer(IEventConsumer consumer) {
		fEventConsumer= consumer;
	}
		
	/*
	 * @see ITextViewer#setIndentPrefixes 
	 */
	public void setIndentPrefixes(String[] indentPrefixes, String contentType) {
					
		int i= -1;
		boolean ok= (indentPrefixes != null);
		while (ok &&  ++i < indentPrefixes.length)
			ok= (indentPrefixes[i] != null);
		
		if (ok) {
			
			if (fIndentChars == null)
				fIndentChars= new HashMap();
			
			fIndentChars.put(contentType, indentPrefixes);
		
		} else if (fIndentChars != null)
			fIndentChars.remove(contentType);
	}
				
	/*
	 * @see ITextViewer#getTopInset
	 */
	public int getTopInset() {
		return fTopInset;
	}
	
	/*
	 * @see ITextViewer#isEditable
	 */
	public boolean isEditable() {
		if (fTextWidget == null)
			return false;
		return fTextWidget.getEditable();
	}
	
	/*
	 * @see ITextViewer#setEditable
	 */
	public void setEditable(boolean editable) {
		if (fTextWidget != null)
			fTextWidget.setEditable(editable);
	}
			
	/*
	 * @see ITextViewer#setDefaultPrefixes
	 */
	public void setDefaultPrefixes(String[] defaultPrefixes, String contentType) {
				
		if (defaultPrefixes != null && defaultPrefixes.length > 0) {
			if (fDefaultPrefixChars == null)
				fDefaultPrefixChars= new HashMap();
			fDefaultPrefixChars.put(contentType, defaultPrefixes);
		} else if (fDefaultPrefixChars != null)
			fDefaultPrefixChars.remove(contentType);
	}
	
	/*
	 * @see ITextViewer#setUndoManager
	 */
	public void setUndoManager(IUndoManager undoManager) {
		fUndoManager= undoManager;
	}
	
	/*
	 * @see ITextViewer#setTextHover
	 */
	public void setTextHover(ITextHover hover, String contentType) {
		
		if (hover != null) {
			if (fTextHovers == null)
				fTextHovers= new HashMap();
			fTextHovers.put(contentType, hover);
		} else if (fTextHovers != null)
			fTextHovers.remove(contentType);
	}
	
	/**
	 * Returns the text hover for a given offset.
	 * 
	 * @param offset the offset for which to return the text hover
	 * @return the text hover for the given offset
	 */
	protected ITextHover getTextHover(int offset) {
		return (ITextHover) selectContentTypePlugin(offset, fTextHovers);
	}
	
	/**
	 * Returns the text hovering controller of this viewer.
	 * 
	 * @return the text hovering controller of this viewer
	 */
	protected AbstractInformationControlManager getTextHoveringController() {
		return fTextHoverManager;
	}
	
	/**
	 * Sets the creator for the hover controls.
	 *  
	 * @param creator the hover control creator
	 */
	public void setHoverControlCreator(IInformationControlCreator creator) {
		fHoverControlCreator= creator;
	}
	
	/*
	 * @see IWidgetTokenOwner#requestWidgetToken(Object)
	 */
	public synchronized boolean requestWidgetToken(Object tokenRequester) {
		return true;
//		if (fTextWidget != null) {
//			if (fWidgetTokenKeeper == null) {
//				fWidgetTokenKeeper= tokenRequester;
//				return true;
//			}
//			return (fWidgetTokenKeeper == tokenRequester);
//		}
//		return false;
	}
	
	/*
	 * @see IWidgetTokenOwner#releaseWidgetToken(Object)
	 */
	public synchronized void releaseWidgetToken(Object tokenKeeper) {
		if (fWidgetTokenKeeper == tokenKeeper)
			fWidgetTokenKeeper= null;
	}
	
	
	//---- Selection
	
	/*
	 * @see ITextViewer#getSelectedRange
	 */
	public Point getSelectedRange() {
		if (fTextWidget != null) {
			Point p= fTextWidget.getSelectionRange();
			int offset= getVisibleRegionOffset();			
			return new Point(p.x + offset, p.y);
		}
		return new Point(-1, -1);
	}
	
	/*
	 * @see ITextViewer#setSelectedRange
	 */
	public void setSelectedRange(int offset, int length) {
		
		if (fTextWidget == null)
			return;
			
		int end= offset + length;
		
		IDocument doc= getVisibleDocument();
		if (doc instanceof ChildDocument) {
			Position p= ((ChildDocument) doc).getParentDocumentRange();
			if (p.overlapsWith(offset, length)) {
				
				if (offset < p.getOffset())
					offset= p.getOffset();
				offset -= p.getOffset();	
				
				int e= p.getOffset() + p.getLength();
				if (end > e)
					end= e;
				end -= p.getOffset();
				
			} else
				return; 
		}			
		
		length= end - offset;
		
		int[] selectionRange= new int[] { offset, length };
		validateSelectionRange(selectionRange);
		if (selectionRange[0] >= 0 && selectionRange[1] >= 0) {
			fTextWidget.setSelectionRange(selectionRange[0], selectionRange[1]);
			selectionChanged(selectionRange[0], selectionRange[1]);
		}
	}
	
	/**
	 * Validates and adapts the given selection range if it is not a valid
	 * widget selection. The widget selection is invalid if it starts or ends
	 * inside a multi-character line delimiter. If so, the selection is adapted to
	 * start <b>after</b> the divided line delimiter and to end <b>before</b>
	 * the divided line delimiter.  The parameter passed in is changed in-place
	 * when being adapted. An adaptation to <code>[-1, -1]</code> indicates
	 * that the selection range could not be validated.
	 * Subclasses may reimplement this method.
	 * 
	 * @param selectionRange selectionRange[0] is the offset, selectionRange[1]
	 * 				the length of the selection to validate.
	 */
	protected void validateSelectionRange(int[] selectionRange) {
		
		IDocument document= getVisibleDocument();
		int documentLength= document.getLength();
		
		int offset= selectionRange[0];
		int length= selectionRange[1];
		
		
		if (offset <0)
			offset= 0;
			
		if (offset > documentLength)
			offset= documentLength;
			
		int delta= (offset + length) - documentLength;
		if (delta > 0)
			length -= delta;
			
		try {
			
			int lineNumber= document.getLineOfOffset(offset);
			IRegion lineInformation= document.getLineInformation(lineNumber);
			
			int lineEnd= lineInformation.getOffset() + lineInformation.getLength();
			delta= offset - lineEnd;
			if (delta > 0) {
				// in the middle of a multi-character line delimiter
				offset= lineEnd;
				String delimiter= document.getLineDelimiter(lineNumber);
				if (delimiter != null)
					offset += delimiter.length();
			}
						
			int end= offset + length;
			lineInformation= document.getLineInformationOfOffset(end);
			lineEnd= lineInformation.getOffset() + lineInformation.getLength();
			delta= end - lineEnd;
			if (delta > 0) {
				// in the middle of a multi-character line delimiter
				length -= delta;
			}
			
		} catch (BadLocationException x) {
			selectionRange[0]= -1;
			selectionRange[1]= -1;
			return;
		}
		
		selectionRange[0]= offset;
		selectionRange[1]= length;
	}

	/*
	 * @see Viewer#setSelection(ISelection)
	 */
	public void setSelection(ISelection selection, boolean reveal) {
		if (selection instanceof ITextSelection) {
			ITextSelection s= (ITextSelection) selection;
			setSelectedRange(s.getOffset(), s.getLength());
			if (reveal)
				revealRange(s.getOffset(), s.getLength());
		}
	}
	
	/*
	 * @see Viewer#getSelection()
	 */
	public ISelection getSelection() {
		Point p= getSelectedRange();
		if (p.x == -1 || p.y == -1)
			return TextSelection.emptySelection();
			
		return new TextSelection(getDocument(), p.x, p.y);
	}
	
	/*
	 * @see ITextViewer#getSelectionProvider
	 */
	public ISelectionProvider getSelectionProvider() {
		return this;
	}
	
	/**
	 * Sends out a selection changed event to all registered listeners.
	 *
	 * @param offset the offset of the newly selected range in the visible document
	 * @param length the length of the newly selected range in the visible document
	 */
	protected void selectionChanged(int offset, int length) {
		ISelection selection= new TextSelection(getDocument(), getVisibleRegionOffset() + offset, length);
		SelectionChangedEvent event= new SelectionChangedEvent(this, selection);
		fireSelectionChanged(event);
	}
	
	
	
	//---- Text listeners
	
	/*
	 * @see ITextViewer#addTextListener
	 */
	public void addTextListener(ITextListener listener) {
		if (fTextListeners == null)
			fTextListeners= new ArrayList();
	
		if (!fTextListeners.contains(listener))
			fTextListeners.add(listener);
	}
	
	/*
	 * @see ITextViewer#removeTextListener
	 */
	public void removeTextListener(ITextListener listener) {
		if (fTextListeners != null) {
			fTextListeners.remove(listener);
			if (fTextListeners.size() == 0)
				fTextListeners= null;
		}
	}
	
	/**
	 * Informs all registered text listeners about the change specified by the
	 * widget command. This method does not use a robust iterator.
	 *
	 * @param cmd the widget command translated into a text event and sent to all text listeners
	 */
	protected void updateTextListeners(WidgetCommand cmd) {
		
		if (fTextListeners != null) {
			
			DocumentEvent event= cmd.event;
			if (event instanceof ChildDocumentEvent)
				event= ((ChildDocumentEvent) event).getParentEvent();
				
			TextEvent e= new TextEvent(cmd.start, cmd.length, cmd.text, cmd.preservedText, event);
			for (int i= 0; i < fTextListeners.size(); i++) {
				ITextListener l= (ITextListener) fTextListeners.get(i);
				l.textChanged(e);
			}
		}
	}
	
	
	//---- Text input listeners
	
	/*
	 * @see ITextViewer#addTextInputListener
	 */
	public void addTextInputListener(ITextInputListener listener) {
		if (fTextInputListeners == null)
			fTextInputListeners= new ArrayList();
	
		if (!fTextInputListeners.contains(listener))
			fTextInputListeners.add(listener);
	}
	
	/*
	 * @see ITextViewer#removeTextInputListener
	 */
	public void removeTextInputListener(ITextInputListener listener) {
		if (fTextInputListeners != null) {
			fTextInputListeners.remove(listener);
			if (fTextInputListeners.size() == 0)
				fTextInputListeners= null;
		}
	}
	
	/**
	 * Informs all registered text input listeners about the forthcoming input change,
	 * This method does not use a robust iterator.
	 *
	 * @param oldInput the old input document
	 * @param newInput the new input document
	 */
	protected void fireInputDocumentAboutToBeChanged(IDocument oldInput, IDocument newInput) {
		if (fTextInputListeners != null) {
			for (int i= 0; i < fTextInputListeners.size(); i++) {
				ITextInputListener l= (ITextInputListener) fTextInputListeners.get(i);
				l.inputDocumentAboutToBeChanged(oldInput, newInput);
			}
		}
	}
	
	/**
	 * Informs all registered text input listeners about the sucessful input change,
	 * This method does not use a robust iterator.
	 *
	 * @param oldInput the old input document
	 * @param newInput the new input document
	 */
	protected void fireInputDocumentChanged(IDocument oldInput, IDocument newInput) {		
		if (fTextInputListeners != null) {
			for (int i= 0; i < fTextInputListeners.size(); i++) {
				ITextInputListener l= (ITextInputListener) fTextInputListeners.get(i);
				l.inputDocumentChanged(oldInput, newInput);
			}
		}
	}
	
	//---- Document
	
	/*
	 * @see Viewer#getInput
	 */
	public Object getInput() {
		return getDocument();
	}
	
	/*
	 * @see ITextViewer#getDocument
	 */
	public IDocument getDocument() {
		return fDocument;
	}
	
	/*
	 * @see Viewer#setInput
	 */
	public void setInput(Object input) {
		
		IDocument document= null;
		if (input instanceof IDocument)
			document= (IDocument) input;
		
		setDocument(document);
	}
	
	/*
	 * @see ITextViewer#setDocument(IDocument)
	 */
	public void setDocument(IDocument document) {
		
		fReplaceTextPresentation= true;
		fireInputDocumentAboutToBeChanged(fDocument, document);
				
		IDocument oldDocument= fDocument;
		fDocument= document;
		
		setVisibleDocument(fDocument);
		
		inputChanged(fDocument, oldDocument);
		
		fireInputDocumentChanged(oldDocument, fDocument);
		fReplaceTextPresentation= false;
	}
	
	/*
	 * @see ITextViewer#setDocument(IDocument, int int)
	 */
	public void setDocument(IDocument document, int visibleRegionOffset, int visibleRegionLength) {
		
		fReplaceTextPresentation= true;
		fireInputDocumentAboutToBeChanged(fDocument, document);
				
		IDocument oldDocument= fDocument;
		fDocument= document;
		
		try {
			int line= fDocument.getLineOfOffset(visibleRegionOffset);
			int offset= fDocument.getLineOffset(line);
			int length= (visibleRegionOffset - offset) + visibleRegionLength;
			setVisibleDocument(getChildDocumentManager().createChildDocument(fDocument, offset, length));
		} catch (BadLocationException x) {
			throw new IllegalArgumentException(JFaceTextMessages.getString("TextViewer.error.invalid_visible_region_1")); //$NON-NLS-1$
		}
		
		inputChanged(fDocument, oldDocument);
		
		fireInputDocumentChanged(oldDocument, fDocument);
		fReplaceTextPresentation= false;
	}		
	
	//---- Viewports	
	
	/**
	 * Initializes all listeners and structures required to set up viewport listeners.
	 */
	private void initializeViewportUpdate() {

		if (fViewportGuard != null)
			return;

		if (fTextWidget != null) {
			
			fViewportGuard= new ViewportGuard();
			fLastTopPixel= -1;

			fTextWidget.addKeyListener(fViewportGuard);
			fTextWidget.addMouseListener(fViewportGuard);

			fScroller= fTextWidget.getVerticalBar();
			if (fScroller != null)
				fScroller.addSelectionListener(fViewportGuard);
		}
	}
	
	/**
	 * Removes all listeners and structures required to set up viewport listeners.
	 */
	private void removeViewPortUpdate() {
		
		if (fTextWidget != null) {
			
			fTextWidget.removeKeyListener(fViewportGuard);
			fTextWidget.removeMouseListener(fViewportGuard);

			if (fScroller != null && !fScroller.isDisposed()) {
				fScroller.removeSelectionListener(fViewportGuard);
				fScroller= null;
			}

			fViewportGuard= null;
		}
	}
	
	/*
	 * @see ITextViewer#addViewportListener
	 */
	public void addViewportListener(IViewportListener listener) {
		
		if (fViewportListeners == null) {
			fViewportListeners= new ArrayList();
			initializeViewportUpdate();
		}
	
		if (!fViewportListeners.contains(listener))
			fViewportListeners.add(listener);
	}
	
	/*
	 * @see ITextViewer#removeViewportListener
	 */
	public void removeViewportListener(IViewportListener listener) {
		if (fViewportListeners != null)
			fViewportListeners.remove(listener);
	}
		
	/**
	 * Checks whether the viewport changed and if so informs all registered 
	 * listeners about the change.
	 *
	 * @param origin describes under which circumstances this method has been called.
	 *
	 * @see IViewportListener
	 */
	protected void updateViewportListeners(int origin) {
		
		int topPixel= fTextWidget.getTopPixel();
		if (topPixel >= 0 && topPixel != fLastTopPixel) {
			if (fViewportListeners != null) {
				for (int i= 0; i < fViewportListeners.size(); i++) {
					IViewportListener l= (IViewportListener) fViewportListeners.get(i);
					l.viewportChanged(topPixel);
				}
			}
			fLastTopPixel= topPixel;
		}
	}
	
	//---- scrolling and revealing
	
	/*
	 * @see ITextViewer#getTopIndex
	 */
	public int getTopIndex() {
		
		if (fTextWidget != null) {
			
			int top= fTextWidget.getTopIndex();
			
			int offset= getVisibleRegionOffset();
			if (offset > 0) {
				try {
					top += getDocument().getLineOfOffset(offset);
				} catch (BadLocationException x) {
					if (TRACE_ERRORS)
						System.out.println(JFaceTextMessages.getString("TextViewer.error.bad_location.getTopIndex")); //$NON-NLS-1$
					return -1;
				}
			}
			
			return top;
		}
					
		return -1;
	}
		
	/*
	 * @see ITextViewer#setTopIndex
	 */
	public void setTopIndex(int index) {
		
		if (fTextWidget != null) {
			
			int offset= getVisibleRegionOffset();
			if (offset > 0) {
				try {
					index -= getDocument().getLineOfOffset(offset);
				} catch (BadLocationException x) {
					if (TRACE_ERRORS)
						System.out.println(JFaceTextMessages.getString("TextViewer.error.bad_location.setTopIndex_1")); //$NON-NLS-1$
					return;
				}
			}
			
			if (index >= 0) {
				
				int lines= getVisibleLinesInViewport();
				if (lines > -1 ) {					
					IDocument d= getVisibleDocument();
					int last= d.getNumberOfLines() - lines;
					if (last > 0 && index  > last)
						index= last;
					
					fTextWidget.setTopIndex(index);
					updateViewportListeners(INTERNAL);
				
				} else
					fTextWidget.setTopIndex(index);
			}
		}
	}
	
	/**
	 * Returns the viewport height in lines.
	 * The actual visible lines can be fewer if the document is shorter than the viewport.
	 *
	 * @return the viewport height in lines
	 */
	protected int getVisibleLinesInViewport() {
		if (fTextWidget != null) {
			Rectangle clArea= fTextWidget.getClientArea();
			if (!clArea.isEmpty())
				return clArea.height / fTextWidget.getLineHeight();
		}
		return -1;
	}
	
	/*
	 * @see ITextViewer#getBottomIndex
	 */
	public int getBottomIndex() {
		
		if (fTextWidget == null)
			return -1;
		
		IRegion r= getVisibleRegion();
		
		try {
			
			IDocument d= getDocument();
			int startLine= d.getLineOfOffset(r.getOffset());
			int endLine= d.getLineOfOffset(r.getOffset()  + r.getLength() - 1);
			int lines= getVisibleLinesInViewport();
			
			if (startLine + lines < endLine)
				return getTopIndex() + lines - 1;
				
			return endLine;
			
		} catch (BadLocationException x) {
			if (TRACE_ERRORS)
				System.out.println(JFaceTextMessages.getString("TextViewer.error.bad_location.getBottomIndex")); //$NON-NLS-1$
		}
		
		return -1;
	}
	
	/*
	 * @see ITextViewer#getTopIndexStartOffset
	 */
	public int getTopIndexStartOffset() {
		
		if (fTextWidget != null) {	
			int top= fTextWidget.getTopIndex();
			try {
				top= getVisibleDocument().getLineOffset(top);
				return top + getVisibleRegionOffset();
			} catch (BadLocationException ex) {
				if (TRACE_ERRORS)
					System.out.println(JFaceTextMessages.getString("TextViewer.error.bad_location.getTopIndexStartOffset")); //$NON-NLS-1$
			}
		}
		
		return -1;
	}
	
	/*
	 * @see ITextViewer#getBottomIndexEndOffset
	 */
	public int getBottomIndexEndOffset() {
		try {
			
			IRegion line= getDocument().getLineInformation(getBottomIndex());
			int bottomEndOffset= line.getOffset() + line.getLength() - 1;
			
			IRegion region= getVisibleRegion();
			int visibleRegionEndOffset=  region.getOffset() + region.getLength() - 1;
			return visibleRegionEndOffset < bottomEndOffset ? visibleRegionEndOffset : bottomEndOffset;
				
		} catch (BadLocationException ex) {
			if (TRACE_ERRORS)
				System.out.println(JFaceTextMessages.getString("TextViewer.error.bad_location.getBottomIndexEndOffset")); //$NON-NLS-1$
			return getDocument().getLength() - 1;
		}
	}
	
	/*
	 * @see ITextViewer#revealRange
	 */
	public void revealRange(int start, int length) {
		
		if (fTextWidget == null)
			return;
		
		int end= start + length;

		IDocument doc= getVisibleDocument();
		Position p= (doc instanceof ChildDocument)
			? ((ChildDocument) doc).getParentDocumentRange()
			: new Position(0, doc.getLength());
			
		if (p.overlapsWith(start, length)) {
				
			if (start < p.getOffset())
				start= p.getOffset();
			start -= p.getOffset();	
				
			int e= p.getOffset() + p.getLength();				
			if (end > e)
				end= e;
			end -= p.getOffset();
				
		} else
			return; 
		
		internalRevealRange(start, end);
	}
	
	/**
	 * Reveals the given range of the visible document.
	 *
	 * @param start the start offset of the range
	 * @param end the end offset of the range
	 */
	protected void internalRevealRange(int start, int end) {			
		
		try {
			
			IDocument doc= getVisibleDocument();
			
			int startLine= doc.getLineOfOffset(start);
			int endLine= doc.getLineOfOffset(end);
			
			int top= fTextWidget.getTopIndex();
			if (top > -1) {
				
				// scroll vertically
				
				int lines= getVisibleLinesInViewport();
				int bottom= top + lines;
				
				// two lines at the top and the bottom should always be left
				// if window is smaller than 5 lines, always center position is chosen
				int bufferZone= 2; 
				
				if (startLine >= top + bufferZone 
						&& startLine <= bottom - bufferZone
						&& endLine >= top + bufferZone 
						&& endLine <= bottom - bufferZone) {
						
					// do not scroll at all as it is already visible
					
				} else {
					
					int delta= Math.max(0, lines - (endLine - startLine));
					fTextWidget.setTopIndex(startLine - delta/3);
					updateViewportListeners(INTERNAL);
				}
				
				// scroll horizontally
				
				if (endLine < startLine) {
					endLine += startLine;
					startLine= endLine - startLine;
					endLine -= startLine;
				}
				
				int startPixel= -1;
				int endPixel= -1;
				
				if (endLine > startLine) {
					// reveal the beginning of the range in the start line
					IRegion line= doc.getLineInformation(startLine);
					startPixel= getWidthInPixels(line.getOffset(), start - line.getOffset());
					endPixel= getWidthInPixels(line.getOffset(), line.getLength());
				} else {
					int lineStart= doc.getLineOffset(startLine);
					startPixel= getWidthInPixels(lineStart, start - lineStart);
					endPixel= getWidthInPixels(lineStart, end - lineStart);
				}
				
				int visibleStart= fTextWidget.getHorizontalPixel();
				int visibleEnd= visibleStart + fTextWidget.getClientArea().width;
				
				// scroll only if not yet visible
				if (startPixel < visibleStart || visibleEnd < endPixel) {
					
					// set buffer zone to 10 pixels
					bufferZone= 10;
					
					int newOffset= visibleStart;
					if (startPixel < visibleStart)
						newOffset= startPixel;
					else if (endPixel - startPixel  + bufferZone < visibleEnd - visibleStart)
						newOffset= visibleStart + (endPixel - visibleEnd + bufferZone);
					else
						newOffset= startPixel;
						
					fTextWidget.setHorizontalIndex(newOffset / getAverageCharWidth());
				}
				
			}
		} catch (BadLocationException e) {
			throw new IllegalArgumentException(JFaceTextMessages.getString("TextViewer.error.invalid_range")); //$NON-NLS-1$
		}
	}
	
	/**
	 * Returns the width of the text when being drawed into this viewer's widget.
	 * 
	 * @param the string to messure
	 * @return the width of the presentation of the given string
	 * @deprecated use <code>getWidthInPixels(int, int)</code> instead
	 */
	final protected int getWidthInPixels(String text) {
		GC gc= new GC(fTextWidget);
		gc.setFont(fTextWidget.getFont());
		Point extent= gc.textExtent(text);
		gc.dispose();
		return extent.x;
	}
	
	/**
	 * Returns the width of the representation of a text range in the
	 * visible region of the viewer's document as drawn in this viewer's
	 * widget.
	 * 
	 * @param offset the offset of the text range in the visible region
	 * @param length the length of the text range in the visible region
	 * @return the width of the presentation of the specified text range
	 */
	final protected int getWidthInPixels(int offset, int length) {		
		
		Point left= fTextWidget.getLocationAtOffset(offset);
		Point right= new Point(left.x, left.y);
		
		int end= offset + length;
		for (int i= offset +1; i <= end; i++) {
			
			Point p= fTextWidget.getLocationAtOffset(i);
			
			if (left.x > p.x)
				left.x= p.x;
								
			if (right.x  < p.x)
				right.x= p.x;				
		}
		
		return  right.x - left.x;
	}
	
	/**
	 * Returns the average character width of this viewer's widget.
	 * 
	 * @return the average character width of this viewer's widget
	 */
	final protected int getAverageCharWidth() {
		GC gc= new GC(fTextWidget);
		gc.setFont(fTextWidget.getFont());
		int increment= gc.getFontMetrics().getAverageCharWidth();
		gc.dispose();
		return increment;
	}
	
	/*
	 * @see Viewer#refresh
	 */
	public void refresh() {
		setDocument(getDocument());
	}
	
	//---- visible range support
	
	/**
	 * Returns the child document manager
	 *
	 * @return the child document manager
	 */
	private ChildDocumentManager getChildDocumentManager() {
		if (fChildDocumentManager == null)
			fChildDocumentManager= new ChildDocumentManager();
		return fChildDocumentManager;
	}
	
	/**
	 * Invalidates the current presentation by sending an initialization
	 * event to all text listener.
	 */
	public final void invalidateTextPresentation() {
		if (fVisibleDocument != null) {
			fWidgetCommand.start= 0;
			fWidgetCommand.length= 0;
			fWidgetCommand.text= fVisibleDocument.get();
			fWidgetCommand.event= null;
			updateTextListeners(fWidgetCommand);
		}
	}
	
	/**
	 * Initializes the text widget with the visual document and
	 * invalidates the overall presentation.
	 */
	private void initializeWidgetContents() {
		
		if (fTextWidget != null && fVisibleDocument != null) {
		
			// set widget content
			if (fDocumentAdapter == null)
				fDocumentAdapter= createDocumentAdapter();
				
			fDocumentAdapter.setDocument(fVisibleDocument);
			fTextWidget.setContent(fDocumentAdapter);
								
			// invalidate presentation				
			invalidateTextPresentation();
		}
	}
	
	/**
	 * Sets this viewer's visible document. The visible document represents the 
	 * visible region of the viewer's input document.
	 *
	 * @param document the visible document
	 */
	private void setVisibleDocument(IDocument document) {
		
		if (fVisibleDocument != null && fDocumentListener != null)
			fVisibleDocument.removeDocumentListener(fDocumentListener);
		
		fVisibleDocument= document;
		
		initializeWidgetContents();
		resetPlugins();
		
		if (fVisibleDocument != null && fDocumentListener != null)
			fVisibleDocument.addDocumentListener(fDocumentListener);
	}
	
	/**
	 * Returns the viewer's visible document.
	 *
	 * @return the viewer's visible document
	 */
	protected IDocument getVisibleDocument() {
		return fVisibleDocument;
	}
	
	/**
	 * Returns the offset of the visible region.
	 *
	 * @return the offset of the visible region
	 */
	protected int getVisibleRegionOffset() {
		
		IDocument document= getVisibleDocument();
		if (document instanceof ChildDocument) {
			ChildDocument cdoc= (ChildDocument) document;
			return cdoc.getParentDocumentRange().getOffset();
		}
		
		return 0;
	}
	
	/*
	 * @see ITextViewer#getVisibleRegion
	 */
	public IRegion getVisibleRegion() {
		
		IDocument document= getVisibleDocument();
		if (document instanceof ChildDocument) {
			Position p= ((ChildDocument) document).getParentDocumentRange();
			return new Region(p.getOffset(), p.getLength());
		}		
		
		return new Region(0, document.getLength());
	}
		
	/*
	 * @see ITextViewer#setVisibleRegion
	 */
	public void setVisibleRegion(int start, int length) {
		
		IRegion region= getVisibleRegion();
		if (start == region.getOffset() && length == region.getLength()) {
			// nothing to change
			return;
		}
		
		ChildDocument child= null;
		IDocument parent= getVisibleDocument();
		
		if (parent instanceof ChildDocument) {
			child= (ChildDocument) parent;
			parent= child.getParentDocument();
		}
		
		try {
			
			int line= parent.getLineOfOffset(start);
			int offset= parent.getLineOffset(line);
			length += (start - offset);
			
			if (child != null) {
				child.setParentDocumentRange(offset, length);
			} else {
				child= getChildDocumentManager().createChildDocument(parent, offset, length);
			}
			
			setVisibleDocument(child);
							
		} catch (BadLocationException x) {
			throw new IllegalArgumentException(JFaceTextMessages.getString("TextViewer.error.invalid_visible_region_2")); //$NON-NLS-1$
		}
	}
				
	/*
	 * @see ITextViewer#resetVisibleRegion
	 */
	public void resetVisibleRegion() {
		IDocument document= getVisibleDocument();
		if (document instanceof ChildDocument) {			
			ChildDocument child = (ChildDocument) document;
			setVisibleDocument(child.getParentDocument());
			getChildDocumentManager().freeChildDocument(child);
		}
	}
	
	/*
	 * @see ITextViewer#overlapsWithVisibleRegion
	 */
	public boolean overlapsWithVisibleRegion(int start, int length) {
		IDocument document= getVisibleDocument();
		if (document instanceof ChildDocument) {
			ChildDocument cdoc= (ChildDocument) document;
			return cdoc.getParentDocumentRange().overlapsWith(start, length);
		} else if (document != null) {
			int size= document.getLength();
			return (start >= 0 && length >= 0 && start + length <= size);
		}
		return false;
	}
		
	
	
	//--------------------------------------
	
	/*
	 * @see ITextViewer#setTextDoubleClickStrategy
	 */
	public void setTextDoubleClickStrategy(ITextDoubleClickStrategy strategy, String contentType) {		
		
		if (strategy != null) {
			if (fDoubleClickStrategies == null)
				fDoubleClickStrategies= new HashMap();
			fDoubleClickStrategies.put(contentType, strategy);
		} else if (fDoubleClickStrategies != null)
			fDoubleClickStrategies.remove(contentType);
	}
	
	/**
	 * Selects from the given map the one which is registered under
	 * the content type of the partition in which the given offset is located.
	 *
	 * @param plugins the map from which to choose
	 * @param offset the offset for which to find the plugin
	 * @return the plugin registered under the offset's content type 
	 */
	protected Object selectContentTypePlugin(int offset, Map plugins) {
		try {
			return selectContentTypePlugin(getDocument().getContentType(offset), plugins);
		} catch (BadLocationException x) {
			if (TRACE_ERRORS)
				System.out.println(JFaceTextMessages.getString("TextViewer.error.bad_location.selectContentTypePlugin")); //$NON-NLS-1$
		}
		return null;
	}
	
	/**
	 * Selects from the given <code>plugins</code> this one which is registered for
	 * the given content <code>type</code>.
	 */
	private Object selectContentTypePlugin(String type, Map plugins) {
		
		if (plugins == null)
			return null;
		
		return plugins.get(type);
	}
	
	/**
	 * Hook called on receipt of a <code>VerifyEvent</code>. The event has
	 * been translated into a <code>DocumentCommand</code> which can now be
	 * manipulated by interested parties. By default, the hook forwards the command
	 * to the installed <code>IAutoIndentStrategy</code>.
	 *
	 * @param command the document command representing the verify event
	 */
	protected void customizeDocumentCommand(DocumentCommand command) {
		if (!fIgnoreAutoIndent) {
			IAutoIndentStrategy s= (IAutoIndentStrategy) selectContentTypePlugin(command.offset, fAutoIndentStrategies);
			if (s != null)
				s.customizeDocumentCommand(getDocument(), command);
		}
		fIgnoreAutoIndent= false;
	}
	
	/**
	 * @see VerifyListener#verifyText
	 */
	protected void handleVerifyEvent(VerifyEvent e) {
				
		if (fEventConsumer != null) {
			fEventConsumer.processEvent(e);
			if (!e.doit)
				return;
		}
		
		int offset= getVisibleRegionOffset();
		fDocumentCommand.setEvent(e, offset);
		customizeDocumentCommand(fDocumentCommand);
		if (!fDocumentCommand.fillEvent(e, offset)) {
			try {
				fVerifyListener.forward(false);
				getDocument().replace(fDocumentCommand.offset, fDocumentCommand.length, fDocumentCommand.text);
			} catch (BadLocationException x) {
				if (TRACE_ERRORS)
					System.out.println(JFaceTextMessages.getString("TextViewer.error.bad_location.verifyText")); //$NON-NLS-1$
			} finally {
				fVerifyListener.forward(true);
			}
		}	
	}
	
	//---- text manipulation
	
	/*
	 * @see ITextViewer#canDoOperation
	 */
	public boolean canDoOperation(int operation) {
		
		if (fTextWidget == null)
			return false;

		switch (operation) {
			case CUT:
				return isEditable() && fTextWidget.getSelectionCount() > 0;
			case COPY:
				return fTextWidget.getSelectionCount() > 0;
			case DELETE:
			case PASTE:
				return isEditable();
			case SELECT_ALL:
				return true;
			case SHIFT_RIGHT:
			case SHIFT_LEFT:
				return isEditable() && fIndentChars != null && areMultipleLinesSelected();
			case PREFIX:
			case STRIP_PREFIX:
				return isEditable() && fDefaultPrefixChars != null;
			case UNDO:
				return fUndoManager != null && fUndoManager.undoable();
			case REDO:
				return fUndoManager != null && fUndoManager.redoable();
			case PRINT:
				return isPrintable();
		}
		
		return false;
	}
	
	/*
	 * @see ITextViewer#doOperation
	 */
	public void doOperation(int operation) {
		
		if (fTextWidget == null)
			return;

		switch (operation) {

			case UNDO:
				if (fUndoManager != null) {
					fIgnoreAutoIndent= true;
					fUndoManager.undo();
				}
				break;
			case REDO:
				if (fUndoManager != null) {
					fIgnoreAutoIndent= true;
					fUndoManager.redo();
				}
				break;
			case CUT:
				fTextWidget.cut();
				break;
			case COPY:
				fTextWidget.copy();
				break;
			case PASTE:
				fIgnoreAutoIndent= true;
				fTextWidget.paste();
				break;
			case DELETE:
				deleteText();
				break;
			case SELECT_ALL:
				setSelectedRange(getVisibleRegionOffset(), getVisibleDocument().getLength());
				break;
			case SHIFT_RIGHT:
				shift(false, true, false);
				break;
			case SHIFT_LEFT:
				shift(false, false, false);
				break;
			case PREFIX:
				shift(true, true, true);
				break;
			case STRIP_PREFIX:
				shift(true, false, true);
				break;
			case PRINT:
				print();
				break;
		}
	}
	
	/**
	 * Deletes the current selection. If the selection has the length 0
	 * the selection is automatically extended to the right - either by 1
	 * or by the length of line delimiter if at the end of a line.
	 * 
	 * @deprecated use <code>StyledText.invokeAction</code> instead
	 */
	protected void deleteText() {
		fTextWidget.invokeAction(ST.DELETE_NEXT);
	}
		
	/**
	 * A block is selected if the character preceding the start of the 
	 * selection is a new line character.
	 *
	 * @return <code>true</code> if a block is selected
	 */
	protected boolean isBlockSelected() {
		
		Point s= getSelectedRange();
		if (s.y == 0)
			return false;
		
		try {
			
			IDocument document= getDocument();
			int line= document.getLineOfOffset(s.x);
			int start= document.getLineOffset(line);
			return (s.x == start);
			
		} catch (BadLocationException x) {
		}
		
		return false;
	}
	
	/**
	 * Returns whether multiple lines are selected.
	 * 
	 * @return <code>true</code> if multiple lines are selected
	 */
	protected boolean areMultipleLinesSelected() {
		Point s= getSelectedRange();
		if (s.y < 1)
			return false;
			
		try {
			
			IDocument document= getDocument();
			int startLine= document.getLineOfOffset(s.x);
			int endLine= document.getLineOfOffset(s.x + s.y -1);
			return startLine != endLine;
		
		} catch (BadLocationException x) {
		}
		
		return false;
	}
	
	/**
	 * Returns the index of the first line whose start offset is in the given text range.
	 *
	 * @param region the text range in characters where to find the line
	 * @return the first line whose start index is in the given range, -1 if there is no such line
	 */
	private int getFirstCompleteLineOfRegion(IRegion region) {
		
		try {
			
			IDocument d= getDocument();
			
			int startLine= d.getLineOfOffset(region.getOffset());
			
			int offset= d.getLineOffset(startLine);
			if (offset >= region.getOffset())
				return startLine;
				
			offset= d.getLineOffset(startLine + 1);
			return (offset > region.getOffset() + region.getLength() ? -1 : startLine + 1);
		
		} catch (BadLocationException x) {
			if (TRACE_ERRORS)
				System.out.println(JFaceTextMessages.getString("TextViewer.error.bad_location.getFirstCompleteLineOfRegion")); //$NON-NLS-1$
		}
		
		return -1;
	}
	
	
	/**
	 * Creates a region describing the text block (something that starts at
	 * the beginning of a line) completely containing the current selection.
	 * 
	 * @param selection the selection to use
	 */
	private IRegion getTextBlockFromSelection(Point selection) {
				
		try {
			IDocument document= getDocument();
			IRegion line= document.getLineInformationOfOffset(selection.x);
			int length= selection.y == 0 ? line.getLength() : selection.y + (selection.x - line.getOffset());
			return new Region(line.getOffset(), length);
			
		} catch (BadLocationException x) {
		}
		
		return null;		
	}

	/**
	 * Shifts a text block to the right or left using the specified set of prefix characters.
	 * The prefixes must start at the beginnig of the line.
	 *
	 * @param useDefaultPrefixes says whether the configured default or indent prefixes should be used
	 * @param right says whether to shift to the right or the left
	 * 
	 * @deprecated use shift(boolean, boolean, boolean) instead
	 */
	protected void shift(boolean useDefaultPrefixes, boolean right) {
		shift(useDefaultPrefixes, right, false);
	}
		
	/**
	 * Shifts a text block to the right or left using the specified set of prefix characters.
	 * If white space should be ignored the prefix characters must not be at the beginning of
	 * the line when shifting to the left. There may be whitespace in front of the prefixes.
	 *
	 * @param useDefaultPrefixes says whether the configured default or indent prefixes should be used
	 * @param right says whether to shift to the right or the left
	 * @param ignoreWhitespace says whether whitepsace in front of prefixes is allowed
	 */
	protected void shift(boolean useDefaultPrefixes, boolean right, boolean ignoreWhitespace) {
		
		if (fUndoManager != null)
			fUndoManager.beginCompoundChange();
						
		try {
			
			Point selection= getSelectedRange();
			IRegion block= getTextBlockFromSelection(selection);
			ITypedRegion[] regions= getDocument().computePartitioning(block.getOffset(), block.getLength());
			
			IDocument d= getDocument();
			int[] lines= new int[regions.length * 2]; // [startline, endline, startline, endline, ...]
			for (int i= 0, j= 0; i < regions.length; i++, j+= 2) {
				// start line of region
				lines[j]= getFirstCompleteLineOfRegion(regions[i]);
				// end line of region
				int offset= regions[i].getOffset() + regions[i].getLength() - 1;
				lines[j + 1]= (lines[j] == -1 ? -1 : d.getLineOfOffset(offset));
			}
			
			// Remember the selection range.
			IPositionUpdater positionUpdater= new ShiftPositionUpdater(SHIFTING);
			Position rememberedSelection= new Position(selection.x, selection.y);
			d.addPositionCategory(SHIFTING);
			d.addPositionUpdater(positionUpdater);
			try {
				d.addPosition(SHIFTING, rememberedSelection);
			} catch (BadPositionCategoryException ex) {
				// should not happen
			}
			
			fTextWidget.setRedraw(false);
			
			// Perform the shift operation.
			Map map= (useDefaultPrefixes ? fDefaultPrefixChars : fIndentChars);
			for (int i= 0, j= 0; i < regions.length; i++, j += 2) {
				String[] prefixes= (String[]) selectContentTypePlugin(regions[i].getType(), map);
				if (prefixes != null && prefixes.length > 0 && lines[j] >= 0 && lines[j + 1] >= 0) {
					if (right)
						shiftRight(lines[j], lines[j + 1], prefixes[0]);
					else
						shiftLeft(lines[j], lines[j + 1], prefixes, ignoreWhitespace);
				}
			}
			
			// Restore the selection.
			setSelectedRange(rememberedSelection.getOffset(), rememberedSelection.getLength());
			
			try {
				d.removePositionUpdater(positionUpdater);
				d.removePositionCategory(SHIFTING);			
			} catch (BadPositionCategoryException ex) {
				// should not happen
			}
			
			fTextWidget.setRedraw(true);
			
		} catch (BadLocationException x) {
			if (TRACE_ERRORS)
				System.out.println(JFaceTextMessages.getString("TextViewer.error.bad_location.shift_1")); //$NON-NLS-1$
		} finally {
			if (fUndoManager != null)
				fUndoManager.endCompoundChange();
		}
	}
	
	/**
	 * Shifts the specified lines to the right inserting the given prefix
	 * at the beginning of each line
	 *
	 * @param prefix the prefix to be inserted
	 * @param startLine the first line to shift
	 * @param endLine the last line to shift
	 */
	private void shiftRight(int startLine, int endLine, String prefix) {
		
		try {
						
			IDocument d= getDocument();
			while (startLine <= endLine) {
				d.replace(d.getLineOffset(startLine++), 0, prefix);
			}

		} catch (BadLocationException x) {
			if (TRACE_ERRORS)
				System.out.println("TextViewer.shiftRight: BadLocationException"); //$NON-NLS-1$
		}
	}
	
	/**
	 * Shifts the specified lines to the right or to the left. On shifting to the right
	 * it insert <code>prefixes[0]</code> at the beginning of each line. On shifting to the
	 * left it tests whether each of the specified lines starts with one of the specified 
	 * prefixes and if so, removes the prefix.
	 *
	 * @param prefixes the prefixes to be used for shifting
	 * @param right if <code>true</code> shift to the right otherwise to the left
	 * @param startLine the first line to shift
	 * @param endLine the last line to shift
	 */
	private void shiftLeft(int startLine, int endLine, String[] prefixes, boolean ignoreWhitespace) {
		
		IDocument d= getDocument();
		
		try {
						
			IRegion[] occurrences= new IRegion[endLine - startLine + 1];
			
			// find all the first occurrences of prefix in the given lines
			for (int i= 0; i < occurrences.length; i++) {
				
				IRegion line= d.getLineInformation(startLine + i);
				String text= d.get(line.getOffset(), line.getLength());
				
				int index= -1;
				int[] found= TextUtilities.indexOf(prefixes, text, 0);
				if (found[0] != -1) {
					if (ignoreWhitespace) {
						String s= d.get(line.getOffset(), found[0]);
						s= s.trim();
						if (s.length() == 0)
							index= line.getOffset() + found[0];
					} else if (found[0] == 0)
						index= line.getOffset();
				}
				
				if (index > -1) {
					// remember where prefix is in line, so that it can be removed
					int length= prefixes[found[1]].length();
					if (length == 0 && !ignoreWhitespace && line.getLength() > 0) {
						// found a non-empty line which cannot be shifted
						return;
					} else 
						occurrences[i]= new Region(index, length);
				} else {
					// found a line which cannot be shifted
					return;
				}
			}

			// ok - change the document
			for (int i= occurrences.length - 1; i >= 0; i--) {
				IRegion r= occurrences[i];
				d.replace(r.getOffset(), r.getLength(), ""); //$NON-NLS-1$
			}

		} catch (BadLocationException x) {
			if (TRACE_ERRORS)
				System.out.println("TextViewer.shiftLeft: BadLocationException"); //$NON-NLS-1$
		}
	}
	
	/**
	 * Returns whether the shown text can be printed.
	 *
	 * @return the viewer's printable mode
	 */
	protected boolean isPrintable() {
		/*
		 * 1GK7Q10: ITPUI:WIN98 - internal error after invoking print at editor view
		 * Changed from returning true to testing the length of the printer queue
		 */
		PrinterData[] printerList= Printer.getPrinterList();
		return (printerList != null && printerList.length > 0);
	}
	
	/**
	 * This implementation brings up a print dialog, then 
	 * calls printContents(Printer), which performs the actual print.
	 *
	 * Subclasses may override.
	 */
	protected void print() {
		
		final PrintDialog dialog= new PrintDialog(fTextWidget.getShell(), SWT.NULL);
		final PrinterData data= dialog.open();
		
		if (data != null) {
			
			final Printer printer= new Printer(data);
			final Runnable styledTextPrinter= fTextWidget.print(printer);
	
			Thread printingThread= new Thread("Printing") { //$NON-NLS-1$
				public void run() {
					styledTextPrinter.run();
					printer.dispose();
				}
			};
			printingThread.start();
		}
    }
	
		
	//------ find support
	
	/**
	 * @see IFindReplaceTarget#canPerformFind
	 */
	protected boolean canPerformFind() {
		IDocument d= getVisibleDocument();
		return (fTextWidget != null && d != null && d.getLength() > 0);
	}
	
	/**
	 * @see IFindReplaceTarget#findAndSelect(int, String, boolean, boolean, boolean)
	 */
	protected int findAndSelect(int startPosition, String findString, boolean forwardSearch, boolean caseSensitive, boolean wholeWord) {
		if (fTextWidget == null)
			return -1;
			
		try {
			int offset= (startPosition == -1 ? startPosition : startPosition - getVisibleRegionOffset());
			int pos= getVisibleDocument().search(offset, findString, forwardSearch, caseSensitive, wholeWord);
			if (pos > -1) {
				int length= findString.length();
				fTextWidget.setSelectionRange(pos, length);
				internalRevealRange(pos, pos + length);
				selectionChanged(pos, length);
			}
			return pos + getVisibleRegionOffset();
		} catch (BadLocationException x) {
			if (TRACE_ERRORS)
				System.out.println(JFaceTextMessages.getString("TextViewer.error.bad_location.findAndSelect")); //$NON-NLS-1$
		}
		
		return -1;
	}
	
	/**
	 * Performs a search similar to <code>IFindReplaceTarget.findAndSelect()</code> within the given
	 * range of the viewer's visible document.
	 */
	private int findAndSelectInRange(int startPosition, String findString, boolean forwardSearch, boolean caseSensitive, boolean wholeWord, int rangeOffset, int rangeLength) {
		if (fTextWidget == null)
			return -1;
			
		try {
			int offset;
			if (forwardSearch && (startPosition == -1 || startPosition < rangeOffset)) {
				offset= rangeOffset;
			} else if (!forwardSearch && (startPosition == -1 || startPosition > rangeOffset + rangeLength)) {
				offset= rangeOffset + rangeLength;
			} else {
				offset= startPosition;
			}
			offset -= getVisibleRegionOffset();
			
			int pos= getVisibleDocument().search(offset, findString, forwardSearch, caseSensitive, wholeWord);

			int length =  findString.length();
			if (pos != -1 && (pos + getVisibleRegionOffset() < rangeOffset || pos + getVisibleRegionOffset() + length > rangeOffset + rangeLength))
				pos= -1;

			if (pos > -1) {
				fTextWidget.setSelectionRange(pos, length);
				internalRevealRange(pos, pos + length);
				selectionChanged(pos, length);
			}
			return pos + getVisibleRegionOffset();
		} catch (BadLocationException x) {
			if (TRACE_ERRORS)
				System.out.println(JFaceTextMessages.getString("TextViewer.error.bad_location.findAndSelect")); //$NON-NLS-1$
		}
		
		return -1;
	}	
	
	//---------- text presentation support
	
	/*
	 * @see ITextViewer#setTextColor
	 */
	public void setTextColor(Color color) {
		if (color != null)
			setTextColor(color, 0, getDocument().getLength(), true);
	}
	
	/*
	 * @see ITextViewer#setTextColor 	 
	 */
	public void setTextColor(Color color, int start, int length, boolean controlRedraw) {		
		
		if (fTextWidget != null) {
									
			if (controlRedraw)
				fTextWidget.setRedraw(false); 
			
			StyleRange s= new StyleRange();
			s.foreground= color;
			s.start= start;
			s.length= length;
			
			fTextWidget.setStyleRange(s);
			
			if (controlRedraw)
				fTextWidget.setRedraw(true);
		}
	}
	
	/**
	 * Adds the given presentation to the viewer's style information.
	 *
	 * @param presentation the presentation to be added
	 */
	private void addPresentation(TextPresentation presentation) {
		
		StyleRange range= presentation.getDefaultStyleRange();
		if (range != null) {
			
			fTextWidget.setStyleRange(range);
			Iterator e= presentation.getNonDefaultStyleRangeIterator();
			while (e.hasNext()) {
				range= (StyleRange) e.next();
				fTextWidget.setStyleRange(range);
			}
		
		} else {
			
			Iterator e= presentation.getAllStyleRangeIterator();
			
			// use optimized StyledText
			StyleRange[] ranges= new StyleRange[presentation.getDenumerableRanges()];
			for (int i= 0; i < ranges.length; i++)
				ranges[i]= (StyleRange) e.next();
				
			IRegion region= presentation.getCoverage();
			fTextWidget.replaceStyleRanges(region.getOffset(), region.getLength(), ranges);
			
//			// use unoptimized StyledText
//			while (e.hasNext()) {
//				StyleRange r= (StyleRange) e.next();
//				fTextWidget.setStyleRange(r);
//			}
			
		}	
	}
	
	/**
	 * Returns the visible region if it is not equal to the whole document.
	 * Otherwise returns <code>null</code>.
	 *
	 * @return the viewer's visible region if smaller than input document, otherwise <code>null</code>
	 */
	protected IRegion internalGetVisibleRegion() {
		
		IDocument document= getVisibleDocument();
		if (document instanceof ChildDocument) {
			Position p= ((ChildDocument) document).getParentDocumentRange();
			return new Region(p.getOffset(), p.getLength());
		}		
		
		return null;
	}
	
	/*
	 * @see ITextViewer#changeTextPresentation
	 */
	public void changeTextPresentation(TextPresentation presentation, boolean controlRedraw) {
				
		if (presentation == null)
			return;
			
		presentation.setResultWindow(internalGetVisibleRegion());
		if (presentation.isEmpty() || fTextWidget == null)
			return;
					
		if (controlRedraw)
			fTextWidget.setRedraw(false);
		
		if (fReplaceTextPresentation)
			TextPresentation.applyTextPresentation(presentation, fTextWidget);
		else
			addPresentation(presentation);
		
		if (controlRedraw)
			fTextWidget.setRedraw(true);
	}

	/*
	 * @see ITextViewer#getFindReplaceTarget()
	 */
	public IFindReplaceTarget getFindReplaceTarget() {
		if (fFindReplaceTarget == null)
			fFindReplaceTarget= new FindReplaceTarget();
		return fFindReplaceTarget;
	}

	/*
	 * @see ITextViewer#getTextOperationTarget()
	 */
	public ITextOperationTarget getTextOperationTarget() {
		return this;
	}

	/*
	 * @see ITextViewerExtension#appendVerifyKeyListener(VerifyKeyListener)
	 */
	public void appendVerifyKeyListener(VerifyKeyListener listener) {
		int index= fVerifyKeyListenersManager.numberOfListeners();
		fVerifyKeyListenersManager.insertListener(listener, index);
	}
	
	/*
	 * @see ITextViewerExtension#prependVerifyKeyListener(VerifyKeyListener)
	 */
	public void prependVerifyKeyListener(VerifyKeyListener listener) {
		fVerifyKeyListenersManager.insertListener(listener, 0);
		
	}
	
	/*
	 * @see ITextViewerExtension#removeVerifyKeyListener(VerifyKeyListener)
	 */
	public void removeVerifyKeyListener(VerifyKeyListener listener) {
		fVerifyKeyListenersManager.removeListener(listener);
	}
}
