PageRenderTime 120ms CodeModel.GetById 100ms app.highlight 16ms RepoModel.GetById 1ms app.codeStats 0ms

/jEdit/tags/jedit-4-3-pre5/org/gjt/sp/jedit/BufferHistory.java

#
Java | 397 lines | 282 code | 60 blank | 55 comment | 39 complexity | 9af5f4525e7c6230a4ff2765ca295412 MD5 | raw file
  1/*
  2 * BufferHistory.java - Remembers caret positions
  3 * :tabSize=8:indentSize=8:noTabs=false:
  4 * :folding=explicit:collapseFolds=1:
  5 *
  6 * Copyright (C) 2000, 2005 Slava Pestov
  7 *
  8 * This program is free software; you can redistribute it and/or
  9 * modify it under the terms of the GNU General Public License
 10 * as published by the Free Software Foundation; either version 2
 11 * of the License, or any later version.
 12 *
 13 * This program is distributed in the hope that it will be useful,
 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 16 * GNU General Public License for more details.
 17 *
 18 * You should have received a copy of the GNU General Public License
 19 * along with this program; if not, write to the Free Software
 20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 21 */
 22
 23package org.gjt.sp.jedit;
 24
 25//{{{ Imports
 26import java.io.*;
 27import java.util.*;
 28
 29import org.xml.sax.InputSource;
 30import org.xml.sax.helpers.DefaultHandler;
 31
 32import org.gjt.sp.jedit.msg.DynamicMenuChanged;
 33import org.gjt.sp.jedit.textarea.*;
 34import org.gjt.sp.util.Log;
 35//}}}
 36
 37/**
 38 * Recent file list.
 39 * @author Slava Pestov
 40 * @version $Id: BufferHistory.java 5444 2006-06-18 21:41:00Z vanza $
 41 */
 42public class BufferHistory
 43{
 44	//{{{ getEntry() method
 45	public static Entry getEntry(String path)
 46	{
 47		Iterator iter = history.iterator();
 48		while(iter.hasNext())
 49		{
 50			Entry entry = (Entry)iter.next();
 51			if(MiscUtilities.pathsEqual(entry.path,path))
 52				return entry;
 53		}
 54
 55		return null;
 56	} //}}}
 57
 58	//{{{ setEntry() method
 59	public static void setEntry(String path, int caret, Selection[] selection,
 60		String encoding)
 61	{
 62		removeEntry(path);
 63		addEntry(new Entry(path,caret,selectionToString(selection),
 64			encoding));
 65		EditBus.send(new DynamicMenuChanged("recent-files"));
 66	} //}}}
 67
 68	//{{{ getHistory() method
 69	/**
 70	 * @since jEdit 4.2pre2
 71	 */
 72	public static List getHistory()
 73	{
 74		return history;
 75	} //}}}
 76
 77	//{{{ load() method
 78	public static void load()
 79	{
 80		String settingsDirectory = jEdit.getSettingsDirectory();
 81		if(settingsDirectory == null)
 82			return;
 83
 84		File recent = new File(MiscUtilities.constructPath(
 85			settingsDirectory,"recent.xml"));
 86		if(!recent.exists())
 87			return;
 88
 89		recentModTime = recent.lastModified();
 90
 91		Log.log(Log.MESSAGE,BufferHistory.class,"Loading recent.xml");
 92
 93		RecentHandler handler = new RecentHandler();
 94		try
 95		{
 96			MiscUtilities.parseXML(new FileInputStream(recent), handler);
 97		}
 98		catch(IOException e)
 99		{
100			Log.log(Log.ERROR,BufferHistory.class,e);
101		}
102	} //}}}
103
104	//{{{ save() method
105	public static void save()
106	{
107		String settingsDirectory = jEdit.getSettingsDirectory();
108		if(settingsDirectory == null)
109			return;
110
111		File file1 = new File(MiscUtilities.constructPath(
112			settingsDirectory, "#recent.xml#save#"));
113		File file2 = new File(MiscUtilities.constructPath(
114			settingsDirectory, "recent.xml"));
115		if(file2.exists() && file2.lastModified() != recentModTime)
116		{
117			Log.log(Log.WARNING,BufferHistory.class,file2
118				+ " changed on disk; will not save recent"
119				+ " files");
120			return;
121		}
122
123		jEdit.backupSettingsFile(file2);
124
125		Log.log(Log.MESSAGE,BufferHistory.class,"Saving " + file1);
126
127		String lineSep = System.getProperty("line.separator");
128
129		boolean ok = false;
130
131		BufferedWriter out = null;
132
133		try
134		{
135			out = new BufferedWriter(new FileWriter(file1));
136
137			out.write("<?xml version=\"1.0\"?>");
138			out.write(lineSep);
139			out.write("<!DOCTYPE RECENT SYSTEM \"recent.dtd\">");
140			out.write(lineSep);
141			out.write("<RECENT>");
142			out.write(lineSep);
143
144			Iterator iter = history.iterator();
145			while(iter.hasNext())
146			{
147				out.write("<ENTRY>");
148				out.write(lineSep);
149
150				Entry entry = (Entry)iter.next();
151
152				out.write("<PATH>");
153				out.write(MiscUtilities.charsToEntities(entry.path));
154				out.write("</PATH>");
155				out.write(lineSep);
156
157				out.write("<CARET>");
158				out.write(String.valueOf(entry.caret));
159				out.write("</CARET>");
160				out.write(lineSep);
161
162				if(entry.selection != null
163					&& entry.selection.length() > 0)
164				{
165					out.write("<SELECTION>");
166					out.write(entry.selection);
167					out.write("</SELECTION>");
168					out.write(lineSep);
169				}
170
171				if(entry.encoding != null)
172				{
173					out.write("<ENCODING>");
174					out.write(entry.encoding);
175					out.write("</ENCODING>");
176					out.write(lineSep);
177				}
178
179				out.write("</ENTRY>");
180				out.write(lineSep);
181			}
182
183			out.write("</RECENT>");
184			out.write(lineSep);
185
186			out.close();
187
188			ok = true;
189		}
190		catch(Exception e)
191		{
192			Log.log(Log.ERROR,BufferHistory.class,e);
193		}
194		finally
195		{
196			try
197			{
198				if(out != null)
199					out.close();
200			}
201			catch(IOException e)
202			{
203			}
204		}
205
206		if(ok)
207		{
208			/* to avoid data loss, only do this if the above
209			 * completed successfully */
210			file2.delete();
211			file1.renameTo(file2);
212		}
213
214		recentModTime = file2.lastModified();
215	} //}}}
216
217	//{{{ Private members
218	private static LinkedList history;
219	private static long recentModTime;
220
221	//{{{ Class initializer
222	static
223	{
224		history = new LinkedList();
225	} //}}}
226
227	//{{{ addEntry() method
228	/* private */ static void addEntry(Entry entry)
229	{
230		history.addFirst(entry);
231		int max = jEdit.getIntegerProperty("recentFiles",50);
232		while(history.size() > max)
233			history.removeLast();
234	} //}}}
235
236	//{{{ removeEntry() method
237	/* private */ static void removeEntry(String path)
238	{
239		Iterator iter = history.iterator();
240		while(iter.hasNext())
241		{
242			Entry entry = (Entry)iter.next();
243			if(MiscUtilities.pathsEqual(path,entry.path))
244			{
245				iter.remove();
246				return;
247			}
248		}
249	} //}}}
250
251	//{{{ selectionToString() method
252	private static String selectionToString(Selection[] s)
253	{
254		if(s == null)
255			return null;
256
257		StringBuffer buf = new StringBuffer();
258
259		for(int i = 0; i < s.length; i++)
260		{
261			if(i != 0)
262				buf.append(' ');
263
264			Selection sel = s[i];
265			if(sel instanceof Selection.Range)
266				buf.append("range ");
267			else //if(sel instanceof Selection.Rect)
268				buf.append("rect ");
269			buf.append(sel.getStart());
270			buf.append(' ');
271			buf.append(sel.getEnd());
272		}
273
274		return buf.toString();
275	} //}}}
276
277	//{{{ stringToSelection() method
278	private static Selection[] stringToSelection(String s)
279	{
280		if(s == null)
281			return null;
282
283		Vector selection = new Vector();
284		StringTokenizer st = new StringTokenizer(s);
285
286		while(st.hasMoreTokens())
287		{
288			String type = st.nextToken();
289			int start = Integer.parseInt(st.nextToken());
290			int end = Integer.parseInt(st.nextToken());
291			if(end < start)
292			{
293				// I'm not sure when this can happen,
294				// but it does sometimes, witness the
295				// jEdit bug tracker.
296				continue;
297			}
298
299			Selection sel;
300			if(type.equals("range"))
301				sel = new Selection.Range(start,end);
302			else //if(type.equals("rect"))
303				sel = new Selection.Rect(start,end);
304
305			selection.addElement(sel);
306		}
307
308		Selection[] returnValue = new Selection[selection.size()];
309		selection.copyInto(returnValue);
310		return returnValue;
311	} //}}}
312
313	//}}}
314
315	//{{{ Entry class
316	/**
317	 * Recent file list entry.
318	 */
319	public static class Entry
320	{
321		public String path;
322		public int caret;
323		public String selection;
324		public String encoding;
325
326		public Selection[] getSelection()
327		{
328			return stringToSelection(selection);
329		}
330
331		public Entry(String path, int caret, String selection, String encoding)
332		{
333			this.path = path;
334			this.caret = caret;
335			this.selection = selection;
336			this.encoding = encoding;
337		}
338
339		public String toString()
340		{
341			return path + ": " + caret;
342		}
343	} //}}}
344
345	//{{{ RecentHandler class
346	static class RecentHandler extends DefaultHandler
347	{
348		public void endDocument()
349		{
350			int max = jEdit.getIntegerProperty("recentFiles",50);
351			while(history.size() > max)
352				history.removeLast();
353		}
354
355		public InputSource resolveEntity(String publicId, String systemId)
356		{
357			return MiscUtilities.findEntity(systemId, "recent.dtd", getClass());
358		}
359
360		public void endElement(String uri, String localName, String name)
361		{
362			if(name.equals("ENTRY"))
363			{
364				history.addLast(new Entry(
365					path,caret,selection,
366					encoding));
367				path = null;
368				caret = 0;
369				selection = null;
370				encoding = null;
371			}
372			else if(name.equals("PATH"))
373				path = charData.toString();
374			else if(name.equals("CARET"))
375				caret = Integer.parseInt(charData.toString());
376			else if(name.equals("SELECTION"))
377				selection = charData.toString();
378			else if(name.equals("ENCODING"))
379				encoding = charData.toString();
380			charData.setLength(0);
381		}
382
383		public void characters(char[] ch, int start, int length)
384		{
385			charData.append(ch,start,length);
386		}
387
388		// end HandlerBase implementation
389
390		// private members
391		private String path;
392		private int caret;
393		private String selection;
394		private String encoding;
395		private StringBuffer charData = new StringBuffer();
396	} //}}}
397}