Initial revision
[old-projects.git] / ekit / com / hexidec / ekit / component / HTMLUtilities.java
CommitLineData
c2da4d40
JL
1/*\r
2GNU Lesser General Public License\r
3\r
4HTMLUtilities - Special Utility Functions For Ekit\r
5Copyright (C) 2003 Rafael Cieplinski, modified by Howard Kistler\r
6\r
7This library is free software; you can redistribute it and/or\r
8modify it under the terms of the GNU Lesser General Public\r
9License as published by the Free Software Foundation; either\r
10version 2.1 of the License, or (at your option) any later version.\r
11\r
12This library is distributed in the hope that it will be useful,\r
13but WITHOUT ANY WARRANTY; without even the implied warranty of\r
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
15Lesser General Public License for more details.\r
16\r
17You should have received a copy of the GNU Lesser General Public\r
18License along with this library; if not, write to the Free Software\r
19Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
20*/\r
21\r
22package com.hexidec.ekit.component;\r
23\r
24import java.io.*;\r
25import java.lang.reflect.*;\r
26import java.util.*;\r
27import javax.swing.*;\r
28import javax.swing.text.*;\r
29import javax.swing.text.html.*;\r
30\r
31import com.hexidec.ekit.EkitCore;\r
32import com.hexidec.ekit.component.*;\r
33\r
34public class HTMLUtilities\r
35{\r
36 EkitCore parent;\r
37 Hashtable tags = new Hashtable();\r
38\r
39 public HTMLUtilities(EkitCore newParent)\r
40 {\r
41 parent = newParent;\r
42 HTML.Tag[] tagList = HTML.getAllTags();\r
43 for(int i = 0; i < tagList.length; i++)\r
44 {\r
45 tags.put(tagList[i].toString(), tagList[i]);\r
46 }\r
47/*\r
48 HTML.Tag classTag = new HTML.Tag();\r
49 Field[] fields = classTag.getClass().getDeclaredFields();\r
50 for(int i = 0; i < fields.length; i++)\r
51 {\r
52 try\r
53 {\r
54 System.out.println("Adding " + (String)fields[i].get(null).toString() + " => " + (HTML.Tag)fields[i].get(null));\r
55 tags.put((String)fields[i].get(null).toString(), (HTML.Tag)fields[i].get(null));\r
56 }\r
57 catch (IllegalAccessException iae)\r
58 {\r
59 }\r
60 }\r
61*/\r
62 }\r
63\r
64 /** Diese Methode fügt durch String-Manipulation in jtpSource\r
65 * ein neues Listenelement hinzu, content ist dabei der Text der in dem neuen\r
66 * Element stehen soll\r
67 */\r
68 public void insertListElement(String content)\r
69 {\r
70 int pos = parent.getCaretPosition();\r
71 String source = parent.getSourcePane().getText();\r
72 boolean hit = false;\r
73 String idString;\r
74 int counter = 0;\r
75 do\r
76 {\r
77 hit = false;\r
78 idString = "diesisteineidzumsuchenimsource" + counter;\r
79 if(source.indexOf(idString) > -1)\r
80 {\r
81 counter++;\r
82 hit = true;\r
83 if(counter > 10000)\r
84 {\r
85 return;\r
86 }\r
87 }\r
88 } while(hit);\r
89 Element element = getListItemParent();\r
90 if(element == null)\r
91 {\r
92 return;\r
93 }\r
94 SimpleAttributeSet sa = new SimpleAttributeSet(element.getAttributes());\r
95 sa.addAttribute("id", idString);\r
96 parent.getExtendedHtmlDoc().replaceAttributes(element, sa, HTML.Tag.LI);\r
97 parent.refreshOnUpdate();\r
98 source = parent.getSourcePane().getText();\r
99 StringBuffer newHtmlString = new StringBuffer();\r
100 int[] positions = getPositions(element, source, true, idString);\r
101 newHtmlString.append(source.substring(0, positions[3]));\r
102 newHtmlString.append("<li>");\r
103 newHtmlString.append(content);\r
104 newHtmlString.append("</li>");\r
105 newHtmlString.append(source.substring(positions[3] + 1, source.length()));\r
106 parent.getTextPane().setText(newHtmlString.toString());\r
107 parent.refreshOnUpdate();\r
108 parent.setCaretPosition(pos - 1);\r
109 element = getListItemParent();\r
110 sa = new SimpleAttributeSet(element.getAttributes());\r
111 sa = removeAttributeByKey(sa, "id");\r
112 parent.getExtendedHtmlDoc().replaceAttributes(element, sa, HTML.Tag.LI);\r
113 }\r
114\r
115 /** Diese Methode löscht durch Stringmanipulation in jtpSource das übergebene Element,\r
116 * Alternative für removeElement in ExtendedHTMLDocument, mit closingTag wird angegeben\r
117 * ob es ein schließenden Tag gibt\r
118 */\r
119 public void removeTag(Element element, boolean closingTag)\r
120 {\r
121 if(element == null)\r
122 {\r
123 return;\r
124 }\r
125 int pos = parent.getCaretPosition();\r
126 HTML.Tag tag = getHTMLTag(element);\r
127 // Versieht den Tag mit einer einmaligen ID\r
128 String source = parent.getSourcePane().getText();\r
129 boolean hit = false;\r
130 String idString;\r
131 int counter = 0;\r
132 do\r
133 {\r
134 hit = false;\r
135 idString = "diesisteineidzumsuchenimsource" + counter;\r
136 if(source.indexOf(idString) > -1)\r
137 {\r
138 counter++;\r
139 hit = true;\r
140 if(counter > 10000)\r
141 {\r
142 return;\r
143 }\r
144 }\r
145 } while(hit);\r
146 SimpleAttributeSet sa = new SimpleAttributeSet(element.getAttributes());\r
147 sa.addAttribute("id", idString);\r
148 parent.getExtendedHtmlDoc().replaceAttributes(element, sa, tag);\r
149 parent.refreshOnUpdate();\r
150 source = parent.getSourcePane().getText();\r
151 StringBuffer newHtmlString = new StringBuffer();\r
152 int[] position = getPositions(element, source, closingTag, idString);\r
153 if(position == null)\r
154 {\r
155 return;\r
156 }\r
157 for(int i = 0; i < position.length; i++)\r
158 {\r
159 if(position[i] < 0)\r
160 {\r
161 return;\r
162 }\r
163 }\r
164 int beginStartTag = position[0];\r
165 int endStartTag = position[1];\r
166 if(closingTag)\r
167 {\r
168 int beginEndTag = position[2];\r
169 int endEndTag = position[3];\r
170 newHtmlString.append(source.substring(0, beginStartTag));\r
171 newHtmlString.append(source.substring(endStartTag, beginEndTag));\r
172 newHtmlString.append(source.substring(endEndTag, source.length()));\r
173 }\r
174 else\r
175 {\r
176 newHtmlString.append(source.substring(0, beginStartTag));\r
177 newHtmlString.append(source.substring(endStartTag, source.length()));\r
178 }\r
179 parent.getTextPane().setText(newHtmlString.toString());\r
180 parent.refreshOnUpdate();\r
181 }\r
182\r
183 /** Diese Methode gibt jeweils den Start- und Endoffset des Elements\r
184 * sowie dem entsprechenden schließenden Tag zurück
185 */\r
186 private int[] getPositions(Element element, String source, boolean closingTag, String idString)\r
187 {\r
188 HTML.Tag tag = getHTMLTag(element);\r
189 int[] position = new int[4];\r
190 for(int i = 0; i < position.length; i++)\r
191 {\r
192 position[i] = -1;\r
193 }\r
194 String searchString = "<" + tag.toString();\r
195 int caret = -1; // aktuelle Position im sourceString\r
196 if((caret = source.indexOf(idString)) != -1)\r
197 {\r
198 position[0] = source.lastIndexOf("<",caret);\r
199 position[1] = source.indexOf(">",caret)+1;\r
200 }\r
201 if(closingTag)\r
202 {\r
203 String searchEndTagString = "</" + tag.toString() + ">";\r
204 int hitUp = 0;\r
205 int beginEndTag = -1;\r
206 int endEndTag = -1;\r
207 caret = position[1];\r
208 boolean end = false;\r
209 // Position des 1. Treffer auf den End-Tag wird bestimmt\r
210 beginEndTag = source.indexOf(searchEndTagString, caret);\r
211 endEndTag = beginEndTag + searchEndTagString.length();\r
212 // Schleife läuft solange, bis keine neuen StartTags mehr gefunden werden\r
213 int interncaret = position[1];\r
214 do\r
215 {\r
216 int temphitpoint = -1;\r
217 boolean flaghitup = false;\r
218 // Schleife sucht zwischen dem Start- und End-Tag nach neuen Start-Tags\r
219 hitUp = 0;\r
220 do\r
221 {\r
222 flaghitup = false;\r
223 temphitpoint = source.indexOf(searchString, interncaret);\r
224 if(temphitpoint > 0 && temphitpoint < beginEndTag)\r
225 {\r
226 hitUp++;\r
227 flaghitup = true;\r
228 interncaret = temphitpoint + searchString.length();\r
229 }\r
230 } while(flaghitup);\r
231 // hitUp enthält die Anzahl der neuen Start-Tags\r
232 if(hitUp == 0)\r
233 {\r
234 end = true;\r
235 }\r
236 else\r
237 {\r
238 for(int i = 1; i <= hitUp; i++)\r
239 {\r
240 caret = endEndTag;\r
241 beginEndTag = source.indexOf(searchEndTagString, caret);\r
242 endEndTag = beginEndTag + searchEndTagString.length();\r
243 }\r
244 end = false;\r
245 }\r
246 } while(!end);\r
247 if(beginEndTag < 0 | endEndTag < 0)\r
248 {\r
249 return null;\r
250 }\r
251 position[2] = beginEndTag;\r
252 position[3] = endEndTag;\r
253 }\r
254 return position;\r
255 }\r
256\r
257 /* Diese Methode prüft ob der übergebene Tag sich in der Hierachie nach oben befindet */\r
258 public boolean checkParentsTag(HTML.Tag tag)\r
259 {\r
260 Element e = parent.getExtendedHtmlDoc().getParagraphElement(parent.getCaretPosition());\r
261 String tagString = tag.toString();\r
262 if(e.getName().equalsIgnoreCase(tag.toString()))\r
263 {\r
264 return true;\r
265 }\r
266 do\r
267 {\r
268 if((e = e.getParentElement()).getName().equalsIgnoreCase(tagString))\r
269 {\r
270 return true;\r
271 }\r
272 } while(!(e.getName().equalsIgnoreCase("html")));\r
273 return false;\r
274 }\r
275\r
276 /* Diese Methoden geben das erste gefundende dem übergebenen tags entsprechende Element zurück */\r
277 public Element getListItemParent()\r
278 {\r
279 String listItemTag = HTML.Tag.LI.toString();\r
280 Element eleSearch = parent.getExtendedHtmlDoc().getCharacterElement(parent.getCaretPosition());\r
281 do\r
282 {\r
283 if(listItemTag.equals(eleSearch.getName()))\r
284 {\r
285 return eleSearch;\r
286 }\r
287 eleSearch = eleSearch.getParentElement();\r
288 } while(eleSearch.getName() != HTML.Tag.HTML.toString());\r
289 return null;\r
290 }\r
291\r
292 /* Diese Methoden entfernen Attribute aus dem SimpleAttributeSet, gemäß den übergebenen Werten, und\r
293 geben das Ergebnis als SimpleAttributeSet zurück*/
294 public SimpleAttributeSet removeAttributeByKey(SimpleAttributeSet sourceAS, String removeKey)\r
295 {\r
296 SimpleAttributeSet temp = new SimpleAttributeSet();\r
297 temp.addAttribute(removeKey, "NULL");\r
298 return removeAttribute(sourceAS, temp);\r
299 }\r
300\r
301 public SimpleAttributeSet removeAttribute(SimpleAttributeSet sourceAS, SimpleAttributeSet removeAS)\r
302 {\r
303 try\r
304 {\r
305 String[] sourceKeys = new String[sourceAS.getAttributeCount()];\r
306 String[] sourceValues = new String[sourceAS.getAttributeCount()];\r
307 Enumeration sourceEn = sourceAS.getAttributeNames();\r
308 int i = 0;\r
309 while(sourceEn.hasMoreElements())\r
310 {\r
311 Object temp = new Object();\r
312 temp = sourceEn.nextElement();\r
313 sourceKeys[i] = (String) temp.toString();\r
314 sourceValues[i] = new String();\r
315 sourceValues[i] = (String) sourceAS.getAttribute(temp).toString();\r
316 i++;\r
317 }\r
318 String[] removeKeys = new String[removeAS.getAttributeCount()];\r
319 String[] removeValues = new String[removeAS.getAttributeCount()];\r
320 Enumeration removeEn = removeAS.getAttributeNames();\r
321 int j = 0;\r
322 while(removeEn.hasMoreElements())\r
323 {\r
324 removeKeys[j] = (String) removeEn.nextElement().toString();\r
325 removeValues[j] = (String) removeAS.getAttribute(removeKeys[j]).toString();\r
326 j++;\r
327 }\r
328 SimpleAttributeSet result = new SimpleAttributeSet();\r
329 boolean hit = false;\r
330 for(int countSource = 0; countSource < sourceKeys.length; countSource++)\r
331 {\r
332 hit = false;\r
333 if(sourceKeys[countSource] == "name" | sourceKeys[countSource] == "resolver")\r
334 {\r
335 hit = true;\r
336 }\r
337 else\r
338 {\r
339 for(int countRemove = 0; countRemove < removeKeys.length; countRemove++)\r
340 {\r
341 if(removeKeys[countRemove] != "NULL")\r
342 {\r
343 if(sourceKeys[countSource].toString() == removeKeys[countRemove].toString())\r
344 {\r
345 if(removeValues[countRemove] != "NULL")\r
346 {\r
347 if(sourceValues[countSource].toString() == removeValues[countRemove].toString())\r
348 {\r
349 hit = true;\r
350 }\r
351 }\r
352 else if(removeValues[countRemove] == "NULL")\r
353 {\r
354 hit = true;\r
355 }\r
356 }\r
357 }\r
358 else if(removeKeys[countRemove] == "NULL")\r
359 {\r
360 if(sourceValues[countSource].toString() == removeValues[countRemove].toString())\r
361 {\r
362 hit = true;\r
363 }\r
364 }\r
365 }\r
366 }\r
367 if(!hit)\r
368 {\r
369 result.addAttribute(sourceKeys[countSource].toString(), sourceValues[countSource].toString());\r
370 }\r
371 }\r
372 return result;\r
373 }\r
374 catch (ClassCastException cce)\r
375 {\r
376 return null;\r
377 }\r
378 }\r
379\r
380 /* liefert den entsprechenden HTML.Tag zum Element zurück */\r
381 public HTML.Tag getHTMLTag(Element e)\r
382 {\r
383 if(tags.containsKey(e.getName()))\r
384 {\r
385 return (HTML.Tag)tags.get(e.getName());\r
386 }\r
387 else\r
388 {\r
389 return null;\r
390 }\r
391 }\r
392\r
393 public String[] getUniString(int strings)\r
394 {\r
395 parent.refreshOnUpdate();\r
396 String[] result = new String[strings];\r
397 String source = parent.getSourcePane().getText();\r
398 for(int i=0; i<strings; i++)\r
399 {\r
400 int start = -1, end = -1;\r
401 boolean hit = false;\r
402 String idString;\r
403 int counter = 0;\r
404 do\r
405 {\r
406 hit = false;\r
407 idString = "diesisteineidzumsuchen" + counter + "#" + i;\r
408 if(source.indexOf(idString) > -1)\r
409 {\r
410 counter++;\r
411 hit = true;\r
412 if(counter > 10000)\r
413 {\r
414 return null;\r
415 }\r
416 }\r
417 } while(hit);\r
418 result[i] = idString;\r
419 }\r
420 return result;\r
421 }\r
422\r
423 public void delete()\r
424 throws BadLocationException,IOException\r
425 {\r
426 JTextPane jtpMain = parent.getTextPane();\r
427 JTextPane jtpSource = parent.getSourcePane();\r
428 ExtendedHTMLDocument htmlDoc = parent.getExtendedHtmlDoc();\r
429 int selStart = jtpMain.getSelectionStart();\r
430 int selEnd = jtpMain.getSelectionEnd();\r
431 String[] posStrings = getUniString(2);\r
432 if(posStrings == null)\r
433 {\r
434 return;\r
435 }\r
436 htmlDoc.insertString(selStart,posStrings[0],null);\r
437 htmlDoc.insertString(selEnd+posStrings[0].length(),posStrings[1],null);\r
438 parent.refreshOnUpdate();\r
439 int start = jtpSource.getText().indexOf(posStrings[0]);\r
440 int end = jtpSource.getText().indexOf(posStrings[1]);\r
441 if(start == -1 || end == -1)\r
442 {\r
443 return;\r
444 }\r
445 String htmlString = new String();\r
446 htmlString += jtpSource.getText().substring(0,start);\r
447 htmlString += jtpSource.getText().substring(start + posStrings[0].length(), end);\r
448 htmlString += jtpSource.getText().substring(end + posStrings[1].length(), jtpSource.getText().length());\r
449 String source = htmlString;\r
450 end = end - posStrings[0].length();\r
451 htmlString = new String();\r
452 htmlString += source.substring(0,start);\r
453 htmlString += getAllTableTags(source.substring(start, end));\r
454 htmlString += source.substring(end, source.length());\r
455 parent.getTextPane().setText(htmlString);\r
456 parent.refreshOnUpdate();\r
457 }\r
458\r
459 private String getAllTableTags(String source)\r
460 throws BadLocationException,IOException\r
461 {\r
462 StringBuffer result = new StringBuffer();\r
463 int caret = -1;\r
464 do\r
465 {\r
466 caret++;\r
467 int[] tableCarets = new int[6];\r
468 tableCarets[0] = source.indexOf("<table",caret);\r
469 tableCarets[1] = source.indexOf("<tr",caret);\r
470 tableCarets[2] = source.indexOf("<td",caret);\r
471 tableCarets[3] = source.indexOf("</table",caret);\r
472 tableCarets[4] = source.indexOf("</tr",caret);\r
473 tableCarets[5] = source.indexOf("</td",caret);\r
474 java.util.Arrays.sort(tableCarets);\r
475 caret = -1;\r
476 for(int i=0; i<tableCarets.length; i++)\r
477 {\r
478 if(tableCarets[i] >= 0)\r
479 {\r
480 caret = tableCarets[i];\r
481 break;\r
482 }\r
483 }\r
484 if(caret != -1)\r
485 {\r
486 result.append(source.substring(caret,source.indexOf(">",caret)+1));\r
487 }\r
488 } while(caret != -1);\r
489 return result.toString();\r
490 }\r
491\r
492}