package cx.fbn.nevernote.xml;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.w3c.tidy.Tidy;
import org.w3c.tidy.TidyMessage;
import com.evernote.edam.type.Note;
import com.evernote.edam.type.Resource;
import com.trolltech.qt.core.QByteArray;
import com.trolltech.qt.core.QDataStream;
import com.trolltech.qt.core.QFile;
import com.trolltech.qt.core.QIODevice;
import com.trolltech.qt.core.QIODevice.OpenModeFlag;
import com.trolltech.qt.core.QTemporaryFile;
import com.trolltech.qt.core.QTextCodec;
import com.trolltech.qt.core.QUrl;
import com.trolltech.qt.core.Qt.BGMode;
import com.trolltech.qt.gui.QColor;
import com.trolltech.qt.gui.QPainter;
import com.trolltech.qt.gui.QPainter.RenderHint;
import com.trolltech.qt.gui.QPixmap;
import com.trolltech.qt.xml.QDomAttr;
import com.trolltech.qt.xml.QDomDocument;
import com.trolltech.qt.xml.QDomElement;
import com.trolltech.qt.xml.QDomNodeList;
import cx.fbn.nevernote.Global;
import cx.fbn.nevernote.config.FileManager;
import cx.fbn.nevernote.filters.EnSearch;
import cx.fbn.nevernote.gui.PDFPreview;
import cx.fbn.nevernote.sql.DatabaseConnection;
import cx.fbn.nevernote.utilities.ApplicationLogger;
public class NoteFormatter {
private final ApplicationLogger logger;
private final DatabaseConnection conn;
public boolean resourceError = false;
public boolean readOnly = false;
public boolean inkNote = false;
public boolean addHighlight = true;
private Note currentNote;
private String currentNoteGuid;
private boolean pdfPreview;
ArrayList<QTemporaryFile> tempFiles;
private EnSearch enSearch;
private boolean noteHistory;
public boolean formatError;
public NoteFormatter(ApplicationLogger logger, DatabaseConnection conn, List<QTemporaryFile> tempFiles2) {
this.logger = logger;
this.conn = conn;
noteHistory = false;
}
private class TidyListener implements org.w3c.tidy.TidyMessageListener {
ApplicationLogger logger;
public boolean errorFound;
public TidyListener(ApplicationLogger logger) {
this.logger = logger;
errorFound = false;
}
@Override
public void messageReceived(TidyMessage msg) {
if (msg.getLevel() == TidyMessage.Level.ERROR) {
logger.log(logger.LOW, "******* JTIDY ERORR *******");
logger.log(logger.LOW, "Error Code: " +msg.getErrorCode());
logger.log(logger.LOW, "Column: " +msg.getColumn());
logger.log(logger.LOW, "Column: " +msg.getColumn());
logger.log(logger.LOW, "Line: " +msg.getLine());
logger.log(logger.LOW, "Message: " +msg.getMessage());
logger.log(logger.LOW, "***************************");
errorFound = true;
} else
logger.log(logger.EXTREME, "JTidy Results: "+msg.getMessage());
}
}
public void setNote(Note note, boolean pdfPreview) {
currentNote = note;
this.pdfPreview = pdfPreview;
readOnly = false;
currentNoteGuid = null;
if (note != null) {
currentNoteGuid = note.getGuid();
readOnly = conn.getNotebookTable().isReadOnly(note.getNotebookGuid());
}
resourceError = false;
}
public void setHighlight(EnSearch search) {
if (search==null || search.hilightWords == null ||search.hilightWords.size() == 0) {
enSearch = null;
addHighlight = false;
} else {
enSearch = search;
addHighlight = true;
}
}
// Set if we are coming here through note histary. It triggers longer file names to avoid conflicts
public void setNoteHistory(boolean value) {
noteHistory = value;
}
// Rebuild the note HTML to something usable
public String rebuildNoteHTML() {
formatError = false;
if (currentNote == null)
return null;
logger.log(logger.HIGH, "Entering NeverNote.rebuildNoteHTML");
logger.log(logger.EXTREME, "Note guid: " +currentNoteGuid);
logger.log(logger.EXTREME, "Note Text:" +currentNote);
QDomDocument doc = new QDomDocument();
QDomDocument.Result result = doc.setContent(currentNote.getContent());
// Handle any errors
if (!result.success) {
logger.log(logger.LOW, "Error parsing document. Attempting to restructure");
Tidy tidy = new Tidy();
TidyListener tidyListener = new TidyListener(logger);
tidy.setMessageListener(tidyListener);
tidy.getStderr().close(); // the listener will capture messages
tidy.setXmlTags(true);
QTextCodec codec;
codec = QTextCodec.codecForName("UTF-8");
QByteArray unicode = codec.fromUnicode(currentNote.getContent());
logger.log(logger.MEDIUM, "Starting JTidy check");
logger.log(logger.MEDIUM, "Start of JTidy Input");
logger.log(logger.MEDIUM, currentNote.getContent());
logger.log(logger.MEDIUM, "End Of JTidy Input");
ByteArrayInputStream is = new ByteArrayInputStream(unicode.toByteArray());
ByteArrayOutputStream os = new ByteArrayOutputStream();
tidy.setInputEncoding("UTF-8");
tidy.parse(is, os);
String tidyContent = os.toString();
if (tidyListener.errorFound) {
logger.log(logger.LOW, "Restructure failed!!!");
} else {
doc = null;
doc = new QDomDocument();
result = doc.setContent(tidyContent);
}
}
if (!result.success) {
logger.log(logger.MEDIUM, "Parse error when rebuilding XML to HTML");
logger.log(logger.MEDIUM, "Note guid: " +currentNoteGuid);
logger.log(logger.MEDIUM, "Error: "+result.errorMessage);
logger.log(logger.MEDIUM, "Line: " +result.errorLine + " Column: " +result.errorColumn);
System.out.println("Error: "+result.errorMessage);
System.out.println("Line: " +result.errorLine + " Column: " +result.errorColumn);
logger.log(logger.EXTREME, "**** Start of unmodified note HTML");
logger.log(logger.EXTREME, currentNote.getContent());
logger.log(logger.EXTREME, "**** End of unmodified note HTML");
formatError = true;
readOnly = true;
return currentNote.getContent();
}
if (tempFiles == null)
tempFiles = new ArrayList<QTemporaryFile>();
tempFiles.clear();
doc = modifyTags(doc);
if (addHighlight)
doc = addHilight(doc);
QDomElement docElem = doc.documentElement();
docElem.setTagName("Body");
// docElem.setAttribute("bgcolor", "green");
logger.log(logger.EXTREME, "Rebuilt HTML:");
logger.log(logger.EXTREME, doc.toString());
logger.log(logger.HIGH, "Leaving NeverNote.rebuildNoteHTML");
// Fix the stupid problem where inserting an <img> tag after an <a> tag (which is done
// to get the <en-media> application tag to work properly) causes spaces to be inserted
// between the <a> & <img>. This messes things up later. This is an ugly hack.
StringBuffer html = new StringBuffer(doc.toString());
for (int i=html.indexOf("<a en-tag=\"en-media\" ", 0); i>-1; i=html.indexOf("<a en-tag=\"en-media\" ", i)) {
i=html.indexOf(">\n",i+1);
int z = html.indexOf("<img",i);
for (int j=z-1; j>i; j--)
html.deleteCharAt(j);
i=html.indexOf("/>", z+1);
z = html.indexOf("</a>",i);
for (int j=z-1; j>i+1; j--)
html.deleteCharAt(j);
}
return html.toString(); //.replace("<Body", "<Body dir=\"rtl\"");
}
private void addImageHilight(String resGuid, QFile f) {
if (enSearch == null || enSearch.hilightWords == null || enSearch.hilightWords.size() == 0)
return;
// Get the recognition XML that tells where to hilight on the image
Resource recoResource = conn.getNoteTable().noteResourceTable.getNoteResourceRecognition(resGuid);
if (recoResource.getRecognition().getBody() == null || recoResource.getRecognition().getBody().length == 0)
return;
QByteArray recoData = new QByteArray(recoResource.getRecognition().getBody());
String xml = recoData.toString();
// Get a painter for the image. This is the background (the initial image).
QPixmap pix = new QPixmap(f.fileName());
QPixmap hilightedPix = new QPixmap(pix.size());
QPainter p = new QPainter(hilightedPix);
p.drawPixmap(0,0, pix);
// Create a transparent pixmap. The only non-transparent
// piece is the hilight that will be overlayed to hilight text no the background
QPixmap overlayPix = new QPixmap(pix.size());
overlayPix.fill(QColor.transparent);
QPainter p2 = new QPainter(overlayPix);
p2.setBackgroundMode(BGMode.TransparentMode);
p2.setRenderHint(RenderHint.Antialiasing, true);
QColor yellow = QColor.yellow;
// yellow.setAlphaF(0.4);
p2.setBrush(yellow);
// Get the recognition data from the note
QDomDocument doc = new QDomDocument();
doc.setContent(xml);
// Go through all "item" nodes
QDomNodeList anchors = doc.elementsByTagName("item");
for (int i=0; i<anchors.length(); i++) {
QDomElement element = anchors.at(i).toElement();
int x = new Integer(element.attribute("x")); // x coordinate
int y = new Integer(element.attribute("y")); // y coordinate
int w = new Integer(element.attribute("w")); // width
int h = new Integer(element.attribute("h")); // height
QDomNodeList children = element.childNodes(); // all children ("t" nodes).
// Go through the children ("t" nodes)
for (int j=0; j<children.length(); j++) {
QDomElement child = children.at(j).toElement();
if (child.nodeName().equalsIgnoreCase("t")) {
String text = child.text(); // recognition text
int weight = new Integer(child.attribute("w")); // recognition weight
if (weight >= Global.getRecognitionWeight()) { // Are we above the maximum?
// Check to see if this word matches something we were searching for.
for (int k=0; k<enSearch.hilightWords.size(); k++) {
String searchWord = enSearch.hilightWords.get(k).toLowerCase();
if (searchWord.startsWith("*"))
searchWord = searchWord.substring(1);
if (searchWord.endsWith("*"))
searchWord = searchWord.substring(0,searchWord.length()-1);
if (text.toLowerCase().contains(searchWord)) {
p2.drawRect(x,y,w,h);
}
}
}
}
}
}
p2.end();
// Paint the hilight onto the background.
p.setOpacity(0.4);
p.drawPixmap(0,0, overlayPix);
p.end();
// Save over the initial pixmap.
hilightedPix.save(f.fileName());
}
// Modify the en-media tag into an image tag so it can be displayed.
private void modifyImageTags(QDomDocument doc, QDomElement docElem, QDomElement enmedia, QDomAttr hash) {
logger.log(logger.HIGH, "Entering NeverNote.modifyImageTags");
String type = enmedia.attribute("type");
if (type.startsWith("image/"))
type = "."+type.substring(6);
else
type="";
String resGuid = conn.getNoteTable().noteResourceTable.getNoteResourceGuidByHashHex(currentNoteGuid, hash.value());
QFile tfile = new QFile(Global.getFileManager().getResDirPath(resGuid + type));
// if (!tfile.exists()) {
Resource r = null;
if (resGuid != null)
r = conn.getNoteTable().noteResourceTable.getNoteResource(resGuid,true);
if (r==null || r.getData() == null || r.getData().getBody().length == 0) {
resourceError = true;
readOnly = true;
}
if (r!= null && r.getData() != null && r.getData().getBody().length > 0) {
tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));
QByteArray binData = new QByteArray(r.getData().getBody());
tfile.write(binData);
tfile.close();
// If we have recognition text, outline it
addImageHilight(r.getGuid(), tfile);
enmedia.setAttribute("src", QUrl.fromLocalFile(tfile.fileName()).toString());
enmedia.setAttribute("en-tag", "en-media");
enmedia.setNodeValue("");
enmedia.setAttribute("guid", r.getGuid());
enmedia.setTagName("img");
}
// }
// Technically, we should do a file:// to have a proper url, but for some reason QWebPage hates
// them and won't generate a thumbnail image properly if we use them.
// enmedia.setAttribute("src", QUrl.fromLocalFile(tfile.fileName()).toString());
enmedia.setAttribute("src", tfile.fileName().toString());
enmedia.setAttribute("en-tag", "en-media");
enmedia.setTagName("img");
if (r != null && r.getAttributes() != null &&
(r.getAttributes().getSourceURL() == null || !r.getAttributes().getSourceURL().toLowerCase().startsWith("http://latex.codecogs.com/gif.latex?")))
enmedia.setAttribute("onContextMenu", "window.jambi.imageContextMenu('" +tfile.fileName() +"');");
else {
QDomElement newText = doc.createElement("a");
enmedia.setAttribute("src", tfile.fileName().toString());
enmedia.setAttribute("en-tag", "en-latex");
newText.setAttribute("onMouseOver", "style.cursor='hand'");
if (r!= null && r.getAttributes() != null && r.getAttributes().getSourceURL() != null)
newText.setAttribute("title", r.getAttributes().getSourceURL());
newText.setAttribute("href", "latex://"+tfile.fileName().toString());
enmedia.parentNode().replaceChild(newText, enmedia);
newText.appendChild(enmedia);
}
enmedia.setNodeValue("");
enmedia.setAttribute("guid", resGuid);
logger.log(logger.HIGH, "Leaving NeverNote.modifyImageTags");
}
// Modify tags from Evernote specific things to XHTML tags.
private QDomDocument modifyTags(QDomDocument doc) {
logger.log(logger.HIGH, "Entering NeverNote.modifyTags");
if (tempFiles == null)
tempFiles = new ArrayList<QTemporaryFile>();
tempFiles.clear();
QDomElement docElem = doc.documentElement();
// Modify en-media tags
QDomNodeList anchors = docElem.elementsByTagName("en-media");
int enMediaCount = anchors.length();
for (int i=enMediaCount-1; i>=0; --i) {
QDomElement enmedia = anchors.at(i).toElement();
if (enmedia.hasAttribute("type")) {
QDomAttr attr = enmedia.attributeNode("type");
QDomAttr hash = enmedia.attributeNode("hash");
String[] type = attr.nodeValue().split("/");
String appl = type[1];
if (type[0] != null) {
if (type[0].equals("image")) {
modifyImageTags(doc, docElem, enmedia, hash);
}
if (!type[0].equals("image")) {
modifyApplicationTags(doc, docElem, enmedia, hash, appl);
}
}
}
}
// Modify todo tags
anchors = docElem.elementsByTagName("en-todo");
int enTodoCount = anchors.length();
for (int i=enTodoCount-1; i>=0; i--) {
QDomElement enmedia = anchors.at(i).toElement();
modifyTodoTags(enmedia);
}
// Modify en-crypt tags
anchors = docElem.elementsByTagName("en-crypt");
int enCryptLen = anchors.length();
for (int i=enCryptLen-1; i>=0; i--) {
QDomElement enmedia = anchors.at(i).toElement();
enmedia.setAttribute("contentEditable","false");
enmedia.setAttribute("src", Global.getFileManager().getImageDirPath("encrypt.png"));
enmedia.setAttribute("en-tag","en-crypt");
enmedia.setAttribute("alt", enmedia.text());
Global.cryptCounter++;
enmedia.setAttribute("id", "crypt"+Global.cryptCounter.toString());
String encryptedText = enmedia.text();
// If the encryption string contains crlf at the end, remove them because they mess up the javascript.
if (encryptedText.endsWith("\n"))
encryptedText = encryptedText.substring(0,encryptedText.length()-1);
if (encryptedText.endsWith("\r"))
encryptedText = encryptedText.substring(0,encryptedText.length()-1);
// Add the commands
String hint = enmedia.attribute("hint");
hint = hint.replace("'","'");
enmedia.setAttribute("onClick", "window.jambi.decryptText('crypt"+Global.cryptCounter.toString()+"', '"+encryptedText+"', '"+hint+"');");
enmedia.setAttribute("onMouseOver", "style.cursor='hand'");
enmedia.setTagName("img");
enmedia.removeChild(enmedia.firstChild()); // Remove the actual encrypted text
}
// Modify link tags
anchors = docElem.elementsByTagName("a");
enCryptLen = anchors.length();
for (int i=0; i<anchors.length(); i++) {
QDomElement element = anchors.at(i).toElement();
if (!element.attribute("href").toLowerCase().startsWith("latex://"))
element.setAttribute("title", element.attribute("href"));
else {
element.setAttribute("title", element.attribute("title").toLowerCase().replace("http://latex.codecogs.com/gif.latex?",""));
}
}
logger.log(logger.HIGH, "Leaving NeverNote.modifyTags");
return doc;
}
// Get an ink note image. If an image doesn't exist then we fall back
// to the old ugly icon
private boolean buildInkNote(QDomDocument doc, QDomElement docElem, QDomElement enmedia, QDomAttr hash, String appl) {
String resGuid = conn.getNoteTable().noteResourceTable.getNoteResourceGuidByHashHex(currentNote.getGuid(), hash.value());
Resource r = conn.getNoteTable().noteResourceTable.getNoteResource(resGuid, false);
// If we can't find the resource, then fall back to the old method. We'll return & show
// an error later
if (r == null || r.getData() == null)
return false;
// If there isn't some type of error, continue on.
if (!resourceError) {
// Get a list of images in the database. We'll use these to bulid the page.
List<QByteArray> data = conn.getInkImagesTable().getImage(r.getGuid());
// If no pictures are found, go back to & just show the icon
if (data.size() == 0)
return false;
// We have pictures, so append them to the page. This really isn't proper since
// we leave the en-media tag in place, but since we can't edit the page it doesn't
// hurt anything.
for (int i=0; i<data.size(); i++) {
QFile f = new QFile(Global.getFileManager().getResDirPath(resGuid + new Integer(i).toString()+".png"));
f.open(OpenModeFlag.WriteOnly);
f.write(data.get(i));
f.close();
QDomElement newImage = doc.createElement("img");
newImage.setAttribute("src", QUrl.fromLocalFile(f.fileName()).toString());
enmedia.appendChild(newImage);
}
return true;
}
return false;
}
// Modify the en-media tag into an attachment
private void modifyApplicationTags(QDomDocument doc, QDomElement docElem, QDomElement enmedia, QDomAttr hash, String appl) {
logger.log(logger.HIGH, "Entering NeverNote.modifyApplicationTags");
if (appl.equalsIgnoreCase("vnd.evernote.ink")) {
inkNote = true;
if (buildInkNote(doc, docElem, enmedia, hash, appl))
return;
}
String resGuid = conn.getNoteTable().noteResourceTable.getNoteResourceGuidByHashHex(currentNote.getGuid(), hash.value());
Resource r = conn.getNoteTable().noteResourceTable.getNoteResource(resGuid, false);
if (r == null || r.getData() == null)
resourceError = true;
if (r!= null) {
if (r.getData()!=null) {
// Did we get a generic applicaiton? Then look at the file name to
// try and find a good application type for the icon
if (appl.equalsIgnoreCase("octet-stream")) {
if (r.getAttributes() != null && r.getAttributes().getFileName() != null) {
String fn = r.getAttributes().getFileName();
int pos = fn.lastIndexOf(".");
if (pos > -1) {
appl = fn.substring(pos+1);
}
}
}
String fileDetails = null;
if (r.getAttributes() != null && r.getAttributes().getFileName() != null && !r.getAttributes().getFileName().equals(""))
fileDetails = r.getAttributes().getFileName();
String contextFileName;
FileManager fileManager = Global.getFileManager();
if (fileDetails != null && !fileDetails.equals("")) {
if (!noteHistory) {
enmedia.setAttribute("href", "nnres://" +r.getGuid()
+Global.attachmentNameDelimeter +fileDetails);
contextFileName = fileManager.getResDirPath(r.getGuid()
+Global.attachmentNameDelimeter + fileDetails);
} else {
enmedia.setAttribute("href", "nnres://" +r.getGuid() + currentNote.getUpdateSequenceNum()
+Global.attachmentNameDelimeter +fileDetails);
contextFileName = fileManager.getResDirPath(r.getGuid() + currentNote.getUpdateSequenceNum()
+Global.attachmentNameDelimeter + fileDetails);
}
} else {
if (!noteHistory) {
enmedia.setAttribute("href", "nnres://" +r.getGuid() +currentNote.getUpdateSequenceNum()
+Global.attachmentNameDelimeter +appl);
contextFileName = fileManager.getResDirPath(r.getGuid() +currentNote.getUpdateSequenceNum()
+Global.attachmentNameDelimeter + appl);
} else {
enmedia.setAttribute("href", "nnres://" +r.getGuid()
+Global.attachmentNameDelimeter +appl);
contextFileName = fileManager.getResDirPath(r.getGuid()
+Global.attachmentNameDelimeter + appl);
}
}
contextFileName = contextFileName.replace("\\", "/");
enmedia.setAttribute("onContextMenu", "window.jambi.resourceContextMenu('" +contextFileName +"');");
if (fileDetails == null || fileDetails.equals(""))
fileDetails = "";
enmedia.setAttribute("en-tag", "en-media");
enmedia.setAttribute("guid", r.getGuid());
enmedia.setTagName("a");
QDomElement newText = doc.createElement("img");
boolean goodPreview = false;
String filePath = "";
if (appl.equalsIgnoreCase("pdf") && pdfPreview) {
String fileName;
Resource res = conn.getNoteTable().noteResourceTable.getNoteResource(r.getGuid(), true);
if (res.getAttributes() != null &&
res.getAttributes().getFileName() != null &&
!res.getAttributes().getFileName().trim().equals(""))
fileName = res.getGuid()+Global.attachmentNameDelimeter+res.getAttributes().getFileName();
else
fileName = res.getGuid()+".pdf";
QFile file = new QFile(fileManager.getResDirPath(fileName));
QFile.OpenMode mode = new QFile.OpenMode();
mode.set(QFile.OpenModeFlag.WriteOnly);
file.open(mode);
QDataStream out = new QDataStream(file);
Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(res.getGuid(), true);
QByteArray binData = new QByteArray(resBinary.getData().getBody());
resBinary = null;
out.writeBytes(binData.toByteArray());
file.close();
PDFPreview pdfPreview = new PDFPreview();
goodPreview = pdfPreview.setupPreview(file.fileName(), appl,0);
if (goodPreview) {
QDomElement span = doc.createElement("span");
QDomElement table = doc.createElement("table");
span.setAttribute("pdfNavigationTable", "true");
QDomElement tr = doc.createElement("tr");
QDomElement td = doc.createElement("td");
QDomElement left = doc.createElement("img");
left.setAttribute("onMouseDown", "window.jambi.nextPage('" +file.fileName() +"')");
left.setAttribute("onMouseDown", "window.jambi.nextPage('" +file.fileName() +"')");
left.setAttribute("onMouseOver", "style.cursor='hand'");
QDomElement right = doc.createElement("img");
right.setAttribute("onMouseDown", "window.jambi.nextPage('" +file.fileName() +"')");
left.setAttribute("onMouseDown", "window.jambi.previousPage('" +file.fileName() +"')");
// NFC TODO: should these be file:// URLs?
left.setAttribute("src", Global.getFileManager().getImageDirPath("small_left.png"));
right.setAttribute("src", Global.getFileManager().getImageDirPath("small_right.png"));
right.setAttribute("onMouseOver", "style.cursor='hand'");
table.appendChild(tr);
tr.appendChild(td);
td.appendChild(left);
td.appendChild(right);
span.appendChild(table);
enmedia.parentNode().insertBefore(span, enmedia);
}
filePath = fileName+".png";
}
String icon = findIcon(appl);
if (icon.equals("attachment.png"))
icon = findIcon(fileDetails.substring(fileDetails.indexOf(".")+1));
// NFC TODO: should this be a 'file://' URL?
newText.setAttribute("src", Global.getFileManager().getImageDirPath(icon));
if (goodPreview) {
// NFC TODO: should this be a 'file://' URL?
newText.setAttribute("src", fileManager.getResDirPathSpecialChar(filePath));
newText.setAttribute("style", "border-style:solid; border-color:green; padding:0.5mm 0.5mm 0.5mm 0.5mm;");
}
newText.setAttribute("title", fileDetails);
enmedia.removeChild(enmedia.firstChild());
enmedia.appendChild(newText);
}
}
logger.log(logger.HIGH, "Leaving NeverNote.modifyApplicationTags");
}
// Modify the en-to tag into an input field
private void modifyTodoTags(QDomElement todo) {
logger.log(logger.HIGH, "Entering NeverNote.modifyTodoTags");
todo.setAttribute("type", "checkbox");
String checked = todo.attribute("checked");
todo.removeAttribute("checked");
if (checked.equalsIgnoreCase("true"))
todo.setAttribute("checked", "");
else
todo.setAttribute("unchecked","");
todo.setAttribute("value", checked);
todo.setAttribute("onClick", "value=checked;window.jambi.contentChanged(); ");
todo.setAttribute("onMouseOver", "style.cursor='hand'");
todo.setTagName("input");
logger.log(logger.HIGH, "Leaving NeverNote.modifyTodoTags");
}
// Modify any cached todo tags that may have changed
public String modifyCachedTodoTags(String note) {
logger.log(logger.HIGH, "Entering NeverNote.modifyCachedTodoTags");
StringBuffer html = new StringBuffer(note);
for (int i=html.indexOf("<input", 0); i>-1; i=html.indexOf("<input", i)) {
int endPos =html.indexOf(">",i+1);
String input = html.substring(i,endPos);
if (input.indexOf("value=\"true\"") > 0)
input = input.replace(" unchecked=\"\"", " checked=\"\"");
else
input = input.replace(" checked=\"\"", " unchecked=\"\"");
html.replace(i, endPos, input);
i++;
}
logger.log(logger.HIGH, "Leaving NeverNote.modifyCachedTodoTags");
return html.toString();
}
// Scan and do hilighting of words
public QDomDocument addHilight(QDomDocument doc) {
// EnSearch e = listManager.getEnSearch();
if (enSearch.hilightWords == null || enSearch.hilightWords.size() == 0)
return doc;
XMLInsertHilight hilight = new XMLInsertHilight(doc, enSearch.hilightWords);
return hilight.getDoc();
}
// find the appropriate icon for an attachment
private String findIcon(String appl) {
logger.log(logger.HIGH, "Entering NeverNote.findIcon");
appl = appl.toLowerCase();
String relativePath = appl + ".png";
File f = Global.getFileManager().getImageDirFile(relativePath);
if (f.exists()) {
return relativePath;
}
if (f.exists())
return appl+".png";
logger.log(logger.HIGH, "Leaving NeverNote.findIcon");
return "attachment.png";
}
}