OSDN Git Service

9347616187b2ba92506661a575a5feca7efe74e4
[neighbornote/NeighborNote.git] / src / cx / fbn / nevernote / xml / NoteFormatter.java
1 package cx.fbn.nevernote.xml;\r
2 \r
3 import java.io.File;\r
4 import java.util.ArrayList;\r
5 import java.util.List;\r
6 \r
7 import com.evernote.edam.type.Note;\r
8 import com.evernote.edam.type.Resource;\r
9 import com.trolltech.qt.core.QByteArray;\r
10 import com.trolltech.qt.core.QDataStream;\r
11 import com.trolltech.qt.core.QFile;\r
12 import com.trolltech.qt.core.QIODevice;\r
13 import com.trolltech.qt.core.QIODevice.OpenModeFlag;\r
14 import com.trolltech.qt.core.QTemporaryFile;\r
15 import com.trolltech.qt.core.QUrl;\r
16 import com.trolltech.qt.xml.QDomAttr;\r
17 import com.trolltech.qt.xml.QDomDocument;\r
18 import com.trolltech.qt.xml.QDomElement;\r
19 import com.trolltech.qt.xml.QDomNodeList;\r
20 \r
21 import cx.fbn.nevernote.Global;\r
22 import cx.fbn.nevernote.config.FileManager;\r
23 import cx.fbn.nevernote.filters.EnSearch;\r
24 import cx.fbn.nevernote.gui.PDFPreview;\r
25 import cx.fbn.nevernote.sql.DatabaseConnection;\r
26 import cx.fbn.nevernote.utilities.ApplicationLogger;\r
27 \r
28 public class NoteFormatter {\r
29 \r
30         private final ApplicationLogger logger;\r
31         private final DatabaseConnection conn;\r
32         public boolean resourceError = false;\r
33         public boolean readOnly = false;\r
34         public boolean addHighlight = true;\r
35         private Note currentNote;\r
36         private String currentNoteGuid;\r
37         private boolean pdfPreview;\r
38         ArrayList<QTemporaryFile> tempFiles;\r
39         private EnSearch enSearch;\r
40         private boolean noteHistory;\r
41         \r
42         public NoteFormatter(ApplicationLogger logger, DatabaseConnection conn, List<QTemporaryFile> tempFiles2) {\r
43                 this.logger = logger;\r
44                 this.conn = conn;\r
45                 noteHistory = false;\r
46         }\r
47         \r
48         \r
49         public void setNote(Note note, boolean pdfPreview) {\r
50                 currentNote = note;\r
51                 this.pdfPreview = pdfPreview;\r
52                 currentNoteGuid = note.getGuid();\r
53                 readOnly = false;\r
54                 resourceError = false;\r
55         }\r
56         \r
57         public void setHighlight(EnSearch search) {\r
58                 if (search==null || search.hilightWords == null ||search.hilightWords.size() == 0) {\r
59                         enSearch = null;\r
60                         addHighlight = false;\r
61                 } else {\r
62                         enSearch = search;\r
63                         addHighlight = true;\r
64                 }\r
65         }\r
66         \r
67         // Set if we are coming here through note histary.  It triggers longer file names to avoid conflicts\r
68         public void setNoteHistory(boolean value) {\r
69                 noteHistory = value;\r
70         }\r
71         \r
72         // Rebuild the note HTML to something usable\r
73         public String rebuildNoteHTML() {\r
74                 logger.log(logger.HIGH, "Entering NeverNote.rebuildNoteHTML");\r
75                 logger.log(logger.EXTREME, "Note guid: " +currentNoteGuid);\r
76                 logger.log(logger.EXTREME, "Note Text:" +currentNote);\r
77                 QDomDocument doc = new QDomDocument();\r
78                 QDomDocument.Result result = doc.setContent(currentNote.getContent());\r
79                 if (!result.success) {\r
80                         logger.log(logger.MEDIUM, "Parse error when rebuilding HTML");\r
81                         logger.log(logger.MEDIUM, "Note guid: " +currentNoteGuid);\r
82                         logger.log(logger.EXTREME, "Start of unmodified note HTML");\r
83                         logger.log(logger.EXTREME, currentNote.getContent());\r
84                         logger.log(logger.EXTREME, "End of unmodified note HTML");\r
85                         return currentNote.getContent();\r
86                 }\r
87 \r
88                 if (tempFiles == null)\r
89                         tempFiles = new ArrayList<QTemporaryFile>();\r
90                 tempFiles.clear();\r
91                 \r
92                 doc = modifyTags(doc);\r
93                 if (addHighlight)\r
94                         doc = addHilight(doc);\r
95                 QDomElement docElem = doc.documentElement();\r
96                 docElem.setTagName("Body");\r
97 //              docElem.setAttribute("bgcolor", "green");\r
98                 logger.log(logger.EXTREME, "Rebuilt HTML:");\r
99                 logger.log(logger.EXTREME, doc.toString());     \r
100                 logger.log(logger.HIGH, "Leaving NeverNote.rebuildNoteHTML");\r
101                 // Fix the stupid problem where inserting an <img> tag after an <a> tag (which is done\r
102                 // to get the <en-media> application tag to work properly) causes spaces to be inserted\r
103                 // between the <a> & <img>.  This messes things up later.  This is an ugly hack.\r
104                 StringBuffer html = new StringBuffer(doc.toString());\r
105                 for (int i=html.indexOf("<a en-tag=\"en-media\" ", 0); i>-1; i=html.indexOf("<a en-tag=\"en-media\" ", i)) {\r
106                         i=html.indexOf(">\n",i+1);\r
107                         int z = html.indexOf("<img",i);\r
108                         for (int j=z-1; j>i; j--) \r
109                                 html.deleteCharAt(j);\r
110                         i=html.indexOf("/>", z+1);\r
111                         z = html.indexOf("</a>",i);\r
112                         for (int j=z-1; j>i+1; j--) \r
113                                 html.deleteCharAt(j);\r
114                 } \r
115                 return html.toString();\r
116         }       \r
117 \r
118         \r
119     // Modify the en-media tag into an image tag so it can be displayed.\r
120     private void modifyImageTags(QDomElement docElem, QDomElement enmedia, QDomAttr hash) {\r
121         logger.log(logger.HIGH, "Entering NeverNote.modifyImageTags");\r
122         String type = enmedia.attribute("type");\r
123         if (type.startsWith("image/"))\r
124                 type = "."+type.substring(6);\r
125         else\r
126                 type="";\r
127         \r
128         String resGuid = conn.getNoteTable().noteResourceTable.getNoteResourceGuidByHashHex(currentNoteGuid, hash.value());\r
129         QFile tfile = new QFile(Global.getFileManager().getResDirPath(resGuid + type));\r
130         if (!tfile.exists()) {\r
131                 Resource r = null;\r
132                 if (resGuid != null)\r
133                         r = conn.getNoteTable().noteResourceTable.getNoteResource(resGuid,true);\r
134                         if (r==null || r.getData() == null || r.getData().getBody().length == 0)\r
135                                 resourceError = true;;\r
136                         if (r!= null && r.getData() != null && r.getData().getBody().length > 0) {\r
137                                 tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));\r
138                                 QByteArray binData = new QByteArray(r.getData().getBody());\r
139                                 tfile.write(binData);\r
140                                 tfile.close();\r
141                                 enmedia.setAttribute("src", QUrl.fromLocalFile(tfile.fileName()).toString());\r
142                                 enmedia.setAttribute("en-tag", "en-media");\r
143                                 enmedia.setNodeValue("");\r
144                         enmedia.setAttribute("guid", r.getGuid());\r
145                         enmedia.setTagName("img");\r
146                 }\r
147         }\r
148         // Technically, we should do a file:// to have a proper url, but for some reason QWebPage hates\r
149         // them and won't generate a thumbnail image properly if we use them.\r
150 //              enmedia.setAttribute("src", QUrl.fromLocalFile(tfile.fileName()).toString());\r
151                 enmedia.setAttribute("src", tfile.fileName().toString());\r
152                 enmedia.setAttribute("en-tag", "en-media");\r
153                 enmedia.setAttribute("onContextMenu", "window.jambi.imageContextMenu('" +tfile.fileName()  +"');");\r
154                 enmedia.setNodeValue("");\r
155                 enmedia.setAttribute("guid", resGuid);\r
156                 enmedia.setTagName("img");\r
157 \r
158                 logger.log(logger.HIGH, "Leaving NeverNote.modifyImageTags");\r
159     }\r
160     \r
161     \r
162         // Modify tags from Evernote specific things to XHTML tags.\r
163         private QDomDocument modifyTags(QDomDocument doc) {\r
164                 logger.log(logger.HIGH, "Entering NeverNote.modifyTags");\r
165                 if (tempFiles == null)\r
166                         tempFiles = new ArrayList<QTemporaryFile>();\r
167                 tempFiles.clear();\r
168                 QDomElement docElem = doc.documentElement();\r
169                 \r
170                 // Modify en-media tags\r
171                 QDomNodeList anchors = docElem.elementsByTagName("en-media");\r
172                 int enMediaCount = anchors.length();\r
173                 for (int i=enMediaCount-1; i>=0; i--) {\r
174                         QDomElement enmedia = anchors.at(i).toElement();\r
175                         if (enmedia.hasAttribute("type")) {\r
176                                 QDomAttr attr = enmedia.attributeNode("type");\r
177                                 QDomAttr hash = enmedia.attributeNode("hash");\r
178                                 String[] type = attr.nodeValue().split("/");\r
179                                 String appl = type[1];\r
180                                 \r
181                                 if (type[0] != null) {\r
182                                         if (type[0].equals("image")) {\r
183                                                 modifyImageTags(docElem, enmedia, hash);\r
184                                         }\r
185                                         if (!type[0].equals("image")) {\r
186                                                 modifyApplicationTags(doc, docElem, enmedia, hash, appl);\r
187                                         }\r
188                                 }\r
189                         }\r
190                 }\r
191                 \r
192                 // Modify todo tags\r
193                 anchors = docElem.elementsByTagName("en-todo");\r
194                 int enTodoCount = anchors.length();\r
195                 for (int i=enTodoCount-1; i>=0; i--) {\r
196                         QDomElement enmedia = anchors.at(i).toElement();\r
197                         modifyTodoTags(enmedia);\r
198                 }\r
199                 \r
200                 // Modify en-crypt tags\r
201                 anchors = docElem.elementsByTagName("en-crypt");\r
202                 int enCryptLen = anchors.length();\r
203                 for (int i=enCryptLen-1; i>=0; i--) {\r
204                         QDomElement enmedia = anchors.at(i).toElement();\r
205                         enmedia.setAttribute("contentEditable","false");\r
206                         enmedia.setAttribute("src", Global.getFileManager().getImageDirPath("encrypt.png"));\r
207                         enmedia.setAttribute("en-tag","en-crypt");\r
208                         enmedia.setAttribute("alt", enmedia.text());\r
209                         Global.cryptCounter++;\r
210                         enmedia.setAttribute("id", "crypt"+Global.cryptCounter.toString());\r
211                         String encryptedText = enmedia.text();\r
212                         \r
213                         // If the encryption string contains crlf at the end, remove them because they mess up the javascript.\r
214                         if (encryptedText.endsWith("\n"))\r
215                                 encryptedText = encryptedText.substring(0,encryptedText.length()-1);\r
216                         if (encryptedText.endsWith("\r"))\r
217                                 encryptedText = encryptedText.substring(0,encryptedText.length()-1);\r
218                         \r
219                         // Add the commands\r
220                         String hint = enmedia.attribute("hint");\r
221                         hint = hint.replace("'","&apos;");\r
222                         enmedia.setAttribute("onClick", "window.jambi.decryptText('crypt"+Global.cryptCounter.toString()+"', '"+encryptedText+"', '"+hint+"');");\r
223                         enmedia.setAttribute("onMouseOver", "style.cursor='hand'");\r
224                         enmedia.setTagName("img");\r
225                         enmedia.removeChild(enmedia.firstChild());   // Remove the actual encrypted text\r
226                 }\r
227 \r
228                 \r
229                 // Modify link tags\r
230                 anchors = docElem.elementsByTagName("a");\r
231                 enCryptLen = anchors.length();\r
232                 for (int i=0; i<anchors.length(); i++) {\r
233                         QDomElement element = anchors.at(i).toElement();\r
234                         element.setAttribute("title", element.attribute("href"));\r
235                 }\r
236 \r
237                 logger.log(logger.HIGH, "Leaving NeverNote.modifyTags");\r
238                 return doc;\r
239         }\r
240         \r
241 \r
242         // Get an ink note image.  If an image doesn't exist then we fall back \r
243         // to the old ugly icon\r
244     private boolean buildInkNote(QDomDocument doc, QDomElement docElem, QDomElement enmedia, QDomAttr hash, String appl) {\r
245         String resGuid = conn.getNoteTable().noteResourceTable.getNoteResourceGuidByHashHex(currentNote.getGuid(), hash.value());\r
246         Resource r = conn.getNoteTable().noteResourceTable.getNoteResource(resGuid, false);\r
247  \r
248         // If we can't find the resource, then fall back to the old method.  We'll return & show\r
249         // an error later\r
250         if (r == null || r.getData() == null) \r
251                 return false;\r
252         \r
253         // If there isn't some type of error, continue on.\r
254                 if (!resourceError) {\r
255                         \r
256                         // Get a list of images in the database.  We'll use these to bulid the page.\r
257                         List<QByteArray> data = conn.getInkImagesTable().getImage(r.getGuid());\r
258                         \r
259                         // If no pictures are found, go back to & just show the icon\r
260                         if (data.size() == 0)\r
261                                 return false;\r
262                         \r
263                         // We have pictures, so append them to the page.  This really isn't proper since\r
264                         // we leave the en-media tag in place, but since we can't edit the page it doesn't\r
265                         // hurt anything.\r
266                         for (int i=0; i<data.size(); i++) {\r
267                         QFile f = new QFile(Global.getFileManager().getResDirPath(resGuid + new Integer(i).toString()+".png"));\r
268                                 f.open(OpenModeFlag.WriteOnly);\r
269                                 f.write(data.get(i));\r
270                                 f.close();\r
271                                 QDomElement newImage = doc.createElement("img");\r
272                                 newImage.setAttribute("src", QUrl.fromLocalFile(f.fileName()).toString());\r
273                                 enmedia.appendChild(newImage);\r
274                         }\r
275                         return true;\r
276                 }\r
277         return false;\r
278     }\r
279         \r
280         \r
281     // Modify the en-media tag into an attachment\r
282     private void modifyApplicationTags(QDomDocument doc, QDomElement docElem, QDomElement enmedia, QDomAttr hash, String appl) {\r
283         logger.log(logger.HIGH, "Entering NeverNote.modifyApplicationTags");\r
284         if (appl.equalsIgnoreCase("vnd.evernote.ink")) {\r
285                 readOnly = true;\r
286             if (buildInkNote(doc, docElem, enmedia, hash, appl))\r
287                 return;\r
288         }\r
289         String resGuid = conn.getNoteTable().noteResourceTable.getNoteResourceGuidByHashHex(currentNote.getGuid(), hash.value());\r
290         Resource r = conn.getNoteTable().noteResourceTable.getNoteResource(resGuid, false);\r
291         if (r == null || r.getData() == null) \r
292                 resourceError = true;\r
293                 if (r!= null) {\r
294                         if (r.getData()!=null) {\r
295                                 // Did we get a generic applicaiton?  Then look at the file name to \r
296                                 // try and find a good application type for the icon\r
297                                 if (appl.equalsIgnoreCase("octet-stream")) {\r
298                                         if (r.getAttributes() != null && r.getAttributes().getFileName() != null) {\r
299                                                 String fn = r.getAttributes().getFileName();\r
300                                                 int pos = fn.lastIndexOf(".");\r
301                                                 if (pos > -1) {\r
302                                                         appl = fn.substring(pos+1);\r
303                                                 }\r
304                                         }\r
305                                 }\r
306                                 \r
307                                 String fileDetails = null;\r
308                                 if (r.getAttributes() != null && r.getAttributes().getFileName() != null && !r.getAttributes().getFileName().equals(""))\r
309                                         fileDetails = r.getAttributes().getFileName();\r
310                                 String contextFileName;\r
311                                 FileManager fileManager = Global.getFileManager();\r
312                 if (fileDetails != null && !fileDetails.equals("")) {\r
313                         if (!noteHistory) {\r
314                                 enmedia.setAttribute("href", "nnres://" +r.getGuid() \r
315                                                 +Global.attachmentNameDelimeter +fileDetails);\r
316                                 contextFileName = fileManager.getResDirPath(r.getGuid() \r
317                                                 +Global.attachmentNameDelimeter + fileDetails);\r
318                         } else {\r
319                                 enmedia.setAttribute("href", "nnres://" +r.getGuid() + currentNote.getUpdateSequenceNum() \r
320                                                 +Global.attachmentNameDelimeter +fileDetails);\r
321                                 contextFileName = fileManager.getResDirPath(r.getGuid() + currentNote.getUpdateSequenceNum() \r
322                                                 +Global.attachmentNameDelimeter + fileDetails);\r
323                         }\r
324                                 } else { \r
325                                         if (!noteHistory) {\r
326                                                 enmedia.setAttribute("href", "nnres://" +r.getGuid() +currentNote.getUpdateSequenceNum()\r
327                                                                 +Global.attachmentNameDelimeter +appl);\r
328                                                 contextFileName = fileManager.getResDirPath(r.getGuid() +currentNote.getUpdateSequenceNum() \r
329                                                                 +Global.attachmentNameDelimeter + appl);\r
330                                         } else {\r
331                                                 enmedia.setAttribute("href", "nnres://" +r.getGuid() \r
332                                                                 +Global.attachmentNameDelimeter +appl);\r
333                                                 contextFileName = fileManager.getResDirPath(r.getGuid() \r
334                                                                 +Global.attachmentNameDelimeter + appl);\r
335                                         }\r
336                                 }\r
337                                 contextFileName = contextFileName.replace("\\", "/");\r
338                                 enmedia.setAttribute("onContextMenu", "window.jambi.resourceContextMenu('" +contextFileName +"');");\r
339                                 if (fileDetails == null || fileDetails.equals(""))\r
340                                         fileDetails = "";\r
341                                 enmedia.setAttribute("en-tag", "en-media");\r
342                                 enmedia.setAttribute("guid", r.getGuid());\r
343                                 enmedia.setTagName("a");\r
344                                 QDomElement newText = doc.createElement("img");\r
345                                 boolean goodPreview = false;\r
346                                 String filePath = "";\r
347                                 if (appl.equalsIgnoreCase("pdf") && pdfPreview) {\r
348                                         String fileName;\r
349                                         Resource res = conn.getNoteTable().noteResourceTable.getNoteResource(r.getGuid(), true);\r
350                                         if (res.getAttributes() != null && \r
351                                                         res.getAttributes().getFileName() != null && \r
352                                                         !res.getAttributes().getFileName().trim().equals(""))\r
353                                                 fileName = res.getGuid()+Global.attachmentNameDelimeter+res.getAttributes().getFileName();\r
354                                         else\r
355                                                 fileName = res.getGuid()+".pdf";\r
356                                         QFile file = new QFile(fileManager.getResDirPath(fileName));\r
357                                 QFile.OpenMode mode = new QFile.OpenMode();\r
358                                 mode.set(QFile.OpenModeFlag.WriteOnly);\r
359                                 file.open(mode);\r
360                                 QDataStream out = new QDataStream(file);\r
361                                 Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(res.getGuid(), true);\r
362                                         QByteArray binData = new QByteArray(resBinary.getData().getBody());\r
363                                         resBinary = null;\r
364                                 out.writeBytes(binData.toByteArray());\r
365                                 file.close();\r
366                                 PDFPreview pdfPreview = new PDFPreview();\r
367                                         goodPreview = pdfPreview.setupPreview(file.fileName(), appl,0);\r
368                                         if (goodPreview) {\r
369                                                 QDomElement span = doc.createElement("span");\r
370                                                 QDomElement table = doc.createElement("table");\r
371                                                 span.setAttribute("pdfNavigationTable", "true");\r
372                                                 QDomElement tr = doc.createElement("tr");\r
373                                                 QDomElement td = doc.createElement("td");\r
374                                                 QDomElement left = doc.createElement("img");\r
375                                                 left.setAttribute("onMouseDown", "window.jambi.nextPage('" +file.fileName() +"')");\r
376                                                 left.setAttribute("onMouseDown", "window.jambi.nextPage('" +file.fileName() +"')");\r
377                                                 left.setAttribute("onMouseOver", "style.cursor='hand'");\r
378                                                 QDomElement right = doc.createElement("img");\r
379                                                 right.setAttribute("onMouseDown", "window.jambi.nextPage('" +file.fileName() +"')");\r
380                                                 left.setAttribute("onMouseDown", "window.jambi.previousPage('" +file.fileName() +"')");\r
381                                                 // NFC TODO: should these be file:// URLs?\r
382                                                 left.setAttribute("src", Global.getFileManager().getImageDirPath("small_left.png"));\r
383                                                 right.setAttribute("src", Global.getFileManager().getImageDirPath("small_right.png"));\r
384                                                 right.setAttribute("onMouseOver", "style.cursor='hand'");\r
385                                                 \r
386                                                 table.appendChild(tr);\r
387                                                 tr.appendChild(td);\r
388                                                 td.appendChild(left);\r
389                                                 td.appendChild(right);\r
390                                                 span.appendChild(table);\r
391                                                 enmedia.parentNode().insertBefore(span, enmedia);\r
392                                         } \r
393                                         filePath = fileName+".png";\r
394                                 }\r
395                                 String icon = findIcon(appl);\r
396                                 if (icon.equals("attachment.png"))\r
397                                         icon = findIcon(fileDetails.substring(fileDetails.indexOf(".")+1));\r
398                                 // NFC TODO: should this be a 'file://' URL?\r
399                                 newText.setAttribute("src", Global.getFileManager().getImageDirPath(icon));\r
400                                 if (goodPreview) {\r
401                                 // NFC TODO: should this be a 'file://' URL?\r
402                                         newText.setAttribute("src", fileManager.getResDirPath(filePath));\r
403                                         newText.setAttribute("style", "border-style:solid; border-color:green; padding:0.5mm 0.5mm 0.5mm 0.5mm;");\r
404                                 }\r
405                                 newText.setAttribute("title", fileDetails);\r
406                                 enmedia.removeChild(enmedia.firstChild());\r
407                                 \r
408                                 enmedia.appendChild(newText);\r
409                         }\r
410                 }\r
411                 logger.log(logger.HIGH, "Leaving NeverNote.modifyApplicationTags");\r
412     }\r
413     // Modify the en-to tag into an input field\r
414     private void modifyTodoTags(QDomElement todo) {\r
415         logger.log(logger.HIGH, "Entering NeverNote.modifyTodoTags");\r
416                 todo.setAttribute("type", "checkbox");\r
417                 String checked = todo.attribute("checked");\r
418                 todo.removeAttribute("checked");\r
419                 if (checked.equalsIgnoreCase("true"))\r
420                         todo.setAttribute("checked", "");\r
421                 else\r
422                         todo.setAttribute("unchecked","");\r
423                 todo.setAttribute("value", checked);\r
424                 todo.setAttribute("onClick", "value=checked;window.jambi.contentChanged(); ");\r
425                 todo.setTagName("input");\r
426                 logger.log(logger.HIGH, "Leaving NeverNote.modifyTodoTags");\r
427     }\r
428     \r
429     \r
430     \r
431     // Modify any cached todo tags that may have changed\r
432     public String modifyCachedTodoTags(String note) {\r
433         logger.log(logger.HIGH, "Entering NeverNote.modifyCachedTodoTags");\r
434         StringBuffer html = new StringBuffer(note);\r
435                 for (int i=html.indexOf("<input", 0); i>-1; i=html.indexOf("<input", i)) {\r
436                         int endPos =html.indexOf(">",i+1);\r
437                         String input = html.substring(i,endPos);\r
438                         if (input.indexOf("value=\"true\"") > 0) \r
439                                 input = input.replace(" unchecked=\"\"", " checked=\"\"");\r
440                         else\r
441                                 input = input.replace(" checked=\"\"", " unchecked=\"\"");\r
442                         html.replace(i, endPos, input);\r
443                         i++;\r
444                 }\r
445                 logger.log(logger.HIGH, "Leaving NeverNote.modifyCachedTodoTags");\r
446                 return html.toString();\r
447     }\r
448     \r
449     \r
450 \r
451 \r
452         // Scan and do hilighting of words\r
453         public QDomDocument addHilight(QDomDocument doc) {\r
454 //              EnSearch e = listManager.getEnSearch();\r
455                 if (enSearch.hilightWords == null || enSearch.hilightWords.size() == 0)\r
456                         return doc;\r
457                 XMLInsertHilight hilight = new XMLInsertHilight(doc, enSearch.hilightWords);\r
458                 return hilight.getDoc();\r
459         }\r
460         \r
461         \r
462     // find the appropriate icon for an attachment\r
463     private String findIcon(String appl) {\r
464         logger.log(logger.HIGH, "Entering NeverNote.findIcon");\r
465         appl = appl.toLowerCase();\r
466         String relativePath = appl + ".png";\r
467         File f = Global.getFileManager().getImageDirFile(relativePath);\r
468         if (f.exists()) {\r
469             return relativePath;\r
470         }\r
471         if (f.exists())\r
472                 return appl+".png";\r
473         logger.log(logger.HIGH, "Leaving NeverNote.findIcon");\r
474         return "attachment.png";\r
475     }\r
476 \r
477 \r
478 }\r