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