X-Git-Url: http://git.phpeclipse.com diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/Buffer.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/Buffer.java index c26691d..832144f 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/Buffer.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/Buffer.java @@ -20,410 +20,468 @@ import net.sourceforge.phpdt.core.IBufferChangedListener; import net.sourceforge.phpdt.core.IJavaModelStatusConstants; import net.sourceforge.phpdt.core.IOpenable; import net.sourceforge.phpdt.core.JavaModelException; +import net.sourceforge.phpdt.internal.core.util.Util; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.ISafeRunnable; -import org.eclipse.core.runtime.Platform; +//import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.SafeRunner; /** * @see IBuffer */ public class Buffer implements IBuffer { protected IFile file; + protected int flags; + protected char[] contents; + protected ArrayList changeListeners; + protected IOpenable owner; - protected int gapStart= -1; - protected int gapEnd= -1; - protected Object lock= new Object(); + protected int gapStart = -1; - protected static final int F_HAS_UNSAVED_CHANGES= 1; - protected static final int F_IS_READ_ONLY= 2; - protected static final int F_IS_CLOSED= 4; + protected int gapEnd = -1; -/** - * Creates a new buffer on an underlying resource. - */ -protected Buffer(IFile file, IOpenable owner, boolean readOnly) { - this.file = file; - this.owner = owner; - if (file == null) { - setReadOnly(readOnly); + protected Object lock = new Object(); + + protected static final int F_HAS_UNSAVED_CHANGES = 1; + + protected static final int F_IS_READ_ONLY = 2; + + protected static final int F_IS_CLOSED = 4; + + /** + * Creates a new buffer on an underlying resource. + */ + protected Buffer(IFile file, IOpenable owner, boolean readOnly) { + this.file = file; + this.owner = owner; + if (file == null) { + setReadOnly(readOnly); + } } -} -/** - * @see IBuffer - */ -public void addBufferChangedListener(IBufferChangedListener listener) { - if (this.changeListeners == null) { - this.changeListeners = new ArrayList(5); + + /** + * @see IBuffer + */ + public void addBufferChangedListener(IBufferChangedListener listener) { + if (this.changeListeners == null) { + this.changeListeners = new ArrayList(5); + } + if (!this.changeListeners.contains(listener)) { + this.changeListeners.add(listener); + } } - if (!this.changeListeners.contains(listener)) { - this.changeListeners.add(listener); + + /** + * Append the text to the actual content, the gap is moved to + * the end of the text. + */ + public void append(char[] text) { + if (!isReadOnly()) { + if (text == null || text.length == 0) { + return; + } + int length = getLength(); + moveAndResizeGap(length, text.length); + System.arraycopy(text, 0, this.contents, length, text.length); + this.gapStart += text.length; + this.flags |= F_HAS_UNSAVED_CHANGES; + notifyChanged(new BufferChangedEvent(this, length, 0, new String( + text))); + } } -} -/** - * Append the text to the actual content, the gap is moved - * to the end of the text. - */ -public void append(char[] text) { - if (!isReadOnly()) { - if (text == null || text.length == 0) { + + /** + * Append the text to the actual content, the gap is moved to + * the end of the text. + */ + public void append(String text) { + if (text == null) { return; } - int length = getLength(); - moveAndResizeGap(length, text.length); - System.arraycopy(text, 0, this.contents, length, text.length); - this.gapStart += text.length; - this.flags |= F_HAS_UNSAVED_CHANGES; - notifyChanged(new BufferChangedEvent(this, length, 0, new String(text))); + this.append(text.toCharArray()); } -} -/** - * Append the text to the actual content, the gap is moved - * to the end of the text. - */ -public void append(String text) { - if (text == null) { - return; + + /** + * @see IBuffer + */ + public void close() throws IllegalArgumentException { + BufferChangedEvent event = null; + synchronized (this.lock) { + if (isClosed()) + return; + event = new BufferChangedEvent(this, 0, 0, null); + this.contents = null; + this.flags |= F_IS_CLOSED; + } + notifyChanged(event); // notify outside of synchronized block + this.changeListeners = null; } - this.append(text.toCharArray()); -} -/** - * @see IBuffer - */ -public void close() throws IllegalArgumentException { - BufferChangedEvent event = null; - synchronized (this.lock) { - if (isClosed()) - return; - event = new BufferChangedEvent(this, 0, 0, null); - this.contents = null; - this.flags |= F_IS_CLOSED; + + /** + * @see IBuffer + */ + public char getChar(int position) { + synchronized (this.lock) { + if (position < this.gapStart) { + return this.contents[position]; + } + int gapLength = this.gapEnd - this.gapStart; + return this.contents[position + gapLength]; + } } - notifyChanged(event); // notify outside of synchronized block - this.changeListeners = null; -} -/** - * @see IBuffer - */ -public char getChar(int position) { - synchronized (this.lock) { - if (position < this.gapStart) { - return this.contents[position]; + + /** + * @see IBuffer + */ + public char[] getCharacters() { + if (this.contents == null) + return null; + synchronized (this.lock) { + if (this.gapStart < 0) { + return this.contents; + } + int length = this.contents.length; + char[] newContents = new char[length - this.gapEnd + this.gapStart]; + System.arraycopy(this.contents, 0, newContents, 0, this.gapStart); + System.arraycopy(this.contents, this.gapEnd, newContents, + this.gapStart, length - this.gapEnd); + return newContents; } - int gapLength = this.gapEnd - this.gapStart; - return this.contents[position + gapLength]; } -} -/** - * @see IBuffer - */ -public char[] getCharacters() { - if (this.contents == null) return null; - synchronized (this.lock) { - if (this.gapStart < 0) { - return this.contents; + + /** + * @see IBuffer + */ + public String getContents() { + char[] chars = this.getCharacters(); + if (chars == null) + return null; + return new String(chars); + } + + /** + * @see IBuffer + */ + public int getLength() { + synchronized (this.lock) { + int length = this.gapEnd - this.gapStart; + return (this.contents.length - length); } - int length = this.contents.length; - char[] newContents = new char[length - this.gapEnd + this.gapStart]; - System.arraycopy(this.contents, 0, newContents, 0, this.gapStart); - System.arraycopy(this.contents, this.gapEnd, newContents, this.gapStart, length - this.gapEnd); - return newContents; } -} -/** - * @see IBuffer - */ -public String getContents() { - char[] chars = this.getCharacters(); - if (chars == null) return null; - return new String(chars); -} -/** - * @see IBuffer - */ -public int getLength() { - synchronized (this.lock) { - int length = this.gapEnd - this.gapStart; - return (this.contents.length - length); + + /** + * @see IBuffer + */ + public IOpenable getOwner() { + return this.owner; } -} -/** - * @see IBuffer - */ -public IOpenable getOwner() { - return this.owner; -} -/** - * @see IBuffer - */ -public String getText(int offset, int length) { - if (this.contents == null) - return ""; //$NON-NLS-1$ - synchronized (this.lock) { - if (offset + length < this.gapStart) - return new String(this.contents, offset, length); - if (this.gapStart < offset) { - int gapLength = this.gapEnd - this.gapStart; - return new String(this.contents, offset + gapLength, length); + + /** + * @see IBuffer + */ + public String getText(int offset, int length) { + if (this.contents == null) + return ""; //$NON-NLS-1$ + synchronized (this.lock) { + if (offset + length < this.gapStart) + return new String(this.contents, offset, length); + if (this.gapStart < offset) { + int gapLength = this.gapEnd - this.gapStart; + return new String(this.contents, offset + gapLength, length); + } + StringBuffer buf = new StringBuffer(); + buf.append(this.contents, offset, this.gapStart - offset); + buf.append(this.contents, this.gapEnd, offset + length + - this.gapStart); + return buf.toString(); } - StringBuffer buf = new StringBuffer(); - buf.append(this.contents, offset, this.gapStart - offset); - buf.append(this.contents, this.gapEnd, offset + length - this.gapStart); - return buf.toString(); } -} -/** - * @see IBuffer - */ -public IResource getUnderlyingResource() { - return this.file; -} -/** - * @see IBuffer - */ -public boolean hasUnsavedChanges() { - return (this.flags & F_HAS_UNSAVED_CHANGES) != 0; -} -/** - * @see IBuffer - */ -public boolean isClosed() { - return (this.flags & F_IS_CLOSED) != 0; -} -/** - * @see IBuffer - */ -public boolean isReadOnly() { - if (this.file == null) { - return (this.flags & F_IS_READ_ONLY) != 0; - } else { - return this.file.isReadOnly(); + + /** + * @see IBuffer + */ + public IResource getUnderlyingResource() { + return this.file; } -} -/** - * Moves the gap to location and adjust its size to the - * anticipated change size. The size represents the expected - * range of the gap that will be filled after the gap has been moved. - * Thus the gap is resized to actual size + the specified size and - * moved to the given position. - */ -protected void moveAndResizeGap(int position, int size) { - char[] content = null; - int oldSize = this.gapEnd - this.gapStart; - if (size < 0) { - if (oldSize > 0) { - content = new char[this.contents.length - oldSize]; - System.arraycopy(this.contents, 0, content, 0, this.gapStart); - System.arraycopy(this.contents, this.gapEnd, content, this.gapStart, content.length - this.gapStart); - this.contents = content; + + /** + * @see IBuffer + */ + public boolean hasUnsavedChanges() { + return (this.flags & F_HAS_UNSAVED_CHANGES) != 0; + } + + /** + * @see IBuffer + */ + public boolean isClosed() { + return (this.flags & F_IS_CLOSED) != 0; + } + + /** + * @see IBuffer + */ + public boolean isReadOnly() { + if (this.file == null) { + return (this.flags & F_IS_READ_ONLY) != 0; + } else { + return this.file.isReadOnly(); } - this.gapStart = this.gapEnd = position; - return; } - content = new char[this.contents.length + (size - oldSize)]; - int newGapStart = position; - int newGapEnd = newGapStart + size; - if (oldSize == 0) { - System.arraycopy(this.contents, 0, content, 0, newGapStart); - System.arraycopy(this.contents, newGapStart, content, newGapEnd, content.length - newGapEnd); - } else - if (newGapStart < this.gapStart) { + + /** + * Moves the gap to location and adjust its size to the anticipated change + * size. The size represents the expected range of the gap that will be + * filled after the gap has been moved. Thus the gap is resized to actual + * size + the specified size and moved to the given position. + */ + protected void moveAndResizeGap(int position, int size) { + char[] content = null; + int oldSize = this.gapEnd - this.gapStart; + if (size < 0) { + if (oldSize > 0) { + content = new char[this.contents.length - oldSize]; + System.arraycopy(this.contents, 0, content, 0, this.gapStart); + System.arraycopy(this.contents, this.gapEnd, content, + this.gapStart, content.length - this.gapStart); + this.contents = content; + } + this.gapStart = this.gapEnd = position; + return; + } + content = new char[this.contents.length + (size - oldSize)]; + int newGapStart = position; + int newGapEnd = newGapStart + size; + if (oldSize == 0) { + System.arraycopy(this.contents, 0, content, 0, newGapStart); + System.arraycopy(this.contents, newGapStart, content, newGapEnd, + content.length - newGapEnd); + } else if (newGapStart < this.gapStart) { int delta = this.gapStart - newGapStart; System.arraycopy(this.contents, 0, content, 0, newGapStart); - System.arraycopy(this.contents, newGapStart, content, newGapEnd, delta); - System.arraycopy(this.contents, this.gapEnd, content, newGapEnd + delta, this.contents.length - this.gapEnd); + System.arraycopy(this.contents, newGapStart, content, newGapEnd, + delta); + System.arraycopy(this.contents, this.gapEnd, content, newGapEnd + + delta, this.contents.length - this.gapEnd); } else { int delta = newGapStart - this.gapStart; System.arraycopy(this.contents, 0, content, 0, this.gapStart); - System.arraycopy(this.contents, this.gapEnd, content, this.gapStart, delta); - System.arraycopy(this.contents, this.gapEnd + delta, content, newGapEnd, content.length - newGapEnd); + System.arraycopy(this.contents, this.gapEnd, content, + this.gapStart, delta); + System.arraycopy(this.contents, this.gapEnd + delta, content, + newGapEnd, content.length - newGapEnd); } - this.contents = content; - this.gapStart = newGapStart; - this.gapEnd = newGapEnd; -} -/** - * Notify the listeners that this buffer has changed. - * To avoid deadlock, this should not be called in a synchronized block. - */ -protected void notifyChanged(final BufferChangedEvent event) { - if (this.changeListeners != null) { - for (int i = 0, size = this.changeListeners.size(); i < size; ++i) { - final IBufferChangedListener listener = (IBufferChangedListener) this.changeListeners.get(i); - Platform.run(new ISafeRunnable() { - public void handleException(Throwable exception) { - Util.log(exception, "Exception occurred in listener of buffer change notification"); //$NON-NLS-1$ - } - public void run() throws Exception { - listener.bufferChanged(event); - } - }); - + this.contents = content; + this.gapStart = newGapStart; + this.gapEnd = newGapEnd; + } + + /** + * Notify the listeners that this buffer has changed. To avoid deadlock, + * this should not be called in a synchronized block. + */ + protected void notifyChanged(final BufferChangedEvent event) { + if (this.changeListeners != null) { + for (int i = 0, size = this.changeListeners.size(); i < size; ++i) { + final IBufferChangedListener listener = (IBufferChangedListener) this.changeListeners + .get(i); + SafeRunner.run(new ISafeRunnable() { + public void handleException(Throwable exception) { + Util + .log(exception, + "Exception occurred in listener of buffer change notification"); //$NON-NLS-1$ + } + + public void run() throws Exception { + listener.bufferChanged(event); + } + }); + + } } } -} -/** - * @see IBuffer - */ -public void removeBufferChangedListener(IBufferChangedListener listener) { - if (this.changeListeners != null) { - this.changeListeners.remove(listener); - if (this.changeListeners.size() == 0) { - this.changeListeners = null; + + /** + * @see IBuffer + */ + public void removeBufferChangedListener(IBufferChangedListener listener) { + if (this.changeListeners != null) { + this.changeListeners.remove(listener); + if (this.changeListeners.size() == 0) { + this.changeListeners = null; + } } } -} -/** - * Replaces length characters starting from position with text. - * After that operation, the gap is placed at the end of the - * inserted text. - */ -public void replace(int position, int length, char[] text) { - if (!isReadOnly()) { - int textLength = text == null ? 0 : text.length; - synchronized (this.lock) { - // move gap - moveAndResizeGap(position + length, textLength - length); - // overwrite - int min = Math.min(textLength, length); - if (min > 0) { - System.arraycopy(text, 0, this.contents, position, min); + /** + * Replaces length characters starting from + * position with text. + * After that operation, the gap is placed at the end of the + * inserted text. + */ + public void replace(int position, int length, char[] text) { + if (!isReadOnly()) { + int textLength = text == null ? 0 : text.length; + synchronized (this.lock) { + // move gap + moveAndResizeGap(position + length, textLength - length); + + // overwrite + int min = Math.min(textLength, length); + if (min > 0) { + System.arraycopy(text, 0, this.contents, position, min); + } + if (length > textLength) { + // enlarge the gap + this.gapStart -= length - textLength; + } else if (textLength > length) { + // shrink gap + this.gapStart += textLength - length; + System.arraycopy(text, 0, this.contents, position, + textLength); + } } - if (length > textLength) { - // enlarge the gap - this.gapStart -= length - textLength; - } else if (textLength > length) { - // shrink gap - this.gapStart += textLength - length; - System.arraycopy(text, 0, this.contents, position, textLength); + this.flags |= F_HAS_UNSAVED_CHANGES; + String string = null; + if (textLength > 0) { + string = new String(text); } + notifyChanged(new BufferChangedEvent(this, position, length, string)); } - this.flags |= F_HAS_UNSAVED_CHANGES; - String string = null; - if (textLength > 0) { - string = new String(text); - } - notifyChanged(new BufferChangedEvent(this, position, length, string)); } -} -/** - * Replaces length characters starting from position with text. - * After that operation, the gap is placed at the end of the - * inserted text. - */ -public void replace(int position, int length, String text) { - this.replace(position, length, text == null ? null : text.toCharArray()); -} -/** - * @see IBuffer - */ -public void save(IProgressMonitor progress, boolean force) throws JavaModelException { - // determine if saving is required - if (isReadOnly() || this.file == null) { - return; + /** + * Replaces length characters starting from + * position with text. + * After that operation, the gap is placed at the end of the + * inserted text. + */ + public void replace(int position, int length, String text) { + this + .replace(position, length, text == null ? null : text + .toCharArray()); } - synchronized (this.lock) { - if (!hasUnsavedChanges()) + + /** + * @see IBuffer + */ + public void save(IProgressMonitor progress, boolean force) + throws JavaModelException { + + // determine if saving is required + if (isReadOnly() || this.file == null) { return; - - // use a platform operation to update the resource contents - try { -// String encoding = ((IJavaElement)this.owner).getJavaProject().getOption(PHPCore.CORE_ENCODING, true); - String encoding = null; - String contents = this.getContents(); - if (contents == null) return; - byte[] bytes = encoding == null - ? contents.getBytes() - : contents.getBytes(encoding); - ByteArrayInputStream stream = new ByteArrayInputStream(bytes); - - this.file.setContents( - stream, - force ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY, - null); - } catch (IOException e) { - throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION); - } catch (CoreException e) { - throw new JavaModelException(e); } + synchronized (this.lock) { + if (!hasUnsavedChanges()) + return; - // the resource no longer has unsaved changes - this.flags &= ~ (F_HAS_UNSAVED_CHANGES); - } -} -/** - * @see IBuffer - */ -public void setContents(char[] newContents) { - // allow special case for first initialization - // after creation by buffer factory - if (this.contents == null) { - this.contents = newContents; - this.flags &= ~ (F_HAS_UNSAVED_CHANGES); - return; - } - - if (!isReadOnly()) { - String string = null; - if (newContents != null) { - string = new String(newContents); + // use a platform operation to update the resource contents + try { + // String encoding = + // ((IJavaElement)this.owner).getJavaProject().getOption(PHPCore.CORE_ENCODING, + // true); + String encoding = null; + String contents = this.getContents(); + if (contents == null) + return; + byte[] bytes = encoding == null ? contents.getBytes() + : contents.getBytes(encoding); + ByteArrayInputStream stream = new ByteArrayInputStream(bytes); + + this.file + .setContents(stream, force ? IResource.FORCE + | IResource.KEEP_HISTORY + : IResource.KEEP_HISTORY, null); + } catch (IOException e) { + throw new JavaModelException(e, + IJavaModelStatusConstants.IO_EXCEPTION); + } catch (CoreException e) { + throw new JavaModelException(e); + } + + // the resource no longer has unsaved changes + this.flags &= ~(F_HAS_UNSAVED_CHANGES); } - BufferChangedEvent event = new BufferChangedEvent(this, 0, this.getLength(), string); - synchronized (this.lock) { + } + + /** + * @see IBuffer + */ + public void setContents(char[] newContents) { + // allow special case for first initialization + // after creation by buffer factory + if (this.contents == null) { this.contents = newContents; - this.flags |= F_HAS_UNSAVED_CHANGES; - this.gapStart = -1; - this.gapEnd = -1; + this.flags &= ~(F_HAS_UNSAVED_CHANGES); + return; + } + + if (!isReadOnly()) { + String string = null; + if (newContents != null) { + string = new String(newContents); + } + BufferChangedEvent event = new BufferChangedEvent(this, 0, this + .getLength(), string); + synchronized (this.lock) { + this.contents = newContents; + this.flags |= F_HAS_UNSAVED_CHANGES; + this.gapStart = -1; + this.gapEnd = -1; + } + notifyChanged(event); } - notifyChanged(event); } -} -/** - * @see IBuffer - */ -public void setContents(String newContents) { - this.setContents(newContents.toCharArray()); -} -/** - * Sets this Buffer to be read only. - */ -protected void setReadOnly(boolean readOnly) { - if (readOnly) { - this.flags |= F_IS_READ_ONLY; - } else { - this.flags &= ~(F_IS_READ_ONLY); + + /** + * @see IBuffer + */ + public void setContents(String newContents) { + this.setContents(newContents.toCharArray()); } -} -public String toString() { - StringBuffer buffer = new StringBuffer(); -// buffer.append("Owner: " + ((JavaElement)this.owner).toStringWithAncestors()); //$NON-NLS-1$ - buffer.append("Owner: " + (this.owner).toString()); //$NON-NLS-1$ - buffer.append("\nHas unsaved changes: " + this.hasUnsavedChanges()); //$NON-NLS-1$ - buffer.append("\nIs readonly: " + this.isReadOnly()); //$NON-NLS-1$ - buffer.append("\nIs closed: " + this.isClosed()); //$NON-NLS-1$ - buffer.append("\nContents:\n"); //$NON-NLS-1$ - char[] contents = this.getCharacters(); - if (contents == null) { - buffer.append(""); //$NON-NLS-1$ - } else { - int length = contents.length; - for (int i = 0; i < length; i++) { - char car = contents[i]; - switch (car) { - case '\n': + + /** + * Sets this Buffer to be read only. + */ + protected void setReadOnly(boolean readOnly) { + if (readOnly) { + this.flags |= F_IS_READ_ONLY; + } else { + this.flags &= ~(F_IS_READ_ONLY); + } + } + + public String toString() { + StringBuffer buffer = new StringBuffer(); + // buffer.append("Owner: " + + // ((JavaElement)this.owner).toStringWithAncestors()); //$NON-NLS-1$ + buffer.append("Owner: " + (this.owner).toString()); //$NON-NLS-1$ + buffer.append("\nHas unsaved changes: " + this.hasUnsavedChanges()); //$NON-NLS-1$ + buffer.append("\nIs readonly: " + this.isReadOnly()); //$NON-NLS-1$ + buffer.append("\nIs closed: " + this.isClosed()); //$NON-NLS-1$ + buffer.append("\nContents:\n"); //$NON-NLS-1$ + char[] contents = this.getCharacters(); + if (contents == null) { + buffer.append(""); //$NON-NLS-1$ + } else { + int length = contents.length; + for (int i = 0; i < length; i++) { + char car = contents[i]; + switch (car) { + case '\n': buffer.append("\\n\n"); //$NON-NLS-1$ break; case '\r': - if (i < length-1 && this.contents[i+1] == '\n') { + if (i < length - 1 && this.contents[i + 1] == '\n') { buffer.append("\\r\\n\n"); //$NON-NLS-1$ i++; } else { @@ -433,9 +491,9 @@ public String toString() { default: buffer.append(car); break; + } } } + return buffer.toString(); } - return buffer.toString(); -} }