PageRenderTime 44ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/jEdit/tags/jedit-4-2-pre4/org/gjt/sp/jedit/BufferHistory.java

#
Java | 440 lines | 308 code | 58 blank | 74 comment | 43 complexity | d6ddaa7392eaf7d68387d94e4b3c5bf3 MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-1.0, Apache-2.0, LGPL-2.0, LGPL-3.0, GPL-2.0, CC-BY-SA-3.0, LGPL-2.1, GPL-3.0, MPL-2.0-no-copyleft-exception, IPL-1.0
  1. /*
  2. * BufferHistory.java - Remembers caret positions
  3. * :tabSize=8:indentSize=8:noTabs=false:
  4. * :folding=explicit:collapseFolds=1:
  5. *
  6. * Copyright (C) 2000, 2003 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. package org.gjt.sp.jedit;
  23. //{{{ Imports
  24. import com.microstar.xml.*;
  25. import java.io.*;
  26. import java.util.*;
  27. import org.gjt.sp.jedit.msg.DynamicMenuChanged;
  28. import org.gjt.sp.jedit.textarea.*;
  29. import org.gjt.sp.util.Log;
  30. //}}}
  31. /**
  32. * Recent file list.
  33. * @author Slava Pestov
  34. * @version $Id: BufferHistory.java 4835 2003-07-23 06:08:54Z spestov $
  35. */
  36. public class BufferHistory
  37. {
  38. //{{{ getEntry() method
  39. public static Entry getEntry(String path)
  40. {
  41. Iterator iter = history.iterator();
  42. while(iter.hasNext())
  43. {
  44. Entry entry = (Entry)iter.next();
  45. if(pathsCaseInsensitive)
  46. {
  47. if(entry.path.equalsIgnoreCase(path))
  48. return entry;
  49. }
  50. else
  51. {
  52. if(entry.path.equals(path))
  53. return entry;
  54. }
  55. }
  56. return null;
  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. //{{{ getHistory() method
  68. /**
  69. * @since jEdit 4.2pre2
  70. */
  71. public static List getHistory()
  72. {
  73. return history;
  74. } //}}}
  75. //{{{ getBufferHistory() method
  76. /**
  77. * @deprecated Call {@link #getHistory()} instead.
  78. */
  79. public static Vector getBufferHistory()
  80. {
  81. Vector retVal = new Vector(history.size());
  82. Iterator iter = history.iterator();
  83. while(iter.hasNext())
  84. retVal.add(iter.next());
  85. return retVal;
  86. } //}}}
  87. //{{{ load() method
  88. public static void load()
  89. {
  90. String settingsDirectory = jEdit.getSettingsDirectory();
  91. if(settingsDirectory == null)
  92. return;
  93. File recent = new File(MiscUtilities.constructPath(
  94. settingsDirectory,"recent.xml"));
  95. if(!recent.exists())
  96. return;
  97. recentModTime = recent.lastModified();
  98. Log.log(Log.MESSAGE,BufferHistory.class,"Loading recent.xml");
  99. RecentHandler handler = new RecentHandler();
  100. XmlParser parser = new XmlParser();
  101. Reader in = null;
  102. parser.setHandler(handler);
  103. try
  104. {
  105. in = new BufferedReader(new FileReader(recent));
  106. parser.parse(null, null, in);
  107. }
  108. catch(XmlException xe)
  109. {
  110. int line = xe.getLine();
  111. String message = xe.getMessage();
  112. Log.log(Log.ERROR,BufferHistory.class,recent + ":" + line
  113. + ": " + message);
  114. }
  115. catch(FileNotFoundException fnf)
  116. {
  117. //Log.log(Log.DEBUG,BufferHistory.class,fnf);
  118. }
  119. catch(Exception e)
  120. {
  121. Log.log(Log.ERROR,BufferHistory.class,e);
  122. }
  123. finally
  124. {
  125. try
  126. {
  127. if(in != null)
  128. in.close();
  129. }
  130. catch(IOException io)
  131. {
  132. Log.log(Log.ERROR,BufferHistory.class,io);
  133. }
  134. }
  135. } //}}}
  136. //{{{ save() method
  137. public static void save()
  138. {
  139. String settingsDirectory = jEdit.getSettingsDirectory();
  140. if(settingsDirectory == null)
  141. return;
  142. File file1 = new File(MiscUtilities.constructPath(
  143. settingsDirectory, "#recent.xml#save#"));
  144. File file2 = new File(MiscUtilities.constructPath(
  145. settingsDirectory, "recent.xml"));
  146. if(file2.exists() && file2.lastModified() != recentModTime)
  147. {
  148. Log.log(Log.WARNING,BufferHistory.class,file2
  149. + " changed on disk; will not save recent"
  150. + " files");
  151. return;
  152. }
  153. jEdit.backupSettingsFile(file2);
  154. Log.log(Log.MESSAGE,BufferHistory.class,"Saving " + file1);
  155. String lineSep = System.getProperty("line.separator");
  156. try
  157. {
  158. BufferedWriter out = new BufferedWriter(
  159. new FileWriter(file1));
  160. out.write("<?xml version=\"1.0\"?>");
  161. out.write(lineSep);
  162. out.write("<!DOCTYPE RECENT SYSTEM \"recent.dtd\">");
  163. out.write(lineSep);
  164. out.write("<RECENT>");
  165. out.write(lineSep);
  166. Iterator iter = history.iterator();
  167. while(iter.hasNext())
  168. {
  169. out.write("<ENTRY>");
  170. out.write(lineSep);
  171. Entry entry = (Entry)iter.next();
  172. out.write("<PATH>");
  173. out.write(MiscUtilities.charsToEntities(entry.path));
  174. out.write("</PATH>");
  175. out.write(lineSep);
  176. out.write("<CARET>");
  177. out.write(String.valueOf(entry.caret));
  178. out.write("</CARET>");
  179. out.write(lineSep);
  180. if(entry.selection != null
  181. && entry.selection.length() > 0)
  182. {
  183. out.write("<SELECTION>");
  184. out.write(entry.selection);
  185. out.write("</SELECTION>");
  186. out.write(lineSep);
  187. }
  188. if(entry.encoding != null)
  189. {
  190. out.write("<ENCODING>");
  191. out.write(entry.encoding);
  192. out.write("</ENCODING>");
  193. out.write(lineSep);
  194. }
  195. out.write("</ENTRY>");
  196. out.write(lineSep);
  197. }
  198. out.write("</RECENT>");
  199. out.write(lineSep);
  200. out.close();
  201. /* to avoid data loss, only do this if the above
  202. * completed successfully */
  203. file2.delete();
  204. file1.renameTo(file2);
  205. }
  206. catch(Exception e)
  207. {
  208. Log.log(Log.ERROR,BufferHistory.class,e);
  209. }
  210. recentModTime = file2.lastModified();
  211. } //}}}
  212. //{{{ Private members
  213. private static LinkedList history;
  214. private static boolean pathsCaseInsensitive;
  215. private static long recentModTime;
  216. //{{{ Class initializer
  217. static
  218. {
  219. history = new LinkedList();
  220. pathsCaseInsensitive = OperatingSystem.isDOSDerived()
  221. || OperatingSystem.isMacOS();
  222. } //}}}
  223. //{{{ addEntry() method
  224. /* private */ static void addEntry(Entry entry)
  225. {
  226. history.addFirst(entry);
  227. int max = jEdit.getIntegerProperty("recentFiles",50);
  228. while(history.size() > max)
  229. history.removeLast();
  230. } //}}}
  231. //{{{ removeEntry() method
  232. /* private */ static void removeEntry(String path)
  233. {
  234. Iterator iter = history.iterator();
  235. while(iter.hasNext())
  236. {
  237. Entry entry = (Entry)iter.next();
  238. if(entry.path.equals(path))
  239. {
  240. iter.remove();
  241. return;
  242. }
  243. }
  244. } //}}}
  245. //{{{ selectionToString() method
  246. private static String selectionToString(Selection[] s)
  247. {
  248. if(s == null)
  249. return null;
  250. StringBuffer buf = new StringBuffer();
  251. for(int i = 0; i < s.length; i++)
  252. {
  253. if(i != 0)
  254. buf.append(' ');
  255. Selection sel = s[i];
  256. if(sel instanceof Selection.Range)
  257. buf.append("range ");
  258. else //if(sel instanceof Selection.Rect)
  259. buf.append("rect ");
  260. buf.append(sel.getStart());
  261. buf.append(' ');
  262. buf.append(sel.getEnd());
  263. }
  264. return buf.toString();
  265. } //}}}
  266. //{{{ stringToSelection() method
  267. private static Selection[] stringToSelection(String s)
  268. {
  269. if(s == null)
  270. return null;
  271. Vector selection = new Vector();
  272. StringTokenizer st = new StringTokenizer(s);
  273. while(st.hasMoreTokens())
  274. {
  275. String type = st.nextToken();
  276. int start = Integer.parseInt(st.nextToken());
  277. int end = Integer.parseInt(st.nextToken());
  278. if(end < start)
  279. {
  280. // I'm not sure when this can happen,
  281. // but it does sometimes, witness the
  282. // jEdit bug tracker.
  283. continue;
  284. }
  285. Selection sel;
  286. if(type.equals("range"))
  287. sel = new Selection.Range(start,end);
  288. else //if(type.equals("rect"))
  289. sel = new Selection.Rect(start,end);
  290. selection.addElement(sel);
  291. }
  292. Selection[] returnValue = new Selection[selection.size()];
  293. selection.copyInto(returnValue);
  294. return returnValue;
  295. } //}}}
  296. //}}}
  297. //{{{ Entry class
  298. /**
  299. * Recent file list entry.
  300. */
  301. public static class Entry
  302. {
  303. public String path;
  304. public int caret;
  305. public String selection;
  306. public String encoding;
  307. public Selection[] getSelection()
  308. {
  309. return stringToSelection(selection);
  310. }
  311. public Entry(String path, int caret, String selection, String encoding)
  312. {
  313. this.path = path;
  314. this.caret = caret;
  315. this.selection = selection;
  316. this.encoding = encoding;
  317. }
  318. } //}}}
  319. //{{{ RecentHandler class
  320. static class RecentHandler extends HandlerBase
  321. {
  322. public Object resolveEntity(String publicId, String systemId)
  323. {
  324. if("recent.dtd".equals(systemId))
  325. {
  326. // this will result in a slight speed up, since we
  327. // don't need to read the DTD anyway, as AElfred is
  328. // non-validating
  329. return new StringReader("<!-- -->");
  330. /* try
  331. {
  332. return new BufferedReader(new InputStreamReader(
  333. getClass().getResourceAsStream("recent.dtd")));
  334. }
  335. catch(Exception e)
  336. {
  337. Log.log(Log.ERROR,this,"Error while opening"
  338. + " recent.dtd:");
  339. Log.log(Log.ERROR,this,e);
  340. } */
  341. }
  342. return null;
  343. }
  344. public void doctypeDecl(String name, String publicId,
  345. String systemId) throws Exception
  346. {
  347. if("RECENT".equals(name))
  348. return;
  349. Log.log(Log.ERROR,this,"recent.xml: DOCTYPE must be RECENT");
  350. }
  351. public void endElement(String name)
  352. {
  353. if(name.equals("ENTRY"))
  354. {
  355. addEntry(new Entry(path,caret,selection,encoding));
  356. path = null;
  357. caret = 0;
  358. selection = null;
  359. encoding = null;
  360. }
  361. else if(name.equals("PATH"))
  362. path = charData;
  363. else if(name.equals("CARET"))
  364. caret = Integer.parseInt(charData);
  365. else if(name.equals("SELECTION"))
  366. selection = charData;
  367. else if(name.equals("ENCODING"))
  368. encoding = charData;
  369. }
  370. public void charData(char[] ch, int start, int length)
  371. {
  372. charData = new String(ch,start,length);
  373. }
  374. // end HandlerBase implementation
  375. // private members
  376. private String path;
  377. private int caret;
  378. private String selection;
  379. private String encoding;
  380. private String charData;
  381. } //}}}
  382. }