Commit | Line | Data |
---|---|---|
c2da4d40 JL |
1 | /*\r |
2 | GNU Lesser General Public License\r | |
3 | \r | |
4 | HTMLUtilities - Special Utility Functions For Ekit\r | |
5 | Copyright (C) 2003 Rafael Cieplinski, modified by Howard Kistler\r | |
6 | \r | |
7 | This library is free software; you can redistribute it and/or\r | |
8 | modify it under the terms of the GNU Lesser General Public\r | |
9 | License as published by the Free Software Foundation; either\r | |
10 | version 2.1 of the License, or (at your option) any later version.\r | |
11 | \r | |
12 | This library is distributed in the hope that it will be useful,\r | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of\r | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r | |
15 | Lesser General Public License for more details.\r | |
16 | \r | |
17 | You should have received a copy of the GNU Lesser General Public\r | |
18 | License along with this library; if not, write to the Free Software\r | |
19 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r | |
20 | */\r | |
21 | \r | |
22 | package com.hexidec.ekit.component;\r | |
23 | \r | |
24 | import java.io.*;\r | |
25 | import java.lang.reflect.*;\r | |
26 | import java.util.*;\r | |
27 | import javax.swing.*;\r | |
28 | import javax.swing.text.*;\r | |
29 | import javax.swing.text.html.*;\r | |
30 | \r | |
31 | import com.hexidec.ekit.EkitCore;\r | |
32 | import com.hexidec.ekit.component.*;\r | |
33 | \r | |
34 | public 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 | } |