I am in the process of adding some html based formatting features to a JTextPane. The idea is that the user would select text in the JTextPane, then click a button (bold, italic etc) to insert the html tags at the appropriate locations. I can do this without difficulty using the JTextPane.getSelectionStart() and .getSelectionEnd() methods.
My problem is that I also want to scan each character in the JTextPane to index all the html tag locations - this is so the software can detect where the JTextPane caret is in relation to the html tags. This information is then used if the user wants to remove the formatting tags. I am having difficulty synchronising this character index with the caret position in the JTextPane. Here is the code I have been using:
public void scanHTML(){
try {
boolean blnDocStartFlag = false;
alTagRecords = new ArrayList(25);
alTextOnlyIndex = new ArrayList();
String strTagBuild = "";
int intTagIndex = 0; // The index for a tag pair record in alTagRecords.
int intTextOnlyCount = 0; // Counts each text character, ignoring all html tags.
// Loop through HTMLDoc character array:
for (int i = 0; i <= strHTMLDoc.length() -1; i ++){
// Look for the "<" angle bracket enclosing the tag keyword ...
if (strHTMLDoc.charAt(i) == '<'){// It is a html tag ...
int intTagStartLocation = i; // this value will go into alTagFields(?,0) later ...
while (strHTMLDoc.charAt(i) != '>'){
strTagBuild += strHTMLDoc.charAt(i);
i ++; // continue incrementing the iterator whilst in this sub loop ...
}
strTagBuild += '>'; // makes sure the closing tag is not missed from the string
if (!strTagBuild.startsWith("</")){
// Create new tag record:
ArrayList<Integer> alTagFields = new ArrayList(3);
alTagFields.add(0, intTagStartLocation); // Tag start location index ...
alTagFields.add(1, -1); // Tag end not known at this stage ...
alTagFields.add(2, getTagType(strTagBuild));
alTagRecords.add(intTagIndex, alTagFields); // Tag Type
System.out.println("Tag: " + strTagBuild);
intTagIndex ++; // Increment the tag records index ...
} else { // find corresponding start tag and store its location in the appropriate field of alTagFields:
int intManipulatedTagIndex = getMyOpeningTag(getTagType(strTagBuild));
ArrayList<Integer> alManipulateTagFields = alTagRecords.get(intManipulatedTagIndex);
alManipulateTagFields.set(1, (intTagStartLocation + strTagBuild.length() -1) ); // store the position of the end angled bracket of the closing tag ...
alTagRecords.set(intManipulatedTagIndex, alManipulateTagFields);
System.out.println("Tag: " + strTagBuild);
}
strTagBuild = "";
} else {
// Create the text index:
if (blnDocStartFlag == false){
int intAscii = (int) strHTMLDoc.charAt(i);
if (intAscii >= 33){ // Ascii character 33 is an exclamation mark(!). It is the first character after a space.
blnDocStartFlag = true;
}
}
// Has the first non space text character has been reached? ...
if (blnDocStartFlag == true){ // Index the character if it has ...
alTextOnlyIndex.add(i);
intTextOnlyCount ++;
}
}
}
} catch (Exception ex){
System.err.println("Error at HTMLTagIndexer.scanHTML: " + ex);
}
}
The problem with the code above is that the string variable strHTMLDoc is obtained using JTextPane.getText, and this appears to have inserted some extra space characters within the string. Consequently this has put it out of sync with the corresponding caret position in the text pane.
Can anybody suggest an alternative way to do what I am trying to achieve?
Many thanks