Initial revision
[old-projects.git] / ekit / com / hexidec / ekit / component / HTMLUtilities.java
diff --git a/ekit/com/hexidec/ekit/component/HTMLUtilities.java b/ekit/com/hexidec/ekit/component/HTMLUtilities.java
new file mode 100644 (file)
index 0000000..6298488
--- /dev/null
@@ -0,0 +1,492 @@
+/*\r
+GNU Lesser General Public License\r
+\r
+HTMLUtilities - Special Utility Functions For Ekit\r
+Copyright (C) 2003 Rafael Cieplinski, modified by Howard Kistler\r
+\r
+This library is free software; you can redistribute it and/or\r
+modify it under the terms of the GNU Lesser General Public\r
+License as published by the Free Software Foundation; either\r
+version 2.1 of the License, or (at your option) any later version.\r
+\r
+This library is distributed in the hope that it will be useful,\r
+but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
+Lesser General Public License for more details.\r
+\r
+You should have received a copy of the GNU Lesser General Public\r
+License along with this library; if not, write to the Free Software\r
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+*/\r
+\r
+package com.hexidec.ekit.component;\r
+\r
+import java.io.*;\r
+import java.lang.reflect.*;\r
+import java.util.*;\r
+import javax.swing.*;\r
+import javax.swing.text.*;\r
+import javax.swing.text.html.*;\r
+\r
+import com.hexidec.ekit.EkitCore;\r
+import com.hexidec.ekit.component.*;\r
+\r
+public class HTMLUtilities\r
+{\r
+       EkitCore parent;\r
+       Hashtable tags = new Hashtable();\r
+\r
+       public HTMLUtilities(EkitCore newParent)\r
+       {\r
+               parent = newParent;\r
+               HTML.Tag[] tagList = HTML.getAllTags();\r
+               for(int i = 0; i < tagList.length; i++)\r
+               {\r
+                       tags.put(tagList[i].toString(), tagList[i]);\r
+               }\r
+/*\r
+               HTML.Tag classTag = new HTML.Tag();\r
+               Field[] fields = classTag.getClass().getDeclaredFields();\r
+               for(int i = 0; i < fields.length; i++)\r
+               {\r
+                       try\r
+                       {\r
+                               System.out.println("Adding " + (String)fields[i].get(null).toString() + " => " + (HTML.Tag)fields[i].get(null));\r
+                               tags.put((String)fields[i].get(null).toString(), (HTML.Tag)fields[i].get(null));\r
+                       }\r
+                       catch (IllegalAccessException iae)\r
+                       {\r
+                       }\r
+               }\r
+*/\r
+       }\r
+\r
+       /** Diese Methode fügt durch String-Manipulation in jtpSource\r
+         * ein neues Listenelement hinzu, content ist dabei der Text der in dem neuen\r
+         * Element stehen soll\r
+         */\r
+       public void insertListElement(String content)\r
+       {\r
+               int pos = parent.getCaretPosition();\r
+               String source = parent.getSourcePane().getText();\r
+               boolean hit = false;\r
+               String idString;\r
+               int counter = 0;\r
+               do\r
+               {\r
+                       hit = false;\r
+                       idString = "diesisteineidzumsuchenimsource" + counter;\r
+                       if(source.indexOf(idString) > -1)\r
+                       {\r
+                               counter++;\r
+                               hit = true;\r
+                               if(counter > 10000)\r
+                               {\r
+                                       return;\r
+                               }\r
+                       }\r
+               } while(hit);\r
+               Element element = getListItemParent();\r
+               if(element == null)\r
+               {\r
+                       return;\r
+               }\r
+               SimpleAttributeSet sa = new SimpleAttributeSet(element.getAttributes());\r
+               sa.addAttribute("id", idString);\r
+               parent.getExtendedHtmlDoc().replaceAttributes(element, sa, HTML.Tag.LI);\r
+               parent.refreshOnUpdate();\r
+               source = parent.getSourcePane().getText();\r
+               StringBuffer newHtmlString = new StringBuffer();\r
+               int[] positions = getPositions(element, source, true, idString);\r
+               newHtmlString.append(source.substring(0, positions[3]));\r
+               newHtmlString.append("<li>");\r
+               newHtmlString.append(content);\r
+               newHtmlString.append("</li>");\r
+               newHtmlString.append(source.substring(positions[3] + 1, source.length()));\r
+               parent.getTextPane().setText(newHtmlString.toString());\r
+               parent.refreshOnUpdate();\r
+               parent.setCaretPosition(pos - 1);\r
+               element = getListItemParent();\r
+               sa = new SimpleAttributeSet(element.getAttributes());\r
+               sa = removeAttributeByKey(sa, "id");\r
+               parent.getExtendedHtmlDoc().replaceAttributes(element, sa, HTML.Tag.LI);\r
+       }\r
+\r
+       /** Diese Methode löscht durch Stringmanipulation in jtpSource das übergebene Element,\r
+         * Alternative für removeElement in ExtendedHTMLDocument, mit closingTag wird angegeben\r
+         * ob es ein schließenden Tag gibt\r
+         */\r
+       public void removeTag(Element element, boolean closingTag)\r
+       {\r
+               if(element == null)\r
+               {\r
+                       return;\r
+               }\r
+               int pos = parent.getCaretPosition();\r
+               HTML.Tag tag = getHTMLTag(element);\r
+               // Versieht den Tag mit einer einmaligen ID\r
+               String source = parent.getSourcePane().getText();\r
+               boolean hit = false;\r
+               String idString;\r
+               int counter = 0;\r
+               do\r
+               {\r
+                       hit = false;\r
+                       idString = "diesisteineidzumsuchenimsource" + counter;\r
+                       if(source.indexOf(idString) > -1)\r
+                       {\r
+                               counter++;\r
+                               hit = true;\r
+                               if(counter > 10000)\r
+                               {\r
+                                       return;\r
+                               }\r
+                       }\r
+               } while(hit);\r
+               SimpleAttributeSet sa = new SimpleAttributeSet(element.getAttributes());\r
+               sa.addAttribute("id", idString);\r
+               parent.getExtendedHtmlDoc().replaceAttributes(element, sa, tag);\r
+               parent.refreshOnUpdate();\r
+               source = parent.getSourcePane().getText();\r
+               StringBuffer newHtmlString = new StringBuffer();\r
+               int[] position = getPositions(element, source, closingTag, idString);\r
+               if(position == null)\r
+               {\r
+                       return;\r
+               }\r
+               for(int i = 0; i < position.length; i++)\r
+               {\r
+                       if(position[i] < 0)\r
+                       {\r
+                               return;\r
+                       }\r
+               }\r
+               int beginStartTag = position[0];\r
+               int endStartTag = position[1];\r
+               if(closingTag)\r
+               {\r
+                       int beginEndTag = position[2];\r
+                       int endEndTag = position[3];\r
+                       newHtmlString.append(source.substring(0, beginStartTag));\r
+                       newHtmlString.append(source.substring(endStartTag, beginEndTag));\r
+                       newHtmlString.append(source.substring(endEndTag, source.length()));\r
+               }\r
+               else\r
+               {\r
+                       newHtmlString.append(source.substring(0, beginStartTag));\r
+                       newHtmlString.append(source.substring(endStartTag, source.length()));\r
+               }\r
+               parent.getTextPane().setText(newHtmlString.toString());\r
+               parent.refreshOnUpdate();\r
+       }\r
+\r
+       /** Diese Methode gibt jeweils den Start- und Endoffset des Elements\r
+         * sowie dem entsprechenden schließenden Tag zurück\r
+         */\r
+       private int[] getPositions(Element element, String source, boolean closingTag, String idString)\r
+       {\r
+               HTML.Tag tag = getHTMLTag(element);\r
+               int[] position = new int[4];\r
+               for(int i = 0; i < position.length; i++)\r
+               {\r
+                       position[i] = -1;\r
+               }\r
+               String searchString = "<" + tag.toString();\r
+               int caret = -1; // aktuelle Position im sourceString\r
+               if((caret = source.indexOf(idString)) != -1)\r
+               {\r
+                       position[0] = source.lastIndexOf("<",caret);\r
+                       position[1] = source.indexOf(">",caret)+1;\r
+               }\r
+               if(closingTag)\r
+               {\r
+                       String searchEndTagString = "</" + tag.toString() + ">";\r
+                       int hitUp = 0;\r
+                       int beginEndTag = -1;\r
+                       int endEndTag = -1;\r
+                       caret = position[1];\r
+                       boolean end = false;\r
+                       // Position des 1. Treffer auf den End-Tag wird bestimmt\r
+                       beginEndTag = source.indexOf(searchEndTagString, caret);\r
+                       endEndTag = beginEndTag + searchEndTagString.length();\r
+                       // Schleife läuft solange, bis keine neuen StartTags mehr gefunden werden\r
+                       int interncaret = position[1];\r
+                       do\r
+                       {\r
+                               int temphitpoint = -1;\r
+                               boolean flaghitup = false;\r
+                               // Schleife sucht zwischen dem Start- und End-Tag nach neuen Start-Tags\r
+                               hitUp = 0;\r
+                               do\r
+                               {\r
+                                       flaghitup = false;\r
+                                       temphitpoint = source.indexOf(searchString, interncaret);\r
+                                       if(temphitpoint > 0 && temphitpoint < beginEndTag)\r
+                                       {\r
+                                               hitUp++;\r
+                                               flaghitup = true;\r
+                                               interncaret = temphitpoint + searchString.length();\r
+                                       }\r
+                               } while(flaghitup);\r
+                               // hitUp enthält die Anzahl der neuen Start-Tags\r
+                               if(hitUp == 0)\r
+                               {\r
+                                       end = true;\r
+                               }\r
+                               else\r
+                               {\r
+                                       for(int i = 1; i <= hitUp; i++)\r
+                                       {\r
+                                               caret = endEndTag;\r
+                                               beginEndTag = source.indexOf(searchEndTagString, caret);\r
+                                               endEndTag = beginEndTag + searchEndTagString.length();\r
+                                       }\r
+                                       end = false;\r
+                               }\r
+                       } while(!end);\r
+                       if(beginEndTag < 0 | endEndTag < 0)\r
+                       {\r
+                               return null;\r
+                       }\r
+                       position[2] = beginEndTag;\r
+                       position[3] = endEndTag;\r
+               }\r
+               return position;\r
+       }\r
+\r
+       /* Diese Methode prüft ob der übergebene Tag sich in der Hierachie nach oben befindet */\r
+       public boolean checkParentsTag(HTML.Tag tag)\r
+       {\r
+               Element e = parent.getExtendedHtmlDoc().getParagraphElement(parent.getCaretPosition());\r
+               String tagString = tag.toString();\r
+               if(e.getName().equalsIgnoreCase(tag.toString()))\r
+               {\r
+                       return true;\r
+               }\r
+               do\r
+               {\r
+                       if((e = e.getParentElement()).getName().equalsIgnoreCase(tagString))\r
+                       {\r
+                               return true;\r
+                       }\r
+               } while(!(e.getName().equalsIgnoreCase("html")));\r
+               return false;\r
+       }\r
+\r
+       /* Diese Methoden geben das erste gefundende dem übergebenen tags entsprechende Element zurück */\r
+       public Element getListItemParent()\r
+       {\r
+               String listItemTag = HTML.Tag.LI.toString();\r
+               Element eleSearch = parent.getExtendedHtmlDoc().getCharacterElement(parent.getCaretPosition());\r
+               do\r
+               {\r
+                       if(listItemTag.equals(eleSearch.getName()))\r
+                       {\r
+                               return eleSearch;\r
+                       }\r
+                       eleSearch = eleSearch.getParentElement();\r
+               } while(eleSearch.getName() != HTML.Tag.HTML.toString());\r
+               return null;\r
+       }\r
+\r
+       /* Diese Methoden entfernen Attribute aus dem SimpleAttributeSet, gemäß den übergebenen Werten, und\r
+               geben das Ergebnis als SimpleAttributeSet zurück*/\r
+       public SimpleAttributeSet removeAttributeByKey(SimpleAttributeSet sourceAS, String removeKey)\r
+       {\r
+               SimpleAttributeSet temp = new SimpleAttributeSet();\r
+               temp.addAttribute(removeKey, "NULL");\r
+               return removeAttribute(sourceAS, temp);\r
+       }\r
+\r
+       public SimpleAttributeSet removeAttribute(SimpleAttributeSet sourceAS, SimpleAttributeSet removeAS)\r
+       {\r
+               try\r
+               {\r
+                       String[] sourceKeys = new String[sourceAS.getAttributeCount()];\r
+                       String[] sourceValues = new String[sourceAS.getAttributeCount()];\r
+                       Enumeration sourceEn = sourceAS.getAttributeNames();\r
+                       int i = 0;\r
+                       while(sourceEn.hasMoreElements())\r
+                       {\r
+                               Object temp = new Object();\r
+                               temp = sourceEn.nextElement();\r
+                               sourceKeys[i] = (String) temp.toString();\r
+                               sourceValues[i] = new String();\r
+                               sourceValues[i] = (String) sourceAS.getAttribute(temp).toString();\r
+                               i++;\r
+                       }\r
+                       String[] removeKeys = new String[removeAS.getAttributeCount()];\r
+                       String[] removeValues = new String[removeAS.getAttributeCount()];\r
+                       Enumeration removeEn = removeAS.getAttributeNames();\r
+                       int j = 0;\r
+                       while(removeEn.hasMoreElements())\r
+                       {\r
+                               removeKeys[j] = (String) removeEn.nextElement().toString();\r
+                               removeValues[j] = (String) removeAS.getAttribute(removeKeys[j]).toString();\r
+                               j++;\r
+                       }\r
+                       SimpleAttributeSet result = new SimpleAttributeSet();\r
+                       boolean hit = false;\r
+                       for(int countSource = 0; countSource < sourceKeys.length; countSource++)\r
+                       {\r
+                               hit = false;\r
+                               if(sourceKeys[countSource] == "name" | sourceKeys[countSource] == "resolver")\r
+                               {\r
+                                       hit = true;\r
+                               }\r
+                               else\r
+                               {\r
+                                       for(int countRemove = 0; countRemove < removeKeys.length; countRemove++)\r
+                                       {\r
+                                               if(removeKeys[countRemove] != "NULL")\r
+                                               {\r
+                                                       if(sourceKeys[countSource].toString() == removeKeys[countRemove].toString())\r
+                                                       {\r
+                                                               if(removeValues[countRemove] != "NULL")\r
+                                                               {\r
+                                                                       if(sourceValues[countSource].toString() == removeValues[countRemove].toString())\r
+                                                                       {\r
+                                                                               hit = true;\r
+                                                                       }\r
+                                                               }\r
+                                                               else if(removeValues[countRemove] == "NULL")\r
+                                                               {\r
+                                                                       hit = true;\r
+                                                               }\r
+                                                       }\r
+                                               }\r
+                                               else if(removeKeys[countRemove] == "NULL")\r
+                                               {\r
+                                                       if(sourceValues[countSource].toString() == removeValues[countRemove].toString())\r
+                                                       {\r
+                                                               hit = true;\r
+                                                       }\r
+                                               }\r
+                                       }\r
+                               }\r
+                               if(!hit)\r
+                               {\r
+                                       result.addAttribute(sourceKeys[countSource].toString(), sourceValues[countSource].toString());\r
+                               }\r
+                       }\r
+                       return result;\r
+               }\r
+               catch (ClassCastException cce)\r
+               {\r
+                       return null;\r
+               }\r
+       }\r
+\r
+       /* liefert den entsprechenden HTML.Tag zum Element zurück */\r
+       public HTML.Tag getHTMLTag(Element e)\r
+       {\r
+               if(tags.containsKey(e.getName()))\r
+               {\r
+                       return (HTML.Tag)tags.get(e.getName());\r
+               }\r
+               else\r
+               {\r
+                       return null;\r
+               }\r
+       }\r
+\r
+       public String[] getUniString(int strings)\r
+       {\r
+               parent.refreshOnUpdate();\r
+               String[] result = new String[strings];\r
+               String source = parent.getSourcePane().getText();\r
+               for(int i=0; i<strings; i++)\r
+               {\r
+                       int start = -1, end = -1;\r
+                       boolean hit = false;\r
+                       String idString;\r
+                       int counter = 0;\r
+                       do\r
+                       {\r
+                               hit = false;\r
+                               idString = "diesisteineidzumsuchen" + counter + "#" + i;\r
+                               if(source.indexOf(idString) > -1)\r
+                               {\r
+                                       counter++;\r
+                                       hit = true;\r
+                                       if(counter > 10000)\r
+                                       {\r
+                                               return null;\r
+                                       }\r
+                               }\r
+                       } while(hit);\r
+                       result[i] = idString;\r
+               }\r
+               return result;\r
+       }\r
+\r
+       public void delete()\r
+       throws BadLocationException,IOException\r
+       {\r
+               JTextPane jtpMain = parent.getTextPane();\r
+               JTextPane jtpSource = parent.getSourcePane();\r
+               ExtendedHTMLDocument htmlDoc = parent.getExtendedHtmlDoc();\r
+               int selStart = jtpMain.getSelectionStart();\r
+               int selEnd = jtpMain.getSelectionEnd();\r
+               String[] posStrings = getUniString(2);\r
+               if(posStrings == null)\r
+               {\r
+                       return;\r
+               }\r
+               htmlDoc.insertString(selStart,posStrings[0],null);\r
+               htmlDoc.insertString(selEnd+posStrings[0].length(),posStrings[1],null);\r
+               parent.refreshOnUpdate();\r
+               int start = jtpSource.getText().indexOf(posStrings[0]);\r
+               int end = jtpSource.getText().indexOf(posStrings[1]);\r
+               if(start == -1 || end == -1)\r
+               {\r
+                       return;\r
+               }\r
+               String htmlString = new String();\r
+               htmlString += jtpSource.getText().substring(0,start);\r
+               htmlString += jtpSource.getText().substring(start + posStrings[0].length(), end);\r
+               htmlString += jtpSource.getText().substring(end + posStrings[1].length(), jtpSource.getText().length());\r
+               String source = htmlString;\r
+               end = end - posStrings[0].length();\r
+               htmlString = new String();\r
+               htmlString += source.substring(0,start);\r
+               htmlString += getAllTableTags(source.substring(start, end));\r
+               htmlString += source.substring(end, source.length());\r
+               parent.getTextPane().setText(htmlString);\r
+               parent.refreshOnUpdate();\r
+       }\r
+\r
+       private String getAllTableTags(String source)\r
+       throws BadLocationException,IOException\r
+       {\r
+               StringBuffer result = new StringBuffer();\r
+               int caret = -1;\r
+               do\r
+               {\r
+                       caret++;\r
+                       int[] tableCarets = new int[6];\r
+                       tableCarets[0] = source.indexOf("<table",caret);\r
+                       tableCarets[1] = source.indexOf("<tr",caret);\r
+                       tableCarets[2] = source.indexOf("<td",caret);\r
+                       tableCarets[3] = source.indexOf("</table",caret);\r
+                       tableCarets[4] = source.indexOf("</tr",caret);\r
+                       tableCarets[5] = source.indexOf("</td",caret);\r
+                       java.util.Arrays.sort(tableCarets);\r
+                       caret = -1;\r
+                       for(int i=0; i<tableCarets.length; i++)\r
+                       {\r
+                               if(tableCarets[i] >= 0)\r
+                               {\r
+                                       caret = tableCarets[i];\r
+                                       break;\r
+                               }\r
+                       }\r
+                       if(caret != -1)\r
+                       {\r
+                               result.append(source.substring(caret,source.indexOf(">",caret)+1));\r
+                       }\r
+               } while(caret != -1);\r
+               return result.toString();\r
+       }\r
+\r
+}
\ No newline at end of file