|
What this is
Other links
The source code/* * Buffer.java - jEdit buffer * :tabSize=8:indentSize=8:noTabs=false: * :folding=explicit:collapseFolds=1: * * Copyright (C) 1998, 2004 Slava Pestov * Portions copyright (C) 1999, 2000 mike dillon * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package org.gjt.sp.jedit; //{{{ Imports import gnu.regexp.*; import javax.swing.*; import javax.swing.text.*; import java.awt.Toolkit; import java.io.File; import java.io.IOException; import java.net.Socket; import java.util.*; import org.gjt.sp.jedit.browser.VFSBrowser; import org.gjt.sp.jedit.buffer.*; import org.gjt.sp.jedit.io.*; import org.gjt.sp.jedit.msg.*; import org.gjt.sp.jedit.search.RESearchMatcher; import org.gjt.sp.jedit.syntax.*; import org.gjt.sp.jedit.textarea.*; import org.gjt.sp.util.*; //}}} /** * A
NOT_CHANGED , CHANGED , or
* DELETED .
*
* @since jEdit 4.2pre1
*/
public int checkFileStatus(View view)
{
// - don't do these checks while a save is in progress,
// because for a moment newModTime will be greater than
// oldModTime, due to the multithreading
// - only supported on local file system
if(!getFlag(IO) && !getFlag(LOADING) && file != null
&& !getFlag(NEW_FILE))
{
boolean newReadOnly = (file.exists() && !file.canWrite());
if(newReadOnly != getFlag(READ_ONLY))
{
setFlag(READ_ONLY,newReadOnly);
EditBus.send(new BufferUpdate(this,null,
BufferUpdate.DIRTY_CHANGED));
}
long oldModTime = modTime;
long newModTime = file.lastModified();
if(newModTime != oldModTime)
{
modTime = newModTime;
if(!file.exists())
{
setFlag(NEW_FILE,true);
setDirty(true);
return FILE_DELETED;
}
else
{
return FILE_CHANGED;
}
}
}
return FILE_NOT_CHANGED;
} //}}}
//}}}
//{{{ Getters/setter methods for various buffer meta-data
//{{{ getLastModified() method
/**
* Returns the last time jEdit modified the file on disk.
* This method is thread-safe.
*/
public long getLastModified()
{
return modTime;
} //}}}
//{{{ setLastModified() method
/**
* Sets the last time jEdit modified the file on disk.
* @param modTime The new modification time
*/
public void setLastModified(long modTime)
{
this.modTime = modTime;
} //}}}
//{{{ getVFS() method
/**
* Returns the virtual filesystem responsible for loading and
* saving this buffer. This method is thread-safe.
*/
public VFS getVFS()
{
return VFSManager.getVFSForPath(path);
} //}}}
//{{{ getAutosaveFile() method
/**
* Returns the autosave file for this buffer. This may be null if
* the file is non-local.
*/
public File getAutosaveFile()
{
return autosaveFile;
} //}}}
//{{{ getName() method
/**
* Returns the name of this buffer. This method is thread-safe.
*/
public String getName()
{
return name;
} //}}}
//{{{ getPath() method
/**
* Returns the path name of this buffer. This method is thread-safe.
*/
public String getPath()
{
return path;
} //}}}
//{{{ getSymlinkPath() method
/**
* If this file is a symbolic link, returns the link destination.
* Otherwise returns the file's path. This method is thread-safe.
* @since jEdit 4.2pre1
*/
public String getSymlinkPath()
{
return symlinkPath;
} //}}}
//{{{ getDirectory() method
/**
* Returns the directory containing this buffer.
* @since jEdit 4.1pre11
*/
public String getDirectory()
{
return directory;
} //}}}
//{{{ isClosed() method
/**
* Returns true if this buffer has been closed with
* {@link org.gjt.sp.jedit.jEdit#closeBuffer(View,Buffer)}.
* This method is thread-safe.
*/
public boolean isClosed()
{
return getFlag(CLOSED);
} //}}}
//{{{ isLoaded() method
/**
* Returns true if the buffer is loaded. This method is thread-safe.
*/
public boolean isLoaded()
{
return !getFlag(LOADING);
} //}}}
//{{{ isPerformingIO() method
/**
* Returns true if the buffer is currently performing I/O.
* This method is thread-safe.
* @since jEdit 2.7pre1
*/
public boolean isPerformingIO()
{
return getFlag(LOADING) || getFlag(IO);
} //}}}
//{{{ isNewFile() method
/**
* Returns whether this buffer lacks a corresponding version on disk.
* This method is thread-safe.
*/
public boolean isNewFile()
{
return getFlag(NEW_FILE);
} //}}}
//{{{ setNewFile() method
/**
* Sets the new file flag.
* @param newFile The new file flag
*/
public void setNewFile(boolean newFile)
{
setFlag(NEW_FILE,newFile);
if(!newFile)
setFlag(UNTITLED,false);
} //}}}
//{{{ isUntitled() method
/**
* Returns true if this file is 'untitled'. This method is thread-safe.
*/
public boolean isUntitled()
{
return getFlag(UNTITLED);
} //}}}
//{{{ isDirty() method
/**
* Returns whether there have been unsaved changes to this buffer.
* This method is thread-safe.
*/
public boolean isDirty()
{
return getFlag(DIRTY);
} //}}}
//{{{ isReadOnly() method
/**
* Returns true if this file is read only, false otherwise.
* This method is thread-safe.
*/
public boolean isReadOnly()
{
return getFlag(READ_ONLY) || getFlag(READ_ONLY_OVERRIDE);
} //}}}
//{{{ isEditable() method
/**
* Returns true if this file is editable, false otherwise. A file may
* become uneditable if it is read only, or if I/O is in progress.
* This method is thread-safe.
* @since jEdit 2.7pre1
*/
public boolean isEditable()
{
return !(getFlag(READ_ONLY) || getFlag(READ_ONLY_OVERRIDE)
|| getFlag(IO) || getFlag(LOADING));
} //}}}
//{{{ setReadOnly() method
/**
* Sets the read only flag.
* @param readOnly The read only flag
*/
public void setReadOnly(boolean readOnly)
{
setFlag(READ_ONLY_OVERRIDE,readOnly);
} //}}}
//{{{ setDirty() method
/**
* Sets the 'dirty' (changed since last save) flag of this buffer.
*/
public void setDirty(boolean d)
{
boolean old_d = getFlag(DIRTY);
boolean editable = isEditable();
if(d)
{
if(editable)
{
setFlag(DIRTY,true);
setFlag(AUTOSAVE_DIRTY,true);
}
}
else
{
setFlag(DIRTY,false);
setFlag(AUTOSAVE_DIRTY,false);
if(autosaveFile != null)
autosaveFile.delete();
// fixes dirty flag not being reset on
// save/insert/undo/redo/undo
if(!getFlag(UNDO_IN_PROGRESS))
{
// this ensures that undo can clear the dirty flag properly
// when all edits up to a save are undone
undoMgr.bufferSaved();
}
}
if(d != old_d && editable)
{
EditBus.send(new BufferUpdate(this,null,
BufferUpdate.DIRTY_CHANGED));
}
} //}}}
//{{{ isTemporary() method
/**
* Returns if this is a temporary buffer. This method is thread-safe.
* @see jEdit#openTemporary(View,String,String,boolean)
* @see jEdit#commitTemporary(Buffer)
* @since jEdit 2.2pre7
*/
public boolean isTemporary()
{
return getFlag(TEMPORARY);
} //}}}
//{{{ getIcon() method
/**
* Returns this buffer's icon.
* @since jEdit 2.6pre6
*/
public Icon getIcon()
{
if(getFlag(DIRTY))
return GUIUtilities.loadIcon("dirty.gif");
else if(getFlag(READ_ONLY) || getFlag(READ_ONLY_OVERRIDE))
return GUIUtilities.loadIcon("readonly.gif");
else if(getFlag(NEW_FILE))
return GUIUtilities.loadIcon("new.gif");
else
return GUIUtilities.loadIcon("normal.gif");
} //}}}
//}}}
//{{{ Thread safety
//{{{ readLock() method
/**
* The buffer is guaranteed not to change between calls to
* {@link #readLock()} and {@link #readUnlock()}.
*/
public void readLock()
{
lock.readLock();
} //}}}
//{{{ readUnlock() method
/**
* The buffer is guaranteed not to change between calls to
* {@link #readLock()} and {@link #readUnlock()}.
*/
public void readUnlock()
{
lock.readUnlock();
} //}}}
//{{{ writeLock() method
/**
* Attempting to obtain read lock will block between calls to
* {@link #writeLock()} and {@link #writeUnlock()}.
*/
public void writeLock()
{
lock.writeLock();
} //}}}
//{{{ writeUnlock() method
/**
* Attempting to obtain read lock will block between calls to
* {@link #writeLock()} and {@link #writeUnlock()}.
*/
public void writeUnlock()
{
lock.writeUnlock();
} //}}}
//}}}
//{{{ Line offset methods
//{{{ getLength() method
/**
* Returns the number of characters in the buffer. This method is thread-safe.
*/
public int getLength()
{
// no need to lock since this just returns a value and that's it
return contentMgr.getLength();
} //}}}
//{{{ getLineCount() method
/**
* Returns the number of physical lines in the buffer.
* This method is thread-safe.
* @since jEdit 3.1pre1
*/
public int getLineCount()
{
// no need to lock since this just returns a value and that's it
return lineMgr.getLineCount();
} //}}}
//{{{ getLineOfOffset() method
/**
* Returns the line containing the specified offset.
* This method is thread-safe.
* @param offset The offset
* @since jEdit 4.0pre1
*/
public int getLineOfOffset(int offset)
{
try
{
readLock();
if(offset < 0 || offset > getLength())
throw new ArrayIndexOutOfBoundsException(offset);
return lineMgr.getLineOfOffset(offset);
}
finally
{
readUnlock();
}
} //}}}
//{{{ getLineStartOffset() method
/**
* Returns the start offset of the specified line.
* This method is thread-safe.
* @param line The line
* @return The start offset of the specified line
* @since jEdit 4.0pre1
*/
public int getLineStartOffset(int line)
{
try
{
readLock();
if(line < 0 || line >= lineMgr.getLineCount())
throw new ArrayIndexOutOfBoundsException(line);
else if(line == 0)
return 0;
return lineMgr.getLineEndOffset(line - 1);
}
finally
{
readUnlock();
}
} //}}}
//{{{ getLineEndOffset() method
/**
* Returns the end offset of the specified line.
* This method is thread-safe.
* @param line The line
* @return The end offset of the specified line
* invalid.
* @since jEdit 4.0pre1
*/
public int getLineEndOffset(int line)
{
try
{
readLock();
if(line < 0 || line >= lineMgr.getLineCount())
throw new ArrayIndexOutOfBoundsException(line);
return lineMgr.getLineEndOffset(line);
}
finally
{
readUnlock();
}
} //}}}
//{{{ getLineLength() method
/**
* Returns the length of the specified line.
* This method is thread-safe.
* @param line The line
* @since jEdit 4.0pre1
*/
public int getLineLength(int line)
{
try
{
readLock();
return getLineEndOffset(line)
- getLineStartOffset(line) - 1;
}
finally
{
readUnlock();
}
} //}}}
//{{{ invalidateCachedScreenLineCounts() method
/**
* Invalidates all cached screen line count information.
* @since jEdit 4.2pre7.
*/
public void invalidateCachedScreenLineCounts()
{
lineMgr.invalidateScreenLineCounts();
} //}}}
//}}}
//{{{ Text getters and setters
//{{{ getLineText() method
/**
* Returns the text on the specified line.
* This method is thread-safe.
* @param line The line
* @return The text, or null if the line is invalid
* @since jEdit 4.0pre1
*/
public String getLineText(int line)
{
if(line < 0 || line >= lineMgr.getLineCount())
throw new ArrayIndexOutOfBoundsException(line);
try
{
readLock();
int start = (line == 0 ? 0
: lineMgr.getLineEndOffset(line - 1));
int end = lineMgr.getLineEndOffset(line);
return getText(start,end - start - 1);
}
finally
{
readUnlock();
}
} //}}}
//{{{ getLineText() method
/**
* Returns the specified line in a Segment .
*
* Using a
*
* This method is thread-safe.
*
* @param line The line
* @since jEdit 4.0pre1
*/
public void getLineText(int line, Segment segment)
{
if(line < 0 || line >= lineMgr.getLineCount())
throw new ArrayIndexOutOfBoundsException(line);
try
{
readLock();
int start = (line == 0 ? 0
: lineMgr.getLineEndOffset(line - 1));
int end = lineMgr.getLineEndOffset(line);
getText(start,end - start - 1,segment);
}
finally
{
readUnlock();
}
} //}}}
//{{{ getText() method
/**
* Returns the specified text range. This method is thread-safe.
* @param start The start offset
* @param length The number of characters to get
*/
public String getText(int start, int length)
{
try
{
readLock();
if(start < 0 || length < 0
|| start + length > contentMgr.getLength())
throw new ArrayIndexOutOfBoundsException(start + ":" + length);
return contentMgr.getText(start,length);
}
finally
{
readUnlock();
}
} //}}}
//{{{ getText() method
/**
* Returns the specified text range in a
*
* Using a
*
* This method is thread-safe.
*
* @param start The start offset
* @param length The number of characters to get
* @param seg The segment to copy the text to
*/
public void getText(int start, int length, Segment seg)
{
try
{
readLock();
if(start < 0 || length < 0
|| start + length > contentMgr.getLength())
throw new ArrayIndexOutOfBoundsException(start + ":" + length);
contentMgr.getText(start,length,seg);
}
finally
{
readUnlock();
}
} //}}}
//{{{ insert() method
/**
* Inserts a string into the buffer.
* @param offset The offset
* @param str The string
* @since jEdit 4.0pre1
*/
public void insert(int offset, String str)
{
if(str == null)
return;
int len = str.length();
if(len == 0)
return;
if(isReadOnly())
throw new RuntimeException("buffer read-only");
try
{
writeLock();
if(offset < 0 || offset > contentMgr.getLength())
throw new ArrayIndexOutOfBoundsException(offset);
contentMgr.insert(offset,str);
integerArray.clear();
for(int i = 0; i < len; i++)
{
if(str.charAt(i) == '\n')
integerArray.add(i + 1);
}
if(!getFlag(UNDO_IN_PROGRESS))
{
undoMgr.contentInserted(offset,len,str,
!getFlag(DIRTY));
}
contentInserted(offset,len,integerArray);
}
finally
{
writeUnlock();
}
} //}}}
//{{{ insert() method
/**
* Inserts a string into the buffer.
* @param offset The offset
* @param seg The segment
* @since jEdit 4.0pre1
*/
public void insert(int offset, Segment seg)
{
if(seg.count == 0)
return;
if(isReadOnly())
throw new RuntimeException("buffer read-only");
try
{
writeLock();
if(offset < 0 || offset > contentMgr.getLength())
throw new ArrayIndexOutOfBoundsException(offset);
contentMgr.insert(offset,seg);
integerArray.clear();
for(int i = 0; i < seg.count; i++)
{
if(seg.array[seg.offset + i] == '\n')
integerArray.add(i + 1);
}
if(!getFlag(UNDO_IN_PROGRESS))
{
undoMgr.contentInserted(offset,seg.count,
seg.toString(),!getFlag(DIRTY));
}
contentInserted(offset,seg.count,integerArray);
}
finally
{
writeUnlock();
}
} //}}}
//{{{ remove() method
/**
* Removes the specified rang efrom the buffer.
* @param offset The start offset
* @param length The number of characters to remove
*/
public void remove(int offset, int length)
{
if(length == 0)
return;
if(isReadOnly())
throw new RuntimeException("buffer read-only");
try
{
setFlag(TRANSACTION,true);
writeLock();
if(offset < 0 || length < 0
|| offset + length > contentMgr.getLength())
throw new ArrayIndexOutOfBoundsException(offset + ":" + length);
int startLine = lineMgr.getLineOfOffset(offset);
int endLine = lineMgr.getLineOfOffset(offset + length);
int numLines = endLine - startLine;
if(!getFlag(UNDO_IN_PROGRESS) && !getFlag(LOADING))
{
undoMgr.contentRemoved(offset,length,
getText(offset,length),
!getFlag(DIRTY));
}
firePreContentRemoved(startLine,offset,numLines,length);
contentMgr.remove(offset,length);
lineMgr.contentRemoved(startLine,offset,numLines,length);
positionMgr.contentRemoved(offset,length);
fireContentRemoved(startLine,offset,numLines,length);
/* otherwise it will be delivered later */
if(!getFlag(UNDO_IN_PROGRESS) && !insideCompoundEdit())
fireTransactionComplete();
setDirty(true);
}
finally
{
setFlag(TRANSACTION,false);
writeUnlock();
}
} //}}}
//}}}
//{{{ Undo
//{{{ undo() method
/**
* Undoes the most recent edit.
*
* @since jEdit 4.0pre1
*/
public void undo(JEditTextArea textArea)
{
if(undoMgr == null)
return;
if(!isEditable())
{
textArea.getToolkit().beep();
return;
}
try
{
writeLock();
setFlag(UNDO_IN_PROGRESS,true);
int caret = undoMgr.undo();
if(caret == -1)
textArea.getToolkit().beep();
else
textArea.setCaretPosition(caret);
fireTransactionComplete();
}
finally
{
setFlag(UNDO_IN_PROGRESS,false);
writeUnlock();
}
} //}}}
//{{{ redo() method
/**
* Redoes the most recently undone edit.
*
* @since jEdit 2.7pre2
*/
public void redo(JEditTextArea textArea)
{
if(undoMgr == null)
return;
if(!isEditable())
{
Toolkit.getDefaultToolkit().beep();
return;
}
try
{
writeLock();
setFlag(UNDO_IN_PROGRESS,true);
int caret = undoMgr.redo();
if(caret == -1)
textArea.getToolkit().beep();
else
textArea.setCaretPosition(caret);
fireTransactionComplete();
}
finally
{
setFlag(UNDO_IN_PROGRESS,false);
writeUnlock();
}
} //}}}
//{{{ isTransactionInProgress() method
/**
* Returns if an undo or compound edit is currently in progress. If this
* method returns true, then eventually a
* {@link org.gjt.sp.jedit.buffer.BufferChangeListener#transactionComplete(Buffer)}
* buffer event will get fired.
* @since jEdit 4.0pre6
*/
public boolean isTransactionInProgress()
{
return getFlag(TRANSACTION)
|| getFlag(UNDO_IN_PROGRESS)
|| insideCompoundEdit();
} //}}}
//{{{ beginCompoundEdit() method
/**
* Starts a compound edit. All edits from now on until
* {@link #endCompoundEdit()} are called will be merged
* into one. This can be used to make a complex operation
* undoable in one step. Nested calls to
* {@link #beginCompoundEdit()} behave as expected,
* requiring the same number of {@link #endCompoundEdit()}
* calls to end the edit.
* @see #endCompoundEdit()
*/
public void beginCompoundEdit()
{
// Why?
//if(getFlag(TEMPORARY))
// return;
try
{
writeLock();
undoMgr.beginCompoundEdit();
}
finally
{
writeUnlock();
}
} //}}}
//{{{ endCompoundEdit() method
/**
* Ends a compound edit. All edits performed since
* {@link #beginCompoundEdit()} was called can now
* be undone in one step by calling {@link #undo(JEditTextArea)}.
* @see #beginCompoundEdit()
*/
public void endCompoundEdit()
{
// Why?
//if(getFlag(TEMPORARY))
// return;
try
{
writeLock();
undoMgr.endCompoundEdit();
if(!insideCompoundEdit())
fireTransactionComplete();
}
finally
{
writeUnlock();
}
}//}}}
//{{{ insideCompoundEdit() method
/**
* Returns if a compound edit is currently active.
* @since jEdit 3.1pre1
*/
public boolean insideCompoundEdit()
{
return undoMgr.insideCompoundEdit();
} //}}}
//}}}
//{{{ Buffer events
public static final int NORMAL_PRIORITY = 0;
public static final int HIGH_PRIORITY = 1;
static class Listener
{
BufferChangeListener listener;
int priority;
Listener(BufferChangeListener listener, int priority)
{
this.listener = listener;
this.priority = priority;
}
}
//{{{ addBufferChangeListener() method
/**
* Adds a buffer change listener.
* @param listener The listener
* @param priority Listeners with HIGH_PRIORITY get the event before
* listeners with NORMAL_PRIORITY
* @since jEdit 4.2pre2
*/
public void addBufferChangeListener(BufferChangeListener listener,
int priority)
{
Listener l = new Listener(listener,priority);
for(int i = 0; i < bufferListeners.size(); i++)
{
Listener _l = (Listener)bufferListeners.get(i);
if(_l.priority < priority)
{
bufferListeners.insertElementAt(l,i);
return;
}
}
bufferListeners.addElement(l);
} //}}}
//{{{ addBufferChangeListener() method
/**
* Adds a buffer change listener.
* @param listener The listener
* @since jEdit 4.0pre1
*/
public void addBufferChangeListener(BufferChangeListener listener)
{
addBufferChangeListener(listener,NORMAL_PRIORITY);
} //}}}
//{{{ removeBufferChangeListener() method
/**
* Removes a buffer change listener.
* @param listener The listener
* @since jEdit 4.0pre1
*/
public void removeBufferChangeListener(BufferChangeListener listener)
{
for(int i = 0; i < bufferListeners.size(); i++)
{
if(((Listener)bufferListeners.get(i)).listener == listener)
{
bufferListeners.removeElementAt(i);
return;
}
}
} //}}}
//{{{ getBufferChangeListeners() method
/**
* Returns an array of registered buffer change listeners.
* @since jEdit 4.1pre3
*/
public BufferChangeListener[] getBufferChangeListeners()
{
BufferChangeListener[] returnValue
= new BufferChangeListener[
bufferListeners.size()];
for(int i = 0; i < returnValue.length; i++)
{
returnValue[i] = ((Listener)bufferListeners.get(i))
.listener;
}
return returnValue;
} //}}}
//}}}
//{{{ Property methods
//{{{ propertiesChanged() method
/**
* Reloads settings from the properties. This should be called
* after the
*
* Using this method is generally discouraged, because it returns an
* * * The following methods should be used instead: *
Object , not a String .
*/
public Object getProperty(Object name)
{
synchronized(propertyLock)
{
// First try the buffer-local properties
PropValue o = (PropValue)properties.get(name);
if(o != null)
return o.value;
// For backwards compatibility
if(!(name instanceof String))
return null;
// Now try mode.setProperty() instead.
*/
public void putProperty(Object name, Object value)
{
// for backwards compatibility
if(!(name instanceof String))
return;
setProperty((String)name,value);
} //}}}
//{{{ putBooleanProperty() method
/**
* @deprecated Call setBooleanProperty() instead
*/
public void putBooleanProperty(String name, boolean value)
{
setBooleanProperty(name,value);
} //}}}
//{{{ markTokens() method
/**
* @deprecated Use org.gjt.sp.jedit.syntax.DefaultTokenHandler instead
*/
public static class TokenList extends DefaultTokenHandler
{
public Token getFirstToken()
{
return getTokens();
}
}
/**
* @deprecated Use the other form of markTokens() instead
*/
public TokenList markTokens(int lineIndex)
{
TokenList list = new TokenList();
markTokens(lineIndex,list);
return list;
} //}}}
//{{{ getRootElements() method
/**
* @deprecated
*/
public Element[] getRootElements()
{
return new Element[] { getDefaultRootElement() };
} //}}}
//{{{ getParagraphElement() method
/**
* @deprecated
*/
public Element getParagraphElement(int offset)
{
return new LineElement(this,getLineOfOffset(offset));
} //}}}
//{{{ getDefaultRootElement() method
/**
* @deprecated Use getLineOfOffset() ,
* getLineStartOffset() , and
* getLineEndOffset() instead.
*/
public Element getDefaultRootElement()
{
return new RootElement(this);
} //}}}
//{{{ insertString() method
/**
* @deprecated Call insert() instead.
*/
public void insertString(int offset, String str, AttributeSet attr)
{
insert(offset,str);
} //}}}
//{{{ getFile() method
/**
* @deprecated Do not call this method, use {@link #getPath()}
* instead.
*/
public File getFile()
{
return file;
} //}}}
//{{{ getCurrentIdentForLine() method
/**
* @deprecated Use the correctly spelled getCurrentIndentForLine() instead.
*/
public int getCurrentIdentForLine(int lineIndex, int[] whitespaceChars) {
return getCurrentIndentForLine(lineIndex,whitespaceChars);
}//}}}
//}}}
//{{{ Folding methods
//{{{ isFoldStart() method
/**
* Returns if the specified line begins a fold.
* @since jEdit 3.1pre1
*/
public boolean isFoldStart(int line)
{
return (line != getLineCount() - 1
&& getFoldLevel(line) < getFoldLevel(line + 1));
} //}}}
//{{{ isFoldEnd() method
/**
* Returns if the specified line ends a fold.
* @since jEdit 4.2pre5
*/
public boolean isFoldEnd(int line)
{
return (line != getLineCount() - 1
&& getFoldLevel(line) > getFoldLevel(line + 1));
} //}}}
//{{{ invalidateCachedFoldLevels() method
/**
* Invalidates all cached fold level information.
* @since jEdit 4.1pre11
*/
public void invalidateCachedFoldLevels()
{
lineMgr.setFirstInvalidFoldLevel(0);
fireFoldLevelChanged(0,getLineCount());
} //}}}
//{{{ getFoldLevel() method
/**
* Returns the fold level of the specified line.
* @param line A physical line index
* @since jEdit 3.1pre1
*/
public int getFoldLevel(int line)
{
if(line < 0 || line >= lineMgr.getLineCount())
throw new ArrayIndexOutOfBoundsException(line);
if(foldHandler instanceof DummyFoldHandler)
return 0;
int firstInvalidFoldLevel = lineMgr.getFirstInvalidFoldLevel();
if(firstInvalidFoldLevel == -1 || line < firstInvalidFoldLevel)
{
return lineMgr.getFoldLevel(line);
}
else
{
if(Debug.FOLD_DEBUG)
Log.log(Log.DEBUG,this,"Invalid fold levels from " + firstInvalidFoldLevel + " to " + line);
int newFoldLevel = 0;
boolean changed = false;
for(int i = firstInvalidFoldLevel; i <= line; i++)
{
newFoldLevel = foldHandler.getFoldLevel(this,i,seg);
if(newFoldLevel != lineMgr.getFoldLevel(i))
{
if(Debug.FOLD_DEBUG)
Log.log(Log.DEBUG,this,i + " fold level changed");
changed = true;
}
lineMgr.setFoldLevel(i,newFoldLevel);
}
if(line == lineMgr.getLineCount() - 1)
lineMgr.setFirstInvalidFoldLevel(-1);
else
lineMgr.setFirstInvalidFoldLevel(line + 1);
if(changed)
{
if(Debug.FOLD_DEBUG)
Log.log(Log.DEBUG,this,"fold level changed: " + firstInvalidFoldLevel + "," + line);
fireFoldLevelChanged(firstInvalidFoldLevel,line);
}
return newFoldLevel;
}
} //}}}
//{{{ getFoldAtLine() method
/**
* Returns an array. The first element is the start line, the
* second element is the end line, of the fold containing the
* specified line number.
* @param line The line number
* @since jEdit 4.0pre3
*/
public int[] getFoldAtLine(int line)
{
int start, end;
if(isFoldStart(line))
{
start = line;
int foldLevel = getFoldLevel(line);
line++;
while(getFoldLevel(line) > foldLevel)
{
line++;
if(line == getLineCount())
break;
}
end = line - 1;
}
else
{
start = line;
int foldLevel = getFoldLevel(line);
while(getFoldLevel(start) >= foldLevel)
{
if(start == 0)
break;
else
start--;
}
end = line;
while(getFoldLevel(end) >= foldLevel)
{
end++;
if(end == getLineCount())
break;
}
end--;
}
while(getLineLength(end) == 0 && end > start)
end--;
return new int[] { start, end };
} //}}}
//{{{ getFoldHandler() method
/**
* Returns the current buffer's fold handler.
* @since jEdit 4.2pre1
*/
public FoldHandler getFoldHandler()
{
return foldHandler;
} //}}}
//{{{ setFoldHandler() method
/**
* Sets the buffer's fold handler.
* @since jEdit 4.2pre2
*/
public void setFoldHandler(FoldHandler foldHandler)
{
FoldHandler oldFoldHandler = this.foldHandler;
if(foldHandler.equals(oldFoldHandler))
return;
this.foldHandler = foldHandler;
lineMgr.setFirstInvalidFoldLevel(0);
fireFoldHandlerChanged();
} //}}}
//}}}
//{{{ Position methods
//{{{ createPosition() method
/**
* Creates a floating position.
* @param offset The offset
*/
public Position createPosition(int offset)
{
try
{
readLock();
if(offset < 0 || offset > contentMgr.getLength())
throw new ArrayIndexOutOfBoundsException(offset);
return positionMgr.createPosition(offset);
}
finally
{
readUnlock();
}
} //}}}
//}}}
//{{{ Marker methods
//{{{ getMarkers() method
/**
* Returns a vector of markers.
* @since jEdit 3.2pre1
*/
public Vector getMarkers()
{
return markers;
} //}}}
//{{{ getMarkerStatusPrompt() method
/**
* Returns the status prompt for the given marker action. Only
* intended to be called from actions.xml .
* @since jEdit 4.2pre2
*/
public String getMarkerStatusPrompt(String action)
{
return jEdit.getProperty("view.status." + action,
new String[] { getMarkerNameString() });
} //}}}
//{{{ getMarkerNameString() method
/**
* Returns a string of all set markers, used by the status bar
* (eg, "a b $ % ^").
* @since jEdit 4.2pre2
*/
public String getMarkerNameString()
{
StringBuffer buf = new StringBuffer();
for(int i = 0; i < markers.size(); i++)
{
Marker marker = (Marker)markers.elementAt(i);
if(marker.getShortcut() != '\0')
{
if(buf.length() != 0)
buf.append(' ');
buf.append(marker.getShortcut());
}
}
if(buf.length() == 0)
return jEdit.getProperty("view.status.no-markers");
else
return buf.toString();
} //}}}
//{{{ addOrRemoveMarker() method
/**
* If a marker is set on the line of the position, it is removed. Otherwise
* a new marker with the specified shortcut is added.
* @param pos The position of the marker
* @param shortcut The shortcut ('\0' if none)
* @since jEdit 3.2pre5
*/
public void addOrRemoveMarker(char shortcut, int pos)
{
int line = getLineOfOffset(pos);
if(getMarkerAtLine(line) != null)
removeMarker(line);
else
addMarker(shortcut,pos);
} //}}}
//{{{ addMarker() method
/**
* Adds a marker to this buffer.
* @param pos The position of the marker
* @param shortcut The shortcut ('\0' if none)
* @since jEdit 3.2pre1
*/
public void addMarker(char shortcut, int pos)
{
Marker markerN = new Marker(this,shortcut,pos);
boolean added = false;
// don't sort markers while buffer is being loaded
if(!getFlag(LOADING))
{
if(jEdit.getBooleanProperty("persistentMarkers"))
setDirty(true);
markerN.createPosition();
for(int i = 0; i < markers.size(); i++)
{
Marker marker = (Marker)markers.elementAt(i);
if(shortcut != '\0' && marker.getShortcut() == shortcut)
marker.setShortcut('\0');
if(marker.getPosition() == pos)
{
markers.removeElementAt(i);
i--;
}
}
for(int i = 0; i < markers.size(); i++)
{
Marker marker = (Marker)markers.elementAt(i);
if(marker.getPosition() > pos)
{
markers.insertElementAt(markerN,i);
added = true;
break;
}
}
}
if(!added)
markers.addElement(markerN);
if(!getFlag(LOADING) && !getFlag(TEMPORARY))
{
EditBus.send(new BufferUpdate(this,null,
BufferUpdate.MARKERS_CHANGED));
}
} //}}}
//{{{ getMarkerInRange() method
/**
* Returns the first marker within the specified range.
* @param start The start offset
* @param end The end offset
* @since jEdit 4.0pre4
*/
public Marker getMarkerInRange(int start, int end)
{
for(int i = 0; i < markers.size(); i++)
{
Marker marker = (Marker)markers.elementAt(i);
int pos = marker.getPosition();
if(pos >= start && pos < end)
return marker;
}
return null;
} //}}}
//{{{ getMarkerAtLine() method
/**
* Returns the first marker at the specified line, or null
* if there is none.
* @param line The line number
* @since jEdit 3.2pre2
*/
public Marker getMarkerAtLine(int line)
{
for(int i = 0; i < markers.size(); i++)
{
Marker marker = (Marker)markers.elementAt(i);
if(getLineOfOffset(marker.getPosition()) == line)
return marker;
}
return null;
} //}}}
//{{{ removeMarker() method
/**
* Removes all markers at the specified line.
* @param line The line number
* @since jEdit 3.2pre2
*/
public void removeMarker(int line)
{
for(int i = 0; i < markers.size(); i++)
{
Marker marker = (Marker)markers.elementAt(i);
if(getLineOfOffset(marker.getPosition()) == line)
{
if(jEdit.getBooleanProperty("persistentMarkers"))
setDirty(true);
marker.removePosition();
markers.removeElementAt(i);
i--;
}
}
EditBus.send(new BufferUpdate(this,null,
BufferUpdate.MARKERS_CHANGED));
} //}}}
//{{{ removeAllMarkers() method
/**
* Removes all defined markers.
* @since jEdit 2.6pre1
*/
public void removeAllMarkers()
{
if(jEdit.getBooleanProperty("persistentMarkers"))
setDirty(true);
for(int i = 0; i < markers.size(); i++)
((Marker)markers.elementAt(i)).removePosition();
markers.removeAllElements();
if(!getFlag(LOADING))
{
EditBus.send(new BufferUpdate(this,null,
BufferUpdate.MARKERS_CHANGED));
}
} //}}}
//{{{ getMarker() method
/**
* Returns the marker with the specified shortcut.
* @param shortcut The shortcut
* @since jEdit 3.2pre2
*/
public Marker getMarker(char shortcut)
{
Enumeration e = markers.elements();
while(e.hasMoreElements())
{
Marker marker = (Marker)e.nextElement();
if(marker.getShortcut() == shortcut)
return marker;
}
return null;
} //}}}
//}}}
//{{{ Miscellaneous methods
//{{{ setWaitSocket() method
/**
* This socket is closed when the buffer is closed.
*/
public void setWaitSocket(Socket waitSocket)
{
this.waitSocket = waitSocket;
} //}}}
//{{{ getNext() method
/**
* Returns the next buffer in the list.
*/
public Buffer getNext()
{
return next;
} //}}}
//{{{ getPrev() method
/**
* Returns the previous buffer in the list.
*/
public Buffer getPrev()
{
return prev;
} //}}}
//{{{ getIndex() method
/**
* Returns the position of this buffer in the buffer list.
*/
public int getIndex()
{
int count = 0;
Buffer buffer = prev;
for(;;)
{
if(buffer == null)
break;
count++;
buffer = buffer.prev;
}
return count;
} //}}}
//{{{ toString() method
/**
* Returns a string representation of this buffer.
* This simply returns the path name.
*/
public String toString()
{
return name + " (" + directory + ")";
} //}}}
//}}}
//{{{ Methods that really shouldn't be public...
//{{{ _getLineManager() method
/**
* Plugins and macros should not call this method.
* @since jEdit 4.2pre3
*/
public LineManager _getLineManager()
{
return lineMgr;
} //}}}
//}}}
//{{{ Package-private members
Buffer prev;
Buffer next;
//{{{ Buffer constructor
Buffer(String path, boolean newFile, boolean temp, Hashtable props)
{
lock = new ReadWriteLock();
propertyLock = new Object();
contentMgr = new ContentManager();
lineMgr = new LineManager();
positionMgr = new PositionManager();
integerArray = new IntegerArray();
undoMgr = new UndoManager(this);
bufferListeners = new Vector();
seg = new Segment();
markers = new Vector();
properties = new HashMap();
//{{{ need to convert entries of 'props' to PropValue instances
Enumeration e = props.keys();
while(e.hasMoreElements())
{
Object key = e.nextElement();
Object value = props.get(key);
properties.put(key,new PropValue(value,false));
} //}}}
// fill in defaults for these from system properties if the
// corresponding buffer.XXX properties not set
if(getProperty(ENCODING) == null)
properties.put(ENCODING,new PropValue(System.getProperty("file.encoding"),false));
if(getProperty(LINESEP) == null)
properties.put(LINESEP,new PropValue(System.getProperty("line.separator"),false));
setFlag(TEMPORARY,temp);
// this must be called before any EditBus messages are sent
setPath(path);
/* Magic: UNTITLED is only set if newFile param to
* constructor is set, NEW_FILE is also set if file
* doesn't exist on disk.
*
* This is so that we can tell apart files created
* with jEdit.newFile(), and those that just don't
* exist on disk.
*
* Why do we need to tell the difference between the
* two? jEdit.addBufferToList() checks if the only
* opened buffer is an untitled buffer, and if so,
* replaces it with the buffer to add. We don't want
* this behavior to occur with files that don't
* exist on disk; only untitled ones.
*/
setFlag(UNTITLED,newFile);
setFlag(NEW_FILE,newFile);
} //}}}
//{{{ commitTemporary() method
void commitTemporary()
{
setFlag(TEMPORARY,false);
finishLoading();
} //}}}
//{{{ resetCachedProperties() method
void resetCachedProperties()
{
// Need to reset properties that were cached defaults,
// since the defaults might have changed.
Iterator iter = properties.values().iterator();
while(iter.hasNext())
{
PropValue value = (PropValue)iter.next();
if(value.defaultValue)
iter.remove();
}
} //}}}
//{{{ close() method
void close()
{
setFlag(CLOSED,true);
if(autosaveFile != null)
autosaveFile.delete();
// notify clients with -wait
if(waitSocket != null)
{
try
{
waitSocket.getOutputStream().write('\0');
waitSocket.getOutputStream().flush();
waitSocket.getInputStream().close();
waitSocket.getOutputStream().close();
waitSocket.close();
}
catch(IOException io)
{
//Log.log(Log.ERROR,this,io);
}
}
} //}}}
//}}}
//{{{ Private members
//{{{ Flags
//{{{ setFlag() method
private void setFlag(int flag, boolean value)
{
if(value)
flags |= (1 << flag);
else
flags &= ~(1 << flag);
} //}}}
//{{{ getFlag() method
private boolean getFlag(int flag)
{
int mask = (1 << flag);
return (flags & mask) == mask;
} //}}}
//{{{ Flag values
private static final int CLOSED = 0;
private static final int LOADING = 1;
private static final int IO = 2;
private static final int NEW_FILE = 3;
private static final int UNTITLED = 4;
private static final int AUTOSAVE_DIRTY = 5;
private static final int DIRTY = 6;
private static final int READ_ONLY = 7;
private static final int READ_ONLY_OVERRIDE = 8;
private static final int UNDO_IN_PROGRESS = 9;
private static final int TEMPORARY = 10;
private static final int TRANSACTION = 11;
//}}}
private int flags;
//}}}
//{{{ Instance variables
private String path;
private String symlinkPath;
private String name;
private String directory;
private File file;
private File autosaveFile;
private long modTime;
private Mode mode;
private HashMap properties;
private ReadWriteLock lock;
private Object propertyLock;
private ContentManager contentMgr;
private LineManager lineMgr;
private PositionManager positionMgr;
private IntegerArray integerArray;
private UndoManager undoMgr;
private Vector bufferListeners;
private Vector markers;
// Display
private boolean textMode;
private TokenMarker tokenMarker;
private Segment seg;
private FoldHandler foldHandler;
private Socket waitSocket;
//}}}
//{{{ setPath() method
private void setPath(String path)
{
this.path = path;
VFS vfs = VFSManager.getVFSForPath(path);
if((vfs.getCapabilities() & VFS.WRITE_CAP) == 0)
setFlag(READ_ONLY,true);
this.name = vfs.getFileName(path);
this.directory = vfs.getParentOfPath(path);
if(vfs instanceof FileVFS)
{
file = new File(path);
symlinkPath = MiscUtilities.resolveSymlinks(path);
// if we don't do this, the autosave file won't be
// deleted after a save as
if(autosaveFile != null)
autosaveFile.delete();
autosaveFile = new File(file.getParent(),'#' + name + '#');
}
else
{
// I wonder if the lack of this broke anything in the
// past?
file = null;
autosaveFile = null;
symlinkPath = path;
}
} //}}}
//{{{ recoverAutosave() method
private boolean recoverAutosave(final View view)
{
if(!autosaveFile.canRead())
return false;
// this method might get called at startup
GUIUtilities.hideSplashScreen();
final Object[] args = { autosaveFile.getPath() };
int result = GUIUtilities.confirm(view,"autosave-found",args,
JOptionPane.YES_NO_OPTION,JOptionPane.WARNING_MESSAGE);
if(result == JOptionPane.YES_OPTION)
{
VFSManager.getFileVFS().load(view,this,autosaveFile.getPath());
// show this message when all I/O requests are
// complete
VFSManager.runInAWTThread(new Runnable()
{
public void run()
{
GUIUtilities.message(view,"autosave-loaded",args);
}
});
return true;
}
else
return false;
} //}}}
//{{{ checkFileForLoad() method
private boolean checkFileForLoad(View view, VFS vfs, String path)
{
if((vfs.getCapabilities() & VFS.LOW_LATENCY_CAP) != 0)
{
Object session = vfs.createVFSSession(path,view);
if(session == null)
return false;
try
{
VFS.DirectoryEntry file = vfs._getDirectoryEntry(session,path,view);
if(file == null)
{
setNewFile(true);
return true;
}
if(!file.canRead)
{
VFSManager.error(view,path,"ioerror.no-read",null);
setNewFile(false);
return false;
}
setFlag(READ_ONLY,!file.canWrite);
if(file.type != VFS.DirectoryEntry.FILE)
{
VFSManager.error(view,path,
"ioerror.open-directory",null);
setNewFile(false);
return false;
}
}
catch(IOException io)
{
VFSManager.error(view,path,"ioerror",
new String[] { io.toString() });
return false;
}
finally
{
try
{
vfs._endVFSSession(session,view);
}
catch(IOException io)
{
VFSManager.error(view,path,"ioerror",
new String[] { io.toString() });
return false;
}
}
}
return true;
} //}}}
//{{{ checkFileForSave() method
private boolean checkFileForSave(View view, VFS vfs, String path)
{
if((vfs.getCapabilities() & VFS.LOW_LATENCY_CAP) != 0)
{
Object session = vfs.createVFSSession(path,view);
if(session == null)
return false;
try
{
VFS.DirectoryEntry file = vfs._getDirectoryEntry(session,path,view);
if(file == null)
return true;
if(file.type != VFS.DirectoryEntry.FILE)
{
VFSManager.error(view,path,
"ioerror.save-directory",null);
return false;
}
}
catch(IOException io)
{
VFSManager.error(view,path,"ioerror",
new String[] { io.toString() });
return false;
}
finally
{
try
{
vfs._endVFSSession(session,view);
}
catch(IOException io)
{
VFSManager.error(view,path,"ioerror",
new String[] { io.toString() });
return false;
}
}
}
return true;
} //}}}
//{{{ finishLoading() method
private void finishLoading()
{
parseBufferLocalProperties();
// AHA!
// this is probably the only way to fix this
FoldHandler oldFoldHandler = foldHandler;
setMode();
if(foldHandler == oldFoldHandler)
{
// on a reload, the fold handler doesn't change, but
// we still need to re-collapse folds.
// don't do this on initial fold handler creation
lineMgr.setFirstInvalidFoldLevel(0);
fireFoldHandlerChanged();
}
// Create marker positions
for(int i = 0; i < markers.size(); i++)
{
Marker marker = (Marker)markers.elementAt(i);
marker.removePosition();
int pos = marker.getPosition();
if(pos > getLength())
marker.setPosition(getLength());
else if(pos < 0)
marker.setPosition(0);
marker.createPosition();
}
} //}}}
//{{{ finishSaving() method
private void finishSaving(View view, String oldPath,
String oldSymlinkPath, String path,
boolean rename, boolean error)
{
//{{{ Set the buffer's path
// Caveat: won't work if save() called with a relative path.
// But I don't think anyone calls it like that anyway.
if(!error && !path.equals(oldPath))
{
Buffer buffer = jEdit.getBuffer(path);
if(rename)
{
/* if we save a file with the same name as one
* that's already open, we presume that we can
* close the existing file, since the user
* would have confirmed the overwrite in the
* 'save as' dialog box anyway */
if(buffer != null && /* can't happen? */
!buffer.getPath().equals(oldPath))
{
buffer.setDirty(false);
jEdit.closeBuffer(view,buffer);
}
setPath(path);
}
else
{
/* if we saved over an already open file using
* 'save a copy as', then reload the existing
* buffer */
if(buffer != null && /* can't happen? */
!buffer.getPath().equals(oldPath))
{
buffer.load(view,true);
}
}
} //}}}
//{{{ Update this buffer for the new path
if(rename)
{
if(file != null)
modTime = file.lastModified();
if(!error)
{
// we do a write lock so that the
// autosave, which grabs a read lock,
// is not executed between the
// deletion of the autosave file
// and clearing of the dirty flag
try
{
writeLock();
if(autosaveFile != null)
autosaveFile.delete();
setFlag(AUTOSAVE_DIRTY,false);
setFlag(READ_ONLY,false);
setFlag(NEW_FILE,false);
setFlag(UNTITLED,false);
setFlag(DIRTY,false);
// this ensures that undo can clear
// the dirty flag properly when all
// edits up to a save are undone
undoMgr.bufferSaved();
}
finally
{
writeUnlock();
}
parseBufferLocalProperties();
if(!getPath().equals(oldPath))
{
jEdit.updatePosition(oldSymlinkPath,this);
setMode();
}
else
{
// if user adds mode buffer-local property
String newMode = getStringProperty("mode");
if(newMode != null &&
!newMode.equals(getMode()
.getName()))
setMode();
else
propertiesChanged();
}
EditBus.send(new BufferUpdate(Buffer.this,
view,BufferUpdate.DIRTY_CHANGED));
// new message type introduced in 4.0pre4
EditBus.send(new BufferUpdate(Buffer.this,
view,BufferUpdate.SAVED));
}
} //}}}
} //}}}
//{{{ parseBufferLocalProperties() method
private void parseBufferLocalProperties()
{
int lastLine = Math.min(9,getLineCount() - 1);
parseBufferLocalProperties(getText(0,getLineEndOffset(lastLine) - 1));
// first line for last 10 lines, make sure not to overlap
// with the first 10
int firstLine = Math.max(lastLine + 1, getLineCount() - 10);
if(firstLine < getLineCount())
{
int length = getLineEndOffset(getLineCount() - 1)
- (getLineStartOffset(firstLine) + 1);
parseBufferLocalProperties(getText(getLineStartOffset(firstLine),length));
}
} //}}}
//{{{ parseBufferLocalProperties() method
private void parseBufferLocalProperties(String prop)
{
StringBuffer buf = new StringBuffer();
String name = null;
boolean escape = false;
for(int i = 0; i < prop.length(); i++)
{
char c = prop.charAt(i);
switch(c)
{
case ':':
if(escape)
{
escape = false;
buf.append(':');
break;
}
if(name != null)
{
// use the low-level property setting code
// so that if we have a buffer-local
// property with the same value as a default,
// later changes in the default don't affect
// the buffer-local property
properties.put(name,new PropValue(buf.toString(),false));
name = null;
}
buf.setLength(0);
break;
case '=':
if(escape)
{
escape = false;
buf.append('=');
break;
}
name = buf.toString();
buf.setLength(0);
break;
case '\\':
if(escape)
buf.append('\\');
escape = !escape;
break;
case 'n':
if(escape)
{ buf.append('\n');
escape = false;
break;
}
case 'r':
if(escape)
{ buf.append('\r');
escape = false;
break;
}
case 't':
if(escape)
{
buf.append('\t');
escape = false;
break;
}
default:
buf.append(c);
break;
}
}
} //}}}
//{{{ setTokenMarker() method
private void setTokenMarker(TokenMarker tokenMarker)
{
TokenMarker oldTokenMarker = this.tokenMarker;
this.tokenMarker = tokenMarker;
// don't do this on initial token marker
if(oldTokenMarker != null && tokenMarker != oldTokenMarker)
{
lineMgr.setFirstInvalidLineContext(0);
}
} //}}}
//{{{ getPriorNonEmptyLine() method
/**
* Auto indent needs this.
*/
private int getPriorNonEmptyLine(int lineIndex)
{
int returnValue = -1;
for(int i = lineIndex - 1; i >= 0; i--)
{
getLineText(i,seg);
if(seg.count != 0)
returnValue = i;
for(int j = 0; j < seg.count; j++)
{
char ch = seg.array[seg.offset + j];
if(!Character.isWhitespace(ch))
return i;
}
}
// didn't find a line that contains non-whitespace chars
// so return index of prior whitespace line
return returnValue;
} //}}}
//{{{ contentInserted() method
private void contentInserted(int offset, int length,
IntegerArray endOffsets)
{
try
{
setFlag(TRANSACTION,true);
int startLine = lineMgr.getLineOfOffset(offset);
int numLines = endOffsets.getSize();
lineMgr.contentInserted(startLine,offset,numLines,length,
endOffsets);
positionMgr.contentInserted(offset,length);
setDirty(true);
if(!getFlag(LOADING))
{
fireContentInserted(startLine,offset,numLines,length);
if(!getFlag(UNDO_IN_PROGRESS)
&& !insideCompoundEdit())
{
fireTransactionComplete();
}
}
}
finally
{
setFlag(TRANSACTION,false);
}
} //}}}
//{{{ Event firing methods
//{{{ getListener() method
private BufferChangeListener getListener(int index)
{
return ((Listener)bufferListeners.elementAt(index)).listener;
} //}}}
//{{{ fireFoldLevelChanged() method
private void fireFoldLevelChanged(int start, int end)
{
for(int i = 0; i < bufferListeners.size(); i++)
{
try
{
getListener(i).foldLevelChanged(this,start,end);
}
catch(Throwable t)
{
Log.log(Log.ERROR,this,"Exception while sending buffer event to "+getListener(i)+" :");
Log.log(Log.ERROR,this,t);
}
}
} //}}}
//{{{ fireContentInserted() method
private void fireContentInserted(int startLine, int offset,
int numLines, int length)
{
for(int i = 0; i < bufferListeners.size(); i++)
{
try
{
getListener(i).contentInserted(this,startLine,
offset,numLines,length);
}
catch(Throwable t)
{
Log.log(Log.ERROR,this,"Exception while sending buffer event to "+getListener(i)+" :");
Log.log(Log.ERROR,this,t);
}
}
} //}}}
//{{{ fireContentRemoved() method
private void fireContentRemoved(int startLine, int offset,
int numLines, int length)
{
for(int i = 0; i < bufferListeners.size(); i++)
{
try
{
getListener(i).contentRemoved(this,startLine,
offset,numLines,length);
}
catch(Throwable t)
{
Log.log(Log.ERROR,this,"Exception while sending buffer event to "+getListener(i)+" :");
Log.log(Log.ERROR,this,t);
}
}
} //}}}
//{{{ firePreContentRemoved() method
private void firePreContentRemoved(int startLine, int offset,
int numLines, int length)
{
for(int i = 0; i < bufferListeners.size(); i++)
{
try
{
getListener(i).preContentRemoved(this,startLine,
offset,numLines,length);
}
catch(Throwable t)
{
Log.log(Log.ERROR,this,"Exception while sending buffer event to "+getListener(i)+" :");
Log.log(Log.ERROR,this,t);
}
}
} //}}}
//{{{ fireTransactionComplete() method
private void fireTransactionComplete()
{
for(int i = 0; i < bufferListeners.size(); i++)
{
try
{
getListener(i).transactionComplete(this);
}
catch(Throwable t)
{
Log.log(Log.ERROR,this,"Exception while sending buffer event to "+getListener(i)+" :");
Log.log(Log.ERROR,this,t);
}
}
} //}}}
//{{{ fireFoldHandlerChanged() method
private void fireFoldHandlerChanged()
{
for(int i = 0; i < bufferListeners.size(); i++)
{
try
{
getListener(i).foldHandlerChanged(this);
}
catch(Throwable t)
{
Log.log(Log.ERROR,this,"Exception while sending buffer event to "+getListener(i)+" :");
Log.log(Log.ERROR,this,t);
}
}
} //}}}
//}}}
//}}}
}
|
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.