X-Git-Url: http://secure.phpeclipse.com
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/DocumentAdapter.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/DocumentAdapter.java
new file mode 100644
index 0000000..70e1767
--- /dev/null
+++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/DocumentAdapter.java
@@ -0,0 +1,492 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpeclipse.phpeditor;
+
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import net.sourceforge.phpdt.core.BufferChangedEvent;
+import net.sourceforge.phpdt.core.IBuffer;
+import net.sourceforge.phpdt.core.IBufferChangedListener;
+import net.sourceforge.phpdt.core.IOpenable;
+import net.sourceforge.phpdt.core.JavaModelException;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.text.Assert;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.DocumentEvent;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentListener;
+import org.eclipse.jface.text.ILineTracker;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.swt.widgets.Display;
+
+
+
+/**
+ * Adapts IDocument
to IBuffer
. Uses the
+ * same algorithm as the text widget to determine the buffer's line delimiter.
+ * All text inserted into the buffer is converted to this line delimiter.
+ * This class is public
for test purposes only.
+ */
+public class DocumentAdapter implements IBuffer, IDocumentListener {
+
+ /**
+ * Internal implementation of a NULL instanceof IBuffer.
+ */
+ static private class NullBuffer implements IBuffer {
+
+ public void addBufferChangedListener(IBufferChangedListener listener) {}
+
+ public void append(char[] text) {}
+
+ public void append(String text) {}
+
+ public void close() {}
+
+ public char getChar(int position) {
+ return 0;
+ }
+
+ public char[] getCharacters() {
+ return null;
+ }
+
+ public String getContents() {
+ return null;
+ }
+
+ public int getLength() {
+ return 0;
+ }
+
+ public IOpenable getOwner() {
+ return null;
+ }
+
+ public String getText(int offset, int length) {
+ return null;
+ }
+
+ public IResource getUnderlyingResource() {
+ return null;
+ }
+
+ public boolean hasUnsavedChanges() {
+ return false;
+ }
+
+ public boolean isClosed() {
+ return false;
+ }
+
+ public boolean isReadOnly() {
+ return true;
+ }
+
+ public void removeBufferChangedListener(IBufferChangedListener listener) {}
+
+ public void replace(int position, int length, char[] text) {}
+
+ public void replace(int position, int length, String text) {}
+
+ public void save(IProgressMonitor progress, boolean force) throws JavaModelException {}
+
+ public void setContents(char[] contents) {}
+
+ public void setContents(String contents) {}
+ };
+
+
+ /** NULL implementing IBuffer
*/
+ public final static IBuffer NULL= new NullBuffer();
+
+
+ /**
+ * Executes a document set content call in the ui thread.
+ */
+ protected class DocumentSetCommand implements Runnable {
+
+ private String fContents;
+
+ public void run() {
+ fDocument.set(fContents);
+ }
+
+ public void set(String contents) {
+ fContents= contents;
+ Display.getDefault().syncExec(this);
+ }
+ };
+
+ /**
+ * Executes a document replace call in the ui thread.
+ */
+ protected class DocumentReplaceCommand implements Runnable {
+
+ private int fOffset;
+ private int fLength;
+ private String fText;
+
+ public void run() {
+ try {
+ fDocument.replace(fOffset, fLength, fText);
+ } catch (BadLocationException x) {
+ // ignore
+ }
+ }
+
+ public void replace(int offset, int length, String text) {
+ fOffset= offset;
+ fLength= length;
+ fText= text;
+ Display.getDefault().syncExec(this);
+ }
+ };
+
+ private IOpenable fOwner;
+ private IDocument fDocument;
+ private DocumentSetCommand fSetCmd= new DocumentSetCommand();
+ private DocumentReplaceCommand fReplaceCmd= new DocumentReplaceCommand();
+
+ private Object fProviderKey;
+ private PHPDocumentProvider fProvider;
+ private String fLineDelimiter;
+ private ILineTracker fLineTracker;
+
+ private List fBufferListeners= new ArrayList(3);
+
+ private IStatus fStatus;
+
+ /**
+ * This method is public
for test purposes only.
+ */
+ public DocumentAdapter(IOpenable owner, IDocument document, ILineTracker lineTracker, PHPDocumentProvider provider, Object providerKey) {
+
+ Assert.isNotNull(document);
+ Assert.isNotNull(lineTracker);
+
+ fOwner= owner;
+ fDocument= document;
+ fLineTracker= lineTracker;
+ fProvider= provider;
+ fProviderKey= providerKey;
+
+ fDocument.addPrenotifiedDocumentListener(this);
+ }
+
+ /**
+ * Sets the status of this document adapter.
+ */
+ public void setStatus(IStatus status) {
+ fStatus= status;
+ }
+
+ /**
+ * Returns the status of this document adapter.
+ */
+ public IStatus getStatus() {
+ return fStatus;
+ }
+
+ /**
+ * Returns the adapted document.
+ *
+ * @return the adapted document
+ */
+ public IDocument getDocument() {
+ return fDocument;
+ }
+
+ /**
+ * Returns the line delimiter of this buffer. As a document has a set of
+ * valid line delimiters, this set must be reduced to size 1.
+ */
+ protected String getLineDelimiter() {
+
+ if (fLineDelimiter == null) {
+
+ try {
+ fLineDelimiter= fDocument.getLineDelimiter(0);
+ } catch (BadLocationException x) {
+ }
+
+ if (fLineDelimiter == null) {
+ /*
+ * Follow up fix for: 1GF5UU0: ITPJUI:WIN2000 - "Organize Imports" in java editor inserts lines in wrong format
+ * The line delimiter must always be a legal document line delimiter.
+ */
+ String sysLineDelimiter= System.getProperty("line.separator"); //$NON-NLS-1$
+ String[] delimiters= fDocument.getLegalLineDelimiters();
+ Assert.isTrue(delimiters.length > 0);
+ for (int i= 0; i < delimiters.length; i++) {
+ if (delimiters[i].equals(sysLineDelimiter)) {
+ fLineDelimiter= sysLineDelimiter;
+ break;
+ }
+ }
+
+ if (fLineDelimiter == null) {
+ // system line delimiter is not a legal document line delimiter
+ fLineDelimiter= delimiters[0];
+ }
+ }
+ }
+
+ return fLineDelimiter;
+ }
+
+ /**
+ * Converts the given string to the line delimiter of this buffer.
+ * This method is public
for test purposes only.
+ */
+ public String normalize(String text) {
+ fLineTracker.set(text);
+
+ int lines= fLineTracker.getNumberOfLines();
+ if (lines <= 1)
+ return text;
+
+ StringBuffer buffer= new StringBuffer(text);
+
+ try {
+ IRegion previous= fLineTracker.getLineInformation(0);
+ for (int i= 1; i < lines; i++) {
+ int lastLineEnd= previous.getOffset() + previous.getLength();
+ int lineStart= fLineTracker.getLineInformation(i).getOffset();
+ fLineTracker.replace(lastLineEnd, lineStart - lastLineEnd, getLineDelimiter());
+ buffer.replace(lastLineEnd, lineStart, getLineDelimiter());
+ previous= fLineTracker.getLineInformation(i);
+ }
+
+ // last line
+ String delimiter= fLineTracker.getLineDelimiter(lines -1);
+ if (delimiter != null && delimiter.length() > 0)
+ buffer.replace(previous.getOffset() + previous.getLength(), buffer.length(), getLineDelimiter());
+
+ return buffer.toString();
+ } catch (BadLocationException x) {
+ }
+
+ return text;
+ }
+
+ /*
+ * @see IBuffer#addBufferChangedListener(IBufferChangedListener)
+ */
+ public void addBufferChangedListener(IBufferChangedListener listener) {
+ Assert.isNotNull(listener);
+ if (!fBufferListeners.contains(listener))
+ fBufferListeners.add(listener);
+ }
+
+ /*
+ * @see IBuffer#removeBufferChangedListener(IBufferChangedListener)
+ */
+ public void removeBufferChangedListener(IBufferChangedListener listener) {
+ Assert.isNotNull(listener);
+ fBufferListeners.remove(listener);
+ }
+
+ /*
+ * @see IBuffer#append(char[])
+ */
+ public void append(char[] text) {
+ append(new String(text));
+ }
+
+ /*
+ * @see IBuffer#append(String)
+ */
+ public void append(String text) {
+ fReplaceCmd.replace(fDocument.getLength(), 0, normalize(text));
+ }
+
+ /*
+ * @see IBuffer#close()
+ */
+ public void close() {
+
+ if (isClosed())
+ return;
+
+ IDocument d= fDocument;
+ fDocument= null;
+ d.removePrenotifiedDocumentListener(this);
+
+ fireBufferChanged(new BufferChangedEvent(this, 0, 0, null));
+ fBufferListeners.clear();
+ }
+
+ /*
+ * @see IBuffer#getChar(int)
+ */
+ public char getChar(int position) {
+ try {
+ return fDocument.getChar(position);
+ } catch (BadLocationException x) {
+ throw new ArrayIndexOutOfBoundsException();
+ }
+ }
+
+ /*
+ * @see IBuffer#getCharacters()
+ */
+ public char[] getCharacters() {
+ String content= getContents();
+ return content == null ? null : content.toCharArray();
+ }
+
+ /*
+ * @see IBuffer#getContents()
+ */
+ public String getContents() {
+ return fDocument.get();
+ }
+
+ /*
+ * @see IBuffer#getLength()
+ */
+ public int getLength() {
+ return fDocument.getLength();
+ }
+
+ /*
+ * @see IBuffer#getOwner()
+ */
+ public IOpenable getOwner() {
+ return (IOpenable) fOwner;
+ }
+
+ /*
+ * @see IBuffer#getText(int, int)
+ */
+ public String getText(int offset, int length) {
+ try {
+ return fDocument.get(offset, length);
+ } catch (BadLocationException x) {
+ throw new ArrayIndexOutOfBoundsException();
+ }
+ }
+
+ /*
+ * @see IBuffer#getUnderlyingResource()
+ */
+ public IResource getUnderlyingResource() {
+ return fProvider != null ? fProvider.getUnderlyingResource(fProviderKey) : null;
+ }
+
+ /*
+ * @see IBuffer#hasUnsavedChanges()
+ */
+ public boolean hasUnsavedChanges() {
+ return fProvider != null ? fProvider.canSaveDocument(fProviderKey) : false;
+ }
+
+ /*
+ * @see IBuffer#isClosed()
+ */
+ public boolean isClosed() {
+ return fDocument == null;
+ }
+
+ /*
+ * @see IBuffer#isReadOnly()
+ */
+ public boolean isReadOnly() {
+ IResource resource= getUnderlyingResource();
+ return resource == null ? true : resource.isReadOnly();
+ }
+
+ /*
+ * @see IBuffer#replace(int, int, char[])
+ */
+ public void replace(int position, int length, char[] text) {
+ replace(position, length, new String(text));
+ }
+
+ /*
+ * @see IBuffer#replace(int, int, String)
+ */
+ public void replace(int position, int length, String text) {
+ fReplaceCmd.replace(position, length, normalize(text));
+ }
+
+ /*
+ * @see IBuffer#save(IProgressMonitor, boolean)
+ */
+ public void save(IProgressMonitor progress, boolean force) throws JavaModelException {
+ if (fProvider != null) {
+ try {
+ fProvider.saveDocumentContent(progress, fProviderKey, fDocument, force);
+ } catch (CoreException e) {
+ throw new JavaModelException(e);
+ }
+ }
+ }
+
+ /*
+ * @see IBuffer#setContents(char[])
+ */
+ public void setContents(char[] contents) {
+ setContents(new String(contents));
+ }
+
+ /*
+ * @see IBuffer#setContents(String)
+ */
+ public void setContents(String contents) {
+ int oldLength= fDocument.getLength();
+
+ if (contents == null) {
+
+ if (oldLength != 0)
+ fSetCmd.set(""); //$NON-NLS-1$
+
+ } else {
+
+ // set only if different
+ String newContents= normalize(contents);
+ int newLength= newContents.length();
+
+ if (oldLength != newLength || !newContents.equals(fDocument.get()))
+ fSetCmd.set(newContents);
+ }
+ }
+
+ /*
+ * @see IDocumentListener#documentAboutToBeChanged(DocumentEvent)
+ */
+ public void documentAboutToBeChanged(DocumentEvent event) {
+ // there is nothing to do here
+ }
+
+ /*
+ * @see IDocumentListener#documentChanged(DocumentEvent)
+ */
+ public void documentChanged(DocumentEvent event) {
+ fireBufferChanged(new BufferChangedEvent(this, event.getOffset(), event.getLength(), event.getText()));
+ }
+
+ private void fireBufferChanged(BufferChangedEvent event) {
+ if (fBufferListeners != null && fBufferListeners.size() > 0) {
+ Iterator e= new ArrayList(fBufferListeners).iterator();
+ while (e.hasNext())
+ ((IBufferChangedListener) e.next()).bufferChanged(event);
+ }
+ }
+}