⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 buffer.java

📁 开源的java 编辑器源代码
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
/* * Buffer.java - jEdit buffer * :tabSize=8:indentSize=8:noTabs=false: * :folding=explicit:collapseFolds=1: * * Copyright (C) 1998, 2003 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;//{{{ Importsimport 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 <code>Buffer</code> represents the contents of an open text * file as it is maintained in the computer's memory (as opposed to * how it may be stored on a disk).<p> * * In a BeanShell script, you can obtain the current buffer instance from the * <code>buffer</code> variable.<p> * * This class does not have a public constructor. * Buffers can be opened and closed using methods in the <code>jEdit</code> * class.<p> * * This class is partially thread-safe, however you must pay attention to two * very important guidelines: * <ul> * <li>Changes to a buffer can only be made from the AWT thread. * <li>When accessing the buffer from another thread, you must * grab a read lock if you plan on performing more than one call, to ensure that * the buffer contents are not changed by the AWT thread for the duration of the * lock. Only methods whose descriptions specify thread safety can be invoked * from other threads. * </ul> * * @author Slava Pestov * @version $Id: Buffer.java,v 1.213 2004/02/27 23:59:09 spestov Exp $ */public class Buffer{	//{{{ Some constants	/**	 * Line separator property.	 */	public static final String LINESEP = "lineSeparator";	/**	 * Backed up property.	 * @since jEdit 3.2pre2	 */	public static final String BACKED_UP = "Buffer__backedUp";	/**	 * Caret info properties.	 * @since jEdit 3.2pre1	 */	public static final String CARET = "Buffer__caret";	public static final String SELECTION = "Buffer__selection";	/**	 * This should be a physical line number, so that the scroll	 * position is preserved correctly across reloads (which will	 * affect virtual line numbers, due to fold being reset)	 */	public static final String SCROLL_VERT = "Buffer__scrollVert";	public static final String SCROLL_HORIZ = "Buffer__scrollHoriz";	/**	 * Character encoding used when loading and saving.	 * @since jEdit 3.2pre4	 */	public static final String ENCODING = "encoding";	/**	 * Should jEdit try to set the encoding based on a UTF8, UTF16 or	 * XML signature at the beginning of the file?	 */	public static final String ENCODING_AUTODETECT = "encodingAutodetect";	/**	 * This property is set to 'true' if the file has a trailing newline.	 * @since jEdit 4.0pre1	 */	public static final String TRAILING_EOL = "trailingEOL";	/**	 * This property is set to 'true' if the file should be GZipped.	 * @since jEdit 4.0pre4	 */	public static final String GZIPPED = "gzipped";	//}}}	//{{{ Input/output methods	//{{{ reload() method	/**	 * Reloads the buffer from disk, asking for confirmation if the buffer	 * has unsaved changes.	 * @param view The view	 * @since jEdit 2.7pre2	 */	public void reload(View view)	{		if(getFlag(DIRTY))		{			String[] args = { name };			int result = GUIUtilities.confirm(view,"changedreload",				args,JOptionPane.YES_NO_OPTION,				JOptionPane.WARNING_MESSAGE);			if(result != JOptionPane.YES_OPTION)				return;		}		view.getEditPane().saveCaretInfo();		load(view,true);	} //}}}	//{{{ load() method	/**	 * Loads the buffer from disk, even if it is loaded already.	 * @param view The view	 * @param reload If true, user will not be asked to recover autosave	 * file, if any	 *	 * @since 2.5pre1	 */	public boolean load(final View view, final boolean reload)	{		if(isPerformingIO())		{			GUIUtilities.error(view,"buffer-multiple-io",null);			return false;		}		setBooleanProperty(BufferIORequest.ERROR_OCCURRED,false);		setFlag(LOADING,true);		// view text areas temporarily blank out while a buffer is		// being loaded, to indicate to the user that there is no		// data available yet.		if(!getFlag(TEMPORARY))			EditBus.send(new BufferUpdate(this,view,BufferUpdate.LOAD_STARTED));		final boolean loadAutosave;		if(reload || !getFlag(NEW_FILE))		{			if(file != null)				modTime = file.lastModified();			// Only on initial load			if(!reload && autosaveFile != null && autosaveFile.exists())				loadAutosave = recoverAutosave(view);			else			{				if(autosaveFile != null)					autosaveFile.delete();				loadAutosave = false;			}			if(!loadAutosave)			{				VFS vfs = VFSManager.getVFSForPath(path);				if(!checkFileForLoad(view,vfs,path))				{					setFlag(LOADING,false);					return false;				}				// have to check again since above might set				// NEW_FILE flag				if(reload || !getFlag(NEW_FILE))				{					if(!vfs.load(view,this,path))					{						setFlag(LOADING,false);						return false;					}				}			}		}		else			loadAutosave = false;		//{{{ Do some stuff once loading is finished		Runnable runnable = new Runnable()		{			public void run()			{				String newPath = getStringProperty(					BufferIORequest.NEW_PATH);				Segment seg = (Segment)getProperty(					BufferIORequest.LOAD_DATA);				IntegerArray endOffsets = (IntegerArray)					getProperty(BufferIORequest.END_OFFSETS);				if(seg == null)					seg = new Segment(new char[1024],0,0);				if(endOffsets == null)				{					endOffsets = new IntegerArray();					endOffsets.add(1);				}				try				{					writeLock();					// For `reload' command					firePreContentRemoved(0,0,getLineCount()						- 1,getLength());					contentMgr.remove(0,getLength());					lineMgr.contentRemoved(0,0,getLineCount()						- 1,getLength());					positionMgr.contentRemoved(0,getLength());					fireContentRemoved(0,0,getLineCount()						- 1,getLength());					// theoretically a segment could					// have seg.offset != 0 but					// SegmentBuffer never does that					contentMgr._setContent(seg.array,seg.count);					lineMgr._contentInserted(endOffsets);					positionMgr.contentInserted(0,seg.count);					fireContentInserted(0,0,						endOffsets.getSize() - 1,						seg.count - 1);				}				finally				{					writeUnlock();				}				unsetProperty(BufferIORequest.LOAD_DATA);				unsetProperty(BufferIORequest.END_OFFSETS);				unsetProperty(BufferIORequest.NEW_PATH);				undoMgr.clear();				undoMgr.setLimit(jEdit.getIntegerProperty(					"buffer.undoCount",100));				if(!getFlag(TEMPORARY))					finishLoading();				setFlag(LOADING,false);				// if reloading a file, clear dirty flag				if(reload)					setDirty(false);				if(!loadAutosave && newPath != null)					setPath(newPath);				// if loadAutosave is false, we loaded an				// autosave file, so we set 'dirty' to true				// note that we don't use setDirty(),				// because a) that would send an unnecessary				// message, b) it would also set the				// AUTOSAVE_DIRTY flag, which will make				// the autosave thread write out a				// redundant autosave file				if(loadAutosave)					setFlag(DIRTY,true);				// send some EditBus messages				if(!getFlag(TEMPORARY))				{					EditBus.send(new BufferUpdate(Buffer.this,						view,BufferUpdate.LOADED));					//EditBus.send(new BufferUpdate(Buffer.this,					//	view,BufferUpdate.MARKERS_CHANGED));				}			}		}; //}}}		if(getFlag(TEMPORARY))			runnable.run();		else			VFSManager.runInAWTThread(runnable);		return true;	} //}}}	//{{{ insertFile() method	/**	 * Loads a file from disk, and inserts it into this buffer.	 * @param view The view	 *	 * @since 4.0pre1	 */	public boolean insertFile(final View view, String path)	{		if(isPerformingIO())		{			GUIUtilities.error(view,"buffer-multiple-io",null);			return false;		}		setBooleanProperty(BufferIORequest.ERROR_OCCURRED,false);		path = MiscUtilities.constructPath(this.path,path);		Buffer buffer = jEdit.getBuffer(path);		if(buffer != null)		{			view.getTextArea().setSelectedText(				buffer.getText(0,buffer.getLength()));			return true;		}		VFS vfs = VFSManager.getVFSForPath(path);		// this returns false if initial sanity		// checks (if the file is a directory, etc)		// fail		return vfs.insert(view,this,path);	} //}}}	//{{{ autosave() method	/**	 * Autosaves this buffer.	 */	public void autosave()	{		if(autosaveFile == null || !getFlag(AUTOSAVE_DIRTY)			|| !getFlag(DIRTY)			|| getFlag(LOADING)			|| getFlag(IO))			return;		setFlag(AUTOSAVE_DIRTY,false);		VFSManager.runInWorkThread(new BufferIORequest(			BufferIORequest.AUTOSAVE,null,this,null,			VFSManager.getFileVFS(),autosaveFile.getPath()));	} //}}}	//{{{ saveAs() method	/**	 * Prompts the user for a file to save this buffer to.	 * @param view The view	 * @param rename True if the buffer's path should be changed, false	 * if only a copy should be saved to the specified filename	 * @since jEdit 2.6pre5	 */	public boolean saveAs(View view, boolean rename)	{		String[] files = GUIUtilities.showVFSFileDialog(view,path,			VFSBrowser.SAVE_DIALOG,false);		// files[] should have length 1, since the dialog type is		// SAVE_DIALOG		if(files == null)			return false;		return save(view,files[0],rename);	} //}}}	//{{{ save() method	/**	 * Saves this buffer to the specified path name, or the current path	 * name if it's null.	 * @param view The view	 * @param path The path name to save the buffer to, or null to use	 * the existing path	 */	public boolean save(View view, String path)	{		return save(view,path,true);	} //}}}	//{{{ save() method	/**	 * Saves this buffer to the specified path name, or the current path	 * name if it's null.	 * @param view The view	 * @param path The path name to save the buffer to, or null to use	 * the existing path	 * @param rename True if the buffer's path should be changed, false	 * if only a copy should be saved to the specified filename	 * @since jEdit 2.6pre5	 */	public boolean save(final View view, String path, final boolean rename)	{		if(isPerformingIO())		{			GUIUtilities.error(view,"buffer-multiple-io",null);			return false;		}		setBooleanProperty(BufferIORequest.ERROR_OCCURRED,false);		if(path == null && getFlag(NEW_FILE))			return saveAs(view,rename);		if(path == null && file != null)		{			long newModTime = file.lastModified();			if(newModTime != modTime				&& jEdit.getBooleanProperty("view.checkModStatus"))			{				Object[] args = { this.path };				int result = GUIUtilities.confirm(view,					"filechanged-save",args,					JOptionPane.YES_NO_OPTION,					JOptionPane.WARNING_MESSAGE);				if(result != JOptionPane.YES_OPTION)					return false;			}		}		EditBus.send(new BufferUpdate(this,view,BufferUpdate.SAVING));		setFlag(IO,true);		final String oldPath = this.path;		final String oldSymlinkPath = this.symlinkPath;		final String newPath = (path == null ? this.path : path);		VFS vfs = VFSManager.getVFSForPath(newPath);		if(!checkFileForSave(view,vfs,newPath))		{			setFlag(IO,false);			return false;		}		if(!vfs.save(view,this,newPath))		{			setFlag(IO,false);			return false;		}		// Once save is complete, do a few other things		VFSManager.runInAWTThread(new Runnable()		{			public void run()			{				setFlag(IO,false);				finishSaving(view,oldPath,oldSymlinkPath,					newPath,rename,getBooleanProperty(					BufferIORequest.ERROR_OCCURRED));			}		});		return true;	} //}}}	//{{{ checkFileStatus() method	public static final int FILE_NOT_CHANGED = 0;	public static final int FILE_CHANGED = 1;	public static final int FILE_DELETED = 2;	/**	 * Check if the buffer has changed on disk.	 * @return One of <code>NOT_CHANGED</code>, <code>CHANGED</code>, or	 * <code>DELETED</code>.	 *	 * @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);	} //}}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -